pax_global_header00006660000000000000000000000064134715510610014515gustar00rootroot0000000000000052 comment=8cd4b8cec7ffda0b19b01129e96eda8d2fb75ec0 qbs-src-1.13.1/000077500000000000000000000000001347155106100131525ustar00rootroot00000000000000qbs-src-1.13.1/.gitmodules000066400000000000000000000001201347155106100153200ustar00rootroot00000000000000[submodule "qtscript"] path = src/shared/qtscript url = ../../qt/qtscript.git qbs-src-1.13.1/.mailmap000066400000000000000000000026601347155106100145770ustar00rootroot00000000000000 qbs-src-1.13.1/LGPL_EXCEPTION.txt000066400000000000000000000022501347155106100160660ustar00rootroot00000000000000The Qt Company LGPL Exception version 1.1 As an additional permission to the GNU Lesser General Public License version 2.1, the object code form of a "work that uses the Library" may incorporate material from a header file that is part of the Library. You may distribute such object code under terms of your choice, provided that: (i) the header files of the Library have not been modified; and (ii) the incorporated material is limited to numerical parameters, data structure layouts, accessors, macros, inline functions and templates; and (iii) you comply with the terms of Section 6 of the GNU Lesser General Public License version 2.1. Moreover, you may apply this exception to a modified version of the Library, provided that such modification does not involve copying material from the Library into the modified Library's header files unless such material is limited to (i) numerical parameters; (ii) data structure layouts; (iii) accessors; and (iv) small macros, templates and inline functions of five lines or less in length. Furthermore, you are not required to apply this additional permission to a modified version of the Library. qbs-src-1.13.1/LICENSE.GPL3-EXCEPT000066400000000000000000001070131347155106100156530ustar00rootroot00000000000000This is the GNU General Public License version 3, annotated with The Qt Company GPL Exception 1.0: ------------------------------------------------------------------------- The Qt Company GPL Exception 1.0 Exception 1: As a special exception you may create a larger work which contains the output of this application and distribute that work under terms of your choice, so long as the work is not otherwise derived from or based on this application and so long as the work does not in itself generate output that contains the output from this application in its original or modified form. Exception 2: As a special exception, you have permission to combine this application with Plugins licensed under the terms of your choice, to produce an executable, and to copy and distribute the resulting executable under the terms of your choice. However, the executable must be accompanied by a prominent notice offering all users of the executable the entire source code to this application, excluding the source code of the independent modules, but including any changes you have made to this application, under the terms of this license. ------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . qbs-src-1.13.1/LICENSE.LGPLv21000066400000000000000000000635021347155106100152530ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This 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 Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! qbs-src-1.13.1/LICENSE.LGPLv3000066400000000000000000000175601347155106100151760ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd. Contact: http://www.qt.io/licensing You may use, distribute and copy the Qt GUI Toolkit under the terms of GNU Lesser General Public License version 3, which is displayed below. ------------------------------------------------------------------------- GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this licensedocument, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, “this License†refers to version 3 of the GNU Lesser General Public License, and the “GNU GPL†refers to version 3 of the GNU General Public License. “The Library†refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An “Application†is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A “Combined Work†is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the “Linked Versionâ€. The “Minimal Corresponding Source†for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The “Corresponding Application Code†for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser 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 Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any later version†applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. qbs-src-1.13.1/README000066400000000000000000000004511347155106100140320ustar00rootroot00000000000000Qbs === Qbs is a cross-platform build tool. The project's homepage is http://wiki.qt.io/qbs Qbs product documentation is available at: http://doc.qt.io/qbs/index.html For more information about building Qbs from sources, see "Appendix A: Building Qbs" at: http://doc.qt.io/qbs/building-qbs.html. qbs-src-1.13.1/VERSION000066400000000000000000000000071347155106100142170ustar00rootroot000000000000001.13.1 qbs-src-1.13.1/bin/000077500000000000000000000000001347155106100137225ustar00rootroot00000000000000qbs-src-1.13.1/bin/ibmsvc.xml000066400000000000000000000011221347155106100157230ustar00rootroot00000000000000 qbs-src-1.13.1/bin/ibqbs.bat000066400000000000000000000000751347155106100155140ustar00rootroot00000000000000@xgConsole /profile=%~dp0\ibmsvc.xml /command="qbs -j 20 %*" qbs-src-1.13.1/changelogs/000077500000000000000000000000001347155106100152645ustar00rootroot00000000000000qbs-src-1.13.1/changelogs/changes-1.10.0.md000066400000000000000000000035371347155106100177410ustar00rootroot00000000000000# General * Added the `vcs` module to provide VCS repository information. Git and Subversion are supported initially. * Added initial support for the Universal Windows Platform. * Improved a lot of error messages. # Language * Profiles can now be defined within a project using the `Profile` item. * Groups without a prefix now inherit the one of the parent group. * Both the `Module` and the `FileTagger` item now have a `priority` property, allowing them to override conflicting instances. * It is now possible to add file tags to generated artifacts by setting the new `fileTags` property in a group that has a `fileTagsFilter`. * Added new open mode `TextFile.Append`. * Added the `filePath` function to the `TextFile` class. * `Process` and `TextFile` objects in rules, commands and configure scripts are now closed automatically after script execution. # C/C++ Support * Added the `cpufeatures` module for abstracting compiler flags related to CPU features such as SSE. * Added property `cpp.discardUnusedData` abstracting linker options that strip unneeded symbols or sections. * Added property `cpp.variantSuffix` for making binary names unique when multiplexing products. * Added property `cpp.compilerDefinesByLanguage` providing the compiler's pre-defined macros. # Android * The deprecated `apkbuilder` tool is no longer used. # Qt * Added support for the Qt Quick compiler. * Added support for `qmlcachegen`. # Command-line interface * Removed some non-applicable options from a number of tools. * The `run` command can now deploy and run Android apps on devices, and deploy and run iOS and tvOS apps on the simulator. * Added new command `list-products`. # Documentation * Added porting guide for qmake projects. * Added in-depth descriptions of all command-line tools. * Added "How-to" for creating modules for third-party libraries. * Added a man page. qbs-src-1.13.1/changelogs/changes-1.10.1.md000066400000000000000000000012351347155106100177330ustar00rootroot00000000000000# Important bugfixes * Fix assertion on project loading (QBS-1275). * Fix crash when the "original" value is misused (QBS-1255). * Fix qtquickcompiler support for qml files in subdirectories (QBS-1261). * Fix constant rebuilding after moving an external header file (QBS-1285). * Fix GCC support for "bare metal" systems (QBS-1263, QBS-1265). * Fix using ids in Depends items (QBS-1264). * Fix access to module instances in dependency parameters (QBS-1253). * Fix race condition when creating Inno Setup, NSIS, or WiX installers. * Fix release builds for Android with NDK r12 and above (QBS-1256). * Fix parametrized dependencies in Export and Module items (QBS-1287). qbs-src-1.13.1/changelogs/changes-1.11.0.md000066400000000000000000000060671347155106100177430ustar00rootroot00000000000000# General * Added `qbs.targetPlatform` and `qbs.hostPlatform` properties which are scalar versions of `qbs.targetOS` and `qbs.hostOS`. `qbs.targetPlatform` is a "write-only" property that can be used to set the OS/platform that is being targeted, while `qbs.targetOS` and `qbs.hostOS` should continue to be used to *read* the OS/platform that is being targeted. `qbs.targetOS` is also now read-only. * The "run" functionality as used by the command-line command of the same name now considers an executable's library dependencies, that is, it adds the paths they are located in to the respective environment variable (e.g. PATH on Windows). # Language * Modules can now declare target artifacts using the new `filesAreTargets` property of the `Group` item. * The Module.setupRunEnvironment script now has a new parameter `config`. Users can set it via the `--setup-run-env-config` option of the `run` command. The only value currently supported is `ignore-lib-dependencies`, which turns off the abovementioned injection of library dependencies' paths into the run environment. * Module.setupBuildEnvironment and Module.setupRunEnvironment now have access to the `product` and `project` variables. With regards to accessing module properties, these script now behave like rules, rather than normal properties. * Added the `BinaryFile` service for reading and writing binary data files. * The `SubProject` item now has a condition property. # C/C++ Support * Added property `cpp.rpathOrigin` which evaluates to `@loader_path` on Darwin and `$ORIGIN` on other Unix-like platforms. * Added the `qbs.toolchainType` property, which is a scalar version of the `qbs.toolchain` property and is used to set the current toolchain. * Added `cpp.driverLinkerFlags` for flags to be passed to the compiler driver only when linking. * We now properly support `"c++17"` as a possible value of `cpp.cxxLanguageVersion`. * The auto-detection mechanism for GCC-like compilers now considers typical mingw prefixes. # Qt Support * Added the Qt.scxml.generateStateMethods property to back the --statemethods option. # Command-line interface * Configuration names are now passed as "config:". * Options do not have to precede property assignments anymore. * Referencing a non-existing product in a property override now results in an error. # Documentation * Major overhaul of the module and item reference for improved readability. * Added a how-to on the topic of pre-compiled headers. * Added documentation for the built-in XML support. * Added documentation for qbs.Utilities. * Added documentation on how to target specific platforms. # Important bug fixes * Fixed some inconsistencies related to item ids (QBS-1016, QBS-1262). * Fixed slow project resolving on macOS (QBS-1277). * Fixed problems with qtquickcompiler support in Qt 5.11 (QBS-1299). * Fixed race conditions in multi-configuration builds (QBS-1308). # Other * The `InnoSetup`, `nsis`, and `wix` modules' rules now have a dependency on installable artifacts of dependencies. * Introduced the `ico` module for creating .ico and .cur files. qbs-src-1.13.1/changelogs/changes-1.11.1.md000066400000000000000000000005061347155106100177340ustar00rootroot00000000000000# Important bugfixes * Speed up run environment setup (QTCREATORBUG-20175). * Fix qbs command line generated by the Visual Studio project generator (QBS-1303). * Install all required header files when building Qbs with qmake. * Fix undefined behavior in the qbscore library where a reference to a temporary object was stored. qbs-src-1.13.1/changelogs/changes-1.12.0.md000066400000000000000000000035571347155106100177450ustar00rootroot00000000000000# General * Added new module `Exporter.qbs` for creating qbs modules from products. * Added new module `Exporter.pkgconfig` for creating pkg-config metadata files. * Introduced the concept of system-level qbs settings. * Added a Makefile generator. * All command descriptions now contain the product name. # Language * The `explicitlyDependsOn` property of the `Rule` item no longer considers target artifacts of product dependencies. The new property `explicitlyDependsOnFromDependencies` can be used for that purpose. * The `excludedAuxiliaryInputs` property of the `Rule` item has been renamed to `excludedInputs`. The old name is now deprecated. * Added a new property type `varList`. * Added `FileInfo.suffix` and `FileInfo.completeSuffix`. * The deprecated JS extensions `XmlDomDocument` and `XmlDomElement` have been removed. Use `Xml.DomDocument` and `Xml.DomDocument` instead. # C/C++ Support * For MSVC static libraries, compiler-generated PDB files are now tagged as `debuginfo_cl` to make them installable. * The `cxxLanguageVersion` property can now be set to different values in different modules, and the highest value will be chosen. # Qt Support * Amalgamation builds work properly now in the presence of "mocable" files. * Fixed some redundancy on the linker command line. # Other modules * Added support for `%option outfile` and `%output` to the `lex_yacc` module. * The `vcs` module now creates the header file even if no repository is present. # Autotest support * Added an `auxiliaryInputs` property to the `AutotestRunner` item for specifying run-time dependencies of test executables. * The `AutotestRunner` item now has a `workingDirectory` property. By default, the respective test executable's location is used. # Important bug fixes * Disabled products no longer cause their exported dependencies to get pulled into the importing product (QBS-1250). qbs-src-1.13.1/changelogs/changes-1.12.1.md000066400000000000000000000010051347155106100177300ustar00rootroot00000000000000# Important bugfixes * Lifted the restriction that the -march option cannot appear in cpp.*Flags (QBS-1018). * All required header files get installed now (QBS-1370). * Fixed rpaths not ending up on the command line under certain circumstances (QBS-1372). * Fixed possible crash when scanning qrc files (QBS-1375). * Fixed spurious re-building of .pc and .qbs module files. * Fixed possible crash on storing a build graph after re-resolving. * Fixed possible assertion on input artifacts with alwaysUpdated == false. qbs-src-1.13.1/changelogs/changes-1.12.2.md000066400000000000000000000010411347155106100177310ustar00rootroot00000000000000# Important bugfixes * The Visual Studio 2017 Build Tools are properly supported now. * Android NDK r18 is properly supported now. * Removed invalid assertion that prevented deriving from the Properties item. * Fixed build error on some BSD hosts (QBS-1395). * setup-qt fixes: * The QtWebkit module is now properly detected (QBS-1399). * The case of the qtmain library being called "qt5main" is properly handled now (QBS-767). * Building against a Qt that was built with sanitizing support works out of the box now (QBS-1387). qbs-src-1.13.1/changelogs/changes-1.13.0.md000066400000000000000000000032261347155106100177370ustar00rootroot00000000000000# General * Added a lot more documentation. * The `--show-progress` command line option is now supported on Windows. # Language * Introduced module providers. * The `Depends` item now falls back to `pkg-config` to locate dependencies whose names do not correspond to a qbs module. * Added the concept of job pools for limiting concurrent execution of commands by type. * Added support for rules without output artifacts. * Added `atEnd` function to the `Process` service. * Added `canonicalPath` function to the `FileInfo` service. * Removed the need to add "import qbs" at the head of project files. * The `Application`, `DynamicLibrary` and `StaticLibrary` items now have properties for more convenient installation of target binaries. # C/C++ Support * Added recursive dependency scanning of GNU ld linkerscripts. * Added new `cpp` property `linkerVariant` to force use of `gold`, `bfd` or `lld`. # Qt Support * It is no longer required to call `setup-qt` before building Qt projects. * Introduced the property `Qt.core.enableBigResources` for the creation of "big" Qt resources. * Static builds now pull in the default set of plugins as specified by Qt, and the user can specify the set of plugins by type. * Files can be explicitly tagged as mocable now. # Other modules * Added `protobuf` support for C++ and Objective-C. * Introduced the `texttemplate` module, a facility similar to qmake's `SUBSTITUTES` feature. # Android Support * The `AndroidApk` item was deprecated, a normal `Application` item can be used instead. * Building Qt apps is properly supported now, by making use of the `androiddeployqt` tool. # Autotest support * Introduced the `autotest` module. qbs-src-1.13.1/changelogs/changes-1.13.1.md000066400000000000000000000010611347155106100177330ustar00rootroot00000000000000# Important bugfixes * Qt support: Plugins are no longer linked into static libraries when building against a static Qt (QBS-1441). * Qt support: Fixed excessively long linker command lines (QBS-1441). * Qt support: Host libraries are now looked up at the right location (QBS-1445). * Qt support: Fixed failure to find Qt modules in Qt Creator when re-parsing a project that hasn't been built yet. * macOS: Properties in bundle.infoPlist are no longer overridden (QBS-1447). * iOS: Fixed generation of default Info.plist (QBS-1447). qbs-src-1.13.1/changelogs/changes-1.6.0000066400000000000000000000016311347155106100172600ustar00rootroot00000000000000* Added lex_yacc module. * Introduced property cpp.systemRunPaths. * Introduced the ability to check a module's version in a Depends item. * Introduced cpp.driverFlags, which allows specifying flags to be passed to the compiler driver (in any mode), but never the system linker. * Introduced cpp.linkerMode property to allow selection of the correct linker (C driver, C++ driver, or system linker) based on the objects being linked. * Added automatic escaping of arguments passed to the cpp.linkerFlags and cpp.platformLinkerFlags properties using the -Wl or -Xlinker syntaxes. To revert to the old behavior, Project.minimumQbsVersion can be set to a version lower than 1.6. * Each build configuration now requires a unique name, which is specified on the command line in the same place that qbs.buildVariant used to be specified. This allows building for multiple configurations with the same variant. qbs-src-1.13.1/changelogs/changes-1.6.1000066400000000000000000000004071347155106100172610ustar00rootroot00000000000000Features: * Added cpp.linkerWrapper property. Important bug fixes: * Fixed a number of bugs evaluating module properties (QBS-845, QBS-1005). * Fixed x86_64 > x86 cross compiling (QBS-1028). * Fixed dynamic rules with generated inputs (QBS-1029). qbs-src-1.13.1/changelogs/changes-1.7.0000066400000000000000000000020471347155106100172630ustar00rootroot00000000000000Features: * Added a generator for Visual Studio projects. * The Group item is now nestable. * Stricter type checking for properties. * Added support for generating qrc files. * Added full support for the QtScxml module. * Introduced cpp.soVersion. * Added support for building Inno Setup packages. * Tentative support for Visual Studio 2017. * We now assume UTF-8 encoding for project files. * In Scanner items, input.fileName now contains a filename rather than the full path. * Warnings encountered during project resolving are now stored and re-displayed when the project is loaded. * Documentation was improved in several places, most notably for the Rule item. * Support for the deprecated Transformer item was removed. Important bug fixes: * Long paths on Windows are handled (QBS-1068). * Cyclic module dependencies are detected (QBS-1044). * The libqbscore soname now includes the minor version, so that it will not stay the same across ABI changes (QBS-1002). qbs-src-1.13.1/changelogs/changes-1.7.1000066400000000000000000000003711347155106100172620ustar00rootroot00000000000000Important bug fixes: * Fixed race condition in qmake build (QBS-1091) * Qt Creator no longer leaves empty build directories behind after cancelled project loading (QTCREATORBUG-17543) * Fixed an exception crossing the API boundary qbs-src-1.13.1/changelogs/changes-1.7.2000066400000000000000000000004521347155106100172630ustar00rootroot00000000000000Important bug fixes: * macOS: Fixed App Extension builds on older versions of Xcode/macOS * Windows: Fixed handling of files on network shares * Fixed syntax error in Qt module that occurred with static Qt builds * Several fixes for the Visual Studio generator (QBS-1077, QBS-1100) qbs-src-1.13.1/changelogs/changes-1.8.0000066400000000000000000000031701347155106100172620ustar00rootroot00000000000000Features: * General: * It is no longer strictly required to provide a profile. * Sub-second timestamp resolutions are now supported on Unix systems. * Added a convenient replacement for product.moduleProperty("module", "property"), namely product.module.property. * The loadFile and loadExtension functions are deprecated in favor of the new require function, which accepts arguments of either form accepted by the deprecated functions. * Added new tool qbs-create-project to set up a new qbs project from an existing source tree. * FileTagger items can now have conditions. * Probe items can now appear directly under a Project item. * Cpp module: * Added support for QNX and the QCC toolchain * Added the cpp.useRPathLink property to control whether to use the -rpath-link linker option. * Provided the means to easily combine source files for the C language family in order to support "amalgamation builds". * Introduced cpp.treatSystemHeadersAsDependencies. * Qt modules: * Introduced property Qt.core.combineMocOutput. * Introduced Qt.core.enableKeywords for simple disabling of the "signals", "slots" and "emit" symbols. Important bug fixes: * Improved scalability of parallel builds on Linux by starting Process commands via a dedicated launcher process. Behavior changes: * The base directory for source files changed from the product source directory to the parent directory of the file where the files are listed. qbs-src-1.13.1/changelogs/changes-1.8.1000066400000000000000000000007761347155106100172740ustar00rootroot00000000000000Important bug fixes: * Qbs-specific build errors are now correctly linked in Qt Creator's issues pane (QBS-1151). * Fixed automatic base profile assignment for MSVC Qt installations (QBS-1141) * Various QNX fixes (QBS-1136, QBS-1137, QBS-1138, QBS-1139, QBS-1143). Behavior changes: * Users now get early error messages if they forget the "modules", "products" or "projects" prefix in command line property overrides such as "modules.cpp.enableExceptions:false". qbs-src-1.13.1/changelogs/changes-1.9.0.md000066400000000000000000000053121347155106100176620ustar00rootroot00000000000000# General * Setting module property values from the command line can now be done per product. * Introduced new properties `qbs.architectures` and `qbs.buildVariants` to allow product multiplexing by `qbs.architecture` and `qbs.buildVariant`, respectively. * When rebuilding a project, the environment, project file and property values are taken from the existing build graph. # Language * `Depends` items can now be parameterized to set special module parameters for one particular product dependency. The new item type `Parameter` is used to declare such parameters in a module. The new item type `Parameters` is used to allow products to set default values for such parameters in their `Export` item. * The functions `loadExtension` and `loadFile` have been deprecated and will be removed in a future version. Use the `require` function instead. # Custom Rules and Commands * Artifacts corresponding to the `explicitlyDependsOn` property are now available under this name in rules and commands. * A rule's `auxiliaryInputs` and `explicitlyDependsOn` tags are now also matched against rules of dependencies, if these rules are creating target artifacts. * Rules now have a property `requiresInputs`. If it is `false`, the rule will be run even if no artifacts are present that match its input tags. * Added a new property `relevantEnvironmentVariables` to the `Command` class. Use it if the command runs an external tool whose behavior can be influenced by special environment variables. # C/C++ Support * Added the `cpp.link` parameter to enable library dependencies to be excluded from linking. * When pulling in static library products, the new `Depends` parameter `cpp.linkWholeArchive` can now be specified to force all the library's objects into the target binary. * When pulling in library products, the new `Depends` parameter `cpp.symbolLinkMode` can now be specified to control how the library is linked into the target binary on Apple platforms: specifically, whether the library is linked as weak, lazy, reexported, and/or upward (see the `ld64` man page for more information). * The property `cpp.useCxxPrecompiledHeader`, as well as the variants for the other languages, now defaults to true. * The property `cpp.cxxLanguageVersion` now gets mapped to MSVC's `/std` option, if applicable. # Apple * Added support for building macOS disk images. # Android * Product multiplexing is no longer done via profiles, but via architecture, employing the new `qbs.architectures` property (see above). As a result, the `setup-android` command now sets up only one profile, rather than one for each architecture. * Added support for NDK Unified Headers. # Documentation * Added a "How-to" section. qbs-src-1.13.1/changelogs/changes-1.9.1.md000066400000000000000000000003731347155106100176650ustar00rootroot00000000000000# Important bugfixes * Lower the response file threshold on Windows to fix build failures with mingw (QBS-1201). * Fix explicitly specified build variant being ignored for Darwin targets (QBS-1202). * Fix building for the AVR architecture (QBS-1203). qbs-src-1.13.1/dist/000077500000000000000000000000001347155106100141155ustar00rootroot00000000000000qbs-src-1.13.1/dist/.gitignore000066400000000000000000000000021347155106100160750ustar00rootroot00000000000000* qbs-src-1.13.1/doc/000077500000000000000000000000001347155106100137175ustar00rootroot00000000000000qbs-src-1.13.1/doc/appendix/000077500000000000000000000000001347155106100155275ustar00rootroot00000000000000qbs-src-1.13.1/doc/appendix/qbs-porting.qdoc000066400000000000000000000346061347155106100206550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \previouspage building-qbs.html \page porting-to-qbs.html \nextpage attributions.html \title Appendix B: Migrating from Other Build Systems You can use the \l{create-project}{qbs create-project} command to automatically generate \QBS project files from an arbitrary directory structure. This is a useful starting point when migrating from other build tools, such as qmake or CMake. To use the tool, switch to the project directory and run the \c {qbs create-project} command, which is located in the \c bin directory of the \QBS installation directory (or the Qt Creator installation directory). After generating the initial .qbs file, add the missing configuration variables and functions to it, as described in the following sections. \section1 Migrating from qmake The following sections describe the \QBS equivalents of qmake variable values. \section2 CONFIG Specify project configuration and compiler options. \section3 console Set the \l{Product::consoleApplication}{Product.consoleApplication} property to \c true for the \l{Application}, \l{CppApplication},or \l{QtApplication} item. For example: \code Application { name: "helloworld" files: "main.cpp" Depends { name: "cpp" } consoleApplication: true } \endcode \section3 ordered This qmake variable has no direct equivalent in \QBS. Instead, the build order is determined by implicit and explicit dependencies between products. To add an explicit dependency, add a \l{Depends} item to a \l{Product}{product}: \code CppApplication { name: "myapp" Depends { name: "mylib" } } \endcode The \c myapp product depends on and links to the \c mylib product, and is therefore built after it. \section3 qt In qmake, the Qt dependency is implicit, whereas in \QBS it is not. If \c {CONFIG -= qt}, add a \l{Depends} item to specify that the \l{Product}{product} depends on the \l{cpp} module: \code Product { Depends { name: "cpp" } } \endcode \section2 DEFINES Set the \l{cpp::defines}{cpp.defines} property for the \l{Product}{product}. \note To reference \c cpp.defines, you must specify a dependency on the \l{cpp} module. \code Product { Depends { name: "cpp" } cpp.defines: ["SUPPORT_MY_FEATURES"] } \endcode \section2 DESTDIR We recommend that you use the \l{Installing Files}{installation mechanism} to specify the location of the target file: \code Application { Group { name: "Runtime resources" files: "*.qml" qbs.install: true qbs.installDir: "share/myproject" } Group { name: "The App itself" fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } } \endcode If that is not possible, you can use the \l{Product::}{destinationDirectory} property: \code DynamicLibrary { name: "mydll" destinationDirectory: "libDir" } \endcode \section2 HEADERS, SOURCES, FORMS, RESOURCES, OTHER_FILES Include header, source, form, and resource files as well as any other files as values of a \l{Product::files}{Product.files} or \l{Group::files}{Group.files} property: \code QtApplication { name: "myapp" files: ["myapp.h", "myapp.cpp", "myapp.ui", "myapp.qrc", "readme.txt"] } \endcode \QBS uses \l{FileTagger}{file taggers} to figure out what kind of file it is dealing with. \section2 ICON There is no direct equivalent in \QBS. If you add a \l{Depends} {dependency} to the \l{ib} module and add the \c .xcassets directory as a value of the \l{Product::files}{Product.files} property, \QBS takes care of setting the application icon automatically when building for Apple platforms: \code Application { name: "myapp" files [".xcassets"] Depends { name: "ib" } } \endcode Alternatively, you can set the icon name as the value of the \l{bundle::infoPlist}{bundle.infoPlist} parameter, specify a dependency to the \l{ib} module, and add the application \c .icns file as a value of the \l{Product::}{files} property: \code Application { name: "myapp" files ["myapp.icns"] Depends { name: "ib" } bundle.infoPlist: ({"CFBundleIconFile": "myapp"}) \endcode \section2 INCLUDEPATH Add the paths to the include files as values of the \l{cpp::includePaths} {cpp.includePaths} property: \code CppApplication { cpp.includePaths: ["..", "some/other/dir"] } \endcode \section2 LIBS For libraries that are part of the project, use \l{Depends} items. To pull in external libraries, use the \l{cpp::libraryPaths} {cpp.libraryPaths} property for the Unix \c -L (library path) flags and the \l{cpp::dynamicLibraries}{cpp.dynamicLibraries} and \l{cpp::staticLibraries} {cpp.staticLibraries} properties for the \c -l (library) flags. For example, \c {LIBS += -L/usr/local/lib -lm} would become: \code CppApplication { cpp.libraryPaths: ["/usr/local/lib"] cpp.dynamicLibraries: ["m"] } \endcode \section2 OUT_PWD Use the \l{Product::buildDirectory}{Product.buildDirectory} property to refer to the base output directory of the generated artifacts. \section2 PWD Corresponds to the the file-scope variable \c path. \section2 _PRO_FILE_ Corresponds to the file-scope variable \c filePath when used in a \l{Project}{project} or \l{Product}{product}. \section2 _PRO_FILE_PWD_ Corresponds to the \l{Project::sourceDirectory}{Project.sourceDirectory} or \l{Product::sourceDirectory}{Product.sourceDirectory} property. \section2 QMAKE_ASSET_CATALOGS Add a \l{Depends}{dependency} to the \l{ib} module and add the \c .xcassets directory as a value of the \l{Product::}{files} property: \code Application { name: "myapp" files [".xcassets"] Depends { name: "ib" } } \endcode \section2 QMAKE_BUNDLE_DATA For the time being, you can manually place files in the appropriate location using the \l{Installing Files}{installation mechanism}. Better solutions are under development. \section2 QMAKE_BUNDLE_EXTENSION Set the \l{bundle::extension}{bundle.extension} property. \note Unlike qmake, \QBS automatically prepends a period (.) to the property value. \section2 QMAKE_{C,CXX,OBJECTIVE}_CFLAGS{_DEBUG,_RELEASE} Use the \l{cpp::commonCompilerFlags}{cpp.commonCompilerFlags} property or the properties corresponding to each compiler flags variable: \table \header \li qmake Variable \li cpp Module Property \row \li \c QMAKE_CFLAGS_DEBUG \c QMAKE_CFLAGS_RELEASE \li \l{cpp::cFlags}{cpp.cFlags} \row \li \c QMAKE_CXXFLAGS_DEBUG \c QMAKE_CXXFLAGS_RELEASE \li \l{cpp::cxxFlags}{cpp.cxxFlags} \row \li \c QMAKE_OBJECTIVE_CFLAGS \li \l{cpp::objcFlags}{cpp.objcFlags} \l{cpp::objcxxFlags}{cpp.objcxxFlags} \endtable Use \l{Properties} items or simple conditionals as values of the \l{qbs::buildVariant}{qbs.buildVariant} property to simulate the \c _DEBUG and \c _RELEASE variants of the qmake variables. \section2 QMAKE_FRAMEWORK_BUNDLE_NAME Set the \l{bundle::bundleName}{bundle.bundleName} property (which is derived from \l{Product::targetName}{Product.targetName}) combined with \l{bundle::extension}{bundle.extension}. \section2 QMAKE_FRAMEWORK_VERSION Set the \l{bundle::frameworkVersion}{bundle.frameworkVersion} property. \section2 QMAKE_INFO_PLIST Include the \c info.plist file as a value of \l{Product::}{files} property and specify a dependency to the \l{bundle} module: \code Application { name: "myapp" files ["info.plist"] Depends { name: "bundle" } } \endcode \QBS will automatically add any necessary properties to your \c Info.plist file. Typically, it determines the appropriate values from the other properties in the project, and therefore you do not need to use the \c {Info.plist.in > Info.plist} configuration mechanism. Further, you almost never need to embed placeholders into the source \c Info.plist file. Set the \l{bundle::processInfoPlist}{bundle.processInfoPlist} property to \c false to disable this behavior: \code \\ ... bundle.processInfoPlist: false \endcode In addition to, or instead of, using an actual \c Info.plist file, you can add \c Info.plist properties using the \l{bundle::infoPlist} {bundle.infoPlist} property. For example: \code \\ ... bundle.infoPlist: ({ "NSHumanReadableCopyright": "Copyright (c) 2017 Bob Inc", "Some other key", "Some other value, & XML special characters are no problem! >;) éžå‡¡!" }) \endcode \section2 QMAKE_LFLAGS Set the \l{cpp::linkerFlags}{cpp.linkerFlags} property for the \l{Product} {product}. \section2 QMAKE_{MACOSX,IOS,TVOS,WATCHOS}_DEPLOYMENT_TARGET For each qmake deployment target variable, use the corresponding property of the \l{cpp} module: \table \header \li qmake Variable \li cpp Module Property \row \li \c QMAKE_MACOSX_DEPLOYMENT_TARGET \li \l{cpp::minimumMacosVersion}{cpp.minimumMacosVersion} \row \li \c QMAKE_IOS_DEPLOYMENT_TARGET \li \l{cpp::minimumIosVersion}{cpp.minimumIosVersion} \row \li \c QMAKE_TVOS_DEPLOYMENT_TARGET \li \l{cpp::minimumTvosVersion}{cpp.minimumTvosVersion} \row \li \c QMAKE_WATCHOS_DEPLOYMENT_TARGET \li \l{cpp::minimumWatchosVersion}{cpp.minimumWatchosVersion} \endtable \section2 QMAKE_RPATHDIR Set the \l{cpp::rpaths}{cpp.rpaths} property for the \l{Product}{product}. \section2 QMAKE_SONAME_PREFIX Use the \l{cpp::sonamePrefix}{cpp.sonamePrefix} property for the \l{Product} {product}. \section2 QML_IMPORT_PATH Used only for Qt Creator QML syntax highlighting. Inside a \l{Product}, \l{Application}, \l{CppApplication}, or \l{QtApplication}, create a \c qmlImportPaths property: \code Product { name: "myProduct" property stringList qmlImportPaths: [sourceDirectory + "/path/to/qml/"] } \endcode \section2 QT Add a \l{Depends} item to the \l{Product}{product} that specifies the dependencies to \l{Qt} modules. For example: \code QtApplication { Depends { name: "Qt.widgets" } } \endcode You could also use the following form that is equivalent to the previous one: \code QtApplication { Depends { name: "Qt"; submodules: "widgets" } } \endcode \section2 QTPLUGIN Building static applications often requires linking to static QPA plugins, such as \c qminimal. You can use the following syntax to enable \QBS to link to the required plugins: \code QtApplication { name: "myapp" Depends { name: "Qt"; submodules: ["core", "gui", "widgets"] } Depends { name: "Qt.qminimal"; condition: Qt.core.staticBuild } } \endcode \section2 RC_FILE Add Windows resource files to the value of the \l{Product::files} {Product.files} property. \section2 TARGET Use the \l{Product::targetName}{Product.targetName} property to specify the base file name of target artifacts. \section2 TEMPLATE \section3 app Use \l{Application} or \l{CppApplication} as the \l{Product}{product}: \code CppApplication { name: "helloworld" files: "main.cpp" } \endcode This is roughly equivalent to: \code Product { name: "helloworld" type: "application" files: "main.cpp" Depends { name: "cpp" } } \endcode \section3 lib Use either \l{DynamicLibrary} or \l{StaticLibrary} as the \l{Product} {product}, depending on whether the value of \c CONFIG in the .pro file is \c shared or \c static. For example, if the value is \c shared: \code DynamicLibrary { name: "mydll" files: ["mySourceFile.cpp"] Depends { name: "cpp" } } \endcode \section3 subdirs In a \l{Project} item, specify subdirectories as values of the \l{Project::}{references} property: \code Project { references: [ "app/app.qbs", "lib/lib.qbs" ] } \endcode \section2 message(), warning(), error(), log() You can use the \l{Console API} to print info, warning, error, and log messages to the console. \code Product { name: { console.info("--> now evaluating the product name"); return "theName"; } Depends { name: "cpp" } cpp.includePath: { throw "An error occurred." } } \endcode */ qbs-src-1.13.1/doc/classic.css000066400000000000000000000103201347155106100160460ustar00rootroot00000000000000BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { font-family: Arial, Geneva, Helvetica, sans-serif; } H1 { text-align: center; font-size: 160%; } H2 { font-size: 120%; } H3 { font-size: 100%; } h3.fn,span.fn { background-color: #eee; border-width: 1px; border-style: solid; border-color: #ddd; font-weight: bold; padding: 6px 0px 6px 10px; margin: 42px 0px 0px 0px; } hr { border: 0; color: #a0a0a0; background-color: #ccc; height: 1px; width: 100%; text-align: left; margin: 34px 0px 34px 0px; } table.valuelist { border-width: 1px 1px 1px 1px; border-style: solid; border-color: #dddddd; border-collapse: collapse; background-color: #f0f0f0; } table.indextable { border-width: 1px 1px 1px 1px; border-collapse: collapse; background-color: #f0f0f0; border-color:#555; font-size: 110%; } table td.largeindex { border-width: 1px 1px 1px 1px; border-collapse: collapse; background-color: #f0f0f0; border-color:#555; font-size: 120%; } table.valuelist th { border-width: 1px 1px 1px 2px; padding: 4px; border-style: solid; border-color: #666; color:white; background-color:#666; } th.titleheader { border-width: 1px 0px 1px 0px; padding: 4px; border-style: solid; border-color: #444; color:white; background-color:#555555; font-size: 110%; } th.largeheader { border-width: 1px 0px 1px 0px; padding: 4px; border-style: solid; border-color: #444; color:white; background-color:#555555; font-size: 120%; } p { margin-left: 4px; margin-top: 8px; margin-bottom: 8px; } a:link { color: #0046ad; text-decoration: none } a:visited { color: #672967; text-decoration: none } a.obsolete { color: #661100; text-decoration: none } a.compat { color: #661100; text-decoration: none } a.obsolete:visited { color: #995500; text-decoration: none } a.compat:visited { color: #995500; text-decoration: none } body { background: #ffffff; color: black } table.generic, table.annotated { border-width: 1px; border-color:#bbb; border-style:solid; border-collapse:collapse; } table td.memItemLeft { width: 180px; padding: 2px 0px 0px 8px; margin: 4px; border-width: 1px; border-color: #E0E0E0; border-style: none; font-size: 100%; white-space: nowrap } table td.memItemRight { padding: 2px 8px 0px 8px; margin: 4px; border-width: 1px; border-color: #E0E0E0; border-style: none; font-size: 100%; } table tr.odd { background: #f0f0f0; color: black; } table tr.even { background: #e4e4e4; color: black; } table.annotated th { padding: 3px; text-align: left } table.annotated td { padding: 3px; } table tr pre { padding-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; border: none; background: none } tr.qt-style { background: #96E066; color: black } body pre { padding: 0.2em; border: #e7e7e7 1px solid; background: #f1f1f1; color: black } table tr.qt-code pre { padding: 0.2em; border: #e7e7e7 1px solid; background: #f1f1f1; color: black } span.preprocessor, span.preprocessor a { color: darkblue; } span.comment { color: darkred; font-style: italic } span.string,span.char { color: darkgreen; } .title { text-align: center } .subtitle { font-size: 0.8em } .small-subtitle { font-size: 0.65em } .qmlitem { padding: 0; } .qmlname { white-space: nowrap; font-weight: bold; font-size: 125%; } .qmltype { font-weight: bold; font-size: 125%; } .qmlproto, .qmldoc { // border-top: 1px solid #84b0c7; } .qmlproto { padding: 0; //background-color: #e4e4e4;//#d5e1e8; //font-weight: bold; //-webkit-border-top-left-radius: 8px; //-webkit-border-top-right-radius: 8px; //-moz-border-radius-topleft: 8px; //-moz-border-radius-topright: 8px; } .qmldoc { border-top: 1px solid #e4e4e4; //padding: 2px 5px; //background-color: #eef3f5; //border-top-width: 0; //-webkit-border-bottom-left-radius: 8px; //-webkit-border-bottom-right-radius: 8px; //-moz-border-radius-bottomleft: 8px; //-moz-border-radius-bottomright: 8px; } .qmldoc p, .qmldoc dl, .qmldoc ul { //margin: 6px 0; } *.qmlitem p { //margin-top: 0px; //margin-bottom: 0px; } qbs-src-1.13.1/doc/codeattributions.qdoc000066400000000000000000000160231347155106100201530ustar00rootroot00000000000000/*! \contentspage attributions.html \ingroup attributions-libs \ingroup attributions-qbs \page qbs-attribution-ds_store.html attribution \target ds_store \title ds_store \brief MIT License Manipulate Finder .DS_Store files from Python Used in the qbs dmg module for building Apple disk images. The sources can be found in src/3rdparty/python/lib/python2.7/site-packages/ds_store. \l{https://github.com/al45tair/ds_store}{Project Homepage}, upstream version: 1.1.2 \badcode Copyright (c) 2014 Alastair Houghton \endcode \l{https://spdx.org/licenses/MIT.html}{MIT License}. \badcode Copyright (c) 2014 Alastair Houghton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \endcode */ /*! \contentspage attributions.html \ingroup attributions-libs \ingroup attributions-qbs \page qbs-attribution-dmgbuild.html attribution \target dmgbuild \title dmgbuild \brief MIT License macOS command line utility to build disk images Used in the qbs dmg module for building Apple disk images. The sources can be found in src/3rdparty/python/lib/python2.7/site-packages/dmgbuild. \l{https://github.com/al45tair/dmgbuild}{Project Homepage}, upstream version: 1.3.1 \badcode Copyright (c) 2014 Alastair Houghton \endcode \l{https://spdx.org/licenses/MIT.html}{MIT License}. \badcode Copyright (c) 2014 Alastair Houghton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \endcode */ /*! \contentspage attributions.html \ingroup attributions-libs \ingroup attributions-qbs \page qbs-attribution-mac_alias.html attribution \target mac_alias \title mac_alias \brief MIT License Generate/parse Mac OS Alias records from Python Used in the qbs dmg module for building Apple disk images. The sources can be found in src/3rdparty/python/lib/python2.7/site-packages/mac_alias. \l{https://github.com/al45tair/mac_alias}{Project Homepage}, upstream version: 2.0.6 \badcode Copyright (c) 2014 Alastair Houghton \endcode \l{https://spdx.org/licenses/MIT.html}{MIT License}. \badcode Copyright (c) 2014 Alastair Houghton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \endcode */ /*! \contentspage attributions.html \ingroup attributions-libs \ingroup attributions-qbs \page qbs-attribution-biplist.html attribution \target biplist \title biplist \brief BSD 3-clause "New" or "Revised" License biplist is a library for reading/writing binary plists. Used in the qbs dmg module for building Apple disk images. The sources can be found in src/3rdparty/python/lib/python2.7/site-packages/biplist. \l{https://bitbucket.org/wooster/biplist}{Project Homepage}, upstream version: 1.0.2 \badcode Copyright (c) 2010, Andrew Wooster \endcode \l{https://spdx.org/licenses/BSD-3-Clause.html}{BSD 3-clause "New" or "Revised" License}. \badcode Copyright (c) 2010, Andrew Wooster All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of biplist nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \endcode */ qbs-src-1.13.1/doc/config/000077500000000000000000000000001347155106100151645ustar00rootroot00000000000000qbs-src-1.13.1/doc/config/macros.qdocconf000066400000000000000000000054201347155106100201670ustar00rootroot00000000000000macro.QBS = "Qbs" macro.qbsversion = $QBS_VERSION macro.defaultvalue = "Default:" macro.nodefaultvalue = "Default: Undefined" macro.appleproperty = "This property is specific to Apple platforms." macro.unixproperty = "This property is specific to Unix platforms." macro.windowsproperty = "This property is specific to Windows." macro.baremetalproperty = "This property is specific to bare-metal platforms." macro.funsince.HTML = "

This function was introduced in version \1.

" macro.aacute.HTML = "á" macro.Aring.HTML = "Å" macro.aring.HTML = "å" macro.Auml.HTML = "Ä" macro.author = "\\b{Author:}" macro.BR.HTML = "
" macro.copyright.HTML = "©" macro.eacute.HTML = "é" macro.gui = "\\b" macro.HR.HTML = "
" macro.iacute.HTML = "í" macro.key = "\\b" macro.macos = "macOS" macro.menu = "\\b" macro.oslash.HTML = "ø" macro.ouml.HTML = "ö" macro.QA = "\\e{Qt Assistant}" macro.QD = "\\e{Qt Designer}" macro.QL = "\\e{Qt Linguist}" macro.QQV = "\\e{Qt QML Viewer}" macro.param = "\\e" macro.raisedaster.HTML = "*" macro.rarrow.HTML = "→" macro.reg.HTML = "®" macro.return = "Returns" macro.starslash = "\\c{*/}" macro.begincomment = "\\c{/*}" macro.endcomment = "\\c{*/}" macro.uuml.HTML = "ü" macro.mdash.HTML = "—" macro.pi.HTML = "Π" macro.beginqdoc.HTML = "/*!" macro.endqdoc.HTML = "*/" macro.borderedimage = "\\div {class=\"border\"} \\image \1\n\\enddiv" macro.beginfloatleft.HTML = "
" macro.beginfloatright.HTML = "
" macro.endfloat.HTML = "
" macro.clearfloat.HTML = "
" macro.emptyspan.HTML = "" # Embed YouTube content by video ID - Example: \youtube dQw4w9WgXcQ # Also requires a .jpg thumbnail for offline docs. In .qdocconf, add: # # HTML.extraimages += images/dQw4w9WgXcQ.jpg # qhp.ProjectName.extraFiles += images/dQw4w9WgXcQ.jpg # macro.youtube.HTML = "
\n\n" \ "
\n" qbs-src-1.13.1/doc/config/qbs-project.qdocconf000066400000000000000000000021111347155106100211260ustar00rootroot00000000000000include($QT_INSTALL_DOCS/global/qt-cpp-defines.qdocconf) include($QT_INSTALL_DOCS/global/compat.qdocconf) include($QT_INSTALL_DOCS/global/fileextensions.qdocconf) project = "Qbs" description = "Qbs Manual" headerdirs = sourcedirs = .. imagedirs = ../images ../templates/images exampledirs = .. include(macros.qdocconf) sources.fileextensions = "*.qdoc" qhp.projects = Qbs qhp.Qbs.file = qbs.qhp qhp.Qbs.namespace = org.qt-project.qbs.$QBS_VERSION_TAG qhp.Qbs.virtualFolder = doc qhp.Qbs.indexTitle = Qbs qhp.Qbs.filterAttributes = qbs $QBS_VERSION qhp.Qbs.customFilters.Qbs.name = Qbs $QBS_VERSION qhp.Qbs.customFilters.Qbs.filterAttributes = qbs $QBS_VERSION qhp.Qbs.indexRoot = qhp.Qbs.subprojects = manual qhp.Qbs.subprojects.manual.title = Qbs Manual qhp.Qbs.subprojects.manual.indexTitle = Qbs Manual qhp.Qbs.subprojects.manual.type = manual # Doxygen compatibility commands macro.see = "\\sa" macro.function = "\\fn" navigation.homepage = "Qbs Manual" buildversion = "Qbs $QBS_VERSION" qbs-src-1.13.1/doc/config/style/000077500000000000000000000000001347155106100163245ustar00rootroot00000000000000qbs-src-1.13.1/doc/config/style/qt5-sidebar.html000066400000000000000000000014071347155106100213340ustar00rootroot00000000000000

Qbs Manual

qbs-src-1.13.1/doc/doc.pri000066400000000000000000000006511347155106100152020ustar00rootroot00000000000000include(../src/install_prefix.pri) include(doc_shared.pri) DOC_OUTDIR_POSTFIX = /html DOC_HTML_INSTALLDIR = $$QBS_INSTALL_PREFIX/share/doc/qbs DOC_QCH_OUTDIR = $$OUT_PWD/doc DOC_QCH_INSTALLDIR = $$QBS_INSTALL_PREFIX/share/doc/qbs include(doc_targets.pri) fixnavi.commands = \ cd $$shell_path($$PWD) && \ perl fixnavi.pl -Dqcmanual -Dqtquick \ qbs.qdoc QMAKE_EXTRA_TARGETS += fixnavi include(man/man.pri) qbs-src-1.13.1/doc/doc.qbs000066400000000000000000000063501347155106100151770ustar00rootroot00000000000000import qbs 1.0 import qbs.File import qbs.FileInfo Project { references: ["man/man.qbs"] Product { name: "qbs documentation" builtByDefault: false type: ["qch", "qbsdoc.qdoc-html-fixed"] property string fixedHtmlDir: FileInfo.joinPaths(buildDirectory, "qdoc-html-fixed") Depends { name: "Qt.core" } Depends { name: "qbsbuildconfig" } Depends { name: "qbsversion" } files: [ "../README", "classic.css", "external-resources.qdoc", "fixnavi.pl", "howtos.qdoc", "qbs.qdoc", "qbs-online.qdocconf", "config/*.qdocconf", "config/style/qt5-sidebar.html", "reference/**/*", "templates/**/*", "images/**", "targets/**", ] Group { name: "main qdocconf file" files: "qbs.qdocconf" fileTags: "qdocconf-main" } Group { name: "fix-imports script" files: ["fix-qmlimports.py"] fileTags: ["qbsdoc.fiximports"] } property string versionTag: qbsversion.version.replace(/\.|-/g, "") Qt.core.qdocEnvironment: [ "QBS_VERSION=" + qbsversion.version, "SRCDIR=" + path, "QT_INSTALL_DOCS=" + Qt.core.docPath, "QBS_VERSION_TAG=" + versionTag ] Rule { inputs: ["qdoc-png"] explicitlyDependsOn: ["qbsdoc.fiximports"] multiplex: true outputFileTags: ["qdoc-html", "qbsdoc.dummy"] // TODO: Hack. Rule injection to the rescue? outputArtifacts: [{filePath: "dummy", fileTags: ["qbsdoc.dummy"]}] prepare: { var scriptPath = explicitlyDependsOn["qbsdoc.fiximports"][0].filePath; var htmlDir = FileInfo.path(FileInfo.path(inputs["qdoc-png"][0].filePath)); var fixCmd = new Command("python", [scriptPath, htmlDir]); fixCmd.description = "fixing bogus QML import statements"; return [fixCmd]; } } Rule { inputs: ["qdoc-html"] Artifact { filePath: FileInfo.joinPaths(product.fixedHtmlDir, input.fileName) fileTags: ["qbsdoc.qdoc-html-fixed"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return [cmd]; } } Group { fileTagsFilter: ["qbsdoc.qdoc-html-fixed"] qbs.install: qbsbuildconfig.installHtml qbs.installDir: qbsbuildconfig.docInstallDir qbs.installSourceBase: product.fixedHtmlDir } Group { fileTagsFilter: ["qdoc-css", "qdoc-png"] qbs.install: qbsbuildconfig.installHtml qbs.installDir: qbsbuildconfig.docInstallDir qbs.installSourceBase: Qt.core.qdocOutputDir } Group { fileTagsFilter: ["qch"] qbs.install: qbsbuildconfig.installQch qbs.installDir: qbsbuildconfig.docInstallDir } } } qbs-src-1.13.1/doc/doc_shared.pri000066400000000000000000000007031347155106100165260ustar00rootroot00000000000000include(../qbs_version.pri) qbsdoc_version.name = QBS_VERSION qbsdoc_version.value = $$QBS_VERSION qbsdoc_versiontag.name = QBS_VERSION_TAG qbsdoc_versiontag.value = $$replace(QBS_VERSION, "[-.]", ) qbsdoc_qtdocs.name = QT_INSTALL_DOCS qbsdoc_qtdocs.value = $$[QT_INSTALL_DOCS/src] QDOC_ENV += qbsdoc_version qbsdoc_versiontag qbsdoc_qtdocs build_online_docs: \ DOC_FILES += $$PWD/qbs-online.qdocconf else: \ DOC_FILES += $$PWD/qbs.qdocconf qbs-src-1.13.1/doc/doc_targets.pri000066400000000000000000000070761347155106100167430ustar00rootroot00000000000000# Creates targets for building documentation # (adapted from qt_docs.prf) # # Usage: Define variables (details below) and include this pri file afterwards. # # QDOC_ENV - environment variables to set for the qdoc call (see example below) # DOC_INDEX_PATHS - list of paths where qdoc should search for index files of dependent # modules (Qt index path is included by default) # DOC_FILES - list of qdocconf files # DOC_OUTDIR_POSTFIX - html is generated in $$OUT_PWD/$$DOC_OUTDIR_POSTFIX # DOC_HTML_INSTALLDIR - path were to install the directory of html files # DOC_QCH_OUTDIR - path where to generated the qch files # DOC_QCH_INSTALLDIR - path where to install the qch files # DOC_TARGET_PREFIX - prefix for generated target names # # Example for QDOC_ENV: # ver.name = VERSION # ver.value = 1.0.2 # foo.name = FOO # foo.value = foo # QDOC_ENV = ver foo isEmpty(DOC_FILES): error("Set DOC_FILES before including doc_targets.pri") isEmpty(DOC_HTML_INSTALLDIR): error("Set DOC_HTML_INSTALLDIR before including doc_targets.pri") isEmpty(DOC_QCH_OUTDIR): error("Set DOC_QCH_OUTDIR before including doc_targets.pri") isEmpty(DOC_QCH_INSTALLDIR): error("Set DOC_QCH_INSTALLDIR before including doc_targets.pri") QT_TOOL_ENV = $$QDOC_ENV qtPrepareTool(QDOC, qdoc) QT_TOOL_ENV = !build_online_docs: qtPrepareTool(QHELPGENERATOR, qhelpgenerator) DOCS_BASE_OUTDIR = $$OUT_PWD/doc DOC_INDEXES += -indexdir $$shell_quote($$[QT_INSTALL_DOCS]) for (index_path, DOC_INDEX_PATHS): \ DOC_INDEXES += -indexdir $$shell_quote($$index_path) DTP = $$DOC_TARGET_PREFIX for (doc_file, DOC_FILES) { !exists($$doc_file): error("Cannot find documentation specification file $$doc_file") DOC_TARGET = $$replace(doc_file, ^(.*/)?(.*)\\.qdocconf$, \\2) DOC_TARGETDIR = $$DOC_TARGET DOC_OUTPUTDIR = $${DOCS_BASE_OUTDIR}/$${DOC_TARGETDIR}$${DOC_OUTDIR_POSTFIX} $${DTP}html_docs_$${DOC_TARGET}.commands = $$QDOC -outputdir $$shell_quote($$DOC_OUTPUTDIR) $$doc_file $$DOC_INDEXES QMAKE_EXTRA_TARGETS += $${DTP}html_docs_$${DOC_TARGET} !isEmpty($${DTP}html_docs.commands): $${DTP}html_docs.commands += && $${DTP}html_docs.commands += $$eval($${DTP}html_docs_$${DOC_TARGET}.commands) $${DTP}inst_html_docs.files += $$DOC_OUTPUTDIR !build_online_docs { $${DTP}qch_docs_$${DOC_TARGET}.commands = $$QHELPGENERATOR $$shell_quote($$DOC_OUTPUTDIR/$${DOC_TARGET}.qhp) -o $$shell_quote($$DOC_QCH_OUTDIR/$${DOC_TARGET}.qch) $${DTP}qch_docs_$${DOC_TARGET}.depends = $${DTP}html_docs_$${DOC_TARGET} QMAKE_EXTRA_TARGETS += $${DTP}qch_docs_$${DOC_TARGET} !isEmpty($${DTP}qch_docs.commands): $${DTP}qch_docs.commands += && $${DTP}qch_docs.commands += $$eval($${DTP}qch_docs_$${DOC_TARGET}.commands) $${DTP}inst_qch_docs.files += $$DOC_QCH_OUTDIR/$${DOC_TARGET}.qch } } !build_online_docs { $${DTP}qch_docs.depends = $${DTP}html_docs $${DTP}inst_qch_docs.path = $$DOC_QCH_INSTALLDIR $${DTP}inst_qch_docs.CONFIG += no_check_exist no_default_install no_build install_$${DTP}docs.depends = install_$${DTP}inst_qch_docs $${DTP}docs.depends = $${DTP}qch_docs INSTALLS += $${DTP}inst_qch_docs QMAKE_EXTRA_TARGETS += $${DTP}qch_docs install_$${DTP}docs } else { $${DTP}docs.depends = $${DTP}html_docs } $${DTP}inst_html_docs.path = $$DOC_HTML_INSTALLDIR $${DTP}inst_html_docs.CONFIG += no_check_exist no_default_install directory INSTALLS += $${DTP}inst_html_docs install_$${DTP}docs.depends += install_$${DTP}inst_html_docs QMAKE_EXTRA_TARGETS += $${DTP}html_docs $${DTP}docs unset(DTP) qbs-src-1.13.1/doc/external-resources.qdoc000066400000000000000000000062151347155106100204250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \externalpage https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html#//apple_ref/doc/uid/TP40012302-CH7-SW28 \title Adopt the @2x Naming Convention */ /*! \externalpage https://login.qt.io/ \title Qt Account */ /*! \externalpage https://www.qt.io/ide/ \title Qt Creator */ /*! \externalpage https://www.qt.io/download/ \title Qt SDK */ /*! \externalpage https://doc.qt.io/qt-5/licensing.html \title Qt Licensing */ /*! \externalpage https://www.gnu.org/licenses/gpl-2.0.html \title GNU General Public License, version 2 */ /*! \externalpage http://www.linfo.org/bsdlicense.html \title BSD */ /*! \externalpage https://chocolatey.org/packages/qbs \title Chocolatey */ /*! \externalpage https://www.macports.org/ports.php?by=name&substr=qbs \title MacPorts */ /*! \externalpage https://brew.sh/ \title Homebrew */ /*! \externalpage http://www.typescriptlang.org \title TypeScript */ /*! \externalpage http://www.typescriptlang.org/docs/handbook/compiler-options.html \title Compiler Options */ /*! \externalpage https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/dyld.1.html \title DYLD documentation */ /*! \externalpage https://dmgbuild.readthedocs.io/en/latest/settings.html#background \title dmgbuild - Settings */ /*! \externalpage http://www.jrsoftware.org/isinfo.php \title Inno Setup */ /*! \externalpage http://nodejs.org \title Node.js */ /*! \externalpage http://wixtoolset.org \title Windows Installer XML Toolset */ /*! \externalpage https://clang.llvm.org/docs/JSONCompilationDatabase.html \title JSON Compilation Database Format Specification */ /*! \externalpage https://github.com/protocolbuffers/protobuf \title protoc */ /*! \externalpage nolink \title macOS \internal */ qbs-src-1.13.1/doc/fix-qmlimports.py000077500000000000000000000132021347155106100172650ustar00rootroot00000000000000#!/usr/bin/env python ############################################################################# ## ## Copyright (C) 2017 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# from __future__ import print_function import os import glob import errno import sys import argparse import shutil import urllib from subprocess import Popen, PIPE import re from collections import Counter import platform useShell = (platform.system() == 'Windows') gotSoup = True try: from bs4 import BeautifulSoup except ImportError: print('Warning: Failed to import BeautifulSoup. Some functionality is disabled.', file=sys.stderr) gotSoup = False qmlTypeString = ' QML Type' # Modifies a QML Type reference page to look like a generic # JavaScript reference - Removes the 'QML Type' strings from # the titles as well as the import statement information. # This is used in the Installer Framework docs, which contain # JS reference documentation generated using commands specific # to documenting QML code. # # Parameters: a Beautiful Soup object constructed with an opened # html file to process. # # Returns True if the element tree was modified, False otherwise def modifyQMLReference(soup): pageTitle = soup.head.title.string soup.head.title.string = pageTitle.replace(qmlTypeString, '') for t in soup.find_all('h1', class_='title'): t.string = t.string.replace(qmlTypeString, '') for table in soup.find_all('table'): td = table.find('td') if td and td.string: if 'Import Statement:' in td.string: td.parent.extract() return True return False if __name__ == '__main__': parser = argparse.ArgumentParser( description = """Removes bogus import statements from the offline docs""") parser.add_argument('outputdir', help = 'output directory of the generated html files') args = parser.parse_args() if not gotSoup: print('Error: This script requires the Beautiful Soup library.', file=sys.stderr) sys.exit(1) if not os.path.isdir(args.outputdir): print('Error: No such directory:', args.outputdir, file=sys.stderr) sys.exit(1) # compile a list of all html files in the outputdir htmlFiles = [] for f in os.listdir(args.outputdir): fullPath = os.path.join(args.outputdir, f) if os.path.isdir(fullPath): continue if os.path.splitext(f)[1] == '.html': htmlFiles.append(fullPath) sys.stdout.flush() modified = {} pre_blocks = {} fileCount = 0 progStep = max(16, len(htmlFiles)) / 16 for html in htmlFiles: fileCount += 1 if not (fileCount % progStep): print('.', end='') sys.stdout.flush() with open(html, 'r+') as file_: try: soup = BeautifulSoup(file_, 'lxml') actions = [] val = 0 if modifyQMLReference(soup): actions.append('Removed QML type info') for a in actions: modified[a] = modified.get(a, 0) + 1 if actions: file_.seek(0) file_.write(str(soup)) file_.truncate() file_.close() except (AttributeError, KeyError): print('\nFailed to parse', html, ':', sys.exc_info()[0], file=sys.stderr) except IOError as e: print('\nError:', e, file=sys.stderr) except ValueError as e: print('\nError:', e, file=sys.stderr) if 'lxml' in str(e): print('(If using pip, try \"pip install lxml\")', file=sys.stderr) quit(1) for k, v in modified.iteritems(): print ('\n\t', k, 'in %d files' % v, end='') pb = pre_blocks.get(k, 0) if pb: print (' (', pb, '
 blocks)', sep='', end='')
    print('\n')
qbs-src-1.13.1/doc/fixnavi.pl000066400000000000000000000147361347155106100157330ustar00rootroot00000000000000#! /usr/bin/perl -w

#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qbs.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################
use strict;

my @files = ();
my %defines = ();
for (@ARGV) {
    if (/^-D(.*)$/) {
        $defines{$1} = 1;
    } elsif (/^-/) {
        printf STDERR "Unknown option '".$_."'\n";
        exit 1;
    } else {
        push @files, $_;
    }
}

int(@files) or die "usage: $0 [-D]... \n";

my @toc = ();
my %title2page = ();
my $doctitle = "";
my $curpage = "";
my $intoc = 0;
my %prev_skips = ();
my %next_skips = ();
my %define_skips = ();
my %polarity_skips = ();
my $prev_skip = "";
my $next_skip = "";
my $define_skip = "";
my $polarity_skip = 0;
for my $file (@files) {
    my $skipping = 0; # no nested ifs!
    open FILE, $file or die "File $file cannot be opened.\n";
    while () {
        if (/^\h*\\if\h+defined\h*\(\h*(\H+)\h*\)/) {
            $skipping = !defined($defines{$1});
            if (!$intoc) {
                $define_skip = $1;
                $polarity_skip = $skipping;
            }
        } elsif (/^\h*\\else/) {
            $skipping = 1 - $skipping;
        } elsif (/^\h*\\endif/) {
            $skipping = 0;
        } elsif (keys(%title2page) == 1 && /^\h*\\list/) {
            $intoc++;
        } elsif (!$intoc) {
            if ($skipping && /^\h*\\previouspage\h+(\H+)/) {
                $prev_skip = $1;
            } elsif ($skipping && /^\h*\\nextpage\h+(\H+)/) {
                $next_skip = $1;
            } elsif (/^\h*\\page\h+(\H+)/) {
                $curpage = $1;
            } elsif (/^\h*\\title\h+(.+)$/) {
                if ($curpage eq "") {
                    die "Title '$1' appears in no \\page.\n";
                }
                if (length($define_skip)) {
                     $define_skips{$1} = $define_skip;
                     $polarity_skips{$1} = $polarity_skip;
                     $prev_skips{$1} = $prev_skip;
                     $next_skips{$1} = $next_skip;
                     $define_skip = $prev_skip = $next_skip = "";
                }
                $title2page{$1} = $curpage;
                $doctitle = $1 if (!$doctitle);
                $curpage = "";
            }
        } else {
            if (/^\h*\\endlist/) {
                $intoc--;
            } elsif (!$skipping && /^\h*\\(?:o|li)\h+\\l\h*{(.*)}$/) {
                push @toc, $1;
            }
        }
    }
    close FILE;
}

my %prev = ();
my %next = ();
my $last = $doctitle;
for my $title (@toc) {
    $next{$last} = $title2page{$title};
    $prev{$title} = $title2page{$last};
    $last = $title;
}

for my $file (@files) {
    open IN, $file or die "File $file cannot be opened a second time?!\n";
    open OUT, '>'.$file.".out" or die "File $file.out cannot be created.\n";
    my $cutting = 0;
    while () {
        if (!$cutting) {
            if (/^\h*\\contentspage/) {
                $cutting = 1;
            }
        } else {
            if (/^\h*\\title\h+(.+)$/) {
                if (defined($define_skips{$1})) {
                    print OUT "    \\if defined(".$define_skips{$1}.")\n";
                    if ($polarity_skips{$1}) {
                        print OUT "    \\previouspage ".$prev_skips{$1} if ($prev_skips{$1});
                        print OUT "    \\else\n";
                    }
                }
                print OUT "    \\previouspage ".$prev{$1} if ($prev{$1});
                if (defined($define_skips{$1})) {
                    if (!$polarity_skips{$1}) {
                        print OUT "    \\else\n";
                        print OUT "    \\previouspage ".$prev_skips{$1} if ($prev_skips{$1});
                    }
                    print OUT "    \\endif\n";
                }
                print OUT "    \\page ".$title2page{$1};
                if (defined($define_skips{$1})) {
                    print OUT "    \\if defined(".$define_skips{$1}.")\n";
                    if ($polarity_skips{$1}) {
                        print OUT "    \\nextpage ".$next_skips{$1} if ($next_skips{$1});
                        print OUT "    \\else\n";
                    }
                }
                print OUT "    \\nextpage ".$next{$1} if ($next{$1});
                if (defined($define_skips{$1})) {
                    if (!$polarity_skips{$1}) {
                        print OUT "    \\else\n";
                        print OUT "    \\nextpage ".$next_skips{$1} if ($next_skips{$1});
                    }
                    print OUT "    \\endif\n";
                }
                print OUT "\n";
                $cutting = 0;
            } else {
                next;
            }
        }
        print OUT $_;
    }
    close OUT;
    close IN;
    rename($file.".out", $file) or die "Cannot replace $file with new version.\n";
}
qbs-src-1.13.1/doc/howtos.qdoc000066400000000000000000000420201347155106100161100ustar00rootroot00000000000000/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
    \contentspage index.html
    \previouspage custom-modules.html
    \nextpage reference.html
    \page howtos.html

    \title How-tos

    This page provides concrete instructions for common scenarios.

    \list
    \li \l{How do I build a Qt-based project?}
    \li \l{How do I make my app build against my library?}
    \li \l{How do I use precompiled headers?}
    \li \l{How do I make sure my generated sources are getting compiled?}
    \li \l{How do I run my autotests?}
    \li \l{How do I create a module for a third-party library?}
    \li \l{How do I build against libraries that provide pkg-config files?}
    \li \l{How do I create application bundles and frameworks on iOS, macOS, tvOS, and watchOS?}
    \li \l{How do I apply C/C++ preprocessor macros to only a subset of the files in my product?}
    \li \l{How do I make the state of my Git repository available to my source files?}
    \li \l{How do I limit the number of concurrent jobs for the linker only?}
    \li \l{How do I add QML files to a project?}
    \endlist

    \section1 How do I build a Qt-based project?

    First of all, your project files need to declare \l{Depends}{dependencies}
    on \l{Qt} modules.

    To build the project, you need a matching \e profile. The following commands
    set up and use a Qt-specific profile:
    \code
    $ qbs setup-qt /usr/bin/qmake qt
    $ cd my_project
    $ qbs profile:qt
    \endcode
    If you plan to use this profile a lot, consider making it the default one:
    \code
    $ qbs config defaultProfile qt
    $ cd my_project
    $ qbs
    \endcode
    See \l{Managing Qt Versions} for more details.
    \note These instructions are only relevant for building from the command line.
    If you use Qt Creator, profiles are set up automatically from the information in the Kit.

    \section1 How do I make my app build against my library?

    This is achieved by introducing a \e dependency between the two products using the
    \l{Depends} item. Here is a simple, but complete example:
    \code
    Project {
        CppApplication {
            name : "the-app"
            files : [ "main.cpp" ]
            Depends { name: "the-lib" }
        }
        DynamicLibrary {
            name: "the-lib"
            Depends { name: "cpp" }
            files: [
                "lib.cpp",
                "lib.h",
            ]
            Export {
                Depends { name: "cpp" }
                cpp.includePaths: [product.sourceDirectory]
           }
        }
    }
    \endcode

    The product \c the-lib is a dynamic library. It expects other products to build against it, and
    for that purpose, it exports an include path (via an \l{Export} item), so that the
    source files in these products can include the library's header file.

    The product \c the-app is an application that expresses its intent to link against \c the-lib
    by declaring a dependency on it. Now \c main.cpp can include \c lib.h (because of the exported
    include path) and the application binary will link against the library (because the linker
    \l{Rule}{rule} in the \l{cpp} module considers library dependencies as inputs).
    \note In a non-trivial project, the two products would not be defined in the same file.
          Instead, you would put them into files of their own and use the
          \l{Project::references}{Project.references} property to pull them into the project.
          The product definitions would stay exactly the same. In particular, their location
          in the project tree is irrelevant to the relationship between them.

    \section2 Choosing Between Dynamic and Statically-built Qt Projects

    To build \c "the-lib" as either a dynamic or static library, depending on
    how Qt was built, you can use the following code:

    \code
    Product {
        name: "the-lib"
        type: Qt.core.staticBuild ? "staticlibrary" : "dynamiclibrary"

        Depends { name: "Qt.core" }
        // ...
    }
    \endcode

    \section1 How do I use precompiled headers?

    If you use a \l Group item to add a precompiled header file to a product
    and mark it with the \l{filetags-cpp}{relevant file tag} (\c c_pch_src,
    \c cpp_pch_src, \c objc_pch_src, or \c objcpp_pch_src), it is used
    automatically.

    Only one precompiled header is allowed per product and language.

    For example:

    \code
    CppApplication {
        name: "the-app"
        files: ["main.cpp"]

        Group {
            files: ["precompiled-header.pch"]
            fileTags: ["cpp_pch_src"]
        }
    }
    \endcode

    \section1 How do I make sure my generated sources are getting compiled?

    The rules in a \QBS project do not care whether its inputs are actual source files
    listed on the right-hand side of a \l{Product::files}{files} property or artifacts
    that were generated by another rule. For instance, the C++ compiler rule considers
    all input files of type "cpp", no matter how they got into the product. The following
    example project demonstrates this. One of its source files exists in the repository,
    the other one is generated at build time. Both are getting compiled the same way.
    \note Do not try to add the generated files to a \c files property. Declaring them
    as rule outputs is all that is needed to make \QBS know about them.
    \code
    import qbs.TextFile
    CppApplication {
        files: ["impl.cpp", "impl.h"]
        cpp.includePaths: sourceDirectory
        Rule {
            multiplex: true
            Artifact { filePath: "main.cpp"; fileTags: "cpp" }
            prepare: {
                var cmd = new JavaScriptCommand();
                cmd.description = "generating " + output.fileName;
                cmd.sourceCode = function() {
                    var f = new TextFile(output.filePath, TextFile.WriteOnly);
                    f.writeLine("#include ");
                    f.writeLine("int main()");
                    f.writeLine("{");
                    f.writeLine("    return functionFromImpl();");
                    f.writeLine("}");
                    f.close();
                };
                return cmd;
            }
        }
    }
    \endcode

    \section1 How do I run my autotests?

    There are two simple things you need to do in your project. Firstly, you
    mark your test executables as such. This is done by adding the tag \c{"autotest"}
    to the product type:
    \code
    CppApplication {
        name: "test1"
        type: base.concat("autotest")
        // ...
    }
    \endcode
    The second step is to instantiate an \l AutotestRunner product in your project:
    \code
    Project {
        // ...
        AutotestRunner { name: "run_my_tests" }
    }
    \endcode
    Building an AutotestRunner product does not produce artifacts, but triggers execution of all
    applications whose products are tagged as autotests:
    \code
    $ qbs -p run_my_tests
    test1: PASS
    test2: PASS
    test3: FAIL
    ...
    \endcode
    See the \l{AutotestRunner}{AutotestRunner documentation} for how to fine-tune the behavior.

    \section1 How do I create a module for a third-party library?

    If you have pre-built binary files in your source tree, you can create
    modules for them and then introduce dependencies between your project and
    the modules to pull in the functionality of a third-party library.

    Create the following folder structure to store the module files:

    \code
    $projectroot/modules/ThirdParty
    \endcode

    Then create a file in the directory that specifies the module properties
    for each supported toolchain. The filename must have the \c .qbs extension.
    The module will be pulled in if a product declares a dependency on it.

    In the following example, \c lib1.dylib is a multi-architecture library
    containing both 32-bit and 64-bit code.

    \code
    ---ThirdParty.qbs---

    Module {
        Depends { name: "cpp" }
        cpp.includePaths: ["/somewhere/include"]
        Properties {
            condition: qbs.targetOS.contains("android")
            cpp.dynamicLibraries: ["/somewhere/android/" + Android.ndk.abi + "/lib1.so"]
        }
        Properties {
            condition: qbs.targetOS.contains("macos")
            cpp.dynamicLibraries: ["/somewhere/macos/lib1.dylib"]
        }
        Properties {
            condition: qbs.targetOS.contains("windows") && qbs.architecture === "x86"
            cpp.dynamicLibraries: ["/somewhere/windows_x86/lib1.lib"]
        }
        Properties {
            condition: qbs.targetOS.contains("windows") && qbs.architecture === "x86_64"
            cpp.dynamicLibraries: ["/somewhere/windows_x86_64/lib1.lib"]
        }
    }
    \endcode

    Finally, declare dependencies on \c ThirdParty in your project:

    \code
    CppApplication {
        name: "the-app"
        files: ["main.cpp"]
        Depends { name: "ThirdParty" }
    }
    \endcode

    \section1 How do I create application bundles and frameworks on iOS, macOS, tvOS, and watchOS?

    Creating an application bundle or framework is achieved by introducing a
    dependency on the \l{bundle} module and setting the \l{bundle::isBundle}
    {bundle.isBundle} property to \c true.

    Here is a simple example for an application:

    \code
    Application {
        Depends { name: "cpp" }
        Depends { name: "bundle" }
        bundle.isBundle: true
        name: "the-app"
        files: ["main.cpp"]
    }
    \endcode

    and for a framework:

    \code
    DynamicLibrary {
        Depends { name: "cpp" }
        Depends { name: "bundle" }
        bundle.isBundle: true
        name: "the-lib"
        files: ["lib.cpp", "lib.h"]
    }
    \endcode

    \QBS also supports building static frameworks. You can create one by
    replacing the \l{DynamicLibrary} item with a \l{StaticLibrary} item in the
    example above.

    \note When using the \l{Application} item (or convenience items, such as
    \l{CppApplication}, \l{DynamicLibrary}, and \l{StaticLibrary}), your
    products will be built as bundles on Apple platforms by default (this
    behavior is subject to change in a future release).

    To explicitly control whether your product is built as a bundle, set the \c bundle.isBundle
    property. Setting the \l{Product::}{consoleApplication} property of your
    product will also influence whether your product is built as a bundle.

    Building your application against your framework is the same as linking a normal dynamic or
    static library; see the \l{How do I make my app build against my library?} section for an
    example.

    \section1 How do I build against libraries that provide pkg-config files?

    Just add a \l Depends item that matches the name of the pkg-config module, and \QBS
    will automatically employ \l{https://www.freedesktop.org/wiki/Software/pkg-config}{pkg-config}
    to find the headers and libraries if no matching \QBS module can be found. For instance,
    to build against the OpenSSL library, you would write this:
    \code
    Depends { name: "openssl" }
    \endcode
    That's it. The pkg-config behavior can be fine-tuned via the \l pkgconfig module,
    but normally you will not need to pull it in explicitly.

    Internally, this functionality is implemented via \l {Module Providers}

    \section1 How do I apply C/C++ preprocessor macros to only a subset of the files in my product?

    Use a \l{Group} item to define a subset of project files. To add
    macros within the group, you need to use the \c outer.concat property,
    because you are adding macros to those specified in the outer scope.

    In the following example, \c MACRO_EVERYWHERE is defined for all files in
    the \l{Product} unless a Group overrides the macro, whereas
    \c MACRO_GROUP is only defined for \c groupFile.cpp.

    \code
    Product {
        Depends { name: "cpp" }
        cpp.defines: ["MACRO_EVERYWHERE"]
        Group {
            cpp.defines: outer.concat("MACRO_GROUP")
            files: "groupFile.cpp"
        }
    }
    \endcode

    The \c cpp.defines statements inside a \c Group only apply to the files in
    that \c Group, and therefore you cannot use a \c Group to include a bunch of
    files and globally visible macros. The macros must be specified in a
    \l{Properties} item at the same level as the \c Group if
    they need to be visible to files outside the \c Group:

    \code
    Product {
        Depends { name: "cpp" }
        Group {
            condition: project.supportMyFeature
            files: "myFile.cpp"
        }

        property stringList commonDefines: ["ONE", "TWO"]

        Properties {
            condition: project.supportMyFeature
            cpp.defines: commonDefines.concat("MYFEATURE_SUPPORTED")
        }
    }
    \endcode

    \section1 How do I make the state of my Git repository available to my source files?

    Add a dependency to the \l{vcs} module to your product:
    \code
    CppApplication {
        // ...
        Depends { name: "vcs" }
        // ...
    }
    \endcode
    Your source files will now have access to a macro whose value is a string representing the
    current Git or Subversion HEAD:
    \code
    #include 
    #include 

    int main()
    {
        std::cout << "I was built from " << VCS_REPO_STATE << std::endl;
    }
    \endcode

    This value is also available via the \l{vcs::repoState}{vcs.repoState}
    property.

    \section1 How do I limit the number of concurrent jobs for the linker only?
    \target job-pool-howto

    While it is usually desirable to run as many compiler jobs as there are CPU cores,
    the same is not true for linker jobs. The reason is that linkers are typically
    I/O bound rather than CPU bound. When building large libraries, they also tend
    to use up enormous amounts of memory. Therefore, we'd like to make sure that
    only a few linkers are running at the same time without limiting other types
    of jobs. In \QBS, this is achieved via \e{job pools}. There are several ways
    to make use of them.

    Firstly, you can provide a limit via the command line:
    \code
    $ qbs --job-limits linker:4
    \endcode
    The above call instructs \QBS to run at most four linker instances at the same
    time, while leaving the general number of concurrent jobs at the default
    value, which is derived from the number of CPU cores.
    The \c linker string on the command line refers to the job pool of the same
    name, which the \l{cpp-job-pools}{cpp module} assigns to all its commands that
    invoke a linker.

    Secondly, you can set a limit via the settings, either generally
    or for a specific profile:
    \code
    $ qbs config preferences.jobLimit.linker 4
    $ qbs config profiles.myprofile.preferences.jobLimit.linker 2
    \endcode

    And finally, you can also set the limit per project or per product, using a
    \l JobLimit item:
    \code
    Product {
        name: "my_huge_library"
        JobLimit {
            jobPool: "linker"
            jobCount: 1
        }
        // ...
    }
    \endcode
    The above construct ensures that this specific library is never linked at
    the same time as any other binary in the project.

    Job limits set on the command line override those from the settings, which in turn
    override the ones defined within a project. Use the \c{--enforce-project-job-limits}
    option to give the job limits defined via \c JobLimit items maximum precedence.

    \section1 How do I add QML files to a project?

    The simplest way to add QML files to a project is to add them to a
    \l {The Qt Resource System}{resource file}:

    \code
    QtGuiApplication {
        // ...

        files: "main.cpp"

        Group {
            prefix: "qml/"
            files: ["main.qml", "HomePage.qml"]
            fileTags: ["qt.qml.qml", "qt.core.resource_data"]
        }
    }
    \endcode

    In the example above, we declare each QML file as having the
    \l {filetags-qtcore}{"qt.core.resource_data"} file tag. This ensures
    that it is added to a generated resource file.
*/
qbs-src-1.13.1/doc/images/000077500000000000000000000000001347155106100151645ustar00rootroot00000000000000qbs-src-1.13.1/doc/images/qbs-build-process.png000066400000000000000000000123271347155106100212350ustar00rootroot00000000000000‰PNG


IHDRIé8H>t PLTE°P°p°±Q½½¬ËȱR³V´Xµ[¸a¹c¹cºf ºf!»g&¼k(½l0¿q6Áu8Âw:°P:°p:°:½P:½p:½:Ë:ˬ:ËÈ:ØÈ:Øä@Ä|HÇ‚PɇXÌ`Î’eÏ–f°Pf°pf½Pf½pfËfجfØäfåäfåÿhјnÒ›pÓxÖ£×§ƒÙ«‡Ú­Ü²½PËpËåÈòÿ—߸Ÿá½§äïæÈ¶ËP¶Ëp¶Ø¶å¬¶åȶåä¶òÿ¶ÿÿ·éοëÓÇîÙÏðÞ×óäÛØpÛØÛåÛåÈÛòäÛòÿÛÿÿßõéçøïïúô÷ýúÿåÿò¬ÿòÈÿòäÿÿÈÿÿäÿÿÿ$ɱÂrIDATxÚí{Ú8†Ew’í¶»Ë®YÜvzÃ$l›Ì´dC–dfHH;íd€ÐÙ6ÜBþÿÿb…/\,K::8GÏÓ(±MùüZ::–t$æB¥vÕq˜îä8û箙¾gP±*ͦö¯i6s¥~šI¶óU°[:±é%ynAÖ¹žsšV’ƒ\ô¦z¹^JIVªÀwUßN'Éóømm¦’äÁøm”RI2ß¿­n6•$³ÝôúɰßWD’HI"I$‰$‘$’D’HI"I$ÓFòë™ëŽ–ÉØi|TàÿÊ·Ž_ýæ,I’QEïËF‡Êä²ï]„¿tf¹G2€z1w™OráÄìƒ÷šäøˆ1;Sãùs›±WsyP»‡;|&@9¼ìóÿòOج|`£Cer’>nr ¯;îÐ.ÏrŸäøèUgî2¿Lú'x¡õ/ì¸WoÊDr’.7:~#ò¡0Ë}’Ã'µùËf$ý³É«Ÿw¿·§$7gy@òéïó—Í‘ôNL?@$‡ö»oË•$ÃˈäÒï˜Ð‰Q»Ã˨v/'ù€­?’œÎ,_hqÂË|¤Ó‡·4Dræ=c/l^IYÆÎ¼sgyèÙä]æ^ï,xA¯\"yÿæ@<×;Ìo_pÛ
_Ð;NTÙ,/äÔD$“üµ¶ITwE$‰$‘$’D’HI"I$‰$‘$’Dÿ7>îI5)¼Þ”J’¥ðÛj:©$Ù(‚ßÖÞq:íIz€vnN’=xi
1§@mÜÉ6hÙ¯¤×ï:ÌÁ•’vÞH0¿«ßƒ1–çû¹–›f’®{\d)w8pSN2}êˆ$‘$’D’ÔIÒJ$‰$‘$’¤•H’:"IZ‰$‘$uD’´IRG$‰$‘$’¤ŽH’V"I$‰$‘$­D’ÔIÒJ$•§Ö¿DRAêïåÅ­‘”M'Ö$:éÔªI©ÔvJ~iìWÍÀOÉÁAn¶ðy~¿O$“¥Fî`!€áЪÉ©·]l¯>D$W¦èx³˜ÉUi©Q\0Dr¥yWC=mΉäÊ´Êyô]L"¹*uW¿Ððמ6‘\•ªVœ—ì–UI5„ªÙ‘\^kKµ¶W,öˆä’–$+¶N#[%’ÑÞè{õa·†q’Jû<¿×'’Õª&l‹­"9k<¶ŠÝä.9m"vVœJ}¾‰©[à ɖ|.ïÖhÜ{’ý}%Kvµ‹Û½ûM²n*ûŸŽï1ɮʒĻ5Îï)ÉA¼Î
‹›«ôï#ÉfN}wNUÒXG’}=^ ÷L{÷‹¤hg…ÀÛ’án
X’í|IŸAT¬Ö=!©ýVµ>(D$!ªŸ>ã‡$P“Ð7Ö­EÎMÑádá!	ê:+wüñëšèÖ i¢‹A]	’†º½uÚá!i°+¶<X/I±á¯g|“î…Rß~Ú­¡“¤àÕt7ùÙ²´ÛMIÑaÔ	É…2©`KïäƒÀxHŠí{$ƒ4ê,’'­ç	'&à!™dºIX»ÇGÏmÆ6:>É/ü—댙œxÿÑ.¦	&Ë "™¨³bF²Ðq¯Þ”½?†OøVóxa½|ðûø(óòm·†’	§åÍHNÊÝï¯Æ_¿å4¯ß”ÛM¡I…ˆH&*A2cóºÍËå/Ÿ?Ú)K´@SÕ“tŠ	5G|ý¿LmBòÅ<Õ¤Úò’³v$»I#‰£j·ûJÏVÊyESýuØÉ„‘Ä‘$¯½–§ I"üDKÛ,’8’ä¤Ív‡;ì›´ÝÉH„Diò'UG¾Ét¢€øæÚÞq°Dƒ…Žê{ïFI(‚¥¡8 ¨Zû'
GÃ.û ¹ÏÜ`$1ôR$ÚÇqLEƒ/£lÑH$q~É&ˆñnøHbs`æ`ÀF›‰šIÒiŽ$Ü”[cóþàæO‚DC
Ú%	I7h˜¤îHbÀÁmã$uFƒN¸0OR_$ñ¡éØ&ø1-Ó×Zæ×¨4·¨|J%üdI$$UOó50
I•SÏ»Hbå­9 (ÂP &’jBtLßà")6ÖÇ´ÎÙõ‚äº5)¢#)^k4pÉÄ@sc$™¬’"\7Ãú“Â
‡ùE/’uf,Ä‚–¤ˆƒbq ¼$c¿ô!Y°
3Éxu¼kÃcZceçž…ý“\Ña‹i±Iô$ïDh"ß×Ýþ8K¶-Ê»$£[±-½$oOÀ·xùš¼1)e°ûbÝoqÖ­r“‡5"NÞCºñÈ:‘ô'”bÝg½Hºîþ\¸DR…±¤ý»‰$‘$’D’HI"I$‰$‘$’D’HI"I$‰$‘$’D’H®)ɦâTaM­©‡–$s§¿9:Óã¼$ݵJ%"I$‰$‘$’D’HI"I$‰$‘$’D’HI"I$‰$‘$’D2ÎÍw‹Î#¦9=tœƒvÊIV­ýFS{Øå Ù<°ŒÅÜ@ìo¯j*À€dvMÇv^~róÆ(’¤¼¾z×’­‰ŒQ»§ÒE‘¬V ëÙñžÔÇQ#¦£„ˆ'©µŸq£’ðÆÿ¤$ñaÆ(‚dÑ@HuÛ’¨n8ŒQɬ‰í˜âoŒ"îàá`­Hb1FÉÛsò/ÅbŒÖŸ$c´þ$±£õ'‰E.‘$’D’HI"I$ï1É‘T#m|T&’T&M’ÍÁ]ÌŸèÌŠé‘\U‘ŸÛŒ½Üån¯ùŒÙ™šW»ý>Ëá³YHÞM²Ðq‡OÞsZO÷Ž|ÜHòWoÊÁEü¼]&’«ïÇõÛšwär£ã“œ€ûàÄá“Úôw$¿ž!&9ùqõóî÷vI¯¸~ØDCÒ«$˜Iíwß:—DRžäå¤Á^»'^D@2t4¾uæ3OCɼìýqƒäõnÙ´>†Ir/‚1OPèh¸'3}
a&æiè"ÉÅ=c/ìÍE’œ §í/h|ôª3_»¹£1|Zó-Pm¾êÇô4ô½ã,­Hýd¦‘­Ý¡£áÿ²9˨v¶8¡£áöK Ï={Üg>´ç¼ ÏÑðŽ|wd‚žÆ½}˜yáocß%›õÌ×$Ö¾ "I$‰$‘$’D’HI"I$—Z³xÄ$ó­{ÓHrï^Y£˜F’M^™Dø?âxw»-¬•OþY,Æ(ŠdßÞèy“X ‹1Š´2
§
²t(ñi,Æ(Ú^×!£ø[¹C©Ï#1FKZ¾^qû&°¹——\{	‰1ZêCÔ·2ˆäÈ›9Æ(몡0FéX¡ƒ1JËZæÑ}^5‘áý߈$‘$’D’HI"I$‰$‘$’D’HI"I$‰$‘$’D’HI"I$‰$‘$’D2}$Ùë#½ùÛë¯ÈFö¿ÇÙ”$Ù+•¦5õŠE>í_Ê·Ñ‘T/Mgªfƒ9Y-e›2¼Òô¥Så(Hj‘¦+ݬ7~mBAR“4Méä¶-od«(Hê’¦%µó¥ÿbP±ZÆIꓦÅ\*+ú6IꔦŬ
U-@’Z¥éq!ã›{@’š¥)®Ø1\
)Žá•¦45s±”T³§à$õKSY±KNÌÚÑÛ*vAIBHS—Ž-‹Ý°ª8’ ÒT¥ó¼XÕ ’k‘’¦èݰ’ölÛN©@Lš’tj%zÛ:±Žµ“„“¦ u‹[	Ÿ`/®•$¤4.¤Ldh+Wék#	+
È…¼Ãƒ³N5‘–åB*òà^ip.¤Žá•&‘ZyU£œñ=8†WZrr_åBmg»§Œ¤iISÝ:4ñ2¼Ò>§¢úç«$1¼ÒÙŽƒœ–ÍV~¿/IÒ ´$íYî@W{vhÕ¥Hš”&îcm5öѯúß^iæP±bx¥a0¦Žá•†¢	‹ßü2¼Ò¸Uq¿Šá•fÔ…/þ¯´ø¯ŸÀsã¢íÃ+
S—È­¶ø$I4ÒbyR†Æ€#º^i1d×ñt«Û›á•¶Ú((ιIöH¿9ÃtHK¦Op”HÙ›¿1q‚½‡™i‰õ‰Œ\*ö%Þ#}~Èšé–\_ÜÑt©Á&ŠÓ½GÓ“¼>÷ÂÂE±+Æl—¦U_¬#þèá.çã£ç|ÏÏ—»üØëàW³Ús½“±3“ßߌ¹·;7µ‡‰JÓ®oõ¬#?m~t¾Ë9Ï;|+ß÷ÞÎÈã£×ÿ` t²»/ß¶v|”y)b߃±B–Ä…Ô¬ïîaL!?-Ø$9ÜÙÛñÞûqý¶æåÁÁ‰R~ˆSö{p,‰©[ß]Î¥˜ŸlÜîÍ=SÊJ7C¥Ã'¿|þüiGœ¤ïÁ±$.¤~}KK§Ø×§ôÅ<Õäëî;LP”>.m‰£$¶´öÌ”fJkSÿM´	ç±	¬› 4N¿¾;Â&„âÏæ-úU`b”ry¡ÒÐg'éÅ˰$¡qÚõÝÊ#æoîr~C)ã^Å»™—Á/zÆ&m£É †‹¹IBãôê[^&vÓóÝ88ú– {4€ÇÄ¥iÖ빪ˆ?KÒ²Üak˜BiJôÅ´5
âÏœ’c
¥)Ð'.6þµ&y¯QrL¡4y}bË^Üà/†WšÒ¬<ݪÃ¯4…VU}ºÝ®0¼ÒÔµôÊÓy„¯ÃðJ‹ï}×£è>T†WZüâ¶¤_Ÿá•&ð$ãÏ–Ž51¼Ò„š} ø³;Æ?^i‚®(ÄHý]cò¯4Ñ×#í³Gîž'ÂðJw.õÎhZ%ÇðJKâ\ê‹?[9äÉðJKä\jZÜ †ŸÆðJCä\ÆñÓ^ihœËx~Ã+
‰s98ˆç§1¼Ò¤œËº2‡ nÌÃ+MÊ¿R&ðÿ0¼Ò<0‘(9†Wš´‘
áÉ`x¥É;—RaE¢aB¯4I"þLø£¯4%Îe§— Ì0¼Ò9—	,J";ÆðJS•„[¹dm+Ã+Ís™ÔOcx¥™q.ûi¯4Îe+—ØOcx¥©v.W÷šHõÕ0¼ÒT§•=yrý‡¯4õÎå½Ë²}Ú¯4
iùˆ‡ü8Ã+MKZ2
§`ìᕦɹŒV2ÍðJÓ•nÍVP3G‚ᕦϹ\˜A£jh…ᕦ1͆äÔùi¯4çR¡ŸÆðJÓï\*õÓ^iÚËþU¥Ÿ¦r¯äóü½é®Q:8p‘’tK'.‘$’D2yÚ;&’å*%YlI5ÉiI"I$‰$‘LIµ
ä}&©V.‘$’©&™oI5)Û%’D’HJ¤Ü9‘Ä(—HI"I$‰$‘4L²{Xt1±ô'Áë:Ϊ°ˆÓ’“cz“ål×Â$«Ö~£©{¢Ô ÙR»Yß^¾Bg4É^±6´*¿´È ’‡Šøé—-JI²kA¶ó’omƒ<äš™'9ê€{Ǻ–\¨À.>Ú(Æ&Y­7¢Ç{R62,w»“¤lId:69è¨È^dýŽ ©vâQ<ÛSJþÙú6¸ÜHsAÒÀœ”¶¥º®iM‘ö„áxS‘xÕÊÁOkï?ŠwkEòq‡\¦ùU\?I,r‰$‘$’D’HI"I$‰$‘$’©!9"’jH*ظP7ɯgT&•|4ÜÉѼ…SG™ô‹ÅCs§ˆd é9ßÜ÷å.GÍÿ`ÌÎÔ‚Í|''6|`|S_¾°è•æ†HNj@2|îß:ó™¢/L²Ðá{J¿Ÿî†î~Ü·EîLv ö/
6¥~ͯµËan„døPÓçî~œÌ§(„™²/L²ü¸~ëïšz¹ÑñINH}ð•ù›ŸÏ‚&9¿Óxð܇OýmÜŸÖn^#÷à“œü¸úy÷{;‚¤_\ƒC›an‚äô¡$ùs¿|à©2u^†äÐ~÷­s‰›d(…›>wöüÇ37ÈÔÉ•!y9i`p×î9’ásçíɧŸìÂ4CArRAþ¸Aòz·<5yÔÍ=ùjp,€²Ô«o=dÉQàruspoɃ3áתoKó€EYM7½$'÷wáVöŽ—ï%™’nw?`‹ï-_tãÿ܆Ô—[fIEND®B`‚qbs-src-1.13.1/doc/images/qbs-dmg.png000066400000000000000000001206521347155106100172320ustar00rootroot00000000000000‰PNG


IHDR•óf
¼ôPLTE~ÖŠêèêããã}ÔˆtÅ~rÃ|mºwl¹uvÇ€o»yxÉ‚q¾{p¾z×Ö×ËÈÊÐÎС¡¡¢°£j´sÙØÙ=jCæäæ~Õ‰}ÔˆÖŠ€×‹|Ӈ،‚Ù{Ò†ƒÚŽ|ÓˆzÑ…ÕŠ׋€Ö‹|Ò‡èæèÙØÙÙŒàÞàüûü„ÚÛÕÚÖ‹ÛÙÛåäåãá䂨ÝÛܱ¾²„߆á‘IÌYÀëÅÛÃíÈyÒ„¾êĽé°¼±ƒÜŽlÌö„ÜvÏ‚}ÔùƒÞÂëǪâ±oÍ÷wЃ±å·Äðɇâ“zÐ…ÖÖ×´çº{Ö‡zÎò­ä´yÔ…FËWÕúìëíÝÜÞrÏø@ËSuÑùÙרÇôÍ»æÁNÌ^ÿÿÿyÓúHÉY¿íÉ|Ñ÷ÄÃĹá¾}׈ŽÚ—‹‰‹4ÉK˜Þþ‘Úþa¿é®±´z΋wÉíeËqÓÑÒÍËÌ|Ô‚rÆí¿¾À°ÆP\WnÁç´Ûº~Ö…–t€Ö–ËÈÇ{ÐõfÃí[ºæÇð̤ӾÀá¸qÇzkÂu؈ØñÛÂñÌ·¹¼½Ù¯hµ•˜£~ihi±àÅ{Ð|¦¥§™Ý¡)ÈEuÎõÎÏҖó{ÑçrËä›Ì¸­Ð¯˜sqsovgüc_ü¾Eñïñ˜ßï¯Ö´¤²‹ÅÇÌÅé¾]{}soTÊñÅWlm^a_?6@¬ÚÁµ®«vž™«¾”m¶wöûöËúÑ·èË~ÐŽÈ=}Ôþ„¬¡¤šL¹Z^[LMTJmÈñ—œ¦È-¸Ñ§š™›h‹Š†}yé÷ꉵ¨q„t„fALSM2"åèëJ`häÞÜ–°™m““ûTN–ÞóÁº¶¥Å§|¤˜‘Žy•Šz|‚Å“|Â…þ¿*™ÐžoÑyð¾n[Ëh+E4 Ǫ7’ÚçQ±àçÕÏä³´ÌÕÒãÍǸɹ~«ƒ„[ÿ½k¸˜üKB_M5¯ÉÖÒßÒꛛ싊tº},Oa…ÐééÏ´©¸«ƒØæÃ–“ÒØï{yj¨rW°¢WtRNSþþµþééÞÞéÞéÝÓáäã"õºeÚ5Æ´ïgžNIDATxÚì”1«ÓPÇ{ÝÅ‚ø<%=¿ƒ[á†Ð劷CÀ2fséP¸J–¦öeȤdxƒ%P§(…R-µÃ[úž‚&¾\?~pýÜ0Y™[~±vÔÓœž»Š]ÜeªÂ6©=ÇPK*+ˆ€ŸÎ&“ÉÙ×"§>GNV>“#ŠoŽ»ÝîñC‹!ìÖ3Öoܾ»n›DùSª+0 \¦‹ÂBOõ¾@hëÜþT0žÒ­7ÎÆ¾@¨XZœ<Ì&%g'9"ò͇bµ)‘Ý?êtºÝÎñˆáÈ|pçöíÛ#éGŒUÚ.åTŵÒÜN‡3Fþ25à±^h”:Ëx?0]ì/‚¨|µ?wl¥
|Œ5ÒjëEJ¢•s˜kd…};‹ÐèOW§u¨Ó¦r¡ÃÖ–Y7ߤ»ö[Ó:_Ñ-¦Rp֨׉šù¡·˜JÂ"zü~ÿQwxy||ùü¬ÌÝðó¢ë¡ó3‘÷4?^YSùªÒ®‡û!Á“µö›t·ÉVÕöë~Ê:d´mvuhîW½¬züþ³¡éí0N
’tµÙå%¶kÌ^¾»Y,‰™õøú÷õÈÂ#j߇·gŒè¯‡Owˆ®ˆØøÔ¦!æéStB¦ˆ­j+=U>zÃ!xËDâB¨Šf|’õij¬·ž%2e,+õ©õêbPÆê©¥¨¤¬L™c“9BËÅÍÂ8J–”QÇl-Mæ9%¸ks°^çy`"'K%Ò¥¸K¥ŽŒQ&ÀÆ·õ‰Hu¬¬„,– ‰Çc„…L›ÌgƩرrÄ£€É1ÜÅXf¶pWÅgÜé,Ný'rÎP0”¬ƒŒ™‹EÀÒ)¦Yb§©¼Ÿ%ÿÈ£ƒ„a
Ã\€s$K^ n–zÈé-Â샿u*EUÀ€±¯Q›.ËÈÿ¼•×¶¾‰53b”D.˜)Õ=­ #Š–-•mE‹mýŠ^ÜlV©ù]Pþ«'÷Ïu…)ÒNtLÖíõx~n²fÑ{&yì3‰žÓE8kÌÍh“ªERºAqX×L]îP‡ê°P¾4"»™Ô@,PB¹Ÿ4F@õC}Ð#%u%í'µ¤ÑØq¢î;eîçÍrÕtçsÅÝ’”ùN¿lÑAÊÜ0àa 7­È±+ÉàÍ,²Ëªºèº÷¿LŸœæÏP˜à±¿<¢—´~?+Åá]A¸™úë¤1Ž~¿¯ÌÆ¥p9
›WŬTü#ÃõÀ}@­Ä{Ý?訧”í/]Ö<ŽÈ7«ƒ8Jf¹©/‹q„Œq#R
èÀFEÐ c`"„§“îcÔc®½XÐ2)/ÊL“
æe‹§l Tþ¡úQÁã®`¿è=M:+j_ð+°YAåù²³‚³-¹é0zWðøùíñÚz#w­¢¸‹4Ïê’i¡†¡'aCimݶ ¼%:©Oš\”žêA{ÖÞ	k©oPßÔ5‹kO35S
¦¹÷XsõIµ‰¼U…µ%ØŒøD®¤}U_‚f¯øiÞ¼¹8¨(2[Ó‹Ò²’· îU²g¤æ ™‚’pPì¤5]s•í®@ç\}RÑôtÄžô
äIW[“Î
òWa-E¯
ø©´ùæÏ³‚µ«Æ\ QÁ_Eøãu·ê4Ex@ñöÏìÉĤ…€œ‹‚‚—‚w¾ÿ¹Öž¤‰Q«á´“Ïv¯•	=ªŠ5ÑÖļùR<Ü|sÓŠ…XEðÃ\&Hj4DVе
já BZ«‡(ÇPïfaÅ@mûÚ Jºöt…ç!UIË“Úf *=ð£YÃ&å°EE$s­O꒔ǠÆ\ëImË
ÜAíï”xV°d®õ—\å¬Ô+* -rT ¤î¢—
j¶eÝß|ÆUÙn,Ŷ…·mfÁ‰n‹²Þ&"{x=èJÚH…AòsšZØIƒ”Gwž -ª ®V+sR'm |Nêê>¨µP4Ïþ”§1¾‚ÄXÒ¯ÒGSSÐ=Wa®Z
ÅAªÆ\ZýZ©û3—±IåB{®ÛAËÿUÐX–IÏ
ê½|þ€{¥„*–ëýSwdk˜-Z3°ŒV+ï¥Êšï×>õxq²Àá¤:“Ú-“jÒxM9N/•ӘΤËìŸØ´“ù£¨
µ&Õjn¦Ö{[IsØl/|§
TÝ* îG®Íž´ÊÚ”¹üRAË
ú¿*ЬÀ0goƒ^+¸M¤GsîÃþZA	g|5³‚êý®ÊVÏ«p?6^Iç@,É[XTϦ©J3¡Ž? á }PפBªáÚvÚð\¥uҙ罒ÆA”Û. A…4dª<Óy«§Ô+mÑ7ÓµéÎó&W*Ö!VóÇÈeê#—d.PÛÎ
ú¯¬ 7Ò£‚Ç*¤ÿ_ŽKºW°çòú‘ôÌÅ{e{ƒ·ª àD3Qÿô­™äÝ,U
'óMðj‰À±rÓ~kžWÔPQu»Wunß™´‰¢å¦ýÖwj­;Uno6†“¤íÛ',o=H
£y¸ÿd§~P
ÐEX"N	)ËYÔZðÈ\qÍ%¹H…,;•x]Á$&gÙsÉ£
Ž\~暎\I¬g[V0ÿZ$2•¯ïËûïoÄð¸ñê+§t¸@¹c”3”µ™-I×U¯Õ{À‚†Â47IjE™G忦ÈoýIaØ«@³¨¡‡ÞH¹Ç1¨êNob6iëƒ6Ò\'J8r-ÌÝI·ÌõŠ2—HÒ‘ë¨`Ë
N*{[·ƒî¹fË

iq»T`¬€eù¥‚Ím¹T0}[ÞáõÀßü,ƒÇ(%Ûá®~Ytß~/-ðäIt­ ëò@‰EÅüQHõ¤Üo b«(sA jR+I+J¹s‚Åûv¡‘THÃŽ­YǰÞPÓØü vÐêzæ:¨ó¶û{.¯*X/,Â\îY]*³‚r­àv­  ×væ2{ƒÿ¯¼ýüÈ;Qrú©"¬$óh¹“T2)PÒP«
ê¤ÅTŠ¿3&Í9-édËø /;Rh¾¤ƒ6K¹ö¤¬n¾aä²/Ö:*8*8=*Àë
в
NgЫ‚1éÌUŸ+Øgþ
¶pOz|‹Uy㮥uãnè&&)Øjp(WÛ«¯z9٩Ô”,ªÏ„ˆVaú¯A— fý/_S€º/¾UÆx–®â›3éãë¢4úÎNeä¤t—&eðê†
nuåBæ’8'8€‘ËmàNµÕ†?Ô&bO+X2—IzÒ™+iV°´ÙÖvËý^ÁÈÅ:*9+°‹¶YÁ—ïïûªœõ¤ç”",”€Ì½K2³»×N€/UÒ±É1):­²Óìõ¢L
C% ë¬gÒ:(ÿA©cœ•Õ«wJ$•²ÐAU³• ˜Ô+!çÒ©’JQ.&E§'’’È\ƒf®cP¥ŸZä¢kæ:tµÅŠT€Ç
pÏE虞Iß|{÷8A·|ÁÑéÞ`«H	†FFQ‘¼3$QR%ÿP•2©BwA?YˆR(X~;wªÒ
(’Lbã§Ç¸*äEÑ)ï”힋Ġ;žTÔ/
o¼W°wJ=U€Ç
œ•="Wë´%}ÈÕiäºuÚ*àÌ… íû»\•|M73ÙŠ|€æT€¼R”¹¡xÀ òöšy¯|Ô®'ÔI9éøÍ+EtZ(ãAÒ–Ô-€ÿ‡ç°Ú;Ýíæ°È\wzÜ)D»Ý+xEÇ>½sœè¡‚“Aå®{®{çE
8cXîò×¹®
^F_ß.o¿¿éÔ¹t õ£ØÈúk;Â:÷?öt@<‹;õ¤Lj,-RPÏU:]Æ;¤°ë4l§óÊÔ>éA]jAõqíô°k$	Ê¥Ó¹CæhÛ¯NI+û²µÛš{ƒ#Íúæ°Û¯¼	E¸hÏ¥A÷×¹²‚bô%*@RÿCw4¢SŠ¿*ð?$}P˜Í
nöÜVìäÇ>Øo¾ÍeÇy"ˆÂ–`xêªî¶;¾H‘¢,"Ä
!±ƒ÷Î9íK2 a&±¿8U_ÛÕû×T@ê	yà„- ê4…Ê÷ôp‹5Wï(Z9BhZôi‰¬y/FüàÈZ±ÖЦ~-bØÿo4Uæ@cQ?Ð(©è¨ÌÇ“µîQµÂl'jYhZv”2†irÛÑt¡—‚Ò¬ÞÑx¶¼xþFÁê§‚žW:òJG^@¥À)ˆOëo|Æeˆ0µWÏ4h³1ƒ_V¿†Æ¶éfKÈŠÝv4ÃÝëâ>Ò(4nɉ6¡yG„ð^ˆP^ˆ”KÊD
è(”Y
ež6¶d÷©æÑWû=Óôòu
&9ÖQ^>»òj@ñ•–(òr
¼ñ!»õI)P°DV,O+;ã…
R|¯€¬#Äw²uÛÑÑâR¾*ˆÞ¸ârתtÛ4¸¥=S/Þx(9®{Ì¥Ïú
Õ`WOÔðyEX(·7¢FTá[	¡E¨
pi@M(#j¡êáƒ(6ZptŸrãö|Ë'ªðˆ@=	-ˆ–‰¦Žæ3¯5ðVhÏ‹hNR ¼¾S`'êDŸR¨ ‰eª‹]
æ¿G’‚Q~Q`‡‚qW2χ‚Ð*?ÿÖÒß›ßqî×ÈFK€¾w¡Sì÷êÄ8Fë3‚¨‰¨ºÓè¨Õ-“kÙÉ—B4;QßQªÛßBƒÓopúÉÔº€–׎ÆT2ý’»³*ŒØ±¥7ÚLè2UH¹ÁÊÓëPæÅ¥¦èìD÷¼òÚ˜”Ðl§MXèW¥+è¶Ü¿Wа®tÞ(¯7/*˜•WÀ–òÒÏïh•_ÌnÈúÍë9ƒHº+„ïÏë쩨6.Øæ,­Bs¾ÅvwgÏ¢  hÊÆ~x!P϶[ òÖŽÖ’4°TTÙÆ®VóîeY&º:ToT#…´!XÊyD HOÁ`¹xë8k¹SyÁ
P:…ôP^¥‚íß
fKD•×Ìœ¹bÓ‡‚1×wâB˶nÛ›‚ü¡`ýTw@ÿú	­ÒúH°ßW¶$’á±Ñ~§jˆ–ᯉ(~©ß_#ˆÚæêDh‰îw

hbØü÷Xž)„:P@B“ÆÅBsžØy¼ÝJI^ïpMÔ;Ê7BhÕåÔ–º£*½
è4m-¨‚µræµ–ôPÀÑÕ³+û¡ßOË¡ ]
ìT[Ì-·œ¦»lAAì
ž_üð;Zå×–T®Ý,Xà–ÀþÜ¿‹vEg4[ê>kêD½d ¶·ßr©@
¨u”¬@UM‘PyÄ«]¨Ÿè¬{ôÅ€&ßQ¯¼ÐJå…ú˜å4 7›vY±=^PƈÐÚ²¯‘„ÖÂ0„–J4]
B
Ì»‚,þ¿
t*}U0襀ž?Ä© I•w½~Y32Û˜é%4ÃåYjOþA0ÁJ¦™1Ñq´ 5îñÂq¹®¢–µÍ‰f¡ÖbòLÔXxn‰¨ï(1Ѿº®fÙÑ~JGJ¥žåeμÒP‹ÐÌ++/FßèCÁ,Ôj¥­ïˆø–gj0ºÍňšÐÙYi͉f¡
%nb	6Ä¡€LóÞ4mŒ´Qdž?ÑýÉ<ìÚWÜ;ÊÓNšÀlšbN6‡õ¼.t`µ)hþŸ
L
€Úó¨€VØ"¶}¯`´ŽÚ¥ _ñ
è•—3/‹õô+w~¤VçÒuoeŒ‹RWwÈxRœèÂ%(¢fãâØ^h¯Œì 5)ášÜÝò@ÔGç·j°â>«Î8QD/h¶@Q„jMœGePIhñ"Ô,„yÂ{µ6¥ìÁEDÓÝKìy¥ÔìNt1o„ºwmW°…y…uƒŽJ{&4åÝ–
Z(XõTPƒyÌ»‚Õ¥`T^Y¶ÌŸP°,T°T¼~ÿO´®W/eݨ4K:Þ#ÆDÃz\=Ü—%RˆIh¸Ð¸?
O"Ž'€>Us;Zv´µ‚MJ4€²–øÜQ'êý¦‰®¢Ó”.ŽßQ
1DC¨6,è%€.b™×À¾‹9}–éácÚ:ÊëPp¢‡5“‚‚	õ|*0¡%·®àB™„òÚ€f ö¦`=óú´…'Z1‹üÁ“MÜR<í#A­zLnMÁA€Æ9wž­S
¢FÔ€jŒ7õ÷™heg™kª"éìGcGÛŽÞ‰–	hD2†P‹PDÕÑ-h˜·˜âé<ª(ãпâ/QM_ˆ¾ˆÎý•Žbç:¿*‹¤ò
Ÿ=v(`rez;ª=¤o=ÌÖê$TPAûPóŽÆ¥À~`«üÆbX&=òÁò¢SX½Ö¹§pø9{jüz¢®1e¡¨
pÁÞâ긞ý†"ÍS8¹zŽ>#$H9ÑÔT‹·1ÛÚˆÖjÏr×ÚW#ETÄä7´$–·—òŠÅº×¢1Ñv˹çÔÚ›—‚ˆñMAª½RðˆKÁòoÉfŸ¾*ð®à-¯ò©`Ðó`™<ÏóýªÎ;OËÈDø_™5ýLCG¡^ˆRsä[2’:rœZïr/ôeXpñt¢‘Äu€îÓ:{ ·ÑíÖ>Ñ@çpDp¢Å¬9õ^Rlõ#/×:Úó‚Sî’‚øP`š
cÍÉ/B»‚ùDOgW`iWà³_
–ª¼¾W`Pð;{û@úÍßG;naᯡöólºJ™Yîæ¯H¢‹…gu-Ü1…Ð Š˜¨,:šp4ìö†pñžƒT]ÐÑ$”“uÐêò¦\*ÑRvtê]õ},+И²jš‡ÍB3'2Ê‹¨õ±pð³>¥¤D0¯f&ôSA¸ÙfÓ5mÝÑô®À¥+/-}*À¶]Á|*¸½m¼Vt‡°li_­)Që¨I›ò޾PÙó£/ùr ú¦Aô)ÿ;‚Ye_õÕÉŸ;
Êðƒ­RX3—"8ß5ÃêxÉlq/j©¡ñ]f5 ¨à•Uµd@µ¡h¢£¦‰[“xÙhzå¼w³ø”@kù@µH kŒiUT+Úû*%V¤UÎ5ÅÀdgnW“})-‚3"È=»E 5‚‘VDp\Ñäh»uš9T#ÀžŽ­EPFÉÇ`¾:)jÏ2¥2kœQÒ¤GÞ-b i†ªâh|už_bŽâѦ¼J…¨¢ŠIŽ‚ÿo(J¢SZºP\cO#*+n:@7-}o±Õ£®Ê'­¿–I
h&Z€
oM±‘˜}­^³(ú²âè:ú
tâ· œåæM
&¸þ_x+ÐÅ&ôeåŠiôUGÊ<É¢/ ¯´Íò¨d #-[#8ŸØý=)¯È²ð$PŽ™'ô•šº)oþ¥¾ÛÑ'P/éU7ìCM³!š7G
“ž9PÓ¢@U_ºšäu¨bÓ$b6Ïûæh	ô]곉y¤½¢3êV{:jæ>ôTš×4Ð…è,¨)Qè™'u”4z83k"úD›i­Û(æÇ¤kEwjøZŠxö™Š5µDÔc_
-*w49о€Žö@³äÁaŒ@ïÌi«}}‰@ó:Ðöõ鋎ìøóÓbF³F80œÁܼI8REÕQu4„
QstsÔK²ÂÛÔÁÙ™•Ðe­K‹¸çM_å"Ò!Ãíq„1„¨˜5PQShŠbó#tû“ÆGwö¡8t4Ôº1¤ˆ|C¶œy/½G@cˆ£"˜.hEM-"ðwkûúˆà`Z|:F6ÑÒºÀs mƳ©CÒIT¬¡Õ1Œ!Öué®Ëл.cº æè6ÐÅÑù&i¨–náþ7[<¾.)jFt»¢­/ K3†U+á!)2åÒ"¥ŒàŒbòUt~ÿ8‚÷Õ¢#«èGR^Dn9¬a4kxEŪ„CÕöC–Å!+Dß&¶ÐTsÊz7†ìÀfü-
SŸÌS ÓÍ2PZ€R.B
ȪË@ÃÒŽêg*H€–×½¯@uÈER“‹H±–…¨ŠØ÷†1„Ø=‚7# jÌÅ‹d[~oÆõ®Ë(U—a‹¿Ì±¦Œü¤¢%Ðè»é2Ö_€†.8¢b¿¢?{
cˆ£é>µÂb
Ý 
¨¤‹Yãp4[áÜ)4 #þ.5ýÔe¤,§4cÈ<ãçfYº.(§9D©Ëúº-ÿ6kÄ'µÔÔhq´Í*ëªJcˆJûŠw2¢"0† $C¶‹|3†X7†,Ñ'A‰}U”¼~‹€è0†D/}™iLj_D‡1äÁúA5†`ÅeRÝïÏÁ?21ZzPJŠÇ…Š| u¿Þ!2Œ!-š^éa¿R2Pâîr5÷¥¡ÚQ!Æ­)© ¡…ƒÆ`KT°×b+*U.¢Õò½/éÒôU"‚ô£Ê&Šº	…im4†:u”›“Ú‹HGÙ×ÝÂldãó%ëŬÁ;+‡YcªŒÃÑ0†Ñ)¥».Ctc#C—¡jÚuw¹ˆ÷7u4?Ú‡èz1†ˆ~3†üv¢û7cˆØ³õ%£¯Šîµ/ž.×¶ŠÚG0õ#z@G“ÓÜãòûÛR¦ãàŽ°aQÿWWû6~‹ôé5µ.I@¡Ëèè$4†GWù¢ËàΈbó>tÕ¬±Çeƒj•Z,ÐC›Y#iCïÆ¢Â²³GDt#:1“GÒ“@þ4†¼$"hö~‰Ž¾Á‚¾€š£{‰RjÕ¨¡£‘-\@ƒ—ÄoÆæ÷
$u¹ˆWpA.£cõ
ªgY¥)@{òY{÷"a	¦Ë¨šÈY¥iás°C2Œ!›ÈC¥wtºŒS.’úëŒáoÍñpcî?J!‹\„ÅåwCkž}¢’´£¶³3t¼ù(ô†>Um¼7*xŠØýtäª>³]èw©m<Ñ5W0tVð·rŸþqðÆdèŸf)þÎªËø;k±ž ËÐw]FèaŠU•õDéD©¡_Cb(©úèxCØPª¸G;!,!2P°ŽÒi1
ˆ¯½‹í>MÍy¢¬›¡#×Ñsš€nx•¦8j¹Æ¯`·\Ÿ¦Ãä"6Uµ¶tm˪¯zWäbäò
¶¦
Ãòã/:ÍYºéÖ>Ø1ÏàÙ¨«­ÔQhÚ!@mBCr¢±!µ‡·«.#áN<‡1$Õ¯‡ß€ýz $ Jv?eAu ÜÐ!ÁM׆âîmX* Ké¬@zU¦p­ÀÐÏ
xT€™ܯHÒÙVúíûf„ƒQ]tb“iQ ]b_æo¨eGõjÖ ŽnЀ(C—qAË#ÀMU
Í.I_ùˆÏ!á€m訊ydº‡[Ê7›)(KHp
¹xS1—8Œ!âÆ©cHô
žÿXdui
r…Q­ˆC‹
ÜòµV¶±ý#–aÖÀ~zê2èbIª7k´i}C”‚
´`q¿”£4QŸýຌ<Œ!©ýgß;Í|(iƒB¶£8¡þÞÐÛ­šÀA
´ªÆ™(?“44½äÌõ²\d¹€¹ÈÁ§ä].¢^²C€F«(*ˆ³ñ
F.û+tt­¨WPÜÒ¾©-P’ÆÞ ËØÝâ:a?’½\—a3Tô”‹°ª£!oÄÑu].Bªn)«Y#é0†|=M—A)ÑSÛ§t\>,¢BŽ&C³‰Í¬ÜªÕ­Žòо¬_C)
¹ˆ
	(ŒÔse—‹hBzVÀkÓràXó}ÅSš²7(
B±¶f¡¡Ux¼PPñ
”DcH]Ìœ\—a¥k—p`€e(çûÅRR×eD©Œ!ȹÈÁ§.£6(¹.#^å"éáÆäÆûzC"	5ôILïf
½+fvjCÈE®Æs(Ü‘+
cHª
=š.(* Cgù‘è¬ '¹jžñYÁí–rå3WúH0†Œ
î¿ÊiY*xy®´C\—!ŠsHì…·¡¡L’‡.ã5u†*Ðp5†¼]uÛ˜*wcÈaº¡äK(J@%Mcˆ±¸Y•¼³£À€ò0†˜Ë¨’¡/eÏEÈ•´Ú@1}uT	Ъ’Ò*ÜP]*¸#—¤<å"³­ðéWÙ®èG–KíH¯À>ùîÏŸÚR‰Ó¢1{¶DuóŠé2ì¾\ªÝ¬AÝñ†h„\Ä!‡}ÿø³Fp]†¡]—?Œ!t•‹XC–»©
TO”tÈE
$-ÜPºÈE^	¨çÚ].‚tʆrVäêGƒ¥3A1º§¦mÆ)
Œ\öí"iT`(Œ!×
Š£¸ðah4Tb9†1ä5* ÏÕ¨ï6Ü·¿Ý {À5”nÖ(73ײ	…p& Wcˆ¡Xö7_«n´:t-§.CuÈEìé—Ýòè¨fž¨}ÀÜ
þŠÃb蔋T’džõ4>	èÃQ<4™SE)È•3‹Qõ¡'
†vå×
"r
žv0±9KŠ
ì§œÆô.)ȵŸ˜^4”ÚøÍ+xyKðOCdê2l,h÷¦5m›ˆ¬‚ÛÐedÛ˜ÊÞä"4Q+dCð˜“
;ª÷4	4 «\Äu¨D¹ç
hè(ŸÆù*Tw%ñ§êºWŒDÝrŒË @{®íÉ6ˆºèÍQÉã4†¼U.”.Mùù?U€ÅÒPZü*žKeõ«T`(ž¦ø}Ï‚+:OùPÂ̬‘Ü!käðô\Ù¦1¤&‚1ÄÑPé)%Väšrê(‰oq3Жë‰Í_-W’bG.m=ÝâPµMÉå"–ÃÛriŠU0ü*0†ü¦1f
[[w­)ßͬ!OòÇÕícCŠë2°Pzب;àDm œ)m˜ÑÂlÅ®v‰4FGYO³†õ—(_Ò¤Ét¶)švCÅþN†c7Tž].âÆ9³W”V
i¹Û<Á²½¡ÑÑÊ:+ІÒ@=—ŠÌ
H©¡&A®î†æK‚m[­‚R§	eTðjè§1t‡1¤ß!—Ã+Œ!IjT….ã_0òbaCT:jÈ+ÉW:§ºê2€âÃÐiᕨ†J—‹@Ë®™ ëzCÝí!wMÚgÖ(jáB¶\„©z®W¢
$¯¬¤¡áüºTе‚øVÁ£ç*dW¤JBŸÆ’¬­mc,•ßã‡1DcH7k@"Ìú¥Ó¬±u”ŒºC´Øe¶†ª¡ì(¢¦­²ü¾óÃ5 rOvyÑÐXGTÕgt¹Hœ˜r•ö‰ô«Š~@l(EGw{ÆÊ÷p1†Ø¡ç‰#Ð8rKù¨àÆ=Wüfúw”³‚(VAšÈYÁm© ¡DE`y¸1äqL]†7kÄ¡ËØ5S_ksšèf)pJÑeìY:úÊŽŠ¥¨CZ)S—Q0éhèwgqÓ¼«O4qc»1DÜ‚ª
•£È¨¡â¨m@Õ„b2M(ž‹ñ¸Û>4 eVF(7Z®Ó’«ç’­@z‘:Œ!¥¡«4%«£Ã¯2!«.o)ÛìÞèNÐel›T¡2Œ!D4Q×eÜø.S—á/ŠÞ¯º&rcHÌf}î(F
§.ƒ©£	hÊ7ì¨ÆTÍ	ÛP›<!r‹Ž*ÙxÆìh¡¿5†ðMî12B®‰ö\¼Vpô
ÂG@§1$ŸÔ¿« r8+ˆ¼¶å”ßa±E®¶E~7†<ïÙµƒW]FŠeC67†ˆ&7†ÍEò›1Dž˜Š¡
T€ÂrAÕЋYÖe5´Æ ;+Æ ô4†j¹ ›RCsCU¬‚WÚb™ø°,Ô!Mù¬@Hf®Ð8 ×
rh覣‚ê?aæz\Œ!û»1$ÙJÕ¥*UI]ØQ¿eIÚ%ê"‘ì¨â•8B@CJW]†^uÓ2Q¦4Œ!JIÿÑBêÆM
€=Ü-ÓÖ…†ê¨Så
è¥ñ
·+ ¶Óíµ²
êjäú¬ÀsÑwšezO꺌:!ѦSl®ú«t¨Ø>€ª šêj±M>Ô_È6´T Ýr
‘Wœ
e"[‚åj)7找›5b x5†°ë¤¡‹\äj©16tC«•bè0†\+¸\Ê#6’ÅbèЀh¢jcIKñb9ÑÍsÙF4P«à»ß~°ßÙmhIQ`qcYZ+žmúšÜ¬±WKkIm9tµju4V˜±©ËE
tp0ØÖ?ï4PÞ¥jJ»ë2üd¨*Pô§}p,~Çv1†TG	¨& õôÐ~CKi¢	#@¡aT`;šDCQÁFµ¡AÔÚR …¬-5´²ŸC‹C|ám!TÀØr¹ñã"©g.ñ
âiɳ†¼™5¦„§ÃÚ¼5Ä-Œ*z‹ÔѼC‹€ý<žÑP°ÍX ¸•
]Œ!âÆÆíÓ²u;ré5—©.•.¨ú=}«úv	ÆQAxwVðaÙì‹aQ±ýè5×1+Ðn	‹.üÓ¬1!Ddúp rÏ@sCu¢¬©žºŒPc¡nyÊvê2vñ™±üoÆÇ]6Ü%w4ëD‡1„VcHRÚŠ«DVcHºCãDÏ\ºJS-£c.¶wò
‚Ê”¦Ì¶‹¬©C.t›Æ‡/ÆéÆÞVpcˆDCºYC»¤CêÐeh×ep}s1`Lìh6Ô;ÐnQøÄFg6Òöµ±&
­„"ÄÍcÈkãÏ#Ocȣȷ!·âè0†„d¥l†¦zÑ€$%7¡È™‹¼‚tVÀ¡WPžШÀ!ª´¶E=s=9eËtT`¹´6v[+H÷Í!C—A–4ÝñÀ–¶Éñ«Æ‰gÓrÿWcÈC€Ú·'
mÀU\hßÞ]b¨°K¶z5Ð9±­É¤wéÆô‰&ºCÆ|C,J5ôb9+x.TB‚
¥¥‚ÇY!W’ž«Ì
¦1di+Ár©àb©®Ë8›ï*Ñ…ÕöLŇU‘t¨¤a)S—ah>QhÛ¹£)ÒiÑÀÉQÃôDi5†àˆ*¬†6öD7G!(̰Ä9*-×D“¨çêÆG‘k³
2rÝ—
|œ
¤)@w^!³ìyöÓ’Ö
­^re]¥)ÉÜßÃÒ_S0]ÆóbÙÚ,.Æ,ÔÑô•²Í¡Ëhq÷½5t¨~¡µôXŒ!7°n)LÆÊÄ
JìhDuvé1]5 ù5!™ý0†´ª_«1$'3†ðiy*½Ëu¢[ÑÏ
€¢‚×5*ÐY[l(Ÿä¥ „âÏÇY[¿âM	˜5ì‘ùœ©šJ@mHý³Æ§.CµmÒ!™Ycê2
£C±¯mÚQý0†DV›}MTjî¢`ƒ­§1„#66~_ÉëÝP«Ç!»òT£¡ÒÐÃ5 2ÑL«1$"*`Aý,ðï+†RB†²¡‹1䣥ǧ1¹X«W€ê}wcˆÆÓŸâ¨$~Y‰¤ÅBô¡ËaÖ5ô4†È7PÞ8.º„oHŒ­LÝ¥fÖ¯oC*P—”úšÆ>ÕD´ l¨ùî–ËÐÓbhè(Ù9l°/™Ð¹®¼*Q襂™ëøFϬ~ ~	S®¸üÜÞŒ!"È™ô<¯Ö4Í…4δ·áÚ·P°”L—g×ïe ’Rð;}ø¤›5†1¤ë(¸&rT€
Vv j¨Ï¬ª¡žhÊ‘k[QMúVÁ“£.¼çª].²
cHpô¡ÁPþ¬@Ô+˜Æ‰Š£½{ÆåÇ__þ☿
àÆ"C—‘4ÉŬa¨;0å!‘r]†ËEìêùBC·a)tè2ìøO
È6Œ!®1tZܬ1ÐÝOŠ)6îæ.	>;¸†\â(”I7BšwcH¯à’‹QApcH@. ÷!MÙÖ
€ö\<Å况‚àl—
tVðÝþäÑ9äìï‚y)Vï©ËÕi™h±Uz¢V
PÜŠ!z³µS oŪǛ¿3“à9SHÆÈe8:‹!»Û‘ŽêtC€VDZUÊ&JØÛvT¸D¶ŠG1(WæÒ2P6ì¸2@#‚‚‘œs•K1ÄÑ^Bé(]QÞ§‚ågåM©ßl	P,Öm‰+*ź‚ÊÁŠb®-õbÈ/ø:®_CFÕWù=ìZa¶Èe¨dZ".bñÐéÕsKÅÓBlKëe
LŒÿ*!C.(õb3)Q‰²?lQ=Ð%â"QÖ œ¨(Ê&<â"èÃV™hsTøÁ‰¹`«´2Š!—¹¸	PÊ
Ø
Ö·h
wK&²›‚v-†`±‹BA

rŸ¶¦‚YÁ÷N–ÇY1¹—5ðL§ÚËüàÄÖsø..Èx<îíBt-k¬¨D.ãyQÓš¾1ä2Ü`e÷bHqtÓtÏŒü¾(1C–Y!d@–dsñ÷¹äRa‹¹ö‹‚åM€-\”†uUl(ØBÁXìÃRÍT|±Ÿ¤«‚
ì;þB¶§—‘í¸„Q¡‘Ëxm!¥70-«šÿ”½ÅE.¹Œ’kä2r¾å2€ì@©ç2€î¤{d@È_ºŽ6Ì}x +5V¨8Êõ%£¨¹?ß*+.Žöbȉ {ÃVMÙ¤+(Š!\".
b®©O鵯Ò˜ˆMÅL©Å³ò,Ldã $Aí€áà‘ñ‘ås1DÜï,WÊ¡@Þˆn_¦~½+؆‚„¹èMùË‹![ÅC!PÙâÏoáß3 ໽i9V{+†¬¿£œšâ»{1ÄÑÔÑýñx˜ŠLÔ/¿Òk.c=3 .P+ºJ»£´ŒbÈšÖ@ý
¾^ažCpáæDŠDk
”€Ž¹xÌõõ\¡ .ëïm*J@é ‡-̵Pz+†8P˜
T¥GSdΕþñbˆ[1îe
û¹R´‡-ö3¢t°mõsäìïþõ»>ø‚rGy ÍÖsŽJ騭ìSvtUÚ™}õÙåJt 
‹E1d/ì77·,ÚÑZ'ZQ‚1—£(†¤3.RöY¡M[ e*ˆSu4lU³‹=Ð$]A|S œ	¨b®P0æ:m=ÃgûE_–“/‰™GKƒpIz´µq:˘GYƒŠåPèâ/U~]ãB£bµ":Š!Z°Õv tCàϪ& kC䌋¨Ðr-†-Ø-9v
hÌÅ'Ê'Ê2â"@]AÁ#Ðý@-]ÁãTP.
F1$lݤ:®Ø-§­‰Ò@å¦ÀP1{}R¼8‘Ë(ŸItæ2¸ ¬Q¦ÌÔ/?Qa³@ÉËèq,³^3–žË¨)²^c¯h ”ûþ@•Ùðû]{YƒÉQÊ(9Êq±kG¿’á€]™ ¬Fú:Ð*‹b.ÿüÄì
ÒM²{ú®€ÙÈ]AÑo
ž§‚"-Ø©€¿+ȹ¦Æ¢UÒßdzòÑ¥¬ñD.Õálv/kˆ£„}•ú
íø{;úòûék½3rÆ«'<ôX¡£–"Xö@ÅÑk1D¬£*´g£(kË,†$Ä…R/†hÜýÖQZPCôV/¡,=.òå¹í˜ë“‚×%
¤£F#š”W<Ú­¯"m*øZ
–®`öU®Å”þúuCH¢²L6s=dû¥=—A74‰£2P>ËMF.c¢\8Ó(†X‚À>©t”úžðdG1$?2n[4Š!JtE7Lúåë³(†8J´jè^¶tεcÎ(†è\ß‹!(ÐSAÃb§‚91ÌbÈ›‚ýªÀ\Á3¶zQ wËŸ^ABþ–ËÀÏÊ£beæ2å‰âÔYÏedÿwk#—q¢¯Äyä2RGÕQAJïÅlÅ4Š!+íF©ùc¢²[!G«ÿ5èÅ}C[
×âèâs%ml½bMÉîÅÔìxÓK1ÄF\de~S`® 
‰ýOõMèT[9»‚
´q £²>uä2>Z
Är3Cˆ¢ËàæM».—²¯I|Oª³¬Áù	Tµ”®q¾ ²¨õ¸HT‚”puúY¡LœÖGlkÖÅ@G1䅹ȰʚF1„äÙü	ÛV ÅQÂi23só£â
Š+(SA ̹֟ ;ùï’G1„pT¼úN[$5G(#—ATÌõ‹\†l·D‹™Òƒe>®Q!d@šR‰[¢Q ’YßË<Ê&_ÿ3v7«‘QÀ|ˆóQu;׺·¡1ÜEo‚¨ ¢Žq“E°ÛÙ8D%Ùa"8ÉRŒ`\ú3;™MÀA˜yA\Z眪®{Ûö£¦'éîù“éúu»;éþe©®–Fy„‹`ÆE¼æˆ]Š6”rEñbÊm‹!DɃ̋,š*ˆóbl[{qækâ¢VÐÕ
M‘¶0WÀVAoF!EkS1ÄKþ«‚òsûhp-1d_fÚ(—€æÑ€q݈Ë`æ Q5óÈÄí(htŸ;ùŸ8.bÄBÃE˜$º%†x °‰êò
o…~#† ÷\IJ7„ùH¤Ññ~ÓYÁÏ?9/ã¢LUÀÌ‹QU!ç
8UÐ×
²¾±
¸¯b0Z4£)f“Û»U_
AAGÁy·—Å=Ể;D ©âLÖh,ÊMC°(æ("¹¼A¢žÓŽ\Cæ`¾!b‹Pd
Ò(mÄ2!GbHÔg\¤D»|C\C€Ý€Œ L¼‰!Ÿ|YÆ·µym*h8“y$†xa@ÀEâqÅ©åu¡Å®ÁõV ¢)”+kk#†8"‰!ƲaÕ=TXe
0Y#/—dQ*†8ȲK”=D"^$hQÈbˆz79šeÖÃ&jS´£ ¸HhÀÍ·g<–¨wÉnæe߇›ûáüËç?oÆŸÝcœG楜Y8çJ7Y:Ðë†Ò¶úRAKÔѼe.èÐ
x\¦„DwWÀà|ŠÊªT1¤÷Èc1$eaÙ¯2¦bˆ™”ËÈQ†Øj%N£«„ ¯øpq@’yf®s&kX‘ä‰!b„Q,ˆ®>Pä=ÅE`„‹gàl–ë³(±Ì+z 
."Ë8›9ŠŸ|ðüÓÑøá›ÅÕÅÕE:˜]\œ§OWé³]f©±2 ù{ÔŽÚÂM[ž4ä©/¾Š¡)¨muRI´ebHÏ!†&pMÖ`tÈYÖcàŽ"Ñ
&4.Ua•5¨pQ7Ž‚G£p$Ê%—ËÞÆ2äBœÇøÒKésŸ¢C#¸1dÈb+.ÒÙï§C^
½s¼%†@ШÎË12Á"Eg0\£ÏôqCš‹¶†‹—Q£!GQŒÊeÈÜá22°?ÿú‹o7ö¤°È=ÝC{]#;ÕDº"†ìi´­ÑUY01j64
@P³Oèãù™î•:~Ü=žyqŒ¦ˆ!!D”¤, TЖ¶8‹!Ž]C°ˆ!u^,óŠÈÒÖ@YiÉcc\F—¹Œ~†¬àËsï‹A-!CÌì””W"yæS4&†8ôEÖC‚ÒÏÝÌ~$2ÿâðøŸÇ£90ñDY4¡ˆ!$.+¡W²Ø¨©¶ˆ!#ăÍKá ,†0îüþYÚ+ÿc|úüƒ×d­‹‚¹¶
p\jM¡Zµ&†”
@ÅŸÅ€†¦ÐDiiºj`TYcVdÆéàV
Öhe@ÚÙË™Ë ‰‚Ç.âPg¥Q1øS4-ÊáA+[ãþ£¹‰!3¥˜I¼ìE@lMX`ÃEhVÄJQÝ^¢{d7ÛÌ€Ä@2¯øþÙï'oÞ»÷æ›rº'w£ßŸœÏǤÕW±yµ’bUÐ!X´â"¥ר-Ö¶<šÒ9Cvs½q8C/¦]íVŒ£Œ-IT¸,\`•5ÈÃDÁ™_„¾59ºŸª?XÝ|ûÊú•»»õúq³zöîúúôX÷ŠÞ¯D?‡±¢{¤â">‚‡"†´rcÁÄ'7G5±.E£!E]Š¢Í+ÁŽîmŸ^¼x¸}åÑíÙ¹¬et¹¶
T7öVA;CvT€1¤F‘&bH¶"R@Ä·À„˜°ü.£3.8êksÛP¹îAÁC
—!WQäEˆ¾k˜%ZÄ&”ÒÝ?¼¸:ýõn}}¾Zí§OLJÏÞX_?==,÷+À}C |U$ÅE†‘‚2.b76„œÌ±D—EAÉádUŽìãÑç/.íütUZsHÌÄ!.¾JAS j[µ‚mxn¸Š!Z¶Õú¸™—Yä)E¡ÍbHä‰20¨!mW.£3.£_—­qÑlŽº/7bÆXÄ|C,J>~-G°ÕÓo×/žþö`ýÊ/ç×wëÇ××ïݬì~eabÈXÖ˜op‘°—ÙpCjt"†ÔyMÄ—¢ñBVåh2~þðòÅçGÓ‘Vå¢0 Ì¨á½%!ê¼Øé;lcCâÐ[´V`b[‘ÈãMqUºþjCH_µEe
Â,kPú
‘"k˜²
ä$Zl¨bU.ƒ²âˆ-
º*O?Z_Ë#¯ã´g¾}°Öñѳ¼*2C3Cìméa¿£.‹!ÎÞj{0$GR”SÔe1„ƒF=¤U9ɽŸØÇ{—/>|qùæI¹Ê®N«x3¯"†ô&†XdÐDBÑÏøŠ‹¹‚*†ÔèÌböUÒ#ã*†,€ö‚SÃésèFŸ«N¹õ™h	Ðk¶Ä¡FY}&“+ú
A¢¶WO¿ZušöÌñáõúÃýëõ݃¿çÇ`eÌ€HµóYÐÄ61¤·ûаí9C¶q¶h:#Ñxñäö仓ñxxùùwߥÍ2¹RWe©NU*†x-ÍËmW;*pŠ‹ÄÍËQæ«€Š!
¹wª8sLLQ{ׇíKT1¤à":c@ˆGM&d¶&pŠöÄK[•ãëõ»7²<×ëןþ–vγ§ÇùÞ^êKÑ©bÒ+tòŸªB)#M‡]bˆÍ‹&bÈ`Q
é1ØÇãú?þéòò§OäãôúïÏ®*#—RMBYXa\AŸ+P÷+L+¨mé¼bÓo|1dÑsf­äÙI60˜ª¬a¸ÂÞ_Œ[ÈaÇGîܹzóî³³,Z,9ä”crNrjåPŸ3å†rHnœåʽ
%’rãÂBŠKJ¹”¸ñüŸgÞygñZvwü¾Ù}þÏÎ7³³3¿U)(Ñeà<êþ"ž5±*;‹.# Vº2­ìÊÅ]Óh¿i“lŸÌm£‹‚K³F—å"ü:+Œ!º1ÄäÎÿjc=Z¯«{zÏÕ{[(ôrÀ-1˜èu…Þ¯øhö•FüsQ=1¡`wX5‚&§%z“Rš’2
ÅFa‰JcÎÐÇéðÝ*m#è2ðykÍ‚Ôhcˆ©Cڄʹ.¶@ƒ.cºÂÍ8® =ï^¤m0l‚IWºÎM¯CX"¡‡bD"OÖaÆÁ⿹4µÔ×U¢
t¥WD‰¾kßš{Ô•ŽÔ…]]©ê¤…þS
©«Aê!„* øÑ€Ö¥)ucˆaiÊ,+ª‘#s­#zÂbÖ02†ÄIâ!r†5HÌ#r|ÅPškT’š.h“=FãX—1NÖöñë•Mg6/¹{qfeY9•Oo¿¸³]5úŒ!5;Â46:©>‘‹caYvA\PÔÕÆS!]™?Ë–ù—Ž?>8€AºÐõ¥ù4èÿч”—‹„:jDˆ Ï¢å%U"p•¤.IKi
Kúæxcˆ5h“XžÄ2b^ß¶Ý¥BuiÖ 4o–¨è2tcnÃÖ!f&MÚ‰¼.#Ý\^ԻŖñÊÍO¨%o/ùÂE,+±°ðzeFëù³¥6cˆ—‹`Þ1ÔŒ!‰¡®Ðd[¢]µ*-$"ÞâdY™ÏãÒÀÀà ýà1Hƒ®ÐîŠn…"ëÓÊ´Ž$‚˜"cEœŠ$#´8hºÉ
cˆó¨+Ó’­™£Æ¤íÂb¼„Ca6Ö*êlSÔU]hèjZÖü‹Yƒ
K}f€–ƶͿÁVoº;nìæïîÞ}´róí7ëi;ùÉ>^V6MÝõöÅ·Ý_Vu½1D£ªŽ¬ŠŸ©¸iy¥Á(ŠËª¬•ÿ*ëÔCp¨ˆtEF¯GyØ;Ö£q·/õŽÍ¯vÅ×Õäº]"oBɹ.m¼1¤Ž*
̨¨OËycˆÔè~cH¿YÃCìŒ!:Cò¿C¥1ÄØ¨U…Æ®të“Û/\Xx{ó¬‹xO¹ùÉí%w7­ßµëÔä£GŸ´b鈄£bÉJcHV5†àQ(*~:MB˺2©K$¨ËñÚÞ'¿fÍÃÁÞšbô®YSíJ‹ˆ £‹º:ucˆ‰ú#‘{”ã#Hc^Îv€öC:Ä.ÆGY©&È‘IËè;0\]—am{Í?P*“Ѩ-Ý"QÎáqE(Œš6w…Ú²ëÍ™Í<ÎÐ/²õS§Ý¾}{Ñ£õo_~X·aÌÑ[q†Lƒ1ÄøÖ?ÙH‰\$–=É9Àß*«>PoŠþ¾C]Aökèrlpà’ïî¡-kBWÆÕ"p>-¼ÖøU$­J@ó†ëp†#È$‚˜#ºBZNPÌ–öÃMÁMa퓜Ê,º\Q(í†Cl‚CŽ*¨”Ï„®›5lÜÒ:è2¬S¥„Q-ën˦³Nœx‚Ý’›h›ìí¾·§^L¾<䯆uk‡Ÿr|¶oL«š1ÄõC‚\ĘR’Z•5µ1&mâ©Å‚t…•‡Üº1–î
­Ä3ÔÕJ¨`Û,"Àx-I«	õcHHËiÌU…´†cˆé7†¤….Ãx
HªPz@#
ÉD@i¶Œf•	5A—‘hÔ1]ᶬ¿{÷â»c7/§Ý_ô¹ð‹û'®½}ãòèûoÍSZ¤Ý¥„&@xÂÏÀIå8Û@Œ!¡MFs?i
ÔéR£.=.•®†ß_hÎ¥Ácr]¡÷öUJ%-“hŽV]•‹--@[þAªUMª"X6†¤¨6–DœÛ0«fĪf]Ìo*¢™Wt0kD@3×¶–QoQ¼’rÆ£ŽÍ¼Ç…öäûOˆiù½i99yÿÄ!k×Þu`ÒÚQßN*6†èLž~V7†$Tô7h”i”Æ[C2 "ïjq]@6†ÍЕž¬ê׬ ¦àÖübЄckz˜BÿI]éôE *dÞ¢"ŸV©7‰ã¼Œ +!ˆ ©ÜCUT¤)„Ú|ìdcHæQ%¨7†`²™ÂºŒŽ‘SßRè2J³ÓäU5Xeå¸jL T—hn
4ÍLñæ‹%£-¬ÛNÞÿm<[6iÒ˜‰ö¿nü˜ç9ÿ%[QMY½×€Xì 7„xT”YQlÅn2TL(1>_¹´wÅ¿Ç1ÚgÜé3†¤Fê²TZ­G i™
1êl0†0Út¥1„.Z¾æÎN”r¼1Äx]^zŒZ#h0†¤u¹H,f

T\æQ5ïË­[t©Œ³Ç?fÌ£F/¿aø)	L4 ­ 1V[˜×¬mÉb„t€jAc²ÄôºXhzp-+{íýç Ï"³ÿŠ@…<šü=]ESb–úcƒ1DÌ5]†‚Ä
R9sUŒ&ýÆ”©	Õ….#ÃüØèuá¸u Æ j¾×”Õ•Úþòðø
ë&mÛ¶lÿþe£ÏÞÙ(Ì–ÚâžÌ5›ÒÁ\«Æ8h@
ue@‹º%H/¾þ™Æ×ÁCÿÔD@ÑgÊ›P*¨z
 <þ-FáNc”î	šÊ™ï‰7† ¡‘Ò¢Ÿð¸bÖð†H$Âß\‰†ÚRðOQ?
Tíx]FJ¨ÅK].Òá½ÔòJÜ«^n=~Ùámû/_¾¼ÛÇ“Žý@¶b‘§cÇšc£¦f‡œÓÆÚN 1nuå‹_Ÿðôñ÷ãGþ5®-Ué"0>‚5‡RñicHÖ-ý*±Ô%¨j‰_%Sù‚Š1s^—QœœVè2šÖÑ^0†ô¡±ÊÅA”m2šU^4)v?³ƒ¨Óaÿ$£jÆËmã/Þvàèû·½?¥R *V¢iþÕÆäeÅ›

ˆ&´Œ!1P>aÆÙ7_í¼òóÓ§sµA÷ëS¾Ä
&¬"í#¨§•˜Âb|Z6¤"~“«HÒ’D.R5†`"Fp`à{ù±8Y|Е@GàáŠÍS ®X;‰\D‰1ÄJŠ †P\à¬ûE×Ù«L
Da8àXÍßÉd’I  )¶ÄBüjAðDm´Pl;¬ìµ²µ±ðlìl,TÐÊÖ{°ò¼çd2‰?ßîf¿'ÉœwB²;›<Ë÷fCBjJèpýëÃûÏo>~̽òðÇ[ëä"ŽQq{C­ÆÆ2¥¨!EÉé0¿7†,Ǻ¨£[¯_½ù|çÛ÷G^nÛä“'OdúY©«©àÏéfòÏ®C©ÕÒJ*MY#X¥)Œë:‰1„hÁœÆèÞxÓeèØ*/^¾Æé`Ö ’VV4͆¶›.#V¹HAmc:5{c÷Ê݇oÞ¼ùðùùŸOÞ¦pMjÖè¼ t•¦ƒ1$UcˆÛ£j™<ÑŠêÊ":êòío>~zþíÆÅK:±€eh–œ3-‹±Í°,ÙØ|ZN|» „-Ÿñ½À.¿"è
iµN"0+º“¦t3†\J«„Ãõ	Öt0†ðB€_l_ùh©r fo±nÕ€ÌjqDÔêÏ~þøøñ㟿Þ>1"aÔmgú h
ÿ¯6àhY……}´@U.¨8{h6?Í·?¼üòô˽[äWt1	Ú#Á*M‘“ÔE5IëÒ©ëo¿ÊߨF`¥.w@'CfÎ×b}rc¯™„fJƪ˳Fð@¿-PõU]DѬè2€F¹	ShlÕejÖ(¨³†?{ŠÛ“³è­ê
Õ’-6¬1†8ôŽC†1DÇÕRä"Öã?k]<ãt¼õîý—³xfFFÛ"IÎì"PcHYªõ«1$”ºŠ1$ÕШƒ1dR”³‡̘ÿŽ€¸ 3Œ!çàÀÀO”Á¬!t`Ñet«ˆ5†L¦ScHtúõÅÞ6¬'RÌ-6ƒ%̉hœºCŒÚ]¸Ú1~Á¥(#f42:­rcm5ktjAY!z¢bºÒýÍ2ß©Ä*ºY4_ûò.£
£M‰u£) []´lu=DíŽm43:h8 RkVô?A«1äœèRô\˜±UcÁcã@–Ó¹«.CQÚËEzCr·Óe„¾C€Vc†‡\·7†=˜5Ô›–˜5flµ‹CqE=æTc^NŒzϨÊE²ÊEP:Új\$_ÎÒ“õD¥’·GbÑ€ÎÉKœ@óf¡Á‚ÖU¹ÈxŒ "‚ÁcÈ!‚j‰¢²ÓI$'f
ò\D1kàh°T]†©rfnº»ÉE’I!ÙÁ耭§4¥àO^>ÇFjM²þäDÂ1@¯îJ4}‘…aø^vg‰jÁ”ÈEöƃT´¥Qß¡c¯ (Ñ鄺àb5ŽÆå’=aŸÆu¥–RbK­XÃh1†”´B€¸ÄPÓ²ñ ‰*M±NMæ@“¢ŽÒ_ÆÌAv:ê2°'UcÈN—AÔ(ºê2Zì4_t²ÏÐû}F(8<ÐìÂåÞdn:¸Ç‹†ÑÔ¸ŠÆÞÏÙöŒ dNrM0¹Íbuóö›\i¥4¨¥ #½ÎF¬lfôrÀRmžMd6ò¯"[‘a 8c€ZAc–3"jšÖD&–´$‚…[èJ“/Š\ÄéÐb±²V®åWôh¹"ÆnSÕeÈ…ýxÚŠQy_!‹ôƒê2Æd	¨TY‹YÃ2šoÅ%ÉHOÎ!pºü¢ËÓÑf.[6[K£º—Êژg¿¡.sZ¦* ½ÇýYñ1½íZÂà1`øÎ§>ä"RW3j]ׯsMÈ¡ñ†Í-"Íd{tƒÑ4<óÌ@î ·GcóuƬmQ7´ßA'ÉvTÛ…BÉé¸JC.ÍQZšÕZ®¿ŒðT{1Â5x08ÔKƒ'51$C BÀICh‡„,YšµC?Dß»'YrB+ÌY¾þ­w÷?Ÿ¤*z?­½Rä™5'† YÀ°JJДˆ]JR}NBaF,Õ"¸S—Û1§kpà
ÐK8<1„ØüCb\FBÖÈYc)"kd´Œ—^ŒpfmõÍêêê»Õ7°ÀÊ›ÔB5øï´ÐçHoiu¢JI{–VÂ)ÌÈâc1ü™³„«”Þe`êàРQÉVS›Ž0o,ÉîK{€V#Øò¢pO‰+ùØr+M1
KO#¾ŠŽ…YMR¤ôGf"†<$bHÞTˆ¬Aƒ¡ÁȪÙȘ‚˲ÇQ^*JAk Yc¥"È\j™+®Ü–ʼ\.(…(ùJ¬ÂÚ²€uUP’RÈr¥’–buEbIR«½g%K”E¤çæp"Ÿ[ê5êæDP`¿Œ§ÚÊmUà‹â@ÈPCm¥ÆBHÔ(­ˆ¥e§ö¬˜ŠYSnÍ-ИJ%Bbˆv çrç*LhÅWÉ&Rºå¤ðFÒÒó„Bd
ã.Y#Ë€s5í.\=)ÃáJà"Ëk5Ƕ=Y
¸p¸íذpG½A	PFµÉ\Õgg}Ý£:,\[ÚîEÀüäP}ùå«ÇzL1#ø2þ]OÃELL®a	1¤ô¾æpŠÉi[6½\2Þ8¾$w.&Ð2×áéÀv¹÷ÂÒŠ‹ Λ,0ð0šðULrÏ¥–A›––`—‰’{Ò1$“QÄ7œÁ©e°»Ø/èæœBÏOE©¡¤8#\SCO÷*«žÁ¨x£F½¾Ý”.—û*%\pìžÄß;WÚäIŽf	»~œ4ŽÛ6T€Ú¶×ºðZ‡³ŽPßä(/ߦ‰!ŠM}b¼0‹Xk0*2
æ`ɽðcBr!q°¤t0äèp&h7HTc¡ä½…X@”脯¢ö¤11ÄÒQJÄMM”¢–ay“Œ’jÄW1AC4Jâ‹Ò:M•±)”yÜ«©»Ó5õͱ,”.¥p˜‹ -­ÕÀ¿ÆÏ~pús"í *Áæ Â+(«ÐI,?»HÇÕ -á0*;ÍÖg.ÝÀ–¾Â?ø;¾^0ï<áp•(]Uåòd19‹@CôT¿t~*eG…·!$s™N%Ü™´.À“ز²ôÏ'üsU€Dr׿+lµnóÞZÖÈfÈ-`)Э"Y@¹Ê‰[Daêlärib5–ˆ!Fš¢iê	ïE6'†0=W$bˆCJê9Â1¤¨2!Í—‘E—´—‘}[sÚáY¯=nF§õú7êÔëWû-XŸµÃ!”¸—ªll/+£ÎÉÉ×Ýö”›ûáNwzPña–øëAkëz3èÆðõcïhxr¸9‘å—k˺C°Å:CÔ%bRRöUŽnâPËÊ{Ü­V6>
/Ûr!ý““Ãínë?!÷CyÞ”úqWðÞ[LbûÀf&¬ 4úÄ À$Å’jJŠÄœf‘ÔœKuâ«èº¹@Qw˜Ñ™–â×)Ú›–f`äŒ9.c)["bˆ’bi¥Orïknůw¥Ã½qã|2½iNoG‡ýÆywzÛô¯Üo]áòñ°´½?ÞúÙôoú×ýðÏ.XÔù1:Û­žþX¿êú_&Óú`´Õ÷oáÙÁÑõ$ñr-&†`RQ1Œˆ!ÊÕX!Ÿ&&† ô}
æçø4Ò¿žU·6UÈÖÙe²é×›QÈ?—áÍnuë8¼é·M	sÇX¥^%|Ã$XÊüí²„RÒ-’Zù¢úBJº‘P–Ÿf‹)bôN_Â3Žqd˜EÄ﨡½(Цp(Ÿ~‚”¡ï¨QÒWÜ6ŒŠ°ÝÊè°¿7>=hìîI;Äõß—bú«ñ­)ÝvøeæßÆ[³J¥±Û9nïM7?ƒE—þù~Å©ò‹_/Íðãþh8èü¨ìmlúÛû{ ƒQ1ˆbÆÄLþõ#‚‹è:C`Ú¦‰!¦Yx£â…g³)†<Àþ¶·wt¾þ±ÛÙ]	Ã64TÈõ	”Õ­íïà¼÷êLÇX`ܵÀZ°`)€$|kš¢™xÍ|‘²‚Rã1„%Ä"khЇYwˆ!…„Âb\=2›`üeëŒyÚ¢8ÎÒÏà”P‰*!11N±:¥Ã
Eêz·Drø‰P&'K„(R‡H‰êÅQ$ˆH0DJ†ˆªTÁÊÒ©]:ñ	úïl'fsyöÿå=ûÝó|Ú1j¯×<««»ÖQCÛ¬U6)CíÉÍ>²‚jòpyy}¤YÑÈÊg›•“íÉà¦Wwâ¬è>²r öo)+ÄLB¡NbáÕ}v
U0e%q"¤Yé´Â8+y’üÍ’Ç,ÉY©¢Îj7W“¦BV\Dˆàõj‚”â¾}­6ub&i— ) ÖÃokÊŘžK~IY{FA;f‰!ð‚7è°i‚Ë`œÝ;ju^cÁIMלujwäãÓ‰×þSEÕÂÑÀYߨtL©×|¼ÐWhtRö'>Çר`ÍÚð¶6är2ð*Ó«ÃBÿWÉ¥ròP­ý½/MÎu…®•¢ûbÅŠY›ô#Gl‘RÜ4,™ï?’ä
æ=îu­¤¨L¿Ç’ÕDòÛÈM4=¨]ÿÐ9Ü(ÍB°CÏDñt“8­.’Iœ]BSœC–R
=í3OyEÄE²ÆÚ›
»Nhyx"•&)HÐe™ÀEðŸUÜ"„Ë<.ÃþJ
³½@·NºÌíGåÑ=ÚäærÞ®—Fݰs"ãî	R6*“°wQßï…#L½áAûT÷Gå2æ¡rØE|~îVǼ{éð\ïŸÖó¶]f<ÄÄ|îØÙ”‚;höÚ~®¥1yŠ(«ã$ká•ì÷Âaù¤öuA²³ ‰Ný¬?5Wå.ÏöÅ­Œ
Ár–C€ÖwFq8Œp‘ƒš’C¬©mKpÇ’–`ŠŠûŒ²¼îïXîwmê[³ÜeÁŸ›ý¸Оê/®~ð×oÞnÿqvíľ²C\$U>MžB
ÊËq×ï¾#Ïü€7Ù%ãÚCüx„(¾JOˆ!ÓÂ8Ì)˜möl¥%jÎQRÞ€{¶*Ív…/~EA‘"† ¡DÖȺD‡ÎÀ ”!Á'A1$‡ø"=ʾ—çqÌs9°<Ëñ<°ÂRÊ^hÛ¹)åñ(OX Yf¤kRx‘¡÷(ÇNi;’K¥J½0ÇÍÌÎ G{¼…F	"†È;½íŒ	[¹þéÅ ‚'vÏÁ[Gb;Êl6P¬ÐKšËø/[£óUøµUH$ªÂE²¤ÁþU%†¨áâ*Y#%nÄÑŽË4™¤iBy"†àC—ÞÔçÉ›a¤Ôàu…Ç““5ØèS4‚€íÆrlÜ$½Æ‘Òœ`¡”˜’âLÓWFG8æÕ‰!¼´/6~ox1d Tp‘k'† l¯WÞ4Ú·òyÓ zÁ·‰¿%J5]žaG-¤fÑ4†kúšB¯q`
š²RjSZª4§–­ÈÜFÑÔ(ê5ü8CVv¹ô<àÌ%XùLÉÂe@:¤NY%íÄNÖˆ
—ñÖ‰!™—IÓ	—¡éx•ð&B¤¡CŒRëÄ•@G$|°‰Ò•î.âÄ œG'†D£4ª^YÍÈ@nžž‚(ô=¤RÕ+üC‰§L/)¯) ôLY^R`"†Hš¼øv"†L•Rú|›x…kÄ‹ã2.VŸìqbÈÒUϸŒ“¤~óB8ŒZ҆˗!)%jIøÌ¬g~‘Δ&;ƒýÃØ¹åÈ	QÔR²‡zØÐ‚„ñ1;ÈþW×-Æ„H™¿Öœß;Ý´ÙŸ ÖÆ- ìËÓâsÇl¹6Ö@–K®\].²H¹W0½W°\¹˜*:èU..M‰
FT”€¾VðåÆ×ë‡1dÂÕ¡f9Šä3
Ÿ,M—QF]ÆÑ!âìºýG³Òå"…¥ë2Dgè2*š•_“/”Êjr¥Ñ¬¡(ÅP3†8ŠIéiá§1ÄQ½ä";Ph¤¬‘+*Š

*€1ä­‚È¥KHSòÍ@uh«ðj¹*º¬¨ Œ!Âb1踌!2C^u*ŸCO—‹|äfÉlk˜ì/±LTsA.òÐeº,J&)äÚóºM¸ì¸C~˜1duT¦ƒŠ_økƒ…1¤øÂÓ`Ù
VE.ò\Œ\ˆ‘›~ý†1ÄÏø0®$*Ýò1¤„1(шƵݭqËùõn'㬿?EFcˆ8¦
íòÆòocH¦­Cª\DWC/
P
Ööa#;µ\x·•È%Ï
Âò…w+ÐhËŠï(ç©æÚŠ\§’=ç\|}…nf
cH3 —˜ŠÙ£rvY‡£d(«ýX7TB4]ºC§®ËøÙt× ˆMÒP×€`Ò„½8èæÆœ´ng0†è`	TóN*@¿~rî(u¾å:Þ*¨«ï@£­A’x@¥¢žë«¶Å*ÆïÝ¢ƒ1dfnÆýËÂŽÚ︢û‚åc€&C™/´ˆtcH†.c‘énÖ¨©ÙuRY-(Æ„¯æ†’›5ÆM%ù`»1d*º%J+óOɦ~ÈËhji–RÚ˜E³‚}HS*p4=*(÷
²¡bh¹Uð1”¼­4VÀ2u”øøÜ*øcHiÆÒ!³p–›1$µïÎ@“¡j¨4cˆŒDúqa«/•‡1dÛˆµËï.]†b®îèa¨–vŸ«ð’MOÂݲ	©4I×€H3†4A¦C(N>P”òD•Ã4Üs½T JVAÛrt% 2C¢Ì'‘m­¯Æ@ŸÆOÑnÖcˆ`Ê"ÔœÕÆæ(Ïsè2—‹”I7lšwæ]ŸºŒ|C0úЀÔ'¿›5LâÆJ3¦D§£b(4 2Ϧ·zåÌ…Ö¦7äšmㆧØ^ýĦ
з
`ë{V´ðœcH)þ²5tsqT „
m0fÑ"††1df%ÚêÃnÖ€ý!DïÅÒ™C—%‰8Ê/èÒQièÆNzG³l”€Âõ.B¼“ÜÍq3[ÒUU¶Á²ì5©¯G€m(iS–ô\‹ä†Š£«à)IWŒ\»0GÅ+à¨`ð«ÅÞ^+xC¢GÃ’©‹-$Ïùf9B—qYÒYì¨Cžr‘Í×v2T0|⼫V”¥0k$%Â
Ì|þaì\v¤†(‰¨*ÛmLš$V‰%ÿÿ?Ô½eÇ	Ä,è>Ó“:IFžäoP²Ü€V+õCüTx-†p#±oò¤™{äó,†¼F1ÄD«q®š]”…¾MhÊSÁs.¥YòÑ‹!êsy1¤£+Ðs.M<_ú*•
ÖMu*ˆ¹¶-놹ʷ³’ó(kðÿQÖI©ç2TîÅÝòfY	T ¨ÚhÈpteÔQA.#~ó
ëjEœñ
j2Ñå,†¼¢@c­\ŒèŸ‹!9}”L8ºt”
TêÏ1»'OÒ®ÅF[If4Å.¨Êˆ¦PÁf;P™èTÅ%s®£CŽŠ†H®þQb­„w¯×qëñç—]sU‰¦@Åÿòý¦îg1ÄÉf°­Ï¸È:PyuTR–ŽŠ£r/†(Z¯–YÖÐ’%ÊüQ‘…–^Õz-†(NÖ@sHʹˆG±9W b¡À®Å¹)°nK’}K¶]¦‚:`®ikCÖßüüІƒ,ô&°‘t´èVõ£]Úã“E€*P!*¹£
…p¢)¤Œ8¤Xé¨ü½¥êºì[)×\ÆjrE³âŸ¸ ×îè,†ÚˆŽ¸Hz *RlÌ…úsmTñã4Ы‚=¨Ø[Ì%SÁ@×i«Iþ»‚t«æQ¹+èè­ÂA…ë5%g°’ÖFNlŸ¹Œ¨8Š’ýVôp´]ɈfGkßz-%m¸MÕ]‰F.óÊš¾w×[1$ÍH {ÑD4UÅÙ•#Ý&:æësQèè›Ïu¢PЈ^dÙ€RAz(Ø€¾õ¾J[º‚å¡ @l	W„~·¥Wû(†È,†ˆÉ(†DÊGbIŸšg1$ЙËà9°Cä·bÄÝz.ƒ×ÿ±E%É@µP–GQYåZ9 ËÝ"½2Qí蘋¨êPTÚB´=QÌuS…¨SAŸë´%D§‚£+˜è[¦¤•
’©þ®àøz)†pÅäx•ÑÀ°ßròTÅ3U;ª@q¨}–5è¶hÖEˆö¶GGD:М
PK[C k )ç@¹~é¨IÃ÷@袲!Ž£Dƪ¹üeW¢Fú›‚ôPðçbPh–?+X­¿Û’¥£"s®åÛµ²%a£e…[áØx¡‘ůEùÎbH&šã¨€‡OT‰¶Èe8ºàUÕQJHô‚<ÃÔ5œe1d [ èïÅ|E-ÂÆæCF1dïhÄEXx—Yö¥»Ì¥0‡wø÷¹Žè«$ J4ú*ÛSAÌåh	´Õ
`k*ÊbÈe–5Þ'YUQ¿>4KâÕhl`°ââ ÐýüQGÅeCã=Q®…#Šÿ!—Q!)Ú–ˆš„|ª?
Åì9å’zGe ¿CR!ºš£ûD9—œ¨½ÍET;ZÄõ¹ž
öÔÑõ-!dà¬´+øT¶©àÍåȘë'Ї‚õ´U^(†|ÇÞ9mãîØè
YéÅe1ä“Ôñ½.¨åê(vçÈe(sV™ËhËY˜ËP¢4‰2—‘Åí—Š£42 -Š!YS 6Q!ŠÝ™è¢QÑLôY1 .oÌõé½Ö
\õ9×
î(\mi( *Ž^¼a.Þ7èT }ß|O·bˆ´(†8ÅmyCìÅ\F\먜hÕ@KÜË¨ŽšÑ£V ±¬µ,޾f.C²èDsGkã¥3g1D£¬7ùæ6_5â"³â(×D«êm.Ê:b®%q®s¥|¢úP°„‚|*V;þ`kYBA›
ú\Ê=ÎbHYì_
êæWéE1$õdÒ|5v›/¹ŒcCˆ–V
>è‰Fx`KBEÈeͼ/P˜Ëè5c¢kÚ®q‘çAÞ¸Š”|`
j‘Q*gù#2 Ô^Îz+NÆŒ‹MDk 	¨”íh&kÎåvu¢Òª¦-â"CÁŒ‹Ü(ÐtQ Õd
æ\oPO­+°§û­¯’kÞ¡ÀÑ=Š!¸Gެ¡Nàx€ðdÓMüñj®Ä8j¾F\¨Öì(®ãq‚â*ÿªñª‡–ÝQq”g	¹ô™²-¨”Tv¢ìJ½‰ýìÂÅz`¨#áX££¹€b.ã\D-׿¢p¸'(¢Û‹(›­®%qªhcÀ$çÚ
òS<¼>U¢O1W £R‘|ëe¤·bˆ)~Ôk1ÄõG¯Å–5f1d]2 mglä2è,†¬Zµ' /Éx³é7#÷€Ë+Ð(†-QQªî—(ã"øb	“r®ØØÒã"Q©Œ‹|d\dÙ¬ÜÐ{1¤Ö?*Ž–§GÇ\Ž•PðñTðŒ¦ÐÖþå,†¨ðÐvdAÔ;ë‹w„D1$Êr.Ÿ­©—5¨Õ@õàýÐ9ãúÏ«#Š3Ë@åP#j¯Q¨`z„cÆEm¨a®
/T˜¬%º`Íú®àg¾*ø
ô¢ÀY¢‡£¥4*(T@t*ÈŒ‹È´F1äÝ¥²9YÒ}ÅMo"«K©¹é‘/q‘{.㌋x]";š‰&–5"—a;e•—1—gŸ‹íÌeÈ,k¤Ö3 Z]{Y£5GßÚ÷‡«3Ž*P¤nÅG%-Ôf š„è¨õ¹ êh\Xs©|ûe®;â)¸ÅEP®] ò‹°sÙq܆‚(ä­¡dÀ@ …,²
d—üÿÿDU—”(u'™ 3ížÓjUYfK4u¦U°ì¬@!é¨;îõú“~CVŠ5…'?ý½
ËÍ’qPÊa!ª
-Ôs
cÈ]—aÔe|œS
K â•É_Ôe˜,D³O'jE¢—®É@óV‰J6 ‰+^:úÑG^“m
-ÉL+ÐT$»vÔ'ÝÑ*ð£C®tV —
$Ðí¨Àÿ¯‚Ewtc.û¦šdhúõ0†èN«¸•Ìÿ˜¼4	‡)§¶5m@gy±=>Ðe”òyNL‘1_ýºŒŽnûš‚SGÅOÔæ@Õ]žtT¶ºp$Ÿ3û Ó(®'Ô§1„¨¾ðœD.,{ê¹v4_r³hòMcR&\ʼ˜K´L|ÎytwcȽ*H_*˜¿1†ˆª…Öuyr§qòà<ÑUiÆ.o’íºŒ"˜§ºC‡þÐe¨XWöÈFtÐed©ƒ.#uÜÐ̉²ªÕÇÜb:ÌJTµ<ùgç@;SþÛÒ8ãEKnhö§[ÈE&›ä3QTY¶š,¤)u¬ r¥„@QÁ<‹ÈXý*gFÔ?ø#K:*°K3_¶‘ësT@sîò2˜ºY#ÆK‰·?.Œ×£ºíºúûªfùV—®ùjœý™¥]Åìèfx€üDÝ›‡ÄŠü
4`¾1̉‹-DuG
c ä†JGçlC®(çœlß8µ
Vï¨%ÕZ M!ªhÎÖ+ØXAb&ßV°ô
¼UÐÑïŒ!z1†ÌaÖpy„7;kdˆ97Ïô4†Hè2xQ¥¦sËðÈuÓšOô¥R/f
̧ˆrI°¤XÔžu#”͉†‡D4h¶5lr3†$a.ÍÕ½ÉE„ÝÍfDÉn‘k¨€Ò9+0\Âߥ)Ò+ài@-zC:磂ǭCj7†TV =ׂgåçß!^ÊÝR”z*«ñý—lÍQ*‚5Îà	ÑotíæLõ¹ë2èrE7ºh&*jRÄhÖXÌÓ‰Š'êDó*Ù´ˆìèëjá²|¾rä2ir‘õDƒÄU 'j^ª­Y++H2T°}[Áh«àmßµeÞ!±rT’ÇÉËÑ»ƒ"®±*!@¹.cúqÿc":7¹Hw`P—ImÐed%:ßuI²Ò¬á@?öËÓ€jÖYT¨·ª 0†üÒÑÜЂ°“¿]š\¤æ²éŸó€гi]¬à—^ÁÜ+0K¬ ¡sË厶ô^”âoV _+С‚zV@cÈŸ³ÍÊùì0kpa'øŠàôZPÆÅéçâ;êîD
-tK.¿-@U¹øÓÝJG3PüBì]¨IÔP–µEðLTW"{¾1‰¨;ÅŠ½Chï¢h*‹µŒÙ˜5äzž䲇s©²‚˜ól¼#Q-ÍrÏøXzz¸o7ô]>¨ÀYÁÛyñÍÂ]õ9Ûi¡Ø¢tcHz:Ðåߌ!±¤ë2°'HzÑedÉÝí1 šå]Ô€&îj XõÕ2Im;{CêëG3†¤f!êO‘u °½«2WC5ß+Xv´åÒ/älßT;÷d3+Xn¸ü`®ùVÁ¤¶ŒÆ:΄WÍòC'ÞÊÓš»1Ävð@­ »Iö°v zC­ýà
¨ØMþ,jR)
¥Øüxx˜5Šw4cZ¯Š‰ò¿’¤*JÙÑòÈ@-Pɧ1„¹Š¹dz¼ð¡ƒ%ª¬@ìZ eöß|ZòohT€¿7ÅXôÕ`M>Œ!
U`Y`ºÃbVݪiè­!êÊ7|i©&+âvcˆ
¨Õ†Zç•é)1¹±HE¤®ËàVÍ?žÕeãv¦_p¸”Uvšhht6/DmêO ÅňòÿvO‹häBïÕlG){+*ª@çyÖŽšD¿5]¾V Gt¬@¾«À¼¤V±‚ýW ½‚燆ëßhÎmí4†pQf™b¦6dÈ.2«Q-o¡Ë Zý˜MÎŒF‘ºŒtÑexñúq›‰¾‹›†
/Í¡I‰â˳âR‡—¦â
-;ºê@GŠO1m)Dý-^«uNhm¦Lc娀p‰À`Ñw«@–ÞÖXÁÝÒ*P‰û©´C°3’¼Èh™M‘»Mä2 f
°™Ä9ê»1$Ðt>ä"É&‹û¶r“‹Xe¬÷4u³>½3EĘq/(JAIÙ¨.ôÓ¢@M…®¨†¦ÓbVRVŸ{®â‡\„sIj̨ _¤);ñª)ÐVÁ2#¶:C¸Q(+p檨@sT@Ô>êÒŒ!þä<ãÝó(ÆÜ!bM˜>7¹¸â4ºucH"J]FC]ÙýU—a±°1•7¦U¸k¬€ÇâDZÔºUš:ZÔ€šåØY¤p žvt4†D.ó-žˆš—²©Â0ñŸhTÀ‰F>i
Péô\VÆ
$÷
´U0GKT`¬À€6cÈ`Ö˜%Mf^ÚƒŠ³CkܲYi™Þ‹^âqP]B.¨M]—QԊͺí(þbj(‹»¬Èm›6³†µU_UvlíhC–Ñ­nËŽ¦›1$í¨Mh»oÕ³’@‹9Ь†
*XÅ(æŠ
¦±sêl+rÙºFèÝÑVAÝÑÏÕ¢aÖhwÀ‰—Ô$ñ
Ñ&¶ø‘¹¨—“Äwòe)Ö.ØîºŒ„Or-–®è]—1=AÖpöl‡‡D8úÍWTÒh1騹$ýh¡Ô ò¥ˆù»ËE̹dð@¹{¬€£ýQ|SÚ²I¼çº¡m+H@¿­ aϯÆ¡1¤â‡1¤àÄ4ðÅ‚[,Pã!B4Œ!õ0†h“‹„A£XÈE0_à@G]ǃôÈ‹+ÐU€ºOFTJ!ªkÙ}^+Df
¢ÞŒ!…Æ<èè#Zv”¹5¸ ˆ~º\k$++˜Æ
ì}HSªhT¹¢‚.MñfÑ_¡­JcȺ£©WP¦k¬Í¶œr‘ÑbZB—±X‰ÈfMRã:È'i?#š.ƒß±-ŸÆ¿é2<”DßnKÓeÜPê2PÌD´²!Uïw‰É˜@qý¨·ÍËl':Ctz
®Η¼2Ì¥÷
v–Cý—
4û”€¢‚•,‘kµe>!¶
”tÔi9Qä!ïÃÂÙn|£ºŒºŒbƒDT³ÛQº=>;Öjq£Ÿ*Z1ÜcˆºŒ³Æ³e/Üjâ±]ÔÐÓgŠ5š…èjE6NdQe Ð{ ‹–}3—¹D„yÚ–·kT0ÅÎ"S p9×È•T²3W÷«tôým½-tMÔÕÑ#jSQæ
Ôt*a	³†É¨Ëxû4­ØGŒo
¸\¨.¡Ëx–åÐe4¡P ]—¡£1„ %P}Ä¢?¢tÙQ;Ð7Q)¼â™‰æW7†,cÈŽL“hC9äœÆf?!@(rÍDç–ËcˆGŸç¢¾³éRõw&ƒ1dêð’uþ÷
°Õ±Nî8g	¢¬à/¼VÒdšôp`s>3ÏÁ¬aÚÞdŽCŒh±çÛhŸÙƒ¬§1ñòa‰{¹üš(5 <ëå"å0kL}A³ïhéh†xK(i!jï‰Ã퉠Ýò#Œ!¹é:ZÌ>—\uG‘«}©Ö¨`ùZA+@[Èt)-×Uš’GÊÉûni{ù«1Ä×K¥‹q¶ÁÂiokTb|ŒE‡+P_pÖrCêŽ~º{Ï‹Mú>bÄf¥.Ã0H4û¢­‡1ÄE­Í¨—@ßͼ4Ý!M²ÆU"Ɉr²‡¹C.¹€
sÑ\Ñ+˜
˾­`‰/Dï^AI¨Uw–h]¼£VÊ
+°na[FTÝç÷i‰ÛN»1d~HŒÙŸÉõÐexèB,iC]fׇ–»1¤jb¨¸×Ùd‹Ô@W<&šcµI^ˆv9Kµ@Ó€Z3†XC§mØÙJh±¹h©½ç¢;ÒZ®¦ÄÏØAšR†
cH¯às¢x¸ô
iʵa.[Kä"zCD¡Ó!‚	ÈðËûÔ€äú½1äAcˆ^Œ!ÒÑÍOcˆZÎDí&‰÷ ãf ÝB´¸% ê¢‘_¶­š¯=!&†1d&j6ÊE˜KKñ-í¬Ò2V îÒŒ!Š
ªˆ|•¦¤»1äkÌu7†Ü+«4EþŒ•G«H\"Ý Ës]Æ*Æ!Oò;*JŽ£&Œ!æ|ל'fDרÀ"J_h3†Q9P74£á€ÕÌ›‰[7k,HÚ!rj@FÔˆö\Ù2×;PæB ¡‚Ê\Î
Ô|‰
¢Èu 2T@”¹Æ
j´µ¤VM2è#Ppò½1$«íN 5t¯—nÝò>Œ!y4†àyê™ÆÉv5ÐÚt!A)›fá;A;ºU ‚/æ!rCÀÂ^ J³ÆóbáεLô‘-
%w¶³Ð€¸µ\”‹ðº§˜C®/hÎâQÁ€ÎDÝÆ
À¨ç”¹ˆö
R¯@¢‚W¾ÈERT ¨ ^!?ÄCqÕe¼@«,7cˆà3_u:C„±táþºŒ,BTtFDÉÆ*Qô§#êÂú²ÅVOcHÎÐ.Åä²7T¹²h7†p%ºj
uû¦¢×UOuño+˜u+ 1dùZÁ=×,—\	ÏÊï3ç1PïgÖÄU°òC¿ChÖÈØºÆ¿s R:Êb\¨Ë0¼]†Ø]†ºíáyånyH7†hÞ<+hëÆ’ÈÝ’D{®&±«1Ä.Ækô\vä²£‚¹U`Â÷V¯Æ
cÈ‹¹ðìÞ+pVð¾WàòÚÑø×0gD]F˜5ÂèjùÇ‹7š­£c†YƒºŒY,ÙÖчÔªú#T@?f
÷p—‹Ø ËP%š‹„.CCæT~ü˜Ó]¢B¼­fòFüqAeGý¥úø;«Xäª5ä"@Ç\ù‡Exöj«1opXÁk—‹s-—\@=PÑÇ!ùß
Ù£»1$—cn]ŠH˜5º€g‡.£lDC—Q’šÊŠ«Æö}&×S.rè2€š&UW ÿc)ŽP_!jGµ¨8Q«Ы1$?ò¤{;û*ªÞr­nuG“´\ü¶žK€ªiŠ
ª#×(M)èVPYAäZ[©£ëQïèô^Amhýú÷ïÝ".S¨«XøJMiÖ0óA—Ñѵ§@@éf@-E±5PÙÑJ4Œ!@7¢Ô;±Xãf±Õd
ÍD“mƒYƒ¨6ÔH)§“µCÞ¥¬*«j_ÑúÕõM@·=ÐÑÂ\c½-¡1¤·µX« ¢­±‚dërV g®µCôjÙ]F¨ßݱ]—ñj¨5ë¨jD¿ê2vÔi±=̵C^2?¸’—Vï↗¨jߘ5ŠÆ@U*ÐuDói)蜛1Ä=P!QÁ2T¯Û+Ƚ‚@ßú z«`þ—
êwÆ^I)¿áYÁgš1d>Œ!€M¯ÆþãøÝ8·xGãm‹½ËEÌ7~´Z×eŠ	ÂÓb•Ûq¢QÙѶØð…¤êÂ%nõb±W>Ñmr˯®IW¹si Ù¢g.ý¶‚ÑÒÑѲ¹0ŒŽm騺Ü+Èz7†@>&KÚùÑbƒ.Cx(&Ä”6=ÓuÅ›;Œ!©90€*?mͲйáÕæ
Ebòˆ¨u
Qtç,¹t
ÈÕ¸>j16Zu»¢²(Q!j†Á‰¨KG_ÜY鯠«f[YQnU­çJca*°Ó‚bYAÎáúeD¥ËEÆMqöOgg·Û:…Ñ‘Â?\!Äž='fìH‘P."µW‰»òþïÃþ¾=ã™8$JÏ9M²¼W·™8«ü´¬11¢¾:SËF•TË!а¬q÷\FE§ŽJC13ÑU$w4^}¯TWÏe¬D—^Ñ@tš
m}‰‹°2ïÅ«@­nDÇbÈÙ‹!XüQlCs––¹×bˆ£ñ“¹è¶º‚†Æ£¢}®Šö¾Š¨¶¹ÀƆÎo­'{Êe°–2grªD£ðQ;QC0ªÎíÅŽ
®TZ.ƒÅæ2‹!ªýÅPÏ€Øl†Î…ñ•NˆFGcCkâe}*†”>WQ ŸCÖ¦ ú×AÁÍÐ;Q¿K"Є
þ¢ œ‹
Ö]Á¦y®s]ÿúë,*@ç¦à6 j(^)1C´700‘ç2f7aÅI•ŽF¼"ÝÑ™h-†L~ˆQÞÑk.£Ä!—!‚\Æ$†J$ZP›ª™[¯ÖÞlR‰,†ÌSìŽ"²´ˆx1ÄÛâÅCÐ"ÚÚMD)÷×ã"|1ÃQÁT<€F¥‚ùµ²Lƒ‚$81»‚ÝV‰»p.*Xerzb1äd½I<ï
ÅPŠÏ§$Cæœì¢Æ–Žž%yãrc1$š1Óê¨ÐÅsæNz.#êüY\ä€*‹!!?²œGôL4Ê»qÅI‹?8gmè"ñ	eÛc›/µ’û\Dãõ¡‚mj
¢ï€ò×µ¹¤)Ø}Ε
nMAEa1ä:¡¬qfÛc,†häB°â¦¶!—‘&¢ÌeŒh":)Q1Ôš%æ2OŽÅ”¹ŒRsËyJ†F 3 ÁP0%¥
¨ºïÅ,Ì„¦(–ÅîÞˆÞô­"ר@9—g@¼ò¹‚1.Ò
}Mé
nÌ
<.2*¸ŽÅCÏPÀbÈï'AGiöbˆŽÅƒPI=ý4æ2QÉj(—ô€î¹Œˆ¥
­¹Œ¹‰@=—1–52Qq4߀N@SEÑCYã’R‹‹¤U‰²rÙXì0„˧©ëèeÞ0ü¥¢]A¡æ°Ê?(® Ù
MüOo_îÅe¡9_°Í×+®á¹ŒdûÈ‹ú6=J146´CˆÊSYC¹GÓ¥CD(kô\†.˜TÑY€î¡ñ
/kŒÅ©8jæ[1„è9«²E4Ë0×ìs-D±÷MI. AÕÑQæºY1D€º‚-ÆÀ¹„
ÔЭ)ȽÒ$*À‹uG+ÄOÄóuÒ5÷bˆÁþ½È_ Ã¯ÕÙUÿç;Ø­rÝÑ¥du÷Kã_C%®¦ÁÐéÚ2 Sñ\ÆmîŨŸC&!:Cˆ–2‹!KCý5J
5)ÉŒüÐûGÂcÈ¥¢&蕇Á;ª˜K[1ÄÈ“‚´z1䑚‚tP0)LT4§‰
ØÌï
0RH+Ø¥KSº‚Ž.·±âŽ)æéÜʈ?
ËâQyCx*o@££Ê±æ¹à5ï‰q‘äO‡ŧ"‹¿øè9³¬áè#õbH†¤Þi°«н¡Í€}¤T´D4CC’¯q‘›L‹¡²ŠÔcÓ®Ž
ÂSâq‘¬@MŠC$ÔólQ¦˜w“çæ¶*à\Ë
QDS
ˆ&¢]4ôêÅßX©¹Qe«2dS+†,‰½n®uÕ\†òeTÅ8ü,«þÒrD™Ëàj7Ëâ¿ "¢lç_Z.c;×bˆÖbÑeGÐ4'¢“–†úƪ?a!^){1„¿¨1ã\¹DC”ö›%&yR°ÆZY\ÁtP4:šâ¨Àö÷T9
ÎÕã"“ÛjÅßã‰G8î©Cþ»¤æ2¦(K+†ºªz„CÿÀC!k:eCñC.§j/kœã7R‹!I^â"öÑ(†_þÈ=”5"PFg`Aæg4Úå5oJt9÷¸HÆ\@S0ô<%ÌM´+À\+䛡TÒS4¥äúÍìî
¤n6©RAè[ˆb%> .b
úÆÆ3,/
Ÿ·91—1”5’¡ê¹ŒÌ03 <ˆÍ‹!*RËDÅQ“‰ú!ÙsZËG[.#ò«KhÊ2¢8Ò8`ÿ¸Cp®ŒÅ¢	ˆ?~a1伬2CV ë\K¾li•eJól¨q-:ª½’’PÁJ=šÒæRW5|¢à

Ô<âõ0WLP\ÁLc1¤F¤e»'Åàqñ²FªÅ¼·²†L‘e
OÖÜ èk.ƒßmês~¨\)üh̆F¢N\+*9M\9ö²†oP¯šø7¢ ®‰D{$”èbèšèD€q‘‰(ßë\‹û:	èÍè® çjÒ£x\„hWPº‚>—ÎMÁM‰rg¹ZžlÕbH-kpdì*
ÝÒ„[‹á9—T’T4ÆTzYC¦Ž²?sA[Íњˈ†²RUßk$«ê?½!$î{1$Jlh2}8ÿa(줡t(†¬Ø–PR‹ŒÅ•w¿(g*)ã\»‚…¨ºñ6*Ѓu‹Š!PÄwα£Pð”>W¬¶0WLÛ܃¥ÔŠ!0"zÖ˜°‚‡y¼"5¡-.R“([ËeØ

U \{ÌÊ'b¢ÐZÖX+
V$´\FŠŽÆ¨†ÚYå+ºŽÅ¹C–$P™…»ÚД
Ðlh‰‹C$Î7ŸKžã":( ê
"P°:(HTÀ¹¼²ÇEÖnKãPi
Š6ŸCnë¥CJÏeÔêžhF1dÁFÆVÖ€squ´CBäÕw”ÅšчúÑ65—t˽¬ÑŠ!¦ZfŽôëghôn~Ë€ŒÅ¹™çЋ!¸ÙtKY7QC“¡æÊ^vÛ°":‰Œs)ô¹‘è¹^ðçÅ®ÀmÅÁ–‘si
8WnsÕ®s…Vùc±±y|Ø\ë»·–˘øEÏ€Š!1‚:O8„=s",†ä—bÈ£¢ç	ÓƒŠº9вìŬ³jàÕPŠ!+3¼¢^)Ëõ¸9—jE{1ä˜YZ1„è¨ >¡ùU–³•%_š‚…
¦]ÁDtTP£)§W'í5—qWO/¤i*YÄÏe°YÉbˆ]Èe¤!—!šÌpðÆ%ãÿêh ÊÈÄ?Žî¹Œ[´“D§c1$g	­â_^K/†‹¡ÅÑ ÇbHŒÕÉž‰Ã\‡3V‰(£)#z—
؂ϋ!²ædÄ®`mhð¹z_Å7vW0GÌU{ñʲ†Š!vÅÖB¶[Z½òÔ˯ŦaËÑÏ‹!3Šº9ø2þ¶ç2$
e’ƒ
vdÓS1$íÅ,½¢§‰Û_¦t,†¬¸uÎ%þRG»‚ ]Á#Úƒú‡?=‘îÿª`†‚ì
ˆÄ'WWóªës1DX¹Œ.GÖ_JRË*,†D­‡ŠCPÏeTT¦¢DÑ»ÀðsEãs.cc1Dk÷c¾ L7ßÅ©¢sEhÜ¢®^MeŽ4CdjÅ’€f¸¢%Z::ɲÏÅ{é×5Úó&Uçê訠ÅT°úÆ6«+˜£RÁ
ô `uQ›Éɉ¨èè‚
‹!C.ã¾70˜­™÷_¯:«70޹mq½e%jL¬h$2–R‰úÂOÈù¾øRô¡Rj1$åO,¹NªÉQM
zˆ
PÍ

†Î"õg–XèÜŠ!@ƒH¤‚+Qí

z	eƒ‚è
â“¢i@:*ÀÊÿšµÎ•$ï(‹!ÅPA1äCð!ÝPJJLð®0Å)êËP|ͬ;ªY܉¸;Ïõ÷ÆéFt(†„û­B/R
ŒÅØ‹!@¹/†,@/޲ˆjK*Ž&Ü*¬_þEÁB@©à2*(;ÊbHí³x¡5Ï]÷Uî¹ Kdè2ÚZâ–+J^y‰_ásÞšz.ƒƒÂË|™»¶¸ˆj”åµ’ö\Æ^É›¡µ‚{¼•¡RžË¶×3×C1d1;[/kÕC1„hJ”mu¤ÆE|.¢c1DÚ\]ÁÒ,Ó® ¥Pçê
z1dT°¦Ô‹!*X>Câ¡Ò˜­Óo,†ð!õ;KÔ±§–ËÀ¬S-kp·Š‹æ„²ÊXºnI®
]gƒ*D×B´-Ð^£
;ZQ/†¨'ÁGk1Ä#M³ÕÔ3 ¡¡“ªl{Jã#ã"J”sÅ}.åEWt©
«¥¢Å‹!±e@ˆJGk_…O¾mX"ë
ü÷¢ì¶R/†ä¡rþTjý*¢H4IHó^Ѹô\F‹Ü(j64øÍ9zßsWÙs¸00—a¸£`
•^)™U‚äUYyl;:ºíÅGYFMÅPh2tÏ€hË€p®çÂP/è"º•ŽBAP)k¦­
°×*TP¢ÔhJ³ÅOànK–T%ø"Ô® „ÛAÞ
•u/†à®ƒbÈéw;™¤•5VÏ€„ìw™žŠ!bË䥯Ez1$ÕbHl
¢ç©–5”è–fq”»å^q4
q‘„ø»£­¢Y_‹!M@WĦc1¤¡·ÙÐí¶CÚ\Ü÷2R‹!\xJ˜‹¨¬C1wØBú¤à¶+PG="£%ŠhJλ+Ð'+‹!¿
¹Œâ-šV®Ì²,åïòc/†¨¦VI^!:æ2õbHCo
ý·bȽ£ø‘zºµbHCg%™fîÿV›a#¼uC¹¾r|&Ê4çÂzÿÝÑ×bˆ¸‚­+X]>)X¡€s­Ã\@ÅÞz_¥)í¶Ž
¢)8ýù
‹!8;±ß[Û½¬Ñ¶¹c.CÐ4‰£bhy-†0.R3 øæµ—5‚¡›IîÅÆEZDöbH’²—5bö»Ä
ÕU¢3jh(æÂÒËÍØdñ;_|ÊEÎW­*3>Q·Ñ® ™ÖTÐl
ˆÎyT òTIµ’ƲFʵ"’e/k¬žË€Š”+Iéµ4šÍD™ËèhºVÔ¤´bÈÆ#S“¡âÅ¢š=>ËèŒCÆÝÑ4õ¹¼’^‹!‹Q%ŸÊj(`®ËQAl

ü¹‚¹*xØÆ>)ȃ­
îDo¯
¦ƒ‚»¯¬…Œj$1—ë_æµC¤æ2æ´£7$²Ò!—”Å¢­2«ÝØ€â®ÃbHìÅGo³ù04‹!qJÒÊ‘«@™I@U2:Ç­bhº±vôb½èŠzÄ|Ú\ÚŠ!:¯âèAÂ'È‹‚TÑQA®Åa1äá
bS°î¨ýTÁü°=ا­œ‚\OWÙÂõ6\~;7ˆØÂé|=Ù[W»ÔÎ8eèèÉ®øøã±BÐÍPÙº-@ÃÉ®’‰n9yF%ø©Óµ*èe¢å|Æ…²ìß­ˆA@å*¶y'9]·_
Cm«*Š›j›·ðïm3ät¿b.¢ÜXPœ«¡T°
:ZlÏ
€ºÚ¢>WÙNŽÞ·“+kG7W꺸-ÛSðñcøé»·÷÷÷·7ûçÏ7~üçûŸ¿½ØïïþþçŸÚù8Ã.Ç»½
èÛ‡q@?Þˆ¾9Š·wàvÎÑ·ßþx@ÁØmåÍòïß;úôÏŽ¶wnÿûï	ôhߨWtœlE¿¿%K´Í5¢o]É6×ûë\ï®ÀP²¥dcúþÍOáçŸ~üaxûþûï¿ýêk{ÿú«oíÍN}ûíW_ÙÉo¿ýú[\„7œó/7gá$P\èW@ù±qdý4n–(¯jï@¿÷[5ŒdCyŽo@E¿¶S;¢ßVÔÞ1Â?¢öçr´ÎE”;Î…“Žþ·£ˆö¹^PœÚÅâý{{??þôó߿ŠIU¬ýTIEND®B`‚qbs-src-1.13.1/doc/images/qbs-settings-gui.png000066400000000000000000000752041347155106100211070ustar00rootroot00000000000000‰PNG


IHDReÕ?ϘzKIDATxÚí{|e¾ÿ³ºêTpwÏË=ççùýw¤^V=—¥p÷·g邲»¶âîžÕPu¥€®PhW‘V.M¥¡”k¸X®å#(‘K(
¥)e€›®ÚÁfšYí¸Íï;ód¦Ó4iS(ÚÖÏûõ¼tòtîòÎ÷yž<_SYYYiié‰'JJJ<øÑG}¨²WÃÞ–=mÙ]À·GT7Eø+Ânºõ˜ɆäD2#ù‘,I®4ÑÿŽ?~àÀªª*A‚MAr"™‘üH–$WšÈœôÂ_ãÿâÊŸ×^÷·ºÏj?CAAAAAù.²!9‘ÌH~$K’+MGŽQ"ËÏ…¿ùÿ†‚‚‚‚‚‚b,äG²$¹ÒDÚ¬û¬®¶¦¥}!K’+Mûöíã?ãýŸúQPPPPPPÚ²$¹ÒDƒ‚¨q¶ærMÌâ.ýtñ’Ëxþrâh¥üáyzI•m¢•Ë•îËÎÜê­)—Vý„
-ÐKªŒgÛãçOÍ9ž—ôá¤ÁÛþƒ
-ÐKªŒg[”ïN¹tþn
Êu-dIr¥‰ÆÔÒ‹O}ŸF/îó™Óš~öóÐøñ¡§§”ñãé%UÒŸbn¥_ÙÞêí¿oÜ<ìkû¶L¢Bô’*éOo»ýì‡?Û÷GÓGÿi::ÚtêJ¡…þ“*éOo‹‚ÒíÅwéÜÞõ…¯OuÆëo.]³ýìy«/?¼õчŸù¤âb×÷é;þÑÎw^Ÿñêô×­+¶”UV_݉;iôáGs·ºð¡ \¿B–$Wšè')—«/G/'ݾçÓ¾7.ôÌ3¡gRC©j¡…gž¡Jú­kÛjï‰êm¿ÿj×#-‡G·ÕZ¦Jú­kÛOªNþìÃ?š'ÝRö«:ý«[K•Bô’*éO´BÌsFAéîr±âø´Çÿû‘Ÿ<òÌä¿Ìœú{Zxä'iÇ+.ÒŸÎ8‹ùÉÿ¸Î^èê>w¾÷
í'iBZfÆTu‡ÿËvµ\ðºžúÉ#¶§ÙKõ ©Ç+•õ/–Ÿ9ɼûèY¼M((×µ+Mô»Nß%_ô’·X‰,[e™¢–°2•(3oq¬m«.¤P2,˃£Z¨å`X™J”ypa¬mg}’K¡dX–§þ§Ÿ[)´VæGÿI+Äý\–«ì¼qó*Ï‘_<4¢pïI­æÂÁí[>.)S6<vÝ»a&?÷Ž»œ£ø½ú’ÊcOg»¶ÚËënõ¯‰[e´ð§Ñ*Ú¼&Ѱ-;“÷þò{¶þ{k¶¾óÜÓœ¦ú³Ç¼úôc¬þ­¼Í•ÜE¼×((Å—;wî¼È]ŒZ|#G)–,²$M>ý´RR´(óéßÑ
±¶½¸r„ÒgyH
+™,Y9 †˜“h…XÛÚú(uXR,…•¤É:ñK*´ D™¥¿¢?Ñ
1‹‚Ò­¥ìãMÇ
ßK­¥†Ês¥F¾zÿÉÒ7Ð_‡{v÷Ç%û·®¡ÊŸ¿´œã.:7½;|دw~|¬ôØÇÏþÿ^YeÜœ«:ýÊcÒ†µ¬9pè“ò
NÿÓM>ì‰õÅ»î¡
ÿ{Üœ3ç¼wÒÊóVmûä詪Š3EKfÑ:ìq”–Už;sø	õLhá×Ê™üvçÇ%öl Ê_ä¸Õoüjø°‘k¶î§¦©¥•/œ÷¾û»¤¤ßes{ly_­<…÷¥ƒB®4_8!j‰Ç—±¶Ç—±¶Ç—±¶EAéÞâþhõC&—œ9g¬ôZ^È*ðœ;Ïv›±lOUU%mxdû’‡{ðtå¹³JýêÜlÛÓ7P½Ó£´Ò㫞	-Ð:+ö…×Ù2oRâosN{QeÎÆÃ¬²òÔÇ?UW¦#½™ôHâo3Oœ.?¯üéüy¼×((r¥iÇŽô9j©žô§ŽÛci…XÛ^,ú]Çí±´B¬mGîIí¸=–Vˆµ-
J÷–Soxðþ·)3VVœø*×í?yrÿºïÿ¯OUVþ½¬<}ì­~GëPù_NÞuðdŒýŸ;sêäúÅ™´Úy;+Nü•º‰¡üê੊ŠÓJ}áÞcl+õ ?;¨”þô3õOú[ggÞ”ŸŒ|ýÄIÇÏÔóŸöÉÔÖ9¶oËïFþ„åϯç´B¬mQPº·x˦ÜÿÀo笥å³'öþÏýä}ðáæ¼—¸?åh¹÷ÄþµÜÿ¸ãÔY¶ò¡M¸ÿh/ÏUœ=uÌ™>rĈ‘§½•ú>KKv¾ùÆ¢O<^­¦òí_>:iþVv¬›éõg¼Ñ((r¥iëÖ­••±ÊùíÅÿ÷ùöóP%ý©ƒ
©œûdû…ÍÏ´Ÿ¯€*éOo»ñäŽÑ{žm?_UÒŸ:Þ¥ÛËîUîzŸ±|xâÕb/xè¿&/ΙÊ*G>3ûhéYª/ûdÿsO<Ì*ú¯ÔmŽ“;t¯mØÛ_rV—õR}…çØ;æ_jõã?øðuýŠÍ–Yê®fœ*¯ ufLøOzù»¿n<ãvü¿¡÷­Þ{L_`û߾襇Ÿø«ºÏŠ–¼¥ëÿ­°­¢…å»Ò
o°>ªýwSæ;]w¥ƒB®4mÙ²¥‚þÆ.•‡ŸŸ¿ðâ3ôýtZ —TÙñVáròPÕ¾yÜ¿¹X8‚
-ÐKªŒgÛK3œ9ÿ½ûéA[¥Bô’*ã:.
Jw—³ee'8qì”Ûµÿ™:ú¥ürÃ_ÏP6ÙÒ²ˆMÎPÆûòË/¿úê«ævÈ*úˆ†²[<¾$W—ú²/=Ïa•3gΫôåÒ¥KáKðåÒ¥K¸	ôa_~ñÅ%%%‡4œNçÑ£G©²«¾$Wš¬V+|	¾³\¸p᪶«//¿Àí Çû’"ËCœ*TÙU_’+MK–,¹
_W’é—%|P]vÿÉtã›{ÎãM½Ý—¥–	ÃÞú¸õ9÷ízÀôÇÒvbò3ͬÅí Çû’Ú`Ûû’*»êKråÕû2ÑôÓƒ|0(]|ÓtSrÞa¼C ø²ñ¶ÛM/œÓ^žZúäW÷¶ß*È;“ï_Ðó}y¨-Ì—´p5¾ÌÏÏ¿êøò„ÀÛ~3xЫ;µïßÂþ<³IåMÛ1åÛºõ™§—s·NNÉ;†7ôd_RCë»ÿÞoþ‰Ï”‡\ºLßß/o
gßýM=Õ7˜†Îßã5úÒøTŸ°Lž_R£J×ñ§¡7Óú·ý4ãDm7€>àKr¥iñâÅWçËÿ1Ýð¿zp)Sÿ–Íí˜:è§‹|Ê_Ë^2}ÿ½ÒÏÏ­hšéÓ>zVžkÄ	z¶/¥J[Ú—v*Ú;·‘=½ö,|ùÝ]ô¥0xa×­¦‰Ô<«û²$çñ‡Þr²
Kþ:þ̓5Ôâòªé¦ù•aDgliƒš/à.Ðû}I®¼&_Þ÷ÛkºAï¹Üÿú˜û_ʵÙV®´Ù^½÷–§mIúÛ[¦›Wk
^Øh4+=Ö—äÂûMË)^ÌyiTÞ±ãK'¤¬ôà]=ß—’ ^†wyÓ”°Ã§´¦É›pËÈVnÞ½oÏâ_–üõáaï†;ï÷¿2Zõå‡I¦‰¶=ôÏ`ÇžýKJNÔ—ô~_’+Myyy×2Þ‡5:Ñ	ú}få¤A¿]¡¶>	{rÞÞq®}[ÿ•)¾°³•èñ¾”üÑ·@ía®Ïû÷~¯íW:&ý%Ë
¾Ì"_ú÷ÏüÛ5‚òœ+£Ä©ÿ2(£F—U¥Ÿ+ÿÊw¾ýî.´ÇÐ|I®¼&_–„(l~ñ‡ƒÿ´Iþf{ñ!6ÞçÁ?-ñi+ïxñGôW|ɽŗÁ@uÀÿEëhðŸX“`ú=Õ¿z5çÏ?ýMØ—?Í®U5I]ô'
@ßøÓ¸ùkZ×O¸‘ƽó!ÐW|i±Xºw¾‚€@åø·¼ÿ¾ýmõs€^áËÏu̯|Ïí×ç|G Ïø’\Ùý¾l†º©mjÀŸVðxAóá_ÆëËÜÜÜë:›xóôj_’+M‹-Âü±àËlH®ì‚/O=žëåË…ÆéËÐã¹¾$W—àKø|	_ðeL$ÿ)KƤI›D<¾_.X°àZ|¹mÛ¶+W®|³·¢©pä€~©ïØ]ž×ß—äÊkõåüùóéWœG¥3ûÆÂKë½ýó¼_á™Ð›|É(((à8.΋i‘Ê''N9äÙ›J)ëM¦~ɳ=BÕ½kƧ¾³"ûIªÌq}N¡¤Ó:Mà>*½À/+šM7²š©J{¬X™2ŒÕdfû÷®˜nÎ^’‘Øÿ&ÓH—Øs˺ìq¨òÖ„çözÂ''VZ´•§YJZeû=È|ifjëš2R€/;õ%#ÎæÙ©4ÙtÃ-¦_{jÿ˸ƒ‡.B¡€g9¹g|æ&/ÇùEÙ³dâm¦ç\­CbdÞ(‡$Þ&sè­¯Ÿ¦9®[Bµ™¦›ïH_Ëñ‚ϵá>Ó÷²œŸÑþiCÚO¶ý$çó;\g©ó¼À_X—ñ“»Lɾl‡·¥.òø…:ï.Zy¸åxŒ£HE)Cdl§©që<iW+½MxL Ïú’$×¾$(	5m/s\á—â1’Ðz.ðä4½Æ³ÊÐåtÓ÷§Ù/Q 'É¡Ïr
Ý,†š¨=6Ç­lP+]BsH¢8PvÎyxPòrZr玞}œí<žuš¹5$oÚ9[Ù-µ„£Jß)—§&Æ”Óh^ë—Ћ
}Ü—d·nöå–-[h‚õxâË$Ó
v³æËòežûsò%š¢&ÑdµµV§ŸéiæK˽ýrÜŸ‡´xÔÈÀä|±/;]‡Îç1S"µÜÜùƒMs#. Ö$ß‘ôÄ~¬fªe·€‡àËN}¹lÙ²ªªª8/†Å—yîF£>©=“|ÉÚEUê©TíÅŒ Õ—ÔßIq¡§]ϡхñ¬£û’V6Æ—²Pëóbí!Œ$Öx?¤óO+ªÂc
ðeGãc>Ü¥ñ±ä'és{Â·? Kµ¶ôÔëW"9£/eû”VÖáƒäÈC–§h_[_¶Èçh?ã³w2¹­’ú5'XOGº0žu4_ÒÊ4žhXÆ&^
5¥´<8ûHÔ=Ps1é|’µ„4Ú,”«MÇŸâ1ø2º/ãl€mïKòÓŠ¢<Ö˜©êñ‘CÆöXb’JõÆØÞ‹/ÕþËpÜôHÕšm4çûÔ(Ðcpa<ëÐùŒ2S{CÍþ#ú\”ËVŽº‡ç2jFf•ã3Öú1@àËî߇ùRmö”EQìX4²$‰b'cj”5$ùÚ×i]YY[Žc²Z‰çúº/ß}÷ÝoÁ—â1ŠÉœbÞW=ß—äÊoÇ—ÊØR·Ù_À—|	À—ð%ø¾_—àKøRA®wþ559u³7P]ü*Mwà•h*»Ìk1æàKø2L}Ö
¦kñGœÐ\ç^=Éœ¯Ì¥ç6Î¥¾ì1¾¤ÉðæGƒê¯ë½(Ëý»ÓÝ1ÚÎ=¾ì1¾¤™c)…f„,©¦Óe[¤òɉSyö²IYû%ÏöÊ\?”	d|ê;+²Ÿ¤J53I“Ó:=Ç龤åx.†%ˆ¶û›5_–/óÜŸóy‘D“9¥i¼ÜùÒÔ–Éù¢2eí‘ôÄ~¬fªe·€g
àËox|,øÿ0_ê.dú¤Rc$kVÍÑבÏ)!i¾¤MjÅõÄŠr%±Æû!.­¨
OÀ—ߨ/i€Onnnü‰£I4Òçö„n@–j))45ÃúÛquÍûù¦—]Ê:õöì§Øï,;õ%™•v>>{· ‡d¡2sè­¬§©u—ì;ÉZBmÊ©¥wšýSþ‹aù¢Wå±ÖQ¡ÃdòÓÛcUêmSÆD¬j×É61nô`#o•µæ|ŸkÖ8—Q«/«Ÿ±Ö²_öðù
˜/ÝJ°(‹¢Ø±¹dIÅ«¤£l&É‘;S*ñ8|Ù+|)£ Ï)¶à}_vûù8æâ_ð%_—àKø|	_€/áËèH²F&oöð |	_ƤE,U'gÿ
À—}Ê—lŠööÄ?i{_Jð%€¾èKšœ}Á‚²¤š¸&m+-)ÃØL°Ó¬¥_
åóhö×IÙÛÙî¼+¦›-ë²Ç
 Ê[žÛëm`{ªv,f“ÊŽÊ(Øa}!­ð45€/{V{,t„/©¦óPRÍóu[ê"_¨óî"Û
·7øR.~þ‡’q‚XÇ)³®³¼]ž%IŠKçþºŒŸ„SšxWSeVÑQ^à…Óiy‚å5€/{–/eY.((ÐeIËTÓéV”ú&ÓHu®v5Ôôryj¢´ÇÊ4Õºä˜óððì#¡¶)Àš9%A¦[l¡Ê!æmúE)CH½xÔ¾ìqã}8ŽÓ}IËñlpç6Íh´5úÒçx_ÏÛ¥‡ŒF_²ì(.±Å1óîÇ-¥úN*–<¡¯¾ìYãcÙÀŸø‡ù½kŒñ¥,ÔúüÝ—-Ry²é†,GT3ÌÕ—”GsHêF-¤•mã!¾ø²‡ú’øäææÆ5̇ÙN>g6Ý8,c/…š…RZœ}ÄàKe!ËN¾”k\«(Ðì ¾dý—“­»9Wœý,ú/¾ìÑ¿¿äy¾Kë7û&Ysë¨ôŸbaåRO#ýµ¢ø-ö§~ɳ—dŒ£*ÐÓÖ—£LãÜjöÍ€w—9ñ~Åš…Y'¢=à˾6_$‰¢c|L”:߃ÿÔNûI}=ï3X¾Äü±­´ǨÁöŸ’gØl…éÉwÜ`J(öñ¨|	_¶1ùÊbÛRKvv^áNhÆsð%|	¾„/ø€/ø€/ø¾_öN_²)ÚÛÿ¤íà˾ïKšœ}Á‚²¤š¸&m+-)ÃØ³Ó¬%e:ÙòɉSyöRri6ë¬GP¦–U¾ì5í±tÁ¾¤šN·j	Õfšn¾-u‘Ç/ÔywÑdx”À‹¦_§¹Ú)ƒt±§F🱌8xèBA–=j=ø²×øR–å‚‚]–´L5nð,7æÎ}§\žæÅWcØ©¢2©ìz.«Ï"À—½i¼Çqº/i9žMîüÁ¦¹1"K™i÷7k^,!/ê©4Û×ãYø²—eâæô®1Æ—²PëóX™çn4ês¥·)V=žE€/{™/i€Onnn\Ã|˜óäs”hzXÆ&^
5¥´L	/I„4¢çö„n@–jmé#š^ó«‚ŒZ¾ì}¿¿äy¾Kë7û&ÙøØQé>Yñâc¦ÄEy¬ò6Ós5f¬zðåwe¾IE)<>ˆyQm¤•EQÔG
Ū_~ç÷¡¯>:Å–8ëÀ—ßÍùð$ç»P¾Äü±àKø|	_€/áK¾àË>‹×öJZáévÕRQÊ;3v_ÇKõn§ÓÆÍñâ5Ÿ3`ÈœÛå“Ôéø¹z-p§NqPèŠÛ}?þ„/¯’“¹ÿ1<ûH{›9æ½0ÍvDsÇ›ÚòFQïQ“-eôROc‡çÂ÷*Çtsާ±"÷ÿÞ•©Ü%÷¼{~˜y¼E>þiº_—W‰;wìðìãßüqÛæ&“OÚ^1N%ßÞßÖ{û縛"ÎYF¸Í—t¯ò¼Kž`w‰n׈ìÒ¹ôÉ{‘ø¾Œ¡<;eæÒ,ûY¨'wì¨ÌME™Så
¦„<Ç%¶®wÅ‹ÏZY|)9­ÓÙV™çy„°ÒjÜ(ÿ	URJê•®m«éS÷¦§zò«çŠ^yȼVko•s~6©ðtØ—ÚôC-r9íM ›Ö7ØáHžáâ›[¤òtÓ÷YÍÀÔ1|ÎkÙQèèëÝuxo__—ÝCK¨6Ótss¾—üžIN£-%Š/—ü¬3µð Ÿ÷-z“–×{Æγd"9©È]-Š—­ã²$'An#­ùº­„xwÑ[´¼RÝŠVVöVt”â´¾@Ë;}ÍÍþÝ´àà5’ü’Õ´b¹¯[„#”ž“vÒàZ@ÚÞì©…ËëÒt×ÐÅbHâýg2‡Þúzñižô£äØËÁoÏ~ªŸéi¯„iÿtd¯Óé[Dî§Wù&!x?9쥎ÌúOœÈ€/áËNˆðu2Í”-;dÜícT¦a>z#-´„.Sl—åÔ²LKµ.§›—•oHêF}çö)ÿ–kîØÁû´j¥uŒå„ÒB8òŽgmUTUçœ=È4‹Wχ¼Xè8êv»]ŽÍæ„›]hÈÕ"S[kkUªi“Ú£ü =|šVþ~S¢ÓäàKø²{|éÎlš+^’>I3Š-¥újÆN/Å—â±$CÒiÇÌ»7lå]2‘¤+±­,­½¡îy²½Õ8þr—i!­@>ž`;Ëü­´ß—˜””t_RÒÔìüª´%ÿ±ŒÄþú  Á‰‹™/-÷öËq‡µmìseiXàK|	_v[|Iͪ-zò•—R‹)š·µFŠÏÿ
=ÕœTO­¸Y®ÏõÑçóQn0úëÌ»ô­œ3̶¢½Ý•q@_¹pä&6j†ýµ)aç0ýשö€FÄ»zXYüü¦oÔóº’e
¾l„/ð%|y}¡–ÕÓM£3·ó’àKi™5œj}g%Y>ï\FËyj§9I¶Ï¼›rM;}Ô=ÙDËw˜^ö‘ɼkhÍ¥Îó’,U»Vé[±½±ú
û|µ74<¨•†ùÐËAæ²æoà¶=MåwŸ´Ž Ë&3ñ6-¾¼B¾L³Ô±ð%¾„/¯#Aÿ³éFÖÎ9*½€µzr'>¾(sÜVÿºí[ÙÓê¤z[Æã쯷&<·Wùå»BEñ[z«iVÑim«‰7šç¤'ö×·Þv6D(GUY¼ënç¹fÿTuØ-ÙtNvšæËǦŒEbÝ™ø_—×IEIŽV/ª•?êPíµºY»ä¶[…ôÞÐö¡¯§rñ
ÐŒqŽ_—=šLgˆþ‘.A?õc¿ù‹Ø¡}γÊ>mx¾ì;È~¯‡ãƒW¼ò—}Qf‚•=Žw5î,À—|	À—|	_€/áKð%|Ùz7NhMÈÕéBÖÈäÍñýø¤ºøUúféDk¸~—`¸Ùçv9]a<Þ¹»nÈ·ŒÌ¹]>)$úÚÜI‘;å¾ö+^pº*b½ã”d&)œ”-Öæ—?q§ÿs.—2­"¾ì™RZv
šœ]›Ç5
-b©:'ûçñìªÎ½z’9ß{…¿à¼ÖKÓ/Áp-Êœ´&”\Sˆïl'=5—ddþKö¥¦ðßo›êøôw]Süç$®‰õŽ·Hç^™RìÆ~æÒ¤ÿRHÊ3Ýb˜”_ö0ŒÓÈuÍ—ž})©ŸžežØkÜWu’^š~	†ki3‡{ƒw]ÅöOã9Û‰ÔS}I¹Ïò¼zªå=’Ïé3Ý_4ZÑ¥«~ǵû&©ÙÙàKàËž)Ë/²(ŠšCÕY[›œÖ鬿ÁäÙý“T(ÏNÆêÓ,ûÅv¾¬soHVçw½ù¾§×»k˜/©&£°MNû`ê;^¡™}p;¬o°]=<ÃÅ+•4Qû蔵]tÍøÔE¨9¥Ù¼µr[_ÆZAæK3SÃg8ÍzPniB¹Å<šÕLÊÞ.tâËÖÔ+¶qƒX–¿kCjÂÍlÛ| é5ŸúHÙ»ú›ó½¼à÷|HŸ‰£-%FÙ¹­ôñ7µð /Š'm¯(éG¸ }zÒé$WSç?•9ôV–ù„&Œ¥ŒÐ›=u¢py]úîºØØÊò_>cÙíø2U<;}ÍF_ÆXAI`2 ƒ²¬Hužê¤}Mm/MÉ6 y'ˆuœ2u{ZQUG¾lílS’Z+)?¥rºð´ÂAÊìóéh2÷ˆ»ÇÎm|Æ&Ž8§šž¥ƒN»oü­ö:>±Eä>qzëXUÅŠßÎ<j7=½v·£ÜU&Åþ	/;<^Ÿ_éªlñïfÙiØ;N_&ŠÜÊóc5ßEÏß°s¶m¿äÙn_]÷CZyŒµT93¡òcgɘs:¼|3>€/{z{,åö¢@Aÿ‚ß"—«Ík9)ÉmýLOÓØÝ1J²ÌÔZœL£68!mè9¥k쯶íÛ“)WkK-bôûUQ²l²Ô%_F]Ailh^ë—¤NÚceš°]rÌy˜ÅFQ}I‚œ\¸ßív»\Nkúò„±ïväèumÛc—+w&|#”4Ÿ
{ò¦„ÎYÎÏbû2Ê]e®+½_é5ôÎþ e›¬µ(°†Zä¾Tþh©Ü®º#ø¾üvÐUÔ"K2Ž}\RË$	’šËtÕÑK–¢RwŒcæÝ«éGŒ„?.µ†Í ¶²ä?–‘Ø_MÃ2s½Åj<_F]AòÑó…MµìÚ^ás¼ÏšÔ,+Ñ}9n é¾û’’’KHüµyžšã“¸Rœý¬qPÛ„ ¡(çF©¥çúÀØyáKÝdíï*[ӘЛu^Þqýù©WZ€ÝŸ}ÍÊø²ùÒÂâK¥ÝUêBŸ§.(¾TsRz´ø‘̧¼4Ä—´‡!æmú¿²OGøR[Yi˜¾IP÷t/ŒÐUÛ1D­]‰F_F]A™DjèKÒš[[/MmMÍrT±‹pÎüqÄÞÚµÇ6EÜ%êc£ØÑ¥N7޼õ³o{­¾4æ>ëi¹pç%ûªt?¹S3™kÎ#mLf¸«ÎÓ;/CZ|™Ñ>__öÊ–Œ½3a.'(™%]ó~N}Q.@–êíÙO±ßDR;m†é¦Ñ™Ô%øRZf=‘ºÜùJ¼e?K{¨q.Ö;º¢ùRédÞ(ȲğÉL¼­}|y¾¤3$ÓO²–Ð	4åô	>MѪ_Z³z2Yvò¥\ãZEfñe¤ƒ
­Ð.0$_q¨£Ø¥ï^ïò%§u^ªÚ»H7n (Ëuž-t¯èÌ£ÞÕH_j—!­ÿ’žŠÈéùÙ‘ý3åù‘Cð%ðe!èS†ð°&VjC³M£ùthývAÿ6Ì•
kôˑ͜}¾ÞP™UtBÖB:ýWêúÊÍ~e¸
e:';M÷¥Þ‘µ¹ÕÓY{ls™ÞÜ:>c-;Cã¥UhÃVi¼É’Œ1c4_¶;nSô_5Èõ¶ôl“-d'Þ·hßÛƒ}ÙÚyjûÒ¸VKzøþ´¿«ÎÓ;/™/m÷c=ÛD8ÆB¡˜¾Dÿ%ðe¯G–$QŒòSµºƒ_ÖÉbÔÍ¢~Zw¼§«>qÚ­Ôñ…I×|€¾0
5¶?Óþ——tyBûùu:º«ö)ÿÌ:/Ûm"ažàKz£‚w¹q×UJ×Ðy	€/è£2"@àKø|	_€/áK¾àK¾ìe½'˜×Šxʾ„/;€%Éð”|Ù—|¹eË–ùÑ ú«ôe8m=ø²ùR„DÈ’j¨¾Óm›ùp’,šüsGñ{R
Øœ¨w&.Ç龤åx6QÒHæÎr:2Íâ
Z½Á” èS®/Ê|6Ü›úŽÛăðeïËþÄ?̇¼H¹=Z´pÍ5Æ—zÜp/¤”–\kP)‹ÂkÊໆ.ÆoN¾ì}¾¤>¹¹¹ñóaP.CJæ<>{7/ÉßZ6ö_ŽÎØä—dÑŠú8gì£õË
ÿ0 ñNñhÓž9ÿ2dÜŒ¡ø²Wþþ’çù.­ð*ÃyÈŽPγ¤iñeþíI³?°†‡ÂÒ€ ¿\¶¥l0­R™ð²Ã‡öX€/¿CóÈ¢(R¤Øì]Âú/[ÿ Iê_Ú®-‰í+À—ß•ù}î¹Æá?àKø2R=çãñ[€/áKðå7ëËÿ3¥§ø¾DAAAAA/QPPPPPàK”NÊØµ
†/žŠµÂŒKÜ—_Xs>ž]½^B¿ýjþŒ
ÜÕëV*^ßZ»aïg›÷ú_L¯ø×Ù—VïôQý[;kßœåµUÎ)‰/ów×	¼µµöÍ–Ö¬^ÁE]§ýYé'ÐÉÃv}Ž~íå÷…5ËVœ¿grÕ²­¾G'Ÿ}dî¥õ}FïÂêÕâ™D/{]ÉñüýÊÙ«ùLœ°õšQ/æGجOÿ
ÙÂų«´­‚ÐxÕŒ·ãz•{&Ÿó|
}ýµÐ(-~­bÂVšÐ"ø‹É•žPèBñ…X[½_õµ|ñ³î:o(tnÃùœª„|ŸÅx¢"ÏJ?N¶ësôk/ï_¤Ãýíÿ¦×È!édýB^hj¾¤¡ŽÁ?â±D/{]É«’å‹»_nìè#잊/Ë7TÑ2¾J÷_²·CïÈ
î„*c§yÿjŸ¨'@Ç*_s>§"æ>ÛŸ•~?l×éèÝàKåükÿ-ýÓÀ×¢.ȇ×^¹–kA/áËoI–ž¿k¿íùjù¬
úXY_ž$On’¿n ý×¹—½ÿ`õ|ÿT;_¦mm°?Ý|dË%æKªñ•}QÇöÖœÿ¶—}rm®j‡øûšw½jk›ð÷ÆÆ§Ô…@£øqEø¬|§jáÚnô¥®	[±Ô¿Îòy´·¸¶¢îm}ë]‹úf=2ß_ý%{¾<|\dí¨ñExvñe„/Ï}Òøû«µïd—ëBÿ8°¢ŠÉá‹_±'y£åÂæ‹ÍêrË™ý¾ÿsµG§vÔ½—Ù>C•GøOäÒ
çcÝ«ÿ3¹Rÿ·ó÷† û·_ÆÕ0ƒ‚_öÌòȬöÚȵ
o¾{þÙ¿_AŸ2_¸¡úï^þ„§O„¿¿i®ø·É”<œ
ù¾±Ž>T¾<÷™Ñ—c?W>8Êê^œUõþ)å#ãÈŠ*ò¥:'ßW[V\zÁRÃQc`m½Ò£³“vÐr`ÃÅ'ß¾ää[B_‹O>A&l¤¯Þ¡+Uõ¯¼}á½’&ZþÐZ‰'ÝîËGæ^Þ¼÷SÒÛ[{ëæ¿ë
¿ÅâbËùÖ*“C}}îoF]E×¢½Y÷¤_ô+OK#=-olý\qé—Õ
ïîýìÍY
ýÖ\Œþ4¶=«¨ñeާ9ôecø[ÚGtпS3>;¾¢îÅ·/9j¿ÖÏjs=Ï_ÍRquG_uQ¹;7\úCÞ§ž&%/õ/ĺWyê¿[ªŸœuÉ­¬¬œØï×Òá¸{&s«Ô=ÇÓ0ƒ‚_ö‚öØ›¬|Òé=7ÿ–~YmP=¯~ýcùk†oÇÍ46GÿgO{5^yTX±³öí·½,¾<³%<ÞgÚ!òh“¡Ï¦â‘ô³iô)þäÕ}ùû Q?â•|Ù•ÝÔ“_}Ù®)²í[Lƒb6^ŠÖÛþ]‹|³ÔÊÖ]=»Wd+_C{fÛöع#[my—ö_éhjËj´¿J/šõÖÎæ¹fõfQ`÷5o^Í8²{Ò/Õ?Ö¿@¾Œz¯Âÿvìá•ÿuÆ…U긪«èÈ@A/{niýLœUówƒáX—}ª‚¶mMR>ƒôöEµ-_ž«Ú©÷«­üDžÖXÇPƒ6¾Ô>^õÀ{tÝ}Ùö-nÿlÄ|×Ú½Y»¿S¼7D뿬t6µ\9æ£NA9,Î6g¢œ€~VÊCx•¾Œøç@aeu(ÊF]ùZ:þQPàËíKÖ Äš*õˆt_€}@(_¨¿^<¥Â`¾¯•1–Ú?{ÚC¨¡¡u}Þ¥gx#|©­\aoh	ñWþ ~õ«ô5µ‹/›žŠã#¥}IýƘ鑹ß°TtÕÉ»fÜÿ…
Ê×)mWJ“i÷Æ—,fý²ñ½CÁЗ_ü¢ÚœÕ5ø’"fêòôÙ/éF”Õç9ê½báµaTmåK/=‰ø¾ìkí±rèëàÛoŸ{4ÜaóåjKÕ£3¸beYùM$µ5Ñ7ë¿_n >9¿¦:î‰ÔÿÙÿ^ùÆ:s°†ö0}¯²||MU_V:[B
ôÉë}bþ§Ü—ÑâKøò÷%}7¢¶G¹öÊ3*û©2DëÂg]uò®÷Ïž–PSpõŠKï}ôE¨µÿ²mgáüO?>UÿJg¿¸êKÖRªœ£&³®ú2Σ¯Wþ	üã˜ýÓ7Öþ…×Jÿeô{U±£–ú,¿Ú`¥_[žS—¿|Ó_¢À—}«<±´NÚª|¬Ð×d'ÿµ>bv‹5üóƒ'ò>«ÓjÿÎ7¾’ÙöÖ¡ÖÕŽ)ã$iì"í–'4®üHÞgZnÎ\¸øeDËÚc¿™ß“Dí’÷7ã[ü¦úë}Û¿koùÌÍÊ5ŠEï¿T‡ê°‘8qu®¥ŒÄQò|©oÞ¦=vcçí±q,¸êTP½’ÙRãþ²…]`Ô{¥üÛ©Õþí|ýÕÎ1Ûfñ{ø²
šqîÉY碘uFÕ“3:˜÷¤âÉYU¿ˆSÒ³ªžHÇ­þÆç+hÎT]y3v\Õñ[Ï»vOú…ÍÇùùÚ/‘~¿·)VÏhˆÿü[새çè¯ïä·l¸¨÷Ljï±îU¬;ávï¥;SÕèUFžc¾ø¥‡–ʼCõŽy>%ýºÎ;¨ŒÇQ~øxêÊ)õÇ‹¼ÛEÞT°ú[ûêßѧR~rzåbãአûaÌ‹×6ÕÃy5‡=WŸº²÷£OñÃbøå;_Ò«–}Ôpæb°²ê‹?v¬˜¾öò+³¾­é‚»pôéÿv¬ª©òbàð!?ZPQàKø²3_†€|	À—|	À—|	_€/¿-_nÙ²e~4¨o6ø2Œ ,ˆ%ÕP}§Û6óÇ2û›L¦þ	/¯+zw‚y-›’µÎ½!ÙtÕß|ßÓëÝ5áµÅJKÊ0“Ê4ëA	À—½«=–N:—TÓéV-òåtÓ÷ï0xy¡Ú½%ÉtÃàÄÅäË ·•Œ8µð /Š'm¯Ðòz.تÍ4Ý|[ê"_¨óîºÏô½á–ãx˜¾ìM¾”e¹  @—%-SM§[<ù7™Fº¥ö²Á9wðÐ…äKOîØ!©µíeÎåâ„æ€g¹qeÑwÊå©ÁÃðe/ïÃqœîKNÉ#Û9wþ`Ó\½Ñ6àš{—Iñ¥cæÝ[J;^|Ù[ÇDz?ñó	r)dti!cc6‹/Ý_š·é«	~/ÉAïc|)µ>À—½Ï—4À'777ža>Œ–ÐåÓM·'¿ãâ|eŽ÷©Ÿ’õ_6¸ói9Ï~–šdkœ‹iy¥·©E>g6Ý8,c/…š…RZœ}À—½ò÷—<Ïwiýù¢5}<‘ò²Ïgñ%ÁÙç›4²ŠN°¾ÌfÿÒ$«•^à“ñ,|ù]˜¯@®uÙ½‚>ÞgvÛJYÅö?‘$ª…*¾üÍï#ÙÆ
ºÁ”`±Ù¬™“(jL³Æó¾lb^q;6[²3³-+œÞ:<àK¾àK¾àKø|	_€/áKðåwÞ—lŠööÄ?i;ø²ïû’&g_°`A„,©&®IÛÅJKÊ06ì4ëAš9¯E*Ÿœ8ågoªéªì—<Û£N¶«|ÙkÚcé‚#|I5nÕªÍ4ÝL³´{üBw×}¦ï
·o‘J“M7ÜbúU±§F🱌H¸Š/£×€/{/eY.((ÐeIËTÓéVÏrc:LÑwÊå©a^Ìq5†*#®ç‚±êñ,|Ù›Æûp§û’–ãÙ$àÎo›ÌD¡TšdºÁîoÖ¼XB^Ìs«Ï"À—½l|,øÿ0Ÿ w1¾”…ZŸ?Àâȹ¹¹q
óaΓÏQîèa›x)Ô,”Òòàì#$BÑs{Â·? Kµ¶ôM¯ùUAF­_ö¾ß_ò<ߥõ›ýGH“l|ì¨ôŸ¬xñ1S⊢Î'v¡|‰ùcÀ—ð%ø¾_—|	À—}¯í•´ÂÓíª¥¢”!wf쾎–êÝN§+Œ›ãÅk>gÀ9·Ë'©Óñs
ôZàNâ¡Ð·û<~†|	_^%'sÿcxö‘ö6sÌ{aší::‰æŽ7µå¢Þ£&[Ê襞ÆÏ„ïUŽéæOcEîÿ½+S¹Kîy÷ü0óx‹|ü!Ó,$t¾„/¯wîØáÙÇ¿ùã¶ÍM&Ÿ´½bœJ¾½¿­÷öÏq7Eœ³Œp)š/é^åy+–<Áîݮ٥-ré“÷"*ð%|ByvÊ0Ì¥Yö³POîØQ™›Š2§ÊL	yŽKl]µ²øRrZ§³­3Ïóa¥Õ¸7Pþª¤”Ô+]5ÚVÓ§î)LNõä?VϽòy­ÖÞ*;æülRáé°/µé‡ZärÚ›A69¬o°Ã=<ÃÅ7·Håé¦ï³š©bøœ×²£ÐÑ×»ëðÞ"¾¾„/»‡–Pm¦éæþæ|//ø=’œF[J_.ùYgjáA?ï?Zô&-¯÷Œ1œgÉDrR‘»Z/[Ç
dIN‚ÜFZóu[	/ðhy¥º­¬ì­è(Äi}–wúš›ý»iÁÁ+j$ù%«iÅ"r_·G(='í¤Áµ€´½ÙS'
—×¥ÿ计‹ÅÄûÏd½õõâÓdš)[2vȸ5ÚǨLÃ|ôFiA–%þLfâmZ|y…|™f;!©#báK|	_^G‚þfÓ¬sTzkÿôäN| }Q測þuÛ	¶²§ÕIõ¶ŒÇÙ_oMxn¯òËw…Šâ·ôVÓ¬¢ÓÚVo4ÏIOì®/n½ílˆPŽª²x×ÝÎsÍþ©ê°[²éœì4Í—!M‹Äº3=ð%¾„/¯7’$Š’­^2T+Ô¡:Úku³vÉm·
齡íB_)Nåâ ã¾„/{4™Îý'"]‚~êÇ~ó±Cûœg•}Úð.|Ùwý^ǯ&xå/û¢Ì+{;îjÜY€/ø€/ø¾_—àKø²'ônœÐš«Ò…¬‘É›ãûñIuñ«ô+ÌÒ‰Ü)×pý.Áp-²ÏírºÂx¼5rwÝo™s»|RHôµ¹“"wÊ}í7V¼àtUÄzÇ)ÉLR8)[¬Í/â:Oÿç\.eZE|Ù31¤´ì49»6kZÄRuNöÏãÙU{õ$s¾?ö
1~Áy­—¦_‚áZ”9iM(¹¦ß!ØNzj.ÉÈü—ìKMá¿ß6Õñé5øÏ?H\ëo‘ν>2¥ØŒý.Ì¥Iÿ¥”gºÅ0)1¾ìa§‘ëš/=úRR?==Ê<±×2¸¯ê$;½4ý×Òf÷ï.ºŠ7ìŸÆs¶©§ú’rŸåyõT3Ê{$ŸÓgº¿h:þ´¢KWýŽk÷MR³³Á—À—=S–+^dQ5‡ª³¶69­ÓY̓ɳ=ú'©Pž2ŒÕ§Yö‹í|YçÞ¬Îïzó}O¯w×0_RMFa!›œöÁÔw¼B3ûàvXß`»z y†‹W*i¢öÑ)j»èšñ©‹>PsJ³ykå¶¾Œµ‚Ì—f¦†Ïpšõ ÜþÒ„r‹y4«™”½]èÄ—­©Wlã±,+~׆Ԅ›Ù¶yŽªöwvrgâÂCÚºiÖƒ=ÉQâKº™Øñj¢˜ÉCŸ×§íÕƒæöw•Öœ:rÊÅK©†ÝJ9NÉP7ûšÙ;ži+JO¸…þÚ?)üæê;gÛîq¬¤àl²bŸÄâË…ˆ/€/{:²X_<ó'Ã2¶ûx^ITiHÓ{ª¾²0}ø@Ók>õ‘²wõ7ç{yÁïù>G[JŒ²	r[éãojáA^OÚ^QÒpAúô¤ÒI$®¦Î*sè­,ó	MK¡7{êDáòºôÝ5t±±9”å¿|ƲÛ/ðeªxvúš¾Œ±‚’Àd@eY‘ê<ÕIûšÚ^š’l@ò"Në8eêö´¢ªŽ|ÙÚÙ¦$µVR~Jåtái…%‚$”ÙçÓ%ÐdîwÛøŒM/pN5=Kvßø[íu:}b‹È}âôÖ±ªŠ¿œy ÔnzzínG¹«LŠý^vx¼>¿ÒUÙâßͲӰwœ¾L¹•çÇj¾‹ž¿açlÛ~ɳݾºòk©rfBåÇÎ
’1çtxùf|,_öôöXÊíE‚þ¿E.W›×#rR’Ûú™ž¦±9ºc”d™©µ&8™FmpB8ÚÐsJר_mÛ·'S®:×–ZÄè-ö!«¢dÙd©K¾Œº‚ÒØ8мÖ/I´ÇÊ4a»ä˜ó0‹¢ú’9¹p¿Ûív¹œÖô1ä	cßí ÈÑ;êÚ¶Ç.WîLøF(i>'öäL	³œŸÅöe”»Ê]Wz¿ÒkèýAÊ6YkQ`;µ6È7}©üÑR¹]uGð%|ùí «¨E<–d0û¸¤–I$5—骣—,E¥îÇÌ»WÓ	\j
›AmeÉ,#±¿>š†eæ2z‹Ôx¾Œº‚ä;¢ç›jÙ-´½4ÂçxŸ52&¨YV¢ûrÜ@Ó}÷%%%=–økó<5Ç'q¥8ûYã8 ¶	ACQÎSKÏõ±ó2—ºÉÚßU¶¦1¡7ë¼4¼ãúóS¯´»?7ú2š•ðe/ò¥…Å—J»«>Ô…>O)\P|©æ¤ôhñ#™Oyiˆ/iCÌÛô
~eŸŽð¥¶²Ò.:0}“ î-è^¡«¶cˆZ»¾Œº‚2‰ÔЗ¤5·¶^šÚššå¨báœù㈽µkmЏKÔÇF±£Kn>yë'f9Þö[}iÌ}ÖÓráÎKöUé~r§f2לGÚ˜ÌpW#œ§w^†´ø2'¢}¾¾ì3”-{gÂ\NP2Kºæýœú¢\þ€,ÕÛ³Ÿb¿‰¤vÚÓM£3©Kð¥´Ìz"u=4¸ó•xË~–öPã\¬wtEó¥Ò%6ȼQe‰?“™x[ûøò*|IgH¦Ÿd-¡hÊé|š:¢U¿´fõd²ìäK¹ÆµŠÍâËHZ¡]þ`H¾âPG±K3Þ½ÞåKNë¼Tµw‘nÝ@Q–ë<[è^Ñ™G½«‘¾Ô:/CZÿ%=3‘Óó³#ûgÊó#‡àKàË>BЧáaM¬Ô†f›2FóéÐúí‚þl˜+Öè—#›9û|½¡2«è„¬…tú¯Ôõ•›ýÊp6ÊtNvšîK½#3js«§³öØç2½¹u|ÆZv†ÆK«Ð†­Òx“%cÆh¾lwܦè¿jëmé#Ø&[>ÈN¼5<Ѿ=¶û²µó2Ôö¤q­–ôðýiW#œ§w^2_þÚ4îÇz¶‰2pŒ„B1}‰þKàË^,I¢å§ju¿¬“Ũ›Eý´îxOW}â´[©ã“®ù}ajl¦ý//éò„öóëttWíSþ™u^¶ÛDÂ<=À—ôþFïr㮫”®¡ó_ÐGdD€À—ð%ø¾_—|	À—|ÙËz7N0¯ñ”|	_vK’%à)ø²/ùrË–-ó£AõWéËpÚzðeò¥ ,ˆ%ÕP}§Û6óá$Y4ùçŽâ÷&¤°9QïL\xÔþ^xþÏÌíÚŽ®Ø-/„'ƒ5/òŠ-x¾ìMí±tÁ¾¤šN·bùCú›ó½¼PíÞB³]k“˜/'#ÞžüŽÇÏW{vÑ´à£-%´~s6¥Ú $AñBö½ýXædðe¯ñ¥,˺,iYŽcÒ2ò"åÇÐSøÖ9fk97–kYG\sYê¥óE/Q½Ã×€ùоì­ã}8ŽÓ}IËñl¢¤‘2Ì4ätdšÅ´zƒ)Aѧ\_”ùl¸=6õ·?ˆàËÞ7>–
ü‰˜y‘r
z´h1àškŒ/õ¸3à^H)-¹Ö R…Ö”Áw
]Œßœ|Ùû|I|rssãæÃ \†”Ìy|ön^’¾#´l쿱É/É¢ÿõqÎØGë—þa@â;œâѦ=sþeȸ5Cðe¯üý%Ïó]Z?àU†ó) œgIÓâËüÛ“f`
…¥A~5¸lJÙ`Z¥2áe‡í±_~‡æ+EQ¤H±Ù»„õ_¶þA’Ô¿´][ÛW€/¿+óûÜsÃÀ—ðe4¤zÎÇã·"_—àKø€/ø€/øt‰ wãóÚ˜séI²F&oöâÙUuñ«4WŸWBf±ë‡ìs»è_”ÃéVO‹—?q§ZÎåò‰Ý3˜ZàNâèí¾âvŸ§=ÊÂe:áòTc´6ðe_À»âÅg­§¯bÀ;?bb#-bi’é†<÷çñìªÎ½zM?„7ã:Òd¹·ß÷ï÷LêÔÂ~¤+…¤<Ó-Y®Ï»åîy÷ü0óx‹|ü!Ó,úùoÛ•šœššt+~
|ÙGð䎞}üj|ééЗ’êKO“Úà.÷_²·CïÈ—Ö{û縻ɗ¹cGd—¶È¥OÞ»Pd³wy	¾ì=²\ñ"›H–šCÝJ¦Ì&§u:«y0y¶GÐH…òì”a¬>Ͳ_lçË:÷6íÍ÷=½Þ]Ã|I5……4ÿ»²·Ôw¼B3ûàvXß`»z y†‹W*ƒÞ5£S
Dua|ê"}ÎÛ×m'àÚnô¥®FJV_6óÇØ¬Â4¥ðº¢w[[ÚÅJ‹öÖO³ÔfP”ôçä1ó<öœDÄ—ñ4B®Î—‡nïKª„/¯#²X_<ó'Ã2¶ûxž>
ÝÖ‰”¬ØS-ð•…éÚ^£üÒ-¡ÚLÓÍ4]»—üžÉ‚£-%F_¹­ô¹9µð /Š'm¯Ðòz.H¾L5Ý@vp5uþS™CoeÙQ\(
çfO(\^—þ#–MLÿTe9Už±ìö|Yñ[´¼Ó׌'ÝîKY¨üØYAßE8§ÃË7·È—ÓMß¿Ã\@oqµ{5°7ì­¿-u‘Ç/ÔywÝgúÞp‹ÒáY¢<'EîjQ¼l7žjK¼Ÿö6„BõŸ¨{ާpu¾ôx<í}I•ðåu1µöØ–ò¡©÷fµÈåjƒjc»<šùýLOÓØý£ö0$u£ö)ÓNhfñež»‘ÕÖØ_¥•
ýX²,‡ê\ôT*zŽköá«ROÖ9ÝÔ»_}Ývã[ÜàŒžBUôryjÂωSÛ•Tëbcˆbì¾ Û}ùÅ_”””}yôèQª„/¯/nÝ—â±$ƒáè–un‘ C6è%}†ºÄV_:fÞý¸¥4b·áþKí:¨­,ùéÙÄ-Ug«/Ù'µñð]w_F¼Å®¹á·£m}ø|N:¾àzø’)“ÊÃ*gΜilllÖ€/¯§/-,¾Tßr´ÏAJCM¢âKÏrj|óh™Oyiˆ/iCÌÛô
~e®Žð¥¶²\üü¦oÔ½ÝuMF,túºÑ—An£òH‹#ë³Ù·êN6Æ—²PëóXÜoU+ù|1“_p|iDV/¯;eKÆÞ™0—$úÄsÍûù¦—]þ€,ÕÛ³Ÿb¿‰¤ö·ÓM£3·“|)-³žHý£°ÁO‘bžý,í¡Æ¹˜–Wz›bøR*J2ȼQe‰?“™x[ûø¾üæ}ÉÞâÛ“ßqq¾2ÇûzÜOß™h¸Ö°ŒMÔ¹Ý,”Òòàì#äMûÌ»éÙpúÈM´LÏŒñ%ðeŸ'èS†ð°&V
lSÆè#f¾`xÿ6Ì••^à—Ã…zÛ)gŸ¯7±f)ƒZ[¤rÚíRO£þ¹ÉVnöHUGÒÒçd§é¾Ô;2Ñ{ý|©ÿž$Š2å‹ÖôñÊûžºè}¾þ.4ûßz_8ެ·e<Î*oMxn/sV
üžø²/#K’(JíëÕê~ß!‹Q7‹F'{×Ç—7šçäYÖùÚ¿Ir­£Èîôñ>³#º-£¾õ±ž“ð&¾#‹u^úpÌW|	@/BòØ‹‹Šl+wø£|S‘lãÑï|,6›5s’ò+[Ûék<žì?e+´;øj|	@ŸiU¸âvl¶dgf[V8½u¸À—ð%ø¾_—àKø€/ø²GA	CZó1€/{ /·mÛvåÊ•o÷¶´yYÀ—=Ô—óçÏÏÍÍ¥Ô*tUßÖmmƤ_ö|_2


8Ž‹s«Ç|š´Ú­ÌàJ3vî{Ì”X¬ÌÝ%‹=Ml¦W>˜<[«É4ºš'«ÂËëlo´ÎÂ*Vf§Ófv=gàËžåKFÜͳM4!™šK™çs¸’"z{·U©,öT|eaúpªôiù%ú›ó½~¾Ú½…ƒ„óK¨)ºîH_Ëñ‚ϵá>Ó÷²œŸá±ø²Çù’X¼x1´Ó
[ÄRJÜ1.ue×âU¶Ïb_'«•ZêÁ¹\É™åi¤•Æ<…Ê|ÙátJ½Kh¦	³)uÎyxPòr	ÏÀ—=Í—[¶l„xÓ3ÔØgQ«éR5éRÔ,öí*ï”4X†,ÁÖt’ËMm˜œ~M€/{/—-[VUUÿ†”€ÚT’n¹3q¡j¾(Yì²Ò¾š£ù’ÒùRŽIÕ—Ë©‘Ö£¥¸°ø2è]c¬_ö¬ñ±‡îêøXÇÌ»‡¤nlÕ’5'žŽ•ÅÞ5ïç´àòd©Þžý­à•ZHœ”Ôwtæv^’j‚ßpÿ¥|ŽÚxÇgïä,Tf½u‚C~¾ì¾ìR¬Ns‚.u°kÀ³šN‹”ñ±Q³Ø×Û¦Œa•$K‡²šSr»(Ö¤Jê°ÌµLc¾$‚¾©j½2žÖœïC¬	ðeŸœß'jû©íe¥6š•z	ªøóá€/áKð%|	À—|	À—|	_€/¿³¾r['˜×~ÓóÄJ²F&oöðX|Ù9q'ðºŽÜ¿ù|Ñ”_E¾ƒL,M¶”ÑK=xî¾Ï{ôèÑ®ÎÛ4kùI¾Q_JúRR³©4á¹ø²5?IAAÇqqnUã˜O³¨»EeþØfÿ¾ÇL‰ÅÊİ’Ó:Mýú˜yžG`é-›ôÊ“gk•!™/ÍHìO•ý^^g{ƒå'Q+³S†±õ³ŠbO¶.”[Ì£Ùj“²·³	p½+¦O-ÜCY©Ù´´+]5¡Øõm}Ùz’£Òü2ýµœ2w†sŠ¥þ}£LO»´“opå?”¸Ð¯ž†~¶i–ýšò¯Ø-/„÷f^ä[ð/_öµü—q7Ï6ÙÆ
bÞF–{û
Ï>BUž%iö"wµ(^¶Ž8ÐôÅmU*‹=Õ_IÆ¢JŸš\š²šô7ç{ý|µ{y+œŸ$¤äÿº#}-Ç>׆ûLßËr~íèrñó?¼ˆÄ:N™Ÿ=­¨Š)jjÑQ^ð;­Š±vúšcÕ}I+(sÁsu‚ÿLö¸ƒÌåÄûÏP‚”׋Oó<éøJŽéæ´âKìèE)C†[޳³U®‚öëù¦m)	)“ÑÏîgzšò´ÅÙÚÍø²Où’X¼x1´Ó
©ÿD5.uÔ	syUe9µ
¥Z—Ó]'«•ZR̹\Q”§‘ò_Rœç–´pÍ9›Å—¬Þ%4‡$šœ]vÎyxPòr‰bQΫÃù
#tdš”]rÌy8,ìܱƒ3öiSZSÇXNĪ×}ÉÎ|šýÛ];7%(dÙ­Ãý—Õžk¨*u5	v±¿9â*î|Ò$e+;_ôÕ;|
˜0_öY_v)½W}ÅjK=M!Í"yîÆ¶N¨d¢|ÑùƒMsõõþK2©-“óÅhK¢×LPès¼OÑgD¥;w,…}úÑÝóž}Ÿ/ +-–zˆFé ÉLª/—S#­G‹¿®,¾z×ëcZ*§ýd9ªØŠÎ™?f^¤8ò®Œú	ŽÐA½¡=V9óWûšùR—½Ò<¹è5ƦÙ?
©v7ž-Y_y)齕²(\°¦frø²/Œ=|øpWÇÇ:fÞ=$ucs¨–¬9¡æÈö™wS/ õÛ‘ih™QW¥kÞÏiÁåÈR½=û)ZZ,IœfÓ£3·ó’ð¡åpÿ¥|ŽÚxÇgïä,TR÷áëéh¾TT—e'_Ê5®Uö±ø’õS.už—d©Â>Ÿ–×{›bÕ|)Û§üóí	3Ü<‚M‡,O±NVê³$_¦ÙNH²¬EËYôɤÈzaÃWA×L7±Vß²Â?H|‡SÖiÚ3ç_†Œ[#៾ìí¾ìR¬NsÅRl¼hÀ³š,R¤Œ­·e<ÎÚ!oMxn/Ç:ëmSưJeL/Ü8àv±VPjÃ̵Lc¾T¢4Ÿ2~'<žÖœï‹kV¿n;Mž½$cŒÖO9ñFóœôÄ~ááµÅáÛµž©ÚÏ+ëmé#ôÆØÚ$Û›T£Ý%AR$úPæ~ý4‚þ${ãÀZe5!<ô—þÕ/àKÌïÓŠ,I¢(ÅS©TSm4#*õ’Ç‘ÚìSí§,
o.w^ßIvŽm¿Êµ‰,ð%|ÙópÏ»ç®Ì#ñ×€/¿‹Hüe/Æ_¾àK¾„/À—ð%ø¾_—׃ ·u‚yí7=€Uº52y³7Ðn À¶fg[¬ëœÞº(ê?ãt89¡ÿ€ðåÕw¯ëHÀ½ð[È-vš/ºÉ–2Z›¨çRíx›&ºß<3=UÉÄùzq›I€Ù¤}Tm‚\€/ã†Í{ôèÑ®ÎÛ4kùI¾Q_JúRR³©4õä'’®‚fõ›V~0NZÇÒ¤ƒ\›¹&þSÒËæ„›;¼R€/ãð%£  €ã¸8·ªq̧YÔÕ¤W¡fÿ¾ÇL‰ÅÊ,©’Ó:Í›ú˜yžG`™:šôÊ“gk•”Ó2<É*ͰºÎö†>GkH¬ÌNžèµètÌ3Ê-æÑlµIÙÛÙ¸ÞÓ§ÔlZÚ•®šPìú¶¾l=I6
,Í.KI1Ã9ÅRÿ¾Q¦§]ÚÉ7¸òJ\èWOC?Û4Ë~MùWì–Â{3/òŠ-]ºsöº3,5˜òÒ²"3ñ6Zç¡ôMu™Œ¡ÿ¤Ü´¤.evxšÈ÷mšž©³ùÉê}õûEÍ—ÍþÝ´r±¿ÎöÓ9ð%¾ì_2ânžm²4ļ%½
§k^2‘&a/rW‹âeë¸ô9NFq[•ÊbOµÀW’±XêÖHØßœïõóÕî-ä­p~’’ÿëŽôµ/ø\(ñH–ó³hGWRk
H^Ä	b§ÌÏžVTÒòL-:Ê~§U1ÖN_s¬z£/ie.x®NðŸÉ7`y#¥¡æýg(AÊëŧyž\v%ÇtsZñ%vtJéE	5ÙÙ*WAûõ|HqÞhK‰ê°Ù4i;åi	вµ›Ó¥KȶŸä|~I{isWóÜašØýSB¡ë¼r’‰·³þhj\Ê…²£0,ûÛ“ßñ´ê¹É:òõè,P†/ðe÷ù’X¼x1´ó–@±”>åÇ¥Žº3a.¯*²,§¶¡TërºëdµRë9k‘ËEy)s$ÅOn-Udƒs6‹/Y½‹F¦H$Ù9çáAÉË%Š™8¯ç7ŒÐ‘)¦’s;w,˨¥·¦jyK¢Ô·æ‹VÏ|šýÛ];75_´ª™pÿeuñŸY&K–»Øßq”/š4IÙÊνDõ_ƒ¡Y4ÞKP¦†Ï6¤¶6¼4fñ¬Xñºc‚"Ô?&G§¯õ	¢ÈŸ±¤dšågmöW©
€câ„/ðe÷ú²Ké½jì³”¼’ž¦f‘#*Õ<$ÙÌ{”É&j}«/ÅcÉZ1=¥ó¥š/úsýZ舱¥Áñ&N¤ñ*è%kD
ÉõE™Ï†ÛcSßqûƒêС¸/!†/ËeKƲs TÉÇ©™¹…ßG1(}›QRj;?U«ëéB´e€/¯Í—Ë–-«ªªŠÃù"µ©&$ÝrgâBÕõÔ8™Õ:Sòù|Yi±ÔC4JMâª/—S#­þ)p-`ñeлÆXóÐjêÊ,G[Ñ9óÇL$ÆŒN pä€ê
í±Ê™G>Ê|ÙhlA\t‚cÓìŠ{"®‚¬¯¼”ôæPY.XS3±Åy	]õe8¨Õ})d¾¤!ǦvÄhø2>_ÒøØÃ‡wu|¬cæÝCR76‡jÉš
i`ŽlŸy7õR¿™†–©1º*]ó~N.@–êíÙOÑ
ÔbIâ¤Þ¸Ñ™ÛyIøÐr¸ÿR>Gm¼ã³wrH*©ûp‚õt4_*ªË²“lä×*ŠÒXpÆzû–:ÏK²TaŸOËë½M±ê
¾”íSþùö„neMÓ!ËS¬“•ú,É—i¶’,kär}2)²^ØðUÐð%ÓM¬Õ·¬ðÔ§È)ë4í™ó/CÆ­‘⾄®ú²EVRXfwL¼\øüÂí±júM†$ÕR7j–ã’,Ëø7€/¯’.5ÀêÔ9P,ÅÆ‹<«É"EÊøØz[Æã,”¹5á¹½륫·MÃ*•15Êjª{¸]¬”Ú0s-Ó˜/•(ͧ~	§5çûb|ÂW¿n;Mž½$cŒÖO9ñFóœôÄ~ááµÅáÛµžExÚÏ+ëmé#ôÆØÚ$Û›T£Ý%A’œÊܯŸFЀdoX«yá¡¿lô¯~Éñ]B_zÚö_¶./™¨ß±á˜~t8ß~^‚6±_öèw
ÒÄSÉ‚ )š•zIŽãHmö©öS–†7—;¯ï$;Gж_5À“ºz	WK“ßïç‘ã_bþØxpÏ»‡ýÊ"Îzðåw‰¿ì‹cŪ_ð%_—àKø|	_€/áËëAÛ:Á¼ö›À*]È™¼ÙèÞ½V¿Êæ0ºú»áÝø-Ü
€/;&î^ךìô[È-vš/š&I­M/uîÕ“ÌùþkºdÏö®xñYëiükÀ—ßÂü±Gíêü±ÝH³'ÿ[ð¥Ô©/YÚȦoúÛCgw#bÎ<€/¿Ñü$ÇŹUc>Í¢®&½
5û÷=fJ,VfI•œÖpââÇÌó<k“lÒ+Lž­URBÈð$«4åé:Ûú­!±2;eXx¢×¢ØQ”Pn1f«MÊÞ.„¯éS÷PVj6-íJWM(v}[_¶ž$›–f—¥¤˜áœb©‚ß(ÓÓ.íä\ù%.¤ Òç\ÅfÁ½ù¾§×»ëBjŠ•Ñ)¢:?íÔ‘SvØÃI»rìU5îÕÚ	ïf+Lú¼[Kï¬GF_ú]Rnf§çPJ¯xQŸŒ—m[ãÞÀÎfôÕ.M9ôÅK‘“_v¿/q7Ï6ÙÆ
bÞÆ’^…Ó5/™HÙEîjQ¼l7²|QÜV¥²ØS-ð•d,–úƒeöèoÎ÷úùj÷òV8?IHÉÿuGúZŽ|®
dš,çgÑŽ®¤Ö¼ˆÄ:N™Ÿ=­¨*¤å!™Zt”üNë´¼Ó׫ÞèKZA™ž«üg²Ç
dÞH9œyÿJòzñiž'_É1ÝœV|‰RzQBMÒí!ÇQ%É¢Ëú{%‹ÜÚšJû'ÝžüŽÇϳ¤(·'Ívûyº.Z¦œ ´}Ïpi¾ÔÓè¾d3§–’PfŸÏuÉb}ñÌŸËØîãyIéúÝH{{ÝV¼»H™À}¥7À­Lõîñúüü»À—ÝïKbñâÅtÐÎÛ3ÅRÕ¸ÔQw&ÌåUR@–åÔ6”j]Nw¬Vj©%[dE0yžFÊI“[ÓàœÍâKVïši
sÒ’sÎÃ’—K‹r^Î(™¦9—s;w,˨¥·¦êI?Ú×·æ‹VÏ|šýÛ];75_´1­GuñŸÃ)´Ô$ØÅþf–A:Ë~Ö8׺ÁvÊþWr¬•ûŠ!(kæý¼S_¯2Èiµ{Û¤%”UM_““é©=Wz¿Â¿X|y½|Ù¥ô^5öYJ^IOSH³H^Û¤Qí*™(_tþ`Ó\ý0AÍäˈÇ“óÅhK¢×°<‘>G¸ÓX©æ!1$œ÷hkævõ­¾%kÄô”^Ì—j¾èÏõk¡#:Ä–Ç_´в§ø½$­=v¥ã|„/I‡Úw‚ð…³e¶Û_z¢øòJqö³Æc¾4&¤,¤«©WºK&RºÍ`›C|Ù­¾\¶lYUUUü¶È©M5!é–;ªæ«§J%)Šòù|¹ÖW)é ÉLª/—S#­GË®,¾¤Î?c}ÌC«
•YŽ*¶¢sæ™?H9weÐO pä€ê
í±Ê™ç¸Ú‡ÔLlÆFàÉE'¨16Íþ©q=IN½ÂÚK#|©éШ^Í—â±ûM	NÍ—®9Dø’†
“¹]Jk-4×}iiM"ýó.ýLÔ[q$ÂÄ_v/i|ìáÇ»:>–"j	lÕ’5'Ò@Ù>ónêtú¨½´‰–•þ<ÒÀ¼ŸÓ‚Ë¥z{öSì·‰$NJq<:s;/ÉÿZ÷_Êç¨w|önAÉB%uNˆöÃ	¦º,;ùR®q­¢°Å—¬Ÿr©ó¼$K¬Ëp½·)V½Á—25cÞž0혩éå)ÖÉJá‰-ÍvB’ø—³èÓ£†nÔwHŽÜìi)?#YÆZ˜»àËÐEjžd-e¹Î£tâ²Öcƒ/ó_úƒ!ùŠCíve¾,[2–ÚÀ9Ai¦oú¥U»V±uàK|Ùý¾ìR¬Ns‚l¼hÀ£û,RÆÇÖÛ2g-‡·&<·—cõ¶)cô!e5Õ=Ü.Ö
JšÉµLc¾T$äSÆï„ÇÓšó}1bÍŠâ·Âm§É³—dŒÑú)'Þhž“žØ/<¼¶ø¬ÖÔ¥ž©ÚÏ+ëmé#ôÆØÚ$Û›T£Ý¥žNŠDÊܯ ö9áöRgŽº[¥©yh_ÛcõeN•·2H8i†%}ŒîËðåÖ³šlù ;ñvÖ²ô}Hg®tôª;×o…>¢¾À—½`~Y’DQЧR©¦ÚhFTê%9Ž#µÙ§ÚPYÞ\î¼>¾“ìü‚EQ”¯á~‰BG›ËŸtë¹w~þªçÝsWæ‘øëÀ—ßE$þ²ã¯_ð%_—àKø|	_€/áËëAÛ:Á¼ö›À*]È™¼ÙÛÍé;ª‹_es]ýÝðnüè;e³Z²³—ìtžoûcNÉc_Ÿ½Ò¶‡ë`érqa^¶ÅºÙQåw¬r½Ûét¹Ïãg¢À—½Ò—q'ðºŽÐD©ßB¾h±Ó|ÑM¶”ÑÚ@ñRç^=ɜ₩»ÑI¾h=Sf÷ÒàZ¦L·”:3;3†eîÖÄÖT4åGT“ž™Aó
ѼNN¾9ÊýŽÑÄL4;RFÆdZyPꚈK ™ÙdI>H€/{ïü±Gíêü±ÝH³'ÿ[ð¥Ô©/Yâ­¦oúÛCgwØϫûh²Ž¼cpæÍÙËÙôñÊ7çÛ´¼WÍ$ʔ꫃GšŒž’Éðì
嶪‰kZ¿j4«y:S’o×'>À—½5?IAAÇqqnUã˜O³¨«I¯BÍþ}4[i±21¬ä´Ng™>fžçÂS§ê•&ÏÖ*)§eiFbeêÔ„—×ÙÞÐçh
‰•Ù)ÃŒ³¡FG(·˜G³Õ&eoÂ×ô©…{(+5›–v¥«&»¾­/[OrTz_Vf—¥ÉÐÃ9ÅRÿ¾Q4õ¹vò
®ü‡Rés®JÖòy­w×…Ô	ÐG§°lÏSGNÙaç˱WÕ¸Wk'¼›­0yèón­yS¾ô»6¤&ÜÌN;Ï¡æÄ^ñ¢>/۶ƽE~Ú¥)‡þ x)U²Ì 5MpŸãd)V®XS†¥ÙN³Yà'ت´`ñ æKIIŽ­ê9<ãž|Åßnò6¯šìSfkQºm¡u‚¾zʶ=ÞvºÂöG-¾ìåù/ãnžm²4ļ}ΆÓ5/™HÙEîjQ¼l7²|QÜV¥²ØS-ð•d,–úƒ&.§¬&ýÍù^?_íVRs„ó“¨áËék9^ð¹6(Ù˜ŸE;ºÍH^Ä	b§ÌÏžVTÒòL-:Ê~§šÐc§E­7ú’VPæ‚çêÿ™ìq™7ÊÊþJòzñiž'_¡Oü´âKìèŠB,”Lɱ•㨒dÑeý½’EnmM¥ý“BnO~ÇãçYR”Û“f»ý<]—šE¤±Ó|ÑLBi…%‚$”Ùç3Éb}ñÌŸËØîãyIÍ‘B{{ÝV¼»H™x}¥7ÀM_D¯Ï¥ƒ–:YYÞ´ê¢?jÉXB5ÎÅTiµõ¸?Î7`LÆn‰Å÷öO·í°¤bžN³ì—¢4ÆyÀô«ŽõIÚú+]­oÜù¢—è(zV,y¾¾ì#¾$/^Lí¼=S,%QKE¹¥xUe9µ
¥Z—Ó]'«•ZjÉpGO#å¿dÙ¯Âášs6‹/Y½Kh¦X†´äœóð äåÅ¢œW‡3
@¦FrÌy8,ìܱƒ3ö[Sµ¼%Qê[óE«g>Í~‰í®›š/ZmmÔógöYÏ’`û›Yé,ûYãDçÆ|^IáK	ãy@Y3ïçúÒx•AþH«Ý
í±´LYÕô5)1™žÚs¥÷«p$åîIô…ÔœB	87û‘NI{BVNºï&ÅÁáྩpÜjR—Ó4>ûr3©02î§o	áü3\$òÎB%Xg{&•Ò]bm³”‰¾¾ì#¾ìRz¯û,µ›ª)¤Y$ÏÝØÖ©•áTVJÊ*Ó\ý0A=ã£g¹©-Ô%&†D[ʽ†¥ºô9ÂíœÆJc"eåå¼G™W¢Ö·úR<–¬eÓSz1_’V†˜bKƒã/Ú‡¾ì)~/Ik]é8áKÒ¡ö M>¯pþ˶¾ôDñå•âìg'Öš/Zó%e!}\M½nÔ]2qȸ5Á¶‡n÷ÔË)¡ËÑ¿FÐWº	ÓŠÂ¥£¿æ)’Sû5[¿m„*Vü¦ý˜죄ڮÖ7š®q’í¬Òœûü¥oSCR™Îœ¶å1@ø²WûrÙ²eUUUñoØ"_¤6Õ„¤[îLdŸžõBé¡$}Pú|¾€\kˆ«”tÐô¡¬úr9kG'®,¾¤Î?c}ÌC«
•YŽ*¶¢sæ™?H9weÐO pä€ê
í±Ê™ç¸Ú‡ÔLlÆFàÉE'¨16Íþ©q=ÊÈu²èÖ^Ú…|Ñâ1
/]s‰ð%
VòE+Y¬µÐ\÷¥¦Zþy—~&ê­8OþK缟ßp_"³Ý¯Fü>åü[#+wI9ŠÒiôåùu¤Ó‹ô¥z3sÚ~1c-eõßôÌø²÷=|øpWÇÇRdC-Í¡Z²æ¥N¶Ï¼›Z䜾€’HyæÝJžú+Zpù²ToÏ~Šý6‘ÄICNFgnç%9à?BËáþKùµñŽÏÞ-È!Y¨¤îÃ	Ñ~8Á>…³ìäK¹ÆµŠ"!6±~Ê¥Îó’,±.ÃõÞ¦Xõ_ÊÔŒy{Â·b¦¦C–§´.½+$¶4Û	I–µVÇå,úô¨^¡¾CrÌfOCHùÉ2ÖÂÜ_†.R;ð$k‰(Ëu¥SÏ­ù2_ñ¥?HClj·+ó%µjR8§§¡oú¥U»V±u:õ%Wbg«|&µ9]½ó£Õ;O7¤Ú¹Làdƒ]]ÕôAí-£©F¨£šî›G¹‡R™šÂšµÇ*ÙAU¨——$=È4ˇDÀ—½Ñ—]j€Õ©s. @
x”aŸEÊøØz[Æã,†¸5á¹½ë*«·M£ét(«©îáv%kcCr-ÓôŸ}Ê'rx<­9ß㣵BýDVì•<{IÆ­Ÿrâæ9é‰ýÂÃk‹ÏjMQêYªýæ¡Þ–>BoŒÝ©Mbà±½É~2ÈÎz:)}(s¿EÙç„ÛKIœ9ên•¦æ¡Q|ilÕ—9UÞÊ á¤–ô1º/ÃG”[Ïj²åƒìÄÛYË65–Ò™ëQš~+ôÅû²ER¾¬¼®ô׆	&XÕãzw¥bÁ×m'ô{_혯×ÏÜãq¡ŸiŽhm:vDi«ð¨ÍÅ>H€/1¿OHý=ÅñT*ÕJØe'J}§Qˆ²Ó6ûT*KÛË×Çw’_0Oò5Ü/Qèhs¹ã“n=w©;Â6Yäy?Ï·?!—ë÷ûÙ™¶È—‹,k+–¥¶CìÆ	~ÚZ@_—=÷¼{îÊ<=¸Z«Ö:ŠÚ°Ù^†¨_ö$þ²ã¯_ð%_—àKø|	_€/áËëÍ 3Á¼¶+X•IÚîÌØÝÁ^Û+i…§ñÈ|Ù=ÄÀë:B¥v1_´ä˜÷Â4[G:<™ûíS?€/¯6ìÑ£G»:l7ÒÜ.ƒÕµ£'ñ1×À—ÝâKFAAÇqqnUã˜O³¨«I¯BÍþ}4[i±21¬ä´NgÓ‡>fžçÂS§ê•&ÏÖ*)+ciFbeêÔ„—×ÙÞÐçh
‰•Ù)ÃŒ³¡FÅ»âE–…Ñ»búÔÂ=”‰ZKS\ÃV œ$£2ײzšêv½».¼¥P®ïŸR‡'­õ®ŸºèuNó6S§F?™èWäs®JÖr{µàË>™ÿ2îæÙ&Û¸ACÌÛX¶pºæ%ÉLEîjQ¼l7²UøÕ´TYì©øJ²KýA—Ó4ßýÍù^?ÏR‡ó“„”ü_w¤¯åxÁçÚ dcv~õðzs+Ë=2µè(/øªðvªi1X}޽Lü”…fQWò¢¨ûWŽKk{”YËG[JBZÞÍg,»ýÏrkÐNbLô+’”|[9Ž*ÊÂá²þ^ÉÍ‚¸_öa_‹/¦ƒvºa‹XJé,Æ¥Ž¢ÜR¼ª@ÊN•åÔ6”j]Nw¬Vj©%ÃI=ä'–OŠÕ78g³ø’Õ»„æDÓ‘ÊÎ9J^.Q,Êyu8¿’±‚Ñ—ÊþýHÏlåQé~uÿQÛccŸLÔ+j²Ïy–U’8sŠ1¾Äü>"K’(JñT*ÕT͈J}|#gÔþËÒð&qµ‘º²vÔ“‰~EʉñðeÃ=ïž»21À—ðeÇÁÙÇ‹¸_—àKø|	_€/áK¾àËžCÛ:Á¼¶Kù¢‹R†Ü™±»ƒ5¼¶WÒ
O÷å‡Qº\\˜—m±nv”µÿekH®w;.÷yü_vq'ðºŽÜ»˜/ZrÌ{aš­#ê	¿ú$-Â1šxˆ’«ddL¦…¥®‰¸{4iÕÓ¤EþÕàËnÍ{ôèÑ®ÎÛ4·™¾µ{Ðç•û`„%?ÿCJ–³»ÇmU³Ä´f†iæ6RMJòíú,ƒ_vƒ/ÇŹUc>Í9îVgdmöï£ÙY‹•iT%§u:›Cõ1ó<À&oÒ+Lž­URNËÒŒÄþTÙ?áåu¶7Z§o+³S†…'ƒ-ŠAzW¼8Imnõ®˜>µpåmfSÑ®tÕ°hþØQ™kY=Mu»Þ]ÞR(×÷ŸfÙž´Ö»f|ê¢ÔtÓÄë¶rG'ýŠ|ÎUÉZ>¯ÖÃEÒä°¾Á¶} y†‹WR[S®é©#§|P¼”*)&f/wØß§„šjÊëª÷j¶É¤ìÝ¢º>h%÷•:+Ÿr¦ïZgì«Ï1Ý<ÞvºÂöÇ»†Â—ø²»}Ɉ»y¶É6nÐó6–̓µ|Rª2S‘»Z/[Ç
d˜ÝV¥²ØS-ð•d/ªô©É¥)7Hs¾×ÏW»·PÚÈp~5[Öék9^ð¹6(˜ŸE=¼ÞÜÊò“L-:Ê~§*¼¾f½>Ç^&~Ê"ÂòB³ý+Ç¥µ=’uF[JBZÞÍg,»ý_VüÛI¬“‰~E’’8:ÇQ%É¢Ëú{%7K´¸¶Áµ@McR'
—×¥ÿˆùŒ¦ƒ§3¡ï
×ç°—·'¿ãñó,ãÊíI³Ý~žÎ–)õf‹päÓ¯v8Ö'iÖ¯tµÞ¥óE/Ñ)QèY±ä	ø_^/_‹/¦ƒvºa‹XJ]hãRGÝ™0—W˜nú~–SÛPªu9Ýu²Z©%Ål‘©äyÉOÆŒW
ÎÙ,¾dõ.¡™&D§àÉ9çáAÉË%ŠE9¯çWÒžó_²œ\쨔ZdŒšPšê®'ݯå¿4—òE3R~fwŸ).]ŸG=™`(úQflE¨ö³m&fë
ç]gø=*¡:-ë'íd¥÷+ýl“Âá#qÅnS
'²vç‡S£pu’È;•`w³ú-TJ§ÁÚfË–Œ…/ðåõòe—Ò{ÕØg©=gMª>)æp7¶ujDe8U–’?Ë4W?LPë¿dqžê¥C¢-eˆ^3AÕ¡îK5?Éqýˆîyv”/ÚÝæ¸ôR1¢âÑ(ù¼¢žL Æ‘=Åï%ií±+çCm/‡h:®ä?ÆZ¡õJQ;=Ýâm_¶&kMÌ)(çãj=ªŸd;«~þ‡ƒÒ·©ÃeeºtQ<ÈàËîõå²e˪ªªâß°E¾Hmª	I·Ü™Èa*a™xÑg·Ïçȵ†ðHIM-LEÔ¤éÑ>ÊZ¤EýˆÆú0Æ—weÐZ8r@G¾l{\ò´òR/Û狎z2¬‘¶ýé+H¢p²èjteé6Û¢ŽÓIß$¨ûj£‚é9C‘/Ã'ÓÆ—jšÓÖÙc¬¥¬>ÂñìþéàËnð%=|øpWÇÇ:fÞ=$ucs¨–¬9Az#ÛgÞM„N_@Iž<ón¥Oýa-¸üYª§~DZAéG”ÏQ񾄪ÛyIøÐr8Ò’ÏQïøìÝdY¨ÌzëëéN|©öS.už—d‰õö­÷6Åò%ë7
—™nbm¹Q}ëd¢^QÛ¨vL6Ð
uîeÆV_ÊÏF™7
²,ñg2o3Æ—ñû2¤ö¡R²‡WÆX±WÖ«¤ßT¡nT缟2ÍòI0ðewÐ¥X:çн\êÐЀG½Y¤Œ­·e<Κ[žÛËÔuëmSưJ¥ËMYM)¹]ÉÚp•\Ë4ý—AßT-HzМï‹ñiïi/'Þhž“žØ/<еølÄ

úžÙÊ£Òüêþ£¶ÇÆ>™¨WÔdŸó,«$qæG§šýáÒUÏÉN‹Ç—ÆöXãrÑ”z™çˆÒ0@ß$†Œ[#á_-¾ì™ÐO(¼‰§R©V"¡(;QêãŒÔþËÒð&q‡RRWÖŽz2ѯH¹ QŽg‡Ýõ	~?Ï"H|‰ùc;÷å¼{îÊ<‚ûð%|Ùa¬Æ_öñøÑÀ—ð%ø¾_—àKø虾DAAAAAé{¥{|¹úè}G((((((}µï®É—Ï
¸‰(((((}¾ï®É—L™ˆ2QPPPPúpdÙ±,ãõ%ð¾àK¾àK¾àK¾àKDõåÄ&ìË¿ 6Š/çÏŸï@lÈ•Š// 6a_V 6a_^@l¾<€Ø„}Y	€Ø(¾\°`AbC®T|y±	û²±	ûÒ
€Ø(¾\¸páqĆ\©øòÄ&ìËÄFñå¢E‹œˆ
¹Ò”——w±!Wš–,Yb·Û?@4È’äJSAAÁºuë>@4È’äJÓš5k–/_¾yóæ=hù‘,I®4­_¿~åʕ˖-[µjÕöíÛw`×.r"™‘dI–$Wš6mÚd³ÙèÅÒ¥K-Ë»ï¾ûÎ;ï¼õÖ[YYYsæÌ™5kÖ›o¾ùÆodddÌœ9óµ×^{õÕW_yå•éÓ§O›6-==}Ê”)/¿üòŸÿüç—^zéÅ_|á…ÒT&OžlVyþùçŸSù“Êÿ¶åÑø€ï6Qía¦¦r
“Ù‡iˆ|DV"7‘¡ÈSd+r™‹üE#—‘ÑÈkd7r™Ž|GÖ#÷‘ɃdCr"™‘üH–$WþXÓ†o~¹·IEND®B`‚qbs-src-1.13.1/doc/man/000077500000000000000000000000001347155106100144725ustar00rootroot00000000000000qbs-src-1.13.1/doc/man/man.pri000066400000000000000000000001671347155106100157650ustar00rootroot00000000000000qbs_no_man_install: return()

man.files = $$PWD/qbs.1
man.path = $${QBS_INSTALL_PREFIX}/share/man/man1
INSTALLS += man
qbs-src-1.13.1/doc/man/man.qbs000066400000000000000000000047051347155106100157620ustar00rootroot00000000000000import qbs
import qbs.File
import qbs.FileInfo
import qbs.ModUtils
import qbs.Probes
import qbs.Utilities

Product {
    name: "qbs man page"
    type: ["manpage"]

    Depends { productTypes: ["qbsapplication"]; condition: updateManPage }
    Depends { name: "qbsbuildconfig" }

    property bool updateManPage: false
    property string help2ManFilePath: help2ManProbe.filePath

    Group {
        name: "man page"
        files: ["qbs.1"]
        qbs.install: qbsbuildconfig.installManPage
        qbs.installDir: "share/man/man1"
    }

    Group {
        name: "additional sections"
        files: ["see-also.h2m"]
        fileTags: ["man.section"]
    }

    Rule {
        condition: updateManPage
        multiplex: true
        // TODO: Remove in 1.14.
        explicitlyDependsOn: ["application"]
        property stringList explicitlyDependsOnFromDependencies: ["application"]
        inputs: ["man.section"]
        Artifact {
            filePath: "qbs.1"
            fileTags: ["manpage"]
        }
        prepare: {
            var help2ManExe = product.help2ManFilePath;
            if (!help2ManExe)
                throw "Cannot update man page: help2man not available";
            if (Utilities.versionCompare(product.qbs.version, "1.9") < 0)
                throw "Cannot update man page: qbs >= 1.9 required";
            var qbsApp;
            for (var i = 0; i < explicitlyDependsOn.application.length; ++i) {
                var artifact = explicitlyDependsOn.application[i];
                if (artifact.product.name === "qbs_app")
                    qbsApp = ModUtils.artifactInstalledFilePath(artifact);
            }
            var args = [qbsApp, "-o", output.filePath,
                        "--no-info", "--name=the Qbs build tool"];
            var sections = inputs ? inputs["man.section"] : [];
            for (var i = 0; i < sections.length; ++i)
                args.push("--include=" + sections[i].filePath);
            var help2ManCmd = new Command(help2ManExe, args);
            help2ManCmd.description = "creating man page";
            var copyCmd = new JavaScriptCommand();
            copyCmd.silent = true;
            copyCmd.sourceCode = function() {
                File.copy(output.filePath,
                          FileInfo.joinPaths(product.sourceDirectory, output.fileName));
            }
            return [help2ManCmd, copyCmd];
        }
    }

    Probes.BinaryProbe {
        id: help2ManProbe
        names: ["help2man"]
    }
}
qbs-src-1.13.1/doc/man/qbs.1000066400000000000000000000032131347155106100153400ustar00rootroot00000000000000.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.47.7.
.TH QBS "1" "December 2018" "qbs 1.12.3" "User Commands"
.SH NAME
qbs \- the Qbs build tool
.SH SYNOPSIS
.B qbs
[\fI\,command\/\fR] [\fI\,command parameters\/\fR]
.SH DESCRIPTION
Qbs 1.12.3, a cross\-platform build tool.
.SS "Built-in commands:"
.TP
build
Build (parts of) a project. This is the default command.
.TP
clean
Remove the files generated during a build.
.TP
dump\-nodes\-tree
Dumps the nodes in the build graph to stdout.
.TP
generate
Generate project files for another build tool.
.TP
help
Show general or command\-specific help.
.TP
install
Install (parts of) a project.
.TP
list\-products
Lists all products in the project, including sub\-projects.
.TP
resolve
Resolve a project without building it.
.TP
run
Run an executable generated by building a project.
.TP
shell
Open a shell with a product's environment.
.TP
show\-version
Print the Qbs version number to stdout.
.TP
status
Show the status of files in the project directory.
.TP
update\-timestamps
Mark the build as up to date.
.SS "Auxiliary commands:"
.TP
config
This tool manages qbs settings.
.TP
config\-ui
This tool displays qbs settings in a GUI.
.TP
create\-project
This tool creates a qbs project from an existing source tree.
.TP
setup\-android
This tool creates qbs profiles from Android SDK and NDK installations.
.TP
setup\-qt
This tool creates qbs profiles from Qt versions.
.TP
setup\-toolchains
This tool creates qbs profiles from toolchains.
.SH "SEE ALSO"
For detailed help on a command, use the
.B help
command. For instance:
.IP
qbs help build
.PP

The full documentation for
.B qbs
is available at .
qbs-src-1.13.1/doc/man/see-also.h2m000066400000000000000000000002551347155106100166140ustar00rootroot00000000000000[SEE ALSO]
For detailed help on a command, use the
.B help
command. For instance:
.IP
qbs help build
.PP

The full documentation for
.B qbs
is available at .
qbs-src-1.13.1/doc/qbs-online.qdocconf000066400000000000000000000017071347155106100175110ustar00rootroot00000000000000include(config/qbs-project.qdocconf)

HTML.footer = \
    "   
\n" \ "

\n" \ " © 2018 The Qt Company Ltd.\n" \ " Documentation contributions included herein are the copyrights of\n" \ " their respective owners. " \ " The documentation provided herein is licensed under the terms of the" \ " GNU Free Documentation" \ " License version 1.3 as published by the Free Software Foundation. " \ " Qt and respective logos are trademarks of The Qt Company Ltd " \ " in Finland and/or other countries worldwide. All other trademarks are property\n" \ " of their respective owners.

\n" include($QT_INSTALL_DOCS/global/qt-html-templates-online.qdocconf) # Add an .html file with sidebar content, used in the online style HTML.stylesheets += config/style/qt5-sidebar.html qbs-src-1.13.1/doc/qbs.qdoc000066400000000000000000002014461347155106100153630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ // ********************************************************************** // NOTE: the sections are not ordered by their logical order to avoid // reshuffling the file each time the index order changes (i.e., often). // Run the fixnavi.pl script to adjust the links to the index order. // ********************************************************************** /*! \contentspage{index.html}{Qbs} \page index.html \nextpage overview.html \title Qbs Manual \section1 Version \qbsversion \QBS is a tool that helps simplify the build process for developing projects across multiple platforms. \QBS can be used for any software project, regardless of programming language, toolkit, or libraries used. \note Please report bugs and suggestions to the \l{http://bugreports.qt.io/}{Qt Bug Tracker}. \list \li \l{Introduction} \li \l{Setup} \list \li \l{Installing} \li \l{Configuring Profiles and Preferences} \li \l{Managing Qt Versions} \endlist \li \l{Usage} \list \li \l{Language Introduction} \li \l{Building Applications} \li \l{Running Applications} \li \l{Installing Files} \li \l{Target Platforms} \li \l{Using the Shell} \li \l{Generators} \li \l{Multiplexing} \li \l{Custom Modules and Items} \li \l{Module Providers} \endlist \li \l{How-tos} \li \l{Reference} \list \li \l{List of All Items} \list \li \l{List of Language Items} \li \l{List of Convenience Items} \li \l{List of Probes} \endlist \li \l{List of Built-in Services} \li \l{Command-Line Interface} \li \l{List of Modules} \li \l{Command and JavaScriptCommand} \endlist \li \l{Appendix A: Building Qbs} \li \l{Appendix B: Migrating from Other Build Systems} \li \l{Appendix C: Licenses and Code Attributions} \endlist */ /*! \contentspage index.html \previouspage index.html \page overview.html \nextpage setup.html \title Introduction \QBS is a build automation tool designed to conveniently manage the build process of software projects across multiple platforms. \section1 Features \QBS provides the following benefits: \list \li Declarative paradigm \li Well-defined language \li Platform and programming language independence \li Correct and fast incremental builds \li Extensible architecture \li Easy integration to IDEs \endlist \section2 Declarative Paradigm When writing a project, it is important to describe the build tasks and dependencies between them, rather than the build order. It is difficult to determine the correct build order in complex projects, especially during parallel builds. The build tool should bear that burden, not the developer. With a declarative language, \QBS enables you to express intent rather than specifying single build steps. This provides the appropriate level of abstraction for a build system. For example, \e dependencies can be created between \e products, such that the target \e artifacts of the dependency can be used as input to the build \e rules in the context of the depending product. In addition, you can \e export dependencies and \e properties to other products. \QBS is modular with clean interfaces between modules. A \e module is a collection of properties and \e {language items} that are used for building a product if the product depends on the module. The properties that can be set for a module are used to control the behavior of the toolchain used to build the module. \QBS itself knows nothing about file types or extensions, and therefore all source files in a product are handled equally. However, you can assign \e {file tags} to an artifact to act as markers or to specify a file type. \QBS applies a rule to the source files of the project and chooses the ones that match the input file tags specified by the rule. It then creates artifacts in the build graph that have other filenames and file tags. Products and projects can contain \e probes that are run prior to building, for instance to locate dependent headers, libraries, and other files outside the project directory. \section2 Well-Defined Language \QBS projects are specified in a QML dialect. QML is a concise, easy to learn, and intuitive language that is used successfully in the Qt project. Its core is declarative, but it can be extended with JavaScript snippets for extra flexibility. \QBS builds applications based on the information in a project file. Each project file specifies one \l{Project}{project} that can contain several \l{Product}{products}. You specify the type of the product, such as an \e application, and the dependencies the product has on other products. The product type determines the set of \l{Rule}{rules} that \QBS applies to produce artifacts from input files. The input files can be divided into \l{Group}{groups} according to their type or purpose, for example. A group can also be used to attach \l{Properties}{properties} to products. The following is an example of a minimal project file that specifies the product type, application name, source file, and a dependency on the \l{cpp} module: \code Application { name: "helloworld" files: "main.cpp" Depends { name: "cpp" } } \endcode For more information, see \l{Language Introduction}. \section2 Platform and Programming Language Independence \QBS can be used for any software project, regardless of programming language, toolkit, or libraries used. \QBS has built-in support for building applications for Windows, Linux, macOS, Android, iOS, tvOS, watchOS, QNX, and FreeBSD, as well as for cross-compilation. It can be easily extended to support further platforms. Invoking \l{build}{qbs build} from the command line automatically builds the project for the current host platform using the best available toolchain and settings, unless a default profile is set. You can configure additional profiles for each toolchain you want to use and select the profile to use at build time. For example, to build applications for Android devices, you would need to set up a profile for the Android toolchain and select it when you build the application. If you name the profile \e Android, you would then enter the following command: \code qbs build profile:Android \endcode For more information, see \l{Building Applications}. Platform and programming language support is implemented as a set of \l{List of Modules}{modules} that your product depends on. In the language example above, the dependency on the \l{cpp} module determines that the C++ sources are compiled and linked into a binary. Alternatively, you could use the \l{CppApplication} convenience item that implies a dependency on the \l{cpp} module: \code CppApplication { name: "helloworld" files: "main.cpp" } \endcode Additionally, if the sources use Qt, you need a dependency to the \l{Qt.core} module, and so on. In addition to building projects, \QBS can install the build artifacts to a location from where they can be run on the desktop or on a device. \QBS modules can be used to create installers for the end users of the applications. For example, the \l{dmg} module contains properties and rules for building Apple Disk Images, which are typically used to distribute applications and installers on macOS. The \l{innosetup}, \l{nsis}, and \l{wix} modules contain properties and rules for building installers for Windows platforms. \section2 Correct and Fast Incremental Builds \QBS is an all-in-one tool that generates a build graph from a high-level project description (like qmake or CMake) and additionally undertakes the task of executing the commands in the low-level build graph (like make). \QBS automatically takes advantage of multi-processor and multi-core systems to achieve maximum build parallelization. By default, running \c qbs without any arguments is roughly equivalent to running \c {make -j} where \c n is the number of CPU cores. Similarly, \QBS allows the number of concurrent jobs to be explicitly specified using its own \c -j option. \QBS has knowledge about the whole project, and therefore builds remain correct even when you build sub-projects, because \QBS ensures that all dependencies are built too. This virtually eliminates the need for clean builds. \QBS uses dynamic build graphs with build rules that can generate a variable number of files and that are executed only when needed. When figuring out which rules to execute, \QBS starts at the product type and then looks for a way to produce artifacts with matching file tags from source files, using a chain of rules that are connected by their respective input and output tags. For an example of how rules are applied when building products, see \l{Rules and Product Types}. The \QBS build rules can produce a variable number of outputs. If the input changes, only the required rules are applied at build time. If a rule is applied, all the dependent rules are applied as well, but only those. This feature ensures the correctness of the build graph after source code changes without having to re-configure the whole project. Changing properties that do not affect the build, because they are not used by rules, will not cause the project to be rebuilt. The use of properties is tracked. Generated artifacts that cease to exist are deleted to avoid picking outdated generated artifacts and indefinitely increasing the size of the build directory. Fast incremental builds are crucial for a fast edit-build-run cycle. Instead of retrieving the timestamps of generated files, \QBS uses the time stamps stored in the build graph. This is especially important on Windows, where file system operations are slow. If the project files were not changed, the build graph is loaded from disk. It is stored in a binary format that can be loaded much faster than the real project files. The project files are parsed only if they were changed. \section2 Extensible Architecture You can create your own custom \l{List of Modules}{modules} and \l{List of Language Items}{items} and make \QBS aware of them. You store the custom modules and items in a subdirectory of the project directory and specify the path to the subdirectory as a value of the \l{Project::}{qbsSearchPaths} property. For example, if the custom module is located at \c my-modules/modules/modulename/modulename.qbs, you would specify it in the project file as follows: \code Project { qbsSearchPaths: "my-modules" \endcode For more information, see \l{Custom Modules and Items}. \section2 IDE Integration \QBS can be used not only from the command line, but also in combination with an IDE, such as Qt Creator, Microsoft Visual Studio, or Xcode. Qt Creator directly supports \QBS projects. Visual Studio and Xcode users can use \QBS to generate Microsoft Visual Studio and Xcode projects. For more information, see \l {Generators}. \section3 Qt Creator \l{http://doc.qt.io/qtcreator/index.html}{Qt Creator} uses the same \QBS library as the \QBS command line tools. Therefore, it can retrieve all the information required to build a single file or project through a defined public API. Qt Creator provides accurate information about the build progress and displays a project tree that reflects the logical structure of the project, instead of presenting low-level information, such as the file system structure. Adding or removing source files keeps the existing project file structure intact. For more information about using \QBS to build projects from Qt Creator, see \l{http://doc.qt.io/qtcreator/creator-project-qbs.html}{Setting Up Qbs}. \section1 Build Process \image qbs-build-process.png The build process of a product starts by examining the \l{Product::}{type} property of the product. It contains a list of \e {file tags} that are similar to MIME types. The following example product contains one file tag, \e application: \code Product { Depends { name: "cpp" } type: ["application"] files: ["main.cpp", "class.cpp", "class.h"] } \endcode \QBS then searches through all \e rules available in the context, meaning rules that are defined in the project or those that are made available through the dependency on a module, such as the compiler and linker rules pulled in from the \c cpp dependency in the example. When \QBS finds a rule that produces one or more artifacts with the relevant file tag, it looks at the depencencies of that rule and finds out that it produces artifacts tagged \c obj. It then finds a rule that produces \c obj artifacts that takes \c .cpp artifacts as input. \code Module { // ... Rule { inputs {"cpp"] Artifact [ filePath: input.fileName + ".o" fileTags: {"obj"] } prepare: [ // g++ -c main.cpp -o main.o ... } } //... } \endcode There is no rule in the current context that produces \c .cpp files, but we have defined \c .cpp files as inputs for the product. When we added a dependency on the \l{cpp} module, that dependency also pulled in another \QBS primitive called the \l{FileTagger}{file tagger}. The file tagger looked for files matching the pattern \c *.cpp, and then applied the \c cpp tag to those input files: \code Module { // ... FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } //... } \endcode Since the \c .cpp files are input files, they by definition have no other dependencies, and we can go back the opposite way in the tree starting with the compiler rule described above. This design works well for generated files. The \c .cpp artifacts could come from another rule that produced them by processing some other input, either instead of or in addition to the raw files listed in the product. The compiler rule will be invoked twice, once for each \c .cpp file, producing a separate object file for each one. Then the linker rule will be invoked. Its \c multiplex property is set to \c true, which means that instead of producing one output per input and invoking the rule multiple times, all input will be collected before invoking the rule only once to produce the final application object. The standard versus multiplex rules map well to the compiler and linker processes. The compiler takes one input file to produce one output file, whereas the linker takes multiple input files to produce one output file. Finally, after the linker rule has been invoked, it produces an artifact tagged \c application. Because the product's type property did not contain other file tags, the build process is now complete. */ /*! \contentspage index.html \previouspage overview.html \page setup.html \nextpage installing.html \title Setup \list \li \l{Installing} \li \l{Configuring Profiles and Preferences} \li \l{Managing Qt Versions} \endlist */ /*! \contentspage index.html \previouspage reference.html \page building-qbs.html \nextpage porting-to-qbs.html \title Appendix A: Building Qbs \QBS can be \l{Installing}{installed from binary packages} or built from sources, as described in this appendix. In addition, this appendix describes how to use Docker images for developing \QBS. \section1 Supported Platforms \QBS can be installed and run on the following platforms: \list \li Windows 7, or later \li Linux (tested on Debian 8 and 9, Ubuntu 16.04, OpenSuSE 13.2, and Arch Linux) \li macOS 10.7, or later \endlist \section1 System Requirements To build \QBS from the source, you need: \list \li Qt 5.9, or later \li Windows: MinGW with GCC 4.9 or Microsoft Visual Studio 2015, or later \li Linux: GCC 4.9, or later, or Clang 3.9.0, or later \li macOS: Xcode 6.2, or later \endlist An installed toolchain has to match the one that Qt was compiled with. \section2 Documentation Building the \QBS documentation requires Python 2.7 or 3.2 or above, as well as some third party Python modules. These can be installed via \c pip: \code pip install beautifulsoup4 lxml \endcode Regenerating the man page requires the \c help2man tool. \section1 Building To build \QBS, enter the following command: \code qmake -r qbs.pro && make \endcode Depending on your platform, you might use \c mingw32-make, \c nmake, or \c jom instead of \c make. Installation by using \c {make install} is usually not needed. It is however possible, by entering the following command. \code make install INSTALL_ROOT=$INSTALL_DIRECTORY \endcode \section1 Configure Options \QBS recognizes the following qmake CONFIG options to customize the build: \table \header \li Option \li Notes \row \li qbs_enable_unit_tests \li Enable additional autotests. \row \li qbs_disable_rpath \li Disable the use of rpath. This can be used when packaging \QBS for distributions which do not permit the use of rpath, such as Fedora. \row \li qbs_no_dev_install \li Exclude header files from installation, that is, perform a non-developer build. \row \li qbs_no_man_install \li Exclude the man page from installation. \row \li qbs_enable_project_file_updates \li Enable API for updating project files. This implies a dependency to the Qt GUI module. \row \li qbs_use_bundled_qtscript \li Use the bundled QtScript library. \endtable In addition, you can set the \c QBS_SYSTEM_SETTINGS_DIR environment variable before running qmake to specify a custom location for \QBS to look for its system-level settings. \section1 Using Docker A set of Docker images for developing \QBS (which are maintained by the \QBS team) is available \l{https://hub.docker.com/u/qbsbuild/}{on Docker Hub}. Both Windows Server Core and Debian Linux container types are available. \note The source code for the \QBS development Docker images is located in the \c{docker/} directory of the \QBS source tree, if you wish to build them yourself. \section2 Linux Containers The easiest way to get started is to build \QBS using a Linux container. These types of containers are supported out of the box on all the supported host platforms: Windows, macOS, and Linux. Run the following to download the \QBS development image based on Debian 9 \e Stretch: \code docker pull qbsbuild/qbsdev:stretch \endcode You can then create a new container with the \QBS source directory mounted from your host machine's file system, by running: \code docker run -it -v $PWD:/qbs -w /qbs qbsbuild/qbsdev:stretch \endcode Or with a slightly different syntax for Windows: \code docker run -it -v %CD%:/qbs -w /qbs qbsbuild/qbsdev:stretch \endcode You will now be in an interactive Linux shell where you can develop and build \QBS. \section2 Windows Containers To build \QBS for Windows using Windows containers, your host OS must be running Windows 10 Pro and have Hyper-V enabled. \l{https://docs.docker.com/docker-for-windows/#switch-between-windows-and-linux-containers}{Switch your Docker environment to use Windows containers}, then run the following command to download the Windows 10 \QBS development image: \code docker pull qbsbuild/qbsdev:windowsservercore \endcode You can then create a new container with the \QBS source directory mounted from your host machine's file system, by running: \code docker run -it -v %CD%:C:\qbs -w C:\qbs qbsbuild/qbsdev:windowsservercore \endcode If you want to use Windows containers on a macOS or Linux host, you will have to create a virtual machine running Windows 10 and register it with \c{docker-machine}. There is at least \l{https://github.com/StefanScherer/windows-docker-machine}{one Open Source project} that helps to facilitate this by using using Packer, Vagrant, and VirtualBox. The \c{docker run} command to spawn a Windows container on a Unix host will look slightly different (assuming \c windows is the name of the Docker machine associated with the Windows container hosting VM): \code eval $(docker-machine env windows) docker run -it -v C:$PWD:C:\\qbs -w C:\\qbs qbsbuild/qbsdev:windowsservercore \endcode \section2 Building Release Packages Release packages for \QBS for Windows can be built using the following command on Windows: \code docker run --rm -v %CD%:C:\qbs -w C:\qbs qbsbuild/qbsdev:windowsservercore cmd /c scripts\make-release-archives \endcode For building release packages for Windows on macOS or Linux: \code eval $(docker-machine env windows) docker run --rm -v C:$PWD:C:\\qbs -w C:\\qbs qbsbuild/qbsdev:windowsservercore cmd /c scripts\\make-release-archives \endcode */ /*! \contentspage index.html \previouspage setup.html \page installing.html \nextpage configuring.html \title Installing \QBS binaries are available for Windows, macOS, Linux, and FreeBSD. On all platforms, \QBS binaries are part of the \l{Qt Creator} and \l{Qt SDK} installers. You can find the \c qbs executable in the \c bin directory of Qt Creator, or within the application bundle's \c MacOS directory on macOS. \QBS can also be built locally from sources. For more information, see \l{Appendix A: Building Qbs}. \section1 Windows The Qt Project provides prebuilt binaries for Windows (x86 and x64) at \l{https://download.qt.io/official_releases/qbs/}. For commercial customers of The Qt Company, the binaries are available in the \l {Qt Account}. The binaries are packaged in a .zip folder that can be extracted to a location of your choice. \QBS is also available as a \l Chocolatey package, which can be installed in the usual way: \code choco install qbs \endcode The \c .nupkg file can also be downloaded directly from \l{https://download.qt.io/official_releases/qbs/} for \l{https://chocolatey.org/security#organizational-use-of-chocolatey}{offline installation}. \section1 macOS \QBS can be conveniently installed on macOS with the \l{MacPorts} or \l{Homebrew} package managers: \code brew install qbs \endcode or \code port install qbs \endcode \section1 Linux and FreeBSD \QBS is \l{https://repology.org/metapackage/qbs/versions}{available via the package management systems} of Linux distributions, and FreeBSD. */ /*! \contentspage index.html \previouspage installing.html \page configuring.html \nextpage qt-versions.html \title Configuring Profiles and Preferences Profiles contain properties that apply to one or more projects. They are stored independently of the project files and are usually not shared between build hosts. Typically, profiles contain module properties, such as installation paths of tools or libraries on the host computer. This approach has the following advantages, among others: \list \li Team members with different computer setups can work together smoothly because no host-specific settings end up in the project files. \li Different versions of a tool or library can be used to build the same project without affecting each other. \endlist For example, a profile for building C++ applications contains at least the installation path and the type of the compiler toolchain. A profile for building Qt applications contains the toolchain-specific properties as well as \l{Qt-specific Module Provider Properties}{the path to the Qt installation}. This topic describes profiles stored in the \QBS settings. In some cases it might be beneficial to keep profiles explicitly in the project sources. This can be achieved with the \l{Profile} item. \section1 Setting Up Toolchain Profiles \QBS comes with a helper tool \l{setup-toolchains} that can create profiles for many toolchains. Open a terminal window and type: \code qbs setup-toolchains --detect \endcode This will automatically set up a profile for each detected toolchain on your computer. You can list the existing profiles by running: \code qbs config --list profiles \endcode Some toolchains, especially for bare-metal targets, may require additional module properties. Those can be added with the \l{config} or the \l{config-ui} tools. Now you should be ready to build your first project with \QBS. Go into examples/helloworld-minimal and type: \code qbs build profile: \endcode You have successfully built your first \QBS project. If you want to build projects that use Qt, additional steps might be necessary. Please refer to \l{Managing Qt Versions} for more information. \section1 Global Preferences In addition to profiles, \QBS provides some global preferences such as \c qbsSearchPaths and \c defaultProfile. \section1 Managing Profiles and Preferences You can use the \l{config} command to manage all \QBS configuration settings, such as profiles and global preferences from the command line, for example: \code qbs config profiles..qbs.architecture arm \endcode For convenience, \QBS provides a tool \l{config-ui} where you can manage the settings in a hierarchical view. \image qbs-settings-gui.png \QBS Settings displays the keys in the specified settings directory and their values. To expand all keys, select \uicontrol View > \uicontrol {Expand All} (\key Ctrl+E or \key Cmd+E on macOS). To collapse all keys, select \uicontrol {Collapse All} (\key Ctrl+C or \key Cmd+C). To change the value of a key, double-click it and enter the new value. To save your changes, select \uicontrol File > \uicontrol Save. To refresh the settings from the settings directory, select \uicontrol File > \uicontrol Reload. */ /*! \contentspage index.html \previouspage configuring.html \page qt-versions.html \nextpage usage.html \title Managing Qt Versions \section1 Introduction If your environment has the right \c qmake binary in its \c PATH and is also set up properly for a matching toolchain, then you do not necessarily need a profile to build projects with a Qt dependency. Otherwise, you should create one: \code qbs setup-qt /usr/bin/qmake myqt \endcode This will create the \c myqt profile which can then be used on the command line: \code qbs profile:myqt \endcode \note If the \c setup-toolchains command has found more than one toolchain, you will need to manually link your Qt profile to one of them, like this: \code qbs config profiles.myqt.baseProfile \endcode \section1 Multiple Qt Builds To support multiple Qt builds, or in fact any combination of related settings, you need to create several profiles. The following example illustrates how to set up three different profiles, each for a different Qt build: \code qbs setup-qt ~/dev/qt/4.7/bin/qmake qt47 qbs setup-qt ~/dev/qt/4.8/bin/qmake qt48 qbs setup-qt ~/dev/qt/5.0/qtbase/bin/qmake qt5 \endcode You can set the default Qt build like this: \code qbs config defaultProfile qt5 \endcode To choose a Qt build that is different from the default, use: \code qbs build profile:qt48 \endcode You can set other properties in a profile (not just Qt ones), in the same way you override them from the command line. For example: \code qbs setup-qt C:\Qt\5.0.0\qtbase\bin\qmake.exe qt5 qbs config profiles.qt5.qbs.architecture x86_64 qbs config profiles.qt5.baseProfile msvc2010 \endcode The last example uses the inheritance feature of profiles. All settings in the profile set as \c baseProfile are known in the derived profile as well. They can of course be overridden there. */ /*! \contentspage index.html \previouspage qt-versions.html \page usage.html \nextpage language-introduction.html \title Usage \list \li \l{Language Introduction} \li \l{Building Applications} \li \l{Running Applications} \li \l{Installing Files} \li \l{Target Platforms} \li \l{Using the Shell} \li \l{Generators} \li \l{Multiplexing} \li \l{Custom Modules and Items} \li \l{Module Providers} \endlist */ /*! \contentspage index.html \previouspage usage.html \page language-introduction.html \nextpage building-applications.html \title Language Introduction \QBS uses project files (*.qbs) to describe the contents of a project. A project contains one or more \l{Product}{products}. A product is the target of a build process, typically an application, library or maybe a tar ball. \note \QBS source files are assumed to be UTF-8 encoded. \section1 The Obligatory Hello World Example \QBS project files are written using a QML dialect. A very simple C++ hello world project looks like this: \code ---helloworld.qbs--- Application { name: "helloworld" files: "main.cpp" Depends { name: "cpp" } } \endcode The import statement gives us access to some built-in types and specifies the used language version. \a Application describes the product we want to build. In this case, an application. This is just a shortcut for writing \code Product { type: "application" // ... } \endcode The \a name is the name of the product. In this case it is also the name of the produced executable (on Windows, the ".exe" extension is added by default). In the property \a files, we specify the source files for our product. Unlike QML, the right-hand side can be either a string or a string list. A single string is converted to a stringlist containing just one element. So we could have also written \code files: [ "main.cpp" ] \endcode \a Depends adds the dependency to the \l{cpp} module. This is necessary to let \QBS know that we have a C++ project and want to compile main.cpp with a C++ compiler. For more information about \QBS modules, see \l{Modules}. \section1 Reusing Project File Code QML-like inheritance works also in \QBS. \code ---CrazyProduct.qbs--- Product { property string craziness: "low" } ---hellocrazyworld.qbs--- import "CrazyProduct.qbs" as CrazyProduct CrazyProduct { craziness: "enormous" name: "hellocrazyworld" // ... } \endcode You can put JS code into separate \c{.js} files and then import them. \code ---helpers.js--- function planetsCorrectlyAligned() { // implementation } ---myproject.qbs--- import "helpers.js" as Helpers Product { name: "myproject" Group { condition: Helpers.planetsCorrectlyAligned() file: "magic_hack.cpp" } // ... } \endcode \section1 Modules A \e module is a collection of properties and language items that are used for building a product if the product depends on (or loads) the module. For example, the \a cpp module looks like this (simplified): \code Module { name: "cpp" property string warningLevel property string optimization property bool debugInformation property pathList includePaths // ... FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } Rule {...} // compiler Rule {...} // application linker Rule {...} // static lib linker Rule {...} // dynamic lib linker } \endcode The properties that can be set for the \a cpp module are used to control the behavior of your C++ toolchain. In addition, you can use FileTaggers and Rules that are explained later. As soon as your product depends on a module, it can set the properties of the module. You specify the optimization level for your product (and all build variants) like this: \code ---helloworld.qbs--- Application { name: "helloworld" files: ["main.cpp"] cpp.optimization: "ludicrousSpeed" Depends { name: "cpp" } } \endcode A module can implicitly depend on other modules. For example, the \l{Qt.core} module depends on the \l{cpp} module. However, to set the properties of a module, you must make the dependency explicit. \code // THIS DOES NOT WORK Application { name: "helloworld" files: ["main.cpp"] Depends { name: "Qt.core" } cpp.optimization: "ludicrousSpeed" // ERROR! We do not know about "cpp" here, // though "Qt.core" depends on "cpp". } // THIS WORKS Application { name: "helloworld" files: ["main.cpp"] Depends { name: "Qt.core" } Depends { name: "cpp" } cpp.optimization: "ludicrousSpeed" } \endcode \section2 Different Properties for a Single File Not only the product, but all the source files of the product can have their own set of module properties. For example, assume you have some files that are known to crash your compiler if you turn on optimizations. You want to turn off optimizations for just these files and this is how you do it: \code Application { name: "helloworld" files: "main.cpp" Group { files: ["bad_file.cpp", "other_bad_file.cpp"] cpp.optimization: "none" } Depends { name: "cpp" } } \endcode \section2 Selecting Files by Properties Sometimes you have a file that is only going to be compiled on a certain platform. This is how you do it: \code Group { condition: qbs.targetOS.contains("windows") files: [ "harddiskdeleter_win.cpp", "blowupmonitor_win.cpp", "setkeyboardonfire_win.cpp" ] } Group { condition: qbs.targetOS.contains("linux") files: [ "harddiskdeleter_linux.cpp", "blowupmonitor_linux.cpp", "setkeyboardonfire_linux.cpp" ] } \endcode In the above example, \l{qbs::targetOS}{qbs.targetOS} is a property of the target of the the \l{qbs} module. The \c qbs module is always implicitly loaded. Its main properties are: \list \li \l{qbs::}{buildVariant} that specifies the name of the build variant for the current build. \li \l{qbs::}{hostOS} that is set by \QBS internally and specifies the operating system \QBS is running on. \li \l{qbs::}{targetOS} that specifies the operating system you want to build the project for. \endlist You can set these properties on the command line or by using a profile. \code $ qbs # qbs.buildVariant:debug, profile: (or profile:none, if no default profile exists) $ qbs config:release # qbs.buildVariant:release, profile: $ qbs config:debug config:release # builds two configurations of the project $ qbs profile:none # all module properties have their default values \endcode To select files by build variant: \code Group { condition: qbs.buildVariant == "debug" files: "debughelper.cpp" } \endcode To set properties for a build variant: \code Properties { condition: qbs.buildVariant == "debug" cpp.debugInformation: true cpp.optimization: "none" } \endcode Or, to use a more QML-like style: \code cpp.debugInformation: qbs.buildVariant == "debug" ? true : false cpp.optimization: qbs.buildVariant == "debug" ? "none" : "fast" \endcode \section1 Property Types While properties in \QBS generally work the same way as in QML, the set of possible property types has been adapted to reflect the specific needs of a build tool. The supported types are as follows: \table \header \li Property type \li Example \li Description \row \li \c bool \li \c{property bool someBoolean: false} \li The usual boolean values. \row \li \c int \li \c{property int theAnswer: 42} \li Integral numbers. \row \li \c path \li \c{property path aFile: "file.txt"} \li File paths resolved relative to the directory the product they are associated with is located in. \row \li \c pathList \li \c{property pathList twoFiles: ["file1.txt", "./file2.txt"]} \li A list of \c path values. \row \li \c string \li \c{property string parentalAdvisory: "explicit lyrics"} \li JavaScript strings. \row \li \c stringList \li \c{property stringList realWorldExample: ["no", "not really"]} \li A list of JavaScript strings. \row \li \c var \li \c{property var aMap: ({ key1: "value1", key2: "value2" })} \li Generic data, as in QML. \row \li \c varList \li \c{property var aMapList: [{ key1: "value1", key2: "value2" }, { key1: "value3" }]} \li A list of generic data, typically JavaScript objects. \endtable \section1 Overriding Property Values from the Command Line Property values set in project files or profiles can be overridden on the command line. The syntax is \c{.:}. The following command lines demonstrate how to set different kinds of properties: \code $ qbs projects.someProject.projectProperty:false # set a property of a project $ qbs products.someProduct.productProperty:false # set a property of a product $ qbs modules.cpp.treatWarningsAsErrors:true # set a module property for all products $ qbs products.someProduct.cpp.treatWarningsAsErrors:true # set a module property for one product \endcode Property values on the command line can also be expressed in JavaScript form, the same way as you would write them in a project file. Make sure to take care of proper quoting, so that the shell does not interpret any of the values itself. Properties of type \c stringList can also be provided as comma-separated values, if none of the strings contain special characters: \code $ qbs projects.someProject.listProp:'["a", "b", "c"]' $ qbs projects.someProject.listProp:a,b,c # same as above $ qbs projects.someProject.listProp:'["a b", "c"]' # no CSV equivalent \endcode \section1 File Tags and Taggers \QBS itself knows nothing about C++ files or file extensions. All source files in a product are handled equally. However, you can assign \a{file tags} to an artifact to act as a marker or to specify a file type. An artifact can have multiple file tags. For example, you can use the \a Group item to group files with the same file tags (or a set of properties). \code Product { Group { files: ["file1.cpp", "file2.cpp"] fileTags: ["cpp"] } Group { files: "mydsl_scanner.l" fileTags: ["flex", "foobar"] } // ... } \endcode When you load the \a cpp module, you also load the following item: \code FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } \endcode This construct means that each source file that matches the pattern \c{*.cpp} (and has not explicitly set a file tag) gets the file tag \c{cpp}. The above example can be simplified to \code Product { Depends: "cpp" files: ["file1.cpp", "file2.cpp"] Group { files: "mydsl_scanner.l" fileTags: ["flex", "foobar"] } // ... } \endcode The \a FileTagger from the \a cpp module automatically assigns the \c cpp file tag to the source files. Groups that just contain the \a files property can be more simply expressed by using the \a files property of the product. File tags are used by \a rules to transform one type of artifact into another. For instance, the C++ compiler rule transforms artifacts with the file tag \c cpp to artifacts with the file tag \c{obj}. In addition, it is possible to use file taggers to tag files and specify custom file tags: \code Product { Depends: "cpp" Group { overrideTags: false // The overrideTags property defaults to true. fileTags: ["foobar"] files: ["main.cpp"] // Gets the file tag "cpp" through a FileTagger item and // "foobar" from this group's fileTags property. } // ... } \endcode \section1 Rules \QBS applies a \e rule to a pool of artifacts (in the beginning it is just the set of source files of the project) and chooses the ones that match the input file tags specified by the rule. Then it creates output artifacts in the build graph that have other filenames and file tags. It also creates a script that transforms the input artifacts into the output artifacts. Artifacts created by one rule can (and typically do) serve as inputs to another rule. In this way, rules are connected to one another via their input and output file tags. For examples of rules, see the share/qbs/modules directory in the \QBS repository. You can define rules in your own module to be provided along with your project. Or you can put a rule directly into your project file. For more information, see \l{Rule}. */ /*! \contentspage index.html \previouspage language-introduction.html \page building-applications.html \nextpage running-applications.html \title Building Applications To build applications from the command line, enter the following commands: \code cd examples/collidingmice qbs \endcode By default, \QBS uses all the CPU cores available to achieve maximum build parallelization. To explicitly specify the number of concurrent jobs, use the \c -j option. For example, to run 4 concurrent jobs, enter the following command: \code qbs -j4 \endcode The application is built using the default build profile that is set up in your \QBS configuration. You can use the \l{config} command to set the max number of jobs per profile. For example, to set four jobs as the default option for a profile named \e Android, enter the following command: \code qbs config profiles.Android.preferences.jobs 4 \endcode To build with other profiles than the default one, specify options for the \l{build} command. For example, to build debug and release configurations with the \e Android profile, enter the following command: \code qbs build profile:Android config:debug config:release \endcode The position of the property assignment is important. In the example above, the profile property is set for all build configurations that come afterwards. To set a property just for one build configuration, place the assignment after the build configuration name. In the following example, the property \l{cpp::treatWarningsAsErrors} {cpp.treatWarningsAsErrors} is set to \c true for debug only and \l{cpp::optimization}{cpp.optimization} is set to \c small for release only. \code qbs build config:debug modules.cpp.treatWarningsAsErrors:true config:release modules.cpp.optimization:small \endcode Projects are built in the debug build configuration by default. */ /*! \contentspage index.html \previouspage running-applications.html \page installing-files.html \nextpage {Target Platforms} \title Installing Files To install your project, specify the necessary information in the project file: \code Application { Group { name: "Runtime resources" files: "*.qml" qbs.install: true qbs.installDir: "share/myproject" } Group { name: "The App itself" fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } } \endcode In this example, we want to install a couple of QML files and an executable. The actual installation is then done like this (using the default profile): \code qbs --clean-install-root qbs.installRoot:/tmp/myProjectRoot \endcode Here, we want the \c installDir properties from the project file to be interpreted relative to the directory \c{/tmp/myProjectRoot}, and we want that directory to be removed first. If the \l{qbs::installRoot}{qbs.installRoot} property is not given, a default is used, namely \c{/install-root}. For more information about how the installation path is constructed, see \l {Installation Properties}. */ /*! \contentspage index.html \previouspage building-applications.html \page running-applications.html \nextpage installing-files.html \title Running Applications By default, running an application also builds it and installs it to a location from where it can be run on the desktop or on a device. For example, entering the following command runs the Qt Creator application: \code qbs run --products qtcreator \endcode This command also builds and installs the product, if necessary. */ /*! \contentspage index.html \previouspage {Target Platforms} \page shell.html \nextpage generators.html \title Using the Shell To use the \QBS shell, enter the following command: \code qbs shell \endcode This is mainly a debugging tool. It opens a shell with the same environment that \QBS uses when building the project, so you can, for example, inspect which environment variables will be set up. */ /*! \contentspage index.html \previouspage multiplexing.html \page custom-modules.html \nextpage module-providers.html \title Custom Modules and Items Users of \QBS are not limited to the pre-defined \l{List of Modules}{modules} and \l{List of Language Items}{items}, they can also create their own. Here we describe how to set up custom modules and items so that \QBS will find them. \section1 File System Layout Items and modules are located under a common base directory, whose name and location is completely arbitrary. We will refer to it as \c search-path here. This directory has two subdirectories \c modules and \c imports, which contain \QBS modules and items, respectively. \section1 Custom Modules To introduce a custom module \c mymodule, create a directory \c{search-path/modules/mymodule/}. \note Module names are case-sensitive, and this also goes for the corresponding directory name. Then, put a file containing an instance of the \l{Module} in there and give it the \c{.qbs} extension. This module will be pulled in if a \l{Product}{product} declares a \l{Depends}{dependency} on \c mymodule. \section1 Custom Items To introduce a custom item \c MyItem, create the file \c{search-path/imports/MyItem.qbs}. \section1 Making \QBS Aware of Custom Modules and Items To be able to use your custom modules and items, you need to make them known to \QBS. You can do this per project or globally. \section2 Project-specific Modules and Items Let's assume you have a project that is located in \c{project_dir} and you have created some modules in \c{project_dir/custom-stuff/modules/} as well as some items in \c{project_dir/custom-stuff/imports/} that you want to use in the project. To achieve this, your top-level project file should look like this: \code // ... Project { // .. qbsSearchPaths: "custom-stuff" // .. } \endcode \note For technical reasons, the custom modules and items will not be available in the file that contains the \l{Project::qbsSearchPaths} {Project.qbsSearchPaths} property. Any product that wants to make use of them needs to be in a different file that is pulled in via the \l{Project::references}{Project.references} property, for example. This is not a serious limitation, since every well-structured project will be split up in this manner. \section2 Making Custom Modules and Items Available Across Projects What if your modules and items are generally useful and you want to access them in several projects? In this case, it is best to add the location to your preferences. For example: \code qbs config preferences.qbsSearchPaths /usr/local/share/custom-qbs-extensions \endcode */ /*! \contentspage index.html \previouspage custom-modules.html \page module-providers.html \nextpage howtos.html \title Module Providers There are use cases for which a pre-defined module is not flexible enough. For instance, the overall set of modules related to a certain task might depend on some information present on the local platform. \note Module providers are an advanced concept that you will rarely need to use directly. Reading this section is not required for most people's everyday work. \section1 How \QBS Uses Module Providers If \QBS encounters a \l Depends item whose name does not match a known module, it checks whether such a module can be generated. This procedure works as follows: \list 1 \li All \l{Project::qbsSearchPaths}{search paths} are scanned for a file called \c {module-providers//provider.qbs}, where \c is the name of the dependency as specified in the \c Depends item. Multi-component names such as "a.b" are turned into nested directories, and each of them is scanned, starting with the deepest path. For instance, if the dependency's name is \c {a.b}, then \QBS will look for \c {a/b/provider.qbs} and then \c {a/provider.qbs}. \li If such a file is found, it needs to contain a \l ModuleProvider item. This item is instantiated, which potentially leads to the creation of one or more modules, and \QBS retrieves the search paths to find these modules from the item. The details are described in the \l ModuleProvider documentation. \li If a matching module provider was found and provided new search paths, a second attempt will be made to locate the dependency using the new paths. The search for a matching module provider ends as soon as one was found, regardless of whether it created any modules or not. \li If no matching module provider was found in any of the search paths, \QBS will fall back to a generic module provider, which creates a module that attempts to locate the dependency via \c pkg-config. This fallback mechanism can be disabled in the respective \l{Depends::enableFallback}{Depends} item or globally via the \l{no-fallback-module-provider}{--no-fallback-module-provider} option. \endlist \section1 Parameterizing Module Providers You can pass information to module providers from the command line, via profiles or from within a product, in a similar way as you would do for modules. For instance, the following invocation of \QBS passes information to two module providers \c a and \c b: \code $ qbs moduleProviders.a.p1:true moduleProviders.a.p2:true moduleProviders.b.p:false \endcode \QBS will set the properties of the respective module providers accordingly. In the above example, module provider \c a needs to declare two boolean properties \c p1 and \c p2, and they will be set to \c true and \c false, respectively. */ /*! \contentspage index.html \previouspage shell.html \page generators.html \nextpage multiplexing.html \title Generators Generators are a \QBS sub-tool and set of APIs that enable arbitrary processing to be performed on the build graph. Currently, they are used to integrate \QBS with popular IDEs, such as Microsoft Visual Studio, and to generate Clang compilation databases. \section1 Generating Projects To generate a project for another build system, such as Microsoft Visual Studio, use the \l{generate}{qbs generate} command and specify a generator using the \l{generate-generator}{-g} option. For example: \code # For Visual Studio qbs generate -g visualstudio2015 \endcode \QBS will then generate a series of files in the current directory, based on the generator that was chosen. The resulting project files can be opened in the respective IDE and all work can be performed there. The project files will expose as much information as possible to the IDE and will use \QBS to perform the actual build. \note You cannot modify build system files and expect the changes to be reflected in \QBS. You must edit your \QBS project files and re-run \l{generate}{qbs generate} in order for the changes to be reflected in your IDE. \section1 Generating Clang Compilation Databases To generate a \l{JSON Compilation Database Format Specification} {Clang compilation database (clangdb)}, use the following command: \code qbs generate --generator clangdb \endcode \section1 Generating Makefiles To generate a Makefile, use the following command: \code qbs generate --generator makefile \endcode \section2 Targets The generated Makefile will contain targets for all output artifacts known to \QBS. In addition, the following targets are created for every product: \list \li \c {} to build the product \li \c {clean-} to remove all files generated by the above target \li \c {install-} to install the product's artifacts that have \c{qbs.install} set \endlist In the above list, the placeholder \c{} stands for the product's name with all characters that are not ASCII letters, digits, dots or underscores replaced with underscore characters. The special target \c all builds all products whose \l{Product::builtByDefault}{builtByDefault} property is enabled. This is the default target. It is complemented by \c install and \c clean. \note The Makefile will not be able to build artifacts created by \l{JavaScriptCommand}{JavaScriptCommands}, because there is no command line to run for them. \section2 Pre-defined Variables The build directory and the install root are set to whatever you specified when calling the generator. If you did not specify anything, \QBS' default values are used. You can override these values when invoking the \c make tool by explicitly setting the \c{BUILD_ROOT} and \c{INSTALL_ROOT} variables, respectively. For instance: \code $ qbs generate -g makefile config:make modules.qbs.installRoot:/opt/mydir $ make -f make/Makefile # Will install to /opt/mydir $ make -f make/Makefile INSTALL_ROOT=/opt/myotherdir # Will install to /opt/myotherdir \endcode \section2 Spaces in Directory Names Due to the difficulties involved in making this work correctly, \QBS will refuse to generate a Makefile if the source, build or install root directories contain spaces. It will try to handle spaces in file names of output artifacts, though. \section2 Platform-specific Differences in Format \QBS assumes that the Makefile will be invoked on the current host platform, so that platform's tools will be used for copying and removing files, and path separators will be converted to backslashes on Windows. When dealing with spaces in artifact names, on Unix-like systems compatibility with GNU make is assumed with regards to quoting. \section1 Limitations Due to the high flexibility of the \QBS project format and build engine, some projects may be too complex to produce an equivalent project file for another build system. This list of limitations aims to be as small as possible, but one of the most notable (at least for the Microsoft Visual Studio generator) is that certain properties must contain the same value across all build configurations. For example, the following is not allowed: \code Product { // ERROR: 'name' property cannot have different values based on the configuration name: qbs.configuration === "debug" ? "MyProduct_debug" : "MyProduct" } \endcode \note This limitation only applies when property values are varied on the configuration name. For example, the following is OK (as long as the value of xyz itself does not vary across configurations): \code Product { // OK property bool isDebug: name: isDebug ? "MyProduct_debug" : "MyProduct" } \endcode The properties to which the limitation applies includes but is not limited to: \list \li \l{Product::name}{Product.name} \li \l{bundle::isBundle}{bundle.isBundle} \endlist If a simple workaround is possible in a particular case (for example, varying \l{Product::targetName}{Product.targetName} across configuration instead of \l{Product::name}{Product.name}, the generator will typically suggest it in the error message. */ /*! \contentspage index.html \previouspage generators.html \page multiplexing.html \nextpage custom-modules.html \title Multiplexing Multiplexing is an advanced \QBS feature that allows a product to be transparently built in multiple \e passes along with an optional, final \e aggregate pass that allows the output artifacts of the initial passes to be combined or otherwise operated on in some way. The multiplexing feature is used to implement certain platform-specific behavior: specifically, it allows applications and libraries on Apple platforms to be compiled into \e fat binaries containing multiple CPU architectures, the creation of Apple frameworks containing multiple \e variants (for example, combined debug and release builds), and the creation of Android application and library packages containing native code built for multiple Android ABIs. A product can be multiplexed over the \l{qbs::architectures} {qbs.architectures} property (which maps to \l{qbs::architecture} {qbs.architecture}), \l{qbs::buildVariants}{qbs.buildVariants} property (which maps to \l{qbs::buildVariant}{qbs.buildVariant}), and \l{qbs::profiles} {qbs.profiles} (which maps to \l{Project::profile}{Project.profile}). \note The implementation details around multiplexing are subject to change. Product multiplexing works by examining the \l{Product::multiplexByQbsProperties}{Product.multiplexByQbsProperties} property, which can be set to the list of properties your product should multiplex over. For example, \c multiplexByQbsProperties might contain two strings, \c "architectures" and \c "buildVariants". \QBS evaluates the values of \c qbs.architectures and \c qbs.buildVariants, which in turn might contain the values \c ["x86", "x86_64"] and \c ["debug", "release"]. \QBS will build all the possible configurations of the product: \c {(x86, debug)}, \c {(x86, release)}, \c {(x86_64, debug)}, and \c {(x86_64, release)}. If the \l{Product::aggregate}{Product.aggregate} property is \c true, the product will also be built a fifth time, with the values of the multiplexed properties left undefined. The aggregate product will have an automatic dependency on the original four instances of the product, allowing it to collect their output artifacts and to operate on them. The aggregate product is used in situations where the target artifacts of the individually multiplexed instances must be combined into one final aggregate artifact that makes up the overall product. Bundle products on Apple platforms use the aggregate product to create the bundle artifacts (such as \c Info.plist and \c PkgInfo) that are independent of a particular architecture or build variant. In addition, they use the \c lipo tool to join together the built native code for different architectures (such as \c x86 and \c x86_64) into the final, multi-architecture fat binary that the app bundle contains. */ /*! \contentspage index.html \previouspage porting-to-qbs.html \page attributions.html \title Appendix C: Licenses and Code Attributions \section1 Licenses The \QBS library and tools are available under commercial licenses from \l{Qt Licensing}{The Qt Company}. In addition, they are available under \l{GNU Lesser General Public License, Version 3} (LGPL version 3) and \l{GNU General Public License, version 2} (GPL version 2). Shared functionality, which might be pulled in by user build scripts, is available under commercial licenses, \l{GNU Lesser General Public License, Version 2.1} (LGPL version 2.1) with \l{The Qt Company LGPL Exception version 1.1}, and LGPL version 3. Autotests are available under commercial licenses and \l{GNU General Public License Version 3, Annotated with The Qt Company GPL Exception 1.0}. Examples are available under commercial licenses and \l{BSD}. \section2 GNU Lesser General Public License, Version 3 \quotefile ../LICENSE.LGPLv3 \section2 GNU General Public License Version 3, Annotated with The Qt Company GPL Exception 1.0 \quotefile ../LICENSE.GPL3-EXCEPT \section2 GNU Lesser General Public License, Version 2.1 \quotefile ../LICENSE.LGPLv21 \section2 The Qt Company LGPL Exception version 1.1 \quotefile ../LGPL_EXCEPTION.txt \section1 Third-Party Attibutions \QBS contains third-party code, which we gratefully acknowledge: \generatelist{groupsbymodule attributions-qbs} */ qbs-src-1.13.1/doc/qbs.qdocconf000066400000000000000000000001511347155106100162170ustar00rootroot00000000000000include(config/qbs-project.qdocconf) include($QT_INSTALL_DOCS/global/qt-html-templates-offline.qdocconf) qbs-src-1.13.1/doc/reference/000077500000000000000000000000001347155106100156555ustar00rootroot00000000000000qbs-src-1.13.1/doc/reference/cli/000077500000000000000000000000001347155106100164245ustar00rootroot00000000000000qbs-src-1.13.1/doc/reference/cli/builtin/000077500000000000000000000000001347155106100200725ustar00rootroot00000000000000qbs-src-1.13.1/doc/reference/cli/builtin/cli-build.qdoc000066400000000000000000000101121347155106100226010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-build.html \ingroup cli \title build \brief Builds a project. \section1 Synopsis \code qbs build [options] [[config:configuration-name] [property:value] ...] \endcode \section1 Description Builds projects in one or more configurations. You can specify \l{Project}{project}, \l{Product}{product}, or \l{List of Modules}{module} properties, as well as a \l{Profile} {profile} separately for each configuration. This is the default command. If the build directory does not exist, it will be created. For more information, see \l{Building Applications}. \section1 Options \target build-all-products \include cli-options.qdocinc all-products \include cli-options.qdocinc build-directory \include cli-options.qdocinc changed-files \include cli-options.qdocinc check-outputs \include cli-options.qdocinc check-timestamps \include cli-options.qdocinc clean_install_root \include cli-options.qdocinc command-echo-mode \include cli-options.qdocinc dry-run \include cli-options.qdocinc project-file \target build-force-probe-execution \include cli-options.qdocinc force-probe-execution \include cli-options.qdocinc jobs \include cli-options.qdocinc job-limits \include cli-options.qdocinc keep-going \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc no-install \target build-products \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \include cli-options.qdocinc show-progress \target no-fallback-module-provider \include cli-options.qdocinc no-fallback-module-provider \include cli-options.qdocinc wait-lock \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples Builds the application specified by the \c .qbs file in the current directory using the default profile: \code qbs \endcode Builds the application using four concurrent build jobs: \code qbs -j 4 \endcode Builds the default configuration of an application using the profile called \c Android: \code qbs build profile:Android \endcode Builds the application using different \l{cpp} module properties for debug and release configurations. For the debug configuration, warnings will cause the build to fail, whereas for the release configuration, the size of the build artifacts will be optimized. Both configurations are built with a profile named \c{"qt"}: \code qbs build profile:qt config:debug modules.cpp.treatWarningsAsErrors:true config:release modules.cpp.optimization:small \endcode */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-clean.qdoc000066400000000000000000000044051347155106100225740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-clean.html \ingroup cli \title clean \brief Removes the files generated during a build. \section1 Synopsis \code qbs clean [options] [config:configuration-name] \endcode \section1 Description Removes build \l{Artifact}{artifacts} for the specified build configuration. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc dry-run \include cli-options.qdocinc keep-going \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \include cli-options.qdocinc show-progress \section1 Parameters \include cli-parameters.qdocinc configuration-name \section1 Examples Removes the build artifacts in the current directory for the default build configuration: \code qbs clean \endcode */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-dump-nodes-tree.qdoc000066400000000000000000000040261347155106100245210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-dump-nodes-tree.html \ingroup cli \title dump-nodes-tree \brief Dumps the nodes in the build graph to \c stdout. \section1 Synopsis \code qbs dump-nodes-tree [options] [config:configuration-name] \endcode \section1 Description Dumps the nodes in the build graph to \c stdout. This is an internal command that is used for debugging purposes only. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \section1 Parameters \include cli-parameters.qdocinc configuration-name \section1 Examples Dumps the nodes tree into a file called \c nodes-tree.log: \code qbs dump-nodes-tree >nodes-tree.log \endcode */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-generate.qdoc000066400000000000000000000051741347155106100233100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-generate.html \ingroup cli \title generate \brief Invokes a project generator, for example to create project files for another build tool. \section1 Synopsis \code qbs generate [options] [[config:configuration-name] [property:value] ...] \endcode \section1 Description Invokes a project generator, for example to create project files for another build tool. For more information, see \l{Generators}. \section1 Options \target generate-generator \include cli-options.qdocinc generator \include cli-options.qdocinc build-directory \include cli-options.qdocinc project-file \include cli-options.qdocinc install-root \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc settings-dir \include cli-options.qdocinc show-progress \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples Generates a project for Microsoft Visual Studio: \code qbs generate -g visualstudio2015 \endcode Generates a \l{https://clang.llvm.org/docs/JSONCompilationDatabase.html} {Clang compilation database (clangdb)}: \code qbs generate --generator clangdb \endcode */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-help.qdoc000066400000000000000000000035221347155106100224410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-help.html \ingroup cli \title help \brief Shows general or command-specific help. \section1 Synopsis \code qbs help [] \endcode \section1 Description Shows a list of available commands with descriptions. Specify a command name to list the options that the command takes with descriptions. \section1 Options This command takes no options. \section1 Examples Shows an overview of all commands: \code qbs help \endcode Lists the options that the \c build command takes: \code qbs help build \endcode */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-install.qdoc000066400000000000000000000054751347155106100231700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-install.html \ingroup cli \title install \brief Installs a project. \section1 Synopsis \code qbs install [options] [[config:configuration-name] [property:value] ...] \endcode \section1 Description Install all files marked as installable to their respective destinations. The project is built first, if necessary, unless the \c --no-build option is given. For more information, see \l{Installing Files}. \section1 Options \include cli-options.qdocinc all-products \include cli-options.qdocinc build-directory \include cli-options.qdocinc changed-files \include cli-options.qdocinc check-outputs \include cli-options.qdocinc check-timestamps \include cli-options.qdocinc clean_install_root \include cli-options.qdocinc command-echo-mode \include cli-options.qdocinc dry-run \include cli-options.qdocinc project-file \include cli-options.qdocinc force-probe-execution \include cli-options.qdocinc install-root \include cli-options.qdocinc jobs \include cli-options.qdocinc keep-going \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc no-build \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \include cli-options.qdocinc wait-lock \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-list-products.qdoc000066400000000000000000000036431347155106100243310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-list-products.html \ingroup cli \title list-products \brief Lists all products in the given project. \section1 Synopsis \code qbs list-products [options] [config:configuration-name] \endcode \section1 Description Lists all products that exist in a project. \section1 Options \include cli-options.qdocinc project-file \include cli-options.qdocinc build-directory \include cli-options.qdocinc settings-dir \section1 Parameters \include cli-parameters.qdocinc configuration-name \section1 Examples To list all products for the project in the current directory: \code qbs list-products \endcode */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-resolve.qdoc000066400000000000000000000046571347155106100232020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-resolve.html \ingroup cli \title resolve \brief Resolves a project without building it. \section1 Synopsis \code qbs resolve [options] [[config:configuration-name] [property:value] ...] \endcode \section1 Description Resolves a \l{Project}{project} in one or more configurations. Run this command to change the properties of an existing build. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc dry-run \include cli-options.qdocinc project-file \include cli-options.qdocinc force-probe-execution \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc settings-dir \include cli-options.qdocinc show-progress \include cli-options.qdocinc no-fallback-module-provider \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples Resolves the default configuration of the project in the current directory: \code qbs resolve \endcode */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-run.qdoc000066400000000000000000000063521347155106100223210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-run.html \ingroup cli \title run \brief Runs an executable generated by building a project. \section1 Synopsis \code qbs run [options] [config:configuration-name] [property:value] ... [ -- ] \endcode \section1 Description Runs the specified product's executable with the specified \c . If the project has only one product, the \c --products option may be omitted. The product will be built if it is not up to date, unless the \c --no-build option is specified. For more information, see \l{build}. For more information about running applications, see \l{Running Applications}. \section1 Options \include cli-options.qdocinc all-products \include cli-options.qdocinc build-directory \include cli-options.qdocinc changed-files \include cli-options.qdocinc check-outputs \include cli-options.qdocinc check-timestamps \include cli-options.qdocinc clean_install_root \include cli-options.qdocinc command-echo-mode \include cli-options.qdocinc dry-run \include cli-options.qdocinc project-file \include cli-options.qdocinc force-probe-execution \include cli-options.qdocinc install-root \include cli-options.qdocinc jobs \include cli-options.qdocinc keep-going \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc log-time \include cli-options.qdocinc more-verbose \include cli-options.qdocinc no-build \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \include cli-options.qdocinc setup-run-env-config \include cli-options.qdocinc wait-lock \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Arguments \include cli-parameters.qdocinc arguments \section1 Examples Runs the Qt Creator application: \code qbs run --products qtcreator \endcode */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-shell.qdoc000066400000000000000000000041621347155106100226210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-shell.html \ingroup cli \title shell \brief Opens a shell with a product's environment. \section1 Synopsis \code qbs shell [options] [config:configuration-name] [property:value] \endcode \section1 Description Opens a shell in the environment that a build with the specified parameters would use. For more information, see \l{Using the Shell}. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc project-file \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings-dir \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples Opens a shell with the same environment that \QBS uses when building the project: \code qbs shell \endcode */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-status.qdoc000066400000000000000000000036661347155106100230450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-status.html \ingroup cli \title status \brief Shows the status of files in the project directory. \section1 Synopsis \code qbs status [options] [config:configuration-name] \endcode \section1 Description Lists all the files in the project directory and shows whether they are known to \QBS in the respective configuration. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc settings-dir \section1 Parameters \include cli-parameters.qdocinc configuration-name \section1 Examples To list the files in the project directory and view their status: \code qbs status \endcode */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-update-timestamps.qdoc000066400000000000000000000045671347155106100251710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-update-timestamps.html \ingroup cli \title update-timestamps \brief Marks the build as up-to-date. \section1 Synopsis \code qbs update-timestamps [options] [config:configuration-name] ... \endcode \section1 Description Updates the timestamps of all build \l{Artifact}{artifacts}, causing the next builds of the \l{Project}{project} to do nothing until source files are updated again. This command is useful if you know that the current changes to source files are irrelevant to the build. \note Using this command causes a discrepancy between the actual state of source files and the information in the build graph, so be careful. \section1 Options \include cli-options.qdocinc build-directory \include cli-options.qdocinc less-verbose \include cli-options.qdocinc log-level \include cli-options.qdocinc more-verbose \include cli-options.qdocinc products-specified \include cli-options.qdocinc settings \section1 Parameters \include cli-parameters.qdocinc configuration-name \include cli-parameters.qdocinc property \section1 Examples */ qbs-src-1.13.1/doc/reference/cli/builtin/cli-version.qdoc000066400000000000000000000030321347155106100231720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-version.html \ingroup cli \title show-version \brief Prints the \QBS version. \section1 Synopsis \code qbs show-version \endcode \section1 Description Prints the version of \QBS to stdout. \section1 Options This command takes no options. */ qbs-src-1.13.1/doc/reference/cli/cli-options.qdocinc000066400000000000000000000304641347155106100222350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! //! [all-products] \section2 \c --all-products Processes all \l{Product}{products}, even if their \c builtByDefault property is \c false. //! [all-products] //! [blacklist] \section2 \c {--blacklist } Ignores files whose names match the patterns specified by \c . The list entries can contain wildcards and are separated by commas. By default, no files are ignored. //! [blacklist] //! [build-directory] \section2 \c {--build-directory|-d } Specifies a \c where build artifacts are stored. The default value is the current directory unless \c preferences.defaultBuildDirectory is set. Relative paths will be interpreted relative to the current directory. You can use the following special values as placeholders: \list \li \c @project is expanded to the name of the project file excluding the extension \c .qbs. \li \c @path is expanded to the name of the directory containing the project file. \endlist //! [build-directory] //! [changed-files] \section2 \c {--changed-files [,...]} Assumes that the files specified by \c , and only those files, have changed. //! [changed-files] //! [check-outputs] \section2 \c --check-outputs Forces transformer output \l{Artifact}{artifact} checks. Verifies that the output artifacts declared by \l{Rule}{rules} in the \l{Project}{project} are actually created. //! [check-outputs] //! [check-timestamps] \section2 \c --check-timestamps Forces timestamp checks. Retrieves the timestamps from the file system, instead of using the file timestamps that are stored in the build graph. //! [check-timestamps] //! [clean_install_root] \section2 \c --clean-install-root Removes the installation base directory before installing. //! [clean_install_root] //! [command-echo-mode] \section2 \c {--command-echo-mode } Determines what kind of output to show when executing commands. Possible values of \c are: \list \li \c silent \li \c summary (default value) \li \c command-line \li \c command-line-with-environment \endlist //! [command-echo-mode] //! [detect-qt-versions] \section2 \c --detect Attempts to auto-detect all known Qt versions, looking them up in the PATH environment variable. //! [detect-qt-versions] //! [detect-toolchains] \section2 \c --detect Attempts to auto-detect all known toolchains, looking them up in the PATH environment variable. //! [detect-toolchains] //! [dry-run] \section2 \c --dry-run|-n Performs a dry run. No commands will be executed and no permanent changes to the build graph will be done. //! [dry-run] //! [export] \section2 \c {--export } Exports settings to the specified \c . //! [export] //! [project-file] \section2 \c {[--file|-f ]} Uses \c as the project file. If \c is a directory and it contains a single file with the extension \c .qbs, that file will be used. If this option is not given at all, the behavior is the same as for \c{-f }. //! [project-file] //! [flat] \section2 \c --flat Does not create nested project files, even if there are subdirectories and the top-level directory does not contain any files. //! [flat] //! [force-probe-execution] \section2 \c --force-probe-execution Forces re-execution of all \l{Probe} items' configure scripts, rather than using the cached data. //! [force-probe-execution] //! [generator] \section2 \c {--generator|-g } Uses the specified build system generator. Possible values of \c include: \list \li \c clangdb \li \c visualstudio2015 \endlist The available generators are listed if you run the \c {qbs generate} command without passing a generator to it. //! [generator] //! [help] \section2 \c {--help|-h|-?} Displays help for the command. //! [help] //! [import] \section2 \c {--import } Imports settings from the specified \c . //! [import] //! [install-root] \section2 \c {--install-root } Installs into the specified \c . If the directory does not exist, it will be created. The default value is \c /install-root. Use the special value \c @sysroot to install into the \c sysroot. That is, the value of the \l{qbs::sysroot}{qbs.sysroot} property. //! [install-root] //! [jobs] \section2 \c {--jobs|-j } Uses \c concurrent build jobs, where \c must be an integer greater than zero. The default is the number of logical cores. //! [jobs] //! [job-limits] \section2 \c {--job-limits :[,:...]} Sets pool-specific job limits. See \l{job-pool-howto}{here} for more information on job pools. \section2 \c {--enforce-project-job-limits} Normally, job limits defined in project files via the \l JobLimit item get overridden by those set on the command line. If this option is passed, they get maximum priority instead. Use it if there are product-specific limits that make more sense for that part of the code base than the generic ones you'd like to apply globally. //! [job-limits] //! [keep-going] \section2 \c --keep-going|-k Keeps going when errors occur, if at all possible. //! [keep-going] //! [less-verbose] \section2 \c --less-verbose|-q Becomes more quiet by decreasing the log level by one. This option can be given more than once. Excessive occurrences have no effect. If the option \c --log-level appears anywhere on the command line in addition to this option, its value is taken as the base for the decrease. //! [less-verbose] //! [list-root] \section2 \c {--list [ ...]} Lists keys under the key \c or all keys if the root is not specified. Possible values are: \list \li \c defaultProfile is the default \l{Profile}{profile} to use if a profile is not specified \li \c preferences accepts build preferences as second-level keys \li \c profiles accepts profile names as second-level keys \endlist //! [list-root] //! [config-user] \section2 \c {--user} Causes read operations to display only the user-level settings, while the system-level settings are ignored. Write operations will target the user-level settings, which is also the default. //! [config-user] //! [config-system] \section2 \c {--system} Read and write operations will consider only the system-level settings. //! [config-system] //! [config-ui-system] \section2 \c {--system} Instructs the tool to work on the system-level settings. Otherwise, the user-level settings are presented. //! [config-ui-system] //! [log-level] \section2 \c {--log-level } Uses the specified log level. Possible values of \c are: \list \li \c error \li \c warning \li \c info (default value) \li \c debug \li \c trace \endlist //! [log-level] //! [log-time] \section2 \c --log-time Logs the time that the operations involved in this command take. This option is implied in log levels \c debug and higher. This option is mutually exclusive with \c --show-progress. //! [log-time] //! [more-verbose] \section2 \c --more-verbose|-v Becomes more verbose by increasing the log level by one. This option can be given more than once. Excessive occurrences have no effect. If the option \c --log-level appears anywhere on the command line in addition to this option, its value is taken as the base for the increase. //! [more-verbose] //! [ndk-dir] \section2 \c {--ndk-dir } Specifies a \c that contains an Android NDK. //! [ndk-dir] //! [no-build] \section2 \c --no-build Does not re-build the project before installing or running it. //! [no-build] //! [no-install] \section2 \c --no-install Does not install any artifacts as part of the build process. //! [no-install] //! [products-specified] \section2 \c {--products|-p [,...]} Takes only the \l{Product}{products} specified by \c and their dependencies into account. //! [products-specified] //! [qt-dir] \section2 \c {--qt-dir } Specifies a \c that contains a Qt version. //! [qt-dir] //! [sdk-dir] \section2 \c {--sdk-dir } Specifies a \c that contains an Android SDK. //! [sdk-dir] //! [settings-dir] \section2 \c {--settings-dir } Reads all settings (such as \l{Profile}{profile} information) from the specified \c . If the directory does not exist, it will be created. The default value is system-specific. For example: \list \li Linux: \c $HOME/.config/QtProject/qbs \li Windows: \c %APPDATA%\QtProject\qbs \li macOS: \c $HOME/Library/Preferences/qbs \endlist //! [settings-dir] //! [setup-run-env-config] \section2 \c --setup-run-env-config A comma-separated list of strings. They will show up in the \c config parameter of all \l{Module::}{setupRunEnvironment} scripts. //! [setup-run-env-config] //! [show-progress] \section2 \c --show-progress Shows how command execution is progressing. This option is mutually exclusive with \c --log-time. //! [show-progress] //! [no-fallback-module-provider] \section2 \c --no-fallback-module-provider If this option is set, then \QBS will not fall back to a pkg-config based \l{Module Providers}{module provider} if a dependency is not found. //! [no-fallback-module-provider] //! [setup-tools-system] \section2 \c {--system} If this option is given, the profile(s) created by this tool will end up in the system-level settings and thus be available to all users. Otherwise, they go into the user-level settings. //! [setup-tools-system] //! [type] \section2 \c {--type } Specifies the type of the toolchain. Needed if \QBS cannot determine the compiler from the name of the executable file located in the specified directory. Possible values include: \list \li \c clang \li \c gcc \li \c mingw \li \c msvc \li \c iar \li \c keil \endlist //! [type] //! [unset] \section2 \c {--unset } Removes the specified \c . //! [unset] //! [wait-lock] \section2 \c --wait-lock Waits indefinitely for other processes to release the build graph lock. This option is typically used by \l{Generators}{generators}, which may re-invoke multiple \QBS processes on the same project simultaneously. //! [wait-lock] //! [whitelist] \section2 \c {--whitelist } Considers only files whose names match the patterns specified by \c . The list entries can contain wildcards and are separated by commas. By default, all files are considered. //! [whitelist] */ qbs-src-1.13.1/doc/reference/cli/cli-parameters.qdocinc000066400000000000000000000072131347155106100227010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! //! [arguments] \section2 \c -- Command-line arguments to be passed to the program to be run. //! [arguments] //! [configuration-name] \section2 \c config:configuration-name Specifies the build configuration to use. \QBS can build a project for one or multiple configurations at once, each having a different set of parameters. The \c config parameter has a special function: with each occurrence a new configuration instance begins and all subsequent parameters until the next \c config are assigned to this instance. Parameter assignments before the first occurrence of \c config are applied to all build configurations. Inside products and modules, the current active build configuration can be retrieved via \l{qbs::configurationName}{qbs.configurationName}. In the following snippet, a profile \c clang is applied to all configurations while \c cpp.optimization is different for \c debug and \c release: \code profile:clang config:debug cpp.optimization:none config:release cpp.optimization:small \endcode The value of \c config determines the name of the build folder and affects the default value of the \l{qbs::buildVariant}{qbs.buildVariant} property. \QBS knows the \c config values \c{"debug"} and \c{"release"}, but in general any name can be chosen. When naming configurations created for special purposes, follow the rules for legal names generally used in programming languages: \list \li The first character must be a letter (a-z), an underscore (_), or a dollar sign ($). \li Subsequent characters may be letters, digits, underscores, or dollar signs. \endlist //! [configuration-name] //! [key] \section2 \c Typically, a \c consists of several levels separated by periods. The first level shows a \e root value, such as \e preferences or \e profiles. The root determines whether the second-level keys are build preferences or profile names. The lower level keys consist of a module name, followed by a property name. //! [key] //! [property] \section2 \c {property:value} Property values set in project files or profiles can be overridden on the command line. The syntax is: \code .: \endcode For more information, see \l{Overriding Property Values from the Command Line}. //! [property] */ qbs-src-1.13.1/doc/reference/cli/cli.qdoc000066400000000000000000000033121347155106100200420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage reference.html \group cli \title Command-Line Interface \brief A list of available command-line commands. The \c qbs command-line commands can be invoked as \c{qbs }. This reference summarizes the command-line commands. The authoritative source of up-to-date information is the respective help screen, which you get by calling \c{qbs help }. Some commands are described in context in the \l{Usage} section of the manual. */ qbs-src-1.13.1/doc/reference/cli/tools/000077500000000000000000000000001347155106100175645ustar00rootroot00000000000000qbs-src-1.13.1/doc/reference/cli/tools/cli-config-ui.qdoc000066400000000000000000000041731347155106100230660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-config-ui.html \ingroup cli \title config-ui \brief Opens a GUI application for managing \QBS settings, such as preferences and profiles. \section1 Synopsis \code qbs config-ui [--settings-dir ] [--system] \endcode \section1 Description Opens the \QBS Settings application for managing \QBS settings, such as preferences and profiles, in a hierarchical view. This makes it easier to manage a large number of settings than using the \l{config} command from the command line. \image qbs-settings-gui.png For more information, see \l{Configuring Profiles and Preferences}. \section1 Options \include cli-options.qdocinc settings-dir \include cli-options.qdocinc config-ui-system \include cli-options.qdocinc help \section1 Examples Opens \QBS Settings: \code qbs config-ui \endcode */ qbs-src-1.13.1/doc/reference/cli/tools/cli-config.qdoc000066400000000000000000000106731347155106100224550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-config.html \ingroup cli \title config \brief Manages \QBS settings, such as preferences and profiles. \section1 Synopsis \code qbs config [--settings-dir ] [--user|--system] [--list [ ...]] [--unset ] [--export ] [--import ] qbs config [--settings-dir ] [--user|--system] qbs config [--settings-dir ] [--user|--system] \endcode \section1 Description Manages \QBS settings, such as preferences and profiles. You can list all keys and remove the specified key, as well as import settings from a file or export them to a file. The second form of this command displays the specified \c . The third form sets the specified \c with the specified \c . There are two sets of settings: The system-level settings affect all users, while the user-level settings are specific to the current user. By default, the read operations consider both sources. If the same key is present in both settings, then for list values, the system value is appended to the user value, while for other types of values the user-level one takes precedence. Write operations go to the user-level settings by default. Use the \c {--user} and \c {--system} options to change this behavior. \note It is conceivable that the default system value of the \c {preferences.qbsSearchPaths} setting could pull in unwanted \QBS modules, in particular when doing cross-builds. In such a case, you can set \c {preferences.ignoreSystemSearchPaths} to exclude the search paths coming from the system settings. You'll typically do this for a specific profile: \code $ qbs config profiles.myprofile.preferences.ignoreSystemSearchPaths true \endcode You can use the \l{config-ui} command to open the Qbs Settings tool for managing settings in a hierarchical view. For more information, see \l{Configuring Profiles and Preferences}, \l{Managing Qt Versions}, \l{Modules}, \l {List of Modules}, and \l{Custom Modules and Items}. \section1 Options \include cli-options.qdocinc settings-dir \include cli-options.qdocinc list-root \include cli-options.qdocinc unset \include cli-options.qdocinc export \include cli-options.qdocinc import \include cli-options.qdocinc config-user \include cli-options.qdocinc config-system \include cli-options.qdocinc help \section1 Parameters \include cli-parameters.qdocinc key \section1 Examples Lists the existing profiles: \code qbs config --list profiles \endcode Shows the default profile: \code qbs config defaultProfile \endcode \note If no output is shown, the default profile used is the built-in profile \c none, which sets no properties. Sets the profile called \c gcc as the base profile of the Qt profile called \c myqt: \code qbs config profiles.myqt.baseProfile gcc \endcode Adds the location of a custom module to your preferences, to make the module accessible in several projects: \code qbs config preferences.qbsSearchPaths /usr/local/share/custom-qbs-extensions \endcode */ qbs-src-1.13.1/doc/reference/cli/tools/cli-create-project.qdoc000066400000000000000000000046301347155106100241130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-create-project.html \ingroup cli \title create-project \brief Creates a \QBS project from an existing set of source files. \section1 Synopsis \code qbs create-project [--blacklist ] [--whitelist ] [--flat] \endcode \section1 Description Automatically generates \QBS project files from an arbitrary directory structure. You can filter the files to add to the project by blacklisting or whitelisting them. The command creates nested project files, unless you use the \c --flat option. This is a useful starting point when migrating from other build tools, such as qmake or CMake. \note Run this command from the project directory. After generating the initial .qbs files, add the missing configuration variables and functions to them. \section1 Options \include cli-options.qdocinc blacklist \include cli-options.qdocinc whitelist \include cli-options.qdocinc flat \include cli-options.qdocinc help \section1 Examples Creates \c .qbs files in the project directory when run from there: \code qbs create-project \endcode */ qbs-src-1.13.1/doc/reference/cli/tools/cli-setup-android.qdoc000066400000000000000000000045241347155106100237640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-setup-android.html \ingroup cli \title setup-android \brief Creates \QBS profiles for Android SDK and NDK installations. \section1 Synopsis \code qbs setup-android [--settings-dir ] [--ndk-dir ] [--sdk-dir ] [--qt-dir ] \endcode \section1 Description Creates \QBS profiles for Android SDK and NDK installations. If a Qt path is given, these additional profiles will be suitable for building Qt binaries for the respective architecture, if the Qt installation has support for it. \section1 Options \include cli-options.qdocinc settings-dir \include cli-options.qdocinc ndk-dir \include cli-options.qdocinc sdk-dir \include cli-options.qdocinc qt-dir \include cli-options.qdocinc help \section1 Examples Creates a profile with the name \c oreo that specifies the target platforms' \l{qbs::}{architectures} and operating systems, as well as the toolchains available: \code qbs setup-android oreo \endcode */ qbs-src-1.13.1/doc/reference/cli/tools/cli-setup-qt.qdoc000066400000000000000000000046311347155106100227670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-setup-qt.html \ingroup cli \title setup-qt \brief Creates \QBS profiles for Qt installations. \section1 Synopsis \code qbs setup-qt [--settings-dir ] [--system] --detect qbs setup-qt [--settings-dir ] [--system] \endcode \section1 Description Creates \QBS profiles for Qt installations. The first form tries to auto-detect all known Qt versions, looking them up via the PATH variable. The second form creates a profile with the name \c {} for the Qt version located at \c {}. For more information, see \l{Managing Qt Versions}. \section1 Options \include cli-options.qdocinc detect-qt-versions \include cli-options.qdocinc settings-dir \include cli-options.qdocinc setup-tools-system \include cli-options.qdocinc help \section1 Examples Looks up Qt versions in the PATH and creates profiles for them: \code qbs setup-qt --detect \endcode Creates a profile called \c myqt for the Qt version located in \c /usr/bin/qmake: \code qbs setup-qt /usr/bin/qmake myqt \endcode */ qbs-src-1.13.1/doc/reference/cli/tools/cli-setup-toolchains.qdoc000066400000000000000000000057631347155106100245150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage cli.html \page cli-setup-toolchains.html \ingroup cli \title setup-toolchains \brief Creates \QBS profiles for toolchains, such as GCC or MSVC. \section1 Synopsis \code qbs setup-toolchains [--settings-dir ] [--system] --detect qbs setup-toolchains [--settings-dir ] [--system] [--type ] \endcode \section1 Description The first form tries to auto-detect all known toolchains, looking them up via the PATH variable. The second form creates a profile with the name \c {} for the toolchain located at \c {}. It will attempt to determine the toolchain type automatically based on the file name or the compiler executable. If that fails, you need to provide the compiler type as a value of the \c --type option. For more information, see \l{Configuring Profiles and Preferences}. \section1 Options \include cli-options.qdocinc settings-dir \include cli-options.qdocinc setup-tools-system \include cli-options.qdocinc detect-toolchains \include cli-options.qdocinc type \include cli-options.qdocinc help \section1 Examples Looks up toolchains via the PATH variable and creates profiles for them: \code qbs setup-toolchains --detect \endcode Creates a profile called \c mingw for the toolchain located in \c C:\mingw530_32\bin on Windows: \code qbs setup-toolchains C:\mingw530_32\bin\g++.exe mingw \endcode Creates a profile called \c g++-mingw-w64 for the toolchain located in \c /usr/bin/x86_64-w64-mingw32-g++ g++-mingw-w64 on Ubuntu: \code qbs setup-toolchains /usr/bin/x86_64-w64-mingw32-g++ g++-mingw-w64 \endcode */ qbs-src-1.13.1/doc/reference/commands.qdoc000066400000000000000000000222141347155106100203270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ // TODO: "\c" markup is used for all properties in table due to QTBUG-35505. /*! \contentspage reference.html \page commands.html \title Command and JavaScriptCommand \brief Types of commands to be used in rules A \e command is what \QBS executes at build time. It is represented in the language by an object of type \c Command, which runs a process, or \c JavaScriptCommand, which executes arbitrary JavaScript code. A command is always created in the prepare script of a \c Rule. \section1 Command A \c Command represents a process that will be invoked at build time. Its constructor arguments are the binary to run and a list of command-line arguments. For instance: \code var insaneCommand = new Command("rm", ["-r", "/"]); \endcode The \l{Rule} item documentation shows a \c Command in context. \section1 JavaScriptCommand A \c JavaScriptCommand represents a chunk of JavaScript code that is run at build time. For instance: \code var cmd = new JavaScriptCommand(); cmd.apology = "Sorry."; cmd.sourceCode = function() { console.info("I'm a rather pointless command."); console.info(apology); }; \endcode Within the source code, the special identifiers \c project and \c product (giving access to project and product properties, respectively) as well as \c inputs and \c outputs are available. As the example shows, arbitrary properties can be set on the command object and then used within the source code. This technique is typically used to forward values from the prepare script to the command. The \l{Rule} item documentation shows a \c JavaScriptCommand in context. \section1 Properties \section2 Common Properties The following properties are available in both \c Command and \c JavaScriptCommand. \table \header \li Property \li Type \li Default \li Description \row \li \c description \li string \li empty \li A message that is displayed when the command is executed. \row \li \c extendedDescription \li string \li empty \li A detailed description that is displayed when the command is executed. \row \li \c highlight \li string \li empty \li A tag that can be used to influence how the \c description is displayed. In principle, the values are arbitrary. The \QBS command-line tool understands the following values and maps them to different colors if the output device is a terminal: \list \li "compiler" indicates that the command processes source code \li "linker" indicates that the command links objects \li "codegen" indicates that the command generates source code \li "filegen" indicates that the command creates arbitrary files \endlist All other values are mapped to the default color. \row \li \c jobPool \li string \li empty \li Determines which job pool the command will use. An empty string, which is the default, stands for the global job pool. See \l{JobLimit}{here} and \l{job-pool-howto}{here} for more information on job pools. \row \li \c silent \li bool \li false \li A flag that controls whether the \c description is printed. Set it to \c true for commands that users need not know about. \note If this property is \c false, then \c description must not be empty. \endtable \section2 Command Properties \table \header \li Property \li Type \li Default \li Description \row \li \c arguments \li stringList \li empty \li The list of arguments to invoke the command with. Explicitly setting this property overrides an argument list provided when instantiating the object. \row \li \c environment \li stringList \li empty \li A list of environment variables that are added to the common build environment. They are provided as a list of strings in the form "varName=value". \row \li \c maxExitCode \li int \li 0 \li The maximum exit code from the process to interpret as success. Setting this should rarely be necessary, as all well-behaved applications use values other than zero to indicate failure. \row \li \c program \li string \li undefined \li The binary to invoke. Explicitly setting this property overrides a path provided when instantiating the object. \row \li \c relevantEnvironmentVariables \li stringList \li undefined \li Names of environment variables that the invoked binary considers. If one of these variables changes in the build environment, the command will be re-run even if the input files are still up to date. \row \li \c responseFileThreshold \li int \li 32000 on Windows, -1 elsewhere \li If this value is greater than zero and less than the length of the full command line, and if \c responseFileUsagePrefix is not empty, the contents of the command line are moved to a temporary file, whose path becomes the entire contents of the argument list. The program is then supposed to read the full argument list from that file. This mechanism is mainly useful to work around Windows limitations regarding the maximum length of the command line and will only work with programs that explicitly support it. \row \li \c responseFileArgumentIndex \li int \li 0 \li Index of the first argument to include in the response file. For example this may be used in conjunction with a compiler wrapper where the first argument (the path to the compiler) must be included on the raw command line. \row \li \c responseFileUsagePrefix \li string \li empty \li The prefix that informs \c program that the rest of the argument is a path to a file containing the actual command line. \row \li \c stderrFilterFunction \li function \li undefined \li A function that takes as input the command's actual standard error output and returns a string that is presented to the user as the command's standard error output. If it is not set, the output is shown unfiltered. \row \li \c stdoutFilterFunction \li function \li undefined \li A function that takes as input the command's actual standard output and returns a string that is presented to the user as the command's standard output. If it is not set, the output is shown unfiltered. \row \li \c workingDirectory \li string \li empty \li The program's working directory. \row \li \c stdoutFilePath \li string \li undefined \li Redirects the filtered standard output content to \c stdoutFilePath. If \c stdoutFilePath is undefined, the filtered standard output is forwarded to \QBS, possibly to be printed to the console. \row \li \c stderrFilePath \li string \li undefined \li Redirects the filtered standard error output content to \c stderrFilePath. If \c stderrFilePath is undefined, the filtered standard error output is forwarded to \QBS, possibly to be printed to the console. \endtable \section2 JavaScriptCommand Properties \table \header \li Property \li Type \li Default \li Description \row \li \c sourceCode \li function \li undefined \li The JavaScript function to execute. \endtable */ qbs-src-1.13.1/doc/reference/items/000077500000000000000000000000001347155106100167765ustar00rootroot00000000000000qbs-src-1.13.1/doc/reference/items/convenience/000077500000000000000000000000001347155106100212725ustar00rootroot00000000000000qbs-src-1.13.1/doc/reference/items/convenience/appleapplicationdiskimage.qdoc000066400000000000000000000101511347155106100273430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \nextpage AppleDiskImage \qmltype AppleApplicationDiskImage \since Qbs 1.9 \inherits AppleDiskImage \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.AppleApplicationDiskImage \brief Apple application drag 'n' drop disk image installer. An AppleApplicationDiskImage item is a \l{Product}{product} of the \l{Product::}{type} \c{"dmg.dmg"} that has a dependency on the \l{dmg} module. In addition, it has rules and properties specific to building drag 'n' drop disk image installers with an application bundle and symbolic link to the \c /Applications directory. Any artifacts of product dependencies that are tagged \c{"installable"} will be copied into the disk image, provided their file paths are relative to the path specified by the \l{sourceBase} property (that is, are located in that directory). Any artifacts tagged \c{"installable"} that are not relative to \l{sourceBase} will be ignored. Here is what the project file could look like for a simple DMG installer: \code AppleApplicationDiskImage { Depends { name: "myapp" } name: "My App" dmg.volumeName: name dmg.iconSize: 128 dmg.windowWidth: 640 dmg.windowHeight: 280 dmg.iconPositions: [ {"path": "Applications", "x": 128, "y": 128}, {"path": "My App.app", "x": 256, "y": 128} ] files: ["background.tiff", "volume-icon.icns"] Group { files: ["*.lproj/**"] // licenses fileTags: ["dmg.license.input"] } } \endcode For plain disk images whose contents are not a single application bundle, consider the base \l{AppleDiskImage} item instead. */ /*! \qmlproperty string AppleApplicationDiskImage::sourceBase The base directory from which artifacts installed into the disk image will be copied. This directory is always considered to be relative to \l{qbs::installRoot} {qbs.installRoot}. For example, if the application Example.app exists at \c{qbs.installRoot/Applications/Example.app}, and the value of this property is \c{"/Applications"}, the application will be located at\c{/Example.app} relative to the disk image root. Therefore, its full path when the disk image is mounted would be something like \c{/Volumes/Example-1.0/Example.app}. \defaultvalue \c{"/Applications"} */ /*! \qmlproperty stringList AppleApplicationDiskImage::symlinks List of symlinks to create in the disk image. This is specified as a list of strings, each string containing two file paths separated by a colon. The first path is the symlink target, and the second path is the name of the symlink relative to the root of the disk image. \defaultvalue \c{["/Applications:Applications"]} */ qbs-src-1.13.1/doc/reference/items/convenience/applediskimage.qdoc000066400000000000000000000034361347155106100251270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage AppleApplicationDiskImage \nextpage Application \qmltype AppleDiskImage \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.AppleDiskImage \brief Apple disk image. An AppleDiskImage item is a is a \l{Product}{product} of the \l{Product::} {type} \c{"dmg.dmg"} that has a dependency on the \l{dmg} module. For single-application drag 'n' drop disk image installers, you will probably want to use the \l{AppleApplicationDiskImage} item instead. */ qbs-src-1.13.1/doc/reference/items/convenience/application.qdoc000066400000000000000000000050651347155106100244530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage AppleApplicationDiskImage \nextpage ApplicationExtension \qmltype Application \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.Application \brief Product of the type application. An Application item is a \l{Product} representing an application. The target artifact of this type of product is usually an executable binary tagged \c "application". However, on Android, unless you set \l{Product::}{consoleApplication} to \c true, the application target will be an APK package tagged \c "android.apk", and a dependency to the \l{Android.sdk} module is automatically added to the product. */ /*! \qmlproperty bool Application::install If \c{true}, the executable that is produced when building the application will be installed to \l installDir. \defaultvalue \c false \since Qbs 1.13 */ /*! \qmlproperty string Application::installDir Where to install the executable that is produced when building the application, if \l install is enabled. The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} when constructing the actual installation directory. \defaultvalue \c Applications if the app is a \l{bundle::isBundle}{bundle}, \c bin otherwise. \since Qbs 1.13 */ qbs-src-1.13.1/doc/reference/items/convenience/applicationextension.qdoc000066400000000000000000000033751347155106100264120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage Application \nextpage AutotestRunner \qmltype ApplicationExtension \inherits XPCService \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.ApplicationExtension \brief Application Extension for iOS, macOS, tvOS, or watchOS. An ApplicationExtension item is a \l{Product} based on the \l{XPCService} item that sets some properties required for iOS, macOS, tvOS, or watchOS Application Extensions. */ qbs-src-1.13.1/doc/reference/items/convenience/autotestrunner.qdoc000066400000000000000000000111371347155106100252470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage ApplicationExtension \nextpage CppApplication \qmltype AutotestRunner \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.AutotestRunner \brief Product that runs all autotests in the project. An AutotestRunner has a dependency on all \l{Product}{products} with the \l{Product::}{type} \c "autotest". Building the AutotestRunner product will then run the respective executables. The \l{Product::}{builtByDefault} property is set to \c false by default, so running the autotests has to be explicitly requested. The default name of the product is \c "autotest-runner". To use this feature: \list 1 \li Attach the \c "autotest" type to your autotests: \code CppApplication { name: "tst_mytest" type: ["application", "autotest"] // ... } \endcode \li Instantiate exactly one AutotestRunner in your project, typically at the top level: \code Project { // ... AutotestRunner { } // ... } \endcode \li Trigger the autotest execution by building the product: \code qbs build -p autotest-runner \endcode \endlist */ /*! \qmlproperty stringList AutotestRunner::arguments The list of arguments to invoke the autotest with. A test can override this by setting the \l{autotest::arguments}{arguments} property of the \l autotest module. \defaultvalue \c [] */ /*! \qmlproperty stringList AutotestRunner::auxiliaryInputs This property can contain arbitrary file tags. The AutotestRunner will get dependencies on all products whose type matches at least one of these tags, and invocation of the test executables will happen only after all of the respective artifacts have been built. Set this property if your test executables have run-time dependencies on other products. \nodefaultvalue \since Qbs 1.12 */ /*! \qmlproperty stringList AutotestRunner::environment A list of environment variables that are added to the run environment. They are provided as a list of strings in the form \c "varName=value". \defaultvalue DYLD_LIBRARY_PATH, DYLD_FRAMEWORK_PATH, and DYLD_ROOT_PATH are set on macOS, or an empty list for other platforms. */ /*! \qmlproperty bool AutotestRunner::limitToSubProject By default, only those autotests are considered that are in the same sub-project that AutotestRunner was instantiated in. If you want to run all autotests regardless of their location in the project hierarchy, set this property to \c false. \defaultvalue \c true */ /*! \qmlproperty string AutotestRunner::workingDir If this property is set, it will be the working directory for all invoked test executables. Otherwise, the working directory will the the parent directory of the respective executable. A test can override this by setting the \l{autotest::workingDir}{workingDir} property of the \l autotest module. \nodefaultvalue \since Qbs 1.12 */ /*! \qmlproperty stringList AutotestRunner::wrapper Wrapper binary and its arguments for wrapping autotest calls. This is useful for tools like Valgrind and alike. \defaultvalue empty */ qbs-src-1.13.1/doc/reference/items/convenience/cppapplication.qdoc000066400000000000000000000033111347155106100251460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage AutotestRunner \nextpage DynamicLibrary \qmltype CppApplication \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.CppApplication \brief C++ application. A CppApplication is a \l{Product}{product} that has a dependency on the \l{cpp} module. It is entirely equivalent to the following: \code Application { Depends { name: "cpp" } } \endcode */ qbs-src-1.13.1/doc/reference/items/convenience/dynamiclibrary.qdoc000066400000000000000000000063041347155106100251560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage CppApplication \nextpage InnoSetup \qmltype DynamicLibrary \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.DynamicLibrary \brief Dynamic library. A DynamicLibrary item is a \l{Product} of the \l{Product::}{type} \c "dynamiclibrary". For Android targets, the following applies: \list \li The \l{Product::type}{Product.type} property value contains \c "android.nativelibrary" in addition to \c "dynamiclibrary". \li There is a dependency on the \l{cpp} and \l{Android.ndk} modules. \endlist */ /*! \qmlproperty bool DynamicLibrary::install If \c{true}, the library will be installed to \l installDir. \defaultvalue \c false \since Qbs 1.13 */ /*! \qmlproperty string DynamicLibrary::installDir Where to install the library, if \l install is enabled. On Unix, the symbolic links are also installed to this location. The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} when constructing the actual installation directory. \defaultvalue \c Library/Frameworks if the library is a \l{bundle::isBundle}{bundle}, otherwise \c bin for Windows and \c lib for Unix-like targets. \since Qbs 1.13 */ /*! \qmlproperty bool DynamicLibrary::installImportLib If \c{true}, the import library will be installed to \l importLibInstallDir. This property is only relevant for Windows targets. Enable it if you want to create a development package. \defaultvalue \c false \since Qbs 1.13 */ /*! \qmlproperty string DynamicLibrary::importLibInstallDir Where to install the import library, if \l installImportLib is enabled. The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} when constructing the actual installation directory. This property is only relevant for Windows targets. \defaultvalue \c lib \since Qbs 1.13 */ qbs-src-1.13.1/doc/reference/items/convenience/innosetup.qdoc000066400000000000000000000032101347155106100241620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage DynamicLibrary \nextpage InstallPackage \qmltype InnoSetup \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.InnoSetup \brief Inno Setup installer executable. A InnoSetup item is a \l{Product}{product} of the \l{Product::}{type} \c{"innosetup.exe"} that has a dependency on the \l{innosetup} module. */ qbs-src-1.13.1/doc/reference/items/convenience/installpackage.qdoc000066400000000000000000000055711347155106100251340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage InnoSetup \nextpage JavaClassCollection \qmltype InstallPackage \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.InstallPackage \brief Archive of an installed project. An InstallPackage item is a \l{Product}{product} of the \l{Product::}{type} \c{archiver.archive} that has a \l{Depends}{dependency} on the \l{archiver} module. It is used to produce an archive from a set of installable files. Consider the following example project: \code Project { CppApplication { name: "myapp" Depends { name: "mylib" } files: ["main.cpp"] Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "bin" } } DynamicLibrary { name: "mylib" files: ["mylib.cpp"] Group { name: "public headers" files: ["mylib.h"] qbs.install: true qbs.installDir: "include" } Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "lib" } } InstallPackage { archiver.type: "tar" name: "tar-package" Depends { name: "myapp" } Depends { name: "mylib" } } } \endcode Building the product \c "tar-package" on a Unix system will result in a tar file with these contents: \code include/mylib.h lib/libmylib.so bin/myapp \endcode */ qbs-src-1.13.1/doc/reference/items/convenience/javaclasscollection.qdoc000066400000000000000000000034171347155106100261720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage InstallPackage \nextpage JavaJarFile \qmltype JavaClassCollection \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.JavaClassCollection \brief Collection of Java class files not bundled in a jar file. A JavaClassCollection item is a \l{Product}{product} of the \l{Product::} {type} \c{"java.class"} that has a dependency on the \l{java} module. If the files should end up in a jar file, you should use \l{JavaJarFile} instead. */ qbs-src-1.13.1/doc/reference/items/convenience/javajarfile.qdoc000066400000000000000000000034611347155106100244240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage JavaClassCollection \nextpage LoadableModule \qmltype JavaJarFile \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.JavaJarFile \brief Collection of Java class files bundled in a jar file. A JavaJarFile item is a \l{Product}{product} of the \l{Product::}{type} \c{java.jar}. It is used to produce a jar archive from a set of Java sources. */ /*! \qmlproperty string JavaJarFile::entryPoint The entry point for an executable jar file. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/items/convenience/loadablemodule.qdoc000066400000000000000000000032571347155106100251220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage JavaJarFile \nextpage QtApplication \qmltype LoadableModule \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.LoadableModule \brief Loadable module. A LoadableModule item is a \l{Product}{product} of the \l{Product::}{type} \c{"loadablemodule"}. It exists for the convenience of project file authors. */ qbs-src-1.13.1/doc/reference/items/convenience/qtapplication.qdoc000066400000000000000000000034411347155106100250140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage LoadableModule \nextpage QtGuiApplication \qmltype QtApplication \inherits CppApplication \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.QtApplication \brief Application with a dependency on the Qt Core module. A QtApplication is a \l{CppApplication}{C++ application} that has a \l{Depends}{dependency} on the \l{Qt.core} module. It is entirely equivalent to the following: \code CppApplication { Depends { name: "Qt.core" } } } \endcode */ qbs-src-1.13.1/doc/reference/items/convenience/qtguiapplication.qdoc000066400000000000000000000032171347155106100255220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage QtApplication \nextpage StaticLibrary \qmltype QtGuiApplication \inherits QtApplication \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.QtGuiApplication \brief Application with a dependency on the Qt GUI module. A QtGuiApplication is an application that extends the \l{QtApplication} item by loading the \l{Qt.gui} module. */ qbs-src-1.13.1/doc/reference/items/convenience/staticlibrary.qdoc000066400000000000000000000042001347155106100250120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage QtGuiApplication \nextpage XPCService \qmltype StaticLibrary \inherits Product \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.StaticLibrary \brief Static library. A StaticLibrary item is a \l{Product}{product} of the \l{Product::}{type} \c "staticlibrary". */ /*! \qmlproperty bool StaticLibrary::install If \c{true}, the library will be installed to \l installDir. \defaultvalue \c false \since Qbs 1.13 */ /*! \qmlproperty string StaticLibrary::installDir Where to install the library, if \l install is enabled. The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} when constructing the actual installation directory. \defaultvalue \c Library/Frameworks if the library is a \l{bundle::isBundle}{bundle}, \c lib otherwise. \since Qbs 1.13 */ qbs-src-1.13.1/doc/reference/items/convenience/xpcservice.qdoc000066400000000000000000000032511347155106100243160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-convenience-items.html \previouspage StaticLibrary \qmltype XPCService \inherits Application \inqmlmodule QbsConvenienceItems \ingroup list-of-items \keyword QML.XPCService \brief XPC service for macOS, iOS, tvOS, or watchOS. An XPCService item is a convenience item based on \l Application that sets some properties required for macOS, iOS, tvOS, or watchOS XPC services. */ qbs-src-1.13.1/doc/reference/items/language/000077500000000000000000000000001347155106100205615ustar00rootroot00000000000000qbs-src-1.13.1/doc/reference/items/language/artifact.qdoc000066400000000000000000000054101347155106100232260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \nextpage Depends \ingroup list-of-language-items \qmltype Artifact \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Artifact \brief Describes a file produced by a Rule. An Artifact represents a single file produced by a \l{Rule}. For example, if a rule produces three files, it needs to contain three Artifact items. In addition to Artifact properties, you can set module properties within an Artifact item, as follows: \code Artifact { filePath: "somefile.cpp" fileTags: ["cpp"] cpp.cxxLanguageVersion: "c++11" // ... } \endcode \note The code on the right-hand side of Artifact properties has access to the set of input artifacts. That is, it can refer to the \c inputs map and, if the rule is not a multiplex rule, the \c input variable. */ /*! \qmlproperty bool Artifact::alwaysUpdated Setting this property to \c false means the file is not necessarily always written to by any command run by the rule. If all artifacts of a rule have this property set to \c false, the commands of the rule are only executed if all of them are out of date compared to the inputs. \defaultvalue \c true */ /*! \qmlproperty string Artifact::filePath The file path of the target artifact. \nodefaultvalue */ /*! \qmlproperty stringList Artifact::fileTags A list of tags to attach to the target file. These can then be matched by a \l{Rule}. \defaultvalue An empty list */ qbs-src-1.13.1/doc/reference/items/language/depends.qdoc000066400000000000000000000134601347155106100230570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Artifact \nextpage Export \qmltype Depends \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Depends \brief Represents dependencies between products and modules. A Depends item can appear inside a \l{Product} or \l{Module} item. For example, the following product will load the \l{cpp} module. In addition, it will try to load modules that may or may not exist, and pass this information on to the compiler. \code Product { Depends { name: "cpp" } Depends { name: "optional_module" versionAtLeast: "2.0" required: false } Properties { condition: optional_module.present cpp.defines: "HAS_OPTIONAL_MODULE" } // ... } \endcode \section1 Dependency Parameters Sometimes it is desirable to have certain dependencies handled differently than others. For example, one might want to depend on a dynamic library without linking it. This can be done by setting the \l{dependency-parameters-cpp}{cpp.link} dependency parameter to \c{true} in the dynamic library dependency: \code Product { Depends { name: "cpp" } Depends { name: "some_dynamic_lib"; cpp.link: false } // ... } \endcode Dependency parameters are a special type of property that can only be set within Depends and \l [QML] {Parameters} items. Dependency parameters are declared in the modules they belong to. In the example above, the \l{cpp} module declares the parameter \c{link}. The Depends item for \c{some_dynamic_lib} sets \c{cpp.link} to \c{false}, which tells the linker rule to ignore this particular dependency. */ /*! \qmlproperty bool Depends::condition Determines whether the dependency will actually be applied. \defaultvalue \c true */ /*! \qmlproperty string Depends::versionAtLeast The minimum value that the dependency's \c version property needs to have. If the actual version is lower than that, loading the dependency will fail. The value consists of integers separated by dots. \nodefaultvalue */ /*! \qmlproperty string Depends::versionBelow A value that the dependency's \c version property must be lower than. If the actual version is equal to or higher than that, loading the dependency will fail. The value consists of integers separated by dots. \nodefaultvalue */ /*! \qmlproperty stringList Depends::productTypes A list of product types. Any enabled product in the project that has a matching type will become a dependency of the product containing the Depends item. This property is mutually exclusive with the \l name and \l submodules properties. The \l required and \l profiles properties are ignored if this property is set. Product types attached via Module::additionalProductTypes are not considered. \nodefaultvalue */ /*! \qmlproperty bool Depends::required Setting this property to \c false creates a \e{soft dependency}, meaning that it is not considered an error if the given module cannot be found. In such a case, an instance of the respective module will be created, but only the \l{Module::present}{Module.present} property will be available for querying, and it will be set to \c false. \defaultvalue \c true */ /*! \qmlproperty string Depends::name The name of the dependent product or module. \nodefaultvalue */ /*! \qmlproperty stringList Depends::profiles A list of profiles. If the dependency is on a product and that product is going to be built for more than one profile, you can specify here which instance of the product the dependency is on. See the \l{qbs::profiles}{qbs.profiles} property for more information. An empty list means a dependency on all instances of the product with the given name, regardless of their profile. \nodefaultvalue */ /*! \qmlproperty bool Depends::limitToSubProject If \l productTypes is set and this property is \c true, only products that are in the same sub-project as the product containing the Depends item are considered. \defaultvalue \c false */ /*! \qmlproperty stringList Depends::submodules A list of submodules of the module to depend on, if applicable. \nodefaultvalue */ /*! \qmlproperty bool Depends::enableFallback Whether to fall back to a pkg-config based \l{Module Providers}{module provider} if the dependency is not found. \defaultvalue \c true */ qbs-src-1.13.1/doc/reference/items/language/export.qdoc000066400000000000000000000076221347155106100227610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Depends \nextpage FileTagger \qmltype Export \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Export \brief Exports dependencies and properties to other products. An Export item can appear inside a \l{Product} item. It defines a \l{Module} with the product's name that can be depended on by other products. The properties attached to the Export item will take effect in all products that depend on the product inside which the Export item is defined. As an example, consider these two products: \code Product { name: "A" Export { Depends { name: "cpp" } cpp.includePaths: product.sourceDirectory cpp.defines: ["USING_" + product.name.toUpperCase()] } } Product { name: "B" Depends { name: "A" } } \endcode The sources in product B will be able to use headers from product A without specifiying the full path to them, because the include path has been made known to the compiler via A's Export item. Additionally, product B will be compiled with the define \c{USING_A}. \note This relationship is transitive, so a product C depending on product B will also get the include paths and preprocessor macros via A's Export item. In contrast to Module items, \c{product} within Export items refers to the product which defines the Export item. Use the \c{importingProduct} variable to refer to the product that pulls in the resulting module. */ /*! \qmlproperty var Export::prefixMapping This property allows to provide a translation of exported values between non-deployed and deployed contexts. It is an array of objects with properties \c prefix and \c replacement. The array's elements get applied to all other properties set in this item such that if the property's value start with \c prefix, that prefix gets replaced with \c replacement. It is typically used for C/C++ include paths. For instance, in a library that provides header files for inclusion both directly from its source directory (when building it as part of a bigger project) and from some installed location (when building an unrelated project against it), you would write something like the following: \code Export { Depends { name: cpp" } cpp.includePaths: [product.sourceDirectory] prefixMapping: [{ prefix: product.sourceDirectory, replacement: FileInfo.joinPaths(qbs.installPrefix, "include") }] } \endcode \defaultvalue \c undefined \see Exporter.qbs \see Exporter.pkgconfig \since 1.12 */ qbs-src-1.13.1/doc/reference/items/language/filetagger.qdoc000066400000000000000000000071431347155106100235470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Export \nextpage Group \qmltype FileTagger \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.FileTagger \brief Assigns file tags to files. This item assigns file tags to files. The FileTagger item can appear in \l{Product} items or \l{Module} items. For every source artifact that has no file tag, \QBS will search for a FileTagger with a pattern that matches the file name of the source artifact. If a matching file tagger is found, then the file tags specified in the FileTagger item are assigned to the source artifact. If there is more than one matching FileTagger, all file taggers with the same highest priority are taken into account and their file tags are accumulated. The FileTagger item can be attached to a product or a module. In the latter case, its effect is the same as if it had been attached to all products having a dependency on the respective module. For instance, the \l{cpp} module of \QBS has, among others, the following file tagger: \code FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } \endcode As a result, the \c "cpp" tag is automatically attached to all files ending with \c ".cpp" in products depending on the \c cpp module. This causes them to be compiled, because a C++ compiler rule has \c "cpp" in its list of matching input tags. File taggers are disabled if file tags are set explicitly in a \l{Product} {product} or \l{Group}{group}. For example, the \c "cpp" tag is not attached to the \c .cpp files in the following product: \code Product { Depends { name: "cpp" } Group { files: "*.cpp" fileTags: "other" } } \endcode */ /*! \qmlproperty stringList FileTagger::patterns \since Qbs 1.0 A list of patterns to match against. Supports the usual wildcards '*', '?' and '[]'. Neither the list itself nor any of its elements may be empty. */ /*! \qmlproperty list FileTagger::fileTags \since Qbs 1.0 Tags to attach to a product's files. These can then be matched by a rule. \defaultvalue An empty list */ /*! \qmlproperty int FileTagger::priority \since Qbs 1.10 The priority of the FileTagger. A higher numerical value means a higher priority. \defaultvalue 0 */ qbs-src-1.13.1/doc/reference/items/language/group.qbs000066400000000000000000000034301347155106100224240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Project { Product { //! [0] Group { name: "Word processing documents" files: ["*.doc", "*.rtf"] prefix: "**/" qbs.install: true qbs.installDir: "share" excludeFiles: "do_not_install_this_file.*" } //! [0] } } qbs-src-1.13.1/doc/reference/items/language/group.qdoc000066400000000000000000000152621347155106100225730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage FileTagger \nextpage JobLimit \qmltype Group \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Group \brief Groups files in a product. This item is attached to a \l{Product}{product} and used to group files that have something in common. For example: \code Application { Group { name: "common files" files: ["myclass.h", "myclass_common_impl.cpp"] } Group { name: "Windows files" condition: qbs.targetOS.contains("windows") files: "myclass_win_impl.cpp" } Group { name: "Unix files" condition: qbs.targetOS.contains("unix") files: "unixhelper.cpp" Group { name: "Linux files" condition: qbs.targetOS.contains("linux") files: "myclass_linux_impl.cpp" } Group { name: "FreeBSD files" condition: qbs.targetOS.contains("freebsd") files: "myclass_freebsd_impl.cpp" } } Group { name: "Files to install" qbs.install: true qbs.installDir: "share" files: "runtime_resource.txt" } } \endcode When specifying files, you can use the wildcards "*", "?" and "[]", which have their usual meaning. By default, matching files are only picked up directly from the parent directory, but you can tell \QBS to consider the whole directory tree. It is also possible to exclude certain files from the list. The pattern ** used in a pathname expansion context will match all files and zero or more directories and subdirectories. For example: \snippet reference/items/language/group.qbs 0 A group can also be used to attach properties to build artifacts such as executables or libraries. In the following example, an application is installed to "/bin". \code Application { Group { fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } } \endcode Groups may also appear in \l{Module}{modules}, which causes the respective sources to be added to the products depending on the said module, unless the \l{filesAreTargets} property is set. Groups can be nested. In this case, child groups inherit the module properties and \l{FileTagger}{file tags} as well as the prefix of their parent group. The \l{condition} of a child group gets logically ANDed with the one of its parent group. */ /*! \qmlproperty string Group::name The name of the group. Not used internally; mainly useful for IDEs. \defaultvalue "Group x", where x is a unique number among all the groups in the product. */ /*! \qmlproperty list Group::files The files in the group. Mutually exclusive with \l{fileTagsFilter}. Relative paths are resolved using the parent directory of the file that contains the Group item. However, if the \l{prefix} property is set to an absolute path, then that one becomes the base directory. \defaultvalue An empty list */ /*! \qmlproperty bool Group::filesAreTargets If this property is \c true and the group is in a \l{Module}, the files in the group will not become source artifacts of the product that depends on the module. Instead, they are treated like target artifacts of products. That is, they will be matched against the \l{Rule::inputsFromDependencies}{inputsFromDependencies} file tag list of \l{Rule}{rules} in products that depend on the module. \defaultvalue \c false */ /*! \qmlproperty string Group::prefix A string to prepend to all files. Slashes are allowed and have directory semantics. \defaultvalue The prefix of the parent group if one exists, otherwise empty. */ /*! \qmlproperty list Group::fileTagsFilter List of \l{Artifact::fileTags}{artifact.fileTags} to match. Any properties set in this group will be applied to the product's artifacts whose file tags match the ones listed here. The file tags that the group's \l{fileTags} property specifies will be added to the matching artifacts. This property is mutually exclusive with \l{files}. \defaultvalue An empty list */ /*! \qmlproperty bool Group::condition Determines whether the files in the group are actually considered part of the project. \defaultvalue \c true */ /*! \qmlproperty list Group::fileTags A list of file tags to attach to the group's files. These can then be matched by a \l{Rule}{rule}. \note \l{FileTagger}{File taggers} are never applied to a file that has this property set. \defaultvalue An empty list */ /*! \qmlproperty bool Group::overrideTags Determines how tags on files that are listed both at the top level of a product (or the parent group, if there is one) and a group are handled. If this property is \c true, then the \l{FileTagger}{file tags} set via the group replace the ones set via the product or parent group. If it is \c false, the \e {group tags} are added to the \e {parent tags}. This property is ignored if \l{fileTagsFilter} is set. \defaultvalue \c true */ /*! \qmlproperty list Group::excludeFiles A list of files that are \e subtracted from the files list. Useful when using wildcards. \defaultvalue An empty list */ qbs-src-1.13.1/doc/reference/items/language/joblimit.qdoc000066400000000000000000000074031347155106100232460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Group \nextpage Module \qmltype JobLimit \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.JobLimit \brief Restricts concurrent execution of jobs in a given pool. In addition to the global limit on concurrently running commands, a project might want to restrict concurrent execution of certain types of commands even further, for instance because they are not well-suited to share certain types of resources. In the following example, we define a rule that runs a tool of which at most one instance can be running for the same project at any given time: \code Rule { // ... prepare: { var cmd = new Command("my-exclusive-tool", [project.buildDirectory]); cmd.description = "running the exclusive tool"; cmd.jobPool = "exclusive_tool"; return cmd; } } JobLimit { jobPool: "exclusive_tool" jobCount: 1 } \endcode \c JobLimit items can appear inside \l Product, \l Project and \l Module items. In the case of collisions, that is, items matching the same job pool but setting different values, the ones defined inside products have the highest precedence, and the ones inside modules have the lowest. Items defined in sub-projects have higher precedence than those defined in parent projects. For items with the same precedence level, the most restrictive one is chosen, that is, the one with the lowest job number greater than zero. \see {How do I limit the number of concurrent jobs for the linker only?} */ /*! \qmlproperty bool JobLimit::condition Determines whether the job limit is active. If this property is set to \c false, the job limit is ignored. \defaultvalue \c true */ /*! \qmlproperty string JobLimit::jobCount The maximum number of commands in the given \l{jobPool}{job pool} that can run concurrently. A value of zero means "unlimited", negative values are not allowed. \note The global job limit always applies: For instance, if you set this property to 100 for some job pool, and "-j 8" was given on the command line, then no more than eight instances of commands from the respective job pool will run at any time. This property must always be set. \nodefaultvalue */ /*! \qmlproperty string JobLimit::jobPool The job pool to which apply the limit. This property must always be set to a non-empty value. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/items/language/module.qdoc000066400000000000000000000260571347155106100227300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage JobLimit \nextpage ModuleProvider \qmltype Module \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Module \brief Represents a collection of properties and items that can be loaded into a product. A Module item is a collection of properties and language items. It contributes to building a product if the product has a \l{Depends}{dependency} on the module. Modules may contain the following items: \list \li \l{Depends} \li \l{FileTagger} \li \l{Group} \li \l{JobLimit} \li \l{Parameter} \li \l{Probe} \li \l{PropertyOptions} \li \l{Rule} \li \l{Scanner} \endlist When a product expresses a dependency on a module, \QBS will create an instance of the module item in the scope of the product. The product can then read and write properties from and to the loaded module, respectively. Modules in different products are isolated from each other, just as products cannot access each other's properties. However, products can use the \l{Export} item to pass dependencies and properties of modules to other dependent products. The following (somewhat artificial) module pre-processes text files by removing certain characters from them. The module's name is \c{txt_processor}. \qml import qbs.FileInfo import qbs.TextFile Module { property stringList unwantedCharacters: [] FileTagger { patterns: ["*.raw"] fileTags: ["raw-txt"] } Rule { inputs: ["raw-txt"] Artifact { filePath: FileInfo.relativePath(input.filePath, product.sourceDirectory) + "/" + input.fileName + ".processed" fileTags: ["processed-txt"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Processing " + input.fileName; cmd.sourceCode = function() { var inFile = new TextFile(input.filePath, TextFile.ReadOnly); var content = inFile.readAll(); inFile.close(); var unwantedChars = input.txt_processor.unwantedCharacters; for (var c in unwantedChars) content = content.replace(unwantedChars[c], ""); var outFile = new TextFile(output.filePath, TextFile.WriteOnly); outFile.write(content); outFile.close(); }; return cmd; } } } \endqml And this is how a \l{Product} would use the module: \qml Product { type: "processed-txt" Depends { name: "txt_processor" } txt_processor.unwantedCharacters: ["\r"] files: [ "file1.raw", "file2.raw" ] } \endqml The resulting files are tagged with \c{processed-txt} and might be consumed by a rule in another module. That is possible if another rule has \c{processed-txt} in its \l{Rule::inputs}{inputs} property. For more information about how you make your own modules available to \QBS, see \l{Custom Modules and Items}. \section1 Accessing Product and Module Properties When defining a property in a module item, the right-hand side expression is a binding. Bindings may reference other properties of: \list \li the current module \li other modules that this module depends on \li the dependent product \endlist Please note that this applies to bindings in modules only. Property access in rules and other nested items is different. \section2 Accessing Properties of the Current Module Sibling properties in the same module can be accessed directly by their name: \qml Module { property stringList windowsDefaults: ["\r"] property stringList unwantedCharacters: windowsDefaults } \endqml \section2 Properties of the Dependent Modules When a module loads another module through a \l{Depends} element, it can access properties of the other module through its name. Assuming there was a module \c OtherModule with a property \c otherProperty, such an access would look like this: \qml Module { Depends { name: "OtherModule" } property string myProperty: "something-" + OtherModule.otherProperty } \endqml \section2 Accessing Properties of the Dependent Product \qml Module { property bool featureEnabled: (product.type.contains("application")) ? true : false } \endqml \section1 Special Property Values For every property defined in a module, \QBS provides the following special built-in values: \list \li \l base \li \l original \li \l outer \endlist \section2 \c base This value is useful when making use of inheritance. It stands for the value of the respective property in the item one level up in the inheritance chain. For instance: \code Product { // defined in MyProduct.qbs Depends { name: "mymodule" } mymodule.someProperty: ["value1"] } ------ some other file ------ MyProduct { mymodule.someProperty: base.concat(["value2"]) // => ["value1", "value2"] } \endcode \section2 \c original This is the value of the property in the module itself (possibly overridden from a profile or the command line). Use it to set a module property conditionally: \code Module { // This is mymodule property string aProperty: "z" } ---------- Product { Depends { name: "mymodule" } Depends { name: "myothermodule" } mymodule.aProperty: myothermodule.anotherProperty === "x" ? "y" : original // => "y" if myothermodule.anotherProperty is "x", "z" otherwise \endcode \section2 \c outer This value is used in nested items, where it refers to the value of the respective property in the surrounding item. It is only valid in \l{Group} and \l{Properties} items: \code Product { Depends { name: "mymodule" } mymodule.someProperty: ["value1"] Group { name: "special files" files: ["somefile1", "somefile2"] mymodule.someProperty: outer.concat(["value"]) // => ["value1", "value2"] } } \endcode \section1 Dependency Parameters Modules can declare dependency parameters. Those parameters can be set within \l{Depends} items. \l{Rule}{Rules} of the module can read the parameters of dependencies and act accordingly. In the following example, the module \e{foo} declares the parameter \c{ignore}. A dependency to \c{bar} then sets the parameter \c{foo.ignore} to \c{true}. A rule in \c{foo} ignores all dependencies that have \c{foo.ignore} set to true. \code Module { // Definition of module 'foo'. Parameter { property bool ignore } Rule { ... prepare: { for (i in product.dependencies) { var dep = product.dependencies[i]; if (dep.foo.ignore) continue; // Do something with the dependency. } } } ... } ---------- Product { Depends { name: "foo" } Depends { name: "bar"; foo.ignore: true } } \endcode */ /*! \qmlproperty stringList Module::additionalProductTypes A list of elements that will be added to the \l{Product::type}{type} property of a product that has a dependency on the module. \defaultvalue \c [] */ /*! \qmlproperty bool Module::condition Whether the module is enabled. If this property is \c false, the surrounding Module item will not be considered in the module look-up. \defaultvalue \c true */ /*! \qmlproperty bool Module::present \readonly This property is \c false if and only if the respective \l{Depends} item had its \l{Depends::required}{required} property set to \c false and the module was not found. \defaultvalue \c true */ /*! \qmlproperty int Module::priority The priority of this module instance. If there is more than one module instance available for a module name, the module with the highest priority is chosen. \defaultvalue 0 */ /*! \qmlproperty script Module::setupBuildEnvironment A script for setting up the environment in which a product is built. The code in this script is treated as a function with the signature \c{function(project, product)}. Use the \l{Environment Service}{Environment} functions to alter the environment. The return value of this script is ignored. \nodefaultvalue */ /*! \qmlproperty script Module::setupRunEnvironment A script for setting up the environment in which a product is run. The code in this script is treated as a function with the signature \c{function(project, product, config)}. The \c config parameter is a list of arbitrary strings that can be passed via the \l{run} command. The values supported by specific modules are listed in their respective documentation. Use the \l{Environment Service}{Environment} functions to alter the environment. The return value of this script is ignored. \nodefaultvalue */ /*! \qmlproperty script Module::validate A script that is run after the module is loaded. It can be used to check property values and throw errors in unexpected cases. The return value is ignored. \nodefaultvalue */ /*! \qmlproperty string Module::version The module's version. It consists of integer values separated by dots. You can check for specific values of this property in a \l{Depends} item. */ qbs-src-1.13.1/doc/reference/items/language/moduleprovider.qdoc000066400000000000000000000110751347155106100244750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Module \nextpage Parameter \qmltype ModuleProvider \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.ModuleProvider \brief Creates modules on demand. The \c ModuleProvider item implements the module creation part of the procedure described in the \l {Module Providers} overview. It is always located in a file called \c provider.qbs. The actual module creation is done on the right-hand side of the \l{ModuleProvider::relativeSearchPaths}{relativeSearchPaths} property. Here is a complete minimal example of a module provider. It just creates an empty module. If you put this item into the file \c {module-providers/mymodule/provider.qbs} in your project source directory, you will be able to successfully build a product which contains a dependency on the module \c mymodule. \code import qbs.File import qbs.FileInfo import qbs.TextFile ModuleProvider { relativeSearchPaths: { var moduleDir = FileInfo.joinPaths(outputBaseDir, "modules", name); File.makePath(moduleDir); var moduleFilePath = FileInfo.joinPaths(moduleDir, name + ".qbs"); var moduleFile = new TextFile(moduleFilePath, TextFile.WriteOnly); moduleFile.writeLine("Module {"); moduleFile.writeLine("}"); moduleFile.close(); return ""; } } \endcode */ /*! \qmlproperty string ModuleProvider::name The name of the module provider. This property is set by \QBS. For simple dependency names, it is the name of the dependency as specified in the \l Depends item. If the dependency name consists of multiple components, the value is the name up until (and including) the component that corresponds to the directory the provider was found in. For instance, if the dependency is \c {x.m1} and the provider was found in \c {module-providers/x/m1/provider.qbs}, then \c name is \c {x.m1}. If the provider was found in \c {module-providers/x/provider.qbs}, then \c name is \c x. */ /*! \qmlproperty string ModuleProvider::outputBaseDir The path under which the new modules should be created when \l relativeSearchPaths is evaluated. The path is unique for the current provider in the given configuration. This property is set by \QBS. */ /*! \qmlproperty stringList ModuleProvider::relativeSearchPaths This property gets evaluated by \QBS to retrieve new search paths with which to re-attempt the module look-up. It is here where you need to put the code that creates the new module files. Use the directory structure explained in \l {Custom Modules and Items}. That is, the file for a module called \c m will be located in a directory \c {modules/m/}, anchored at \l outputBaseDir. The return value is the list of search paths required to find the new module, relative to \l outputBaseDir. In most cases, only a single search path will be required, in which case a single-element list containing an empty string should be returned (or just the empty string, because of \QBS' auto-conversion feature). The returned list can also be empty, which means that the module provider was not able to generate any modules in this environment. */ qbs-src-1.13.1/doc/reference/items/language/parameter.qdoc000066400000000000000000000035521347155106100234160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Module \nextpage Parameters \qmltype Parameter \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Parameter \brief Declares a dependency parameter. The Parameter item declares a dependency parameter. It can appear only within \l{Module} and \l{Export} items. The Parameter item contains exactly one property declaration. Example: \code Module { Parameter { property string extra } } \endcode For more information about dependency parameters, see \l{Module#dependency-parameters}{Module - Dependency Parameters}. */ qbs-src-1.13.1/doc/reference/items/language/parameters.qdoc000066400000000000000000000044101347155106100235730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Parameter \nextpage Probe \qmltype Parameters \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Parameters \brief Defines default values for dependency parameters within Export items. The Parameters item defines default values for dependency parameters within \l{Export} items. Example: \code DynamicLibrary { name: "foo" ... Export { ... Parameters { cpp.link: false } } } \endcode Every dependency on \e{foo} has the parameter \l{dependency-parameters-cpp} {cpp.link} set to \c{false} by default. This can be overridden explicitly: \code Depends { name: "foo"; cpp.link: true } \endcode The Parameters item contains a number of property bindings where each property must be a properly declared dependency parameter. For more information, see \l{Parameter} and \l{Module#dependency-parameters}{Module - Dependency Parameters}. */ qbs-src-1.13.1/doc/reference/items/language/probe.qdoc000066400000000000000000000057431347155106100225510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Parameters \nextpage Product \qmltype Probe \inqmlmodule QbsLanguageItems \ingroup list-of-items \ingroup list-of-probes \keyword QML.Probe \brief Locates files outside the project. Probe items can appear inside \l{Product} and \l{Project} items. They are run prior to building, for instance to locate dependent headers, libraries, and other files outside the project directory whose locations are not known ahead of time. Probes can be parameterized via their properties and typically store results in properties as well. These results are then retrieved via the Probe's id, which is mandatory: \code Product { Probe { id: valueCalculator property string parameter: "whatever" property int value configure: { value = Utils.calculateValue(parameter); // Expensive operation found = true; } } property int theValue: valueCalculator.value } \endcode \note Because Probes often invoke external processes, which is relatively expensive compared to evaluating normal properties, their results are cached. To force re-evaluation of a Probe, you can supply the \l{build-force-probe-execution} {--force-probe-execution} command-line option to the \l{build} command. */ /*! \qmlproperty bool Probe::condition Determines whether the probe will actually be run. \defaultvalue \c true */ /*! \qmlproperty bool Probe::found Indicates whether the probe was run successfully. Set by \l{configure}. \nodefaultvalue */ /*! \qmlproperty script Probe::configure A script that is executed when the probe is run. */ qbs-src-1.13.1/doc/reference/items/language/product.qdoc000066400000000000000000000200501347155106100231060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Probe \nextpage Profile \qmltype Product \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Product \brief Represents the result of a build process. A Product typically represents the result of a build process. It specifies a set of input and output files and a way to transform the former into the latter. For example, the following product sets up a very simple C++ application: \code Product { name: "helloworld" type: "application" files: "main.cpp" Depends { name: "cpp" } } \endcode The \l{type} property specifies what will be built (an executable). The \l{files} property specifies the input files (one C++ source file), and the \l{Depends} item pulls in the logic from the \l{cpp} module about how to do the necessary transformations. For some often-used types of products, \QBS pre-defines special derived items that save users some typing. These are: \list \li \l{Application} \li \l{CppApplication} \li \l{DynamicLibrary} \li \l{StaticLibrary} \endlist Therefore, the above example could also be written like this: \code CppApplication { name: "helloworld" files: "main.cpp" } \endcode Any property \c prop attached to this item is available in sub-items as \c product.prop, as well as in modules that are loaded from this product. \section1 Multiplexing Properties The following properties are relevant for product multiplexing only. Unless multiplexing is desired, they can be left at their default values: \list \li \l{aggregate} \li \l{multiplexedType} \li \l{multiplexByQbsProperties} \endlist \note We do not promise backwards compatibility for multiplexing properties as they are likely to change in future \QBS versions. \section1 Read-Only Properties The following properties are automatically set by \QBS and cannot be changed by the user: \list \li \l{buildDirectory} \li \l{sourceDirectory} \endlist */ /*! \qmlproperty bool Product::builtByDefault Determines whether the product will be built. If \c false, the product will only be built if this is explicitly requested, either by listing the product name as an argument to the \l{build-products}{--products} option or by using the \l{build-all-products}{--all-products} option of the \l{build} command. \defaultvalue \c true */ /*! \qmlproperty bool Product::condition Determines whether the product will be built. If \c false, the product will not be built. \defaultvalue \c true */ /*! \qmlproperty string Product::name The name of the product. Used to identify the product in a \l{Depends} item, for example. The value of this property must be a simple JavaScript expression that does not depend on module properties or values that are non-local to this product. \code CppApplication { name: "hello" + "world" // valid } CppApplication { name: "app_" + qbs.targetOS.join("_") // invalid } \endcode To change the name of your product's target artifact, modify \l{targetName} instead. \defaultvalue An empty string */ /*! \qmlproperty stringList Product::type The file tags matching the product's target artifacts. \defaultvalue An empty list */ /*! \qmlproperty string Product::targetName The base file name of the product's target artifacts. \defaultvalue The value of \l{name} with illegal file name characters replaced by underscores. */ /*! \qmlproperty string Product::destinationDirectory The directory where the target artifacts will be located. If a relative path is given, the base directory will be \l{Project::buildDirectory} {project.buildDirectory}. \defaultvalue \c{product.buildDirectory} */ /*! \qmlproperty stringList Product::files A list of source files. Syntactic sugar to save a \l{Group} item for simple products. Relative paths are resolved using the parent directory of the project file that sets the property. \defaultvalue An empty list */ /*! \qmlproperty stringList Product::excludeFiles A list of source files not to include. Useful with wildcards. For more information, see \l{Group}. \defaultvalue An empty list */ /*! \qmlproperty bool Product::consoleApplication On Windows, determines whether a console or GUI application is generated. If \c true, a console application is generated. If \c false, a GUI application is generated. On Apple platforms, influences the default application type. If \c true, a normal executable is generated. If \c false, an application bundle is generated. \defaultvalue Linker-dependent */ /*! \qmlproperty stringList Product::qbsSearchPaths The value set here will be merged with the value of \l{Project::qbsSearchPaths}{project.qbsSearchPaths}. \defaultvalue \l{Project::qbsSearchPaths}{project.qbsSearchPaths} */ /*! \qmlproperty string Product::version The version number of the product. Used in shared library filenames and generated Info.plist files in Apple application and framework bundles, for example. \nodefaultvalue */ /*! \qmlproperty bool Product::aggregate If \c{true}, an aggregate product will be created that has dependencies on all multiplex instances of this product. \note If you do not want to do multiplexing, you can use the default value \c{undefined}. */ /*! \qmlproperty stringList Product::multiplexedType Specifies the product type for the multiplexed product instances. \note If you do not want to do multiplexing, you can use the default value \c{undefined}. */ /*! \qmlproperty stringList Product::multiplexByQbsProperties Specifies which properties of the \l{qbs} module will be used for product multiplexing: \list \li \l{qbs::architectures}{architectures} \li \l{qbs::buildVariants}{buildVariants} \li \l{qbs::profiles}{profiles} \endlist The value must be a subset of the above values. \note If you do not want to do multiplexing, you can use the default value \c{["profiles"]}. */ /*! \qmlproperty path Product::buildDirectory \readonly The build directory for this product. This is the directory where generated files are placed. The value of this property is automatically set by \QBS and cannot be changed by the user. */ /*! \qmlproperty path Product::sourceDirectory \readonly The source directory for this product. This is the directory of the file where this product is defined. The value of this property is automatically set by \QBS and cannot be changed by the user. */ qbs-src-1.13.1/doc/reference/items/language/profile.qdoc000066400000000000000000000062411347155106100230740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Product \nextpage Project \qmltype Profile \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Profile \brief Creates a profile within the project. The profiles used by \QBS are normally set up on a user's machine and are then available to all projects. See \l{Configuring Profiles and Preferences} for information on how to set up and use profiles on the command line. In some rare cases, however, the creator of a project has complete knowledge about the system on which that project is to be built. Then it can make sense to integrate the profile into the project: \code Product { // ... Profile { name: "my-special-profile" qbs.toolchainType: "gcc" qbs.targetPlatform: "linux" qbs.architecture: "armv7a" cpp.toolchainInstallPath: "/opt/special-gcc/bin" cpp.toolchainPrefix: "arm-linux-gnueabi-" } qbs.profiles: ["my-special-profile"] // ... } \endcode The project in the above example can be built in a particular well-known environment without any additional setup. \c Profile items can appear inside \l{Product} and \l{Project} items. */ /*! \qmlproperty string Profile::baseProfile The name of a profile from which this profile inherits. If the same property is set in both this profile and the base profile, the value from this profile takes precedence. \nodefaultvalue */ /*! \qmlproperty bool Profile::condition Determines whether this profile can be used. If this property is set to \c false, the profile cannot be used. \defaultvalue \c true */ /*! \qmlproperty string Profile::name The name under which the profile can be referenced later. Setting this property is required. The value must be unique among all profiles in an entire project. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/items/language/project.qdoc000066400000000000000000000075061347155106100231070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Profile \nextpage Properties \qmltype Project \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Project \brief Represents a collection of products and properties. A Project item represents a collection of of products. In a non-trivial project, these products are typically defined in their own files and referenced in the main project file: \code Project { references: [ "product1/product1.qbs", "product2/product2.qbs" ] } \endcode Any property \c prop attached to this item is available in sub-items as \c project.prop. While the root of the item hierarchy is always a Project, this kind of item can also appear further down the hierarchy. Such sub-projects are usually introduced to group products. See \l{SubProject} for details. \note If your project consists of only one product, the Project item can be omitted. */ /*! \qmlproperty path Project::buildDirectory \readonly The build directory of the top-level project. */ /*! \qmlproperty string Project::name The project name. Only relevant when displaying a project tree in an IDE, for example. \defaultvalue The basename of the file that defines the project. */ /*! \qmlproperty string Project::profile \readonly The top-level \l{Profile}{profile} for building the project. This property is set by \QBS when the project is being set up. */ /*! \qmlproperty bool Project::condition Whether the project is enabled. If \c false, no \l{Product}{products} or sub-projects will be collected. \defaultvalue \c true */ /*! \qmlproperty stringList Project::qbsSearchPaths A list of paths that are searched for imports and modules in addition to the ones listed in \c{preferences.qbsSearchPaths}. The value set here is merged with the value inherited from the parent project, if there is one. The result is inherited by all products in the project. \defaultvalue An empty list */ /*! \qmlproperty pathList Project::references A list of files from which to import products. This is equivalent to defining the respective \l{Product} items directly under this Project item. \defaultvalue An empty list */ /*! \qmlproperty path Project::sourceDirectory \readonly The directory where the file containing the top-level Project item is located. */ /*! \qmlproperty string Project::minimumQbsVersion The minimum version of \QBS that is needed to build this project. \defaultvalue \c "1.3.0" */ qbs-src-1.13.1/doc/reference/items/language/properties.qdoc000066400000000000000000000107141347155106100236300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Project \nextpage PropertyOptions \qmltype Properties \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Properties \brief Provides conditional setting of properties. \note This topic documents the Properties item in the context of \l{Product} {products}. For more information about using it in sub-projects, see \l{SubProject}. The Properties item is an auxiliary item for setting multiple property values conditionally. In the following example, two properties are set if the project is built for Windows: \code Product { Properties { condition: qbs.targetOS.contains("windows") cpp.defines: ["ON_WINDOWS"] cpp.includePaths: ["extraWindowsIncludes"] } } \endcode Multiple Properties items can be specified to set properties dependent on different conditions. The order of appearance is important. Semantics are similar to if-else-chains. The following example \code Product { Properties { condition: qbs.targetOS.contains("windows") cpp.defines: ["ON_WINDOWS"] cpp.includePaths: ["myWindowsIncludes"] } Properties { condition: qbs.targetOS.contains("linux") cpp.defines: ["ON_LINUX"] cpp.includePaths: ["myLinuxIncludes"] } cpp.defines: ["ON_UNKNOWN_PLATFORM"] } \endcode is equivalent to \code Product { cpp.defines: { if (qbs.targetOS.contains("windows")) return ["ON_WINDOWS"]; if (qbs.targetOS.contains("linux")) return ["ON_LINUX"]; return ["ON_UNKNOWN_PLATFORM"]; } cpp.includePaths: { if (qbs.targetOS.contains("windows")) return ["myWindowsIncludes"]; if (qbs.targetOS.contains("linux")) return ["myLinuxIncludes"]; return base; } } \endcode In Properties items, one can access the \l{Module#outer}{outer value} of a property. \code Product { Properties { condition: qbs.targetOS.contains("windows") cpp.defines: outer.concat("ON_WINDOWS") // === ["FOO", "ON_WINDOWS"] } Properties { condition: qbs.targetOS.contains("linux") cpp.defines: ["ON_LINUX"] // === ["ON_LINUX"] } cpp.defines: ["FOO"] } \endcode We suggest to use the Properties item for mutually exclusive conditions only. It is especially useful if there are several properties to set, based on the same condition. */ /*! \qmlproperty bool Properties::condition The condition to be used for the other bindings in this item. This is a mandatory property that has no default value. */ /*! \qmlproperty bool Properties::overrideListProperties List properties set within this item will override the values coming from modules, rather than getting merged with them, which is the default behavior. Use this in the rare case that a module you depend on inserts a value into a list property that is problematic for some product. \defaultvalue \c false */ qbs-src-1.13.1/doc/reference/items/language/propertyoptions.qdoc000066400000000000000000000040741347155106100247360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Properties \nextpage Rule \inqmlmodule QbsLanguageItems \qmltype PropertyOptions \ingroup list-of-items \keyword QML.PropertyOptions \brief Provides inline documentation for properties within product and module items. A PropertyOptions item can appear inside a \l{Product} or \l{Module} item to provide inline documentation for properties. */ /*! \qmlproperty stringList PropertyOptions::allowedValues A list of the values permitted by the property. The default value, \c{undefined}, indicates that any value is permitted. */ /*! \qmlproperty string PropertyOptions::description A brief description of the property. \nodefaultvalue */ /*! \qmlproperty string PropertyOptions::name The name of the property to document. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/items/language/rule.qdoc000066400000000000000000000316101347155106100224010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage PropertyOptions \nextpage Scanner \qmltype Rule \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Rule \brief Creates transformers for input tags. In \QBS, rules create \e transformers that produce output files from input files. The term \e transformer refers to a list of \l{Command and JavaScriptCommand}{commands}. These commands are created in a rule's \l{prepare} script. They do the actual work, either directly or by executing external commands. \section1 A Simple Example The following rule takes text files and replaces Windows-style line endings with their Unix-style counterparts. We will look at it one piece at a time. \code Rule { multiplex: false \endcode A \e {multiplex rule} creates one transformer that takes all input artifacts with the matching input file tag and creates one or more output artifacts. We are setting the respective property to \c false here, indicating that we want to create one transformer per input file. \note This is actually the default, so the above assignment is not required. \code inputs: ["txt_input"] \endcode Here we are specifying that our rule is interested in input files that have the tag \c "txt_input". Such files could be source files, in which case you would tag them using a \l{Group}. Or they could in turn get generated by a different rule, in which case that rule would assign the file tag. The files matching the tag will be available in the \l{prepare} script under the name \c inputs (see \l{inputs and outputs}{The inputs and outputs Variables}). \code Artifact { filePath: input.fileName + ".out" fileTags: ["txt_output"] } \endcode Here we are specifying that for every input file, we want to create one output file whose name is the same as the input file, but with an additional extension. Because we are giving a relative path, \QBS will prepend that path by the product's build directory. In addition, we tell \QBS that the output files should get the file tag \c "txt_output". This enables other rules to use these files as inputs. You must always assign suitable file tags to your output artifacts, or the rule will not be run. See \l{Rules and Product Types} for details. If you want to create more than one output file per input file, you simply provide multiple \l Artifact items. The set of output artifacts will be available in the prepare script under the name \c outputs (see \l{inputs and outputs}{The inputs and outputs Variables}). \code prepare: { var cmd = new JavaScriptCommand(); cmd.description = input.fileName + "->" + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(input.filePath); var content = file.readAll(); file.close() content = content.replace(/\r\n/g, "\n"); file = new TextFile(output.filePath, TextFile.WriteOnly); file.write(content); file.close(); } return [cmd]; } } \endcode The prepare script shown above puts everything together by creating the command that does the actual transformation of the file contents, employing the help of the \l{TextFile Service}{TextFile} class. As you can see, the return value is an array, meaning you can provide several commands to implement the rule's functionality. For instance, if we had provided two \c Artifact items, we might have also provided two commands, each of them creating one output file. For the \c input and \c output variables used in the code, see the next section. \target inputs and outputs \section1 The \c inputs and \c outputs Variables We already mentioned that the input and output artifacts are available in the prepare script via the variables \c inputs and \c outputs, respectively. These variables are JavaScript objects whose property keys are file tags and whose property values are lists of objects representing the artifacts matching these tags. In our example, the \c inputs variable has a single property \c txt_input, whose value is a list with one element. Similarly, the \c outputs variable also has one single property \c txt_output, again with a list containing one element. The actual artifact objects have the following properties: \table \header \li Property \li Description \row \li \c baseName \li The file name without any extension. \row \li \c completeBaseName \li The file name without the last extension. \row \li \c fileName \li The name of the file (that is, \c filePath without any directory components). \row \li \c filePath \li The full file path. \row \li \c fileTags \li The list of the artifact's file tags. \endtable The artifact object contains a property for every module that is used in the product. That can be used to access the module's properties. For instance, for an artifact in a C++ product, \c{artifact.cpp.defines} is the list of defines that will be passed when compiling the respective file. But what about the variables \c input and \c output that appeared in our example? These are simply convenience variables which are available in the case that the \c inputs and \c outputs variables contain only one artifact, respectively. So in our example, instead of \c input we also could have written \c {inputs.txt_input[0]}, which is considerably more verbose. \section1 Rules and Product Types It is important to know that when figuring out which rules to execute, \QBS starts at the product type and then looks for a way to produce artifacts with matching file tags from source files, using a chain of rules that are connected by their respective input and output tags. For instance, consider this simple C++ project: \code Product { type: ["application"] Depends { name: "cpp" } files: ["main.cpp"] } \endcode Here's how this product is built: \list 1 \li \QBS looks for a rule that can produce artifacts with the file tag \c{"application"}. Such a rule is found in the \l{cpp} module (namely, the rule that invokes the linker). \li Since the rule found in the previous step takes inputs of type \c{"obj"}, \QBS now looks for a rule that produces artifacts of that type. Again, such a rule is found in the \c cpp module (the rule that runs the compiler). \li The rule found in the previous step takes inputs of type \c{"cpp"}. No rule is found that creates such artifacts, but we do have a source file with a matching type (because the \c cpp module contains a \l{FileTagger} which attached that type to \c{"main.cpp"} due to its file extension). \li Now that there is a chain of rules leading from a source file tag to the product type, the commands of these rules are executed one after the other until we end up with our executable. \endlist */ /*! \qmlproperty bool Rule::multiplex Determines whether this is a multiplex rule. \defaultvalue \c false */ /*! \qmlproperty stringList Rule::inputs A list of file tags the input artifacts must match. All output artifacts will depend on all artifacts in the product with the given input file tags. Also, these artifacts are available in the \c inputs variable of the \l{prepare} script. \nodefaultvalue */ /*! \qmlproperty stringList Rule::auxiliaryInputs A list of file tags. This rule will be dependent on every other rule that produces artifacts that are compatible with the value of this property. Unlike \l{inputs}, this property has no effect on the content of the \c inputs variable of the \l{prepare} script. All rules in this product and rules of product dependencies that produce target artifacts are considered. \nodefaultvalue */ /*! \qmlproperty stringList Rule::excludedInputs A list of file tags. Connections to rules that produce these file tags are prevented. \nodefaultvalue \since Qbs 1.12 */ /*! \qmlproperty stringList Rule::inputsFromDependencies A list of file tags that the artifacts of product dependencies must match. For example, the product \a foo might appear as follows in the current product: \code Depends { name: "foo" } \endcode All artifacts of \a foo that match the given file tags will appear in the \c inputs variable of the \l{prepare} script. \nodefaultvalue */ /*! \qmlproperty var Rule::outputArtifacts An array of output artifacts, specified as JavaScript objects. For example: \code outputArtifacts: [{ filePath: "myfile.cpp", fileTags: ["cpp"], cpp: { cxxLanguageVersion: "c++11" } }] \endcode For a description of the possible properties, see the documentation of the \l{Artifact} item. Output artifacts can be specified either by this property or by \l{Artifact} items. Use this property if the set of outputs is not fixed but depends the input's content. If no file tags are provided, \QBS will apply all \l{FileTagger}{file taggers} known in the current context to the output file name. The user may set the property \c{explicitlyDependsOn} on artifact objects, which is similar to \l{Rule::explicitlyDependsOn}{Rule.explicitlyDependsOn}. \nodefaultvalue */ /*! \qmlproperty stringList Rule::outputFileTags If output artifacts are specified by \l{outputArtifacts}, this property must specify a list of file tags that the rule potentially produces. \nodefaultvalue */ /*! \qmlproperty bool Rule::condition If \c true, the rule is enabled, otherwise it does nothing. \defaultvalue \c true */ /*! \qmlproperty stringList Rule::explicitlyDependsOn A list of file tags. Each artifact that matches the file tags is added to the dependencies of each output node. All artifacts in the current product are considered. \nodefaultvalue */ /*! \qmlproperty stringList Rule::explicitlyDependsOnFromDependencies A list of file tags. Each artifact that matches the file tags is added to the dependencies of each output node. Only target artifacts of products that this product depends on are considered. \nodefaultvalue \since Qbs 1.12 */ /*! \qmlproperty script Rule::prepare A script that prepares the commands to transform the inputs to outputs. The code in this script is treated as a function with the signature \c{function(project, product, inputs, outputs, input, output, explicitlyDependsOn)}. The argument \c{input} is \c{undefined} if there's more than one input artifact for this rule. Similarly, \c{output} is only defined if there is exactly one output artifact. \nodefaultvalue */ /*! \qmlproperty bool Rule::requiresInputs Specifies whether a rule's commands should be created even if no inputs are available. Enabling this property can be useful if you are not sure whether input files exist, and you want \QBS to create an output file even if they do not. Set to \c true if the rule declares any inputs, \c false otherwise. */ /*! \qmlproperty bool Rule::alwaysRun If \c true, the rule's commands are always executed, even if all output artifacts are up to date. \defaultvalue \c false */ qbs-src-1.13.1/doc/reference/items/language/scanner.qdoc000066400000000000000000000062151347155106100230660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Rule \nextpage SubProject \qmltype Scanner \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.Scanner \brief Creates custom dependency scanners in modules. A Scanner item can appear inside a \l{Module} item, and allows to extract dependencies for artifacts from the artifacts' file contents. For example, this is what a scanner for "qrc" files might look like: \code import qbs.Xml Module { Scanner { inputs: 'qrc' scan: { var xml = new Xml.DomDocument(input.filePath); dependencies = []; // retrieve entries from the XML document return dependencies; } } } \endcode */ /*! \qmlproperty bool Scanner::condition If \c true, the scanner is enabled, otherwise it does nothing. \defaultvalue \c true */ /*! \qmlproperty stringList Scanner::inputs A list of \l{FileTagger}{file tags} the input artifacts must match. \nodefaultvalue */ /*! \qmlproperty bool Scanner::recursive Determines whether to scan the returned dependencies using the same scanner. \defaultvalue \c false */ /*! \qmlproperty script Scanner::searchPaths A script that returns the paths where to look for dependencies. The code in this script is treated as a function with the signature \c{function(project, product, input)}. \nodefaultvalue */ /*! \qmlproperty script Scanner::scan A script that reads the input artifact and returns a string list with dependencies. The code in this script is treated as a function with the signature \c{function(project, product, input, filePath)}, where \c input is the artifact at which the scan originated, and \c filePath is the currently scanned file. For non-recursive scans, \c filePath is always equal to \c{input.filePath}. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/items/language/subproject.qdoc000066400000000000000000000065661347155106100236260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-language-items.html \previouspage Scanner \qmltype SubProject \inqmlmodule QbsLanguageItems \ingroup list-of-items \keyword QML.SubProject \brief Adds a project from a different file. A SubProject item is used to add a sub-project that is defined in a separate file. Additionally, properties of the sub-project can be set without modifying the separate project file. The following example adds a sub-project defined in \c{subdir/project.qbs} and overrides its name. \code Project { SubProject { filePath: "subdir/project.qbs" Properties { name: "A sub-project" } } ... } \endcode A typical use case for SubProject items is to conditionally include sub-projects. The following example pulls in the \e{tests} sub-project if and only if the \c{withTests} property is \c{true}. \code Project { property bool withTests: false SubProject { filePath: "tests/tests.qbs" Properties { condition: parent.withTests } } ... } \endcode If you do not need to set any properties on the sub-project, you can also use the \l{Project::references}{Project.references} property, the same way you would for a product. \code Project { references: "subdir/project.qbs" } \endcode is equivalent with \code Project { SubProject { filePath: "subdir/project.qbs" } } \endcode It is also possible to nest \l{Project} items directly in the same file. */ /*! \qmlproperty path SubProject::filePath The file path of the project to add as a sub-project. If the top-level item in this file is a \l{Product}, it gets wrapped automatically in a new project. \defaultvalue empty */ /*! \qmlproperty bool SubProject::inheritProperties Determines whether the sub-project should inherit the properties of the surrounding \l{Project}. You can use this feature to share global settings between projects and sub-projects. \defaultvalue \c true */ qbs-src-1.13.1/doc/reference/items/probe/000077500000000000000000000000001347155106100201055ustar00rootroot00000000000000qbs-src-1.13.1/doc/reference/items/probe/binary-probe.qdoc000066400000000000000000000057641347155106100233620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-probes.html \qmltype BinaryProbe \ingroup list-of-probes \ingroup list-of-items \keyword QML.BinaryProbe \inherits PathProbe \brief Locates executable files outside the project. Finds executable files that have the specified file names. BinaryProbe searches for executable files within directories specified by the PATH environment variable. \note On Unix, also searches in the \c /usr/bin and \c /usr/local/bin directories by default. Override \l {PathProbe::platformSearchPaths}{PathProbe.platformSearchPaths} to change this behavior. \note On Windows, only files that have \e .com, \e .exe, \e .bat, \e .cmd extensions are considered \e executables. Override \l {PathProbe::nameSuffixes}{PathProbe.nameSuffixes} to change this behavior. For example, BinaryProbe can be used to search for a protobuf compiler executable as follows: \code import qbs.File import qbs.Probes Module { // search for a protoc executable Probes.BinaryProbe { id: protocProbe names: "protoc" } property string executableFilePath: protocProbe.filePath validate: { if (!File.exists(executableFilePath)) throw "The executable '" + executableFilePath + "' does not exist."; } // use the found executable Rule { // rule input/outputs here... // run executable prepare: { var args = // initialize arguments... var cmd = new Command(executableFilePath, args); cmd.highlight = "codegen"; cmd.description = "generating protobuf files for " + input.fileName; return [cmd]; } } } \endcode */ qbs-src-1.13.1/doc/reference/items/probe/framework-probe.qdoc000066400000000000000000000043531347155106100240640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-probes.html \qmltype FrameworkProbe \ingroup list-of-probes \ingroup list-of-items \keyword QML.FrameworkProbe \inherits PathProbe \brief Locates \macos frameworks outside the project. Finds \macos frameworks that have the specified file names. By default, FrameworkProbe searches for frameworks in \c ~/Library/Frameworks, \c /usr/local/lib, \c /Library/Frameworks, and in \c /System/Library/Frameworks. Also, if \l {qbs::sysroot}{qbs.sysroot} is specified (for example, when compiling using XCode SDK), the probe searches in the \c sysroot/System/Library/Frameworks folder first. For example, a simple FrameworkProbe that searches for the Foundation framework can be used as follows: \code import qbs.Probes Product { Depends { name: "cpp"; } Probes.FrameworkProbe { id: foundationProbe names: ["Foundation"] } cpp.frameworkPaths: foundationProbe.found ? [foundationProbe.path] : [] } \endcode */ qbs-src-1.13.1/doc/reference/items/probe/iar-probe.qdoc000066400000000000000000000050271347155106100226410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-probes.html \qmltype IarProbe \ingroup list-of-probes \ingroup list-of-items \keyword QML.IarProbe \inherits PathProbe \brief Collects IAR toolchain compiler information. \since Qbs 1.13 \internal Detects the version, supported architecture and the platform endianness of the specified compiler executable file from the \l{https://www.iar.com/}{IAR} toolchain. */ /*! \qmlproperty string IarProbe::compilerFilePath An input property which is a full path to the IAR compiler executable file. \nodefaultvalue */ /*! \qmlproperty string IarProbe::architecture Detected architecture of the target platform's processor. The possible values are \c "arm", \c "mcs51" and \c "avr". \nodefaultvalue */ /*! \qmlproperty string IarProbe::endianness Detected endianness of the target platform's processor architecture. The possible values are \c "big" or \c "little". \nodefaultvalue */ /*! \qmlproperty int IarProbe::versionMajor Detected major compiler version. \nodefaultvalue */ /*! \qmlproperty int IarProbe::versionMinor Detected minor compiler version. \nodefaultvalue */ /*! \qmlproperty int IarProbe::versionPatch Detected patch compiler version. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/items/probe/include-probe.qdoc000066400000000000000000000035501347155106100235100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-probes.html \qmltype IncludeProbe \ingroup list-of-probes \ingroup list-of-items \keyword QML.IncludeProbe \inherits PathProbe \brief Locates header files outside the project. This is the convenience item that searches for files in "include" directories. For example, IncludeProbe can be used to search for a zlib header as follows: \code import qbs import qbs.Probes CppApplication { Probes.IncludeProbe { id: zlibProbe names: "zlib.h" } cpp.includePaths: zlibProbe.found ? [zlibProbe.path] : [] files: 'main.cpp' } \endcode */ qbs-src-1.13.1/doc/reference/items/probe/keil-probe.qdoc000066400000000000000000000050311347155106100230050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-probes.html \qmltype KeilProbe \ingroup list-of-probes \ingroup list-of-items \keyword QML.KeilProbe \inherits PathProbe \brief Collects KEIL toolchain compiler information. \since Qbs 1.13 \internal Detects the version, supported architecture and the platform endianness of the specified compiler executable file from the \l{https://www.keil.com/}{KEIL} toolchain. */ /*! \qmlproperty string KeilProbe::compilerFilePath An input property which is a full path to the KEIL compiler executable file. \nodefaultvalue */ /*! \qmlproperty string KeilProbe::architecture Detected architecture of the target platform's processor. The possible values are \c "arm" and \c "mcs51". \nodefaultvalue */ /*! \qmlproperty string KeilProbe::endianness Detected endianness of the target platform's processor architecture. The possible values are \c "big" or \c "little". \nodefaultvalue */ /*! \qmlproperty int KeilProbe::versionMajor Detected major compiler version. \nodefaultvalue */ /*! \qmlproperty int KeilProbe::versionMinor Detected minor compiler version. \nodefaultvalue */ /*! \qmlproperty int KeilProbe::versionPatch Detected patch compiler version. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/items/probe/path-probe.qdoc000066400000000000000000000113341347155106100230200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-probes.html \qmltype PathProbe \ingroup list-of-probes \ingroup list-of-items \keyword QML.PathProbe \brief Locates files outside the project. Finds files that have the specified file name suffix, such as \e .exe, from the specified locations. PathProbe takes as input lists of paths to search files from and file name patterns. The paths are specified by using the searchPaths, platformSearchPaths, environmentPaths, and platformEnvironmentPaths properties. The file name patterns are specified by the \l names and nameSuffixes properties. Returns the first file that matches the file name patterns. If no such file is found, the \l {Probe::found}{probe.found} property is set to \c false. For example, a simple PathProbe that searches for the stdio.h header can be used as follows: \code Product { Depends { name: "cpp" } PathProbe { id: probe pathSuffixes: ["include"] names: ["stdio.h"] } cpp.includePaths: probe.found ? [probe.path] : [] } \endcode */ /*! \qmlproperty stringList PathProbe::names The list of file names to search for. \nodefaultvalue */ /*! \qmlproperty stringList PathProbe::nameSuffixes The list of file suffixes to search for. These suffixes are appended to every file name passed via the \l names property. If \l names is empty, the probe looks for any file that ends with the given suffix. \nodefaultvalue */ /*! \qmlproperty script PathProbe::nameFilter A script that is executed for each file name before prepending file suffixes. Can be used to transform file names. */ /*! \qmlproperty pathList PathProbe::searchPaths The list of paths where to search files. \nodefaultvalue */ /*! \qmlproperty pathList PathProbe::platformSearchPaths The list of platform paths where to search files. \defaultvalue \c {['/usr', '/usr/local']} on Unix hosts, empty otherwise */ /*! \qmlproperty stringList PathProbe::pathSuffixes A list of relative paths that are appended to each path where PathProbe searches for files. That is, the file should be located within one of the subfolders passed using this property. \nodefaultvalue */ /*! \qmlproperty stringList PathProbe::environmentPaths The list of environment variables that contains paths where to search files. Paths in the environment variable should be separated using \l{qbs::pathListSeparator}{qbs.pathListSeparator}. \nodefaultvalue */ /*! \qmlproperty stringList PathProbe::platformEnvironmentPaths The list of platform environment variables that contains paths where to search files. Paths in the environment variable should be separated using \l{qbs::pathListSeparator}{qbs.pathListSeparator}. \nodefaultvalue */ /*! \qmlproperty stringList PathProbe::candidatePaths This property contains the result list of all paths that were checked before a file was found (including the file names). \nodefaultvalue */ /*! \qmlproperty string PathProbe::path This property contains the full path where the found file is located (that is, the file directory). \nodefaultvalue */ /*! \qmlproperty string PathProbe::filePath This property contains the full path to the found file, including the file name. \nodefaultvalue */ /*! \qmlproperty string PathProbe::fileName This property contains the found file's name (excluding the path). \nodefaultvalue */ qbs-src-1.13.1/doc/reference/items/probe/pkgconfig-probe.qdoc000066400000000000000000000141021347155106100240270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Ivan Komissarov ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-probes.html \qmltype PkgConfigProbe \ingroup list-of-probes \ingroup list-of-items \keyword QML.PkgConfigProbe \brief Retrieves the information about installed packages using the pkg-config binary. This probe takes the package name or the list of package names as input and returns the information that is required to compile and link using those packages. Usually, you can simply use a Depends item as described in \l{How do I build against libraries that provide pkg-config files?}. Alternatively, the probe can be used directly as follows: \code CppApplication { name: project.name Probes.PkgConfigProbe { id: pkgConfig name: "QtCore" minVersion: '4.0.0' maxVersion: '5.99.99' } files: 'main.cpp' cpp.cxxFlags: pkgConfig.cflags cpp.linkerFlags: pkgConfig.libs } \endcode */ /*! \qmlproperty string PkgConfigProbe::executable The name of or the path to the pkg-config executable. \defaultvalue "pkg-config" */ /*! \qmlproperty string PkgConfigProbe::name The name this probe. This property is used as \l{PkgConfigProbe::packageNames}{PkgConfigProbe.packageNames} value by default. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::packageNames The list of package names to pass to the pkg-config executable. For each package, pkg-config will return the information required to compile and link to this package. \defaultvalue [\l{PkgConfigProbe::name}{PkgConfigProbe.name}] */ /*! \qmlproperty string PkgConfigProbe::minVersion The minimum version of the required package. If set, pkg-config will ignore packages with version less than the value of this property. \nodefaultvalue */ /*! \qmlproperty string PkgConfigProbe::exactVersion The exact version of the required package. If set, pkg-config will ignore packages with version greater than the value of this property. \nodefaultvalue */ /*! \qmlproperty string PkgConfigProbe::maxVersion The maximum version of the required package. If set, pkg-config will ignore packages with version that is not equal to the value of this property. \nodefaultvalue */ /*! \qmlproperty bool PkgConfigProbe::forStaticBuild If \c true, pkg-config will return linker flags for a static linking instead of dynamic. \defaultvalue \c false */ /*! \qmlproperty stringList PkgConfigProbe::libDirs List of full, non-sysrooted paths where pkg-config should search for .pc files. This overrides the built-in path (which is usually /usr/lib/pkgconfig). \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::cflags \internal This property contains the unparsed output from "pkg-config --cflags" call. Usually, you should use \l{PkgConfigProbe::defines}{PkgConfigProbe.defines}, \l{PkgConfigProbe::includePaths}{PkgConfigProbe.includePaths} and \l{PkgConfigProbe::compilerFlags}{PkgConfigProbe.compilerFlags} properties instead. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::libs \internal This property contains the unparsed output from "pkg-config --libs" call. Usually, you should use \l{PkgConfigProbe::libraries}{PkgConfigProbe.libraries}, \l{PkgConfigProbe::libraryPaths}{PkgConfigProbe.libraryPaths} and \l{PkgConfigProbe::linkerFlags}{PkgConfigProbe.linkerFlags} properties instead. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::defines This output property contains the list of defines that should be passed to a compiler when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::libraries This output property contains the list of library names that should be passed to a linker when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::libraryPaths This output property contains the list of library paths that should be passed to a linker when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::includePaths This output property contains the list of include paths that should be passed to a compiler when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::compilerFlags This output property contains the list of flags that should be passed to a compiler when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::linkerFlags This output property contains the list of flags that should be passed to a linker when using requested package. \nodefaultvalue */ /*! \qmlproperty stringList PkgConfigProbe::modversion This output property contains the version of the found package. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/jsextensions/000077500000000000000000000000001347155106100204115ustar00rootroot00000000000000qbs-src-1.13.1/doc/reference/jsextensions/jsextension-binaryfile.qdoc000066400000000000000000000071631347155106100257630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 Sergey Belyashov ** Copyright (C) 2017 Denis Shienkov ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-binaryfile.html \ingroup list-of-builtin-services \title BinaryFile Service \brief Provides read and write operations on binary files. The \c BinaryFile service allows you to read from and write into binary files. \section1 Related Declarations \section2 BinaryFile.OpenMode \code enum BinaryFile.OpenMode { ReadOnly, WriteOnly, ReadWrite } \endcode List of modes that a file may be opened in. The OpenMode values can be combined with the bitwise or operator. \section1 Available operations \section2 Constructor \code BinaryFile(filePath: string, openMode: OpenMode = BinaryFile.ReadOnly) \endcode Opens the file at \c filePath in the given mode and returns the object representing the file. \note The mode influences which of the operations listed below can actually be used on the file. \section2 atEof \code atEof(): boolean \endcode Returns \c{true} if no more data can be read from the file, \c{false} otherwise. \section2 close \code close(): void \endcode Closes the file. It is recommended to always call this function as soon as you are finished with the file, in order to keep the number of in-flight file descriptors as low as possible. \section2 filePath \code filePath(): string \endcode The absolute path of the file represented by this object. \section2 size \code size(): number \endcode Returns the size of the file (in bytes). \section2 resize \code resize(size: number): void \endcode Sets the file \c size (in bytes). If \c size is larger than the file currently is, the new bytes will be set to 0; if \c size is smaller, the file is truncated. \section2 pos \code pos(): number \endcode Returns the position that data is written to or read from. \section2 seek \code seek(pos: number): void \endcode Sets the current position to \c pos. \section2 read \code read(size: number): number[] \endcode Reads at most \c size bytes of data from the file and returns it as an array. \section2 write \code write(data: number[]): void \endcode Writes \c data into the file at the current position. */ qbs-src-1.13.1/doc/reference/jsextensions/jsextension-environment.qdoc000066400000000000000000000051651347155106100262030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-environment.html \ingroup list-of-builtin-services \title Environment Service \brief Provides operations on the system environment. The \c Environment service offers access to the system environment or process environment. \section1 Available Operations \section2 currentEnv \code Environment.currentEnv(): { [key: string]: string; } \endcode Returns the environment of \QBS in the current context as an object whose properties are the environment variables. \section2 getEnv \code Environment.getEnv(key: string): string \endcode Tries to find a variable with the given name in the current context's environment and returns its value. If no such variable could be found, \c undefined is returned. \section2 putEnv \code Environment.putEnv(key: string, value: string): void \endcode Sets the value of the environment variable with the given name in the build or run environment. This method is only available in the \c Module.setupBuildEnvironment and \c Module.setupRunEnvironment scripts. \section2 unsetEnv \code Environment.unsetEnv(key: string): void \endcode Unsets the environment variable with the given name from the build or run environment. This method is only available in the \c Module.setupBuildEnvironment and \c Module.setupRunEnvironment scripts. */ qbs-src-1.13.1/doc/reference/jsextensions/jsextension-file.qdoc000066400000000000000000000072611347155106100245550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-file.html \ingroup list-of-builtin-services \title File Service \brief Provides operations on the file system. The \c File service offers limited access to the file system for operations such as copying or removing files. \section1 Available Operations \section2 copy \code File.copy(sourceFilePath: string, targetFilePath: string): boolean \endcode Copies \c sourceFilePath to \c targetFilePath. Any directory components in \c targetFilePath that do not yet exist will be created. If \c sourceFilePath is a directory, a recursive copy will be made. If an error occurs, a JavaScript exception will be thrown. \note \c targetFilePath must be the counterpart of \c sourceFilePath at the new location, \b{not} the new parent directory. This allows the copy to have a different name and is true even if \c sourceFilePath is a directory. \section2 exists \code File.exists(filePath: string): boolean \endcode Returns true if and only if there is a file at \c filePath. \section2 directoryEntries \code File.directoryEntries(path: string, filter: File.Filter): string[] \endcode Returns a sorted list of the directory \c{path}'s contents non-recursively, filtered by \c filter. The values of \c filter are equivalent to Qt's \c QDir::Filter. \section2 lastModified \code File.lastModified(filePath: string): number \endcode Returns the time of last modification for the file at \c filePath. The concrete semantics of the returned value are platform-specific. You should only rely on the property that a smaller value indicates an older timestamp. \section2 makePath \code File.makePath(path: string): boolean \endcode Makes the directory at \c path, creating intermediate directories if necessary. Conceptually equivalent to \c{mkdir -p} \section2 move \code File.move(oldPath: string, newPath: string, overwrite: boolean = true): boolean \endcode Renames the file \c oldPath to \c newPath. Returns \c true if successful; otherwise returns \c false. If a file with the name \c newPath already exists, and \c overwrite is \c false, \c move() returns \c false (that is, the file will not be overwritten). \section2 remove \code File.remove(filePath: string): boolean \endcode Removes the file at \c filePath. In case of a directory, it will be removed recursively. */ qbs-src-1.13.1/doc/reference/jsextensions/jsextension-fileinfo.qdoc000066400000000000000000000133201347155106100254220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-fileinfo.html \ingroup list-of-builtin-services \title FileInfo Service \brief Provides operations on file paths. The \c FileInfo service offers various operations on file paths, such as turning absolute paths into relative ones, splitting a path into its components, and so on. \section1 Available Operations \section2 baseName \code FileInfo.baseName(filePath: string): string \endcode Returns the file name of \c filePath up to (but not including) the first '.' character. \section2 canonicalPath \code FileInfo.canonicalPath(filePath: string): string \endcode Returns a canonicalized \c filePath, i.e. an absolute path without symbolic links or redundant "." or ".." elements. On Windows, drive substitutions are also resolved. It is recommended to use \c{canonicalPath} in only those cases where canonical paths are really necessary. In most cases, \c{cleanPath} should be enough. \section2 cleanPath \code FileInfo.cleanPath(filePath: string): string \endcode Returns \c filePath without redundant separators and with resolved occurrences of \c{.} and \c{..} components. For instance, \c{/usr/local//../bin/} becomes \c{/usr/bin}. \section2 completeBaseName \code FileInfo.completeBaseName(filePath: string): string \endcode Returns the file name of \c filePath up to (but not including) the last '.' character. \section2 completeSuffix \code FileInfo.completeSuffix(filePath: string): string \endcode Returns the file suffix of \c filePath from (but not including) the last '.' character. \funsince 1.12 \section2 fileName \code FileInfo.fileName(filePath: string): string \endcode Returns the last component of \c filePath, that is, everything after the last '/' character. \section2 fromNativeSeparators \code FileInfo.fromNativeSeparators(filePath: string): string \endcode On Windows hosts, this function behaves the same as \l fromWindowsSeparators. On other operating systems, it returns the input unmodified. \section2 fromWindowsSeparators \code FileInfo.fromWindowsSeparators(filePath: string): string \endcode Returns \c filePath with all '\\' characters replaced by '/'. \section2 isAbsolutePath \code FileInfo.isAbsolutePath(filePath: string, hostOS?: string[]): boolean \endcode Returns true if \c filePath is an absolute path and false if it is a relative one. If \c hostOS is specified, treats \c filePath as a file path of the kind found on that platform. This parameter defaults to the host OS on which \QBS is running and should normally be omitted. \section2 joinPaths \code FileInfo.joinPaths(...paths: string[]): string \endcode Concatenates the given paths using the '/' character. \section2 path \code FileInfo.path(filePath: string, hostOS?: string[]): string \endcode Returns the part of \c filePath that is not the file name, that is, everything up to (but not including) the last '/' character. If \c filePath is just a file name, then '.' is returned. If \c filePath ends with a '/' character, then the file name is assumed to be empty for the purpose of the above definition. If \c hostOS is specified, treats \c filePath as a file path of the kind found on that platform. This parameter defaults to the host OS on which \QBS is running and should normally be omitted. \section2 relativePath \code FileInfo.relativePath(dirPath: string, filePath: string): string \endcode Returns a relative path so that joining \c dirPath and the returned path results in \c filePath. If necessary, '..' components are inserted. The function assumes \c dirPath and \c filePath to be absolute paths and \c dirPath to be a directory. \section2 suffix \code FileInfo.suffix(filePath: string): string \endcode Returns the file suffix of \c filePath from (but not including) the first '.' character. \funsince 1.12 \section2 toNativeSeparators \code FileInfo.toNativeSeparators(filePath: string): string \endcode On Windows hosts, this function behaves the same as \l toWindowsSeparators. On other operating systems, it returns the input unmodified. \section2 toWindowsSeparators \code FileInfo.toWindowsSeparators(filePath: string): string \endcode Returns \c filePath with all '/' characters replaced by '\\'. */ qbs-src-1.13.1/doc/reference/jsextensions/jsextension-process.qdoc000066400000000000000000000140251347155106100253100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-process.html \ingroup list-of-builtin-services \title Process Service \brief Allows you to start external processes. The \c Process service allows you to start processes, track their output, and so on. \section1 Available Operations \section2 Constructor \code Process() \endcode Allocates and returns a new Process object. \section2 close \code close(): void \endcode Frees the resources associated with the process. It is recommended to always call this function as soon as you are finished with the process. \section2 closeWriteChannel \code closeWriteChannel(): void \endcode Schedules the stdin channel of process to be closed. The channel will close once all data has been written to the process. After calling this function, any attempts to write to the process will do nothing. See \c QProcess::closeWriteChannel() for more details. \section2 exec \code exec(filePath: string, arguments: string[], throwOnError: boolean): number \endcode Executes the program at \c filePath with the given argument list and blocks until the process is finished. If an error occurs (for example, there is no executable file at \c filePath) and \c throwOnError is true, then a JavaScript exception will be thrown. Otherwise (the default), -1 will be returned in case of an error. The normal return code is the exit code of the process. \section2 exitCode \code exitCode(): number \endcode Returns the exit code of the process. This is needed for retrieving the exit code from processes started via \c start(), rather than \c exec(). \section2 getEnv \code getEnv(varName: string): string \endcode Returns the value of the variable \c varName in the process' environment. \section2 kill \code kill(): void \endcode Kills the process, causing it to exit immediately. \section2 readLine \code readLine(): string \endcode Reads and returns one line of text from the process output, without the newline character(s). \section2 atEnd \code atEnd(): boolean \endcode Returns true if there is no more data to be read from the process output, otherwise returns false. \section2 readStdErr \code readStdErr(): string \endcode Reads and returns all data from the process' standard error channel. \section2 readStdOut \code readStdOut(): string \endcode Reads and returns all data from the process' standard output channel. \section2 setCodec \code setCodec(codec) \endcode Sets the text codec to \c codec. The codec is used for reading and writing from and to the process, respectively. The supported codecs are the same as for \c QTextCodec, for example: "UTF-8", "UTF-16", and "ISO 8859-1". \section2 setEnv \code setEnv(varName: string, varValue: string): string \endcode Sets the value of variable \c varName to \c varValue in the process environment. This only has an effect if called before the process is started. \section2 setWorkingDirectory \code setWorkingDirectory(path: string): void \endcode Sets the directory the process will be started in. This only has an effect if called before the process is started. \section2 start \code start(filePath: string, arguments: string[]): boolean \endcode Starts the program at \c filePath with the given list of arguments. Returns \c{true} if the process could be started and \c{false} otherwise. \note This call returns right after starting the process and should be used only if you need to interact with the process while it is running. Most of the time, you want to use \c exec() instead. \section2 terminate \code terminate(): void \endcode Tries to terminate the process. This is not guaranteed to make the process exit immediately; if you need that, use \c kill(). \section2 waitForFinished \code waitForFinished(timeout: number): boolean \endcode Blocks until the process has finished or \c timeout milliseconds have passed (default is 30000). Returns true if the process has finished and false if the operation has timed out. Calling this function only makes sense for processes started via \c start() (as opposed to \c exec()). \section2 workingDirectory \code workingDirectory(): string \endcode Returns the directory the process will be started in. \section2 write \code write(data: string): void \endcode Writes \c data into the process' input channel. \section2 writeLine \code writeLine(data: string): void \endcode Writes \c data, followed by the newline character(s), into the process' input channel. */ qbs-src-1.13.1/doc/reference/jsextensions/jsextension-propertylist.qdoc000066400000000000000000000114301347155106100264070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-propertylist.html \ingroup list-of-builtin-services \title PropertyList Service \brief Provides read, write and convert operations on property list files. The \c PropertyList service allows you to read and write property list files in all formats supported by the Core Foundation API: XML, binary, JSON, and OpenStep (read-only). This service is only available on Darwin platforms such as iOS, macOS, tvOS, and watchOS. \section1 Available operations \section2 Constructor \code PropertyList() \endcode Allocates and returns a new PropertyList object. \section2 clear \code clear(): void \endcode Voids the property list by deleting its internal object reference. \section2 isEmpty \code isEmpty(): boolean \endcode Returns true if the property list has no internal object reference set, otherwise false. \section2 format \code format(): string \endcode Returns the data format that the property list data was deserialized from. This property is set after calling \c readFromString or \c readFromFile. Possible return values include: \c "binary1", \c "json", \c "openstep", and \c "xml1". If the property list object is empty or the input format could not be determined, returns \c undefined. \section2 readFromFile \code readFromFile(filePath: string): void \endcode Parses the file and stores the result in the property list. Throws an exception if an I/O error occurs or the input is in an invalid format. \section2 readFromObject \code readFromObject(obj: any): void \endcode Sets the given object as the property list's internal object. \c format() will return \c undefined as this method does not deserialize a storage format. \section2 readFromString \code readFromString(input: string): void \endcode Parses \c input and stores the result in the property list. This is most useful for initializing a property list object from the result of a \c JSON.stringify call. Throws an exception if the input is in an invalid format. \section2 toObject \code toObject(): any \endcode Returns an object representing the property list. \section2 toJSON \code toJSON(style: string = "compact"): string \endcode Returns a string representation of the property list in JSON format. Possible values for \c style include \c "pretty" and \c "compact". The default is compact. \section2 toString \code toString(format: string): string \endcode Returns a string representation of the property list in the specified format. Possible values for \c format include: \c "json" (compact), \c "json-compact", \c "json-pretty", and \c "xml1". Currently, the OpenStep format is not supported. Throws an exception if the object cannot be written in the given format. \section2 toXMLString \code toXMLString(): string \endcode Returns a string representation of the property list in XML format. This function is a synonym for \c toString("xml1"). \section2 writeToFile \code writeToFile(filePath: string, format: string): void \endcode Writes the property list to the file in the given format. Possible values for \c format include: \c "binary1", \c "json" (compact), \c "json-compact", \c "json-pretty", and \c "xml1". Currently, the OpenStep format is not supported for writing. Throws an exception if an I/O error occurs or the object cannot be written in the given format. */ qbs-src-1.13.1/doc/reference/jsextensions/jsextension-temporarydir.qdoc000066400000000000000000000044741347155106100263620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-temporarydir.html \ingroup list-of-builtin-services \title TemporaryDir Service \brief Creates a unique directory for temporary use. The \c TemporaryDir service creates a unique directory for temporary use. \section1 Available Operations \section2 Constructor \code TemporaryDir() \endcode Allocates and returns a new TemporaryDir object. This method creates the temporary directory. \section2 isValid \code isValid(): boolean \endcode Returns \c true if the temporary directory was created successfully. \section2 path \code path(): string \endcode Returns the path to the temporary directory. Empty if the temporary directory could not be created. \section2 remove \code remove(): boolean \endcode Removes the temporary directory, including all its contents. Returns \c true if removing was successful. It is recommended to always call this function as soon as you are finished with the temporary directory. The directory will not be removed automatically. */ qbs-src-1.13.1/doc/reference/jsextensions/jsextension-textfile.qdoc000066400000000000000000000071321347155106100254570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-textfile.html \ingroup list-of-builtin-services \title TextFile Service \brief Provides read and write operations on text files. The \c TextFile service allows you to read from and write into text files. \section1 Related Declarations \section2 TextFile.OpenMode \code enum TextFile.OpenMode { ReadOnly, WriteOnly, ReadWrite, Append } \endcode List of modes that a file may be opened in. The OpenMode values can be combined with the bitwise or operator. \section1 Available operations \section2 Constructor \code TextFile(filePath: string, openMode: OpenMode = TextFile.ReadOnly) \endcode Opens the file at \c filePath in the given mode and returns the object representing the file. \note The mode influences which of the operations listed below can actually be used on the file. \section2 atEof \code atEof(): boolean \endcode Returns \c{true} if no more data can be read from the file, \c{false} otherwise. \section2 close \code close(): void \endcode Closes the file. It is recommended to always call this function as soon as you are finished with the file, in order to keep the number of in-flight file descriptors as low as possible. \section2 filePath \code filePath(): string \endcode The absolute path of the file represented by this object. \section2 readAll \code readAll(): string \endcode Reads all data from the file and returns it. \section2 readLine \code readLine(): string \endcode Reads one line of text from the file and returns it. The returned string does not contain the newline characters. \section2 setCodec \code setCodec(codec: string): void \endcode Sets the text codec to \c codec. The supported codecs are the same as for \c QTextCodec, for example: "UTF-8", "UTF-16", and "ISO 8859-1". \section2 truncate \code truncate(): void \endcode Truncates the file, that is, gives it the size of zero, removing all content. \section2 write \code write(data: string): void \endcode Writes \c data into the file at the current position. \section2 writeLine \code writeLine(data: string): void \endcode Writes \c data into the file at the current position and appends the newline character(s). */ qbs-src-1.13.1/doc/reference/jsextensions/jsextension-utilities.qdoc000066400000000000000000000056531347155106100256540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-utilities.html \ingroup list-of-builtin-services \title Utilities Service \brief Provides miscellaneous operations. The \c Utilities service offers miscellaneous operations. \section1 Available Operations \section2 cStringQuote \badcode Utilities.cStringQuote(str: string): string \endcode Takes a string and escapes special characters in a way that the result is suitable for use as a C/C++ string literal. This function is typically used to specify values for \l{cpp::defines}{cpp.defines}. \section2 getHash \badcode Utilities.getHash(key: string): string \endcode Calculates a 16-byte hash of the input and returns it. Rules in modules should use this function to find unique locations for output artifacts in the build directory without duplicating the whole directory structure of the respective input file (to deal with the case of two files with the same name in different subdirectories of the same product). \section2 rfc1034Identifier \badcode Utilities.rfc1034Identifier(str: string): string \endcode Returns an RFC-1034 compliant identifier based on the given string by replacing each character that is not Latin alphanumeric or \c{.} with \c{-}. \section2 versionCompare \badcode Utilities.versionCompare(version1: string, version2: string): number \endcode Interprets the two arguments as version numbers and returns a number that is smaller than, equal to, or greater than zero if \c version1 is smaller than, equal to, or greater than \c version2, respectively. The version strings consist of up to three numbers separated by dots. */ qbs-src-1.13.1/doc/reference/jsextensions/jsextension-xml.qdoc000066400000000000000000000176371347155106100244460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-xml.html \ingroup list-of-builtin-services \title Xml Service \brief Provides a DOM parser and generator to JavaScript. The \c Xml service enables you to access and manipulate XML Document Object Model (DOM) documents. The entire document is a \e {document node}, each XML element is an \e {element node}, the text paragraphs in the XML elements are \e {text nodes}, and each attribute is an \e {attribute node}. XML DOM presents documents as tree structures. The contents of the nodes can be accessed in the tree. They can be modified or deleted, and new nodes can be created. The nodes in the node tree have a hierarchical relationship to each other. The top node is called the \e root. Each node, except the root, has exactly one \e parent node, while it can have any number of \e children. Nodes with the same parent are called \e siblings. \section1 XML DOM Document Node Operations A document node represents an entire document. That is, the root of the DOM tree. \section2 Constructor \badcode Xml.DomDocument() \endcode Creates an XML DOM root node that can contain one element. \section2 createCDATASection \badcode Xml.DomDocument.createCDATASection(value: string) \endcode Creates a CDATA section that is not parsed by a parser. It can be used to include XML fragments without having to escape the delimiters, for example. Tags inside the section are not treated as markup nor are entities expanded. \section2 createElement \badcode Xml.DomDocument.createElement(tagName: string) \endcode Creates an element that can contain other elements, CDATA sections, and text nodes. \section2 createTextNode \badcode Xml.DomDocument.createTextNode(value: string) \endcode Creates a text node that represents textual content in an element or attribute. \section2 documentElement \badcode Xml.DomDocument.documentElement() \endcode Returns the document element. \section2 load \badcode Xml.DomDocument.load(filePath: string): void \endcode Loads the document specified by \c filePath. \section2 save \badcode Xml.DomDocument.save(filePath: string, indentation: int): void \endcode Saves the document at the location specified by \c filePath with the indentation specified by \c int. \section2 setContent \badcode Xml.DomDocument.setContent(content: string) \endcode Returns the content of the document. \section2 toString \badcode Xml.DomDocument.toString(indentation: int) \endcode Converts the document to a string with the indentation specified by \c int. \section1 XML DOM Node Operations A node represents a single node in the document tree. There are several different types of nodes, such as element, attribute, and text nodes. All objects inherit the node properties for handling parents and children, even if they cannot have parents or children. For example, attempting to add children to text nodes results in a DOM error. \section2 Constructor \badcode Xml.DomNode() \endcode Creates an XML DOM node. \section2 appendChild \badcode Xml.DomNode.appendChild(tagName: string) \endcode Appends a new child node to the end of the list of children of a node. \section2 attribute \badcode Xml.DomNode.attribute(name: string, defaultValue: string) \endcode Returns the name and default value of the attribute. \section2 clear \badcode Xml.DomNode.clear() \endcode Clears the contents of the node. \section2 data \badcode Xml.DomNode.data() \endcode Returns the contents of the text node, CDATA section, or character data node. \section2 firstChild \badcode Xml.DomNode.firstChild(tagName: string) \endcode Returns the first child of a node. \section2 hasAttribute \badcode Xml.DomNode.hasAttribute(name: string) boolean \endcode Returns \c true if the node has the specified attribute. \section2 hasAttributes \badcode Xml.DomNode.hasAttributes() boolean \endcode Returns \c true if the node has attributes. \section2 hasChildNodes \badcode Xml.DomNode.hasChildNodes() boolean \endcode Returns \c true if the node has children. \section2 insertAfter \badcode Xml.DomNode.insertAfter(newChild: tagName, refChild: tagName) \endcode Inserts a new child node after the child node specified by \c refChild. \section2 insertBefore \badcode Xml.DomNode.insertBefore(newChild: tagName, refChild: tagName) \endcode Inserts a new child node before the child node specified by \c refChild. \section2 isCDATASection \badcode Xml.DomNode.isCDATASection() boolean \endcode Returns \c true if this is a CDATA section. \section2 isElement \badcode Xml.DomNode.isElement() boolean \endcode Returns \c true if this is an element. \section2 isText \badcode Xml.DomNode.isText() boolean \endcode Returns \c true if this is a text node. \section2 lastChild \badcode Xml.DomNode.lastChild(tagName: string) \endcode Returns the last child of a node. \section2 nextSibling \badcode Xml.DomNode.nextSibling(tagName: string) \endcode Returns the node immediately following a node. \section2 parentNode \badcode Xml.DomNode.parentNode() \endcode Returns the parent of the node. \section2 previousSibling \badcode Xml.DomNode.previousSibling(tagName: string) \endcode Returns the node before a node. \section2 removeChild \badcode Xml.DomNode.removeChild(tagName: string) \endcode Removes the child node. \section2 replaceChild \badcode Xml.DomNode.replaceChild(newChild: tagName, oldChild: tagName) \endcode Replaces a child node with another one. \section2 setAttribute \badcode Xml.DomNode.setAttribute(name: string, value: string) \endcode Sets the name and value of an attribute. \section2 setData \badcode Xml.DomNode.setData(value: string): void \endcode Sets the data of the node to a text node, CDATA section, or character data node. \section2 setTagName \badcode Xml.DomNode.setTagName(tagName: string) \endcode Sets the tag name of the node. \section2 tagName \badcode Xml.DomNode.tagName() \endcode Returns the tag name of the node. \section2 text \badcode Xml.DomNode.text() \endcode Returns the text of the node. */ qbs-src-1.13.1/doc/reference/jsextensions/jsextensions-general.qdoc000066400000000000000000000131321347155106100254300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page jsextensions-general.html \ingroup list-of-builtin-services \title General Services \brief Provides various operations. These are operations that do not fit into any of the other categories. They are automatically available in any \QBS project file or JavaScript file. \section1 Available Operations \section2 require \code require(identifier: string): any \endcode Loads an extension and returns an object representing the extension. If \a identifier is a relative or absolute file path, this function will load a JavaScript file and return an object containing the evaluated context of that file. Otherwise, loads a \QBS extension named \a identifier and returns an object that contains the extension's context. This function is only available in JavaScript files and is designed to behave similarly to the CommonJS/RequireJS/Node.js module resolution systems. \code var MyFunctions = require("./myfunctions.js"); MyFunctions.doSomething(); var FileInfo = require("qbs.FileInfo"); var fileName = FileInfo.fileName(filePath); \endcode \section1 Extensions to JavaScript Built-in Objects \section2 Array.contains \code Array.contains(e: any): boolean \endcode Returns \c{true} if the array contains the element \c{e}. Returns \c{false} otherwise. \section2 Array.containsAll \code Array.containsAll(other: any[]): boolean \endcode Returns \c{true} if the array contains every element in the \c{other} array. Returns \c{false} otherwise. \section2 Array.containsAny \code Array.containsAny(other: any[]): boolean \endcode Returns \c{true} if the array contains some element(s) in the \c{other} array. Returns \c{false} otherwise. \section2 Array.uniqueConcat \code Array.uniqueConcat(other: any[]): any[] \endcode Returns a copy of this array joined with the array \c{other}. Duplicates that would originate from the concatenation are removed. The order of elements is preserved. \section2 String.contains \code String.contains(s: string): boolean \endcode Returns \c{true} if the string contains the substring \c{s}. Returns \c{false} otherwise. \section2 startsWith \code String.startsWith(s: string): boolean \endcode Returns \c{true} if the string starts with the substring \c{s}. Returns \c{false} otherwise. \section2 endsWith \code String.endsWith(s: string): boolean \endcode Returns \c{true} if the string ends with the substring \c{s}. Returns \c{false} otherwise. \section1 Console API \QBS provides a subset of the non-standard Console API available in most ECMAScript runtimes. The output of each of these functions will only be displayed if the logging level is at least the level which the function outputs at. Logging levels from lowest to highest are: 'error', 'warning', 'info', 'debug', and 'trace'. The default is 'info'. \warning The contents of this section are subject to change in order to align with future \l{https://www.w3.org/2011/08/browser-testing-charter.html}{standardization} \l{https://github.com/DeveloperToolsWG/console-object/blob/master/api.md}{processes}. \section2 console.debug \code console.debug(s: string): void \endcode This method is an alias for \c{console.log()}. \section2 console.error \code console.error(s: string): void \endcode Logs an \c{error} level message. Outputs to stderr when the logger output is a terminal. The string will be prefixed with \c{"ERROR: "} and colored red when the logger output is a color-capable terminal. \section2 console.info \code console.info(s: string): void \endcode Logs an \c{info} level message. Outputs to stdout when the logger output is a terminal. \section2 console.log \code console.log(s: string): void \endcode Logs a \c{debug} level message. Outputs to stderr when the logger output is a terminal. \section2 console.warn \code console.warn(s: string): void \endcode Logs a \c{warning} level message. Outputs to stderr when the logger output is a terminal. The string will be prefixed with \c{"WARNING: "} and colored yellow when the logger output is a color-capable terminal. */ qbs-src-1.13.1/doc/reference/modules/000077500000000000000000000000001347155106100173255ustar00rootroot00000000000000qbs-src-1.13.1/doc/reference/modules/android-ndk-module.qdoc000066400000000000000000000065551347155106100236650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Android.ndk \inqmlmodule QbsModules \since Qbs 1.4 \brief Provides support for building native Android libraries. The \c Android.ndk module contains the properties and rules to create native libraries for use in Android applications. Normally, you will not use this module directly, but instead work with the \l{DynamicLibrary}, \l{StaticLibrary} and \l Application items that \QBS provides. Here is what the project file for the \c hello-jni example that comes with the NDK could look like: \code CppApplication { name: "HelloJni" Android.sdk.packageName: "com.example.hellojni" qbs.architectures: ["mips", "x86"] files: "app/src/main/jni/hello-jni.c" } \endcode \section2 Relevant File Tags \target filetags-android-ndk \table \header \li Tag \li Since \li Description \row \li \c{"android.nativelibrary"} \li 1.4.0 \li Attached to dynamic libraries that will end up in APK packages. You do not normally need to use the tag explicitly, as it is the default type of the \l{DynamicLibrary} item for Android targets. \endtable */ /*! \qmlproperty string Android.ndk::abi The ABI name as it appears under \c "lib/" in the application package. Corresponds to \c APP_ABI in \c Android.mk. \nodefaultvalue */ /*! \qmlproperty string Android.ndk::appStl The library to use for C++. The possible values are: \list \li \c "c++_shared" \li \c "c++_static" \li \c "gabi++_shared" (until r17) \li \c "gabi++_static" (until r17) \li \c "gnustl_shared" (until r17) \li \c "gnustl_static" (until r17) \li \c "stlport_shared" (until r17) \li \c "stlport_static" (until r17) \li \c "system" \endlist \defaultvalue \c{"system"} */ /*! \qmlproperty path Android.ndk::ndkDir The NDK base directory. \nodefaultvalue */ /*! \qmlproperty string Android.ndk::platform The versioned platform name. \defaultvalue \c{"android-9"} */ qbs-src-1.13.1/doc/reference/modules/android-sdk-module.qdoc000066400000000000000000000134261347155106100236650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Android.sdk \inqmlmodule QbsModules \since Qbs 1.4 \brief Provides support for building Android packages. The Android.sdk module contains the properties and rules to create Android application packages from Java sources, resources, and so on. It is usually pulled in indirectly by declaring an \l Application product. \section2 Relevant File Tags \target filetags-android-sdk \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"android.aidl"} \li \c{*.aidl} \li 1.4.0 \li Attached to Android AIDL files. One Java source file will be generated for each such file. \row \li \c{"android.assets"} \li - \li 1.4.0 \li Attached to Android assets, which are typically located in an \c{assets/} subdirectory. These files are tagged automatically if the \l automaticSources property is enabled. \row \li \c{"android.manifest"} \li \c{AndroidManifest.xml} \li 1.4.0 \li Attached to the Android manifest. There must be one such file for every Android app. \row \li \c{"android.resources"} \li - \li 1.4.0 \li Attached to Android resources, which are typically located in a \c{res/} subdirectory. These files are tagged automatically if the \l automaticSources property is enabled. \endtable */ /*! \qmlproperty string Android.sdk::buildToolsVersion The version of the build tools such as \c aapt and \c dx. \defaultvalue Highest build tools version version available in the SDK. */ /*! \qmlproperty string Android.sdk::ndkDir The NDK base directory, if an NDK is present. \defaultvalue Determined automatically based on standard search paths. */ /*! \qmlproperty string Android.sdk::platform The versioned platform name (for example, \c "android-21"). \defaultvalue Highest build tools version version available in the SDK. */ /*! \qmlproperty string Android.sdk::sdkDir The SDK base directory. \defaultvalue Determined automatically based on standard search paths. */ /*! \qmlproperty bool Android.sdk::embedJar \since Qbs 1.10 If \c true, then if the dependency is a JAR file, its classes and the classes of its dependencies (if \c{embedJar} is also true for them) will be recursively processed by \c{dex} and included in the final APK. \defaultvalue \c{true} */ /*! \qmlproperty string Android.sdk::assetsDir The base directory for Android assets in the respective product. \note Android requires that the file name of this directory is always \c "assets". \defaultvalue \c "src/main/assets" in the product source directory */ /*! \qmlproperty bool Android.sdk::automaticSources If \c true, Java sources as well as Android resources, assets, and the manifest file will be automatically included in the respective product via wildcards. Set this property to \c false if you want to specify these files manually. \defaultvalue \c true */ /*! \qmlproperty string Android.sdk::manifestFile The file path to the Android manifest file. This property is only relevant if \l automaticSources is enabled. \note Android requires that the file name is always "AndroidManifest.xml". \defaultvalue \c "src/main/AndroidManifest.xml" in the product source directory */ /*! \qmlproperty string Android.sdk::packageName The package name of the respective product. The \c package attribute in the manifest file will be set to this value automatically. \defaultvalue \c name */ /*! \qmlproperty string Android.sdk::resourcesDir The base directory for Android resources in the respective product. \note Android requires that the file name of this directory is always \c "res". \defaultvalue \c "src/main/res" in the product source directory */ /*! \qmlproperty path Android.sdk::sourcesDir The base directory for Java sources. This property is only relevant if \l automaticSources is enabled. \defaultvalue \c "src/main/java" in the product source directory */ /*! \qmlproperty string Android.sdk::apkBaseName The base name of the APK file to to be built, that is, the file name without the ".apk" extension. \defaultvalue \l packageName */ /*! \qmlproperty stringList Android.sdk::aidlSearchPaths Search paths for import statements to pass to the \c aidl tool via the \c{-I} option. */ qbs-src-1.13.1/doc/reference/modules/archiver-module.qdoc000066400000000000000000000114571347155106100232730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype archiver \inqmlmodule QbsModules \since Qbs 1.4 \brief Provides support for building archives. The \c archiver module contains the properties and rules for creating (compressed) archives. The output artifact has the file tag \c "archiver.archive". The sole input artifact is a text file containing the list of files to package, with one file path per line. The paths can be relative, in which case they will be looked for in \l{archiver::}{workingDirectory}. The file tag of this input artifact is \c "archiver.input-list". */ /*! \qmlproperty stringList archiver::flags Custom options not covered by any of the other properties. \defaultvalue \c [] */ /*! \qmlproperty string archiver::archiveBaseName The base name of the archive file. That is, the file name without any extensions. \defaultvalue \l{Product::targetName}{product.targetName} */ /*! \qmlproperty string archiver::compressionLevel How much effort to put into the compression of a \c 7-Zip or \c zip archive. Possible values for zip are: \list \li \c undefined \li \c "0" \li \c "1" \li \c "2" \li \c "3" \li \c "4" \li \c "5" \li \c "6" \li \c "7" \li \c "8" \li \c "9" \endlist 7-Zip only supports 0 and the odd numbers above. Higher numbers result in a smaller archive, but the compression process will take more time. If the value is left undefined, the default compression level is used. \nodefaultvalue */ /*! \qmlproperty string archiver::compressionType How to compress a \c tar or \c zip archive. Possible options are: \list \li \c "bz2" \li \c "deflate" \li \c "gz" \li \c "none" \li \c "store" \li \c undefined, which uses the archiver's default compression type. \li \c "xz" \li \c "Z" \endlist \defaultvalue \c{"gz"} for \c tar archives, otherwise \c undefined. */ /*! \qmlproperty string archiver::outputDirectory Where to put the archive file. \defaultvalue \l{Product::destinationDirectory} {product.destinationDirectory} */ /*! \qmlproperty string archiver::type Which kind of archiver to use. The currently supported values are: \list \li \c "7zip" \li \c "tar" \li \c "zip" \endlist \nodefaultvalue */ /*! \qmlproperty string archiver::workingDirectory The directory in which to execute the archiver tool specified by \l{archiver::}{command}. \nodefaultvalue */ /*! \qmlproperty string archiver::command The path to the executable used to create the archive. This is usually the native tool corresponding to the archive type being produced, but may fall back to another tool also capable of producing that archive type if the native tool is not installed on the host system. This behavior is especially useful on platforms such as Windows, where the native tools for producing \c tar and \c zip archives in particular are much less likely to be installed. The following table lists the supported \l{archiver::type}{archive types} and the tools capable of producing them, listed in search order from left to right: \table \header \li Type \li Supported tools \row \li 7zip \li 7z \row \li tar \li tar, 7z \row \li zip \li zip \e (Info-Zip), 7z, jar \e (from Java JDK) \endtable \defaultvalue Depends on \l{archiver::}{type}. */ qbs-src-1.13.1/doc/reference/modules/autotest-module.qdoc000066400000000000000000000044441347155106100233360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype autotest \inqmlmodule QbsModules \since Qbs 1.13 \brief Allows to fine-tune autotest execution. The \c autotest module provides properties that allow autotest applications to specify how exactly they should be run. */ /*! \qmlproperty bool autotest::allowFailure Autotests for which this property is \c true can return a non-zero exit code without causing the entire \l AutotestRunner to fail. Use this for tests that are known to be unreliable. \defaultvalue \c false */ /*! \qmlproperty stringList autotest::arguments The list of arguments to invoke the autotest with. If not specified, then the \l{AutotestRunner::arguments}{arguments} property of the \l AutotestRunner that invokes the autotest is used. \nodefaultvalue */ /*! \qmlproperty string autotest::workingDir The working directory for running the autotest. If not specified, then the \l{AutotestRunner::workingDir}{workingDir} property of the \l AutotestRunner that invokes the autotest is used. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/modules/bundle-module.qdoc000066400000000000000000000327231347155106100227400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype bundle \inqmlmodule QbsModules \since Qbs 1.4 \brief Provides Core Foundation bundle support. The \c bundle module contains properties and rules for building and working with Core Foundation bundles on Apple platforms (commonly known as CFBundles or simply \e bundles), directories with a standardized hierarchical structure that hold executable code and resources. Examples include applications, frameworks, and plugins. This module is available on all platforms but is currently only useful on Apple platforms. \note Core Foundation bundles are not to be confused with Mach-O loadable modules, which are also referred to as (loadable) \e bundles in Apple parlance. In \QBS, Core Foundation bundles are referred to as \e bundles, while Mach-O loadable bundles are referred to as \e {loadable modules}. \section2 Relevant File Tags \target filetags-bundle \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"bundle.content"} \li - \li 1.8 \li Attached to the output artifacts of the rule that produces the bundle. \row \li \c{"infoplist"} \li \c{Info.plist}, \c{*-Info.plist} \li 1.5 \li Source files with this tag are Info property lists files or fragments that are merged into the bundle's final \c Info.plist. \endtable */ /*! \qmlproperty bool bundle::isBundle Whether the product should actually be packaged as a bundle as opposed to a flat file. This allows a product indirectly dependent on the \c{bundle} module to retain control of whether it should actually be built as a bundle. \defaultvalue \c{true} for applications and dynamic libraries on Apple platforms, \c{false} otherwise. */ /*! \qmlproperty bool bundle::isShallow \readonly Whether the bundle directory tree is \e shallow. That is, whether it lacks a \c Contents subdirectory. This is the default on all platforms other than macOS. \defaultvalue \c{false} on macOS, otherwise \c{true}. */ /*! \qmlproperty string bundle::identifierPrefix A prefix for the product's bundle identifier. If \l{bundle::}{identifier} is left unset, the bundle identifier will be a concatenation of this value and the \l{bundle::}{identifier} property, separated by a period (.). This corresponds to the organization identifier in Xcode. \defaultvalue \c{org.example} */ /*! \qmlproperty string bundle::identifier The bundle's identifier. If left unset, the bundle identifier will be a concatenation of this value and the \l{bundle::}{identifierPrefix} property, separated by a period (.). \defaultvalue A combination of \l{bundle::}{identifierPrefix} and the product's target name formatted as an RFC-1034 identifier. */ /*! \qmlproperty string bundle::extension The extension of the bundle's wrapper directory, without the leading period (.). This property should not normally need to be set unless creating a custom bundle type. \defaultvalue \c{"app"} for \c{"APPL"} packages, \c{"framework"} for \c{"FMWK"} packages, and \c{"bundle"} for \c{"BNDL"} and custom packages. */ /*! \qmlproperty string bundle::packageType The four-letter file type code of the bundle, specified in the bundle's \c PkgInfo file and in the bundle's \c Info.plist as the value for the \c CFBundlePackageType key. This property should almost never need to be changed, even though specifying an alternative package type for custom bundles is allowed. \defaultvalue \c{"APPL"} for applications, \c{"FMWK"} for frameworks, and \c{"BNDL"} for custom bundles. */ /*! \qmlproperty bool bundle::generatePackageInfo \since Qbs 1.5 Whether to generate a \c PkgInfo file for the bundle. This property should almost never need to be changed, even though enabling it when specifying an alternative package type for custom bundles using \l{bundle::}{packageType} is allowed. \defaultvalue \c{true} for applications, otherwise \c{false}. */ /*! \qmlproperty string bundle::signature The four-letter signature specific to the bundle, also known as the creator code, specified in the bundle's \c PkgInfo file and in the bundle's \c Info.plist as the value for the \c CFBundleSignature key. This property should normally never need to be set. \defaultvalue \c{"????"} */ /*! \qmlproperty string bundle::bundleName The file name of the bundle's wrapper directory. This property should not normally need to be changed. \defaultvalue A combination of the product's \l{Product::}{targetName} and bundle's \l{bundle::}{extension}. */ /*! \qmlproperty string bundle::frameworkVersion For framework bundles, the version of the framework. Not used for other package types. \defaultvalue \c{"A"} */ /*! \qmlproperty pathList bundle::publicHeaders A list of public header files to copy to a framework bundle's \c Headers subdirectory. \nodefaultvalue */ /*! \qmlproperty pathList bundle::privateHeaders A list of private header files to copy to a framework bundle's \c PrivateHeaders subdirectory \nodefaultvalue */ /*! \qmlproperty bool bundle::resources A list of resources to copy to a bundle's \c Resources subdirectory. Files will automatically be copied into \c lproj subdirectories corresponding to the input files' paths. \nodefaultvalue */ /*! \qmlproperty var bundle::infoPlist A dictionary of key-value pairs to add to the bundle's \c Info.plist. The contents of this property will be aggregated with the values from any \c plist files. If this property and any \c plist files contain the same key, this property will take precedence. However, it might be overridden during postprocessing (see \l{bundle::}{processInfoPlist}). If \c undefined, will not be taken into account. \nodefaultvalue */ /*! \qmlproperty bool bundle::processInfoPlist Whether to perform post-processing on the aggregated \c Info.plist contents. If this property is \c{true}, various post-processing operations will be applied to the bundle's property list dictionary after it has been aggregated from the contents of any \c plist files on disk, and the \l{bundle::}{infoPlist} property. First, values from a list of defaults will be added to the dictionary if they were not already present. Second, values from the \c AdditionalInfo key of the platform SDK's \c Info.plist file will be added to the dictionary if they were not already present, as well as some other miscellaneous keys, such as \c BuildMachineOSBuild and \c UIDeviceFamily (on iOS). Finally, variable expansions will be performed such that substrings of the form \c $(VAR) or \c ${VAR} will be replaced with their corresponding environment variables. \defaultvalue \c{true} */ /*! \qmlproperty bool bundle::embedInfoPlist Whether to create a \c{__TEXT} section in the product's executable containing the processed \c Info.plist. Only applies to command line applications. \defaultvalue \c{true} if the product is a command line tool, otherwise \c{false}. */ /*! \qmlproperty string bundle::infoPlistFormat The file format to write the product's resulting \c Info.plist in. Possible values are: \list \li \c{"binary1"} \li \c{"json"} \li \c{"same-as-input"} \li \c{"xml1"} \endlist \defaultvalue \c{"binary1"} for iOS, \c{"same-as-input"} or \c{"xml1"} for macOS depending on whether a \c plist file is used, and \c{undefined} for all other operating systems. */ /*! \qmlproperty string bundle::infoPlistPath \readonly The path that the \c Info.plist file will be written to. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::infoStringsPath \readonly \since Qbs 1.5 The path that the \c InfoPlist.strings file will be written to. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::pkgInfoPath \readonly The path that the \c PkgInfo file will be written to. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::versionPlistPath \readonly The path that the \c version.plist file will be written to. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::executablePath \readonly The path that the main executable file will be written to. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::contentsFolderPath \readonly The path of the bundle's \c Contents subdirectory. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::documentationFolderPath \readonly \since Qbs 1.5 The path of the directory where documentation will be written. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::executableFolderPath \readonly The path of the directory where the main exectuable will be written. The path is relative to the directory that contains the bundle. Not to be confused with \l{bundle::}{executablesFolderPath}. */ /*! \qmlproperty string bundle::executablesFolderPath \readonly The path of the directory where auxiliary executables will be copied. The path is relative to the directory that contains the bundle. Not to be confused with \l{bundle::}{executableFolderPath}. */ /*! \qmlproperty string bundle::frameworksFolderPath \readonly The path of the directory where internal frameworks will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::javaFolderPath \readonly \since Qbs 1.5 The path of the directory where Java content will be written. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::localizedResourcesFolderPath \readonly \since Qbs 1.5 The path of the directory where localized resource files will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::pluginsFolderPath \readonly The path of the directory where plugins will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::privateHeadersFolderPath \readonly The path of the directory where private header files will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::publicHeadersFolderPath \readonly The path of the directory where public headers files will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::scriptsFolderPath \readonly The path of the directory where script files will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::sharedFrameworksFolderPath \readonly The path of the directory where shared frameworks will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::sharedSupportFolderPath \readonly The path of the directory where shared support files will be copied. The path is relative to the directory that contains the bundle. */ /*! \qmlproperty string bundle::unlocalizedResourcesFolderPath \readonly The path of the directory where non-localized resource files will be copied. The path is relative to the directory that contains the bundle. This is the same as the base resources path. */ /*! \qmlproperty string bundle::versionsFolderPath \readonly \since Qbs 1.5 The path of the bundle's \c Versions subdirectory. The path is relative to the directory that contains the bundle. This is only relevant for (non-shallow) framework bundles. */ qbs-src-1.13.1/doc/reference/modules/cpp-module.qdoc000066400000000000000000001311051347155106100222430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype cpp \inqmlmodule QbsModules \since Qbs 1.0 \brief Provides C/C++ support. The \c cpp module contains the properties and rules for toolchains of the C/C++ family. On Apple platforms, this includes support for Objective-C/C++. \section2 Setting Up the Run Environment When running an application that has dependencies on dynamic libraries, the script specified by \l{Module::setupRunEnvironment}{Module.setupRunEnvironment} automatically adds the locations of the libraries to the environment. That is, to \c PATH on Windows, \c DYLD_LIBRARY_PATH on macOS, and \c LD_LIBRARY_PATH on Linux and other Unix platforms. If the value \c{"ignore-lib-dependencies"} shows up in the \c config array, this behavior is disabled. Users can set the value via the \l run command. \target dependency-parameters-cpp \section2 Dependency Parameters \table \header \li Parameter \li Type \li Since \li Default \li Description \row \li \c{link} \li \c{bool} \li 1.9 \li undefined \li If \c{false}, the dependency will not be linked, even if it is a valid input for a linker rule. This property affects library dependencies only. \row \li \c{linkWholeArchive} \li \c{bool} \li 1.9 \li undefined \li If \c{true}, then if the dependency is a static library, all of its objects will be pulled into target binary, even if their symbols do not appear to be used. This parameter is mainly useful when creating a dynamic library from static libraries. \row \li \c{symbolLinkMode} \li \c{string} \li 1.9 \li undefined \li Attribute specifying how the library or framework will be linked. May contain the values: "weak", "lazy", "reexport", and "upward"; refer to the Apple ld64 man page for full details. \c{undefined} uses normal linking. Currently only applies when linking for Apple platforms. \endtable \section2 Relevant File Tags \target filetags-cpp \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"application"} \li n/a \li 1.0.1 \li The rule that creates executable files (typically via a linker) attaches this tag to its output artifact. \row \li \c{"asm"} \li \c{*.s} (for GCC-like toolchains), \c{*.asm} (for MSVC) \li 1.1.0 \li Source files with this tag serve as inputs to a rule invoking the toolchain's assembler. One object file is generated for each such file. \row \li \c{"asm_cpp"} \li \c{*.S}, \c{*.sx} \li 1.1.0 \li Like \c{"asm"}, but for source files that need preprocessing. This tag only has an effect with GCC-like toolchains. \row \li \c{"c"} \li \c{*.c} (if \c combineCSources is not enabled) \li 1.0.1 \li Source files with this tag serve as inputs to a rule invoking the toolchain's C compiler. One object file is generated for each such file. \row \li \c{"c.combine"} \li \c{*.c} (if \c combineCSources is enabled) \li 1.8 \li Source files with this tag serve as inputs to a rule combining them into a single C file, which will then be compiled. \row \li \c{"cpp"} \li \c{*.C}, \c{*.cpp}, \c{*.cxx}, \c{*.c++}, \c{*.cc} (if \c combineCxxSources is not enabled) \li 1.0.1 \li Source files with this tag serve as inputs to a rule invoking the toolchain's C++ compiler. One object file is generated for each such file. \row \li \c{"cpp.combine"} \li \c{*.C}, \c{*.cpp}, \c{*.cxx}, \c{*.c++}, \c{*.cc} (if \c combineCxxSources is enabled) \li 1.8 \li Source files with this tag serve as inputs to a rule combining them into a single C++ file, which will then be compiled. \row \li \c{"c_pch_src"}, \c{"cpp_pch_src"}, \c{"objc_pch_src"}, \c{"objcpp_pch_src"} \li - \li 1.5 \li Files with this tag will be turned into precompiled headers for C, C++, Objective-C and Objective-C++, respectively. There can be only one such file per product and language. \row \li \c{"dynamiclibrary"} \li n/a \li 1.0.1 \li The rule that creates dynamic libraries (typically via a linker) attaches this tag to its output artifact. \row \li \c{"dynamiclibrary_import"} \li n/a \li 1.0.0 \li This tag is used for import libraries of dynamic libraries. For example, the MSVC linker rule creates a \c{dynamiclibrary_import} artifact \c{foo.lib} in addition to a \c{dynamiclibrary} artifact \c{foo.dll}. \row \li \c{"hpp"} \li \c{*.h}, \c{*.H}, \c{*.hpp}, \c{*.hxx}, \c{*.h++} \li 1.0.1 \li This tag is used for header files (C, C++, Objective-C and Objective-C++). No rule in this module generates output artifacts from such files directly, but the compiler rule will have a dependency on all rules that create such files. \row \li \c{"linkerscript"} \li - \li 1.5.0 \li This tag is used for \c ld linker scripts. You can provide such a file if you need to replace the default linker script. This file tag only has an effect with GCC-like toolchains. The linker needs to be \c{ld}-compatible. \row \li \c{"obj"} \li n/a \li 1.0.1 \li The rule that creates object files (typically via a compiler) attaches this tag to its output artifacts. Such files are usually intermediate artifacts of the build process and rarely need to be referenced in project files. \row \li \c{"objc"} \li \c{*.m} (if \c combineObjcSources is not enabled) \li 1.1.0 \li Source files with this tag serve as inputs to a rule invoking the toolchain's Objective-C compiler. One object file is generated for each such file. \row \li \c{"objc.combine"} \li \c{*.m} (if \c combineObjcSources is enabled) \li 1.8 \li Source files with this tag serve as inputs to a rule combining them into a single Objective-C file, which will then be compiled. \row \li \c{"objcpp"} \li \c{*.mm} (if \c combineObjcxxSources is not enabled) \li 1.1.0 \li Source files with this tag serve as inputs to a rule invoking the toolchain's Objective-C++ compiler. One object file is generated for each such file. \row \li \c{"objcpp.combine"} \li \c{*.mm} (if \c combineObjcxxSources is enabled) \li 1.8 \li Source files with this tag serve as inputs to a rule combining them into a single Objective-C++ file, which will then be compiled. \row \li \c{"rc"} \li \c{*.rc} \li 1.1.0 \li Files with this tag serve as inputs to the Windows resource compiler. One object file is generated for each such file. The tag has no effect on target platforms other than Windows. \row \li \c{"staticlibrary"} \li n/a \li 1.0.1 \li The rule that creates static libraries (typically via a linker) attaches this tag to its output artifact. \row \li \c{"versionscript"} \li - \li 1.5.0 \li This tag is used for \c ld linker scripts. You can provide such a file if you need fine-grained control over the symbols present in a shared library. This file tag only has an effect with GCC-like toolchains. The linker needs to be \c{ld}-compatible. \endtable \section2 Relevant Job Pools \target cpp-job-pools \table \header \li Pool \li Since \li Description \row \li \c{"assembler"} \li 1.13 \li The job pool used by rules that run the toolchain's assembler. This is only relevant for direct invocations of the assembler binary, not for running it indirectly via the compiler. \row \li \c{"compiler"} \li 1.13 \li The job pool used by rules that run a compiler. All language variants use the same pool. \row \li \c{"linker"} \li 1.13 \li The job pool used by rules that run a linker. \endtable */ /*! \qmlproperty bool cpp::allowUnresolvedSymbols \since Qbs 1.2 Set to \c true if you want the linking step to succeed even if the resulting binary contains unresolved symbols. Normally, this makes little sense, but in special cases it is possible that the respective symbols will be available at load time even if they are not present during linking. \nodefaultvalue */ /*! \qmlproperty string cpp::architecture The target architecture. \defaultvalue \l{qbs::architecture}{qbs.architecture} */ /*! \qmlproperty string cpp::endianness \since Qbs 1.9 Specifies the endianness of the target platform's processor architecture (\c{"big"} or \c{"little"}). The value is automatically detected from the compiler's default values, but can also be manually set in order to select a specific endianness when targeting bi-endian architectures like MIPS and PowerPC. \defaultvalue Compiler default value. */ /*! \qmlproperty bool cpp::debugInformation Whether to generate debug information. \defaultvalue \l{qbs::debugInformation}{qbs.debugInformation} */ /*! \qmlproperty bool cpp::combineCSources \since Qbs 1.8 Enabling this property on a \l{Product}{product} instructs the \l{FileTagger}{file tagger} to attach the tag \c{"c.combine"} to C sources, rather than \c{"c"}. As a result, all C sources of the product will be combined into a single file, which is then compiled. This can speed up initial compilation significantly, but is of course detrimental in the context of incremental builds. Also, perfectly legal code may fail to compile with this option due to the merging of translation units. To enable this property in a product that has sources that cannot be merged, put the sources into a dedicated \l{Group} and set their \l{Group::} {fileTags} property to \c{"c"}, overriding the file tagger. \note Module properties set on specific source files (that is, at the Group level) will not be taken into account when building the combined file. You either need to set these properties at the product level or prevent the respective files from getting combined via the mechanism described above. \defaultvalue \c false */ /*! \qmlproperty bool cpp::combineCxxSources \since Qbs 1.8 Like \l{cpp::}{combineCSources}, but for C++. The \l{filetags-cpp} {relevant file tags} are \c{"cpp"} and \c{"cpp.combine"}. \defaultvalue \c false \sa combineCSources */ /*! \qmlproperty bool cpp::combineObjcSources \since Qbs 1.8 Like \l{cpp::}{combineCSources}, but for Objective-C. The \l{filetags-cpp} {relevant file tags} are \c{"objc"} and \c{"objc.combine"}. \defaultvalue \c false \sa combineCSources */ /*! \qmlproperty bool cpp::combineObjcxxSources \since Qbs 1.8 Like \l{cpp::}{combineCSources}, but for Objective-C++. The \l{filetags-cpp} {relevant file tags} are \c{"objcpp"} and \c{"objcpp.combine"}. \defaultvalue \c false \sa combineCSources */ /*! \qmlproperty bool cpp::discardUnusedData \since Qbs 1.10 If this property is \c true, the linker will discard data from objects that it determines to be unused. With MSVC and on Apple platforms, the granularity is per symbol, elsewhere it is per section. \nodefaultvalue */ /*! \qmlproperty bool cpp::separateDebugInformation \since Qbs 1.4 Whether to store debug information in an external file or bundle instead of within the binary. The type of files that will be generated when this property is \c{true} is dependent on the compiler and target platform: \list \li With MSVC, this property controls the generation of \c{.pdb} (Program Debug Database) files. \li On Apple platforms with GCC or Clang, this property controls the generation of \c{.dSYM} (DWARF Symbol) bundles or, if \l{cpp::}{dsymutilFlags} contains the \c{-f} or \c{--flat} flags, \c{.dwarf} symbol files. \li On other platforms with GCC or Clang (including Windows/MinGW), this property controls the generation of \c{.debug} symbol files. \endlist \defaultvalue \c{true} for MSVC and with GCC or Clang on Apple platforms, otherwise \c{false}. */ /*! \qmlproperty stringList cpp::defines A list of preprocessor macros that gets passed to the compiler. To set macro values, use the following syntax: \code cpp.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"'] \endcode \nodefaultvalue */ /*! \qmlproperty stringList cpp::platformDefines A list of preprocessor macros that are used for all projects that are built for the current target platform. User project files usually do not set this property. \nodefaultvalue */ /*! \qmlproperty pathList cpp::includePaths A list of include paths. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue */ /*! \qmlproperty pathList cpp::systemIncludePaths A list of include paths that are passed as system include paths to the compiler. For header files in those paths, warnings will be ignored. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue */ /*! \qmlproperty stringList cpp::systemRunPaths \since Qbs 1.6 The paths the dynamic linker uses on process start-up to locate dynamic libraries. \defaultvalue Auto-detected for host builds on Linux via \c ldconfig, \c{["/lib", "/usr/lib"]} otherwise on Unix, \c [] on Windows. */ /*! \qmlproperty pathList cpp::libraryPaths A list of library search paths. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue */ /*! \qmlproperty stringList cpp::dynamicLibraries A List of dynamic libraries to be linked. If the library is part of your project, consider using a \l{Depends} item instead. \nodefaultvalue */ /*! \qmlproperty stringList cpp::staticLibraries A list of static libraries to be linked. If the library is part of your project, consider using a \l{Depends} item instead. \nodefaultvalue */ /*! \qmlproperty pathList cpp::prefixHeaders \since Qbs 1.0.1 A list of files to automatically include at the beginning of each source file in the \l{Product}{product}. \nodefaultvalue */ /*! \qmlproperty string cpp::optimization The optimization level. \defaultvalue \l{qbs::optimization}{qbs.optimization} */ /*! \qmlproperty bool cpp::treatWarningsAsErrors Whether warnings will be handled as errors and cause the build to fail. \defaultvalue \c{false} */ /*! \qmlproperty bool cpp::useCPrecompiledHeader \since Qbs 1.5 Whether to use a precompiled header for compiling C sources if one is present. Set this property to \c false in a \l Group item to disable precompiled headers for some sources even though a precompiled header is present in the product. See \l{filetags-cpp}{Relevant File Tags} for the associated file tags. \defaultvalue \c true */ /*! \qmlproperty bool cpp::useCxxPrecompiledHeader \since Qbs 1.5 Like \l useCPrecompiledHeader, but for C++. \defaultvalue \c true */ /*! \qmlproperty bool cpp::useObjcPrecompiledHeader \since Qbs 1.5 Like \l useCPrecompiledHeader, but for Objective-C. \defaultvalue \c true */ /*! \qmlproperty bool cpp::useObjcxxPrecompiledHeader \since Qbs 1.5 Like \l useCPrecompiledHeader, but for Objective-C++. \defaultvalue \c true */ /*! \qmlproperty string cpp::warningLevel The warning level for the compiler: \c{"none"} or \c{"all"}. \defaultvalue \c{"all"} */ /*! \qmlproperty stringList cpp::driverFlags \since Qbs 1.6 A list of flags that are added to all compilation and linking commands performed by the compiler driver, independently of the language. \nodefaultvalue */ /*! \qmlproperty stringList cpp::driverLinkerFlags \since Qbs 1.11 A list of flags that are added to all linking commands performed by the compiler driver, independently of the language. \nodefaultvalue */ /*! \qmlproperty stringList cpp::commonCompilerFlags \since Qbs 1.0.1 A list of flags that are added to all compilation commands independently of the language. \nodefaultvalue */ /*! \qmlproperty int cpp::compilerVersionMajor \since Qbs 1.4 The major version of the compiler. \nodefaultvalue */ /*! \qmlproperty int cpp::compilerVersionMinor \since Qbs 1.4 The minor version of the compiler. \nodefaultvalue */ /*! \qmlproperty int cpp::compilerVersionPatch \since Qbs 1.4 The patch level component of the compiler version. \nodefaultvalue */ /*! \qmlproperty stringList cpp::assemblerFlags \since Qbs 1.5 A list of additional flags for the assembler. \nodefaultvalue */ /*! \qmlproperty stringList cpp::cppFlags A list of additional flags for the C preprocessor. \nodefaultvalue */ /*! \qmlproperty stringList cpp::cFlags A list of additional flags for the C compiler. \nodefaultvalue */ /*! \qmlproperty stringList cpp::cxxFlags A list of additional flags for the C++ compiler. \nodefaultvalue */ /*! \qmlproperty stringList cpp::cLanguageVersion \since Qbs 1.4 The version of the C standard with which the code must comply. If this property is set, the corresponding compiler and linker flags will be added, depending on the toolchain. If the value is left undefined, the compiler default will be used. If the list contains more than one value, the highest version is chosen. Possible values include: \c{"c89"}, \c{"c99"}, \c{"c11"}. \nodefaultvalue */ /*! \qmlproperty stringList cpp::cxxLanguageVersion \since Qbs 1.4 The version of the C++ standard with which the code must comply. If this property is set, the corresponding compiler and linker flags will be added, depending on the toolchain. If the value is left undefined, the compiler default will be used. If the list contains more than one value, the highest version is chosen. Possible values include: \c{"c++98"}, \c{"c++11"}, \c{"c++14"}, \c{"c++17"}. \nodefaultvalue */ /*! \qmlproperty bool cpp::useLanguageVersionFallback \since Qbs 1.11 Whether to explicitly use the language standard version fallback values in compiler command line invocations. By default, \QBS will automatically substitute fallback values for the C and C++ language standard versions specified by the \l cLanguageVersion and \l cxxLanguageVersion properties, which are passed to the \c{-std=} compiler command line option with GNU-compatible toolchains, if it detects that you are using an older toolchain which does not support the standard values. The substitutions are made as follows: \table \header \li Value \li Substitute \row \li c++11 \li c++0x \row \li c11 \li c1x \row \li c++14 \li c++1y \row \li c++17 \li c++1z \endtable If this property is explicitly set to \c true, \QBS will always use the fallback values. If this property is explicitly set to \c false, \QBS will never use the fallback values. This property has no effect with the Microsoft Visual C++ compiler. \nodefaultvalue */ /*! \qmlproperty string cpp::cxxStandardLibrary \since Qbs 1.4 The C++ standard library to link to. If this property is set, the corresponding compiler and linker flags will be added, assuming the value is valid for the current toolchain. If the value is left undefined, the compiler default will be used. Possible values include: \c{"libstdc++"}, \c{"libc++"}. \nodefaultvalue */ /*! \qmlproperty stringList cpp::objcFlags A list of additional flags for the Objective-C compiler. \nodefaultvalue */ /*! \qmlproperty stringList cpp::objcxxFlags A list of additional flags for the Objective-C++ compiler. \nodefaultvalue */ /*! \qmlproperty stringList cpp::linkerFlags A list of additional flags for the linker. These flags should \e not be escaped using the \c -Wl or \c -Xlinker syntaxes, as \QBS will do this automatically based on the linker being used. \sa linkerMode \nodefaultvalue */ /*! \qmlproperty string cpp::assemblerName \since Qbs 1.5 The name of the assembler binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::toolchainInstallPath The directory path where the toolchain is installed. This property is set in the build profile. This is usually the base property from which all compiler and tool paths are automatically derived. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::assemblerPath \since Qbs 1.5 The full path of the assembler binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::compilerName The name of the main compiler binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::compilerPath The full path of the main compiler binary. This property is set in the build profile. If the toolchain provides different compilers for different languages, \l{cpp::}{compilerPathByLanguage} is used. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty var cpp::compilerPathByLanguage \since Qbs 1.3 A \c{string} to \c{string} map that maps file tags to full paths of compiler binaries. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty stringList cpp::compilerWrapper \since Qbs 1.1 A wrapper binary and its arguments for wrapping compiler calls. This is useful for compiler wrappers, such as \c ccache. \nodefaultvalue */ /*! \qmlproperty string cpp::linkerName \since Qbs 1.1.1 The name of the linker binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::linkerPath \since Qbs 1.1.1 The full path of the linker binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty stringList cpp::linkerWrapper \since Qbs 1.6.2 A wrapper binary and its arguments for wrapping linker calls. This is useful for linker wrappers as needed by Bullseye Coverage, for example. \nodefaultvalue */ /*! \qmlproperty string cpp::entryPoint \since Qbs 1.3 The name of the entry point of an executable or dynamic library. If this property is left undefined, the toolchain's default is used. \nodefaultvalue */ /*! \qmlproperty string cpp::runtimeLibrary \since Qbs 1.3.3 The type of the runtime library used. Accepted values are \c{"static"} and \c{"dynamic"}. If this property is set to \c{undefined}, the default runtime library of the toolchain is used. \note This property is only functional for MSVC. \defaultvalue \c{"dynamic"} for MSVC, \c{undefined} for other compilers. */ /*! \qmlproperty bool cpp::enableExceptions \since Qbs 1.5 Whether to enable exceptions in C++ code. \defaultvalue \c{true} */ /*! \qmlproperty string cpp::exceptionHandlingModel \since Qbs 1.5 The exception handling model to use. For MSVC, this can be \c{"default"}, \c{"seh"} or \c{"externc"}. For all other compilers, \c{"default"} indicates the default or the only exception handling model. \defaultvalue \c{"default"} */ /*! \qmlproperty bool cpp::enableRtti \since Qbs 1.5 Whether to enable runtime type information in C++ code. \nodefaultvalue */ /*! \qmlproperty bool cpp::enableReproducibleBuilds \since Qbs 1.5 Whether the compiler should try to generate reproducible object files. Some compilers (notably GCC) use random numbers for generating symbol names that have to be different in every compilation unit. This is avoided by setting this property to \c{true}. \defaultvalue \c{false} */ /*! \qmlproperty bool cpp::treatSystemHeadersAsDependencies \since Qbs 1.8 Whether included header files found via \l{cpp::}{systemIncludePaths}, \l{cpp::}{distributionIncludePaths}, or \l{cpp::}{compilerIncludePaths} will be added to the dependencies of the respective object file. This means that modification of such header files (or any of the headers they include) will cause recompilation. \defaultvalue \c{false} */ /*! \qmlproperty stringList cpp::dsymutilFlags \since Qbs 1.4.1 \appleproperty Additional flags for the \c dsymutil tool. \note If this property contains the \c{-f} or \c{--flat} options, this will cause \QBS to generate "flat" (single-file) \c{.dwarf} debug symbol files instead of \c{.dSYM} bundles (directories) when \l{cpp::}{separateDebugInformation} is set to \c{true}. \nodefaultvalue */ /*! \qmlproperty string cpp::dsymutilPath \since Qbs 1.4 \appleproperty The full path of the \c dsymutil binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::lipoPath \since Qbs 1.9 \appleproperty The full path of the \c lipo binary. \defaultvalue Determined automatically. */ /*! \qmlproperty pathList cpp::frameworkPaths \appleproperty A list of framework search paths. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue */ /*! \qmlproperty pathList cpp::systemFrameworkPaths \appleproperty A list of framework search paths. Relative paths are considered to be relative to the \c .qbs product file they are used in. Header files in frameworks in those paths will not cause warnings. \nodefaultvalue */ /*! \qmlproperty stringList cpp::frameworks \appleproperty A list of frameworks to be linked. If the framework is part of your project, consider using a \l{Depends} item instead. \nodefaultvalue */ /*! \qmlproperty stringList cpp::weakFrameworks \appleproperty A list of frameworks to be weakly linked. If the framework is part of your project, consider using a \l{Depends} item instead. \nodefaultvalue */ /*! \qmlproperty bool cpp::automaticReferenceCounting \since Qbs 1.4 \appleproperty Whether to enable Automatic Reference Counting (ARC) for Objective-C and Objective-C++ source code. If left undefined, uses the compiler default (probably \c{false}). \nodefaultvalue */ /*! \qmlproperty bool cpp::requireAppExtensionSafeApi \since Qbs 1.4 \appleproperty Whether to enforce the use of only app-extension-safe APIs on Apple platforms. This is necessary for building Application Extensions in OS X Yosemite and iOS 8 and above. If left undefined, uses the compiler and linker defaults (probably \c{false}). \nodefaultvalue */ /*! \qmlproperty string cpp::minimumIosVersion \appleproperty A version number in the format \c{[major].[minor]} indicating the earliest version of iOS that the product should run on. Passes \c{-miphoneos-version-min=} to the compiler. If left undefined, compiler defaults will be used. \nodefaultvalue */ /*! \qmlproperty string cpp::minimumOsxVersion \obsolete \appleproperty Deprecated in \QBS 1.5.2. Use \l{cpp::minimumMacosVersion} instead. \nodefaultvalue */ /*! \qmlproperty string cpp::minimumMacosVersion \since Qbs 1.5.2 \appleproperty A version number in the format \c{[major].[minor]}indicating the earliest version of macOS that the product should run on. Passes \c{-mmacosx-version-min=} to the compiler. If left undefined, compiler defaults will be used. \nodefaultvalue */ /*! \qmlproperty string cpp::minimumWatchosVersion \appleproperty A version number in the format \c{[major].[minor]} indicating the earliest version of Apple watchOS that the product should run on. If left undefined, compiler defaults will be used. \nodefaultvalue */ /*! \qmlproperty string cpp::minimumTvosVersion \since Qbs 1.5 \appleproperty A version number in the format \c{[major].[minor]} indicating the earliest version of Apple tvOS that the product should run on. If left undefined, compiler defaults will be used. \nodefaultvalue */ /*! \qmlproperty string cpp::archiverName \unixproperty The name of the archiver binary. This property is set in the build profile. \defaultvalue \c{"ar"} */ /*! \qmlproperty string cpp::archiverPath \unixproperty The full path of the archiver binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::exportedSymbolsCheckMode \since Qbs 1.4.1 \unixproperty Controls how \QBS determines whether an updated dynamic library causes relinking of dependents. The default value is \c "ignore-undefined", which means that undefined symbols being added or removed do not cause any relinking. If that should happen, for example because dependent products are linked with an option such as \c "--no-undefined", this property can be set to \c "strict". \defaultvalue \c "ignore-undefined" */ /*! \qmlproperty string cpp::linkerMode \since Qbs 1.6 \unixproperty Controls whether to automatically use an appropriate compiler frontend instead of the system linker when linking binaries. The default is \c{"automatic"}, which chooses either the C++ compiler, C compiler, or system linker specified by the \l{cpp::}{linkerName} and \l{cpp::}{linkerPath} properties, depending on the type of object files present on the linker command line. Set this property to \c{"manual"} to explicitly specify the linker using the \l{cpp::}{linkerName} and \l{cpp::}{linkerPath} properties. \defaultvalue \c "automatic" */ /*! \qmlproperty string cpp::linkerVariant \since Qbs 1.13 \unixproperty Set this property to force the use of a specific \c ld implementation. A non-empty value will result in the \c {-fuse-ld} option being emitted when linking with \c gcc or \c clang. The possible values are \c "bfd", \c "gold" and \c "lld". \nodefaultvalue */ /*! \qmlproperty string cpp::nmName \since Qbs 1.2 \unixproperty The name of the \c nm binary. This property is set in the build profile. \defaultvalue \c{"nm"} */ /*! \qmlproperty string cpp::nmPath \since Qbs 1.2 \unixproperty The full path of the \c nm binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::objcopyName \since Qbs 1.4 \unixproperty The name of the \c objcopy binary. This property is set in the build profile. \defaultvalue \c{"objcopy"} */ /*! \qmlproperty string cpp::objcopyPath \since Qbs 1.4 \unixproperty The full path of the \c objcopy binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty string cpp::stripName \since Qbs 1.4 \unixproperty The name of the \c strip binary. This property is set in the build profile. \defaultvalue \c{"strip"} */ /*! \qmlproperty string cpp::stripPath \since Qbs 1.4 \unixproperty The full path of the \c strip binary. This property is set in the build profile. \defaultvalue Determined by \l{setup-toolchains}{qbs setup-toolchains}. */ /*! \qmlproperty bool cpp::positionIndependentCode \unixproperty Whether to generate position-independent code. If this property is left undefined, position-independent code is generated for libraries, but not for applications. \nodefaultvalue */ /*! \qmlproperty string cpp::rpathOrigin \since Qbs 1.11 \unixproperty A placeholder value used in an \c rpath string to refer to the directory containing the referring executable or shared library. \defaultvalue \c{"@loader_path"} on Mach-O based platforms (macOS, iOS, tvOS, watchOS); \c{"$ORIGIN"} on ELF based platforms (Linux and most other Unix-like platforms). */ /*! \qmlproperty stringList cpp::rpaths \unixproperty A list of \c rpaths that are passed to the linker. Paths that also appear in \l{cpp::}{systemRunPaths} are ignored. \nodefaultvalue */ /*! \qmlproperty string cpp::sonamePrefix \since Qbs 1.5 \unixproperty A library name or full library path. If defined, the value of this property is used as a path to be prepended to the built shared library's \c SONAME identifier. The \c SONAME (\c LC_ID_DYLIB on Apple platforms, \c DT_SONAME on other Unix-like platforms) is the identifier that the dynamic linker will later use to reference the library. On Apple platforms, the path may contain the following placeholders: \list \li \c @rpath - Expands to paths defined by \c LC_RPATH Mach-O commands in the current process executable or the referring libraries. \li \c @executable_path - Expands to the current process executable location. \li \c @loader_path - Expands to the referring executable or library location. \endlist In most cases, using \c @rpath is sufficient and recommended. However, the prefix may be also specified using different placeholders, or an absolute path. For more information, see the \l{DYLD documentation} on dynamic library install names. \nodefaultvalue */ /*! \qmlproperty string cpp::soVersion \since Qbs 1.7 \unixproperty The version number to be appended to the soname in ELF shared libraries. \defaultvalue The major part of \l{Product::version}{product.version} if a version is set, otherwise \c []. */ /*! \qmlproperty bool cpp::useRPaths \since Qbs 1.3 \unixproperty If \c{false}, prevents the linker from writing \c rpaths to the binary. \defaultvalue \c{true} */ /*! \qmlproperty bool cpp::useRPathLink \since Qbs 1.8 \unixproperty Whether to use the \c{-rpath-link} linker option for transitive shared objects. \defaultvalue \c{true} on non-Darwin Unix platforms or when targeting macOS 10.4.x and older. */ /*! \qmlproperty string cpp::variantSuffix \since Qbs 1.10 A suffix to add to a product's target name if that product is of the \l{Product::type}{type} \c staticlibrary or \c dynamiclibrary. On Darwin platforms, applications and loadable modules are also affected. By default, this property is left empty on all platforms unless the product is multiplexed over the \l{qbs::buildVariants}{qbs.buildVariants} property. In that case, for the debug variant of the product, the default value is \c{"d"} on Windows and \c{"_debug"} on Darwin platforms, such as macOS. On all other platforms and in release mode, the default value is \c []. For example, building a dynamic library called \c MyLib that is multiplexed over the \l{qbs::buildVariants}{qbs.buildVariants} property with MSVC will produce files called \c{MyLib.dll} (for the release version of the product) and \c{MyLibd.dll} (for the debug version). \defaultvalue Platform-specific. */ /*! \qmlproperty string cpp::visibility \unixproperty The visibility level for exported symbols. Possible values include: \c{"default"}, \c{"hidden"}, \c{"hiddenInlines"}, and \c{"minimal"}, which combines \c{"hidden"} and \c{"hiddenInlines"}. \defaultvalue \c{"default"} */ /*! \qmlproperty bool cpp::generateManifestFile \since Qbs 1.5.0 \windowsproperty Whether to auto-generate a manifest file and include it in the binary. Set this property to \c false if you provide your own \c rc file. \defaultvalue \c{true} */ /*! \qmlproperty string cpp::windowsApiCharacterSet \since Qbs 1.0.1 \windowsproperty The character set used in the Win32 API. The value \c "unicode" defines the preprocessor symbols \c UNICODE and \c _UNICODE, \c "mbcs" defines \c _MBCS, and setting the value to \c undefined will use the default character set. \defaultvalue \c{"unicode"} */ /*! \qmlproperty string cpp::windowsApiFamily \since Qbs 1.10 \windowsproperty The Windows API family that the application or library is targeting. This value is used when building Universal Windows Platform applications. Possible values include: \c{"desktop"}, \c{"pc"}, \c{"phone"}, \c{"server"}, and \c{"system"}, which are mapped to the corresponding set of possible values for the \c WINAPI_FAMILY preprocessor define in the Windows SDK. \defaultvalue Undefined, which lets the Windows SDK headers determine the default. */ /*! \qmlproperty stringList cpp::windowsApiAdditionalPartitions \since Qbs 1.10 \windowsproperty A list of additional Windows API partitions to enable in addition to the ones implicitly enabled by the value of \l{cpp::}{windowsApiFamily} (\c WINAPI_FAMILY). This value is used when building Windows Store applications. For example, setting \l{cpp::}{windowsApiFamily} to \c{"pc"} and this property to \c{["phone"]} will allow you to create Windows Store applications that target all Universal Windows Platform device families (\c "Universal" apps). Possible values include: \c{"app"}, \c{"desktop"}, \c{"pc"}, \c{"phone"}, \c{"server"}, and \c{"system"}, which are mapped to the corresponding set of possible \c WINAPI_PARTITION_* preprocessor defines in the Windows SDK. \defaultvalue Undefined, which lets the Windows SDK headers determine the default partitions based on the value of \c WINAPI_FAMILY. \sa windowsApiFamily */ /*! \qmlproperty bool cpp::requireAppContainer \since Qbs 1.10 \windowsproperty Whether the generated executable or dynamic-link library \e requires an AppContainer execution environment. Set to \c true when creating Universal Windows Platform applications. \nodefaultvalue */ /*! \qmlproperty string cpp::minimumWindowsVersion \windowsproperty A version number in the format \c{[major].[minor]} indicating the earliest version of Windows that the product should run on. Defines \c WINVER, \c _WIN32_WINNT, and \c _WIN32_WINDOWS, and applies a version number to the linker flags \c /SUBSYSTEM and \c /OSVERSION for MSVC or \c --major-subsystem-version, \c --minor-subsystem-version, \c --major-os-version, and \c --minor-os-version for MinGW. If left undefined, compiler defaults will be used. \nodefaultvalue */ /*! \qmlproperty bool cpp::alwaysUseLipo \since Qbs 1.9 Whether to always use \c lipo when combining Mach-O output files on Apple platforms, even if there is only one CPU architecture. This value should not normally need to be changed. \defaultvalue \c{false} */ /*! \qmlproperty var cpp::compilerDefinesByLanguage \since Qbs 1.10 A \c{string} to \c{string} to \c{string} map of language tags to list of preprocessor macros that are used for all projects that are using the current toolchain. User project files usually do not set this property. \note This property will not be usable without also setting \l{cpp::}{enableCompilerDefinesByLanguage}. \nodefaultvalue */ /*! \qmlproperty pathList cpp::compilerIncludePaths \since Qbs 1.6 A list of \c #include search paths that are used for all projects that are using the current toolchain. User project files usually do not set this property. \defaultvalue Determined automatically by probing the compiler. */ /*! \qmlproperty pathList cpp::compilerFrameworkPaths \since Qbs 1.6 A list of framework search paths that are used for all projects that are using the current toolchain. User project files usually do not set this property. \defaultvalue Determined automatically by probing the compiler. */ /*! \qmlproperty pathList cpp::compilerLibraryPaths \since Qbs 1.6 A list of library search paths that are used for all projects that are using the current toolchain. User project files usually do not set this property. \defaultvalue Determined automatically by probing the compiler. */ /*! \qmlproperty pathList cpp::distributionFrameworkPaths \since Qbs 1.8 A list of distribution-specific framework search paths, prioritized after \l{cpp::}{systemFrameworkPaths}. Intended for use by module authors implementing support for new operating systems or distributions. User project files should not set this property. \nodefaultvalue */ /*! \qmlproperty pathList cpp::distributionIncludePaths \since Qbs 1.8 A list of distribution-specific include paths that are passed as system include paths to the compiler, prioritized after \l{cpp::}{systemIncludePaths}. Intended for use by module authors implementing support for new operating systems or distributions. User project files should not set this property. \nodefaultvalue */ /*! \qmlproperty pathList cpp::distributionLibraryPaths \since Qbs 1.8 A list of distribution-specific library search paths. Intended for use by module authors implementing support for new operating systems or distributions. User project files should not set this property. \nodefaultvalue */ /*! \qmlproperty stringList cpp::enableCompilerDefinesByLanguage \since Qbs 1.10 A list of languages (one or more of \c{"c"}, \c{"cpp"}, \c{"objc"}, \c{"objcpp"}) to extract the list of default compiler defines for in \l{cpp::}{compilerDefinesByLanguage}. Because this has performance implications, no languages are enabled by default. \nodefaultvalue */ /*! \qmlproperty bool cpp::generateMapFile \since Qbs 1.13 \baremetalproperty Whether to auto-generate a linker map file. \defaultvalue \c{true} */ qbs-src-1.13.1/doc/reference/modules/cpufeatures-module.qdoc000066400000000000000000000122011347155106100240020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype cpufeatures \inqmlmodule QbsModules \since Qbs 1.10 \brief Provides support for fine-tuning CPU features. The \c cpufeatures module offers properties for enabling or disabling specific CPU features. Use it if you want to override the compiler defaults for a given platform. The compiler rules in the \l{cpp} module evaluate this module's properties and generate matching compiler flags. All properties in this module are of type \c bool and have the following semantics: \list \li The default value \c undefined has no effect on the compiler command line. \li If the value is \c true and the compiler has a flag to enable the feature, that flag is added to the command line if it is applicable to the current architecture. For example, enabling the property \c x86_sse2 would result in the GCC option \c{-msse2}. \li If the value is \c false and the compiler has a flag to disable the feature, that flag is added to the command line if it is applicable to the current architecture. For example, disabling the property \c x86_sse2 would result in the GCC option \c{-no-msse2}. \endlist */ /*! \qmlproperty bool cpufeatures::arm_neon Whether to use NEON instructions in ARM binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::arm_vfpv4 Whether to use VFPv4 instructions in ARM binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::mips_dsp Whether to use DSP instructions in MIPS binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::mips_dspr2 Whether to use DSPr2 instructions in MIPS binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx Whether to use AVX instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx2 Whether to use AVX2 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512bw Whether to use AVX-512-BW instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512cd Whether to use AVX-512-CD instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512dq Whether to use AVX-512-DQ instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512er Whether to use AVX-512-ER instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512f Whether to use AVX-512 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512ifma Whether to use AVX-512-IFMA instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512pf Whether to use AVX-512-PF instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512vbmi Whether to use AVX-512-VBMI instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_avx512vl Whether to use AVX-512-VL instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_f16c Whether to use F16C instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_sse2 Whether to use SSE2 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_sse3 Whether to use SSE3 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_ssse3 Whether to use SSSE3 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_sse4_1 Whether to use SSE4.1 instructions in x86 binaries. \nodefaultvalue */ /*! \qmlproperty bool cpufeatures::x86_sse4_2 Whether to use SSE4.2 instructions in x86 binaries. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/modules/dmg-module.qdoc000066400000000000000000000317061347155106100222360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype dmg \inqmlmodule QbsModules \since Qbs 1.9 \brief Provides support for building Apple Disk Images. The \c dmg module contains properties and rules for building Apple Disk Images, which are typically used to distribute applications and installers on macOS. This module is only available on Apple platforms. \QBS enables you to build macOS disk images with custom backgrounds and icon layouts. Most applications on macOS are installed via a \c .dmg file, which is usually customized by using a custom image background and icon layout. Unfortunately, it is challenging to construct such DMG files correctly, because the layout relies on several undocumented proprietary file formats, some of which date back to the Mac OS Classic days, and which are even nested within one another. Most of the existing tools to create DMG files do so by using AppleScript to manipulate the Finder graphically to generate the appropriate icon layout, which is both unstable and incompatible with headless build servers, because the necessary OS services to launch graphical applications may not be running at all. Many projects create the primary \c .DS_Store file manually, and commit the result to their source repository. This binary blob is difficult to inspect and edit, and might not be backwards compatible with older versions of the OS, depending on how it was generated. \QBS takes a different approach. It generates the necessary files programmatically, in an entirely reproducible manner. There are no external dependencies that need to be separately installed nor do any binary blobs need to be committed to your source repository. \section2 Appearance Properties Appearance properties are used to control the contents of the .DS_Store file and its embedded Alias and Bookmark records, that will be generated by \QBS in order to control the appearance of the disk image when mounted in Finder. \section2 License Properties License properties are used to control the content and appearance of the license prompt displayed when a user attempts to mount the resulting disk image via Finder. \section2 Relevant File Tags \target filetags-dmg The file tags determine how the tagged files are handled. \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"dmg.input"} \li n/a \li 1.9 \li Tagged files are copied into the disk image. The \l{dmg::}{sourceBase} property controls the destination directory and hierarchy of copied files within the disk image. \row \li \c{"dmg.license.input"} \li \c{*.txt}, \c{*.rtf}, \c{*.html}, \c{*.doc}, \c{*.docx}, \c{*.odt}, \c{*.xml}, \c{*.webarchive} \li 1.9 \li Tagged files are converted into rich text and used for the license prompt when mounting the DMG. \row \li \c{"icns"} \li \c{*.icns} \li 1.3 \li The tagged file is added as the Apple Disk Image volume icon, which will show up in the Finder as an overlay on the file icon. \row \li \c{"tiff"} \li \c{*.tif}, \c{*.tiff} \li 1.9 \li The tagged file is used as the background image of the directory as shown in Finder when the DMG file is mounted. \endtable */ /*! \qmlproperty string dmg::volumeName The name of the disk image that is displayed in Finder when the DMG is mounted. \defaultvalue \l{Product::targetName}{product.targetName} */ /*! \qmlproperty bool dmg::badgeVolumeIcon Whether to render the user-supplied icon (\l{filetags-dmg}{"icns"}) on top of the default volume icon instead of using it directly. This generally gives the disk image icon a better and more consistent appearance. \defaultvalue \c{false} */ /*! \qmlproperty string dmg::format The format to create the disk image in. Allowed values include but are not limited to \c{"UDZO"}, \c{"UDBZ"}, and \c{"ULFO"}. \defaultvalue \c{"UDBZ"} */ /*! \qmlproperty int dmg::compressionLevel The \c zlib, \c bzip2, or \c lzfse compression level for UDZO, UDBZ, or ULFO disk images. \defaultvalue \c 9 in release mode, otherwise \c undefined. */ /*! \qmlproperty string dmg::sourceBase The base directory of the files that are going to be embedded in the DMG (\l{filetags-dmg}{"dmg.input"}). The source base directory is omitted from the target directory path of the DMG directory. \defaultvalue The directory of the current file to be embedded, relative to the product's source directory. */ /*! \qmlproperty string dmg::backgroundColor The background color of the disk image as seen when mounted in Finder. For the full list of supported color names and formats, see the \l{dmgbuild - Settings} documentation. For more information about how to use an image for the background instead, see \l{filetags-dmg}{"tiff"}. \nodefaultvalue */ /*! \qmlproperty int dmg::iconSize The width and height of the file icons as seen when the disk image is mounted in Finder. \defaultvalue \c{128} */ /*! \qmlproperty int dmg::windowX The x position of the Finder window that displays the disk image contents when it is mounted. \defaultvalue \c{100} */ /*! \qmlproperty int dmg::windowY The y position of the Finder window that displays the disk image contents when it is mounted. \defaultvalue \c{100} */ /*! \qmlproperty int dmg::windowWidth The width of the Finder window that displays the disk image contents when it is mounted. \defaultvalue \c{640} */ /*! \qmlproperty int dmg::windowHeight The height of the Finder window that displays the disk image contents when it is mounted. \note The window height includes the height of the standard macOS title bar (22 points). \defaultvalue \c{480} */ /*! \qmlproperty list dmg::iconPositions A list of objects containing the \c{path}, \c{x}, and \c{y} properties, which correspond to disk image-relative file paths and visual coordinates of file icons in the disk image as seen when it is mounted in Finder. For example: \code dmg.iconPositions: [ {"path": "Applications", "x": 128, "y": 128}, {"path": "Foo Bar.app", "x": 256, "y": 128} ] \endcode This property is useful for specifying the positions of files where you do not have direct control over the corresponding \QBS artifact, or there is no corresponding \QBS artifact (for example, "Foo Bar.app" is a directory, which has no equivalent artifact in the build graph). For files to which you are directly applying the \l{filetags-dmg}{dmg.input} file tag, you should use the \l{dmg::}{iconX} and \l{dmg::}{iconY} properties instead. \nodefaultvalue */ /*! \qmlproperty int dmg::iconX The x position of the file icon in the Finder window that displayed the disk image contents when it is mounted. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.input}. It cannot be used at the product level to affect all files. If you do not have access to the artifact corresponding to the file whose position you want to set, use the \l{dmg::}{iconPositions} property instead. \defaultvalue \c{windowWidth / 2} */ /*! \qmlproperty int dmg::iconY The y position of the file icon in the Finder window that displayed the disk image contents when it is mounted. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.input}. It cannot be used at the product level to affect all files. If you do not have access to the artifact corresponding to the file whose position you want to set, use the \l{dmg::}{iconPositions} property instead. \defaultvalue \c{windowHeight / 2} */ /*! \qmlproperty string dmg::defaultLicenseLocale The locale of the default license to display when there is no license whose locale matches the system locale. \defaultvalue \c{"en_US"} */ /*! \qmlproperty string dmg::licenseLocale The locale of the license file. Defaults to a value guessed from the file path, specifically the base name of any \c .lproj directory found in the file's path. If the locale could not be determined from the file path and this property is not set, an error will be emitted. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue Determined automatically. */ /*! \qmlproperty string dmg::licenseLanguageName The name of the language associated with the license file, localized to that language. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"English"} */ /*! \qmlproperty string dmg::licenseAgreeButtonText The text shown on the \e Agree button associated with the license file, localized to the value of \l{dmg::}{licenseLanguageName}. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"Agree"} */ /*! \qmlproperty string dmg::licenseDisagreeButtonText The text shown on the \c Disagree button associated with the license file, localized to the value of \l{dmg::}{licenseLanguageName}. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"Disagree"} */ /*! \qmlproperty string dmg::licensePrintButtonText The text shown on the \c Print button associated with the license file, localized to the value of \l{dmg::}{licenseLanguageName}. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"Print"} */ /*! \qmlproperty string dmg::licenseSaveButtonText The text shown on the \e Save button associated with the license file, localized to the value of \l{dmg::}{licenseLanguageName}. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"Save"} */ /*! \qmlproperty string dmg::licenseInstructionText An instruction text associated with the license file that will be shown on the license dialog, localized to the value of \l{dmg::}{licenseLanguageName}. This property is only useful with artifacts tagged \l{filetags-dmg} {dmg.license.input}. It cannot be used at the product level to affect all files. \defaultvalue \c{"If you agree with the terms of this license, press \"Agree\" to install the software. If you do not agree, press \"Disagree\"."} */ /*! \qmlproperty string dmg::dmgSuffix The file extension for disk images. This should not normally need to be changed. \defaultvalue \c{".dmg"} */ /*! \qmlproperty string dmg::hdiutilPath The path to the \c hdiutil binary used to perform disk image related operations. This should not normally need to be changed. \defaultvalue \c{"/usr/bin/hdiutil"} */ /*! \qmlproperty string dmg::textutilPath The path to the \c textutil binary used to convert license agreement files to rich text format. This should not normally need to be changed. \defaultvalue \c{"/usr/bin/textutil"} */ qbs-src-1.13.1/doc/reference/modules/exporter-pkgconfig-module.qdoc000066400000000000000000000157731347155106100253120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Exporter.pkgconfig \inqmlmodule QbsModules \since Qbs 1.12 \brief Provides support for generating pkg-config files. The \c Exporter.pkgconfig module contains the properties and rules to create a \l{https://www.freedesktop.org/wiki/Software/pkg-config}{pkg-config} metadata (\c{.pc}) file for a \l Product. By default, \QBS will attempt to derive some of the \c {.pc} file's contents from the product's \l Export item. This behavior can be suppressed by setting the \l autoDetect property to \c false. \section2 Relevant File Tags \target filetags-exporter-pkgconfig \table \header \li Tag \li Since \li Description \row \li \c{"Exporter.pkgconfig.pc"} \li 1.12.0 \li This tag is attached to the generated \c{.pc} file. \endtable */ /*! \qmlproperty bool Exporter.pkgconfig::autoDetect If this property is enabled, then \QBS will try to derive various \c {.pc} file entries from the contents of the product's \l Export item, including the dependencies declared therein. Values for these fields can still be explicitly provided via the respective properties, in which case they will be concatenated with the auto-detected ones. If an exported dependency is known to correspond to a pkg-config module (either by pulling in the \c{Exporter.pkgconfig} module or by appearing in the \l requiresEntry property), it will end up in the \c Requires field of the \c{.pc} file, otherwise its exported \l cpp properties will be collected for use in the \c Cflags and \c Libs fields. The \l excludedDependencies property can be used to ignore specific products altogether. \defaultvalue \c true */ /*! \qmlproperty stringList Exporter.pkgconfig::cflagsEntry The value of the \c Cflags field in the \c {.pc} file. If \l autoDetect is enabled, then this value will be appended to the flags derived from the product's \l Export item and the dependencies declared therein. \defaultvalue \c {[]} */ /*! \qmlproperty stringList Exporter.pkgconfig::conflictsEntry The value of the \c Conflicts field in the \c {.pc} file. \defaultvalue \c {[]} */ /*! \qmlproperty stringList Exporter.pkgconfig::excludedDependencies If \l autoDetect is enabled, the entries of this property will be matched against the product's exported dependencies. In case such a dependency's name is present in the array, \QBS will not traverse that dependency to collect entries for the \c Cflags, \c Libs, \c Requires and \c {Requires.private} fields. This list must not contain any values that are present in \l requiresEntry. \defaultvalue \c undefined */ /*! \qmlproperty string Exporter.pkgconfig::fileName The file name of the generated pkg-config metadata file. \defaultvalue \c {product.targetName + ".pc"} */ /*! \qmlproperty stringList Exporter.pkgconfig::libsEntry The value of the \c Libs field in the \c {.pc} file. If \l autoDetect is enabled, then this value will be appended to the flags derived from the product's \l Export item and the dependencies declared therein. \defaultvalue \c {[]} */ /*! \qmlproperty stringList Exporter.pkgconfig::libsPrivateEntry The value of the \c Libs.Private field in the \c {.pc} file. \defaultvalue \c {[]} */ /*! \qmlproperty string Exporter.pkgconfig::nameEntry The value of the \c Name field in the \c {.pc} file. \defaultvalue \c {product.name} */ /*! \qmlproperty stringList Exporter.pkgconfig::requiresEntry The value of the \c Requires field in the \c {.pc} file. If \l autoDetect is enabled, then those of the product's exported dependencies that pull in the \c {Exporter.pkgconfig} module will also end up in the \c Requires field, provided they are not listed in \l excludedDependencies. If an exported dependency matches an entry of this array, \QBS will not traverse that dependency to gather \l cpp properties for use in the \l cflagsEntry and \l libsEntry values, as pkg-config takes care of that itself. \defaultvalue \c {[]} */ /*! \qmlproperty stringList Exporter.pkgconfig::requiresPrivateEntry The value of the \c Requires.private field in the \c {.pc} file. If \l autoDetect is enabled, then those of the product's non-exported dependencies that pull in the \c {Exporter.pkgconfig} module will also end up in the \c Requires.private field, provided they are not listed in \l excludedDependencies. \defaultvalue \c {[]} */ /*! \qmlproperty var Exporter.pkgconfig::transformFunction A function with the signature \c {function(product, moduleName, propertyName, value)}. This can be useful to "fine-tune" property values if \l autoDetect is enabled, in case they need amending for the purpose of pkg-config. The \c product parameter represents the exporting product, the remaining parameters describe the module property. The modified value of the module property shall be returned. \defaultvalue \c undefined */ /*! \qmlproperty string Exporter.pkgconfig::urlEntry The value of the \c URL field in the \c {.pc} file. \defaultvalue \c undefined */ /*! \qmlproperty string Exporter.pkgconfig::versionEntry The value of the \c Version field in the \c {.pc} file. \defaultvalue \c {product.version} */ /*! \qmlproperty string Exporter.pkgconfig::customVariables Use this property to add arbitrary variable assignments into the \c .pc file. The property is a map that will produce one assignment per entry. The keys and values of the map represent the left-hand sides and right-hand sides of these assignments, respectively. The values are strings that will be written into the file verbatim. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/modules/exporter-qbs-module.qdoc000066400000000000000000000106751347155106100241240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Exporter.qbs \inqmlmodule QbsModules \since Qbs 1.12 \brief Provides support for generating \QBS modules from products. The Exporter.qbs module contains the properties and rules to create a \QBS module from the \l Export item of a \l Product. Such a module acts as your product's interface to other projects written in \QBS. For instance, suppose you are creating a library. To allow other products both within and outside of your project to make use of it, you would write something like the following: \code DynamicLibrary { name: "mylibrary" qbs.installPrefix: "/opt/mylibrary" Depends { name: "Exporter.qbs" } property string headersInstallDir: "include" // ... Group { name: "API headers" files: ["mylib.h"] qbs.install: true qbs.installDir: headersInstallDir } Group { fileTagsFilter: ["Exporter.qbs.module"] qbs.installDir: "qbs/modules/mylibrary" } Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory] prefixMapping: [{ prefix: product.sourceDirectory, replacement: FileInfo.joinPaths(qbs.installPrefix, product.headersInstallDir) }] } } \endcode To build against this library, from within your project or any other one, you simply declare a \l{Depends}{dependency}: \code Depends { name: "mylibrary" } \endcode \section2 Relevant File Tags \target filetags-exporter-qbs \table \header \li Tag \li Since \li Description \row \li \c{"Exporter.qbs.module"} \li 1.12.0 \li This tag is attached to the generated module file. \endtable */ /*! \qmlproperty stringList Exporter.qbs::artifactTypes Artifacts that match these tags will become \l{Group::filesAreTargets}{target artifacts} of the generated module, so they can get picked up by the rules of depending products. If you do not specify anything here, all installed artifacts of the product are considered. \note You can only limit the default set of artifacts by setting this property, but you cannot extend it, because only artifacts that are to be installed are considered. \defaultvalue \c undefined */ /*! \qmlproperty string Exporter.qbs::additionalContent The value of this property will be copied verbatim into the generated module. \defaultvalue \c undefined */ /*! \qmlproperty stringList Exporter.qbs::excludedDependencies Normally, all \l Depends items in the \l Export item are copied into the generated module. However, if there are any exported dependencies that only make sense for products in the same project, then you can enter their names into this array, and they will get filtered out. \note You should strive to structure your projects in such a way that you do not need to set this property. \defaultvalue \c undefined */ /*! \qmlproperty string Exporter.qbs::fileName The name of the generated module file. \defaultvalue \c {product.targetName + ".qbs"} */ qbs-src-1.13.1/doc/reference/modules/ib-module.qdoc000066400000000000000000000171111347155106100220530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype ib \inqmlmodule QbsModules \since Qbs 1.1 \brief Provides support for Apple Interface Builder and related tools and file types. The \c ib module contains properties and rules for building Interface Builder documents, storyboards, asset catalogs, and icon sets. This module is only available on Apple platforms. \section2 Relevant File Tags \target filetags-ib The file tags determine how the tagged directories and files are handled. \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"assetcatalog"} \li \c{*.xcassets} \li 1.3 \li Tagged directories are compiled into compiled asset catalog archives (\c .car files) on supported platforms, or a collection of loose resource files. The resulting files will be automatically tagged \l{filetags-bundle}{bundle.input}. If the current product is a bundle, the files will be included in the bundle's resources directory. \row \li \c{"iconset"} \li \c{*.iconset} \li 1.3 \li Tagged directories are compiled into Apple ICNS files. The resulting files will be automatically tagged \l{filetags-bundle} {bundle.input}. If the current product is a bundle, the files will be included in the bundle's resources directory. \row \li \c{"nib"} \li \c{*.nib}, \c{*.xib} \li 1.1 \li Tagged "NIB" and "XIB" files will be compiled. The output may be a flat file or a bundle (directory structure). The resulting files will be automatically tagged \l{filetags-bundle} {bundle.input}. If the current product is a bundle, the files will be included in the bundle's resources directory. \row \li \c{"png"} \li \c{*.png} \li 1.9 \li Tagged PNG files may be converted into multi-resolution TIFFs. Source files should adopt the \l{Adopt the @2x Naming Convention} {@2x naming convention} in order to be properly grouped. The resulting files will be given the \l{filetags-dmg}{tiff} file tag. \row \li \c{"storyboard"} \li \c{*.storyboard} \li 1.3 \li Tagged storyboard files will be compiled. The output may be a flat file or a bundle (directory structure). The resulting files will be automatically tagged \l{filetags-bundle} {bundle.input}. If the current product is a bundle, the files will be included in the bundle's resources directory. \endtable */ /*! \qmlproperty bool ib::warnings Whether to print warnings when compiling. Does not apply to icon sets. \defaultvalue \c{true} */ /*! \qmlproperty bool ib::errors Whether to print errors when compiling. Does not apply to icon sets. \defaultvalue \c{true} */ /*! \qmlproperty bool ib::notices Whether to print notifications when compiling. Does not apply to icon sets. \defaultvalue \c{true} */ /*! \qmlproperty stringList ib::flags Additional flags to pass to the underlying tool (\c ibtool, \c actool, \c iconutil). \nodefaultvalue \defaultvalue \c{true} */ /*! \qmlproperty string ib::ibtoolName \since Qbs 1.3 The name of the \c ibtool binary used to compile NIBs and storyboards. This property should not normally need to be changed. \defaultvalue \c{"ibtool"} */ /*! \qmlproperty string ib::ibtoolPath \since Qbs 1.3 The directory where the \c ibtool binary is located. This property should not normally need to be changed. \defaultvalue \c{ibtoolName} */ /*! \qmlproperty bool ib::flatten Compiles XIBs and storyboards into flattened (non-wrapper) files. Set to \c{false} to preserve editability of the resulting NIB and storyboard bundles in Interface Builder. This property should not normally need to be changed. \defaultvalue \c{true} */ /*! \qmlproperty string ib::module \since Qbs 1.3 Sets the name of the module that the NIB or storyboard is a part of. Requires Xcode 6 or newer. \nodefaultvalue */ /*! \qmlproperty bool ib::autoActivateCustomFonts \since Qbs 1.3 Instructs the \c ibtool compiler to add custom fonts to the application's \c Info.plist when compiling XIBs and storyboards, which will cause the fonts to activate upon application launch. Requires Xcode 6 or newer. \defaultvalue \c{true} */ /*! \qmlproperty string ib::actoolName \since Qbs 1.3 The name of the \c actool binary used to compile asset catalogs. This property should not normally need to be changed. \defaultvalue \c{"actool"} */ /*! \qmlproperty string ib::actoolPath \since Qbs 1.3 The directory where the \c actool binary is located. This property should not normally need to be changed. \defaultvalue \c{actoolName} */ /*! \qmlproperty string ib::appIconName \since Qbs 1.3 The name of the resource in the asset catalog that will be used as the application's icon. Used to generate the partial \c Info.plist which will be merged into the resulting app. If this property is \c{undefined}, no application icon will be specified. \nodefaultvalue */ /*! \qmlproperty string ib::launchImageName \since Qbs 1.3 The name of the resource in the asset catalog that will be used as the application's launch image. Used to generate the partial \c Info.plist which will be merged into the resulting app. If this property is \c{undefined}, no launch image will be specified. This property is specific to iOS. \nodefaultvalue */ /*! \qmlproperty bool ib::compressPngs \since Qbs 1.3 Whether to compress PNG image files when building asset catalogs. \defaultvalue \c{true} */ /*! \qmlproperty string ib::iconutilName \since Qbs 1.3 The name of the \c iconutil binary used to compile icon sets. This property should not normally need to be changed. \defaultvalue \c{"iconutil"} */ /*! \qmlproperty string ib::iconutilPath \since Qbs 1.3 The directory where the \c iconutil binary is located. This property should not normally need to be changed. \defaultvalue \c{iconutilName} */ qbs-src-1.13.1/doc/reference/modules/ico-module.qdoc000066400000000000000000000073751347155106100222460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype ico \inqmlmodule QbsModules \since Qbs 1.11 \brief Provides support for building ICO (.ico) and CUR (.cur) files. The \c ico module contains properties and rules for building Microsoft Windows Icon (.ico) and Microsoft Windows Cursor (.cur) files. \note This module relies on the \c icotool command-line tool from the \c icotools package, which must be installed separately and found in the \c PATH or an appropriate system binaries directory for your system (for example, \c /usr/bin or \c /usr/local/bin). \section2 Relevant File Tags \target filetags-ico \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"cur"} \li n/a \li 1.11 \li The rule that creates cursor (.cur) files attaches this tag to its output artifact. \row \li \c{"ico"} \li n/a \li 1.11 \li The rule that creates icon (.ico) files attaches this tag to its output artifact. \row \li \c{"png"} \li \c{"*.png"} \li 1.11 \li Source files with this tag indicate PNG files which are used as inputs to create icon or cursor files. \endtable */ /*! \qmlproperty int ico::cursorHotspotX The cursor hotspot x coordinate. Only relevant when building .cur files. This property must be set individually for each input PNG file. \note \c icoutils version 0.32 or greater is required to set the hotspot in cursor files with multiple images. \nodefaultvalue */ /*! \qmlproperty int ico::cursorHotspotY The cursor hotspot y coordinate. Only relevant when building .cur files. This property must be set individually for each input PNG file. \note \c icoutils version 0.32 or greater is required to set the hotspot in cursor files with multiple images. \nodefaultvalue */ /*! \qmlproperty bool ico::raw Whether to store the input file as a raw PNG, as supported in Windows Vista. Only relevant when building .ico files. This property must be set individually for each input PNG file. It is recommended to set this value only for icon sizes larger than or equal to 256x256. \defaultvalue \c{false} */ /*! \qmlproperty string ico::icotoolFilePath The full path of the \c icotool binary. This property should not normally need to be changed if \QBS was able to automatically detect it. \defaultvalue Determined automatically. */ qbs-src-1.13.1/doc/reference/modules/innosetup-module.qdoc000066400000000000000000000115011347155106100235020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype innosetup \inqmlmodule QbsModules \since Qbs 1.7 \brief Provides Inno Setup support. The \c innosetup module contains properties and rules for building EXE setup packages with \l{Inno Setup}. Inno Setup 5 and above are supported. \note A typical Inno Setup Script includes an \c OutputBaseFilename command to set the filename of the generated installer executable. However, \QBS overrides any \c OutputBaseFilename commands found in the script by passing the \c /F option to the ISCC compiler, and therefore, you must use the \l{Product::targetName}{Product.targetName} property to set the filename. \QBS also overrides any \c Output commands by passing the \c /O option to the ISCC compiler. \section2 Relevant File Tags \target filetags-innosetup \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"innosetup.iss"} \li \c{"*.iss"} \li 1.7 \li Source files with this tag identify Inno Setup Script files, which serve as inputs to a rule invoking the Inno Setup Script Compiler. \row \li \c{"innosetup.exe"} \li n/a \li 1.7 \li The rule that creates Inno Setup executable files attaches this tag (as well as the \l{filetags-cpp}{"application"} tag) to its output artifact. \endtable */ /*! \qmlproperty stringList innosetup::defines A list of preprocessor macros that get passed to the compiler. To set macro values, use the following syntax: \badcode innosetup.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"'] \endcode \nodefaultvalue */ /*! \qmlproperty pathList innosetup::includePaths A list of include paths. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue */ /*! \qmlproperty bool innosetup::verboseOutput Whether to display verbose output from the Inno Setup compiler. \defaultvalue \c{false} */ /*! \qmlproperty stringList innosetup::compilerFlags A list of additional flags for the Inno Setup compiler. \nodefaultvalue */ /*! \qmlproperty string innosetup::version The Inno Setup version. Consists of three numbers separated by dots, for instance \c {"5.5.9"}. \nodefaultvalue */ /*! \qmlproperty int innosetup::versionMajor The Inno Setup major version. \defaultvalue \c{versionParts[0]} */ /*! \qmlproperty int innosetup::versionMinor The Inno Setup minor version. \defaultvalue \c{versionParts[1]} */ /*! \qmlproperty list innosetup::versionParts The Inno Setup version as a list. For instance, Inno Setup version 5.5.9 would correspond to a value of \c[5, 5, 9]. \defaultvalue \c [] */ /*! \qmlproperty int innosetup::versionPatch The Inno Setup patch level. \defaultvalue \c{versionParts[2]} */ /*! \qmlproperty path innosetup::toolchainInstallPath The Inno Setup installation directory. Determined by searching the registry for the latest version. This property should not normally need to be changed. \defaultvalue Determined automatically. */ /*! \qmlproperty string innosetup::compilerName The name of the compiler binary. This property should not normally need to be changed. \defaultvalue \c{"ISCC.exe"} */ /*! \qmlproperty string innosetup::compilerPath The full path of the compiler binary. This property should not normally need to be changed. \defaultvalue \c{compilerName} */ qbs-src-1.13.1/doc/reference/modules/java-module.qdoc000066400000000000000000000137031347155106100224050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype java \inqmlmodule QbsModules \since Qbs 1.4 \brief Provides Java support. The \c java module contains the properties and rules for building Java projects. \section2 Relevant File Tags \target filetags-java \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"java.class"} \li - \li 1.4 \li This tag is attached to the output artifacts of the rule that runs the \c javac tool. \row \li \c{"java.jar"} \li - \li 1.4 \li This tag is attached to the output artifacts of the rule that runs the \c jar tool. \row \li \c{"java.java"} \li \c{*.java} \li 1.4 \li Source files with this tag serve as inputs to the rule running the \c javac tool. \row \li \c{"java.manifest"} \li \c{*.mf} \li 1.8 \li The contents of files with this tag will be aggregated with the values in \l{java::}{manifest}. \endtable */ /*! \qmlproperty stringList java::additionalClassPaths The locations beside this product's class output path to consider when compiling. \nodefaultvalue */ /*! \qmlproperty stringList java::additionalCompilerFlags A list of compiler flags not covered by any of the properties in this module. \nodefaultvalue */ /*! \qmlproperty stringList java::additionalJarFlags A list of archiver flags not covered by any of the properties in this module. \nodefaultvalue */ /*! \qmlproperty stringList java::bootClassPaths A list of non-standard bootstrap class files. \nodefaultvalue */ /*! \qmlproperty string java::compilerFilePath The command to invoke when compiling Java sources. \defaultvalue \l compilerName, prefixed by \l jdkPath if it is defined. */ /*! \qmlproperty string java::compilerName The file name of the Java compiler. \defaultvalue \c{"javac"} */ /*! \qmlproperty bool java::enableWarnings Whether warnings are emitted when compiling Java sources. \defaultvalue \c true */ /*! \qmlproperty string java::interpreterFilePath The command to invoke when executing Java code. \defaultvalue \l interpreterName, prefixed by \l jdkPath if it is defined. */ /*! \qmlproperty string java::interpreterName The file name of the Java interpreter. \defaultvalue \c{"java"} */ /*! \qmlproperty string java::jarFilePath The command to run when creating or extracting \c jar files. \defaultvalue \l jarName, prefixed by \l jdkPath if it is defined. */ /*! \qmlproperty string java::jarName The file name of the \c jar tool. \defaultvalue \c{"jar"} */ /*! \qmlproperty pathList java::jdkIncludePaths \since Qbs 1.4.1 A list of include paths for native header files. Applications using JNI to interface with native code should add these paths to \l{cpp::includePaths}{cpp.includePaths}. \defaultvalue Determined automatically. */ /*! \qmlproperty string java::jdkPath The base path of the Java Development Kit (JDK). This is equivalent to the \c JAVA_HOME environment variable, and by default will be determined automatically from one of the following: \list \li \c JAVA_HOME environment variable (all platforms) \li Registry (Windows) \li \c java_home tool (macOS) \li Known JDK paths (other Unix platforms) \endlist \defaultvalue Determined automatically. */ /*! \qmlproperty string java::languageVersion The Java language version to interpret source code as. If left undefined, the compiler will use its default. \nodefaultvalue */ /*! \qmlproperty string java::runtimeVersion The version of the Java runtime to generate compatible bytecode for. If left undefined, the compiler will use its default. \nodefaultvalue */ /*! \qmlproperty var java::manifest \since Qbs 1.4.2 The properties to add to the manifest file when building a JAR. The contents of this property will be aggregated with the values from any files tagged \l{filetags-java}{"java.manifest"}. If this property and a manifest file contain the same key, this property will take precedence. If left undefined, this property will not be taken into account. \nodefaultvalue */ /*! \qmlproperty stringList java::manifestClassPath A list of entries to add to the manifest's Class-Path when building a JAR. \nodefaultvalue */ /*! \qmlproperty bool java::warningsAsErrors If this property is \c true, the compiler will abort where it would normally emit a warning. \defaultvalue \c false */ qbs-src-1.13.1/doc/reference/modules/lexyacc-module.qdoc000066400000000000000000000105301347155106100231070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype lex_yacc \inqmlmodule QbsModules \since Qbs 1.6 \brief Provides support for the \c lex and \c yacc tools. The \c lex_yacc module allows you to create scanners and parsers via the POSIX tools \c lex and \c yacc, respectively. These tools are closely related and share a number of properties, which is why they are represented by a single module. \section2 Relevant File Tags \target filetags-lexyacc \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"lex.input"} \li \c{*.l} \li 1.6 \li Source files with this tag serve as inputs to the \c lex tool. \row \li \c{"yacc.input"} \li \c{*.y} \li 1.6 \li Source files with this tag serve as inputs to the \c yacc tool. \endtable */ /*! \qmlproperty bool lex_yacc::enableCompilerWarnings \since Qbs 1.8 Whether compiler warnings are displayed. Because \c lex and \c yacc are known to produce files that will trigger compiler warnings, such warnings are suppressed by default. Set this property to \c true if you want to see them. \defaultvalue \c{false} */ /*! \qmlproperty string lex_yacc::lexBinary The file path of the \c lex tool. \defaultvalue \c{"lex"} */ /*! \qmlproperty stringList lex_yacc::lexFlags Additional command-line options for the \c lex tool. \defaultvalue \c [] */ /*! \qmlproperty string lex_yacc::lexOutputFilePath The output file for the \c lex tool. This corresponds to \c{%option outfile} in the .l file. If \c{%option outfile} is set in the .l file then this property is ignored. \defaultvalue \c undefined \since 1.12 */ /*! \qmlproperty string lex_yacc::outputTag The file tag for the generated scanner and parser sources. Use \l{filetags-cpp}{"cpp"} if you want to use a C++ compiler on them. \defaultvalue \l{filetags-cpp}{"c"} */ /*! \qmlproperty bool lex_yacc::uniqueSymbolPrefix If this property is \c true, the prefix \c yy normally used for the generated lexer and parser functions is replaced by the base name of the file provided as input to \c lex and \c yacc, respectively. Enable this property if you want to use more than one lexer or parser in a single product. \note Enabling this property requires that the associated lexer and scanner source files have the same base name. It also assumes a variant of \c lex that supports the non-POSIX option \c{-P}, such as \c flex. \defaultvalue \c{false} */ /*! \qmlproperty string lex_yacc::yaccBinary The file path of the \c yacc tool. \defaultvalue \c{"yacc"} */ /*! \qmlproperty stringList lex_yacc::yaccFlags Additional command-line options for the \c yacc tool. \defaultvalue \c [] */ /*! \qmlproperty string lex_yacc::yaccOutputFilePath Main output file for the \c yacc tool. This corresponds to \c{%output} in the .y file. If \c{%output} is set in the .y file then this property is ignored. \defaultvalue \c undefined \since 1.12 */ qbs-src-1.13.1/doc/reference/modules/nodejs-module.qdoc000066400000000000000000000032761347155106100227520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype nodejs \inqmlmodule QbsModules \since Qbs 1.3 \brief Provides Node.js support. The \c nodejs module contains support for running \l{Node.js} applications from \QBS. */ /*! \qmlproperty path Node.js::applicationFile The input JavaScript file whose corresponding output will be executed when running the Node.js application. If this property is \c{undefined}, the product will not be runnable. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/modules/nsis-module.qdoc000066400000000000000000000132051347155106100224350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype nsis \inqmlmodule QbsModules \since Qbs 1.2 \brief Provides Nullsoft Scriptable Install System support. The \c nsis module contains properties and rules for building EXE installers for Windows using the Nullsoft Scriptable Install System (NSIS). This module is available on all platforms. \note A typical NSIS script includes an \c OutFile command to set the filename of the generated installer executable. However, \QBS overrides any \c OutFile commands found in the script, and therefore, you must use the \l{Product::targetName}{product.targetName} property to set the filename. \section2 Relevant File Tags \target filetags-nsis \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"nsh"} \li \c{*.nsh} \li 1.2 \li This tag is attached to NSIS header files. \row \li \c{"nsi"} \li \c{*.nsi} \li 1.2 \li This tag is attached to NSIS script files. \row \li \c{"nsissetup"} \li - \li 1.2 \li The rule that creates the NSIS setup executable attaches this tag to its output artifact. \endtable */ /*! \qmlproperty stringList nsis::defines A list of preprocessor macros that get passed to the compiler. To set macro values, use the following syntax: \badcode cpp.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"'] \endcode \nodefaultvalue */ /*! \qmlproperty bool nsis::disableConfig Whether to exclude \c nsisconf.nsh. Generally, you do not need to set this property. \defaultvalue \c{false} */ /*! \qmlproperty bool nsis::enableQbsDefines Whether to define preprocessor macros corresponding to the values from the \l{Project}{project} and \l{Product}{product} objects. When building a 64-bit package, the preprocessor variable \c{Win64} will also be defined. \defaultvalue \c{true} */ /*! \qmlproperty string nsis::warningLevel The severity of the warnings to emit. The higher the level, the more warnings will be shown. The levels \c{none}, \c{errors}, \c{warnings}, \c{info}, and \c{all} correspond to the NSIS verbosity levels 0 through 4, inclusive. \c{normal} corresponds to the default level. \defaultvalue \c{"normal"} */ /*! \qmlproperty stringList nsis::compilerFlags A list of additional flags for the NSIS compiler. \nodefaultvalue */ /*! \qmlproperty string nsis::compressor The compression algorithm used to compress files and data in the installer. Setting this property overrides any \c SetCompressor command in the NSI file being compiled. Possible values include: \c{"default"}, \c{"zlib"}, \c{"zlib-solid"}, \c{"bzip2"}, \c{"bzip2-solid"}, \c{"lzma"}, \c{"lzma-solid"}. \defaultvalue \c{"default"} */ /*! \qmlproperty string nsis::version The NSIS version. Consists of four numbers separated by dots. For example, \c "2.46.0.0". \nodefaultvalue */ /*! \qmlproperty int nsis::versionMajor The NSIS major version. \defaultvalue \c{versionParts[0]} */ /*! \qmlproperty int nsis::versionMinor The NSIS minor version. \defaultvalue \c{versionParts[1]} */ /*! \qmlproperty list nsis::versionParts The NSIS version as a list. For example, the NSIS version 2.46.0.0 would correspond to a value of \c[2, 46, 0, 0]. \defaultvalue \c [] */ /*! \qmlproperty int nsis::versionPatch The NSIS patch level. \defaultvalue \c{versionParts[2]} */ /*! \qmlproperty int nsis::versionBuild The fourth NSIS version number component. \defaultvalue \c{versionParts[3]} */ /*! \qmlproperty path nsis::toolchainInstallPath The NSIS installation directory. Determined by searching from the known registry keys and known installation paths until a match is found. This property should not normally need to be changed. \defaultvalue Determined automatically. */ /*! \qmlproperty string nsis::compilerName The name of the compiler binary. This property should not normally need to be changed. \defaultvalue \c{"makensis"} */ /*! \qmlproperty string nsis::compilerPath The directory where the compiler binary is located. This property should not normally need to be changed. \defaultvalue \l{nsis::}{compilerName} */ qbs-src-1.13.1/doc/reference/modules/pkgconfig-module.qdoc000066400000000000000000000045351347155106100234360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype pkgconfig \inqmlmodule QbsModules \since 1.13 \brief Allows to configure the pkg-config tool. The \c pkgconfig module is used to fine-tune the behavior of the \c {pkg-config} tool, which is \l{How do I build against libraries that provide pkg-config files?}{potentially employed} when looking up dependencies. */ /*! \qmlproperty string pkgconfig::executableFilePath The path to the \c {pkg-config} executable. \defaultvalue auto-detected */ /*! \qmlproperty stringList pkgconfig::libDirs Set this if you need to overwrite the default search directories. The values given here will be forwarded to the tool via the \c PKG_CONFIG_LIBDIR environment variable. \note You do not need to set this for cross-compilation in order to point \c {pkg-config} to the sysroot. \QBS does that for you. \nodefaultvalue */ /*! \qmlproperty bool pkgconfig::staticMode If this property is \c true, then calls to \c{pkg-config} will include the \c{--static} option. Set this if your product is to be linked statically. \defaultvalue \c false */ qbs-src-1.13.1/doc/reference/modules/protobufcpp-module.qdoc000066400000000000000000000055531347155106100240330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype protobuf.cpp \inqmlmodule QbsModules \since Qbs 1.13 \brief Provides support for protocol buffers for the C++ language. The \c protobuf.cpp module provides support for generating C++ headers and sources from proto definition files using the \l protoc tool. \section2 Relevant File Tags \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"protobuf.input"} \li \c{*.proto} \li 1.13.0 \li Source files with this tag are considered inputs to the \c protoc compiler. \endtable */ /*! \qmlproperty string protobuf.cpp::protocBinary The command to invoke when compiling proto definition files. \defaultvalue \c auto-detected */ /*! \qmlproperty pathList protobuf.cpp::importPaths The list of imports that are passed to the \c protoc tool via the \c --proto_path option. These imports should contain the proto files. They are used to determine the relative structure of the generated files. \note The paths are passed to \c protoc in the same order as specified in this property and \c protoc output may differ depending on that order. \defaultvalue \c [] */ /*! \qmlproperty string protobuf.cpp::includePath The path where protobuf C++ headers are located. Set this property to override the default location. \defaultvalue \c auto-detected */ /*! \qmlproperty string protobuf.cpp::libraryPath The path where the protobuf C++ library is located. Set this property to override the default location. \defaultvalue \c auto-detected */ qbs-src-1.13.1/doc/reference/modules/protobufobjc-module.qdoc000066400000000000000000000061651347155106100241660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype protobuf.objc \inqmlmodule QbsModules \since Qbs 1.13 \brief Provides support for protocol buffers for the Objective-C language. The \c protobuf.objc module provides support for generating Objective-C headers and sources from proto definition files using the \l protoc tool. \section2 Relevant File Tags \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"protobuf.input"} \li \c{*.proto} \li 1.13.0 \li Source files with this tag are considered inputs to the \c protoc compiler. \endtable */ /*! \qmlproperty string protobuf.objc::protocBinary The command to invoke when compiling proto definition files. \defaultvalue \c auto-detected */ /*! \qmlproperty pathList protobuf.objc::importPaths The list of imports that are passed to the \c protoc tool via the \c --proto_path option. These imports should contain the proto files. They are used to determine the relative structure of the generated files. \note The paths are passed to \c protoc in the same order as specified in this property and \c protoc output may differ depending on that order. \defaultvalue \c [] */ /*! \qmlproperty string protobuf.objc::includePath The path where protobuf Objective-C headers are located. Set this property to override the default location. \note If frameworkPath is specified, this property has no effect. \defaultvalue \c auto-detected */ /*! \qmlproperty string protobuf.objc::libraryPath \note If frameworkPath is specified, this property has no effect. \defaultvalue \c auto-detected */ /*! \qmlproperty string protobuf.objc::frameworkPath The path where \c Protobuf.framework is located. Set this property to override the default location. \defaultvalue \c auto-detected */ qbs-src-1.13.1/doc/reference/modules/qbs-module.qdoc000066400000000000000000000372661347155106100222630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage list-of-modules.html \qmltype qbs \inqmlmodule QbsModules \since Qbs 1.0 \brief Comprises general properties. The \c qbs module is implicitly loaded in every product. It contains properties of the current build environment, independent of the used programming languages and toolchains. \section2 Installation Properties Typically, you use \l{Group} items to specify the target directories for installing files. To install a group of files, set the \l{qbs::install} {qbs.install} property of the Group to \c true. The value of \l{qbs::installDir}{qbs.installDir} specifies the path to the directory where the files will be installed. You can specify a base directory for all installation directories as the value of \l{qbs::installPrefix} {qbs.installPrefix}. For example, the following properties specify where a set of QML files and an application executable are installed on Windows and Linux: \badcode Application { name: "myapp" Group { name: "Runtime resources" files: "*.qml" qbs.install: true qbs.installDir: condition: qbs.targetOS.contains("unix") ? "share/myapp" : "resources" } Group { name: "The App itself" fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } qbs.installPrefix: condition: qbs.targetOS.contains("unix") ? "usr/local" : "MyApp" } \endcode On Windows, the QML files will ultimately get installed in \c{MyApp\resources} and the application executable in \c MyApp\bin, for instance under \c{C:\Program Files}. On Linux, the QML files will be installed in \c /usr/local/share/myapp and the executable in \c /usr/local/bin. By default, \l{qbs::installRoot}{qbs.installRoot} creates the \c install-root directory in the build directory for packaging the binaries before installation. It is a temporary directory that is usually not available when the application is run, and it should therefore not be set in the project files. You can override the default value from the command line, as described in \l{Installing Files}. \section2 Multiplexing Properties The following properties are specific to \l{Multiplexing} {product multiplexing}: \list \li \l{qbs::}{architectures} \li \l{qbs::}{buildVariants} \li \l{qbs::}{profiles} \endlist */ /*! \qmlproperty string qbs::configurationName \since Qbs 1.6 \readonly The name of the current build configuration. The build configuration is set via the command line parameter \c config. For more information, see \l{build}{build}. \defaultvalue \c{"default"} */ /*! \qmlproperty string qbs::buildVariant The name of the build variant for the current build. Possible values are \c{"debug"} and \c{"release"}. A debug build usually contains additional debug symbols that are needed for debugging the application but that can be left out from the release version. Debug builds are used for testing and release builds for creating the final installation file. \defaultvalue \c{"release"} if \l{qbs::configurationName}{qbs.configurationName} is \c{"release"}. Otherwise \c{"debug"} */ /*! \qmlproperty bool qbs::debugInformation Whether to generate debug information. \defaultvalue \c{true} for debug builds, \c{false} otherwise. */ /*! \qmlproperty bool qbs::enableDebugCode Whether to enable debug functionality in the product. Not to be confused with generation of debug symbols or the code optimization level. The property changes the following things when enabled: \list \li Passes a flag to the Windows linker to link against a debug Windows CRT (common runtime) library (for example /MTd instead of /MT) \endlist The property changes the following things when disabled: \list \li Passes the \c{NDEBUG} define to the compiler \endlist Typically, this property is enabled for debug builds and disabled for release builds. \defaultvalue \c{true} for debug builds, \c{false} otherwise. */ /*! \qmlproperty string qbs::optimization The general type of optimization that should be performed by all toolchains. Allowed values are: \list \li \c{"fast"} \li \c{"none"} \li \c{"small"} \endlist \defaultvalue \c{"none"} for debug builds, \c{"fast"} for release builds. */ /*! \qmlproperty stringList qbs::targetPlatform \since 1.11 The OS you want to build the project for. This property is typically set in a profile or for a particular product where the target OS is always known (such as an Apple Watch app written in native code). You should generally treat this property as \e{write-only} and avoid using it to test for the current target OS. Instead, use the \l{qbs::}{targetOS} property for conditionals. For example, instead of: \code qbs.targetPlatform === "macos" || qbs.targetPlatform === "ios" || qbs.targetPlatform === "tvos" || qbs.targetPlatform === "watchos" \endcode use \code qbs.targetOS.contains("darwin") \endcode However, in some cases using \c targetPlatform would be acceptable, such as when the resulting condition would be simpler while still being correct: \code qbs.targetPlatform === "linux" \endcode versus \code qbs.targetOS.contains("linux") && !qbs.targetOS.contains("android") \endcode The possible values include one or more of the following: \list \li \c{"aix"} \li \c{"android"} \li \c{"freebsd"} \li \c{"haiku"} \li \c{"hpux"} \li \c{"hurd"} \li \c{"integrity"} \li \c{"ios"} \li \c{"ios-simulator"} \li \c{"linux"} \li \c{"lynx"} \li \c{"macos"} \li \c{"netbsd"} \li \c{"openbsd"} \li \c{"qnx"} \li \c{"solaris"} \li \c{"tvos"} \li \c{"tvos-simulator"} \li \c{"vxworks"} \li \c{"watchos"} \li \c{"watchos-simulator"} \li \c{"windows"} \endlist \nodefaultvalue */ /*! \qmlproperty string qbs::architecture The target platform's processor architecture. \c{undefined} indicates that the target platform is architecture-independent (for example the CLR or JVM). This property is typically set in a profile. Commonly used values are: \c{"x86"}, \c{"x86_64"}, and \c{"arm"}. \nodefaultvalue */ /*! \qmlproperty string qbs::toolchainType \since Qbs 1.11 The toolchain that is going to be used for this build. You should generally treat this property as \e{write-only} and avoid using it to test for the current toolchain. Instead, use the \l{qbs::}{toolchain} property for conditionals. For example, instead of: \code (qbs.toolchainType === "xcode" || qbs.toolchainType === "clang" || qbs.toolchainType === "gcc") \endcode use: \code qbs.toolchain.contains("gcc") \endcode However, there are some cases when using \c toolchainType would be acceptable, such as when the resulting condition would be simpler while still being correct: \code (qbs.toolchainType === "gcc") \endcode versus: \code (qbs.toolchain.contains("gcc") && !qbs.toolchain.contains("clang")) \endcode Typical values include: \c{"gcc"}, \c{"clang"}, \c{"mingw"}, \c{"msvc"}, and \c{"xcode"}. \defaultvalue Determined automatically. */ /*! \qmlproperty string qbs::sysroot The \c sysroot of the target platform. This property is typically set in a profile for cross-compiling. \nodefaultvalue */ /*! \qmlproperty string qbs::pathListSeparator The platform-specific separator for a path list that is used in environment variables or other contexts. \defaultvalue \c{";"} on Windows, \c{":"} on Unix. */ /*! \qmlproperty string qbs::nullDevice \since Qbs 1.4.2 The platform-specific file path corresponding to the null device. \defaultvalue \c{"NUL"} on Windows, \c{"/dev/null"} on Unix. */ /*! \qmlproperty path qbs::shellPath \since Qbs 1.5 The platform-specific file path corresponding to the command line interpreter. On Windows, this is the path to \c{cmd.exe}, which is held in the \c{COMSPEC} environment variable (typically, \c{C:/Windows/System32/cmd.exe}), On Unix-like platforms, this is \c{/bin/sh}. \defaultvalue \c{"%COMSPEC%"} on Windows, \c{"/bin/sh"} on Unix */ /*! \qmlproperty stringList qbs::hostOS This property is set by \QBS internally and specifies the OS \QBS is running on. The possible values for this property are the values of \l{qbs::}{targetOS}, even though some of them may not be supported. \nodefaultvalue */ /*! \qmlproperty string qbs::hostOSVersion \readonly \since Qbs 1.2 The host operating system version. Currently, only defined for Windows and Apple platforms. Consists of two or three numbers separated by dots. For example, \c "10.9" or \c "6.3.9600". \nodefaultvalue */ /*! \qmlproperty string qbs::hostOSBuildVersion \readonly \since Qbs 1.2 The host operating system's build version. Currently, only defined for Windows and Apple platforms. On Windows, this is the 4 or 5 digit Windows build number and is equivalent to \l{qbs::}{versionPatch}. On Apple platforms, this is a standard build number in the Apple versioning scheme. For example, \c "13C64". \nodefaultvalue */ /*! \qmlproperty int qbs::hostOSVersionMajor \readonly \since Qbs 1.2 The host operating system major version. \defaultvalue \c{hostOSVersionParts[0]} */ /*! \qmlproperty int qbs::hostOSVersionMinor \since Qbs 1.2 The host operating system minor version. \defaultvalue \c{hostOSVersionParts[1]} */ /*! \qmlproperty list qbs::hostOSVersionParts \readonly \since Qbs 1.2 The host operating system version as a list. For example, Windows 8.1 (version 6.3.9600) would correspond to a value of \c[6, 3, 9600]. \defaultvalue \c [] */ /*! \qmlproperty int qbs::hostOSVersionPatch \readonly \since Qbs 1.2 The host operating system patch level. \defaultvalue \c{hostOSVersionParts[2]} */ /*! \qmlproperty string qbs::hostPlatform \since Qbs 1.11 Do not use this property. \defaultvalue Determined automatically. */ /*! \qmlproperty stringList qbs::targetOS Specifies the OS you want to build the project for. Use this property to test for a particular OS or OS family in conditionals. Do not use \l{qbs::}{targetPlatform} for this purpose. Possible values include one or more of \c{"bsd"}, \c{"darwin"}, and \c{"unix"}, in addition to the possible values of \l{qbs::}{targetPlatform}. \nodefaultvalue */ /*! \qmlproperty stringList qbs::toolchain The attributes of the toolchain that is going to be used for this build. Typical values include \c{"llvm"}, in addition to the possible values of \l{qbs::}{toolchainType}. \nodefaultvalue */ /*! \qmlproperty string qbs::version \readonly \since Qbs 1.4.1 The version number of \QBS as a string. For example, \c "1.4.1". */ /*! \qmlproperty int qbs::versionMajor \readonly \since Qbs 1.4.1 The major version number of \QBS. */ /*! \qmlproperty int qbs::versionMinor \readonly \since Qbs 1.4.1 The minor version number of \QBS. */ /*! \qmlproperty int qbs::versionPatch \readonly \since Qbs 1.4.1 The patch version number of \QBS. */ /*! \qmlproperty bool qbs::install Whether to install a certain set of files. This property is typically set in a \l{Group} item to mark a number of files as installable. \note Artifacts for which this property is enabled automatically receive the file tag \c "installable". This is useful for writing packaging-related rules. \defaultvalue \c{false} */ /*! \qmlproperty string qbs::installSourceBase \since Qbs 1.4 The base directory of the local files that are going to be installed. The source base directory is omitted from the target directory path specified in \l{qbs::}{installDir}. \defaultvalue The directory of the current file to be installed, relative to the product's source directory. */ /*! \qmlproperty string qbs::installDir The installation directory for the files of a \l{Product}{product} or a \l{Group}. The value of this property is a path that is relative to \l{qbs::} {installPrefix}. \nodefaultvalue */ /*! \qmlproperty string qbs::installPrefix \since Qbs 1.1 The global installation prefix. It is implicitly prepended to all values of \l{qbs::}{installDir}. The value of this property itself is relative to the \l{qbs::}{installRoot} in the context of installation. \defaultvalue \c [] */ /*! \qmlproperty string qbs::installRoot \since Qbs 1.4 The global installation root. It is implicitly prepended to all values of \l{qbs::}{installPrefix} in the context of installation. \note This property is fundamentally different from \l{qbs::}{installDir} and \l{qbs::}{installPrefix} in that it must not be visible to the code being built. In fact, the install root is often just a temporary location used to package the binaries, which should therefore not assume they will be in that location at run-time. For the same reason, this property is usually not set from within project files. \defaultvalue \c{/install-root} */ /*! \qmlproperty stringList qbs::architectures \since Qbs 1.9 The architectures the product will be built for. \defaultvalue \c{["armv5te"]} on Android, same as Xcode on Apple platforms, otherwise equivalent to \l{qbs::architecture}{[qbs.architecture]}. */ /*! \qmlproperty stringList qbs::buildVariants \since Qbs 1.9 The build variants the product will be built for. \defaultvalue Equivalent to \l{qbs::buildVariant}{[qbs.buildVariant]}. */ /*! \qmlproperty stringList qbs::profiles \since Qbs 1.9 The profiles for which the product should be built. For each profile listed here, one instance of the product will be built according to the properties set in the respective profile. \defaultvalue \l{Project::profile}{[project.profile]} */ qbs-src-1.13.1/doc/reference/modules/qnx-module.qdoc000066400000000000000000000051561347155106100222750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype qnx \inqmlmodule QbsModules \since Qbs 1.8 \brief Provides support for building QNX applications using the QNX SDK. The \c qnx module contains properties and rules for QNX development. It has been tested with the QNX 6.5, 6.6, and 7.0 SDKs. */ /*! \qmlproperty string qnx::sdkDir The SDK base directory. \defaultvalue Determined automatically if the QNX SDK is installed at one of the standard locations, such as \c ~/qnx700, \c /opt/qnx700, or \c C:\\qnx700. */ /*! \qmlproperty string qnx::configurationDir The QNX configuration directory. Equivalent to the \c{QNX_CONFIGURATION} environment variable. \defaultvalue \c{~/.qnx} */ /*! \qmlproperty string qnx::hostDir The QNX host directory. Equivalent to the \c{QNX_HOST} environment variable. You should not normally need to set this property as it will be set to an appropriate value based on your host operating system and the installed QNX SDK in \l{qnx::}{sdkDir}. \defaultvalue Determined automatically. */ /*! \qmlproperty string qnx::targetDir The QNX target directory. Equivalent to the \c{QNX_TARGET} environment variable. You should not normally need to set this property as it will be set to an appropriate value based on the installed QNX SDK in \l{qnx::}{sdkDir}. \defaultvalue Determined automatically. */ qbs-src-1.13.1/doc/reference/modules/qt-android_support-module.qdoc000066400000000000000000000056131347155106100253230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Qt.android_support \inqmlmodule QbsModules \brief Provides Qt support for the Android platform. The \c Qt.android_support module provides the glue for \QBS' Qt and Android support. It is automatically pulled in by \c Qt.core, so you do not need to add an explicit dependency to it in your product, unless you want to set one of its properties. */ /*! \qmlproperty bool Qt.android_support::useMinistro Whether or not to use the Ministro service. If this property is enabled, then the Qt libraries required by your application as well as some other resources will not be packaged into the APK file, but are expected to be present on the device at run time. \defaultvalue \c false */ /*! \qmlproperty string Qt.android_support::qmlRootDir The root directory of the product's QML files. This information is passed to the \c androiddeployqt tool, which will use it to decide which resources to include in the APK file. \defaultvalue \c product.sourceDirectory */ /*! \qmlproperty stringList Qt.android_support::deploymentDependencies Use this property to completely override the Qt deployment dependencies of your app. Corresponds to qmake's ANDROID_DEPLOYMENT_DEPENDENCIES. \defaultvalue \c undefined */ /*! \qmlproperty stringList Qt.android_support::extraPlugins Additional non-asset files to be packaged. Corresponds to qmake's ANDROID_EXTRA_PLUGINS. \defaultvalue \c undefined */ /*! \qmlproperty bool Qt.android_support::verboseAndroidDeployQt Enable this property if you want verbose output from the \c androiddeployqt tool. \defaultvalue \c false */ qbs-src-1.13.1/doc/reference/modules/qt-core-module.qdoc000066400000000000000000000262511347155106100230400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Qt.core \inqmlmodule QbsModules \brief Provides Qt Core support. All other Qt modules have a dependency on the Qt.core module, and therefore you do not need to list it in your dependencies if you depend on at least one other \l{Qt Modules}{Qt module}. Some of the Qt.core properties only need to be defined if the respective installation of Qt was built in some unusual way, for instance by setting non-default \c configure flags. \section2 Relevant File Tags \target filetags-qtcore \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"qch"} \li n/a \li 1.1 \li This tag is attached to the output artifacts of the rule that runs the \c qhelpgenerator tool. \row \li \c{"qdoc"} \li \c{*.qdoc} \li 1.1 \li Source files with this tag trigger a re-execution of the rule running the \c qdoc tool when their timestamp changes. \row \li \c{"qdocconf"} \li \c{*.qdocconf} \li 1.1 \li Source files with this tag trigger a re-execution of the rule running the \c qdoc tool when their timestamp changes. \row \li \c{"qdocconf-main"} \li - \li 1.1 \li Source files with this tag serve as inputs to the rule running the \c qdoc tool. \row \li \c{"qdoc-output"} \li n/a \li 1.5 \li Use this tag to match all \c qdoc outputs, for instance in a \l{Group} using the \l{Group::fileTagsFilter}{group.fileTagsFilter} property. \row \li \c{"qhp"} \li \c{*.qhp} \li 1.1 \li Files with this tag serve as inputs to the rule running the \c qhelpgenerator tool. Such files are created by \c qdoc, but can also appear as source files. \row \li \c{"qm"} \li n/a \li 1.1 \li This tag is attached to the output artifacts of the rule that runs the \c lrelease tool. \row \li \c{"qrc"} \li \c{*.qrc} \li 1.0 \li Files with this tag serve as inputs to the rule running the \c rcc tool. \row \li \c{"qt_plugin_metadata"} \li - \li 1.0 \li Source files with this tag trigger a re-execution of the rule running the \c moc tool when their timestamp changes. \row \li \c{"qt.core.resource_data"} \li - \li 1.7 \li Source files with this tag serve as inputs to the rule creating \c qrc files. \row \li \c{"ts"} \li \c{*.ts} \li 1.0 \li Files with this tag serve as inputs to the rule running the \c lrelease tool. \row \li \c{"mocable"} \li - \li 1.13 \li Use this tag to force \QBS to run \c moc on the respective files, even though they do not contain \c Q_OBJECT or a related macro. \row \li \c{"unmocable"} \li - \li 1.2 \li Use this tag for files that \QBS should not run \c moc on, even though they contain \c Q_OBJECT or a related macro. \endtable */ /*! \qmlproperty stringList Qt.core::availableBuildVariants The build variants that this Qt installation offers. \defaultvalue Set by \l{setup-qt}. */ /*! \qmlproperty path Qt.core::binPath The path in which Qt tools such as \c qmake, \c moc, and so on are located. \nodefaultvalue */ /*! \qmlproperty bool Qt.core::combineMocOutput Whether the C++ sources created by \c moc are combined into a single C++ file per product. For projects where many header files are to be handled by \c moc, this can speed up compilation considerably. However, side effects may occur as a result of merging translation units. \defaultvalue \l{cpp::combineCxxSources}{cpp.combineCxxSources} */ /*! \qmlproperty bool Qt.core::enableBigResources Whether the Qt resource compiler is run in a two-pass fashion that supports the creation of big resources. \defaultvalue \c{false} */ /*! \qmlproperty stringList Qt.core::config Corresponds to the default value of qmake's \c CONFIG variable. \defaultvalue \c [] */ /*! \qmlproperty path Qt.core::docPath The path in which the Qt documentation is located. \nodefaultvalue */ /*! \qmlproperty bool Qt.core::enableKeywords Set this property to \c false if you do not want Qt to define the symbols \c {signals}, \c {slots}, and \c {emit}. This can be necessary if your project interacts with code that also defines such symbols. \defaultvalue \c true */ /*! \qmlproperty bool Qt.core::frameworkBuild Whether Qt was built as a framework. This is only relevant for Darwin systems. \nodefaultvalue */ /*! \qmlproperty path Qt.core::incPath The base path of the Qt headers. \nodefaultvalue */ /*! \qmlproperty string Qt.core::libInfix The library infix can be set at Qt build time to change the name of Qt's libraries. For example, if the infix is \c "Test", on Unix systems, the Qt Core library will be in a file called \c{libQt5CoreTest.so} instead of the default \c{libQt5Core.so}. \defaultvalue \c [] */ /*! \qmlproperty path Qt.core::libPath The path in which the Qt libraries are located. \nodefaultvalue */ /*! \qmlproperty bool Qt.core::lreleaseMultiplexMode If this property is \c true, \c lrelease will merge all \c .ts files into one \c .qm file. Otherwise, one \c .qm file will be created for each \c .ts file. \defaultvalue \c{false} */ /*! \qmlproperty string Qt.core::lreleaseName The base name of the \c lrelease tool. Set this if your system uses a name such as \c "lrelease-qt4". \defaultvalue \c{"lrelease"} */ /*! \qmlproperty path Qt.core::mkspecPath The path in which the Qt \c mkspecs are located. \nodefaultvalue */ /*! \qmlproperty stringList Qt.core::mocFlags A list of additional flags to \c moc. You will rarely need to set this property. \defaultvalue \c [] */ /*! \qmlproperty string Qt.core::mocName The base name of the \c moc tool. Set this if your system uses a name such as \c "moc-qt4". \defaultvalue \c{"moc"} */ /*! \qmlproperty string Qt.core::namespace The Qt namespace that can be set at build time via the \c configure script. By default, Qt is not built in a namespace. \nodefaultvalue */ /*! \qmlproperty stringList Qt.core::pluginMetaData A list of additional plugin metadata. The elements of the list are key-value pairs separated by the \c = character. A possible use case is to set the plugin URI when building a static QML plugin: \badcode Qt.core.pluginMetaData: ["uri=thePlugin"] \endcode \defaultvalue \c [] */ /*! \qmlproperty path Qt.core::pluginPath The path in which the Qt plugins are located. \nodefaultvalue */ /*! \qmlproperty stringList Qt.core::qdocEnvironment The environment for calls to \c qdoc. Typically, you will need to set some variables here when running \c qdoc to build your project documentation. \nodefaultvalue */ /*! \qmlproperty string Qt.core::qdocName The base name of the \c qdoc tool. \defaultvalue \c{"qdoc3"} for Qt 4, \c{"qdoc"} otherwise. */ /*! \qmlproperty string Qt.core::qmBaseName The base name of the \c .qm file to be built from the \c .ts files in the product. This property is ignored if \l{Qt.core::}{lreleaseMultiplexMode} is \c false. \defaultvalue \l{Product::targetName}{product.targetName} */ /*! \qmlproperty string Qt.core::qtBuildVariant Specifies the type of Qt libraries to build against: \c "debug" or \c "release". \note On some systems, it is not possible to link code built in debug mode against libraries built in release mode and vice versa. \defaultvalue The build variant of the code linking against Qt. If Qt does not offer that build variant, the build variant offered by Qt is chosen instead. */ /*! \qmlproperty stringList Qt.core::qtConfig Corresponds to the default value of qmake's \c QT_CONFIG variable. \defaultvalue \c [] */ /*! \qmlproperty path Qt.core::resourceSourceBase For files tagged as \l{filetags-qtcore}{qt.core.resource_data}, this property determines which part of their path will end up in the generated \c .qrc file. If this property is set to \c undefined, only the file name is used. \nodefaultvalue */ /*! \qmlproperty string Qt.core::resourcePrefix For files tagged as \l{filetags-qtcore}{qt.core.resource_data}, this property determines the prefix under which they will be available in the generated \c .qrc file. \defaultvalue \c{"/"} */ /*! \qmlproperty string Qt.core::resourceFileBaseName For files tagged as \l{filetags-qtcore}{qt.core.resource_data}, this property determines the base name of the generated \c .qrc file. If this property needs to be changed, it must be set in the corresponding \l{Product}{product} rather than in a \l{Group}. \defaultvalue \l{Product::targetName}{product.targetName} */ /*! \qmlproperty bool Qt.core::staticBuild Whether Qt was built statically. \nodefaultvalue */ /*! \qmlproperty string Qt.core::version The Qt version. Consists of three numbers separated by dots. For example "5.9.1". \nodefaultvalue */ /*! \qmlproperty int Qt.core::versionMajor The Qt major version. \defaultvalue \c{versionParts[0]} */ /*! \qmlproperty int Qt.core::versionMinor The Qt minor version. \defaultvalue \c{versionParts[1]} */ /*! \qmlproperty list Qt.core::versionParts The Qt version as a list. For example, Qt version 5.9.1 would correspond to a value of \c[5, 9, 1]. \defaultvalue \c [] */ /*! \qmlproperty int Qt.core::versionPatch The Qt patch level. \defaultvalue \c{versionParts[2]} */ qbs-src-1.13.1/doc/reference/modules/qt-dbus-module.qdoc000066400000000000000000000052621347155106100230440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Qt.dbus \inqmlmodule QbsModules \brief Provides Qt D-Bus support. The Qt.dbus module provides support for the Qt D-Bus module, which contains classes for inter-process communication over the D-Bus protocol. \section2 Relevant File Tags \target filetags-debus \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"qt.dbus.adaptor"} \li - \li 1.5 \li Source files with this tag serve as inputs to the rule running the \c qdbusxml2cpp tool, which will create an adaptor class. \row \li \c{"qt.dbus.interface"} \li - \li 1.5 \li Source files with this tag serve as inputs to the rule running the \c qdbusxml2cpp tool, which will create an interface class. \endtable */ /*! \qmlproperty string Qt.dbus::xml2cppName The base name of the \c qdbusxml2cpp tool. Set this property if your system uses a name different from the default value. \defaultvalue \c{"qdbusxml2cpp"} */ /*! \qmlproperty stringList Qt.dbus::xml2CppHeaderFlags A list of additional flags when running the \c qdbusxml2cpp tool to create header files. \defaultvalue \c [] */ /*! \qmlproperty stringList Qt.dbus::xml2CppSourceFlags A list of additional flags when running the \c qdbusxml2cpp tool to create source files. \defaultvalue \c [] */ qbs-src-1.13.1/doc/reference/modules/qt-declarative-module.qdoc000066400000000000000000000037361347155106100243760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Qt.declarative \inqmlmodule QbsModules \brief Provides Qt Quick 1 support. The Qt.declarative module provides support for Qt Quick 1. \sa Qt.quick, Qt.qml */ /*! \qmlproperty bool Qt.declarative::qmlDebugging Whether QML debugging support is compiled into your binaries. \defaultvalue \c{false} */ /*! \qmlproperty string Qt.declarative::qmlImportsPath The absolute path to the directory where Qt's QML imports are installed. \defaultvalue Determined by \l{setup-qt}. */ /*! \qmlproperty string Qt.declarative::qmlPath The absolute path to the directory where Qt's QML files are installed. This property is left undefined for Qt 4. \defaultvalue Determined by \l{setup-qt}. */ qbs-src-1.13.1/doc/reference/modules/qt-gui-module.qdoc000066400000000000000000000037611347155106100226750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Qt.gui \inqmlmodule QbsModules \brief Provides Qt GUI support. The Qt.gui module provides support for the Qt GUI module, which contains base classes for graphical user interface (GUI) components. \section2 Relevant File Tags \target filetags-gui \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"ui"} \li \c{*.ui} \li 1.0 \li Source files with this tag serve as inputs to the rule running the \c uic tool. \endtable */ /*! \qmlproperty string Qt.gui::uicName The base name of the \c uic tool. Set this property if your system uses a name such as \c uic-qt4. \defaultvalue \c{"uic"} */ qbs-src-1.13.1/doc/reference/modules/qt-modules.qdoc000066400000000000000000000134541347155106100222760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page qt-modules.html \inmodule qbs-modules \title Qt Modules \brief Provides Qt support. The \c{Qt.*} modules contain properties and rules for Qt. \section1 Creating Dependencies to Qt Modules The Qt modules are grouped using the prefix \c Qt. If your product depends on the Qt.core and Qt.network modules, you could write: \code Depends { name: "Qt.core" } Depends { name: "Qt.network" } \endcode Or, alternatively: \code Depends { name: "Qt"; submodules: [ "core", "network" ] } \endcode The Qt modules that have properties and relevant file tags are described in separate topics. \section1 Qt-specific Module Provider Properties Looking up a Qt installation happens via a \l{Module Providers}{module provider}. By default, if a dependency to a Qt module is encountered, \QBS collects all Qt installations it can find. This lookup happens by searching for \c qmake executables in the \c PATH environment variable. Alternatively, you can explicitly tell \QBS which Qt installations it should consider by setting the \c Qt.qmakeFilePaths \l{Parameterizing Module Providers}{module provider property}. In that case, the environment will be ignored. For instance, with the following Linux command line, \QBS will build the project against a custom Qt instead of the standard one in \c{/usr/bin}: \code $ qbs moduleProviders.Qt.qmakeFilePaths:/opt/myqt/bin/qmake \endcode You can also set the module provider property in a profile. The simplest way to do this is via the \l setup-qt tool. \section1 List of Submodules \table \header \li Submodule Name \li Qt Module Name \li Notes \row \li axcontainer \li QAxContainer \li This module is only available on Windows. \row \li axserver \li QAxServer \li This module is only available on Windows. \row \li concurrent \li Qt Concurrent \li \row \li \l{Qt.core}{core} \li Qt Core \li For more information, see \l{Qt.core}. \row \li \l{Qt.dbus}{dbus} \li Qt D-Bus \li For more information, see \l{Qt.dbus}. \row \li \l{Qt.declarative}{declarative} \li Qt Quick 1 \li Provides the \c{Qt Quick 1} module. For more information, see \l{Qt.declarative}. \row \li designer \li Qt Designer \li \row \li enginio \li Qt Enginio \li \row \li \l{Qt.gui}{gui} \li Qt GUI \li For more information, see \l {Qt.gui}. \row \li help \li Qt Help \li You do not need this module for building \c qdoc documentation, because that functionality is part of the Qt.core module. This module is for using Qt classes such as \c QHelpEngine. \row \li multimedia \li Qt Multimedia \li \row \li multimediawidgets \li Qt Multimedia Widgets \li \row \li network \li Qt Network \li \row \li opengl \li Qt OpenGL \li \row \li phonon \li Phonon (Qt 4 only) \li \row \li printsupport \li Qt Print Support \li \row \li \l{Qt.quick}{quick} \li Qt Quick 2 \li Provides the \c{Qt Quick} module (Qt Quick 2). For more information, see \l{Qt.quick}. \row \li \l{Qt.qml}{qml} \li Qt QML \li For more information, see \l{Qt.qml}. \row \li qmltest \li Qt Quick Test \li \row \li script \li Qt Script \li \row \li \l{Qt.scxml}{scxml} \li Qt Scxml \li For more information, see \l {Qt.scxml}. \row \li sql \li Qt SQL \li \row \li svg \li Qt SVG \li \row \li testlib \li Qt Test \li \row \li webkit \li Qt WebKit \li \row \li webkitwidgets \li Qt WebKit Widgets \li \row \li widgets \li Qt Widgets \li \row \li xml \li Qt XML \li You do not need this module for the \c QXmlStreamReader and \c QXmlStreamWriter classes, because those classes are a part of the \c Qt.core module. This module provides the deprecated DOM and SAX classes. \row \li xmlpatterns \li Qt XML Patterns \li \li \endtable */ qbs-src-1.13.1/doc/reference/modules/qt-plugin_support-module.qdoc000066400000000000000000000057141347155106100252030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Qt.plugin_support \inqmlmodule QbsModules \since Qbs 1.13.0 \brief Allows to fine-tune which Qt plugins get pulled in. The \c Qt.plugin_support module provides properties that allow users to control which Qt plugins to pull into a product. This is mostly relevant if Qt was built statically, in which case the respective plugins are static libraries that get linked into your application or library. */ /*! \qmlproperty varList Qt.plugin_support::pluginsByType Set this property if you want to override the set of plugins for a certain plugin type. For instance, to disable all image plugins except the JPEG one: \code Qt.plugin_support.pluginsByType: ({imageformats: "qjpeg"}) \endcode For plugin types that are not specifically overridden like this, the value in defaultPluginsByType is used. \nodefaultvalue */ /*! \qmlproperty var Qt.plugin_support::allPluginsByType Provides the complete set of plugins in a statically built Qt. The value is a map. The keys are the plugin types, and the values are lists of plugin names. \readonly */ /*! \qmlproperty var Qt.plugin_support::defaultPluginsByType Provides the set of plugins that your application or library will link to if you do not set pluginsByType. The value is a map. The keys are the plugin types, and the values are lists of plugin names. The value depends on the Qt modules your product pulls in. \readonly */ /*! \qmlproperty bool Qt.plugin_support::linkPlugins Controls whether plugins of a statically built Qt should be linked into the product. \defaultvalue \c true if the product is an application or shared library, \c false otherwise. */ qbs-src-1.13.1/doc/reference/modules/qt-qml-module.qdoc000066400000000000000000000064551347155106100227050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Qt.qml \inqmlmodule QbsModules \brief Provides Qt QML support. The Qt.qml module provides support for the Qt QML module, which contains classes for QML and JavaScript languages. \note If the current value of \l{qbs::architecture}{qbs.architecture} is not supported by \c qmlcachegen, the QML cache file generator rule is disabled. \sa Qt.quick, Qt.declarative \section2 Relevant File Tags \target filetags-qml \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"qt.qml.js"} \li \c{*.js} \li 1.10 \li QML companion JavaScript files. Source files with this tag serve as input for the QML cache file generator. \row \li \c{"qt.qml.qml"} \li \c{*.qml} \li 1.8 \li Source files with this tag serve as inputs to the QML plugin scanner. \endtable */ /*! \qmlproperty string Qt.qml::qmlImportScannerName The base name of the QML import scanner. Set this value if your system uses a name different from the default value. \defaultvalue \c{"qmlimportscanner"} */ /*! \qmlproperty string Qt.qml::qmlPath The absolute path to the directory where Qt's QML files are installed. \defaultvalue Determined by \l{setup-qt}. */ /*! \qmlproperty bool Qt.qml::generateCacheFiles Whether QML cache files are generated. \defaultvalue \c{false} */ /*! \qmlproperty bool Qt.qml::cachingEnabled \readonly This property is \c true if \l{Qt.qml::}{generateCacheFiles} is \c{true} and the platform supports QML cache generation. \defaultvalue \c{false} */ /*! \qmlproperty string Qt.qml::qmlCacheGenPath The absolute path to the \c qmlcachegen executable. \defaultvalue Determined by \l{setup-qt}. */ /*! \qmlproperty string Qt.qml::cacheFilesInstallDir The path to the directory where the cache files are installed. If this property is set, QML cache files are automatically installed. \nodefaultvalue */ qbs-src-1.13.1/doc/reference/modules/qt-quick-module.qdoc000066400000000000000000000055051347155106100232230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Qt.quick \inqmlmodule QbsModules \brief Provides Qt Quick 2 support. The Qt.quick module provides support for Qt Quick 2. \sa Qt.qml, Qt.declarative \section2 Relevant File Tags \target filetags-quick \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"qt.quick.qrc"} \li \c{*.qrc} \li 1.10 \li Qt resource files with this file tag will be picked up by the Qt Quick compiler rule, and all QML files in the resource will be compiled. This file tag will only be added automatically if the Qt Quick compiler is available. \endtable */ /*! \qmlproperty bool Qt.quick::compilerAvailable Whether the Qt installation contains the Qt Quick compiler. \defaultvalue auto-detected \since 1.10 */ /*! \qmlproperty bool Qt.quick::useCompiler Whether to make use of the Qt Quick compiler. \defaultvalue \l compilerAvailable \since 1.11 */ /*! \qmlproperty bool Qt.quick::qmlDebugging Whether QML debugging support should be compiled into your binaries. \defaultvalue \c{false} */ /*! \qmlproperty string Qt.quick::qmlImportsPath The absolute path to the directory where Qt's QML imports are installed. \defaultvalue Determined by \l{setup-qt}. */ /*! \qmlproperty string Qt.quick::qmlPath The absolute path to the directory where Qt's QML files are installed. This property is left undefined for Qt 4. \defaultvalue Determined by \l{setup-qt}. */ qbs-src-1.13.1/doc/reference/modules/qt-scxml-module.qdoc000066400000000000000000000053511347155106100232340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype Qt.scxml \inqmlmodule QbsModules \brief Provides Qt SCXML support. The Qt.scxml module provides support for the Qt SCXML module, which enables creating state machines from SCXML files. \section2 Relevant File Tags \target filetags-scxml \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"qt.scxml.compilable"} \li - \li 1.7 \li Source files with this tag serve as inputs to the rule running the Qt SCXML compiler, which will create a C++ class representing a state machine. \endtable */ /*! \qmlproperty string Qt.scxml::className The class name of the generated state machine. By default, the compiler will use the \c name attribute of the input file's \c{} tag. \nodefaultvalue */ /*! \qmlproperty string Qt.scxml::generateStateMethods If this property is \c true, the Qt SCXML compiler will generate read and notify methods for states. \defaultvalue \c false \since 1.11 */ /*! \qmlproperty string Qt.scxml::namespace The C++ namespace in which to put the generated class. By default, the compiler will place the class in the global namespace. \nodefaultvalue */ /*! \qmlproperty string Qt.scxml::qscxmlcName The base name of the Qt SCXML compiler. Set this value if your system uses a name different from the default value. \defaultvalue \c{"qscxmlc"} */ qbs-src-1.13.1/doc/reference/modules/texttemplate-module.qdoc000066400000000000000000000062551347155106100242100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype texttemplate \inqmlmodule QbsModules \since Qbs 1.13 \brief Provides support for text template files. The \c texttemplate module provides support for text template files. \section2 Example Consider the following text file \e{greeting.txt.in}. \code ${greeting} ${name}! \endcode This can be used in a project like this: \code Product { type: ["text"] files: ["greeting.txt.in"] Depends { name: "texttemplate" } texttemplate.dict: ({ greeting: "Hello", name: "World" }) } \endcode Which will create the file \e{greeting.txt}. \code Hello World! \endcode \section2 Placeholder Syntax A placeholder \c{${foo}} is replaced by its corresponding value in \e{texttemplate.dict}. Placeholder names consist of alphanumeric characters only. The placeholder \c{${$}} is always replaced with \c{$}. If you need a literal \c{${foo}} in your template, use \c{${$}{foo}}. Placeholders that are not defined in the dictionary will produce an error. \section2 Relevant File Tags \target filetags-texttemplate \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"texttemplate.input"} \li \c{*.in} \li 1.13.0 \li Source files with this tag serve as inputs for the text template rule. \endtable */ /*! \qmlproperty var texttemplate::dict The dictionary containing values for all keys used in the template file. \defaultvalue \c{{}} */ /*! \qmlproperty string texttemplate::outputFileName The output file name that is assigned to produced artifacts. \defaultvalue Complete base name of the input file */ /*! \qmlproperty string texttemplate::outputTag The output tag that is assigned to produced artifacts. \defaultvalue \c{"text"} */ qbs-src-1.13.1/doc/reference/modules/typescript-module.qdoc000066400000000000000000000117571347155106100237010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype typescript \inqmlmodule QbsModules \since Qbs 1.3 \brief Provides TypeScript support. The \c typescript module contains properties and rules for building \l{TypeScript} applications and may be used in combination with the \l{nodejs} module to run the applications directly from \QBS. */ /*! \qmlproperty string typescript::warningLevel The severity of warnings to emit. The higher the level, the more warnings will be shown. \c{pedantic} causes the TypeScript to emit warnings on expressions and declarations with an implied \e any type. \defaultvalue \c{"normal"} */ /*! \qmlproperty string typescript::targetVersion The ECMAScript target version for generated JavaScript code. If left undefined, the TypeScript \l{Compiler Options}{compiler default} is used. \nodefaultvalue */ /*! \qmlproperty string typescript::moduleLoader If TypeScript modules are being used, the JavaScript module loading mechanism to use in the generated JavaScript code. If left undefined, modules are not used. See \l{Compiler Options} for a list of possible values. \nodefaultvalue */ /*! \qmlproperty bool typescript::stripComments Whether to remove comments from the generated JavaScript files. \defaultvalue \l{qbs::debugInformation}{!qbs.debugInformation} */ /*! \qmlproperty bool typescript::generateDeclarations Whether to generate the corresponding \c .d.ts files during compilation. These are TypeScript's equivalent of header files. \defaultvalue \c{false} */ /*! \qmlproperty bool typescript::generateSourceMaps Whether to generate the corresponding \c .map files during compilation. \defaultvalue \l{qbs::debugInformation}{qbs.debugInformation} */ /*! \qmlproperty stringList typescript::compilerFlags A list of additional flags for the TypeScript compiler. \nodefaultvalue */ /*! \qmlproperty bool typescript::singleFile Whether to compile all TypeScript source files to a single JavaScript output file. The default is to compile each TypeScript file to a corresponding JavaScript file. This property is incompatible with \l{typescript}{moduleLoader}. \defaultvalue \c{false} */ /*! \qmlproperty string typescript::version The TypeScript version. Consists of four numbers separated by dots. For example, "1.0.0.0". \nodefaultvalue */ /*! \qmlproperty int typescript::versionMajor The TypeScript major version. \defaultvalue \c{versionParts[0]} */ /*! \qmlproperty int typescript::versionMinor The TypeScript minor version. \defaultvalue \c{versionParts[1]} */ /*! \qmlproperty list typescript::versionParts The TypeScript version as a list. For example, TypeScript version 1.0 would correspond to a value of \c[1, 0, 0, 0]. \defaultvalue \c [] */ /*! \qmlproperty int typescript::versionPatch The TypeScript patch level. \defaultvalue \c{versionParts[2]} */ /*! \qmlproperty int typescript::versionBuild The fourth TypeScript version number component. \defaultvalue \c{versionParts[3]} */ /*! \qmlproperty path typescript::toolchainInstallPath The TypeScript installation directory. This property should not normally need to be changed if \c{tsc} is available by searching the PATH environment variable. \nodefaultvalue */ /*! \qmlproperty string typescript::compilerName The name of the compiler binary. This property should not normally need to be changed. \defaultvalue \c{"tsc"} */ /*! \qmlproperty string typescript::compilerPath The directory where the compiler binary is located. This property should not normally need to be changed. \defaultvalue \c{compilerName} */ qbs-src-1.13.1/doc/reference/modules/vcs-module.qdoc000066400000000000000000000064411347155106100222600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype vcs \inqmlmodule QbsModules \since Qbs 1.10 \brief Provides support for version control systems. The \c vcs module provides the current state of the project's repository via the \l{vcs::}{repoState} property. By default, a \c C header is also generated, allowing for simple retrieval of the repository state directly from within your C/C++ sources. This is useful to embed information into binaries about the exact state of the repository from which they were built. For example: \code #include #include int main() { std::cout << "I was built from " << VCS_REPO_STATE << std::endl; } \endcode Above, a header file called \c{vcs-repo-state.h} is created, defining a macro called \c VCS_REPO_STATE, which expands to a character constant describing the current state of the repository. For Git, this would be the current HEAD's commit hash. */ /*! \qmlproperty string vcs::headerFileName The name of the C header file to be created. Set this to \c undefined if you do not want a header file to be generated. \defaultvalue \c{"vcs-repo-state.h"} */ /*! \qmlproperty string vcs::repoDir The root directory of the repository. \defaultvalue The top-level project directory (\l{Project::sourceDirectory} {project.sourceDirectory}). */ /*! \qmlproperty string vcs::repoState The current state of the repository. For example, in Git this is the commit hash of the current HEAD. \nodefaultvalue */ /*! \qmlproperty string vcs::toolFilePath Set this property if the tool has an unusual name in your local installation, or if it is located in a directory that is not in the build environment's \c PATH. \defaultvalue The file name of the version control tool corresponding to \l{vcs::type}{type}. */ /*! \qmlproperty string vcs::type The version control system used in the project. Currently, the supported values are \c{"git"} and \c{"svn"}. \defaultvalue auto-detected */ qbs-src-1.13.1/doc/reference/modules/wix-module.qdoc000066400000000000000000000175731347155106100223040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype wix \inqmlmodule QbsModules \since Qbs 1.2 \brief Provides Windows Installer XML Toolset support. The \c wix module contains properties and rules for building MSI and EXE setup packages with the \l{Windows Installer XML Toolset}. This module is available on all platforms. \section2 Relevant File Tags \target filetags-wix \table \header \li Tag \li Auto-tagged File Names \li Since \li Description \row \li \c{"msi"} \li - \li 1.2 \li The rule that creates the Microsoft Installer setup file attaches this tag to its output artifact. \row \li \c{"wixpdb"} \li - \li 1.2 \li The rule that creates the Microsoft Installer setup file or WiX setup executable attaches this tag to the associated debug symbol file. \row \li \c{"wixsetup"} \li - \li 1.2 \li The rule that creates the WiX setup executable attaches this tag to its output artifact. \row \li \c{"wxi"} \li \c{*.wxi} \li 1.2 \li This tag is attached to WiX include files. \row \li \c{"wxl"} \li \c{*.wxl} \li 1.2 \li This tag is attached to WiX localization files. \row \li \c{"wxs"} \li \c{*.wxs} \li 1.2 \li This tag is attached to WiX source files. Each source file will be compiled into one WiX object file. \endtable */ /*! \qmlproperty bool wix::debugInformation Whether to generate debug information. \sa {qbs::debugInformation}{qbs.debugInformation} \defaultvalue \l{qbs::debugInformation}{qbs.debugInformation} */ /*! \qmlproperty stringList wix::defines A list of preprocessor macros that get passed to the compiler. To set macro values, use the following syntax: \badcode wix.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"'] \endcode \nodefaultvalue */ /*! \qmlproperty bool wix::enableQbsDefines Whether to define preprocessor macros corresponding to values from the project and product objects. When building a 64-bit package, the preprocessor variable \c{Win64} will also be defined. \defaultvalue \c{true} */ /*! \qmlproperty bool wix::visualStudioCompatibility Whether to pass most of the same preprocessor macros to the compiler as Visual Studio does. This allows easier authoring of WiX files that are compatible with both \QBS and MSBuild. \defaultvalue \c{true} */ /*! \qmlproperty pathList wix::includePaths A list of include paths. Relative paths are considered to be relative to the \c .qbs product file they are used in. \nodefaultvalue */ /*! \qmlproperty bool wix::treatWarningsAsErrors Whether warnings will be handled as errors and cause the build to fail. \defaultvalue \c{false} */ /*! \qmlproperty string wix::warningLevel The severity of warnings to emit. The higher the level, the more warnings will be shown. Possible values include: \c{"none"}, \c{"normal"}, \c{"pedantic"} \defaultvalue \c{"normal"} */ /*! \qmlproperty bool wix::verboseOutput Whether to display verbose output from the compiler and linker. \defaultvalue \c{false} */ /*! \qmlproperty stringList wix::compilerFlags A list of additional flags for the Candle compiler. \nodefaultvalue */ /*! \qmlproperty stringList wix::linkerFlags A list of additional flags for the Light linker. \nodefaultvalue */ /*! \qmlproperty stringList wix::cultures A list of localizations to include in the MSI. If left undefined, includes all localizations. \nodefaultvalue */ /*! \qmlproperty stringList wix::extensions A list of extension assemblies to link into the output. Possible values include: \list \li custom assemblies \li \c{"WixBalExtension"} \li \c{"WixComPlusExtension"} \li \c{"WixDependencyExtension"} \li \c{"WixDifxAppExtension"} \li \c{"WixDirectXExtension"} \li \c{"WixFirewallExtension"} \li \c{"WixGamingExtension"} \li \c{"WixIisExtension"} \li \c{"WixMsmqExtension"} \li \c{"WixNetFxExtension"} \li \c{"WixPSExtension"} \li \c{"WixSqlExtension"} \li \c{"WixTagExtension"} \li \c{"WixUIExtension"} \li \c{"WixUtilExtension"} \li \c{"WixVSExtension"} \endlist \defaultvalue \c{["WixBalExtension"]} if the product type is an EXE setup application, otherwise \c{undefined}. */ /*! \qmlproperty string wix::version The WiX version. Consists of four numbers separated by dots. For example, "3.7.1224.0". \nodefaultvalue */ /*! \qmlproperty int wix::versionMajor The WiX major version. \defaultvalue \c{versionParts[0]} */ /*! \qmlproperty int wix::versionMinor The WiX minor version. \defaultvalue \c{versionParts[1]} */ /*! \qmlproperty list wix::versionParts The WiX version as a list. For example, WiX version 3.7.1224.0 would correspond to a value of \c[3, 7, 1224, 0]. \defaultvalue \c [] */ /*! \qmlproperty int wix::versionPatch The WiX patch level. \defaultvalue \c{versionParts[2]} */ /*! \qmlproperty int wix::versionBuild The fourth WiX version number component. \defaultvalue \c{versionParts[3]} */ /*! \qmlproperty path wix::toolchainInstallPath The WiX installation directory. This property should not normally need to be changed. \defaultvalue Determined automatically by searching the registry for the latest version. */ /*! \qmlproperty path wix::toolchainInstallRoot The WiX binaries directory. This property should not normally need to be changed. \defaultvalue Determined automatically by searching the registry for the latest version. */ /*! \qmlproperty string wix::compilerName The name of the compiler binary. This property should not normally need to be changed. \defaultvalue \c{"candle.exe"} */ /*! \qmlproperty string wix::compilerPath The directory where the compiler binary is located. This property should not normally need to be changed. \defaultvalue \l{wix::}{compilerName} */ /*! \qmlproperty string wix::linkerName The name of the linker binary. This property should not normally need to be changed. \defaultvalue \c{"light.exe"} */ /*! \qmlproperty string wix::linkerPath The directory where the linker binary is located. This property should not normally need to be changed. \defaultvalue \l{wix::}{linkerName} */ qbs-src-1.13.1/doc/reference/modules/xcode-module.qdoc000066400000000000000000000110741347155106100225650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \qmltype xcode \inqmlmodule QbsModules \since Qbs 1.5 \brief Provides Xcode support. The \c xcode module contains properties and rules for Xcode-based development. This module provides the foundation for several other modules on Apple platforms, including the \l{cpp} and \l{ib} modules. */ /*! \qmlproperty path xcode::developerPath The developer directory of the Xcode installation. Corresponds to the \c DEVELOPER_DIR environment variable. \defaultvalue The developer directory of the Xcode installation at its default location in \c /Applications. For example, \c{"/Applications/Xcode.app/Contents/Developer"}. */ /*! \qmlproperty string xcode::sdk The version of the Xcode SDK used to build products. This can be specified as a full canonical SDK name (\c{"macosx10.10"}), a platform version number (\c{"10.10"}), or a platform identifier (\c{"macosx"}), in which case the latest SDK available for that platform will be used. \defaultvalue The latest SDK available in the Xcode installation for the current platform. Determined by \l{qbs::targetOS}{qbs.targetOS}. */ /*! \qmlproperty stringList xcode::targetDevices A list of the Apple devices targeted by this product. For macOS, watchOS, and tvOS, this should always be \c "mac", \c "watch", and \c "tv", respectively. For iOS, this can be one or both of \c "iphone" and \c "ipad". \defaultvalue The list of all device types supported by the current platform. Determined by \l{qbs::targetOS}{qbs.targetOS}. */ /*! \qmlproperty string xcode::sdkName \readonly The canonical name of the SDK used to build products. For example, \c macosx10.9. \defaultvalue \l{xcode::}{sdk} */ /*! \qmlproperty string xcode::sdkVersion \readonly The version number of the SDK used to build products. For example, 10.9. \defaultvalue \l{xcode::}{sdk} */ /*! \qmlproperty string xcode::latestSdkName \readonly The canonical name of the latest SDK available in the Xcode installation. For example, \c {macosx10.10}. \defaultvalue \l{xcode::}{developerPath} */ /*! \qmlproperty string xcode::latestSdkVersion \readonly The version number of the latest SDK available in the Xcode installation. For example, 10.10. \defaultvalue \l{xcode::}{developerPath} */ /*! \qmlproperty stringList xcode::availableSdkNames \readonly The canonical names of all SDKs available in the Xcode installation for the current platform. For example, \c {[macosx10.9, macosx10.10]}. \defaultvalue \l{xcode::}{developerPath} */ /*! \qmlproperty stringList xcode::availableSdkVersions \readonly The version numbers of all SDK available in the Xcode installation for the current platform. For example, \c {[10.9, 10.10]}. \defaultvalue \l{xcode::}{developerPath} */ /*! \qmlproperty path xcode::platformPath \readonly The path of the platform directory containing \l{xcode::}{sdkPath}. \defaultvalue \l{xcode::}{developerPath} */ /*! \qmlproperty path xcode::sdkPath \readonly The path of the SDK used to build products. Equivalent to \l{qbs::sysroot}{qbs.sysroot}. \defaultvalue Determined by \l{xcode::}{developerPath} and \l{xcode::}{sdk}. */ qbs-src-1.13.1/doc/reference/reference.qdoc000066400000000000000000000073241347155106100204710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \previouspage howtos.html \page reference.html \nextpage building-qbs.html \title Reference \list \li \l{List of All Items} \list \li \l{List of Language Items} \li \l{List of Convenience Items} \li \l{List of Probes} \endlist \li \l{List of Built-in Services} \li \l{Command-Line Interface} \li \l{List of Modules} \li \l{Command and JavaScriptCommand} \endlist */ /*! \contentspage reference.html \group list-of-builtin-services \title List of Built-in Services \QBS provides the following built-in JavaScript extensions to simplify operations that are expected to be needed often in project files. To gain access to the operations provided by a particular Service - for example, the File service - use the following statement at the top of your \QBS project file: \code import qbs.File \endcode If you instead need to access the service from a JavaScript file, import it using the following statement at the top of your JavaScript file: \code var File = require("qbs.File"); \endcode */ /*! \contentspage reference.html \qmlmodule QbsModules \title List of Modules These are the modules shipped with \QBS. For a list of \QBS modules that provide support for Qt modules, see \l{Qt Modules}. Only the Qt modules that have properties and relevant file tags are described in separate topics. */ /*! \contentspage reference.html \group list-of-items \title List of All Items \QBS provides the following \l{List of Language Items}{built-in}, \l{List of Convenience Items}{convenience}, and \l{List of Probes}{probe} items to define projects. */ /*! \contentspage reference.html \qmlmodule QbsLanguageItems \title List of Language Items \QBS provides the following built-in QML items to define projects. These are the primitives upon which all other \QBS items are built. */ /*! \contentspage reference.html \qmlmodule QbsConvenienceItems \title List of Convenience Items \QBS provides the following QML items for convenience. */ /*! \contentspage reference.html \group list-of-probes \title List of Probes These are the probes shipped with \QBS. Probes are used to retrieve information from the system prior to building. Typically, probes call external processes to get the required information. For details, see \l{Probe}{Probe} page. */ qbs-src-1.13.1/doc/targets/000077500000000000000000000000001347155106100153705ustar00rootroot00000000000000qbs-src-1.13.1/doc/targets/qbs-target-android.qdoc000066400000000000000000000062561347155106100217400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page qbs-target-android.html \ingroup platforms \title Building for Android \brief Platform notes for Android. To develop applications for Android, you need development tools provided by the Android SDK from Google, and (optionally) a C/C++ toolchain provided by the Android NDK. \note \QBS does not yet support the Kotlin programming language. \section1 Creating Android Application Packages On Android, applications are distributed in a specially structured type of ZIP package called an APK. The following files should be created and bundled into an APK: \list \li Android assets. \li Android resource files. \li AndroidManifest.xml, which provides meta-information about your application. \li Compiled Java code, which serves as the entry point into your application and that automatically executes the native code in your application (if there is any). \li Shared libraries containing native code. \endlist You can use the \l{Application} item to build application packages for Android. If the \l{qbs::targetPlatform}{target platform} is \c{"android"}, then the Application item has a dependency on the \l{Android.sdk} module, which contains the properties and rules to create Android application packages from source files. You can use the \l{DynamicLibrary} item to build native Android libraries that are bundled into the APK. The \c qbs.architectures property specifies the architectures to build for, with the default value \c armv7a. If you have only one native library, you can simply list its sources within the main Application item, and it will get built and packaged automatically. The \l{DynamicLibrary} item, as well as the \l CppApplication item, has a dependency on the \l{Android.ndk} module, and contains the properties and rules to create native libraries. */ qbs-src-1.13.1/doc/targets/qbs-target-apple-common.qdocinc000066400000000000000000000101001347155106100233600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! //! [xcode] \note \QBS does not yet support the Swift programming language. The \l{xcode} module contains properties and rules for Xcode-based development. //! [xcode] //! [building user interfaces] \section1 Building User Interfaces The \l{ib} module contains properties and rules for building Interface Builder documents, storyboards, asset catalogs, and icon sets. //! [building user interfaces] //! [creating app bundles] \section1 Creating App Bundles The \l{bundle} module contains properties and rules for building and working with Core Foundation bundles (application bundles and frameworks) on Apple platforms. To build an application product as a bundle, or a dynamic or static library product as a framework, add a dependency on the bundle module and set the \l{bundle::isBundle}{bundle.isBundle} property to \c true: \code Depends { name: "bundle" } bundle.isBundle: true \endcode \QBS also provides a number of powerful features to assist in creating the Info.plist file that is part of your bundle. In fact, you do not need to provide an Info.plist file at all. Instead, \QBS will generate one automatically with the necessary keys, based on the values of module properties set in the product. If you do specify an Info.plist file, \QBS may still inject additional keys into the final output from other sources. One notable source of Info.plist keys are \e partial Info.plist files which are generated as a result of compiling other resources like asset catalogs, XIBs/NIBs, and storyboards. You may also use the \c bundle.infoPlist property to apply a set of key-value pairs to be added to the final Info.plist. This can be used instead of or in addition to an actual Info.plist file on disk. //! [creating app bundles] //! [architectures and variants] \section1 Multiple Architectures and Build Variants \QBS uses \l{Multiplexing}{multiplexing} to create multi-architecture \e fat binaries and multi-variant frameworks, where a single framework can contain both a release and debug build of a library on Apple platforms. You can set the \c qbs.architectures property to a list of CPU architectures (such as \c x86, \c x86_64, \c armv7a, \c armv7k, and \c arm64), and the \c qbs.buildVariants property to a list of build variants (such as \c debug and \c release), and \QBS will transparently perform the necessary steps to produce the various artifacts and combine them into a single bundle. Since the individual build configurations are completely independent of one another, you can continue to use conditional branches in your projects such as the following: \code Properties { condition: qbs.buildVariant === "release" cpp.optimization: "small" } \endcode //! [architectures and variants] */ qbs-src-1.13.1/doc/targets/qbs-target-integrity.qdoc000066400000000000000000000032301347155106100223230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page qbs-target-integrity.html \ingroup platforms \title Building for INTEGRITY \brief Platform notes for INTEGRITY. The Green Hills INTEGRITY RTOS is not yet supported but is planned for a future release. For more information about developing applications for the Green Hills INTEGRITY RTOS, see the \l{https://www.ghs.com/products/rtos/integrity.html} {INTEGRITY Product Documentation}. */ qbs-src-1.13.1/doc/targets/qbs-target-ios.qdoc000066400000000000000000000032411347155106100211010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page qbs-target-ios.html \ingroup platforms \title Building for iOS \brief Platform notes for iOS. This topic describes the \QBS features specific to iOS. \include qbs-target-apple-common.qdocinc xcode \include qbs-target-apple-common.qdocinc building user interfaces \include qbs-target-apple-common.qdocinc creating app bundles \include qbs-target-apple-common.qdocinc architectures and variants */ qbs-src-1.13.1/doc/targets/qbs-target-linux.qdoc000066400000000000000000000027241347155106100214530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page qbs-target-linux.html \ingroup platforms \title Building for Linux \brief Platform notes for Linux. To develop applications for Linux, you need a GCC or Clang toolchain installed on your host machine. */ qbs-src-1.13.1/doc/targets/qbs-target-macos.qdoc000066400000000000000000000062351347155106100214170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page qbs-target-macos.html \ingroup platforms \title Building for macOS \brief Platform notes for macOS. This topic describes the \QBS features specific to macOS. \include qbs-target-apple-common.qdocinc xcode \include qbs-target-apple-common.qdocinc building user interfaces \include qbs-target-apple-common.qdocinc creating app bundles \include qbs-target-apple-common.qdocinc architectures and variants \section1 Building macOS Disk Images The \l{AppleDiskImage} and \l{AppleApplicationDiskImage} items have a dependency on the \l{dmg} module. The former represents a product that is a basic Apple disk image, while the latter extends the former to create a drag 'n' drop disk image installer used for installing single application bundles. For example, the following code snippet creates a macOS disk image with a custom background and icon layout: \code AppleApplicationDiskImage { targetName: "cocoa-application-" + version version: "1.0" files: [ "CocoaApplication/dmg.iconset", "CocoaApplication/en_US.lproj/LICENSE", // comment out the following line to use a solid-color background // (see dmg.backgroundColor below) "CocoaApplication/background*" ] dmg.backgroundColor: "#41cd52" dmg.badgeVolumeIcon: true dmg.iconPositions: [ {"x": 200, "y": 200, "path": "Cocoa Application.app"}, {"x": 400, "y": 200, "path": "Applications"} ] dmg.windowX: 420 dmg.windowY: 250 dmg.windowWidth: 600 dmg.windowHeight: 422 // this includes the macOS title bar height of 22 dmg.iconSize: 64 } \endcode \image qbs-dmg.png In addition, \QBS supports multi-language license agreement prompts that appear when the DMG is opened, with full Unicode and rich-text formatting support. */ qbs-src-1.13.1/doc/targets/qbs-target-platforms.qdoc000066400000000000000000000041301347155106100223140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \previouspage installing-files.html \group platforms \nextpage shell.html \title Target Platforms \QBS has built-in support for building applications for all major platforms. Platform support is implemented as a set of \l{List of Modules}{modules} that products depend on. The following topics describe the features specific to a particular platform, point out things to look out for, and provide tips for fully benefiting from the \QBS functions. In addition to the platforms explicitly listed below, \QBS should generally work on other UNIX and Unix-like platforms but these are not regularly tested or officially supported. \QBS recognizes the existence of at least AIX, HP-UX, Solaris, FreeBSD, NetBSD, OpenBSD, GNU Hurd, and Haiku, but provides no explicit support (except some minimal support for FreeBSD). */ qbs-src-1.13.1/doc/targets/qbs-target-qnx.qdoc000066400000000000000000000052621347155106100211220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page qbs-target-qnx.html \ingroup platforms \title Building for QNX \brief Platform notes for QNX. To develop applications for the QNX Neutrino RTOS, you need to install the QNX Software Development Platform (SDP) on a Linux, macOS, or Windows development host. You can deploy the QNX Neutrino RTOS on a target system, such as embedded hardware, a virtual machine, or a PC. \QBS automatically determines the location of the SDP base directory if the SDP is installed at one of the standard locations, such as \c ~/qnx700, \c /opt/qnx700, or \c C:\qnx700. In addition, \QBS uses the SDP and the information it has about the host operating system to determine the location of the QNX host and target directories. If the QNX SDP path could not be determined automatically, you must add a dependency to the \l{qnx} module to your application and set the \l{qnx::sdkDir}{qnx.sdkDir} property: \code Application { name: "helloworld" files: "main.cpp" Depends { name: "cpp" } Depends { name: "qnx" } qnx.sdkDir: "/path/to/qnx700" } \endcode Alternatively, you can set the \c qnx.sdkDir property in a profile or on the command line. \QBS supports QNX SDP version 6.5 and above. For more information about developing applications for the QNX Neutrino RTOS, see the \l{http://www.qnx.com/developers/docs/} {QNX Product Documentation}. */ qbs-src-1.13.1/doc/targets/qbs-target-tvos.qdoc000066400000000000000000000032451347155106100213060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page qbs-target-tvos.html \ingroup platforms \title Building for tvOS \brief Platform notes for tvOS. This topic describes the \QBS features specific to tvOS. \include qbs-target-apple-common.qdocinc xcode \include qbs-target-apple-common.qdocinc building user interfaces \include qbs-target-apple-common.qdocinc creating app bundles \include qbs-target-apple-common.qdocinc architectures and variants */ qbs-src-1.13.1/doc/targets/qbs-target-vxworks.qdoc000066400000000000000000000032041347155106100220310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page qbs-target-vxworks.html \ingroup platforms \title Building for VxWorks \brief Platform notes for VxWorks. The Wind River VxWorks RTOS is not yet supported but is planned for a future release. For more information about developing applications for the WindRiver VxWorks RTOS, see the \l{https://www.windriver.com/products/vxworks/} {VxWorks Product Documentation}. */ qbs-src-1.13.1/doc/targets/qbs-target-watchos.qdoc000066400000000000000000000032611347155106100217610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page qbs-target-watchos.html \ingroup platforms \title Building for watchOS \brief Platform notes for watchOS. This topic describes the \QBS features specific to watchOS. \include qbs-target-apple-common.qdocinc xcode \include qbs-target-apple-common.qdocinc building user interfaces \include qbs-target-apple-common.qdocinc creating app bundles \include qbs-target-apple-common.qdocinc architectures and variants */ qbs-src-1.13.1/doc/targets/qbs-target-windows.qdoc000066400000000000000000000060501347155106100220020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \contentspage index.html \page qbs-target-windows.html \ingroup platforms \title Building for Windows \brief Platform notes for Windows. This topic describes the \QBS features specific to Windows. \note \QBS does not currently support building applications using .NET technologies and languages such as C#, F#, and Visual Basic. At this time we recommend that you use MSBuild and the tools shipped with the various implementations of the .NET platform. \section1 Windows Resources The \l{ico} module contains rules and properties for building Windows icon (.ico) and cursor (.cur) files from a set of raw PNGs. \section1 Universal Windows Platform Building applications for the Universal Windows Platform is currently only partially supported. Notably, support for building APPX packages is missing, but will be added in a future release. Relevant properties include: \list \li \l{cpp::windowsApiFamily}{cpp.windowsApiFamily} \li \l{cpp::windowsApiAdditionalPartitions} {cpp.windowsApiAdditionalPartitions} \li \l{cpp::requireAppContainer}{cpp.requireAppContainer} \endlist See the \l{cpp} module for more information. \note \QBS does not (and will not) support building Windows Runtime applications targeting Windows 8 or Windows 8.1. We encourage users to instead build desktop applications for older versions of Windows, or migrate to Windows 10 and the Universal Windows Platform. \section1 Building Windows Installers The following modules contain properties and rules for building Windows installers using a number of different technologies: \list \li \l{innosetup} - Inno Setup \li \l{nsis} - Nullsoft Scriptable Install System \li \l{wix} - Windows Installer XML Toolset \endlist */ qbs-src-1.13.1/docker/000077500000000000000000000000001347155106100144215ustar00rootroot00000000000000qbs-src-1.13.1/docker/docker.qbs000066400000000000000000000014251347155106100164010ustar00rootroot00000000000000import qbs Project { Product { Depends { name: "docker"; required: false } name: "qbs-docker-stretch" type: ["docker.docker-image"] builtByDefault: false condition: docker.present docker.imageTag: "qbsbuild/qbsdev:stretch" files: [ "stretch/Dockerfile", "stretch/qtifwsilent.qs", ] } Product { Depends { name: "docker"; required: false } name: "qbs-docker-windowsservercore" type: ["docker.docker-image"] builtByDefault: false condition: docker.present docker.imageTag: "qbsbuild/qbsdev:windowsservercore" files: [ "windowsservercore/Dockerfile", "windowsservercore/qtifwsilent.qs", ] } } qbs-src-1.13.1/docker/stretch/000077500000000000000000000000001347155106100160755ustar00rootroot00000000000000qbs-src-1.13.1/docker/stretch/Dockerfile000066400000000000000000000021061347155106100200660ustar00rootroot00000000000000FROM debian:9 LABEL Description="Debian development environment for Qbs with Qt 5.9 and various dependencies for testing Qbs modules and functionality" # Dependencies of the Qt offline installer RUN apt-get -y update && apt-get install -y \ curl \ libdbus-1-3 \ libexpat1 \ libfontconfig1 \ libfreetype6 \ libgl1-mesa-glx \ libglib2.0-0 \ libx11-6 \ libx11-xcb1 COPY qtifwsilent.qs qtifwsilent.qs RUN curl -L -O 'https://download.qt.io/official_releases/qt/5.9/5.9.3/qt-opensource-linux-x64-5.9.3.run' && \ chmod +x qt-opensource-linux-x64-5.9.3.run && \ QT_INSTALL_DIR=/usr/local/Qt ./qt-opensource-linux-x64-5.9.3.run --platform minimal --script qtifwsilent.qs && \ rm -f qt-opensource-linux-x64-5.9.3.run ENV QTDIR /usr/local/Qt/5.9.3/gcc_64 ENV PATH="/usr/local/Qt/Tools/QtCreator/bin:${PATH}" RUN ls "$QTDIR" && stat "$QTDIR/lib/libQt5Script.so" && qbs --version RUN apt-get -y update && apt-get install -y \ g++ \ gcc \ git \ help2man \ python-pip RUN pip install beautifulsoup4 lxml # for building the documentation qbs-src-1.13.1/docker/stretch/qtifwsilent.qs000066400000000000000000000032171347155106100210160ustar00rootroot00000000000000function Controller() { installer.autoRejectMessageBoxes(); installer.installationFinished.connect(function() { gui.clickButton(buttons.NextButton); }) } Controller.prototype.WelcomePageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.CredentialsPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.IntroductionPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.TargetDirectoryPageCallback = function() { gui.currentPageWidget().TargetDirectoryLineEdit.setText(installer.environmentVariable("QT_INSTALL_DIR")); gui.clickButton(buttons.NextButton); } Controller.prototype.ComponentSelectionPageCallback = function() { var widget = gui.currentPageWidget(); widget.deselectAll(); widget.selectComponent("qt.593.gcc_64"); widget.selectComponent("qt.593.qtscript"); gui.clickButton(buttons.NextButton); } Controller.prototype.LicenseAgreementPageCallback = function() { gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true); gui.clickButton(buttons.NextButton); } Controller.prototype.StartMenuDirectoryPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.ReadyForInstallationPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.FinishedPageCallback = function() { var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm; if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) checkBoxForm.launchQtCreatorCheckBox.checked = false; gui.clickButton(buttons.FinishButton); } qbs-src-1.13.1/docker/windowsservercore/000077500000000000000000000000001347155106100202135ustar00rootroot00000000000000qbs-src-1.13.1/docker/windowsservercore/Dockerfile000066400000000000000000000037431347155106100222140ustar00rootroot00000000000000FROM microsoft/windowsservercore:10.0.14393.1884 LABEL Description="Windows Server Core development environment for Qbs with Qt 5.9, Chocolatey and various dependencies for testing Qbs modules and functionality" # Disable crash dialog for release-mode runtimes RUN reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting" /v Disabled /t REG_DWORD /d 1 /f RUN reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting" /v DontShowUI /t REG_DWORD /d 1 /f COPY qtifwsilent.qs C:\qtifwsilent.qs RUN powershell -NoProfile -ExecutionPolicy Bypass -Command \ $ErrorActionPreference = 'Stop'; \ $Wc = New-Object System.Net.WebClient ; \ $Wc.DownloadFile('https://download.qt.io/official_releases/qt/5.9/5.9.3/qt-opensource-windows-x86-5.9.3.exe', 'C:\qt.exe') ; \ Echo 'Downloaded qt-opensource-windows-x86-5.9.3.exe' ; \ $Env:QT_INSTALL_DIR = 'C:\\Qt' ; \ Start-Process C:\qt.exe -ArgumentList '--verbose --script C:/qtifwsilent.qs' -NoNewWindow -Wait ; \ Remove-Item C:\qt.exe -Force ; \ Remove-Item C:\qtifwsilent.qs -Force ENV QTDIR C:\\Qt\\5.9.3\\msvc2015 ENV QTDIR64 C:\\Qt\\5.9.3\\msvc2015_64 RUN dir "%QTDIR%" && dir "%QTDIR64%" && dir "%QTDIR%\bin\Qt5Script.dll" && dir "%QTDIR64%\bin\Qt5Script.dll" RUN @powershell -NoProfile -ExecutionPolicy Bypass -Command \ $Env:chocolateyVersion = '0.10.8' ; \ $Env:chocolateyUseWindowsCompression = 'false' ; \ "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" RUN choco install -y python2 --version 2.7.14 && refreshenv && python --version && pip --version RUN choco install -y qbs --version 1.9.1 && qbs --version RUN choco install -y unzip --version 6.0 && unzip -v RUN choco install -y visualcpp-build-tools --version 14.0.25420.1 && dir "%PROGRAMFILES(X86)%\Microsoft Visual C++ Build Tools" RUN choco install -y zip --version 3.0 && zip -v # for building the documentation RUN pip install beautifulsoup4 lxml qbs-src-1.13.1/docker/windowsservercore/qtifwsilent.qs000066400000000000000000000035131347155106100231330ustar00rootroot00000000000000function Controller() { installer.autoRejectMessageBoxes(); installer.installationFinished.connect(function() { gui.clickButton(buttons.NextButton); }) } Controller.prototype.WelcomePageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.CredentialsPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.IntroductionPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.TargetDirectoryPageCallback = function() { gui.currentPageWidget().TargetDirectoryLineEdit.setText(installer.environmentVariable("QT_INSTALL_DIR")); gui.clickButton(buttons.NextButton); } Controller.prototype.ComponentSelectionPageCallback = function() { var widget = gui.currentPageWidget(); widget.deselectAll(); widget.selectComponent("qt.593.win32_msvc2015"); widget.selectComponent("qt.593.win64_msvc2015_64"); widget.selectComponent("qt.593.qtscript"); widget.selectComponent("qt.tools.vcredist_msvc2015_x86"); widget.selectComponent("qt.tools.vcredist_msvc2015_x64"); gui.clickButton(buttons.NextButton); } Controller.prototype.LicenseAgreementPageCallback = function() { gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true); gui.clickButton(buttons.NextButton); } Controller.prototype.StartMenuDirectoryPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.ReadyForInstallationPageCallback = function() { gui.clickButton(buttons.NextButton); } Controller.prototype.FinishedPageCallback = function() { var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm; if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) checkBoxForm.launchQtCreatorCheckBox.checked = false; gui.clickButton(buttons.FinishButton); } qbs-src-1.13.1/examples/000077500000000000000000000000001347155106100147705ustar00rootroot00000000000000qbs-src-1.13.1/examples/app-and-lib/000077500000000000000000000000001347155106100170545ustar00rootroot00000000000000qbs-src-1.13.1/examples/app-and-lib/app/000077500000000000000000000000001347155106100176345ustar00rootroot00000000000000qbs-src-1.13.1/examples/app-and-lib/app/app.qbs000066400000000000000000000050631347155106100211270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs 1.0 Product { type: "application" consoleApplication: true files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "mylib" } } qbs-src-1.13.1/examples/app-and-lib/app/main.cpp000066400000000000000000000050021347155106100212610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main() { puts("Now calling a function from mylib:"); return bla(); } qbs-src-1.13.1/examples/app-and-lib/app_and_lib.qbs000066400000000000000000000047561347155106100220270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs 1.0 Project { references: [ "app/app.qbs", "lib/lib.qbs" ] } qbs-src-1.13.1/examples/app-and-lib/lib/000077500000000000000000000000001347155106100176225ustar00rootroot00000000000000qbs-src-1.13.1/examples/app-and-lib/lib/lib.cpp000066400000000000000000000050321347155106100210740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE not defined #endif int bla() { puts("Hello World!"); return 2; } qbs-src-1.13.1/examples/app-and-lib/lib/lib.h000066400000000000000000000047051347155106100205470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef LIB_H #define LIB_H int bla(); #endif // LIB_H qbs-src-1.13.1/examples/app-and-lib/lib/lib.qbs000066400000000000000000000052641347155106100211060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs 1.0 Product { type: "staticlibrary" name: "mylib" files: [ "lib.cpp", "lib.h", ] Depends { name: 'cpp' } cpp.defines: ['CRUCIAL_DEFINE'] Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory] } } qbs-src-1.13.1/examples/cocoa-application/000077500000000000000000000000001347155106100203555ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication.qbs000066400000000000000000000052541347155106100243020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs import qbs.Utilities Project { references: [ "app.qbs" ] SubProject { filePath: "dmg.qbs" Properties { condition: Utilities.versionCompare(qbs.version, "1.9") >= 0 } } } qbs-src-1.13.1/examples/cocoa-application/CocoaApplication.xcodeproj/000077500000000000000000000000001347155106100255615ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication.xcodeproj/project.pbxproj000066400000000000000000000345071347155106100306460ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 14ABF7A71717761200140DA2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14ABF7A61717761200140DA2 /* Cocoa.framework */; }; 14ABF7B11717761200140DA2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 14ABF7AF1717761200140DA2 /* InfoPlist.strings */; }; 14ABF7B31717761200140DA2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 14ABF7B21717761200140DA2 /* main.m */; }; 14ABF7B71717761200140DA2 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 14ABF7B51717761200140DA2 /* Credits.rtf */; }; 14ABF7BA1717761200140DA2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14ABF7B91717761200140DA2 /* AppDelegate.m */; }; 14ABF7BD1717761300140DA2 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14ABF7BB1717761300140DA2 /* MainMenu.xib */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 14ABF7A31717761200140DA2 /* Cocoa Application.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Cocoa Application.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 14ABF7A61717761200140DA2 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 14ABF7A91717761200140DA2 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 14ABF7AA1717761200140DA2 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 14ABF7AB1717761200140DA2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 14ABF7AE1717761200140DA2 /* CocoaApplication-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CocoaApplication-Info.plist"; sourceTree = ""; }; 14ABF7B01717761200140DA2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 14ABF7B21717761200140DA2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 14ABF7B41717761200140DA2 /* CocoaApplication-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CocoaApplication-Prefix.pch"; sourceTree = ""; }; 14ABF7B61717761200140DA2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 14ABF7B81717761200140DA2 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 14ABF7B91717761200140DA2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 14ABF7BC1717761300140DA2 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 14ABF7A01717761200140DA2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 14ABF7A71717761200140DA2 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 14ABF79A1717761200140DA2 = { isa = PBXGroup; children = ( 14ABF7AC1717761200140DA2 /* CocoaApplication */, 14ABF7A51717761200140DA2 /* Frameworks */, 14ABF7A41717761200140DA2 /* Products */, ); sourceTree = ""; }; 14ABF7A41717761200140DA2 /* Products */ = { isa = PBXGroup; children = ( 14ABF7A31717761200140DA2 /* Cocoa Application.app */, ); name = Products; sourceTree = ""; }; 14ABF7A51717761200140DA2 /* Frameworks */ = { isa = PBXGroup; children = ( 14ABF7A61717761200140DA2 /* Cocoa.framework */, 14ABF7A81717761200140DA2 /* Other Frameworks */, ); name = Frameworks; sourceTree = ""; }; 14ABF7A81717761200140DA2 /* Other Frameworks */ = { isa = PBXGroup; children = ( 14ABF7A91717761200140DA2 /* AppKit.framework */, 14ABF7AA1717761200140DA2 /* CoreData.framework */, 14ABF7AB1717761200140DA2 /* Foundation.framework */, ); name = "Other Frameworks"; sourceTree = ""; }; 14ABF7AC1717761200140DA2 /* CocoaApplication */ = { isa = PBXGroup; children = ( 14ABF7B81717761200140DA2 /* AppDelegate.h */, 14ABF7B91717761200140DA2 /* AppDelegate.m */, 14ABF7BB1717761300140DA2 /* MainMenu.xib */, 14ABF7AD1717761200140DA2 /* Supporting Files */, ); path = CocoaApplication; sourceTree = ""; }; 14ABF7AD1717761200140DA2 /* Supporting Files */ = { isa = PBXGroup; children = ( 14ABF7AE1717761200140DA2 /* CocoaApplication-Info.plist */, 14ABF7AF1717761200140DA2 /* InfoPlist.strings */, 14ABF7B21717761200140DA2 /* main.m */, 14ABF7B41717761200140DA2 /* CocoaApplication-Prefix.pch */, 14ABF7B51717761200140DA2 /* Credits.rtf */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 14ABF7A21717761200140DA2 /* Cocoa Application */ = { isa = PBXNativeTarget; buildConfigurationList = 14ABF7C01717761300140DA2 /* Build configuration list for PBXNativeTarget "Cocoa Application" */; buildPhases = ( 14ABF79F1717761200140DA2 /* Sources */, 14ABF7A01717761200140DA2 /* Frameworks */, 14ABF7A11717761200140DA2 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "Cocoa Application"; productName = CocoaApplication; productReference = 14ABF7A31717761200140DA2 /* Cocoa Application.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 14ABF79B1717761200140DA2 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0460; ORGANIZATIONNAME = "Petroules Corporation"; }; buildConfigurationList = 14ABF79E1717761200140DA2 /* Build configuration list for PBXProject "CocoaApplication" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 14ABF79A1717761200140DA2; productRefGroup = 14ABF7A41717761200140DA2 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 14ABF7A21717761200140DA2 /* Cocoa Application */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 14ABF7A11717761200140DA2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 14ABF7B11717761200140DA2 /* InfoPlist.strings in Resources */, 14ABF7B71717761200140DA2 /* Credits.rtf in Resources */, 14ABF7BD1717761300140DA2 /* MainMenu.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 14ABF79F1717761200140DA2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 14ABF7B31717761200140DA2 /* main.m in Sources */, 14ABF7BA1717761200140DA2 /* AppDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 14ABF7AF1717761200140DA2 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 14ABF7B01717761200140DA2 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; 14ABF7B51717761200140DA2 /* Credits.rtf */ = { isa = PBXVariantGroup; children = ( 14ABF7B61717761200140DA2 /* en */, ); name = Credits.rtf; sourceTree = ""; }; 14ABF7BB1717761300140DA2 /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( 14ABF7BC1717761300140DA2 /* en */, ); name = MainMenu.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 14ABF7BE1717761300140DA2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.8; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; name = Debug; }; 14ABF7BF1717761300140DA2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.8; SDKROOT = macosx; }; name = Release; }; 14ABF7C11717761300140DA2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaApplication/CocoaApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaApplication/CocoaApplication-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Debug; }; 14ABF7C21717761300140DA2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaApplication/CocoaApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaApplication/CocoaApplication-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 14ABF79E1717761200140DA2 /* Build configuration list for PBXProject "CocoaApplication" */ = { isa = XCConfigurationList; buildConfigurations = ( 14ABF7BE1717761300140DA2 /* Debug */, 14ABF7BF1717761300140DA2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 14ABF7C01717761300140DA2 /* Build configuration list for PBXNativeTarget "Cocoa Application" */ = { isa = XCConfigurationList; buildConfigurations = ( 14ABF7C11717761300140DA2 /* Debug */, 14ABF7C21717761300140DA2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 14ABF79B1717761200140DA2 /* Project object */; } qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/000077500000000000000000000000001347155106100235655ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/AppDelegate.h000066400000000000000000000051141347155106100261120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import @interface AppDelegate : NSObject @property (nonatomic, assign) IBOutlet NSWindow *window; @end qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/AppDelegate.m000066400000000000000000000033741347155106100261250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "AppDelegate.h" @implementation AppDelegate @synthesize window = _window; - (void)dealloc { [super dealloc]; } - (void)applicationDidFinishLaunching:(NSNotification *) __unused aNotification { // Insert code here to initialize your application } @end qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication-Info.plist000066400000000000000000000022521347155106100307440ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile CFBundleIdentifier org.example.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} NSHumanReadableCopyright Copyright © 2014 Petroules Corporation. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass NSApplication qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication-Prefix.pch000066400000000000000000000030371347155106100307270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifdef __OBJC__ #import #endif qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/000077500000000000000000000000001347155106100306315ustar00rootroot00000000000000AppIcon.appiconset/000077500000000000000000000000001347155106100342475ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassetsContents.json000066400000000000000000000024241347155106100367410ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset{ "images" : [ { "size" : "16x16", "idiom" : "mac", "filename" : "icon_16x16.png", "scale" : "1x" }, { "size" : "16x16", "idiom" : "mac", "filename" : "icon_16x16@2x.png", "scale" : "2x" }, { "size" : "32x32", "idiom" : "mac", "filename" : "icon_32x32.png", "scale" : "1x" }, { "size" : "32x32", "idiom" : "mac", "filename" : "icon_32x32@2x.png", "scale" : "2x" }, { "size" : "128x128", "idiom" : "mac", "filename" : "icon_128x128.png", "scale" : "1x" }, { "size" : "128x128", "idiom" : "mac", "filename" : "icon_128x128@2x.png", "scale" : "2x" }, { "size" : "256x256", "idiom" : "mac", "filename" : "icon_256x256.png", "scale" : "1x" }, { "size" : "256x256", "idiom" : "mac", "filename" : "icon_256x256@2x.png", "scale" : "2x" }, { "size" : "512x512", "idiom" : "mac", "filename" : "icon_512x512.png", "scale" : "1x" }, { "size" : "512x512", "idiom" : "mac", "filename" : "icon_512x512@2x.png", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } }icon_128x128.png000066400000000000000000000122101347155106100367160ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset‰PNG  IHDR€€Ã>aËOIDATxÚí] |WÚ¿D"ŠR ÚŽF‹êbf|­òÍ7Ó–)ÃÐiƒh1šªÖZŒù™©©eø‰µ–Qû6öÝXcO¬„„ˆXƒ$d±ïÁùÎÿÍsÒãí}ßÜå½7÷ÆyüžŸäÞ÷ž÷ÍyþÏsžíœk³)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)Rä ³ÃÅ;ÌöæÏ¯À9sIÎÁÄ¥;ÅbÞ‚h>}BËKp~†sÎ/p®Æù%ÎÕ;Ř·9ÿŒsišWŸ>ÐZÞpÍß¿{è#¦Ø}æóY•¬B€/@æ¾´ýíM§+ÁY €_r~––Õ⾽𫿽¬ÉL%4ËðçŠ4Ï>côÂÿþ,%0à7œ«Ð2PÂðSá/UÂ÷ Þ&‡º´/@ ßûhDAòŠ)á?]hÌùçŠ+á+(á+(á+(á+x#½«„ÿ”@?RÕU’çé@ežž/ŒÜþgǾfߥNg²¶±C7Øù»iìòý,vãáMv5÷:K¿w‰%ß>Év_f 2V°oN`-ªàíÙ[(8ýâ|–z÷"s…î=ºÏ¢®îg=’ÿ¡`ö—¤ÄëÞø#Gû7»‘{“YE{¯Å°„Ï]~3zP‚Ì?  <ùÇ5köäD2OÐÕÜkì«ã³ïúø©@i*@4ôÔ†‰Üye/ó$Ý~x›…%õ±M8h‹: (@4òÔ6õâ<æ ºx/ƒ5oošÆµ-Ò`ºicOüQŸ$~Ŷ{¦ý˜ÿC0áü öyR_öqB{?.Dæ'G»±þ)CتËXæƒìA°äÒËðA|;wys¶ùºêÎYMèŽú3Ó²‡ŽwÿÑ @V ™“ÖD@Çm¾`¹&ÂJº•Âþÿ‰Óã=3V³F´0c¥%påÙ$ž‘¶Àprïòe!4ñK—Ç^›¹Ùpl$’õàÍÈÛ §"€“wÎN.èÎØí»š.=í$‰œ¥›oiIÁz«ãÌRóÔàÏG>34Óx½ó±ÞnßcOѼôen  úðHg#þöô(É;w÷‚%÷qv‚á=boñ8Zé¤`ijÓNܺ¬Í–Ü>„!dô4Zî `Ä[svN4תûå°Ìè8«Éj'±H åöiÉë–<À²ûÄßH4¼¾>`5Y'(R¸óè®áÄ}d¡÷l–h~v¼[a`«ÃØâÚ©0ÐùÊ_[ÓZ¾•U¶ùéË ï5ñüLU. À;6¢ì9–NÚä s ï…¦€B’4F”Æ+vVNÚÉŒè?Ü:(ä1¢3wR-´‘ç&Þkùåu …xßF”|û”¥“†Â­ÏÚªPèzü¯†“ŠðÐÊIvæ;·N @Ç£==žþ±Ét²á½Vò&€B@›„.†“Š>+'müyc'pñ¥Õ …€?îh^±tÒ¾¿0שР€WAm 'Bè÷³ê^‹2V=­‰ ùdÖbßI£ÂˆÜÙÈáL*B€|J+6ô–jÞ¼ùsÓ§Oç€~?G‹4î0êþFÔ7ePQ@1;ÛùĆžò=zô¨¿zõê-;w~ÑoÊÁCÐLGù½tÃû %½ˆ@¯õ8¥µÊ AƒÚ¯]»6‹kÿ€Á§07}‰áÄ.½ô_ËœM£¶3G‹Nfd¥¯â&ž8›¹råÊ5§M›6uÆ ¹öŸâ¿ã„Ñç| ÿ:3Îpbß}ZûüäÉ“£¹ŒÞ'í¯ê®ö*äbjö+xû6öøÁñ{ðø®$W{GȚр“à åtϦ±mÙçû¾f#vŽcK#–?!ôíÛ·³Ã‡kÞ¼=¡ƒ¯^½ÊV­ZÅx¦O»N>a ÆjÙ²å߸ŒÞÂaÞVh¿OÀŒõǽÁ‘¼m’·‡ÙöÖ¡NÆtb_ïù›¸m [»qíæ=**J[³áÈ]»vMc#áÃÛ_´hÌ»æèé…/œ¿9sæ$Q’èU«´ßçàlÿŸÖš±šy*” å¦ý›¨alö–yOh9{Bð˜xxî0ï.\ЄoÙ è—ü´.b|„yò2‹ñ<ËСC—q¹ü–JÄ©9IJoõ[€Çò†{»Ž&_˜Í£P‡»»‡ä{ñˆÓav!øÔÔT-Q´ à=¤uy¡GWŒ!¥,/ß«Y³f{”‡é0ïgm©´_ÊÙ<ð•ò~—ZÉxšVxö0ùHµBX€Ù2 [ý2 @€hβx²5‘­Š=@ <¤v¯h*ú ä[™Ú½­Ôþ§mb>Ï/Á" ƒ¹ ZqcbbØÌ™3µl “lU̱k×.Mû›5kÖG*ú”·"í«ÀyúÖÙšð¡™(»z+ _ rÁ0÷ðôaY˜dP™@<oã²hbeÑG‡VDwÏ_÷fz+ _ rñúš5kØüùó53.'Ë ˆBð|­[·`uÑÇl{±ÂŒ†EÂñCÍ Ð[gA\·xñb-̃ðÅx2° òx¶Ù³g'Ú)úyBûÄ·†!Çüë¢*|4]"Þ‡ãS AÙ³Î:ƒ&ãêÇ”Ç6^‡UÂÚò —ÃÛRѧ”•‰#”¢8³6íLiɹ-çO9w$îä‡üÎaœ»wêÔi!4 !– Ù 8ë ÂɃ³Ç ã ãÊãÛƒ¸'ºƒÈó‘´ÿy«Ó¾FßZŽ–ºÔpؘv©¼Kሿñû4™-8‡Ž7n& YcuQâΚæñ#€1ev¸I"žõ{À›=¿¢µ¿†ÕE3Gðºé ô¯€Æz~Æ(›¾N)TTÑþÄ×苘hÄç²\qѺÅ4´uÞ> ÙQ@ yÀ _OÀõÊÚoÏ ˆ]¨å¨èP™¤*™#â(ªAùôJ•*µ\¿~ý#N½eÀÌÄÏhÝâ;r5ó0É,ÀP Ðÿáó1oT«V-”,ou+>€A -¥È1,ã§\–’'h›®ÝªU«0L4´MÇÞ2`æ âuäôQÔð‘DB™XfgëQƒÀsõêÕk²´Í«²'ã~GO›*Aè§\RZÒjõîÝ{ &ûëd8º àzäôáé£ HfA°3€@ÉÏÄCôiN{ü«y2ëç Šé@áo\‚&¦ô¾Ùò;‘ý“µÑ‘eÝ;pöD@°+€]¾0ýuëÖ “¶x‹ŠŸWµ¿(Q1]d PgäÈ‘³0á·d“\Ð2€n „y°Ø¥#XÁ@P´Ã÷qÇŽéÜûªtÀCÉÂÒþ¢8³¯Ž=z1€M˜b{Ë€ ˜{$x ­!8Á2ô€Á Þß¼y³¦ýÇ_ËŸ­™þ—tI¥ý ˜PO)`ö¬xùòåZj€§dvøÛ»ðS§Nã]¾­©ÚW“Lieú­&öµQ£F-ÁÄc¿½ìŒé­^C1ž>„ë ¸ T ñ |üT–¶§D[m ³Ë*ÓïÀ=rÙ @H¼£­Ï>CfWŸ…Ç¿téÒÌ:uê|A!ß«”¯(/ÅüJû=€z‹ ìµ×‡dÖy8{0щÌ ®ÿ ³Ï—•œúõë÷ Ôúëºu_™~O`ðàÁÓD@—£ÍG’ù}€Af#0\/>îOd4hР'¥zߤl_Eµî{uû÷ï?Rde@@ØŽ !¬ƒ`A°+€À}ÄaN<’8]«V­.’ðAÏ%Ÿª„ï! P»k×®‡0P €àóê›æí£” Ë ³ g ­ÇaÆ Û„S¿(Ö“Šl?SÂ÷^kìË-Z´[½óÂÖ¾áCh`$}›Bƒ`,#Bðt|k:¿çP~ïV¶¼þŠ×Éì Í—=~ 8M2<ì*Th‚Ì›’<¾Ì¿ã}„u²ÐÁü€‡œ¾}ûÎ BeﶼΞº”㯨„ï]ˆ3õ1ù y¿^¦,,Tâ @´baiÀI‚!\0~†÷q­|R§tbçCžØIàG“¸àßÿÑ–·—¯>¬…zÈá RÂ÷‰&Ñëø/M@»5vÛê…è,sM¿ÂÏê‹éÖ­Û,îà!´ûØ–WÑC|ÿÒz˜|”vËI¡ž¾­€èu¬HéV´Z}À9¤^½z½xëu8ÿª•9ëÆŒ³‡Ã~€ÂÏm8Ês'8'ãw¼>dÈM}úôYضmÛ±¼q§tAÓ?²åµ›Á»G×ѯIð5tÈäë“Kÿ܃H“,ƒ‹UIEND®B`‚icon_128x128@2x.png000066400000000000000000000260501347155106100372770ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset‰PNG  IHDR\r¨f+ïIDATxÚí] ¼MÕþ¿2Fez¥'‘’¢P¯i¢áyõ„¡Òô"¥TÒø4hEÒ@t‘y“"óÉ£¶O´ªýâ 3é xE2• @H~¹©_\ŒíÀ±ƒbÄöñ1×í·ü¥­²m´•ßÞ^ó‘ïÁV ÀQÿX [úq;¾>×k«¿à>¹+˜³Ë°éÐV™vkä+¸}A  õü"ÆÕÿ±â••zíW¼.öÝÓu¾¹º‹¯ þ‚{)€Ôò™ŠÚC /Œ BɸV¸{Žîõ|­klHH,À+îXx?€ZÂ7öŠÃÇ‹6¿>ŸÔëÅç!²ïm—¿èh¸°%€ZÎÛ³ØóÜscßÀ¹,£wLò‘<@ ¤ŽHËy ®­Ü¿&eÍ,æ­>°ÎÓuï“ÁÎx—{ÒŸ @Êøé†>žÞ—V¾“ÒkmÕû ¿öDcë¡íÖlD›†‡;tÂëZÚŽ@HþöB©îeGςׂ!Ô)øAb‚¢ €çè?‚x^Ð}Cï@§/7Ëš€t€ûy‚@ðžW÷‚cÇù&z}×¢‡=Ç0"9îw`0+€à‰¶ ÷ôÐa¶¿Ÿîã·ý«<Ýú‚.Í—´¦P¼qþ^oþ?æóûé>pˆ Û66ðpÏN¡øxÐç>µÿ.{ÖW÷Òî·ÿyº%ìdüŽ&‹ÿK DÏf‹[yî­OöÀÍpDK­—8ÀAÙµˆLB1  j¢qÇ –Ésüüx?8k0>´ß‘ʳ(”ðzÚrýx?ßɓм™ €ßK‰)>ýÃÀ½åÿ{ùò~úÈ3 ½§Yø¼›àÓ? ÎÔóÙíÏŽÆ®žî§ÿ–a€£ÇžPì÷yŸþa¼–Ðúµð-Â^€±á© æÄt92ŒàÓ?Œ×`¿±DU_¢R<”V€)¼^€´™ŸÏ0ôLA¦P2J;ö´«úùaórz1Úo)€Œô{Áò?WùúaÛvx‡§ Z<üm  0Ðnù+iÑtr1Ц”Å5(€À¦áxÁÜ= }ý°aDYªªé(€À€×QZ3vÍöõÆãÀ5€@HxkM—”æÌýÖÞÜbÉc @æÀ»k»yzX'ü>Å×Û¬Ýó<ÝW<æêQ(Ô¿{ÁHŸ6ÙœúÇLO÷ë!¦ @  ëúÏ==¬C·ñõÃöíΩžî«Õ²ö @æÀ‡ëzzzXGlçë‡ 1 î(€0|omwOëØ“}ý°Mßõ³§ûºoÉã @æ€×Ã@±ÅöóÃ6GÖ)¤j°&€踺³§‡õÇ]3}ý°-Ú»”…@ @8¾ºê=O+Òl~~Ø~•ó ½ þ‚û(€ÌLõñ‚{—øúaózZð¿ç7£P2GZ/{ÎÓÊR[??l^§Åã¨p  0€±^^€f??l;ÿõ=a2çP2J0IÖ vÞéë‡íбèÇœm=´^K#À‰uæÞéy"­_‡UÂ÷6äd% øËàß4Rœèõ\ÀÛ´H«£Îâ•Ù ¤DL£Ï­Þû”fÍšyê©§ŠPâ<<ãþ_žH«±à~ÿž<p3üü’…[µjU~РAÕ×'b¸G: Òqõ‡žîç›­#(Á'ÃÇ{’<ãå—_®;|øðu¯¿þz-ùu € ‡mëéE'¡ïç‹Mý<ÝϧûP‚!N«þ)j•/*ù÷.]º<=räȃÙÙÙ_˯‹SB¾ Ú:Ê—÷3fÇ·žîç«Þ¥ø_B­úÅÊ—/_á‹/¾è;jÔ(!`ßí·ß~™üþé€|Ùã`Pœ)èÇûÁ ?©šDH˜8­úy•a#À÷÷FÕþæ›oÃøÁ®]»v’ß/-yšdA €kÔ¼µ§6^iÄ“HMî?v ê{9.ÿ*@ @B ¤¯/YFúùOJ¯müC† Y_ªT©ÊòßÎTPˆÂhpÔ—4\ØÒW÷âõ\ÀM‡¶Æí¼âƹ(‘­úùíUÿÊ+¯¬&·üCl÷پ}û'Õg•RP˜‚ËþüÍÓC‹sÒaÌùÌÝsãv Gd‘TªúÒHÜVý‚jÕÿÇsÏ=÷àСC·šÆß·oß¹òß/•,«àtîÂpÔö‰žÚÁ> bT™·€æÈ”Vá Ö €\aV}¼¦” ô]Ô£G^ÒØ™Æ/y¼iӦȟ»HòõYt5ÈoMAk¬÷to®î’ÒF$ ÑÂ(¡Wý³{ì±»daÏ÷سgÏïäÏ]!yv ’%”»À,@(6Yü_Ͼ+JoƒìÿÇëD X[‘ã•…ä×@§áG^¿T™2e*uëÖí3™Ú;êfü#FŒ8R§Næò竪Ï9 ©Aåÿ³0Ñ çŸoüÚ×ÿ™¼/Øyø_”V?¹üåL€"Ê(ó*ƒÏm¬ú…•ñ–‘¾~K¹ê¯v3|›;w%¾¦äÅ’çjÀ‚ªPˆЍ…÷‚ rÅ»anÔg2ÖØà± ¾§-Ù÷«§ëè´æãL€Ê0ó(!°·û0Ú³n»í¶k¾üòË1á ”)À•+W¾[¾îrÉóá.¨ ÀS5¡¡„"*á¼Ñ÷T^û‹+ßò|íñªŒu$y¼z|.ÔÊ\T{>e Õ÷JžuÖY|ðÁä–~$ÆvìØq€|íµ’U$Ë!E¨EÿOQ» @(Þ2ïnqÀc=vx}ªf¬Ø¿ÚÓuã~ã}Ç©Ié8f-P[­Î¶qžª¶úET°®¬Ìß?Év_çàÁƒ÷”.]º‘ þUTÁ?sõç<€HøÝÎižWÒÛǧ䚳7ñ|͉8à¤û†Þž®Õˆ÷Ä1éC¸VEçK+-®ì£ÌÃ?\ÿ믿žáÛ|á…zË÷¸NåþË©ê?sõ§D—<öØøD>üɼÞwdú†ã.{6î×ôÌo¯z¾hrsŠvRI€ëµrôå6lX÷óÏ?ê’ÓcÆŒ±bõßU¬X±†ò½®”¼0ÄꟋQŽê5`¯b½6 Hʸ0´#Çbüó÷.NÈuÝáq΢õ7Z É#KŸ±Î+Ä“vË_¯ÈxæàH7ˆ-ZŸ³· ñmg¦!7I¢;ï’ºuëÞòÙgŸ —F|ÔÍðçÌ™#f̘rõ—.ÃJX°ú—×jÿ «? Rv[ÿ¥ˆXÉÐd”ˆë»sáƒòøïŸb¾F”߯’Ç¿÷H¨ÑE5”½úýe€ï›áÏ›7OlÙ²ELŸ>¹}ëûÓ¦M;i'0pàÀß‹-zGˆÕß,2¢DBż–³ê@M!épÛüæ¾}¦þ3«…x÷Ýw' 6ì@(Ãß¾}»Ø¶m›˜2eŠÁ@KæÎ+–-[vÒkÚµk×SÚÕ šïÿ÷T®þi#± qŸ¸»JôÙ<ÈÚÖF:LÓ}QÓkS«Ç?–í¾H¢v'6Û¯x=ép÷¢G|÷5þéAñηňQ#·ðãÆ ,;vì»wï›6mãÇ2 hýû/¿ü"vîÜ)¦NzÂëdßÿŽSO=5ÒÕŸçDŸZk$Ví_›°‡õO¹Ã@Åܼ=‹¬N¼)2û0s÷ËuÀ÷÷Ý›°ÏWÂ(ŒòÚà~*%¾gÆŇ»‰‘£F:>Œ|Ñ¢Eâ÷ß· \³fÝ}¢W¯^bìØ±bÕªU–ñCÌ×·mÛ¶»æûûbõO+ûµCÜV]¿[ÿdgï]T8 P˜Êç¥îÏwŠ6SŸ½Æõq ÚMœ8Q,]ºTüñÇ>øë¯¿ 9¿OÈÞ~1a±~ýzËøAìô÷0`À¶ üG­þfÞ?¥§ ¥•Xñ†>icüëlŒË៑òÖyM’º €Û‘Šg¤áÌûÅKS:ŠAc»þwß}'~ûí7±k×® _Ã÷—ѧOË÷ߺuë_ÆDÃðý?S«ÿ%!Vÿ\€÷Øû Hm¦ÂG~ö·×’¶‹Jf9v9ÄÃÓžOü4dš¾ûêÕ«O0z›ØüðÃâÃ?ýúõ³R~ˆØÆ ÐßOw.\øcõ·;þR~Ö`Z âßîœXã_p“Õß߇ëz&EPè†+øöoL~W =ÄÕèÑÿùçŸ-ßÝÉðADûGÌÒyV¤«½nüàO?ýtÂ{wèСw‘ÿ\€üñûÊ(~а`ïñŸ÷ú¢ÂrïÑ} ½×î ªÂĿÔ×Dß±Ù!W{øî‹/¶ŒÛÍðíH¿ôã-ãGÐ1ÓðA¸ ½æÿŒ3Îhä×Õ?­Àæë«?»ì „ñ#íè§â˜ú î³…¼` ‡¯6}·k½mV3ñÌ/‹/Ƕ~»“ïDDúè{ÿý÷­×®\¹ÒÑøAˆ‰þ9ò¤Ÿ~~^ý3B¬‡cAó”ºD‹w¼%Žåôâ÷×~"«gzJw9~ÄJ•¢q 5(Æ9芌I fÝ+žùþeÑsü—®é;=‡m{¨m¾É%K–Xþ¾œ×o½^ô;qÒ¤I}žÜ)ì“mÂw9äý}³úgŒèiÂi»fù6U¸çÈ^kÕõûï±ñ¢‡¬©·×t=7öµjûAT=bƒ­=êÿŸ’EQ(`Šç®zOýð‚è1þó°Fíø?þh­Úf/gΜ)Þ~ûm!‡yŠÉ“'[¥¾¡Œß þÉ~ÿaÒ†nôóêŸq`óÞ%mÄðmã¬ÑZ~C¼NüMÞ0»¡¸wzkñêwo‹>ã²#j·…ÁbõçÛ»Eú±Ú¿ñÆBN÷±ïÊøAôh³þWªTé^iCW9TýùfõÏXÐ…(FÁd›å®ô<?Þx*Ígí…ííø¹‰h5õñþ¤®bpˆè}¬[|“H類_žÚƒYý®‘~“›7o>!ø'gýM–öSG û,ï×Õ?ãÀäMó‹VËÚ[i0´«~ÿÇ ñ‹œz³ãðNqèØáµúð1âãµÐòŠí|,íµ¸–ŒùÝϾCÜõÓCâÙï_‰hk¯WéÍž=ÛÊÛGÐ ElñQ؃•_Öí[;ˆp†osþüù'Ìù¿þúëÛHû¹Z²†‡ø¡æŸÇ1dèb«/Su¡NÆAŽ;ôŽc„ܼùç»Ä#²0çÉÅ7cE/m§–:é§ŒšèËÕŸ`>´´8vüXL€’Õ”ÈJ<ÔÝ>¾WÄ«<¶ö³fÍË—/·zíM?Ü€XEîÃ;?ÝÚY ~€Ï2Jô¶ßÞ½{/—vs‹š"TAôá4ë)²mtL®@<KŠ‹4ûn«æ=õƒÇDÀC=¢èX7lØ`ãl:b¬€×¡ÙG¦ê„<½Ç2bTñ¹}®› àZõûxðÁßQ“„/V3KŠøÊø)IšVK‡ªýP²PhÖ=¢Ý/‰" à!bÄ =äÏa|Xé‘nà €›DbüxLíyíµ×ħŸ~jí4ìÏÖ?פ“àµö=õïßsîܹëi}”Vçúvõ§$‰WwŽi0zÇ$ÿ­ô?ßm¥êB Ñ0ëîQ\ƒ>zlµaô¶áÛ´ÀMbuðy¨é‡ñ#âè½þ™&C ²zêïé§ŸþT¯¬ŽùÖOÊ›ìYŸq®œËäâ¶Ë_Jýæ9 åöþIñÑÄý·ß~kùÙˆª#W£±i €.áÀM"l×1¹Æ°ã nN 0@kúÙ-›~h§üê«>?ÿ(I&Jb?Ópºs§,zÿâ”7Dÿ1ß„Ý򣄮Ü]|LF"zן<äóÐyçw´—ªå÷l¿µüRüRü"‹ˆ6ÚÓtà¦I8Š«éŒGÂúöðéÃêŠíµM[t'n"K0ÿEÌAÚi¥ùtÄ5éŸïtáßÓG~É‚‰ªì×lúñýêOØ©ÀÀ¬Ýó:»Û÷‘Y˜|‹/0ú+)ÚcÁpà&ѸÑñ30xäø»wïnî %DÑ‚1ïÿxÍš5[©²_ß¶üR|F¯Çq£YiÂïSâ~:pÙwZt†»ÌÂÿþûïÅÂ… ­-> ߦ-n"à5h Þ}o½õ–5È©FóóM†ó!,FÙïMFÙ¯/›~(>â]‹ŽêXsü,š$â$Þ–ÓÙcû;>V{¤í`ø¨—·©¸‰@¢Ü\Ç!C¬`ê€ÿ¯¾› E*fÙoãÆ_RÙ/ÀGDÇ`8ì:²Û:¸4Ò“‰¢’ûæä÷\W|luaø6ÀM¢q¼MÀÐYŒcU÷¡¥ƪ_‡y-^‚hÿŽd»ðj—²__6ýP|7¹øN±öÀGÃßrh›øHž$|K‚ŽÝ®'+÷¾ßÛÑÇÇ¡HáÙthܯÁÀhܬô²ßÚöã>æsºŽXï©þ´nݺsÐÊ~)>#NûÕ¹y¨ý¯“ÀÁ Èé÷×ÏuP&ôpà&‰rÜj@øøÈñ¿÷Þ{Vá®M¿“^‰ú9 ¼=he¿ròÎÅ¢½KE‡Þù‡É¹ýÆ8Éø%G:ÆoÓI¢q¼#uðïØ’£™ƒ;a úu8]WA€{¡ÿ¾^|ñÅ>Ò>®“¬¤²_ €O1IJ Âì»ÏÀC.8Nâ ŒGM~«=òûHóáÜ)‚ ·üÊ!ûå´ßÆZÙïÙjõLêÃI>˜ôÑIÆÓp°òÛà&‰r¼Ôàsá‹£²C;‘ž4¯Å¤WAÀuã÷£ÿÎäçŽV³þWöKÈP¶ýáy×m$``Ï—Å'“ñœ-¨¯þõêÕ{F5ý8•ývõw€JjÑzº¬øÓ‡y`V5øµ‘ @*‚¨éGzi¾Z_ë׿vñôBèÂ)w ó²rNú©žYÿñ€ò€àq˜9¿.n"ªšló1´Ónè»â&RшA4‚€¯õc¾Àúõëw±úªì7(¬RÈq^Ec fðO¯÷Gä+i¤ì` þ?júáëãx.Ì´cúõ™L„  2R7~9Pd‰Öò{¾ZýÏH—Õ_€Üê† «Ê&(Ýe4¨àc½ô‡þ, Ê7HF0Ðü"ý]ºtù«¡G¿6“‰ûÞð<꾃 °ú_£­þ%ÓiõÏÒ.Þ€BÊ¿A{c%Uô€èç$ÑÑT²™d Å{É”ò>I”¦¶”|X²M‡&™Í>‘@²kðØ ¸«¿}hˆÉd ‚Þî«EþÓzõ7 ¯jh(ªÎUÊw¹ò0÷¼® ˆàs+™þKÇPý[ò6ÉúJ [ÊŠ¹ úöõò7HF0Ð|®=ºë«¯¾²Î°¯Ñ¼Îd\$}تþjÕªõ˜æû;µüæúêïȯ¹g©XÀ…ªóé2Õ‰Fˆ«Ôî€L kª‡óÕ—ŽúôÛ*Uªô¶®æö?”Ä#€šþììlËøéGÔ]¿F“¡Ä ‚€ÿÖb£æÿ[µÐ9­þ-û4PP튫/«ÒU±²«Iã%ª!¥šÚ¡An’§Ó¾oæþ‘þs2¨TÔ`z&õ"Ò:!¸>“É3ð'ûý\|ñÅ÷kUç¤ó꯻z6ÀbÊ8K5?œ£Áæ¹dJXNÕj\ R䨯—†5T˜ÑDã&ñFê࿈ô£¤‘~¤Ú°í†{bÓIb„Pbâõ¨4¦ýd«•]óoæýÓjõwÚäÕD °‚Ó•WyÐJÉä³”jCµE¹œÚ•Õ–yôEzé¯nX‰vÜ‚ø>R{(ëE]?jì±ò›`2‚`Ôû£ÝxSáÂ…ïP.n¥tÌûG*y”ÚåWÛžBJ «b!25,¢xšòIK*¨˜'OžÚ²„vŸ~2¯›Ñ$«&¯9r¤µåG¤I0|7&SPxdIiѢś*Ø}©*†;3ªþ¢qt!È«nþµ3 SÃüš T‚p†zH/GT5Òf¤µœvɪ Àçàî7ÞxCôéÓÇJGbå×J )ø”G뿯O>ùd¶Ê®\‘ur¿Ú¯þá„ ·&dj™×ˆÓÀ¨Ø²eË'Ìü¿i(^Ü/ÁÀE‹Ye½0~9BÛ þá{ )©}Ї=èó’K.yHeUªd<í'íW7Èå dê¨ïÊ hPI¯ÞÓjlqÝ ‘5ø\¹šþUÓ¿müNô*¡Ä ” @ŒÌ­Û¶m{¨;í¨#¾S!djø7‡¢-¸•å1Õýõ‡m´¦1$²&ÄÀŒê–×bEú‘ãÇu˜L• à=Œr_*²PT]¥2*vÑO`'ýé-ĺ`‹Š²íKemŠYè´&"ˆïaÖ V}¤ú0º )H€M'!H¶ }þÖÖ¿jÕª˜ów­ ü—îE?Dú@A%Ø®V“%µ ôÁŸºDãD ÄÏIC²ü}Dú‘ï7߉ÉE™[ÿÇ[ÿ›T1UE—ÀWÂw`Wl"E…ùt—Ëö*ûÁWh¯` ÞÇp¿öÚkV¤Fãw¢W1ˆ‡ àóÍ‚Ùì3++§â*UGaò‘±?"XPHmUá³^!ÄÞ¦×D"±a¸8”+?ŽãFÖ?nbLAÀÏ›C>dzr[éÒ¥ÑÕŠÓ}«[§À€ð¥S+W Y´_orò…ãåÀØÑ¿¹}(ôA==¢ÿ )©ÌÐ_ö ¹õÖ[Ñç_Gmý/P[»â?·`gN˜Þ$«kê]€(q %^ƒøÿ0(œË‡9ý(¦™={ö_ÆïÄd ‚nüf?øÌ3ÏôÎÊi«®¡Eý¹õ'+åK•*uƒþëà5h þ ?m¼ü±åf §îD?Œè=þ œ<4Mþ¾nÏÊéôCÁOyný‰  ÀI#ÜË–-{s$àÕ ÀÏÃÏG°í¼¨¤ÃÊoÓM‰A¢×dýdeâŠ"EŠÜ••“òC§Ÿ]ðè?h¨ û×ëE+‘º¤!Â`çĶ>¿.&S)ø Óøe9òŽŠ+>(W7fåTû!åg÷ùåÖŸªÀw­P½zõú¡À«ƒD¤Û~Œðš>}ºeüNL„ „'AÀkÌ&û\wÝu8Øùþ+”ßÀ)J¨íN?ný‰@ @~]d5ÛíúC@]¨Ê¸HjàCcZ/xØg ú¯ÓM R!x­™îÃl¿fÍšuRA?äû+;øýÜú€"¶œþùÿ2GG+º`ÃGY/ª QàAMðƒ 8?²">úh÷¬œ:ý0F ùþÒ.~?·þD àü’%KÖÑ~Là WïÖ*kGú?ûì31qâÄ¿ ߉¡Ä Y‚€Ÿw2þvíÚõV´øVUA?3ßO¿Ÿ´XA@Yp­nv)p4»üûàÁƒEÇŽ­C9±‹ÀÊoÒO‚€×a‡bæú_xá…Y9gYÔVû”qúÑï'°Or®5|øðƒ¶ å5\—œ.(šA¤+?Ò}pàóÛt‚X!”D"x³µ|ýõ×Ge圓€qéÕµˆ¿]ìàx0r¯) w»y`$»øÐÈí£º£º‘ãG´_“©¤"Í"eü£5ãG™/F{•ÍrŽø3èG^쓜¯–]y«tc@N<œÀð0½Ñ~øþ0,¿ý"fm¿íóËmÿ eü×+ãÇT_¤û00Å)âO¿ŸH Àüº²Òm9,Ô.Ó{`øèáGîÆ^~›nB*AÀû:ùûhîiݺuO?‘)pR3䲿}ªn0('ãGeêø1ºKž#h aü¦˜L• à¿Xõ¶ü2h¹·aƳr¢ý×fåTù™ÆÏt‘Ö€‡ýŸÒ G™cÁMãG°[}tòaZ/Ò…¶ñ;Ñ« „ƒhñ§@(Ó”Ëd 4ðÄ!©µCã§}€}ˆ+"Ü—Éy|Ù¡Š™«#¼ðïpL¦Zð5 ß,éÕ«û¤¿?8wîÜhìÁž8$µº ø9ÿ)4~"À‚üvÕ矾«[-â0únݺY<°¥†‘Ùt‚d ¾ër[ñUGß*Y×ÿ¼¼_ß…(ïÅ0O¤úÊfåDûiüDÆvT·U‘ƒŸH{0-ªVÆs•áÀˆ0üò6µ²6½ôÒKÛÉÕ¶ë³Ï>;HvýM…0H{ ‚mñ2rÔä÷ï߇tCVÊÓ§ËêׯÿŽôçÿ« ¾±ÚÞÿ[­ô0úÚjµGýþ¥ÊÇ¿À0üâj»j˜UŸÆOddÀ®,­bfå¤ËàG£Z¹s Èh Dáne”Í‹/þÈÕW_ý|½zõÞlҤɇ=ôP϶mÛfwèÐa¨ä0ƒCe>¾_«V­¾’u=7nܹN:ÿ«P¡¢õ-Ô{6QŸÑ@­ðÿR×p£ èÕR"£¯ª­öçi>~)ÃçªOP 7  Ú”P®ÚƒQ‰ò£k(1¸F ±®2Ê[”þ[k}µJƒ ]Ø@ý{}%*Øi ÿVõžu5c¿F}ö•Êà«©ëºH3úsÕj¦ hž¡mõ *‘s3|?‘±n€ ,¤‰rãç(㪨Œ­ŠZm«+C¼BåUÊ@k)c­­‚pש݃¯S¼V½¦–z«”Ø\¡>£ºÚÖWÑ ¾‚ÚÞŸ£ÄÊ6úbjµ/¢î¥@˜Ÿ†OP´X@>µZQ+hIe\ÿPÆVN ÂùÊ+)£¬¬ ôe¬UÕ*]]ãeŠú÷ª©Ÿ­ª^[E½×Eê½+ªÏ²WøsÔµœ¥üú†Ñ›«}^Ãð¹Ý'ˆ®€½( Œ Fuº2²ʧ>SàÙš0”UZN¹ç©Uº‚2`7VP?{žz]9õ^¶¡Ÿ­{)ÍàOW;•SÕJo}>Ãè¹âD®€-ön ¿2®ÂÊØŠ¨ÕötµC€1W†YRéß•HØBa³´Fýûgj^R½WqõÞghÆ^Ä0x}{o½ÛjOÃ'BpŠ¢-”RÔÅ¡ˆ2Ö¢J(l±p£ý3E #/¬¨{~ÃàVzÓèiøáAri•[„<šñéÂ`‹ƒ-4¡EýgókFžO{ÿ¼+¼nð4z‚H ä2ŒMStˆ–y æŽÐØiô‘D1'áÄÂͰÿ¡¡Óà "Â/AAAAàÿÉsÃ$tö3IEND®B`‚icon_16x16.png000066400000000000000000000007471347155106100365620ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset‰PNG  IHDR(-SêPLTEÿÿÿ¿¿¿®®®¶¶¶DÌUcÅn³³³µµµ´´´ºººµµµºÁ»¹¹¹ÅÅŹ¹¹AÍRAÍRtÇ~ÊÊÊÁÁÁÄÄÄAÍRBÍSLÊ\NÊ]OÑ_PÊ_PÑ`\Ôj]ÔlcÈocÖqdÖrkØx{܇|ÜˆŠÆ‘à˜¥Ê©©Ì®´Àµ½É¿ÀÓÃÆÆÆÇÇÇÈÈÈÊÊÊÌÌÌÌÓÌÍÍÍÎÏÎÏÏÏÏòÔÓó×ÕÕÕÕôØÖÖÖÖ×ÖררõÛØõÜÚÚÚÛöÞÜÜÜÜÝÜÜößÝÝÝÝöàßßßß÷âà÷ãáááâââãããèèèìúîÿÿÿ£\­tRNS,QVWZfßþw&(/Fì¿9éäL,ÜÝY%ÀíŸL+M‡–›ŽkL#6"(wäïIDATÕÁMKqÇñïoþÿÿÎÌÎn©(nùPƒ°ƒ!Ö±‡S"BèÔ¨K/ êЩSï k—.£§‹‚K ‹Ž™ëª³»ÓÌú\½>þ¢Cþ”z XrNÔ6 "ã•[ö:{¢8µ€+&á4ÿ`ðÀ…I4Í¿xXhu•©ÍAV`Ñ1M’3V›àHØcÁ¹@¹#«b¡åÈùRLOA¤Ô¶ÈZ1,›Ÿýœ££ ϲ£¢ò/Àá*R›™àG%ðØ¬ød|ê5çj5r^%²;õƒc›Íxìró£p¦0\¥´p’ÌØY{ÛË®pBú0Åæñåî<0UË®÷—õ.¼€Ò%åÖ#y5¨Ì)ró‹æüÌ•ê5[ÙÜ5æ“ǾïÏ>GSs7J¥F5Š ËÆ˜¦4Ùó8˜ ã`( ‡ŠÎÍâãdߣ0 6‚-ß÷{K7½¤Þrc¾$:$=ô¿®o:Ã-©º”Xh..÷ž¦C™p±>¡zTH}½ÛjbIYêJgéèŠËã­¾Rx4¾gçë)R☜e­ïœV¤ÕÙ©ûîMy­ HÙ– †Õ°DðòUA#síÄAêN'ÕñmDOã0²Ùó14¯»K}Ïg)™ßù>…ú^„Z°IEND®B`‚icon_256x256.png000066400000000000000000000260501347155106100367310ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset‰PNG  IHDR\r¨f+ïIDATxÚí] ¼MÕþ¿2Fez¥'‘’¢P¯i¢áyõ„¡Òô"¥TÒø4hEÒ@t‘y“"óÉ£¶O´ªýâ 3é xE2• @H~¹©_\ŒíÀ±ƒbÄöñ1×í·ü¥­²m´•ßÞ^ó‘ïÁV ÀQÿX [úq;¾>×k«¿à>¹+˜³Ë°éÐV™vkä+¸}A  õü"ÆÕÿ±â••zíW¼.öÝÓu¾¹º‹¯ þ‚{)€Ôò™ŠÚC /Œ BɸV¸{Žîõ|­klHH,À+îXx?€ZÂ7öŠÃÇ‹6¿>ŸÔëÅç!²ïm—¿èh¸°%€ZÎÛ³ØóÜscßÀ¹,£wLò‘<@ ¤ŽHËy ®­Ü¿&eÍ,æ­>°ÎÓuï“ÁÎx—{ÒŸ @Êøé†>žÞ—V¾“ÒkmÕû ¿öDcë¡íÖlD›†‡;tÂëZÚŽ@HþöB©îeGςׂ!Ô)øAb‚¢ €çè?‚x^Ð}Cï@§/7Ëš€t€ûy‚@ðžW÷‚cÇù&z}×¢‡=Ç0"9îw`0+€à‰¶ ÷ôÐa¶¿Ÿîã·ý«<Ýú‚.Í—´¦P¼qþ^oþ?æóûé>pˆ Û66ðpÏN¡øxÐç>µÿ.{ÖW÷Òî·ÿyº%ìdüŽ&‹ÿK DÏf‹[yî­OöÀÍpDK­—8ÀAÙµˆLB1  j¢qÇ –Ésüüx?8k0>´ß‘ʳ(”ðzÚrýx?ßɓм™ €ßK‰)>ýÃÀ½åÿ{ùò~úÈ3 ½§Yø¼›àÓ? ÎÔóÙíÏŽÆ®žî§ÿ–a€£ÇžPì÷yŸþa¼–Ðúµð-Â^€±á© æÄt92ŒàÓ?Œ×`¿±DU_¢R<”V€)¼^€´™ŸÏ0ôLA¦P2J;ö´«úùaórz1Úo)€Œô{Áò?WùúaÛvx‡§ Z<üm  0Ðnù+iÑtr1Ц”Å5(€À¦áxÁÜ= }ý°aDYªªé(€À€×QZ3vÍöõÆãÀ5€@HxkM—”æÌýÖÞÜbÉc @æÀ»k»yzX'ü>Å×Û¬Ýó<ÝW<æêQ(Ô¿{ÁHŸ6ÙœúÇLO÷ë!¦ @  ëúÏ==¬C·ñõÃöíΩžî«Õ²ö @æÀ‡ëzzzXGlçë‡ 1 î(€0|omwOëØ“}ý°Mßõ³§ûºoÉã @æ€×Ã@±ÅöóÃ6GÖ)¤j°&€踺³§‡õÇ]3}ý°-Ú»”…@ @8¾ºê=O+Òl~~Ø~•ó ½ þ‚û(€ÌLõñ‚{—øúaózZð¿ç7£P2GZ/{ÎÓÊR[??l^§Åã¨p  0€±^^€f??l;ÿõ=a2çP2J0IÖ vÞéë‡íбèÇœm=´^K#À‰uæÞéy"­_‡UÂ÷6äd% øËàß4Rœèõ\ÀÛ´H«£Îâ•Ù ¤DL£Ï­Þû”fÍšyê©§ŠPâ<<ãþ_žH«±à~ÿž<p3üü’…[µjU~РAÕ×'b¸G: Òqõ‡žîç›­#(Á'ÃÇ{’<ãå—_®;|øðu¯¿þz-ùu € ‡mëéE'¡ïç‹Mý<ÝϧûP‚!N«þ)j•/*ù÷.]º<=räȃÙÙÙ_˯‹SB¾ Ú:Ê—÷3fÇ·žîç«Þ¥ø_B­úÅÊ—/_á‹/¾è;jÔ(!`ßí·ß~™üþé€|Ùã`Pœ)èÇûÁ ?©šDH˜8­úy•a#À÷÷FÕþæ›oÃøÁ®]»v’ß/-yšdA €kÔ¼µ§6^iÄ“HMî?v ê{9.ÿ*@ @B ¤¯/YFúùOJ¯müC† Y_ªT©ÊòßÎTPˆÂhpÔ—4\ØÒW÷âõ\ÀM‡¶Æí¼âƹ(‘­úùíUÿÊ+¯¬&·üCl÷پ}û'Õg•RP˜‚ËþüÍÓC‹sÒaÌùÌÝsãv Gd‘TªúÒHÜVý‚jÕÿÇsÏ=÷àСC·šÆß·oß¹òß/•,«àtîÂpÔö‰žÚÁ> bT™·€æÈ”Vá Ö €\aV}¼¦” ô]Ô£G^ÒØ™Æ/y¼iӦȟ»HòõYt5ÈoMAk¬÷to®î’ÒF$ ÑÂ(¡Wý³{ì±»daÏ÷سgÏïäÏ]!yv ’%”»À,@(6Yü_Ͼ+JoƒìÿÇëD X[‘ã•…ä×@§áG^¿T™2e*uëÖí3™Ú;êfü#FŒ8R§Næò竪Ï9 ©Aåÿ³0Ñ çŸoüÚ×ÿ™¼/Øyø_”V?¹üåL€"Ê(ó*ƒÏm¬ú…•ñ–‘¾~K¹ê¯v3|›;w%¾¦äÅ’çjÀ‚ªPˆЍ…÷‚ rÅ»anÔg2ÖØà± ¾§-Ù÷«§ëè´æãL€Ê0ó(!°·û0Ú³n»í¶k¾üòË1á ”)À•+W¾[¾îrÉóá.¨ ÀS5¡¡„"*á¼Ñ÷T^û‹+ßò|íñªŒu$y¼z|.ÔÊ\T{>e Õ÷JžuÖY|ðÁä–~$ÆvìØq€|íµ’U$Ë!E¨EÿOQ» @(Þ2ïnqÀc=vx}ªf¬Ø¿ÚÓuã~ã}Ç©Ié8f-P[­Î¶qžª¶úET°®¬Ìß?Év_çàÁƒ÷”.]º‘ þUTÁ?sõç<€HøÝÎižWÒÛǧ䚳7ñ|͉8à¤û†Þž®Õˆ÷Ä1éC¸VEçK+-®ì£ÌÃ?\ÿ믿žáÛ|á…zË÷¸NåþË©ê?sõ§D—<öØøD>üɼÞwdú†ã.{6î×ôÌo¯z¾hrsŠvRI€ëµrôå6lX÷óÏ?ê’ÓcÆŒ±bõßU¬X±†ò½®”¼0ÄꟋQŽê5`¯b½6 Hʸ0´#Çbüó÷.NÈuÝáq΢õ7Z É#KŸ±Î+Ä“vË_¯ÈxæàH7ˆ-ZŸ³· ñmg¦!7I¢;ï’ºuëÞòÙgŸ —F|ÔÍðçÌ™#f̘rõ—.ÃJX°ú—×jÿ «? Rv[ÿ¥ˆXÉÐd”ˆë»sáƒòøïŸb¾F”߯’Ç¿÷H¨ÑE5”½úýe€ï›áÏ›7OlÙ²ELŸ>¹}ëûÓ¦M;i'0pàÀß‹-zGˆÕß,2¢DBż–³ê@M!épÛüæ¾}¦þ3«…x÷Ýw' 6ì@(Ãß¾}»Ø¶m›˜2eŠÁ@KæÎ+–-[vÒkÚµk×SÚÕ šïÿ÷T®þi#± qŸ¸»JôÙ<ÈÚÖF:LÓ}QÓkS«Ç?–í¾H¢v'6Û¯x=ép÷¢G|÷5þéAñηňQ#·ðãÆ ,;vì»wï›6mãÇ2 hýû/¿ü"vîÜ)¦NzÂëdßÿŽSO=5ÒÕŸçDŸZk$Ví_›°‡õO¹Ã@Åܼ=‹¬N¼)2û0s÷ËuÀ÷÷Ý›°ÏWÂ(ŒòÚà~*%¾gÆŇ»‰‘£F:>Œ|Ñ¢Eâ÷ß· \³fÝ}¢W¯^bìØ±bÕªU–ñCÌ×·mÛ¶»æûûbõO+ûµCÜV]¿[ÿdgï]T8 P˜Êç¥îÏwŠ6SŸ½Æõq ÚMœ8Q,]ºTüñÇ>øë¯¿ 9¿OÈÞ~1a±~ýzËøAìô÷0`À¶ üG­þfÞ?¥§ ¥•Xñ†>icüëlŒË៑òÖyM’º €Û‘Šg¤áÌûÅKS:ŠAc»þwß}'~ûí7±k×® _Ã÷—ѧOË÷ߺuë_ÆDÃðý?S«ÿ%!Vÿ\€÷Øû Hm¦ÂG~ö·×’¶‹Jf9v9ÄÃÓžOü4dš¾ûêÕ«O0z›ØüðÃâÃ?ýúõ³R~ˆØÆ ÐßOw.\øcõ·;þR~Ö`Z âßîœXã_p“Õß߇ëz&EPè†+øöoL~W =ÄÕèÑÿùçŸ-ßÝÉðADûGÌÒyV¤«½nüàO?ýtÂ{wèСw‘ÿ\€üñûÊ(~а`ïñŸ÷ú¢ÂrïÑ} ½×î ªÂĿÔ×Dß±Ù!W{øî‹/¶ŒÛÍðíH¿ôã-ãGÐ1ÓðA¸ ½æÿŒ3Îhä×Õ?­Àæë«?»ì „ñ#íè§â˜ú î³…¼` ‡¯6}·k½mV3ñÌ/‹/Ƕ~»“ïDDúè{ÿý÷­×®\¹ÒÑøAˆ‰þ9ò¤Ÿ~~^ý3B¬‡cAó”ºD‹w¼%Žåôâ÷×~"«gzJw9~ÄJ•¢q 5(Æ9芌I fÝ+žùþeÑsü—®é;=‡m{¨m¾É%K–Xþ¾œ×o½^ô;qÒ¤I}žÜ)ì“mÂw9äý}³úgŒèiÂi»fù6U¸çÈ^kÕõûï±ñ¢‡¬©·×t=7öµjûAT=bƒ­=êÿŸ’EQ(`Šç®zOýð‚è1þó°Fíø?þh­Úf/gΜ)Þ~ûm!‡yŠÉ“'[¥¾¡Œß þÉ~ÿaÒ†nôóêŸq`óÞ%mÄðmã¬ÑZ~C¼NüMÞ0»¡¸wzkñêwo‹>ã²#j·…ÁbõçÛ»Eú±Ú¿ñÆBN÷±ïÊøAôh³þWªTé^iCW9TýùfõÏXÐ…(FÁd›å®ô<?Þx*Ígí…ííø¹‰h5õñþ¤®bpˆè}¬[|“H類_žÚƒYý®‘~“›7o>!ø'gýM–öSG û,ï×Õ?ãÀäMó‹VËÚ[i0´«~ÿÇ ñ‹œz³ãðNqèØáµúð1âãµÐòŠí|,íµ¸–ŒùÝϾCÜõÓCâÙï_‰hk¯WéÍž=ÛÊÛGÐ ElñQ؃•_Öí[;ˆp†osþüù'Ìù¿þúëÛHû¹Z²†‡ø¡æŸÇ1dèb«/Su¡NÆAŽ;ôŽc„ܼùç»Ä#²0çÉÅ7cE/m§–:é§ŒšèËÕŸ`>´´8vüXL€’Õ”ÈJ<ÔÝ>¾WÄ«<¶ö³fÍË—/·zíM?Ü€XEîÃ;?ÝÚY ~€Ï2Jô¶ßÞ½{/—vs‹š"TAôá4ë)²mtL®@<KŠ‹4ûn«æ=õƒÇDÀC=¢èX7lØ`ãl:b¬€×¡ÙG¦ê„<½Ç2bTñ¹}®› àZõûxðÁßQ“„/V3KŠøÊø)IšVK‡ªýP²PhÖ=¢Ý/‰" à!bÄ =äÏa|Xé‘nà €›DbüxLíyíµ×ħŸ~jí4ìÏÖ?פ“àµö=õïßsîܹëi}”Vçúvõ§$‰WwŽi0zÇ$ÿ­ô?ßm¥êB Ñ0ëîQ\ƒ>zlµaô¶áÛ´ÀMbuðy¨é‡ñ#âè½þ™&C ²zêïé§ŸþT¯¬ŽùÖOÊ›ìYŸq®œËäâ¶Ë_Jýæ9 åöþIñÑÄý·ß~kùÙˆª#W£±i €.áÀM"l×1¹Æ°ã nN 0@kúÙ-›~h§üê«>?ÿ(I&Jb?Ópºs§,zÿâ”7Dÿ1ß„Ý򣄮Ü]|LF"zן<äóÐyçw´—ªå÷l¿µüRüRü"‹ˆ6ÚÓtà¦I8Š«éŒGÂúöðéÃêŠíµM[t'n"K0ÿEÌAÚi¥ùtÄ5éŸïtáßÓG~É‚‰ªì×lúñýêOØ©ÀÀ¬Ýó:»Û÷‘Y˜|‹/0ú+)ÚcÁpà&ѸÑñ30xäø»wïnî %DÑ‚1ïÿxÍš5[©²_ß¶üR|F¯Çq£YiÂïSâ~:pÙwZt†»ÌÂÿþûïÅÂ… ­-> ߦ-n"à5h Þ}o½õ–5È©FóóM†ó!,FÙïMFÙ¯/›~(>â]‹ŽêXsü,š$â$Þ–ÓÙcû;>V{¤í`ø¨—·©¸‰@¢Ü\Ç!C¬`ê€ÿ¯¾› E*fÙoãÆ_RÙ/ÀGDÇ`8ì:²Û:¸4Ò“‰¢’ûæä÷\W|luaø6ÀM¢q¼MÀÐYŒcU÷¡¥ƪ_‡y-^‚hÿŽd»ðj—²__6ýP|7¹øN±öÀGÃßrh›øHž$|K‚ŽÝ®'+÷¾ßÛÑÇÇ¡HáÙthܯÁÀhܬô²ßÚöã>æsºŽXï©þ´nݺsÐÊ~)>#NûÕ¹y¨ý¯“ÀÁ Èé÷×ÏuP&ôpà&‰rÜj@øøÈñ¿÷Þ{Vá®M¿“^‰ú9 ¼=he¿ròÎÅ¢½KE‡Þù‡É¹ýÆ8Éø%G:ÆoÓI¢q¼#uðïØ’£™ƒ;a úu8]WA€{¡ÿ¾^|ñÅ>Ò>®“¬¤²_ €O1IJ Âì»ÏÀC.8Nâ ŒGM~«=òûHóáÜ)‚ ·üÊ!ûå´ßÆZÙïÙjõLêÃI>˜ôÑIÆÓp°òÛà&‰r¼Ôàsá‹£²C;‘ž4¯Å¤WAÀuã÷£ÿÎäçŽV³þWöKÈP¶ýáy×m$``Ï—Å'“ñœ-¨¯þõêÕ{F5ý8•ývõw€JjÑzº¬øÓ‡y`V5øµ‘ @*‚¨éGzi¾Z_ë׿vñôBèÂ)w ó²rNú©žYÿñ€ò€àq˜9¿.n"ªšló1´Ónè»â&RшA4‚€¯õc¾Àúõëw±úªì7(¬RÈq^Ec fðO¯÷Gä+i¤ì` þ?júáëãx.Ì´cúõ™L„  2R7~9Pd‰Öò{¾ZýÏH—Õ_€Üê† «Ê&(Ýe4¨àc½ô‡þ, Ê7HF0Ðü"ý]ºtù«¡G¿6“‰ûÞð<꾃 °ú_£­þ%ÓiõÏÒ.Þ€BÊ¿A{c%Uô€èç$ÑÑT²™d Å{É”ò>I”¦¶”|X²M‡&™Í>‘@²kðØ ¸«¿}hˆÉd ‚Þî«EþÓzõ7 ¯jh(ªÎUÊw¹ò0÷¼® ˆàs+™þKÇPý[ò6ÉúJ [ÊŠ¹ úöõò7HF0Ð|®=ºë«¯¾²Î°¯Ñ¼Îd\$}تþjÕªõ˜æû;µüæúêïȯ¹g©XÀ…ªóé2Õ‰Fˆ«Ôî€L kª‡óÕ—ŽúôÛ*Uªô¶®æö?”Ä#€šþììlËøéGÔ]¿F“¡Ä ‚€ÿÖb£æÿ[µÐ9­þ-û4PP튫/«ÒU±²«Iã%ª!¥šÚ¡An’§Ó¾oæþ‘þs2¨TÔ`z&õ"Ò:!¸>“É3ð'ûý\|ñÅ÷kUç¤ó꯻z6ÀbÊ8K5?œ£Áæ¹dJXNÕj\ R䨯—†5T˜ÑDã&ñFê࿈ô£¤‘~¤Ú°í†{bÓIb„Pbâõ¨4¦ýd«•]óoæýÓjõwÚäÕD °‚Ó•WyÐJÉä³”jCµE¹œÚ•Õ–yôEzé¯nX‰vÜ‚ø>R{(ëE]?jì±ò›`2‚`Ôû£ÝxSáÂ…ïP.n¥tÌûG*y”ÚåWÛžBJ «b!25,¢xšòIK*¨˜'OžÚ²„vŸ~2¯›Ñ$«&¯9r¤µåG¤I0|7&SPxdIiѢś*Ø}©*†;3ªþ¢qt!È«nþµ3 SÃüš T‚p†zH/GT5Òf¤µœvɪ Àçàî7ÞxCôéÓÇJGbå×J )ø”G뿯O>ùd¶Ê®\‘ur¿Ú¯þá„ ·&dj™×ˆÓÀ¨Ø²eË'Ìü¿i(^Ü/ÁÀE‹Ye½0~9BÛ þá{ )©}Ї=èó’K.yHeUªd<í'íW7Èå dê¨ïÊ hPI¯ÞÓjlqÝ ‘5ø\¹šþUÓ¿müNô*¡Ä ” @ŒÌ­Û¶m{¨;í¨#¾S!djø7‡¢-¸•å1Õýõ‡m´¦1$²&ÄÀŒê–×bEú‘ãÇu˜L• à=Œr_*²PT]¥2*vÑO`'ýé-ĺ`‹Š²íKemŠYè´&"ˆïaÖ V}¤ú0º )H€M'!H¶ }þÖÖ¿jÕª˜ów­ ü—îE?Dú@A%Ø®V“%µ ôÁŸºDãD ÄÏIC²ü}Dú‘ï7߉ÉE™[ÿÇ[ÿ›T1UE—ÀWÂw`Wl"E…ùt—Ëö*ûÁWh¯` ÞÇp¿öÚkV¤Fãw¢W1ˆ‡ àóÍ‚Ùì3++§â*UGaò‘±?"XPHmUá³^!ÄÞ¦×D"±a¸8”+?ŽãFÖ?nbLAÀÏ›C>dzr[éÒ¥ÑÕŠÓ}«[§À€ð¥S+W Y´_orò…ãåÀØÑ¿¹}(ôA==¢ÿ )©ÌÐ_ö ¹õÖ[Ñç_Gmý/P[»â?·`gN˜Þ$«kê]€(q %^ƒøÿ0(œË‡9ý(¦™={ö_ÆïÄd ‚nüf?øÌ3ÏôÎÊi«®¡Eý¹õ'+åK•*uƒþëà5h þ ?m¼ü±åf §îD?Œè=þ œ<4Mþ¾nÏÊéôCÁOyný‰  ÀI#ÜË–-{s$àÕ ÀÏÃÏG°í¼¨¤ÃÊoÓM‰A¢×dýdeâŠ"EŠÜ••“òC§Ÿ]ðè?h¨ û×ëE+‘º¤!Â`çĶ>¿.&S)ø Óøe9òŽŠ+>(W7fåTû!åg÷ùåÖŸªÀw­P½zõú¡À«ƒD¤Û~Œðš>}ºeüNL„ „'AÀkÌ&û\wÝu8Øùþ+”ßÀ)J¨íN?ný‰@ @~]d5ÛíúC@]¨Ê¸HjàCcZ/xØg ú¯ÓM R!x­™îÃl¿fÍšuRA?äû+;øýÜú€"¶œþùÿ2GG+º`ÃGY/ª QàAMðƒ 8?²">úh÷¬œ:ý0F ùþÒ.~?·þD àü’%KÖÑ~Là WïÖ*kGú?ûì31qâÄ¿ ߉¡Ä Y‚€Ÿw2þvíÚõV´øVUA?3ßO¿Ÿ´XA@Yp­nv)p4»üûàÁƒEÇŽ­C9±‹ÀÊoÒO‚€×a‡bæú_xá…Y9gYÔVû”qúÑï'°Or®5|øðƒ¶ å5\—œ.(šA¤+?Ò}pàóÛt‚X!”D"x³µ|ýõ×Ge圓€qéÕµˆ¿]ìàx0r¯) w»y`$»øÐÈí£º£º‘ãG´_“©¤"Í"eü£5ãG™/F{•ÍrŽø3èG^쓜¯–]y«tc@N<œÀð0½Ñ~øþ0,¿ý"fm¿íóËmÿ eü×+ãÇT_¤û00Å)âO¿ŸH Àüº²Òm9,Ô.Ó{`øèáGîÆ^~›nB*AÀû:ùûhîiݺuO?‘)pR3䲿}ªn0('ãGeêø1ºKž#h aü¦˜L• à¿Xõ¶ü2h¹·aƳr¢ý×fåTù™ÆÏt‘Ö€‡ýŸÒ G™cÁMãG°[}tòaZ/Ò…¶ñ;Ñ« „ƒhñ§@(Ó”Ëd 4ðÄ!©µCã§}€}ˆ+"Ü—Éy|Ù¡Š™«#¼ðïpL¦Zð5 ß,éÕ«û¤¿?8wîÜhìÁž8$µº ø9ÿ)4~"À‚üvÕ矾«[-â0únݺY<°¥†‘Ùt‚d ¾ër[ñUGß*Y×ÿ¼¼_ß…(ïÅ0O¤úÊfåDûiüDÆvT·U‘ƒŸH{0-ªVÆs•áÀˆ0üò6µ²6½ôÒKÛÉÕ¶ë³Ï>;HvýM…0H{ ‚mñ2rÔä÷ï߇tCVÊÓ§ËêׯÿŽôçÿ« ¾±ÚÞÿ[­ô0úÚjµGýþ¥ÊÇ¿À0üâj»j˜UŸÆOddÀ®,­bfå¤ËàG£Z¹s Èh Dáne”Í‹/þÈÕW_ý|½zõÞlҤɇ=ôP϶mÛfwèÐa¨ä0ƒCe>¾_«V­¾’u=7nܹN:ÿ«P¡¢õ-Ô{6QŸÑ@­ðÿR×p£ èÕR"£¯ª­öçi>~)ÃçªOP 7  Ú”P®ÚƒQ‰ò£k(1¸F ±®2Ê[”þ[k}µJƒ ]Ø@ý{}%*Øi ÿVõžu5c¿F}ö•Êà«©ëºH3úsÕj¦ hž¡mõ *‘s3|?‘±n€ ,¤‰rãç(㪨Œ­ŠZm«+C¼BåUÊ@k)c­­‚pש݃¯S¼V½¦–z«”Ø\¡>£ºÚÖWÑ ¾‚ÚÞŸ£ÄÊ6úbjµ/¢î¥@˜Ÿ†OP´X@>µZQ+hIe\ÿPÆVN ÂùÊ+)£¬¬ ôe¬UÕ*]]ãeŠú÷ª©Ÿ­ª^[E½×Eê½+ªÏ²WøsÔµœ¥üú†Ñ›«}^Ãð¹Ý'ˆ®€½( Œ Fuº2²ʧ>SàÙš0”UZN¹ç©Uº‚2`7VP?{žz]9õ^¶¡Ÿ­{)ÍàOW;•SÕJo}>Ãè¹âD®€-ön ¿2®ÂÊØŠ¨ÕötµC€1W†YRéß•HØBa³´Fýûgj^R½WqõÞghÆ^Ä0x}{o½ÛjOÃ'BpŠ¢-”RÔÅ¡ˆ2Ö¢J(l±p£ý3E #/¬¨{~ÃàVzÓèiøáAri•[„<šñéÂ`‹ƒ-4¡EýgókFžO{ÿ¼+¼nð4z‚H ä2ŒMStˆ–y æŽÐØiô‘D1'áÄÂͰÿ¡¡Óà "Â/AAAAàÿÉsÃ$tö3IEND®B`‚icon_256x256@2x.png000066400000000000000000000645501347155106100373120ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset‰PNG  IHDRôxÔúi/IDATxÚíx\å•þϨYÕ²Üe[²Ü ˜^B ”dI²v—ì&dÙH²d—ä¿!Mo”¥‡P–j:Û€PmÍ4î6î½K¶z™™ÿ÷^ëÚ£ñ­SîÜ{çýù¹dI£;ºÝ÷=ç;ç|"„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„Øá%àï›Bò€8/¿[B!yo (ü}BÉC3@ÁÈŸß!ׄŠ<E!~wþî !ü”?z#@×ï-’æ×BH>ˆÜá׆ÚPÂ)ü‘M!„„ÝXý?žO&€BìßU$÷ù „äSôo$ôq‡F ”&€7ÿð¿ÕÇ"³„æ¨ßéÛ¼0¼ùWü“E=ùã½G¤÷­ÓŒ_#„ FøN#~ýýXÂáÄ„Îðælñ˜¼Á/VG‰:ú%˜§€¯ BH€•øÇ{E¿[êèêý²A½ (âë'âoíG’>VØ+þ'?}Î¥£*.åå$„C™wì¬a½âßc`"IoïÁ¡04ÁÿˆPÔ+þå'Ï>ûçJüÀËI!¦ KÚ.ÆYO+À É™øG,Ä¿â¤Yg_YZ_ù}^NB±Õ@}‰4fbÌîÕñ0üð$¸â_pˆøÏ<ëʲѕ—ðrBˆ-Ò·F*fòu¡ÌÐSü«û±æ_¢‰ÿ“g]QÖPEñ'„Ô @¢ °[÷¼! ð·ø'¿_`ùïÿ'”ø©º˜—“BSØ{D¢|£VëxXDŸ xâ_d ÅÿÄ'ÎúYÙXŠ?!„¤‘ˆ'e"a‹¿UÚ_ÿÊg|ágåc«¾ÇËI!)gtOºïÆmŒ@ M @pÄ_7Å"ˆÿ¸þBÉLÀÌ„€àˆrä9ÅŸBÒÎ$€˜É}X$„üýRüùBHf3ÉÙV»û7 ñXü×Äÿ»¼œ„’QP`q?¥ šø§øBH† €‘à;Ý95äžPü !$ß3f& æžøWüûQü !$«˜Üjm&ü¬ žŠÅŸB²zŸ¶~»{; aäO!¼WÛ¡ÍÐøWü/§øBˆ'÷k«È?´u4BÉ÷ @(#|Š?!„{•ÿ4B!yñÓPü !„ØÐgh(þ„Âûx¥þi(þ„BòŠ?!„ð^N@(þ„BhÅŸB ÅŸâO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü !„Š?!„B@ñ'„Bh(þ„B ÅŸB¡ øB!4B!„€âO!„ÐPü !„Š?!„’§€âO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü)þ„BhB þâ@ü+(þ„BhÂ!þâ@üKzÅÿgB!4Á6ÉQ…øWRü !„Ð;ú7ÿÅŸB @xÅß*åŸøŠ?!„€™»ŠÿbŠ?!„|¢(ÄÑ¿•ø§ýg(ñGñÏGUËÀâ2¸x ö¶º¨¿T–KyA™”«·eý$)Ð>vñ¸´D[µwÛbÒm“Öh»z¿]šº÷JcO“ìîn”=ÝMÒÔ³—›BEñ7ûX²(½Ú†jõ£ø‡ûÅ)’1eõ2¾¬AêJGʨ~µ2²÷()(öä9tźeSçÙÒ¹M½Ý*;6˪öµ²¶}£ôÄ{øK"„Ðd8`ý&EþßãË!\ RÑüQUSeZåT™T>^‰fr ŒÆØ²ÑÚ‘HO<ªLÀYÞö©,jY&7/–]Ý{øK$„Фý›-Àô;ñɳ~Z>¦Šâ’šüS«—ãú¥EøÁyî…2¡|Œv|yðÙÚÇ%xoßGòöÞ÷哿¥Òïæ/™Bà"ú1®þ‡(Uâ _Á¥@­Ë¯Äþ¬Ÿ“ûc¼FPFô.?ä‹ÚѦj ÞÝ·@^Þ󺼿ïc‰ªŒ!„Л³È?1PÄ—@0©í7L‹”Ïxš–ê;å…eòùšSµ£Q¾Òø†<³óÙ¬²„’¯ bò~òÇŒ¦þò%,&–“ó‡þœQó)Œä篯Fu)üÓÐ/Ë?=O4/’Y;ž“ù{?”¸úG!ùžH³À¾‚Á‘•Sä»#¾!‡WNæÅ8ð¢ŽÈ±UGjÇâ–år÷–‡eaËR^BHÞ€D±7ÿ3ÁÕò¼PNè4/†0F7Mü½V4xǦ鲮cc^^‡¹ÇÌôô|g,8Ÿ/>Bã?ù}#3À @€è§ï|}ØßË7†-ç­{AFéØÃŽ”§U}À=[‘v5˜ˆdóáÒ ¡ðy&ÀÊŸq\ÿiòßõ?”¡%ƒy1Rµ_Su§ 8^®^÷g. dt¡°#ƒöõbÑ7úxrôáKÀ_ÂõoµÈ5ãIñÏÃK†Ê'—Žú¶6g€d'@3Ì4€àÿnìåZ•?ɬ@!0¡|¬üz͵j/‚}¼(ͨ[ W39{7F ±äL¿ûó¤?Qü³È•‡É_&_# ¥u¼½ñðBhü(úÉ_c– 9ä´'ÉŸ'^%CŠñbd™Zµ$p«2Zh©$™ºòBhülÌZir ¦ÚýrÌO<Û‰ˆ¶µñ5ã!ǪBK’›L„·B„Ì€™ 9àì§Ëÿ4\–·Óür Z,ÿ0ö š€ŒÜlx !4~þˆCѧÈ!'U+?ýC­…ŠäÊ”ÈoÇüT«¿ éÜ@ù&4AÍÐx̤òñò«1ÿ‘¿ÀC÷?2¬d/Fª7.€@d„‘nÁ®}w¥”ª4ñËï¤Fk¿,ް#µ(o%„ ˆ†€FÀCñÿr̵숿ÀŒ€Žºˆ"¥ — !–|»ö_Ø~æc¾:ä\9½æ^f @^fH–˜R1I.öU^ŸsYÝÅ2šn%„ÐAè)üƒjó+. ]ÅK´Uš£-¡ú™úU)p _´Ì<û¬’¬rQí×eT¿y¾Û»vʆŽÍ²¥s›lÖŽ­Úû±Ni‹¶Kg¼SºbÝ}ÿˆÔvÅe¥RVXª8/&#û —êÀÛQ¥#Ô5¨ ÄÏÿ™'ÈçÔRÀëoóÅë$Â`¡t†€d ˆßùj#?³§»I©ír?l^(îûD¶vípý=zâ=Z6@ÏÀ@$3 ¨Z¦UM•#*&Ëá•“µÂ;¿‘AAà»{?ÔL±Ë°ŒŠÐr?ªûŽû Dòóß”gw½"+ÚVyrΦž½ZT­GÖÈœ9ð49{ÐéÚŒ~?}¾>ìäþ­ñEÌ ¡ Ä'ô?ZÇøê9­i_/³wþUæîyCÚc9}.›ÔÒÂô­Ë[gÈ©*íŽ"É©ªXÒ/àù<»ë%ÙÕ½‡/fË ¡ ä`T¤þ}{Ä¿øæù ­Ïæ‡UÔÿ–ÚºÝ_›·ãù¼Ùô®vœ\}œ\<òB]:*çÏ Å›ßþrÓÆÿã ÚòµÎ%dKH†9uÀñ2±|\ΟG4•G·Í–o/½L檔¿ßÄ?™wö~ ß[ö¹gË#‡æ‚/ >S4å ÚÊ0@h9ý£ò?× šÿ²•¿”»¶<$*fëQ¦åám3åÒWªe‚-9}.¨ßø×á_ã‹ÚòÊ[(¡ DãøþGÉØ²Ñ9}K[WÊ–_.KZWö:®j_+—,û©ªÆ_ÓçqŽ*Räp kÃK !Šú圞ÿ­½ïÉO>ý•ªºßøk‰BÅ_®¹Z[¾ÈØ$è˃Ïá Ûìʽ !¢EþÇö?2gç³é=ùíšë|±~ž)°$pÕº[r:˜ç«CΑ’îÈ ¡ Ä„¯¨H1W7Äm«åënÒ3l ˜?ÛÇÍKrr~ 1úLõ‰|fh Ésú©¸gülNν³{·\¹ê*öK%ð»µ×i?k.øÒà/ðEn˜à-”Ð<çój~|Ea¹ççEkßÕëþ¬MÚ ;¨køãÚ›$y~×ö6 É€’çœ;茜œ÷ÉÏÊGÍ‹òæ:/Tû<½ë…]D¾£ ¯ ‹ Ég”#*óü¼;ºvÉý[òo^=íÎÁˆÞ3jh½2@hHóùšSsRü‡Yú¹žéŸ °™ÑÃÛfy~ÞúÒ‘ÒPZÇ|b€€î@Òætµþï5ÛÔ|ÿ—÷¼ž·×üùݯÈ7Ô”>d_¼ý]ŸšÑ]ç33п‡KÕŽ—-ÑVíýBO•–Y~}YA™š°XhúùBõ¹²ÂRËïQQP~`þÀõn—çÔ®–„ÐÏT\#‡ULðü¼˜ñÆ–?§`ÖÁŒíÏÈF]äéy±a· >ȤïyÍAA( \ iqRõ±ž§AÑ ÷ÂîyyíŸQÛõzÝý0¾¼A{œu æÄ…€ÐqbÿcûÄO©˜äé91ò·#Äþ¤Ê¾žfYÚºÂÓsY9…Þ° €ÐÏ™P>FíXâé9ßÝû/¼ ìûØÓóM*Ï‹î8€ÐÏÉÅðŸš?æ…7á} ÀÐ’ÁR]ÔŸ>çÖâ1“˽5ë;6ÉÖÎí¼ð&¬l[ãùP q,Ì9¬ 4Ä{àqÀëw#Áo‹<¾|,/|® k ñ’ŠÂrÑo˜§ç\زŒÞ†Å-Ë==ß„²1¼èÌ’O ÜëA0+ÚVñÂûìM`ÀÖâ!cÊê==ßžî&NÿsÀêöuj@gç«+¡¶·-å…g€Ð¼É”z[üÅèߨ"xmûÏ·,Ðævâ)£ËFÑø”m«==ߘ²:^ôÂ9„€xJm‰·€^‹ZYéñµV2”=§B@<¢(R(ƒ‹zzÎ í›xá²±c‹Ç`/za ¡ žÞð "Þ½lºãݲ½›€NÙÔ¹ÕÓóÕ2[ÀB@¼b¸Çýÿ›;·1ÊqÁžîFO7LÞ€B@ò¯#¾M§´ƒªÂ·(Ó䃊k¤¤ ˜>‡¿oBR¥ˆ—€¸Šø<6;i\›&µ 0Ö£ö<´-ìùÒCØéŒuIW¼ËðsíÑUýÕÞïŠuñbâ‘ð8廹ƒÂâ÷k†×DªàŒçgô¹Ì=f¦§?û÷—_®½m¶®ÇÇãqõ¹6ÃÇ¢¾ÅËåBhHZxݸ½k'/ºKvx\49< W²E•ÖWxÝöµ§§‰Ý%»U! — e+ !4$Ü`½·º¨ÊÓsîêÞà ïÖ4u{kšª‹*yÑ ¡ aÛªA@^mZzZyá]Òèq ª°Šfú{ý#•Í6§®[Ç€BhH¸©*ôöFïõZvXÀ®€f•çY1†…4„Ðp€¢ OÏ×ÈÀ”ñ²€BhHÈ©.êïéùš¹þŸ2-Qï®3„аg<¾Ñ·y˜Æ^^»²Â2m—HB mÀÛ"À¶X;/z®ÚC+™ „€„—JÏ34©_»OÏןu„Ððâu`+ @o—O0#‚B@BJI¤$Ô"® €·æ©(ÂmE¡ ¡ÅëB/.¤cž¼½vÅ4„Ð0ooòÜ*5kíôøµQÌ‹N +^GyÑx”=Õk'Þ^;¶B@BL¡Ç ‡ 0æ‰K„Ð0g ˜ 03‡ÌB@B‹×iÞ˜Ð&PÀ !4$ÄÀë @Œ= ׎m€„ЀŒÑïáEȵ£ „€Ðd0Šå3„’ûKÄÛ—Kœ—|ï¥ ¾ÍÔ àEOþEURäá(`f „èkˆ‹HÏÛµÞŠÂr))(æ…wÉ£ÐÌ !¹þHºß„€8&¦¶|õºuî©öÚ0@ˆ_„?bq@ï‘,ê}?B@\±³k7 €ÏXìíÒIcO/:!Þˆ¿è[=z_|íµ×6ÜqÇ“ðâŠí];== ýŸØÝM@H¢~£›EþXK-»á†>7~üø~ýë_¯a qÉŽ®]žžoXÉ^t— -ì±ØÃ‹Nˆ·¿Óÿôê|Ùm·Ýö/uuu×.]ºô+Û·oëŸ$Ä· ¶d/ºK†÷ê±häE'$ûâŸñ'þß(ê‡ð÷Þ­Ž( qŸèö:0”ÝuÀ;ӄΦž}¼è„x/üñ×"ÿýèGÓN?ýô{úõë× oÛ·ßñàƒnÐÅ£ î2Þf¼NgÒ‚~ª°Ê³ó¡&€â™øGL>¦û•^wÝuÿn#øéFýHùk½ýßûÞ÷ŽRiÿëKKK'Ú=±… Þ¼víÚæ$ñ$ýŸsHj¬éðv`jÅ$^t&•óö5àñR¼6$EŒ¡ˆ3£à¶¯ÿ€ð«I~ý¯¿þú‹¿ò•¯<éDü[ZZýéOzNö§þãç8øúåý­—Ï 8Ù³óM«œÊ‹nwª¼½FkÚ7øîDU4î¥(E ùÂ#Y‹úQè÷­o}ëUíÿ§øõ×_¿A-tÊþ¡?¦âO@ýM®˜ ¹íˆuò ‰cËF{k;ü—ðÞðJ ¿•Ð×ú {ú•ÿæ7¿ùÊ´iÓ~S\\<ÀéIwíÚõúí·ßþaoôo6e€¤Çª¶užž‘ÖÔÊÉòá¾Oxñ 8¢ò0OG#Õ¾®}£/ €·¯KÞBC.ÞÉÛ|Ìn󻨿Ÿêé¯ýþ÷¿ÿó¡C‡þƒ«¿Éx<:{öì¿ÈÁyÿF™fHúlëÚ¡í?¨¸Æ³sb€ÀäÚxœþG(ºü†×yÈJ‘¼5 q ÃRÔ¯Úûþîè£þ•Šú‡¸}B›6mšóôÓO¯’ƒóþž[Ã"@’2KZWxz¾cªŽàE75GS¼ýÝ·¬ðåuð:P]ÔŸ/¾üÊ8ùœÝ4¿BIhíƒð«¨¿Nmâs½zûçTÄ_ ýéxàî‘ým1ƒçg€dX–ËiNòì|‡©:ìA€ì9ÈÐ’Á2¡|¬§ç\ܺܗע+Þí±¨â 0?Ì@b ÛÈ¿@æ‡飲_ÿú×ç!êWC}§ú?ýôÓ'ÔÌÿ­rèУè?®ÌÀˆÖ¸O«9™>‰ÓT7†—ëÿ`i«?3^/K0À ƒÈ?yQå¹çž;þÁ¼óøã¿%ñïîîÞ{ë­·>¤Þíƒ ,L3$uV¶­‘Öh›T–{vÎ3jN•ÛŸæÅOº&^‹¬ As· ?3at³¯‰'½5‹üÒÿšø«¾þ Uáÿ/S¦Lù………Õib‹?¬†þ4%Dÿ}¢|“Cû’2Xoý¸e±œZ}‚g眨†ÝŒêW+›:·ò À’ȤŠñžžs±ZúñëÀ–h‹§çÀ @ØMAÄøÛeŠzÅ¿ì’K.9öÌ3ÏüMyyyF š:::¶ßtÓM³¥ïÚÜ©àI‹÷-ôüœ_ø9^ø^>¯¢¯ÓÿïíûÈ·×£Ùã%€ý†óEžè߬]ÎIŸQ[Ÿ¶kŸ:Ê'MšTû—¿üåççwÞã™íoñ½÷¦«-[zÅ¿Otoù —HF @³÷my_|–<¼m¦t{\ðå7°ÓyêZxÍ;{?ð¯èñ60ºtoáüÅ&ò94ݯ‹¿Vä§ú\YRR’Q·¨Fþ®»á†^”ýkÿ1§Qâ×Ñ´ØØ±EKÇ#-ï5j0ÖYO“çw¿š××þ”ê㥶ß0Oω €¶wíôí5iìiòô|X‚éWP¢mEB1^óO½º_K÷_tÑE‡ŸuÖYWª1¾Y)ÒyõÕWïéééÁhÔ¨‰ÐÇ„K$Û¼Ýôžçç¼°öŸ¤8RœÇw¦ˆ|cø×ý'áµ9AfT¿¼ „KäTô'§úõêþ UÜ7ò¶ÛnûùùçŸ?;[â¿gÏž%wÝu×;rp»_+Ñ73DÒçͽÞ€a%Cä†~)o¯9Ú!'•ϋߵŸ À>$T&@Äù@]üËUuÍÕW_}‘Ú‰ïÕúúú‹#‘¬E(ñ§žzênõVþc‚Kÿä¯fHFÀT¸Æî&ÏÏ{QíZ 6ß@ÛåŒúwÏÏ‹ôÿòÖOi’8®êHÞÂaì?ñÐ…¿Týÿû¿ÿû¬‡zhÎá‡þ{ÕÓŸÕùè›7o~gÖ¬YKä`ß¿Ùa·À É€Uÿ^kzÛóóbûå£/ÕÒ°ùÄ¥£¾#ƒ‹z~Þ¿îžëûkÓØ½×óõø“ªótÉŠð»‰úuá¯ºà‚ ¦a˜Ïé§Ÿ~_YYÙ¤l?Y5ò7öøã?˜ý›¶4$#¼´ûõœœ÷(µ ο×~=o®ó!ç :ÝóóöÄ{äå=¯ûþúÀŒz=*E€7ø ¼ „'ú7Šøõ {4á?å”Sî¼óÎß|ó›ßœSSSs–ˆ7½¸7nüÛܹs×ÈÁÊÿ˜šú™üÿNvŒ°¢m•¬ïØ”“¶¨UÅp›U' »ç…úUu¸\VqNÎý¦*ôÜÛ³/×iUÛZÏ_‡ßv¾ÌÛó–ììÞÍ›A0Å?±°/Öû6±íO3‡vXÍ~ðƒ=zôEjŠ_¥—OTÿÑG}ô19tíßM@„K$+Y€=¯åè/8"?©ÿ|n@x÷ @¡ÙïÇþ,gOìx&0×jUûZÏÏYUT)¥Ö¢Jýø¡—¿bèСƒ®½öÚ謹—ÆŽ{i*â¯IEEEÊOtݺu¯¿ùæ›ëz£ÿ¨ðÛFÿÂ%’IþºëÕœ ç)ŠÊ/ÇüDÎU)òðEþSåºñ¿ÎÙ:óÇÍ‹e™Ï‹ÿú€u99ïø²1rÏa7ÈW†œ#å…eY9Gea… T&óÆ”Õó¦“ù @â†=åjxÏ5·ÿ몭ï9ÕÞ÷sµUï T„„ Ò¿imMmR¥Šþ{T­¢ÿ.é›þ7z'Ñ?'’ÌÒ¤Rį5¾­†ôäfT/Š/ýÒPZ'wmyÈó½á³Á—Ÿ#?ªû¶28¹ûS}tûì@]3,äŠEÕrYÝÅòƒ‘©Í²VkÙˆ]»´M³ÚcJe ´š˜¹õ…¬åR\P,å¥RVX*%‘Í@ôSŸÃ×Tª¯íÁû}³?øž_þäBÞxÒ¼mHßÊ~cú’Ë.»ìój§¾‹•€§Ôo ᯫ«“ÊòåË¥±±1õ×ôªUóÞÿ}ìÀÕ-Ö…vË}'þþI&yjç_sftþyØWäðÊÉrÕº›UmÀ¶@^G¤”!$Ÿ÷x§¿d>U;>¾¿ïã@];Ô*x=2ˆü•‡iG¶€IÀò—_7f P@/ð%üÅ—^zéi'tÒ·Uº>%áGšÔ¨Q2dÈéêê’… ˆüãñ¸¨ùÚûªk@¢Ñ¨ö56Ñ÷Ã?ü„Iô÷kÿÜ d¤Š?iY"Ó*§æôyL©˜(w«tì#*z}|ûSÒëÈÝ(¢¨‹G^¨¥zsÍÿmy(¯Ãj“ªQCjCý·†× 2mÑvÞxRGâ1¼øâ‹?ãŒ3¾[YY9.]á‡ÈCôÕV½šÀCèÕØ^QÂöüª*ihhE‹Ù›ðO?}õÃ?ÜÔk¢bßþç(úg€d…·>!Ó&LÍùó@ -‚_t¦<²m–ÖÇŽv6¿ÞÌOª>V¾UûÏjÂß8_<§ù{?T»=~È×àj“*¬Å‡ò‚2€4@1ßøÃÓN>ù䯩5ú1™~°k×.Y±b¢wlÙ«Eþˆø*(UHˆ–>Ûï­ŒC×ý÷ßè?¹ï?*©Uþ'þŸ€d!új^$KZWÈÔŠI¾x>üãúK4q}eÏßäEÕ.¸®c£/žÛ â9sàg土÷UQê'îØ<=°¯A.âg(Œ†úo µ»º÷ð¦ã’Uÿ>¹}¬\òðÃ׫ˆ?¥]úŒ„lÙ²EÖ¬Y£‰~SS“õëâšøÜŽöó*TíÀË*K€uÌnÑ·ë°ŒþiHÖ¸gË#rÄßúê9Al/öUíÀÜ /ZмP6tlötSüŽQãcÏø5Fvš/'>½óíº•–h«,jY®uP„ÝçÇŠäˆö‰r\ëRU-y•âZü•aÐD|ðàÁ}>Q_½zµlݺU{Û¶mZ @AAŒ7N3 ÝÝÝvÑçôéÓgªw;ä`ë_Ôeôo–   ÙÀ0<æ3NðåóÃF:úf:è^XܲLÕ.,Õj¶¨ÂÁ¦ž½»A×– “IªžèU˜xDåõï_°µs»fà‚ÎËj.EØ @¶Ú Cwbertëar”:JãýRújg?-⇨ˆµ–òß½{·–òß¾}»Œ9RÔ¾Ú1yòd­ PgçNû=+–-[öâÒ¥KÓþ“‰3@<áN•B>©ú˜œ¶°9a@QeTNÔŽX§f¶vm—m;¤KÍ7@TÙëÑÚ¹pÀåïo×*9к…¶­¡%ƒ5‘‡ð£š?H ríú¿h?_ÐAKê¥uß‘²‚Òðf ˜°¢¦§Z‰þd9²}²ÅS[0`€¨É}<ù-Y²DZZZ´”?|=–JKKEÍÐÞê òWÛùZžS ¶«í~ý[õý§ý÷ùs§ Y-xl›­ÖÞÿ)pÏýÙcËFkG>1{ÇóZG€‰y³éÝœ·¥fÕp àPP[ßY«"þ)2¶³Nû¿ëï¡Ä‘¾ÚÖWKù›Jˆ?¢~µKŸ º Ò‘¿ê,ìóDÿø:+T÷À j9a—ô­ü·[pý3@²ÎCÛžS§MI#þCkîÚòp¨~¦'wÌ‘/ <-%å4ÅLųSÚÆË±mSe ŠüSkõX§Ç¿^¸gÖñUš^:;;µ¢?…#FhŸ4hLœ8±Oq`¢°‹þï¾ûî§ÄÙŽN³†f€€d•U‰}ͺ[å¶ÉWçlŽ=±Ãs~µúZµ•ng¨~®OÕTÀ·´Z”Cš` @MO9\öÙ6IJc©­ïCøkkkµ5~5þ×öëQ০óIss³¬]»V[ï×kð>–ŒÀ2Ý8`e*^Qsÿýcí¿Ç$úŠ}ëŸeôO@|øpM¸e5ÔgåÊ•Z…?L¢¤ù±T#1iÒ$­SÀêñd…šú7Oe¶;ˆþí6ý±þiˆ§Ü¼ñÿ´ùìÙœNÜv?ìßvnß4]Ž®:B½þFÐ4ÚGŠ\Çh5¸?õ¹ˆÔ!üÉÃ{ì@å¾jÉÓ"x¤þaPݬÌÄa‡f[3€AŒ¶0==ôÐ,9Ø÷ŸÕ蟀x æñ_¹úrã„ßÉ„ò±¼ 9ro›™?+Ú:¯Vµ(7MüïÛRiöƒA=‡µ“i*ÚïM½V¯èÇú¾Y+ŸmmmÚLˆ?Šý°Ëßøñã1FX3'ËvŪêÿoüñæ^ñÏêÚ? É ˜[~E¯ ¨/É ’#flZú} ¯~æ¥j<õïÖÞ ¿óÿB3"8lƒ€PÉ?AEùG´M”Q]ÃÓªÛ€@#Ò‡ðÛEçf §‘?Zü°îê~´ùÁTàý &8ZB@§ÀÞ½{­¢ÿèc=7޵»-㙈þiHNhìn’­ü¹\5î´]ûˆw`ÐÏÝ›–GÕ.‰ùæ\»þV¹¢á?CQŠ €’¥‘ÝÃdJûxm>I<½n!Tñ£¢…}X›O¬õcºÖû‘¾6l˜f& þøÞú°' {`Õû¿~ýú·ß}÷Ý rpê_ªÑÜDðÙ@üCsO‹\¾êwò‡±W¨q­‡ó‚x@g¬K«ö£i~^_‡—Õ†P;Õ:¿hø±/¶\N+à.€AÝdJÇx™Ú6A*béÿHïC˜1£ßÍú¾}ÌõǶ=ˆ½^70fÌ­xÐ 6éÿø¬Y³’gþ§ý›Š= ñX€ øá¨—¿òE^,‚?¤¿—«½Èþ½*¾¿ü§ò‹1?–#Õþ ÌxÖòåÞ>AÓ›.H¿c}…}©¬ï'ƒJ}U‰¯­õ£ØÿÇz?Æ#›€ª¼ï¤þ1)Ð µ-ð{óæÍ[-é÷ý»ŠþiHÎÁ  [6Þ­íÎwYÝÅj®~?^” 󺚉݆ۥ5ÚÆ‹‘¶ÑýñÊ_Éi5'ËÅ#¾)µý†/ j°”áån–nÁæ;Û´)}#º‡fdé;ì! GªßIž£{‘ªÐÇz?„Æ š¹€à£ÐÏi¥¿¡ùÞ¶Í2úŸ={ö“r°ï߳蟀ø†w¿&KZVªµÙKU]À$^ s•m~©á„AzgïûÚœ€¯9WkU Ó²ÂR-›æ'úÅKTË^ŠöÇÉèΪq/3[^#ú†è£/Ý4"ˆÐ-Z¤õùc½â·n*ý“±ÛøG úø¥—^Z!gþÇ$µ¾×Ñ? ñ›:·È®ü…\0ô«ÚB̤Oea/‚Т:sdz2kÇs2Mm!|Þà³ääêã|µ“ ²e:6iƒÖ´¯W6׫÷×ûFüém¯“‰ ÒÐ5R ã™é´@êxþT«ù­@Š~áÂ…ZÁ†ûTTThÕý8¯›J#PHhUü÷ì³Ï>!×þí2þiˆïÀXZT¨¿¼çuùÞÈo†z#/¸°öåõ¦·ecÇ^ ‡Ôà(R­‚S+&Ëqý§É±UGª!ÔvÏÙßÏ‚¾¹s«2Ä[µ·:6k¢¿^‰O¼ÇW× “ù&v6Èøöz©ëªÍèß*"oˆ>Fë¦*Àv`2Ÿê½×ÄÛú"Àq¾8ŸÛJÿC^KJøaÌP…‹Ÿyæ™%IÑÌÀd%úߟA .‘¤÷‚Þ£0á€Ù)N8`%}þïÍåmÏ¿`jà¿×~iðÁ¾O´bK’˜0²ßpm‹è1¥õ2´dˆÖE0¨¸F{; È¾¨ -ÑÙÙµ[öô4%¼Ý%[;whY°Ýݾ¾(äßQ¯ÖõÇÈÈža’Éò´ðA𱾟h?Ìñÿàƒ´‚?ˆ5΋íS­ôOFß-Ð Õ÷ÿ5ùï õ.vÒûÿž¤#*öÛÿÒЄTj_¨–‰÷üaí2·ñM^ˆ,ƒ/KÕÒUa¤@­Íï°öh‡tÇ»]„Y­ÒÖô!ú™*ä;póV‚‹úÙXÛ7‹ÌQéÿÉ'ŸhÃ}€¾!†aí¿¦¦&íó,_¾Ütý_ Z÷Ío~ó2õ.¦uôf¬ @Ô"3 rèðG¶ŒK$,lY*?ýô·Ú,÷/>ClÍõmü‡jµÄ†?Í*ú$ÙBßíÞ“W[,íèªí´7®³^f e/ŒÔÅÚ>"o'[ðfTú/Y²D ÷ÙÀd?<û¡ ]°œ€ €o¿ýöÓð†b=ø'kkÿÌ0hÐþtÚ€“äÌšÏj›¼D xQl˜³ëE¹qÃÿñBCJcý¤^mºƒª}¤øËc™OÁ£’b áÏDß¾PéáGµ?Šýí£Ç¿ªªJ}ˆ¦Œˆêí×#ÔÞ;Tôÿeö¤ý›þå nP(õÂîyÚõ×Ï 8QN쌣̻Œ9OeMÐn¹´u%/ÑÐSûc;Qħ¶ÆgÞHCh‘R‡èãm¶SüF@ð,X õùÃÀˆ ºY BÚ?S…†vÅï½÷Þ3Jü[¥ïº¾Yäwp¤ <{ÔÞÏì|Q;P¥=­rªv €pRùxO*·ƒÖmRÿ}¹DMÀ‹Æ£¼ yúÑÕ›ÚWQþ žìŒB†ÈCì‘ÞGÄŸ­*~' Õb?ôøc Å…|˜€t+ý@êKF¨MöÝ{ï½/÷FýFѽ“ôÿ!ž#•蟀„ôsc­@Q¶§Z¸Æ—7¨·£¥AUpçrµí];e˜ª Ϩ`ÿÇ¡çÉãÛŸæ‹%O¨Œ•KCÇHÓU'£;FhCz²Di}>æægjB_: Ò_m²ƒÍv´ÈÏoܸqZ?ÖþQx˜i¶nÝjú9µ­ð ª0pŸ8ëùÏjôO@Bв° ,ŽDjÔ²AmÉ0ÕÖ5L[S„v®êãÕêýj©*ªÔŠ S©vîT{Ï·ª%жX›ìRË|˜Ãc]ûFYܺ\ËX\=þäµd‘ þ­öyMM¿ƒ!áŒò‡vÒÖòǪô~¦«ö“E½óØ€Ât.Rü‡„ÄJì1Òi˜ oå ñGú©ÿLÓÞÞnºí¯Ê>´ßsÏ=Ï&DÿFSÿÒ‰þiq¶$Æ‘l ’AK²¨+ÀMTï<ÀÀ˜–hëþ?zÕæ¥§Ô[•èc˜‘·l¼Gî=순,OàgúϺïÊÿ¬¾Š/„P+ÕñhëùêÀT¾l…èCP!¢ýdñÍ¥ ˆF£Z¥ÿG}t  õuuuZ‘ßäÉ“µ!CÙÀ*úWKsÕ»¤ï¦?‰Bo·á]ôÏI€„d’ÍãÈ4[:·©‰‡³´h<`Ì- 'ßlz—¿ä ¢nõµ=Cd ¿k” ë,ÙÜ3ñ±¦ÁGϾ¾¦ï‡h?µÆ® ?ªýUµ½ö1 ÷A-*ý!þøY²e<̶ýU» ö¨¡?O'Eÿv›þd\ðiñ l›-g¨6ƺÒ99ÿÕ}O>j^Ä]¢úúÎRûXÛÏvDÉ|?ªåÄ>×Ñ~"---òá‡b]+ƒIÁz? 2“&M:$[‘I°‰L€k×®}Sí7°Yìûþãb?þ7cf€€ú„?oº[®ÿ«œœ#l/Rˆ¿lº¿ ¢­å÷ T|£T¤?*«kùE{J>Þ"ÕŸªØ{m Pyÿþûïk3ýQé¡Ç:?L Òÿí‹ç£oÌ“çfÑú‡-£ÿ¨ËÈ?+Ñ? !9sú_ozG>7à䜜ÿ†|I^R/}Ú¶†¿ P/RQ~­6}oLç(©ŠfoÚ%"d ÁÑ#äÄ x~Kí[±mÛ6­ÍEx¤ø!þh÷úÿÈ‘# JrÆ#ÔhßKɨ"Ä^{íµUb¿éYñŸdË Ð’cnÛxŸê8:'[Ïb‚"füÇŠ+/’ÌSÝS© >úòGªa<…’½žyˆ#Òú|´ÄAøÒMíçjç]·nV鯊ë´ÁÄ`ºŸnœVú§k¬ÿÌ;÷Ù¿ÙObßTÌwþ³Ëd¬Úƒ€³³{·Lß:C¾?ò[99ÿ¤òqòÕÁçÊìÏó—ჺÈÄŽ1Jøë´–½l¥ö‘ÖG„¯GùéöæûŨ¢:m§=¬÷ëm~úV¾¥¥¥Úz?Ì@ªÂîæq(<´ÚôGíú÷QBôoõ›íðÇ6@BÂÊÌÏÊYOÓå‚ïŒøWy£i¾ìêÞÃ_F(RqýÈÎaZñބΆ¬¥ö!TzZ‡“m2!Ô^fPà‡yþhõÔ?€9˜è‡ŸâoVéŸ C€Ö¿äÏë¼óÎ;ˆþ;ÄÝà»Þÿ ¾. !9snÙx·Ü4ñ÷Y-ô2³þ£îÛòÛ5×ñ—‘!°¹_[ÏW­zűìÜn!v{¤ôñV¯t÷Cj?ÓÆ µµUT5½6Óß¾ý»-ê[ùâgGÚ?¹xÑ©°»yžúã‰@õ¿ª&`—ûûºô]û7ücµÓŸÙÎl$$,,jY&/í~]ÎtzNÎBDÌxgïüe¤zCj­zSÛÇËøÎÑYÙ\±×Ãm¼ê\­ù£Ðîã?Ö*ýQp‡ç€ê~¬ócôpr¥&£|3Ð÷®#Ô,‚¿ªÉ€mÒwW?«êÿ˜dh›_BÈí›ïW"|¬ô/ªÊÉùõÙÙ~ZÑWéýz5c’ZÓGz?Ó‘¾Þ“¯GùN÷«÷:‚Ϧ1@¥?ÒþØÐGïñG±®Ç¨Q£ +ýÓv§3›ü‡±¿Ó§OQÿ¹úcùg<ú§ Ägìëi–{·>*—Õ]œ“ó-,Öþ“ܵù!þ2,(T‘>ò@ôÇwŒ–’xfG:#ÊÇZ> ÛpØ °ñsj?Ýó¡ÂÅ~hóàd<ô­|Qô‡‘ÄnŸO& f`ö¿*Kñê¦M›PPÓ-öé³e€ŒŠ= !`ÎΗäì§Ë”Љ99ÿ?ýŠÌÝó¦¬n_Ç_F¢P¨(ä;¼c‚&úýb™ÝU}ëzµ¾>y/h|&³X_GÄÿé§ŸÊêÕ«µï­oå«¿Mœéïeêß*úWÏ;úøãÏ‘C[ÿÜìú'ÙŽþiñ!Øh·MºZëÓ÷<ºj³.]q¥ö\òŠh¹¶¦Dû$Г¹¥½b‚¯¯å‡1‚O…îîn­Ê¯÷øë[ùBôQéow½Ò-ð³z,jô"Äd6nÜ8_Í&Ø,éoù›Õ蟀Ÿ²²mµÌÙõ’|uȹ99ÿaäKƒ¿ Ïíz9o£} æ9²m¢4¨‰|™êÌHž¾gW±–Ô¾›¯EZ)ÿ5kÖèñ×ÛüpÝ`pݼHû›=Öj׿çž{cõÖ¿Ä©™Øò7£†€€Ÿr×–‡´û0³?\<ò›òVÓ{ÒÔ³7o®9¶Õ=B‰þ´¶ÉÒ?š™-c±~¯÷å#Š… sj?óíÝ»÷@ä¿k×.ícz›*ýa¿·×i=;¡?·dTWÀÒçŸ~¹ºéÛè?ë3hñ1mÑv­åäüU…•òƒQÉUënýµ¢6Ý9¶åp™Ô>F«êÏT¤¯ñéÛç†E¨³ñÜÐR·|ùrmÍF_ÛÐРù¡Ò¿¶¶6kÂîæqèH0üóÆo$þéw<þiñ9/«zÎôy9ªêðœœÓ _Ú=O>l^Êë;²k˜ßr„ŒU#yÓMóC4áësöƒ:'&ëüHù£èÃ~âGª×QïõOe'¿L&šÍýWÛoU­óåÐMœ¶Š—Ñ? !>Ex7o¼Kî:ì)Šæä9üWýÅòÝe?–®Xw(®éþõý:9±eš ï’¶è£b_ôƒ6k?ׯ‚Šˆ_µÌiâßÑÑq`#û¡×?±Ò?QÏ„!ÀÔ?³Á?jGÂ9ªM1yì¯Ù€§›þÐPÖwl’'wÌ‘¯ûûœœT¿Zù×açËý[ üµDïþg[Ž“a]ƒÓú>hC«©©ÑŽLòù)*Ïösƒb¤/Rꬭë»ùaùo±±O¶DÝícñµx®F(ãÒ¬Æþ¾*}7ý1Ûú×Í🬚Bv <½æ^24'çÿ×áÿ óßÔÌH¥¶ÙýLó±ZÊ?Uôb>¤£õ>ý|àSýˆôQì‡tº>àGßÍO½Ò?Õh=Ó†;þaç?#TíÂKêóͲ¿øÏjòŸÕŽžS „ßÓ©FóÞ¾izÎÎ_)’×_’“ŠÒ»î}±é4¹`÷—R} /ªÏ§L™¢£AüSÃl|m¦"x/Ÿúç1Ó_õËk‘?Äذašè£Ò=þFYœ;ñpóœSy\òcÍ¢µŒÑ­Öþÿ8­øOe3„ä#Ø®÷ݽ äÄêcrrþ‰åãd|yƒ|Ú¶Ö÷ת(^¤÷ÐrdJUýH=#ÒGÄ1J7Ú[Ÿê×¢ÒkþS}ÀO}}½ :T«òG»_&¢õL?] (N4bíÚµo¨Ÿi§8Ûõ/Ñd]ài Þt]u„”{vÎÖh›¼¨:Ù>Köt7ùþaLï™ûN–ʨ»H]ŸÌ‡¶3£Â3¦öÓ;†ú Ò0hD¥?RÿȰ$Vú»õl³èê©§žéþÅßwci 8[:·É£Jˆÿ­ö‚¬Ÿk{×Nyfç‹òÌ®5àwJcýä³ÍÇ©é}“\=Bñð£Šß­è„­8/ÓçÃÇõ©~*ZÖÖÒqõÝüôuÿLŠz& &šýUÆà“yóæ­–¾ƒ|9ö—€ðȶÙrFÍg¥®tDV¾ÿÚö òøö§enãÒ⚌Um}gï;U›ÛïFø±æ áOÔÃ>sçÃú>†û@ôQì!EEb¥?Úþ²-ê鮳^Îmú¬¶îïôð£Â€|vMËîÝ»5чø#òÇÀ˜.´P"ë2räÈ”~6/ gµéšcШÿ¼&}ÿÄÄyÿ¿ä:ú§ $Àìîn”¶=)ßù-ÇiuÈ_w½*3v<#;ºvòçF‘ßYj½ßém¢3}6Ä7hÏ Ûä®[·NµÂ?| *ü!üuuuZ ÓÑz¶ *ÿ1ªØˆ… þUÍþG_ ÝÚ¿oÆþÒ2fîxVÛ°g\Yƒå×ííÙ'Oí|Afí|Nš{ZûóÓ6UNß{‚㨟õ3µŸóáó¨ð‡h"j^¿~½öõXï‡ècCŸäÖÊL‰z6 Uô¯2÷ßÿ_{£ÿÄÁ?F™«ŠOÇþÒ2¢*•ËÆ»å¦‰¿7œÒ·­k‡fžÝõŠ6M0È`¨Úüœ€5~DœN+Ì™ÚOý¹éú Òó8Ðæ7qâDmŠýð{p»›_. ÖþÍ¢ÕÍðšb´GÌçþ[Uþç,Ú§ $„,jY¦õ¼¦m¬³¦}½ÌØþŒ¼ªZù¢iå³sü±{Ÿ°¡ Ö›[ûü&¾aYv@¤Œ6?¬÷c²&ý¡ÍODþÉc}ýRàgjÌ¢õ}bO>ù¤>øÇ*ýïfßœM¤ $ܱyºœ\}¬lìØ¸V>;ŽlìXüQaŽÃ.]æÔ¾WÏ £q!þØØgõêÕÚ¸\,·`ºf+ ãÄ„å¢ÀÏêqØòó ŒPS ?˜?>fw‹» 섟BHjìëi–‹–þ—¶Ö&ÆuÔËÔX_' Ò<±ÈŒ|öžzãQéñ×{üa¼Pð‡áJ¨½ÀãݦýsmöGà 5øÇ(úw3PüýÓ"Â&þµ]C弯Ï;ÚÐHüÃ*¾¹~nHTøCôa° €K´÷á-¢ÿL‰³×†kÿfÑ¿jo\5sæÌ…Ò·ï?*ûK@ ¥ñ~r^Óé¶;ùá¦ñdž2Lígÿ¹a#é‹´?"f¬ó#êGôo6Ó?[† “FÂoý¿õÖ[úØßn±ßö7&>üC@ñ7êVø¥ÆÓ¤´ÒQäñgŸÝç¡Ç,Túëm~h³D±ŸÞæ—XéïE´žéÌÄß,úWõÛ§OŸþ–ôÝò×nýßé f!œØ:MÆtÖÙ~Öœ“ÅŸ©ýÌ?7¤ø‘êGÔA?hóƒØO˜0ADþÉ•þ¹öTg·öÿÁÌQû´‰³µ·ci!sýOi>ÚöëPm•‡ëü+V¬ÐŠý0ác~Ñf‰?XëG»¥Ù„Å Tþ£ýÏ%ü{ï¹çž—“¢ÿDá·ÛøGüjh!¾ @ý;kï©Ú[+Ðg>|øpFðY>ÚúöÇF>z›2.ìƒÑ¾X~I¬ôw+Î~1~«ècÕÒ*l»Åýè_ßDû4„ßrBË2¬gõ K¥šQiž©>㯅 b´/ÄéÿöövMð±‹Zü¬:.üXàgõ8«ÊeÚÕØßçäб¿v)»1À9þi!¾ ¦§ZNl>ÊòkpS‡ø˜­7ûM|ýüܬ¾ÇæÍ›µJˆ>züa üȺ åJ·Ï×Ë(ßÍcýcYà µ¥ñ˪àq·šþ·kô…ÀÓB|Ï™jØ]Ë_MM”——3‚ÏÒùðxô÷£Ê_oóÃǰÞ6?˜€ÒÒÒœ {6 ÕŽêãÝ>ø`òà§|9ø‡€â+êºjetç˯ð¸)ú£1p÷µˆ„‘êW[ÜjéÌõG¦E/ö³ªôª!@wÚÍPfèoK—.Ý*ÿ¤2ö××u4„Ü¡n‹§ï³ÞÞ7v¤Ÿý"¾~àS=Ÿªr×*ý‘ò×ÛüPh™Xé™þnŸŸß Öþ““øížx≧¢»-Í Å¯Ñ? !$§Lé'C»­ ÿúÇö¾Œà3"~DþXçGú3þ±ÆñG¥?ŽÄs­ÀÏìq0=¦UwÕ俵âlì¯]€]„Ò熬þlÓó}ågË3µŸ¹¯Eú•þC´ûaw?}ªŸ]¥®¢üLÓ.úöÙgg‰³-3ö—€â&¶7È€h˯IŽ@s%û9‚Oõ|Hó£Ú?±Ò_oóCÊ¿²²2¥ˆ=†C0ÓÀâÚ|ôüóÏ/“CÇþZ˜8üà !$¿9¾õËÏ£âSçÁgî¹ÌñG¡DiTÁ£Èó þ‰•þ¹ölTþ[Dÿ¢¢ÿ'åÐÊÿ¨‰ p’òç€O‰ !ÄsPõ?¬Ûºªßh[Ù ‹o®Ÿ†Ý ÕßÜܬ¾E¥?Šûôõþºº:mÉÅ­Èú¹00ù±XæÀÏo†*‚üä™gžYœý;ÝøÇ÷ci!¾àØÖ©–ŸGäH”©ýÌ<7¬ó#Õô7„b }Ðã?räÈ•þ~ŠÖ3ù8<]VÌ™3çqٿ寛Mìªÿ}K¾€@Ìg&$ÌTE+¤¡s”éçq3·‹þ™Úwþ=õ"ò‡øc¸†ü`yE³Ë ø™=Uÿ¸f¨¥… Ñ¿Ýà«~_ŽýÍGˆ4 !ùÄámµ«èÛ͆A|sýÜÐÖ‡J2(ú«®®>öwRéC€:d=¬xî¹çfDÿ‰GTÌûþ©+¬ „xúwxûË/ÁŽs?m ‚àa¦?Ö¼‘À´?½Ò¨ôÏ…°çÂ`¼±Ùv¿½Ñÿ¢Ù³g/ç3ÿ¬ûû~O€¢ü¹í«=ƒ02¦k”ôVš~‘?¦Ð1‚Oý|xãÆZ¥?ÒÞ¨ôÇÇôüÌ*ýD6H~fÃÈ_« €jûKŒþízÿÍ–Xæc €‘) „xÀäöq)EÿLí;û¨ôGÊ© »A ±Ò‘¿ÓJÿ\Eë™~2!fþe”Ïš5+9ú7kù ä¦?ùf¬Ä…€„ä€Âx¡Œë¨3ÿ|aá´t®…:#7!Ÿ*ýí£èoݺuZÔ«Wúc#%ˆ?Ì€¢u¯ ÝÐÐ[ùßžý›õý»Ùù€Ä@ìÍŽ(oË„xzÿûÅÍgúc=nîLí»ÿZ÷¡Â_Ÿì‡ÿ¨ô×·òÅÚ¿ŸÄÙ«sÚŒüÅ4ÄTôÿ‰Aôš-óÅ$‹¿]äíu{„˜Ô1Æòó0Aß\?7´õ!íßÖÖv ×K)cÇŽÕÄ•þ~ßÉ/çÄuA6Äê¡jÇ¿Gåе³â¿@nù›O«,€þ~,Á´Ï;vÖ)ê-zŽŠ{\“„£ áˆ$b`8"BH~1x?ñmâßI‘*î+¿ô‘oüFý¥Vøa·?/Zÿ2rƒñ‘1@u; þ v¨ôG €^é·‰¦*HéûäǺ}œ“¶?•1ùÛ+¯¼²ÒEôÈ-ó͘ â¡ÿ"ñ‹oé}[”p81 ?ÉcÑ·~ýÀßMñ™gž9^ |YªÑ˜#øTÏ…?TúãÀt?ÐÐР ?Öû­*ýƒfÜ>Æ™¡ B÷ôéÓýwf úlAy €UÊ?ñsV&¿äný5‘ð±¢ñ/L¸‘YehH>Gþf⿟¢ã?~²Õ7u[ü—ÏÆÑ-ŠüPÜ€ÍmPÜ7nÜ8-åñ/**: ša-ð3{Úþ°Õ±K–,yaÁ‚› @ÞEÿaÊ™3—fôKš<¾ ÷ó 74a€Pü‰Lÿ:µ}˜Ù7E¥ºQk÷8ô|fƒb?ù¡âí~X>A±*ýý£›"—âœkC`·ÛŸ2mwÞyçL1Þñ/o¢ÿ0'f –tcJ~³¯OŽþ n~B#@húAÂßOL­GWªÙþ¦ýýËq¿ö Â¢ñÇz?ŠþpíÐæ‡B?ôùûQœ“›M#kƒÃ ù?­2(;Åxê_&¢€‹Ü"  hÂ[3ñOŒþ¹þO(ü}E_’„?Ñèf¹H­ÿO²ú;ˆù]|sýÜ0Εþz±25552fÌ-òÇûA™à—­Ì–FÐögc¢vß|óÍODÿVÃÜFÿœè#C`$þ—â_ Ækÿv±·ÊEþÉêx³oˆµëÄêÿ¬ÜÞQ€>XëÇ[˜6ÿÐ9ñÆSO=…‘¿Å?ôÑX €YÕÄà3ýäåDá/0¹ñ1ú'ùý‹þ%Fÿzv ®DËtû?ˆXrû_¾ûÅ_DüèñÇX_ ³Á?Úü0ÞÑ¿™ø%ZÏäc1ùЮðmùË_¦KßÂ?£Vp'3ÿCý‡1(þf¿œXÒÍ,Yücâ|ÝŸ€ä›0[û×—Ñô¯ÓÞWûÏ7˜}cLªãšÿÁï¶>}?´ûAÜñc¦?Úüô­’ó±ÀÏ챘‚ˆŒ‰ï¾ûîÌ•+Wnç}ÿyý‡ÉØM42‰¢OzkÔæDÑ'ù"ôfŸ3öShðõÚߘ®ÑfßÔ¬ú?÷hllÔŠüÍêc}õJDýV“óÕ`.Ú"­PŸß¬Úþ戻¡?1 ÑŽù–A·Ê$ÞÐâ&ÂO@òÙØ ý1ÿ¸êï/T3þMa];L|ªçƒè£ÚˆŸÃLŒõE›2%n¿&DÖïFÂ.õ/Sëþ÷*£ ï÷Ò#îZþb‚ÿòÅ­û›™€¸X§ùüÑ|2FÅÉéP}¶†f >ûÙÏŽRëÕÅV Ÿ×üñ9ìä‡k0ÞÃ~0ÆëýHý£Ò3ýígúœ0Jv=ÿj9eþŒ3>㿘˜ÿYeBý‡1àÆ™qõÓ|3‰™²‚¤¯Ñ#ÿŸ4i’iôoT˜iñõƒ‰0ëûXïG{ŠýPü‡%Œõ­®®¶¬ôÏwCà$õ¯ê:î¸ãþµ‹qáŸQ&À*ò]ôF`g̾6î ê§à“|~#P`ùG’n¤%b¦ QüómÜ/*û!þˆbùà `2"ˆ?Öüñ}Ü>ÿ|0÷»cÇ»žyï½÷ž\¼xñf1Ný;]q^@`g¬>O@húŠÉ¡Ó6ù*=Êì›;Yÿ£1@ôŠ6?}ÍŸÓ+ý!þ¨ôOü¾¬øï 2&0PV¨¯YuÍ5×`Þ?RÿÝ)Š wùËw`f$IÜ“72%Úô!Ÿü7’ü·“¾iÿägDŽt’ÈêMÀGèíG¥?„`_Jµ[¢e¥¦EÖÏFÂì¹vvvjÝV¨lJ×í·ß~«zÛ*wû3úc7õ/ÔÑØ €‘ 03bõÇý“<#n`’_ÿ‰¢ot3Ô– Êˡ95a÷«o胔?Œ@b¥?Rþz¥˜¢õL>ÎaÕ¿ÌŸ?ÿ‰wÞygX§þýåEyrC‹8¼Ñ™EDŒþ 1ΉD¥²U–¿¤ÆôÆSäìÖc°yófM¼0ÖÃ~ð³c¦?Rÿ0FÙVü÷Rÿ«¯¿þz=õß%é¥þCýç‹°‹äíÖú)þ$Þ.Sfõw9ú裇ʡ3\¿ƒTž Öôt?ÄëôJµI’Öãït¬o>Ìù·«úGêÿÎ;ï¼U™·©£ €F0B#@Á'ùÑýXÔšQ ŠÚ†›žLÝØÑï”>•ç†õõë×k[ùb¬/¯ÏôWµÚš¿^éïרÛ†¦ Ýv êÿ­·ÞZ-ÖÿÌ6û‰IÈGþÒ˜ÿ¹¾Oò³,XÜ$`e$´C¥¶‡š}Ä?Ìkþ¨ô‡øcÈÏ–-[´!Ý?fÌ­Ò‡Ñ÷Ïç?³¯ƒø£MÒ ¤þ¯¾úêÙr°ê¿GÌÿDŠ^„E¼÷þ‚i H¾ÿMD\DüÉ;œÒúÐ÷@ªÂV?þ#F`S$Í À?gC±$Ì”j™¥ç¾ûî»#¡êßMôïtÚ_hÍ €sS@H‰80Nßgn€Zë®2{€›ílsÁ§úÜУñW;ÏiÅ~‰•þØÍ•þ~Y¿'-@Uü?6oÞ¼•²?õo%üQaá !ÄÔ즪„Éû(Ðßì‹õõÿ°¬ùãkQè‡jŒõEµº^éÁ>hó³{LCÐ÷k‘ú·›ö§–W]{íµ‰ì¢«ô^4„·Q¿.ö“ÿG¬ €hiTúCøÑãb?¬W'Vú#ò7*xt*–aYÏwsN,Ømô£2Í7Üpƒ>ðG/üK§ï?o ÿh!™ÂÐ¨Ž–‚<î"áGÁÚý@b¥?ÖüõÇçûz¾ÓÇ¢å»"Ú}ùìÙ³o[¾|9*,“×ýͶü52yYøG@IUìEÌwÇ<°O€JyW:1^‹}¦ŒÒü~ô÷cH @ªôèÑšø#ú·KsÓj¨ôkiÅ¢E‹þúÐCÍëYÿVÑ^þÑBÒ5fFêQ £E€ÙˆàSýÚ––Mü±Þ¯G«¨ôÇ559¥óç³!pºËZþþøÇ?>(û·ù5kù3[û;0y•   „¤› 8d+mµà8¤™MMMZ‹Ä•êøYÐßÁ>½Ò?(Q·_ž+"»uÿŽŽŽæë®»îeÀ0ÐiêŸ=ÿ4„¯ ª€/TGZK~4)ˆ¿>Ö•ýXïGºÀÉxã|/ð3ýþh›´û¶O<ñÄ­ .Ü(Ίþ£3ñ·~vBH’À›e|LÂ¡ç­ ]àc€ô4&ú¡Ðÿ/++ÓÄE(öÓ§æC´žÉçŠA?0v¨Q¿3üñ÷äЖ?3#à¦÷?/£BHºf y@DÁ¹¾¯øu&"}½ÅO니=þXëO¬ô÷«ÈúÕèEvëþªÍòcµî?Cö¯ûwÙDÿÉUÿN¶úçcôO@q"ö‡ŠŠŠ’L<—Ækü˜ì‡õ~}¬/¦úÕ××k‘?Œ@£n?<ó0ìÙ+T‘åÖßþö·7'úMŒþS­üÏë@4„¬dTdœÒ}ÅOû )ÿ+VhUÿÂ-|!üˆþYà—Úãð9DþÈ®X¡2m7ß|óu*ó‚Þ@¬û'¶üY™€äÂ?¦þi!YÊôùœš„—ÑûŠ×3P鯷ù©Ês­f)¤û!þÉ•þF¢Ç?óÇ!›‚ìŠ*3›1cÆ-óçÏÇ¿‰ýþV•ÿnÖü%ߣBH¦ AD d±ñ“1€8­[·î@¥?ÆúêÅ~ØÆWµ7æU´žéÇÂ\9¨ø—·ÞzëQŠþŒúýíÖÿ¶ûåu !$ã(‘Lù¾’«}ô }ùë•þ}Dþ¨øGb¥¿ŸEÖ¯†Àá˜_d^^¿æškžã¢?3gÛý2õO@ÉVF ÓKÙŠöu ö(öK¬ôÇ&>ØÊâ´¿Yë" ³Ç¢ÝÛ%Û±uëÖEW^yåêÝ6—âû¢?³h?oÍ !$%¡7û¿ËB7‚â•Ø}­¾¡ÏÊ•+Túc¤omm­V臹þ\ÏOïq¨£p"þjy`ÃÏþóë1ñOý¹£èßJèYH!™BµlÅrýœD¥‰•þˆò±™¦ú©VFíÈÇh=“çĦI;Ó§Dïÿ*Tk \X‡CñO¥å©BH¶PÞ=6!k¢îô{`-ëýˆü¡b¬ï„ 4ÑGÊÅAY¿}Ð]¯?Úýn»í¶«?ùä£1¿NÚýìÖýÍ¢ý¼74„tˆDsÝn„%]±wk P‰Žõ~½Òëü´÷¡Ò3ý½ØÉ/̆À©ø+3ØýàƒÞ0wîÜårhÅ8Ÿùï6êg&€€’IñªÍ«ËêAv¢-c€ÿcËY´ùáÀó€à;V‹øñ~b± üR{¬SñWŸÎœ9óÖY³f-ƒÿf©ÿd#`ý' }Þ·üÑB²M\€žt3™6#5S^~ýaÆI]]–þ‡øÛ‰ üì ñG1¥“õÕW§?ðÀoJßv¿ä ~ìRÿqáº? !ÄìÛ·/#€L­ù#Íñ×+ýñ=1Ösý‘öG¿*çã(ྠà×׉ÁSƒ~Wc~Ÿ—CÛýìvùsjÌ¢}šBH¶PvÝ™0™0(ðCÄ¿|ùr­Òëûîƒö>´ùá’Èúõ¹b´occ£#ñÿý÷g_uÕU3Å<íof’ßí Š? !$‹ÄÕþîݽ7ÛHº 5>ü ÍFëüz± €U¥? ósb´¯ú;úúÅ‹¿¤v÷{´7òïã‚?»èßÌ$ =×ýi!^‰¿þŽªîîT£s wͱÛ.Æ‚¤·ùá|Hóc¦?fùCüõJÿ GÝ~x®0YNÆû‚¥K—¾|ÅWÜ£Þ5ÛÚ×éö¾õK@ñ‹à'\‰n›™Hu€SáB:æùãÀÿ±Ö5ûAüÆú²ÀÏÝsÅÿU­‡£}€j¹|SøMÿ.›è?Õâ?£×%Í !Ä#Çp•b˜ àtK Û·oׄ©€*Tûëâïר;H™üþ0KENX¶lÙ<ùß©×"Güµ÷ ¿“ˆŸE4„ŸdZ­„bm¶ÁN*Æi~läñÇ®~øÞèïÇ.~Xë7ëËõ|÷C›ŠýœÖq,\¸ð5ßÿ>Ù¿æŸ8ßß*âwýÇ„E4„ÿ™%­vQdº@èj9l#«ÍÇ:ÿĉµb?LùÃô¨ÛÏ×µç8ÄçÏŸ?óøÃ ‡âŸJÚ?YèYôG@É5*=Übg–O%ÚO{Ì#ò‡ø£ Å~hóÃ÷FÔ3m¡ Rf!•窯÷£“Âé)ÔŸn¼ñÆç\ˆ¿“´¿QÔÏ¢?Bˆ—¾A´•øÿ˜ Ë @&: JˆüQéý( ¢Š5#€Jÿ|Ö3õ8¤ü±Þï4åÙþÏ>ûì]ŠyrpÈ“ùþN6ûaÑ !ÄçÆK–‹ëoÞ›À[LœCÁ"£1B;tñ·Z^ !°Þ"»â´Ê(ÖtÏ=÷Üô /,–C‡ü¸í÷§øÓB‚h”p4eÚèÂáÇÝüð ÷Á,]üÝŽ¦!8ôwƒìŠ›n Õz¹öÿ÷o\²d 6Zègm~FóþÝTýSüi!9Žø“‰©b±ÝVLe ‚áÇŽ~¬óc¸Æùb­Å~º°±ÀÏýãæÇ`kýjƒ¥÷ñ‹_ÜÖ„µ‚ýâï$ê7«Iq›×"¡ „x,ø’•ÅUŠ~O& ÒüzäýPàñÇ:?ªýqx!²a+ðÓƒ ¤üÝìÔ¨ CÚÔçÉk®¹æi9Xì×#Ƴý­ÄßIÑ_ÜàuFñ§ „øÀ$¾© xvÛEóNg@œõ£¿Æ RSS£õøCàõ#ú×…‹ëù·ϣµÂïvƒ&Õq±ýþûï¿ýÅ_\"SþÝ¢µÿÄ·f›ü˜‰?¡ „dYÜ#&7̨Êü]vßkÍvò µ£}!þØÕ…~µµµšq@ê_¯ô÷«ÈúÕ £‚¿T–bV¯^=_õ÷ß½sçÎF1NùGm"~#ñONùÇŠ?Í !$¦@LnÐq©·ª¨²S µ©ÂC„¬ –”1u›ú ê)LöC±ÄßIö€† /ˆø!ü©ìÇ ~_­sæÌ¹ÿ¾ûî{S¬·ò5û¿•ø;™òGñ§ „äHôͲFo1  Q õp+`&h*ºÔ Òò‡˜É©Š? !Äg‚q)øÉ)[-ÂS©û­V'Â:4D ‘= âAüñ9RÔ àÿ\Ï7fJ?RöuÔVÊ ~øáÇß|óÍÕ½Âß%Öã{FývBˆOÍ€þ³­WoÞ1U¸·Íî~ žA¥?„K‰Vè‡V?½Íëþ~Žºsé#S‚#¢TÁå†Y³f=>{öìåÐi~fsûÍD¿'AôôúSüi!4 É7gí&¯Öð79µ0jÉà@…?Rþfâo'–AZÏwúXÔGè¢ÌI&D¨VËj÷¾Y¨îW3áwbœÌô·šðGñ§ „Pø“·D?øàƒMßùÎw,¿‰.þÈôïß_[ë‡èCü+ýƒ­§j^ øz]ðS­à7CkÞª&ù½pï½÷þ­w÷ÆÄa>f‡[á·Zï§øÓBBbú˜•ÎoQâÕ¬Öï«ìÄëü¾Dñr´îöqøZ½&B›©?U›±éí·ß~ùÎ;ï|]«Ý¡ðÛmÝk¶ÖoõSüi!ŽünÖúÍ>ªzÏ·©ú, @¢0BüЯŽ%€Ä_c4ø'h†"yüœºèëc‘³ý{S†lѼyó^™1cÖø; „?æÂX rÔïd;_Š? !ħ¢¯i°:¢ª|‡2\,A“ÑÍ€nô÷Í ‚׆@ùd±Ç[ÙŠêÍP©ýæåË—¿£Šû^]°`Áfé»aO, ñ¥õSüi!4‹¬@⡉€*òÛ„ùý™ÂI¤œh ÿ¯ˆD·údqO|« º~‰œü’TÿÖ­[—«Œ·zè¡ù*£’<À'f¹Û‰½UÄïDøjG(þ4„€eì {ÔT¿µS§NõZ}!Ä^ƒÁK‹/~gæÌ™o¬X±b§:µ/Y¬í €ð[¥ûÍ ý(þ4„€DúNf¦ÿq¨ôó§gžy&¯h–~OjÖ†O?ýôcµ-ïü÷ß)þné;±Ï(B7~«%³ïc'üN·ó¥øç€/!ÄæÞI: ŽÂÞ£(á(î=ÊTEõƒ>øˆè3‚—4}TWEç–-[–/[¶ì“^xaÁªU«öÈ¡ó˜­É[e¬Öõí"~'é~Š? !$ âÀàm L€:*Ž9æ˜úÓO?ýØúúúÃKX‚P+NŒÔÕXÞNõ6® ðÚ•¨koÕ.†8ÚÔN|Úû*šoV#v›Ô|ý}*}ߨÚ÷*¡oRkø=6ÑyÜ&²6}7Ñ¿]V nó¼ì*û™ò§ „„܈X/Õ$‹~âÛ‚$`$üN10 f_“ü«ŸÙLÄŒö>°q}z‘Ñ[»iŠfÑ¿YzÞ­ ˆ;ˆöcb¾çƒðSü} çBœ`40Y$"IïG“7ùq…½_ëÔˆ‰€[}˜|}º×ÂÊ$~,fò9'‡Sñwc쾇“ç%BH~Š~¢°™€Ä#j"’1ñ/0È2ˆK3 6ï§c¬RÛv†À‰ 0‹¾Ý.8z ? !„¤ '§»ÍÐ…Èmôï$•ïÔ dÃ8Í ¤ý»1F-{©Š¾Sá§øÓBB˜0,&Âo¶s`AÂ×§³öo—pbÜ·‘¿ø‹MäoUWàÔ¤"øN«úõÓBHÁˆ™|>Ñ87…|nÅ?’Ÿ5Uñw’ ˆ‰»e7n¢|Fý4„ ¼m@„=f"þqáwý›™€t²V·‹tÍ2é.¸É¤áSø !$mCàÆÄ\FýÙŽþs±i3ŽàÛ‰=…?Äp!$•û…U+ž™°»}§Q¿W~1"™| ?ÿ  !ÄõýÂÎDl„¾ h?Õ´ÄÅÏçTSépcÄÅÇí„>Õú(ü4„Þ3›;Sà¦Âßíz6ZÓÉX s<…ÿ»‰îÓÕKñ§ „Ç&À©É|¤Ÿ©Ö¿l™§ÙtDž¢Oh!žšgc{~>U±wõ§[`%°™4©<…ŸÐBrj2!îN¾¯Óç•iŠ»s'Ÿs"òñ6B@!Žï!nÛM$ï4ÂÏFÚ?ÝŒ@:Q{ª‘}<ÅŸÐBHZ÷‘TÛm4Ÿ­h?S&Àîÿ©~Îé¹)ú„€â #à4Bwŧígº0QΤ¸Sô !Ä÷÷7‚J4ÉÀsLWLã9ú8EŸÐBqo‰dùó^ÝãÒÀ3Y GÑ'4„@Þg"YøžÙ¸ßųôõqž !…¼„~ Vâ|,!ÌBByÿñË=-îÓïE !„÷%ŸA¡'üC#„߯(ô„P„²{ÅB!„B!„B!„B!„xÊÿ½Œ£ŒXçIEND®B`‚icon_32x32.png000066400000000000000000000025361347155106100365540ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset‰PNG  IHDR D¤ŠÆ¸PLTE7­E6§C6§C6©D––– ¢¢¢–––NNN«««­­­ÌÌÌzzz ‡‡‡ÑÑÑ...¢¢¢OOO§§§¤¤¤ÈÈÈUUU²²²‘‘‘²²²ªªª¬¬¬¥¥¥"""ššš­­­ppp 888bbbfffjjj]]]///AÍRFÎWHÏX}݉ß÷âÿÿÿéùë”ãžnÙ{ýþýêúì©è°¢æªÝöàŒá–ÅðÊþÿþaÕoKÐ[òüóãøæèùê¼íÂHÏYBÍSûþûÇð̧è¯[Ôj³ëºûþüùýúCÎTÆðË¥ç­öý÷ïûñìúîÚõݺíÀOÑ_ðûñÏòÔmÙzTÒdóüôÙõÜíúïUÉc—ÜÉÉÉ€ÞŒñûò™ä¢â™ãøåƒÞŽÐóÔÉñÍÀîÅFÍVhÅs¦ÅªØÙØÞÞÞÙÙÙ“ãïûðÓó×h×uÒñÖÞåßÈÐÉÇÌÈãããñññÝÝÝëëëTÒcÎòÒh×vKË[†ÂŽÂÈÃÜÜÜéééìììïïïÔÔÔÚÚÚbÖpüþü_ÇlÁÆÁßßßæææèèèÑÑÑäääWÓfKËZ¿Ã¿àààâââåååçççÍÍÍØØØÒÒÒxÁÕÕÕáááÈÈÈÖÖÖÛÛÛÃÃÃ×××½½½ÏÏÏÓÓÓ¼¼¼ËËËÌÌÌÎÎι¹¹ÆÆÆÇÇǺºº¾¾¾¿¿¿»•ľftRNS —œ)2 ›4 $ .372?(—auØß#þ…!ñ?«-þXÐ5qÚ:>QVWZfßþw&(/Fì¿9éäL,ÜÝY%ÀíŸL+M‡–›ŽkL#6"(wäïIDATÕÁMKqÇñïoþÿÿÎÌÎn©(nùPƒ°ƒ!Ö±‡S"BèÔ¨K/ êЩSï k—.£§‹‚K ‹Ž™ëª³»ÓÌú\½>þ¢Cþ”z XrNÔ6 "ã•[ö:{¢8µ€+&á4ÿ`ðÀ…I4Í¿xXhu•©ÍAV`Ñ1M’3V›àHØcÁ¹@¹#«b¡åÈùRLOA¤Ô¶ÈZ1,›Ÿýœ££ ϲ£¢ò/Àá*R›™àG%ðØ¬ød|ê5çj5r^%²;õƒc›Íxìró£p¦0\¥´p’ÌØY{ÛË®pBú0Åæñåî<0UË®÷—õ.¼€Ò%åÖ#y5¨Ì)ró‹æüÌ•ê5[ÙÜ5æ“ǾïÏ>GSs7J¥F5Š ËÆ˜¦4Ùó8˜ ã`( ‡ŠÎÍâãdߣ0 6‚-ß÷{K7½¤Þrc¾$:$=ô¿®o:Ã-©º”Xh..÷ž¦C™p±>¡zTH}½ÛjbIYêJgéèŠËã­¾Rx4¾gçë)R☜e­ïœV¤ÕÙ©ûîMy­ HÙ– †Õ°DðòUA#síÄAêN'ÕñmDOã0²Ùó14¯»K}Ïg)™ßù>…ú^„Z°IEND®B`‚icon_32x32@2x.png000066400000000000000000000045671347155106100371340ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset‰PNG  IHDR@@ªiqÞ >IDATxÚí[ PT×¥¨ic Ä’4ŽN&¶Ó1mCÆ8±Ú¦‰budb@ BÒVƫѶ”1±hŠ:iLkJ@ ­5‡—ÊK°‚€ò~¿ßï÷à ¿ç»sÎν¸À¢‹²3û;ß,³{îÝó}ÿãüçìu΃Ì`3˜Á f0ƒÌ`ÓÞŒT & sg10?c]“Ç MždXÌð4Ã3 ?˜EÀœ¬ÌÌt)¼>79tß«YoÒl›ë÷æñ¨Õ ùgV½ ä¹?âó6Òù³úBž ð"Ç@oÉs^bxâA0Ögò+€1¯ zKþaÀj±2øõ3òÅë²·ÒÞ²èhÍIòi8G'ëÏÐGÕŸ’Kñûz!‹á¹é~áy¿¥ðöhº;:HYçp—$ Dšè>(;H§Ï«ñ8XÀðÂt¾l{á.‰œ¶–ÙŸG69ïØ¬û«,»G..²žNÈ×6(&Ýï%t'Ó[B(¸õ¥õfÒðذb ¢E^˶,¼¤í}Z篘prO:mÊuºoœsáï©n°Q=ndl„Þ.Ü=¥“¥Ë¬ äërõdÛ¾é  9ŽŽE!cÿ„6¥þLä<ÒCnM5a]ö¶Ù#€}¾‹‚ÐÍAS^“w§H=¾l Rý¾¶¶!ç­Ù#€GÅGŠÉ¡‚Ou<ÄQDŽkkë³fXÒäf›÷Δנ'›« xÿËÖ0 wJŸ‹÷]Hm‹â#U^ØÐèVC”Èmwé_&-‚£ÐZ€Ð¶HõD{îõi51÷’ ‚,÷Ò_®tÄ©'Ú5Ü£ÕÄvïSô¬ôÖ_BdðÍèð¥À¾²õW€ -¡ŠÉNÔÞÊq°ò˜â¤Ä `,ãfÌ7{*­g“µÏwòšc5Ÿi\fP'ŽÓâù666–ëtÔümÒŠ® gYg' MÔøÆFÇ›¡ïpâ8ßøž»»ûÏÃÂÂÒÝÜÜ^ЉîŠÉ¢/˜êšÔÞ õø†¡æIšNç§A€• c|33³gOœ8áuùòå___~œ¯›½€|'X>P5©Çpf€b),²#þ¾1ŸÕ(p—"Ó` Î5öìÙã”IÌû]K—.ý{ÿ) ðŸæ‹Š cûûº†ܷܿ)³/W1ö½RÏ)Ûë¤î›t¨êcòªþ„>®õÑZkkkÿȸ¸¸Ñ«W¯8tèÐiÆíÇ<5t#€mî;Ô?rG1馡 k"߆/ètÓyŠéL ¾{ýŠ1×{R5ÞocÎvd]åÄ›!ÇÉÓ2ÝŽ&ž Fü^QQ¥¤¤Pvv6…„„ôZXXlàáoª3€ýå•Zam­èë2gÿ¨÷Wì2åf—¿ã¾ñ6™´;åÏt&î]¿~***¨­­¨±±‘ÒÓÓÉÓÓ3']Üû* ü®h¯TàFÇF§`·†Ð×tvpŽm€P'"ÚcèTã¿É«êïê¢Ò裂^ûœ¢b£)33“¨¯¯êêê(::Z`¹ßϼ¿Qæ}# O‰«ŽKÅ Kš›ø¿X¿ ¦t â–·7nÿ†ö&{ÒÉx_ŠŒ”<[]]M===q ¤¤„óÔÝÝM………tøðዌÓOù»ª@› ÇåZ¸¦½K‡“ŽÓùØ/)))IÊg{{{ÕäHŽŽêêê’Æ01†—/_nÏ8=ËO¼tz$¦-óò“ã‘Ú:Aç¸>syüÏ‹‘¾@×®]£¬¬,ª­­¥ÖÖV)¤AP ¼b—šš*}ÞÞÞ.¡¬¬ŒØúC^†ESyFRq·Zcçø^²…Æ…ÑíÛ·©ªªJÊ릦&jnn¦––5A/C„ØØX)2ð9¡€ÄÄıµk׺2>KµñþŒ \l»,­õšj€wâ'˜4•——KG1ƒ¨äAƒˆˆqéÒ%Âr‡1bÄB-ðóóËu„sg…áý%òXÂã555’õõõŠ(i€Ï"""¤ñbœ  lÙ²åºAþcñt¶Ã/>Jò2Þ¢ð˜*..¦ÊÊJ)ô!Àø(iï òB,ùxÜ‡íø Wð;§¶Þ—ÿ4¶âQ °?ùJNN–B¤ ˆ Bð¬oĘ˜i,Ä‚‰kðŠÈÑÑÑ“ñx~:Þ˜ò%c-Æm 3„í î>>>ʹ¹RÕ† %< Dh£Ò#MJKK¥±€M\‡¥ðÔ©SYÜû–Ó}NH<÷âê9®âLà‡ ?111ÙÈÂù.ÂZ^QÄÇÇÓ7¤ð0€B訨VùwN7÷5‰0/f3€ùüùÅ«W¯¶e5áQx½rå ¥¥¥QAAtwËA£täÈ‘~b>Ü×$ÂLÁXvDeîää´a “" ð^xx8eddR$//OB~~¾¹ h‹«LMM×óÖés‚3ñÄ)'-wíÚµž^Q€bǶ°RNão4:@NNŽ$†\Ú¿jÕ*7þxÜ·µéú·A€§vîܹ  رã+©9B1ä‚` K‘¡M›6y°ûýŒ‡þ¼ÙN^`éââ²ý¾b°B&å<¸uë–„ñ‚ܼyB ;;;åßb^·ŒçèAs[[['ôòäQ ‡Í 1ä‚ào¬õÁÁÁ]›7o>È¯Z"ïôE€ï.Y²äUæñ1°ÔhŒ!^ÑÞb9d!?ìíígeeåÈ+¾_YTúB^<ˆ~c«Þ,”GpŠ ÓCTøï±Õ`r{xx|µlÙ²ìº_ò‚gÁ=¯Wäå]'B÷•… ne=Á{{ûã®®®¾¬8ú³úð¹Ý±5kÖüI¥Rmeã~ͰšŸì>Í«ý<} {MÏ#/à¶£;\Á/PÐ^æ¯Öüýçùúnɉ›ê£×'ë:pb‹øþÝœ¿.âï/à¤çʈë5ùñBsbâ¿ä˜È~ÉUÉÂ\'¤ÿ¤›h”ÀƒAIEND®B`‚icon_512x512.png000066400000000000000000000645501347155106100367260ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset‰PNG  IHDRôxÔúi/IDATxÚíx\å•þϨYÕ²Üe[²Ü ˜^B ”dI²v—ì&dÙH²d—ä¿!Mo”¥‡P–j:Û€PmÍ4î6î½K¶z™™ÿ÷^ëÚ£ñ­SîÜ{çýù¹dI£;ºÝ÷=ç;ç|"„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„Øá%àï›Bò€8/¿[B!yo (ü}BÉC3@ÁÈŸß!ׄŠ<E!~wþî !ü”?z#@×ï-’æ×BH>ˆÜá׆ÚPÂ)ü‘M!„„ÝXý?žO&€BìßU$÷ù „äSôo$ôq‡F ”&€7ÿð¿ÕÇ"³„æ¨ßéÛ¼0¼ùWü“E=ùã½G¤÷­ÓŒ_#„ FøN#~ýýXÂáÄ„Îðælñ˜¼Á/VG‰:ú%˜§€¯ BH€•øÇ{E¿[êèêý²A½ (âë'âoíG’>VØ+þ'?}Î¥£*.åå$„C™wì¬a½âßc`"IoïÁ¡04ÁÿˆPÔ+þå'Ï>ûçJüÀËI!¦ KÚ.ÆYO+À É™øG,Ä¿â¤Yg_YZ_ù}^NB±Õ@}‰4fbÌîÕñ0üð$¸â_pˆøÏ<ëʲѕ—ðrBˆ-Ò·F*fòu¡ÌÐSü«û±æ_¢‰ÿ“g]QÖPEñ'„Ô @¢ °[÷¼! ð·ø'¿_`ùïÿ'”ø©º˜—“BSØ{D¢|£VëxXDŸ xâ_d ÅÿÄ'ÎúYÙXŠ?!„¤‘ˆ'e"a‹¿UÚ_ÿÊg|ágåc«¾ÇËI!)gtOºïÆmŒ@ M @pÄ_7Å"ˆÿ¸þBÉLÀÌ„€àˆrä9ÅŸBÒÎ$€˜É}X$„üýRüùBHf3ÉÙV»û7 ñXü×Äÿ»¼œ„’QP`q?¥ šø§øBH† €‘à;Ý95äžPü !$ß3f& æžøWüûQü !$«˜Üjm&ü¬ žŠÅŸB²zŸ¶~»{; aäO!¼WÛ¡ÍÐøWü/§øBˆ'÷k«È?´u4BÉ÷ @(#|Š?!„{•ÿ4B!yñÓPü !„ØÐgh(þ„Âûx¥þi(þ„BòŠ?!„ð^N@(þ„BhÅŸB ÅŸâO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü !„Š?!„B@ñ'„Bh(þ„B ÅŸB¡ øB!4B!„€âO!„ÐPü !„Š?!„’§€âO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü)þ„BhB þâ@ü+(þ„BhÂ!þâ@üKzÅÿgB!4Á6ÉQ…øWRü !„Ð;ú7ÿÅŸB @xÅß*åŸøŠ?!„€™»ŠÿbŠ?!„|¢(ÄÑ¿•ø§ýg(ñGñÏGUËÀâ2¸x ö¶º¨¿T–KyA™”«·eý$)Ð>vñ¸´D[µwÛbÒm“Öh»z¿]šº÷JcO“ìîn”=ÝMÒÔ³—›BEñ7ûX²(½Ú†jõ£ø‡ûÅ)’1eõ2¾¬AêJGʨ~µ2²÷()(öä9tźeSçÙÒ¹M½Ý*;6˪öµ²¶}£ôÄ{øK"„Ðd8`ý&EþßãË!\ RÑüQUSeZåT™T>^‰fr ŒÆØ²ÑÚ‘HO<ªLÀYÞö©,jY&7/–]Ý{øK$„Фý›-Àô;ñɳ~Z>¦Šâ’šüS«—ãú¥EøÁyî…2¡|Œv|yðÙÚÇ%xoßGòöÞ÷哿¥Òïæ/™Bà"ú1®þ‡(Uâ _Á¥@­Ë¯Äþ¬Ÿ“ûc¼FPFô.?ä‹ÚѦj ÞÝ·@^Þ󺼿ïc‰ªŒ!„Л³È?1PÄ—@0©í7L‹”Ïxš–ê;å…eòùšSµ£Q¾Òø†<³óÙ¬²„’¯ bò~òÇŒ¦þò%,&–“ó‡þœQó)Œä篯Fu)üÓÐ/Ë?=O4/’Y;ž“ù{?”¸úG!ùžH³À¾‚Á‘•Sä»#¾!‡WNæÅ8ð¢ŽÈ±UGjÇâ–år÷–‡eaËR^BHÞ€D±7ÿ3ÁÕò¼PNè4/†0F7Mü½V4xǦ鲮cc^^‡¹ÇÌôô|g,8Ÿ/>Bã?ù}#3À @€è§ï|}ØßË7†-ç­{AFéØÃŽ”§U}À=[‘v5˜ˆdóáÒ ¡ðy&ÀÊŸq\ÿiòßõ?”¡%ƒy1Rµ_Su§ 8^®^÷g. dt¡°#ƒöõbÑ7úxrôáKÀ_ÂõoµÈ5ãIñÏÃK†Ê'—Žú¶6g€d'@3Ì4€àÿnìåZ•?ɬ@!0¡|¬üz͵j/‚}¼(ͨ[ W39{7F ±äL¿ûó¤?Qü³È•‡É_&_# ¥u¼½ñðBhü(úÉ_c– 9ä´'ÉŸ'^%CŠñbd™Zµ$p«2Zh©$™ºòBhülÌZir ¦ÚýrÌO<Û‰ˆ¶µñ5ã!ǪBK’›L„·B„Ì€™ 9àì§Ëÿ4\–·Óür Z,ÿ0ö š€ŒÜlx !4~þˆCѧÈ!'U+?ýC­…ŠäÊ”ÈoÇüT«¿ éÜ@ù&4AÍÐx̤òñò«1ÿ‘¿ÀC÷?2¬d/Fª7.€@d„‘nÁ®}w¥”ª4ñËï¤Fk¿,ް#µ(o%„ ˆ†€FÀCñÿr̵숿ÀŒ€Žºˆ"¥ — !–|»ö_Ø~æc¾:ä\9½æ^f @^fH–˜R1I.öU^ŸsYÝÅ2šn%„ÐAè)üƒjó+. ]ÅK´Uš£-¡ú™úU)p _´Ì<û¬’¬rQí×eT¿y¾Û»vʆŽÍ²¥s›lÖŽ­Úû±Ni‹¶Kg¼SºbÝ}ÿˆÔvÅe¥RVXª8/&#û —êÀÛQ¥#Ô5¨ ÄÏÿ™'ÈçÔRÀëoóÅë$Â`¡t†€d ˆßùj#?³§»I©ír?l^(îûD¶vípý=zâ=Z6@ÏÀ@$3 ¨Z¦UM•#*&Ëá•“µÂ;¿‘AAà»{?ÔL±Ë°ŒŠÐr?ªûŽû Dòóß”gw½"+ÚVyrΦž½ZT­GÖÈœ9ð49{ÐéÚŒ~?}¾>ìäþ­ñEÌ ¡ Ä'ô?ZÇøê9­i_/³wþUæîyCÚc9}.›ÔÒÂô­Ë[gÈ©*íŽ"É©ªXÒ/àù<»ë%ÙÕ½‡/fË ¡ ä`T¤þ}{Ä¿øæù ­Ïæ‡UÔÿ–ÚºÝ_›·ãù¼Ùô®vœ\}œ\<òB]:*çÏ Å›ßþrÓÆÿã ÚòµÎ%dKH†9uÀñ2±|\ΟG4•G·Í–o/½L檔¿ßÄ?™wö~ ß[ö¹gË#‡æ‚/ >S4å ÚÊ0@h9ý£ò?× šÿ²•¿”»¶<$*fëQ¦åám3åÒWªe‚-9}.¨ßø×á_ã‹ÚòÊ[(¡ DãøþGÉØ²Ñ9}K[WÊ–_.KZWö:®j_+—,û©ªÆ_ÓçqŽ*Räp kÃK !Šú圞ÿ­½ïÉO>ý•ªºßøk‰BÅ_®¹Z[¾ÈØ$è˃Ïá Ûìʽ !¢EþÇö?2gç³é=ùíšë|±~ž)°$pÕº[r:˜ç«CΑ’îÈ ¡ Ä„¯¨H1W7Äm«åënÒ3l ˜?ÛÇÍKrr~ 1úLõ‰|fh Ésú©¸gülNν³{·\¹ê*öK%ð»µ×i?k.øÒà/ðEn˜à-”Ð<çój~|Ea¹ççEkßÕëþ¬MÚ ;¨køãÚ›$y~×ö6 É€’çœ;茜œ÷ÉÏÊGÍ‹òæ:/Tû<½ë…]D¾£ ¯ ‹ Ég”#*óü¼;ºvÉý[òo^=íÎÁˆÞ3jh½2@hHóùšSsRü‡Yú¹žéŸ °™ÑÃÛfy~ÞúÒ‘ÒPZÇ|b€€î@Òætµþï5ÛÔ|ÿ—÷¼ž·×üùݯÈ7Ô”>d_¼ý]ŸšÑ]ç33п‡KÕŽ—-ÑVíýBO•–Y~}YA™š°XhúùBõ¹²ÂRËïQQP~`þÀõn—çÔ®–„ÐÏT\#‡ULðü¼˜ñÆ–?§`ÖÁŒíÏÈF]äéy±a· >ȤïyÍAA( \ iqRõ±ž§AÑ ÷ÂîyyíŸQÛõzÝý0¾¼A{œu æÄ…€ÐqbÿcûÄO©˜äé91ò·#Äþ¤Ê¾žfYÚºÂÓsY9…Þ° €ÐÏ™P>FíXâé9ßÝû/¼ ìûØÓóM*Ï‹î8€ÐÏÉÅðŸš?æ…7á} ÀÐ’ÁR]ÔŸ>çÖâ1“˽5ë;6ÉÖÎí¼ð&¬l[ãùP q,Ì9¬ 4Ä{àqÀëw#Áo‹<¾|,/|® k ñ’ŠÂrÑo˜§ç\زŒÞ†Å-Ë==ß„²1¼èÌ’O ÜëA0+ÚVñÂûìM`ÀÖâ!cÊê==ßžî&NÿsÀêöuj@gç«+¡¶·-å…g€Ð¼É”z[üÅèߨ"xmûÏ·,Ðævâ)£ËFÑø”m«==ߘ²:^ôÂ9„€xJm‰·€^‹ZYéñµV2”=§B@<¢(R(ƒ‹zzÎ í›xá²±c‹Ç`/za ¡ žÞð "Þ½lºãݲ½›€NÙÔ¹ÕÓóÕ2[ÀB@¼b¸Çýÿ›;·1ÊqÁžîFO7LÞ€B@ò¯#¾M§´ƒªÂ·(Ó䃊k¤¤ ˜>‡¿oBR¥ˆ—€¸Šø<6;i\›&µ 0Ö£ö<´-ìùÒCØéŒuIW¼ËðsíÑUýÕÞïŠuñbâ‘ð8廹ƒÂâ÷k†×DªàŒçgô¹Ì=f¦§?û÷—_®½m¶®ÇÇãqõ¹6ÃÇ¢¾ÅËåBhHZxݸ½k'/ºKvx\49< W²E•ÖWxÝöµ§§‰Ý%»U! — e+ !4$Ü`½·º¨ÊÓsîêÞà ïÖ4u{kšª‹*yÑ ¡ aÛªA@^mZzZyá]Òèq ª°Šfú{ý#•Í6§®[Ç€BhH¸©*ôöFïõZvXÀ®€f•çY1†…4„Ðp€¢ OÏ×ÈÀ”ñ²€BhHÈ©.êïéùš¹þŸ2-Qï®3„аg<¾Ñ·y˜Æ^^»²Â2m—HB mÀÛ"À¶X;/z®ÚC+™ „€„—JÏ34©_»OÏןu„Ððâu`+ @o—O0#‚B@BJI¤$Ô"® €·æ©(ÂmE¡ ¡ÅëB/.¤cž¼½vÅ4„Ð0ooòÜ*5kíôøµQÌ‹N +^GyÑx”=Õk'Þ^;¶B@BL¡Ç ‡ 0æ‰K„Ð0g ˜ 03‡ÌB@B‹×iÞ˜Ð&PÀ !4$ÄÀë @Œ= ׎m€„ЀŒÑïáEȵ£ „€Ðd0Šå3„’ûKÄÛ—Kœ—|ï¥ ¾ÍÔ àEOþEURäá(`f „èkˆ‹HÏÛµÞŠÂr))(æ…wÉ£ÐÌ !¹þHºß„€8&¦¶|õºuî©öÚ0@ˆ_„?bq@ï‘,ê}?B@\±³k7 €ÏXìíÒIcO/:!Þˆ¿è[=z_|íµ×6ÜqÇ“ðâŠí];== ýŸØÝM@H¢~£›EþXK-»á†>7~üø~ýë_¯a qÉŽ®]žžoXÉ^t— -ì±ØÃ‹Nˆ·¿Óÿôê|Ùm·Ýö/uuu×.]ºô+Û·oëŸ$Ä· ¶d/ºK†÷ê±häE'$ûâŸñ'þß(ê‡ð÷Þ­Ž( qŸèö:0”ÝuÀ;ӄΦž}¼è„x/üñ×"ÿýèGÓN?ýô{úõë× oÛ·ßñàƒnÐÅ£ î2Þf¼NgÒ‚~ª°Ê³ó¡&€â™øGL>¦û•^wÝuÿn#øéFýHùk½ýßûÞ÷ŽRiÿëKKK'Ú=±… Þ¼víÚæ$ñ$ýŸsHj¬éðv`jÅ$^t&•óö5àñR¼6$EŒ¡ˆ3£à¶¯ÿ€ð«I~ý¯¿þú‹¿ò•¯<éDü[ZZýéOzNö§þãç8øúåý­—Ï 8Ù³óM«œÊ‹nwª¼½FkÚ7øîDU4î¥(E ùÂ#Y‹úQè÷­o}ëUíÿ§øõ×_¿A-tÊþ¡?¦âO@ýM®˜ ¹íˆuò ‰cËF{k;ü—ðÞðJ ¿•Ð×ú {ú•ÿæ7¿ùÊ´iÓ~S\\<ÀéIwíÚõúí·ßþaoôo6e€¤Çª¶užž‘ÖÔÊÉòá¾Oxñ 8¢ò0OG#Õ¾®}£/ €·¯KÞBC.ÞÉÛ|Ìn󻨿Ÿêé¯ýþ÷¿ÿó¡C‡þƒ«¿Éx<:{öì¿ÈÁyÿF™fHúlëÚ¡í?¨¸Æ³sb€ÀäÚxœþG(ºü†×yÈJ‘¼5 q ÃRÔ¯Úûþîè£þ•Šú‡¸}B›6mšóôÓO¯’ƒóþž[Ã"@’2KZWxz¾cªŽàE75GS¼ýÝ·¬ðåuð:P]ÔŸ/¾üÊ8ùœÝ4¿BIhíƒð«¨¿Nmâs½zûçTÄ_ ýéxàî‘ým1ƒçg€dX–ËiNòì|‡©:ìA€ì9ÈÐ’Á2¡|¬§ç\ܺܗע+Þí±¨â 0?Ì@b ÛÈ¿@æ‡飲_ÿú×ç!êWC}§ú?ýôÓ'ÔÌÿ­rèУè?®ÌÀˆÖ¸O«9™>‰ÓT7†—ëÿ`i«?3^/K0À ƒÈ?yQå¹çž;þÁ¼óøã¿%ñïîîÞ{ë­·>¤Þíƒ ,L3$uV¶­‘Öh›T–{vÎ3jN•ÛŸæÅOº&^‹¬ As· ?3at³¯‰'½5‹üÒÿšø«¾þ Uáÿ/S¦Lù………Õib‹?¬†þ4%Dÿ}¢|“Cû’2Xoý¸e±œZ}‚g眨†ÝŒêW+›:·ò À’ȤŠñžžs±ZúñëÀ–h‹§çÀ @ØMAÄøÛeŠzÅ¿ì’K.9öÌ3ÏüMyyyF š:::¶ßtÓM³¥ïÚÜ©àI‹÷-ôüœ_ø9^ø^>¯¢¯ÓÿïíûÈ·×£Ùã%€ý†óEžè߬]ÎIŸQ[Ÿ¶kŸ:Ê'MšTû—¿üåççwÞã™íoñ½÷¦«-[zÅ¿Otoù —HF @³÷my_|–<¼m¦t{\ðå7°ÓyêZxÍ;{?ð¯èñ60ºtoáüÅ&ò94ݯ‹¿Vä§ú\YRR’Q·¨Fþ®»á†^”ýkÿ1§Qâ×Ñ´ØØ±EKÇ#-ï5j0ÖYO“çw¿š××þ”ê㥶ß0Oω €¶wíôí5iìiòô|X‚éWP¢mEB1^óO½º_K÷_tÑE‡ŸuÖYWª1¾Y)ÒyõÕWïéééÁhÔ¨‰ÐÇ„K$Û¼Ýôžçç¼°öŸ¤8RœÇw¦ˆ|cø×ý'áµ9AfT¿¼ „KäTô'§úõêþ UÜ7ò¶ÛnûùùçŸ?;[â¿gÏž%wÝu×;rp»_+Ñ73DÒçͽÞ€a%Cä†~)o¯9Ú!'•ϋߵŸ À>$T&@Äù@]üËUuÍÕW_}‘Ú‰ïÕúúú‹#‘¬E(ñ§žzênõVþc‚Kÿä¯fHFÀT¸Æî&ÏÏ{QíZ 6ß@ÛåŒúwÏÏ‹ôÿòÖOi’8®êHÞÂaì?ñÐ…¿Týÿû¿ÿû¬‡zhÎá‡þ{ÕÓŸÕùè›7o~gÖ¬YKä`ß¿Ùa·À É€Uÿ^kzÛóóbûå£/ÕÒ°ùÄ¥£¾#ƒ‹z~Þ¿îžëûkÓØ½×óõø“ªótÉŠð»‰úuá¯ºà‚ ¦a˜Ïé§Ÿ~_YYÙ¤l?Y5ò7öøã?˜ý›¶4$#¼´ûõœœ÷(µ ο×~=o®ó!ç :ÝóóöÄ{äå=¯ûþúÀŒz=*E€7ø ¼ „'ú7Šøõ {4á?å”Sî¼óÎß|ó›ßœSSSs–ˆ7½¸7nüÛܹs×ÈÁÊÿ˜šú™üÿNvŒ°¢m•¬ïØ”“¶¨UÅp›U' »ç…úUu¸\VqNÎý¦*ôÜÛ³/×iUÛZÏ_‡ßv¾ÌÛó–ììÞÍ›A0Å?±°/Öû6±íO3‡vXÍ~ðƒ=zôEjŠ_¥—OTÿÑG}ô19tíßM@„K$+Y€=¯åè/8"?©ÿ|n@x÷ @¡ÙïÇþ,gOìx&0×jUûZÏÏYUT)¥Ö¢Jýø¡—¿bèСƒ®½öÚ謹—ÆŽ{i*â¯IEEEÊOtݺu¯¿ùæ›ëz£ÿ¨ðÛFÿÂ%’IþºëÕœ ç)ŠÊ/ÇüDÎU)òðEþSåºñ¿ÎÙ:óÇÍ‹e™Ï‹ÿú€u99ïø²1rÏa7ÈW†œ#å…eY9Gea… T&óÆ”Õó¦“ù @â†=åjxÏ5·ÿ몭ï9ÕÞ÷sµUï T„„ Ò¿imMmR¥Šþ{T­¢ÿ.é›þ7z'Ñ?'’ÌÒ¤Rį5¾­†ôäfT/Š/ýÒPZ'wmyÈó½á³Á—Ÿ#?ªû¶28¹ûS}tûì@]3,äŠEÕrYÝÅòƒ‘©Í²VkÙˆ]»´M³ÚcJe ´š˜¹õ…¬åR\P,å¥RVX*%‘Í@ôSŸÃ×Tª¯íÁû}³?øž_þäBÞxÒ¼mHßÊ~cú’Ë.»ìój§¾‹•€§Ôo ᯫ«“ÊòåË¥±±1õ×ôªUóÞÿ}ìÀÕ-Ö…vË}'þþI&yjç_sftþyØWäðÊÉrÕº›UmÀ¶@^G¤”!$Ÿ÷x§¿d>U;>¾¿ïã@];Ô*x=2ˆü•‡iG¶€IÀò—_7f P@/ð%üÅ—^zéi'tÒ·Uº>%áGšÔ¨Q2dÈéêê’… ˆüãñ¸¨ùÚûªk@¢Ñ¨ö56Ñ÷Ã?ü„Iô÷kÿÜ d¤Š?iY"Ó*§æôyL©˜(w«tì#*z}|ûSÒëÈÝ(¢¨‹G^¨¥zsÍÿmy(¯Ãj“ªQCjCý·†× 2mÑvÞxRGâ1¼øâ‹?ãŒ3¾[YY9.]á‡ÈCôÕV½šÀCèÕØ^QÂöüª*ihhE‹Ù›ðO?}õÃ?ÜÔk¢bßþç(úg€d…·>!Ó&LÍùó@ -‚_t¦<²m–ÖÇŽv6¿ÞÌOª>V¾UûÏjÂß8_<§ù{?T»=~È×àj“*¬Å‡ò‚2€4@1ßøÃÓN>ù䯩5ú1™~°k×.Y±b¢wlÙ«Eþˆø*(UHˆ–>Ûï­ŒC×ý÷ßè?¹ï?*©Uþ'þŸ€d!új^$KZWÈÔŠI¾x>üãúK4q}eÏßäEÕ.¸®c£/žÛ â9sàg土÷UQê'îØ<=°¯A.âg(Œ†úo µ»º÷ð¦ã’Uÿ>¹}¬\òðÃ׫ˆ?¥]úŒ„lÙ²EÖ¬Y£‰~SS“õëâšøÜŽöó*TíÀË*K€uÌnÑ·ë°ŒþiHÖ¸gË#rÄßúê9Al/öUíÀÜ /ZмP6tlötSüŽQãcÏø5Fvš/'>½óíº•–h«,jY®uP„ÝçÇŠäˆö‰r\ëRU-y•âZü•aÐD|ðàÁ}>Q_½zµlݺU{Û¶mZ @AAŒ7N3 ÝÝÝvÑçôéÓgªw;ä`ë_Ôeôo–   ÙÀ0<æ3NðåóÃF:úf:è^XܲLÕ.,Õj¶¨ÂÁ¦ž½»A×– “IªžèU˜xDåõï_°µs»fà‚ÎËj.EØ @¶Ú Cwbertëar”:JãýRújg?-⇨ˆµ–òß½{·–òß¾}»Œ9RÔ¾Ú1yòd­ PgçNû=+–-[öâÒ¥KÓþ“‰3@<áN•B>©ú˜œ¶°9a@QeTNÔŽX§f¶vm—m;¤KÍ7@TÙëÑÚ¹pÀåïo×*9к…¶­¡%ƒ5‘‡ð£š?H ríú¿h?_ÐAKê¥uß‘²‚Òðf ˜°¢¦§Z‰þd9²}²ÅS[0`€¨É}<ù-Y²DZZZ´”?|=–JKKEÍÐÞê òWÛùZžS ¶«í~ý[õý§ý÷ùs§ Y-xl›­ÖÞÿ)pÏýÙcËFkG>1{ÇóZG€‰y³éÝœ·¥fÕp àPP[ßY«"þ)2¶³Nû¿ëï¡Ä‘¾ÚÖWKù›Jˆ?¢~µKŸ º Ò‘¿ê,ìóDÿø:+T÷À j9a—ô­ü·[pý3@²ÎCÛžS§MI#þCkîÚòp¨~¦'wÌ‘/ <-%å4ÅLųSÚÆË±mSe ŠüSkõX§Ç¿^¸gÖñUš^:;;µ¢?…#FhŸ4hLœ8±Oq`¢°‹þï¾ûî§ÄÙŽN³†f€€d•U‰}ͺ[å¶ÉWçlŽ=±Ãs~µúZµ•ng¨~®OÕTÀ·´Z”Cš` @MO9\öÙ6IJc©­ïCøkkkµ5~5þ×öëQ০óIss³¬]»V[ï×kð>–ŒÀ2Ý8`e*^Qsÿýcí¿Ç$úŠ}ëŸeôO@|øpM¸e5ÔgåÊ•Z…?L¢¤ù±T#1iÒ$­SÀêñd…šú7Oe¶;ˆþí6ý±þiˆ§Ü¼ñÿ´ùìÙœNÜv?ìßvnß4]Ž®:B½þFÐ4ÚGŠ\Çh5¸?õ¹ˆÔ!üÉÃ{ì@å¾jÉÓ"x¤þaPݬÌÄa‡f[3€AŒ¶0==ôÐ,9Ø÷ŸÕ蟀x æñ_¹úrã„ßÉ„ò±¼ 9ro›™?+Ú:¯Vµ(7MüïÛRiöƒA=‡µ“i*ÚïM½V¯èÇú¾Y+ŸmmmÚLˆ?Šý°Ëßøñã1FX3'ËvŪêÿoüñæ^ñÏêÚ? É ˜[~E¯ ¨/É ’#flZú} ¯~æ¥j<õïÖÞ ¿óÿB3"8lƒ€PÉ?AEùG´M”Q]ÃÓªÛ€@#Ò‡ðÛEçf §‘?Zü°îê~´ùÁTàý &8ZB@§ÀÞ½{­¢ÿèc=7޵»-㙈þiHNhìn’­ü¹\5î´]ûˆw`ÐÏÝ›–GÕ.‰ùæ\»þV¹¢á?CQŠ €’¥‘ÝÃdJûxm>I<½n!Tñ£¢…}X›O¬õcºÖû‘¾6l˜f& þøÞú°' {`Õû¿~ýú·ß}÷Ý rpê_ªÑÜDðÙ@üCsO‹\¾êwò‡±W¨q­‡ó‚x@g¬K«ö£i~^_‡—Õ†P;Õ:¿hø±/¶\N+à.€AÝdJÇx™Ú6A*béÿHïC˜1£ßÍú¾}ÌõǶ=ˆ½^70fÌ­xÐ 6éÿø¬Y³’gþ§ý›Š= ñX€ øá¨—¿òE^,‚?¤¿—«½Èþ½*¾¿ü§ò‹1?–#Õþ ÌxÖòåÞ>AÓ›.H¿c}…}©¬ï'ƒJ}U‰¯­õ£ØÿÇz?Æ#›€ª¼ï¤þ1)Ð µ-ð{óæÍ[-é÷ý»ŠþiHÎÁ  [6Þ­íÎwYÝÅj®~?^” 󺚉݆ۥ5ÚÆ‹‘¶ÑýñÊ_Éi5'ËÅ#¾)µý†/ j°”áån–nÁæ;Û´)}#º‡fdé;ì! GªßIž£{‘ªÐÇz?„Æ š¹€à£ÐÏi¥¿¡ùÞ¶Í2úŸ={ö“r°ï߳蟀ø†w¿&KZVªµÙKU]À$^ s•m~©á„AzgïûÚœ€¯9WkU Ó²ÂR-›æ'úÅKTË^ŠöÇÉèΪq/3[^#ú†è£/Ý4"ˆÐ-Z¤õùc½â·n*ý“±ÛøG úø¥—^Z!gþÇ$µ¾×Ñ? ñ›:·È®ü…\0ô«ÚB̤Oea/‚Т:sdz2kÇs2Mm!|Þà³ääêã|µ“ ²e:6iƒÖ´¯W6׫÷×ûFüém¯“‰ ÒÐ5R ã™é´@êxþT«ù­@Š~áÂ…ZÁ†ûTTThÕý8¯›J#PHhUü÷ì³Ï>!×þí2þiˆïÀXZT¨¿¼çuùÞÈo†z#/¸°öåõ¦·ecÇ^ ‡Ôà(R­‚S+&Ëqý§É±UGª!ÔvÏÙßÏ‚¾¹s«2Ä[µ·:6k¢¿^‰O¼ÇW× “ù&v6Èøöz©ëªÍèß*"oˆ>Fë¦*Àv`2Ÿê½×ÄÛú"Àq¾8ŸÛJÿC^KJøaÌP…‹Ÿyæ™%IÑÌÀd%úߟA .‘¤÷‚Þ£0á€Ù)N8`%}þïÍåmÏ¿`jà¿×~iðÁ¾O´bK’˜0²ßpm‹è1¥õ2´dˆÖE0¨¸F{; È¾¨ -ÑÙÙµ[öô4%¼Ý%[;whY°Ýݾ¾(äßQ¯ÖõÇÈÈža’Éò´ðA𱾟h?Ìñÿàƒ´‚?ˆ5΋íS­ôOFß-Ð Õ÷ÿ5ùï õ.vÒûÿž¤#*öÛÿÒЄTj_¨–‰÷üaí2·ñM^ˆ,ƒ/KÕÒUa¤@­Íï°öh‡tÇ»]„Y­ÒÖô!ú™*ä;póV‚‹úÙXÛ7‹ÌQéÿÉ'ŸhÃ}€¾!†aí¿¦¦&íó,_¾Ütý_ Z÷Ío~ó2õ.¦uôf¬ @Ô"3 rèðG¶ŒK$,lY*?ýô·Ú,÷/>ClÍõmü‡jµÄ†?Í*ú$ÙBßíÞ“W[,íèªí´7®³^f e/ŒÔÅÚ>"o'[ðfTú/Y²D ÷ÙÀd?<û¡ ]°œ€ €o¿ýöÓð†b=ø'kkÿÌ0hÐþtÚ€“äÌšÏj›¼D xQl˜³ëE¹qÃÿñBCJcý¤^mºƒª}¤øËc™OÁ£’b áÏDß¾PéáGµ?Šýí£Ç¿ªªJ}ˆ¦Œˆêí×#ÔÞ;Tôÿeö¤ý›þå nP(õÂîyÚõ×Ï 8QN쌣̻Œ9OeMÐn¹´u%/ÑÐSûc;Qħ¶ÆgÞHCh‘R‡èãm¶SüF@ð,X õùÃÀˆ ºY BÚ?S…†vÅï½÷Þ3Jü[¥ïº¾Yäwp¤ <{ÔÞÏì|Q;P¥=­rªv €pRùxO*·ƒÖmRÿ}¹DMÀ‹Æ£¼ yúÑÕ›ÚWQþ žìŒB†ÈCì‘ÞGÄŸ­*~' Õb?ôøc Å…|˜€t+ý@êKF¨MöÝ{ï½/÷FýFѽ“ôÿ!ž#•蟀„ôsc­@Q¶§Z¸Æ—7¨·£¥AUpçrµí];e˜ª Ϩ`ÿÇ¡çÉãÛŸæ‹%O¨Œ•KCÇHÓU'£;FhCz²Di}>æægjB_: Ò_m²ƒÍv´ÈÏoܸqZ?ÖþQx˜i¶nÝjú9µ­ð ª0pŸ8ëùÏjôO@Bв° ,ŽDjÔ²AmÉ0ÕÖ5L[S„v®êãÕêýj©*ªÔŠ S©vîT{Ï·ª%жX›ìRË|˜Ãc]ûFYܺ\ËX\=þäµd‘ þ­öyMM¿ƒ!áŒò‡vÒÖòǪô~¦«ö“E½óØ€Ât.Rü‡„ÄJì1Òi˜ oå ñGú©ÿLÓÞÞnºí¯Ê>´ßsÏ=Ï&DÿFSÿÒ‰þiq¶$Æ‘l ’AK²¨+ÀMTï<ÀÀ˜–hëþ?zÕæ¥§Ô[•èc˜‘·l¼Gî=순,OàgúϺïÊÿ¬¾Š/„P+ÕñhëùêÀT¾l…èCP!¢ýdñÍ¥ ˆF£Z¥ÿG}t  õuuuZ‘ßäÉ“µ!CÙÀ*úWKsÕ»¤ï¦?‰Bo·á]ôÏI€„d’ÍãÈ4[:·©‰‡³´h<`Ì- 'ßlz—¿ä ¢nõµ=Cd ¿k” ë,ÙÜ3ñ±¦ÁGϾ¾¦ï‡h?µÆ® ?ªýUµ½ö1 ÷A-*ý!þøY²e<̶ýU» ö¨¡?O'Eÿv›þd\ðiñ l›-g¨6ƺÒ99ÿÕ}O>j^Ä]¢úúÎRûXÛÏvDÉ|?ªåÄ>×Ñ~"---òá‡b]+ƒIÁz? 2“&M:$[‘I°‰L€k×®}Sí7°Yìûþãb?þ7cf€€ú„?oº[®ÿ«œœ#l/Rˆ¿lº¿ ¢­å÷ T|£T¤?*«kùE{J>Þ"ÕŸªØ{m Pyÿþûïk3ýQé¡Ç:?L Òÿí‹ç£oÌ“çfÑú‡-£ÿ¨ËÈ?+Ñ? !9sú_ozG>7à䜜ÿ†|I^R/}Ú¶†¿ P/RQ~­6}oLç(©ŠfoÚ%"d ÁÑ#äÄ x~Kí[±mÛ6­ÍEx¤ø!þh÷úÿÈ‘# JrÆ#ÔhßKɨ"Ä^{íµUb¿éYñŸdË Ð’cnÛxŸê8:'[Ïb‚"füÇŠ+/’ÌSÝS© >úòGªa<…’½žyˆ#Òú|´ÄAøÒMíçjç]·nV鯊ë´ÁÄ`ºŸnœVú§k¬ÿÌ;÷Ù¿ÙObßTÌwþ³Ëd¬Úƒ€³³{·Lß:C¾?ò[99ÿ¤òqòÕÁçÊìÏó—ჺÈÄŽ1Jøë´–½l¥ö‘ÖG„¯GùéöæûŨ¢:m§=¬÷ëm~úV¾¥¥¥Úz?Ì@ªÂîæq(<´ÚôGíú÷QBôoõ›íðÇ6@BÂÊÌÏÊYOÓå‚ïŒøWy£i¾ìêÞÃ_F(RqýÈÎaZñބΆ¬¥ö!TzZ‡“m2!Ô^fPà‡yþhõÔ?€9˜è‡ŸâoVéŸ C€Ö¿äÏë¼óÎ;ˆþ;ÄÝà»Þÿ ¾. !9snÙx·Ü4ñ÷Y-ô2³þ£îÛòÛ5×ñ—‘!°¹_[ÏW­zűìÜn!v{¤ôñV¯t÷Cj?ÓÆ µµUT5½6Óß¾ý»-ê[ùâgGÚ?¹xÑ©°»yžúã‰@õ¿ª&`—ûûºô]û7ücµÓŸÙÎl$$,,jY&/í~]ÎtzNÎBDÌxgïüe¤zCj­zSÛÇËøÎÑYÙ\±×Ãm¼ê\­ù£Ðîã?Ö*ýQp‡ç€ê~¬ócôpr¥&£|3Ð÷®#Ô,‚¿ªÉ€mÒwW?«êÿ˜dh›_BÈí›ïW"|¬ô/ªÊÉùõÙÙ~ZÑWéýz5c’ZÓGz?Ó‘¾Þ“¯GùN÷«÷:‚Ϧ1@¥?ÒþØÐGïñG±®Ç¨Q£ +ýÓv§3›ü‡±¿Ó§OQÿ¹úcùg<ú§ Ägìëi–{·>*—Õ]œ“ó-,Öþ“ܵù!þ2,(T‘>ò@ôÇwŒ–’xfG:#ÊÇZ> ÛpØ °ñsj?Ýó¡ÂÅ~hóàd<ô­|Qô‡‘ÄnŸO& f`ö¿*Kñê¦M›PPÓ-öé³e€ŒŠ= !`ÎΗäì§Ë”Љ99ÿ?ýŠÌÝó¦¬n_Ç_F¢P¨(ä;¼c‚&úýb™ÝU}ëzµ¾>y/h|&³X_GÄÿé§ŸÊêÕ«µï­oå«¿Mœéïeêß*úWÏ;úøãÏ‘C[ÿÜìú'ÙŽþiñ!Øh·MºZëÓ÷<ºj³.]q¥ö\òŠh¹¶¦Dû$Г¹¥½b‚¯¯å‡1‚O…îîn­Ê¯÷øë[ùBôQéow½Ò-ð³z,jô"Äd6nÜ8_Í&Ø,éoù›Õ蟀Ÿ²²mµÌÙõ’|uȹ99ÿaäKƒ¿ Ïíz9o£} æ9²m¢4¨‰|™êÌHž¾gW±–Ô¾›¯EZ)ÿ5kÖèñ×ÛüpÝ`pݼHû›=Öj׿çž{cõÖ¿Ä©™Øò7£†€€Ÿr×–‡´û0³?\<ò›òVÓ{ÒÔ³7o®9¶Õ=B‰þ´¶ÉÒ?š™-c±~¯÷å#Š… sj?óíÝ»÷@ä¿k×.ícz›*ýa¿·×i=;¡?·dTWÀÒçŸ~¹ºéÛè?ë3hñ1mÑv­åäüU…•òƒQÉUënýµ¢6Ý9¶åp™Ô>F«êÏT¤¯ñéÛç†E¨³ñÜÐR·|ùrmÍF_ÛÐРù¡Ò¿¶¶6kÂîæqèH0üóÆo$þéw<þiñ9/«zÎôy9ªêðœœÓ _Ú=O>l^Êë;²k˜ßr„ŒU#yÓMóC4áësöƒ:'&ëüHù£èÃ~âGª×QïõOe'¿L&šÍýWÛoU­óåÐMœ¶Š—Ñ? !>Ex7o¼Kî:ì)Šæä9üWýÅòÝe?–®Xw(®éþõý:9±eš ï’¶è£b_ôƒ6k?ׯ‚Šˆ_µÌiâßÑÑq`#û¡×?±Ò?QÏ„!ÀÔ?³Á?jGÂ9ªM1yì¯Ù€§›þÐPÖwl’'wÌ‘¯ûûœœT¿Zù×açËý[ üµDïþg[Ž“a]ƒÓú>hC«©©ÑŽLòù)*Ïösƒb¤/Rꬭë»ùaùo±±O¶DÝícñµx®F(ãÒ¬Æþ¾*}7ý1Ûú×Í🬚Bv <½æ^24'çÿ×áÿ óßÔÌH¥¶ÙýLó±ZÊ?Uôb>¤£õ>ý|àSýˆôQì‡tº>àGßÍO½Ò?Õh=Ó†;þaç?#TíÂKêóͲ¿øÏjòŸÕŽžS „ßÓ©FóÞ¾izÎÎ_)’×_’“ŠÒ»î}±é4¹`÷—R} /ªÏ§L™¢£AüSÃl|m¦"x/Ÿúç1Ó_õËk‘?Äذašè£Ò=þFYœ;ñpóœSy\òcÍ¢µŒÑ­Öþÿ8­øOe3„ä#Ø®÷ݽ äÄêcrrþ‰åãd|yƒ|Ú¶Ö÷ת(^¤÷ÐrdJUýH=#ÒGÄ1J7Ú[Ÿê×¢ÒkþS}ÀO}}½ :T«òG»_&¢õL?] (N4bíÚµo¨Ÿi§8Ûõ/Ñd]ài Þt]u„”{vÎÖh›¼¨:Ù>Köt7ùþaLï™ûN–ʨ»H]ŸÌ‡¶3£Â3¦öÓ;†ú Ò0hD¥?RÿȰ$Vú»õl³èê©§žéþÅßwci 8[:·É£Jˆÿ­ö‚¬Ÿk{×Nyfç‹òÌ®5àwJcýä³ÍÇ©é}“\=Bñð£Šß­è„­8/ÓçÃÇõ©~*ZÖÖÒqõÝüôuÿLŠz& &šýUÆà“yóæ­–¾ƒ|9ö—€ðȶÙrFÍg¥®tDV¾ÿÚö òøö§enãÒ⚌Um}gï;U›ÛïFø±æ áOÔÃ>sçÃú>†û@ôQì!EEb¥?Úþ²-ê鮳^Îmú¬¶îïôð£Â€|vMËîÝ»5чø#òÇÀ˜.´P"ë2räÈ”~6/ gµéšcШÿ¼&}ÿÄÄyÿ¿ä:ú§ $Àìîn”¶=)ßù-ÇiuÈ_w½*3v<#;ºvòçF‘ßYj½ßém¢3}6Ä7hÏ Ûä®[·NµÂ?| *ü!üuuuZ ÓÑz¶ *ÿ1ªØˆ… þUÍþG_ ÝÚ¿oÆþÒ2fîxVÛ°g\Yƒå×ííÙ'Oí|Afí|Nš{ZûóÓ6UNß{‚㨟õ3µŸóáó¨ð‡h"j^¿~½öõXï‡ècCŸäÖÊL‰z6 Uô¯2÷ßÿ_{£ÿÄÁ?F™«ŠOÇþÒ2¢*•ËÆ»å¦‰¿7œÒ·­k‡fžÝõŠ6M0È`¨Úüœ€5~DœN+Ì™ÚOý¹éú Òó8Ðæ7qâDmŠýð{p»›_. ÖþÍ¢ÕÍðšb´GÌçþ[Uþç,Ú§ $„,jY¦õ¼¦m¬³¦}½ÌØþŒ¼ªZù¢iå³sü±{Ÿ°¡ Ö›[ûü&¾aYv@¤Œ6?¬÷c²&ý¡ÍODþÉc}ýRàgjÌ¢õ}bO>ù¤>øÇ*ýïfßœM¤ $ܱyºœ\}¬lìØ¸V>;ŽlìXüQaŽÃ.]æÔ¾WÏ £q!þØØgõêÕÚ¸\,·`ºf+ ãÄ„å¢ÀÏêqØòó ŒPS ?˜?>fw‹» 섟BHjìëi–‹–þ—¶Ö&ÆuÔËÔX_' Ò<±ÈŒ|öžzãQéñ×{üa¼Pð‡áJ¨½ÀãݦýsmöGà 5øÇ(úw3PüýÓ"Â&þµ]C弯Ï;ÚÐHüÃ*¾¹~nHTøCôa° €K´÷á-¢ÿL‰³×†kÿfÑ¿jo\5sæÌ…Ò·ï?*ûK@ ¥ñ~r^Óé¶;ùá¦ñdž2Lígÿ¹a#é‹´?"f¬ó#êGôo6Ó?[† “FÂoý¿õÖ[úØßn±ßö7&>üC@ñ7êVø¥ÆÓ¤´ÒQäñgŸÝç¡Ç,Túëm~h³D±ŸÞæ—XéïE´žéÌÄß,úWõÛ§OŸþ–ôÝò×nýßé f!œØ:MÆtÖÙ~Öœ“ÅŸ©ýÌ?7¤ø‘êGÔA?hóƒØO˜0ADþÉ•þ¹öTg·öÿÁÌQû´‰³µ·ci!sýOi>ÚöëPm•‡ëü+V¬ÐŠý0ác~Ñf‰?XëG»¥Ù„Å Tþ£ýÏ%ü{ï¹çž—“¢ÿDá·ÛøGüjh!¾ @ý;kï©Ú[+Ðg>|øpFðY>ÚúöÇF>z›2.ìƒÑ¾X~I¬ôw+Î~1~«ècÕÒ*l»Åýè_ßDû4„ßrBË2¬gõ K¥šQiž©>㯅 b´/ÄéÿöövMð±‹Zü¬:.üXàgõ8«ÊeÚÕØßçäб¿v)»1À9þi!¾ ¦§ZNl>ÊòkpS‡ø˜­7ûM|ýüܬ¾ÇæÍ›µJˆ>züa üȺ åJ·Ï×Ë(ßÍcýcYà µ¥ñ˪àq·šþ·kô…ÀÓB|Ï™jØ]Ë_MM”——3‚ÏÒùðxô÷£Ê_oóÃǰÞ6?˜€ÒÒÒœ {6 ÕŽêãÝ>ø`òà§|9ø‡€â+êºjetç˯ð¸)ú£1p÷µˆ„‘êW[ÜjéÌõG¦E/ö³ªôª!@wÚÍPfèoK—.Ý*ÿ¤2ö××u4„Ü¡n‹§ï³ÞÞ7v¤Ÿý"¾~àS=Ÿªr×*ý‘ò×ÛüPh™Xé™þnŸŸß Öþ““øížx≧¢»-Í Å¯Ñ? !$§Lé'C»­ ÿúÇö¾Œà3"~DþXçGú3þ±ÆñG¥?ŽÄs­ÀÏìq0=¦UwÕ俵âlì¯]€]„Ò熬þlÓó}ågË3µŸ¹¯Eú•þC´ûaw?}ªŸ]¥®¢üLÓ.úöÙgg‰³-3ö—€â&¶7È€h˯IŽ@s%û9‚Oõ|Hó£Ú?±Ò_oóCÊ¿²²2¥ˆ=†C0ÓÀâÚ|ôüóÏ/“CÇþZ˜8üà !$¿9¾õËÏ£âSçÁgî¹ÌñG¡DiTÁ£Èó þ‰•þ¹ölTþ[Dÿ¢¢ÿ'åÐÊÿ¨‰ p’òç€O‰ !ÄsPõ?¬Ûºªßh[Ù ‹o®Ÿ†Ý ÕßÜܬ¾E¥?Šûôõþºº:mÉÅ­Èú¹00ù±XæÀÏo†*‚üä™gžYœý;ÝøÇ÷ci!¾àØÖ©–ŸGäH”©ýÌ<7¬ó#Õô7„b }Ðã?räÈ•þ~ŠÖ3ù8<]VÌ™3çqٿ寛Mìªÿ}K¾€@Ìg&$ÌTE+¤¡s”éçq3·‹þ™Úwþ=õ"ò‡øc¸†ü`yE³Ë ø™=Uÿ¸f¨¥… Ñ¿Ýà«~_ŽýÍGˆ4 !ùÄámµ«èÛ͆A|sýÜÐÖ‡J2(ú«®®>öwRéC€:d=¬xî¹çfDÿ‰GTÌûþ©+¬ „xúwxûË/ÁŽs?m ‚àa¦?Ö¼‘À´?½Ò¨ôÏ…°çÂ`¼±Ùv¿½Ñÿ¢Ù³g/ç3ÿ¬ûû~O€¢ü¹í«=ƒ02¦k”ôVš~‘?¦Ð1‚Oý|xãÆZ¥?ÒÞ¨ôÇÇôüÌ*ýD6H~fÃÈ_« €jûKŒþízÿÍ–Xæc €‘) „xÀäöq)EÿLí;û¨ôGÊ© »A ±Ò‘¿ÓJÿ\Eë™~2!fþe”Ïš5+9ú7kù ä¦?ùf¬Ä…€„ä€Âx¡Œë¨3ÿ|aá´t®…:#7!Ÿ*ýí£èoݺuZÔ«Wúc#%ˆ?Ì€¢u¯ ÝÐÐ[ùßžý›õý»Ùù€Ä@ìÍŽ(oË„xzÿûÅÍgúc=nîLí»ÿZ÷¡Â_Ÿì‡ÿ¨ô×·òÅÚ¿ŸÄÙ«sÚŒüÅ4ÄTôÿ‰Aôš-óÅ$‹¿]äíu{„˜Ô1Æòó0Aß\?7´õ!íßÖÖv ×K)cÇŽÕÄ•þ~ßÉ/çÄuA6Äê¡jÇ¿Gåе³â¿@nù›O«,€þ~,Á´Ï;vÖ)ê-zŽŠ{\“„£ áˆ$b`8"BH~1x?ñmâßI‘*î+¿ô‘oüFý¥Vøa·?/Zÿ2rƒñ‘1@u; þ v¨ôG €^é·‰¦*HéûäǺ}œ“¶?•1ùÛ+¯¼²ÒEôÈ-ó͘ â¡ÿ"ñ‹oé}[”p81 ?ÉcÑ·~ýÀßMñ™gž9^ |YªÑ˜#øTÏ…?TúãÀt?ÐÐР ?Öû­*ýƒfÜ>Æ™¡ B÷ôéÓýwf úlAy €UÊ?ñsV&¿äný5‘ð±¢ñ/L¸‘YehH>Gþf⿟¢ã?~²Õ7u[ü—ÏÆÑ-ŠüPÜ€ÍmPÜ7nÜ8-åñ/**: ša-ð3{Úþ°Õ±K–,yaÁ‚› @ÞEÿaÊ™3—fôKš<¾ ÷ó 74a€Pü‰Lÿ:µ}˜Ù7E¥ºQk÷8ô|fƒb?ù¡âí~X>A±*ýý£›"—âœkC`·ÛŸ2mwÞyçL1Þñ/o¢ÿ0'f –tcJ~³¯OŽþ n~B#@húAÂßOL­GWªÙþ¦ýýËq¿ö Â¢ñÇz?ŠþpíÐæ‡B?ôùûQœ“›M#kƒÃ ù?­2(;Åxê_&¢€‹Ü"  hÂ[3ñOŒþ¹þO(ü}E_’„?Ñèf¹H­ÿO²ú;ˆù]|sýÜ0Εþz±25552fÌ-òÇûA™à—­Ì–FÐögc¢vß|óÍODÿVÃÜFÿœè#C`$þ—â_ Ækÿv±·ÊEþÉêx³oˆµëÄêÿ¬ÜÞQ€>XëÇ[˜6ÿÐ9ñÆSO=…‘¿Å?ôÑX €YÕÄà3ýäåDá/0¹ñ1ú'ùý‹þ%Fÿzv ®DËtû?ˆXrû_¾ûÅ_DüèñÇX_ ³Á?Úü0ÞÑ¿™ø%ZÏäc1ùЮðmùË_¦KßÂ?£Vp'3ÿCý‡1(þf¿œXÒÍ,Yücâ|ÝŸ€ä›0[û×—Ñô¯ÓÞWûÏ7˜}cLªãšÿÁï¶>}?´ûAÜñc¦?Úüô­’ó±ÀÏ챘‚ˆŒ‰ï¾ûîÌ•+Wnç}ÿyý‡ÉØM42‰¢OzkÔæDÑ'ù"ôfŸ3öShðõÚߘ®ÑfßÔ¬ú?÷hllÔŠüÍêc}õJDýV“óÕ`.Ú"­PŸß¬Úþ戻¡?1 ÑŽù–A·Ê$ÞÐâ&ÂO@òÙØ ý1ÿ¸êï/T3þMa];L|ªçƒè£ÚˆŸÃLŒõE›2%n¿&DÖïFÂ.õ/Sëþ÷*£ ï÷Ò#îZþb‚ÿòÅ­û›™€¸X§ùüÑ|2FÅÉéP}¶†f >ûÙÏŽRëÕÅV Ÿ×üñ9ìä‡k0ÞÃ~0ÆëýHý£Ò3ýígúœ0Jv=ÿj9eþŒ3>㿘˜ÿYeBý‡1àÆ™qõÓ|3‰™²‚¤¯Ñ#ÿŸ4i’iôoT˜iñõƒ‰0ëûXïG{ŠýPü‡%Œõ­®®¶¬ôÏwCà$õ¯ê:î¸ãþµ‹qáŸQ&À*ò]ôF`g̾6î ê§à“|~#P`ùG’n¤%b¦ QüómÜ/*û!þˆbùà `2"ˆ?Öüñ}Ü>ÿ|0÷»cÇ»žyï½÷ž\¼xñf1Ný;]q^@`g¬>O@húŠÉ¡Ó6ù*=Êì›;Yÿ£1@ôŠ6?}ÍŸÓ+ý!þ¨ôOü¾¬øï 2&0PV¨¯YuÍ5×`Þ?RÿÝ)Š wùËw`f$IÜ“72%Úô!Ÿü7’ü·“¾iÿägDŽt’ÈêMÀGèíG¥?„`_Jµ[¢e¥¦EÖÏFÂì¹vvvjÝV¨lJ×í·ß~«zÛ*wû3úc7õ/ÔÑØ €‘ 03bõÇý“<#n`’_ÿ‰¢ot3Ô– Êˡ95a÷«o胔?Œ@b¥?Rþz¥˜¢õL>ÎaÕ¿ÌŸ?ÿ‰wÞygX§þýåEyrC‹8¼Ñ™EDŒþ 1ΉD¥²U–¿¤ÆôÆSäìÖc°yófM¼0ÖÃ~ð³c¦?Rÿ0FÙVü÷Rÿ«¯¿þz=õß%é¥þCýç‹°‹äíÖú)þ$Þ.Sfõw9ú裇ʡ3\¿ƒTž Öôt?ÄëôJµI’Öãït¬o>Ìù·«úGêÿÎ;ï¼U™·©£ €F0B#@Á'ùÑýXÔšQ ŠÚ†›žLÝØÑï”>•ç†õõë×k[ùb¬/¯ÏôWµÚš¿^éïרÛ†¦ Ýv êÿ­·ÞZ-ÖÿÌ6û‰IÈGþÒ˜ÿ¹¾Oò³,XÜ$`e$´C¥¶‡š}Ä?Ìkþ¨ô‡øcÈÏ–-[´!Ý?fÌ­Ò‡Ñ÷Ïç?³¯ƒø£MÒ ¤þ¯¾úêÙr°ê¿GÌÿDŠ^„E¼÷þ‚i H¾ÿMD\DüÉ;œÒúÐ÷@ªÂV?þ#F`S$Í À?gC±$Ì”j™¥ç¾ûî»#¡êßMôïtÚ_hÍ €sS@H‰80Nßgn€Zë®2{€›ílsÁ§úÜУñW;ÏiÅ~‰•þØÍ•þ~Y¿'-@Uü?6oÞ¼•²?õo%üQaá !ÄÔ즪„Éû(Ðßì‹õõÿ°¬ùãkQè‡jŒõEµº^éÁ>hó³{LCÐ÷k‘ú·›ö§–W]{íµ‰ì¢«ô^4„·Q¿.ö“ÿG¬ €hiTúCøÑãb?¬W'Vú#ò7*xt*–aYÏwsN,Ømô£2Í7Üpƒ>ðG/üK§ï?o ÿh!™ÂÐ¨Ž–‚<î"áGÁÚý@b¥?ÖüõÇçûz¾ÓÇ¢å»"Ú}ùìÙ³o[¾|9*,“×ýͶü52yYøG@IUìEÌwÇ<°O€JyW:1^‹}¦ŒÒü~ô÷cH @ªôèÑšø#ú·KsÓj¨ôkiÅ¢E‹þúÐCÍëYÿVÑ^þÑBÒ5fFêQ £E€ÙˆàSýÚ––Mü±Þ¯G«¨ôÇ559¥óç³!pºËZþþøÇ?>(û·ù5kù3[û;0y•   „¤› 8d+mµà8¤™MMMZ‹Ä•êøYÐßÁ>½Ò?(Q·_ž+"»uÿŽŽŽæë®»îeÀ0ÐiêŸ=ÿ4„¯ ª€/TGZK~4)ˆ¿>Ö•ýXïGºÀÉxã|/ð3ýþh›´û¶O<ñÄ­ .Ü(Ίþ£3ñ·~vBH’À›e|LÂ¡ç­ ]àc€ô4&ú¡Ðÿ/++ÓÄE(öÓ§æC´žÉçŠA?0v¨Q¿3üñ÷äЖ?3#à¦÷?/£BHºf y@DÁ¹¾¯øu&"}½ÅO니=þXëO¬ô÷«ÈúÕèEvëþªÍòcµî?Cö¯ûwÙDÿÉUÿN¶úçcôO@q"ö‡ŠŠŠ’L<—Ækü˜ì‡õ~}¬/¦úÕ××k‘?Œ@£n?<ó0ìÙ+T‘åÖßþö·7'úMŒþS­üÏë@4„¬dTdœÒ}ÅOû )ÿ+VhUÿÂ-|!üˆþYà—Úãð9DþÈ®X¡2m7ß|óu*ó‚Þ@¬û'¶üY™€äÂ?¦þi!YÊôùœš„—ÑûŠ×3P鯷ù©Ês­f)¤û!þÉ•þF¢Ç?óÇ!›‚ìŠ*3›1cÆ-óçÏÇ¿‰ýþV•ÿnÖü%ߣBH¦ AD d±ñ“1€8­[·î@¥?ÆúêÅ~ØÆWµ7æU´žéÇÂ\9¨ø—·ÞzëQŠþŒúýíÖÿ¶ûåu !$ã(‘Lù¾’«}ô }ùë•þ}Dþ¨øGb¥¿ŸEÖ¯†Àá˜_d^^¿æškžã¢?3gÛý2õO@ÉVF ÓKÙŠöu ö(öK¬ôÇ&>ØÊâ´¿Yë" ³Ç¢ÝÛ%Û±uëÖEW^yåêÝ6—âû¢?³h?oÍ !$%¡7û¿ËB7‚â•Ø}­¾¡ÏÊ•+Túc¤omm­V臹þ\ÏOïq¨£p"þjy`ÃÏþóë1ñOý¹£èßJèYH!™BµlÅrýœD¥‰•þˆò±™¦ú©VFíÈÇh=“çĦI;Ó§Dïÿ*Tk \X‡CñO¥å©BH¶PÞ=6!k¢îô{`-ëýˆü¡b¬ï„ 4ÑGÊÅAY¿}Ð]¯?Úýn»í¶«?ùä£1¿NÚýìÖýÍ¢ý¼74„tˆDsÝn„%]±wk P‰Žõ~½Òëü´÷¡Ò3ý½ØÉ/̆À©ø+3ØýàƒÞ0wîÜårhÅ8Ÿùï6êg&€€’IñªÍ«ËêAv¢-c€ÿcËY´ùáÀó€à;V‹øñ~b± üR{¬SñWŸÎœ9óÖY³f-ƒÿf©ÿd#`ý' }Þ·üÑB²M\€žt3™6#5S^~ýaÆI]]–þ‡øÛ‰ üì ñG1¥“õÕW§?ðÀoJßv¿ä ~ìRÿqáº? !ÄìÛ·/#€L­ù#Íñ×+ýñ=1Ösý‘öG¿*çã(ྠà×׉ÁSƒ~Wc~Ÿ—CÛýìvùsjÌ¢}šBH¶PvÝ™0™0(ðCÄ¿|ùr­Òëûîƒö>´ùá’Èúõ¹b´occ£#ñÿý÷g_uÕU3Å<íof’ßí Š? !$‹ÄÕþîݽ7ÛHº 5>ü ÍFëüz± €U¥? ósb´¯ú;úúÅ‹¿¤v÷{´7òïã‚?»èßÌ$ =×ýi!^‰¿þŽªîîT£s wͱÛ.Æ‚¤·ùá|Hóc¦?fùCüõJÿ GÝ~x®0YNÆû‚¥K—¾|ÅWÜ£Þ5ÛÚ×éö¾õK@ñ‹à'\‰n›™Hu€SáB:æùãÀÿ±Ö5ûAüÆú²ÀÏÝsÅÿU­‡£}€j¹|SøMÿ.›è?Õâ?£×%Í !Ä#Çp•b˜ àtK Û·oׄ©€*Tûëâïר;H™üþ0KENX¶lÙ<ùß©×"Güµ÷ ¿“ˆŸE4„ŸdZ­„bm¶ÁN*Æi~läñÇ®~øÞèïÇ.~Xë7ëËõ|÷C›ŠýœÖq,\¸ð5ßÿ>Ù¿æŸ8ßß*âwýÇ„E4„ÿ™%­vQdº@èj9l#«ÍÇ:ÿĉµb?LùÃô¨ÛÏ×µç8ÄçÏŸ?óøÃ ‡âŸJÚ?YèYôG@É5*=Übg–O%ÚO{Ì#ò‡ø£ Å~hóÃ÷FÔ3m¡ Rf!•窯÷£“Âé)ÔŸn¼ñÆç\ˆ¿“´¿QÔÏ¢?Bˆ—¾A´•øÿ˜ Ë @&: JˆüQéý( ¢Š5#€Jÿ|Ö3õ8¤ü±Þï4åÙþÏ>ûì]ŠyrpÈ“ùþN6ûaÑ !ÄçÆK–‹ëoÞ›À[LœCÁ"£1B;tñ·Z^ !°Þ"»â´Ê(ÖtÏ=÷Üô /,–C‡ü¸í÷§øÓB‚h”p4eÚèÂáÇÝüð ÷Á,]üÝŽ¦!8ôwƒìŠ›n Õz¹öÿ÷o\²d 6Zègm~FóþÝTýSüi!9Žø“‰©b±ÝVLe ‚áÇŽ~¬óc¸Æùb­Å~º°±ÀÏýãæÇ`kýjƒ¥÷ñ‹_ÜÖ„µ‚ýâï$ê7«Iq›×"¡ „x,ø’•ÅUŠ~O& ÒüzäýPàñÇ:?ªýqx!²a+ðÓƒ ¤üÝìÔ¨ CÚÔçÉk®¹æi9Xì×#Ƴý­ÄßIÑ_ÜàuFñ§ „øÀ$¾© xvÛEóNg@œõ£¿Æ RSS£õøCàõ#ú×…‹ëù·ϣµÂïvƒ&Õq±ýþûï¿ýÅ_\"SþÝ¢µÿÄ·f›ü˜‰?¡ „dYÜ#&7̨Êü]vßkÍvò µ£}!þØÕ…~µµµšq@ê_¯ô÷«ÈúÕ £‚¿T–bV¯^=_õ÷ß½sçÎF1NùGm"~#ñONùÇŠ?Í !$¦@LnÐq©·ª¨²S µ©ÂC„¬ –”1u›ú ê)LöC±ÄßIö€† /ˆø!ü©ìÇ ~_­sæÌ¹ÿ¾ûî{S¬·ò5û¿•ø;™òGñ§ „äHôͲFo1  Q õp+`&h*ºÔ Òò‡˜É©Š? !Äg‚q)øÉ)[-ÂS©û­V'Â:4D ‘= âAüñ9RÔ àÿ\Ï7fJ?RöuÔVÊ ~øáÇß|óÍÕ½Âß%Öã{FývBˆOÍ€þ³­WoÞ1U¸·Íî~ žA¥?„K‰Vè‡V?½Íëþ~Žºsé#S‚#¢TÁå†Y³f=>{öìåÐi~fsûÍD¿'AôôúSüi!4 É7gí&¯Öð79µ0jÉà@…?Rþfâo'–AZÏwúXÔGè¢ÌI&D¨VËj÷¾Y¨îW3áwbœÌô·šðGñ§ „Pø“·D?øàƒMßùÎw,¿‰.þÈôïß_[ë‡èCü+ýƒ­§j^ øz]ðS­à7CkÞª&ù½pï½÷þ­w÷ÆÄa>f‡[á·Zï§øÓBBbú˜•ÎoQâÕ¬Öï«ìÄëü¾Dñr´îöqøZ½&B›©?U›±éí·ß~ùÎ;ï|]«Ý¡ðÛmÝk¶ÖoõSüi!ŽünÖúÍ>ªzÏ·©ú, @¢0BüЯŽ%€Ä_c4ø'h†"yüœºèëc‘³ý{S†lѼyó^™1cÖø; „?æÂX rÔïd;_Š? !ħ¢¯i°:¢ª|‡2\,A“ÑÍ€nô÷Í ‚׆@ùd±Ç[ÙŠêÍP©ýæåË—¿£Šû^]°`Áfé»aO, ñ¥õSüi!4‹¬@⡉€*òÛ„ùý™ÂI¤œh ÿ¯ˆD·údqO|« º~‰œü’TÿÖ­[—«Œ·zè¡ù*£’<À'f¹Û‰½UÄïDøjG(þ4„€eì {ÔT¿µS§NõZ}!Ä^ƒÁK‹/~gæÌ™o¬X±b§:µ/Y¬í €ð[¥ûÍ ý(þ4„€DúNf¦ÿq¨ôó§gžy&¯h–~OjÖ†O?ýôcµ-ïü÷ß)þné;±Ï(B7~«%³ïc'üN·ó¥øç€/!ÄæÞI: ŽÂÞ£(á(î=ÊTEõƒ>øˆè3‚—4}TWEç–-[–/[¶ì“^xaÁªU«öÈ¡ó˜­É[e¬Öõí"~'é~Š? !$ âÀàm L€:*Ž9æ˜úÓO?ýØúúúÃKX‚P+NŒÔÕXÞNõ6® ðÚ•¨koÕ.†8ÚÔN|Úû*šoV#v›Ô|ý}*}ߨÚ÷*¡oRkø=6ÑyÜ&²6}7Ñ¿]V nó¼ì*û™ò§ „„܈X/Õ$‹~âÛ‚$`$üN10 f_“ü«ŸÙLÄŒö>°q}z‘Ñ[»iŠfÑ¿YzÞ­ ˆ;ˆöcb¾çƒðSü} çBœ`40Y$"IïG“7ùq…½_ëÔˆ‰€[}˜|}º×ÂÊ$~,fò9'‡Sñwc쾇“ç%BH~Š~¢°™€Ä#j"’1ñ/0È2ˆK3 6ï§c¬RÛv†À‰ 0‹¾Ý.8z ? !„¤ '§»ÍÐ…Èmôï$•ïÔ dÃ8Í ¤ý»1F-{©Š¾Sá§øÓBB˜0,&Âo¶s`AÂ×§³öo—pbÜ·‘¿ø‹MäoUWàÔ¤"øN«úõÓBHÁˆ™|>Ñ87…|nÅ?’Ÿ5Uñw’ ˆ‰»e7n¢|Fý4„ ¼m@„=f"þqáwý›™€t²V·‹tÍ2é.¸É¤áSø !$mCàÆÄ\FýÙŽþs±i3ŽàÛ‰=…?Äp!$•û…U+ž™°»}§Q¿W~1"™| ?ÿ  !ÄõýÂÎDl„¾ h?Õ´ÄÅÏçTSépcÄÅÇí„>Õú(ü4„Þ3›;Sà¦Âßíz6ZÓÉX s<…ÿ»‰îÓÕKñ§ „Ç&À©É|¤Ÿ©Ö¿l™§ÙtDž¢Oh!žšgc{~>U±wõ§[`%°™4©<…ŸÐBrj2!îN¾¯Óç•iŠ»s'Ÿs"òñ6B@!Žï!nÛM$ï4ÂÏFÚ?ÝŒ@:Q{ª‘}<ÅŸÐBHZ÷‘TÛm4Ÿ­h?S&Àîÿ©~Îé¹)ú„€â #à4Bwŧígº0QΤ¸Sô !Ä÷÷7‚J4ÉÀsLWLã9ú8EŸÐBqo‰dùó^ÝãÒÀ3Y GÑ'4„@Þg"YøžÙ¸ßųôõqž !…¼„~ Vâ|,!ÌBByÿñË=-îÓïE !„÷%ŸA¡'üC#„߯(ô„P„²{ÅB!„B!„B!„B!„xÊÿ½Œ£ŒXçIEND®B`‚icon_512x512@2x.png000066400000000000000000001741301347155106100372740ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/CocoaApplication.xcassets/AppIcon.appiconset‰PNG  IHDR+ƒøIDATxÚìÝxdW}7à3õ•¶w¯{ïÆÆpÌGsòBB ‚ ùZƒ˜lbBŒLy )`=´ÐbÀš{Y—õºlß•V]óÝ;»kïÊiFšÍœû¾ûÌ£Ñh¤Õ½çÎèü÷œsC²*gÞFÁ.@gðú`" ð: Ã(À뀌 ($¯S2F °¼6Èa€"ÈðëÑ{@öŠpA€‚hòס×9@œ Mös€×Ÿ×2 XÀ  @¼îrMú{(Λïÿ(D€:¿Þr^ë̲ /ÌÁÿ‰¼Îjð½^ÓÙU¨ñó Ê¯±\ül²Sà×#8@^[~On^×Þ'澘ŸíÏ*ÔàwÀëªÊÏÏUáÿòZˆC5ÎêªôàõT…ç×âk^ÿ þj…Bx-Õ¨ðÏUñgy/hþ‚¦Å}¡FA€@^C³(ÖsüŒ\_çÞâ*ügó˜@T©øŸiá_­pÀû@óåê…*=G ¯þ•~>ÛÀû@ã‡3-þgûy5~G©â¶…5CïÍTzf¿0ƒçUú˜@™|Í”{¾ÜB¿Ú@-_ÿÞS…{íÞtEy¥÷+ùZ¹Û*@ô¯•jžáŸêþž[K…ÀL_ûÞ+æ&(˜É<þÉŠùÂîÛøîÛl!€ÿÿ•Üßû±´èoMní»o-»o•þ.Þ š+˜Iávüéç£Ém ¹ìL"ÕjÀ¬‹ÿrβ— Ê-üs{ÿmÉ­ëÌ/]ø¦Îýæ½ZP®ïžò…»ѽú˜…Ý÷ “<¶wŸSÐ @ñ?õc•œÝÏMñqÏ™ÿî3ÿý‚7'Åÿ«4j ûN#XüOVì禦 „Ètñ_nÁ¿÷Çü>Åÿ=—h"f e’>éT#„PüOóX¥Cû§;óß¶»ø“â€Yöus“üaŠ@ PFQ¯È€â¿Ì Ôcû?ã ŠªLWôçÊ Êýhêâ¿’!ÿ¹ €üÞÅ×=¯ÔDT9(5쿜À(d¾øŸéÙþ½ï?:ìÿŒë/økÅ?5 &ªtø%!€€@ _üW²Ø_©â¿œ¢ÿq þqýùoê:¨çÏ45 ¡ô¢€!Tg húâ¿Ò!ÿÓ{ù?ÿ¯»êUüPíþoK(½ÀdŸWs*€AQÿåœõß3çWñÿùóߨø ZBé)“…!ÔfQ@}ñ?ÙçûžùO‹ÿƒÿÔ¬<Ý!L=% ÔÏ5 @™+þ+ òŠÿWh"æ((L7(þÃãÏöO~æÿsŠ&˜„PÝQ )ŠÿÜ$o !”?Üï3ÿékpÞéŸ;ÿ ]‡(þ¨[žˆ¯ð{«9 @8 €¨Šÿ©€G‡ý§Å·â€úõ‹§[pº>s%£@Sÿå.öWê±=Åræÿ¼´ø¹& Nö.þ'Ž(LÓwžlxÿt£ÈDñ?õ™ÿK‹ÿùŠêÝ?žl$ëÄû…iúÏ…*ý.Âd ø?Tñ@Ã…÷'*g‘?…}ƒj± Pü+þÈT?¹eŠ~ëd!ÁtýéÜ4}ðœÝÞŒ@ñ_¿â^Rü¿^ñÀj ûÎÿ/Õç-LÓ·v†¿Iÿ•ÿåÞZÿ4Xyº³ÿ!L?`ºþ·³þ Èÿ3+þ§{óLõ½‡ý+þhÔ „éרóy˜ä9{>ŸêjSý>FÔ‰(þÿrSô…C‰>q5ûë ©ŠÿÅ?ML̤¿¢.þ­ö@³S…Sõ»Ë½Rˆºø™& ‰€rB€Éž¯à@ôÅ‹â€È€©úÌÕê«#€¦+þsŠÿy§ÿ«â€¦ ¦{N%!@n–¿hªâÿõ݇)þhŠ T_wªyÿ¹*üß@ñu¦šËŸ›¦O­°€âš¨ø%úÃ¥úÑ!”^$p&ýx ø€ö­seþ³í‡#Å?4PÊ*-îPü@ÿå\(þ  ûÙSÍëŸnñ?€ÿФ!ÀLæÿϤÿ0ýíé.ïWêk }(þ ÉúÞå† (þ ÉûÞ¹2¿& €âš°ï=Uq_é:¹*þ^Pü+þ Fýp‹þ @ñ÷Ãs3øž‰×s¤ÿЍq]/Å?4a_|&W@Š(þ Yúæ³] Ð(Þ`ÿÐ`}ó\Šv€Å¿â¼¯x€â2Þ—GŠPÔ#À‹â@€â_ñ ÑoGŠ À†â@€â_ñ @ñ¯ø€ÆêÏ#Å?¨à…¯ø øWüPü+þ ¹ê(þÿÿŠŠÅ?€Å¿â@€âŠŠÅ?€Å¿â@€â_ñ @ñ¯ø øWüÀöÿ øWüPü+þ(þÿÿŠŠ(þ ø øWüPü+þ(þÿÿŠŠ(þ ø@ øWü Pü+þ(þÿš¥øŸî{ÿ"(þsŠÙ ÿš¼¸Wü Pü+þd­ø/õ=Šÿ ü‰÷ÿ"/þseÜÿ0¨FñߢøÐþdÏ/µØŸâ@@ÿ3]ñºùþŠ TZüçBesþ»ÿÍ©Õ.hª¿ÞÅË>Åÿ¿÷†îCÿÍÈ€æ,þgò}åùWühÐp 7Åsf2ä?§øPÿ¿Ü⿜ÿK…{ßZ÷*þ_¯øh~Öh®â?Ì øŸ¬ðŸîÌë^ÅÿË5 0QWKgèÎw‡žäÖïÚ}^ñM$ýøè™\kñ¹{t´t„ÑÂh+Œ=úØŽ±¾Gï§ï ã…ñ°slgòµþâÇã¡l Ùù€L‡¥FTRøï{©?Å?dJ>—‹Z„%m‹Ãâ¶…aiñã¢äã¢âÇ%É­7ßzZçí.ôssò{‚$èK‚­£ÛÖѭaÓÈæ°ydkØ8²%ù¸ë–Þß:ºmŸ @@3øSù¥«tÑ?Å?d È_Þ¾4¬n_Vu캥÷ê: ìß±:´äZšbz[{Š·ô÷Ÿ.,xdxcX?üpxph×mÏý{ïOF ;(M”;ï¿ÜÿÿEÉYüû‡wë>8ÚuPXÙ¾<’ŸÏÌ>HÂ=AGè}|8ðÐð†pçÀÚpçε~Ü”ŒPÏ¢¾Ü¯M7ôªï+µÚ¿âšÌüÖÞpü¼£Ã»‹ýôc:”Ÿ©Ãý:Voç,<óÑÇÓ©{€ÛvÞ~Ówsqª€€F rÓ„¥n-Šh>é¢{GwNžB8¥÷„âYþ¹š“›týƒÓÚžN›ÿ„GK§ ü|ǯÃoûn ¿ìûmqZ@,Å$ÕSå/õqº[Ë^Åâ[GK{89)ôOR8±çØdÎþþ þ9´nh}øÕŽ›ÂO¶ÿo¸qû/à+ÐD¾{ÊÎM>lMn#Éml÷m|’“Ý “|œì&ÜSÜeêŠð•ß ]]Ø1Úg§QÇ&gÍ €¿‡UxN% ªX`†×t·W®ùã°0  –ÇZzéÈsžY Ò0@ÑD Zr-a¬0fG(QèO·øßdóÿË € Òu`xÍþ¯(Ó†zémí uÀ+‹ÁÓU÷}$Ü3x¿B“wrtAÙ,ìgúü©þs@¨²Ž–Žâ<ÿô²~­¹¼œ8¾çèðOG_þåá/†O?øoa´0j§Ð”ZrIÄ`€``VÏ)5ïªð˜ÆAû‡KþËâÙ˜ó?ܹÖð‡+/N.xR¸|íº¡õv MØéi±æ€wßæ ¦þŸ+ñX©‘@É[.9ãQøÈÑW(þi8Gt>zôû‹Ç(ÄÔÑ vŒhŽ¿Ó­þ?ÕóM€Xغ ¼ñÀW‡Óœlgа:ZÚ߯ù“pBÏ1áÊûþÑ•hé"€ÌÁû¯]0'}=‚\p˜‘Óæ?!\{ÌUŠšÆ“ž>zÔûÑ݇Ù4I‡H@ ˜ésr%>–z®JH/¹ö®CßTÍdyûÒð÷G\Î[|¶At@uAæ‚)ÍLUÄOuÆ_áä“•ý_ ¥~β§Û4­ö–¶ð¦ƒþ_8¸ë€ð±>“,²n™u´C“ÓPªÈ/UØOö¼rWþ7v›ßÚÞ~ðëÂI½ÇÙDðG$^¸âyauûŠðÞ{ÿ! Û)4œ]€9zÿ¥Y‚€rž;ÕâÓ=™t`çšðGþ­âŸèœ³èIáïg2e¾A“wsPê/¨³ÿP¦Ã»8âoªŽvQ:zÞáÉ1~yXÒ¶ØÎ ±: ¦2V¨Wã{sSÜŸêì5~'hjG&×P¿ò°·‡Î޹:÷KF¼#,ÐP"]P€` –?«T@™s|ÏÑáý‡¿=ô¶öØdÂþ«Ã|WXÕ¾ÜΠA: º ¦+îK áŸêì¿¡ÿ°—{Ž ï=ìÒÐï¶3È”•IñÿwG¼Ó”£Sc €€²çóOöy®‚Ÿm™”.ô—ÿ]-v™´¢}Y¸2ý²¸m¡Áw@uAÔŠyÿd^z]ôwò†ÐÑÒngié4€wúfAsÛ11@À¬‹ôrýsöŸLI?{Ï¡o =ùyv$ŽHÁ¼ì׆|.og0GÝ3 rÓ¥žë¯/Ñ›—ÌõO‡ý/o_jgÀ^N›røËþÌŽ`Ž: º ê@&´æZÃ;’aÿ‡thgÀ$ž¹äÜð‡+/¶#¨ÇÄSïÓ=ž«ðû!z¯?ðÏÃɽÇÛ0…—®~a8sÁíêÜÕ0[S…¦)ÿgéáüÅgÛ0íŽ\øëƒþ¢¸8 Ôó¸@@å…~©ùÿ¹ ‚ˆJ:äÿUk^jG@™zó=á­ÿUqÚ Ô¥šÓP«‚ÝÙ2£;ß.;øu.÷:jÞááûý¡" jõ³ ^¹ð†_öï\mgÀ \¼üYáÉ Ï°#¨CT@ h¯ÅÏÏÕùw9óÜeÏg+^`Lráu^–´-¶3¨í±æ*¦-òs³ü~ˆVº€ÙËö{‘³”®ðÚ^iGPã¨n € ›E}-¿ß¥ÉÈ )Þ˜¬bÞÕÒig@œ±à”pá’§ØÔî}Û"€ê\3A$ž¿ü™á„žc쨢W¯ùÓ°¼}©A: º!sÁõ~â-è'[ñß_[¢³ºceøÓÕ†þ7¢¡ñá0\.Þ/Œ‡cû|½£¥#´µìú3”Oþ¥Wp qÌËw‡×ìÿŠðæ»ÞmgPƒN‹. €€© z`’äë|UèL Iêc¤0Ö=6o F6…‡‡7† ÉmóèÖ°c´/ôõo;ÆúÂðøHE?;ŸË‡žü¼dú¼ÐÓÚ“Üï‹Z„eÉYèemKŠg£ÓÛŠöeÅçQ{{¦|cÓ÷ì ªûþm@U üU%ÒÂäÄžcíˆY7´>ܾóîpÏÀ}áÞÁÂÚäãúᇊgóka¬0¶n/ÞÂÐÔÏ]š¬R`×þá Îô¶&ÚuP8¬ûК„Tןí÷âðí? ýc;í ªØaÑU(Þëýsüõ¥i¥ÃÅ_¶úíˆ*IÏìßÔw{ømÿ­á–þÛÃMý·…í£;ö÷Ý8²¹xûùö_=úXGK{8¢ûÐp̼#±óŽ 'öS\ÑžÙY˜ŒÂøãUÿ7\³î“vUÓb*@¹^¼ò÷Ââ¶…vÄ,lÙnÜñ«ðãm7†·ÿ²éÏð¦kü¦ï–â-„/†–d•ñúg.xbr;%žŒpÖqfž·ì™á뛾î¸×Π*LP§¿¹vÍnMÇêdåÿ‹ìˆØœýßÝòÃð­Íß·í¼+êmM§*ÜžlczûÔƒÿZ\?àÜEOç->;Üu€ƒ¡éú —ì÷Çáõw¾ÓΠ*\@P–?_óÒd®··¯rFÃ÷·ÞœÁýNøÅŽßÔl£{$Y¬ðŸþ÷â-]3à‚d ‰§/yªie:eþ‰á¬…§'ëüÄÎ`Ör9SÔäo¬]@LN_prñÆôÒÅô¾¼ñ¿Âløz̗ؔç1w Üþ1™Óþ‰õÿ\ .^ö¬°çj;fé(€¶ý¼*Î € †Æ\x¹…ÿ¦•^žïº¯ßÜüÝâ¼xJ _ÚððŸ¾Y –þxÕï‡#“…™ÜªŽá™KÏ-î3˜ ‹¨uíMî)‹žé:ÐŽ(!]µÿ_þbøÂ†¯(ü+THþ¥g¶ÓÛ)½'„KּıV­üÝðMÂ%fÙ)± Àœ¿Íñf•ÌMÏÎòxépìϾþ³açØ€R%éB‰_IÖOøÃ›ÿ¼¸ŽB:B€Ç¼pÅóCGK‡ÁŒ¹$'€€JÿvBF´&— {ñªß³#ö²slg¸òÞkÂknk¸gð~;¤FÒ—ŒxÃS¼Š»,n[ž»ìév3 ˜Ì…É¥ÚVw¬´#v»mçÉõׇ¯nú¶3Óuòóí¿ /¿õµáGÛ~jgìö‚Ï ]-v3$L|“JæþÿA2ܘ] Õý[²Èß_Üö–°~è!;¤ÎÒÑo»ë}áCë® #…‘Ìï­óÃ3’+ÀÌ: 3á/(Q;kÁiÅKe]º°ß;î¾2|øO»ûJC˜ëùJø«Û/ ÛF·g~\¼ì¢bHw^7€‰þïŠgg~¤…æî|gøþÖ â¦þÛ«nûëpÿàúLï‡4œ{ò‚ÓÌ êü€`/ÇÌ;"¹™é}pïàºpÉ­o,®öOcypèáðÿnK¸9 ²ì÷VüsÀ„Â"Ûgÿӳ˯»ãíá¡áG *ñº;Þ~Ýwsf÷AÒe=¨cPS{¬l_^œÿŸåâÿ¯îx[Ø4²ÅÁÐàLJ›ïzw¸¥ÿŽÌîSu¨”€G]¼ü¢Ïå3¹í÷ >^sÇ[ÿMdçØ@xãîØ¹6“ÛŸ†uËÛ—:*ÓÞÒ.Xü”LnûöÑá-ÉÙä-#[M¦o¬? ð®°adSö:Épîg,yšƒ€ Ž€ qÎÂ3CokOæ¶;½¼ßÛ×^zÈAФÒQ—Þõžâ´€¬yÆ’sÍë¦lFvçen›ÓëËÿí½W‡_î¸ÉÐäÒiï½çƒÅ6Í’t À)½'8(¯*,¬îXNì=&sÛýÅ _ßÞü@$¾¿õ†ð…G¾’¹í~f2 Êa€ 'SÛ<<>ÞuÏÂÐø° 2#…‘pùÚ«2Õ¶­¹Öä5|¶ÆgúÀõû»kЈÎ\ðݤmQ¦¶ùÃ|*Ü=p¯ÆÔ½ƒëµë?›©m¾pÉS5r_ØðÕpçÀÚÌlï!]†;×hx¦d a]-áŒù§df{Ç ãáïîûpñ#q+Œ…Þÿ±L]à)‹~GÃ3uÔ]OZxjèhiÏÌöþû†¯%—‹»[ÃgÄoûn _ßôÝ OÒèLÉ"€ Þš¡3†}cýáÓý›FϘ¯ÿL² àP&¶5N€’P#@6õäç…S矔™íýç‡ÿ=ìíÓð³ydkqäGV˜ÀT¬07Zí`®µðôЖkËĶnÝþ㑯iôŒúç‡þ=\´ô¼Ð›ï‰~[Ÿ–|„ïœ|½r=¡÷¸G¯KFÌËwOùüt˜ô2“%;´É׺Z:¦üiØ<Õõ;“ïo›âÿhɵ„y-SÿžÝù®âóJiOþÖu$ÿÏ­ýw„WÝö×@dÏS™™mýôƒŸ ãƒ=£vŒõ…ëùrxɪD¿­«;V†ÃºÎÔ(ßióO.Þ²jnî¿-Ü5pOôÛ™Žò™ê²hEcF k²²Bø—Íý§„¯oúNôÛØÛÚS\ xLÁ€È’tèÿá݇D¿é¥ÿ~¸õ§œI}sógâʧfd­(—5)'õW\0úoÓ÷’ÕÞG58“Ú1Ú~°õ†è·óÄÞc46Ù ÷¸Llçmþ¾ÆfJßÞòƒè·ñ˜yG„Ž–v {‹ [À±Ñoã}ƒdb‘7fçÆí¿Œþ‘m¹¶pt»€` @dÄ’¶EaMÇêè·3 gv™½ÑÂX6¦ô«±aO` ²"+Ãÿ¿»ùG›òŽ•-?ÊÀë^{Œ@f€ œ ¼cçÚ°nh½Æ¦,¿ì»©xň˜Y3f ²âÄ Œøñ6—þ£|épà¶ý"êm´<¦à*€È‚%m‹“ùÿ«2ܨ±©È 8fŽï9ZCC° 2âØ œÜ8²9Ü™L€Jü,¹ÀHa$êm<ªû0 ÁUGÍ;<úmüáÖŸXà‰Š Œ†_ï¸9êm<:¯(+0™ºã/~²ýš¹!òcgaë‚°¼}©†&ó¬€èå’Gtõ6Ž%×tÿMß-›ùß¿‰~î6 \Ñ;¸ë€ÐïŠzoî¿=ìÐØÌÈÚû–‘­Qoã‘󬦉 zY˜ÿû‹ œÁ¥¶EÁ¯úâ^ÀB€` @d@:þ¿Øñk ͬüïŽßF½}GtZœ™Œ@ô@ä#†Æ‡Â-ýwhhfÄ=Š$t@ç~šlF fm¹¶p`çþQocZüF56³²nh}ôë¤ë@¦W@Ìì\Zsù¨·ñ·ý·ihªâÖwÆt Èx` ¢îðgàŒßͪv,ÝùûÁ™Ls@DíÈ;üigî&€2ߌ ÛÆŒ€ yÝ7ø@Ø1Ú§¡©Š[’`¬0íö­êX:[:44™U° bû€[ûïÔÈTÍ`rE‰{×E»}ée2 € /˜€Hõ¶ö„¥m‹£ÞÆ;îÖÐTÕk£Þ¾ƒ#¿*L€Xš¿îØ) ºîÚyOÜ€dXÁ@Äê È/ù•.x×À=šªº3òcê —$ÃÆŒ@¬èÜ/êí{`è¡°sl@CSÝ`çÚ¨/¶_ÇJLf\±ZÓ±:úB ªmÇX_xdxc´Û·¢}Yh͵jh2É€ˆVìgúî¸W#ãØª´’kI.¸\#“ÍÀ€ˆQz†/=Ó³˜/×ÆÜºoð¨·oµid50qvðWÏôÅܯ¡©‰û#Öt¬ÒÈd301Ú/òþha´¸ ÔÂ}CF@”€€ˆQìgøî\Æ cššˆ}z‰+U®€8€Î¸óÿ©¥£}aëèöˆ€Õ™L2QZý€42ޱJ}˜4° b´²=îË|­6ÿŸcCG»m­¹|XܺP#“½À@Ä&—ü[Ú¶Xq³ðÐpÜÇØòö¥™ìÖ@l´ö†Ž–ṽCD½}ËÚ–hd²Ì‘V»¨YÇ>ò3{Ãã#aóÈ Mm€ÈG,3€54>† #“~­lg²’ÿãçñ%ÿvŽ ”øyÃþ¼Í#[í`@Äey[Üû´0+ 9Qããl(ö`nF<í7ô~ùÎÉ×GÝîWÝ÷‘b=6Ù™ð¤°îëŸôûF £a0)Ì'30>FK\–µotòŸ7šü¼ñAo4€ Y;öõ²~È€ÔÞ¦d”I:Ú¤½¥-Êí[n @&}yã Pæ€5€Úuì#ÚûððLÍ¥EÒ†‘MÑn_ìA!@6ŽlÖÈÔéX‹7Xj€æûêÞ†7idê Ç6-i[Zrº# šÚÒ¶Åq#êD<Ú$ŸË'— ¯‘@4³Em ã†7jdêÄ6-j] ‘@4«Ž–ŽÐ™Üâ.ʬ@޵á¸5#@4±…‘wèwŒö…¡ña M}€Èæ…Í+öáÿ›G·jdêfËè¶ÈS@4oy‡~k䎷úF€Ð¡oÔ‚lD@ýìÃã#ñ¾_´ @4q‡>öÛ52u>æâ ˜ ‰€VTÓ¶ˆ9—ÐÔ@äS¬@ݹx—ÐÄzó=Qoß6#TMO~žд@kÜÀöÑ™ºêëvÛæå»40€æíÐwG½}}c;52u•^ V-¡5—×È gÇXŸF¦¾Àø@ÔÛ×ù{€x€–ÈGŒökdêŒÅÌ€h>¹ä_W¾3Úí+$ÿúÇM ¾"{h ÎŽ|r&/ bÕŸÌÿ/ŒkhêjçØ`ôï€Ð‘o¸êÄ}ܹ @b™úwÑ/èR€  fp|H#SÿÀ"€€h4]-qŸÉÔÈÔÝ@äÇ]gK‡FÐ|ùv…TYì#Ú[Ú42€æëÈǘÀœÉé%(cÕ‘3@óuäc0fõ—^zrx|8Úí3@3väsF@-Ä< ö‘C "íÈÇ}&/æ³°4¶þˆ/Ø! #ßhF £™91ñ±ûÈ!:òMh<ŒidæÄX!ÞcÏ šPì#Æ’ÅØ@På÷ #@4ŸØó5€9 â Ÿ,  µåâÊks%ê5LÐ|ZsùÈk0WÇ^¼áS‹. €&|cÉÅýÖ2f@{Þ7@B>ò·#pìU_.ù€fëÈçàØ«L>ò©C "}c@mŽ=k ä£à*Ìѱg @4ÖKÜo-1_Š"}Òb Í'—‹»#o€tHŒÐ|¢¿ €Ë"€ þ޼EqìÕ¢C¢K éä"kÌñN?ÉY@ó)„¸çÈç½u2WErÄ5òx°¶€&ìÈÇ}†<ŸËkdæèv¼Çž©5 š1ˆ|•ü¼Åʘ³c/Þ`ÜÕ5@4Ÿø§€ Ú\]@3vä£ `®Ž½xÿl ù¢_À['s£5×q`€¦3nÔèØ‹÷϶«€hBcA59ö¢¾ €@Ó)âžÐb@æ*p@4TG>¸ *c :òŠ0xô¶5Ð@†ÇGP­F ‘Œb¼u2WÇž5Ð@†Æ‡ã.Â,ÈœñþÙ3@óŽ=0Ç^ Þ7F40€f3Tˆ;h ¨þûÆøÐlb?“×ÕÒ©‘™m¹¶h·mP  €ÈGtå»42s¢;âðI # 6Ç^ÄáÓàø Ð|@Ü#ºóê/—üëhivûb¿z€8€Ø§´˜ÀwI𔆱2@ˆ¼#ßm æ"ˆ@  Œ †ñÂx´Û—®Änõâ>æLЄ É¿ØG¨·Ø§ž Ižà¼|·F¦®:#Æ52€fûB€FPgó"°c´O#€hFÑOÈ ¨ó1qè4Z3@³êëzûzó=™ú‡N}cÎþ€hZÛ"λ°uF¦®æç{#~¿Ø¡ Zí 6úmQoߢ¶ù™ºZØoèdþ?”%Wæó  Î@ÜgôŒÀ1WÅÀ˜I¡_É÷@ÍlÝõö-à˜@cüeÿ &¶EÄ<›Æ“ÏåCok¼ Oš€¢¿>€`&€Ôõx›ŸôrÑnŸ(ü€ a™@}€¸·£ýE¸ P±¯ÇnM†eC]€È§œ@Ä…C áµéÐ'szÇ ã¿›ç‚V—¤>bq²Ý(ü@ó*$ÿ¶G~VoQëB M]Ä6õ€ÂªŸWéMÔßæ‘-QoßÂ6#¨# )Šÿjû³ùYi­Ÿß}Ë €šÛ8²YQUû›"¯ úÂ?7ËïÍÕàwJ ÿ¶~ô£Çyä‘m{jW3-ÊÔIÌaÓÀø`ñMXøÏÅ÷N§ewßþéOú¥ù|~à¶Ûn»iÏÿ+j G´ ¨Ó±qàì?)þsux~zk[±bż«®ºê²®®®³ÿäOþä콟$jŒlŠzû–´-ÒÈÔ'h‹9Ø¢PøWgÎÇsŸûÜU/zÑ‹®MŠÿ'%gþŸ¿eË–áäñôÒ\ c? ËÛ–idêÐÓÈ…¥‡M2\øçªô»¥óý;_ýêWwî¹ç~º­­í;v|鵯}í÷“ÇÇö~²¨™ØG¬h_ª‘©¹Åm C[®MÍQüçªðóÊý?÷Ì÷ïxï{ßûÌcŽ9æš–––ù…Bað?øÁ»’LJÂcgÿs ¦6D¾À²ö%ų³…]#ª &–G4 PøÏ|¾rëþÈG>òûí·ß›Ã®‘aÆ ¾æšknOîŽì.þ÷I jbÛèö0R‰vûZ“uT­@퀸§šX€È‹ÿR—ù+瀹In-» ýŽäŒÿ’Ï|æ3×$Åÿ[÷ÿccc}øÃþ`rwxbñ_ì¿j[ VÒ3ã›G¶&Cåã-`Òâl£†ZcmK¢Þ¾ô="-ü«ñøÄç‹ÿ¿øÅ‡=ûÙϾ¶³³óø½Ÿp÷Ýw¿ó§?ýiÚ9Û+Èí¹oPSoˆzû¬@Í€ÈGľVQÿ¹i ù\™çÊüY{ ÿâÿw¼ãç^|ñÅ_›Xü üä/ÿò/¯“ ýßós@M­z8êí[Ù±\#SãÀ¨qá_iñ_îÏ™¬ÀÏ•ñܽ¿¾gØZüÏûЇ>ôÊ“O>ùŸóùüijPã7ÜpÃeÉÇÁðØÙÿÇý?¦5õÐpÜÀêö•™ÚcñcCãC¡l§F`.‹ÿjþÕ|,LRü·uÔQ ßò–·¼oÑ¢E¿7Ù7lÙ²å_Þÿþ÷ÿ"¹;Zâç@Í=ù€5«425µª}E´Û¶Ñhü¶Ånß³ç±â|ÿ?øƒ?8ìùÏþG“!ÿ'LöKŒoûìg?ûÞðø³ÿ!LX@ÔÔ‘ûu¨Åm Cw¾+ÚíÛ0lþ? ]üײðŸêg¤gýÓZ½ó²Ë.{Z2äÿêdÈÉ9ëÖ­ûà×¾öµõ»‹ÿÉ~æ£!€¨©Ø§¤—ìléƒÉPf¨¶Ø¦õÃid±ø¯duÿJ>/ç¹Åùþ݉+¯¼òUûï¿ÿs¹Òuûððð]W\qÅÇî…ÿÆ'ü\Wê+]àk`|0â¿"¹¨çh3×@ÜÇÖú!u+üg[ü—Z̯œÏ'»?ñóGÏúŸuÖY«?ö±}ò€xËTÅêæ›o¾|íÚµ;ÂcsÿsS…F5÷ÐÐ#áà®".ÒV…»îÕÐT]ìáRìk„Ð0Åÿl ÿ©+÷ŒÿTß“ß}ëxÍk^sê9çœómmmûO÷ ÷õõ}çÒK/ýÆ„ââüS€:wò“i1tî§‘ÌÀzs_øWRü϶Ø/u9Àô]É*þ/:âˆ#Þ™œõïœî. #ßýîwßÜ»†þ?n¸ÿ„@ÀU€zuòãæ{Pçþ™š8°sMÜï Ö`n‹ÿjœõŸî~©¯·ì¾µ}ôÑ‹Þô¦7½{ñâÅ¿[înܸñ_>ò‘ÜvýŸì¬˜Pü» P÷®»HëZ£‘©º–\KXÓ±:Úíëë;Fû44‹ìB ÿJŠÿjþ{LkñŽ—¿üåÇ_xá…W'—ø;²Ü_<¹ìߎ뮻ëìÿØ„}7ÕS€Ú»gðþ¨·ï€Ž5Åbm¼0®±©šÕí+CGK{´Ûg@ªÌöù3î?“¿¸Êrëzï{ßû¼cŽ9æÝ---=•üò÷Ýwß?|ûÛß~pŠâ² ¥ø˜«5wïຨ·¯½¥-)ÖVhhªê ®¸§–˜ÿÀÿ¹ÿS­æ¿÷c¹)ÛSøú;òÈ#—^{íµï=î¸ã>Xiñ?44to|"ìºì_¡ÄïS*°P{ÛGw„­£ÛÃÂÖùQkë†ÔØT|m W`Š"½Pæóf”{Ö&gú÷þøè*ÿ/}éK»è¢‹þ¡’!ÿ{»é¦›þvݺuýá±³ÿ{ï³i?ÔŽ‘O8¨óLu©ØG ˜QqŸ õ?ë?Ýc¥n{Îú§Cþç½ë]ïú½ç>÷¹_˜iñßßßÿ³·½ím_ »Îþ‡I~‡©Bˆ"P÷E> àˆîC42Uupä¡’5(³pŸlˆýl‚„ÜÅþl þ‰Å:â¾+™ç¿üSŸúÔU'žxâßçóùžîñüàïI>…]—ý›ìwœªø/Þ7¨‹{ˆzûPEéâtî' †"¾0Gÿo9—»’¥ó»kíŽW¼âO¸à‚ ®JÎú6› J.û÷¥«¯¾úîËþMÜ¿{ ¡ôÕ@½€¸G¬h_V\ã ]ëfëЮƒB>—vû†Æ‡Â#Ã5t†å“Y¨£…1;h„²~º"¿Ô×ZvßÚ“‚¿û=ïyÏK;ì°7ær¹ŽÙlTrÙ¿Ïþóv]ö¯0Eñÿ¸‚â}PŸ`àþè·ñ°îƒÃÛ¥±©Ê±³ôÒ …99!D£H/ÀÜÿ³=ë?ñ~ñ¬ÿù矿ÿK^ò’+,XðäjlX²èß'¾üå/§éÑ …}¨¤øOï €ºØ8²9ú+¤ÓTåXêŠ{JÉÝ÷iäÌ÷Ò-CŠõª%ÁÕ*üË)òKþé›ZºÐ_ç›ßüæóN;í´¿mmm]ZÝpÕUW}4”>û&¹_r{÷êæ®k£Þ¾#ºÕÈTéXŠ;X+ȼ¼ QUüOµ˜ßT_ß³Ð_çªU«ìcû›'=éI«VñŸºõÖ[?xÇwl _øo²@b²Ï÷Ùf#€º¹}àîpÊü£Ý¾cç©‘™µ¶\[8¸+î+¬¸WCO#"‘«x±ëfê±ç42Ð(…ÿd…s%gý;^þò—Ÿxá…^‘Ìû?ªš¹sçÎÛ“Ëþ]v]ö¯œ3þ{¾÷v@ÝݱóoiÛâ°²}yxhøÍŒ5ï°Ðù=w ¦5Z-†A±Šy‘K ¢"¾0ƒï)÷k³™ë?Õýô–¾‰µ%ÿ¼w¿ûÝ|øá‡¿a¶ ýMæÇ?þñ߆ÇÎþ‡ ÿ‰[TÓq=G…‡6 ˜¹ØG’¤klݦ¡§1^1Ÿ$oÓ³ðŸ.Èï¾u>ûÙÏ>ä…/|áûz{{O«ÅoÙ²å¿?ðü8ì:û?ÛÂÿQÞ}ºY?ôpèë=ùyñóŽ ßÚü}ÍÌ€ž¸€»ý/Kz‰¼Žˆ·¯=âÑ À”…z¡ŒÇfZøÏ¶øŸn¸ÿž!ÿ]—_~ùóŽ?þø·åóù5ÚWc_ÿú×?ö]øoâ6•ó¸˜;éœÖ;wÞNê=6Þ ç( Í,zF¹èG˜ÿ_fÏ/òKäµ·´kdÈV¡?ÝógòT«ð/Uôïù<¿»nn?ýôÓW\rÉ%ï\ºté3k¹zè¡/}æ3Ÿ¹%ýs0á÷,”ØþB¹í"êêÎd!À˜€tñ¶t„C:Ò*µ_ÇÊäR™ ¢ÞFW(Ϩ Ò²¾œb²¢ÿqgý/½ôÒ žøÄ'¾3Yáy-7p|||àºë®»&ì:û?^b[g| EPW±¯žÁ=©÷¸ðí?ÑØTìøž££ßÆ»å qÈr_˜á÷MõØlÎúOöùžËûÏú¿ò•¯|˲eËžê°:ËÚµk?ó½ï}ï°ëìÿd«ýÏŠ¨«[úïˆ~ŸØ{¢€‰ù2™»z.…pe‰}@GNŠþªþ“öSûÓÝO ÿ=Cþ»ÞúÖ·^xÊ)§¼£Ögý÷ÙüÁ~ð韽ŠÿB™ÁCYûXÔÕº¡Ãæ‘­aqÛBEìÓSIFôõ6Þ7ø@ÒØe+ŒF½}-²[ø—TRø—*ø+ ö>ëßqÚi§¥gýß¼|ùòºœõßãæ›oþè]wݵ5”žû?“ý½O@ êîæþÛÃY O‹vûÒyÜ«:V„“«@¹é:0ê`,•…@Õ Æ£Þ¾yùn qøåžíŸôõe• ý/g‘¿½Ïúwï>ëÿözõßc``àþ÷½ï}ׇÇÎþ×D‹ã¨·›úo~Oé=ACSÙ13?þcFPI÷4DñÞÿßÄb¼Ô×§+øgzK‹þâ"ÉYÿ5×^{í•Éœÿkê]ü§~úÓŸ^½mÛ¶°ïÙÿR·™r þ~ÛpÆ‚S—7þ—Ʀl'÷ý6Þ¶óN -@Ü¡Ba_Ÿ*0¨æ¥ýöÜò{Šÿ·½ímO?ùä“/›‹Â?µ}ûöß\qÅßJîŽTi_—$êîöäJÃã#Ée Ú¢ÝÆS矺ó]açØ€gZ]É|è“zâÒ×üÝ÷hì2D¾@½/·èÜ{‘ºB—ûÿÎd¥ÿéVùÏï¾uœzê©+/¹ä’7%sýŸ7‡û»ðíoûCaßËþM¶/\hÖŽíHÜŽë9*Úml˵…S{O ÿ½õ48Ó:mÁÉQb©ô5ûÊöÕ{x8/?O#C\A¡ÂçWòœ™,öWêÌZø§—!é¼ôÒKŸ‘Ìõ[[[Ûò¹Üy6løïüã7†]sÿg³ŸËjksâ¦þÛ¢ßÆß‰x¡Cªë¬ñ+¿é»ECW`ÇX_ÔÛ7¿µG#Csü•|=WáÏžjž˜¢¸o)ñyË^…÷Ygµÿ§>õ©«Ï8ãŒ«çºøýÜç>÷á°ëì¡Ä>˜­}‚#€9+~Ås¢ÞÆt€Ö\krÖsTƒSRk.NOFÄî×ý7kì ôE,n[¤‘!AAaBÑ^(3P˜épÿ0IðèYÿË/¿üyÇ{ì[’¿!.»³nݺÿüêW¿zWxlá¿ÉöA9gö “|^ØëñGï €9ñ«¾›Š‹\åsùh·±'âš®ð?ÛnÔà”tRïqÅc%fãÉ%í²°øg5ííZÌWò¼É>ŸîûË)ü§*úÃîÂ?½¥óë:_ð‚ýœç<çí½½½ 3änlllàŸøÄµaß¹ÿå*LSü—ü>0'úÇvW?fÞ‘QoçKž"`Jç.:;úm¼s`mñ5O@ä#–´  ÁŠûRÅw©âºÇJÝŸ®èŸê÷)w¾~wñßqÈ!‡,zýë_ÿkÖ¬yI.—k¨Åvî¸ãŽùÙÏ~öpØ÷ì%gý§ &%æÌÛ}ð¤O ½É\×£}œÇéhéO^xzôÛiþåúÆâ.z™^ P0  LuFºû“M˜iQÎpÿ}ùK ÿ§$óüßÖÑÑq`£íØááámúЇþ5ìºì_¹Å~ašÇ å|E9óó¿Š~Ó«çœs>ÖˆÅꦛnºníÚµ[Âcgÿ+Y8±0Mñ_jþ¿5€¹uKÿíÅK]Å^=}ÉSÃ7|]ƒó8ç->'úmLÁüåŽßjìJ€ÈG¤Vu¬÷®ÓØÐœEaš¯Urö¦ þíSü'Å~÷Ûßþöß?æ˜c^—Ïç4êÎ|äÊ+¯üBxüÙÿ\‰â>”(ôÃ4AÀ¤ß/æ°0+.xf2L>fGvŽšwx¸µÿΣ–·/ §ôžýv¦ÃÿLJ4x…b¿ @1h_¡¡¡1‹û™þ“ÿ•¬ü_iá¿g¸:¯¿ãe/{Ù.¸à‚wtwwßè;øÆoüä¶mÛÒ”·œ…ÿJÓ(É`Neehðï.–ÆfÏYöôÐ’‹ÿÏð϶ÿRcÏ@ìWH­îX©¡¡± þé öRC÷'>6ÃüK ÷O ÿ®#6ŒlÒèÿ{Ö’ó3±­7fä5^õ #Vw Tôç¦)öËYѿԀr~—rÎüï=׿ó²Ë.»èÄO|S{{{Ó¤‰?üá?>::š‹/cŸNu–¿Ô× ÓFs*ÿ¹nh}ôÛٚˇç.†§è‚dîzuˆØ=<¼!Ü5pŸt}”tý„˜Ô¹¿††Æ raêùù¡D±BéÅs¡ò3ÿé-=qÝ‘Üæ½èE/:áºë®ûä©§žú÷ÍTüoݺõ–«¯¾úûÉÝÑr õ B€ʼ@ú˜˜s?Þú³Llçs–^æ·öjðÌ÷¨ráùË/ÊĶþhëO“ÞGA£Ï@ºß6ŽlŽzWv,½ù UôW; ˜ÉÐÿIW÷O÷[‘÷Á þ?{çG}¦ÿ×ê½[ÕêrÅ4 ¤¹”#—Â%!„;ÒŽ$—ÜýÓ.—äH¹¦0¦cŒ1Æ`Ó1¶%Ù–mõÞ¥Õêÿ{FŒ¼Zm™í³3ÏןùlÑîÎÎoGò>oyÞË×çååÅ݈¥7Þª.&d~ï¿W_÷ž  Bˆ ØÚ¿ÝÇ™¡f^ÿsÉÇøÛœ Ζê´E¶8Öçû^â]Ö V—^ÍšØ þ@Kõ©¦Ï[Ò;[šr÷Ϲîºë>÷óŸÿü™ªªª«,XwÏ»ºv¨Ñ„ÈxMIàÙo‚?òÿÙÇ3@‰9o5JÏdŸ-Žõ²…ÔÜ߉=éßçK?e‹cp ÊÎá=üÐCÀž! µü  ‰­øbÞ›¸wø¤øOð üåx¹Ö5×\sÎwÞ¹nåÊ•?MJJ*ˆÓµv®_¿þ6™Éþ{ øþ¾Ä¿À9ûa€sPêúBÿ˶8Ö”„dù\é'ù¡Û”^(•iå¶8Ömý;djzŠzX½¬Ì\Êšsø „º%ÊñrÿÌ|à *cþ'uyw<¸ûû¢¥¥åù|p—xîý7"ü½=ÎhÀœû „˜D,l·Í±~°è"Yž¹˜ºÍÈHL—Ï—}Ê6ÇûtÏf~è!Ò9aý €S³OÔZ!¦  ,ߎýF³þºðGYFIIIáõ×_ÍÕW_ýDQQÑDâû„Ó霺ï¾ûîùcÿþTøºBˆyxeàMÍõÚÿ».oUý«6€Ø‡«Ê?§FAÚâXáþÿÆà.~è!Ò:Þnùc„1*Û‰™Ð7bÚg¤·ßˆð÷ ÐúüÕ–õÃþðcùË_6,^¼ø;‰‰Ê8É477?µiÓ¦f9^úï+KoÄÌOÄw€ß*!¦`rzR¶¼f›ã…ñÕå%—ñƒ· 'f-—,¼Ä6ÇûtϺÿ‡cm¶8Î3sNå‡MHì‚Þn{ „RþïšõŸíó¿êª«Þ½fÍšµgœqÆúY¦ONeÿÇUÃßÄ{￯콯*ßž‚ ³× „˜†=[lu¼ŸU^õé5üà-NjBŠVña§2ç Ý›ùÁ‡# *ìH¹¤ð|~Ø„˜#àM¸‹_òï*þõŒ¿Öçî¹çÖÞzë­¿úèG?º6++k•Õ¶©©éÑ×^{­Íƒø÷gÜç-àÍàoÚÇ6/À!Ä4lxUú¶9^þ¸î;Zo8±.ߨü²T¥UØæxßÚ%GÆñƒãÎq5!¥×òǹ(µ\–Ñ…XŠÙÿPKý]ûüÓ—,YRò‡?üáÚo}ë[O-\¸ð­¨IÇÈ7Þ¸Vfzÿî"<áhÿ¿xØÇœë BÌóÇR9†?Û»ÍVÇ\‘Z*ß®ú7~ø®ÿïW›x¤k?ø0rtÜmS#R !QþFzû>ƽÄß½Ç_þ©©©¹ÿû¿ÿ{Å/ù˧kkk¿¦úü³¬ºÀ»vízXUÀÉÕ!þ{õ½ ÿ`úÿ}2@1O÷?ÿ½òñâñ÷hïøºÊþÛ Tðlé}‘~94vÄÇyQþÙR¶ˆ8!±xº?Ð>ÿDá¯ü}÷»ßýÀ]wÝõ؉'žø“¤¤¤"+/æäääÐ 7ܰN|gÿ½ w#SŒT°€ìÞ+-cö+þ·E_óòÞÃÀ"%ÈOë¿§õÿÛ‰'»ŸÕ =Iøh=l‹ãLX WW\Á‘€„ÄVøkê— ó³þšÁß7¾ñsaðwÎ9çÜžž^o‡E}óÍ78|ø0ú·|eÿ ÿio¯+ž„¿~›BˆéØØ»ÅvÇŒ/½ÿYó Í-žÄ7Ùª¢ñ—‹(%) muÜ0«{”åÿaçàX‹mŽõÌÜUòÅl ÄDÂ_Äxù¿žõGÆ?ó3ŸùÌ©wÜqÇ _|ñÊàï»,ìøøxߟþô§õ2?ûo¤_ß_@Ä{5€§×ð„ól:B ¦€?­ûž4¤s&v¼‚Œ?2ÿ5i•¶;öm};lÓ¯MìR ó•ŠÏË HH´ÁT¸ôÓœý/½ôÒ†›o¾ùW—_~ùº‚‚‚˜˜à$''KfffLT¹þ¯ëè耣õ”^öˆË¿·×sß×¼K!¦£U¾zuð-[{vR–üfÉËŠÌ¥<⌴„TùYýÙ¶Šã¾Ž‡yDø*ôLöÙæx“$© ÚÊÅçòÃ'$6Â_ƹŸ«Á_ÆòåËË”³ÿw¯¹æšÇKJJþaÁ‚‰±þUUU¢ö/ÃÃÃQ_Ô±±±î?þñŠ÷ì(â_Ä÷(A÷ÏÂ!Ä”¬ï|¶Ǟ•˜)¿^ü#95ûDžqö™­²égÖ8²_ÞÚÍ!bë»ÏVÇ›¤tZ¢~¦Å)E<‰\À“Ø÷•ñw5øCÆ?£²²ráo~ó›¯]wÝu”³ÿ—¢o~á_]]-§vD¸9óÔíÛ·¯íëë’ãÙÿHˆ_•îO—Ú‡G!¦ãïý/KÇD—m¿ü!›üsõå÷ºƒçú^à ab&ÊÏþKsý·+kÛ×óDˆpà=¹ï²Ýqã˜OÉ^)Ow?'Oö<+{”Il¼üýNV-] ¦.HQí])êz†v™ª~65í­}Ûyb3‹qýN·çh™ÿ¬oûÛ_¶lÙ—”É—5ÿòòr©¨¨ééiÙ½{·(“iWÙÿ'eÆøÏéçáÁ–ýûsÿ7â30Í!Ä”8§òp×Sreùgl»ø¢øÃºoÉšö‡dõÑ¿ÙÒÁì¬ÌZ&?®ýŽ$çÙv ŽŒ·2Haö ï·í±§'¤ÉG^ªmÇ”ÇÄ[C{d×p“4© HÇd·ôÙ³Îä„$íï,Äyò‚dm_é‰é’¢®g¨Ë4uÞ,™êçºÏV¢âÞóó’Ôó2 ýÎ0@LX ÆÌÿÜ„Æ×¿þõ¬\¹òK©©©e±xójŒ &ú±%&&jYÿ;wÊèèhÌô…^¸WFå¸ó NÿþÆý‰øŸ /î?g€bZïÚ(W”}Jû‚eßÿ¡ȧK>&•©rÝ¡ßËÈÔ(O “ð‘¢Käk•_Òz–íÌ­÷i;9ìÖàòÔRm»´ðüÙû0v²k¢G§†Ä¡2ë£Îq•aŸÒ~–¢D{Fbš›Oծǒ̄t~˜ÄìAw៨ ý2¾öµ¯}褓Nú‚þå±þÈúã:]»vÉädìFÐ ýýï¿QfzÿC1ø æ¶x xbšBˆ©éSæWÏön“K ηýZœw†¬ÎøÖðæÐ.ž1Fߨü²\˜¶í×ÙM½[yRD"k¼(6É6SƒqYj‰”IIܼg#U„ÄPü'¸<&)???ý«_ýêO9å”+b%ü‘å/++å70+üAWW—455ÉÔÔÔ\•;=£ƒ•¡Ç×KOOkµÀ–-[îQïa\<;ÿ­ ¬ì?¨ì?„ÓóPç“ ¼CiJ±\¿ä'r¯ê·¾õØ-óE¢ Æ“}§úߤ0¹€‹¡¸«mÝl¶•D–7ßfÀ"`\(*‡P±@ˆ‰®Nÿ‰Jh§^{íµï;ýôÓ¯T‚ÙTÂ;vL80+öuœN§Œk"ÞA«€€2*”žžž°úûûþõ¯Ý"Þ³ÿF‚ÁVˆ—à€'hH‰`úôºúâ{Jö \ ™i ¸¼ä2Íë-7Ë+ƒorQ¢@^R®\Yñù@á…Úg@D‘ =›¹QâÍ¡·åCEïãBXx 8¹Ä ]økÚ0-- Âÿý«V­ú¬º“¨£/áÁ¿oß>ikk›÷<Tdddx|Í¥K—j?knnÛ{ݼyó—ì¿3ÌA€°gÿ „Äw¶ÝÇ€Õi‹äWjìÜ jZ­\”€qdÿ°ðýò/e—kýÃä87½“½ÿQPbà0 ˜õ €Ú)ÊÜï‚3Ï<óó™™™±xSº«¿k¿+÷púïíí÷3¸ÿã9YYYó~–’’"Ë—/u\Úˆ@÷ª`Aöÿ–[n î¤ñíì¿'ñO@BH|ñÚà[²S9?ÃqÌ•«²O’õªUâÞŽõA;b÷oF äܼwËÊ?-Ui\7ÞÚ­ŸHôèTŽ÷ô°P@M $† ë7Ìd•O½æšk.z×»Þõ©X ÝÕßpúûí·1no®úUb¾½½]rrr´¿¥a{ß›6mBïÿ˜ÌïýD @ <1ïq BâTü¢á\ ŸôS%U™êKå‘® ÚØÀ‚ûF´ AÎÏ{¯|¶ìR“VÉñøMbZþª²ÿ$úlïUˆ aÐ@H,¿:äææ&_yå•窌ÿ'•p.•ð_´h‘&þ¼>nppPsúŸ˜˜˜s?n=zT  ËïŽY(‹/ž}m¼N¸zÿUÅAóm·Ýö¢ûËìÿ< „Ä;^×ü–e.æbx ¤Ê'Š?¢ÆÓ]ª¦'lUUOq|˜A²T6îâ‚óäcÅPÖr.ˆžîyNÍaoäBÄ€^‘dÀ°¥ˆÄŠ”édùÞ÷¾w™2÷{¿rõÏÉ{Pb¢}þÞ2þ:púollÔÌýܸö3˜úyz ª««çLèè_»¤Êþûêý1iöŸBH\qgÛýò³úÿäBø ¤Èû•Y¶Æ‘ýò°jØÜûw5{Œ‹ãÆŠÌ%òᢋå‚ü³´ ñÍÈÔ¨Ütô..DŒxcp—ö0{ÿð3$Q?çœéròð29mäI=;åÓ1ù~’šªeüKJJü àÍé÷#“_WW7¯r@wú/-[Ô€×èîîËq¨)ûTï?²ÿfïý÷ `€7¼ØÿŠìVUËY`˜¥õjlÝ5òu5·þ¥WUeÀ6mÇã¶]“ŵrž*ó?/ÿ½R‘ZÊ“$ЊÓ=ÙË…ˆýùªšüqvÞ™\Œ8‡$ZäNe˪¡rÒè2IšNŒÉ{Ð…?D¹¯RW±¾ÿ~imms¿ÃáÐñW__?ïy*,Y²Dòóç6@üãùá@eÿת =û©~ÿpgÿ…BHÜÞã?¹Uþ°ôgÅ辪*¦vØÆ”øß>ðš¼2ð†¼¬Z+¬>A™ý“³Vhf‰gåAÑ$Í£‡e]Çc\ˆƒj,H`€D–…Žy×ÐJY6ª²ä’“÷¡ŽQ~ÅÅÅsJñ}áÍéhhH  zÀ=»\þ=®òõ¾ö©Þÿ—dnï¿ø÷ÁT øýAeÿ „Äè=FûÂü³¹A’¦± GÇÛ´`ÀÎá=šÏœÆãú‹µÊ¬¡òaEæRMôŸµD’$óƒŒûûõá?‹cÚÁň1Ûúwhí<é i\Œ8&-$BTL”ÈéC'JÝxeÌ’%áÈø/\¸Ð°ðãããšÙÄþ¬rUÕpîÇø¾šš)((ð¸¿eË–i•ž€Y Ù–cÛ¸qã½xIñÜû¬à×Ã’ýg€—`þøY¹ghYm†/ *#^±°T>ª¦€AÇìÙ+ÃûäàX‹´Œ“–ñ£ªm`ÂTï_lJRÊ¢´2©N[$K”è_šÑ •iå¬ 3v>®µß؃öŒ`d4¾Éd€„%÷Æ«å]Ã+µ@ÌÎk%Ä«ªª¤¨¨(àçkcþÐA5ÀÁƒe``@sóÏÎΞ÷¼¼¼ÔHA-ãï);oPXkeÿü:###ZÉ?Üÿ‘ÝG;;h€ ¿*T„ƒ 6Éþ‡³÷?ìÙ!qË=íÊ‹.ÒD!‰<äe)ÅÚæ‹ ç¤ M kÛ˜*SFÕÀÄ;A)U>>:53‰ EUo¤¼SÁ‘ ^_†Q¦Ë,µeð˱)@à纃Ð|#ˆy€¡g» È¡†Ä'ô !å̇U›Ûð I›ŽÝdß1j/'''è×hkk“}ûöÍÉÐðïСC’––¦‰ÿää¹Á~~´`Œ ?µ‰¡‚ìÿwÞé-ûï+j;€»¸)ûÏ!$n ùó‘Ûäµ×r1L2ò yRœÇŰkÚ’7‡vq!L<žìÞ$W”ý#Na †’É"MôÇÒØâ™~”úgeeý:ü(ïGo¿ë}¸ÝÞÞ®àôï^Ú)pú7Zm.ó¿§žzjËþ"øEŒgÿ§ý {1ýg€×À FvçF /{GšåÖÖ5\“òX×Fùlé'$qA"#.¬ F•²h†~g $“±ëï‡ðGÉ=Jý=•ãÊú÷ìÙ£eúu&''µ’j~÷Ò~8ý£"Àhà×}KOOÏÞ»îºëe™qþDà‡3û/†ì?„¸çw-7ÉÉÙ'H^R.ƒ0—ùŸ¼ž®ÿ&¦Kùo<×÷½â” V?¤L'ËÊ‘ÅZÎTVÌÞ2î(µ¯¨¨ðê²pä‡ÙŸ«Ó?Êô8 dÀè@w`0ˆ1âßáýÿ±gžyæ>u1.sGÿ…kÜ_T³ÿ Bâž>Ç€üß¡äê¿ËÅ $LüöðrX>sswÛrAþYœz‡dÒ€x!ß‘#«FNFk&±¥÷þÈø»÷à‹»Ó¿>⯥¥E»Ž¶‚ââù^CFœþ=ŽòÕû@9ÿïð!þÃ!ú£–ýÇÏ „Ä=Ûú·Ë¦Þ­Ì„èxLžîyŽ =$;^S;Vq1â w¹V=Q.',•Åc51 ê!îgüܾèëë“]»vÍ:ý£  ¹¹Y›€*¸ùçççÏ{žQ§wdèïïù}oÞ¼yÌdÿuþ7úX‘(fÿ„Kðû–ÕrrÖ N $v 7Ê GïàBÄw´Þ'§«‘¬ˆ/RÕ”$åßà˜žâbؘ gºVæáŸ;•Ó÷‚¾þòòr)--Õy8qwúÓúýáΟ””$ ûúÑ à©ÀÈþ»N†–Ûn»íïâÙùß]äkþÕì?„Ë0à”ø•\¿ä'Ú89BH`t«žòø5ûþãŒ]ÃM²¥ïE9/ï=\Œxª ÿwû7ˆþ# JŒÅÖȽõ(ó_¸paÀYv#>|X駃¬<úýQ €j8úcÜŸ+:ýÏS¹Jø‡£üëÖ­¨÷éîüoDè›6ûÏ!Är_„ÿtäVùfåU\ B¦ßÛ÷3ÍXŽÄ7½SÎÊ=]e”ùµ.žÈLH—aÀ.ÀÔãûNY!E“ù1?(·Gv=772&Ê(ñoll”®®®ÙûŽ;¦mzàañâÅZ€+ð€Ù_(#dÐ}‚E™¶þõ¯Ý"3£ÿü úP²ÿžÄ¾7röŸBˆåx¸ó)Y–Ñ ï/¼‹Aˆ¦Õ¿Ÿ7ÿNöäbÄ)­ãíÊ»áqùTÉG¹ñHÌä"Ø€‚©\9á2ÿ4gjLß 2ü±‡ŒvväZàæ¿{÷îÙ|dûQò¯JêµÛ999R__?Ïc ##Cÿ¡N@ËA¨¼øâ‹ª÷=&Þ{ÿžì¿ø øöF³ÿsÇ!Ärü¶åF©M¯’¥*@ñÍŸUÕ Œ4I|skë9;ï )O-åbÄ h]§•™_µœ2²\*&Jbÿ~”ÐFo¸Fùù}ýpúÇ%ÑÄ¿ž‘/**’êêêyí¨DX¶lYÈÆƒ>Àp0Ô{îTÙÿge~ï°Žÿ±Îþ „K3áœÔüþ¼ôRœÇ!Ä ··®•uÊõŸÄ?ãÎq¹^?ÙðÆ ™œ`9 ¹Úø¾•#K”Á_ZÌßîès?÷RûH€ ?œþ!ÂÊÿÑÿ¯›ñá}`s£ÿPŒDûA(ìØ±c½ `ŒÈÌè¿@ÌÿLŸýg€bY:&ºä?öýD®_üÉNÊâ‚âÚeno½— a!^xCê|B>¶ðƒ\Œ8€Ö IeûëÆ«´ÿêñrS¼'ô×ChCX‡ÛÑß—ðnjjÒÄ7ÿ‘#G¤½½}öçÈúÃhÐPœþ=~ÿ ÑüOM(èùË_þ²A,šýg€bi0#û?÷ÿL~½øÇ’–Ê!äžì~V~×r‚üåÈmZûÓŠÌ%\ ³XÏèNþËÇê%ÙiI…2zô÷ëž,®Nÿ‡C+ùœ1¸DÙ}w³AÜñh Ø'ZBáµ×^{TâE¦$0ó¿¸Èþ3@±<˜ ðƒ¿Ÿ×ÿ'ÇòŽøÿÕ¡?iæÄz`®üÏþVµ@]'¹I9\“Å€¸&~KÆj´Þþ…“¦xOÒÑþÈüGdû÷îÝ;›u‡øÞ·oŸLLLh·ÑÏq~îï NÿK—.ÕÌÉkÅA0(Ÿ‚Õûÿ¤Ì8ÿOIèŽÿ¡dÿ݃H!FAYì/þQþ_í7ÙK(þ)þ-¦`¬ãõK~Âê'“΀ø@ý¹¬ž(—£ Jü×j%ÿf šÆ~ž@¦ýþºÓww·{ˆ8ý»÷ûë"¿®®n^p¢¤¤D»?Nÿžµü_Ó“­­­ýÄ¿¥²ÿ BlÇßûwÈÿÛÿsùIýwÕ—¯4.±4Îi§üþÈjÍñŸØ“ú_–5ÿR~\û­ Š˜Ž4ùûf+ñÑpÎG™´ûû=ûÆÆF-ÓîÞïàE·w‘n§wP‘à„È]½zõ#2“ýw(úã*ûÏ!Ä–¼2ø¦\ÛôC¹®áû4É"–eÔ9¦•€#èEìÍKý¯Ê×ÿK~Zÿ=)N)ₘ&À €XR8™§eúWŽ,– §¹>‹””)++Ó6÷2úX±~ÍÍÍÚõžžíºÞïЖ€Í=€ žÆÿ…×öƒ`ؽ{÷ÓÊ¿ }ÜŸ©³ÿ BlKãÈ~ùwøyÃIiJ1„Xж‰ùþþë´Q˜„€}£ÍrMã÷ä¿ëþƒ#M`@´A/ÿòÑz9A‰þ‚©\Ó½¿¬¬,MôǬ¿žšT"eþª<Þc¿?²ýUUUóD~¤œþÝù_gggÐÏWÕ wÜqÇz9žý¤ü?î²ÿ BlÍÁ±¹zÏÈj¯•Ó²Oâ‚KðæÐ.ùñ_KŸ£Ÿ‹AæÐ=Ù+ßhú¾|¶ôò9µÑ5¶d° *`tßâ±j-Û_1^bºi@úèëG™¤ÅrâXöìÙ£eü=õûë~øÌYó´4Y±b…viúúú4?‚`Qc 7© Dôì¸zþM™ýg€b{”)àw÷ý|©üŸåò’Ë8&Ä-p÷°ãq¹áèíÚ,xB<~¡WçÆí­÷Ê«ªê»Õ_•òÔR.JŒÈL`@¤@Õx¹rðo†ñjI˜6_° eþÈôCøãºÙ×Ìþ†‡‡=öû#ÿx±jŸÈ˜{gggkcþ¢Õº€Ê„`QÕŽ»îºë!®žý7"úM—ýg€BdÆ( éûFšå;Õ×pn6‰;F¦FäW‡þ,Ïõ½ÀÅ †xkh·üË®oÈ?,¼T¾¨ 4E>l+‰JôW+Ñ¿Tù5¨ŒÊ´9'_˜±Ì߈þ;wj‚¿··Wë÷G©½2ûç縀 ‚‘rúwæA?ÿÀϽþúëÇdÆù?œæ¦Íþ3@!.<Û»M•ï×þ»T§-₸rÿ{ð÷Zß?!à˜vȺŽÇd[ßø´\Tp« ¢¦2$-HdÅN((ÉS1Y"KFkdÙX½2ó3g +11Q둇ðGÀÌÀéeÿ(ÿÇh=˜ÿ¹0$)i®ŒŒ´Ó¿'ðþ\A4¦î¹çže¦÷Ê€˜·DöŸBqcÿèAùÊžoËeÿÄ–bjPÊ}WÛ:¹³í>­Š…`Aðèç'Sçþö—ÿþí‹™‰™ÒïàBHÉd‘¬©WÙþ:Étš×K!==]JKK¥¤¤Ä4nþ¾8vì²âšøGÖÙWòòò´ž× ´œþ=xéè>ð}èС¿¿ôÒK-2ÓûïMì[.ûÏ!„x`Â9©µìxMþCõÈrJ1#ß?p6Þpqhìˆü¤ùÿ¤üX©|¨è}òᢋ%;1‹ A2TëE¿0ऊ' µò~l9Sæ=/!ŽaЇlaaaÔÊáCYtPö~ôý»‚ †{†Upúw7Œ0& Áüoú¾ûî['Ç{ÿžñ"áËþO‡"ò „ x}ðm¹r÷µruÅÚ—afĈ™¸¸à<HD86Þ¦AQ€ó G†ªtŽªu= ªÌPiv`ô°4«1­lÝñIádž,Q‚¹*ïÏwä˜ú½ê¦~ååå’š?^BȤ£ä¥ÿCCCšø‡ã¿+8&l®À`ùòåZ•C,@ù°>|ø¥-[¶4Ëqçÿp˜ÿyôf0@!addjT~søÍ\í«‹¾Hob.Ì?[žê~VUª¼ÎÅ ûû·¾óIm«L+—÷åŸ+gç)µéU\ ¤ÿ€÷®ÆÎŽ;'¸8¤L‰£HêÆ*eÅh½äMå˜þ-»fûÍjêç W§ÿÎÎNã9=õ¨^¨­­Õƺm§w`þ×ßô¨Ûé‡zÙÿ ñý¥ü߈ØzïÿìçÊ¿4Qaûݯ/p»î¾%x¸ô´%z¸Ä†ßؼ ^ùÇgøñbŒDeÖtÙÂ÷Ë¿”]®ú6éÞLbz·¿¸ë›2æçb¨Q¦Ú¢Þ›wºœ‘³JNÌZnÛÉ)£Î192Öª‰{dóõÌ~÷dO’Eÿ¢ÉR•é¯Ñ¶Ì)óÿÿªgûÑß« x¨@ôCü#£¿¶¶¶¹ßy”q!ýÝM èÀý± v_úI ø€$,Hà˜Š.ý¸Ürìn.‰([ÇßBlp±_šÑ 'gŸ +3—É’Œz)Hγ̱NNOª–ˆvi;¦Jø[å6u—ú¡‰~ݽéxm\ˆþxìí÷F__ŸìÚµKë÷‡Ùn»‚Ì>Æü¹7ÐP]]ÓcG˪‚eÆ ÉÜì Yþ`&xî1Éþkç2ÿEço†ûY@Hœ/½_©øœœ’½’‹AbF¹}y÷·47BÌ@Qr¨Ï¨ÑÚ¦*SËU A…i+úTÉ~Ïd¯tLti}ú3Bÿ˜–ÝoŸèTß¾§ù¡†$õõ³b¼D+ï7»{¿+èç‡Ã}¼õö{™~ôù£Œ~ïÞ½Ú¥+ýÈð£ÊÁ5øQWW§Æˆ¼ï`P>W\qÅwe&ûA×ì¿§¬¿å²ÿ3¿‹„B‚¢qdŸ\»÷G²2k™|ºäcòžÜwqQHô¿T/H’k«®–o6ý€B…˜‚.•ïêï‘¿÷ï8. Ô¿…)…RœR$ÅÉE³× ’ò$7)WmÙjËÑ.Ñn*¨Øž‘^G¿&îñžºõË µ9z¥s¢[ý¬OËò“È<$•ãešsÃX•¤L§ÄÅûFy;úÞ‘íÇè;«€5þNëŸ×Çý¹’““# sÊûcéôï‰PÌÿ6oÞ¬gÿ§Ä˜ù_0®ÿîß“pYöŸB ;‡öÈÿú_HÌ@öû /'º7q1ˆ)Ap vlþHMH‘µe%fjUÉ ’µv«Ì„t¯;453®lLõäCôãö8}1bFº3MjÇiýüµ‹$a:~Zå222´,7¶XÜE”Í755iÙsOf ¨¨h^y¬þÝ•àÆfªç¹ãŽ;^’™Ì¿/±ì8@‘àÇ*øC 0@!a@Œ]^r™¼;÷4Ž$Qã+Ÿ—ú_ÖÊ™ ‰gà–mÐ1ÄňrYR?^¥zúk¥ÂQ"ñTŒ³;”øCô#n5&''µ~gÿŽŽù£'afXQQ1GüÃüâßLw£Â@x饗Vˆ ºfÿb|ôŸSŒ—òÉèÇ$ûÏ!„D€·†vk[Yj‰|¸èbù`áEZi+!‘$G•N¥â ùÅ¡?p1!ÁíòÉb©­”ú‰*)œŒ¿2y\”øÃÍ?ÞÆ÷eddDvîÜ©eÎ÷ïß?otUU•qí04Óº„bþ§Ž¿çæ›oÞ,áËþK?ó'죒ýg€B"H«r޾éè]rÛ±{µ‘YŸ,þˆ¬È\Â…!ã’ÂódCÏfymð-.!$¬èýüÈôÃÈ/ËãpQÒ®gûãu|ŸQàì¿{÷nmÜLÿpâ¾¾¾~^o¿œþ=ñïp8‚zî믿þØÐÐz…(ùÇš™T1¨ ~pß»víÚ ‚ýâÙù?Ðò‘8Ïþ3@!1Â9íœõ ø“ ¼7÷t9/ÿ½ò®ì“ !ó™’˳=[Õ,óV.!Ä'iÎT©šPeßãåÚ¨¾ g|–Æ#ƒ ?¸Ù£ÌßJ.þ†¾W(¡¿wï^-SÞÚÚ*ÇŽ›÷˜ììlmÌ¿0ûËÌÌ4í±›ýW¦Êùÿ™Ÿý& œ/€?aÕì?„bàvýlï6mè+T`‚Ài*°$£ž D&%!Y®­úWùÖÞicÒ!ĕܩl©WYþ:ÕÏ_9Q—¥ý:®ýÈö£Çߎ 7Nÿ½½½ràÀ­ÿßd÷QâïZ aF§">hó?Õþð\cc#žìߥþÁøˆÄaöŸB1®•7©Ûe)År¦ œžsЬÌZ&Ù‰Y\$bˆS²O‹”ßÄÆž-\ BlŽæÚ?¡\ûUY½Êò:â»>55uVôCÄÚ™±±1ÍéýþèûG¹¼;0=¬¬¬œs|Ð `ööˆ‚`zݺuÈþÃaJÂcøç+ Ù!Ää´NtÈCOhÀhÁ3—kÁ€³–KuÚ".ñÊ5‹¾ ;^—~ǃ›‘6­JûUY½ÖÏ_%©Î”¸>d©u3?”ú›Í¥>`¬œþq‰òw³?€1X3WÌêô¶¶ ž§ü^ܶmÛA™ÉþÍú:P¼~OÂÝÙ!$Þj´ 6ŒzEÉrRÖ Õ*P'õé5RŸQ£¦ är¡ˆF®š4ñ¥ò–ß¾‹AˆÅÑ üR3¶HjÕV>Y¬Ýï¢&~Èö£„¢ÿ8]]]ÒÔÔ¤•ýÃéß=KîiÌŸÙþ=8FFF‚zîã?þ Ïþ‡jþçÏÐW ÀTÙ!$Þ¿LöȦޭڦS˜œ/uéÕ3µáú¢´2I^lË5BÅуrVî¶<þ½Ožê~VÞVÓ'!Ö"y:I*ÇË´ íø"ɞʌÿcR¢b¢⟢>0øC¯GG‡æú?==W#Âäåý®ífwú÷D°Ùµ.o©@ã;gb?˜@€ˆ÷€˜gÿ „ Ò=Ù«m(ýÖAhaJ¡”«‚²”uYªµTàRÝÎIʶı:†ä¨r¾oÙ¯m;‡ö('ü'ä_-þ‘f¬h7ðÙÿ{ÕWäê=ßÇôA‰s¬dà§'z]ð#c­‹~Š7•¨„>úüáòïÍéþÿ®†ˆñàôïÎÄÄ„6Ê06nÜøÌwþ÷—õd  Hœfÿ „»|iPÿ:&º´íuy{þ†„T)HÎÓªÐB€Ö\ê÷¡”„‰i’ž®.£7&jÌ9.ÃS#225*#ÎR×!ô;'»¥}¢Sk‰Àe›Êôã1Þø}ËM²zùolY *OTîi¿ „ÄI*Ë_?%ú×X"˯ UôôCø£§ß›àe`W§ÕßîQCàCü'%%͹oÙ²eÚzÇÈþ»W6AM@h¾ûî»_•ã½ÿá,ÿ÷V ‚â#`q‘Ï!„ŸŒ+‘­û %+1S ¤'¤i— é³÷Ë;_Ø%aN°ÿ˵½³)õÿ®»`sŽÉä´C»>ä–a%ø1!´Œ“{Û–Ï–~Ü–ŸñçË>©šD „bnå¯V~ý5’8h‰ãJOOŸývwï8ý¿ýöÛ288¨™ý Í{L^^žÔÕÕÍqõÇ}K—.ÕÊÿã §Ó)íííA=Wÿ­Ç×™ßûjù¿øþq“ýg€BHÐ M k[<ñ·¶ûå¢ü³µö»*oV]%ßÛ÷Sž¼„˜Œ$%ð+&J4Áß0^-9SÖÇÈÞ#Ò~ôžë¢ŸY}ã@ô#óK˜þÏ{Œ§1¸x\ëîîn ü¡ ;n¾ùf˜"MúüÁD3ƒ¨Š|!„A¥Ã„üNµ\×ð}[ÿ9§Êyyï‘çú^àÉ@HŒqÍòWW¨/åÖÈò#Ì3?²ý0õ›§z(í·sœþe``@ëýG€;é‡MkUSS#eeeq{Üð7†;v<¬¼PZ¨gÿ–ÿ:þÏŸp7möŸB!¶cûÀk²­»m§|­òJyeð͸«Þ $ÞA–¿rB ~åÖ_3V!yS9–96Wç~˜ø¹–¡“àÐþ@Ï¿{?¼>ÒÕ:Xw8ý»Þo {lqð‡ªŒèWÙÿâ9û®^O·==^ĤÙ!„Ø’?´Ü¬&œ,i ©¶;v;~¡ürm !‘EÏòc«QÂ?eÚ:&¤šè‡ØÌÎΞ¥$4 ô÷ïß?ëòïÉé& s|„Ó¼{+;úoçÎO*cDD¦$|åÿ"Ëþ3@!Ä–`Â]ÊàÊòÏØòø/[øy¦çyÙ5ÜÄ“0‚±›åpì¯ÔDÉd‘eŽ Fr(íÇÑÍÒ~»´LMMÉîÝ»5§ÿC‡Iggç¼Çxó‡` œþ]ï‹GÐâàé˜ Wj·ŠFû9rDúúú´ €{ï;޳ººZ­¨ƒ` Ìþ"åô«€Àèè¨GÏttt¼­â¹÷?Ðòw‘/bÌýß[° ª¢žB!$ê|B.-¸@gÔÚòø¿^y¥¼6ø–Œ:Çx2[‘ëÈ’ê‰ -Ë_;±H¦ãßäN/ë׿·²þHŠo–ö{BÏž=ÒÝÝ-]]]šÛ¿»ðFÐýþøütð™.]ºT›­õV@½ÿîû2ÂæÍ›]{ÿƒÍö» ùpJÁ€¨  „Â/dÓNùÍáäÏË®³¥!`qJ‘\Qö)¹áè<ˆµy§´‚®ýVӇ̰žåw5ï³äGÇÁ…‰‰‰Y§ÿÖÖV­ÀÓg‰~|®ºÓ´Åy¤ˆ¨L~ÀÏ8ú·¿ýmû;Wñï«üßh@Äxö_<<>ꢞB!$@GöÉc]åÃEÛòø?^üay¦÷yÙ;ÒÌ“XФé$©W~ãUÊįJ2-PÚ!¨g÷qiÆù﬘‹îô£;dý‘ýwŸ#„¾kNÿµµµ~×'^âp8~ÞŽ;™šš‚c¢CB3ý d"€/ןKäÏ „B"ÉMÇî’³óΔ¼¤Û{â‚D¹¶êjù·=ßSßF¦y2¸&C¹ö׌-’%c5R£Jü§ãúx\Ëú!ú‘íG™x´Å7Kûƒ}þ»víÒLþöïßï±ßŸiCCÜ,?\þuú·€€§*¨I }7ÝtÓ&ñªÈwößÔ0@!„¼Ã cHn:z§|§ú[ÿÒŒUq‰<ÒõOwäNekcú–ŒÖZµ½ÞºàÇ–””diñmÕ@Üíáðòÿ½{÷jãþÜAÛ²üzPdž`ÆÿÅRœGzŸýÀ@Ù¹sçSjr°Ì7ÿ §ë¿/ñ#øþõ‰É_)!„žì~V.)<_NÎ:Á–Çÿ•ŠÏjº'{x2ÓS8™§²üµ–èç‡À×Å>Fô™µŸÆQ3êµr•±–¦¦&íÒ’’©¬¬œ½­{à<ˆ¥8Æ>ƒÉþ£ìÿöÛoB|;ÿ‡ÒÿoÄì/ì¿éB‘ B!sþ§ž–ß·¬–¿.ûµ$-H´Ýñg$fÈ¿.ºB~Ú|=Ob:`ÒY9^úŽè¯’¬©Œø=%¸Pö ±±çjúmñÍÒþðc»ÆÆF­Ï_eªµ O}îUUUZ¿<àôKW±l%ÇTB3úOµP<§Æ&v‹ÿÑŠ~obÞ[ .³ÿ B!h=¬F>.Ÿ(þˆ-ÿÂü³åéžçä¥þWy2Sˆþò‰bUÚ_#KÇêâÚÄeýz–åýz¿7Kû­´@ŸÿîÝ»5q‹Þôüó‡s™T‚ÄZœGcŸ˜‚ÌÛzà‘ã£ÿÂÕÿ/>n‹‡`€ø˜Bä3@!„Èm­÷ÊùùgIQr-ÿ«‹¾$¯î”qçOSÑ¿L‰þŒ8ýzYYYZ–ßìãùX1:èg‡Ó?.1Ú-î è¡óB§¨¨hŽ@¬Åy¤÷‰ ‰§)þ8räÈŽ­[·ÏÎÿÎ b@øö¦Ïþ3@!„xadjTþrä6ùAíµ¶<þŠÔRùLéÇå–c÷ðd ýžž®ev±¡Ä߈Pbi䃑Fͥלþaö‡ì¶§þvT€`Ì.uàò_QQaq}¶··kmòôÓO?¬.•ž’ð:ÿ{sÿ72þ/®²ÿ B!>x¶w›\ª ÏÈYeË㿼ä2y¦çy94v„'‰Š©œ,“å£õÚȾTgJÜJ¶õ>~Ý­?šB,Ä·ÕƒÈöÃá_ÔIss³ôôÌ7QEÆÎþúùc¬««Ó²ÿfç‘Þ'„?&#Jww÷ÞuëÖ픹½ÿ¾‚F"ÆLÿŒû¸Èþ3@!„øá-7ËÍËO””„dÛ{Ò‚$¹¶êjùfÓ4sDBÂ…îÞÂØbÉudÅÝû׳üüF³üVêdÝéâýþ¨píûúÚ"€6œ;Ñ:ÌPB^k”mÛ¶!û1 ž²ÿÁTˆØ0ûÏ!„⇣ãm²¶c½|¶ô¶<þ³–«*ˆ ÔxÄM<HHdOeÊâ±j9at±OÆÕ{×{ù!úéåg–ܺA d²‘õGö‚×álïŽû˜?8ü£ —fçÑØg0£ÿÔºvÞvÛm/ˆç£ß- °›ì?„BˆþÖ¶N.Ê?GÊRKlyüÿZq…¼Øÿ²ô9x2€Èp*±3Z++Æê¥tb¡Öç/@äëeýØtÇ~«Ã …0Òýþpú—¦¦&íÒ÷1"Aü{rú7ƒ8ô>Qá)HâW_}õ1å­0*ÆFÿ…êøo´% .³ÿ B!€þïZn’ë¾oËãÏNÊ’«*>/¿<ôGž Ä€š©ž(—“F–JÃxµ$L'ÄÅÛ†èAi?úù‘éÏÈȰ¥P·zÐ"TÆÆÆ4§YlÈü»—´£b¤¦¦F ŽO‘ÁuŒþ ô}Z) Ìè?µ¶Ã·Þzë™ýg4Ûïßåû¾Jÿ½‰zoUq×Ç!„b€í¯ÉÖ¾írvÞ¶<~˜!>Ýóœ¼6øOâ‘|G®,­“•ªÄ?g*>úú!Ô öuÑo4ËÏ,¹=ƒºÓ??®ïÛ·ož›½§1eeesÚÌ(Î#½ONúúú~ÞîÝ»ŸVSP~æ-û®i"JÁÓ  „B òÇ#7Ëi9'IzBšíŽ¥Ûÿ^u•|i×µ29=É“Ì|‘œN”ºñ*-Û_5^%þh®®ý,ígÐÂ0¯kllÔÌþpýàÁƒó„±û˜?˜jkk¥°°0¢Ÿk<àüïþ<¨àŠãî»ï~Lf²ÿþ„~ ãÙñðxS‰z!„Ð1Ñ%wµÝ/_.ÿ¬-Qj¹üSÉ?hk@ìMÅD‰œ8ºDsòOvšÿë$z®õL?D?]ûí´×8p@ÛLÿàüïNff¦–ù×ûûõJ8ýëÂ×êÞöÏ„ÎÎ΀_WY¶íܹ3õ줲ýâá¾i/A1(äg B!fæ¾öGä’‚ó¥:m‘-ÿseŸçúþ.-cÇx2ØŒ$I”%#µò®‘•²p²ÀôïYXݵýüF„³ä Z¸¿WŒöCï:®=zÔã {÷18÷ þá)a&q}zÚÄ?*'}©‡~x½xÎþG:àI¸ÇuÖŸB!$HÓùÍáä·Kþ'®ÍÃEò‚dù÷Ê«å[{¤¾Mó„°yŽl•í_*' /•´éTS¿WÝÄY~W?Šo-‚uÏž=ÒÓÓ£­Ess³vÝ÷1¨ðçôo§€<<Mü¡žóæÆ÷‹ïòÿ`Þļ·@€%Fÿ1@!„„À[C»å™žçå}çÚòøOÉ>A.,8[[bUUyÜÉñX©ƒ]\º‰ŸÞ{m'¡Î Eø× #ýàô?<<¬ X˜ýÁôÏ÷1púGÏ?zÿãAœGcŸšx‘èÍ›7?ŒBŒ•þ; D|/÷ùËþÇU4œB!$þrôvywîi’•˜iËãÿ·Š‘íý¯ÉàÔO ‘æL•G–ÈÉ£Ë%×a^'ÿ´´4­ì‚+%%%î'ƒæ¢_õ‹š;¯¹ýcÌŸûìz|ŒôCÐIG¯ç˜±Ÿ?P‚Éþ«`KË]wÝõŠÌuþµì_ £Â>n³ÿ B!AÒ;Ù'·[#_«ü’-??9O®¬øŒ\ø¯<,@îT¶¬Z¡•ú'O›óë!D?2ýþz¦Ÿâ›A‹p_WW—æô¬?²ÖMMMó²×ÉÉÉZ¿Þb‚}ÕÔÔHQQQTÅy4ÎÿP÷744¤m²}ûöGÕńڦ$<ýÿžÄ¿xŽˆÅ²ÿ B!!ðPçr±jX–¹Ø–ÇÿᢋeC÷fy{¸‘'CœR4™/§Ÿ(ËFë$AL÷þÝ×ÝûQêo'¡nu̶n®NÿÈø#ó Wà1ñ¯WÀé¿¡¡aŽÓ´Äy<`ž(*àÒ·zõêgÅÿè?§^æïMä"ìã:ûÏ!„Ê—!õïw-7ÉŸ—ý–†€8æk«®–¯ìù¶2Gœâ G`ŒßéC'JÝx¥éÎ]dX!øˆ~fÉÍ%¾ãqÝðž!üèõGÏ?ª\ÉÊÊÒľnî§;ý£2Å âÜl±±1éíí ø5UûÅSªj`XRt‰-¿6½J>^üa¹·}=OÓ+Ñÿ™C'Kùd±©Þ2©ÈôcC65X5Šo-y,D>œþ»»»µÛ¸T³çç [´¸šû!0…`‚Ufç±è£AM^˜¸ýöÛŸùÙÿ@+Äø÷W`Ùì?„BHX}ôorNÞ™’—”kËãÿ—²’-½/HëDO‚ ÿòÑzyÏЩÚH?³1…q}W¸´‹P·:ñ²n0ùƒÓ¿Þ£ÞÑÑ!‡ž÷8÷1îÁ€xçîûŒäþÐ:ÑÙÙðóT%Ƶ!ãð"ìC­ð׉`„BˆÕ€þGï’ÿ¨¾Æ–ÇŸš*ߨú²|oßÏx2˜Lø×Ž-’³‡N“…“æxOJt Ã…l¿7Â,¹¹Ä·ÕÖÍÕéÇvôèQnõÕÕÕ²páÂ9Á€E‹Ed-âÍàÏXË@³ÿxKëׯDfÌÿûˆàbß[Ùÿ´UÎ!„0ðT÷³riáùrrÖ ¶<þ3rVɹyï–-}/òd0ÕãårÎ໤d²ÈïýÒèé7:¶â›A‹H=}é»wïF¹¹ö˜ææfmV½+îcþð:¨p Dc]â1 €u &û¯Z^ݼyóA™ÉþO‡qñߨ¸Ÿòg B!–ù«þý¾eµüuÙ¯%iA¢-×àk•WÊ+ƒoÊðÔOˆs?dü—Æü½è}ýý®#Ó¬*8-ÿ7Îë†Ì4 þðþÐÿë0ýsÅ}ÌÎc”üëÁ€Xˆóx @ü;Ž€÷÷Ì3Ï û™‹N—-OÂÝŸù_\Ã!„&šG˃Ë'‹?bËã/LΗ/”].wï½}¢SîïxDëÚ¨eÿIdX2V+õ¿G2œ‘aŒFíy¦ø¦ø6㺠jârrR» #:dþuçòòrmÓÅ0Fü¹;ýGKœ»ï3Þ'  å"˜ìÿ¶mÛôìÿ”„¯ä_Ä÷8@o¢ÞŸùŸå`€B‰k;–‹ Αºôê¸x¿FÉÚö‡eSïó☞â!R¦“å}ýï•å£õQþè{ŽGÁiu¸nÆcý öÑëPþž”ÿ» ]8ûÃ× ÛïÍé?bÙ û ç>±Öî‹FPÕ]·Þzëó23ú/Ð1FÄ¿'áïmb€ø ø\J!„âýË’Ñ¿k¹I~»äd˜÷‹»î胿iû$DbB‰£P>Ô{ä;r"dPgþèy¦àŒ®øæº…-0o¾¹¹yVÈ¢ýàÁƒs„-Ä~CCÃì9Ÿ””Ó?þAöß5àb”7ß|óÉÑ™ž O½ÿ¡D¼Wx „#À!„BæóÖÐne ÷¼\¬FšêKü;Žþw·= o7òƒŠ§¯ó”ËâtbÄö„^glf¡ß\7£ïëÀšéœ«Usäç<ÿpú×+]t§Ýù?žºYxŒ>q!T»ÆÈêÕ«Ÿ”ãåÿÑvù÷'ì-Ÿýg€B‰27½]Þ“{šd%fÆü½ ´ÿÙÞ­šð?4v„N€àGÉÿÊÑÅÝÊœKKKµÌ§Ù§Õẅ¾èëß³gÏœqsþî"bñâųcýt§ÿH™ýÙ5 € Ý{!TÛÆ&UÁÑ'Á÷þ‹ø/ý¯!bÓì?„BH”éì“[ŽÝ#_¯¼2fïaÔ9&Ot=£ùÀ D‡L5Öï²Þ‹¤traÄö,gYY™dggSp « ¬´€£?ÆüéNÿØZzzzæ<Î}ÌF[VUUEõó²’ÁŸ7ເ6Œ ž7µfÍšGåøè?#‚ß)¾3ûþÜÿö¶Èþ3@!„Ä€õjœÞ%çɲÌÅQÝoŸå‡}?Ðù˜ :†øAD‘²‰bùh匌ó>¾øçååi½þÑmFñÍu‹púGæãæzÎaþ744÷ï—û˜?T¿`‹¥XŽgƒ?_ÀsAÿ<¡¥¥å¥W_}õ˜ÌÏþ‡Ë0˜–Ûeÿ „Bbñ_ýƒ!àŸ–^' "/ÖZ':äŽGåQ5Êoœ£ü¢NÃXµ|¨ï|IŠP¿jjª6æ,XwŠoẙp-áojjšuúGÉ9në•:îcþõÏÏÏ7@·B@¯×ÞÞÔsŸxâ‰õb,ûh @ÄÿØ?ñòø@¿% B!1 qd¿<Öý´|¤èÒˆícÿèA¹¯ýyFò›â(¿˜°rd±\Ü–$Hd=Èú#Óéžõ§à¤Pçµ@‰¹«³?Úçô㽡¿¥þš¨Q~uuu;ý3 `eðYŠøö£>ºGæŽþ‹D¶_<ܨh·üø!„±úèÝrNÞ»%/)7¬¯ËQ~±£ß;xª¼{蔈¼>úœ‘õ4ÚëOñÍ E¼¬úû]þѰoß¾9#çpþÃì/++K»––¦‰Ýü/ÜbÙªýüì ¦÷<ÿüóÈñì¿3ÌA_O¢>PÏ!„§†äÆ£wÊT5ô/rïŒòû[Û:Ù5ÜÄűø?àLY¥FýE‚ÌÌL©¨¨ðëðOñm.¡ÎuóýX|dùûúúfïëííÕz€Èǘ?ˆ~€ X$þãAœGcŸø,ÆÇo!8zûí·¿$ž³ÿ¡¼‰x_†þÿ+ îg B!ÄOuoV†€È)Ù'õ|Ç´CòÛ¦ ÿÃcG¹ &ÿ¼[N^‘×G¹³»¹E$…z¼¯LåvïÞ-ÃÃó÷¡×\ÇÍyÊû!þõà~*++ç‰W–®UðòË/?ª‚;ˆøýlß¿·q€âå>Ûfý „BÌòÅ]ýû½2¼qùÿIÒã&q#S£òd÷&YÓþtMöp!Í"þû•ø ¿øGv3V%ÿß ZDrÝ úáôïš]†ðw7›ƒßÊüõL?a˜za±lõ€²ÿîæ‹FP~ƒ·ÝvÛ³b¼÷ßÈcÄ€ð€@îöq B!Ä?ÇZ”Kÿcò©’ú}lŸ£_ò{J{¦Fù=­FùMpÁLÆÙƒ§EDüëýþ0=£ˆdÐÂJëQ ±¯ W‡Ã!û÷ï×Lÿ\qó‡Òÿšší÷"\b™¾éïï—‘‘‘€Ÿ§‚:*ûÿ˜Ìdÿ§d~–?Ô²£.ÿÌþ3@!„˜”ôÿùÈmò£Úo͹ßh³Üßþ¨lìÝ"Îi'Ê„œ9t²œ1tRØ_β²2KNŠo®›ëÏQâôèqÏx ÀuÄJý!öõ1¨„Ù.)Σ·Ï`{ÿU0ç¹t«« ¾ìß]ˆ{Êþ 0ûÏ!„b>žëý»¼¤ ÏÌ]5;Êï…þ—¹0&Ydÿà z›uáCÁIñm•uƒ›?„>Jÿuà€1“““ÇŠÊô744ÌŽùCÆÁ€hTÂ0 påà?ǘ1—_·nëè¿HŒüñ_Àì?„Bˆ¹ù2ÌnÍ”½#Í\ “S3^¡™þ…| ‡¹Y ýÍV‘ ZXoÝ ðÝþ1òOe‰çŒùC†Nÿz¦???_óÀЋýüÑÛg°ÙUÝñʶmÛÊñ츂"ÆÚ" `€B!á§m¢Cm\³SèÈ“÷] ¾ÙãøÂ~ÿH8ýS|3hËuC¹»ÓGG‡>|xÎópî#ó¯gúQ ãÍé?VbÙ.dÿ‡†‚3š}úé§×Ëñì¿«øD ÀŸ¨ŸRð[60À!„BHd:Óå{.‘TgJØ^ýÎÿ˜›QpÚg-âyÝ`"רØ8Ç鿵µUŽ;6çq………Z™¿îô¬?²ÿ¡ˆeöóO°Îÿêón¾ÿþûß”™ì¿7ÁL @ÄXÿ ~ÚŽ# „B1*Ô§äz/’œ©¬°ŠÿÊÊJIOO·¼ˆdÐÂ^ëæîôK”ü»z¸üÃðLjì8œþ­,Î#½O´i¸Oc0ÊÖ­[õì¿‘ÑF«DŒWbþgK „B1ÈEƒï–²‰â°½¾¨‡"þ)¾)¾Íºnpú?räÈìmTìÝ»wNY9^ bÙ’’§Û'*4‚AµztÝ|óÍÏËÌè¿H•û{Êô-ó·}ù?„B!Y1Z/' / Ûë!ó2gwñOÁiŸµ°âºaßpõïîîž½½ÿÿ®cþéG¿¿îy‘‘‘!ÕÕÕÚ]À²Ÿ?úû„_C°Ùÿ×^{íQ5ÒqLæöþ»_†*þE¼—üsô„B!¡SƒíýWûw®]»VýÈØ¿@¿ûÞÊþ™ýg€B!Ä7 Ô¿‹ûÏ’Ôé”°¼ÌÎŒô9ÛIpZ+¯„~ss³–ý×ñ4æ¥þ(ù×Ëüñ{€±¨ Á_ä÷itÃÃÃA;ÿ:tè…_|±Ef²ÿÓaÜDü·*Ú§ù—‰ÛþŸÄ% „B¼sÒÈR©_–×JNN–ŠŠŠ ¾ü3Kn.ñÍu›qú‡Ðw-ǘ?xàÒõ¼_¼xñ¬Ù%*`ð{€ ÅytöitÁfÿ±‹‡~øA9žýwÿ.ñ/~ æ„B!„¹äLeɹ§‡åµ vÊË˵Œ'E$Åw¼¯>ÆüŽŽÎÞ‡ì1®cþéǘ?ŒûEEEZL ï™èì®U olذa¯ÌïýWÿ¿'ï)`¤ß?ó@!„B¬JÿS¦“ÃòZ=‘îu6›à´:v]7ˆDˆW¡1h@K€NNNŽÔ××kA/}äe Þ D7 Bö_6nÜøÌdÿÃ1úÏß@O¢ŸÙ!„B‚géh­ÔŒW„åµòóó51MÉ,9×-k¡¿oß¾9BßÓ˜¿ÂÂB­ÇÏG ªª*¬Nÿ „wŸèûGG0ôôôì¿÷Þ{_WW' Š#Â_<¹?ØÇ1@!„b%õ?ð̰¼J 1ò"’â;Þ×­½½Fo~Çü¡ÕÙ~¼'8ýCüë-çáßg8ö×ÖÖôs·lÙ²N]ÀôÁ5ûJÙ¿'ñ/ž#â?ûϪ!„BærÖÀ*ÉšÊùuÐ÷¯ !+ N«Ãu›/4QÞßÙÙ9{¿§1Xdý‘ý~Aü'%%ÙVœGcŸ¡î¯¿¿_FFF‚Ú·j9vë­·¾(ž{ÿƒû'D~ žÙ!„B¼S4™/§Ž¬Ëk•––j蜱ß\·à‹‘~(ù‡HÔ™œœÔÌþ\E#Êüaö—­ÝFË‹7§;‰óx ²#XÔØ¿‡Ô92f `${/bÜøÏ— ³ÿ B!„ãü3d„þHCßßñ¸nÚH?W¡?66¦Ý‡Ÿé ÌÉ’%³&—¨ÄéŸØPÁá:É!ԹгzõêgßÿF³ýVˆø®ð÷3CKÄ!„Bˆ i«–ê‰ÐÿPòɾŠo®[¤×¢ß]èÃ(Õ¨ бßâÅ‹gËüÃáôoç€@4÷‡ËPzÿ_}õÕGT ÀˆxÏþGj@0¢ŸÙ!„BŽ“0 ç¾+ä×Áx”þ£$š‚3òâ›ëþµ€Óÿþýûç8ýwwwËÁƒçˆÕ¼¼<©««ÓÊü±-Z´(¢U/,ß/øœÇÇǃz®jºù曟cÎÿDŒgÿ½ | ~!„B¼sòÈ2Éwä†ü:¹¹¹’‘‘·ë@ñmï úÁáìïš%Æ}GŽ™ó8”øWVVj×ásëhПÇò}sï¯ë>½!Þ~ûí§Ôy1 dzÿáÎö{ø¾\ÿ}n?c€˜ÿÿ)ü]à2B!‘<$gú—)U]TTDÁÉ EÜ­®Cø»Âá>dý‘ýwÎþÅÅÅÚuˆ~W§;‰óxtuuÍiïÕ2~Ë-·<*ž³ÿáÿç¯Ü?Ñ„B!„ãœ:¼B2é!¿D‘»ë9'…ºÙ×=ý釒p‡Ã¡õû«ïÙûpn£ä¥ÿF—ååå>þ0_@Ÿw(Ù5b“:_º$4ç£Uâð0r°c€B!Ä*¤N§ÈéC'†ü:è}ÎÊÊ¢àdÐ"®Ö“Ó?úÂ1æŽÿ:(óǘ?˜þ8ý#àìñÒà/vLj쿫‘c (_ˆ©5kÖ<"3Ùÿ) Ìõß)Ƴÿžn‹xo ù¶‚¥ÿ„BH¬:AÒ¦SCz d@}¹þSp2haÆuÃø7w§dü‘ùG€Êü1æãþðºèÿ—Ó¿f8FÿÎÎΠ_Oµ‰l{ùå—aá)ûl5€ø¸. {fÿ <á !„Ï ÷ÕÈŠ_ÙP÷hŠo-̼nýýýšÓ¿k&-ÍÍÍsÜÿQæ___¯Mµ@ «¢¢"¢Nÿ Dˆ×Ï7з|ÿý÷? .1š’ð¸þ{ÿbà9"Ìþ3@!„'Ž,‘4ghÙdEõžh+ NŠoë®JÀ]Gúá²µµUŽ;6çq0´¬®®ÖŽ-óçêôoeqnÅ€€Ý7ÏÐ1ZZZ^Ú¼yó1ÞûŠ?€Ï¥ Qð30À!„Bì†ÊgÊiÃ+C~£}Ðê\‹X¯îÃ8¿¶¶¶9÷yrú‡¹_YY™ö©©©Ú˜?ì*έÀ„‡P²ÿ=ôÐ:9Þûïîöªë¿»0göŸŽ¿#\B!d†¥£u’3ši_FF†¶Q|3haöuÃ~àôßÓÓ3{ÊÿÑï?888GdÖÔÔhm-Æ–(û7âôo瀀ÙÆŽ}}}AïûèÑ£¯>õÔSMâyô_ Yñ!þýU0ûÏa@€B œÓ†Oéùøòéxœßö[7úÁÕßu¤Ÿ'§ôùÃé_ïñGk ªâ]œGcŸf?F´x¸?>{ì±ûåxï(f"Æ«üµ0ûÏ!„BˆjÇIñdaH¯‘„Òh NŠo3¯~cc£_§xYÀé=þx}LµÐ«ì&–­vŒø¼]«<EµŒ¼ñðÃï’ùÙ_åÿFƒ"ƲÿÞZ(ø ÁþÍàB± g ŸÒóñÅ:ÜcÐÌ*"´ˆßuÐÊþ]…> :4G,fffÊâÅ‹µIxÏ(ùGé4ÛˆÜ>]=‚aÆ ®Îÿ¡–ÿ‡+ûŒ¦¡Þa€¢žB±¥“ eÑxiH¯‘››ëÕâ›âÛ ëæ.ô½9ý£Ì¿®®NëñG@wú·“8·r@ãGGGƒ~~GGÇ®µk×¾!3Ùÿé0o"Ƴÿâáñ„âö˱€¿„BÈ\N^ÒóñE=??Ÿ‚Ó¦â;Ö "ßUè{sú/))ÑÜýÚY þý¶hð?Ljׄó(¨ìÿ}êb\ægÿCqÿŸö!æý¹þû øÓF„Ó‹÷H½¶ü…"„B,EêtŠ,« é5ýG¦4ÞE$ƒÖ[7OB³ß÷ïß?ÇTUUi#,Zuú·S@ ^\½EGkÖ¬yM]uûN O+€/áÎÑ 0 `ðñì…!„BËÔ迤éà¿òxÊþS|S|›aÝ0ÒÏÝé€MMMsD D~}}½È¸ ‡Ó?æ:Fœ!íSý[+ž{ÿÃÕëïIà{ 0ûÏ!„BHàœ4²4¤ççääD5û¯BÝê˜mÝ ôáêï:Ò€ÈüCê ¼fÚmŒ±Œä(Kb·Ox@¸š?ŠÊþï½ûî»_‘ùÎÿ¡šþ‰Ûâ! >ù _'üüñ—†Bˆ¥)šÌiôŸ¯ì¿™D$³äöZ7O#ýù=|øð‘˜žž®ùCU¥¥¥Ú(K+ôº²O;#Ú>Üýå‰'ž¸GæfÿÃ]þïMøöÌþ3@/þÛø @!Ķœ<²,¤çc,šƒ4Šo-¢µèñFÏ¿Ó霽¯¥¥ežñ*WPöŸ˜˜¨U°”——k³ ×hìÓLjÏßõœ@Ú­zÿ_ÏÙÿPûûŒýcöŸ x/'ù‚^‡ÙB!öù’3(ËÆêBz ŒK³»à´ü—±8Z75žMŽ92+.!ø8 }}}s·páBÍðïUwú7ÚÆÂ€@üí#ÿ0ú/ž|òIoÎÿ¡D˜ýg€D5hàí¿„B,Ï’ÑZIs¦ý|ôL»ÎF…ˆd–œë¦Ï¡C‡æ”xÃäf®b¥þú9ŒÌ?ª(–­{Œmmm!½XÚuï½÷"ûïc£þ‚ ˆ0ûÏE{ØŸïk¤†«!„؄ǖ„ô|Ý1â›A‹X® ý`ì7888{Ÿ'ôø×ÕÕÍV­àüÕËÖ=FdþGFFBÚ·êý¿W¼gÿýœb¬ôŸÙH¾F² €BˆmÈrfÈ¢‰àÅÊ¥1'ÝÊ‚Óò_–,°nãããóœþáÐÜÜa€>öoxöðç¬éäRB±™ÎôÊÿažª`–œA‹@€ÉJü‘í×AÀáÇý:ýDu=ˆý>1‘¡ KÏoÚ´i¿„–ýwŠqã?_ÙÿPG—3`À€åF\ÿýôë.1!„+±d4<îÿßêÑX ˆ~8ýë%þxLKK˼ÑnîNÿÈúÿÿöÎôK®ê<÷»Z#HÍó<ÙÁ&ä.Ç^we%Yɧ¬ø[¾äËýî§L˱×JlÇ8v°c ÌÅÈ„0ó`l Â!BcKjI­¡Õ-©5vwÝýžÖi>}†½÷Ù§êTÕï·V­šëTUWuçyß÷ÙaÒ'‰åN7äòÞÞÞB­s†¶lÙò_ú¤|è’ªÿE–ü£úÒõá—£–py^@x^¾ð—_ùÜOÿ·>–ĘI×]‘C-å|-átü  ŽÇýoãÏPIj x¼ZÆù¼Óá±ü&Mû??üâÿU‹Õj—'&ÖiÓ¦u¤PÇ´hüûvöìÙ Ù?lñ—ciùŽѤÈKúÇh_CàôéÓ…—ýûä“O^zûí·»Uzõ?ÉQöKþùªþçi'Àè(s /ü/Í W¯_‰ ý¤C-Ãp1²v*1ÚÛ0¨žÏüÑëä7iÒÂ… oЇ®O<^Qm7Á‰iQdù6©ô‡ÂNBÝ$ìïÒ¥Kãn7þ|µjÕªà=ƒJÂþä¸Å2íûÅð±ìŸ6™.?üðÃaõ?oé?ÛÊYÕD>@Gû"÷O[ éË9ùò‡âÞG€²0|~ €Ö3Lªþ&@׵ߴ®¿ú«¿ú”®:G¡çˆoL‹¢·•eÛŽ;6®[–÷ñ û–/_®/^œ–¤©üûHúo–Xfž¿ò™)¸ìŸÚ¹sç³}ôQ¯òSý71”¢ú€Ð/å¾ñ€º2[ -Ð#JWìò®k§k±ÓñC=átÝ£Pã@ˈÿzÎeñ߈´Ñ¶DMuí÷¨ëÖ[o½ÅõIJKµkeµÊ‚ñ]÷MÄ[<é_*ºÝÝÝãD£´ù¯^½z,àO–¥# Ý:†€9.\FFŠ Ã&Ïßwß}?U£ÀÃ9¢¿H€RÙKýQýÇO†AÒÎRÝÓa$"ö•øÏêðe˜P  ë²<ñ_74ºt«ô§\Ÿ¤ˆ,„:¦EYHû¶„ý‰ ßé8zôèøóÉ“ÕúõëÇ>sæÌ ÒþãB’yþÎÙ¦à?áÝwßÝÚÓÓsFå·þ—Uý7öTÿ1@%·ø§íH%uýc;U1 Oü'JÐŽbÞ‡ö;ÿ=I˾©}á _X2cÆŒ¹®/,\Z­ÓÅ7¦…ÿÛJÒ¿„û…ámÒ çûûûÇÝNºPDüK¥<Ö‚ 2W¥hw±Œ!0Š|NâÙ¶hãéÔ=÷ܳU]Oþ·YîÏWõ?m€ê?‚_e·î×r./bÄEZë¿R€ùÿnÓyÿ¬jªø—ߨ?û³?û¬ë“—¥ÕÊjÿG|w¶i!k¶‹Øg·uv0ïv„Hþ„ˆÿ0éÉ’%FIÿU®TëËÙ¦|nNž®M„KÊ®ú_w4”PDðc `´½ÐOkLýѪ¬u8ÓÄ’ðOšùÏ3ÒvÞ’vkžv2 ºæ@ÚÿþøïC–ÙýMœpÙ_ÿõ_oÔ¢išË“±%3×UœˆïÖ~ßä9Kª¿þð¼¸9rd‚P”ªð'¡2ó/íÿzžÕݦ<Ž˜HñdzE?Æï·lÙò?j4ùßt‰?s IoPýÇF‰5 `b$%þ'íœeµý»´þ#øZ[èçÝÆ¦í¿– øÓ~»>ûÙÏ~ÚõÅHû¸“ŽPïÓ¢Œ÷M’þe™¿óçÏÝOÎË(@16lØ0–ô?{öì`É¿èç°™ÂqÞümúþ“Íÿä'?yL]oýQnóþ¦ãÊÀ("ø10ø=ÊÙéªgg þ¼ªýÚu¦âß×òì…´¦9àÒöo:rV¬XQùöªäíý¾]¾|9û“ãÐ eÿ$0Št›è¼Š±®“ùóç«›o¾¹RÂqÞ\£EfþO:Ux[{÷î}õ¥—^Ú«Ò«ÿ¶F€RTÿ1À» Ïªú§¥g}qj†F@VÕ?)ô¯®Ê ÿCè´¶àÏû¿ïCüõIëдIºzµÓ“×;àñ¤uÄ7¦…-Rñ—ùþ0¬M–ýÓâkÌ ‘Š¿$ýOž<9hõ_´h‘“…!ÐÛLÛÞ‰' ÿéû_~衇~¢Oʇ0¯úï# PE?Ɔ€Á"*þóŒ•bØT`ÒÄ¿IÕÑкB?ï¶yâßÔˆG‡¿Uµ¿üË¿\¥M€é./JB×5sÝŠB½íw´<¼o2ë/Iÿ¡˜ÓK­•ÿ¸€“JÿªU«Æ%ýûZzC } Y)b`` ðcíØ±ã—~øáqeWý·¹.®%¨þc€ƒ°wyœ¬²zÎé¸àW âß6õ¿¬öŒ€Ö3 òÂÿLÅô7jÂoÐm·Ýö)×',@UÅ7ÝÕß$¤M!²d[Ô ‰&ýKëYIÿ­¿Mù Egœ¹÷Þ{ªFgÿ³‚ÿ²ZÿGTvû?Õ (ÙHZÚ¯føÅ¨Å®Ïüqñß•¶Ã¥Ê›ýGä´®èW9¿.â$Å~ u’ú×'oÿG|cZ˜¼>9¡Mú?|øpкˆkÖ¬ þ œ\¸páØc4C¸"Ϋû¾öõõùþS/¿üò½ò„¬8tíÿ§mê^Û¿RTÿ1 á†@üËbr›´Ëâ†@™âßt‰(h-ÁŸv½©øW†¿5ñεšž£v2d‡ÝG@+ õ¶ßy*ñ}“Ö~™÷“þå¼ÌûÇÃþdÎݺujÖ¬YÁy ú‹&ý7K¸R­¯æö®^½:aµôcì}à^Qã[ÿmÂþLgþó:ò„=Õ „½Å}ÒBmˆî<% åAüWeÙ?ö†šó¿6í÷ÀTü§u¥…«Ø¨?üÃ?œ¯Eü—',â?k'*yµÄwÞ·+W®â?¬ÒJÈßž={&Tm¥Í_–ù ?c:¤RÝtÓMm)\Ù¦ŸíIëÿÈÈHáÍ>õÔShSJ>IÕÛÔÓêžp§ú–æ€I@ÍáK4¢&†*å âß¶z­#úÓ~LçÿÓ~o’Bjkþç~‹ë“¯zõñ]­÷MÂÙDüËò~‚tHå?<Oú—–ÿ"KMb´¿! Ÿ¥x‰ úóøÚ3Ï<ó¡º^ý÷Õú¯Õ hº9Õ`Û'ømÿHÿ豟u›"â?ë÷&ìùÿõ®/(mþ¿•…zÛï5é}ëïïfüà ­¬ÑÞÝÝ=AÔÍ™3'˜ùá/ÀâÅ‹ÕÔ©SK’ˆóÖ7ä3ÏŽpAQõ²«Ñà¿á ñï£õ_)ªÿPHÌ›\gÚPOØñª{xŽ.€/ÑÏ^@k.ËþeµÿÇ«ÿ¡ PÓ3Õ«\Ÿ¸IB½ü÷¢êý£GÏSÇŽ ÎÇ‘”I÷—×"¢_Ä¿˜åÖßf™Û“Ö™ÿ/ÊöíÛYöoØ@ü»Œ(Eõšj˜fÔ ¿Dõ”°ºÊnùÏÚÑËñˆ{€ÖûyÂßEüGoÿѱµš®¸.wÿ­$ÖiíoÎû&UIf¤R»ÿþ  .Fu'J0ç/HÒÿ‚ Æ%ý7J¸b´Öö$;âìÙ³…G§œ¸ûQ׫ÿy~ñ¯TþòiÂê?dˆn“ëâ?ÍHýµœ/_-e[I&€RåWÿ1ZÓðYýO:wXÕç?ÿùES¦L™åj´’Poû¡Š½o’ì/-þá\¶Th%ìOrÆíDë ¿ÌûËÜ¿ Iÿ2öü00¢¡—ê›ðX.<ûì³?Ò9ƒêzð_\Ü­ü×SÄ=Õ h²‰fd™õ á?_WÌýt²¸7½­Éo…Ië¿JÿAûÿç>÷¹µ®/Îf.›*yg"ö%ìïâÅ‹ÁùÁÁÁ ì/Þ¦Oú—%þL“þ10¤³DV‘(ŠGyï‘GyKVÿmBÿlÓÿ©þc@ Þäº$‘ŸgÔžG’ðÏë8ÈÛÄh_SÀGûÒÜ¿JÿÁoÐÊ•+ oˆoL‹8Rá?xðà˜Ø?sæLÐöxRññ?iÒ¤±¤¡’ü•¿Í*¼Fù|…£%EÐc)W~øáGôIYö/ü—×àög:@õJ0LGLFòŒ…¤î‚¤ãºƒ€Ð>F€I@Z¶LVè_=ÁC—ž³^ãôäõθm8â»ZB½ Æ’þÃöì#GŽL¸Tú%é?ü‰ø/ÃP¢Zß¾¯ñøñã^Zÿß{⦅¿ýöÛÝêú²e$þ›¤þ+•<*@õ,D¾Ë}MMŸßéKÚŽËÒQк@ü7"-P6J–øïJØ­Íž=Ûika@Ur áôéÓã’þ¥ @.‹#ÉþË–-Kúñ/&@#Þ öØžMáxIôÌÿ‰ï~÷»?Õ'/_û?9¢ü&þ tüaiÿ7 té(Hÿy_æ_x€¶3”Jî ËjÿW¦âÕªU3uËõ—'ï{]öª uL‹üÛ†ËúÉR‚^K=˜÷×âj‚(Œ&ýK»¿$ýKû§W âÈç+ü¬eëÖ­?Ô+HJåPñŸd¤Uò©þc@D¾ X¤ ÍÈÿ5ƒ/y-)ü³ÌÞ¤±´pÙ$á¯2ÄÿØNæŸþ韮UŽÝcÑvmªäkZHÒ¿´ü‡Ë°IUVÄ<˜Mæü%éÖ¬Ñ'ä84:E¸bøÙÞÉ“'ƒ“¢:tè­Ç|»ºÞúï*þ‹Œ˜vPýÇ€›qá^d ïtž¨¯ñEhYÑŸõ¿=ÉN[&þ[0¢’«ÿ*cGS:Vº¾ ªuTE|w’i!•ØhÒ¿´eKØŸ˜Q¢Iÿ‚,ñ'Ký’ˆór¶Yå×(KJÆ;K\П݋÷ßÿ£j´õØ“ø·øõ ñž×À¾?”`dUçm»Š ÿ²?yýÉú_œô;4:–õ¿;^ýÏ›7­éöëeN? zg½Q+ ¾«iZ\ºt)˜ñ¿råJp^ª²º¢:AØI¥_*ÿÒ Û–ÿo¼q^ámVõ5бtâÄ /Û{çwžúàƒŽªÑêÿpIâ_eüV*;ýßec€-e×t™ÉH@|G®^à9&št(þI´i¦nšÕoÿOÚÙLÛñºôzëNÀ”)SêlZH¶»»{,é_F’„Ùüùó•î2 ^Ÿ‹-*µsC ½_£|Æ|´þëq•ž»îºk›>yÅAü䈥ò—÷3íPŠê?TÆP*IÀ"ϱž#ô]·GÕ ù¿KIÿ“ëA-ç7-^ùîdÖ2žCM¯Ã¾ÔåET¹ýŸÖþrß·3gÎŒ-ë'Ù}ûöÍÿGYºtipÄ0Š&ýwšpÅ(Ž|Æ|´þËÓâ‰'Ðc+ƒÊlÙ¿¢Éÿy¢ß¦úŸ PP€§í˜åUk²N»î(Ö<¾Vh,yfn’él»¬m^»é„ùÝÂ?E§°/vyAIUêí,¾›ý¾I¶··78-!{öì F¢H¢¿$ýÏ;78/sÿ"þÓV@œcä!F“¯Ôÿ>úèù_üâ¨ñÁeˆ¥ìºØoÇ€’¾© ¶c¦ _ÏÑ·ýÊ2\§TÂïNÔ@ÈÚá¬é–j±æ´ÿ’f ÔÛó½×"Uÿþþþà¼Tb%é_B㟠û güu‡‰QÒ?â¼qÛlÅ×(ÆSÉ H3LMÛŠ´ÞïQžÈÏúýªçlcì¶ðༀ€ªˆoL‹ìÛŠÈ—y-ž‚óR‰•óq‘§»IñŽ‡Ìž=Û9éC€×"fÓàà —ç±uëÖj3¡ßƒøOê°É úÛé²éÈþyf€­øP)¿5ñÐÀ¼ T×âÅ‹W”a ¾ÛÇ´6YæïêÕ«Á6;¦Ž=:áv:LR­[·n,é_ªþ3fÌ@œcÚ¦Týeu èÏñ¯{ì±·UrðŸMò¿I RÙ•¥¨þc@K˜¦F€‰u¹ÉŽ´®hw]A¦–³™—ý½ªéíå./@DžÌy#ÔÛ©¼Ê²~"Â$y}ÿþýc#QdY¿•+WŽ%ýËùF„Db´ÿkñï£õ_Yguêÿ#úä¥kâ?-øo$Ãð1@õZÀPF@Öå6B¾Æ?€¶þ¦ÿû“*ú&[O8Ÿ–:Ý¥ç´}‹;Zû«÷¾IÒOOOp^ªÿöŽDY±bE°´Ÿ&ý‹ uˆór¶ÙίÑcê¿zá…~¤ ,IR׫ÿ6Uÿ¢3ÿYéÿTÿ1 b&@ÞmëbÝTÈ#øÚOðgýOÏ ‘­©äðÙ´û&IÛ:´°Ài‡grþ.â»uM \“ƒ ³×ö'&@éY»vm0ç/HÒÿüùóS;C¨ÖómÏÛéÓ§½<–YyÓ¦M¯©Ñà¿°úošúïcÙ¿¼¥õPa@¶;}>¾ð„Tó7&ïwZNLÖé¬ß%ÃzLÃéJþ<—ÖŒÀª õv55$é`` 8/]Òö|IIÿá’ˆs ¢Û”Ç“Ö;ñ`$\¼÷Þ{P[ÿËHýW&@üÿq^Õ (q­æñöyË=e}ik^T—¼pٸொ|“Ùÿøó¨iw“®äßà´Ã3Ùl—‡Öþj™Y·•9ë0é_n×ÛÛ˜qDô¯_¿~l DRþ‹$ýc`Ä‘œ‰‹/zy.o¼ñÆ–;vÈ,ËUåüg“úŸUåO›ÿwÙgß<5‡/^Íò Zã ÐÖÂÞö÷ ÉÈký·5£'<çÛn»m‰óÏäöÝåéDÓâÊ•+êàÁƒÁ±¶)ŸAé<ñ´þßyçϪÑÔ“6ÿ$ŸvY#–ýC`@ƒL›¹¤2Û@å°M¨Þo‡­Q&ü³N'm;É,Ⱥ\ÞµlٲŮ/¸ ~Þ7©øKå_:†††‚yÿ¤à5 ú“À?ABþDüO›6­aï-íÿ¾†'ñë]Эÿƒwß}÷ýjtîH%Wð‹,÷—×þŸ÷[AðTpg®h+~­À}]aï 5Œ‚´Yþ´ö~ßti·Ðé‡Fï¬Û,ˆP/ÿ½p}ßdÖ_’þeÖZZ®%é_*°ñ¿·,ñ'Kû 2ÿ/aQˆj=¯ÑÇ6O:5áóçŠNýd×®]ÇÔõÖÿ¬p¿"ÁJ±ì´ÝŽZ­àý)ÎùçP-lW‰Šþ¬$ÿ¢¿)µY³f9aû7⻵M iñ?~üxðüŰ¿øzëRé_·nºé¦›‚ó2÷/F@ž„!Àk´E (Yöχzû¾ûî{E¶þ«ìп¢Ái"Ÿeÿ0 ƒ€¼/,U{€öÿ IûŸoÛêŸw¿¼Öÿð¸kÆŒN@Ùíÿt ”ÿ¾IÕ?œ³–åþ´`špiï—¤YÞOП— ÀåýÆà5f!(’úïƒË—/|ç;ßyPoýw©ú(·à¿$#€eÿ0 Ã_zövÚç·$IÀ›Šú¬ß‡¬ûtÝpà NKJU¡ÞÓÂ÷û&þÇ«ÁÁÁà±å´qDìKҸܣ¤ü‡]W ßÛñ/ù>žÎÖ­[ÒÝ,§ÔhëÚÜ¿Ë쿯à?–ýÃŒ€†™ÐLa1ëŸöüjºÂ;ÛåΡ(D|·2[-•~]! Ä–´ü'µ\K•íÚµÁk—ÃܹsKKúïdCÓcù Š!å`ùú£>ú[u½õ?+½?ÏhFðûþÐ"F@³Í¨îïCÖo„‰èw1j ÷©Å®«éyn§ÅÛmßÕ08d¾:Lú@Âþ.]º4ávK—.UK–, zŒ&ý#\y¾·)¦T__Ÿ—íèÕ,Në[ßzDŸ¼¤Ê ý+3ø‘˜ÐF¿5‹ÛÛü–ØÞ¶¦çºõ(ÿä™./&è¡ÞÝRa “þey?Yæ/Þn-ÏeõêÕàvhuÎC<éáŠ!às›á’ò¹ôñ°O=õÔý:ÔR‚-†Ôõà?Ûöÿøì?Á€Öf¦d {×YjñãÏ|æ3sô±S)ßµ Åw³M ©®†Iÿ2g-#qÑ'†ŽÌûëU!‚ó’ô/âßôïŒ!ÀktA–ü»zõª—Çzÿý÷ŸyòÉ'§Fƒÿ† …ÿˆè·]P)‚ÿ0r¾ä˜e’´­š®öÎu}Àhâ»zGx{þa{õ‘#G‚óqâIÿ:2˜ù/ò7bžC ™ù—nèÕ,üû¿ÿûObâßVø».ùçügc``@‡6;r€Y`óûQÓÞ9¾ Äwµ i©––ÿsçΧ%쯿¿Âí$ÕݺucOé´„+¯±ÌmÊø‰Tÿ} ;.~ÿûß¿ûü¨›pUe/ùç*üóÒÿóöïë—€wÃÊÅe¯»Œ.€šáeÒ×Ý5{öì–0è.°{}ÒR-KûIÀŸ¬É¼¿G›p;iñ_µjÕXÒ¿þ<”žô!Àû*Ȳ“žæþÕ‹/¾ø£wÞy§[¥/ùgø7’p(˜·ÏβÐʺ¬ àjd þø*2tõ×ÙHš G¨7ÿ½Ñ/â_L€´°?A’þåþ-¥å_F®¼Æ²·)#)² …öíÛ÷Æ~ðƒ—Tò’Ib>MøÛVýÓL»\)Zÿ1 #Ì€fÎø›l[Vh耭.¾«nZˆà—9©¬ŠÈ:pàÀ1&»µk×Õþ`§U'üKêRÒ?ÂCÀ÷6¥e``ÀËãêñ–ÞÛo¿ý‡jtÉ¿!•Þúïsî_©ìö‚ÿ0 ƒ{×>c\w€NzwZЗ@Ç€¿÷B¸œš‹gÊ”)AÒÿŒ3ÆÎÛ$ýw²pÅô(Žt¥È*>Пó¡Í›7ߣG $ØBZÿ‡ ÿ¢-ÿÿa4<í߯@¨iè4ð5ÿPoì{.í'jrZªþaêIö—¤YÞ/osÿo¼ñÆ–mÛ¶íT£­ÿÃâݵÀµC OäÓúÐ03 i, 8è§€Ö~ÿ·íïï—ùçà6Ò â*Ž$ûKØß7Žz;ú'•ÿ¬àÆN®TëËABÿ’:S\8tèÐ;wÜqǶ˜ø¯+û—%•ð7mý c!Ÿ6ã_3ÿî«+ÂN­$ìÛ¥c@BÔBAµoß¾`®:ŽÌöË2bÓ§O÷–ô!€!`ƒ´ýK>…tÈeï׿þõûõIyÀ¤Ð¿¼j¿MH`‘Öÿ´Ûd7½0  ~Öy¯ÛÒIð“u%j™­ýÅM 9}ôèÑ@ðKÈŸ„ýIè_úkÖ¬ëÎ3 Ì¤  4dL%É rA^—7mÚô]=î"k[†sÿ&U}›Ù~_­ÿÿaTÂ@ˆ/¨æÍ›7ÝuC¾3ª*¾›mZHµ_ZýEðŸ?>XæohhhÂí/^¬–/_>v^fÿÀN›uGœ7w›bR>}ÚÛsx饗}íµ×öªìÐ?›¶Ûª‘ÖD=@é&@Ò¨ÀtÅxj+¿Ðvï!%â_Ž¥Z’þ“ÙêÕ«ÅÌ Î‹13{öì Iÿ$\çÙfÒöİòú÷ñÇ¿tÏ=÷¼ Fçþ‡T~èŸIÛ¿mÕ?ñ­P´þ4Aì+±_K8®éñiõjšRñ—tÿPPé´ ·‘P?™÷Ÿ5kÖØyÓ¤  ßÛ|†þõõõíû×ý×ÿ§ÆÏýÛˆ~q_…ÖÀ„}ùÛÐÎ@+ŠôVÉ#ÙiIú—%Ô<˜ØN-á~7n þ ý+’ô!€!P ©¼|ù²—ÇÒá:ñÿ.%p^Ÿû·ý#­ÿ*CüÛ~Ì €ÒÍé¨ä@'w ˆˆ’ƒÌù˼¿ÌýÇ‘`¿uëÖ‰}i÷÷ô!€!`ƒ˜V.\ðòXÚøºúè£ÞõÁôè³WTþ<¿ËŒ¿© $Öm«ý´þcxöµœÛL˜–6(n²qKñ@kömå2©ú‹’*ª$ý'-¡¶`ÁµråʱûKÒ8Ш×ÙLáŠ8¯Þû*ã*Þž×Ë/¿¼ù™gžÙ¡Fçþ‡•¿ê¿1€¸p§õ0 T¡ïíquùÔvxƒZ}©A™™îéé *¨YIÿ+V¬P‹-;/aÒ§WªõÕÚÞÕ«Wƒ_¡;wî|öî»ï~."þó„½Mõ?é>ÍLýÇÀ(dÔlŒƒ"€‹ ! 0Y@IØŸTýEHÉÌ\LI²ÿÚµkƒtÿð¼ˆÉ@¸b4k{b\IèŸdUø@‡]îú—ù—ÍúäE5ú7œ#ìóþ‹ü©áo*èiýÇhˆ!6wÉi7•·«9¦…ÜVD¿,ó'Õ~iÿ?zôè„ÛIÈ߆ Ô 7Üœ—¹1$ôáŠ!Ь÷U΋øOêTqAw¾ôjñ§^òrP%'þÛTÿóFF”YÕŸÖÀ€ÊˆüÂèJr¥÷WZ½µ? ™õ?~üxPEíîîNLú—ù~Yæ/û²¼Ÿ¤  ¢HP¥ë^K›—6mÚt—î„9¥Òÿ]ÃþŠ.ù§bAšø§õ0 ‚?5,PÎë:óÛ)­ýYô÷÷K»sÐþŸ–ô/B_ÚþÃ÷Jò¥ò_æ{GÀï« }}}‰•®Oõ¿øÅý¯¾úê'j4ñX™Wþó–ú³1ÒÄ9­ÿ€-iL¸_­ƒ•x³º z{{@’Ó%é?©ŠºtéRµdÉ’±Ç‘ö™ù ;ªõl³Û“´ÿÁÁAoÏí­·Þú¯Gyä7ñŸ'à]ĽmÊ?­ÿ€íg h!ÐåKT´‚øn&”&3þ"ž¤ýß¾}Aû ÷[µj•š7oÞØe3gÎ F®ÍÞ^øÙõ…6ÀÞøÆ7¾ñ”>)íW•ÝR~®•W3 MüÓúàG 'ù$h¡Ž‹4þ .»lúôé’þ®l³YÛ“Š¿´ýûÿòÔž~úé<ÿüóéÓ—#âߤêïZùQöIÿ¶)ÿ|À€† þB3R ¯×‡Ъ­ýY¢IZþÏŸ?Òö‹¥ÅݺujÖ¬Yc—IÊRÒ?ÂC ۓϬ˜Xq㪯¿þúã›7oþMLüûªúçÍý§& ¥Ì—üË}ûùYèŠÑP.PÞ«j`ÙFDÚm¥]Z–ù“´ô'N¨C‡M¸$úKØŸTûC¤ê=ß ÂqÞ¾ï«\/3ÿ>Åÿ‡~øüüÇüâšøRf¡6KÚVü}-ùGë?`@eÿоBÁZ¥µ? ™óïéé D“1âÌœ9S­_¿>èdÎ_æý‹$ý7K¸R­oÏ×(§e©?ù<ûBÞÕËý=¢F—ûRÙíü¶³ý.#6sÿÊQü@ㄽéí›=ЪDÍ…ÁÁAYÓ<3éþüùjÕªUc÷ “þË ûÃÀpA‚+¥ƒÅ½½½éK_úžö%Ód¹?Ûöÿ¤êü8­Â¯.óµäæ@eŒ€1ôŽùP;ew œ={6˜ù—ÊÿÞ½{3 ÎÒ¥KƒCˆ$ýËü¿l«Q] ¼¯yHå_B+=š Ý_ùÊWî8+_³Ä—Ð?ÛÊ\ô³ä`@G ;©µ"¾F!ÔË@Òå SIú·MKuíÚµA¥?Dfý£áU®ˆs ßâ_a'ÿíßþíÛÚ니1ï#ðÏÖ`î0 3LݶN ¥¹ ·Ñ­ÍêܹsÁA*ÿñ(™ë—°¿o¼qì2Iùžo7É6³·YÅ×(·—¶Ÿâ_bwÜqÇ7µ)v,&þ‹þe%ûXšÊ@èÛŠ ¨6E Ÿeu—Ûæ!B?Lú—¤ôîîî ¢KD¾„ýI«(¤ê/+´‚pÅèŒ×þùœù×£07mÚtÇöíÛ»•[Û^û¿Mõ_©üŸ"s0 Ú\)÷íÛ¨Jk—/_Ä¿ÌûK蟜Ž3gεfÍš±p?9–eþ|$ý#\1|m3¬üûÿÚ»ºyóæ;_|ñÅ"â?¯õßGÛž  R„¿R´þtuÝú[ láS¤càÂ… AØŸ$ýˆYæOZ¦£H¨ß† ƽIú—@„+†@•¶)·—e*¥›¥ tæÿðÿ°IwÉ ¦ˆŸÂ?­ÚŸgÄ…âs0 å ƒ h ÐšaÒN_¦PT\:u*h“–ç)añ%Ò$ìoÍš5A«ˆ¬Š iÿ>D⼜mvâû*ùbf•5zóÑG½ü¥/}é‡×ÒþÓÄÙ#*½Å?Mø#þÀ`g¶p@•‚£Hµ_ZþeY4NŸ|òI03E‚þ–/_>î2ép]qÞ¸mvÚû*Ÿciù/cÞ_رcdz_þò—7ë“Ä¿kÕ?/ðÏfÞ_)?‰ÿEþ_`@ËÁŽóµ/gÊ EÍ€˜ö'Iÿ"úu[sp:Dªý«W¯VsçÎ'æ¤å¿ìn ^£ bdIKY-ÿò2^yå•ǾûÝïþòšøJÿE«ýYsÿ¶iÿy‚?OÄ#ð*#ÌkžÇø¶çâ=ñ–T­@„’TþŘá´oß¾qÏQ¾ÌûK¥?jˆø&ý#\1š½M1­¤å_L€2Ð;ôË_þò¡xàU}ö’­ü»¶ü›¤ý'Uý‹ÿe'ý/¤õ0 ­ h0 ÉmëZ`T¾À©ö‡IÿúwðàÁq¢LæúEüKÀߨÛäÉAò4áŠ!Ðìmʪe¥ü z,æâ–-[îyê©§ÞÕg/;Šÿ<ÑŸ—öo»€R„þ€»FÑB¹P€Ì×7䉿ŒHµ_ÿ„'NÈ:æã®O û“nÿ6ÂŒ€¿ò·ÙÉï«t«HÕ¿Ìï•Îý8£«þw¾ð _ÿC–âß4ÀeÖ¿Ëý!þZOÌ«ñYí²c—ëYùBeÆFY¢Jªýb"üň’ö'Ar("ü¨Öó}mSNËøŠTýËjùôwåÀí·ß~§Å<¦Ï^qÿE–ú³­þ+År€m*Ú½íúþýûÏ_Ûïr1Rµ”ùùF¦¨0“óaÒ¿œÖ¯E9sfœˆ“°¿yóæ{™ÿŸ6mÂC Û ó*ʧéîîþŸ¯|å+÷õ÷÷Ÿ½&þ‡-¾kÕßt©?“ªšèwóˆÀ€J ý¤*Ía·Ã:l쬞‹Ÿ]DÀ4ˆ"¦Ãñãǃª©l_’þen:DÚûׯ_´øGEœˆ¹Îfe„+†@YÛóJ>·e-ï>ýßýîw¿üÚ×¾ö¸þÞ„Ëü\3ê†âßµêïÒþ¯”ùr$þ`"X¡F® S™ñ—9i1vïÞ=nô›o¾Y­]»vœÐ—Ó²Ì_–HCœ7f›þ¾ÊçV>Ãr(ÝYprÓ¦Mß{å•W>QÃþêʼõßEü×-Ä’ð¯çüßBüt”è·¹oæy1Š<¹FR1 “þõsÄ´‚ºhÑ"µbÅŠñ;d×–ù³¼FŸÛòÒÓÓ³óßøÆ½‡–/ÌU•öçZýÏÿI˺¤þg#þÀÒ¨ëjd_‘iÄJ:¸l,àOf¦¥í_rBA—ö'c 2€pÅhæ6¥SE>³ 2Êêï½÷Þõ«_ýIdÞXŸ÷÷Qý7ÿEçÿÿ€ üäŒíPëÊzU k'Ož ø“. ü «¨Rá_·nÒ# ãî'¿Ì\ ^cò•Ï­t«4Ýapþç?ÿùüã¿­ìæým ños@ü€¥PÏØ9NÚ ÑK.ò¤_Fª¾<®Ìû‡ª¯¯O8p`L°‰È—¤ÿ¨Ð“þÅo‡8/g›¼¯é÷oÔœˆþž|òï|ç¾]»vU£Kü åˆtWÀVü›eŠ h{3Àdy¬`‡û´¦è†¥ šºïãñ¤Aºô:æc×'…ýIÒ¿ˆÿø’„TëyئÜNæü¥ê߈9ÿp³Û·oßvûí·?©¿3¯‰ÿá Ñ_¤ú_EñoúZNÔ›\n³ãìt;v¬¯è“ôiˆˆêíí›ñ#àÈ‘#c×'…ý…ËüÉ1ÂC ‘Û ?³ þÒaÐ÷ÄO<ôôÓO¿§&¦ü—mTEüÓú€Q±#ß!Ñz…;$èLxQ$%]’þEdÉA„¿˜¡¸[µj•š?þ¸ûL™2%p¼F×m‰ð—VÿF AwÃüî[ßúÖC:å_¾»Ñ–ÿ<Ño:P/Yü+ñoò?ñ†;ÁÁÎ÷ÁƒÏksYWÏSóÄ(J4éÿšÈ[öOÚú7lØ fΜ9î>Òuà+éCCÀ”Pø‡]*BÚü_xá…-÷Ýwß+jbП/ â?oÉ¿¬ÓˆÀ€¶íµlcì´4ýZH/* L ‰4úRýÏïÛ·/0ø"þã#þ7}útÄy ÛÄôH¾¯ÿ‹/6\ø zTg×]wÝõ ú;¦®ÏúçsŸ@⿎ø ;£Àµý?¼lD'í2$¬Ïe%i–¤U¡ÈÚ»w¯Î'…ý ñ¤„+¯±¬mÊgTV¢C£[ým®]xå•Wž¸çž{^T£³þWcÂßVô»Tüó?â0x  ‰Æ€ÍõbH¯ý§Š)ˆ.ÉgbHÀ_Ø=VþCñ¿`ÁµråÊq¢,\æ/n \1|oSªü¡ðo===;¿ÿýï?¼sçÎpy¿°êŸ$ü}ˆ h p¯eœ·yŒ´ç¤®‘³gÏö.Y²¤Ð“!ojH+µˆÿ°¢mû¡')ÿ .wŸp™?“¤  WÄÈ’Ž”p Êf ¿çž{î¹-=ôЯUú¬£ €2’þÿ€P‚`rŸºÞ½E7nšMú‹ië_·nš5kÖ¸ûHÅßÇ*¼Æ$ĈSªYmþÑ—¥¿ ïÜyç›uf<áßFø›Š|ÑøÀGqžwyÖŽ®M—@=çò`gþäÉ“… PyèNÕ××7Nü‡3ÿÒ= añ`¿p™?„«Ÿmbz\¿½˜Vò¹õ±ŠEQô ‡Ÿxâ‰ÍÛ¶mû0"ü‡s¸m ¿IÈŸ–ÿF‰ èH3!ËÈ[g»®×?^¶púôéÀˆ °={ö—ÝtÓMAå?:Û/N’ÿåà0ˆ!€é‘´M™í—Ϫš\í¥ý~ûÛßn½ûÕFÄ5ò7¢®Ïúç ÿ"@-ÿÿ€#ú}<¦0òÞ{ï+ú`"¦¤¢*ûøåѤÿ¸øO û¤# úX´ïó‹~6¥Ò_dÉJßoÃîÝ»}ß}÷=©ÛþO^þYíþ¶­ÿ¶•~Ä?´€!4ûŸ8nçüèÑ£´0:§÷¬"OJVT´KZooï¸kcÒöîܹ@øÇÃþD JËZÒ?††€éc†-þýú;±û±Ç{\/ï·W.í7¤òÛïMŽm*ü¾…?â0šl ˜îLè ýÉ¢€ˆ­0¬ON‹ø—–ë¨(ñáµqãÆ aaÒ¿‹džC \޲b•þ1´éuâå—_þÙµtÿPø%m[ÀÆ ð=ë_OúˆÀ((ê³.7 L\ pppð„žÅ_[Ôôc),8AÈ8p ¸Í§?ýé a²€\æK`R­ïŒmV´½zuþ7ß|sÛý÷ßÿ’>-³0òD‡-…¸Kåßg»ÿH‚¸Gü`@ „¬ÓÁκE7$"Lýu¢ùѦƒƒ‘€[n¹eB{¿Œ Ä Ä2¯1 ù…íýUòËø>\x÷Ýwuï½÷þ·þ^œWésþ¶@‘ná?¢²ÛüóÚýÿ€`¸³[³¸ír€ñó#ýýý…—1&ËüÅééé „¢,óˆÑ¤ÿv®îŸ+ü¡ðo£jèçxyÇŽ/?øàƒÏèÏ~¿]Ö/«â_dîßEø×3žG^û¿Bü`@µÌ“ ÀèmGtRÿÑ2žŒ,ÿ'þeË–M¸NªþÒú߉âC û>¡à—C4G¢Êèçyù£>úÍÃ?üs½ÊEV²–à²ìŸË±ëÌ¿Bü`€?ñn3×orÿzÎŽu°ó¯—$;üÅ/~Ñë‹‘°?ÿóæÍ› Eüç%ýw²!ÐI¦G(øE臢¿•Šÿ®]»^“Šww·´À\Éþ.-ÿ>Ë^âñ¢Ýd‡8É$ÈzœzÎñÈ[o½Õ£[­‡uÿ$//J‹:ií—Tÿ(’ô/â_Ž[]¸v‚8/iéV÷[¥ÂGú{ÿý÷_Öÿ_é¥4¥Õ? ÷6×yíøeE—øËû‚ø @è+»j~Öý]+k§]B¯è¥{õ2~K}¼Xñö~¹lÚ´iÞ…%†@u· üpŽ¿UÅ~ý]9µ}ûv™ñ1îþyB»ìê¿mÂxRvÕÄ?4ÁPˆŸ¶ÍZ•µ°9êËH”ÚdNKû¿J9–n90Zï5Êu¡ÐoõÊ~§N:ðÚk¯=·yóæwdÞ_%/ç—gý÷Õæï3èñ¼Ð` é¼R9gÏž=ºpá†<ñPFç½C 4Ĉš­*–ÛÉ€íˆÈ~Tø·#2£—°ÜñÜsÏýê™gžÙ¥®Ï÷Û¶ùûªþþ.Ay¢¿n(öÿ€à(ô]#íXúÂÙ³~ýúæ½H-&C™Dh„Æ€kçíû¹¢wÜ!ùíVÑÏBÏ÷ŸýàƒÞxì±Ç^Ø·oßiu=ÑßDøÿ>Ûümgýó*þõŒÿ)ˆÀ(Yô'…¦d™#ÇŽ;\å7$4Ò„h܈ŸO3 :ň,¡¸~–ùÒ)ß¹ãÇòöÛo¿¶eË–·õ*#¢ÄBLûÿ6Uÿ,Ñ?¢Ò«ü6Iÿˆ ¨°q`ÒÊ;òûßÿþàßüÍß´ì 7¯¡ØC“ ¼,É(ð1†àÓE{ô¾Q1}/¢—Ç·£è\Šþ;w¾ùôÓO¿ª{Õøj¿mÝEü1Êj÷/:ïø Ÿ&èm—T9;õ#ï¾ûî Ô~nÊ”)³ÚöÍMζÄM„Ð3.àã糄xÒuI‚Š¡?ç—:ôþo~ó›ßþô§?Ý¡Ï_V«ýyÉø6ÂßUü—!úm+þˆ (Qôçí0ç‰ý´}¥ÒÛE< ë•Íž=û3üIÌMh ´Ù3tôèÑwìØ±ýÉ'Ÿ|[g^œSÉ-þ#*»MÞ¶ÝÞG€k«¿KË?â(ô]/¯ À¤â7Ü×××íô;yòä]»v½«[üßÜ¿Ÿº¾|ŸI ŸRvKè𹜟ÉkQÊß¼?â0J6’L•°³¯2vòÇ:tUôàÚµky·¡¥9sæÌ‘?üðí­[·þV‹ÿ“1ÑïRéw(Òà³Íßµåñ€-`Ô Ì€DsðàÁ}_øÂxG¡¥Ð«\Õ•~]àß¿ëå—_ÞþÖ[oIý¦•ñ"¡6¢ÞEð»üùhù75ÿ€PPØ›ÜÖt9À¤þ!жçoÿöo}*xçÊ•+ƒ:ÈïCÜÿþ¶mÛ~¯—ð‹Ïô+·Yx_¿¨ø÷]ñ7ýÌû`@…Òù´Ûe-˜$ ‚´½{÷ž9pàÀÖ… ~~ÆŒKùS@•èïïïÙ·oߺÂÿ»çŸ~¯TþÕø*4½?-Å_)3ÿ.+؈}[ ë{®”yË?âÀspÙO¨%œŽÇOG] ÇñÓáaRÆé)ú0]¦ýÑýÑ¢¿ø‹¿ø_«V­ºuñâÅŸ™5kÖ2ös ‘èU)N÷ôôìÖÆÔîW_}õÃkóü"ö‡Trrž.sæßÕ ðQé/º´ŸMË?â<ì+äiâ?ÏÈ:Ä €ð0ùÚaJx¼qãÆyÚ¸uÍš5-Z´nΜ9ë¦L™rNð,ø?ÁÿÚk¯íÒA~'Ôõ |¹>ÑÛˆ¶ý"€RÅæüÿЂ€‹ Ö 7¢¦@`Lš4iòŸüÉŸ¬ÐW®\¹^ ¬ÕK®Ð—OáO &œ;wîdooï¾Ý»wüæ›oîÚ±c‡Tø³æøGÄk#«þEýˆr7lÌ SÀô´­¨Gü?êŽ@šøW)Âßt Ið§™&ÝÁñôéÓ§Þzë­‹n¹å–•ºS`Í’%KVkS`‰Î˜Ç>RgséÒ¥³z™ÉÃÇŽëÖiýµàÿD¨üà>“5ëMEQ#`¤„ëÚ¥êø~Ô €¸ðWÊ< ­ –#þ³.7=LJ0&-[¶lÖÿñ‹)°\›Ëu·Àʹsç.×ÝSù8´W¯^½¨ûŽëê~·nçßóë_ÿz÷Ç|ZoãÏZžOÛfVþ}WöËø3­ô#þ0 û Íp1’: L·˜:?`òm·Ý¶pÆ K´A°hÁ‚‹u·À¢›nºi¾î˜ÛÕÕ5‰Jký¾¾¾cZìíîî>¢çö{ôÒ|Q±Îï'µñ›V­‹VþËÿ+Cø+UnÀ_^Ë¿©¨Gø?ê¼฿55 ÐåÙ09d ÿ$SB©ô.…IÑÓz”`òg?ûÙ…ŸúÔ§ks`ñ¼yóêÐÁ…7ß|óÂo¼qN­Vëâ#Ô0êÒ¾¯9¥…þñ'NÕKEö|ðÁGtU¿/"î³Bú\ÛÔ]M€FUÿË ósyýižª?´˜eä‰_&@-ÃÈ2j†Ï]ÅkÂvµ0Esuðà<=N0_3OwÌÕËΙ9sæ\}ýlV'°C üs:¿O‡òÖ"ÿÔ™3gNëYý“‡:©ƒùNœ?þJLÜǯ2û6‚?ï2Û–ÿ2 2™3þˆ ¨¨þJÙ˜„º˜6Õÿ,‘ŸõÚ”q>}nºS`êÚµkgëî9º{àfmÌÑÁMú0[Ü4mÚ´õaFxÜŽûoõz}äòåËç/^¼xîÂ… ú õý¹]ÉÐÇguË~ÿÉ“'t»þÉK1Ak²ÜžMå9í6e¶ý—!ø}Ïñûžñ/"üÿЄýÛ¥Ò+ðY]6¿Ö` í}°¹oÚèAü¹t-_¾|ÆâÅ‹gép™zÔ`æ mÜ(Çzašî(Ð>Á´ôaºœrg}<]ç?uêÔ ó@Ÿl»âÈÈÈÐðððUîz¶^¹ºråÊ%9?44tE_?,— ZØ_ЇKZÜ_Ї‹ºBA ûA}¸¨Åü NÛ¿ Ûôôã…óöiËÒůËã&"ÓÆð-üóD³Lå úmÿTý0 ÷|Œ˜ŒÔ,¿Mð_# •s¾fñ~*e6¦e@˜>7a•&ØŠˆá<Áž'] —ª¿oáo+ø}.Âßæ}**üÿ˜Ì[ž¨§ˆÈº¸´XÑŠ°º&æ“.Éëu@Y&f@^³¼ée¶@ÝñzSÑ^/p_¡oz™ëò~6F@Ù]J•/üM €¬¿±Ïª?âš ú]vÎk†"k$"ú£Â¿+fäµÜ§™J•×P†x7yÿk ü<¹]Q ‘-ÿ¦bßFø›ˆvSÀÅ`0y]yïKÞ{n*ü}|¦d D ‚<³ žbDüt\øçUþãâ¾®Šwø6Ê0eY‹½Ä¿Röíÿʳ€¯;nS)¿mþuÇ¿£‹ Gü`@ ‚Þõvq# K¤¦ µ$#ÀVø›´þ»Œ¸ÌñÛš.—7Ò@üþ®f€* þ} ÓÓ¶ŸÄ?TØ0íH3ÒF¢â?Ɉ›¶þgêùÊÈúðeøií,þm¸ïËMžË\áosÂZØÈúy"o$Cè+e>ïŸ×úï»ÀFø72Ô¯Ÿ…f &€Oño"ü}^f*þ]…¿‰ `rñ€-$ìMDZ€©@ …~žÕ}ë¿I€‹!`"ümDU‚Ë^%À§à·ý6†@Q# ¨¸/bV ü0¼™QC O”¦ ˆ¨ÿi§£&D—ÊoûwIÿ/+ÀÖ pû¾Vr("ú}[ Y9EM"‚ß·ðÏ3ÿÐfÂÞä>iݦąžàOö>’ÿ›è2àb ¸~>l¯·5š=ÿo+þ}˜Íüõï?Â:Ì0YöÏÖˆš*CüÛ´ügµý»Îÿ·b@Úýê?®F€oÀÖ pÿ>M×ÓE¿4Âñ€ú6÷I:V–F@TôÇ/«e¶©ÿšÿo‡,_³ÿeÿ""¸è(€oqï#³Àæýò%ümÅ<ÂZÐH ÿËp1âÂ_ˆSáßìù3 OÔךð(jTÕ(£+ ˆÐoT•¿QÂñ€-n˜ÞÞdi@SÀ5ð¯ˆè/*þ›5Pó,ÊZy ¨ PÖe¦·±}\…>íþ€ÈO¼mÖ(@R7@Ýâñ]fý« þ}Ž˜ ÿšçÏ‚/# Q«5\Í€¢×¹›ˆ}„?@‡Pã-€’ö%L*Üysö&¢ÝµÒßnâ¿VàoÕ(3 Ñ«Ø ã²M²Ä¾éue Ä?@ @4“¬PÀ¢i—™þ¹ši×ÿ­0ÿ_D(–5àKü—-â)ö]–ïCø´t@™û¦Ø$qߤror}Þã› ýªÿÕ<üÝ|Š8á˜'}UZükï“Ëþ\2lÅhÌß"Þå9æ]Wô2„??ÒM7\żë\E~™‚ßwտȾ ÏxWñêÛ(Ã4pݶËù¬÷áPIÀD|û¾Ì‡ø/Û(Ã(_+øÌ>M_"ßå5ç½ÇÀ€¦ïcØš®b¾UÅ~­„÷·UÄ¿O1ìºDž¯¥õšQÕ/Kô#ü0¼‹T—yû¢íúÍšã/k‰¿V0|‰ÛzÏûôýÀ€Jìkíða´‹ð¯Ú>^³L_b¼¬ ~+ˆ~„?@ÃLß"݇ /Kà·CÅ¿,# ¨`n¤aàCð¹áÐV&€/ñîSð·’è÷¹XVˆ\Yf@3/s¹ÑÐÖûEŒ€F {ߢ¾Ö€÷¯ÑÔ=ÞÖE8—aøüUý~ˆ*k”eØÞ¶ À÷mÊØô%}ˆ[qݬË} ~„?`F@ ——u]Y"¿Êûv¾Åm½×UeVÑÐû!µ ]׈ë}ì³5k_¯^òýê%^_¥–ýzþ&€д}‘Zů÷y›2öÛÊØÿkteºìñŸè €’€fˆõZ“_o£³ aY/éöõÞ¦ìׂè€BLâ-€6lï×l!_á_e¡Y¦x®JžÞBà‡ ’û'e òFŠ÷ZßÛVµõŠÝ¾LqŽè `?¥…{­bï[Õ…j#x½¯ÑÀþJ ‰ôZßv3êM|~À¨ð~K­MŸS;RoÓÇAô@ö_j-ô\[y®ÕÄs½MÞ `_¦ÉÛ`¬"¹ÞF¯€`¿¦Mö£Úi®S„7‚0Út‡ý¬æQç9ðÃìïðÜø~à€} ž7±üø°Obø±`_ ûü¨°}~¸ØÇD>?Nì‡â€öÛõÀ øß7D xàÿ¦'¶¸»OÌoIEND®B`‚qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/background.png000066400000000000000000002511431347155106100264200ustar00rootroot00000000000000‰PNG  IHDRXr5˜sRGB®Îé pHYs  šœ@IDATxìÝÙ²eÉqèª:Y™UA#kQˆ¥~Ž6I$E }§ ™å….ô‚2ÓcÈÐ@¡2kjÿþXÿ>+“$ª/šHÌubòðð˜Üÿ{íÿëÿüïß?==}ôÝwß}T÷Í·ß~ôôÉ'}ÿý÷}7ð'ó|;éè>ûì³Gøã?NZóñúúë¯?úèã>úîÛï>zñé§áóÉÐÉCÏ…÷­N奩{ù÷í7ß~ôêÕ«¤ûÝ·}ÿÝ÷‘£åùʵlÃêÇ+nêS·zûH׎oçiž0É”ÓN²rõ¥}:má¾üòË^¾|ùh7ü¾ùæ›ç´/¦ý߆—þj¾òŸ ½zÉIfåð«ÌÒ^N»ß¾y3ý÷"íVŽCóÉÓ'#ë)¯œò•M?½}ó6ý§ÿë^Œ<Ú¯üÝ®ü¥Ýñßñßõ¿ëŸ®XýæÁêÿµÿµ±ˆýúÑ_þì5ãÏÐrÂ/Ôøß¯°E—…7tŸ¾À18 àøá%~¥3 ¢Fœÿñ'x†ÚbÈ'Ìÿ~øáO±Ç]ø¨²}<éʈsh_}ö*qa¼#Ç=€ð ÜÕ¶¼þ4-üäO»ðÁC^y [\÷6ÊÓÒ9¢~÷ýw½üôåxW­#ýrõzéé€$?á¡y”¹h´¥}®>ò6ÎW®ÀN>:L>úôŧiÃçŸðõfÀZÚ <‰â­WxÇÇ×ÿÑ)ÖÅ®ÿg[ÝCO¬þ_ý_;϶°E±%ã7ýC·ÿOÿâXv8(¾Nb¤ bÀ@t‘½x:´íØ–e ÛáÒ8Ÿ„¾ývvx0àËÀËËîËøvjÔÛ]%<ëjüÉÔt´ß ?;9ÒÊ3uMÐ=Ê–Ù•¦ §­Á§ü•CcÍŽ‘tý#]¸}Õ Û‘’N®{Ûõ MÀåLJ&å#åÈ8å8eñPÂóâWYžËöyB+7#ÚÊ(Ú&ÏËWü)Wƒ~S:c±ã¿ãß5l>uíúßõïä]ïÑ«ÿ¿Ï‡W}±úÿØØ’µÿlóô'ÿŸX7Õø2ÄÇŒÛÜ02ÿ-0ŽÁæ’žÐ2ò«”›WZò–@0åп}û6 ÊˆÙý¡à_Ž\÷ÝeñÀ|<­WzÓÂlèÑlM˜Ã#iÒçQÏ•ñhïI8´Âø¿zô•týöjÀ‹#à̹=Zå%ˆúU$í铳c¦oÈØEšúÑL~Û'¼Ÿ @»$>rMâÝù ÿ‹Výv°ð°Køöë·G²·ŸðÜñŸ›1h¿N,®}¹ã?³sþëÎÜå²~:óZ¾>ã7¯´»þOîú_ý¿úÿØzzâÝþg‹Ž´ðÆV£™*É*V4ÒªH…›VÿéÅó}.FœCGÑâÙ8Ÿ“îÈðÔŸô©Ç'&w‰ÈƒÿÖ„…nÒË;ñáTHâ” gË£ãÐÈû~ê)ðAS'¬Þò ÏÉ”®ŸîÎ]1È)½¶õ˜¥|íT¡iÿu·N?µ¡G–Ô5qýQ9ÕUyÒ¾ÉWN¿´­ƒ<ú®bdŸ;ZWøÔ%oǿݑ¾Úñ7»ž•9bÞun 7­þ®ÿ£výŸyó§ºmõÿêÿξ5òØÿç£8w£ÎŽÌ«ø6éÆ1øAãSªU¬Í³“S`Õ4>‡7ƒ¯ŒËï|ˆàÍWoÂÓ1Öçs!;*è²Ã2„1ö3yWoé-#Ís„ÆÉûæë\ÀÍ<Â@XÜt<^ÎùñÉñ™²×\€qw›ð X‚ņÁ½NaîÐ⯧ÀJ~Ëðïr·|}eò>»|d!cwýÔ#Ÿü”oûXüëožA¦ãCˆ ˆSr|²Ýwï¤yêÔ1 z´IüNC~~¡‚éËGÛ¨Œ0ºÿÛü¾ÍÛŽ{ýÿ]ÿÖK×û®ÿÕÿôhçÃêÿc¥ôÉÝŽJú€ìî`éJÂn÷ÝìIËû0àÀ´L``v~”ÑÒ@¬F1BOÕ¡ó7%æv²&!à/@ LêoÁññ¿ËSçnY8†O\ ê÷ä8ñ’¥ò£­±$O&Á¤ñ¹Ò©C]ÀˆÎè¥qx á†|ùúJ¸ýAöƇã߆8´^ã ŸS^¸à¬2„^yÊh¶Ÿ”ÑÖÆñécð“ٹƩ þòñßñßñßõ¿ëŸ‚XýÙ¹ÕÿÏ6„;ÁfäÔhíìôï²ÿO?þ«Ÿ¿¶¨NïÅpÛ5RÚ¡ Œ¸f¨kø{„6p›éÕ°'áúS0†gÀÀ|›0ßÎËÝMqîeÕ‘ú.ʾïäGÎÙÅÊ7‡Ð sÊOº¶¡/ϔіqiû”‰?qeåMiß{:¢ËÎ9‡¶å„• @_?ˆ“K^Úznvþ€,;[dAÛúÔù>ïìÒMzûåÎ/BÌŸæiMǪý‚È-G„©câv¬Ðqiû„Ñíøïø›]#SæMæËøæ.·ë׿yáGÇT%áú³úÿ¬§Õÿ–ýúÑ, „2»ŒlŒð$4=Šu´.pÅ$<´þMÀßÄrð²è.¾Œ·0E­LDÅaÃ38B£ñMý¡8¯ß»_iC¢;HÝݺ·§õÛíâÜå.àAÛúƒöµß\—ÙÃwø£Ç‹ U0ÚÏ=â—!B£=¥ÏbŸ“~wm—:ÂdŠ»èíhq¥KdþTv¼[V^Û,LÙå^×ð,ïGýÃȺ÷—2©ÇPÏ¿´Mxèvüwüg"X™»þwýG7]:”^YýÖÆêÿÏþ¿pôõÑÑ fAe j è¤ÕøÖx…Zä×ÎÊ)º¾¥¼<ºëƒW úiÆ„î"÷ èë·_ŸOÈSf,}¨ò­_¸NZã|9 ß&ï*x(çHXô>__äNØÐU6õ åz,w—ÃÅVòr‡j:“Ø×Ž>êVgzi}MCÛ ­áT¨NåÇ¿Ëð½úæi;ж}Ò#ŸÄ‘»åøò¸ŒùøOÛµœÀŽÿŽ&Æ®ÿ]ÿ&³>¡Wª7¢WèBŠnôÆêÿóÅ&ý³úÿÌ“µÿïÚÿTª‰ìJ0ÈŒîm5lÅ K°È.×]©Æ›÷0ìŽ×†þŠcü•á¤áÙ00’o¹½œ‰;Çs=Â*0)] ÌŸ‚ ~]”@#—_iï@EmðrŒ(mgîTM¯äîÒðJ²dçkÚ„–Ì\Úw—,ä@+½òå>â«ÿš.©ýÀ¼CƒGù ×=ÊÝÚ}Ïk>?Ow ¥åø]u{ÿßñOíøf¸æ¿ë¢s³óm×ÿ®ÿΓ̉KOU_ù )ŒÆZáÕÿG—ßûmõÿÙÔø£³ÿä.viz)_š=;(]@Òcžg! Á;庘(gÀÀ»÷6z'_‹Î$ëñ[Ží®…‰)ir­;ò Àñ.«ï¾yþF#yž¾¬4‹zÊwG©|:±ËS>yÃ{|ùýÖceÌÚ0¨¼¡yÐNùÔ=<†€Ó¦Ô;¼êr!ý’±uל¼ã)Ó¼,Mý2õÉAË2>:ù9m'£§®wJ·ãŸžÍ8íøŸõÓ¹R?kb"»þ}(Ýõßy±úÿ\‰`?¢×Wÿ³;læ‡lÿ_hª‡YŸòÂó³ÆñÑ{ ¦Âÿ2îQÐC/-€gÊ™”­£á‚ Ò¿_¿ô:ßx©“ÞQoø XË›­'>ÛXI«qJÙ)ïRpAÜÅâÑõœÞ|0?ña¢üÝÝejÿðõQiÕÍ5_ú©cxÍÿ¤_ct(Ïßòæ÷‘“ò;þÓgž¶Ovü}pšu¹ë×?wéöÕÿlVTmt'ý¹úÿÜþÿèú±gÆ<ÚºÔúw0PÃ]C^…zâP¡·°“ ÷ÎÓã(n,;ÞŒOÊø„¤àݺ³Ã5ùèÍØÊa!+çá*sýòíYÓù}!h¾f mŒ Ð%¯ò§=Öðj8„󎟉9=t@œz'3e[7>÷rê5á¼$0À&G°¹òøÊ‘ëïsiïUgî]ò‘ƒL<øu;þvbwü;:OëwÎÈ7¿¸³Þgí]€êÄwýë‡]ÿ«ÿ­™Õÿ¦ýþ-BGU£@‚òdˆÝ?¢\«H¥UÙ&mâ_ ˜<”¥zÑGŽÁð”€5>0„&»Lè¯O®udwi¤‚ô•(ä W^à@º¸ºÑ*S÷hÓ•¦¬üòÎ%»áS ¡ ײ|ôNûìÂÝÓð!ǧ̤kC¾ÍxñÒ'0ºò§Pʩ˃Ÿg¤ÈÅÿS÷1hxq凾}-ý›kíå§/?å3Ü#ÐU—£Ê©cÇÿ€çÿ]ÿÖœõÄñéþ}­ïú_ý¿úíÿ]'ÜíÿÓOþýŸ½¦4Çp¨áýv€ €àëîût*_Çd/0óBǯÊ)¯\žÔ”ô: ¡´&#ùÍã+ïáò:Ê-±Ã§ z_áè䓵r´î– ¯ìbµ“G^@Ù¤‹{Ä¥¸èôiR|+O;Ш€I½¥v¼ùê«ì„Z/_~:>·#ŒôÍÔSùêWîÐÜþd·@ÿL™wÚ04ʶÝ|í '?ÿÚ¦ÿÿL/óéævýïú_ý¿úíÿÙ¸¡ÿûÿôã¿þÅëÝ›ćÙýÜ<àj ¶‡¦`«ú˜çò 7Šz†œ_C¯\Zéuò8%0àF+e=¥MùÓ8¿àBØó¦¡-]ùä•ü€Ùq{1÷à HÐrøê\€¨±k׺€+®üïí’.Ìðñm~ÛÒr•ë}?¼oüÅ9åüã"§>›XyË#Ÿ]ªÉzÈ(Ÿá1å¦À£LåÙñ?óUê«ÿ]ÿ»þWÿ¯þ_ûÿûØÿDL4Ã|Œô1&Œ,£"­ÆZZ.-%W¹îîÄ¡÷oòk”ZÖý¦þì\…âƒÖÓM™(i=¥í®6ÒÔƒÎÓ´úòF‹@äû¦¡ …µO~w¯ÜÁªüï×·WÛ?˜†ÏÔ«\ðÐxÇ—4ŽNbþ&]Ý­ÿΓ.ms¤©ßmñ¹Öß¾Ö÷•³õ‡÷ðØñßñ7oÌ“Á¼2Gø÷9(m×ÿÑ1»þÞ¨^®~Ê<ÝÈuþ˜7«ÿO¬þ~¿£9r·o±K£‚X°?ûÿ‚’H£êc—¾t ÄâjÁH'.oâhä¡—o!qâø?êH*öá[ã_z¼"ÏU^¾× í@ð\RÏÐ4M3B3¾÷i “ßSÆCÖoãØîe.¦T ȼ¿"í”^z>>øáãyûæù<=vŠ>þø\>Ýìzé3`L¾·Æóå‘!²O.ióMÌéµG¿UVþÉŸö m‡K¹„ç¾=ÿOÉãe‡GÇ£õÊÆÏ /Æ-CVnÇÇßœÙõ¿ë?ú`tÆêÿÕÿlÒÚÿcÓß·ÿù-B‹%FV`œpŸ“òœOÁNæã äLçê`O-t†>  M‘áLzQá1®åjܹ̓Âs€‰»A.¸×È£+Èy”‰<‡¯dR×Zä´=ü:uÛæ³÷í·Þgu.k›»R½è ¢7WC£vEŽC§ž’ʉ6}sÉUYÂÒ¯¯ºöÏ­êG[¤¥6e'Ü>’Þr½C¦ŽöKëC׺ê7Müý4yÊNÆŽÿô ±ã¿ë×ÿ꺱zñWÿ¯ý,ò“¹ƒeB0œù&Ù€#nÒmÆXàn®Ý 8 EÆÐâ!.pAûˆ_y´)ÒzîÆünÔñpTG†Ô;<ÞwM/Mdš6pÂî`¥m' § ×z¿µ#Ü0ôW{{¤—ݨ/~2àjåñu‡ë› œÉW.}2y pÈI÷•mýÈ0ãÃáqwÒ¥½“þŒ ³ˆs ˆF;n2)Sùz|[Y’žv `õbTã9ôí“”pû¸<„{ôÇŽÿŽ¿)‘õv[?™_×\1‡Ä3‡wýïúŸyò˜×Ü0’6sfõÿꪣ6«a>÷Ç`ÿó&w "ö2À—{³(‹ÂÃÈæÛ‚“$(e:ñ`|òÉ~|Çk¾½Všú“p7ÄØ_à%õN=xôžG¸´È8eÕ…Wéùå0´œ²O&' %/tòæv$¨Âò9¾²Ò§³C¹&/ß[~¶Àå*0¥OÇÈ|:ßDߣǧ¡qçK¹»S?‡Ö7IxÐ3}6‰yhÈ©/"ËÈ“rÇŸ¾z_!VMÇË'nG§_Où¦Ÿ20«{ÇÇßœØõo5ìú¯®Yý¿úŸ^XûÿûÙÿ|‹5†bÇû¡eÆ» ‹ÁvtÆPß ;# ر)øÇKÜCQÇ¡Næ¾äqê<ã2îS×Ýá‡_ýx‡~*{ 4y=ýÖ£2dâðÆ« C¹¶·€,w¸"Ýš|ô飫¾¶KÿCãѧ&¢~m=@ÐÔºZOižòç“GZù&>}§›†tÚbg pu׋H¥mhâÔ%°ãÿè¿ÿ]ÿtÒ®ÿÕÿtÁêÿó!~í?;ù‡Ûÿ§ŸþÍŸ¿fcktc¤ôy„ïN^—Å ¸òýŠЮ‹ïWYàMÙÖyTú3` *@;ÚZOâ2ôç8ÈT^Òï®òóñ©»Óœð)Wò¬ûIŸôÅä+'-å‡0Äqêh™¼äSziêzt’ûe·Ü‘SÛ§.õöÑò<éó‘§-•÷þh¹¦O.ò<Ê ŸŽgû#íž²Séióô›4Mé¥UŽÈ²ãŸ>Ò';þ»þ­Ÿ]ÿGÑùâÓ¥GVÿÏÉÁêÿ‡Íþc¶ÿ€Å:@©5æ"§(<½ïÏØNZ ¯|—ÑçïìˆL™޽ÉqXï!pä”eè[ßÝƨã?Ö<`K˜¹GO–Ô›úO\Z]d¿h¥+ €ï—_€Á8*Wá#Jûj^JnJ°ð{…Q vð.ˆ!#ÀÖ:”-(Æ£}u—ÙhÕ‘Ê$æ¨pêˆ>ôWêÉšöOòõÁ8ᤫy€¾âu;þÏß”|ôíŽÿY?3g²dΘM»þwý?tGôÍêý±ú´Ã171+®Ã|Èöÿñ&÷Y¾‰Âìê' èäÇøgQCc4ñã_€è*?ćßä<0öñ*êÇbUÁÍeÒŽ -SYÈ¥>2ò9yÍW®ã\q ËÕ>2ÌsÞÄîH`Òü–,’‚!eðì.—ß¼ƒ¬%í¸äAç´\d¹hÎ&ݤ‚°^´ú¬my eÐ8 ÝÕhðFÏϥѫqmhß$Òü¶£Kýïçµ~~hÇßñŸÖÿÌÅûüØõÿü!k×õ~ýÕÿ«ÿÅý­mb&ûÌVBùìÿ ÕuÊ”aþxòßÂÓ)óp'Æ@3>'­@†¡¢tÞ¡PÒòÊøöàp 8±›õƒü @/ Ã3GhSàÄ´om £84ò»÷º•ÑV»†‘ïj¥vhpɃÚÄ¡ ¿ÀÕ8–Fø»‘W<ã;eî2¦.~;þzuÇ×ÿ®z!zhô·úõÿÚÿ¯²Aò»ìÿ‹ Èi?¥2X‚ѵ ¸€+\Ÿ Ö|Hj¼öXøü¹âµ0ÑãçÒ5WCþôñ¹LŠºõ5ˆæ¿˜sd§Lv­|tÁßå¼+<ê¤GF•ñjk&9ù€ ßÎ ¤Ó @òm»K–ïÁ¡ûÕ¯~õÑþÉ?É‹‚œ«;RmÁZ`É7 ½ÿÊë|º±³õbÚf'Ìý.2å™Ò@­rjSö¾Ã•>¾íd=¾æ¬iåáèïãÃ/€jƲß<Æyœ2;þ;þŸÌ<༒d×ÿ®ÿ»^]ý?ß¶Žn««ÿ5ólÛ”à³%”ÇÞpüÒþÿø¯~þZãuFAE¿åÖ´ÉLÕØ—žïQ€8qgñÇ¥ƒ'OyamÃè{ÔwJÜþNžADÏUe¸úåuO£ JÏ·CE°È8†¤mLœvÆy¯•2ÙyšºÕFFô\ûè7¿ùÍGŸþù£=}Eù Õ_è àRפãß:ø¶\y“©xÒ[ß‘óô%Pä±ÃE6yJ„×´Ìâ|m‚ÃkÀ#9Ó§ …Nùñ[Wû?i¥ÙñßñŸ)õ˜/gNîú·Nvý¯þ·Vÿ¯ý§#9öòq‹’Èk(q1Ú“VÇÐÆ€Ï$VX< %¦üø;MŒóeÜC;̤ÝyKo^€š«tu¡™8š¦ác·Éº€‰«yùÆ Ñ.ú08†e/ÞÉsÔ‡?z`È‘¦ôÖcѤ-SR8´dоùêM^ÇðòÕË€0ÀK¾W4™ŸÛŒ_Ûžz®ß@Ä» S™ôúȉ{åØôè»IǧeÂ3@Jß@ª®pfÊ¥ŽÛ7oÞ„¯?åW™vüwü}Pâ:'™?抹(]x×ÿ®ÿê·ó‘nõ¿¦«ÿŸu=1 ã]R›“¹3z…ßð±Ylس­«þ9síŸý²ƒÅ {î_ŸÍ̧¡)õMª»*œ£«vÒô^¾I¨c•á»h­LALÊ\Š^@R䚸2©ã,qu9ÒóƠédª|xW¾dëS:ùžÔ{G¼82–?0BK6èÅ€3i>Á~6;ZŽÿ1êƒÊ¦\ ¾Ž sd8åÄÅÖ§N}PGæî ã5B“ð*+,¿4M“Þvò¹Ô5,ÄSnÒÔ¸ã~5@veS§ ÇÙå·}" ¿÷åj]M/¸’h¹#V×þç·ùèÔ©îJºß–þ^î»ÍßüœÏŽÿŽÿ®ÿëÃȵKÞ5¹ëÿûè»Õÿ«ÿ×þÿnûÿô'ÿöO_3ÖŽ–\¸®ÁeˆZqJ…‚, >ìP)‡®´òjÜïoy©g‡_i„îÙHï#]ÝÀK?)Ë{ç5r"ãÐLwê{ Ê6]^ŸÖ§ÒÚ^¼îíhûÐÈ ­þ¹—ÃÿË/¿üè‹/¾HŸ¶ÿ\ðûÍ—çÞ–Ëíø¶, fÇPÕÏUÖ{‘¾²Þehߦà{´…K;ÜϺõÁTö}Çÿy—qÇÿÌ‹]ÿ»þ«¿èÕÿǾÝuouxí]»úÿÝø²ýÿø¿þÏÿ>scª#¹1ð\A…tˆ·KcâˆË—f¢Õ`çÒõÐ÷hPzéÊO…zßÉJ¥×uÖ•·#7®`âG'^Ôºì*8x‡”c¯ðN°ß§ó»8»qøàÝöôR>ä'»2í3å¤+ <¡CÿO曆|}9H™lʽ}ó6|”k;É ®nV<<€¦6 ×΂¼{ytœ²=æuOŒ¼¥Kùá1 mË£ìÕ†ÿs ­_õÛŽÿ®ÿ]ÿ«ÿWÿ¯ý¯ÍümöÿéŸÿ›Ÿ¼fŒÆ”sTCi~4ø³WŸ ÆØçUC_#XÙ¥ÁË«8<˧Æ]:€®ÀæžWãß4† q åµÊð1˜<ÂÒ›§]@Ud™KñqC@ÉŸ:JÛz'1rÆŸ°zÉÁ‘ðBÛËòê®Qéòé|Ç£Êáí¤M•yuƒ8žmÂsú“WÃ.}2“îOê¿ùÒ„¹Ðޝ½d"{Û¨Ž‡úTuíø_ïkÓA;þ™?/»þwý¯þ_ýTãùu“OÖþÿNûŸŸÊa|³krð|3oÒj Ö'¶^ÌF \Âçaµ‰gc_@„®Æ)ã_ .ŸS_•º´¾è°Ç„h œ.àÖeðîþU*?ÊRRò€åÔa¨Gâ©käj~A”rê$s}ô꬯O æØÅ_Û9~Á‹xÚ5Ç¤Êø)<<€SGãè<é ·ïš&î©ìÊáW^ê•ß:нC{ÕƒnÇÿÌÿ]ÿ]g]÷õ­+k¬þ®šã¸Õÿ—þXýÛg Y+¢ýúÙ\rò ²A"ç7»TŽÏ({ç“#B äÕ®h”ŽE\pò8;Y×N®ÂâßóBôÞƒr¿Ä­î) ï¤ïöÈh_ðÃÛ'nï´ Ü›¸4rñ 2¼G Kû'y®|üÑË“.Œ¿òêÏ®ÙÕ6;Wv‹ÔžÂí1¨úôÑ/ùËʃþíúé£îü¡ @K;Ϥ; ßëž´ƒ<•¿m³s&Ó<òêk‡æÑþ Û³Ûñ?ócÇ?S$Ì¡]ÿ»þWÿ¯þ_ûÿ‡ÙÿÿËÿøoßO‘W»9@Ä<Œ # LxÄ™æ—ófò7s‡htò Dhåô¹s¤@vj` ¹ó–«>ŠMZõG–IÑÜà¾"äW†¢eñY^ò+v&¸¼bá:fTÇï§T@¥N½ÒÛêLŸ Aù‰s‘÷ª` øÔŽë"ûgŸ–÷g‘­®r‹«ãÞWåQúø€æuÜÙ>R¿vÀ oFQØ¢ £rþºúHÜñ?TßïøŸµß9Üù¾ë×?´úÿØÃÕÿkÿûŸ¬L–9^ã3Âüî1:â­Ý;J { uŒÒ”©`÷Ž|[]y¢ÁËS D‘{îqtâ,||9e0&œü«<ùìÉÇ/e†Gê»x°1;9ÃÏ®Që,Oqò’?íK§N<¹óΪ³L&»`äI\õ‹ø\y‘ùÂŽßyO×È´)¢ÞÈ9e¾¶[ziêã)("“r\óå)O~á!:4#¾2èÛ¾rÒ¯òßñàžžÝñ7/výïú_ý¿úí?[ÿûÛÿÜÁbGjt…)T®ÆÚ®ƒÝ4>…+M¹ã¡›Âbc5ڼ횈£÷4Y¼×}$4x¿ýzv_†?WÀÀWïÉG£LÓ&a Äi‡–´$gòíèD^ù7äÇËÎQ_G»|ÊL>¨+½2q²‘S™ºÖ£\vÒæÛ„ŽäÔIe³û¤þÙýëËHq¸;³|ð¾‡ï}¬ÎÓ†9*¼d(­<.|§NN^]eÞñßñ·nÌMëŽ3'8sMšy³ëÿè‹]ÿ«ÿWÿ¯ý§kÿŸ~ô׿xÍ3ª&ŸR­²à((¤°|Á‘€ñÕ›¯Xè(\`)†Êy?ÕgŸ}–21àCsœŸ ° ŠZ9;^_ý¯ƒ ú­õ‘,=þ¯,êçÚ´‰çï1 ä÷Ä Œ,@ á32(ãçb€°9üÒžKö´ãâÜz#û%GÂ剑xÒ'A=Ú¦MyY)ÙFŽö·<ÇŠ#ÀÙÁŸ+ßÊ&~£‰Ì“¥ÛçQ`xowv¯6–z…ûTžÿéÃkèØÿ]ÿÖÆ®ÿÕÿæÝy}8^ýÿaÛÿì`™ -Ãۉ˜րtW]Š#6.÷ƒfÆQÙ̦ìÆ(k‡H¹®û3õXxOÛ0@†)÷Ãþ0“?—Æ{ù•áL^éø4}Ij2'#ox_°Ççrõy­oH"Ò .”uÌ©BŠì„óü9UD®&¡ÉÎÔEý’>iæå«ÿá†~JÚQ0êΘ~Ñ×_Ý;e'1²5s|õyÓ«R’v#9ió]ËWîÿÿ]ÿçÃ…5±ëÿùhXxVÿ_Útõ:bíÿùµQ;j£¨ö?or4<ß%ÄÞ)t0þÞßÔûA¡-èºOçh/̘wÂy¦|ø/ ˆßŸTzýÁÿË_ÿ:@¦`‚ö´lé „Î·ñžåºCSº‰îÚ8ž<¯s8÷˜*_Üì½™Ý$?ØI^»JqÓ¨Ù¯xg×­mÂÈÖzB?ií»CN_yÁhÍäÝ]ANû½z3q‡Ð`¡‘_Z 2Hkâ[ ¬—:ÓˆIÊå¯>-ÐăKìøïøßæð®ÿ]ÿ«ÿWÿ¯ý?§ìæïkÿó[„ï_† F¾~;¿é7Æýó9êsäGÙöÞ‘Š„ï @>@Äð3Þåۭͬ‘^p$IŸ…)w@͹×ÁØ£åÊ`=К;oéÞ3U ÅýÐ àQÞÛX݃ҶÈ;|}–ÙÈ1ñÁ§õÉópvW[´sˆô탖㓿m'>­Ó‘ágŸ ¸6Ò•o]çøñâÓri£¾¸èÛÜÒ"Ë¡Âh<Æ×«,òM^wÝvüŸ¿-´ã¿ë×ÿêÿèRJ÷rÕÉ¢«ÿŸ7cj«×þÏFËþêç¯M™³óÂÕðPoæ¨Ng$ôí¼ì¦0Ì ä_ Þ û¸ó÷&ÁxèLØ–† …—üÖ-Œgë~óöÍãu˜=6u.O€(ˆyŒÉ¸¦²ÐQÆt yÄñ°8²Hçê'">ÿ(ä¤ãyшûQe®üùåÕ¶©°mÿ¡8œ:íLu¬¤ë mÊ„ O%™RädÍßÉïTFr•çŽÿ»ã£KõÏŽÿ®ÿ]ÿ«ÿWÿ¯ýgj³køuwûÿ °²‹2; ìàÄð 2< áÜpÜk²£tOW T/€C#ÏÐÏ£l“¸‡cð,usÊ¡è ò¤QzdSŸyŸ“,à†_ÛÜ ?¼Üort'_9Y¤7øµm U¶v ¸ü¦¹ÂL0•ðU62\è[¦a¾vh7¿íR¯ð½ÿÚž‡¼“Ï)ÇÄ‘ 0 ÀKú„®ö·^¼<ŽZ#ïŽÿŽÿ®ÿ]ÿôÑêÿÕÿc7ض¥¶‚Ï&­ýÿ=ì¿{®q׉Â7áûK4˜f´¥—–«éxᯤà‚MÀÌ ˆðL‰sŒ;w$LéxЧî.Ø`¬ÔK£N E\¸?ñóÒ}ªáÑ|u R5/_½Ìbò&?íª›ÒÑ’ÐÓ7ÒÈâÁOž€M{2Šj¾5)=Øñ¼Ê…nâP÷ö ]ûO{¹Êkâsú”ýt•]¸áÙݨÐÌEþþ,89ÛOúJùð˜ðÃMxÇÿÌ=}¢vüχƒû|1výïú¯Ž^ý¿úíÿ±ÿù±çTв´†<0èvC¤ÜI;» Òcü1F\逦P ­¸2,æsIŸ ç/?=Ǿä@¯N¾¦\XŸ²å-soÌOúøv¡4¦²?Œä%cÚ0u«? iÊãR:åœÔw);wä’ÎáAmûν.‰—,ÃøÚ!:;H}ã<þ!ËßóG]mƒýWÅ¥Žö§´|ÃðtÙ;eÔ}zácC+åÁ—\ó~ÚP׺K×øŽÿŽ¿u‘ub&ÍÜé<yÐÉ÷ ÂС @š´‡lÞÐ>quÔá¡,yRÇdè éâèåÇ O®rhoä¼èr&ßNÚÇÃ#}4}ëµûÀΩ‡g§Ç„\Ë+'sÜè°ñ´19Ïcˆ¾é©ç*‹¬é;þ‚wüwýïúö ™¾Ýñßõ¿ëõÿêÿµÿÿPûŸ÷`1À&Ñ}÷¦aÇH NŒÎmF¸zçèï*¦Æ]ò6diê`ð4ƒ €7îÔ?uL]£m9ï~ï·û·‚$`ÃoöS:€)ò^á\×¾yZ§zð³sQ`6•<äÓF¼Èæ:¾<ü++y¸È<>Ù¸óŽ­óN¯Ô}É#Oùqus襟˷¾öCùž¾>u´m´p:5ïøïø› »þwýÓ!Ñ#3Vÿ¯þ_ûÿûÛÿ§Ï,Æ·‹¨†™Ñ€yÝ"³;@1úw#®W£ýÅ_<”¿<ìˆq°tåÊCþYØнùêMâd x—®rýÓ—sá|йú @Uä¼ÀÉ ¬Ï®Üðâ(&Ý=.õ÷¥íå8ù\@Õ¤µ¤¡Íeúñ“Ó­_ù¹±SwDÇ$|ðjÝ脹¶7üFññûȇ´ëÆGÂ-½åÙzôµ0~ú`Çÿ€üÎïÿ]ÿ»þωÕÿcVÿÇVT?²µÝ|ñÝþç’{ ´ájhùJwO’9,®{gJ/ À €xünßÄ÷Ö¶/Ë4>á¥.LjÂgÊ‹;Æ*ÐS®2 ¯,|F#:…:ð“IÆ¡Sž­C=/¯«5åÛ& N9ih]hçÛÙr1:áÉÓ¦‚“ÔŸ*O¿«2’©ýF,r©ë':²¢myi‘cŽoû³8¥­ÌŽvÏ{¾OÎÑ(¹§Î-«¾>xråÃßñßñ7_:/Í®½ÎmiÇèvýïú_ý6'ºFº.ª¿­™ÕÿüöÿéÇó&w†´ί!o°pŸè{„&£TYnJZwe’–—÷öÍy¨ g÷ç†g•¸´|R€‚È7`dv½Èþ“'ÝN–Šì0gx÷¾ÙÀ†¼|s)h y¼'‹ï‘¦îúÚ ®Ä‡‡×/ ðÒ~øözÇTËé›8ũ3~å–×6:rì(éx(Cô“ðDòÕYyñ(:ô'§8i§áà«Áúgؾ“ïøG}xrøq;þgìø_ótæá®ÿ]ÿý`X½GwDGÎXýÿl7Vÿ¯ý!µ>þÅ\r‰a€‰1´þÁícQu1¡ß(—À«4dî/¹¿ èpè[¾eŒSÇ‘Aº]˜ÒÍg†ïdÉDÅÌG¼(˜ù¶VÞþ<ƨM]ô(¡Ô5rˆ;â¤å¹@%î‘Æ•WyØ!âÎ1ÞÙýŠ|Ë˱ٔ'_âÈ.o¼ÂoÒêËozýÃwÑ´í~7KzÚ†Él§®ýÜú¤·ÿ¥ÉOÚðáý͹û†à& ¨ÔÆ;/=¢}wYÓÿIÓ~cù·ïw¡oý)‹~ø3’•CÝÚ²ã憾ØñŸÙ²ë×ÿ¥s¢—.ÝL_¬þ¾n@WèŸÕÿÏ6›­áèÒùslÍ?rûŸ;X”bÜ4Jãªâ Çpß3øèMOv‚®NèŽvá3å|OÇU‘¸Çõ8¬ô‡ÇÈpñ GôÝJxdÉ`ˆp—\ýª=ùÜÁSØq¢c±È=²°•h.àÐöã¨<^/1q²ú"Šc€ 04€Eâ‰4;[É¿úÌ}-åÚ÷¶w·‰,ýîÓÌg¯ÎËVµ¿Ç”~ÚG¿âã>ؽ/Zyá£{´yú"}›ø 'aâêŠ,;þù¯?vügÆè‡™O»þwýWÏš«ÿÏ5ŒÕÿ³.ØXà²5t'ûãùPíÿyÖeX)Q;Œ°Åè4N:€bgHAës€@ÀÁ$Æ _k≣wù›ïµ Ò²Ô=e¤Ç¸_a¼i—|øäV ŒÏ¿z F`òÅe2è˜É??isŠ©C¹Ôq˜û“˜ôä_4¬.Z Ê=.m©¼Ú)ÞËÀ>¹};}Xq&[À×”¯ÃK=ú NXOs ªøk‹òí?“—ó6y»uÒýî"Ú¼žbèÓ¯_rµß3¦ÆxòRïø;þ ó¸klô£°ñÙñßõÿø µëß*™µá™?£;Vÿ¶úÿ̶éC·ÿ¹ä#’ubµ 1 G'X¡a„uX½rŒN ÏÐÊÏz›´,¸+¯q´@›× ¸÷ÄØ7ŸÏUž–‰?w¦ jä“랯>à€y”^üĹðŸ`òÑ XD xÈ##¹ø­]óðòn.Gr+#¶üʯLé-¶o¾p4|ÛN}ˆWvׯçÔåáô¶àƒVüä}Ç€¼xª«õ¡é4ûFdëÄWØÃZOš²\ó'ÃŽÿµó7ýÝ1Úñ?sNxÌsz×ÿùI×ã®ÿç¹Qý¹úõÿ‡bÿ¯iLJò2ÂD”§‹Ñ€Ëü»áXåëÅ7e˧iYX“n×XžŒ÷ú)|/§^å<€X_EPš‚Š‚|Ð6ŸEäõS:Oh¦.rØ ¸PÇRÔÐ44ÎÇŹG=ŽL×Åvaôüðžz•BùÚ|Ixyùêç.!õ9ÐUFtÞú> ü“†/ZmF¯­mw;ièÒÆp;²·Íù¢AåVËз Èwüwü3výïú_ýÿУtd_5$¼úÿØ•˜˜›-Ò7ßÕ–Ñþ¿ @Qž“$Ô¨?™<ó蘵MÙ±ó‚†f„O7Ã_#ÝNµs£s<ÒÉsÔøôñÙý¾ Ã)['œ£Äð?5H»Ótr+C²p¢îI?·½.çÛƒ×ÎÚòüú$x8r“/÷€F\»ä€vÃÈÀTù§ÑÝù ã”y´G~¨ÏŸÒG–ÁxŸ¾:¯~(¯ŽÛ]¾WV9:@ñÅÕÿglÁº>û^/}²ãÆsÇÿ€ú]ÿ»þWÿ¯þ_ûÿ·ÿO:ß"˜jT€ BïOuÎØîÉ·õ=jr'H>h$ h>ŒËâ‡f‚gcÔw“€‚Ò£få(TÈãÈÇnàþ×ý± Xø†·c½iWw«”ÁS^AIiS¿]¢qÂ¥«<è*4Ž<ŸÒ²Swñ–_úò/ªrœg"×éÃì üääK©þøx8iø¥•§õ|2 ²àÖµŽSåÙñßñïœÙõÿ¼“kýq]GÖž~òìú_ý_ýÙµ³úíÿûöÿéçÿñ/^û-?“£€Æ.¥‚’Î@KÓ…Œ¸¼)JˆÂq¶>êI4»9I›2R\(¢ðR¯îPuçÇD èúГ6đà =1×㓭»B.¡Šãÿ„Ãc¢²-&“!®^~ÊiÇ„ñz," ghõCä0+/_½ú+÷s†G±zÒwSFZÚDœK~àHÙÒédï@‚p²K¦÷Õ™]¨Éë˜(ÀK¦áƒoÓÐûÖaeûf^!Ì‘Q_&}ÇÇ×ÖÍ®ÿ³¯Vÿ¯þ_û6,r:6kâµÿO?ÿOñ𡤀’ad\ŒÁæ[l| Véî]ƒ8œ\Øà€uÇøÂ£yêR&õŒß£¶‚ÇnGo!ŸÝª‘“Œœt²Uw§#ðBÈp¨Ÿœ6“G~eGy†×I²O©ýƒmè'¬G.í¡ 0¾:Ñ3=³WyÛ—¼‘ -^šÂí'i&ùw¸Òÿ#[_мÛ)“6M¾]íöàJ?¨KymWÞ·}»ÑŽVÛ·ã?s9ýåÙñßõßõ±ëõõ‚¹°úÿ|@×{tY×ô¾úÐíÿÓ?ÿ7?yÍÐP€Ix:kâ™HÓyI¿ 7P<0þÀÁ;nÊèXåj.`“!8y¨Ý…É M¾rê ¤y¼×*;:*ºdrÄ(í^¿²€H?êã:Èc‡ Àø†Bñ·ÿ˜\m’‹Ç½â.®;~ÜOai¯æmêtd}GÐü´Ò2¾øk¾úÐÊø’[ß“A‡0áîÞG ªïÆÂGý•Û½+áöóŽÿ€ïÿ]ÿYeûÏ®ÿÕÿÕ÷fGõ(J7‹¯þ¿ÖÍØžöÕÚÿ7ÍYÝGýæËßd’x³: ÕIĈǸOÉx2¹¦tYCß]”‚y\@ÛLÀ)zÀ˜¸Oμð÷´>yás " $,ç­æÄШO9<”Ínؤ·|eÇ m¤»äŸ–¥éî]2Žû[1¼9Þ¼úД‡>x>ÿüóÔ­ï´#‡tG£@Þ@UÛž&Í=´ ð´”O¿ïg…Ú×Ò#£E}…-l Hòª Ç®ä.-?cÈ¿.ãë3Ž/mÇÇß¼Üõ¿ëõÿê¶¡¶4¶ã²©µ¡¬gmÒÚÿßnÿŸþäßþékʸë4ÆžÑæìŽ ÜIØË+¹^¢nÇP€åêܹšÊñÆ[N8®:шóñîÎTÊO½J¥…ÔUÀ1ÈÙ¹I[¤©GøÎ§¼rñ{Ê)£Þ<ÂÞÕ5—â9À0¯J[ð#³wi©CûZWøµ¾âÒ²äs9ž›pß[UÙ’7éÊ{ʳ`R¼õâåɘŸûU#S%^ÆÈæ†ø€âI'þ~é³ÿÿ]ÿ9bßõ¿úõÿÚöñjÿç”ê\žfhcp™ã çíä¿9Ø'[ ÇQ³ëaw§ÇoÙ•ñžœ1úÁbƒì <ÌØPRŽ«€üå§³C–S­SŸ´y á (Nì|K Ñ¼Æ Ä¾vt64ø…œ×@ @™:Ïô8¢ÀÆg2Gû㦬v ¡:KmÕüK¶nåÐ+ç¸Ïù­@ñÖGFá>M•á1à«¿•¨œ¶q-7èAÿ¾ë}3ô#Uv½€=´ÆEãÅÉÆn÷jvÚÈÝ,Q™ÿóÈ\Øõ¿ëÿÛÕÿ«ÿG¬ýÿ‡ÛÿüTN7 € Œ!NzÇèGñŽÁ~yG‰úâ¼€ágô»%JxL:° l Ë€‚‰óÑÕ'´Èؘtç]iñºóèÐc\/mŸÈÕ¦‰ô>—¶’S].»Y·zË|Ëòí¹hLM;¤+ÀTÞ~3²2MòÉ-|È|dÊkÉÒ;WÂÚkW r¥Œ€(?§£_¹ôáì*#L6a¼›ï§u*·¼¦ïø?ïtêçÿ™Y¾gýì»þÏ·‡wý¯þ_ý¿ö¿v4¶vì³/˜Õþ?ýdÞƒÅ2Û eP’1Œ{ ïµ ÂH»ôÃþ0é'5Ü1ÞS~2cüÝe’G!Ë{ðž°¸Ý ¡Ž‰GÿÚ%jž»Lêæ »Oøõ ÿiO \äGö¶‡¯œü´{ÚÊ)[p1™‘ƒˆLW9üÐ9}$Α¯G=ÇQ™È54ø ÿúË_§ïí~¦ÊI·ƒÀ ·úRXYNëÄ9w¶šÞ2|üÈW:iœôŽõŽÿŽÿ®ÿ]ÿtDuBõ%¥FïÐ!«ÿŸwúWÿŸÍ ö„݉ía‹&®oÖþûÿô³ÿð/_»ŸcNb¸Ä0ÄÓaûôÚ=ŒzñZçÚUa¬•EË&ä½]Û‹÷—}2î5öʽ~Ÿr™´—ñG×ÁS·£´Ð ¸r¬—ßÄk‰¹ü%ó„#í@¦yð*¿ÐNZËU/Þä¢ÇÎz»iIWh•Ã_Mß_w³„Û®a=¾ÒíšÙÝÂ3ý4Gxøê¿·oÎ7Ãð ®2£IçáI¯S‡“_çn–<íjûê7È›Ûñ?;‡;þ3Ofê˜Ë»þÎØõ¿úõÿÚÿÚÓ?Ôþ?ýl^4ZÎ÷n†€Ïù&ÝäùWp OýË/¿c²sSÃN9ÇØO ‚7ùåÁ¸›¸ò¹ø.È…²aŠÐPë7æÈ¨è&»mÊâ퉑¼dh½h„Ó†KuÖ ÞeÿÉÃKŸL!"¤lÂÞs•]ò—»=d”¦ÍNUYUvíkßóµqpÙ£])¨ìÈCn<ÐõØÐÎW‘ê½÷ÿŽÿé;sA?íø_ÏúÑ`@IDATŒfžìú?:¨kh×ÿõÍéÕÿ«ÿÇÅîŒíYû3ûΟ§ÿÕÏ_÷Ûh 3p¢ÃXiÆŸ‘”€ŠÅ.ÿ@0t€A ÷„;2œ²ž‚¦ð”>,FÌ.Ìí®`· ü=Œ\ Ý39õHw±»@‡ Ê\]äS:ñò«d”Ÿ¶\~vÄFfédÏ)m¬)rdÂoê«k‰?'C4‘¯ùø©/ýuN_àuÑúÝ@»Hœ6®X¦Œòóˆk‡4þýQN¾z<òR¿Œq‘aާ¼ô÷´ßÿsl»ã¿ë×ÿ꺒]¢OëèÒìÐM^]õ{âÏÉÞüèÞÕÿ–ýÿùúWsëy7 Ør4Èà›+9®»f’‰ÂQ>5à™‰#mL} ¶´‚yXÇpÙù,\÷ðTº„o~ÁCù©Ç·ßçüïà% aä´„åñO¹³C!ŒŸôÔ3>ÙÑJ?€1"=@ ººÏ¡å¤‡·–‘ž¶©GžÒðýU`-HuÁT) Ê‚><ëO^ÛrÏ»‡+':}ÇQ Ý8Àꀰÿÿε]ÿ»þWÿ¯þ¯ýZûÓù¶ÿO?ùë_¼Æ" "—ÇÏ7âÄ=v™\¸fÆšÑfÄ]@ŸÀàq JmÁ~€‚rÂ.WC!vl\\4r¡WŸ|áÏ^}vÞÓ3åÅ›¯ž —¸ûÍ(uÐ3àpŽÑqüÊì Ž,¾äá§ “†¦eÔ•üI/˜RR×…ÉÈP d;Užþûê7¿Iº{fòMêì*NòoÒêR÷)¿ò”Ü0™'^i³ø<ÊËKۦƕ“~¾<ðíŽÿŽÿ®ÿ]ÿ«ÿ£ãéD=»úíÿï²ÿO?oÆÂÎF—Á2L *ù1¶—aﮋ0 Ð§ÆûD¼¿v üõ«_ àaW« NÝ[~ Çä€ì’ã­‘Mc¹‚"á®I¿ . 2§®9vÅ âZÎ}²Öß¶´}ÊÙ±;ÿIqúïÞMK¦?#DZñÓ&ßÈüÁ~¾ÿõ¯PämìäEû¾«ÒµS}jØÈÖ|ò½ÿíLiv±¸„§ úºÿâõ‡9²ã>Péó¤s_|×ÿ®:„«Î‹.ºlÄC_µ´ú:jõtȇdÿŸþôßÿÙkÊ3¿Áw ¢Æš·€t‹ê®lå‹çhëx–rK³•ùl~™ï¢9?üoONÙ¼™|Âè8»êmâ™ú²_Ö*:šÏ»†øèãÿÿ¬Ç]ÿ×rÜõ¿úÿÌêZƒî]ýÿüe4}Òþ©]gþ±Úÿ¼hT£jL ª¡žYpŒüøµ¯1ÖâãÐ2Ä kÃø ÛaA%nwFDYNZ'—O?wg·É1?òà=åÔQùâ¯f' /N\ØŽŒúÝÅÊOÛ p"{ê9zÄ!˜`òCÉ×±œ²d³3U¾¤&ûtL8u\í áõ§m$»Gœ¯~áÊ[Þêê¥yõäµ.UÌòLYmäš—Èœ^MìJ:)ê{ÿ)ù9òà×¾•®2Oá‡Ü;þ;þæKç“°¹bî˜/ ›O»þwýÓBæÃêÿÕÿšýúñuɤ9aÎ1\.Š 3´ã’Ç`O¸J´ÀH²…NÙúôú(蔿@£ÍYtxB¨¹w¥ÜUž±Ç瀶Ê?ò¬lŽ¥á÷©ßJ?Lj×+ÈÚvá÷8NÐUùå\ù7aN9|ôü|*ùêFmš«žðºöeËU÷#!ºñ×nN{¹GÙáÍ@__Ï[ñ!zm—ïŸì\¤žõ“8jô'G®»/½õ–æ1~Cø¨Gù«<*ƒðŽÿY÷¾Üñ?GÓoµÕy¸ë?zÏZÜõ?_rZýÿÐÃlËêÿÜöÿqÉýnjx›=€ÈØUƒ#|ç)ð'̨عÀHùÇxr=†çÆ›qVV9çÒ=5P|÷°ú2êÎ(%áîxY ~¢§ß}o*‹LÚÅQ^MpxÎeù)Óz´14@Ä<€Œ]ùd‹üC N2> ¾W» F’?iz.<'Ì/¯d\*Gò†Æ»ÁÊ/`sØùö¥±ÑÏå£×øÅîQÇ=¿yü»\ K;þ;þ×¼…ÜwýïúޏtÍêÿÕÿlÒÚÿcãÙ^v³öšÿä=X5¨|‰5ÆÙ™ÀJ 3ã@“…æA+Æ„bœ•®ôîØË£Ã» «B~ÁMd¦ýá§°#wÎl'þb@Q½²m—80‡§]¯þÆ!šÒÝÃÀUÀã€;w°ðцö‡vw—Oùá¶M/é'|ËkÛøÀ܈ð:}t£Å·®2tMbúåÊŒlWXzó*OË"y¿¼:J¿ã?ý½ã¿ëŸŽÙõ½°úõÿÚÿßßþçMî *P@ÃðZHC+aà1‰I/­4a†ÙQ—rÒƒò-¸Â£<ù€Š) Ù‘á*Œ?z¾ûI|õ@LzÀÀÔ8ÍM@É}ª‰Ûûͼ_êPðÆÏcç˃g%Š—ü¦‘ `°åÛ6ò¦O‚*'Ð8íšzrÜyÕ×¶ëðu'¬rx¦' ϸ‹VÕ«,YðtòW&yê©ÜÚ0 IÜVsórçí¢U&}8tøxå'/<].mZ饕&ŒÏŽ¿ ;þæD׈¹±ëÿèº]ÿÏ:…ž1GÌÕÿGÁê‡[ýÿGaÿŸ~ú7þÚ Ö°2”œ¯ñ&Ã*o·Ê10a  ý܉²hЄnWþ|é¹@>þ·sgëÕËW)3D¡£ Ýÿ©{ð¹[Õ#Áð3 ‹<ÔqÏ1àËO_žŸöy î<Nà ð‰lÓ1xS§~°óƒ1m÷ H2ˆ“ûôÛ30Ã'í^Âa¼Û[òÑ—'¿´|4þ„É#¬ÏV¾|K×6é£gŒYiAuå9íØñßñßõ?+.:e×TFtÎêÿs÷uõÿÚÿÚêßfÿŸþó“×IB5îŒmÁ ekP lð=1Fc¬l/·¤¸úÜ㺌y'󀓡ˮŠüáW@Ìõ{ܯ Zù­›,â‘ÐQÿÀ‚a´8ôÒ<êl[ȉr0ÁLSÿ´ë%te PlLvø]?¥|Ò¡š´EßM;ìVåÛCÛ6¼½vÈ´Ñ(´Ï䧇¶ýÐöâJG¯ÒÞËÒ²–—rzazw¹ô™ëš¯,zòówüÏ<Ýñßõo­ìú_ý×™«ÿ×þëïCÙåØÿŸüû_¼¶óSƒ*«F6†xŒ+#lG‹áFp-â€@ ½°´ñ㎱ÆÏÝ©‚¥Ôéz”k}\S°õµqe¿üòË>ÿüóì"M¡”sd&Ÿ¬¥ðš´—³Óƒ·|²>h€‰@œ}â ñøM]S,e6¦|eЮ€´ñO†PöèÜIo¿@vù î´[;ÜSy’€+¯®»—H‘‡;GŒ‡V.'ýþ"Qtêkÿ†·>oûvüuÑœïøŸ5Õùb~îúŸ»þWÿϨýZý¿öŸ½ÿmöÿüáRpÅZ'Øa.@ñ#ÊP;ƒŽÞS`Upc…+yuøMÁ€’‡É+/¾ lGÌËÁ•YÝ©ÏO˼yä¹äþPA;a2(Ûv×Q <€¢² HGÏ„tiŸÞÃK9 ˆß…¥,'«ì‰OQmÞ\ŽÏÏß ?yÒôzôkÚJÎK4•…œåŸ:kŽžÊ©k”E—öNXþ$fŒHõqïónÑ)_¾•½4íÜñßñ7Ì/ói×ÿßþ‚ˆuÓuhMîú¿¾©MW]¬ïº¬:jº*ºK^û¿úÿœ^Üû,×Z¦?õÝêÿÿÿÛÿÿËÿøoßw‰Aí6°vHrq|&<#kPk¬ÑP¸½PþÅ_ämë¾ç­ëw^Â5îÂ}+º4õdM:P#¿i%vx¦>N¹~õ¡ûåÿóËütÊÍý¸ÒŽ×݈©'ŸÐ‡§ÇgúD^Â׎€5‰©Ë?í˜c¶ëG§¥…ßÈBi¯ oyê­‘Š‚™týÉ`õøIÛÚ¯Êx­Þßø£'—x}ùÚÈÉ–ï§¾›/ìøŸ‹úúgÇÿ¬?}a>íú·3~v´wý¯þŸEÝI§®þ_ûïËw¿Íþg+ŠãR¨>5˜D&§;85Ìô|ìxÞÝ$î\¼ÿ,(ë‚ å)î:lʳyÙ!:e<êîN](õàÄ9ôÛ}vˆ\jÇ#è¾™8qåb¦ §vi>ž.šwä¼@9€å¹â‡ç¼$tÚ9ç[Œ|qŽ,~Àz.@gÒãO½>{3m!‹¸Ý¹þN"‘‘’Ç@]7Y%¥ß&wF,åK'=ùÃ3a}2ÿ ¨Nî”'ó8ã²ãÍŸôÈ(ÿÌ)ëÜ5:—LHóÕ¼1Gåïúßõï¸ùpwÑ‹“`î¬þ_ýß¹ÁU§tnü1Ùÿ§ýõü!Ó\c¬å”èx] £ï8X°XlùÖµ,ú(Üñ‡€Ò¾/8`Ã}Ͻ¬pãå]ì,Pò€^ñ'<äŠ F†îh˜3F`øFžÉóÏ])ÎŽFFü ¬{Q\AQåÁ×#^Cƒîž.ÎIà ºíKLÉÚÉõj@á¼ U¹êäëøîžI~´ïÀ³mn¯õ¶]]ä ÎøŒ¬ÙÅ›]3|{q-~ÙÅ›#ÇüÚÔ—?;þ;þg›æé®ÿ]ÿ«ÿWÿÓ‹lÎÚÿc/k‡‹èKiûÿãù±g‰us÷hJ¨S)YOïˆLÒjŽÑîq!>@ÑXõëUVCSP!.œ¼9–ãRÿ¤Up<Õ©9>½Ê±ÖwG–‰«ƒ,Žò^ÎëðrNû#>QøŒ/þÉäP©ø«h‰?ùh#Ó¤qd”'-}2¾v—MÓù¸úÐŽŒÞÉ•t<&\Öiƒ#@Ž#¸ò&»'|ë!›Àtˆ6Fæ‰÷‚=:idF~?RŒð¯uTÞ$ÌŸ”:Nž‰²ã¿ã¿ë×ÿêÿÕÿkÿÇ&þö¾Eøg¯RFWAŽ‘íÄhOºðXÝ*€®„Wv„³¡Ç?F~vvøŽgÂ-M®:”-Én̪ ²^€*G…Øë¤Ü”/ L˜ÎLñ Q÷ÔEf}üË|·>ñé\ŠŸ¥ÃS[Ú‡xvg.@èG×ÁZìNá#Xʧƒ Gw£&Ï(Þï´çz'Ö$RèÜ¥Ò eñ+ˆ–ÉØñö*+ÚöAóñS¾Œ‘š„§ðŽÿŽæ”ɳë×?=Bw­þŸ£'WÿŸùÀ–°ì ÛÁmú€ìV) ¢ ´ NF®ŽÒgEüÊR²^…ॡ>åY|yxpø ÇH+; yì–ejÃ.MÙL\<*«´Ò#ƒ7ƒ˜ÀMžz ˜òÉëfÒ¸îðàAQðs¯kÚDÞȵ±eÔ‹‡¾mì$ xºä×§þE¾Ië¥auM²û†oâûYv²ô»O 褿ß^iÃx幨._™€7 HZA,y»S§>y?ÏŽÿŽÿ®ÿ]ÿtÎ8z-z{t ßíþ_ýŸyÀÎŒíXû0ÛkÜíVVMìetÏB:à‘·{Ô£º\À£®s1,ðp©üÕgóΩù€È+0âÿ {ƒ¹Œš<.Oe-gqŽßp®?€DøŒ?&UÙîº$aX©÷·ä“¯À jœ|ʺo@&eÐIWŽ ÿ‰Ë&WÛ%M¼m³›†·üæuçÊ@ä÷åÏÓöñµÚÄ-Mý“Vzß3eÚ_©kâhãðó4>‰‰OÚÕæ–kÇŽÿŽÿ®ÿ]ÿ«ÿWÿ³kÿÏ&ûú»ì~*‡Af¬»›Ãè*èÁäý,Æ™Âå1èG 40Ê ¿òøJ¯0 “Þ:ñàê'rÅ¥5½¾üÊ–°?C—·®«O_Ìû¹¦>qËÁ®š€WHw  º;üÈÌç´·ŸÒ Õ°1|9`¥mG ©£ró˳éúgÓ?/ß_Çh‚~ÇÇK~ûóð¢ä§nõû;ÿ•á’Ÿô³;˜ü‰;ŽEØ]ÁÈFÆ«ñŽÅŽÿŽÿL–¸®1ók×ÿY_»þÏú 3Vÿ¯þ7Öþûû÷Ùÿ¬³lŽbu¤åxªÙN‰Ý&Ÿ^8Š—Avɽ!q»0\ŒùÅ }B¿µV=)< ÇÐ&å9O´ÊÿÈv€žôƒ%9–øØ…’À†æó/>Ï›àïÀI{ª<ñðHSt´¹„¨L/ofÇ?u í?âd©Œ/烓•2x¢÷£Ôê@#ŒRGy©O¾ºu©o<&~Ƀ= $}¥[ËW¾ú8½ZYã_iòB/p¹ÿÿ]ÿ»þWÿ¯þg+ÖþÿïÙÿüáÃO‡ÆëÖëçXž€«1î5ôv[¼FÀ]'à‚Í@C‹.å ½ëS0ÁŽã-îA{êœ áz.{ŸxÃwè‡Ïû)Ûev2…ÿ¤÷}RäHÙy¼ŸÛ!¿úäeg Ïqú£Gohyk<™Ë/mzõ‘¿2µOÉÒ~ sü¯w+ÝëUxL¾t’´ ”©§`*´CAFõ(§\ú3¡òðJÙÉ/}g·JàUYÃ#lvüwüÏ©]ÿGìú?ôVÿ¯þ_ûÿûÛÿ'¯i`€k„íƒôE” cnÇ"ãÎvÍ0{Cº]ò€˜Ioœ­OÚÌ”gè=÷ðÝø_ø ^ƒ|áÆá€°FÈKVm°CÆòŌܡß[çÉõÈÞ>µ‰ŸÓÞ‰»ƒÕ6†~r+we©l){ÉY¾•¹y 7ô<ýä7]=œ2òÑJ’ì äXQ;%ŽãN•ßt~꿟L¥Õ¡õàáߎ¿°ão>žyµëŸŽÛõíîÒ‘£“VÿÝK·fè—[˜~N¾>y«ÿ?,ûÿôc?öã<ŸX¯×˜ nÁˆ£À¼4s”ŒtGd ?…c'Hy´â&hàLÈSÎ_¼àΛøßJ»ç#šÜµºMìðYì’E!^ÞΠDNaÀ© +—¹‹jÛÈëWvªð¹ä!|;RƒAtð÷"Ñ#ÊgÂèšFÆö^y&?íçºã&L~å=•H4Ò!G‰z«²UV~û¨œJKšô>'ñ¤d;þÓç;þg®˜»þwýÓ%«ÿŸuìêÿµÿˆýúÓyV úûñ f„-2Ç\ŒƒÃΖ.‚Þ±¡×ØñN””<ßç' Òû´.y@Ã|ˆGÞä30$7C ÍMùJ ÔµPÊ?cd©è*à¹aõ5½wÖü€¡Ö7>°'¯}B~ßF ¡vÆïqfîµ o—îÕNYý̵ž¶Hü~ Uº1ééÓIkù+;}r/‡—~¾xvתòßéÑíøïøïú?÷N».wý¯þ؛ѣ«ÿ×þ×~ÆÏœxúÑ_þìu€ÈQ™ k€pïZ) îN“0p€ž+ ê(ã*¢úòRv€DòŒ 89øymÂ|ûÍŽZê˜zRÓå·ÞaPbû^¾mkŽ<À8ø™W×[Þ¥¿|yÀ >>‘ðBõ ÛÝ 0›pÜø•¿Ò9† ðRnÓSò›¯Ïî]ÚxñÀ ÙÚ_úÂÓ¼©<}üZ¾]È©Úb·¯ôá¡Ï†_ÆlÂ|éê"Nüª‹LÝÕ’Þvá+^æ„wü§#ný´ã¿ë×ÿêºrõÿ±µgkÿφÎÝþ?ýÙþׯQ†hr¡]‡1½¯S 1é‰_X¸ ƒQ®¡æ{š†®ix÷QÓù z¶`SÊõó~*éêY[GÓ}£/÷ÀÈ}ñ±Ûä˜öä(rÂÊâÛ+ùbãWôÞö®NN»¾>¼ìÔáá‰i)?a»f:ŸôéȦ¬zm`•“ÇáÓ0¹¸”^i«ox-¨üCÑO¸²òñÑóGú°y'?¼®2wÃÇÇ×ÿÑQÖÜ®ÿÕÿÕ©«ÿŸï ³-ìÛÂŽ¯ýÿûíÿÓÿú¯™`Uƒ/ž`Ó‰ãS<~ŽæH¦³å{¸‚ €-? ÜŒˆü™´ €+Á`™Ì&292ˆ×}0áCÀºÖW¹.6¡S_Ê 9€CQ*ß:X¦eµÃ*ࢼðV^[È¢îõ©K:>y„AwZ>þð.ÂxÒkúi›²©‹aÃS?-Í}\¯>æ§ÿ\ÞbªŒ§.ñ+’¾ø;hd§®áË©ÇÿÌåÿ]ÿ»þ?{èÄêÆèŸÕÿ«ÿÙu6ì²MÂÜÚÿ¿Óþ@Ü@!:KØ.‰…ÅKã3ÂÝAb„„åpÍŽNA Sï…žhìô:'Ú<ÁŸáð°{¥[¯-£Þ»S¯8 ßÅh\È'‹ˆ£?ÏH»ì\)kG*|B?`ex8l[õCëw̨îó>¬ùáé«o `ìnqè=•1}6m:€)×(?…s.Ñæw'+}:´H˜üMÃOÿxa*×,2£¹?É¿ú·ò¤ÐõçN«Mâ;þ;þ»þwýÓ«ÿŸ¯N¬þ_ûÏlþCí^4Zãp3à€ Ä ¤Õ˜3ÀÙ PÒt4?‘»aǯ»[õ Q€‡rèùòù¾í§éÒ*¹È$­/…¦¥SÀµÇQÏKÙñ?si×ÿ®kaõÿÑ «ÿ>Xû?o÷wÙÿ¼‹ávôǸ2Þ,cØcXfA™H£Ë1ÌvŠäôŒBÃɳ¿îQÀ]^‚“¦.´œÝ*¯F2jüñ&G_ƒ >>çO¹Êí W°%¬]•¬ù¶Ü\TWV™‚ w¥"»¶M;b®öàƒ*h2©ðPÞã MZy+×mÓ¶«;wèO™³c…V9mô҉ܤ©WýúÈ87µMö3 ’ÖºÂÍÕÖ¦××^2ìø€Ýñϼ1¯Ì süñìúßõO¯¬þ_ýoD7ŒO7¬ýÿíöÿÆ•{5> `1ÀŽÒÒ“Æ—¦c9q.ñ À8ÚãüÍ>O™òÀ»/ޝ, boú§óM¿¼àíä»—ÁNÊ䣶ÓÐ÷#Hu“ p!³rxi»¸6ß‹°4yiãÕ6ßeÀqê(}ÛGûO`+wÄ®¾h¿µNùsü‰>2O~ºDÿ¨û€¬Ó&åÆ:ùž÷]ÓñV®uîøïø›/»þŸ?°ìú_ý¿úíí9ýÈ^rì§tNÚï²ÿO?ûñzJåŒÑ¤€;G­ þܥⷢæ)+MÅÊ —®´|â1ý¡›8‡Èp]Y®@² ‘æá¤À(ûP†4ì\ɻˣü×ßÌ· 'ÿÕ\X×FòPå·”Å%v™¦ÐôÃáËu䤾)kGÐý©ôÅÐ’=´×±j˧þ«¯ÐôQwË’ òäAÓr÷±’&ã+¯Œ×Bp)3éÊ„÷„wügΦ¯vü3—fžÜçÔ®ÿs”¸ë´éêÿÕÿ£+ÇäaOî®6)¶eòÄ?4ûŸKî v€Ä†éÑáÕ8þíuVžÖÕz½f‚C˵üÄD?ŸN®Ì´¿´cÇ?ݲã¾`²ë×ÿêÿcÛªoWÿ¯ýÿCìÿÓOæ·¡ÊpFßS#΀ûÔ*nrÅ`j:ð"¯†^¾Éhǽ#(yå+Ì€©Ó^ÊNòüò£ä#ÏU¸ê½)»Yà1ù){í&©ÛnLä¾øG®©ðRæ»9ÊóÕJ<]¨ÿõ—¿ÎëRö’ÇòŽ8;?åI¾ºÔ?u<ÚÞŒË'ƒ{XúD]€6ewíF‹gøâu¥÷þÞ\ë峯Þ|•#@üÄŠ`èÕ›û[SÇòÀGß«Ÿÿÿ]ÿ»þé1z$úvt]B?¬þ_ý;:s a‰:/ÖþŸÍŒôËôM1Ë=ýâ?ÿ«×.™ë°,¨YX¹od C<$ rAZÿ”«a/IÞäã ‰ uøXÔUîõÀ`ʈ\õH÷Í^¶Iޝæe¦ïÔ?ôê›Êr¿?å[7ŸSVº;H¾h=\A ^À˜Itwm ‡VûRÏ좩£€Kòy¸¶»wÂÈyïÏ]N¿ëúÓwxrx¥Ïæ§€ÎÐL¯Ÿ¶Me@§<§Ò¹È#y¢/_ÍÏíøïøÏ¼2WÓ]ÿçÈ×?3ŠbæEt }ré!seõÿê¶„Ý<óálF$<ócíÿôÇ¿øw?{ÍðpÌâ6t¸»Ç2ga¡sÔ¤C m‡¦UÆB,˜à7\p2xÌÓ4>º Å<¼¤åèod€lWÿÓúOã¿pÞE'\<[9â&kzùj2€“¶h+G¡þò—¿Œo§)çÅ/ôú#2Møî·?”W~ü”™þäô«42œ>ü¾I‘eòúÍMéø·o2¥]}U¾ä#gËI0¥Hõj¯°4|+[dp¥üŽÿŽ¿ù¶ë×?±úõÿÚÿùR߬.6wlôÝîKÿ­öÿ§sɽ…ëìÈŒ)êÊ(þ«9BËÏÒ ó(ä!VäÄ0Þ1ó#þ½§õäÕÉ=`Cà |ÜÎÏÉLX9²!êS/¾h<¹À=i‘ëªt|ɧ°òq“×oÓy÷Ö«—¯r¬‰V¹<—,êR¾m,¸Ñ: 4uú÷Î+¦ûk,  \eà@4¥Ûñßñ7÷výïú_ýÞ¸úímæÿŽýŸ#Ÿ¾fh1óÉäîÞ7Üòã,B´cð{&Gù lºCx€S‚2ò]€¦ð“4$ãÈÄ)G–„‡îN/Ü>wùä hó𳃕×?øâµ‘£àãÞnm)øÁÇQ%¹½ÐïSßóñÜ$¦žÈwšñhCdŸ|­ìdv™F6y€h@ÒP„ï¤ùæ# ŠŸ4Æ­OTä~€×«ô5Z.ùÓ^>úŽÛŽÿ™K;þ™&™æ˜ùQw_3©wýïúÏÔ¸ëW â«ÿGßΙ…´úæÃ‡hÿ°,Æ7¯4…pr-F8ÎD'Þç1y®ËÝîu‡¤åðÍŽÐeÜ | ~Gj_¿=wªÐ{ï”c,´@38ø \ÞÉsÉE´\Ë5®lDåB'œvÏEo»m:—¾•}óöùçÄå‘—S®ŸøXÔþÜ2¡¦L^Ñ>Õ†¤>îo-öŽ”4í¶8à øSãö¨wÒô«º¥kKÚéNÜäIç§Ýã‡ïå‡Ç옃Ê.mÇÇßœ0W,sç±^&ë¸uÞÐ+«ÿ¯5µúÿè–é‡Åþ?ýùÿý¾¦P_Ì·Òz7‡¶VY0%;ihν¡sìe1鸸ÉkØ7Õ”HÐ0êv}òÀ%´9^ºÇq /ÍÑY"âó¥Ç“â‘sèêÄF‚Ì£ü2J;¾|™Èâ‡~”‰Ú â(ÌÀJº2•³;FhË“¼ );Rk³r¥kyÇ…Ýá“_ õÜšù¸é'm"ßW_Í+nF/m¦êéN ~x¡GË'Ú¶EˆT&FÿÿÿëèÜ<íÜÞõ?ïßÛõ¿úõ?uûB'ÐkÿÏæÊßgÿç5 ÿúuŒûe„kÀ«`hùÒët®ÿ“AÿÊl9~Ãhcð‡Þ€ÄÀ(() è XßP±S0¸‘Ásç:È0Îß6ô!3QÉ)ÿ’ M]ˆ]'Ç~híiWå 'od:œ#¼+_ÛØzÑ4¬œ°GyïáºË#¿m,ë _=åÒ~e¦¯Ü!˜éÂïÕ©<@Õ{m•¥m/ßÖE¦ºÿÿ]ÿ»þG‰­þ¥¸úÿØWö¡vƒßð‡lÿó&w;œ#·ÏĨñtØtœ…ÅàCüîQ£S/¥ ™;Y@ `àðI|~ÚÆq!ôv\&¬L×Ð’‰¬|CÙê“oœz»#u—©á†­#ºaYÈSÔãÛÜÙ}°E&|rD8räÈr!Ohæˆÿ#ßô裯ÿHÆ©G_¢VÆ“ú‡¯vë<Õ†öâ­Œ/¤ý#|À‰3¦§9©<úÈ94èvü§ßwüwýïú_ý?:uõLHú½àjc&°öÿ²¡¿ý„p&UŒLb'.X ÀØ_ŽçÇŽ™þžøøâ~ø@ô÷²à‰P€0ðåüDÍ_|q þ—ÉCww8(ŒoÇ廩  ñÚ†|[±2SG'y¦mC‡ì™÷sè€íV”Kx neF“Ü P’¢œ9ŠÄ3Ÿff/ŒÚ“oFNé'mÁ“œœvµoÜÕB Mm‡:.9êð&žì‘ï׿š·ÑÏ[éÄ´œzÚa´Žm¶Üc†òwüwü;·îóÅ\Úõ¿ëõÿêÿµÿ˜ýúùü‹×W #üP°cx)X¾N<p5ùh“ uŒ¹4ÁÑCΩ‡¢ö¨ @)¨úü³ó#Îè¢Ì§¼¼ ‰ï»A3xƒ«Œ"•_ · üÐMùðàJ½ ðt8 æ‡?üáGÿëý¯¼èT»”»óSËù¹S5üòK÷^6aŽÂIò¹×¾ÅÛ{®ðh;Sç¹€¢é»l2_ž‡Ó¯ÎPÍeÒ^‘qê-ÀÈǵ¼pû,€yøµ­ò*cîðD›|m (îÙñßñßõ¿ëõÿêvƒùàìÿOþú¯5œAd` XV®Ç[³{źƒ=÷£jl"Æí~Ûa€`— XøÙ»—eË’ã<Ð(œªÌªÀÇik‘@áFŠb?‡Œ R{¦A›å@ƒ~A™õcÐÐ@Ue]€öïõï³2‰KêˆôÈ\'n7÷GÄ^[ôŽ ²Ôã<~ë*ìÌLƃ?ù 6ÔåQ.e/¿åkàËW9aùm£°6‘£à O®uµMè¸ï~÷»Ùɸ´‰ï5 ÝU–ð÷àkGJŸô¯>ÐGã¤ËÀÒiãìr¡#kËèFêä{·×ùýEõrÀU™rÞË¥LÆì’§;]ò9y•¥u‘©}¸ãÀQç‰>Ûñßõo­ïú_ý¿ú>L¯ýÿ½öÿé‡ócÏ :Ã^ã 1ÜÓ/\#Ì00w¥ã‚úòÐñ•4ޱœ^Ä3àC`œº ~ijc2ivƒ |ðÏ=§É/@¸×OîÊPƒ(ÎEþ‘Iúõòí%á©^eR×䵞– ¹d¥`+7z»]š‚àEûÅå—/Àª¬>íë ô>AÃÉ×oÚï]2¶eïrH#¼rxkÿƒìÀÙ¶ÒÓ¾©¿üZ^Âo?ÒñávüwüwýŸ"]7»þχDý°úõÿÝþÖ¦˜kÿÏ&EíÿÓ÷ÿîǯtE ;6"Ü€Iã„u¦'Àa~Ž…1¯aæ‡C}¥Ÿ£ª³#£~q©-†|xòü«Ø•ç*•çоüðeâÂU„ˆú‡I ¿¶-¯?M ?mŸ6ᣠòÊSØÄ¹·Qž>ΠyñÁ‹ì¼á阱u¤_®~C/Ý#}z3~ÂCó(sÑhKû\}x7ÎWÐ’.? jÊR‚ät øê6½úÑÊ3Æ·^y;þ;þ»þŸwÈwý?ëÜêzÂÏqQ~tÇ—žñÕÿϺ\¿¬þ?vï³ÿOq¬•æ[$Óé‡!ÜÆÏ¥ó¡íÂjYº Ng‚åÕ =fyÙ…ß·ßÔëN‘Ý.<ëjüÉÔt´Þ95R& ÐÀÉz²GY—“Fþ‡›8Z¼Ë¿4ŽÚìI§h¥ ·º;U™ÕM޶íQÏÔç‰î-E¾‰ûÇE!/ÿ¥ÉWOÓZß)CÚg…†Fß Q¾2J÷Eò¸Ôžc×)WƒQžèÈ+_~å·ã¿ã›÷æÎ®ÿÛÏz]zÁÚÙõ¿úõÿ±Oú{WíÿÓŸÏOå >±2À5¾:å˜q›;æÁGLÒŽ«1®ß¼Ò :[~ ø”Á/ßÈ¥d‹3ù6ÛÐy³ø}wFY<ðÄ>ò¤7-Ì& #Ÿã'Mú<“t~Û{žËàÿ6èÑWÒõÛK/Rã8à0oC@Fn€Vy 9¦"iKídšJ ÒR?š¹ôÞöI#o.§‡àôŸ:ÉÝ¿¶­úí`áa—Ð;·TDööºÿéÀÿ]ÿ׺ª×µ´ë”Æü×ÝÅE&tôš|}Æo^iWÿŸ>\ýÿnÙÿì`Y#ˆ`lûª.’.,4Òº„›VßxÆ›«ÎB+š½ó=é³?ÿÔÏYŒŽÜúâL4ø· ,t“^Þ‰ÏÂ*ÂèñA €´<:¼¼aoç‹«·ü*³ôÊFóÇ]*È)½>ê1‹2œ*4í¿îÖé§¶#´¡?eR×Äs풯ʓöM¾rúå”:ÊPy&3Ç~âî¶\áS—¼ÿvGúsÇßìz6¬æˆy×ù+Ü´ú»þþÙõ¿úõÿÁµmï¨ý>Šóõÿ³#ó2~ %{Tí9^ê{ (Õ*V4À@/v‹sw0‚7ƒ¯ŒKÜ|ˆàõç¯êc}4ߎK]óç;ßùNAÀDhуbGéç³£E™q “cCåÑà4hŸFÿâ›úCqþ4^¿gÿiC¢;HÝݺ·§õÛíâÜåf4*këw Ú×N|u]fßá/2TÁô\øeˆÐà]zñ,¶ñ9éw×vV~}ÍÙÑŠÅ™?èKPÑ#Ãä]åFå)KºoAϰ¡«lêA˵]w9\ø%? w¨¦3‰}íxUvuð 'O_ÓÐ6Hk8ªSÛÇ¿ËðkõÍÓv mû¤G>‰#wËñåqóñŸÞ³k9ÿÿLŒ³~Np×?ÝÄu íú¿ôÉõ)võÿ{ù½ºúÿ§µÿoÚÿ÷©T»-þÅ 3ºãj°~t àì§á¸+¯J Ð>€â¹¢•$4 Œä[n/fâÎñ\° LJ—ó§2òëÔu€NSFÜ+x*Êh%úcDi;s§jJæîÒ”J²dçkêAKf®@íW—,ä@+½òå>âÉãš.Ü~à'W;æ)áºG¹[»ïyÍçãçé§iyA$~Wz,½&¾ãŸþÚñ?˼2gº.:7;ßvýïú¯¾Éœ¸ôTõÕêÿÕÿæ‚9bCC˜Îà¤Õî%ÿOÑþwqt!°î€HÓÓ×iö@ì tÉŠy 5…Þ(×Τœ9ïÞÛè |uºÎîñ[Ží®Á‡b7@\ëŽ<3(Þeõ«¯ž¿ÑˆFž§/+Í Nùî(•O¸<å“7¼Ç—ßo=VÆ¡ ƒÊšíÙÁ˧»¡à´)õ¯º\H¿dlÝõ'¯ÇxÊ4¯Î6¼ü´,ã£óŸÓq2zêz t;þéٌӎÿ®ÿ]ÿoêz#}2þꛫÿÍ níÿ¹*?Ä®†˜¾yŸ1al͘ñtÚe΢júÃKOîü™òÂóÓÌñÑx ¦Âÿ2îÒÅ=E±„’^ \Tú·ë—^ç/uÒ›W~¾¨¾:éw~À^ù¤Û¹p½ï‰"_xÍ¥üÊÚ:ø_€ðÚ®æ©ÑN—²yí…~úÉ·36=ò†LåñõäOÂç'ÿü{Oú¸‚,õ„ßÐ s“­iú]|jN?£Ûñ?ǼúhÇߌxÖæPçNç¥ÙõX™K»þwý¯þ^¥«Ç­þ?›)ú„Í«Ýë:yWìÞËÀØúŸ Ba^“$3eþTÁòûÈ‹òΛ‚!ͮȯÏËW}¯;ZÀ¥lJ™v®$ö^(ùÃ84ø Žm˜:&½õHÚÊ›,eÀÓ5@ ­]'O_ŸÐ6·žÊVkóþ­HzúD½á3`-o¶žølc%­Æ)e§¼K±Ú[žo·÷ôæƒù1lÃDù»kyéí¾>*­º¹æKWnÇÿƒôÃŽÿ¬Ïkž™rþvnñûÈÉüÙõ?ýpôTûd׿ÝÑË«ÿWÿ³q—m'íÿ÷¯{>ªô iU¨õï` †»†¼ êÄ B¯c“ ÷ÎÓã(nÌ;Þ”OÊØ!RðnÝÙá†~ðCèÉj •óp•¹~ùv‡¬éü¾4_3cFŽÑ•WùÓžkx5ÂùƒÇÏD€: N½“™²­Ÿ{9õ>.Ó2^‡a.Í]]r¡SŽ\¿Í¥½W¹StÉG2yðàש»ý'­rÖoyøsè¹ÿÿ̹̇]ÿÖÅ®ÿÕÿtæêÿwÓþ?ÿ¡£ªK1š%CìþãZC*­Æ6iÿr@ˆ;<¥Q–éE 9Ãÿ¬ñ!4ÙeB=a2ZGv—ÆxÛéQ W@&\yéâêF«LÝ£MWš²ióÅC¸?%S ¡ ײüÊ&]ûìÂÝÓð!Ç̤kC¾ÍxñÒ¿]ùS(åÔåÁÏ3Räâ?žÓC4xq凾}-ý«kíÅ/¥CdºêrT9uàÜþÜñÞÍÕ¯úƒëÿ]ÿ»þWÿßuÂêÿµÿµÿOŸüÃ_¾b4ÛÜ1Þ5»ÐAßÞ¸î¾Ow òuLù3 4qüL2~^¹0<Áñ:FœŒÖd$¿yügPá“0 w^W ŸNè{X€ ùd­­»åÂß+$†Xíä‘P6éâqénêx¼ uÂ@Šoåiuf7GûK;áןž0@ëÅ‹"heÇSLE©«2ò+whn²[4|•y£ C£\ÛÍ×ròñó¯m*hØñßñÏô2Ÿnn×ÿ®º}õÿùàni¬þû>öŽmYûÿ»íÿÓ~öÓW1º7ÿˆÏdºŸ›\M§Zph ¶ªp.ßp£¨çaÈù5ôÊ •^'Pn´rðWÖSÚ˜?óñä{\0oZa®|òÊ‚‹Fz@È츽?÷à HÐrøZ\Pc×®uW\ùßÛ%]˜áãÛü¶¥å*×Û~xßø‹sÊùÇEΉë?¬¼å‘Ï.Õd=d”OŽðÐ/·¾­<;þg¾êC}µã¿ë×ÿêÿÕÿkÿ¿‰ýÏa.¶Ža˜‘>Æ„‘eT¤ÕXKË¥5 „q¾ŒwACèñ™|®å•s¿©†?;W¡8À uñïÄÇÇ¿»H¥í®6ÒȈÎÓ´úi×E‡ €È÷MC “—O~w¯ÜÁº·ý^:GD^ÊzF˜Óð™Ô×#<ùÞñ%ãߟ“˜¿IW_ë¿óŸÄ¤·>Gš“2ý{|ZûZßWÎÖÞ#i”Á ÿ.ƒ´ÿ3Çvüwýïú?Þ¬…ê§è‘‰sÕôÆêÿÓ«ÿŸßïhŽÜí[ìÒŸýßÂH£ÆŽ}=îò¥[ Ýa¨u#ÍÙÝøzâhä¡—o!qâø?êHê1äÒð­ñ/=^‘ç*/ß·Ñv ø .©ghšFüÐŒï}ZÂêãðç”ñõëÏÛ½ÈÅt€ €˜÷W¤ÒKÏÇ?|<_¼~¾OF¢÷Þ;—ÏC7»^úŒ2–ï­ñ|ydˆ¬Ã“KÚ|szíÑo••ò§=CÛáR.áùC¹ÿX’9îQvxtÚõÿ¼&uSûG¸î¾6wý_ÈJ¡¯ž£ÇëÚgüº¬ÉÕÿéŽ{¿ü¦¾jþêÿ3{ôƒš¿Ïþ?}2w°9Ær ÁF3n˜0Ú&"cÁÜ\»A:=“TÆÐâ!.pAûˆ_y´)Òz: Øt …ñpTG†‚*éw×ôÒD¦i'ìVÚ6q²pÊp­÷k;rÁ Cµ·GzÙøâ's®–Q_w¸¾ºÀ™|åÒ'“g¡÷Ç_¥ûʶ~40ø”G×éøzîY'ú¢ÑމW¦´³qã0 *KhÒŽ¬^Œj<‡Gû$eÜîøŸù¾ã?“gæG×îÿ]ÿôQôíMF¿È .}¶úõÿÌó£6MØüIÚL™wÁþçMî”h ìe€­—ܳ™ÃÐè%›o N: \;¯ Ÿ »ñ¯ùöZiêOBÀc—Ô;õàÑ{>]ÀÒ"ã”U^¥ç—wÀÐrb¨øë@IDATÊ>M˜œ€–¼ÐÉ›GØ‘ 6 ËçøÊJ?œÎQäš<¾|;lùqè—«¼réÓQ2Ì7Ñ÷èñihÜùRîîÔÏ¡õÄMR.ÒôNŸMbArê‹È2ò¤Üðá§o‡ÞWÈ&4/;nŽN¿œòM?e`V÷ŽÿŽ¿9±ëßjØõ_]³úõ?½°öÿ›Ùÿ|‹5†bÇû¡eÆ» ‹ÁvtÆPß ;# ر)øÇKÜCQÇ¡Næ¾äqê<ã2îS×Ýá‡_ýxƒ~*{ 4y=ýÖ£2dâðÆ« C¹¶·€,w¸"Ýš|ô飫¾¶KÿCãѧ&¢~m=@YŽ%¯ºZOõ{ÊŸOž¶ħïôaëB'¶ØÙ\Ýõ"Ri[š8u ìø?úoÇ×?´ëõ?]°úÿ|ˆ_ûÏNþáöÿéGÿøW¯ØØÝéa„™ðÝÀ£±ƒÂÉ+@ã²80áWžaG´ëâûUxS¶u•þ ˜‚ ÐΣ¶Ö“øÅƒ ý92•—ô»«ü||êîô'|Ê•¼é‡‘_ØOú¤/&_9i)?ì„9 ŽSG@ãÈä%ŸÒKP×­óÜ/ûÍrGNm¿úOÝ!Ï“>y ÐRyÿ mwºô_¹Èó(3|:ží´;u:Ûx )=ºÊYvüÓÍúdÇ×?]µëõÿêÿwÛþ?ë¥Ö˜ŠLœ¢ðô¾O |<è¯Ô“54ÚÙv”?Ú¤«Ùý¶©K¼nÇÿù›’¾ÝñÏúÛõîVîú?úiõÿêÿ‡íˆ½Yû¯?Þ¶ÿ7¹×Èò2» 7PT-‹ñO§Cc4ñã_€Ý!>ü&?àa Ö$„¿xêc°”¹¹=2´Le!—úÔÁçä5_¹Ô?é…G5\í#Ã<çMìŽæˆmþK:©`H<  üÆà]É(iÇ%:Ǩx å"ËEp6ùè|º) áE;>Úòú6¸:ýG.¼ÑósiðªG\Ú7É×^`ð‡÷¼ÖÏíøúoÇÇ¿kÊÜàvý?ÈÚõ_½_õÿêÿcqck›Ø£ G—°U£GÞûÿ¾Œªp•)ãûÞÄßÂÓ)óDÁÎqÇscÖO¹¤ÎŸ¡Ÿ„tÞ¡ÝØÙzÚf'Ìý®öGxL]ʨMÙûWúø:MÛFþøóçÁÃÑß{úî€(}T‡oã<ÍŽÿŽÿ·gp»þwý¯þ_ý·«kÿçÛö£a‘?ÊþÿàïòŠÑ­ANxŒô=m2¯±oߌ'î,ö8<{l%Ì¡m}úN‰Ûßɳƒž»Ë'®,W^ÂM3AJÏ·CE°È8£ßäKœvÆy¯•2ùä1u«%ÇdÓ'\×gŸ}ö­>úèÑž¾Ž¢|Ðê/ôp©kÒñoüÊ­ñù£xÒ[ß‘sÚ0y@‘ÇÙäµìyo×)?OÖä£É™¾8U„_Ê¿ÖÕ¾!‹4u¢Ùñßñï¼ì¼Í¼š9²ëÿ¼Žf×ÿêk„[ý¿öÿq‹ÂÌk(q5º‰Ì†¶JUØäh‰)g‡p¨Òq¾Œ{h/>wÞ-£ž#4ÀÀÔ®îÔuŽ´˜&`p>`âªG^~ª‡h“–øÈÊ Ìˆ¼Â½x¯¶úñG 9Ò”Þz(Í´eÊ ‡v@Úן¿Îë^¼|ÐxÉ÷І#ó³QƯmO=×o â]ŬL°ÏÕvq¯\ {û¤ím™ðÞšð¤}§!V.uÌØ¾~ýZóãʯ2íøïøJ\çD"óÇ\1¥ ïúßõ_ý½:s$ºë6GÌ“™0o̥꜔½•1ώ΢ÞutîÔµú?ërúƒ¿úÿ}ûÿd‹ÁöÜ_ŸÄ‚ •+ø¨o·Ã@[8vU8»V]$³2òMBùÊð]´V¦ &e®E…^@R䚸2©chªàÕåHÏLº‹îììœ$VæÊ×EÝúÔ£¼|Oêv¢S'‡Gùó#´dÿÞp&ÍÎЇ³£åøÏ£>¨lÊáS¾Ž sd8åÔ(¶>uêƒ:eº; Œ×ü MÂC¨¬°üÒ4MzÛÉçR×°O¹ISãŽÿùÕ}ØñØñ?s¤kÉœ®¿ë×õëêÿÕÿìËÚÿgûÿô£ÿòï_Ã|v<üœ ÀàS‰N¾™îô@’ËÞM£t%‹m < }Ÿ|ñ)O| V„û4ŒwÉpvq¼ý<Š~èä¹/Ð1qòsœ7aå"ËEL”~’žep£¡~ñ¦u—¬MŽšy¾0¥?È÷ùµ{¥_ȧlêTá8»\ø¶O¤á÷¶\­«éACøWò-wÄêÚÿüö#:Õ]CI@÷ÛÒÿÃ+g̳vüwüwýïú_ý}½NIª“Wÿÿ:öníÿ7³ÿOþŸ~øŠ±v´äÂu .CLÑŠ›T&`Qða‡J9t¥•Wã~7ðxËK=3aqüJ tÏFzéê^úIYÞ¯˜8‡>ÆaÒ¸Sß3Q¶éòú´>íÖöâuoGÛ‡>@nhõϽþŸ~úé·>þøãôiûÏÿÏ>=÷¶\nÇ·e1;†Ú¨~®²Þûˆô•õ.Cû6ßú£-\Ú1u”oꙺ*ûŽÿó.ãŽÿ™»þwýWÑ«ÿ}»ëÞêðÚ ºvõÿ›ðßeûÿÞÿõÿüß37F¡:’{ë"·tˆ·Kcâˆ3ÖÒL´ìÍ }¥—.Æ}âÊx,ÔûN–IY§ÎºòväÆ,PüèÄ ‚Z—]¥É pð)Ç^á`=¾OgwdpvãðÁ»íé1¤4|ÈOveÚgÊIWxB‡þ»óMC¾>‹œ¤L6å¾xýEø(×v’A\Ý$¬,xxMm@¯y÷òè8e{ÌëžyK—òÃc<Ú–GÙ« ;þçZ¿ê·ÿ]ÿ»þWÿ¯þ_û_›ù»ìÿÓ¿ûÛO^1ÆÀ cÊ9?†þ Òühð‡/?Œ±Ï« †¾F°²Kƒ—Wpx0¼"@t65üÊÔø7aÃGH¹@­²| f °ôæiPYæR|ÜÐPò§ŽÒ¶ÞI ‹?aõ’ƒ#?à…¶—åÕ\¢Ò=äÓùŽG•!Ó6UæÕ âx¶]dÏé/N^ »ôÉLº?©cüæKæB;¾ö’‰ìm£:nè Pյ㽯Míøgþt¾ìúßõ¿úõÿQç×M¼2iíÿ±Õ¿Íþç§rßìš\<ßÌ›4†š‚õ‰­³ÑW€ƒðãyXm@âÙØ¡«1GÊøˆËçÔW¥.­/:í1!š‚§ x u¼»?A•ÊÏ…òƒ””<àC9uØêÑ£x깚_¥œ:É\½:ëëÇ‚¹vñ×vŽg]Ú5Ǥʼ?ß$ÄÃ8u4ŽÎÓqÞpû®iâžÊ®~å¥nù­Ý´W=èvüÏüØñßõßuÖu_ߺ²Æêïú§9Ž[ýéÕÿ±}Öµò.Úÿ§Ï%w ß $’ßöëJ¹|FÙ;Ÿ%/pÕ@#¡t,*à‚“ÇÙÉ¢€¸vrÿž¢·þ”û%nuO±€y ý*`ŒðÅ?¼}âöN«À½‰K#¿ Ã{¤±´‘çÊǽ<éÂø+¯^ñìš]m³se·Hýè)܃ªOýüç?ϱ¡<èß®Ÿ>êκ´´óLJ°³ ñ­îI;ÈSùÛ6;gÒ8<É#¯¾¶qhퟰ=»ÿ3?vü3EòÇÚõ¿ëõÿêÿµÿ˜ýï¿ýÿþë)ãj7'ˆ˜‡‘a„ 8ÓübÞLþzîMƒN^­ƒ>wŽÈNÍ 4wþÀrÕG‘£©C«þÈ2‰@ š»\Âw@„üÊP´,ž#ËK>`ÅΗW,\ÇŒêàøý” ¨Ô©WzûCé“!(?q.ò^õLŸÚq]dÿð£óþ,²ÕUnquÜûª#Ìïî£#NÑÚí°£Ä°×PÇ(M™:0qïÈ·Ñ•'¼<J¹çG'^ÀÂÇ—S6cÂɿʓώ‘|üRfx¤¾‹×³“3üìµÎò'/ùÓ¾ÔxêÄ“;ï¬:[Àd² Fž´ÁU¿x€Ï•™/ìø«²ú1iSD½‘sÊ}m·ôÒÔÇS:PD&叿ËSžüÂCthF|eз-|å¤9^å7¾ã?À==»ão^ìúßõ¿úõÿÚ¶þ›ÛÿÜÁbGjt…)T®ÆÚ®ƒÝ4>…+M¹ã¡›Âbc5ڼ횈£÷4Y¼×}$4xñåì¾ ®€¯,Þ“F™¦MÂ@‰Ó-.hIÎäÛщ¼òo<È!Ž—£¾ŽÿPWze<âd#§2u­G¹ì¤Í· É©“,Êf÷Iý³û×—‘âpÿvfùà}ßûX§ sTxÉPZy\øNœ¼ºÊ¼ã¿ãoݘ›ÖgNpæš4óf×ÿÑ»þWÿ¯þ_ûO'Öþ?}ÿg?}Å3ª&ŸR­²à((¤°|Á‘€ñùëÏYè(\`)†Êy?Õ‡~˜21àCsœŸ ° ŠZ9;^Ÿ†×ÁýÖŠúÈ@–‰Wõ‰smÚÄó÷ò{bF ð”ñs1@X~iÏ%{Úqqn½‘ý’‚#áò¿ÄH<é“ mÓ¦¼¬”l#Gû[žcÅàìàÏ•oe¿‡ÑDæIŠÒíó¨0¼·;;ƒWËG½Â}*ÏŽÿôá5tìŽÿ®kc×ÿêó€nˆÎ¼> ¯þ·ív°L†–áíDaLk@º«ƒ® Å—ûA³ ã¨lfSvc”µC¤\Wˆý™z ,¼§Ší ÔûÞ÷¾—I‰ŸK㌽üÊ€p&¯tüš¾$5™“Α7¼¯‰X‰ãáS¹ú¼uÝ7$éÊ:æT!ÅvÂyþœ*"W“Ðdgj€¢~IŸ4óòÕÿpC?¥Ní(ugL¿èk€¯î²“Ùš9¾ú¼éU)I»‘œ´ù‹®å+÷ŽÿŽÿ®ÿóášØõÿ|4¬?<«ÿ/mºú?±öÿüÚΨµQTûŸ7¹ŽïŽbï¸:ïoêý Ðt Ýs´æÌ;áüÆÄïO*½þàÿé/ S0aA{Z¶ôBçÛxÏÇrÝ¡)]DwmOž×9œ{L•/nv‹^Ïn’l&¯]¥¸iÔìW¼±ëÖ6adk=¡Ÿ´ö]Ž!§¯¼`4€fòî® §ýŒ^½™¸Ch°ÐÈ/-‡ ¤µ?ñ-PÖÆ‡KiÄ$e„òWŸhâÁ¥?vüwüosx×ÿ®ÿÕÿ«ÿ×þŸS vó›ÚÿüáÄ—¡(€‘/¿˜ßôãþÑõ9ò£l{ïHEÂw  bøïòfÖíÖH/8’$ŽO€Â”; æÜë`ìÑrå‰?0„èÀ¿Í·tï™* Ðâ‚~hð(ïm¬îAi[侎>Ë‹läÈøàÓúäy¸»«-Ú9ÄúöAËñÉß¶“ŸÖéÈðÃÜ éÊ·®süxŽ?ñi¹´Q_\ôáMni‘å€Pa4ãëUù&¯»n;þÏßÚñßõ¿ëõt)¥{¹êdÑÕÿÏ›1µÕkÿg£åûÿ“W& ƒÌÙyájx¨×sT§³úv^vSæ‹€rÈ/ o†}Üù{“`¼t&lKà ÂK~ëƳu¿þâõãu˜=6u.O€(ˆyŒÉ¸¦²ÐQÆt yÄñ°8²Hçê'">ÿ(ä¤ãyшûQe®üùåÕ¶©°mÿ¡8œ:íLu¬¤ë mÊ„ O%™RädÍßÉïTFr•çŽÿ›ã£KõÏŽÿ®ÿ]ÿ«ÿWÿ¯ýgj³køuwûÿ °²‹2; ìàÄð 2< áÜpÜk²£tOW T/€C#ÏÐÏ£l“¸‡cð,usÊ¡è ò¤QzdSŸy “,à†_ÛÜ ?¼Üort'_9Y¤7øµm U¶v ¸ü¦¹ÂL0•ðU62\è[¦a¾vh7¿íR¯ð½ÿÚž‡¼“Ï)ÇÄ‘ 0 ÀKú„®ö·^¼<ŽZ#ïŽÿŽÿ®ÿ]ÿôÑêÿÕÿc7ض¥¶‚Ï&­ýÿöß=׸ëDᇛðý%š@L 3ÚÒKËÎÕt¼ð—RpA&`fDø¦Ä9Æ»’¦t<ÅS÷ì 0Ö ê¥Q'".ÜŸøyá>Õðh¾º…©‚š/_ä1y“€vÕMéhÉèéidñà'OÀ¦=E5ßš”ž ìx^åB7ñ¨{{ކ®ý§½\å5ñ9}JŽ~ºÊ.ÜðìnThæ"Hœœí'}¥|xLøá&¼ãæž>Ñ?;þçÃÁ}¾˜?»þwýWG¯þ_ý¿öÿØÿüØs *EÙGZà t»!Ò î¤]é1þÈ#®tÀGÓ¨†V\™– ó¹¤Ï…óœã@_r W'ßS.¬OÙò–ι7æ'}|»PSÙFò’1m˜ºÕ4åq)ò@N껀”;rIç𠃶ýʽ.‰—,ÃøÚ!:;H}ã<þ!ËßóG]mƒýWÅ¥Žö§´|ÃðtÙeÔ}zácC+åÁ—\ó~ÚP׺K×øŽÿŽ¿u‘ub&ÍÜé<yÐÉ÷ ÂС @š´‡lÞÐ>quÔá¡,yRÇdè éâèåÇ O®rhoä¼èr&ßNÚ{Ã#}4}ëµûÀΩ‡g§Ç„\Ë+'sÜè°ñ´19Ïcˆ¾é©ç*‹¬é;þ‚wüwýïúö ™¾Ýñßõ¿ëõÿêÿµÿ¬ýÏ{°`“è¾{Ó°c$'FgŒ6£\½qôw•GSã. y²4u0øšÁÀwêŸ:¦®ÆÑ¶œw?‰÷Û}€[A°á7 û)Ày¯p.‹kß<­S=øÙ¹(0›Jòi#^dó‚ßNþ••<\dŸlÜyÇÖy§Wê¾ä‘§|ޏº9tžºö›Üðo;.zåPŸÒÏå[_û¡|O_Ÿ:Ú¶GZ8šwüwüÍ„]ÿ»þéè‘™«ÿWÿ¯ýÿæöÿés‹ñí"ªaftà£@@^·ÈìPŒþ݈+ÇÕhüñÇåoÇ;bÜ,]€A¹òö{t¯?8™^À¥«œAÿàÅ\8´A®>€P9/p2ë³+7¼¸ŠIwKý}AiûFy N>P5iíihs™~üäŸÄô_ë—D~®@ìÔÑ1 ¼Z7:a®í ¿Q|ü>ò!íº„ñ‘pK/Ey¶}-ŒŸ>Øñ? ¿ó{Ç×ÿ®ÿsEbõÿØÕÿ±ÕlGm7_ü]·ÿ¹ä^­C¸Z>…ÒÝ“d΋ëÞ™Ò (ð ¿Û7qƽu íË2 ‚ODx©ËÃñ¢ð™ò⎱ ô”« è+ ŸäȃÎc!¤üd’qèÔgëPÏ‹kçª@Mù¶ ˆSNZÚùv¶\ŒNxò´©à$õ§ÊÓ/䪌dj¿‹\ê:Áã㉎¬h[^Zä˜ãÛþ,Ni+³£Ýóž/Ç“s4Jî)‡s˪¯ž\ùðwüwüÍ—ÎKó£k¯s[Zç1º]ÿ»þWÿŸÍ‰®‘®‹êokfõÿŸ¾ýúÁ¼É!í€ókÈ›,Ü'ú¡Éã(U–Û„’Ö]€¤åå}ñú¼ Ô„³ûó óJ\Z>)@Aä02»^äÿÉ“n'KÅŒ@vÈ3¼{_‰l`C^¾9”´††<Þ“Å÷HSw}mPWâÃÃëÈ€xi?|}½cªåôMœ:æ‰Á¿rËk9ö”t<”!úIx"ùꬼx”Nú“ÓGœ´ŒÓpðÕ`ý3ìßÉwü£><9ü¸ÿ3vü¯y:óp×ÿ®ÿ~0¬Þ£;¢£Fg¬þ¶«ÿ×þÇZ1—ÜEbØ`b ­ÿcpûXT]Lèß6Ê¥ƒð*MAE™ûKîo(:ú–oY ãÔqdîAg¦ôÚ ihš¯|ùE¢#VÒ|Â:Àæ€+÷±‘ÖÁ'{A‹¢áE†´ÎqàUöúù ˆ¢Q®|„ÉQУ¨¼Òñ ˜Âvþœ6ÎΕo¶M¼4ò ¨„[‡°2õÑËó-K_HЗâ˜á™¾›Vèÿ–“o'.<3ø;þ;þÏëÌÖugm¾9ï2—L3sm\ËHßõ>ôèý³ëõ¿õTÝN¯×Y/ìãêüÿÛÿOþñ¯^Ýlx¨BDÆGI¢5jħùoìÀ0â,™(£˜ùèÝ‘’3ßÖÊÛŸ§Âõ¡©‹‚%”ºFqG\€‚´< Ä=Ò¸ò*;DÜ9Æ;»_‘oxq96›òäKüÂåWøMZ}ùM¯ø š¶ÝïfIïBBÛ0™íÔµŸ[Ÿôö¿4ùI>ü/¿:wßðܤ•Úxç¥G´ï.kú?iÚo,ÿõý.ô­?eÑF²r¨[[vüÏÜÐ;þ3[výïú¿tNôÒ¥›é‹ÕÿÏ× è ý³úÿÙf³5]:Ž­ù7nÿs‹RŒ›Fi@C<áîñÛ`½ÉáÉNÐÕ ÝÂ.|¦ƒï à¸*·à¸‡•þð.ä胾»S , î’«_µ'Ÿû"x ;Nt,¹G¶¶òÍÚ~ü•Çë%&N6ÀB_Dq ðt†°¨S ‘fg+ùWŸ¹¯¥\ûáÞöî6‘Å£ß}šùðåyÙªö÷˜ÒOûèW|Ü»÷EÂC+/|t6O_¤o?á$L\]‘eÇÿ1ÿõÇŽÿÌý0ói×ÿ®ÿêYóaõÿ¹†±úÖÛ \¶†îd<ïªý?ïÁº +%jǃ¶x€ÆIPìl)hâb}8˜Äô«sM;þ»þ´vý[%³6<ógtÇêÿcÃVÿŸùÀ6½ëö?—ÜcD²N¬–ã4fá褫14Œ°«±WŽÑ‰áZùYo“–wåãU#Žhó÷žûæó¹ÊÓ2ñçÎTA|rÝóÕ0ÒKƒŸ8þL>š‹è$ yd$¿õ k^ÞÍåH.`eÄ–_ù•)½ÅöÕ—ކoÛ©ñÊîÚøœº<œþÑ|ЪƒŸü¡ïOuµ>4ýf߈lø {¸SëIS–k^ÃâdØñ¿vþ¦¿;F;þgÎé¹bNïú?_"ézÜõÿ<7ª?Wÿ¯þWìÿã5 €ÉCI^F€ˆòt1p™w#«|ý±xâ¦lù4- kÒíÚ BÓñâC?…ïåÔ«œë«JSPQ0ƒÚæó¡ˆ¼ž`êAç ÍÔE;Aê¸@Šzš†Æù¸8÷¨gÂ‘éºØ.ŒžÞS¯2@(_›ï //_âÜ¥"¤ž#ºÊˆŽÃ[ߤ‘ÒðE«Íèµµí®bG# ]ÚnGö¶9_4¨Üjú¶ùŽÿŽæÑ®ÿ]ÿ«ÿz”Žì«†„Wÿ»s³Eú†ã»Úò.Úÿ÷)Ðc”gÇäýjÔŸLžytLŽÚ¦¿ìŽØyAÃ@3§ᯑn§Ú¹Ñ¹ éä9j|zïìþ¿ Ã)['œ£Äð?5H»Ótr+C²p¢îI?·½.çÛƒ×ÎÚòüò$x8r“/÷€F\»ä€vÃÈÀTù§ÑÝù ã”y´G~¨ÏŸÒG–Áx¼<¯~(¯ŽÛ]¾WV9:@ñý«ÿÏØ‚u|ö½^údÇÿŒçŽÿõ»þwý¯þ_ý¿öÿ·ÿO?œoL5*@P¡w‡§Æ:gì ÷äÛúž5¹$4’Î4 Æ¿eñC3Á€³1ê@ˆ»I@Aéщ3ò *äqäã·ð ÿëþØ„,|ÃÛ±Þ´«»UÊà)¯ ¤´©ß.Ñ8áÒUt•GGž‚OiÙ©»xË/}ù‰U9Î3‘ëôavÐF~rrŽ¥Ô‹|<œ4ü€ÒÊÓz¾= ²àÖµŽSåÙñßñïœÙõÿ¼“kýq]GÖž~òìú_ý_ýÙµ³úíÿÛöÿé'ÿôׯü–ŸÉQ@c—ƒRA HIg ¥éBF\^%Dá8[õ$šÝœ¤M).”Qx)‡Ww¨ºóc¢t }h€IâÈá…ž˜áËñÉÖÇ]!—PÅñÂá1ÑGÙ–“ÉW/?å´cÂx=3´ú!òN˜Œ•—¯^ý•û9ãŠX=é»)#-m"Î%?p¤lét²w  Á8Ù%ÓûêÌ.ÔäuL” à%ÓðÁ·iè}ë°²}5¯æÈ¨/“¾ã¿ã¿ë?ëf×ÿى׫ÿWÿ¯ý?9›5ñ‡Úÿ§Ÿü׿~ÅÐR@É0²À.Æ`ó-6>«t÷ˆ®AN.lpÀ ºc|áÑôp€"¾äÖ÷dÐÆ!L¸»wƈ껱ðQåvïJ¸ý¼ã?à{Ç×VÙ¿þ³ëõõ½ÙQ=J§ÒÍâ«ÿ¯u3¶§}µöÿõ·æ¬î[ßúìÓÏ2I¼YÐê$bÄcÜǧd<™\SHºŽ¬¡ï.JAŠ<. m&à =`LÜ'g?^ø{ZŸ¼ð¹P–óVóbhÔ§Êf7lÒ[¾²ã…6Ò]òOËR‡t÷.Çý­Þo^}hÊC<}ôQêÖwÚÆ‘Cº£Q  o ªm‹ O“æÚxÚÊ§ßÆ÷³Bíké‘Ñ¢¾Â6 $yÕ„cWr—–Ÿ1ä_—ñõÇ—¶ã¿ão^îúßõ¿úõ?ÛP[ÛqÙÔÚPÖ³6iíÿï¶ÿOþŸ~øJ‡2î:±g´9»#wöòJ®—¨Û±`9‚:w®f„r|g „ñVG€ÓŽ«N4â|ü„»3•òSoRi!$upL òDvnÒiê@ã¾ó)¯\üžrʨ7°wuÍ¥x0ŒÃë„ÒüÈì]ZêоÖþC­¯¸ôÁ€,ù\Žç&Ü÷VU¶äMºòžò,˜o½xy2fãç~ÕÈTE‰—1ò€¹!> xÒÉ…?‡_úlÇÇ׎Øwý¯þ_ý¿öŸ}ücíÿœRËÓ m .s<á¼ü³c€}²r5»vwzü–]ïÉ£,6ØÁJÀÃŒ %å¸ (`À_|0;d9Õ:õI«‘×®€âÄηÑÍk¼@ìKGgCƒßXÈy Ä”©óL lqö's´?nÊjWÁZ °ÔVíÀß±dëV½rŽûøœß o}dîó­©2<|õ·•Ó6®å&ð=èßv½o†~¤Ê®°‡Ö¸h¼8ùÑØmã^ÎN¹»ƒ2*³ã¿ão™ »þwý½úõÿ肵ÿ¼ýÏOåÔx(ÀÀâ¤'pŒ~ïì×q”øïŸ×0ÜâŒ>`c·@ I„í€aP0q>ºúd€û“îÜ +-^wz̽”“ë¥í¹Ú4‘ÞçÒVrªËÃe7ëV`™oY~qî„ZSÓéÊ0•·ßŒ¬Ì@“|r ßòŸ™òÚF²ôΕ°öÚ•B£\i'# ÊÏéèW.}8»„Ê“MïæûiÊ-¯é;þÏ;úyÇfF–ïY¿û®ÿóíá]ÿ«ÿWÿ¯ý¯­ûì fµÿOŸÌ{°Xf[¡ J2†€qá½vAi÷¾÷½ï%½à¤†;Æ{ÊOfŒ¿»Lò(dyÞ·›$Ô1ñèã_»DÍs—IÝd÷ ¿>á?àã©¡‘‹<ãÈÞöð•“ŸvO[9e .&3rðÑ‘©ã*‡ß:§Ä9²ãÏáõ¨gâ8*¹†?á_~úËô½Ý/ÀT9év8á¶S_ +Ëi8çÎVÓ[†ùJ'“Þ±Þñßñßõ¿ëŸŽ¨N¨¾¤Ôè:dõÿóNÿêÿ³9Áž°;±=lÑÄõÍÚÿcÿŸ~ü_þý+÷s, ÓI ÷€†x:Ì¢Óa\»'€Q/^ë\»*Œµ²hùÀ„¼/f×ÇöâýeŸŒ{½r¯‡ħ\&íeüÑuðÔí(-4®ëå·ñÀEb.É<áÈ@;i¼Ê/´“ÀrÕ‹7y†è±ó…ÞnZÒGFåðWÓ¯¯»YÂm×0‡_évÍìná™~š#<|õ߯Ï7Ãð ®2£IçáI¯S‡“_çn–<íjûê7È›Ûñ?;‡;þ3Ofê˜Ë»þÎØõ¿úõÿÚÿÚÓ?Ôþ?ýx^4ZÎ÷n†€Ïù&ÝäùWp OýÓO?c²sSÃN9ÇØO ‚7ùåÁ¸›¸ò¹ø.È…²aŠÐPë7æÈ¨[ZÁ‹¼N¬c¸ìü®{Hxª ]Â7¿à¡üÔã[‚‡ïáSþwð’…0òZÂòø§ÜÙ¡ÆOzêŸìh¥À‘ ]]€çÐrÒÃ[ËÈ?OÛÔ#Oix‡þ*°¤º`ªPŠGeAžõ'¯m¹çÝÕ¾ã(†îF`u@ØŽÿŽçÚ®ÿ]ÿ«ÿWÿ×~­ýéü£íÿÓ'?ûé+,*ryü|#NÜc—É…k`¬maFÜô €Ø ´Ñ à(('ìr5bÇÆÅu@ãx*zõÉþðå‡ç==S^¼ùê©¡p‰»ßŒRÇ=çHǯLÀžp@àÈÂáK~Ú0ihZF]ÉŸô‚)åŽ;€+u]˜Œ J¶Såé¿Ï?û,éî™É7©³«8mÈ¿I«KÝW¤üÊSrÃdžHx¥Íâó(//m›vWNúùòÀs<´;þ;þ»þwý¯þާ=ôìêÿµÿ¿Ïþ?ýh¾E ;]È0 ¨äÇØ^†Y¼».€BŸo<îñþÚòÿÅ/~€‚‡]­‚8ul<ø“ °KŽ·F6å Š„¸&ý€º0ÈœºäØ+ˆk9÷ÉZÛÒö)gÇîü'Åé¿{?4-™þŒ=jÅO›|#ó;ßùNúþ—¿üe@‘·±“íÛ®rH×Nõ©`#[óÉ÷ö·3¥ÙÅâž2èëvüˆ×æÈŽÿù@¥?Ì“Î}ñ]ÿ»þé®:/ºè²}=4ÖÒêÿé¨ÕÿÑ!ï’ýúá?üå+Ê3¿Áw ¢Æš·€t‹ê®lå‹çhëx–rK³•ùp~™ï¢9?üoONÙ¼™|Âè8»êmâ™ú²_Ö*:šÏ»†øèãÿÿ¬Ç]ÿ×rÜõ¿úÿÌêZƒî]ýÿüe4}Òþ©]gþ­Úÿ¼hT£jL ª¡žYpŒüøµ¯1ÖâãÐ2Ä kÃø ÛaA%nwFDYNZ'—O?wg·É1?òà=åÔQùâ/g' /N\ØŽŒúÝÅÊOÛ p"{ê9zÄ!˜`òCÉ×±œ²d³3U¾¤&ûtL8u\í áõ§m$»Gœ¯~áÊ[Þêê¥yõäµ.UÌòLYmäš—Èœ^MìJ:)ê{û)ù9òà×¾•®2Oá‡Ü;þ;þæKç“°¹bî˜/ ›O»þwýÓBæÃêÿÕÿïšýúÁuɤ9aÎ1\.Š 3´ã’Ç`O¸J´ÀH²…NÙúôú(蔿@£ÍYtxB¨¹w¥ÜUž±Ç瀶Ê?ò¬lŽ¥á÷ßJ?Lj×+ÈÚvá÷8NÐUùå\ù7aN9|ôü|*ùêFmš«žðºöeËU÷#!ºñ×nN{¹GÙáÍ@__Î[ñ!zm—ïŸì\¤žõ“8jô'G®»/½õ–æ1~Cø¨Gù«<*ƒðŽÿY÷¾Üñ?GÓoµÕy¸ë?zÏZÜõ?_rZýÿÐÃlËêÿÛöÿqÉýnjx›=€ÈØUƒ#|ç)ð'̨عÀHùÇxr=†çÆ›qVV9çÒ=5P|÷°ú2êÎ(%áîxY ~¢§ß}o*‹LÚÅQ^MpxÎeù)Óz´14@Ä<€Œ]ùd‹üC N2> ¾W» F’?iz.<'Ì/¯d\*Gò†Æ»ÁÊ/`sØùö¥±ÑÏå£×øÅîQÇ=¿yü»\ K;þ;þ×¼…ÜwýïúޏtÍêÿÕÿlÒÚÿcãÙ^v³öšÿä=X5¨|‰5ÆÙ™ÀJ 3ã@“…æA+Æ„bœ•®ôîØË£Ã» «B~ÁMd¦ýá°#wÎl'þþ€¢:zeÛ.q`O»^ýC4¥»‡«€Çwî`ᣠííî.žò=Âm+š^ÒOø–×¶ñ¹/à/túèF‹o]eèšÄô˕ٮ°ôæUž–Eòvyu”~Çú{Ç×?³ë?zaõÿêÿµÿßÜþçMî *P@ÃðZHC+aà1‰I/­4a†ÙQ—rÒƒò-¸Â£<ù€Š) Ù‘á*Œ?z¾ûI|õ@LzÀÀÔ8ÍM@É}ª‰ÛûlÞ/u(xãç±óåÁ³ÀƒÅK~ÓȆ0ØòmyÓ'A• hœvM=9î¼êk[‡uøºV¹¼NÓ“†gÜE«êU–‹,øN:ù+“<õTnm˜†$n«¹y¹óvÑ*“>:|<ò“ˆ.—¶­ôÒJÆgÇ߇†s¢kÄÜØõtÝ®ÿgBϘ#æÇêÿ£`õÇíþÿ“°ÿO?úÇ¿zePkXJÎ×ø“¿Ža•Æ·[å˜ ˜° Є~îDY4hB7 ‰+¾ô\ ÿë¹³õòÅË”¢ÐQÐîÿÔ= øÜ­ê‘`ø™„E긇çðÅ/ÎOûŒ<wžŽ §‡áøD¶éƒˆ ¼©S?ØùŠÁ˜¶û$ÄÉ}úí˜á“v /a0Þí‚-ùèË“_Z>ÂäÖç +_¾¥k›‡ôÑ3Ƭ´Æ ‹ºòœvìøïøïúŸ²ë?*#:gõÿ¹ûºúímõï²ÿOÿûß~òŠ"©S¨Æ±-¸¤l Ê€ ¾'ÆhŒ5ƒíå–WCŸ{\—1ïQàdp2tÙU‘?¼ñ ˆà£~ûU2C+¿u“E<2:êXÐ!Œö‡^šGm 9ñQî&˜iꟶq½„®LÊɲëÇ£”O:T“¶è»i‡Ýª|»qhÛ†/®2m4 í3ùéÇ¡m?´½ø†ÒÑë_€´÷²´…¬å¥‡^؃Þ].}Gæºæ+‹žüüÿ3Owüwý[+»þWÿßuæêÿµÿÇúûPv9öÿ“øé+;?5¨²jdcˆÇ¸2Âv´ntÐ"ÔÐ K+ ?îküÜ*XJ¾¡7`A¹ÖÀ5[_ëWöÓO?ýÖG}”]¤)”rŽÌ䓵ô^“öbvzð–OÖ 2ñ¨‚³o{C<~S×KÙ€)_´+ müÀ“á”=:wÒÛ¯]¾‚;íÖwÆÔCž€$`çÊã«ëîÄ¥RäáÎã¡ÕÆ€ËI¿¿HúÚ¿á­ÏÛ¾]ôç;þgMu¾˜Ÿ»þçÃÆ®ÿÕÿ3j¿Vÿ¯ýgï—ý?¿ExÜC±Ö‰vX„ Püˆ2ÔΠ£÷XÄØ_@¡ÀJ^~S0 $ÀaòÊ‹oÛóÆrpeVwêóÓ2¯Gy.¹¨ 0”m;Èë(P@QÙ P¤£ç Bº€´Oïá¥ÄïÂR–“ÆUöħ¨6o.Ççço†Ÿž‘5¨5Öh(Ü^(ÿøãó¶ußÎóÖõ;/áwá¾]šz2‰&¨‘ß´Œ€;íú·3~v´wý¯þŸEÝI§®þ_ûïËw¿Ëþg+ŠãR¨>5˜D&§;85Ìô|ìxÞÝ$î\¼ÿ,(ë‚ å)î:lʳyÙ!:e<êîN](õàÄ9ôÛ}vˆ\jÇ#è¾™8qåb¦ §vi>ž.š7ä¼@9€å¹â‡ç¼$tÚ9ç[Œ|qŽ,~Àz.@gÒãO½>{=m!‹¸Ý¹þN"‘‘’Ç@]7Y%¥ß&wF,åK'=ùÃ3a}2ÿ ¨Nî”'ó8ã²ãÍŸôÈ(ÿÌ)ëÜ5:—LHóÕ¼1Gåïúßõï¸ùpwÑ‹“`î¬þ_ýß¹ÁU§tnü)Ùÿ§ïÿl~‹i®1ÖrJt¼.‹…Ñw,X,¶|ëZ}øC@é ß°á>ƒç^V¸ñò® v(y@ ¯ø“FrÅ#Cw´Ì#0|#Ïäùç®gÇH##~Ö½(® ¨òà믡AwOç¤áÝö%¦díä¿|9 p^†*\uòu|wϤ?ÚwàÙ6·‹×zÛ®‚.rg|FÖìâÍ®¾½¸¿ìâÍ‘cþ mêËŸÿÿ3Mót×ÿ®ÿÕÿ«ÿéE6gíÿ±—µÃÅ ô¥´‡ýÿÁüسÄ:„¹{4 %Ô©”¬§÷‰D¦i 5Çh÷¸ h¬zŽõ€ª«¡)¨NÞËq©Ò*8žêÔŸŒ^æXëWG–‰«ƒ,Žò^ÌëðrNû#>QøŒ/þíÉ RÿðW'ÐòÑF¦IãÈ(OZúd|í.š¦óqõ¡½“+éxL¸¬ÓG€2GpåMvOøÖC6émŒÌï{tÒÈŒü~¤:á…_먼I˜?);tœ<eÇÇ×ÿ®ÿÕÿ«ÿ×þMüìÿ|‹ð/_1¤Œ®‚#Û'ˆÑžtᱺT \ ®ì5fC >>Œüììð9Ï„[š\u([0’ݘ TAd½UŽ °9ÖI¹)_@˜09œ™â¢î©‹Ìú ù—ùn}"þþs)~þ•OmiâÙ¹¡[]h±;…t`)Ÿ&YÜšd0FjžÂ;þ;þ™S&Ï®ÿ]ÿôݵú>ž\ýæ[Â^°7l?¶é²ÿX5¦€ŠN(Ð*8 ¹:JŸñ|(KÉz‚—†ú”dñåáÁá+#­ì$ä±[–©y »4e;0apñ¨¬ÒJCŽ Þ b^7yê)`Ê'¯ ˜HHãºÃƒEÁϽ®iy#ÿÕÆ–Q/>ú¶±“(àé’_Ÿúù&­—†Õ5 È?<ìfÙÉÒï>1 “þv{¥ ã”確|idÞ€"i±äíNúäqü<;þ;þ»þwýÓ9ãèµèíÑ%|·úõæ;3¶cíÿÁ8l¯5r·ÿXY55²—Ñ= é€FÞîQêr{ŒºÎŰÀÃ¥ò—Î;§æ"¯À`ˆbü'ì æ0hòL¸<•µœÅ9~ÃI¸þá3þT˜Te»ë’„aA¦Þß’O¾#€ªqò)ë¾™”A']9.ü'._˜\m—4ñ¶ÍnÞò›×+‘ßC”?OÛÇ×j·4õOZyè| Ì”i¥®‰£ÃÏÓø$&>iWš[¬;þ;þ»þwý¯þ_ýÏb¬ý?›Pìëï³ÿù©™±în£« “·w°g —Ä O-ÐÀ(3üÊã+½Â(Lzëă«ŸÈ—Öôúò+[Âþ ]Þº>¬>xÞÏ5õ‰[vÕ¼’@º»PÕÝáGf>§½ý”Vð¨þ€áË+m›8z`H•›_žM×?“˜þ)xùõu܉&èw|¼ä·?/J~êV¿¿ó_.ùI?»ƒÉŸ¸ãX„ÝŒld¼êïXìøïøÏd‰ë3¿výŸõµëÿ¬:cõÿêó`íÿ±¿¿Íþan±¨@IDAT`es«#-ÇS5ÈvJì6ùôÂQ¼ ²»Hî ‰Û…ábÌ/fè ú­µ‚ Àè)øHáùcÀ8þƒ6)Ïy¢UþG¶ô¤Ç (ɱÜðÀÇ. 64}üQÞNÚS則Gšz¤£Í%t@eâxy3;þ©ch‡ø'Ke|1ßœ¬”Á½¥Vq`Ø8ÊK}òÕ­K}ã1ñKtè%éÃ(ÝZ¾òÕÇéÕÊÿJ“zËíøïøïúßõ¿úõ?[±öÿÎþç·†x:4ÖX·^?Çò\q¯¡·Ûâ5î:lZt(Xè]Ÿ‚ voqÚSçd ×sÙûľû@Ç08|&ØOÙ.³“)ü'½ï“"@âÈΛàýÜùÕ'/;KxŽÓ=zk¼@Ë[ãÉ\~iëЫü•©}J–öK˜ã½[é^¯úÃcò¥ë”ì¤] L=S¡ 2ªG9íàÒŸ ‡WÊN~ùë;»Uú¯Êa³ã¿ã>Híú?ú`×ÿù ·úõÿÚÿonÿŸ¼¦®¶ÒQ€Œ¹‹|Œ7:Ûa 4Ãì évujÈb&½q¶>i0Sž¡÷ÜÃwãáƒxò…‡ 8À!/YµÁN Ë3r‡f|o'×#xûÔ&~þM{'îVÛúÉ­Ü•¥²¥ì%gùVææ1ÜdÐwòô#ÜtõpÊÈG+mH²k(cEí”8Ž8U6~Óù©ü~2•V‡Öƒ‡;þfÀŽ¿ùxæÕ®:n×ÿµ»KGŽNZýt/Ýšu¢_naú5:5úúä­þ·ìÿÓüØsŒó|b½^o`b0¸#ŽóÒÌQ2Ò‘1üŽ åÑŠ›@| sTX0!O9Gd|ñ‚ <84nâÿ*ížhhr×ê6±Ãd±K…xMx;[€9…§‚¬\æv,ªm#¯{\Ù©Âç’‡tòíH  ÐÁß‹D(œ £kÛ?xå™Lü´ŸëŽ›0ù•÷T~< ÑH‡%ê­ÊVYùí; r*U,iÒûœÄ“>’íøOŸïøŸ¹bþíúßõO—¬þÖ±«ÿ×þÿ!öÿé‡ó¬ô9öã 4Ì[d޹;†,] ½cC¯!° â()74x¾ÍOA¥÷i]ò€†)ø¼ È?f`Hn†@šš:ò•¨k¡”~ÆÈR?ÐUÀs Âêjzï¬ùC­o|`O^û„ü¾@4BìŒßãÌÜkÞ.Ý«²ú™k=m‘øýªtcÒÓ§“ÖòWvúä^.ý|ñì®Uå¿Ó£Ûñßñßõîv]îú_ýÿ°7£GWÿ¯ý¯ýŒ-ž9ñôý¿ûñ«‘1¢2ÖáÞµR@Ü&aà=W@8ÔQÆUDõå¥ì‰ä:qrðóÚ„ùö›µÔ1õ¤¦Ëo½Ã, Äö½|ÛÖy8€pð3/¯·¼Kñâ€||"á„ê¶»`6á¸ñ+~¥s à¥Ü¦§äW_žÝ»´ñâ/²µ¿ô…§;ySyúø´|»Sÿ´Ån_éÃCŸ ¿ŒÙ„ùÒÕD6œøU™º«%½íÂW<¼&Ì ïøOGÜúiÇ×ÿ®ÿÕÿtåêÿckÏÖþŸ »ýúËþ›WŒ(C 4¹Ð®ÃáÞ×)P€˜ôÄ/,\Á(×Pó=MC×4¼{‡¨é|=[°)å‚úy?•ô€u¬­£é¾Ñ—{`ä¾øØmrLˆF{r9aeñ펕ü±ñ+ zo{W'§Ý@_^vêðŽðDƒ´”Ÿ°]3OútdSV=Œ6°ÊÉãði˜\\Ê ¯´Õ7<‡Tþ¡è'\Yùøèù#}ؼ‘^W™€»á¿ã¿ã¿ëÿè(kn×ÿêÿêÔÕÿÏ÷…Ùö‹maG„×þÿvûÿôƒŸýô¬£jðÅóL@b:1€b|ŠÇÏÑ<Ét¶|W°°å‡Aƒ›ñ‘?“p%,“ÙD&Gñº&|èXC×ú*×Å&têK™!p(Jå[GËÔ¡¬v¸C\”ÞÊk Yôý>uILJ#0Hã®BËÇ¿ÞEOºcM?m@6u1lxŠã§¥¹ ëÕÇüôÿ€«ÃûRL•ñÔ%~EÒ¿Fv꾜úwüÏ\Þñßõ¿ëÿÇN¬nŒþYý¿úŸ]gÃ.Û$Ì­ýÿöÿ à ÑYÂvI,,FXŸî#$,/€kvt Z˜z/ôDc§б8Ñæ.žÀ ‡‡Ý+uØzmõÞòx=Àù.@ ¸àB>YDýy¦@ÚeçJY;Ráú+à ÀaÛªZ¿cFuŸ÷aÍO_}Scw‹C社é³iÓL!¸îDù)œs‰6¿#8YéÓ¡@Âäo~úÇ S¹îd‘ÍýIþÕ¿•'…®?wZmßñßñßõ¿ëŸ>Xýÿ|ubõÿÚfóµÿyÑhoÀÍ€€/PVcθ£j>`d7h@IÓÑ< üDînYÔCp4DÊ¡çËçû¶Ÿz¤K«lä"“´¾š–NY7vÔ?D=/ñüèÃÒÆ‡LS»ã½Ü㚺¸Ô M}Òñ¿)õKë±æ_~qúaÒõAZëv1ˆÂ_»ù½ø~¯-þÒŒGŽ)G| nñ¡Mx|ô®þ=Üüòáü!_éwüOßé“ÿ3—výïú·Vÿݰúÿàƒµÿófq¿Éþç=X ·£?Æ•ñ`ÃÃ2 ÊDâ]Ža¶S$? gŒÆHžøe²îòœ4u¡åìVy5Qã79úñ©ð9ÊU>h/À͸‚-aíªldÍ·åæ¢º²ÊT¸+ÙµmÚsµ´€TA“I…‡òžmÒÊ[¹n›¶]ݹCÊœ+´Êi  —öHä&M½ê×GvèĹ©m²Ÿ•´Ö~h®¶6½¾ö’aÇìŽæyeN˜æg×ÿ®zeõÿêó ºa|ºaíÿï¶ÿßf\¹—ã ì(-8i|i:–çŸ`Œ£=Îßüèó”)¼ëðâøÊ¢(ö¦0ßôË >ÑN¾Kñwìà LÞ9j; }Û8‚T7Ù2+‡—¶‹kó°K“—6ŽPmó]i§ŽÒ·x´ñ¶rGìê‹ö[ûè”?ÇŸè#óÔá§KôºÈ:mR`¬“ïyÛ5aåZçŽÿŽ¿ù²ëÿùË®ÿÕÿ«ÿ×þמÓì%Ç~Jç¤ý>ûÿôãúëWS*gŒ&p,Ø9jñç.¿5OYi*VN¸t¥åéÝÄ9t@†‹èÊr 4'­FÙ‡2 açJÞ]å¿üj¾e8ù/çº6rh”€*¯¸Ý ,.á© á»Ð4öˆ²|䩳>¾îp‘¯(ÀÂôCÛ¡\ëo[}“SXPꚢäËÑç€-=ªMÊsü·²¨å.Ü5•K?ßäœüáI&gÌê!׎ÿôÿŽæ y˜g×ÿ®ÿ™ t×yAwH£{VÿÛ³úÿy÷Û\1?ÌšwÑþ?ýoÿñû¯|{ÌÝ%œa™ÉŸì¸Ì¢²p<ÀÇsYj·Åe‘9îC‹Æ"TF÷v÷ þÝYBËeâ5á–mÃO6´Èy-våÐóÕ'?á¡í°"äáF¾çá&ˆ”F^åC#]ÜN™Ëÿ©cøp9®›—°¶o‡.²]»gød+¹çhôtâi’¯v åÒ–«­Íò©â:e®rè[6ôó§÷ÆÐk?™8»€Ú³ã¿ã¿ë×ÿêÿ±£wWÿ¯ýÿÿËþ?ýðÿêƒ[ÐàþQºtf>þeðÀ&-Ç 1FÝ£Ü݉{Âû ˆL8FýÚ1)pê1Ev}.ð@4u”χós7äÁG^@Ã|º®S–,Ú„ðÅ9ß–ñ‚1P™Ã÷¼Ul@”Ž8ÃøØešBÓX„/×Z“ú¦¬A÷§ÒCKöÐ^Ǫ-Ÿú¯¾BÓGÝ-K&tÊ“MËÝÇJš<ޝ¼2^ Á¥Ì¤+ÞÞñŸ9›¾ÚñÏ\šyrŸS»þÏQâ®ÿѦ«ÿWÿ®C’‡=¹»Ú¤Ø–É×ì.¹3Øòá1ºÂ>Ù\§“¸Â÷ÌŸôëÝÐçHjøö˜«åRC~•ÑùÈL¢>®Eã;ÒBç7sohÂò >;UÊöß•äðVÿÝ)GFùŸÍï)>Ú¢®áAN4•“/ñĤëŸôÛôUº{¹Ö \Io[ùwÃE6´}ңëqüÛ/ê¬<­«õz͇–kùˆ‰~>\™i ~iÇŽºeÇÿ|Ád×ÿ®ÿÕÿǶUß®þ_ûÿ‡Øÿ§Oæ·¡ÊpFßS#΀ûÔ*nrÅ`j:ð"¯†^¾Éhǽ#(yå+Ì€©Ó^ÊNòüò£ä#ÏU¸ê½)»Yà1ù){í&©ÛnLä¾øG®©ðRæWs”ç«•xºPÿËO™×7¤ì%åqv~Ê“|u©êx´½—O÷°ô‰º;mÊîÚÏðÅëJïý-¼¹ÖË7fŸ¿þ;þ;þ»þwýÓcôHôí躄~Xý¿ú?vtæÂu^¬ý?›é—é›b 6–{úé?ÿ‡W.™ë°,¨YX¹od C<$ rAZÿ”«a/IÞäã ‰ uøXÔUîõÀ`ʈ\õH÷Í^¶IŽÏçe¦oÔ?ôê›Êr¿?å[7ŸSVº;H¾h=\A ^À˜Itwm ‡VûRÏ좩£€Kòy¸¶»wÂÈyïÏ]N¿ëúÓwxrx¥Ïæ§€ÎÐL¯Ÿ¶Me@§<§Ò¹È#y¢/^ÎÏíøïøÏ¼2WÓ]ÿçÈ×?3ŠbæEt }ré!seõÿê¶„Ý<óálF$<ócíÿôÇ_üç¿bx8fñ:HÜ΋Ýc™³°Ð9jÒ¡ …¶ÃÓ*c!Lð.8H<æi]Èb^Òrô72À¶«ÿìÏþ,þλ¨à„‹gë#GܤsM/_íQpÒmå(ÔŸÿüçñí4å¼øâ…^D¦ ßýö‡òêŸ2ÓŸœ~•F†Ó‡À7©#²L^¿¹)ÿöM&°´«¯Ê—|älù!‰¦ô©^í–†oe‹¬®”ßñßñ7ßvýïú§#Vÿ¯þ_û?_꛵Àſ޾Û}iâ¿Óþÿh.¹·c™1ÅÀB]ÅŸc5GhùYša…<„ÀŠü‚Æ;f~äßã£÷´ž¼º ¹lÈ”›¢Âù9™ +G6 D}êÅ'¸'-r]õ¡“Ž/ùV>nòúm:ïÞzùâeŽ5Ñ*—ç’E]Ê·7Z§“„¦NÿÞx…”'^‘uU¸}¢ì™ÐÏÀT?GÎKŽ{;É4Ê0m_N[ZGû @Ð<4iÛ%“ðŽÿŽ×å®ÿ]ÿQ$—ž gèúzõÿ9Xý¿ö?kbÖÈo³ÿ±Æ2 Ê•QÄsçhp@á@øÍã«ÿ“og èPY}eg„_€ü¼1~êð#Ê_²†Ñ*÷þÔa÷E]w0!üþ¼ lá1õuÁ+§¼8ùmKzÐ}týPs.ÜOYt/îäÈ•z&íż™ý‹×_$ßÑYJߦ? `ôGý.Þ×é3ý7DuÜ™×XàAÖ´yú­ß8,ÏöWêÆÞН~mêƒ Ã#m¸ÂäÆIïÑ`ۢϓ>4¥Ûñßñ7÷výïú_ýÞ¸úímæÿŒýŸ#½bh1óÉäîÞ6Üòã,B´cð{&Gù lºCx€S‚2ò]€¦ð“4$ãÈÄ)G–„‡îN/Ü>wùä hó𳃕×Çßùøµ‘£àãÞnm)øÁÇQ%¹½ÐïSßóñÜ$¦žÈwšñhCdŸ|­ìdv™F6y€h@ÒP„ï¤ùæ# ŠŸ4Æ­OTä~€×«ô5Z.ùÓ^>úŽÛŽÿ™K;þ™&™æ˜ùQw_3©wýïúÏÔ¸ëW â«ÿGßΙ…´úæÃ»hÿ°,Æ7¯4…pr-F8ÎD'Þç1y®ËÝîu‡¤åðÍŽÐeÜ | ~Gj_~qîT¡÷Þ)ÇXh€fpð+@¸¼“ç’‹,h¹–k\ىʅN8íž‹ÞvÛ8t.}+ûú‹çŸ —G^N¹~âR8`QûsÊ„š2yeDûT’vúP¸¿µØ;RÒ´Øâ€'àO}ŒÛ£ÞIӯꖮ-i§;q“'Ÿv¾—³cf *»´ÿsÂ\±ÌÇz™4®ó,éÒÌé]ÿé›]ÿ´ßùàÖyC¯¬þ¿ÖÔêÿ£[¦ÞûÿôWÿçÿñŠB}¾•Ö»9´…´:È‚±x¸(ÙICsî c/‹IÇÅM^þ©¦ @‚†Q·ë“o(¡Íñ¢Ð=Ž)xiŽÎŸ‡,=žœCW'þ0dåQÚñå{ÈD?ô ¤ôHÔNGa¨VÒ•©œÝ1B[žäMxäHÙ‘Z›•+]Ë;.ìŸü©çÖÌoÄM?iù>ÿ|^Ép3ziû0UOwñà =Z>yж-â@¤21 øïøïø_Gçæiç–ð®ÿyÿÞ®ÿÕÿ«ÿ©ƒØ:ŽXû6W~›ýŸ×4üÍ«÷Ë×€WÁ2Ðò¥×é\ÿ'ƒ&>þ•Ùrü†ÑÆà½‰PP S@ÐA°¾ b§ `(p#ƒçÎ;uaœ¿mèCf¢’Sþ%šº»NŽýÐÚ5Ò®Ê:NÞÈ>t>8FxW¾¶±õ¢iX9aòÞÃu—G~ÛXÖ#@¾z:&Ê¥ýÊL_¹C01Ò…ߪSy€ª÷Ú*KÛ ^¾­‹Lu;þ;þ»þwý[ý?Jqõÿ±¯ìCí¿áwÙþçMîv68Gn1ž‰ Pãÿè°é8 ‹Á=†øÍ£„G§^4fÊy/—2³KžîtÉçäU–ÖE¦öáŽÿG'úlÇ׿µ¾ëõÿêÿù0½öÿ÷Úÿ§Í=3è {+0ÄpsL¿p0ÃübîJ1Æõå¡ã+ic8½ˆgÀ‡À8uüˆgÇdÒìøàŸ{N“_€p¯ŸÜ•¡Qœ‹ü#“ô·ê!ÿäÛKÂS½Ê¤®Ék=-@rÉJÁVnôv»84)À‹ö‹Ë/_€UY}Ú×Aè}‚†“¯ß´ß»dlËÞåFxåðÖ6þ‹ìÀÙ¶ÒÓ¾©¿üZ^Âï>ÒñávüwüwýŸ"]7»þχDý°úõÿÝþÖ¦˜kÿÏ&EíÿÓ÷ÿö'¯uE ;6"Ü€Iã„u¦'Àa~Ž…1¯aæ‡C}¥Ÿ£ª³#£~q©-†|xòü«Ø•ç*•çоúèUâÂU„ˆú‡I ¿¶-¯?M ?mŸ6ᣠòÊSØÄ¹·Qž>ΠyùâevÞðtÌØ:Ò/W¿¡—î‘>½?á¡y”¹h´¥}®>¼ç+hI—P5e)Arº|u›^ýhåãÆ[¯¼ÿÿ]ÿÏ;ä»þŸunu=áç¸(?:ˆãKÏÎøêÿg]®_Vÿ»÷žÙÿ§?¿VŽÊÆ@ó-’étÈÀ€îãçÒùÐvaµ,Ý'3Áòê…3¼ìÂŒïÛoêu§Ènžu5þdj:Zïœ)“†hàä=Ù£¬ŒËI#ÿÃM-Þå_GmvŒ¤S´Ò…ÛݪÌê&GÛö¨gêóD÷–"ßÄýã¢Æ—Ž€Òä«§i­ï”!í³BC£oÐ(_¥û"y\jϱ딫Á(Otä•Î/¿ò €Ûñßñ¿Í{sg×ÿíg½.½`íìú_ý¿úÿØ'ýÀ½¯öÿéÏæ§r€ŸXà_r̸Íó¿à£@&éÇÕ×o^i-?|Êà—oäR²ƒÅˆ|›mè¼Yü¾;£,xâyÒ›f“†Œ‘Ïñ“&}žIH:¿í= Ïeðôè+éúí•©Îqp˜·¡ #·@«¼‰S‘´Ç¥v2M¥i©Í\zoû¤‘7—ÓCpúOäîÎ_Û‰Výv°ð°Kè[*"{û ÝŽÿtàŽÿ®ÿk]ÕëZÚõ?JcþëŽîâ¢?:zM¾>ã7¯´«ÿO®þ¿ìv°¬D0¶}UIi]HÂM«ï<ãÍÕGg¡ÍÞùžôÙŽŸêç,FGn}q&ü[ºI/ïÄgaá?ôø @Z‡F^^0wóÅÕ[~•Yzå £ùã.ä”^õ˜EÎNšö_wëôSÛÚП2©k⹃vɉWåIû&_9ýrJe(<“™c?qwÛ ®ð©KÞŽ»#ý¹ãov=VsļëünZý]ÿGÿìú_ý¿úÿà€Ú¶÷Ôþ?ÅùúÿÙ‘y¿À†’=ªö/õ=P”j+` »Å¹;Á›ÁWÆ%n>Dðæó7uޱ>žoÇ¥®ùóï|'€ `"´èA±£ôóŠÙÑ¢Ì8ɱ¡òhð¿4‡Ož){Ñøs›ÔÛ#@}9† Ô;MÀJÞô ‡OËj¯>ؼ ùvíÈ[À“44n]/¬wd+×vFöIã× ·^ò`vŤWæö2;þgü:†üÿ3«Ìå]ÿ»þ̓èœK×™ÒVÿ¯þÍ9êâ½·ÿc_Ïv.âhÊÌÎÊÄëy tA€tc?‹­qixKoie¾7ay~`ñaqƒðêϹäøLÙy8ÀhïÛÖóÒÓA (îu sU ‹Ï€IçZ†—»åë+£¿ô•4²hkãøÉ'щùÕ3ÈÌëF4 NY<”ã“HºxúlÒ¤×Efm¿=òKC~OË+—>¼xG>zat;þ·ù=}£_úè?anÇæÎ®ÿÇzßõ¿úŸ]ý¿öŸ¸ÛÿÜÁ29( ¿³Çå-é ñE¬p€.…¹¬­ #-é1ÁjÔU„žá®Cç9nJÌÿìdMB.À_€@eï.¦í&õ¹[”^1Ã'®†Æ'^²T~|k,ÉCfüù\éÔ¡.àÄ gôÒ8<ÐðC¾|}%ÜþÀ»ñáðè·!­wZÉç”.8«L¡Wžrší'e´µq|ú8ü¶ò½ê@ƒ¿|üÅwüwüwýïú§ƒVÿ_vnõÿ³ agÇN°ôÄÚÿofÿó[„ 0½Ãm×Hi‡00â:˜¡®áïÚ|ÖÇ&Gz5ìI¸þŒá00ß&Ì·ó¼ >ˆhØí½¬:RßÅCÙwüÈ9ßÐËû¢†Ð sÊOº¶¡/ϔіqiû”‰?qeåMiß\`·õÝ÷O‘¿å„• @_?ˆ“K^Úzn>ùY½h޶õ©ó]ÞÙ¥›ôöË_„˜?ÍÓšŽUûÅZŽSÇÄíX¡ãÒö £Ûñßñ7+ºF:§Ì›Ì—ñ­#n×ÿ®óÂ?ŽŽ©>JÂõgõÿYO«ÿß/ûÿôý¿ûék „2»ŒlŒð$4=Šu´.pÅ$<´þMÀßÄrð²è.¾Œ·0E­LDÅaÃ38B£ñMý¡8¯ß³ÿ€´!Q‡¤înÝÛÓúívqîr 3•µõ;ík'¾º.³‡ïðGª`ú®Gü2Dhð.½xÛøœô»k» +¿¾æìhÅ¿â‰Ìt¼[V^Û,LÙå^×ÐEöñõ? «õ5=òLÕ;þg§V¿ìøïú7²†.€±ë>@ÒM—Ò?Õ©«ÿWÿ[+æûò>Øÿ}}ë|}%FXGôÑ!\wt c;;#¡‘yuœ‹Ò=¾Jg^oîD?ÍXxÂ]„â>}ùÅ—1^xZ¨Ò•oýÂuÒçË9Ÿ¥¨è‘aò®r £rŽ%Ý· çNØÐU6õ åÚ®».ü’;Tәľv¼*»: xГ§¯ih¤5œ Õ©íãßeøµúæi;ж}Ò#ŸÄ‘»åøò¸ŒùøOصœÀŽÿŽ&ÆY?'¸ëŸn⺆vý_úäú»úÿƒ|áƒ^]ý€ÓÚÿ·íÿ‡TªÝÿbÝq5Ø ? º„ pöS‰pÜ•W¥h@ñŒ\ÑJFò-·—3qçx®GX&¥KùSùuê:@§)#î¼e´‰}È1¢´¹S5%swiÊ% Y²ó5õ %3W ö«Kr •^ùr ñäqMn?ð“«ó”¿pݣܭÝ÷¼æóñóôÓ‚´¼ ¿«=–^ßñOíø€e^™3]›o»þwýWßdN\zªújõÿêsÁ±¡!LgpÒj÷’ÿ§hÿ»8ºXw@¤éé‰ë4{ vPº€dÅ<šBo•kgR΀wïmôN¾:]g÷ø-Çv×ÀàC± ®uGžï²úÕWÏßhD#ÏÓ—•fP§|w”ʧ\žòÉÞãËï·+cŽÐ†Aå ̓öìàåÓÝÐpÚ”z‡W].¤_2¶îú‚“×cõ¿M‰Õÿæ·öÿ\ €b×CLß|Ș0¶fLx:mŒ2gQ5ýaŒ¥'wþLyáùiæøh<Sáwé➢XBI/.*ý»õK¯ó—:éÍ+?ßT_ô;?`¯Ç|Òí\¸€Þ÷D‘/¼æR~emü/@xmWóÔh§KÙ¼öB? ýƒÇä‹Û›yK¦òøzò'ás‡“þ} }\A–zÂoh…¹ÆÉÖ4ý.>5§ŸÑíøŸc^}´ãoF<ës¨s§óÒìz¬ÀÌ¥]ÿ»þWÿG¯ÒÕãVÿŸÍ}ÂæÕîu¼/ö?ïe`lýÏ¡0¯I’™2ª`ù}äEùNçMÁfWä×g‚嫾×-`‹R¶¥L;×{/”üaü Gž»_9"'Å?ÿ¼E½txŸ6L“Þz¤måM–ƒ2à鎠…Ö®“§¯Oh›[Oå@«µyÿV$=}¢Þð°–7[O|¶±’V㔲SÞ¥Xí-ÏwÛ{zóÁü¶a¢üݵ¼ôö_•VÝ\ó¥+·ãÿ"ý°ã?ëóZ£g¦œ¿[ü>r2výO?=Õ>ÙõowgôòêÿÕÿlÜeÛßKûÿýëÇž*=À£@BZjý;¨á®!ï‚:ñ¨ÐëXÇd½óô8ŠóŽ7¥ÄÇÓƒ‡2vˆ€¼[wv¸€‡¡üz²Hå<\e®_¾Ý!k:¿/Í׌Á˜‘ctåUþ´gÀ^ ‡pþàÃñó#Ñ# ‡ˆSïd¦lëÆç^N½Ë´Œ×a˜KóAW—\è”#×osiïUgî]ò‘ƒL<øuênÿI«œõ[Fþz@nÇÇ?s.óa׿u±ëõ?¹úÿý´ÿÏ¿Eè¨êRŒ&EÉ»ĸÖJ«±MÚÄ¿âOi”ezÑGŽÁðÄ?k|`Mv™Ð_O˜ÌŸÖ‘Ý¥1Þvz”(ä W^à@º¸ºÑ*S÷hÓ•¦lÚ|ñîOÉh(õ,¿²I×>»p÷4|Èñb€™tmÈ·/^úà7£+ ¥œº<øyFŠ\üÇsz(€/®üз¯¥uí¢½|ñ2`Q0D& «.G•SÎíÏÿçÝ\ýª?ø÷±Þñßõ¿ëõÿ]'¬þ_û_ûÿôÃø‹×ŒÆc›;Æ»f:èÛ×Ý÷éT¾ŽÉ _`æ„&ŽŸIÆÏ+†'˜"^Lj‚ÑšŒä7ÿ *|ôÎë äáÓ }ËÔ"Ÿ¬•£u·\ø{…Ä«<òÊ&]Ü#.½ÀM¤NHñ­<í@£Îìæhi'üæóϳh½|ù"‚Vv<õÁT”º*#¿r‡æö'»EÃW™·Ú04ʵÝ|í '?ÿÚ¦‚†ÿÿL/óéævýïú§ÛWÿŸî–Æêÿ±ïcïØ–µÿ¿Ûþ?ýàïö:F÷fàñ™L÷sÓ€«éT MÁVõ1Îånõ< 9¿†^¹´ÒëäqJ`ÀVþÊzJ›ó§q>ž| æMC+Ì•O^YpÑH™·ç~X Z_‹ àjìÚµ.àŠ+ÿ{»¤‹3||›ß¶´\åz×ïqN9ÿ¸È9qý€•·<òÙ¥š¬‡ŒòÉúåÖ·•gÇÿÌW}¨¯vüwýïú_ý¿úíÿ7±ÿ9"ÌÅÖ1 ó1Òǘ0²ŒŠ´ki¹´”0Ηñ.h=>“ϵ¼rî7Õðgç*´.>Òàøøøw©´Ý5ÂFÑyšV?íºèТù¾i¨BaòòÉïî•;X÷¶ßë@爈ÃKYÏ`>#“úz„'ß;¾¤qüûsó7éêkýwþ“˜ôÖçHsR¦Cëo_ëûÊÙúÃ{d"òâ"ø¢áße¶ãæØŽÿ®ÿ]ÿçÛµPý=2q®úƒÞXýúcõÿóûÍ‘»}‹]ú²ÿZiÔÒ±¯Ç]¾t ¤»3 µÎ`¤9»_O<ôò-$NÿGI=†\¾5þ¥Ç+ò\ååûv"Ú¿aÀ%õ MÓˆšñ½OKX}þœ2²~ý™c»—¹˜PóþŠ´Széùøà‡ç‹7Ï—àÉè±SôÁçòyèf×KŸQÆò½5ž/ ‘uxrI›obN¯=ú­²òOþ´gh;\Ê%<(·óÿK2Ç=ÊŽGë•7ŒŸ^Œ[†¬ÜŽÿŽ¿9³ë×ôÁèŒÕÿ«ÿÙ¤µÿǦ¿kÿó[„KŒ¬À8á>'å9Ÿ‚Ì1ÆÈ™ÎÕÁž:[è }@ÍÙ9ü²OrQá1®åjܹ̓Âs€‰»A.¸×È£+Èy”‰<‡¯d¦‘ñ¤þæ6©Û6Ÿ¸¯¿ö>«sù[ÛÜ•êE÷¨åæjh´3uÉ»úåÏ¥ht•múfÒJÃÿ‹îž.Üþ®ÃÏÃ…“²nIo¹Þ!SGû¥õ¡+ŸúM»×Ñ4¾²m§°¾SWëC³ãúµ€T_êŸÿ3g̡͑ñ:oÚG»þŸ×¤njÿ×Ý׿®ÿëùQ©1ôÕsôx]ûŒ_—5¹ú?Ýqï—ßÔWÍ_ýf~ðAó÷Ùÿ§Î,EޱC0€†ÑŒ&Œ¶‰ÈXp7×nNÏ$•1´xˆK\Ð>âWÞ#mŠ´ž(6Ha<Õ‘¡ JúÝ5½4‘iÚÀ »ƒ•¶Mœ,œ2\ëýÚŽ\pÃÐ_íí‘^v£¾øÉ€«e”Ç×®¯.p&_¹ôÉäYèýñWé¾²­ >å‘ÀõG:¾ž‡{Ö „>Ç€h´câ•)ílÜ8 ƒÊš´c«£ÏáÑ>IÙ·;þg¾ïøÏä™ùÑõ°ë×?}}{ÓŸÑ/2è£KŸD‡­þ_ý?óÄü¨M6’6Sæ}°ÿy“;%{`ë%÷lfÁ04:ÅCÉæÛ‚“$(×ΫÆ'Èn|Çk¾½Všú“pÄØ_à%õN=xôžO°´È8eÕ…Wéùå0´œ²O&' %/tòæv$¨Âò9¾²Ò§³C¹&/ß[~ºÀå*¯\út”Ì‹ùÆ ú=> ;_ÊÝú9´ž¸IÊEº€Þé³I,ÈCCN}YFž”>üôíÐû 9Є¦ãeÇÍÑé—S¾é§ÌÌêÞñßñ7'vý[ »þ«kVÿ¯þ§Öþ3ûŸo²ÆÀC¬ór?´Ìxwa1¸ÂŽÎê»ag¤;6?âx‰{(ê8tÀÉ<À—}tÕ×vé2ph<úÔDÔ¯­(˱äUWËã©~OùóÉÓöà‘øô>l]èä¡Ó;[€«»^D*më@§.ÿGÿíøïú§“vý¯þ§ VÿŸñkÿÙÉ?Üþ?ýøÿò5[£#=Œ0¾x4vP8yh\&<âÊ3ìè‚v]|¿ÊoʶΣҟSPÚyÔÖz¿x¡?Ç@¦ò’~w•ŸOݾà„O¹’7ý0ò ûIŸôÅä+'-å‡0Äqêh™¼äSziêºužûe¿YîÈ©íWÿ©Û£3äyÒç#OZ*íN—þ«#ye†Odzý‘v§®Sgû4¥GW9"ËŽºYŸìøïú§«vý¯þ_ýÿ~ÛÿÀb Ôó@‘‰SžÞ÷‰gl'-F_Á„g1Í¿€¥g“ã°ÞC àB?NY†¾õÝýGq`Œ:þcͶR×Už,.Á·ld#óåñ)/Ì¡ PÀ÷ŠãY€Á8¢-p¥}>/ %7ÐXø½Bá‚´‚ÀFZëP¶ HöUeCk Hê¤çoÊ$æ~”¾àćý•z²†F;ÛŽòG›t5»ß6u‰×íø?SòÑ·;þY»þÏÝÊ]ÿG?­þ_ýÿ°±7kÿõÇ»öÿñ&÷Y>Bf—áŠj åq1þéÔcÈcŒ&~ü ¡;ćßä<ŒÁš„ðïB} –27¡G†–©,äRŸ:øœ¼æ+—ú'½⨆«}d˜ç¼‰Ý‘À±Í?`I' )ƒg”ß¼+Ù%í¸äAç´\d¹hÎ&O7a!¼h§ÂG[žBßW§ÿÈ…7z~. ^õˆkCû&ùÚ ^àðž×úù¡_ÿíøïøwM™Ü®ÿçY»þ«÷ë¯þ_ý,nìom{4áè¶jôÈû`ÿ?Ô``€Q®2e|?˜øã[x:ež(ع"îxnÌú)—Ôù3ô“Î;”çJYù㦨¿šW0(!íþJ,Ÿe‚ð~ð˜ÀV‡®éᯞy”7\x]€IŠóõÖ™ûgSàƒ%-¯ŒoÁ€»YßùÎw²$ñ2p÷®S·2Új× ò]­Ômz8`°ã…NýÓ[ñ \ci„5òŠg|§Ì]ÆôÏÕW;þéâÿ™ƒæEæáÌnfÏ®ÿÙÉÞõtöÑ®&Æ„fŽ˜%g¦¬þ_ý~w—þÈü07®ðû`ÿ? мŒªWÀŒn:a:ƒ¡þZ‡Œ«OĪJŸå³žà•1ÙUÌèñséš«!úà\&Žõ5ß`€œ„@ðzò½Ë©ü>œ4ôYñã%<éˆÃO> Â·³M ù¶Ý%˯Á¡ûÅ/~ñ­ï|÷»¹cQóÜêç7£µÀ|“л¡¼ÎÁ§;[NÛ섹ßÕþ©K¹µ){ßáJ_G¢iÛÈþOzë;rN&(òØá"›¼–=ïí2åç Àš|4À#9Ó§ŠðKùá׺Ú7d‘¦N4;þ;þ—·™W3GvýŸ×Ñìú_ýop«ÿ×þ?î`Q˜yÍÂ%®F7‘ùÃÐV© ›<â-1åìðUº1ΗqíÅçλeÔ`„˜:ÐպΑVÓä .ÐL\õÈËOõmÒY¹‘W¸ïµÃV?þè!GšÒ[¥™¶L9áÐHCûæó7yÃËW/Ú/ù^Ñpd~6Êøµí©çú D¼«˜• ö¹Ú.î• doŸ´½-žÃ[óž´oâá4ÄÊ¥ŽÛ7oÞh~\ùU¦ÿ@‰ëœHdþ˜+æ¢tá]ÿ»þ«ß¢WgŽDwÝæˆy2æ­¹T“²·2æÙÑYtس®“κVÿg]NðWÿÿÏoÿŸì`1Øžûë²2ƒXP@¡rõívh Ç® gת‹dVF¾I(_¾‹ÖÊĤ̵¨Ð«HŠ\W&u M¼ºéá™IwÑó‚ÄÊ\ùº¨[Ÿz”—ïI½ÓNtêäð(>`„–là߇ΤÙúhv´ÿ9bÔ•M9|Ê×QaŽ §œzÅÖ§N}P§Lw„ñš?¡Ix•–_š¦Io;ù\êâ)7ijÜñ?¿ ;;þgŽt-™ÓÂõwýïú¯~]ý¿úŸ}YûÿlÿŸ~üŸÿÃëc˜ÏއŸs|*±³ÃÉ·#Ó HrÙ»i”.£d±M‡¡ïâ³s‚/>å‰oÁŠ0c_`€€ñ.Î.Ž·ŸGѼ#÷:&îB~Žó&¬\d¹è€‰ÒOÒ³¬.ð`4Ô/Þ´î’À Éq P3Ï—¦ôù>¿v¯ô ù”M*g— ßö‰4üÞ•«u5½ hàJ åŽX]ûŸß~ä£S§ºk( è~[úxåŒy`ÖŽÿŽÿ®ÿ]ÿ«ÿ¯£×)Iuòêÿ_ÇÞ­ýÿföÿéÏþÓ^3ÖŽ–\¸®Áeˆ)Zq“Ê, >ìP)‡®´òjÜïoy©g&,#Ž_i„îÙHï#]ÝÀK?)Ë{ë5r"ãÐÇ8Lwê{ Ê6]^ŸÖ§ÒÚ^¼îíhûÐÈ ­þ¹—ÃÿÓO?ýÖ'Ÿ|’>mÿ¹àÿÙ§çÞ–Ëíø¶, fÇPÕÏUÖ{‘¾²Þehߦà;´…K;¦ŽòM=SWeßñÞeÜñ?ób×ÿ®ÿê/zcõÿ±owÝ[^»A×®þûþûlÿ?ø¿þŸÿ{æÆ(TGrï\ä–n1àviLqÆZš‰Vƒ£¹¡ïÑ ôÒŸO\…zßÉ2)ëÔYWގܸ‚ŠxAP벫4™Þ!åØ+| ¬Ç÷éìî€ În>x·==†”†ùÉ®LûL9éÊOèÐw¾iÈ×g‘s€”ɦÜo¾åÚN2ˆ«›„• © èµ³ ï^§lyÝ#oéR~xLƒGÛò({µaÇÿCëWý¶ã¿ë×ÿêÿÕÿkÿk3—ýú÷óÃ׌1°Â˜rcΡ¿@ƒ4?üÑ«cìó*ƒ¡¯‘¬ìÒàåUž ï€]M ¿25þMcØðRî@P«ìƒÈ#,½yÚTE–¹7´”ü©£´­wƒÇâOX½äàÈx¡íeyuW€¨tùt¾ãQeÈðŤM•yuƒ8žmÂsú‹“WÃ.}2“îOê¿ùÒ„¹Ðޝ½d"{Û¨Ž‡úTuíø_ïkÓA;þ™?/»þwý¯þ_ýTãùu¯LZûlõo³ÿù©Æ7»&—Ï7ó&¡¦`}bëÅl´Àà üxVx6öDèjÌ‘2þâò9õU©Kë‹N{Lˆ¦` Àéh]ïîOP¥òs¡ü %%øPNvzô(žºF®æD)§N2×G¯Îúúı`î]üµããY—vÍ1©2Î7 ñðN£ót¤7ܾkš¸§²+‡_y©[~ë@÷íUºÿ3?vüwýwuÝ×·®¬±ú»þiŽãVÿ_úcõlŸ5d­¼öÿé'sÉÈ7ȉä·ýºR.ŸQöÎ'G„@É«\5ÐH(‹ ¸àäqv²( ®\…Å¿ç…è?å~‰[ÝS, AÞH¿ Ø#£|9ÀoŸ¸½Ó*poâÒÈÅ/Èð)@,íŸpä¹òñG/Oº0þÊ«W<»fWÛì\Ù-R?z ·Ç êÓG?ÿùÏsl(ú·ë§ºó‡.-í<“ì,h|§{ÒòTþ¶ÍΙ4OòÈ«¯mšGû'lÏnÇÿÌÿL‘ü1‡výïú_ý¿úíÿfÿ?ø¯ÿý¿ýzŠÄ¸ÚÍ €"æada`Â#Î4¿œ7“¿™;D“ð “W B+Ç Ï#²S3Íÿ°\õQähêЪ?²L"ˆæî—ð!¿2-‹çÈò’X±3Áå ×1£:8~?¥*uê•ÞþPgúdÊOœ‹¼W}SÀ§v\Ù?úø£¼?‹lu•[\÷¾*ÒÇ4¯ãÎö‘úµ;nx3ŠÂ•{ô×Õ·@âŽÿ ú~Çÿ¬ýÎáÎ÷]ÿ»þé¤ÕÿÇ®þ_ûÿMìv°2YæxÏó»;ÄèˆS´v;ì(1ì5Ô1JS¦€LÜ;òmAtå‰/OEî¹Çщ°ðñå” À˜pò¯òä³c$¿”©ïâuÀÆìä ?»F­³<ÅÉKþ´/5ž:ñäÎ;«Î0™ì‚‘'mDpÕ/àsåEæ ;þj€¬~LÚQo䜲@_Û-½4õñ”‘I9®ùò”'¿ðš_ôm _9iŽWùïøpOÏîø›»þwý¯þ_ý¿öŸ­ÿæö?w°Ø‘]a •«±¶+Â`7OáJS®Çxè¦p€˜ÅXc¶Ào»&âè=Mïu Þ_|9»/ß+`à+‹w€Æä£Q¦i“0Pâ´CK„ Z’3ùvt"¯ürˆãe稯£À?]>e&ŸÔ•^8ÙÈ©L]ëQ.;iómBGrê$‹²Ù}Rÿìþõe¤8Ü¿Y>xßÃ÷>VçiÃ^2”V¾S''¯®2ïøïø[7æ¦uÇ™œ¹&ͼÙõôÅ®ÿÕÿ«ÿ×þÓ‰µÿOßÿûŸ½f€U“ƒO©VYð RX>€àHÀøüÍç,t.°Ã?弟ê£>J™ð¡9ÎÎÏX†E­œ¯Ï?Ãë`‚~kE}d K¿Ä+‹úŶmâù{ ù=1# ЂGøŒ Êø¹ ¬@¿´ç’=í¸8·ÞÈ~ɃGÁ‘pù_b$žôIP¶iS^VJ¶‘£ý-ϱâpvðÆçÊ·²‰ßÃh"ó¤EéöyÔÞÛÁ«å£^á>•gÇúðš:vÇ׿µ±ëõ¿y@7Dg^Ž…Wÿ¿ßö?;X&CËðv¢0¦5 ÝÕAW…âˆËý Ù…qT6³)»1ÊÚ!R®€+ÄþL=ÞSÅö aÊ}ï{ßˤÄÏ¥qÆ^~e@8“W:þM_’šÌIçÈÞ×D¬Äñð©\}޺ˆô‚ esª‡â;á<N‘«Ih²35@Q¿¤Ošyù긡R§vŒº3¦_ô5ÀW÷VÙIŒlÍ_ýGÞôª”¤ÝHNÚüE×ò•{ÇÇ×ÿùpaMìú>ÖžÕÿ—6]ýŸŽXû~íFgÔŽÚ(ªýÏ›Ü ÇwG ±w\Œ¿÷7õ~Ph :†îÅí…ùóN8Ï”¿ñÅñû“J¯?øúË_ÈLXО–-}Ðù6Þó±\whJW Ñ]Ç“çuçSå €›Ý¢7³›ä›ÉkW)n5ûoíºµCÙZOè'­}—cÈé+/  ™¼»+Èi?£Wo&î,4òK ÄáBiíO| ”µñáRg1I¡üÕ§šxpéÿÿÛÞõ¿ëõÿêÿµÿçÔ‚Ýü¦ö?¿Eøñeh `äË/æ7ýƸø´>y.Àîj‹vñƒ¾}Ðr|ò·íäÁ§u:2üè£wÃFºò­ë?žãO|Z.mÔ}x“[Zd9 TÇøz•ÅC¾Éë®ÛŽÿó·…vüwýïú_ý]Jé^®:YtõÿófLmõÚÿÙhùþßýôµ‰Â sv^¸^êÍÕé,€Äƒ¾—݆ùâ ò Ä›awþÀd ¯ ›ÀÒð¤ð’ߺ…ñlÝo¾xóxÝÁfÏ€M]€ËÓ bcò®©ìtÔ_€ñCGq<,$Ž,Ò¹ú‰ˆÏ? 9éx^4â~T™+~yµmêlÛè§N;S+éúB›²C'aÂSÉC¦Ô#9Yówò;•‘\å¹ãÿöøèRý³ã¿ë×ÿêÿÕÿkÿÙ„ÚìÚ~ÝÝþ?¬ì¢ÌŽÇ;81ü€¨ H8÷†÷šì(ÝÓU(ÕÇ àÐÅÈ3ôó([À$îá| Íäw.@IDATKÝœrhº‚Zý¿úì;öÔVðÙ¤µÿßÀþû±çw(üp¾¿Dˆ©aF[ziÙ¹šŽþr@ .èÑÌÌ€ßÁ”8Ǹsw@ÒÁ”ާxêà‚½ÀzA½4êRÄ…û?/ݧÍW·0 UPóòÕË!&oòЮºÉ!-Y=}#,üäá Ø´'£¨æ[“ÒsÏ«\è&^uooÀÑеÿ´—«¼&>§OÉÑOWÙ…žÝ Í\äïω“³ý¤¯” ?Ü„wüÏÜÓ'úgÇÿ|8¸Ïóg×ÿ®ÿêèÕÿ«ÿ×þûŸ{®A¥(ûHk8€aÀƒn7D:@Á´³ "=ÆcÄ•øhZÕЊ+À2a>—ô¹pþòÅ9 ð%zuòí0åÂú”-oéœ{c~ÒÇ· ¥0•ýa$/Ó†©[ýIS—Ò)䤾 HÙ¹#—t2hÛ¯Üë’xÉ2Œ¯¢³ƒÔ7Îã²ü=ÔÕ6HÑU\êhJË7 O—½UFݧ.06´R|É5à§ u­»tïøïø[Y'fÒÌÎÓ¶ë×ÿùL§ùðY}Üy²úÿèq¶`õÿ`ögì%]– ó¹¤ÿ‰Øÿ§Î{°jè»ÓÒÅ¡±òìœ`„öê¯–_ãÎ0{Õg¡ªYˆ×±h»o‡ó)-¯.ðp?S7PPÐqU}Ç•]œÒdà†ß$<RšúÉÀFÛGåÂ_XÝüÆ)å¤ûĶ»VZôx¶.éú€lÚvw‘ñžðN8ò\«®Ky׾˽O»&ßxewk &jþÑz¸ÿó¡`Çÿôƒ9anìúßõ¿úõ¿ †ØŠËŽ®ýÿýö?V>¸q:ÍÜðø–0 s`40Þ_¯€y|éÞk%\ Ñ®Qo]­OýMÂùå9ºãFÂÜ™Â=àxàU€"üíÉ':ùôC:´H“öÍÚ'®Ž:<”%Oê˜ }!]½ü¸áÉUíœ]@ÎäÛIû`x¤¦o½vØ9uãðìÔá˜kyå¤sŽ6ž6&çy Ñ7=õ\e‘5}Ç@ðŽÿ®ÿ]ÿÑô‚çèŸÕÿ«ÿ×þ[ ìäjÿŸ¾ÿ·?y ‰ÞÕÃð2ÎvJfwÇ· { ‰aç3Þ€z`‚+Fñ€«äNþðÚùóÕ€ FRÓ ÊKËšÜÛ³Ú‰«ß#^PUš³ks…cµ®©›ŒÂBN;æ½SäÖ6?˜¬>€ @áä÷ñòÑtþäóÛîÈuÈ“Ž¾i:Ó»Ï`HYúøè=Êê1`J^(š»k ×xë-Ü÷rà½ãÿ|·Ð+GÒ'Ó·;þ»þwý¯þ_ý¿öÿµÿylÝwovŒÄàÄèŒÑft€«·Žþ®òhjÜ…!oC–¦ÿA3ØxãNýSÇÔÕ8Ú–óî'ñ~»p+H6üfa?e ˜"ïÎeqí›§uª?;fSÉC>mÄ‹l@ ãÛÉÿ²’‡‹Ìã“;ïØ:ïôJÝ—<ò”/ÀW7‡ÎS×~“þmÇE¯êSú¹|ëk?”ïéëSGÛöH §SóŽÿŽ¿™°ë×?=2óaõÿêÿµÿßÜþ?ý`î`1¾]D5ÌŒ.|Èë™Ý!ŠÑ¿qå¸íO>ù$à¡üíøàaGŒ{€¥ 0(WòÏÂþ €îÍço'SÀ ¸t•3è/^Î…óAäê(U‘ó'ƒ`°>»rË  ˜t÷¸Ôß”¶o”âäsU“Ö>†6—éÇOþILÿµ~Iäç ÄNÝ“ðÁ«u£æÚÞðÅÇï#Ò®K ·ôR”gëÑ×Âøéƒÿò;¿wüwýïú?W$VÿXý[QýÈvÔvóÅßwûŸKî5Ð:„«¡åS(Ý=Iæü±¸î)½€/âñ»}gÜ[Ú¾,Ó øD„—º<? Ÿ)/î«@O¹Ê€¾²ðAŽ<è<BêÀO&‡Nx¶õ¼¼v® Ô”o›€8夡u¡ogËÅè„'O› NRª<ýB®ÊH¦ö±È¥®<>žèÈŠ¶å¥EŽ9¾íÏâ”¶2;Ú=ïùr<9G£äžr8·¬úúàÉ•ÇÇß|é¼4?ºö:·¥u£Ûõ¿ëõÿÙœè麨þ¶fVÿÿéÛÿ§Ì›ÜÒ8¿†¼iÀÂ}b ïš<ŽRe¹M(iÝ•HZ^ÞoÎË@M8»? 0<«Ä¥å“"0D¾#³ëEŽðŸ<év²TÌd‡<û÷•È6äå›H@khÈã=Y|4u××u%><¼~ h€—öÃ××;¦ZNßÄ©cžœñ+·¼¶Ñ‘cï@IÇCò Ÿ„ ’¯ÎÊ‹GéÔ¡?9}ÄIË8 _ Ö?Ãîð|Ç?êÓÃÛñ?ó`Çÿš§3wýïúïÃê=º#:jtÆêÿg»±úí ©õñçsÉ]$†ý&ÆÐú?·EÕÅ„þ]£\:h¯ÒT¹¿äþ€r Ã¡où–2NGétvaJð¨ І¦ùÊ—_$:b%Í'¬l¸r‹i|²´(^dHë^e¯Ÿ¯¡€(åÊG˜=ŠÊ+¿€)lçÏiãì\ùfÛÄK#¿€J¸u+S½<ß²ô…})Žžé»i…þo9ùvâÂ3ƒ¿ã¿ãÿ¼ÎÌaýQwÖæÛó.sÉ43ׯµŒô]ÿçC~Ñ?»þWÿ[OÕíôzõÂ>®þ÷Áÿ߸ýÿá?þå뻑í U¨€ÈXâ(I´&Cø4ÿ­F¼“%e3½;Rò¢`æÛZyûóT£>4uQУ„R×È!îˆ P–甸GW^åa‡ˆ;Çxg÷+ò /.ÇfSž|‰_ C¸¼ñ ¿I«/¿éõßDÓ¶ûÝ,é]Hh&³ºösë“Þþ—&?iÇÿåWçî>€›4 Rï¼ôˆöÝeMÿ'Mû忾߅¾õ§,úáÏHVukËŽÿ™úbÇfË®ÿ]ÿ—Ή^ºt3}±úÿùº]¡Vÿ?Ûl¶†£Kçϱ5ÿÆíî`QŠqÓ(¨bˆ'Ã=~Ìà£79<Ù º:¡;BØ…Ï”cð=WEâ×ã°Ò#ÃŃ}Ðww*á‘%ƒ!Â]rõ«öäs_OaljŽÅ"÷ÈVÀVþ¡¹€CÛ? òx½ÄÄÉXè‹(Ž€NÀÐuŠ$Òìl%ÿê3÷µ”k?ÜÛÞÝ&²xô»O3½:/[ÕþSúiýŠû`÷¾Hxhå…îÑæé‹ômâ'œ„‰«+²ìø?æ¿þØñŸ£f>íúßõ_=k>¬þ?×0VÿϺ`[`ËÖÐìç}µÿç=X—a¥Díx0 Ó8éŠ M\¬Ï“ƒ~u®‰'ŽÞåo¾×&HÈR÷”‘ã~…ñ~¤]òá“wZ)0N< üBè€Én”É Oü`&ÿü¤Í*¦åRÇaîoxLbÒ“Ѱºh(÷¸´¥òj§x/ûäöõô`Å™l_S¾/õèƒ:au>Í1¨và¯-Ê·ÿL^ÎÛäíÖI÷»‹hózŠ¡O¿^|ÉÕ~ϘãÉK½ãïøƒÎã®±ÑÂÆgÇ×ÿãƒÖ®«dÖ†gþŒîXýlØêÿ3ئ÷Ýþç’{ŒHÖ‰Õr\€Æ,`5††Öa5öÊ1:1WyZ&þÜ™*¨‘O®{¾ú€æQziðç‚ÉG3`€4â!Œäâ·tÍÃË»¹É¬ŒØò+¿2¥·Ø¾úrÀÑðm;õ!^Ù]ŸS—‡Ó?Ú‚Zuð“?ôòâ©®Ö‡¦?Ðì‘­_awj=iÊrÍkXœ ;þ×ÎßôwÇhÇÿÌ9ýá1WÌé]ÿçK$]»þŸçFõçêÿÕÿï‹ý¼¦0y(ÉËQž.F.óïn„c•¯?OÜ”-Ÿ¦eaMº]`!@hx2ÞC|è§ð½œz•ób}Ai * fðAÛ|>‘×L=è<¡™ºÈa'(àBHQo@ÓÐ8çõL82]Û…ÑóÃ{êUåkó$áåå«Cœ»T„Ôsä@WÑqxëû€4òO¾hµ½¶¶ÝUìh¤¡KÃíÈÞ6ç‹•[-Cß6 ßñßñÏ<Úõ¿ëõÿCÒ‘}ÕðêÿcWbbn¶Hßp|W[ÞGûÿ!zŒòì˜|x@Bú“É3ŽÉQÛô—Ý;/hhFøtã1ü5ÒíT;7:€Á#p{Ÿð¿îMÀÂ7¼ëM»º[¥ žò JJ›úí.]åAWy¤qä)ø”–º‹·üÒ—ŸxQ•ã<¹Nfmä''çXJ½èðÇÇÃIÃ(­<­çÛ* nÝYë8UžÿÿΙ]ÿÏ;¹Ö×udíé'Ï®ÿÕÿÕŸ];«ÿ×þ¿kÿŸ~úOõÚoù™4v9(Ä€”tZš.dÄåHQB޳õQO¢ÙÍIÚ”‘âBù…—rxu‡ª;?&j@ÇЇ˜´!Ž^艾Ÿl}Ür Uÿ }”mù0™ qõòSN;&Œ×c9C«"ï„ÉXyùêÕ_¹Ÿ3<ªˆÕ“¾›2ÒÒ&â\òGÊ–N'{Ê<€“]2½¯ÎìBM^ÇD¹^2 |›†Þ·+ÛWó `ŽŒú2é;þ;þ»þ³nvýŸxý°úõÿÚÿ³a‘Ó±Y¨ýúéù«× -€ ” # ,àb 6ßbã°JwètÀá䬨;FÀÍS—2©güµ„8v;rx ùìVœd䤓¨º;/BF€Cýä °™<ò+;‚äÈ3¼îL’}ú€LíôhC?aí(8ri]€áÐðÕ‰˜é™½ÊÛ¾älhñ*Ðn?I3É5€+ý?²õå¡øÈ °2iÓäÛ…Ðn¯q®ôƒº”×vå}«Ñ·íhµ};þÓ9—Ó_žÿ]ÿ]»þWÿW/˜ «ÿÏtýÀ±G—uMßè«÷Ýþ?ýû¿ùák†€LjÄÓYÏDšÎKúe¸àñÞrSFÇ*Ps› A0ÀÉëDí.Liò•SP Íã½VÙÑQÑ%“#Fi÷ú•å @ø)¸P×É@;TFÀ0Šý'Àäj“\<îmwqØñã–x K{5oS§ #Ûðè;º€.à§•>ñÅ_ðÕ‡PÄ—Üúž Ú8„ w÷Î8Q}7>ê¯Üî] ·Ÿwü|ïøïúÏ*û×vý¯þ¯¾7;ªGéTºY|õÿµnÆö´¯Öþ¿ùÖœÕ}ë[Ÿ}úY&‰7«ZDŒxŒûø”Œ'“k Iב5ôÝE)H‘Ç´Íœ‚¡Œ€‰ûä¬ñÇ Oë“>@"JÂrÞj>@ ú”ÃCÙì†MzËWv¼ÐFºKþiYêîÞ ฿ÛãÍ ¡Myè€çã?NÝúNÛ8rHw4 Tá Tµm‘áiÒÜC»OûAùôÛø~V¨}-=2ZÔWØÂ2$¯špìJîÒò3†üë2¾>ãøÒvüwüÍË]ÿ»þWÿ¯þgjKc;.›ZÊzÖ&­ýÿÝöÿéÏþÓ^ëPÆ]§1öŒ6gwdàNÂ^^Éõu;¶€â,GPçÎÕŒPŽï ”0Þêp ÀqÕ‰FœŸpw¦R~ê-P*-„¤®Ž D>€ÈÎMÚ Mh<Âw>å•‹ßSNõæö®®¹Ï†qxPÚ‚™½KKÚ׺¨õ—>%ŸËñÜ„ûުʖ¼IWÞSž“â­/OÆlüܯ™ª(ñ2†@07ÄO:¹ðçðKŸíøïøïúÏû®ÿÕÿ«ÿ×þ³¬ýŸSªsyš¡ÁeŽ'œ·“v °O¶@@Ž£f×ÃîNß²+ã=9côƒÅ;ØA x˜±¡¤W øË³C–S­SŸ´y á (Nì|K Ñ¼Æ Ä¾tt64ø…œ×@ @™:Ïô8¢ÀÆg2Gû㦬v ¡:KmÕüK¶nåÐ+ç¸Ïù­@ñÖGFá>ßš*ÃcÀW+Q9mãZnЃþ]×ûfèGªìz{h‹Æ‹“Ý6îÕì´‘»;X £2;þ;þ摹°ë×ÿ׫ÿWÿ.XûÿÇÛÿüTN7 € Œ!NzÇèGñŽÁ~yG‰¿øð¼€ágô»%JxL:° l Ë€‚‰óÑÕ'´Èؘtç]iñºóèÐc\/mŸÈÕ¦‰ô>—¶’S].»Y·zË|Ëò‹s' Ð ˜švHW€©¼ýfdešä“[øþø,È”×6’¥w®„µ×®åJ;Q~NG¿réÃÙ%TF˜lÂx7ßOëTnyMßñÞéÔÏ;þ33²|ÏúØwýŸoïú_ý¿úííhlíØg_0«ýúἋe¶Ê $c÷Þk„‘vè{ßû^Ò Nj¸c¼§üdÆø»Ë$B–÷à=aq»)@B>þµKÔž¹È3Žìm_9ùi÷´•S¶àb2#-™:®rø súHœ#;þ^z&Ž£2‘khðþå§¿LßÛýL•“nn;õ¥°²œÖ‰sîl5½eøø‘¯tÒ8éëÿÿ]ÿ»þéˆê„êKJÞ¡CVÿ?ïô¯þ?›ì »ÛÃM\߬ý?öÿé'ÿù?¼v?Ç:Äpˆaˆ§Ã,:öâÚ=ŒzñZçÚUa¬•EË&ä}1»>¶ï/ûdÜkì•{3ü >å2i/㮃§nGi¡påX/¿ˆ×.sùKæ GÚLóàU~¡´–«^¼É3D/ôvÓ’®Ð82*‡¿š~}ÝÍn»„9ôøJ·kfw ÏôÓáá«ÿ¾xs¾†÷Ðu•}xL:÷Ozz<œü:w³ìäiWÛïøP¿AÞÜŽÿÙ9ÜñŸy2SÇ\ÞõtÆ®ÿÕÿ«ÿ×þמþ¡öÿé'ó¢Ñp†¸w“0|Î7éÆ Ï¿‚yÊ0èŸ~ú)“›vÊ9Æ~|¼É/ÆÝÄ•ÏÅ¿pA.” S<€t€Z¿1GFåÉÛOZø¦ž©C=Ê9Ê̺£•º§ §¼:/ôÊ܈{Ôß§r6OÝî 5Â+ÌG–»S/§¬¸6à©_µ/iïb&K˴ΟG•§‘—ghŸö£y¸¢Ç¤-hvüÖ÷þÝñ^»—úg×ÿ®:­'æÆêÿ£ïõ÷ÐÛ«ÿÓtëûbÿŸ~öÏýš¢ÌEôë()àãºåNUAŒŽáB?6,*G\¹£4;L€BÞ¬>é¹›5aFŸÑªñÇÇnŽ<çÚêRŽ_ÀPÐѲ3uG¶Ùuºhñ|ÐLvÛ”ÅÛ#yÉÐzѧ —<ê¬A½Ëþ“‡—>™BDHÙ„¼ã*»ä;/w{È(M›=œª²ªìÚ×¾çkãà²G»RPÙ‘‡Üx ë±¡3®<"ÿÔ{ïÿÿÓwæ‚~Úñ¿>Í<ÙõtP×Юÿë›Ó«ÿWÿ-ŠÝÛ³ö?fö­?O?ø»Ÿ¾î·ÑfàD‡±ÒŒ?# (=‹]$þ‡ÁÐ1ÜìÈpÊz šÂSú°1»0·»V@€Ý&<ð÷0r5tÏäÔ#ÝÅî2(Kpu‘O=èÄ˯rQ~ÚrùÙ™¥“=<§üµ±¦È‘ ¿©¯®u$þœ ÑD¾æã§¾ô×U8}×Eëwí"qÚ ¸b™2ÊÏ#®Òø÷G9ùêñÈKý2ÆE†9"4žòÒßÓV|wüϱíŽÿ®ÿ]ÿ«ÿéJv‰>­£K³C7yuÕï‰?'?tzó£{Wÿ¿_öÿ§ÿå?άçÝ(`ËÑ ƒo®ä¸îšI& GùÔ€d&Ž´1õ1ØÒ ^äubÃeç°pÝCÂS]è¾ùå§ß<|Ÿò¿ƒ—,„‘ЖÇ?åÎ…0~ÒSÏødG+ýƈô)èê<‡–“ÞZFþyÚ¦yJÃ;ôW€µ ÕS¥€R<* úð¬?ymË=ﮜèôG1t7â«Âvüwü;×výïú_ý¿ú¿ökíLçmÿŸ~ø÷?{E@E.Ÿoĉ{ì2¹pÍ Œ5£-̈»€>0Àâ”6Ú‚üå„]®†BìØ¸¸hÜOåB¯>ù½úè¼§gÊ‹7_=5.q÷›Qê8 gÀá)¢ãø• ØY8|ÉÃO& M˨+ù“^0¥Üqp¥® “‘¡@Évª<ý÷ùgŸ%Ý=3ù&uv§ ù7iu©ûŠ”_yJn˜Ì ¯´Y|åå¥mÓNãÊI?_xއvÇÇ×ÿ®ÿÕÿÑñt¢‡ž]ý¿öÿ÷Ùÿ§Ï·caç£Ëà&P•üÛË0‹w×EPèSãÇ}"Þ_;Pþ¿øÅ/Pð°«U§î‚­€?còÀvÉñÖȦ±\A‘pפßP™S×€»bq-ç>Yëo[Ú>åìØÿ¤8ýw%ÓŸ¢G­øi“od~ç;ßIßÿò—¿ (ò6vò¢}×UéÚ©>µldk>ùÞýv¦4»X\ÂS}ÝŽÿñúÃÙñ?¨ô‡yÒ¹/¾ë×?ÂUçE]6⡯‡ÆZZý?µú?:ä}²ÿO?ú‡¿xMyæ7ø.€TÔX3âðQƒnQÝ•­|ñm]ÀÏòQ®qi¢2Í!ó]4ç‡ÿ àÉ)›7“Og—' ûñ9´ç¸Ò·Ãshì¬õÒ{ÿÈÈÄÐAg7 `au·?( éçxð·I˜]¸ó®©–kÙÐ^y|þÜiúíHü…Õí% îbu÷ ½‡Óxz¼1¾ L¯d÷0TÁ}™ðÖ¾#‹o'ÚÝ{Vxïøïø›#\×mæÅ5ovýŸ/»þÏî?âáèáÕÿÏwlõIí\uv:kþXWò=«ÿÿ´íÿÓ÷璻Œ‘ï29ê“ìÚ\ ÊÕQÎÊT)÷• €È̤YŽ-ö¼Åüìä¨WWYz?Io· BG–"áÒ‰W^¾rèÓ¾«äL]Oõ‘ÑQ¨z½×JÙÈ ó ´ò«)wø€™µï’]܃WÚ1@‰S¦OÛ×ôì*M™æ+ß‹îÒÄsxräç2W¹$ø3ñ¸«¾ûŽUøÏÜëÇKzÓÄÓ?ÃG½íO¥"?GüÚ·ÒÕCæ)ü{ÇÇß|é|6WÌó¥aóIx×ÿ®ZÈ|Xý¿úÿ}³ÿO?¸.¹S˜"'Ì9†ËEqa†v\òì W‰8I¶Ð)[Ÿ^å/òH`´9‹O5÷®”»Ê3öøÂÐV™ãáGž•Íq#°4ü^ø­ÄñsŒx½ò€¬m~ã´]•_>À•æ”ÃGßÈϧò‘¯nÔÆ¡¹ê ¡k_F±\u?ò¢íæ´—{”Þ ðõå¼¢×vùî ñÉÎEÚáY?‰ó§F¯q2päºûÒ[oiã7„z”¿êÁ£2ïøŸõqïËÿs4ÝùöX[‡»þ£÷¬Å]ÿó%§Õÿ=̶¬þÿ·mÿ—ÜïF¡†×±ÙˆŒ]5Ø1—q.pyÂŒz€€ Œ”Œ÷(×cxpa¼ge•s.]ÐSÅw«?!£.àŒRê'zzñÝ·ñ¦²È¤]åÕ‡ç\–Ÿ2­GCDÌÈØµ‘O¶È?ê$ãÃ`à{µ«`$ù“Æ¡çÂsÂüòJÆõ§r$oh¼¬ü6‡o_ý\>Êq_ìuÜó›Ç¿ËÕ°ôȱã¿ãÍ[È}×ÿ®ÿèˆK׬þ_ýÏ&­ý?6žíe7k¯ùOÞƒUƒÊ—Xcœí)¬´034Yh´ò8`L(ÆY9àJïŽÍƒvÊÌàó¸<:¼ ² äÜD¶aÚo¾¸€¹sf;ñuÐÑ+Ûv‰sxÚõêo¢)Ý= \<¸s mhhww‰ð”ïn[Ñô’~·¼¶Ìx¡ÓG7Z|ë*C@×$¦_®ÌÈv…¥7¯ò´,’wË«£ô;þÓß;þ»þé˜]ÿÑ «ÿWÿ¯ýÿæö?orgP„†×BzZ ãILzi¥ 3ÌŽº”“”oÁåÉÈTLY`ÈŽ W9ð`üÑóÝOâ«'bÒ¦ÆinÂJîSMÜ.Øgó~©;@Á?/ž”(^ò›F6<€Á–oÛÈ›> ªœH@ã´kêÉqçU_Û:¬Ã×°Êàušž4<ã.ZmT¯²\dÁwÒÉ_™ä©§rkÃ4$q[ÍÍË·‹V™ôáÐáãy”Ÿ¼ð@t¹´uh¥—Vš0>;þ>4ìø›]#æÆ®ÿ£ëvý?ëzÆ1?Vÿ«?nõÿŸ„ýúñ?þåkƒZÃÊPr¾Æ|˜üu «4¾Ý*ÇlÀ„] €&ôs'Ê¢AºYH\ùó¥çùø_Ï­W/_¥Ì…Ž‚vÿ§îaÀçnUÃÏ$,òPÇ=<Ç€/_¼YKà5i/g§oùd}Ð!/€*8û¶7Äã7uM±” ؘò•A»ÒÆ<^@Ù£s'½ý Ùå+¸ÓnípgL=ä Hv®<¾ºîN\: Eî1Zm ¸œôû‹DÑ©¯ýÞú¼íÛñ×Ep¾ãÖTç‹ù¹ë>lìú_ý?s ökõÿÚöþwÙÿó[„HaÀ=k8``‡E¸Å(Cí :zOUÁAŒý ¬äÕá7J&¯¼ø&°1o,Wfu§>?-ófä‘ç’û€ Ú “AÙ¶ƒ¼Žå•­E:z® ¤ Hûô^ÊAü.,e9i\eO|Šj3ðær|~þføÉ“¦oÔ£_ÓVr^r ©,ä,ÿÔáXsäðTN]£,º´wÂò'1cÄ@ª{—/p‹Nùò­è¥içŽÿŽ¿¹`~™O»þÿõD¬›®Ckr×ÿõMmºêú`}×eÕQÓUÑ]òÚ‡üÕÿçôâÞg¹Ö2ý©ïVÿÿÏoÿ?ø¯ÿý¿ýº;H j'¸°µC’‹ã3áYƒZc†Âí…òO>ù$o[÷íü8õ8>Ó'ò¾v´¬IL]&øidz]?:--üFJƒ|axËSoT̤ëO«ÇOÚÖ~UÆãhõþvwüРÅG8¹ÄëË×FN¾°|? ô«ùòÀŽÿ¹¨¯vüÏúÓæÓ®;ãgG{×ÿêÿYÑtêêÿµÿ¾|÷»ìv°¢8.…êSƒIdòxºƒSÃüHÏÇŽçÝ@‚áÎÅëñïÀ‚².˜Pžâ®Ã¦<›—¢¡SÆ£îîôØ…Rþ@œã@¿Ýg‡È¥v<‰î›‰W> fÊpj—Æá#ìé¢y @Î D‘XžÛ!~xÎKB§=‘s¾ÅÈçÈâœÑ¡çt&=þÄÑë³7Ó²ˆÛëï$â)y Ôu“URúmrgÄR¾tÒ“?<Ö'ó¯€êäNy23.;þ×üIŒÙñÏœ²>ÌYó¨sÉ„4_ÍsTþ®ÿ]ÿ.€›w½8 æÎêÿÕÿlPuJçÆŸ’ýúþßÏo2Í5ÆZN‰Ž×…`±0úŽã€‹Å–o]Ë¢Â0(]áû‚6ÜgðÜË 7^Þ•ÁÎ%háÒÈC®8bdèŽÖ9c†oä™<ÿÜ•âìidÄÏÀºÅU|=â54èîéâœ4¼ Û¾Ä”Ì¡üW¯ÎËP¥‘«N¾Žïî™tàGû<ÛævñZoÛUÐEî‘àŒÏÈš]¼Ù5÷÷Ñâ—]¼9rÌ¿¡M}ù³ã¿ãæ±é`žîúßõ¿úõ?½Èæ¬ý?ö²v¸8¾”ö°ÿ?˜{–X‡0w&¡„:•’õô>Q€ÈÔ!¡æíâUϱP`54âÂÉ›c9.õOZÇSšã“Ñ«kýêÈ2quÅQÞËyÝ^Ωsÿadà ŸñÅ¿=ùTêþêZâO>ÚÈ4iåIKŸŒ¯Ý¥CÓtþ#®>´#£wr% —uÚàP†ã®¼Éî ßÃzÈ&0¢‘yâ½`N™‘ßT'#¼ðk•7 ó'e‡Ž“g¢ìøïøïúßõ¿úõÿÚÿ±‰€ýŸoþÅk†”ÑUcdû1Ú“.Ç€ã€pK“«e F²s€*‚¬ ÊQ!6Ç:)7åË&‡3S<@Ô=u‘Y$ÿò#ß­OÄ?|1—âç_éðÔ–ö!žÝ™ ºÅÑup€»SøH–òé`‘ÅݨÉsŠ÷[í¹Þ‰5‰:w©4HYü ¢€e2v|½Êж}Ð|ü”ïCc¤&á)¼ã¿ãŸ9eòìúßõOÐ]«ÿçƒðèÉÕÿg>°%ì{Ãvðc›Þ#û€Uc ¨è„­‚“€‘«£ôY@À‡²”¬W!xi¨O9@_¾Â1ÒÊ@@»e™šÇ°KS¶Ê*­4äÈàÍ æp“§ž¦|òº€Y„4®;ãO…IU¶».Idêý-ùä+0¨'Ÿ²îItÒ•ãÂâò…ÉÕvIoÛì¦á-¿yݹ2ù=Dùó´}|­6q @Sÿ¤•‡ÞÁ·ÀL™öWêš8Ú8üûŸŸÊaëîæ0º z0yw‹q¦pù@@ úÄÑ Œ2ï<¾Ò+L€Â¤·N<¸ú‰\qiM¯/¿²%ìÏÐå­ëÃêŇó~®©OÜr°«&à•ÒÝ…¨î?2ó9íí§´‚Gõl _XiÛÄÑCê¨Üüòlºþ™ÄôOÁ˯¯ãN4A¿ãã%¿ýyxQòS·úýÿÊpÉOúÙLþÄÇ"ì®`d#ãU‡xÇbÇÇ&K\טùµëÿ¬¯]ÿg}ЫÿWÿ›kÿýýmö?ë,›£Xi9žªA¶Sb·É§ŽâeÝEroHÜ. c~1C_€Ðo­d@OÁG ÏÆñ´Iyέò?² '=Æ`@IŽå†>va€¤°¡ùø“ó&ø;pÒž*O<<ÒÔ#m.¡*ÇË›ÙñOC;Ä8Y*ãËùÆàd¥ žèý(µ:Ј£€ÀÆQ^ꓯn]ê‰_ò C(IFéÖò•¯>N¯VÖøWš¼Ð \nÇÇ×ÿ®ÿÕÿ«ÿÙŠµÿÿcö?¿Eø0ÄÓ¡±Æºõú9–'àjŒ{ ½Ý¯p× ø€`3ÀÀТ @¹ÀBïúL°ãx‹{О:'H¸žËÞ'ÞðÝ:†Áá3Á~Êv™Lá?é}Ÿ¹GvÞïçvȯ>yÙYÂsœþèÑ[ãZÞOæòK[‡^}ä¯LíS²´_ÂÿëÝJ÷zÕ“/]§d'íeê)˜ íPQ=Êi—þLè€<¼RvòË_ßÙ­ÒxUÖð›ÿÿóAj×ÿÑ»þϽÕÿ«ÿ×þsûÿä5 p°}¾ˆ²dÌíXäc¼ÑÙc foH·«SC3é³õI»€™ò ½ç¾ÿ Ä+p/Ü8pÁÀyɪ vbÈX¾˜‘;4ã{ë<¹ùÃÛ§6ñóoÚ;qw°ÚÆÐOnå®,•-e/9Ë·27á&ƒ¾“§Ÿ€ᦫ‡SF>ZiC’]C+j§Äq|À©²ñ›ÎOýã÷“©´:´<üÛñ7vüÍÇ3¯výÓq»þ¯Ý]:rtÒêÿ£{éÖ¬ýr ӯѩÑ×'oõÿûeÿŸ~àÇžcœçëõzƒÁ-q˜—fŽ’‘á§pì)VÜâ œ£Â‚ yÊ9"ã‹\àÁ™ qÿWi÷|DC“»V·‰þ#‹]²(ÄkÂÛÙ”È) 8då2·cQmyÝãÊN>—<¤“oGj0H€þ^$zD9àL]ÓÈØþÁ+Ïdâ§ý\w܄ɯ¼§òãQ‰F:à(QoU¶ÊÊoß•S©bI“Þç$žô‘lÇú|ÇÿÌóo×ÿ®ºdõÿ³Ž]ý¿öÿ±ÿO?š÷`Šϱ¿` aFØ"sÌÅø0Ø1ì|`é!èz ]ïDI¹¡Áó]~ò*½Oë’4LÁ€xäM@þ1Cr3ÒìÐÔ‘¯”@] ¥ìðð36@–ú®ž;VPÓ{gÍj}ã{òÚ'ä÷mÄ¢*`gügæ^Ûðvé^Ýè”ÕÏ\ëi‹ÄßêÇP¥“ž>´–¿²Ó'÷røpéç‹gw­*ÿÝŽÿŽÿ®ÿsï´ër×ÿêÿ‡½=ºúííglñ̉§ïÿíO^ˆŒ•ɰ÷®•âî4 è¹ À¡Ž2®"ª//eH$ÿÀ¨Ð‰“ƒŸ×&Ì·ßì¨¥Ž©'5]~ëf%¶ïåÛ¶æÈÃ,€ƒŸùxu½å]úË—Ìàã  T¿°Ý­³ Ç_ùð+cÈ/å†0ý8%¿úòìÞ¥|Ñ­ý¥/<ÝÉ›ÊÓÇ åÛ…œú§-vûJúløeÌ&Ì—®. ²áįºÈÔ]-ém¾âá5aNxÇ:âÖO;þ»þwý¯þ§+WÿûX{¶öÿlèÜíÿÓ_üó_¿fDj É…vÆ÷¾NBĤ'~`á‚ F¹†šïiº¦áÝ;DMç3èÙ‚M)ÔÏû©¤ ¨{dmM÷¾Ü#÷ÅÇn“cB4Ú“£È +‹ow¬äˆ_YÐ{Û»:9íú øð²S‡?p„'|¤¥ü„íšél|Ò§#›²êa´UN‡OÃäâRnx¥­¾á9´ òE?áÊÊÇGÏéÃæ­üðºÊÜ ÿÿÿ]ÿGGYs»þWÿW§®þ¾/̶°_l ;"¼öÿ·Ûÿ§üýÏ^3Á:ª_¡°2<ȶ­ú¡õ;fT÷yÖüðôÕ70v·8ôžÊ˜>›6À‚ëN”ŸÂ9—hó;‚“•>Ú $Lþ¦á§¼0•ëN™ÑÜŸä_ý[yRèús§Õ&ñÿÿ]ÿ»þéƒÕÿÏW'Vÿ¯ýg6ÿXûŸÖøÜ 8àñi5æŒ;ªæ0Fvƒ”4ÍÃÀOänØñëî–E=„GCà¡z¾|¾oû©Gº´ÊF.2Ië @¡ié”pcGíñCÔóÏ?ú8m|È4µ;ÞË=®©‹KÀÑÔ'ÿ;R¿´k~ñå§&] µiã€(üµ›ß‹ï÷:Ñâ/Íxä˜rdÁ·àïðÚ„ÇGïáêßÃÍ/ïÎò•~Çÿô>Ùñ?si×ÿ®kaõÿÑ «ÿ>Xû?o÷›ìÞƒÅp;úc\ï–1ì1,³ L$ŽÑåf;EòzÆ¡aŒäY€_ö( à./ÁISZÎn•W#5þx“£¯AŸ Ÿó§\åƒö ÐŒ+ØÖ®ÊFÖ|[n.ª+«LA…»R‘]Û¦1W{ðA H4™Tx(ï‰ñÐ&­¼•ë¶iÛÕ;ô§ÌÙ±B«œ¶ziDnÒÔ«~}d‡Nœ›Ú&ûPIk]á‡æjkÓëk/vüÀîøgÞ˜W愹aÞxvýïú§WVÿ¯þ7¢ƧÖþÿnûÿmÆ•{5> `1ÀŽÒÒ“Æ—¦c9q.ñ À8ÚãüÍ>O™òÀ»/ޝ, boú‹ù¦_^ð‰vò]Š¿Ë`'eòÎQÛiè»ÆÀ¤ºÉ¸Y9¼´]\›ï€EXš¼´q„j›ï2Hà8u”¾íÀ£ýˆ'°•;bW_´ßÚG§ü9þD™§?]¢Ô}@Öi“rc|Ï»®éø +×:wüwüÍ—]ÿÏXvý¯þ_ý¿ö¿öœ~d/9öS:'í÷Ùÿ§ŸüÓ_½žR9c4©€`ÁÎQ+ˆ?w©ø­¨yÊJS±rÂ¥+-ŸxLè&Ρ2\DW–+P€,h¤y8i0Ê>”á ;Wòîò(ÿåWó-ÃÉ5Öµ‘C£<TyÅíeq O ß…> ±G”å#Oõñuff‹|EùÞ¦ÚåZÛꛜÂê€R×%_Ž>léQmRžã¿û¥@-wᨩ\úù&çäO29cV¹vü§ÿwü3ÍÃ<»þwýÏ\ ;¸Î ºCݳúÿØžÕÿÏ»ßæŠùaÖ¼öÿéùß¿ÿÚ·ÇÜ]bÀ–é‘ÜñÉŽË,* ÇlpŒ0—¥v[\™ã>´h,BetowÐàß%´\(^nÙæ1üdóH‹œ×bW=_}òÚ+ ’Aþhä{n‚€HiäU>4ÒÅ픹üŸ:†—ãºy kû&|©qè"Ûµ{†Ov°’{ŽFO'žö'ùjZ.m¹ÚÚ| Ï‘*þ¡Sæ*‡¾eC?zo ½ö“‰³ ¨=;þ;þ»þwý¯þ‹1zwõÿÚÿÿ¿ìÿÓþñ/_3¸ îÕ¨Kgæã_?lÒr0cÔ=Êݸ'¼¯p€È„cÔ¯“§Sd×çDSGù|4?wC|ä4̧ë:eÉ¢@_œó÷]/ó%‘9|Ï[ÕÉDé€3ü‡]¦)4ý0€Eør] 9©oÊÚt*}1´díu¬Úò©ÿê+4}ÔݲdB§Q`§MÙ]»Ñâ¾x]齿…7×zùÆìó7Ÿç?ñ‡"zõæþ֔ñ<ðÑ÷êÇgÇÇ×ÿ®zŒ‰¾ÝA—ЫÿWÿÇŽÎ\`CX¢Î‹µÿg3#ý2}SŒÁÆrO?ûçÿøÚ%s–5 +÷,°!`ˆ'#€„A.(@ëŸr5ì#É›||$q´á‹ºÊ½þL¹‘«é~ ÙË6Éñù¼Ìô­ú‡^}SYîá§|ëæsÊJw‰Ã­‡+(Á 3‰î®môÐj_ê™]4up)C>×v÷N9ïý¢ëÏéw]úO¯ôÙüКéõáÓ6¢© è”ç´C:y$Oôå«ù9¢ÿÿ™Wæ cºëÿùïú§bFQ̼ˆ.¡O.=d®¬þ_ýÏ–°›g>œÍˆ„g~¬ýŸþøóÿã'¯ÞŽY<À†·sãb÷Xæ,,tŽšthÂc¡í°À´ÊXˆü† RyšÆG×A²˜‡—´ý ð€íê÷ïþ]ü/&œwQÁ ÏÖGޏIçš^¾Ú£ à¤-ÚÊQ¨?ÿùÏãÛiÊyñÅ ½þˆL¾ûíåÕ…?e¦?9ý* §_À7©#²L^¿¹)ÿöM&°´«¯Ê—|älù!‰¦ô©^í–†oe‹¬®”ßñßñ7ßvýïú§#Vÿ¯þ_û?_꛵Àſ޾Û}iâ¿Óþÿx.¹·c™1ÅÀB]ÅŸc5GhùYša…<„ÀŠü‚Æ;f~äßã£÷´ž¼º ¹lÈ”›¢Âù9™ +G6 D}êÅ'¸'-r]õ¡“Ž/ùV>nòúm:ïÞzõòUŽ5Ñ*—ç’E]Ê·7Z§“„¦NÿÞz…”'^‘uU¸}¢ì™ÐÏÀT?GÎKŽ{;É4Ê0m_N[ZGû @Ð<4iÛ%“ðŽÿŽ×å®ÿ]ÿQ$—ž gèúzõÿ9Xý¿ö?kbÖÈo³ÿ±Æ2 Ê•QÄsçhp@á@øÍã«ÿ“og èPY}eg„_€ü¼1~êð#Ê_²†Ñ*÷áÔa÷E]w0!üá¼ lá1õuÁ+§¼8ùmKzÐ}|ýPs.ÜOYt/îäÈ•z&íå¼™ý‹7_$ßÑYJߦ? `ôGý.Þ×é3ý7DuÜ™×XàAÖ´yú­ß8,ÏöWêÆÞН~mêƒ Ã#m¸ÂäÆIïÑ`ۢϓ>4¥Ûñßñ7÷výïú_ýÞ¸úímæÿˆýŸ#¿fh1óÉäîÞ5Üòã,B´cð{&Gù lºCx€S‚2ò]€¦ð“4$ãÈÄ)G–„‡îN/Ü>wùä hó𳃕×'ßù䵑£àãÞnm)øÁÇQ%¹½ÐïSßóñÜ$¦žÈwšñhCdŸ|­ìdv™F6y€h@ÒP„ï¤ùæ# ŠŸ4Æ­OTä~€×«ô5Z.ùÓ^>úŽÛŽÿ™K;þ™&™æ˜ùQw_3©wýïúÏÔ¸ëW â«ÿGßΙ…´úæÃûhÿ°,Æ7¯4…pr-F8ÎD'Þç1y®ËÝîu‡¤åðÍŽÐeÜ | ~Gj_~qîT¡÷Þ)ÇXh€fpð+@¸¼“ç’‹,h¹–k\ىʅN8íž‹ÞvÛ8t.}+ûæ‹çŸ —G^N¹~âR8`QûsÊ„š2yeDûT’vúP¸¿µØ;RÒ´Øâ€'àO}ŒÛ£ÞIӯꖮ-i§;q“'Ÿv¾—³cf *»´ÿsÂ\±ÌÇz™4®ó,éÒÌé]ÿé›]ÿ´ßùàÖyC¯¬þ¿ÖÔêÿ£[¦Þûÿô—ÿçÿöšBýp¾•Ö»9´…´:È‚±x¸(ÙICsî c/‹IÇÅM^þ©¦ @‚†Q·ë“o(¡Íñ¢Ð=Ž)xiŽÎŸ‡,=žœCW'þ0dåQÚñå{ÈD?ô ¤ôHÔNGa¨VÒ•©œÝ1B[žäMxäHÙ‘Z›•+]Ë;.ìŸü©çÖÌoÄM?iù>ÿ|^Ép3ziû0UOwñê4 þÌIDAT =Z>yж-â@¤21 øïøïø_Gçæiç–ð®ÿyÿÞ®ÿÕÿ«ÿ©ƒØ:ŽXû6W~›ýŸ×4üõë÷Ë×€WÁ2Ðò¥×é\ÿ'ƒ&>þ•Ùrü†ÑÆà½‰PP S@ÐA°¾ b§ `(p#ƒçÎ;uaœ¿mèCf¢’Sþ%šº»NŽýÐÚ5Ò®Ê:NÞÈ>t>8FxW¾¶±õ¢iX9aòÞÃu—G~ÛXÖ#@¾z:&Ê¥ýÊL_¹C01Ò…ß©Sy€ª÷Ú*KÛ ^¾­‹Lu;þ;þ»þwý[ý?Jqõÿ±¯ìCí¿á÷ÙþçMîv68Gn1ž‰ Pãÿè°é8 ‹Á=†øí£„G§^ùäü9.“‡îîp Pߎ˯¦.€Ækòm=ÄÊLxä™¶ ²gÞÏ¡F´XQ.á1¸•tL6r€@Ivˆ pæ(Ï|š™½42jO¾9=¦Ÿ´OrrÚÕ¾qW 6µêh¸tä¨Ã›ÞJP1»W©³AqØs>ªÎ6AÄ8âñÝ/g;L Ø¥,¨ƒÞcÂYÚˆsž´m *ìÌLÁ‹?ùlhË¥^êÞ´õëàËW=yåí£¼>‘£Áž mµOèÀ·ß~›,—>I½F¡»J‚%ü]øÚ‘’Ç'ú¥:€Wž‹Òìr¡#këÐ'uʽÛëüýEíÁU3õ¼—KŒÙ•§;]ʲÊÒ¶ÈTîøŸà¨ó„Îvüwý[ë»þ×þ¯ýŸ/Óëÿÿ«ÿÿðÇùcÏ:Ç^ç*â¸×/_'Ì15g¥8ãM•¡“ªi<Æàô ž >d´ÝàÇ}vLg7¨þ9ç4å ží“»2Ô!º‘d‚ÿ¤òO¹½$<µ«NÚš²¶Ó: H®¬ låFo·  i"xÑ÷ÊËWÀª.öuôC'h€rzÓï’±-û”Žðêá­oÒ¯²gÛŠ§Ó~ùµ¾6ä?¿àñ;þ;þ»þÏ‘®›]ÿçK"=¬ý_ûÿô¿õ)æÆúÿ³IQÿÿỿþé{ÊbH€¼ÇF‚7ÁÇà€´]X­ËAwÁÁ,¯^ècÆ¡Q–]˜IýúM»ÎÙí³PçO¦âÑzçÔHAP&è½ê*¸GþÌ=Z¼Ë¿4µÙ1‚ghá嫇îNUfm“£}{µ3íùE¢sK‘oîý1H“ÂãŸ@iʵS\Û;uHûfÐÐÐ õ+#¼Ç¡ö/w¯Ýò«Ìð•3ŒæÃY* È)=õ1‹:ÀNšê¯»uôÔ~„6ô§NÚšûœA»râUyÒ¿)W^N­c áÈ3…yìçÞÙ¶WøR¶ã_uDŸ;þf×›c5GÌ»Î_ùâšîú?ög×ÿÚÿµÿ'¨o{§þÿíQœŸÿŸ™IØ0²ÇÔžÇK}£ZÊF0ЃÝîÁ3Á›ÃWÇ!n©ˆà‡ü Îc¬ßίãÒÖ||óÍ7 L„½Pìý¼b`v´3 dòØP}4ø?4/À'×Ô½tçþ­OÚí#@ºˆÃ@ Ô3M‚•>z£€Oëê/$ؼ r»vämÀ@×ëÅ굟‘}pÒ‚|Û%¯Ì®|e®îÔÙñïœ8ã×1”îøŸYe.ïúßõoÄæ\[gvÀ­ý_ûŸsÌÅ»÷ÿã_Ïv.âÑœ(3;+s_à`”qÐ 쨠³¨@œý,¶ÞÃá ß:pe~7yeþ €Å%/ Lœ€WÿœKŸ©;¸Ü÷mëyééD (žmʃ„äÝÏ%ƒ­#}ÊÝúMÕ¡/º‚#‹¾ö?åäï£Dtîüé-ÈÌëF4Aœºx¨'%¼ûèlpð…ȬïKyiÈïj}õ¢Ã˃<ÊÑË£ÛñÌïÑ ½ô¢?y°ã?sg×ÿk½ïú_ûÏŽ®ý_ÿÏG<ýÎ`™Œ„¿³ò–tŽø« 8@—Ê‚9¬­' Çõ˜`uêBÏqйLùŸ¬Aäü ÔQ÷ qmyÐhÏÙ¢¼ðrˆ9>÷Z¨cÌãÄ+KåÇ·Î’òLÓ;þg§–^vüwý›YC7ÀØõ?_ Ù¦k‡è§6uíÿÚkÅœà_ÞƒÿÿÒ£¯_/£¯@‰¦ˆ^ê¼cK8ÛÙ «8¥ûø*ʼo—ï#ˆ~›±ðä»Ýûôã?ŒóÂÓB…W¿íËàz/Ur¾K ¢ SvëqŒêy¤(X2Ð} z΄ ]eÓZÐ~=åpà—ü¹C5Ê$öÝñªìÚlÀƒž<}MCû×|Ô¦¾Oú”áíÍÕ~ mÿà#äÈÝzRe c>é‡/ìZNfÇÇ?㬟“ÝõÏ6®¡]ÿמÜo±kÿ¿È>ØÕµÿ'pZÿÿ©ÿÿ’IµÛâ_2§;P‡ÝüË¡CÜ€C¶ßJä·¬FI !Š·È-œ ¡yÁH~åöõLÜy<×GX LJ— óQ¥m@§˜÷fŸŠ:úĈ¾äQÚÏœ©šš9»4õ%²dçkÚAKfÐ@íç+ 9ÐÂW¾œC©We2Î@€wÏmôL¾”NÙ}ü–Çvw`ðaØ hÛ‘gÅ»¬~þéíh”¹ú²Ò êÔïŽRùt€ËS9yÃ{RåýÕceÌ#´aPyCó¢=;xùv748}J»Ã«éWƶÝ4à”õ1ž:-«ƒ³ ¯|-ˤè\äú➌®BÏ”nÇ?šÍ8íøïúßõÿ©]a7¢“I×þÛ”XûoN€õÿç¨PâñCüúÄ£›/9ÎÖŒ©ÒÆ)‹ªø—3†Oé|L}ùùÓÌIѸL…ÿuîðî]b ß @¾APé?o¾à/ø–•Ÿ_j¯ÿä'Øëc>x; ÷=Qä ¯9”_YÛ†ôÇ  xíWË´h§Kݼö‚ž†þÅcÊÝÛ|"Syükʧá›ÂÉ?ÿ¾€h¥ðZyÐ{²Gïî§åèÝŽÿyÌKG;þfÄ›-0‡:w:/Í®× Ì\Úõ¿ëíì*[=°öÿl¦Ð ŸW¿×uò^üÞËÀÙúŸ Â`ÞI’™25°Ò^Êb|GyS1¤ÙùåL°üÔ÷žÑl1Êv Ô©rýAbï…R>ŒCƒ¿Áäy¦•#r2üóÏ[ÔK‡÷éô1ø¶/h+o²œ(ó<ÝQh¡µëäêëÚç¶S9ÐêmÞ¿IN´>¬åÍÖs?ÛXÁÕ9¥îÔw(VËóóþm¾˜Ç6LÔBëÃW?R:*­¶AËáÕÛñÿ*zØñŸõy×è™)ç³sKÚKIæÏ®ÿÑñSÕÉ®»;c—×þ¯ýçã®o—þÿ»ûÇž)=G ¸Ô¦Ï` Ž»Ž¼ êÜŸ€ =ÅzL&ß3O¯GqãÞñf”¤xºðPÇ‘ ï¶.ÁÃÐOüz²Hõ\ 27-ßî/í Aó3caÌÈ8]e•?ý™` ¯æC8øiþHôÈ!ÐC'ˆÓî¦nÛÆçYO»¯Ã´œ×a˜C󉮮\èÔ#ׂô÷¶™3EW>rÉ…‡´ íê®r6meøô¹ÿÿ̹̇]ÿÖÅ®ÿµÿlæÚÿ÷éÿÿ $ôn>4•IEND®B`‚qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/background@2x.png000066400000000000000000006507741347155106100270070ustar00rootroot00000000000000‰PNG  IHDR° 3à›sRGB®Îé pHYs%%IR$ð@IDATxìÝÙ²9’jfn™•ê÷9jUU×ЭáEZêIÃ¥.dÆ ]èe¦çè£Êdfÿbý;Hµt¤žLUå c#p8Àá¾ÿgÿé¿ý—Ÿžž^üðÃ/>|ÿý‹§Ï?ñã?¾øaçŸÏñý¤£ûâ‹/çŸ}öYÒš×û÷ï_¼øìÅ‹¾ÿáÅËW¯Âç󡓇^ï[ÊKS÷œ¼ðïûß¿xóæMÒ¿ÿáû?þðcähy±r-Ûsõã•0õ©[½=¤kÇ÷s4Ï9É”ÓN² ¥½š¶_ýõ‹×¯_?Ú¿><§½|9íÿ>¼ôWó•ÿ|èÕKN2+‡_e–özÚýî»ï¦ÿ^¦ÝÊ h>ú|d=å•S¾²é§wß½Kÿéÿ†—#ö+WþÒîýßû¿óç?]±úÿŒƒÕÿ»þwÝõí¿µÿŽ/À~dÛ²Yk7¯ýÿù‹§µÿ×ÿ[ÿoýÿëÿfqá Ö !¾Å¬ Öiÿ§øÏÓOÿì—o-@eìüå,Wîà†s•´òW¯ÐœHå‚8¼\_é¤)H"þìó”†f(™sñS/þç„ ªlŸMº2®´o¾x“kçxGŽ!z7:M¹«ÓRðúÓ´ð“?íÂyåéÜÂ|o£<} ] ê?þðâõ«×` xÕ:Ò/W¿¡—î¨ç|he.miŸ«¼½+WàL>o˜¼xõòUÚðå—_ÜúnÀ°<´!†Æ$ºn½Î÷þïýßùtŠy±óÿYçV÷ЫÿWÿw·¶X‹²–LÜô]ÿ¯~Ùõ?6ÆÚkÿ­ý¿öÿúëÿ­ÿ¿þ?âï‚ÿ<ý³ À²C‡£&f„A ² €¦ K˜—O‡¶†kË@jÐJ<ÉÿþûÙ¡4€ ¾——ÝCÛi¤ÞîŠÂ³¡à ™šŽöÃð)“Vž©kò€J”ä£l™]iÚðÚ:x—¿rhì³ãIºþ‘î¼}੬s£trÝÛö¨ghb¼}vhR>RŽŒSNPÿQx^ü*ËsÒ>; Êéùh+£tO‹ÉóúÍ×”«C~S{±÷ïç°ñÔq´óç?€þ®÷èŽÕÿ?æá€¾XýÖ¬%»þ?lc#aâ]ÿ×þû|í¿ØwùÕÚÿQt'›kíÿg?OÇè“„‰Ù ‚¾Zÿïø’úb:iý¿ËîÐëÿŸ±ñ»îÿ?ýá¿ùÅ[ Œ¶EÜ $.µ‘‰Ñ'ªÒ->ÂÃ8›ó:»›WZ>çX~&Ü”¡ŒÞ½{ÐÊ,Ðe÷’ ùzäºï.R<ñÇÇ<éM ³IC—Á<纤IŸC=WÆ£½'áÐ:ÇÿÓEE_I×oo²ó øFf€¹°ÊKõ«HÚÓçgÇ—¾!c ÔfòÛ>iäe]¹¦N×ݹþ­úíÀÂÊùîý»<ïöwéxîýŸ›{Ð~«„öåÞÿó_?Æ®ù“³3®åë3qóJ»óÿôáÎÿÕÿ«ÿÏZOOìú?àø®ÿÙo)Yûïzp»ößÚÿkÿ¯ÿ7>ZíîõÿÖÿ_ÿÿcü';°+ 0ƒQ (ªÚ „&“èrT7­ñÓËçïiHtY<{-Æ÷¤{¥ðÔŸô©Çßr"ü[#'t“^Þ¹~@iCü0 -Ÿ‚ó .?N=–Ð48Woù…çdJ×O÷à[]©ôÚÖ×°Ê×N+4ò‡r~’ÚN²OMᙺÐÜä”Qy´/‡~i Zyð³+îÔy^Cì½I%½ÿí½Ó§{ÿ¯y6ãU0~Œ»Ž-çMk¼óÿèŸÿç)©qcœ˜K«ÿWÿw<ˆÍ‘3.výï¡G­×óG[c®wý_û¯vªqa¼$ž?ÆŒcí¿gûÛ*0œÙtõQ:mþ迵ÿÛg ­ýt®^1ŸÖþ_û¿þ|õ­q±þÿÁ/ô‰þ¸ÇÿØþߨן™´ÞM?;ŠÞ$6 (œ¡| ª<5G^€ÆµéŽÜo6Þ„2>îÞÃþ»o¿ hæ5·/çƒç©kþ|õÕW³«ixZ¬Éq$"7PÆÇÛK’m¥Ê£ÁÿMÒs˜<ùŸÍŽ&|Ñëç6©€&Ö‘c8¢úM)mµ£IÐ/>-«½ú }rÝp4òí:#¯éâç­—¼ »º¤Wæö2{ÿ;&Îýë=ïý?£ÊXÞù¿óß8ˆÎ¹tÑ!mõÿêÿ¬9G]|dìíú >]³ëÿÚkÿ­:ÿ×þ_ûŸM¹þßø„ëÿ­ÿÙNÖÿÿ_à??ÿË?~ËàôtÜ«{›<ÉǤà†I‡e€›¼Þ§ggá¦ÈkàÐôºÎÍÝÑ)”p”üÚ!4 ˜0'<±—-s“7¹q˜1¿’~l¨?z®Çÿëÿÿbýÿ¿=þóô³?ÿÕ[*íFüºȼOÈNP@H•¾bçõ=Xòñ@Mò´Á3`Ëüa~ÝøÄ)ãù£²êÀ«AÙOƒüÈ9S~áp9”HÊOº¶¡q]ž)sñNÛ§L'[u‹RÚ7¯Ez5&;½Ì»¡Ð;r=ÿ\“K^ÚzÆìÀb œBÛúÈô)o¯þUÖòÔ†{žc«<]+'06^îWSÇ\ÛMN Ç\„nïÿp÷þïüßùÿlÑÑW­þ_ýo\ø'ìú¿ël‘ˮȠ˜?ì#:£6[mí¿³kí¿ ìê‰îc§¶zÇPíÙ^‹ÑÇ>^û?nÔÚÿëÿÕNë|YÿoýÿßUÿÿé§`ðì1¤ Mã2Xð%ƪóY<üS â: à„Q{ñŽ8§\»àô:ü/^ê+ø$? ÊÅ7õ#¸B¯÷Û+Y‡_; º; ?AºÃµÝ[‚Wëœ[0+kë÷Ë‚ò…×ÇÚÃwxÔ #C xíר„ou;wÌšX~ò….â• &ÝŽ,¡t¹˜?è}U±ùm3:ÆdÞ«:ùèõϵÁÞúš>îÓüKÛœ]î|â½ÿúvïÿ´Ææ5ŸÎ©ÿ;ÿéŒê¢:nèógÆMðÕÿ«ÿéÔ¬33nî¡ã¥ñ®ÿ§wvýŸñ2]AǬý÷ü¸:×(Yûoíÿµÿ×ÿ³VX?×ÿ[ÿßúÀ>¿Æ„ë¦ÇÎb§Ï¿ÿ›üÿ§Ÿýå¯ßôx„¯Q(nBÓ`Î.”È{ì‹®´²úAte}ï@ ‚nÎ2u^’>iœ‡Wõä;†écráÖÑúÊ×uCÏÅê@ -#.²ÛA ®Ô?¯ ÖÉ&‹sáÞ®ËÃy·(Ã{xiCvlMýéƒ C/H‹<ÓêuÞ´¶ïP^]=ùBèæ\¬ôBø]yç|êHÎùsÏ7]“™¬‚ëùó¸ŸM»·ýܽÉÙûÿè÷½ÿg/í»ôÕØ£ëÿeèdÌèÇúGXÿÿ·ßÿúù_üúm@èÀÆÇ Ô]!˜ 17€&Á;Îb“ô HÁ‹ž“‘ sYÐb´Üé”Ëvlj=‰|0X¡+ÜåqÞ£ùâc¡8ùø$\´çâÈ¥þVä(èä\z&:™æôt7¥ êV?Àk“ö¤ÍóÊ¡ å…¤L™†»ì©Ê¼»b2Ô”_úÆm'ŽMk¬íêÊû9oä¹õ‡üƒvíýïØÝûÿñÜ2v2–΀Êx‘ ùc'kç¿~¡K„ÿÓôË„Ž!sKÐ7÷¼Õÿ«ÿwý?±¥Wwý?z"ÊâúS"¾wšÚEkÿ­ý·öÿÚÿÑ —¾¨ž ;Øt¬óøH>3¾šóµÿŸõ«>ÓGBtëå/J[ûÿôÓúÿgÕ5w:‡Œ—έž‹ÿ>íÿ'¿B'bê¯ÓÕÁª²OCÁ’¤Ô×`NÙ¹Vö^ï^[L”¯Sw>.~¢7c´Å‰)àsë Ý#¯¼Ä®óáñaZƒ/mÚæ{ýOZÁ°ò/Ÿ(*ù@)ò]|Å”äͯ&Îd×Ñ1Œôš:c“ÐidC‡äœ|¥ðu¤/&–W™‡ûä$k]‰¯z‡IòÅw¾x”úòoZó½b(%y{ÿÓúCŸ‰÷vïÆJÆË5f’0}46ƒèÒs­ß ÆV¯wþïü72Vÿ¯þ§cwýßõß8p¬ýwìIëfVÏYC×þ{v†Öþ×3F±¹Öþ§7Öÿ[ÿÂ\ÿÿø]õï£,æ9rOëùïŠÿÿ2Æ0c4cãÕòžs>ïç²)ч‹:äüûù'®[gõnœÈsí( gൎžspÊí§õËkð‹i -ãZü^Îkx4H¿óó á»wï7Ú+a>°î咞º×áü½ïIMÿµ]•M¾«¥¬[òåµ¾²³kþÝe*ïµóZ¬Nþù÷™ô ŒœaœòÊ9>åuïÃjÔž~2˜÷þ§ßöþgH|4†îãIîÎÿ£̵ÿ«ÿWÿïú¿ëÿÚµñ¬‘kÿ‡Õú„Í[»·ódíÿËWZûÿá³tŒ¬ÿwìËõÿ>~ÀS¿¸1=»þÿï·ÿ?ï½£fÂÌÿ,ÀÐ"½¡¬¸‡¼€%” „|öã™|V¾±4N0‹ÓÛ×áºx½zùjÀ÷ç5¿‹ŠL Ï=®‘P3ÿ¾Ÿ«—Ž<§ ³óiÒ[tJ±¼Ébw”tuõ—´YÒ|äÒÑŸ·l›[Oå@«µ^»l¦Þð0Ìî­ìþò}¯É«óŸ²sÝ]]å‰Ï½žÓ›÷«>L”¿‡–—ž>¸â€]­º…æGžéï½ÿ¯26öþ±óçÿÿD·TÞuMôÕÿG±Î_:uõÿ1,wýßõß|Xûo²®ý·öÿÌ…µÿÏúhÁ\ÿoý¿õÿ¸_›Ú¼XÿÿÿyúéŸýòm£tÞ(Ùv ë»Óâm;›q’2ãÀJj°*OQ¬Ð‹½Žå0¤@)@ÊÀ'ø1úÅòò”±Ã„wëB¯Ž¡WQå`()çäßò-ÂϳãJ¹ü 8XêjPC^åO{®b=OeW}­÷Í›7‡ßiè€dê"oë&“ó–SïãÅ)weÌN+ «K.±r}Íí~ü7í½êìÇÆQƒL<Ä ênÿI«œ[F^ûýÞÿÓWí³½ÿ;ÿ£Ovþ¯þýºú×ÿ]ÿ×þƒ*vSí©µÿÖþ7j7²ë×þ_ÿ/ã¡~ÙŒõÿÖÿ_ÿÿàÁo`3/žþÙX&K>R â¼6gaEøùÓ ‡LZ_å>Ÿë÷òôûYh”…µ Í÷£f›,àC^¬‰ûŠavI¡¿<…Ö‘ÝQØ©¤<ÀF^/çx+OñKw­n´Ê4<Út¥)+¿<œ?}~ý* ~s­ŒÐ²bôAû È÷4åÈñj€/éÚàuÂòÒ#ðtÕ5…R½?ÇH‘Ý\§îâ%”úöµô×.°×¯^çUIiÀ&2µöþŸñµ÷çæÜ5ïœ b:E|Ÿë;ÿWÿ¯þßõÿ®vý_ûoí¿µÿ×þ_ÿoý¿±™×ÿ_ÿÿÿÉGÜ9e×à.`¦ÀÆ÷;^Îáu‘î \1Ô¤qì@Ó\ã'OüþÝyEðl:Î Þ@‹¼²CÀ«uŠ•w@õµô݉¼Ÿ£+¡£8ÈZ9Ð 54ÃÀ9Äj'¼€^“îÚáZz1<€zv„ @ —O/Ó4ê¥ÞÒN;¾ûöÛìäd½~ý*‚Vö0"ßÔSùWîÐÜþd·›þ™2µah”m»ÅÚAN1~þµMuÊ÷þïýÏð2žnaçÿÎÿÕÿ«ÿwý?ƨÆ]ÿǾ[û/«äÚkÿ¯ý¿þ?jý¿Ûf’ñ;ùšëÿcýÿ). ÆÂ ‹øûÀž~ö¿~Pã <®§¢ûw«^ÍÀäР)˜••üʹïèH€+ ¤(W€­ôy(0ËVŽF+ë(m ÌŸ^‹ Þ8÷õ¦¡-]ùX| ìÈÏù Æ/çû\MG+àËx¨ì:k]n†Pþ÷vIwMɉñm~ÛÒr•ëÓ8¼oü] Êù'DN}@€­¼å‘>Yå“#<¦Üx”©<{ÿÏxÕ‡újïÿÎÿÿ«ÿWÿïú¿ëÿù„µQ`×kÿ}l×ê¶ÃÚǯÝÙ~ µ9×þ?v¸~ê‘þ¹õ‘kaíÿç~hÜ}šõÿŽo¸þßÁ:æš[ëÿÿvûÿy…0nžÙoá 0çUâ*Ñ(Ë:òQNÀðcÊ™eBÏeÌ´¼²ùÙì X±˜7à/¿uY@FxwÀáßzJ[Ôiø {R“vÏë9Z48±_*T¡s2ˆÉïÛW¾Uù>­Wˆ¼”uŒ0þÂçj[_ñ“ÿnvCá%ˆïÇIÌߤßûþ΄Š\­Ïë“î_cZû¨U9[Ú62‘Fy×{ÿ÷þWƈø>¥íü?:fçÿêÿÕÿ»þ[k»®v=î÷?³¾ŽÎÜõí?ãÄøXûo¾]²ö¿áð‘í_›<Æø•w·½Œê—µÿ Ì'l?ê+6™£iåõ<6ìЬÿ7>ßôKýøõÿÖÿÏ<0€žùmðÿžþðßüâmçY”b&ùhÐ*K M'¿óLþKiÄH3¦­ù¡Vx8§P”;ËDók…å…<çí¬GÇ ½´¼Â7%Ñâ%M·>1!*çd†Fk^^ %îåD¶‘åÃûùPüЬ’M=5@Û.ù•UYçò¨# uª‡ì↓“_Kôjâ¼’YÞÊ´=•ýÓ´^‹[gËTñG›û²é®„òLÿLЏýˆ@¾#ü¦ü\¤œ]­K™;´ùUEü¦mý–YûI~è÷þ§öþïüßù¿úõÿ®ÿvïîú¿ößÚkÿ×'ª-_Ûõ=­×âÚäÍ_ûÿø£ñoÖÿ[ÿïò_ùÂÂúÿÇŸÿ]öÿŸ~úç¿zëfW)ö¼ŠÓµÐü(Z¤àÇäP® ^±VQÒA·¦Ã/Õ5ÈZN¾s¯¹å›WøŽÁçÛLŒ¾C—w0*e"Ïáëfq0dlh{ÚéÊ},ß?ß®z¯G*ç[Uv3…F[3Ê ÉùÆ–ôÔ%+rœ:ÕSð§mC›¾™²‡üšhøÏQÙ£Qÿ§A~iÂIÙ!j¡o¹€ÿö‹ºBù4nÚ½Ž¦‰SîjgdvŸ®C¾°÷ÿôëÞÿÿ™#3_¢Gvþá/2¡zоq¾úÿY'ßû'uý¹ëæÕÿçIa—ç]ÿÏ é¼ÚõÿôG猸!:yí¿tǽ_þ¦¾jþÚgôè;xÖþ_ûý¿3ªW×ÿ[ÿ^üÇÀž~>ßÀ2ð1NÄF„QÒ@ =ÃPx˜š`Q‹àâE\K ¡}\O¾óGšòW=]0±éBé¯ò‘!õOCÓK™¦ ‚sï@§ms­~A¡õ~? 8ôW{~¡@Í¿Ï}H~øµŒ<|í´úp_ò•S<€ðMî)¼~´ðá# »éÒ>J¶¹y^D£s]™”éyŸÎT–¤§ç ¨°N%>IÙiëÞÿ3Þ÷þgpîüßù±úõ¿u*ëímýÌú"ãZ³\g Ûõ×ÿ'ñpÙÆOÒfȬý·öÕQ›µçbaíÿÓy:}Ng­ýß¾˜xý¿õÿø®ëÿÜ ºô÷Åÿú£¿üã·@ èi PJbÒ9ò”D לôÒB;çÒ&‚Á$ßn&ç‚k4ás•‡ËxÐ.«–-_ÀÓ£,º¹–§¾ÖÕºïe[—ø‘~ɯ|ŽÉS·ò}°mRNP6 €h®[Wå_€ O×òå"ë”ô}-e½¦èu;t}• Ä×4­CÙ„©8¼Û?CsߦÂ,Ó§BŒÂ‹ßÓ‚»|xö¾Jwíèî‡ÈÙ.÷mh÷þŸq¨ßöþïüPgŽÎxØù¿úŸÚ\ý¿ëÖÓ]ÿŸm¸±%Öþ[û/väÚÿÛÖ aíÿc;ЛÆÈúÅúæ?֘Ț:¾íúÿÇg_ÿÆ‚_!4Q|ÿ©¿\—3àH ŽÄ—bñjŽë *€Bsè¥ß•±k£>Ý8{Êù by‚:EB?}®Î_<ñØšøNl¹Ë>pÕ_MœÂ™òêdtˆñ6QÈD:÷ ­w*Dê6‘êk»ÈL/‡>ÍÇ]€j=À«¼¶xÕÕòœd(1¤•o®§^}Ø4t•ŸLvf_H;ߪBÛ:Ð$¨ËÉÞÿGÿíý?£ÝwÎ̃ö‡ñí|çÿqÎÍ¥ÿGë:jõÿê:ÃXè:æÚÑun2vý÷ÚÚô}Ú~éÚÜ~sí@#M°ÆçzæÛ®ÿkÿuL'kÿ­ýOO¬ýlsƒ®t¬ÿ÷ vŒèkñúgHõ§ñÂ^Yÿÿ·Ãÿ{úÅ_ýÉ[c¹ F8ƒiç1˜\_4v òj`¡±ÓXãp­<# 4ùÒα²­ó¸ÌÏÉdÚ¡W¢õ(_ÃÃèÖ]IM¿Ç•_ŒOCëvÝÁ+6xÉ«4Î_½òÔ¾OÝú$ånä"Ï£Ìðéýl¤ÝS–üÎÛØ )½¼ÊYöþ§§õÉÞÿÿæÏÎÿÕÿ«ÿwýßõí?ÆÁÚÇv_û^£]ûý¿±ëwÅy¸þð!â­ÿ·þÿŒ‘øñë c£~7¼âáËßqÕr·ôßEÿÿ`i§]í¬@=×D2™ú½¥tàжƒÒ?é¬qVæ_À¨gœ(¯Ðõ;P´RÀü|ÞQÕ:?ŠOý™àC;w-ƒ™,–A´dñúá£Ü\Kkˆ¬®/ZéhÄŒrèµü*7Y¹Ò8ïk†Ò¾ýöÛ F)àæ‹/¾@U¬ƒ„ŒÒZ‡²œÇ˜û“9»Ï¦Ðù¥ÆT%æûT#ëazJÃK‹¯Ô“54íu•¿ó¤»K¾/6õºnØû~©Q¿è«öÝÞÿÿæ«ñ°ó?~õÿêÿçµ#ëÍ®ÿÖÒ]ÿMS›Â'Öþ;öåÚtÄ æŠ5UüéÁžM¸ì°!Xûº`íÿÆK¢õÿ>ŠþÈ„9:ŸêǬÿwÆŠÞÑ7í·^SÒ„õÿ/ì@gÀ%èÞ9þoÅž~>ßÀrSï!€üs:JpeÊt¢d@Ìõ‰g \ü²] Ú€3W§¨Ñu°Oeh]Ò³]~be*‹4õ©£ƒO^ó•Ký“ßÖ׋xϲ{Ñk‚ýV`Ê ®±¡ ž¨Þ¼yó‘ J;.yÐyÍ ´Bd¹hÐ÷5,Oç r…ð¢ S§zŸ²Èºx=÷ÞèÓ¦‘Á9Y\kCû&ù“ö~Úç£õŸæµ~qh'Þû?;÷þg,ÞÇÇÎÿg{çõ~ãÕÿ«ÿÏŠ»ëÿ®ÿÛ„=rÙ5c`Ä&[ûoí¿µÿÏCîÚWlos¦¾ÌÚÿëÿƒ—ëÿ­ÿOM\P®8ß¿žóß'ÿÿe@’[(Î*MÊ40á]ÐvT”ëäM ¹?@P¢!„~Ä89&ìyÅ®OZ’?埕´oêÌ7.>Ò{”ç]¦ò&_e9¸é¹™Mo”g( áuRW­‚øq |6ímyeüúàppðÇnœ¯¾ú* Êu/<-ÈÚ ˜ÉÃÏ–áa”€F>ðìÓ€V™)Ô3òM Ú¡Mô&¶i“€ÎY—‰k¸¥qþÃÈëú>È+cúçâ·÷_¯îýßù¿óŸ^ˆ#¬þ_ý¿ëÿ·y×ÿç…ìv -q4ÅÚµ­Öþ›qÙ–Öç„­ýŸ%õñG߬ýÿ¬Sî>Iu‹ÎÊšxý¿õÿŒãD¸Û©Ö éëÿŸ¾ù]ôÿŸ~:qèâæÏOÆ uXœgÜbiÂ&×à“ôÓé¬;MÁй úCQO ê/MËMóÿy‘ú7÷òw:pï1^º6$ç'5uº4)ggC°T>¯¤2òï¢ûî»ï^|ù“Ÿ„oËjµ¾ »°®]Nøãé×ZMúëÙ™åƒÇ1~dø§ŽéðÉ€›:È0¤ä§§'v.„ÇõXi¡¾ úŽ ¹ÏSh§m{ÿ÷þ#;ÿwþôHuÊêÿÕÿ]ÛžW’ÇHÆŒÕ(ÏTG]ÛwýŸ‡V»þG·Ð/Æ«ií¿µÿª#ºþÌ"4ÿ×þç_4¬ý¿þß(Ïõÿn¾íÃN½Ò\÷xÌ>ðeȲIN8›8\ׇ_ÿÿGxôët–«puÞG>‚´è¦tmû÷ÙF¬nÿ‡°ÿž~öç¿zKX7²õWòšf1AüJ/v( 9×Ïï¹+ßmmδ=Gß­€É¼ÿ™<=‡^¨,ÊËëžf@–^ìXã.DÆêÚÆ\“#Æ”]Yó¡õ)ã:QÆdD/´¾ùæ›_~ùå£=½Ê­þBÌj=ÿuˆm™2®çâIo}§ü´aò€NÕ¦]d“§DxMÛR‡òsdœ|4çÒ§ŠðKùáÙºÚ7øIS'š½ÿ{ÿgHñv‰Œ«#;ÿè½óõ¿9"¬þßõ×ÿc?Ä®™9¡?zníXûoí¿Ø˜Ñ˜·?36Öþ?¾•yr޵ÿõƒÐ¸ºäž¶þ_¦Îú×Z³þÿï®ÿÿøEŸA ªÊà®jxPÎçÉ}r 8ÇfJ“…éR¾å%M~¯[FQ<úDN^è§š ÈáñPX žyùÅÃI|\x3¥þ{|XT;¼ ˆ?z`“W¥·NiÚ2õ8íEh¿ûö»¯_¿ž]U¯r¶äK;2?ƒø©CzꙜv‘®ã+/ØÒÐ ®˜'QúøÑw“ŽOË„çðÖ¶€S“¯®¢¢Ê9€ v5”_eÚû¿÷ß:&îcÅX”nÜìüßùo<Ð9«ÿWÿÓY»n:‚ž…ñ‘.éš“±s+£üY³výßõÿÙÖ1.„£kÖþ˺<ý!^ûoís#cbíÿôƒ5dý¿®¥³’Ìk®cý¿«¦ÌúÿӵŢ?Ænûmôÿ³‹Áä¸ÿ¼­×‰4¬  ‡U(¸ÓØn ©Î°+H°s© ÔXù%Bùʈm£W¦ QÊ\Ž1ú*¡È5×ʤŽËn]¶üáÙÐt2U>¼+_æÖ§tò©wÚ‰/Œå/<¡%ˆéå€_ÒìÀúbvdùp»WõAeS®?¾¾(ç×úÔ©È‚ö.Ã\„Fš lóÑ;ošó¶S\z»N¹ITãÞÿYüöþŸ±³ó?seçÿõzíêÿèÊÕÿçáN××]ÿwý¯}µößÚ͵ÿ×þ_ÿoý¿ø´ãú%Zçlñúÿëÿ³øVÅ$ŠYüŸâ?O¿ø·ÿü-ÐÃûævì|ÿá|¿ÉSu;“ùvu§Æ ô1ó¦Æà$! ¤Ô¸±ó‡ñOy¢‘_ ª þ~¸>tnÒ‡÷ó z©É—wä~Þ‚íƒÓyÝï*Y.:UúIz–uÎÛ‰`®›Ö]^zF^4y]hd2X¥?È÷íµûJ¿OÙÔ©Â viáÛ>‘†ß§rµ®¦çñÔ¯íbyÎ}ˆ¾¡ý/v('F§Nu§ÿ6>PŸþ¿½ÿ{ÿwþ›/;ÿç•çù·úÿèp»|«“Wÿÿ˜õn×ÿ]ÿ×þ[ûoíÿµÿù"ëÿ­ÿÇvŽÏ}ù§l¦úºëÿ¯ÿÿÿ<ýá¿þ£·WÏ^½|õ4(¤>mf´Œ€›:wö*®ÒÊ3ˆ{@Á[^êPHöȰLb Ò{¸V7p¨OzåÙyÕº†8 Rdz2£N}ÏÏ=]^Ö§ÒÚ^¼´E¾¸uºP6´&轜z¿þúë?™¼k·|ü^ÍñÍ×ç»Yß~ûmøµ, ËŽ7mT¿PYÛ—I»Ò+oehߢù4¨[H;®]5®SÏÔUÙ÷þ?ï’ÛûÆÅÎÿÿÕ_tÎêÿ³¾­þ÷MÉ]ÿ­¡]Ãk7X[wýÿøÚÚkÿÕFeë®ý¿ö¿5ôîÛ¬ÿ·þŸµ³¾­Xà‹­ÿ0=rïŸõÿ7ùOÿí¿Œí5ëÞ|ò¡òh»Œf ¶‚9íL->Ý:*¯tOæGè¾Kùu6t{%O(ñFçº Së²+j2Ì<üJ…»õÄgÿŽ'qO“ðÁ»íékŠÒð!?Ù•iŸ)']Yà:ôÿäŸü“Äú,rÎâ͘SîÝwïÂG¹¶“ ®ÕMÜʂבi^œ6 ×Îà{yt‚²} ÔwºÈ[º”“ðàѶ<Ê^m ;™öþïýßù¿óõÿêkK×­®)]/wýßõ?¶ÇØ'½Žm3¶ÄÚkÿ­ý¿ö?_£þŠsá~ݵeý¿õÿŒõÿ×ÿ7îøÏÓ?ýÓŸ¿e`œa¦ËRÆØ'¼ÿ0ßxzóEÎ)Jåó¡/ˆÂpµËý‡ ³FK• tŽîyÎ{„vêÂGÁï@ C¨²Ci¡>äq.½yÚ´Š,ó:HÂаO¥}È2i‚Äs¨·H:` ­×Ku¯=•Ÿ|À-Û'•!ûI›*_¼zý*×x¶]dÏéwAžºËoN’îOÒ&n¾4ç‚vÞÝKÙ¥ü|0ý JžÎRN=v1õÕÄt¨ºæh~TåÔIæÆèÉÕXŸxm0ßáºø÷‰ á•vÍk”Êôwø`›:œ—/ÚÞi=oß5͵£²§Ïn¼Ô+¿u ûˆöª]~ÙñVïÞÿ½ÿ;ÿwþÓ¯ôÊêÿ££õEõôê+Ç »þûb×ÿµÿ̈µÿÖþ_ûý¿ky\ÿo:býÿõÿ‹a˜li=í¤ýÿá?O¿œ¸[`ó tƒô|6¯¸ý;á‘?Û—ó {^!ú¼@«‚ d«L¨²†ÄW¨B‹ïy)øÉô÷”«{Šeð‡×\œVM {=ÀÞvŒ½|òý§pI#—¸ N˦ýS>ò\ùø£—'Ý9þÊçõ½¹Î®/5LšWv;©=‡¦Û¤Õ§þú¯ÿ:¯ʳ{Í®5}Ô'W耥§¿ÜÖ‚rŸtÏC Tþ¶ 2)MÀ“<òk›€FߥüœÛs´÷ÿŒ½ÿ"ùc íüßù¿úõÿ®ÿ»þ¯ýwìÁµÿÎkÿ¯ýÏg\ÿoý?ÃúÿëÿÿøÏgÿñ¿þçÇ$ xa7R Íœxà†ép úx=¯¿}7ßpš„¼=„`2ß|R`c‘Csçÿ„®ú8ÊhЪ?²L" Í=<øH#¿2t·—ëli½äÙY%¼ðƯØ‘¦.<Õjp-½ýAÎôÉ”_'nä½ê£Ô£ÜµãúPû_~ñÂw©ÔÛP¹]«ãÞWåQúÄ€¼kûzûHýÚ€lxœs:Ȩܣ¿®¾e„íý?Ÿ¾ßûæ~ÇpÇûÎÿÿtÒêÿ³®þßõ×ÿµÿèõÿΛw–ýàƒíkÿ¯ý¿þßñéÖÿ[ÿƲþÿñ1ÿ>ðŸìÀŠ1~½b x"¾À"×Y»u순‰Ó?´ "Àï>ùµtå‰/G( ã~Îu!1¾‚²ø ɿʓώ'ùø¥ÌðH}¯æXXŸ²ë©u–§kò’?íK-§N<‹òçÓWd “>rž6"¸êw`éÊsïoH~˜A¬“–ëKÎ) Tk»ÉSšÆxJ:‘‰ìBóå)O~çCthF|eÚ?Ê(¯œ´¾Ôk ×Þ½´÷ßøØù¿óõÿêÿ]ÿwý_ûoí¿ØÇ—íÉVlXûÿøìèµÿ×ÿ37ŒÇúÇ—âOÄ7¥Áuܯé’ú±ÎãË_ºFÙôå•οUÞ\[ÿÿ¹ß~_üÿ|Ë 1 ¡ƒR¦Cš&6`¤)××üÐ  ‹³c ÕùE_ïìúqÞ0ŠsôêìÂûÝûÙ=tÉÕ"Voüä;:°¥MÂ@5×d™ØyA¡äL¾§f‘Wþ9\ãoç“×üð~v©)3ùb“¦ôÊ8\“ƒœÊ5´å,ô~ùÏ+{ê$‹²Ù=¥þÊ€JÒq¸ÿºSùà}?¿÷±:OæUÂK†ÒÊÂwêä5TfmÐodÐïBúwbuISnïÿ/{ÿwþïü_ýO'®þßõ×ÿµÿjK±j­ý·öÿÚÿëÿ­ÿ·þÿúÿ7üçé§ñë· -çK ´¨3.®!Æ(·õÊçÛï¾µ:ÐFáày?¯¯}ñÅ…Í v.=ƒB€åìØúö¼æÒ_=TȀ璩²¨O¾Ðv Íuþà…üŽ.# P¨FÅÓÈ ÌÓËó‹…ÊðK{.ÙÑŸpÒÕÙ'–‡GÁ'çåzÐàLÓ6mò ­È6r´¿åÙv:œh å[Ù\ßÏÑDæIJu*K}y"pk·…ôå£^ç=*ÏÞÿc„ê_«Ïöþïüßù¿úŸXýÖñ®=»þïú¿öß±1ÍpìvÕÚÇ~¢+Öþ_ûý¿õÿÖÿþL ½¸þÿùÕkýÀ¾¶nþø_!dx2:5Äuл+ ]vò}¦ÙE”×Í&­²v89§˜ðy„9/p4²Ë SîþàrŽŸ¢^~e°Ø #€Ñ«—ϯÞMFhð oÜ®\ãaW9¿úê«üÂ" GzÁô^ƒT!]L çùs5‰\ hòde€8ýÒWðš/Vÿ# =YÕ©5ö|³K¿èk€ZÃGe'1²5sbõyÓ«R’v#9ió]ËWî½ÿ{ÿwþðÖœØùÿüê¨þp¬þ¿´éêÿtÄ®ÿ»þ{мöß±¿Öþ[ûŸ#¾öÿúëÿ­ÿY‹è#~ìéõÿ& âoÿ<ýá¿þ£·€‡ ö( ŸäèÓ‘w°ôûL¡¾¯Sój^ý‹¸°ë›n·OøM,ÍÍs}?Réõÿ¯ó›E½Ñ&GË–¾@Óù5¿Ãßî0*]šî¶òÑr¯æõãå•/ÙìvúnvC}óÍ7‘×®¨„iÔ>l^Ÿìýþµ1ãpïÿÎÿÌ‘Û$´óÿèÓÕÿG·Ž²=úÖØ¸wø¬þ?kX×@ñ®ÿgÍÙõí¿µÿæ!óÚÿ±ï­µ5Öþ_ÿÏцõÿÖÿ‡Ôç×;ÿ}ñÿŸ~úç¿zkh°ÐÉQ`@õݼÊÜø8МÊn KÁâ€>ùºÂ{h„7î°HHºn‚4ü9BxÉoÝÎñlÝß½ûnd;¯ùàëS`èéh ÍÝ x# å†çfOœ…BÚçsNçxpT²HçÂõüx$}Ê¡r~Žùã[^m›z‡í?|¾MvVõ^I×#Üùž—„9ŸŠNݹ$Éé÷´gò{*#¹ÊsïÿÇ÷G—ꟽÿ;ÿwþ¯þ_ý¿ë¿5¡kv×qîÿkÿÕ¶b­ý763»tBmϵÿg„°Åç¨.Yûÿ|¢€½½þßúëÿŸˆ£7×ÿ=YIož¬ì:¯àyÅ:;t,¾¦*Ùœï6aà»RvDÝÓÓáã1^^áÐY̤9”- Õ4tJLÝ‚rhfѤq*ÉfAôäRÞ«¹¤cÔŠo¯AÍEøáåûR^퓯œƒ,Òu~m›Bx5P+Ó»:OËÒÆ§ÿr~•L#ú–é¹X;´[Üv©Ïù½ÿÚž‡¼“/('¨W »*ésvµ¿õâåð*fäUÿÞÿ½ÿÆãÎÿÿ£7躥ºBL'­þ?ëWuùêÿ3.¬=ÖãÆúç¾~Íâ÷X­Q»þŸþØõÿÙ.ZûïØµæÐÚÌÖµÿ…®ÁtêÚÿëÿÅ_]ÿoýÿÑ ¿—þÿ/çBŠp4ãç IwãxÚìcì: åcôYœKc¬2D«`ß.ù`‡Pöe“?¼Sçà>oE mi*OëÇ«òô[Vh@/“Úá#ð_óõ‹ï?Ä?iKéú‘füÓÆyÝoù€m*_1´ÎçO>\Zã[9ù~]Q9²>íׯN;} ](¯Ldkh_ë€Iê”vï;çäh½ø¹_‘ b5yx’Áñó³md«ü‘ïâ»÷ïÿÎÿÑq;ÿν ¬þ_ý¿ëÿ±+vý_û¯6ÛÚÇ^ÒìȵÿŸíðµÿg÷Ôúëÿ xýÿ ëÿÓ¸cÖ‡OTÁ%8ÿ§øÏÓ?ýÓŸ¿·Âaz\‡´žÛ¤â€FWz:iGô ð2€ŠP:å hÁnK@—‰5¢ƒ]~Òçƒê¯_×Dø’CêÛ!•²ßò–.è”7Cï× #—z&=çëu¢M®Î$gè&]è”J¥¾ H²óŒ\î𠃶‹"Å%Ë0¹v8 gm:ðvG✦®¶AŠþ« êhJË/v½ ~å©÷Cʃ†\sÿ´¡A~i=ßû¿÷çÿÎÿèÉK/T´Õÿ«ÿo·¬q»þgÍÚ:ýqv8ïú¯?Öþ[û/öçè6fmq±°ö­÷µÿù'ëÿµuý¿õÿkw¯ÿá??ÿ‹_¿-’W†f—NO‹‰<»š à„ö2Pïß©ƒ+¿êða” ãc¸ <$ßÂ…¶7¤×]ÐÄ&ìóñx‡piê¦ÐÜ@4÷s `Éâècä¥ÉÂ8i“¶¹v¨? “øBIÕƒGåÂß¹ºÅ½ )/݇ðšóW#CiÑãߺ¤Ç4m»‡ÈxOøä<ò\«®š÷)×Úw…O¯s?'ßý:i?÷ÀíÑ:„½ÿ`ÝûúÁ˜06vþïü_ý¿úßœ¬×:ºëÿ®ÿ±ÆžaÛ°iŒZ"kÿ­ý·öÿÚÿtÿeý¿õÿ¼æe}¨¿¿öv½þ¿Ùò?†õÿÿfüçégów€pÇöWÁ êó+}>èΉíGÕt¦ü>1¦±s §G™$êPWyßce‹0Ko^Œæ§4Xl1ÈÈláÍPJÙ9ËCãè5ºò‡è!¿6kûIe;Jw®ÍäÒ×zÇ5Ëõã˜t¯é¨ `4i)7õ ¨€#íþb'ô0|LneÐÝS#îÅ£¼å{ñQVÂ-T¶&=è.¹Õå~ ëùÞ}±÷¿cÇøÛù¿óõÿêÿ]ÿwý_ûoí?ö'˜ Äkÿ¯ýßq°þßy¼þßúÿ}È·þÿ,ÿøÏÓOÿì—ouòÝi ¨‘ú ¥çU3NL¿ 8N¹)&ô&« ã+ xäÚ¢w ±Éw®!hçø0 Ñ@g“vÊJ/ÀS^[†!íhÑí\«ßáš"u”æì:‚ÓÌ¢;h—78Źžó(šÉK;>œWkÛ—_~™úIÊÚÓã³yÕQ•µínÐ;Gß4õ§Îôî‘C¹x9Gß²úÊwÅäÝwáß Œ€Fèuë-|›khÈA®½ÿÇAÕ_ßïýŒ›ŒÃÿ;ÿçÁÁêÿÕÿ»þgY}¬ýgíÜõ?ëæÚ±Õô»·6—S®ikÿûÔßµÿ×þ_ÿïÙ÷£?Öÿ{Þô9Š¢>íúÿëÿ Åvž~1q7H$ú×Ðs¯™=ÀšÉê¯>Ú|•G׿Ü`ó¡tiê094ƒµÇ„SÿÔ3uõºYÞç³ËuP ˜óîý»€:­8¤eœçCéÚ7GëT~v¡Qv <äÓFåSÿäYhfâ>‰¬¬ä"óÄdΫ1hæ:u_òÈ#_$×êÐ9Ú&¹áßv\ôÊ¡>¥ŸË·¾öCùâw?oû’¶÷ïÿ5ðvþïü7VÿŸ‡«ÿg=ñ°ëÿ®ÿkÿ½‰@?²ŸÖþ;6åö·n¬ý¿öÿúñÙÖÿ[ÿ¿þ8¬AXÿfqP‹ƒIüí🧟Í7°t®íTà¦OŠ ´ ³X¦ `b´Ê\!Œp„úñÅO~ò“€3åoÇžè ÎñW^P®<\‡÷4`öÝ·ßåú€R^Ÿ›W9FÕ«×óKˆƒæ«G¼tvQiÃüÁúì*¸TöIïñý"YÛÔöåûWX£eênà‡w_%LþI|´¯¯vkwH}þG6|z¨]äâ¶W\¹œ7½uà›s¼RÉisNý™Pžb¼ÎñrÔKVqó´K›÷þÏøÝûŸ±ÒqhìtîŠ]ïü?;3_§?„ÿ«ÿƒÕÿ»þÇöˆ °ëÿÚY7­këÚkÿ BíüØ36Ä=ä¯ý¿þŸq ¬ÿwÞîZÿÃ¥?Œ‹"Õ)]gêãÓ'¿-þÿ“¸W¶AmHÏ,@Kh€hë¬J/`ƒŽƒ¨JPnh[‡4ߘRÖá‰î½å«ð™ò®½æV E¹Ê€¾²ˆLyZÇT~ê —L2þx’MŽ××Î+wPƒGÛ$SNZlÛ™eÏùäi¾ø£=Už~!We$oûí"J]¥ã‰/´-ß6û.˜þ¼ÓVæ~3ÌÏx~>4^A¤ÔôAÚ0é½/b<ï|Ô ÐC/¿¡}ß¶Io;ÚW{ÿ÷þg¼7ÆÜÄC;ÿŽÚù¿ú¿z³s¥s¤ñêÿ]ÿwý_ûoí¿µÿ×þö±êƒX7ë ‰ë[é+þI|”Ë·ñëïñbæzý?¾àúëÿ?àæP›ó·ÁÿÏGÜ *´U”Ms“¥U9 ï+vò ,í@aHëSEŠ¢åå½ûî]x1ÐDU>xÖh—8‰ã t‰|öÌ®-r„ÿÐH÷šžŠ)&òEžáÝïE‘Ímâ8IŠlhÈóáûH9—¦îÆÚ€_®‡Ç×íјüxÔý¼<ü„½ÿgìý¿ÆéÎÿèÿx«Þ«N£3Vÿ?¯«ÿwý7',¶»þ¯ý·ößñتkÿ{íÿõÿø¸ëÿ–MÉž:7æ$¾ññO×ÿ×7úbýÿóFš¾xúgówàäÖŒ’õPO~ÃT‡FZé -ˆ-#/@Ê Pßò:`Ðß@3‡¾å[–áwê82Hw ³‹¨ô@-þ€šæ+_~™g~$Í¡0È÷°7­C p*(¤hx‘Aƒç¯_D €tí(1V ×È霕”ħtâHyÂiãì¼òˈs]y©ïº•Uº2ÑËó+>¸¯/ìC7<Ów#?h¬åäÛIž¹ù‡ghõ¹ÁrÕ«žso>®7¼FàÔuÑ(#}ïÿõþÙû?s3£ûôGÇYÇÎÎÿÿGǬþ_ýÀÁ¬MÖ¢9ª/vý^÷­-úe×ÿ3>è®'1ýòç¬7kÿ­ý·öÿÚÿŸÕ‡[ÿoý¿õÿëüÿ§ŸÿÕŸ¼eô]ìg XPôc„@ D©‘4¦ÂG;ˆø¤ò´ŒˆU¾Q%O=~í ˜¥æ¦)t]ObÊ‘C¾Wà8µxå¸@ü[‡òå%ÆÂ-œ×üÎî­È'B^«Ú“ë Äq^Þx…ߤ5–ßôƇïNÓ6ÀWi¥× ‘Ösí€Â·Ÿ[Ÿôö¿´‚@øÈ{ÿáðÆ0&Q¯w^úVûî²â‘ûðÀ½<SiB<ZÒñþ@¨È6×êÖ–½ÿgl苽ÿ3Zvþïü¿tNôÒêÿè…êüÕÿ»þw,˜»þ;J_4˜#c\[cí¿µÿb[­ý¿öÿúôäú¼ÎY/æÿÝgޝz­]CÖÿÿÝöÿó ¬k#DŒ7À cÎŒL\ƒÂ€Ao"9ò$ë22úDc²nàPqй*r͈€R­«u'¾xÈë¾O_s>² }„K.9Éç]ir9÷º¡×æ"·zçp^þ¡¹€™»LL«/~úA&:´°Hríû>êt-]šYÉŸºÔá{YʵÒ^|µU|É…V}v«}ñæ‹4Sû=u–÷úÍù>>¾Çu¼ð™ÒÒÒ.ç¹g×üIBhöþ<&÷þϹƤñl¼SŽÿ;ÿ=Ť[Vÿ¯þÏXÈRrÖ1ëc×ÿ±.¹ëÿÚkÿ­ýO/Y;¯õsíÿË–¸Öúfb¡:4çc‹ÆÏIÎü¹ìÒõÿ˜ëéŒõÿÖÿÿöÿŸ~:¯VΨώÊ‚såz);y@væªP8nD@IDAT  C7Ê7—çš‚î!ô>n.þ~tüÕ9Sí+·óIzN“>GœæË–ÿp /ovœì«<ðø¤Ž¢¹öMµ·ýÊ¥ŽÉK›&J;/Ã3ùv£RùŽ–¶ ÅK;]÷Cƒvž}?}Æpó·ôÛðR§ò ÎÕù4€•và¯-Ê·ÿô±ð~ò¡ÍÒ_ÏÎ6´ú9m>åK®ö{îé\ËKþÄÒRÏÈ‚NŸ {ÿ¯Ý„{ÿwþg®îüb ÂôÇèŽÕÿ«ÿ­^Yˬ%»þa×ÿØkÿ­ýW»´ö«ucíÿKg®ýÿ l c¥¾‰8¾ÙØß!ºÖ™<@½Ðó—-¿þßùâßM§¬ÿw|]fëúÿÏoRý¶úÿùˆ»‰/ÄðÌÙ9w§€«K™Xx ¦ÜÚ(|¢dÎ.–€>Wž|×@‘—¯æÕ¹yïØ„z”:¡ò ~Õp²ÑÊ'×#oèæ" ‹QÒKƒŸkAYº.ùhŒC€Êá!Œä·tÍÃëó§);2 #—üðŸÌúëÿ­ÿÿ»íÿûÂc(<+“ß?‹(‘  ÆÎ!M¢K™¤Ü¥H(eñæ¼0Z âN ßÞÙ±3çQ:+Çù:'GøŒ ‘ãJ—€gø‹É7L '™xã«\hGªÓÞc9—//ÛMç\ý©oÒ¤+ëºé-¯]ΡJòÂÒ´)íºäl»b°MZ¯õÁŠ&qø”ï\=Îî9ÝÅ%u ¥éyùÈÝ,|q¦ŒëÜ—”›~žöú½ÿ{ÿ(sÆÈÎscçÿêÿÕÿ»þ[#wý_û¯¶•xí¿µÿƒµÿ˜»qü‹êÊõÿŽ_¨_„õÿÎ&ŽõÿÏxXÿÿïŽÿ<ýÑü !@ª`ˆEP4ê%y9&($ß«q‘<·DºðP‚×Uß4sÚAüaœD߆¢ôJÎuÑu<8çY4††|àmEø_ßošsN¨ôðöÚDö’I<å=”îE›úˆœ—®íQ¦òHÈ£/9½Ò UÞÒ—Ÿël©š²^÷R5èÃì^U|¶-ª7`ÖÕå- ?ß½ª<­çóÙ~¯ÐØŠßûTyöþïýï˜Ùùt…¹cþ GÑ!—îØù¿ú¿ú³sgõÿ®ÿ»þ¯ý·ößù‘¡ûz¹öÿysÂZQ{bíŸoYÿ¹þßúÿëÿ¼)çÿyúÕ¿ûoß½ð¥,À”,c P%"‰ $‘W Ê´XeÇS ¬óŠ^Ò¦ èÊÓ†(¼”Ã+sÞê(÷(õ9 °eÒ†øú0ú|Ûi˜á+ˆÉÖ÷šj®ñÔpË¢¡À)Óòa24®Õ+N¹¡wŽ×ÃIžäБwÎÉXyÅê͇J”=?•POúnÊhOÚDœK~WÙÒéd[ì‡  SxÏk”z_êW¶÷D¹Šd>òš†Þ¯V¶ó ”%0L$}ïÿÞÿ_csçÿÎújõÿêÿ]ÿÏ!¯ïìú¿ößÚkÿ¯ý¿þŸµ`ý¿Tó5ùœëÿ¯ÿ?¨I°‡bü)ÿ`øÏ¯þý¿x« IwWl‘Öï qf\›¸@¬î~âô0áüžÜk@­¿;ž4 öÉ0)“z&ö­ƒ~XOºs²hü‡³Ûjä$£ ,@«{ /¾:Œõ×9¯üâ$<¯;“‹¿t2µÐK ýœkGÁ'%FG©É«Ó9°ÈŽ6mÒyiÛœ'ob´xeaœº·Ÿ¤q"~@+ý?ùžZ´ïäEqL™a˜VxÚ¥Ý¯ß È8à•~P—ò(”÷«ˆ~±GMÞÈÐohK¿÷￱±ótßÌ+óÂá|çÿÀõƒ@¯­þ_ýo,æÉ®ÿ»þ¯ý·öŸµaíÿµÿÙ’]êÃH3>Öÿ;¾¬þi?­ÿ·þÿúÿÿsüçéŸþéÏß28¨Љ#Ä©£6×IŸ‰gL.àËGaÊ0\£†&€R¯¡ ÆròêvQœ ÉWN]@iŽïg×Pv$©è’É+ˆÒîõ++p5À¥‚7q:'-õˆS'àÒÈzàŸÉø$§m’…G¯ àù0»ö“Ÿü$<ÂsFé³ûç‘ÌQǼԙ8ç÷ëÒÈ èc¼Ï9š×€€;Lˆ*_ù‹ÉQ°‚,hÊÇwoü\2¹ÖeÈÐCé€Ò›7o"Âc—ÊÈ8ûòË/§µç„ÿði]‘ÏÙeF^²§´oÊþ êV^½Ý-'_: /}ß0̽TßÄWŸM 4i{ÿ÷þwíüßù¿úÿèW:rõÿ®ÿ–Ï]ÿ­ÅÖ`«¬ý·ö_íÑØ²ÆÅèËœ_1ýézíÿóКӱöÿúÆ@æÉÌõÿÖÿ_ÿÿoÿ<ýá¿þ£·‹Ç¨ái¢`wFx}4ýHx@¢™€è…ó›WÔð@É7©&vŽw< ‘ Ü:ïà ~òH‚<­PZ‹ºÐâ='É÷Ä•¶ £ÜCYÌùOyåÃæSNõæp>¯Ú%Øñ•0õœšÎb„™?|ä®r’þC@i §0"×÷æÜŽ(¡²9G£¼£<Oh\·Þ¶-÷lÊäûVCˆh(ˆFYê§Ü»ÉìÄA‡_úldÙûï»a{ÿwþïü_ý¿úßú°ëÿ®ÿÆÁÚkÿ±×þ_ûŸï±þßúÖ…õÿ×ÿÿq0«c›Á-þ1🧟ÿÕ¿-H°äz5ã`f Ž,аPe,(‹Øìê‘Hf$§Ôüò_æ:e'ˆ’Ø%íÄàÝ€—€OC•¤ëÒö•Â]ïg'y„îN*@ù†_yêØî¼ÊÇÌ•™2êKY¯(ެ^ÝSO¨‹ùÛO˜yÒ4|¾0KŸªÏ.e• ˆt*t~oÛ§m×}­ùx ‰'­|5€œúÇÑváFY°ìÍ€[øÉ»ƒthújæÞÿóÚêÞÿÿ;ÿWÿ¯þßõ×ÿµÿØcµéÖþ›ÏX¬ý»íÿqJÆa17Öÿ[ÿoýÿõÿéƒhüçé§öË·Nj¤z:ˆP€¯çu5r¯^ç¨âÚ(ßbÎXàÃ{Òñtî °¨üj 4&€ä\zwá縗ÅÓµ…=æÞ?ï cp$ !£Ã/üM8éyš¤>!»±nõ|ò+󚥺>}5QºvºI•·¿¬X™IwÀ®“˜Ü¾UU€)ÀÓU7YúÍ+çêî+ŠÊ•v2D= 0xµ4ýÐû£OÆ ¾¤½ŸvUn¼›N–ìô•ô«ÓÚç{ÿ÷þïü?¯&ïü_ý¿ú×ÿ®£Ykg]çÌîú¿ö{‹¶ö;rícá~¬ý|·útb:tý¿ã§­ÿ·þ?!´þÿ±'ª+ôý9;°þä-¢;†bxfòؘµhùöÛo_üÁüAÒ þ ÁÔa‘¨PÒ¾"OÙVZ£Îµƒ®„‚>ñL©ûÊô-)u ¦¾‚¨ŽðŸFˆñ¤#y&½í+þÚ °™ lÁ›ÉŒb´@ºÔq•ÃO=Ÿ x…kìø x=ê™k•‰\CƒŸóß|ý›ô½Ý[ý»t¯$ ÎñqèK±²‚Ö¹uMo19ÈW:i‚ôÞë½ÿ{ÿwþïü§#ªª/)µÕÿ«ÿ­!»þ_Nø®ÿ±€·ì vGl¶È\³sÖþ[ûÏØXûÿØÛkÿ¼aý¿õÿ¬ f }‘xýÿõÿg,4ü¯ðŸ§_þÛþÖ/ã1Pƒ1H85Ú«yíLLñ0d \?ú¬,Z±a(ïÝìZòs[J38/¡ ¦àñÝðóÄR9üÁ1Òe¤«ûC¿ÿ4;¿üÜ*Kh‘8çùCú){ýÓàNëÇï]€ÐU¯ôÔ;uöDe< ¨<ʑѢŒ¿š¼÷~®¦á¹ë0"Ý®/»³ðL?Í·°ðÕï¾;¿,x Ufôá1éÂãüªOùïm“&øž•ö ³ð ïpM¿y2(ìý?ßÛû?ãd†°q½óÿèŒÿ«ÿWÿïúŸ…rþìú¿ößÚkÿ¯ý¿þßúëÿ¯ÿ~ô®\câ`/ƒ7ücà?O¿üwÿâm@G_=c°å½nÀÀcþ|‘Wa¿þúë6ÝÙ$ó0eb_Á±/bà Ç@~ʈþÐS<€:èaÀ˜l1ðJyòv§ÙRÏö óªàËù š2‚òêî7 ”-xÔþØ3ôâÊÙ>9¿Ëw§‘—chŸö£}„§¯Q¶\bí¹ZÏÞÿsï÷þïüßù¿úÿ#}¼ú?kÊ®ÿ»þ³nÖþ[û )¬ý¿öü ~Îø4ëÿ­ÿg<Ð|Kñúÿëÿÿ½à?¿þÿê­Áå[LvJupõ=dß´*HÔ*ô°Yœ”-¯ÀåQ³CŠpý ½ó|khƒ7@ú \ÁÇn$y¶¦«K9qÀ˜)[P§eíuÊè/Z¼Kè(M»Å”ÅÛ'ô’¡õ¢qž6\ò¨³ë]†ðŸ<¼ôÉ"BÊæÁ'¡²K¾óòm-2JÓf‡ ‡j Vöé„ôƒ|²i#°¯í’.´ x ëk…v~ Ò„È?õjcûaïÿYlõÇÞÿw¯ïÐíüÖAæNæÕÎÿèØÕÿ«ÿ­%Ywf-ÜõŸ†ø8ìúýõØúBXûo¶®ý÷‘ýI¬ý¿öÿúëÿ­ÿÿ öÑ‹ãt<|wþÇúÿçÄ´åÓÏþüWo9©yÍnŒ NI ±5€+ÒQ•δ Jì×Ù†0ÆH€‘9ÈL÷ÆHQÖÑE©Æ‹o#$°‹èö®+Ån©¢õê°HzxN=Ò}¸¼@”Õ(u‘O=è\—_å dÁ›Æ™]‹ÃsÊŸ¥YG&ü¦¾†Ö‘ëçä <ò5?r¤¿®ÂêÊõä¡ý|ú¥¯Gj3`ËҨ׵vHßlå«Ç!/õ˘ Œuý~Eú{Úº÷îËô×Þÿÿ;ÿ0c.¬þ_ý¿ëÿY;ýµ–f‡É¬£ ]ßsýœ¼ëÿèµÿÖþcDzC…µÿ×þϳþ_æÃúG/¬ÿ¿þÿß ÿùÕ¿ÿ—ó ¬çÝTÀ,¯Ž Ò ÄNŒ†šÇæH^@i¥D’fb¬ h2ôÇ1´s Èr€åvºœßâ‚3å‡Þ¯ ¢E†Où·>å¦7"wâ)$ïÞøH{„¢¯bâ§M~Ññ«¯¾ Ýo~ó›€N¯íÈšBh? •CºvªO ¢ºšO¾OÝQš]XBΧ úå÷þŸo‘#{ÿÃj|'ÆGÇóÎÿÿtˆP]t‘‡¾siõÿtÔêÿè]ÿŸ–íúl6FÌÚkÿ±Á­+kÿ¯ýÏ¿©ÿõ°'ÖÿËü`w­ÿ·þÿï»ÿÿôGùÇo9§ÞM7!J£`ˆ4 Š…¥ÍÝ™•ï:¯¾]À žå£\¯¥éte¾øâ‹Ä>¤î:ü‡PžÎ•õÝ&AºàÕ–8N7À ŸC{^gð+„á94¾oÔºGŽL€¢WÛí†J½°ã\x¶?8bÒÏë#›„ÇðÑÊoÙЪÒî4ýuEü¢ÞÃç[Xù7åÒ¦á+è¿òÿáýäÂ=w ÕÜŸ‰ûQ~¼õÑhwÚ3p…ÿÞÿÙ¸÷?£§ó6ãbçÿÎÿÑA«ÿÏÃÕÿg÷²5Å!XWœïúÖê®Ïµsºf§³æÏ®ÿkÿuŒ¬ý÷Yìrý±öÿÚÿ÷ì]_âÿ¬ÿ—å£k‰ù²þß`ëÿg\ü¾úÿO?¸› 5ª ˆRÕ„iüt·‘4å,>ÊÔéõn7z@φŒ¹ÛhýòwâÑ©÷®°ðîûáò8PžVœÐ)ã¸Ó¥¾K^r+‡>í»Ú˜ER]O‚‘Ñ«’dÿñúõµÈ éRxùМr‡ß€"³öL‚kG”îðó*£ LöuÓ£´§Ló•ï‡Ü¥¹ÎÆ/Љ,‚ö&Oý C›pÕw_ÂîÀ½~¼¤7͵_ÇÞÿ½ÿZoF;ÄžÇÝÎÿÿô=b,¬þ¿^5[ý¿ëÿ¨Ë®í÷µ–u½ëÿÚcl=Æ=ºößÚÿÕÆÃÚÿëÿuÓÁúëÿÓ ëÿÏ¥_^¯¬ø˜ uD2YÆÈЏþk 2‰ÐÁqé9zç^ƒãæºþ¸PVVãÍÓÛ{°[Ê6bqäÁ{Ê©£2Š]¿™\x ®ÛQ¤~’Xýzê9ú ”|Ƃެ¾¶§,ÙúM |IMö¨3ç©ãjO¸þ´dw¸«ßyåEŽ·ºúQ`õ¨MëREwd¡š—‹!8½š«+館ïÓ£TäZWûVzä™§ðCî½ÿ{ÿ—Ž'çÆŠ±h¼ôÜxr¾óç?-d<¬þ_ý¿ëÿ®ÿÖNXûoí¿Ù½™AqýYûíÿõÿÖÿ[ÿÿl ²d®ÿÿ7à??»>âΨàp 50€>ùú¤_yC[§D™3@(¯Xpf¡ƒòCÏXIy·!wã2b.pÇ«¼÷®ÜU˜‚O”ÇWÙ:Ësñâý\ÊæuD`Ôð{õúüò`^3pJPÛåúñºÝˆUùå´òŒŽ‘u=ùäQøe‡æª'<†®}©|ë~äqôoüµ[Ð^áQvxyï߽ϮuË÷ °ö½2‘vx6–&T8WÏ÷–LBc²µ^çÂãþ9ßûŸñ³÷ÆÆ5ÎŒŽAç;ÿÏüºÏ%ýâèÜOÞÎÿŒ!:¦;ZWÿ¯þßõ××þ»*®ý·öÿÚÿÌŽÊúóVÓúëÿ¯ÿ6KðCq¿;]G_Œã5¯Õ=€žñ[)9F™&‡žó!–çh’‰6qw0•¿XÅDZ;Àp„ó«¬r¾ PP© Øw°ü"bΧ.ÎÐG½}bÃz7`O?ìî×ü(?25©¾Ÿr‡ç| ~Ê´žîÀ"§Pdב|²Eþa¤N2ÞÁ.yè ö$Ò„ôÛÄá9eÅå‚ëOåHÞÐ|˜>)?} ¡Ê¯/νѦòQNèõÅîQÇ=¿yâ»\=—9öþïýŸ±š°óçÿêÿ‡>]ý¿ëÿ®ÿkÿ­ý·öíx1»¹öúÚÿëÿulÔ·ríU@qóŽ}þÆïš1”¼õÿŽ:ý¡_Öÿ_ÿÿSüçéWÿþ_¾5u Òíy¶ó8×dËäBsí2)¥u"»À5¡Ë€»^»›ôî8zÐÏ‚Eø<>Ž;¼ b ‘_ð(²M%ýÂWpFî|3k®_èTP ½²m—k`žvmˆÊ¿t➯ΠxæX]”´#²L{ɉ‡C¾ÃyÛ:$Ðçü–׺ÅÀ²/àZèôÑß¼µ&±²Èl¡ôæUž–Eòiyu”~ïÿô÷ÞÿÿtÌÎÿè«Äêÿ£{«'Wÿ[õgݱVMÜ5ÇÃ#×Òwý¿LÜ×ô]ÿO¬ý·ö»´¶·‡Økÿ¯ýoLTG:Ïš»þ_|<ýñ©ÿ6ËËúëÿs[j‹¹0^÷üÓñóÛæÿ?ýl>⮑‹.©¢,\\Áâ2‰I/­4çîå¤Q:å[ã›òÔh”6Ùí%¸và¡sÑ‹}J¬e¥§³§FOÁœ€ò=«¹¶~óÍ7‹ø*ç°s«¯(öfrRñ’ß4²‘ØÖòmyÓ'±ÚçB›SO^‡¸êk[‡uøú&IŸ:;Ú¤=ÂE›v e…Ȃﴗü•I~•[¦!¹ž?òò͉‹V™ôáÐáãx”Ÿ¼ð@t…´uh¥—Všs|öþïýßù¿óŸN¨Ž¤VÿϘ ÛWÿ?Ö”¬}Ó'ÆÇ®ÿgÝõí¿ÚZÕkÿ­ýOG®ý¿þݰþßúÿð…õÿþóô‹¿ú“·&F ¦`›#ÀˆqÙ¸(¨ä©ª×ðt¦]L£ÐÏ7©(\´Žò½ÇÒ)Žïç›Yo^Ÿ§-Czï/5à€d¾mÕWÃCPÍ>ÄÏk‚¯_½Î®,2`¹óô*!`*ÀÌð,E¶éƒ8`8¦Ný`çYäùE2œÅåh¨¶Ÿ´cx9Èà\ùÒÌ’¾<Å¥øÏ9yœëóž+_¾¥k›‡ôÑKîYiõ¿2BåQFØû?ìÞÿÿ3svþG%Dç¬þ_ýo}Ùõÿy­žÅ3kû®ÿc/®ýeiެý÷l×¾¬]»öÿ8Öþ_ÿ¯>ØúëÿÓ0…êIc#þüúÿù¶9_¬8PãéÿùÓŸ¿å¨7è¸v0£àQ@  `1Ñ€9bG;Ù¢ôr:_%BÆî\„®[Å]ü:å’?uã%°¤~‡ï[•V~ë&§ëÈ0eðà`ÔqŽö ½4‡:•W–œø(—zcêŸ<ÁÎ"A™@gùIrøØe èqÒÓÁÚ2‡vØá•_GÚ¶áݵÃKÝ…ö™üôãжÚ^|Ú?èõ/ÀÈ•¾ËõH2yÉ>x8Ðû–VÚŸšCòÈW=~Gö‰§?Úg•ïÿÿöþ@zçÿÌÇ3•‚g>>æÐÎÿÕÿ³ûvôoõçêÿ]ÿÙ»þ 6óB_Dg®ý·öߨŸlϵÿŸ?]b~¬ý|ÏúCëÿ­ÿÇÇgwýÿé:Vñûàÿ?ýü/ýÖÎ¥|¯‚:f¡ ìÈÑ1è:@!× q‹ŒtçÒ ¹>á€!øùvEH¤c”k}´&¿õµ×Ê~ýõ×/¾üòË삚B)gK|²–¾àÊëÙ©„·|²>hÜä¹.@Uðëó‘1ü¦®)–²Êµ*@0í8:¯ >‡ö+€É.µ‚gÚ‡ov©‡<¡&nž˜¼÷àZ: Š<‚ÅlC«ï&¬÷ ¾öoxëó¶oïºjïÿSÆIΗŽ}cgçÿÑ_;ÿWÿÓ÷«ÿwý·ïú¿ößÚkÿ×î^ûý?öòúëÿ¯ÿ6Ïü}ã?O?ÿ‹_¿Ë++€ÄÁympͱ÷ÄyÚ—byb0©³[à*ÉÐL¹À• .¯¿Ô= Ò3ÙïÎó¤ÙÑñþƒ×G¦¹Æó«¯¾zñÝÈ#ÏGÜß‚ÐÎ9ÈÓv׫‚ò6èÚrHo{ ò Ò>Þ úÈvÅu\•ä í‡\OQmæìûøûë‰åË“¦êѯÒ#§ú& ©,ÒË_^^{9ÈT9uMy—üIÌ=©Oø”/ðòÊ8œ7¸Öνÿg!r/öþÏ÷vþg^˜'ŸæMç¡9¹óÿú¥×Ñ!«ÿWÿ[{:WÌ›®QVéŽÎ!1=»ëÿ®ÿkÿ=ÛÌkÿ­ý_;}íÿõÿ¬£ëÿ­ÿ_¿ã÷Íÿÿì?þ×ÿücw@e.\N˜s¥>ù0ú¤w+oÁ4:¬LÿÉO~òâÛo¿Í¯û‰kŒ¢s^ðÄ9PÇ1l'hÔ›!­N@;”¦Œ \¿&ˆî¯ÿß¿~ñÅ›/Nù¡¹¿ÎdÇÖ=èR€§‹z¼^§OR¿ókG$}SW—÷*Ziá7²0ÊÉWKÝòÔKVuÆ€Ÿtý èë‰di¿*ãðêû è Z|œ£s-ßucùêä;—ÿ*»çF»±´m‚2åßÞÿ½ÿ;ÿÏŽÌÿçUîÕÿg·/=¹ú×ÿ]ÿÏæ¬ý·ößÚÿãO°½Ç–^ûÿÙ—°VÖ79ëæúõ¹Öÿ;>î8žëÿÞ0Oøçp•õÿ®ñ?ò+ŽÙtœÎòÔsNžŒkRÊÇ }å)GYFòañ‰ïÀͰþ Aß@Ñ—§¸287ÁêîN%»¨Ôƒ¿ÅÒë‚ï²ÃÉGÛ•‹ƒ5Œóˆs­|”Ä”Ô.MÀǹC]òÉh@#ƒéBÏíp}xÎ÷±¦=‘s~QìZÀë7¿ùMèÐ ’&=ñ\£×gßM[ÈâÚî2íÁÈDÃ@]7Y%¡0·äôYé¤'ÿj—{†®€ÕÉòdžÐ¾W‡²)?ÌÒ¶©“Ìt…¯¼½ÿ{ÿQãcçÿÎ?pa<ÜCôâ$ЫÿWÿwlXFº¦tld‡ëŒc¦kÏ®ÿ»þkÿ­ýÇΰ¾¬ý,øè͵ÿ×ÿ[ÿ/¶ÄúÿcT]><;‹OGü.úÿO?ý‹_½|¤›K9€†K‹PÅëzGŒÊTZ–c"/ßÅFÚÝ¡æø¦Žã^Öy¯Ë»ÎÈÄÅ+ñò+a„FßYr&£• Çksìx²’?†³ïR Úy@«ôHø*O>ô•3<¯ôœ?ÒðòtÞGÛ]“9´“ÿæÍ€nïÎ7±ôMƒ|ßÝ_Ò >í;Ûy­Bÿ†×Ч¿Å¨•É;­ôÊÎyv¡Í®/|ûaz´øeÚ¼^™¸úògïÿÞÿÿ;ÿ]ýæ»ú×ÿ]ÿÏ+Á1Ø —í`~¬ý·ößÚÿkÿGŒnXÿoý?caýÿõÿk/ü}â?O?ûó_½-c1c$ß~šs †3o:ú=§=ƒvH„@;0¾ùæ›ð:ÍI-BGð hAïÚàNÞ¼ª'¤þI+@ƒg·äz²ÿ&¯½ýpd™kuÅk¯_¿9 Ó€2ùþÌȆ%>#ë¼™ú‡¿:-º‰‡mdš4Œò¤¥O&ÖîÒ¡iºøq­>´#£>I:srÿÈúÙ7ߨš ¯+ åMvGøÖá MÚ™'¥E'­ ˆúËo2 ¿¦UÞ$ÌŸ”:AÞÞÿ½ÿ;ÿwþ¯þ_ý¿ëÿ®ÿkÿM´ößyлöÆÂÃVfÛ¯ý¿þ_}§õÿÖÿ·V¬ÿÿÀSà° !øËßÿ™_!üã·”.PCˆÑ#PdÒSñœ¬pqf@.à•M½³¡Ç?€ >@”Ù™$$C0×Ï»±¤ÉU‡²{òM« |X© æÃæÀœ¼Jàš×þRnÊ—«ç›x*ŽN]dÖäl<Éõ‰ë—¯æ£ïó¯txj >ÊáÙev{ ½FWã(`w>ÒÉ/ xY¦äyEïÚ3¿BèZÛt? ½ê”Å,ÉÃ{dtº'¿²¢%a¯÷þïý7fŒŸ[×q>ƒeçÿÎÿèÊcõÿê눵k×ÿ]ÿ×þ{¶÷Öþ‹qû’íÀÎŒmºöôåÚÿëÿ™æÄúëÿ¯ÿÿŒ ýïâ?°ê¬ú…‹LŒ‚?{&]žÐI<€—²œ˜×^}?÷”–#ÎÄðDP¶’k”þ±Û+PÊqœ¥)«Lœf&¸®¬®KCŽä2°KKã•+•'Ç órF>¡;”ð`ˆ‹ó]­ ¤#óT”6â#¨·úÐLzé€S—üúÔ¿ÊÞ¢« _À¾¹¾xø`»XúÝOtUtø´½é×Ó6¯’Kšü¼÷zÉZp.;ÍÔ‡^çØû¿÷ÿ_ÆÅÎÿ€ÏäØù?ã‚îVÿ¯þÏ8°Î\sc×ÿ]ÿ×þ; ÍÚkÿÓ‹Ç'YûßZ¡/ÖÿÿìúQ´õÿÖÿçW¬ÿ0ˆó°çàÿ'øO, FgÈÈõü2Q:@»Ÿú*_>0(º”tMóÅ›6J«À þ€–€+sþò鼂‡šs^žÊr—\ âž'áú¨!£x*Lª²ÝÅ•„a1¥ßÏ’O>å€U¯É§¬ïN‘É·±Ð4BþC'ß9¹Ú.i®#“ôÙ †·üæõÉ CÇ÷º€nú¦ík5`°_ꟴòÐ;øøR¦ý•ºæm~Ž^Ob®'íJsKÛû¿÷ß8Þù¿óõÿyHB_®þŸW×z¥/výßõ?óbí¿‡}¶ößÚÿlìµÿ¯5é‹õÿê‡ñÍÖÿ;»×õEŽËeSä˜EE ÿƒ¿šÔIŸ²Ñµ|Û)'Ä>ã—_4NÖÿÿÝôÿŸ~ñWòà én¤ÁÀút–ÁÄ¡Y˜Ìu'¥XQßÐ ¬©«±¼ûíxwÀþMùÊ;„ü9@ê«—¯RŸkyž :y5 9|‹ `ux‘¹<µ·» jœ“ ™§msØ¤Ž»ìåÙtJk*Jÿ„_ú㼉&Oï&ÆK¾k1ž?Úµ6m11MHÿ•’Ÿô<&®½®‰°¨fd#ãU‡ë½ÿ{ÿåÿÑ&Ñw;ÿŽ¥_VÿýºúÿÌkÆ®ÿ»þkÿûkí¿µÿ×þ?þ‹urý¿ñÀâ³5sý¿³Ùƒ¯É'®Ï©„ƹ¸®¥5½±|åëW§w‡nýÿkËô'¿/þ¬3Å Hó™×× xÌPÉn©¼Ê6ù|¾å½]×v K.fè ÀôWï:‰/@¥Âž?¤âí•Ù<—ÊåˆlÜ‘g Øãµ½kð»™@¨ ð¡ùò'_¾øúë¯OÑ™LuNðpt¢IWÞk}#a~í¯Ü=ê˜ò#Ðãš,•ñõüâàd¥~<•yzy{4®){@UÁ1Îúä«[—úÅÄ\_ò¨= Jú0J·’=ד¯>AwWÖÄWš¼Ð;¹ÂÞÿ½ÿ;ÿwþ¯þ?†Öêÿ]ÿwý??ÞÃD`[°+Öþ[ûoíÿãgÄξlyöu特²öÿ|e|ë(_#ý³þßñ»®1³þ_¦ÌsjŒ<ÆÊÉzäÝçÖÁ&Öÿÿ}öÿŸþŸ?ýùÛÐAùFÿÎИíàÒŸæU?àI»€|oÉ+”’'pœNôZ :ƒ¯€‘ÉÙü(¯x£w =uf䆶tëýÜuPg>sÚ]Þ)%SøOz^w¼äøØÒûÕW_Ä"?þ1P‡¦A»ÉÝpúáYï†?™•Á/mzõ ³‡LíS²´_üFù÷zXá1DÒuJv‚ ÕS°*´CAF|”k?¥?¯Š¤ã•²×=’¥ïì¶!?^•5<öþ§?öþïü¿¦QÆCŒÿ«ÿéÓÕÿ»þïú¿ö]Plí¿µÿÇ=^›zíÿõÿÖÿ;ø@}Ôõÿ×ÿ‡M8‚Wsok0 c¤ã„ÿu?¯?&.þóô³?ÿÕ[L)<À €Êuž©*%Jg»4„’þòË/ƒ°( H4é½VYÒ.à »ð= çoNó§ ù¦‚¿É»®=ä%«½Hv‘±|•!wh&þÉO~¹ùÃÇ®×çßìNškßÀjµC^Ûð©l){ÉY¾•¹y€2è;yú ˆä¼éꔑVÚd×›@¢^¨ b}WÙÄBóS¿ü¡kZ¤ ­Cº{ÿÝå½ÿÆãWÓó¿ãdçÿÑaGæVú‰î¸›_™S™¯'oçÿêÿêyccõÿ™æpþæ4>c½Þõ×ÿŒ…™CÂÚkÿÑ«,·X±kÿÿú“n]ûÿ¼5´þ_†GþÔ®§O×ÿ£Aü[ÿï·Áÿ{úÙ_þú­ë–ÙTCҠ΂0†¥­Â^t-Ýî*†7PÅëxÊËsÍAe¯¬‘§œWèÄ® ÞÄúÖ?LÃGÚ'çhÈ"ßGø[Èf—9šng ŠœÎSUbùX¹×&µmäõ­ì´Àç2¬™Iò=Q™Y~údø?M;„ôáE‹®idlÿTN“?íºcÌ9ù•wT~å°eاî)+n]`\L¹4¼9‘ ™!™r•Aš' ä+%Ь…Rvxüæ7¿ ˆ¥n V%ò¶íbõ™œýîCó6µ¾‰iò*ùýša§*`ÒÄÀ¨ðœþœ“|T¾_Yý,´ž¶ÈõGýªgãO¡å¯ìôɽ>úòì®+×d¸Ó£Ûû¿÷çÿùîŸ9âØù¿úÿ±ÞÌxXý¿ë×ϬÅ3&vý_ûoí¿OìÖ±'ÏüXûíÿãûñ7ê“Ä/q1ú“GSÿGºëÆ!Yÿ/ý£ÿ2§¦SÖÿ32Îfõÿ&r÷çÙ(BæÙœËûmõÿŸ~úg¿| çfhѰ~ëJc]û¦”s;«Úl3 &‘üûÑN³ 'ÿRMh\“CìWíø²#,uà£ð'í0 8ä#òû+jäÔãÆ|7»­Þ¼~ó˜Ø¯_Ÿ]bøx¢*¸©ß¹ÝYøsž0qåït^STG®‡P¬Ü‡÷g÷YÚxñÀ7²µ¿ô£x•kC£ñDcgØ£þICSúðÐgC§ŒºÄÒÕEÑ÷<×W]èº+KzÛ…¯ëðšsÁùÞÿéˆ[?íýßù¿óõ?]¹úÿ¬Y‹fÍØõ×ÿó§¶O批2‡ÀÎXûïììÔµçÖþ[ûŸÉæ^ûý?kêúëÿgѽàáèúÿC©-1‹ç‹§?þÿê-”òÁö3y°º #h¦P®§gv(£ü€7B.ÎMS¦i”~éébü²E?œ|€}Ùð–NhåúÊ ë¦ûE@ –6”ÝR^#üÿØ»³eMv#;ЇgçtÈb=N›©Š3kú9Ú$U±©ïú¢Íò¢/úÛ¬CVÏ™‡lÿ±þ™¢TªQÍâBflD‡8Ü׈@£=n~^‚Žov\ÉO‘ý·În*¢hP-€^všá|Ò.4øHÛòsn×0‹¬Û§ÓFeÕc± ò|rN.aË¥0ÓN›òêÄ;zçÛÏÎ%\Aº N¿9_ðlø÷þ0÷ ÷¿ó?s¦óÿúÁü ¿hzÄyõõ¿±!æÍ®Asž´¬­;~&½ë×JÆ…˜>©ýwlÁÚµÿéÎÚÿõÿø¼ë³Õÿ«ÿ_ÿÿacšO?üÅÏßR” ˆ*®ß¼y³` ¢lOç½æøŒ!*ß!̈Ù:/¶ùL9¶í¦p†½Œà‡As½‡Á;™,ãC;ç©/r…-:õm™! "¤§Ž]¦­Êj‡wXo oåµ…,úá^Ÿº¤ã#Ûù˜äû®”ßøÐ.¤Ò~5;Ìðšºòž0×küå¾€×ÉÏíÿ¯ïcðaªŒ#a¯¯‹í‹ß@#{ëºúµ÷@ɹ/éëÞÿÎÿÎÿ3'¢WÿTÿWÿ[×­a×Úä\èúvC?Öì®ÿµÿ®¹1ÆÖÎs¥ö{~»cÿÄ6¯ý_ûŸÍEæ}Ì뿘;—ŸÂgÉz»ä1’äͱeêÿm·l_ÌÙú„úñêÿÕÿÏøømõÿŸ~úWò–ðDÊÁ!]#ïJõÁŸrK7;ž(a†‡]Bhì„Ú÷b]“g'’Jæzó?Ãïæ0Žgw“úºêÊÔ»§+³2†Î¿ïÌ#~À¡ì„bTkC@µ¯¿þz í´GC|•çˆ&LêwCôˆÄ‡oÏŽªäËÓŽ€O®å…Çò¼Ú6S²Î=Žvê|îO¼ÂcO.~äðëäËÙ ÜÒn;϶??)#-íÃ#<ïürŽoîcïÿ,žÓ1¹w½ÿÿÿÕÿteõÿ©¬õÖ7kJÖ®ÿ]ÿÙyµÿžm·ØµÿjÿG_²ù×6g¯³ÑkÿïæýSÿﬧñÕôI‚óú§7èU}‘1SÿÿyóJÆÌê˜é§„Œ©\‡Îµ¾Œ÷Ûèÿ?ýä/ÿøm¦!i,£Ôµ&-JfÍJ¾÷G1^v7Ó€EI·œ+»åçBÇåPgvg-Ø2t;eMÖù" 2hÅòÅž 2Ÿ,=@–´€:€+é ÀM;ì x„úâÍ ÐEž…¿æÓ}Öð¶Î)»4ã¯þäéiÙöþîý»Ó÷A1¼R‡~¹ /à†ÿT²õäÅî÷:Ñâ/ÍýØÇ§O´)ÛJñ^C»ç£_Þ×ùDîiÎÃ;ùä MïïÿcÏX:ÿ;ÿé˜êÿ£ªÿ}Ðõ¾L<¡ëÿìf¯ý÷±S0kgí?vníÿÚÿõÿv¡`O_¾íúns]ÿ¯þ¿u‚ÿMOÄ—^ÿÿ7ã?O?ü󟽌x4Pç1@à$ /C]Љ‚N6É_Pi:Ž—ÇÁyŸG݆fÃ9ÏB+xÔïå‹—;‰Éà@C ˜àzþlÞæ_i›n}œ2òõ‡·vE6²úÕÃȬ¬wU­ìÚ6i1Ä  Jºó|eQyÇ:÷°‘!¼É’Ç*”Ùcø‹ÑŸ2j]r§-v¡y„9U¯ú):/¸w-Lmc<VÒR×òCsë·ä‰µ ½ÿ½ÿÿÿt½B'Ð ô†£úÿèÔêÿ®ÿ]ÿkÿÑ“µÿŽ]Yû¿ö?ÿ'>ÖúPõÿþ[ý¿úÿùßõÿxD°•þó9ðBxí%壈€Th/9×ñÒrR¡ka¯ç4Ê+[Ð@/¯ß¼^>áOþ‚XY4@ŽSÒ_Η¿øâ‹Ý¥5óÿM‘Á¤€&ÏŽ-ùQ¤xlË‹ÝÉR^9uk»k´w@ȹ4y©/mVîžÆñÔú´ô#ž”Ù>£}õEú-}tÊŸÝgk(“yÚ÷ù´Oÿ¨û€X,ܼãä;> IÇß¹r©³÷¿÷ßxéü„;ÿ«ÿ«ÿ»þg=§­—‚õSº ­ëí?c¡öߨç×+Hjÿ?¦öÿñ5Ì GB|qý¿ã_?ëúÆEýÿóJ'6Fýÿÿ6þóôÓ¿þÓ·c•í;>(\à‹ÉdçS ¸¯÷RÅKž²Ò :åN‡?ÿzOiIcþYØ–n®<(0/Z‚“¿u YÐHsÒ)ûp6í¬Âkòïò(ÿþÃ|¥pò__/¦Çò&4¹¶›i—ÉS'ÀHì=Y@¹<ˆF§ÎÄøx‡Wùò+m·ÒåRÚêKÎÕ`Úº¦(y÷ÑHïøšÚ¤|äp~?È ŒL€>•KמÍždòŽõ«÷ú¿÷Ç q¸Gççÿ¥'雌 ºƒ¡wªÿÏÚSýßõ¿ëÿ±/è úÅWû¯öß®3kHíÿÚÿõÿÎzi>˜õÿF?̾húD¿ñ›×ÿ¯ÿÿô¿üo?xëëƒÞe@pÜÇâØw,펡™TŒ10G0ˆ„]†n΋Af;Ú >e˜/Ùý´qÊdgZA:PÅ0MÙäVÈæ¶r^ΔrèÅ»ü=Ú˜Myd!õé„8•ŸGôÖкÚùäKw òrú­cêöq¾§óxŸk€ÑUsŽne»vmý#çY¾gN_å‚Ì®v Ò®\O‚h¹ÄÓ•¹Ê¡Ð.‡‘ãzozí'“`›öôþ÷þwþŸ—•›;æPçÿ|IÖŽÑK§ÒÕÿÕÿÖ¬]ÿ»þ³éKúA\û¯öŸ±@GX;jÿoRû¿þßõz™}Ç":¡þßóμ]C¬%Ó/ÑôˆPÿÿœÛÖÚñçëÿ_›Ž~·e(ð 'šmߤ‰¥·æb¯õ4P€-t÷rÚ-¯¤§­â;Ø„&}·}%ax% ÿô‹:#OêJ½F­òp<í°óêÊÜ:ðÛvôþo·ôþŸ(tþwþWÿŸµ-ú¶ú¿ë׿”×þ«ýWû¿öÿ¬ã§|‘øõÿNŸè¡þßY/ÖלqžÖO>â£Ç¿MŒBï9êÿ×ÿåò_á?O?ú‹?z @TqhEüêê:;¡ (ÊJº'/@Š »ƒsFz¨É _ç¨:=â·e§Œ€Fyqø1Vž«ð*ï­‚ÆQž;à'ËÚ5AÝv_­ÜÿǤ¹Êüj¶uúô5ž^ÿË/ùÙo¾8e/yL"ÊG°s)<É— ÷h{2®˜ Þƒå—uQîÚ´»Ãn´x.ß‘÷ôˆ‰{¶Yâ-¤^±{öõ7_ï–Bü\kcÚ, 8†‡k}¯~|zÿ{ÿ;ÿ;ÿé1zdõíèŽêÿ³±ú¿ë¿5³ëÿå N_°jÿÇ c[Õþ;?¸Öþ?ã"kÿ×ÿ«ÿwìJëFýÿúÿÿXøÏÓÏÿã¿~ë%zÖ:,ã¸ìûž80£‰]Ðú§\€“€=›7ùø \[ÜS‡ó€,sœçÄàeÊ-ÐsÕ#ý—¿üå|¡àÕÊñõW_}\ÿЫo*Û÷;á§|ê Ú =;‘ðEëúàùÒÝCÚHC«}[ÏìSG-e´Ù!¤Ýy'9ïý¹DןÓïºþôž^Ûg/GÖ½5ógø¤h":å…}¿ØÕŽ•Gò4ëÕëWódïïççÿè:ºp:‘Ѝþ¯þŸEdל®ÿVÒó*ëj×ÿÚµÿjÿ×þ¿Þ:ºÑ=úÃQÿ¯þ_|åø§ÆEüàø©ìîõi¯¸þìîúÿþóô‡ÿþ§o ¤tðXÇe™kÊè|¹î-è<ŠfÀíù åI=@É” X#ÎyÀ—-s-I£‹Òc J˵ú|F’3åq–ßÿýßßøÝœ¿~ýzÓÃ7õMalØ%=|Gø•0¥-Ú*˜ló7³±RPÂðRG”³óLDqúCyuá'Þ2ã úUN¾„mèäåËÒñMßà¿ÎäÕWáK>r¦¼z`zzµ×ùò˜¼È&^)ßûßûo¼uþwþÓ=ÕÿÕÿ]ÿ»þ×þ;¶äÚ\c/Ýí>iµÿjÿ×þ¯ÿGÔÿ«ÿ¿>uýÿÅôÅâãW æH¾¦ŒÃ:êHZ®ÿ6üçé'ówÄCö¥:LÆy¡ñ…=çyɵ´ux‡„Ž@Ò ~½?` ^¡W&õä‹}ò2òÄi<ÔŹúœ+G6 úÔ›úÐí Ê'-ޏt|·ã¦°ò&¸ãQÇ—¯^~öúÕë=G«ÜÃWP—òicÀ#Ýn[ iÚîŸ]VÊ ú+r¬¬“·ýƒöêCeÃð ü)·.9îíÄ×û®¤q6·×Ä‘§-©#}„à¸FéÐlÛ& ç½ÿ½ÿ™—ÿÿôˆ@7DGTÿWÿwý?6N×ÿÚ«GGÖþ«ý_û¿þ;©þ_ýÿúÿÿ<øÏÓçXÀÛá-Æ@1P0@¡˜¥;ÖÁ5IYC7ö+|)«º(s¼ï€ÐåÅPòíþ1á9Ëû‹ÿ¤©S Qd™¤ÝŽ*~È6åB—ºðˆ¬hw‡ÖÐyçÔ’fG×T|€í½ä%£ô?ÿçÿüÙë7om¶vA«áI&2ë²8÷bym÷^ºÚ&/²F>´>Šnûw®—ßðõ¥3ŸÇT ,@˵gÎmNùjøªƒLé“|ÎÚn,eñÛº®ûöQ=ó÷ÿŒÇÞÿÎÿÎÿêÿêÿ®ÿÖKG×ÿÚµÿjÿóMÖ†›ºöý¿úõÿëÿÿÏÅæŸ¼µ8>9÷àæPØ;ä ’¤ÉWnÎg@IDAT;œÐ„:瀣찲 ˆ´“þ¢Ý]Oð#¨caP‡@&A9²ìùÄ„> м•ib´Q.â€:‘OþfÚ<ùv`ƒÂë»ßûî­äpàîíÖF­€ ŒÜï?œ/6žúžß¶ž•ï4c늌òµÐD¶Ý%5ü¿ mß_5ËwÒ|9P†Ÿ4ò¡¾[M™‹§¾F+ MÝèÓ/½ÿ§ÿ{ÿw˜ì81ÆŒ„û<˜AÔùßù¿CÉ‘à¼úôíÌ‘™HÕÿ3ºþÍÔõ× ú¡ößù”~¨ýWû?¶zíÿú|µúõÿëÿÿ÷ñŸ°8& `„úàÆå„˜Dâ\çxç×ËË=¯èß#èñµ»'€O€“€/Œ[.ß¿;ï´Bo7’ÇÜÐ:;x`¡à/^\\´çô”SVPœïÉ•¾íž™Ç°D—÷B}óî›GÙÈA^A9 •v„óh£ÇôìPƒ}êÿõÈúèSmشӇν÷JÈ;ª¤i§ÅLØÝkè¦>àÁ£ÞIӯꖞ>×7xHo»'^¾W¼<¾ýXvi½ÿÇñîýŸqkL^ónâŒ!ãL<ƒJÂŒ×k|uþ¯þëü?úÍx¡Wªÿ¯5µú×!º£ëÿ±ºþ×þ£'kÿÕþ_“^û¿þ_ý¿‡Ï?¤þýÿ]+oøÏÓÿïÿë[àÆ‹ùª]Þ„HZ€‰Ñ9ªu“Ö‰44€åbŠ7L^Î}éN€‡¸b×Ò~Qp@3Þ2^ªãÅÓy”PÚ‡ZÖ›¦j'‹Gí×+çÐ%¸V¯xe§Oai'–ïO–ïÏ®/;«¤ÙÉ$äÑFåWÒåGÎìxBžäÝó)³ ÒH©ÍÊ….å=æ—jòíCûÜšó¤úT_ýõÖ^izò#~òÑo_NL´+ÏÄ®4Ê,è†ïÿ¾'Mßõþ?Ïc¶ó¿óß¼¨þ¯þ_}0cÁ?kJ×ÿóãU×ÿ³\?l¸ì çµÿjÿY?jÿ?¡öý?c þß/×ÿSbm‰Ì‹úÿg õNRÿÿôÇož~þÿÍ[‹K@ƒh•1@„ìÀxõ¼_™UÄ9G»€ÊÐ3x@Ð%@ú¶ž!Ü›5Ö·ÙMê(“~ç½u\²’Ï•™¨äœròÔ»¼ÉpMv=iWä²ðH$¿˜’GØzÄW[#_Ú˜zÕžsåœ;”÷þÝÆÒð!k\KÏ=Q~Û?õÕ»oæEôJÛ¤;_Pnòïu*°¢(¶ —,ʨmø¦®íËKÀÞÿÞÿÎÿÎÿQÕÿ£«ÿÏújyȺ!Îy×ÿ®ÿ숼“ÍáÇ´Úµÿè öæÚ™µÿuÇÚàtgíÿúüßúõÿéÈúÿgƒÓݶ|úáŸÿì-cBðHÞ‚{uƆð(4Š•ãò t|ü¨ÑÃh½x„Îå(@ 4n€EÈÍyùbaœ/ô`–Þ—ü¦~çÊ, 5u“‰¬ ¾Lù•-1ù&¨7;ªî2å|™­-ÜÃhe!O@¨<å1ÀÕ·f‘ Ÿ}„pÒÈÅH'ÏÒx!ûÔ䛽Bx'0èô%:çÊ8¶þá«Ýú Oõ3ø–öâ­ÌÊ3²G>`JpOOçB•“ SíÊ94èzÿ§ß{ÿ;ÿg^˜{ÿ4ÈÑËô…@g8è:+zÊeÎC·®?É«þ?? TÿwýÏüèú_û.­ýwœ³ÚÿµÿëÿÕÿ«ÿ6íÔÿÿÛñŸ§üâçoTë Ä²šønh[`「s¨ø2ûî›çÝLëÜ\¼q^”}H}õÕW \P€Y@txy40`Š|áªmÏñ!'|‘ôGþå„.ß[úòãqMXãqbW€(í èã\YAdùòË/7ºù*`€¥­chÔ­ýâ<Æ'ï¼ã‚‘rÞéµ<‡nÛ¡Ý×ù‚`#Œò9´Ñášlbõâ»×#×Ë‘Uº4rùË/w·˜4òÈOØ:‡ßÞ>_P ÍC¦NÜûßûŸá`,uþwþŸ¯¹}AqVÿŸ¯ÓZ#¢oÅÕÿgŒX“ôÇãèú¿*5k~Þ“éºëí?:õ1Wè‘ÚºäôÍÚ°µÿkÿÏܨÿWÿr #è…‡~¸ô&ûãž¾´—¿[ÿÿ_†ÿÿô³¿þÓ·‹Üð„ntFò‹ì¤³ÊîBk C¼´< /Å£wv êá Z0hÀ#ô_¼ùb•2:ùÒ-gÁ’úI˜]E1åDÆ¥¿d’®Î´eeœ4ñÒM{—ÇÐØÉ¤^»«ìÆ9ßù:á¾ÿýïöŸþÓúì÷ÿ÷WÎLuà¥/Ÿç¼LÂîf!¿t‡ÇLl„Êã&Êâ(áÈ—w‰¥-F<Òέs€¾}yý´Ñ.1»ÌÄò‚6Ù¦Êá}vcm{]LP¯vI³+‹|BÊ;L½ÿ½ÿÆ…Ðùv7š?BçÿÙ]DáTÿWÿ[;]ÿ»þ×þ«ýWû¿ö?;‰ŸQÿïøžú£þßlÿ–­PÿæÇõ.ñø[õÿÿvüçéG³‹b1ˆ:OB™ÇߣvH­³6/kâÌ.H£ìÚï̦;@¿ûÝïÎËØÏWñÐÛyK]qS·A½ïG˜:Ÿ|sÔåPnË^qÊ£u„¯rÎå§Îµ‰¯ðRWÚ„Nø½ßû½Ýe”6‰}æR,£ðwà;—{Žž€1à’€FþX:mÂwTŠÜ)£'ÿ;;чh땼Êã…î™rï0TfïÙ%>xËäE–Ô•¾‘ßûœŒ}Òûßùo®wþWÿWÿwýïú_û¯ößÙaɆ\û»öíÿñµÆ™áHÕÿÿëá_Ý|®ú·§œŒ• «?&®ÿ6Äð×ëÿŸõE_ü&üçéÇñGo;h&`D­8Ï$|xVÝT&eÅòЉ•p½ðÈÝH÷G î`>A9GêÞ?xÍn¦KêÙ-öC¿p¯_ÙÈâ\ý®…•ÿZ\?ª‡ü“oêà©^e¶®Ké(Ÿ2xFV†kÎÑç]^h‡´ßµüðÍcúÔ—ñÑ?úMêÔoÚﱇi›4Â+‡·t±Ç=Ö#Oín°« i‡:"û=–Žlìý?ã,ýÖû@XýÐùßù׿Ñ)ÆFõÿù¨ú¿ë×ÿÚµÿjÿ×þ¯ÿÇFZ›iüA>Eý¿u5¾h|Ïúÿs¨ÿÿ?†ÿ<ýàÏ~úÖÄ2©ç+ÒT îLšàÜDÌd|ùj^Â9`IŸxyB®ôó(ÛA0¹SÛ%ÃS ØÁ?À‰òBdã(ãZ@ûúÍë½v ÀgÃ¥(Ò¶“˜¬çöNá‘÷ìNÒôáéœcvo£<} ] *ÀèÕËWwzín+|'l¿\ýæO‡ôéÍ÷|h¤ ü´%}®>íϵX¹ “ò´@r~ñÅ ne7ÞxÈsszåõþ÷þwþ?ïðìüÖ¹Ñ=ôDõõ¿ÅÏ$ˆ‹ÝÙÛõÿy-×/]ÿÝSûïôCí¿Úÿ£jÿ×ÿ³n:ØVñÃêÿ­Iqì‰Ñ•õÿÞÀ¾Š ^ÿÿõgOxXû(Ý b43i'“‰µÉ4™déÀO‡Vº2) ‰A+M`À}ûí¼Ï)!¼ÝE4±¯çááN&/ž ™ÔdJ:ÚÃo¤Ü44@AP ô(+ã Ò´áæ-ÞáâÙñ$#+Ýyú ¿®Dfu“#m{ÔC91Þæ1Á•o®ýÖàŸX:þ DM¾z’–úN™06eÐè4ÊGFéyùü«×\S_òðDG^éâð ŸÞÿÞí}Ü;ÿg÷¥¾èü¯þ¾®þïúßõÿØSúA¨ýWû¯öíÿúõÿø•wÉ“CõÿëÿÃþ®øÏÓüûŸ¼ÂØqáyË€ŒŽ“Øœ4@Ëüg  Š6}SP$? GòBËÁcÌÈ_€dÊ¡÷ÉLBÛ%0tì^ÂÙÑt¶oÃ.ð<ñ—îH½Ò“¶Ì†:0‘zñ¦IŸC=WÆ£½'á¹ þŸ‚JúJº~{=àOÚAf€ÐÇ‹¼Y9¦Ji—¶‘i*|äšy©[Ú'¼ûòõ%8ý§N-Èε´­úíÀÂÃ.·wïßí}${ú ]ïÿtà܃k$\½ÛûŸþØy2ÔxŒ]aÓ÷ìôUæ¡8y¡íüŸìü_ýG÷ÆIõÿ€ãÕÿ]ÿ͇ѱ£®ÿµÿjÿ±¿Ù¶µÿÏ“(Y?kÿ×ÿ«ÿ÷üÔTüZóƒOÇá[Ç/ošô9Ðl˜8þÎIx.cM®ÿÿÿOÿow`¹an¬›ÌàTX(â„Æ¨ÊÍwóOã§yÁ{”Äøpdñî|Oú<®3ÿÔ/0äìøx÷Í»•zRké&=¼÷zäÚ,ÿ¡c``¦üœ?hpñÕ¬8–hœ«7ü"³ôÈZï²€H¡×Gy +|í´B“þ³øl['N;–vå8²l]s­?"§º"O&§rú%-H䙯ïc+û¼[ì£IŽÙ„Íëý?qõGïÿ5ÏfÌ Æˆq—±å{Lû/ºsýÜ&õæA}‘v¢òN)ÊÀŽ&A¿ø¤¬öê—ó.‡|»ÎÈ…²ihܺ}·Õ¤ž>™Ê¥+û$‹œ§^òZøýª+=2§ï”éýϘ8÷/÷PÜûF•±Üùßùo¬Î¹tÑQý_ýßõ¿ëÿÚg¹8Üu^ûïüà£;jÿÕþ¯ý?¾Êü¯ÿwž$ªÿWÿßxöàÏÂYÿP¸Æuè¸Åâ??š¯28ü:îÑ=€Íîäâ€:u–)´÷é×áL‘—À¡Éuœ›»£:»4¾3ï‚Z~íZá†YÎ/,g±ßGæ†/¡ñ„ª ø‡4b¿Ê7i/MdØAÇuÊ>d½òÕ•¾˜B+KÊFerD.un_ yÊ}ﻼÞÿG_ëGý¥ÎõcïçÿÎÑBçõõ׺ 묵µëÿ±Õ¬µÿjÿÅŽ2O„ÚÿµÿëÿÕÿ«ÿ_ÿ†ÇØ>2¾ößÿÙw`1¾0²›IøÕl3”6ýÉón1Ú]O@)GŸ0$»UðpžðñB6%æÿîÄ‚}Áã>`ʉ×L¾ÉƒF}Þíäö¾¹æ^ÀÙΘrdqA/¸ÖWb!têXl^0ïìûoè·Ó‡.ƪ˜##ÆO_9Oàk<ÒoC¼´oì:»ÉãrdÚ¯0 ýÒM¬‚tmÍuúzåÙû9÷áªM Kü]“©÷¿÷ßXêü~¦¾óÿ€¸ÕÿÕÿÖ ëI×ÿ1º&XsÙâ®ÿµÿŒƒÚdž×ô…ù‘›ô\U<ÿkÿûYíÿúæ‹`Ž8¯ÿwüÚ£+VU¬ÿRÿÿàt¬`Ìü.úÿO?üóŸ½Õ»Ð\Àˆ¯‹éž¬&“r@sòVòˆÇ÷ÏØfmÂõ'  žÛÙó5ÂýºðIeg=û¨,peë»xäfÝùÊ_9`Ú/\L¦Iæ-?éÚ†Æuxnm™°mŸ2Ïuœ5Fé¶o^ÐîшÝéEΡM9çÊ-Ę®É%oÛzÆìÀâ œB›úÈô)oþEÖðÔ†{¾Ç$æ^¹VNð¼Ünsm7:aۮ̽ÿÀíý?kÆ”q³ãeâŒÁÎÿÎãÂ?¡ú¿ú×¢k]ÙA1ºþ{ªëí¿Úc?Ôþ_ªöý¿úc Ôÿ_½þÿÁ2ØÁjœ Á3ÎÕùûôƒ°tÚ#ó1Ò‘I_Çu°‹ï:+·ֿ9ñw¯Dœpj.¾”´sUi3:ÎÄ>W;tòÑ?êŸk VêKúòqŸæß¶ÍùÐõþ÷þ“F¥ñÐùßù¿ºéÒCôGtjõõ?‘µ(†;å±ëËè®ÿVè[Œý o²Óµ›ßõÿôÃÕµÿ¶;vœÔþ«ý_û¿þ_|Gš!k®óú¨ÿÿÛïÿ?ýð/~þÖ ^’q9GŒIqŒ¥Y7uÎ.”ÈsÌ¡­,òåÚóîÂ`xϹ‰ã5†'0äQ=ùÆš|2àçÜáܾ9ws±r¨¤Ks„Ùí Q×Ö? ÆÉ"‹sáÞá…‡G(Ã{xiÃîØšú•ÅûÒ½!/²F6qÂvõu½ts.ÖÇBäöñ1}&ßóP®ÉLVÁõüyÜϤÝÛNÞ ½ÿ~ïýwÆJççõõÿ®/Ö¾®ÿ]ÿÇhX;…2çµÿŽ=«7jÿ;zíïÚÿ;OÖ?–öqµØæŽÍ~ì­Úÿ§Oè•{å|ûjÖŸúg éõÿŽPÿÿ·ßÿúÑ/~þö:eð1(uW‡Ù,:£?ä-дIg!ÂkÙ àA³ü‡&¼ Y´îyÊíãnû%öñÂx_!<Ä÷#ùâ#ÉOä»äâGýh”U+rtr.}':™æôd7¥¸@ÕM€—~Qo¼u(/lÊä%DþÍ»ÊêÏmûÄdˆ3¾)³u\Œp¼§;×vußy‡&`›ëälª÷?c·÷ÿy~#±rÌ$œ´ÎÿÓOÿÕÿÕÿ–À®ÿte×ÿ£¶/fLÜ×k«PûïÙ&5oµÿ޽]û¿öý¿ú»PÜþÄßIýÿé›ßÿÿÉW-œîzŒ® ’û ÈyÀ’½€(+ØÜUèñ?‹’òu¼/eA+€àfŽ\+¯l…á¾çá%–·/¦Ê.è@ž É÷øß·ÝTÊ…OÊ(Y“¿Néð:_M9G­ŒÚ=ýƒæªG,è4uDø¯œ“¯”zÛËÃ'üÄË}ò’ÝóP.ý•¯¾;_yá§\ø'-ù¶ dÙ¼aÜûÆjïÿß;@>ù“±¶É3vfðì€íü~·\çÿóø¡[¢k«ÿ«ÿŒ®ÿ]ÿ­±µÿjÿvõÚÖ×5ûÂÚ!omÖ¹vžµDìºöí±_ÎØÉø¨ÿwÍvú„Ks^ÿïØ¨3ÆOlÕ虇o?»È'¯GYÅï¹úòASÿߤÛ~ŠŽNåúŸÂþáfí``\ƒ<‹Užôb*œ[8'•‰¾b4Ž»ü¯ÅIºk‡#ÒÕ‘snø ý´~y ¾˜–2®ÃïÅ<ˆG‚ô;?¾{÷ni¤{$Ì ÖBvï½çï½OjÀ ´+²©Ñ3¶xÚ±%_^Úøè+;»æß]¦ðøV;§ü|îpòÏ¿ïHŸä’¯¼rŽOyÝû0€šeO? ½ÿ½ÿ `_cʘ¸¡ûùæÍŸÇ 4®çºóÿèµÌÝÎÿÑG3.è:/z/z²úŸÚ-\ýÿX³2FºþíÚõÿc€'º5±µ¨ö_í?ã@X}::U`³Ð'µÿ?žCµÿëÿ­/ZÿoõEýÿßnÿž{㌎ҟÿ;°/ EzBXqyŒP¦ŒùίϰØw, 0 Ü’Çáâ¼¼|ñr ÷›?Œ—& ~ä¹Ç‘cåT÷üûv^¬:òœ6ÌΧIO=ÒÅáM»£¤[äò%5@–4/¹säó¶isê‰hµÖc— ÒÔ»| ³{k·Âz¾òÔ}Ê\õ_¨nxâs¯çôæÅýª¼î!å¥o\±> ­º…ä¯<Óï½ÿ/wlôþÕùßùÿßÐ-уw]Sý_ý? Ê®+]ÿϺÜõÿKµÿjÿ±1kÿÏìµÿëÿÍ\¨ÿwücCýÿÑõÿÿAøÏÓþì§o8 €(ÒîN‹s´w z@I –s}+ô€+[휆,j¥R>ÁÑ'–ç§ŒN@ ¼S÷þB«Î¡§Ð Jå‚üû¾ù…÷žgÇ•rûxÓŨ!/òo{®b9ßÊ®úRïëׯ¿ÒÐÉÔ;­¼©›LÎSN½îÁ^O¹s2íØG4çêÊ+—-Œ‡ðã¿Ûޫμl9ÈäÀCœÐûo'aïÆCÆiâŒù™wæMçÿÑ7úE_uþWÿïzRýßõÖ×®ÿµÿjÿÕþã`í¦ØSµÿëÿ ±ùuõÿêÿïxˆ_>ã£þÿoÆžþp,µ2¬#ê׳óXŸ÷ó§çÇÛäÒ¢|•û|®ßÈ“÷'¡¡”A0h÷ýQó˜žòÀš8î.)ô×§:vwÔ¸ÇJå6òx9¼&¾t×êF«L‚:¶MWš²òÃÃùÓç×W‡Öµ2BÊŠÑ;í³‹ìž¦9^ð%]}-ýõ ìÕËWû¨¤4`™€Z ½ÿg|õþwþæsALwˆïs½ó¿ú¿ú¿ëÿ]'tý¯ýWû¯öíÿúõÿÆf®ÿ_ÿÿŸÿÙ—¸sÊÁ]ÀL€o8v¼˜Ãã"ÙA¸b¨IãØ=€¦¹ÆOžøý»óˆ 7ÐuÅ"¯ìd,à•<±ò¨ ¾”Æ'ãý-X |²FŽÔrËÀ9Äj'¼½&ݵõôcêêÙ&^<½Øv Q'€hë í´ã›¯¿Þ\€¬W¯^® ‘}雩'ò%ŽÜKsû³»ÝôÏ”ù¨ C£lÚ-ÖrŠñó/mŠSÞûßû¿ÃËxº…ÎÿÎÿêÿêÿ®ÿç‡1ª±ëÿØwµÿv•¬ýWû¿öý?~Tý¿Ûf’ñ;ùšõÿŽQÿ` Ç`ÿøÏÓñó· jÜ”ÇõTvoÕ‚W3094hfÝ…rî=:àJâ)Ê`A+=AžZ˜åF+G£•u„v ÌŸ\‹Þ8÷õ¤¡ ]øX|ìÈßóAŒ_Ìû¹’ŽVÀ—ñ PÙu–ºÜ !üïí’îš’ã›ü´%å"×§ñò¾ñw-(矰rê3Úlá-|ðÉzÈ(ŸËcÊMG™ÈÓûÆ«>ÔW½ÿÿÿÕÿÕÿ]ÿ»þŸ×AXvPûïc»VŸ°jÿ[B¸/nžÙoá 0çQâ(ÑU–tìKCÀ)gr”Yz|.c&å•ÝÏ&_ÀŠÅ<ù©È2Â;ÿÔÚ ÞøHÃÝÚ´{^ÎÑ¢À‰}©D…ÎÉ &¿w_yVäû´t!ðRÖ1Â,ð·|®¶å?ùïf7^‚ø~œÄý»é÷¾¿ó¡V®ÔçñI÷/1©?} ÔŠœ©Û62‘Fy×½ÿ½ÿÆ•1"¾AiÿGÇtþWÿWÿwý·Öf]Íz쇟¬¿tf×ÿÚƉñQûï×çÉ 2amÐËÖX»´öÿö‹¾¸Û^ÆNôËdl^®c÷'Æ ú§öÿóÐúÔ¡oêÿ]soÆUý¿úÿ¿þÿÓüûŸ¼ÝEc&5¥(ØÑeIù-¨1éÎwò_»ÖH›2?-ùK?¬ðpNY(§ƒ€(¾V$¤VϹüÔ¹çs-ÞGø¦Z¼¤ âÔ'&DäœÌ¥ÑšPežòV¶‘åÃûyQüЬ$›zb€¦]ò#«²‘À…_u(OÈ.þè89ûµD&Î#™á­Lä‰ìŸ¦åZœ:S&"y´9ï!›îÚžÛ?“"N?"ïX~S~.¶\ïïÆš1sGÆÊ~UÓxš±wÙežÈ_úÎÿí‡Îÿêÿêÿ®ÿ]ÿkÿÙ½]û¯öíÿúñ‰ãËÅÆv}O˵86yòëÿÀkûRù ŸÊ¸‰·?òC³œ¦¼’é#¤ä¼ø§_RŸüðIœ´{I+›v®ÌîÓuÈzÿO¿öþwþg^¯éü? ÂßK×EOÑ7ΫÿŸu²nJÿ8O¸ëæê6‚µþô›uÎ:ž>[Ú+qçd×ÿí{¿ü¦¾J~×ÿ3xôCí¿Úÿµÿkÿ×ÿ;c kmý¿úôâ?þóô£y–wÀˆq"0èl˜E(ÂÐ[”s<LM`Ô¬èbhñp-0„öq}å=Ò”¿ê‰Á„M %çxx” [ïðø4$=4+Ó´ApîèmÛ\“EPFH½ßÅ^ú«½€Ÿ¥@ͿϽH~ø¥Œ<|í´úp_ò•Û>™<†4ðMîWXýÈðÁGÀã¤Kû(ý²ÉßmÂh´c®#“29×·ŠE–Mßvœ_À¼„u*yôÉ–¶öþŸñÞû?ƒgÆGçç?Rý_ýoÚõö¶~îú"Ãzt­'»†uýïú?ãÄøØñp ãgÓfÈÔþ«ýGuÄf͹X¨ýúa ùët:«öúbâúõÿØõÿn]ú»âÿ?ýø/þè­zº%1éyJ"†‡kÎ zi1N¤1LƒI¾ÝLÎ×h–ÏUÀâqB»¬R6|O²èæZžúRWê¾—M]âGú%¿ò{Lžº•Ï#€i“r‚² bˆæ:uEù¨ðt-OPne’Þ¯¥¬Ç=n….[É—øúƒ&u(»a*^Þ韡¹ï Ó?Ë,Ó§Â….Þ;¦wùðÌ}•îÚ‘Ý+f7º½oCÛûÆ¡~ëýïüPïñÐù_ýOmVÿwýßõ´ëÿ³ 7¶Dí¿ÚkGÖþü°m½jÿÛÞ4FêÿõÿÌ ~¬1±kêø¶õÿÏ^ÿÆ‚¯š(Þÿd÷A²fÀ‘_ŠÅ£u:.ƒ( Ì¡—~WÆ®Œú èÆÙSÎ'ˆå ê yIô¹:ñÄC¼ÀÖÄwz`Ë]–åsWùjâÞöÉ‹“‘A ÆÛD!êÜ;´NL¡«îí£«¾´‹ÌdðrèS»­ôkê^íc‹W])ŸÉI†ð“AZøî5ðdޤ¡‹üúÀÎ,ÀàËÒλŠÐ¦4Ôå¤÷ÿѽÿÿÿ£ƒ/Ÿù@¿9¯þ?à ]JFWÿwýïú_û9UûïùÇXk©#z’ ]ûÿüo=M¿Ä6¯ý_ÿÏXÈaŒÔÿãz×ÿ·®ìx»³þÿÁž~ò—üÖ¢PÃ@±ËÇBãü>ÐlÞÐË3Éä;ìôÖ8\+¯“ÑI“/Mà)›:Ëü H­!ˆv%RÏ^_<–ÏðeW’´OCä㓺]ü[lÉ»ý0ò;ùâ|6žÜÊIÛòÃι°ïΚXxõÃtÒCc±zÙr· r‘çQføä~¦?¶Ý[×)ŸþÃMèÑEŽ•¥÷{ZŸôþwþwþWÿWÿwýïú_û¯ö_íÆaíÞ\ý?þÒy¿sý?ã¡þ¿^x|HþCýÿéƒé–à Û'°‰+üj0‡€%Í¯È z'$\©`Þ·„™¼$Ècï\Rnr·ðæì#tyÔZ'yë¡ÐSß=~ŸºX!4ÙR×Vy¦ìÊFæ+<®É¥£] fÀÁõü9õÌ5ðmhœç1Ci_ýõ.DŒŠèÍ›7 P HDViBê\ çÁv1»ú*²¡u´à×û¥ÆTmþ0Ü÷S‘Wp Pšý•z²†FiGø£Ýô)±ï˜º¶ý[ª÷_7ôþ_cGgÌø˜²Gçÿy·]çõ?Ý]ýô5AGì:Üõ× •õ¸ëÿ8íó …ÚǾ¬ýÇG8ÝYûì+ÿÙYW¨ýχ¼Âô ŸemP¾ŠdkÍFõÿêÿñ_ëÿ›/Ñ«gŠ\>Ü5¢_þ%úÿO?šw`ÝAŒG̉Ž:¥ä ®¬Ñz:j'Ò\ŸøR8èñ ²C·Ê™²¾”ëaŸÊ ¨ }·Ë]e"‹4õ©C,ÈK¾r[ÿ¤çæ×ëðŒLcô˜`ÞÅ1bÄØPÏT¯_¿þÄZ J;.yÐyÌ´ÂÊrѬó3ùèº1r—ð¢ myZïSðê(qrá~Û£®z\kCúfó'íý´ÏKë?ÍKýâ¥Xÿõþ÷þgNBçÿ3ˆÝù½Ÿ¸ú¿úÿ¬¸»þfm²Íùê’9GÑõ¿ëí¿ó#ç.¬ó‡íņ3Oµÿjÿÿx]û¿þ5Qÿ¯þÿY/Ögÿôÿ_ì"9`‹È¢i1||g&Èã+~ŒNštÂÀ5€Ìc€c†n¹M•1à ݜÊóˆ]~iÙ|yø -GøÃ¼Y i÷cßey½sÞçôÔp «3™“¾ü‘Ï¡M eaÛwRRW©Óñë)ð}R^_Nü±ë{ßûÞ‚X(×¼ðÜGì¦>ÀH~¶Œ£ häÏ> h•ÑV»^V¾éoA;´i½‰mÚ$ s6½µq C÷14Î5òºÞû;eî2nÿ\üzÿ·[{ÿg ;g¼ÿÿÕÿ_ïÕÿÏ?¢Øu‹–8š¢ë×ÿ6;>Œ ëÈŒ•Úµÿjÿ³¨žƒ¹QûÿyM¹û$£8ëÊêé¶úõÿÌãD¸û)léõÿOßüKôÿŸ~0/q_ÐÅÍÿü˜qXw@ò®Xšp§ÙkTÛO§³î4K(ætE=œÕš”› æÿó"õnîåï2dàÞc¼tiÀžŸÔ­Ó5G9;“M€¥ðy5 • °ÿ.ºo¾ùæ³/¾ûÝ囲Z­–Ï€SyÄ<}ÝqA«©ãÕìÌòÂûu~døo+ìJ‡Ï¸©3 SÁöƒüíé‰ Ëc>_î:‡´}G†½ÏSh§m½ÿ½ÿÆHçç¿q@gD§Dï'–/Üiöš6ZUó¬oBÝ^ý??ZTÿ?Ö&ãÁªÙõ¿ëtDtË(˜ù_û}™Pû¯öÿ(ÏÚÿ—ûÂüˆ¿só†t0Êœp~Äw®þŸNúض‹Ý—øôÝÇ4[¦ö_ýÿÿ öÿÓÿügoMz9FD¾’—4Æà‡ú( å4çúù9w彈ì#Gq •>Ù º ÷?SŸ9^ˆ,ê‡×=B ½Ø5°Æ[¨KÌׯÃäÅÓ¼h}Ê,P6u«Œè…ôÑW_}õÙ_|±×èz£|I·¿Ð³R~èS‡øÑ–+o2—ôÔwÊŸ¾:-¨6í"›<%–×´më˜kñ@“¿¼.pnûâT¡Ð)?qêJßà'-4½ÿ½ÿ掷kÜ츚1Òù@ïÎÿêsD /«ÿÏúa-ôGÎ鎮ÿ]ÿׯØÑqû3c£ö_í¿ŒØ¢t†8ºäžVû§Níÿk­©ÿWÿ¯þÿ¬%ÿýÿÇ;°,vqD³Ü‡žqXç›?ëÉLà˜ Í.>x^Òäç:eÔ¹ ÏÄŸþ"+oé§šUHÃÇ ñ‚P¦1žyûÅÃI|\x£ÒÏú÷x±¨vxôÀ&!ý/v('F§Nuoÿ)0l¼ ~ûùõþ÷þwþ›/ÿóÈóü«þ?:Ü.ßèäêÿ_ïz×õ¿ëí¿ÚµÿkÿóEêÿÕÿc;¯Ï}ù§l¦øºõÿëÿÿSà?Oðï~ü–òèÙË/€…”_›í#à&΄=Š+´ò âPð–·õ ¨${äX&±é9\«8”_zåÙy•º†xA¤•qèÉŒF8õ=<÷ty9RŸvHK{ñÒùâÔéz²¡5AïåÔûå—_~öÝyÉ»vËÇïå_}yÞ›õõ×_/¿”ty¶6ª_ˆ¬éËM»Ò#odHߢù4¨[Øv\»j\o=SWdïýÞ%×ûÆEççôSýÖ·êï”ìúo Í»ÁÚÚõÿãÐjÿÕþ‹ÊÖ­ý_ûßz÷mêÿÕÿ³vÆ· |±úÿ#Ñ#÷þ©ÿ?¸Éÿùÿþßc{Ãú«o>yQy 4‹]F 3[Àœt¦¶î Ÿl•ºOæGè¾Kùu&d{$OñFç: Sê²+j2˜y2ø”Z>î>ÖŸý[8žÄüš„ÞiOS”†ùÉ®LúL9éʧСÿ½ßû½õÙÊ9‹7cN¹wß¼[>Ê¥dp­nâF¼ŽLóà´½vfßË£”ŠÉóž.ò†nËOú$© ÞMÚTùÙËW/÷Ï´‹ Ësú]§îð›“M÷gÓ&N¾4ç‚fQ–†PE~-ɋǥ¯ÜçcE9À'ÒBâã:`‰tàJqú;È"Í{­ÄÙFˆ6`ËSd¾ø{Ùyv/í®(åç…é‰Pòt–r걋)&n‡ªkŽäÇHUNdNŒž\‰õ‰Ç÷=\ÿÜ qÀ!¼¶]ó¥2yÁ> °MÎÃmœ§ï’æÚÙ·Ïn¼Ô+?u ûˆöªÝ~ÙñVoïïçç?ýJ¯Tÿ­/¢§«ÿ­'tý?öE×ÿÚfDí¿Úÿµÿëÿ]Ëcý¿éˆúÿõÿƒa˜li=í¤ýmøÏÓOç%îØýÝ =ß™GÜÎþå± ¶/æ {!ú¼@+‚EÈ&V™e ‰0„%P„ßó¶à'Ðß_R®î)¶ƒyÍ5ÀiÁª‰d¯XÃÛŽ±OÞÿt.iäÄIÙmÿ”_y®|üÑË“îå÷ñ½¹Þ]_j˜4;¯ìvR?zM¶I«OýÍßüÍ>V(Ïî5»ÖôQ~¹B·Ø¶óô—ÛPî“îy(ÈŸ¶A&¥ x’G^bmÐè»-?çöõþŸñÑû¿CdÿCÿÿÕÿÕÿ]ÿ»þ×þ;ö`í¿óÄFíÿÚÿ|Æúõÿ8 õÿëÿÿøÏwþÿçÿúõ˜d ^Ø´ fN;žäã·e†ÇÖwñ:`Ž…õiw=¥ÎðtM^òoû¶–S'ž‚Eùóé+2I9ß6"¸êw½ÀÒ•çz½¿!ùÕ bý¸i{}É9eji7yB“Oé@'2‘]H¾<åÉï|ˆ͈¯LúGå•“–ǃr ôêý×K½ÿÆGççõõ×ÿ®ÿµÿjÿ­}|ÙžlÅ„ÚÿÇÿ`G×þ¯ÿgn ŽúÇ—âO¬o:Jƒê¸_Ó%ñc¯/ée·/¯tþ­òæZýÿç~û]ñÿ÷X‰A`D2’4±#M¹<æ‡nк8;Zœ_ôøíà]?®Ñ;Fë½|»ð~÷~v]r冈•Å?ùŽ li“0PÍ5Y&vPhs&߯f+¯ür¸ÆßÎ'ùáý8ìRSfòÅ&Mè•q¸&9•KH=ÊYè}ùÏ#{ê$‹²»{Jý”•¤ãpÿºSøà}?¿÷±:OæQÂK†ÐÊ–ïÔ)ÈKˆÌÚ ßÈ ß…í߉Õ%M¹Þÿ3^zÿ;ÿ;ÿ«ÿéÄêÿ®ÿ]ÿkÿÅ–b;ÅþªýWû¿öý¿úõÿëÿÿÃðŸ§üâçoZΗhg\CŒQn"ê‘=Î×ß|mu^@…€çý<¾öæÍ›ÇÂæ;—žA!@ˆrvl}ý^sÉWÕG²,ÀsÉYÔ'_H;Ðîõþ=À ù ¸Œ,@¡O#ƒ2O/Î ”á·í¹dGÂIWïÊ>±<<>9ÿ«Ðƒ`š¶i“wh­l#Gú[žm§#ÀÙ6±¾‘ÍõýÍÊ<é‹Rʶ¾ýEàÖn )þèÃG½ÎsDžÞÿc„ê_«Ïzÿ;ÿ;ÿ«ÿéêÿ³Žgíéúßõ¿öß±1ÍpìvUí¿c?ѵÿkÿ×ÿ«ÿWÿÿù5%ôbýÿóÕkýÀ¾¶nþWø¯2¼âÀŠ8èÙ•„.» û~¦ÙE´›M>ZeíprN1áósàhd!—¿2L¹ïÿû{ŽŸ—¢^~d°Ø #€ÑËÏÞMÆÒ๼ s¸r‡]EäüÞ÷¾·_XôHxƒÞcê!¤ë“–óü¹šD®4ûËÊqú%à%_¬þGz²ªS;bìyg—~Ñ×µ„ÊNâʖ̉ÕäÝ^•²i7’“6Ñ¥|äîýïýïü?à­9Ñùÿüè¨þpTÿ_Ú´ú;¢ë׿"×þ;öWí¿ÚÿñÚÿõÿêÿÕÿ¿¬ÅGô‘?ötýÿƒ‰,ñ÷Àžþàßýø- Ç!ˆ½# ç9òëÈ»Xò~¦¥¾Sórý[pa×'ÝnŸå7±47ÏõýØJ¯?øùË_.P”Íar¤lè4¯ùþøf‡QèÔd·•—–{4///| Ín§of7ÔW_}µòÚµa5¿}´k,m•-õ,ý­ïeШÏÇÈ[Àhòî! Rú½z×1B‹!ù¡e$áBiéO|Djã#lÛˆIÚ;´õi€<<„íÞÿÞÿÛ®vþwþWÿ?ï¨þ^ç»þŸÝËYŸÙ±ºþŸ÷xÖþ«ý>öjlÎ5<çOíÿ÷k×þ?>•qQÿ¯þ_ýÿúÿY;²VÿyúÉ_ýÉÛŒñ ÈØyÞ¿{?»€^|öÅ< è‘ÎlÞû„©ó;È"߀cÌ1ÞÂlm”žÊ%¹ÆGì‘ÄÝR8´BxâlBÔÁ?Í·ô¸æ(ä¤K3€’òyYÛVÞKŽðJÇÙ5v¯ ?ya³«-Ú9ÄúôÁ^ÈŸ¶“ŸÔi›Ü›7ž éʧ®óxây<«”[ÙôÅE¿¼§½I÷+iÎÑ8ÜßO§“—_ zÿŸ¿6föþwþï¹MâÌIIÿGŸVÿÝ:Êöè[cãvžáSýÖ°¬â®ÿgÍéú_û¯ößüÈ\ûí{ëGlÚÿõÿü8’Pÿ¯þ?Ü þ;¿ÞùïŠÿÿôƒ?ÿÙ[“@ƒ…LŽªoæQ>àÀÇ>àÔîº,¨1á7?@×ò!ÃM§;,R $]7Aþ!¼ä§nçx¦îoÞ}3²Çüðõ ˆ© 0ôt4‰æî.x# å†ïÍžx iœï ˜sò8ǃ£*Eºx/\Ï?€Ç¦O9TÎÏñ1|Ã+mSà0ý‡ï‚oS§U¹WÒõÅwÞç%aΧ¢S÷^’äôû¶gòs"#¹Â³÷ÿãû£KõOïççõõ×kBÖì¬â„®ÿµÿb[±ÇjÿÍÌ.Û³öÿŒ¶øÑ%µÿÏ+ ØÛõÿêÿÕÿ?ˆ£7ëÿ¿X=Iož¬ÝtÁóKè*ÖÙ¡cñ0EÉæ¼· #êž¾><ãå>ÅLšCÙRICP¡ÄÔ-(‡`M§’lD¿\Ê{9 —t`ŒZÑáí1¨¹X~xy¿”Gûä+ç ‹t…_Ú¦B ÔÈŸô¬ÎÓ²m㯧ÿöü*»2\èS&çbíÐnqÚ¥>ç÷þK{òN¾ œ ^ìþP›>gWûS/^b®¼êïýïý7;ÿ;ÿGoÐ3tKt…˜Nªþ?ëWtyõÿÖëqbýs_¿fñ{¬Ö¨®ÿ§?ºþ?ÛEµÿŽ]kÕþc¶Öþ7²Ó©µÿëÿ­¿Zÿ¯þÿè†ßIÿÿ§ó!E8šqŽó IvãøµÙËØu ÊsÑ dq.±Ê‚}ºhä[€B Û”Ýüá½uîóxWÔІ&ò¤~¼"OÞe…Öô2©^ÿåW_~öáý‡qÀOÚº¼¤ÿmã9_y®ŽU×@Mû´×Úw…O¯÷~N¾ûu^Ò~îÚ£u½ÿ`íý?ý`LÿÿÕÿÕÿ~ÀÙµâZG»þwý_»aì¶ ›Æøˆ%Rû¯ö_íÿÚÿtÿ¥þ_ý?yYâï¯_{»®ÿo¶üסþÿoÆž~8/qøwl ¢ 0_éóBwNl^ª¦3ågð‰0‰3h8=Ê Q‡ºÂû+„YzòÖh~:@€Å3€Œ|ÀÞ ¥-;çbyh¹F—Cþ=ä×fm?é£lçEéε™\ÚâZï¸b¹~“î1½U MÚ–›z…TÀ‘ôG¾€˜ = “[tg÷Ôˆ{ñoùG|”•p ‘-IºKnu¹èrÞû¯/zÿ3vŒ¿ÎÿÎÿêÿêÿ®ÿ]ÿkÿÕþc²ÙbA\û¿öÆAý¿ópý¿úÿù‘¯þÿ,ÿøÏÓþì§ouòÝi]Pc냖žGÍ81y/à8妘Л¬‚4ޝ4à‘k‹ÞÆ&ß¹† ãÀDMÚ)+=Ox!L†´s DiçZýש#4gלfÝyA»¼Á)Îõœ¯¢™¼mLJó¨£smûâ‹/¶>@’2‚öäøÎ<ê¨ÎÈšv§ è£Ošú·ÎíÝ#‡r9ðrŽ>eõ•÷ŠÉ»ï:Ã?AëÔûn®¡!¹zÿƒª¿¾íýŒ›‡ÿÿóÃAõõ×ÿ]VkÿY;»þïºYûom5}ÁîÍeÄĆKZí¿cŸú[û¿öý¿gßþ¨ÿ÷¼écuæ(Šø´õÿëÿ Ávž~2/q7H$ú—s™=ÀšÉê¯>Ú|•G—æÜßY8•@IDAT`ó¢tiê094ƒµÇ„SÿÔ3uå:YÞç³Ëu¾È@Ìy÷þÝ‚:©8¤eœï‹ÒµoŽÔ©üì:B£ìxȧÊoý“g¡˜‰óKdd%°2OL6áì°ƒf®·îKyä €äZÝ:GBÚ$wù§½r¨Oéçò©/ý¾øÝÏÓ¾Mëýïý¿^çç¿¡Pý~D¨þŸõtÆC×ÿ®ÿµÿ^¯@?²Ÿjÿ›òaÛ[7jÿ×þ¯ÿ·>[ý¿úÿñÇa Bý˜ÅA-&ñ÷Þ~8ïÀÒ¹:4 P€›üR Å0£U.à a„#Ô¯?ûîw¿»àLøÛ±„‡_ôçø+/(®—÷4`öÍ×ßìõ¥<>7ÿ®rŒª—¯æKˆƒæ+Gš|©O?¡÷ÿŒƒÞÿkœvþ¯éü?À[ô^tQýÿ¼nTÿwý7',¶]ÿkÿÕþ;þ[µöÿ±±kÿ×ÿããÖÿ;>,›’=)dnÌÉúÆÇ?­ÿ¯oôEýÿóDš¾xúÃy‰»ŽYàäÖŒ’õPŽ%žü„3¨´ÐA[2SFÞ)3@½?Ê》þ.4sèS>e~§Ž#ƒt:»ˆBÔ2ìè I¾òá·SãÌM³CèG ò>,ÀMêœ )º¼È Áó×@ºv”ˆ+ÐkätNŽ€JJâ:q¤<á´qv^ù2â\‡FÞÖw݇È*]™ÄèåùJ£îëË#ûÐ Ïí»‘4–ròí$[ž{óÏ¥ÕçËU¯zνù¸Þå5o]2Ò{ÿ¨¨ïôOïÿÌÍݧ?2Î2v:ÿ;ÿŽ©þ¯þ?àà®MÖ¢9¢/ºþ?¯ûÖýÒõÿŒú#ëÉš~ûç¬7µÿjÿÕþ¯ýÿøpõÿêÿÕÿÿ­óÿŸ~ô—ü–Ñ#d±wœ `AÑe´ Z JŒ¤1>ÚAÄ'•/ eDĨòŽ*yêñµ7`–šc˜n¡ëz·9ä{ŽS‹×È‚êP>¼Äx@¸…ó˜ßÙ½µòÉŸ°Õ íÙë ÄqÞx-¿IK,?é‰ßœ¦m€¯ÐJ"-çÚ…O?§>ééið‘÷þÃá`L£^ï¼ô­öÝeÅcïç‚îå˜B³Äó'õo:õ²Íµºµ¥÷ÿŒ }Ñû?£¥ó¿óÿÒ9«—ªÿW/DçWÿwýÏX0?ºþ;J_$˜#c\[£ö_í¿µ­jÿ×þ¯ÿGOÖÿãuÎz1ÿï>óúª×º‘5¤þÿ¿lÿßum„X£Áp,Ð1ç ŒLƒÂ€Ao"9ö—¬ËÈÈ/“½à^Ç:WE®qP*u¥î/òr Ï¯¯{>² }„K.9ÉçYir9÷¸¡ÇæVnõÎá<ü—æfî21­~}ñÓj4Ô¡€@’kï÷Q§kéÒìÌÚü©KÞ—¥\úaÛ‹¯¶Š/¹ÐªÏnµ7¯ßl3µß¯Îò^½>/ÒÇÇû¸î}±çC#oùLiiÛ.ç{=ήûg–¦÷ÿã1Ùû?ä“ƳñbL9:ÿ;ÿýŠI·TÿWÿïXØ¥ä¬cÖG×ÿ±.Ùõ¿ö_í¿Úÿô¢q°kçµ~Öþ¿l‰k ‰o&¢C÷|lÑõs6gþ\viý?æúvFý¿úÿÿ¢ýÿ§Ì#„Q 3êwÇeÁ9]åz);y@væ¢P  C¼î*ß½<×tv¡÷rsñ·£x¤ã¯Î™jX¹OÒsšô9Öi¾hùúB`ðæ`¯“}•ŸÔñ@4×Þi£ö´_¹­cò¶Mm;/Ãsó/íF ¤ò-mA‹—vºÎ‹í<ûvúŒá*0æÜÒoWÀKÊ'8WçÓVÚ¿¶(ŸþÓÇÂûɇ6K5;ÛÐêçmûð _r¥ß÷žÎµ¼ÍŸXÚÖ3² ÓgBïÿµ›°÷¿óçjçÿ**LŒî¨þ¯þ·zíZf-éúl„®ÿkSÔþ«ý»4ö«u£öÿ¥3kÿ?ÆÛÂX‰o"^ßlìï%ºÖ™ýõJ@Ï_r¤|ý¿ò­7RÿïøºÌÖúÿÏORý¶úÿûw_XÃsÏιëý•pu) OÀ”»Â@»JŸU2gË‚>Wž|×@‘/çѹyîØ„z”:!ò ¾j8Ùhå“ë‘7ts± ‹QÒCƒŸkAYºnóÑ ‡”ÃCÉ%N=è’‡×çOSvd@G.ùËò” =£íÃûŸ†oÚ©ñÚÝa êrú`„Ozñæ}îyÓ©ç ¾¨˜:];w§Öçþ”–¼œ»&×WûS·ú‘­6áÞûßûolf|dldþtþwþWÿWÿwýŸÝá£'…¬£Î»þü؃>â¨Öþ;6jl°ÚÏþ¾`3×þ¯ýO_°=ù.«O/»þͨ‘ÍGSÿo}>}%lÿìÙ9w]ÿïà úȸY|ú¨þÿÿ?üÿ}„Сøãhf hܰ}ñ÷äÏrñÑ ¿ÆúFxl˜A>IÛ?év|v¡™—‰¯‚ ý¾—S¯r†®Gó„ÐPQR;‡Úä‹¡4Þñ¤žK3|Èa'Ó–UÇÅO½ J ÷SdÀ*¿´“¾2 _×ÎÑ‹—÷Ô« O¬Í 4bá›o¾ÁdŸe&¤žÃK¾zðIPνYLÞd໼¦.ôÚšvG&4ÒÐEn<ñÞë‰ïŸQUGxˆ…ÞÿÞÿG^ü?ÿ:ÿŸ+ú(s­óÿè•U7]=&¶õ¿ú¿úß\éúßõŸMÉv£ãØ£y)1:JM¾XÎEv´i“ÎÛ¶ÍùæMŒ¯]§nçé'iœˆ_  µý?ù~µHßÉ[Å1e†á¶Â¯]Úýêõ€Œ^éu)By_EôuļuóF–ý†6ô½ÿ½ÿÆFçÿè¾™Wæ…ÃyçÿÀõƒ@¯UÿWÿ Æ„yÒõ¿ëí¿ÚÖ†ÚÿµÿÙ’YâÃH3>êÿ_Vÿ¤ŸêÿÕÿ¯ÿÿ߯žþÕ¿ýÑ[@•B1q„uFâ¨Íõ¦ÏÄŒ€3&ðå£0e®«†f¥]¼†j1–“G0»ˆÖ š|åÔt‘æøvv íŽ$]2yQÚ½~e ¸ðfÎIÛzÄŽ©€³àÒÈzàŸÉø$'m’…G®ày1»öÝï~wy:—öúÍ›­leÙµ? p)•>~Ù»økƒzðw A|É­ïɰÛ/y²ûÌ}R½¼À4|Ô¹}¥Ðyú¹÷ÿŒÓÞÿÎÿhŸüéü¯þ¾74¢GéÔêÿ®ÿÆC×ÿKiŽí‘¹bnÔþ«ý·¶ç*Næ{íÿÚÿçÇ{c¡þßÑ›õÿÆ#¯ÿ¿ƒa}ó±)ÄõÿÿûøÏÓñ³·ïß½_`ÄBÈÒi”‹”6'{¾Š÷BGòâÜíƒg(/ˆ÷ù÷á±Ò¥×¯_¯]*#àì‹/¾˜Öž°ü‡OêZðœ]fä%ûööMB9Ã?AÝÊ«7»åäKB᥯ñ†{/•Åwã«OÈ&Pš€´ÞÿÞÿŒ£ÎÿÎÿêÿ£_éÈêÿ®ÿ–Ï®ÿÇÖbk°UjÿÕþ‹=º¶¬q1úrϯ˜þt]ûÿühÍé¨ý_ÿÏØy2s£þ_ýÿúÿüçéþÝßZh,F †_»{0« ¤ÉKÂ$š ˆ^8±yDí/”}'ÕÄÎñ΂42Sç¼ÁOI' Bk1PZ¼çdóýâ€Ú¶ £ÜCYÌùOxí‹Í§œ2êÝÃù<hw–`Ç׆©çÔt#üÈüáÛ#w”“ôå?Ô (Má탌È#ìã{snG”Ùœ£QÞž€'4®SoÚ¶÷lÊìû­†‘²ÔO{ï&3~Ûg#Kï¿÷†õþwþwþWÿWÿ[ºþwý7jÿÕþc+Öþ¯ýÏ÷¨ÿWÿϺPÿ¿þÿ¯#±:.b3¸Å?þóô£¿ü£·i,¹Íã¸,03€GhØYPe,h±ÙÕ#m!™‘œRóå¿M˜ë-;ùC´ ‰]QÒî@ Þ x ø$DIºm) Ðõ~v"‘GÈî¤4+ßð O›Wû2seæ@§Œú¶¬GGVî©g¨‹ùÓ¿0<ö—¦áóí€YúT}t[V™‘N…Îïmû´íz"uâ#/aãI _ §þq¤]ø£Q,{=à~òî š<šÙû[íýïüïü¯þ¯þïúßõ¿ö{,6]í¿yEíÿµûkÿS2‹¹Qÿ¯þ_ýÿúÿôÁ?5þóôƒ?ûéÛ'1ÒG = Ä(@Wó¸H¹—/ŽsTqm”w1g,ðË{Òñtî<`QøÅHL ɹôì<ÂÏq/‹§k )zÌ?¼ÞÆàØ€†Œ_ø›p Òók’ú„Ýu«à³_iœÇ,ÕðÉ£‰ÒµÓMмù²bd&Ý»Lbr{WU¦ž®ºÉ’w^9WwQT.´“±@ÔÓƒWK·rôÉ‚qC§ïiï§]‘邏e;}%ýê´ôyïïçÿy4¹ó¿ú¿ú¿ëÖÑ]kg]çÌvý¯ýÇÞb§ÕþcGÖþ7îGíÿã»Å§Ó¡õÿŽŸVÿ¯þ^!TÿÿØÑúƒþœXüH‘Ckxfò,°1kÐòõ×_öýïÓþ ÁÔa‘¨PÒÞ"OÙT£Îµƒ.„‚~㘶î+Ó»¤Ô-˜ò¢8–ÿ4BŒ'%¸r‘gÙÓ±2Ë_»6” x3™+‡-në¸Êá§žï x…kìø x=ê™k•Y¹†?ç¿üò—Û÷voå%ìÒ=’(8ÇÇ¡/ÅÊ ZçZÔ%=eÄä _è¤ Òs¯{ÿ{ÿ;ÿ;ÿéˆè„èKJ­ú¿úßÒõÿr»þ¯ý¼eO°;Öö`‹Ì5;§ö_í?c£öÿ±·kÿ¼¡þ_ý?ëD‚YB_l\ÿ¿þÿŒ…„ÿþóôÓ¿ú“·¾ŒÇ@=F`d@" Æ áÔh/ç±31ÅÀpyé³²hņ¡¼w³kÉ Îm)ÝÁy 0o†Ÿ_,•Ã#]PFºº?äýO³óËçVX@‹Ä{¾H?e¯ÚÜIýø² ºê•¾õNyQ¿DåÈhQÆ_Mžû\~®¦á¹ë0"Ý®/»³ðÜ~šwaá«ÿÞ}s¾,x[ÞC4‹Ìè—Ǥ ó«>iä¿·Mšà}VÚ3Ì–ßÒy×ô›_…ÞÿóN±Þÿ'3„ëÎÿ£3:ÿ«ÿ«ÿ»þïB9ºþ×þ«ýWû¿öý¿úõÿëÿŸþÁטx±—Áþ9🧟þõŸ¾ @èÈ£g ¶}®°ð˜_äEØ/¿ür›ìl’Çù]0eb_À±/bà Ç@þ–ügA#Lñê „cv‹é€WÊ“7;ȶõ\`:ú¾œ?À )#(¯î¼Ó@Ù€Gé{†^9“§î' k:dy-ó‘åÔ-lû'v­ŸñÔ¯Ú·isg‰,)“:||r~—ïN#oa }ÚöFœ]ÿ¯/P½¡/„Úóckí¿ìOz¤öíÿúõÿêÿ?ƒ}ôâ8ßÿQÿÿ¼ƒ˜¶|úáŸÿì-'u³ã‚S²†ÆØÀé€(ƒJgÚ%öu¶!\cd‘9ÈL÷®‘¢¬#‹RŒïFXÀ.¢Û³®@»¥‚Ö«À éà9õH÷âòIdPV£ÔE>õ s~‘ƒodv-^žSþ´h›udÂoêKH{ýœ¼|ÉÇÛ_Wauíõä¡ý|ú%Gj3`ËШ׵vHßlå«Ç!oë—1A;êòþŠíïikïÿÜ—é¯ÞÿÎÿÎÿ̘ ÕÿÕÿ]ÿÏÚ鯵tw˜Ì:šõ}¯Ÿ“»þþ¨ýWûËjÿ×þ_Ÿ§þß·úG/Ôÿ¯ÿÿ÷Â~öþõ¼ëy70Ë£cƒt,b'FCMXÇæH^@i¥,ˆ$ÍÄ X³ ÉÐÇÐÎ% ËR”Ø}èöüœ ?ô¾2ˆ>áŸúðXCsäd9—'>åÎ+çøIßz&ήé[‘Íœf!–º†ýð¤/ïKÂ¥MÛ‡æé¤‘cé¯2A ¼²^ ¬£ÏudAïúÏyÚòHÛÜgºÈ‰Nß o ™¼\«÷¿÷?c­óÿì*íü?ú«úÿ(Ö]#æ4zUjõÿÙílm2_ºþ›3óÏZ=G×ÿã¬ëvOí¿ÚOóãiíÿí‚]Kjÿ×ÿ«ÿ7ËåØSù¸×5{ËQÿ¿þ?‚yÇž~ô‹Ÿ¿±²Æy9úù¢b‡]R^(ð°HŒyç–¬ÏÉž¯ñ6e\Œœb´Ž1båðöòp#׎#u›È\gah"zõå—œ7¯ßì[ú•——|åâˆ{Iy¾¬¦ŽKC'ˆÉ±²Ù•4çkd,¾k˜OŒÖB“2ê:†ûÇp Ï*ïÖuš²×+ÞÃOžþûú«¯6Ï{¾¶Ì€†»+nÚ°ÿ†OÂÖ}] Í‘üÿ‘y2÷Q°m³ë9”OŸés÷UÞûßûï1⌇+ÿ;_:ÿ«ÿ«ÿ»þÓ‰ël×ÿÚµÿjÿ3ï­ ±½×€ªý_ÿÿ5>ÀV¸ûjõÿêÿ×ÿÿ‡ã?O?™¯îìš?€ €Çd `%ÙÉG#5vîFä8Ä4†Þ‡oÏKÉå‡ÿù/ÿe ‡ö<Îà+„Ësh¼ß(/u_e82Ѝ¸Ún7ÔÖ{;ÎÕgúƒ#&ý<>r€±Ix¼­ü”]ZõOZÂ&_WÄß9 êý8|Þ…µÿ¦Ü¶iø ú/üßxÿ¹pß—»-ÕÜŸ‰óR~¼õÑhwÚ3p…ïÿììýßÑ“y»ã¢ó¿ótPõÿùq úÿì^¶¦8ëŠó®ÿg­Îú;'kövÖüéú_û/c¤ößwÖ.×µÿkÿß`Ïú²þOý¿]>²–˜/õÿ¨ÿ¿ãâwÕÿúÁ¼ÄÝdˆQµ Ð€(1PM˜ÀOvIS.Áâ£Lœ^Ïv£ô á’1wS­/ßy&zï ï<.å×J€:ewº­ï’—ÜÊ¡ßö]mÜER]O‚‘Ñ£’dÿõõõµ•o¤HáåEsÊ~Z™µod\;Vé?2 ÊäH_'}•ö”I¾òy‘»4×û‚ñ t"‹ ½›§þ„¡ÝpÕw_–ÿÜ{ýxIOšk¾ŽÞÿÞÿ ­o fˆ=»ÎÿÎú‚1ªÿ¯Gͪÿ»þºÌÚ~_kiQ×]ÿkÿ±õ#ôhí¿ÚÿÑÆCíÿúÙtPÿ¯þ?ÝPÿ6(ýôz„0`Àlj#²“eŒ¬U¢ÇA¦#Ñ:8.9GïÜcpÜ\×ÀÊ Òb¼ùõöì–²X¼òà=åÔÅ®_ÏN.¼×Îí(R?ÉN¬¼H}ë9ò”|Ƃެ<¶§,ÙòN |IMö¨3ç[ÇÕžàú“6’ÝáZ¬~ç‘9ÞêÊKÕ£4©KÙ‘…^HÞ^ ÁéÕ½º’NŠú>=BE~!u¥o¥¯\#ó~ÈÝûßûo¼d<97VŒEã%çÆ“óÎÿÎZÈx¨þ¯þïúßõßÚ!Ð µÿjÿÍ@ØÝ›;(®?µÿkÿ×ÿ«ÿWÿÿl ²dÖÿÿ øÏ¯—¸3*8œB  Ï¾}Ò€/¼¡S¢L€ ”G,8³ÐÁGù¡g¬ly·aïÆeÄ\àŽVûÜ»rWy` >¦<¾ÊÆYž‹ÏÞÀ¥ì>ŽŒ~/_/îc†N êO»\?·±"¿|€Öþ#ã„cd@O>yÔŸ0nÙ¡¹êYC—¾T>u?ò8ú7þÚ-h¯ð(;¼Œ¼÷ïÞï®uË÷°ô½2+íðL,M¨p®žï-™„ÄdK½Îÿ?öîmi“Ý8ô"ÿÞ­µ$]΄-‘7’7s²EJöxÎ|0}àƒ¹Á‰˜ËpÈÁµéîEN>/êýþê=²,É’‰îúQ$ È|?T•ð¸Î÷þgüìýŸ±q3c§cÐùÎÿ3¿îsI¿8:÷“·ó?cˆŽéŽÖÕÿ«ÿwýßõßkÿ]?*®ý·öÿÚÿÌŽÊúóTÓúëÿ¯ÿ6KðC/q¿;]G_Œã5Õ=€žñ[)9F™&‡žó!–çh’‰6qw0•¿XÅDZ;Àp„ó«¬rÞ PP© Ø{°|1çSçè£ÞþbÃz7`O_ìîk~”™€TßM¹Ãs^?eZOw`‘Ó(²ëH>Ù"ÿ0R'ï`—LŸ”Ÿ>†Påë‹so´©|”z}±{ÔqÏožø.WÏ¥G޽ÿ{ÿg¬&ìüßù¿úÿ¡OWÿïú¿ëÿÚkÿ­ý_;^Ìn®½¾öÿúõ­\{Pܼc`Ÿ¿ñ»f %oý¿ã‡Nè—õÿ×ÿÿÿyúéÿþ¯Þš:ˆ@éö<Ûy œk²er¡¹v™”Ò:]àšÐeÀ]ÝMzw=h‡gÁ"|/ÇÞ± ÐÈ/xÙ¦’~ð圑;ïÌšë:TC¯lÛåX†§][¢ò/¸çÀ«€sžyV%íˆ,Ó^râáïpÞ¶Éã%ô9¿åµn1°lÄ ¸:}t£Å·oG@­I¬,ò#ÛE(½y•§e‘|Z^¥ßû?ý½÷ç?³ó?zÁ*±úÿèÞêÉÕÿVýYw¬UwÍñã‘ké»þ_?LÜ×ô]ÿO¬ý·ö»´¶·±×þ_ûߘ¨Žtž5wý¿øxúãSÿm–—õÿÖÿç¶&Ôsa¼4îù§ãç·Íÿúá¼Ä]#-]04RDY¸¸‚Åe“^ZiÎ5Ü#ÊI£tÊ·Æ+6å©Ñ( l²ÛKpíÀCç¢{?”X=ÊJOgO~sÊû¬æÚøõ×_d,⫝̸Ãέ>¢Ø›ÉIÅK~ÓÈFN`[Ë·mäMŸÄjŸ mrL=y⪯mÖáë\x$}êìh“ömÚ5|”" ¾Ó^òW&yøUnm˜†äzZüÈË;'.ZeÒ‡C‡ãQ~òÂÑÒÖ¡•^ZiÎñÙû¿÷çÿÎ:¡:’nXý?c‚n_ýÿXS²öMŸ»þŸv×ÿµÿjkUW¬ý·ö?¹öÿútÃúëÿÃÖÿ?øÏÓÿúÏßš.,˜‚mŽ#Æeࢠ’_U=†§3íb…~ÞIEá¢u”ï=–Hq|7ïÌzýêüÚ2Ä¡çyÿR~HæÝV}d0ü8ÕìCüÑù<&øêå«ìÊ"c–;O¦Ì /ÀRd›>ˆvcêÔvn‘Ež/(’á,.@ƒDµø¤Ã˹@çÊ—®`–|ôå).­À—xÎÉã\Ÿ÷\ùò-]Û<¤^rÏJ«ÿ•*2ÂÞÿ`÷þïüŸ™³ó?*!:gõÿêëË®ÿÏkõ,žYÛwý{qí¿(Ksdí¿g{¸öeíÚµÿÇᘰöÿúõÁÖÿ[ÿŸ~„)TOñç×ÿÏ»ÍùbÅ9€Oÿì/~ô–£Þ ãÚyÀŒ‚G.€ÅDæˆíd‹Ò‹é|•R»sºnwðgè”KþÔ—tÀ’úÞoUZù­›œ®#ÔÁƒƒUPÇ9Ú7ôÒêT^Yrâ£\ꌩò;‹e å'Éác—~< ÇIOkËÚa‡W¾Ž8´mûk‡—6º í3ùéÇ¡m?´½ø´Ðë_€+}—ë‘dò’?<|ðp ÷.­´?5‡ä‘¯züŽìO´Ï*ÿÞÿþíý?€ôÎÿ™g*5Î||Ì¡ÿ«ÿg÷íèßêÏÕÿ»þ³=výlæ…¾ˆÎ\ûoí¿±?Ùžkÿ?¿ºÄüXûÿøžõ‡Öÿ[ÿ=ÎîúÿÓt¬â÷ÁÿúÑ_ýì­K,ø^9tÌBAØ‘£cÐt€B®âéÎ¥0r}ÂCðóî*Š:HÆ(×úhM~ëk®•ýꫯ>ûüóϳ j ¥œ-uòÉZú‚+¯f§ÞòÉú q“çºUÁ¯ïŒá7uM±”U®}Pù‚iÇiÌÐyñ9´_Lv©<Ón<¼³K=ä 5qóÄä½×ÒUä,f“Zm x7éd½õµÃ[Ÿ·}{ÿÓU{ÿϘ2Nzt¾tì;;ÿþÚù¿úŸ¾_ý¿ë¿5x×ÿµÿÖþ[û¿v÷Úÿëÿ±—×ÿ[ÿýÿ³yæÿyúÑ/~öv,¯8¬çµÁ5ÇÞ¯ ÎëоË/f“:»® mÀ” \©àòðKÝ“ =“ýîªQÃvÒF½Ò àô±CiÊÊXñ5Ató_þæ³7¯ßœòCsœÉŽ­{(Ð¥Oõx¼NŸ¤~ç׎,Hú$¦®=^.ïQ<´ÒÂoda”“¯ —ºå©—¬êŒ?éú ÐÇÉÒ~UÆáÑ÷AÐ?´ø8GçZ¾ëÆòÕ'Èw.ÿevÏvciÛeÊ¿½ÿ{ÿwþŸ™;ÿϣܫÿÏn_zrõÿ®ÿ»þŸæ¬ý·ößÚÿãO°½Ç–^ûÿÙ—°VÖ79ëæúõ¹Öÿ;>î8žëÿÞ0Oøçp•õÿ®ñ_ò+ŽÙtœÎò«çœ<פ”#úÊS޲ŒäÅâß›aý@‚¾¢/Oqepn‚;ÔÝJvQ©‹¥Çßd‡“—¶+kçˆs­|”Ä”Ô.MÀǹC]òÉh@#ƒéBÏíp}xÎû±¦=‘s¾‚(v-àõË_þ2tè…I“žx®Ñë³o§-dqmw™öàGd¢a ®›¬’ÐŒ ˜[rú¬tÒ“µË=CWÀêäNy2Ohß«CÙ”fiÛÔIæGºÂWÞÞÿ½ÿƨñ±óç¿\÷½8 ôÇêÿÕÿ–‘®)Ùá:ãĘéÚ³ëÿ®ÿÆÇÚkÿ±3¬/kÿ >zsíÿõÿÖÿ‹-±þÿU—ÏÎâßÓ¿‹þÿÓ~ñÓ·€4PcÓb)Ðpi±ªx\ÏàˆQ9€JCËrLäåýQâ!°ØH»;4ÀïÔqÜË:ïuy×ÙÀ™²x%¾@r%ŒÐè»#+@Îdôå òôxln‚OA2âÇpö^*A;h• _åɇ¾r†ç•ž‚óG^~÷Òv×díä¿~= Û»óN,}Ó _Çw÷—tƒOûÀv«Ð¿á5ôéoñjeòN+=²3Bž]h³ë ß¾˜-~Ù…6W柮¾üÙû¿÷çÿÎÿ£AWÿŸ¹@ç®þßõ×ÿóHp 6Ãe;˜kÿ­ý·öÿÚÿÑ£Öÿ[ÿÏXXÿýÿÚ ÿ˜øÏÓþÓ·e,fŒäÝOsÎ Äpæ @Gßç gÐi€(bÆ×_>@§9  Eè~-è]ÜÉ›Gõ„Ô?ihðì–\¿ì¿Îco¿:²Ìµ:ÈⱿW¯^Ði@™¼fdÇ Ÿ‰‘u‡LýÃ_ÝÄC62Mš@FyÒÒ'kwéÐ4]ü¸VÚ‘QŸ$9¹¿dýl›wTM†Ç…ò&»#|ë€p&mŒÌ“ÒÈ¢“ÖDýå7á…_Ó*oæOÊ oïÿÞÿÿ;ÿWÿ¯þßõ×ÿµÿÆ&ZûïüлöÆÂÃVfÛ¯ý¿þ_}§õÿÖÿ·V¬ÿÿÀSà° !øË?ÿ™¯þÙ[J¨¡Äè€ (2é©xÎV¸83 ðÊŽ¦^‡ÙÐã@ ÊìL ’!˜ëçÝXÒäªCÙ‚=y§Õ¾¬Ô?óbs`N%pÍc)7åËÈÕÎóÎ <G§.2ër6žäúÄõ‹—óÒ÷ùW:<µåðìÎ2»½„^£«ñ°» éä—<Œ,ÓGò<"‰÷G홯ºÖvݯ†^uÊâG–äá=2ºNÝ“_YÑ’°×{ÿ÷þ3ÆOŒ­kŽ8ŸÁ²óçt å±úõ¿uÄÚµëÿ®ÿkÿ=Û{kÿŸŒ}Év`gÆ6]û?úríÿõÿÌ sbý¿õÿ×ÿÆ„þ[ñŸXuV}áÄ"S £àOÀžI—'tà¥,'æÕ€WßÍ‹ÆýJˈgbx"([É5ÊÿØí(å8ÎÒ”U&N³\WV×¥!GòFØ¥¥ñʈÊ/Ç órF>¡;”ð`ˆ‹ó^­ ¤#óT”6â#¨·úÐLzé€S—üúÔ¿ÊÞ—¢« _À¾¹¾xxa»XúÝ/žèªèði{Ó7®§m;$—4ùyîõ’µ á\>v𩽠α÷ïÿ5¾Œ‹ÿŸÉ±óÆÝ#¬þ_ýŸq`¹æÆ®ÿ»þ¯ýw@šµÿÖþ§O²ö¿µB_¬ÿ7þÙõQ´õÿÖÿçW¬ÿ0ˆócÏÁ!þ>øO, FgÈÈõü2Q:@»Ÿú(_^0(º”t/Mýæu¥Uà@KÀ•9ñtÁÃMŽ9/Oe¹K®qÏ“pýÔQ<&UÙîâJ°˜Ò÷gÉ'ŸrÀª×äSÖ{§ÈäÝXè ¡ÿ¡“ïœ\m—4בIúìÃ[~óúË CÇûº€nú¦ík5`°_ꟴòÐ;øøR¦ý•ºæm~Ž^Ob®'íJsKÛû¿÷ß8Þù¿óõÿù‘„¾\ý?;®®õJ_ìú¿ëæÅÚûlí¿µÿÙØkÿ_;kÒëÿÕã›­ÿwv¯ë‹—ʦÈ1‹Šþþ–¿šÔIŸ²Ñµ|Û)'Ä>ã—_4NÖÿÿÝôÿŸ~ü×þà én¤ÁÀút–ÁÄ¡Y˜Ìu'¥XQßÐ ¬©«±¼ûíxwÀþ¦|åBþŽ õå‹—©Ïµ<¿ :y9 9¼‹ `ux‘¹<µ·» jœ“ ™§msØ¤Ž»ìåÙtJk*Jÿ„_úã<‰&¿ÞMŒ—|×b<m×Ú´ÅÄ4!ýWFH~Òð˜ü¹ö¸&¢š‘ŒW®÷þïý7–wþG›Dßíü?:–~Yýôëêÿ3?¬»þïúo¬ýw쯵ÿÖþ_ûÿø/ÖÉõÿÆ‹ÏvÖÌõÿÎf¾&Ÿ¸>§>ç⺖ÖôÆò•¯_Þºõÿ¯ ,Ó?6žü¾øÿ°Î34f Ícd_+à1C%»¥ò(Ûäwðy”çv]ÛE$,¹˜¡/Ó¯Þu^€J„)<:HÅÚ+³y.•ËÙ¸#=ΰÇc{×àw3PàCóùŸöÕW_=~5Fg2Õ9ÁÃщ&]yõ„ùÚ^¸{Ô1åG Ç5Y*ã«ùâàd¥~<•yzq{4®){@UÁ1Îúä«[—úbb®/yÔ%}¥[ÉžëÉWŸ »+kâ+M^è\aïÿÞÿÿ;ÿWÿCkõÿ®ÿ»þŸ÷0Ø습ÿÖþ[ûÿø±³/[ž}Ýyb®¬ý?¯CŸÅ:Ê×Hÿ¬ÿwü®k̬ÿ—)sÆÆœ#±r²y÷¹u°‰õÿŸýÿ§ö?zû:(ßèß³\úÓ<ê<)b÷-y„€Rò œ§=ˆÎà+`dr6?ÊkF ÞèhO¹¡-Áz?wÝԇϜv—€gJÉþ“žÇ/ù>¶ô~ùå—±È Ô¡iÐnr7œ~8@Ö»áOfeðK[‡^}Ãì!Sû”,í—¿‘Aþ½^Vx ‘t’`CGFõ¬ íPåÚOéÏ«"éx¥ìudé;»mÈWe ½ÿé½ÿ;ÿ¯i”ñP cçÿêútõÿ®ÿ»þ¯ýGÔ[ûoíÿ1Æcצ^ûý¿õÿ>PuýÿõÿaŽàÁÆÛŒÂé8áÝÏ뉋ÿ<ýðç?}‹‰#…8P¹.À3U¥Dél—€PÒŸþyö%‰&½×*KÚ|áq¾çbáüÍiþ´ò#ß4Pð7y×5°‡¼dµÉN"2–¯2äÍÄ_|ñEäzä»\Ÿ³;i®½«mÔymç²¥ì%gùVææFÈ ïäé' ’ó¦«GPF>ZiC’]oN‰z¡2ˆõ]e ÍOýò‡®i!6´éþíýw—÷þg\MoÌÿŽ“ÿG‡u™[é'ºãvn~eNe¾ž¼ÿ«ÿ«çÕÿg^˜7Âù›ÓüùtŽõz×ÿ]ÿ3f kÿ­ýG¯²ÜbÅ®ýÿ·ô'ݺöÿyjhý¿ ü©]OŸ®ÿGƒø·þßoƒÿ÷ôÿúÙ[×-³;©†¤Aa K[…=èZºÝU o ŠÇñ”—皃&Ê%,X#O9Љ]¼‰12ô­˜†/´OÎÑE¾ð·Í./r4ÝÎ,@9¦ªÄò²rMjÛÈë=ZÙiÏeX3“äûEefùé“áÿ4íÒ‡-º¦‘±ýS9Mü´_èŽ1çäWÞQùñ¨†FºæQÃòB_YÛf´À†Ép9ÈÒã$^²ïýßû¿óçÿM‡­þ_ýo-Ùõÿ¬×ÖØ]ÿ×þ[ûoíÿèĵÿ×ÿ[ÿïáßòK×ÿ?8Aým¾ûúÿg³Î?þóô§õgo˜\»®ÚÙÒœ ŒXÛ ;‘'♼urÐ{¬ÐgBç–}öúõëSnhðù”_À–aŸº§¬¸u€q1å Ð<òæDþd†dÊUi~ah _)f-”²Ãã—¿üe@,uµ (‘·m«Ïäì{š°©õM L“WyÈïk†œF¨€I£ÂsúsNòRùN|eõ³ÐzÚ"×õc¨žk<…–¿²Ó'÷røè˳»®\“áNnïÿÞÿÿç½æˆcçÿêÿÇz3ãaõÿ®ÿ]?³ϘØõí¿µÿ>±[Çž<ócíÿµÿïÇߨO¿ÄÅèOMý鮇dý¿ôþËœšNYÿÏÈ8›AÖÿ?˜ÈÝŸg£™gs.ï·ÕÿúÁ_þäm€ž˜Q EÃú®+uíRÎí¬jG°Ì4˜DòïG;Í‚žüK5¡qM±¯ÚñeGXêÀGá+NÚapÈKå÷+jäÔãÆ|;»­^¿zý˜Ø¯^]bøøEU pS¿s»³2ðçvKyŒö¸ù} :¾Ýq%¿uTôß}8»©ˆ¢m@µjxÙi†?ðI»Ðà#-åçÜ®/`YÓ§ÓFeÕc± ò|zN.!åÚ˜i'€Myuâݽóô³s W.ˆÛoΞ ÿ½ÿì=Øû¿ó¿sfçÿ1$ôƒùAÑ&ôˆóÕÿ«ÿ Áø0o²ÍyÓº¶füLú®ÿ»þ³P:.ÄôÉÚÇ\ûoíºsíÿõÿø¼ñÙÖÿ[ÿýÿ‡iN<ýð?{KQ2 ¨¸~óæMÀDlOç½æøŒ!*ß!̈Ù:/.‚þ¦Û6)œ!F/#øaÐ\ïãaðN&ËøÐÎyë«\e‹N})3ä$@„ôÖ‘aÚª¬vx‡ð¦¼ðV^[È¢îõ©K:>¹Ižw…´|â @»I¤ýjv˜ðšºúž0×1þ‡2/ ÇuòË3ý?àÕá} >L•q4äúºH_üÙ©ëê×½ÿJÎ}i_ïýßù¿óÿ̉êÆèŸÕÿ«ÿ­ëÖ°kmr.ìúvC?Öì]ÿ×þ»æÆ[™#æÊÚìùtGþÔ6_ûí6ýÙ÷1Ç1w.?…ÏÒõ¦vÉc$É›#eÖÿK·¤/æ,>¡~¼…õÿÖÿïøømõÿŸ~òïþÅ[Â[<<!pT(‡t¼+ ×Ë…nvðgø=ÀÆñìnR_€¡«®N½{º2y|‘0tþ}oñu'£Z ª}óÍ71´Ûq ñ(ÏM™Ôï<†è‰ßUÍ—§Ÿ\Ë+ð¼ÚÐ6S²Î=Žvê|îO¼Ê#'?røuòåìni·géÏOÊHkûð(Ï;¿žãÛû¸÷Ïé˜Þ»½ÿ;ÿwþ¯þ§+WÿÊZo}³¦tÝØõ×vÞÚ϶[mˆµÿÖþ¯¾dóÇ6g¯³Ñ×þÏæý³þßYOë«é“çëÿÞ WõEÇÌúÿÏ›W:f¢c¦Ÿ:¦z]:×ú²vÜo£ÿÿôã¿þó·m˜†´±ŒRר´*™ š)Ô|ïb¼d7Ó€EM·œ+›òs¡ãz¨³»³¶ ]¦¬É:_T­X¾Ø3ÁEæ;¥È’VPp%=Ü´ÃŽ°‚W@¨Ïß|€®òþš_Ló­á)¤Î)š‰ñWóô´n{÷þÝé‡û ^­C¿\…¸á?•¤ž¾Øý^'Zü¥¹yŒqúD›º­ïðÚœOŒ>¼¯ó‰îiÎË»ùä+ÍÞÿ½ÿyê64 Wä¼7 ­àQ¿—/^f“Á†@1ÁõüI^ò¯´¤[§Œ|Aýå­]•¬~õpT2+ë]U‘]Û&­†Xù TIwÞ¯,*ïˆsÊ›,}¬B™Ã_Œþ”Pë’»m±{ Í#Ì©zÕOÑyÁ½kajÛà°’ÖºÂÍ­ßš'Ö62ìýßû¿óç?@¯Ð t½áXýtêêÿ]ÿwý_ûž\ûïØ•kÿ¯ýÏÿ©jý¿‡ÿ¶þßúÿùßëÿ?ðˆb+ÿüçûÀ áµ—”"RY ½ä\ÇKë h…®…\Ïi•W· ^^¿y>åOþ‚XY4@ŽSÓ_Η?ÿüóìÒ‚ù€¦Ê`R É³cK~)Ûúbw²†”WNÝÚîír.M^ëk›•»§qüu—¾íÀ£ýˆ'e–g´¯¾h¿µNù³û,†2™§}ߟöéu뀅É0®A¾ãÓÐtü+×:÷þïý7^vþ?Â;ÿWÿ¯þßõ¿ë9ýh½¬ŸÒi»þ¯ýg,¬ý7öùõ ’µÿ³öÿñ5Ì GC}ñúÇ¿~ÖëÿëÿŸW:±1Öÿÿ¯ã?O?ù÷ÿòíXeyÇ… |1™ì|ª—øz/U ¹æ)+Í Sîtøó¯÷”–4柅-ts-àAyÑzœüÔ1$dA#Í!H+@¤ìÃÙ´³ ¯É¿Ë£üûó•ÂÉ}½˜4ʘÐôÚn¦8/“§N€‘Ø{²€r}„ Oññ¯*$òõW*Ú¦ÚåZÛêKÎÕ`J]S”¼y4Ò;¾æŸ6)_9œß²# OåÒµ'ùÓLÞñ¢ríýŸþßûŸ1hæØù¿óÿÒ“ôMÇÝAÐ;«ÿÏÚ³ú×ÿ]ÿ}AWÐ,¾µÿÖþË:1ãA°†¬ý¿öÿúg½4ÌõÿF?̾hûD¿õ›¯ÿ¿þÿÓÿò¿ýà­¯zw”Áq‹#ïXÊŽ¡™TŒ10G0ˆ„,C7çÅ ³ mŸ2Ì—î~Ê@œ2Ý…VT1L[¶y€²9¤EÎË™R½Ø`—Ÿó¡­ÙÔGRŸNˆSùyD/†ÖÕžÊ'_ºk—Ó§Ž©KÈã|Oçñ>×£UsŽ.²]»¿RÿÈy–ÓW½ sÂÕ´BÛÕëIˆæ‘Kü“®ÌUýƒ6FŽë½]赟L‚]lÚE%¶œ@IDAT³÷ïÿÎÿó²rsÇÚù?_’µcôÒ©tÇêÿÕÿÖ®»þïúÏV¤/éñÚkÿ t„µcíÿñMÖþ_ÿïz½LžÀ±ˆNXÿïyg^ÖkÉôKu="¬ÿÎt†µvüùõÿ¯MG:/q7`b€Ì‚ãýOSFªü‚"¸&-Û…gÀ¡›9”»×˜Oçq‚&hríø)0Õǘ²kiʨŸ.Ÿ7óX!yð‘Gn¿x7(Kíp“?z)ûásLôhŸü~渠 ÐÄ¡ ÿa%ñ62äübZ¸ý•ú¦¬mÞ_•~Z²‡öÚv]™R?æ@ÓCÝ-K.ùÊ“MËÝïUyàFye¾›XH™Ißûÿ úµO|Érï¿~;ÿwþ¯þ_ýVÊ]ÿϣƻþµö_lŵÿÖþA=bÓ_¶¹4ö¤µcíÿãÓ¬ÿ7þõŒ þØú牟õÿiŠâŽÎ×÷¯ÿ~$ûÿÉKÜŽú€2:* Ç€DÎį́RÖÅ:6×3 ÅŽù“Þ×ѽydm€è©ÇàZ.u]“W! ÊdfQš9oŒ«Éî°; Ý»yä/ïmšó*‚Ðd§•sïÃÊù””õk‡Ãæ28ø’ÿõW_=·e(ð 'š´oÒÄÒ€[s‘ký# T` ݽœv À+ém«ø6¡iߥ¯$ ¯¦áß~Qgåi]­÷ÃÈ" Zþާv^]™©¿´cïºeïÿù€ÂÎÿÿ«ÿÏÚV}»ú×ÿ]ÿýR¾ößÚkÿ¯ý?ëãø)_¤þÆú§Oô‡°þßY/âkÎ8aO ñS§øèõo£Ð{Žõÿ×ÿåò·ðŸ§ýÕŸ½…Š ª8 ´‚"~uuÝPe%ÝÀ“W Å„ÍàœÑ‡Þ#jòÊ×¹ªNø¥ì”Ð(/.?FBä¹Ê¯úÞ*hå™?ù)kgÔuÛ}¹/þIs•ùÕlëôék<½0þ—_ýò³Ïß|~Ê^ò˜D”`çRy’¯¡îÑöf\1¼Ë/1ê¢Üµ)»Ãn´x†ïÈ{zÄÄ=Û,ñZ¯Ø=ûæÛo²¥?×ÚØ6‹ˆŽåáZß«Ÿ½ÿ{ÿwþïü§Çè‘èÛÑ«ÿÏÄÕÿ»þ[3wý¿Ôé vÃÚFÅqÂØVkÿ\×þ?ã¢×þ_ÿoý¿cWZ7Öÿ_ÿÿ ÿyúÙøWo½DÏÀŠÃ2ŽKÞ÷Ä è(Hð(è‚Ö?å œìIÞäã€rmqoÎ ²Ìuž?€—) çªGú/ùËùBÁ«ÈñÍ×_\ÿЫo*ËûðS¾u‹mÞHø¢u}ð‚üéî¡m¤¡Õ¾Ô3»ÀÔQ@KmvmwßÉEÎ{†èúsú]ן¾ÃSÀ+}ördÍ­™?çmDSÐ)/äýbW;"äi֫ׯæȽÿ{ÿwþïü]GÎA'R«ÿWÿÏ"’5g×+éy•€uu×ÿµÿÖþ[ûíÿëý¡£ýØ£?ëÿ­ÿW_¹þ©qQ?¸~*»;>í¯ÿ_»{ýÿ¿ ÿyú“û“·R<â¸Ì sM/× GÑ ¸œYžÔ”L¹‚5âž|I™ liš]•QZ¯Õç3’œ)³üÑýQâwsþúõ뤗oë›ÂØØ5½|GøÈ˜ÒmL¶¿ù›¿Il§”°¼ÔQåì¼QÜþP^]ø‰SfAA¿J#Ãé×ð£ÔN^¿ü(ßö þq&¯¾*_ò‘³åÕ#«ÐèÔ«½ÎÃcò*›x¥üÞÿ½ÿÆÛÎÿÿtÏêÿÕÿ»þïú¿öß±%cs½t·û¤­ý·öÿÚÿëÿÑëÿ­ÿŸzýÿ` ú"xÄø•‚9Òƒ¯)ã°Ž:šÖë¿ ÿyúñ¼Ä1ÆÀü¢4P‡ÉØ ¯4¾°çñiuÄÅè¤ã›Ž›ÂÊ'LpÇ£Ž/_½üìõ«×9G«\Žá+¨Kù¶±à‘n·ˆhš¶ûg—•²‚þª‘uòÒ?h¯>Tö8 ÏÀŸrápÉqo'¾Þw%³™6^Gž¶´Žö€cŒÒ¡IÛ& ç{ÿ÷þw^îüßùOtCuÄêÿÕÿ»þg×ÿµÿ¢GG®ý·öÿÚÿëÿ±“Öÿ[ÿýÿÿ1øÏÓŸÎ;°€+¶Ã[Œb `€B1KwÄÁ5IYC7ò¾–U]•9Þw@ èòb(ùvÿ˜ðœåüâ?iêTHTY&)ÛQÅÙ¦\éZ•mvh wN(é€avtMÅøÑÞK^ò0JÿËù/Ÿ½~óæÑf[aZ O2‘Y?ŹËkƒ¼÷ÒÕ6y•µò¡õéTtéß¹¿áëKg>©AY€–k;Ïœ ÚÜòÔðU™Ú'ýœµÝXÊâ—º®ûöQ=Ãsïÿ{ÿwþïü_ý¿ú×ë¥c×ÿµÿÖþ[ûŸozlêµÿ×ÿ[ÿoýÿõÿÿçâ?óáßZœ€œ{ps(ì‚ò IÒôNhÊsÀQwXÙDʤ¿h³ëé~¤u, êÈ$(G–œ_@Lé» È‹L£­rÔ©|ò˜ióäÛ *¯/¾ü"F+9¸{»µ…Q+à(#÷ûç‹§¾çÇ÷F ÔùN3RWe”¯•€&²e—Ôðwþf€´¼¿j(ÂwÒ|9P†Ÿ4ò¡¾ ˆ¦ÌÅS_£жnôí—½ÿ§ÿ÷þg˜dœcÆGÃ}Ì Úù¿ó?Cé‘à|õÿèÛ™#3‘VÿÏxØõl¦]ÿ³fÐkÿ@釵ÿÖþ¯­¾öÿú|µõÿÖÿ_ÿÿÿÿ €Åá0a#Ö€—b%0Ä'¸îñ0ί——{^Ñ¿GþÐãkwOŸ'_1¶\¾wÞi…Þn$¹¡u0vð,ÀBÁ ^8\\´çô”SVPžçäJO»çEæ5,Ñõ½Pß¾ûöQ¶rWPh¥@ á<Úè1=;ÔÆ`Ÿú=²>úT’vúй÷^ }G•4í´˜ Ù½†nê<ê4ýªnéís}ƒ‡tqÚ=qø^qx|÷±ìÒöþÇ{ïÿŒ[còšwˆ3v„Ž3ñ * 3^¯ñµó?úoçÿÑoÆ ½²úÿZSWÿg¢;vý?¶À®ÿkÿÑ“kÿ­ý“¾öÿúëÿ=|Öú!ëÿ¯ÿŸµò†ÿ<ýùÿñ¿¾n¼˜¯ÚõÝHˆ¤5˜£Z“'vÒÐZ”«A*N˜¼žûÒ2 pÅ®¥|Qp@3Þ2^ªãÅÓy”PÚ‡ZâMSµ“Å£v‚ëÈ9t ®Õ+ŽÌãTã)„vbùùdùðþìú²³JšLBmTp%]~åìŽ'´åIÞœO™€H#¥6+Wº–÷˜_w¨É· ískÎcêR}óÍ7©»¼ÚõôFüä£O_NL´‘gb×@eºá¿÷?ïIÓw{ÿŸçŠ1»óç¿y±úõôÁŒÿ¬)»þŸ¯vý?»ÁõCÂeg8_ûoí?ëÇÚÿÇOXûý?c`ý¿_ÆÿS"¶DçÅúÿg õN²þÿéß„ÿ<ýì?üë·—‚Qœ•1@„îî‘ÞÀxõ¼_™UÄ=G@eè¼Pt)P ¾Ô3„¹Y`}7@ÝD Ž2àwÞ©ã’•ÄèxFf¢’sBËÉoPox“ášìzÒ®Êeá5H~1%zÄW[+_ÛØzÕÞsåœ;”÷þ]bé øµ ®Š¥÷ž(ŸöOA}õîÛyý€RÀ6éÎÊMþ½NåVEÚpÉ¢ŒºÑ–oëJ_^îýßû¿óçÿ(ŠÕÿ£WÿŸõÕòÐuCÜó]ÿwýgGô}œl?¦­ý·öÁÞŒ¹ö¿îˆ Nw®ý¿þÿwý¿õÿéÈõÿϧ»mùôßÿô-cBðH^À‰\……±!< bå¸<?jô0Z/¥³@y' ›`zs^¾˜Gç }˜Ðû’ßÔï\™ZS7™ÈðeÊG¶Æä› ÞËÔó27Z[¸‡Qd!OA¨>å1ÀÕwf‘ Ÿõù¦Go Þ :}‰Î¹2ŽÔ?|µ[?á©~_h/ÞÊDž‘…<òS‚{zÚ8ªœ|òh#çРÛû?ý¾÷çÿÌ soç? rô2}!Ðz„ΪžrÙóÒ¥Àõ§y«ÿÏ«ÿwýïüØõí?ºtí¿ãœ­ý¿öÿúëÿ­ÿ6í¬ÿÿwã?O?øÅÏÞ2¨â Ô²šønh[`뀌s¨ø2y÷Íón¦87/DœeÇR_ýu€+ 0 è‚/L‘/\µårÙÈWYÐHä_NhøÞÒÃÇ5!ÆãÄ®QÚWÐǹ²‚:ÈòÕW_%ºù*`¥Ô14êÖ~qã“wÞqÁH9ïô Ï¡K;´û:6Â(ßC®É&V/¾¹¹^Ž¬Ò¥‘û«_~•ÝbÒÈ#¿!u¿¼}? š‡L%œxïÿÞÿciçÿÎÿó5×£/(ÎÕÿçë´Öˆê[ñêÿ3F¬Iúãqìú•Ú5¿ïÉt½ëÿÚtêc®Ð#kÿé’GÐ7±a×þ_ûæÆúëÿQt½ðЗÞdÜÓC{ù»ëÿÿnøÿO?ý÷ÿòmÁ"7¼¡†ÝѼÇ";鬲Yh `ˆ—–wá²xôÎî!A=áDƒÏy™„ìf!¿t‡ÇLl„êã&Êâ(áÊ×w‰µ-F<ÚÎÔ9@_^^?m´KÌ.3±<‡  @¶©rxŸÝXi¯‹ êÕ.ive‘Ohyç•iïÿÞÿŽGãBØùv7š?ÂÎÿ³»ˆÂYý¿úßÚáØõ×ÿµÿÖþ[ûív?cý¿ã{êõÿf3Èø·l…õÿg~\ﯿµþÿßÿ<ýhv`Q,Cç E(ûøcÔ©8kóòq1°¦Îl@ec¿0k˜f€~ñÅó2öóU<ôv^ÄRWÁÖmPçýSGù“¯`ŽºÊ¥ì·xÆ€Kù°tÚ„ï ¨T¹[F?0Oþ÷2ч(õJ^õñB÷L¹w*“{vɃÞòy•¥uµoäïý?ÎGlj>Ùû¿óß\ßù¿úõÿ®ÿ»þ¯ý·ößÙaɆŒý½öÿÚÿãk3ÑZÿoü¯‡uó¹Öÿ»=åd¬Lˆþ˜xýÿ³!†¿¾þÿY_ôÅožþô¯þì-pÁcÍDŒ ç„€Ϫ›€Ê´¬X:±’®¹é¾ó(àæ”s´îìøÁkv3XRO¶Ø=þ½~e+‹sõ»"ÿµ¸~Tù'ßÔÁS½Ê¤®Ké(ß2xVV†kÏÑ÷]^h ‡´ßµüòícúÔ—ñÑ?úMëÔoÚﱇm›4Â+‡·t±Ç=Ö#Oe7ØÕ†¶C•ýKÇG6îý?ã¬ý¶÷ÿ€°úaçÿÎÿ»þ­N16VÿŸVÿïú¿ëÿÚkÿ­ý¿öÿúl¤ØLãò)Öÿ‹«ùðEë{®ÿ0‡õÿÿÛðŸ§üåOÞšX&•àÜce@ƒ*àΤ ÎMÄNÆ—¯æ%œ–tð‰Ã r¥ŸGÙ¢ÀäzNmJ†§°ƒå…ÊÆ!PƵ€öõ›×¹v^ À'áRmÛIlÖs{§ðÈ{v'iúòtÎ1»·Qž>.`ôêå«Ç;½²Û ß é—«ß\ãé>½™8çC#](à§-ísõi¯ÅÊ™”ÐjxÈùùçŸÜê6n¼ñç÷ºõÊÛû¿÷çÿóÏÿÏ:·º‡žXý¿úßâg ÄÆEvöîúÿ¼–ë—]ÿݳöß釵ÿÖþ½°öÿúÖMÛª~Øú1)Ž=1ºrýÿƒ7°¯jƒ¯ÿÿú³§?¹¬‡z®ŒG{OÂsü?•ô•týözÀ!;Ÿ´ƒÌ/ Vy 9¦Ji—¶‘i*­|äšy©[Û'¼yùzNÿ©S ºs­íD«~;°ð°ËíÝûw¹do?¡Ûû?8÷à WïîýodžÌ5ÞcWHzÎN_uŠ›WÚÿÓ;ÿ£ÿèÁ8Yý?àøêÿ]ÿ͇Õ±£]ÿ×þ[ûï|ĈýͶ]ûÿ<‰ÒõsíÿõÿÖÿ{~jª~­ùÁ§ã‡ð­ë‹“&}4 ×ß9 Ïe¬ÉëÿÿÿÓÿË,7Ìu“€œ EÐU½ù®{þiü4/x¯ƒÒŽ,žÂïIŸÇuæŸú†œï¾}yШ§u¹B7éåë‘ hþC_ÇÀÀlùœ?hpñÕ¬:–hœ«·ü*³ôÊYZï²€H¥×G} «|í´BÓþ³ø¤­·¡G–Ô5×ú£rª«òtr*§_Ú‚ÖAži| Œìón±&9f’·÷ÿtÆÕ{ÿ¯y6cV0FŒ»Ž-çMk¼óÿèŸÿç%㦺mõÿêÿޱ9²ëÿùA¯s„µ^Ï]tl¹Þõí¿µÿŽý±öÿÚÿt£¯±WoæzÖ“ú_tèúçýÊúÂSQÖï–^ÿïÌŸõÿÍš26~ ýÿ±!ŸÕ£Îޢ׉ iâqeA•_ͧ±í D`K_\š„+­çxS0ÊxI™˜öí7ß4ó˜ÛçóU¿p›?_~ùe&\ø‡=¨ë¿&åÓ€bmHÊc…Ê£ÁÿUŽÄøä˜ö_tçú¹Mêí#‚ú¢íDõR”M‚~ðiYíÕ/ó.‡|»ÎÈ[…’44n]Þm5i§§O¦rmgdŸdqƒóÖK^ ¿_u¥Wæö2{ÿ;&Îýë=ïý?£ÊXÞù¿óß8ˆÎ¹tѱúõÿ®ÿ»þÇæ8ËÅà®óµÿÎ>ºcí¿µÿ×þ_eþ¯ÿwž$ZÿoýcàÙƒ? çúÿƒzÀ5®CÿÀ-‚ÿüh¾BÈàðë¸G÷6ÙÉ3Ä7tj–)”Çûôëp¦ÈkàÐôºÎÍÝÑ)]ß›wAE_;„"Üð"Ëù…å,öydnøO¨º€/pH#òU¾IÀxi|i*C×ñQ™ À Zk 9Jï:Ååb” ÒÑã ìpÍÑG#y~IuŽF_Û½%FÞ7>Ê>d½òÕÕ¾˜B‘¥e+‡2=*—:ÓWÃ_ž2dÏ}—·÷ÿÑ×úQé#‡sý¸÷çæèŒ açÿêÿÕÿ»þÓ]g­­»þ[ÍÚ¹ößÚµ£Ìaíÿµÿ×ÿ[ÿoýÿõÿa8pŒð‘ñµÿ>øOÞÅøÂÈn&áW³ÍPÚxô'¾Î»Å(»ž€R¦Ž>3¶`Hw«àá¼áã…lJÌÿìÄ‚¼àq„G_°åÄ1“oò QŸw;¹„<Â7×ÜË8éŒ)Gù‚kmp%J§Ž€dó‚y/`Ï¿¡O§]U1GFŒŸ¾rÞþÀ»×x´ß†8´oì:»ÉãreÊW†>tD#« ][{ݾŽ<¹Ÿs®:ÐÔ°Äß5™öþïý7–vþ??S¿óÿ€¸«ÿWÿ['¬'»þÑ5ÁšËFïú¿öŸq°öß±áõ}a~4Ô&=×cÏÿµÿ¿ûlíÿõÿÌÁq¾þßñk®ˆªˆÿZ²þÿÁ1èXÁ˜ù}ôÿŸ~øóŸ¾ÕYh.`Ä×ÅtO V“I9  9y+}ÄÎã{‚gl;È’pý)hƒg:{¾F˜¯ûŸTvÖ³ÊWRßÅ£7ëÎW~ä€)_¸˜L7’Ì)?éÚ†Æuy¦Œ¶LHÛ§Lâ¹®³Æ(MûæíÈN/rmË9W.cvþ¹&—¼´õŒÙÅ*8…¶õ‘éSÞý«¬å© ÷ =Ç$ö^¹VNð¼Ü¦Ž¹¶›¶+3ÇÞÿàîý?kÇ”q“ñ2qÇàÎÿÿÆ…ÂêÿÕÿY‹®u%ƒbþìúì©]ÿ×þ[ûo쇵ÿcC­ý¿þßúc ¬ÿ}ýÿƒe°‹Õ8Šgœ«ó÷é`é´Gæb´#›Çu°‹oœçCëßœø›ë€H€NÍÅ—’vn¢*ƒg¯ÃÿâE¤‚Oòª\|S?‚+ôºqß½Á" ¾v@uw~‚ôÖo÷–àÑ:ç:¬²¶~/Z—/|¸^Ö¾Ã=^d¨§ýÂãú›Ðà]z×1f'¤ßCÛÕ›Xùõµ`GVâë:ó£*–OÛŒŽ3‘çj‡N>úGýs Äj}M÷iþ¥m·nïÿÞcÒ¨4vþïünºôýQºúõ?ѵ¨†;å‘õetÈ®ÿVè[Œý oºÓµÉßõÿôÃÕkÿ¥;2NÖþ[ûíÿõÿê;Ò ]s¯ÿwð‡õÿûýÿ§þÕÏÞÔ1 —sÔ˜ÀMÜÔ9»P"Ï1—¾´²<Ê×kÏ» 1Àðžs«Æk 3N`È£zòŒ5ùdÀϹù£|{îºçbåPM—æ(²ÛA¢®Ô? ÖÉ"‹sáÞå…‡ÐG”á=¼´!;¶¦~eñ¾‡¶GoÈ«¬•MÜ®¾®C7çb},TiÓge2ñ=åšÌd\ÏŸÇýlÚ½íäMØûÿè÷½ÿÏãÎXÙù¿óõÿêÿ¬/Ö¾]ÿwý£!v eÎ×þ;ö¬ÞXûïØÑ±¿×þÏ<‰-~,íãj±Í'›ýØ[kÿŸ>¡WîýÕóôÕ¬?ëÿ¤?z¬ÿwp„õÿûýÿ§ýâgoqa SƒRw…p(Í¢3úC^€¦$…¯8²Àƒ&ü‡¦¼ Y´îyÊåq·‰ýûxa¼Š¯PâûÑ|ñ‘d€'ò]r ñ£~4ʪ¿€9 :9—ž‰N¦9=ÝÍE)¨ºÉðÒ/Êâ— å…¤L^CåOÞUV¦í“¡Î`ù¶Lê¸áxOw®íê¾ó.MÁ6×Í?ØÔÞÿŽÝ½ÿÏóËyŒ•3`&á¤íü?ý´óõÿêKà®ÿtå®ÿG¤/fLÜ×k«°öß³MjÞ8Öþ;ööÚÿkÿ¯ÿ·þ_ŠÛŸú!âûq#Yÿúæ÷ÅÿòB §»^£«ƒä>(z^°$×eE›Û *=ÞågQR¾ Ž÷¥´XnæèµòÊPî9//±¼¼x|˜*Ð<šïñ¿·ÝTÊ•OË(_Y›§tx¯¦œÇ£"£vO@ÿ ¹êѦƒÿÈ9ùJ©×‘¾˜X>å'÷É+HvÏCú+_}w¾òÊO¹òoZóm1È’¼a¼÷ÿŒÕ½ÿg|g€|ò§c-É3vfðdÀîü~·ÜÎÿçñC·T×®þ_ýodìú¿ë¿5ví¿µÿŒ»:¶õu;°vÈ‹Í:×λ–ˆ]¯ý¿ö?ÈØ©/gìt|¬ÿwÍvú„Ì¥9_ÿïØ¨3ÆOmÕꙇo?»È'¯G‰Žâ÷\}ù YÿߤK?UG·zýOaÿ¿p³2˜× oÅb•7½‚˜ çΉEe¢ï柣†ÿµ8Iwí0pBº:zÎÀ-´ŸÖ/¯ÁÓZÆuù½˜Çñh~ççÂwïÞ…FºG¼`Ý!t`wðÞëpþÞû¤ j»*›=c‹§[òåµ¾²³kþÝe*ï´sÊOÁç'ÿüûžô @.ùÊ+çø”×½ ¨Yöô³°÷ïìkL÷1t?OÞüyÌ@ãz®wþ½Ö¹»óôÑŒ º‡Î«Þ«ž\ýOm^ýÿX³:Fvý?Úu×ÿžêÖÆÖ¢µÿÖþ3„èÓÑ©›…>Yûÿã9´öÿúñE×ÿ‹¾Xÿÿ·ÛÿŸçÞ8££ôçö´Ho¨+î!Ï‚eÊ€ïýú, ‹¼cih€Yà–>Wçåå‹—½Oþ0MüÈs+GäT÷üûn^¬^:òœ6ÌΧIo=ÒÅåM»£¤[äú%5@–4/¹sôó¶msë©hµÖc— ÒÔ>†Ù½•­°žïŸr-¬ýÿÜí»O³þßñ ×ÿ;8ÃCÇ\skýÿßnÿ?æÅÍ3û-&ã¼J@\%e9@G^Ê~L9“£ Lèñ¹Œ™–W6ŸM¾€‹yþò['d„wþ­§´E½ñ‘†º‡!5i÷¼ž£E€ûR‰ “AL~ï¾ò¬Ê÷ièWÛúˆŸüw³ /A|?Nbþ&ýÞ÷wþ#Täj}ŸtÿãÐúÛ×@­ÊÙúÓ¶‘‰4Ê»Þû¿÷߸2FÄ÷1(mçÿÑ1;ÿWÿ¯þßõßZÛuµë±~ºþÒ™»þ¯ýgœkÿýú¼ŸÅÀ* ÙÔS´í’_Y•­¬.4øªCy²@vñGÇÉÉ×=š8d–·2•§²šÖkqël™ˆäÑæ¾‡lº+¡<Ó?“"n?"ï¿)?)·÷ïÇš1sGÆJ¾ªi<ÍØî»ì:Oä‡~çúaçÿêÿÕÿ»þïú¿öŸÝÛkÿ­ý¿öÿúõ‰ëËÕÆv}O뵸6yó×ÿ;xDüÛõÿ/ýÿ§üü§o¡=ïÄq-4?m&°Ã¹IÔ‰u(9¶ãôÎ?“4èÖ8³á—‹‹ Ê ò{Ì-ï¼Âw|ïf²èºèî`TÊDž° HÃa±¡íi;¤+ ôцロwW ½Ç#•ó®*¿f„f®ý»´|é©Kfä8tê©óß¶¡MßLÙC~ú¯ô¥ò>•1‰·?òKNS^ÉöRr /þí—Ö'¿|7í^GÓÄʶ‘Ù}ºùÂÞÿÓ¯{ÿwþw^Gìü? ÂßK×UOÑ7ÎWÿ?ëdÝÔþqÞp×Í«ÿÙÖúÓ;tn×9ëxCû,´Wbæä®ÿé{¿ü¦¾jþ®ÿgð臵ÿÖþ_ûíÿõÿÎèZ»þßúôâÿüçéGó,ï€ãD `ÐI˜E(ÂÐ Ê9‰S51] -®¥†Ð>®¯¼GšòW=5˜°©¡äò‘!õOCÓK™¦ ‚sÏ@§msMA¡õ~7@8ôW{?¡@Í¿ï{‘üðkyøÚiõá¿ä+—>™<†4ðMîWXýÈðÁGÀã¤Kû(ý²ÉÏ6a4Ú1וI™žë[Å*KÒÓŽó ˜—°N%>IÙiëÞÿ3Þ÷þÏà™ñ±óç?²úõ¿(ëímýÌú"Ãzt­'YÃvýßõƉñ‘ñp ã'i3dÖþ[ûê¨ÍÚs±°öÿé‡ò×étÖÚÿ틉×ÿ[ÿݱþÿÁ ªK_üÿ§?ý«?{kÀ€žÆà $&#OIÔðpÍ™A/­Æ‰4†‰`0É·›É¹àMø\å,'´ËªeËðô(‹n®å©¯uµî{ÙÖ%~¤_ò+ŸcòÔ­|l›”” ˆ šëÖU9ä ÂÓµA,OP' HèK¢ÏÕù‹'â[ßé-wYÂç®úÕÄ)œöÉ«“ÑA ÆÛD!êÜ;´NL¡«îôÑU_ÛEf2x9ô©ÝVúµõ¯òØâUWËwr’¡üÅdV¾¹žÌÑ4t•_Ø™| í¼«më@“ .'{ÿý·÷çÿÎÿÑÁ—Žï| ßœ¯þ?à ]JV¯þßõ×ÿµÿ˜Skÿ=ÿk-uTO²¡×þ??Ä[OÛ/µÍ×þ_ÿÏXèaŒ¬ÿÇõ^ÿߺ’ñ0vçúÿÿyúñ_ÿù[‹nA Å. óûB“¼¡—g’ÉwØé¬q¸V^'£“&_šÀ9R¶u—ùŠ!ˆv%ZO®/á3ñ¥pÐâd‡.Ê™²¾”ëaŸÊ ¨ =Ûå®2•EšúÔ!ä5_¹Ô?é½¹Çõ:<+“Ç=&ØwEqL€56”Á³Õëׯ?±DiÇ%:ÙàVˆ,MœŸÉGÇЭ‘‹v*|´å) ß§àÕQâäÂ}Ú£®z\kCû&ù“ö~Úç¥õŸæµ~qh'Ö{ÿ÷þwNÂÎÿg{çõ~ãÕÿ«ÿÏŠ›õ·k“õhΣKæÅ®ÿ»þ¯ýw~äÌÂ:Ø^l8óıößÚÿ†ÄÇ?^¯ý¿þ5±þßúÿg½ˆÏþ{èÿ¿È"9`‹è¢i1||o&Èã+~ŒNštÂÀ5€Ìc€c†¦\ReÌpB7§‡ò§§†]ÉÜôðG>‡61”…´ï¤¤®Z§â×Sà{ú´¼2¾>8œü±ëË/¿ ˆ€r]À ÏŒ ëÈŒ•µÿÖþ[ûŸEõ̵ÿŸ×”»O2Šã±®D‡L·­ÿ·þŸÙcœw?… "}ýÿÓ7¿‹þÿÓæ%î]Üüï³³k„A  wš\£J?κÓ,¡˜kÐ=õpViZn*˜ÿÏ;ˆÔ¸¹—¿ËÐ{ñе9?©©Ó5G9;“M€¥òy5 • Ý·ß~ûÙç_|¾-«Õú(|œê#&øãé뎭¦ŽW³3Ë ïãüÈðO6Òá“7u6a*H?ÈOOOì\ù|¹ëÒôrŸ§ÐNÛöþïý7Fvþïü7èŒê”êýÆò…;M®i£¨šg}SšêöÕÿó£ÅêÿÇÚdnˆ„2ñtÈË'ñq]àJ?ëßãÅ¢ÚáQ@üÑ›<ò(½õpJ»:íEh¿ýæÛÏ^½z5»ª^älÉ—vd~=ðS‡ôÔ3/8­‘VÇW^Lý¡k»5¿DêãGß]ím™ðÞÚ–‰:ùê §a¦œÃ½µ{¬¡ü*ÓÞÿ½ÿ;ÿwþÓÕ w]A7I§7Vÿ¯þïú¶ëÿ®ÿôDl—›Ž 'Fa|¤KjsdìÜÊ(l–µÿÖþ{¶u áèšµÿ³.Oˆ×þ_ÿÏÜȘXÿ/ý` Yÿ¿ké¬$¿ãþv`Y0¿º@©vòŒ’,èÂa î4¶[‡"UÆ® Á®«‚P³òäK4ò•{ŒB™‚D)s9Fè;#×\+“:.c¨uÙò‰g&ðEwv&M…wå«ÑÔúÔƒN¾#õÞúË_ xBK6Ó‹¿¤Ùõfvdyq»GõAeS®Ù?|7<LRÎ5 NüÓ–2£½Ë0Vô¤¡S¶ùè7ÍyÛ).=á]§Ü$ªqïÿ(¿½ÿgììüÏ\Ùù=^»ú?ºrõÿùq§ëë®ÿ»þ×¾Zûoí?‹æÚÿkÿ¯ÿ·þ_|ÚñG}‰Ö9›A¼þÿúÿl¾U1‰b_üçéÇÿî_¼zx߀;ß}8ïoò«ªI‚|;ŠºS Hcz™yÓcpŒRjÜØùÃøÇ§<ÑÈ/PÕFˆ?\/:· éÃûù‚Gjò幟/œÏã~W¹ÈrÑé¨ÒOÒ³¬sÞNìsÝ´îò Ð3ò¢Éã‚@#“qÀ*ýA¾o®ÝWú…|ʦNN°K ßö‰4ü>•«u5=׈§~mËsîEô í±C91:uª;ý§À°ñ‚úôøíýßû¿óß|Ùù?<Ï¿ÕÿG‡Ûå[¼úÿ×Yïvýßõí¿µÿÖþ_ûŸ/²þßúlçøÜ—Êfª¯»þÿúÿÿøÏÓÿ›?}Kyôìå‹—@ƒBê¯ÍŒvƒpSçÂ^ÅUZyq(xËK=êÉy– @,Az×êõ—^yv^µ®!ˆ‡žÌh„Sß3ÀsO—×£õi‡´¶/m‘/n®” ­ z/§Þ¯¾úê³/æ%ïÚ-¿—s|ýÕyoÖ7ß|~- èòmmT¿PYÛ—I»Ò+oehߢù4¨[H;®]5®SÏÔUÙ÷þ?ï’ÛûÆÅÎÿÿÕ_tÎêÿ³¾­þ÷NÉ]ÿ­¡]Ãk7X[wýÿø´µÿÖþ«ÊÖ]ûíkèÝ·Yÿoý?kg}[±À[ÿÿ`$zäÞ?ëÿnòþ?ÿר^ã°þjÀ›O^T^Íâc—ÃŒÁV0§i åѽáÓ­£òJðd®ñqp„î;±”oPgC±Gò„‚1kt® 2µ.»¢&3ÀÌ“Á? Tø¸ûXO|öoáxGðk>x·=}LQ>ä'»2í3å¤+ œB‡þþàë³È9‹7cN¹wß¾ åÚN2¸V7q+ ^G¦ypÚ€^;;€ïåÑ ÊÅäyOyK—ò“> mË£ìäáEv2íýßû¿óçÿêÿÕÿÖ–®[]Sº^îú¿ël±:NzÛfl‰µÿÖþ[ûí¾FýçÂýºkËúëÿëÿ¯ÿoÜñŸ§þ?zËÀ088'ÂL—¤Œ±!OxÿaÞñôúMÎ)JåûC_…áj—ú „g–*# @,è Ýóœ÷íÔ…4‚߆Pe‡ÒB}Èã\zó´ hYæq„¡ `'ž:JûeÒ‰çPo'tÀZ—ê^z*?ù€[¶O*C†w“6U~öòÕË\ãÙv‘!<§ßyê.¿9Iº?I›¸ùÒœ òí%ÙåµO’éϤX›zÕµ÷ÿŒ³ôÏôÍÞÿÿ戹³óõÿêÿ]ÿ³lΟ]ÿ×þ‹­¶öß±-Çæ\ûí>ÆúLJ]ÿoýÿõÿϦ¥bµŸè >•pÏsÞ#´ã{±»¥')½ùõôã¿þó·´ìú)ð1‹²4„*òkI_<.xåÆ8åüŸH‰ë‚%Ò+Äuéï ‹4ïµw!Ú‚-¦È|ñ÷²óî^Ê®(åç…é‰Pòt–r걋©&¦CÕ5Gók¤*§N27FO®ÆúÄcƒy×Å¿7H\p¯´k£T¦/¸Ã'ÛÔá¼|Ñö>Hëyû®i®•=}vã¥^ù­ÝG´W=èòeÇ[½{ÿ÷þïüßùO¿Ò+«ÿŽÖÕÓ«ÿ­'ìúì‹]ÿ×þ3#Öþ[ûíÿõÿ®åqý¿éˆõÿ×ÿ/†a^°¥ö´Cöwá?O?™—¸[`óºAz¾7¸ý;á‘?Ûçó…=}^ UA²‰U&TYCâ+ a T¡Å÷¼üäúûKÊÕ=Å2øÃk®N«&½` o;Æ^ê/W耥§¿ÜÖ‚rŸtÏC Tþ¶ 2)MÀ“<òk›€FߥüœÛs´÷ÿŒ½ÿ"ùc íüßù¿úõÿ®ÿ»þ¯ýwìÁµÿÎkÿ¯ýÏg\ÿoý?Ãúÿëÿÿ#ðŸïýÇÿû?ýzL²€v# ÒÌÁ‰n× WóøÛ·ó§IxÐÉ+ÐCø&óÎ'694wþ@誣Œ¦­ú#Ë$ÙÐÜÃï€4ò+Cw{¹Î–ÖK>`U‹o|å°ÀŽ4uá©@Pƒkéír¦O† ü:q#ïU¥å®׋Úß|þ&ï¥RoCåv­Ž{_•Géò®íëí#õkw²á tpÎé £rþºú–¶÷ÿ|ú~ïÿ™ûÃï;ÿwþÓI«ÿÏz¸ú×ÿ]ÿ×þ£×þ;ObÜmXöƒ¶¯ý¿öÿúǧ[ÿoýËúÿÇÇüÇÀ²+ÆøõxˆE(à‰ø‹\sdíÖ±# pR $NÿÐ6ˆ?Þûäk#èÊ ^ŽQ:ÇýëBb|eñ’•'ŸOòñK™á‘ú.^̱°>e×Së,O×ä%Ú—ZNx åïO_‘LúÈyÚˆàªßu€¥+Ïu¼¿!ùÕ bý˜´\_rNY ZÛMžÒ4ÆS:ЉLdš/Oyò;¢C3â+ÓþQFyå¤õñ ^½öþ륽ÿÆÇÎÿÿ«ÿWÿïú¿ëÿÚkÿÅ>¾lO¶bÃÚÿÇÿ`G¯ý¿þŸ¹a,8Öÿ;¾"¾é( >¨ã~M—Ôu_þÒ5ʦ/¯tþ­òæÚúÿÏýöûâÿçX‰AÐ`D2Ò4±#M¹>æ‡nÐ]œ­Î/zü2xg×kô€Qœ£—Ï`ÞïÞÏî¡K®Þ±²xã'ßÑ-mª¹&ËÄÎ %gòýjyåßxÃ5þv>yÌïÇa—š2“/6iJ¯ŒÃ59È©\CëQÎBïËÙS'Y”Íî)õPT’ŽÃýëNåƒ÷ýüÞÇê•q±þßúëÿ¯ÿßµ£kEñŸ§ÿ»ñö#cü26@ž÷ïÞÏ. Ÿ}>z$€3Û÷>aêü²È7àsŒ·ò›@¥·rI®ñ{$ñ€Fg·”­Pžø›Ðuðo@sç-ýÅ®9 yihPR¾Ï!k[ä½ä(¯vœ]c÷ºð“çœ]mÑÎ!~зBxý!ÛN|Z§mroÞ x6l¤+ߺÎã‰çñH¬Z.²é‹‹>¼§½M÷+iÏÑ8*Tk£@IDATÜßO§›×_ öþ?mÌ8Üû¿ó?sä6‰;'%íü?útõÿÑ­£l¾56nç>«ÿÏÖ5P¼ëÿYsvý_ûoí¿ù‘yíÿØ÷ÖÚkÿ¯ÿçÇ‘†õÿÖÿ‡Ôç×;ÿ}ñÿŸ~ðóŸ¾5 4Xèä(° úvåî|è Ne7Ð¥`ñ@ Ÿü]á=4B‡›NwX¤$]7Aþ!¼ä·nçx¶îoß};²Çüðõ ˆ© 0ôt4‰æî¼‘ÐrÃs³'ÎB!m‚ó Š9's<8ªY¤ sázþ<’>åP9?ÇÇüñ-¯¶M=€Ãö¾ߦN;«z¯¤ë‹î¼ÏKœOE§î\’äô{Ú3ù½•‘\å¹÷ÿãû£KõÏÞÿÿ;ÿWÿ¯þßõßšÐ5»ëƒ¸a×ÿµÿj[±ÇÖþ›™]:¡¶çÚÿ3BØâsT—¬ý^QÀÞ^ÿoý¿õÿÏâèÍõÿ_DOVGÒ›ðŸg+»€Î#x~ b:_S•ìaÎ{›0ð^);¢îééðáÑ/ð è,fÒÊj:€ %¦nA9´³‚hÒ8•d³ úåRÞ˹¤cÔŠoAÍEøáåýR퓯œƒ,Òu~m›Bx5P+Ó»:OËÒÆ_Oÿåü*™F.ô-Ós±vh·¸íRŸó{ÿµ=y'_PNP¯@v?TÒçìjëÅËáQÌÈ«þ½ÿ{ÿÇÿ;ÿGoÐ3tKu…˜NZýÖ¯êòÕÿg\X{¬ÇõÏ}ýšÅï±Z£vý?ý±ëÿ³]´öß±kÍ¡µÿ˜­kÿ ]ƒéÔµÿ×ÿ‹¿ºþßúÿ£~/ýÿŸÌ#„áhÆ9Î/$Ýã×f/c×1h(Ï£Èâ\c•!ZûtÑÈ·;„¶-›üá:÷y¼+jhKSyZ?^•§ï²Bëz™Ô/ÿêë¯>ûðþC@ð“¶”®/iÆ?mœÇ ñ–øÑ¦ò£Aë|þäÅ¥5¾•“ïëŠÊ‘õÙh¿¾~8íô‚v¡¼ 0‘­¡}¬&©Sڽ£õâç~E6ˆÕäáIǯ~5;ÛF¶Êù.¾{ÿ÷þïü·óÿèŒÑ ÂêÿÕÿ»þ»b×ÿµÿj³­ýwì%ýÀŽ\ûÿÙ_ûvO­ÿ·þߨñ‡×ÿŸ±°þ1;†aípxE\‚óñ÷Åžþù_üèm¼ Ðã:¤õÜn$4ºÒ+ÐI;‚ 'H€—T„Ò)o@ vûXºL¬ìò“>/Tõò<.$—êP§Ø©¼}ø–·tA§¼z_'Œ\ê™ôœ¯Ö‰6m¸:“œ¡›tu¢S(•ú. ÉÎ3r¸Ãƒ Ú,Š—,ÃäÚá4œµuêÀÛ!‰sšºÚ)ú¯2¨£ý)-_($ì„{üÊS ¹æþiCƒüÒz¾÷ïÿÎÿÿÑ“—^¨:i«ÿWÿß~ܲÆíúŸ56këôÇÙá¼ë¿þXûoí¿ØŸ£#ؘµÅÅÂÚÿµÞ×þ矬ÿwÖÖõÿÖÿ¯Ý½þÿ…ÿüè?{[ % Í.Ÿyv5À íe ÞßRW~Õ/àÃ.(AÇÇpxH¾… moH¯» ‰MØ7óòx‡piê¦ÐÜ@4÷s `Éâèeä¥ÉÂ8i“¶¹v¨? “øBIÕƒGåÂß¹ºÅ½ )/Ý/á5ç/G†Ò¢Ç¿uI!;iÚv‘ñžðÉyä¹:V]5=îS®µï Ÿ^ç~N¾ûu^Ò~îÚ£u{ÿÀº÷ÿôƒ1alìüßù¿úõ¿p²V\ëè®ÿ»þÇn{†mæ1>j‰¬ý·ößÚÿkÿÓü—õÿÖÿó˜—õ¡þ~üÚÛõúÿfËßëÿÿfüçé‡ów€pÇöWÁ êó•>/tçÄö¥j:S~ŸÓØ9ƒ†Ó£Lu¨«¼ï±²E˜¥7/FóÓš,¶˜dä¶ðf(¥ìœ‹å¡qô]ùCô_›µý¤²¥;×fri‹k½ãˆåúqLºÇô T0š´”›z…TÀ‘öG¿€Ø = “[tg÷Ôˆ{ñ(oùG|”•p •­IºKnu¹èz¾÷__ìýïØ1þvþïü_ý¿ú×ÿ]ÿ×þ[ûýÉf#ˆñÚÿkÿw¬ÿw~^ÿoýÿþÈ·þÿ,ÿøÏÓþò'ouòÝi ¨‘ú ¥çQ3NLß 8N¹)&ô&« ã+ xäÚ¢w ±Éw®!hçø0 Ñ@g“vÊJ/ÀS^[†!íhÑí\«ßáš"u”æì:‚ÓÌ¢;/h—78Źžó(šÉK;>œGkÛ矞úIÊÚÓã{ó¨£:+kÛÝ6 w޾iêOéÝ#‡r=ðr޾eõ•÷ŠÉ»ï:ÿAÐëÖ[y7×Ѓ\{ÿƒª¿¾Ûûÿ7‡;ÿwþÏ«ÿWÿïúŸeõ±öŸµs×ÿ¬›kÿÅVÓìÞÚ\FLm¸¦­ýwìS×þ_ûý¿gßþXÿïyÓGtæ(Šú´ëÿ¯ÿo,Ûyúñ¼ÄÝ ‘è_CÏ=fök&¨¼úhkðU]šsƒÍ‹Ò¥©Ãä|Ð ÖNýSÏÔÕëNdyߟX®ûu@BA(`λ÷ïê´àz”qž¥kß­S=øÙu„FÙ)ðO•Oý“g¡˜‰ûKde%™'&›pvXA3שû’Gù ¹V·€ÎÑÐ6É ÿ¶ã¢Wõ)ý\¾õµÊ¿ûyÛ—´½ÿ{ÿ¯·óç¿¡°úÿüˆ°úÖÓ»þïú¿ößëØ ô#ûií¿cS>l{ëÆÚÿkÿ¯ÿŸmý¿õÿëÄõÿaµ8˜ÄþóôÃy–ÎÕ¡]€ Üô—¢-è,Ö€)˜­rW#¡~ýÙ_|p¦üíXÂÃ/ú‚sü•”+×á= ˜}ûÍ·¹> ”ÇçæßUŽQõòÕ| qÐrõàˆ—Î.*m˜?XŸ]×€ŠÃ>é}#¾/’µMm_ÞuU1Z¦îö~x÷QÂäŸÄGûú8`±v‡„Ðçd燺ÑEî!n{Å•ËyÓ[¾9Ç+•œ6çÔŸ å)ÆËá/÷@½d7O»´yïÿŒß½ÿ+‡ÆNç®ØõÎÿ³Ó1óuúCØù¿úß8Xý¿ë¿qpl˜»þ¯ý—uÓÚé°¶®ý·ö¿± ÔÎ=1cCÜCþÚÿëÿÂúçé®õÿg0\úø(PÒu¦>>}òÛâÿ?y‰{`Ô†dñÀ´„¦x¶Îªô6è8h€ª冶uHóŽ)e~ѽw |õâ>SÞµÇÜ ¤(WÐW1I Oë˜ÊOä’IÆ¡ÃO²©ÃñêÚyå.jðh›€dÊICë…íb;³ ì9ŸH&½÷EŒçºzèå7´ïÛ6émGûjïÿÞÿŒãƘ›¸chçÿÑQ;ÿWÿWov®tŽ4^ý¿ëÿ®ÿkÿ­ý·öÿÚÿÏ>V}ëf}!q}+}Å?‰rù6¾þ/f®×ÿã ®ÿ·þÿ3nþµ9üÿ¼Ä BPEÙ47YZ•ú>b'O°ÀÒ†´þªHQ´¼¼wß¾ /:€¨ÊÏíÒ'q|.‘oÀžÙµEŽðéÓS1ÅD¾È3¼û¾(²¹-@')C‘ y>|w)çÒÔÝXðËõðøÕõB{4&?^µ†G_/OZ‚:æÐ7xTnym£GSú*éè”i?NBÚæZP§s¥S‡þô‘ -÷i8PÞúgØ>š|©O?aïÿ{ÿ¯qºó?:dçÿÞª÷ªÓèŒÕÿÏëÆêÿ]ÿÍ ‹í®ÿkÿ­ýwü¶êÚÿÇÆ^ûý?>îúLJeS²'…Î9‰o|üÓõÿõ¾Xÿÿ<‘¦/žþd^â®cœ<ÀšQ²þÏêâÉo8ƒêÐH+´¥±eäH™êýQ úhæÐ·|Ë2üNGétv•¨eØÐAÓ|åË/Sã̤Ù!t€£yà¦uˆN… /2hðüõEÄH׎2cåzœÎÉQPII|J''œ6ÎÎ+_FœëÒÈK}×}¨¬Ò•iŒ^ž¯4zá¾¾<²ÝðLßü ±–“o'Yxææž¡ÕçËU¯zνù¸ÞðS×E£Œô½ÿTÔwúgïÿÌÍŒîÓg;;ÿwþ³úõÿ³6Y‹æ¨¾ØõÿyÝ·¶è—]ÿÏø ?ºžÄôËŸ³Þ¬ý·ößÚÿkÿ¯>Üúëÿ­ÿÿ[çÿ?ýè¯ÿü-£Gèbï8SÀ‚¢Ë( Z J¤1>ÚAÄ'•/ eDÔ¨òŽ*yêñµ7`–šk˜¦Ðu=‰)GùãÔâ•ãYðoÊ——·pó;»·"Ÿü y¬nxhO®/Çyyã~“ÖX~Ó¾8MÛ_¥•^'DZϵ ß~n}ÒÛÿÒ á#ïý‡ÃÀ˜4F½6Þyé[í»ËŠGîgÀ÷òL¥ ñüiýIÇcø¡"Û\«[[öþŸ±¡/öþÏhÙù¿óÿÒ9ÑK«ÿ£ªóWÿïúß±`~ìúì(}Ñ`ŽŒqqlµÿÖþ‹mµöÿÚÿëÿÑ“ëÿñ:g½˜ÿwŸ9¾êµnt YÿÿwÛÿÏ;°®1ÜxG€Ž902q ½‰äÈ/Y—‘Ñ_4&;à^G«"׌8(ÕºZw⋇¼èûëkÎG´pÉ@"'ù<+M.ç7ôØ\äVïÎË?40s—‰iõ닟~P£ ¤íì’\{¿:]K—fgVò§.ux_–r퇴_m_r¡UŸÝjo^¿I3µß¯Îò^½>/ÒÇÇû¸î}‘ó¡‘>SZZÚå<×ãLàš?IÍÞÿÇäÞÿ ט4žcʱóç¿_1é–Õÿ«ÿ3²”œuÌúãØõìƒKgîú¿ößÚkÿÓ‹ÆAÖÎký\ûÿ²%®5¤¾™X¨ÍùØ¢ñs’3.»tý?æz:cý¿õÿ§ýÿ§Ì#„U 3ê³c‡²àœF¹^ŠÃN9@ *(èÇÁòÍ幦 »C½—›‹¿Å#uÎT;ÀÊí|’žÓ¤Ï§ùr å?è Á›ƒ'û*<>©ã#€h®½ÓFím¿r©còÒ¦‰ÒÎËðLþE£ÝhTÞ£¥-hñÒN×}Ñ gßMŸ1\Æ|À-ýv¼Ô©|ƒsu> `¥øk‹òí?},¼Ÿ|h³ôW³³ ­~NÛ‡Où’«ýž{:×ò’?±´Ô3² ÓgÂÞÿk7áÞÿÿ™«;ÿ£¨0ý1ºcõÿê«WÖ2kÉ®ÿÇFØõ?6ÅÚkÿÕ.­ýjÝXûÿÒ™kÿ?ÆÛÂX©o"Žo6öwˆ®u&? ^ èùKŽ–_ÿï€|ñï¦SÖÿ;¾.³uýÿç'©~[ýÿ¼ÄÝÄbxæìœ»Î¯€«K™Xx ¦ÜÚ(|¢dÎ.–€>Wž|×@‘/çѹyîØ„z”:¡ò ¾j8Ùhå“ë‘7tsÅÎ(é¥Áϵ ,]—|4Æ¡@åðGFr‰[ºæáõÿ²woK›ìÆy ù¯î^I—3aËÜS²ì¹Ž Ù")Ëš3LDø`nÐsÚk×Ý‹œ|^ÔûýÕmʲ¬M2Ñ]?ª€D"™ï‡ªúîÓ”БK~øOž2¥g´½{;àÓðm;õ!^Ù6± .‡ Føt¡'è{ÈÛþh}h¼8_ðEÅÖéÚ¹C8µ>÷§´æõÜ5\^íoÝêsTn´Ú„ûÞÿ½ÿÆfÇGÇFçÏÎÿÿ«ÿWÿïú?»ÃGO ]Gïúÿþcúˆ£ºöß±Qkƒ­ý÷ìè 6óÚÿkÿÓlO¾Kôé¥cãߌI>šõÿâóé+!ý“³sîzý¿ƒ3è#ã&>øôÑúÿÿ{øÿy„Сøëhv hܰ¼ø{òg¹xo_c= 3è˧i¹ñ“n×À' ͼL< ¦ôSø^N½Ê9ºÍJc@UIe´ÍCi¼ãI==B3|Èa'Sʪãâ§Þ€RCãý°Ê‡vÒ#Óðuí½8¼§^e€|bmfp  ß|ó &y–™z/ùêÁ§A9÷& ˜¼ÉÀ7¼¦.ôÚÚvW&4ÒÐUn<ñÎõÄ÷Ϩª£<ÄÂÞÿ½ÿG^ü?ÿvþ?;VôQçÚÎÿ£W¢4nº¨zLlëÿêÿÕÿæÊ®ÿ»þ³)Ù.ct»c”Gí英_ÄŽµÿÖþ[û~_ûÿ¡#Ø^އ_6z„®¨‰³þßúëÿÿnûÿ¾Bx …ge`òûgÑeA8²£!ÄØ9$  @t)“”» å¢,ÞœFkAÀ ô[À;;væå;WóðŸkÎ_wqÉÇCBiz^>òC7 _œ†)ã:÷%妟§}‡~ïÿÞÿÊœ1²óßÜØù¿úõÿ®ÿÖÈ]ÿ×þ«m%^ûoíã`íÿ&Ånÿ¢ºrý¿ãêaý¿³‰cýÿ3Öÿÿûã?O?œ¯¤ †X”%@£îP’—cÒBò= ÉsK¤ o%x]eñM@3§ÄïÆIôn(J¯ôè\]ǃápžEchÈ'ÐFQ„ÿõþ¦9ç„JoýAd/™”ÁSÞCé^´©€(ÁyéÚe*4<ú’Ó+­ Qå-}ù¹Î–ª)ëq? Uƒ>̰áUÅgÛ¢zf]ýPÞÒðóÞ«ÊÓz¾;Ûïõ[ñ{Ÿ*ÏÞÿ½ÿ3;ÿ®0wÌ?¡ó(:äÒ;ÿWÿWvî¬þßõ×ÿµÿÖþ;º¯—kÿŸ''¬µ'Öþ÷ú–õÿؘëÿ­ÿ¿þÿû›rþG🧟üÕŸ½~óöMÀ—°S²Œ1@•tˆ4&*D^*Ðb•O²Î#zI›2 +/L¢ðR¯¼Ì}x«O Ü£Ôç<4À–IâëÅèón§a†¯ &[ïj¨¹ÆPÀ-‹†§LˇÉиV¯8å†Þ9^'ex’C?DÞ9'cå«7/* Pöü«„zÒwSF{Ò&â\ò¸Ê–N'Ûb?Â{£ÔûêT¿²½'ÊP$Óð‘×4ô¾ZXÙÞÍ)K`˜þHúÞÿ½ÿ¾ ÆæÎÿÿôÕêÿÕÿ»þŸ„<¾³ëÿÚkÿ­ý¿öÿúÖ‚õÿPÍ×äs®ÿ¿þÿ &ÁŠQð#¤ü£á??ù÷öZ @’î®*Ø"­ïAâ̸6qXÝýÄé-`Âù=¹×€Z ~w 04Θ\À—÷”a¸F! M¥,^CŒåäÕì.¢8A“¯œº€.Òßή¡ìHRÑ%“G¥ÝëWVàj€KoâtNZê;¦NÀ¥‘õÀ?“ñA OÛ$ ^Àóbví³Ï> OçÒ^}òI*‹l#»¶àÔ.µÒÇ/{mPþ!ˆ/¹õ=²íð’§»ÏÜG Õ‹ LÃGý•ÛW ·Ÿ÷þŸqº÷ç&Úvþ¯þ¯¾74ªGéÔÕÿ»þ»þ_JslÎscí¿µÿb{Fq2ß×þ_ûÿüxo,¬ÿwôæú㑯ÿŸÁß|l ñúÿÿ}üçéû?ÿÉë·oޱвt墥ÍIΣx/ p$¯ÎÝÙ>x(@€ò‚8Ï¿ðœQú«ÙýóÈæ¨c^êÌ œóûuiäô1ÞçMƒkÀNÀ¦D•¯üÅä(XA4åã½7~.™\kŠ2dè¡ô@éÕ«Wá±Kedœ}úé§ÓÚsÂø´®È€çì2#/ÙÓ?Ú7å ÿu+¯Þî–“/…—¾Æoæ^*‹oâ«OÈ&Pš€´½ÿ{ÿ;Žvþïü_ýô+¹ú×Ëç®ÿÇÖbk°UÖþ[û¯öhlYãbôeί˜þt½öÿùÑšÓ±öÿúÆ@æÉÌõÿÖÿ_ÿÿÿyúãóÃ׋Ǩá×DÁîŒðòiú’ð€D3Ñ ç16¨à€’wRMìï.x@#¸uÞÁüä1yZ¡´u¡Å{N’ï?TÚ2@Žre1çw>å•›O9eÔ›Ãù<hw–`ÇWÂÔsj:‹~d~÷í‘»ÊIzøu¥)œ>Àˆ U’®KÛG t½Häº;©Mä~å©c»ó*/3Wftʨ/e=¢8²ztO= .>äoüÂðÈ/MÃçÛ³ô©úèRV™€H§Bç÷¶}Øv=ÑÇ:ñ‘—xÒÊWÈ©mþh”€Ë^ ¸…Ÿ¼;H‡¦fîý?­îýßù¿óõÿêÿ]ÿwý_û=V›ní¿yÅÚÿ±û×þ§dscý¿õÿÖÿ_ÿŸ>øÇÆž¾÷?~]à¤Fúh¡ ÓXèñrW)÷âããÜU\Ûå]LÀ |xO:žÎý‚,*¿ÉD 9—ÞGø9îeñtm!Eù»·Ï»Â hÈèð…¿ Ç =¿&©OÈn¬[=Ÿ|¥q³TÀ§&J×N7©òöËŠ•˜tì 0‰Éí]U˜<]u“¥ï¼r®î>¢¨\i'#@ÔÓƒWKÓ½?ú$`ÜÐé;AÚÛiW寻édÁN_I¿:­}¾÷ïÿÎÿóhòÎÿÕÿ«ÿwýï:šµvÖuÎì®ÿkÿ±·Øikÿ±#×þ7îÇÚÿÇw«O'¦C×ÿ;~Úúëÿ÷Bëÿ{¢ºBП³ëO_)ºc(†×`&O€Y{€@¯¿þú£?üÃ?LzÁ4˜:,RJÚ»Cä)ÛJkÔ¹vcÐ5€PÐ'€)u_™Þ%¥nÀÔG5ÀþÓ1ž”`ä"ϲ·=beÂ_»6”-x3™‘CŒH—:®rø©ç;^áãZ ;þ^zæGe"×Ðàçü‹/¿HßÛ½Õ—°K÷H¢à‡¾++hkP×ô–“ƒ|¥“&Hï½Þû¿÷çÿÎ:¢:¡ú’R[ý¿úß²ëÿå„ïúûxËž`wÄö`‹Ì5;gí¿µÿŒµÿ½½öÿûÖÿ[ÿÏ:Ñ`–Љ×ÿ_ÿÆBÃÿyúñ¿û—¯}zŒÀÈ€DŒA©1Ð^ÌcgbЇ! 1àúÒgeÑŠ Cyof×’œÛRšÁy U0o†Ÿ_,•Ã#]PFººßõýO³óËçVX@‹Ä9ÏÒOÙëŸ6wZ?~‡ì„®z¥§Þ©³ *ã׀ʣ-Êø«ÉsŸáçjêž»þ#Òíú²; ÏôÓ¼ _ý÷æ›óeAÀ[x Ь2£IçW}ÒÈo›4Áû¬´g˜…_輇kúÍ/ƒÂÞÿóN±½ÿ3Nf×;ÿÎØù¿úõÿ®ÿY(çÏ®ÿkÿ­ý·öÿÚÿëÿ­ÿ·þÿúÿç£p…à{¼áŸÿyúñ_ýÙë$€Ž>zÆ`ËsÝ€-€Çü+ø"¯Â~ùå—lº³Iç7`ÊÄ ¾‚c^ÄÀŽü”ü' ¦xuЀ1Ùb:à•òäíN²¥ž ìAçQ?À—ó4eåÕÝw([ð¨ý°gèÅ•³yê>pÒ²¦CÂ+ÌG–{P·öOìZ?ã©_µ/is]g‰,-Ó:||r~—ïN#/Ç0Ð>íGû#N£l¹ÄÚ9rµž½ÿçÞïýßù¿óõÿ{úxõÖ”]ÿwýgݬý·öRXûíÿøüœñiÖÿ[ÿÏx ø–âõÿ×ÿÿÁ~ú×ÿúµÁå]LvJupõ9dï´*HÔ*ô°Yœ”-ÀåQ³CŠp} ½ó¼khƒ7@ú \ÁÇn$y¶¦«K9qÀ˜)[P§eíuÊ è/Z¼Kè(M»Å”ÅÛ'ô’¡õ¢qž6\ò¨³ë]†ðŸ<¼ôÉ"BÊæÁ¡²K¾óòn-2JÓf‡ ‡j Vöé„ôƒ|²i#°¯í’.´ x ëc…v~ Ò„È?õjcûaïÿYlõÇÞÿw¯÷ÐíüÖAæNæÕÎÿèØÕÿ«ÿ­%Ywf-ÜõŸ†x?ìú}zì }!¬ý7?¶®ý÷žýI¬ý¿öÿúëÿ­ÿÿ öÑ‹ãt<|wþÇúÿçÄ´åÓ÷ö“לÔ¡¨±s7¢GÁ‘"¦5ôÞ}{^J.¿üÿëý¯€ð0É ’)S0«ËƒHgò-€Òäñ·á˘ :9 5é÷¦†'™S×€HP½‚d-ç}^­¿FkÛ§ÜôFäN<…äÝûi0BôQLü´É?ÿüóÐ}ñÅ^Ú‘5…Ð~*‡tíTŸ(Du5Ÿ|~ÝQš]XBΧ úå÷þŸw‘#{ÿÃj|'ÆGÇóÎÿÿtˆP]t‘‡¾siõÿtÔêÿè]ÿŸ,ÛõÿØlŒ˜µÿÖþcƒ[WÖþ_ûŸSÿëaO¬ÿ—ùÁîZÿoýÿßwÿÿ釿ø“לSϦ›¥Q0DšÅÂÒ ƒæîÌÊwGß.`ÏòQ®×Òtº2Ÿ|òIb/RwþÃG(OçÊzo“ ]ðhK§à†Ï¡=3ø ax÷õ¥îQ†# (@ÅÕv»¡Rïì8WžíŽ˜ôóøÈÆ&áñ|´ò[6´êŸ´†;M¿®ˆ¿s@ÔÛqø¼ +ÿ¦\Ú4|ýWþoß½}€\¸çån¡šû3q_Ê·~8²íN{®ðßû?;÷þgôtÞf\ìüßù?:hõÿùq`õÿÙ½lMqÖç»þŸµºës휮Ùé¬ù³ëÿÚ#kÿ}'v¹þXûíÿûì]_âÿ¬ÿ—å£k‰ù²þß`ëÿg\ü¾úÿOß›—¸› 5ª ˆRÕ„iüt·‘4å,>ÊÔéõl7z@φŒ¹Ûh}ùÎ3ñèÔ{WXx÷ùpy(¿VœÐ)ã¸Ó¥¾K^r+‡>í»Ú˜ER]O‚‘Ñ£’dÿõõõµÈ éRxyÑœr‡ß€"³öL‚kG”îðó(£ LöuÓ£´§Ló•ï‹Ü¥¹Î Æ/Љ,‚ö&Oý C›pÕw_ÂîÀ½~¼¤7͵_ÇÞÿ½ÿZoF;ÄžÇÝÎÿÿô=b,¬þ¿5[ý¿ëÿ¨Ë®í÷µ–u½ëÿÚcl=Æ=ºößÚÿÕÆÃÚÿëÿuÓÁúëÿÓ ëÿÏ¥_¬ø˜ uD2YÆÈЏþk 2‰ÐÁqé9zçƒãæºþ¸PVVãͯ·÷`·”mÄâȃ÷”SGe»~5;¹ð\;·£Hý$;±ú"õÔ9rô(ùŒ „Y}lOY²õ@ø’šìPgÎSÇÕžpýiÉîp-V¿óÊ‹ouõ¥ÀêQšÖ¥ŠîÈB/4/Cpz5WWÒIQ߇G©È/´®ö­ôÈ52Oá‡Ü{ÿ÷þ/OÎcÑxé¹ñä|çÿÎZÈxXý¿ú×ÿ]ÿ­°ößÚ3²{3ƒâú³öÿÚÿëÿ­ÿ·þÿÙ@dÉ\ÿÿ7à?ß¿^âΨàp 50€>yú¤_yC[§D™3@(Xpf¡ƒòCÏXIy·!wã2b.pÇ«<÷®ÜU˜‚O”ÇWÙ:ËsñÑÛ¸”ÍãˆÀ¨á÷âåùò`3pJPÛåúñ¸ÝˆUùå´òŒŽ‘u=ùäQøe‡æª'<†®}©|ë~äqôoüµ[Ð^áQvxyo߼ͮuË÷°ö½2‘vx6–&T8WÏ÷–LBc²µ^çÂãþ9ßûŸñ³÷ÆÆ5ÎŒŽAç;ÿÏüºÏ%ýâèÜOÞÎÿŒ!:¦;ZWÿ¯þßõ×?<®ýwý¨¸ößÚÿkÿ38*ëÿÍSMëÿ­ÿ¿þÿÙ,Á}¼Äýît}1Ž×]ý¿ëÿ®ÿkÿ­ý·öíx1»¹öúÚÿëÿulÔ·ríQ@qóŽ}þÆïš1”¼õÿŽ:ý¡_Öÿ_ÿÿCüçé'ÿþ_½6u Òíy¶ó8×dËäBsí2)¥u"»À5¡Ë€»»›ôî8zÐÏ‚Eø<^Ž;¼ b ‘_ð(²M%ýá‹ 8#wÞ™5×èTP ½²m—k`žvmˆÊ¿t➯ΠxæX]”´#²L{ɉ‡C¾ÃyÛ:$—Ðçü–׺ÅÀ²/àZèôÑß¼µ&±²Èl¡ôæUž–Eòayu”~ïÿô÷ÞÿÿtÌÎÿè«Äêÿ£{«'Wÿ[õgݱVMÜ5ÇG®¥ïúý0ýq_Ówý?ý±ößÚìÒÚÞ~Ä^ûíc¢:ÒyÖÜõÿâãéý·Y^Öÿ[ÿŸÛšP[Ì…ñҸ玟ß6ÿÿéûów´XtÁÐHeáâ —ILzi¥9×p('Ò)߯ؔ§D£,°Én/Áµ‹^ìýPbõ(+==5úÌ9(ﳚk àW_}õž±ˆ¯r;·úˆbo&'/ùM#9m-ß¶‘7}«}.´É1õäqˆ«¾¶uX‡¯wrá‘ô©³£MÚ#\´i×ðQVˆ,øN{É_™äáW¹µa’ëiñ#/h•I>ŽGùÉ DWH[‡Vzi¥9ÇgïÿÞÿÿ;ÿé„êHºaõÿŒ º}õÿcMÉÚ7}b|ìúØ]ÿ×þ«­U]±ößÚÿtäÚÿëÿÑ ëÿ­ÿ_Xÿÿà?O?úË?}mb¸°` ¶9Œ— €‹‚J~UõžÎ´‹ `úy'…‹ÖQ¾÷X: Åñí¼3ëÕËókˇžäýK ø ™w[õ‘ÁðãT³ñ{çó˜àË/³+‹ŒXî<=J˜ 03¼K‘mú ØŽ©S?عEy¾ H†³¸ Õvâ“v /çœ+_º‚YòÑ—§¸´b_â9's}ÞsåË·tmó>zÉ=+­þWF¨<Ê{ÿ€Ýû¿ófÎÎÿ¨„èœÕÿ«ÿ­/»þ?¯Õ³xfmßõìŵÿ¢,Í‘µÿžíáÚ—µk×þ‡cÂÚÿëÿÕ[ÿoýú¦P=ilÄŸ_ÿ?ï6ç‹çj<ý³?ÿÁkŽzƒŽkç3 º ˜#v´“-JOç«D(ÂØ‹Ðu«¸ë€?C§\ò§n¼¤–Ôïð~«ÒÊoÝät¦ ¬‚:ÎÑ>@¸¡—æP§òÊ’åR`Lý“'ØY$(Sè,?I» ôã=Nz:X[æÐ;¼òuÄ¡mÞ\;¼´Ñ]hŸÉO?mû¡íŧýƒ^ÿü€\é»\$“—üá!àƒ‡½wi¥ý©9$|åÐãwdŸxú£}Vù÷þðoïÿ¤wþÏ|Þ úÈvÅu\•ä í‡\OQmæì{ùûˉåË“¦êѯÒ#§ú& ©,ÒË_^{9ÈT9uMy—üIÌ=©Oø/ðòÊ8œ7¸Öνÿg!r/öþÏûvþg^˜'ŸæMç¡9¹óÿúÒëèÕÿ«ÿ­=+æM×(«tG瘞Ýõ×ÿµÿžmæµÿÖþ¯¾öÿúÖÑõÿÖÿ¯ßñûæÿç?ü§ÿøëî€Ê\¸œ0ç J;|òbôIïVÞ‚!htX_˜þÙgŸ}ôõ×_çë~â£èœ˜³ößÚkÿ?Áö[zíÿg_ÂZYß䬛ëÿÕçZÿïø¸ãx®ÿ?zÃ<áŸÃUÖÿ?¸Æß„ÿdV³é8åWÏ9y2®H>(G4ô•§e É‹Å'¾7Ãú=€}E_žâÊàÜw¨»;•ì¢RþK ¾È'/mW.Ö0Η çZù(‰)#¨]š€s‡ºå“; Ñ€FÓ„žÛáúðœ÷cM{"ç|QìZÀë‹/¾z!@Ò¤'žkôúì›i Y\Û]¦=øãh¨ë&«$4£æ–œ>+ôä_írÏа:¹SžÌÚ÷êP6å‡YÚ6u’ù‘®ð•·÷ï¿1j|ìüßùïÆÃ=D/Ný±úõdže¤kJÇFv¸Î81fºöìú¿ë¿ñ±ößÚì ëËÚÿÇ‚Þ\ûý¿õÿbK¬ÿ?FÕåó³ø÷tÄï¢ÿÿô½Ÿÿä5à# ÔØ´XÊ4\Z,€*×38bT Òвyy”x,6Òî 0Ç;u÷²Î{]Þuv p@&†,^‰/‡\ #4úîÈ 3}9¨¼=››`Ç“EŒø1œ½—JÐÎZ¥GÂWyò¡¯œáy¥§àü‘†—_ç½´Ý5™C;ù¯^ èöæ¼Kß4È×ñÝý%ÝàÓ¾°Ç*ôox }ú[|Z™¼ÓJìŒgÚìú·/¦G‹_v¡Íã•ùg€«/öþïýßù¿óÿhÐÕÿg.й«ÿwýßõÿ<ƒÍpÙæÇÚkÿ­ý¿öôÀè†õÿÖÿ3Öÿ_ÿ¿öÂ?$þóôýŸýäu‹#y÷Óœ3H1œyÐÑ÷9è´C DŠØñÕW_…ÐiNh:‚_@ z×wòæQ=!õOZ<»%×/û¯òØÛ¯Ž,s­²xìïåËWtP&ïŸÙð¡DÃgâcdÇ!SÿðW§E7ñУL“&Qž´ôÉÄÚ]:4M?®Õ‡vdÔ'IÇcNî/Y?ÛãæU“áqE¡¼ÉîßÃ: ¤I#ó¤ô²è¤uQùMFxá×´Ê›„ù“²C'ÈÛû¿÷çÿÎÿÕÿ«ÿwýßõí¿±‰Öþ;?ô®ýŸ±ð°•Ùökÿ¯ÿWßiý¿õÿ­ëÿ?ð¸lBþò÷Äæ+„òšÒj`(1z`ŠLz*žs€A.ÎÀ ȼ²£©×a6ôøPÁˆ2;“Ä€dæúy7–4¹êP¶`OÞiu/+õOÁ¼Ø˜“G \óØ_ÊMùòrµó¼³OÅÑ©‹Ìú€œ'ù½>qýñ‹yéûü+žÚ‚rxvg™Ý^B¯ÑÕø Ø]…tòKF–é#y‘Äû½öÌW]k»€îWC¯:eñ#Kòð]§îɯ¬hIØë½ÿ{ÿã§GÆÖ5GœÏ`Ùù¿ó?:…òXý¿úß:bíÚõ×ÿµÿží½µÿb\ƾd;°3c›®ý}¹öÿúæ…9±þßúÿëÿ?cBÿ£øO¬:«¾pb‘)Qð'`ϤË:‰ðR–órÀ«oçEã~¥eĈ31<”-€äeìö ”rgiÊ*§Y ®+«ëÒ#y£ ìÒÒxå Då—ã Ðy9#ŸÐJx0ÄÅy¯ÖÒ‘y*JñÔ[€}h&½‹tÀ©K~}ê_eïKÑÕ…/` ß\_<¼°ÝN,ýîOtUtø´½é×Ó6’Kšü<÷zÉZp.;ÍÔ‡^çØû¿÷ÿ_ÆÅÎÿ€ÏäØù?ã‚îVÿ¯þÏ8°Î\sc×ÿ]ÿ×þ; ÍÚkÿÓ‹Ç'YûßZ¡/Öÿÿìú(Úúëÿó+Öÿ?Äù±çàü'£3 däzþ™( ŠÝO}”//]JºÀŽ—¦¿úäU¥Uà@KÀ•9ÿøé<‚‡šs^žÊr—\ âž'áú¨!£x*Lª²ÝÅ•„a1¥ïÏ’O>å€U¯É§¬÷N‘É»±Ð4BþC'ß9¹Ú.i®#“ôÙ †·üæõ—†Ž÷uÝôMÛ'ÖjÀ`¾Ô?iå¡wð-ð¥Lû+uÍ5Úü½žÄ\OÚ#”æ–¶÷ï¿q¼óçÿêÿó# }¹úv\]땾Øõ×ÿÌ‹µÿöÙÚkÿ³±×þ¿vÖ¤/Öÿ«Æ7[ÿïì^×9.”M‘cý%ü7þjR'}ÊF×òm§œûŒ_~Ñ8YÿÿwÓÿúÑ_þék€0¤»‘: ëÃX‡F d `2×”`Ey|;@3°¦®Æòî´ãMÜû›ò•wù;r€ Ô¿H}®åùUÐÉ‹©Èá]T«{À‹Ì婽ÝePãœhÈ,˜8m›kôÀ&uÜe/ϦSZSQú'üÒçqH4ùõnb¼ä»ãùk»Ö¦-&¦ é¿2Bò“~€ÇäϵÇ5ÕŒld¼êp½÷￱¼ó?Ú$únçÿѱôËêÿ£_WÿŸùaÍØõ×ã`í¿c­ý·öÿÚÿDZN®ÿ7X|¶³f®ÿw6{ð5ùÄõ9õ‘Ð8×µ´¦7–¯|ýêôîЭÿm`™þ±ñä÷Åÿ€u¦˜¡1i#óøZ*Ù-•GÙ&¿ƒÏ» <·ëÚ."!`ÉÅ }˜~õ®“ðTê LáùÓA*~Ð^™Ís©\ŽÈvÀéq¶€=Û»¿› „ÊšO?ûô£/¿üòñ«1:“©Î ŽN4éÊ{¬o$Ì×þðz7ÀÝ£Ž)?=®ÉR_Î'+õã©ÌÓÇg±Gãš²Tã¨O¾ºu©/&æú’GèQÒ‡Qº•칞|õ º»²&¾Òä…ÞÉöþïýßù¿óõÿ1´Vÿïú¿ëÿùxmÁ®Xûoí¿µÿŸ;û²åÙ×'æÊÚÿó:”ñY¬£|ôÏúÇïºÆÌú™2glÌ©1ò+'ë‘wŸ[›Xÿÿ÷Ùÿúgþƒ× ƒòþ¡1ÛÁ¥?Í£~À“)vyß’G(%¿Àp:Ñcè ¾F&gó£¼fâÞöÔ™‘ÚÒ¬÷s× @apøÌiw x¦”Lá?éyÜñ’àcKï矋üøÇ@ší&wÃé‡d½þdV¿´uèÕ7Ì2µOÉÒ~yðäßë`…ÇI×)Ù 6tdTOÁªÐñQ®ý”þ¼*’ŽWÊ^÷H–¾³Û†üxUÖðØûŸþØû¿óÿšF2vþ¯þ§OWÿïú¿ëÿÚtAm°µÿÖþc<öxmêµÿ×ÿ[ÿïàõQ×ÿ_ÿ6á^Ìa¼­Á(Œ‘Žþ×ý¼þ˜¸øÏÓ÷ö“ט8Rx€•ëþOÓ!}xÑ¢kÛ?•ÓäÀOû…îsN~å•hh¤›a5,/ô•µmF l˜ §‘ƒ,=Nâ%ûÞÿ½ÿ;ÿwþßtØêÿÕÿÖ’]ÿÏzmÝõí¿µÿÖþN\ûý¿õÿþ-¿týÿƒÔßæ»¯ÿ6ëücà?O?üÅŸ¼`ríºjgKs.0bmƒîDœˆgòÖÉAï±BŸ [öÑ«W¯N¹¡ÁçC~[†}êž²âÖÆÅ”+@óÈ›ù’’)W¤ù…¡|¥šµPÊ/¾ø" –ºZ”ÈÛ¶‹Õgrö½ÍØÔú&¦É«<ä÷5ÃN#TÀ¤‰Qá9ý9'y©|'¾²úYh=m‘ë÷ú1TÏÆ5žBË_Ùé“{9|ôåÙ]W®Ép§G·÷ïÿÎÿóÞ?sıóõÿc½™ñ°ú×ÿ®ŸY‹gLìú¿ößÚØ­cOžù±öÿÚÿÇ÷ãoÔ'‰_âbô'¦þt×C²þ_úGÿeNM§¬ÿgdœÍ ëÿLäîϳQ„̳9—÷Ûêÿ?}ï/~ü:@Ï Ì(Тa}וƺöN)çvVµ# ØfL"ù÷£fAOþ¥šÐ¸&‡ØWíø²#,uà£ð'í0 8ä%òû5òêqc¾™ÝV¯^¾zLì—/Ï.1|ü¢*¸©ß¹ÝYøsž0qåïtSTG®‡P¬Ü»·g÷YÚxñÀ7²µ¿ô£x•kC£ñDcgØ£þICSúðÐgC§ŒºÄÒÕEÑ÷<×W]èº+KzÛ…¯ëðšsÁùÞÿéˆ[?íýßù¿óõ?]¹úÿ¬Y‹fÍØõ×ÿó§¶O批2‡ÀÎXûïììÔµçÖþ[ûŸÉæ^ûý?kêúëÿgѽàÇÑõÿ†R[bÏžþä¯ÿõk  (å…ígò `u5FÐL¡\OÏìPFùo„!]œ›¦LÓ(}‡SÓÅøe‹~8yû(²á-ÐÊõ‘A×M÷E@ –6”ÝR#D£=n~_‚Žow\Éo•ý·ïÎn*¢hP­€^všá|Ò.4øHKù9·ë ˜EÖôé´QYõX¬€ Ât@IDAT‚<Ÿž“KH¹öÁfÚ `S^x÷@ï<ýì\¤ âö›ó€gÃïÿ{öþïüïœÙù ý`~Ð_´ =â|õÿêcC0>Ì›¬AsÞ´®­?“¾ëÿ®ÿ,”Ž 1}²öß±×þ[ûŸî\ûý?>o|¶õÿÖÿ_ÿÿacšOßÿùO_S” ˆ*®?ùä“€-ˆØ žÎ{;ÌðCT¾C(˜³u^\,ýL9¶mR8CŒ^Fðà¹ÞÇÃàL–ñ¡óÖW¹ÊúRfÈH€é­# ´UYíð+àMyá­¼¶E?ÜëS—t|r;“<ï iùÄ€v&’HûÕì0 à5uõ=a®cüe^@ëä—gúÀ«Ãû|˜*ãhÈõu‘¾ø 4²S×Õ¯{ÿ”œûÒ¾Þû¿óçÿ™ÕÑ?«ÿWÿ[×­a×Úä\Øõÿì†~¬Ù»þ¯ýwÍ1¶2GÌ•µÿØóéŽü©m¾öÿÚÿl.ú³ïcŽÿbî\~ Ÿ¥ëMí’ÇH’7Gʬÿ—nI_ÌY|Býx ëÿ­ÿßññÛêÿ?ýøßýËׄ·xx$Bà¨PéyW® þ– Ýìx¢t »„ÐØ •÷b]“'I%s|àÏð{€9ŒãÙݤ¾CW]z÷teòø #aèüûÎ<âêN(Fµ6Tûúë¯ch·=ââQž#š42©ß!x Ñ#ï¾=;ªš/O; >¹–Wáyµ¡m¦d{íÔùÜŸx•GN.~äðëä‹Ù ÜÒn;ÏÒŸ”‘ÖöáQžw~=Ç·÷qïÿ,žÓ1½w{ÿwþïü_ýOW®þ? •µÞúfM麱ëÿ®ÿì¼µÿžm·Úkÿ­ý_}ÉæmÎ^g£¯ýŸÍúgý¿³žÖWÓ' Î×ÿ;½A¯ê‹Ž™õÿŸ7¯tÌDÇL?5tLõºt®õeí¸ßFÿÿéGù§¯Û0 ic¥®5°iU24S¨ùÞÅxÉn¦‹šn9W6åçBÇõPgwglºLY“u¾¨ Z±|±g‚‹Ìw K/%­ àJz¸i‡a¯€PŸ~òiºÊøk~1Í{´†§:§lh&Æ_ýÍÓ7ÒºíýÍÛ7§îƒbxµýrà†ÿT’zúb÷{hñ—æ~ä1Æémê¶R¼Ãchs>1úð¾Î'J¸§9/ïæ“¯4{ÿ÷þ?æñŒaçÿÎ:fõÿÑ «ÿ}°ëÿ|™x®ÿ³›}í¿÷‚Y;×þcç®ý¿öÿúY(ØÓ—oßm®×ÿ[ÿß:Áÿ¦'êË×G_ÿÿ7ã?OßÿÙO^F<¨ó „8éÂËPt¢ SMò*M‡£Ññò88oû¨ÛÐ$\‘óÞ(´‚Gý^|ü"“˜ 4äŠ ®çOò’¥%Ýú8eä ê/oíªldõ«‡£2YY慠ìÚ6i5ÄÊ  Jºó~eQyGœ{ØÈPÞdécÊäþbô§Ì€Z—Üm‹ÝchaNÕ«~ŠÎ î] SÛØÏ€•´Ö~hnýÖ<±¶‘aïÿÞÿÿ;ÿéz…N è Çêÿ£SWÿïú¿ëÿÚôäÚÇ®\ûíþO}¬øPëÿ=ü·õÿÖÿÏÿ^ÿÿG[ùûà?ß^¯¼¤|Êí%ç:^Zo@+t-äzN«¼º ôòê“WáSø4à/ˆ•E”á85ýÅ|)ðÓO?Í.­!˜ÿhª v š<;¶äW‘âQ°­/v'`HyåÔ­í®ÑÞ!çÒäµ¾¶Y¹{Ç_PwéÛ<ÚxRfyFûê‹ö[ûè”?»Ïb(“yÚ÷ÝiŸþQ÷±X˜¼ãä;> MÇß¹r­sïÿÞãeçÿ3 ¼óõÿêÿ]ÿ»žÓÖKÁú)]¶ëÿÚÆÂÚcŸ_¯ Yûÿø1kÿ_ÃÜp4ÔG¯ÿwüëgý±þŸq±þÿy¥cýÿ¿ÿyúñ_ýÙë±ÊòŽ øb2ÙùT.ñõ^ªrÍSVšA§Üéðç_ï)-iÌ? [èæZÀƒó¢õ*8ù©cHÈ‚FšCV€HÙ‡³ig^“—Gù·ïæ+…“ÿêz1=>h”0¡éµÝLq^&O#±÷dåú#Až:ãã^UHäë¯T´!L?´ʵþ¶Õ— «À”º¦(yóh¤w|Í?mR¾r8¿d)F&@ŸÊ¥kOò‡'™¼ãE=äÚû?ý¿÷?cÐ8̱óçÿ¥'雎 ºƒ¡wVÿŸµgõÿ®ÿ»þû‚® X|kÿ­ý—ubƃ` YûíÿõÿÎzi>˜ëÿ~˜ÿ|Ñö‰~ê7;_ÿýÿ§ÿãÿúÞk_ôî(‚ã>GÞ±”C3©c`Ž` Y†n΋Af;Ú>e˜/Ýý”8eº3 ­ ¨b˜¶ló+dsH‹œ—3¥z±Á.?çC[³© 2¤>œ§òóˆ^ ­«=•O¾t× /§OS—ÇùžÎã}®Fªæ]d»v¥þ‘ó,ß3§¯zAæ„«h…¶«×“Í#—ø']™«úm8Œ×{»Ðk?™»Ø´gïÿÞÿÿçeåæŽ9´ó¾$kÇè¥SéŽÕÿ«ÿ­]?výßõŸ­H_ÒâµÿÖþ3èkÇÚÿ㛬ý¿þßõz™ùýÌqA3  ‰CþÃJãmdÈùÅ´pû+õMY;Ú¼¿*ý<´díµíº2¥~2̦‡º[–\ò•'š–»ß«òÀòÊ|;±2“¾÷ÿôkŸø’åÞ;ývþïü_ý¿úÿ¬”»þŸGwý;jí¿ØŠkÿ­ýƒzþĦ¿lsiìIkÇÚÿǧYÿoüëü±õÿÎ?ëÿÓ'Äÿ!®ï/^ÿÿüHö!þ“—¸?õetT@މœÛ™Q¥¬‹ul®gŠó'½¯£{òÈÚ-ÐSÁµ\êº&¯B@•ÉÌ¢4sÞW“Ýawº7óÈ_ÞÛ4çU¡ ÈN+çÞ‡•ó)(ëׇÍ#dp ð%ÿ«/¿|nËPàAN4iߤ‰¥·æ"×úG¨Àº{9í€WÒÛVñlBÓ¾K_I^Mÿý¢ÎÊÓºZﻑE@+´üO;켺2S~iÇÞÿtËÞÿó…ÿ;ÿWÿŸµ­úvõÿ®ÿ»þû¥|í¿µÿÖþ_ûÖÇñS¾HýõÿNŸèaý¿³^Äלqžâ§NñÑëß6F¡÷ëÿ¯ÿ?Êå¿Áž~ð‹?y /@TqhEüêêº;¡ (ÊJº'¯@Š ›Á9£½GÔ䕯sTñKÙ)# Q^\~Œ„Ès•^õ½UÐ8Ê3~òSÖΨ ê¶û*r_ü“æ*ó«ÙÖéÓ×xzaü_~ñѧŸ|zÊ^ò˜D”`çRy’¯¡îÑöf\1¼Ë/1ê¢Üµ)»Ãn´x†ïÈ{zÄÄ=Û,ñZ¯Ø=ûú›¯³¥?×ÚØ6‹ˆŽåáZß«Ÿ½ÿ{ÿwþïü§Çè‘èÛÑ«ÿÏÄÕÿ»þ[3wý¿Ôé vÃÚFÅqÂØVkÿ\×þ?ã¢×þ_ÿoý¿cWZ7Öÿ_ÿÿ ÿyúé_ÿ«×^¢g`ÅaÇ%ï{âÀŒt$xtAëŸrN ö$oòñ@¹¶¸·çY æ:ÏÀË” ÐsÕ#ý‹/¾˜/¼Œ_õÕûõ½ú¦²¼ß ?å[·XÐé݉„/Z‡PÐ/È/îÚ&@ZíK=³ L´”Ñf‡Ðv÷\ä¼÷gˆ®?§ßuýé;<¼Òg/FÖÜšù3|ÚF4•òBÞ/vµ#òHžf½|õrÜû¿÷çÿÎÿÑutát"±úõÿ,"Ysvý·’žW XWwý_ûoí¿µÿ×þ¿Þ:ºÑ=úñþßúõ•ëŸõƒë§²»ãÓ^ñúÿµ»×ÿÿÛðŸ§ñoüÚ@  3€G—d®)£ó庴 ó(š—óA@ Ë“z€’)W°FÜó‚/)s-M£«Òc Jëµú|F’3åq–?ú£?JüfÎ_½z•ôòm}S›;¢¦—ïùSÚ¢­‚ÉöË_þ2±RPÂòRG•³óNDqûCyuá'N™qý* §_ÀR:yýò£t|Û7øÇ™¼úª|ÉGΖW¬B S¯ö:É«lbà•ò{ÿ÷þo;ÿwþÓ=«ÿWÿïú¿ëÿÚÇ–ŒÍ5öÒÝî“¶ößÚÿkÿ¯ÿG¬ÿ·þ|êõÿƒ1è‹àãW æH¾¦PŒÃ:êhZ¯ÿ6üçéGówÄCò‹Ò@&cƒ¼ÒøÂžÇó¼äZZÞ!¡#tŸ_ïƒWé•i=ýbŸ|€ŒçÊ‘ È£>õ¶>tyAù¤Õ£“Žo:n +Ÿ0yÀ:¾xùâ£W/_å­r9†¯ .åÛÆ‚GºÝ" iÚîŸ]VÊ ú«rDÖÉKÿ ½úPÙã0<Ê…Ã%ǽøzß•4ÎfÚxMyÚÒ:ÚGhŽ1J‡&m›4<œïýßûßy¹óç?="Ð Õ«ÿWÿïúlœ]ÿ×þ‹n¹ößÚÿkÿ¯ÿÇNZÿoýÿõÿÿiðŸ§Î;°€+¶Ã[Œb `€B1KwÄÁ5IYC7ò¾–U]•9Þw@ èòñPòíþ1á9ËùÅÒÔ© ¨²LR¶£Š²M¹Òµ.<*+ÚìÐ:ïœ:PÒÃì蚊𣽗¼äa”þ—ÿò_>zõÉ'6Û Ðjx’‰Ìú,νX^何®¶É«¬•­O§¢KÿÎuø __:óyLõÊ´\Ûyæ\Ðæ–/ †¯:ÈÔ>éç¬íÆR¿ÔuÝ·÷êž{ÿÏxÜû¿óçÿêÿÕÿ»þ[/»þ¯ý·ößÚÿ|“ØÐcS¯ý¿þßúëÿ¯ÿÿ¿ÿ™GôÚâ øä܃›CaìW€H:¦ïpBS>蜎ºÃÊ( R&ýE›]Oð#¨caP‡@&A9²äübJßE^dšm•‹¸ Nå“ÀL›'ß,`Py}öùg1ZÉáÀÝÛ­-ŒZ@¹ß¾;_l<õ=?¾7¥žÈwš‘º*£|­4‘-»¤†¿óOHËû«†"|'Í—eøI#ZàK±€hÊ\<õ5ZmëFß~Ùûúï†IƉ1f|4ÜçÁ ¢ÿ;ÿ34Œ‘ê ÎWÿ¾92iõÿŒ‡]ÿÇfÚõ?ký°ößù”~XûoíÿÚêkÿ¯ÿÇW[ÿoýÿõÿÿûøO,‡ á°ܸœ“(!>Áu‡q~½¼ÜóŠþ=ò‡_»{ ø8)øÂˆ±åòí›óN+ôv#yÌ ­ƒ±ƒg ^ðÂáÈàâ¢=§§œ²‚²xô<'WzÚ=/2¯a‰®ï…úæÍ7²•ƒ¼‚r@+í çÑFéÙ¡6ûÔÿë‘õѧڴӇν÷Jè;ª¤i§ÅLÈî5tSðàQï¤éWuKoŸë<¤‹Óî‰Ã÷ŠÃãÛ÷e—¶÷ÿ8Þ{ÿgܓ׼Ë@œ±#tœ‰gPI˜ñz¯ÿÑ;ÿ~3^è•Õÿךºú?ëݱëÿ±vý_ûž\ûoíÿÀ˜lôµÿ×ÿ[ÿïá³ÖYÿýÿ¬•7üçéOÿïÿó5pããùª]ß„HZ€‰Ñ9ª5Iqb'  E¹¤â„Éë¹/Ý)ðáÐWìZÊ4ã-ãe :>~:J{7@K¼éaªv²xÔNp9‡®ÁµzÅ‘yœj<…ÐN,ß!Ÿ,ïÞž]_vVI³“Iè£Ê®¤Ë¯œÝñ„¶<É›ó)i¤ÔfåJ×òóë5ùv¡}nÍy Rý@ª¯¿þ:u—WÛ£ž>ˆŸ|ôéˉɃ6òLìH£L@7ü÷þç=iúnïÿó\1fwþïü7/Vÿ¯þ>˜±àŸ5e×ÿóãÕ®ÿg7¸~H¸ì çkÿ­ýgýXûÿø kÿ¯ÿg ¬ÿ÷EüÏ1%bKt^¬ÿ–Pá$ëÿŸþøMøÏÓOÿú_¿¶¸ä0ˆâ¬Œ"twôÆ«ÿChäøÊ,¨"î9Ú*CÏà €2 Kõ¥ž!ÌÍëÛ‚ì&Èu”é¿óN—¬$FçÀ32•œZN~ƒzÛ ÐdדvU. ¯@ò‹)y„Ô#¾ÚZùÚÆÖ«öž+çÜ¡ü›·oKoÀ‡¬Up}DP,½÷Dù´ ê«7ß̋蔶IwPnòïu*°¢(Ò†KeÔ¶|[WúòpïÿÞÿÿ;ÿGQ¬þ¸úÿ¬¯–‡®âžïú¿ë?;¢ïãdsø1mí¿µÿè öfì̵ÿuGlpºsíÿõÿø¿ëÿ­ÿOG®ÿ68Ým˧ïÿì'¯‚GòNäê,,Œ áQh+ÇåèxÿQ£‡Ñzñ(Ê;Q€@hÜ ‹Ð›óâãy„q¾Ð€ ½/ùMýΕ  5u“‰¬_¦|dkL¾ ê펪»L= s£µ…{Eò„êãQƒ\};`™ðÉ#„“F.F:yBã…ìSÿ‘ozô áÝÀ Ó—èœ+ãHýÃW»õžêgð…öâ­LäYÈ#0%¸§§s¡ÊÉÐ)6r º½ÿÓï{ÿwþϼ0÷vþÓ G/Óá Gè¬ê)—=/] \š·úÿü(°ú×ÿÎ]ÿ×þ£K×þ;ÎÙÚÿkÿ¯ÿ·þßúÿgÓÎúÿ;þóô½Ÿÿô5ƒ*J-«‰ï†¶¶ȸ1‡Š/“wß<ïfŠssñBÄyQöq õÕW_¸ ³€.èðòh`ÁùÂU[Îñ!'|•ôGþ儆ï-=üx\by猔óN¯ðº´C»¯ó€`#Œò=´Ñášlbõâ›ë‘ëÅÈ*]¹¿üâËì“Fù ©søàí»ÅÐRF'_ å,XR?³«¨²œÊúK&éêl["㤉C7í ¡±“I½vWÙs¿óuÂýáþáGÿù?ÿçþèþ(rvr¨/õxù<çe²›…üÒ3±ª›(ˆ£„+_ß%Ö¶¼9ðh;Sç}yyý´Ñ.1»ÌÄò‚6Ù¦Êá}vc¥½.&¨W»¤Ù•E>¡åW¦½ÿ{ÿ; açÿÙÝhþ;ÿÏî" gõÿêk‡c×ÿ]ÿ×þ[ûoíÿµÿÙIüŒõÿŽï©?Öÿ›Í ãß²ÖÿŸùq½K¼þÖúÿ;þóôƒÙE±D '¡ìãoŒQ;¤â¬ÍËÇÅÀš:³i”ý~À¬ašúÙgŸÍËØÏWñÐÛyUK]u[·A÷#LåO¾‚9êr(—²WÜòh嫜sùm£sm"GÁ+<…ÖÕ6¡þàþ ; ì‚Ò&±Ï\Š`þ|ç2çøà . häÀÒi¾3 RånýÀ<ùßÉD¢Ô+ xÕÇ Ý3åÞ `¨LîÙ%>xËäU–ÖÕ¾‘¿÷ÿ8'údïÿÎs}çÿêÿÕÿ»þïú¿ößÚg‡%2ö÷Úÿkÿ¯5Î Gjý¿ñ¿þÕÍçZÿïö”“±2!úcâõÿφþúúÿg}Ñ¿ ÿyúá/þä5pÁcÍDŒ ç„€Ϫ›€Ê´¬X:±’®=r7Ò}çQÀÌ'(çhÝÙñƒ×ìf*°¤žl±zü…{ýÊVçêw-Dþkq}¯òO¾©ƒ§z•I]—ÒQ¾e𬬠מ£ï»¼Ði¿kùåÛÇô©/â£ô šÖ©ß´ßc;Û6i„Woéb z¬GžþÊn°« m‡:*û=–ŽlÜûÆYûmïÿaõÃÎÿÿwý[bl¬þ??­þßõ×ÿµÿÖþ[ûíÿõÿØH±™ÆäS¬ÿWóá‹Ö÷\ÿÿ`ëÿÿá?Oßû‹¿6±L*Á¹ÇÊ€4UÀIœ›ˆŒ/^ÎK8,éà‡ äJ?²D1€ÉõœÚ” O1`ÿ'Ê •C Œkí«O^åÚyDŸ„KQ´m'±YÏíÂ#ïÙ¤ èËÓ9ÇìÞFyú@º@T€ÑË/ïôÊn+|'¤_®~s§Cúôfâœt¡€Ÿ¶´ÏÕ§ý½+WdR~@«ád ç§Ÿ~p«Û¸ñÆCž{ÜëÖ+oïÿÞÿÿÏ;è¯+•YÝähÛõPNŒ·yL0ò͵B þ‰¥ã jòÕÓ´ÖwÊÜ€±)ƒFß Q¾2JïËç_¾:àšúê—':òJ—_ùìýßû ½{cgçÿÙ}©/vþ¯þ¯¾^ý¿ëÿ®ÿÇžÒÂÚkÿ­ý¿öÿúëÿñ+ï6’'‡Öÿ_ÿîðwÅžþøßþè5ÆŽ Ï[Ü`t˜Äæ¤Zæ?](P”ô¤ H~Aæ•–ƒÇ˜‘€dÊ¡÷ÉLBÛ%0tì^ÂÙÑt¶§ax„žøKw´^éM ³áL¤^Aœ4és¨çÊx´÷$<—ÁÿCPI_I×o¯²óI;È ðú8`•— ‘cª”öxi™¦Ò:ÁGž¡™—ºµ}ÒÈ›—¯‡àôŸ:µ ;×ÚN´ê· »ÜÞ¼}“ûHööº½ÿÓs®‘põîÞÿöGæÉ Pã]0v…¤çìôU硸y¥Ýù?¸ó?úÕÿޝþßõß|˜qPk1Úõí¿µÿÎGŒØßlÛµÿÏ“(]?×þ_ÿoý¿ç§¦êך|:~ߺ~±8iÒç@“0qý“ð\Æš¼þÿÿžþ_v`¹an¬›ÌàTX(ê„Ö¨êÍwÝóã§yÁ{”Æøpdñî|Oú<®3ÿÔ/0äìøxó͛ȃF=­ ȺI/ï\\@›ðú:f˧àüAƒ‹¯fÕ±DÓà\½åW™¥WÎÒz—•D*½>êcXåk§šöŸÅ'm¸ímä8²¤®¹Ö•S]•§“S9ýÒ´òLãóX`dŸw‹½7É1›¼½ÿ§3®þØûͳ³‚1bÜul9oZãÿGÿìü?¿(7Õm«ÿWÿw<ˆÍ‘]ÿÏz#ô¨õzþè¢ckÌõ®ÿkÿ­ýwìµÿ×þ§}½z3׳žÔÿ¢C×ÿ;ïWÖžŠ²¶x·ôúgþ¬ÿoÖœ±ñ[èÿ ùü¨…pv½J\àH+{ ªüj>Õh%"[úâÒ$\i=Ç›‚QÆKÊÄì´o¾þ& ™ÇÜ>¯ú…ÛüùüóÏ3áÂ?´èA]Çø5)Ÿk@R+T þwÀ¨r$Æ'Ç´ÿ¢;×ÏmRoÔm' ªï”¢ ìhô‹€OËj¯~ ˜w9ühäÛuFÞ*”¤¡Ap èòn«I;=}2•k;#û$‹œ·^òZøýª+½2·ï”Ùûß1qî_ï¡xïÿUÆòÎÿÿÆAtΥ댎Õÿ«ÿwýßõ?6ÇY.w¯ýw~ðÑkÿ­ý¿öÿø*óý¿ó$ÑúëÿÏüY8×ÿÔ®qúnüçóB‡_Ç=º°ÉNž!.¸¡Sã°L¡<Þ§_‡ 0E^‡¦×unîŽNéìÒøÎ¼ * üÚ!á†YÎ/,g±Ï#s×ÐxBÕ|C‘¯òMÆKãKS2(𸎇ŒÊ\^Ðú[[ÈQzçèÔ). £LŽo`‡kŽ>éxÈóKªs4úÚî-1šð¾ñQö!땯®öÅŠ,-[9”éQ¹Ô™¾þò”!{½ÿ¾ÖúK9œëǽÿ;ÿ3GgL;ÿWÿ¯þßõŸ.è:kmÝõÿØjÖεÿÖþ«ežkÿ¯ý¿þßúëÿ¯ÿÃc䀌¯ýwÁò,ÆFv3 ¿šm†ÒÆ£8ñuÞ-FÙõ4”2uô™±Cº[ç ï/dSbþg'Öä#<ú€-'Ž™|“ú¼Û È%ä¾¹æ^ÀIgL9²8È È\kƒ+±P:u$›Ì{{þ }:}èj¬Š92büô•óö޽ƣý6Ä¡ýÄ®³›<Îñà W¦|…aèC7qA4² Òµµ×íëÈ“û9÷áªM Kü]“iïÿÞciçÿó3õ;ÿˆ»úõ¿uÂz²ëÿ]¬¹lñ®ÿkÿkÿ^_ÐæGCmÒs=Vñü_ûÿÛÖþ_ÿÏ|Ìçëÿ¿öèŠ¨Šø¯Õ!ëÿƒŽŒ™ßGÿÿéû?ûÉk…æF|]L÷Ô`5™tÚ“°ÒGì<¾'xƶƒ, ן‚6x¦³çk„ùºðIeg={¯,p%õ]äíÑ¿ÊZžÚpÒsLbï•kåÀ˽ñaê˜k»éÐ i»2sìý?îÞÿã°vL7/w îüßùo\ø'¬þ_ýŸµèZW2(æÏ®ÿÇžÚõí¿µÿÆ~Xû?6ÔÚÿëÿ­ÿ7Âúÿñ××ÿ?X»±Xs¡xƹ:Ÿ¾7–N{d^ F;²éq\ë°øÆYq>´þ͉¿¹ˆ8áÔ\|)iç&ª2xö:ü/^D*ø$? ÊÅ7õ#¸B¯÷ÝÜ(²àkTwgá'Hoývo ­s®Ã*kë÷¢uù»ëeíá;|ÐãE†:pÚ/<®/° Þ¥wcvbAú=´]½‰•__ vd%¾®s1Ð9ú¨bù´Íè8y®vèä£Ô?×@¬Ö×ôðqŸæ_Úæ|èöþïý7&JãaçÿÎÿè¦KÑÕ©«ÿWÿÓ]‹j¸SY_F‡ìúo…¾õÇØú¦ë1]›ü]ÿO?\ý±ö_º#ãdí¿µÿ×þ_ÿ¯¾#ÍÐ5×ùúXÿÿ·ßÿúþ/~úÚ Žɸœ£Æ¤¸Fhâ¦ÎÙ…y޹ô¥•åQ¾^{Þ]ˆ†÷œ›X5^k˜qrCÕ“ï`¬É'~ÎÎåÛs×=+€jº4GùÝu¥þyT°NYœ ÷>(/<„>:  ïᥠٱ5õ+‹÷=´=zC^e­lâ†tõuº9ëc¡rH{ÿ˜>+“‰ïy(×d&«àzþ<îgÓîm'oÂÞÿG¿ïýwÆÊÎÿÿ«ÿWÿg}±öíú¿ëÿ ±SØ(s¾öß±gõÆÚÇŽŽý½öæIlñciW‹m>áØìÇÞZûÿô ½rﯞ§¯fýYÿï $ýÑcý¿ƒ#¬ÿÿÛïÿ?ýàç?}}Œ 2x”º+„ClÑò4%é,DxÅ‘½4á?4åU`È¢uÏS.»Mì—ØÇ ãU|…òßæ‹$<‘ï’cˆõ£QVý¬ÈQÐɹôLt2Íèén.J1@ÕM€—~Qo¼u(/$eò*ò®²ú3mŸ˜ uË·eRÇÅÇ{ºsmW÷wi ¶¹nþÁ¦öþwìîýž_ÆÈc¬œ3 'mçÿé§ÿ«ÿWÿ[wý§+wý?ú }1c⾆X[…µÿžmRóƱöß±·×þ_ûý¿õÿ²PÜþÔßÉúÿÓ7¿/þÿ“¯Z8Ýõ]$÷AÑó‚%¹€(+ØÜUéñ.?‹’òu¼/% À p3G¯•W¶€ÂpÏyy‰ååÅãÃTÙ€ä™Ð|ÿÅ0¸í¦R®|ZFùÊÚü8¥Ãë|5å<µ{úÍU>è4uDøGÎÉWJ½ŽôÅÄòð)?q¸O^A²{ÊÐ_ùê»ó•W~ʕӚo‹±@–ä ã½ÿg¬îý?ã;äƒ?kIž±3ƒ'vçÿó»åvþ?º¥ºvõÿê#c×ÿ]ÿ­±kÿ­ýg8ØÕ±­¯kö…µC^lÖ¹vÞµDìzíÿµÿ9@ÆN}9c§ãcý¿kþ°Ó'd.ÍùúÇFí˜1~j«VÏ<|ûÙEnÈ%_yåòº÷a5Ëž~öþïý€})câ>†îçÉ›?h\ÏõÎÿ£×:wwþ>šqA÷ÐyÕ{Õ“«ÿ©íÑ«ÿkVÇÈ®ÿG»îúÿ>ÀSÝÚØZ´ößÚÆ}::U`³Ð'kÿ¿?‡Öþ_ÿ/¾èúÑëÿÿvûÿóÜgt”þüÏÀ¾€é u`Å=äY0 Lò_Ÿ„a‘w, 0 ÜÒÇáê¼¼øøÅ@o“?ŒCÓ…?òÜãÊ9Õ=ÿ¾«—Ž<§ ³óiÒ[tFqy“Åî(é¹~I %ÍKîý¼mÛÜz*Z­õØeƒ4õ†Ï€avoe+¬çû'OݧÌUÿ…ê–'>÷zNo^ܯú0ÁëZ^zúàŠõQiÕ-4?òL¿ïý‘±±÷À¨ÿ;ÿÿÝR=x×5«ÿWÿÏ‚’ue×ÿ³.ïú€¥µÿÖþcc®ý??²¯ý¿þßÌ…õÿŽÌ`Xÿtãúÿ/üçé{ñã×@œÀNiw§Å9Ú»ƒ= ¤˹>€zÀ•­vÎC5€R€”Oðcô‰å9ä)c‡ïÖ_hÕ9ô4zÁB©œC?Ê·¿ðÞóì¸R.Ÿ1]<ò*Úsíëy*»êk½¯^½:üHC$Sïy[7™œ·œz݃\O¹s2íÈ#šsu剕ëÆCøþß´÷ª³/GA29ð7ìý·“pïÇCÇiãŽùwæÍÎÿ£oô‹¾Úù¿ú?ëÉêÿ]ÿg}Ýõí¿µÿÖþã vSí©µÿ×ÿ3j7òëÖÿ[ÿ?ã¡~ùŒõÿ3þóô/ÀÒYy”!ލ_ÏÎc}Üï>=?ÞÆ —Vå«Üwçúí€<}Jƒ6ïšÇ$ð”kâ>b˜]Rè¯O¡udwÔ¸ÇJå6ò x9¯¼&¾t×êF«Lƒ:Ò¦+MYùåáüé»×W‡Öµ2BËŠÑ;í³‹ìž¦9^ ð%]€!^Bù¡o_Kwí{ùâe•”l P«aïÿ_{ÿwþgÎ]óι ¦;Ä÷¹¾óõÿêÿ]ÿï:a×ÿµÿÖþ[ûíÿõÿÖÿ›yýÿõÿÿ‘ðŸ¼ÄSöx îf l|;À°ãã9<.ÒT€+†š4ŽÝhšküä‰ß¾9r]7Y,òÊNF¯æ‰•w@õµ4>5ïçhÁJè䓵r´î– ÿç«<òzMºk‡kéÆÔÔ³#L}üôqÚF¢Ô[ÚiÇ7_\€¬—/_DÐÊFúfê©|+whn²ÛMÿL™÷Ú04ʶÝbí §?ÿÚ¦:å{ÿ÷þgxO·°óçÿêÿÕÿ»þŸƨÆ]ÿǾ[û/«äÚkÿ¯ý¿þ?jý¿Ûf’ñ;ùšëÿcýÿ)`W€EüCà?OßÿùO_Ô¸(ë©ìþÞª€W3094h fÝ…rî=:àJã)Ê`A+½Až Ìr£•£ÑÊ:J›ó§×â‚7ν@½ihKW>Ÿ;òs>ˆñÇó~®¦£ðe¼Ô€Fvµ.7C(ÿ{»¤»¦äÄø6¿mi¹ÊõaÞ7þ®åü"§>  ÀVÞòÈ Ÿ¬‡ŒòÉSn <ÊTž½ÿg¼êC}µ÷çÿÎÿÕÿ«ÿwýßõÿ¼ÂÚ(°k„µÿÞ·kõ Ûaí¿c‹×îl¿ˆ…Úœkÿ;\?õHÿÜúȵ°öÿs?´?î>ÍúÇ7\ÿïà sÍ­õÿ»ýÿè†Ô¤ÝózŽ NìK%*tN1ù½ûÊ;°*߇u ó‘€—²Ž&À_ø\më#~òßÌn(¼ñý8‰ù›ô{ßßùP‘«õy|ÒýkŒCëo_µ*gëOÛF&Ò(ïzïÿÞãÊßÇ ´ÿGÇìü_ý¿ú×km×Õ®Ç~øéúKgîú¿öŸqb|¬ý÷ëóä…™ô²5b—®ýŸ~ÑwÛËØ©~™Œäõºvc ªÖþþZŸ:ôÍú×Ü›qµþßúÿ¿þÿÓÿ۽΢1“šRì該¤üjLºóLþk·QŒ´)cð3Кúa…‡sÊB9Dñµ" <çò[gÎçZœGø¦Z¼¤ âÖ'&DåœÌÐhÍÇPVeÞò"ÛÈòîí¼(~èVɦž m—üʪlep¡ÁWÊ“²‹?:NN¾–èÑÄy$³¼•©<•ýô^‹[gË@$6÷=dÓ] å™þ™qû|GøMù¹H¹½ÿ{ÿ;ÖŒ™û82VòUMãiÆvße×y"?ô;ÿÓ;ÿWÿ¯þßõ×ÿµÿìÞ^ûoíÿµÿ×ÿ«O\_®6¶ë{Z¯ÅµÉ›¿þßÁ#âß®ÿÿ{éÿ?}ïg?y µè¤èy'Žk¡ù™h3™€ÎM¢N¬Cɱ§wþ™¤A·Æ™ ¿\\TxLPVïÜcnyç¾³à{7“E?ÀÐEw£R&ò„M@†Œ mOÛ!]Y 6|ûí¼»jè=©œwUù5#4síß= …àKO]2#Ç¡SOÿ¶ múfÊòÓx¥/•Ÿð¡ŒI¼ý‘_špšòJ¶’[xño¿´>ùåÓ¸i÷:š&V¶íŒÌîÓuÈöþŸ~Ýû¿ó¿ó:zdçÿQþ^º®zоq¾úÿY'ë¦öó†»n^ýÏF°ÖŸÞ¡s»ÎYÇÚg¡½3'wýOoÜûå7õUówý?ƒG?¬ý·öÿÚÿkÿ¯ÿwÆ@×ÚõÿÖÿ£ÿ)ðŸ§Ì;° ¼FŒ1€@'ai C/(ç$<LM`ÔÄt1´x¸–Bû¸¾òiÊ_õÔ`¦†’s<<ÊG†Ô;<> M/Mdš6Î=¶Í5Ye„ÖûíQ àÐ_íü„f5ÿ¾ëEòïeäák§Õ» ü’¯\údòÒÀ7Aº_aõ#Ã{.í½ôCzÈ&?Û„ÑhÇ\W&ez®o«,IO;Î/`^Â:•<ú$e§­{ÿÏxßû?ƒgÆÇÎÿÿtÈêÿÕÿ ¬··õ3ë‹ ëѵžd Ûõ×ÿ'ÆGÆÃ56ŒŸ¤ÍYûoí?ª£6kÏÅÂÚÿ§bÈ_§ÓYkÿ·/&^ÿoý?vÇúÿ7¨.ý}ñÿŸ~ø‹?ymÀ€žÆà $&#OIÔðpÍ™A/­Æ‰4†‰`0É·›É¹àMø\å,'´ËªeËðô(‹n®å©¯uµî{ÙÖ%~¤_ò+ŸcòÔ­|l›”” ˆ šëÖU9ä ÂÓµA,OP' HèK¢ÏÕù‹'â[ßé-wYÂç®úÕÄ)œöÉ«“ÑA ÆÛD!êÜ;´NL¡«îôÑU_ÛEf2x9ô©ÝVúµõ¯òØâUWËwr’¡üÅdV¾¹žÌÑ4t•_Ø™| í¼«më@“ .'{ÿý·÷çÿÎÿÑÁ—Žï| ßœ¯þ?à ]JV¯þßõ×ÿµÿ˜Skÿ=ÿk-uTO²¡×þ??Ä[OÛ/µÍ×þ_ÿÏXèaŒ¬ÿÇõ^ÿߺ’ñ0vçúÿÿyúÑ_þék‹nA Å. óûB“¼¡—g’ÉwØé¬q¸V^'£“&_šÀ9R¶u—ùŠ!ˆv%ZO®/á3>Ÿ'·rÒR~Ø9òÕYß @'½4«Ç£•y¿×Ù·?‘SÛ¯þ#‹CgÈs¤ÏGž.€·â©[Ÿ¤Ü-ƒ\äy”>½Ÿí´;uòí?lД]åˆ,{ÿÓÓúdïÿÎÿÿ«ÿWÿïú¿ëÿÚkÿ­ýÏ8\ûŸ7·þé¼ßyý?ãaý½ðøü‡õÿ§¦[Š3¤O`WøÕ`Kš_‘z'$\©`ß·„™¼$Ècï\RnrS89y„®ï  u’S…Þúîñ£øÔ`…Ðdk]©ò(?lÙÈFæ+<®É¥£ 3`Œàzþœzæø€¶4Îû˜¡´¯¿þ: £„"úä“OP+HDViBë Ðs`YÌ®¾ªlhÝ-øu¾Ôx€ªäüŸŠ¼‚k€Òè¯Ô“54êl;ÊmÒ§DÞ/0u¥ý)µ÷_7ìý¿ÆŽÎ˜ñ1$ÇÎÿón»ÿ«ÿéîÕÿGOPtDÖá]ÿ³~­¬Ç»þÓ>¯PXûïØ—kÿñN`w®ý?ö•ÿì¬+¬ýχ¼Âô Ÿ%6(_E²µ&Ñúëÿñ_×ÿ7_ªWϹ|¸kþT¿ü.úÿO?˜w`ÝAŒG̉Ž:µä Wb´žŽÊDšë_ Ý!žAv袜)ëK ¹.ö¡ Š Ò³]î*SY¤©ObA^ó•Ký“Þ›{\¯Ã³2yŒÑc‚}WLjQcC< P½zõê=+@”v\ò ó˜ h…ÈrÑÄù™|t ݹ!¼h§ÂG[žò}^%N.¼Ñ§=úáªÇµ6´o’?io§}^Zÿa^ë‡vbý·÷ïç”±!ìü±wþWï7^ý¿úÿ¬¸Y»6Yæ<ºdÎQìú¿ëÿÚçGÎ,¬ó‡íņ3Okÿ­ýoH¼ÿãõÚÿëÿQëÿ­ÿÖ‹øì¿‡þÿÇY$lÑ]4-¦€ïÌy|ÅÑI“N¸fy pÌДKªŒNèæôPžGìúKKòåá3´áwód%¤Ý¿ay½s^ÞçôÔp «3™›þÈçÐ&†²ö]€”ÀUë´@üz |g@Ÿ–WÆ×‡ƒÓ€?vc}þùç±P® xá™Gì¦>ÀH~¶Œ£4òg´Êh«]/‘oú[Ðm  71°M›tΦ·×0tKãüW#¯ëÜß)s—1ýsñÛûŸnÝû?cиÈ8œñ"ìüßù¿úÿëü±úÿù‡¢QY·h‰£)výßõÿÝc§MƇ±a™±²ößÚkÿ³¨žƒ¹±öÿóšr÷IFq<Ö•èé¶õÿÖÿ3{Œáî§°A¤¯ÿúæwÑÿúÞ¼Ä= ‹›ÿÝcvÖaÍ€0ä]±4áN“kTé§ÓYwš‚%s º‡¢Îê/MËMóÿy‘ú7÷òw:pï1^º6 ç'5uºâ(gg  °T>/¤2òï¢ûæ›o>úô³Ï·eµZ…Ï€S}Ä<}Ý1 ÕÔñrvfyá}œþ©#ÂF:|2à¦Î2Léùéé‰ á1Ÿ/wÝCZƒ¾#CîóÚiÛÞÿ½ÿÆÈÎÿÿÆQR½ßX¾p§É5mUó¬oJSݾú~´XýÿX›Œ«æ®ÿ»þWGT·Œ‚™ÿkÿ±/Öþ[û”çÚÿ—SûÂü¨¿só†t0Êœp~Äw]ný?ô¾mW»¯ñé»÷iRfí¿õÿÿØÿOßÿÙO^›ô&rˆ~%¯iŒ 4À¡ôUÊhÎõósîÊ{Ù1FŽâ@+½|º4 ÷?SŸ9^¨,ê—×=B*½Ø5°Æ‹ŒÔµGæëWaòñÓ¼h}Ê(›ºÕFFôBû諯¾úèÓO?Í5ú‚^Ç(iú =0«õà‡¾uˆm¹ò&3 ¤·¾Sþô%Ð) Ú´‹lò”¯i[ê˜kq  É¯ œK_œ*:å'n]íü¤•fïÿÞ3ãí7W3FvþÐ{çÿêsD /WÿŸõÃZ"èžÓ»þïú#£ãögÆÆÚkÿulÔ¥3„ÆÕ%÷´µÿ3uÖþ¿ÖšõÿÖÿ[ÿÖ’ßAÿÿñ, ]AÑ.÷Å¡†gVÆyòg=9 œã3¥Éâs'å%M~¯[FYx&þðYy¡Ÿrh¢†â¡Lc<òòÅÃI|\x£ÒÏú÷x±¨vxôÀ&õ “ïH½·>@GÆòžÐ’ Äôñ€_ÒìÀúdvdyq»GõAeS®Ùß};<LRÎ5 NüÓ–2£½Ë0Vô¤¡S¶ùè7ÍyÛ).=á]§Ü$ªqïÿ(¿½ÿgììüÏ\Ùù=^»ú?ºrõÿùq§ëë®ÿ»þ×¾Zûoí?‹æÚÿkÿ¯ÿ·þ_|ÚñG}‰Ö9›A¼þÿúÿl¾U1‰bWüçéGÿî_¾zx߀;ß¾;ïoò«ªI‚|;ŠºS Hcz™yÓcpŒRjÜØùÃøÇ§<ÑÈ/PÕFˆß]/:· éÝÛù‚Gjò幟/œÏã~W¹ÈrÑé¨ÒOÒ³¬sÞNìsÝ´îò Ð3ò¢Éã‚@#“qÀ*ýA¾¯¯ÝWú…|ʦNN°K ßö‰4ü>”«u5=׈§~mËsîEô í±C91:uª;ý§À°ñ‚úôøíýßû¿óß|Ùù?<Ï¿ÕÿG‡Ûå[¼úÿ×Yïvýßõí¿µÿÖþ_ûŸ/²þßúlçøÜ—Êfª¯»þÿúÿÿøÏÓÿ›¾¦€x·=}LQ>ä'»2í3å¤+ œB‡þþàë³È9‹7cN¹7ß¼ åÚN2¸V7q+ ^G¦ypÚ€^;;€ïåÑ ÊÅäyOyK—ò“> mË£ìäáEv2íýßû¿óçÿêÿÕÿÖ–®[]Sº^îú¿ël±:NzÛfl‰µÿÖþ[ûí¾FýçÂýºkËúëÿëÿ¯ÿoÜñŸ§þç?xÍÀ088'ÂL—¤Œ±!OxûnÞñôꓜS2”Êw‡¾ ÃÕ.#ôï.@Ï-UF€XÐ8ºç9ïÚ© i¿1 ¡Ê¥…úǹôæiÐ*²Ìã CÀN‘.×K¤W*ˆëÒßAiÞk%î6B´[L‘ùâïeçݽ”]QÊÏ Ó¡äé,åÔcSML‡ªkŽæ×HUNdnŒž\õ‰Çó®‹o¸à^i×}¿÷ÿÌýŽáŽ÷ÿ;ÿé¤Õÿg=\ý¿ëÿ®ÿkÿчkÿ'1î6,ûÁ Û×þ_ûý¿ãÓ­ÿ·þ?ŒeýÿãcþSà?Ùcüz<Ä"ðD|E®9²vëØ8)§hD€ï}òµtå‰/G( ã~Îu!1¾‚²ø ɿʓώ'ùø¥ÌðH}¯æXXŸ²ë©u–§kò’?íK-§N<‹ò÷§¯È@&}äüØÓëÿL$Ä?ÿyúwÿé'o9AìQ> ÈÑ_GÞÀÒ÷3…vú¾NÍ‹yô/ à®oºÝ>á7±47ÏõýH¥×ü¿úòËE½Ñ&GË–¾@Óùšßáow•®@Mw[yi¹GóúòòÊ€lv;};»¡¾þúëÈkWTÂ4j~/ú`×XÛ8„‘­õ„þÖw€2hÔ÷ÇÈ `4y÷P©ýŒ^½q †ÐbˆF~iI¸AZûß‘Úø©3˜¤Ü¡üÕ§òðÒ{ÿ÷þ߯0puçÿÎÿÕÿÏ»Vÿ?¯ó»þŸÝË]ŸÙµvý?ïñ\ûoí¿ÚðµWksÆðœ?kÿ¿‹=¾öÿñ©Œ‹õÿÖÿ[ÿýÿ®]+Šÿ<ýô¿üû7ã°ò¼{ûnv}úÉgó( G8³}ï¦Îï ‹|Ž1Çx+o° ´Qz+—ä±GhtvKYàÐ å‰?° =Pÿ4wÞÒ?½À5ç@!/ ÍJÊ÷9dm‹¼—åÕŽ³kì^~òB€³«-Ú9ÄúöA¯?äoÛɃOë´Mîõëφtå[×y<ñ<‰UËE6}qч÷´·é~%í9‡ûûéÓéÃæõWƒ½ÿÏ_3÷þïüϹMâÎII;ÿ>]ýtë(Û£oÛy‡Ïêÿ³†u ïúÖœ]ÿ×þ[ûo~d^û?ö½õ£¶ÆÚÿëÿùq¤aý¿õÿáõßùõÎWüÿ§þéÏߘ,trØP};òw>ô§²èR°x Æ„O~®ð¡ÃM§;,R’®› Ž^ò[·s<[÷·o¿ÙÎc~øzÄÔzºš‚DswÞÈh¹á¹Ùg¡6ÁyÅœ“Ç9U,҅ƹp=ÿIŸr¨œŸãCþø–WÛ¦Àaû߀oS§U½WÒõÅwÞç%aΧ¢Sw.Irú=í™üÞƒÊH®òÜûÿáýÑ¥úgïÿÎÿÿ«ÿWÿïúoMèšÝõAܰëÿÚµ­ØckÿÍÌ.PÛsíÿ!lñ9ªKÖþ?¯(`o¯ÿ·þßúÿçqôæúÿŸFOVGÒ›ðŸg+»€Î#x~ b:_S•ìaÎ{›0ð^);¢îééðáÑ/ð è,fÒÊj:€ %¦nA9´³‚hÒ8•d³ úåRÞ‹¹¤cÔŠoAÍEøáåýR퓯œƒ,Òu~m›Bx5P+Ó»:OËÒÆ_Oÿåü*™F.ô-Ós±vh·¸íRŸó{ÿµ=y'_PNP¯@v?TÒçìjëÅËáQÌÈ«þ½ÿ{ÿÇÿ;ÿGoÐ3tKu…˜NZýÖ¯êòÕÿg\X{¬ÇõÏ}ýšÅï±Z£vý?ý±ëÿ³]´öß±kÍ¡µÿ˜­kÿ ]ƒéÔµÿ×ÿ‹¿ºþßúÿ£~'ýÿŸÍ#„áhÆ9Î/$Ýã×f/c×1h(Ï£Èâ\c•!ZûtÑÈ·;„¶-›üá:÷y¼+jhKSyZ?^•§ï²Bëz™Ô/ÿêë¯>yÿî}@ð“¶”®/iÆ?mœÇ ñ–øÑ¦ò£Aë|þäÅ¥5¾•“ïëŠÊ‘õÙh¿¾~8íô‚v¡¼ 0‘­¡}¬&©Sڽ£õâç~E6ˆÕäáIǯ~5;ÛF¶Êù.¾{ÿ÷þïü·óÿèŒÑ ÂêÿÕÿ»þ»b×ÿµÿj³­ýwì%ýÀŽ\ûÿÙ_ûvO­ÿ·þߨñ‡×ÿŸ±°þ1;†aípxE\‚óñ÷ÅžþíÿøM¼ Ðã:¤õÜn$4ºÒ+ÐI;‚ 'H€—T„Ò)o@ vûXºL¬ìò“>/Tùâ<.$—êP§Ø©¼}ø–·tA§¼z_'Œ\ê™ôœ¯Ö‰6m¸:“œ¡›tu¢S(•ú. ÉÎ3r¸Ãƒ Ú,Š—,ÃäÚá4œµuêÀÛ!‰sšºÚ)ú¯2¨£ý)-_($ì„{üÊS ¹æþiCƒüÒz¾÷ïÿÎÿÿÑ“—^¨:i«ÿWÿß~ܲÆíúŸ56këôÇÙá¼ë¿þXûoí¿ØŸ£#ؘµÅÅÂÚÿµÞ×þ矬ÿwÖÖõÿÖÿ¯Ý½þÿ…ÿüø—¿xS % Í.Ÿyv5À íe ÞßRW~Õ/àÃ.(AÇÇpxH¾… moH¯» ‰MØ×óòx‡piê¦ÐÜ@4÷s `Éâèeä¥ÉÂ8i“¶¹v¨? “øBIÕƒGåÂß¹ºÅ½ )/Ý/á5ç/F†Ò¢Ç¿uI!;iÚv‘ñžðÑyä¹:V]5=îS®µï _ç~N¾ûu^Ò~îÚ£u{ÿÀº÷ÿôƒ1alìüßù¿úõ¿p²V\ëè®ÿ»þÇn{†mæ1>j‰¬ý·ößÚÿkÿÓü—õÿÖÿó˜—õ¡þ~üÚÛõúÿfËß ëÿÿfüçéGów€pÇöWÁ êó•>/tçÄö¥j:S~ŸÓØ9ƒ†Ó£Lu¨«¼ï±²E˜¥7/FóÓš,¶˜dä¶ðf(¥ìœ‹å¡qô]ùCô_›µý¤²¥;×fri‹k½ãˆåúqLºÇô T0š´”›z…TÀ‘öG¿€Ø = “[tg÷Ôˆ{ñ(oùG|”•p •­IºKnu¹èz¾÷__ìýïØ1þvþïü_ý¿ú×ÿ]ÿ×þ[ûýÉf#ˆñÚÿkÿw¬ÿw~^ÿoýÿþÈ·þÿ,ÿ øÏÓÿägotòÝi ¨‘ú ¥çQ3NLß 8N¹)&ô&« ã+ xäÚ¢w ±Éw®!hçx? Ñ@g“vÊJ/ÀS^[†!íhÑí\«ßáš"u”æì:‚ÓÌ¢;/h—78Źžó(šÉK;ÞŸGkÛgŸ}–úIÊÚÓã{ó¨£:+kÛÝ6 w޾iêOéÝ#‡r=ðr޾eõ•÷ŠÉ»ï:ÿAÐëÖ[y7×Ѓ\{ÿƒª¿¾Ûûÿ7‡;ÿwþÏ«ÿWÿïúŸeõ±öŸµs×ÿ¬›kÿÅVÓìÞÚ\FLm¸¦­ýwìS×þ_ûý¿gßþXÿïyÓGtæ(Šú´ëÿ¯ÿo,Ûyúé¼ÄÝ ‘è_CÏ=fök&¨¼ú`kðU]šsƒÍ‹Ò¥©Ãä|Ð ÖNýSÏÔÕëNdyߟX®ûu@BA(`ÎÛwoê´àz”qž¥kß­S=øÙu„FÙ)ðO•Oý“g¡˜‰ûKde%™'&›pvXA3שû’Gù ¹V·€ÎÑÐ6É ÿ¶ã¢Wõ)ý\¾õµÊ¿ûyÛ—´½ÿ{ÿ¯·óç¿¡°úÿüˆ°úÖÓ»þïú¿öß«Ø ô#ûií¿cS>l{ëÆÚÿkÿ¯ÿŸmý¿õÿëÄõÿaµ8˜Ä? ÿyúѼKçêÐ.@núKQtkÀLŒV¹‚+„ŽP¿þäóÏ?8Sþv,áá}Á9þÊ Ê•‡ëðž†̾ýæÛ\PÊãsóï*Ǩzñr¾„8h¹zpÄKg•6̬Ϯ‚k@ÅaŸô¾ßÉÚ¦¶/Àª-Swû?¼û(aòOâ£}}°ƒX»CBèó?²áÓCÝè"÷·½âÊå¼é­ßœã•JN›sêÏ„òãåpŽ—{ ^²Š›§]Ú¼÷ÆïÞÿŒ•ŽCc§sWìzçÿÙé˜ù:ý!ìü_ýo¬þßõß88¶GL€]ÿ×þ˺iítX[×þ[ûßXjçÇž˜±!î!íÿõÿŒaý¿ót×úÿ3.ýa\ ¨Né:SŸ>ùmñÿŸ¼Ä½ ° jC²x`ZBÓ¼@[gUzt4@U‚rCÛ:¤yÇ”²¿èÞ;P¾zñŸ)ïÚcnR”« è+‹È$§uLå§rÉ$ãÐá'ÙÔáxyí¼r—5x´M@2夡õÂv±YPöœOž6á‹?ÚSåérUFò¶ß.¢ÔUz1žèðBÛòm³÷‚éÏ;meî;Ã|ÆóûCãDJM¤ “Þû"ÆóÎGÝ=ôòÚ÷m›ô¶£}µ÷ïÆ‹qcÌMÜ1´óÿè¨ÿ«ÿ«7;W:G¯þßõ×ÿµÿÖþ[ûíÿg«>ˆu³¾¸¾•¾âŸÄG¹|_3×ëÿñ×ÿ[ÿÿ7„Úœ¿ þ^âNP¡ ¨¢lš›,­Ê}±“'X`i CZU¤(Z^ÞÛo߆@Tåƒgvi€“8¾@—È7`ÏìÚ"Gøt驘b"_äÞ}_ÙÜ Ž“”¡È††<ï¿;€”siên¬ øåzxüêz¡=“¯€Zã/—'-Asè<*·¼¶Ñ£)}•ttÊ´'!ms-¨Ó¹Ò©C úH–û4(oý3ìNM¾ÇƒÔ‡§€Ÿ°÷ÿŒƒ½ÿ×8Ýù²óÿoÕ{ÕitÆêÿçucõÿ®ÿæ„Åv×ÿµÿÖþ;þ[uíÿcc¯ý¿þwý¿ãò)Ù“BçÆœÄ7>þéúÿúF_¬ÿžHÓO¿?/q×1N`Í(Yÿgõñä7œAuh¤•ÚÒØ2ò¤Ìõþ(ý 4sè[¾e~§Ž#ƒt:»ˆJÔ2ì è i¾òå—©qæGÒì:Àу¼ pÓ:ħ‚BІ4xþú"b¤kG€ˆ±ò½FNçä(¨¤$>¥w@ÊNgç•/#Îui䥾ë>TVéÊ4F/ÏW½p__Ù‡nx¦ïF~ÐXËÉ·“,éíið‘÷îýá`L£^ï¼ô­öÝeÅ#÷3à{y¦Ò„xþ´þ¤ã1üP‘m®Õ­-{ÿÏØÐ{ÿg´ìüßùéœè¥ÕÿÑ Õù«ÿwýïX0?vý?v”¾h0GƸ8¶ÆÚkÿŶZûíÿõÿèÉõÿx³^Ìÿ»Ï_õZ7º†¬ÿÿ/ÛÿÏ;°®1ÜxG€Ž902q ½‰äÈ/Y—‘Ñ_4&;à^G«"׌8(ÕºZw⋇¼èûëkÎG´pÉ@"'ù<+M.ç7ôØ\äVïÎË?40s—‰iõ닟~P£ ¤íì’\{¿:]K—fgVò§.ux_–r퇴_m_r¡UŸÝj¯_½N3µß¯Îò^¾:/ÒÇÇû¸î}‘ó¡‘>SZZÚå<×ãLàš?IÍÞÿÇäÞÿ ט4žcʱóç¿_1é–Õÿ«ÿ3²”œuÌúãØõìƒKgîú¿ößÚkÿÓ‹ÆAÖÎký\ûÿ²%®5¤¾™X¨ÍùØ¢ñs’3.»tý?æz:cý¿õÿÿEûÿO?œG«@gÔgÇeÁ9r½‡< ;s€@U(PÐ!Žƒå›ËsMAw‡z/77ŠG:þꜩv€•Ûù$=§IŸ#Nóå@Ë8Ѓ7;NöUx|RÇÑ\{§ÚÛ~åRÇä¥M¥—á™ü‹F»Ñ©¼GK[Ð⥮û¢A;Ͼ›>c¸ Œù€[úí x©Sùçê|ÀJ;ð×åÛúXx7ùÐfé/ggZýœ¶Ÿò%Wû=÷t®å%bi©gdA§Ï„½ÿ×n½ÿ;ÿ3WwþG1PaúctÇêÿÕÿV¯¬eÖ’]ÿ°ëlеÿÖþ«]ZûÕº±öÿ¥3×þŒ¶…±RßDßlìï]ëL~@½Ðó—-¿þßùâßM§¬ÿw|]fëúÿÏORý¶úÿy‰»‰/ÄðÌÙ9w_ W—2±ðL¹+ ´Q2øDÉœ],}®<ù®"Ÿ¾˜Gçæ¹cêQvè„ʃþqøªád£•O®GÞÐÍE@;£¤—?ׂ²t]òÑ ‡”ÃCÉ%n=蚇×÷Ÿ¦ìÈ€Ž\òÃò”)=£íý»Ÿ†oÛ©ñÊî°‰u9ý0§ ½8ùCß{@ÞöGëCãÅù‚/*¶N×Ωõ¹?¥5¯ç®ÉàòjëVŸ£r£Õ&Ü÷þïý76;>:6:vþïü_ý¿ú×ÿÙ>zRè:ê|×ÿ{ÐGÕµÿŽZlí¿gÿ@_°™×þ_ûŸ¾`{ò]¢O/ÿfÔHòѬÿŸO_ 韜s×ëÿœA7ñÁ§ÖÿÿßÃÿÏ#„n Å_G³@ã†åÅß“?ËŃüë‰ðH˜A_>MËŸt»Ž>YhæeâQ0¥ŸÂ÷rêUÎÁÐõhžPªJ*pø m¾JãOêéšáC;™RV?õ”ï§è€U>´“™†¯kçèÅá=õ*äk3ƒXøöÛo1ɳ̄ÔsxÉW> ʹ7ÁäM¾á5u¡×Ö¶»2¡‘†®rã‰w®'¾FUå!öþïýÏ8òâÿù·óÿÙ±¢:×vþ½¥qÓEÕcb[ÿWÿ¯þ7WvýßõŸMÉv£ãØ£ïvfø b²õð®&€škü5ܲh(pÊ´|˜ kõŠSnèãõpR†'9ôCäs2V^±zó¢ÒeÏ¿J¨'}7e´'m"Î%¿«lét²-öCÐ)¼ç1J½¯Nõ+Û{¢\E2 yMCï«…•íý|¡‘²†é¤ïýßû?૱`lîüßùO_­þ_ý¿ëÿùAÈã;»þ¯ý·ößÚÿkÿ¯ÿg-XÿïÕ|M>çúÿëÿjì¡?BÊ?þóóÿúGoÔ$é-Òú$ÎŒkˆÕÝOœÞ&œß“{ 衵àwÇ“Æá‘Á>y&eRÏÄÞuÐëIwNÿ~v[œd¤“huäÅW’ £þ:ç•_<‚ä…çáugrñ—N¦özi¡Ÿsí(øä¥Äè(5ùbu:ÙѦM:/m›óäMŒ¯,ŒS·óö“4NįÐJÿO¾_-Úwò¢8¦Ì0L+üÚ¥Ý/_ È8à•~P—ò(”÷UD_GìËQ“7²ôÚÒïýßûolìüÝ7óʼp8ßùpý Ðk«ÿWÿ Æ„y²ëÿ®ÿkÿ­ýgmXûí¶d׆ú0ÒŒõÿŽ/«ÚOëÿ­ÿ¿þÿߎÿ<ýÛ?þñ@•B1q„8#uÔæ:é3±#@#àŒÉ|ù L†kÒÐPÊâ5TÁXN^Áî"Š4ùÊ© è"ÍñÝìÊŽ$]2yQÚ½~e ¸Tð&N礥±cêà\Yü3ò´M²ðèuÿüóðt.íÕëש,²ìÚ‚P ¸ÔJ¿ì]üµA=ø;† ¾äÖ÷dȶÃKžî>sT/.0 õWn_)tÞ~ÞûÆéÞÿÿ™hýÙù¿ú¿úÞШ¥SWÿïúo<ìú)ͱ=:W̵ÿÖþ‹íÅÉ|_ûíÿóã½±°þßÑ›ëÿG¾þC|ó±)ÄëÿÿñŸ§ýòçoÞ½}`ÄBÈÒi”‹”6'9â½€À‘¼:wgûàY Ê â<ÿ><ÂsFé¯f÷Ï#˜£Ž x©37pÎï×¥‘ÐÇxŸs4 ®;w˜U¾ò“£`YД÷Þø¹dr­)Ê¡‡>Ò¥W¯^E„Ç.•‘ pöÙgŸMkÏ ÿáÓº"ž³ËŒ¼dOÿhß ”3üÔ­¼z»[N¾t ^ú¿a˜{©,¾‰¯>!›@iÒöþïýï8Úù¿óõÿѯtäêÿ]ÿ-Ÿ»þ[‹­ÁVYûoí¿Ú£±e‹Ñ—9¿búÓõÚÿçGkNÇÚÿëÿ™'37Öÿ[ÿýÿ8þóôïþÓOÞXh,F †_»{0ÂË ¤éKÂÍD/œÇØ<¢v€JÞI5±s¼»àLàÖyoð“Ç@ä h…ÒZ Ô…ï9I¾_üPiË9Ê=”Åœßù”W^l>å”QoçóX ÝY‚_ SÏ©é,Fø‘ùýwGî*'éá?Ô”¦pú`#òy|oÎíˆ*›s4Ê;Êð„ÆuëmÛrϦLÞo54€ˆ†‚h”¥~ʽ›ÌNtø¥ÏF–½ÿÞ¶÷çÿÎÿÕÿ«ÿ­»þïúo¬ý·ö[qíÿµÿùëÿ­ÿg]Xÿýÿ_Fbu b3¸Åÿ üçéÇþo Ò,¹Í㸘@ƒ# 4ìT™ $Ê"6»z¤’É)5_þKÂ\§ìäQ@»¢¤Ý¼ðði¨’t]Ú>RX ëÝìD"ÐÝIh"ßð+OÛWy™¹2s SF})ëőգ{ê uñ!Ûà&€G~i>ß ˜¥OÕç@—²ÊD::¿·íã¶ë‰>Ö‰|¼„Ä“V¾@Nýãh»ðG£, XöjÀ-üäÝA:4}4sïÿyluïÿÎÿÿ«ÿWÿïú¿ëÿÚì±ÚtkÿÍk,ÖþÝ¿öÿ8%ã°˜ëÿ­ÿ·þÿúÿôÁ?7þóôÃ?ùÙ›'5ÒG =Ä(@—ó¸H¹Ÿç¨âÚ(ïbÎXàÃ{Òñtî<`QùÕhL ɹôî<ÂÏq/‹§k )zÌß¿{ÞÆàH@CF‡/üM8éù5I}BvcÝêøä+󘥺>}4QºvºI•·_V¬ÌÀ¤;`W€ILnïª*Àà骛,}ç•su÷EåJ;¢ž¼Zš~èýÑ'ã†Nß ÒÞM»*7ÞM'ËvúJúÕiíó½ÿ{ÿwþŸG“wþ¯þ_ý¿ë×Ѭµ³®sfwý_û½ÅN[û¹ö¿±p?Öþ?¾[}:1ºþßñÓÖÿ[ÿ¿¯ZÿÿØÕúƒþœXøHÑC1¼Æ3ylÌÚ´‚|óÍ7Ÿüà?HzÁ4˜:,RJÚ»Cä)ÛJkÔ¹vcÐ5€PÐ'€)u_™Þ%¥nÀÔG5ÀþÓ1ž”`ä"ϲ·=beÂ_»6”-x3™‘CŒH—:®rø©ç{^áãZ ;þ^zæGe"×Ðàçü˯¾LßÛ½Õ—°K÷H¢à‡¾++hkP×ô–“ƒ|¥“&Hï½Þû¿÷çÿÎ:¢:¡ú’R[ý¿úß²ëÿå„ïúûxËž`wÄö`‹Ì5;gí¿µÿŒµÿ½½öÿ‡Öÿ[ÿÏ:Ñ`–Љ×ÿ_ÿÆBÃÿÿyúÙù÷o|zŒÀÈ€DŒA©1Ð^ÌcgbЇ! 1àúÒgeÑŠ Cyog×’œÛRšÁy U0o‡Ÿ_,•Ã#]PFººß÷ýO³óËçVX@‹Ä9ÏÒOÙëŸ6wZ?~‡ì„®z¥§Þ©³ *ã׀ʣ-Êø«ÉsŸáçjêž»þ#Òíú²; ÏôÓ¼ _ý÷öÛóeAÀ[x Ь2£IçW}ÒÈo›4Áû¬´g˜…_輇kúÍ/ƒÂÞÿóN±½ÿ3Nf×;ÿÎØù¿úõÿ®ÿY(çÏ®ÿkÿ­ý·öÿÚÿëÿ­ÿ·þÿúÿç£p…à{¼áþóô³¿ø£7H}ôŒÁ–çº[ùWðE^…ýꫯØtg“<ÎoÀ”‰|Ç ¼ˆ'ù)#>øO@#Lñê „c²ÅtÀ+åÉÛdK=؃Σ~€/ç0hÊÊ«»ï4P¶àQû#`ÏЋ+góÔ}à¤dM‡„W˜,÷ n!íŸØµ~ÆS¿j_ÒæºÎYZ¦u>ø øäü.ßF^Ža }ÚöFœ>FÙr‰µsäj={ÿϽßû¿óçÿêÿôñêÿ¬)»þïúϺYûoí?6¤°öÿÚÿñ7ø9ãÓ¬ÿ·þŸñ@?ð-Åëÿ¯ÿÿO‚ÿüâ/ÿãƒË»˜ì”êàêsÈÞiU¨ Tè`²87(-ZË;¢f‡áúzçy7ÖÐo€(ô¸‚ÝHòlMW—râ€1S¶ NËÚë”Ð_´x–ÐQšv‹)‹·#Nè%CëEãt9¿Ågʽ¯ ¢E†Où·>ðq¯kö–cýÿõÿÙìÌ;þóôã_þâÍŒ•çåèç‹zˆvIy¡8ÀÀb 1æX^°>'9ñ6e\Œœb´Ž1båðöòp#׎#u›ÈŒ³04• ½úúKÎëW¯ó–~åå5_¹:â^RÞ/«©#“cbiè19"›]Is#kdða>1ZCM˨ëîNÀžUßÔuš’ëÈ÷ð“§ÿ¾ùúëäyÏWÊ h˜]qÓ†ü> ©ûº@Û£ùþ#ódæQ°´ÙõÊ·Ïô¹û*Hßû¿÷ßcÄ+;ÿ3_vþ¯þ_ý¿ë?è°Îîú¿ößÚkÿ3ï­ µ½c@­ý¿þÿk|<€­p÷ÕÖÿ[ÿýÿ<þóôÓù af×ül4€8&[+ùqf'PÔØ¹Ñ£àHÓzï¿;/%—_þÿý¿ÿ÷@x˜äÉ”)˜U€åÁ¤3ùÀÀ iòøÛðeLœКôûSÓ̩k@$¨^A²–ó>¯Ö_£µíSnz#r'žBòîý€´G!ú(&~Ú䋎_|ñEè¾üòË€N/íÈšBh?•CºvªO ¢ºšO¾¿î(Í.,!çS}ƒò{ÿϻȌ‘½ÿÇa5>Œã£ãyçÿÎ:D¨Î‹.ºÆÈC_¹´ú:jõôÇ®ÿÏ?–íúl6FÌÚkÿ±Á­+kÿ¯ýÏ¿©ÿõ°'ÖÿËü`w­ÿ·þÿïºÿÿô“?ûƒ7œSϦ›¥Q0DšÅÂÒ ƒæîÌÊwGß.`ÏòQ®×Òtº2¯_¿NìEê®Ãøåé\Yïm¤ m‰ãtÜð9´çq_! Ï¡ñ~£¾Ô=Êpd¨¸Ún7Tê½€çêÀ³ýÁ“~9ÀØ$<^€V~ˆVý“Öp§é×ñwˆz7Ÿwaåß”K›†¯ ÿÊÿÝûw ÷¼Ü-Ts&îKùñÖG@¢ÝiÏÀþ{ÿgàÞÿŒžÎÛŒ‹ÿ;ÿG­þ??¬þ?»—­)Áºâ|×ÿ³Vw}®Ó5;5vý_û¯cdí¿ïÅ.×kÿ¯ýÿ½ëKüŸõÿ²|t-1_Öÿ `ýÿŒ‹ßUÿÿé‡ów“¡FU@¡Qj š0 €Ÿî6’¦\ƒÅG™:½žíFèÂ1w[­/ßy&zï ï>.å×J€:ewºÔwÉKnåЧ}W³HªëâI02zT’쿾¾¾ù$@ //šSîð;PdÖ¾‘IpíˆÒ~e”éѾnz”ö”i¾ò}‘»4×yÁø:‘EÐÞä©¿ah®úî BøÏ¸×—ô¦¹vàëØû¿÷¿C+ã-Ðh‡Øó¸Ûù¿óŸ¾ GŒ…Õÿ×£f«ÿwýuÙµý¾ÖÒ¢®wý_ûoŒ­Ç¡G×þ[û¿úÁxXûý¿n:XÿoýºaýÿÙ ô³ë‚¤ŽH&ËYQ¢×­A¦#Ñ:8.=GïÜcpÜ\×ÀÊ Òj¼ùõöì–²Xyðžrꨌbׯf'^‚kçv©€d'V_¤ž:GŽ>%Ÿ±`°#«í)K¶¾_R“ýêÌyê¸Ú®?m#Ù®Åêw^y‘ã­®¾X=ê@ÓºTÑYè…æåbN¯æêJ:)êûø(ù…ÖÕ¾•¹Fæ)ü{ïÿÞã¥ãɹ±b,/=7žœïüßùO «ÿWÿïú¿ë¿µC Öþ[ûoBvofP\Öþ_ûý¿õÿÖÿ?ˆ,™ëÿÿüçG×KÜN¡Ð'/BŸ4àË#ohë”(S`å Î,tðQ~è+)ï6än\FÌîØa•çÞ•»ÊSðI˜òø*[gy.>y7—²y5ü^¼<_Ìc†N êo»\?·±*¿|€Vþ‘qÂ1² 'Ÿ<êo·ìÐ\õ„Çе/•oÝ<Žþ¿v Ú+<Êo#ïÝÛwÙÕ nùÞÖ¾W&ÒÏÆÒ„‚ çêùÞ’IhL¶Öë\xÜ?ç{ÿ3~öþÏØ¸Æ™±Ó1è|çÿ™_÷¹¤_ûÉÛùŸ1DÇtGëêÿÕÿ»þïúï‡Çµÿ®×þ[ûífGeý¿yªiý¿õÿ×ÿ?›%ø¡—¸ß®£/ÆñšÇê@Ïø­À”€£L“‰CÏùËs4ÉD›¸;˜Ê_¬âãØ`8ÂùUV9ï(¨TPì=X¾ˆ˜ó©‹óôQo±a½°§/v÷5?ÊL @ªï¦Üá9/ƒŸ2­§;°ÈéÙu$Ÿl‘©“Œw°Kº‚=ÉŸ4!ý6qxNYqy…àúS9’74ï§OÊOC¨òõŹ7ÚT>Ê ½¾Ø=ê¸ç7O|—«çÒ#ÇÞÿ½ÿ3Vvþïü_ýÿЧ«ÿwýßõí¿µÿÖþ¯/f7×^_ûý¿ŽúV®= (nÞ1°Ïßø]3†’·þßñC§?ôËúÿëÿŒÿ<ýü¿þ‡7¦Ž"Pº=Ïvçšl™\h®]@&¥´ND`¸&tp×cw“ÞGÚáY°ŸÇËq‡wA¬4ò E¶©¤_ |qgäÎ;³æúÓ ª¡W¶ír ,ÃÓ®-Qù—NÜsàUÀ¹ϼ«‹’vD–i/9ñpÈw8o[‡äñúœßòZ·X6â\ >ºÑâÛ€·# Ö$Vù‘í"”Þ¼ÊÓ²H>.¯ŽÒïýŸþÞû¿óŸŽÙù½`•Xýtoõäê«þ¬;Öª‰»æøñȵô]ÿ¯¦?îkú®ÿ§?Öþ[û]ZÛÛØkÿ¯ýoLTG:Ïš»þ_|<ýñ±ÿ6ËËúëÿs[j‹¹0^÷üãñóÛæÿ?ýh^⮑‹.©¢,\\Áâ2‰I/­4çîå¤Q:å[ã›òÔh”6Ùí%¸và¡sÑ‹½J¬e¥§³§F¿‚9å}Vsmüúë¯?0ñUÎaçVQìÍä¤â%¿id#'°­åÛ6ò¦ObµÏ…69¦ž<qÕ×¶ëðõN.<’>uv´I{„‹6í>Ê ‘ßi/ù+“<ü*·6LCr=-~äå­2éáÃÇñ(?yáè iëÐJ/­4çøìýßû¿óç?PI7¬þŸ1A·¯þ¬)Yû¦OŒ]ÿÏ»ëÿÚµµª+Öþ[ûŸŽ\ûý?ºaý¿õÿá ëÿüçé§þ‡oLŒLÁ6G€ã²pQPɯªÃÓ™v1ŒB?濫pÑ:Ê÷K¤8¾›wf½zy~mâÐs€¼©¿$ón«>2~‚jö!þà||ùâeve‘±Ë§G Sf†`)²MÄ»À1uê;·È"ÏÉp— A¢ÚN|ÒŽáå\ ƒsåKW0K>úò—V àK<çäq®Ï{®|ù–®mÒG/¹g¥ÕÿÊ•Gaïÿ°{ÿwþÏÌÙù•³úõ¿õe×ÿçµzϬí»þ½¸ö_”¥9²öß³=\û²víÚÿãpLXûý¿ú`ëÿ­ÿO?ª'øóëÿçÝæ|±â@§óÇ?~ÃQoÐqí<`FÁ£€@Àb¢sÄŽv²EéÓé|•R»sºnwðgè”KþÔ—tÀ’úÞoUZù­›œ®#ÔÁƒƒUPÇ9Ú7ôÒêT^Yrâ£\ꌩò;‹e å'Éác—~< ÇIOkËÚa‡W¾Ž8´mÃÛk‡—6º í3ùéÇ¡m?´½ø´Ðë_€+}—ë‘dò’?<|ðp ÷.­´?5‡ä‘¯züŽìO´Ï*ÿÞÿþíý?€ôÎÿ™g*5Î||Ì¡ÿ«ÿg÷íèßêÏÕÿ»þ³=výlæ…¾ˆÎ\ûoí¿±?Ùžkÿ?¿ºÄüXûÿøžõ‡Öÿ[ÿ=ÎîúÿÓt¬âwÁÿúñŸýâK,ø^9tÌBAØ‘£cÐt€B®âéÎ¥0r}ÂCðóî*Š:HÆ(×úhM~ëk®•ýꫯ>ùì³Ï² j ¥œ-uòÉZú‚+/g§ÞòÉú q“çºUÁ¯ïŒá7uM±”U®}Pù‚iÇiÌÐyñ9´_Lv©<Ón<¼³K=ä 5qóÄä½×ÒUä,f“Zm x7éd½õµÃ[Ÿ·}{ÿÓU{ÿϘ2Nzt¾tì;;ÿþÚù¿úŸ¾_ý¿ë¿5x×ÿµÿÖþ[û¿v÷Úÿëÿ±—×ÿ[ÿýÿ³yæŸÿyúñ/ñf,¯8¬çµÁ5ÇÞ¯ ÎëÐ~: –_Ì&uv \ Ú€)¸RÁå5à—º'Az&ûÝyž4;:Þ½÷ãÈ4×x~ñÅŸ|;òÈó÷·€ ´sNò´äõ¨ <€ º¶ƒÒÛÞ‚<¨´w‚>²]qWeyBû!×ST›9û^þþrbùò¤i‡zô«ôÈ©¾ h*‹ôò——ÇG2UN]SÞå#sdê>æ ‚ÿ™æIç§yÓyhNîü¿¾ô::dõÿêkOçŠyÓ5Êj#ÝÑ9$¦gwýßõí¿g›yí¿µÿk§¯ý¿þŸutý¿õÿëwü®ùÿßû¿ÿßÿç×Ý•¹p9aΔvøäÅè“Þ­¼CÐè°¾0ýóÏ?ÿä›o¾É×ýÄ5FÑ9/xâ¨c÷QÚ¶“4êÍV' JSFP®ÀН ¢û«¿þ«O^¿z}ÊÍýq&;¶î¡@—:<] Ôãñ:}’ú_;² 铘º ôx¹¼GñÐJ ¿‘…QN¾‚\ê–§^²ª3ü¤ëO€@O$KûU‡GoÜAÿhÐâãkù®ËWŸ ß¹üÙ=7rØ¥m”)üöþïýßùvdîü?r¯þ?»}éÉÕÿ»þïú>˜³ößÚkÿ?Áö[zíÿg_ÂZYß䬛ëÿÕçZÿïø¸ãx®ÿ?zÃ<áŸÃUÖÿ?¸Æß†ÿdV³é8åWÏ9y2®H>(G4ô•§e É‹Å'¾7Ãú€}E_žâÊàÜw¨»;•ì¢RþK ¾È'/mW.Ö0Η çZù(‰)#¨]š€s‡ºå“; Ñ€FÓ„žÛáúðœ÷cM{"ç|QìZÀëË/¿ z!@Ò¤'žkôúìÛi Y\Û]¦=øãh¨ë&«$4£æ–œ>+ôä_írÏа:¹SžÌÚ÷êP6å‡YÚ6u’ù‘®ð•·÷ï¿1j|ìüßùïÆÃ=D/Ný±úõdže¤kJÇFv¸Î81fºöìú¿ë¿ñ±ößÚì ëËÚÿÇ‚Þ\ûý¿õÿbK¬ÿ?FÕåó³ø÷tÄ¿Dÿÿ釿üùÀG¨±i±”h¸´XU<®gpĨ@¥¡e9&òòþ(ñXl¤Ý`Žwê8îe÷º¼ëì@à€L Y¼_ ¹FhôÝ‘ g2úrPyz<67ÁŽ'‹ ñc8{/• ´J„¯òäC_9ÃóJOÁù# /¿Î{i»k2‡vò_½Ðííy'–¾i¯ã»ûKºÁ§}`;Uèßðúô·øµ2y§•Ù!Ï.´Ùõ…o_L¿ìB›Ç+óÏW_þìýßû¿óçÿÑ «ÿÏ\ sWÿïú¿ëÿy$8›á²̵ÿÖþ[ûíÿèÑ ëÿ­ÿg,¬ÿ¿þí…JüçéGúó7e,fŒäÝOsÎ Äpæ @Gßç gÐi€(bÆ×_>@§9  Eè~-è]ÜÉ›Gõ„Ô?ihðì–\¿ì¿Êco¿:²Ìµ:ÈⱿ—/_Ði@™¼fdÇ Ÿ‰‘u‡LýÃ_ÝÄC62Mš@FyÒÒ'kwéÐ4]ü¸VÚ‘QŸ$9¹¿dýl›wTM†Ç…ò&»#|ë€p&mŒÌ“ÒÈ¢“ÖDýå7á…_Ó*oæOÊ oïÿÞÿÿ;ÿWÿ¯þßõ×ÿµÿÆ&ZûïüлöÆÂÃVfÛ¯ý¿þ_}§õÿÖÿ·V¬ÿÿÀSà° !øË?ÿ™¯þÁJ¨¡Äè€ (2é©xÎV¸83 ðÊŽ¦^‡ÙÐã@ ÊìL ’!˜ëçÝXÒäªCÙ‚=y§Õ¾¬Ô?óbs`N%pÍc)7åËÈÕÎóÎ <G§.2ër6žäúÄõ§/æ¥ïó¯txj >ÊáÙev{ ½FWã(`w>ÒÉ/ xY¦äyDïÚ3_!t­íº_ ½ê”Å,ÉÃ{dtº'¿²¢%a¯÷þïý7fŒŸ[×q>ƒeçÿÎÿèÊcõÿê눵k×ÿ]ÿ×þ{¶÷Öþ‹qû’íÀÎŒmºöôåÚÿëÿ™æÄúëÿ¯ÿÿŒ ýÏâ?°ê¬ú‰E¦@FÁŸ€=“.Oè$ÀKYNÌ˯¾›û•–#ÎÄðDP¶’k”þ±Û+PÊqœ¥)«Lœf&¸®¬®KCŽä2°KKã•+•_Ž/@çäŒ|Bw(áÁç½ZHGæ©(mÄGPo"ô¡™ô.Ò§.ùõ©•½/EW¾€5|s}ñðÂv;±ô»_<ÑUÑáÓö¦o\OÛ“cçÿŒ ºGXý¿ú?ãÀ:sÍ]ÿwý_ûï€4kÿ­ýO/Ÿdík…¾Xÿoü³ë£hëÿ­ÿϯXÿÿ`çÇžƒCü}ðŸXŒÎ,‘ëùd¢t€(v?õQ¾¼`Pt)é;^šþêõ«6J«À þ€–€+sþéÓy49æ¼<•å.¹Ä=OÂõPCFñT˜Te»‹+ ÃbJ?ÞŸ%Ÿ|Ê «^“OYï"“wc¡+h„>ü‡N¾srµ]Ò\G&é³ oùÍë// ïëºé›¶O¬Õ€Á|©ÒÊCïà[àK™öWêšk´ ø9z=‰¹ž´G(Í-mïÿÞãxçÿÎÿÕÿçGúrõÿ츺Ö+}±ëÿ®ÿ™kÿ=ì³µÿÖþgc¯ýí¬I_¬ÿW?Œo¶þßÙ½®/r\>(›"Ç,*úKøþjR'}ÊF×òm§œûŒ_~Ñ8Yÿÿ_¦ÿÿôÓ?ÿÃ7`Hw#uÖÇ;° &ÈÀd®;) (ÀŠòøv€f`M]åÝhÇ›¸ö7å+ïòwä¨/>}‘ú\Ëó« “R‘û¨V÷€™ËS{»Ë Æ99ÐY0qÚ6×èMê¸Ë^žM§´¦¢ôOø¥?ÎJÓÐ@IDATãhòëÝÄxÉw-Æó×v­M[LLÒe„ä'ýÉŸkk",ªÙÈxÕázïÿÞcyç´IôÝÎÿ£cé—ÕÿG¿®þ?óÚ±ëÿ®ÿÆÁÚÇþZûoíÿµÿÿb\ÿo<°ølgÍ\ÿïlöàkò‰ësê#¡q.®kiMo,_ùúÕéÝ¡[ÿÿÚÀ2ýcãÉïŠÿëL1CcÒ4Ÿ}þÙ'_}õÕãWct&S<hÒ•÷XßH˜¯ýáõ~€»GS~z\“¥2¾œ/NVêÇS™§OÏbÆ5e¨*8Æ9PŸ|uëR_LÌõ%:Т¤£t+Ùs=ùêtweM|¥É ½“+ìýßû¿óçÿêÿch­þßõ×ÿóñ&Û‚]±ößÚkÿ?#vöe˳¯;OÌ•µÿçu(ã³XGùéŸõÿŽßu™õÿ2eÎØ˜Scä1VNÖ#ï>·6±þÿï²ÿÿôoþøÇo@åý;Cc¶ƒKšGý€'Rìò¾%PJ~3àt¢ÇÑ|ŒLÎæGyÍĽí©3#7´¥3Xï简:Ãàð™ÓîðL)™ÂÒó¸ã%?ÀÇ–Þ/¾ø" ùñ:4 ÚMî†ÓÈz;üɬ ~iëЫo˜=djŸ’¥ýòà72È¿× À !’®S²lèȨž‚U¡ 2â£\û)ýyU$¯”½î‘,}g· ùñª¬á±÷?ý±÷çÿ52 dìü_ýOŸ®þßõ×ÿµÿè‚Ú`kÿ­ý?ÆxìñÚÔkÿ¯ÿ·þßÁ꣮ÿ¿þ?l¼"˜Ãx[ƒQ#'ü¯ûyý1qñŸ§ýéÏß`âHáNT® ðLU)Q:Û¥ ”ôgŸ}„½@I@¢IïµÊ’v_xÜ…ï¹X8sš?m€üÈ7 üMÞu ì!/YíE²“ˆŒå« ¹C3ñ矹ùÃÇ®×çßìNškïÀjµC^Ûð±l){ÉY¾•¹y€2è;yú ˆä¼éꔑVÚd×›@¢^¨ b}WÙÄBóS¿ü¡kZ¤ ­Cº{ÿÝå½ÿÆãWÓó¿ãdçÿÑaGæVú‰î¸›_™S™¯'oçÿêÿêyccõÿ™æpþæ4>žc½Þõ×ÿŒ…™CÂÚkÿÑ«,·X±kÿÿ ýI·®ýžZÿ/Ã#j×Ó§ëÿÑ þ­ÿ÷Ûàÿ=ýèÏ~ñÆÀuËìNª!iPgAÃÒVaº–nwèâq<å广 ‰2‚G ÖÈSÎ#tb×obŒ }ë¦á‹Ç#í£s4d‘ïÀ#ü-d³Ë‹M·3 EN瀩*±¼¬Üc“Ú6òzVvZàsÖÌ$ù~Q™Y~údø?M;„ôáE‹®idlÿTN“?íºcÌ9ù•wT~ó Ø2ìS÷”·®0.¦\šGÞœÈ?ÌL¹Ê Í/ ä+%Ь…Rvx|ùå—±Ô Ô* DÞ¶]¬>“³ï}h~À¦Ö710M^å!¿¯p¡&M Œ ÏéÏ9ÉKå;ñ•ÕÏBëi‹\Сz6®ñZþÊNŸÜËá# /ÏîºrM†;=º½ÿ{ÿwþŸ÷þ™#Žÿ«ÿëÍŒ‡Õÿ»þwýÌZIü£?y4õ¤»n’õÿÒ?ú/sj:eý?#ãlYÿÿ`"wž"džÍ¹¼ßVÿÿé‡ò³7zn`F ë»®4ÖµwJ9·³ªQÀ0Ó`É¿í4 zò/Õ„Æ59ľhÇ—a©…¯8i‡YÀ!/ ”߯¨‘GPóíì¶zõòÕcb¿|yv‰áãU1ÀMýÎíÎÊÀŸó„‰+~¥ó˜¢:r=„båÞ¿;»ÏÒÆ‹¾¸‘­ý¥À«ìX}Œ';ÃõOšÒ‡‡>:eÔ%–®.Š¾ç¹¾êB×]YÒÛ.|]‡×œ Î÷þOGÜúiïÿÎÿÿ«ÿéÊÕÿg}ÌZ4kÆ®ÿ»þÇp˜?µ}2OÌ•9vÆÚgg§¾¨=·ößÚÿìL6÷ÚÿëÿYS×ÿ[ÿ?‹æè?Ž®ÿ0”Ú³x~òôùß)!@)/l?“g«Ëð¨1€f åzz6`‡2Êx#éâÜ4eš@é;œš.Æ/[ôÃÉ ØG‘ oé„V® ºnº/±´¡|ì–ò!íqóût|»ãJ~ë¨,è¿{vSEÛ€jÔð²Ó à“v¡ÁGZÊϹ]_À,²¦O§ÊªÇb ä øôœ\Bʵ0ÓN›òêÄ»zçégç® ]·ßœ<þ{ÿØ{°÷ççÌÎÿcHèóƒþ¢Mèç«ÿWÿ‚ñaÞd šó¦umÍø™ô]ÿwýg¡t\ˆé“µÿŽ-¸ößÚÿtçÚÿëÿñyã³­ÿ·þÿúÿÓœxúÑ/ñ†¢d@Pqýúõë€-ˆØ žÎ{7ÌðCT¾C(˜³u^\,ýL9¶mR8CŒ^Fðà¹ÞÇÃàL–ñ¡óÖW¹ÊúRfÈH€é­# ´UYíð+àMyá­¼¶E?ÜëS—t|r;“<ï iùÄ€v&’HûÕì0 à5uõ=a®cüe^@ëä—gúÀ«Ãû|˜*ãhÈõu‘¾ø 4²S×Õ¯{ÿ”œûÒ¾Þû¿óçÿ™ÕÑ?«ÿWÿ[×­a×Úä\Øõÿì†~¬Ù»þ¯ýwÍ1¶2GÌ•µÿØóéŽü©m¾öÿÚÿl.ú³ïcŽÿbî\~ Ÿ¥ëMí’ÇH’7Gʬÿ—nI_ÌY|Býx ëÿ­ÿßññÛêÿ?ýì¿üû7„·xx$Bà¨PéyW® þ– Ýìx¢t »„ÐØ •÷b]“'I%s|àÏð{€9ŒãÙݤ¾CW]z÷teòø #aèüûÞ<âêN(Fµ6Tûæ›obh·=ââQž#š42©ß!x Ñ#ï¿;;ªš/O; >¹–Wáyµ¡m¦d{íÔùÜŸx•GN.~äðëä‹Ù ÜÒn;ÏÒŸ•‘ÖöáQžw~=Ç·÷qïÿ,žÓ1½w{ÿwþïü_ýOW®þ? •µÞúfM麱ëÿ®ÿì¼µÿžm·Úkÿ­ý_}ÉæmÎ^g£¯ýŸÍúgý¿³žÖWÓ' Î×ÿ;½A¯ê‹Ž™õÿŸ7¯tÌDÇL?5tLõºt®õeí¸ßFÿÿé§þ‡oÚ0 ic¥®5°iU24S¨ùÞÅxÉn¦‹šn9W6åçBÇõPgwglºLY“u¾¨ Z±|±g‚‹Ìw K/%­ àJz¸i‡a¯€PŸ½þ,]å ü5¿˜æ=ZÃSHS64ã¯þæéiÝöþöÝÛÓ÷A1¼Z‡~¹ pÃ*I=}±û½N´øKs?òãô‰6u[)Þá1´9Ÿ}x_ç%ÜÓœ—wóÉWš½ÿ{ÿóxÆŠ°óç?³úÿè†ÕÿÇ>Øõ¾LDøÜÃ=Ú'¿Ÿ9.h¤4qèÂ@Éc¼ 9¿˜Ön¥¾)kG›÷W¥Ÿ‡–졽¶]W¦ÔO†9ÐôPwË’K¾òäAÓr÷{Ux£Q^™ï&RfÒ÷þ?ƒ~í_²Üûo§ßÎÿÿ«ÿWÿŸ•r×ÿó¨ñ®ÿcG­ý[qí¿µÿcPÏŸØô—m.=iíXûÿø4ëÿ=ã‚?¶þßyâgýšâ„øŸ£3ÄõýÅëÿŸÉ>Æò÷‡£> ŒŽ È1 ‘s;3ª”u±ŽÍõLC±cþ¤÷uto@Y zê1¸–K]×äU¨2™ÙA€fÎãj²;ìÎB÷vùË{›æ¼Š ôÙiåÜû°r>eeýÚá°y„ ޾äýÕWÏm <ȉ&í›4±4àÖ\äZÿHØBw/§ÝðJzÛ*¾ƒMhÚwé+ ëiø·_ÔYyZWë}?²h…–?€ãi‡WWfêÀ/íØûŸnÙû> °óçÿêÿ³¶Uß®þßõ׿”¯ý·ößÚÿkÿÏú8~ŠÀ©¿±þßéý!¬ÿwÖ‹øš3NØSBüÔé#>zýÛÆ(ôžcýÿõÿG¹ü üçéÇöo âH€*­ ˆ_]]w'”EYI7ðäH1a38gô¡÷ˆš¼òun€ªÓ#~);e4ʋˑy®rÀ«¾· GyfÀO~ÊÚ5AÝv_Eî‹ÿcÒ\e~5Û:}úO/Œÿò«/?ùìõg§ì%IDùv.•'ù:ámoÆ“Á{°ü£.Ê]›²;ìF‹gøŽ¼§GLܳÍo¡õŠÝ³o¾ý&[ ñs­m³€(àX®õ½úñÙû¿÷çÿÎzŒ‰¾ݱúÿì@\ý¿ë¿5s×ÿËA¾`7¬ýgT'ŒmµößùÁuíÿ3.úwíÿõÿÖÿ;v¥ucýÿõÿÿ©ðŸ§_üåxã%zV–q\ò¾'Ìh`@GA"€GA´þ)Wà¤`Oò&”k‹{ëp^Å`®óÜø¼L¹=W=Ò¿üòËùBÁËÈñÍ×_XÿЫo*ËûðS¾u‹mÞHø¢u}ð‚üéî¡m¤¡Õ¾Ô3»ÀÔQ@KmvmwßÉEÎ{†èúsú]ן¾ÃSÀ+}öbdÍ­™?çmDSÐ)/äýbW;"äiÖËW/çȽÿ{ÿwþïü]GÎA'R«ÿWÿÏ"’5g×+éy•€uu×ÿµÿÖþ[ûíÿëý¡£ýØ£?ëÿ­ÿW_¹þ©qQ?¸~*»;>í¯ÿ_»{ýÿ¿ ÿyúýÿü³7R<â¸Ì sM/× GÑ ¸œYžÔ”L¹‚5âž|I™ liš]•QZ¯Õç3’œ)³üÞïý^â·sþêÕ«¤—oë›ÂØØ5½|GøÈ˜ÒmL¶¿ú«¿Jl§”°¼ÔQåì¼QÜþP^]ø‰SfAA¿J#ÃéÃð£ÔN^¿ü(ßö þq&¯¾*_ò‘³åÕ#«ÐèÔ«½ÎÃcò*›x¥üÞÿ½ÿÆÛÎÿÿtÏêÿÕÿ»þïú¿öß±%cs½t·û¤­ý·öÿÚÿëÿÑëÿ­ÿŸzýÿ` ú"xÄø•‚9Òƒ¯)ã°Ž:šÖë¿ ÿyúé¼Ä1ÆÀü¢4P‡ÉØ ¯4¾°çñiuÄÅè¤ã›Ž›ÂÊ'LpÇ£Ž/^¾øäÕËW9G«\Žá+¨Kù¶±à‘n·ˆhš¶ûg—•²‚þª‘uòÒ?h¯>Tö8 ÏÀŸrápÉqo'¾Þw%³™6^Gž¶´Žö€cŒÒ¡IÛ& ç{ÿ÷þw^îüßùOtCuÄêÿÕÿ»þg×ÿµÿ¢GG®ý·öÿÚÿëÿ±“Öÿ[ÿýÿÿ5øÏÓOæXÀÛá-Æ@1P0@¡˜¥;âàš¤€¬¡›?ù _Ë*‡®Êï; tùt(ùvÿ˜ðœåüâ?iêTHTY&)ÛQÅÙ¦\éZ•mvh wN(é€avtMÅøÑÞK^ò0Jÿú¯ÿú“W¯_?Úl+l@«áI&2ë²8÷bym÷NºÚ&¯²V>´>Š.ý;×á7|}éÌç1Õ#( Ðrmç™sA›[¾€¾ê Sû¤Ÿ³¶KYüR×uß>¨gxîý?ãqïÿÎÿÿ«ÿWÿïúo½tìú¿ößÚkÿóMbCM½öÿúëÿ­ÿ¿þÿÿ¿øÏÑJîÞnmaÔ øÊÈýîýùbã©ïùñ½(õD¾ÓŒÔUåk% ‰lÙ%5ü¿ -﯊ð4_N”á'|h/Æ¢)sñÔ×h´­}ûeïÿéÿ½ÿ&'ƘñÑpŸ3ˆvþïüÏÐ0FªG$8_ý?úvæÈL¤Õÿ3vý›i×ÿ¬ôÃÚçPúaí¿µÿk«¯ý¿þ_mý¿õÿ×ÿÿã?°8& `„ÃpãrBL¢†ø×=ÆùõòrÏ+ú÷Èz|íî)àSà¤à #Æ–ËwoÏ;­ÐÛä17´ÆžX(xÁ ‡#ƒ‹‹öœžrÊ ÊâÑóœ\éi÷¼È¼†%º¾êÛ·ß>ÊVò Ê­´$œG=¦g‡ÚìSÿ¯GÖGŸjCÒN:÷Þ+¡ï¨’¦3!»×ÐM}ÀƒG½“¦_Õ-½}®oð.N»'ß+ï>”]ÚÞÿãxïýŸqkL^ó.qÆŽÐq&žA%aÆë5¾vþGÿíü?úÍx¡WVÿ_kêêÿ¬CtÇ®ÿÇØõí?zrí¿µÿc²Ñ×þ_ÿoý¿‡ÏZ?dýÿõÿ³VÞðŸ§?ü¿þ7ÀOç«v}7"i &Fç¨Ö$ʼn44€åjŠ&¯ç¾t§ À‡C\±k)_ÐŒ·Œ—êøôéLè}Éoêw®L­©›Ld ø2å#[còMPowTÝeêy™­-ÜÃ(²§ Tò à껳ȄO!œ4r1ÒÉ/dŸú|Ó£7Pï¾Dç\Gê¾Ú­ŸðT?ƒ/´oe"ÏÈBù€)Á==mœ UN>€Ny´‘shÐíýŸ~ßû¿óæ…¹·óŸ9z™¾è =BgUO¹ìyéRàúÓ¼ÕÿçGÕÿ»þw~ìú¿ö]ºößqÎÖþ_ûý¿õÿÖÿ?›vÖÿÿ»ñŸ§þòoTqPjYM|7´-°u@Æ9T|™¼ûæy7Sœ›‹"΋²c©¯¿þ:À˜tA‡—G ¦È®ÚrŽ9lä«,h¤?ò/'4|oéáÇãšãqbW€(í+èã\YAdùꫯÝ|°ÀRêuk¿¸ñÉ;ï¸`¤œwz…çÐ¥Ú}a”ï¡×d«ß\\/FVéÒÈýÕ—_e·˜4òÈoHÃïoß(†æ!S 'Þû¿÷¿ÃÁXÚù¿óÿ|Íõè Šsõÿù:­5¢úV¼úÿŒk’þx»þG¥vÍï{2]ïú¿öú˜+ôÈÚºäôMlصÿ×þŸ¹±þßú”A/<ôÃ¥7Ù÷ôÐ^þîúÿÿ2üÿ§ŸÿŽ)Xä†7Àp£;0š÷XdÇ U6 ­ ñÒò.¼@ÞÙ=$¨‡#\€(`ЀGè?{ýY”2:ùÒ-gÁ’úQ˜]E5åTÆÐ_2IWgÛ'Mºiox Lêµ»Ênœóø¯Ðè?øÁ'ÿí¿ý·O~ï÷~/rvr¨/õxù<çe²›…üÒ3±ª›(ˆ£„+_ß%Ö¶¼9ðh;Sç}yyý´Ñ.1»ÌÄò‚6Ù¦Êá}vc¥½.&¨W»¤Ù•E>¡åW¦½ÿ{ÿ; açÿÙÝhþ;ÿÏî" gõÿêk‡c×ÿ]ÿ×þ[ûoíÿµÿÙIüŒõÿŽï©?Öÿ›Í ãß²ÖÿŸùq½K¼þÖúÿ7þóôãÙE±D '¡ìãoŒQ;¤â¬ÍËÇÅÀš:³i”ý~À¬ašúùçŸÏËØÏWñÐÛyUK]u[·A÷#LåO¾‚9êr(—²WÜòh嫜sùm£sm"GÁ+<…ÖÕ6¡þÕ¿úWÙe”6‰}æR,£ðwà;—9ÇOÀpI@#?–N›ð½•*wËèFàÉÿ^&ú¥^iÀ«>^èž)÷vCerÏ.yðÁ[¾ ¯²´®öü½ÿÇùè8Ñ'{ÿwþ›ë;ÿWÿ¯þßõ×ÿµÿÖþ;;,Ù±¿×þ_û|­qf8Rëÿÿõð¯n>×ú·§œŒ• ѯÿ6Äð××ÿ?닾øMøÏÓOþìÞw<ÐL4ÀˆZqÞIøð¬º ¨LËŠå¡+ àúÔ#w ÝwÜÁ|‚rŽÖ?xÍn¦KêÉû¡Ç_¸×¯leq®~×Bä¿×ê!ÿä›:xªW™Ôu)å[ÏÊÊpí9ú¾Ë MA àö»–_¾}l@Ÿú >úGŸ iúMû=¶Sà°m“Fxåð–.ö¸ Çzäé¯ì»ÚÐv¨£²ßcéøÀƽÿgœµßöþV?ìüßù׿Õ)ÆÆêÿó#Ðêÿ]ÿwý_ûoí¿µÿ×þ_ÿ›iüA>Åúq5¾h}Ïõÿæ°þÿÿþóôÃ?ùÙˤœ{¬ HcPÜ™4Á¹‰ØÉøâ弄sÀ’>qxB®ôó(ÛA˜\À©-@Éðvð/p¢¼PÙ8ʸоzý*×Î 4 ø$\Š¢m;‰ÍznïyÏî$m@_žÎ9f÷6ÊÓÒ¢Œ^¾xùx§Wv[á;!ýrõ›k<Ò§7ç|h¤ ü´¥}®>íïµX¹"“òZ  9?ûì³€[ÝÆ7òÜã^·^y{ÿ÷þïüÞá¹óÿYçV÷ЫÿWÿ[ü¬A‚ظÈÎÞ]ÿŸ×rý²ëÿ±{Öþ;ý°ößÚÿ£Öþ_ÿϺé`[Õ[ÿ/&ű'FW®ÿðöUmðõÿ_}òôû€•Gé뤙I™L&V’h:ÉÚŸ>ZéÊ´,¤­4÷Ýwó>§>†84ò²‹hb_ÏÃÃ;L^<:©ÉÔt´ï‡ßH™44@AP ô(+ã Ò´áæ-Þå_âÙñ$#+Ýyû ¿®Tfu“£m{ÔC91Þæ1ÁÈ7×þ 1ø'–Ž€¨ÉWOÓZß)sƦ }ƒFùÊ(½/Ÿùê€kê«C^žèÈ+]\~å³÷ï?€ö>îÿg÷¥¾Øù¿ú¿úzõÿ®ÿ»þ{J?kÿ­ý·öÿÚÿëÿ­ÿǯ¼ÛHžZÿý¸Ãßÿyúwÿù§o€0v\xÞ²à£ãÀ$6' Ð2ÿèB¢¤'åEò z4¯´<ÆŒü$S½OfÚ,¡c÷ÒÎŽ¦³ý8 »À#<ðÄ_º£õJoZ˜ t`"õ â¤IŸC=WÆ£½'á¹ þƒJúJº~{5àOÚAf€ÐÇ«¼‰S¥´ÇKÛÈ4•Ö >ò ͼԭí“FÞ¼|=§ÿÔ©ݹÖv¢U¿XxØåööÝÛÜG²·ŸÐíýŸœ{p„«w÷þ·?2Of€+$=g§¯:ÅÍ+íÎÿéÀÿÑt`œ¬þp|õÿ®ÿæÃŒƒêX‹Ñ®ÿkÿ­ýw>bÄþfÛ®ýžDéú¹öÿúëÿ=?5U¿ÖüàÓñCøÖõ‹ÅI“>š„‰ëç2Öäõÿÿ÷ôÿ²Ë scÝ$`§ÂBQ'´FUo¾ëž?Í Þë 4Ƈ#‹§pç{Òçqù§~!gÇÇÛoßF4êi]@®ÐMzyçzäÚ„ÿÐ×100[>ç\|5«Ž%šçê-¿Ê,½r–Ö»¬ RéõQÃ*_;­Ð´ÿ,>iëÄmGh#Ç‘%u͵þ¨œêª<œÊé—¶ ugŸÇ#û¼[ìƒIŽÙ„äíý?qõÇÞÿkžÍ˜Œã®cËyÓïü?úgçÿùEɸ©n[ý¿ú¿ãAlŽìú~Ðë¡G­×óG[c®wý_ûoí¿c¬ý¿ö?ÝèkìÕ›¹žõ¤þºþßy¿²¾ðT”µÅ»¥×ÿ;ógý³æ„ŒßBÿlÈçGõ(„³£èUâGšx\ÙcPåWói¬F;(ØÒ—&áJë9ÞŒ2^R&f§}ûÍ·Í<æöÙ|Õ/ÜæÏ_|‘ þ¡Eê:ƯIù4 XÛ’òX¡òhð¿F•#1>9¦ýݹ~n“zûˆ ¾h;Q}§e`G“ _|ZV{õKÀ¼ËáG#ß®3òV¡$ ‚[@—w[MÚéé“©\ÛÙ'YÜà¼õ’×ÂïW]镹}§ÌÞÿމsÿzÅ{ÿϨ2–wþïü7¢s.]gt¬þ_ý¿ëÿ®ÿ±9Îrq¸ë|í¿óƒîXûoíÿµÿÇW™ÿëÿ'‰Öÿ[ÿßxöàϹþÿ pëÐ?p‹à??ž¯28ü:îÑ=€Mvò qÁ ‡e åñ>ý:\€)ò84½®sswtJg—Æ÷æ]PQàס7¼Èr~a9‹}™¾„ƪ.à Òˆ|•oÒ0^_šÊAÇuYûý?óE0Gœ¯ÿwüÚ£+¢*â¿V‡¬ÿp :V0f~ýÿ§ýéÏßè€,40âëbº§«É¤ƒМ<€•>bçñ=Á3¶dI¸þ´Á3=_#Ì×ý€O*;ëÙe+©ïâÑ›uç+?rÀ”/\L¦I攟tmCãº*‡´é³2™øž€rMf² ®çÏã~6íÞvò&ìýôûÞÿçqg¬ìüßù¿úõÖkß®ÿ»þÑ;…2çkÿ{Vo¬ýwìèØßkÿgžÄ?–öqµØæŽÍ~ì­µÿOŸÐ+÷þêyújÖŸõÿÎ@Ò=Öÿ;8Âúÿ¿ýþÿÓù‹7Ǹ0Ð)ƒA©»B8ÈfÑý!/@S’ÎB„WÙ àAþCS^†,Z÷<åò¸ÛÄ~‰}¼0^ÅW(ñýh¾øH2Àù.9†øQ?eÕ_ÀŠœKÏD'Ó€žîæ¢TÝdxéeñÆKP‡òBR&¯¡ò'ï*«?Óö‰ÉPg°|[&u\Œp¼§;×vußy—¦`›ëæljïÇîÞÿçùeŒ<ÆÊ0“pÒvþŸ~Úù¿úõ¿%p׺r×ÿ£Ò3&îkˆµUXûïÙ&5okÿ{{íÿµÿ×ÿ[ÿ/ ÅíOýñý¸‘¬ÿ?}ó»âÿ?ù ¡…Ó]¯ÑÕAr=/X’kˆ²"€ÍmP•ïò³()_PÇûRZ¬7sôZye ( ÷œ——X^^<>L• è@ž Í÷ø_ ƒÛn*åʧe”¯¬ÍS:¼ÎWSÎãQ‘Q»' Ð\õ胀NS‡A„äœ|¥ÔëH_L,Ÿò‡ûä$»ç¡ ý•¯¾;_yå§\ù7­ù¶ dIÞ0ÞûÆêÞÿ3¾3@>úÓ±–ä;3x2`wþ?¿[nçÿóø¡[ªkWÿ¯þ72výßõß»ößÚƃ]Ûúºf_X;äÅfkç]KÄ®×þ_ûŸdìÔ—3v:>Öÿ»æ;}BæÒœ¯ÿwlÔŽã§¶jõÌ÷Ÿ]䯓ףDGñ{®¾|ЬÿoÒ¥Ÿª£ÛG½þç°ÿ?u³2˜× oÅb•7½‚˜ çΉEe¢ï柣†ÿµ8Iwí0pBº:zÎÀ-´×/¯ÁÓZÆuù}:âÑ ýÎÏ#„oß¾ t„yÁºCèÀîà½×áü÷I ÔvU65zÆO;¶äËk}eg×ü»ËTßi生‚ÏNþù÷=é€\ò•WÎñ1¯{P³ìégaïÿÞÿØ×˜2&îcè~ž¼ùó˜Æõ\ïü?z­swçÿè£tW½W=¹úŸÚ-¼úÿ±fuŒìú´ë®ÿ<Õ­­Ekÿ­ýgѧ£S6 }²öÿ‡shíÿõÿâ‹®ÿ}±þÿo·ÿ?ϽqFGéÏÿ ì h‘ÞPVÜCž#Ê”!ßûõY@yÇÒгÀ-}®ÎË‹O_ ô.ùÃ84]xð#Ï=®‘SÝóï»y±zéÈsÚ0;Ÿ&½õHg—7Y쎒n‘ë—ÔYÒ¼äÎÑÏÛ¶Í­§r ÕZ]6HSoø f÷V¶Âz¾òÔ}Ê\õ_¨nyâs¯çôæÅýª¼î¡å¥§®X•VÝBó#ÏôûÞÿ{ÿŒÚù¿óÿoÑ-Õƒw]³úõÿ,(YWvý?ëò®ÿXZûoí?6æÚÿó#ûÚÿëÿÍ\XÿïøÇ †õÿG7®ÿÿž~ø'?{Äiì@‘vwZœ£½;0hÐJj°œëX¡\Ùjç0dQ(Hø?FŸXžCž2v8ðnÝù…VCO# ,”Ê9ù÷£|û ï=ÏŽ+åòxÓŨ!¯ò§=×±ž§²«¾ÖûêÕ«Ão€4t@2õŽ@‘·u“ÉyË©×=Èõ”;'ÓŽ<¢9WWžX¹na<„þM{¯:û²qä “qÃÞ; ÷þw}ú4õ@£LQÊ-íÔã›·o³’ õòå‹ZÙÃHÛL9•¯çÊšÛŸ¬vÓ>“çƒ: ¼­·³zÓ?ÿZ§:åûü÷ù§{éO·°ãÇÿêÿÕÿ;ÿŸƨÆÿǾ[û/³äÚkÿ¯ý¿þ?jý¿Ûb’ñ;ùšëÿcýÿ)`W€EüCà?O?üåÏßÔ¸(û)ì¾oUÀ«é˜4³îB¹¶€¸Òsù ° ß Mf¹ÑJQiy¥M†ùÓ{ç‚7®m Þ8´¥+“Oé¹ÄøÓÙŸ«ñh|¯5 ‘Ug-ËÃÊÿ^/ñî)9g|›Þº4_åúøÞ7þîùü"§6  ÀVÞÒÈ Ÿ¤‡ŒÒÉ“o2<òTž}þ§¿jCmµÏÇÿŽÿÕÿ«ÿwþßùÿlanØ5ÂÚÚµÚ„í°öß±Åkw¶]œ…Úœkÿ;\;õHûÜÚȽ°öÿs;´=î>ÍúÇ7\ÿïà s­õÿ»ýÿ¼B˜›gô›8(LÆy•€s•h”åÙ”0ü˜|GA™Ðãs3Í/o>›|+&óü¥·L Èïv8ü[Ni‹zã#tCjâîi½F‹çìK% tMgòÛûÊX•ïã2Ðy…HÀK^Çà/|®ºõ?éßÎj(¼çûq"ó7ñ÷¶¿ó¡"WËóú¤ç×3-¿m Ôªœ-?u™H#¿û}þûüõ+}ÄùÞÅíø?:fÇÿêÿÕÿ;ÿ›k;¯v>öÃOç_:sçÿµÿôýcí¿ßœ7/4Ȅؠ—­»tíÿ´‹¶¸Û^úNõË$$­÷µû{Æ úgíÿ硵©CÛ¬ÿw½éWëÿ­ÿÿÛèÿ?ýá¿ûÉ›L3¨)EÁŠž*KÊ/ ÆÄ»Îà¿VÅH›<:?­é¡Vx¸¦,äÓ@@_+RQÀs-½eæzîó ßäC‹—8Á¹å9¢rNbhÔæÓ («2o~‘mdyÿn6Š:€U@²)§hë%½²Ê[Y\hðU†üdì⎓“¯%z5q^É,oy*Oeÿ8®÷Î-³y ’G»Ù4WBy¦}&ƹíˆ@º#ü&ÿÜ$ß>ÿ}þíkú̽é+ùª¦þ4}»{ÙuœHýŽÿ´ÃŽÿÕÿ«ÿwþßùí?«·×þ[ûíÿõÿê×—«íþ×{çÚäM_ÿïàño×ÿÿ½ôÿŸ~ðg?{µè èuŽ{¡éh3˜€® ¢¬Cɱ§wþ¤A·Æ™ ¿Ü\TxLWîÚknÙó ß™ðíÍdÒ0tÑÝÁ¨ä‰=7î^Fãœåm=#³çtÒ…}þ§]÷ùïøï¸ŽÙñ„¿—®«ž¢o\¯þÖÉš©íãºá®›Wÿ³Ìõ§uèÜÎsæñ†¶Yh¯ÈŒÉÿÓ÷vùÛÚªé;ÿŸÎ£Öþ[ûíÿµÿ×ÿ;} síúëÿÑ‹ÿøÏÓf,ï€ãD `ÐI˜I(ÂÐ Ê9‘S51Ý -îņÐ>GœüW95˜°©¡ä¯ò‘!åCãK™¦‚kï@§nsOA¡å~7@8ôW}?¡@Í¿ïÛH~ø54|­´z_ÒåK›LCø&ˆ÷+¬vdøà#àqâÅ}HÙ¤g™0õ˜ûÊ$O¯µ­l•%ñ©ÇùÌ&¬SÈ£M’wêºÏÿô÷}þÓy¦ìøßñO‡¬þ_ýoÊ|{›?3¿H0]óIæ°ÿwþŸ~¢¤?\}CÿIÜt™µÿÖþ£:j³öÚYXûÿ´C ùërkíÿ¶Åœ×ÿ[ÿݱþÿÁ ªK_üÿ§ÿù½Ñ `@OcpPÏ‘§$jx¸çÌ WãDÃDЙ¤[ÍäZp&|®ü¯ZeÕ¼å xzäE7÷ҔײZö=oËr~Ä_òËŸcÒ”-_lää ˆ šû–U9¤ ÂÓ½4A¾È:9í¯%¯×½n…®KÉC|ýAÓ2äM˜‚ûí34÷UaÚ'üÈ2m*Ä(¼èp±ï˜ÜåóÏU¼{GW?DÌntynC»ÏÿôCí¶ÏÇ?€:ctúÃŽÿÕÿÔæêÿÿ3ŸîüÿlÃ-±ößÚ±#×þü°m¾Öþ?¶½©¬ÿ§S¬ÿglðcõ‰Ì©ãÛ®ÿ|öõÿ§/ø ¡bÿ'«ot’t˜Gjpä|)¯Öi¸v¢(0‡^ü]»w0êг'ŸOK” (ºIô¹;ñÄÃ9ÀÖœïôÀ–»,ásWýjâdNý¤ÕÉh'pÆÛ@!êÚZ§E&ÓUvÚè*¯õ"3¼ÚÔj+íÚr€Wymñ*«ù;8ÉPþÎdW¾¹žÌÑ8t•_X™| íìU„¶e IP–‹}þöÛç¿ãÇÿèàKÇw<Ðo®Wÿp†.¥G«¿Wÿïü¿óÿÚÌ©µÿžŒ5—:ª'ÙÐkÿŸâͧm—Úækÿ¯ÿ§/ôÐGÖÿãz¯ÿo^I»sýÿƒÿ<ýä/~ñƤ[PCG±ÊÇDãú>€Ð$mè¥dÒVúkîå×ÈèÄI'pŽäm™Çe~¤b¢CŽ–“û‹Gø OàPW%‰û8T~g|Z¶û‚?Î&[ò¦F~×/>=Ÿ'·|â’ع²wÖœ•Yß@'¾4&«Ç«•Ùß묌 ƒÛŸÈ©îWû‘Å¡1¤9Òæ#O'À[ö”­M’ï–@.ò<ò Ÿ>϶Gê²Nþ¶6hJ®rD–}þiim²ÏÇÿŽÿÕÿ«ÿwþßùí¿µÿÖþg®ýÏ›[ÿ¿töw^ÿOXÿ_+<>$ÿaýÿiƒi–â iØÄ~=˜ÃÀçWä€À WCÊØý–0“V€ÙalÏ%ù&5™“’WèºT­r(ô–w??²OYVM¶–•"€âõÃæld¾ÂãžüW<Ú1ÆîçÏ)gîhK㺯Š{ûöm&"F EôúõëTÁ ‘UœÐ2ô\ X&³«­*ZÏ@ ~“/5 *éÃ0ûS‘WpPšý{’†F™­Gù£MüäÈþSVêŸ\ûü5Ã>ÿ«ïhŒéÓArìø?{Ûíø_ýOw¯þ?z‚š #2ïüŸùhe>ÞùœöÙBaí¿c_®ýÇG8ݹöÿØWþ³³®°ö?ò Ó.|–Ø |ÑæšœÖÿ[ÿÿºþ¿ñR½z†ÈåÃ]ã§úåwÑÿúÑìu1 0èÔ&\‰Ñz*iîÏùR8èñt²CåLY_JÈ}°eUŸårWžÊ"NyÊp¤5]¾”?ñ}¸Çõ:<+“×½&ؽ¢8&@ŒòàY€êÕ«W€X¢Ôã’×lð@+D–‹&ÎϤ£cèÖÈ áE;>êòïcðê(qrá>õÑW9îÕ¡m“ô‰{7õ³iýÇi-ß9´sÖ~ûü÷ùwLéÂŽÿg{Çõ~Ï«ÿWÿŸ7óoç&óÑ\G—Ì5Šÿwþ_ûïüÈ™‰uþ°½ØpƉcí¿µÿu‰¼^ûý?jbý¿õÿÏ|Ÿý÷Ðÿÿ4“ä€- “¦Éðñ½ ¯ø1:iÒ × 2¯Žš|‰•0Ý Ý\ÊóŠ]iIº4|†–#ü~6A–CÜýˆñ–—Ñ;×å}.O º:ƒ¹ñá|ub( ©ßH‰\µLÄo&Ã÷ôi~y|}p8¸ øc5Ö_| å¾€žyÅnÊL‰¤ágÉè0J@#xöq@+ºZõù¦½õP§zs¶©“€ÎÕ´VÎ5 =ÇÒ¸þõÈë>ÏwòÜeLû\üöù§Y÷ùOÔ/Ò§¿;þwü¯þ› Vÿ?ÿP4Š"ó-q4ÅÎÿ;ÿ¿¬´IÿÐ7Ì#ÓWÖþ[ûoíÕs06ÖþžSî>É(ŽÇ¼2ͶþßúF~"Üý6ˆøõÿOÛü.úÿO?˜Mܺxøß?fgÖt@Úu'Üir*ítëNS°„b®A÷PÔÃYù¥i¾)`þ?¯ Ràæžÿ.C;îýŒ—€®Èõ‰M™î8òY™h,•ÏË© €ü»è¾ùæ›O>ûüóðm^µÖFá3àT_1ÁO_w h5e¼œ•Y6¼ó Ã?eDØH‡O:Ü”Ù@†) í =-=g×BxÌçËÝ÷× íÈç²ãÇ¿~@gT§Tï÷,]¸Óäž6ŠªyÖ7¥©n_ý??Z¬þÌMúƒYsçÿÿ«#ª[FÁÌÿµÿØ— kÿ­ý?ÊsíÿË¿©}a|Ôß¹Ÿã†t0òœp~Äw_ný?ô¡mW»¯çÓvÒ$ÏÚëÿÿ/°ÿŸ~øg?{cÐÈ5"ú•¼Æ1&Ð?„ÒWYÈ 9÷Ïï¹Ëo#²cŒÅV|ùt)h"î¦Øõqù@IDATû,÷è z£<¤i/ôÀ¬–ƒú–áü¨Ë•6‰a ¾åü§-NÕ¦^d“&GxMÝRÆÜ;ÇšôðºÀ¹´Å)B¦“Î-«mƒŸ¸Òìóßç¯c¦¿]ý&ýjúÈŽÿzïø_ýoŒôåêÿ3˜KíÑkºcçÿÿcc¤wÜþLßXûoí¿öÚ¢t†ÐsuÉ=níÿ µÿ¯¹fý¿õÿÖÿŸ¹äwÐÿìe"°*ˆ#ÚÉà>9Ôð¬ÃÊ8OúÌ'2s`¦4™|.ð¤¼ÄIï}ó(3Ïœ?þEVZè'š(¤áãØ ”iŒ§CZ¾x8‘ûoTú™ÿ‹ª‡WñGlòÊ£ø–Ã)íDê:´¡ýæí7Ÿ¼|ùrVU½ ÈØ’.îÈü zà§ ñ)g68­‘VÇWZLý¡k½=¿DjãGÛ]õmžðÞê–:éÊ §a&ŸÃ³µz¬¡ü*Ó>ÿ}þ;þwüÓÕ w]A7‰§7Vÿ¯þïü¶óÿÎÿôDl—›Ž 'Fa| Kjs¤ïÜòÈl–µÿÖþ{¶uõ áèšµÿ3/O{8¯ý¿þŸ±‘>±þ_ÚÁ²þçÒ™I~Çýÿ¬À2a:~}R12¬ä%YÐ…Ã"ÜéÙjŠT«‚«® BÍÌ“/ÑH—ÇÙkò$JžË1BßN¹æ^ž”qC-Ë’O<3€/º³2iʼ@(¼+_¦–§tÒ)÷ÖèÈXþ΀'´d1}:à—8+°^ÏŠ,·{5PT6ùêð‘ýýwÃcÀ$ùÜâœaêÒ@f´wæÆŒž8tò6½ëƹn=KOx÷É7‘JÜç?ÊoŸÿé;;þ3Vvü_¯×®þ®\ý~ÜéüºóÿÎÿµ¯Öþ[ûϤ¹öÿÚÿëÿ­ÿŸvüQ_¢uÍfp^ÿý6ߪ˜D1‹ÿYüçé'ùÇo€ö°bç»÷gÿ&¿ªZ™$H·¢¨+•€4:¡ÍÌG“`„(RãÆÊÆ?>å‰FzªVÂYð÷ýµÑ¹UHïßÍô8R“.íÈý äØp>¯û]ù"ËE§¡J?QϲÎu±Ì}ãºÊ+@ÏÈ‹&¯  Æ«´ùÞ^«¯´ ùäM™ œ`•¾mqø},WËj|îOùêî,͵èÚþÎùœÑ)SÙi?† êÓþá·ÏŸÿŽãeÇÿ¼ò<ÿVÿn•ouòêÿßd¾ÛùçÿµÿÖþ[ûí¾Èúëÿ±ãs_þ)›©¾îúÿëÿÿcà?Oøoü†òêÙ‹O_< ©¿63ÚuFÀM;{Wi¥éÄ=  à--å ¨${¤X&±ñ=Ü+8Ô_z¥YyÕ²†8 Rdz2£NyÏÏ=^Z–§âZ_¼ÔEºsËt lh Ð{>å~õÕWŸ|>›¼«·tü^ÌñõWg߬·o߆_óºl ­ŽÊ*kÛ2qW|å­ m[4e ©ÇµªÆ}Ê™²*û>ÿçUrûüO¿Øñ¿ã¿ú‹ÎYýæ·Õÿö”ÜùßÚ9¼vƒ¹uçÿ@[ûoí¿Ú¨lݵÿ×þ7‡Þ}›õÿÖÿ3wÖ·uøbëÿŒD‹ÜÛgýÿÁMþ¯ÿ÷ÿÛkÖ_xóÑFå5ÐL>V1ÌlsÚ˜:Z^Ý>]:*­tOæGè¾Kþe6´{%O(ñFç¾ S˲*jÌ<éüJ…§õœÏú-Oâ~MÂïÖ§¯)ŠÃ‡üd—§m&ŸxySèÐÿ³öÏrÖf‘s&oÆœ|ß~ómøÈ×z’Á½²‰[Yð:2Í+€SôêÙ|ÏN(&Í>]ä-]òOüD\ÿ> ç‚Cx¥^ó¥<ÝàŸlS†ëòEÛç ®×m»Æ¹wTö´Ù—r¥· tÐ^å Ë—oåîóßç¿ãÇ?ýJ¯¬þ?:Z[TO¯þ7sœ°óÿ±/vþ_ûψXûoíÿµÿ×ÿ»¦Çõÿ¦!Öÿ_ÿ¿†qÁ–ØÓAÜÿyúélân‚ÍèéùÞ¼âvÖï„GþèlŸÍö¼Bôy5€VAÈæ¬0¡Ê_aK  í|OKÆþ ¿oR®ìÉ–Î^sp X5gÙËÖð¶bìÓ'û?€K¹œ â4oê?ù#Ï•Ž?ziâ]ã/^ß›û¬úRÂÄYyeµ“òÑshºLZyÚèW¿úU^+”fõšUkÚ¨¿\¡ –zžöòX Ê}Ô<%Pù[7Ȥ8OòHëYÝ4Ú.ùçÚš£}þ§ìóOÉ}hÇÿŽÿÕÿ«ÿwþßùí¿c®ýwÞØXûí>ãúëÿqÖÿ_ÿ_?ø§À¾÷ŸþŸÿü›1É^X€H3'¸¡C:܃>^ÎëoßÌNñ “V ‡ðLfÏ'6&94wþ@è*£Œ¦­ò#ËDÙÐÜÃï€4Ò+CW{¹Ï’ÖK>`•U§ÞøÊaqÊÂS9€ ÷âÛäL› AùuàFÞ«eÕSË,O÷ä%ê—RN™x &åïO[‘LÚÈuêˆà*ß}€¥+Í}¼¿!ùõtb호Ü_rN^ ZëMžÒôŒ§x ™È.4]šüäw=D‡fÄ—§í#üò‰ëëA½zíó×Jûüõÿ;þWÿ¯þßùçÿµÿÖþ‹}|ÙžlņµÿÿÁŽ^ûý?cC_p¬ÿw|)þD|ÓQ|PÇýž.©ë:¾ü¥käM[^ñü[ùµõÿŸÛí÷ÅÿÏX:‰NР“íD2 Ò8gFœ|}ÍÝ !º8;:Z_ôø¥óΪ÷è£8G/žÁ.¼¿}7«‡.¹ú@œåÅ?éŽvlq1PÍ5Xæìº PR&ݯf‘Wú9Üãoå“×üð~V©É3éÎMéåq¸'9åkh9ò™è}ùÏ+{Ê$‹¼Y=¥üÊ€Jâq¸Ý©|ð¾_ßÛX™§ó*á%Ci¥ á;e Ò*³:h72hw!í;ge‰“oŸÿé/ûüwüïø_ýO'®þßùçÿµÿjK±j­ý·öÿÚÿëÿ­ÿ·þÿúÿ?üçé¿üù‡‰–óå ´¨3î\CŒQn."ê•=ÎÛoÞšh£ðð¼›××^¿~ý˜¸Ñœ`åÒ3(‘ÏŠ­·_ãu0—~õPyd KžK¦Ê¢<éBë6÷ù{€ò;¸Œ,@¡O#ƒ¹.ÿ+Óƒ`šº©“=´"ÛÈÑö–fÙépV ÍY(ßÊæþ~&2O|PªSXÊË/·z›HñG_>ÊuÝ£òìó?F¨öÕ°ÚlŸÿŽÿÿ«ÿéÕÿgïܳóÿÎÿkÿóØ Ç~`W­ýwì'ºbíÿµÿ×ÿ[ÿoýÿçmJèÅõÿÏW¯µûÚ¼ù7ð_!dx2:5Äuл* ]v ÙŸiVåu³IG+¯N®)&|a® ÜLäÒ#Ãäûƒ?øƒ\ãgStÂK¯ &;AeÄã0zñéó«w“<ÛÁ0×€+÷xXUDÎ/¾ø"_Xôˆ/xƒÞkÊ!¤û€Iá<®*‘«M~Y N»ô¼¦;+ÿ†ž¬ÊT{öìÒ.Ú ÖðAÞ‰ŒlMœ³ò¼iU1‰»‘œ¸ù‹®ù+÷>ÿ}þ;þxkLìø~uT{8Vÿ_Útõbçÿÿýмöß±¿Öþ[ûŸ#¾öÿúëÿ­ÿY‹Ó>üØÓëÿL$ÄßÿyúÃûã7€‡àl( Ÿäè¯#ßÀÒý™B;m_§æÅ¼úpa×7ÞjŸð›³8ÏýýH¡×ü¿úòËE}Ð&Gó–¾@ÓùšßáoW•®@MW[Ù´Ü«yݼ¼ò ›ÕNßÌj¨¯¿þ:òZ•0•šß‹>X5Ö:adk9¡¿µ  õý1òMÚ=Dj;£Wnƒ!4¢‘^ZF.d×öÄ·@¤:>BÊL%&*O(µi<<„´Ç>ÿ}þ·> \Ýñ¿ãõÿóªÕÿÏóüÎÿgõrçg6Am§ÿÏ>žkÿ­ýW¾öjmΞógíÿw±Ç×þ?>•~±þßúëÿ¯ÿß¹£sEñŸ§Ÿüå¿ùÀ¿€ € çÝ·ïfЧŸ|6¯z%€3Û}Ÿ0u}Y¤ëpŒ9Æ[yƒM â[¸(÷ø8{%ñ€Fgµ” ­Pžø›Ðuðo@sç-þÓ \s ²ihP’¿ï!«[ä½ä(¯6œUc÷²ð“æœ]uQÏ!~з Bxý!ëN|Z¦er¯_x6lÄËß²Îë‰çõH¬š/²i‹‹>¼§¾÷+i¯Ñ8<ßOŸN6­¿ìóþÚ˜~¸ÏÇÆÈmwLŠÚñôéêÿ£[GÙ}«oÜ®Û}VÿŸ9¬s óÎÿgÎÙùí¿µÿæGæµÿcß›?jk¬ý¿þŸGÖÿ[ÿnPÿ_ïú÷ÅÿúÁŸýìA ÂBG Õ7ó*pàã@_p*«.‹jLø¤è ï¡ÚÝ4ºÃ$ ézâðçá%½e»Æ³eóí7#ÛyÍï_Ï€˜²CO@ShžnÀé-<{Ι(ÄMpN1×äqGU ‹x¡çܸŸÄO>T®Ïñ!|Ë«uSà°í‡oÀ·)Óʪ>+ñÚb„;ûy‰˜ë)è”[’œvO}&½Ï 2’«<÷ùø|4©öÙç¿ãÇÿêÿÕÿ;ÿ›:gw~pnØùí¿ÚVì±µÿÆff—N¨í¹öÿô¶øÕ%kÿŸ- ØÛëÿ­ÿ·þÿù@½¹þÿ§Ñ“Õ‘ô&üçÀÊ* ó ž_B£Xg…ŽÉÀT%{@˜³oö•²"êŸ=ãå>ÉLœCÞRCP¡Ä”-ȇ`VM§’l&D¿\J{1 —x`ŒRÑáí5¨¹ ?¼ì/åÕ>éò9È"^Cá׺Ʉ‡Pµò7¾³óÔ,uüÍ´_®¯¼‘iäBß<½vVõvn½”çúÞ~­ÏCÞIä”+]Ç•ø¹ºêßrñrx3ò*Ÿÿ>ýqÇÿŽÿÑô ÝR]áL'­þ?óWuùêÿÓ/Ì=æãžµÏ}þšÉï1š£vþ?í±óÿ³]´öß±k¡µÿ˜­kÿë ƒéÔµÿ×ÿ‹¿ºþßúÿ£~/ýÿŸÎ+„áhÆ9Î/$]ã×f›±k4”gŒÑ dq-ޱÊ­‚}ºh¤›€B ÛæMúðN™ƒû<öŠÚÒTž–Wåé^Vh@/ƒÚaø¯¾þê“÷ïÞÄ?©KéºI3þ©ã¼nˆ·tÀ:•¯3´®çO6.­ñ-Ÿt_W”¬ÏFûõõé§ Ú…ò*ÀD¶†¶°˜¤Lq÷¶sMŽ–‹ŸçÙ V“†'¿þõ¬lÙ*仸îóßç¿ãtÜŽÿ£3F/«ÿWÿïüìŠÿ×þ«Í¶öß±—´;ríÿg;|íÿY=µþßúcCÆ^ÿúÂúÿÅ4Ãa‹*¸çãÿyú—ú£7ñV8,@ë×k«‘Ð芯@' ^PJ'¿-Xí` è2g•hg—žøÙPýå‹óº _r(C™ÎVHeCöá[Þâòjè}0r)gâs=¼Z&ÚÔájLr†n╉N TÊ»€$+ÏÈUà2¨°(R\² “k…ÓpV×)o‡p$ÎeÊjÄh¿Ê Œ¶§¸|¡°îyð+Oexb4äšø§ Ò{ˆëõ>ÿ}þ;þwüGO^z¡zèÄ­þ_ýûqË·óæØÌ­Óg…óÎÿÚcí¿µÿbŽŽ`cÖwÖþ¯õ¾ö?ÿdý¿3·®ÿ·þíîõÿ/üçG¿üù›)yehVéÔø4™H³ª©Nh/õ¾H\éU¿€«  Ãeà!é&.´} ½ï„ælÀ¾žÍãBÀ¥)›BóÑܯV€%“£ÍÈK“‰qâ&"usïP~@'ç %U• ×Êvî=PH~ñ~q¯¹~12”=þ-K| Ù‰S·{ˆŒ÷ˆ®#Ïհʨéñœr¯~Wøø>ÏsÒ=¯³Iûy6´Gëöù€uŸÿi}Bߨñ¿ãõÿê?àd®¸æÑÿwþÝ0ö Û†M£ÔYûoí¿µÿ×þ§#ø/ëÿ­ÿç5/óCýýøµ·ûõÿ–¿ÖÿÿÛñŸ§Î&îàŽå¯‚NÔæ+}6tçÄvS5)½ÏÓ³k §Gž$ÊPVyßÏòaß´ÍOh°Xb‘ØÂ›¡”¼sí, £÷èzH¢‡üê¬î'~”íl”îZÉ¥.{ –ûÇ1ñ^Ó+PÀhâ’oÊ PGÚýbô0| nyÐÕS#îÅ£¼¥{ñ‘WÄ-T¶F=è.¹•åy ëõ>m±Ï¿}GÿÛñ¿ãõÿêÿÿwþ_ûoí?ö'˜à,8¯ý¿öûÁúçàõÿÖÿï|ëÿÏDñ€ÿ<ýàßÿôF¾;­5R´ô¼jƉé¾P€à”‡`Bo° â8¾â€GîMz›t×*‚vŽ÷ t6q'¯ø<å…°yÒ®VýÐνòî)RGiΪ#8ÍLº³A»´Á)Îý\GÑLZêñþ¼êèZÝ>ûì³”H’GPŸß›W•YY[ïÖ½kôS~ÊLë9äë—kôÍ«­ì+&í¾ê ÿy4Bï[nydo®¡!¹öùU{}·ÏÿÑoÒwüïøŸVÿ¯þßù?Óêcî?sçÎÿ™7×þ‹­¦-ؽµ¹ô˜Úp[ûïØ§þ®ý¿öÿúϾý±þßó¢èÌQõi×ÿ_ÿ__(¶óô“ÙÄ]'é_C¯½fök&¨¼ú`ið•];škÍFéâ”ap>hkŽ §ü)gÊê}²´ïÏ ,÷ý: ¡ 0çÛwßÔiÀ!åÈã:¥«ß-S9øYu„FÞÉðOåOù“f¢˜9÷—ÈÊJ!2Ï™lÂYa5ÍܧìKiä+€ä^Ù:GCë$5ü[‹^>Ô'÷sþ–×v(_üî×­_âöùïó¿:ÞŽÿÿºÂêÿó#Âêÿ™O§?ìü¿óÿÚ¯b'Ðì§µÿŽMù°íÍkÿ¯ý¿þ_|¶õÿÖÿ¯?kÖÿ‡YÔâ`7üç釳–ÆÕ € Üô—¢-èLÖ€)˜3Zù ®F8Býæ“Ï?ÿ<àLù[±„‡_ô×øË/ÈWîÃ{* 0ûæí7¹? ”×çæß•Qõâå| qÐrõàˆ—Î**u˜?XŸUW‡ŠÃ>ñÝßÉZ§Ö/û_]`UŒ–)»m€Þ}•0é'òQ¿¾ØN¬Þ!!ôùÙðé¡lt‘{ˆ[_çÊåºñ-ß\ã•BNséÏ„òtÆËá/Ï@¹dunšz©ó>ÿé¿ûüÓWÚõŽ]g÷;þÏJÇŒ×iaÇÿêý`õÿÎÿúÁ±=bìü¿ö_æMs§ÃܺößÚÿú‚P;?öÄô çÒ×þ_ÿO?Öÿ;ow­ÿ?áÒúE‘€ê”Î3õñé“ßÿÿÉ&îU€­P+’És КàÚ:«â Ø ã ªäÚ–!ÎSò:ü¢{o@éÊÅ#|&¿{¯¹H‘¯2 ¯,Î@&<-c ?eK"‡<ɦ ÇËkå•§ ¨Á£u’É'­ Û­Ì‚²çzÒÔ _üÑž"O»«2’·ív¥¬Ò;ã‰/´Íß:ÛL{Þi+s÷ óÏïW)5m:L|Ÿ‹3žw>Êè¡—ÞжoÝÄ·m«}þûüÓ_ô}nÎíC;þŽÚñ¿ú¿z³c¥c¤çÕÿ;ÿïü¿ößÚkÿ¯ýÿìcÕ1oÖr®o¥­ø'ñQ.߯×ßãÅÌýú|ÁõÿÖÿÀ¡6çoƒÿŸMÜ *´U”óÅU9 ï+vÒ,í@aˆë¯ŠEóKûö›oË ªòÁ³F»8ÀI_ Kä°gVm‘#ü‡F¼×ôL1‘/ò ïîE6ˆã"y(²¡!Ïûï åZœ²{Vür?<~}mhÆàÇ+ Öðè&ðÒÄ%(cmƒGå–Ö:z5¥{P‰G'OÛq"R7÷‚2];ð(2´§ qyNÃòÖ>Ãî´Ñ¤{=Hyx ø ûüO?ØçõÓÿÑ!;þðV½WFg¬þž7VÿïüoL˜lwþ_ûoí¿ã?°U×þ?6öÚÿëÿñq×ÿ;>,›’=)tlÌE|ã㟮ÿ¯m´Åúÿç4mñô¯fw àäÖŒ’õ:POzÃéT‡F\é -íˆÍ#-@ÊtPûGy0èo ™CßüÍËð;eÄ;ÐYETz –n_@MÓå/¿ 3>g…ÐŽd?,ÀMËp8’5¼È Âó× ]+ÊDŒ•è5rº&GA%9ñ)s;¤4áÔqV^ù2âÜ—FZÊ»žCe/OÏè¥ùJ£ ÷µå‘}è†gÚnä5Ÿt+ÉÂ3ÿð ­6×Y®r•sžÍ‡å†×œ².yÄïó? ¢¶Ó>ûügl¦wŸöh?kßÙñ¿ãÿè˜Õÿ«ÿ8˜¹É\4GõÅÎÿÏó¾¹E»ìüúýÑù$¦_þœùfí¿µÿÖþ_ûÿ{õáÖÿ[ÿoýÿß:ÿÿéGñ‹7Œ¡“½kàL Š~,£€h(5’ÆTø`ŸTº€–Q£ÊUÒ”ãkoÀ,%×0M¦ë~"“ҽǩÅ+Dzàß2ä//g< ÜÂyÍï¬ÞŠ|Ò'䵺á¡>¹¿@×åWøM\ÏÒßóá;€ÓÔ ðUZñuBÄõZ= ðmç–'¾í/® >ÒÞ½?¼ñŒ‰cÔ«ã—¶U¿»¬xäy<ð,ÀTšÏŸ–Ÿx<†?*²Í½²ÕeŸÿéÚbŸÿô–ÿ;þ/½´ú?z¡:õÿÎÿí ÆÇÎÿÇŽÒ ÆÈÇÖXûoí¿ØVkÿ¯ý¿þ=¹þ¯sæ‹ù÷™ã«^óFçõÿ·ýÿìu-„ˆÑàÁ8tÌu€‘9× ÐaÐHŽü’uýEc’nàPqй rψ€R-«eç|ñÖ}}ÍõÈ‚ö.¹Hä$Ÿw¥ÉåÚë†^›‹ÜÊÃuù‡æfî21­~sñÓJ4€”¡€@’{ûû(Ó½xqVf%}ÊR†ý²äk;¤¾øª«ó%ZåY­öúÕëTSýýê,í嫳‘>>ö㺷E®‡FZøLnq©—ëÜ3kþ$"4ûü?ì“ûü§ƒ\}RÖ_ô)ÇŽÿÿ~Ť[Vÿ¯þO_ÈTræ1ócçÿ±.¹óÿÚkÿ­ýO/ê™;¯ùsíÿË–¸æúfÎBuh®ÇŸ“”ùsÙ¥ëÿ1×Óëÿ­ÿÿ;íÿ?ý`^!¬^Ÿ;”ç4ÊõRVò€¬ÌU¡@A‡8n”onÏ=ÝBèmnîüÝ(ñø+s†ÚVn×õ'~Ž8Í—-ýá@_ Þì8ÙW~àðIDsoO¥·þò¥ŒIKæ”z^†gÒ/õF ¤²–º ÅK=Ýw£A+Ͼ›6c¸ Œù€[Úí x)Sþ×Ê|ÀJ=ðWùÛ~ÚXx7éÐfñ/geZ휺Ÿò%WÛ=Ïtî¥%}ÎâRÎÈ‚N› ûü¯Õ„ûüwüg¬îøb Â´ÇèŽÕÿ«ÿÍ^™ËÌ%;ÿaçÿØkÿ­ýW»´ö«ycíÿKg®ýÿè l }¥¾‰s|³±¿CtÍ3ùõŠ@Ï_r4ÿúä‹7²þßñu™­ëÿ?¿IõÛêÿgw_ˆá™«sí>¿®.ebâ)˜rWh£dð‰’9«Xú\iÒÝE>}1¯ÎÍ{ÇÔ#ïÐ •ýãðUÃIF+\´¡››€,VF‰/ ~îy麤£0 (‡‡42’˹å k^ßš¼#:rIÿI“§ôŒ¶÷ï|¾­§6Ä+«Ãæ,(Ë!h€>è“>ô}äm{´<46Î|Q±eºwíN©Ïí)®i½vO†—Wý[¶ò•­:á¾ÏŸ¿¾ÙþѾÑñ³ãÇÿêÿÕÿ;ÿÏêðÑ“BçQ×;ÿøÚƒ6⨮ýwlÔÚ`kÿ=ûڂͼöÿÚÿôÛ“ï}z騸7£F’Žfý¿ø|ÚJHûäê\»_ÿïà ÚH¿‰>m´þÿÿ?üÿ¼BèÁPüu4Û‘4X6þžô™.>èäW_Ï „éôåÓ¸<ø‰·êà“‰f6‚)ýd¾çS®|†®Wó„ÒèPUR€ÃmÓ¡4öxRNÐ rXÉ”¼Ê¸ø)7 ÔÐØŸ¢VþÐN|d¾î]£wï)W Ÿ³:38Ð8 ß|ó &y—™Z/éÊÁ§A>Ï& ˜´IÀ7¼¦,ôêÚzW&4âÐUn<ñÎýœïŸQUFy8 ûü÷ù§Ùøþíøv¬è£ŽµÿG¯DiÜtQõ˜³¥ÿ«ÿWÿ+;ÿïüϦd»ŒÑqìŽQµ?¢/Æ~qv¬ý·ößÚÿó#øÚÿÁör<ü²Ñ#tEuH|˜õÿÖÿ[ÿÿwÛÿ÷Âc(<+ƒß?“(‘  ÆÊ!M¢K™$ߥH(yñæ¼0Z âN ßÞY±3×Q:s–7ŽóuMŽð"Ç/.Ïðw&ß0y€@~ÉÄ_ùB;RúãȵtiYn:×ÊOy'^^÷o~õr U’þ§N©×%gëƒmâz¯ T4‘ç|çîqþsÏùë*.éx(S(M¯ËGzèfâ‹Ó0yÜç¹$ß´óÔïÐïóßç@™ÓGvü;þWÿ¯þßùß¹óÿÚµ­œ×þ[û_?Xûÿ€I±Ç¿¨®\ÿïø…ÚEXÿï,âXÿÿô‡õÿÿþøÏÓç+„©‚!&e@ Ш+”¤å˜x t¯ÆABDÒ<ñBÀ@ ^W^|ÐÌe;ñûqí Eé•û¢ëxp"®3i ùÀÚ(Šð¿öoškN¨øðöÚDö’I<¥=”îE›òˆ\—®õ‘§òˆÈ£-9½â UÞÒ—Ÿû,©š¼^÷R5hì^U|–-*7`ÖÕå-?û^Už–óýY~¯ÐXŠßçTyöùïóoŸÙñt…±cü GÑ!—îØñ¿ú¿ú³cgõÿÎÿ;ÿ¯ý·ößùÈÐ}¾\ûÿ¼9a®¨=±ö¿í[Öÿcc®ÿ·þÿúÿ.ÊùÁž~öþäÍ·ï¾ øÒ &`J–1¨ÇD’H+Peš¬²â)PÖyE/q“teô! /ùðÊfîÃ[yå¥>ס¶LÜ_£ÏÞNà _Á™l=ìÕPs? &€[& Nžæ“¡q¯\çäz×x=œ”áIíy皌•×Y¹Ù¨4@Ùó¯ÊIÛMõIˆsɯãÊ[:l‰ýt ïyRë+Sùòö™È@‘LÃGZãÐûjae{?_h¤,aÚ#ñûü÷ùøª/è›;þwüÓW«ÿWÿïü~òúÎÎÿkÿ­ý·öÿÚÿëÿ™ Öÿ;@5_“Ϲþÿúÿƒš{(FÁó†ÿüì?þÉ%Iººª`‹¸îƒÄ™qo౺ú‰Ó[À„ó{R¯=´&ü®xR9<ÒÙ' À$OÊ™³½º±žx×dQù÷ïgµÕÈIFAÿ}þúÆŽÿÑ}3®Œ ‡ëÿ×½¶úõ¿¾ O';ÿïü¿ößÚ憵ÿ×þgKvn¨#NÿXÿïø²Ú§í´þßúÿëÿÿ×ñŸ§ù§?zÈà R(Žg¤ŽÚÜ'~`hœ1¸€/„ÉÃpBšJ™¼†*ËI«#ØUDq‚&]>e]Ä9¾›UCY‘¤ K&¯ Š»—/¯ÀÔ— ÞÄ霸”ãì˜r8—FÖÿLÂG<­“$6…óúÿÿmüç釿üÙ›wß¾ 0b¢di4ÊEŠ›‹\Gñ^@àHZ»³|ðLP€ùç¼ÿ><Âszé¯gõÏ# ˜£Œ x)3p®ï÷¥‘ÐGŸk4 î;w˜U¾òw&GÁ ² )ûÞø¹dr¯*ò¡‡6Ò¥W¯^E„Ç*•‘ pöÙgŸMmÏÿáÓ²"ž³ÊŒ¼dOû¨ß ”+ü”-¿r»ZNºx ^Ú¿a˜g)/¾9_mB6Ò¤íóßçß~´ãÇÿêÿ£_éÈÕÿ;ÿ›>wþ?¶[ƒ­²ößÚµGcËê£/s}éO÷kÿŸ­9kÿ¯ÿ§dœÌØXÿoýÿõÿÿîøÏÓþÛ¿1јŒ8.@ ¿& V÷`„—HÓMÂÍD/œ×ؼ¢v€Jö¤š³k¼;á à–yoð“Æ@¤ h…Òš ”…ï¹Hº_üP©Ë9ò=”Å\ßù”W66Ÿ|ò(7‡ëy-Ðê,ÁН„)ç”t&#üÈüþ»#w•“øðêJ“9m0€y„¼¾7×VD •Í5ùå xBã¾å¶nyf“'û[ ¢¡ e©òì&±~i³‘eŸ¿}Ãöùïøßñ¿úõ¿ùaçÿÿõƒµÿÖþc+®ý¿ö?ßcý¿õÿÌ ëÿ¯ÿÿ›ÁHÌŽAl·ø§Àž~ôô¦ MÀ’ëÕ<ŽK€™48²@ÀN@•é°@¢Lb³ªG\ ™‘œRóå¿DÌ}òNú$±*J܈Á»/Ÿ†*I÷¥í+…ºÞÍJ$ò]T€&ò ¿òÔ°]y•ÍÌå™<ÊK^¯(ެ^ÝSN¨‹ù[¿0<òKÓðùnÀ,mª<ºä•' Ò)Ðõ½n×]KôµN|¤ã%äŽÖ 4òÀ€e¯ÜÂOÚ¤CÓW3÷ùŸ×V÷ùïøßñ¿úõÿÎÿ;ÿ¯ýÇ«M·ößlc±öìþµÿÇ)‡ÅØXÿoý¿õÿ×ÿ§þ±ñŸ§üûŸ¾)pR#}´ÐÐiG,€ôx9¯«€ä{ñéqn€*î­€²pÆÞ§k¿à‹Ê¯Æ@Ïd¢\‹ïÊ#ü÷¼xº7‘¢Çüý»çUa Ž4dtøÂß„cž_“”'d5Ö­€O¾Ò8¯Y* àÓWÅ«§‡TyûeÅÊ Lºv˜œÉm¯ªLž®²ÉÒ=¯\+»¯(ÊWÚIõ4ÀàUÓ´CŸ6 7tÚN÷nêU¹ñnî²ã/àõ(gîq”'r ~®¿üêË´½Õ[Ý„]¼W×ø8´¥³¼‚Ú¹uogr¯tâñ}Öûü÷ùïøßñOGT'T_Rj«ÿWÿ›Cvþ¿œðÿc?oÙìŽØl‘¹gç¬ý·öŸ¾±öÿ±·×þÿp!Âúëÿ™'Œú"çõÿ×ÿŸ¾Ððßž~ú—üÆ—ñ¨ÇŒ H„Á$œíżvæLñ0d :\7}–­³n(íÛYµdƒsKJÓ9/¡ ¦àñÍðó‹¥|øƒcÄ òˆWöûîÿ4+¿|nˆ%´Hœëü!ýä½þ©p§åãwÈ.@è*W|Ê2û ¢<~ ¨<ò‘ѤŒ¿’¼÷~î¦á¹é0"Þª/«³ðL;Í^Xøj¿o¿9_¼…÷ÐÍ*3úð˜xáq}•'Žü÷º‰ìg¥>Ã,üBg®i7¿ ûüÏžbûü§ŸLÖ¯wü±ãõÿêÿÿ3QΟÿ×þ[ûoíÿµÿ×ÿ[ÿoýÿõÿÏGÿà Á5æìeð† üçé§ÿáOÞ tôÕ3[Þël<æ_Áiö«¯¾ `Ó•MÒ8¿SæÌà+8VàÅxÂ1ž<Îÿ h„)@t€0`L–˜x%?y»R€l)ç{ÐyÕðåúMA~ewOy µ=ö ½sålš²œt€¬ið ó‘å”-¤þsv¯ñԮꗸ¹¯³D–æi™>>¹¾Ëw§‘–c¨Ÿú£}„§¯Q6_Îê9rµœ}þçÙïóßñ¿ãõÿúxõæ”ÿwþgݬý·öRXûíÿøüœñiÖÿ[ÿO ø–Îëÿ¯ÿÿ‚ÿüü¯þÍË^LVJµsõ=d{Z$êúX€,®uJ“–Wà²GÔ¬"\w¡w½±†FÐyD¡¿À|¬F’fiº²äs3y ê4¯µNÙ€þ¢Å°„ŽÒ´ZL^¼qB/Z.שÃ%2ë°ÞeÿIÃK›L&"$o®|*»è;/{k‘Qœ:;-Tc°²O#¤¤“M}­—x¡uÀ]_+´òK'Dþ)WÛûüÏd«=öù¸{íC·ãÿY;W;þ£cWÿ¯þ7—dÞ™¹pçâðóÿõê±7´…°ößüغößö'=²öÿÚÿëÿ­ÿ·þÿ3ØG/ŽÓñðÝùëÿŸ=ˆi˧þÙÏÞpRóšÝœ’ckWÄ¢t*i”³¯³ aŒ‘#s ™æ‘"¯£“R{#$°Šèö®+Åj©¢õʰHzxN9âm\^ ‰ òª”²È§tî˯r²àMÏ:™Ý;‡çä?5JµŽLøMy -#÷ÏÑéxäk:~äH{]™••ûICûýi—¾©Î€A,K£\÷ê!Îù~`+]9i)_Ây¬¨ëþiï©ë>ÿy.Ó^ûüwüïø?ÀŒ±°úõÿÎÿgîô×\š&36t~ÏýsôÎÿ£?Öþ[ûËÖþ_û?>Ïúëÿ½°þÿúÿ'üçgÿñ_ÏXÏ«©€Y^¤#@ˆ• 5!ŽÍ¼€"âJ ˆ$ÎÀ,XÐdèchåå)ò ì>t¹¾ Δz_D‹ ŸòoyxÄÐyY®¥9Ÿ|g…•küħœ9wUøÈE¤C3—ˆÅư¾‚øð¾ä!\ë”64N'Ž¡¿òMðòÚ@Y.FŸûÊ‚Þýã<×­Ë#.©Ït•¶Þ@2i¸: ×>ÿ}þík;þϪÒÿG­þ?Š5sÄ\V¯Š]ýV;››Œ—ÿ™ùg®žcçÿã¬kvÏÚkÿ=ͧkÿ§ 2—¬ý¿þßú3]Ž=õ{ݳ·ëÿ¯ÿφ`gÞñŸ§ýòço¦¯ÄÀ8›£Ÿ/ê!vX%eCq€€EGbֱ̻l°>¹Žñ6yÜ댜b´Ž1Îòámóp=׊#eÈŒ³04• ½òúKÎëW¯³K¿üÒš._q›”÷ËjÊÈà˜³8t‚39"›UIs#kdða>g´ºšæQÖ1Ü?€É<³4¾)ëT%÷‘ïá'Mû½ýúë¤Ùç+y4̪¸©Cþ Ÿ†”}Ý íÑôÿ‘yó*Xêì~ùÛfÚÜsÄïóßçï5âö‡ô•ÿ/;þWÿ¯þßùŸNt˜gwþ_ûoí¿µÿ™÷æ†ÚÞ1 Öþ_ÿÿ5>ÀV¸ûjëÿ­ÿ¿þÿßÿyúÉ|…0£kþ6@ƒ­€•ô8³“ŽF(jìÚƒèQp¤ˆi ½÷ßMÉ¥—ÿù/ÿ%yA2y f`yðéL:°0Cš¼þ6|BA'×´&þ>ÁÔð$sÊ ªW¬ùìçÕòk´¶~òMkDîœ'“´{;à#îFˆ¾Š‰Ÿ:ù¢ã_|º/¿ü2 ÓK+²&ÚC寞ÊS…¨¬¦“ïã¯;г KÈõäAß ÿ>ÿ³™>²Ïÿ8¬ú‡~¢´?ïøßñO‡ÕyÑEWyèë¡1–VÿOC­þþØùÿùDzÿÍÆˆYûoí?6¸yeíÿµÿù7õ¿öÄúì®õÿÖÿÿ}÷ÿŸ~üçô†sêÝtB 4 †ˆ3¡˜X:`ÐÜYéîóêÛÌàY>òõ^œF—çõë×9ÛHÝ}ø¡<]Ëkß&A¼àÕ–8N7À ŸC{^gðÂðûuS÷(Ñ P âª»ÕP)÷v\+϶GLüy}äcñØ­ôæ ­ò'®áNÓ¯+âïõn>{aåßäK†¯ ýÊÿÝûw ÷lîªy>sî¦üxk‡# Ñê´gà ÿ}þ³pŸzOÇmúÅŽÿÿ£ƒVÿŸVÿŸÕËæ‡`^q½óÿ™«;?×ÎéœÆš?;ÿ¯ý×>²öß÷b—kµÿ×þ¿ÿÀÞù%þÏú™>:—/ëÿ °þúÅï«ÿÿôƒÙÄÝ`¨QPh@”¨Là§«ÄÉ×`ò‘§N¯w»Ñz†0dÌÝæ@ëËwÞ‰G§Ü»Â»ï‡Kã@ùµà„NÇ.å]ò’[>ô©ßUÇL’ʺxŒŒ^•$ûo®¯¯E¾IÂËFsò~ŠÌê72 îQºÃÏ«Œ‚<=ÚÖÒžÿ}þíZéoFÛÅžûÝŽÿÿô=¢/¬þ¿^5[ý¿óÿ¨ËÎí÷¹–u¿óÿÚcl=ú=ºößÚÿÕúÃÚÿëÿuÑÁúëÿÓ ëÿÏ¥Ÿ^¯¬ø uD2XÆÈŠsý×d- ƒãÒkô®½ÇÍuüq#¯ ®Æ›_oïÁj)ˈ#Þ“O•ÑÙý«YÉ…—àÞµEÊ Y‰ÕÔSæÈÑW ¤3LVdõµ=yÉÖ=ð%5Ù Î\§Œ«>àúÓ:’ÝáÞYù®+/r¼•ÕM•£ 4-K]‘…^hZn†à´j£¼R‘_hYm[ñ‘kdžÌ¹÷ùïó×_ÚŸ\ë+ú¢þÒkýÉõŽÿÿ´þ°úõÿÎÿ;ÿ›;:aí¿µÿ¦#dõf:Åõgíÿµÿ×ÿ[ÿoýÿ³€È”¹þÿß‚ÿüðÚÄQÁáj`}²úÄ_iC[§Dž3@(¯Xpf¡ƒüCÏXI~!Oã2b.pÇ «¼÷.ß•˜‚OÂäÇWÞ:ËsóÉ»¸äÍëˆÀ¨á÷âåùò`^3pJP~ëåþñºÝˆUù¥´òŒŽ‘u=éäQ~øe‡æ*'<†®m)Ë~¤qôoüÕ[P_á‘wxyï¾}—U Ê–n°¶½<‘vxö,N(¨p-™„žÉÖr] ççzŸúÏ>ÿéW?ÓwÚ]ïø?ãë>–´‹£c?i;þӇ蘮h]ý¿úçÿÿýð¸ößõ£âÚkÿ¯ýÏLਬÿ7o5­ÿ·þÿúÿg±?ô±‰ûÝé:úb¯y­îôŒß L È1ÊD0˜8ôœgi®&hsî ¦òwVðqì0áüÊ+Ÿ} *Õt¶–/"æzÊâü}”Û_l@ߨÓÝ}Íò#Sê»ÉwxÎfð“§åt9€"«Ž¤“-ò#e’ñvICW°'é'¤Ý枓׹¼Bpý©Iš÷Ó&å§!Tùúâ<u*ù„Þ_ìeÜÓ›æ|—«×â#Ç>ÿ}þÓWvüïø_ýÿЧ«ÿwþßùí¿µÿÖþ¯ïÌn®½¾öÿúíõ­Ü{йiÇÀ>ãwMJÚúÇöÐ.ëÿ¯ÿÿ1þóô³ÿø¯ß::ˆ@éö:Ëytœk°ep¡¹V”â:]àšÐ¥Ã]¯ÝM|W=h‡gÁ"|›ãï‚Xh¤<ŠlSH¿@øâÎÈ=³æþÓ ª¡—·õr,ÃÓª-Qù—ι×À«€sžÙ«“’zD–©/9ñpHw¸n]‡ä± }®oi-ÛX6â\ 6ºÑâÛ€·# ÖDVé‘í"ß´ÊÓ¼H>ίŒÒïóŸöÞç¿ãŸŽÙñ½`–Xýtoõäê³þÌ;æª9wÎñã‘{ñ;ÿ_?L{ÜçôÿO{¬ý·ö»´¶·±×þ_û_Ÿ¨Žt9wý¿øxÚãcÿm¦—õÿÖÿç¶&Ôs£¿ôÜëûÏo›ÿÿôÃÙÄ]%M0TRDY¸¹‚Ée"_Zq®UÜ+ò‰£tÊ·Æ+6å©ÑÈ l²ÚKpïÀCã¢w¶?”³räŸÆžý æ”ý¬æÞøõ×_`,â+ŸÃÊ­¾¢Ø‡ÉIÅKzãÈFN`[ó·näM›ÄjŸurL9yâ*¯uÖákO.<?e¶·‰{„‹6õ>ò ‘ß©/ù+“4ü*·:LEr?5~¤eω‹Vž´áÐáãx䟴ð@t…ÔuhÅ—Vœk|öùïóßñ¿ãŸN¨Ž¤VÿOŸ ÛWÿ?æ”Ì}Ó&úÇÎÿg‚Ýùí¿ÚZÕkÿ­ýOG®ý¿þݰþßúÿð…õÿþóô“¿øÅ£À… S°Ì`ĸl\Tò«ª×ð4¦UL£ÐÏžT.ZGùÞÏâ)ŽïfϬW/ϯ-Czý—ð @2{[õ•ÁðãT³ñ×óšàË/³*‹ŒXî<½J˜ 03¼K‘mÚ ØŽ)S;X¹Ei¾ H†3¹ Õzâ“z /×\Ë_º‚YÒÑ—§si|9Ï5y\kó^Ë_¾¥k‡ôÑJžYiµ¿ÿÿ3rvüG%Dç¬þ_ýo~Ùùÿy®žÉ3sûÎÿc/®ýeiŒ¬ý÷l×¾¬]»öÿ8Öþ_ÿ¯>ØúëÿÓ0…êI}#þüúÿÙÛœ/Vœ¨ñô/þôGo8ê ®Ì(xèX 4`޳£lRút_!BÆîÜ„®KÅÝü:ù’>eã%°¤|‡ý­J+½e“Ó}d˜môÚàäJÛå~$™´¤<èí¥•ú§ä<ÒåCß‘}ÎÓm³Ê¿Ïÿ€ûü ½ãÆãJA3chÇÿêÿY};ú·úsõÿÎÿlÿÇ›q¡-¢3×þ[ûoìO¶çÚÿÏ[—kÿß³þÐúëÿñ±ÇÙ]ÿÚŽ€Uü>øÿO?ú󟿱r©€ß« G€Ž™@(+r4 :€PÈ=CÜ$#Þµ¸FîO8`~ö®b )s€`Œ|-/€Ö¤·¼–á^Þ¯¾úê“Ï>û,« &SòYR'¬¥/¸òrV*á-¬yî PüúþÈ~SÖdK^ùÚ•? ˜zœÊ WŸCÛÀd•ZÁ3õÆÃž]Ê!O@¨97Í™¼÷à^< Š<‚Él"C«Žï&ž¬÷ ¼¶oxkóÖoŸšjŸÿéSúIŽ—ö}}gÇÿÑ_;þWÿÓ÷«ÿwþ7ïü¿ößÚkÿ×î^ûý?öòúëÿ¯ÿÏüCã?O?úåÏߌå‡@âà¼6¸çØûÄuÚOÄò‹À¤În«$C0åW*¸´üRöDˆÏ`¿;ÏgEÇ»÷^c™æÏ/¾øâ“oFi6qÿ„v®É@žÖƒ¼^”°A×zC|ë[§•úñNÐG¶ë\ÇU^AšÐvÈýdUgξÍß_ÎYº4qê¡í*>r*ošÊ"¾ü¥åµÇ‘ƒL•SÓ”wùHŸÈ<#™ò„ùÑÉ/Ãuƒ{õÜç&"ÏbŸÿìG°ã?ãÂ8éø4n:Éÿ×—^G‡¬þ_ýoîéX1n:G™mÄ;:†œéÙÿwþ_ûïÙf^ûoíÿÚékÿ¯ÿg]ÿoýÿú¿oþÿ÷þÓÿóŸÓP —æšAi…O6FŸø.å-‚FƒuÃôÏ?ÿü“·oßæë~Î5Fѹ.xâ¨cõQÚ¶4êÃW' J“G¯ÀН ¢ûÕ_ÿê“ׯ^ŸüCsÉŠ­{(Ð¥ O'åx½N›r#ÄÂ@IDAT¤|×׊,HúD¦¬=6—÷*Zqá7²0ÊÉWKÙÒ”KVeÆ€Ÿxí èë‰di»Êãðêç h Z|\£s/Ý}ÏÒ•'Hw-ýEVÏVc©ÛyÊ¿}þûüwüŸ™;þϫܫÿÏj_zrõÿÎÿ;ÿŸæ¬ý·ößÚÿãO°½Ç–^ûÿÙ—0WÖ79óæúõ¹Öÿ;>î8žëÿÞ0Nøçp•õÿ®ñ_ò+ŽÙ4œÆò«ç\<× ¤”#úJ“²Œdcñ9ß›aý@‚¾¢/OçÊàÚw(»+•¬¢Rþ&K¯ ¾È '›¶Ëkçˆs/”Ää”.NÀǵCYüIh@#éBÏõpxÎþXSŸÈ9_Atv/àõå—_†½ iâsž{ôÚ웩 YÜ[]¦>øãh(ë&«(4£摜6+ø¤_õòÌа:©“ŸÌÚöÊ7ù‡Yê6e’ù/ó•¶ÏŸ¿>ªìøßñïúÃ=D/Ný±úõû†i¤sJûFV¸N?Ñg:÷ìü¿ó¿þ±ößÚì óËÚÿÇ‚Þ\ûý¿õÿbK¬ÿ?FÕåó³ø÷tÄï¢ÿÿôƒ_þì à#TÙÔXÌ4Üš,€*^×Ó9bT ÒмiÙ?ÊyL6âî 0Çž:Ž{^×½/ï:;8 C¯œ/‡\ #4ú®È 3 ÝTZ€¯ÍM°âÉ$HFüÎö¥Ôó€Vi‘ð•Ÿ|è+gx^ñÉ8Äáå×y›¶»'sh'ýÕ«ݾ={bi›é¾«¿Äë|êw¶óZ…ö ¯¡O{;_ VïÔÒ+;#äY…6«¾ðíÆôhñË*´y½2ÿtpååÏ>ÿ}þ;þwü ºúÿŒ:wõÿÎÿ;ÿŸW‚c0°.ÛÁøXûoí¿µÿ×þݰþßúúÂúÿëÿ×^ø‡Äž~øg?{SÆÎŒ‘ìý4× @ g^tt?§=ƒvˆ„@+0¾þúëð:ÍE-BGð hAï^çNÚ¼ª'¤ü‰+@ƒg—äúeÿU^{ûõ‘eî•A¯ý½|ùê€NÊdÿ™‘ J4|æ|Œ¬ó:dÊþÊ4éæ<ôh#ÓÄ d”&.m2gõ.šÆ;?vdÔ&‰Çc.Ÿåq³GÕ$x]Q(o²;Â÷°iRÇÈ<1Ý@¸N Ê/¿I/üWy1’wèiûü÷ùïøßñ¿úõÿÎÿ;ÿ¯ý76ÑÚç‡ÞµÿÓ¶2Û~íÿõÿê;­ÿ·þ¿¹býÿž×€MÁ_þžøÏ|…ðÞPº@  FL@‘‰OÁs °"ÀÅu˜¹€WV4õ>̆ÿ*øQfe’³ ‚¹^%Nª2ä-Ø“=­.ð`¥üɘÍ9y•À5¯ý%ßä/ WÏžxÊŽNYdÖäìy¢?h÷Ÿ¾˜Mßç_éðT|äó+ˬöz®ÆPÀê*|Ä“_ð0²LIóŠ$ÞÔg¾Bè^Ýt¿zÅÉ‹Y’†÷Èè>eOzeEKÂÞïóßç¯Ïè?=Ò·®1âz:ËŽÿÿÑ)”ÇêÿÕÿæs×Îÿ;ÿ¯ý÷lï­ýã2ö%ÛÛtíÿè˵ÿ×ÿ3.Œ‰õÿÖÿ_ÿÿúÅ`ÕYõ…“LŒ‚?{&^šÐÉy/y91/¼ún6÷+-#Æ9sÀAÞHîP&øÇj¯@)Çq'¯ÿ}þWÿÒ/vü|ÇŽÿét°úõúyæ;ÿïü¿ößiÖþ[ûŸ^<>ÉÚÿæ m±þßøg×GÑÖÿ[ÿŸ_±þÿÁ Î=‡øŸÁ`Q0³@Fîç‰Ò¢XýÔWù²Á8 èRÒvlšþêõ«6J«À þ€–€+sýéÓy49æº<åå.¹œ{ˆë †ŒÎS`båí*®D ‹ÉýØ?K:ùäV½'Ÿ¼ö"“½±Ð4BþC'Ý5¹Z/qî#“øY †·ô¦õ—†Žýº€nÚ¦õsVkÀ`¾”?qå¡uð-ð%OÛ+eÍ=Úü½ŸÈÜOÜ#”æ·ÏŸ¿~¼ãÇÿêÿó# }¹úV\]ó•¶ØùçÿŒ‹µÿöÙÚkÿ³±×þ¿VÖ¤-Öÿ«Æ7[ÿï¬^×9.”M‘c&í%ü 5±?y£kù¶“Oˆ}Æ/¿h\¬ÿÿ»éÿ?ýä/~ñà éj¤vAÇúx–ÎÄ¡q²0™ûJ °"?¾í éXSVÏÒî´ý͹öoK—ß!äïÈÒQ_|ú"å¹—æWA/¤"‡½¨V÷€™ËS}»Ê Æ99ÐY0pZ7÷èMʸË^ž§´¦ ´Oø¥=ÎëhòëÝœñ’îÞÏßXµ6u10 Hÿå’žø<&}î½®‰°¨fd#ãU†û}þûüõåÿÑ&Ñw;þŽ¥_VÿýºúÿŒsÆÎÿ;ÿëkÿûkí¿µÿ×þ?þ‹yrý¿ñÀâ³9sý¿³Øƒ¯É'®Ï©„žssÝ‹k|ÏÒå¯_Öºõÿ¯,Ó>žü¾øÿ°ÎÓ5¦#Íkd^_+à1]%«¥ò*Û¤·óÙ Ê{»î­"–\ÌЀéWï:ˆ/@¥vÂdž?í¤ÎÚ+±inåËÙ¸#>ΰÇk{Wç÷0PéàCóÙçŸ}òÕW_=~5Fg0Õ9ÁÃÑ&^~¯õ„ùÚ^ï¸{”1ùG Ç=Y*ãËùâà$¥|<åyúôLöhÜSö€ª‚cœåIW¶&õÅÄÜ_ò(= Jü0J³’=÷“®ÞÃD`[°+Öþ[ûoíÿãgÄξlyöulj±²öÿl‡2>‹y”¯‘öYÿïø]WŸYÿ/Cæô¹ÔG}å$=Òîcë`ëÿÿ>ûÿOÿâOôætP¾Ñ¿Ó5f9¸ø§yÕxR Å* û-y…€Rò œ§½ˆNç+`dp6=Êkz ÞèhO™é¹¡-Îz¿vßÔ‡Ï\v•€wJÉþŸ×/ù>–ô~ñÅ±È Ô¡iPor7œv8@ַßÌòà—º½ò†ÙC¦¶)YÚ.~#ƒô{¹¬ð"ñ%+Á†ŽŒÊ)XÚ¡ #>òµÒžWAâñJÞëIÒvVÛ¯ÊûüÓûüwü_Ã(ý¡@ÆŽÿÕÿôéêÿÿwþ_û.¨ ¶ößÚÿcŒÇ¯M½öÿúëÿ| >êúÿëÿÃ&Á+‚9Œ·5…>Ò~Âÿº_×s.þóôÃ?ûÙLÉ<À €Ê}ž)*9Jg¹4„’þì³Ï‚°( H4ñ½WXâ.à »ð½vÎß\æO+ =òM“vÝ{ÈKVk‘¬$"cùÊCîÐÌùóÏ?\ôácÕûóoV'ͽ=°ZGõÖ:|,[ò^r–oen`„ ÚNšv"¹n¼ry¤£7$Yõæ¨*ƒ³¶«lÎBÓS¾ô¡k\Ä ­C¼ûü=å}þúãéWÓó¿ýdÇÿÑaGÆVÚ‰î¸]_S¯'mÇÿêÿêy}cõÿÆpþæ2>c½ßùçÿô…CÂÚkÿÑ«,·X±kÿÿ ýI·®ýÞZÿ/Ý#j×Ó§ëÿÑ þ­ÿ÷Ûàÿ=ýðÏþFÇõȬNª!©SgBÃÒRa¯ºouèâu<ù¥¹ç 9e¯¬‘&ŸWèœÝ¼‰12ô-˜†/¸®ÑEºð7‘Í*/r4ÞÊ,@9]¦ªÄ²Y¹×&ÕmäµVVZàsÖÌ$é~Q™Q~Údø?M=„´áE‹®qdlûTNƒ?õºbÌ5ùåwT~æ°eاìÉëܲÀ¸™|his!ý@2C2ù*ƒ8¿04¯”@³fJÞáñå—_ÄR6P«€y[wgåœÝ÷¡é›ZÞœiÒ*ù}Í0€Ó0iÎÀ¨ðœöœ‹l*ß/¯vZNkäþƒv Õ³q§ÐüWrÚäž}yvÕ•{2ÜéÑíóßç¿ãÿìûgŒ8vü¯þÌ7ÓVÿïüßù3sñô‰ÿ×þ[ûï#»uìÉ3>Öþ_ûÿø~üú$ñKÜŒþäÑÔÿï¾ç¬ÿ—öÑ~SÓ(ëÿég1Èúÿ¹ûól!ãl®¥ý¶úÿO?ø÷?} çfhQ±îu¥²îí)åÚʪ6DÀLƒA$ý~´ÑLèI¿T÷äpö•@+¾¬KøÈ|w˜²I ô~E<‚r<˜ofµÕ«—¯ûå˳J ¿¨:Ü”ïÚê¬tü¹N˜såït^STFî‡ÐY¾÷ïÎê³Ôñâ/ndk{iGð*+Ö†Fã‰ÆÊ°Gù‡¦ôá¡Í†Ne9‹WEßëÜ_e¡ëª,ñ­¾îÃk®×ûü§!ní´ÏÇÿŽÿÕÿtåêÿ3?f.š9cçÿÿc8ÌŸÚ>'ÆÊ;cí¿³²S[Ôž[ûoív&›{íÿõÿÌ©ëÿ­ÿŸIsô‚G×ÿ?Jm‰™~7AÇ·+®¤·ŒÊ‚þ»÷g5QÔ ¨V@ /+Íð>©|Ä%ÿ\[õÌ"kÚtê(¯rLVÀ@Aš€O¯É%$_Û`3õ°É¯L¼{ wvv-â âç¶›ë€gßÿû öùïøï˜Ùñ í`|Ð_´ =âzõÿê}CÐ?Œ›ÌAsݸέé?¿óÿÎÿ,”ö gúdí¿c ®ý·ö?ݹöÿú|Þølëÿ­ÿ¿þÿÃÆ4&ž~øËŸ¿¡(TÜ¿~ý:` ¢6ˆ§ñÞ ó|Æ•î æÄ,w.‚þ¦Û61œ!F/#øaÐ\ûñ0x'‘e|hçºåU®²E§¼är B|ËÈ„0u•W=ìa¼)/¼åW²h‡{yÊ@n×c’g¯æÏùÐ.œÄÒ~=+ÌxMYÝ'Ì}Œÿ¡Ìô¸Nzy¦ý¼:¼Á‡©<ކÜ_7i‹¿…FrʺÚuŸÿ€’ó\ÚÖûüwüïø?c¢º1úgõÿêóº9ìš›\ ;ÿŸÕÐ9{çÿµÿ®±1ÆVƈ±²ö{>Í‘?µÍ×þ_ûŸÍEv?æø/ÆÎå§ðY:ßÔ.yô$is$Ïúi–´Å\Å'ÔŽ·°þßúÿí¿­þÿÓOÿòßÞäá•£B98Ä«ä]i¸×ù›/t³â‰Ò 3<¬Bc%TöźO’Bæ>éÀŸá÷sdzºIy†®²:ôîñòäõAFÂÐù÷½yÅ8Ô•PŒju(¨ööíÛÚ­s ñ(ÏM™”&è‰÷ßUM—¦ŸÜK+ð¼êÐ:S²®½ŽvÊ|nO¼Ê#?røuòŬn©·•giÏòˆkýð(Ï;¿^ãÛç¸Ï&Ïi˜>»}þ;þwü¯þ§+WÿÊ\o~3§tÞØùçvÞÚ϶[mˆµÿÖþ¯¾dóÇ6g¯³Ñ×þÏâí³þß™Oë«i“×ëÿÖ WµEûÌúÿÏ‹WÚg¢c¦Ú§z_:÷Ú²vÜo£ÿÿô“¿øÅ›VLEZYF©{l\•L:Ídjºý£/YÍ4`QãMçò&ÿÜh¸Êì꬀-C—!k°ÎåAë,ÝÙ;ÁEæÛ‘ÅÈWPp%>ÜÔʰ‚W@¨Ï^€®òþš_L³ÖðRæä ÍœñW~Ó´¸.{ÿöÝ·§îbxµ íreà†ÿ’rº±û½L´ø‹ó<òã´‰:uY)Þá1´¹ž3úð¾®ç”ps]ÞM'_iöùïóŒãé+ÂŽÿÿtÌêÿ£Vÿû`çÿù2ñ„ÿg5ûÚ:3w®ýÇÎ]ûíÿõÿ2Q°§/ß6¾Ûܯÿ·þ¿y‚ÿMOÔ—¯¾þÿߎÿ<ýðÏ~ö0âÕ@Ç 4ÀI'^†º  l’Pi†—ÆÁy×W݆&á:¹îƒB+xÕïŧ/2ˆÉà@C ˜à~þ$-éW\âÍ“Gº üòV¯ÊFV¿z8*™åµWUdW·‰«!V>hUâ]÷+‹ò;âÜÀF†ò&K_«'ÇðwFò ¨uÉݺX=†ææR¹Ê§èlpï^˜ÒÆ6x¬Äµ¬ðCsk·¦9«öùïóßñ¿ãŸN WèºÞp¬þ?:uõÿÎÿ;ÿ¯ýGO®ýwìʵÿ×þçÿÔÇŠµþßÃ[ÿoýÿüïõÿxD±•¿þó}à…ðÊ&壈€T&h›œkxq}-нû¹¬òê4Ð˫ׯ§<ðiÀ_p– P†ãÔøó¥ÀÏ>û,«´†`þ ©2XhҬؒ^EŠGÁ¶nìN6Àüò)[ÝÝ£½B®ÅIky­³|÷8Ž¿ ìÒ·x´ñ¤ÌòŽöÕm·¶ÑÉVŸÅP&óÔïûS?í£ìb°0iÆ5Hw|¿kùZæ>ÿ}þúËŽÿg@xÇÿêÿÕÿ;ÿw>§Í—‚ùS¼ nçÿµÿô…µÿÆ>¿¶ Yûÿø1kÿ_ÃØp4ÔGq^ÿïø×Ïúcý?ýbýÿ³¥cýÿÿ:þóôÓÿð'oÆ*Ë.ðÅ`²ò©\Î×¾T5äš&¯8N¾ÓàÏ¿ÞSZâ˜&¶Ðͽ€f£õ*8é)cHÈ‚FœCW€HÞ‡³ie^“~—Gþwïç+…“þêÚ˜4ò˜ÐôÞj¦8/“¦L€‘³}²€r}… M™=ãc¯*$òõW*Ú¦ZùZ~ëêK®•`JY“•¼y5Ò_óO䯮ïY „‘ Чpñê“ôáI&{¼(‡\ûü§ý÷ù§ê‡9vüïø¿ô$}Ó~AwÐ#ôÎêÿ3÷¬þßùçÿc_Ðô‹oí¿µÿ2OLÌ!kÿ¯ý¿þß™/ãcý¿ÑóŸ/Ú6Ñ.Býf×ëÿ¯ÿÿô¿ý?xãëƒöŽÒ!8îcqd¥¬šAÅssHÈ4ts^t2ËÁжóÉÃ|éê§tÄÉÓ•Qhñ@Ý´y›X!›C\伜)ùÐ;ëìÒs=´5›úÊ Cêãq ?¯èÅкêSù¤‹w²9}ʘ²„¼Î÷t^ïs0 P5×è"Ûµú+åœgúž8mÕ2'\õ@+´^½Ÿˆ€h^¹Ä?ñò\ùÐ?hÃaä¸öíB¯þd¬bSŸ}þûüwüŸÍÊchÇÿ|IÖŠÑK§Ò«ÿWÿ›7:ìü¿ó?[‘¾¤œ×þ[ûO_ #Ìkÿo²öÿú×ö2yÇ$:aý¿ç•y™CÌ%Ó.Õôˆ°þÿ8ÓæÚñç×ÿ¿ýx6q×ab€Ì„cÿ'©@#UzA‘\—åÂÓáÐM†ò݃ûtÌ‹§ë8Ashr­ø)0Õט²jiò(Ÿ.Ÿ×óZ!yð‘Fn¿x7ÈKõð?Ø”}ˆð¹‡ &zÔOz?s\Ð HhâÐ…ÿ0€’Çxr}1­ÜöJy“׊6ûW¥‡–졽–]W¦”O†9ÐôPvó’KºüäAÓ|÷gUx£‘_žïæ,$ÏÄïóýÚ&¾d¹ÏßJ¿ÿ;þWÿ¯þ?3åÎÿçUãÿÇŽZû/¶âÚkÿÇ ž?±é/Û\{ÒܱöÿñiÖÿÿzúlý¿óÆÏúÿ4Å ñ?Gg8×÷w^ÿÿüHö1þ“MÜŽú€2* Ç€D®­Ì¨RÖÄ6÷3 ó'­¯¡ûòÊÚ-ÐS¯Á5_ʺ¯L@•IÌ ¢4sÝ3®»Ãê,tßÎ+Ù·i®«B?@•V®í‡•ëÉ(ëׇÍ#¤s ð%ý믾z®ËPàAN4©ßÄ9‹nÍMîµ8P-t÷|ê-¯Ä·®Îw° MÛ.m%bx5ÿ¶‹2+OËj¹ïG­Ðüp<õ°òêJLø¥ûüÓ,ûüÏvüïø_ýæ¶êÛÕÿ;ÿïüï—òµÿÖþ[ûíÿ™ÇOø"õ7Öÿ;m¢=„õÿÎ|_sú {JˆŸ:mÄG¯Û3 ­çXÿýÿQ.ÿyúÑŸÿѨx ŠCG+(âWW÷] ¥CQVâuàU÷­‚ÆQžé𓞼VFMP¶ÕW‘ûâÿ4Wž_ϲNŸ¾ÆÓ†ñ_~õå'Ÿ½þìä½ä1ˆ(ÁÊ¥ò$_CÜ£îM¸Îd°–_b”E¹«SV‡Ýhñ ß‘÷´ˆ{–Yâ-´\gÏìí7o³¤?÷êØ:;Ëý¶W>>ûü÷ùïøßñOÑ#Ñ·£;VÿŸˆ«ÿwþ7gîü9¨Ó솵ÿôŠã„±­Öþ;?¸®ýúEÿ®ý¿þßúÇ®4o¬ÿ¿þÿ?þóôó¿ú×ol¢§cÅaÇ%û=q`F: < º õO¾'{’6éø Ü›Ü[†ë‚,:sçžÀËä Ðs•#þË/¿œ/¼Œo¿þúÃò‡^ySXöwÂOþ–í,¨ƒø®D­C(èƒäHw­ ­ú¥œY¦ŒZò¨³Ch½»'9ïí¢ëÏiwMÚO¯´Ù‹‘5fþ ŸÖMe@'¿ýÅ®zDÑS­—¯^Î+ûü÷ùïøßñ?ºŽ.œƒN¤"Vÿ¯þŸI$sÎÎÿfÒ³•€yuçÿµÿÖþ[ûíÿkÿÐÑ~ìÑŽõÿÖÿ«¯\ÿT¿¨\?•ÝŸö:¯ÿ_»{ýÿÿþóô¯þÝOßèHtðˆã2Ì=et¾\w€t^EÓár=dybP2ù Ö8÷ºàKò\`KãœÑUé1Åõ^y>#É™ò:Ë?ÿçÿ<çoçúÕ«W‰/ß–7™± °ãÔøòá#?`J]ÔU0Ø~õ«_ål¥”°¼”Qåìºѹí!¿²ðsNžqí*Ž § _ÀR:iýò£x|Û6øÇ™¼Úª|ÉGÎæWެB S®úºI«lÎÀ+ù÷ùïó×ßvüïø§{Vÿ¯þßùçÿµÿŽ-›k쥻Ý'ní¿µÿ×þ_ÿ.XÿoýÿøÔëÿcÐÁ#ƯŒ‘|M¡‡yÔѸÞÿ÷🧟Ì&îˆ1†ä¥: Æi¥ñ…=¯çÙäZ\Þ!¡#xŸ_ïƒWéåi9ýbŸt€Œ4çVêâZy®å#GyÊmyè²AùÄÕwF'ß4Üd–?aÒ€;^u|ñòÅ'¯^¾Ê5Zùr _AYò·Ž4»I,@ÓÔÝ?«¬ä´W刬“–öA{µ¡¼Çaxþä ‡KŽ{=ñµß•8Îfêx iêÒ2ÚFhŽ1J‡&u›8<\ïóßçßq¹ãÇ?="Ð Õ«ÿWÿïülœÿ×þ‹n¹ößÚÿkÿ¯ÿÇNZÿoýÿõÿÿiðŸ§ÏXÀËáMÆ@g `€B1‹wÄÁ5HYC7ò¾æ•]•9Þw@ èòéPÒ­þ1à9ËùÅâ”)¨²LT–£:?d›|¥kYxTV´Y¡5töœ:PÒì蚂𣾗¼äa”þõ_ÿõ'¯^¿~ÔÙRØ€VÓLdÖdqmcyuöN¼Ò&­²V>´>Š.í;÷á7|}éÌç1•#È Ðroå™kA›¿€¾Ê SÛ¤Ÿ³¶K^üRÖõÜ>(gxîó?ýqŸÿŽÿÿ«ÿWÿïüo¾tìü¿ößÚkÿóMbCM½öÿúëÿ­ÿ¿þÿÿZüg^!üÉ“3às…]°CZ"ñ@šîᄦ|йu…•P@¤ ú‹6«ž.àGÑJî^ouaÔ øÊÈýîýùbã)ïùõ½(åD¾S”U¥«% ‰lY%5ü]¿ -ûW EøNœ/'ÊðG>´À—cÑä¹xjk´Ú–¾í²Ïÿ´ÿ>ÿt“ô}Lÿh¸ƒéD;þwü§kè#Õ#"\¯þ};cdÒêÿé;ÿÍ´óæ úaí¿ó(ý°ößÚÿµÕ×þ_ÿ¯¶þßúÿëÿÿ·ñŸX0Âa ¸q9!QC|‚ûãüÚ¼ÜûŠþ=Ò‡_«{ ø8)øÂˆ±äòÝ·gO+ôV#yÍ ­ƒ±ƒg ^°ápdpsў˓O^A^õžÌkX¢ë¾Pß|ûÍ#oå ¯ ÐJ=€@ÂyµÑkzV¨Á>åÿfd}´©:$î´¡kû^ Ý£JœzšÌ„¬^C7ååNœvU¶ø¶¹¶ÁC¼sê=çð½Îáñ݇²‹Ûçï}þÓoõÉkÜ¥#NßÚÏœ§S‰˜þzõ¯ÿÑ;þ~Ó_è•Õÿלºú?óݱóÿ±vþ_ûž\ûoíÿÀ˜lôµÿ×ÿ[ÿïá³ÖYÿýÿÌ•7üçéÿçÿþ¸ñé|Õ®{#!×`btŽjMTœØ‰Ch‘¯©s¤õÚ—îäøph€+V-å‹‚šñ–ñÒQŸ>W Ž %Þô0U:Y¼j'¸œC×à^¹Î‘yœj<…ÐÎYºC:YÞ¿;«¾¬¬g%“ÐWå\‰—^9»â my’7ד' ÒH©Îò•®ù½æ×jÒ­Cû\›ó¤òToß¾MÙåÕú(§¯0â'}ÚrÎäAyæìH#O@7ü÷ùgŸ4m·Ïÿy¬è³;þwü«ÿWÿGL_ðÏœ²óÿùñjçÿ³\;$\v†ëµÿÖþ3¬ýü„µÿ×ÿÓÖÿû2þ瘱%:.Öÿ?S¨¿p’õÿO{ümøÏÓÏÿêß¼1¹äЉ⬌"tuøÆ«ÿC¨çó•XPŹ×h¨ =ƒ7Ê€. ”—r†0k¬ï²š Ô‘§üÎ;e\²’ÏÈLTrNh>éÿ{÷¶­Én\z“«û úyl™Ü"7%Ëý"²EJ¶ûÒ=F]ø¢_Ðcôcx¨Í}¨ªMv|9ÿ•U¦:¶Iªr!H 1dfƒzÛ ÐdדvU. ¯@ò‹)y„Ô#¾ÚZùÚÆÖ«öž+çÜ¡üÛwoKoÀ‡¬Up}DP,½÷Dù´ ê«·ß͋蔶IwPnòïu*°¢(Ò†KeÔ¶|[WúòpïÿÞÿÿ;ÿGQ¬þ¸úÿ¬¯–‡®âžïú¿ë?;¢ïãdsø1mí¿µÿè öfì̵ÿuGlpºsíÿõÿø¿ëÿ­ÿOG®ÿ68Ým˧Ÿüâ«7Œ Á#y'ruƆð(4Š•ãò t|ø¨ÑÃh½x”Îå(@ 4n€EèÍyùbaœ/ô`BïK~S¿sehMÝd"kÀ—)Ù“o‚z»£ê.SÏÈÜhmáF‘…<¡úx”Ç`WߘE&|òᤑ‹‘NžÐx!ûÔ䛽Bx70èô%:çÊ8RÿðÕný„§ú|¡½x+yFòÈL îéiã\¨ròtÊ£œCƒnïÿôûÞÿÿ3/̽ÿ4ÈÑËô…@g8è:«zÊeÏK—ןæ­þ?? ¬þßõ¿óc×ÿµÿèÒµÿŽs¶öÿÚÿëÿ­ÿ·þÿÙ´³þÿÿÿyúñ/þ†A¥–ÕÄwCÛ[dܘCÅ—É»ožw3ʹx!â¼(û8úæ›o\P€Y@txy4°`Š|áª-çøÈF¾Ê‚Fú#ÿrBÃ÷–~<® 1'vˆÒ¾‚>ΕÔA–¯¿þ:1ÐÍW ,¥Ž¡Q·ö‹ûŸ¼óŽ FÊy§Wx]Ú¡Ý×y@°FùÚèpM6±zñÍõÈõrd•.Ü_ÿêëì“Fù ©søàí‡ÅСåW¦½ÿ{ÿ; açÿÙÝhþ;ÿÏî" gõÿêk‡c×ÿ]ÿ×þ[ûoíÿµÿÙIüŒõÿŽï©?Öÿ›Í ãß²ÖÿŸùq½K¼þÖúÿÿsüçéËÙE±D '¡ìãoŒQ;¤â¬ÍËÇÅÀš:³i”ý~À¬ašúùçŸÏËØÏWñÐÛyUK]u[·A÷#LåO¾‚9êr(—²WÜòh嫜sùm£sm"GÁ+<…ÖÕ6¡þèþ(; ì‚Ò&±Ï\Š`þ|ç2çøà . häÀÒi~0 RånýÀ<ù?ÈD¢Ô+ xÕÇ Ý3åÞ`¨LîÙ%>xËäU–ÖÕ¾‘¿÷ÿ8'údïÿÎs}çÿêÿÕÿ»þïú¿ößÚg‡%2ö÷Úÿkÿ¯5Î Gjý¿ñ¿þÕÍçZÿïö”“±2!úcâõÿφþúúÿg}Ñ¿ ÿyú“¿úÓ7À4 0"€Vœw><«n*Ó²byèÄJ¸^xän¤ûΣ€;˜OPÎѺ³ã¯ÙÍT`I=Ùb?ôø ÷ú•­,ÎÕïZˆü×âúA=äŸ|SOõ*“º.¥£|ËàYY®=Gßwy¡)Ò~×òË· èS_ÄGÿè4­S¿i¿Çv ¶mÒ¯ÞÒÅôX<ý•Ý`WÚuTö{,ظ÷ÿŒ³öÛÞÿÂê‡ÿ;ÿïú·:ÅØXý~Zý¿ëÿ®ÿkÿ­ý·öÿÚÿëÿ±‘b3?ȧXÿ/®æÃ­ï¹þÿÁÖÿÿ_Þ~ü—?{cb™T‚s•i ª€;“&87;_¾š—pXÒÁ'/@È•~e;ˆb“ë8µ(žbÀþN”*‡@×Úן¾Îµó ˆ> —¢hÛNb³žÛ;…GÞ³;IЗ§sŽÙ½òôt¨£W/_=Þé•ÝVøNH¿\ýæO‡ôéÍÄ9éB?miŸ«Oû{-V®È¤ü€VÃÈ@ÎÏ>û,àV·qã‡<÷¸×­WÞÞÿ½ÿ;ÿŸwxîüÖ¹Õ=ôÄêÿÕÿ?k 6.²³w×ÿçµ\¿ìúìžµÿN?¬ý·öÿè…µÿ×ÿ³n:ØVõÃÖÿ‹Iqì‰Ñ•ëÿ¼}U|ýÿן<ýË ÀÊ£t€ˆuÒ̤L&+É4díÀO‡Vº2- ©A+M`À}ÿý¼Ï©!¼ì"šØ×óððN'“φNj25íûá7R& PFT=Êʸ‚4mx„¹F‹wù—Æ£xvè¯+•YÝähÛõPNŒ·yL0ò͵B þ‰¥ã jòÕÓ´ÖwÊÜ€±)ƒFß Q¾2JïËç_½>àšúê—':òJ—_ùìýßû ½{cgçÿÙ}©/vþ¯þ¯¾^ý¿ëÿ®ÿÇžÒÂÚkÿ­ý¿öÿúëÿñ+ï6’'‡Öÿ_ÿîð·Åžþøßþô ÆŽ Ï[Ü`t˜Äæ¤Zæ?](P”ô¤ H~Aæ•–ƒÇ˜‘€dÊ¡÷ÉLBÛ%0tì^ÂÙÑt¶§ax„žøKw´^éM ³áL¤^Aœ4és¨çÊx´÷$<—ÁÿcPI_I×o¯²óI;È ðú8`•— ‘cª”öxi™¦Ò:ÁGž¡™—ºµ}ÒÈ›—¯‡àôŸ:µ ;×ÚN´ê· »ÜÞ¾{›ûHööº½ÿÓs®‘põîÞÿöGæÉ Pã]0v…¤çìôU硸y¥Ýù?¸ó?úÕÿޝþßõß|˜qPk1Úõí¿µÿÎGŒØßlÛµÿÏ“(]?×þ_ÿoý¿ç§¦êך|:~ߺ~±8iÒç@“0qý“ð\Æš¼þÿÿžþ_v`¹an¬›ÌàTX(ê„Ö¨êÍwÝóã§yÁ{”Æøpdñî|Oú<®3ÿÔ/0äìøxûÝÛȃF=­ ȺI/ï\\@›ðú:f˧àüAƒ‹¯fÕ±DÓà\½åW™¥WÎÒz—•D*½>êcXåk§šöŸÅ'm¸ímä8²¤®¹Ö•S]•§“S9ýÒ´òLãóX`dŸw‹}0É1›¼½ÿ§3®þØûͳ³‚1bÜul9oZãÿGÿìü?¿(7Õm«ÿWÿw<ˆÍ‘]ÿÏz#ô¨õzþè¢ckÌõ®ÿkÿ­ýwìµÿ×þ§}½z3׳žÔÿ¢C×ÿ;ïWÖžŠ²¶x·ôúgþ¬ÿoÖœ±ñ;èÿ ùü¨…pv½N\àH+{ ªüj>Õh%"[úâÒ$\i=Ç›‚QÆKÊÄì´ï¾ý. ™ÇÜ>›¯ú…Ûüùâ‹/2áÂ?´èA]Çø5)Ÿk@R+T þwÀ¨r$Æ'Ç´ÿ¢;×ÏmRoÔm' ªï”¢ ìhô‹€OËj¯~ ˜w9ühäÛuFÞ*”¤¡Ap èòn«I;=}2•k;#û$‹œ·^òZøýª+½2·ï”Ùûß1qî_ï¡xïÿUÆòÎÿÿÆAtΥ댎Õÿ«ÿwýßõ?6ÇY.w¯ýw~ðÑkÿ­ý¿öÿø*óý¿ó$ÑúëÿÏüY8×ÿÔ®qúnüçËù !ƒÃ¯ãÝØd'ÏÜЩqX¦PïӯØ"¯CÓë:7wG§tviü`Þ~íŠpË,ç–³Øç‘¹áKh<¡ê¾À!ÈWù& ã¥ñ¥© x\ÇCFe./hý­-ä(½stê—?ˆQ&HG7°Ã5Gt<äù%Õ9}m÷–Mxßø(ûõÊWWûb E––­Êô¨\êL_ yÊ=÷]ÞÞÿG_ëGý¥ÎõãÞÿÿ™£3&„ÿ«ÿWÿïúOtµ¶îúl5kçÚkÿÕŽ2O„µÿ×þ_ÿoý¿õÿ×ÿ‡áÀ1rÀGÆ×þÛà?yã #»™„_Ï6CiãÑ?œø:ï£ìzJ™:úÌØ‚!Ý­‚‡ó†²)1ÿ³kò‚Ç} À–ÇL¾ÉƒF}Þíäòß\s/ à¤3¦Ydä ®µÁ•X(:’Í æ½€=ÿ†>>t5VÅ1~úÊyûï^ãÑ~âÐ~j×ÙMçxp+S¾Â0ô¡›¸ YéÚÚëöuäÉýœûpÕ¦†%þ®É´÷￱´óÿù™úÿÄ]ý¿úß:a=ÙõŒ® Ö\6‚x×ÿµÿŒƒµÿŽ ¯/è ó£¡6鹫xþ¯ýÿý'kÿ¯ÿg¾æˆóõÿŽ_{tETEü×êõÿŽAÇ ÆÌ¢ÿÿô“_|õFd¡¹€_Ó=5XM&ä0€æä¬ô;ï ž±í KÂõ§  žéìùa¾î|RÙYÏ>( \I}Þ¬;_ù‘s¦|áb2ÝH2§ü¤k×å™2Ú2!mŸ2‰çºÎ£4í›´{4";½È9´-ç\¹@ŒÙùçš\òÒÖ0fW¨àÚÖG¦y{ô¯²–§6܃ô“Ø{åZ9ÀðroɨrñMý®ÐëÆ}÷7Š,øÚÕÝYø Ò[¿Ý[‚Gëœë°ÊÚú½h]¾ðþzY{øôx‘¡œö ë lBƒwé]ǘX~mWobå×ׂY‰¯ë\ÌtŽ>ªX>m3:ÎDž«:ùèõÏ5«õ5=|ܧù—¶9º½ÿ{ÿI£ÒxØù¿ó?ºéÒCôGuêêÿÕÿtD×¢î”GÖ—Ñ!»þ[¡oý1öƒ¾ézL×&×ÿÓW¬ý—îÈ8Yûoíÿµÿ×ÿ«ïH3tÍu¾þßÁÖÿÿÝ÷ÿŸ~òW?cPÇ€d\ÎQcR\#4qSçìB‰<Ç\úÒÊò(_¯=ï.ÄÃ{ÎM¬¯5Ì89€!êÉw0Öä“?ççŽòí¹ëž‹•@5]š£|Èn‰ºRÿ<*X'‹,Î…{”BP†÷ðÒ†ìØšú•ÅûÚ½!¯²V6qCºúºÝœ‹õ±P9¤}xLŸ•ÉÄ÷<”k2“Up=÷³i÷¶“7aïÿ£ß÷þ?;ceçÿÎÿÕÿ«ÿ³¾XûvýßõŒ†Ø)l”9_ûïØ³zcí¿cGÇþ^û?ó$¶ø±´«Å6Ÿplöco­ýú„^¹÷WÏÓW³þ¬ÿw’þè±þßÁÖÿÿÝ÷ÿŸ¾üåÏßãÂ@§ >¥î áP ›Egô‡¼MI: ^qd/€MøMy²hÝó”Ëãnû%öñÂx_¡<Ä÷£ùâ#ÉOä»äâGýh”U+rtr.=Lszº›‹R Pu“à¥_”Å/AÊ I™¼†ÊŸ¼«¬þLÛ'&CÁòm™Ôq1Âñžî\ÛÕ}ç]š‚m®›°©½ÿ»{ÿŸç—1ò+gÀLÂIÛùúiçÿêÿÕÿ–À]ÿéÊ]ÿ>H_̘¸¯!ÖVaí¿g›Ô¼q¬ýwìíµÿ×þ_ÿoý¿,·?õCÄ÷ãF²þÿôÍŠÿÿä+„Nw½FWÉ}Pô¼`I® ÊŠ6·AUz¼ËÏ¢¤|AïK h°ÜÌÑkå•- 0Üs^^byyñø0U6 y&4ßã1 n»©”+Ÿ–Q¾²6?Néð:_M9GEF힀þAsÕ£:Mþ‘sò•R¯#}1±<|ÊOî“W잇2ôW¾úî|啟råß´æÛb,%yÃxïÿ«{ÿÏøÎùèOÇZ’gìÌàÉ€Ýùÿün¹ÿÏã‡n©®]ý¿úßÈØõ×kìÚkÿvulëëš}aí›u®w-»^ûí±S_ÎØéøXÿïš?ìô ™Ks¾þß±Q;fŒŸÚªÕ3ß~v‘O^Åï¹úòA³þ¿I—~ªŽnõúÃþáfe00®AÞŠÅ*oz1Î-œ‹ÊDßÏ?1G… ÿkq’îÚaà„tuôœ[>h?®_^ƒ/¦5´Œëò{1âÑ ýÎÏ#„oß¾ t„yÁºCèÀîà½×áü÷I ÔvU65zÆO;¶äËk}eg×ü»ËTßk生‚ÏNþù÷é€\ò•WÎñ1¯{P³ìégaïÿÞÿØ×˜2&îcè~ž¼ùó˜Æõ\ïü?z­swçÿè£tW½W=¹úŸÚ-¼úÿ±fuŒìú´ë®ÿ<Õ­­Ekÿ­ýgѧ£S6 }²öÿ‡shíÿõÿâ‹®ÿ}±þÿï¶ÿ?ϽqFGéÏÿ ì h‘ÞPVÜCž#Ê”!?øÍY@yÇÒгÀ-}®ÎËË/z—üaš.<ø‘çWŽÈ©îù÷ý¼X½tä9m˜O“Þz¤3ŠË›,vGI·ÈõKj€,i^rçèçmÛæÖS9Ðj­Ç.¤©7| ³{+[a=ß?yê>e®ú/T·<ñ¹×szóâ~Õ‡ ^÷ÐòÒÓW¬J«n¡ù‘gú}ïÿËŒ½ÿFíüßùÿßÑ-Õƒw]³úõÿ,(YWvý?ëò®ÿXZûoí?6æÚÿó#ûÚÿëÿÍ\XÿïøÇ †õÿG7®ÿÿ÷ž~ü—?{Äiì@‘vwZœ£½;0hÐJj°œëX¡\Ùjç0dQ(Hø?FŸXžCž2v8ðnÝù…VCO# ,”Ê9ù÷£|û ï=ÏŽ+åòxÓŨ!¯ò§=×±ž§²«¾ÖûúõëÃo€4t@2õŽ@‘·u“ÉyË©×=Èõ”;'ÓŽ<¢9WWžX¹na<„þM{¯:û²qä “qÃÞ; ÷þw»ÈîiÊ‘ãå_ÒµÁã„å¥~+ðtÕ5…R½?ÇH‘Ý\§îâ%”úöµô÷×.°W/_åQIiÀ2µöþŸñµ÷çæÜ5ïœ bºC|Ÿë;ÿWÿ¯þßõÿ®vý_ûoí¿µÿ×þ_ÿoý¿±™×ÿ_ÿÿ ÿÉKÜ9eÇà.`¦ÀÆ÷;^Ìáq‘î \1Ô¤qì@Ó\ã'OüîíyDèºÈb‘Wv2x5O¬¼C*¨¯¥ñ©Áx?G VB'Ÿ¬•£u·\ø8‡Xíä‘ÐkÒ];\K/0¦ žaèÅÓ‹´:D©·´ÓŽï¾ý6;¹Y¯^½Œ •=ŒôÍÔSùWîÐÜþd·›þ™2´ah”m»ÅÚAN1~þµMuÊ÷þïýÏð2žnaçÿÎÿÕÿ«ÿwý??ŒQ»þ}·ö_VɵÿÖþ_ûý?~Ôú·Í$ãwò5×ÿ?8ÆúÿSÀ8®‹ø‡Àž~òËŸ¿ ¨qP×SÙý½U¯f`rhÐ̺ åÜ{t$À•ÆR”+À‚Vzƒ<˜åF+G£•u”6æO¯Åoœ{zÓЖ®|,>väç|ãó~®¦£ðe¼Ô€Fvµ.7C(ÿ{»¤»¦äÄø6¿mi¹ÊõqÞ7þ®åü"§>  ÀVÞòÈ Ÿ¬‡ŒòÉSn <ÊTž½ÿg¼êC}µ÷çÿÎÿÕÿ«ÿwýßõÿ¼ÂÚ(°k„µÿ>´kõ Ûaí¿c‹×îl¿ˆ…Úœkÿ;\?õHÿÜúȵ°öÿs?´?î>ÍúÇ7\ÿïà sÍ­õÿ·ýÿè†Ô¤ÝózŽ NìK%*tN1ù½ûÊ;°*ßÇu ó‘€—²Ž&À_ø\më#~òßÎn(¼ñý8‰ù›ô{ßßùP‘«õy|ÒýkŒCëo_µ*gëOÛF&Ò(ïzïÿÞãÊßÇ ´ÿGÇìü_ý¿ú×km×Õ®Ç~øéúKgîú¿öŸqb|¬ý÷›óä…™ô²5b—®ýŸ~ÑwÛËØ©~™Œäõºvc ªÖþþZŸ:ôÍú×Ü›qµþßúÿ¿‹þÿÓÿÛŸ¾É¢1“šRì該¤üjLºóLþk·QŒ´)cð3Кúa…‡sÊB9Dñµ" <çò[gÎçZœGø¦Z¼¤ âÖ'&DåœÌÐhÍ‹ («2oy‘mdyÿn^?t«€dSO жK~eU¶²¸Ðà«åÉÙÅ''_Kôhâ<’YÞÊTžÊþqZ¯Å­³e ’G›û²é®„òLÿLЏýˆ@¾#ü¦ü\¤ÜÞÿ½ÿkÆÌ}+ùª¦ñ4c»ï²ë<‘úÿé‡ÿ«ÿWÿïú¿ëÿÚvo¯ý·öÿÚÿëÿÕ'®/WÛõ=­×âÚäÍ_ÿïàño×ÿÿƒôÿŸ~ü‹¯Þ@-:)zÞ‰ãZh~&ÚL&`‡s“¨ëPrlÇé&iЭqfÃ/”ä;÷˜[Þy…ï,øÞÍdÑ0tÑÝÁ¨”‰ÐoÎWÿp†.¥G«¿Wÿïú¿ëÿÚÌ©µÿžŒµ–:ª'ÙÐkÿŸâ­§í—Úækÿ¯ÿg,ô0FÖÿãz¯ÿo]Éx»sýÿƒÿ<ýô¯ÿìE· †b—…Æù}¡IÞÐË3Éä;ìôÖ8\+¯“ÑI“/Mà)Û:Ëü HÅD;‡­'×ðžÀ¡îJ’öq¨üb|Z·ë‚?b‹-yÓ#¿ó—/ÎgãÉ­œ´”vÎ…¼;kbuàAÖ÷ÐI/ÅêñheÞïuvF…ÁíOäÔö«ÿÈâÐòéó‘§ à­xêÖ')wË ye†Oïgû#íN]§|û4¥GW9"ËÞÿô´>Ùû¿óçÿêÿÕÿ»þïú¿ößÚkÿ3×þçÍ­ÿÇ_:ïw^ÿÏxXÿ_/<>$ÿaýÿéƒé–â éØÄ~=˜ÃÀ’æWä€À WG*Ø÷-a&¯ ²ÃØ;—”›ÜNN¡ë{ häÔC¡·¾{ü(>uX!4ÙZWª<ŠÇ[6²‘ù kò_éhÄ #¸ž?§ž¹> -ó>f(íÛo¿ÍBÄ(¡ˆ>ýôÓTÁ ‘UšÐ:ô\ X³«¯*Z÷@ ~“/5 *ùÃ0ï§"¯à 4ú+õd :ÛŽòG›ô)‘÷ L]iJíý× {ÿ¯±£3f|Ìɱóÿ¼Ûnçÿêº{õÿÑÔ‘ux×ÿ¬@+ëñ®ÿã´Ï+Öþ;öåÚ|„Økÿ}å?;ë kÿó!¯0ýÂg‰ ÊW‘l­I´þßúü×õÿÍ—êÕ3E.îš?Õ/¿þÿÓ—ó¬;ˆñè€9Ñ1@§v€–AQAz¶Ë]e*‹4õ©C,Èk¾r©Ò{sëuxV&1zL°ïŠâ˜1jl(ƒgª×¯_bˆÒŽKt³Á­Y.š8?“Ž¡[#7„íTøhËS@¾Á«£ÄÉ…7ú´G?\õ¸Ö†öMò'íÝ´ÏKë?ÎkýâÐN¬ÿöþïýïœ26„ÿÏ öÎÿêýÆ«ÿWÿŸ7ëo×&ëÑœG—Ì9Š]ÿwý_ûïüÈ™…uþ°½Øpæ‰cí¿µÿ ‰¼^ûý?jbý¿õÿÏzŸýÐÿ‘ErÀÐEÓb øøÁLÇWü4é„k™ÇÇ M¹¤Ê˜á„nNåyÄ®¿´$_>CË~?/AVBÚýˆñ–—Ñ;çå}NO º:“¹éá|mb( ißHI\µN Äo¦Àôiye|}p88 øc7Ö_| 庀žyÄnêL‰äágËè0J@#xöq@«Œ¶Úõù¦¿íЦzÛ´I@çlz+q C÷±4Î=òºÎý2wÓ?¿½ÿéÖ½ÿ3‹ŒÃ/ÂÎÿÿ«ÿ¿Í«ÿŸ(E‘u‹–8šb×ÿ]ÿß?vÚd|Ö‘+kÿ­ý·ö?‹ê9˜kÿ?¯)wŸdÇc]‰™n[ÿoý?³Ç8î~ Dúúÿ§o~ýÿ§ÏKܺ¸ù?ÿ<|[V«õQø 8ÕGLðÇÓ×ZM¯fg–ÞÇùáŸ:"l¤Ã'nêl ÃT~ŸžžØ¹óùr×=¤5è;2ä>O ¶íýßûoŒìüßùoÐÕ)Õûå wš\ÓFQ5Ïú¦4Õí«ÿçG‹ÕÿµÉx°jîú¿ëuDuË(˜ù¿öû²aí¿µÿGy®ýù7µ/Ìú;÷ø1oø@—£Ì çG|×õáÖÿÓIÚvµûŸ¾û&eÖþ[ÿÿÿûÿé'¿øêIo"׈èWòšÆ˜@üJ_e¡€æ\??箼‘cä(´Ò˧[A“pÿ3õ™è…Ê¢¡qyÝÓ(¤Ò‹]kŒ°È8@]Ûxd¾~õ&/žæEëS&@ÙÔ­62¢ÚGß|óÍ'Ÿ}öY®Ñô:FyHÓ_èY­?ô­CühË•7™a ½õò§/NÕ¦]d“§DxMÛRÇ\‹cM~x]à\úâT¡Ð)?qëjßà'­4{ÿ÷þ˜o׸ɸš1²óÿ€Þ;ÿWÿ›#}¹úÿ¬ÖAôœîØõ×ÿØ·?36Öþ[û¯c£¶(!4®.¹§­ýŸ©³öÿµÖ¬ÿ·þßúÿ³–üúÿw`Yì âˆv1¸/5<ë°2Γ?ëÉLà˜)MŸ <)/iò{Ý2êÌÂ3ñÇ¿ÈÊ ý”C…4|Ü/eãé—/NâãºÀ•~Ö¿Ç‹EµÃ£€ø£6yäQzëá”v!uÚŠÐ~÷íwŸ¼zõjvU½ ÈØ’/íÈü zà§é©g^pZ#­Ž¯¼˜úC×vÿz~‰ÔǾ»ÚÛ2á9¼µ-uòÕNÃL9‡{k÷XCùU¦½ÿ{ÿwþïü§ªn’No¬þ_ýßõm×ÿ]ÿ鉨.7AOŒÂø@—ÔæÈØ¹•QþØ,kÿ­ý÷lëÂÑ5kÿg]žþ¯ý¿þŸ¹‘1±þ_úÁ²þ×ÒYI~ÏýÿìÀ²`:~}R12ìä%YÐ…Ã"Üil·EªŒ]A‚]W¡fåÉ—hä+#ö…2‰RærŒÐwF®¹V&u\ÆPë²åÏLà‹îìLš:/ ïÊW£©õ©|Gê½õ:2–¿ð„–l ¦~I³ëÓÙ‘åÅí Ô•M¹:|dÿýð0I9×€8ñ#L[ÈŒö.Ã\XÑ“†NÙæ£wÞ4çm§¸ô„wr“¨Æ½ÿ£üöþŸ±³ó?seçÿõxíêÿèÊÕÿçÇ®¯»þïú_ûjí¿µÿ,škÿ¯ý¿þßúñiÇõ%Zçlñúÿëÿ³øVÅ$ŠYümñŸ§Ÿþ»õèá}vì|ÿþ¼¿É¯ªv& òí(êN% AèeæM#ŒÁI0BH©qcçãŸòD#¿@U!ü}½èÜ.¤÷ïæ z©É—wä~r¼p>û]å"ËE§£J?IϲÎy;±ÌuÓºË+@ÏÈ‹& LÆ«ôù¾½v_éò)›:U8Á.-|Û'ÒðûX®ÖÕô\#žúµ],ϹÑ7´ÿÅåÄèÔ©îôŸÃÆ êÓÿá·÷ïÿÎóeçÿ<ò<ÿVÿn—ouòêÿßd½Ûõ×ÿµÿÖþ[ûí¾Èúëÿ±ãs_þ)›©¾îúÿëÿÿcà?Oüoþä äѳ—/^> ©¿63Ú FÀM;{WiåÄ=  à-/õ ¨${äX&±é=\«8Ô_zåÙyÕº†8 Rdz2£N}ÏÏ=]^Ö§ÒÚ^¼´E¾¸uºP6´&轜z¿þúëO>Ÿ—¼k·|ü^ÎñÍ×ç½Yß~ûmøµ, Ë ´µQýBem_&íJ¯¼•¡}‹æã n!í¸vÕ¸N=SWeßûÿ¼Knïÿ;ÿwþWÑ9«ÿÏú¶úß;%wý·†v ¯Ý`mÝõÿÃÐÖþ[û¯6*[wíÿµÿ­¡wßfý¿õÿ¬õmÅ_lýÿƒ‘è‘{ÿ¬ÿ?¸Éÿõÿüßc{Ãúëo>zQy 4‹]F 3[Áœv¦–G÷†O·ŽÊ+]À“¹ÆÇÁºïÄR¾A ÄÉ Æp¬Ñ¹.ÈԺ슚Ì3Oÿ€Ráãîc=ñÙ¿…ã @Á¯IøàÝöô1EiøŸìÊ´Ï”“®,p ú?ú£?J¬Ï"ç,ÞŒ9åÞ~÷6|”k;ÉàZÝÄ­,x™æÀizíì¾—G'( “ç=]ä-]ÊOú$Ò~bB•J õ!séÍÓ. Ud™ÇA†6€xê(íC–I $žC½@Ò[h=^"¨xè©üänÙ>© ÞNÚTùÉËW/sgÛE†ðœ~ä©»üæ$éþ$mâæKs.È´—Ld—×>I¦?“`mêU×Þÿ3ÎÒ?Ó7{ÿwþ›#æÎÎÿÕÿ«ÿwýϲ9vý_û/¶ÚÚǶ›síÿµÿùëÿvý¿õÿ×ÿ?›–ŠIÔ~¢'øTÂ=ÏyÐŽïÅî–Vœ¤ôæ×ÓOÿúÏÞpвë§ÀÇ,ÊҪȯ%}ñ¸tà•ãüqD”ó|"] $>® –H®T×¥¿ƒ,Ò¼×JÜm„h ¶˜"óÅßËλ{)»¢”Ÿ¦$BÉÓYÊ©Ç.¦>š˜U×ͯ‘ªœ:ÉÜ=¹ë æ=\ÿÞ qÁ!¼Ò®yŒR™¾àŸlS‡óòEÛû ­çí»¦¹vTöôÙ—zå·tÐ^õ Ë—oõîýßû¿óç?ýJ¯¬þ?:Z_TO¯þ·rœ°ëÿ±/vý_ûÏŒXûoíÿµÿ×ÿ»–Çõÿ¦#Öÿ_ÿ¿†yÁ–ØÓAÚÿ ÿyúÙ¼ÄÝ›/Ð ÒóƒyÄíìß ü1Ø>›/ìy„èóz­ ‚M¬2¡Ê_aK  -¾ç¥àGÐß_R®î)–Á^s p X51€ìÕkxÛ1öâÉûŸÀ%\â‚8-›öOùÈsåã^žtçø+ŸÇ÷æ:»¾Ô0iv^Ùí¤~ôšn“VŸ>ú›¿ù›ãúëÿqÖÿ_ÿß8ø§À~ðÿóú͘d/ìF @¤™ƒÜ0 ®A¯æñ·ïæN“ð “W ‡ðLæO l,rhîü€ÐUGMZõG–I²¡¹‡ßiäW†îör-­—|À ;«„ÞøÊaiêÂS=€ ×ÒÛäLŸ AùuâFÞ«>J=Ê];®µúÙ§y/•z*·kuÜûªÝúëÿÃXÖÿ?>æ?þ“X1ƯÇC,BOÄXäš#k·ŽQ€“!qú‡¶@øñÞ'_AWžhðrˆ²Ð9î×è\ã+(‹Ÿü«<ùìx’_Ê Ôwñ:`Ž…õ)»žZgyº&/ùÓ¾ÔrêÄS°(ÿpúŠ dÒGÎÓFWý®,]y®ãý ɯgëǤåú’sÊÕÚnò”¦1žÒNd"»Ð|yÊ“ßùš_™ö2Ê+'­õèµ÷_/íý7>vþïü_ý¿ú×ÿ]ÿ×þ[û/öñe{²Öþ?þ;zíÿõÿÌ cÁ±þßñ¥øñMGiðA÷kº¤~¬óøò—®Q6}y¥óo•7×Öÿî·?ÿ?ïÀ2H ‚ƒDè ‚”馉 iÊõ1?tƒ†èâìhu~Ñã—Á;»~\£wŒâ½|»ð~ûnv]rõ†ˆ•Å?ùŽli“0PÍ5Y&v^P(9“ïW³È+ÿƃ®ñ·óÉc~x?»Ô”™|±ISze®ÉANåZrz_þóÈž:É¢lvO©€2 ’tî_w*¼ïç÷>VçiÃZeíprN1áós^àhd!—¦Ü~ô£œãç¥è„—_,v‚ÆHÇ`ôòÅó£w“<ÛÁ0ç€+×xØUDÎ/¾ø"_XôH/xƒÞcê!¤ë€Iá<®&‘«M~Y N¿ô¼æ‹ÕÿCOVujG=ïìÒ/ú ÖðAÙIŒlÍœXýGÞôª”¤ÝHNÚüE×ò•{ïÿÞÿÿ¼5'vþ??:ª?«ÿ/mºú?±ëÿ®ÿ~E^ûïØ_kÿ­ýÏ_ûý¿õÿÖÿ¿¬ÅGô?öôúÿ ñwÀžþøßüÉ@ŽC{G†Orôב·°ôýL¡¾¯Sórý‹¸°ë›n·OøM,ÍÍs}?Réõÿ¯õ«E½Ñ&GË–¾@Óùšßáow•®@Mw[yi¹GóúòòÊ€lv;}7»¡¾ùæ›ÈkWTÂ4j~/ú`×XÛ8„‘­õ„þÖw€2hÔÇÈ `4y÷P©ýŒ^½q †ÐbˆF~iI¸AZûß‘Úø©3˜¤Ü¡üÕ§òðÒ{ÿ÷þ߯0puçÿÎÿÕÿÏ»Vÿ?¯ó»þŸÝË]ŸÙµvý?ïñ\ûoí¿ÚðµWksÆðœ?kÿ¿‹=¾öÿñ©Œ‹õÿÖÿ[ÿýÿ®]+Šÿ<ýôßý«7ã°ò¼{ûnv½øä³yÐ#œÙ¾÷ SçwE¾ǘc¼•7ØÚ(½•KrØ#‰4:»¥,ph…òÄØ„¨ƒš;oé/.pÍ9PÈ HC3€’ò}YÛ"ï%Gyµãì»×…Ÿ<‡àìj‹vñƒ¾}ÂëùÛvòàÓ:m“ûôÓφtå[×y<ñ<‰UËE6}qч÷´·é~%í9‡ûûâéôaóú«ÁÞÿ篇{ÿwþgŽÜ&q礤ÿGŸ®þ?ºu”íÑ·ÆÆí¼ÃgõÿYúŠwý?kήÿkÿ­ý7?2¯ýûÞúQ[cíÿõÿü8Ò°þßúÿpƒúïüzç(þÿÓñÕ“@ƒ…NŽªïæQ>àÀǾàTv] Ô˜ðÉ/ÐÞC#t¸ét‡E*@Òu¤áÏÂK~ëvŽgëþîíw#ÛyÌï_Ï€˜ºCO@ShînÀù-7<7{â,Ò&8Ï ˜sò8ǃ£*EºÐ8®çÀ#éS•ós|ÈßòjÛÔ8lÿáðmê´³ª÷Jº¾áÎû¼$ÌùTtêÎ%IN¿§=“ß{PÉUž{ÿ?¼?ºTÿìýßù¿óõÿêÿ]ÿ­ ]³»>ˆvý_û¯¶{lí¿±™Ù¥j{®ý?#„->GuÉÚÿçìíõÿÖÿ[ÿÿ| ŽÞ\ÿÿEôdu$½ ÿy°² è<‚ç—Ð(ÖÙ¡cñ0UÉæ¼· #êžžñòŸ€Îb&Í¡l©¦¡¨Pbê”C 0+ˆ&SI6 ¢_.å½K:0F­èðöÔ\„^Þ/åÑ>ùÊ9È"]Gá×¶)„‡Pµò7½«ó´,müÍô_ί²‘iäBß2=k‡v‹Û.õ9¿÷_Ûówòåõ d7ðc@%}ήö·^¼ÅŒ¼êßû¿÷ßxÜù¿óô=C·TWˆé¤Õÿgýª._ýÆ…µÇzÜXÿÜׯYük 5j×ÿÓ»þ?ÛEkÿ»ÖZûÙºö¿±Ð5˜N]ûý¿ø«ëÿ­ÿ?ºáÒÿÿÙ` o†RÊιXG¯Ñõ?DùµYÛOú(ÛyQºsm&—¶¸Ö;®X®Ǥ{L¯@U£IK¹©W(@iô ˆÐÃð1¹•AwvO¸ò–ïqÄGY ·PÙšô »äV—û®ç{ÿõÅÞÿŽãoçÿÎÿÕÿ«ÿwýßõí¿µÿØŸl`6‚X¯ý¿öÇÁúçàõÿÖÿï|ëÿÏBñ€ÿ<ýø/öF'ßÖ€©Zz5ãÄô½P€à”›`Bo² Ò8¾Ò€G®-z›|ç‚vŽ÷ t6i§¬ô<å…°eÒÎVýÐεú®)RGiή#8Í,ºó‚vyƒSœë9¢™¼´ãýyÔѹ¶}öÙg©¤Œ ==~0:ª³²¶Ýmzç蛦þÔ™Þ=r(×/çè[V_y¯˜¼û®3ü”нn½å‘ws 9ȵ÷ÿ8¨úëû½ÿq“q¸óçÿüp°úõÿ®ÿYVkÿY;wýϺ¹ö_l5}Áî­ÍeÄÔ†kÚÚÇ>õwíÿµÿ×ÿ{öýèõÿž7}DgŽ¢¨O»þÿúÿÆB±§ŸÎKÜ ‰þ5ôÜcf°f2:À«¶_åÑu 97ؼ(]š:LÎÍ`-À1áÔ?õL]½îD–÷ÃÙåº_d „æ¼}÷6 Në©GçyQºöÍÑ:ÕƒŸ]Gh”ù´QùÔ?yZ€™¸¿DVVò‘yb² g‡Õ4sº/y䑯’ku è m“Üðo;.zåPŸÒÏå[_û¡|ñ»Ÿ·}IÛû¿÷ÿx;ÿwþ «ÿÏ«ÿg=ñ°ëÿ®ÿkÿ½Ž@?²ŸÖþ;6åö·n¬ý¿öÿúñÙÖÿ[ÿ¿þ8¬AXÿfqP‹ƒIüÝ🧟Ì;°t®íTিhAg±LAÀÄh•+¸Báõ›O>ÿüó€3åoÇ~ќ㯼 \y¸ïi(Àì»o¿Ëõ¥<>7ÿ®rŒª—¯æKˆƒæ«G¼tvQiÃüÁúì*¸TöIïñ}‘¬mjûòþ« ¬ŠÑ2u·ðû&ÿ$>Ú×Ç;ˆµ;$„>ÿ#>=Ô.rqÛ+®\ΛÞ:ðÍ9^©ä´9§þL(O1^çx¹ê%«¸yÚ¥Í{ÿgüîýÏXé84v:wÅ®wþŸŽ™¯ÓÂÎÿÕÿÆÁêÿ]ÿƒc{ÄØõí¿¬›ÖN‡µuí¿µÿ¡v~ì‰âò×þ_ÿÏ8Öÿ;Ow­ÿ?ƒáÒÆE‘€ê”®3õñé“ßÿÿÉKܫ۠6$‹ç %4 À ´uV¥°AÇAT%(7´­CšwL)ëð‹î½å«ð™ò®=æV E¹Ê€¾²ˆLyZÇT~ê —L2þx’MŽW×Î+wPƒGÛ$SNZ/lÛ™eÏùäi¾ø£=Už~!We$oûí"J]¥ã‰/´-ß6{/˜þ¼ÓVæ¾3Ìg<84A¤ÔôAÚ0é½/b<ï|Ô ÐC/¿¡}ß¶Io;ÚW{ÿ÷þg¼7ÆÜÄC;ÿŽÚù¿ú¿z³s¥s¤ñêÿ]ÿwý_ûoí¿µÿ×þö±êƒX7ë ‰ë[é+þI|”Ë·ñõ÷x1s½þ_pý¿õÿŸpóG¨Íù»àÿç%îÚ€*ʦ¹ÉÒªÐ÷;y‚–v 0¤õWEŠ¢åå½ýîmx1ÐDU>xÖh—8‰ã t‰|öÌ®-r„ÿÐH÷˜žŠ)&òEžáÝ÷E‘Ímâ8IŠlhÈóþûH9—¦îÆÚ€_®‡Ç¯¯Ú£1ùñ ¨5<úxyÒÔ1‡¾Á£rËk=šÒwPIG§LûqÒ6ׂ:;ð(:ô§ i¹OÃòÖ?ÃîôÑä{,›’=)tnÌI|ã㟮ÿ¯oôÅúÿç‰4}ñô/ç%î:&Àɬ%ëÿ  !žü†3¨´ÒA[:[F^€” ÞåqÀ ¿f}Ë·,ÃïÔqdî@gQéZ†}4ÍW¾ü25ÎüHšB8:`÷anZ‡àTPHÑð"ƒÏ__D €tí(1V ×È霕”ħtâHyÂiãì¼òeĹ.¼Ôw݇Ê*]™ÆèåùJ£îëË#ûÐ ÏôÝÈk9ùv’…gnþáZ}n°\õªçÜ›ë ¯8u]4ÊHßû@E}§öþÏÜÌè>ýÑqÖ±³óçÿÑ1«ÿWÿp0k“µhŽê‹]ÿŸ×}k‹~ÙõÿŒú£ëIL¿ü9ëÍÚkÿ­ý¿öÿêíÿ·þßúÿ¿sþÿÓ—ýgo=B{çÀ™ýXF!ÐQj$©ðÁ">©|-#¢F•wTÉS¯½³Ô\Ã4…®ëIL9rÈ÷§¯È‚ëP¾¼Äx@¸…ó˜ßÙ½ùäOÈcuÃC{r}8ÎË¯ð›´Æò›ÞøðÀiÚø*­ô:!Òz®Pøösë“Þþ—VyïÞÞøÆ¤1êµñÎKßjß]V² }„K.9ÉçYir9÷¸¡Çæ"·zçp^þ¡¹€™»LL«ß\üôƒM uh`äÚû}ÔéZº4;³’?u©Ãû²”k?¤½øj«ø’ ­úìVûôõ§i¦öûÕYÞ«×çEúøx×½/r>4òÂgJKK»œçzœ \ó' ¡Ùûÿá˜Üû?ä“ƳñbL9vþïü÷+&ݲúõÆB–’³ŽY»þ}péÌ]ÿ×þ[ûoízÑ8ÈÚy­Ÿkÿ_¶Äµ†Ô7 Õ¡9[4~NræÏe—®ÿÇ\Og¬ÿ·þÿïµÿÿôãy„° tF}vìPœÓ(×KqØÉ²3T…â8¸Q¾¹<×tw¡÷rsñ÷£x¤ã¯Î™jX¹OÒsšô9â4_´ü‡}!0xs°ãd_åGÀ'u|͵wÚ¨½íW.uL^Ú4QÚyžÉ¿h´-Ê{´´-^Úéº/´óìûé3†«À˜¸¥ß®€—:•op®Î§¬´mQ¾ý§…w“m–þjv¶¡ÕÏiûð)_rµßsOçZ^ò'––zFtúLØûí&Üû¿ó?suç¦?Fw¬þ_ýoõÊZf-ÙõÿØ»þǦXûoí¿Ú¥µ_­kÿ_:síÿÇX`[+õMÄñÍÆþѵÎäÔ+=ÉÑòëÿ/þÝtÊúÇ×e¶®ÿÿü$ÕïªÿŸ—¸›øB Ïœs×ù•pu) OÁ”»Â@%ƒO”ÌÙÅÐçÊ“ï(òâå<:7Ï›P²C'TôÃW '­|r=ò†n.²Ø%½4ø¹”¥ë’fÀ8t( òÈH.qëA×<¼~ø4eGtä’þ“§Lémïß ø4|ÛN}ˆWv‡M,¨Ë!è€>]èÅÉúÞò¶?Z/Î|Q±uºvîN­Ïý)­y=wM†—Wû[·ú•­6á¾÷￱ÙñѱÑù³óçÿêÿÕÿ»þÏîðÑ“B×Qç»þøØƒ>⨮ýwlÔÚ`kÿ=ûú‚ͼöÿÚÿôÛ“ï}z騸7£F’fý¿ø|úJHÿä윻^ÿïà úȸ‰>}´þÿÿþ!tc(þ:šÈ7,/þžüY.>ä×XO„G úòiZnü¤ÛuðÉB3/‚)ý¾—S¯r†®Gó„ÒPUR™€ÃmóÅPïxROÐ rØÉ”²ê¸ø©7 ÔÐx?E¬ò¡ôÈ4|];G/ï©W ŸX›hÄÂwß}‡Iže&¤žÃK¾zðiPν &o2𠯩 ½¶¶Ý• 4t•O¼s=ñý3ªê(±°÷ïÆ‘ÿÏ¿ÿÏŽ}Ô¹¶óÿè•(›.ªÛú¿úõ¿¹²ëÿ®ÿlJ¶ËÇîåQû#úbì±cí¿µÿÖþŸÁ×þè¶—ãá—¡+ªCâìÿ·þßúÿ¿ßþ¿¯CáY˜üþY4@@Žìhˆ1v h]Ê$å.EB¹(‹7ç…ÑZpýðÎŽ9Ò™XÙ8Î×99ÂgdˆWº´<Ã_L¾aòü’‰7¾Ê…v¤:í=Æ‘sùò²ÝtÎÕŸú&Mº²®›ÞòÚåª$/ü'M›Ò®Kζ+Û¤õZ¨h‡OùÎÕã<üçšó×]\òñP§Pšž—üÐͧaʸÎ}I¹éçiß¡ßû¿÷ÿ€2gŒìü77vþ¯þ_ý¿ë¿5r×ÿµÿj[‰×þ[ûß8Xûÿ€I±Ç¿¨®\ÿïø…úEXÿïlâXÿÿŒ‡õÿÿþøÏÓŸÌWRC,Ê€ Qw(ÉË1é@!ùƒ„ˆä¹%Ò…€7€¼®²ø& ™Óâ÷ã$z7¥Wzt®‹®ãÁ‰p8Ï¢14äh£(ÂÿzÓœsB¥‡·Çþ ²—LÊà)ï¡t/ÚÔ?@”à¼tm2•Gš@}Éé•VШò–¾ü\gKÕ”õ¸ªAfØðªâ³mQ½³®~(oiøyïUåi=?œí÷ú­ø½O•gïÿÞÿŽ™ÿGW˜;æŸÐyréŽÿ«ÿ«?;wVÿïú¿ëÿÚkÿ Ý×˵ÿϓ֊Úkÿ{}ËúlÌõÿÖÿ_ÿÿÃM9ÿ+øÏÓWÿþÏß¼}÷6àK X€)YÆ J:DH"¯@• h±Êާ@Y罤MЕ¦ Qx)‡W^æ>¼Õ'PîQês`ˤ ñõbôy·Ó0ÃW“­‡w5Ô\㨠à–ECS¦åÃdh\«WœrC﯇“2<É¡"±òŠÕ›•({þUB=é»)£=iq.ù \eK§“m±‚€Ná=Qê}uª_ÙÞå(’iøÈkz_-¬lïç ”%0L$}ïÿÞÿ_csçÿÎújõÿêÿ]ÿÏBßÙõí¿µÿÖþ_ûý?kÁú¨ækò9×ÿ_ÿP“`Å(øRþÑðŸ¯þß¿Q¤»« ¶Hë{83®M\ Vw?qz ˜p~Oî5 ‡Ö‚ßO‡Gû䘔I={×A_¬'Ý9Y4þýûÙm5r’QN Õ=_HF€ŽúëœW~ñ’ž‡×ÉÅ_:™Ú?襅~ε£à“—££Ôä‹ÕéXdG›6é¼´mΓ71Z¼²0NÝÎÛOÒ8¿@+ý?ù~µhßÉ‹â˜2Ã0­ðk—v¿z= ã€WúA]Ê£PÞW}±/GMÞÈÐohK¿÷￱±ótßÌ+óÂá|çÿÀõƒ@¯­þ_ýo,æÉ®ÿ»þ¯ý·öŸµaíÿµÿÙ’]êÃH3>Öÿ;¾¬þi?­ÿ·þÿúÿÿ}üçé_üÅ—oT ÅÄâŒÔQ›ë¤ÏÄŒ€3&ðåƒ0e®QHC@)‹×Pc9yu»‹(NÐä+§. ‹4Ç÷³k(;’TtÉäDi÷ú•8€àRÁ›8“–zÄŽ©€pid=ðÏd|ÈÓ6É£×ð¼˜Ý@ûüóÏÃÓ¹´×Ÿ~šÊ"ÛÈ®-øµ€K­ôñËÞÅ_Ôƒ¿C`âKn}O†l;¼äéî3÷HõòÓðQåö•Bçíç½ÿgœîýßùŸ‰öÑŸÿ«ÿ«ï êQ:uõÿ®ÿÆÃ®ÿ—ÒÛ£sÅÜXûoí¿ØžQœÌ÷µÿ×þ??Þ ëÿ½¹þßxäëÿg0Ä7›B¼þÿÿÿyúÉ/¿zóîí»#@–N£\t ´9ÉyäÕ¹;ÛÏP^çù÷áž3J=»yÀuLÀK¹s~¿.¼€>Æûœ£ip Ø ¸3À€¨ò•¿˜+È‚¦|¼÷&ÀÏ%“kMQ† =ô‘>(½~ý:"ûlZ{n@øŸÖðœ]fä%{úGû&¡œáß nåÕÛÝrò¥¡ðÒ×ø ÃÜKeñM|õ ÙJ¶÷ïÇÑÎÿÿ«ÿ~¥#WÿïúoùÜõÿØZl ¶ÊÚkÿÕ-k\Œ¾ÌùÓŸ®×þ??Zs:Öþ_ÿÏÈ<™¹±þßúÿëÿÿÝñŸ§?þ7òÆBc1â¸5üš(ØÝ€^] M_h& zá<Ææµ¼PòNª‰ãÝhd·Î;xƒŸ<’ O@+”Öb .´xÏIòýâ€J[ÈQî¡,æüΧ¼òbó)§Œzs8ŸÇíÎìøJ˜zNMg1ÂÌï¿?rW9Iÿ¡ 4…Ó‘GÈã{snG”PÙœ£QÞQž€'4®[oÛ–{6eò~«¡D4D£,õSîÝdvâ Ã/}6²ìý÷Þ°½ÿ;ÿwþ¯þ_ýo}Øõ×ã`í¿µÿØŠkÿ¯ýÏ÷Xÿoý?ëÂúÿëÿÿf0«c›Á-þ)ðŸ§/ÿúOߤ Xr=šÇq 03€GhØ ¨2H”ElvõH $3’Sj¾ü—„¹NÙÉ¢€$vEI»1x7à%àÓP%麴}¤°@×»Ù‰D¡»“ ÐD¾áWž:¶;¯ò2seæ@§ŒúRÖ#Š#«G÷ÔêâCþ¶Á/LüÒ4|¾0KŸªÏ.e• ˆt*t~oÛÇm×}¬ùx ‰'­|5€œúÇÑváFY°ìõ€[øÉ»ƒthúhæÞÿóØêÞÿÿ;ÿWÿ¯þßõ×ÿµÿØcµéÖþ›×X¬ý»íÿqJÆa17Öÿ[ÿoýÿõÿéƒlüçéÇù³7Nj¤z:ˆP€¯æq5r/_ç¨âÚ(ïbÎXàÃ{Òñtî<`QùÕhL ɹôî<ÂÏq/‹§k )zÌß¿{ÞÆàH@CF‡/üM8éù5I}BvcÝêøä+󘥺>}4QºvºI•·_V¬ÌÀ¤;`W€ILnïª*Àà骛,}ç•su÷EåJ;¢ž¼Zš~èýÑ'ã†Nß ÒÞM»*7ÞM'ËvúJúÕiíó½ÿ{ÿwþŸG“wþ¯þ_ý¿ë×Ѭµ³®sfwý_û½ÅN[û¹ö¿±p?Öþ?¾[}:1ºþßñÓÖÿ[ÿ¿¯ZÿÿØÕúƒþœXöHÑC1¼Æ3ylÌÚ´‚|ûí·ŸüèG?JzÁ4˜:,RJÚ»Cä)ÛJkÔ¹vcÐ5€PÐ'€)u_™Þ%¥nÀÔG5ÀþÓ1ž”`ä"ϲ·=beÂ_»6”-x3™‘CŒH—:®rø©ç^áãZ ;þ^zæGe"×ÐàçüW_ÿ*}o÷V_Â.Ý#‰‚s|úR¬¬ u®@]Ó[FLò•Nš ½÷zïÿÞÿÿ;ÿéˆê„êKJmõÿêkÈ®ÿ—¾ëìà-{‚ÝÛƒ-2×융ÿÖþ36Öþ?ööÚÿnDXÿoý?ëDƒYB_$^ÿýÿ ÿ#üçégÿî_½ñe<ê1B#a0 §Æ@{9‰)†,Ä€ëKŸ•E+6 å½]K^pnKiç%TÁ<¾~~±TpŒtAéê~ß÷?ÍÎ/Ÿ[b -ç<H?e¯ÚÜiýø² ºê•žz§Î>‚¨Œ_*rd´(ã¯&Ï}†Ÿ«©GxîúŒH·ëËî,<ÓOó.,|õßÛïΗoá=4@³ÊŒ><&]xœ_õI#ÿ½mÒï³Òža~¡ó®é7¿ {ÿÏ;ÅöþÏ8™!l\ïü?:cçÿêÿÕÿ»þg¡œ?»þ¯ý·ößÚÿkÿ¯ÿ·þßúÿëÿŸþÁ‚kLìeð† üçégÿþÏß tôÑ3[žël<æ_Áyö믿`ÓMò8¿S&fð+ð"žp ä§Œøà?0ŨƒŒÉÓ¯”'ow -õ\`:ú¾œ?À )#(¯î¾Ó@Ù‚Gí€=C/®œÍS÷“5^a>²Üƒº…´b×úOýª}I›ë:Kdi™Öùà3à“ó»|wy9†öi?ÚGqúeË%ÖΑ«õìý?÷~ïÿÎÿÿ«ÿ?ÐÇ«ÿ³¦ìú¿ë?ëfí¿µÿØÂÚÿkÿÇßàçŒO³þßúÆýÀ·¯ÿ¿þÿ?þóóÿóÿxcpy“R\}Ù;­ u ý,@ç¥EË#pyGÔì"\ßBï<ïÆÁà …þWð±Iž­éêRN0fÊÔiY{òú‹oÀ:JÓn1eñvÄ ½dh½hœ§ —<ê¬Ãz—!ü'/}2…ˆ²9GðQ¨ì’ï¼¼[‹ŒÒ´Ù!衃•}:!ý ŸlÚìk»¤ mèúX¡_‚4!òO½ÚØ~Øû[ý±÷ÀÝë=t;ÿŸu¹“yµó?:võÿêkIÖY wý§!> »þ__ {C_kÿÍ­kÿ}`Ò#kÿ¯ý¿þßúëÿ?ƒ}ôâ8ßÿ±þÿy1mùô“_|õ†“šÇìÆ¸à”ÄÐ[¸"ePéL» Ä¾Î6„1FŒÌ9@fº7FвŽ.J5^¼! ]D·g],vK­W€¥@Ò3Àsê‘îÅå’È ¬F©‹|êAçºü*! Þ460ÈìZžSþ´(Í:2á7õ5´Ž\?'gà‘¯ùø‘#ýuVW®'í§_úx¤6±,z]k‡4ñýÀV¾zòR¿Œ ÊØQ×÷W¤¿§­{ÿç¾Líýßù¿óÿ3æÂêÿÕÿ»þŸµÓ_kiv˜Ì:ÚÐõ=×ÏÉ»þþXûoí?v,;TXûíÿø<ëÿe>¬ÿwôÂúÿëÿÿðŸ¯þÿžw`=ï¦fytlŽ!vb40Ô„86@ðŠH(% ’4³`M@“¡?Ž¡K@–¤('°ûÐåüœ)?ô¾2ˆ>åßúðˆ¡9ò²œËŸrg‡•sü¤§ž‰»«@úä"Ò¡™Ó.ÄRcØ_Azx_ò®mJš§“FŽÐ_e‚xe½@Y)FŸëÊ‚Þõ#žó¶å‘–ÜgºÊ‰Nß o ™¼\kïÿÞÿ޵ÿgWéÎÿ£¿VÿÅš5bN«W¥®þ?»­MæË®ÿæÌü³VϱëÿqÖõ»gí¿µÿžæÇÓµÿÓYKÖþ_ÿoý¿Y.ÇžúÀǽ®Ù[Žõÿ×ÿgC°3ïøÏÓ—¿üù›+10ÎËÑÏõ;ì’òBq€€Å@bÌ;7°¼`}Nrãmʸ69Åh5bÄÊáíåáF®Gê6‘ gah*zõõ—œO_š·ô+/¯ùÊÕ÷’ò~YM™KC'ˆÉÙìJšóY#‹€o ó‰ÑBhZF]Çpÿp¦ð¬Òø¦®Ó”\G¼‡Ÿ<ý÷í7ß$Ï{¾Rf@Ã슛6äßðiHÝ×ÚÍð™'3‚¥Í®çP¾}¦ÏÝWAúÞÿ½ÿ#îxÈXÙùŸù²óõÿêÿ]ÿéD‡uv×ÿµÿÖþ[ûŸyom¨íjíÿõÿø_ããl…»¯¶þßúÿëÿÿýñŸ§ŸÎW3»æ` Ä1Ù XÉ3;ùh„¢ÆÎ݈GŠ˜ÖÐ{ÿýy)¹üòÿ¯ÿõ¿ÂÃ$/H¦LÁ¬,~ ɶfH“Ç߆/cB(èä<€Ö¤ß˜ždN]"Aõ ’µœ÷yµþ­mŸrÓ‘;ñ’wï|¤=ÂÑG1ñÓ&_tüâ‹/B÷«_ý* Ó+;²¦ÚCå®êS…¨®æ“ïã¯;J³ KÈù”Aß üÞÿó.2cdïÿqXãÄøèxÞù¿óŸªó¢‹®1òÐ×Cc.­þŸŽZýý±ëÿóe»þ›³ößÚlpëÊÚÿkÿóoê=ì‰õÿ2?Ø]ëÿ­ÿÿ‡îÿ?ýÉ_ýéΩgÓMÒ("Í‚baé„Aswfå»Î£o0ƒgù(×ki:]™O?ý4±©»ÿá#”§se½·I.x´%ŽÓ pÃçОÇ|…0<‡ÆûúR÷(Ñ P âj»ÝP©÷vœ«ÏöGLúy|äc“ðx>Zù-ZõOZæ_WÄß9 êÝ8|Þ…•S.m¾‚þ+ÿwïß=@.Üór·PÍý™¸/åÇ[?Y‰v§=WøïýŸ€{ÿ3z:o3.vþïü´úÿü8°úÿì^¶¦8ëŠó]ÿÏZÝõ¹vN×ìtÖüÙõí¿Ž‘µÿ~»\¬ý¿öÿýö®/ñÖÿËòѵÄ|Yÿo0€õÿ3.þPýÿ§ÏKÜM†U…D©jÂ4~ºÛHšr eêôz¶= gCÆÜm ´¾|ç™xtê½+,¼û|¸<”_+Nè”qÜéRß%/¹•CŸö]mÌ"©®‹'ÁÈèQI²ÿæúúZä t)¼¼hN¹Ãï@‘YûF&Áµ#Jwøy”QP¦GûºéQÚS¦ùÊ÷EîÒ\çãèDA{“§þ†¡M¸ê»/á?wà^?^Ò›æÚ¯cïÿÞÿ­Œ·@£bÏãnçÿÎú‚1Vÿ_š­þßõÔe×öûZK‹ºÞõí¿1¶c„]ûoíÿêãaíÿõÿºé`ý¿õÿé†õÿgƒÒÏ®G V|L:"™,cdE‰N\ÿµ™ŽD èà¸ô½sÁqs]\(+H«ñæ×Û{°[Ê6bqäÁ{Ê©£2Š]¿ž\x ®ÛQ¤~’X}‘zê9ú”|Ƃެ>¶§,ÙúN |IMö¨3ç©ãjO¸þ´dw¸«ßyåEŽ·ºúR`õ¨MëREwd¡š—‹!8½š«+館ïã£TäZWûVzä™§ðCî½ÿ{ÿ—Ž'çÆŠ±h¼ôÜxr¾óç?-d<¬þ_ý¿ëÿ®ÿÖNXûoí¿Ù½™AqýYûíÿõÿÖÿ[ÿÿl ²d®ÿÿ[ðŸŸ\/qgTp8…@Ÿ¼}Ò€/¼¡­S¢L ”G,8³ÐÁGù¡g¬¤¼Û»q1¸c‡Už{Wî*LÁ'aÊã«lå¹øäÝ\ÊæqD`Ôð{ùê|y08%¨¿írýxÜnĪüòZùGÆ ÇÈ:€ž|ò¨¿aܲCsÕC×¾T¾u?ò8ú7þÚ-h¯ð(;¼Œ¼woßeWƒºå{Xû^™H;<K *œ«ç{K&¡1ÙZ¯sáqÿœïýÏøÙû?cãgÆNÇ óÿg~Ýç’~qtî'oçÆÓ­«ÿWÿïú¿ë¿×þ»~T\ûoíÿµÿ™ •õÿ橦õÿÖÿ_ÿÿl–à‡>^â~wºŽ¾Çk«{=ã·SrŒ2L&=çC,Ï9Ð$mâî`*±Šcw€!àçWYå¼  R@±³” Ä@IDAT÷`ù"bΧ.ÎÐG½ýņôvÀž¾ØÝ×ü(?25©¾Ÿr‡ç¼ ~Ê´žîÀ"§Pdב|²Eþa¤N2ÞÁ.yè ö$Ò„ôÛÄá9eÅå‚ëOåHÞмŸ>)?} ¡Ê×çÞhSù('ôúb÷¨ãžß<ñ]®žK{ÿ÷þÏXMØù¿óõÿCŸ®þßõ×ÿµÿÖþ[û¿v¼˜Ý\{}íÿõÿ:6ê[¹ö( ¸yÇÀ>ãwÍJÞúÇþÐ/ëÿ¯ÿÿ1þóôÕø×oLD t{ží<Î5Ù2¹Ð\»€LJiˆÀ.pMè2à®Çî&½;Ž´Ã³`>—ãï‚Xhä<ŠlSI¿@øòÎÈwfÍõ‹ ª¡W¶ír ,ÃÓ®-Qù—NÜsàUÀ¹ϼ«‹’vD–i/9ñpÈw8o[‡äñúœßòZ·X6â\ >ºÑâÛ€·# Ö$Vù‘í"”Þ¼ÊÓ²H>.¯ŽÒïýŸþÞû¿óŸŽÙù½`•Xýtoõäê«þ¬;Öª‰»æøñȵô]ÿ¯¦?îkú®ÿ§?Öþ[û]ZÛÛØkÿ¯ýoLTG:Ïš»þ_|<ýñ±ÿ6ËËúëÿs[j‹¹0^÷üãñó»æÿ?ýd^⮑‹.©¢,\\Áâ2‰I/­4çîå¤Q:å[ã›òÔh”6Ùí%¸và¡sÑ‹½J¬e¥§³§F¿‚9å}Vsmüæ›o>0ñUÎaçVQìÍä¤â%¿id#'°­åÛ6ò¦ObµÏ…69¦ž<qÕ×¶ëðõN.<’>uv´I{„‹6í>Ê ‘ßi/ù+“<ü*·6LCr=-~äå­2éáÃÇñ(?yáè iëÐJ/­4çøìýßû¿óç?PI7¬þŸ1A·¯þ¬)Yû¦OŒ]ÿÏ»ëÿÚµµª+Öþ[ûŸŽ\ûý?ºaý¿õÿá ëÿüçé§ýgoLŒLÁ6G€ã²pQPɯªÃÓ™v1ŒB?濫pÑ:Ê÷K¤8¾Ÿwf½~u~mâÐs€¼©¿$ón«>2~‚jö!þà||õòUve‘±Ë§G Sf†`)²MÄ»À1uê;·È"ÏÉp— A¢ÚN|ÒŽáå\ ƒsåKW0K>úò—V àK<çäq®Ï{®|ù–®mÒG/¹g¥ÕÿÊ•Gaïÿ°{ÿwþÏÌÙù•³úõ¿õe×ÿçµzϬí»þ½¸ö_”¥9²öß³=\û²víÚÿãpLXûý¿ú`ëÿ­ÿO?ª'øóëÿçÝæ|±â@§þ_¾á¨7è¸v0£àQ@  `1Ñ€9bG;Ù¢ôb:_%BÆî\„®[Å]ü:å’?uã%°¤~‡÷[•V~ë&§ëÈ0eðà`ÔqŽö ½4‡:•W–œø(—zcêŸ<ÁÎ"A™@gùIrøØe èqÒÓÁÚ2‡vØá•¯#mÛðöÚá¥îBûL~úqhÛm/>íôúàäJßåz$™¼ä<è½K+íOÍ!yä+‡¿#ûÄÓí³Ê¿÷ÿ€{ÿ ½óæã™JA3shçÿêÿÙ};ú·úsõÿ®ÿl]ÿÇ›y¡/¢3×þ[ûoìO¶çÚÿϯ.1?Öþ?¾gý¡õÿÖÿãc³»þÿô«øCðÿŸ¾ü«Ÿ¿±s©€ß« G€ŽY@(;rt :€PÈ5CÜ"#ݹ´F®O8`~Þ]Å@Rç)ÀåZ_­Éo}­Ãµ²_ýõ'Ÿ}öYvAM¡”³¥N>YK_påÕìTÂ[>Y4nò\ *øõÑ1ü¦®)–²Êµ*@0í8: >‡ö+€É.µ‚gÚ‡wv©‡<¡&nž˜¼÷àZ: Š<‚ÅlC«ï&¬÷ ¾öoxëó¶oïºjïÿSÆIΗŽ}cgçÿÑ_;ÿWÿÓ÷«ÿwý·ïú¿ößÚkÿ×î^ûý?öòúëÿ¯ÿ6ÏüCã?O_þòçoÆòŠÃ qp^\sìý â¼í‹±üb0©³[à*ÉÐL¹À• .¯¿Ô= Ò3ÙïÎó¤ÙÑñî½ÇG¦¹Æó‹/¾øä»‘Gž—¸¿¡s2§í ¯GålеäÞöä)@¥}¼ô‘íŠë¸*+ÈÚ¹ž¢ÚÌÙ÷ò÷WË—'M;Ô£_¥GNõM@SY¤—¿¼<ö8r©rêšò.ù“˜{ SŸð1_à!:å•q8op­{ÿÏBä^ìýŸ÷ìüϼ0O:?Í›ÎCsrçÿõ¥×Ñ!«ÿWÿ[{:WÌ›®QVéŽÎ!1=»ëÿ®ÿkÿ=ÛÌkÿ­ý_;}íÿõÿ¬£ëÿ­ÿ_¿ãÍÿÿÁüÏÿé7Ý•¹p9aΔvøäÅè“Þ­¼CÐè°¾0ýóÏ?ÿäÛo¿Í×ýÄ5FÑ9/xâ¨c÷QÚ¶“4êÍV' JSFP®ÀН ¢û›ÿ÷o>ùôõ§§üÐÜg²cë t©ÀÓÅ@=¯Ó'©ßùµ# ’>‰©«@—Ë{­´ðYåä+È¥nyê%«:cÀOºþôñD²´_•qxôÆ}ô€->Îѹ–ﺱ|õ òË™Ýs#‡ÝXÚ6A™òÇoïÿÞÿÿgGæÎÿó(÷êÿ³Û—ž\ý¿ëÿ®ÿçƒ9kÿ­ý·öÿølï±¥×þö%¬•õMκ¹þ_}®õÿŽ;Žçúÿ£7Ìþ9\eýÿƒkü÷ðŸìÀŠc6§³üê9'Ï@Ƶ©Àå㈆¾ò”£¬#y±øÄwàfX o èËS\œ›àuw§’]TêÁßbéqÁwÙáä¥íÊÅÁÆù²á\+%1eµKðqîP×£|r$ÐÈ`:€Ðs;\žó~¬iO䜯 Š] xýêW¿ z!@Ò¤'žkôúì»i Y\Û]¦=øãh¨ë&«$4£æ–œ>+ôä_írÏа:¹SžÌÚ÷êP6å‡YÚ6u’ù‘®ð•·÷ï¿1j|ìüßùïÆÃ=D/Ný±úõdže¤kJÇFv¸Î81fºöìú¿ë¿ñ±ößÚì ëËÚÿÇ‚Þ\ûý¿õÿbK¬ÿ?FÕåó³ø÷tÄï£ÿÿôã_~õð‘jlZ,å.-@ë1*PihYމ¼¼?J<iw‡˜ã:Ž{Yç½.ï:;8 C¯ÄÈC®„}wdÈ™Œ¾T^€ÍM°ãÉ"HFüÎÞK%hç­Ò#á«<ùÐWÎð¼ÒSpþHÃ˯ó^ÚîšÌ¡üׯt{{Þ‰¥oäëøîþ’nðiߨÎcú7¼†>ý-¾@­LÞi¥GvFȳ mv}áÛÓ£Å/»ÐæñÊü3ÀÕ—?{ÿ÷þïüßù4èêÿ3èÜÕÿ»þïú ŽÁÀf¸lócí¿µÿÖþ_û?z`tÃúëÿ ëÿ¯ÿ_{áÿyúÉ/¾zSÆbÆHÞý4ç @ gÞtô}Nzí€"v`|óÍ7átš“Z„ŽàЂ޵Á¼yTOHý“V€ÏnÉõËþë<ööë#Ë\«ƒ,û{õêõ”ÉûgF6|(Ñð™øYçqÈÔ?üÕiÑM<ôh#Ó¤ d”'-}2±v—MÓÅkõ¡õIÒñ˜“ûKÖÏö¸yGÕdx\Q(o²;Â÷°iÒÆÈ<)},:i]@Ô_~“^ø5­ò&aþ¤ìÐ òöþïýßù¿óõÿêÿ]ÿwý_ûol¢µÿνkÿg, gãIþ O\¿x9/}Ÿ¥ÃS[ðQÏî,³ÛKè5º?@»«ð‘N~iÀÃÈ2}$Ï#’xОù ¡kmÐýzèU§,~dIÞ#£ëÔ=ù•- {½÷ï¿1cüôÈØºæˆó,;ÿwþG§P«ÿWÿ[G¬]»þïú¿öß³½·ö_ŒËØ—lvflÓµÿ£/×þ_ÿϼ0'Öÿ[ÿýÿgLèÿ €UgÕN,22 þì™tyB@'ñ^Êrb^ xõý¼hܯ´Œq&æ€'‚²\ ,ðÝ^RŽã,MYeâ4+0Áueu]r$o”]Z¯\¨ür|: gäºC †¸8ïÕº@:2OEi#>‚z ¡ͤw‘8uɯOý«ì})ººð¬á›ë‹‡¶Û‰¥ßý≮ŠŸ¶7}ãzÚæ±CrI“Ÿç^/Y Îåc§™úÐ â{ÿ÷þ_ã˸Øùð™;ÿg\Ð=ÂêÿÕÿÖ™knìú¿ëÿÚ¤Yûoízñø$kÿ[+ôÅúãŸ]E[ÿoý~Åúÿƒ8?öâoƒÿÀ¢`tfŒ\Ï ¥D±û©òå〢KIØñÒôן¾`à¡´ ¼àh ¸2ç/žÎ#xx É1çå©,wɵ îy®?€2Š§Â¤*Û]\ISúñþ,ùäSNXõš|Êz ]A#ôá?tò“«í’æ:2IŸÝ`xËo^yaèx_ÐMß´}b­ àKý“Vzß_Ê´¿R×\£MÀÏÑëIÌõ¤=Bini{ÿ÷þÇ;ÿwþ¯þ??’З«ÿgÇÕµ^é‹]ÿwýϼXûïaŸ­ý·ö?{íÿkgMúbý¿úa|³õÿÎîu}‘ãòAÙ9fQÑ_Âã¯&uÒ§lt-ßvÊ ±Ïøå“õÿ?ýÿ§ŸþõŸ½xCº©ƒÀ@0°>Þe0qhÄ@–&sÝIi@V”Ç·4kêj,ï>@;Þİ¿-_y‡¿#È@}ùâeês-ϯ‚N^HEï¢XÝ^d.Oíí.ƒçä@CfÁÄiÛ\£6©ã.{y6ÒšŠÒ?á—þ8C¢É¯wã%ßµÏߨµ6m11MHÿ•’Ÿô<&®=®‰°¨fd#ãU‡ë½ÿ{ÿåÿÑ&Ñw;ÿŽ¥_VÿýºúÿÌkÆ®ÿ»þkÿûkí¿µÿ×þ?þ‹urý¿ñÀâ³5sý¿³Ùƒ¯É'®Ï©„ƹ¸®¥5½±|åëW§w‡nýÿkËô'(þ¬3Å Hó™Ç× xÌPÉn©<Ê6ù|Þå¹]×v K.fè Àô«wÄ€ Ra ÏŸRñƒöÊlžKårD¶îH³ìñØÞ5øÝL TøÐ|öùgŸ|ýõ×_Ñ™LuNðpt¢IWÞc}#a¾ö‡×ûîuLùèqM–Êøj¾88Y©Oež^œÅkÊPUpŒs >ùêÖ¥¾˜˜ëKu DIFéV²çzòÕ'èîÊšøJ“z'WØû¿÷çÿÎÿÕÿÇÐZý¿ëÿ®ÿçã=L¶»bí¿µÿÖþ?~FììË–g_wž˜+kÿÏëPÆg±Žò5Ò?ëÿ¿ë3ëÿeÊœ±1§ÆÈc¬œ¬GÞ}nlbýÿ?dÿÿéŸÿÅ—o@åý;Cc¶ƒKšGý€'Rìò¾%PJ~3àt¢ÇÑ|ŒLÎæGyÍĽí©3#7´¥3Xï简:Ãàð™ÓîðL)™ÂÒó¸ã%?ÀÇ–Þ/¾ø" ùñ:4 ÚMî†ÓÈz;üɬ ~iëЫo˜=djŸ’¥ýòà72È¿× À !’®S²lèȨž‚U¡ 2â£\û)ýyU$¯”½î‘,}g· ùñª¬á±÷?ý±÷çÿ52 dìü_ýOŸ®þßõ×ÿµÿè‚Ú`kÿ­ý?ÆxìñÚÔkÿ¯ÿ·þßÁ꣮ÿ¿þ?l¼"˜Ãx[ƒQ#'ü¯ûyý1qñŸ§Ÿüâ«7˜8Rx€•ë¼hÑ5ŒíŸÊirà§ýBwŒ9'¿òŽÊG 44ÒÍ0–úÊÚ6£6L†ÓÈA–'ñ’}ïÿÞÿÿ;ÿo:lõÿêkÉ®ÿg½¶Æîú¿ößÚkÿG'®ý¿þßúÿ–_ºþÿÁ êoóÝ×ÿ?›uþ-🧟ýö×o˜\»®ÚÙÒœ ŒXÛ ;‘'♼urÐ{¬ÐgBç–}ñúõëSnhðùœ_À–aŸº§¬¸u€q1å Ð<òæDþd†dÊUi~ah _)f-”²Ã㫯¾ ˆ¥n V%ò¶íbõ™œ}ïCó6µ¾‰iò*ù}Í0€Ó0ib`TxNÎI^*߉¯¬~ZO[äú“~ Õ³q§ÐòWvúä^}yvוk2ÜéÑíýßû¿óÿ¼÷Ïqìü_ýÿXof<¬þßõ¿ëgÖâ»þ¯ý·ößgvëØ“g~¬ý¿öÿñýøõIâ—¸ýÉ£©ÿ#Ýuã¬ÿ—þÑ™SÓ)ëÿg3Èúÿ¹ûól!ólÎå}Wýÿ§ÿí/Þè¹Z4¬ïºÒX×Þ)åÜΪvDÀLƒI$ÿ~´Ó,èÉ¿T×äûJ _v„¥|¾â¤f‡¼$P~¿¢FA=nÌ7³Ûêõ«×‰ýêÕÙ%†_TÅ7õ;·;+Î&®|ø•ÎcŠêÈõŠ•ûøáì>K/øâF¶ö—~t¯²cmhô1žhì {Ô?ihJúlè”Q—Xºº(úžçúª ]weIo»ðu^s.8ßû?që§½ÿ;ÿwþ¯þ§+WÿŸõ1kѬ»þïúÃaþÔöÉ<1WæØkÿú¢öÜÚkÿ³3ÙÜkÿ¯ÿgM]ÿoýÿ,š£ü8ºþÿÁPjKÌâùÅÓ¯ÿþ?¼RB€R^Ø~&ÏV—áQc$ÍÊõôlÀe”ðF(ÒŹiÊ4 €Òw85]Œ_¶è‡“°"ÞÒ ­\tÝt_biCùØ-å1B4Úãæ÷%èøvÇ•üÖQYÐûñì¦"жÕ ¨áe§þÀ'íBƒ´”Ÿs»¾€YdMŸN•UÅ (Èðé9¹„”k `¦6åÕ‰wôÎÓÏÎ%\Aº n¿9x6ü÷þ°÷`ïÿÎÿΙÿÇÐæýE›Ð#ÎWÿ¯þ76ãüÉ4çMëÚšñ3é»þïúÏBé¸Ó'kÿ[pí¿µÿéεÿ×ÿãóÆg[ÿoýÿõÿ6¦9ñô“¿ûÕ[Š’Q@Åõ—_~°QÄÓy€y>cˆÊwsb¶Î‹ ‚… €)ǶM gˆÑË~4×ûx¼“É2>´sÞú*WÙ¢S_Ê 9 !½udA˜¶*«Þa¼)/¼•ײè‡{}ê’Ž@nçc’ç]!-ŸøÐ.ÂDÒi¿Ÿf¼¦®¾'ÌuŒÿ¡Ì èqüòLÿxuxƒSe ¹¾.Ò„Fvêºúuïÿ€’s_Ú×{ÿwþïü?s¢º1úgõÿêëº5ìZ›œ »þŸÝÐ5{×ÿµÿ®¹1ÆV戹²ö{>Ý‘?µÍ×þ_ûŸÍEö}Ìñ_ÌËOá³t½©]òIòæH™õÿÒ-é‹9‹O¨oaý¿õÿ;>¾«þÿÓ/þóÿý–ðDÊÁ!]#ïJõÁßr¡›O”N@˜áa—;¡ò^¬kòd"©d®“ü~0‡q<»›Ô`誫Sïž®Ld$ ß›Gü€CÝ Å¨Ö†‚jïÞ½‹¡ÝöˆkˆGyŽhÒȤ~‡à1DH|üöì¨j¾<í(øäZ^y„çÕ†¶™’uîq´SçsâU9¹ø‘ï“/g'pK»í1úð¾Î'J¸§9/ïæ“¯4{ÿ÷þ?æñŒaçÿÎ:fõÿÑ «ÿ}°ëÿ|™x®ÿ³›}í¿O‚Y;×þcç®ý¿öÿúY(ØÓ—oßm®×ÿ[ÿß:Áÿ¦'êË×G_ÿÿã?O?ùÍ/ßF<¨ó „8éÂËPt¢ SMò*M‡£Ññò88ú¨ÛÐ$\‘óÞ(´‚Gý^¾x™ILrÅ×ó'yɿҒn}œ2òõ—·vU6²úÕÃQȬ¬wUEvm›´båƒP%Ýy¿²¨¼#Î=ld(o²ô± er 1úSf@­Kî¶Åî140§êU?Eç÷®…©mlƒgÀJZë ?4·~kžXÛȰ÷ïÿÎÿÿt½B'Ð ô†cõÿÑ©«ÿwýßõí?zrí¿cW®ý¿ö?ÿ§>V|¨õÿþÛúëÿâ¯ÿÿÀ#Š­üà?ß^¯½¤|Êí%ç:^Zo@+t-äzN«¼º ôòúË×áSø4à/ˆ•E”á85ýå|)ðÍ›7Ù¥5óÿM•Á¤@“gÇ–ü*R< ¶õÅîd )¯œºµÝ5Ú; ä\š¼Ö×6+wOãø ê.}ÛGûOÊ,Ïh_}Ñ~kòg÷Y e2Oû¾?íÓ?ê> Ö “7`\ƒ|Çç¡éø;W®uîýßûo¼ìü„wþ¯þ_ý¿ë×súÑz)X?¥ Òvý_ûÏXXûoìóë$kÿ?fíÿãk˜ކú(âõÿŽý¬?Öÿ3.Öÿ?¯tbc¬ÿÿÏã?O¿ø/ÿþíXeyÇ… |1™ì|ª—øz/U ¹æ)+Í Sîtøó¯÷”–4柅-ts-àAyÑzœüÔ1$dA#Í!H+@¤ìÃÙ´³ ¯É¿Ë£ü‡ó•ÂÉ}½˜4ʘÐôÚn¦8/“§N€‘Ø{²€r}„ Oññ¯*$òõW*Ú¦ÚåZÛêKÎÕ`J]S”¼y4Ò;¾æŸ6)_9œß²# OåÒµ'ùÓLÞñ¢ríýŸþßûŸ1hæØù¿óÿÒ“ôMÇÝAÐ;«ÿÏÚ³ú×ÿ]ÿ}AWÐ,¾µÿÖþË:1ãA°†¬ý¿öÿúg½4ÌõÿF?̾hûD¿õ›¯ÿ¿þÿÓÿõÿþø­¯zw”Áq‹#ïXÊŽ¡™TŒ10G0ˆ„,C7çÅ ³ mŸ2Ì—î~Ê@œ2Ý…VT1L[¶y€²9¤EÎË™R½Ø`—Ÿó¡­ÙÔGRŸOˆSùyD/†ÖÕžÊ'_ºk—Ó§Ž©KÈã|Oçñ>×£UsŽ.²]»¿RÿÈy–ÓW½ sÂÕ´BÛÕëIˆæ‘Kü“®ÌUýƒ6FŽë½]赟L‚]lÚ³÷ïÿÎÿó²rsÇÚù?_’µcôÒ©tÇêÿÕÿÖ®»þïúÏV¤/éñÚkÿ t„µcíÿñMÖþ_ÿïz½LžÀ±ˆNXÿïyg^ÖkÉôKu="¬ÿÎt†µvüùõÿ¯MG?›—¸01@fÁñþ'ƒ©@#U~A‘\“–íÂ3àÐMÊ݃ë Ì‹§ó8A4¹vü˜êcLÙµ4eÔ‰¿Ï—Ï—óX!yð‘Gn¿x7(Kíp“?y)ûásLôhŸü~渠 ÐÄ¡ ÿa%ñ62äübZ¸ý•ú¦¬mÞ_•~Z²‡öÚv]™R?æ@ÓCÝ-K.ùÊ“MËÝïUyàFye¾XH™Ißûÿ úµO|Érï¿~;ÿwþ¯þ_ýVÊ]ÿϣƻþµö_lŵÿÖþA=bÓ_¶¹4ö¤µcíÿãÓ¬ÿ7þõŒ þØú牟õÿiŠâŽÎ×÷¯ÿ~$ûÿÉKÜŽú€2:* Ç€DÎį́RÖÅ:6×3 ÅŽù“Þ×ѽydm€è©ÇàZ.u]“W! ÊdfQš9oŒ«Éî°; Ýûyä/ïmšó*‚Ðd§•sïÃÊù””õk‡Ãæ28ø’ÿõï~÷Ü–¡ÀƒœhÒ¾IKnÍE®õ4P-t÷rÚ-¯¤·­â;Ø„¦}—¾’0¼š†ûE•§uµÞ#‹€Vhù8žvØyue¦üÒŽ½ÿé–½ÿç ;ÿwþ¯þ?k[õíêÿ]ÿwý÷KùÚkÿ­ý¿öÿ¬ã§|‘úëÿ>ÑÂúg½ˆ¯9ã„=%ÄO>â£×¿mŒBï9Öÿ_ÿ”Ë…ÿ<ýô·¿~ /@TqhEüêêº;¡ (ÊJº'¯@Š ›Á9£½GÔ䕯sTñKÙ)# Q^\~Œ„Ès•^õ½UÐ8Ê3~òSÖΨ ê¶û*r_ü“æ*óûÙÖéÓ×xzaüW¿ûê‹7_¾9e/yL"ÊG°s©<É×Ð ÷h{3®˜ Þƒå—uQîÚ”Ýa7Z<Ãwä==bâžm–x ­Wìž½ûæ]¶âçZÛf1QÀ±<\ë{õã³÷ïÿÎÿÿô=};ºcõÿÙ¸ú×kæ®ÿ—ƒ:}ÁnXûϨ8NÛjí¿óƒëÚÿg\ôïÚÿëÿ­ÿwìJëÆúÿëÿÿÏž~õ÷ÿÏ[/Ñ3°â°Œã’÷=q`F: < º õO¹'{’7ùø \[Ü[‡ó‚,sçÆàeÊè¹ê‘þÕW_Í ^EŽw_ýiýC¯¾©,ïwÂOùÖ-´Azw"á‹Ö!ôÁ ò ¤»‡¶ †VûRÏìSG-e´Ù!´Ý}'9ïý¢ëÏéw]úO¯ôÙË‘5·fþ Ÿ¶Me@§¼÷‹]íˆ<’§Y¯^¿šG ÷þïýßù¿ót]8HE¬þ_ý?‹HÖœ]ÿ­¤çUÖÕ]ÿ×þ[ûoíÿµÿ¯÷‡Žnôcþp¬ÿ·þ_}åú§ÆEýàú©ìîø´W¼þíîõÿÿ%üçé¯þæo ¤:xÄq™Aæš2:_®;@ :¢p9²<©(™rkÄ=/ø’2ØÒ41º*=¢´^«Ïg$9SgùÑ~”øýœ¿~ý:éåÛú¦06vDM/ß>ò¦´E[“íÿñÛ)%,/uT9;ïD·?”W~â”GPЯÒÈpúð%ü(u “×/?JÇ·}ƒœÉ«¯Ê—|älyõÀ*ô:õj¯óð˜¼Ê&^)¿÷ï¿ñ¶óç?ݳúõÿ®ÿ»þ¯ýwlÉØ\c/Ýí>ikÿ­ý¿öÿútÁúëÿǧ^ÿ?ƒ¾1~¥`Žôàk Å8¬£Ž¦õú_ž~>/qGŒ10$¿( Ôa26È+/ìy<ÏK®¥ÅáB`:I'üùõþ€1x•^™ÖÓ/öÉÈÈ·ñPçês®Ù€<êSoëC—”OZq1:éø¦ã¦°ò “Üñ¨ãËW/¿xýêuÎÑ*—cø êR¾m,x¤Û-bš¦íþÙe¥¬ ¿*Gd¼ôÚ«•=Ã3ð§\8\rÜÛ‰¯÷]Iãl¦×Ä‘§-­£}„à£thÒ¶IÃÃùÞÿ½ÿ—;ÿwþÓ#ÝP±úõÿ®ÿÇÆÙõí¿èÆÑ‘kÿ­ý¿öÿúì¤õÿÖÿ_ÿÿ þóô³ypÅvx‹1ÐC ÌP(féŽ8¸&) kèæO¾Âײʡ«2ÇûH]^ %ßîž³œ_ü'Mʉ*Ë$e;ªø!Û”+]룲¢Í­¡óΩ%0ÌŽ®©ø?Ú{ÉKFé?ýÓ?}ñúË/m¶6 Õð$™õYœ{±¼6Èû ]m“WY+ZŸNE—þëð¾¾tæó˜ê”h¹¶ó̹ Í-_@ _u©}ÒÏYÛ¥,~©ëºoŸÔ3<÷þŸñ¸÷çÿÎÿÕÿ«ÿwý·^:vý_ûoí¿µÿù&±¡Ç¦^ûý¿õÿÖÿ_ÿÿ/þ3þü­Åðȹ7‡Â.Ø!¯‘t Mßᄦ|Ð9u‡•P@¤Lú‹6»ž.àG:PÇ L‚rdÉùÄ”¾ мÈ41Ú*qAÊ'?€™6O¾XÀ òúÁ£•ܽÝÚ¨ð”‘ûÃÇóÅÆSßóã{#Pê‰|§©«2Ê×J@Ù²Kjø;ÿr€´¼¿j(ÂwÒ|9P†Ÿ4ò¡¾ ˆ¦ÌÅS_£жnôí—½ÿ§ÿ÷þg˜dœcÆGÃ}Ì Úù¿ó?Cé‘à|õÿèÛ™#3‘VÿÏxØõl¦]ÿ³fÐkÿ@釵ÿÖþ¯­¾öÿú|µõÿÖÿ_ÿÿ¿ÿÀâp˜0€kÀË 1‰â\÷xç×ËË=¯èß#èñµ»§€O“‚/Œ[.?¼?ï´Bo7’ÇÜÐ:;x`¡à/Ž ..ÚszÊ)+(‹GÏsr¥§Ýó"ó–èú^¨oÞó([9È+(´Ò pmô˜žjc°OýY}ª I;}èÜ{¯„¾£JšvZÌ„ì^C7õõNš~U·ôö¹¾ÁCº8íž8|¯8<¾ýTvi{ÿã½÷Æ­1yÍ» Ä;BÇ™x•„¯×øÚùý·óÿè7ã…^Yý­©«ÿ³Ñ»þ[`×ÿµÿèɵÿÖþŒÉF_ûý¿õÿ>kýõÿ×ÿÏZyÞþúÿûo/æ«v}7"i &Fç¨Ö$ʼn44€åjŠ&¯ç¾t§ À‡C\±k)_ÐŒ·Œ—êxñt%”öq€–xÓÃTídñ¨à:r]ƒkõŠ#ó8Õx ¡X¾C>Y>~8»¾ì¬’f'“ÐG•\I—_9»ã my’7çS& ÒH©ÍÊ•®å=æ×jòíCûÜšó¤úTïÞ½KÝåÕö¨§0â'}úrbò <»Ò(Ð ÿ½ÿyOš¾Ûûÿퟂúêý7ó"ú¥€mÒ”›ü{ʬ(Š´á’Eu£-ßÖ•¾¼Üû¿÷çÿÎÿQ«ÿG'®þ?ë«å¡ë†¸ç»þïúÏŽèû8Ù~L[ûoí?:ƒ½;síÝœî\ûý?þïúëÿÓ‘ëÿŸ NwÛòé'¿ùå[Æ„à‘¼€¹: cCxÅÊqy:>}Ôèa´^y„pÒÈÅH'Oh¼}ê?òMÞ@!¼túse©øj·~ÂSý ¾Ð^¼•‰<# yä¦÷ô´q.T9ù:åÑFΡA·÷ú}ïÿÎÿ™æÞÎäèeúB 3ôU=å²ç¥KëOóVÿŸVÿïúßù±ëÿÚtéÚÇ9[ûíÿõÿÖÿ[ÿÿlÚYÿÿ_Æž~üw¿zË ŠƒRËj⻡m­2nÌ¡âËäÝ7Ï»™âÜ\¼q^”}H}ýõ×®(À,  :¼<X0E¾pÕ–s|È d#_eA#ý‘9¡á{K?ׄ»Di_AçÊ ê Ëï~÷»Ä@7_,°”:†FÝÚ/îc|òÎ;.)ç^á9ti‡v_çÁFå{h£Ã5ÙÄêÅ7×#×Ë‘Uº4rÿî«ße·˜4òÈoHÃïoß(†æ!S 'Þû¿÷¿ÃÁXÚù¿óÿ|Íõè Šsõÿù:­5¢úV¼úÿŒk’þx»þG¥vÍï{2]ïú¿öú˜+ôÈÚºäôMlصÿ×þŸ¹±þßú”A/<ôÃ¥7Ù÷ôÐ^þîúÿþÿÓ/ÿË¿[°È o(€áFw`4ï±ÈŽA:«lZâ¥å]x,½³{HPG¸QÀ пùòM”2:ùÒ-gÁ’úY˜]E5åTÆÐ_2IWgÛ'Mºiox Lêµ»Ênœóø¯Ðè/ÿò/¿ø‡ø‡/~ô£EÎNuà¥/Ÿç¼LBv³_ºÃc&6Bõqåq”påë»ÄÚ–#mgê //¯Ÿ6Ú%f—™XžCÐ ÛT9¼Ïn¬´×Åõj—4»²È'´¼óÊ´÷ïÇ£q!ìü?»ÍaçÿÙ]Dá¬þ_ýoípìú¿ëÿÚkÿ­ý¿ö?;‰Ÿ±þßñ=õÇú³dü[¶Âúÿ3?®w‰×ßZÿÿ_Æž~:;°(ƒ€¡ó„"”}ü1j‡Tœµyù¸XSg6 ²±ß˜5L3@ðƒÌËØÏWñÐÛyUK]u[·A÷#LåO¾‚9êr(—²WÜòh嫜sùm£sm"GÁ+<…ÖÕ6¡þâ/þ"; ì‚Ò&±Ï\Š`þ|ç2çøà . häÀÒi¾7 RånýÀ<ùßËD¢Ô+ xÕÇ Ý3åÞ`¨LîÙ%>xËäU–ÖÕ¾‘¿÷ÿ8'údïÿÎs}çÿêÿÕÿ»þïú¿ößÚg‡%2ö÷Úÿkÿ¯5Î Gjý¿ñ¿þÕÍçZÿïö”“±2!úcâõÿφþúúÿg}Ñ ÿyúÙoý¸ƒà1€f¢FЊóNBÀ‡gÕM@eZV,XI× Ü €tßypó Ê9Zwvüà5»™ ,©'[ì‡á^¿²•Źú] ‘ÿZ\?©‡ü“oêà©^eR×¥t”o<++õçèû./4€CÚïZ~ùö±}êK€øè}‚¦uê7í÷ØNöMá•Ã[ºØã‚ë‘§¿²ìjCÛ¡ŽÊ~¥ã#÷þŸqÖ~Ûû@Xý°óçÿ]ÿV§«ÿÏ@«ÿwýßõí¿µÿÖþ_ûý?6Rl¦ñùëÿÅÕ|ø¢õ=×ÿ?˜Ãúÿÿ}øÏÓÿöoM,“Jpî±2 ApgÒç&b'ãËWóÎK:øÄá¹ÒÏ£lQ `r=§¶%ÃS ØÁ¿À‰òBeã(ãZ@ûúË×¹v^ À'áRmÛIlÖs{§ðÈ{v'iúòtÎ1»·Qž>.`ôêå«Ç;½²Û ß é—«ß\ãé>½™8çC#](à§-ísõi¯ÅÊ™”ÐjxÈùæÍ›€[ÝÆ7òÜã^·^y{ÿ÷þïüÞá¹óÿYçV÷ЫÿWÿ[ü¬A‚ظÈÎÞ]ÿŸ×rý²ëÿ±{Öþ;ý°ößÚÿ£Öþ_ÿϺé`[Õ[ÿ/&ű'FW®ÿðöUmðõÿ_ñôW€•Gé뤙I™L&V’h:ÉÚ/ž­teZRƒVšÀ€ûöÛyŸSCyÙE4±¯çááN&/ž Ôdj:ÚÃo¤L Œ ¨ z”•qiÚðsïò/Gñìx’Α•î¼}Ð_W*³ºÉѶ=ꡜoó˜`ä›kÿ„üKÇ?@Ôä«§i­ï”¹cS¾A£|e”Þ—Ï¿z}À5õÕ!/Otä•..¿òÙû¿÷@{÷ÆÎÎÿ³ûR_ìü_ý_}½ú×ÿ]ÿ=¥„µÿÖþ[ûíÿõÿÖÿãWÞm$O­ÿ¿þ?Üá_‹ÿ<ý»¿ùù[ Œž·,¸Áè80‰ÍI´ÌºP (éI9@‘ü‚Í+-1#?É”Cï“™„¶K`èØ½4„³£él?NÃ.ð<ñ—îh½Ò›fØH½‚8iÒçPÏ•ñhïIx.ƒÿç ’¾’®ß^8dç“vàôqÀ*/A"ÇT)íñÒ62M¥u‚÷‘ìí't{ÿ§ç\#áêݽÿíÌ“ Æ»`ì IÏÙé«ÎCqóJ»ó:pçôÝ#'«ÿ_ý¿ë¿ù0ã :Öb´ëÿÚkÿ±¿Ù¶kÿŸ'Qº~®ý¿þßúÏOMÕ¯5?øtü¾uýbqÒ¤Ï&aâú;'Ṍ5yýÿÿ3ý¿ìÀrÃÜX7 ˜Á©°PÔ ­QÕ›ïºçŸÇOó‚÷:(ñáÈâ)Üùžôy\gþ©_`ÈÙññþ›÷‘zZ+t“^Þ¹¹€6á?ôu Ì–OÁùƒ_ͪc‰¦Á¹z˯2K¯œ¥õ.+ˆTz}ÔǰÊ×N+4í?‹OÚ:qÛÚÈqdI]s­?*§º*O'§rú¥-h䙯ç±ÀÈ>ïûd’c6!y{ÿOg\ý±÷ÿšg3fcĸëØrÞ´Æ;ÿþÙù~Q2nªÛVÿ¯þïx›#»þŸô:GèQëõüÑEÇÖ˜ë]ÿ×þ[ûïØkÿ¯ýO7ú{õf®g=©ÿE‡®ÿwÞ¯¬/<emñnéõÿÎüYÿ߬9!cã;èÿ ùü¨…pv½N\àH+{ ªüj>Õh%"[úâÒ$\i=Ç›‚QÆKÊÄì´oÞ}ÐÌcnoæ«~á6~øÃfÂ…hуºŽñkR> (Ö6€¤"¨/ÚN@Tß)EØÑ$蟖Õ^ý0ïrøÑȷ댼U(ICƒàÐåÝV“vzúd*×vFöI78o½äµðûUWzenß)³÷¿câÜ¿ÞCñÞÿ3ªŒåÿ;ÿƒèœK׫ÿWÿïú¿ël޳\î:_ûïüà£;Öþ[ûíÿñUæÿúçI¢õÿÖÿ7ž=ø³p®ÿ?¨\ã:ôÜ"øÏOç+„ ¿Ž{t`“r8×{ÿwþgŽÎ˜vþ¯þ_ý¿ë?]ÐuÖÚºëÿ±Õ¬kÿ­ýW;Ê<Öþ_ûý¿õÿÖÿ_ÿ†ÇÈ_û_ƒÿäXŒ/Œìf~?Û ¥Gÿpâë¼[Œ²ëi(eêè3c †t· Î>]ȦÄüÏN¬!È Gxô5[N3ù&õy·KÈ#|sͽ,€“ΘrdqA/¸ÖWb¡têH6/˜÷öüútúÐÕXsdÄøé+çí¼{GûmˆCû¥]g7yœãÁA®Lù ÃЇnâ‚hd¤kk¯Ûב'÷sîÃUš–ø»&ÓÞÿ½ÿÆÒÎÿçgêwþwõÿêë„õd×ÿ1º&XsÙâ]ÿ×þ3Öþ;6¼¾ /̆ڤçz¬âù¿öÿ·_¬ý¿þŸù"˜#Î×ÿ;~íÑQñ_«CÖÿ?8+3ŽþÿÓO~óË·: ÍŒøº˜î©Áj2é ‡4'`¥Øy|OðŒmY®?mðLgÏ×óu?à“ÊÎzöIYàJê»xôfÝùÊœ0å “éF’9å']Ûи.ϔі iû”I<×uÖ¥iß¼ Ý£ÙéEΡm9çÊbÌÎ?×ä’—¶Þ€1;°¸B§Ð¶>2}ÎÛ£•µ<µá¤ç˜ÄÞ+×Ê >€—{ãÂÔ1×vÓ¡ÒveæØûܽÿÇaí˜2n2^&îÜù¿ó߸ðOXý¿ú?kѵ®dPÌŸ]ÿ=µëÿÚkÿý°öl¨µÿ×ÿ[ÿo „õÿ㯯ÿ° vc±çBñŒsuþ>ýx,öȼ@ŒvdÓã¸Öañ³â|hý›s p©¹øRÒÎMTeðìuø_¼ˆTðI~@•‹oêGp…^7î»7¸QdÁרîÎÂOÞúíÞÍ¿´ÍùÐíýßûoL•ÆÃÎÿÿÑM—¢?ªSWÿ¯þ§#ºÕp§<²¾ŒÙõß }ë±ôM×cº6ù»þŸ~¸úcí¿tGÆÉÚkÿ¯ý¿þ_}Gš¡k®óõÿþ°þÿwßÿúÉoõÖ Žɸœ£Æ¤¸Fhâ¦ÎÙ…y޹ô¥•åQ¾^{Þ]ˆ†÷œ›X5^k˜qrCÕ“ï`¬É'~ÎÎåÛs×=+€jº4GùÝu¥þyT°NYœ ÷>(/<„>:  ïᥠٱ5õ+‹÷=´=zC^e­lâ†tõuº9ëc¡rHûô˜>+“‰ïy(×d&«àzþ<îgÓîm'oÂÞÿG¿ïýwÆÊÎÿÿ«ÿWÿg}±öíú¿ëÿ ±SØ(s¾öß±gõÆÚÇŽŽý½öæIlñciW‹m>áØìÇÞZûÿô ½rﯞ§¯fýYÿï $ýÑcý¿ƒ#¬ÿÿÝ÷ÿŸ~úw¿z{Œ 2ø”º+„ClÑò4%é,DxÅ‘½4á?4åU`È¢uÏS.»Mì—ØÇ ãU|…òßæ‹$<‘ï’cˆõ£QVý¬ÈQÐɹôLt2Íèén.J1@ÕM€—~Qo¼u(/$eò*ò®²ú3mŸ˜ uË·eRÇÅÇ{ºsmW÷wi ¶¹nþÁ¦öþwìîýž_ÆÈc¬œ3 'mçÿé§ÿ«ÿWÿ[wý§+wý?ú }1c⾆X[…µÿžmRóƱöß±·×þ_ûý¿õÿ²PÜþÔßÉúÿÓ7.þÿ“¯Z8Ýõ]$÷AÑó‚%¹€(+ØÜUéñ.?‹’òu¼/% À p3G¯•W¶€ÂpÏyy‰ååÅãÃTÙ€ä™Ð|ÿÅ0¸í¦R®|ZFùÊÚü8¥Ãë|5å<µ{úÍU>è4uDøGÎÉWJ½ŽôÅÄòð)?q¸O^A²{ÊÐ_ùê»ó•W~ʕӚo‹±@–ä ã½ÿg¬îý?ã;ä³?kIž±3ƒ'vçÿó»åvþ?º¥ºvõÿê#c×ÿ]ÿ­±kÿ­ýg8ØÕ±­¯kö…µC^lÖ¹vÞµDìzíÿµÿ9@ÆN}9c§ãcý¿kþ°Ó'd.ÍùúÇFí˜1~j«VÏ<|ûÙEn4Ò=æë¡»ƒ÷^‡óÞ'5`PÛUÙÔè[<íØ’/¯m|ô•]óï.Sy|«S~ >w8ùçß÷¤OrÉW^9Çç¼î}X@Ͳ§Ÿ…½ÿ{ÿ`_cʘ¸¡ûyòæÏc×s½óÿèµÎÝÿ£f\Ð=t^õ^õäêj{´ðêÿÇšÕ1²ëÿÑ®»þ ðT·6¶­ý·öŸq DŸŽNØ,ôÉÚÿŸÎ¡µÿ×ÿ‹/ºþ_ôÅúÿßmÿž{㌎ҟÿØÐ"½¡¬¸‡< F”)#B¾÷‡³€0,òŽ¥¡f[ú8\——/^ô!ùÃ84]xð#Ï=®‘SÝóïÛy±zéÈsÚ0;Ÿ&½õHg—7Y쎒n‘ë—ÔYÒ¼äÎÑÏÛ¶Í­§r ÕZ]6HSoø f÷V¶Âz¾òÔ}Ê\õ_¨nyâs¯çôæÅýª¼î¡å¥§®X•VÝBó#ÏôûÞÿ—{ÿŒÚù¿óÿŸÑ-Õƒw]³úõÿ,(YWvý?ëò®ÿXZûoí?6æÚÿó#ûÚÿëÿÍ\XÿïøÇ †õÿG7®ÿÿ?„ÿ<ýøoñˆÓØ)€"íî´8G{w`Р”Ô`9×°B¸²ÕÎ9`È¢P 2ð ~Œ>±<‡»ÈîiÊ‘ãå_ÒµÁã„å¥þ(ðtÕ5…R½?ÇH‘Ý\§îâ%”úöµô×.°W/_åQIiÀ2µöþŸñµ÷çæÜ5ïœ bºC|Ÿë;ÿWÿ¯þßõÿ®vý_ûoí¿µÿ×þ_ÿoý¿±™×ÿ_ÿÿßÿÉKÜ9eÇà.`¦ÀÆ·;^Ìáq‘î \1Ô¤qì@Ó\ã'OüáýyDèºÈb‘Wv2x5O¬¼C*¨¯¥ñ©Áx?G VB'Ÿ¬•£u·\ø8‡Xíä‘ÐkÒ];\K/0¦ žaèÅÓ‹´:D©·´ÓŽoÞ½ËN.@Ö«W/#he#}3õT¾Æ•;4·?Ùí¦¦Ì'meÛn±vSŒŸmSò½ÿ{ÿ3¼Œ§[Øù¿óõÿêÿ]ÿÏcTã®ÿcß­ý—Urí¿µÿ×þ_ÿµþßm3Éø|ÍõÿޱþÿÀ0Ž+À"þgà?O?ù»_½ ¨qP×SÙý½U¯f`rhÐ̺ åÜ{t$À•ÆR”+À‚Vzƒ<˜åF+G£•u”6æO¯Åoœ{zÓЖ®|,>väç|ãó~®¦£ðe¼Ô€Fvµ.7C(ÿ{»¤»¦äÄø6¿mi¹ÊõyÞ7þ®åü"§>  ÀVÞòÈ Ÿ¬‡ŒòÉSn <ÊTž½ÿg¼êC}µ÷çÿÎÿÕÿ«ÿwýßõÿ¼ÂÚ(°k„µÿ>µkõ Ûaí¿c‹×îl¿ˆ…Úœkÿ;\?õHÿÜúȵ°öÿs?´?î>ÍúÇ7\ÿïà sÍ­õÿ¿Ûþ!Ì‹›gö[8(LÆy•€¸J4Êr€Ž¼”0ü˜r&GA™Ðãs3-¯l>›|+óüå·N Èï8ü[Oi‹zã# tCjÒîy=G‹'ö¥:'ƒ˜üÞ}åX•ïó:Ðy„HÀKYÇà/|®¶õ?ùïg7^‚ø~œÄüMú½ïïüG¨ÈÕú<>éþ5Æ¡õ·¯Z•³õ§m#i”w½÷ï¿qeŒˆïcPÚÎÿ£cvþ¯þ_ý¿ë¿µ¶ëj×c?ütý¥3wý_ûÏ81>ÖþûÃyòB‡Lˆ zÙ±K×þO¿è‹»íeìT¿LFòz]»¿1Õ?kÿ?ÿ­Oúfý¿kî͸Zÿoýÿï¢ÿÿôïþæço³h̤¦;zª,)¿€“î<“ÿÚm#mÊü ´æ‡~XáᜲPNQ|­HHEϹüÖ™ó¹ç¾)‡/i‚¸õ‰ Q9'34ZóâʪÌ[AdY>~˜ÅÀ* ÙÔS´í’_Y•­¬.4øªCy²@vñGÇÉÉ×=š8d–·2•§²žÖkqël™ˆäÑæ¾‡lº+¡<Ó?“"n?"ï¿)?)·÷ïÇš1sGÆJ¾ªi<ÍØî»ì:Oä‡~çúaçÿêÿÕÿ»þïú¿öŸÝÛkÿ­ý¿öÿúõ‰ëËÕÆv}O뵸6yó×ÿ;xDüÛõÿÿ,ýÿ§ÿæ—o¡=ïÄq-4?m&°Ã¹IÔ‰u(9¶ãôÎ?“4èÖ8³á—‹‹ Ê ò{Ì-ï¼Âw|ïf²èºèî`TÊDž° HÃa±¡íi;¤+ ôцo¿wW ½Ç#•ó®*¿f„f®ý»´|é©Kfä8tê©óß¶¡MßLÙC~ú¯ô¥ò>—1‰·?òKNS^ÉöRr /þí—Ö'¿|7í^GÓÄʶ‘Ù}ºùÂÞÿÓ¯{ÿwþw^Gìü? ÂßK×UOÑ7ÎWÿ?ëdÝÔþqÞp×Í«ÿÙÖúÓ;tn×9ëxCû,´Wbæä®ÿé{¿ü±¾jþ®ÿgð臵ÿÖþ_ûíÿõÿÎèZ»þßúôâÿ üçé§ó,ï€ãD `ÐI˜E(ÂÐ Ê9‰S51] -®¥†Ð>®¯¼GšòW=5˜°©¡äò‘!õÏCÓK™¦ ‚sÏ@§msMA¡õ~;@8ôW{?¡@Í¿ï{‘üðkyøÚiõñ¿ä+—>™<†4ðMîWXýÈðÁGÀã¤Kû$ý²ÉÏ6a4Ú1וI™žë[Å*KÒÓŽó ˜—°N%>IÙiëÞÿ3Þ÷þÏà™ñ±óç?²úõ¿(ëímýÌú"Ãzt­'YÃvýßõƉñ‘ñp ã'i3dÖþ[ûê¨ÍÚs±°öÿé‡ò×étÖÚÿ틉×ÿ[ÿݱþÿÁ ªKÿ\üÿ§Ÿýö×o €ÐÓ”Ĥsä)‰®93è¥Õ8‘Æ0 &ùv39\£ Ÿ«<€Åã„vYµlùžeÑ͵<õµ®Ö}/ÛºÄôK~åsLžº•ï#€m“r‚²1Dsݺ*‡üTxº–'(Y§¤÷k)ë1E[¡ëVò_дe¦âðnÿ Í}W˜þ ?²LŸ 1 /:\¼wL îòáÙû*ݵ£»"f7ºÜ·¡ÝûÆ¡~Ûû¿ó@9:ãaçÿêjsõÿ®ÿYOwý¶áÆ–Xûoí¿Ø‘kÿ?~ض^kÿÛÞ4FÖÿ3(Öÿ37ø±ÆDÖÔñm×ÿ?>ûúÿ3|…ÐDñþ'»o ’ ˜Gjp$¾‹Gët\Q ˜C/ý®Œ];õ èÆÙSÎ'ˆå ê }Iô¹:ñÄC`kâ;=°å.Kø\ÀU¿š8…Ó>yu2:Äx›(d¢@{‡Öé‘)tÕ>ºêk»ÈL/‡>µÛJ¿¶àU[¼êjùNN2”¿˜ ÒÊ7×À“9š†®òë;³ƒ/¤w¡mhÔådïÿ£ÿöþïüßù?:øÒñô›óÕÿœ¡KéÑêïÕÿ»þïú¿ösjí¿çc­¥ŽêI6ôÚÿç‡xëiû¥¶ùÚÿëÿ =Œ‘õÿ¸Þëÿ[W2Æî\ÿÿà?O?ÿOýÖ¢[PÃ@±ËÇBãü>Ð$oèå™dòvúk®•×Éè¤É—&pŽ”mÇe~¤b¢C‰Ö“ë‹Gø OàPw%Iû ­ÛuÁ±Å–¼é‡‘ßùËç³ñäVNZÊ;çBÞ5±:ð ëÇ褗Æbõx´2ï÷:;£Âàö'rjûÕdqè yŽôùÈÓðVuˆyÍW.õOzoîq½ÏÊä1F ö]Q F eð,@õúõëO@¬QÚqɃÎc6x "ËEçgòÑ1tkä†ð¢ my È÷9xu”8¹ðFŸö臫×ÚоIþ¤}˜öyiýçy­_Ú‰õßÞÿ½ÿSƆ°óÿÄÞù_½ßxõÿêÿ³âfýíÚd=šóè’9G±ëÿ®ÿkÿ9³°Î¶Î-¯Œ¯§ìÆúá 庀žyÄnêL‰äágËè0J@#xöy@«Œ¶Úõù¦¿íЦzÛ´I@çlz+q C÷±4Î?òºÎý2wÓ?¿½ÿéÖ½ÿ3‹ŒÃ/ÂÎÿÿ«ÿßåˆÕÿÏ?¢ÈºEKM±ëÿ®ÿ;m2>Œ ëÈŒ•µÿÖþ[ûŸEõ̵ÿŸ×”»O2Šã±®D‡L·­ÿ·þŸÙcœw?… "}ýÿÓ7ŠþÿÓç%î]Üüï³³k„A  wš\£J?κÓ,¡˜kÐ=õpViZn*˜ÿÏ;ˆÔ¸¹—¿ËÐ{ñе9?©©Ó5G9;“M€¥òy5 • Ý7ß|óÅ›ü |[V«õQø 8ÕGLðÇÓ×ZM¯fg–ÞÇùáŸ:"l¤Ã'nêl ÃT~ŸžžØ¹óùr×=¤5è;2ä>O ¶íýßûoŒìüßùoÐÕ)Õûå wš\ÓFQ5Ïú¦4Õí«ÿçG‹ÕÿµÉx°jîú¿ëuDuË(˜ù¿öû²aí¿µÿGy®ýù7µ/Ìú;÷ø1oø@—£Ì çG|×õáÖÿÓIŸÚvµûŸ¾û”&eÖþ[ÿÿƒýÿô“ßüò­Io"׈èWòšÆ˜@üJ_e¡€æ\??箼‘cä(´Ò˧[A“pÿ3õ™è…Ê¢¡qyÝÓ(¤Ò‹]kŒ°È8@]Ûxd¾~õ&/žæEëS&@ÙÔ­62¢ÚG_ýõoÞ¼É5ú‚^Ç(iú =0«õà‡¾uˆm¹ò&3 ¤·¾Sþô%Ð) Ú´‹lò”¯i[ê˜kq  É¯ œK_œ*:å'n]íü¤•fïÿÞ3ãí7W3FvþÐ{çÿêsD /WÿŸõÃZ"èžÓ»þïú#£ãögÆÆÚkÿulÔ¥3„ÆÕ%÷´µÿ3uÖþ¿ÖšõÿÖÿ[ÿÖ’?Aÿÿñ, ]AÑ.÷Å¡†gVÆyòg=9 œã3¥Éâs'å%M~¯[FYx&þüYy¡Ÿrh¢†â¡Lc<òòÅÃI|\x£ÒÏú÷x±¨vxôÀ&aËOIDATxÚí] |WÚ¿D"ŠR ÚŽF‹êbf|­òÍ7Ó–)ÃÐiƒh1šªÖZŒù™©©eø‰µ–Qû6öÝXcO¬„„ˆXƒ$d±ïÁùÎÿÍsÒãí}ßÜå½7÷ÆyüžŸäÞ÷ž÷ÍyþÏsžíœk³)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)Rä ³ÃÅ;ÌöæÏ¯À9sIÎÁÄ¥;ÅbÞ‚h>}BËKp~†sÎ/p®Æù%ÎÕ;Ř·9ÿŒsišWŸ>ÐZÞpÍß¿{è#¦Ø}æóY•¬B€/@æ¾´ýíM§+ÁY €_r~––Õ⾽𫿽¬ÉL%4ËðçŠ4Ï>côÂÿþ,%0à7œ«Ð2PÂðSá/UÂ÷ Þ&‡º´/@ ßûhDAòŠ)á?]hÌùçŠ+á+(á+(á+(á+x#½«„ÿ”@?RÕU’çé@ežž/ŒÜþgǾfߥNg²¶±C7Øù»iìòý,vãáMv5÷:K¿w‰%ß>Év_f 2V°oN`-ªàíÙ[(8ýâ|–z÷"s…î=ºÏ¢®îg=’ÿ¡`ö—¤ÄëÞø#Gû7»‘{“YE{¯Å°„Ï]~3zP‚Ì?  <ùÇ5köäD2OÐÕÜkì«ã³ïúø©@i*@4ôÔ†‰Üye/ó$Ý~x›…%õ±M8h‹: (@4òÔ6õâ<æ ºx/ƒ5oošÆµ-Ò`ºicOüQŸ$~Ŷ{¦ý˜ÿC0áü öyR_öqB{?.Dæ'G»±þ)CتËXæƒìA°äÒËðA|;wys¶ùºêÎYMèŽú3Ó²‡ŽwÿÑ @V ™“ÖD@Çm¾`¹&ÂJº•Âþÿ‰Óã=3V³F´0c¥%påÙ$ž‘¶Àprïòe!4ñK—Ç^›¹Ùpl$’õàÍÈÛ §"€“wÎN.èÎØí»š.=í$‰œ¥›oiIÁz«ãÌRóÔàÏG>34Óx½ó±ÞnßcOѼôen  úðHg#þöô(É;w÷‚%÷qv‚á=boñ8Zé¤`ijÓNܺ¬Í–Ü>„!dô4Zî `Ä[svN4תûå°Ìè8«Éj'±H åöiÉë–<À²ûÄßH4¼¾>`5Y'(R¸óè®áÄ}d¡÷l–h~v¼[a`«ÃØâÚ©0ÐùÊ_[ÓZ¾•U¶ùéË ï5ñüLU. À;6¢ì9–NÚä s ï…¦€B’4F”Æ+vVNÚÉŒè?Ü:(ä1¢3wR-´‘ç&Þkùåu …xßF”|û”¥“†Â­ÏÚªPèzü¯†“ŠðÐÊIvæ;·N @Ç£==žþ±Ét²á½Vò&€B@›„.†“Š>+'müyc'pñ¥Õ …€?îh^±tÒ¾¿0שР€WAm 'Bè÷³ê^‹2V=­‰ ùdÖbßI£ÂˆÜÙÈáL*B€|J+6ô–jÞ¼ùsÓ§Oç€~?G‹4î0êþFÔ7ePQ@1;ÛùĆžò=zô¨¿zõê-;w~ÑoÊÁCÐLGù½tÃû %½ˆ@¯õ8¥µÊ AƒÚ¯]»6‹kÿ€Á§07}‰áÄ.½ô_ËœM£¶3G‹Nfd¥¯â&ž8›¹råÊ5§M›6uÆ ¹öŸâ¿ã„Ñç| ÿ:3Îpbß}ZûüäÉ“£¹ŒÞ'í¯ê®ö*äbjö+xû6öøÁñ{ðø®$W{GȚр“à åtϦ±mÙçû¾f#vŽcK#–?!ôíÛ·³Ã‡kÞ¼=¡ƒ¯^½ÊV­ZÅx¦O»N>a ÆjÙ²å߸ŒÞÂaÞVh¿OÀŒõǽÁ‘¼m’·‡ÙöÖ¡NÆtb_ïù›¸m [»qíæ=**J[³áÈ]»vMc#áÃÛ_´hÌ»æèé…/œ¿9sæ$Q’èU«´ßçàlÿŸÖš±šy*” å¦ý›¨alö–yOh9{Bð˜xxî0ï.\ЄoÙ è—ü´.b|„yò2‹ñ<ËСC—q¹ü–JÄ©9IJoõ[€Çò†{»Ž&_˜Í£P‡»»‡ä{ñˆÓav!øÔÔT-Q´ à=¤uy¡GWŒ!¥,/ß«Y³f{”‡é0ïgm©´_ÊÙ<ð•ò~—ZÉxšVxö0ùHµBX€Ù2 [ý2 @€hβx²5‘­Š=@ <¤v¯h*ú ä[™Ú½­Ôþ§mb>Ï/Á" ƒ¹ ZqcbbØÌ™3µl “lU̱k×.Mû›5kÖG*ú”·"í«ÀyúÖÙšð¡™(»z+ _ rÁ0÷ðôaY˜dP™@<oã²hbeÑG‡VDwÏ_÷fz+ _ rñúš5kØüùó53.'Ë ˆBð|­[·`uÑÇl{±ÂŒ†EÂñCÍ Ð[gA\·xñb-̃ðÅx2° òx¶Ù³g'Ú)úyBûÄ·†!Çüë¢*|4]"Þ‡ãS AÙ³Î:ƒ&ãêÇ”Ç6^‡UÂÚò —ÃÛRѧ”•‰#”¢8³6íLiɹ-çO9w$îä‡üÎaœ»wêÔi!4 !– Ù 8ë ÂɃ³Ç ã ãÊãÛƒ¸'ºƒÈó‘´ÿy«Ó¾FßZŽ–ºÔpؘv©¼Kሿñû4™-8‡Ž7n& YcuQâΚæñ#€1ev¸I"žõ{À›=¿¢µ¿†ÕE3Gðºé ô¯€Æz~Æ(›¾N)TTÑþÄ×苘hÄç²\qѺÅ4´uÞ> ÙQ@ yÀ _OÀõÊÚoÏ ˆ]¨å¨èP™¤*™#â(ªAùôJ•*µ\¿~ý#N½eÀÌÄÏhÝâ;r5ó0É,ÀP Ðÿáó1oT«V-”,ou+>€A -¥È1,ã§\–’'h›®ÝªU«0L4´MÇÞ2`æ âuäôQÔð‘DB™XfgëQƒÀsõêÕk²´Í«²'ã~GO›*Aè§\RZÒjõîÝ{ &ûëd8º àzäôáé£ HfA°3€@ÉÏÄCôiN{ü«y2ëç Šé@áo\‚&¦ô¾Ùò;‘ý“µÑ‘eÝ;pöD@°+€]¾0ýuëÖ “¶x‹ŠŸWµ¿(Q1]d PgäÈ‘³0á·d“\Ð2€n „y°Ø¥#XÁ@P´Ã÷qÇŽéÜûªtÀCÉÂÒþ¢8³¯Ž=z1€M˜b{Ë€ ˜{$x ­!8Á2ô€Á Þß¼y³¦ýÇ_ËŸ­™þ—tI¥ý ˜PO)`ö¬xùòåZj€§dvøÛ»ðS§Nã]¾­©ÚW“Lieú­&öµQ£F-ÁÄc¿½ìŒé­^C1ž>„ë ¸ T ñ |üT–¶§D[m ³Ë*ÓïÀ=rÙ @H¼£­Ï>CfWŸ…Ç¿téÒÌ:uê|A!ß«”¯(/ÅüJû=€z‹ ìµ×‡dÖy8{0щÌ ®ÿ ³Ï—•œúõë÷ Ôúëºu_™~O`ðàÁÓD@—£ÍG’ù}€Af#0\/>îOd4hР'¥zߤl_Eµî{uû÷ï?Rde@@ØŽ !¬ƒ`A°+€À}ÄaN<’8]«V­.’ðAÏ%Ÿª„ï! P»k×®‡0P €àóê›æí£” Ë ³ g ­ÇaÆ Û„S¿(Ö“Šl?SÂ÷^kìË-Z´[½óÂÖ¾áCh`$}›Bƒ`,#Bðt|k:¿çP~ïV¶¼þŠ×Éì Í—=~ 8M2<ì*Th‚Ì›’<¾Ì¿ã}„u²ÐÁü€‡œ¾}ûÎ BeﶼΞº”㯨„ï]ˆ3õ1ù y¿^¦,,Tâ @´baiÀI‚!\0~†÷q­|R§tbçCžØIàG“¸àßÿÑ–·—¯>¬…zÈá RÂ÷‰&Ñëø/M@»5vÛê…è,sM¿ÂÏê‹éÖ­Û,îà!´ûØ–WÑC|ÿÒz˜|”vËI¡ž¾­€èu¬HéV´Z}À9¤^½z½xëu8ÿª•9ëÆŒ³‡Ã~€ÂÏm8Ês'8'ãw¼>dÈM}úôYضmÛ±¼q§tAÓ?²åµ›Á»G×ѯIð5tÈäë“Kÿ܃H“,ƒ‹UIEND®B`‚qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_128x128@2x.png000066400000000000000000000260501347155106100310270ustar00rootroot00000000000000‰PNG  IHDR\r¨f+ïIDATxÚí] ¼MÕþ¿2Fez¥'‘’¢P¯i¢áyõ„¡Òô"¥TÒø4hEÒ@t‘y“"óÉ£¶O´ªýâ 3é xE2• @H~¹©_\ŒíÀ±ƒbÄöñ1×í·ü¥­²m´•ßÞ^ó‘ïÁV ÀQÿX [úq;¾>×k«¿à>¹+˜³Ë°éÐV™vkä+¸}A  õü"ÆÕÿ±â••zíW¼.öÝÓu¾¹º‹¯ þ‚{)€Ôò™ŠÚC /Œ BɸV¸{Žîõ|­klHH,À+îXx?€ZÂ7öŠÃÇ‹6¿>ŸÔëÅç!²ïm—¿èh¸°%€ZÎÛ³ØóÜscßÀ¹,£wLò‘<@ ¤ŽHËy ®­Ü¿&eÍ,æ­>°ÎÓuï“ÁÎx—{ÒŸ @Êøé†>žÞ—V¾“ÒkmÕû ¿öDcë¡íÖlD›†‡;tÂëZÚŽ@HþöB©îeGςׂ!Ô)øAb‚¢ €çè?‚x^Ð}Cï@§/7Ëš€t€ûy‚@ðžW÷‚cÇù&z}×¢‡=Ç0"9îw`0+€à‰¶ ÷ôÐa¶¿Ÿîã·ý«<Ýú‚.Í—´¦P¼qþ^oþ?æóûé>pˆ Û66ðpÏN¡øxÐç>µÿ.{ÖW÷Òî·ÿyº%ìdüŽ&‹ÿK DÏf‹[yî­OöÀÍpDK­—8ÀAÙµˆLB1  j¢qÇ –Ésüüx?8k0>´ß‘ʳ(”ðzÚrýx?ßɓм™ €ßK‰)>ýÃÀ½åÿ{ùò~úÈ3 ½§Yø¼›àÓ? ÎÔóÙíÏŽÆ®žî§ÿ–a€£ÇžPì÷yŸþa¼–Ðúµð-Â^€±á© æÄt92ŒàÓ?Œ×`¿±DU_¢R<”V€)¼^€´™ŸÏ0ôLA¦P2J;ö´«úùaórz1Úo)€Œô{Áò?WùúaÛvx‡§ Z<üm  0Ðnù+iÑtr1Ц”Å5(€À¦áxÁÜ= }ý°aDYªªé(€À€×QZ3vÍöõÆãÀ5€@HxkM—”æÌýÖÞÜbÉc @æÀ»k»yzX'ü>Å×Û¬Ýó<ÝW<æêQ(Ô¿{ÁHŸ6ÙœúÇLO÷ë!¦ @  ëúÏ==¬C·ñõÃöíΩžî«Õ²ö @æÀ‡ëzzzXGlçë‡ 1 î(€0|omwOëØ“}ý°Mßõ³§ûºoÉã @æ€×Ã@±ÅöóÃ6GÖ)¤j°&€踺³§‡õÇ]3}ý°-Ú»”…@ @8¾ºê=O+Òl~~Ø~•ó ½ þ‚û(€ÌLõñ‚{—øúaózZð¿ç7£P2GZ/{ÎÓÊR[??l^§Åã¨p  0€±^^€f??l;ÿõ=a2çP2J0IÖ vÞéë‡íбèÇœm=´^K#À‰uæÞéy"­_‡UÂ÷6äd% øËàß4Rœèõ\ÀÛ´H«£Îâ•Ù ¤DL£Ï­Þû”fÍšyê©§ŠPâ<<ãþ_žH«±à~ÿž<p3üü’…[µjU~РAÕ×'b¸G: Òqõ‡žîç›­#(Á'ÃÇ{’<ãå—_®;|øðu¯¿þz-ùu € ‡mëéE'¡ïç‹Mý<ÝϧûP‚!N«þ)j•/*ù÷.]º<=räȃÙÙÙ_˯‹SB¾ Ú:Ê—÷3fÇ·žîç«Þ¥ø_B­úÅÊ—/_á‹/¾è;jÔ(!`ßí·ß~™üþé€|Ùã`Pœ)èÇûÁ ?©šDH˜8­úy•a#À÷÷FÕþæ›oÃøÁ®]»v’ß/-yšdA €kÔ¼µ§6^iÄ“HMî?v ê{9.ÿ*@ @B ¤¯/YFúùOJ¯müC† Y_ªT©ÊòßÎTPˆÂhpÔ—4\ØÒW÷âõ\ÀM‡¶Æí¼âƹ(‘­úùíUÿÊ+¯¬&·üCl÷پ}û'Õg•RP˜‚ËþüÍÓC‹sÒaÌùÌÝsãv Gd‘TªúÒHÜVý‚jÕÿÇsÏ=÷àСC·šÆß·oß¹òß/•,«àtîÂpÔö‰žÚÁ> bT™·€æÈ”Vá Ö €\aV}¼¦” ô]Ô£G^ÒØ™Æ/y¼iӦȟ»HòõYt5ÈoMAk¬÷to®î’ÒF$ ÑÂ(¡Wý³{ì±»daÏ÷سgÏïäÏ]!yv ’%”»À,@(6Yü_Ͼ+JoƒìÿÇëD X[‘ã•…ä×@§áG^¿T™2e*uëÖí3™Ú;êfü#FŒ8R§Næò竪Ï9 ©Aåÿ³0Ñ çŸoüÚ×ÿ™¼/Øyø_”V?¹üåL€"Ê(ó*ƒÏm¬ú…•ñ–‘¾~K¹ê¯v3|›;w%¾¦äÅ’çjÀ‚ªPˆЍ…÷‚ rÅ»anÔg2ÖØà± ¾§-Ù÷«§ëè´æãL€Ê0ó(!°·û0Ú³n»í¶k¾üòË1á ”)À•+W¾[¾îrÉóá.¨ ÀS5¡¡„"*á¼Ñ÷T^û‹+ßò|íñªŒu$y¼z|.ÔÊ\T{>e Õ÷JžuÖY|ðÁä–~$ÆvìØq€|íµ’U$Ë!E¨EÿOQ» @(Þ2ïnqÀc=vx}ªf¬Ø¿ÚÓuã~ã}Ç©Ié8f-P[­Î¶qžª¶úET°®¬Ìß?Év_çàÁƒ÷”.]º‘ þUTÁ?sõç<€HøÝÎižWÒÛǧ䚳7ñ|͉8à¤û†Þž®Õˆ÷Ä1éC¸VEçK+-®ì£ÌÃ?\ÿ믿žáÛ|á…zË÷¸NåþË©ê?sõ§D—<öØøD>üɼÞwdú†ã.{6î×ôÌo¯z¾hrsŠvRI€ëµrôå6lX÷óÏ?ê’ÓcÆŒ±bõßU¬X±†ò½®”¼0ÄꟋQŽê5`¯b½6 Hʸ0´#Çbüó÷.NÈuÝáq΢õ7Z É#KŸ±Î+Ä“vË_¯ÈxæàH7ˆ-ZŸ³· ñmg¦!7I¢;ï’ºuëÞòÙgŸ —F|ÔÍðçÌ™#f̘rõ—.ÃJX°ú—×jÿ «? Rv[ÿ¥ˆXÉÐd”ˆë»sáƒòøïŸb¾F”߯’Ç¿÷H¨ÑE5”½úýe€ï›áÏ›7OlÙ²ELŸ>¹}ëûÓ¦M;i'0pàÀß‹-zGˆÕß,2¢DBż–³ê@M!épÛüæ¾}¦þ3«…x÷Ýw' 6ì@(Ãß¾}»Ø¶m›˜2eŠÁ@KæÎ+–-[vÒkÚµk×SÚÕ šïÿ÷T®þi#± qŸ¸»JôÙ<ÈÚÖF:LÓ}QÓkS«Ç?–í¾H¢v'6Û¯x=ép÷¢G|÷5þéAñηňQ#·ðãÆ ,;vì»wï›6mãÇ2 hýû/¿ü"vîÜ)¦NzÂëdßÿŽSO=5ÒÕŸçDŸZk$Ví_›°‡õO¹Ã@Åܼ=‹¬N¼)2û0s÷ËuÀ÷÷Ý›°ÏWÂ(ŒòÚà~*%¾gÆŇ»‰‘£F:>Œ|Ñ¢Eâ÷ß· \³fÝ}¢W¯^bìØ±bÕªU–ñCÌ×·mÛ¶»æûûbõO+ûµCÜV]¿[ÿdgï]T8 P˜Êç¥îÏwŠ6SŸ½Æõq ÚMœ8Q,]ºTüñÇ>øë¯¿ 9¿OÈÞ~1a±~ýzËøAìô÷0`À¶ üG­þfÞ?¥§ ¥•Xñ†>icüëlŒË៑òÖyM’º €Û‘Šg¤áÌûÅKS:ŠAc»þwß}'~ûí7±k×® _Ã÷—ѧOË÷ߺuë_ÆDÃðý?S«ÿ%!Vÿ\€÷Øû Hm¦ÂG~ö·×’¶‹Jf9v9ÄÃÓžOü4dš¾ûêÕ«O0z›ØüðÃâÃ?ýúõ³R~ˆØÆ ÐßOw.\øcõ·;þR~Ö`Z âßîœXã_p“Õß߇ëz&EPè†+øöoL~W =ÄÕèÑÿùçŸ-ßÝÉðADûGÌÒyV¤«½nüàO?ýtÂ{wèСw‘ÿ\€üñûÊ(~а`ïñŸ÷ú¢ÂrïÑ} ½×î ªÂĿÔ×Dß±Ù!W{øî‹/¶ŒÛÍðíH¿ôã-ãGÐ1ÓðA¸ ½æÿŒ3Îhä×Õ?­Àæë«?»ì „ñ#íè§â˜ú î³…¼` ‡¯6}·k½mV3ñÌ/‹/Ƕ~»“ïDDúè{ÿý÷­×®\¹ÒÑøAˆ‰þ9ò¤Ÿ~~^ý3B¬‡cAó”ºD‹w¼%Žåôâ÷×~"«gzJw9~ÄJ•¢q 5(Æ9芌I fÝ+žùþeÑsü—®é;=‡m{¨m¾É%K–Xþ¾œ×o½^ô;qÒ¤I}žÜ)ì“mÂw9äý}³úgŒèiÂi»fù6U¸çÈ^kÕõûï±ñ¢‡¬©·×t=7öµjûAT=bƒ­=êÿŸ’EQ(`Šç®zOýð‚è1þó°Fíø?þh­Úf/gΜ)Þ~ûm!‡yŠÉ“'[¥¾¡Œß þÉ~ÿaÒ†nôóêŸq`óÞ%mÄðmã¬ÑZ~C¼NüMÞ0»¡¸wzkñêwo‹>ã²#j·…ÁbõçÛ»Eú±Ú¿ñÆBN÷±ïÊøAôh³þWªTé^iCW9TýùfõÏXÐ…(FÁd›å®ô<?Þx*Ígí…ííø¹‰h5õñþ¤®bpˆè}¬[|“H類_žÚƒYý®‘~“›7o>!ø'gýM–öSG û,ï×Õ?ãÀäMó‹VËÚ[i0´«~ÿÇ ñ‹œz³ãðNqèØáµúð1âãµÐòŠí|,íµ¸–ŒùÝϾCÜõÓCâÙï_‰hk¯WéÍž=ÛÊÛGÐ ElñQ؃•_Öí[;ˆp†osþüù'Ìù¿þúëÛHû¹Z²†‡ø¡æŸÇ1dèb«/Su¡NÆAŽ;ôŽc„ܼùç»Ä#²0çÉÅ7cE/m§–:é§ŒšèËÕŸ`>´´8vüXL€’Õ”ÈJ<ÔÝ>¾WÄ«<¶ö³fÍË—/·zíM?Ü€XEîÃ;?ÝÚY ~€Ï2Jô¶ßÞ½{/—vs‹š"TAôá4ë)²mtL®@<KŠ‹4ûn«æ=õƒÇDÀC=¢èX7lØ`ãl:b¬€×¡ÙG¦ê„<½Ç2bTñ¹}®› àZõûxðÁßQ“„/V3KŠøÊø)IšVK‡ªýP²PhÖ=¢Ý/‰" à!bÄ =äÏa|Xé‘nà €›DbüxLíyíµ×ħŸ~jí4ìÏÖ?פ“àµö=õïßsîܹëi}”Vçúvõ§$‰WwŽi0zÇ$ÿ­ô?ßm¥êB Ñ0ëîQ\ƒ>zlµaô¶áÛ´ÀMbuðy¨é‡ñ#âè½þ™&C ²zêïé§ŸþT¯¬ŽùÖOÊ›ìYŸq®œËäâ¶Ë_Jýæ9 åöþIñÑÄý·ß~kùÙˆª#W£±i €.áÀM"l×1¹Æ°ã nN 0@kúÙ-›~h§üê«>?ÿ(I&Jb?Ópºs§,zÿâ”7Dÿ1ß„Ý򣄮Ü]|LF"zן<äóÐyçw´—ªå÷l¿µüRüRü"‹ˆ6ÚÓtà¦I8Š«éŒGÂúöðéÃêŠíµM[t'n"K0ÿEÌAÚi¥ùtÄ5éŸïtáßÓG~É‚‰ªì×lúñýêOØ©ÀÀ¬Ýó:»Û÷‘Y˜|‹/0ú+)ÚcÁpà&ѸÑñ30xäø»wïnî %DÑ‚1ïÿxÍš5[©²_ß¶üR|F¯Çq£YiÂïSâ~:pÙwZt†»ÌÂÿþûïÅÂ… ­-> ߦ-n"à5h Þ}o½õ–5È©FóóM†ó!,FÙïMFÙ¯/›~(>â]‹ŽêXsü,š$â$Þ–ÓÙcû;>V{¤í`ø¨—·©¸‰@¢Ü\Ç!C¬`ê€ÿ¯¾› E*fÙoãÆ_RÙ/ÀGDÇ`8ì:²Û:¸4Ò“‰¢’ûæä÷\W|luaø6ÀM¢q¼MÀÐYŒcU÷¡¥ƪ_‡y-^‚hÿŽd»ðj—²__6ýP|7¹øN±öÀGÃßrh›øHž$|K‚ŽÝ®'+÷¾ßÛÑÇÇ¡HáÙthܯÁÀhܬô²ßÚöã>æsºŽXï©þ´nݺsÐÊ~)>#NûÕ¹y¨ý¯“ÀÁ Èé÷×ÏuP&ôpà&‰rÜj@øøÈñ¿÷Þ{Vá®M¿“^‰ú9 ¼=he¿ròÎÅ¢½KE‡Þù‡É¹ýÆ8Éø%G:ÆoÓI¢q¼#uðïØ’£™ƒ;a úu8]WA€{¡ÿ¾^|ñÅ>Ò>®“¬¤²_ €O1IJ Âì»ÏÀC.8Nâ ŒGM~«=òûHóáÜ)‚ ·üÊ!ûå´ßÆZÙïÙjõLêÃI>˜ôÑIÆÓp°òÛà&‰r¼Ôàsá‹£²C;‘ž4¯Å¤WAÀuã÷£ÿÎäçŽV³þWöKÈP¶ýáy×m$``Ï—Å'“ñœ-¨¯þõêÕ{F5ý8•ývõw€JjÑzº¬øÓ‡y`V5øµ‘ @*‚¨éGzi¾Z_ë׿vñôBèÂ)w ó²rNú©žYÿñ€ò€àq˜9¿.n"ªšló1´Ónè»â&RшA4‚€¯õc¾Àúõëw±úªì7(¬RÈq^Ec fðO¯÷Gä+i¤ì` þ?júáëãx.Ì´cúõ™L„  2R7~9Pd‰Öò{¾ZýÏH—Õ_€Üê† «Ê&(Ýe4¨àc½ô‡þ, Ê7HF0Ðü"ý]ºtù«¡G¿6“‰ûÞð<꾃 °ú_£­þ%ÓiõÏÒ.Þ€BÊ¿A{c%Uô€èç$ÑÑT²™d Å{É”ò>I”¦¶”|X²M‡&™Í>‘@²kðØ ¸«¿}hˆÉd ‚Þî«EþÓzõ7 ¯jh(ªÎUÊw¹ò0÷¼® ˆàs+™þKÇPý[ò6ÉúJ [ÊŠ¹ úöõò7HF0Ð|®=ºë«¯¾²Î°¯Ñ¼Îd\$}تþjÕªõ˜æû;µüæúêïȯ¹g©XÀ…ªóé2Õ‰Fˆ«Ôî€L kª‡óÕ—ŽúôÛ*Uªô¶®æö?”Ä#€šþììlËøéGÔ]¿F“¡Ä ‚€ÿÖb£æÿ[µÐ9­þ-û4PP튫/«ÒU±²«Iã%ª!¥šÚ¡An’§Ó¾oæþ‘þs2¨TÔ`z&õ"Ò:!¸>“É3ð'ûý\|ñÅ÷kUç¤ó꯻z6ÀbÊ8K5?œ£Áæ¹dJXNÕj\ R䨯—†5T˜ÑDã&ñFê࿈ô£¤‘~¤Ú°í†{bÓIb„Pbâõ¨4¦ýd«•]óoæýÓjõwÚäÕD °‚Ó•WyÐJÉä³”jCµE¹œÚ•Õ–yôEzé¯nX‰vÜ‚ø>R{(ëE]?jì±ò›`2‚`Ôû£ÝxSáÂ…ïP.n¥tÌûG*y”ÚåWÛžBJ «b!25,¢xšòIK*¨˜'OžÚ²„vŸ~2¯›Ñ$«&¯9r¤µåG¤I0|7&SPxdIiѢś*Ø}©*†;3ªþ¢qt!È«nþµ3 SÃüš T‚p†zH/GT5Òf¤µœvɪ Àçàî7ÞxCôéÓÇJGbå×J )ø”G뿯O>ùd¶Ê®\‘ur¿Ú¯þá„ ·&dj™×ˆÓÀ¨Ø²eË'Ìü¿i(^Ü/ÁÀE‹Ye½0~9BÛ þá{ )©}Ї=èó’K.yHeUªd<í'íW7Èå dê¨ïÊ hPI¯ÞÓjlqÝ ‘5ø\¹šþUÓ¿müNô*¡Ä ” @ŒÌ­Û¶m{¨;í¨#¾S!djø7‡¢-¸•å1Õýõ‡m´¦1$²&ÄÀŒê–×bEú‘ãÇu˜L• à=Œr_*²PT]¥2*vÑO`'ýé-ĺ`‹Š²íKemŠYè´&"ˆïaÖ V}¤ú0º )H€M'!H¶ }þÖÖ¿jÕª˜ów­ ü—îE?Dú@A%Ø®V“%µ ôÁŸºDãD ÄÏIC²ü}Dú‘ï7߉ÉE™[ÿÇ[ÿ›T1UE—ÀWÂw`Wl"E…ùt—Ëö*ûÁWh¯` ÞÇp¿öÚkV¤Fãw¢W1ˆ‡ àóÍ‚Ùì3++§â*UGaò‘±?"XPHmUá³^!ÄÞ¦×D"±a¸8”+?ŽãFÖ?nbLAÀÏ›C>dzr[éÒ¥ÑÕŠÓ}«[§À€ð¥S+W Y´_orò…ãåÀØÑ¿¹}(ôA==¢ÿ )©ÌÐ_ö ¹õÖ[Ñç_Gmý/P[»â?·`gN˜Þ$«kê]€(q %^ƒøÿ0(œË‡9ý(¦™={ö_ÆïÄd ‚nüf?øÌ3ÏôÎÊi«®¡Eý¹õ'+åK•*uƒþëà5h þ ?m¼ü±åf §îD?Œè=þ œ<4Mþ¾nÏÊéôCÁOyný‰  ÀI#ÜË–-{s$àÕ ÀÏÃÏG°í¼¨¤ÃÊoÓM‰A¢×dýdeâŠ"EŠÜ••“òC§Ÿ]ðè?h¨ û×ëE+‘º¤!Â`çĶ>¿.&S)ø Óøe9òŽŠ+>(W7fåTû!åg÷ùåÖŸªÀw­P½zõú¡À«ƒD¤Û~Œðš>}ºeüNL„ „'AÀkÌ&û\wÝu8Øùþ+”ßÀ)J¨íN?ný‰@ @~]d5ÛíúC@]¨Ê¸HjàCcZ/xØg ú¯ÓM R!x­™îÃl¿fÍšuRA?äû+;øýÜú€"¶œþùÿ2GG+º`ÃGY/ª QàAMðƒ 8?²">úh÷¬œ:ý0F ùþÒ.~?·þD àü’%KÖÑ~Là WïÖ*kGú?ûì31qâÄ¿ ߉¡Ä Y‚€Ÿw2þvíÚõV´øVUA?3ßO¿Ÿ´XA@Yp­nv)p4»üûàÁƒEÇŽ­C9±‹ÀÊoÒO‚€×a‡bæú_xá…Y9gYÔVû”qúÑï'°Or®5|øðƒ¶ å5\—œ.(šA¤+?Ò}pàóÛt‚X!”D"x³µ|ýõ×Ge圓€qéÕµˆ¿]ìàx0r¯) w»y`$»øÐÈí£º£º‘ãG´_“©¤"Í"eü£5ãG™/F{•ÍrŽø3èG^쓜¯–]y«tc@N<œÀð0½Ñ~øþ0,¿ý"fm¿íóËmÿ eü×+ãÇT_¤û00Å)âO¿ŸH Àüº²Òm9,Ô.Ó{`øèáGîÆ^~›nB*AÀû:ùûhîiݺuO?‘)pR3䲿}ªn0('ãGeêø1ºKž#h aü¦˜L• à¿Xõ¶ü2h¹·aƳr¢ý×fåTù™ÆÏt‘Ö€‡ýŸÒ G™cÁMãG°[}tòaZ/Ò…¶ñ;Ñ« „ƒhñ§@(Ó”Ëd 4ðÄ!©µCã§}€}ˆ+"Ü—Éy|Ù¡Š™«#¼ðïpL¦Zð5 ß,éÕ«û¤¿?8wîÜhìÁž8$µº ø9ÿ)4~"À‚üvÕ矾«[-â0únݺY<°¥†‘Ùt‚d ¾ër[ñUGß*Y×ÿ¼¼_ß…(ïÅ0O¤úÊfåDûiüDÆvT·U‘ƒŸH{0-ªVÆs•áÀˆ0üò6µ²6½ôÒKÛÉÕ¶ë³Ï>;HvýM…0H{ ‚mñ2rÔä÷ï߇tCVÊÓ§ËêׯÿŽôçÿ« ¾±ÚÞÿ[­ô0úÚjµGýþ¥ÊÇ¿À0üâj»j˜UŸÆOddÀ®,­bfå¤ËàG£Z¹s Èh Dáne”Í‹/þÈÕW_ý|½zõÞlҤɇ=ôP϶mÛfwèÐa¨ä0ƒCe>¾_«V­¾’u=7nܹN:ÿ«P¡¢õ-Ô{6QŸÑ@­ðÿR×p£ èÕR"£¯ª­öçi>~)ÃçªOP 7  Ú”P®ÚƒQ‰ò£k(1¸F ±®2Ê[”þ[k}µJƒ ]Ø@ý{}%*Øi ÿVõžu5c¿F}ö•Êà«©ëºH3úsÕj¦ hž¡mõ *‘s3|?‘±n€ ,¤‰rãç(㪨Œ­ŠZm«+C¼BåUÊ@k)c­­‚pש݃¯S¼V½¦–z«”Ø\¡>£ºÚÖWÑ ¾‚ÚÞŸ£ÄÊ6úbjµ/¢î¥@˜Ÿ†OP´X@>µZQ+hIe\ÿPÆVN ÂùÊ+)£¬¬ ôe¬UÕ*]]ãeŠú÷ª©Ÿ­ª^[E½×Eê½+ªÏ²WøsÔµœ¥üú†Ñ›«}^Ãð¹Ý'ˆ®€½( Œ Fuº2²ʧ>SàÙš0”UZN¹ç©Uº‚2`7VP?{žz]9õ^¶¡Ÿ­{)ÍàOW;•SÕJo}>Ãè¹âD®€-ön ¿2®ÂÊØŠ¨ÕötµC€1W†YRéß•HØBa³´Fýûgj^R½WqõÞghÆ^Ä0x}{o½ÛjOÃ'BpŠ¢-”RÔÅ¡ˆ2Ö¢J(l±p£ý3E #/¬¨{~ÃàVzÓèiøáAri•[„<šñéÂ`‹ƒ-4¡EýgókFžO{ÿ¼+¼nð4z‚H ä2ŒMStˆ–y æŽÐØiô‘D1'áÄÂͰÿ¡¡Óà "Â/AAAAàÿÉsÃ$tö3IEND®B`‚qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_16x16.png000066400000000000000000000007471347155106100303120ustar00rootroot00000000000000‰PNG  IHDR(-SêPLTEÿÿÿ¿¿¿®®®¶¶¶DÌUcÅn³³³µµµ´´´ºººµµµºÁ»¹¹¹ÅÅŹ¹¹AÍRAÍRtÇ~ÊÊÊÁÁÁÄÄÄAÍRBÍSLÊ\NÊ]OÑ_PÊ_PÑ`\Ôj]ÔlcÈocÖqdÖrkØx{܇|ÜˆŠÆ‘à˜¥Ê©©Ì®´Àµ½É¿ÀÓÃÆÆÆÇÇÇÈÈÈÊÊÊÌÌÌÌÓÌÍÍÍÎÏÎÏÏÏÏòÔÓó×ÕÕÕÕôØÖÖÖÖ×ÖררõÛØõÜÚÚÚÛöÞÜÜÜÜÝÜÜößÝÝÝÝöàßßßß÷âà÷ãáááâââãããèèèìúîÿÿÿ£\­tRNS,QVWZfßþw&(/Fì¿9éäL,ÜÝY%ÀíŸL+M‡–›ŽkL#6"(wäïIDATÕÁMKqÇñïoþÿÿÎÌÎn©(nùPƒ°ƒ!Ö±‡S"BèÔ¨K/ êЩSï k—.£§‹‚K ‹Ž™ëª³»ÓÌú\½>þ¢Cþ”z XrNÔ6 "ã•[ö:{¢8µ€+&á4ÿ`ðÀ…I4Í¿xXhu•©ÍAV`Ñ1M’3V›àHØcÁ¹@¹#«b¡åÈùRLOA¤Ô¶ÈZ1,›Ÿýœ££ ϲ£¢ò/Àá*R›™àG%ðØ¬ød|ê5çj5r^%²;õƒc›Íxìró£p¦0\¥´p’ÌØY{ÛË®pBú0Åæñåî<0UË®÷—õ.¼€Ò%åÖ#y5¨Ì)ró‹æüÌ•ê5[ÙÜ5æ“ǾïÏ>GSs7J¥F5Š ËÆ˜¦4Ùó8˜ ã`( ‡ŠÎÍâãdߣ0 6‚-ß÷{K7½¤Þrc¾$:$=ô¿®o:Ã-©º”Xh..÷ž¦C™p±>¡zTH}½ÛjbIYêJgéèŠËã­¾Rx4¾gçë)R☜e­ïœV¤ÕÙ©ûîMy­ HÙ– †Õ°DðòUA#síÄAêN'ÕñmDOã0²Ùó14¯»K}Ïg)™ßù>…ú^„Z°IEND®B`‚qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256.png000066400000000000000000000260501347155106100304610ustar00rootroot00000000000000‰PNG  IHDR\r¨f+ïIDATxÚí] ¼MÕþ¿2Fez¥'‘’¢P¯i¢áyõ„¡Òô"¥TÒø4hEÒ@t‘y“"óÉ£¶O´ªýâ 3é xE2• @H~¹©_\ŒíÀ±ƒbÄöñ1×í·ü¥­²m´•ßÞ^ó‘ïÁV ÀQÿX [úq;¾>×k«¿à>¹+˜³Ë°éÐV™vkä+¸}A  õü"ÆÕÿ±â••zíW¼.öÝÓu¾¹º‹¯ þ‚{)€Ôò™ŠÚC /Œ BɸV¸{Žîõ|­klHH,À+îXx?€ZÂ7öŠÃÇ‹6¿>ŸÔëÅç!²ïm—¿èh¸°%€ZÎÛ³ØóÜscßÀ¹,£wLò‘<@ ¤ŽHËy ®­Ü¿&eÍ,æ­>°ÎÓuï“ÁÎx—{ÒŸ @Êøé†>žÞ—V¾“ÒkmÕû ¿öDcë¡íÖlD›†‡;tÂëZÚŽ@HþöB©îeGςׂ!Ô)øAb‚¢ €çè?‚x^Ð}Cï@§/7Ëš€t€ûy‚@ðžW÷‚cÇù&z}×¢‡=Ç0"9îw`0+€à‰¶ ÷ôÐa¶¿Ÿîã·ý«<Ýú‚.Í—´¦P¼qþ^oþ?æóûé>pˆ Û66ðpÏN¡øxÐç>µÿ.{ÖW÷Òî·ÿyº%ìdüŽ&‹ÿK DÏf‹[yî­OöÀÍpDK­—8ÀAÙµˆLB1  j¢qÇ –Ésüüx?8k0>´ß‘ʳ(”ðzÚrýx?ßɓм™ €ßK‰)>ýÃÀ½åÿ{ùò~úÈ3 ½§Yø¼›àÓ? ÎÔóÙíÏŽÆ®žî§ÿ–a€£ÇžPì÷yŸþa¼–Ðúµð-Â^€±á© æÄt92ŒàÓ?Œ×`¿±DU_¢R<”V€)¼^€´™ŸÏ0ôLA¦P2J;ö´«úùaórz1Úo)€Œô{Áò?WùúaÛvx‡§ Z<üm  0Ðnù+iÑtr1Ц”Å5(€À¦áxÁÜ= }ý°aDYªªé(€À€×QZ3vÍöõÆãÀ5€@HxkM—”æÌýÖÞÜbÉc @æÀ»k»yzX'ü>Å×Û¬Ýó<ÝW<æêQ(Ô¿{ÁHŸ6ÙœúÇLO÷ë!¦ @  ëúÏ==¬C·ñõÃöíΩžî«Õ²ö @æÀ‡ëzzzXGlçë‡ 1 î(€0|omwOëØ“}ý°Mßõ³§ûºoÉã @æ€×Ã@±ÅöóÃ6GÖ)¤j°&€踺³§‡õÇ]3}ý°-Ú»”…@ @8¾ºê=O+Òl~~Ø~•ó ½ þ‚û(€ÌLõñ‚{—øúaózZð¿ç7£P2GZ/{ÎÓÊR[??l^§Åã¨p  0€±^^€f??l;ÿõ=a2çP2J0IÖ vÞéë‡íбèÇœm=´^K#À‰uæÞéy"­_‡UÂ÷6äd% øËàß4Rœèõ\ÀÛ´H«£Îâ•Ù ¤DL£Ï­Þû”fÍšyê©§ŠPâ<<ãþ_žH«±à~ÿž<p3üü’…[µjU~РAÕ×'b¸G: Òqõ‡žîç›­#(Á'ÃÇ{’<ãå—_®;|øðu¯¿þz-ùu € ‡mëéE'¡ïç‹Mý<ÝϧûP‚!N«þ)j•/*ù÷.]º<=räȃÙÙÙ_˯‹SB¾ Ú:Ê—÷3fÇ·žîç«Þ¥ø_B­úÅÊ—/_á‹/¾è;jÔ(!`ßí·ß~™üþé€|Ùã`Pœ)èÇûÁ ?©šDH˜8­úy•a#À÷÷FÕþæ›oÃøÁ®]»v’ß/-yšdA €kÔ¼µ§6^iÄ“HMî?v ê{9.ÿ*@ @B ¤¯/YFúùOJ¯müC† Y_ªT©ÊòßÎTPˆÂhpÔ—4\ØÒW÷âõ\ÀM‡¶Æí¼âƹ(‘­úùíUÿÊ+¯¬&·üCl÷پ}û'Õg•RP˜‚ËþüÍÓC‹sÒaÌùÌÝsãv Gd‘TªúÒHÜVý‚jÕÿÇsÏ=÷àСC·šÆß·oß¹òß/•,«àtîÂpÔö‰žÚÁ> bT™·€æÈ”Vá Ö €\aV}¼¦” ô]Ô£G^ÒØ™Æ/y¼iӦȟ»HòõYt5ÈoMAk¬÷to®î’ÒF$ ÑÂ(¡Wý³{ì±»daÏ÷سgÏïäÏ]!yv ’%”»À,@(6Yü_Ͼ+JoƒìÿÇëD X[‘ã•…ä×@§áG^¿T™2e*uëÖí3™Ú;êfü#FŒ8R§Næò竪Ï9 ©Aåÿ³0Ñ çŸoüÚ×ÿ™¼/Øyø_”V?¹üåL€"Ê(ó*ƒÏm¬ú…•ñ–‘¾~K¹ê¯v3|›;w%¾¦äÅ’çjÀ‚ªPˆЍ…÷‚ rÅ»anÔg2ÖØà± ¾§-Ù÷«§ëè´æãL€Ê0ó(!°·û0Ú³n»í¶k¾üòË1á ”)À•+W¾[¾îrÉóá.¨ ÀS5¡¡„"*á¼Ñ÷T^û‹+ßò|íñªŒu$y¼z|.ÔÊ\T{>e Õ÷JžuÖY|ðÁä–~$ÆvìØq€|íµ’U$Ë!E¨EÿOQ» @(Þ2ïnqÀc=vx}ªf¬Ø¿ÚÓuã~ã}Ç©Ié8f-P[­Î¶qžª¶úET°®¬Ìß?Év_çàÁƒ÷”.]º‘ þUTÁ?sõç<€HøÝÎižWÒÛǧ䚳7ñ|͉8à¤û†Þž®Õˆ÷Ä1éC¸VEçK+-®ì£ÌÃ?\ÿ믿žáÛ|á…zË÷¸NåþË©ê?sõ§D—<öØøD>üɼÞwdú†ã.{6î×ôÌo¯z¾hrsŠvRI€ëµrôå6lX÷óÏ?ê’ÓcÆŒ±bõßU¬X±†ò½®”¼0ÄꟋQŽê5`¯b½6 Hʸ0´#Çbüó÷.NÈuÝáq΢õ7Z É#KŸ±Î+Ä“vË_¯ÈxæàH7ˆ-ZŸ³· ñmg¦!7I¢;ï’ºuëÞòÙgŸ —F|ÔÍðçÌ™#f̘rõ—.ÃJX°ú—×jÿ «? Rv[ÿ¥ˆXÉÐd”ˆë»sáƒòøïŸb¾F”߯’Ç¿÷H¨ÑE5”½úýe€ï›áÏ›7OlÙ²ELŸ>¹}ëûÓ¦M;i'0pàÀß‹-zGˆÕß,2¢DBż–³ê@M!épÛüæ¾}¦þ3«…x÷Ýw' 6ì@(Ãß¾}»Ø¶m›˜2eŠÁ@KæÎ+–-[vÒkÚµk×SÚÕ šïÿ÷T®þi#± qŸ¸»JôÙ<ÈÚÖF:LÓ}QÓkS«Ç?–í¾H¢v'6Û¯x=ép÷¢G|÷5þéAñηňQ#·ðãÆ ,;vì»wï›6mãÇ2 hýû/¿ü"vîÜ)¦NzÂëdßÿŽSO=5ÒÕŸçDŸZk$Ví_›°‡õO¹Ã@Åܼ=‹¬N¼)2û0s÷ËuÀ÷÷Ý›°ÏWÂ(ŒòÚà~*%¾gÆŇ»‰‘£F:>Œ|Ñ¢Eâ÷ß· \³fÝ}¢W¯^bìØ±bÕªU–ñCÌ×·mÛ¶»æûûbõO+ûµCÜV]¿[ÿdgï]T8 P˜Êç¥îÏwŠ6SŸ½Æõq ÚMœ8Q,]ºTüñÇ>øë¯¿ 9¿OÈÞ~1a±~ýzËøAìô÷0`À¶ üG­þfÞ?¥§ ¥•Xñ†>icüëlŒË៑òÖyM’º €Û‘Šg¤áÌûÅKS:ŠAc»þwß}'~ûí7±k×® _Ã÷—ѧOË÷ߺuë_ÆDÃðý?S«ÿ%!Vÿ\€÷Øû Hm¦ÂG~ö·×’¶‹Jf9v9ÄÃÓžOü4dš¾ûêÕ«O0z›ØüðÃâÃ?ýúõ³R~ˆØÆ ÐßOw.\øcõ·;þR~Ö`Z âßîœXã_p“Õß߇ëz&EPè†+øöoL~W =ÄÕèÑÿùçŸ-ßÝÉðADûGÌÒyV¤«½nüàO?ýtÂ{wèСw‘ÿ\€üñûÊ(~а`ïñŸ÷ú¢ÂrïÑ} ½×î ªÂĿÔ×Dß±Ù!W{øî‹/¶ŒÛÍðíH¿ôã-ãGÐ1ÓðA¸ ½æÿŒ3Îhä×Õ?­Àæë«?»ì „ñ#íè§â˜ú î³…¼` ‡¯6}·k½mV3ñÌ/‹/Ƕ~»“ïDDúè{ÿý÷­×®\¹ÒÑøAˆ‰þ9ò¤Ÿ~~^ý3B¬‡cAó”ºD‹w¼%Žåôâ÷×~"«gzJw9~ÄJ•¢q 5(Æ9芌I fÝ+žùþeÑsü—®é;=‡m{¨m¾É%K–Xþ¾œ×o½^ô;qÒ¤I}žÜ)ì“mÂw9äý}³úgŒèiÂi»fù6U¸çÈ^kÕõûï±ñ¢‡¬©·×t=7öµjûAT=bƒ­=êÿŸ’EQ(`Šç®zOýð‚è1þó°Fíø?þh­Úf/gΜ)Þ~ûm!‡yŠÉ“'[¥¾¡Œß þÉ~ÿaÒ†nôóêŸq`óÞ%mÄðmã¬ÑZ~C¼NüMÞ0»¡¸wzkñêwo‹>ã²#j·…ÁbõçÛ»Eú±Ú¿ñÆBN÷±ïÊøAôh³þWªTé^iCW9TýùfõÏXÐ…(FÁd›å®ô<?Þx*Ígí…ííø¹‰h5õñþ¤®bpˆè}¬[|“H類_žÚƒYý®‘~“›7o>!ø'gýM–öSG û,ï×Õ?ãÀäMó‹VËÚ[i0´«~ÿÇ ñ‹œz³ãðNqèØáµúð1âãµÐòŠí|,íµ¸–ŒùÝϾCÜõÓCâÙï_‰hk¯WéÍž=ÛÊÛGÐ ElñQ؃•_Öí[;ˆp†osþüù'Ìù¿þúëÛHû¹Z²†‡ø¡æŸÇ1dèb«/Su¡NÆAŽ;ôŽc„ܼùç»Ä#²0çÉÅ7cE/m§–:é§ŒšèËÕŸ`>´´8vüXL€’Õ”ÈJ<ÔÝ>¾WÄ«<¶ö³fÍË—/·zíM?Ü€XEîÃ;?ÝÚY ~€Ï2Jô¶ßÞ½{/—vs‹š"TAôá4ë)²mtL®@<KŠ‹4ûn«æ=õƒÇDÀC=¢èX7lØ`ãl:b¬€×¡ÙG¦ê„<½Ç2bTñ¹}®› àZõûxðÁßQ“„/V3KŠøÊø)IšVK‡ªýP²PhÖ=¢Ý/‰" à!bÄ =äÏa|Xé‘nà €›DbüxLíyíµ×ħŸ~jí4ìÏÖ?פ“àµö=õïßsîܹëi}”Vçúvõ§$‰WwŽi0zÇ$ÿ­ô?ßm¥êB Ñ0ëîQ\ƒ>zlµaô¶áÛ´ÀMbuðy¨é‡ñ#âè½þ™&C ²zêïé§ŸþT¯¬ŽùÖOÊ›ìYŸq®œËäâ¶Ë_Jýæ9 åöþIñÑÄý·ß~kùÙˆª#W£±i €.áÀM"l×1¹Æ°ã nN 0@kúÙ-›~h§üê«>?ÿ(I&Jb?Ópºs§,zÿâ”7Dÿ1ß„Ý򣄮Ü]|LF"zן<äóÐyçw´—ªå÷l¿µüRüRü"‹ˆ6ÚÓtà¦I8Š«éŒGÂúöðéÃêŠíµM[t'n"K0ÿEÌAÚi¥ùtÄ5éŸïtáßÓG~É‚‰ªì×lúñýêOØ©ÀÀ¬Ýó:»Û÷‘Y˜|‹/0ú+)ÚcÁpà&ѸÑñ30xäø»wïnî %DÑ‚1ïÿxÍš5[©²_ß¶üR|F¯Çq£YiÂïSâ~:pÙwZt†»ÌÂÿþûïÅÂ… ­-> ߦ-n"à5h Þ}o½õ–5È©FóóM†ó!,FÙïMFÙ¯/›~(>â]‹ŽêXsü,š$â$Þ–ÓÙcû;>V{¤í`ø¨—·©¸‰@¢Ü\Ç!C¬`ê€ÿ¯¾› E*fÙoãÆ_RÙ/ÀGDÇ`8ì:²Û:¸4Ò“‰¢’ûæä÷\W|luaø6ÀM¢q¼MÀÐYŒcU÷¡¥ƪ_‡y-^‚hÿŽd»ðj—²__6ýP|7¹øN±öÀGÃßrh›øHž$|K‚ŽÝ®'+÷¾ßÛÑÇÇ¡HáÙthܯÁÀhܬô²ßÚöã>æsºŽXï©þ´nݺsÐÊ~)>#NûÕ¹y¨ý¯“ÀÁ Èé÷×ÏuP&ôpà&‰rÜj@øøÈñ¿÷Þ{Vá®M¿“^‰ú9 ¼=he¿ròÎÅ¢½KE‡Þù‡É¹ýÆ8Éø%G:ÆoÓI¢q¼#uðïØ’£™ƒ;a úu8]WA€{¡ÿ¾^|ñÅ>Ò>®“¬¤²_ €O1IJ Âì»ÏÀC.8Nâ ŒGM~«=òûHóáÜ)‚ ·üÊ!ûå´ßÆZÙïÙjõLêÃI>˜ôÑIÆÓp°òÛà&‰r¼Ôàsá‹£²C;‘ž4¯Å¤WAÀuã÷£ÿÎäçŽV³þWöKÈP¶ýáy×m$``Ï—Å'“ñœ-¨¯þõêÕ{F5ý8•ývõw€JjÑzº¬øÓ‡y`V5øµ‘ @*‚¨éGzi¾Z_ë׿vñôBèÂ)w ó²rNú©žYÿñ€ò€àq˜9¿.n"ªšló1´Ónè»â&RшA4‚€¯õc¾Àúõëw±úªì7(¬RÈq^Ec fðO¯÷Gä+i¤ì` þ?júáëãx.Ì´cúõ™L„  2R7~9Pd‰Öò{¾ZýÏH—Õ_€Üê† «Ê&(Ýe4¨àc½ô‡þ, Ê7HF0Ðü"ý]ºtù«¡G¿6“‰ûÞð<꾃 °ú_£­þ%ÓiõÏÒ.Þ€BÊ¿A{c%Uô€èç$ÑÑT²™d Å{É”ò>I”¦¶”|X²M‡&™Í>‘@²kðØ ¸«¿}hˆÉd ‚Þî«EþÓzõ7 ¯jh(ªÎUÊw¹ò0÷¼® ˆàs+™þKÇPý[ò6ÉúJ [ÊŠ¹ úöõò7HF0Ð|®=ºë«¯¾²Î°¯Ñ¼Îd\$}تþjÕªõ˜æû;µüæúêïȯ¹g©XÀ…ªóé2Õ‰Fˆ«Ôî€L kª‡óÕ—ŽúôÛ*Uªô¶®æö?”Ä#€šþììlËøéGÔ]¿F“¡Ä ‚€ÿÖb£æÿ[µÐ9­þ-û4PP튫/«ÒU±²«Iã%ª!¥šÚ¡An’§Ó¾oæþ‘þs2¨TÔ`z&õ"Ò:!¸>“É3ð'ûý\|ñÅ÷kUç¤ó꯻z6ÀbÊ8K5?œ£Áæ¹dJXNÕj\ R䨯—†5T˜ÑDã&ñFê࿈ô£¤‘~¤Ú°í†{bÓIb„Pbâõ¨4¦ýd«•]óoæýÓjõwÚäÕD °‚Ó•WyÐJÉä³”jCµE¹œÚ•Õ–yôEzé¯nX‰vÜ‚ø>R{(ëE]?jì±ò›`2‚`Ôû£ÝxSáÂ…ïP.n¥tÌûG*y”ÚåWÛžBJ «b!25,¢xšòIK*¨˜'OžÚ²„vŸ~2¯›Ñ$«&¯9r¤µåG¤I0|7&SPxdIiѢś*Ø}©*†;3ªþ¢qt!È«nþµ3 SÃüš T‚p†zH/GT5Òf¤µœvɪ Àçàî7ÞxCôéÓÇJGbå×J )ø”G뿯O>ùd¶Ê®\‘ur¿Ú¯þá„ ·&dj™×ˆÓÀ¨Ø²eË'Ìü¿i(^Ü/ÁÀE‹Ye½0~9BÛ þá{ )©}Ї=èó’K.yHeUªd<í'íW7Èå dê¨ïÊ hPI¯ÞÓjlqÝ ‘5ø\¹šþUÓ¿müNô*¡Ä ” @ŒÌ­Û¶m{¨;í¨#¾S!djø7‡¢-¸•å1Õýõ‡m´¦1$²&ÄÀŒê–×bEú‘ãÇu˜L• à=Œr_*²PT]¥2*vÑO`'ýé-ĺ`‹Š²íKemŠYè´&"ˆïaÖ V}¤ú0º )H€M'!H¶ }þÖÖ¿jÕª˜ów­ ü—îE?Dú@A%Ø®V“%µ ôÁŸºDãD ÄÏIC²ü}Dú‘ï7߉ÉE™[ÿÇ[ÿ›T1UE—ÀWÂw`Wl"E…ùt—Ëö*ûÁWh¯` ÞÇp¿öÚkV¤Fãw¢W1ˆ‡ àóÍ‚Ùì3++§â*UGaò‘±?"XPHmUá³^!ÄÞ¦×D"±a¸8”+?ŽãFÖ?nbLAÀÏ›C>dzr[éÒ¥ÑÕŠÓ}«[§À€ð¥S+W Y´_orò…ãåÀØÑ¿¹}(ôA==¢ÿ )©ÌÐ_ö ¹õÖ[Ñç_Gmý/P[»â?·`gN˜Þ$«kê]€(q %^ƒøÿ0(œË‡9ý(¦™={ö_ÆïÄd ‚nüf?øÌ3ÏôÎÊi«®¡Eý¹õ'+åK•*uƒþëà5h þ ?m¼ü±åf §îD?Œè=þ œ<4Mþ¾nÏÊéôCÁOyný‰  ÀI#ÜË–-{s$àÕ ÀÏÃÏG°í¼¨¤ÃÊoÓM‰A¢×dýdeâŠ"EŠÜ••“òC§Ÿ]ðè?h¨ û×ëE+‘º¤!Â`çĶ>¿.&S)ø Óøe9òŽŠ+>(W7fåTû!åg÷ùåÖŸªÀw­P½zõú¡À«ƒD¤Û~Œðš>}ºeüNL„ „'AÀkÌ&û\wÝu8Øùþ+”ßÀ)J¨íN?ný‰@ @~]d5ÛíúC@]¨Ê¸HjàCcZ/xØg ú¯ÓM R!x­™îÃl¿fÍšuRA?äû+;øýÜú€"¶œþùÿ2GG+º`ÃGY/ª QàAMðƒ 8?²">úh÷¬œ:ý0F ùþÒ.~?·þD àü’%KÖÑ~Là WïÖ*kGú?ûì31qâÄ¿ ߉¡Ä Y‚€Ÿw2þvíÚõV´øVUA?3ßO¿Ÿ´XA@Yp­nv)p4»üûàÁƒEÇŽ­C9±‹ÀÊoÒO‚€×a‡bæú_xá…Y9gYÔVû”qúÑï'°Or®5|øðƒ¶ å5\—œ.(šA¤+?Ò}pàóÛt‚X!”D"x³µ|ýõ×Ge圓€qéÕµˆ¿]ìàx0r¯) w»y`$»øÐÈí£º£º‘ãG´_“©¤"Í"eü£5ãG™/F{•ÍrŽø3èG^쓜¯–]y«tc@N<œÀð0½Ñ~øþ0,¿ý"fm¿íóËmÿ eü×+ãÇT_¤û00Å)âO¿ŸH Àüº²Òm9,Ô.Ó{`øèáGîÆ^~›nB*AÀû:ùûhîiݺuO?‘)pR3䲿}ªn0('ãGeêø1ºKž#h aü¦˜L• à¿Xõ¶ü2h¹·aƳr¢ý×fåTù™ÆÏt‘Ö€‡ýŸÒ G™cÁMãG°[}tòaZ/Ò…¶ñ;Ñ« „ƒhñ§@(Ó”Ëd 4ðÄ!©µCã§}€}ˆ+"Ü—Éy|Ù¡Š™«#¼ðïpL¦Zð5 ß,éÕ«û¤¿?8wîÜhìÁž8$µº ø9ÿ)4~"À‚üvÕ矾«[-â0únݺY<°¥†‘Ùt‚d ¾ër[ñUGß*Y×ÿ¼¼_ß…(ïÅ0O¤úÊfåDûiüDÆvT·U‘ƒŸH{0-ªVÆs•áÀˆ0üò6µ²6½ôÒKÛÉÕ¶ë³Ï>;HvýM…0H{ ‚mñ2rÔä÷ï߇tCVÊÓ§ËêׯÿŽôçÿ« ¾±ÚÞÿ[­ô0úÚjµGýþ¥ÊÇ¿À0üâj»j˜UŸÆOddÀ®,­bfå¤ËàG£Z¹s Èh Dáne”Í‹/þÈÕW_ý|½zõÞlҤɇ=ôP϶mÛfwèÐa¨ä0ƒCe>¾_«V­¾’u=7nܹN:ÿ«P¡¢õ-Ô{6QŸÑ@­ðÿR×p£ èÕR"£¯ª­öçi>~)ÃçªOP 7  Ú”P®ÚƒQ‰ò£k(1¸F ±®2Ê[”þ[k}µJƒ ]Ø@ý{}%*Øi ÿVõžu5c¿F}ö•Êà«©ëºH3úsÕj¦ hž¡mõ *‘s3|?‘±n€ ,¤‰rãç(㪨Œ­ŠZm«+C¼BåUÊ@k)c­­‚pש݃¯S¼V½¦–z«”Ø\¡>£ºÚÖWÑ ¾‚ÚÞŸ£ÄÊ6úbjµ/¢î¥@˜Ÿ†OP´X@>µZQ+hIe\ÿPÆVN ÂùÊ+)£¬¬ ôe¬UÕ*]]ãeŠú÷ª©Ÿ­ª^[E½×Eê½+ªÏ²WøsÔµœ¥üú†Ñ›«}^Ãð¹Ý'ˆ®€½( Œ Fuº2²ʧ>SàÙš0”UZN¹ç©Uº‚2`7VP?{žz]9õ^¶¡Ÿ­{)ÍàOW;•SÕJo}>Ãè¹âD®€-ön ¿2®ÂÊØŠ¨ÕötµC€1W†YRéß•HØBa³´Fýûgj^R½WqõÞghÆ^Ä0x}{o½ÛjOÃ'BpŠ¢-”RÔÅ¡ˆ2Ö¢J(l±p£ý3E #/¬¨{~ÃàVzÓèiøáAri•[„<šñéÂ`‹ƒ-4¡EýgókFžO{ÿ¼+¼nð4z‚H ä2ŒMStˆ–y æŽÐØiô‘D1'áÄÂͰÿ¡¡Óà "Â/AAAAàÿÉsÃ$tö3IEND®B`‚qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_256x256@2x.png000066400000000000000000000645501347155106100310420ustar00rootroot00000000000000‰PNG  IHDRôxÔúi/IDATxÚíx\å•þϨYÕ²Üe[²Ü ˜^B ”dI²v—ì&dÙH²d—ä¿!Mo”¥‡P–j:Û€PmÍ4î6î½K¶z™™ÿ÷^ëÚ£ñ­SîÜ{çýù¹dI£;ºÝ÷=ç;ç|"„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„Øá%àï›Bò€8/¿[B!yo (ü}BÉC3@ÁÈŸß!ׄŠ<E!~wþî !ü”?z#@×ï-’æ×BH>ˆÜá׆ÚPÂ)ü‘M!„„ÝXý?žO&€BìßU$÷ù „äSôo$ôq‡F ”&€7ÿð¿ÕÇ"³„æ¨ßéÛ¼0¼ùWü“E=ùã½G¤÷­ÓŒ_#„ FøN#~ýýXÂáÄ„Îðælñ˜¼Á/VG‰:ú%˜§€¯ BH€•øÇ{E¿[êèêý²A½ (âë'âoíG’>VØ+þ'?}Î¥£*.åå$„C™wì¬a½âßc`"IoïÁ¡04ÁÿˆPÔ+þå'Ï>ûçJüÀËI!¦ KÚ.ÆYO+À É™øG,Ä¿â¤Yg_YZ_ù}^NB±Õ@}‰4fbÌîÕñ0üð$¸â_pˆøÏ<ëʲѕ—ðrBˆ-Ò·F*fòu¡ÌÐSü«û±æ_¢‰ÿ“g]QÖPEñ'„Ô @¢ °[÷¼! ð·ø'¿_`ùïÿ'”ø©º˜—“BSØ{D¢|£VëxXDŸ xâ_d ÅÿÄ'ÎúYÙXŠ?!„¤‘ˆ'e"a‹¿UÚ_ÿÊg|ágåc«¾ÇËI!)gtOºïÆmŒ@ M @pÄ_7Å"ˆÿ¸þBÉLÀÌ„€àˆrä9ÅŸBÒÎ$€˜É}X$„üýRüùBHf3ÉÙV»û7 ñXü×Äÿ»¼œ„’QP`q?¥ šø§øBH† €‘à;Ý95äžPü !$ß3f& æžøWüûQü !$«˜Üjm&ü¬ žŠÅŸB²zŸ¶~»{; aäO!¼WÛ¡ÍÐøWü/§øBˆ'÷k«È?´u4BÉ÷ @(#|Š?!„{•ÿ4B!yñÓPü !„ØÐgh(þ„Âûx¥þi(þ„BòŠ?!„ð^N@(þ„BhÅŸB ÅŸâO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü !„Š?!„B@ñ'„Bh(þ„B ÅŸB¡ øB!4B!„€âO!„ÐPü !„Š?!„’§€âO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü)þ„BhB þâ@ü+(þ„BhÂ!þâ@üKzÅÿgB!4Á6ÉQ…øWRü !„Ð;ú7ÿÅŸB @xÅß*åŸøŠ?!„€™»ŠÿbŠ?!„|¢(ÄÑ¿•ø§ýg(ñGñÏGUËÀâ2¸x ö¶º¨¿T–KyA™”«·eý$)Ð>vñ¸´D[µwÛbÒm“Öh»z¿]šº÷JcO“ìîn”=ÝMÒÔ³—›BEñ7ûX²(½Ú†jõ£ø‡ûÅ)’1eõ2¾¬AêJGʨ~µ2²÷()(öä9tźeSçÙÒ¹M½Ý*;6˪öµ²¶}£ôÄ{øK"„Ðd8`ý&EþßãË!\ RÑüQUSeZåT™T>^‰fr ŒÆØ²ÑÚ‘HO<ªLÀYÞö©,jY&7/–]Ý{øK$„Фý›-Àô;ñɳ~Z>¦Šâ’šüS«—ãú¥EøÁyî…2¡|Œv|yðÙÚÇ%xoßGòöÞ÷哿¥Òïæ/™Bà"ú1®þ‡(Uâ _Á¥@­Ë¯Äþ¬Ÿ“ûc¼FPFô.?ä‹ÚѦj ÞÝ·@^Þ󺼿ïc‰ªŒ!„Л³È?1PÄ—@0©í7L‹”Ïxš–ê;å…eòùšSµ£Q¾Òø†<³óÙ¬²„’¯ bò~òÇŒ¦þò%,&–“ó‡þœQó)Œä篯Fu)üÓÐ/Ë?=O4/’Y;ž“ù{?”¸úG!ùžH³À¾‚Á‘•Sä»#¾!‡WNæÅ8ð¢ŽÈ±UGjÇâ–år÷–‡eaËR^BHÞ€D±7ÿ3ÁÕò¼PNè4/†0F7Mü½V4xǦ鲮cc^^‡¹ÇÌôô|g,8Ÿ/>Bã?ù}#3À @€è§ï|}ØßË7†-ç­{AFéØÃŽ”§U}À=[‘v5˜ˆdóáÒ ¡ðy&ÀÊŸq\ÿiòßõ?”¡%ƒy1Rµ_Su§ 8^®^÷g. dt¡°#ƒöõbÑ7úxrôáKÀ_ÂõoµÈ5ãIñÏÃK†Ê'—Žú¶6g€d'@3Ì4€àÿnìåZ•?ɬ@!0¡|¬üz͵j/‚}¼(ͨ[ W39{7F ±äL¿ûó¤?Qü³È•‡É_&_# ¥u¼½ñðBhü(úÉ_c– 9ä´'ÉŸ'^%CŠñbd™Zµ$p«2Zh©$™ºòBhülÌZir ¦ÚýrÌO<Û‰ˆ¶µñ5ã!ǪBK’›L„·B„Ì€™ 9àì§Ëÿ4\–·Óür Z,ÿ0ö š€ŒÜlx !4~þˆCѧÈ!'U+?ýC­…ŠäÊ”ÈoÇüT«¿ éÜ@ù&4AÍÐx̤òñò«1ÿ‘¿ÀC÷?2¬d/Fª7.€@d„‘nÁ®}w¥”ª4ñËï¤Fk¿,ް#µ(o%„ ˆ†€FÀCñÿr̵숿ÀŒ€Žºˆ"¥ — !–|»ö_Ø~æc¾:ä\9½æ^f @^fH–˜R1I.öU^ŸsYÝÅ2šn%„ÐAè)üƒjó+. ]ÅK´Uš£-¡ú™úU)p _´Ì<û¬’¬rQí×eT¿y¾Û»vʆŽÍ²¥s›lÖŽ­Úû±Ni‹¶Kg¼SºbÝ}ÿˆÔvÅe¥RVXª8/&#û —êÀÛQ¥#Ô5¨ ÄÏÿ™'ÈçÔRÀëoóÅë$Â`¡t†€d ˆßùj#?³§»I©ír?l^(îûD¶vípý=zâ=Z6@ÏÀ@$3 ¨Z¦UM•#*&Ëá•“µÂ;¿‘AAà»{?ÔL±Ë°ŒŠÐr?ªûŽû Dòóß”gw½"+ÚVyrΦž½ZT­GÖÈœ9ð49{ÐéÚŒ~?}¾>ìäþ­ñEÌ ¡ Ä'ô?ZÇøê9­i_/³wþUæîyCÚc9}.›ÔÒÂô­Ë[gÈ©*íŽ"É©ªXÒ/àù<»ë%ÙÕ½‡/fË ¡ ä`T¤þ}{Ä¿øæù ­Ïæ‡UÔÿ–ÚºÝ_›·ãù¼Ùô®vœ\}œ\<òB]:*çÏ Å›ßþrÓÆÿã ÚòµÎ%dKH†9uÀñ2±|\ΟG4•G·Í–o/½L檔¿ßÄ?™wö~ ß[ö¹gË#‡æ‚/ >S4å ÚÊ0@h9ý£ò?× šÿ²•¿”»¶<$*fëQ¦åám3åÒWªe‚-9}.¨ßø×á_ã‹ÚòÊ[(¡ DãøþGÉØ²Ñ9}K[WÊ–_.KZWö:®j_+—,û©ªÆ_ÓçqŽ*Räp kÃK !Šú圞ÿ­½ïÉO>ý•ªºßøk‰BÅ_®¹Z[¾ÈØ$è˃Ïá Ûìʽ !¢EþÇö?2gç³é=ùíšë|±~ž)°$pÕº[r:˜ç«CΑ’îÈ ¡ Ä„¯¨H1W7Äm«åënÒ3l ˜?ÛÇÍKrr~ 1úLõ‰|fh Ésú©¸gülNν³{·\¹ê*öK%ð»µ×i?k.øÒà/ðEn˜à-”Ð<çój~|Ea¹ççEkßÕëþ¬MÚ ;¨køãÚ›$y~×ö6 É€’çœ;茜œ÷ÉÏÊGÍ‹òæ:/Tû<½ë…]D¾£ ¯ ‹ Ég”#*óü¼;ºvÉý[òo^=íÎÁˆÞ3jh½2@hHóùšSsRü‡Yú¹žéŸ °™ÑÃÛfy~ÞúÒ‘ÒPZÇ|b€€î@Òætµþï5ÛÔ|ÿ—÷¼ž·×üùݯÈ7Ô”>d_¼ý]ŸšÑ]ç33п‡KÕŽ—-ÑVíýBO•–Y~}YA™š°XhúùBõ¹²ÂRËïQQP~`þÀõn—çÔ®–„ÐÏT\#‡ULðü¼˜ñÆ–?§`ÖÁŒíÏÈF]äéy±a· >ȤïyÍAA( \ iqRõ±ž§AÑ ÷ÂîyyíŸQÛõzÝý0¾¼A{œu æÄ…€ÐqbÿcûÄO©˜äé91ò·#Äþ¤Ê¾žfYÚºÂÓsY9…Þ° €ÐÏ™P>FíXâé9ßÝû/¼ ìûØÓóM*Ï‹î8€ÐÏÉÅðŸš?æ…7á} ÀÐ’ÁR]ÔŸ>çÖâ1“˽5ë;6ÉÖÎí¼ð&¬l[ãùP q,Ì9¬ 4Ä{àqÀëw#Áo‹<¾|,/|® k ñ’ŠÂrÑo˜§ç\زŒÞ†Å-Ë==ß„²1¼èÌ’O ÜëA0+ÚVñÂûìM`ÀÖâ!cÊê==ßžî&NÿsÀêöuj@gç«+¡¶·-å…g€Ð¼É”z[üÅèߨ"xmûÏ·,Ðævâ)£ËFÑø”m«==ߘ²:^ôÂ9„€xJm‰·€^‹ZYéñµV2”=§B@<¢(R(ƒ‹zzÎ í›xá²±c‹Ç`/za ¡ žÞð "Þ½lºãݲ½›€NÙÔ¹ÕÓóÕ2[ÀB@¼b¸Çýÿ›;·1ÊqÁžîFO7LÞ€B@ò¯#¾M§´ƒªÂ·(Ó䃊k¤¤ ˜>‡¿oBR¥ˆ—€¸Šø<6;i\›&µ 0Ö£ö<´-ìùÒCØéŒuIW¼ËðsíÑUýÕÞïŠuñbâ‘ð8廹ƒÂâ÷k†×DªàŒçgô¹Ì=f¦§?û÷—_®½m¶®ÇÇãqõ¹6ÃÇ¢¾ÅËåBhHZxݸ½k'/ºKvx\49< W²E•ÖWxÝöµ§§‰Ý%»U! — e+ !4$Ü`½·º¨ÊÓsîêÞà ïÖ4u{kšª‹*yÑ ¡ aÛªA@^mZzZyá]Òèq ª°Šfú{ý#•Í6§®[Ç€BhH¸©*ôöFïõZvXÀ®€f•çY1†…4„Ðp€¢ OÏ×ÈÀ”ñ²€BhHÈ©.êïéùš¹þŸ2-Qï®3„аg<¾Ñ·y˜Æ^^»²Â2m—HB mÀÛ"À¶X;/z®ÚC+™ „€„—JÏ34©_»OÏןu„Ððâu`+ @o—O0#‚B@BJI¤$Ô"® €·æ©(ÂmE¡ ¡ÅëB/.¤cž¼½vÅ4„Ð0ooòÜ*5kíôøµQÌ‹N +^GyÑx”=Õk'Þ^;¶B@BL¡Ç ‡ 0æ‰K„Ð0g ˜ 03‡ÌB@B‹×iÞ˜Ð&PÀ !4$ÄÀë @Œ= ׎m€„ЀŒÑïáEȵ£ „€Ðd0Šå3„’ûKÄÛ—Kœ—|ï¥ ¾ÍÔ àEOþEURäá(`f „èkˆ‹HÏÛµÞŠÂr))(æ…wÉ£ÐÌ !¹þHºß„€8&¦¶|õºuî©öÚ0@ˆ_„?bq@ï‘,ê}?B@\±³k7 €ÏXìíÒIcO/:!Þˆ¿è[=z_|íµ×6ÜqÇ“ðâŠí];== ýŸØÝM@H¢~£›EþXK-»á†>7~üø~ýë_¯a qÉŽ®]žžoXÉ^t— -ì±ØÃ‹Nˆ·¿Óÿôê|Ùm·Ýö/uuu×.]ºô+Û·oëŸ$Ä· ¶d/ºK†÷ê±häE'$ûâŸñ'þß(ê‡ð÷Þ­Ž( qŸèö:0”ÝuÀ;ӄΦž}¼è„x/üñ×"ÿýèGÓN?ýô{úõë× oÛ·ßñàƒnÐÅ£ î2Þf¼NgÒ‚~ª°Ê³ó¡&€â™øGL>¦û•^wÝuÿn#øéFýHùk½ýßûÞ÷ŽRiÿëKKK'Ú=±… Þ¼víÚæ$ñ$ýŸsHj¬éðv`jÅ$^t&•óö5àñR¼6$EŒ¡ˆ3£à¶¯ÿ€ð«I~ý¯¿þú‹¿ò•¯<éDü[ZZýéOzNö§þãç8øúåý­—Ï 8Ù³óM«œÊ‹nwª¼½FkÚ7øîDU4î¥(E ùÂ#Y‹úQè÷­o}ëUíÿ§øõ×_¿A-tÊþ¡?¦âO@ýM®˜ ¹íˆuò ‰cËF{k;ü—ðÞðJ ¿•Ð×ú {ú•ÿæ7¿ùÊ´iÓ~S\\<ÀéIwíÚõúí·ßþaoôo6e€¤Çª¶užž‘ÖÔÊÉòá¾Oxñ 8¢ò0OG#Õ¾®}£/ €·¯KÞBC.ÞÉÛ|Ìn󻨿Ÿêé¯ýþ÷¿ÿó¡C‡þƒ«¿Éx<:{öì¿ÈÁyÿF™fHúlëÚ¡í?¨¸Æ³sb€ÀäÚxœþG(ºü†×yÈJ‘¼5 q ÃRÔ¯Úûþîè£þ•Šú‡¸}B›6mšóôÓO¯’ƒóþž[Ã"@’2KZWxz¾cªŽàE75GS¼ýÝ·¬ðåuð:P]ÔŸ/¾üÊ8ùœÝ4¿BIhíƒð«¨¿Nmâs½zûçTÄ_ ýéxàî‘ým1ƒçg€dX–ËiNòì|‡©:ìA€ì9ÈÐ’Á2¡|¬§ç\ܺܗע+Þí±¨â 0?Ì@b ÛÈ¿@æ‡飲_ÿú×ç!êWC}§ú?ýôÓ'ÔÌÿ­rèУè?®ÌÀˆÖ¸O«9™>‰ÓT7†—ëÿ`i«?3^/K0À ƒÈ?yQå¹çž;þÁ¼óøã¿%ñïîîÞ{ë­·>¤Þíƒ ,L3$uV¶­‘Öh›T–{vÎ3jN•ÛŸæÅOº&^‹¬ As· ?3at³¯‰'½5‹üÒÿšø«¾þ Uáÿ/S¦Lù………Õib‹?¬†þ4%Dÿ}¢|“Cû’2Xoý¸e±œZ}‚g眨†ÝŒêW+›:·ò À’ȤŠñžžs±ZúñëÀ–h‹§çÀ @ØMAÄøÛeŠzÅ¿ì’K.9öÌ3ÏüMyyyF š:::¶ßtÓM³¥ïÚÜ©àI‹÷-ôüœ_ø9^ø^>¯¢¯ÓÿïíûÈ·×£Ùã%€ý†óEžè߬]ÎIŸQ[Ÿ¶kŸ:Ê'MšTû—¿üåççwÞã™íoñ½÷¦«-[zÅ¿Otoù —HF @³÷my_|–<¼m¦t{\ðå7°ÓyêZxÍ;{?ð¯èñ60ºtoáüÅ&ò94ݯ‹¿Vä§ú\YRR’Q·¨Fþ®»á†^”ýkÿ1§Qâ×Ñ´ØØ±EKÇ#-ï5j0ÖYO“çw¿š××þ”ê㥶ß0Oω €¶wíôí5iìiòô|X‚éWP¢mEB1^óO½º_K÷_tÑE‡ŸuÖYWª1¾Y)ÒyõÕWïéééÁhÔ¨‰ÐÇ„K$Û¼Ýôžçç¼°öŸ¤8RœÇw¦ˆ|cø×ý'áµ9AfT¿¼ „KäTô'§úõêþ UÜ7ò¶ÛnûùùçŸ?;[â¿gÏž%wÝu×;rp»_+Ñ73DÒçͽÞ€a%Cä†~)o¯9Ú!'•ϋߵŸ À>$T&@Äù@]üËUuÍÕW_}‘Ú‰ïÕúúú‹#‘¬E(ñ§žzênõVþc‚Kÿä¯fHFÀT¸Æî&ÏÏ{QíZ 6ß@ÛåŒúwÏÏ‹ôÿòÖOi’8®êHÞÂaì?ñÐ…¿Týÿû¿ÿû¬‡zhÎá‡þ{ÕÓŸÕùè›7o~gÖ¬YKä`ß¿Ùa·À É€Uÿ^kzÛóóbûå£/ÕÒ°ùÄ¥£¾#ƒ‹z~Þ¿îžëûkÓØ½×óõø“ªótÉŠð»‰úuá¯ºà‚ ¦a˜Ïé§Ÿ~_YYÙ¤l?Y5ò7öøã?˜ý›¶4$#¼´ûõœœ÷(µ ο×~=o®ó!ç :ÝóóöÄ{äå=¯ûþúÀŒz=*E€7ø ¼ „'ú7Šøõ {4á?å”Sî¼óÎß|ó›ßœSSSs–ˆ7½¸7nüÛܹs×ÈÁÊÿ˜šú™üÿNvŒ°¢m•¬ïØ”“¶¨UÅp›U' »ç…úUu¸\VqNÎý¦*ôÜÛ³/×iUÛZÏ_‡ßv¾ÌÛó–ììÞÍ›A0Å?±°/Öû6±íO3‡vXÍ~ðƒ=zôEjŠ_¥—OTÿÑG}ô19tíßM@„K$+Y€=¯åè/8"?©ÿ|n@x÷ @¡ÙïÇþ,gOìx&0×jUûZÏÏYUT)¥Ö¢Jýø¡—¿bèСƒ®½öÚ謹—ÆŽ{i*â¯IEEEÊOtݺu¯¿ùæ›ëz£ÿ¨ðÛFÿÂ%’IþºëÕœ ç)ŠÊ/ÇüDÎU)òðEþSåºñ¿ÎÙ:óÇÍ‹e™Ï‹ÿú€u99ïø²1rÏa7ÈW†œ#å…eY9Gea… T&óÆ”Õó¦“ù @â†=åjxÏ5·ÿ몭ï9ÕÞ÷sµUï T„„ Ò¿imMmR¥Šþ{T­¢ÿ.é›þ7z'Ñ?'’ÌÒ¤Rį5¾­†ôäfT/Š/ýÒPZ'wmyÈó½á³Á—Ÿ#?ªû¶28¹ûS}tûì@]3,äŠEÕrYÝÅòƒ‘©Í²VkÙˆ]»´M³ÚcJe ´š˜¹õ…¬åR\P,å¥RVX*%‘Í@ôSŸÃ×Tª¯íÁû}³?øž_þäBÞxÒ¼mHßÊ~cú’Ë.»ìój§¾‹•€§Ôo ᯫ«“ÊòåË¥±±1õ×ôªUóÞÿ}ìÀÕ-Ö…vË}'þþI&yjç_sftþyØWäðÊÉrÕº›UmÀ¶@^G¤”!$Ÿ÷x§¿d>U;>¾¿ïã@];Ô*x=2ˆü•‡iG¶€IÀò—_7f P@/ð%üÅ—^zéi'tÒ·Uº>%áGšÔ¨Q2dÈéêê’… ˆüãñ¸¨ùÚûªk@¢Ñ¨ö56Ñ÷Ã?ü„Iô÷kÿÜ d¤Š?iY"Ó*§æôyL©˜(w«tì#*z}|ûSÒëÈÝ(¢¨‹G^¨¥zsÍÿmy(¯Ãj“ªQCjCý·†× 2mÑvÞxRGâ1¼øâ‹?ãŒ3¾[YY9.]á‡ÈCôÕV½šÀCèÕØ^QÂöüª*ihhE‹Ù›ðO?}õÃ?ÜÔk¢bßþç(úg€d…·>!Ó&LÍùó@ -‚_t¦<²m–ÖÇŽv6¿ÞÌOª>V¾UûÏjÂß8_<§ù{?T»=~È×àj“*¬Å‡ò‚2€4@1ßøÃÓN>ù䯩5ú1™~°k×.Y±b¢wlÙ«Eþˆø*(UHˆ–>Ûï­ŒC×ý÷ßè?¹ï?*©Uþ'þŸ€d!új^$KZWÈÔŠI¾x>üãúK4q}eÏßäEÕ.¸®c£/žÛ â9sàg土÷UQê'îØ<=°¯A.âg(Œ†úo µ»º÷ð¦ã’Uÿ>¹}¬\òðÃ׫ˆ?¥]úŒ„lÙ²EÖ¬Y£‰~SS“õëâšøÜŽöó*TíÀË*K€uÌnÑ·ë°ŒþiHÖ¸gË#rÄßúê9Al/öUíÀÜ /ZмP6tlötSüŽQãcÏø5Fvš/'>½óíº•–h«,jY®uP„ÝçÇŠäˆö‰r\ëRU-y•âZü•aÐD|ðàÁ}>Q_½zµlݺU{Û¶mZ @AAŒ7N3 ÝÝÝvÑçôéÓgªw;ä`ë_Ôeôo–   ÙÀ0<æ3NðåóÃF:úf:è^XܲLÕ.,Õj¶¨ÂÁ¦ž½»A×– “IªžèU˜xDåõï_°µs»fà‚ÎËj.EØ @¶Ú Cwbertëar”:JãýRújg?-⇨ˆµ–òß½{·–òß¾}»Œ9RÔ¾Ú1yòd­ PgçNû=+–-[öâÒ¥KÓþ“‰3@<áN•B>©ú˜œ¶°9a@QeTNÔŽX§f¶vm—m;¤KÍ7@TÙëÑÚ¹pÀåïo×*9к…¶­¡%ƒ5‘‡ð£š?H ríú¿h?_ÐAKê¥uß‘²‚Òðf ˜°¢¦§Z‰þd9²}²ÅS[0`€¨É}<ù-Y²DZZZ´”?|=–JKKEÍÐÞê òWÛùZžS ¶«í~ý[õý§ý÷ùs§ Y-xl›­ÖÞÿ)pÏýÙcËFkG>1{ÇóZG€‰y³éÝœ·¥fÕp àPP[ßY«"þ)2¶³Nû¿ëï¡Ä‘¾ÚÖWKù›Jˆ?¢~µKŸ º Ò‘¿ê,ìóDÿø:+T÷À j9a—ô­ü·[pý3@²ÎCÛžS§MI#þCkîÚòp¨~¦'wÌ‘/ <-%å4ÅLųSÚÆË±mSe ŠüSkõX§Ç¿^¸gÖñUš^:;;µ¢?…#FhŸ4hLœ8±Oq`¢°‹þï¾ûî§ÄÙŽN³†f€€d•U‰}ͺ[å¶ÉWçlŽ=±Ãs~µúZµ•ng¨~®OÕTÀ·´Z”Cš` @MO9\öÙ6IJc©­ïCøkkkµ5~5þ×öëQ০óIss³¬]»V[ï×kð>–ŒÀ2Ý8`e*^Qsÿýcí¿Ç$úŠ}ëŸeôO@|øpM¸e5ÔgåÊ•Z…?L¢¤ù±T#1iÒ$­SÀêñd…šú7Oe¶;ˆþí6ý±þiˆ§Ü¼ñÿ´ùìÙœNÜv?ìßvnß4]Ž®:B½þFÐ4ÚGŠ\Çh5¸?õ¹ˆÔ!üÉÃ{ì@å¾jÉÓ"x¤þaPݬÌÄa‡f[3€AŒ¶0==ôÐ,9Ø÷ŸÕ蟀x æñ_¹úrã„ßÉ„ò±¼ 9ro›™?+Ú:¯Vµ(7MüïÛRiöƒA=‡µ“i*ÚïM½V¯èÇú¾Y+ŸmmmÚLˆ?Šý°Ëßøñã1FX3'ËvŪêÿoüñæ^ñÏêÚ? É ˜[~E¯ ¨/É ’#flZú} ¯~æ¥j<õïÖÞ ¿óÿB3"8lƒ€PÉ?AEùG´M”Q]ÃÓªÛ€@#Ò‡ðÛEçf §‘?Zü°îê~´ùÁTàý &8ZB@§ÀÞ½{­¢ÿèc=7޵»-㙈þiHNhìn’­ü¹\5î´]ûˆw`ÐÏÝ›–GÕ.‰ùæ\»þV¹¢á?CQŠ €’¥‘ÝÃdJûxm>I<½n!Tñ£¢…}X›O¬õcºÖû‘¾6l˜f& þøÞú°' {`Õû¿~ýú·ß}÷Ý rpê_ªÑÜDðÙ@üCsO‹\¾êwò‡±W¨q­‡ó‚x@g¬K«ö£i~^_‡—Õ†P;Õ:¿hø±/¶\N+à.€AÝdJÇx™Ú6A*béÿHïC˜1£ßÍú¾}ÌõǶ=ˆ½^70fÌ­xÐ 6éÿø¬Y³’gþ§ý›Š= ñX€ øá¨—¿òE^,‚?¤¿—«½Èþ½*¾¿ü§ò‹1?–#Õþ ÌxÖòåÞ>AÓ›.H¿c}…}©¬ï'ƒJ}U‰¯­õ£ØÿÇz?Æ#›€ª¼ï¤þ1)Ð µ-ð{óæÍ[-é÷ý»ŠþiHÎÁ  [6Þ­íÎwYÝÅj®~?^” 󺚉݆ۥ5ÚÆ‹‘¶ÑýñÊ_Éi5'ËÅ#¾)µý†/ j°”áån–nÁæ;Û´)}#º‡fdé;ì! GªßIž£{‘ªÐÇz?„Æ š¹€à£ÐÏi¥¿¡ùÞ¶Í2úŸ={ö“r°ï߳蟀ø†w¿&KZVªµÙKU]À$^ s•m~©á„AzgïûÚœ€¯9WkU Ó²ÂR-›æ'úÅKTË^ŠöÇÉèΪq/3[^#ú†è£/Ý4"ˆÐ-Z¤õùc½â·n*ý“±ÛøG úø¥—^Z!gþÇ$µ¾×Ñ? ñ›:·È®ü…\0ô«ÚB̤Oea/‚Т:sdz2kÇs2Mm!|Þà³ääêã|µ“ ²e:6iƒÖ´¯W6׫÷×ûFüém¯“‰ ÒÐ5R ã™é´@êxþT«ù­@Š~áÂ…ZÁ†ûTTThÕý8¯›J#PHhUü÷ì³Ï>!×þí2þiˆïÀXZT¨¿¼çuùÞÈo†z#/¸°öåõ¦·ecÇ^ ‡Ôà(R­‚S+&Ëqý§É±UGª!ÔvÏÙßÏ‚¾¹s«2Ä[µ·:6k¢¿^‰O¼ÇW× “ù&v6Èøöz©ëªÍèß*"oˆ>Fë¦*Àv`2Ÿê½×ÄÛú"Àq¾8ŸÛJÿC^KJøaÌP…‹Ÿyæ™%IÑÌÀd%úߟA .‘¤÷‚Þ£0á€Ù)N8`%}þïÍåmÏ¿`jà¿×~iðÁ¾O´bK’˜0²ßpm‹è1¥õ2´dˆÖE0¨¸F{; È¾¨ -ÑÙÙµ[öô4%¼Ý%[;whY°Ýݾ¾(äßQ¯ÖõÇÈÈža’Éò´ðA𱾟h?Ìñÿàƒ´‚?ˆ5΋íS­ôOFß-Ð Õ÷ÿ5ùï õ.vÒûÿž¤#*öÛÿÒЄTj_¨–‰÷üaí2·ñM^ˆ,ƒ/KÕÒUa¤@­Íï°öh‡tÇ»]„Y­ÒÖô!ú™*ä;póV‚‹úÙXÛ7‹ÌQéÿÉ'ŸhÃ}€¾!†aí¿¦¦&íó,_¾Ütý_ Z÷Ío~ó2õ.¦uôf¬ @Ô"3 rèðG¶ŒK$,lY*?ýô·Ú,÷/>ClÍõmü‡jµÄ†?Í*ú$ÙBßíÞ“W[,íèªí´7®³^f e/ŒÔÅÚ>"o'[ðfTú/Y²D ÷ÙÀd?<û¡ ]°œ€ €o¿ýöÓð†b=ø'kkÿÌ0hÐþtÚ€“äÌšÏj›¼D xQl˜³ëE¹qÃÿñBCJcý¤^mºƒª}¤øËc™OÁ£’b áÏDß¾PéáGµ?Šýí£Ç¿ªªJ}ˆ¦Œˆêí×#ÔÞ;Tôÿeö¤ý›þå nP(õÂîyÚõ×Ï 8QN쌣̻Œ9OeMÐn¹´u%/ÑÐSûc;Qħ¶ÆgÞHCh‘R‡èãm¶SüF@ð,X õùÃÀˆ ºY BÚ?S…†vÅï½÷Þ3Jü[¥ïº¾Yäwp¤ <{ÔÞÏì|Q;P¥=­rªv €pRùxO*·ƒÖmRÿ}¹DMÀ‹Æ£¼ yúÑÕ›ÚWQþ žìŒB†ÈCì‘ÞGÄŸ­*~' Õb?ôøc Å…|˜€t+ý@êKF¨MöÝ{ï½/÷FýFѽ“ôÿ!ž#•蟀„ôsc­@Q¶§Z¸Æ—7¨·£¥AUpçrµí];e˜ª Ϩ`ÿÇ¡çÉãÛŸæ‹%O¨Œ•KCÇHÓU'£;FhCz²Di}>æægjB_: Ò_m²ƒÍv´ÈÏoܸqZ?ÖþQx˜i¶nÝjú9µ­ð ª0pŸ8ëùÏjôO@Bв° ,ŽDjÔ²AmÉ0ÕÖ5L[S„v®êãÕêýj©*ªÔŠ S©vîT{Ï·ª%жX›ìRË|˜Ãc]ûFYܺ\ËX\=þäµd‘ þ­öyMM¿ƒ!áŒò‡vÒÖòǪô~¦«ö“E½óØ€Ât.Rü‡„ÄJì1Òi˜ oå ñGú©ÿLÓÞÞnºí¯Ê>´ßsÏ=Ï&DÿFSÿÒ‰þiq¶$Æ‘l ’AK²¨+ÀMTï<ÀÀ˜–hëþ?zÕæ¥§Ô[•èc˜‘·l¼Gî=순,OàgúϺïÊÿ¬¾Š/„P+ÕñhëùêÀT¾l…èCP!¢ýdñÍ¥ ˆF£Z¥ÿG}t  õuuuZ‘ßäÉ“µ!CÙÀ*úWKsÕ»¤ï¦?‰Bo·á]ôÏI€„d’ÍãÈ4[:·©‰‡³´h<`Ì- 'ßlz—¿ä ¢nõµ=Cd ¿k” ë,ÙÜ3ñ±¦ÁGϾ¾¦ï‡h?µÆ® ?ªýUµ½ö1 ÷A-*ý!þøY²e<̶ýU» ö¨¡?O'Eÿv›þd\ðiñ l›-g¨6ƺÒ99ÿÕ}O>j^Ä]¢úúÎRûXÛÏvDÉ|?ªåÄ>×Ñ~"---òá‡b]+ƒIÁz? 2“&M:$[‘I°‰L€k×®}Sí7°Yìûþãb?þ7cf€€ú„?oº[®ÿ«œœ#l/Rˆ¿lº¿ ¢­å÷ T|£T¤?*«kùE{J>Þ"ÕŸªØ{m Pyÿþûïk3ýQé¡Ç:?L Òÿí‹ç£oÌ“çfÑú‡-£ÿ¨ËÈ?+Ñ? !9sú_ozG>7à䜜ÿ†|I^R/}Ú¶†¿ P/RQ~­6}oLç(©ŠfoÚ%"d ÁÑ#äÄ x~Kí[±mÛ6­ÍEx¤ø!þh÷úÿÈ‘# JrÆ#ÔhßKɨ"Ä^{íµUb¿éYñŸdË Ð’cnÛxŸê8:'[Ïb‚"füÇŠ+/’ÌSÝS© >úòGªa<…’½žyˆ#Òú|´ÄAøÒMíçjç]·nV鯊ë´ÁÄ`ºŸnœVú§k¬ÿÌ;÷Ù¿ÙObßTÌwþ³Ëd¬Úƒ€³³{·Lß:C¾?ò[99ÿ¤òqòÕÁçÊìÏó—ჺÈÄŽ1Jøë´–½l¥ö‘ÖG„¯GùéöæûŨ¢:m§=¬÷ëm~úV¾¥¥¥Úz?Ì@ªÂîæq(<´ÚôGíú÷QBôoõ›íðÇ6@BÂÊÌÏÊYOÓå‚ïŒøWy£i¾ìêÞÃ_F(RqýÈÎaZñބΆ¬¥ö!TzZ‡“m2!Ô^fPà‡yþhõÔ?€9˜è‡ŸâoVéŸ C€Ö¿äÏë¼óÎ;ˆþ;ÄÝà»Þÿ ¾. !9snÙx·Ü4ñ÷Y-ô2³þ£îÛòÛ5×ñ—‘!°¹_[ÏW­zűìÜn!v{¤ôñV¯t÷Cj?ÓÆ µµUT5½6Óß¾ý»-ê[ùâgGÚ?¹xÑ©°»yžúã‰@õ¿ª&`—ûûºô]û7ücµÓŸÙÎl$$,,jY&/í~]ÎtzNÎBDÌxgïüe¤zCj­zSÛÇËøÎÑYÙ\±×Ãm¼ê\­ù£Ðîã?Ö*ýQp‡ç€ê~¬ócôpr¥&£|3Ð÷®#Ô,‚¿ªÉ€mÒwW?«êÿ˜dh›_BÈí›ïW"|¬ô/ªÊÉùõÙÙ~ZÑWéýz5c’ZÓGz?Ó‘¾Þ“¯GùN÷«÷:‚Ϧ1@¥?ÒþØÐGïñG±®Ç¨Q£ +ýÓv§3›ü‡±¿Ó§OQÿ¹úcùg<ú§ Ägìëi–{·>*—Õ]œ“ó-,Öþ“ܵù!þ2,(T‘>ò@ôÇwŒ–’xfG:#ÊÇZ> ÛpØ °ñsj?Ýó¡ÂÅ~hóàd<ô­|Qô‡‘ÄnŸO& f`ö¿*Kñê¦M›PPÓ-öé³e€ŒŠ= !`ÎΗäì§Ë”Љ99ÿ?ýŠÌÝó¦¬n_Ç_F¢P¨(ä;¼c‚&úýb™ÝU}ëzµ¾>y/h|&³X_GÄÿé§ŸÊêÕ«µï­oå«¿Mœéïeêß*úWÏ;úøãÏ‘C[ÿÜìú'ÙŽþiñ!Øh·MºZëÓ÷<ºj³.]q¥ö\òŠh¹¶¦Dû$Г¹¥½b‚¯¯å‡1‚O…îîn­Ê¯÷øë[ùBôQéow½Ò-ð³z,jô"Äd6nÜ8_Í&Ø,éoù›Õ蟀Ÿ²²mµÌÙõ’|uȹ99ÿaäKƒ¿ Ïíz9o£} æ9²m¢4¨‰|™êÌHž¾gW±–Ô¾›¯EZ)ÿ5kÖèñ×ÛüpÝ`pݼHû›=Öj׿çž{cõÖ¿Ä©™Øò7£†€€Ÿr×–‡´û0³?\<ò›òVÓ{ÒÔ³7o®9¶Õ=B‰þ´¶ÉÒ?š™-c±~¯÷å#Š… sj?óíÝ»÷@ä¿k×.ícz›*ýa¿·×i=;¡?·dTWÀÒçŸ~¹ºéÛè?ë3hñ1mÑv­åäüU…•òƒQÉUënýµ¢6Ý9¶åp™Ô>F«êÏT¤¯ñéÛç†E¨³ñÜÐR·|ùrmÍF_ÛÐРù¡Ò¿¶¶6kÂîæqèH0üóÆo$þéw<þiñ9/«zÎôy9ªêðœœÓ _Ú=O>l^Êë;²k˜ßr„ŒU#yÓMóC4áësöƒ:'&ëüHù£èÃ~âGª×QïõOe'¿L&šÍýWÛoU­óåÐMœ¶Š—Ñ? !>Ex7o¼Kî:ì)Šæä9üWýÅòÝe?–®Xw(®éþõý:9±eš ï’¶è£b_ôƒ6k?ׯ‚Šˆ_µÌiâßÑÑq`#û¡×?±Ò?QÏ„!ÀÔ?³Á?jGÂ9ªM1yì¯Ù€§›þÐPÖwl’'wÌ‘¯ûûœœT¿Zù×açËý[ üµDïþg[Ž“a]ƒÓú>hC«©©ÑŽLòù)*Ïösƒb¤/Rꬭë»ùaùo±±O¶DÝícñµx®F(ãÒ¬Æþ¾*}7ý1Ûú×Í🬚Bv <½æ^24'çÿ×áÿ óßÔÌH¥¶ÙýLó±ZÊ?Uôb>¤£õ>ý|àSýˆôQì‡tº>àGßÍO½Ò?Õh=Ó†;þaç?#TíÂKêóͲ¿øÏjòŸÕŽžS „ßÓ©FóÞ¾izÎÎ_)’×_’“ŠÒ»î}±é4¹`÷—R} /ªÏ§L™¢£AüSÃl|m¦"x/Ÿúç1Ó_õËk‘?Äذašè£Ò=þFYœ;ñpóœSy\òcÍ¢µŒÑ­Öþÿ8­øOe3„ä#Ø®÷ݽ äÄêcrrþ‰åãd|yƒ|Ú¶Ö÷ת(^¤÷ÐrdJUýH=#ÒGÄ1J7Ú[Ÿê×¢ÒkþS}ÀO}}½ :T«òG»_&¢õL?] (N4bíÚµo¨Ÿi§8Ûõ/Ñd]ài Þt]u„”{vÎÖh›¼¨:Ù>Köt7ùþaLï™ûN–ʨ»H]ŸÌ‡¶3£Â3¦öÓ;†ú Ò0hD¥?RÿȰ$Vú»õl³èê©§žéþÅßwci 8[:·É£Jˆÿ­ö‚¬Ÿk{×Nyfç‹òÌ®5àwJcýä³ÍÇ©é}“\=Bñð£Šß­è„­8/ÓçÃÇõ©~*ZÖÖÒqõÝüôuÿLŠz& &šýUÆà“yóæ­–¾ƒ|9ö—€ðȶÙrFÍg¥®tDV¾ÿÚö òøö§enãÒ⚌Um}gï;U›ÛïFø±æ áOÔÃ>sçÃú>†û@ôQì!EEb¥?Úþ²-ê鮳^Îmú¬¶îïôð£Â€|vMËîÝ»5чø#òÇÀ˜.´P"ë2räÈ”~6/ gµéšcШÿ¼&}ÿÄÄyÿ¿ä:ú§ $Àìîn”¶=)ßù-ÇiuÈ_w½*3v<#;ºvòçF‘ßYj½ßém¢3}6Ä7hÏ Ûä®[·NµÂ?| *ü!üuuuZ ÓÑz¶ *ÿ1ªØˆ… þUÍþG_ ÝÚ¿oÆþÒ2fîxVÛ°g\Yƒå×ííÙ'Oí|Afí|Nš{ZûóÓ6UNß{‚㨟õ3µŸóáó¨ð‡h"j^¿~½öõXï‡ècCŸäÖÊL‰z6 Uô¯2÷ßÿ_{£ÿÄÁ?F™«ŠOÇþÒ2¢*•ËÆ»å¦‰¿7œÒ·­k‡fžÝõŠ6M0È`¨Úüœ€5~DœN+Ì™ÚOý¹éú Òó8Ðæ7qâDmŠýð{p»›_. ÖþÍ¢ÕÍðšb´GÌçþ[Uþç,Ú§ $„,jY¦õ¼¦m¬³¦}½ÌØþŒ¼ªZù¢iå³sü±{Ÿ°¡ Ö›[ûü&¾aYv@¤Œ6?¬÷c²&ý¡ÍODþÉc}ýRàgjÌ¢õ}bO>ù¤>øÇ*ýïfßœM¤ $ܱyºœ\}¬lìØ¸V>;ŽlìXüQaŽÃ.]æÔ¾WÏ £q!þØØgõêÕÚ¸\,·`ºf+ ãÄ„å¢ÀÏêqØòó ŒPS ?˜?>fw‹» 섟BHjìëi–‹–þ—¶Ö&ÆuÔËÔX_' Ò<±ÈŒ|öžzãQéñ×{üa¼Pð‡áJ¨½ÀãݦýsmöGà 5øÇ(úw3PüýÓ"Â&þµ]C弯Ï;ÚÐHüÃ*¾¹~nHTøCôa° €K´÷á-¢ÿL‰³×†kÿfÑ¿jo\5sæÌ…Ò·ï?*ûK@ ¥ñ~r^Óé¶;ùá¦ñdž2Lígÿ¹a#é‹´?"f¬ó#êGôo6Ó?[† “FÂoý¿õÖ[úØßn±ßö7&>üC@ñ7êVø¥ÆÓ¤´ÒQäñgŸÝç¡Ç,Túëm~h³D±ŸÞæ—XéïE´žéÌÄß,úWõÛ§OŸþ–ôÝò×nýßé f!œØ:MÆtÖÙ~Öœ“ÅŸ©ýÌ?7¤ø‘êGÔA?hóƒØO˜0ADþÉ•þ¹öTg·öÿÁÌQû´‰³µ·ci!sýOi>ÚöëPm•‡ëü+V¬ÐŠý0ác~Ñf‰?XëG»¥Ù„Å Tþ£ýÏ%ü{ï¹çž—“¢ÿDá·ÛøGüjh!¾ @ý;kï©Ú[+Ðg>|øpFðY>ÚúöÇF>z›2.ìƒÑ¾X~I¬ôw+Î~1~«ècÕÒ*l»Åýè_ßDû4„ßrBË2¬gõ K¥šQiž©>㯅 b´/ÄéÿöövMð±‹Zü¬:.üXàgõ8«ÊeÚÕØßçäб¿v)»1À9þi!¾ ¦§ZNl>ÊòkpS‡ø˜­7ûM|ýüܬ¾ÇæÍ›µJˆ>züa üȺ åJ·Ï×Ë(ßÍcýcYà µ¥ñ˪àq·šþ·kô…ÀÓB|Ï™jØ]Ë_MM”——3‚ÏÒùðxô÷£Ê_oóÃǰÞ6?˜€ÒÒÒœ {6 ÕŽêãÝ>ø`òà§|9ø‡€â+êºjetç˯ð¸)ú£1p÷µˆ„‘êW[ÜjéÌõG¦E/ö³ªôª!@wÚÍPfèoK—.Ý*ÿ¤2ö××u4„Ü¡n‹§ï³ÞÞ7v¤Ÿý"¾~àS=Ÿªr×*ý‘ò×ÛüPh™Xé™þnŸŸß Öþ““øížx≧¢»-Í Å¯Ñ? !$§Lé'C»­ ÿúÇö¾Œà3"~DþXçGú3þ±ÆñG¥?ŽÄs­ÀÏìq0=¦UwÕ俵âlì¯]€]„Ò熬þlÓó}ågË3µŸ¹¯Eú•þC´ûaw?}ªŸ]¥®¢üLÓ.úöÙgg‰³-3ö—€â&¶7È€h˯IŽ@s%û9‚Oõ|Hó£Ú?±Ò_oóCÊ¿²²2¥ˆ=†C0ÓÀâÚ|ôüóÏ/“CÇþZ˜8üà !$¿9¾õËÏ£âSçÁgî¹ÌñG¡DiTÁ£Èó þ‰•þ¹ölTþ[Dÿ¢¢ÿ'åÐÊÿ¨‰ p’òç€O‰ !ÄsPõ?¬Ûºªßh[Ù ‹o®Ÿ†Ý ÕßÜܬ¾E¥?Šûôõþºº:mÉÅ­Èú¹00ù±XæÀÏo†*‚üä™gžYœý;ÝøÇ÷ci!¾àØÖ©–ŸGäH”©ýÌ<7¬ó#Õô7„b }Ðã?räÈ•þ~ŠÖ3ù8<]VÌ™3çqٿ寛Mìªÿ}K¾€@Ìg&$ÌTE+¤¡s”éçq3·‹þ™Úwþ=õ"ò‡øc¸†ü`yE³Ë ø™=Uÿ¸f¨¥… Ñ¿Ýà«~_ŽýÍGˆ4 !ùÄámµ«èÛ͆A|sýÜÐÖ‡J2(ú«®®>öwRéC€:d=¬xî¹çfDÿ‰GTÌûþ©+¬ „xúwxûË/ÁŽs?m ‚àa¦?Ö¼‘À´?½Ò¨ôÏ…°çÂ`¼±Ùv¿½Ñÿ¢Ù³g/ç3ÿ¬ûû~O€¢ü¹í«=ƒ02¦k”ôVš~‘?¦Ð1‚Oý|xãÆZ¥?ÒÞ¨ôÇÇôüÌ*ýD6H~fÃÈ_« €jûKŒþízÿÍ–Xæc €‘) „xÀäöq)EÿLí;û¨ôGÊ© »A ±Ò‘¿ÓJÿ\Eë™~2!fþe”Ïš5+9ú7kù ä¦?ùf¬Ä…€„ä€Âx¡Œë¨3ÿ|aá´t®…:#7!Ÿ*ýí£èoݺuZÔ«Wúc#%ˆ?Ì€¢u¯ ÝÐÐ[ùßžý›õý»Ùù€Ä@ìÍŽ(oË„xzÿûÅÍgúc=nîLí»ÿZ÷¡Â_Ÿì‡ÿ¨ô×·òÅÚ¿ŸÄÙ«sÚŒüÅ4ÄTôÿ‰Aôš-óÅ$‹¿]äíu{„˜Ô1Æòó0Aß\?7´õ!íßÖÖv ×K)cÇŽÕÄ•þ~ßÉ/çÄuA6Äê¡jÇ¿Gåе³â¿@nù›O«,€þ~,Á´Ï;vÖ)ê-zŽŠ{\“„£ áˆ$b`8"BH~1x?ñmâßI‘*î+¿ô‘oüFý¥Vøa·?/Zÿ2rƒñ‘1@u; þ v¨ôG €^é·‰¦*HéûäǺ}œ“¶?•1ùÛ+¯¼²ÒEôÈ-ó͘ â¡ÿ"ñ‹oé}[”p81 ?ÉcÑ·~ýÀßMñ™gž9^ |YªÑ˜#øTÏ…?TúãÀt?ÐÐР ?Öû­*ýƒfÜ>Æ™¡ B÷ôéÓýwf úlAy €UÊ?ñsV&¿äný5‘ð±¢ñ/L¸‘YehH>Gþf⿟¢ã?~²Õ7u[ü—ÏÆÑ-ŠüPÜ€ÍmPÜ7nÜ8-åñ/**: ša-ð3{Úþ°Õ±K–,yaÁ‚› @ÞEÿaÊ™3—fôKš<¾ ÷ó 74a€Pü‰Lÿ:µ}˜Ù7E¥ºQk÷8ô|fƒb?ù¡âí~X>A±*ýý£›"—âœkC`·ÛŸ2mwÞyçL1Þñ/o¢ÿ0'f –tcJ~³¯OŽþ n~B#@húAÂßOL­GWªÙþ¦ýýËq¿ö Â¢ñÇz?ŠþpíÐæ‡B?ôùûQœ“›M#kƒÃ ù?­2(;Åxê_&¢€‹Ü"  hÂ[3ñOŒþ¹þO(ü}E_’„?Ñèf¹H­ÿO²ú;ˆù]|sýÜ0Εþz±25552fÌ-òÇûA™à—­Ì–FÐögc¢vß|óÍODÿVÃÜFÿœè#C`$þ—â_ Ækÿv±·ÊEþÉêx³oˆµëÄêÿ¬ÜÞQ€>XëÇ[˜6ÿÐ9ñÆSO=…‘¿Å?ôÑX €YÕÄà3ýäåDá/0¹ñ1ú'ùý‹þ%Fÿzv ®DËtû?ˆXrû_¾ûÅ_DüèñÇX_ ³Á?Úü0ÞÑ¿™ø%ZÏäc1ùЮðmùË_¦KßÂ?£Vp'3ÿCý‡1(þf¿œXÒÍ,Yücâ|ÝŸ€ä›0[û×—Ñô¯ÓÞWûÏ7˜}cLªãšÿÁï¶>}?´ûAÜñc¦?Úüô­’ó±ÀÏ챘‚ˆŒ‰ï¾ûîÌ•+Wnç}ÿyý‡ÉØM42‰¢OzkÔæDÑ'ù"ôfŸ3öShðõÚߘ®ÑfßÔ¬ú?÷hllÔŠüÍêc}õJDýV“óÕ`.Ú"­PŸß¬Úþ戻¡?1 ÑŽù–A·Ê$ÞÐâ&ÂO@òÙØ ý1ÿ¸êï/T3þMa];L|ªçƒè£ÚˆŸÃLŒõE›2%n¿&DÖïFÂ.õ/Sëþ÷*£ ï÷Ò#îZþb‚ÿòÅ­û›™€¸X§ùüÑ|2FÅÉéP}¶†f >ûÙÏŽRëÕÅV Ÿ×üñ9ìä‡k0ÞÃ~0ÆëýHý£Ò3ýígúœ0Jv=ÿj9eþŒ3>㿘˜ÿYeBý‡1àÆ™qõÓ|3‰™²‚¤¯Ñ#ÿŸ4i’iôoT˜iñõƒ‰0ëûXïG{ŠýPü‡%Œõ­®®¶¬ôÏwCà$õ¯ê:î¸ãþµ‹qáŸQ&À*ò]ôF`g̾6î ê§à“|~#P`ùG’n¤%b¦ QüómÜ/*û!þˆbùà `2"ˆ?Öüñ}Ü>ÿ|0÷»cÇ»žyï½÷ž\¼xñf1Ný;]q^@`g¬>O@húŠÉ¡Ó6ù*=Êì›;Yÿ£1@ôŠ6?}ÍŸÓ+ý!þ¨ôOü¾¬øï 2&0PV¨¯YuÍ5×`Þ?RÿÝ)Š wùËw`f$IÜ“72%Úô!Ÿü7’ü·“¾iÿägDŽt’ÈêMÀGèíG¥?„`_Jµ[¢e¥¦EÖÏFÂì¹vvvjÝV¨lJ×í·ß~«zÛ*wû3úc7õ/ÔÑØ €‘ 03bõÇý“<#n`’_ÿ‰¢ot3Ô– Êˡ95a÷«o胔?Œ@b¥?Rþz¥˜¢õL>ÎaÕ¿ÌŸ?ÿ‰wÞygX§þýåEyrC‹8¼Ñ™EDŒþ 1ΉD¥²U–¿¤ÆôÆSäìÖc°yófM¼0ÖÃ~ð³c¦?Rÿ0FÙVü÷Rÿ«¯¿þz=õß%é¥þCýç‹°‹äíÖú)þ$Þ.Sfõw9ú裇ʡ3\¿ƒTž Öôt?ÄëôJµI’Öãït¬o>Ìù·«úGêÿÎ;ï¼U™·©£ €F0B#@Á'ùÑýXÔšQ ŠÚ†›žLÝØÑï”>•ç†õõë×k[ùb¬/¯ÏôWµÚš¿^éïרÛ†¦ Ýv êÿ­·ÞZ-ÖÿÌ6û‰IÈGþÒ˜ÿ¹¾Oò³,XÜ$`e$´C¥¶‡š}Ä?Ìkþ¨ô‡øcÈÏ–-[´!Ý?fÌ­Ò‡Ñ÷Ïç?³¯ƒø£MÒ ¤þ¯¾úêÙr°ê¿GÌÿDŠ^„E¼÷þ‚i H¾ÿMD\DüÉ;œÒúÐ÷@ªÂV?þ#F`S$Í À?gC±$Ì”j™¥ç¾ûî»#¡êßMôïtÚ_hÍ €sS@H‰80Nßgn€Zë®2{€›ílsÁ§úÜУñW;ÏiÅ~‰•þØÍ•þ~Y¿'-@Uü?6oÞ¼•²?õo%üQaá !ÄÔ즪„Éû(Ðßì‹õõÿ°¬ùãkQè‡jŒõEµº^éÁ>hó³{LCÐ÷k‘ú·›ö§–W]{íµ‰ì¢«ô^4„·Q¿.ö“ÿG¬ €hiTúCøÑãb?¬W'Vú#ò7*xt*–aYÏwsN,Ømô£2Í7Üpƒ>ðG/üK§ï?o ÿh!™ÂÐ¨Ž–‚<î"áGÁÚý@b¥?ÖüõÇçûz¾ÓÇ¢å»"Ú}ùìÙ³o[¾|9*,“×ýͶü52yYøG@IUìEÌwÇ<°O€JyW:1^‹}¦ŒÒü~ô÷cH @ªôèÑšø#ú·KsÓj¨ôkiÅ¢E‹þúÐCÍëYÿVÑ^þÑBÒ5fFêQ £E€ÙˆàSýÚ––Mü±Þ¯G«¨ôÇ559¥óç³!pºËZþþøÇ?>(û·ù5kù3[û;0y•   „¤› 8d+mµà8¤™MMMZ‹Ä•êøYÐßÁ>½Ò?(Q·_ž+"»uÿŽŽŽæë®»îeÀ0ÐiêŸ=ÿ4„¯ ª€/TGZK~4)ˆ¿>Ö•ýXïGºÀÉxã|/ð3ýþh›´û¶O<ñÄ­ .Ü(Ίþ£3ñ·~vBH’À›e|LÂ¡ç­ ]àc€ô4&ú¡Ðÿ/++ÓÄE(öÓ§æC´žÉçŠA?0v¨Q¿3üñ÷äЖ?3#à¦÷?/£BHºf y@DÁ¹¾¯øu&"}½ÅO니=þXëO¬ô÷«ÈúÕèEvëþªÍòcµî?Cö¯ûwÙDÿÉUÿN¶úçcôO@q"ö‡ŠŠŠ’L<—Ækü˜ì‡õ~}¬/¦úÕ××k‘?Œ@£n?<ó0ìÙ+T‘åÖßþö·7'úMŒþS­üÏë@4„¬dTdœÒ}ÅOû )ÿ+VhUÿÂ-|!üˆþYà—Úãð9DþÈ®X¡2m7ß|óu*ó‚Þ@¬û'¶üY™€äÂ?¦þi!YÊôùœš„—ÑûŠ×3P鯷ù©Ês­f)¤û!þÉ•þF¢Ç?óÇ!›‚ìŠ*3›1cÆ-óçÏÇ¿‰ýþV•ÿnÖü%ߣBH¦ AD d±ñ“1€8­[·î@¥?ÆúêÅ~ØÆWµ7æU´žéÇÂ\9¨ø—·ÞzëQŠþŒúýíÖÿ¶ûåu !$ã(‘Lù¾’«}ô }ùë•þ}Dþ¨øGb¥¿ŸEÖ¯†Àá˜_d^^¿æškžã¢?3gÛý2õO@ÉVF ÓKÙŠöu ö(öK¬ôÇ&>ØÊâ´¿Yë" ³Ç¢ÝÛ%Û±uëÖEW^yåêÝ6—âû¢?³h?oÍ !$%¡7û¿ËB7‚â•Ø}­¾¡ÏÊ•+Túc¤omm­V臹þ\ÏOïq¨£p"þjy`ÃÏþóë1ñOý¹£èßJèYH!™BµlÅrýœD¥‰•þˆò±™¦ú©VFíÈÇh=“çĦI;Ó§Dïÿ*Tk \X‡CñO¥å©BH¶PÞ=6!k¢îô{`-ëýˆü¡b¬ï„ 4ÑGÊÅAY¿}Ð]¯?Úýn»í¶«?ùä£1¿NÚýìÖýÍ¢ý¼74„tˆDsÝn„%]±wk P‰Žõ~½Òëü´÷¡Ò3ý½ØÉ/̆À©ø+3ØýàƒÞ0wîÜårhÅ8Ÿùï6êg&€€’IñªÍ«ËêAv¢-c€ÿcËY´ùáÀó€à;V‹øñ~b± üR{¬SñWŸÎœ9óÖY³f-ƒÿf©ÿd#`ý' }Þ·üÑB²M\€žt3™6#5S^~ýaÆI]]–þ‡øÛ‰ üì ñG1¥“õÕW§?ðÀoJßv¿ä ~ìRÿqáº? !ÄìÛ·/#€L­ù#Íñ×+ýñ=1Ösý‘öG¿*çã(ྠà×׉ÁSƒ~Wc~Ÿ—CÛýìvùsjÌ¢}šBH¶PvÝ™0™0(ðCÄ¿|ùr­Òëûîƒö>´ùá’Èúõ¹b´occ£#ñÿý÷g_uÕU3Å<íof’ßí Š? !$‹ÄÕþîݽ7ÛHº 5>ü ÍFëüz± €U¥? ósb´¯ú;úúÅ‹¿¤v÷{´7òïã‚?»èßÌ$ =×ýi!^‰¿þŽªîîT£s wͱÛ.Æ‚¤·ùá|Hóc¦?fùCüõJÿ GÝ~x®0YNÆû‚¥K—¾|ÅWÜ£Þ5ÛÚ×éö¾õK@ñ‹à'\‰n›™Hu€SáB:æùãÀÿ±Ö5ûAüÆú²ÀÏÝsÅÿU­‡£}€j¹|SøMÿ.›è?Õâ?£×%Í !Ä#Çp•b˜ àtK Û·oׄ©€*Tûëâïר;H™üþ0KENX¶lÙ<ùß©×"Güµ÷ ¿“ˆŸE4„ŸdZ­„bm¶ÁN*Æi~läñÇ®~øÞèïÇ.~Xë7ëËõ|÷C›ŠýœÖq,\¸ð5ßÿ>Ù¿æŸ8ßß*âwýÇ„E4„ÿ™%­vQdº@èj9l#«ÍÇ:ÿĉµb?LùÃô¨ÛÏ×µç8ÄçÏŸ?óøÃ ‡âŸJÚ?YèYôG@É5*=Übg–O%ÚO{Ì#ò‡ø£ Å~hóÃ÷FÔ3m¡ Rf!•窯÷£“Âé)ÔŸn¼ñÆç\ˆ¿“´¿QÔÏ¢?Bˆ—¾A´•øÿ˜ Ë @&: JˆüQéý( ¢Š5#€Jÿ|Ö3õ8¤ü±Þï4åÙþÏ>ûì]ŠyrpÈ“ùþN6ûaÑ !ÄçÆK–‹ëoÞ›À[LœCÁ"£1B;tñ·Z^ !°Þ"»â´Ê(ÖtÏ=÷Üô /,–C‡ü¸í÷§øÓB‚h”p4eÚèÂáÇÝüð ÷Á,]üÝŽ¦!8ôwƒìŠ›n Õz¹öÿ÷o\²d 6Zègm~FóþÝTýSüi!9Žø“‰©b±ÝVLe ‚áÇŽ~¬óc¸Æùb­Å~º°±ÀÏýãæÇ`kýjƒ¥÷ñ‹_ÜÖ„µ‚ýâï$ê7«Iq›×"¡ „x,ø’•ÅUŠ~O& ÒüzäýPàñÇ:?ªýqx!²a+ðÓƒ ¤üÝìÔ¨ CÚÔçÉk®¹æi9Xì×#Ƴý­ÄßIÑ_ÜàuFñ§ „øÀ$¾© xvÛEóNg@œõ£¿Æ RSS£õøCàõ#ú×…‹ëù·ϣµÂïvƒ&Õq±ýþûï¿ýÅ_\"SþÝ¢µÿÄ·f›ü˜‰?¡ „dYÜ#&7̨Êü]vßkÍvò µ£}!þØÕ…~µµµšq@ê_¯ô÷«ÈúÕ £‚¿T–bV¯^=_õ÷ß½sçÎF1NùGm"~#ñONùÇŠ?Í !$¦@LnÐq©·ª¨²S µ©ÂC„¬ –”1u›ú ê)LöC±ÄßIö€† /ˆø!ü©ìÇ ~_­sæÌ¹ÿ¾ûî{S¬·ò5û¿•ø;™òGñ§ „äHôͲFo1  Q õp+`&h*ºÔ Òò‡˜É©Š? !Äg‚q)øÉ)[-ÂS©û­V'Â:4D ‘= âAüñ9RÔ àÿ\Ï7fJ?RöuÔVÊ ~øáÇß|óÍÕ½Âß%Öã{FývBˆOÍ€þ³­WoÞ1U¸·Íî~ žA¥?„K‰Vè‡V?½Íëþ~Žºsé#S‚#¢TÁå†Y³f=>{öìåÐi~fsûÍD¿'AôôúSüi!4 É7gí&¯Öð79µ0jÉà@…?Rþfâo'–AZÏwúXÔGè¢ÌI&D¨VËj÷¾Y¨îW3áwbœÌô·šðGñ§ „Pø“·D?øàƒMßùÎw,¿‰.þÈôïß_[ë‡èCü+ýƒ­§j^ øz]ðS­à7CkÞª&ù½pï½÷þ­w÷ÆÄa>f‡[á·Zï§øÓBBbú˜•ÎoQâÕ¬Öï«ìÄëü¾Dñr´îöqøZ½&B›©?U›±éí·ß~ùÎ;ï|]«Ý¡ðÛmÝk¶ÖoõSüi!ŽünÖúÍ>ªzÏ·©ú, @¢0BüЯŽ%€Ä_c4ø'h†"yüœºèëc‘³ý{S†lѼyó^™1cÖø; „?æÂX rÔïd;_Š? !ħ¢¯i°:¢ª|‡2\,A“ÑÍ€nô÷Í ‚׆@ùd±Ç[ÙŠêÍP©ýæåË—¿£Šû^]°`Áfé»aO, ñ¥õSüi!4‹¬@⡉€*òÛ„ùý™ÂI¤œh ÿ¯ˆD·údqO|« º~‰œü’TÿÖ­[—«Œ·zè¡ù*£’<À'f¹Û‰½UÄïDøjG(þ4„€eì {ÔT¿µS§NõZ}!Ä^ƒÁK‹/~gæÌ™o¬X±b§:µ/Y¬í €ð[¥ûÍ ý(þ4„€DúNf¦ÿq¨ôó§gžy&¯h–~OjÖ†O?ýôcµ-ïü÷ß)þné;±Ï(B7~«%³ïc'üN·ó¥øç€/!ÄæÞI: ŽÂÞ£(á(î=ÊTEõƒ>øˆè3‚—4}TWEç–-[–/[¶ì“^xaÁªU«öÈ¡ó˜­É[e¬Öõí"~'é~Š? !$ âÀàm L€:*Ž9æ˜úÓO?ýØúúúÃKX‚P+NŒÔÕXÞNõ6® ðÚ•¨koÕ.†8ÚÔN|Úû*šoV#v›Ô|ý}*}ߨÚ÷*¡oRkø=6ÑyÜ&²6}7Ñ¿]V nó¼ì*û™ò§ „„܈X/Õ$‹~âÛ‚$`$üN10 f_“ü«ŸÙLÄŒö>°q}z‘Ñ[»iŠfÑ¿YzÞ­ ˆ;ˆöcb¾çƒðSü} çBœ`40Y$"IïG“7ùq…½_ëÔˆ‰€[}˜|}º×ÂÊ$~,fò9'‡Sñwc쾇“ç%BH~Š~¢°™€Ä#j"’1ñ/0È2ˆK3 6ï§c¬RÛv†À‰ 0‹¾Ý.8z ? !„¤ '§»ÍÐ…Èmôï$•ïÔ dÃ8Í ¤ý»1F-{©Š¾Sá§øÓBB˜0,&Âo¶s`AÂ×§³öo—pbÜ·‘¿ø‹MäoUWàÔ¤"øN«úõÓBHÁˆ™|>Ñ87…|nÅ?’Ÿ5Uñw’ ˆ‰»e7n¢|Fý4„ ¼m@„=f"þqáwý›™€t²V·‹tÍ2é.¸É¤áSø !$mCàÆÄ\FýÙŽþs±i3ŽàÛ‰=…?Äp!$•û…U+ž™°»}§Q¿W~1"™| ?ÿ  !ÄõýÂÎDl„¾ h?Õ´ÄÅÏçTSépcÄÅÇí„>Õú(ü4„Þ3›;Sà¦Âßíz6ZÓÉX s<…ÿ»‰îÓÕKñ§ „Ç&À©É|¤Ÿ©Ö¿l™§ÙtDž¢Oh!žšgc{~>U±wõ§[`%°™4©<…ŸÐBrj2!îN¾¯Óç•iŠ»s'Ÿs"òñ6B@!Žï!nÛM$ï4ÂÏFÚ?ÝŒ@:Q{ª‘}<ÅŸÐBHZ÷‘TÛm4Ÿ­h?S&Àîÿ©~Îé¹)ú„€â #à4Bwŧígº0QΤ¸Sô !Ä÷÷7‚J4ÉÀsLWLã9ú8EŸÐBqo‰dùó^ÝãÒÀ3Y GÑ'4„@Þg"YøžÙ¸ßųôõqž !…¼„~ Vâ|,!ÌBByÿñË=-îÓïE !„÷%ŸA¡'üC#„߯(ô„P„²{ÅB!„B!„B!„B!„xÊÿ½Œ£ŒXçIEND®B`‚qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32.png000066400000000000000000000025361347155106100303040ustar00rootroot00000000000000‰PNG  IHDR D¤ŠÆ¸PLTE7­E6§C6§C6©D––– ¢¢¢–––NNN«««­­­ÌÌÌzzz ‡‡‡ÑÑÑ...¢¢¢OOO§§§¤¤¤ÈÈÈUUU²²²‘‘‘²²²ªªª¬¬¬¥¥¥"""ššš­­­ppp 888bbbfffjjj]]]///AÍRFÎWHÏX}݉ß÷âÿÿÿéùë”ãžnÙ{ýþýêúì©è°¢æªÝöàŒá–ÅðÊþÿþaÕoKÐ[òüóãøæèùê¼íÂHÏYBÍSûþûÇð̧è¯[Ôj³ëºûþüùýúCÎTÆðË¥ç­öý÷ïûñìúîÚõݺíÀOÑ_ðûñÏòÔmÙzTÒdóüôÙõÜíúïUÉc—ÜÉÉÉ€ÞŒñûò™ä¢â™ãøåƒÞŽÐóÔÉñÍÀîÅFÍVhÅs¦ÅªØÙØÞÞÞÙÙÙ“ãïûðÓó×h×uÒñÖÞåßÈÐÉÇÌÈãããñññÝÝÝëëëTÒcÎòÒh×vKË[†ÂŽÂÈÃÜÜÜéééìììïïïÔÔÔÚÚÚbÖpüþü_ÇlÁÆÁßßßæææèèèÑÑÑäääWÓfKËZ¿Ã¿àààâââåååçççÍÍÍØØØÒÒÒxÁÕÕÕáááÈÈÈÖÖÖÛÛÛÃÃÃ×××½½½ÏÏÏÓÓÓ¼¼¼ËËËÌÌÌÎÎι¹¹ÆÆÆÇÇǺºº¾¾¾¿¿¿»•ľftRNS —œ)2 ›4 $ .372?(—auØß#þ…!ñ?«-þXÐ5qÚ:>QVWZfßþw&(/Fì¿9éäL,ÜÝY%ÀíŸL+M‡–›ŽkL#6"(wäïIDATÕÁMKqÇñïoþÿÿÎÌÎn©(nùPƒ°ƒ!Ö±‡S"BèÔ¨K/ êЩSï k—.£§‹‚K ‹Ž™ëª³»ÓÌú\½>þ¢Cþ”z XrNÔ6 "ã•[ö:{¢8µ€+&á4ÿ`ðÀ…I4Í¿xXhu•©ÍAV`Ñ1M’3V›àHØcÁ¹@¹#«b¡åÈùRLOA¤Ô¶ÈZ1,›Ÿýœ££ ϲ£¢ò/Àá*R›™àG%ðØ¬ød|ê5çj5r^%²;õƒc›Íxìró£p¦0\¥´p’ÌØY{ÛË®pBú0Åæñåî<0UË®÷—õ.¼€Ò%åÖ#y5¨Ì)ró‹æüÌ•ê5[ÙÜ5æ“ǾïÏ>GSs7J¥F5Š ËÆ˜¦4Ùó8˜ ã`( ‡ŠÎÍâãdߣ0 6‚-ß÷{K7½¤Þrc¾$:$=ô¿®o:Ã-©º”Xh..÷ž¦C™p±>¡zTH}½ÛjbIYêJgéèŠËã­¾Rx4¾gçë)R☜e­ïœV¤ÕÙ©ûîMy­ HÙ– †Õ°DðòUA#síÄAêN'ÕñmDOã0²Ùó14¯»K}Ïg)™ßù>…ú^„Z°IEND®B`‚qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_32x32@2x.png000066400000000000000000000045671347155106100306640ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ >IDATxÚí[ PT×¥¨ic Ä’4ŽN&¶Ó1mCÆ8±Ú¦‰budb@ BÒVƫѶ”1±hŠ:iLkJ@ ­5‡—ÊK°‚€ò~¿ßï÷à ¿ç»sÎν¸À¢‹²3û;ß,³{îÝó}ÿãüçìu΃Ì`3˜Á f0ƒÌ`ÓÞŒT & sg10?c]“Ç MždXÌð4Ã3 ?˜EÀœ¬ÌÌt)¼>79tß«YoÒl›ë÷æñ¨Õ ùgV½ ä¹?âó6Òù³úBž ð"Ç@oÉs^bxâA0Ögò+€1¯ zKþaÀj±2øõ3òÅë²·ÒÞ²èhÍIòi8G'ëÏÐGÕŸ’Kñûz!‹á¹é~áy¿¥ðöhº;:HYçp—$ Dšè>(;H§Ï«ñ8XÀðÂt¾l{á.‰œ¶–ÙŸG69ïØ¬û«,»G..²žNÈ×6(&Ýï%t'Ó[B(¸õ¥õfÒðذb ¢E^˶,¼¤í}Z篘prO:mÊuºoœsáï©n°Q=ndl„Þ.Ü=¥“¥Ë¬ äërõdÛ¾é  9ŽŽE!cÿ„6¥þLä<ÒCnM5a]ö¶Ù#€}¾‹‚ÐÍAS^“w§H=¾l Rý¾¶¶!ç­Ù#€GÅGŠÉ¡‚Ou<ÄQDŽkkë³fXÒäf›÷Δנ'›« xÿËÖ0 wJŸ‹÷]Hm‹â#U^ØÐèVC”Èmwé_&-‚£ÐZ€Ð¶HõD{îõi51÷’ ‚,÷Ò_®tÄ©'Ú5Ü£ÕÄvïSô¬ôÖ_BdðÍèð¥À¾²õW€ -¡ŠÉNÔÞÊq°ò˜â¤Ä `,ãfÌ7{*­g“µÏwòšc5Ÿi\fP'ŽÓâù666–ëtÔümÒŠ® gYg' MÔøÆFÇ›¡ïpâ8ßøž»»ûÏÃÂÂÒÝÜÜ^ЉîŠÉ¢/˜êšÔÞ õø†¡æIšNç§A€• c|33³gOœ8áuùòå___~œ¯›½€|'X>P5©Çpf€b),²#þ¾1ŸÕ(p—"Ó` Î5öìÙã”IÌû]K—.ý{ÿ) ðŸæ‹Š cûûº†ܷܿ)³/W1ö½RÏ)Ûë¤î›t¨êcòªþ„>®õÑZkkkÿȸ¸¸Ñ«W¯8tèÐiÆíÇ<5t#€mî;Ô?rG1馡 k"߆/ètÓyŠéL ¾{ýŠ1×{R5ÞocÎvd]åÄ›!ÇÉÓ2ÝŽ&ž Fü^QQ¥¤¤Pvv6…„„ôZXXlàáoª3€ýå•Zam­èë2gÿ¨÷Wì2åf—¿ã¾ñ6™´;åÏt&î]¿~***¨­­¨±±‘ÒÓÓÉÓÓ3']Üû* ü®h¯TàFÇF§`·†Ð×tvpŽm€P'"ÚcèTã¿É«êïê¢Ò裂^ûœ¢b£)33“¨¯¯êêê(::Z`¹ßϼ¿Qæ}# O‰«ŽKÅ Kš›ø¿X¿ ¦t â–·7nÿ†ö&{ÒÉx_ŠŒ”<[]]M===q ¤¤„óÔÝÝM………tøðዌÓOù»ª@› ÇåZ¸¦½K‡“ŽÓùØ/)))IÊg{{{ÕäHŽŽêêê’Æ01†—/_nÏ8=ËO¼tz$¦-óò“ã‘Ú:Aç¸>syüÏ‹‘¾@×®]£¬¬,ª­­¥ÖÖV)¤AP ¼b—šš*}ÞÞÞ.¡¬¬ŒØúC^†ESyFRq·Zcçø^²…Æ…ÑíÛ·©ªªJÊ릦&jnn¦––5A/C„ØØX)2ð9¡€ÄÄıµk׺2>KµñþŒ \l»,­õšj€wâ'˜4•——KG1ƒ¨äAƒˆˆqéÒ%Âr‡1bÄB-ðóóËu„sg…áý%òXÂã555’õõõŠ(i€Ï"""¤ñbœ  lÙ²åºAþcñt¶Ã/>Jò2Þ¢ð˜*..¦ÊÊJ)ô!Àø(iï òB,ùxÜ‡íø Wð;§¶Þ—ÿ4¶âQ °?ùJNN–B¤ ˆ Bð¬oĘ˜i,Ä‚‰kðŠÈÑÑÑ“ñx~:Þ˜ò%c-Æm 3„í î>>>ʹ¹RÕ† %< Dh£Ò#MJKK¥±€M\‡¥ðÔ©SYÜû–Ó}NH<÷âê9®âLà‡ ?111ÙÈÂù.ÂZ^QÄÇÇÓ7¤ð0€B訨VùwN7÷5‰0/f3€ùüùÅ«W¯¶e5áQx½rå ¥¥¥QAAtwËA£täÈ‘~b>Ü×$ÂLÁXvDeîää´a “" ð^xx8eddR$//OB~~¾¹ h‹«LMM×óÖés‚3ñÄ)'-wíÚµž^Q€bǶ°RNão4:@NNŽ$†\Ú¿jÕ*7þxÜ·µéú·A€§vîܹ  رã+©9B1ä‚` K‘¡M›6y°ûýŒ‡þ¼ÙN^`éââ²ý¾b°B&å<¸uë–„ñ‚ܼyB ;;;åßb^·ŒçèAs[[['ôòäQ ‡Í 1ä‚ào¬õÁÁÁ]›7o>È¯Z"ïôE€ï.Y²äUæñ1°ÔhŒ!^ÑÞb9d!?ìíígeeåÈ+¾_YTúB^<ˆ~c«Þ,”GpŠ ÓCTøï±Õ`r{xx|µlÙ²ìº_ò‚gÁ=¯Wäå]'B÷•… ne=Á{{ûã®®®¾¬8ú³úð¹Ý±5kÖüI¥Rmeã~ͰšŸì>Í«ý<} {MÏ#/à¶£;\Á/PÐ^æ¯Öüýçùúnɉ›ê£×'ë:pb‹øþÝœ¿.âï/à¤çʈë5ùñBsbâ¿ä˜È~ÉUÉÂ\'¤ÿ¤›h”ÀƒAIEND®B`‚qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512.png000066400000000000000000000645501347155106100304560ustar00rootroot00000000000000‰PNG  IHDRôxÔúi/IDATxÚíx\å•þϨYÕ²Üe[²Ü ˜^B ”dI²v—ì&dÙH²d—ä¿!Mo”¥‡P–j:Û€PmÍ4î6î½K¶z™™ÿ÷^ëÚ£ñ­SîÜ{çýù¹dI£;ºÝ÷=ç;ç|"„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„Øá%àï›Bò€8/¿[B!yo (ü}BÉC3@ÁÈŸß!ׄŠ<E!~wþî !ü”?z#@×ï-’æ×BH>ˆÜá׆ÚPÂ)ü‘M!„„ÝXý?žO&€BìßU$÷ù „äSôo$ôq‡F ”&€7ÿð¿ÕÇ"³„æ¨ßéÛ¼0¼ùWü“E=ùã½G¤÷­ÓŒ_#„ FøN#~ýýXÂáÄ„Îðælñ˜¼Á/VG‰:ú%˜§€¯ BH€•øÇ{E¿[êèêý²A½ (âë'âoíG’>VØ+þ'?}Î¥£*.åå$„C™wì¬a½âßc`"IoïÁ¡04ÁÿˆPÔ+þå'Ï>ûçJüÀËI!¦ KÚ.ÆYO+À É™øG,Ä¿â¤Yg_YZ_ù}^NB±Õ@}‰4fbÌîÕñ0üð$¸â_pˆøÏ<ëʲѕ—ðrBˆ-Ò·F*fòu¡ÌÐSü«û±æ_¢‰ÿ“g]QÖPEñ'„Ô @¢ °[÷¼! ð·ø'¿_`ùïÿ'”ø©º˜—“BSØ{D¢|£VëxXDŸ xâ_d ÅÿÄ'ÎúYÙXŠ?!„¤‘ˆ'e"a‹¿UÚ_ÿÊg|ágåc«¾ÇËI!)gtOºïÆmŒ@ M @pÄ_7Å"ˆÿ¸þBÉLÀÌ„€àˆrä9ÅŸBÒÎ$€˜É}X$„üýRüùBHf3ÉÙV»û7 ñXü×Äÿ»¼œ„’QP`q?¥ šø§øBH† €‘à;Ý95äžPü !$ß3f& æžøWüûQü !$«˜Üjm&ü¬ žŠÅŸB²zŸ¶~»{; aäO!¼WÛ¡ÍÐøWü/§øBˆ'÷k«È?´u4BÉ÷ @(#|Š?!„{•ÿ4B!yñÓPü !„ØÐgh(þ„Âûx¥þi(þ„BòŠ?!„ð^N@(þ„BhÅŸB ÅŸâO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü !„Š?!„B@ñ'„Bh(þ„B ÅŸB¡ øB!4B!„€âO!„ÐPü !„Š?!„’§€âO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü)þ„BhB þâ@ü+(þ„BhÂ!þâ@üKzÅÿgB!4Á6ÉQ…øWRü !„Ð;ú7ÿÅŸB @xÅß*åŸøŠ?!„€™»ŠÿbŠ?!„|¢(ÄÑ¿•ø§ýg(ñGñÏGUËÀâ2¸x ö¶º¨¿T–KyA™”«·eý$)Ð>vñ¸´D[µwÛbÒm“Öh»z¿]šº÷JcO“ìîn”=ÝMÒÔ³—›BEñ7ûX²(½Ú†jõ£ø‡ûÅ)’1eõ2¾¬AêJGʨ~µ2²÷()(öä9tźeSçÙÒ¹M½Ý*;6˪öµ²¶}£ôÄ{øK"„Ðd8`ý&EþßãË!\ RÑüQUSeZåT™T>^‰fr ŒÆØ²ÑÚ‘HO<ªLÀYÞö©,jY&7/–]Ý{øK$„Фý›-Àô;ñɳ~Z>¦Šâ’šüS«—ãú¥EøÁyî…2¡|Œv|yðÙÚÇ%xoßGòöÞ÷哿¥Òïæ/™Bà"ú1®þ‡(Uâ _Á¥@­Ë¯Äþ¬Ÿ“ûc¼FPFô.?ä‹ÚѦj ÞÝ·@^Þ󺼿ïc‰ªŒ!„Л³È?1PÄ—@0©í7L‹”Ïxš–ê;å…eòùšSµ£Q¾Òø†<³óÙ¬²„’¯ bò~òÇŒ¦þò%,&–“ó‡þœQó)Œä篯Fu)üÓÐ/Ë?=O4/’Y;ž“ù{?”¸úG!ùžH³À¾‚Á‘•Sä»#¾!‡WNæÅ8ð¢ŽÈ±UGjÇâ–år÷–‡eaËR^BHÞ€D±7ÿ3ÁÕò¼PNè4/†0F7Mü½V4xǦ鲮cc^^‡¹ÇÌôô|g,8Ÿ/>Bã?ù}#3À @€è§ï|}ØßË7†-ç­{AFéØÃŽ”§U}À=[‘v5˜ˆdóáÒ ¡ðy&ÀÊŸq\ÿiòßõ?”¡%ƒy1Rµ_Su§ 8^®^÷g. dt¡°#ƒöõbÑ7úxrôáKÀ_ÂõoµÈ5ãIñÏÃK†Ê'—Žú¶6g€d'@3Ì4€àÿnìåZ•?ɬ@!0¡|¬üz͵j/‚}¼(ͨ[ W39{7F ±äL¿ûó¤?Qü³È•‡É_&_# ¥u¼½ñðBhü(úÉ_c– 9ä´'ÉŸ'^%CŠñbd™Zµ$p«2Zh©$™ºòBhülÌZir ¦ÚýrÌO<Û‰ˆ¶µñ5ã!ǪBK’›L„·B„Ì€™ 9àì§Ëÿ4\–·Óür Z,ÿ0ö š€ŒÜlx !4~þˆCѧÈ!'U+?ýC­…ŠäÊ”ÈoÇüT«¿ éÜ@ù&4AÍÐx̤òñò«1ÿ‘¿ÀC÷?2¬d/Fª7.€@d„‘nÁ®}w¥”ª4ñËï¤Fk¿,ް#µ(o%„ ˆ†€FÀCñÿr̵숿ÀŒ€Žºˆ"¥ — !–|»ö_Ø~æc¾:ä\9½æ^f @^fH–˜R1I.öU^ŸsYÝÅ2šn%„ÐAè)üƒjó+. ]ÅK´Uš£-¡ú™úU)p _´Ì<û¬’¬rQí×eT¿y¾Û»vʆŽÍ²¥s›lÖŽ­Úû±Ni‹¶Kg¼SºbÝ}ÿˆÔvÅe¥RVXª8/&#û —êÀÛQ¥#Ô5¨ ÄÏÿ™'ÈçÔRÀëoóÅë$Â`¡t†€d ˆßùj#?³§»I©ír?l^(îûD¶vípý=zâ=Z6@ÏÀ@$3 ¨Z¦UM•#*&Ëá•“µÂ;¿‘AAà»{?ÔL±Ë°ŒŠÐr?ªûŽû Dòóß”gw½"+ÚVyrΦž½ZT­GÖÈœ9ð49{ÐéÚŒ~?}¾>ìäþ­ñEÌ ¡ Ä'ô?ZÇøê9­i_/³wþUæîyCÚc9}.›ÔÒÂô­Ë[gÈ©*íŽ"É©ªXÒ/àù<»ë%ÙÕ½‡/fË ¡ ä`T¤þ}{Ä¿øæù ­Ïæ‡UÔÿ–ÚºÝ_›·ãù¼Ùô®vœ\}œ\<òB]:*çÏ Å›ßþrÓÆÿã ÚòµÎ%dKH†9uÀñ2±|\ΟG4•G·Í–o/½L檔¿ßÄ?™wö~ ß[ö¹gË#‡æ‚/ >S4å ÚÊ0@h9ý£ò?× šÿ²•¿”»¶<$*fëQ¦åám3åÒWªe‚-9}.¨ßø×á_ã‹ÚòÊ[(¡ DãøþGÉØ²Ñ9}K[WÊ–_.KZWö:®j_+—,û©ªÆ_ÓçqŽ*Räp kÃK !Šú圞ÿ­½ïÉO>ý•ªºßøk‰BÅ_®¹Z[¾ÈØ$è˃Ïá Ûìʽ !¢EþÇö?2gç³é=ùíšë|±~ž)°$pÕº[r:˜ç«CΑ’îÈ ¡ Ä„¯¨H1W7Äm«åënÒ3l ˜?ÛÇÍKrr~ 1úLõ‰|fh Ésú©¸gülNν³{·\¹ê*öK%ð»µ×i?k.øÒà/ðEn˜à-”Ð<çój~|Ea¹ççEkßÕëþ¬MÚ ;¨køãÚ›$y~×ö6 É€’çœ;茜œ÷ÉÏÊGÍ‹òæ:/Tû<½ë…]D¾£ ¯ ‹ Ég”#*óü¼;ºvÉý[òo^=íÎÁˆÞ3jh½2@hHóùšSsRü‡Yú¹žéŸ °™ÑÃÛfy~ÞúÒ‘ÒPZÇ|b€€î@Òætµþï5ÛÔ|ÿ—÷¼ž·×üùݯÈ7Ô”>d_¼ý]ŸšÑ]ç33п‡KÕŽ—-ÑVíýBO•–Y~}YA™š°XhúùBõ¹²ÂRËïQQP~`þÀõn—çÔ®–„ÐÏT\#‡ULðü¼˜ñÆ–?§`ÖÁŒíÏÈF]äéy±a· >ȤïyÍAA( \ iqRõ±ž§AÑ ÷ÂîyyíŸQÛõzÝý0¾¼A{œu æÄ…€ÐqbÿcûÄO©˜äé91ò·#Äþ¤Ê¾žfYÚºÂÓsY9…Þ° €ÐÏ™P>FíXâé9ßÝû/¼ ìûØÓóM*Ï‹î8€ÐÏÉÅðŸš?æ…7á} ÀÐ’ÁR]ÔŸ>çÖâ1“˽5ë;6ÉÖÎí¼ð&¬l[ãùP q,Ì9¬ 4Ä{àqÀëw#Áo‹<¾|,/|® k ñ’ŠÂrÑo˜§ç\زŒÞ†Å-Ë==ß„²1¼èÌ’O ÜëA0+ÚVñÂûìM`ÀÖâ!cÊê==ßžî&NÿsÀêöuj@gç«+¡¶·-å…g€Ð¼É”z[üÅèߨ"xmûÏ·,Ðævâ)£ËFÑø”m«==ߘ²:^ôÂ9„€xJm‰·€^‹ZYéñµV2”=§B@<¢(R(ƒ‹zzÎ í›xá²±c‹Ç`/za ¡ žÞð "Þ½lºãݲ½›€NÙÔ¹ÕÓóÕ2[ÀB@¼b¸Çýÿ›;·1ÊqÁžîFO7LÞ€B@ò¯#¾M§´ƒªÂ·(Ó䃊k¤¤ ˜>‡¿oBR¥ˆ—€¸Šø<6;i\›&µ 0Ö£ö<´-ìùÒCØéŒuIW¼ËðsíÑUýÕÞïŠuñbâ‘ð8廹ƒÂâ÷k†×DªàŒçgô¹Ì=f¦§?û÷—_®½m¶®ÇÇãqõ¹6ÃÇ¢¾ÅËåBhHZxݸ½k'/ºKvx\49< W²E•ÖWxÝöµ§§‰Ý%»U! — e+ !4$Ü`½·º¨ÊÓsîêÞà ïÖ4u{kšª‹*yÑ ¡ aÛªA@^mZzZyá]Òèq ª°Šfú{ý#•Í6§®[Ç€BhH¸©*ôöFïõZvXÀ®€f•çY1†…4„Ðp€¢ OÏ×ÈÀ”ñ²€BhHÈ©.êïéùš¹þŸ2-Qï®3„аg<¾Ñ·y˜Æ^^»²Â2m—HB mÀÛ"À¶X;/z®ÚC+™ „€„—JÏ34©_»OÏןu„Ððâu`+ @o—O0#‚B@BJI¤$Ô"® €·æ©(ÂmE¡ ¡ÅëB/.¤cž¼½vÅ4„Ð0ooòÜ*5kíôøµQÌ‹N +^GyÑx”=Õk'Þ^;¶B@BL¡Ç ‡ 0æ‰K„Ð0g ˜ 03‡ÌB@B‹×iÞ˜Ð&PÀ !4$ÄÀë @Œ= ׎m€„ЀŒÑïáEȵ£ „€Ðd0Šå3„’ûKÄÛ—Kœ—|ï¥ ¾ÍÔ àEOþEURäá(`f „èkˆ‹HÏÛµÞŠÂr))(æ…wÉ£ÐÌ !¹þHºß„€8&¦¶|õºuî©öÚ0@ˆ_„?bq@ï‘,ê}?B@\±³k7 €ÏXìíÒIcO/:!Þˆ¿è[=z_|íµ×6ÜqÇ“ðâŠí];== ýŸØÝM@H¢~£›EþXK-»á†>7~üø~ýë_¯a qÉŽ®]žžoXÉ^t— -ì±ØÃ‹Nˆ·¿Óÿôê|Ùm·Ýö/uuu×.]ºô+Û·oëŸ$Ä· ¶d/ºK†÷ê±häE'$ûâŸñ'þß(ê‡ð÷Þ­Ž( qŸèö:0”ÝuÀ;ӄΦž}¼è„x/üñ×"ÿýèGÓN?ýô{úõë× oÛ·ßñàƒnÐÅ£ î2Þf¼NgÒ‚~ª°Ê³ó¡&€â™øGL>¦û•^wÝuÿn#øéFýHùk½ýßûÞ÷ŽRiÿëKKK'Ú=±… Þ¼víÚæ$ñ$ýŸsHj¬éðv`jÅ$^t&•óö5àñR¼6$EŒ¡ˆ3£à¶¯ÿ€ð«I~ý¯¿þú‹¿ò•¯<éDü[ZZýéOzNö§þãç8øúåý­—Ï 8Ù³óM«œÊ‹nwª¼½FkÚ7øîDU4î¥(E ùÂ#Y‹úQè÷­o}ëUíÿ§øõ×_¿A-tÊþ¡?¦âO@ýM®˜ ¹íˆuò ‰cËF{k;ü—ðÞðJ ¿•Ð×ú {ú•ÿæ7¿ùÊ´iÓ~S\\<ÀéIwíÚõúí·ßþaoôo6e€¤Çª¶užž‘ÖÔÊÉòá¾Oxñ 8¢ò0OG#Õ¾®}£/ €·¯KÞBC.ÞÉÛ|Ìn󻨿Ÿêé¯ýþ÷¿ÿó¡C‡þƒ«¿Éx<:{öì¿ÈÁyÿF™fHúlëÚ¡í?¨¸Æ³sb€ÀäÚxœþG(ºü†×yÈJ‘¼5 q ÃRÔ¯Úûþîè£þ•Šú‡¸}B›6mšóôÓO¯’ƒóþž[Ã"@’2KZWxz¾cªŽàE75GS¼ýÝ·¬ðåuð:P]ÔŸ/¾üÊ8ùœÝ4¿BIhíƒð«¨¿Nmâs½zûçTÄ_ ýéxàî‘ým1ƒçg€dX–ËiNòì|‡©:ìA€ì9ÈÐ’Á2¡|¬§ç\ܺܗע+Þí±¨â 0?Ì@b ÛÈ¿@æ‡飲_ÿú×ç!êWC}§ú?ýôÓ'ÔÌÿ­rèУè?®ÌÀˆÖ¸O«9™>‰ÓT7†—ëÿ`i«?3^/K0À ƒÈ?yQå¹çž;þÁ¼óøã¿%ñïîîÞ{ë­·>¤Þíƒ ,L3$uV¶­‘Öh›T–{vÎ3jN•ÛŸæÅOº&^‹¬ As· ?3at³¯‰'½5‹üÒÿšø«¾þ Uáÿ/S¦Lù………Õib‹?¬†þ4%Dÿ}¢|“Cû’2Xoý¸e±œZ}‚g眨†ÝŒêW+›:·ò À’ȤŠñžžs±ZúñëÀ–h‹§çÀ @ØMAÄøÛeŠzÅ¿ì’K.9öÌ3ÏüMyyyF š:::¶ßtÓM³¥ïÚÜ©àI‹÷-ôüœ_ø9^ø^>¯¢¯ÓÿïíûÈ·×£Ùã%€ý†óEžè߬]ÎIŸQ[Ÿ¶kŸ:Ê'MšTû—¿üåççwÞã™íoñ½÷¦«-[zÅ¿Otoù —HF @³÷my_|–<¼m¦t{\ðå7°ÓyêZxÍ;{?ð¯èñ60ºtoáüÅ&ò94ݯ‹¿Vä§ú\YRR’Q·¨Fþ®»á†^”ýkÿ1§Qâ×Ñ´ØØ±EKÇ#-ï5j0ÖYO“çw¿š××þ”ê㥶ß0Oω €¶wíôí5iìiòô|X‚éWP¢mEB1^óO½º_K÷_tÑE‡ŸuÖYWª1¾Y)ÒyõÕWïéééÁhÔ¨‰ÐÇ„K$Û¼Ýôžçç¼°öŸ¤8RœÇw¦ˆ|cø×ý'áµ9AfT¿¼ „KäTô'§úõêþ UÜ7ò¶ÛnûùùçŸ?;[â¿gÏž%wÝu×;rp»_+Ñ73DÒçͽÞ€a%Cä†~)o¯9Ú!'•ϋߵŸ À>$T&@Äù@]üËUuÍÕW_}‘Ú‰ïÕúúú‹#‘¬E(ñ§žzênõVþc‚Kÿä¯fHFÀT¸Æî&ÏÏ{QíZ 6ß@ÛåŒúwÏÏ‹ôÿòÖOi’8®êHÞÂaì?ñÐ…¿Týÿû¿ÿû¬‡zhÎá‡þ{ÕÓŸÕùè›7o~gÖ¬YKä`ß¿Ùa·À É€Uÿ^kzÛóóbûå£/ÕÒ°ùÄ¥£¾#ƒ‹z~Þ¿îžëûkÓØ½×óõø“ªótÉŠð»‰úuá¯ºà‚ ¦a˜Ïé§Ÿ~_YYÙ¤l?Y5ò7öøã?˜ý›¶4$#¼´ûõœœ÷(µ ο×~=o®ó!ç :ÝóóöÄ{äå=¯ûþúÀŒz=*E€7ø ¼ „'ú7Šøõ {4á?å”Sî¼óÎß|ó›ßœSSSs–ˆ7½¸7nüÛܹs×ÈÁÊÿ˜šú™üÿNvŒ°¢m•¬ïØ”“¶¨UÅp›U' »ç…úUu¸\VqNÎý¦*ôÜÛ³/×iUÛZÏ_‡ßv¾ÌÛó–ììÞÍ›A0Å?±°/Öû6±íO3‡vXÍ~ðƒ=zôEjŠ_¥—OTÿÑG}ô19tíßM@„K$+Y€=¯åè/8"?©ÿ|n@x÷ @¡ÙïÇþ,gOìx&0×jUûZÏÏYUT)¥Ö¢Jýø¡—¿bèСƒ®½öÚ謹—ÆŽ{i*â¯IEEEÊOtݺu¯¿ùæ›ëz£ÿ¨ðÛFÿÂ%’IþºëÕœ ç)ŠÊ/ÇüDÎU)òðEþSåºñ¿ÎÙ:óÇÍ‹e™Ï‹ÿú€u99ïø²1rÏa7ÈW†œ#å…eY9Gea… T&óÆ”Õó¦“ù @â†=åjxÏ5·ÿ몭ï9ÕÞ÷sµUï T„„ Ò¿imMmR¥Šþ{T­¢ÿ.é›þ7z'Ñ?'’ÌÒ¤Rį5¾­†ôäfT/Š/ýÒPZ'wmyÈó½á³Á—Ÿ#?ªû¶28¹ûS}tûì@]3,äŠEÕrYÝÅòƒ‘©Í²VkÙˆ]»´M³ÚcJe ´š˜¹õ…¬åR\P,å¥RVX*%‘Í@ôSŸÃ×Tª¯íÁû}³?øž_þäBÞxÒ¼mHßÊ~cú’Ë.»ìój§¾‹•€§Ôo ᯫ«“ÊòåË¥±±1õ×ôªUóÞÿ}ìÀÕ-Ö…vË}'þþI&yjç_sftþyØWäðÊÉrÕº›UmÀ¶@^G¤”!$Ÿ÷x§¿d>U;>¾¿ïã@];Ô*x=2ˆü•‡iG¶€IÀò—_7f P@/ð%üÅ—^zéi'tÒ·Uº>%áGšÔ¨Q2dÈéêê’… ˆüãñ¸¨ùÚûªk@¢Ñ¨ö56Ñ÷Ã?ü„Iô÷kÿÜ d¤Š?iY"Ó*§æôyL©˜(w«tì#*z}|ûSÒëÈÝ(¢¨‹G^¨¥zsÍÿmy(¯Ãj“ªQCjCý·†× 2mÑvÞxRGâ1¼øâ‹?ãŒ3¾[YY9.]á‡ÈCôÕV½šÀCèÕØ^QÂöüª*ihhE‹Ù›ðO?}õÃ?ÜÔk¢bßþç(úg€d…·>!Ó&LÍùó@ -‚_t¦<²m–ÖÇŽv6¿ÞÌOª>V¾UûÏjÂß8_<§ù{?T»=~È×àj“*¬Å‡ò‚2€4@1ßøÃÓN>ù䯩5ú1™~°k×.Y±b¢wlÙ«Eþˆø*(UHˆ–>Ûï­ŒC×ý÷ßè?¹ï?*©Uþ'þŸ€d!új^$KZWÈÔŠI¾x>üãúK4q}eÏßäEÕ.¸®c£/žÛ â9sàg土÷UQê'îØ<=°¯A.âg(Œ†úo µ»º÷ð¦ã’Uÿ>¹}¬\òðÃ׫ˆ?¥]úŒ„lÙ²EÖ¬Y£‰~SS“õëâšøÜŽöó*TíÀË*K€uÌnÑ·ë°ŒþiHÖ¸gË#rÄßúê9Al/öUíÀÜ /ZмP6tlötSüŽQãcÏø5Fvš/'>½óíº•–h«,jY®uP„ÝçÇŠäˆö‰r\ëRU-y•âZü•aÐD|ðàÁ}>Q_½zµlݺU{Û¶mZ @AAŒ7N3 ÝÝÝvÑçôéÓgªw;ä`ë_Ôeôo–   ÙÀ0<æ3NðåóÃF:úf:è^XܲLÕ.,Õj¶¨ÂÁ¦ž½»A×– “IªžèU˜xDåõï_°µs»fà‚ÎËj.EØ @¶Ú Cwbertëar”:JãýRújg?-⇨ˆµ–òß½{·–òß¾}»Œ9RÔ¾Ú1yòd­ PgçNû=+–-[öâÒ¥KÓþ“‰3@<áN•B>©ú˜œ¶°9a@QeTNÔŽX§f¶vm—m;¤KÍ7@TÙëÑÚ¹pÀåïo×*9к…¶­¡%ƒ5‘‡ð£š?H ríú¿h?_ÐAKê¥uß‘²‚Òðf ˜°¢¦§Z‰þd9²}²ÅS[0`€¨É}<ù-Y²DZZZ´”?|=–JKKEÍÐÞê òWÛùZžS ¶«í~ý[õý§ý÷ùs§ Y-xl›­ÖÞÿ)pÏýÙcËFkG>1{ÇóZG€‰y³éÝœ·¥fÕp àPP[ßY«"þ)2¶³Nû¿ëï¡Ä‘¾ÚÖWKù›Jˆ?¢~µKŸ º Ò‘¿ê,ìóDÿø:+T÷À j9a—ô­ü·[pý3@²ÎCÛžS§MI#þCkîÚòp¨~¦'wÌ‘/ <-%å4ÅLųSÚÆË±mSe ŠüSkõX§Ç¿^¸gÖñUš^:;;µ¢?…#FhŸ4hLœ8±Oq`¢°‹þï¾ûî§ÄÙŽN³†f€€d•U‰}ͺ[å¶ÉWçlŽ=±Ãs~µúZµ•ng¨~®OÕTÀ·´Z”Cš` @MO9\öÙ6IJc©­ïCøkkkµ5~5þ×öëQ০óIss³¬]»V[ï×kð>–ŒÀ2Ý8`e*^Qsÿýcí¿Ç$úŠ}ëŸeôO@|øpM¸e5ÔgåÊ•Z…?L¢¤ù±T#1iÒ$­SÀêñd…šú7Oe¶;ˆþí6ý±þiˆ§Ü¼ñÿ´ùìÙœNÜv?ìßvnß4]Ž®:B½þFÐ4ÚGŠ\Çh5¸?õ¹ˆÔ!üÉÃ{ì@å¾jÉÓ"x¤þaPݬÌÄa‡f[3€AŒ¶0==ôÐ,9Ø÷ŸÕ蟀x æñ_¹úrã„ßÉ„ò±¼ 9ro›™?+Ú:¯Vµ(7MüïÛRiöƒA=‡µ“i*ÚïM½V¯èÇú¾Y+ŸmmmÚLˆ?Šý°Ëßøñã1FX3'ËvŪêÿoüñæ^ñÏêÚ? É ˜[~E¯ ¨/É ’#flZú} ¯~æ¥j<õïÖÞ ¿óÿB3"8lƒ€PÉ?AEùG´M”Q]ÃÓªÛ€@#Ò‡ðÛEçf §‘?Zü°îê~´ùÁTàý &8ZB@§ÀÞ½{­¢ÿèc=7޵»-㙈þiHNhìn’­ü¹\5î´]ûˆw`ÐÏÝ›–GÕ.‰ùæ\»þV¹¢á?CQŠ €’¥‘ÝÃdJûxm>I<½n!Tñ£¢…}X›O¬õcºÖû‘¾6l˜f& þøÞú°' {`Õû¿~ýú·ß}÷Ý rpê_ªÑÜDðÙ@üCsO‹\¾êwò‡±W¨q­‡ó‚x@g¬K«ö£i~^_‡—Õ†P;Õ:¿hø±/¶\N+à.€AÝdJÇx™Ú6A*béÿHïC˜1£ßÍú¾}ÌõǶ=ˆ½^70fÌ­xÐ 6éÿø¬Y³’gþ§ý›Š= ñX€ øá¨—¿òE^,‚?¤¿—«½Èþ½*¾¿ü§ò‹1?–#Õþ ÌxÖòåÞ>AÓ›.H¿c}…}©¬ï'ƒJ}U‰¯­õ£ØÿÇz?Æ#›€ª¼ï¤þ1)Ð µ-ð{óæÍ[-é÷ý»ŠþiHÎÁ  [6Þ­íÎwYÝÅj®~?^” 󺚉݆ۥ5ÚÆ‹‘¶ÑýñÊ_Éi5'ËÅ#¾)µý†/ j°”áån–nÁæ;Û´)}#º‡fdé;ì! GªßIž£{‘ªÐÇz?„Æ š¹€à£ÐÏi¥¿¡ùÞ¶Í2úŸ={ö“r°ï߳蟀ø†w¿&KZVªµÙKU]À$^ s•m~©á„AzgïûÚœ€¯9WkU Ó²ÂR-›æ'úÅKTË^ŠöÇÉèΪq/3[^#ú†è£/Ý4"ˆÐ-Z¤õùc½â·n*ý“±ÛøG úø¥—^Z!gþÇ$µ¾×Ñ? ñ›:·È®ü…\0ô«ÚB̤Oea/‚Т:sdz2kÇs2Mm!|Þà³ääêã|µ“ ²e:6iƒÖ´¯W6׫÷×ûFüém¯“‰ ÒÐ5R ã™é´@êxþT«ù­@Š~áÂ…ZÁ†ûTTThÕý8¯›J#PHhUü÷ì³Ï>!×þí2þiˆïÀXZT¨¿¼çuùÞÈo†z#/¸°öåõ¦·ecÇ^ ‡Ôà(R­‚S+&Ëqý§É±UGª!ÔvÏÙßÏ‚¾¹s«2Ä[µ·:6k¢¿^‰O¼ÇW× “ù&v6Èøöz©ëªÍèß*"oˆ>Fë¦*Àv`2Ÿê½×ÄÛú"Àq¾8ŸÛJÿC^KJøaÌP…‹Ÿyæ™%IÑÌÀd%úߟA .‘¤÷‚Þ£0á€Ù)N8`%}þïÍåmÏ¿`jà¿×~iðÁ¾O´bK’˜0²ßpm‹è1¥õ2´dˆÖE0¨¸F{; È¾¨ -ÑÙÙµ[öô4%¼Ý%[;whY°Ýݾ¾(äßQ¯ÖõÇÈÈža’Éò´ðA𱾟h?Ìñÿàƒ´‚?ˆ5΋íS­ôOFß-Ð Õ÷ÿ5ùï õ.vÒûÿž¤#*öÛÿÒЄTj_¨–‰÷üaí2·ñM^ˆ,ƒ/KÕÒUa¤@­Íï°öh‡tÇ»]„Y­ÒÖô!ú™*ä;póV‚‹úÙXÛ7‹ÌQéÿÉ'ŸhÃ}€¾!†aí¿¦¦&íó,_¾Ütý_ Z÷Ío~ó2õ.¦uôf¬ @Ô"3 rèðG¶ŒK$,lY*?ýô·Ú,÷/>ClÍõmü‡jµÄ†?Í*ú$ÙBßíÞ“W[,íèªí´7®³^f e/ŒÔÅÚ>"o'[ðfTú/Y²D ÷ÙÀd?<û¡ ]°œ€ €o¿ýöÓð†b=ø'kkÿÌ0hÐþtÚ€“äÌšÏj›¼D xQl˜³ëE¹qÃÿñBCJcý¤^mºƒª}¤øËc™OÁ£’b áÏDß¾PéáGµ?Šýí£Ç¿ªªJ}ˆ¦Œˆêí×#ÔÞ;Tôÿeö¤ý›þå nP(õÂîyÚõ×Ï 8QN쌣̻Œ9OeMÐn¹´u%/ÑÐSûc;Qħ¶ÆgÞHCh‘R‡èãm¶SüF@ð,X õùÃÀˆ ºY BÚ?S…†vÅï½÷Þ3Jü[¥ïº¾Yäwp¤ <{ÔÞÏì|Q;P¥=­rªv €pRùxO*·ƒÖmRÿ}¹DMÀ‹Æ£¼ yúÑÕ›ÚWQþ žìŒB†ÈCì‘ÞGÄŸ­*~' Õb?ôøc Å…|˜€t+ý@êKF¨MöÝ{ï½/÷FýFѽ“ôÿ!ž#•蟀„ôsc­@Q¶§Z¸Æ—7¨·£¥AUpçrµí];e˜ª Ϩ`ÿÇ¡çÉãÛŸæ‹%O¨Œ•KCÇHÓU'£;FhCz²Di}>æægjB_: Ò_m²ƒÍv´ÈÏoܸqZ?ÖþQx˜i¶nÝjú9µ­ð ª0pŸ8ëùÏjôO@Bв° ,ŽDjÔ²AmÉ0ÕÖ5L[S„v®êãÕêýj©*ªÔŠ S©vîT{Ï·ª%жX›ìRË|˜Ãc]ûFYܺ\ËX\=þäµd‘ þ­öyMM¿ƒ!áŒò‡vÒÖòǪô~¦«ö“E½óØ€Ât.Rü‡„ÄJì1Òi˜ oå ñGú©ÿLÓÞÞnºí¯Ê>´ßsÏ=Ï&DÿFSÿÒ‰þiq¶$Æ‘l ’AK²¨+ÀMTï<ÀÀ˜–hëþ?zÕæ¥§Ô[•èc˜‘·l¼Gî=순,OàgúϺïÊÿ¬¾Š/„P+ÕñhëùêÀT¾l…èCP!¢ýdñÍ¥ ˆF£Z¥ÿG}t  õuuuZ‘ßäÉ“µ!CÙÀ*úWKsÕ»¤ï¦?‰Bo·á]ôÏI€„d’ÍãÈ4[:·©‰‡³´h<`Ì- 'ßlz—¿ä ¢nõµ=Cd ¿k” ë,ÙÜ3ñ±¦ÁGϾ¾¦ï‡h?µÆ® ?ªýUµ½ö1 ÷A-*ý!þøY²e<̶ýU» ö¨¡?O'Eÿv›þd\ðiñ l›-g¨6ƺÒ99ÿÕ}O>j^Ä]¢úúÎRûXÛÏvDÉ|?ªåÄ>×Ñ~"---òá‡b]+ƒIÁz? 2“&M:$[‘I°‰L€k×®}Sí7°Yìûþãb?þ7cf€€ú„?oº[®ÿ«œœ#l/Rˆ¿lº¿ ¢­å÷ T|£T¤?*«kùE{J>Þ"ÕŸªØ{m Pyÿþûïk3ýQé¡Ç:?L Òÿí‹ç£oÌ“çfÑú‡-£ÿ¨ËÈ?+Ñ? !9sú_ozG>7à䜜ÿ†|I^R/}Ú¶†¿ P/RQ~­6}oLç(©ŠfoÚ%"d ÁÑ#äÄ x~Kí[±mÛ6­ÍEx¤ø!þh÷úÿÈ‘# JrÆ#ÔhßKɨ"Ä^{íµUb¿éYñŸdË Ð’cnÛxŸê8:'[Ïb‚"füÇŠ+/’ÌSÝS© >úòGªa<…’½žyˆ#Òú|´ÄAøÒMíçjç]·nV鯊ë´ÁÄ`ºŸnœVú§k¬ÿÌ;÷Ù¿ÙObßTÌwþ³Ëd¬Úƒ€³³{·Lß:C¾?ò[99ÿ¤òqòÕÁçÊìÏó—ჺÈÄŽ1Jøë´–½l¥ö‘ÖG„¯GùéöæûŨ¢:m§=¬÷ëm~úV¾¥¥¥Úz?Ì@ªÂîæq(<´ÚôGíú÷QBôoõ›íðÇ6@BÂÊÌÏÊYOÓå‚ïŒøWy£i¾ìêÞÃ_F(RqýÈÎaZñބΆ¬¥ö!TzZ‡“m2!Ô^fPà‡yþhõÔ?€9˜è‡ŸâoVéŸ C€Ö¿äÏë¼óÎ;ˆþ;ÄÝà»Þÿ ¾. !9snÙx·Ü4ñ÷Y-ô2³þ£îÛòÛ5×ñ—‘!°¹_[ÏW­zűìÜn!v{¤ôñV¯t÷Cj?ÓÆ µµUT5½6Óß¾ý»-ê[ùâgGÚ?¹xÑ©°»yžúã‰@õ¿ª&`—ûûºô]û7ücµÓŸÙÎl$$,,jY&/í~]ÎtzNÎBDÌxgïüe¤zCj­zSÛÇËøÎÑYÙ\±×Ãm¼ê\­ù£Ðîã?Ö*ýQp‡ç€ê~¬ócôpr¥&£|3Ð÷®#Ô,‚¿ªÉ€mÒwW?«êÿ˜dh›_BÈí›ïW"|¬ô/ªÊÉùõÙÙ~ZÑWéýz5c’ZÓGz?Ó‘¾Þ“¯GùN÷«÷:‚Ϧ1@¥?ÒþØÐGïñG±®Ç¨Q£ +ýÓv§3›ü‡±¿Ó§OQÿ¹úcùg<ú§ Ägìëi–{·>*—Õ]œ“ó-,Öþ“ܵù!þ2,(T‘>ò@ôÇwŒ–’xfG:#ÊÇZ> ÛpØ °ñsj?Ýó¡ÂÅ~hóàd<ô­|Qô‡‘ÄnŸO& f`ö¿*Kñê¦M›PPÓ-öé³e€ŒŠ= !`ÎΗäì§Ë”Љ99ÿ?ýŠÌÝó¦¬n_Ç_F¢P¨(ä;¼c‚&úýb™ÝU}ëzµ¾>y/h|&³X_GÄÿé§ŸÊêÕ«µï­oå«¿Mœéïeêß*úWÏ;úøãÏ‘C[ÿÜìú'ÙŽþiñ!Øh·MºZëÓ÷<ºj³.]q¥ö\òŠh¹¶¦Dû$Г¹¥½b‚¯¯å‡1‚O…îîn­Ê¯÷øë[ùBôQéow½Ò-ð³z,jô"Äd6nÜ8_Í&Ø,éoù›Õ蟀Ÿ²²mµÌÙõ’|uȹ99ÿaäKƒ¿ Ïíz9o£} æ9²m¢4¨‰|™êÌHž¾gW±–Ô¾›¯EZ)ÿ5kÖèñ×ÛüpÝ`pݼHû›=Öj׿çž{cõÖ¿Ä©™Øò7£†€€Ÿr×–‡´û0³?\<ò›òVÓ{ÒÔ³7o®9¶Õ=B‰þ´¶ÉÒ?š™-c±~¯÷å#Š… sj?óíÝ»÷@ä¿k×.ícz›*ýa¿·×i=;¡?·dTWÀÒçŸ~¹ºéÛè?ë3hñ1mÑv­åäüU…•òƒQÉUënýµ¢6Ý9¶åp™Ô>F«êÏT¤¯ñéÛç†E¨³ñÜÐR·|ùrmÍF_ÛÐРù¡Ò¿¶¶6kÂîæqèH0üóÆo$þéw<þiñ9/«zÎôy9ªêðœœÓ _Ú=O>l^Êë;²k˜ßr„ŒU#yÓMóC4áësöƒ:'&ëüHù£èÃ~âGª×QïõOe'¿L&šÍýWÛoU­óåÐMœ¶Š—Ñ? !>Ex7o¼Kî:ì)Šæä9üWýÅòÝe?–®Xw(®éþõý:9±eš ï’¶è£b_ôƒ6k?ׯ‚Šˆ_µÌiâßÑÑq`#û¡×?±Ò?QÏ„!ÀÔ?³Á?jGÂ9ªM1yì¯Ù€§›þÐPÖwl’'wÌ‘¯ûûœœT¿Zù×açËý[ üµDïþg[Ž“a]ƒÓú>hC«©©ÑŽLòù)*Ïösƒb¤/Rꬭë»ùaùo±±O¶DÝícñµx®F(ãÒ¬Æþ¾*}7ý1Ûú×Í🬚Bv <½æ^24'çÿ×áÿ óßÔÌH¥¶ÙýLó±ZÊ?Uôb>¤£õ>ý|àSýˆôQì‡tº>àGßÍO½Ò?Õh=Ó†;þaç?#TíÂKêóͲ¿øÏjòŸÕŽžS „ßÓ©FóÞ¾izÎÎ_)’×_’“ŠÒ»î}±é4¹`÷—R} /ªÏ§L™¢£AüSÃl|m¦"x/Ÿúç1Ó_õËk‘?Äذašè£Ò=þFYœ;ñpóœSy\òcÍ¢µŒÑ­Öþÿ8­øOe3„ä#Ø®÷ݽ äÄêcrrþ‰åãd|yƒ|Ú¶Ö÷ת(^¤÷ÐrdJUýH=#ÒGÄ1J7Ú[Ÿê×¢ÒkþS}ÀO}}½ :T«òG»_&¢õL?] (N4bíÚµo¨Ÿi§8Ûõ/Ñd]ài Þt]u„”{vÎÖh›¼¨:Ù>Köt7ùþaLï™ûN–ʨ»H]ŸÌ‡¶3£Â3¦öÓ;†ú Ò0hD¥?RÿȰ$Vú»õl³èê©§žéþÅßwci 8[:·É£Jˆÿ­ö‚¬Ÿk{×Nyfç‹òÌ®5àwJcýä³ÍÇ©é}“\=Bñð£Šß­è„­8/ÓçÃÇõ©~*ZÖÖÒqõÝüôuÿLŠz& &šýUÆà“yóæ­–¾ƒ|9ö—€ðȶÙrFÍg¥®tDV¾ÿÚö òøö§enãÒ⚌Um}gï;U›ÛïFø±æ áOÔÃ>sçÃú>†û@ôQì!EEb¥?Úþ²-ê鮳^Îmú¬¶îïôð£Â€|vMËîÝ»5чø#òÇÀ˜.´P"ë2räÈ”~6/ gµéšcШÿ¼&}ÿÄÄyÿ¿ä:ú§ $Àìîn”¶=)ßù-ÇiuÈ_w½*3v<#;ºvòçF‘ßYj½ßém¢3}6Ä7hÏ Ûä®[·NµÂ?| *ü!üuuuZ ÓÑz¶ *ÿ1ªØˆ… þUÍþG_ ÝÚ¿oÆþÒ2fîxVÛ°g\Yƒå×ííÙ'Oí|Afí|Nš{ZûóÓ6UNß{‚㨟õ3µŸóáó¨ð‡h"j^¿~½öõXï‡ècCŸäÖÊL‰z6 Uô¯2÷ßÿ_{£ÿÄÁ?F™«ŠOÇþÒ2¢*•ËÆ»å¦‰¿7œÒ·­k‡fžÝõŠ6M0È`¨Úüœ€5~DœN+Ì™ÚOý¹éú Òó8Ðæ7qâDmŠýð{p»›_. ÖþÍ¢ÕÍðšb´GÌçþ[Uþç,Ú§ $„,jY¦õ¼¦m¬³¦}½ÌØþŒ¼ªZù¢iå³sü±{Ÿ°¡ Ö›[ûü&¾aYv@¤Œ6?¬÷c²&ý¡ÍODþÉc}ýRàgjÌ¢õ}bO>ù¤>øÇ*ýïfßœM¤ $ܱyºœ\}¬lìØ¸V>;ŽlìXüQaŽÃ.]æÔ¾WÏ £q!þØØgõêÕÚ¸\,·`ºf+ ãÄ„å¢ÀÏêqØòó ŒPS ?˜?>fw‹» 섟BHjìëi–‹–þ—¶Ö&ÆuÔËÔX_' Ò<±ÈŒ|öžzãQéñ×{üa¼Pð‡áJ¨½ÀãݦýsmöGà 5øÇ(úw3PüýÓ"Â&þµ]C弯Ï;ÚÐHüÃ*¾¹~nHTøCôa° €K´÷á-¢ÿL‰³×†kÿfÑ¿jo\5sæÌ…Ò·ï?*ûK@ ¥ñ~r^Óé¶;ùá¦ñdž2Lígÿ¹a#é‹´?"f¬ó#êGôo6Ó?[† “FÂoý¿õÖ[úØßn±ßö7&>üC@ñ7êVø¥ÆÓ¤´ÒQäñgŸÝç¡Ç,Túëm~h³D±ŸÞæ—XéïE´žéÌÄß,úWõÛ§OŸþ–ôÝò×nýßé f!œØ:MÆtÖÙ~Öœ“ÅŸ©ýÌ?7¤ø‘êGÔA?hóƒØO˜0ADþÉ•þ¹öTg·öÿÁÌQû´‰³µ·ci!sýOi>ÚöëPm•‡ëü+V¬ÐŠý0ác~Ñf‰?XëG»¥Ù„Å Tþ£ýÏ%ü{ï¹çž—“¢ÿDá·ÛøGüjh!¾ @ý;kï©Ú[+Ðg>|øpFðY>ÚúöÇF>z›2.ìƒÑ¾X~I¬ôw+Î~1~«ècÕÒ*l»Åýè_ßDû4„ßrBË2¬gõ K¥šQiž©>㯅 b´/ÄéÿöövMð±‹Zü¬:.üXàgõ8«ÊeÚÕØßçäб¿v)»1À9þi!¾ ¦§ZNl>ÊòkpS‡ø˜­7ûM|ýüܬ¾ÇæÍ›µJˆ>züa üȺ åJ·Ï×Ë(ßÍcýcYà µ¥ñ˪àq·šþ·kô…ÀÓB|Ï™jØ]Ë_MM”——3‚ÏÒùðxô÷£Ê_oóÃǰÞ6?˜€ÒÒÒœ {6 ÕŽêãÝ>ø`òà§|9ø‡€â+êºjetç˯ð¸)ú£1p÷µˆ„‘êW[ÜjéÌõG¦E/ö³ªôª!@wÚÍPfèoK—.Ý*ÿ¤2ö××u4„Ü¡n‹§ï³ÞÞ7v¤Ÿý"¾~àS=Ÿªr×*ý‘ò×ÛüPh™Xé™þnŸŸß Öþ““øížx≧¢»-Í Å¯Ñ? !$§Lé'C»­ ÿúÇö¾Œà3"~DþXçGú3þ±ÆñG¥?ŽÄs­ÀÏìq0=¦UwÕ俵âlì¯]€]„Ò熬þlÓó}ågË3µŸ¹¯Eú•þC´ûaw?}ªŸ]¥®¢üLÓ.úöÙgg‰³-3ö—€â&¶7È€h˯IŽ@s%û9‚Oõ|Hó£Ú?±Ò_oóCÊ¿²²2¥ˆ=†C0ÓÀâÚ|ôüóÏ/“CÇþZ˜8üà !$¿9¾õËÏ£âSçÁgî¹ÌñG¡DiTÁ£Èó þ‰•þ¹ölTþ[Dÿ¢¢ÿ'åÐÊÿ¨‰ p’òç€O‰ !ÄsPõ?¬Ûºªßh[Ù ‹o®Ÿ†Ý ÕßÜܬ¾E¥?Šûôõþºº:mÉÅ­Èú¹00ù±XæÀÏo†*‚üä™gžYœý;ÝøÇ÷ci!¾àØÖ©–ŸGäH”©ýÌ<7¬ó#Õô7„b }Ðã?räÈ•þ~ŠÖ3ù8<]VÌ™3çqٿ寛Mìªÿ}K¾€@Ìg&$ÌTE+¤¡s”éçq3·‹þ™Úwþ=õ"ò‡øc¸†ü`yE³Ë ø™=Uÿ¸f¨¥… Ñ¿Ýà«~_ŽýÍGˆ4 !ùÄámµ«èÛ͆A|sýÜÐÖ‡J2(ú«®®>öwRéC€:d=¬xî¹çfDÿ‰GTÌûþ©+¬ „xúwxûË/ÁŽs?m ‚àa¦?Ö¼‘À´?½Ò¨ôÏ…°çÂ`¼±Ùv¿½Ñÿ¢Ù³g/ç3ÿ¬ûû~O€¢ü¹í«=ƒ02¦k”ôVš~‘?¦Ð1‚Oý|xãÆZ¥?ÒÞ¨ôÇÇôüÌ*ýD6H~fÃÈ_« €jûKŒþízÿÍ–Xæc €‘) „xÀäöq)EÿLí;û¨ôGÊ© »A ±Ò‘¿ÓJÿ\Eë™~2!fþe”Ïš5+9ú7kù ä¦?ùf¬Ä…€„ä€Âx¡Œë¨3ÿ|aá´t®…:#7!Ÿ*ýí£èoݺuZÔ«Wúc#%ˆ?Ì€¢u¯ ÝÐÐ[ùßžý›õý»Ùù€Ä@ìÍŽ(oË„xzÿûÅÍgúc=nîLí»ÿZ÷¡Â_Ÿì‡ÿ¨ô×·òÅÚ¿ŸÄÙ«sÚŒüÅ4ÄTôÿ‰Aôš-óÅ$‹¿]äíu{„˜Ô1Æòó0Aß\?7´õ!íßÖÖv ×K)cÇŽÕÄ•þ~ßÉ/çÄuA6Äê¡jÇ¿Gåе³â¿@nù›O«,€þ~,Á´Ï;vÖ)ê-zŽŠ{\“„£ áˆ$b`8"BH~1x?ñmâßI‘*î+¿ô‘oüFý¥Vøa·?/Zÿ2rƒñ‘1@u; þ v¨ôG €^é·‰¦*HéûäǺ}œ“¶?•1ùÛ+¯¼²ÒEôÈ-ó͘ â¡ÿ"ñ‹oé}[”p81 ?ÉcÑ·~ýÀßMñ™gž9^ |YªÑ˜#øTÏ…?TúãÀt?ÐÐР ?Öû­*ýƒfÜ>Æ™¡ B÷ôéÓýwf úlAy €UÊ?ñsV&¿äný5‘ð±¢ñ/L¸‘YehH>Gþf⿟¢ã?~²Õ7u[ü—ÏÆÑ-ŠüPÜ€ÍmPÜ7nÜ8-åñ/**: ša-ð3{Úþ°Õ±K–,yaÁ‚› @ÞEÿaÊ™3—fôKš<¾ ÷ó 74a€Pü‰Lÿ:µ}˜Ù7E¥ºQk÷8ô|fƒb?ù¡âí~X>A±*ýý£›"—âœkC`·ÛŸ2mwÞyçL1Þñ/o¢ÿ0'f –tcJ~³¯OŽþ n~B#@húAÂßOL­GWªÙþ¦ýýËq¿ö Â¢ñÇz?ŠþpíÐæ‡B?ôùûQœ“›M#kƒÃ ù?­2(;Åxê_&¢€‹Ü"  hÂ[3ñOŒþ¹þO(ü}E_’„?Ñèf¹H­ÿO²ú;ˆù]|sýÜ0Εþz±25552fÌ-òÇûA™à—­Ì–FÐögc¢vß|óÍODÿVÃÜFÿœè#C`$þ—â_ Ækÿv±·ÊEþÉêx³oˆµëÄêÿ¬ÜÞQ€>XëÇ[˜6ÿÐ9ñÆSO=…‘¿Å?ôÑX €YÕÄà3ýäåDá/0¹ñ1ú'ùý‹þ%Fÿzv ®DËtû?ˆXrû_¾ûÅ_DüèñÇX_ ³Á?Úü0ÞÑ¿™ø%ZÏäc1ùЮðmùË_¦KßÂ?£Vp'3ÿCý‡1(þf¿œXÒÍ,Yücâ|ÝŸ€ä›0[û×—Ñô¯ÓÞWûÏ7˜}cLªãšÿÁï¶>}?´ûAÜñc¦?Úüô­’ó±ÀÏ챘‚ˆŒ‰ï¾ûîÌ•+Wnç}ÿyý‡ÉØM42‰¢OzkÔæDÑ'ù"ôfŸ3öShðõÚߘ®ÑfßÔ¬ú?÷hllÔŠüÍêc}õJDýV“óÕ`.Ú"­PŸß¬Úþ戻¡?1 ÑŽù–A·Ê$ÞÐâ&ÂO@òÙØ ý1ÿ¸êï/T3þMa];L|ªçƒè£ÚˆŸÃLŒõE›2%n¿&DÖïFÂ.õ/Sëþ÷*£ ï÷Ò#îZþb‚ÿòÅ­û›™€¸X§ùüÑ|2FÅÉéP}¶†f >ûÙÏŽRëÕÅV Ÿ×üñ9ìä‡k0ÞÃ~0ÆëýHý£Ò3ýígúœ0Jv=ÿj9eþŒ3>㿘˜ÿYeBý‡1àÆ™qõÓ|3‰™²‚¤¯Ñ#ÿŸ4i’iôoT˜iñõƒ‰0ëûXïG{ŠýPü‡%Œõ­®®¶¬ôÏwCà$õ¯ê:î¸ãþµ‹qáŸQ&À*ò]ôF`g̾6î ê§à“|~#P`ùG’n¤%b¦ QüómÜ/*û!þˆbùà `2"ˆ?Öüñ}Ü>ÿ|0÷»cÇ»žyï½÷ž\¼xñf1Ný;]q^@`g¬>O@húŠÉ¡Ó6ù*=Êì›;Yÿ£1@ôŠ6?}ÍŸÓ+ý!þ¨ôOü¾¬øï 2&0PV¨¯YuÍ5×`Þ?RÿÝ)Š wùËw`f$IÜ“72%Úô!Ÿü7’ü·“¾iÿägDŽt’ÈêMÀGèíG¥?„`_Jµ[¢e¥¦EÖÏFÂì¹vvvjÝV¨lJ×í·ß~«zÛ*wû3úc7õ/ÔÑØ €‘ 03bõÇý“<#n`’_ÿ‰¢ot3Ô– Êˡ95a÷«o胔?Œ@b¥?Rþz¥˜¢õL>ÎaÕ¿ÌŸ?ÿ‰wÞygX§þýåEyrC‹8¼Ñ™EDŒþ 1ΉD¥²U–¿¤ÆôÆSäìÖc°yófM¼0ÖÃ~ð³c¦?Rÿ0FÙVü÷Rÿ«¯¿þz=õß%é¥þCýç‹°‹äíÖú)þ$Þ.Sfõw9ú裇ʡ3\¿ƒTž Öôt?ÄëôJµI’Öãït¬o>Ìù·«úGêÿÎ;ï¼U™·©£ €F0B#@Á'ùÑýXÔšQ ŠÚ†›žLÝØÑï”>•ç†õõë×k[ùb¬/¯ÏôWµÚš¿^éïרÛ†¦ Ýv êÿ­·ÞZ-ÖÿÌ6û‰IÈGþÒ˜ÿ¹¾Oò³,XÜ$`e$´C¥¶‡š}Ä?Ìkþ¨ô‡øcÈÏ–-[´!Ý?fÌ­Ò‡Ñ÷Ïç?³¯ƒø£MÒ ¤þ¯¾úêÙr°ê¿GÌÿDŠ^„E¼÷þ‚i H¾ÿMD\DüÉ;œÒúÐ÷@ªÂV?þ#F`S$Í À?gC±$Ì”j™¥ç¾ûî»#¡êßMôïtÚ_hÍ €sS@H‰80Nßgn€Zë®2{€›ílsÁ§úÜУñW;ÏiÅ~‰•þØÍ•þ~Y¿'-@Uü?6oÞ¼•²?õo%üQaá !ÄÔ즪„Éû(Ðßì‹õõÿ°¬ùãkQè‡jŒõEµº^éÁ>hó³{LCÐ÷k‘ú·›ö§–W]{íµ‰ì¢«ô^4„·Q¿.ö“ÿG¬ €hiTúCøÑãb?¬W'Vú#ò7*xt*–aYÏwsN,Ømô£2Í7Üpƒ>ðG/üK§ï?o ÿh!™ÂÐ¨Ž–‚<î"áGÁÚý@b¥?ÖüõÇçûz¾ÓÇ¢å»"Ú}ùìÙ³o[¾|9*,“×ýͶü52yYøG@IUìEÌwÇ<°O€JyW:1^‹}¦ŒÒü~ô÷cH @ªôèÑšø#ú·KsÓj¨ôkiÅ¢E‹þúÐCÍëYÿVÑ^þÑBÒ5fFêQ £E€ÙˆàSýÚ––Mü±Þ¯G«¨ôÇ559¥óç³!pºËZþþøÇ?>(û·ù5kù3[û;0y•   „¤› 8d+mµà8¤™MMMZ‹Ä•êøYÐßÁ>½Ò?(Q·_ž+"»uÿŽŽŽæë®»îeÀ0ÐiêŸ=ÿ4„¯ ª€/TGZK~4)ˆ¿>Ö•ýXïGºÀÉxã|/ð3ýþh›´û¶O<ñÄ­ .Ü(Ίþ£3ñ·~vBH’À›e|LÂ¡ç­ ]àc€ô4&ú¡Ðÿ/++ÓÄE(öÓ§æC´žÉçŠA?0v¨Q¿3üñ÷äЖ?3#à¦÷?/£BHºf y@DÁ¹¾¯øu&"}½ÅO니=þXëO¬ô÷«ÈúÕèEvëþªÍòcµî?Cö¯ûwÙDÿÉUÿN¶úçcôO@q"ö‡ŠŠŠ’L<—Ækü˜ì‡õ~}¬/¦úÕ××k‘?Œ@£n?<ó0ìÙ+T‘åÖßþö·7'úMŒþS­üÏë@4„¬dTdœÒ}ÅOû )ÿ+VhUÿÂ-|!üˆþYà—Úãð9DþÈ®X¡2m7ß|óu*ó‚Þ@¬û'¶üY™€äÂ?¦þi!YÊôùœš„—ÑûŠ×3P鯷ù©Ês­f)¤û!þÉ•þF¢Ç?óÇ!›‚ìŠ*3›1cÆ-óçÏÇ¿‰ýþV•ÿnÖü%ߣBH¦ AD d±ñ“1€8­[·î@¥?ÆúêÅ~ØÆWµ7æU´žéÇÂ\9¨ø—·ÞzëQŠþŒúýíÖÿ¶ûåu !$ã(‘Lù¾’«}ô }ùë•þ}Dþ¨øGb¥¿ŸEÖ¯†Àá˜_d^^¿æškžã¢?3gÛý2õO@ÉVF ÓKÙŠöu ö(öK¬ôÇ&>ØÊâ´¿Yë" ³Ç¢ÝÛ%Û±uëÖEW^yåêÝ6—âû¢?³h?oÍ !$%¡7û¿ËB7‚â•Ø}­¾¡ÏÊ•+Túc¤omm­V臹þ\ÏOïq¨£p"þjy`ÃÏþóë1ñOý¹£èßJèYH!™BµlÅrýœD¥‰•þˆò±™¦ú©VFíÈÇh=“çĦI;Ó§Dïÿ*Tk \X‡CñO¥å©BH¶PÞ=6!k¢îô{`-ëýˆü¡b¬ï„ 4ÑGÊÅAY¿}Ð]¯?Úýn»í¶«?ùä£1¿NÚýìÖýÍ¢ý¼74„tˆDsÝn„%]±wk P‰Žõ~½Òëü´÷¡Ò3ý½ØÉ/̆À©ø+3ØýàƒÞ0wîÜårhÅ8Ÿùï6êg&€€’IñªÍ«ËêAv¢-c€ÿcËY´ùáÀó€à;V‹øñ~b± üR{¬SñWŸÎœ9óÖY³f-ƒÿf©ÿd#`ý' }Þ·üÑB²M\€žt3™6#5S^~ýaÆI]]–þ‡øÛ‰ üì ñG1¥“õÕW§?ðÀoJßv¿ä ~ìRÿqáº? !ÄìÛ·/#€L­ù#Íñ×+ýñ=1Ösý‘öG¿*çã(ྠà×׉ÁSƒ~Wc~Ÿ—CÛýìvùsjÌ¢}šBH¶PvÝ™0™0(ðCÄ¿|ùr­Òëûîƒö>´ùá’Èúõ¹b´occ£#ñÿý÷g_uÕU3Å<íof’ßí Š? !$‹ÄÕþîݽ7ÛHº 5>ü ÍFëüz± €U¥? ósb´¯ú;úúÅ‹¿¤v÷{´7òïã‚?»èßÌ$ =×ýi!^‰¿þŽªîîT£s wͱÛ.Æ‚¤·ùá|Hóc¦?fùCüõJÿ GÝ~x®0YNÆû‚¥K—¾|ÅWÜ£Þ5ÛÚ×éö¾õK@ñ‹à'\‰n›™Hu€SáB:æùãÀÿ±Ö5ûAüÆú²ÀÏÝsÅÿU­‡£}€j¹|SøMÿ.›è?Õâ?£×%Í !Ä#Çp•b˜ àtK Û·oׄ©€*Tûëâïר;H™üþ0KENX¶lÙ<ùß©×"Güµ÷ ¿“ˆŸE4„ŸdZ­„bm¶ÁN*Æi~läñÇ®~øÞèïÇ.~Xë7ëËõ|÷C›ŠýœÖq,\¸ð5ßÿ>Ù¿æŸ8ßß*âwýÇ„E4„ÿ™%­vQdº@èj9l#«ÍÇ:ÿĉµb?LùÃô¨ÛÏ×µç8ÄçÏŸ?óøÃ ‡âŸJÚ?YèYôG@É5*=Übg–O%ÚO{Ì#ò‡ø£ Å~hóÃ÷FÔ3m¡ Rf!•窯÷£“Âé)ÔŸn¼ñÆç\ˆ¿“´¿QÔÏ¢?Bˆ—¾A´•øÿ˜ Ë @&: JˆüQéý( ¢Š5#€Jÿ|Ö3õ8¤ü±Þï4åÙþÏ>ûì]ŠyrpÈ“ùþN6ûaÑ !ÄçÆK–‹ëoÞ›À[LœCÁ"£1B;tñ·Z^ !°Þ"»â´Ê(ÖtÏ=÷Üô /,–C‡ü¸í÷§øÓB‚h”p4eÚèÂáÇÝüð ÷Á,]üÝŽ¦!8ôwƒìŠ›n Õz¹öÿ÷o\²d 6Zègm~FóþÝTýSüi!9Žø“‰©b±ÝVLe ‚áÇŽ~¬óc¸Æùb­Å~º°±ÀÏýãæÇ`kýjƒ¥÷ñ‹_ÜÖ„µ‚ýâï$ê7«Iq›×"¡ „x,ø’•ÅUŠ~O& ÒüzäýPàñÇ:?ªýqx!²a+ðÓƒ ¤üÝìÔ¨ CÚÔçÉk®¹æi9Xì×#Ƴý­ÄßIÑ_ÜàuFñ§ „øÀ$¾© xvÛEóNg@œõ£¿Æ RSS£õøCàõ#ú×…‹ëù·ϣµÂïvƒ&Õq±ýþûï¿ýÅ_\"SþÝ¢µÿÄ·f›ü˜‰?¡ „dYÜ#&7̨Êü]vßkÍvò µ£}!þØÕ…~µµµšq@ê_¯ô÷«ÈúÕ £‚¿T–bV¯^=_õ÷ß½sçÎF1NùGm"~#ñONùÇŠ?Í !$¦@LnÐq©·ª¨²S µ©ÂC„¬ –”1u›ú ê)LöC±ÄßIö€† /ˆø!ü©ìÇ ~_­sæÌ¹ÿ¾ûî{S¬·ò5û¿•ø;™òGñ§ „äHôͲFo1  Q õp+`&h*ºÔ Òò‡˜É©Š? !Äg‚q)øÉ)[-ÂS©û­V'Â:4D ‘= âAüñ9RÔ àÿ\Ï7fJ?RöuÔVÊ ~øáÇß|óÍÕ½Âß%Öã{FývBˆOÍ€þ³­WoÞ1U¸·Íî~ žA¥?„K‰Vè‡V?½Íëþ~Žºsé#S‚#¢TÁå†Y³f=>{öìåÐi~fsûÍD¿'AôôúSüi!4 É7gí&¯Öð79µ0jÉà@…?Rþfâo'–AZÏwúXÔGè¢ÌI&D¨VËj÷¾Y¨îW3áwbœÌô·šðGñ§ „Pø“·D?øàƒMßùÎw,¿‰.þÈôïß_[ë‡èCü+ýƒ­§j^ øz]ðS­à7CkÞª&ù½pï½÷þ­w÷ÆÄa>f‡[á·Zï§øÓBBbú˜•ÎoQâÕ¬Öï«ìÄëü¾Dñr´îöqøZ½&B›©?U›±éí·ß~ùÎ;ï|]«Ý¡ðÛmÝk¶ÖoõSüi!ŽünÖúÍ>ªzÏ·©ú, @¢0BüЯŽ%€Ä_c4ø'h†"yüœºèëc‘³ý{S†lѼyó^™1cÖø; „?æÂX rÔïd;_Š? !ħ¢¯i°:¢ª|‡2\,A“ÑÍ€nô÷Í ‚׆@ùd±Ç[ÙŠêÍP©ýæåË—¿£Šû^]°`Áfé»aO, ñ¥õSüi!4‹¬@⡉€*òÛ„ùý™ÂI¤œh ÿ¯ˆD·údqO|« º~‰œü’TÿÖ­[—«Œ·zè¡ù*£’<À'f¹Û‰½UÄïDøjG(þ4„€eì {ÔT¿µS§NõZ}!Ä^ƒÁK‹/~gæÌ™o¬X±b§:µ/Y¬í €ð[¥ûÍ ý(þ4„€DúNf¦ÿq¨ôó§gžy&¯h–~OjÖ†O?ýôcµ-ïü÷ß)þné;±Ï(B7~«%³ïc'üN·ó¥øç€/!ÄæÞI: ŽÂÞ£(á(î=ÊTEõƒ>øˆè3‚—4}TWEç–-[–/[¶ì“^xaÁªU«öÈ¡ó˜­É[e¬Öõí"~'é~Š? !$ âÀàm L€:*Ž9æ˜úÓO?ýØúúúÃKX‚P+NŒÔÕXÞNõ6® ðÚ•¨koÕ.†8ÚÔN|Úû*šoV#v›Ô|ý}*}ߨÚ÷*¡oRkø=6ÑyÜ&²6}7Ñ¿]V nó¼ì*û™ò§ „„܈X/Õ$‹~âÛ‚$`$üN10 f_“ü«ŸÙLÄŒö>°q}z‘Ñ[»iŠfÑ¿YzÞ­ ˆ;ˆöcb¾çƒðSü} çBœ`40Y$"IïG“7ùq…½_ëÔˆ‰€[}˜|}º×ÂÊ$~,fò9'‡Sñwc쾇“ç%BH~Š~¢°™€Ä#j"’1ñ/0È2ˆK3 6ï§c¬RÛv†À‰ 0‹¾Ý.8z ? !„¤ '§»ÍÐ…Èmôï$•ïÔ dÃ8Í ¤ý»1F-{©Š¾Sá§øÓBB˜0,&Âo¶s`AÂ×§³öo—pbÜ·‘¿ø‹MäoUWàÔ¤"øN«úõÓBHÁˆ™|>Ñ87…|nÅ?’Ÿ5Uñw’ ˆ‰»e7n¢|Fý4„ ¼m@„=f"þqáwý›™€t²V·‹tÍ2é.¸É¤áSø !$mCàÆÄ\FýÙŽþs±i3ŽàÛ‰=…?Äp!$•û…U+ž™°»}§Q¿W~1"™| ?ÿ  !ÄõýÂÎDl„¾ h?Õ´ÄÅÏçTSépcÄÅÇí„>Õú(ü4„Þ3›;Sà¦Âßíz6ZÓÉX s<…ÿ»‰îÓÕKñ§ „Ç&À©É|¤Ÿ©Ö¿l™§ÙtDž¢Oh!žšgc{~>U±wõ§[`%°™4©<…ŸÐBrj2!îN¾¯Óç•iŠ»s'Ÿs"òñ6B@!Žï!nÛM$ï4ÂÏFÚ?ÝŒ@:Q{ª‘}<ÅŸÐBHZ÷‘TÛm4Ÿ­h?S&Àîÿ©~Îé¹)ú„€â #à4Bwŧígº0QΤ¸Sô !Ä÷÷7‚J4ÉÀsLWLã9ú8EŸÐBqo‰dùó^ÝãÒÀ3Y GÑ'4„@Þg"YøžÙ¸ßųôõqž !…¼„~ Vâ|,!ÌBByÿñË=-îÓïE !„÷%ŸA¡'üC#„߯(ô„P„²{ÅB!„B!„B!„B!„xÊÿ½Œ£ŒXçIEND®B`‚qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/dmg.iconset/icon_512x512@2x.png000066400000000000000000001741301347155106100310240ustar00rootroot00000000000000‰PNG  IHDR+ƒøIDATxÚìÝxdW}7à3õ•¶w¯{ïÆÆpÌGsòBB ‚ ùZƒ˜lbBŒLy )`=´ÐbÀš{Y—õºlß•V]óÝ;»kïÊiFšÍœû¾ûÌ£Ñh¤Õ½çÎèü÷œsC²*gÞFÁ.@gðú`" ð: Ã(À뀌 ($¯S2F °¼6Èa€"ÈðëÑ{@öŠpA€‚hòס×9@œ Mös€×Ÿ×2 XÀ  @¼îrMú{(Λïÿ(D€:¿Þr^ë̲ /ÌÁÿ‰¼Îjð½^ÓÙU¨ñó Ê¯±\ül²Sà×#8@^[~On^×Þ'澘ŸíÏ*ÔàwÀëªÊÏÏUáÿòZˆC5ÎêªôàõT…ç×âk^ÿ þj…Bx-Õ¨ðÏUñgy/hþ‚¦Å}¡FA€@^C³(ÖsüŒ\_çÞâ*ügó˜@T©øŸiá_­pÀû@óåê…*=G ¯þ•~>ÛÀû@ã‡3-þgûy5~G©â¶…5CïÍTzf¿0ƒçUú˜@™|Í”{¾ÜB¿Ú@-_ÿÞS…{íÞtEy¥÷+ùZ¹Û*@ô¯•jžáŸêþž[K…ÀL_ûÞ+æ&(˜É<þÉŠùÂîÛøîÛl!€ÿÿ•Üßû±´èoMní»o-»o•þ.Þ š+˜Iávüéç£Ém ¹ìL"ÕjÀ¬‹ÿrβ— Ê-üs{ÿmÉ­ëÌ/]ø¦Îýæ½ZP®ïžò…»ѽú˜…Ý÷ “<¶wŸSÐ @ñ?õc•œÝÏMñqÏ™ÿî3ÿý‚7'Åÿ«4j ûN#XüOVì禦 „Ètñ_nÁ¿÷Çü>Åÿ=—h"f e’>éT#„PüOóX¥Cû§;óß¶»ø“â€Yöus“üaŠ@ PFQ¯È€â¿Ì Ôcû?ã ŠªLWôçÊ Êýhêâ¿’!ÿ¹ €üÞÅ×=¯ÔDT9(5쿜À(d¾øŸéÙþ½ï?:ìÿŒë/økÅ?5 &ªtø%!€€@ _üW²Ø_©â¿œ¢ÿq þqýùoê:¨çÏ45 ¡ô¢€!Tg húâ¿Ò!ÿÓ{ù?ÿ¯»êUüPíþoK(½ÀdŸWs*€AQÿåœõß3çWñÿùóߨø ZBé)“…!ÔfQ@}ñ?ÙçûžùO‹ÿƒÿÔ¬<Ý!L=% ÔÏ5 @™+þ+ òŠÿWh"æ((L7(þÃãÏöO~æÿsŠ&˜„PÝQ )ŠÿÜ$o !”?Üï3ÿékpÞéŸ;ÿ ]‡(þ¨[žˆ¯ð{«9 @8 €¨Šÿ©€G‡ý§Å·â€úõ‹§[pº>s%£@Sÿå.öWê±=Åræÿ¼´ø¹& Nö.þ'Ž(LÓwžlxÿt£ÈDñ?õ™ÿK‹ÿùŠêÝ?žl$ëÄû…iúÏ…*ý.Âd ø?Tñ@Ã…÷'*g‘?…}ƒj± Pü+þÈT?¹eŠ~ëd!ÁtýéÜ4}ðœÝÞŒ@ñ_¿â^Rü¿^ñÀj ûÎÿ/Õç-LÓ·v†¿Iÿ•ÿåÞZÿ4Xyº³ÿ!L?`ºþ·³þ Èÿ3+þ§{óLõ½‡ý+þhÔ „éרóy˜ä9{>ŸêjSý>FÔ‰(þÿrSô…C‰>q5ûë ©ŠÿÅ?ML̤¿¢.þ­ö@³S…Sõ»Ë½Rˆºø™& ‰€rB€Éž¯à@ôÅ‹â€È€©úÌÕê«#€¦+þsŠÿy§ÿ«â€¦ ¦{N%!@n–¿hªâÿõ݇)þhŠ T_wªyÿ¹*üß@ñu¦šËŸ›¦O­°€âš¨ø%úÃ¥úÑ!”^$p&ýx ø€ö­seþ³í‡#Å?4PÊ*-îPü@ÿå\(þ  ûÙSÍëŸnñ?€ÿФ!ÀLæÿϤÿ0ýíé.ïWêk }(þ ÉúÞå† (þ ÉûÞ¹2¿& €âš°ï=Uq_é:¹*þ^Pü+þ Fýp‹þ @ñ÷Ãs3øž‰×s¤ÿЍq]/Å?4a_|&W@Š(þ Yúæ³] Ð(Þ`ÿÐ`}ó\Šv€Å¿â¼¯x€â2Þ—GŠPÔ#À‹â@€â_ñ ÑoGŠ À†â@€â_ñ @ñ¯ø€ÆêÏ#Å?¨à…¯ø øWüPü+þ ¹ê(þÿÿŠŠÅ?€Å¿â@€âŠŠÅ?€Å¿â@€â_ñ @ñ¯ø øWüÀöÿ øWüPü+þ(þÿÿŠŠ(þ ø øWüPü+þ(þÿÿŠŠ(þ ø@ øWü Pü+þ(þÿš¥øŸî{ÿ"(þsŠÙ ÿš¼¸Wü Pü+þd­ø/õ=Šÿ ü‰÷ÿ"/þseÜÿ0¨FñߢøÐþdÏ/µØŸâ@@ÿ3]ñºùþŠ TZüçBesþ»ÿÍ©Õ.hª¿ÞÅË>Åÿ¿÷†îCÿÍÈ€æ,þgò}åùWühÐp 7Åsf2ä?§øPÿ¿Ü⿜ÿK…{ßZ÷*þ_¯øh~Öh®â?Ì øŸ¬ðŸîÌë^ÅÿË5 0QWKgèÎw‡žäÖïÚ}^ñM$ýøè™\kñ¹{t´t„ÑÂh+Œ=úØŽ±¾Gï§ï ã…ñ°slgòµþâÇã¡l Ùù€L‡¥FTRøï{©?Å?dJ>—‹Z„%m‹Ãâ¶…aiñã¢äã¢âÇ%É­7ßzZçí.ôssò{‚$èK‚­£ÛÖѭaÓÈæ°ydkØ8²%ù¸ë–Þß:ºmŸ @@3øSù¥«tÑ?Å?d È_Þ¾4¬n_Vu캥÷ê: ìß±:´äZšbz[{Š·ô÷Ÿ.,xdxcX?üpxph×mÏý{ïOF ;(M”;ï¿ÜÿÿEÉYüû‡wë>8ÚuPXÙ¾<’ŸÏÌ>HÂ=AGè}|8ðÐð†pçÀÚpçε~Ü”ŒPÏ¢¾Ü¯M7ôªï+µÚ¿âšÌüÖÞpü¼£Ã»‹ýôc:”Ÿ©Ãý:Voç,<óÑÇÓ©{€ÛvÞ~Ówsqª€€F rÓ„¥n-Šh>é¢{GwNžB8¥÷„âYþ¹š“›týƒÓÚžN›ÿ„GK§ ü|ǯÃoûn ¿ìûmqZ@,Å$ÕSå/õqº[Ë^Åâ[GK{89)ôOR8±çØdÎþþ þ9´nh}øÕŽ›ÂO¶ÿo¸qû/à+ÐD¾{ÊÎM>lMn#Éml÷m|’“Ý “|œì&ÜSÜeêŠð•ß ]]Ø1Úg§QÇ&gÍ €¿‡UxN% ªX`†×t·W®ùã°0  –ÇZzéÈsžY Ò0@ÑD Zr-a¬0fG(QèO·øßdóÿË € Òu`xÍþ¯(Ó†zémí uÀ+‹ÁÓU÷}$Ü3x¿B“wrtAÙ,ìgúü©þs@¨²Ž–Žâ<ÿô²~­¹¼œ8¾çèðOG_þåá/†O?øoa´0j§Ð”ZrIÄ`€``VÏ)5ïªð˜ÆAû‡KþËâÙ˜ó?ܹÖð‡+/N.xR¸|íº¡õv MØéi±æ€wßæ ¦þŸ+ñX©‘@É[.9ãQøÈÑW(þi8Gt>zôû‹Ç(ÄÔÑ vŒhŽ¿Ó­þ?ÕóM€Xغ ¼ñÀW‡Óœlgа:ZÚ߯ù“pBÏ1áÊûþÑ•hé"€ÌÁû¯]0'}=‚\p˜‘Óæ?!\{ÌUŠšÆ“ž>zÔûÑ݇Ù4I‡H@ ˜ésr%>–z®JH/¹ö®CßTÍdyûÒð÷G\Î[|¶At@uAæ‚)ÍLUÄOuÆ_áä“•ý_ ¥~β§Û4­ö–¶ð¦ƒþ_8¸ë€ð±>“,²n™u´C“ÓPªÈ/UØOö¼rWþ7v›ßÚÞ~ðëÂI½ÇÙDðG$^¸âyauûŠðÞ{ÿ! Û)4œ]€9zÿ¥Y‚€rž;ÕâÓ=™t`çšðGþ­âŸèœ³èIáïg2e¾A“wsPê/¨³ÿP¦Ã»8âoªŽvQ:zÞáÉ1~yXÒ¶ØÎ ±: ¦2V¨Wã{sSÜŸêì5~'hjG&×P¿ò°·‡Î޹:÷KF¼#,ÐP"]P€` –?«T@™s|ÏÑáý‡¿=ô¶öØdÂþ«Ã|WXÕ¾ÜΠA: º ¦+îK áŸêì¿¡ÿ°—{Ž ï=ìÒÐï¶3È”•IñÿwG¼Ó”£Sc €€²çóOöy®‚Ÿm™”.ô—ÿ]-v™´¢}Y¸2ý²¸m¡Áw@uAÔŠyÿd^z]ôwò†ÐÑÒngié4€wúfAsÛ11@À¬‹ôrýsöŸLI?{Ï¡o =ùyv$ŽHÁ¼ì׆|.og0GÝ3 rÓ¥žë¯/Ñ›—ÌõO‡ý/o_jgÀ^N›røËþÌŽ`Ž: º ê@&´æZÃ;’aÿ‡thgÀ$ž¹äÜð‡+/¶#¨ÇÄSïÓ=ž«ðû!z¯?ðÏÃɽÇÛ0…—®~a8sÁíêÜÕ0[S…¦)ÿgéáüÅgÛ0íŽ\øëƒþ¢¸8 Ôó¸@@å…~©ùÿ¹ ‚ˆJ:äÿUk^jG@™zó=á­ÿUqÚ Ô¥šÓP«‚ÝÙ2£;ß.;øu.÷:jÞááûý¡" jõ³ ^¹ð†_öï\mgÀ \¼üYáÉ Ï°#¨CT@ h¯ÅÏÏÕùw9óÜeÏg+^`Lráu^–´-¶3¨í±æ*¦-òs³ü~ˆVº€ÙËö{‘³”®ðÚ^iGPã¨n € ›E}-¿ß¥ÉÈ )Þ˜¬bÞÕÒig@œ±à”pá’§ØÔî}Û"€ê\3A$ž¿ü™á„žc쨢W¯ùÓ°¼}©A: º!sÁõ~â-è'[ñß_[¢³ºceøÓÕ†þ7¢¡ñá0\.Þ/Œ‡cû|½£¥#´µìú3”Oþ¥Wp qÌËw‡×ìÿŠðæ»ÞmgPƒN‹. €€© z`’äë|UèL Iêc¤0Ö=6o F6…‡‡7† ÉmóèÖ°c´/ôõo;ÆúÂðøHE?;ŸË‡žü¼dú¼ÐÓÚ“Üï‹Z„eÉYèemKŠg£ÓÛŠöeÅçQ{{¦|cÓ÷ì ªûþm@U üU%ÒÂäÄžcíˆY7´>ܾóîpÏÀ}áÞÁÂÚäãúᇊgóka¬0¶n/ÞÂÐÔÏ]š¬R`×þá Îô¶&ÚuP8¬ûК„Tןí÷âðí? ýc;í ªØaÑU(Þëýsüõ¥i¥ÃÅ_¶úíˆ*IÏìßÔw{ømÿ­á–þÛÃMý·…í£;ö÷Ý8²¹xûùö_=úXGK{8¢ûÐp̼#±óŽ 'öS\ÑžÙY˜ŒÂøãUÿ7\³î“vUÓb*@¹^¼ò÷Ââ¶…vÄ,lÙnÜñ«ðãm7†·ÿ²éÏð¦kü¦ï–â-„/†–d•ñúg.xbr;%žŒpÖqfž·ì™á뛾î¸×Π*LP§¿¹vÍnMÇêdåÿ‹ìˆØœýßÝòÃð­Íß·í¼+êmM§*ÜžlczûÔƒÿZ\?àÜEOç->;Üu€ƒ¡éú —ì÷Çáõw¾ÓΠ*\@P–?_óÒd®··¯rFÃ÷·ÞœÁýNøÅŽßÔl£{$Y¬ðŸþ÷â-]3à‚d ‰§/yªie:eþ‰á¬…§'ëüÄÎ`Ör9SÔäo¬]@LN_prñÆôÒÅô¾¼ñ¿Âløz̗ؔç1w Üþ1™Óþ‰õÿ\ .^ö¬°çj;fé(€¶ý¼*Î € †Æ\x¹…ÿ¦•^žïº¯ßÜüÝâ¼xJ _ÚððŸ¾Y –þxÕï‡#“…™ÜªŽá™KÏ-î3˜ ‹¨uíMî)‹žé:ÐŽ(!]µÿ_þbøÂ†¯(ü+THþ¥g¶ÓÛ)½'„KּıV­üÝðMÂ%fÙ)± Àœ¿Íñf•ÌMÏÎòxépìϾþ³açØ€R%éB‰_IÖOøÃ›ÿ¼¸ŽB:B€Ç¼pÅóCGK‡ÁŒ¹$'€€JÿvBF´&— {ñªß³#ö²slg¸òÞkÂknk¸gð~;¤FÒ—ŒxÃS¼Š»,n[ž»ìév3 ˜Ì…É¥ÚVw¬´#v»mçÉõׇ¯nú¶3Óuòóí¿ /¿õµáGÛ~jgìö‚Ï ]-v3$L|“JæþÿA2ܘ] Õý[²Èß_Üö–°~è!;¤ÎÒÑo»ë}áCë® #…‘Ìï­óÃ3’+ÀÌ: 3á/(Q;kÁiÅKe]º°ß;î¾2|øO»ûJC˜ëùJø«Û/ ÛF·g~\¼ì¢bHw^7€‰þïŠgg~¤…æî|gøþÖ â¦þÛ«nûëpÿàúLï‡4œ{ò‚ÓÌ êü€`/ÇÌ;"¹™é}pïàºpÉ­o,®öOcypèáðÿnK¸9 ²ì÷VüsÀ„Â"Ûgÿӳ˯»ãíá¡áG *ñº;Þ~Ýwsf÷AÒe=¨cPS{¬l_^œÿŸåâÿ¯îx[Ø4²ÅÁÐàLJ›ïzw¸¥ÿŽÌîSu¨”€G]¼ü¢Ïå3¹í÷ >^sÇ[ÿMdçØ@xãîØ¹6“ÛŸ†uËÛ—:*ÓÞÒ.Xü”LnûöÑá-ÉÙä-#[M¦o¬? ð®°adSö:Épîg,yšƒ€ Ž€ qÎÂ3CokOæ¶;½¼ßÛ×^zÈAФÒQ—Þõžâ´€¬yÆ’sÍë¦lFvçen›ÓëËÿí½W‡_î¸ÉÐäÒiï½çƒÅ6Í’t À)½'8(¯*,¬îXNì=&sÛýÅ _ßÞü@$¾¿õ†ð…G¾’¹í~f2 Êa€ 'SÛ<<>ÞuÏÂÐø° 2#…‘pùÚ«2Õ¶­¹Öä5|¶ÆgúÀõû»kЈÎ\ðݤmQ¦¶ùÃ|*Ü=p¯ÆÔ½ƒëµë?›©m¾pÉS5r_ØðÕpçÀÚÌlï!]†;×hx¦d a]-áŒù§df{Ç ãáïîûpñ#q+Œ…Þÿ±L]à)‹~GÃ3uÔ]OZxjèhiÏÌöþû†¯%—‹»[ÃgÄoûn _ßôÝ OÒèLÉ"€ Þš¡3†}cýáÓý›FϘ¯ÿL² àP&¶5N€’P#@6õäç…S矔™íýç‡ÿ=ìíÓð³ydkqäGV˜ÀT¬07Zí`®µðôЖkËĶnÝþ㑯iôŒúç‡þ=\´ô¼Ð›ï‰~[Ÿ–|„ïœ|½r=¡÷¸G¯KFÌËwOùüt˜ô2“%;´É׺Z:¦üiØ<Õõ;“ïo›âÿhɵ„y-SÿžÝù®âóJiOþÖu$ÿÏ­ýw„WÝö×@dÏS™™mýôƒŸ ãƒ=£vŒõ…ëùrxɪD¿­«;V†ÃºÎÔ(ßióO.Þ²jnî¿-Ü5pOôÛ™Žò™ê²hEcF k²²Bø—Íý§„¯oúNôÛØÛÚS\ xLÁ€È’tèÿá݇D¿é¥ÿ~¸õ§œI}sógâʧfd­(—5)'õW\0úoÓ÷’ÕÞG58“Ú1Ú~°õ†è·óÄÞc46Ù ÷¸Llçmþ¾ÆfJßÞòƒè·ñ˜yG„Ž–v {‹ [À±Ñoã}ƒdb‘7fçÆí¿Œþ‘m¹¶pt»€` @dÄ’¶EaMÇêè·3 gv™½ÑÂX6¦ô«±aO` ²"+Ãÿ¿»ùG›òŽ•-?ÊÀë^{Œ@f€ œ ¼cçÚ°nh½Æ¦,¿ì»©xň˜Y3f ²âÄ Œøñ6—þ£|épà¶ý"êm´<¦à*€È‚%m‹“ùÿ«2ܨ±©È 8fŽï9ZCC° 2âØ œÜ8²9Ü™L€Jü,¹ÀHa$êm<ªû0 ÁUGÍ;<úmüáÖŸXà‰Š Œ†_ï¸9êm<:¯(+0™ºã/~²ýš¹!òcgaë‚°¼}©†&ó¬€èå’Gtõ6Ž%×tÿMß-›ùß¿‰~î6 \Ñ;¸ë€ÐïŠzoî¿=ìÐØÌÈÚû–‘­Qoã‘󬦉 zY˜ÿû‹ œÁ¥¶EÁ¯úâ^ÀB€` @d@:þ¿Øñk ͬüïŽßF½}GtZœ™Œ@ô@ä#†Æ‡Â-ýwhhfÄ=Š$t@ç~šlF fm¹¶p`çþQocZüF56³²nh}ôë¤ë@¦W@Ìì\Zsù¨·ñ·ý·ihªâÖwÆt Èx` ¢îðgàŒßͪv,ÝùûÁ™Ls@DíÈ;üigî&€2ߌ ÛÆŒ€ yÝ7ø@Ø1Ú§¡©Š[’`¬0íö­êX:[:44™U° bû€[ûïÔÈTÍ`rE‰{×E»}ée2 € /˜€Hõ¶ö„¥m‹£ÞÆ;îÖÐTÕk£Þ¾ƒ#¿*L€Xš¿îØ) ºîÚyOÜ€dXÁ@Äê È/ù•.x×À=šªº3òcê —$ÃÆŒ@¬èÜ/êí{`è¡°sl@CSÝ`çÚ¨/¶_ÇJLf\±ZÓ±:úB ªmÇX_xdxc´Û·¢}Yh͵jh2É€ˆVìgúî¸W#ãØª´’kI.¸\#“ÍÀ€ˆQz†/=Ó³˜/×ÆÜºoð¨·oµid50qvðWÏôÅܯ¡©‰û#Öt¬ÒÈd301Ú/òþha´¸ ÔÂ}CF@”€€ˆQìgøî\Æ cššˆ}z‰+U®€8€Î¸óÿ©¥£}aëèöˆ€Õ™L2QZý€42ޱJ}˜4° b´²=îË|­6ÿŸcCG»m­¹|XܺP#“½À@Ä&—ü[Ú¶Xq³ðÐpÜÇØòö¥™ìÖ@l´ö†Ž–ṽCD½}ËÚ–hd²Ì‘V»¨YÇ>ò3{Ãã#aóÈ Mm€ÈG,3€54>† #“~­lg²’ÿãçñ%ÿvŽ ”øyÃþ¼Í#[í`@Äey[Üû´0+ 9Qããl(ö`nF<í7ô~ùÎÉ×GÝîWÝ÷‘b=6Ù™ð¤°îëŸôûF £a0)Ì'30>FK\–µotòŸ7šü¼ñAo4€ Y;öõ²~È€ÔÞ¦d”I:Ú¤½¥-Êí[n @&}yã Pæ€5€Úuì#ÚûððLÍ¥EÒ†‘MÑn_ìA!@6ŽlÖÈÔéX‹7Xj€æûêÞ†7idê Ç6-i[Zrº# šÚÒ¶Åq#êD<Ú$ŸË'— ¯‘@4³Em ã†7jdêÄ6-j] ‘@4«Ž–ŽÐ™Üâ.ʬ@޵á¸5#@4±…‘wèwŒö…¡ña M}€Èæ…Í+öáÿ›G·jdêfËè¶ÈS@4oy‡~k䎷úF€Ð¡oÔ‚lD@ýìÃã#ñ¾_´ @4q‡>öÛ52u>æâ ˜ ‰€VTÓ¶ˆ9—ÐÔ@äS¬@ݹx—ÐÄzó=Qoß6#TMO~žд@kÜÀöÑ™ºêëvÛæå»40€æíÐwG½}}c;52u•^ V-¡5—×È gÇXŸF¦¾Àø@ÔÛ×ù{€x€–ÈGŒökdêŒÅÌ€h>¹ä_W¾3Úí+$ÿúÇM ¾"{h ÎŽ|r&/ bÕŸÌÿ/ŒkhêjçØ`ôï€Ð‘o¸êÄ}ܹ @b™úwÑ/èR€  fp|H#SÿÀ"€€h4]-qŸÉÔÈÔÝ@äÇ]gK‡FÐ|ùv…TYì#Ú[Ú42€æëÈǘÀœÉé%(cÕ‘3@óuäc0fõ—^zrx|8Úí3@3väsF@-Ä< ö‘C "íÈÇ}&/æ³°4¶þˆ/Ø! #ßhF £™91ñ±ûÈ!:òMh<ŒidæÄX!ÞcÏ šPì#Æ’ÅØ@På÷ #@4ŸØó5€9 â Ÿ,  µåâÊks%ê5LÐ|ZsùÈk0WÇ^¼áS‹. €&|cÉÅýÖ2f@{Þ7@B>ò·#pìU_.ù€fëÈçàØ«L>ò©C "}c@mŽ=k ä£à*Ìѱg @4ÖKÜo-1_Š"}Òb Í'—‹»#o€tHŒÐ|¢¿ €Ë"€ þ޼EqìÕ¢C¢K éä"kÌñN?ÉY@ó)„¸çÈç½u2WErÄ5òx°¶€&ìÈÇ}†<ŸËkdæèv¼Çž©5 š1ˆ|•ü¼Åʘ³c/Þ`ÜÕ5@4Ÿø§€ Ú\]@3vä£ `®Ž½xÿl ù¢_À['s£5×q`€¦3nÔèØ‹÷϶«€hBcA59ö¢¾ €@Ó)âžÐb@æ*p@4TG>¸ *c :òŠ0xô¶5Ð@†ÇGP­F ‘Œb¼u2WÇž5Ð@†Æ‡ã.Â,ÈœñþÙ3@óŽ=0Ç^ Þ7F40€f3Tˆ;h ¨þûÆøÐlb?“×ÕÒ©‘™m¹¶h·mP  €ÈGtå»42s¢;âðI # 6Ç^ÄáÓàø Ð|@Ü#ºóê/—üëhivûb¿z€8€Ø§´˜ÀwI𔆱2@ˆ¼#ßm æ"ˆ@  Œ †ñÂx´Û—®Änõâ>æLЄ É¿ØG¨·Ø§ž Ižà¼|·F¦®:#Æ52€fûB€FPgó"°c´O#€hFÑOÈ ¨ó1qè4Z3@³êëzûzó=™ú‡N}cÎþ€hZÛ"λ°uF¦®æç{#~¿Ø¡ Zí 6úmQoߢ¶ù™ºZØoèdþ?”%Wæó  Î@ÜgôŒÀ1WÅÀ˜I¡_É÷@ÍlÝõö-à˜@cüeÿ &¶EÄ<›Æ“ÏåCok¼ Oš€¢¿>€`&€Ôõx›ŸôrÑnŸ(ü€ a™@}€¸·£ýE¸ P±¯ÇnM†eC]€È§œ@Ä…C áµéÐ'szÇ ã¿›ç‚V—¤>bq²Ý(ü@ó*$ÿ¶G~VoQëB M]Ä6õ€ÂªŸWéMÔßæ‘-QoßÂ6#¨# )Šÿjû³ùYi­Ÿß}Ë €šÛ8²YQUû›"¯ úÂ?7ËïÍÕàwJ ÿ¶~ô£Çyä‘m{jW3-ÊÔIÌaÓÀø`ñMXøÏÅ÷N§ewßþéOú¥ù|~à¶Ûn»iÏÿ+j G´ ¨Ó±qàì?)þsux~zk[±bż«®ºê²®®®³ÿäOþä콟$jŒlŠzû–´-ÒÈÔ'h‹9Ø¢PøWgÎÇsŸûÜU/zÑ‹®MŠÿ'%gþŸ¿eË–áäñôÒ\ c? ËÛ–idêÐÓÈ…¥‡M2\øçªô»¥óý;_ýêWwî¹ç~º­­í;v|鵯}í÷“ÇÇö~²¨™ØG¬h_ª‘©¹Åm C[®MÍQüçªðóÊý?÷Ì÷ïxï{ßûÌcŽ9æš–––ù…Bað?øÁ»’LJÂcgÿs ¦6D¾À²ö%ų³…]#ª &–G4 PøÏ|¾rëþÈG>òûí·ß›Ã®‘aÆ ¾æšknOîŽì.þ÷I jbÛèö0R‰vûZ“uT­@퀸§šX€È‹ÿR—ù+瀹In-» ýŽäŒÿ’Ï|æ3×$Åÿ[÷ÿccc}øÃþ`rwxbñ_ì¿j[ VÒ3ã›G¶&Cåã-`Òâl£†ZcmK¢Þ¾ô="-ü«ñøÄç‹ÿ¿øÅ‡=ûÙϾ¶³³óø½Ÿp÷Ýw¿ó§?ýiÚ9Û+Èí¹oPSoˆzû¬@Í€ÈGľVQÿ¹i ù\™çÊüY{ ÿâÿw¼ãç^|ñÅ_›Xü üä/ÿò/¯“ ýßós@M­z8êí[Ù±\#SãÀ¨qá_iñ_îÏ™¬ÀÏ•ñܽ¿¾gØZüÏûЇ>ôÊ“O>ùŸóùüijPã7ÜpÃeÉÇÁðØÙÿÇý?¦5õÐpÜÀêö•™ÚcñcCãC¡l§F`.‹ÿjþÕ|,LRü·uÔQ ßò–·¼oÑ¢E¿7Ù7lÙ²å_Þÿþ÷ÿ"¹;Zâç@Í=ù€5«425µª}E´Û¶Ñhü¶Ånß³ç±â|ÿ?øƒ?8ìùÏþG“!ÿ'LöKŒoûìg?ûÞðø³ÿ!LX@ÔÔ‘ûu¨Åm Cw¾+ÚíÛ0lþ? ]üײðŸêg¤gýÓZ½ó²Ë.{Z2äÿêdÈÉ9ëÖ­ûà×¾öµõ»‹ÿÉ~æ£!€¨©Ø§¤—ìléƒÉPf¨¶Ø¦õÃid±ø¯duÿJ>/ç¹Åùþ݉+¯¼òUûï¿ÿs¹Òuûððð]W\qÅÇî…ÿÆ'ü\Wê+]àk`|0â¿"¹¨çh3×@ÜÇÖú!u+üg[ü—Z̯œÏ'»?ñóGÏúŸuÖY«?ö±}ò€xËTÅêæ›o¾|íÚµ;ÂcsÿsS…F5÷ÐÐ#áà®".ÒV…»îÕÐT]ìáRìk„Ð0Åÿl ÿ©+÷ŒÿTß“ß}ëxÍk^sê9çœómmmûO÷ ÷õõ}çÒK/ýÆ„ââüS€:wò“i1tî§‘ÌÀzs_øWRü϶Ø/u9Àô]É*þ/:âˆ#Þ™œõïœî. #ßýîwßÜ»†þ?n¸ÿ„@ÀU€zuòãæ{Pçþ™š8°sMÜï Ö`n‹ÿjœõŸî~©¯·ì¾µ}ôÑ‹Þô¦7½{ñâÅ¿[înܸñ_>ò‘ÜvýŸì¬˜Pü» P÷®»HëZ£‘©º–\KXÓ±:Úíëë;Fû44‹ìB ÿJŠÿjþ{LkñŽ—¿üåÇ_xá…W'—ø;²Ü_<¹ìߎ뮻ëìÿØ„}7ÕS€Ú»gðþ¨·ï€Ž5Åbm¼0®±©šÕí+CGK{´Ûg@ªÌöù3î?“¿¸Êrëzï{ßû¼cŽ9æÝ---=•üò÷Ýwß?|ûÛß~pŠâ² ¥ø˜«5wïຨ·¯½¥-)ÖVhhªê ®¸§–˜ÿÀÿ¹ÿS­æ¿÷c¹)ÛSøú;òÈ#—^{íµï=î¸ã>Xiñ?44to|"ìºì_¡ÄïS*°P{ÛGw„­£ÛÃÂÖùQkë†ÔØT|m W`Š"½Pæóf”{Ö&gú÷þøè*ÿ/}éK»è¢‹þ¡’!ÿ{»é¦›þvݺuýá±³ÿ{ï³i?ÔŽ‘O8¨óLu©ØG ˜QqŸ õ?ë?Ýc¥n{Îú§Cþç½ë]ïú½ç>÷¹_˜iñßßßÿ³·½ím_ »Îþ‡I~‡©Bˆ"P÷E> àˆîC42Uupä¡’5(³pŸlˆýl‚„ÜÅþl þ‰Å:â¾+™ç¿üSŸúÔU'žxâßçóùžîñüàïI>…]—ý›ìwœªø/Þ7¨‹{ˆzûPEéâtî' †"¾0Gÿo9—»’¥ó»kíŽW¼âO¸à‚ ®JÎú6› J.û÷¥«¯¾úîËþMÜ¿{ ¡ôÕ@½€¸G¬h_V\ã ]ëfëЮƒB>—vû†Æ‡Â#Ã5t†å“Y¨£…1;h„²~º"¿Ô×ZvßÚ“‚¿û=ïyÏK;ì°7ær¹ŽÙlTrÙ¿Ïþóv]ö¯0Eñÿ¸‚â}PŸ`àþè·ñ°îƒÃÛ¥±©Ê±³ôÒ …99!D£H/ÀÜÿ³=ë?ñ~ñ¬ÿù矿ÿK^ò’+,XðäjlX²èß'¾üå/§éÑ …}¨¤øOï €ºØ8²9ú+¤ÓTåXêŠ{JÉÝ÷iäÌ÷Ò-CŠõª%ÁÕ*üË)òKþé›ZºÐ_ç›ßüæóN;í´¿mmm]ZÝpÕUW}4”>û&¹_r{÷êæ®k£Þ¾#ºÕÈTéXŠ;X+ȼ¼ QUüOµ˜ßT_ß³Ð_çªU«ìcû›'=éI«VñŸºõÖ[?xÇwl _øo²@b²Ï÷Ùf#€º¹}àîpÊü£Ý¾cç©‘™µ¶\[8¸+î+¬¸WCO#"‘«x±ëfê±ç42Ð(…ÿd…s%gý;^þò—Ÿxá…^‘Ìû?ªš¹sçÎÛ“Ëþ]v]ö¯œ3þ{¾÷v@ÝݱóoiÛâ°²}yxhøÍŒ5ï°Ðù=w ¦5Z-†A±Šy‘K ¢"¾0ƒï)÷k³™ë?Õýô–¾‰µ%ÿ¼w¿ûÝ|øá‡¿a¶ ýMæÇ?þñ߆ÇÎþ‡ ÿ‰[TÓq=G…‡6 ˜¹ØG’¤klݦ¡§1^1Ÿ$oÓ³ðŸ.Èï¾u>ûÙÏ>ä…/|áûz{{O«ÅoÙ²å¿?ðü8ì:û?ÛÂÿQÞ}ºY?ôpèë=ùyñóŽ ßÚü}ÍÌ€ž¸€»ý/Kz‰¼Žˆ·¯=âÑ À”…z¡ŒÇfZøÏ¶øŸn¸ÿž!ÿ]—_~ùóŽ?þø·åóù5ÚWc_ÿú×?ö]øoâ6•ó¸˜;éœÖ;wÞNê=6Þ ç( Í,zF¹èG˜ÿ_fÏ/òKäµ·´kdÈV¡?ÝógòT«ð/Uôïù<¿»nn?ýôÓW\rÉ%ï\ºté3k¹zè¡/}æ3Ÿ¹%ýs0á÷,”ØþB¹í"êêÎd!À˜€tñ¶t„C:Ò*µ_ÇÊäR™ ¢ÞFW(Ϩ Ò²¾œb²¢ÿqgý/½ôÒ žøÄ'¾3Yáy-7p|||àºë®»&ì:û?^b[g| EPW±¯žÁ=©÷¸ðí?ÑØTìøž££ßÆ»å qÈr_˜á÷MõØlÎúOöùžËûÏú¿ò•¯|˲eËžê°:ËÚµk?ó½ï}ï°ëìÿd«ýÏŠ¨«[úïˆ~ŸØ{¢€‰ù2™»z.…pe‰}@GNŠþªþ“öSûÓÝO ÿ=Cþ»ÞúÖ·^xÊ)§¼£Ögý÷ÙüÁ~ð韽ŠÿB™ÁCYûXÔÕº¡Ãæ‘­aqÛBEìÓSIFôõ6Þ7ø@ÒØe+ŒF½}-²[ø—TRø—*ø+ ö>ëßqÚi§¥gýß¼|ùòºœõßãæ›oþè]wݵ5”žû?“ý½O@ êîæþÛÃY O‹vûÒyÜ«:V„“«@¹é:0ê`,•…@Õ Æ£Þ¾yùn qøåžíŸôõe• ý/g‘¿½Ïúwï>ëÿözõßc``àþ÷½ï}ׇÇÎþ×D‹ã¨·›úo~Oé=ACSÙ13?þcFPI÷4DñÞÿßÄb¼Ô×§+øgzK‹þâ"ÉYÿ5×^{í•Éœÿkê]ü§~úÓŸ^½mÛ¶°ïÙÿR·™r þ~ÛpÆ‚S—7þ—Ʀl'÷ý6Þ¶óN -@Ü¡Ba_Ÿ*0¨æ¥ýöÜò{Šÿ·½ímO?ùä“/›‹Â?µ}ûöß\qÅßJîŽTi_—$êîöäJÃã#Ée Ú¢ÝÆS矺ó]açØ€gZ]É|è“zâÒ×üÝ÷hì2D¾@½/·èÜ{‘ºB—ûÿÎd¥ÿéVùÏï¾uœzê©+/¹ä’7%sýŸ7‡û»ðíoûCaßËþM¶/\hÖŽíHÜŽë9*Úml˵…S{O ÿ½õ48Ó:mÁÉQb©ô5ûÊöÕ{x8/?O#C\A¡ÂçWòœ™,öWêÌZø§—!é¼ôÒKŸ‘Ìõ[[[Ûò¹Üy6løïüã7†]sÿg³ŸËjksâ¦þÛ¢ßÆß‰x¡Cªë¬ñ+¿é»ECW`ÇX_ÔÛ7¿µG#Csü•|=WáÏžjž˜¢¸o)ñyË^…÷Ygµÿ§>õ©«Ï8ãŒ«çºøýÜç>÷á°ëì¡Ä>˜­}‚#€9+~Ås¢ÞÆt€Ö\krÖsTƒSRk.NOFÄî×ý7kì ôE,n[¤‘!AAaBÑ^(3P˜épÿ0IðèYÿË/¿üyÇ{ì[’¿!.»³nݺÿüêW¿zWxlá¿ÉöA9gö “|^ØëñGï €9ñ«¾›Š‹\åsùh·±'âš®ð?ÛnÔà”tRïqÅc%fãÉ%í²°øg5ííZÌWò¼É>ŸîûË)ü§*úÃîÂ?½¥óë:_ð‚ýœç<çí½½½ 3änlllàŸøÄµaß¹ÿå*LSü—ü>0'úÇvW?fÞ‘QoçKž"`Jç.:;úm¼s`mñ5O@ä#–´  ÁŠûRÅw©âºÇJÝŸ®èŸê÷)w¾~wñßqÈ!‡,zýë_ÿkÖ¬yI.—k¨Åvî¸ãŽùÙÏ~öpØ÷ì%gý§ &%æÌÛ}ð¤O ½É\×£}œÇéhéO^xzôÛiþåúÆâ.z™^ P0  LuFºû“M˜iQÎpÿ}ùK ÿ§$óüßÖÑÑq`£íØááámúЇþ5ìºì_¹Å~ašÇ å|E9óó¿Š~Ó«çœs>ÖˆÅꦛnºníÚµ[Âcgÿ+Y8±0Mñ_jþ¿5€¹uKÿíÅK]Å^=}ÉSÃ7|]ƒó8ç->'úmLÁüåŽßjìJ€ÈG¤Vu¬÷®ÓØÐœEaš¯Urö¦ þíSü'Å~÷Ûßþöß?æ˜c^—Ïç4êÎ|äÊ+¯üBxüÙÿ\‰â>”(ôÃ4AÀ¤ß/æ°0+.xf2L>fGvŽšwx¸µÿΣ–·/ §ôžýv¦ÃÿLJ4x…b¿ @1h_¡¡¡1‹û™þ“ÿ•¬ü_iá¿g¸:¯¿ãe/{Ù.¸à‚wtwwßè;øÆoüä¶mÛÒ”·œ…ÿJÓ(É`Neehðï.–ÆfÏYöôÐ’‹ÿÏð϶ÿRcÏ@ìWH­îX©¡¡± þé öRC÷'>6ÃüK ÷O ÿ®#6ŒlÒèÿ{Ö’ó3±­7fä5^õ #Vw Tôç¦)öËYѿԀr~—rÎüï=׿ó²Ë.»èÄO|S{{{Ó¤‰?üá?>::š‹/cŸNu–¿Ô× ÓFs*ÿ¹nh}ôÛٚˇç.†§è‚dîzuˆØ=<¼!Ü5pŸt}”tý„˜Ô¹¿††Æ raêùù¡D±BéÅs¡ò3ÿé-=qÝ‘Üæ½èE/:áºë®ûä©§žú÷ÍTüoݺõ–«¯¾úûÉÝÑr õ B€ʼ@ú˜˜s?Þú³Llçs–^æ·öjðÌ÷¨ráùË/ÊĶþhëO“ÞGA£Ï@ºß6ŽlŽzWv,½ù UôW; ˜ÉÐÿIW÷O÷[‘÷Á þ?{çG}¦ÿ×ê½[ÕêrÅ4 ¤¹”#—Â%!„;ÒŽ$—ÜýÓ.—äH¹¦0¦cŒ1Æ`Ó1¶%Ù–mõÞ¥Õêÿ{FŒ¼Zm™í³3ÏןùlÑîÎÎoGò>oyÞË×çååÅ݈¥7Þª.&d~ï¿W_÷ž  Bˆ ØÚ¿ÝÇ™¡f^ÿsÉÇøÛœ Ζê´E¶8Öçû^â]Ö V—^ÍšØ þ@Kõ©¦Ï[Ò;[šr÷Ϲîºë>÷óŸÿü™ªªª«,XwÏ»ºv¨Ñ„ÈxMIàÙo‚?òÿÙÇ3@‰9o5JÏdŸ-Žõ²…ÔÜ߉=éßçK?e‹cp ÊÎá=üÐCÀž! µü  ‰­øbÞ›¸wø¤øOð üåx¹Ö5×\sÎwÞ¹nåÊ•?MJJ*ˆÓµv®_¿þ6™Éþ{ øþ¾Ä¿À9ûa€sPêúBÿ˶8Ö”„dù\é'ù¡Û”^(•iå¶8Ömý;djzŠzX½¬Ì\Êšsø „º%ÊñrÿÌ|à *cþ'uyw<¸ûû¢¥¥åù|p—xîý7"ü½=ÎhÀœû „˜D,l·Í±~°è"Yž¹˜ºÍÈHL—Ï—}Ê6ÇûtÏf~è!Ò9aý €S³OÔZ!¦  ,ߎýF³þºðGYFIIIáõ×_ÍÕW_ýDQQÑDâû„Ó霺ï¾ûîùcÿþTøºBˆyxeàMÍõÚÿ».oUý«6€Ø‡«Ê?§FAÚâXáþÿÆà.~è!Ò:Þnùc„1*Û‰™Ð7bÚg¤·ßˆð÷ ÐúüÕ–õÃþðcùË_6,^¼ø;‰‰Ê8É477?µiÓ¦f9^úï+KoÄÌOÄw€ß*!¦`rzR¶¼f›ã…ñÕå%—ñƒ· 'f-—,¼Ä6ÇûtϺÿ‡cm¶8Î3sNå‡MHì‚Þn{ „RþïšõŸíó¿êª«Þ½fÍšµgœqÆúY¦ONeÿÇUÃßÄ{￯콯*ßž‚ ³× „˜†=[lu¼ŸU^õé5üà-NjBŠVña§2ç Ý›ùÁ‡# *ìH¹¤ð|~Ø„˜#àM¸‹_òï*þõŒ¿Öçî¹çÖÞzë­¿úèG?º6++k•Õ¶©©éÑ×^{­Íƒø÷gÜç-àÍàoÚÇ6/À!Ä4lxUú¶9^þ¸î;Zo8±.ߨü²T¥UØæxßÚ%GÆñƒãÎq5!¥×òǹ(µ\–Ñ…XŠÙÿPKý]ûüÓ—,YRò‡?üáÚo}ë[O-\¸ð­¨IÇÈ7Þ¸Vfzÿî"<áhÿ¿xØÇœë BÌóÇR9†?Û»ÍVÇ\‘Z*ß®ú7~ø®ÿïW›x¤k?ø0rtÜmS#R !QþFzû>ƽÄß½Ç_þ©©©¹ÿû¿ÿ{Å/ù˧kkk¿¦úü³¬ºÀ»vízXUÀÉÕ!þ{õ½ ÿ`úÿ}2@1O÷?ÿ½òñâñ÷hïøºÊþÛ Tðlé}‘~94vÄÇyQþÙR¶ˆ8!±xº?Ð>ÿDá¯ü}÷»ßýÀ]wÝõ؉'žø“¤¤¤"+/æäääÐ 7ܰN|gÿ½ w#SŒT°€ìÞ+-cö+þ·E_óòÞÃÀ"%ÈOë¿§õÿÛ‰'»ŸÕ =Iøh=l‹ãLX WW\Á‘€„ÄVøkê— ó³þšÁß7¾ñsaðwÎ9çÜžž^o‡E}óÍ78|ø0ú·|eÿ ÿio¯+ž„¿~›BˆéØØ»ÅvÇŒ/½ÿYó Í-žÄ7Ùª¢ñ—‹(%) muÜ0«{”åÿaçàX‹mŽõÌÜUòÅl ÄDÂ_Äxù¿žõGÆ?ó3ŸùÌ©wÜqÇ _|ñÊàï»,ìøøxߟþô§õ2?ûo¤_ß_@Ä{5€§×ð„ól:B ¦€?­ûž4¤s&v¼‚Œ?2ÿ5i•¶;öm};lÓ¯MìR ó•ŠÏË HH´ÁT¸ôÓœý/½ôÒ†›o¾ùW—_~ùº‚‚‚˜˜à$''KfffLT¹þ¯ëè耣õ”^öˆË¿·×sß×¼K!¦£U¾zuð-[{vR–üfÉËŠÌ¥<⌴„TùYýÙ¶Šã¾Ž‡yDø*ôLöÙæx“$© ÚÊÅçòÃ'$6Â_ƹŸ«Á_ÆòåËË”³ÿw¯¹æšÇKJJþaÁ‚‰±þUUU¢ö/ÃÃÃQ_Ô±±±î?þñŠ÷ì(â_Ä÷(A÷ÏÂ!Ä”¬ï|¶Ǟ•˜)¿^ü#95ûDžqö™­²égÖ8²_ÞÚÍ!bë»ÏVÇ›¤tZ¢~¦Å)E<‰\À“Ø÷•ñw5øCÆ?£²²ráo~ó›¯]wÝu”³ÿ—¢o~á_]]-§vD¸9óÔíÛ·¯íëë’ãÙÿHˆ_•îO—Ú‡G!¦ãïý/KÇD—m¿ü!›üsõå÷ºƒçú^à ab&ÊÏþKsý·+kÛ×óDˆpà=¹ï²Ýqã˜OÉ^)Ow?'Oö<+{”Il¼üýNV-] ¦.HQí])êz†v™ª~65í­}Ûyb3‹qýN·çh™ÿ¬oûÛ_¶lÙ—”É—5ÿòòr©¨¨ééiÙ½{·(“iWÙÿ'eÆøÏéçáÁ–ýûsÿ7â30Í!Ä”8§òp×Sreùgl»ø¢øÃºoÉšö‡dõÑ¿ÙÒÁì¬ÌZ&?®ýŽ$çÙv ŽŒ·2Haö ï·í±§'¤ÉG^ªmÇ”ÇÄ[C{d×p“4© HÇd·ôÙ³Îä„$íï,Äyò‚dm_é‰é’¢®g¨Ë4uÞ,™êçºÏV¢âÞóó’Ôó2 ýÎ0@LX ÆÌÿÜ„Æ×¿þõ¬\¹òK©©©e±xójŒ &ú±%&&jYÿ;wÊèèhÌô…^¸WFå¸ó NÿþÆý‰øŸ /î?g€bZïÚ(W”}Jû‚eßÿ¡ȧK>&•©rÝ¡ßËÈÔ(O “ð‘¢Käk•_Òz–íÌ­÷i;9ìÖàòÔRm»´ðüÙû0v²k¢G§†Ä¡2ë£Îq•aŸÒ~–¢D{Fbš›Oծǒ̄t~˜ÄìAw៨ ý2¾öµ¯}褓Nú‚þå±þÈúã:]»vÉädìFÐ ýýï¿QfzÿC1ø æ¶x xbšBˆ©éSæWÏön“K ηýZœw†¬ÎøÖðæÐ.ž1Fߨü²\˜¶í×ÙM½[yRD"k¼(6É6SƒqYj‰”IIܼg#U„ÄPü'¸<&)???ý«_ýêO9å”+b%ü‘å/++å70+üAWW—455ÉÔÔÔ\•;=£ƒ•¡Ç×KOOkµÀ–-[îQïa\<;ÿ­ ¬ì?¨ì?„ÓóPç“ ¼CiJ±\¿ä'r¯ê·¾õØ-óE¢ Æ“}§úߤ0¹€‹¡¸«mÝl¶•D–7ßfÀ"`\(*‡P±@ˆ‰®Nÿ‰Jh§^{íµï;ýôÓ¯T‚ÙTÂ;vL80+öuœN§Œk"ÞA«€€2*”žžž°úûûþõ¯Ý"Þ³ÿF‚ÁVˆ—à€'hH‰`úôºúâ{Jö \ ™i ¸¼ä2Íë-7Ë+ƒorQ¢@^R®\Yñù@á…Úg@D‘ =›¹QâÍ¡·åCEïãBXx 8¹Ä ]økÚ0-- Âÿý«V­ú¬º“¨£/áÁ¿oß>ikk›÷<Tdddx|Í¥K—j?knnÛ{ݼyó—ì¿3ÌA€°gÿ „Äw¶ÝÇ€Õi‹äWjìÜ jZ­\”€qdÿ°ðýò/e—kýÃä87½“½ÿQPbà0 ˜õ €Ú)ÊÜï‚3Ï<óó™™™±xSº«¿k¿+÷púïíí÷3¸ÿã9YYYó~–’’"Ë—/u\Úˆ@÷ª`Aöÿ–[n î¤ñíì¿'ñO@BH|ñÚà[²S9?ÃqÌ•«²O’õªUâÞŽõA;b÷oF äܼwËÊ?-Ui\7ÞÚ­ŸHôèTŽ÷ô°P@M $† ë7Ìd•O½æšk.z×»Þõ©X ÝÕßpúûí·1no®úUb¾½½]rrr´¿¥a{ß›6mBïÿ˜ÌïýD @ <1ïq BâTü¢á\ ŸôS%U™êKå‘® ÚØÀ‚ûF´ AÎÏ{¯|¶ìR“VÉñøMbZþª²ÿ$úlïUˆ aÐ@H,¿:äææ&_yå•窌ÿ'•p.•ð_´h‘&þ¼>nppPsúŸ˜˜˜s?n=zT  ËïŽY(‹/ž}m¼N¸zÿUÅAóm·Ýö¢ûËìÿ< „Ä;^×ü–e.æbx ¤Ê'Š?¢ÆÓ]ª¦'lUUOq|˜A²T6îâ‚óäcÅPÖr.ˆžîyNÍaoäBÄ€^‘dÀ°¥ˆÄŠ”édùÞ÷¾w™2÷{¿rõÏÉ{Pb¢}þÞ2þ:púollÔÌýܸö3˜úyz ª««çLèè_»¤Êþûêý1iöŸBH\qgÛýò³úÿäBø ¤Èû•Y¶Æ‘ýò°jØÜûw5{Œ‹ãÆŠÌ%òᢋå‚ü³´ ñÍÈÔ¨Ütô..DŒxcp—ö0{ÿð3$Q?çœéròð29mäI=;åÓ1ù~’šªeüKJJü àÍé÷#“_WW7¯r@wú/-[Ô€×èîîËq¨)ûTï?²ÿfïý÷ `€7¼ØÿŠìVUËY`˜¥õjlÝ5òu5·þ¥WUeÀ6mÇã¶]“ŵrž*ó?/ÿ½R‘ZÊ“$ЊÓ=ÙË…ˆýùªšüqvÞ™\Œ8‡$ZäNe˪¡rÒè2IšNŒÉ{Ð…?D¹¯RW±¾ÿ~imms¿ÃáÐñW__?ïy*,Y²Dòóç6@üãùá@eÿת =û©~ÿpgÿ…BHÜÞã?¹Uþ°ôgÅ辪*¦vØÆ”øß>ðš¼2ð†¼¬Z+¬>A™ý“³Vhf‰gåAÑ$Í£‡e]Çc\ˆƒj,H`€D–…Žy×ÐJY6ª²ä’“÷¡ŽQ~ÅÅÅsJñ}áÍéhhH  zÀ=»\þ=®òõ¾ö©Þÿ—dnï¿ø÷ÁT øýAeÿ „Äè=FûÂü³¹A’¦± GÇÛ´`ÀÎá=šÏœÆãú‹µÊ¬¡òaEæRMôŸµD’$óƒŒûûõá?‹cÚÁň1Ûúwhí<é i\Œ8&-$BTL”ÈéC'JÝxeÌ’%áÈø/\¸Ð°ðãããšÙÄþ¬rUÕpîÇø¾šš)((ð¸¿eË–i•ž€Y Ù–cÛ¸qã½xIñÜû¬à×Ã’ýg€—`þøY¹ghYm†/ *#^±°T>ª¦€AÇìÙ+ÃûäàX‹´Œ“–ñ£ªm`ÂTï_lJRÊ¢´2©N[$K”è_šÑ •iå¬ 3v>®µß؃öŒ`d4¾Éd€„%÷Æ«å]Ã+µ@ÌÎk%Ä«ªª¤¨¨(àçkcþÐA5ÀÁƒe``@sóÏÎΞ÷¼¼¼ÔHA-ãï);oPXkeÿü:###ZÉ?Üÿ‘ÝG;;h€ ¿*T„ƒ 6Éþ‡³÷?ìÙ!qË=íÊ‹.ÒD!‰<äe)ÅÚæ‹ ç¤ M kÛ˜*SFÕÀÄ;A)U>>:53‰ EUo¤¼SÁ‘ ^_†Q¦Ë,µeð˱)@à纃Ð|#ˆy€¡g» È¡†Ä'ô !å̇U›Ûð I›ŽÝdß1j/'''è×hkk“}ûöÍÉÐðïСC’––¦‰ÿää¹Á~~´`Œ ?µ‰¡‚ìÿwÞé-ûï+j;€»¸)ûÏ!$n ùó‘Ûäµ×r1L2ò yRœÇŰkÚ’7‡vq!L<žìÞ$W”ý#Na †’É"MôÇÒØâ™~”úgeeý:ü(ïGo¿ë}¸ÝÞÞ®àôï^Ú)pú7Zm.ó¿§žzjËþ"øEŒgÿ§ý {1ýg€×À FvçF /{GšåÖÖ5\“òX×Fùlé'$qA"#.¬ F•²h†~g $“±ëï‡ðGÉ=Jý=•ãÊú÷ìÙ£eúu&''µ’j~÷Ò~8ý£"Àhà×}KOOÏÞ»îºëe™qþDà‡3û/†ì?„¸çw-7ÉÉÙ'H^R.ƒ0—ùŸ¼ž®ÿ&¦Kùo<×÷½â” V?¤L'ËÊ‘ÅZÎTVÌÞ2î(µ¯¨¨ðê²pä‡ÙŸ«Ó?Êô8 dÀè@w`0ˆ1âßáýÿ±gžyæ>u1.sGÿ…kÜ_T³ÿ Bâž>Ç€üß¡äê¿ËÅ $LüöðrX>sswÛrAþYœz‡dÒ€x!ß‘#«FNFk&±¥÷þÈø»÷à‹»Ó¿>⯥¥E»Ž¶‚ââù^CFœþ=ŽòÕû@9ÿïð!þÃ!ú£–ýÇÏ „Ä=Ûú·Ë¦Þ­Ì„èxLžîyŽ =$;^S;Vq1â w¹V=Q.',•Åc51 ê!îgüܾèëë“]»vÍ:ý£  ¹¹Y›€*¸ùçççÏ{žQ§wdèïïù}oÞ¼yÌdÿuþ7úX‘(fÿ„Kðû–ÕrrÖ N $v 7Ê GïàBÄw´Þ'§«‘¬ˆ/RÕ”$åßà˜žâbؘ gºVæáŸ;•Ó÷‚¾þòòr)--Õy8qwúÓúýáΟ””$ ûúÑ à©ÀÈþ»N†–Ûn»íïâÙùß]äkþÕì?„Ë0à”ø•\¿ä'Ú89BH`t«žòø5ûþãŒ]ÃM²¥ïE9/ï=\Œxª ÿwû7ˆþ# JŒÅÖȽõ(ó_¸paÀYv#>|X駃¬<úýQ €j8úcÜŸ+:ýÏS¹Jø‡£üëÖ­¨÷éîüoDè›6ûÏ!Är_„ÿtäVùfåU\ B¦ßÛ÷3ÍXŽÄ7½SÎÊ=]e”ùµ.žÈLH—aÀ.ÀÔãûNY!E“ù1?(·Gv=772&Ê(ñoll”®®®ÙûŽ;¦mzàañâÅZ€+ð€Ù_(#dÐ}‚E™¶þõ¯Ý"3£ÿü úP²ÿžÄ¾7röŸBˆåx¸ó)Y–Ñ ï/¼‹Aˆ¦Õ¿Ÿ7ÿNöäbÄ)­ãíÊ»áqùTÉG¹ñHÌä"Ø€‚©\9á2ÿ4gjLß 2ü±‡ŒvväZàæ¿{÷îÙ|dûQò¯JêµÛ999R__?Ïc ##Cÿ¡N@ËA¨¼øâ‹ª÷=&Þ{ÿžì¿ø øöF³ÿsÇ!Ärü¶åF©M¯’¥*@ñÍŸUÕ Œ4I|skë9;ï )O-åbÄ h]§•™_µœ2²\*&Jbÿ~”ÐFo¸Fùù}ýpúÇ%ÑÄ¿ž‘/**’êêêyí¨DX¶lYÈÆƒ>Àp0Ô{îTÙÿge~ï°Žÿ±Îþ „K3áœÔüþ¼ôRœÇ!Ä ··®•uÊõŸÄ?ãÎq¹^?ÙðÆ ™œ`9 ¹Úø¾•#K”Á_ZÌßîès?÷RûH€ ?œþ!ÂÊÿÑÿ¯›ñá}`s£ÿPŒDûA(ìØ±c½ `ŒÈÌè¿@ÌÿLŸýg€bY:&ºä?öýD®_üÉNÊâ‚âÚeno½— a!^xCê|B>¶ðƒ\Œ8€Ö IeûëÆ«´ÿêñrS¼'ô×ChCX‡ÛÑß—ðnjjÒÄ7ÿ‘#G¤½½}öçÈúÃhÐPœþ=~ÿ ÑüOM(èùË_þ²A,šýg€bi0#û?÷ÿL~½øÇ’–Ê!äžì~V~×r‚üåÈmZûÓŠÌ%\ ³XÏèNþËÇê%ÙiI…2zô÷ëž,®Nÿ‡C+ùœ1¸DÙ}w³AÜñh Ø'ZBáµ×^{TâE¦$0ó¿¸Èþ3@±<˜ ðƒ¿Ÿ×ÿ'ÇòŽøÿÕ¡?iæÄz`®üÏþVµ@]'¹I9\“Å€¸&~KÆj´Þþ…“¦xOÒÑþÈüGdû÷îÝ;›u‡øÞ·oŸLLLh·ÑÏq~îï NÿK—.ÕÌÉkÅA0(Ÿ‚Õûÿ¤Ì8ÿOIèŽÿ¡dÿ݃H!FAYì/þQþ_í7ÙK(þ)þ-¦`¬ãõK~Âê'“΀ø@ý¹¬ž(—£ Jü×j%ÿf šÆ~ž@¦ýþºÓww·{ˆ8ý»÷ûë"¿®®n^p¢¤¤D»?Nÿžµü_Ó“­­­ýÄ¿¥²ÿ BlÇßûwÈÿÛÿsùIýwÕ—¯4.±4Îi§üþÈjÍñŸØ“ú_–5ÿR~\û­ Š˜Ž4ùûf+ñÑpÎG™´ûû=ûÆÆF-ÓîÞïàE·w‘n§wP‘à„È]½zõ#2“ýw(úã*ûÏ!Ä–¼2ø¦\ÛôC¹®áû4É"–eÔ9¦•€#èEìÍKý¯Ê×ÿK~Zÿ=)N)ₘ&À €XR8™§eúWŽ,– §¹>‹””)++Ó6÷2úX±~ÍÍÍÚõžžíºÞïЖ€Í=€ žÆÿ…×öƒ`ؽ{÷ÓÊ¿ }ÜŸ©³ÿ BlKãÈ~ùwøyÃIiJ1„Xж‰ùþþë´Q˜„€}£ÍrMã÷ä¿ëþƒ#M`@´A/ÿòÑz9A‰þ‚©\Ó½¿¬¬,MôǬ¿žšT"eþª<Þc¿?²ýUUUóD~¤œþÝù_gggÐÏWÕ wÜqÇz9žý¤ü?î²ÿ BlÍÁ±¹zÏÈj¯•Ó²Oâ‚KðæÐ.ùñ_KŸ£Ÿ‹AæÐ=Ù+ßhú¾|¶ôò9µÑ5¶d° *`tßâ±j-Û_1^bºi@úèëG™¤ÅrâXöìÙ£eü=õûë~øÌYó´4Y±b…viúúú4?‚`Qc 7© Dôì¸zþM™ýg€b{”)àw÷ý|©üŸåò’Ë8&Ä-p÷°ãq¹áèíÚ,xB<~¡WçÆí­÷Ê«ªê»Õ_•òÔR.JŒÈL`@¤@Õx¹rðo†ñjI˜6_° eþÈôCøãºÙ×Ìþ†‡‡=öû#ÿx±jŸÈ˜{gggkcþ¢Õº€Ê„`QÕŽ»îºë!®žý7"úM—ýg€BdÆ( éûFšå;Õ×pn6‰;F¦FäW‡þ,Ïõ½ÀÅ †xkh·üË®oÈ?,¼T¾¨ 4E>l+‰JôW+Ñ¿Tù5¨ŒÊ´9'_˜±Ì߈þ;wj‚¿··Wë÷G©½2ûç縀 ‚‘rúwæA?ÿÀϽþúëÇdÆù?œæ¦Íþ3@!.<Û»M•ï×þ»T§-₸rÿ{ð÷Zß?!à˜vȺŽÇd[ßø´\Tp« ¢¦2$-HdÅN((ÉS1Y"KFkdÙX½2ó3g +11Q둇ðGÀÌÀéeÿ(ÿÇh=˜ÿ¹0$)i®ŒŒ´Ó¿'ðþ\A4¦î¹çže¦÷Ê€˜·DöŸBqcÿèAùÊžoËeÿÄ–bjPÊ}WÛ:¹³í>­Š…`Aðèç'Sçþö—ÿþí‹™‰™ÒïàBHÉd‘¬©WÙþ:Étš×K!==]JKK¥¤¤Ä4nþ¾8vì²âšøGÖÙWòòò´ž× ´œþ=xéè>ð}èС¿¿ôÒK-2ÓûïMì[.ûÏ!„x`Â9©µìxMþCõÈrJ1#ß?p6Þpqhìˆü¤ùÿ¤üX©|¨è}òᢋ%;1‹ A2TëE¿0ऊ' µò~l9Sæ=/!ŽaЇlaaaÔÊáCYtPö~ôý»‚ †{†Upúw7Œ0& Áüoú¾ûî['Ç{ÿžñ"áËþO‡"ò „ x}ðm¹r÷µruÅÚ—afĈ™¸¸à<HD86Þ¦AQ€ó G†ªtŽªu= ªÌPiv`ô°4«1­lÝñIádž,Q‚¹*ïÏwä˜ú½ê¦~ååå’š?^BȤ£ä¥ÿCCCšø‡ã¿+8&l®À`ùòåZ•C,@ù°>|ø¥-[¶4Ëqçÿp˜ÿyôf0@!addjT~søÍ\í«‹¾Hob.Ì?[žê~VUª¼ÎÅ ûû·¾óIm«L+—÷åŸ+gç)µéU\ ¤ÿ€÷®ÆÎŽ;'¸8¤L‰£HêÆ*eÅh½äMå˜þ-»fûÍjêç W§ÿÎÎNã9=õ¨^¨­­Õƺm§w`þ×ßô¨Ûé‡zÙÿ ñý¥ü߈ØzïÿìçÊ¿4Qaûݯ/p»î¾%x¸ô´%z¸Ä†ßؼ ^ùÇgøñbŒDeÖtÙÂ÷Ë¿”]®ú6éÞLbz·¿¸ë›2æçb¨Q¦Ú¢Þ›wºœ‘³JNÌZnÛÉ)£Î192Öª‰{dóõÌ~÷dO’Eÿ¢ÉR•é¯Ñ¶Ì)óÿÿªgûÑß« x¨@ôCü#£¿¶¶¶¹ßy”q!ýÝM èÀý± v_úI ø€$,Hà˜Š.ý¸Ürìn.‰([ÇßBlp±_šÑ 'gŸ +3—É’Œz)Hγ̱NNOª–ˆvi;¦Jø[å6u—ú¡‰~ݽéxm\ˆþxìí÷F__ŸìÚµKë÷‡Ùn»‚Ì>Æü¹7ÐP]]ÓcG˪‚eÆ ÉÜì Yþ`&xî1Éþkç2ÿEço†ûY@Hœ/½_©øœœ’½’‹AbF¹}y÷·47BÌ@Qr¨Ï¨ÑÚ¦*SËU A…i+úTÉ~Ïd¯tLti}ú3Bÿ˜–ÝoŸèTß¾§ù¡†$õõ³b¼D+ï7»{¿+èç‡Ã}¼õö{™~ôù£Œ~ïÞ½Ú¥+ýÈð£ÊÁ5øQWW§Æˆ¼ï`P>W\qÅwe&ûA×ì¿§¬¿å²ÿ3¿‹„B‚¢qdŸ\»÷G²2k™|ºäcòžÜwqQHô¿T/H’k«®–o6ý€B…˜‚.•ïêï‘¿÷ï8. Ô¿…)…RœR$ÅÉE³× ’ò$7)WmÙjËÑ.Ñn*¨Øž‘^G¿&îñžºõË µ9z¥s¢[ý¬OËò“È<$•ãešsÃX•¤L§ÄÅûFy;úÞ‘íÇè;«€5þNëŸ×Çý¹’““# sÊûcéôï‰PÌÿ6oÞ¬gÿ§Ä˜ù_0®ÿîß“pYöŸB ;‡öÈÿú_HÌ@öû /'º7q1ˆ)Ap vlþHMH‘µe%fjUÉ ’µv«Ì„t¯;453®lLõäCôãö8}1bFº3MjÇiýüµ‹$a:~Zå222´,7¶XÜE”Í755iÙsOf ¨¨h^y¬þÝ•àÆfªç¹ãŽ;^’™Ì¿/±ì8@‘àÇ*øC 0@!a@Œ]^r™¼;÷4Ž$Qã+Ÿ—ú_ÖÊ™ ‰gà–mÐ1ÄňrYR?^¥zúk¥ÂQ"ñTŒ³;”øCô#n5&''µ~gÿŽŽù£'afXQQ1GüÃüâßLw£Â@x饗Vˆ ºfÿb|ôŸSŒ—òÉèÇ$ûÏ!„D€·†vk[Yj‰|¸èbù`áEZi+!‘$G•N¥â ùÅ¡?p1!ÁíòÉb©­”ú‰*)œŒ¿2y\”øÃÍ?ÞÆ÷eddDvîÜ©eÎ÷ïß?otUU•qí04Óº„bþ§Ž¿çæ›oÞ,áËþK?ó'죒ýg€B"H«r޾éè]rÛ±{µ‘YŸ,þˆ¬È\Â…!ã’ÂódCÏfymð-.!$¬èýüÈôÃÈ/ËãpQÒ®gûãu|ŸQàì¿{÷nmÜLÿpâ¾¾¾~^o¿œþ=ñïp8‚zî믿þØÐÐz…(ùÇš™T1¨ ~pß»víÚ ‚ýâÙù?Ðò‘8Ïþ3@!1Â9íœõ ø“ ¼7÷t9/ÿ½ò®ì“ !ó™’˳=[Õ,óV.!Ä'iÎT©šPeßãåÚ¨¾ g|–Æ#ƒ ?¸Ù£ÌßJ.þ†¾W(¡¿wï^-SÞÚÚ*ÇŽ›÷˜ììlmÌ¿0ûËÌÌ4í±›ýW¦Êùÿ™Ÿý& œ/€?aÕì?„bàvýlï6mè+T`‚Ài*°$£ž D&%!Y®­úWùÖÞicÒ!ĕܩl©WYþ:ÕÏ_9Q—¥ý:®ýÈö£Çߎ 7Nÿ½½½ràÀ­ÿßd÷QâïZ aF§">hó?Õþð\cc#žìߥþÁøˆÄaöŸB1®•7©Ûe)År¦ œžsЬÌZ&Ù‰Y\$bˆS²O‹”ßÄÆž-\ BlŽæÚ?¡\ûUY½Êò:â»>55uVôCÄÚ™±±1ÍéýþèûG¹¼;0=¬¬¬œs|Ð `ööˆ‚`zݺuÈþÃaJÂcøç+ Ù!Ää´NtÈCOhÀhÁ3—kÁ€³–KuÚ".ñÊ5‹¾ ;^—~ǃ›‘6­JûUY½ÖÏ_%©Î”¸>d©u3?”ú›Í¥>`¬œþq‰òw³?€1X3WÌêô¶¶ ž§ü^ܶmÛA™ÉþÍú:P¼~OÂÝÙ!$Þj´ 6ŒzEÉrRÖ Õ*P'õé5RŸQ£¦ är¡ˆF®š4ñ¥ò–ß¾‹AˆÅÑ üR3¶HjÕV>Y¬Ýï¢&~Èö£„¢ÿ8]]]ÒÔÔ¤•ýÃéß=KîiÌŸÙþ=8FFF‚zîã?þ Ïþ‡jþçÏÐW ÀTÙ!$Þ¿LöȦޭڦS˜œ/uéÕ3µáú¢´2I^lË5BÅуrVî¶<þ½Ožê~VÞVÓ'!Ö"y:I*ÇË´ íø"ɞʌÿcR¢b¢⟢>0øC¯GG‡æú?==W#Âäåý®ífwú÷D°Ùµ.o©@ã;gb?˜@€ˆ÷€˜gÿ „ Ò=Ù«m(ýÖAhaJ¡”«‚²”uYªµTàRÝÎIʶı:†ä¨r¾oÙ¯m;‡ö('ü'ä_-þ‘f¬h7ðÙÿ{ÕWäê=ßÇôA‰s¬dà§'z]ð#c­‹~Š7•¨„>úüáòïÍéþÿ®†ˆñàôïÎÄÄ„6Ê06nÜøÌwþ÷—õd  Hœfÿ „»|iPÿ:&º´íuy{þ†„T)HÎÓªÐB€Ö\ê÷¡”„‰i’ž®.£7&jÌ9.ÃS#225*#ÎR×!ô;'»¥}¢Sk‰Àe›Êôã1Þø}ËM²zùolY *OTîi¿ „ÄI*Ë_?%ú×X"˯ UôôCø£§ß›àe`W§ÕßîQCàCü'%%͹oÙ²eÚzÇÈþ»W6AM@h¾ûî»_•ã½ÿá,ÿ÷V ‚â#`q‘Ï!„ŸŒ+‘­û %+1S ¤'¤i— é³÷Ë;_Ø%aN°ÿ˵½³)õÿ®»`sŽÉä´C»>ä–a%ø1!´Œ“{Û–Ï–~Ü–ŸñçË>©šD „bnå¯V~ý5’8h‰ãJOOŸývwï8ý¿ýöÛ288¨™ý Í{L^^žÔÕÕÍqõÇ}K—.ÕÊÿã §Ó)íííA=Wÿ­Ç×™ßûjù¿øþq“ýg€BHÐ M k[<ñ·¶ûå¢ü³µö»*oV]%ßÛ÷Sž¼„˜Œ$%ð+&J4Áß0^-9SÖÇÈÞ#Ò~ôžë¢ŸY}ã@ô#óK˜þÏ{Œ§1¸x\ëîîn ü¡ ;n¾ùf˜"MúüÁD3ƒ¨Š|!„A¥Ã„üNµ\×ð}[ÿ9§Êyyï‘çú^àÉ@HŒqÍòWW¨/åÖÈò#Ì3?²ý0õ›§z(í·sœþe``@ëýG€;é‡MkUSS#eeeq{Üð7†;v<¬¼PZ¨gÿ–ÿ:þÏŸp7möŸB!¶cûÀk²­»m§|­òJyeð͸«Þ $ÞA–¿rB ~åÖ_3V!yS9–96Wç~˜ø¹–¡“àÐþ@Ï¿{?¼>ÒÕ:Xw8ý»Þo {lqð‡ªŒèWÙÿâ9û®^O·==^ĤÙ!„Ø’?´Ü¬&œ,i ©¶;v;~¡ürm !‘EÏòc«QÂ?eÚ:&¤šè‡ØÌÎΞ¥$4 ô÷ïß?ëòïÉé& s|„Ó¼{+;úoçÎO*cDD¦$|åÿ"Ëþ3@!Ä–`Â]ÊàÊòÏØòø/[øy¦çyÙ5ÜÄ“0‚±›åpì¯ÔDÉd‘eŽ Fr(íÇÑÍÒ~»´LMMÉîÝ»5§ÿC‡Iggç¼Çxó‡` œþ]ï‹GÐâàé˜ Wj·ŠFû9rDúúú´ €{ï;޳ººZ­¨ƒ` Ìþ"åô«€Àèè¨GÏttt¼­â¹÷?Ðòw‘/bÌýß[° ª¢žB!$ê|B.-¸@gÔÚòø¿^y¥¼6ø–Œ:Çx2[‘ëÈ’ê‰ -Ë_;±H¦ãßäN/ë׿·²þHŠo–ö{BÏž=ÒÝÝ-]]]šÛ¿»ðFÐýþøütð™.]ºT›­õV@½ÿîû2ÂæÍ›]{ÿƒÍö» ùpJÁ€¨  „Â/dÓNùÍáäÏË®³¥!`qJ‘\Qö)¹áè<ˆµy§´‚®ýVӇ̰žåw5ï³äGÇÁ…‰‰‰Y§ÿÖÖV­ÀÓg‰~|®ºÓ´Åy¤ˆ¨L~ÀÏ8ú·¿ýmû;Wñï«üßh@Äxö_<<>ꢞB!$@GöÉc]åÃEÛòø?^üay¦÷yÙ;ÒÌ“XФé$©W~ãUÊįJ2-PÚ!¨g÷qiÆù﬘‹îô£;dý‘ýwŸ#„¾kNÿµµµ~×'^âp8~ÞŽ;™šš‚c¢CB3ý d"€/ןKäÏ „B"ÉMÇî’³óΔ¼¤Û{â‚D¹¶êjù·=ßSßF¦y2¸&C¹ö׌-’%c5R£Jü§ãúx\Ëú!ú‘íG™x´Å7Kûƒ}þ»víÒLþöïßï±ßŸiCCÜ,?\þuú·€€§*¨I }7ÝtÓ&ñªÈwößÔ0@!„¼Ã cHn:z§|§ú[ÿÒŒUq‰<ÒõOwäNekcú–ŒÖZµ½ÞºàÇ–””diñmÕ@Üíáðòÿ½{÷jãþÜAÛ²üzPdž`ÆÿÅRœGzŸýÀ@Ù¹sçSjr°Ì7ÿ §ë¿/ñ#øþõ‰É_)!„žì~V.)<_NÎ:Á–Çÿ•ŠÏjº'{x2ÓS8™§²üµ–èç‡À×Å>Fô™µŸÆQ3êµr•±–¦¦&íÒ’’©¬¬œ½­{à<ˆ¥8Æ>ƒÉþ£ìÿöÛoB|;ÿ‡ÒÿoÄì/ì¿éB‘ B!sþ§ž–ß·¬–¿.ûµ$-H´Ýñg$fÈ¿.ºB~Ú|=Ob:`ÒY9^úŽè¯’¬©Œø=%¸Pö ±±çjúmñÍÒþðc»ÆÆF­Ï_eªµ O}îUUUZ¿<àôKW±l%ÇTB3úOµP<§Æ&v‹ÿÑŠ~obÞ[ .³ÿ B!h=¬F>.Ÿ(þˆ-ÿÂü³åéžçä¥þWy2Sˆþò‰bUÚ_#KÇêâÚÄeýz–åýz¿7Kû­´@ŸÿîÝ»5q‹Þôüó‡s™T‚ÄZœGcŸ˜‚ÌÛzà‘ã£ÿÂÕÿ/>n‹‡`€ø˜Bä3@!„Èm­÷ÊùùgIQr-ÿ«‹¾$¯î”qçOSÑ¿L‰þŒ8ýzYYYZ–ßìãùX1:èg‡Ó?.1Ú-î è¡óB§¨¨hŽ@¬Åy¤÷‰ ‰§)þ8räÈŽ­[·ÏÎÿÎ b@øö¦Ïþ3@!„xadjTþrä6ùAíµ¶<þŠÔRùLéÇå–c÷ðd ýžž®ev±¡Ä߈Pbi䃑Fͥלþaö‡ì¶§þvT€`Ì.uàò_QQaq}¶··kmòôÓO?¬.•ž’ð:ÿ{sÿ72þ/®²ÿ B!>x¶w›\ª ÏÈYeË㿼ä2y¦çy94v„'‰Š©œ,“å£õÚȾTgJÜJ¶õ>~Ý­?šB,Ä·ÕƒÈöÃá_ÔIss³ôôÌ7QEÆÎþúùc¬««Ó²ÿfç‘Þ'„?&#Jww÷ÞuëÖ픹½ÿ¾‚F"ÆLÿŒû¸Èþ3@!„øá-7ËÍËO””„dÛ{Ò‚$¹¶êjùfÓ4sDBÂ…îÞÂØbÉudÅÝû׳üüF³üVêdÝéâýþ¨píûúÚ"€6œ;Ñ:ÌPB^k”mÛ¶!û1 ž²ÿÁTˆØ0ûÏ!„⇣ãm²¶c½|¶ô¶<þ³–«*ˆ ÔxÄM<HHdOeÊâ±j9at±OÆÕ{×{ù!úéåg–ܺA d²‘õGö‚×álïŽû˜?8ü£ —fçÑØg0£ÿÔºvÞvÛm/ˆç£ß- °›ì?„BˆþÖ¶N.Ê?GÊRKlyüÿZq…¼Øÿ²ô9x2€Èp*±3Z++Æê¥tb¡Öç/@äëeýØtÇ~«Ã …0Òýþpú—¦¦&íÒ÷1"Aü{rú7ƒ8ô>Qá)HâW_}õ1å­0*ÆFÿ…êøo´% .³ÿ B!€þïZn’ë¾oËãÏNÊ’«*>/¿<ôGž Ä€š©ž(—“F–JÃxµ$L'ÄÅÛ†èAi?úù‘éÏÈȰ¥P·zÐ"TÆÆÆ4§YlÈü»—´£b¤¦¦F ŽO‘ÁuŒþ ô}Z) Ìè?µ¶Ã·Þzë™ýg4Ûïßåû¾Jÿ½‰zoUq×Ç!„b€í¯ÉÖ¾írvÞ¶<~˜!>Ýóœ¼6øOâ‘|G®,­“•ªÄ?g*>úú!Ô öuÑo4ËÏ,¹=ƒºÓ??®ïÛ·ož›½§1eeesÚÌ(Î#½ONúúú~ÞîÝ»ŸVSP~æ-û®i"JÁÓ  „B òÇ#7Ëi9'IzBšíŽ¥Ûÿ^u•|i×µ29=É“Ì|‘œN”ºñ*-Û_5^%þh®®ý,ígÐÂ0¯kllÔÌþpýàÁƒó„±û˜?˜jkk¥°°0¢Ÿk<àüïþ<¨àŠãî»ï~Lf²ÿþ„~ ãÙñðxS‰z!„Ð1Ñ%wµÝ/_.ÿ¬-Qj¹üSÉ?hk@ìMÅD‰œ8ºDsòOvšÿë$z®õL?D?]ûí´×8p@ÛLÿàüïNff¦–ù×ûûõJ8ýëÂ×êÞöÏ„ÎÎ΀_WY¶íܹ3õ줲ýâá¾i/A1(äg B!fæ¾öGä’‚ó¥:m‘-ÿseŸçúþ.-cÇx2ØŒ$I”%#µò®‘•²p²ÀôïYXݵýüF„³ä Z¸¿WŒöCï:®=zÔã {÷18÷ þá)a&q}zÚÄ?*'}©‡~x½xÎþG:àI¸ÇuÖŸB!$HÓùÍáä·Kþ'®ÍÃEò‚dù÷Ê«å[{¤¾Mó„°yŽl•í_*' /•´éTS¿WÝÄY~W?Šo-‚uÏž=ÒÓÓ£­Ess³vÝ÷1¨ðçôo§€<<Mü¡žóæÆ÷‹ïòÿ`Þļ·@€%Fÿ1@!„„À[C»å™žçå}çÚòøOÉ>A.,8[[bUUyÜÉñX©ƒ]\º‰ŸÞ{m'¡Î Eø× #ýàô?<<¬ X˜ýÁôÏ÷1púGÏ?zÿãAœGcŸšx‘èÍ›7?ŒBŒ•þ; D|/÷ùËþÇU4œB!$þrôvywîi’•˜iËãÿ·Š‘íý¯ÉàÔO ‘æL•G–ÈÉ£Ë%×a^'ÿ´´4­ì‚+%%%î'ƒæ¢_õ‹š;¯¹ýcÌŸûìz|ŒôCÐIG¯ç˜±Ÿ?P‚Éþ«`KË]wÝõŠÌuþµì_ £Â>n³ÿ B!AÒ;Ù'·[#_«ü’-??9O®¬øŒ\ø¯<,@îT¶¬Z¡•ú'O›óë!D?2ýþz¦Ÿâ›A‹p_WW—æô¬?²ÖMMMó²×ÉÉÉZ¿Þb‚}ÕÔÔHQQQTÅy4ÎÿP÷744¤m²}ûöGÕńڦ$<ýÿžÄ¿xŽˆÅ²ÿ B!!ðPçr±jX–¹Ø–ÇÿᢋeC÷fy{¸‘'CœR4™/§Ÿ(ËFë$AL÷þÝ×ÝûQêo'¡nu̶n®NÿÈø#ó Wà1ñ¯WÀé¿¡¡aŽÓ´Äy<`ž(*àÒ·zõêgÅÿè?§^æïMä"ìã:ûÏ!„Ê—!õïw-7ÉŸ—ý–†€8æk«®–¯ìù¶2Gœâ G`ŒßéC'JÝx¥éÎ]dX!øˆ~fÉÍ%¾ãqÝðž!üèõGÏ?ª\ÉÊÊÒľnî§;ý£2Å âÜl±±1éíí ø5UûÅSªj`XRt‰-¿6½J>^üa¹·}=OÓ+Ñÿ™C'Kùd±©Þ2©ÈôcC65X5Šo-y,D>œþ»»»µÛ¸T³çç [´¸šû!0…`‚Ufç±è£AM^˜¸ýöÛŸùÙÿ@+Äø÷W`Ùì?„BHX}ôorNÞ™’—”kËãÿ—²’-½/HëDO‚ ÿòÑzyÏЩÚH?³1…q}W¸´‹P·:ñ²n0ùƒÓ¿Þ£ÞÑÑ!‡ž÷8÷1îÁ€xçîûŒäþÐ:ÑÙÙðóT%Ƶ!ãð"ìC­ð׉`„BˆÕ€þGï’ÿ¨¾Æ–ÇŸš*ߨú²|oßÏx2˜Lø×Ž-’³‡N“…“æxOJt Ã…l¿7Â,¹¹Ä·ÕÖÍÕéÇvôèQnõÕÕÕ²páÂ9Á€E‹Ed-âÍàÏXË@³ÿxKëׯDfÌÿûˆàbß[Ùÿ´UÎ!„0ðT÷³riáùrrÖ ¶<þ3rVɹyï–-}/òd0ÕãårÎ໤d²ÈïýÒèé7:¶â›A‹H=}é»wïF¹¹ö˜ææfmV½+îcþð:¨p Dc]â1 €u &û¯Z^ݼyóA™ÉþO‡qñߨ¸Ÿòg B!–ù«þý¾eµüuÙ¯%iA¢-×àk•WÊ+ƒoÊðÔOˆs?dü—Æü½è}ýý®#Ó¬*8-ÿ7Îë†Ì4 þðþÐÿë0ýsÅ}ÌÎc”üëÁ€Xˆóx @ü;Ž€÷÷Ì3Ï û™‹N—-OÂÝŸù_\Ã!„&šG˃Ë'‹?bËã/LΗ/”].wï½}¢SîïxDëÚ¨eÿIdX2V+õ¿G2œ‘aŒFíy¦ø¦ø6㺠jârrR» #:dþuçòòrmÓÅ0Fü¹;ýGKœ»ï3Þ'  å"˜ìÿ¶mÛôìÿ”„¯ä_Ä÷8@o¢ÞŸùŸå`€B‰k;–‹ Αºôê¸x¿FÉÚö‡eSïó☞â!R¦“å}ýï•å£õQþè{ŽGÁiu¸nÆcý öÑëPþž”ÿ» ]8ûÃ× ÛïÍé?bÙ û ç>±Öî‹FPÕ]·Þzëó23ú/Ð1FÄ¿'áïmb€ø ø\J!„âýË’Ñ¿k¹I~»äd˜÷‹»î胿iû$DbB‰£P>Ô{ä;r"dPgþèy¦àŒ®øæº…-0o¾¹¹yVÈ¢ýàÁƒs„-Ä~CCÃì9Ÿ””Ó?þAöß5àb”7ß|óÉÑ™ž O½ÿ¡D¼Wx „#À!„BæóÖÐne ÷¼\¬FšêKü;Žþw·= o7òƒŠ§¯ó”ËâtbÄö„^glf¡ß\7£ïëÀšéœ«Usäç<ÿpú×+]t§Ýù?žºYxŒ>q!T»ÆÈêÕ«Ÿ”ãåÿÑvù÷'ì-Ÿýg€B‰27½]Þ“{šd%fÆü½ ´ÿÙÞ­šð?4v„N€àGÉÿÊÑÅÝÊœKKKµÌ§Ù§Õẅ¾èëß³gÏœqsþî"bñâųcýt§ÿH™ýÙ5 € Ý{!TÛÆ&UÁÑ'Á÷þ‹ø/ý¯!bÓì?„BH”éì“[ŽÝ#_¯¼2fïaÔ9&Ot=£ùÀ D‡L5Öï²Þ‹¤traÄö,gYY™dggSp « ¬´€£?ÆüéNÿØZzzzæ<Î}ÌF[VUUEõó²’ÁŸ7ເ6Œ ž7µfÍšGåøè?#‚ß)¾3ûþÜÿö¶Èþ3@!„Ä€õjœÞ%çɲÌÅQÝoŸå‡}?Ðù˜ :†øAD‘²‰bùh匌ó>¾øçååi½þÑmFñÍu‹púGæãæzÎaþ744÷ï—û˜?T¿`‹¥XŽgƒ?_ÀsAÿ<¡¥¥å¥W_}õ˜ÌÏþ‡Ë0˜–Ûeÿ „Bbñ_ýƒ!àŸ–^' "/ÖZ':äŽGåQ5Êoœ£ü¢NÃXµ|¨ï|IŠP¿jjª6æ,XwŠoẙp-áojjšuúGÉ9në•:îcþõÏÏÏ7@·B@¯×ÞÞÔsŸxâ‰õb,ûh @ÄÿØ?ñòø@¿% B!1 qd¿<Öý´|¤èÒˆícÿèA¹¯ýyFò›â(¿˜°rd±\Ü–$Hd=Èú#Óéžõ§à¤Pçµ@‰¹«³?Úçô㽡¿¥þš¨Q~uuu;ý3 `eðYŠøö£>ºGæŽþ‹D¶_<ܨh·üø!„±úèÝrNÞ»%/)7¬¯ËQ~±£ß;xª¼{蔈¼>úœ‘õ4ÚëOñÍ E¼¬úû]þѰoß¾9#çpþÃì/++K»––¦‰Ýü/ÜbÙªýüì ¦÷<ÿüóÈñì¿3ÌA_O¢>PÏ!„§†äÆ£wÊT5ô/rïŒòû[Û:Ù5ÜÄűø?àLY¥FýE‚ÌÌL©¨¨ðëðOñm.¡ÎuóýX|dùûúúfïëííÕz€Èǘ?ˆ~€ X$þãAœGcŸø,ÆÇo!8zûí·¿$ž³ÿ¡¼‰x_†þÿ+ îg B!ÄOuoV†€È)Ù'õ|Ç´CòÛ¦ ÿÃcG¹ &ÿ¼[N^‘×G¹³»¹E$…z¼¯LåvïÞ-ÃÃó÷¡×\ÇÍyÊû!þõà~*++ç‰W–®UðòË/?ª‚;ˆøýlß¿·q€âå>Ûfý „BÌòÅ]ýû½2¼qùÿIÒã&q#S£òd÷&YÓþtMöp!Í"þû•ø ¿øGv3V%ÿß ZDrÝ úáôïš]†ðw7›ƒßÊüõL?a˜za±lõ€²ÿîæ‹FP~ƒ·ÝvÛ³b¼÷ßÈcÄ€ð€@îöq B!Ä?ÇZ”Kÿcò©’ú}lŸ£_ò{J{¦Fù=­FùMpÁLÆÙƒ§EDüëýþ0=£ˆdÐÂJëQ ±¯ W‡Ã!û÷ï×Lÿ\qó‡Òÿšší÷"\b™¾éïï—‘‘‘€Ÿ§‚:*ûÿ˜Ìdÿ§d~–?Ô²£.ÿÌþ3@!„˜”ôÿùÈmò£Úo͹ßh³Üßþ¨lìÝ"Îi'Ê„œ9t²œ1tRØ_β²2KNŠo®›ëÏQâôèqÏx ÀuÄJý!öõ1¨„Ù.)Σ·Ï`{ÿU0ç¹t«« ¾ìß]ˆ{Êþ 0ûÏ!„b>žëý»¼¤ ÏÌ]5;Êï…þ—¹0&Ydÿà z›uáCÁIñm•uƒ›?„>Jÿuà€1“““ÇŠÊô744ÌŽùCÆÁ€hTÂ0 påà?ǘ1—_·nëè¿HŒüñ_Àì?„Bˆ¹ù2ÌnÍ”½#Í\ “S3^¡™þ…| ‡¹Y ýÍV‘ ZXoÝ ðÝþ1òOe‰çŒùC†Nÿz¦???_óÀЋýüÑÛg°ÙUÝñʶmÛÊñ츂"ÆÚ" `€B!á§m¢Cm\³SèÈ“÷] ¾ÙãøÂ~ÿH8ýS|3hËuC¹»ÓGG‡>|xÎópî#ó¯gúQ ãÍé?VbÙ.dÿ‡†‚3š}úé§×Ëñì¿«øD ÀŸ¨ŸRð[60À!„BHd:Óå{.‘TgJØ^ýÎÿ˜›QpÚg-âyÝ`"רØ8Ç鿵µUŽ;6çq………Z™¿îô¬?²ÿ¡ˆeöóO°Îÿêón¾ÿþûß”™ì¿7ÁL @ÄXÿ ~ÚŽ# „B1*Ô§äz/’œ©¬°ŠÿÊÊJIOO·¼ˆdÐÂ^ëæîôK”ü»z¸üÃðLjì8œþ­,Î#½O´i¸Oc0ÊÖ­[õì¿‘ÑF«DŒWbþgK „B1ÈEƒï–²‰â°½¾¨‡"þ)¾)¾Íºnpú?räÈìmTìÝ»wNY9^ bÙ’’§Û'*4‚AµztÝ|óÍÏËÌè¿H•û{Êô-ó·}ù?„B!Y1Z/' / Ûë!ó2gwñOÁiŸµ°âºaßpõïîîž½½ÿÿ®cþéG¿¿îy‘‘‘!ÕÕÕÚ]À²Ÿ?úû„_C°Ùÿ×^{íQ5ÒqLæöþ»_†*þE¼—üsô„B!¡SƒíýWûw®]»VýÈØ¿@¿ûÞÊþ™ýg€B!Ä7 Ô¿‹ûÏ’Ôé”°¼ÌÎŒô9ÛIpZ+¯„~ss³–ý×ñ4æ¥þ(ù×Ëüñ{€±¨ Á_ä÷itÃÃÃA;ÿ:tè…_|±Ef²ÿÓaÜDü·*Ú§ù—‰ÛþŸÄ% „B¼sÒÈR©_–×JNN–ŠŠŠ ¾ü3Kn.ñÍu›qú‡Ðw-ǘ?xàÒõ¼_¼xñ¬Ù%*`ð{€ ÅytöitÁfÿ±‹‡~øA9žýwÿ.ñ/~ æ„B!„¹äLeɹ§‡åµ vÊË˵Œ'E$Åw¼¯>ÆüŽŽÎÞ‡ì1®cþéǘ?ŒûEEEZL ï™èì®U olذa¯ÌïýWÿ¿'ï)`¤ß?ó@!„B¬JÿS¦“ÃòZ=‘îu6›à´:v]7ˆDˆW¡1h@K€NNNŽÔ××kA/}äe Þ D7 Bö_6nÜøÌdÿÃ1úÏß@O¢ŸÙ!„B‚géh­ÔŒW„åµòóó51MÉ,9×-k¡¿oß¾9BßÓ˜¿ÂÂB­ÇÏG ªª*¬Nÿ „wŸèûGG0ôôôì¿÷Þ{_WW' Š#Â_<¹?ØÇ1@!„b%õ?ð̰¼J 1ò"’â;Þ×­½½Fo~Çü¡ÕÙ~¼'8ýCüë-çáßg8ö×ÖÖôs·lÙ²N]ÀôÁ5ûJÙ¿'ñ/ž#â?ûϪ!„BærÖÀ*ÉšÊùuÐ÷¯ !+ N«Ãu›/4QÞßÙÙ9{¿§1Xdý‘ý~Aü'%%ÙVœGcŸ¡î¯¿¿_FFF‚Ú·j9vë­·¾(ž{ÿƒû'D~ žÙ!„B¼S4™/§Ž¬Ëk•––j蜱ß\·à‹‘~(ù‡HÔ™œœÔÌþ\E#Êüaö—­ÝFË‹7§;‰óx ²#XÔØ¿‡Ô92f `${/bÜøÏ— ³ÿ B!„ãü3d„þHCßßñ¸nÚH?W¡?66¦Ý‡Ÿé ÌÉ’%³&—¨ÄéŸØPÁá:É!ԹгzõêgßÿF³ýVˆø®ð÷3CKÄ!„Bˆ i«–ê‰ÐÿPòɾŠo®[¤×¢ß]èÃ(Õ¨ бßâÅ‹gËüÃáôoç€@4÷‡ËPzÿ_}õÕGT ÀˆxÏþGj@0¢ŸÙ!„BŽ“0 ç¾+ä×Áx”þ£$š‚3òâ›ëþµ€Óÿþýûç8ýwwwËÁƒçˆÕ¼¼<©««ÓÊü±-Z´(¢U/,ß/øœÇÇǃz®jºù曟cÎÿDŒgÿ½ | ~!„B¼sòÈ2Éwä†ü:¹¹¹’‘‘·ë@ñmï úÁáìïš%Æ}GŽ™ó8”øWVVj×ásëhПÇò}sï¯ë>½!Þ~ûí§Ôy1 dzÿáÎö{ø¾\ÿ}n?c€˜ÿÿ)ü]à2B!‘<$gú—)U]TTDÁÉ EÜ­®Cø»Âá>dý‘ýwÎþÅÅÅÚuˆ~W§;‰óxtuuÍiïÕ2~Ë-·<*ž³ÿáÿç¯Ü?Ñ„B!„ãœ:¼B2é!¿D‘»ë9'…ºÙ×=ý釒p‡Ã¡õû«ïÙûpn£ä¥ÿF—ååå>þ0_@Ÿw(Ù5b“:_º$4ç£Uâð0r°c€B!Ä*¤N§ÈéC'†ü:è}ÎÊÊ¢àdÐ"®Ö“Ó?úÂ1æŽÿ:(óǘ?˜þ8ý#àìñÒà/vLj쿫‘c (_ˆ©5kÖ<"3Ùÿ) Ìõß)Ƴÿžn‹xo ù¶‚¥ÿ„BH¬:AÒ¦SCz d@}¹þSp2haÆuÃø7w§dü‘ùG€Êü1æãþðºèÿ—Ó¿f8FÿÎÎΠ_Oµ‰l{ùå—aá)ûl5€ø¸. {fÿ <á !„Ï ÷ÕÈŠ_ÙP÷hŠo-̼nýýýšÓ¿k&-ÍÍÍsÜÿQæ___¯Mµ@ «¢¢"¢Nÿ Dˆ×Ï7з|ÿý÷? .1š’ð¸þ{ÿbà9"Ìþ3@!„'Ž,‘4ghÙdEõžh+ NŠoë®JÀ]Gúá²µµUŽ;6çq0´¬®®ÖŽ-óçêôoeqnÅ€€Ý7ÏÐ1ZZZ^Ú¼yó1ÞûŠ?€Ï¥ Qð30À!„Bì†ÊgÊiÃ+C~£}Ðê\‹X¯îÃ8¿¶¶¶9÷yrú‡¹_YY™ö©©©Ú˜?ì*έÀ„‡P²ÿ=ôÐ:9Þûïîöªë¿»0göŸŽ¿#\B!d†¥£u’3ši_FF†¶Q|3haöuÃ~àôßÓÓ3{ÊÿÑï?888GdÖÔÔhm-Æ–(û7âôo瀀ÙÆŽ}}}AïûèÑ£¯>õÔSMâyô_ Yñ!þýU0ûÏa@€B œÓ†Oéùøòéxœßö[7úÁÕßu¤Ÿ'§ôùÃé_ïñGk ªâ]œGcŸf?F´x¸?>{ì±ûåxï(f"Æ«üµ0ûÏ!„BˆjÇIñdaH¯‘„Òh NŠo3¯~cc£_§xYÀé=þx}LµÐ«ì&–­vŒø¼]«<EµŒ¼ñðÃï’ùÙ_åÿFƒ"ƲÿÞZ(ø ÁþÍàB± g ŸÒóñÅ:ÜcÐÌ*"´ˆßuÐÊþ]…> :4G,fffÊâÅ‹µIxÏ(ùGé4ÛˆÜ>]=‚aÆ ®Îÿ¡–ÿ‡+ûŒ¦¡Þa€¢žB±¥“ eÑxiH¯‘››ëÕâ›âÛ ëæ.ô½9ý£Ì¿®®NëñG@wú·“8·r@ãGGGƒ~~GGÇ®µk×¾!3Ùÿé0o"Ƴÿâáñ„âö˱€¿„BÈ\N^ÒóñE=??Ÿ‚Ó¦â;Ö "ßUè{sú/))ÑÜýÚY þý¶hð?Ljׄó(¨ìÿ}êb\ægÿCqÿŸö!æý¹þû øÓF„Ó‹÷H½¶ü…"„B,EêtŠ,« é5ýG¦4ÞE$ƒÖ[7OB³ß÷ïß?ÇTUUi#,Zuú·S@ ^\½EGkÖ¬yM]uûN O+€/áÎÑ 0 `ðñì…!„BËÔ迤éà¿òxÊþS|S|›aÝ0ÒÏÝé€MMMsD D~}}½È¸ ‡Ó?æ:Fœ!íSý[+ž{ÿÃÕëïIà{ 0ûÏ!„BHàœ4²4¤ççääD5û¯BÝê˜mÝ ôáêï:Ò€ÈüCê ¼fÚmŒ±Œä(Kb·Ox@¸š?ŠÊþï½ûî»_‘ùÎÿ¡šþ‰Ûâ! >ù _'üüñ—†Bˆ¥)šÌiôŸ¯ì¿™D$³äöZ7O#ýù=|øð‘˜žž®ùCU¥¥¥Ú(K+ôº²O;#Ú>Üýå‰'ž¸GæfÿÃ]þïMøöÌþ3@/þÛø @!Ķœ<²,¤çc,šƒ4Šo-¢µèñFÏ¿Ó霽¯¥¥ežñ*WPöŸ˜˜¨U°”——k³ ×hìÓLjÏßõœ@Ú­zÿ_ÏÙÿPûûŒýcöŸ x/'ù‚^‡ÙB!öù’3(ËÆêBz ŒK³»à´ü—±8Z75žMŽ92+.!ø8 }}}s·páBÍðïUwú7ÚÆÂ€@üí#ÿ0ú/ž|òIoÎÿ¡D˜ýg€D5hàí¿„B,Ï’ÑZIs¦ý|ôL»ÎF…ˆd–œë¦Ï¡C‡æ”xÃäf®b¥þú9ŒÌ?ª(–­{Œmmm!½XÚuï½÷"ûïc£þ‚ ˆ0ûÏE{ØŸïk¤†«!„؄ǖ„ô|Ý1â›A‹X® ý`ì7888{Ÿ'ôø×ÕÕÍV­àüÕËÖ=FdþGFFBÚ·êý¿W¼gÿýœb¬ôŸÙH¾F² €BˆmÈrfÈ¢‰àÅÊ¥1'ÝÊ‚Óò_–,°nãããóœþáÐÜÜa€>öoxöðç¬éäRB±™ÎôÊÿažª`–œA‹@€ÉJü‘í×AÀáÇý:ýDu=ˆý>1‘¡ KÏoÚ´i¿„–ýwŠqã?_ÙÿPG—3`À€åF\ÿýôë.1!„+±d4<îÿßêÑX ˆ~8ýë%þxLKK˼ÑnîNÿÈúÿÿöÎôK®ê<÷»Z#HÍó<ÙÁ&ä.Ç^we%Yɧ¬ø[¾äËýî§L˱×JlÇ8v°c ÌÅÈ„0ó`l Â!BcKjI­¡Õ-©5vwÝýžÖi>}†½÷Ù§êTÕï·V­šëTUWuçyß÷ÙaÒ'‰åN7äòÞÞÞB­s†¶lÙò_ú¤|è’ªÿE–ü£úÒõá—£–py^@x^¾ð—_ùÜOÿ·>–ĘI×]‘C-å|-átü  ŽÇýoãÏPIj x¼ZÆù¼Óá±ü&Mû??üâÿU‹Õj—'&ÖiÓ¦u¤PÇ´hüûvöìÙ Ù?lñ—ciùŽѤÈKúÇh_CàôéÓ…—ýûä“O^zûí·»Uzõ?ÉQöKþùªþçi'Àè(s /ü/Í W¯_‰ ý¤C-Ãp1²v*1ÚÛ0¨žÏüÑëä7iÒÂ… oЇ®O<^Qm7Á‰iQdù6©ô‡ÂNBÝ$ìïÒ¥Kãn7þ|µjÕªà=ƒJÂþä¸Å2íûÅð±ìŸ6™.?üðÃaõ?oé?ÛÊYÕD>@Gû"÷O[ éË9ùò‡âÞG€²0|~ €Ö3Lªþ&@׵ߴ®¿ú«¿ú”®:G¡çˆoL‹¢·•eÛŽ;6®[–÷ñ û–/_®/^œ–¤©üûHúo–Xfž¿ò™)¸ìŸÚ¹sç³}ôQ¯òSý71”¢ú€Ð/å¾ñ€º2[ -Ð#JWìò®k§k±ÓñC=átÝ£Pã@ˈÿzÎeñ߈´Ñ¶DMuí÷¨ëÖ[o½ÅõIJKµkeµÊ‚ñ]÷MÄ[<é_*ºÝÝÝãD£´ù¯^½z,àO–¥# Ý:†€9.\FFŠ Ã&Ïßwß}?U£ÀÃ9¢¿H€RÙKýQýÇO†AÒÎRÝÓa$"ö•øÏêðe˜P  ë²<ñ_74ºt«ô§\Ÿ¤ˆ,„:¦EYHû¶„ý‰ ßé8zôèøóÉ“ÕúõëÇ>sæÌ ÒþãB’yþÎÙ¦à?áÝwßÝÚÓÓsFå·þ—Uý7öTÿ1@%·ø§íH%uýc;U1 Oü'JÐŽbÞ‡ö;ÿ=I˾©}á _X2cÆŒ¹®/,\Z­ÓÅ7¦…ÿÛJÒ¿„û…ámÒ çûûûÇÝNºPDüK¥<Ö‚ 2W¥hw±Œ!0Š|NâÙ¶hãéÔ=÷ܳU]Oþ·YîÏWõ?m€ê?‚_e·î×r./bÄEZë¿R€ùÿnÓyÿ¬jªø—ߨ?û³?û¬ë“—¥ÕÊjÿG|w¶i!k¶‹Øg·uv0ïv„Hþ„ˆÿ0éÉ’%FIÿU®TëËÙ¦|nNž®M„KÊ®ú_w4”PDðc `´½ÐOkLýѪ¬u8ÓÄ’ðOšùÏ3ÒvÞ’vkžv2 ºæ@ÚÿþøïC–ÙýMœpÙ_ÿõ_oÔ¢išË“±%3×UœˆïÖ~ßä9Kª¿þð¼¸9rd‚P”ªð'¡2ó/íÿzžÕݦ<Ž˜HñdzE?Æï·lÙò?j4ùßt‰?s IoPýÇF‰5 `b$%þ'íœeµý»´þ#øZ[èçÝÆ¦í¿– øÓ~»>ûÙÏ~ÚõÅHû¸“ŽPïÓ¢Œ÷M’þe™¿óçÏÝOÎË(@16lØ0–ô?{öì`É¿èç°™ÂqÞümúþ“Íÿä'?yL]oýQnóþ¦ãÊÀ("ø10ø=ÊÙéªgg þ¼ªýÚu¦âß×òì…´¦9àÒöo:rV¬XQùöªäíý¾]¾|9û“ãÐ eÿ$0Št›è¼Š±®“ùóç«›o¾¹RÂqÞ\£EfþO:Ux[{÷î}õ¥—^Ú«Ò«ÿ¶F€RTÿ1À» Ïªú§¥g}qj†F@VÕ?)ô¯®Ê ÿCè´¶àÏû¿ïCüõIëдIºzµÓ“×;àñ¤uÄ7¦…-Rñ—ùþ0¬M–ýÓâkÌ ‘Š¿$ýOž<9hõ_´h‘“…!ÐÛLÛÞ‰' ÿéû_~衇~¢Oʇ0¯úï# PE?Ɔ€Á"*þóŒ•bØT`ÒÄ¿IÕÑкB?ï¶yâßÔˆG‡¿Uµ¿üË¿\¥M€é./JB×5sÝŠB½íw´<¼o2ë/Iÿ¡˜ÓK­•ÿ¸€“JÿªU«Æ%ýûZzC } Y)b`` ðcíØ±ã—~øáqeWý·¹.®%¨þc€ƒ°wyœ¬²zÎé¸àW âß6õ¿¬öŒ€Ö3 òÂÿLÅô7jÂoÐm·Ýö)×',@UÅ7ÝÕß$¤M!²d[Ô ‰&ýKëYIÿ­¿Mù Egœ¹÷Þ{ªFgÿ³‚ÿ²ZÿGTvû?Õ (ÙHZÚ¯føÅ¨Å®Ïüqñß•¶Ã¥Ê›ýGä´®èW9¿.â$Å~ u’ú×'oÿG|cZ˜¼>9¡Mú?|øpкˆkÖ¬ þ œ\¸páØc4C¸"Ϋû¾öõõùþS/¿üò½ò„¬8tíÿ§mê^Û¿RTÿ1 á†@üËbr›´Ëâ†@™âßt‰(h-ÁŸv½©øW†¿5ñεšž£v2d‡ÝG@+ õ¶ßy*ñ}“Ö~™÷“þå¼ÌûÇÃþdÎݺujÖ¬YÁy ú‹&ý7K¸R­¯æö®^½:aµôcì}à^Qã[ÿmÂþLgþó:ò„=Õ „½Å}ÒBmˆî<% åAüWeÙ?ö†šó¿6í÷ÀTü§u¥…«Ø¨?üÃ?œ¯Eü—',â?k'*yµÄwÞ·+W®â?¬ÒJÈßž={&Tm¥Í_–ù ?c:¤RÝtÓMm)\Ù¦ŸíIëÿÈÈHáÍ>õÔShSJ>IÕÛÔÓêžp§ú–æ€I@ÍáK4¢&†*å âß¶z­#úÓ~LçÿÓ~o’Bjkþç~‹ë“¯zõñ]­÷MÂÙDüËò~‚tHå?<Oú—–ÿ"KMb´¿! Ÿ¥x‰ úóøÚ3Ï<ó¡º^ý÷Õú¯Õ hº9Õ`Û'ømÿHÿ豟u›"â?ë÷&ìùÿõ®/(mþ¿•…zÛï5é}ëïïfüà ­¬ÑÞÝÝ=AÔÍ™3'˜ùá/ÀâÅ‹ÕÔ©SK’ˆóÖ7ä3ÏŽpAQõ²«Ñà¿á ñï£õ_)ªÿPHÌ›\gÚPOØñª{xŽ.€/ÑÏ^@k.ËþeµÿÇ«ÿ¡ PÓ3Õ«\Ÿ¸IB½ü÷¢êý£GÏSÇŽ ÎÇ‘”I÷—×"¢_Ä¿˜åÖßf™Û“Ö™ÿ/ÊöíÛYöoØ@ü»Œ(Eõšj˜fÔ ¿Dõ”°ºÊnùÏÚÑËñˆ{€ÖûyÂßEüGoÿѱµš®¸.wÿ­$ÖiíoÎû&UIf¤R»ÿþ  .Fu'J0ç/HÒÿ‚ Æ%ý7J¸b´Öö$;âìÙ³…G§œ¸ûQ׫ÿy~ñ¯TþòiÂê?dˆn“ëâ?ÍHýµœ/_-e[I&€RåWÿ1ZÓðYýO:wXÕç?ÿùES¦L™åj´’Poû¡Š½o’ì/-þá\¶Th%ìOrÆíDë ¿ÌûËÜ¿ Iÿ2öü00¢¡—ê›ðX.<ûì³?Ò9ƒêzð_\Ü­ü×SÄ=Õ h²‰fd™õ á?_WÌýt²¸7½­Éo…Ië¿JÿAûÿç>÷¹µ®/Îf.›*yg"ö%ìïâÅ‹ÁùÁÁÁ ì/Þ¦Oú—%þL“þ10¤³DV‘(ŠGyï‘GyKVÿmBÿlÓÿ©þc@ Þäº$‘ŸgÔžG’ðÏë8ÈÛÄh_SÀGûÒÜ¿JÿÁoÐÊ•+ oˆoL‹8Rá?xðà˜Ø?sæLÐöxRññ?iÒ¤±¤¡’ü•¿Í*¼Fù|…£%EÐc)W~øáGôIYö/ü—×àög:@õJ0LGLFòŒ…¤î‚¤ãºƒ€Ð>F€I@Z¶LVè_=ÁC—ž³^ãôäõθm8â»ZB½ Æ’þÃöì#GŽL¸Tú%é?ü‰ø/ÃP¢Zß¾¯ñøñã^Zÿß{⦅¿ýöÛÝêú²e$þ›¤þ+•<*@õ,D¾Ë}MMŸßéKÚŽËÒQк@ü7"-P6J–øïJØ­Íž=Ûika@Ur áôéÓã’þ¥ @.‹#ÉþË–-Kúñ/&@#Þ öØžMáxIôÌÿ‰ï~÷»?Õ'/_û?9¢ü&þ tüaiÿ7 té(Hÿy_æ_x€¶3”Jî ËjÿW¦âÕªU3uËõ—'ï{]öª uL‹üÛ†ËúÉR‚^K=˜÷×âj‚(Œ&ýK»¿$ýKû§W âÈç+ü¬eëÖ­?Ô+HJåPñŸd¤Uò©þc@D¾ X¤ ÍÈÿ5ƒ/y-)ü³ÌÞ¤±´pÙ$á¯2ÄÿØNæŸþ韮UŽÝcÑvmªäkZHÒ¿´ü‡Ë°IUVÄ<˜Mæü%éÖ¬Ñ'ä84:E¸bøÙÞÉ“'ƒ“¢:tè­Ç|»ºÞúï*þ‹Œ˜vPýÇ€›qá^d ïtž¨¯ñEhYÑŸõ¿=ÉN[&þ[0¢’«ÿ*cGS:Vº¾ ªuTE|w’i!•ØhÒ¿´eKØŸ˜Q¢Iÿ‚,ñ'Ký’ˆór¶Yå×(KJÆ;K\П݋÷ßÿ£j´õØ“ø·øõ ñž×À¾?”`dUçm»Š ÿ²?yýÉú_œô;4:–õ¿;^ýÏ›7­éöëeN? zg½Q+ ¾«iZ\ºt)˜ñ¿råJp^ª²º¢:AØI¥_*ÿÒ Û–ÿo¼q^ámVõ5бtâÄ /Û{çwžúàƒŽªÑêÿpIâ_eüV*;ýßec€-e×t™ÉH@|G®^à9&št(þI´i¦nšÕoÿOÚÙLÛñºôzëNÀ”)SêlZH¶»»{,é_F’„Ùüùó•î2 ^Ÿ‹-*µsC ½_£|Æ|´þëq•ž»îºk›>yÅAü䈥ò—÷3íPŠê?TÆP*IÀ"ϱž#ô]·GÕ ù¿KIÿ“ëA-ç7-^ùîdÖ2žCM¯Ã¾ÔåET¹ýŸÖþrß·3gÎŒ-ë'Ù}ûöÍÿGYºtipÄ0Š&ýwšpÅ(Ž|Æ|´þËÓâ‰'Ðc+ƒÊlÙ¿¢Éÿy¢ß¦úŸ PP€§í˜åUk²N»î(Ö<¾Vh,yfn’él»¬m^»é„ùÝÂ?E§°/vyAIUêí,¾›ý¾I¶··78-!{öì F¢H¢¿$ýÏ;78/sÿ"þÓV@œcä!F“¯Ôÿ>úèù_üâ¨ñÁeˆ¥ìºØoÇ€’¾© ¶c¦ _ÏÑ·ýÊ2\§TÂïNÔ@ÈÚá¬é–j±æ´ÿ’f ÔÛó½×"Uÿþþþà¼Tb%é_B㟠û güu‡‰QÒ?â¼qÛlÅ×(ÆSÉ H3LMÛŠ´ÞïQžÈÏúýªçlcì¶ðༀ€ªˆoL‹ìÛŠÈ—y-ž‚óR‰•óq‘§»IñŽ‡Ìž=Û9éC€×"fÓàà —ç±uëÖj3¡ßƒøOê°É úÛé²éÈþyf€­øP)¿5ñÐÀ¼ T×âÅ‹W”a ¾ÛÇ´6YæïêÕ«Á6;¦Ž=:áv:LR­[·n,é_ªþ3fÌ@œcÚ¦Týeu èÏñ¯{ì±·UrðŸMò¿I RÙ•¥¨þc@K˜¦F€‰u¹ÉŽ´®hw]A¦–³™—ý½ªéíå./@DžÌy#ÔÛ©¼Ê²~"Â$y}ÿþýc#QdY¿•+WŽ%ýËùF„Db´ÿkñï£õ_Yguêÿ#úä¥kâ?-øo$Ãð1@õZÀPF@Öå6B¾Æ?€¶þ¦ÿû“*ú&[O8Ÿ–:Ý¥ç´}‹;Zû«÷¾IÒOOOp^ªÿöŽDY±bE°´Ÿ&ý‹ uˆór¶ÙίÑcê¿zá…~¤ ,IR׫ÿ6Uÿ¢3ÿYéÿTÿ1 b&@ÞmëbÝTÈ#øÚOðgýOÏ ‘­©äðÙ´û&IÛ:´°Ài‡grþ.â»uM \“ƒ ³×ö'&@éY»vm0ç/HÒÿüùóS;C¨ÖómÏÛéÓ§½<–YyÓ¦M¯©Ñà¿°úošúïcÙ¿¼¥õPa@¶;}>¾ð„Tó7&ïwZNLÖé¬ß%ÃzLÃéJþ<—ÖŒÀª õv55$é`` 8/]Òö|IIÿá’ˆs ¢Û”Ç“Ö;ñ`$\¼÷Þ{P[ÿËHýW&@üÿq^Õ (q­æñöyË=e}ik^T—¼pٸொ|“Ùÿøó¨iw“®äßà´Ã3Ùl—‡Öþj™Y·•9ë0é_n×ÛÛ˜qDô¯_¿~l DRþ‹$ýc`Ä‘œ‰‹/zy.o¼ñÆ–;vÈ,ËUåüg“úŸUåO›ÿwÙgß<5‡/^Íò Zã ÐÖÂÞö÷ ÉÈký·5£'<çÛn»m‰óÏäöÝåéDÓâÊ•+êàÁƒÁ±¶)ŸAé<ñ´þßyçϪÑÔ“6ÿ$ŸvY#–ýC`@ƒL›¹¤2Û@å°M¨Þo‡­Q&ü³N'm;É,Ⱥ\ÞµlٲŮ/¸ ~Þ7©øKå_:†††‚yÿ¤à5 ú“À?ABþDüO›6­aï-íÿ¾†'ñë]Эÿƒwß}÷ýjtîH%Wð‹,÷—×þŸ÷[AðTpg®h+~­À}]aï 5Œ‚´Yþ´ö~ßti·Ðé‡Fï¬Û,ˆP/ÿ½p}ßdÖ_’þeÖZZ®%é_*°ñ¿·,ñ'Kû 2ÿ/aQˆj=¯ÑÇ6O:5áóçŠNýd×®]ÇÔõÖÿ¬p¿"ÁJ±ì´ÝŽZ­àý)ÎùçP-lW‰Šþ¬$ÿ¢¿)µY³f9aû7⻵M iñ?~üxðüŰ¿øzëRé_·nºé¦›‚ó2÷/F@ž„!Àk´E (Yöχzû¾ûî{E¶þ«ìп¢Ái"Ÿeÿ0 ƒ€¼/,U{€öÿ IûŸoÛêŸw¿¼Öÿð¸kÆŒN@Ùíÿt ”ÿ¾IÕ?œ³–åþ´`špiï—¤YÞOП— ÀåýÆà5f!(’úïƒË—/|ç;ßyPoýw©ú(·à¿$#€eÿ0 Ã_zövÚç·$IÀ›Šú¬ß‡¬ûtÝpà NKJU¡ÞÓÂ÷û&þÇ«ÁÁÁà±å´qDìKҸܣ¤ü‡]W ßÛñ/ù>žÎÖ­[ÒÝ,§ÔhëÚÜ¿Ë쿯à?–ýÃŒ€†™ÐLa1ëŸöüjºÂ;ÛåΡ(D|·2[-•~]! Ä–´ü'µ\K•íÚµÁk—ÃܹsKKúïdCÓcù Š!å`ùú£>ú[u½õ?+½?ÏhFðûþÐ"F@³Í¨îïCÖo„‰èw1j ÷©Å®«éyn§ÅÛmßÕ08d¾:Lú@Âþ.]º4ávK—.UK–, zŒ&ý#\y¾·)¦T__Ÿ—íèÕ,Në[ßzDŸ¼¤Ê ý+3ø‘˜ÐF¿5‹ÛÛü–ØÞ¶¦çºõ(ÿä™./&è¡ÞÝRa “þey?Yæ/Þn-ÏeõêÕàvhuÎC<éáŠ!às›á’ò¹ôñ°O=õÔý:ÔR‚-†Ôõà?Ûöÿøì?Á€Öf¦d {×YjñãÏ|æ3sô±S)ßµ Åw³M ©®†Iÿ2g-#qÑ'†ŽÌûëU!‚ó’ô/âßôïŒ!ÀktA–ü»zõª—Çzÿý÷ŸyòÉ'§Fƒÿ† …ÿˆè·]P)‚ÿ0r¾ä˜e’´­š®öÎu}Àhâ»zGx{þa{õ‘#G‚óqâIÿ:2˜ù/ò7bžC ™ù—nèÕ,üû¿ÿûObâßVø».ùçügc``@‡6;r€Y`óûQÓÞ9¾ Äwµ i©––ÿsçΧ%쯿¿Âí$ÕݺucOé´„+¯±ÌmÊø‰Tÿ} ;.~ÿûß¿ûü¨›pUe/ùç*üóÒÿóöïë—€wÃÊÅe¯»Œ.€šáeÒ×Ý5{öì–0è.°{}ÒR-KûIÀŸ¬É¼¿G›p;iñ_µjÕXÒ¿þ<”žô!Àû*Ȳ“žæþÕ‹/¾ø£wÞy§[¥/ùgø7’p(˜·ÏβÐʺ¬ àjd þø*2tõ×ÙHš G¨7ÿ½Ñ/â_L€´°?A’þåþ-¥å_F®¼Æ²·)#)² …öíÛ÷Æ~ðƒ—Tò’Ib>MøÛVýÓL»\)Zÿ1 #Ì€fÎø›l[Vh耭.¾«nZˆà—9©¬ŠÈ:pàÀ1&»µk×Õþ`§U'üKêRÒ?ÂCÀ÷6¥e``ÀËãêñ–ÞÛo¿ý‡jtÉ¿!•Þúïsî_©ìö‚ÿ0 ƒ{×>c\w€NzwZЗ@Ç€¿÷B¸œš‹gÊ”)AÒÿŒ3ÆÎÛ$ýw²pÅô(Žt¥È*>Пó¡Í›7ߣG $ØBZÿ‡ ÿ¢-ÿÿa4<í߯@¨iè4ð5ÿPoì{.í'jrZªþaêIö—¤YÞ/osÿo¼ñÆ–mÛ¶íT£­ÿÃâݵÀµC OäÓúÐ03 i, 8è§€Ö~ÿ·íïï—ùçà6Ò â*Ž$ûKØß7Žz;ú'•ÿ¬àÆN®TëËABÿ’:S\8tèÐ;wÜqǶ˜ø¯+û—%•ð7mý c!Ÿ6ã_3ÿî«+ÂN­$ìÛ¥c@BÔBAµoß¾`®:ŽÌöË2bÓ§O÷–ô!€!`ƒ´ýK>…tÈeï׿þõûõIyÀ¤Ð¿¼j¿MH`‘Öÿ´Ûd7½0  ~Öy¯ÛÒIð“u%j™­ýÅM 9}ôèÑ@ðKÈŸ„ýIè_úkÖ¬ëÎ3 Ì¤  4dL%É rA^—7mÚô]=î"k[†sÿ&U}›Ù~_­ÿÿaTÂ@ˆ/¨æÍ›7ÝuC¾3ª*¾›mZHµ_ZýEðŸ?>XæohhhÂí/^¬–/_>v^fÿÀN›uGœ7w›bR>}ÚÛsx饗}íµ×öªìÐ?›¶Ûª‘ÖD=@é&@Ò¨ÀtÅxj+¿Ðvï!%â_Ž¥Z’þ“ÙêÕ«ÅÌ Î‹13{öì Iÿ$\çÙfÒöİòú÷ñÇ¿tÏ=÷¼ Fçþ‡T~èŸIÛ¿mÕ?ñ­P´þ4Aì+±_K8®éñiõjšRñ—tÿPPé´ ·‘P?™÷Ÿ5kÖØyÓ¤  ßÛ|†þõõõíû×ý×ÿ§ÆÏýÛˆ~q_…ÖÀ„}ùÛÐÎ@+ŠôVÉ#ÙiIú—%Ô<˜ØN-á~7n þ ý+’ô!€!P ©¼|ù²—ÇÒá:ñÿ.%p^Ÿû·ý#­ÿ*CüÛ~Ì €ÒÍé¨ä@'w ˆˆ’ƒÌù˼¿ÌýÇ‘`¿uëÖ‰}i÷÷ô!€!`ƒ˜V.\ðòXÚøºúè£ÞõÁôè³WTþ<¿ËŒ¿© $Öm«ý´þcxöµœÛL˜–6(n²qKñ@kömå2©ú‹’*ª$ý'-¡¶`ÁµråʱûKÒ8Ш×ÙLáŠ8¯Þû*ã*Þž×Ë/¿¼ù™gžÙ¡Fçþ‡•¿ê¿1€¸p§õ0 T¡ïíquùÔvxƒZ}©A™™îéé *¨YIÿ+V¬P‹-;/aÒ§WªõÕÚÞÕ«Wƒ_¡;wî|öî»ï~."þó„½Mõ?é>ÍLýÇÀ(dÔlŒƒ"€‹ ! 0Y@IØŸTýEHÉÌ\LI²ÿÚµkƒtÿð¼ˆÉ@¸b4k{b\IèŸdUø@‡]îú—ù—ÍúäE5ú7œ#ìóþ‹ü©áo*èiýÇhˆ!6wÉi7•·«9¦…ÜVD¿,ó'Õ~iÿ?zôè„ÛIÈ߆ Ô 7Üœ—¹1$ôáŠ!Ь÷U΋øOêTqAw¾ôjñ§^òrP%'þÛTÿóFF”YÕŸÖÀ€ÊˆüÂèJr¥÷WZ½µ? ™õ?~üxPEíîîNLú—ù~Yæ/û²¼Ÿ¤  ¢HP¥ë^K›—6mÚt—î„9¥Òÿ]ÃþŠ.ù§bAšø§õ0 ‚?5,PÎë:óÛ)­ýYô÷÷K»sÐþŸ–ô/B_ÚþÃ÷Jò¥ò_æ{GÀï« }}}‰•®Oõ¿øÅý¯¾úê'j4ñX™Wþó–ú³1ÒÄ9­ÿ€-iL¸_­ƒ•x³º z{{@’Ó%é?©ŠºtéRµdÉ’±Ç‘ö™ù ;ªõl³Û“´ÿÁÁAoÏí­·Þú¯Gyä7ñŸ'à]ĽmÊ?­ÿ€íg h!ÐåKT´‚øn&”&3þ"ž¤ýß¾}Aû ÷[µj•š7oÞØe3gÎ F®ÍÞ^øÙõ…6ÀÞøÆ7¾ñ”>)íW•ÝR~®•W3 MüÓúàG 'ù$h¡Ž‹4þ .»lúôé’þ®l³YÛ“Š¿´ýûÿòÔž~úé<ÿüóéÓ—#âߤêïZùQöIÿ¶)ÿ|À€† þB3R ¯×‡Ъ­ýY¢IZþÏŸ?Òö‹¥ÅݺujÖ¬Yc—IÊRÒ?ÂC ۓϬ˜Xq㪯¿þúã›7oþMLüûªúçÍý§& ¥Ì—üË}ûùYèŠÑP.PÞ«j`ÙFDÚm¥]Z–ù“´ô'N¨C‡M¸$úKØŸTûC¤ê=ß ÂqÞ¾ï«\/3ÿ>Åÿ‡~øüüÇüâšøRf¡6KÚVü}-ùGë?`@eÿоBÁZ¥µ? ™óïéé D“1âÌœ9S­_¿>èdÎ_æý‹$ý7K¸R­oÏ×(§e©?ù<ûBÞÕËý=¢F—ûRÙíü¶³ý.#6sÿÊQü@ㄽéí›=ЪDÍ…ÁÁAYÓ<3éþüùjÕªUc÷ “þË ûÃÀpA‚+¥ƒÅ½½½éK_úžö%Ód¹?Ûöÿ¤êü8­Â¯.óµäæ@eŒ€1ôŽùP;ew œ={6˜ù—ÊÿÞ½{3 ÎÒ¥KƒCˆ$ýËü¿l«Q] ¼¯yHå_B+=š Ý_ùÊWî8+_³Ä—Ð?ÛÊ\ô³ä`@G ;©µ"¾F!ÔË@Òå SIú·MKuíÚµA¥?Dfý£áU®ˆs ßâ_a'ÿíßþíÛÚ니1ï#ðÏÖ`î0 3LݶN ¥¹ ·Ñ­ÍêܹsÁA*ÿñ(™ë—°¿o¼qì2Iùžo7É6³·YÅ×(·—¶Ÿâ_bwÜqÇ7µ)v,&þ‹þe%ûXšÊ@èÛŠ ¨6E Ÿeu—Ûæ!B?Lú—¤ôîîî ¢KD¾„ýI«(¤ê/+´‚pÅèŒ×þùœù×£07mÚtÇöíÛ»•[Û^û¿Mõ_©üŸ"s0 Ú\)÷íÛ¨Jk—/_Ä¿ÌûK蟜Ž3gεfÍš±p?9–eþ|$ý#\1|m3¬üûÿÚ»ºyóæ;_|ñÅ"â?¯õßGÛž  R„¿R´þtuÝú[ láS¤càÂ… AØŸ$ýˆYæOZ¦£H¨ß† ƽIú—@„+†@•¶)·—e*¥›¥ tæÿðÿ°IwÉ ¦ˆŸÂ?­ÚŸgÄ…âs0 å ƒ h ÐšaÒN_¦PT\:u*h“–ç)añ%Ò$ìoÍš5A«ˆ¬Š iÿ>D⼜mvâû*ùbf•5zóÑG½ü¥/}é‡×ÒþÓÄÙ#*½Å?Mø#þÀ`g¶p@•‚£Hµ_ZþeY4NŸ|òI03E‚þ–/_>î2ép]qÞ¸mvÚû*Ÿciù/cÞ_رcdz_þò—7ë“Ä¿kÕ?/ðÏfÞ_)?‰ÿEþ_`@ËÁŽóµ/gÊ EÍ€˜ö'Iÿ"úu[sp:Dªý«W¯VsçÎ'æ¤å¿ìn ^£ bdIKY-ÿò2^yå•ǾûÝïþòšøJÿE«ýYsÿ¶iÿy‚?OÄ#ð*#ÌkžÇø¶çâ=ñ–T­@„’TþŘá´oß¾qÏQ¾ÌûK¥?jˆø&ý#\1š½M1­¤å_L€2Ð;ôË_þò¡xàU}ö’­ü»¶ü›¤ý'Uý‹ÿe'ý/¤õ0 ­ h0 ÉmëZ`T¾À©ö‡IÿúwðàÁq¢LæúEüKÀߨÛäÉAò4áŠ!Ðìmʪe¥ü z,æâ–-[îyê©§ÞÕg/;Šÿ<ÑŸ—öo»€R„þ€»FÑB¹P€Ì×7䉿ŒHµ_ÿ„'NÈ:æã®O û“nÿ6ÂŒ€¿ò·ÙÉï«t«HÕ¿Ìï•Îý8£«þw¾ð _ÿC–âß4ÀeÖ¿Ëý!þZOÌ«ñYí²c—ëYùBeÆFY¢Jªýb"üň’ö'Ar("ü¨Öó}mSNËøŠTýËjùôwåÀí·ß~§Å<¦Ï^qÿE–ú³­þ+År€m*Ú½íúþýûÏ_Ûïr1Rµ”ùùF¦¨0“óaÒ¿œÖ¯E9sfœˆ“°¿yóæ{™ÿŸ6mÂC Û ó*ʧéîîþŸ¯|å+÷õ÷÷Ÿ½&þ‡-¾kÕßt©?“ªšèwóˆÀ€J ý¤*Ía·Ã:l쬞‹Ÿ]DÀ4ˆ"¦Ãñãǃª©l_’þen:DÚûׯ_´øGEœˆ¹Îfe„+†@YÛóJ>·e-ï>ýßýîw¿üÚ×¾ö¸þÞ„Ëü\3ê†âßµêïÒþ¯”ùr$þ`"X¡F® S™ñ—9i1vïÞ=nô›o¾Y­]»vœÐ—Ó²Ì_–HCœ7f›þ¾ÊçV>Ãr(ÝYprÓ¦Mß{å•W>QÃþêʼõßEü×-Ä’ð¯çüßBüt”è·¹oæy1Š<¹FR1 “þõsÄ´‚ºhÑ"µbÅŠñ;d×–ù³¼FŸÛòÒÓÓ³óßøÆ½‡–/ÌU•öçZýÏÿI˺¤þg#þÀÒ¨ëjd_‘iÄJ:¸l,àOf¦¥í_rBA—ö'c 2€pÅhæ6¥SE>³ 2Êêï½÷Þõ«_ýIdÞXŸ÷÷Qý7ÿEçÿÿ€ üäŒíPëÊzU k'Ož ø“. ü «¨Rá_·nÒ# ãî'¿Ì\ ^cò•Ï­t«4Ýapþç?ÿùüã¿­ìæým ños@ü€¥PÏØ9NÚ ÑK.ò¤_Fª¾<®Ìû‡ª¯¯O8p`L°‰È—¤ÿ¨Ð“þÅo‡8/g›¼¯é÷oÔœˆþž|òï|ç¾]»vU£Kü åˆtWÀVü›eŠ h{3Àdy¬`‡û´¦è†¥ šºïãñ¤Aºô:æc×'…ýIÒ¿ˆÿø’„TëyئÜNæü¥ê߈9ÿp³Û·oßvûí·?©¿3¯‰ÿá Ñ_¤ú_EñoúZNÔ›\n³ãìt;v¬¯è“ôiˆˆêíí›ñ#àÈ‘#c×'…ý…ËüÉ1ÂC ‘Û ?³ þÒaÐ÷ÄO<ôôÓO¿§&¦ü—mTEüÓú€Q±#ß!Ñz…;$èLxQ$%]’þEdÉA„¿˜¡¸[µj•š?þ¸ûL™2%p¼F×m‰ð—VÿF AwÃüî[ßúÖC:å_¾»Ñ–ÿ<Ño:P/Yü+ñoò?ñ†;ÁÁÎ÷ÁƒÏksYWÏSóÄ(J4éÿšÈ[öOÚú7lØ fΜ9î>Òuà+éCCÀ”Pø‡]*BÚü_xá…-÷Ýwß+jbП/ â?oÉ¿¬ÓˆÀ€¶íµlcì´4ýZH/* L ‰4úRýÏïÛ·/0ø"þã#þ7}útÄy ÛÄôH¾¯ÿ‹/6\ø zTg×]wÝõ ú;¦®ÏúçsŸ@⿎ø ;£Àµý?¼lD'í2$¬Ïe%i–¤U¡ÈÚ»w¯Î'…ý ñ¤„+¯±¬mÊgTV¢C£[ým®]xå•Wž¸çž{^T£³þWcÂßVô»Tüó?â0x  ‰Æ€ÍõbH¯ý§Š)ˆ.ÉgbHÀ_Ø=VþCñ¿`ÁµråÊq¢,\æ/n \1|oSªü¡ðo===;¿ÿýï?¼sçÎpy¿°êŸ$ü}ˆ h p¯eœ·yŒ´ç¤®‘³gÏö.Y²¤Ð“!ojH+µˆÿ°¢mû¡')ÿ .wŸp™?“¤  WÄÈ’Ž”p Êf ¿çž{î¹-=ôЯUú¬£ €2’þÿ€P‚`rŸºÞ½E7nšMú‹ië_·nš5kÖ¸ûHÅßÇ*¼Æ$ĈSªYmþÑ—¥¿ ïÜyç›uf<áßFø›Š|ÑøÀGqžwyÖŽ®M—@=çò`gþäÉ“… PyèNÕ××7Nü‡3ÿÒ= añ`¿p™?„«Ÿmbz\¿½˜Vò¹õ±ŠEQô ‡Ÿxâ‰ÍÛ¶mû0"ü‡s¸m ¿IÈŸ–ÿF‰ èH3!ËÈ[g»®×?^¶púôéÀˆ °={ö—ÝtÓMAå?:Û/N’ÿåà0ˆ!€é‘´M™í—Ϫš\í¥ý~ûÛßn½ûÕFÄ5ò7¢®Ïúç ÿ"@-ÿÿ€#ú}<¦0òÞ{ï+ú`"¦¤¢*ûøåѤÿ¸øO û¤# úX´ïó‹~6¥Ò_dÉJßoÃîÝ»}ß}÷=©ÛþO^þYíþ¶­ÿ¶•~Ä?´€!4ûŸ8nçüèÑ£´0:§÷¬"OJVT´KZooï¸kcÒöîܹ@øÇÃþD JËZÒ?††€éc†-þýú;±û±Ç{\/ï·W.í7¤òÛïMŽm*ü¾…?â0šl ˜îLè ýÉ¢€ˆ­0¬ON‹ø—–ë¨(ñáµqãÆ aaÒ¿‹džC \޲b•þ1´éuâå—_þÙµtÿPø%m[ÀÆ ð=ë_OúˆÀ((ê³.7 L\ pppð„žÅ_[Ôôc),8AÈ8p ¸Í§?ýé a²€\æK`R­ïŒmV´½zuþ7ß|sÛý÷ßÿ’>-³0òD‡-…¸Kåßg»ÿH‚¸Gü`@ „¬ÓÁκE7$"Lýu¢ùѦƒƒ‘€[n¹eB{¿Œ Ä Ä2¯1 ù…íýUòËø>\x÷Ýwuï½÷þ·þ^œWésþ¶@‘ná?¢²ÛüóÚýÿ€`¸³[³¸ír€ñó#ýýý…—1&ËüÅééé „¢,óˆÑ¤ÿv®îŸ+ü¡ðo£jèçxyÇŽ/?øàƒÏèÏ~¿]Ö/«â_dîßEø×3žG^û¿Bü`@µÌ“ ÀèmGtRÿÑ2žŒ,ÿ'þeË–M¸NªþÒú߉âC û>¡à—C4G¢Êèçyù£>úÍÃ?üs½ÊEV²–à²ìŸË±ëÌ¿Bü`€?ñn3×orÿzÎŽu°ó¯—$;üÅ/~Ñë‹‘°?ÿóæÍ› Eüç%ýw²!ÐI¦G(øE臢¿•Šÿ®]»^“Šww·´À\Éþ.-ÿ>Ë^âñ¢Ýd‡8É$ÈzœzÎñÈ[o½Õ£[­‡uÿ$//J‹:ií—Tÿ(’ô/â_Ž[]¸v‚8/iéV÷[¥ÂGú{ÿý÷_Öÿ_é¥4¥Õ? ÷6×yíøeE—øËû‚ø @è+»j~Öý]+k§]B¯è¥{õ2~K}¼Xñö~¹lÚ´iÞ…%†@u· üpŽ¿UÅ~ý]9µ}ûv™ñ1îþyB»ìê¿mÂxRvÕÄ?4ÁPˆŸ¶ÍZ•µ°9êËH”ÚdNKû¿J9–n90Zï5Êu¡ÐoõÊ~§N:ðÚk¯=·yóæwdÞ_%/ç—gý÷Õæï3èñ¼Ð` é¼R9gÏž=ºpá†<ñPFç½C 4Ĉš­*–ÛÉ€íˆÈ~Tø·#2£—°ÜñÜsÏýê™gžÙ¥®Ï÷Û¶ùûªþþ.Ay¢¿n(öÿ€à(ô]#íXúÂÙ³~ýúæ½H-&C™Dh„Æ€kçíû¹¢wÜ!ùíVÑÏBÏ÷ŸýàƒÞxì±Ç^Ø·oßiu=ÑßDøÿ>Ûümgýó*þõŒÿ)ˆÀ(Yô'…¦d™#ÇŽ;\å7$4Ò„h܈ŸO3 :ň,¡¸~–ùÒ)ß¹ãÇòöÛo¿¶eË–·õ*#¢ÄBLûÿ6Uÿ,Ñ?¢Ò«ü6Iÿˆ ¨°q`ÒÊ;òûßÿþàßüÍß´ì 7¯¡ØC“ ¼,É(ð1†àÓE{ô¾Q1}/¢—Ç·£è\Šþ;w¾ùôÓO¿ª{Õøj¿mÝEü1Êj÷/:ïø Ÿ&èm—T9;õ#ï¾ûî Ô~nÊ”)³ÚöÍMζÄM„Ð3.àã糄xÒuI‚Š¡?ç—:ôþo~ó›ßþô§?Ý¡Ï_V«ýyÉø6ÂßUü—!úm+þˆ (Qôçí0ç‰ý´}¥ÒÛE< ë•Íž=û3üIÌMh ´Ù3tôèÑwìØ±ýÉ'Ÿ|[g^œSÉ-þ#*»MÞ¶ÝÞG€k«¿KË?â(ô]/¯ À¤â7Ü×××íô;yòä]»v½«[üßÜ¿Ÿº¾|ŸI ŸRvKè𹜟ÉkQÊß¼?â0J6’L•°³¯2vòÇ:tUôàÚµky·¡¥9sæÌ‘?üðí­[·þV‹ÿ“1ÑïRéw(Òà³Íßµåñ€-`Ô Ì€DsðàÁ}_øÂxG¡¥Ð«\Õ•~]àß¿ëå—_ÞþÖ[oIý¦•ñ"¡6¢ÞEð»üùhù75ÿ€PPØ›ÜÖt9À¤þ!жçoÿöo}*xçÊ•+ƒ:ÈïCÜÿþ¶mÛ~¯—ð‹Ïô+·Yx_¿¨ø÷]ñ7ýÌû`@…Òù´Ûe-˜$ ‚´½{÷ž9pàÀÖ… ~~ÆŒKùS@•èïïïÙ·oߺÂÿ»çŸ~¯TþÕø*4½?-Å_)3ÿ.+؈}[ ë{®”yË?âÀspÙO¨%œŽÇOG] ÇñÓáaRÆé)ú0]¦ýÑýÑ¢¿ø‹¿ø_«V­ºuñâÅŸ™5kÖ2ös ‘èU)N÷ôôìÖÆÔîW_}õÃkóü"ö‡Trrž.sæßÕ ðQé/º´ŸMË?â<ì+äiâ?ÏÈ:Ä €ð0ùÚaJx¼qãÆyÚ¸uÍš5-Z´nΜ9ë¦L™rNð,ø?ÁÿÚk¯íÒA~'Ôõ |¹>ÑÛˆ¶ý"€RÅæüÿЂ€‹ Ö 7¢¦@`Lš4iòŸüÉŸ¬ÐW®\¹^ ¬ÕK®Ð—OáO &œ;wîdooï¾Ý»wüæ›oîÚ±c‡Tø³æøGÄk#«þEýˆr7lÌ SÀô´­¨Gü?êŽ@šøW)Âßt Ið§™&ÝÁñôéÓ§Þzë­‹n¹å–•ºS`Í’%KVkS`‰Î˜Ç>RgséÒ¥³z™ÉÃÇŽëÖiýµàÿD¨üà>“5ëMEQ#`¤„ëÚ¥êø~Ô €¸ðWÊ< ­ –#þ³.7=LJ0&-[¶lÖÿñ‹)°\›Ëu·Àʹsç.×ÝSù8´W¯^½¨ûŽëê~·nçßóë_ÿz÷Ç|ZoãÏZžOÛfVþ}WöËø3­ô#þ0 û Íp1’: L·˜:?`òm·Ý¶pÆ K´A°hÁ‚‹u·À¢›nºi¾î˜ÛÕÕ5‰Jký¾¾¾cZìíîî>¢çö{ôÒ|Q±Îï'µñ›V­‹VþËÿ+Cø+UnÀ_^Ë¿©¨Gø?ê¼฿55 ÐåÙ09d ÿ$SB©ô.…IÑÓz”`òg?ûÙ…ŸúÔ§ks`ñ¼yóêÐÁ…7ß|óÂo¼qN­Vëâ#Ô0êÒ¾¯9¥…þñ'NÕKEö|ðÁGtU¿/"î³Bú\ÛÔ]M€FUÿË ósyýižª?´˜eä‰_&@-ÃÈ2j†Ï]ÅkÂvµ0Esuðà<=N0_3OwÌÕËΙ9sæ\}ýlV'°C üs:¿O‡òÖ"ÿÔ™3gNëYý“‡:©ƒùNœ?þJLÜǯ2û6‚?ï2Û–ÿ2 2™3þˆ ¨¨þJÙ˜„º˜6Õÿ,‘ŸõÚ”q>}nºS`êÚµkgëî9º{àfmÌÑÁMú0[Ü4mÚ´õaFxÜŽûoõz}äòåËç/^¼xîÂ… ú õý¹]ÉÐÇguË~ÿÉ“'t»þÉK1Ak²ÜžMå9í6e¶ý—!ø}Ïñûžñ/"üÿЄýÛ¥Ò+ðY]6¿Ö` í}°¹oÚèAü¹t-_¾|ÆâÅ‹gép™zÔ`æ mÜ(Çzašî(Ð>Á´ôaºœrg}<]ç?uêÔ ó@Ÿl»âÈÈÈÐðððUîz¶^¹ºråÊ%9?44tE_?,— ZØ_ЇKZÜ_Ї‹ºBA ûA}¸¨Åü NÛ¿ Ûôôã…óöiËÒůËã&"ÓÆð-üóD³Lå úmÿTý0 ÷|Œ˜ŒÔ,¿Mð_# •s¾fñ~*e6¦e@˜>7a•&ØŠˆá<Áž'] —ª¿oáo+ø}.Âßæ}**üÿ˜Ì[ž¨§ˆÈº¸´XÑŠ°º&æ“.Éëu@Y&f@^³¼ée¶@ÝñzSÑ^/p_¡oz™ëò~6F@Ù]J•/üM €¬¿±Ïª?âš ú]vÎk†"k$"ú£Â¿+fäµÜ§™J•×P†x7yÿk ü<¹]Q ‘-ÿ¦bßFø›ˆvSÀÅ`0y]yïKÞ{n*ü}|¦d D ‚<³ žbDüt\øçUþãâ¾®Šwø6Ê0eY‹½Ä¿Röíÿʳ€¯;nS)¿mþuÇ¿£‹ Gü`@ ‚Þõvq# K¤¦ µ$#ÀVø›´þ»Œ¸ÌñÛš.—7Ò@üþ®f€* þ} ÓÓ¶ŸÄ?TØ0íH3ÒF¢â?Ɉ›¶þgêùÊÈúðeøií,þm¸ïËMžË\áosÂZØÈúy"o$Cè+e>ïŸ×úï»ÀFø72Ô¯Ÿ…f &€Oño"ü}^f*þ]…¿‰ `rñ€-$ìMDZ€©@ …~žÕ}ë¿I€‹!`"ümDU‚Ë^%À§à·ý6†@Q# ¨¸/bV ü0¼™QC O”¦ ˆ¨ÿi§£&D—ÊoûwIÿ/+ÀÖ pû¾Vr("ú}[ Y9EM"‚ß·ðÏ3ÿÐfÂÞä>iݦąžàOö>’ÿ›è2àb ¸~>l¯·5š=ÿo+þ}˜Íüõï?Â:Ì0YöÏÖˆš*CüÛ´ügµý»Îÿ·b@Úýê?®F€oÀÖ pÿ>M×ÓE¿4Âñ€ú6÷I:V–F@TôÇ/«e¶©ÿšÿo‡,_³ÿeÿ""¸è(€oqï#³Àæýò%ümÅ<ÂZÐH ÿËp1âÂ_ˆSáßìù3 OÔךð(jTÕ(£+ ˆÐoT•¿QÂñ€-n˜ÞÞdi@SÀ5ð¯ˆè/*þ›5Pó,ÊZy ¨ PÖe¦·±}\…>íþ€ÈO¼mÖ(@R7@Ýâñ]fý« þ}Ž˜ ÿšçÏ‚/# Q«5\Í€¢×¹›ˆ}„?@‡Pã-€’ö%L*Üysö&¢ÝµÒßnâ¿VàoÕ(3 Ñ«Ø ã²M²Ä¾éue Ä?@ @4“¬PÀ¢i—™þ¹ši×ÿ­0ÿ_D(–5àKü—-â)ö]–ïCø´t@™û¦Ø$qߤror}Þã› ýªÿÕ<üÝ|Š8á˜'}UZükï“Ëþ\2lÅhÌß"Þå9æ]Wô2„??ÒM7\żë\E~™‚ßwտȾ ÏxWñêÛ(Ã4pݶËù¬÷áPIÀD|û¾Ì‡ø/Û(Ã(_+øÌ>M_"ßå5ç½ÇÀ€¦ïcØš®b¾UÅ~­„÷·UÄ¿O1ìºDž¯¥õšQÕ/Kô#ü0¼‹T—yû¢íúÍšã/k‰¿V0|‰ÛzÏûôýÀ€Jìkíða´‹ð¯Ú>^³L_b¼¬ ~+ˆ~„?@ÃLß"݇ /Kà·CÅ¿,# ¨`n¤aàCð¹áÐV&€/ñîSð·’è÷¹XVˆ\Yf@3/s¹ÑÐÖûEŒ€F {ߢ¾Ö€÷¯ÑÔ=ÞÖE8—aøüUý~ˆ*k”eØÞ¶ À÷mÊØô%}ˆ[qݬË} ~„?`F@ ——u]Y"¿Êûv¾Åm½×UeVÑÐû!µ ]׈ë}ì³5k_¯^òýê%^_¥–ýzþ&€д}‘Zů÷y›2öÛÊØÿkteºìñŸè €’€fˆõZ“_o£³ aY/éöõÞ¦ìׂè€BLâ-€6lï×l!_á_e¡Y¦x®JžÞBà‡ ’û'e òFŠ÷ZßÛVµõŠÝ¾LqŽè `?¥…{­bï[Õ…j#x½¯ÑÀþJ ‰ôZßv3êM|~À¨ð~K­MŸS;RoÓÇAô@ö_j-ô\[y®ÕÄs½MÞ `_¦ÉÛ`¬"¹ÞF¯€`¿¦Mö£Úi®S„7‚0Út‡ý¬æQç9ðÃìïðÜø~à€} ž7±üø°Obø±`_ ûü¨°}~¸ØÇD>?Nì‡â€öÛõÀ øß7D xàÿ¦'¶¸»OÌoIEND®B`‚qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/en.lproj/000077500000000000000000000000001347155106100253145ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/en.lproj/Credits.rtf000066400000000000000000000007031347155106100274260ustar00rootroot00000000000000{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} {\colortbl;\red255\green255\blue255;} \paperw9840\paperh8400 \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\b\fs24 \cf0 Engineering: \b0 \ Some people\ \ \b Human Interface Design: \b0 \ Some other people\ \ \b Testing: \b0 \ Hopefully not nobody\ \ \b Documentation: \b0 \ Whoever\ \ \b With special thanks to: \b0 \ Mom\ } qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/en.lproj/InfoPlist.strings000066400000000000000000000000541347155106100306350ustar00rootroot00000000000000/* Localized versions of Info.plist keys */ qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/en.lproj/LICENSE000066400000000000000000000027531347155106100263300ustar00rootroot00000000000000Copyright (C) 2017 The Qt Company Ltd. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/en.lproj/MainMenu.xib000066400000000000000000011340171347155106100275400ustar00rootroot00000000000000 1080 11D50 2457 1138.32 568.00 com.apple.InterfaceBuilder.CocoaPlugin 2457 NSWindowTemplate NSView NSMenu NSMenuItem NSCustomObject com.apple.InterfaceBuilder.CocoaPlugin PluginDependencyRecalculationVersion NSApplication FirstResponder NSApplication AMainMenu CocoaApplication 1048576 2147483647 NSImage NSMenuCheckmark NSImage NSMenuMixedState submenuAction: CocoaApplication About CocoaApplication 2147483647 YES YES 1048576 2147483647 Preferences… , 1048576 2147483647 YES YES 1048576 2147483647 Services 1048576 2147483647 submenuAction: Services _NSServicesMenu YES YES 1048576 2147483647 Hide CocoaApplication h 1048576 2147483647 Hide Others h 1572864 2147483647 Show All 1048576 2147483647 YES YES 1048576 2147483647 Quit CocoaApplication q 1048576 2147483647 _NSAppleMenu File 1048576 2147483647 submenuAction: File New n 1048576 2147483647 Open… o 1048576 2147483647 Open Recent 1048576 2147483647 submenuAction: Open Recent Clear Menu 1048576 2147483647 _NSRecentDocumentsMenu YES YES 1048576 2147483647 Close w 1048576 2147483647 Save… s 1048576 2147483647 Revert to Saved 2147483647 YES YES 1048576 2147483647 Page Setup... P 1179648 2147483647 Print… p 1048576 2147483647 Edit 1048576 2147483647 submenuAction: Edit Undo z 1048576 2147483647 Redo Z 1179648 2147483647 YES YES 1048576 2147483647 Cut x 1048576 2147483647 Copy c 1048576 2147483647 Paste v 1048576 2147483647 Paste and Match Style V 1572864 2147483647 Delete 1048576 2147483647 Select All a 1048576 2147483647 YES YES 1048576 2147483647 Find 1048576 2147483647 submenuAction: Find Find… f 1048576 2147483647 1 Find and Replace… f 1572864 2147483647 12 Find Next g 1048576 2147483647 2 Find Previous G 1179648 2147483647 3 Use Selection for Find e 1048576 2147483647 7 Jump to Selection j 1048576 2147483647 Spelling and Grammar 1048576 2147483647 submenuAction: Spelling and Grammar Show Spelling and Grammar : 1048576 2147483647 Check Document Now ; 1048576 2147483647 YES YES 2147483647 Check Spelling While Typing 1048576 2147483647 Check Grammar With Spelling 1048576 2147483647 Correct Spelling Automatically 2147483647 Substitutions 1048576 2147483647 submenuAction: Substitutions Show Substitutions 2147483647 YES YES 2147483647 Smart Copy/Paste f 1048576 2147483647 1 Smart Quotes g 1048576 2147483647 2 Smart Dashes 2147483647 Smart Links G 1179648 2147483647 3 Text Replacement 2147483647 Transformations 2147483647 submenuAction: Transformations Make Upper Case 2147483647 Make Lower Case 2147483647 Capitalize 2147483647 Speech 1048576 2147483647 submenuAction: Speech Start Speaking 1048576 2147483647 Stop Speaking 1048576 2147483647 Format 2147483647 submenuAction: Format Font 2147483647 submenuAction: Font Show Fonts t 1048576 2147483647 Bold b 1048576 2147483647 2 Italic i 1048576 2147483647 1 Underline u 1048576 2147483647 YES YES 2147483647 Bigger + 1048576 2147483647 3 Smaller - 1048576 2147483647 4 YES YES 2147483647 Kern 2147483647 submenuAction: Kern Use Default 2147483647 Use None 2147483647 Tighten 2147483647 Loosen 2147483647 Ligatures 2147483647 submenuAction: Ligatures Use Default 2147483647 Use None 2147483647 Use All 2147483647 Baseline 2147483647 submenuAction: Baseline Use Default 2147483647 Superscript 2147483647 Subscript 2147483647 Raise 2147483647 Lower 2147483647 YES YES 2147483647 Show Colors C 1048576 2147483647 YES YES 2147483647 Copy Style c 1572864 2147483647 Paste Style v 1572864 2147483647 _NSFontMenu Text 2147483647 submenuAction: Text Align Left { 1048576 2147483647 Center | 1048576 2147483647 Justify 2147483647 Align Right } 1048576 2147483647 YES YES 2147483647 Writing Direction 2147483647 submenuAction: Writing Direction YES Paragraph 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 YES Selection 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 Show Ruler 2147483647 Copy Ruler c 1310720 2147483647 Paste Ruler v 1310720 2147483647 View 1048576 2147483647 submenuAction: View Show Toolbar t 1572864 2147483647 Customize Toolbar… 1048576 2147483647 Window 1048576 2147483647 submenuAction: Window Minimize m 1048576 2147483647 Zoom 1048576 2147483647 YES YES 1048576 2147483647 Bring All to Front 1048576 2147483647 _NSWindowsMenu Help 2147483647 submenuAction: Help CocoaApplication Help ? 1048576 2147483647 _NSHelpMenu _NSMainMenu 15 2 {{335, 390}, {480, 360}} 1954021376 CocoaApplication NSWindow 256 {480, 360} {{0, 0}, {2560, 1418}} {10000000000000, 10000000000000} YES AppDelegate NSFontManager terminate: 449 orderFrontStandardAboutPanel: 142 delegate 495 performMiniaturize: 37 arrangeInFront: 39 print: 86 runPageLayout: 87 clearRecentDocuments: 127 performClose: 193 toggleContinuousSpellChecking: 222 undo: 223 copy: 224 checkSpelling: 225 paste: 226 stopSpeaking: 227 cut: 228 showGuessPanel: 230 redo: 231 selectAll: 232 startSpeaking: 233 delete: 235 performZoom: 240 performFindPanelAction: 241 centerSelectionInVisibleArea: 245 toggleGrammarChecking: 347 toggleSmartInsertDelete: 355 toggleAutomaticQuoteSubstitution: 356 toggleAutomaticLinkDetection: 357 saveDocument: 362 revertDocumentToSaved: 364 runToolbarCustomizationPalette: 365 toggleToolbarShown: 366 hide: 367 hideOtherApplications: 368 unhideAllApplications: 370 newDocument: 373 openDocument: 374 raiseBaseline: 426 lowerBaseline: 427 copyFont: 428 subscript: 429 superscript: 430 tightenKerning: 431 underline: 432 orderFrontColorPanel: 433 useAllLigatures: 434 loosenKerning: 435 pasteFont: 436 unscript: 437 useStandardKerning: 438 useStandardLigatures: 439 turnOffLigatures: 440 turnOffKerning: 441 toggleAutomaticSpellingCorrection: 456 orderFrontSubstitutionsPanel: 458 toggleAutomaticDashSubstitution: 461 toggleAutomaticTextReplacement: 463 uppercaseWord: 464 capitalizeWord: 467 lowercaseWord: 468 pasteAsPlainText: 486 performFindPanelAction: 487 performFindPanelAction: 488 performFindPanelAction: 489 showHelp: 493 alignCenter: 518 pasteRuler: 519 toggleRuler: 520 alignRight: 521 copyRuler: 522 alignJustified: 523 alignLeft: 524 makeBaseWritingDirectionNatural: 525 makeBaseWritingDirectionLeftToRight: 526 makeBaseWritingDirectionRightToLeft: 527 makeTextWritingDirectionNatural: 528 makeTextWritingDirectionLeftToRight: 529 makeTextWritingDirectionRightToLeft: 530 performFindPanelAction: 535 addFontTrait: 421 addFontTrait: 422 modifyFont: 423 orderFrontFontPanel: 424 modifyFont: 425 window 532 0 -2 File's Owner -1 First Responder -3 Application 29 19 56 217 83 81 75 78 72 82 124 77 73 79 112 74 125 126 205 202 198 207 214 199 203 197 206 215 218 216 200 219 201 204 220 213 210 221 208 209 57 58 134 150 136 144 129 143 236 131 149 145 130 24 92 5 239 23 295 296 297 298 211 212 195 196 346 348 349 350 351 354 371 372 375 376 377 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 450 451 452 453 454 457 459 460 462 465 466 485 490 491 492 494 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 534 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin {{380, 496}, {480, 360}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin 535 ABCardController NSObject id id id id id id id addCardViewField: id copy: id cut: id doDelete: id find: id paste: id saveChanges: id ABCardView NSButton NSManagedObjectContext NSSearchField NSTextField NSWindow mCardView ABCardView mEditButton NSButton mManagedObjectContext NSManagedObjectContext mSearchField NSSearchField mStatusTextField NSTextField mWindow NSWindow IBProjectSource ./Classes/ABCardController.h ABCardView NSView id id commitAndSave: id statusImageClicked: id NSObjectController NSImageView NSView ABNameFrameView NSView NSImage ABImageView mBindingsController NSObjectController mBuddyStatusImage NSImageView mHeaderView NSView mNameView ABNameFrameView mNextKeyView NSView mUserImage NSImage mUserImageView ABImageView IBProjectSource ./Classes/ABCardView.h ABImageView NSImageView id id id id copy: id cut: id delete: id paste: id IBProjectSource ./Classes/ABImageView.h DVTBorderedView DVTLayoutView_ML contentView NSView contentView contentView NSView IBProjectSource ./Classes/DVTBorderedView.h DVTDelayedMenuButton NSButton IBProjectSource ./Classes/DVTDelayedMenuButton.h DVTGradientImageButton NSButton IBProjectSource ./Classes/DVTGradientImageButton.h DVTImageAndTextCell NSTextFieldCell IBProjectSource ./Classes/DVTImageAndTextCell.h DVTImageAndTextColumn NSTableColumn IBProjectSource ./Classes/DVTImageAndTextColumn.h DVTLayoutView_ML NSView IBProjectSource ./Classes/DVTLayoutView_ML.h DVTOutlineView NSOutlineView IBProjectSource ./Classes/DVTOutlineView.h DVTSplitView NSSplitView IBProjectSource ./Classes/DVTSplitView.h DVTStackView_ML DVTLayoutView_ML IBProjectSource ./Classes/DVTStackView_ML.h DVTTableView NSTableView IBProjectSource ./Classes/DVTTableView.h DVTViewController NSViewController IBProjectSource ./Classes/DVTViewController.h HFController NSObject selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFController.h HFRepresenterTextView NSView selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFRepresenterTextView.h IBEditor NSObject id id id id id changeFont: id performCopy: id performCut: id selectAll: id sizeSelectionToFit: id IBProjectSource ./Classes/IBEditor.h IDECapsuleListView DVTStackView_ML dataSource id dataSource dataSource id IBProjectSource ./Classes/IDECapsuleListView.h IDEDMArrayController NSArrayController IBProjectSource ./Classes/IDEDMArrayController.h IDEDMEditor IDEEditor DVTBorderedView NSView IDEDMEditorSourceListController DVTSplitView bottomToolbarBorderView DVTBorderedView sourceListSplitViewPane NSView sourceListViewController IDEDMEditorSourceListController splitView DVTSplitView IBProjectSource ./Classes/IDEDMEditor.h IDEDMEditorController IDEViewController IBProjectSource ./Classes/IDEDMEditorController.h IDEDMEditorSourceListController IDEDMEditorController DVTBorderedView IDEDMEditor DVTImageAndTextColumn DVTOutlineView NSTreeController borderedView DVTBorderedView parentEditor IDEDMEditor primaryColumn DVTImageAndTextColumn sourceListOutlineView DVTOutlineView sourceListTreeController NSTreeController IBProjectSource ./Classes/IDEDMEditorSourceListController.h IDEDMHighlightImageAndTextCell DVTImageAndTextCell IBProjectSource ./Classes/IDEDMHighlightImageAndTextCell.h IDEDataModelBrowserEditor IDEDMEditorController IDEDataModelPropertiesTableController IDECapsuleListView NSArrayController IDEDataModelPropertiesTableController IDEDataModelEntityContentsEditor IDEDataModelPropertiesTableController attributesTableViewController IDEDataModelPropertiesTableController capsuleView IDECapsuleListView entityArrayController NSArrayController fetchedPropertiesTableViewController IDEDataModelPropertiesTableController parentEditor IDEDataModelEntityContentsEditor relationshipsTableViewController IDEDataModelPropertiesTableController IBProjectSource ./Classes/IDEDataModelBrowserEditor.h IDEDataModelConfigurationEditor IDEDMEditorController IDECapsuleListView IDEDataModelEditor IDEDataModelConfigurationTableController capsuleListView IDECapsuleListView parentEditor IDEDataModelEditor tableController IDEDataModelConfigurationTableController IBProjectSource ./Classes/IDEDataModelConfigurationEditor.h IDEDataModelConfigurationTableController IDEDMEditorController NSArrayController NSArrayController IDEDataModelConfigurationEditor XDTableView configurationsArrayController NSArrayController entitiesArrayController NSArrayController parentEditor IDEDataModelConfigurationEditor tableView XDTableView IBProjectSource ./Classes/IDEDataModelConfigurationTableController.h IDEDataModelDiagramEditor IDEDMEditorController XDDiagramView IDEDataModelEntityContentsEditor diagramView XDDiagramView parentEditor IDEDataModelEntityContentsEditor IBProjectSource ./Classes/IDEDataModelDiagramEditor.h IDEDataModelEditor IDEDMEditor DVTDelayedMenuButton DVTDelayedMenuButton NSSegmentedControl IDEDataModelConfigurationEditor IDEDataModelEntityContentsEditor IDEDataModelFetchRequestEditor NSSegmentedControl NSTabView addEntityButton DVTDelayedMenuButton addPropertyButton DVTDelayedMenuButton browserDiagramSegmentControl NSSegmentedControl configurationViewController IDEDataModelConfigurationEditor entityContentsViewController IDEDataModelEntityContentsEditor fetchRequestViewController IDEDataModelFetchRequestEditor hierarchySegmentControl NSSegmentedControl tabView NSTabView IBProjectSource ./Classes/IDEDataModelEditor.h IDEDataModelEntityContentsEditor IDEDMEditorController IDEDataModelBrowserEditor IDEDataModelDiagramEditor IDEDataModelEditor NSTabView browserViewController IDEDataModelBrowserEditor diagramViewController IDEDataModelDiagramEditor parentEditor IDEDataModelEditor tabView NSTabView IBProjectSource ./Classes/IDEDataModelEntityContentsEditor.h IDEDataModelFetchRequestEditor IDEDMEditorController NSArrayController IDEDataModelEditor IDECapsuleListView entityController NSArrayController parentEditor IDEDataModelEditor tableView IDECapsuleListView IBProjectSource ./Classes/IDEDataModelFetchRequestEditor.h IDEDataModelPropertiesTableController IDEDMEditorController IDEDMArrayController NSTableColumn NSArrayController IDEDataModelBrowserEditor IDEDMHighlightImageAndTextCell XDTableView arrayController IDEDMArrayController entitiesColumn NSTableColumn entityArrayController NSArrayController parentEditor IDEDataModelBrowserEditor propertyNameAndImageCell IDEDMHighlightImageAndTextCell tableView XDTableView IBProjectSource ./Classes/IDEDataModelPropertiesTableController.h IDEDocDownloadsTableViewController NSObject NSButtonCell DVTTableView IDEDocViewingPrefPaneController _downloadButtonCell NSButtonCell _tableView DVTTableView prefPaneController IDEDocViewingPrefPaneController IBProjectSource ./Classes/IDEDocDownloadsTableViewController.h IDEDocSetOutlineView NSOutlineView IBProjectSource ./Classes/IDEDocSetOutlineView.h IDEDocSetOutlineViewController NSObject id id id id id getDocSetAction: id showProblemInfoForUpdate: id subscribeToPublisherAction: id unsubscribeFromPublisher: id updateDocSetAction: id docSetOutlineView IDEDocSetOutlineView docSetOutlineView docSetOutlineView IDEDocSetOutlineView IBProjectSource ./Classes/IDEDocSetOutlineViewController.h IDEDocViewingPrefPaneController IDEViewController id id id id id id id id id id id addSubscription: id checkForAndInstallUpdatesNow: id deleteDocSet: id downloadAction: id minimumFontSizeComboBoxAction: id minimumFontSizeEnabledAction: id showHelp: id showSubscriptionSheet: id subscriptionCancelAction: id toggleAutoCheckForAndInstallUpdates: id toggleDocSetInfo: id DVTGradientImageButton DVTGradientImageButton DVTGradientImageButton NSSplitView NSView NSView DVTBorderedView DVTBorderedView NSButton NSTextView IDEDocSetOutlineViewController IDEDocDownloadsTableViewController NSComboBox NSTextField NSButton NSTextField NSWindow NSButton _addButton DVTGradientImageButton _deleteButton DVTGradientImageButton _showInfoAreaButton DVTGradientImageButton _splitView NSSplitView _splitViewDocSetInfoSubview NSView _splitViewDocSetsListSubview NSView borderedViewAroundSplitView DVTBorderedView borderedViewBelowTable DVTBorderedView checkAndInstallNowButton NSButton docSetInfoTextView NSTextView docSetOutlineViewController IDEDocSetOutlineViewController downloadsTableViewController IDEDocDownloadsTableViewController minimumFontSizeControl NSComboBox noUpdatesAvailableMessage NSTextField showInfoButton NSButton subscriptionTextField NSTextField subscriptionWindow NSWindow validateAddSubscriptionButton NSButton IBProjectSource ./Classes/IDEDocViewingPrefPaneController.h IDEEditor IDEViewController IBProjectSource ./Classes/IDEEditor.h IDEViewController DVTViewController IBProjectSource ./Classes/IDEViewController.h IKImageView id id id id copy: id crop: id cut: id paste: id IBProjectSource ./Classes/IKImageView.h NSDocument id id id id id id printDocument: id revertDocumentToSaved: id runPageLayout: id saveDocument: id saveDocumentAs: id saveDocumentTo: id IBProjectSource ./Classes/NSDocument.h NSResponder _insertFindPattern: id _insertFindPattern: _insertFindPattern: id IBProjectSource ./Classes/NSResponder.h QLPreviewBubble NSObject id id hide: id show: id parentWindow NSWindow parentWindow parentWindow NSWindow IBProjectSource ./Classes/QLPreviewBubble.h QTMovieView id id id id id showAll: id showCustomButton: id toggleLoops: id zoomIn: id zoomOut: id IBProjectSource ./Classes/QTMovieView.h WebView id id id id reloadFromOrigin: id resetPageZoom: id zoomPageIn: id zoomPageOut: id IBProjectSource ./Classes/WebView.h XDDiagramView NSView id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id _graphLayouterMenuItemAction: id _zoomPopUpButtonAction: id alignBottomEdges: id alignCentersHorizontallyInContainer: id alignCentersVerticallyInContainer: id alignHorizontalCenters: id alignLeftEdges: id alignRightEdges: id alignTopEdges: id alignVerticalCenters: id bringToFront: id collapseAllCompartments: id copy: id cut: id delete: id deleteBackward: id deleteForward: id deselectAll: id diagramZoomIn: id diagramZoomOut: id expandAllCompartments: id flipHorizontally: id flipVertically: id layoutGraphicsConcentrically: id layoutGraphicsHierarchically: id lock: id makeSameHeight: id makeSameWidth: id moveDown: id moveDownAndModifySelection: id moveLeft: id moveLeftAndModifySelection: id moveRight: id moveRightAndModifySelection: id moveUp: id moveUpAndModifySelection: id paste: id rollDownAllCompartments: id rollUpAllCompartments: id selectAll: id sendToBack: id sizeToFit: id toggleGridShown: id toggleHiddenGraphicsShown: id togglePageBreaksShown: id toggleRuler: id toggleSnapsToGrid: id unlock: id _diagramController IDEDataModelDiagramEditor _diagramController _diagramController IDEDataModelDiagramEditor IBProjectSource ./Classes/XDDiagramView.h XDTableView NSTableView showAllTableColumns: id showAllTableColumns: showAllTableColumns: id IBProjectSource ./Classes/XDTableView.h AppDelegate NSObject id id applicationShouldTerminate: id applicationWillFinishLaunching: id IBProjectSource ./Classes/AppDelegate.h 0 IBCocoaFramework YES 3 {11, 11} {10, 3} YES qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/en_US.lproj000077700000000000000000000000001347155106100273132en.lprojustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-application/CocoaApplication/main.m000066400000000000000000000031431347155106100246700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import int main(int argc, char *argv[]) { return NSApplicationMain(argc, (const char **)argv); } qbs-src-1.13.1/examples/cocoa-application/app.qbs000066400000000000000000000070651347155106100216540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs CppApplication { Depends { condition: product.condition; name: "ib" } condition: qbs.hostOS.contains("macos") name: "Cocoa Application" cpp.useObjcPrecompiledHeader: true cpp.minimumMacosVersion: "10.8" cpp.frameworks: ["Cocoa"] Group { prefix: "CocoaApplication/" files: [ "AppDelegate.h", "AppDelegate.m", "CocoaApplication-Info.plist", "CocoaApplication.xcassets", "main.m" ] } Group { name: "Supporting Files" prefix: "CocoaApplication/en.lproj/" files: [ "Credits.rtf", "InfoPlist.strings", "MainMenu.xib" ] } Group { name: "Xcode Project" files: [ "CocoaApplication.xcodeproj/project.pbxproj" ] } Group { files: ["CocoaApplication/CocoaApplication-Prefix.pch"] fileTags: ["objc_pch_src"] } Group { fileTagsFilter: ["bundle.content"] qbs.install: true qbs.installDir: "Applications" qbs.installSourceBase: product.destinationDirectory } ib.appIconName: "AppIcon" } qbs-src-1.13.1/examples/cocoa-application/dmg.qbs000066400000000000000000000065351347155106100216440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs AppleApplicationDiskImage { condition: qbs.targetOS.contains("macos") name: "Cocoa Application DMG" targetName: "cocoa-application-" + version version: "1.0" Depends { name: "Cocoa Application" } Depends { name: "ib" } files: [ "CocoaApplication/dmg.iconset", "CocoaApplication/en_US.lproj/LICENSE", ] // set to false to use a solid-color background (see dmg.backgroundColor below) property bool useImageBackground: true Group { condition: useImageBackground files: ["CocoaApplication/background*"] } dmg.backgroundColor: "#41cd52" dmg.badgeVolumeIcon: true dmg.iconPositions: [ {"x": 200, "y": 200, "path": "Cocoa Application.app"}, {"x": 400, "y": 200, "path": "Applications"} ] dmg.windowX: 420 dmg.windowY: 250 dmg.windowWidth: 600 dmg.windowHeight: 422 // this *includes* the macOS title bar height of 22 dmg.iconSize: 64 } qbs-src-1.13.1/examples/cocoa-touch-application/000077500000000000000000000000001347155106100214755ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication.qbs000066400000000000000000000074701347155106100264270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs 1.0 CppApplication { Depends { condition: product.condition; name: "ib" } condition: qbs.hostOS.contains("macos") name: "Cocoa Touch Application" qbs.targetPlatform: "ios" cpp.useObjcPrecompiledHeader: true cpp.minimumIosVersion: "8.0" cpp.frameworks: [ "UIKit", "Foundation", "CoreGraphics" ] Group { prefix: "CocoaTouchApplication/" files: [ "AppDelegate.h", "AppDelegate.m", "CocoaTouchApplication-Info.plist", "Default-568h@2x.png", "Default.png", "Default@2x.png", "DetailViewController.h", "DetailViewController.m", "MasterViewController.h", "MasterViewController.m", "main.m" ] } Group { name: "Supporting Files" prefix: "CocoaTouchApplication/en.lproj/" files: [ "DetailViewController_iPad.xib", "DetailViewController_iPhone.xib", "InfoPlist.strings", "MasterViewController_iPad.xib", "MasterViewController_iPhone.xib" ] } Group { name: "Xcode Project" files: [ "CocoaTouchApplication.xcodeproj/project.pbxproj" ] } Group { files: ["CocoaTouchApplication/CocoaTouchApplication-Prefix.pch"] fileTags: ["objc_pch_src"] } } qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication.xcodeproj/000077500000000000000000000000001347155106100277045ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication.xcodeproj/project.pbxproj000066400000000000000000000460041347155106100327640ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 14E3FEAA175FB2E800C857C6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14E3FEA9175FB2E800C857C6 /* UIKit.framework */; }; 14E3FEAC175FB2E800C857C6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14E3FEAB175FB2E800C857C6 /* Foundation.framework */; }; 14E3FEAE175FB2E800C857C6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14E3FEAD175FB2E800C857C6 /* CoreGraphics.framework */; }; 14E3FEB4175FB2E800C857C6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEB2175FB2E800C857C6 /* InfoPlist.strings */; }; 14E3FEB6175FB2E800C857C6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEB5175FB2E800C857C6 /* main.m */; }; 14E3FEBA175FB2E800C857C6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEB9175FB2E800C857C6 /* AppDelegate.m */; }; 14E3FEBC175FB2E800C857C6 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEBB175FB2E800C857C6 /* Default.png */; }; 14E3FEBE175FB2E800C857C6 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEBD175FB2E800C857C6 /* Default@2x.png */; }; 14E3FEC0175FB2E800C857C6 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEBF175FB2E800C857C6 /* Default-568h@2x.png */; }; 14E3FEC3175FB2E800C857C6 /* MasterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEC2175FB2E800C857C6 /* MasterViewController.m */; }; 14E3FEC6175FB2E900C857C6 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEC5175FB2E900C857C6 /* DetailViewController.m */; }; 14E3FEC9175FB2E900C857C6 /* MasterViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEC7175FB2E900C857C6 /* MasterViewController_iPhone.xib */; }; 14E3FECC175FB2E900C857C6 /* MasterViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FECA175FB2E900C857C6 /* MasterViewController_iPad.xib */; }; 14E3FECF175FB2E900C857C6 /* DetailViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FECD175FB2E900C857C6 /* DetailViewController_iPhone.xib */; }; 14E3FED2175FB2E900C857C6 /* DetailViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FED0175FB2E900C857C6 /* DetailViewController_iPad.xib */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 14E3FEA6175FB2E800C857C6 /* Cocoa Touch Application.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Cocoa Touch Application.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 14E3FEA9175FB2E800C857C6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 14E3FEAB175FB2E800C857C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 14E3FEAD175FB2E800C857C6 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 14E3FEB1175FB2E800C857C6 /* CocoaTouchApplication-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CocoaTouchApplication-Info.plist"; sourceTree = ""; }; 14E3FEB3175FB2E800C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 14E3FEB5175FB2E800C857C6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 14E3FEB7175FB2E800C857C6 /* CocoaTouchApplication-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CocoaTouchApplication-Prefix.pch"; sourceTree = ""; }; 14E3FEB8175FB2E800C857C6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 14E3FEB9175FB2E800C857C6 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 14E3FEBB175FB2E800C857C6 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 14E3FEBD175FB2E800C857C6 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 14E3FEBF175FB2E800C857C6 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 14E3FEC1175FB2E800C857C6 /* MasterViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MasterViewController.h; sourceTree = ""; }; 14E3FEC2175FB2E800C857C6 /* MasterViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MasterViewController.m; sourceTree = ""; }; 14E3FEC4175FB2E800C857C6 /* DetailViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; 14E3FEC5175FB2E900C857C6 /* DetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; 14E3FEC8175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MasterViewController_iPhone.xib; sourceTree = ""; }; 14E3FECB175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MasterViewController_iPad.xib; sourceTree = ""; }; 14E3FECE175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/DetailViewController_iPhone.xib; sourceTree = ""; }; 14E3FED1175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/DetailViewController_iPad.xib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 14E3FEA3175FB2E800C857C6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 14E3FEAA175FB2E800C857C6 /* UIKit.framework in Frameworks */, 14E3FEAC175FB2E800C857C6 /* Foundation.framework in Frameworks */, 14E3FEAE175FB2E800C857C6 /* CoreGraphics.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 14E3FE9D175FB2E800C857C6 = { isa = PBXGroup; children = ( 14E3FEAF175FB2E800C857C6 /* CocoaTouchApplication */, 14E3FEA8175FB2E800C857C6 /* Frameworks */, 14E3FEA7175FB2E800C857C6 /* Products */, ); sourceTree = ""; }; 14E3FEA7175FB2E800C857C6 /* Products */ = { isa = PBXGroup; children = ( 14E3FEA6175FB2E800C857C6 /* Cocoa Touch Application.app */, ); name = Products; sourceTree = ""; }; 14E3FEA8175FB2E800C857C6 /* Frameworks */ = { isa = PBXGroup; children = ( 14E3FEA9175FB2E800C857C6 /* UIKit.framework */, 14E3FEAB175FB2E800C857C6 /* Foundation.framework */, 14E3FEAD175FB2E800C857C6 /* CoreGraphics.framework */, ); name = Frameworks; sourceTree = ""; }; 14E3FEAF175FB2E800C857C6 /* CocoaTouchApplication */ = { isa = PBXGroup; children = ( 14E3FEB8175FB2E800C857C6 /* AppDelegate.h */, 14E3FEB9175FB2E800C857C6 /* AppDelegate.m */, 14E3FEC1175FB2E800C857C6 /* MasterViewController.h */, 14E3FEC2175FB2E800C857C6 /* MasterViewController.m */, 14E3FEC4175FB2E800C857C6 /* DetailViewController.h */, 14E3FEC5175FB2E900C857C6 /* DetailViewController.m */, 14E3FEC7175FB2E900C857C6 /* MasterViewController_iPhone.xib */, 14E3FECA175FB2E900C857C6 /* MasterViewController_iPad.xib */, 14E3FECD175FB2E900C857C6 /* DetailViewController_iPhone.xib */, 14E3FED0175FB2E900C857C6 /* DetailViewController_iPad.xib */, 14E3FEB0175FB2E800C857C6 /* Supporting Files */, ); path = CocoaTouchApplication; sourceTree = ""; }; 14E3FEB0175FB2E800C857C6 /* Supporting Files */ = { isa = PBXGroup; children = ( 14E3FEB1175FB2E800C857C6 /* CocoaTouchApplication-Info.plist */, 14E3FEB2175FB2E800C857C6 /* InfoPlist.strings */, 14E3FEB5175FB2E800C857C6 /* main.m */, 14E3FEB7175FB2E800C857C6 /* CocoaTouchApplication-Prefix.pch */, 14E3FEBB175FB2E800C857C6 /* Default.png */, 14E3FEBD175FB2E800C857C6 /* Default@2x.png */, 14E3FEBF175FB2E800C857C6 /* Default-568h@2x.png */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 14E3FEA5175FB2E800C857C6 /* Cocoa Touch Application */ = { isa = PBXNativeTarget; buildConfigurationList = 14E3FED5175FB2E900C857C6 /* Build configuration list for PBXNativeTarget "Cocoa Touch Application" */; buildPhases = ( 14E3FEA2175FB2E800C857C6 /* Sources */, 14E3FEA3175FB2E800C857C6 /* Frameworks */, 14E3FEA4175FB2E800C857C6 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "Cocoa Touch Application"; productName = CocoaTouchApplication; productReference = 14E3FEA6175FB2E800C857C6 /* Cocoa Touch Application.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 14E3FE9E175FB2E800C857C6 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0460; ORGANIZATIONNAME = "Petroules Corporation"; }; buildConfigurationList = 14E3FEA1175FB2E800C857C6 /* Build configuration list for PBXProject "CocoaTouchApplication" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 14E3FE9D175FB2E800C857C6; productRefGroup = 14E3FEA7175FB2E800C857C6 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 14E3FEA5175FB2E800C857C6 /* Cocoa Touch Application */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 14E3FEA4175FB2E800C857C6 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 14E3FEB4175FB2E800C857C6 /* InfoPlist.strings in Resources */, 14E3FEBC175FB2E800C857C6 /* Default.png in Resources */, 14E3FEBE175FB2E800C857C6 /* Default@2x.png in Resources */, 14E3FEC0175FB2E800C857C6 /* Default-568h@2x.png in Resources */, 14E3FEC9175FB2E900C857C6 /* MasterViewController_iPhone.xib in Resources */, 14E3FECC175FB2E900C857C6 /* MasterViewController_iPad.xib in Resources */, 14E3FECF175FB2E900C857C6 /* DetailViewController_iPhone.xib in Resources */, 14E3FED2175FB2E900C857C6 /* DetailViewController_iPad.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 14E3FEA2175FB2E800C857C6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 14E3FEB6175FB2E800C857C6 /* main.m in Sources */, 14E3FEBA175FB2E800C857C6 /* AppDelegate.m in Sources */, 14E3FEC3175FB2E800C857C6 /* MasterViewController.m in Sources */, 14E3FEC6175FB2E900C857C6 /* DetailViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 14E3FEB2175FB2E800C857C6 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 14E3FEB3175FB2E800C857C6 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; 14E3FEC7175FB2E900C857C6 /* MasterViewController_iPhone.xib */ = { isa = PBXVariantGroup; children = ( 14E3FEC8175FB2E900C857C6 /* en */, ); name = MasterViewController_iPhone.xib; sourceTree = ""; }; 14E3FECA175FB2E900C857C6 /* MasterViewController_iPad.xib */ = { isa = PBXVariantGroup; children = ( 14E3FECB175FB2E900C857C6 /* en */, ); name = MasterViewController_iPad.xib; sourceTree = ""; }; 14E3FECD175FB2E900C857C6 /* DetailViewController_iPhone.xib */ = { isa = PBXVariantGroup; children = ( 14E3FECE175FB2E900C857C6 /* en */, ); name = DetailViewController_iPhone.xib; sourceTree = ""; }; 14E3FED0175FB2E900C857C6 /* DetailViewController_iPad.xib */ = { isa = PBXVariantGroup; children = ( 14E3FED1175FB2E900C857C6 /* en */, ); name = DetailViewController_iPad.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 14E3FED3175FB2E900C857C6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 14E3FED4175FB2E900C857C6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 14E3FED6175FB2E900C857C6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaTouchApplication/CocoaTouchApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaTouchApplication/CocoaTouchApplication-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Debug; }; 14E3FED7175FB2E900C857C6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaTouchApplication/CocoaTouchApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaTouchApplication/CocoaTouchApplication-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 14E3FEA1175FB2E800C857C6 /* Build configuration list for PBXProject "CocoaTouchApplication" */ = { isa = XCConfigurationList; buildConfigurations = ( 14E3FED3175FB2E900C857C6 /* Debug */, 14E3FED4175FB2E900C857C6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 14E3FED5175FB2E900C857C6 /* Build configuration list for PBXNativeTarget "Cocoa Touch Application" */ = { isa = XCConfigurationList; buildConfigurations = ( 14E3FED6175FB2E900C857C6 /* Debug */, 14E3FED7175FB2E900C857C6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 14E3FE9E175FB2E800C857C6 /* Project object */; } qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/000077500000000000000000000000001347155106100257105ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/AppDelegate.h000066400000000000000000000055351347155106100302440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import @interface AppDelegate : UIResponder { UIWindow *_window; UINavigationController *_navigationController; UISplitViewController *_splitViewController; } @property (nonatomic, retain) UIWindow *window; @property (nonatomic, retain) UINavigationController *navigationController; @property (nonatomic, retain) UISplitViewController *splitViewController; @end qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/AppDelegate.m000066400000000000000000000125211347155106100302420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "AppDelegate.h" #import "MasterViewController.h" #import "DetailViewController.h" @implementation AppDelegate @synthesize window = _window; @synthesize navigationController = _navigationController; @synthesize splitViewController = _splitViewController; - (void)dealloc { [_window release]; [_navigationController release]; [_splitViewController release]; [super dealloc]; } - (BOOL)application:(UIApplication *) __unused application didFinishLaunchingWithOptions:(NSDictionary *) __unused launchOptions { self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; // Override point for customization after application launch. if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:@"MasterViewController_iPhone" bundle:nil] autorelease]; self.navigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease]; self.window.rootViewController = self.navigationController; } else { MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:@"MasterViewController_iPad" bundle:nil] autorelease]; UINavigationController *masterNavigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease]; DetailViewController *detailViewController = [[[DetailViewController alloc] initWithNibName:@"DetailViewController_iPad" bundle:nil] autorelease]; UINavigationController *detailNavigationController = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease]; masterViewController.detailViewController = detailViewController; self.splitViewController = [[[UISplitViewController alloc] init] autorelease]; self.splitViewController.delegate = detailViewController; self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController, detailNavigationController, nil]; self.window.rootViewController = self.splitViewController; } [self.window makeKeyAndVisible]; return YES; } - (void)applicationWillResignActive:(UIApplication *) __unused application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *) __unused application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *) __unused application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *) __unused application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *) __unused application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end CocoaTouchApplication-Info.plist000066400000000000000000000035051347155106100340150ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication CFBundleDevelopmentRegion en CFBundleDisplayName ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier org.example.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1.0 LSRequiresIPhoneOS UIRequiredDeviceCapabilities armv7 UIStatusBarTintParameters UINavigationBar Style UIBarStyleDefault Translucent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight CocoaTouchApplication-Prefix.pch000066400000000000000000000033131347155106100337730ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import #ifndef __IPHONE_4_0 #warning "This project uses features only available in iOS SDK 4.0 and later." #endif #ifdef __OBJC__ #import #import #endif qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/Default-568h@2x.png000066400000000000000000000442421347155106100310520ustar00rootroot00000000000000‰PNG  IHDR€pzå$iCCPICC Profile8…UßoÛT>‰oR¤? XG‡ŠÅ¯US[¹­ÆI“¥íJ¥éØ*$ä:7‰©Û鶪O{7ü@ÙH§kk?ì<Ê»øÎí¾kktüqóÝ‹mÇ6°nÆ¶ÂøØ¯±-ümR;`zŠ–¡Êðv x#=\Ó% ëoàYÐÚRÚ±£¥êùÐ#&Á?È>ÌÒ¹áЪþ¢þ©n¨_¨Ôß;j„;¦$}*}+ý(}'}/ýLŠtYº"ý$]•¾‘.9»ï½Ÿ%Ø{¯_aÝŠ]hÕkŸ5'SNÊ{äå”ü¼ü²<°¹_“§ä½ðì öÍ ý½t ³jMµ{-ñ4%ׯTÅ„«tYÛŸ“¦R6ÈÆØô#§v\œå–Šx:žŠ'H‰ï‹OÄÇâ3·ž¼ø^ø&°¦õþ“0::àm,L%È3â:qVEô t›ÐÍ]~ߢI«vÖ6ÊWÙ¯ª¯) |ʸ2]ÕG‡Í4Ïå(6w¸½Â‹£$¾ƒ"ŽèAÞû¾EvÝ mî[D‡ÿÂ;ëVh[¨}íõ¿Ú†ðN|æ3¢‹õº½âç£Hä‘S:°ßûéKâÝt·Ñx€÷UÏ'D;7ÿ®7;_"ÿÑeó?Yqxl+ pHYs  šœáiTXtXML:com.adobe.xmp 1 5 72 1 72 640 1 1136 2012-07-27T15:07:06 Pixelmator 2.0.5 )ñq™?7IDATxíÛ=ªže†ÑøQñ§±qÎÙ87;;'à RÄBR(Jˆ‰…ŸW¼áw­ž³‰Ý^»¹8‰w<øö¼Îûæ¼Ïûò¼7Îó @€üÿ^Ÿ~:ï÷ó¾;ïùÃóãýóÞ;ï­ó>9Oü @àF®¶»ïó®æ{}w~|ÞÛç}}Þ£ó®ÿæ#@€¸û³ÊËó~<ïÕõÀÏÏûè<ñw| @€¸~ÁwµÞWç=»ðŠ¿ÏÎ󛿃à#@€ܨÀÕzWóý}×? —† pû÷Wø]'ì#@€ˆø?~#‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`p& @ " #‡¶& @`WÞï& @€ÀÍ Ü_øô¼¿n~U  @€\Í÷ô Àgçýzžß @àF®Ö»šïÙÃóãçÿþðá™Î»;ÏG€ p;Wü½<ïñy¯Þ=ïÝóÞ9ÏG€ p;ÏÏ*OÎûá¼Ç×_¿8ïÏóþ>ï·ó^Ÿç#@€¸ «í®Æ»Zïj¾ÿLZ9:\‰oR¤? XG‡ŠÅ¯US[¹­ÆI“¥íJ¥éØ*$ä:7‰©Û鶪O{7ü@ÙH§kk?ì<Ê»øÎí¾kktüqóÝ‹mÇ6°nÆ¶ÂøØ¯±-ümR;`zŠ–¡Êðv x#=\Ó% ëoàYÐÚRÚ±£¥êùÐ#&Á?È>ÌÒ¹áЪþ¢þ©n¨_¨Ôß;j„;¦$}*}+ý(}'}/ýLŠtYº"ý$]•¾‘.9»ï½Ÿ%Ø{¯_aÝŠ]hÕkŸ5'SNÊ{äå”ü¼ü²<°¹_“§ä½ðì öÍ ý½t ³jMµ{-ñ4%ׯTÅ„«tYÛŸ“¦R6ÈÆØô#§v\œå–Šx:žŠ'H‰ï‹OÄÇâ3·ž¼ø^ø&°¦õþ“0::àm,L%È3â:qVEô t›ÐÍ]~ߢI«vÖ6ÊWÙ¯ª¯) |ʸ2]ÕG‡Í4Ïå(6w¸½Â‹£$¾ƒ"ŽèAÞû¾EvÝ mî[D‡ÿÂ;ëVh[¨}íõ¿Ú†ðN|æ3¢‹õº½âç£Hä‘S:°ßûéKâÝt·Ñx€÷UÏ'D;7ÿ®7;_"ÿÑeó?Yqxl+ pHYs  šœàiTXtXML:com.adobe.xmp 1 5 72 1 72 320 1 480 2012-07-27T15:07:80 Pixelmator 2.0.5 X±=Æ"IDATxíÖÑICQDÑDK°Áæ»Iq¦½ï/L {nðäoÖÀàýv»ýœ÷}Þ×y>(‰oR¤? XG‡ŠÅ¯US[¹­ÆI“¥íJ¥éØ*$ä:7‰©Û鶪O{7ü@ÙH§kk?ì<Ê»øÎí¾kktüqóÝ‹mÇ6°nÆ¶ÂøØ¯±-ümR;`zŠ–¡Êðv x#=\Ó% ëoàYÐÚRÚ±£¥êùÐ#&Á?È>ÌÒ¹áЪþ¢þ©n¨_¨Ôß;j„;¦$}*}+ý(}'}/ýLŠtYº"ý$]•¾‘.9»ï½Ÿ%Ø{¯_aÝŠ]hÕkŸ5'SNÊ{äå”ü¼ü²<°¹_“§ä½ðì öÍ ý½t ³jMµ{-ñ4%ׯTÅ„«tYÛŸ“¦R6ÈÆØô#§v\œå–Šx:žŠ'H‰ï‹OÄÇâ3·ž¼ø^ø&°¦õþ“0::àm,L%È3â:qVEô t›ÐÍ]~ߢI«vÖ6ÊWÙ¯ª¯) |ʸ2]ÕG‡Í4Ïå(6w¸½Â‹£$¾ƒ"ŽèAÞû¾EvÝ mî[D‡ÿÂ;ëVh[¨}íõ¿Ú†ðN|æ3¢‹õº½âç£Hä‘S:°ßûéKâÝt·Ñx€÷UÏ'D;7ÿ®7;_"ÿÑeó?Yqxl+ pHYs  šœàiTXtXML:com.adobe.xmp 1 5 72 1 72 640 1 960 2012-07-27T15:07:37 Pixelmator 2.0.5 PFð5IDATxíÛ1ŠÝe‡á HHíìÜŽ;qoV.ÂÒÎ.V‚b˜&ƒ“øýa^p Þßsá›3¦;Ïi^îàýÝÝÝÏç½;ï§óÞŸ÷Ãy¯Îó!@€øÿ <Ÿ>œ÷ñ¼_Î{x}~\ñ÷ö¼¯_æWgú @€܆ÀÕvWë=¾Ì»ûóËoç]ñ÷ãyoλþ͇ @àv¾œU>÷ÇyO×7€×Ÿ}¯*Á‡ pƒ×|Wë}Þãõÿœw}5蛿ƒàC€¸aë›ÀÏWô]¿ø @€Œø>FmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@0 “ 0" GmM @€@W>Ÿ÷¥0  @€nVàj¾ç×çLJóÞž÷íy÷çù @€ÜžÀŸ÷xàÇë—óÞ÷æ<x| @€7$pÅß§óþ:ïéÕùñÝyž÷þ¼ëOÂßœ'‚ @àúæïú«ï¯çý~ßÃy×7€O/óó™> @€·!pµÝ[ïá_ŠÏ4ìýïlÄIEND®B`‚qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/DetailViewController.h000066400000000000000000000054231347155106100321660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import @interface DetailViewController : UIViewController { id _detailItem; UILabel *_detailDescriptionLabel; UIPopoverController *_masterPopoverController; } @property (nonatomic, retain) id detailItem; @property (nonatomic, retain) IBOutlet UILabel *detailDescriptionLabel; @end qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/DetailViewController.m000066400000000000000000000077701347155106100322020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "DetailViewController.h" @interface DetailViewController () @property (nonatomic, retain) UIPopoverController *masterPopoverController; - (void)configureView; @end @implementation DetailViewController @synthesize detailItem = _detailItem; @synthesize detailDescriptionLabel = _detailDescriptionLabel; @synthesize masterPopoverController = _masterPopoverController; - (void)dealloc { [_detailItem release]; [_detailDescriptionLabel release]; [_masterPopoverController release]; [super dealloc]; } #pragma mark - Managing the detail item - (void)setDetailItem:(id)newDetailItem { if (_detailItem != newDetailItem) { [_detailItem release]; _detailItem = [newDetailItem retain]; // Update the view. [self configureView]; } if (self.masterPopoverController != nil) { [self.masterPopoverController dismissPopoverAnimated:YES]; } } - (void)configureView { // Update the user interface for the detail item. if (self.detailItem) { self.detailDescriptionLabel.text = [self.detailItem description]; } } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self configureView]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = NSLocalizedString(@"Detail", @"Detail"); } return self; } #pragma mark - Split view - (void)splitViewController:(UISplitViewController *) __unused splitController willHideViewController:(UIViewController *) __unused viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController { barButtonItem.title = NSLocalizedString(@"Master", @"Master"); [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES]; self.masterPopoverController = popoverController; } - (void)splitViewController:(UISplitViewController *) __unused splitController willShowViewController:(UIViewController *) __unused viewController invalidatingBarButtonItem:(UIBarButtonItem *) __unused barButtonItem { // Called when the view is shown again in the split view, invalidating the button and popover controller. [self.navigationItem setLeftBarButtonItem:nil animated:YES]; self.masterPopoverController = nil; } @end qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/MasterViewController.h000066400000000000000000000053141347155106100322160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import @class DetailViewController; @interface MasterViewController : UITableViewController { NSMutableArray *_objects; DetailViewController *_detailViewController; } @property (nonatomic, retain) DetailViewController *detailViewController; @end qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/MasterViewController.m000066400000000000000000000137701347155106100322300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "MasterViewController.h" #import "DetailViewController.h" @implementation MasterViewController @synthesize detailViewController = _detailViewController; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = NSLocalizedString(@"Master", @"Master"); if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { self.clearsSelectionOnViewWillAppear = NO; self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0); } } return self; } - (void)dealloc { [_detailViewController release]; [_objects release]; [super dealloc]; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.navigationItem.leftBarButtonItem = self.editButtonItem; UIBarButtonItem *addButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)] autorelease]; self.navigationItem.rightBarButtonItem = addButton; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)insertNewObject:(id) __unused sender { if (!_objects) { _objects = [[NSMutableArray alloc] init]; } [_objects insertObject:[NSDate date] atIndex:0]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; } #pragma mark - Table View - (NSInteger)numberOfSectionsInTableView:(UITableView *) __unused tableView { return 1; } - (NSInteger)tableView:(UITableView *) __unused tableView numberOfRowsInSection:(NSInteger) __unused section { return _objects.count; } // Customize the appearance of table view cells. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } } NSDate *object = [_objects objectAtIndex:indexPath.row]; cell.textLabel.text = [object description]; return cell; } - (BOOL)tableView:(UITableView *) __unused tableView canEditRowAtIndexPath:(NSIndexPath *) __unused indexPath { // Return NO if you do not want the specified item to be editable. return YES; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { [_objects removeObjectAtIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view. } } /* // Override to support rearranging the table view. - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { } */ /* // Override to support conditional rearranging of the table view. - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the item to be re-orderable. return YES; } */ - (void)tableView:(UITableView *) __unused tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSDate *object = [_objects objectAtIndex:indexPath.row]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { if (!self.detailViewController) { self.detailViewController = [[[DetailViewController alloc] initWithNibName:@"DetailViewController_iPhone" bundle:nil] autorelease]; } self.detailViewController.detailItem = object; [self.navigationController pushViewController:self.detailViewController animated:YES]; } else { self.detailViewController.detailItem = object; } } @end qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/000077500000000000000000000000001347155106100274375ustar00rootroot00000000000000DetailViewController_iPad.xib000066400000000000000000000317011347155106100351240ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj 1536 12A206j 2519 1172.1 613.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1856 IBNSLayoutConstraint IBProxyObject IBUILabel IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBIPadFramework IBFirstResponder IBIPadFramework 274 298 {{20, 495}, {728, 18}} 3 MQA YES NO IBIPadFramework 1 10 Detail view content goes here 1 MCAwIDAAA 1 1 4 Helvetica 14 16 {{0, 20}, {768, 1004}} NO 2 IBIPadFramework view 12 0 -1 File's Owner -2 8 10 0 10 1 0.0 1000 5 22 2 6 0 6 1 20 1000 8 29 3 5 0 5 1 20 1000 8 29 3 81 94 97 98 DetailViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 98 0 IBIPadFramework YES 3 YES 1856 DetailViewController_iPhone.xib000066400000000000000000000351701347155106100354750ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj 1536 12A269 2835 1187 624.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1919 IBNSLayoutConstraint IBProxyObject IBUILabel IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 274 298 {{20, 265}, {280, 18}} 3 MQA YES NO IBCocoaTouchFramework Detail view content goes here 1 MCAwIDAAA darkTextColor 1 10 1 1 4 Helvetica 14 16 {{0, 20}, {320, 548}} 3 MQA 2 IBUIScreenMetrics YES {320, 568} {568, 320} IBCocoaTouchFramework Retina 4 Full Screen 2 IBCocoaTouchFramework view 3 detailDescriptionLabel 6 0 1 10 0 10 1 0.0 1000 5 22 2 6 0 6 1 20 1000 8 29 3 5 0 5 1 20 1000 8 29 3 -1 File's Owner -2 4 7 9 11 DetailViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 0 IBCocoaTouchFramework YES 3 YES 1919 qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/InfoPlist.strings000066400000000000000000000000541347155106100327600ustar00rootroot00000000000000/* Localized versions of Info.plist keys */ MasterViewController_iPad.xib000066400000000000000000000206341347155106100351600ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj 1536 12A206j 2519 1172.1 613.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1856 IBProxyObject IBUITableView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBIPadFramework IBFirstResponder IBIPadFramework 274 {{0, 20}, {320, 832}} 3 MQA YES 2 IBUISplitViewMasterSimulatedSizeMetrics YES {320, 852} {320, 768} IBIPadFramework Master IBUISplitViewController IBUISplitViewControllerContentSizeLocation IBUISplitViewControllerContentSizeLocationMaster IBIPadFramework YES 1 0 YES 44 22 22 view 3 dataSource 4 delegate 5 0 -1 File's Owner -2 2 MasterViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 5 0 IBIPadFramework YES 3 YES 1856 MasterViewController_iPhone.xib000066400000000000000000000200351347155106100355200ustar00rootroot00000000000000qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj 1536 12A269 2835 1187 624.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1919 IBProxyObject IBUITableView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 274 {{0, 20}, {320, 548}} 3 MQA YES IBUIScreenMetrics YES {320, 568} {568, 320} IBCocoaTouchFramework Retina 4 Full Screen 2 IBCocoaTouchFramework YES 1 0 YES 44 22 22 view 3 dataSource 4 delegate 5 0 -1 File's Owner -2 2 MasterViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 5 0 IBCocoaTouchFramework YES 3 YES 1919 qbs-src-1.13.1/examples/cocoa-touch-application/CocoaTouchApplication/main.m000066400000000000000000000034061347155106100270150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import #import "AppDelegate.h" int main(int argc, char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); [pool release]; return retVal; } qbs-src-1.13.1/examples/code-generator/000077500000000000000000000000001347155106100176665ustar00rootroot00000000000000qbs-src-1.13.1/examples/code-generator/code-generator.qbs000066400000000000000000000062301347155106100232740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs Project { // A code generator that outputs a "Hello World" C++ program. CppApplication { name: "hwgen" consoleApplication: true files: ["hwgen.cpp"] } // Generate and build a hello-world application. CppApplication { name: "hello-world" Depends { name: "hwgen" } Rule { inputsFromDependencies: ["application"] Artifact { filePath: "main.cpp" fileTags: ["cpp"] } prepare: { var hwgen = inputs["application"][0].filePath; var cmd = new Command(hwgen, [output.filePath]); cmd.description = "generating C++ source"; return cmd; } } } } qbs-src-1.13.1/examples/code-generator/hwgen.cpp000066400000000000000000000053251347155106100215070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main(int argc, char **argv) { if (argc < 2) return 1; FILE *f = fopen(argv[1], "w"); if (!f) return 2; fprintf(f, "#include \n\n" "int main()\n" "{\n printf(\"Hello World!\\n\");\n return 0;\n}\n"); fclose(f); return 0; } qbs-src-1.13.1/examples/collidingmice/000077500000000000000000000000001347155106100175725ustar00rootroot00000000000000qbs-src-1.13.1/examples/collidingmice/collidingmice.qbs000066400000000000000000000056411347155106100231110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs 1.0 Application { name : "CollidingMice" Depends { name: "Qt.widgets" } property bool isBundle: qbs.targetOS.contains("darwin") && bundle.isBundle files : [ "images/cheese.jpg", "main.cpp", "mouse.cpp", "mouse.h", "mice.qrc" ] Group { fileTagsFilter: isBundle ? ["bundle.content"] : ["application"] qbs.install: true qbs.installPrefix: isBundle ? "Applications" : "bin" qbs.installSourceBase: product.buildDirectory } } qbs-src-1.13.1/examples/collidingmice/images/000077500000000000000000000000001347155106100210375ustar00rootroot00000000000000qbs-src-1.13.1/examples/collidingmice/images/cheese.jpg000066400000000000000000000057251347155106100230060ustar00rootroot00000000000000ÿØÿàJFIFHHÿîAdobed@ÿÛ„      ÿÀ^^ÿÝ ÿÄ¢  s!1AQa"q2‘¡±B#ÁRÑá3bð$r‚ñ%C4S’¢²csÂ5D'“£³6TdtÃÒâ&ƒ „”EF¤´VÓU(òãóÄÔäôeu…•¥µÅÕåõfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø)9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúm!1AQa"q‘2¡±ðÁÑá#BRbrñ3$4C‚’S%¢c²ÂsÒ5âDƒT“ &6E'dtU7ò£³Ã()Óã󄔤´ÄÔäôeu…•¥µÅÕåõFVfv†–¦¶ÆÖæöGWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúÿÚ ?ûAÓo¢‡Ç<7‰éÔéâk)n£rM ðÈ‚¥²AZ†úFù"7P¦cåâvù`ä•ÁHØt=F V¤š1`¤ìkã’ ¬I’Q­È‘·ê„4¯ÅŽûwÉlIb:¯ž<¿£Ìmîï+84ha£þU6~§§ïNŸ~eøžž/'‡zÿÑû?JíÔöÏ §¨Qy?Ö=°ˆq-Òš„j{d¼&aÆpJ‘Jt"˜øtŽ0UÔ‡nÛŒ ;@ÞÚ ˆšbJƒÄѨ|ù +|µ=ໞYâäÈbBÿ!%OßÇ,ˆÅÖý̼IŽTôk+[-:Ö+ e¶´€)þQ«îNç!–|g•À§šÝNÊ=NÂæÍ¶€PžÌ7ÊÄD½'«!#a…i¾\’ݽ;‹vJÕÆÿÛ˜Ù#,G„¹-€©Ï ·¨J/çŽÚ9îfqP!yôEI9|HËY²h>Ró'æšõKébÐIÓlQˆÒž«Ýœƒ×Àe>)ŸZr#†1çºqå_>y¢Öîõ‹‡¾µ”"L`R¬v÷ȆíÄ%ÈSé›I–EŠhÛœR…daЩfA ‹ØZ¨=5µ„ 1€{|ˆ34›jzïNMïí<™†¸5 ‘ZW·Ë5µŒ¬ k-©­ð9$.ãN„ø}H%A]ÈÔøø×#JÿÿÔûCÉ)Øðzz…zt ôÉÄð›Ô‹K­´}Ní ¿U”±fŽZ”ÿ`À~'›<ûÆ\'¸Ý|ý+Ò†ÄZ'è«`¾¤«xÊ(!ŒÛ“56ÄiñBbRÉ]"þò@jñrO¯4*³Ü¹øª±<@Ø|€ðrä–Be.e”ˆ ª@?>”Ê:3s1 Ü.ʵýXlõE!Üo°&§¬ z×åŠUÐöë¡} 4ðÚ¸ÄyªrRO]öOL<;Õ£‰ÿÕû8ÀÖ£®x]½B“G^„×¹Ä*€·]Ù¶5ÛÄâ(VH _‰ºøòDŒx‚6ªc¢€6##Í’Ÿ¨T|@úâ`–ê\ñ=ÎB’ºª*¤×ß TJT{cJ»wQ·l•*àkþKxd$ÛÔoô`WÿÖû=Q×–xSÔ/$q$liÓÙRnK‹}Q»³¡º†mÁb4ö­r2‘$&1âºf‡æhîª5;É®9 $2HÅ¢„Ҟ؀@«t¢9=âÔ¹†'‘x4ˆ®ÉàXTŒÈɵ*Ƈ®ô4Êì³RcÇzn{âÔL½‡\°´&жþq¯õ–”¯Ñ€Á"j«)$PŽ»ä¦V¦%#š’y)‘¥ÿ×û;ÐPÇ<*Þ¡PPûõÄ«¤U(A^JÀ†SЂ(AƃanöÑGéÃaF¯Ùgäƒè¥Oß™~.!¿þý¿$LõTS#3™$¶ÔÙ‹“'¾¬€¦…jFÕ4`½ÇÏä”5Á"ƒ¹é’Ç»0/8ùÂÇÊvB{ Ó\KQmj†!jeEz岘€óc—Ïòþsù¦æê–‘Ckk_†10»1©ÊŒæz·Œ1Ròoæ<úÄñXêð¤rÌBÅs*9”“JøŒÌA©5Ï«dа'¥wtã³Tdô–µíN™ŽÜÿÿÐû4ÊÛýÆxCÔ¶ŒAZ‘Ö§$‚¨O&@¯°Û¯øTo@r*´ÍU AÔø{âW§A×®ˆC¼m+- Fãl³c7Ë¿™¶7:šeˆ‚ÖÖ¡bDë@?‰9‹’w77 ÆK,ŠF›uðË,Ä0 [!‡Ë2YÜE…Ò}[.Òi½1!ñ#¾lqJñ‚]|ÅJ“~'Óú2¾­ÿÑû9-üNxCÔ0/2k^e°Ôôû- F‹QŠxÚ{¹¦vP[øþÖÕ©öÆy죌˫?µvx‘ =t=A"´>ã$Fì¹A¹p¶ pU vß׆Q€ì—râ4à ‡™yÃËku¨&«lÞµåw*àSìrYôüQãÇËöì«ÒQZF†„§«â‚”¨Úž,Àã2<7»q¡»'m®\E|˜ìÔO†CI£žLüÞÏö°É©ˆ”ÏÒŠâ´‚ºˆÃÿ7ÄŸ¦™¸ÍÁÃCo–ßo7w=U9ÓM©˜öÝOÿÒûy“§9/Ññîøôa>Ý^ÚêÜeÓL+È$ÔB|wäGß•œÚ~+ž;;ÝHú~‰G-}[{•'ŸP–)¾©d–Öá}麻ñïSÊ´ñ É㙜%áDF5½o*ëw¿¾€ b ÄI>idâÅá”§!ðÔeiÿÙqbs-src-1.13.1/examples/collidingmice/main.cpp000066400000000000000000000073671347155106100212370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mouse.h" #include #include #include #include #include #include static const int MouseCount = 7; //! [0] int main(int argc, char **argv) { QApplication app(argc, argv); qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); //! [0] //! [1] QGraphicsScene scene; scene.setSceneRect(-300, -300, 600, 600); //! [1] //! [2] scene.setItemIndexMethod(QGraphicsScene::NoIndex); //! [2] //! [3] for (int i = 0; i < MouseCount; ++i) { const auto mouse = new Mouse; mouse->setPos(::sin((i * 6.28) / MouseCount) * 200, ::cos((i * 6.28) / MouseCount) * 200); scene.addItem(mouse); } //! [3] //! [4] QGraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); view.setBackgroundBrush(QPixmap(":/images/cheese.jpg")); //! [4] //! [5] view.setCacheMode(QGraphicsView::CacheBackground); view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); view.setDragMode(QGraphicsView::ScrollHandDrag); //! [5] //! [6] view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice")); view.resize(400, 300); view.show(); QTimer timer; QObject::connect(&timer, &QTimer::timeout, &scene, &QGraphicsScene::advance); timer.start(1000 / 33); return app.exec(); } //! [6] qbs-src-1.13.1/examples/collidingmice/mice.qrc000066400000000000000000000001411347155106100212120ustar00rootroot00000000000000 images/cheese.jpg qbs-src-1.13.1/examples/collidingmice/mouse.cpp000066400000000000000000000151441347155106100214330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mouse.h" #include #include #include #include static const double Pi = 3.14159265358979323846264338327950288419717; static double TwoPi = 2.0 * Pi; static qreal normalizeAngle(qreal angle) { while (angle < 0) angle += TwoPi; while (angle > TwoPi) angle -= TwoPi; return angle; } //! [0] Mouse::Mouse() : angle(0), speed(0), mouseEyeDirection(0), color(qrand() % 256, qrand() % 256, qrand() % 256) { setRotation(qrand() % (360 * 16)); } //! [0] //! [1] QRectF Mouse::boundingRect() const { qreal adjust = 0.5; return QRectF(-18 - adjust, -22 - adjust, 36 + adjust, 60 + adjust); } //! [1] //! [2] QPainterPath Mouse::shape() const { QPainterPath path; path.addRect(-10, -20, 20, 40); return path; } //! [2] //! [3] void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { // Body painter->setBrush(color); painter->drawEllipse(-10, -20, 20, 40); // Eyes painter->setBrush(Qt::white); painter->drawEllipse(-10, -17, 8, 8); painter->drawEllipse(2, -17, 8, 8); // Nose painter->setBrush(Qt::black); painter->drawEllipse(QRectF(-2, -22, 4, 4)); // Pupils painter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4)); painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4)); // Ears painter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red); painter->drawEllipse(-17, -12, 16, 16); painter->drawEllipse(1, -12, 16, 16); // Tail QPainterPath path(QPointF(0, 20)); path.cubicTo(-5, 22, -5, 22, 0, 25); path.cubicTo(5, 27, 5, 32, 0, 30); path.cubicTo(-5, 32, -5, 42, 0, 35); painter->setBrush(Qt::NoBrush); painter->drawPath(path); } //! [3] //! [4] void Mouse::advance(int step) { if (!step) return; //! [4] // Don't move too far away //! [5] QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0)); if (lineToCenter.length() > 150) { qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length()); if (lineToCenter.dy() < 0) angleToCenter = TwoPi - angleToCenter; angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2); if (angleToCenter < Pi && angleToCenter > Pi / 4) { // Rotate left angle += (angle < -Pi / 2) ? 0.25 : -0.25; } else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) { // Rotate right angle += (angle < Pi / 2) ? 0.25 : -0.25; } } else if (::sin(angle) < 0) { angle += 0.25; } else if (::sin(angle) > 0) { angle -= 0.25; //! [5] //! [6] } //! [6] // Try not to crash with any other mice //! [7] const QList dangerMice = scene()->items(QPolygonF() << mapToScene(0, 0) << mapToScene(-30, -50) << mapToScene(30, -50)); for (QGraphicsItem *item : dangerMice) { if (item == this) continue; QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0)); qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length()); if (lineToMouse.dy() < 0) angleToMouse = TwoPi - angleToMouse; angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2); if (angleToMouse >= 0 && angleToMouse < Pi / 2) { // Rotate right angle += 0.5; } else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) { // Rotate left angle -= 0.5; //! [7] //! [8] } //! [8] //! [9] } //! [9] // Add some random movement //! [10] if (dangerMice.size() > 1 && (qrand() % 10) == 0) { if (qrand() % 1) angle += (qrand() % 100) / 500.0; else angle -= (qrand() % 100) / 500.0; } //! [10] //! [11] speed += (-50 + qrand() % 100) / 100.0; qreal dx = ::sin(angle) * 10; mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5; setRotation(rotation() + dx); setPos(mapToParent(0, -(3 + sin(speed) * 3))); } //! [11] qbs-src-1.13.1/examples/collidingmice/mouse.h000066400000000000000000000055141347155106100211000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MOUSE_H #define MOUSE_H #include //! [0] class Mouse : public QGraphicsItem { public: Mouse(); QRectF boundingRect() const; QPainterPath shape() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); protected: void advance(int step); private: qreal angle; qreal speed; qreal mouseEyeDirection; QColor color; }; //! [0] #endif qbs-src-1.13.1/examples/compiled-qml/000077500000000000000000000000001347155106100173535ustar00rootroot00000000000000qbs-src-1.13.1/examples/compiled-qml/MainForm.ui.qml000066400000000000000000000052211347155106100222120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import QtQuick 2.3 Rectangle { property alias mouseArea: mouseArea width: 360 height: 360 MouseArea { id: mouseArea anchors.fill: parent } Image { anchors.centerIn: parent source: "cheese.jpg" } } qbs-src-1.13.1/examples/compiled-qml/cheese.jpg000066400000000000000000000057251347155106100213220ustar00rootroot00000000000000ÿØÿàJFIFHHÿîAdobed@ÿÛ„      ÿÀ^^ÿÝ ÿÄ¢  s!1AQa"q2‘¡±B#ÁRÑá3bð$r‚ñ%C4S’¢²csÂ5D'“£³6TdtÃÒâ&ƒ „”EF¤´VÓU(òãóÄÔäôeu…•¥µÅÕåõfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø)9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúm!1AQa"q‘2¡±ðÁÑá#BRbrñ3$4C‚’S%¢c²ÂsÒ5âDƒT“ &6E'dtU7ò£³Ã()Óã󄔤´ÄÔäôeu…•¥µÅÕåõFVfv†–¦¶ÆÖæöGWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúÿÚ ?ûAÓo¢‡Ç<7‰éÔéâk)n£rM ðÈ‚¥²AZ†úFù"7P¦cåâvù`ä•ÁHØt=F V¤š1`¤ìkã’ ¬I’Q­È‘·ê„4¯ÅŽûwÉlIb:¯ž<¿£Ìmîï+84ha£þU6~§§ïNŸ~eøžž/'‡zÿÑû?JíÔöÏ §¨Qy?Ö=°ˆq-Òš„j{d¼&aÆpJ‘Jt"˜øtŽ0UÔ‡nÛŒ ;@ÞÚ ˆšbJƒÄѨ|ù +|µ=ໞYâäÈbBÿ!%OßÇ,ˆÅÖý̼IŽTôk+[-:Ö+ e¶´€)þQ«îNç!–|g•À§šÝNÊ=NÂæÍ¶€PžÌ7ÊÄD½'«!#a…i¾\’ݽ;‹vJÕÆÿÛ˜Ù#,G„¹-€©Ï ·¨J/çŽÚ9îfqP!yôEI9|HËY²h>Ró'æšõKébÐIÓlQˆÒž«Ýœƒ×Àe>)ŸZr#†1çºqå_>y¢Öîõ‹‡¾µ”"L`R¬v÷ȆíÄ%ÈSé›I–EŠhÛœR…daЩfA ‹ØZ¨=5µ„ 1€{|ˆ34›jzïNMïí<™†¸5 ‘ZW·Ë5µŒ¬ k-©­ð9$.ãN„ø}H%A]ÈÔøø×#JÿÿÔûCÉ)Øðzz…zt ôÉÄð›Ô‹K­´}Ní ¿U”±fŽZ”ÿ`À~'›<ûÆ\'¸Ý|ý+Ò†ÄZ'è«`¾¤«xÊ(!ŒÛ“56ÄiñBbRÉ]"þò@jñrO¯4*³Ü¹øª±<@Ø|€ðrä–Be.e”ˆ ª@?>”Ê:3s1 Ü.ʵýXlõE!Üo°&§¬ z×åŠUÐöë¡} 4ðÚ¸ÄyªrRO]öOL<;Õ£‰ÿÕû8ÀÖ£®x]½B“G^„×¹Ä*€·]Ù¶5ÛÄâ(VH _‰ºøòDŒx‚6ªc¢€6##Í’Ÿ¨T|@úâ`–ê\ñ=ÎB’ºª*¤×ß TJT{cJ»wQ·l•*àkþKxd$ÛÔoô`WÿÖû=Q×–xSÔ/$q$liÓÙRnK‹}Q»³¡º†mÁb4ö­r2‘$&1âºf‡æhîª5;É®9 $2HÅ¢„Ҟ؀@«t¢9=âÔ¹†'‘x4ˆ®ÉàXTŒÈɵ*Ƈ®ô4Êì³RcÇzn{âÔL½‡\°´&жþq¯õ–”¯Ñ€Á"j«)$PŽ»ä¦V¦%#š’y)‘¥ÿ×û;ÐPÇ<*Þ¡PPûõÄ«¤U(A^JÀ†SЂ(AƃanöÑGéÃaF¯Ùgäƒè¥Oß™~.!¿þý¿$LõTS#3™$¶ÔÙ‹“'¾¬€¦…jFÕ4`½ÇÏä”5Á"ƒ¹é’Ç»0/8ùÂÇÊvB{ Ó\KQmj†!jeEz岘€óc—Ïòþsù¦æê–‘Ckk_†10»1©ÊŒæz·Œ1Ròoæ<úÄñXêð¤rÌBÅs*9”“JøŒÌA©5Ï«dа'¥wtã³Tdô–µíN™ŽÜÿÿÐû4ÊÛýÆxCÔ¶ŒAZ‘Ö§$‚¨O&@¯°Û¯øTo@r*´ÍU AÔø{âW§A×®ˆC¼m+- Fãl³c7Ë¿™¶7:šeˆ‚ÖÖ¡bDë@?‰9‹’w77 ÆK,ŠF›uðË,Ä0 [!‡Ë2YÜE…Ò}[.Òi½1!ñ#¾lqJñ‚]|ÅJ“~'Óú2¾­ÿÑû9-üNxCÔ0/2k^e°Ôôû- F‹QŠxÚ{¹¦vP[øþÖÕ©öÆy죌˫?µvx‘ =t=A"´>ã$Fì¹A¹p¶ pU vß׆Q€ì—râ4à ‡™yÃËku¨&«lÞµåw*àSìrYôüQãÇËöì«ÒQZF†„§«â‚”¨Úž,Àã2<7»q¡»'m®\E|˜ìÔO†CI£žLüÞÏö°É©ˆ”ÏÒŠâ´‚ºˆÃÿ7ÄŸ¦™¸ÍÁÃCo–ßo7w=U9ÓM©˜öÝOÿÒûy“§9/Ññîøôa>Ý^ÚêÜeÓL+È$ÔB|wäGß•œÚ~+ž;;ÝHú~‰G-}[{•'ŸP–)¾©d–Öá}麻ñïSÊ´ñ É㙜%áDF5½o*ëw¿¾€ b ÄI>idâÅá”§!ðÔeiÿÙqbs-src-1.13.1/examples/compiled-qml/main.cpp000066400000000000000000000052061347155106100210060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); } qbs-src-1.13.1/examples/compiled-qml/main.qml000066400000000000000000000051111347155106100210100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import QtQuick 2.4 import QtQuick.Window 2.2 Window { visible: true MainForm { anchors.fill: parent mouseArea.onClicked: { Qt.quit(); } } } qbs-src-1.13.1/examples/compiled-qml/myapp.qbs000066400000000000000000000051421347155106100212120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs CppApplication { Depends { name: "Qt.quick" } files: [ "cheese.jpg", "main.cpp", "qml.qrc" ] Group { name: "QML Files" files: ["*.qml"] } } qbs-src-1.13.1/examples/compiled-qml/qml.qrc000066400000000000000000000002341347155106100206520ustar00rootroot00000000000000 main.qml MainForm.ui.qml cheese.jpg qbs-src-1.13.1/examples/examples.qbs000066400000000000000000000056751347155106100173320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs Project { references: [ "app-and-lib/app_and_lib.qbs", "cocoa-application/CocoaApplication.qbs", "cocoa-touch-application/CocoaTouchApplication.qbs", "code-generator/code-generator.qbs", "collidingmice/collidingmice.qbs", "compiled-qml/myapp.qbs", "helloworld-complex/hello.qbs", "helloworld-minimal/hello.qbs", "helloworld-qt/hello.qbs", "install-bundle/install-bundle.qbs", "protobuf/cpp/addressbook.qbs", "protobuf/objc/addressbook.qbs", ] } qbs-src-1.13.1/examples/helloworld-complex/000077500000000000000000000000001347155106100206105ustar00rootroot00000000000000qbs-src-1.13.1/examples/helloworld-complex/hello.qbs000066400000000000000000000064261347155106100224320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs 1.0 Project { property bool hasSpecialFeature: true Application { name: 'HelloWorld-Complex' Depends { name: 'cpp' } cpp.defines: ['SOMETHING'] files: [ "src/foo.h", "src/foo.cpp" ] Group { condition: project.hasSpecialFeature prefix: "src/" files: ["specialfeature.cpp", "specialfeature.h"] } Group { cpp.defines: { var defines = outer.concat([ 'HAVE_MAIN_CPP', cpp.debugInformation ? '_DEBUG' : '_RELEASE' ]); if (project.hasSpecialFeature) defines.push("HAS_SPECIAL_FEATURE"); return defines; } prefix: "src/" files: [ 'main.cpp' ] } } } qbs-src-1.13.1/examples/helloworld-complex/src/000077500000000000000000000000001347155106100213775ustar00rootroot00000000000000qbs-src-1.13.1/examples/helloworld-complex/src/foo.cpp000066400000000000000000000047671347155106100227040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SOMETHING # error missing define SOMETHING #endif int someUsefulFunction() { return 156; } qbs-src-1.13.1/examples/helloworld-complex/src/foo.h000066400000000000000000000047141347155106100223410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FOO_H #define FOO_H int someUsefulFunction(); #endif qbs-src-1.13.1/examples/helloworld-complex/src/main.cpp000066400000000000000000000055171347155106100230370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "foo.h" #ifdef HAS_SPECIAL_FEATURE #include "specialfeature.h" #endif #include #ifndef HAVE_MAIN_CPP # error missing define HAVE_MAIN_CPP #endif #ifndef SOMETHING # error missing define SOMETHING #endif int main() { someUsefulFunction(); #ifdef _DEBUG puts("Hello World! (debug version)"); #else puts("Hello World! (release version)"); #endif #ifdef HAS_SPECIAL_FEATURE bragAboutSpecialFeature(); #endif } qbs-src-1.13.1/examples/helloworld-complex/src/specialfeature.cpp000066400000000000000000000050341347155106100251010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "specialfeature.h" #include void bragAboutSpecialFeature() { std::cout << "I have a special feature!" << std::endl; } qbs-src-1.13.1/examples/helloworld-complex/src/specialfeature.h000066400000000000000000000047611347155106100245540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef HELLO_SPECIAL_FEATURE #define HELLO_SPECIAL_FEATURE void bragAboutSpecialFeature(); #endif qbs-src-1.13.1/examples/helloworld-minimal/000077500000000000000000000000001347155106100205675ustar00rootroot00000000000000qbs-src-1.13.1/examples/helloworld-minimal/hello.qbs000066400000000000000000000047401347155106100224060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs CppApplication { name: "HelloWorld-minimal" files: "main.cpp" } qbs-src-1.13.1/examples/helloworld-minimal/main.cpp000066400000000000000000000047371347155106100222320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { std::cout << "Hello, World!" << std::endl; } qbs-src-1.13.1/examples/helloworld-qt/000077500000000000000000000000001347155106100175655ustar00rootroot00000000000000qbs-src-1.13.1/examples/helloworld-qt/hello.qbs000066400000000000000000000047321347155106100214050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs QtApplication { name: "HelloWorld-Qt" files: "main.cpp" } qbs-src-1.13.1/examples/helloworld-qt/main.cpp000066400000000000000000000050741347155106100212230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include int main() { QTextStream(stdout) << QCoreApplication::translate("hello", "Hello, World!") << endl; } qbs-src-1.13.1/examples/install-bundle/000077500000000000000000000000001347155106100177055ustar00rootroot00000000000000qbs-src-1.13.1/examples/install-bundle/MainMenu.xib000066400000000000000000001407211347155106100221270ustar00rootroot00000000000000 Default Left to Right Right to Left Default Left to Right Right to Left qbs-src-1.13.1/examples/install-bundle/Storyboard.storyboard000066400000000000000000000053041347155106100241510ustar00rootroot00000000000000 qbs-src-1.13.1/examples/install-bundle/assetcatalog1.xcassets/000077500000000000000000000000001347155106100242745ustar00rootroot00000000000000qbs-src-1.13.1/examples/install-bundle/assetcatalog1.xcassets/other.imageset/000077500000000000000000000000001347155106100272125ustar00rootroot00000000000000qbs-src-1.13.1/examples/install-bundle/assetcatalog1.xcassets/other.imageset/Contents.json000066400000000000000000000005331347155106100317030ustar00rootroot00000000000000{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }qbs-src-1.13.1/examples/install-bundle/assetcatalog1.xcassets/other.imageset/icon_16x16.png000066400000000000000000000012111347155106100315100ustar00rootroot00000000000000‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-1.13.1/examples/install-bundle/assetcatalog1.xcassets/other.imageset/icon_16x16@2x.png000066400000000000000000000012311347155106100320640ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-1.13.1/examples/install-bundle/assetcatalog2.xcassets/000077500000000000000000000000001347155106100242755ustar00rootroot00000000000000qbs-src-1.13.1/examples/install-bundle/assetcatalog2.xcassets/other.imageset/000077500000000000000000000000001347155106100272135ustar00rootroot00000000000000qbs-src-1.13.1/examples/install-bundle/assetcatalog2.xcassets/other.imageset/Contents.json000066400000000000000000000005331347155106100317040ustar00rootroot00000000000000{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }qbs-src-1.13.1/examples/install-bundle/assetcatalog2.xcassets/other.imageset/icon_16x16.png000066400000000000000000000012111347155106100315110ustar00rootroot00000000000000‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-1.13.1/examples/install-bundle/assetcatalog2.xcassets/other.imageset/icon_16x16@2x.png000066400000000000000000000012311347155106100320650ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-1.13.1/examples/install-bundle/coreutils.cpp000066400000000000000000000047011347155106100224240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "coreutils.h" int foo() { return 42; } qbs-src-1.13.1/examples/install-bundle/coreutils.h000066400000000000000000000047021347155106100220720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef _WIN32 __declspec(dllexport) #endif int foo(); qbs-src-1.13.1/examples/install-bundle/install-bundle.qbs000066400000000000000000000031101347155106100233240ustar00rootroot00000000000000import qbs import qbs.FileInfo Project { CppApplication { Depends { name: "windowutils" } Depends { name: "ib"; condition: qbs.targetOS.contains("darwin") } Depends { name: "Qt"; submodules: ["core", "gui", "widgets"] } name: "window" property bool isBundle: qbs.targetOS.contains("darwin") && bundle.isBundle targetName: isBundle ? "Window" : "window" files: [ "main.cpp", "assetcatalog1.xcassets", "assetcatalog2.xcassets", "white.iconset", "MainMenu.xib", "Storyboard.storyboard" ] cpp.minimumMacosVersion: "10.10" Group { fileTagsFilter: isBundle ? ["bundle.content"] : ["application"] qbs.install: true qbs.installDir: isBundle ? "Applications" : (qbs.targetOS.contains("windows") ? "" : "bin") qbs.installSourceBase: product.buildDirectory } } DynamicLibrary { Depends { name: "cpp" } name: "windowutils" property bool isBundle: qbs.targetOS.contains("darwin") && bundle.isBundle targetName: isBundle ? "WindowUtils" : "windowutils" files: ["coreutils.cpp", "coreutils.h"] Group { fileTagsFilter: isBundle ? ["bundle.content"] : ["dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_import"] qbs.install: true qbs.installDir: isBundle ? "Library/Frameworks" : (qbs.targetOS.contains("windows") ? "" : "lib") qbs.installSourceBase: product.buildDirectory } } } qbs-src-1.13.1/examples/install-bundle/main.cpp000066400000000000000000000050751347155106100213440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; window.show(); return app.exec(); } qbs-src-1.13.1/examples/install-bundle/white.iconset/000077500000000000000000000000001347155106100224705ustar00rootroot00000000000000qbs-src-1.13.1/examples/install-bundle/white.iconset/icon_16x16.png000066400000000000000000000012111347155106100247660ustar00rootroot00000000000000‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-1.13.1/examples/install-bundle/white.iconset/icon_16x16@2x.png000066400000000000000000000012311347155106100253420ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-1.13.1/examples/protobuf/000077500000000000000000000000001347155106100166305ustar00rootroot00000000000000qbs-src-1.13.1/examples/protobuf/cpp/000077500000000000000000000000001347155106100174125ustar00rootroot00000000000000qbs-src-1.13.1/examples/protobuf/cpp/README.md000066400000000000000000000012721347155106100206730ustar00rootroot00000000000000### Addressbook c++ example This example shows how to build a cpp application that uses Google protobuf. In order to build this example, you'll need to have a protobuf headers and library installed in the system in locations where QBS can find them. On Linux, you can install a package to the system. On macOS, you can use brew or compile and install protobuf manually: - to /usr/local/ - to any folder, say /Users//protobuf. Then you'll need to set protobuf.libraryPath: "/Users//protobuf/lib" and protobuf.includePath: "/Users//protobuf/include" On Windows, you have to compile and install protobuf manually to any folder and use libraryPath and includePath as shown above qbs-src-1.13.1/examples/protobuf/cpp/addressbook.qbs000066400000000000000000000005421347155106100224220ustar00rootroot00000000000000import qbs CppApplication { name: "addressbook_cpp" consoleApplication: true condition: protobuf.present Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++11" Depends { id: protobuf; name: "protobuf.cpp"; required: false } files: [ "../shared/addressbook.proto", "main.cpp", "README.md", ] } qbs-src-1.13.1/examples/protobuf/cpp/main.cpp000066400000000000000000000141101347155106100210370ustar00rootroot00000000000000// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include #include #include #include "addressbook.pb.h" using google::protobuf::util::TimeUtil; int printUsage(char *argv0) { std::cerr << "Usage: " << argv0 << "add|list ADDRESS_BOOK_FILE" << std::endl; return -1; } std::string readString(const std::string &promt) { std::string result; std::cout << promt; std::getline(std::cin, result); return result; } // This function fills in a Person message based on user input. void promptForAddress(tutorial::Person* person) { std::cout << "Enter person ID number: "; int id; std::cin >> id; person->set_id(id); std::cin.ignore(256, '\n'); *person->mutable_name() = readString("Enter name: "); const auto email = readString("Enter email address (blank for none): "); if (!email.empty()) person->set_email(email); while (true) { const auto number = readString("Enter a phone number (or leave blank to finish): "); if (number.empty()) break; tutorial::Person::PhoneNumber *phone_number = person->add_phones(); phone_number->set_number(number); const auto type = readString("Is this a mobile, home, or work phone? "); if (type == "mobile") phone_number->set_type(tutorial::Person::MOBILE); else if (type == "home") phone_number->set_type(tutorial::Person::HOME); else if (type == "work") phone_number->set_type(tutorial::Person::WORK); else std::cout << "Unknown phone type. Using default." << std::endl; } *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL)); } // Iterates though all people in the AddressBook and prints info about them. void listPeople(const tutorial::AddressBook& address_book) { for (int i = 0; i < address_book.people_size(); i++) { const tutorial::Person& person = address_book.people(i); std::cout << "Person ID: " << person.id() << std::endl; std::cout << " Name: " << person.name() << std::endl; if (person.email() != "") { std::cout << " E-mail address: " << person.email() << std::endl; } for (int j = 0; j < person.phones_size(); j++) { const tutorial::Person::PhoneNumber& phone_number = person.phones(j); switch (phone_number.type()) { case tutorial::Person::MOBILE: std::cout << " Mobile phone #: "; break; case tutorial::Person::HOME: std::cout << " Home phone #: "; break; case tutorial::Person::WORK: std::cout << " Work phone #: "; break; default: std::cout << " Unknown phone #: "; break; } std::cout << phone_number.number() << std::endl; } if (person.has_last_updated()) { std::cout << " Updated: " << TimeUtil::ToString(person.last_updated()) << std::endl; } } } int main(int argc, char* argv[]) { // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION; if (argc != 3) return printUsage(argv[0]); tutorial::AddressBook address_book; // Read the existing address book. std::fstream input(argv[2], std::ios::in | std::ios::binary); if (!input) { std::cout << argv[2] << ": File not found." << std::endl; } else if (!address_book.ParseFromIstream(&input)) { std::cerr << "Failed to parse address book." << std::endl; return -1; } const std::string mode(argv[1]); if (mode == "add") { // Add an address. promptForAddress(address_book.add_people()); if (!input) std::cout << "Creating a new file." << std::endl; // Write the new address book back to disk. std::fstream output(argv[2], std::ios::out | std::ios::trunc | std::ios::binary); if (!address_book.SerializeToOstream(&output)) { std::cerr << "Failed to write address book." << std::endl; return -1; } } else if (mode == "list") { listPeople(address_book); } else { return printUsage(argv[0]); } // Optional: Delete all global objects allocated by libprotobuf. google::protobuf::ShutdownProtobufLibrary(); return 0; } qbs-src-1.13.1/examples/protobuf/objc/000077500000000000000000000000001347155106100175455ustar00rootroot00000000000000qbs-src-1.13.1/examples/protobuf/objc/README.md000066400000000000000000000003511347155106100210230ustar00rootroot00000000000000### Addressbook objc example This example shows how to build an objective-c application that uses Google protobuf. In order to build this example, you'll need to have a ProtocolBuffers library or framework installed in the system. qbs-src-1.13.1/examples/protobuf/objc/addressbook.qbs000066400000000000000000000005131347155106100225530ustar00rootroot00000000000000import qbs CppApplication { name: "addressbook_objc" consoleApplication: true condition: protobuf.present && qbs.targetOS.contains("darwin") Depends { name: "cpp" } Depends { id: protobuf; name: "protobuf.objc"; required: false } files: [ "../shared/addressbook.proto", "main.m", ] } qbs-src-1.13.1/examples/protobuf/objc/main.m000066400000000000000000000143251347155106100206540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov ** Contact: abbapoh@gmail.com ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "Addressbook.pbobjc.h" #import int printUsage(char *argv0) { NSString *programName = [[NSString alloc] initWithUTF8String:argv0]; NSLog(@"%@", [[NSString alloc] initWithFormat:@"Usage: %@ add|list ADDRESS_BOOK_FILE", programName]); [programName release]; return -1; } NSString *readString(NSString *promt) { NSLog(@"%@", promt); NSFileHandle *inputFile = [NSFileHandle fileHandleWithStandardInput]; NSData *inputData = [inputFile availableData]; NSString *result = [[[NSString alloc]initWithData:inputData encoding:NSUTF8StringEncoding] autorelease]; result = [[result stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]] autorelease]; return result; } // This function fills in a Person message based on user input. void promptForAddress(Person* person) { person.id_p = [readString(@"Enter person ID number:") intValue]; person.name = readString(@"Enter name:"); NSString *email = readString(@"Enter email address (blank for none):"); if ([email length] != 0) person.email = email; while (true) { NSString *number = readString(@"Enter a phone number (or leave blank to finish):"); if ([number length] == 0) break; Person_PhoneNumber* phoneNumber = [[Person_PhoneNumber alloc] init]; phoneNumber.number = number; NSString *type = readString(@"Is this a mobile, home, or work phone?:"); NSLog(@"\"%@\"", type); if ([type compare:@"mobile"] == NSOrderedSame) phoneNumber.type = Person_PhoneType_Mobile; else if ([type compare:@"home"] == NSOrderedSame) phoneNumber.type = Person_PhoneType_Home; else if ([type compare:@"work"] == NSOrderedSame) phoneNumber.type = Person_PhoneType_Work; else NSLog(@"%@", @"Unknown phone type. Using default."); [person.phonesArray addObject:phoneNumber]; } } // Iterates though all people in the AddressBook and prints info about them. void listPeople(AddressBook *addressBook) { NSArray *people = addressBook.peopleArray; for (unsigned i = 0; i < [people count]; i++) { Person *person = [people objectAtIndex:i]; NSLog(@"%@", [[[NSString alloc] initWithFormat:@"Person ID: %d", person.id_p] autorelease]); NSLog(@"%@", [[[NSString alloc] initWithFormat:@"Person name: %@", person.name] autorelease]); if ([person.email length] != 0) { NSLog(@"%@", [[[NSString alloc] initWithFormat:@"E-mail address: %@", person.email] autorelease]); } NSArray *phones = person.phonesArray; for (unsigned j = 0; j < [phones count]; j++) { Person_PhoneNumber *phoneNumber = [phones objectAtIndex:j]; NSString *phonePrefix; switch (phoneNumber.type) { case Person_PhoneType_Mobile: phonePrefix = @"Mobile phone"; break; case Person_PhoneType_Home: phonePrefix = @"Home phone"; break; case Person_PhoneType_Work: phonePrefix = @"Work phone"; break; default: phonePrefix = @"Unknown phone"; break; } NSLog(@"%@", [[[NSString alloc] initWithFormat:@" %@ #: %@", phonePrefix, phoneNumber.number] autorelease]); } printf("\n"); } } int main(int argc, char *argv[]) { if (argc != 3) return printUsage(argv[0]); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; AddressBook *addressBook;// = [AddressBook alloc]; NSString *filePath = [[[NSString alloc] initWithUTF8String:argv[2]] autorelease]; // Read the existing address book. NSData *data = [NSData dataWithContentsOfFile:filePath]; if (!data) { NSLog(@"%@", [[NSString alloc] initWithFormat:@"%@ : File not found.", filePath]); addressBook = [[[AddressBook alloc] init] autorelease]; } else { NSError *error; addressBook = [AddressBook parseFromData:data error:&error]; if (!addressBook) { NSLog(@"%@", @"Failed to parse address book."); [pool drain]; return -1; } } if (strcmp(argv[1], "add") == 0) { // Add an address. Person *person = [[Person alloc] init]; promptForAddress(person); [addressBook.peopleArray addObject:person]; if (!data) { NSLog(@"%@", @"Creating a new file."); } [[addressBook data] writeToFile:filePath atomically:YES]; } else if (strcmp(argv[1], "list") == 0) { listPeople(addressBook); } else { [pool drain]; return printUsage(argv[0]); } [pool drain]; return 0; } qbs-src-1.13.1/examples/protobuf/shared/000077500000000000000000000000001347155106100200765ustar00rootroot00000000000000qbs-src-1.13.1/examples/protobuf/shared/addressbook.proto000066400000000000000000000023221347155106100234620ustar00rootroot00000000000000// See README.txt for information and build instructions. // // Note: START and END tags are used in comments to define sections used in // tutorials. They are not part of the syntax for Protocol Buffers. // // To get an in-depth walkthrough of this file and the related examples, see: // https://developers.google.com/protocol-buffers/docs/tutorials // [START declaration] syntax = "proto3"; package tutorial; import "google/protobuf/timestamp.proto"; // [END declaration] // [START java_declaration] option java_package = "com.example.tutorial"; option java_outer_classname = "AddressBookProtos"; // [END java_declaration] // [START csharp_declaration] option csharp_namespace = "Google.Protobuf.Examples.AddressBook"; // [END csharp_declaration] // [START messages] message Person { string name = 1; int32 id = 2; // Unique ID number for this person. string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } repeated PhoneNumber phones = 4; google.protobuf.Timestamp last_updated = 5; } // Our address book file is just one of these. message AddressBook { repeated Person people = 1; } // [END messages] qbs-src-1.13.1/qbs-resources/000077500000000000000000000000001347155106100157475ustar00rootroot00000000000000qbs-src-1.13.1/qbs-resources/imports/000077500000000000000000000000001347155106100174445ustar00rootroot00000000000000qbs-src-1.13.1/qbs-resources/imports/QbsApp.qbs000066400000000000000000000016001347155106100213360ustar00rootroot00000000000000import qbs import qbs.FileInfo QbsProduct { Depends { name: "qbscore" } Depends { name: "cpp" } Depends { name: "qbsversion" } type: ["application", "qbsapplication"] version: qbsversion.version consoleApplication: true cpp.includePaths: [ "../shared", // for the logger ] Group { fileTagsFilter: product.type .concat(qbs.buildVariant === "debug" ? ["debuginfo_app"] : []) qbs.install: true qbs.installDir: targetInstallDir qbs.installSourceBase: buildDirectory } targetInstallDir: qbsbuildconfig.appInstallDir Group { name: "logging" prefix: FileInfo.joinPaths(product.sourceDirectory, "../shared/logging") + '/' files: [ "coloredoutput.cpp", "coloredoutput.h", "consolelogger.cpp", "consolelogger.h" ] } } qbs-src-1.13.1/qbs-resources/imports/QbsAutotest.qbs000066400000000000000000000023041347155106100224300ustar00rootroot00000000000000import qbs import qbs.FileInfo import qbs.Utilities QtApplication { type: ["application", "autotest"] consoleApplication: true property string testName name: "tst_" + testName Depends { name: "Qt.testlib" } Depends { name: "qbscore" } Depends { name: "qbsbuildconfig" } cpp.defines: [ "QBS_TEST_SUITE_NAME=" + Utilities.cStringQuote(testName.toUpperCase().replace("-", "_")) ] cpp.includePaths: [ "../../../src", "../../../src/app/shared", // for the logger ] cpp.cxxLanguageVersion: "c++14" Group { name: "logging" prefix: FileInfo.joinPaths(product.sourceDirectory, "../../../src/app/shared/logging") + '/' files: [ "coloredoutput.cpp", "coloredoutput.h", "consolelogger.cpp", "consolelogger.h" ] } cpp.rpaths: [FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix, qbsbuildconfig.libDirName)] qbs.commonRunEnvironment: ({ "QBS_INSTALL_DIR": FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix) }) Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: qbsbuildconfig.appInstallDir } } qbs-src-1.13.1/qbs-resources/imports/QbsLibrary.qbs000066400000000000000000000054241347155106100222320ustar00rootroot00000000000000import qbs import qbs.FileInfo import qbs.Utilities QbsProduct { Depends { name: "cpp" } version: qbsversion.version type: libType targetName: (qbs.enableDebugCode && qbs.targetOS.contains("windows")) ? (name + 'd') : name cpp.defines: base.concat(visibilityType === "static" ? ["QBS_STATIC_LIB"] : ["QBS_LIBRARY"]) cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined Properties { condition: qbs.toolchain.contains("gcc") cpp.soVersion: version.replace(/\.\d+$/, '') } cpp.visibility: "minimal" property string visibilityType: staticBuild ? "static" : "dynamic" property string headerInstallPrefix: "/include/qbs" property bool hasExporter: Utilities.versionCompare(qbs.version, "1.12") >= 0 property bool generatePkgConfigFile: qbsbuildconfig.generatePkgConfigFiles && hasExporter property bool generateQbsModule: install && qbsbuildconfig.generateQbsModules && hasExporter property bool staticBuild: Qt.core.staticBuild || qbsbuildconfig.staticBuild property stringList libType: [staticBuild ? "staticlibrary" : "dynamiclibrary"] Depends { name: "Exporter.pkgconfig"; condition: generatePkgConfigFile } Depends { name: "Exporter.qbs"; condition: generateQbsModule } Group { fileTagsFilter: libType.concat("dynamiclibrary_symlink") .concat(qbs.buildVariant === "debug" ? ["debuginfo_dll"] : []) qbs.install: install qbs.installDir: targetInstallDir qbs.installSourceBase: buildDirectory } targetInstallDir: qbsbuildconfig.libInstallDir Group { fileTagsFilter: ["dynamiclibrary_import"] qbs.install: install qbs.installDir: qbsbuildconfig.importLibInstallDir } Group { fileTagsFilter: "Exporter.pkgconfig.pc" qbs.install: install qbs.installDir: qbsbuildconfig.pkgConfigInstallDir } Group { fileTagsFilter: "Exporter.qbs.module" qbs.install: install qbs.installDir: FileInfo.joinPaths(qbsbuildconfig.qbsModulesBaseDir, product.name) } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false cpp.linkerFlags: ["-compatibility_version", cpp.soVersion] } Export { Depends { name: "cpp" } Depends { name: "Qt"; submodules: ["core"] } Properties { condition: product.hasExporter prefixMapping: [{ prefix: product.sourceDirectory, replacement: FileInfo.joinPaths(product.qbs.installPrefix, product.headerInstallPrefix) }] } cpp.includePaths: [product.sourceDirectory] cpp.defines: product.visibilityType === "static" ? ["QBS_STATIC_LIB"] : [] } } qbs-src-1.13.1/qbs-resources/imports/QbsProduct.qbs000066400000000000000000000012611347155106100222410ustar00rootroot00000000000000import qbs Product { Depends { name: "qbsbuildconfig" } Depends { name: "qbsversion" } Depends { name: "Qt.core"; versionAtLeast: minimumQtVersion } property string minimumQtVersion: "5.9.0" property bool install: true property string targetInstallDir cpp.defines: { var res = ["QT_NO_CAST_FROM_ASCII", "QT_NO_PROCESS_COMBINED_ARGUMENT_START"]; if (qbs.toolchain.contains("msvc")) res.push("_SCL_SECURE_NO_WARNINGS"); if (qbs.enableDebugCode) res.push("QT_STRICT_ITERATORS"); return res; } cpp.cxxLanguageVersion: "c++14" cpp.enableExceptions: true cpp.rpaths: qbsbuildconfig.libRPaths } qbs-src-1.13.1/qbs-resources/modules/000077500000000000000000000000001347155106100174175ustar00rootroot00000000000000qbs-src-1.13.1/qbs-resources/modules/docker/000077500000000000000000000000001347155106100206665ustar00rootroot00000000000000qbs-src-1.13.1/qbs-resources/modules/docker/docker.qbs000066400000000000000000000026341347155106100226510ustar00rootroot00000000000000import qbs import qbs.FileInfo import qbs.Probes import qbs.Utilities Module { Probes.BinaryProbe { id: dockercli names: ["docker"] } property string dockerFilePath: dockercli.filePath property string imageTag property stringList buildFlags FileTagger { patterns: ["Dockerfile"] fileTags: ["docker.dockerfile"] } Rule { inputs: ["docker.dockerfile"] Artifact { // Let Docker handle the dependency management filePath: FileInfo.joinPaths(product.buildDirectory, Utilities.getHash(input.filePath), ".docker-image-dummy") fileTags: ["docker.docker-image"] } prepare: { var args = ["build"]; var tag = product.docker.imageTag; if (tag) args.push("-t", tag); Array.prototype.push.apply(args, product.docker.buildFlags); args.push("."); var cmd = new Command(product.docker.dockerFilePath, args); cmd.workingDirectory = FileInfo.path(input.filePath); cmd.description = "building docker image " + FileInfo.fileName(cmd.workingDirectory) + (tag ? " (" + tag + ")" : ""); return [cmd]; } } validate: { if (!dockerFilePath) throw ModUtils.ModuleError("Could not find Docker."); } } qbs-src-1.13.1/qbs-resources/modules/qbsbuildconfig/000077500000000000000000000000001347155106100224125ustar00rootroot00000000000000qbs-src-1.13.1/qbs-resources/modules/qbsbuildconfig/qbsbuildconfig.qbs000066400000000000000000000050411347155106100261140ustar00rootroot00000000000000import qbs import qbs.FileInfo Module { Depends { condition: project.withCode name: "cpp" } property bool enableAddressSanitizer: false property bool enableUnitTests: false property bool enableProjectFileUpdates: false property bool enableRPath: true property bool installApiHeaders: true property bool enableBundledQt: true property bool useBundledQtScript: false property bool staticBuild: false property string libDirName: "lib" property string appInstallDir: "bin" property string libInstallDir: qbs.targetOS.contains("windows") ? "bin" : libDirName property string importLibInstallDir: libDirName property string libexecInstallDir: qbs.targetOS.contains("windows") ? appInstallDir : "libexec/qbs" property string systemSettingsDir property bool installManPage: qbs.targetOS.contains("unix") property bool installHtml: true property bool installQch: false property bool generatePkgConfigFiles: installApiHeaders && qbs.targetOS.contains("unix") && !qbs.targetOS.contains("darwin") property bool generateQbsModules: installApiHeaders property string docInstallDir: "share/doc/qbs/html" property string pkgConfigInstallDir: FileInfo.joinPaths(libDirName, "pkgconfig") property string qbsModulesBaseDir: FileInfo.joinPaths(libDirName, "qbs", "modules") property string relativeLibexecPath: "../" + libexecInstallDir property string relativePluginsPath: "../" + libDirName property string relativeSearchPath: ".." property stringList libRPaths: { if (enableRPath && project.withCode && cpp.rpathOrigin && product.targetInstallDir) { return [FileInfo.joinPaths(cpp.rpathOrigin, FileInfo.relativePath( FileInfo.joinPaths('/', product.targetInstallDir), FileInfo.joinPaths('/', libDirName)))]; } return []; } property string resourcesInstallDir: "" property string pluginsInstallDir: libDirName + "/qbs/plugins" property string qmlTypeDescriptionsInstallDir: FileInfo.joinPaths(resourcesInstallDir, "share/qbs/qml-type-descriptions") Properties { condition: project.withCode && enableAddressSanitizer && qbs.toolchain.contains("gcc") cpp.cxxFlags: "-fno-omit-frame-pointer" cpp.driverFlags: "-fsanitize=address" } } qbs-src-1.13.1/qbs-resources/modules/qbsversion/000077500000000000000000000000001347155106100216125ustar00rootroot00000000000000qbs-src-1.13.1/qbs-resources/modules/qbsversion/qbsversion.qbs000066400000000000000000000011641347155106100245160ustar00rootroot00000000000000import qbs import qbs.File import qbs.FileInfo import qbs.TextFile Module { Probe { id: qbsVersionProbe property var lastModified: File.lastModified(versionFilePath) property string versionFilePath: FileInfo.joinPaths(path, "..", "..", "..", "VERSION") property string version configure: { var tf = new TextFile(versionFilePath, TextFile.ReadOnly); try { version = tf.readAll().trim(); found = !!version; } finally { tf.close(); } } } version: qbsVersionProbe.version } qbs-src-1.13.1/qbs.pro000066400000000000000000000032631347155106100144650ustar00rootroot00000000000000requires(!cross_compile) include(src/lib/bundledlibs.pri) defineTest(minQtVersion) { maj = $$1 min = $$2 patch = $$3 isEqual(QT_MAJOR_VERSION, $$maj) { isEqual(QT_MINOR_VERSION, $$min) { isEqual(QT_PATCH_VERSION, $$patch) { return(true) } greaterThan(QT_PATCH_VERSION, $$patch) { return(true) } } greaterThan(QT_MINOR_VERSION, $$min) { return(true) } } greaterThan(QT_MAJOR_VERSION, $$maj) { return(true) } return(false) } !minQtVersion(5, 9, 0) { message("Cannot build qbs with Qt version $${QT_VERSION}.") error("Use at least Qt 5.9.0.") } TEMPLATE = subdirs corelib.file = src/lib/corelib/corelib.pro src_app.subdir = src/app src_app.depends = corelib src_libexec.subdir = src/libexec src_plugins.subdir = src/plugins CONFIG(shared, static|shared): src_plugins.depends = corelib tests.depends = static_res static_res.file = static-res.pro static_res.depends = src_app src_libexec src_plugins static.pro qbs_use_bundled_qtscript { scriptenginelib.file = src/lib/scriptengine/scriptengine.pro corelib.depends = scriptenginelib SUBDIRS += scriptenginelib } SUBDIRS += \ corelib\ src_app\ src_libexec\ src_plugins\ static.pro\ static_res\ tests OTHER_FILES += \ doc/*.qdoc \ doc/reference/*.qdoc \ doc/reference/items/convenience/*.qdoc \ doc/reference/items/language/*.qdoc \ doc/reference/jsextensions/*.qdoc \ doc/reference/modules/*.qdoc \ doc/targets/*.qdoc* \ doc/qbs.qdocconf \ doc/config/qbs-project.qdocconf include(qbs_version.pri) include(doc/doc.pri) qbs-src-1.13.1/qbs.qbs000066400000000000000000000024101347155106100144430ustar00rootroot00000000000000import qbs 1.0 Project { minimumQbsVersion: "1.6" qbsSearchPaths: ["qbs-resources"] property bool withCode: true property bool withDocker: true property bool withDocumentation: true property bool withExamples: false property bool withTests: withCode property stringList autotestArguments: [] property stringList autotestWrapper: [] references: [ "share/share.qbs", "scripts/scripts.qbs", ] SubProject { filePath: "docker/docker.qbs" Properties { condition: parent.withDocker } } SubProject { filePath: "doc/doc.qbs" Properties { condition: parent.withDocumentation } } SubProject { filePath: "examples/examples.qbs" Properties { condition: parent.withExamples } } SubProject { filePath: "src/src.qbs" Properties { condition: parent.withCode } } SubProject { filePath: "tests/tests.qbs" Properties { condition: parent.withTests } } Product { name: "version" files: ["VERSION"] } Product { name: "qmake project files for qbs" files: ["**/*.pr[io]"] } } qbs-src-1.13.1/qbs_version.pri000066400000000000000000000002641347155106100162220ustar00rootroot00000000000000QBS_VERSION = $$cat($$PWD/VERSION) QBS_VERSION_MAJ = $$section(QBS_VERSION, ., 0, 0) QBS_VERSION_MIN = $$section(QBS_VERSION, ., 1, 1) DEFINES += QBS_VERSION=\\\"$$QBS_VERSION\\\" qbs-src-1.13.1/scripts/000077500000000000000000000000001347155106100146415ustar00rootroot00000000000000qbs-src-1.13.1/scripts/make-release-archives.bat000066400000000000000000000065641347155106100215010ustar00rootroot00000000000000@echo off REM Copyright (C) 2017 The Qt Company Ltd. REM Contact: https://www.qt.io/licensing/ REM REM This file is part of Qbs. REM REM $QT_BEGIN_LICENSE:LGPL$ REM Commercial License Usage REM Licensees holding valid commercial Qt licenses may use this file in REM accordance with the commercial license agreement provided with the REM Software or, alternatively, in accordance with the terms contained in REM a written agreement between you and The Qt Company. For licensing terms REM and conditions see https://www.qt.io/terms-conditions. For further REM information use the contact form at https://www.qt.io/contact-us. REM REM GNU Lesser General Public License Usage REM Alternatively, this file may be used under the terms of the GNU Lesser REM General Public License version 3 as published by the Free Software REM Foundation and appearing in the file LICENSE.LGPL3 included in the REM packaging of this file. Please review the following information to REM ensure the GNU Lesser General Public License version 3 requirements REM will be met: https://www.gnu.org/licenses/lgpl-3.0.html. REM REM GNU General Public License Usage REM Alternatively, this file may be used under the terms of the GNU REM General Public License version 2.0 or (at your option) the GNU General REM Public license version 3 or any later version approved by the KDE Free REM Qt Foundation. The licenses are as published by the Free Software REM Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 REM included in the packaging of this file. Please review the following REM information to ensure the GNU General Public License requirements will REM be met: https://www.gnu.org/licenses/gpl-2.0.html and REM https://www.gnu.org/licenses/gpl-3.0.html. REM REM $QT_END_LICENSE$ setlocal enabledelayedexpansion || exit /b if not exist VERSION ( echo This script must be run from the qbs source directory 1>&2 && exit /b 1 ) for /f %%j in (VERSION) do ( set "version=!version!%%j," ) set "version=%version:~0,-1%" set builddir=%TEMP%\qbs-release-%version% if exist "%builddir%" ( del /s /q "%builddir%" || exit /b ) qbs setup-toolchains --settings-dir "%builddir%\.settings" --detect || exit /b if exist "%QTDIR%" ( qbs setup-qt --settings-dir "%builddir%\.settings"^ "%QTDIR%\bin\qmake.exe" qt || exit /b ) else ( echo QTDIR environment variable not set or does not exist: %QTDIR% exit /b 1 ) if exist "%QTDIR64%" ( qbs setup-qt --settings-dir "%builddir%\.settings"^ "%QTDIR64%\bin\qmake.exe" qt64 || exit /b ) else ( echo QTDIR64 environment variable not set or does not exist: %QTDIR64% exit /b 1 ) REM Work around QBS-1142, where symlinks to UNC named paths aren't resolved REM properly, for example if this command is being run in a Docker container REM where the current directory is a symlink subst Q: "%CD%" && Q: qbs build --settings-dir "%builddir%\.settings"^ -f qbs.qbs -d "%builddir%\build"^ -p dist qbs.buildVariant:release "products.qbs archive.includeTopLevelDir:true"^ config:release "qbs.installRoot:%builddir%\qbs-windows-x86-%version%" profile:qt^ config:release-64 "qbs.installRoot:%builddir%\qbs-windows-x86_64-%version%" profile:qt64 || exit /b copy /y "%builddir%\build\release\qbs.%version%.nupkg" dist || exit /b copy /y "%builddir%\build\release\qbs-windows-x86-%version%.zip" dist || exit /b copy /y "%builddir%\build\release-64\qbs-windows-x86_64-%version%.zip" dist || exit /b qbs-src-1.13.1/scripts/make-release-archives.sh000077500000000000000000000042401347155106100213350ustar00rootroot00000000000000#!/bin/sh set -e ############################################################################# ## ## Copyright (C) 2016 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# test $# -eq 1 || { echo "Usage: $(basename "$0") " >&2; exit 1; } tag=${1} version=${tag#v} dir_name=qbs-src-${version} git archive --format=tar.gz "--prefix=${dir_name}/" -o "dist/${dir_name}.tar.gz" "${tag}" git archive --format=zip "--prefix=${dir_name}/" -o "dist/${dir_name}.zip" "${tag}" qbs-src-1.13.1/scripts/scripts.qbs000066400000000000000000000001501347155106100170330ustar00rootroot00000000000000import qbs Product { name: "qbs dev scripts" files: [ "*.bat", "*.sh", ] } qbs-src-1.13.1/scripts/update-dmgbuild.sh000077500000000000000000000044171347155106100202550ustar00rootroot00000000000000#!/bin/bash set -e ############################################################################# ## ## Copyright (C) 2016 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# python_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../src/3rdparty/python" repos=(biplist.git@v1.0.3 dmgbuild.git@v1.3.2 ds_store@v1.1.2 mac_alias.git@v2.0.7) for repo in "${repos[@]}" ; do pip install -U --isolated "--prefix=$python_dir" --no-binary :all: --no-compile --no-deps \ "git+git://github.com/qbs/$repo" done rm "$python_dir/lib/python2.7/site-packages/dmgbuild/resources/"*.tiff qbs-src-1.13.1/scripts/update-xcspecs.sh000077500000000000000000000050731347155106100201350ustar00rootroot00000000000000#!/bin/bash set -e ############################################################################# ## ## Copyright (C) 2016 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of Qbs. ## ## $QT_BEGIN_LICENSE:LGPL$ ## Commercial License Usage ## Licensees holding valid commercial Qt licenses may use this file in ## accordance with the commercial license agreement provided with the ## Software or, alternatively, in accordance with the terms contained in ## a written agreement between you and The Qt Company. For licensing terms ## and conditions see https://www.qt.io/terms-conditions. For further ## information use the contact form at https://www.qt.io/contact-us. ## ## GNU Lesser General Public License Usage ## Alternatively, this file may be used under the terms of the GNU Lesser ## General Public License version 3 as published by the Free Software ## Foundation and appearing in the file LICENSE.LGPL3 included in the ## packaging of this file. Please review the following information to ## ensure the GNU Lesser General Public License version 3 requirements ## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ## ## GNU General Public License Usage ## Alternatively, this file may be used under the terms of the GNU ## General Public License version 2.0 or (at your option) the GNU General ## Public license version 3 or any later version approved by the KDE Free ## Qt Foundation. The licenses are as published by the Free Software ## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ## included in the packaging of this file. Please review the following ## information to ensure the GNU General Public License requirements will ## be met: https://www.gnu.org/licenses/gpl-2.0.html and ## https://www.gnu.org/licenses/gpl-3.0.html. ## ## $QT_END_LICENSE$ ## ############################################################################# # Update build specs from Xcode - this script should be run when new Xcode releases are made. specs_dir="$(xcrun --sdk macosx --show-sdk-platform-path)/Developer/Library/Xcode/Specifications" specs_out_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../share/qbs/modules/bundle" spec_files=("MacOSX Package Types.xcspec" "MacOSX Product Types.xcspec") for spec_file in "${spec_files[@]}" ; do printf "%s\\n" "$(plutil -convert json -r -o - "$specs_dir/$spec_file")" > \ "$specs_out_dir/${spec_file// /-}" done xcode_version="$(/usr/libexec/PlistBuddy -c 'Print CFBundleShortVersionString' \ "$(xcode-select --print-path)/../Info.plist")" echo "Updated build specs from Xcode $xcode_version" qbs-src-1.13.1/share/000077500000000000000000000000001347155106100142545ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/000077500000000000000000000000001347155106100150415ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/imports/000077500000000000000000000000001347155106100165365ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/imports/qbs/000077500000000000000000000000001347155106100173235ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/imports/qbs/BundleTools/000077500000000000000000000000001347155106100215555ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/imports/qbs/BundleTools/bundle-tools.js000066400000000000000000000060351347155106100245260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var DarwinTools = require("qbs.DarwinTools"); var PropertyList = require("qbs.PropertyList"); function destinationDirectoryForResource(product, input) { var path = product.destinationDirectory; var inputFilePath = FileInfo.joinPaths(input.baseDir, input.fileName); var key = DarwinTools.localizationKey(inputFilePath); if (key) { path = FileInfo.joinPaths(path, localizedResourcesFolderPath(product, key)); var subPath = DarwinTools.relativeResourcePath(inputFilePath); if (subPath && subPath !== '.') path = FileInfo.joinPaths(path, subPath); } else { path = FileInfo.joinPaths(path, product.moduleProperty("bundle", "unlocalizedResourcesFolderPath")); } return path; } function localizedResourcesFolderPath(product, key) { return FileInfo.joinPaths(product.moduleProperty("bundle", "unlocalizedResourcesFolderPath"), key + product.moduleProperty("bundle", "localizedResourcesFolderSuffix")); } function infoPlistContents(infoPlistFilePath) { if (infoPlistFilePath === undefined) return undefined; var plist = new PropertyList(); try { plist.readFromFile(infoPlistFilePath); return plist.toObject(); } finally { plist.clear(); } } function infoPlistFormat(infoPlistFilePath) { if (infoPlistFilePath === undefined) return undefined; var plist = new PropertyList(); try { plist.readFromFile(infoPlistFilePath); return plist.format(); } finally { plist.clear(); } } qbs-src-1.13.1/share/qbs/imports/qbs/DarwinTools/000077500000000000000000000000001347155106100215705ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/imports/qbs/DarwinTools/darwin-tools.js000066400000000000000000000231321347155106100245510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var Utilities = require("qbs.Utilities"); var _deviceMap = { "mac": undefined, // only devices have an ID "iphone": 1, "ipad": 2, "tv": 3, "watch": 4, "car": 5 }; var _platformMap = { "ios": "iPhone", "macos": "MacOSX", "tvos": "AppleTV", "watchos": "Watch" }; var _platformDeviceMap = { "ios": ["iphone", "ipad"], "macos": ["mac"], "tvos": ["tv"], "watchos": ["watch"] } /** * Returns the numeric identifier corresponding to an Apple device name * (i.e. for use by TARGETED_DEVICE_FAMILY). */ function appleDeviceNumber(deviceName) { return _deviceMap[deviceName]; } /** * Returns the list of target devices available for the given qbs target OS list. */ function targetDevices(targetOS) { for (var key in _platformDeviceMap) { if (targetOS.contains(key)) return _platformDeviceMap[key]; } } /** * Returns the TARGETED_DEVICE_FAMILY string given a list of target device names. */ function targetedDeviceFamily(deviceNames) { return deviceNames.map(function (deviceName) { return appleDeviceNumber(deviceName); }); } /** * Returns the most appropriate Apple platform name given a targetOS list. */ function applePlatformName(targetOSList, platformType) { return applePlatformDirectoryName(targetOSList, platformType).toLowerCase(); } /** * Returns the most appropriate Apple platform directory name given a targetOS list and version. */ function applePlatformDirectoryName(targetOSList, platformType, version, throwOnError) { var suffixMap = { "device": "OS", "simulator": "Simulator" }; for (var key in _platformMap) { if (targetOSList.contains(key)) { // there are no MacOSXOS or MacOSXSimulator platforms var suffix = (key !== "macos") ? (suffixMap[platformType] || "") : ""; return _platformMap[key] + suffix + (version || ""); } } if (throwOnError || throwOnError === undefined) throw("No Apple platform corresponds to target OS list: " + targetOSList); } /** * Returns the localization of the resource at the given path, * or undefined if the path does not contain an {xx}.lproj path segment. */ function localizationKey(path) { return _resourceFileProperties(path)[0]; } /** * Returns the path of a localized resource at the given path, * relative to its containing {xx}.lproj directory, or '.' * if the resource is unlocalized (not contained in an lproj directory). */ function relativeResourcePath(path) { return _resourceFileProperties(path)[1]; } function _resourceFileProperties(path) { var lprojKey = ".lproj/"; var lproj = path.indexOf(lprojKey); if (lproj >= 0) { // The slash preceding XX.lproj var slashIndex = path.slice(0, lproj).lastIndexOf('/'); if (slashIndex >= 0) { var localizationKey = path.slice(slashIndex + 1, lproj); var relativeResourcePath = FileInfo.path(path.slice(lproj + lprojKey.length)); return [ localizationKey, relativeResourcePath ]; } } return [ undefined, '.' ]; } var PropertyListVariableExpander = (function () { function PropertyListVariableExpander() { } /** * Recursively perform variable replacements in an environment dictionary. */ PropertyListVariableExpander.prototype.expand = function (obj, env) { var $this = this; // Possible syntaxes for wrapping an environment variable name var syntaxes = [ {"open": "${", "close": "}"}, {"open": "$(", "close": ")"}, {"open": "@", "close": "@"} ]; /** * Finds the first index of a replacement starting with one of the supported syntaxes * This is needed so we don't do recursive substitutions */ function indexOfReplacementStart(syntaxes, str, offset) { var syntax; var idx = str.length; for (var i in syntaxes) { var j = str.indexOf(syntaxes[i].open, offset); if (j !== -1 && j < idx) { syntax = syntaxes[i]; idx = j; } } return { "syntax": syntax, "index": idx === str.length ? -1 : idx }; } function expandRecursive(obj, env, checked) { checked.push(obj); for (var key in obj) { var value = obj[key]; var type = typeof(value); if (type === "object") { if (checked.indexOf(value) !== -1) continue; expandRecursive(value, env, checked); } if (type !== "string") continue; var repl = indexOfReplacementStart(syntaxes, value); var i = repl.index; var changes = false; while (i !== -1) { var j = value.indexOf(repl.syntax.close, i + repl.syntax.open.length); if (j === -1) break; var varParts = value.slice(i + repl.syntax.open.length, j).split(':'); var varName = varParts[0]; var varFormatter = varParts[1]; var varValue = env[varName]; if (undefined === varValue) { // skip replacement if ($this.undefinedVariableFunction) $this.undefinedVariableFunction(key, varName); i = j + repl.syntax.close.length; } else { changes = true; varValue = String(varValue); if (varFormatter !== undefined) varFormatter = varFormatter.toLowerCase(); if (varFormatter === "rfc1034identifier") varValue = Utilities.rfc1034Identifier(varValue); value = value.slice(0, i) + varValue + value.slice(j + repl.syntax.close.length); // avoid recursive substitutions to avoid potentially infinite loops i += varValue.length; } repl = indexOfReplacementStart(syntaxes, value, i); i = repl.index; } if (changes) obj[key] = value; } } expandRecursive(obj, env, []); return obj; }; return PropertyListVariableExpander; }()); /** * JSON.stringify(expandPlistEnvironmentVariables({a:"$(x)3$$(y)",b:{t:"%$(y) $(k)"}}, * {x:"X",y:"Y"}, true)) * Warning undefined variable k in variable expansion * => {"a":"X3$Y","b":{"t":"%Y $(k)"}} */ function expandPlistEnvironmentVariables(obj, env, warn) { var expander = new PropertyListVariableExpander(); expander.undefinedVariableFunction = function (key, varName) { if (warn) console.warn("undefined variable " + varName + " in variable expansion"); }; return expander.expand(obj, env); } /** * Recursively removes any undefined, null, or empty string values from the property list. */ function cleanPropertyList(plist) { if (typeof(plist) !== "object") return; for (var key in plist) { if (plist[key] === undefined || plist[key] === null || plist[key] === "") delete plist[key]; else cleanPropertyList(plist[key]); } } function _codeSignTimestampFlags(product) { // If signingTimestamp is undefined, do not specify the flag at all - // this uses the system-specific default behavior var signingTimestamp = product.moduleProperty("xcode", "signingTimestamp"); if (signingTimestamp !== undefined) { // If signingTimestamp is an empty string, specify the flag but do // not specify a value - this uses a default Apple-provided server var flag = "--timestamp"; if (signingTimestamp) flag += "=" + signingTimestamp; return [flag]; } return []; } qbs-src-1.13.1/share/qbs/imports/qbs/ModUtils/000077500000000000000000000000001347155106100210635ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/imports/qbs/ModUtils/utils.js000066400000000000000000000566161347155106100225770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); var TemporaryDir = require("qbs.TemporaryDir"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function mergeCFiles(inputs, outputFilePath) { var f = new TextFile(outputFilePath, TextFile.WriteOnly); try { for (var i = 0; i < inputs.length; ++i) f.writeLine('#include ' + Utilities.cStringQuote(inputs[i].filePath)); } finally { f.close(); } } function sanitizedList(list, product, fullPropertyName) { if (!Array.isArray(list)) return list; var filterFunc = function(elem) { if (typeof elem === "string" && elem.length === 0) { var msg = "Removing empty string from value of property '" + fullPropertyName + "'"; // product might actually be a module if (product.name) msg += " in product '" + product.name + "'."; console.warn(msg); return false; } return true; } return list.filter(filterFunc); } function checkCompatibilityMode(project, minimumQbsVersion, message) { if (Utilities.versionCompare(project.minimumQbsVersion || "1.3", minimumQbsVersion) < 0) { console.warn([message || "", "This message can be silenced by setting your Project's " + "minimumQbsVersion to " + minimumQbsVersion + " (and the new behavior will take effect)."].join(" ")); return true; } return false; } function artifactInstalledFilePath(artifact) { var relativeInstallDir = artifact.moduleProperty("qbs", "installDir"); var installPrefix = artifact.moduleProperty("qbs", "installPrefix"); var installSourceBase = artifact.moduleProperty("qbs", "installSourceBase"); var targetDir = FileInfo.joinPaths(artifact.moduleProperty("qbs", "installRoot"), installPrefix, relativeInstallDir); if (installSourceBase) { if (!FileInfo.isAbsolutePath(installSourceBase)) throw "installSourceBase is not an absolute path"; if (!artifact.filePath.startsWith(installSourceBase)) throw "artifact file path doesn't start with the value of qbs.installSourceBase"; return FileInfo.joinPaths(targetDir, artifact.filePath.substr(installSourceBase.length + 1)); } return FileInfo.joinPaths(targetDir, artifact.fileName); } /** * Given a list of file tags, returns the file tag (one of [c, cpp, objc, objcpp]) * corresponding to the C-family language the file should be compiled as. * * If no such tag is found, undefined is returned. If more than one match is * found, an exception is thrown. */ function fileTagForTargetLanguage(fileTags) { var srcTags = ["c", "cpp", "objc", "objcpp", "asm", "asm_cpp"]; var pchTags = ["c_pch", "cpp_pch", "objc_pch", "objcpp_pch"]; var canonicalTag = undefined; var foundTagCount = 0; for (var i = 0; i < fileTags.length; ++i) { var idx = srcTags.indexOf(fileTags[i]); if (idx === -1) idx = pchTags.indexOf(fileTags[i]); if (idx !== -1) { canonicalTag = srcTags[idx]; if (++foundTagCount > 1) break; } } if (foundTagCount > 1) throw ("source files cannot be identified as more than one language"); return foundTagCount == 1 ? canonicalTag : undefined; } /** * Returns the name of a language-specific property given the file tag * for that property, and the base property name. * * If \a fileTag is undefined, the language-agnostic property name is returned. */ function languagePropertyName(propertyName, fileTag) { if (!fileTag) fileTag = "common"; var asm = { "flags": "assemblerFlags", "platformFlags": "platformAssemblerFlags" }; var map = { "c": { "flags": "cFlags", "platformFlags": "platformCFlags", "usePrecompiledHeader": "useCPrecompiledHeader" }, "cpp": { "flags": "cxxFlags", "platformFlags": "platformCxxFlags", "usePrecompiledHeader": "useCxxPrecompiledHeader" }, "objc": { "flags": "objcFlags", "platformFlags": "platformObjcFlags", "usePrecompiledHeader": "useObjcPrecompiledHeader" }, "objcpp": { "flags": "objcxxFlags", "platformFlags": "platformObjcxxFlags", "usePrecompiledHeader": "useObjcxxPrecompiledHeader" }, "common": { "flags": "commonCompilerFlags", "platformFlags": "platformCommonCompilerFlags" }, "asm": asm, "asm_cpp": asm }; var lang = map[fileTag]; if (!lang) return propertyName; return lang[propertyName] || propertyName; } function modulePropertiesFromArtifacts(product, artifacts, moduleName, propertyName, langFilter) { var result = product.moduleProperty( moduleName, languagePropertyName(propertyName, langFilter)) || []; for (var i in artifacts) { var artifactProp = artifacts[i].moduleProperty( moduleName, languagePropertyName(propertyName, langFilter)); if (artifactProp) result = result.concat(artifactProp); } return sanitizedList(result, product, moduleName + "." + propertyName); } function moduleProperty(product, propertyName, langFilter) { return sanitizedModuleProperty(product, product.moduleName, propertyName, langFilter); } function sanitizedModuleProperty(obj, moduleName, propertyName, langFilter) { return sanitizedList(obj.moduleProperty(moduleName, languagePropertyName(propertyName, langFilter)), obj, moduleName + "." + propertyName); } /** * Returns roughly the same value as moduleProperty for a product, but ensures that all of the * given input artifacts share the same value of said property, as a sort of sanity check. * * This allows us to verify that users do not, for example, try to set different values on input * artifacts for which the value is input specific (not product specific), but which must be the * same for all inputs. */ function modulePropertyFromArtifacts(product, artifacts, moduleName, propertyName, langFilter) { var values = [product.moduleProperty(moduleName, languagePropertyName(propertyName, langFilter))]; for (var i in artifacts) { var value = artifacts[i].moduleProperty(moduleName, languagePropertyName(propertyName, langFilter)); if (!values.contains(value)) { values.push(value); } } if (values.length !== 1) { throw "The value of " + [moduleName, propertyName].join(".") + " must be identical for the following input artifacts: " + artifacts.map(function (artifact) { return artifact.filePath; }); } return values[0]; } function concatAll() { var result = []; for (var i = 0; i < arguments.length; ++i) { var arg = arguments[i]; if (arg === undefined) continue; else if (arg instanceof Array) result = result.concat(arg); else result.push(arg); } return result; } function allFileTags(fileTaggers) { var tags = []; for (var ext in fileTaggers) tags = tags.uniqueConcat(fileTaggers[ext]); return tags; } /** * Flattens a dictionary (string keys to strings) * into a string list containing items like \c key=value1 */ function flattenDictionary(dict, separator) { separator = separator || "="; var list = []; for (var i in dict) { var value = i; if (dict[i] !== undefined) // allow differentiation between undefined and empty string value += separator + dict[i]; list.push(value); } return list; } function ModuleError(message) { var e = new Error(message); e.fileName = ""; return e; } var EnvironmentVariable = (function () { function EnvironmentVariable(name, separator, convertPathSeparators) { if (!name) throw "EnvironmentVariable c'tor needs a name as first argument."; this.name = name; this.value = Environment.getEnv(name) || ""; this.separator = separator || ""; this.convertPathSeparators = convertPathSeparators || false; } EnvironmentVariable.prototype.prepend = function (v) { if (this.value.length > 0 && this.value.charAt(0) !== this.separator) this.value = this.separator + this.value; if (this.convertPathSeparators) v = FileInfo.toWindowsSeparators(v); this.value = v + this.value; }; EnvironmentVariable.prototype.append = function (v) { if (this.value.length > 0) this.value += this.separator; if (this.convertPathSeparators) v = FileInfo.toWindowsSeparators(v); this.value += v; }; EnvironmentVariable.prototype.set = function () { Environment.putEnv(this.name, this.value); }; EnvironmentVariable.prototype.unset = function () { Environment.unsetEnv(this.name); }; return EnvironmentVariable; })(); var PropertyValidator = (function () { function PropertyValidator(moduleName) { this.requiredProperties = {}; this.propertyValidators = []; if (!moduleName) throw "PropertyValidator c'tor needs a module name as a first argument."; this.moduleName = moduleName; } PropertyValidator.prototype.setRequiredProperty = function (propertyName, propertyValue, message) { this.requiredProperties[propertyName] = { propertyValue: propertyValue, message: message }; }; PropertyValidator.prototype.addRangeValidator = function (propertyName, propertyValue, min, max, allowFloats) { var message = []; if (min !== undefined) message.push(">= " + min); if (max !== undefined) message.push("<= " + max); this.addCustomValidator(propertyName, propertyValue, function (value) { if (typeof value !== "number") return false; if (!allowFloats && value % 1 !== 0) return false; if (min !== undefined && value < min) return false; if (max !== undefined && value > max) return false; return true; }, "must be " + (!allowFloats ? "an integer " : "") + message.join(" and ")); }; PropertyValidator.prototype.addVersionValidator = function (propertyName, propertyValue, minComponents, maxComponents, allowSuffixes) { if (minComponents !== undefined && (typeof minComponents !== "number" || minComponents % 1 !== 0 || minComponents < 1)) throw "minComponents must be at least 1"; if (maxComponents !== undefined && (typeof maxComponents !== "number" || maxComponents % 1 !== 0 || maxComponents < minComponents)) throw "maxComponents must be >= minComponents"; this.addCustomValidator(propertyName, propertyValue, function (value) { if (typeof value !== "string") return false; return value && value.match("^[0-9]+(\\.[0-9]+){" + ((minComponents - 1) || 0) + "," + ((maxComponents - 1) || "") + "}" + (!allowSuffixes ? "$" : "")) !== null; }, "must be a version number with " + (minComponents === maxComponents ? minComponents : (minComponents + " to " + maxComponents)) + (minComponents === maxComponents && minComponents === 1 ? " component" : " components")); }; PropertyValidator.prototype.addFileNameValidator = function (propertyName, propertyValue) { this.addCustomValidator(propertyName, propertyValue, function (value) { return !/[/?<>\\:*|"\u0000-\u001f\u0080-\u009f]/.test(propertyValue) && propertyValue !== "." && propertyValue !== ".."; }, "cannot contain reserved or control characters and cannot be \".\" or \"..\""); }; PropertyValidator.prototype.addCustomValidator = function (propertyName, propertyValue, validator, message) { this.propertyValidators.push({ propertyName: propertyName, propertyValue: propertyValue, validator: validator, message: message }); }; PropertyValidator.prototype.validate = function (throwOnError) { var i; var lines; // Find any missing properties var missingProperties = {}; for (i in this.requiredProperties) { var propValue = this.requiredProperties[i].propertyValue; if (propValue === undefined || propValue === null || propValue === "") { missingProperties[i] = this.requiredProperties[i]; } } // Find any properties that don't satisfy their validator function var invalidProperties = {}; for (var j = 0; j < this.propertyValidators.length; ++j) { var v = this.propertyValidators[j]; if (!v.validator(v.propertyValue)) { var messages = invalidProperties[v.propertyName] || []; messages.push(v.message); invalidProperties[v.propertyName] = messages; } } var errorMessage = ""; if (Object.keys(missingProperties).length > 0) { errorMessage += "The following properties are not set. Set them in your profile or product:\n"; lines = []; for (i in missingProperties) { var obj = missingProperties[i]; lines.push(this.moduleName + "." + i + ((obj && obj.message) ? (": " + obj.message) : "")); } errorMessage += lines.join("\n"); } if (Object.keys(invalidProperties).length > 0) { if (errorMessage) errorMessage += "\n"; errorMessage += "The following properties have invalid values:\n"; lines = []; for (i in invalidProperties) { for (j in invalidProperties[i]) { lines.push(this.moduleName + "." + i + ": " + invalidProperties[i][j]); } } errorMessage += lines.join("\n"); } if (throwOnError !== false && errorMessage.length > 0) throw errorMessage; return errorMessage.length == 0; }; return PropertyValidator; })(); var BlackboxOutputArtifactTracker = (function () { function BlackboxOutputArtifactTracker() { } BlackboxOutputArtifactTracker.prototype.artifacts = function (outputDirectory) { var process; var fakeOutputDirectory; try { fakeOutputDirectory = new TemporaryDir(); if (!fakeOutputDirectory.isValid()) throw "could not create temporary directory"; process = new Process(); if (this.commandEnvironmentFunction) { var env = this.commandEnvironmentFunction(fakeOutputDirectory.path()); for (var key in env) process.setEnv(key, env[key]); } process.exec(this.command, this.commandArgsFunction(fakeOutputDirectory.path()), true); var artifacts = []; if (this.fileTaggers) { var files = this.findFiles(fakeOutputDirectory.path()); for (var i = 0; i < files.length; ++i) artifacts.push(this.createArtifact(fakeOutputDirectory.path(), files[i])); } if (this.processStdOutFunction) artifacts = artifacts.concat(this.processStdOutFunction(process.readStdOut())); artifacts = this.fixArtifactPaths(artifacts, outputDirectory, fakeOutputDirectory.path()); return artifacts; } finally { if (process) process.close(); if (fakeOutputDirectory) fakeOutputDirectory.remove(); } }; BlackboxOutputArtifactTracker.prototype.createArtifact = function (root, filePath) { for (var ext in this.fileTaggers) { if (filePath.endsWith(ext)) { return { filePath: filePath, fileTags: this.fileTaggers[ext] }; } } if (!this.defaultFileTags) { var relFilePath = (filePath.startsWith(root + '/') || filePath.startsWith(root + '\\')) ? filePath.substring(root.length + 1) : filePath; throw "BlackboxOutputArtifactTracker: no matching file taggers for path '" + relFilePath + "'. Set defaultFileTags to an array of file tags to " + "apply to files not tagged by the fileTaggers map, which was:\n" + JSON.stringify(this.fileTaggers, undefined, 4); } return { filePath: filePath, fileTags: this.defaultFileTags }; }; BlackboxOutputArtifactTracker.prototype.findFiles = function (dir) { var fileList = File.directoryEntries(dir, File.Files).map(function (p) { return FileInfo.joinPaths(dir, p); }); var dirList = File.directoryEntries(dir, File.Dirs | File.NoDotAndDotDot).map(function (p) { return FileInfo.joinPaths(dir, p); }); for (var i = 0; i < dirList.length; ++i) fileList = fileList.concat(this.findFiles(dirList[i])); return fileList; }; BlackboxOutputArtifactTracker.prototype.fixArtifactPaths = function (artifacts, realBasePath, fakeBasePath) { for (var i = 0; i < artifacts.length; ++i) artifacts[i].filePath = realBasePath + artifacts[i].filePath.substr(fakeBasePath.length); return artifacts; }; return BlackboxOutputArtifactTracker; })(); function hasAnyOf(m, tokens) { for (var i = 0; i < tokens.length; ++i) { if (m[tokens[i]] !== undefined) return true; } } function guessArchitecture(m) { var architecture; if (m) { // based on the search algorithm from qprocessordetection.h in qtbase var arm64Defs = ["_M_ARM64", "__aarch64__", "__ARM64__"]; if (hasAnyOf(m, ["__arm__", "__TARGET_ARCH_ARM", "_M_ARM"].concat(arm64Defs))) { if (hasAnyOf(m, arm64Defs)) { architecture = "arm64"; } else { architecture = "arm"; var foundSubarch = false; for (var i = 8; i >= 4; --i) { var codes = ["zk", "tej", "te", "t2"].concat([].concat.apply([], new Array(26)).map(function(_, i) { return String.fromCharCode(122 - i); })); for (var j = 0; j < codes.length; ++j) { if (m["__ARM_ARCH_" + i + codes[j].toUpperCase() + "__"] !== undefined) { architecture += "v" + i + codes[j].toLowerCase(); foundSubarch = true; break; } } if (i === 7 && m["_ARM_ARCH_7"] !== undefined) { architecture += "v7"; foundSubarch = true; } if (foundSubarch) break; } } } else if (hasAnyOf(m, ["__i386", "__i386__", "_M_IX86"])) { architecture = "x86"; } else if (hasAnyOf(m, ["__x86_64", "__x86_64__", "__amd64", "_M_X64", "_M_AMD64"])) { architecture = "x86_64"; if (hasAnyOf(m, ["__x86_64h", "__x86_64h__"])) architecture = "x86_64h"; } else if (hasAnyOf(m, ["__ia64", "__ia64__", "_M_IA64"])) { architecture = "ia64"; } else if (hasAnyOf(m, ["__mips", "__mips__", "_M_MRX000"])) { architecture = "mips"; if (hasAnyOf(m, ["_MIPS_ARCH_MIPS64", "__mips64"])) architecture += "64"; } else if (hasAnyOf(m, ["__ppc__", "__ppc", "__powerpc__", "_ARCH_COM", "_ARCH_PWR", "_ARCH_PPC", "_M_MPPC", "_M_PPC"])) { architecture = "ppc"; if (hasAnyOf(m, ["__ppc64__", "__powerpc64__", "__64BIT__"])) architecture += "64"; } else if (hasAnyOf(m, ["__s390__"])) { if (hasAnyOf(m, ["__s390x__"])) architecture = "s390x"; } else if (hasAnyOf(m, ["__sparc__"])) { architecture = "sparc"; if (hasAnyOf(m, ["__sparc64__"])) architecture += "64"; } else if (hasAnyOf(m, ["__AVR__"])) { architecture = "avr"; } else if (hasAnyOf(m, ["__AVR32__"])) { architecture = "avr32"; } } return Utilities.canonicalArchitecture(architecture); } function guessTargetPlatform(m) { if (m) { if (hasAnyOf(m, ["__ANDROID__", "ANDROID"])) return "android"; if (hasAnyOf(m, ["__QNXNTO__"])) return "qnx"; if (hasAnyOf(m, ["__INTEGRITY"])) return "integrity"; if (hasAnyOf(m, ["__vxworks"])) return "vxworks"; if (hasAnyOf(m, ["__APPLE__"])) return "darwin"; if (hasAnyOf(m, ["WIN32", "_WIN32", "__WIN32__", "__NT__"])) return "windows"; if (hasAnyOf(m, ["_AIX"])) return "aix"; if (hasAnyOf(m, ["hpux", "__hpux"])) return "hpux"; if (hasAnyOf(m, ["__sun", "sun"])) return "solaris"; if (hasAnyOf(m, ["__linux__", "__linux"])) return "linux"; if (hasAnyOf(m, ["__FreeBSD__", "__DragonFly__", "__FreeBSD_kernel__"])) return "freebsd"; if (hasAnyOf(m, ["__NetBSD__"])) return "netbsd"; if (hasAnyOf(m, ["__OpenBSD__"])) return "openbsd"; if (hasAnyOf(m, ["__GNU__"])) return "hurd"; if (hasAnyOf(m, ["__HAIKU__"])) return "haiku"; } } qbs-src-1.13.1/share/qbs/imports/qbs/PathTools/000077500000000000000000000000001347155106100212405ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/imports/qbs/PathTools/path-tools.js000066400000000000000000000227261347155106100237010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); function _bundleExecutableTemporaryFilePath(product, variantSuffix) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; return ".tmp/" + FileInfo.fileName(bundleExecutableFilePath(product, variantSuffix)); } function bundleExecutableFilePath(product, variantSuffix) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; return product.moduleProperty("bundle", "executablePath") + (variantSuffix || ""); } function applicationFilePath(product, variantSuffix) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; if (product.moduleProperty("bundle", "isBundle")) return _bundleExecutableTemporaryFilePath(product, variantSuffix); return product.moduleProperty("cpp", "executablePrefix") + product.targetName + (variantSuffix || "") + product.moduleProperty("cpp", "executableSuffix"); } function loadableModuleFilePath(product, variantSuffix) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; if (product.moduleProperty("bundle", "isBundle")) return _bundleExecutableTemporaryFilePath(product, variantSuffix); return product.moduleProperty("cpp", "loadableModulePrefix") + product.targetName + (variantSuffix || "") + product.moduleProperty("cpp", "loadableModuleSuffix"); } function staticLibraryFilePath(product, variantSuffix) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; if (product.moduleProperty("bundle", "isBundle")) return _bundleExecutableTemporaryFilePath(product, variantSuffix); return product.moduleProperty("cpp", "staticLibraryPrefix") + product.targetName + (variantSuffix || "") + product.moduleProperty("cpp", "staticLibrarySuffix"); } function dynamicLibraryFilePath(product, variantSuffix, version, maxParts) { if (variantSuffix === undefined) variantSuffix = product.cpp.variantSuffix; if (product.moduleProperty("bundle", "isBundle")) return _bundleExecutableTemporaryFilePath(product, variantSuffix); // If no override version was given, use the product's version // We specifically want to differentiate between undefined and i.e. // empty string as empty string should be taken to mean "no version" // and undefined should be taken to mean "use the product's version" // (which could still end up being "no version") if (version === undefined) version = product.moduleProperty("cpp", "internalVersion"); // If we have a version number, potentially strip off some components if (maxParts === 0) version = undefined; else if (maxParts && version) version = version.split('.').slice(0, maxParts).join('.'); // Start with prefix + name (i.e. libqbs, qbs) var fileName = product.moduleProperty("cpp", "dynamicLibraryPrefix") + product.targetName + (variantSuffix || ""); // For Mach-O images, append the version number if there is one (i.e. libqbs.1.0.0) var imageFormat = product.moduleProperty("cpp", "imageFormat"); if (version && imageFormat === "macho") { fileName += "." + version; version = undefined; } // Append the suffix (i.e. libqbs.1.0.0.dylib, libqbs.so, qbs.dll) fileName += product.moduleProperty("cpp", "dynamicLibrarySuffix"); // For ELF images, append the version number if there is one (i.e. libqbs.so.1.0.0) if (version && imageFormat === "elf") fileName += "." + version; return fileName; } function linkerOutputFilePath(fileTag, product, variantSuffix, version, maxParts) { switch (fileTag) { case "application": return applicationFilePath(product, variantSuffix); case "loadablemodule": return loadableModuleFilePath(product, variantSuffix); case "staticlibrary": return staticLibraryFilePath(product, variantSuffix); case "dynamiclibrary": return dynamicLibraryFilePath(product, variantSuffix, version, maxParts); default: throw new Error("Unknown linker output file tag: " + fileTag); } } function importLibraryFilePath(product) { return product.moduleProperty("cpp", "dynamicLibraryPrefix") + product.targetName + (product.cpp.variantSuffix || "") + product.moduleProperty("cpp", "dynamicLibraryImportSuffix"); } function debugInfoIsBundle(product) { if (!product.moduleProperty("qbs", "targetOS").contains("darwin")) return false; var flags = product.moduleProperty("cpp", "dsymutilFlags") || []; return !flags.contains("-f") && !flags.contains("--flat"); } function debugInfoFileName(product, variantSuffix, fileTag) { var suffix = ""; // For dSYM bundles, the DWARF debug info file has no suffix if (!product.moduleProperty("qbs", "targetOS").contains("darwin") || !debugInfoIsBundle(product)) suffix = product.moduleProperty("cpp", "debugInfoSuffix"); if (product.moduleProperty("bundle", "isBundle")) { return FileInfo.fileName(bundleExecutableFilePath(product, variantSuffix)) + suffix; } else { switch (fileTag) { case "application": return applicationFilePath(product, variantSuffix) + suffix; case "dynamiclibrary": return dynamicLibraryFilePath(product, variantSuffix) + suffix; case "loadablemodule": return loadableModuleFilePath(product, variantSuffix) + suffix; case "staticlibrary": return staticLibraryFilePath(product, variantSuffix) + suffix; default: return product.targetName + (variantSuffix || "") + suffix; } } } function debugInfoBundlePath(product, fileTag) { if (!debugInfoIsBundle(product)) return undefined; var suffix = product.moduleProperty("cpp", "debugInfoBundleSuffix"); if (product.moduleProperty("qbs", "targetOS").contains("darwin") && product.moduleProperty("bundle", "isBundle")) return product.moduleProperty("bundle", "bundleName") + suffix; return debugInfoFileName(product, undefined, fileTag) + suffix; } function debugInfoFilePath(product, variantSuffix, fileTag) { var name = debugInfoFileName(product, variantSuffix, fileTag); if (product.moduleProperty("qbs", "targetOS").contains("darwin") && debugInfoIsBundle(product)) { return FileInfo.joinPaths(debugInfoBundlePath(product, fileTag), "Contents", "Resources", "DWARF", name); } else if (product.moduleProperty("bundle", "isBundle")) { return FileInfo.joinPaths(product.moduleProperty("bundle", "executableFolderPath"), name); } return name; } function debugInfoPlistFilePath(product, fileTag) { if (!debugInfoIsBundle(product)) return undefined; return FileInfo.joinPaths(debugInfoBundlePath(product, fileTag), "Contents", "Info.plist"); } // Returns whether the string looks like a library filename function isLibraryFileName(product, fileName, prefix, suffixes, isShared) { var suffix, i; var os = product.moduleProperty("qbs", "targetOS"); for (i = 0; i < suffixes.length; ++i) { suffix = suffixes[i]; if (isShared && os.contains("unix") && !os.contains("darwin")) suffix += "(\\.[0-9]+){0,3}"; if (fileName.match("^" + prefix + ".+?\\" + suffix + "$")) return true; } return false; } function frameworkExecutablePath(frameworkPath) { var suffix = ".framework"; var isAbsoluteFrameworkPath = frameworkPath.slice(-suffix.length) === suffix; if (isAbsoluteFrameworkPath) { var frameworkName = FileInfo.fileName(frameworkPath).slice(0, -suffix.length); return FileInfo.joinPaths(frameworkPath, frameworkName); } return undefined; } // pathList is also a string, using the respective separator function prependOrSetPath(path, pathList, separator) { if (!pathList || pathList.length === 0) return path; return path + separator + pathList; } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/000077500000000000000000000000001347155106100205555ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs000066400000000000000000000136021347155106100242730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.TextFile import "../../../modules/Android/android-utils.js" as AndroidUtils PathProbe { // Inputs property stringList hostOS: qbs.hostOS property path sdkPath environmentPaths: Environment.getEnv("ANDROID_NDK_ROOT") platformSearchPaths: { var paths = []; if (sdkPath) paths.push(FileInfo.joinPaths(sdkPath, "ndk-bundle")); if (qbs.hostOS.contains("windows")) paths.push(FileInfo.joinPaths(Environment.getEnv("LOCALAPPDATA"), "Android", "sdk", "ndk-bundle")); if (qbs.hostOS.contains("macos")) paths.push(FileInfo.joinPaths(Environment.getEnv("HOME"), "Library", "Android", "sdk", "ndk-bundle")); if (qbs.hostOS.contains("linux")) paths.push(FileInfo.joinPaths(Environment.getEnv("HOME"), "Android", "Sdk", "ndk-bundle")); return paths; } // Outputs property stringList candidatePaths property string samplesDir property var hostArch property stringList toolchains: [] property string ndkVersion property string ndkPlatform configure: { function readFileContent(filePath) { var result = null; if (!File.exists(filePath)) return result; try { var tf = new TextFile(filePath, TextFile.ReadOnly); result = tf.readAll(); } finally { if (tf) tf.close(); } return result; } var i, j, allPaths = (environmentPaths || []).concat(platformSearchPaths || []); candidatePaths = allPaths; for (i in allPaths) { var platforms = []; if (hostOS.contains("windows")) platforms.push("windows-x86_64", "windows"); if (hostOS.contains("darwin")) platforms.push("darwin-x86_64", "darwin-x86"); if (hostOS.contains("linux")) platforms.push("linux-x86_64", "linux-x86"); for (j in platforms) { if (File.exists(FileInfo.joinPaths(allPaths[i], "prebuilt", platforms[j]))) { path = allPaths[i]; var ndkPlatforms = AndroidUtils.availablePlatforms(path); if (ndkPlatforms.length > 0) ndkPlatform = ndkPlatforms[ndkPlatforms.length - 1]; if (File.exists(FileInfo.joinPaths(path, "samples"))) samplesDir = FileInfo.joinPaths(path, "samples"); // removed in r11 hostArch = platforms[j]; toolchains = File.directoryEntries(FileInfo.joinPaths(path, "toolchains"), File.Dirs | File.NoDotAndDotDot); // NDK r11 and above var content = readFileContent(path + "/source.properties"); if (content) { var lines = content.trim().split(/\r?\n/g).filter(function (line) { return line.length > 0; }); for (var l = 0; l < lines.length; ++l) { var m = lines[l].match(/^Pkg\.Revision\s*=\s*([0-9\.]+)$/); if (m) { ndkVersion = m[1]; found = true; return; } } } // NDK r10 and below var releaseTextFileCandidates = ["RELEASE.txt", "RELEASE.TXT"] .map(function(v) { return FileInfo.joinPaths(path, v); }) .filter(File.exists); content = releaseTextFileCandidates.length ? readFileContent(releaseTextFileCandidates[0]) : null; if (content) { var m = content.trim().match(/^r([0-9]+[a-z]?).*/); if (m) { ndkVersion = m[1]; found = true; return; } } } } } } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs000066400000000000000000000062701347155106100243030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import "../../../modules/Android/sdk/utils.js" as SdkUtils import "../../../modules/Android/android-utils.js" as AndroidUtils BinaryProbe { environmentPaths: Environment.getEnv("ANDROID_HOME") platformSearchPaths: { if (qbs.hostOS.contains("windows")) return [FileInfo.joinPaths(Environment.getEnv("LOCALAPPDATA"), "Android", "sdk")]; if (qbs.hostOS.contains("macos")) return [FileInfo.joinPaths(Environment.getEnv("HOME"), "Library", "Android", "sdk")]; if (qbs.hostOS.contains("linux")) return [FileInfo.joinPaths(Environment.getEnv("HOME"), "Android", "Sdk")]; } // Outputs property stringList candidatePaths property var buildToolsVersions property string buildToolsVersion property var platforms property string platform configure: { var suffixes = nameSuffixes || [""]; var i, allPaths = (environmentPaths || []).concat(platformSearchPaths || []); candidatePaths = allPaths; for (i in allPaths) { for (var j in suffixes) { if (File.exists(FileInfo.joinPaths(allPaths[i], "tools", "android" + suffixes[j]))) { path = allPaths[i]; buildToolsVersions = SdkUtils.availableBuildToolsVersions(path) buildToolsVersion = buildToolsVersions[buildToolsVersions.length - 1]; platforms = AndroidUtils.availablePlatforms(path) platform = platforms[platforms.length - 1]; found = true; return; } } } } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/BinaryProbe.qbs000066400000000000000000000033251347155106100235030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ PathProbe { nameSuffixes: qbs.hostOS.contains("windows") ? [".com", ".exe", ".bat", ".cmd"] : undefined platformSearchPaths: hostOS.contains("unix") ? ["/usr/bin", "/usr/local/bin"] : [] platformEnvironmentPaths: [ "PATH" ] } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/FrameworkProbe.qbs000066400000000000000000000035351347155106100242170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ PathProbe { platformSearchPaths: (qbs.sysroot ? [qbs.sysroot + "/System/Library/Frameworks"] : []).concat([ "~/Library/Frameworks", "/usr/local/lib", "/Library/Frameworks", "/System/Library/Frameworks" ]) nameFilter: { return function(name) { return name + ".framework"; } } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/GccBinaryProbe.qbs000066400000000000000000000044231347155106100241200ustar00rootroot00000000000000import qbs.Environment import qbs.FileInfo import "path-probe.js" as PathProbeConfigure BinaryProbe { // Inputs property string _compilerName property string _toolchainPrefix // Outputs property string tcPrefix platformSearchPaths: { var paths = base; if (qbs.targetOS.contains("windows") && qbs.hostOS.contains("windows")) paths.push(FileInfo.joinPaths( Environment.getEnv("SystemDrive"), "MinGW", "bin")); return paths; } names: { var prefixes = []; if (_toolchainPrefix) { prefixes.push(_toolchainPrefix); } else { var arch = qbs.architecture; if (qbs.targetOS.contains("windows")) { if (!arch || arch === "x86") { prefixes.push("mingw32-", "i686-w64-mingw32-", "i686-w64-mingw32.shared-", "i686-w64-mingw32.static-", "i686-mingw32-", "i586-mingw32msvc-"); } if (!arch || arch === "x86_64") { prefixes.push("x86_64-w64-mingw32-", "x86_64-w64-mingw32.shared-", "x86_64-w64-mingw32.static-", "amd64-mingw32msvc-"); } } } return prefixes.map(function(prefix) { return prefix + _compilerName; }).concat([_compilerName]); } configure: { var result = PathProbeConfigure.configure(names, nameSuffixes, nameFilter, searchPaths, pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths, pathListSeparator); found = result.found; candidatePaths = result.candidatePaths; path = result.path; filePath = result.filePath; fileName = result.fileName; (nameSuffixes || [""]).forEach(function(suffix) { var end = _compilerName + suffix; if (fileName.endsWith(end)) tcPrefix = fileName.slice(0, -end.length); }); } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/GccProbe.qbs000066400000000000000000000112611347155106100227510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.ModUtils import "../../../modules/cpp/gcc.js" as Gcc PathProbe { // Inputs property var compilerFilePathByLanguage property stringList enableDefinesByLanguage property stringList flags: [] property var environment property string _nullDevice: qbs.nullDevice property string _pathListSeparator: qbs.pathListSeparator property string _sysroot: qbs.sysroot property stringList _targetOS: qbs.targetOS // Outputs property string architecture property string endianness property string targetPlatform property stringList includePaths property stringList libraryPaths property stringList frameworkPaths property var compilerDefinesByLanguage configure: { compilerDefinesByLanguage = {}; var languages = enableDefinesByLanguage; if (!languages || languages.length === 0) languages = ["c"]; for (var i = 0; i < languages.length; ++i) { var fp = compilerFilePathByLanguage[languages[i]]; if (fp && File.exists(fp)) { try { compilerDefinesByLanguage[languages[i]] = Gcc.dumpMacros(environment, fp, flags, _nullDevice, languages[i]); } catch (e) { // Only throw errors when determining the compiler defines for the C language; // for other languages we presume it is an indication that the language is not // installed (as is typically the case for Objective-C/C++ on non-Apple systems) if (languages[i] === "c") throw e; } } else if (languages[i] === "c") { found = false; return; } } var macros = compilerDefinesByLanguage["c"] || compilerDefinesByLanguage["cpp"] || compilerDefinesByLanguage["objc"] || compilerDefinesByLanguage["objcpp"]; var defaultPaths = Gcc.dumpDefaultPaths(environment, compilerFilePathByLanguage["cpp"] || compilerFilePathByLanguage["c"], flags, _nullDevice, _pathListSeparator, _sysroot, _targetOS); found = !!macros && !!defaultPaths; includePaths = defaultPaths.includePaths; libraryPaths = defaultPaths.libraryPaths; frameworkPaths = defaultPaths.frameworkPaths; // We have to dump the compiler's macros; -dumpmachine is not suitable because it is not // always complete (for example, the subarch is not included for arm architectures). architecture = ModUtils.guessArchitecture(macros); targetPlatform = ModUtils.guessTargetPlatform(macros); switch (macros["__BYTE_ORDER__"]) { case "__ORDER_BIG_ENDIAN__": endianness = "big"; break; case "__ORDER_LITTLE_ENDIAN__": endianness = "little"; break; } } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/GccVersionProbe.qbs000066400000000000000000000051001347155106100243120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import "../../../modules/cpp/gcc.js" as Gcc PathProbe { // Inputs property string compilerFilePath property var environment property string _nullDevice: qbs.nullDevice property stringList _toolchain: qbs.toolchain // Outputs property int versionMajor property int versionMinor property int versionPatch configure: { if (!File.exists(compilerFilePath)) { found = false; return; } var macros = Gcc.dumpMacros(environment, compilerFilePath, undefined, _nullDevice); if (_toolchain.contains("clang")) { versionMajor = parseInt(macros["__clang_major__"], 10); versionMinor = parseInt(macros["__clang_minor__"], 10); versionPatch = parseInt(macros["__clang_patchlevel__"], 10); found = true; } else { versionMajor = parseInt(macros["__GNUC__"], 10); versionMinor = parseInt(macros["__GNUC_MINOR__"], 10); versionPatch = parseInt(macros["__GNUC_PATCHLEVEL__"], 10); found = true; } } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/IarProbe.qbs000066400000000000000000000054771347155106100230040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import "../../../modules/cpp/iar.js" as IAR PathProbe { // Inputs property string compilerFilePath; property string _nullDevice: qbs.nullDevice // Outputs property string architecture; property string endianness; property int versionMajor; property int versionMinor; property int versionPatch; configure: { if (!File.exists(compilerFilePath)) { found = false; return; } var macros = IAR.dumpMacros(compilerFilePath, qbs, _nullDevice); architecture = IAR.guessArchitecture(macros); endianness = IAR.guessEndianness(macros); var version = parseInt(macros["__VER__"], 10); if (architecture === "arm") { versionMajor = parseInt(version / 1000000); versionMinor = parseInt(version / 1000) % 1000; versionPatch = parseInt(version) % 1000; } else if (architecture === "mcs51") { versionMajor = parseInt(version / 100); versionMinor = parseInt(version % 100); versionPatch = 0; } else if (architecture === "avr") { versionMajor = parseInt(version / 100); versionMinor = parseInt(version % 100); versionPatch = 0; } found = version && architecture && endianness; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/IcoUtilsVersionProbe.qbs000066400000000000000000000033541347155106100253620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import "../../../modules/ico/ico.js" as IcoUtils Probe { // Inputs property string toolFilePath // Outputs property var version configure: { version = IcoUtils.findIcoUtilsVersion(toolFilePath); found = !!version; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/IncludeProbe.qbs000066400000000000000000000032431347155106100236410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ PathProbe { pathSuffixes: [ "include" ] platformEnvironmentPaths: { if (qbs.toolchain.contains('msvc')) return [ "INCLUDE" ]; return undefined; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/InnoSetupProbe.qbs000066400000000000000000000042111347155106100241760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Utilities PathProbe { // Outputs property var version configure: { var keySuffix = "Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 5_is1"; var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\" + keySuffix, "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\" + keySuffix ]; for (var i in keys) { var v = Utilities.getNativeSetting(keys[i], "DisplayVersion"); if (v) { path = Utilities.getNativeSetting(keys[i], "InstallLocation"); version = v; found = path && version; return; } } } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/JdkProbe.qbs000066400000000000000000000044221347155106100227660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import "../../../modules/java/utils.js" as JavaUtils PathProbe { // Inputs property stringList hostOS: qbs.hostOS property string architecture: !_androidCrossCompiling ? qbs.architecture : undefined property bool _androidCrossCompiling: qbs.targetOS.contains("android") && !qbs.hostOS.contains("android") environmentPaths: Environment.getEnv("JAVA_HOME") platformSearchPaths: [ "/usr/lib/jvm/default-java", // Debian/Ubuntu "/etc/alternatives/java_sdk_openjdk", // Fedora "/usr/lib/jvm/default" // Arch ] configure: { path = JavaUtils.findJdkPath(hostOS, architecture, environmentPaths, platformSearchPaths); found = !!path; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/JdkVersionProbe.qbs000066400000000000000000000033361347155106100243370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import "../../../modules/java/utils.js" as JavaUtils Probe { // Inputs property string javac // Outputs property var version configure: { version = JavaUtils.findJdkVersion(javac); found = !!version; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/KeilProbe.qbs000066400000000000000000000046431347155106100231470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import "../../../modules/cpp/keil.js" as KEIL PathProbe { // Inputs property string compilerFilePath; property string _nullDevice: qbs.nullDevice // Outputs property string architecture; property string endianness; property int versionMajor; property int versionMinor; property int versionPatch; configure: { if (!File.exists(compilerFilePath)) { found = false; return; } var macros = KEIL.dumpMacros(compilerFilePath, qbs, _nullDevice); architecture = KEIL.guessArchitecture(macros); endianness = KEIL.guessEndianness(macros); var version = KEIL.guessVersion(macros); if (version) { versionMajor = version.major; versionMinor = version.minor; versionPatch = version.patch; } found = version.found && architecture && endianness; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/LibraryProbe.qbs000066400000000000000000000043471347155106100236700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ PathProbe { nameSuffixes: { if (qbs.targetOS.contains("windows")) return [".lib"]; if (qbs.targetOS.contains("macos")) return [".dylib", ".a"]; return [".so", ".a"]; } platformSearchPaths: qbs.targetOS.contains("unix") ? [ "/usr/lib", "/usr/local/lib", ] : [] nameFilter: { if (qbs.targetOS.contains("unix")) { return function(name) { return "lib" + name; } } else { return function(name) { return name; } } } platformEnvironmentPaths: { if (qbs.targetOS.contains("windows")) return [ "PATH" ]; else return [ "LIBRARY_PATH" ]; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/MsvcProbe.qbs000066400000000000000000000075341347155106100231750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Utilities PathProbe { // Inputs property string compilerFilePath property stringList enableDefinesByLanguage property string preferredArchitecture // Outputs property string architecture property int versionMajor property int versionMinor property int versionPatch property stringList includePaths property var buildEnv property var compilerDefinesByLanguage configure: { var languages = enableDefinesByLanguage; if (!languages || languages.length === 0) languages = ["c"]; var info = languages.contains("c") ? Utilities.msvcCompilerInfo(compilerFilePath, "c") : {}; var infoCpp = languages.contains("cpp") ? Utilities.msvcCompilerInfo(compilerFilePath, "cpp") : {}; found = (!languages.contains("c") || (!!info && !!info.macros && !!info.buildEnvironment)) && (!languages.contains("cpp") || (!!infoCpp && !!infoCpp.macros && !!infoCpp.buildEnvironment)); compilerDefinesByLanguage = { "c": info.macros, "cpp": infoCpp.macros, }; var macros = info.macros || infoCpp.macros; architecture = ModUtils.guessArchitecture(macros); var ver = macros["_MSC_FULL_VER"]; versionMajor = parseInt(ver.substr(0, 2), 10); versionMinor = parseInt(ver.substr(2, 2), 10); versionPatch = parseInt(ver.substr(4), 10); buildEnv = info.buildEnvironment || infoCpp.buildEnvironment; var clParentDir = FileInfo.joinPaths(FileInfo.path(compilerFilePath), ".."); var inclPath = FileInfo.joinPaths(clParentDir, "INCLUDE"); if (!File.exists(inclPath)) inclPath = FileInfo.joinPaths(clParentDir, "..", "INCLUDE"); if (!File.exists(inclPath)) inclPath = FileInfo.joinPaths(clParentDir, "..", "..", "INCLUDE"); if (File.exists(inclPath)) includePaths = [inclPath]; if (preferredArchitecture && Utilities.canonicalArchitecture(preferredArchitecture) !== Utilities.canonicalArchitecture(architecture)) { throw "'" + preferredArchitecture + "' differs from the architecture produced by this compiler (" + architecture + ")"; } } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/NodeJsProbe.qbs000066400000000000000000000041041347155106100234350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.FileInfo BinaryProbe { names: ["node", "nodejs"] platformSearchPaths: { var paths = base; if (qbs.hostOS.contains("windows")) { var env32 = Environment.getEnv("PROGRAMFILES(X86)"); var env64 = Environment.getEnv("PROGRAMFILES"); if (env64 === env32 && env64.endsWith(" (x86)")) env64 = env64.slice(0, -(" (x86)".length)); // QTBUG-3845 paths.push(FileInfo.joinPaths(env64, "nodejs")); paths.push(FileInfo.joinPaths(env32, "nodejs")); } return paths; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/NpmProbe.qbs000066400000000000000000000061321347155106100230100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.ModUtils import "path-probe.js" as PathProbeConfigure import "../../../modules/nodejs/nodejs.js" as NodeJs NodeJsProbe { names: ["npm"] // Inputs property string interpreterPath // Outputs property path npmBin property path npmRoot property path npmPrefix configure: { if (!interpreterPath) throw '"interpreterPath" must be specified'; var result = PathProbeConfigure.configure(names, nameSuffixes, nameFilter, searchPaths, pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths, pathListSeparator); var v = new ModUtils.EnvironmentVariable("PATH", pathListSeparator, hostOS.contains("windows")); v.prepend(interpreterPath); result.npmBin = result.found ? NodeJs.findLocation(result.filePath, "bin", v.value) : undefined; result.npmRoot = result.found ? NodeJs.findLocation(result.filePath, "root", v.value) : undefined; result.npmPrefix = result.found ? NodeJs.findLocation(result.filePath, "prefix", v.value) : undefined; found = result.found; candidatePaths = result.candidatePaths; path = result.path; filePath = result.filePath; fileName = result.fileName; npmBin = result.npmBin; npmRoot = result.npmRoot; npmPrefix = result.npmPrefix; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/PathProbe.qbs000066400000000000000000000062301347155106100231510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import "path-probe.js" as PathProbeConfigure import qbs.ModUtils Probe { // Inputs property stringList names property stringList nameSuffixes property var nameFilter property pathList pathPrefixes property pathList searchPaths property stringList pathSuffixes property pathList platformSearchPaths: hostOS.contains("unix") ? ['/usr', '/usr/local'] : [] property pathList platformPaths property stringList environmentPaths property stringList platformEnvironmentPaths property stringList hostOS: qbs.hostOS property string pathListSeparator: qbs.pathListSeparator // Output property stringList candidatePaths property string path property string filePath property string fileName configure: { if (pathPrefixes) console.warn("PathProbe.pathPrefixes is deprecated, use searchPaths instead"); if (platformPaths) console.warn("PathProbe.platformPaths is deprecated, use platformSearchPaths instead"); var _searchPaths = ModUtils.concatAll(pathPrefixes, searchPaths); var _platformSearchPaths = ModUtils.concatAll(platformPaths, platformSearchPaths); var result = PathProbeConfigure.configure(names, nameSuffixes, nameFilter, _searchPaths, pathSuffixes, _platformSearchPaths, environmentPaths, platformEnvironmentPaths, pathListSeparator); found = result.found; candidatePaths = result.candidatePaths; path = result.path; filePath = result.filePath; fileName = result.fileName; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs000066400000000000000000000133071347155106100241270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Process import qbs.FileInfo Probe { // Inputs property string sysroot: qbs.sysroot property string executable: 'pkg-config' property string name property stringList packageNames: [name] property string minVersion property string exactVersion property string maxVersion property bool forStaticBuild: false property stringList libDirs // Full, non-sysrooted paths, mirroring the environment variable property string pathListSeparator: qbs.pathListSeparator // Output property stringList cflags // Unmodified --cflags output property stringList libs // Unmodified --libs output property stringList defines property stringList libraries property stringList libraryPaths property stringList includePaths property stringList compilerFlags property stringList linkerFlags property string modversion configure: { if (!packageNames || packageNames.length === 0) throw 'PkgConfigProbe.packageNames must be specified.'; var p = new Process(); try { var libDirsToSet = libDirs; if (sysroot) { p.setEnv("PKG_CONFIG_SYSROOT_DIR", sysroot); if (!libDirsToSet) { libDirsToSet = [ sysroot + "/usr/lib/pkgconfig", sysroot + "/usr/share/pkgconfig" ]; } } if (libDirsToSet) p.setEnv("PKG_CONFIG_LIBDIR", libDirsToSet.join(pathListSeparator)); var versionArgs = []; if (minVersion !== undefined) versionArgs.push("--atleast-version=" + minVersion); if (exactVersion !== undefined) versionArgs.push("--exact-version=" + exactVersion); if (maxVersion !== undefined) versionArgs.push("--max-version=" + maxVersion); if (versionArgs.length !== 0 && p.exec(executable, versionArgs.concat(packageNames)) !== 0) { return; } var args = packageNames; if (p.exec(executable, args.concat([ '--cflags' ])) === 0) { cflags = p.readStdOut().trim(); cflags = cflags ? cflags.split(/\s/) : []; var libsArgs = args.concat("--libs"); if (forStaticBuild) libsArgs.push("--static"); if (p.exec(executable, libsArgs) === 0) { libs = p.readStdOut().trim(); libs = libs ? libs.split(/\s/) : []; if (p.exec(executable, [packageNames[0]].concat([ '--modversion' ])) === 0) { modversion = p.readStdOut().trim(); found = true; includePaths = []; defines = [] compilerFlags = []; for (var i = 0; i < cflags.length; ++i) { var flag = cflags[i]; if (flag.startsWith("-I")) includePaths.push(flag.slice(2)); else if (flag.startsWith("-D")) defines.push(flag.slice(2)); else compilerFlags.push(flag); } libraries = []; libraryPaths = []; linkerFlags = []; for (i = 0; i < libs.length; ++i) { flag = libs[i]; if (flag.startsWith("-l")) libraries.push(flag.slice(2)); else if (flag.startsWith("-L")) libraryPaths.push(flag.slice(2)); else linkerFlags.push(flag); } console.debug("PkgConfigProbe: found packages " + packageNames); return; } } } found = false; cflags = undefined; libs = undefined; } finally { p.close(); } } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs000066400000000000000000000065571347155106100243770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import "path-probe.js" as PathProbeConfigure import "../../../modules/typescript/typescript.js" as TypeScript BinaryProbe { id: tsc names: ["tsc"] searchPaths: packageManagerBinPath ? [packageManagerBinPath] : [] // Inputs property path interpreterPath property path packageManagerBinPath property path packageManagerRootPath // Outputs property var version configure: { if (!condition) return; if (!interpreterPath) throw '"interpreterPath" must be specified'; if (!packageManagerBinPath) throw '"packageManagerBinPath" must be specified'; if (!packageManagerRootPath) throw '"packageManagerRootPath" must be specified'; var result = PathProbeConfigure.configure(names, nameSuffixes, nameFilter, searchPaths, pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths, pathListSeparator); var v = new ModUtils.EnvironmentVariable("PATH", pathListSeparator, hostOS.contains("windows")); v.prepend(interpreterPath); result.version = result.found ? TypeScript.findTscVersion(result.filePath, v.value) : undefined; if (FileInfo.fromNativeSeparators(packageManagerBinPath) !== result.path || !File.exists(FileInfo.fromNativeSeparators(packageManagerRootPath, "typescript"))) { result = { found: false }; } found = result.found; candidatePaths = result.candidatePaths; path = result.path; filePath = result.filePath; fileName = result.fileName; version = result.version; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/WiXProbe.qbs000066400000000000000000000056371347155106100227760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Utilities PathProbe { // Inputs property string registryKey: { var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Installer XML", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows Installer XML" ]; for (var i in keys) { var groups = Utilities.nativeSettingGroups(keys[i]).filter(function (v) { return v.match(/^([0-9]+)\.([0-9]+)$/); }); groups.sort(function (a, b) { var re = /^([0-9]+)\.([0-9]+)$/; a = a.match(re); b = b.match(re); a = {major: a[1], minor: a[2]}; b = {major: b[1], minor: b[2]}; if (a.major === b.major) return b.minor - a.minor; return b.major - a.major; }); for (var j in groups) { var fullKey = keys[i] + "\\" + groups[j]; if (Utilities.getNativeSetting(fullKey, "ProductVersion")) return fullKey; } } } // Outputs property var root property var version configure: { var key = registryKey; path = Utilities.getNativeSetting(key, "InstallFolder"); root = Utilities.getNativeSetting(key, "InstallRoot"); version = Utilities.getNativeSetting(key, "ProductVersion"); found = path && root && version; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/XcodeProbe.qbs000066400000000000000000000100421347155106100233130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Process import qbs.PropertyList import "../../../modules/xcode/xcode.js" as Xcode Probe { // Inputs property string sdksPath property string developerPath property string xcodebuildPath property stringList targetOS: qbs.targetOS property string platformType property string platformPath property string devicePlatformPath property string _xcodeInfoPlist: FileInfo.joinPaths(developerPath, "..", "Info.plist") // Outputs property var architectureSettings property var availableSdks property string xcodeVersion configure: { if (File.exists(_xcodeInfoPlist)) { // Optimized case (no forking): reads CFBundleShortVersionString from // Xcode.app/Contents/Info.plist var propertyList = new PropertyList(); try { propertyList.readFromFile(_xcodeInfoPlist); var plist = propertyList.toObject(); if (plist) xcodeVersion = plist["CFBundleShortVersionString"]; } finally { propertyList.clear(); } } else { // Fallback case: execute xcodebuild -version if Xcode.app/Contents/Info.plist is // missing; this can happen if developerPath is /, for example var process; try { process = new Process(); process.exec(xcodebuildPath, ["-version"], true); var lines = process.readStdOut().trim().split(/\r?\n/g).filter(function (line) { return line.length > 0; }); for (var l = 0; l < lines.length; ++l) { var m = lines[l].match(/^Xcode ([0-9\.]+)$/); if (m) { xcodeVersion = m[1]; break; } } } finally { process.close(); } } architectureSettings = {}; var archSpecsPath = Xcode.archsSpecsPath(xcodeVersion, targetOS, platformType, platformPath, devicePlatformPath); var archSpecsReader = new Xcode.XcodeArchSpecsReader(archSpecsPath); archSpecsReader.getArchitectureSettings().map(function (setting) { var val = archSpecsReader.getArchitectureSettingValue(setting); if (val) architectureSettings[setting] = val; }); availableSdks = Xcode.sdkInfoList(sdksPath); found = !!xcodeVersion; } } qbs-src-1.13.1/share/qbs/imports/qbs/Probes/path-probe.js000066400000000000000000000100551347155106100231550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); function configure(names, nameSuffixes, nameFilter, searchPaths, pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths, pathListSeparator) { var result = { found: false, candidatePaths: [] }; if (!names) throw '"names" must be specified'; var _names = ModUtils.concatAll(names); if (nameFilter) _names = _names.map(function(n) { return nameFilter(n); }); _names = ModUtils.concatAll.apply(undefined, _names.map(function(name) { return (nameSuffixes || [""]).map(function(suffix) { return name + suffix; }); })); // FIXME: Suggest how to obtain paths from system var _paths = ModUtils.concatAll(searchPaths, platformSearchPaths); // FIXME: Add getenv support var envs = ModUtils.concatAll(platformEnvironmentPaths, environmentPaths); for (var i = 0; i < envs.length; ++i) { var value = Environment.getEnv(envs[i]) || ''; if (value.length > 0) _paths = _paths.concat(value.split(pathListSeparator)); } var _suffixes = ModUtils.concatAll('', pathSuffixes); _paths = _paths.map(function(p) { return FileInfo.fromNativeSeparators(p); }); _suffixes = _suffixes.map(function(p) { return FileInfo.fromNativeSeparators(p); }); for (i = 0; i < _names.length; ++i) { for (var j = 0; j < _paths.length; ++j) { for (var k = 0; k < _suffixes.length; ++k) { var _filePath = FileInfo.joinPaths(_paths[j], _suffixes[k], _names[i]); result.candidatePaths.push(_filePath); if (File.exists(_filePath)) { result.found = true; result.filePath = _filePath; // Manually specify the path components that constitute _filePath rather // than using the FileInfo.path and FileInfo.fileName functions because we // want to break _filePath into its constituent parts based on the input // originally given by the user. For example, the FileInfo functions would // produce a different result if any of the items in the names property // contained more than a single path component. result.fileName = _names[i]; result.path = FileInfo.joinPaths(_paths[j], _suffixes[k]); return result; } } } } return result; } qbs-src-1.13.1/share/qbs/imports/qbs/UnixUtils/000077500000000000000000000000001347155106100212675ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/imports/qbs/UnixUtils/unix-utils.js000066400000000000000000000053301347155106100237470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); function soname(product, outputFileName) { var soVersion = product.moduleProperty("cpp", "soVersion"); if (product.moduleProperty("qbs", "targetOS").contains("darwin")) { // If this is a bundle, ignore the parameter and use the relative path to the bundle binary // For example: qbs.framework/Versions/1/qbs if (product.moduleProperty("bundle", "isBundle")) outputFileName = product.moduleProperty("bundle", "executablePath"); } else if (soVersion) { // For non-Darwin platforms, append the shared library major version number to the soname // For example: libqbscore.so.1 var version = product.moduleProperty("cpp", "internalVersion"); if (version) { outputFileName = outputFileName.substr(0, outputFileName.length - version.length) + soVersion; } else { outputFileName += "." + soVersion; } } // Prepend the soname prefix // For example, @rpath/libqbscore.dylib or /usr/lib/libqbscore.so.1 var prefix = product.moduleProperty("cpp", "sonamePrefix"); if (prefix) outputFileName = FileInfo.joinPaths(prefix, outputFileName); return outputFileName; } qbs-src-1.13.1/share/qbs/imports/qbs/WindowsUtils/000077500000000000000000000000001347155106100217765ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/imports/qbs/WindowsUtils/windows-utils.js000066400000000000000000000066241347155106100251740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ function winapiFamilyDefine(name) { return { "desktop": "DESKTOP_APP", "phone": "PHONE_APP", "pc": "PC_APP", "server": "SERVER", "system": "SYSTEM" }[name]; } function winapiPartitionDefine(name) { return { "app": "APP", "desktop": "DESKTOP", "phone": "PHONE_APP", "pc": "PC_APP", "server": "SERVER", "system": "SYSTEM" }[name]; } function characterSetDefines(charset) { var defines = []; if (charset === "unicode") defines.push("UNICODE", "_UNICODE"); else if (charset === "mbcs") defines.push("_MBCS"); return defines; } function canonicalizeVersion(version) { switch (version) { case "7": return "6.1"; case "8": return "6.2"; case "8.1": return "6.3"; default: return version; } } function knownWindowsVersions() { // Add new Windows versions to this list when they are released return ['10.0', '6.3', '6.2', '6.1', '6.0', '5.2', '5.1', '5.0', '4.0']; } function isValidWindowsVersion(systemVersion) { var realVersions = knownWindowsVersions(); for (i in realVersions) if (systemVersion === realVersions[i]) return true; return false; } function getWindowsVersionInFormat(systemVersion, format) { if (!systemVersion) return undefined; var major = parseInt(systemVersion.split('.')[0], 10); var minor = parseInt(systemVersion.split('.')[1], 10); switch (format) { case "hex": // https://msdn.microsoft.com/en-us/library/6sehtctf.aspx return "0x" + ("0000" + ((major << 8) | minor).toString(16)).slice(-4); case "subsystem": // https://msdn.microsoft.com/en-us/library/fcc1zstk.aspx return major + '.' + (minor < 10 ? '0' : '') + minor; default: throw ("Unrecognized Windows version format " + format + ". Must be in {hex, subsystem}."); } } qbs-src-1.13.1/share/qbs/imports/qbs/base/000077500000000000000000000000001347155106100202355ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/imports/qbs/base/AndroidApk.qbs000066400000000000000000000031701347155106100227610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo Product { type: ["android.apk"] qbs.targetPlatform: "android" Depends { name: "Android.sdk" } } qbs-src-1.13.1/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs000066400000000000000000000116541347155106100257560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils AppleDiskImage { property string sourceBase: "/Applications" readonly property string absoluteSourceBase: FileInfo.joinPaths(qbs.installRoot, sourceBase) property stringList symlinks: ["/Applications:Applications"] readonly property string stageDirectory: FileInfo.joinPaths(destinationDirectory, "Volumes", dmg.volumeName) Rule { multiplex: true outputFileTags: ["dmg.input", "dmg.input.symlink"] outputArtifacts: Array.prototype.map.call(product.symlinks, function (symlink) { var symlinkTarget = symlink.split(':')[0]; var symlinkName = symlink.split(':')[1] || symlinkTarget; if (FileInfo.isAbsolutePath(symlinkName)) throw(symlink + " is an invalid symlink; the destination must be a relative path"); return { filePath: FileInfo.joinPaths(product.stageDirectory, symlinkName), fileTags: ["dmg.input", "dmg.input.symlink"], dmg: { symlinkTarget: symlinkTarget, sourceBase: product.stageDirectory }, }; }) prepare: Array.prototype.map.call(outputs["dmg.input"], function (symlink) { var cmd = new Command("ln", ["-sfn", symlink.dmg.symlinkTarget, symlink.filePath]); cmd.workingDirectory = product.stageDirectory; cmd.description = "symlinking " + symlink.fileName + " => " + symlink.dmg.symlinkTarget; return cmd; }); } Rule { multiplex: true inputs: ["dmg.input.symlink"] inputsFromDependencies: ["installable"] outputFileTags: ["dmg.input"] outputArtifacts: { var absSourceBase = product.absoluteSourceBase; var symlinkPaths = (inputs["dmg.input.symlink"] || []).map(function (s) { return s.filePath; }); return Array.prototype.map.call(inputs["installable"], function (a) { var fp = ModUtils.artifactInstalledFilePath(a); if (fp.startsWith(absSourceBase)) { var outputFilePath = fp.replace(absSourceBase, product.stageDirectory); // Check for symlink conflicts for (var i in symlinkPaths) { if (outputFilePath.startsWith(symlinkPaths[i])) throw new Error("Cannot install '" + a.filePath + "' to '" + outputFilePath + "' because it " + "would conflict with the symlink at '" + symlinkPaths[i] + "'"); } return { filePath: outputFilePath, fileTags: ["dmg.input"], dmg: { sourceBase: product.stageDirectory } } } }).filter(function (a) { return !!a; }); } prepare: { var absSourceBase = product.absoluteSourceBase; var cmds = [], dmgs = outputs["dmg.input"]; for (var i in dmgs) { var a = dmgs[i]; var cmd = new JavaScriptCommand(); cmd.src = a.filePath.replace(product.stageDirectory, absSourceBase); cmd.dst = a.filePath; cmd.silent = true; cmd.sourceCode = function () { File.copy(src, dst); }; cmds.push(cmd); } return cmds; } } } qbs-src-1.13.1/share/qbs/imports/qbs/base/AppleDiskImage.qbs000066400000000000000000000030451347155106100235650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "dmg" } type: ["dmg.dmg"] } qbs-src-1.13.1/share/qbs/imports/qbs/base/Application.qbs000066400000000000000000000056451347155106100232210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ NativeBinary { type: isForAndroid && !consoleApplication ? ["android.apk"] : ["application"] property bool usesNativeCode Depends { // Note: If we are multiplexing, then this dependency is technically only needed in // the aggregate. However, the user should not have to write the respective // condition when assigning to properties of this module, so we load it // regardless and turn off its rules for the native part of the build. name: "Android.sdk" condition: isForAndroid && !consoleApplication } Properties { condition: isForAndroid && !consoleApplication && !usesNativeCode multiplexByQbsProperties: [] aggregate: false } Properties { condition: isForAndroid && !consoleApplication && usesNativeCode && multiplexByQbsProperties && multiplexByQbsProperties.contains("architectures") && qbs.architectures && qbs.architectures.length > 1 aggregate: true multiplexedType: "android.nativelibrary" } aggregate: base multiplexByQbsProperties: base multiplexedType: base installDir: isBundle ? "Applications" : "bin" Group { condition: install fileTagsFilter: isBundle ? "bundle.content" : "application"; qbs.install: true qbs.installDir: installDir qbs.installSourceBase: isBundle ? destinationDirectory : outer } } qbs-src-1.13.1/share/qbs/imports/qbs/base/ApplicationExtension.qbs000066400000000000000000000051441347155106100251100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ XPCService { Depends { name: "xcode" } type: base.concat(["applicationextension"]) property bool _useLegacyExtensionLibraries: qbs.targetOS.contains("macos") && parseInt(xcode.sdkVersion.split(".")[1], 10) < 11 || qbs.targetOS.contains("ios") && parseInt(xcode.sdkVersion.split(".")[0], 10) < 9 cpp.entryPoint: "_NSExtensionMain" cpp.frameworks: { var frameworks = base.concat(["Foundation"]); if (_useLegacyExtensionLibraries) frameworks.push(qbs.sysroot + "/System/Library/PrivateFrameworks/PlugInKit.framework"); return frameworks; } cpp.requireAppExtensionSafeApi: true xpcServiceType: undefined property var extensionAttributes property string extensionPointIdentifier property string extensionPrincipalClass bundle.infoPlist: { var infoPlist = base; infoPlist["NSExtension"] = { "NSExtensionAttributes": extensionAttributes || {}, "NSExtensionPointIdentifier": extensionPointIdentifier, "NSExtensionPrincipalClass": extensionPrincipalClass }; return infoPlist; } } qbs-src-1.13.1/share/qbs/imports/qbs/base/AutotestRunner.qbs000066400000000000000000000102601347155106100237450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils Product { name: "autotest-runner" type: ["autotest-result"] builtByDefault: false property stringList arguments: [] property stringList environment: ModUtils.flattenDictionary(qbs.commonRunEnvironment) property bool limitToSubProject: true property stringList wrapper: [] property string workingDir property stringList auxiliaryInputs Depends { productTypes: "autotest" limitToSubProject: product.limitToSubProject } Depends { productTypes: auxiliaryInputs limitToSubProject: product.limitToSubProject } Rule { inputsFromDependencies: "application" auxiliaryInputs: product.auxiliaryInputs outputFileTags: "autotest-result" prepare: { // TODO: This is hacky. Possible solution: Add autotest tag to application // in autotest module and have that as inputsFromDependencies instead of application. if (!input.product.type.contains("autotest")) { var cmd = new JavaScriptCommand(); cmd.silent = true; return cmd; } var commandFilePath; var installed = input.moduleProperty("qbs", "install"); if (installed) commandFilePath = ModUtils.artifactInstalledFilePath(input); if (!commandFilePath || !File.exists(commandFilePath)) commandFilePath = input.filePath; var workingDir = product.workingDir ? product.workingDir : FileInfo.path(commandFilePath); var arguments = product.arguments; var allowFailure = false; if (input.autotest) { // FIXME: We'd like to let the user override with an empty list, but // qbscore turns undefined lists into empty ones at the moment. if (input.autotest.arguments && input.autotest.arguments.length > 0) arguments = input.autotest.arguments; if (input.autotest.workingDir) workingDir = input.autotest.workingDir; allowFailure = input.autotest.allowFailure; } var fullCommandLine = product.wrapper .concat([commandFilePath]) .concat(arguments); var cmd = new Command(fullCommandLine[0], fullCommandLine.slice(1)); cmd.description = "Running test " + input.fileName; cmd.environment = product.environment; cmd.workingDirectory = workingDir; if (allowFailure) cmd.maxExitCode = 32767; return cmd; } } } qbs-src-1.13.1/share/qbs/imports/qbs/base/CppApplication.qbs000066400000000000000000000030551347155106100236550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Application { Depends { name: "cpp" } usesNativeCode: true } qbs-src-1.13.1/share/qbs/imports/qbs/base/DynamicLibrary.qbs000066400000000000000000000043401347155106100236560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Library { type: ["dynamiclibrary"].concat(isForAndroid ? ["android.nativelibrary"] : []) installDir: isBundle ? "Library/Frameworks" : qbs.targetOS.contains("windows") ? "bin" : "lib" property bool installImportLib: false property string importLibInstallDir: "lib" Group { condition: install fileTagsFilter: isBundle ? "bundle.content" : ["dynamiclibrary", "dynamiclibrary_symlink"] qbs.install: true qbs.installDir: installDir qbs.installSourceBase: isBundle ? destinationDirectory : outer } Group { condition: installImportLib fileTagsFilter: "dynamiclibrary_import" qbs.install: true qbs.installDir: importLibInstallDir } } qbs-src-1.13.1/share/qbs/imports/qbs/base/InnoSetup.qbs000066400000000000000000000031361347155106100226730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "innosetup"; condition: qbs.targetOS.contains("windows") } type: ["innosetup.exe"] } qbs-src-1.13.1/share/qbs/imports/qbs/base/InstallPackage.qbs000066400000000000000000000053061347155106100236320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.ModUtils import qbs.TextFile Product { type: ["archiver.archive"] builtByDefault: false Depends { name: "archiver" } archiver.type: "tar" archiver.workingDirectory: qbs.installRoot Rule { multiplex: true inputsFromDependencies: ["installable"] Artifact { filePath: product.name + ".tarlist" fileTags: ["archiver.input-list"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode =function() { var ofile = new TextFile(output.filePath, TextFile.WriteOnly); try { for (var i = 0; i < inputs["installable"].length; ++i) { var inp = inputs["installable"][i]; var installRoot = inp.moduleProperty("qbs", "installRoot"); var installedFilePath = ModUtils.artifactInstalledFilePath(inp); ofile.writeLine(FileInfo.relativePath(installRoot, installedFilePath)); } } finally { ofile.close(); } }; return [cmd]; } } } qbs-src-1.13.1/share/qbs/imports/qbs/base/JavaClassCollection.qbs000066400000000000000000000030511347155106100246260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "java" } type: ["java.class"] } qbs-src-1.13.1/share/qbs/imports/qbs/base/JavaJarFile.qbs000066400000000000000000000031061347155106100230620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "java" } type: ["java.jar"] property string entryPoint } qbs-src-1.13.1/share/qbs/imports/qbs/base/Library.qbs000066400000000000000000000033361347155106100223550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ NativeBinary { type: { if (qbs.targetOS.contains("ios") && parseInt(cpp.minimumIosVersion, 10) < 8) return ["staticlibrary"]; return ["dynamiclibrary"].concat(isForAndroid ? ["android.nativelibrary"] : []); } } qbs-src-1.13.1/share/qbs/imports/qbs/base/LoadableModule.qbs000066400000000000000000000030541347155106100236170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ DynamicLibrary { type: isForDarwin ? ["loadablemodule"] : base } qbs-src-1.13.1/share/qbs/imports/qbs/base/NSISSetup.qbs000066400000000000000000000031251347155106100225420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "nsis"; condition: qbs.targetOS.contains("windows") } type: ["nsissetup"] } qbs-src-1.13.1/share/qbs/imports/qbs/base/NativeBinary.qbs000066400000000000000000000050571347155106100233460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { property bool isForAndroid: qbs.targetOS.contains("android") property bool isForDarwin: qbs.targetOS.contains("darwin") property bool isBundle: isForDarwin && bundle.isBundle property bool install: false property string installDir Depends { name: "bundle"; condition: isForDarwin } aggregate: { if (!isForDarwin) return false; var multiplexProps = multiplexByQbsProperties; if (!multiplexProps) return false; if (multiplexProps.contains("architectures")) { var archs = qbs.architectures; if (archs && archs.length > 1) return true; } if (multiplexProps.contains("buildVariants")) { var variants = qbs.buildVariants; return variants && variants.length > 1; } return false; } multiplexByQbsProperties: { if (isForDarwin) return ["profiles", "architectures", "buildVariants"]; if (isForAndroid) return ["architectures"] return ["profiles"]; } } qbs-src-1.13.1/share/qbs/imports/qbs/base/NetModule.qbs000066400000000000000000000001041347155106100226330ustar00rootroot00000000000000Product { Depends { name: "cli" } type: ["cli.netmodule"] } qbs-src-1.13.1/share/qbs/imports/qbs/base/NodeJSApplication.qbs000066400000000000000000000030221347155106100242470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "nodejs" } } qbs-src-1.13.1/share/qbs/imports/qbs/base/QtApplication.qbs000066400000000000000000000030321347155106100235120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ CppApplication { Depends { name: "Qt.core" } } qbs-src-1.13.1/share/qbs/imports/qbs/base/QtGuiApplication.qbs000066400000000000000000000030311347155106100241560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ CppApplication { Depends { name: "Qt.gui" } } qbs-src-1.13.1/share/qbs/imports/qbs/base/StaticLibrary.qbs000066400000000000000000000035001347155106100235160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Library { type: ["staticlibrary"] installDir: isBundle ? "Library/Frameworks" : "lib" Group { condition: install fileTagsFilter: isBundle ? "bundle.content" : "staticlibrary"; qbs.install: true qbs.installDir: installDir qbs.installSourceBase: isBundle ? destinationDirectory : outer } } qbs-src-1.13.1/share/qbs/imports/qbs/base/WindowsInstallerPackage.qbs000066400000000000000000000031161347155106100255310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "wix"; condition: qbs.targetOS.contains("windows") } type: ["msi"] } qbs-src-1.13.1/share/qbs/imports/qbs/base/WindowsSetupPackage.qbs000066400000000000000000000031231347155106100246720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "wix"; condition: qbs.targetOS.contains("windows") } type: ["wixsetup"] } qbs-src-1.13.1/share/qbs/imports/qbs/base/XPCService.qbs000066400000000000000000000035441347155106100227250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Application { type: base.concat(["xpcservice"]) condition: qbs.targetOS.contains("darwin") property string xpcServiceType: "Application" bundle.infoPlist: { var infoPlist = base; if (xpcServiceType) { infoPlist["XPCService"] = { "ServiceType": xpcServiceType }; } return infoPlist; } } qbs-src-1.13.1/share/qbs/module-providers/000077500000000000000000000000001347155106100203415ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/module-providers/Qt/000077500000000000000000000000001347155106100207255ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/module-providers/Qt/provider.qbs000066400000000000000000000002561347155106100232710ustar00rootroot00000000000000import "setup-qt.js" as SetupQt ModuleProvider { property stringList qmakeFilePaths relativeSearchPaths: SetupQt.doSetup(qmakeFilePaths, outputBaseDir, path, qbs) } qbs-src-1.13.1/share/qbs/module-providers/Qt/setup-qt.js000066400000000000000000002013511347155106100230470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function splitNonEmpty(s, c) { return s.split(c).filter(function(e) { return e; }); } function toNative(p) { return FileInfo.toNativeSeparators(p); } function exeSuffix(qbs) { return qbs.hostOS.contains("windows") ? ".exe" : ""; } function getQmakeFilePaths(qmakeFilePaths, qbs) { if (qmakeFilePaths && qmakeFilePaths.length > 0) return qmakeFilePaths; console.info("Detecting Qt installations..."); var pathValue = Environment.getEnv("PATH"); if (!pathValue) return []; var dirs = splitNonEmpty(pathValue, qbs.pathListSeparator); var suffix = exeSuffix(qbs); var filePaths = []; for (var i = 0; i < dirs.length; ++i) { var candidate = FileInfo.joinPaths(dirs[i], "qmake" + suffix); var canonicalCandidate = FileInfo.canonicalPath(candidate); if (!canonicalCandidate || !File.exists(canonicalCandidate)) continue; if (FileInfo.completeBaseName(canonicalCandidate) !== "qtchooser") candidate = canonicalCandidate; if (!filePaths.contains(candidate)) { console.info("Found Qt at '" + toNative(candidate) + "'."); filePaths.push(candidate); } } return filePaths; } function queryQmake(qmakeFilePath) { var qmakeProcess = new Process; qmakeProcess.exec(qmakeFilePath, ["-query"]); if (qmakeProcess.exitCode() !== 0) { throw "The qmake executable '" + toNative(qmakeFilePath) + "' failed with exit code " + qmakeProcess.exitCode() + "."; } var queryResult = {}; while (!qmakeProcess.atEnd()) { var line = qmakeProcess.readLine(); var index = (line || "").indexOf(":"); if (index !== -1) queryResult[line.slice(0, index)] = line.slice(index + 1).trim(); } return queryResult; } function pathQueryValue(queryResult, key) { var p = queryResult[key]; if (p) return FileInfo.fromNativeSeparators(p); } function readFileContent(filePath) { var f = new TextFile(filePath, TextFile.ReadOnly); var content = f.readAll(); f.close(); return content; } // TODO: Don't do the split every time... function configVariable(configContent, key) { var configContentLines = configContent.split('\n'); var regexp = new RegExp("\\s*" + key + "\\s*\\+{0,1}=(.*)"); for (var i = 0; i < configContentLines.length; ++i) { var line = configContentLines[i]; var match = regexp.exec(line); if (match) return match[1].trim(); } } function configVariableItems(configContent, key) { return splitNonEmpty(configVariable(configContent, key), ' '); } function msvcPrefix() { return "win32-msvc"; } function isMsvcQt(qtProps) { return qtProps.mkspecName.startsWith(msvcPrefix()); } function msvcCompilerVersionForYear(year) { var mapping = { "2005": "14", "2008": "15", "2010": "16", "2012": "17", "2013": "18", "2015": "19", "2017": "19.1" }; return mapping[year]; } function msvcCompilerVersionFromMkspecName(mkspecName) { return msvcCompilerVersionForYear(mkspecName.slice(msvcPrefix().length)); } function addQtBuildVariant(qtProps, buildVariantName) { if (qtProps.qtConfigItems.contains(buildVariantName)) qtProps.buildVariant.push(buildVariantName); } function checkForStaticBuild(qtProps) { if (qtProps.qtMajorVersion >= 5) return qtProps.qtConfigItems.contains("static"); if (qtProps.frameworkBuild) return false; // there are no Qt4 static frameworks var isWin = qtProps.mkspecName.startsWith("win"); var libDir = isWin ? qtProps.binaryPath : qtProps.libraryPath; var coreLibFiles = File.directoryEntries(libDir, File.Files) .filter(function(fp) { return fp.contains("Core"); }); if (coreLibFiles.length === 0) throw "Could not determine whether Qt is a static build."; for (var i = 0; i < coreLibFiles.length; ++i) { if (Utilities.isSharedLibrary(coreLibFiles[i])) return false; } return true; } function isForMinGw(qtProps) { return qtProps.mkspecName.startsWith("win32-g++") || qtProps.mkspecName.startsWith("mingw"); } function targetsDesktopWindows(qtProps) { return qtProps.mkspecName.startsWith("win32-") || isForMinGw(qtProps); } function guessMinimumWindowsVersion(qtProps) { if (qtProps.mkspecName.startsWith("winrt-")) return "10.0"; if (!targetsDesktopWindows(qtProps)) return ""; if (qtProps.architecture === "x86_64" || qtProps.architecture === "ia64") return "5.2" var match = qtProps.mkspecName.match(/^win32-msvc(\d+)$/); if (match) { var msvcVersion = match[1]; if (msvcVersion < 2012) return "5.0"; return "5.1"; } return qtProps.qtMajorVersion < 5 ? "5.0" : "5.1"; } function fillEntryPointLibs(qtProps, debug) { result = []; var isMinGW = isForMinGw(qtProps); // Some Linux distributions rename the qtmain library. var qtMainCandidates = ["qtmain"]; if (isMinGW && qtProps.qtMajorVersion === 5) qtMainCandidates.push("qt5main"); for (var i = 0; i < qtMainCandidates.length; ++i) { var baseNameCandidate = qtMainCandidates[i]; var qtmain = qtProps.libraryPath + '/'; if (isMinGW) qtmain += "lib"; qtmain += baseNameCandidate + qtProps.qtLibInfix; if (debug) qtmain += 'd'; if (isMinGW) { qtmain += ".a"; } else { qtmain += ".lib"; if (Utilities.versionCompare(qtProps.qtVersion, "5.4.0") >= 0) result.push("Shell32.lib"); } if (File.exists(qtmain)) { result.push(qtmain); break; } } if (result.length === 0) { console.warn("Could not find the qtmain library at '" + toNative(qtProps.libraryPath) + "'. You will not be able to link Qt applications."); } return result; } function getQtProperties(qmakeFilePath, qbs) { var queryResult = queryQmake(qmakeFilePath); var qtProps = {}; qtProps.installPrefixPath = pathQueryValue(queryResult, "QT_INSTALL_PREFIX"); qtProps.documentationPath = pathQueryValue(queryResult, "QT_INSTALL_DOCS"); qtProps.includePath = pathQueryValue(queryResult, "QT_INSTALL_HEADERS"); qtProps.libraryPath = pathQueryValue(queryResult, "QT_INSTALL_LIBS"); qtProps.hostLibraryPath = pathQueryValue(queryResult, "QT_HOST_LIBS"); qtProps.binaryPath = pathQueryValue(queryResult, "QT_HOST_BINS") || pathQueryValue(queryResult, "QT_INSTALL_BINS"); qtProps.documentationPath = pathQueryValue(queryResult, "QT_INSTALL_DOCS"); qtProps.pluginPath = pathQueryValue(queryResult, "QT_INSTALL_PLUGINS"); qtProps.qmlPath = pathQueryValue(queryResult, "QT_INSTALL_QML"); qtProps.qmlImportPath = pathQueryValue(queryResult, "QT_INSTALL_IMPORTS"); qtProps.qtVersion = queryResult.QT_VERSION; var mkspecsBaseSrcPath; if (Utilities.versionCompare(qtProps.qtVersion, "5") >= 0) { qtProps.mkspecBasePath = FileInfo.joinPaths(pathQueryValue(queryResult, "QT_HOST_DATA"), "mkspecs"); mkspecsBaseSrcPath = FileInfo.joinPaths(pathQueryValue(queryResult, "QT_HOST_DATA/src"), "mkspecs"); } else { qtProps.mkspecBasePath = FileInfo.joinPaths (pathQueryValue(queryResult, "QT_INSTALL_DATA"), "mkspecs"); } if (!File.exists(qtProps.mkspecBasePath)) throw "Cannot extract the mkspecs directory."; var qconfigContent = readFileContent(FileInfo.joinPaths(qtProps.mkspecBasePath, "qconfig.pri")); qtProps.qtMajorVersion = parseInt(configVariable(qconfigContent, "QT_MAJOR_VERSION")); qtProps.qtMinorVersion = parseInt(configVariable(qconfigContent, "QT_MINOR_VERSION")); qtProps.qtPatchVersion = parseInt(configVariable(qconfigContent, "QT_PATCH_VERSION")); qtProps.qtNameSpace = configVariable(qconfigContent, "QT_NAMESPACE"); qtProps.qtLibInfix = configVariable(qconfigContent, "QT_LIBINFIX") || ""; qtProps.architecture = configVariable(qconfigContent, "QT_TARGET_ARCH") || configVariable(qconfigContent, "QT_ARCH") || "x86"; qtProps.configItems = configVariableItems(qconfigContent, "CONFIG"); qtProps.qtConfigItems = configVariableItems(qconfigContent, "QT_CONFIG"); // retrieve the mkspec if (qtProps.qtMajorVersion >= 5) { qtProps.mkspecName = queryResult.QMAKE_XSPEC; qtProps.mkspecPath = FileInfo.joinPaths(qtProps.mkspecBasePath, qtProps.mkspecName); if (mkspecsBaseSrcPath && !File.exists(qtProps.mkspecPath)) qtProps.mkspecPath = FileInfo.joinPaths(mkspecsBaseSrcPath, qtProps.mkspecName); } else { if (qbs.hostOS.contains("windows")) { var baseDirPath = FileInfo.joinPaths(qtProps.mkspecBasePath, "default"); var fileContent = readFileContent(FileInfo.joinPaths(baseDirPath, "qmake.conf")); qtProps.mkspecPath = configVariable(fileContent, "QMAKESPEC_ORIGINAL"); if (!File.exists(qtProps.mkspecPath)) { // Work around QTBUG-28792. // The value of QMAKESPEC_ORIGINAL is wrong for MinGW packages. Y u h8 me? var match = fileContent.exec(/\binclude\(([^)]+)\/qmake\.conf\)/m); if (match) { qtProps.mkspecPath = FileInfo.cleanPath(FileInfo.joinPaths( baseDirPath, match[1])); } } } else { qtProps.mkspecPath = FileInfo.canonicalPath( FileInfo.joinPaths(qtProps.mkspecBasePath, "default")); } // E.g. in qmake.conf for Qt 4.8/mingw we find this gem: // QMAKESPEC_ORIGINAL=C:\\Qt\\Qt\\4.8\\mingw482\\mkspecs\\win32-g++ qtProps.mkspecPath = FileInfo.cleanPath(qtProps.mkspecPath); qtProps.mkspecName = qtProps.mkspecPath; var idx = qtProps.mkspecName.lastIndexOf('/'); if (idx !== -1) qtProps.mkspecName = qtProps.mkspecName.slice(idx + 1); } if (!File.exists(qtProps.mkspecPath)) throw "mkspec '" + toNative(qtProps.mkspecPath) + "' does not exist"; // determine MSVC version if (isMsvcQt(qtProps)) { var msvcMajor = configVariable(qconfigContent, "QT_MSVC_MAJOR_VERSION"); var msvcMinor = configVariable(qconfigContent, "QT_MSVC_MINOR_VERSION"); var msvcPatch = configVariable(qconfigContent, "QT_MSVC_PATCH_VERSION"); if (msvcMajor && msvcMinor && msvcPatch) qtProps.msvcVersion = msvcMajor + "." + msvcMinor + "." + msvcPatch; else qtProps.msvcVersion = msvcCompilerVersionFromMkspecName(qtProps.mkspecName); } // determine whether we have a framework build qtProps.frameworkBuild = qtProps.mkspecPath.contains("macx") && qtProps.configItems.contains("qt_framework"); // determine whether Qt is built with debug, release or both qtProps.buildVariant = []; addQtBuildVariant(qtProps, "debug"); addQtBuildVariant(qtProps, "release"); qtProps.staticBuild = checkForStaticBuild(qtProps); // determine whether user apps require C++11 if (qtProps.qtConfigItems.contains("c++11") && qtProps.staticBuild) qtProps.configItems.push("c++11"); // Set the minimum operating system versions appropriate for this Qt version qtProps.windowsVersion = guessMinimumWindowsVersion(qtProps); if (qtProps.windowsVersion) { // Is target OS Windows? if (qtProps.buildVariant.contains("debug")) qtProps.entryPointLibsDebug = fillEntryPointLibs(qtProps, true); if (qtProps.buildVariant.contains("release")) qtProps.entryPointLibsRelease = fillEntryPointLibs(qtProps, false); } else if (qtProps.mkspecPath.contains("macx")) { if (qtProps.qtMajorVersion >= 5) { var lines = getFileContentsRecursively(FileInfo.joinPaths(qtProps.mkspecPath, "qmake.conf")); for (var i = 0; i < lines.length; ++i) { var line = lines[i].trim(); match = line.match (/^QMAKE_(MACOSX|IOS|TVOS|WATCHOS)_DEPLOYMENT_TARGET\s*=\s*(.*)\s*$/); if (match) { var platform = match[1]; var version = match[2]; if (platform === "MACOSX") qtProps.macosVersion = version; else if (platform === "IOS") qtProps.iosVersion = version; else if (platform === "TVOS") qtProps.tvosVersion = version; else if (platform === "WATCHOS") qtProps.watchosVersion = version; } } var isMac = qtProps.mkspecName !== "macx-ios-clang" && qtProps.mkspecName !== "macx-tvos-clang" && qtProps.mkspecName !== "macx-watchos-clang"; if (isMac) { // Qt 5.0.x placed the minimum version in a different file if (!qtProps.macosVersion) qtProps.macosVersion = "10.6"; // If we're using C++11 with libc++, make sure the deployment target is >= 10.7 if (Utilities.versionCompare(qtProps.macosVersion, "10, 7") < 0 && qtProps.qtConfigItems.contains("c++11")) { qtProps.macosVersion = "10.7"; } } } else if (qtProps.qtMajorVersion === 4 && qtProps.qtMinorVersion >= 6) { var qconfigDir = qtProps.frameworkBuild ? FileInfo.joinPaths(qtProps.libraryPath, "QtCore.framework", "Headers") : FileInfo.joinPaths(qtProps.includePath, "Qt"); try { var qconfig = new TextFile(FileInfo.joinPaths(qconfigDir, "qconfig.h"), TextFile.ReadOnly); var qtCocoaBuild = false; var ok = true; do { line = qconfig.readLine(); if (line.match(/\s*#define\s+QT_MAC_USE_COCOA\s+1\s*/)) { qtCocoaBuild = true; break; } } while (!qconfig.atEof()); qtProps.macosVersion = qtCocoaBuild ? "10.5" : "10.4"; } catch (e) {} finally { if (qconfig) qconfig.close(); } if (!qtProps.macosVersion) { throw "Could not determine whether Qt is using Cocoa or Carbon from '" + toNative(qconfig.filePath()) + "'."; } } } else if (qtProps.mkspecPath.contains("android")) { if (qtProps.qtMajorVersion >= 5) qtProps.androidVersion = "2.3"; else if (qtProps.qtMajorVersion === 4 && qtProps.qtMinorVersion >= 8) qtProps.androidVersion = "1.6"; // Necessitas } return qtProps; } function makePluginData() { var pluginData = {}; pluginData.type = undefined; pluginData.className = undefined; pluginData.autoLoad = true; pluginData["extends"] = []; return pluginData; } function makeQtModuleInfo(name, qbsName, deps) { var moduleInfo = {}; moduleInfo.name = name; // As in the path to the headers and ".name" in the pri files. if (moduleInfo.name === undefined) moduleInfo.name = ""; moduleInfo.qbsName = qbsName; // Lower-case version without "qt" prefix. moduleInfo.dependencies = deps || []; // qbs names. if (moduleInfo.qbsName && moduleInfo.qbsName !== "core" && !moduleInfo.dependencies.contains("core")) { moduleInfo.dependencies.unshift("core"); } moduleInfo.isPrivate = qbsName && qbsName.endsWith("-private"); moduleInfo.hasLibrary = !moduleInfo.isPrivate; moduleInfo.isStaticLibrary = false; moduleInfo.isPlugin = false; moduleInfo.mustExist = true; moduleInfo.modulePrefix = ""; // empty value means "Qt". moduleInfo.version = undefined; moduleInfo.includePaths = []; moduleInfo.compilerDefines = []; moduleInfo.staticLibrariesDebug = []; moduleInfo.staticLibrariesRelease = []; moduleInfo.dynamicLibrariesDebug = []; moduleInfo.dynamicLibrariesRelease = []; moduleInfo.linkerFlagsDebug = []; moduleInfo.linkerFlagsRelease = []; moduleInfo.libFilePathDebug = undefined; moduleInfo.libFilePathRelease = undefined; moduleInfo.frameworksDebug = []; moduleInfo.frameworksRelease = []; moduleInfo.frameworkPathsDebug = []; moduleInfo.frameworkPathsRelease = []; moduleInfo.libraryPaths = []; moduleInfo.libDir = ""; moduleInfo.config = []; moduleInfo.supportedPluginTypes = []; moduleInfo.pluginData = makePluginData(); return moduleInfo; } function frameworkHeadersPath(qtModuleInfo, qtProps) { return FileInfo.joinPaths(qtProps.libraryPath, qtModuleInfo.name + ".framework", "Headers"); } function qt4ModuleIncludePaths(qtModuleInfo, qtProps) { var paths = []; if (isFramework(qtModuleInfo, qtProps)) paths.push(frameworkHeadersPath(qtModuleInfo, qtProps)); else paths.push(qtProps.includePath, FileInfo.joinPaths(qtProps.includePath, qtModuleInfo.name)); return paths; } // We erroneously called the "testlib" module "test" for quite a while. Let's not punish users // for that. function addTestModule(modules) { var testModule = makeQtModuleInfo("QtTest", "test", ["testlib"]); testModule.hasLibrary = false; modules.push(testModule); } // See above. function addDesignerComponentsModule(modules) { var module = makeQtModuleInfo("QtDesignerComponents", "designercomponents", ["designercomponents-private"]); module.hasLibrary = false; modules.push(module); } function isFramework(modInfo, qtProps) { if (!qtProps.frameworkBuild || modInfo.isStaticLibrary) return false; var modulesNeverBuiltAsFrameworks = [ "bootstrap", "openglextensions", "platformsupport", "qmldevtools", "uitools", "harfbuzzng" ]; return !modulesNeverBuiltAsFrameworks.contains(modInfo.qbsName); } function libBaseName(modInfo, libName, debugBuild, qtProps) { var name = libName; if (qtProps.mkspecName.startsWith("win")) { if (debugBuild) name += 'd'; if (!modInfo.isStaticLibrary && qtProps.qtMajorVersion < 5) name += qtProps.qtMajorVersion; } if (qtProps.mkspecName.contains("macx") || qtProps.mkspecName.contains("ios") || qtProps.mkspecName.contains("darwin")) { if (!isFramework(modInfo, qtProps) && qtProps.buildVariant.contains("debug") && (!qtProps.buildVariant.contains("release") || debugBuild)) { name += "_debug"; } } return name; } function moduleNameWithoutPrefix(modInfo) { if (modInfo.name === "Phonon") return "phonon"; if (!modInfo.modulePrefix && modInfo.name.startsWith("Qt")) return modInfo.name.slice(2); // Strip off "Qt". if (modInfo.name.startsWith(modInfo.modulePrefix)) return modInfo.name.slice(modInfo.modulePrefix.length); return modInfo.name; } function libraryBaseName(modInfo, qtProps, debugBuild) { if (modInfo.isPlugin) return libBaseName(modInfo, modInfo.name, debugBuild, qtProps); // Some modules use a different naming scheme, so it doesn't get boring. var libNameBroken = modInfo.name === "Enginio" || modInfo.name === "DataVisualization" || modInfo.name === "Phonon"; var libName = !modInfo.modulePrefix && !libNameBroken ? "Qt" : modInfo.modulePrefix; if (qtProps.qtMajorVersion >= 5 && !isFramework(modInfo, qtProps) && !libNameBroken) libName += qtProps.qtMajorVersion; libName += moduleNameWithoutPrefix(modInfo); libName += qtProps.qtLibInfix; return libBaseName(modInfo, libName, debugBuild, qtProps); } function libNameForLinker(modInfo, qtProps, debugBuild) { if (!modInfo.hasLibrary) return undefined; var libName = libraryBaseName(modInfo, qtProps, debugBuild); if (qtProps.mkspecName.contains("msvc")) libName += ".lib"; return libName; } function guessLibraryFilePath(prlFilePath, libDir, qtProps) { var baseName = FileInfo.baseName(prlFilePath); var prefixCandidates = ["", "lib"]; var suffixCandidates = ["so." + qtProps.qtVersion, "so", "a", "lib", "dll.a"]; for (var i = 0; i < prefixCandidates.length; ++i) { var prefix = prefixCandidates[i]; for (var j = 0; j < suffixCandidates.length; ++j) { var suffix = suffixCandidates[j]; var candidate = FileInfo.joinPaths(libDir, prefix + baseName + '.' + suffix); if (File.exists(candidate)) return candidate; } } } function doReplaceQtLibNamesWithFilePath(namePathMap, libList) { for (var i = 0; i < libList.length; ++i) { var lib = libList[i]; var path = namePathMap[lib]; if (path) libList[i] = path; } } function replaceQtLibNamesWithFilePath(modules, qtProps) { // We don't want to add the libraries for Qt modules via "-l", because of the // danger that a wrong one will be picked up, e.g. from /usr/lib. Instead, // we pull them in using the full file path. var linkerNamesToFilePathsDebug = {}; var linkerNamesToFilePathsRelease = {}; for (var i = 0; i < modules.length; ++i) { var m = modules[i]; linkerNamesToFilePathsDebug[libNameForLinker(m, qtProps, true)] = m.libFilePathDebug; linkerNamesToFilePathsRelease[libNameForLinker(m, qtProps, false)] = m.libFilePathRelease; } for (i = 0; i < modules.length; ++i) { var module = modules[i]; doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, module.dynamicLibrariesDebug); doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, module.staticLibrariesDebug); doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease, module.dynamicLibrariesRelease); doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease, module.staticLibrariesRelease); } } function doSetupLibraries(modInfo, qtProps, debugBuild, nonExistingPrlFiles) { if (!modInfo.hasLibrary) return; // Can happen for Qt4 convenience modules, like "widgets". if (debugBuild) { if (!qtProps.buildVariant.contains("debug")) return; var modulesNeverBuiltAsDebug = ["bootstrap", "qmldevtools"]; for (var i = 0; i < modulesNeverBuiltAsDebug.length; ++i) { var m = modulesNeverBuiltAsDebug[i]; if (modInfo.qbsName === m || modInfo.qbsName === m + "-private") return; } } else if (!qtProps.buildVariant.contains("release")) { return; } var libs = modInfo.isStaticLibrary ? (debugBuild ? modInfo.staticLibrariesDebug : modInfo.staticLibrariesRelease) : (debugBuild ? modInfo.dynamicLibrariesDebug : modInfo.dynamicLibrariesRelease); var frameworks = debugBuild ? modInfo.frameworksDebug : modInfo.frameworksRelease; var frameworkPaths = debugBuild ? modInfo.frameworkPathsDebug : modInfo.frameworkPathsRelease; var flags = debugBuild ? modInfo.linkerFlagsDebug : modInfo.linkerFlagsRelease; var libFilePath; if (qtProps.mkspecName.contains("ios") && modInfo.isStaticLibrary) { libs.push("z", "m"); if (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 8) { var platformSupportModule = makeQtModuleInfo("QtPlatformSupport", "platformsupport"); libs.push(libNameForLinker(platformSupportModule, qtProps, debugBuild)); } if (modInfo.name === "qios") { flags.push("-force_load", FileInfo.joinPaths( qtProps.pluginPath, "platforms", libBaseName(modInfo, "libqios", debugBuild, qtProps) + ".a")); } } var prlFilePath = modInfo.isPlugin ? FileInfo.joinPaths(qtProps.pluginPath, modInfo.pluginData.type) : (modInfo.libDir ? modInfo.libDir : qtProps.libraryPath); if (isFramework(modInfo, qtProps)) { prlFilePath = FileInfo.joinPaths(prlFilePath, libraryBaseName(modInfo, qtProps, false) + ".framework"); } var libDir = prlFilePath; var baseName = libraryBaseName(modInfo, qtProps, debugBuild); if (!qtProps.mkspecName.startsWith("win") && !isFramework(modInfo, qtProps)) baseName = "lib" + baseName; prlFilePath = FileInfo.joinPaths(prlFilePath, baseName); var isNonStaticQt4OnWindows = qtProps.mkspecName.startsWith("win") && !modInfo.isStaticLibrary && qtProps.qtMajorVersion < 5; if (isNonStaticQt4OnWindows) prlFilePath = prlFilePath.slice(0, prlFilePath.length - 1); // The prl file base name does *not* contain the version number... prlFilePath += ".prl"; try { var prlFile = new TextFile(prlFilePath, TextFile.ReadOnly); while (!prlFile.atEof()) { var line = prlFile.readLine().trim(); var equalsOffset = line.indexOf('='); if (equalsOffset === -1) continue; if (line.startsWith("QMAKE_PRL_TARGET")) { var isMingw = qtProps.mkspecName.startsWith("win") && qtProps.mkspecName.contains("g++"); var isQtVersionBefore56 = qtProps.qtMajorVersion < 5 || (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 6); // QMAKE_PRL_TARGET has a "lib" prefix, except for mingw. // Of course, the exception has an exception too: For static libs, mingw *does* // have the "lib" prefix. var libFileName = ""; if (isQtVersionBefore56 && qtProps.qtMajorVersion === 5 && isMingw && !modInfo.isStaticLibrary) { libFileName += "lib"; } libFileName += line.slice(equalsOffset + 1).trim(); if (isNonStaticQt4OnWindows) libFileName += 4; // This is *not* part of QMAKE_PRL_TARGET... if (isQtVersionBefore56) { if (qtProps.mkspecName.contains("msvc")) { libFileName += ".lib"; } else if (isMingw) { libFileName += ".a"; if (!File.exists(FileInfo.joinPaths(libDir, libFileName))) libFileName = libFileName.slice(0, -2) + ".dll"; } } libFilePath = FileInfo.joinPaths(libDir, libFileName); continue; } if (line.startsWith("QMAKE_PRL_CONFIG")) { modInfo.config = splitNonEmpty(line.slice(equalsOffset + 1).trim(), ' '); continue; } if (!line.startsWith("QMAKE_PRL_LIBS")) continue; var parts = extractPaths(line.slice(equalsOffset + 1).trim(), prlFilePath); for (i = 0; i < parts.length; ++i) { var part = parts[i]; part = part.replace("$$[QT_INSTALL_LIBS]", qtProps.libraryPath); if (part.startsWith("-l")) { libs.push(part.slice(2)); } else if (part.startsWith("-L")) { modInfo.libraryPaths.push(part.slice(2)); } else if (part.startsWith("-F")) { frameworkPaths.push(part.slice(2)); } else if (part === "-framework") { if (++i < parts.length) frameworks.push(parts[i]); } else if (part === "-pthread") { libs.push("pthread"); } else if (part.startsWith('-')) { // Some other option console.debug("QMAKE_PRL_LIBS contains non-library option '" + part + "' in file '" + prlFilePath + "'"); flags.push(part); } else if (part.startsWith("/LIBPATH:")) { libraryPaths.push(part.slice(9).replace(/\\/g, '/')); } else { // Assume it's a file path/name. libs.push(part.replace(/\\/g, '/')); } } } } catch (e) { libFilePath = guessLibraryFilePath(prlFilePath, libDir, qtProps); if (nonExistingPrlFiles.contains(prlFilePath)) return; nonExistingPrlFiles.push(prlFilePath); if (!libFilePath && modInfo.mustExist) { console.warn("Could not open prl file '" + toNative(prlFilePath) + "' for module '" + modInfo.name + "' (" + e + "), and failed to deduce the library file path. " + " This module will likely not be usable by qbs."); } } finally { if (prlFile) prlFile.close(); } if (debugBuild) modInfo.libFilePathDebug = libFilePath; else modInfo.libFilePathRelease = libFilePath; } function setupLibraries(qtModuleInfo, qtProps, nonExistingPrlFiles) { doSetupLibraries(qtModuleInfo, qtProps, true, nonExistingPrlFiles); doSetupLibraries(qtModuleInfo, qtProps, false, nonExistingPrlFiles); } function allQt4Modules(qtProps) { // as per http://doc.qt.io/qt-4.8/modules.html + private stuff. var modules = []; var core = makeQtModuleInfo("QtCore", "core"); core.compilerDefines.push("QT_CORE_LIB"); if (qtProps.qtNameSpace) core.compilerDefines.push("QT_NAMESPACE=" + qtProps.qtNameSpace); modules.push(core, makeQtModuleInfo("QtCore", "core-private", ["core"]), makeQtModuleInfo("QtGui", "gui"), makeQtModuleInfo("QtGui", "gui-private", ["gui"]), makeQtModuleInfo("QtMultimedia", "multimedia", ["gui", "network"]), makeQtModuleInfo("QtMultimedia", "multimedia-private", ["multimedia"]), makeQtModuleInfo("QtNetwork", "network"), makeQtModuleInfo("QtNetwork", "network-private", ["network"]), makeQtModuleInfo("QtOpenGL", "opengl", ["gui"]), makeQtModuleInfo("QtOpenGL", "opengl-private", ["opengl"]), makeQtModuleInfo("QtOpenVG", "openvg", ["gui"]), makeQtModuleInfo("QtScript", "script"), makeQtModuleInfo("QtScript", "script-private", ["script"]), makeQtModuleInfo("QtScriptTools", "scripttools", ["script", "gui"]), makeQtModuleInfo("QtScriptTools", "scripttools-private", ["scripttools"]), makeQtModuleInfo("QtSql", "sql"), makeQtModuleInfo("QtSql", "sql-private", ["sql"]), makeQtModuleInfo("QtSvg", "svg", ["gui"]), makeQtModuleInfo("QtSvg", "svg-private", ["svg"]), makeQtModuleInfo("QtWebKit", "webkit", ["gui", "network"]), makeQtModuleInfo("QtWebKit", "webkit-private", ["webkit"]), makeQtModuleInfo("QtXml", "xml"), makeQtModuleInfo("QtXml", "xml-private", ["xml"]), makeQtModuleInfo("QtXmlPatterns", "xmlpatterns", ["network"]), makeQtModuleInfo("QtXmlPatterns", "xmlpatterns-private", ["xmlpatterns"]), makeQtModuleInfo("QtDeclarative", "declarative", ["gui", "script"]), makeQtModuleInfo("QtDeclarative", "declarative-private", ["declarative"]), makeQtModuleInfo("QtDesigner", "designer", ["gui", "xml"]), makeQtModuleInfo("QtDesigner", "designer-private", ["designer"]), makeQtModuleInfo("QtUiTools", "uitools"), makeQtModuleInfo("QtUiTools", "uitools-private", ["uitools"]), makeQtModuleInfo("QtHelp", "help", ["network", "sql"]), makeQtModuleInfo("QtHelp", "help-private", ["help"]), makeQtModuleInfo("QtTest", "testlib"), makeQtModuleInfo("QtTest", "testlib-private", ["testlib"])); if (qtProps.mkspecName.startsWith("win")) { var axcontainer = makeQtModuleInfo("QAxContainer", "axcontainer"); axcontainer.modulePrefix = "Q"; axcontainer.isStaticLibrary = true; axcontainer.includePaths.push(FileInfo.joinPaths(qtProps.includePath, "ActiveQt")); modules.push(axcontainer); var axserver = makeQtModuleInfo("QAxServer", "axserver"); axserver.modulePrefix = "Q"; axserver.isStaticLibrary = true; axserver.compilerDefines.push("QAXSERVER"); axserver.includePaths.push(FileInfo.joinPaths(qtProps.includePath, "ActiveQt")); modules.push(axserver); } else { modules.push(makeQtModuleInfo("QtDBus", "dbus")); modules.push(makeQtModuleInfo("QtDBus", "dbus-private", ["dbus"])); } var designerComponentsPrivate = makeQtModuleInfo( "QtDesignerComponents", "designercomponents-private", ["gui-private", "designer-private"]); designerComponentsPrivate.hasLibrary = true; modules.push(designerComponentsPrivate); var phonon = makeQtModuleInfo("Phonon", "phonon"); phonon.includePaths = qt4ModuleIncludePaths(phonon, qtProps); modules.push(phonon); // Set up include paths that haven't been set up before this point. for (i = 0; i < modules.length; ++i) { var module = modules[i]; if (module.includePaths.length > 0) continue; module.includePaths = qt4ModuleIncludePaths(module, qtProps); } // Set up compiler defines haven't been set up before this point. for (i = 0; i < modules.length; ++i) { module = modules[i]; if (module.compilerDefines.length > 0) continue; module.compilerDefines.push("QT_" + module.qbsName.toUpperCase() + "_LIB"); } // These are for the convenience of project file authors. It allows them // to add a dependency to e.g. "Qt.widgets" without a version check. var virtualModule = makeQtModuleInfo(undefined, "widgets", ["core", "gui"]); virtualModule.hasLibrary = false; modules.push(virtualModule); virtualModule = makeQtModuleInfo(undefined, "quick", ["declarative"]); virtualModule.hasLibrary = false; modules.push(virtualModule); virtualModule = makeQtModuleInfo(undefined, "concurrent"); virtualModule.hasLibrary = false; modules.push(virtualModule); virtualModule = makeQtModuleInfo(undefined, "printsupport", ["core", "gui"]); virtualModule.hasLibrary = false; modules.push(virtualModule); addTestModule(modules); addDesignerComponentsModule(modules); var modulesThatCanBeDisabled = [ "xmlpatterns", "multimedia", "phonon", "svg", "webkit", "script", "scripttools", "declarative", "gui", "dbus", "opengl", "openvg"]; var nonExistingPrlFiles = []; for (i = 0; i < modules.length; ++i) { module = modules[i]; var name = module.qbsName; var privateIndex = name.indexOf("-private"); if (privateIndex !== -1) name = name.slice(0, privateIndex); if (modulesThatCanBeDisabled.contains(name)) module.mustExist = false; if (qtProps.staticBuild) module.isStaticLibrary = true; setupLibraries(module, qtProps, nonExistingPrlFiles); } replaceQtLibNamesWithFilePath(modules, qtProps); return modules; } function getFileContentsRecursively(filePath) { var file = new TextFile(filePath, TextFile.ReadOnly); var lines = splitNonEmpty(file.readAll(), '\n'); for (var i = 0; i < lines.length; ++i) { var includeString = "include("; var line = lines[i].trim(); if (!line.startsWith(includeString)) continue; var offset = includeString.length; var closingParenPos = line.indexOf(')', offset); if (closingParenPos === -1) { console.warn("Invalid include statement in '" + toNative(filePath) + "'"); continue; } var includedFilePath = line.slice(offset, closingParenPos); if (!FileInfo.isAbsolutePath(includedFilePath)) includedFilePath = FileInfo.joinPaths(FileInfo.path(filePath), includedFilePath); var includedContents = getFileContentsRecursively(includedFilePath); var j = i; for (var k = 0; k < includedContents.length; ++k) lines.splice(++j, 0, includedContents[k]); lines.splice(i--, 1); } file.close(); return lines; } function extractPaths(rhs, filePath) { var paths = []; var startIndex = 0; for (;;) { while (startIndex < rhs.length && rhs.charAt(startIndex) === ' ') ++startIndex; if (startIndex >= rhs.length) break; var endIndex; if (rhs.charAt(startIndex) === '"') { ++startIndex; endIndex = rhs.indexOf('"', startIndex); if (endIndex === -1) { console.warn("Unmatched quote in file '" + toNative(filePath) + "'"); break; } } else { endIndex = rhs.indexOf(' ', startIndex + 1); if (endIndex === -1) endIndex = rhs.length; } paths.push(FileInfo.cleanPath(rhs.slice(startIndex, endIndex))); startIndex = endIndex + 1; } return paths; } function removeDuplicatedDependencyLibs(modules) { var revDeps = {}; var currentPath = []; var getLibraries; var getLibFilePath; function setupReverseDependencies(modules) { var moduleByName = {}; for (var i = 0; i < modules.length; ++i) moduleByName[modules[i].qbsName] = modules[i]; for (i = 0; i < modules.length; ++i) { var module = modules[i]; for (var j = 0; j < module.dependencies.length; ++j) { var depmod = moduleByName[module.dependencies[j]]; if (!depmod) continue; if (!revDeps[depmod.qbsName]) revDeps[depmod.qbsName] = []; revDeps[depmod.qbsName].push(module); } } } function roots(modules) { var result = []; for (i = 0; i < modules.length; ++i) { var module = modules[i] if (module.dependencies.length === 0) result.push(module); } return result; } function traverse(module, libs) { if (currentPath.contains(module)) return; currentPath.push(module); var moduleLibraryLists = getLibraries(module); for (var i = 0; i < moduleLibraryLists.length; ++i) { var modLibList = moduleLibraryLists[i]; for (j = modLibList.length - 1; j >= 0; --j) { if (libs.contains(modLibList[j])) modLibList.splice(j, 1); } } var libFilePath = getLibFilePath(module); if (libFilePath) libs.push(libFilePath); for (i = 0; i < moduleLibraryLists.length; ++i) libs = libs.concat(moduleLibraryLists[i]); libs.sort(); var deps = revDeps[module.qbsName]; for (i = 0; i < (deps || []).length; ++i) traverse(deps[i], libs); currentPath.pop(); } setupReverseDependencies(modules); // Traverse the debug variants of modules. getLibraries = function(module) { return [module.dynamicLibrariesDebug, module.staticLibrariesDebug]; }; getLibFilePath = function(module) { return module.libFilePathDebug; }; var rootModules = roots(modules); for (var i = 0; i < rootModules.length; ++i) traverse(rootModules[i], []); // Traverse the release variants of modules. getLibraries = function(module) { return [module.dynamicLibrariesRelease, module.staticLibrariesRelease]; }; getLibFilePath = function(module) { return module.libFilePathRelease; }; for (i = 0; i < rootModules.length; ++i) traverse(rootModules[i], []); } function allQt5Modules(qtProps) { var nonExistingPrlFiles = []; var modules = []; var modulesDir = FileInfo.joinPaths(qtProps.mkspecBasePath, "modules"); var modulePriFiles = File.directoryEntries(modulesDir, File.Files); for (var i = 0; i < modulePriFiles.length; ++i) { var priFileName = modulePriFiles[i]; var priFilePath = FileInfo.joinPaths(modulesDir, priFileName); var moduleFileNamePrefix = "qt_lib_"; var pluginFileNamePrefix = "qt_plugin_"; var moduleFileNameSuffix = ".pri"; var fileHasPluginPrefix = priFileName.startsWith(pluginFileNamePrefix); if (!fileHasPluginPrefix && (!priFileName.startsWith(moduleFileNamePrefix)) || !priFileName.endsWith(moduleFileNameSuffix)) { continue; } var moduleInfo = makeQtModuleInfo(); moduleInfo.isPlugin = fileHasPluginPrefix; var fileNamePrefix = moduleInfo.isPlugin ? pluginFileNamePrefix : moduleFileNamePrefix; moduleInfo.qbsName = priFileName.slice(fileNamePrefix.length, -moduleFileNameSuffix.length); if (moduleInfo.isPlugin) { moduleInfo.name = moduleInfo.qbsName; moduleInfo.isStaticLibrary = true; } var moduleKeyPrefix = (moduleInfo.isPlugin ? "QT_PLUGIN" : "QT") + '.' + moduleInfo.qbsName + '.'; moduleInfo.qbsName = moduleInfo.qbsName.replace("_private", "-private"); var hasV2 = false; var hasModuleEntry = false; var lines = getFileContentsRecursively(priFilePath); for (var j = 0; j < lines.length; ++j) { var line = lines[j].trim(); var firstEqualsOffset = line.indexOf('='); if (firstEqualsOffset === -1) continue; var key = line.slice(0, firstEqualsOffset).trim(); var value = line.slice(firstEqualsOffset + 1).trim(); if (!key.startsWith(moduleKeyPrefix) || !value) continue; if (key.endsWith(".name")) { moduleInfo.name = value; } else if (key.endsWith(".module")) { hasModuleEntry = true; } else if (key.endsWith(".depends")) { moduleInfo.dependencies = splitNonEmpty(value, ' '); for (var k = 0; k < moduleInfo.dependencies.length; ++k) { moduleInfo.dependencies[k] = moduleInfo.dependencies[k].replace("_private", "-private"); } } else if (key.endsWith(".module_config")) { var elems = splitNonEmpty(value, ' '); for (k = 0; k < elems.length; ++k) { var elem = elems[k]; if (elem === "no_link") moduleInfo.hasLibrary = false; else if (elem === "staticlib") moduleInfo.isStaticLibrary = true; else if (elem === "internal_module") moduleInfo.isPrivate = true; else if (elem === "v2") hasV2 = true; } } else if (key.endsWith(".includes")) { moduleInfo.includePaths = extractPaths(value, priFilePath); for (k = 0; k < moduleInfo.includePaths.length; ++k) { moduleInfo.includePaths[k] = moduleInfo.includePaths[k] .replace("$$QT_MODULE_INCLUDE_BASE", qtProps.includePath) .replace("$$QT_MODULE_HOST_LIB_BASE", qtProps.hostLibraryPath) .replace("$$QT_MODULE_LIB_BASE", qtProps.libraryPath); } } else if (key.endsWith(".libs")) { var libDirs = extractPaths(value, priFilePath); if (libDirs.length === 1) { moduleInfo.libDir = libDirs[0] .replace("$$QT_MODULE_HOST_LIB_BASE", qtProps.hostLibraryPath) .replace("$$QT_MODULE_LIB_BASE", qtProps.libraryPath); } else { moduleInfo.libDir = qtProps.libraryPath; } } else if (key.endsWith(".DEFINES")) { moduleInfo.compilerDefines = splitNonEmpty(value, ' '); } else if (key.endsWith(".VERSION")) { moduleInfo.version = value; } else if (key.endsWith(".plugin_types")) { moduleInfo.supportedPluginTypes = splitNonEmpty(value, ' '); } else if (key.endsWith(".TYPE")) { moduleInfo.pluginData.type = value; } else if (key.endsWith(".EXTENDS")) { moduleInfo.pluginData["extends"] = splitNonEmpty(value, ' '); for (k = 0; k < moduleInfo.pluginData["extends"].length; ++k) { if (moduleInfo.pluginData["extends"][k] === "-") { moduleInfo.pluginData["extends"].splice(k, 1); moduleInfo.pluginData.autoLoad = false; break; } } } else if (key.endsWith(".CLASS_NAME")) { moduleInfo.pluginData.className = value; } } if (hasV2 && !hasModuleEntry) moduleInfo.hasLibrary = false; // Fix include paths for Apple frameworks. // The qt_lib_XXX.pri files contain wrong values for versions < 5.6. if (!hasV2 && isFramework(moduleInfo, qtProps)) { moduleInfo.includePaths = []; var baseIncDir = frameworkHeadersPath(moduleInfo, qtProps); if (moduleInfo.isPrivate) { baseIncDir = FileInfo.joinPaths(baseIncDir, moduleInfo.version); moduleInfo.includePaths.push(baseIncDir, FileInfo.joinPaths(baseIncDir, moduleInfo.name)); } else { moduleInfo.includePaths.push(baseIncDir); } } setupLibraries(moduleInfo, qtProps, nonExistingPrlFiles); modules.push(moduleInfo); if (moduleInfo.qbsName === "testlib") addTestModule(modules); if (moduleInfo.qbsName === "designercomponents-private") addDesignerComponentsModule(modules); } replaceQtLibNamesWithFilePath(modules, qtProps); removeDuplicatedDependencyLibs(modules); return modules; } function extractQbsArchs(module, qtProps) { if (qtProps.mkspecName.startsWith("macx-")) { var archs = []; if (module.libFilePathRelease) archs = Utilities.getArchitecturesFromBinary(module.libFilePathRelease); return archs; } var qbsArch = Utilities.canonicalArchitecture(qtProps.architecture); if (qbsArch === "arm" && qtProps.mkspecPath.contains("android")) qbsArch = "armv7a"; // Qt4 has "QT_ARCH = windows" in qconfig.pri for both MSVC and mingw. if (qbsArch === "windows") return [] return [qbsArch]; } function qbsTargetPlatformFromQtMkspec(qtProps) { var mkspec = qtProps.mkspecName; var idx = mkspec.lastIndexOf('/'); if (idx !== -1) mkspec = mkspec.slice(idx + 1); if (mkspec.startsWith("aix-")) return "aix"; if (mkspec.startsWith("android-")) return "android"; if (mkspec.startsWith("cygwin-")) return "windows"; if (mkspec.startsWith("darwin-")) return "macos"; if (mkspec.startsWith("freebsd-")) return "freebsd"; if (mkspec.startsWith("haiku-")) return "haiku"; if (mkspec.startsWith(("hpux-")) || mkspec.startsWith(("hpuxi-"))) return "hpux"; if (mkspec.startsWith("hurd-")) return "hurd"; if (mkspec.startsWith("integrity-")) return "integrity"; if (mkspec.startsWith("linux-")) return "linux"; if (mkspec.startsWith("macx-")) { if (mkspec.startsWith("macx-ios-")) return "ios"; if (mkspec.startsWith("macx-tvos-")) return "tvos"; if (mkspec.startsWith("macx-watchos-")) return "watchos"; return "macos"; } if (mkspec.startsWith("netbsd-")) return "netbsd"; if (mkspec.startsWith("openbsd-")) return "openbsd"; if (mkspec.startsWith("qnx-")) return "qnx"; if (mkspec.startsWith("solaris-")) return "solaris"; if (mkspec.startsWith("vxworks-")) return "vxworks"; if (targetsDesktopWindows(qtProps) || mkspec.startsWith("winrt-")) return "windows"; } function pathToJSLiteral(path) { return JSON.stringify(FileInfo.fromNativeSeparators(path)); } function defaultQpaPlugin(module, qtProps) { if (qtProps.qtMajorVersion < 5) return undefined; if (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 8) { var qConfigPri = new TextFile(FileInfo.joinPaths(qtProps.mkspecBasePath, "qconfig.pri")); var magicString = "QT_DEFAULT_QPA_PLUGIN ="; while (!qConfigPri.atEof()) { var line = qConfigPri.readLine().trim(); if (line.startsWith(magicString)) return line.slice(magicString.length).trim(); } qConfigPri.close(); } else { var gtGuiHeadersPath = qtProps.frameworkBuild ? FileInfo.joinPaths(qtProps.libraryPath, "QtGui.framework", "Headers") : FileInfo.joinPaths(qtProps.includePath, "QtGui"); var qtGuiConfigHeader = FileInfo.joinPaths(gtGuiHeadersPath, "qtgui-config.h"); var headerFiles = []; headerFiles.push(qtGuiConfigHeader); while (headerFiles.length > 0) { var filePath = headerFiles.shift(); var headerFile = new TextFile(filePath, TextFile.ReadOnly); var regexp = /^#define QT_QPA_DEFAULT_PLATFORM_NAME "(.+)".*$/; var includeRegexp = /^#include "(.+)".*$/; while (!headerFile.atEof()) { line = headerFile.readLine().trim(); var match = line.match(regexp); if (match) return 'q' + match[1]; match = line.match(includeRegexp); if (match) { var includedFile = match[1]; if (!FileInfo.isAbsolutePath(includedFile)) { includedFile = FileInfo.cleanPath( FileInfo.joinPaths(FileInfo.path(filePath), includedFile)); } headerFiles.push(includedFile); } } headerFile.close(); } } if (module.isStaticLibrary) console.warn("Could not determine default QPA plugin for static Qt."); } function libraryFileTag(module, qtProps) { if (module.isStaticLibrary) return "staticlibrary"; return isMsvcQt(qtProps) || qtProps.mkspecName.startsWith("win32-g++") ? "dynamiclibrary_import" : "dynamiclibrary"; } function findVariable(content, start) { var result = [-1, -1]; result[0] = content.indexOf('@', start); if (result[0] === -1) return result; result[1] = content.indexOf('@', result[0] + 1); if (result[1] === -1) { result[0] = -1; return result; } var forbiddenChars = [' ', '\n']; for (var i = 0; i < forbiddenChars.length; ++i) { var forbidden = forbiddenChars[i]; var k = content.indexOf(forbidden, result[0] + 1); if (k !== -1 && k < result[1]) return findVariable(content, result[0] + 1); } return result; } function toJSLiteral(v) { if (v === undefined) return "undefined"; return JSON.stringify(v); } function minVersionJsString(minVersion) { return !minVersion ? "original" : toJSLiteral(minVersion); } function replaceSpecialValues(content, module, qtProps) { var dict = { archs: toJSLiteral(extractQbsArchs(module, qtProps)), targetPlatform: toJSLiteral(qbsTargetPlatformFromQtMkspec(qtProps)), config: toJSLiteral(qtProps.configItems), qtConfig: toJSLiteral(qtProps.qtConfigItems), binPath: toJSLiteral(qtProps.binaryPath), libPath: toJSLiteral(qtProps.libraryPath), pluginPath: toJSLiteral(qtProps.pluginPath), incPath: toJSLiteral(qtProps.includePath), docPath: toJSLiteral(qtProps.documentationPath), mkspecName: toJSLiteral(qtProps.mkspecName), mkspecPath: toJSLiteral(qtProps.mkspecPath), version: toJSLiteral(qtProps.qtVersion), libInfix: toJSLiteral(qtProps.qtLibInfix), availableBuildVariants: toJSLiteral(qtProps.buildVariant), staticBuild: toJSLiteral(qtProps.staticBuild), frameworkBuild: toJSLiteral(qtProps.frameworkBuild), name: toJSLiteral(moduleNameWithoutPrefix(module)), has_library: toJSLiteral(module.hasLibrary), dependencies: toJSLiteral(module.dependencies), includes: toJSLiteral(module.includePaths), staticLibsDebug: toJSLiteral(module.staticLibrariesDebug), staticLibsRelease: toJSLiteral(module.staticLibrariesRelease), dynamicLibsDebug: toJSLiteral(module.dynamicLibrariesDebug), dynamicLibsRelease: toJSLiteral(module.dynamicLibrariesRelease), linkerFlagsDebug: toJSLiteral(module.linkerFlagsDebug), linkerFlagsRelease: toJSLiteral(module.linkerFlagsRelease), libraryPaths: toJSLiteral(module.libraryPaths), frameworkPathsDebug: toJSLiteral(module.frameworkPathsDebug), frameworkPathsRelease: toJSLiteral(module.frameworkPathsRelease), frameworksDebug: toJSLiteral(module.frameworksDebug), frameworksRelease: toJSLiteral(module.frameworksRelease), libFilePathDebug: toJSLiteral(module.libFilePathDebug), libFilePathRelease: toJSLiteral(module.libFilePathRelease), libNameForLinkerDebug: toJSLiteral(libNameForLinker(module, qtProps, true)), pluginTypes: toJSLiteral(module.supportedPluginTypes), moduleConfig: toJSLiteral(module.config), libNameForLinkerRelease: toJSLiteral(libNameForLinker(module, qtProps, false)), entryPointLibsDebug: toJSLiteral(qtProps.entryPointLibsDebug), entryPointLibsRelease: toJSLiteral(qtProps.entryPointLibsRelease), minWinVersion: minVersionJsString(qtProps.windowsVersion), minMacVersion: minVersionJsString(qtProps.macosVersion), minIosVersion: minVersionJsString(qtProps.iosVersion), minTvosVersion: minVersionJsString(qtProps.tvosVersion), minWatchosVersion: minVersionJsString(qtProps.watchosVersion), minAndroidVersion: minVersionJsString(qtProps.androidVersion), }; var additionalContent = ""; var compilerDefines = toJSLiteral(module.compilerDefines); if (module.qbsName === "declarative" || module.qbsName === "quick") { var debugMacro = module.qbsName === "declarative" || qtProps.qtMajorVersion < 5 ? "QT_DECLARATIVE_DEBUG" : "QT_QML_DEBUG"; var indent = " "; additionalContent = "property bool qmlDebugging: false\n" + indent + "property string qmlPath"; if (qtProps.qmlPath) additionalContent += ": " + pathToJSLiteral(qtProps.qmlPath) + '\n'; else additionalContent += '\n'; additionalContent += indent + "property string qmlImportsPath: " + pathToJSLiteral(qtProps.qmlImportPath); compilerDefines = "{\n" + indent + indent + "var result = " + compilerDefines + ";\n" + indent + indent + "if (qmlDebugging)\n" + indent + indent + indent + "result.push(\"" + debugMacro + "\");\n" + indent + indent + "return result;\n" + indent + "}"; } dict.defines = compilerDefines; if (module.qbsName === "gui") dict.defaultQpaPlugin = toJSLiteral(defaultQpaPlugin(module, qtProps)); if (module.qbsName === "qml") dict.qmlPath = pathToJSLiteral(qtProps.qmlPath); if (module.isStaticLibrary && module.qbsName !== "core") { if (additionalContent) additionalContent += "\n "; additionalContent += "isStaticLibrary: true"; } if (module.isPlugin) { dict.className = toJSLiteral(module.pluginData.className); dict["extends"] = toJSLiteral(module.pluginData["extends"]); } if (module.hasLibrary && !isFramework(module, qtProps)) { if (additionalContent) additionalContent += "\n"; indent = " "; additionalContent += "Group {\n"; if (module.isPlugin) { additionalContent += indent + indent + "condition: Qt[\"" + module.qbsName + "\"].enableLinking\n"; } additionalContent += indent + indent + "files: [Qt[\"" + module.qbsName + "\"]" + ".libFilePath]\n" + indent + indent + "filesAreTargets: true\n" + indent + indent + "fileTags: [\"" + libraryFileTag(module, qtProps) + "\"]\n" + indent + "}"; } dict.additionalContent = additionalContent; for (var pos = findVariable(content, 0); pos[0] !== -1; pos = findVariable(content, pos[0])) { var replacement = dict[content.slice(pos[0] + 1, pos[1])] || ""; content = content.slice(0, pos[0]) + replacement + content.slice(pos[1] + 1); pos[0] += replacement.length; } return content; } function copyTemplateFile(fileName, targetDirectory, qtProps, location, allFiles, module, pluginMap, nonEssentialPlugins) { if (!File.makePath(targetDirectory)) { throw "Cannot create directory '" + toNative(targetDirectory) + "'."; } var sourceFile = new TextFile(FileInfo.joinPaths(location, "templates", fileName), TextFile.ReadOnly); var newContent = sourceFile.readAll(); if (module) { newContent = replaceSpecialValues(newContent, module, qtProps); } else { newContent = newContent.replace("@allPluginsByType@", '(' + toJSLiteral(pluginMap) + ')'); newContent = newContent.replace("@nonEssentialPlugins@", toJSLiteral(nonEssentialPlugins)); } sourceFile.close(); var targetPath = FileInfo.joinPaths(targetDirectory, fileName); allFiles.push(targetPath); var targetFile = new TextFile(targetPath, TextFile.WriteOnly); targetFile.write(newContent); targetFile.close(); } function setupOneQt(qmakeFilePath, outputBaseDir, uniquify, location, qbs) { if (!File.exists(qmakeFilePath)) throw "The specified qmake file path '" + toNative(qmakeFilePath) + "' does not exist."; var qtProps = getQtProperties(qmakeFilePath, qbs); var modules = qtProps.qtMajorVersion < 5 ? allQt4Modules(qtProps) : allQt5Modules(qtProps); var pluginsByType = {}; var nonEssentialPlugins = []; for (var i = 0; i < modules.length; ++i) { var m = modules[i]; if (m.isPlugin) { if (!pluginsByType[m.pluginData.type]) pluginsByType[m.pluginData.type] = []; pluginsByType[m.pluginData.type].push(m.name); if (!m.pluginData.autoLoad) nonEssentialPlugins.push(m.name); } } var relativeSearchPath = uniquify ? Utilities.getHash(qmakeFilePath) : ""; var qbsQtModuleBaseDir = FileInfo.joinPaths(outputBaseDir, relativeSearchPath, "modules", "Qt"); if (File.exists(qbsQtModuleBaseDir)) File.remove(qbsQtModuleBaseDir); var allFiles = []; copyTemplateFile("QtModule.qbs", qbsQtModuleBaseDir, qtProps, location, allFiles); copyTemplateFile("QtPlugin.qbs", qbsQtModuleBaseDir, qtProps, location, allFiles); copyTemplateFile("plugin_support.qbs", FileInfo.joinPaths(qbsQtModuleBaseDir, "plugin_support"), qtProps, location, allFiles, undefined, pluginsByType, nonEssentialPlugins); for (i = 0; i < modules.length; ++i) { var module = modules[i]; var qbsQtModuleDir = FileInfo.joinPaths(qbsQtModuleBaseDir, module.qbsName); var moduleTemplateFileName; if (module.qbsName === "core") { moduleTemplateFileName = "core.qbs"; copyTemplateFile("moc.js", qbsQtModuleDir, qtProps, location, allFiles); copyTemplateFile("qdoc.js", qbsQtModuleDir, qtProps, location, allFiles); } else if (module.qbsName === "gui") { moduleTemplateFileName = "gui.qbs"; } else if (module.qbsName === "scxml") { moduleTemplateFileName = "scxml.qbs"; } else if (module.qbsName === "dbus") { moduleTemplateFileName = "dbus.qbs"; copyTemplateFile("dbus.js", qbsQtModuleDir, qtProps, location, allFiles); } else if (module.qbsName === "qml") { moduleTemplateFileName = "qml.qbs"; copyTemplateFile("qml.js", qbsQtModuleDir, qtProps, location, allFiles); var qmlcacheStr = "qmlcache"; if (File.exists(FileInfo.joinPaths(qtProps.binaryPath, "qmlcachegen" + exeSuffix(qbs)))) { copyTemplateFile(qmlcacheStr + ".qbs", FileInfo.joinPaths(qbsQtModuleBaseDir, qmlcacheStr), qtProps, location, allFiles); } } else if (module.qbsName === "quick") { moduleTemplateFileName = "quick.qbs"; copyTemplateFile("quick.js", qbsQtModuleDir, qtProps, location, allFiles); } else if (module.isPlugin) { moduleTemplateFileName = "plugin.qbs"; } else { moduleTemplateFileName = "module.qbs"; } copyTemplateFile(moduleTemplateFileName, qbsQtModuleDir, qtProps, location, allFiles, module); } // Note that it's not strictly necessary to copy this one, as it has no variable content. // But we do it anyway for consistency. copyTemplateFile("android_support.qbs", FileInfo.joinPaths(qbsQtModuleBaseDir, "android_support"), qtProps, location, allFiles); return relativeSearchPath; } function doSetup(qmakeFilePaths, outputBaseDir, location, qbs) { qmakeFilePaths = getQmakeFilePaths(qmakeFilePaths, qbs); if (!qmakeFilePaths || qmakeFilePaths.length === 0) return []; var uniquifySearchPath = qmakeFilePaths.length > 1; var searchPaths = []; for (var i = 0; i < qmakeFilePaths.length; ++i) { try { console.info("Setting up Qt at '" + toNative(qmakeFilePaths[i]) + "'..."); var searchPath = setupOneQt(qmakeFilePaths[i], outputBaseDir, uniquifySearchPath, location, qbs); if (searchPath !== undefined) { searchPaths.push(searchPath); console.info("Qt was set up successfully."); } } catch (e) { console.warn("Error setting up Qt for '" + toNative(qmakeFilePaths[i]) + "': " + e); } } return searchPaths; } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/000077500000000000000000000000001347155106100227235ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/QtModule.qbs000066400000000000000000000072631347155106100251740ustar00rootroot00000000000000import qbs.FileInfo Module { condition: (qbs.targetPlatform === targetPlatform || isCombinedUIKitBuild) && (!qbs.architecture || architectures.length === 0 || architectures.contains(qbs.architecture)) readonly property bool isCombinedUIKitBuild: ["ios", "tvos", "watchos"].contains(targetPlatform) && ["x86", "x86_64"].contains(qbs.architecture) && qbs.targetPlatform === targetPlatform + "-simulator" Depends { name: "cpp" } Depends { name: "Qt.core" } Depends { name: "Qt.plugin_support" } property stringList pluginTypes Qt.plugin_support.pluginTypes: pluginTypes Depends { condition: Qt.core.staticBuild && !isPlugin name: "Qt"; submodules: { // We have to pull in all plugins here, because dependency resolving happens // before module merging, and we don't know yet if someone set // Qt.pluginSupport.pluginsByType in the product. // The real filtering is done later by the plugin module files themselves. var list = []; var allPlugins = Qt.plugin_support.allPluginsByType; for (var i = 0; i < (pluginTypes || []).length; ++i) Array.prototype.push.apply(list, allPlugins[pluginTypes[i]]) return list; } } property string qtModuleName property path binPath: Qt.core.binPath property path incPath: Qt.core.incPath property path libPath: Qt.core.libPath property string qtLibInfix: Qt.core.libInfix property string libNameForLinkerDebug property string libNameForLinkerRelease property string libNameForLinker: Qt.core.qtBuildVariant === "debug" ? libNameForLinkerDebug : libNameForLinkerRelease property string libFilePathDebug property string libFilePathRelease property string libFilePath: Qt.core.qtBuildVariant === "debug" ? libFilePathDebug : libFilePathRelease version: Qt.core.version property bool hasLibrary: true property bool isStaticLibrary: false property bool isPlugin: false property stringList architectures property string targetPlatform property stringList staticLibsDebug property stringList staticLibsRelease property stringList dynamicLibsDebug property stringList dynamicLibsRelease property stringList linkerFlagsDebug property stringList linkerFlagsRelease property stringList staticLibs: Qt.core.qtBuildVariant === "debug" ? staticLibsDebug : staticLibsRelease property stringList dynamicLibs: Qt.core.qtBuildVariant === "debug" ? dynamicLibsDebug : dynamicLibsRelease property stringList frameworksDebug property stringList frameworksRelease property stringList frameworkPathsDebug property stringList frameworkPathsRelease property stringList mFrameworks: Qt.core.qtBuildVariant === "debug" ? frameworksDebug : frameworksRelease property stringList mFrameworkPaths: Qt.core.qtBuildVariant === "debug" ? frameworkPathsDebug: frameworkPathsRelease cpp.linkerFlags: Qt.core.qtBuildVariant === "debug" ? linkerFlagsDebug : linkerFlagsRelease property bool enableLinking: qtModuleName != undefined && hasLibrary property stringList moduleConfig Properties { condition: enableLinking cpp.staticLibraries: staticLibs cpp.dynamicLibraries: dynamicLibs cpp.frameworks: mFrameworks.concat(!isStaticLibrary && Qt.core.frameworkBuild ? [libNameForLinker] : []) cpp.frameworkPaths: mFrameworkPaths } } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/QtPlugin.qbs000066400000000000000000000032151347155106100251760ustar00rootroot00000000000000import qbs.FileInfo import qbs.TextFile QtModule { isPlugin: true property string className property stringList extendsModules enableLinking: { if (!base) return false; if (!isStaticLibrary) return false; if (!Qt.plugin_support.linkPlugins) return false; if (!(Qt.plugin_support.enabledPlugins || []).contains(qtModuleName)) return false; if (!extendsModules || extendsModules.length === 0) return true; for (var i = 0; i < extendsModules.length; ++i) { var moduleName = extendsModules[i]; if (product.Qt[moduleName] && product.Qt[moduleName].present) return true; } return false; } Rule { condition: enableLinking multiplex: true Artifact { filePath: product.targetName + "_qt_plugin_import_" + product.moduleProperty(product.moduleName, "qtModuleName") + ".cpp" fileTags: "cpp" } prepare: { var cmd = new JavaScriptCommand(); var pluginName = product.moduleProperty(product.moduleName, "qtModuleName"); cmd.description = "Creating static import for plugin '" + pluginName + "'."; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); var className = product.moduleProperty(product.moduleName, "className"); f.writeLine("#include \n\nQ_IMPORT_PLUGIN(" + className + ")"); f.close(); }; return cmd; } } } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/android_support.qbs000066400000000000000000000337571347155106100266650ustar00rootroot00000000000000import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.TextFile import qbs.Utilities Module { property bool useMinistro: false property string qmlRootDir: product.sourceDirectory property stringList extraPrefixDirs property stringList deploymentDependencies // qmake: ANDROID_DEPLOYMENT_DEPENDENCIES property stringList extraPlugins // qmake: ANDROID_EXTRA_PLUGINS property bool verboseAndroidDeployQt: false property string _androidDeployQtFilePath: FileInfo.joinPaths(_qtInstallDir, "bin", "androiddeployqt") property string _qtInstallDir property bool _enableSdkSupport: product.type && product.type.contains("android.apk") && !consoleApplication property bool _enableNdkSupport: !product.aggregate || product.multiplexConfigurationId property string _templatesBaseDir: FileInfo.joinPaths(_qtInstallDir, "src", "android") property string _deployQtOutDir: FileInfo.joinPaths(product.buildDirectory, "deployqt_out") Depends { name: "Android.sdk"; condition: _enableSdkSupport } Depends { name: "Android.ndk"; condition: _enableNdkSupport } Depends { name: "java"; condition: _enableSdkSupport } Properties { condition: _enableNdkSupport && qbs.toolchain.contains("clang") Android.ndk.appStl: "c++_shared" } Properties { condition: _enableNdkSupport && !qbs.toolchain.contains("clang") Android.ndk.appStl: "gnustl_shared" } Properties { condition: _enableSdkSupport Android.sdk.customManifestProcessing: true java._tagJniHeaders: false // prevent rule cycle } Rule { condition: _enableSdkSupport multiplex: true property stringList inputTags: "android.nativelibrary" inputsFromDependencies: inputTags inputs: product.aggregate ? [] : inputTags Artifact { filePath: "androiddeployqt.json" fileTags: "qt_androiddeployqt_input" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var theBinary; var nativeLibs = inputs["android.nativelibrary"]; if (nativeLibs.length === 1) { theBinary = nativeLibs[0]; } else { for (i = 0; i < nativeLibs.length; ++i) { var candidate = nativeLibs[i]; if (!candidate.fileName.contains(candidate.product.targetName)) continue; if (!theBinary) { theBinary = candidate; continue; } if (theBinary.product.name === product.name && candidate.product.name !== product.name) { continue; // We already have a better match. } if (candidate.product.name === product.name && theBinary.product.name !== product.name) { theBinary = candidate; // The new candidate is a better match. continue; } throw "Qt applications for Android support only one native binary " + "per package.\n" + "In particular, you cannot build a Qt app for more than " + "one architecture at the same time."; } } var f = new TextFile(output.filePath, TextFile.WriteOnly); f.writeLine("{"); f.writeLine('"description": "This file was generated by qbs to be read by ' + 'androiddeployqt and should not be modified by hand.",'); f.writeLine('"qt": "' + product.Qt.android_support._qtInstallDir + '",'); f.writeLine('"sdk": "' + product.Android.sdk.sdkDir + '",'); f.writeLine('"sdkBuildToolsRevision": "' + product.Android.sdk.buildToolsVersion + '",'); f.writeLine('"ndk": "' + product.Android.sdk.ndkDir + '",'); var toolPrefix = theBinary.cpp.toolchainTriple; var toolchainPrefix = toolPrefix.startsWith("i686-") ? "x86" : toolPrefix; f.writeLine('"toolchain-prefix": "' + toolchainPrefix + '",'); f.writeLine('"tool-prefix": "' + toolPrefix + '",'); f.writeLine('"toolchain-version": "' + theBinary.Android.ndk.toolchainVersion + '",'); f.writeLine('"ndk-host": "' + theBinary.Android.ndk.hostArch + '",'); f.writeLine('"target-architecture": "' + theBinary.Android.ndk.abi + '",'); f.writeLine('"qml-root-path": "' + product.Qt.android_support.qmlRootDir + '",'); var deploymentDeps = product.Qt.android_support.deploymentDependencies; if (deploymentDeps && deploymentDeps.length > 0) f.writeLine('"deployment-dependencies": "' + deploymentDeps.join() + '",'); var extraPlugins = product.Qt.android_support.extraPlugins; if (extraPlugins && extraPlugins.length > 0) f.writeLine('"android-extra-plugins": "' + extraPlugins.join() + '",'); var prefixDirs = product.Qt.android_support.extraPrefixDirs; if (prefixDirs && prefixDirs.length > 0) f.writeLine('"extraPrefixDirs": ' + JSON.stringify(prefixDirs) + ','); if (Array.isArray(product.qmlImportPaths) && product.qmlImportPaths.length > 0) f.writeLine('"qml-import-paths": "' + product.qmlImportPaths.join(',') + '",'); // QBS-1429 f.writeLine('"stdcpp-path": "' + (product.cpp.sharedStlFilePath ? product.cpp.sharedStlFilePath : product.cpp.staticStlFilePath) + '",'); f.writeLine('"application-binary": "' + theBinary.filePath + '"'); f.writeLine("}"); f.close(); }; return cmd; } } // We use the manifest template from the Qt installation if and only if the project // does not provide a manifest file. Rule { condition: _enableSdkSupport multiplex: true requiresInputs: false inputs: "android.manifest" excludedInputs: "qt.android_manifest" outputFileTags: ["android.manifest", "qt.android_manifest"] outputArtifacts: { if (inputs["android.manifest"]) return []; return [{ filePath: "qt_manifest/AndroidManifest.xml", fileTags: ["android.manifest", "qt.android_manifest"] }]; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "copying Qt Android manifest template"; cmd.sourceCode = function() { File.copy(FileInfo.joinPaths(product.Qt.android_support._templatesBaseDir, "templates", "AndroidManifest.xml"), output.filePath); }; return cmd; } } Rule { condition: _enableSdkSupport multiplex: true inputs: ["qt_androiddeployqt_input", "android.manifest_processed"] outputFileTags: [ "android.manifest_final", "android.resources", "android.assets", "bundled_jar", "android.deployqt_list", ] outputArtifacts: { var artifacts = [ { filePath: "AndroidManifest.xml", fileTags: "android.manifest_final" }, { filePath: product.Qt.android_support._deployQtOutDir + "/res/values/libs.xml", fileTags: "android.resources" }, { filePath: product.Qt.android_support._deployQtOutDir + "/res/values/strings.xml", fileTags: "android.resources" }, { filePath: product.Qt.android_support._deployQtOutDir + "/assets/.dummy", fileTags: "android.assets" }, { filePath: "deployqt.list", fileTags: "android.deployqt_list" }, ]; if (!product.Qt.android_support.useMinistro) { artifacts.push({ filePath: FileInfo.joinPaths(product.java.classFilesDir, "QtAndroid.jar"), fileTags: ["bundled_jar"] }); } return artifacts; } prepare: { var copyCmd = new JavaScriptCommand(); copyCmd.description = "copying Qt resource templates"; copyCmd.sourceCode = function() { File.copy(inputs["android.manifest_processed"][0].filePath, product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml"); File.copy(product.Qt.android_support._templatesBaseDir + "/java/res", product.Qt.android_support._deployQtOutDir + "/res"); File.copy(product.Qt.android_support._templatesBaseDir + "/templates/res/values/libs.xml", product.Qt.android_support._deployQtOutDir + "/res/values/libs.xml"); try { File.remove(FileInfo.path(outputs["android.assets"][0].filePath)); } catch (e) { } }; var androidDeployQtArgs = [ "--output", product.Qt.android_support._deployQtOutDir, "--input", inputs["qt_androiddeployqt_input"][0].filePath, "--aux-mode", "--deployment", product.Qt.android_support.useMinistro ? "ministro" : "bundled", "--android-platform", product.Android.sdk.platform, ]; if (product.Qt.android_support.verboseAndroidDeployQt) args.push("--verbose"); var androidDeployQtCmd = new Command( product.Qt.android_support._androidDeployQtFilePath, androidDeployQtArgs); androidDeployQtCmd.description = "running androiddeployqt"; // We do not want androiddeployqt to write directly into our APK base dir, so // we ran it on an isolated directory and now we move stuff over. // We remember the files for which we do that, so if the next invocation // of androiddeployqt creates fewer files, the other ones are removed from // the APK base dir. var moveCmd = new JavaScriptCommand(); moveCmd.description = "processing androiddeployqt outout"; moveCmd.sourceCode = function() { File.move(product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml", outputs["android.manifest_final"][0].filePath); var libsDir = product.Qt.android_support._deployQtOutDir + "/libs"; var libDir = product.Android.sdk.apkContentsDir + "/lib"; var listFilePath = outputs["android.deployqt_list"][0].filePath; var oldLibs = []; try { var listFile = new TextFile(listFilePath, TextFile.ReadOnly); var listFileLine = listFile.readLine(); while (listFileLine) { oldLibs.push(listFileLine); listFileLine = listFile.readLine(); } listFile.close(); } catch (e) { } listFile = new TextFile(listFilePath, TextFile.WriteOnly); var newLibs = []; var moveLibFiles = function(prefix) { var fullSrcPrefix = FileInfo.joinPaths(libsDir, prefix); var files = File.directoryEntries(fullSrcPrefix, File.Files); for (var i = 0; i < files.length; ++i) { var file = files[i]; var srcFilePath = FileInfo.joinPaths(fullSrcPrefix, file); var targetFilePath; if (file.endsWith(".jar")) targetFilePath = FileInfo.joinPaths(product.java.classFilesDir, file); else targetFilePath = FileInfo.joinPaths(libDir, prefix, file); File.move(srcFilePath, targetFilePath); listFile.writeLine(targetFilePath); newLibs.push(targetFilePath); } var dirs = File.directoryEntries(fullSrcPrefix, File.Dirs | File.NoDotAndDotDot); for (i = 0; i < dirs.length; ++i) moveLibFiles(FileInfo.joinPaths(prefix, dirs[i])); }; moveLibFiles(""); listFile.close(); for (i = 0; i < oldLibs.length; ++i) { if (!newLibs.contains(oldLibs[i])) File.remove(oldLibs[i]); } }; return [copyCmd, androidDeployQtCmd, moveCmd]; } } Group { condition: Qt.android_support._enableSdkSupport name: "helper sources from qt" prefix: Qt.android_support._templatesBaseDir + "/java/" Android.sdk.aidlSearchPaths: prefix + "src" files: [ "**/*.java", "**/*.aidl", ] } validate: { if (Utilities.versionCompare(version, "5.12") < 0) throw ModUtils.ModuleError("Cannot use Qt " + version + " with Android. " + "Version 5.12 or later is required."); } } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/core.qbs000066400000000000000000000501111347155106100243600ustar00rootroot00000000000000import qbs.FileInfo import qbs.ModUtils import qbs.TextFile import qbs.Utilities import qbs.Xml import "moc.js" as Moc import "qdoc.js" as Qdoc Module { condition: (qbs.targetPlatform === targetPlatform || isCombinedUIKitBuild) && (!qbs.architecture || architectures.length === 0 || architectures.contains(qbs.architecture)) readonly property bool isCombinedUIKitBuild: ["ios", "tvos", "watchos"].contains(targetPlatform) && (!qbs.architecture || ["x86", "x86_64"].contains(qbs.architecture)) && qbs.targetPlatform === targetPlatform + "-simulator" Depends { name: "cpp" } Depends { name: "Qt.android_support"; condition: qbs.targetOS.contains("android") } Properties { condition: qbs.targetOS.contains("android") Qt.android_support._qtInstallDir: FileInfo.path(binPath) Qt.android_support.version: version } version: @version@ property stringList architectures: @archs@ property string targetPlatform: @targetPlatform@ property string libInfix: @libInfix@ property stringList config: @config@ property stringList qtConfig: @qtConfig@ property path binPath: @binPath@ property path incPath: @incPath@ property path libPath: @libPath@ property path pluginPath: @pluginPath@ property string mkspecName: @mkspecName@ property path mkspecPath: @mkspecPath@ property string mocName: "moc" property stringList mocFlags: [] property string lreleaseName: "lrelease" property string qdocName: versionMajor >= 5 ? "qdoc" : "qdoc3" property stringList qdocEnvironment property path docPath: @docPath@ property stringList helpGeneratorArgs: versionMajor >= 5 ? ["-platform", "minimal"] : [] property var versionParts: version ? version.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int versionMajor: versionParts[0] property int versionMinor: versionParts[1] property int versionPatch: versionParts[2] property bool frameworkBuild: @frameworkBuild@ property bool staticBuild: @staticBuild@ property stringList pluginMetaData: [] property bool enableKeywords: true property stringList availableBuildVariants: @availableBuildVariants@ property string qtBuildVariant: { if (availableBuildVariants.contains(qbs.buildVariant)) return qbs.buildVariant; return availableBuildVariants.length > 0 ? availableBuildVariants[0] : ""; } property stringList staticLibsDebug: @staticLibsDebug@ property stringList staticLibsRelease: @staticLibsRelease@ property stringList dynamicLibsDebug: @dynamicLibsDebug@ property stringList dynamicLibsRelease: @dynamicLibsRelease@ property stringList staticLibs: qtBuildVariant === "debug" ? staticLibsDebug : staticLibsRelease property stringList dynamicLibs: qtBuildVariant === "debug" ? dynamicLibsDebug : dynamicLibsRelease property stringList linkerFlagsDebug: @linkerFlagsDebug@ property stringList linkerFlagsRelease: @linkerFlagsRelease@ property stringList coreLinkerFlags: qtBuildVariant === "debug" ? linkerFlagsDebug : linkerFlagsRelease property stringList frameworksDebug: @frameworksDebug@ property stringList frameworksRelease: @frameworksRelease@ property stringList coreFrameworks: qtBuildVariant === "debug" ? frameworksDebug : frameworksRelease property stringList frameworkPathsDebug: @frameworkPathsDebug@ property stringList frameworkPathsRelease: @frameworkPathsRelease@ property stringList coreFrameworkPaths: qtBuildVariant === "debug" ? frameworkPathsDebug : frameworkPathsRelease property string libNameForLinkerDebug: @libNameForLinkerDebug@ property string libNameForLinkerRelease: @libNameForLinkerRelease@ property string libNameForLinker: qtBuildVariant === "debug" ? libNameForLinkerDebug : libNameForLinkerRelease property string libFilePathDebug: @libFilePathDebug@ property string libFilePathRelease: @libFilePathRelease@ property string libFilePath: qtBuildVariant === "debug" ? libFilePathDebug : libFilePathRelease property stringList coreLibPaths: @libraryPaths@ // These are deliberately not path types // We don't want to resolve them against the source directory property string generatedHeadersDir: product.buildDirectory + "/qt.headers" property string qdocOutputDir: product.buildDirectory + "/qdoc_html" property string qmDir: product.destinationDirectory property string qmBaseName: product.targetName property bool lreleaseMultiplexMode: false property stringList moduleConfig: @moduleConfig@ Properties { condition: moduleConfig.contains("use_gold_linker") cpp.linkerVariant: "gold" } cpp.entryPoint: qbs.targetOS.containsAny(["ios", "tvos"]) && Utilities.versionCompare(version, "5.6.0") >= 0 ? "_qt_main_wrapper" : undefined cpp.cxxLanguageVersion: Utilities.versionCompare(version, "5.7.0") >= 0 ? "c++11" : original cpp.enableCompilerDefinesByLanguage: ["cpp"].concat( qbs.targetOS.contains("darwin") ? ["objcpp"] : []) cpp.defines: { var defines = @defines@; // ### QT_NO_DEBUG must be added if the current build variant is derived // from the build variant "release" if (!qbs.debugInformation) defines.push("QT_NO_DEBUG"); if (!enableKeywords) defines.push("QT_NO_KEYWORDS"); if (qbs.targetOS.containsAny(["ios", "tvos"])) { defines = defines.concat(["DARWIN_NO_CARBON", "QT_NO_CORESERVICES", "QT_NO_PRINTER", "QT_NO_PRINTDIALOG"]); if (Utilities.versionCompare(version, "5.6.0") < 0) defines.push("main=qtmn"); } return defines; } cpp.driverFlags: { var flags = []; if (qbs.toolchain.contains("gcc")) { if (config.contains("sanitize_address")) flags.push("-fsanitize=address"); if (config.contains("sanitize_undefined")) flags.push("-fsanitize=undefined"); if (config.contains("sanitize_thread")) flags.push("-fsanitize=thread"); if (config.contains("sanitize_memory")) flags.push("-fsanitize=memory"); } return flags; } cpp.includePaths: { var paths = @includes@; paths.push(mkspecPath, generatedHeadersDir); return paths; } cpp.libraryPaths: { var libPaths = [libPath]; if (staticBuild && pluginPath) libPaths.push(pluginPath + "/platforms"); libPaths = libPaths.concat(coreLibPaths); return libPaths; } cpp.staticLibraries: { var libs = []; if (qbs.targetOS.contains('windows') && !product.consoleApplication) { libs = libs.concat(qtBuildVariant === "debug" ? @entryPointLibsDebug@ : @entryPointLibsRelease@); } libs = libs.concat(staticLibs); return libs; } cpp.dynamicLibraries: dynamicLibs cpp.linkerFlags: coreLinkerFlags cpp.frameworkPaths: coreFrameworkPaths.concat(frameworkBuild ? [libPath] : []) cpp.frameworks: { var frameworks = coreFrameworks if (frameworkBuild) frameworks.push(libNameForLinker); if (qbs.targetOS.contains('ios') && staticBuild) frameworks = frameworks.concat(["Foundation", "CoreFoundation"]); if (frameworks.length === 0) return undefined; return frameworks; } cpp.rpaths: qbs.targetOS.contains('linux') ? [libPath] : undefined cpp.runtimeLibrary: qbs.toolchain.contains("msvc") ? config.contains("static_runtime") ? "static" : "dynamic" : original cpp.positionIndependentCode: versionMajor >= 5 ? true : undefined cpp.cxxFlags: { var flags = []; if (qbs.toolchain.contains('msvc')) { if (versionMajor < 5) flags.push('/Zc:wchar_t-'); } return flags; } cpp.cxxStandardLibrary: { if (qbs.targetOS.contains('darwin') && qbs.toolchain.contains('clang') && config.contains('c++11')) return "libc++"; return original; } cpp.minimumWindowsVersion: @minWinVersion@ cpp.minimumMacosVersion: @minMacVersion@ cpp.minimumIosVersion: @minIosVersion@ cpp.minimumTvosVersion: @minTvosVersion@ cpp.minimumWatchosVersion: @minWatchosVersion@ cpp.minimumAndroidVersion: @minAndroidVersion@ // Universal Windows Platform support cpp.windowsApiFamily: mkspecName.startsWith("winrt-") ? "pc" : undefined cpp.windowsApiAdditionalPartitions: mkspecPath.startsWith("winrt-") ? ["phone"] : undefined cpp.requireAppContainer: mkspecName.startsWith("winrt-") additionalProductTypes: ["qm"] validate: { var validator = new ModUtils.PropertyValidator("Qt.core"); validator.setRequiredProperty("binPath", binPath); validator.setRequiredProperty("incPath", incPath); validator.setRequiredProperty("libPath", libPath); validator.setRequiredProperty("mkspecPath", mkspecPath); validator.setRequiredProperty("version", version); validator.setRequiredProperty("config", config); validator.setRequiredProperty("qtConfig", qtConfig); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); if (!staticBuild) validator.setRequiredProperty("pluginPath", pluginPath); // Allow custom version suffix since some distributions might want to do this, // but otherwise the version must start with a valid 3-component string validator.addVersionValidator("version", version, 3, 3, true); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); validator.addCustomValidator("availableBuildVariants", availableBuildVariants, function (v) { return v.length > 0; }, "the Qt installation supports no build variants"); validator.addCustomValidator("qtBuildVariant", qtBuildVariant, function (variant) { return availableBuildVariants.contains(variant); }, "'" + qtBuildVariant + "' is not supported by this Qt installation"); validator.addCustomValidator("qtBuildVariant", qtBuildVariant, function (variant) { return variant === qbs.buildVariant || !qbs.toolchain.contains("msvc"); }, " is '" + qtBuildVariant + "', but qbs.buildVariant is '" + qbs.buildVariant + "', which is not allowed when using MSVC"); validator.addFileNameValidator("resourceFileBaseName", resourceFileBaseName); validator.validate(); } FileTagger { patterns: ["*.qrc"] fileTags: ["qrc"] } FileTagger { patterns: ["*.ts"] fileTags: ["ts"] } FileTagger { patterns: ["*.qdoc", "*.qdocinc"] fileTags: ["qdoc"] } FileTagger { patterns: ["*.qdocconf"] fileTags: ["qdocconf"] } FileTagger { patterns: ["*.qhp"] fileTags: ["qhp"] } property bool combineMocOutput: cpp.combineCxxSources property bool enableBigResources: false Rule { name: "QtCoreMocRuleCpp" property string cppInput: cpp.combineCxxSources ? "cpp.combine" : "cpp" property string objcppInput: cpp.combineObjcxxSources ? "objcpp.combine" : "objcpp" inputs: [objcppInput, cppInput] auxiliaryInputs: "qt_plugin_metadata" excludedInputs: "unmocable" outputFileTags: ["hpp", "unmocable"] outputArtifacts: Moc.outputArtifacts.apply(Moc, arguments) prepare: Moc.commands.apply(Moc, arguments) } Rule { name: "QtCoreMocRuleHpp" inputs: "hpp" auxiliaryInputs: ["qt_plugin_metadata", "cpp", "objcpp"]; excludedInputs: "unmocable" outputFileTags: ["hpp", "cpp", "moc_cpp", "unmocable"] outputArtifacts: Moc.outputArtifacts.apply(Moc, arguments) prepare: Moc.commands.apply(Moc, arguments) } Rule { multiplex: true inputs: ["moc_cpp"] Artifact { filePath: "amalgamated_moc_" + product.targetName + ".cpp" fileTags: ["cpp", "unmocable"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { ModUtils.mergeCFiles(inputs["moc_cpp"], output.filePath); }; return [cmd]; } } property path resourceSourceBase property string resourcePrefix: "/" property string resourceFileBaseName: product.targetName Rule { multiplex: true inputs: ["qt.core.resource_data"] Artifact { filePath: product.Qt.core.resourceFileBaseName + ".qrc" fileTags: ["qrc"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var doc = new Xml.DomDocument("RCC"); var rccNode = doc.createElement("RCC"); rccNode.setAttribute("version", "1.0"); doc.appendChild(rccNode); var inputsByPrefix = {} for (var i = 0; i < inputs["qt.core.resource_data"].length; ++i) { var inp = inputs["qt.core.resource_data"][i]; var prefix = inp.Qt.core.resourcePrefix; var inputsList = inputsByPrefix[prefix] || []; inputsList.push(inp); inputsByPrefix[prefix] = inputsList; } for (var prefix in inputsByPrefix) { var qresourceNode = doc.createElement("qresource"); qresourceNode.setAttribute("prefix", prefix); rccNode.appendChild(qresourceNode); for (var i = 0; i < inputsByPrefix[prefix].length; ++i) { var inp = inputsByPrefix[prefix][i]; var fullResPath = inp.filePath; var baseDir = inp.Qt.core.resourceSourceBase; var resAlias = baseDir ? FileInfo.relativePath(baseDir, fullResPath) : inp.fileName; var fileNode = doc.createElement("file"); fileNode.setAttribute("alias", resAlias); qresourceNode.appendChild(fileNode); var fileTextNode = doc.createTextNode(fullResPath); fileNode.appendChild(fileTextNode); } } doc.save(output.filePath, 4); }; return [cmd]; } } Rule { inputs: ["qrc"] outputFileTags: ["cpp", "cpp_intermediate_object"] outputArtifacts: { var artifact = { filePath: "qrc_" + input.completeBaseName + ".cpp", fileTags: ["cpp"] }; if (input.Qt.core.enableBigResources) artifact.fileTags.push("cpp_intermediate_object"); return [artifact]; } prepare: { var args = [input.filePath, "-name", FileInfo.completeBaseName(input.filePath), "-o", output.filePath]; if (input.Qt.core.enableBigResources) args.push("-pass", "1"); var cmd = new Command(product.Qt.core.binPath + '/rcc', args); cmd.description = "rcc " + (input.Qt.core.enableBigResources ? "(pass 1) " : "") + input.fileName; cmd.highlight = 'codegen'; return cmd; } } Rule { inputs: ["intermediate_obj"] Artifact { filePath: input.completeBaseName + ".2.o" fileTags: ["obj"] } prepare: { function findChild(artifact, predicate) { var children = artifact.children; var len = children.length; for (var i = 0; i < len; ++i) { var child = children[i]; if (predicate(child)) return child; child = findChild(child, predicate); if (child) return child; } return undefined; } var qrcArtifact = findChild(input, function(c) { return c.fileTags.contains("qrc"); }); var cppArtifact = findChild(input, function(c) { return c.fileTags.contains("cpp"); }); var cmd = new Command(product.Qt.core.binPath + '/rcc', [qrcArtifact.filePath, "-temp", input.filePath, "-name", FileInfo.completeBaseName(input.filePath), "-o", output.filePath, "-pass", "2"]); cmd.description = "rcc (pass 2) " + qrcArtifact.fileName; cmd.highlight = 'codegen'; return cmd; } } Rule { inputs: ["ts"] multiplex: lreleaseMultiplexMode Artifact { filePath: FileInfo.joinPaths(product.Qt.core.qmDir, (product.Qt.core.lreleaseMultiplexMode ? product.Qt.core.qmBaseName : input.baseName) + ".qm") fileTags: ["qm"] } prepare: { var inputFilePaths; if (product.Qt.core.lreleaseMultiplexMode) inputFilePaths = inputs["ts"].map(function(artifact) { return artifact.filePath; }); else inputFilePaths = [input.filePath]; var args = ['-silent', '-qm', output.filePath].concat(inputFilePaths); var cmd = new Command(product.Qt.core.binPath + '/' + product.Qt.core.lreleaseName, args); cmd.description = 'Creating ' + output.fileName; cmd.highlight = 'filegen'; return cmd; } } Rule { inputs: "qdocconf-main" explicitlyDependsOn: ["qdoc", "qdocconf"] outputFileTags: ModUtils.allFileTags(Qdoc.qdocFileTaggers()) outputArtifacts: Qdoc.outputArtifacts(product, input) prepare: { var outputDir = product.Qt.core.qdocOutputDir; var args = Qdoc.qdocArgs(product, input, outputDir); var cmd = new Command(product.Qt.core.binPath + '/' + product.Qt.core.qdocName, args); cmd.description = 'qdoc ' + input.fileName; cmd.highlight = 'filegen'; cmd.environment = product.Qt.core.qdocEnvironment; cmd.environment.push("OUTDIR=" + outputDir); // Qt 4 replacement for -outputdir return cmd; } } Rule { inputs: "qhp" auxiliaryInputs: ModUtils.allFileTags(Qdoc.qdocFileTaggers()) .filter(function(tag) { return tag !== "qhp"; }) Artifact { filePath: input.completeBaseName + ".qch" fileTags: ["qch"] } prepare: { var args = [input.filePath]; args = args.concat(product.Qt.core.helpGeneratorArgs); args.push("-o"); args.push(output.filePath); var cmd = new Command(product.Qt.core.binPath + "/qhelpgenerator", args); cmd.description = 'qhelpgenerator ' + input.fileName; cmd.highlight = 'filegen'; cmd.stdoutFilterFunction = function(output) { return ""; }; return cmd; } } @additionalContent@ } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/dbus.js000066400000000000000000000057341347155106100242270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); function outputFileName(input, suffix) { var parts = input.fileName.split('.').filter(function(s) { return s.length > 0; }); if (parts.length === 0) throw "Cannot run qdbusxml2cpp on '" + input.filePath + "': Unsuitable file name."; var outputBaseName = parts.length === 1 ? parts[0] : parts[parts.length - 2]; return outputBaseName.toLowerCase() + suffix; } function createCommands(product, input, outputs, option) { var exe = ModUtils.moduleProperty(product, "binPath") + '/' + ModUtils.moduleProperty(product, "xml2cppName"); var hppOutput = outputs["hpp"][0]; var hppArgs = ModUtils.moduleProperty(product, "xml2CppHeaderFlags"); hppArgs.push(option, hppOutput.fileName + ':', input.filePath); // Can't use filePath on Windows var hppCmd = new Command(exe, hppArgs) hppCmd.description = "qdbusxml2cpp " + input.fileName + " -> " + hppOutput.fileName; hppCmd.highlight = "codegen"; hppCmd.workingDirectory = FileInfo.path(hppOutput.filePath); var cppOutput = outputs["cpp"][0]; var cppArgs = ModUtils.moduleProperty(product, "xml2CppSourceFlags"); cppArgs.push("-i", hppOutput.filePath, option, ':' + cppOutput.fileName, input.filePath); var cppCmd = new Command(exe, cppArgs) cppCmd.description = "qdbusxml2cpp " + input.fileName + " -> " + cppOutput.fileName; cppCmd.highlight = "codegen"; cppCmd.workingDirectory = FileInfo.path(cppOutput.filePath); return [hppCmd, cppCmd]; } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/dbus.qbs000066400000000000000000000042371347155106100243750ustar00rootroot00000000000000import qbs.FileInfo import qbs.ModUtils import "../QtModule.qbs" as QtModule import "dbus.js" as DBus QtModule { qtModuleName: "DBus" property string xml2cppName: "qdbusxml2cpp" property stringList xml2CppHeaderFlags: [] property stringList xml2CppSourceFlags: [] Rule { inputs: ["qt.dbus.adaptor"] Artifact { filePath: FileInfo.joinPaths(input.moduleProperty("Qt.core", "generatedHeadersDir"), DBus.outputFileName(input, "_adaptor.h")) fileTags: ["hpp"] } Artifact { filePath: DBus.outputFileName(input, "_adaptor.cpp") fileTags: ["cpp"] } prepare: { return DBus.createCommands(product, input, outputs, "-a"); } } Rule { inputs: ["qt.dbus.interface"] Artifact { filePath: FileInfo.joinPaths(input.moduleProperty("Qt.core", "generatedHeadersDir"), DBus.outputFileName(input, "_interface.h")) fileTags: ["hpp"] } Artifact { filePath: DBus.outputFileName(input, "_interface.cpp") fileTags: ["cpp"] } prepare: { return DBus.createCommands(product, input, outputs, "-p"); } } architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ moduleConfig: @moduleConfig@ cpp.defines: @defines@ cpp.includePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @additionalContent@ } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/gui.qbs000066400000000000000000000040511347155106100242160ustar00rootroot00000000000000import qbs.FileInfo import qbs.ModUtils import '../QtModule.qbs' as QtModule QtModule { qtModuleName: "Gui" property string uicName: "uic" FileTagger { patterns: ["*.ui"] fileTags: ["ui"] } Rule { inputs: ["ui"] Artifact { filePath: FileInfo.joinPaths(input.moduleProperty("Qt.core", "generatedHeadersDir"), 'ui_' + input.completeBaseName + '.h') fileTags: ["hpp"] } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "binPath") + '/' + ModUtils.moduleProperty(product, "uicName"), [input.filePath, '-o', output.filePath]) cmd.description = 'uic ' + input.fileName; cmd.highlight = 'codegen'; return cmd; } } property string defaultQpaPlugin: @defaultQpaPlugin@ architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ cpp.defines: @defines@ cpp.includePaths: @includes@ cpp.libraryPaths: @libraryPaths@ Properties { condition: Qt.core.staticBuild && qbs.targetOS.contains("ios") cpp.frameworks: base.concat(["UIKit", "QuartzCore", "CoreText", "CoreGraphics", "Foundation", "CoreFoundation", "AudioToolbox"]) } cpp.frameworks: base @additionalContent@ } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/moc.js000066400000000000000000000103701347155106100240400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var ModUtils = require("qbs.ModUtils"); function args(product, input, outputFileName) { var defines = product.cpp.compilerDefinesByLanguage; if (input.fileTags.contains("objcpp")) defines = ModUtils.flattenDictionary(defines["objcpp"]) || []; else if (input.fileTags.contains("cpp")) defines = ModUtils.flattenDictionary(defines["cpp"]) || []; else defines = []; defines = defines.uniqueConcat(product.cpp.platformDefines); defines = defines.uniqueConcat(input.cpp.defines); var includePaths = input.cpp.includePaths; includePaths = includePaths.uniqueConcat(input.cpp.systemIncludePaths); var useCompilerPaths = product.Qt.core.versionMajor >= 5; if (useCompilerPaths) { includePaths = includePaths.uniqueConcat(input.cpp.compilerIncludePaths); } var frameworkPaths = product.cpp.frameworkPaths; frameworkPaths = frameworkPaths.uniqueConcat( product.cpp.systemFrameworkPaths); if (useCompilerPaths) { frameworkPaths = frameworkPaths.uniqueConcat( product.cpp.compilerFrameworkPaths); } var pluginMetaData = product.Qt.core.pluginMetaData; var args = []; args = args.concat( defines.map(function(item) { return '-D' + item; }), includePaths.map(function(item) { return '-I' + item; }), frameworkPaths.map(function(item) { return '-F' + item; }), pluginMetaData.map(function(item) { return '-M' + item; }), product.Qt.core.mocFlags, '-o', outputFileName, input.filePath); return args; } function fullPath(product) { return product.Qt.core.binPath + '/' + product.Qt.core.mocName; } function outputArtifacts(project, product, inputs, input) { var mocInfo = QtMocScanner.apply(input); if (!mocInfo.hasQObjectMacro) return []; var artifact = { fileTags: ["unmocable"] }; if (mocInfo.hasPluginMetaDataMacro) artifact.explicitlyDependsOn = ["qt_plugin_metadata"]; if (input.fileTags.contains("hpp")) { artifact.filePath = input.Qt.core.generatedHeadersDir + "/moc_" + input.completeBaseName + ".cpp"; var amalgamate = input.Qt.core.combineMocOutput; artifact.fileTags.push(mocInfo.mustCompile ? (amalgamate ? "moc_cpp" : "cpp") : "hpp"); } else { artifact.filePath = input.Qt.core.generatedHeadersDir + '/' + input.completeBaseName + ".moc"; artifact.fileTags.push("hpp"); } return [artifact]; } function commands(project, product, inputs, outputs, input, output) { var cmd = new Command(fullPath(product), args(product, input, output.filePath)); cmd.description = 'moc ' + input.fileName; cmd.highlight = 'codegen'; return cmd; } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/module.qbs000066400000000000000000000020141347155106100247140ustar00rootroot00000000000000import '../QtModule.qbs' as QtModule QtModule { qtModuleName: @name@ Depends { name: "Qt"; submodules: @dependencies@} architectures: @archs@ targetPlatform: @targetPlatform@ hasLibrary: @has_library@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ moduleConfig: @moduleConfig@ cpp.defines: @defines@ cpp.includePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @additionalContent@ } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/plugin.qbs000066400000000000000000000016531347155106100247350ustar00rootroot00000000000000import '../QtPlugin.qbs' as QtPlugin QtPlugin { qtModuleName: @name@ Depends { name: "Qt"; submodules: @dependencies@} className: @className@ architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ cpp.libraryPaths: @libraryPaths@ extendsModules: @extends@ @additionalContent@ } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/plugin_support.qbs000066400000000000000000000054401347155106100265270ustar00rootroot00000000000000Module { // Set by user. property varList pluginsByType property bool linkPlugins: product.type && (product.type.contains("application") || product.type.contains("sharedlibrary")) // Set by Qt modules. property stringList pluginTypes // Set by setup-qt. readonly property var allPluginsByType: @allPluginsByType@ readonly property stringList nonEssentialPlugins: @nonEssentialPlugins@ // Derived. readonly property var defaultPluginsByType: { var map = {}; for (var i = 0; i < (pluginTypes || []).length; ++i) { var pType = pluginTypes[i]; map[pType] = (allPluginsByType[pType] || []).filter(function(p) { return !nonEssentialPlugins.contains(p); }); } return map; } readonly property var effectivePluginsByType: { var ppt = pluginsByType || []; var eppt = {}; for (var i = 0; i < ppt.length; ++i) { var listEntry = ppt[i]; for (var pluginType in listEntry) { var newValue = listEntry[pluginType]; if (!newValue) newValue = []; else if (typeof newValue == "string") newValue = [newValue]; if (!Array.isArray(newValue)) throw "Invalid value '" + newValue + "' in Qt.plugin_support.pluginsByType"; eppt[pluginType] = (eppt[pluginType] || []).uniqueConcat(newValue); } } var dppt = defaultPluginsByType; for (var pluginType in dppt) { if (!eppt[pluginType]) eppt[pluginType] = dppt[pluginType]; } return eppt; } readonly property stringList enabledPlugins: { var list = []; var eppt = effectivePluginsByType; for (var t in eppt) Array.prototype.push.apply(list, eppt[t]); return list; } validate: { var ppt = pluginsByType; if (!ppt) return; var appt = allPluginsByType; for (var i = 0; i < ppt.length; ++i) { for (var pluginType in ppt[i]) { var requestedPlugins = ppt[i][pluginType]; if (!requestedPlugins) continue; var availablePlugins = appt[pluginType] || []; if (typeof requestedPlugins === "string") requestedPlugins = [requestedPlugins]; for (var j = 0; j < requestedPlugins.length; ++j) { if (!availablePlugins.contains(requestedPlugins[j])) { throw "Plugin '" + requestedPlugins[j] + "' of type '" + pluginType + "' was requested, but is not available."; } } } } } } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/qdoc.js000066400000000000000000000066151347155106100242170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); function qdocArgs(product, input, outputDir) { var args = [input.filePath]; var qtVersion = ModUtils.moduleProperty(product, "versionMajor"); if (qtVersion >= 5) { args.push("-outputdir"); args.push(outputDir); } return args; } var _qdocDefaultFileTag = "qdoc-output"; function qdocFileTaggers() { var t = _qdocDefaultFileTag; return { ".qhp": [t, "qhp"], ".qhp.sha1": [t, "qhp-sha1"], ".css": [t, "qdoc-css"], ".html": [t, "qdoc-html"], ".index": [t, "qdoc-index"], ".png": [t, "qdoc-png"] }; } function outputArtifacts(product, input) { var tracker = new ModUtils.BlackboxOutputArtifactTracker(); tracker.hostOS = product.moduleProperty("qbs", "hostOS"); tracker.shellPath = product.moduleProperty("qbs", "shellPath"); tracker.defaultFileTags = [_qdocDefaultFileTag]; tracker.fileTaggers = qdocFileTaggers(); tracker.command = FileInfo.joinPaths(ModUtils.moduleProperty(product, "binPath"), ModUtils.moduleProperty(product, "qdocName")); tracker.commandArgsFunction = function (outputDirectory) { return qdocArgs(product, input, outputDirectory); }; tracker.commandEnvironmentFunction = function (outputDirectory) { var env = {}; var qdocEnv = ModUtils.moduleProperty(product, "qdocEnvironment"); for (var j = 0; j < qdocEnv.length; ++j) { var e = qdocEnv[j]; var idx = e.indexOf("="); var name = e.slice(0, idx); var value = e.slice(idx + 1, e.length); env[name] = value; } env["OUTDIR"] = outputDirectory; // Qt 4 replacement for -outputdir return env; }; return tracker.artifacts(ModUtils.moduleProperty(product, "qdocOutputDir")); } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/qml.js000066400000000000000000000044221347155106100240540ustar00rootroot00000000000000var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); function scannerData(scannerFilePath, qmlFiles, qmlPath) { var p; try { p = new Process(); p.exec(scannerFilePath, ["-qmlFiles"].concat(qmlFiles).concat(["-importPath", qmlPath]), true); return JSON.parse(p.readStdOut()); } finally { if (p) p.close(); } } function getPrlRhs(line) { return line.split('=')[1].trim(); } function getLibsForPlugin(pluginData, buildVariant, targetOS, toolchain, qtLibDir) { if (!pluginData.path) return ""; var prlFileName = ""; if (!targetOS.contains("windows")) prlFileName += "lib"; prlFileName += pluginData.plugin; if (buildVariant === "debug" && targetOS.contains("windows")) prlFileName += "d"; prlFileName += ".prl"; var prlFilePath = FileInfo.joinPaths(pluginData.path, prlFileName); if (!File.exists(prlFilePath)) { console.warn("prl file for QML plugin '" + pluginData.plugin + "' not present at '" + prlFilePath + "'. Linking may fail."); return ""; } var prlFile = new TextFile(prlFilePath, TextFile.ReadOnly); try { var pluginLib; var otherLibs = ""; var line; while (!prlFile.atEof()) { line = prlFile.readLine().trim(); if (!line) continue; if (line.startsWith("QMAKE_PRL_TARGET")) pluginLib = FileInfo.joinPaths(pluginData.path, getPrlRhs(line)); if (line.startsWith("QMAKE_PRL_LIBS")) { var otherLibsLine = ' ' + getPrlRhs(line); if (toolchain.contains("msvc")) { otherLibsLine = otherLibsLine.replace(/ -L/g, " /LIBPATH:"); otherLibsLine = otherLibsLine.replace(/-l([^ ]+)/g, "$1" + ".lib"); } otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_LIBS\]/g, qtLibDir); otherLibs += otherLibsLine; } } if (!pluginLib) throw "Malformed prl file '" + prlFilePath + "'."; return pluginLib + ' ' + otherLibs; } finally { prlFile.close(); } } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/qml.qbs000066400000000000000000000126451347155106100242330ustar00rootroot00000000000000import qbs.TextFile import '../QtModule.qbs' as QtModule import "qml.js" as Qml QtModule { qtModuleName: "Qml" Depends { name: "Qt"; submodules: @dependencies@} property string qmlImportScannerName: "qmlimportscanner" property string qmlImportScannerFilePath: Qt.core.binPath + '/' + qmlImportScannerName property string qmlPath: @qmlPath@ property bool generateCacheFiles: false Depends { name: "Qt.qmlcache"; condition: generateCacheFiles; required: false } readonly property bool cachingEnabled: generateCacheFiles && Qt.qmlcache.present property string qmlCacheGenPath Properties { condition: cachingEnabled Qt.qmlcache.qmlCacheGenPath: qmlCacheGenPath || original Qt.qmlcache.installDir: cacheFilesInstallDir || original } property string cacheFilesInstallDir readonly property string pluginListFilePathDebug: product.buildDirectory + "/plugins.list.d" readonly property string pluginListFilePathRelease: product.buildDirectory + "/plugins.list" property bool linkPlugins: isStaticLibrary && Qt.plugin_support.linkPlugins hasLibrary: @has_library@ architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: (linkPlugins ? ['@' + pluginListFilePathDebug] : []).concat(@staticLibsDebug@) staticLibsRelease: (linkPlugins ? ['@' + pluginListFilePathRelease] : []).concat(@staticLibsRelease@) dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ moduleConfig: @moduleConfig@ cpp.defines: @defines@ cpp.includePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @additionalContent@ FileTagger { patterns: ["*.qml"] fileTags: ["qt.qml.qml"] } FileTagger { patterns: ["*.js"] fileTags: ["qt.qml.js"] } Rule { condition: linkPlugins multiplex: true requiresInputs: false inputs: ["qt.qml.qml"] outputFileTags: ["cpp", "qt.qml.pluginlist"] outputArtifacts: { var list = []; if (inputs["qt.qml.qml"]) list.push({ filePath: "qml_plugin_import.cpp", fileTags: ["cpp"] }); list.push({ filePath: product.Qt.core.qtBuildVariant === "debug" ? product.Qt.qml.pluginListFilePathDebug : product.Qt.qml.pluginListFilePathRelease, fileTags: ["qt.qml.pluginlist"] }); return list; } prepare: { var cmd = new JavaScriptCommand(); if (inputs["qt.qml.qml"]) cmd.description = "Creating " + outputs["cpp"][0].fileName; else cmd.silent = true; cmd.sourceCode = function() { var qmlInputs = inputs["qt.qml.qml"]; if (!qmlInputs) qmlInputs = []; var scannerData = Qml.scannerData(product.Qt.qml.qmlImportScannerFilePath, qmlInputs.map(function(inp) { return inp.filePath; }), product.Qt.qml.qmlPath); var cppFile; var listFile; try { if (qmlInputs.length > 0) cppFile = new TextFile(outputs["cpp"][0].filePath, TextFile.WriteOnly); listFile = new TextFile(outputs["qt.qml.pluginlist"][0].filePath, TextFile.WriteOnly); if (cppFile) cppFile.writeLine("#include "); var plugins = { }; for (var p in scannerData) { var plugin = scannerData[p].plugin; if (!plugin || plugins[plugin]) continue; plugins[plugin] = true; var className = scannerData[p].classname; if (!className) { throw "QML plugin '" + plugin + "' is missing a classname entry. " + "Please add one to the qmldir file."; } if (cppFile) cppFile.writeLine("Q_IMPORT_PLUGIN(" + className + ")"); var libs = Qml.getLibsForPlugin(scannerData[p], product.Qt.core.qtBuildVariant, product.qbs.targetOS, product.qbs.toolchain, product.Qt.core.libPath); listFile.write(libs + ' '); } } finally { if (cppFile) cppFile.close(); if (listFile) listFile.close(); }; }; return [cmd]; } } } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/qmlcache.qbs000066400000000000000000000056441347155106100252200ustar00rootroot00000000000000import qbs.File import qbs.FileInfo import qbs.Process import qbs.Utilities Module { additionalProductTypes: ["qt.qml.qmlc", "qt.qml.jsc"] validate: { if (!qmlcachegenProbe.found) throw "qmlcachegen unsupported for this target"; } property string qmlCacheGenPath: FileInfo.joinPaths(Qt.core.binPath, "qmlcachegen") + (qbs.hostOS.contains("windows") ? ".exe" : "") property bool supportsAllArchitectures: Utilities.versionCompare(Qt.core.version, "5.11") >= 0 property string installDir readonly property stringList _targetArgs: { if (supportsAllArchitectures) return []; function translateArch(arch) { if (arch === "x86") return "i386"; if (arch.startsWith("armv")) return "arm"; return arch; } var args = ["--target-architecture", translateArch(qbs.architecture)]; return args; } Depends { name: "Qt.core" } Probe { id: qmlcachegenProbe property string arch: qbs.architecture property string _qmlCacheGenPath: qmlCacheGenPath property stringList targetArgs: _targetArgs property bool _supportsAllArchitectures: supportsAllArchitectures configure: { if (_supportsAllArchitectures) { found = File.exists(_qmlCacheGenPath); return; } var process = new Process(); found = false; try { found = process.exec(_qmlCacheGenPath, targetArgs.concat("--check-if-supported")) == 0; if (!found) { var msg = "QML cache generation was requested but is unsupported on " + "architecture '" + arch + "'."; console.warn(msg); } } finally { process.close(); } } } Rule { condition: qmlcachegenProbe.found inputs: ["qt.qml.qml", "qt.qml.js"] outputArtifacts: [{ filePath: input.fileName + 'c', fileTags: input.fileTags.filter(function(tag) { return tag === "qt.qml.qml" || tag === "qt.qml.js"; })[0] + 'c' }] outputFileTags: ["qt.qml.qmlc", "qt.qml.jsc"] prepare: { var args = input.Qt.qmlcache._targetArgs.concat(input.filePath, "-o", output.filePath); var cmd = new Command(input.Qt.qmlcache.qmlCacheGenPath, args); cmd.description = "precompiling " + input.fileName; cmd.highlight = "compiler"; return cmd; } } Group { condition: product.Qt.qmlcache.installDir !== undefined fileTagsFilter: product.Qt.qmlcache.additionalProductTypes qbs.install: true qbs.installDir: product.Qt.qmlcache.installDir } } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/quick.js000066400000000000000000000061051347155106100243770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); function scanQrc(qrcFilePath) { var absInputDir = FileInfo.path(qrcFilePath); var result = []; var process = new Process(); try { var rcc = FileInfo.joinPaths(product.Qt.core.binPath, 'rcc' + product.cpp.executableSuffix); var exitCode = process.exec(rcc, ["--list", qrcFilePath], true); for (;;) { var line = process.readLine(); if (!line) break; line = line.trim(); line = FileInfo.relativePath(absInputDir, line); result.push(line); } } finally { process.close(); } return result; } function qtQuickCompilerOutputName(filePath) { var str = filePath.replace(/\//g, '_'); var i = str.lastIndexOf('.'); if (i != -1) str = str.substr(0, i) + '_' + str.substr(i + 1); str += ".cpp"; return str; } function qtQuickResourceFileOutputName(fileName) { return fileName.replace(/\.qrc$/, "_qtquickcompiler.qrc"); } function contentFromQrc(qrcFilePath) { var filesInQrc = scanQrc(qrcFilePath); var qmlJsFiles = filesInQrc.filter(function (filePath) { return (/\.(js|qml)$/).test(filePath); } ); var content = {}; if (filesInQrc.length - qmlJsFiles.length > 0) { content.newQrcFileName = qtQuickResourceFileOutputName(input.fileName); } content.qmlJsFiles = qmlJsFiles.map(function (filePath) { return { input: filePath, output: qtQuickCompilerOutputName(filePath) }; }); return content; } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/quick.qbs000066400000000000000000000204071347155106100245510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.Process import qbs.TextFile import qbs.Utilities import '../QtModule.qbs' as QtModule import 'quick.js' as QC QtModule { qtModuleName: @name@ Depends { name: "Qt"; submodules: @dependencies@.concat("qml-private") } hasLibrary: @has_library@ architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ moduleConfig: @moduleConfig@ cpp.defines: @defines@ cpp.includePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @additionalContent@ readonly property bool _compilerIsQmlCacheGen: Utilities.versionCompare(Qt.core.version, "5.11") >= 0 readonly property string _generatedLoaderFileName: _compilerIsQmlCacheGen ? "qmlcache_loader.cpp" : "qtquickcompiler_loader.cpp" property string compilerBaseName: (_compilerIsQmlCacheGen ? "qmlcachegen" : "qtquickcompiler") property string compilerFilePath: FileInfo.joinPaths(Qt.core.binPath, compilerBaseName + product.cpp.executableSuffix) property bool compilerAvailable: File.exists(compilerFilePath); property bool useCompiler: compilerAvailable && !_compilerIsQmlCacheGen Scanner { condition: useCompiler inputs: 'qt.quick.qrc' searchPaths: [FileInfo.path(input.filePath)] scan: QC.scanQrc(input.filePath) } FileTagger { condition: useCompiler patterns: "*.qrc" fileTags: ["qt.quick.qrc"] priority: 100 } Rule { condition: useCompiler inputs: ["qt.quick.qrc"] Artifact { filePath: input.fileName + ".json" fileTags: ["qt.quick.qrcinfo"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var content = QC.contentFromQrc(input.filePath); content.qrcFilePath = input.filePath; var tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.write(JSON.stringify(content)); tf.close(); } return cmd; } } Rule { condition: useCompiler inputs: ["qt.quick.qrcinfo"] outputFileTags: ["cpp", "qrc"] multiplex: true outputArtifacts: { var infos = []; inputs["qt.quick.qrcinfo"].forEach(function (input) { var tf = new TextFile(input.filePath, TextFile.ReadOnly); infos.push(JSON.parse(tf.readAll())); tf.close(); }); var result = []; infos.forEach(function (info) { if (info.newQrcFileName) { result.push({ filePath: info.newQrcFileName, fileTags: ["qrc"] }); } info.qmlJsFiles.forEach(function (qmlJsFile) { result.push({ filePath: qmlJsFile.output, fileTags: ["cpp"] }); }); }); result.push({ filePath: product.Qt.quick._generatedLoaderFileName, fileTags: ["cpp"] }); return result; } prepare: { var infos = []; inputs["qt.quick.qrcinfo"].forEach(function (input) { var tf = new TextFile(input.filePath, TextFile.ReadOnly); infos.push(JSON.parse(tf.readAll())); tf.close(); }); var cmds = []; var qmlCompiler = product.Qt.quick.compilerFilePath; var useCacheGen = product.Qt.quick._compilerIsQmlCacheGen; var cmd; var loaderFlags = []; function findOutput(fileName) { for (var k in outputs) { for (var i in outputs[k]) { if (outputs[k][i].fileName === fileName) return outputs[k][i]; } } throw new Error("Qt Quick compiler rule: Cannot find output artifact " + fileName + "."); } infos.forEach(function (info) { if (info.newQrcFileName) { loaderFlags.push("--resource-file-mapping=" + FileInfo.fileName(info.qrcFilePath) + ":" + info.newQrcFileName); var args = ["--filter-resource-file", info.qrcFilePath]; if (useCacheGen) args.push("-o"); args.push(findOutput(info.newQrcFileName).filePath); cmd = new Command(qmlCompiler, args); cmd.description = "generating " + info.newQrcFileName; cmds.push(cmd); } else { loaderFlags.push("--resource-file-mapping=" + info.qrcFilePath); } info.qmlJsFiles.forEach(function (qmlJsFile) { var args = ["--resource=" + info.qrcFilePath, qmlJsFile.input]; if (useCacheGen) args.push("-o"); args.push(findOutput(qmlJsFile.output).filePath); cmd = new Command(qmlCompiler, args); cmd.description = "generating " + qmlJsFile.output; cmd.workingDirectory = FileInfo.path(info.qrcFilePath); cmds.push(cmd); }); }); var args = loaderFlags.concat(infos.map(function (info) { return info.qrcFilePath; })); if (useCacheGen) args.push("-o"); args.push(findOutput(product.Qt.quick._generatedLoaderFileName).filePath); cmd = new Command(qmlCompiler, args); cmd.description = "generating loader source"; cmds.push(cmd); return cmds; } } } qbs-src-1.13.1/share/qbs/module-providers/Qt/templates/scxml.qbs000066400000000000000000000056771347155106100245770ustar00rootroot00000000000000import qbs.FileInfo import qbs.Utilities import "../QtModule.qbs" as QtModule QtModule { qtModuleName: "Scxml" property string qscxmlcName: "qscxmlc" property string className property string namespace property bool generateStateMethods property stringList additionalCompilerFlags Rule { inputs: ["qt.scxml.compilable"] Artifact { filePath: FileInfo.joinPaths(input.moduleProperty("Qt.core", "generatedHeadersDir"), input.baseName + ".h") fileTags: ["hpp", "unmocable"] } Artifact { filePath: input.baseName + ".cpp" fileTags: ["cpp", "unmocable"] } prepare: { var compilerName = product.moduleProperty("Qt.scxml", "qscxmlcName"); var compilerPath = FileInfo.joinPaths(input.moduleProperty("Qt.core", "binPath"), compilerName); var args = ["--header", outputs["hpp"][0].filePath, "--impl", outputs["cpp"][0].filePath]; var cxx98 = input.moduleProperty("cpp", "cxxLanguageVersion") === "c++98"; if (cxx98) args.push("-no-c++11"); var className = input.moduleProperty("Qt.scxml", "className"); if (className) args.push("--classname", className); var namespace = input.moduleProperty("Qt.scxml", "namespace"); if (namespace) args.push("--namespace", namespace); if (input.Qt.scxml.generateStateMethods && Utilities.versionCompare(product.Qt.scxml.version, "5.9") >= 0) { args.push("--statemethods"); } if (input.Qt.scxml.additionalCompilerFlags) args = args.concat(input.Qt.scxml.additionalCompilerFlags); args.push(input.filePath); var cmd = new Command(compilerPath, args); cmd.description = "compiling " + input.fileName; cmd.highlight = "codegen"; return [cmd]; } } architectures: @archs@ targetPlatform: @targetPlatform@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ pluginTypes: @pluginTypes@ moduleConfig: @moduleConfig@ cpp.defines: @defines@ cpp.includePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @additionalContent@ } qbs-src-1.13.1/share/qbs/module-providers/__fallback/000077500000000000000000000000001347155106100223765ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/module-providers/__fallback/fallback.qbs000066400000000000000000000057261347155106100246560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs import qbs.FileInfo import qbs.Probes Module { Depends { name: "cpp" } Depends { name: "pkgconfig"; required: false } property string theName: FileInfo.completeBaseName(filePath) Probes.PkgConfigProbe { id: pkgConfigProbe condition: pkgconfig.present name: theName executable: pkgconfig.executableFilePath libDirs: pkgconfig.libDirs forStaticBuild: pkgconfig.staticMode } Properties { condition: pkgConfigProbe.found version: pkgConfigProbe.modversion cpp.dynamicLibraries: pkgConfigProbe.libraries cpp.libraryPaths: pkgConfigProbe.libraryPaths cpp.includePaths: pkgConfigProbe.includePaths cpp.defines: pkgConfigProbe.defines cpp.driverLinkerFlags: pkgConfigProbe.linkerFlags cpp.commonCompilerFlags: pkgConfigProbe.compilerFlags } validate: { if (!pkgConfigProbe.found) { throw "Dependency '" + theName + "' not found for product '" + product.name + "'. " + "Locating a package of this name via pkg-config also failed."; } } } qbs-src-1.13.1/share/qbs/module-providers/__fallback/provider.qbs000066400000000000000000000045371347155106100247500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs.File import qbs.FileInfo ModuleProvider { relativeSearchPaths: { console.debug("Running fallback provider for module '" + name + "'."); var inputFilePath = FileInfo.joinPaths(path, "fallback.qbs"); var outputDir = FileInfo.joinPaths(outputBaseDir, "modules", name.replace(".", "/")); File.makePath(outputDir); var outputFilePath = FileInfo.joinPaths(outputDir, name + ".qbs"); File.copy(inputFilePath, outputFilePath); return ""; } } qbs-src-1.13.1/share/qbs/modules/000077500000000000000000000000001347155106100165115ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/Android/000077500000000000000000000000001347155106100200715ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/Android/android-utils.js000066400000000000000000000041651347155106100232130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); function availablePlatforms(baseDir) { var re = /^android-([0-9]+)$/; var platforms = File.directoryEntries(FileInfo.joinPaths(baseDir, "platforms"), File.Dirs | File.NoDotAndDotDot); var versions = []; for (var i = 0; i < platforms.length; ++i) { var match = platforms[i].match(re); if (match !== null) { versions.push(platforms[i]); } } versions.sort(function (a, b) { return parseInt(a.match(re)[1], 10) - parseInt(b.match(re)[1], 10); }); return versions; } qbs-src-1.13.1/share/qbs/modules/Android/ndk/000077500000000000000000000000001347155106100206455ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/Android/ndk/ndk.qbs000066400000000000000000000153721347155106100221400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Utilities import "utils.js" as NdkUtils Module { Probes.AndroidNdkProbe { id: ndkProbe environmentPaths: (ndkDir ? [ndkDir] : []).concat(base) } version: ndkProbe.ndkVersion readonly property string abi: NdkUtils.androidAbi(qbs.architecture) PropertyOptions { name: "abi" description: "Corresponds to the 'APP_ABI' variable in an Android.mk file." allowedValues: ["arm64-v8a", "armeabi", "armeabi-v7a", "mips", "mips64", "x86", "x86_64"] } property string appStl: version && Utilities.versionCompare(version, "17") >= 0 ? "c++_shared" : "system" PropertyOptions { name: "appStl" description: "Corresponds to the 'APP_STL' variable in an Android.mk file." allowedValues: [ "system", "gabi++_static", "gabi++_shared", "stlport_static", "stlport_shared", "gnustl_static", "gnustl_shared", "c++_static", "c++_shared" ] } property string toolchainVersion: latestToolchainVersion PropertyOptions { name: "toolchainVersion" description: "Corresponds to the 'NDK_TOOLCHAIN_VERSION' variable in an Android.mk file." } property string hostArch: ndkProbe.hostArch property string ndkDir: ndkProbe.path property string ndkSamplesDir: ndkProbe.samplesDir property string platform: ndkProbe.ndkPlatform property bool useUnifiedHeaders: version && Utilities.versionCompare(version, "15") >= 0 // Internal properties. property stringList availableToolchains: ndkProbe.toolchains property stringList availableToolchainVersions: { var tcs = availableToolchains; var versions = []; for (var i = 0; i < tcs.length; ++i) { if ((qbs.toolchain.contains("clang") && tcs[i].startsWith("llvm-")) || toolchainDirPrefixAbis.contains(tcs[i].split("-")[0])) { var re = /\-((?:[0-9]+)\.(?:[0-9]+))$/; var m = tcs[i].match(re); if (m) versions.push(m[1]); } } // Sort by version number versions.sort(function (a, b) { var re = /^([0-9]+)\.([0-9]+)$/; a = a.match(re); a = {major: a[1], minor: a[2]}; b = b.match(re); b = {major: b[1], minor: b[2]}; if (a.major === b.major) return a.minor - b.minor; return a.major - b.major; }); return versions; } property string latestToolchainVersion: availableToolchainVersions [availableToolchainVersions.length - 1] property int platformVersion: { if (platform) { var match = platform.match(/^android-([0-9]+)$/); if (match !== null) { return parseInt(match[1], 10); } } } property stringList abis: { var list = ["armeabi", "armeabi-v7a"]; if (platformVersion >= 9) list.push("mips", "x86"); if (platformVersion >= 21) list.push("arm64-v8a", "mips64", "x86_64"); return list; } property stringList toolchainDirPrefixAbis: { var list = ["arm"]; if (platformVersion >= 9) list.push("mipsel", "x86"); if (platformVersion >= 21) list.push("aarch64", "mips64el", "x86_64"); return list; } property string toolchainVersionNumber: { var prefix = "clang"; if (toolchainVersion && toolchainVersion.startsWith(prefix)) return toolchainVersion.substr(prefix.length); return toolchainVersion; } property string armMode: abi && abi.startsWith("armeabi") ? (qbs.buildVariant === "debug" ? "arm" : "thumb") : undefined; PropertyOptions { name: "armMode" description: "Determines the instruction set for armeabi configurations." allowedValues: ["arm", "thumb"] } property bool haveUnifiedStl: version && Utilities.versionCompare(version, "12") >= 0 validate: { if (!ndkDir) { throw ModUtils.ModuleError("Could not find an Android NDK at any of the following " + "locations:\n\t" + ndkProbe.candidatePaths.join("\n\t") + "\nInstall the Android NDK to one of the above locations, " + "or set the Android.ndk.ndkDir property or " + "ANDROID_NDK_ROOT environment variable to a valid " + "Android NDK location."); } if (product.aggregate && !product.multiplexConfigurationId) return; var validator = new ModUtils.PropertyValidator("Android.ndk"); validator.setRequiredProperty("abi", abi); validator.setRequiredProperty("appStl", appStl); validator.setRequiredProperty("toolchainVersion", toolchainVersion); validator.setRequiredProperty("hostArch", hostArch); validator.setRequiredProperty("platform", platform); validator.setRequiredProperty("toolchainVersionNumber", toolchainVersionNumber); return validator.validate(); } } qbs-src-1.13.1/share/qbs/modules/Android/ndk/utils.js000066400000000000000000000066071347155106100223540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ function abiNameToDirName(abiName) { switch (abiName) { case "armeabi": case "armeabi-v7a": return "arm"; case "arm64-v8a": return "arm64"; default: return abiName; } } function androidAbi(arch) { switch (arch) { case "arm64": return "arm64-v8a"; case "armv5": case "armv5te": return "armeabi"; case "armv7": case "armv7a": return "armeabi-v7a"; case "mips": case "mipsel": return "mips"; case "mips64": case "mips64el": return "mips64"; default: return arch; } } function commonCompilerFlags(toolchain, buildVariant, abi, armMode) { var flags = ["-ffunction-sections", "-funwind-tables", "-Werror=format-security", "-fstack-protector-strong"]; if (abi === "arm64-v8a") flags.push("-fpic"); if (abi === "armeabi" || abi === "armeabi-v7a") { flags.push("-fpic"); if (abi === "armeabi") flags.push("-mtune=xscale", "-msoft-float"); if (abi === "armeabi-v7a") { flags.push("-mfpu=vfpv3-d16"); flags.push("-mfloat-abi=softfp"); } } if (abi === "mips" || abi === "mips64") { flags.push("-fpic", "-finline-functions", "-fmessage-length=0", "-fno-inline-functions-called-once", "-fgcse-after-reload", "-frerun-cse-after-loop", "-frename-registers"); } if ((abi === "x86" || abi === "x86_64") && toolchain.contains("clang")) flags.push("-fPIC"); if (armMode) flags.push("-m" + armMode); return flags; } function commonLinkerFlags(abi) { return ["-z", "noexecstack", "-z", "relro", "-z", "now"]; } function getBinutilsPath(ndk, toolchainPrefix) { if (["x86", "x86_64"].contains(ndk.abi)) return ndk.abi + "-" + ndk.toolchainVersionNumber; return toolchainPrefix + ndk.toolchainVersionNumber; } qbs-src-1.13.1/share/qbs/modules/Android/sdk/000077500000000000000000000000001347155106100206525ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/Android/sdk/sdk.qbs000066400000000000000000000430131347155106100221430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.TextFile import qbs.Utilities import qbs.Xml import "utils.js" as SdkUtils Module { Probes.AndroidSdkProbe { id: sdkProbe environmentPaths: (sdkDir ? [sdkDir] : []).concat(base) } Probes.AndroidNdkProbe { id: ndkProbe sdkPath: sdkProbe.path environmentPaths: (ndkDir ? [ndkDir] : []).concat(base) } property path sdkDir: sdkProbe.path property path ndkDir: ndkProbe.path property path ndkSamplesDir: ndkProbe.samplesDir property string buildToolsVersion: sdkProbe.buildToolsVersion property var buildToolsVersionParts: buildToolsVersion ? buildToolsVersion.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int buildToolsVersionMajor: buildToolsVersionParts[0] property int buildToolsVersionMinor: buildToolsVersionParts[1] property int buildToolsVersionPatch: buildToolsVersionParts[2] property string platform: sdkProbe.platform // Product-specific properties and files property string packageName: product.name property string apkBaseName: packageName property bool automaticSources: true property bool legacyLayout: false property string sourceSetDir: legacyLayout ? product.sourceDirectory : FileInfo.joinPaths(product.sourceDirectory, "src/main") property string resourcesDir: FileInfo.joinPaths(sourceSetDir, "res") property string assetsDir: FileInfo.joinPaths(sourceSetDir, "assets") property string sourcesDir: FileInfo.joinPaths(sourceSetDir, legacyLayout ? "src" : "java") property string manifestFile: defaultManifestFile readonly property string defaultManifestFile: FileInfo.joinPaths(sourceSetDir, "AndroidManifest.xml") property bool _enableRules: !product.multiplexConfigurationId && !!packageName Group { name: "java sources" condition: Android.sdk.automaticSources prefix: Android.sdk.sourcesDir + '/' files: "**/*.java" } Group { name: "android resources" condition: Android.sdk.automaticSources fileTags: ["android.resources"] prefix: Android.sdk.resourcesDir + '/' files: "**/*" } Group { name: "android assets" condition: Android.sdk.automaticSources fileTags: ["android.assets"] prefix: Android.sdk.assetsDir + '/' files: "**/*" } Group { name: "manifest" condition: Android.sdk.automaticSources fileTags: ["android.manifest"] files: Android.sdk.manifestFile && Android.sdk.manifestFile !== Android.sdk.defaultManifestFile ? [Android.sdk.manifestFile] : (File.exists(Android.sdk.defaultManifestFile) ? [Android.sdk.defaultManifestFile] : []) } // Internal properties. property int platformVersion: { if (platform) { var match = platform.match(/^android-([0-9]+)$/); if (match !== null) { return parseInt(match[1], 10); } } } property string platformJavaVersion: { if (platformVersion >= 21) return "1.7"; return "1.5"; } property path buildToolsDir: FileInfo.joinPaths(sdkDir, "build-tools", buildToolsVersion) property path aaptFilePath: FileInfo.joinPaths(buildToolsDir, "aapt") property path apksignerFilePath: FileInfo.joinPaths(buildToolsDir, "apksigner") property path aidlFilePath: FileInfo.joinPaths(buildToolsDir, "aidl") property path dxFilePath: FileInfo.joinPaths(buildToolsDir, "dx") property path zipalignFilePath: FileInfo.joinPaths(buildToolsDir, "zipalign") property path androidJarFilePath: FileInfo.joinPaths(sdkDir, "platforms", platform, "android.jar") property path frameworkAidlFilePath: FileInfo.joinPaths(sdkDir, "platforms", platform, "framework.aidl") property path generatedJavaFilesBaseDir: FileInfo.joinPaths(product.buildDirectory, "gen") property path generatedJavaFilesDir: FileInfo.joinPaths(generatedJavaFilesBaseDir, (packageName || "").split('.').join('/')) property string apkContentsDir: FileInfo.joinPaths(product.buildDirectory, "bin") property string debugKeyStorePath: FileInfo.joinPaths( Environment.getEnv(qbs.hostOS.contains("windows") ? "USERPROFILE" : "HOME"), ".android", "debug.keystore") property bool useApksigner: buildToolsVersion && Utilities.versionCompare( buildToolsVersion, "24.0.3") >= 0 property stringList aidlSearchPaths Depends { name: "java"; condition: _enableRules } Properties { condition: _enableRules java.languageVersion: platformJavaVersion java.runtimeVersion: platformJavaVersion java.bootClassPaths: androidJarFilePath } validate: { if (!sdkDir) { throw ModUtils.ModuleError("Could not find an Android SDK at any of the following " + "locations:\n\t" + sdkProbe.candidatePaths.join("\n\t") + "\nInstall the Android SDK to one of the above locations, " + "or set the Android.sdk.sdkDir property or " + "ANDROID_HOME environment variable to a valid " + "Android SDK location."); } } FileTagger { patterns: ["AndroidManifest.xml"] fileTags: ["android.manifest"] } FileTagger { patterns: ["*.aidl"] fileTags: ["android.aidl"] } FileTagger { patterns: ["*.keystore"] fileTags: ["android.keystore"] } // Typically there is a debug keystore in ~/.android/debug.keystore which gets created // by the native build tools the first time a build is done. However, we don't want to create it // ourselves, because writing to a location outside the qbs build directory is both polluting // and has the potential for race conditions. So we'll instruct the user what to do. Group { name: "Android debug keystore" files: { if (!File.exists(Android.sdk.debugKeyStorePath)) { throw ModUtils.ModuleError("Could not find an Android debug keystore at " + Android.sdk.debugKeyStorePath + ". " + "If you are developing for Android on this machine for the first time and " + "have never built an application using the native Gradle / Android Studio " + "tooling, this is normal. You must create the debug keystore now using the " + "following command, in order to continue:\n\n" + SdkUtils.createDebugKeyStoreCommandString(java.keytoolFilePath, Android.sdk.debugKeyStorePath) + "\n\n" + "See the following URL for more information: " + "https://developer.android.com/studio/publish/app-signing.html#debug-mode"); } return [Android.sdk.debugKeyStorePath]; } fileTags: ["android.keystore"] } Parameter { property bool embedJar: true } Rule { condition: _enableRules inputs: ["android.aidl"] Artifact { filePath: FileInfo.joinPaths(Utilities.getHash(input.filePath), input.completeBaseName + ".java") fileTags: ["java.java"] } prepare: { var aidl = product.Android.sdk.aidlFilePath; var args = ["-p" + product.Android.sdk.frameworkAidlFilePath]; var aidlSearchPaths = input.Android.sdk.aidlSearchPaths; for (var i = 0; i < (aidlSearchPaths ? aidlSearchPaths.length : 0); ++i) args.push("-I" + aidlSearchPaths[i]); args.push(input.filePath, output.filePath); cmd = new Command(aidl, args); cmd.description = "Processing " + input.fileName; return [cmd]; } } property bool customManifestProcessing: false Group { condition: !Android.sdk.customManifestProcessing fileTagsFilter: "android.manifest_processed" fileTags: "android.manifest_final" } Rule { condition: _enableRules inputs: "android.manifest" Artifact { filePath: FileInfo.joinPaths("processed_manifest", input.fileName) fileTags: "android.manifest_processed" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Ensuring correct package name in Android manifest file"; cmd.sourceCode = function() { var manifestData = new Xml.DomDocument(); manifestData.load(input.filePath); var rootElem = manifestData.documentElement(); if (!rootElem || !rootElem.isElement() || rootElem.tagName() != "manifest") throw "No manifest tag found in '" + input.filePath + "'."; // Quick sanity check. Don't try to be fancy; let's not risk rejecting valid names. var packageName = product.Android.sdk.packageName; if (!packageName.match(/^[^.]+(?:\.[^.]+)+$/)) { throw "Package name '" + packageName + "' is not valid. Please set " + "Android.sdk.packageName to a name following the " + "'com.mycompany.myproduct' pattern." } rootElem.setAttribute("package", packageName); manifestData.save(output.filePath, 4); } return cmd; } } Rule { condition: _enableRules multiplex: true inputs: ["android.resources", "android.assets", "android.manifest_final"] outputFileTags: ["java.java"] outputArtifacts: { var artifacts = []; var resources = inputs["android.resources"]; if (resources && resources.length) { artifacts.push({ filePath: FileInfo.joinPaths(product.Android.sdk.generatedJavaFilesDir, "R.java"), fileTags: ["java.java"] }); } return artifacts; } prepare: SdkUtils.prepareAaptGenerate.apply(SdkUtils, arguments) } Rule { condition: _enableRules multiplex: true Artifact { filePath: FileInfo.joinPaths(product.Android.sdk.generatedJavaFilesDir, "BuildConfig.java") fileTags: ["java.java"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Generating BuildConfig.java"; cmd.sourceCode = function() { var debugValue = product.qbs.buildVariant === "debug" ? "true" : "false"; var ofile = new TextFile(output.filePath, TextFile.WriteOnly); ofile.writeLine("package " + product.Android.sdk.packageName + ";") ofile.writeLine("public final class BuildConfig {"); ofile.writeLine(" public final static boolean DEBUG = " + debugValue + ";"); ofile.writeLine("}"); ofile.close(); }; return [cmd]; } } Rule { condition: _enableRules multiplex: true inputs: ["java.class"] inputsFromDependencies: ["java.jar"] Artifact { filePath: FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "classes.dex") fileTags: ["android.dex"] } prepare: SdkUtils.prepareDex.apply(SdkUtils, arguments) } Rule { condition: _enableRules property stringList inputTags: "android.nativelibrary" inputsFromDependencies: inputTags inputs: product.aggregate ? [] : inputTags Artifact { filePath: FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "lib", input.Android.ndk.abi, input.fileName) fileTags: "android.nativelibrary_deployed" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "copying " + input.fileName + " for packaging"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } Rule { condition: _enableRules multiplex: true property stringList inputTags: "android.gdbserver" inputsFromDependencies: inputTags inputs: product.aggregate ? [] : inputTags outputFileTags: "android.gdbserver_deployed" outputArtifacts: { var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs, "gdbserver"); var outputs = []; for (i = 0; i < deploymentData.outputFilePaths.length; ++i) { outputs.push({filePath: deploymentData.outputFilePaths[i], fileTags: "android.gdbserver_deployed"}); } return outputs; } prepare: { var cmd = new JavaScriptCommand; cmd.description = "deploying gdbserver binaries"; cmd.sourceCode = function() { var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs, "gdbserver"); for (var i = 0; i < deploymentData.uniqueInputs.length; ++i) { File.copy(deploymentData.uniqueInputs[i].filePath, deploymentData.outputFilePaths[i]); } }; return cmd; } } Rule { condition: _enableRules multiplex: true property stringList inputTags: "android.stl" inputsFromDependencies: inputTags inputs: product.aggregate ? [] : inputTags outputFileTags: "android.stl_deployed" outputArtifacts: { var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs, "stl"); var outputs = []; for (i = 0; i < deploymentData.outputFilePaths.length; ++i) { outputs.push({filePath: deploymentData.outputFilePaths[i], fileTags: "android.stl_deployed"}); } return outputs; } prepare: { var cmds = []; var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs); for (var i = 0; i < deploymentData.uniqueInputs.length; ++i) { var input = deploymentData.uniqueInputs[i]; var stripArgs = ["--strip-unneeded", "-o", deploymentData.outputFilePaths[i], input.filePath]; var cmd = new Command(input.cpp.stripPath, stripArgs); cmd.description = "deploying " + input.fileName; cmds.push(cmd); } return cmds; } } Rule { condition: _enableRules multiplex: true inputs: [ "android.resources", "android.assets", "android.manifest_final", "android.dex", "android.gdbserver_deployed", "android.stl_deployed", "android.nativelibrary_deployed", "android.keystore" ] Artifact { filePath: product.Android.sdk.apkBaseName + ".apk" fileTags: "android.apk" } prepare: SdkUtils.prepareAaptPackage.apply(SdkUtils, arguments) } } qbs-src-1.13.1/share/qbs/modules/Android/sdk/utils.js000066400000000000000000000214761347155106100223620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function availableBuildToolsVersions(sdkDir) { var re = /^([0-9]+)\.([0-9]+)\.([0-9]+)$/; var buildTools = File.directoryEntries(FileInfo.joinPaths(sdkDir, "build-tools"), File.Dirs | File.NoDotAndDotDot); var versions = []; for (var i = 0; i < buildTools.length; ++i) { var match = buildTools[i].match(re); if (match !== null) { versions.push(buildTools[i]); } } // Sort by version number versions.sort(function (a, b) { return Utilities.versionCompare(a, b); }); return versions; } function prepareDex(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var dxFilePath = product.Android.sdk.dxFilePath; var args = ["--dex", "--output", output.filePath, product.java.classFilesDir]; var jarFiles = []; function traverseJarDeps(dep) { if (dep.parameters.Android && dep.parameters.Android.sdk && dep.parameters.Android.sdk.embedJar === false) return; var isJar = typeof dep.artifacts["java.jar"] !== "undefined"; if (!isJar) return; dep.artifacts["java.jar"].forEach(function(artifact) { if (!jarFiles.contains(artifact.filePath)) jarFiles.push(artifact.filePath); }); dep.dependencies.forEach(traverseJarDeps); } product.dependencies.forEach(traverseJarDeps); args = args.concat(jarFiles); var cmd = new Command(dxFilePath, args); cmd.description = "Creating " + output.fileName; return [cmd]; } function findParentDir(filePath, parentDirName) { var lastDir; var currentDir = FileInfo.path(filePath); while (lastDir !== currentDir) { if (FileInfo.fileName(currentDir) === parentDirName) return currentDir; lastDir = currentDir; currentDir = FileInfo.path(currentDir); } } function commonAaptPackageArgs(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var manifestFilePath = inputs["android.manifest_final"][0].filePath; var args = ["package", "-f", "-M", manifestFilePath, "-I", product.Android.sdk.androidJarFilePath]; var resources = inputs["android.resources"]; var resourceDirs = []; if (resources) { for (var i = 0; i < resources.length; ++i) { var resDir = findParentDir(resources[i].filePath, "res"); if (!resDir) { throw "File '" + resources[i].filePath + "' is tagged as an Android resource, " + "but is not located under a directory called 'res'."; } if (!resourceDirs.contains(resDir)) resourceDirs.push(resDir); } } for (i = 0; i < resourceDirs.length; ++i) args.push("-S", resourceDirs[i]); var assets = inputs["android.assets"]; var assetDirs = []; if (assets) { for (i = 0; i < assets.length; ++i) { var assetDir = findParentDir(assets[i].filePath, "assets"); if (!assetDir) { throw "File '" + assets[i].filePath + "' is tagged as an Android asset, " + "but is not located under a directory called 'assets'."; } if (!assetDirs.contains(assetDir)) assetDirs.push(assetDir); } } for (i = 0; i < assetDirs.length; ++i) args.push("-A", assetDirs[i]); if (product.qbs.buildVariant === "debug") args.push("--debug-mode"); return args; } function prepareAaptGenerate(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = commonAaptPackageArgs.apply(this, arguments); args.push("--no-crunch", "-m"); var resources = inputs["android.resources"]; if (resources && resources.length) args.push("-J", ModUtils.moduleProperty(product, "generatedJavaFilesBaseDir")); var cmd = new Command(product.Android.sdk.aaptFilePath, args); cmd.description = "Processing resources"; return [cmd]; } function prepareAaptPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var apkOutput = outputs["android.apk"][0]; var args = commonAaptPackageArgs.apply(this, arguments); args.push("-F", apkOutput.filePath + ".unaligned"); args.push(product.Android.sdk.apkContentsDir); var cmd = new Command(product.Android.sdk.aaptFilePath, args); cmd.description = "Generating " + apkOutput.filePath; cmds.push(cmd); if (!product.Android.sdk.useApksigner) { args = ["-sigalg", "SHA1withRSA", "-digestalg", "SHA1", "-keystore", inputs["android.keystore"][0].filePath, "-storepass", "android", apkOutput.filePath + ".unaligned", "androiddebugkey"]; cmd = new Command(product.java.jarsignerFilePath, args); cmd.description = "Signing " + apkOutput.fileName; cmds.push(cmd); } cmd = new Command(product.Android.sdk.zipalignFilePath, ["-f", "4", apkOutput.filePath + ".unaligned", apkOutput.filePath]); cmd.silent = true; cmds.push(cmd); cmd = new JavaScriptCommand(); cmd.silent = true; cmd.unalignedApk = apkOutput.filePath + ".unaligned"; cmd.sourceCode = function() { File.remove(unalignedApk); }; cmds.push(cmd); if (product.Android.sdk.useApksigner) { // TODO: Implement full signing support, not just using the debug keystore args = ["sign", "--ks", inputs["android.keystore"][0].filePath, "--ks-pass", "pass:android", apkOutput.filePath]; cmd = new Command(product.Android.sdk.apksignerFilePath, args); cmd.description = "Signing " + apkOutput.fileName; cmds.push(cmd); } return cmds; } function createDebugKeyStoreCommandString(keytoolFilePath, keystoreFilePath) { var args = ["-genkey", "-keystore", keystoreFilePath, "-alias", "androiddebugkey", "-storepass", "android", "-keypass", "android", "-keyalg", "RSA", "-keysize", "2048", "-validity", "10000", "-dname", "CN=Android Debug,O=Android,C=US"]; return Process.shellQuote(keytoolFilePath, args); } function gdbserverOrStlDeploymentData(product, inputs, type) { var data = { uniqueInputs: [], outputFilePaths: []}; var uniqueFilePaths = []; var theInputs = inputs[type === "gdbserver" ? "android.gdbserver" : "android.stl"]; if (!theInputs) return data; for (var i = 0; i < theInputs.length; ++i) { var currentInput = theInputs[i]; if (uniqueFilePaths.contains(currentInput.filePath)) continue; uniqueFilePaths.push(currentInput.filePath); data.uniqueInputs.push(currentInput); var outputFileName = type === "gdbserver" ? "libgdbserver.so" : currentInput.fileName; data.outputFilePaths.push(FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "lib", currentInput.Android.ndk.abi, outputFileName)); } return data; } qbs-src-1.13.1/share/qbs/modules/Exporter/000077500000000000000000000000001347155106100203215ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/Exporter/pkgconfig/000077500000000000000000000000001347155106100222705ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/Exporter/pkgconfig/pkgconfig.js000066400000000000000000000231661347155106100246050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); function quote(value) { if (value.contains(" ") || value.contains("'") || value.contains('"')) { return '"' + value.replace(/(["'\\])/g, "\\$1") + '"'; } return value; } function writeEntry(product, file, key, propertyName, required, additionalValues) { var value = product.Exporter.pkgconfig[propertyName]; if (additionalValues && additionalValues.length > 0) value = (value || []).concat(additionalValues); var valueIsNotEmpty = value && (!Array.isArray(value) || value.length > 0); if (valueIsNotEmpty) { if (Array.isArray(value)) value = value.join(' '); file.writeLine(key + ": " + value); } else if (required) { throw "Failure creating " + FileInfo.fileName(file.filePath()) + ": The entry '" + key + "' is required, but property Exporter.pkgconfig." + propertyName + " is not set."; } } function collectAutodetectedData(topLevelProduct) { var data = { libs: [], cflags: [], requires: [], requiresPrivate: [] }; if (!topLevelProduct.Exporter.pkgconfig.autoDetect) return data; var excludedDeps = topLevelProduct.Exporter.pkgconfig.excludedDependencies || []; var explicitRequires = topLevelProduct.Exporter.pkgconfig.requiresEntry || []; var explicitRequiresPrivate = topLevelProduct.Exporter.pkgconfig.requiresPrivateEntry || []; var transformFunc = topLevelProduct.Exporter.pkgconfig.transformFunction; // Make use of the "prefix" convenience variable if applicable. function quoteAndPrefixify(value) { var quotedValue = quote(value); var installPrefix = topLevelProduct.qbs.installPrefix || ""; if (!topLevelProduct.Exporter.pkgconfig._usePrefix || typeof value !== "string" || !value.startsWith(installPrefix) || (value.length > installPrefix.length && value[installPrefix.length] !== '/')) { return quotedValue; } return quotedValue.replace(product.qbs.installPrefix, "${prefix}"); } function transformedValue(product, moduleName, propertyName) { var originalValue = product.exports[moduleName][propertyName]; var value = transformFunc ? eval("(" + transformFunc + ")(product, moduleName, propertyName, originalValue)") : originalValue; if (Array.isArray(value)) value.forEach(function(v, i, a) { a[i] = quoteAndPrefixify(v); }); else if (value) value = quoteAndPrefixify(value); return value; } function collectLibs(productOrModule) { var libs = []; var libArtifacts; var isProduct = !productOrModule.present; var considerDynamicLibs = !isProduct || (productOrModule.type && productOrModule.type.contains("dynamiclibrary")); if (considerDynamicLibs) { libArtifacts = productOrModule.artifacts.dynamiclibrary; } else { var considerStaticLibs = !isProduct || (productOrModule.type && productOrModule.type.contains("staticlibrary")); if (considerStaticLibs) libArtifacts = productOrModule.artifacts.staticlibrary; } for (var i = 0; i < (libArtifacts || []).length; ++i) { var libArtifact = libArtifacts[i]; if (libArtifact.qbs.install) { var installDir = FileInfo.path(ModUtils.artifactInstalledFilePath(libArtifact)); installDir = installDir.slice(libArtifact.qbs.installRoot.length); libs.push("-L" + quoteAndPrefixify(FileInfo.cleanPath(installDir)), "-l" + quote(productOrModule.targetName)); } } if (!productOrModule.exports.cpp) return libs; var libPaths = transformedValue(productOrModule, "cpp", "libraryPaths"); if (libPaths) libs.push.apply(libs, libPaths.map(function(p) { return "-L" + p; })); function libNamesToLibEntries(libNames) { return libNames.map(function(libName) { return "-l" + libName; }); }; var dlls = transformedValue(productOrModule, "cpp", "dynamicLibraries"); if (dlls) libs.push.apply(libs, libNamesToLibEntries(dlls)); var staticLibs = transformedValue(productOrModule, "cpp", "staticLibraries"); if (staticLibs) libs.push.apply(libs, libNamesToLibEntries(staticLibs)); var lFlags = transformedValue(productOrModule, "cpp", "linkerFlags"); if (lFlags) libs.push.apply(libs, lFlags); lFlags = transformedValue(productOrModule, "cpp", "driverFlags"); if (lFlags) libs.push.apply(libs, lFlags); lFlags = transformedValue(productOrModule, "cpp", "driverLinkerFlags"); if (lFlags) libs.push.apply(libs, lFlags); return libs; } function collectCFlags(productOrModule) { if (!productOrModule.exports.cpp) return []; var flags = []; var defs = transformedValue(productOrModule, "cpp", "defines"); if (defs) flags.push.apply(flags, defs.map(function(d) { return "-D" + d; })); var incPaths = transformedValue(productOrModule, "cpp", "includePaths"); if (incPaths) flags.push.apply(flags, incPaths.map(function(p) { return "-I" + p; })); var cflags = transformedValue(productOrModule, "cpp", "commonCompilerFlags"); if (cflags) flags.push.apply(flags, cflags); cflags = transformedValue(productOrModule, "cpp", "driverFlags"); if (cflags) flags.push.apply(flags, cflags); cflags = transformedValue(productOrModule, "cpp", "cxxFlags") || transformedValue(productOrModule, "cpp", "cFlags"); if (cflags) flags.push.apply(flags, cflags); return flags; } function collectAutodetectedDataRecursive(productOrModule, privateContext) { if (!privateContext) { data.libs.push.apply(data.libs, collectLibs(productOrModule)); data.cflags.push.apply(data.cflags, collectCFlags(productOrModule)); } var exportedDeps = productOrModule.exports ? productOrModule.exports.dependencies : []; var exportedDepNames = []; var privateDeps = []; for (var i = 0; i < exportedDeps.length; ++i) exportedDepNames.push(exportedDeps[i].name); for (i = 0; i < (productOrModule.dependencies || []).length; ++i) { var dep = productOrModule.dependencies[i]; if (exportedDepNames.contains(dep.name)) continue; privateDeps.push(dep); } function gatherData(dep) { if (dep.name === "Exporter.pkgconfig") return; var depHasPkgConfig = dep.Exporter && dep.Exporter.pkgconfig; if (depHasPkgConfig) { var entry = FileInfo.completeBaseName(dep.Exporter.pkgconfig.fileName); if (excludedDeps.contains(entry)) return; if (isPrivateDep && !data.requiresPrivate.contains(entry) && !explicitRequiresPrivate.contains(entry)) { data.requiresPrivate.push(entry); } if (!isPrivateDep && !data.requires.contains(entry) && !explicitRequires.contains(entry)) { data.requires.push(entry); } } else { if (excludedDeps.contains(dep.name)) return; if (isPrivateDep && explicitRequiresPrivate.contains(dep.name)) return; if (!isPrivateDep && explicitRequires.contains(dep.name)) return; collectAutodetectedDataRecursive(dep, isPrivateDep); } } var isPrivateDep = privateContext; exportedDeps.forEach(gatherData); isPrivateDep = true; privateDeps.forEach(gatherData); } collectAutodetectedDataRecursive(topLevelProduct, false); return data; } qbs-src-1.13.1/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs000066400000000000000000000073651347155106100247610ustar00rootroot00000000000000import qbs.FileInfo import qbs.TextFile import "pkgconfig.js" as HelperFunctions Module { property string fileName: product.targetName + ".pc" property bool autoDetect: true property var transformFunction // function(product, moduleName, propertyName, valueElement) property stringList excludedDependencies property string nameEntry: product.name property string descriptionEntry: product.name property string versionEntry: product.version property string urlEntry property stringList cflagsEntry: [] property stringList libsEntry: [] property stringList libsPrivateEntry: [] property stringList requiresEntry: [] property stringList requiresPrivateEntry: [] property stringList conflictsEntry: [] property var customVariables property bool _usePrefix: autoDetect && qbs.installPrefix additionalProductTypes: ["Exporter.pkgconfig.pc"] Rule { multiplex: true requiresInputs: false // Make sure all relevant library artifacts have been created by the time we run. auxiliaryInputs: { if (!autoDetect) return undefined; if (product.type.contains("staticlibrary")) return ["staticlibrary"]; if (product.type.contains("dynamiclibrary")) return ["dynamiclibrary"]; } Artifact { filePath: product.Exporter.pkgconfig.fileName fileTags: ["Exporter.pkgconfig.pc"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); if (product.Exporter.pkgconfig._usePrefix) f.writeLine("prefix=" + product.qbs.installPrefix + "\n"); var customVariables = product.Exporter.pkgconfig.customVariables; if (customVariables) { for (var customVar in customVariables) f.writeLine(customVar + "=" + customVariables[customVar]); f.writeLine(""); } var autoDetectedData = HelperFunctions.collectAutodetectedData(product); HelperFunctions.writeEntry(product, f, "Name", "nameEntry", true); HelperFunctions.writeEntry(product, f, "Description", "descriptionEntry", true); HelperFunctions.writeEntry(product, f, "Version", "versionEntry", true); HelperFunctions.writeEntry(product, f, "URL", "urlEntry"); HelperFunctions.writeEntry(product, f, "Cflags", "cflagsEntry", false, autoDetectedData.cflags); HelperFunctions.writeEntry(product, f, "Libs", "libsEntry", false, autoDetectedData.libs); HelperFunctions.writeEntry(product, f, "Libs.private", "libsPrivateEntry"); HelperFunctions.writeEntry(product, f, "Requires", "requiresEntry", false, autoDetectedData.requires); HelperFunctions.writeEntry(product, f, "Requires.private", "requiresPrivateEntry", false, autoDetectedData.requiresPrivate); HelperFunctions.writeEntry(product, f, "Conflicts", "conflictsEntry"); }; return [cmd]; } } validate: { if (requiresEntry && excludedDependencies && requiresEntry.containsAny(excludedDependencies)) { throw "The contents of Export.pkgconfig.requiresEntry and " + "Export.pkgconfig.excludedDependencies must not overlap."; } } } qbs-src-1.13.1/share/qbs/modules/Exporter/qbs/000077500000000000000000000000001347155106100211065ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/Exporter/qbs/qbsexporter.js000066400000000000000000000261341347155106100240300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); function tagListToString(tagList) { return JSON.stringify(tagList); } function stringToTagList(tagListString) { return JSON.parse(tagListString); } function writeTargetArtifactGroup(output, tagList, artifactList, moduleInstallDir, moduleFile) { // Do not add our qbs module file itself. if (tagListToString(tagList) === tagListToString(output.fileTags)) return; moduleFile.writeLine(" Group {"); moduleFile.writeLine(" filesAreTargets: true"); var filteredTagList = tagList.filter(function(t) { return t !== "installable"; }); moduleFile.writeLine(" fileTags: " + JSON.stringify(filteredTagList)); moduleFile.writeLine(" files: ["); for (i = 0; i < artifactList.length; ++i) { var artifact = artifactList[i]; var installedArtifactFilePath = ModUtils.artifactInstalledFilePath(artifact); // Use relative file paths for relocatability. var relativeInstalledArtifactFilePath = FileInfo.relativePath(moduleInstallDir, installedArtifactFilePath); moduleFile.writeLine(" " + JSON.stringify(relativeInstalledArtifactFilePath) + ","); } moduleFile.writeLine(" ]"); moduleFile.writeLine(" }"); } function writeTargetArtifactGroups(product, output, moduleFile) { var relevantArtifacts = []; for (var i = 0; i < (product.Exporter.qbs._artifactTypes || []).length; ++i) { var tag = product.Exporter.qbs._artifactTypes[i]; var artifactsForTag = product.artifacts[tag] || []; for (var j = 0; j < artifactsForTag.length; ++j) { if (!relevantArtifacts.contains(artifactsForTag[j])) relevantArtifacts.push(artifactsForTag[j]); } } var artifactsByTags = {}; var artifactCount = relevantArtifacts ? relevantArtifacts.length : 0; for (i = 0; i < artifactCount; ++i) { var artifact = relevantArtifacts[i]; if (!artifact.fileTags.contains("installable")) continue; // Put all artifacts with the same set of file tags into the same group, so we don't // create more groups than necessary. var key = tagListToString(artifact.fileTags); var currentList = artifactsByTags[key]; if (currentList) currentList.push(artifact); else currentList = [artifact]; artifactsByTags[key] = currentList; } var moduleInstallDir = FileInfo.path(ModUtils.artifactInstalledFilePath(output)); for (var tagListKey in artifactsByTags) { writeTargetArtifactGroup(output, stringToTagList(tagListKey), artifactsByTags[tagListKey], moduleInstallDir, moduleFile); } } function checkValuePrefix(name, value, forbiddenPrefix, prefixDescription) { if (value.startsWith(forbiddenPrefix)) { throw "Value '" + value + "' for exported property '" + name + "' in product '" + product.name + "' points into " + prefixDescription + ".\n" + "Did you forget to set the prefixMapping property in an Export item?"; } } function stringifyValue(project, product, moduleInstallDir, prop, value) { if (Array.isArray(value)) { var repr = "["; for (var i = 0; i < value.length; ++i) { repr += stringifyValue(project, product, moduleInstallDir, prop, value[i]) + ", "; } repr += "]"; return repr; } if (typeof(value) !== "string") { var value = JSON.stringify(value); if (prop.type === "variant") value = '(' + value + ')'; return value; } // Catch user oversights: Paths that point into the project source or build directories // make no sense in the module. if (!value.startsWith(product.qbs.installRoot)) { checkValuePrefix(prop.name, value, project.buildDirectory, "project build directory"); checkValuePrefix(prop.name, value, project.sourceDirectory, "project source directory"); } // Adapt file paths pointing into the install dir, that is, make them relative to the // module file for relocatability. We accept them with or without the install root. // The latter form will typically be a result of applying the prefixMapping property, // while the first one could be an untransformed path, for instance if the project // file is written in such a way that include paths are picked up from the installed // location rather than the source directory. var valuePrefixToStrip; var fullInstallPrefix = FileInfo.joinPaths(product.qbs.installRoot, product.qbs.installPrefix); if (fullInstallPrefix.length > 1 && value.startsWith(fullInstallPrefix)) { valuePrefixToStrip = fullInstallPrefix; } else { var installPrefix = FileInfo.joinPaths("/", product.qbs.installPrefix); if (installPrefix.length > 1 && value.startsWith(installPrefix)) valuePrefixToStrip = installPrefix; } if (valuePrefixToStrip) { var deployedModuleInstallDir = moduleInstallDir.slice(fullInstallPrefix.length); return "FileInfo.cleanPath(FileInfo.joinPaths(path, FileInfo.relativePath(" + JSON.stringify(deployedModuleInstallDir) + ", " + JSON.stringify(value.slice(valuePrefixToStrip.length) || "/") + ")))"; } return JSON.stringify(value); } function writeProperty(project, product, moduleInstallDir, prop, indentation, considerValue, moduleFile) { var line = indentation; var separatorIndex = prop.name.lastIndexOf("."); var isModuleProperty = separatorIndex !== -1; var needsDeclaration = !prop.isBuiltin && !isModuleProperty; if (needsDeclaration) line += "property " + prop.type + " "; var moduleName; if (isModuleProperty) { moduleName = prop.name.slice(0, separatorIndex); if ((product.Exporter.qbs.excludedDependencies || []).contains(moduleName)) return; } line += prop.name + ": "; // We emit the literal value, unless the source code clearly refers to values from inside the // original project, in which case the evaluated value is used. if (considerValue && /(project|product)\./.test(prop.sourceCode)) { var value; if (isModuleProperty) { var propertyName = prop.name.slice(separatorIndex + 1); value = product.exports[moduleName][propertyName]; } else { value = product.exports[prop.name]; } line += stringifyValue(project, product, moduleInstallDir, prop, value); } else { line += prop.sourceCode.replace(/importingProduct\./g, "product."); } moduleFile.writeLine(line); } function writeProperties(project, product, moduleInstallDir, list, indentation, considerValue, moduleFile) { for (var i = 0; i < list.length; ++i) { writeProperty(project, product, moduleInstallDir, list[i], indentation, considerValue, moduleFile); } } // This writes properties set on other modules in the Export item, i.e. property assignments // like "cpp.includePaths: '...'". function writeModuleProperties(project, product, output, moduleFile) { var moduleInstallDir = FileInfo.path(ModUtils.artifactInstalledFilePath(output)); var filteredProps = product.exports.properties.filter(function(p) { return p.name !== "name"; }); // The right-hand side can refer to values from the exporting product, in which case // the evaluated value, rather than the source code, needs to go into the module file. var considerValues = true; writeProperties(project, product, moduleInstallDir, filteredProps, " ", considerValues, moduleFile); } function writeItem(product, item, indentation, moduleFile) { moduleFile.writeLine(indentation + item.name + " {"); var newIndentation = indentation + " "; // These are sub-items of the Export item, whose properties entirely live in the context // of the importing product. Therefore, they must never use pre-evaluated values. var considerValues = false; writeProperties(undefined, product, undefined, item.properties, newIndentation, considerValues, moduleFile) for (var i = 0; i < item.childItems.length; ++i) writeItem(product, item.childItems[i], newIndentation, moduleFile); moduleFile.writeLine(indentation + "}"); } function isExcludedDependency(product, childItem) { if ((product.Exporter.qbs.excludedDependencies || []).length === 0) return false; if (childItem.name !== "Depends") return false; for (var i = 0; i < childItem.properties.length; ++i) { var prop = childItem.properties[i]; var unquotedRhs = prop.sourceCode.slice(1, -1); if (prop.name === "name" && product.Exporter.qbs.excludedDependencies.contains(unquotedRhs)) return true; } return false; } function writeChildItems(product, moduleFile) { for (var i = 0; i < product.exports.childItems.length; ++i) { var item = product.exports.childItems[i]; if (!isExcludedDependency(product, item)) writeItem(product, item, " ", moduleFile); } } function writeImportStatements(product, moduleFile) { var imports = product.exports.imports; // We potentially use FileInfo ourselves when transforming paths in stringifyValue(). if (!imports.contains("import qbs.FileInfo")) imports.push("import qbs.FileInfo"); for (var i = 0; i < product.exports.imports.length; ++i) moduleFile.writeLine(product.exports.imports[i]); } qbs-src-1.13.1/share/qbs/modules/Exporter/qbs/qbsexporter.qbs000066400000000000000000000064621347155106100242030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.TextFile import "qbsexporter.js" as HelperFunctions Module { property stringList artifactTypes property string fileName: product.targetName + ".qbs" property stringList excludedDependencies property string additionalContent property stringList _artifactTypes: artifactTypes ? artifactTypes : ["installable"] additionalProductTypes: ["Exporter.qbs.module"] Rule { multiplex: true requiresInputs: false // Make sure we only run when all other artifacts are already present. // TODO: This also matches target artifacts in dependencies. Should not hurt, // but might be a hint that we should have auxiliaryInputsFromDependencies. auxiliaryInputs: product.type.filter(function(t) { return t !== "Exporter.qbs.module"; }) Artifact { filePath: product.Exporter.qbs.fileName fileTags: ["Exporter.qbs.module"] qbs.install: true } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.writeLine("import qbs"); HelperFunctions.writeImportStatements(product, f); f.writeLine("\nModule {"); HelperFunctions.writeModuleProperties(project, product, output, f); HelperFunctions.writeTargetArtifactGroups(product, output, f); HelperFunctions.writeChildItems(product, f); if (product.Exporter.qbs.additionalContent) f.writeLine(product.Exporter.qbs.additionalContent); f.writeLine("}"); f.close(); }; return [cmd]; } } } qbs-src-1.13.1/share/qbs/modules/archiver/000077500000000000000000000000001347155106100203145ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/archiver/archiver.qbs000066400000000000000000000230521347155106100226300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.Probes Module { // jar is a suitable fallback for creating zip files as they are the same format // This will most likely end up being used on Windows Depends { name: "java"; required: false } Probes.BinaryProbe { id: tarProbe names: ["tar"] } Probes.BinaryProbe { id: zipProbe names: ["zip"] } Probes.BinaryProbe { id: sevenZipProbe names: ["7z"] platformSearchPaths: { var paths = base; if (qbs.hostOS.contains("windows")) { var env32 = Environment.getEnv("PROGRAMFILES(X86)"); var env64 = Environment.getEnv("PROGRAMFILES"); if (env64 === env32 && env64.endsWith(" (x86)")) env64 = env64.slice(0, -(" (x86)".length)); // QTBUG-3845 paths.push(FileInfo.joinPaths(env64, "7-Zip")); paths.push(FileInfo.joinPaths(env32, "7-Zip")); } return paths; } } property string type property string archiveBaseName: product.targetName property string workingDirectory property stringList flags: [] property path outputDirectory: product.destinationDirectory property string archiveExtension: { if (type === "7zip") return "7z"; if (type == "tar") { var extension = "tar"; if (compressionType !== "none") extension += "." + compressionType; return extension; } if (type === "zip") return "zip"; return undefined; } property string command: { if (type === "7zip") return sevenZipProbe.filePath; if (type === "tar") { if (tarProbe.found) return tarProbe.filePath; if (sevenZipProbe.found) return sevenZipProbe.filePath; } if (type === "zip") { // Prefer zip (probably Info-Zip) and fall back to 7z or jar when it's not available // (as is the likely case on Windows) if (zipProbe.found) return zipProbe.filePath; if (sevenZipProbe.found) return sevenZipProbe.filePath; if (java.present) return java.jarFilePath; } return undefined; } property string compressionLevel property string compressionType: { if (type === "tar") return "gz"; return undefined; } PropertyOptions { name: "type" description: "The type of archive to create." allowedValues: ["7zip", "tar", "zip"] } PropertyOptions { name: "compressionLevel" description: "How much effort to put into compression.\n" + "Higher numbers mean smaller archive files at the cost of taking more time.\n" + "This property is only used for the '7zip' and 'zip' types.\n" + "'7zip' only supports 0 and odd numbers." allowedValues: [undefined, "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] } PropertyOptions { name: "compressionType" description: "The compression format to use.\n" + "For tar archives, the respective tool needs to be present.\n" + "This property is only used for the 'tar' and 'zip' types." allowedValues: ["none", "gz", "bz2", "Z", "xz", "deflate", "store"] } Rule { inputs: ["archiver.input-list"] Artifact { filePath: FileInfo.joinPaths(product.moduleProperty("archiver", "outputDirectory"), product.moduleProperty("archiver", "archiveBaseName") + '.' + product.moduleProperty("archiver", "archiveExtension")); fileTags: ["archiver.archive"] } prepare: { var binary = product.moduleProperty("archiver", "command"); var binaryName = FileInfo.baseName(binary); var args = []; var commands = []; var type = product.moduleProperty("archiver", "type"); var compression = product.moduleProperty("archiver", "compressionType"); var compressionLevel = product.moduleProperty("archiver", "compressionLevel"); if (binaryName === "7z") { var rmCommand = new JavaScriptCommand(); rmCommand.silent = true; rmCommand.sourceCode = function() { if (File.exists(output.filePath)) File.remove(output.filePath); }; commands.push(rmCommand); args.push("a", "-y", "-mmt=on"); switch (type) { case "7zip": args.push("-t7z"); break; case "zip": args.push("-tzip"); break; case "tar": if (compression === "gz") args.push("-tgzip"); else if (compression === "bz2") args.push("-tbzip2"); else args.push("-ttar"); break; default: throw "7zip: unrecognized archive type: '" + type + "'"; } if (compressionLevel) args.push("-mx" + compressionLevel); args = args.concat(product.moduleProperty("archiver", "flags")); args.push(output.filePath); args.push("@" + input.filePath); } else if (binaryName === "tar" && type === "tar") { args.push("-c"); if (compression === "gz") args.push("-z"); else if (compression === "bz2") args.push("-j"); else if (compression === "Z") args.push("-Z"); else if (compression === "xz") args.push("-J"); args.push("-f", output.filePath, "-T", input.filePath); args = args.concat(product.moduleProperty("archiver", "flags")); } else if (binaryName === "jar" && type === "zip") { if (compression === "none" || compressionLevel === "0") args.push("-0"); args.push("-cfM", output.filePath, "@" + input.filePath); args = args.concat(product.moduleProperty("archiver", "flags")); } else if (binaryName === "zip" && type === "zip") { // The "zip" program included with most Linux and Unix distributions // (including macOS) is Info-ZIP's Zip, so this should be fairly portable. if (compression === "none") { args.push("-0"); } else { compression = compression === "bz2" ? "bzip2" : compression; if (["store", "deflate", "bzip2"].contains(compression)) args.push("-Z", compression); if (compressionLevel) args.push("-" + compressionLevel); } args.push("-r", output.filePath, ".", "-i@" + input.filePath); args = args.concat(product.moduleProperty("archiver", "flags")); } else if (["tar", "zip", "jar"].contains(binaryName)) { throw binaryName + ": unrecognized archive type: '" + type + "'"; } else if (binaryName) { throw "unrecognized archive tool: '" + binaryName + "'"; } else { throw "no archive tool available to produce archive type: '" + type + "'"; } var archiverCommand = new Command(binary, args); archiverCommand.description = "Creating archive file " + output.fileName; archiverCommand.highlight = "linker"; archiverCommand.workingDirectory = product.moduleProperty("archiver", "workingDirectory"); commands.push(archiverCommand); return commands; } } } qbs-src-1.13.1/share/qbs/modules/autotest/000077500000000000000000000000001347155106100203615ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/autotest/autotest.qbs000066400000000000000000000001621347155106100227370ustar00rootroot00000000000000Module { property stringList arguments property bool allowFailure: false property string workingDir } qbs-src-1.13.1/share/qbs/modules/bundle/000077500000000000000000000000001347155106100177625ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/bundle/BundleModule.qbs000066400000000000000000001157651347155106100230670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.BundleTools import qbs.DarwinTools import qbs.Environment import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.PropertyList import qbs.TextFile import qbs.Utilities import "bundle.js" as Bundle Module { Depends { name: "xcode"; required: false; } Probe { id: bundleSettingsProbe condition: qbs.targetOS.contains("darwin") property string xcodeDeveloperPath: xcode.developerPath property var xcodeArchSettings: xcode._architectureSettings property string productTypeIdentifier: _productTypeIdentifier property bool useXcodeBuildSpecs: _useXcodeBuildSpecs property bool isMacOs: qbs.targetOS.contains("macos") property bool xcodePresent: xcode.present // Note that we include several settings pointing to properties which reference the output // of this probe (WRAPPER_NAME, WRAPPER_EXTENSION, etc.). This is to ensure that derived // properties take into account the value of these settings if the user customized them. property var additionalSettings: ({ "DEVELOPMENT_LANGUAGE": "English", "EXECUTABLE_VARIANT_SUFFIX": "", // e.g. _debug, _profile "FRAMEWORK_VERSION": frameworkVersion, "GENERATE_PKGINFO_FILE": generatePackageInfo !== undefined ? (generatePackageInfo ? "YES" : "NO") : undefined, "PRODUCT_NAME": product.targetName, "LOCAL_APPS_DIR": Environment.getEnv("HOME") + "/Applications", "LOCAL_LIBRARY_DIR": Environment.getEnv("HOME") + "/Library", "TARGET_BUILD_DIR": product.buildDirectory, "WRAPPER_NAME": bundleName, "WRAPPER_EXTENSION": extension }) // Outputs property var xcodeSettings: ({}) property var productTypeIdentifierChain: [] configure: { var specsPath = path; var specsSeparator = "-"; if (xcodeDeveloperPath && useXcodeBuildSpecs) { specsPath = xcodeDeveloperPath + "/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications"; specsSeparator = " "; } var reader = new Bundle.XcodeBuildSpecsReader(specsPath, specsSeparator, additionalSettings, !isMacOs); var settings = reader.expandedSettings(productTypeIdentifier, xcodePresent ? xcodeArchSettings : {}); var chain = reader.productTypeIdentifierChain(productTypeIdentifier); if (settings && chain) { xcodeSettings = settings; productTypeIdentifierChain = chain; found = true; } else { xcodeSettings = {}; productTypeIdentifierChain = []; found = false; } } } additionalProductTypes: !(product.multiplexed || product.aggregate) || !product.multiplexConfigurationId ? ["bundle.content"] : [] property bool isBundle: !product.consoleApplication && qbs.targetOS.contains("darwin") readonly property bool isShallow: bundleSettingsProbe.xcodeSettings["SHALLOW_BUNDLE"] === "YES" property string identifierPrefix: "org.example" property string identifier: [identifierPrefix, Utilities.rfc1034Identifier(product.targetName)].join(".") property string extension: bundleSettingsProbe.xcodeSettings["WRAPPER_EXTENSION"] property string packageType: Bundle.packageType(_productTypeIdentifier) property string signature: "????" // legacy creator code in Mac OS Classic (CFBundleSignature), can be ignored property string bundleName: bundleSettingsProbe.xcodeSettings["WRAPPER_NAME"] property string frameworkVersion: { var n = parseInt(product.version, 10); return isNaN(n) ? bundleSettingsProbe.xcodeSettings["FRAMEWORK_VERSION"] : String(n); } property bool generatePackageInfo: { // Make sure to return undefined as default to indicate "not set" var genPkgInfo = bundleSettingsProbe.xcodeSettings["GENERATE_PKGINFO_FILE"]; if (genPkgInfo) return genPkgInfo === "YES"; } property pathList publicHeaders property pathList privateHeaders property pathList resources property var infoPlist property bool processInfoPlist: true property bool embedInfoPlist: product.consoleApplication && !isBundle property string infoPlistFormat: qbs.targetOS.contains("macos") ? "same-as-input" : "binary1" property string localizedResourcesFolderSuffix: ".lproj" property string lsregisterName: "lsregister" property string lsregisterPath: FileInfo.joinPaths( "/System/Library/Frameworks/CoreServices.framework" + "/Versions/A/Frameworks/LaunchServices.framework" + "/Versions/A/Support", lsregisterName); // all paths are relative to the directory containing the bundle readonly property string infoPlistPath: bundleSettingsProbe.xcodeSettings["INFOPLIST_PATH"] readonly property string infoStringsPath: bundleSettingsProbe.xcodeSettings["INFOSTRINGS_PATH"] readonly property string pbdevelopmentPlistPath: bundleSettingsProbe.xcodeSettings["PBDEVELOPMENTPLIST_PATH"] readonly property string pkgInfoPath: bundleSettingsProbe.xcodeSettings["PKGINFO_PATH"] readonly property string versionPlistPath: bundleSettingsProbe.xcodeSettings["VERSIONPLIST_PATH"] readonly property string executablePath: bundleSettingsProbe.xcodeSettings["EXECUTABLE_PATH"] readonly property string contentsFolderPath: bundleSettingsProbe.xcodeSettings["CONTENTS_FOLDER_PATH"] readonly property string documentationFolderPath: bundleSettingsProbe.xcodeSettings["DOCUMENTATION_FOLDER_PATH"] readonly property string executableFolderPath: bundleSettingsProbe.xcodeSettings["EXECUTABLE_FOLDER_PATH"] readonly property string executablesFolderPath: bundleSettingsProbe.xcodeSettings["EXECUTABLES_FOLDER_PATH"] readonly property string frameworksFolderPath: bundleSettingsProbe.xcodeSettings["FRAMEWORKS_FOLDER_PATH"] readonly property string javaFolderPath: bundleSettingsProbe.xcodeSettings["JAVA_FOLDER_PATH"] readonly property string localizedResourcesFolderPath: bundleSettingsProbe.xcodeSettings["LOCALIZED_RESOURCES_FOLDER_PATH"] readonly property string pluginsFolderPath: bundleSettingsProbe.xcodeSettings["PLUGINS_FOLDER_PATH"] readonly property string privateHeadersFolderPath: bundleSettingsProbe.xcodeSettings["PRIVATE_HEADERS_FOLDER_PATH"] readonly property string publicHeadersFolderPath: bundleSettingsProbe.xcodeSettings["PUBLIC_HEADERS_FOLDER_PATH"] readonly property string scriptsFolderPath: bundleSettingsProbe.xcodeSettings["SCRIPTS_FOLDER_PATH"] readonly property string sharedFrameworksFolderPath: bundleSettingsProbe.xcodeSettings["SHARED_FRAMEWORKS_FOLDER_PATH"] readonly property string sharedSupportFolderPath: bundleSettingsProbe.xcodeSettings["SHARED_SUPPORT_FOLDER_PATH"] readonly property string unlocalizedResourcesFolderPath: bundleSettingsProbe.xcodeSettings["UNLOCALIZED_RESOURCES_FOLDER_PATH"] readonly property string versionsFolderPath: bundleSettingsProbe.xcodeSettings["VERSIONS_FOLDER_PATH"] // private properties property string _productTypeIdentifier: Bundle.productTypeIdentifier(product.type) property stringList _productTypeIdentifierChain: bundleSettingsProbe.productTypeIdentifierChain property bool _useXcodeBuildSpecs: true // false to use ONLY the qbs build specs readonly property var extraEnv: ({ "PRODUCT_BUNDLE_IDENTIFIER": identifier }) readonly property var qmakeEnv: { return { "BUNDLEIDENTIFIER": identifier, "EXECUTABLE": product.targetName, "FULL_VERSION": product.version || "1.0", // CFBundleVersion "ICON": product.targetName, // ### QBS-73 "LIBRARY": product.targetName, "SHORT_VERSION": product.version || "1.0", // CFBundleShortVersionString "TYPEINFO": signature // CFBundleSignature }; } readonly property var defaultInfoPlist: { return { CFBundleDevelopmentRegion: "en", // default localization CFBundleDisplayName: product.targetName, // localizable CFBundleExecutable: product.targetName, CFBundleIdentifier: identifier, CFBundleInfoDictionaryVersion: "6.0", CFBundleName: product.targetName, // short display name of the bundle, localizable CFBundlePackageType: packageType, CFBundleShortVersionString: product.version || "1.0", // "release" version number, localizable CFBundleSignature: signature, // legacy creator code in Mac OS Classic, can be ignored CFBundleVersion: product.version || "1.0.0" // build version number, must be 3 octets }; } validate: { if (!qbs.targetOS.contains("darwin")) return; if (!bundleSettingsProbe.found) { var error = "Bundle product type " + _productTypeIdentifier + " is not supported."; if ((_productTypeIdentifier || "").startsWith("com.apple.product-type.")) error += " You may need to upgrade Xcode."; throw error; } var validator = new ModUtils.PropertyValidator("bundle"); validator.setRequiredProperty("bundleName", bundleName); validator.setRequiredProperty("infoPlistPath", infoPlistPath); validator.setRequiredProperty("pbdevelopmentPlistPath", pbdevelopmentPlistPath); validator.setRequiredProperty("pkgInfoPath", pkgInfoPath); validator.setRequiredProperty("versionPlistPath", versionPlistPath); validator.setRequiredProperty("executablePath", executablePath); validator.setRequiredProperty("contentsFolderPath", contentsFolderPath); validator.setRequiredProperty("documentationFolderPath", documentationFolderPath); validator.setRequiredProperty("executableFolderPath", executableFolderPath); validator.setRequiredProperty("executablesFolderPath", executablesFolderPath); validator.setRequiredProperty("frameworksFolderPath", frameworksFolderPath); validator.setRequiredProperty("javaFolderPath", javaFolderPath); validator.setRequiredProperty("localizedResourcesFolderPath", localizedResourcesFolderPath); validator.setRequiredProperty("pluginsFolderPath", pluginsFolderPath); validator.setRequiredProperty("privateHeadersFolderPath", privateHeadersFolderPath); validator.setRequiredProperty("publicHeadersFolderPath", publicHeadersFolderPath); validator.setRequiredProperty("scriptsFolderPath", scriptsFolderPath); validator.setRequiredProperty("sharedFrameworksFolderPath", sharedFrameworksFolderPath); validator.setRequiredProperty("sharedSupportFolderPath", sharedSupportFolderPath); validator.setRequiredProperty("unlocalizedResourcesFolderPath", unlocalizedResourcesFolderPath); if (packageType === "FMWK") { validator.setRequiredProperty("frameworkVersion", frameworkVersion); validator.setRequiredProperty("versionsFolderPath", versionsFolderPath); } // extension and infoStringsPath might not be set return validator.validate(); } FileTagger { fileTags: ["infoplist"] patterns: ["Info.plist", "*-Info.plist"] } Rule { condition: qbs.targetOS.contains("darwin") multiplex: true requiresInputs: false // TODO: The resources property should probably be a tag instead. inputs: ["infoplist", "partial_infoplist"] outputFileTags: ["bundle.input", "aggregate_infoplist"] outputArtifacts: { var artifacts = []; var embed = ModUtils.moduleProperty(product, "embedInfoPlist"); if (ModUtils.moduleProperty(product, "isBundle") || embed) { artifacts.push({ filePath: FileInfo.joinPaths( product.destinationDirectory, product.name + "-Info.plist"), fileTags: ["aggregate_infoplist"].concat(!embed ? ["bundle.input"] : []), bundle: { _bundleFilePath: FileInfo.joinPaths( product.destinationDirectory, ModUtils.moduleProperty(product, "infoPlistPath")), } }); } return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating Info.plist for " + product.name; cmd.highlight = "codegen"; cmd.infoPlist = ModUtils.moduleProperty(product, "infoPlist") || {}; cmd.processInfoPlist = ModUtils.moduleProperty(product, "processInfoPlist"); cmd.infoPlistFormat = ModUtils.moduleProperty(product, "infoPlistFormat"); cmd.extraEnv = ModUtils.moduleProperty(product, "extraEnv"); cmd.qmakeEnv = ModUtils.moduleProperty(product, "qmakeEnv"); cmd.buildEnv = product.moduleProperty("cpp", "buildEnv"); cmd.developerPath = product.moduleProperty("xcode", "developerPath"); cmd.platformInfoPlist = product.moduleProperty("xcode", "platformInfoPlist"); cmd.sdkSettingsPlist = product.moduleProperty("xcode", "sdkSettingsPlist"); cmd.toolchainInfoPlist = product.moduleProperty("xcode", "toolchainInfoPlist"); cmd.osBuildVersion = product.moduleProperty("qbs", "hostOSBuildVersion"); cmd.sourceCode = function() { var plist, process, key, i; // Contains the combination of default, file, and in-source keys and values // Start out with the contents of this file as the "base", if given var aggregatePlist = {}; for (i = 0; i < (inputs.infoplist || []).length; ++i) { aggregatePlist = BundleTools.infoPlistContents(inputs.infoplist[i].filePath); infoPlistFormat = (infoPlistFormat === "same-as-input") ? BundleTools.infoPlistFormat(inputs.infoplist[i].filePath) : "xml1"; break; } // Add local key-value pairs (overrides equivalent keys specified in the file if // one was given) for (key in infoPlist) { if (infoPlist.hasOwnProperty(key)) aggregatePlist[key] = infoPlist[key]; } // Do some postprocessing if desired if (processInfoPlist) { // Add default values to the aggregate plist if the corresponding keys // for those values are not already present var defaultValues = ModUtils.moduleProperty(product, "defaultInfoPlist"); for (key in defaultValues) { if (defaultValues.hasOwnProperty(key) && !(key in aggregatePlist)) aggregatePlist[key] = defaultValues[key]; } // Add keys from platform's Info.plist if not already present var platformInfo = {}; var sdkSettings = {}; var toolchainInfo = {}; if (developerPath) { plist = new PropertyList(); try { plist.readFromFile(platformInfoPlist); platformInfo = plist.toObject(); } finally { plist.clear(); } var additionalProps = platformInfo["AdditionalInfo"]; for (key in additionalProps) { // override infoPlist? if (additionalProps.hasOwnProperty(key) && !(key in aggregatePlist)) aggregatePlist[key] = defaultValues[key]; } props = platformInfo['OverrideProperties']; for (key in props) { aggregatePlist[key] = props[key]; } plist = new PropertyList(); try { plist.readFromFile(sdkSettingsPlist); sdkSettings = plist.toObject(); } finally { plist.clear(); } plist = new PropertyList(); try { plist.readFromFile(toolchainInfoPlist); toolchainInfo = plist.toObject(); } finally { plist.clear(); } } aggregatePlist["BuildMachineOSBuild"] = osBuildVersion; // setup env env = { "SDK_NAME": sdkSettings["CanonicalName"], "XCODE_VERSION_ACTUAL": toolchainInfo["DTXcode"], "SDK_PRODUCT_BUILD_VERSION": toolchainInfo["DTPlatformBuild"], "GCC_VERSION": platformInfo["DTCompiler"], "XCODE_PRODUCT_BUILD_VERSION": platformInfo["DTPlatformBuild"], "PLATFORM_PRODUCT_BUILD_VERSION": platformInfo["ProductBuildVersion"], } env["MAC_OS_X_PRODUCT_BUILD_VERSION"] = osBuildVersion; for (key in extraEnv) env[key] = extraEnv[key]; for (key in buildEnv) env[key] = buildEnv[key]; for (key in qmakeEnv) env[key] = qmakeEnv[key]; var expander = new DarwinTools.PropertyListVariableExpander(); expander.undefinedVariableFunction = function (key, varName) { var msg = "Info.plist variable expansion encountered undefined variable '" + varName + "' when expanding value for key '" + key + "', defined in one of the following files:\n\t"; var allFilePaths = []; for (i = 0; i < (inputs.infoplist || []).length; ++i) allFilePaths.push(inputs.infoplist[i].filePath); if (platformInfoPlist) allFilePaths.push(platformInfoPlist); msg += allFilePaths.join("\n\t") + "\n"; msg += "or in the bundle.infoPlist property of product '" + product.name + "'"; console.warn(msg); }; aggregatePlist = expander.expand(aggregatePlist, env); // Add keys from partial Info.plists from asset catalogs, XIBs, and storyboards. for (var j = 0; j < (inputs.partial_infoplist || []).length; ++j) { var partialInfoPlist = BundleTools.infoPlistContents( inputs.partial_infoplist[j].filePath) || {}; for (key in partialInfoPlist) { if (partialInfoPlist.hasOwnProperty(key) && !aggregatePlist.hasOwnProperty(key)) aggregatePlist[key] = partialInfoPlist[key]; } } } // Anything with an undefined or otherwise empty value should be removed // Only JSON-formatted plists can have null values, other formats error out // This also follows Xcode behavior DarwinTools.cleanPropertyList(aggregatePlist); if (infoPlistFormat === "same-as-input") infoPlistFormat = "xml1"; var validFormats = [ "xml1", "binary1", "json" ]; if (!validFormats.contains(infoPlistFormat)) throw("Invalid Info.plist format " + infoPlistFormat + ". " + "Must be in [xml1, binary1, json]."); // Write the plist contents in the format appropriate for the current platform plist = new PropertyList(); try { plist.readFromObject(aggregatePlist); plist.writeToFile(outputs.aggregate_infoplist[0].filePath, infoPlistFormat); } finally { plist.clear(); } } return cmd; } } Rule { condition: qbs.targetOS.contains("darwin") multiplex: true inputs: ["aggregate_infoplist"] outputFileTags: ["bundle.input", "pkginfo"] outputArtifacts: { var artifacts = []; if (ModUtils.moduleProperty(product, "isBundle") && ModUtils.moduleProperty(product, "generatePackageInfo")) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, "PkgInfo"), fileTags: ["bundle.input", "pkginfo"], bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "pkgInfoPath")) } }); } return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating PkgInfo for " + product.name; cmd.highlight = "codegen"; cmd.sourceCode = function() { var infoPlist = BundleTools.infoPlistContents(inputs.aggregate_infoplist[0].filePath); var pkgType = infoPlist['CFBundlePackageType']; if (!pkgType) throw("CFBundlePackageType not found in Info.plist; this should not happen"); var pkgSign = infoPlist['CFBundleSignature']; if (!pkgSign) throw("CFBundleSignature not found in Info.plist; this should not happen"); var pkginfo = new TextFile(outputs.pkginfo[0].filePath, TextFile.WriteOnly); pkginfo.write(pkgType + pkgSign); pkginfo.close(); } return cmd; } } Rule { condition: qbs.targetOS.contains("darwin") multiplex: true inputs: ["bundle.input", "aggregate_infoplist", "pkginfo", "hpp", "icns", "xcent", "compiled_ibdoc", "compiled_assetcatalog", "xcode.provisioningprofile.main"] // Make sure the inputs of this rule are only those rules which produce outputs compatible // with the type of the bundle being produced. excludedInputs: Bundle.excludedAuxiliaryInputs(project, product) outputFileTags: [ "bundle.content", "bundle.symlink.headers", "bundle.symlink.private-headers", "bundle.symlink.resources", "bundle.symlink.executable", "bundle.symlink.version", "bundle.hpp", "bundle.resource", "bundle.provisioningprofile", "bundle.content.copied", "bundle.application-executable"] outputArtifacts: { var i, artifacts = []; if (ModUtils.moduleProperty(product, "isBundle")) { for (i in inputs["bundle.input"]) { var fp = inputs["bundle.input"][i].moduleProperty("bundle", "_bundleFilePath"); if (!fp) throw("Artifact " + inputs["bundle.input"][i].filePath + " has no associated bundle file path"); var extraTags = inputs["bundle.input"][i].fileTags.contains("application") ? ["bundle.application-executable"] : []; artifacts.push({ filePath: fp, fileTags: ["bundle.content", "bundle.content.copied"].concat(extraTags) }); } for (i in inputs["xcode.provisioningprofile.main"]) { var ext = inputs["xcode.provisioningprofile.main"][i].fileName.split('.')[1]; artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "contentsFolderPath"), "embedded." + ext), fileTags: ["bundle.provisioningprofile", "bundle.content"] }); } var packageType = ModUtils.moduleProperty(product, "packageType"); var isShallow = ModUtils.moduleProperty(product, "isShallow"); if (packageType === "FMWK" && !isShallow) { var publicHeaders = ModUtils.moduleProperty(product, "publicHeaders"); if (publicHeaders && publicHeaders.length) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Headers"), fileTags: ["bundle.symlink.headers", "bundle.content"] }); } var privateHeaders = ModUtils.moduleProperty(product, "privateHeaders"); if (privateHeaders && privateHeaders.length) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "PrivateHeaders"), fileTags: ["bundle.symlink.private-headers", "bundle.content"] }); } artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Resources"), fileTags: ["bundle.symlink.resources", "bundle.content"] }); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), product.targetName), fileTags: ["bundle.symlink.executable", "bundle.content"] }); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "versionsFolderPath"), "Current"), fileTags: ["bundle.symlink.version", "bundle.content"] }); } var headerTypes = ["public", "private"]; for (var h in headerTypes) { var sources = ModUtils.moduleProperty(product, headerTypes[h] + "Headers"); var destination = FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, headerTypes[h] + "HeadersFolderPath")); for (i in sources) { artifacts.push({ filePath: FileInfo.joinPaths(destination, FileInfo.fileName(sources[i])), fileTags: ["bundle.hpp", "bundle.content"] }); } } sources = ModUtils.moduleProperty(product, "resources"); for (i in sources) { destination = BundleTools.destinationDirectoryForResource(product, {baseDir: FileInfo.path(sources[i]), fileName: FileInfo.fileName(sources[i])}); artifacts.push({ filePath: FileInfo.joinPaths(destination, FileInfo.fileName(sources[i])), fileTags: ["bundle.resource", "bundle.content"] }); } var wrapperPath = FileInfo.joinPaths( product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName")); for (var i = 0; i < artifacts.length; ++i) artifacts[i].bundle = { wrapperPath: wrapperPath }; } return artifacts; } prepare: { var i, cmd, commands = []; var packageType = ModUtils.moduleProperty(product, "packageType"); var bundleType = "bundle"; if (packageType === "APPL") bundleType = "application"; if (packageType === "FMWK") bundleType = "framework"; var bundles = outputs.bundle; for (i in bundles) { cmd = new Command("mkdir", ["-p", bundles[i].filePath]); cmd.description = "creating " + bundleType + " " + product.targetName; commands.push(cmd); cmd = new Command("touch", ["-c", bundles[i].filePath]); cmd.silent = true; commands.push(cmd); } // Product is unbundled if (commands.length === 0) { cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function () { }; commands.push(cmd); } var symlinks = outputs["bundle.symlink.version"]; for (i in symlinks) { cmd = new Command("ln", ["-sfn", ModUtils.moduleProperty(product, "frameworkVersion"), symlinks[i].filePath]); cmd.silent = true; commands.push(cmd); } var publicHeaders = outputs["bundle.symlink.headers"]; for (i in publicHeaders) { cmd = new Command("ln", ["-sfn", "Versions/Current/Headers", publicHeaders[i].filePath]); cmd.silent = true; commands.push(cmd); } var privateHeaders = outputs["bundle.symlink.private-headers"]; for (i in privateHeaders) { cmd = new Command("ln", ["-sfn", "Versions/Current/PrivateHeaders", privateHeaders[i].filePath]); cmd.silent = true; commands.push(cmd); } var resources = outputs["bundle.symlink.resources"]; for (i in resources) { cmd = new Command("ln", ["-sfn", "Versions/Current/Resources", resources[i].filePath]); cmd.silent = true; commands.push(cmd); } var executables = outputs["bundle.symlink.executable"]; for (i in executables) { cmd = new Command("ln", ["-sfn", FileInfo.joinPaths("Versions", "Current", product.targetName), executables[i].filePath]); cmd.silent = true; commands.push(cmd); } function sortedArtifactList(list, func) { if (list) { return list.sort(func || (function (a, b) { return a.filePath.localeCompare(b.filePath); })); } } var bundleInputs = sortedArtifactList(inputs["bundle.input"], function (a, b) { return a.moduleProperty("bundle", "_bundleFilePath").localeCompare( b.moduleProperty("bundle", "_bundleFilePath")); }); var bundleContents = sortedArtifactList(outputs["bundle.content.copied"]); for (i in bundleContents) { cmd = new JavaScriptCommand(); cmd.silent = true; cmd.source = bundleInputs[i].filePath; cmd.destination = bundleContents[i].filePath; cmd.sourceCode = function() { File.copy(source, destination); }; commands.push(cmd); } var provisioningProfiles = outputs["bundle.provisioningprofile"]; for (i in provisioningProfiles) { cmd = new JavaScriptCommand(); cmd.description = "copying provisioning profile"; cmd.highlight = "filegen"; cmd.source = inputs["xcode.provisioningprofile.main"][i].filePath; cmd.destination = provisioningProfiles[i].filePath; cmd.sourceCode = function() { File.copy(source, destination); }; commands.push(cmd); } cmd = new JavaScriptCommand(); cmd.description = "copying public headers"; cmd.highlight = "filegen"; cmd.sources = ModUtils.moduleProperty(product, "publicHeaders"); cmd.destination = FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "publicHeadersFolderPath")); cmd.sourceCode = function() { var i; for (var i in sources) { File.copy(sources[i], FileInfo.joinPaths(destination, FileInfo.fileName(sources[i]))); } }; if (cmd.sources && cmd.sources.length) commands.push(cmd); cmd = new JavaScriptCommand(); cmd.description = "copying private headers"; cmd.highlight = "filegen"; cmd.sources = ModUtils.moduleProperty(product, "privateHeaders"); cmd.destination = FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "privateHeadersFolderPath")); cmd.sourceCode = function() { var i; for (var i in sources) { File.copy(sources[i], FileInfo.joinPaths(destination, FileInfo.fileName(sources[i]))); } }; if (cmd.sources && cmd.sources.length) commands.push(cmd); cmd = new JavaScriptCommand(); cmd.description = "copying resources"; cmd.highlight = "filegen"; cmd.sources = ModUtils.moduleProperty(product, "resources"); cmd.sourceCode = function() { var i; for (var i in sources) { var destination = BundleTools.destinationDirectoryForResource(product, {baseDir: FileInfo.path(sources[i]), fileName: FileInfo.fileName(sources[i])}); File.copy(sources[i], FileInfo.joinPaths(destination, FileInfo.fileName(sources[i]))); } }; if (cmd.sources && cmd.sources.length) commands.push(cmd); if (product.moduleProperty("qbs", "hostOS").contains("darwin")) { for (i in bundles) { var actualSigningIdentity = product.moduleProperty("xcode", "actualSigningIdentity"); var codesignDisplayName = product.moduleProperty("xcode", "actualSigningIdentityDisplayName"); if (actualSigningIdentity) { // If this is a framework, we need to sign its versioned directory var subpath = ""; var frameworkVersion = ModUtils.moduleProperty(product, "frameworkVersion"); if (frameworkVersion) { subpath = ModUtils.moduleProperty(product, "contentsFolderPath"); subpath = subpath.substring(subpath.indexOf(ModUtils.moduleProperty("qbs", "pathSeparator"))); } var args = product.moduleProperty("xcode", "codesignFlags") || []; args.push("--force"); args.push("--sign", actualSigningIdentity); args = args.concat(DarwinTools._codeSignTimestampFlags(product)); for (var j in inputs.xcent) { args.push("--entitlements", inputs.xcent[j].filePath); break; // there should only be one } args.push(bundles[i].filePath + subpath); cmd = new Command(product.moduleProperty("xcode", "codesignPath"), args); cmd.description = "codesign " + ModUtils.moduleProperty(product, "bundleName") + " using " + codesignDisplayName + " (" + actualSigningIdentity + ")"; commands.push(cmd); } if (bundleType === "application" && product.moduleProperty("qbs", "targetOS").contains("macos")) { cmd = new Command(ModUtils.moduleProperty(product, "lsregisterPath"), ["-f", bundles[i].filePath]); cmd.description = "register " + ModUtils.moduleProperty(product, "bundleName"); commands.push(cmd); } } } return commands; } } } qbs-src-1.13.1/share/qbs/modules/bundle/MacOSX-Package-Types.xcspec000066400000000000000000000420551347155106100247240ustar00rootroot00000000000000[ { "DefaultBuildSettings" : { "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)", "EXECUTABLE_PREFIX" : "", "EXECUTABLE_SUFFIX" : "", "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)" }, "Identifier" : "com.apple.package-type.mach-o-executable", "Type" : "PackageType", "Name" : "Mach-O Executable", "Description" : "Mach-O executable", "ProductReference" : { "FileType" : "compiled.mach-o.executable", "Name" : "$(EXECUTABLE_NAME)", "IsLaunchable" : "YES" } }, { "DefaultBuildSettings" : { "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)", "EXECUTABLE_PREFIX" : "", "EXECUTABLE_SUFFIX" : "", "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)" }, "Identifier" : "com.apple.package-type.mach-o-objfile", "Type" : "PackageType", "Name" : "Mach-O Object File", "Description" : "Mach-O Object File", "ProductReference" : { "FileType" : "compiled.mach-o.objfile", "Name" : "$(EXECUTABLE_NAME)", "IsLaunchable" : "NO" } }, { "DefaultBuildSettings" : { "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)", "EXECUTABLE_PREFIX" : "", "EXECUTABLE_SUFFIX" : "", "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)" }, "Identifier" : "com.apple.package-type.mach-o-dylib", "Type" : "PackageType", "Name" : "Mach-O Dynamic Library", "Description" : "Mach-O dynamic library", "ProductReference" : { "FileType" : "compiled.mach-o.dylib", "Name" : "$(EXECUTABLE_NAME)", "IsLaunchable" : "NO" } }, { "DefaultBuildSettings" : { "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)", "EXECUTABLE_PREFIX" : "lib", "EXECUTABLE_SUFFIX" : ".a", "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)" }, "Identifier" : "com.apple.package-type.static-library", "Type" : "PackageType", "Name" : "Mach-O Static Library", "Description" : "Mach-O static library", "ProductReference" : { "FileType" : "archive.ar", "Name" : "$(EXECUTABLE_NAME)", "IsLaunchable" : "NO" } }, { "DefaultBuildSettings" : { "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)", "EXECUTABLE_PREFIX" : "", "EXECUTABLE_SUFFIX" : ".dylib", "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)" }, "Identifier" : "com.apple.package-type.mach-o-bundle", "Type" : "PackageType", "Name" : "Mach-O Loadable", "Description" : "Mach-O loadable", "ProductReference" : { "FileType" : "compiled.mach-o.bundle", "Name" : "$(EXECUTABLE_NAME)", "IsLaunchable" : "NO" } }, { "DefaultBuildSettings" : { "PUBLIC_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Headers", "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)", "EXECUTABLE_PREFIX" : "", "PLUGINS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PlugIns", "DOCUMENTATION_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/Documentation", "EXECUTABLES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Executables", "INFOSTRINGS_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/InfoPlist.strings", "INFOPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/Info.plist", "EXECUTABLE_SUFFIX" : "", "VERSIONPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/version.plist", "SHARED_SUPPORT_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/SharedSupport", "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/MacOS", "PBDEVELOPMENTPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/pbdevelopment.plist", "FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Frameworks", "LOCALIZED_RESOURCES_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/$(DEVELOPMENT_LANGUAGE).lproj", "SCRIPTS_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Scripts", "WRAPPER_PREFIX" : "", "PRIVATE_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PrivateHeaders", "CONTENTS_FOLDER_PATH" : "$(WRAPPER_NAME)\/Contents", "WRAPPER_NAME" : "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)", "PKGINFO_PATH" : "$(CONTENTS_FOLDER_PATH)\/PkgInfo", "EXECUTABLE_PATH" : "$(EXECUTABLE_FOLDER_PATH)\/$(EXECUTABLE_NAME)", "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Resources", "JAVA_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Java", "SHARED_FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/SharedFrameworks", "WRAPPER_SUFFIX" : ".bundle" }, "Identifier" : "com.apple.package-type.wrapper", "Type" : "PackageType", "Name" : "Wrapper", "Description" : "Wrapper", "ProductReference" : { "FileType" : "wrapper.cfbundle", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" } }, { "ProductReference" : { "FileType" : "wrapper.cfbundle", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { "CONTENTS_FOLDER_PATH" : "$(WRAPPER_NAME)", "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "SHALLOW_BUNDLE" : "YES", "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper", "Name" : "Wrapper (Shallow)", "Identifier" : "com.apple.package-type.wrapper.shallow", "Description" : "Shallow Wrapper" }, { "ProductReference" : { "FileType" : "wrapper.application", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "YES" }, "DefaultBuildSettings" : { "GENERATE_PKGINFO_FILE" : "YES" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper", "Name" : "Application Wrapper", "Identifier" : "com.apple.package-type.wrapper.application", "Description" : "Application Wrapper" }, { "ProductReference" : { "FileType" : "wrapper.application", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "YES" }, "DefaultBuildSettings" : { "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "SHALLOW_BUNDLE" : "YES", "GENERATE_PKGINFO_FILE" : "YES" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper.shallow", "Name" : "Application Wrapper (Shallow)", "Identifier" : "com.apple.package-type.wrapper.application.shallow", "Description" : "Shallow Application Wrapper" }, { "ProductReference" : { "FileType" : "wrapper.cfbundle", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { "PRIVATE_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/PrivateHeaders\/$(KEXT_FAMILY_NAME)", "PUBLIC_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/Headers\/$(KEXT_FAMILY_NAME)" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper", "Name" : "Kernel Extension Wrapper", "Identifier" : "com.apple.package-type.wrapper.kernel-extension", "Description" : "Kernel Extension Wrapper" }, { "ProductReference" : { "FileType" : "wrapper.cfbundle", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { "PRIVATE_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/PrivateHeaders\/$(KEXT_FAMILY_NAME)", "PUBLIC_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/Headers\/$(KEXT_FAMILY_NAME)", "SHALLOW_BUNDLE" : "YES" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper.shallow", "Name" : "Kernel Extension Wrapper (Shallow)", "Identifier" : "com.apple.package-type.wrapper.kernel-extension.shallow", "Description" : "Shallow Kernel Extension Wrapper" }, { "DefaultBuildSettings" : { "PUBLIC_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Headers", "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)", "EXECUTABLE_PREFIX" : "", "PLUGINS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PlugIns", "DOCUMENTATION_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/Documentation", "EXECUTABLES_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)", "INFOPLIST_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Info.plist", "EXECUTABLE_SUFFIX" : "", "INFOPLISTSTRINGS_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/InfoPlist.strings", "VERSIONPLIST_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/version.plist", "SHARED_SUPPORT_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)", "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "PBDEVELOPMENTPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/pbdevelopment.plist", "VERSIONS_FOLDER_PATH" : "$(WRAPPER_NAME)\/Versions", "FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Frameworks", "CODESIGNING_FOLDER_PATH" : "$(TARGET_BUILD_DIR)\/$(CONTENTS_FOLDER_PATH)", "LOCALIZED_RESOURCES_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/$(DEVELOPMENT_LANGUAGE).lproj", "SCRIPTS_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Scripts", "WRAPPER_PREFIX" : "", "PRIVATE_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PrivateHeaders", "CURRENT_VERSION" : "Current", "PKGINFO_PATH" : "$(WRAPPER_NAME)\/PkgInfo", "WRAPPER_NAME" : "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)", "CONTENTS_FOLDER_PATH" : "$(VERSIONS_FOLDER_PATH)\/$(FRAMEWORK_VERSION)", "EXECUTABLE_PATH" : "$(EXECUTABLE_FOLDER_PATH)\/$(EXECUTABLE_NAME)", "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Resources", "JAVA_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Java", "SHARED_FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/SharedFrameworks", "WRAPPER_SUFFIX" : ".framework" }, "Identifier" : "com.apple.package-type.wrapper.framework", "Type" : "PackageType", "Name" : "Framework Wrapper", "Description" : "Framework wrapper", "ProductReference" : { "FileType" : "wrapper.framework", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" } }, { "ProductReference" : { "FileType" : "wrapper.framework.static", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { "EXECUTABLE_SUFFIX" : "", "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)", "EXECUTABLE_PREFIX" : "" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper.framework", "Name" : "Mach-O Static Framework", "Identifier" : "com.apple.package-type.wrapper.framework.static", "Description" : "Mach-O static framework" }, { "ProductReference" : { "FileType" : "wrapper.framework", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "CONTENTS_FOLDER_PATH" : "$(WRAPPER_NAME)", "SHALLOW_BUNDLE" : "YES", "VERSIONS_FOLDER_PATH" : "$(WRAPPER_NAME)" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper.framework", "Name" : "Shallow Framework Wrapper", "Identifier" : "com.apple.package-type.wrapper.framework.shallow", "Description" : "Shallow framework wrapper" }, { "ProductReference" : { "FileType" : "wrapper.cfbundle", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { "WRAPPER_SUFFIX" : "xctest" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper", "Name" : "Unit Test Bundle", "Identifier" : "com.apple.package-type.bundle.unit-test", "Description" : "Unit Test Bundle" }, { "ProductReference" : { "FileType" : "wrapper.cfbundle", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { "WRAPPER_SUFFIX" : "octest" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper", "Name" : "OCUnit Test Bundle", "Identifier" : "com.apple.package-type.bundle.ocunit-test", "Description" : "OCUnit Test Bundle" }, { "ProductReference" : { "FileType" : "folder", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "JAVA_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)", "INFOSTRINGS_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/ContentInfo.strings", "INFOPLIST_PATH" : "$(WRAPPER_NAME)\/ContentInfo.plist", "WRAPPER_SUFFIX" : "", "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "DOCUMENTATION_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)", "EXECUTABLES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "LOCALIZED_RESOURCES_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/$(DEVELOPMENT_LANGUAGE).lproj", "PLUGINS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "PUBLIC_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "SHARED_SUPPORT_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "SHARED_FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "PRIVATE_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)", "SCRIPTS_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)", "FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper", "Name" : "In-App Purchase Content", "Identifier" : "com.apple.package-type.in-app-purchase-content", "Description" : "In-App Purchase Content" }, { "ProductReference" : { "FileType" : "wrapper.xpc-service", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { "WRAPPER_SUFFIX" : ".xpc" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper", "Name" : "XPC Service", "Identifier" : "com.apple.package-type.xpc-service", "Description" : "XPC Service" }, { "ProductReference" : { "FileType" : "wrapper.app-extension", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { "WRAPPER_SUFFIX" : ".pluginkit" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.xpc-service", "Name" : "PlugInKit PlugIn", "Identifier" : "com.apple.package-type.pluginkit-plugin", "Description" : "PlugInKit PlugIn" }, { "ProductReference" : { "FileType" : "wrapper.app-extension", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { "WRAPPER_SUFFIX" : ".appex" }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.pluginkit-plugin", "Name" : "App Extension", "Identifier" : "com.apple.package-type.app-extension", "Description" : "App Extension" }, { "ProductReference" : { "FileType" : "wrapper.spotlight-importer", "Name" : "$(WRAPPER_NAME)", "IsLaunchable" : "NO" }, "DefaultBuildSettings" : { }, "Type" : "PackageType", "BasedOn" : "com.apple.package-type.wrapper", "Name" : "Spotlight Importer", "Identifier" : "com.apple.package-type.spotlight-importer", "Description" : "Spotlight Importer" }, { "DefaultBuildSettings" : { "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)", "JAVA_MAKE_ZIPFILE" : "NO", "JAVA_ARCHIVE_CLASSES" : "YES", "EXECUTABLE_PREFIX" : "", "EXECUTABLE_SUFFIX" : ".jar", "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)" }, "Identifier" : "com.apple.package-type.jarfile", "Type" : "PackageType", "Name" : "Jar File", "Description" : "Jar file", "ProductReference" : { "FileType" : "archive.jar", "Name" : "$(EXECUTABLE_NAME)", "IsLaunchable" : "NO" } }, { "DefaultBuildSettings" : { "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)", "JAVA_MAKE_ZIPFILE" : "YES", "JAVA_ARCHIVE_CLASSES" : "YES", "EXECUTABLE_PREFIX" : "", "EXECUTABLE_SUFFIX" : ".zip", "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)" }, "Identifier" : "com.apple.package-type.zipfile", "Type" : "PackageType", "Name" : "Zip File", "Description" : "Zip file", "ProductReference" : { "FileType" : "archive.zip", "Name" : "$(EXECUTABLE_NAME)", "IsLaunchable" : "NO" } }, { "DefaultBuildSettings" : { "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)", "JAVA_ARCHIVE_CLASSES" : "NO", "EXECUTABLE_PREFIX" : "", "EXECUTABLE_SUFFIX" : "", "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)" }, "Identifier" : "com.apple.package-type.javaclassfolder", "Type" : "PackageType", "Name" : "Class Folder", "Description" : "Class folder", "ProductReference" : { "FileType" : "wrapper.java-classfolder", "Name" : "$(EXECUTABLE_NAME)", "IsLaunchable" : "NO" } } ] qbs-src-1.13.1/share/qbs/modules/bundle/MacOSX-Product-Types.xcspec000066400000000000000000000512341347155106100250100ustar00rootroot00000000000000[ { "IconNamePrefix" : "TargetExecutable", "DefaultBuildProperties" : { "REZ_EXECUTABLE" : "YES", "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)", "LIBRARY_FLAG_NOSPACE" : "YES", "FRAMEWORK_FLAG_PREFIX" : "-framework", "INSTALL_PATH" : "\/usr\/local\/bin", "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES", "GCC_DYNAMIC_NO_PIC" : "NO", "GCC_SYMBOLS_PRIVATE_EXTERN" : "YES", "CODE_SIGNING_ALLOWED" : "YES", "STRIP_STYLE" : "all", "EXECUTABLE_PREFIX" : "", "MACH_O_TYPE" : "mh_execute", "EXECUTABLE_SUFFIX" : "", "LIBRARY_FLAG_PREFIX" : "-l" }, "PackageTypes" : [ "com.apple.package-type.mach-o-executable" ], "Type" : "ProductType", "DefaultTargetName" : "Command-line Tool", "Name" : "Command-line Tool", "Identifier" : "com.apple.product-type.tool", "Description" : "Standalone command-line tool", "Class" : "PBXToolProductType" }, { "IconNamePrefix" : "TargetExecutable", "IsJava" : "YES", "PackageTypes" : [ "com.apple.package-type.jarfile", "com.apple.package-type.zipfile", "com.apple.package-type.javaclassfolder" ], "Type" : "ProductType", "DefaultTargetName" : "Java Command-line Tool", "Name" : "Java Command-line Tool", "Identifier" : "com.apple.product-type.tool.java", "Description" : "Java Command-line tool", "DefaultBuildProperties" : { "REZ_EXECUTABLE" : "YES", "INSTALL_PATH" : "\/usr\/local\/bin", "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)" } }, { "IconNamePrefix" : "TargetPlugin", "DefaultBuildProperties" : { "DEAD_CODE_STRIPPING" : "NO", "REZ_EXECUTABLE" : "YES", "LINK_WITH_STANDARD_LIBRARIES" : "NO", "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)", "LIBRARY_FLAG_NOSPACE" : "YES", "FRAMEWORK_FLAG_PREFIX" : "-framework", "INSTALL_PATH" : "$(HOME)\/Objects", "SKIP_INSTALL" : "YES", "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES", "KEEP_PRIVATE_EXTERNS" : "YES", "EXECUTABLE_EXTENSION" : "o", "PUBLIC_HEADERS_FOLDER_PATH" : "\/usr\/local\/include", "MACH_O_TYPE" : "mh_object", "EXECUTABLE_SUFFIX" : ".$(EXECUTABLE_EXTENSION)", "LIBRARY_FLAG_PREFIX" : "-l", "PRIVATE_HEADERS_FOLDER_PATH" : "\/usr\/local\/include", "STRIP_STYLE" : "debugging" }, "PackageTypes" : [ "com.apple.package-type.mach-o-objfile" ], "Type" : "ProductType", "DefaultTargetName" : "Object File", "Name" : "Object File", "Identifier" : "com.apple.product-type.objfile", "Description" : "Object File", "Class" : "XCStandaloneExecutableProductType" }, { "IconNamePrefix" : "TargetLibrary", "DefaultBuildProperties" : { "LIBRARY_FLAG_PREFIX" : "-l", "STRIP_STYLE" : "debugging", "REZ_EXECUTABLE" : "YES", "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)", "LD_DYLIB_INSTALL_NAME" : "$(DYLIB_INSTALL_NAME_BASE:standardizepath)\/$(EXECUTABLE_PATH)", "DYLIB_COMPATIBILITY_VERSION" : "1", "INSTALL_PATH" : "\/usr\/local\/lib", "FRAMEWORK_FLAG_PREFIX" : "-framework", "LIBRARY_FLAG_NOSPACE" : "YES", "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES", "CODE_SIGNING_ALLOWED" : "YES", "CODE_SIGNING_REQUIRED" : "NO", "EXECUTABLE_EXTENSION" : "dylib", "PUBLIC_HEADERS_FOLDER_PATH" : "\/usr\/local\/include", "DYLIB_INSTALL_NAME_BASE" : "$(INSTALL_PATH)", "EXECUTABLE_SUFFIX" : ".$(EXECUTABLE_EXTENSION)", "PRIVATE_HEADERS_FOLDER_PATH" : "\/usr\/local\/include", "MACH_O_TYPE" : "mh_dylib", "DYLIB_CURRENT_VERSION" : "1" }, "PackageTypes" : [ "com.apple.package-type.mach-o-dylib" ], "Type" : "ProductType", "DefaultTargetName" : "Dynamic Library", "Name" : "Dynamic Library", "Identifier" : "com.apple.product-type.library.dynamic", "Description" : "Dynamic library", "Class" : "PBXDynamicLibraryProductType" }, { "IconNamePrefix" : "TargetLibrary", "DefaultBuildProperties" : { "STRIP_STYLE" : "debugging", "CLANG_ENABLE_MODULE_DEBUGGING" : "NO", "REZ_EXECUTABLE" : "YES", "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)", "LIBRARY_FLAG_NOSPACE" : "YES", "FRAMEWORK_FLAG_PREFIX" : "-framework", "INSTALL_PATH" : "\/usr\/local\/lib", "EXECUTABLE_EXTENSION" : "a", "EXECUTABLE_PREFIX" : "lib", "PUBLIC_HEADERS_FOLDER_PATH" : "\/usr\/local\/include", "EXECUTABLE_SUFFIX" : ".$(EXECUTABLE_EXTENSION)", "LIBRARY_FLAG_PREFIX" : "-l", "PRIVATE_HEADERS_FOLDER_PATH" : "\/usr\/local\/include", "MACH_O_TYPE" : "staticlib" }, "AlwaysPerformSeparateStrip" : "YES", "PackageTypes" : [ "com.apple.package-type.static-library" ], "Type" : "ProductType", "DefaultTargetName" : "Static Library", "Name" : "Static Library", "Identifier" : "com.apple.product-type.library.static", "Description" : "Static library", "Class" : "PBXStaticLibraryProductType" }, { "IconNamePrefix" : "TargetPlugin", "IsJava" : "YES", "PackageTypes" : [ "com.apple.package-type.jarfile", "com.apple.package-type.zipfile", "com.apple.package-type.javaclassfolder" ], "Type" : "ProductType", "DefaultTargetName" : "Java Library", "Name" : "Java Library", "Identifier" : "com.apple.product-type.library.java.archive", "Description" : "Java library packaged as a Jar file, Zip file, or class folder", "DefaultBuildProperties" : { "INSTALL_PATH" : "\/usr\/local\/lib", "FULL_PRODUCT_NAME" : "$(PRODUCT_NAME)" } }, { "HasInfoPlistStrings" : "YES", "Description" : "Generic bundle", "HasInfoPlist" : "YES", "Name" : "Bundle", "Class" : "PBXBundleProductType", "DefaultTargetName" : "Bundle", "DefaultBuildProperties" : { "LIBRARY_FLAG_NOSPACE" : "YES", "WRAPPER_NAME" : "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)", "FRAMEWORK_FLAG_PREFIX" : "-framework", "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES", "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)", "FULL_PRODUCT_NAME" : "$(WRAPPER_NAME)", "WRAPPER_EXTENSION" : "bundle", "CODE_SIGNING_ALLOWED" : "YES", "WRAPPER_PREFIX" : "", "STRIP_STYLE" : "non-global", "MACH_O_TYPE" : "mh_bundle", "LIBRARY_FLAG_PREFIX" : "-l" }, "PackageTypes" : [ "com.apple.package-type.wrapper", "com.apple.package-type.wrapper.shallow" ], "IsWrapper" : "YES", "Type" : "ProductType", "Identifier" : "com.apple.product-type.bundle", "IconNamePrefix" : "TargetPlugin" }, { "PackageTypes" : [ "com.apple.package-type.wrapper.shallow" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.bundle", "Name" : "Bundle (Shallow)", "Identifier" : "com.apple.product-type.bundle.shallow", "Description" : "Bundle (Shallow)", "Class" : "PBXBundleProductType" }, { "Description" : "Application", "Class" : "PBXApplicationProductType", "Name" : "Application", "RunpathSearchPathForEmbeddedFrameworks" : "@executable_path\/..\/Frameworks", "ValidateEmbeddedBinaries" : "YES", "ProvisioningProfileSupported" : "YES", "DefaultTargetName" : "Application", "DefaultBuildProperties" : { "INSTALL_PATH" : "$(LOCAL_APPS_DIR)", "WRAPPER_EXTENSION" : "app", "GCC_DYNAMIC_NO_PIC" : "NO", "STRIP_STYLE" : "all", "CODE_SIGNING_ALLOWED" : "YES", "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES", "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)", "GCC_SYMBOLS_PRIVATE_EXTERN" : "YES", "MACH_O_TYPE" : "mh_execute" }, "BasedOn" : "com.apple.product-type.bundle", "ProvisioningProfileRequired" : "NO", "PackageTypes" : [ "com.apple.package-type.wrapper.application" ], "Type" : "ProductType", "CanEmbedCompilerSanitizerLibraries" : "YES", "Identifier" : "com.apple.product-type.application", "IconNamePrefix" : "TargetApp" }, { "PackageTypes" : [ "com.apple.package-type.wrapper.application.shallow" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.application", "Name" : "Application (Shallow Bundle)", "Identifier" : "com.apple.product-type.application.shallow", "Description" : "Application (Shallow Bundle)", "Class" : "PBXApplicationProductType" }, { "DefaultBuildProperties" : { "PKGINFO_PATH" : "", "INFOPLIST_PATH" : "" }, "IsJava" : "YES", "Type" : "ProductType", "BasedOn" : "com.apple.product-type.application", "Name" : "Java Application", "Identifier" : "com.apple.product-type.application.java", "Description" : "Java Application", "DefaultTargetName" : "Java Application" }, { "IconNamePrefix" : "TargetFramework", "DefaultTargetName" : "Framework", "DefaultBuildProperties" : { "CODE_SIGNING_REQUIRES_TEAM" : "YES", "LD_DYLIB_INSTALL_NAME" : "$(DYLIB_INSTALL_NAME_BASE:standardizepath)\/$(EXECUTABLE_PATH)", "CODE_SIGNING_REQUIRED" : "NO", "CODE_SIGNING_ALLOWED" : "YES", "INSTALL_PATH" : "$(LOCAL_LIBRARY_DIR)\/Frameworks", "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)", "WRAPPER_EXTENSION" : "framework", "FRAMEWORK_VERSION" : "A", "ENTITLEMENTS_REQUIRED" : "NO", "STRIP_STYLE" : "debugging", "DYLIB_INSTALL_NAME_BASE" : "$(INSTALL_PATH)", "MACH_O_TYPE" : "mh_dylib" }, "PackageTypes" : [ "com.apple.package-type.wrapper.framework" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.bundle", "Name" : "Framework", "Identifier" : "com.apple.product-type.framework", "Description" : "Framework", "Class" : "PBXFrameworkProductType" }, { "PackageTypes" : [ "com.apple.package-type.wrapper.framework.shallow" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.framework", "Name" : "Framework (Shallow Bundle)", "Identifier" : "com.apple.product-type.framework.shallow", "Description" : "Framework (Shallow Bundle)", "Class" : "PBXFrameworkProductType" }, { "IconNamePrefix" : "TargetFramework", "DefaultTargetName" : "Static Framework", "DefaultBuildProperties" : { "WRAPPER_EXTENSION" : "framework", "DYLIB_INSTALL_NAME_BASE" : "", "CODE_SIGNING_ALLOWED" : "NO", "FRAMEWORK_VERSION" : "A", "LD_DYLIB_INSTALL_NAME" : "", "GCC_INLINES_ARE_PRIVATE_EXTERN" : "NO", "INSTALL_PATH" : "$(LOCAL_LIBRARY_DIR)\/Frameworks", "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)", "MACH_O_TYPE" : "staticlib" }, "AlwaysPerformSeparateStrip" : "YES", "PackageTypes" : [ "com.apple.package-type.wrapper.framework.static" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.framework", "Name" : "Static Framework", "Identifier" : "com.apple.product-type.framework.static", "Description" : "Static Framework", "Class" : "XCStaticFrameworkProductType" }, { "DefaultTargetName" : "Kernel Extension", "DefaultBuildProperties" : { "GCC_ENABLE_BUILTIN_FUNCTIONS" : "NO", "MODULE_START" : "0", "PRIVATE_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/PrivateHeaders\/$(KEXT_FAMILY_NAME)", "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)", "MACH_O_TYPE" : "mh_execute", "GCC_ENABLE_KERNEL_DEVELOPMENT" : "YES", "PRODUCT_TYPE_CPLUSPLUSFLAGS" : "$(inherited) $(KEXT_CPLUSPLUSFLAGS)", "MODULE_STOP" : "0", "GCC_ENABLE_FLOATING_POINT_LIBRARY_CALLS" : "YES", "GCC_PRODUCT_TYPE_PREPROCESSOR_DEFINITIONS" : "$(inherited) KERNEL KERNEL_PRIVATE DRIVER_PRIVATE APPLE NeXT", "GCC_DISABLE_STATIC_FUNCTION_INLINING" : "YES", "ENABLE_APPLE_KEXT_CODE_GENERATION" : "YES", "CODE_SIGNING_ALLOWED" : "YES", "GCC_FORCE_CPU_SUBTYPE_ALL" : "YES", "PRODUCT_SPECIFIC_LDFLAGS" : "$(inherited) $(KEXT_LDFLAGS)", "WRAPPER_EXTENSION" : "kext", "KERNEL_EXTENSION_HEADER_SEARCH_PATHS" : "$(KERNEL_FRAMEWORK)\/PrivateHeaders $(KERNEL_FRAMEWORK_HEADERS)", "GCC_INLINES_ARE_PRIVATE_EXTERN" : "NO", "PRODUCT_TYPE_CFLAGS" : "$(inherited) $(KEXT_CFLAGS)", "KEXT_FRAMEWORK_NAME" : "Kernel", "GCC_NO_COMMON_BLOCKS" : "YES", "GCC_ENABLE_PASCAL_STRINGS" : "NO", "PUBLIC_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/Headers\/$(KEXT_FAMILY_NAME)", "GCC_ENABLE_FUNCTION_INLINING" : "YES", "KERNEL_FRAMEWORK_HEADERS" : "$(KERNEL_FRAMEWORK)\/Headers", "KEXT_FAMILY_NAME" : "family", "KEXT_FRAMEWORK" : "$(SYSTEM_LIBRARY_DIR)\/Frameworks\/$(KEXT_FRAMEWORK_NAME).framework", "GCC_ENABLE_CPP_EXCEPTIONS" : "NO", "GCC_ENABLE_CPP_RTTI" : "NO", "MODULE_NAME" : "com.company.driver.modulename", "GCC_USE_STANDARD_INCLUDE_SEARCHING" : "NO", "KERNEL_FRAMEWORK" : "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)\/Frameworks\/Kernel.framework", "MODULE_VERSION" : "1.0", "INSTALL_PATH" : "$(DEFAULT_KEXT_INSTALL_PATH)", "PRODUCT_TYPE_HEADER_SEARCH_PATHS" : "$(inherited) $(KERNEL_EXTENSION_HEADER_SEARCH_PATHS)", "GCC_CHECK_RETURN_VALUE_OF_OPERATOR_NEW" : "YES", "STRIP_STYLE" : "debugging" }, "PackageTypes" : [ "com.apple.package-type.wrapper.kernel-extension", "com.apple.package-type.wrapper.kernel-extension.shallow" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.bundle", "Name" : "Kernel Extension", "Identifier" : "com.apple.product-type.kernel-extension", "Description" : "Kernel extension", "Class" : "XCKernelExtensionProductType" }, { "DefaultBuildProperties" : { }, "PackageTypes" : [ "com.apple.package-type.wrapper.kernel-extension.shallow" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.kernel-extension", "Name" : "Kernel Extension (Shallow)", "Identifier" : "com.apple.product-type.kernel-extension.shallow", "Description" : "Kernel extension (shallow)", "Class" : "XCKernelExtensionProductType" }, { "DefaultTargetName" : "IOKit Kernel Extension", "DefaultBuildProperties" : { "CODE_SIGNING_ALLOWED" : "YES" }, "PackageTypes" : [ "com.apple.package-type.wrapper.kernel-extension", "com.apple.package-type.wrapper.kernel-extension.shallow" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.kernel-extension", "Name" : "IOKit Kernel Extension", "Identifier" : "com.apple.product-type.kernel-extension.iokit", "Description" : "IOKit Kernel extension", "Class" : "XCKernelExtensionProductType" }, { "DefaultTargetName" : "IOKit Kernel Extension (Shallow)", "DefaultBuildProperties" : { }, "PackageTypes" : [ "com.apple.package-type.wrapper.kernel-extension.shallow" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.kernel-extension", "Name" : "IOKit Kernel Extension (Shallow)", "Identifier" : "com.apple.product-type.kernel-extension.iokit.shallow", "Description" : "IOKit Kernel extension (Shallow)", "Class" : "XCKernelExtensionProductType" }, { "DefaultBuildProperties" : { "TEST_FRAMEWORK_SEARCH_PATHS" : [ "$(inherited)", "$(PLATFORM_DIR)\/Developer\/Library\/Frameworks" ], "PRODUCT_SPECIFIC_LDFLAGS" : "-framework XCTest", "WRAPPER_EXTENSION" : "xctest", "PRODUCT_TYPE_FRAMEWORK_SEARCH_PATHS" : "$(TEST_FRAMEWORK_SEARCH_PATHS)" }, "PackageTypes" : [ "com.apple.package-type.bundle.unit-test" ], "CanEmbedCompilerSanitizerLibraries" : "YES", "IsUnitTest" : "YES", "Type" : "ProductType", "BasedOn" : "com.apple.product-type.bundle", "Name" : "Unit Test Bundle", "Identifier" : "com.apple.product-type.bundle.unit-test", "Description" : "Unit Test Bundle", "Class" : "PBXXCTestBundleProductType" }, { "DefaultBuildProperties" : { "TEST_FRAMEWORK_SEARCH_PATHS" : [ "$(inherited)", "$(PLATFORM_DIR)\/Developer\/Library\/Frameworks" ], "PRODUCT_SPECIFIC_LDFLAGS" : "-framework XCTest", "WRAPPER_EXTENSION" : "xctest", "USES_XCTRUNNER" : "YES", "PRODUCT_TYPE_FRAMEWORK_SEARCH_PATHS" : "$(TEST_FRAMEWORK_SEARCH_PATHS)" }, "PackageTypes" : [ "com.apple.package-type.bundle.unit-test" ], "ProvisioningProfileSupported" : "YES", "IsUITest" : "YES", "Type" : "ProductType", "BasedOn" : "com.apple.product-type.bundle.unit-test", "Name" : "UI Testing Bundle", "Identifier" : "com.apple.product-type.bundle.ui-testing", "Description" : "UI Testing Bundle", "Class" : "PBXXCTestBundleProductType" }, { "DefaultBuildProperties" : { "WRAPPER_EXTENSION" : "octest" }, "PackageTypes" : [ "com.apple.package-type.bundle.ocunit-test" ], "IsUnitTest" : "YES", "Type" : "ProductType", "BasedOn" : "com.apple.product-type.bundle", "Name" : "OCUnit Test Bundle", "Identifier" : "com.apple.product-type.bundle.ocunit-test", "Description" : "OCUnit Test Bundle", "Class" : "PBXBundleProductType" }, { "HasInfoPlistStrings" : "NO", "PackageTypes" : [ "com.apple.package-type.in-app-purchase-content" ], "HasInfoPlist" : "YES", "IsWrapper" : "YES", "Type" : "ProductType", "DefaultBuildProperties" : { "FULL_PRODUCT_NAME" : "$(WRAPPER_NAME)" }, "Name" : "In-App Purchase Content", "Identifier" : "com.apple.product-type.in-app-purchase-content", "Description" : "In-App Purchase Content", "Class" : "PBXBundleProductType" }, { "IconNamePrefix" : "XPCService", "DefaultTargetName" : "XPC Service", "CanEmbedCompilerSanitizerLibraries" : "YES", "DefaultBuildProperties" : { "MACH_O_TYPE" : "mh_execute", "WRAPPER_EXTENSION" : "xpc" }, "PackageTypes" : [ "com.apple.package-type.xpc-service" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.bundle", "Name" : "XPC Service", "Identifier" : "com.apple.product-type.xpc-service", "Description" : "XPC Service", "Class" : "PBXBundleProductType" }, { "IconNamePrefix" : "XPCService", "DefaultTargetName" : "PlugInKit PlugIn", "DefaultBuildProperties" : { "WRAPPER_EXTENSION" : "pluginkit", "PRODUCT_SPECIFIC_LDFLAGS" : "$(SDKROOT)\/System\/Library\/PrivateFrameworks\/PlugInKit.framework\/PlugInKit" }, "PackageTypes" : [ "com.apple.package-type.pluginkit-plugin" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.xpc-service", "Name" : "PlugInKit PlugIn", "Identifier" : "com.apple.product-type.pluginkit-plugin", "Description" : "PlugInKit PlugIn", "Class" : "PBXBundleProductType" }, { "Description" : "App Extension", "Class" : "PBXBundleProductType", "Name" : "App Extension", "ProvisioningProfileSupported" : "YES", "DefaultTargetName" : "App Extension", "DefaultBuildProperties" : { "APPLICATION_EXTENSION_API_ONLY" : "YES", "PRODUCT_SPECIFIC_LDFLAGS" : "-e _NSExtensionMain", "WRAPPER_EXTENSION" : "appex", "CODE_SIGNING_ALLOWED" : "YES" }, "BasedOn" : "com.apple.product-type.pluginkit-plugin", "ProvisioningProfileRequired" : "NO", "PackageTypes" : [ "com.apple.package-type.app-extension" ], "Type" : "ProductType", "Identifier" : "com.apple.product-type.app-extension", "IconNamePrefix" : "AppExtension" }, { "Description" : "Xcode Extension", "Class" : "PBXBundleProductType", "Name" : "Xcode Extension", "ProvisioningProfileSupported" : "YES", "DefaultTargetName" : "Xcode Extension", "DefaultBuildProperties" : { "APPLICATION_EXTENSION_API_ONLY" : "YES", "PRODUCT_SPECIFIC_LDFLAGS" : "-e _XCExtensionMain -lXcodeExtension -weak_framework XcodeKit", "PRODUCT_TYPE_LIBRARY_SEARCH_PATHS" : [ "$(inherited)", "$(DEVELOPER_USR_DIR)\/lib" ], "CODE_SIGNING_ALLOWED" : "YES", "WRAPPER_EXTENSION" : "appex", "PRODUCT_TYPE_FRAMEWORK_SEARCH_PATHS" : [ "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)" ] }, "BasedOn" : "com.apple.product-type.app-extension", "ProvisioningProfileRequired" : "NO", "PackageTypes" : [ "com.apple.package-type.app-extension" ], "Type" : "ProductType", "Identifier" : "com.apple.product-type.xcode-extension", "IconNamePrefix" : "XcodeExtension" }, { "DefaultTargetName" : "Spotlight", "DefaultBuildProperties" : { "CODE_SIGNING_ALLOWED" : "YES" }, "PackageTypes" : [ "com.apple.package-type.spotlight-importer" ], "Type" : "ProductType", "BasedOn" : "com.apple.product-type.bundle", "Name" : "Spotlight Importer", "Identifier" : "com.apple.product-type.spotlight-importer", "Description" : "Spotlight Importer", "Class" : "PBXBundleProductType" } ] qbs-src-1.13.1/share/qbs/modules/bundle/bundle.js000066400000000000000000000267371347155106100216100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var DarwinTools = require("qbs.DarwinTools"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); // HACK: Workaround until the PropertyList extension is supported cross-platform var TextFile = require("qbs.TextFile"); var PropertyList2 = (function () { function PropertyList2() { } PropertyList2.prototype.readFromFile = function (filePath) { var str; var process = new Process(); try { if (process.exec("plutil", ["-convert", "json", "-o", "-", filePath], false) === 0) { str = process.readStdOut(); } else { var tf = new TextFile(filePath); try { str = tf.readAll(); } finally { tf.close(); } } } finally { process.close(); } if (str) this.obj = JSON.parse(str); }; PropertyList2.prototype.toObject = function () { return this.obj; }; PropertyList2.prototype.clear = function () { }; return PropertyList2; }()); // Order is significant due to productTypeIdentifier() search path var _productTypeIdentifiers = { "inapppurchase": "com.apple.product-type.in-app-purchase-content", "applicationextension": "com.apple.product-type.app-extension", "xpcservice": "com.apple.product-type.xpc-service", "application": "com.apple.product-type.application", "dynamiclibrary": "com.apple.product-type.framework", "loadablemodule": "com.apple.product-type.bundle", "staticlibrary": "com.apple.product-type.framework.static", "kernelmodule": "com.apple.product-type.kernel-extension" }; function productTypeIdentifier(productType) { for (var k in _productTypeIdentifiers) { if (productType.contains(k)) return _productTypeIdentifiers[k]; } return "com.apple.package-type.wrapper"; } function excludedAuxiliaryInputs(project, product) { var chain = product.moduleProperty("bundle", "_productTypeIdentifierChain"); var bestPossibleType; for (var i = chain.length - 1; i >= 0; --i) { switch (chain[i]) { case "com.apple.product-type.bundle": bestPossibleType = "loadablemodule"; break; case "com.apple.product-type.framework": bestPossibleType = "dynamiclibrary"; break; case "com.apple.product-type.framework.static": bestPossibleType = "staticlibrary"; break; case "com.apple.product-type.application": case "com.apple.product-type.xpc-service": bestPossibleType = "application"; break; } } var excluded = []; var possibleTypes = ["application", "dynamiclibrary", "staticlibrary", "loadablemodule"]; for (i = 0; i < possibleTypes.length; ++i) { if (possibleTypes[i] !== bestPossibleType) excluded.push(possibleTypes[i]); } return excluded; } function packageType(productTypeIdentifier) { switch (productTypeIdentifier) { case "com.apple.product-type.in-app-purchase-content": return undefined; case "com.apple.product-type.app-extension": case "com.apple.product-type.xpc-service": return "XPC!"; case "com.apple.product-type.application": return "APPL"; case "com.apple.product-type.framework": case "com.apple.product-type.framework.static": return "FMWK"; case "com.apple.product-type.kernel-extension": case "com.apple.product-type.kernel-extension.iokit": return "KEXT"; default: return "BNDL"; } } function _assign(target, source) { if (source) { for (var k in source) { if (source.hasOwnProperty(k)) target[k] = source[k]; } return target; } } var XcodeBuildSpecsReader = (function () { function XcodeBuildSpecsReader(specsPath, separator, additionalSettings, useShallowBundles) { this._additionalSettings = additionalSettings; this._useShallowBundles = useShallowBundles; var i; var plist = new PropertyList2(); var plist2 = new PropertyList2(); try { plist.readFromFile(specsPath + ["/MacOSX", "Package", "Types.xcspec"].join(separator)); plist2.readFromFile(specsPath + ["/MacOSX", "Product", "Types.xcspec"].join(separator)); this._packageTypes = plist.toObject(); this._productTypes = plist2.toObject(); this._types = {}; for (i = 0; i < this._packageTypes.length; ++i) this._types[this._packageTypes[i]["Identifier"]] = this._packageTypes[i]; for (i = 0; i < this._productTypes.length; ++i) this._types[this._productTypes[i]["Identifier"]] = this._productTypes[i]; } finally { plist.clear(); plist2.clear(); } } XcodeBuildSpecsReader.prototype.productTypeIdentifierChain = function (typeIdentifier) { var ids = [typeIdentifier]; var obj = this._types[typeIdentifier]; var parentId = obj && obj["BasedOn"]; if (parentId) return ids.concat(this.productTypeIdentifierChain(parentId)); return ids; }; XcodeBuildSpecsReader.prototype.settings = function (typeIdentifier, recursive, skipPackageTypes) { // Silently use shallow bundles when preferred since it seems to be some sort of automatic // shadowing mechanism. For example, this matches Xcode behavior where static frameworks // are shallow even though no such product specification exists, and also seems to match // other behavior i.e. where productType in pbxproj files is never explicitly shallow. if (this._useShallowBundles && this._types[typeIdentifier + ".shallow"] && !skipPackageTypes) typeIdentifier += ".shallow"; var typesObject = this._types[typeIdentifier]; if (typesObject) { var buildProperties = {}; if (recursive) { // Get all the settings for the product's package type if (!skipPackageTypes && typesObject["PackageTypes"]) { for (var k = 0; k < typesObject["PackageTypes"].length; ++k) { var props = this.settings(typesObject["PackageTypes"][k], recursive, true); for (var y in props) { if (props.hasOwnProperty(y)) buildProperties[y] = props[y]; } break; } } // Get all the settings for the product's inherited product type if (typesObject["BasedOn"]) { // We'll only do the auto shallow substitution for wrapper package types... // this ensures that in-app purchase content bundles are non-shallow on both // macOS and iOS, for example (which matches Xcode behavior) var isWrapper = false; if (typesObject["ProductReference"]) { var fileType = typesObject["ProductReference"]["FileType"]; if (fileType) isWrapper = fileType.startsWith("wrapper."); } // Prevent recursion loop if this spec's base plus .shallow would be the same // as the current spec's identifier var baseIdentifier = typesObject["BasedOn"]; if (this._useShallowBundles && isWrapper && this._types[baseIdentifier + ".shallow"] && typeIdentifier !== baseIdentifier + ".shallow") baseIdentifier += ".shallow"; props = this.settings(baseIdentifier, recursive, true); for (y in props) { if (props.hasOwnProperty(y)) buildProperties[y] = props[y]; } } } if (typesObject["Type"] === "PackageType") { props = typesObject["DefaultBuildSettings"]; for (y in props) { if (props.hasOwnProperty(y)) buildProperties[y] = props[y]; } } if (typesObject["Type"] === "ProductType") { props = typesObject["DefaultBuildProperties"]; for (y in props) { if (props.hasOwnProperty(y)) buildProperties[y] = props[y]; } } return buildProperties; } }; XcodeBuildSpecsReader.prototype.setting = function (typeIdentifier, settingName) { var obj = this.settings(typeIdentifier, false); if (obj) { return obj[settingName]; } }; XcodeBuildSpecsReader.prototype.expandedSettings = function (typeIdentifier, baseSettings) { var obj = this.settings(typeIdentifier, true); if (obj) { for (var k in obj) obj[k] = this.expandedSetting(typeIdentifier, baseSettings, k); return obj; } }; XcodeBuildSpecsReader.prototype.expandedSetting = function (typeIdentifier, baseSettings, settingName) { var obj = baseSettings || {}; obj = _assign(obj, this.settings(typeIdentifier, true)); if (obj) { for (var x in this._additionalSettings) { var additionalSetting = this._additionalSettings[x]; if (additionalSetting !== undefined) obj[x] = additionalSetting; } var setting = obj[settingName]; var original; while (original !== setting) { original = setting; setting = DarwinTools.expandPlistEnvironmentVariables({ key: setting }, obj, true)["key"]; } return setting; } }; return XcodeBuildSpecsReader; }()); qbs-src-1.13.1/share/qbs/modules/cli/000077500000000000000000000000001347155106100172605ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/cli/CLIModule.qbs000066400000000000000000000157361347155106100215600ustar00rootroot00000000000000// base for Common Language Infrastructure modules import qbs.FileInfo import qbs.ModUtils import "cli.js" as CLI Module { Depends { name: "bundle"; condition: qbs.targetOS.contains("darwin") } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } condition: false property string warningLevel: 'all' // 'none', 'all' property bool treatWarningsAsErrors: false property string architecture: "anycpu" // for the CLI this is a much better default than qbs.architecture property string optimization: qbs.optimization property bool debugInformation: qbs.debugInformation property stringList defines property stringList platformDefines: qbs.enableDebugCode ? [] : ["NDEBUG"] property stringList compilerDefines PropertyOptions { name: "compilerDefines" description: "preprocessor macros that are defined when using this particular compiler" } property pathList libraryPaths property string csharpCompilerName property string csharpCompilerPath: FileInfo.joinPaths(toolchainInstallPath, csharpCompilerName) property string vbCompilerName property string vbCompilerPath: FileInfo.joinPaths(toolchainInstallPath, vbCompilerName) property string fsharpCompilerName property string fsharpCompilerPath: FileInfo.joinPaths(toolchainInstallPath, fsharpCompilerName) property string resgenName: "resgen" property string resgenPath: FileInfo.joinPaths(toolchainInstallPath, resgenName) property string dynamicLibrarySuffix: ".dll" property string executableSuffix: ".exe" property string netmoduleSuffix: ".netmodule" property string debugInfoSuffix property stringList dynamicLibraries // list of names, will be linked with /reference:name property stringList netmodules // list of netmodule files, will be linked with /addmodule:name property bool generateManifestFile: true property string toolchainInstallPath property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional compiler flags" } // Platform properties. Those are intended to be set by the toolchain setup // and are prepended to the corresponding user properties. property stringList platformCompilerFlags FileTagger { patterns: ["*.cs", "*.CS"] fileTags: ["cli.csharp"] } FileTagger { patterns: ["*.vb", "*.VB"] fileTags: ["cli.vb"] } FileTagger { patterns: ["*.fs", "*.FS"] fileTags: ["cli.fsharp"] } FileTagger { patterns: ["*.fsi", "*.FSI"] fileTags: ["cli.fsharp_signature"] } FileTagger { patterns: ["*.resx", "*.RESX"] fileTags: ["cli.resx"] } validate: { var validator = new ModUtils.PropertyValidator("cli"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.validate(); } setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, product.qbs.hostOS.contains("windows")); v.prepend(product.cli.toolchainInstallPath); v.set(); } Rule { id: cliApplication multiplex: true inputs: ["cli.csharp", "cli.vb", "cli.fsharp"] inputsFromDependencies: ["cli.netmodule", "dynamiclibrary", "cli.resources"] Artifact { fileTags: ["application"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "executableSuffix")) } Artifact { fileTags: ["debuginfo_app"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "debugInfoSuffix")) } prepare: { return CLI.prepareCompiler(product, inputs, outputs.application[0]); } } Rule { id: cliDynamicLibrary multiplex: true inputs: ["cli.csharp", "cli.vb", "cli.fsharp"] inputsFromDependencies: ["cli.netmodule", "dynamiclibrary", "cli.resources"] Artifact { fileTags: ["dynamiclibrary"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "dynamicLibrarySuffix")) } Artifact { fileTags: ["debuginfo_dll"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "debugInfoSuffix")) } prepare: { return CLI.prepareCompiler(product, inputs, outputs.dynamiclibrary[0]); } } Rule { id: netmodule multiplex: true inputs: ["cli.csharp", "cli.vb", "cli.fsharp"] inputsFromDependencies: ["cli.netmodule", "dynamiclibrary", "cli.resources"] Artifact { fileTags: ["cli.netmodule"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "netmoduleSuffix")) } Artifact { fileTags: ["debuginfo_netmodule"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.moduleProperty(product.moduleName, "debugInfoSuffix")) } prepare: { return CLI.prepareCompiler(product, inputs, outputs["cli.netmodule"][0]); } } Rule { inputs: ["cli.resx"] Artifact { fileTags: ["cli.resources"] filePath: FileInfo.joinPaths(product.destinationDirectory, input.completeBaseName + ".resources") } prepare: { var args = [ input.filePath, output.filePath ]; var cmd = new Command(ModUtils.moduleProperty(product, "resgenPath"), args); cmd.description = "building " + input.fileName; cmd.highlight = "compiler"; cmd.workingDirectory = FileInfo.path(output.filePath); return cmd; } } } qbs-src-1.13.1/share/qbs/modules/cli/cli.js000066400000000000000000000162131347155106100203700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); function prepareCompiler(product, inputs, output) { var i; var args = ["/nologo"]; var platformDefines = product.moduleProperty("cli", "platformDefines"); var compilerDefines = product.moduleProperty("cli", "compilerDefines"); var defines = product.moduleProperty("cli", "defines"); var platformCompilerFlags = product.moduleProperty("cli", "platformCompilerFlags"); var compilerFlags = product.moduleProperty("cli", "compilerFlags") var libraryPaths = product.moduleProperty("cli", "libraryPaths"); var dynamicLibraries = product.moduleProperty("cli", "dynamicLibraries"); var netmodules = product.moduleProperty("cli", "netmodules"); var warnAsError = product.moduleProperty("cli", "treatWarningsAsErrors"); var warningLevel = product.moduleProperty("cli", "warningLevel"); var debugInformation = product.moduleProperty("cli", "debugInformation"); var optimization = product.moduleProperty("cli", "optimization"); var architecture = product.moduleProperty("cli", "architecture"); var csharpCompilerPath = product.moduleProperty("cli", "csharpCompilerPath"); var vbCompilerPath = product.moduleProperty("cli", "vbCompilerPath"); var fsharpCompilerPath = product.moduleProperty("cli", "fsharpCompilerPath"); var compilers = { "cli.csharp": csharpCompilerPath, "cli.vb": vbCompilerPath, "cli.fsharp": fsharpCompilerPath }; var pathFunction = product.moduleProperty("qbs", "hostOS").contains("windows") ? FileInfo.toWindowsSeparators : function (path) { return path; }; var outputDescription = "assembly"; if (output.fileTags.contains("application")) { args.push("/target:" + (product.consoleApplication === false ? "winexe" : "exe")); } else if (output.fileTags.contains("dynamiclibrary")) { args.push("/target:library"); } else if (output.fileTags.contains("cli.netmodule")) { args.push("/target:module"); outputDescription = "netmodule"; } // Make sure our input files are all the same language var keys = Object.keys(inputs); var language; for (i in keys) { if (Object.keys(compilers).contains(keys[i])) { if (language) throw("You cannot compile source files in more than one CLI language into a single " + outputDescription + "."); language = keys[i]; } } if (!compilers[language]) { throw("No CLI compiler available to compile " + language + " files."); } // docs state "/platform is not available in the development environment in Visual C# Express" // does this mean from the IDE or the compiler itself shipped with Express does not support it? if (architecture !== undefined) { if (architecture === "x86" || architecture === "anycpu" || architecture === "anycpu32bitpreferred") // requires .NET 4.5 ; else if (architecture === "x86_64") architecture = "x64"; else if (architecture === "ia64") architecture = "Itanium"; else if (architecture === "arm") architecture = "ARM"; else throw("Invalid CLI architecture: " + architecture); args.push("/platform:" + architecture); } if (debugInformation !== undefined) args.push("/debug" + (debugInformation ? "+" : "-")); if (optimization !== undefined) args.push("/optimize" + (optimization !== "none" ? "+" : "-")); if (warnAsError !== undefined) args.push("/warnaserror" + (warnAsError ? "+" : "-")); if (warningLevel !== undefined) { if (language === "cli.vb") { if (warningLevel === "none" || warningLevel === "0") args.push("/quiet"); } else { if (warningLevel === "all") warningLevel = "4"; else if (warningLevel === "none") warningLevel = "0"; args.push("/warn:" + warningLevel); } } // Preprocessor defines var allDefines = (platformDefines || []).concat(compilerDefines || []).concat(defines || []); if (allDefines.length > 0) args.push("/define:" + allDefines.join(";")); // Library search paths for (i in libraryPaths) args.push("/lib:" + libraryPaths.join(",")); // Dependent libraries for (i in dynamicLibraries) { args.push("/reference:" + dynamicLibraries[i] + product.moduleProperty("cli", "dynamicLibrarySuffix")); } for (i in inputs.dynamiclibrary) args.push("/reference:" + inputs.dynamiclibrary[i].filePath); // Dependent netmodules for (i in netmodules) { args.push("/addmodule:" + netmodules.map(function (f) { return f + product.moduleProperty("cli", "netmoduleSuffix"); }).join(";")); } if (inputs["cli.netmodule"]) { args.push("/addmodule:" + inputs["cli.netmodule"].map(function (f) { return f.filePath; }).join(";")); } // Dependent resources for (i in inputs["cli.resources"]) args.push("/resource:" + pathFunction(inputs["cli.resources"][i].filePath)); // Additional compiler flags args = args.concat((platformCompilerFlags || []).concat(compilerFlags || [])); args.push("/out:" + pathFunction(output.filePath)); for (i in inputs[keys[0]]) args.push(pathFunction(inputs[keys[0]][i].filePath)); var cmd = new Command(compilers[language], args); cmd.description = "linking " + output.fileName; cmd.highlight = "linker"; cmd.workingDirectory = FileInfo.path(output.filePath); return cmd; } qbs-src-1.13.1/share/qbs/modules/cli/mono.qbs000066400000000000000000000012131347155106100207340ustar00rootroot00000000000000import qbs.File import qbs.Probes CLIModule { condition: qbs.toolchain && qbs.toolchain.contains("mono") debugInfoSuffix: ".mdb" csharpCompilerName: "mcs" vbCompilerName: "vbnc" fsharpCompilerName: "fsharpc" Probes.PathProbe { id: monoProbe names: ["mono"] platformSearchPaths: { var paths = []; if (qbs.hostOS.contains("macos")) paths.push("/Library/Frameworks/Mono.framework/Commands"); if (qbs.hostOS.contains("unix")) paths.push("/usr/bin"); return paths; } } toolchainInstallPath: monoProbe.path } qbs-src-1.13.1/share/qbs/modules/cli/windows-dotnet.qbs000066400000000000000000000020071347155106100227530ustar00rootroot00000000000000import qbs.Utilities CLIModule { condition: qbs.toolchain && qbs.toolchain.contains("dotnet") debugInfoSuffix: ".pdb" csharpCompilerName: "csc" vbCompilerName: "vbc" fsharpCompilerName: "fsc" Probe { id: dotnetProbe property string toolchainInstallPath // Output configure: { // https://msdn.microsoft.com/en-us/library/hh925568.aspx var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\NET Framework Setup\\NDP" ]; for (var i in keys) { var key = keys[i] + "\\v4\\Full"; var value = Utilities.getNativeSetting(key, "InstallPath"); if (value) { toolchainInstallPath = value; found = true; break; } } } } toolchainInstallPath: dotnetProbe.toolchainInstallPath } qbs-src-1.13.1/share/qbs/modules/cpp/000077500000000000000000000000001347155106100172735ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/cpp/CppModule.qbs000066400000000000000000000457231347155106100217050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // base for Cpp modules import qbs.ModUtils import qbs.Utilities import qbs.WindowsUtils import "setuprunenv.js" as SetupRunEnv Module { condition: false Depends { name: "cpufeatures" } version: compilerVersion property string compilerVersion: [compilerVersionMajor, compilerVersionMinor, compilerVersionPatch].join(".") property int compilerVersionMajor property int compilerVersionMinor property int compilerVersionPatch property string warningLevel : 'all' // 'none', 'all' property bool treatWarningsAsErrors : false property bool enableSuspiciousLinkerFlagWarnings: true property string architecture: qbs.architecture property string endianness property string machineType // undocumented property string imageFormat // undocumented property string optimization: qbs.optimization property bool debugInformation: qbs.debugInformation property bool enableReproducibleBuilds: false property bool separateDebugInformation: false property pathList prefixHeaders property bool useCPrecompiledHeader: true property bool useCxxPrecompiledHeader: true property bool useObjcPrecompiledHeader: true property bool useObjcxxPrecompiledHeader: true property bool treatSystemHeadersAsDependencies: false property stringList defines property stringList platformDefines: qbs.enableDebugCode ? [] : ["NDEBUG"] property stringList compilerDefines: compilerDefinesByLanguage ? ModUtils.flattenDictionary(compilerDefinesByLanguage["c"]) : [] property var compilerDefinesByLanguage: undefined PropertyOptions { name: "compilerDefinesByLanguage" description: "preprocessor macros that are defined when using this particular compiler" } property stringList enableCompilerDefinesByLanguage: [] property string windowsApiCharacterSet property string windowsApiFamily property stringList windowsApiAdditionalPartitions property bool requireAppContainer property string minimumWindowsVersion PropertyOptions { name: "minimumWindowsVersion" description: "A version number in the format [major].[minor] indicating the earliest \ version of Windows that the product should run on. Defines WINVER, \ _WIN32_WINNT, and _WIN32_WINDOWS, and applies a version number to the \ linker flags /SUBSYSTEM and /OSVERSION for MSVC or \ --major-subsystem-version, --minor-subsystem-version, \ --major-os-version and --minor-os-version for MinGW. \ If undefined, compiler defaults will be used." } property string minimumOsxVersion property string minimumMacosVersion: minimumOsxVersion PropertyOptions { name: "minimumMacosVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of macOS that the product should run on. passes -mmacosx-version-min= \ to the compiler. if undefined, compiler defaults will be used." } property string minimumIosVersion PropertyOptions { name: "minimumIosVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of iOS that the product should run on. passes -miphoneos-version-min= \ to the compiler. if undefined, compiler defaults will be used." } property string minimumWatchosVersion PropertyOptions { name: "minimumWatchosVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of watchOS that the product should run on. if undefined, compiler \ defaults will be used." } property string minimumTvosVersion PropertyOptions { name: "minimumTvosVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of tvOS that the product should run on. if undefined, compiler \ defaults will be used." } property string minimumAndroidVersion PropertyOptions { name: "minimumAndroidVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of Android that the product should run on. this value is converted into an SDK \ version which is then written to AndroidManifest.xml." } property string maximumAndroidVersion PropertyOptions { name: "maximumAndroidVersion" description: "a version number in the format [major].[minor] indicating the latest \ version of Android that the product should run on. this value is converted into an SDK \ version which is then written to AndroidManifest.xml. if undefined, no upper limit will \ be set." } property pathList includePaths property pathList systemIncludePaths property pathList distributionIncludePaths property pathList compilerIncludePaths property pathList libraryPaths property pathList distributionLibraryPaths property pathList compilerLibraryPaths property pathList frameworkPaths property pathList systemFrameworkPaths property pathList distributionFrameworkPaths property pathList compilerFrameworkPaths property stringList systemRunPaths: [] property string assemblerName property string assemblerPath: assemblerName property string compilerName property string compilerPath: compilerName property var compilerPathByLanguage property stringList compilerWrapper property string linkerName property string linkerPath: linkerName property stringList linkerWrapper property string staticLibraryPrefix: "" property string dynamicLibraryPrefix: "" property string loadableModulePrefix: "" property string executablePrefix: "" property string staticLibrarySuffix: "" property string dynamicLibrarySuffix: "" property string loadableModuleSuffix: "" property string executableSuffix: "" property string debugInfoSuffix: "" property string debugInfoBundleSuffix: "" property string variantSuffix: "" property string dynamicLibraryImportSuffix: ".lib" property bool createSymlinks: true property stringList dynamicLibraries // list of names, will be linked with -lname property stringList staticLibraries // list of static library files property stringList frameworks // list of frameworks, will be linked with '-framework ' property stringList weakFrameworks // list of weakly-linked frameworks, will be linked with '-weak_framework ' property string rpathOrigin property stringList rpaths property string sonamePrefix: "" property bool useRPaths: true property bool useRPathLink property string rpathLinkFlag property bool discardUnusedData property stringList assemblerFlags PropertyOptions { name: "assemblerFlags" description: "additional flags for the assembler" } property stringList cppFlags PropertyOptions { name: "cppFlags" description: "additional flags for the C preprocessor" } property stringList cFlags PropertyOptions { name: "cFlags" description: "additional flags for the C compiler" } property stringList cxxFlags PropertyOptions { name: "cxxFlags" description: "additional flags for the C++ compiler" } property stringList objcFlags PropertyOptions { name: "objcFlags" description: "additional flags for the Objective-C compiler" } property stringList objcxxFlags PropertyOptions { name: "objcxxFlags" description: "additional flags for the Objective-C++ compiler" } property stringList commonCompilerFlags PropertyOptions { name: "commonCompilerFlags" description: "flags added to all compilation independently of the language" } property stringList linkerFlags PropertyOptions { name: "linkerFlags" description: "additional linker flags" } property stringList driverFlags PropertyOptions { name: "driverFlags" description: "additional compiler driver flags" } property stringList driverLinkerFlags PropertyOptions { name: "driverLinkerFlags" description: "additional compiler driver flags used for linking only" } property bool positionIndependentCode: true PropertyOptions { name: "positionIndependentCode" description: "generate position independent code" } property string entryPoint PropertyOptions { name: "entryPoint" description: "entry point symbol for an executable or dynamic library" } property string runtimeLibrary PropertyOptions { name: "runtimeLibrary" description: "determine which runtime library to use" allowedValues: ['static', 'dynamic'] } property string visibility: 'default' PropertyOptions { name: "visibility" description: "export symbols visibility level" allowedValues: ['default', 'hidden', 'hiddenInlines', 'minimal'] } property stringList cLanguageVersion PropertyOptions { name: "cLanguageVersion" allowedValues: ["c89", "c99", "c11"] description: "The version of the C standard with which the code must comply." } property stringList cxxLanguageVersion PropertyOptions { name: "cxxLanguageVersion" allowedValues: ["c++98", "c++11", "c++14", "c++17"] description: "The version of the C++ standard with which the code must comply." } property bool useLanguageVersionFallback PropertyOptions { name: "useLanguageVersionFallback" description: "whether to explicitly use the language standard version fallback values in " + "compiler command line invocations" } property string cxxStandardLibrary PropertyOptions { name: "cxxStandardLibrary" allowedValues: ["libstdc++", "libc++"] description: "version of the C++ standard library to use" } property bool enableExceptions: true PropertyOptions { name: "enableExceptions" description: "enable/disable exception handling (enabled by default)" } property string exceptionHandlingModel: "default" PropertyOptions { name: "exceptionHandlingModel" description: "the kind of exception handling to be used by the compiler" } property bool enableRtti // Platform properties. Those are intended to be set by the toolchain setup // and are prepended to the corresponding user properties. property stringList platformAssemblerFlags property stringList platformCommonCompilerFlags property stringList platformCFlags property stringList platformCxxFlags property stringList platformObjcFlags property stringList platformObjcxxFlags property stringList platformLinkerFlags property stringList platformDriverFlags // Apple platforms properties property bool automaticReferenceCounting PropertyOptions { name: "automaticReferenceCounting" description: "whether to enable Automatic Reference Counting (ARC) for Objective-C" } property bool requireAppExtensionSafeApi PropertyOptions { name: "requireAppExtensionSafeApi" description: "whether to require app-extension-safe APIs only" } property bool allowUnresolvedSymbols property bool combineCSources: false property bool combineCxxSources: false property bool combineObjcSources: false property bool combineObjcxxSources: false property stringList targetAssemblerFlags property stringList targetDriverFlags property stringList targetLinkerFlags property bool _skipAllChecks: false // Internal property bool validateTargetTriple: true // TODO: The following four rules could use a convenience base item if rule properties // were available in Artifact items and prepare scripts. Rule { multiplex: true inputs: ["c.combine"] Artifact { filePath: "amalgamated_" + product.targetName + ".c" fileTags: ["c"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { ModUtils.mergeCFiles(inputs["c.combine"], output.filePath); }; return [cmd]; } } Rule { multiplex: true inputs: ["cpp.combine"] Artifact { filePath: "amalgamated_" + product.targetName + ".cpp" fileTags: ["cpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { ModUtils.mergeCFiles(inputs["cpp.combine"], output.filePath); }; return [cmd]; } } Rule { multiplex: true inputs: ["objc.combine"] Artifact { filePath: "amalgamated_" + product.targetName + ".m" fileTags: ["objc"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { ModUtils.mergeCFiles(inputs["objc.combine"], output.filePath); }; return [cmd]; } } Rule { multiplex: true inputs: ["objcpp.combine"] Artifact { filePath: "amalgamated_" + product.targetName + ".mm" fileTags: ["objccpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { ModUtils.mergeCFiles(inputs["objcpp.combine"], output.filePath); }; return [cmd]; } } FileTagger { patterns: ["*.c"] fileTags: combineCSources ? ["c.combine"] : ["c"] } FileTagger { patterns: ["*.C", "*.cpp", "*.cxx", "*.c++", "*.cc"] fileTags: combineCxxSources ? ["cpp.combine"] : ["cpp"] } FileTagger { patterns: ["*.m"] fileTags: combineObjcSources ? ["objc.combine"] : ["objc"] } FileTagger { patterns: ["*.mm"] fileTags: combineObjcxxSources ? ["objcpp.combine"] : ["objcpp"] } FileTagger { patterns: ["*.h", "*.H", "*.hpp", "*.hxx", "*.h++"] fileTags: ["hpp"] } validate: { var validator = new ModUtils.PropertyValidator("cpp"); validator.setRequiredProperty("architecture", architecture, "you might want to re-run 'qbs-setup-toolchains'"); validator.addCustomValidator("architecture", architecture, function (value) { return !architecture || architecture === Utilities.canonicalArchitecture(architecture); }, "'" + architecture + "' is invalid. You must use the canonical name '" + Utilities.canonicalArchitecture(architecture) + "'"); validator.setRequiredProperty("endianness", endianness); validator.setRequiredProperty("compilerDefinesByLanguage", compilerDefinesByLanguage); validator.setRequiredProperty("compilerVersion", compilerVersion); validator.setRequiredProperty("compilerVersionMajor", compilerVersionMajor); validator.setRequiredProperty("compilerVersionMinor", compilerVersionMinor); validator.setRequiredProperty("compilerVersionPatch", compilerVersionPatch); validator.addVersionValidator("compilerVersion", compilerVersion, 3, 3); validator.addRangeValidator("compilerVersionMajor", compilerVersionMajor, 1); validator.addRangeValidator("compilerVersionMinor", compilerVersionMinor, 0); validator.addRangeValidator("compilerVersionPatch", compilerVersionPatch, 0); if (minimumWindowsVersion) { validator.addVersionValidator("minimumWindowsVersion", minimumWindowsVersion, 2, 2); validator.addCustomValidator("minimumWindowsVersion", minimumWindowsVersion, function (v) { return !v || v === WindowsUtils.canonicalizeVersion(v); }, "'" + minimumWindowsVersion + "' is invalid. Did you mean '" + WindowsUtils.canonicalizeVersion(minimumWindowsVersion) + "'?"); } validator.validate(); if (minimumWindowsVersion && !WindowsUtils.isValidWindowsVersion(minimumWindowsVersion)) { console.warn("Unknown Windows version '" + minimumWindowsVersion + "'; expected one of: " + WindowsUtils.knownWindowsVersions().map(function (a) { return '"' + a + '"'; }).join(", ") + ". See https://docs.microsoft.com/en-us/windows/desktop/SysInfo/operating-system-version"); } } setupRunEnvironment: { SetupRunEnv.setupRunEnvironment(product, config); } Parameter { property bool link } Parameter { property bool linkWholeArchive } Parameter { property string symbolLinkMode } } qbs-src-1.13.1/share/qbs/modules/cpp/DarwinGCC.qbs000066400000000000000000000252371347155106100215540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.DarwinTools import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.PathTools import qbs.Probes import qbs.PropertyList import qbs.TextFile import qbs.Utilities import "darwin.js" as Darwin import "gcc.js" as Gcc UnixGCC { condition: false Depends { name: "xcode"; required: qbs.toolchain && qbs.toolchain.contains("xcode") } Probes.BinaryProbe { id: lipoProbe condition: !_skipAllChecks names: [lipoName] platformSearchPaths: { var paths = (xcode.present && xcode.devicePlatformPath) ? [xcode.devicePlatformPath + "/Developer/usr/bin"] : []; return paths.concat([toolchainInstallPath, "/usr/bin"]); } } property string lipoPathPrefix: Gcc.pathPrefix(lipoProbe.found ? lipoProbe.path : toolchainInstallPath, toolchainPrefix) lipoName: "lipo" lipoPath: lipoPathPrefix + lipoName property bool enableAggregationRules: product.aggregate && !product.multiplexConfigurationId targetVendor: "apple" targetSystem: "darwin" targetAbi: "macho" imageFormat: "macho" cxxStandardLibrary: libcxxAvailable ? "libc++" : base loadableModulePrefix: "" loadableModuleSuffix: ".bundle" dynamicLibrarySuffix: ".dylib" Properties { condition: product.multiplexByQbsProperties.contains("buildVariants") && qbs.buildVariants && qbs.buildVariants.length > 1 && (!product.aggregate || !!product.multiplexConfigurationId) && qbs.buildVariant !== "release" variantSuffix: "_" + qbs.buildVariant } separateDebugInformation: true debugInfoBundleSuffix: ".dSYM" debugInfoSuffix: ".dwarf" rpathOrigin: "@loader_path" useRPathLink: !minimumDarwinVersion || Utilities.versionCompare(minimumDarwinVersion, "10.5") < 0 rpathLinkFlag: "-L" toolchainInstallPath: xcode.present ? FileInfo.joinPaths(xcode.toolchainPath, "usr", "bin") : base sysroot: xcode.present ? xcode.sdkPath : base sysrootFlags: sysroot ? ["-isysroot", sysroot] : [] setupBuildEnvironment: { for (var key in product.cpp.buildEnv) { v = new ModUtils.EnvironmentVariable(key); v.value = product.cpp.buildEnv[key]; v.set(); } } property var defaultInfoPlist: { var dict = {}; if (qbs.targetOS.contains("macos")) { dict["NSPrincipalClass"] = "NSApplication"; // needed for Retina display support if (minimumMacosVersion) dict["LSMinimumSystemVersion"] = minimumMacosVersion; } if (qbs.targetOS.containsAny(["ios", "tvos"])) { dict["LSRequiresIPhoneOS"] = true; if (xcode.platformType === "device") { if (qbs.targetOS.contains("ios")) { if (qbs.architecture === "arm64") dict["UIRequiredDeviceCapabilities"] = ["arm64"]; else dict["UIRequiredDeviceCapabilities"] = ["armv7"]; } if (qbs.targetOS.contains("tvos")) dict["UIRequiredDeviceCapabilities"] = ["arm64"]; } } if (xcode.present) { var targetDevices = DarwinTools.targetedDeviceFamily(xcode.targetDevices); if (qbs.targetOS.contains("ios")) dict["UIDeviceFamily"] = targetDevices; if (qbs.targetOS.containsAny(["ios", "watchos"])) { var orientations = [ "UIInterfaceOrientationPortrait", "UIInterfaceOrientationPortraitUpsideDown", "UIInterfaceOrientationLandscapeLeft", "UIInterfaceOrientationLandscapeRight" ]; if (targetDevices.contains("ipad")) dict["UISupportedInterfaceOrientations~ipad"] = orientations; if (targetDevices.contains("watch")) dict["UISupportedInterfaceOrientations"] = orientations.slice(0, 2); if (targetDevices.contains("iphone")) { orientations.splice(1, 1); dict["UISupportedInterfaceOrientations"] = orientations; } } } return dict; } targetLinkerFlags: darwinArchFlags.concat(minimumDarwinVersionLinkerFlags) targetAssemblerFlags: !assemblerHasTargetOption ? darwinArchFlags : base; targetDriverFlags: !compilerHasTargetOption ? legacyTargetDriverFlags : base property stringList legacyTargetDriverFlags: base.concat(darwinArchFlags).concat(minimumDarwinVersionCompilerFlags) // private properties readonly property stringList darwinArchFlags: targetArch ? ["-arch", targetArch] : [] readonly property stringList minimumDarwinVersionCompilerFlags: (minimumDarwinVersionCompilerFlag && minimumDarwinVersion) ? [minimumDarwinVersionCompilerFlag + "=" + minimumDarwinVersion] : [] readonly property stringList minimumDarwinVersionLinkerFlags: (minimumDarwinVersionLinkerFlag && minimumDarwinVersion) ? [minimumDarwinVersionLinkerFlag, minimumDarwinVersion] : [] readonly property var buildEnv: { var env = { "ARCHS_STANDARD": xcode.standardArchitectures, "EXECUTABLE_NAME": product.targetName, "LANG": "en_US.US-ASCII", "PRODUCT_NAME": product.name } // Set the corresponding environment variable even if the minimum OS version is undefined, // because this indicates the default deployment target for that OS if (qbs.targetOS.contains("ios") && minimumIosVersion) env["IPHONEOS_DEPLOYMENT_TARGET"] = minimumIosVersion; if (qbs.targetOS.contains("macos") && minimumMacosVersion) env["MACOSX_DEPLOYMENT_TARGET"] = minimumMacosVersion; if (qbs.targetOS.contains("watchos") && minimumWatchosVersion) env["WATCHOS_DEPLOYMENT_TARGET"] = minimumWatchosVersion; if (qbs.targetOS.contains("tvos") && minimumTvosVersion) env["TVOS_DEPLOYMENT_TARGET"] = minimumTvosVersion; if (xcode.present) env["TARGETED_DEVICE_FAMILY"] = DarwinTools.targetedDeviceFamily(xcode.targetDevices).join(","); return env; } property string minimumDarwinVersion property string minimumDarwinVersionCompilerFlag property string minimumDarwinVersionLinkerFlag property bool libcxxAvailable: qbs.toolchain.contains("clang") && cxxLanguageVersion !== "c++98" Rule { condition: enableAggregationRules inputsFromDependencies: ["application"] multiplex: true outputFileTags: ["bundle.input", "application", "primary", "debuginfo_app", "debuginfo_bundle", "bundle.variant_symlink", "debuginfo_plist"] outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "application", "app") prepare: Darwin.prepareLipo.apply(Darwin, arguments) } Rule { condition: enableAggregationRules inputsFromDependencies: ["loadablemodule"] multiplex: true outputFileTags: ["bundle.input", "loadablemodule", "primary", "debuginfo_loadablemodule"] outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "loadablemodule", "loadablemodule") prepare: Darwin.prepareLipo.apply(Darwin, arguments) } Rule { condition: enableAggregationRules inputsFromDependencies: ["dynamiclibrary"] multiplex: true outputFileTags: ["bundle.input", "dynamiclibrary", "dynamiclibrary_symbols", "primary", "debuginfo_dll","debuginfo_bundle","bundle.variant_symlink", "debuginfo_plist"] outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "dynamiclibrary", "dll") prepare: Darwin.prepareLipo.apply(Darwin, arguments) } Rule { condition: enableAggregationRules inputsFromDependencies: ["staticlibrary"] multiplex: true outputFileTags: ["bundle.input", "staticlibrary", "primary"] outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "staticlibrary") prepare: Darwin.prepareLipo.apply(Darwin, arguments) } Rule { condition: qbs.targetOS.contains("darwin") multiplex: true Artifact { filePath: product.name + "-cpp-Info.plist" fileTags: ["partial_infoplist"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.inputData = product.cpp.defaultInfoPlist; cmd.outputFilePath = output.filePath; cmd.sourceCode = function() { var plist = new PropertyList(); try { plist.readFromObject(inputData); plist.writeToFile(outputFilePath, "xml1"); } finally { plist.clear(); } }; return [cmd]; } } } qbs-src-1.13.1/share/qbs/modules/cpp/GenericGCC.qbs000066400000000000000000000747411347155106100217100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.PathTools import qbs.Probes import qbs.Process import qbs.TextFile import qbs.Utilities import qbs.UnixUtils import qbs.WindowsUtils import 'gcc.js' as Gcc CppModule { condition: qbs.toolchain && qbs.toolchain.contains("gcc") priority: -100 Probes.GccBinaryProbe { id: compilerPathProbe condition: !toolchainInstallPath && !_skipAllChecks _compilerName: compilerName _toolchainPrefix: toolchainPrefix } // Find the version as early as possible in case other things depend on it, // for example the question of whether certain flags are supported and which need to be used // in the GccProbe itself. Probes.GccVersionProbe { id: gccVersionProbe compilerFilePath: compilerPath environment: probeEnv } Probes.GccProbe { id: gccProbe condition: !_skipAllChecks compilerFilePathByLanguage: compilerPathByLanguage enableDefinesByLanguage: enableCompilerDefinesByLanguage environment: probeEnv flags: targetDriverFlags.concat(sysrootFlags) _sysroot: sysroot } property var probeEnv Probes.BinaryProbe { id: binutilsProbe condition: !File.exists(archiverPath) && !_skipAllChecks names: Gcc.toolNames([archiverName, assemblerName, linkerName, nmName, objcopyName, stripName], toolchainPrefix) } targetLinkerFlags: Gcc.targetFlags("linker", false, target, targetArch, machineType, qbs.targetOS) targetAssemblerFlags: Gcc.targetFlags("assembler", assemblerHasTargetOption, target, targetArch, machineType, qbs.targetOS) targetDriverFlags: Gcc.targetFlags("compiler", compilerHasTargetOption, target, targetArch, machineType, qbs.targetOS) Probe { id: nmProbe condition: !_skipAllChecks property string theNmPath: nmPath property bool hasDynamicOption configure: { var proc = new Process(); try { hasDynamicOption = proc.exec(theNmPath, ["-D", theNmPath], false) == 0; console.debug("nm has -D: " + hasDynamicOption); } finally { proc.close(); } } } qbs.architecture: gccProbe.found ? gccProbe.architecture : original endianness: gccProbe.endianness compilerDefinesByLanguage: gccProbe.compilerDefinesByLanguage compilerVersionMajor: gccVersionProbe.versionMajor compilerVersionMinor: gccVersionProbe.versionMinor compilerVersionPatch: gccVersionProbe.versionPatch compilerIncludePaths: gccProbe.includePaths compilerFrameworkPaths: gccProbe.frameworkPaths compilerLibraryPaths: gccProbe.libraryPaths property bool compilerHasTargetOption: qbs.toolchain.contains("clang") && Utilities.versionCompare(compilerVersion, "3.1") >= 0 property bool assemblerHasTargetOption: qbs.toolchain.contains("xcode") && Utilities.versionCompare(compilerVersion, "7") >= 0 property string target: targetArch ? [targetArch, targetVendor, targetSystem, targetAbi].join("-") : undefined property string targetArch: Utilities.canonicalTargetArchitecture( qbs.architecture, endianness, targetVendor, targetSystem, targetAbi) property string targetVendor: "unknown" property string targetSystem: "unknown" property string targetAbi: "unknown" property string toolchainPrefix: compilerPathProbe.found ? compilerPathProbe.tcPrefix : undefined property string toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined property string binutilsPath: binutilsProbe.found ? binutilsProbe.path : toolchainInstallPath assemblerName: 'as' compilerName: cxxCompilerName linkerName: 'ld' property string archiverName: 'ar' property string nmName: 'nm' property string objcopyName: "objcopy" property string stripName: "strip" property string dsymutilName: "dsymutil" property string lipoName property string sysroot: qbs.sysroot property string syslibroot: sysroot property stringList sysrootFlags: sysroot ? ["--sysroot=" + sysroot] : [] property string linkerMode: "automatic" PropertyOptions { name: "linkerMode" allowedValues: ["automatic", "manual"] description: "Controls whether to automatically use an appropriate compiler frontend " + "in place of the system linker when linking binaries. The default is \"automatic\", " + "which chooses either the C++ compiler, C compiler, or system linker specified by " + "the linkerName/linkerPath properties, depending on the type of object files " + "present on the linker command line. \"manual\" allows you to explicitly specify " + "the linker using the linkerName/linkerPath properties, and allows linker flags " + "passed to the linkerFlags and platformLinkerFlags properties to be escaped " + "manually (using -Wl or -Xlinker) instead of automatically based on the selected " + "linker." } property string exportedSymbolsCheckMode: "ignore-undefined" PropertyOptions { name: "exportedSymbolsCheckMode" allowedValues: ["strict", "ignore-undefined"] description: "Controls when we consider an updated dynamic library as changed with " + "regards to other binaries depending on it. The default is \"ignore-undefined\", " + "which means we do not care about undefined symbols being added or removed. " + "If you do care about that, e.g. because you link dependent products with an option " + "such as \"--no-undefined\", then you should set this property to \"strict\"." } property string linkerVariant PropertyOptions { name: "linkerVariant" allowedValues: ["bfd", "gold", "lld"] description: "Allows to specify the linker variant. Maps to gcc's and clang's -fuse-ld " + "option." } Properties { condition: linkerVariant driverLinkerFlags: "-fuse-ld=" + linkerVariant } property string toolchainPathPrefix: Gcc.pathPrefix(toolchainInstallPath, toolchainPrefix) property string binutilsPathPrefix: Gcc.pathPrefix(binutilsPath, toolchainPrefix) property string compilerExtension: qbs.hostOS.contains("windows") ? ".exe" : "" property string cCompilerName: (qbs.toolchain.contains("clang") ? "clang" : "gcc") + compilerExtension property string cxxCompilerName: (qbs.toolchain.contains("clang") ? "clang++" : "g++") + compilerExtension compilerPathByLanguage: ({ "c": toolchainPathPrefix + cCompilerName, "cpp": toolchainPathPrefix + cxxCompilerName, "objc": toolchainPathPrefix + cCompilerName, "objcpp": toolchainPathPrefix + cxxCompilerName, "asm_cpp": toolchainPathPrefix + cCompilerName }) assemblerPath: binutilsPathPrefix + assemblerName compilerPath: toolchainPathPrefix + compilerName linkerPath: binutilsPathPrefix + linkerName property string archiverPath: binutilsPathPrefix + archiverName property string nmPath: binutilsPathPrefix + nmName property bool _nmHasDynamicOption: nmProbe.hasDynamicOption property string objcopyPath: binutilsPathPrefix + objcopyName property string stripPath: binutilsPathPrefix + stripName property string dsymutilPath: toolchainPathPrefix + dsymutilName property string lipoPath property stringList dsymutilFlags property bool alwaysUseLipo: false property string includeFlag: "-I" property string systemIncludeFlag: "-isystem" readonly property bool shouldCreateSymlinks: { return createSymlinks && internalVersion && ["macho", "elf"].contains(cpp.imageFormat); } property string internalVersion: { if (product.version === undefined) return undefined; if (!Gcc.isNumericProductVersion(product.version)) { // Dynamic library version numbers like "A" or "B" are common on Apple platforms, so // don't restrict the product version to a componentized version number here. if (cpp.imageFormat === "macho") return product.version; throw("product.version must be a string in the format x[.y[.z[.w]] " + "where each component is an integer"); } var maxVersionParts = 3; var versionParts = product.version.split('.').slice(0, maxVersionParts); // pad if necessary for (var i = versionParts.length; i < maxVersionParts; ++i) versionParts.push("0"); return versionParts.join('.'); } property string soVersion: { var v = internalVersion; if (!Gcc.isNumericProductVersion(v)) return ""; return v.split('.')[0]; } property var buildEnv: { var env = {}; if (qbs.toolchain.contains("mingw")) env.PATH = [toolchainInstallPath]; // For libwinpthread etc return env; } exceptionHandlingModel: { if (qbs.toolchain.contains("mingw")) { // https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html claims // __USING_SJLJ_EXCEPTIONS__ is defined as 1 when using SJLJ exceptions, but there don't // seem to be defines for the other models, so use the presence of the DLLs for now. var prefix = toolchainInstallPath; if (!qbs.hostOS.contains("windows")) prefix = FileInfo.joinPaths(toolchainInstallPath, "..", "lib", "gcc", toolchainPrefix, [compilerVersionMajor, compilerVersionMinor].join(".")); var models = ["seh", "sjlj", "dw2"]; for (var i = 0; i < models.length; ++i) { if (File.exists(FileInfo.joinPaths(prefix, "libgcc_s_" + models[i] + "-1.dll"))) { return models[i]; } } } return base; } validate: { if (_skipAllChecks) return; if (!File.exists(compilerPath)) { var pathMessage = FileInfo.isAbsolutePath(compilerPath) ? "at '" + compilerPath + "'" : "'" + compilerPath + "' in PATH"; throw ModUtils.ModuleError("Could not find selected C++ compiler " + pathMessage + ". " + "Ensure that the compiler is properly " + "installed, or set cpp.toolchainInstallPath to a valid " + "toolchain path, or consider whether you meant to set " + "cpp.compilerName instead."); } var isWrongTriple = false; if (gccProbe.architecture) { if (Utilities.canonicalArchitecture(architecture) !== Utilities.canonicalArchitecture(gccProbe.architecture)) isWrongTriple = true; } else if (architecture) { // This is a warning and not an error on the rare chance some new architecture comes // about which qbs does not know about the macros of. But it *might* still work. console.warn("Unknown architecture '" + architecture + "' " + "may not be supported by this compiler."); } if (gccProbe.endianness) { if (endianness !== gccProbe.endianness) isWrongTriple = true; } else if (endianness) { console.warn("Could not detect endianness ('" + endianness + "' given)"); } if (gccProbe.targetPlatform) { // Can't differentiate Darwin OSes at the compiler level alone if (gccProbe.targetPlatform === "darwin" ? !qbs.targetOS.contains("darwin") : qbs.targetPlatform !== gccProbe.targetPlatform) isWrongTriple = true; } else if (qbs.targetPlatform) { console.warn("Could not detect target platform ('" + qbs.targetPlatform + "' given)"); } if (isWrongTriple) { var realTriple = [ Utilities.canonicalArchitecture(gccProbe.architecture), gccProbe.targetPlatform, gccProbe.endianness ? gccProbe.endianness + "-endian" : undefined ].join("-"); var givenTriple = [ Utilities.canonicalArchitecture(architecture), qbs.targetPlatform, endianness ? endianness + "-endian" : undefined ].join("-"); var msg = "The selected compiler '" + compilerPath + "' produces code for '" + realTriple + "', but '" + givenTriple + "' was given, which is incompatible."; if (validateTargetTriple) { msg += " If you are absolutely certain that your configuration is correct " + "(check the values of the qbs.architecture, qbs.targetPlatform, " + "and qbs.endianness properties) and that this message has been " + "emitted in error, set the cpp.validateTargetTriple property to " + "false. However, you should consider submitting a bug report in any " + "case."; throw ModUtils.ModuleError(msg); } else { console.warn(msg); } } var validateFlagsFunction = function (value) { if (value) { for (var i = 0; i < value.length; ++i) { if (["-target", "-triple", "-arch"].contains(value[i])) return false; } } return true; } var validator = new ModUtils.PropertyValidator("cpp"); var msg = "'-target', '-triple' and '-arch' cannot appear in flags; set qbs.architecture instead"; validator.addCustomValidator("assemblerFlags", assemblerFlags, validateFlagsFunction, msg); validator.addCustomValidator("cppFlags", cppFlags, validateFlagsFunction, msg); validator.addCustomValidator("cFlags", cFlags, validateFlagsFunction, msg); validator.addCustomValidator("cxxFlags", cxxFlags, validateFlagsFunction, msg); validator.addCustomValidator("objcFlags", objcFlags, validateFlagsFunction, msg); validator.addCustomValidator("objcxxFlags", objcxxFlags, validateFlagsFunction, msg); validator.addCustomValidator("commonCompilerFlags", commonCompilerFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformAssemblerFlags", platformAssemblerFlags, validateFlagsFunction, msg); //validator.addCustomValidator("platformCppFlags", platformCppFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformCFlags", platformCFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformCxxFlags", platformCxxFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformObjcFlags", platformObjcFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformObjcxxFlags", platformObjcxxFlags, validateFlagsFunction, msg); validator.addCustomValidator("platformCommonCompilerFlags", platformCommonCompilerFlags, validateFlagsFunction, msg); validator.setRequiredProperty("compilerVersion", compilerVersion); validator.setRequiredProperty("compilerVersionMajor", compilerVersionMajor); validator.setRequiredProperty("compilerVersionMinor", compilerVersionMinor); validator.setRequiredProperty("compilerVersionPatch", compilerVersionPatch); validator.addVersionValidator("compilerVersion", compilerVersion, 3, 3); validator.addRangeValidator("compilerVersionMajor", compilerVersionMajor, 1); validator.addRangeValidator("compilerVersionMinor", compilerVersionMinor, 0); validator.addRangeValidator("compilerVersionPatch", compilerVersionPatch, 0); validator.setRequiredProperty("compilerIncludePaths", compilerIncludePaths); validator.setRequiredProperty("compilerFrameworkPaths", compilerFrameworkPaths); validator.setRequiredProperty("compilerLibraryPaths", compilerLibraryPaths); validator.validate(); } // Product should be linked if it's not multiplexed or aggregated at all, // or if it is multiplexed, if it's not the aggregate product readonly property bool shouldLink: !(product.multiplexed || product.aggregate) || product.multiplexConfigurationId Rule { name: "dynamicLibraryLinker" condition: product.cpp.shouldLink multiplex: true inputs: { var tags = ["obj", "linkerscript", "versionscript"]; if (product.bundle && product.bundle.embedInfoPlist && product.qbs.targetOS.contains("darwin")) { tags.push("aggregate_infoplist"); } return tags; } inputsFromDependencies: ["dynamiclibrary_symbols", "staticlibrary", "dynamiclibrary_import"] outputFileTags: [ "bundle.input", "dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_symbols", "debuginfo_dll", "debuginfo_bundle","dynamiclibrary_import", "debuginfo_plist", ] outputArtifacts: { var artifacts = [{ filePath: product.destinationDirectory + "/" + PathTools.dynamicLibraryFilePath(product), fileTags: ["bundle.input", "dynamiclibrary"], bundle: { _bundleFilePath: product.destinationDirectory + "/" + PathTools.bundleExecutableFilePath(product) } }]; if (product.qbs.toolchain.contains("mingw")) { artifacts.push({ fileTags: ["dynamiclibrary_import"], filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.importLibraryFilePath(product)), alwaysUpdated: false }); } else { // List of libfoo's public symbols for smart re-linking. artifacts.push({ filePath: product.destinationDirectory + "/.sosymbols/" + PathTools.dynamicLibraryFilePath(product), fileTags: ["dynamiclibrary_symbols"], alwaysUpdated: false, }); } if (product.cpp.shouldCreateSymlinks && (!product.bundle || !product.bundle.isBundle)) { var maxVersionParts = Gcc.isNumericProductVersion(product.version) ? 3 : 1; for (var i = 0; i < maxVersionParts; ++i) { var symlink = { filePath: product.destinationDirectory + "/" + PathTools.dynamicLibraryFilePath(product, undefined, undefined, i), fileTags: ["dynamiclibrary_symlink"] }; if (i > 0 && artifacts[i-1].filePath == symlink.filePath) break; // Version number has less than three components. artifacts.push(symlink); } } if (!product.aggregate) artifacts = artifacts.concat(Gcc.debugInfoArtifacts(product, undefined, "dll")); return artifacts; } prepare: { return Gcc.prepareLinker.apply(Gcc, arguments); } } Rule { name: "staticLibraryLinker" condition: product.cpp.shouldLink multiplex: true inputs: ["obj", "linkerscript"] inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary"] outputFileTags: ["bundle.input", "staticlibrary", "c_staticlibrary", "cpp_staticlibrary"] outputArtifacts: { var tags = ["bundle.input", "staticlibrary"]; var objs = inputs["obj"]; var objCount = objs ? objs.length : 0; for (var i = 0; i < objCount; ++i) { var ft = objs[i].fileTags; if (ft.contains("c_obj")) tags.push("c_staticlibrary"); if (ft.contains("cpp_obj")) tags.push("cpp_staticlibrary"); } return [{ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.staticLibraryFilePath(product)), fileTags: tags, bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.bundleExecutableFilePath(product)) } }]; } prepare: { var args = ['rcs', output.filePath]; for (var i in inputs.obj) args.push(inputs.obj[i].filePath); var cmd = new Command(product.cpp.archiverPath, args); cmd.description = 'creating ' + output.fileName; cmd.highlight = 'linker' cmd.jobPool = "linker"; cmd.responseFileUsagePrefix = '@'; return cmd; } } Rule { name: "loadableModuleLinker" condition: product.cpp.shouldLink multiplex: true inputs: { var tags = ["obj", "linkerscript"]; if (product.bundle && product.bundle.embedInfoPlist && product.qbs.targetOS.contains("darwin")) { tags.push("aggregate_infoplist"); } return tags; } inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary"] outputFileTags: ["bundle.input", "loadablemodule", "debuginfo_loadablemodule", "debuginfo_bundle","debuginfo_plist"] outputArtifacts: { var app = { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.loadableModuleFilePath(product)), fileTags: ["bundle.input", "loadablemodule"], bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.bundleExecutableFilePath(product)) } } var artifacts = [app]; if (!product.aggregate) artifacts = artifacts.concat(Gcc.debugInfoArtifacts(product, undefined, "loadablemodule")); return artifacts; } prepare: { return Gcc.prepareLinker.apply(Gcc, arguments); } } Rule { name: "applicationLinker" condition: product.cpp.shouldLink multiplex: true inputs: { var tags = ["obj", "linkerscript"]; if (product.bundle && product.bundle.embedInfoPlist && product.qbs.targetOS.contains("darwin")) { tags.push("aggregate_infoplist"); } return tags; } inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary"] outputFileTags: ["bundle.input", "application", "debuginfo_app","debuginfo_bundle", "debuginfo_plist"] outputArtifacts: { var app = { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.applicationFilePath(product)), fileTags: ["bundle.input", "application"], bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.bundleExecutableFilePath(product)) } } var artifacts = [app]; if (!product.aggregate) artifacts = artifacts.concat(Gcc.debugInfoArtifacts(product, undefined, "app")); return artifacts; } prepare: { return Gcc.prepareLinker.apply(Gcc, arguments); } } Rule { name: "compiler" inputs: ["cpp", "c", "objcpp", "objc", "asm_cpp"] auxiliaryInputs: ["hpp"] explicitlyDependsOn: ["c_pch", "cpp_pch", "objc_pch", "objcpp_pch"] outputFileTags: ["obj", "c_obj", "cpp_obj", "intermediate_obj"] outputArtifacts: { var tags; if (input.fileTags.contains("cpp_intermediate_object")) tags = ["intermediate_obj"]; else tags = ["obj"]; if (inputs.c || inputs.objc) tags.push("c_obj"); if (inputs.cpp || inputs.objcpp) tags.push("cpp_obj"); return [{ fileTags: tags, filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), input.fileName + ".o") }]; } prepare: { return Gcc.prepareCompiler.apply(Gcc, arguments); } } Rule { name: "assembler" inputs: ["asm"] Artifact { fileTags: ["obj"] filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), input.fileName + ".o") } prepare: { return Gcc.prepareAssembler.apply(Gcc, arguments); } } Rule { condition: useCPrecompiledHeader inputs: ["c_pch_src"] auxiliaryInputs: ["hpp"] Artifact { filePath: product.name + "_c.gch" fileTags: ["c_pch"] } prepare: { return Gcc.prepareCompiler.apply(Gcc, arguments); } } Rule { condition: useCxxPrecompiledHeader inputs: ["cpp_pch_src"] auxiliaryInputs: ["hpp"] Artifact { filePath: product.name + "_cpp.gch" fileTags: ["cpp_pch"] } prepare: { return Gcc.prepareCompiler.apply(Gcc, arguments); } } Rule { condition: useObjcPrecompiledHeader inputs: ["objc_pch_src"] auxiliaryInputs: ["hpp"] Artifact { filePath: product.name + "_objc.gch" fileTags: ["objc_pch"] } prepare: { return Gcc.prepareCompiler.apply(Gcc, arguments); } } Rule { condition: useObjcxxPrecompiledHeader inputs: ["objcpp_pch_src"] auxiliaryInputs: ["hpp"] Artifact { filePath: product.name + "_objcpp.gch" fileTags: ["objcpp_pch"] } prepare: { return Gcc.prepareCompiler.apply(Gcc, arguments); } } FileTagger { patterns: "*.s" fileTags: ["asm"] } FileTagger { patterns: "*.S" fileTags: ["asm_cpp"] } FileTagger { patterns: "*.sx" fileTags: ["asm_cpp"] } Scanner { inputs: ["linkerscript"] recursive: true scan: { console.debug("scanning linkerscript " + filePath + " for dependencies"); var retval = []; var linkerScript = new TextFile(filePath, TextFile.ReadOnly); var regexp = /[\s]*INCLUDE[\s]+(\S+).*/ // "INCLUDE filename" var match; while (!linkerScript.atEof()) { match = regexp.exec(linkerScript.readLine()); if (match) { var dependencyFileName = match[1]; retval.push(dependencyFileName); console.debug("linkerscript " + filePath + " depends on " + dependencyFileName); } } linkerScript.close(); return retval; } searchPaths: { var retval = []; for (var i = 0; i < (product.cpp.libraryPaths || []).length; i++) retval.push(product.cpp.libraryPaths[i]); var regexp = /[\s]*SEARCH_DIR\((\S+)\).*/ // "SEARCH_DIR(path)" var match; var linkerScript = new TextFile(input.filePath, TextFile.ReadOnly); while (!linkerScript.atEof()) { match = regexp.exec(linkerScript.readLine()); if(match) { var additionalPath = match[1]; retval.push(additionalPath); } } linkerScript.close(); return retval; } } } qbs-src-1.13.1/share/qbs/modules/cpp/LinuxGCC.qbs000066400000000000000000000053661347155106100214300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Process UnixGCC { condition: qbs.targetOS.contains('linux') && qbs.toolchain && qbs.toolchain.contains('gcc') priority: 1 targetVendor: "pc" targetSystem: "linux" targetAbi: "gnu" Probe { id: runPathsProbe condition: !_skipAllChecks && qbs.targetPlatform === qbs.hostPlatform property stringList systemRunPaths: [] configure: { var paths = []; var ldconfig = new Process(); try { var success = ldconfig.exec("ldconfig", ["-vNX"]); if (success === -1) return; var line; do { line = ldconfig.readLine(); if (line.charAt(0) === '/') { var colonIndex = line.indexOf(':'); if (colonIndex == -1) continue; paths.push(line.slice(0, colonIndex)); } } while (line && line.length > 0) found = true; systemRunPaths = paths; } finally { ldconfig.close(); } } } systemRunPaths: runPathsProbe.found ? runPathsProbe.systemRunPaths : base } qbs-src-1.13.1/share/qbs/modules/cpp/UnixGCC.qbs000066400000000000000000000040271347155106100212450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File GenericGCC { condition: qbs.toolchain && qbs.toolchain.contains("gcc") && qbs.targetOS && qbs.targetOS.contains("unix") priority: -50 staticLibraryPrefix: "lib" dynamicLibraryPrefix: "lib" loadableModulePrefix: "lib" staticLibrarySuffix: ".a" dynamicLibrarySuffix: ".so" debugInfoSuffix: ".debug" imageFormat: "elf" systemRunPaths: ["/lib", "/usr/lib"].filter(function(p) { return File.exists(p); }) rpathOrigin: "$ORIGIN" useRPathLink: true rpathLinkFlag: "-rpath-link=" } qbs-src-1.13.1/share/qbs/modules/cpp/android-gcc.qbs000066400000000000000000000255321347155106100221630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.TextFile import qbs.Utilities import "../../modules/Android/ndk/utils.js" as NdkUtils import 'gcc.js' as Gcc LinuxGCC { Depends { name: "Android.ndk" } condition: qbs.targetOS.contains("android") && qbs.toolchain && qbs.toolchain.contains("gcc") priority: 2 rpaths: [rpathOrigin] property string toolchainDir: { if (qbs.toolchain && qbs.toolchain.contains("clang")) { return Utilities.versionCompare(Android.ndk.version, "10") <= 0 ? "llvm-" + Android.ndk.toolchainVersionNumber : "llvm"; } return NdkUtils.getBinutilsPath(Android.ndk, toolchainTriple + "-") } property string cxxStlBaseDir: FileInfo.joinPaths(Android.ndk.ndkDir, "sources", "cxx-stl") property string gabiBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "gabi++") property string stlPortBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "stlport") property string gnuStlBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "gnu-libstdc++", Android.ndk.toolchainVersionNumber) property string llvmStlBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "llvm-libc++") property string stlBaseDir: { if (Android.ndk.appStl.startsWith("gabi++_")) return gabiBaseDir; else if (Android.ndk.appStl.startsWith("stlport_")) return stlPortBaseDir; else if (Android.ndk.appStl.startsWith("gnustl_")) return gnuStlBaseDir; else if (Android.ndk.appStl.startsWith("c++_")) return llvmStlBaseDir; return undefined; } property string stlLibsDir: { if (stlBaseDir) { var infix = Android.ndk.abi; if (Android.ndk.armMode === "thumb" && !Android.ndk.haveUnifiedStl) infix = FileInfo.joinPaths(infix, "thumb"); return FileInfo.joinPaths(stlBaseDir, "libs", infix); } return undefined; } property string sharedStlFilePath: (stlLibsDir && Android.ndk.appStl.endsWith("_shared")) ? FileInfo.joinPaths(stlLibsDir, dynamicLibraryPrefix + Android.ndk.appStl + dynamicLibrarySuffix) : undefined property string staticStlFilePath: (stlLibsDir && Android.ndk.appStl.endsWith("_static")) ? FileInfo.joinPaths(stlLibsDir, staticLibraryPrefix + Android.ndk.appStl + staticLibrarySuffix) : undefined Group { name: "Android STL" condition: product.cpp.sharedStlFilePath && product.cpp.shouldLink files: product.cpp.sharedStlFilePath ? [product.cpp.sharedStlFilePath] : [] fileTags: "android.stl" } Group { name: "gdbserver" condition: qbs.buildVariant !== "release" && product.cpp.shouldLink files: FileInfo.joinPaths(Android.ndk.ndkDir, "prebuilt", "android-" + NdkUtils.abiNameToDirName(Android.ndk.abi), "gdbserver", "gdbserver") fileTags: "android.gdbserver" } toolchainInstallPath: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains", toolchainDir, "prebuilt", Android.ndk.hostArch, "bin") property string toolchainTriple: [targetAbi === "androideabi" ? "arm" : targetArch, targetSystem, targetAbi].join("-") toolchainPrefix: { if (qbs.toolchain && qbs.toolchain.contains("clang")) return undefined; return toolchainTriple + "-"; } machineType: { if (Android.ndk.abi === "armeabi") return "armv5te"; if (Android.ndk.abi === "armeabi-v7a") return "armv7-a"; } qbs.optimization: targetAbi === "androideabi" ? "small" : base enableExceptions: Android.ndk.appStl !== "system" enableRtti: Android.ndk.appStl !== "system" commonCompilerFlags: NdkUtils.commonCompilerFlags(qbs.toolchain, qbs.buildVariant, Android.ndk.abi, Android.ndk.armMode) linkerFlags: NdkUtils.commonLinkerFlags(Android.ndk.abi) platformDriverFlags: ["-no-canonical-prefixes"] libraryPaths: { var prefix = FileInfo.joinPaths(sysroot, "usr"); var paths = []; if (Android.ndk.abi === "mips64" || Android.ndk.abi === "x86_64") // no lib64 for arm64-v8a paths.push(FileInfo.joinPaths(prefix, "lib64")); paths.push(FileInfo.joinPaths(prefix, "lib")); return paths; } dynamicLibraries: { var libs = ["c", "m"]; if (sharedStlFilePath) libs.push(sharedStlFilePath); return libs; } staticLibraries: { var libs = ["gcc"]; if (staticStlFilePath) { libs.push(staticStlFilePath); if (Android.ndk.appStl === "c++_static") { var libAbi = FileInfo.joinPaths(stlLibsDir, "libc++abi.a"); if (File.exists(libAbi)) libs.push(libAbi); } } return libs; } systemIncludePaths: { var includes = []; if (Android.ndk.useUnifiedHeaders) { // Might not be needed with Clang in a future NDK release includes.push(FileInfo.joinPaths(sysroot, "usr", "include", toolchainTriple)); } if (Android.ndk.appStl === "system") { includes.push(FileInfo.joinPaths(cxxStlBaseDir, "system", "include")); } else if (Android.ndk.appStl.startsWith("gabi++")) { includes.push(FileInfo.joinPaths(gabiBaseDir, "include")); } else if (Android.ndk.appStl.startsWith("stlport")) { includes.push(FileInfo.joinPaths(stlPortBaseDir, "stlport")); } else if (Android.ndk.appStl.startsWith("gnustl")) { includes.push(FileInfo.joinPaths(gnuStlBaseDir, "include")); includes.push(FileInfo.joinPaths(gnuStlBaseDir, "libs", Android.ndk.abi, "include")); includes.push(FileInfo.joinPaths(gnuStlBaseDir, "include", "backward")); } else if (Android.ndk.appStl.startsWith("c++_")) { if (Utilities.versionCompare(Android.ndk.version, "13") >= 0) { includes.push(FileInfo.joinPaths(llvmStlBaseDir, "include")); includes.push(FileInfo.joinPaths(llvmStlBaseDir + "abi", "include")); } else { includes.push(FileInfo.joinPaths(llvmStlBaseDir, "libcxx", "include")); includes.push(FileInfo.joinPaths(llvmStlBaseDir + "abi", "libcxxabi", "include")); } } return includes; } defines: { var list = ["ANDROID"]; if (Android.ndk.useUnifiedHeaders) { // Might be superseded by an -mandroid-version or similar Clang compiler flag in future list.push("__ANDROID_API__=" + Android.ndk.platformVersion); } return list; } binutilsPath: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains", NdkUtils.getBinutilsPath(Android.ndk, toolchainTriple + "-"), "prebuilt", Android.ndk.hostArch, "bin"); binutilsPathPrefix: Gcc.pathPrefix(binutilsPath, toolchainTriple + "-") driverFlags: qbs.toolchain.contains("clang") ? ["-gcc-toolchain", FileInfo.path(binutilsPath)].concat(base || []) : base syslibroot: FileInfo.joinPaths(Android.ndk.ndkDir, "platforms", Android.ndk.platform, "arch-" + NdkUtils.abiNameToDirName(Android.ndk.abi)) sysroot: !Android.ndk.useUnifiedHeaders ? syslibroot : FileInfo.joinPaths(Android.ndk.ndkDir, "sysroot") targetArch: { switch (qbs.architecture) { case "arm64": return "aarch64"; case "armv5": case "armv5te": return "armv5te"; case "armv7a": case "x86_64": return qbs.architecture; case "x86": return "i686"; case "mips": case "mipsel": return "mipsel"; case "mips64": case "mips64el": return "mips64el"; } } targetVendor: "none" targetSystem: "linux" targetAbi: "android" + (["armeabi", "armeabi-v7a"].contains(Android.ndk.abi) ? "eabi" : "") endianness: "little" Rule { condition: shouldLink inputs: "dynamiclibrary" Artifact { filePath: FileInfo.joinPaths("stripped-libs", input.fileName) fileTags: "android.nativelibrary" } prepare: { var stripArgs = ["--strip-unneeded", "-o", output.filePath, input.filePath]; var stripCmd = new Command(product.cpp.stripPath, stripArgs); stripCmd.description = "Stripping unneeded symbols from " + input.fileName; return stripCmd; } } _skipAllChecks: !shouldLink validate: { if (_skipAllChecks) return; var baseValidator = new ModUtils.PropertyValidator("qbs"); baseValidator.addCustomValidator("architecture", targetArch, function (value) { return value !== undefined; }, "unknown Android architecture '" + qbs.architecture + "'."); var validator = new ModUtils.PropertyValidator("cpp"); validator.setRequiredProperty("targetArch", targetArch); return baseValidator.validate() && validator.validate(); } } qbs-src-1.13.1/share/qbs/modules/cpp/cpp.js000066400000000000000000000040601347155106100204130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ function languageVersion(versionArray, knownValues, lang) { if (!versionArray) return undefined; var versions = [].uniqueConcat(versionArray); if (versions.length === 1) return versions[0]; for (var i = 0; i < knownValues.length; ++i) { var candidate = knownValues[i]; if (versions.contains(candidate)) return candidate; } var version = versions[0]; console.debug("Randomly choosing '" + version + "' from list of unknown " + lang + " version strings (" + versions + ")"); return version; } qbs-src-1.13.1/share/qbs/modules/cpp/darwin.js000066400000000000000000000211571347155106100211230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Gcc = require("./gcc.js"); var ModUtils = require("qbs.ModUtils"); var PathTools = require("qbs.PathTools"); function lipoOutputArtifacts(product, inputs, fileTag, debugSuffix) { var buildVariants = []; for (var i = 0; i < inputs[fileTag].length; ++i) { var variant = inputs[fileTag][i].qbs.buildVariant; var suffix = inputs[fileTag][i].cpp.variantSuffix; if (!buildVariants.some(function (x) { return x.name === variant; })) buildVariants.push({ name: variant, suffix: suffix }); } var list = []; if (fileTag === "dynamiclibrary") { Array.prototype.push.apply(list, buildVariants.map(function (variant) { return { filePath: product.destinationDirectory + "/.sosymbols/" + PathTools.dynamicLibraryFilePath(product, variant.suffix), fileTags: ["dynamiclibrary_symbols"], qbs: { buildVariant: variant.name }, cpp: { variantSuffix: variant.suffix }, alwaysUpdated: false }; })); } // Bundles should have a "normal" variant. In the case of frameworks, they cannot normally be // linked to without a default variant unless a variant is specifically chosen at link time // by passing the full path to the shared library executable instead of the -framework switch. // Technically this doesn't affect qbs since qbs always uses full paths for internal // dependencies but the "normal" variant is always the one that is linked to, since the // alternative variants should only be chosen at runtime using the DYLD_IMAGE_SUFFIX variable. // So for frameworks we'll create a symlink to the "default" variant as chosen by the user // (we cannot do this automatically since the user must tell us which variant should be // preferred, if there are multiple alternative variants). Applications are fine without a // symlink but still need an explicitly chosen variant to set as the CFBundleExecutable so that // Finder/LaunchServices can launch it normally but for simplicity we'll just use the symlink // approach for all bundle types. var defaultVariant; if (!buildVariants.some(function (x) { return x.name === "release"; }) && product.multiplexByQbsProperties.contains("buildVariants") && product.qbs.buildVariants && product.qbs.buildVariants.length > 1) { var defaultBuildVariant = product.qbs.defaultBuildVariant; buildVariants.map(function (variant) { if (variant.name === defaultBuildVariant) defaultVariant = variant; }); if (!defaultVariant) { throw new Error("qbs.defaultBuildVariant is '" + defaultBuildVariant + "', but this " + "variant is not in the qbs.buildVariants list (" + product.qbs.buildVariants.join(", ") + ")"); } buildVariants.push({ name: "release", suffix: "", isSymLink: true }); } Array.prototype.push.apply(list, buildVariants.map(function (variant) { var tags = ["bundle.input"]; if (variant.isSymLink) tags.push("bundle.variant_symlink"); else tags.push(fileTag, "primary"); return { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.linkerOutputFilePath(fileTag, product, variant.suffix)), fileTags: tags, qbs: { buildVariant: variant.name, _buildVariantFileName: variant.isSymLink && defaultVariant ? FileInfo.fileName(PathTools.linkerOutputFilePath( fileTag, product, defaultVariant.suffix)) : undefined }, bundle: { _bundleFilePath: product.destinationDirectory + "/" + PathTools.bundleExecutableFilePath(product, variant.suffix) }, cpp: { variantSuffix: variant.suffix } }; })); if (debugSuffix) Array.prototype.push.apply(list, Gcc.debugInfoArtifacts(product, buildVariants, debugSuffix)); return list; } function prepareLipo(project, product, inputs, outputs, input, output) { var cmd; var commands = []; for (var p in inputs) inputs[p] = inputs[p].filter(function(inp) { return inp.product.name === product.name; }); var allInputs = [].concat.apply([], Object.keys(inputs).map(function (tag) { return ["application", "dynamiclibrary", "staticlibrary", "loadablemodule"].contains(tag) ? inputs[tag] : []; })); (outputs["bundle.variant_symlink"] || []).map(function (symlink) { cmd = new Command("ln", ["-sfn", symlink.qbs._buildVariantFileName, symlink.filePath]); cmd.silent = true; commands.push(cmd); }); for (var i = 0; i < outputs.primary.length; ++i) { var vInputs = allInputs.filter(function (f) { return f.qbs.buildVariant === outputs.primary[i].qbs.buildVariant }).map(function (f) { return f.filePath }); if (vInputs.length > 1 || product.cpp.alwaysUseLipo) { cmd = new Command(ModUtils.moduleProperty(product, "lipoPath"), ["-create", "-output", outputs.primary[i].filePath].concat(vInputs)); cmd.description = "lipo " + outputs.primary[i].fileName; cmd.highlight = "linker"; } else { cmd = new JavaScriptCommand(); cmd.src = vInputs[0]; cmd.dst = outputs.primary[i].filePath; cmd.sourceCode = function () { File.copy(src, dst); }; cmd.silent = true; } commands.push(cmd); } var debugInfo = outputs.debuginfo_app || outputs.debuginfo_dll || outputs.debuginfo_loadablemodule; if (debugInfo) { var dsymPath = debugInfo[0].filePath; if (outputs.debuginfo_bundle && outputs.debuginfo_bundle[0]) dsymPath = outputs.debuginfo_bundle[0].filePath; var flags = ModUtils.moduleProperty(product, "dsymutilFlags") || []; cmd = new Command(ModUtils.moduleProperty(product, "dsymutilPath"), flags.concat([ "-o", dsymPath ]).concat(outputs.primary.map(function (f) { return f.filePath; }))); cmd.description = "generating dSYM for " + product.name; commands.push(cmd); } cmd = new Command(ModUtils.moduleProperty(product, "stripPath"), ["-S", outputs.primary[0].filePath]); cmd.silent = true; commands.push(cmd); if (outputs.dynamiclibrary_symbols) Array.prototype.push.apply(commands, Gcc.createSymbolCheckingCommands(product, outputs)); return commands; } qbs-src-1.13.1/share/qbs/modules/cpp/freebsd-gcc.qbs000066400000000000000000000035561347155106100221570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import "freebsd.js" as FreeBSD UnixGCC { condition: qbs.targetOS && qbs.targetOS.contains("freebsd") && qbs.toolchain && qbs.toolchain.contains("gcc") priority: 1 targetSystem: "freebsd" + (qbs.hostOS.contains("freebsd") ? FreeBSD.hostKernelRelease() : "") distributionIncludePaths: ["/usr/local/include"] distributionLibraryPaths: ["/usr/local/lib"] } qbs-src-1.13.1/share/qbs/modules/cpp/freebsd.js000066400000000000000000000004071347155106100212440ustar00rootroot00000000000000var Utilities = require("qbs.Utilities"); function stripKernelReleaseSuffix(r) { var idx = r.indexOf("-RELEASE"); return idx >= 0 ? r.substr(0, idx) : r; } function hostKernelRelease() { return stripKernelReleaseSuffix(Utilities.kernelVersion()); } qbs-src-1.13.1/share/qbs/modules/cpp/gcc.js000066400000000000000000001675651347155106100204110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Cpp = require("cpp.js"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var DarwinTools = require("qbs.DarwinTools"); var ModUtils = require("qbs.ModUtils"); var PathTools = require("qbs.PathTools"); var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); var UnixUtils = require("qbs.UnixUtils"); var Utilities = require("qbs.Utilities"); var WindowsUtils = require("qbs.WindowsUtils"); function effectiveLinkerPath(product, inputs) { if (product.cpp.linkerMode === "automatic") { var compilers = product.cpp.compilerPathByLanguage; if (compilers) { if (inputs.cpp_obj || inputs.cpp_staticlibrary) { console.log("Found C++ or Objective-C++ objects, choosing C++ linker for " + product.name); return compilers["cpp"]; } if (inputs.c_obj || inputs.c_staticlibrary) { console.log("Found C or Objective-C objects, choosing C linker for " + product.name); return compilers["c"]; } } console.log("Found no C-language objects, choosing system linker for " + product.name); } return product.cpp.linkerPath; } function useCompilerDriverLinker(product, inputs) { var linker = effectiveLinkerPath(product, inputs); var compilers = product.cpp.compilerPathByLanguage; if (compilers) { return linker === compilers["cpp"] || linker === compilers["c"]; } return linker === product.cpp.compilerPath; } function collectLibraryDependencies(product, isDarwin) { var publicDeps = {}; var objects = []; var objectByFilePath = {}; var tagForLinkingAgainstSharedLib = product.qbs.toolchain.contains("mingw") ? "dynamiclibrary_import" : "dynamiclibrary"; function addObject(obj, addFunc) { addFunc.call(objects, obj); objectByFilePath[obj.filePath] = obj; } function addPublicFilePath(filePath, dep) { var existing = objectByFilePath[filePath]; var wholeArchive = dep.parameters.cpp && dep.parameters.cpp.linkWholeArchive; var symbolLinkMode = dep.parameters.cpp && dep.parameters.cpp.symbolLinkMode; if (existing) { existing.direct = true; existing.wholeArchive = wholeArchive; existing.symbolLinkMode = symbolLinkMode; } else { addObject({ direct: true, filePath: filePath, wholeArchive: wholeArchive, symbolLinkMode: symbolLinkMode }, Array.prototype.unshift); } } function addPrivateFilePath(filePath) { var existing = objectByFilePath[filePath]; if (!existing) addObject({ direct: false, filePath: filePath }, Array.prototype.unshift); } function addArtifactFilePaths(dep, tag, addFunction) { var artifacts = dep.artifacts[tag]; if (!artifacts) return; var artifactFilePaths = artifacts.map(function(a) { return a.filePath; }); for (var i = 0; i < artifactFilePaths.length; ++i) addFunction(artifactFilePaths[i], dep); } function addExternalLibs(obj) { if (!obj.cpp) return; function ensureArray(a) { return Array.isArray(a) ? a : []; } function sanitizedModuleListProperty(obj, moduleName, propertyName) { return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName)); } var externalLibs = [].concat( ensureArray(sanitizedModuleListProperty(obj, "cpp", "staticLibraries")), ensureArray(sanitizedModuleListProperty(obj, "cpp", "dynamicLibraries"))); for (var i = 0, len = externalLibs.length; i < len; ++i) addObject({ direct: true, filePath: externalLibs[i] }, Array.prototype.push); if (isDarwin) { externalLibs = [].concat( ensureArray(sanitizedModuleListProperty(obj, "cpp", "frameworks"))); for (var i = 0, len = externalLibs.length; i < len; ++i) addObject({ direct: true, filePath: externalLibs[i], framework: true }, Array.prototype.push); externalLibs = [].concat( ensureArray(sanitizedModuleListProperty(obj, "cpp", "weakFrameworks"))); for (var i = 0, len = externalLibs.length; i < len; ++i) addObject({ direct: true, filePath: externalLibs[i], framework: true, symbolLinkMode: "weak" }, Array.prototype.push); } } function traverse(dep, isBelowIndirectDynamicLib) { if (publicDeps[dep.name]) return; if (dep.parameters.cpp && dep.parameters.cpp.link === false) return; var isStaticLibrary = typeof dep.artifacts["staticlibrary"] !== "undefined"; var isDynamicLibrary = !isStaticLibrary && typeof dep.artifacts[tagForLinkingAgainstSharedLib] !== "undefined"; if (!isStaticLibrary && !isDynamicLibrary) return; var nextIsBelowIndirectDynamicLib = isBelowIndirectDynamicLib || isDynamicLibrary; dep.dependencies.forEach(function(depdep) { // If "dep" is an aggregate product, and "depdep" is one of the multiplexed variants // of the same product, we don't want to depend on the multiplexed variants, because // that could mean linking more than one time against the same library. Instead skip // the multiplexed dependency, and depend only on the aggregate one. if (depdep.name === dep.name) return; traverse(depdep, nextIsBelowIndirectDynamicLib); }); if (isStaticLibrary) { if (!isBelowIndirectDynamicLib) { addArtifactFilePaths(dep, "staticlibrary", addPublicFilePath); addExternalLibs(dep); publicDeps[dep.name] = true; } } else if (isDynamicLibrary) { if (!isBelowIndirectDynamicLib) { addArtifactFilePaths(dep, tagForLinkingAgainstSharedLib, addPublicFilePath); publicDeps[dep.name] = true; } else { addArtifactFilePaths(dep, tagForLinkingAgainstSharedLib, addPrivateFilePath); } } } function traverseDirectDependency(dep) { traverse(dep, false); } product.dependencies.forEach(traverseDirectDependency); addExternalLibs(product); var seenRPathLinkDirs = {}; var result = { libraries: [], rpath_link: [] }; objects.forEach( function (obj) { if (obj.direct) { result.libraries.push({ filePath: obj.filePath, wholeArchive: obj.wholeArchive, symbolLinkMode: obj.symbolLinkMode, framework: obj.framework }); } else { var dirPath = FileInfo.path(obj.filePath); if (!seenRPathLinkDirs.hasOwnProperty(dirPath)) { seenRPathLinkDirs[dirPath] = true; result.rpath_link.push(dirPath); } } }); return result; } function escapeLinkerFlags(product, inputs, linkerFlags) { if (!linkerFlags || linkerFlags.length === 0) return []; if (useCompilerDriverLinker(product, inputs)) { var sep = ","; var useXlinker = linkerFlags.some(function (f) { return f.contains(sep); }); if (useXlinker) { // One or more linker arguments contain the separator character itself // Use -Xlinker to handle these var xlinkerFlags = []; linkerFlags.map(function (linkerFlag) { if (product.cpp.enableSuspiciousLinkerFlagWarnings && linkerFlag.startsWith("-Wl,")) { console.warn("Encountered escaped linker flag '" + linkerFlag + "'. This may " + "cause the target to fail to link. Please do not escape these " + "flags manually; qbs does that for you."); } xlinkerFlags.push("-Xlinker", linkerFlag); }); return xlinkerFlags; } if (product.cpp.enableSuspiciousLinkerFlagWarnings && linkerFlags.contains("-Xlinker")) { console.warn("Encountered -Xlinker linker flag escape sequence. This may cause the " + "target to fail to link. Please do not escape these flags manually; " + "qbs does that for you."); } // If no linker arguments contain the separator character we can just use -Wl, // which is more compact and easier to read in logs return [["-Wl"].concat(linkerFlags).join(sep)]; } return linkerFlags; } function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPath) { var libraryPaths = product.cpp.libraryPaths; var distributionLibraryPaths = product.cpp.distributionLibraryPaths; var isDarwin = product.qbs.targetOS.contains("darwin"); var libraryDependencies = collectLibraryDependencies(product, isDarwin); var frameworks = product.cpp.frameworks; var weakFrameworks = product.cpp.weakFrameworks; var rpaths = (product.cpp.useRPaths !== false) ? product.cpp.rpaths : undefined; var systemRunPaths = product.cpp.systemRunPaths || []; var canonicalSystemRunPaths = systemRunPaths.map(function(p) { return File.canonicalFilePath(p); }); var i, args = additionalCompilerAndLinkerFlags(product); var escapableLinkerFlags = []; if (primaryOutput.fileTags.contains("dynamiclibrary")) { if (isDarwin) { args.push((function () { var tags = ["c", "cpp", "objc", "objcpp", "asm_cpp"]; for (var i = 0; i < tags.length; ++i) { if (linkerPath === product.cpp.compilerPathByLanguage[tags[i]]) return "-dynamiclib"; } return "-dylib"; // for ld64 })()); } else { args.push("-shared"); } if (isDarwin) { var internalVersion = product.cpp.internalVersion; if (internalVersion && isNumericProductVersion(internalVersion)) args.push("-current_version", internalVersion); escapableLinkerFlags.push("-install_name", UnixUtils.soname(product, primaryOutput.fileName)); } else { escapableLinkerFlags.push("-soname=" + UnixUtils.soname(product, primaryOutput.fileName)); } } if (primaryOutput.fileTags.contains("loadablemodule")) args.push(isDarwin ? "-bundle" : "-shared"); if (primaryOutput.fileTags.containsAny(["dynamiclibrary", "loadablemodule"])) { if (isDarwin) escapableLinkerFlags.push("-headerpad_max_install_names"); else escapableLinkerFlags.push("--as-needed"); } if (isLegacyQnxSdk(product)) { ["c", "cpp"].map(function (tag) { if (linkerPath === product.cpp.compilerPathByLanguage[tag]) args = args.concat(qnxLangArgs(product, tag)); }); } var targetLinkerFlags = product.cpp.targetLinkerFlags; if (targetLinkerFlags) Array.prototype.push.apply(escapableLinkerFlags, targetLinkerFlags); var sysroot = product.cpp.syslibroot; if (sysroot) { if (product.qbs.toolchain.contains("qcc")) escapableLinkerFlags.push("--sysroot=" + sysroot); else if (isDarwin) escapableLinkerFlags.push("-syslibroot", sysroot); else args.push("--sysroot=" + sysroot); // do not escape, compiler-as-linker also needs it } if (product.cpp.allowUnresolvedSymbols) { if (isDarwin) escapableLinkerFlags.push("-undefined", "suppress"); else escapableLinkerFlags.push("--unresolved-symbols=ignore-all"); } function fixupRPath(rpath) { // iOS, tvOS, watchOS, and others, are fine if (!product.qbs.targetOS.contains("macos")) return rpath; // ...as are newer versions of macOS var min = product.cpp.minimumMacosVersion; if (min && Utilities.versionCompare(min, "10.10") >= 0) return rpath; // In older versions of dyld, a trailing slash is required if (!rpath.endsWith("/")) return rpath + "/"; return rpath; } function isNotSystemRunPath(p) { return !FileInfo.isAbsolutePath(p) || (!systemRunPaths.contains(p) && !canonicalSystemRunPaths.contains(File.canonicalFilePath(p))); }; for (i in rpaths) { if (isNotSystemRunPath(rpaths[i])) escapableLinkerFlags.push("-rpath", fixupRPath(rpaths[i])); } if (product.cpp.entryPoint) escapableLinkerFlags.push("-e", product.cpp.entryPoint); if (product.qbs.toolchain.contains("mingw")) { if (product.consoleApplication !== undefined) escapableLinkerFlags.push("-subsystem", product.consoleApplication ? "console" : "windows"); var minimumWindowsVersion = product.cpp.minimumWindowsVersion; if (minimumWindowsVersion) { var subsystemVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'subsystem'); if (subsystemVersion) { var major = subsystemVersion.split('.')[0]; var minor = subsystemVersion.split('.')[1]; // http://sourceware.org/binutils/docs/ld/Options.html escapableLinkerFlags.push("--major-subsystem-version", major, "--minor-subsystem-version", minor, "--major-os-version", major, "--minor-os-version", minor); } } } if (inputs.aggregate_infoplist) args.push("-sectcreate", "__TEXT", "__info_plist", inputs.aggregate_infoplist[0].filePath); var isLinkingCppObjects = !!(inputs.cpp_obj || inputs.cpp_staticlibrary); var stdlib = isLinkingCppObjects ? product.cpp.cxxStandardLibrary : undefined; if (stdlib && product.qbs.toolchain.contains("clang")) args.push("-stdlib=" + stdlib); // Flags for library search paths var allLibraryPaths = []; if (libraryPaths) allLibraryPaths = allLibraryPaths.uniqueConcat(libraryPaths); if (distributionLibraryPaths) allLibraryPaths = allLibraryPaths.uniqueConcat(distributionLibraryPaths); if (systemRunPaths.length > 0) allLibraryPaths = allLibraryPaths.filter(isNotSystemRunPath); args = args.concat(allLibraryPaths.map(function(path) { return '-L' + path })); var linkerScripts = inputs.linkerscript ? inputs.linkerscript.map(function(a) { return a.filePath; }) : []; Array.prototype.push.apply(escapableLinkerFlags, [].uniqueConcat(linkerScripts) .map(function(path) { return '-T' + path })); var versionScripts = inputs.versionscript ? inputs.versionscript.map(function(a) { return a.filePath; }) : []; Array.prototype.push.apply(escapableLinkerFlags, [].uniqueConcat(versionScripts) .map(function(path) { return '--version-script=' + path })); if (isDarwin && product.cpp.warningLevel === "none") args.push('-w'); var useCompilerDriver = useCompilerDriverLinker(product, inputs); args = args.concat(configFlags(product, useCompilerDriver)); Array.prototype.push.apply(escapableLinkerFlags, product.cpp.platformLinkerFlags); Array.prototype.push.apply(escapableLinkerFlags, product.cpp.linkerFlags); // Note: due to the QCC response files hack in prepareLinker(), at least one object file or // library file must follow the output file path so that QCC has something to process before // sending the rest of the arguments through the response file. args.push("-o", primaryOutput.filePath); if (inputs.obj) args = args.concat(inputs.obj.map(function (obj) { return obj.filePath })); for (i in frameworks) { frameworkExecutablePath = PathTools.frameworkExecutablePath(frameworks[i]); if (FileInfo.isAbsolutePath(frameworkExecutablePath)) args.push(frameworkExecutablePath); else args = args.concat(['-framework', frameworks[i]]); } for (i in weakFrameworks) { frameworkExecutablePath = PathTools.frameworkExecutablePath(weakFrameworks[i]); if (FileInfo.isAbsolutePath(frameworkExecutablePath)) args = args.concat(['-weak_library', frameworkExecutablePath]); else args = args.concat(['-weak_framework', weakFrameworks[i]]); } var wholeArchiveActive = false; for (i = 0; i < libraryDependencies.libraries.length; ++i) { var dep = libraryDependencies.libraries[i]; var lib = dep.filePath; if (dep.wholeArchive && !wholeArchiveActive) { var wholeArchiveFlag; if (isDarwin) { wholeArchiveFlag = "-force_load"; } else { wholeArchiveFlag = "--whole-archive"; wholeArchiveActive = true; } Array.prototype.push.apply(args, escapeLinkerFlags(product, inputs, [wholeArchiveFlag])); } if (!dep.wholeArchive && wholeArchiveActive) { Array.prototype.push.apply(args, escapeLinkerFlags(product, inputs, ["--no-whole-archive"])); wholeArchiveActive = false; } var symbolLinkMode = dep.symbolLinkMode; if (isDarwin && symbolLinkMode) { if (!["lazy", "reexport", "upward", "weak"].contains(symbolLinkMode)) throw new Error("unknown value '" + symbolLinkMode + "' for cpp.symbolLinkMode"); if (FileInfo.isAbsolutePath(lib) || lib.startsWith('@')) escapableLinkerFlags.push("-" + symbolLinkMode + "_library", lib); else if (dep.framework) escapableLinkerFlags.push("-" + symbolLinkMode + "_framework", lib); else escapableLinkerFlags.push("-" + symbolLinkMode + "-l" + lib); } else if (FileInfo.isAbsolutePath(lib) || lib.startsWith('@')) { args.push(dep.framework ? PathTools.frameworkExecutablePath(lib) : lib); } else if (dep.framework) { args.push("-framework", lib); } else { args.push('-l' + lib); } } if (wholeArchiveActive) { Array.prototype.push.apply(args, escapeLinkerFlags(product, inputs, ["--no-whole-archive"])); } var discardUnusedData = product.cpp.discardUnusedData; if (discardUnusedData !== undefined) { var flags = []; if (discardUnusedData === true) { if (isDarwin) escapableLinkerFlags.push("-dead_strip"); else escapableLinkerFlags.push("--gc-sections"); } else if (!isDarwin) { escapableLinkerFlags.push("--no-gc-sections"); } } if (product.cpp.useRPathLink) { if (!product.cpp.rpathLinkFlag) throw new Error("Using rpath-link but cpp.rpathLinkFlag is not defined"); Array.prototype.push.apply(escapableLinkerFlags, libraryDependencies.rpath_link.map( function(dir) { return product.cpp.rpathLinkFlag + dir; })); } var importLibs = outputs.dynamiclibrary_import; if (importLibs) escapableLinkerFlags.push("--out-implib", importLibs[0].filePath); var escapedLinkerFlags = escapeLinkerFlags(product, inputs, escapableLinkerFlags); Array.prototype.push.apply(escapedLinkerFlags, args); var driverLinkerFlags = useCompilerDriver ? product.cpp.driverLinkerFlags : undefined; if (driverLinkerFlags) Array.prototype.push.apply(escapedLinkerFlags, driverLinkerFlags); return escapedLinkerFlags; } // for compiler AND linker function configFlags(config, isDriver) { var args = []; if (isDriver !== false) { args = args.concat(config.cpp.platformDriverFlags); args = args.concat(config.cpp.driverFlags); args = args.concat(config.cpp.targetDriverFlags); } var frameworkPaths = config.cpp.frameworkPaths; if (frameworkPaths) args = args.concat(frameworkPaths.map(function(path) { return '-F' + path })); var allSystemFrameworkPaths = []; var systemFrameworkPaths = config.cpp.systemFrameworkPaths; if (systemFrameworkPaths) allSystemFrameworkPaths = allSystemFrameworkPaths.uniqueConcat(systemFrameworkPaths); var distributionFrameworkPaths = config.cpp.distributionFrameworkPaths; if (distributionFrameworkPaths) allSystemFrameworkPaths = allSystemFrameworkPaths.uniqueConcat(distributionFrameworkPaths); args = args.concat(allSystemFrameworkPaths.map(function(path) { return '-iframework' + path })); return args; } function languageTagFromFileExtension(toolchain, fileName) { var i = fileName.lastIndexOf('.'); if (i === -1) return; var m = { "c" : "c", "C" : "cpp", "cpp" : "cpp", "cxx" : "cpp", "c++" : "cpp", "cc" : "cpp", "m" : "objc", "mm" : "objcpp", "s" : "asm", "S" : "asm_cpp" }; if (!toolchain.contains("clang")) m["sx"] = "asm_cpp"; // clang does NOT recognize .sx return m[fileName.substring(i + 1)]; } // Older versions of the QNX SDK have C and C++ compilers whose filenames differ only by case, // which won't work in case insensitive environments like Win32+NTFS, HFS+ and APFS function isLegacyQnxSdk(config) { return config.qbs.toolchain.contains("qcc") && config.qnx && !config.qnx.qnx7; } function effectiveCompilerInfo(toolchain, input, output) { var compilerPath, language; var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags)); // Whether we're compiling a precompiled header or normal source file var pchOutput = output.fileTags.contains(tag + "_pch"); var compilerPathByLanguage = input.cpp.compilerPathByLanguage; if (compilerPathByLanguage) compilerPath = compilerPathByLanguage[tag]; if (!compilerPath || tag !== languageTagFromFileExtension(toolchain, input.fileName) || isLegacyQnxSdk(input)) { if (input.qbs.toolchain.contains("qcc")) language = qnxLangArgs(input, tag); else language = ["-x", languageName(tag) + (pchOutput ? '-header' : '')]; } if (!compilerPath) // fall back to main compiler compilerPath = input.cpp.compilerPath; return { path: compilerPath, language: language, tag: tag }; } function qnxLangArgs(config, tag) { switch (tag) { case "c": return ["-lang-c"]; case "cpp": return ["-lang-c++"]; default: return []; } } function handleCpuFeatures(input, flags) { function potentiallyAddFlagForFeature(propName, flagName) { var propValue = input.cpufeatures[propName]; if (propValue === true) flags.push("-m" + flagName); else if (propValue === false) flags.push("-mno-" + flagName); } if (!input.qbs.architecture) return; if (input.qbs.architecture.startsWith("x86")) { potentiallyAddFlagForFeature("x86_avx", "avx"); potentiallyAddFlagForFeature("x86_avx2", "avx2"); potentiallyAddFlagForFeature("x86_avx512bw", "avx512bw"); potentiallyAddFlagForFeature("x86_avx512cd", "avx512cd"); potentiallyAddFlagForFeature("x86_avx512dq", "avx512dq"); potentiallyAddFlagForFeature("x86_avx512er", "avx512er"); potentiallyAddFlagForFeature("x86_avx512f", "avx512f"); potentiallyAddFlagForFeature("x86_avx512ifma", "avx512ifma"); potentiallyAddFlagForFeature("x86_avx512pf", "avx512pf"); potentiallyAddFlagForFeature("x86_avx512vbmi", "avx512vbmi"); potentiallyAddFlagForFeature("x86_avx512vl", "avx512vl"); potentiallyAddFlagForFeature("x86_f16c", "f16c"); potentiallyAddFlagForFeature("x86_sse2", "sse2"); potentiallyAddFlagForFeature("x86_sse3", "sse3"); potentiallyAddFlagForFeature("x86_sse4_1", "sse4.1"); potentiallyAddFlagForFeature("x86_sse4_2", "sse4.2"); potentiallyAddFlagForFeature("x86_ssse3", "ssse3"); } else if (input.qbs.architecture.startsWith("arm")) { if (input.cpufeatures.arm_neon === true) flags.push("-mfpu=neon"); if (input.cpufeatures.arm_vfpv4 === true) flags.push("-mfpu=vfpv4"); } else if (input.qbs.architecture.startsWith("mips")) { potentiallyAddFlagForFeature("mips_dsp", "dsp"); potentiallyAddFlagForFeature("mips_dspr2", "dspr2"); } } function standardFallbackValueOrDefault(toolchain, compilerVersion, languageVersion, useLanguageVersionFallback) { // NEVER use the fallback values (safety brake for users in case our version map is ever wrong) if (useLanguageVersionFallback === false) return languageVersion; // Deprecated, but compatible with older compiler versions. // Note that these versions are the first to support the *value* to the -std= command line // option, not necessarily the first versions where support for that language standard was // considered fully implemented. Tested manually. var languageVersionsMap = { "c++11": { "fallback": "c++0x", "toolchains": [ {"name": "xcode", "version": "4.3"}, {"name": "clang", "version": "3.0"}, {"name": "gcc", "version": "4.7"} ] }, "c11": { "fallback": "c1x", "toolchains": [ {"name": "xcode", "version": "5.0"}, {"name": "clang", "version": "3.1"}, {"name": "gcc", "version": "4.7"} ] }, "c++14": { "fallback": "c++1y", "toolchains": [ {"name": "xcode", "version": "6.3"}, {"name": "clang", "version": "3.5"}, {"name": "gcc", "version": "4.9"} ] }, "c++17": { "fallback": "c++1z", "toolchains": [ {"name": "xcode", "version": "9.3"}, {"name": "clang", "version": "5.0"}, {"name": "gcc", "version": "5.1"} ] }, "c++20": { "fallback": "c++2a", "toolchains": [ {"name": "xcode"}, // not yet implemented {"name": "clang"}, // not yet implemented {"name": "gcc"} // not yet implemented ] } }; var m = languageVersionsMap[languageVersion]; if (m) { for (var idx = 0; idx < m.toolchains.length; ++idx) { var tc = m.toolchains[idx]; if (toolchain.contains(tc.name)) { // If we found our toolchain and it doesn't yet support the language standard // we're requesting, or we're using an older version that only supports the // preliminary flag, use that. if (useLanguageVersionFallback || !tc.version || Utilities.versionCompare(compilerVersion, tc.version) < 0) return m.fallback; break; } } } // If we didn't find our toolchain at all, simply use the standard value. return languageVersion; } function compilerFlags(project, product, input, output, explicitlyDependsOn) { var i; var includePaths = input.cpp.includePaths; var systemIncludePaths = input.cpp.systemIncludePaths; var distributionIncludePaths = input.cpp.distributionIncludePaths; var platformDefines = input.cpp.platformDefines; var defines = input.cpp.defines; // Determine which C-language we're compiling var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags)); if (!["c", "cpp", "objc", "objcpp", "asm_cpp"].contains(tag)) throw ("unsupported source language: " + tag); var compilerInfo = effectiveCompilerInfo(product.qbs.toolchain, input, output); var args = additionalCompilerAndLinkerFlags(product); Array.prototype.push.apply(args, product.cpp.sysrootFlags); handleCpuFeatures(input, args); if (input.cpp.debugInformation) args.push('-g'); var opt = input.cpp.optimization if (opt === 'fast') args.push('-O2'); if (opt === 'small') args.push('-Os'); if (opt === 'none') args.push('-O0'); var warnings = input.cpp.warningLevel if (warnings === 'none') args.push('-w'); if (warnings === 'all') { args.push('-Wall'); args.push('-Wextra'); } if (input.cpp.treatWarningsAsErrors) args.push('-Werror'); args = args.concat(configFlags(input)); if (!input.qbs.toolchain.contains("qcc")) args.push('-pipe'); if (input.cpp.enableReproducibleBuilds) { var toolchain = product.qbs.toolchain; if (!toolchain.contains("clang")) { var hashString = FileInfo.relativePath(project.sourceDirectory, input.filePath); var hash = Utilities.getHash(hashString); args.push("-frandom-seed=0x" + hash.substring(0, 8)); } var major = product.cpp.compilerVersionMajor; var minor = product.cpp.compilerVersionMinor; if ((toolchain.contains("clang") && (major > 3 || (major === 3 && minor >= 5))) || (toolchain.contains("gcc") && (major > 4 || (major === 4 && minor >= 9)))) { args.push("-Wdate-time"); } } var useArc = input.cpp.automaticReferenceCounting; if (useArc !== undefined && (tag === "objc" || tag === "objcpp")) { args.push(useArc ? "-fobjc-arc" : "-fno-objc-arc"); } var enableExceptions = input.cpp.enableExceptions; if (enableExceptions !== undefined) { if (tag === "cpp" || tag === "objcpp") args.push(enableExceptions ? "-fexceptions" : "-fno-exceptions"); if (tag === "objc" || tag === "objcpp") { args.push(enableExceptions ? "-fobjc-exceptions" : "-fno-objc-exceptions"); if (useArc !== undefined) args.push(useArc ? "-fobjc-arc-exceptions" : "-fno-objc-arc-exceptions"); } } var enableRtti = input.cpp.enableRtti; if (enableRtti !== undefined && (tag === "cpp" || tag === "objcpp")) { args.push(enableRtti ? "-frtti" : "-fno-rtti"); } var visibility = input.cpp.visibility; if (!product.qbs.toolchain.contains("mingw")) { if (visibility === 'hidden' || visibility === 'minimal') args.push('-fvisibility=hidden'); if ((visibility === 'hiddenInlines' || visibility === 'minimal') && tag === 'cpp') args.push('-fvisibility-inlines-hidden'); if (visibility === 'default') args.push('-fvisibility=default') } if (compilerInfo.language) // Only push language arguments if we have to. Array.prototype.push.apply(args, compilerInfo.language); args = args.concat(ModUtils.moduleProperty(input, 'platformFlags'), ModUtils.moduleProperty(input, 'flags'), ModUtils.moduleProperty(input, 'platformFlags', tag), ModUtils.moduleProperty(input, 'flags', tag)); var pchTag = compilerInfo.tag + "_pch"; var pchOutput = output.fileTags.contains(pchTag); var pchInputs = explicitlyDependsOn[pchTag]; if (!pchOutput && pchInputs && pchInputs.length === 1 && ModUtils.moduleProperty(input, 'usePrecompiledHeader', tag)) { var pchInput = pchInputs[0]; var pchFilePath = FileInfo.joinPaths(FileInfo.path(pchInput.filePath), pchInput.completeBaseName); args.push('-include', pchFilePath); } var prefixHeaders = input.cpp.prefixHeaders; for (i in prefixHeaders) { args.push('-include'); args.push(prefixHeaders[i]); } var positionIndependentCode = input.cpp.positionIndependentCode; if (positionIndependentCode && !product.qbs.toolchain.contains("mingw")) args.push('-fPIC'); var cppFlags = input.cpp.cppFlags; for (i in cppFlags) args.push('-Wp,' + cppFlags[i]) var allDefines = []; if (platformDefines) allDefines = allDefines.uniqueConcat(platformDefines); if (defines) allDefines = allDefines.uniqueConcat(defines); args = args.concat(allDefines.map(function(define) { return '-D' + define })); if (includePaths) { args = args.concat([].uniqueConcat(includePaths).map(function(path) { return input.cpp.includeFlag + path; })); } var allSystemIncludePaths = []; if (systemIncludePaths) allSystemIncludePaths = allSystemIncludePaths.uniqueConcat(systemIncludePaths); if (distributionIncludePaths) allSystemIncludePaths = allSystemIncludePaths.uniqueConcat(distributionIncludePaths); allSystemIncludePaths.forEach(function(v) { args.push(input.cpp.systemIncludeFlag, v); }); var minimumWindowsVersion = input.cpp.minimumWindowsVersion; if (minimumWindowsVersion && product.qbs.targetOS.contains("windows")) { var hexVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'hex'); if (hexVersion) { var versionDefs = [ 'WINVER', '_WIN32_WINNT', '_WIN32_WINDOWS' ]; for (i in versionDefs) args.push('-D' + versionDefs[i] + '=' + hexVersion); } } function currentLanguageVersion(tag) { switch (tag) { case "c": case "objc": var knownValues = ["c11", "c99", "c90", "c89"]; return Cpp.languageVersion(input.cpp.cLanguageVersion, knownValues, "C"); case "cpp": case "objcpp": knownValues = ["c++20", "c++2a", "c++17", "c++1z", "c++14", "c++1y", "c++11", "c++0x", "c++03", "c++98"]; return Cpp.languageVersion(input.cpp.cxxLanguageVersion, knownValues, "C++"); } } var langVersion = currentLanguageVersion(tag); if (langVersion) { args.push("-std=" + standardFallbackValueOrDefault(product.qbs.toolchain, product.cpp.compilerVersion, langVersion, product.cpp.useLanguageVersionFallback)); } if (tag === "cpp" || tag === "objcpp") { var cxxStandardLibrary = product.cpp.cxxStandardLibrary; if (cxxStandardLibrary && product.qbs.toolchain.contains("clang")) { args.push("-stdlib=" + cxxStandardLibrary); } } args.push("-o", output.filePath); args.push("-c", input.filePath); return args; } function additionalCompilerAndLinkerFlags(product) { var args = [] var requireAppExtensionSafeApi = product.cpp.requireAppExtensionSafeApi; if (requireAppExtensionSafeApi !== undefined && product.qbs.targetOS.contains("darwin")) { args.push(requireAppExtensionSafeApi ? "-fapplication-extension" : "-fno-application-extension"); } return args } // Returns the GCC language name equivalent to fileTag, accepted by the -x argument function languageName(fileTag) { if (fileTag === 'c') return 'c'; else if (fileTag === 'cpp') return 'c++'; else if (fileTag === 'objc') return 'objective-c'; else if (fileTag === 'objcpp') return 'objective-c++'; else if (fileTag === 'asm') return 'assembler'; else if (fileTag === 'asm_cpp') return 'assembler-with-cpp'; } function prepareAssembler(project, product, inputs, outputs, input, output) { var assemblerPath = product.cpp.assemblerPath; var includePaths = input.cpp.includePaths; var systemIncludePaths = input.cpp.systemIncludePaths; var distributionIncludePaths = input.cpp.distributionIncludePaths; var args = product.cpp.targetAssemblerFlags; if (input.cpp.debugInformation) args.push('-g'); var warnings = input.cpp.warningLevel if (warnings === 'none') args.push('-W'); var tag = "asm"; args = args.concat(ModUtils.moduleProperty(input, 'platformFlags', tag), ModUtils.moduleProperty(input, 'flags', tag)); var allIncludePaths = []; if (includePaths) allIncludePaths = allIncludePaths.uniqueConcat(includePaths); if (systemIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths); if (distributionIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(distributionIncludePaths); args = args.concat(allIncludePaths.map(function(path) { return input.cpp.includeFlag + path })); args.push("-o", output.filePath); args.push(input.filePath); var cmd = new Command(assemblerPath, args); cmd.description = "assembling " + input.fileName; cmd.highlight = "compiler"; cmd.jobPool = "assembler"; return cmd; } function compilerEnvVars(config, compilerInfo) { if (config.qbs.toolchain.contains("qcc")) return ["QCC_CONF_PATH"]; var list = ["CPATH", "TMPDIR"]; if (compilerInfo.tag === "c") list.push("C_INCLUDE_PATH"); else if (compilerInfo.tag === "cpp") list.push("CPLUS_INCLUDE_PATH"); else if (compilerInfo.tag === "objc") list.push("OBJC_INCLUDE_PATH"); else if (compilerInfo.tag === "objccpp") list.push("OBJCPLUS_INCLUDE_PATH"); if (config.qbs.targetOS.contains("macos")) list.push("MACOSX_DEPLOYMENT_TARGET"); else if (config.qbs.targetOS.contains("ios")) list.push("IPHONEOS_DEPLOYMENT_TARGET"); else if (config.qbs.targetOS.contains("tvos")) list.push("TVOS_DEPLOYMENT_TARGET"); else if (config.qbs.targetOS.contains("watchos")) list.push("WATCHOS_DEPLOYMENT_TARGET"); if (config.qbs.toolchain.contains("clang")) { list.push("TEMP", "TMP"); } else { list.push("LANG", "LC_CTYPE", "LC_MESSAGES", "LC_ALL", "GCC_COMPARE_DEBUG", "GCC_EXEC_PREFIX", "COMPILER_PATH", "SOURCE_DATE_EPOCH"); } return list; } function linkerEnvVars(config, inputs) { if (config.qbs.toolchain.contains("clang") || config.qbs.toolchain.contains("qcc")) return []; var list = ["GNUTARGET", "LDEMULATION", "COLLECT_NO_DEMANGLE"]; if (useCompilerDriverLinker(config, inputs)) list.push("LIBRARY_PATH"); return list; } function setResponseFileThreshold(command, product) { if (product.qbs.toolchain.contains("mingw") && product.qbs.hostOS.contains("windows")) command.responseFileThreshold = 10000; } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var compilerInfo = effectiveCompilerInfo(product.qbs.toolchain, input, output); var compilerPath = compilerInfo.path; var pchOutput = output.fileTags.contains(compilerInfo.tag + "_pch"); var args = compilerFlags(project, product, input, output, explicitlyDependsOn); var wrapperArgsLength = 0; var wrapperArgs = product.cpp.compilerWrapper; var extraEnv; if (wrapperArgs && wrapperArgs.length > 0) { // distcc cannot deal with absolute compiler paths (QBS-1336). for (var i = 0; i < wrapperArgs.length; ++i) { if (FileInfo.baseName(wrapperArgs[i]) !== "distcc") continue; if (i === wrapperArgs.length - 1) { if (FileInfo.isAbsolutePath(compilerPath)) { extraEnv = ["PATH=" + FileInfo.path(compilerPath)]; compilerPath = FileInfo.fileName(compilerPath); } } else if (FileInfo.isAbsolutePath(wrapperArgs[i + 1])) { extraEnv = ["PATH=" + FileInfo.path(FileInfo.path(wrapperArgs[i + 1]))]; wrapperArgs[i + 1] = FileInfo.fileName(wrapperArgs[i + 1]); } break; } wrapperArgsLength = wrapperArgs.length; args.unshift(compilerPath); compilerPath = wrapperArgs.shift(); args = wrapperArgs.concat(args); } var cmd = new Command(compilerPath, args); cmd.description = (pchOutput ? 'pre' : '') + 'compiling ' + input.fileName; if (pchOutput) cmd.description += ' (' + compilerInfo.tag + ')'; cmd.highlight = "compiler"; cmd.jobPool = "compiler"; cmd.relevantEnvironmentVariables = compilerEnvVars(input, compilerInfo); if (extraEnv) cmd.environment = extraEnv; cmd.responseFileArgumentIndex = wrapperArgsLength; cmd.responseFileUsagePrefix = '@'; setResponseFileThreshold(cmd, product); return cmd; } // Concatenates two arrays of library names and preserves the dependency order that ld needs. function concatLibs(libs, deplibs) { var r = []; var s = {}; function addLibs(lst) { for (var i = lst.length; --i >= 0;) { var lib = lst[i]; if (!s[lib]) { s[lib] = true; r.unshift(lib); } } } addLibs(deplibs); addLibs(libs); return r; } function collectStdoutLines(command, args) { var p = new Process(); try { p.exec(command, args); return p.readStdOut().split(/\r?\n/g).filter(function (e) { return e; }); } finally { p.close(); } } function getSymbolInfo(product, inputFile) { var result = { }; var command = product.cpp.nmPath; var args = ["-g", "-P"]; if (product.cpp._nmHasDynamicOption) args.push("-D"); try { result.allGlobalSymbols = collectStdoutLines(command, args.concat(inputFile)); // GNU nm has the "--defined" option but POSIX nm does not, so we have to manually // construct the list of defined symbols by subtracting. var undefinedGlobalSymbols = collectStdoutLines(command, args.concat(["-u", inputFile])); result.definedGlobalSymbols = result.allGlobalSymbols.filter(function(line) { return !undefinedGlobalSymbols.contains(line); }); result.success = true; } catch (e) { console.debug("Failed to collect symbols for shared library: nm command '" + command + "' failed (" + e.toString() + ")"); result.success = false; } return result; } function createSymbolFile(filePath, allSymbols, definedSymbols) { var file; try { file = new TextFile(filePath, TextFile.WriteOnly); for (var lineNr in allSymbols) file.writeLine(allSymbols[lineNr]); file.writeLine("==="); for (lineNr in definedSymbols) file.writeLine(definedSymbols[lineNr]); } finally { if (file) file.close(); } } function readSymbolFile(filePath) { var result = { success: true, allGlobalSymbols: [], definedGlobalSymbols: [] }; var file; try { file = new TextFile(filePath, TextFile.ReadOnly); var prop = "allGlobalSymbols"; while (true) { var line = file.readLine(); if (!line) break; if (line === "===") { prop = "definedGlobalSymbols"; continue; } result[prop].push(line); } } catch (e) { console.debug("Failed to read symbols from '" + filePath + "'"); result.success = false; } finally { if (file) file.close(); } return result; } function createSymbolCheckingCommands(product, outputs) { var commands = []; if (!outputs.dynamiclibrary || !outputs.dynamiclibrary_symbols) return commands; if (outputs.dynamiclibrary.length !== outputs.dynamiclibrary_symbols.length) throw new Error("The number of outputs tagged dynamiclibrary (" + outputs.dynamiclibrary.length + ") must be equal to the number of " + "outputs tagged dynamiclibrary_symbols (" + outputs.dynamiclibrary_symbols.length + ")"); for (var d = 0; d < outputs.dynamiclibrary_symbols.length; ++d) { // Update the symbols file if the list of relevant symbols has changed. var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.d = d; cmd.sourceCode = function() { if (outputs.dynamiclibrary[d].qbs.buildVariant !== outputs.dynamiclibrary_symbols[d].qbs.buildVariant) throw new Error("Build variant of output tagged dynamiclibrary (" + outputs.dynamiclibrary[d].qbs.buildVariant + ") is not equal to " + "build variant of output tagged dynamiclibrary_symbols (" + outputs.dynamiclibrary_symbols[d].qbs.buildVariant + ") at index " + d); var libFilePath = outputs.dynamiclibrary[d].filePath; var symbolFilePath = outputs.dynamiclibrary_symbols[d].filePath; var newNmResult = getSymbolInfo(product, libFilePath); if (!newNmResult.success) return; if (!File.exists(symbolFilePath)) { console.debug("Symbol file '" + symbolFilePath + "' does not yet exist."); createSymbolFile(symbolFilePath, newNmResult.allGlobalSymbols, newNmResult.definedGlobalSymbols); return; } var oldNmResult = readSymbolFile(symbolFilePath); var checkMode = product.cpp.exportedSymbolsCheckMode; var oldSymbols; var newSymbols; if (checkMode === "strict") { oldSymbols = oldNmResult.allGlobalSymbols; newSymbols = newNmResult.allGlobalSymbols; } else { oldSymbols = oldNmResult.definedGlobalSymbols; newSymbols = newNmResult.definedGlobalSymbols; } if (oldSymbols.length !== newSymbols.length) { console.debug("List of relevant symbols differs for '" + libFilePath + "'."); createSymbolFile(symbolFilePath, newNmResult.allGlobalSymbols, newNmResult.definedGlobalSymbols); return; } for (var i = 0; i < oldSymbols.length; ++i) { var oldLine = oldSymbols[i]; var newLine = newSymbols[i]; var oldLineElems = oldLine.split(/\s+/); var newLineElems = newLine.split(/\s+/); if (oldLineElems[0] !== newLineElems[0] // Object name. || oldLineElems[1] !== newLineElems[1]) { // Object type console.debug("List of relevant symbols differs for '" + libFilePath + "'."); createSymbolFile(symbolFilePath, newNmResult.allGlobalSymbols, newNmResult.definedGlobalSymbols); return; } } } commands.push(cmd); } return commands; } function prepareLinker(project, product, inputs, outputs, input, output) { var i, primaryOutput, cmd, commands = []; if (outputs.application) { primaryOutput = outputs.application[0]; } else if (outputs.dynamiclibrary) { primaryOutput = outputs.dynamiclibrary[0]; } else if (outputs.loadablemodule) { primaryOutput = outputs.loadablemodule[0]; } var linkerPath = effectiveLinkerPath(product, inputs) var args = linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPath); var wrapperArgsLength = 0; var wrapperArgs = product.cpp.linkerWrapper; if (wrapperArgs && wrapperArgs.length > 0) { wrapperArgsLength = wrapperArgs.length; args.unshift(linkerPath); linkerPath = wrapperArgs.shift(); args = wrapperArgs.concat(args); } var responseFileArgumentIndex = wrapperArgsLength; // qcc doesn't properly handle response files, so we have to do it manually var useQnxResponseFileHack = product.qbs.toolchain.contains("qcc") && useCompilerDriverLinker(product, inputs); if (useQnxResponseFileHack) { // qcc needs to see at least one object/library file to think it has something to do, // so start the response file at the second object file (so, 3 after the last -o option) var idx = args.lastIndexOf("-o"); if (idx !== -1 && idx + 3 < args.length) responseFileArgumentIndex += idx + 3; } cmd = new Command(linkerPath, args); cmd.description = 'linking ' + primaryOutput.fileName; cmd.highlight = 'linker'; cmd.jobPool = "linker"; cmd.relevantEnvironmentVariables = linkerEnvVars(product, inputs); cmd.responseFileArgumentIndex = responseFileArgumentIndex; cmd.responseFileUsagePrefix = useQnxResponseFileHack ? "-Wl,@" : "@"; setResponseFileThreshold(cmd, product); commands.push(cmd); var debugInfo = outputs.debuginfo_app || outputs.debuginfo_dll || outputs.debuginfo_loadablemodule; if (debugInfo) { if (product.qbs.targetOS.contains("darwin")) { if (!product.aggregate) { var dsymPath = debugInfo[0].filePath; if (outputs.debuginfo_bundle && outputs.debuginfo_bundle[0]) dsymPath = outputs.debuginfo_bundle[0].filePath; var flags = product.cpp.dsymutilFlags || []; cmd = new Command(product.cpp.dsymutilPath, flags.concat([ "-o", dsymPath, primaryOutput.filePath ])); cmd.description = "generating dSYM for " + product.name; commands.push(cmd); cmd = new Command(product.cpp.stripPath, ["-S", primaryOutput.filePath]); cmd.silent = true; commands.push(cmd); } } else { var objcopy = product.cpp.objcopyPath; cmd = new Command(objcopy, ["--only-keep-debug", primaryOutput.filePath, debugInfo[0].filePath]); cmd.silent = true; commands.push(cmd); cmd = new Command(objcopy, ["--strip-debug", primaryOutput.filePath]); cmd.silent = true; commands.push(cmd); cmd = new Command(objcopy, ["--add-gnu-debuglink=" + debugInfo[0].filePath, primaryOutput.filePath]); cmd.silent = true; commands.push(cmd); } } if (outputs.dynamiclibrary) { Array.prototype.push.apply(commands, createSymbolCheckingCommands(product, outputs)); // Create symlinks from {libfoo, libfoo.1, libfoo.1.0} to libfoo.1.0.0 var links = outputs["dynamiclibrary_symlink"]; var symlinkCount = links ? links.length : 0; for (i = 0; i < symlinkCount; ++i) { cmd = new Command("ln", ["-sf", primaryOutput.fileName, links[i].filePath]); cmd.highlight = "filegen"; cmd.description = "creating symbolic link '" + links[i].fileName + "'"; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath); commands.push(cmd); } } if (product.xcode && product.bundle) { var actualSigningIdentity = product.xcode.actualSigningIdentity; var codesignDisplayName = product.xcode.actualSigningIdentityDisplayName; if (actualSigningIdentity && !product.bundle.isBundle) { args = product.xcode.codesignFlags || []; args.push("--force"); args.push("--sign", actualSigningIdentity); args = args.concat(DarwinTools._codeSignTimestampFlags(product)); for (var j in inputs.xcent) { args.push("--entitlements", inputs.xcent[j].filePath); break; // there should only be one } args.push(primaryOutput.filePath); cmd = new Command(product.xcode.codesignPath, args); cmd.description = "codesign " + primaryOutput.fileName + " using " + codesignDisplayName + " (" + actualSigningIdentity + ")"; commands.push(cmd); } } return commands; } function debugInfoArtifacts(product, variants, debugInfoTagSuffix) { var fileTag; switch (debugInfoTagSuffix) { case "app": fileTag = "application"; break; case "dll": fileTag = "dynamiclibrary"; break; default: fileTag = debugInfoTagSuffix; break; } variants = variants || [{}]; var artifacts = []; if (product.cpp.separateDebugInformation) { variants.map(function (variant) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoFilePath(product, variant.suffix, fileTag)), fileTags: ["debuginfo_" + debugInfoTagSuffix] }); }); if (PathTools.debugInfoIsBundle(product)) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoBundlePath(product, fileTag)), fileTags: ["debuginfo_bundle"] }); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoPlistFilePath(product, fileTag)), fileTags: ["debuginfo_plist"] }); } } return artifacts; } function isNumericProductVersion(version) { return version && version.match(/^([0-9]+\.){0,3}[0-9]+$/); } function dumpMacros(env, compilerFilePath, args, nullDevice, tag) { var p = new Process(); try { p.setEnv("LC_ALL", "C"); for (var key in env) p.setEnv(key, env[key]); // qcc NEEDS the explicit -Wp, prefix to -dM; clang and gcc do not but all three accept it p.exec(compilerFilePath, (args || []).concat(["-Wp,-dM", "-E", "-x", languageName(tag || "c") , nullDevice]), true); var map = {}; p.readStdOut().trim().split(/\r?\n/g).map(function (line) { var parts = line.split(" ", 3); map[parts[1]] = parts[2]; }); return map; } finally { p.close(); } } function dumpDefaultPaths(env, compilerFilePath, args, nullDevice, pathListSeparator, sysroot, targetOS) { var p = new Process(); try { p.setEnv("LC_ALL", "C"); for (var key in env) p.setEnv(key, env[key]); args = args || []; p.exec(compilerFilePath, args.concat(["-v", "-E", "-x", "c++", nullDevice]), true); var suffix = " (framework directory)"; var includePaths = []; var libraryPaths = []; var frameworkPaths = []; var addIncludes = false; var lines = p.readStdErr().trim().split(/\r?\n/g).map(function (line) { return line.trim(); }); for (var i = 0; i < lines.length; ++i) { var line = lines[i]; var prefix = "LIBRARY_PATH="; if (line.startsWith(prefix)) { libraryPaths = libraryPaths.concat(line.substr(prefix.length) .split(pathListSeparator)); } else if (line === "#include <...> search starts here:") { addIncludes = true; } else if (line === "End of search list.") { addIncludes = false; } else if (addIncludes) { if (line.endsWith(suffix)) frameworkPaths.push(line.substr(0, line.length - suffix.length)); else includePaths.push(line); } } sysroot = sysroot || ""; if (includePaths.length === 0) includePaths.push(sysroot + "/usr/include", sysroot + "/usr/local/include"); if (libraryPaths.length === 0) libraryPaths.push(sysroot + "/lib", sysroot + "/usr/lib"); if (frameworkPaths.length === 0 && targetOS.contains("darwin")) frameworkPaths.push(sysroot + "/System/Library/Frameworks"); return { "includePaths": includePaths, "libraryPaths": libraryPaths, "frameworkPaths": frameworkPaths }; } finally { p.close(); } } function targetFlags(tool, hasTargetOption, target, targetArch, machineType, targetOS) { var args = []; if (hasTargetOption) { if (target) args.push("-target", target); } else { var archArgs = { "compiler": { "i386": ["-m32"], "x86_64": ["-m64"], }, "linker": { "i386": ["-m", targetOS.contains("windows") ? "i386pe" : "elf_i386"], "x86_64": ["-m", targetOS.contains("windows") ? "i386pep" : "elf_x86_64"], }, "assembler": { "i386": ["--32"], "x86_64": ["--64"], }, }; var flags = archArgs[tool] ? archArgs[tool][targetArch] : undefined; if (flags) args = args.concat(flags); if (machineType && tool !== "linker") args.push("-march=" + machineType); } return args; } function toolNames(rawToolNames, toolchainPrefix) { return toolchainPrefix ? rawToolNames.map(function(rawName) { return toolchainPrefix + rawName; }) : rawToolNames; } function pathPrefix(baseDir, prefix) { var path = ''; if (baseDir) { path += baseDir; if (path.substr(-1) !== '/') path += '/'; } if (prefix) path += prefix; return path; } qbs-src-1.13.1/share/qbs/modules/cpp/iar.js000066400000000000000000000330771347155106100204160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Cpp = require("cpp.js"); var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); var TemporaryDir = require("qbs.TemporaryDir"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); var WindowsUtils = require("qbs.WindowsUtils"); function guessArchitecture(macros) { if (macros["__ICCARM__"] === "1") return "arm"; else if (macros["__ICC8051__"] === "1") return "mcs51"; else if (macros["__ICCAVR__"] === "1") return "avr"; } function guessEndianness(macros) { if (macros["__LITTLE_ENDIAN__"] === "1") return "little"; return "big" } function dumpMacros(compilerFilePath, qbs, nullDevice) { var tempDir = new TemporaryDir(); var inFilePath = FileInfo.fromNativeSeparators(tempDir.path() + "/empty-source.c"); var inFile = new TextFile(inFilePath, TextFile.WriteOnly); var outFilePath = FileInfo.fromNativeSeparators(tempDir.path() + "/iar-macros.predef"); var p = new Process(); p.exec(compilerFilePath, [ inFilePath, "--predef_macros", outFilePath ], true); var outFile = new TextFile(outFilePath, TextFile.ReadOnly); var map = {}; outFile.readAll().trim().split(/\r?\n/g).map(function (line) { var parts = line.split(" ", 3); map[parts[1]] = parts[2]; }); return map; } function collectLibraryDependencies(product) { var seen = {}; var result = []; function addFilePath(filePath) { result.push({ filePath: filePath }); } function addArtifactFilePaths(dep, artifacts) { if (!artifacts) return; var artifactFilePaths = artifacts.map(function(a) { return a.filePath; }); artifactFilePaths.forEach(addFilePath); } function addExternalStaticLibs(obj) { if (!obj.cpp) return; function ensureArray(a) { return Array.isArray(a) ? a : []; } function sanitizedModuleListProperty(obj, moduleName, propertyName) { return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName)); } var externalLibs = [].concat( sanitizedModuleListProperty(obj, "cpp", "staticLibraries")); var staticLibrarySuffix = obj.moduleProperty("cpp", "staticLibrarySuffix"); externalLibs.forEach(function(staticLibraryName) { if (!staticLibraryName.endsWith(staticLibrarySuffix)) staticLibraryName += staticLibrarySuffix; addFilePath(staticLibraryName); }); } function traverse(dep) { if (seen.hasOwnProperty(dep.name)) return; seen[dep.name] = true; if (dep.parameters.cpp && dep.parameters.cpp.link === false) return; var staticLibraryArtifacts = dep.artifacts["staticlibrary"]; if (staticLibraryArtifacts) { dep.dependencies.forEach(traverse); addArtifactFilePaths(dep, staticLibraryArtifacts); addExternalStaticLibs(dep); } } product.dependencies.forEach(traverse); addExternalStaticLibs(product); return result; } function compilerFlags(project, product, input, output, explicitlyDependsOn) { // Determine which C-language we"re compiling. var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags)); var args = []; args.push(input.filePath); switch (input.cpp.optimization) { case "small": args.push("-Ohs"); break; case "fast": args.push("-Ohz"); break; case "none": args.push("-On"); break; } if (input.cpp.debugInformation) args.push("--debug"); var warnings = input.cpp.warningLevel; if (warnings === "none") { args.push("--no_warnings"); } else if (warnings === "all") { args.push("--deprecated_feature_warnings=" +"+attribute_syntax," +"+preprocessor_extensions," +"+segment_pragmas"); if (tag === "cpp") args.push("--warn_about_c_style_casts"); } if (input.cpp.treatWarningsAsErrors) args.push("--warnings_are_errors"); // Choose byte order. var endianness = input.cpp.endianness; if (endianness) { if (input.qbs.architecture === "arm") args.push("--endian=" + endianness); } if (tag === "c") { // Language version. if (input.cpp.cLanguageVersion === "c89") args.push("--c89"); } else if (tag === "cpp") { if (input.qbs.architecture === "arm") { args.push("--c++"); if (!input.cpp.enableExceptions) args.push("--no_exceptions"); if (!input.cpp.enableRtti) args.push("--no_rtti"); } else if (input.qbs.architecture === "mcs51") { args.push("--ec++"); } else if (input.qbs.architecture === "avr") { args.push("--ec++"); } } var allDefines = []; var platformDefines = input.cpp.platformDefines; if (platformDefines) allDefines = allDefines.uniqueConcat(platformDefines); var defines = input.cpp.defines; if (defines) allDefines = allDefines.uniqueConcat(defines); args = args.concat(allDefines.map(function(define) { return "-D" + define })); var allIncludePaths = []; var includePaths = input.cpp.includePaths; if (includePaths) allIncludePaths = allIncludePaths.uniqueConcat(includePaths); var systemIncludePaths = input.cpp.systemIncludePaths; if (systemIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths); var compilerIncludePaths = input.cpp.compilerIncludePaths; if (compilerIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths); args = args.concat(allIncludePaths.map(function(include) { return "-I" + include })); args.push("-o", output.filePath); args.push("--silent"); // Silent operation. args = args.concat(ModUtils.moduleProperty(input, "platformFlags"), ModUtils.moduleProperty(input, "flags"), ModUtils.moduleProperty(input, "platformFlags", tag), ModUtils.moduleProperty(input, "flags", tag), ModUtils.moduleProperty(input, "driverFlags", tag)); return args; } function assemblerFlags(project, product, input, output, explicitlyDependsOn) { // Determine which C-language we"re compiling var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags)); var args = []; args.push(input.filePath); if (input.cpp.debugInformation) args.push("-r"); var warnings = input.cpp.warningLevel; if (warnings === "none") args.push("-w-"); else args.push("-w+"); var allIncludePaths = []; var systemIncludePaths = input.cpp.systemIncludePaths; if (systemIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths); var compilerIncludePaths = input.cpp.compilerIncludePaths; if (compilerIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths); args = args.concat(allIncludePaths.map(function(include) { return "-I" + include })); args.push("-o", output.filePath); args.push("-S"); // Silent operation. args = args.concat(ModUtils.moduleProperty(input, "platformFlags", tag), ModUtils.moduleProperty(input, "flags", tag), ModUtils.moduleProperty(input, "driverFlags", tag)); return args; } function linkerFlags(project, product, input, outputs) { var i; var args = []; if (inputs.obj) args = args.concat(inputs.obj.map(function(obj) { return obj.filePath })); args.push("-o", outputs.application[0].filePath); if (product.cpp.generateMapFile) { if (product.qbs.architecture === "arm") args.push("--map", outputs.map_file[0].filePath); else if (product.qbs.architecture === "mcs51") args.push("-l", outputs.map_file[0].filePath); else if (product.qbs.architecture === "avr") args.push("-l", outputs.map_file[0].filePath); } var allLibraryPaths = []; var libraryPaths = product.cpp.libraryPaths; if (libraryPaths) allLibraryPaths = allLibraryPaths.uniqueConcat(libraryPaths); var distributionLibraryPaths = product.cpp.distributionLibraryPaths; if (distributionLibraryPaths) allLibraryPaths = allLibraryPaths.uniqueConcat(distributionLibraryPaths); args = args.concat(allLibraryPaths.map(function(path) { return '-L' + path })); var libraryDependencies = collectLibraryDependencies(product); if (libraryDependencies) args = args.concat(libraryDependencies.map(function(dep) { return dep.filePath })); if (product.cpp.debugInformation) { if (product.qbs.architecture === "mcs51") args.push("-rt"); else if (product.qbs.architecture === "avr") args.push("-rt"); } var linkerScripts = inputs.linkerscript ? inputs.linkerscript.map(function(a) { return a.filePath; }) : []; for (i in linkerScripts) { if (product.qbs.architecture === "arm") args.push("--config", linkerScripts[i]); else if (product.qbs.architecture === "mcs51") args.push("-f", linkerScripts[i]); else if (product.qbs.architecture === "avr") args.push("-f", linkerScripts[i]); } if (product.cpp.entryPoint) { if (product.qbs.architecture === "arm") args.push("--entry", product.cpp.entryPoint); else if (product.qbs.architecture === "mcs51") args.push("-s", product.cpp.entryPoint); else if (product.qbs.architecture === "avr") args.push("-s", product.cpp.entryPoint); } if (product.qbs.architecture === "arm") args.push("--silent"); // Silent operation. else if (product.qbs.architecture === "mcs51") args.push("-S"); // Silent operation. else if (product.qbs.architecture === "avr") args.push("-S"); // Silent operation. args = args.concat(ModUtils.moduleProperty(product, "driverLinkerFlags")); return args; } function archiverFlags(project, product, input, outputs) { var args = []; if (inputs.obj) args = args.concat(inputs.obj.map(function(obj) { return obj.filePath })); args.push("--create"); args.push("-o", outputs.staticlibrary[0].filePath); return args; } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = compilerFlags(project, product, input, output, explicitlyDependsOn); var compilerPath = input.cpp.compilerPath; var cmd = new Command(compilerPath, args) cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; return [cmd]; } function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = assemblerFlags(project, product, input, output, explicitlyDependsOn); var assemblerPath = input.cpp.assemblerPath; var cmd = new Command(assemblerPath, args) cmd.description = "assembling " + input.fileName; cmd.highlight = "compiler"; return [cmd]; } function prepareLinker(project, product, inputs, outputs, input, output) { var primaryOutput = outputs.application[0]; var args = linkerFlags(project, product, input, outputs); var linkerPath = product.cpp.linkerPath; var cmd = new Command(linkerPath, args) cmd.description = "linking " + primaryOutput.fileName; cmd.highlight = "linker"; return [cmd]; } function prepareArchiver(project, product, inputs, outputs, input, output) { var args = archiverFlags(project, product, input, outputs); var archiverPath = product.cpp.archiverPath; var cmd = new Command(archiverPath, args) cmd.description = "linking " + output.fileName; cmd.highlight = "linker"; cmd.stdoutFilterFunction = function(output) { return ""; }; return [cmd]; } qbs-src-1.13.1/share/qbs/modules/cpp/iar.qbs000066400000000000000000000172161347155106100205640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.PathTools import qbs.Probes import qbs.Utilities import "iar.js" as IAR CppModule { condition: qbs.toolchain && qbs.toolchain.contains("iar") Probes.BinaryProbe { id: compilerPathProbe condition: !toolchainInstallPath && !_skipAllChecks names: ["iccarm"] } Probes.IarProbe { id: iarProbe condition: !_skipAllChecks compilerFilePath: compilerPath } qbs.architecture: iarProbe.found ? iarProbe.architecture : original compilerVersionMajor: iarProbe.versionMajor compilerVersionMinor: iarProbe.versionMinor compilerVersionPatch: iarProbe.versionPatch endianness: iarProbe.endianness compilerDefinesByLanguage: [] property string toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined property string compilerExtension: qbs.hostOS.contains("windows") ? ".exe" : "" property bool generateMapFile: true PropertyOptions { name: "generateMapFile" description: "produce a linker list file (enabled by default)" } /* Work-around for QtCreator which expects these properties to exist. */ property string cCompilerName: compilerName property string cxxCompilerName: compilerName compilerName: { switch (qbs.architecture) { case "arm": return "iccarm" + compilerExtension; case "mcs51": return "icc8051" + compilerExtension; case "avr": return "iccavr" + compilerExtension; } } compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) assemblerName: { switch (qbs.architecture) { case "arm": return "iasmarm" + compilerExtension; case "mcs51": return "a8051" + compilerExtension; case "avr": return "aavr" + compilerExtension; } } assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName) linkerName: { switch (qbs.architecture) { case "arm": return "ilinkarm" + compilerExtension; case "mcs51": return "xlink" + compilerExtension; case "avr": return "xlink" + compilerExtension; } } linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) property string archiverName: { switch (qbs.architecture) { case "arm": return "iarchive" + compilerExtension; case "mcs51": return "xlib" + compilerExtension; case "avr": return "xlib" + compilerExtension; } } property string archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName) runtimeLibrary: "static" staticLibrarySuffix: { switch (qbs.architecture) { case "arm": return ".a"; case "mcs51": return ".r51"; case "avr": return ".r90"; } } executableSuffix: { switch (qbs.architecture) { case "arm": return ".out"; case "mcs51": return qbs.debugInformation ? ".d51" : ".a51"; case "avr": return qbs.debugInformation ? ".d90" : ".a90"; } } property string objectSuffix: { switch (qbs.architecture) { case "arm": return ".o"; case "mcs51": return ".r51"; case "avr": return ".r90"; } } imageFormat: { switch (qbs.architecture) { case "arm": return "elf"; case "mcs51": return "ubrof"; case "avr": return "ubrof"; } } enableExceptions: false enableRtti: false Rule { id: assembler inputs: ["asm"] Artifact { fileTags: ["obj"] filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + input.cpp.objectSuffix } prepare: IAR.prepareAssembler.apply(IAR, arguments); } FileTagger { condition: qbs.architecture === "arm"; patterns: "*.s" fileTags: ["asm"] } FileTagger { condition: qbs.architecture === "mcs51"; patterns: ["*.s51", "*.asm"] fileTags: ["asm"] } Rule { id: compiler inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] Artifact { fileTags: ["obj"] filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + input.cpp.objectSuffix } prepare: IAR.prepareCompiler.apply(IAR, arguments); } Rule { id: applicationLinker multiplex: true inputs: ["obj", "linkerscript"] inputsFromDependencies: ["staticlibrary"] outputFileTags: { var tags = ["application"]; if (product.moduleProperty("cpp", "generateMapFile")) tags.push("map_file"); return tags; } outputArtifacts: { var app = { fileTags: ["application"], filePath: FileInfo.joinPaths( product.destinationDirectory, PathTools.applicationFilePath(product)) }; var artifacts = [app]; if (product.cpp.generateMapFile) { artifacts.push({ fileTags: ["map_file"], filePath: FileInfo.joinPaths( product.destinationDirectory, product.targetName + ".map") }); } return artifacts; } prepare:IAR.prepareLinker.apply(IAR, arguments); } Rule { id: staticLibraryLinker multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary"] Artifact { fileTags: ["staticlibrary"] filePath: FileInfo.joinPaths( product.destinationDirectory, PathTools.staticLibraryFilePath(product)) } prepare: IAR.prepareArchiver.apply(IAR, arguments); } } qbs-src-1.13.1/share/qbs/modules/cpp/ios-gcc.qbs000066400000000000000000000066001347155106100213300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.DarwinTools import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Utilities DarwinGCC { priority: 1 condition: qbs.targetOS.contains('ios') && qbs.toolchain && qbs.toolchain.contains('gcc') targetSystem: "ios" + (minimumIosVersion || "") minimumDarwinVersion: minimumIosVersion minimumDarwinVersionCompilerFlag: qbs.targetOS.contains("ios-simulator") ? "-mios-simulator-version-min" : "-miphoneos-version-min" minimumDarwinVersionLinkerFlag: qbs.targetOS.contains("ios-simulator") ? "-ios_simulator_version_min" : "-iphoneos_version_min" libcxxAvailable: base && minimumDarwinVersion && Utilities.versionCompare(minimumDarwinVersion, "5") >= 0 platformObjcFlags: base.concat(simulatorObjcFlags) platformObjcxxFlags: base.concat(simulatorObjcFlags) // Private properties readonly property stringList simulatorObjcFlags: { // default in Xcode and also required for building 32-bit Simulator binaries with ARC // since the default ABI version is 0 for 32-bit targets return qbs.targetOS.contains("ios-simulator") ? ["-fobjc-abi-version=2", "-fobjc-legacy-dispatch"] : []; } Rule { condition: !product.qbs.targetOS.contains("ios-simulator") inputsFromDependencies: ["bundle.content"] Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".ipa") fileTags: ["ipa"] } prepare: { var cmd = new Command("PackageApplication", [input.filePath, "-o", output.filePath]); cmd.description = "creating ipa"; cmd.highlight = "codegen"; return cmd; } } } qbs-src-1.13.1/share/qbs/modules/cpp/keil.js000066400000000000000000000475171347155106100205730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Cpp = require("cpp.js"); var Environment = require("qbs.Environment"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); var TemporaryDir = require("qbs.TemporaryDir"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); var WindowsUtils = require("qbs.WindowsUtils"); function guessArchitecture(macros) { if (macros["__C51__"]) return "mcs51"; else if (macros["__CC_ARM"] === 1) return "arm"; } function guessEndianness(macros) { if (macros["__C51__"]) { // The 8051 processors are 8-bit. So, the data with an integer type // represented by more than one byte is stored as big endian in the // Keil toolchain. See for more info: // * http://www.keil.com/support/man/docs/c51/c51_ap_2bytescalar.htm // * http://www.keil.com/support/man/docs/c51/c51_ap_4bytescalar.htm return "big"; } else if (macros["__ARMCC_VERSION"]) { return macros["__BIG_ENDIAN"] ? "big" : "little"; } } function guessVersion(macros) { if (macros["__C51__"]) { var version = macros["__C51__"]; return { major: parseInt(version / 100), minor: parseInt(version % 100), patch: 0, found: true } } else if (macros["__CC_ARM"]) { var version = macros["__ARMCC_VERSION"]; return { major: parseInt(version / 1000000), minor: parseInt(version / 10000) % 100, patch: parseInt(version) % 10000, found: true } } } // Note: The KEIL 8051 compiler does not support the predefined // macros dumping. So, we do it with following trick where we try // to compile a temporary file and to parse the console output. function dumpC51CompilerMacros(compilerFilePath, qbs) { function createDumpMacrosFile() { var td = new TemporaryDir(); var fn = FileInfo.fromNativeSeparators(td.path() + "/dump-macros.c"); var tf = new TextFile(fn, TextFile.WriteOnly); tf.writeLine("#define VALUE_TO_STRING(x) #x"); tf.writeLine("#define VALUE(x) VALUE_TO_STRING(x)"); tf.writeLine("#define VAR_NAME_VALUE(var) \"\"\"|\"#var\"|\"VALUE(var)"); tf.writeLine("#ifdef __C51__"); tf.writeLine("#pragma message(VAR_NAME_VALUE(__C51__))"); tf.writeLine("#endif"); tf.close(); return fn; } var fn = createDumpMacrosFile(); var p = new Process(); p.exec(compilerFilePath, [ fn ], false); var map = {}; p.readStdOut().trim().split(/\r?\n/g).map(function(line) { var parts = line.split("\"|\"", 3); map[parts[1]] = parts[2]; }); return map; } function dumpArmCompilerMacros(compilerFilePath, qbs, nullDevice) { var p = new Process(); p.exec(compilerFilePath, [ "-E", "--list-macros", nullDevice ], false); var map = {}; p.readStdOut().trim().split(/\r?\n/g).map(function (line) { if (!line.startsWith("#define")) return; var parts = line.split(" ", 3); map[parts[1]] = parts[2]; }); return map; } function dumpMacros(compilerFilePath, qbs, nullDevice) { var map1 = dumpC51CompilerMacros(compilerFilePath, qbs); var map2 = dumpArmCompilerMacros(compilerFilePath, qbs, nullDevice); var map = {}; for (var attrname in map1) map[attrname] = map1[attrname]; for (var attrname in map2) map[attrname] = map2[attrname]; return map; } function adjustPathsToWindowsSeparators(sourcePaths) { var resulingPaths = []; sourcePaths.forEach(function(path) { resulingPaths.push(FileInfo.toWindowsSeparators(path)); }); return resulingPaths; } function getMaxExitCode(architecture) { if (architecture === "mcs51") return 1; else if (architecture === "arm") return 0; } function collectLibraryDependencies(product) { var seen = {}; var result = []; function addFilePath(filePath) { result.push({ filePath: filePath }); } function addArtifactFilePaths(dep, artifacts) { if (!artifacts) return; var artifactFilePaths = artifacts.map(function(a) { return a.filePath; }); artifactFilePaths.forEach(addFilePath); } function addExternalStaticLibs(obj) { if (!obj.cpp) return; function ensureArray(a) { return Array.isArray(a) ? a : []; } function sanitizedModuleListProperty(obj, moduleName, propertyName) { return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName)); } var externalLibs = [].concat( sanitizedModuleListProperty(obj, "cpp", "staticLibraries")); var staticLibrarySuffix = obj.moduleProperty("cpp", "staticLibrarySuffix"); externalLibs.forEach(function(staticLibraryName) { if (!staticLibraryName.endsWith(staticLibrarySuffix)) staticLibraryName += staticLibrarySuffix; addFilePath(staticLibraryName); }); } function traverse(dep) { if (seen.hasOwnProperty(dep.name)) return; seen[dep.name] = true; if (dep.parameters.cpp && dep.parameters.cpp.link === false) return; var staticLibraryArtifacts = dep.artifacts["staticlibrary"]; if (staticLibraryArtifacts) { dep.dependencies.forEach(traverse); addArtifactFilePaths(dep, staticLibraryArtifacts); addExternalStaticLibs(dep); } } product.dependencies.forEach(traverse); addExternalStaticLibs(product); return result; } function filterStdOutput(cmd) { cmd.stdoutFilterFunction = function(output) { var sourceLines = output.split("\n"); var filteredLines = []; for (var i in sourceLines) { if (sourceLines[i].startsWith("***") || sourceLines[i].startsWith(">>") || sourceLines[i].startsWith(" ") || sourceLines[i].startsWith("Program Size:") || sourceLines[i].startsWith("A51 FATAL") || sourceLines[i].startsWith("C51 FATAL") || sourceLines[i].startsWith("ASSEMBLER INVOKED BY") || sourceLines[i].startsWith("LOC OBJ LINE SOURCE") ) { filteredLines.push(sourceLines[i]); } } return filteredLines.join("\n"); }; } function compilerFlags(project, product, input, output, explicitlyDependsOn) { // Determine which C-language we"re compiling. var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags)); var architecture = input.qbs.architecture; var args = []; var allDefines = []; var platformDefines = input.cpp.platformDefines; if (platformDefines) allDefines = allDefines.uniqueConcat(platformDefines); var defines = input.cpp.defines; if (defines) allDefines = allDefines.uniqueConcat(defines); var allIncludePaths = []; var includePaths = input.cpp.includePaths; if (includePaths) allIncludePaths = allIncludePaths.uniqueConcat(includePaths); var systemIncludePaths = input.cpp.systemIncludePaths; if (systemIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths); var compilerIncludePaths = input.cpp.compilerIncludePaths; if (compilerIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths); if (architecture === "mcs51") { args.push(FileInfo.toWindowsSeparators(input.filePath)); args.push("OBJECT (" + FileInfo.toWindowsSeparators(output.filePath) + ")"); switch (input.cpp.optimization) { case "small": args.push("OPTIMIZE (SIZE)"); break; case "fast": args.push("OPTIMIZE (SPEED)"); break; case "none": args.push("OPTIMIZE (0)"); break; } if (input.cpp.debugInformation) args.push("DEBUG"); var warnings = input.cpp.warningLevel; if (warnings === "none") { args.push("WARNINGLEVEL (0)"); } else if (warnings === "all") { args.push("WARNINGLEVEL (2)"); args.push("FARWARNING"); } if (allDefines.length > 0) args = args.concat("DEFINE (" + allDefines.join(",") + ")"); if (allIncludePaths.length > 0) { var adjusted = adjustPathsToWindowsSeparators(allIncludePaths); args = args.concat("INCDIR (" + adjusted.join(";") + ")"); } } else if (architecture === "arm") { args.push("-c", input.filePath); args.push("-o", output.filePath); switch (input.cpp.optimization) { case "small": args.push("-Ospace") break; case "fast": args.push("-Otime") break; case "none": args.push("-O0") break; } if (input.cpp.debugInformation) { args.push("--debug"); args.push("-g"); } var warnings = input.cpp.warningLevel; if (warnings === "none") { args.push("-W"); } else if (warnings === "all") { // By default all warnings are enabled. } if (tag === "c") { // Note: Here we use the '==' operator because the '===' // operator does not work! if (input.cpp.cLanguageVersion == "c99") args.push("--c99"); } else if (tag === "cpp") { args.push("--cpp"); // Note: Here we use the '==' operator because the '===' // operator does not work! if (input.cpp.cxxLanguageVersion == "c++11") args.push("--cpp11"); var enableExceptions = input.cpp.enableExceptions; if (enableExceptions !== undefined) args.push(enableExceptions ? "--exceptions" : "--no_exceptions"); var enableRtti = input.cpp.enableRtti; if (enableRtti !== undefined) args.push(enableRtti ? "--rtti" : "--no_rtti"); } args = args.concat(allDefines.map(function(define) { return '-D' + define })); args = args.concat(allIncludePaths.map(function(include) { return '-I' + include })); } args = args.concat(ModUtils.moduleProperty(input, "platformFlags"), ModUtils.moduleProperty(input, "flags"), ModUtils.moduleProperty(input, "platformFlags", tag), ModUtils.moduleProperty(input, "flags", tag), ModUtils.moduleProperty(input, "driverFlags", tag)); return args; } function assemblerFlags(project, product, input, output, explicitlyDependsOn) { // Determine which C-language we"re compiling var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags)); var architecture = input.qbs.architecture; var args = []; var allDefines = []; var platformDefines = input.cpp.platformDefines; if (platformDefines) allDefines = allDefines.uniqueConcat(platformDefines); var defines = input.cpp.defines; if (defines) allDefines = allDefines.uniqueConcat(defines); var allIncludePaths = []; var includePaths = input.cpp.includePaths; if (includePaths) allIncludePaths = allIncludePaths.uniqueConcat(includePaths); var systemIncludePaths = input.cpp.systemIncludePaths; if (systemIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths); var compilerIncludePaths = input.cpp.compilerIncludePaths; if (compilerIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths); if (architecture === "mcs51") { args.push(FileInfo.toWindowsSeparators(input.filePath)); args.push("OBJECT (" + FileInfo.toWindowsSeparators(output.filePath) + ")"); if (input.cpp.debugInformation) args.push("DEBUG"); if (allDefines.length > 0) args = args.concat("DEFINE (" + allDefines.join(",") + ")"); if (allIncludePaths.length > 0) { var adjusted = adjustPathsToWindowsSeparators(allIncludePaths); args = args.concat("INCDIR (" + adjusted.join(";") + ")"); } } else if (architecture === "arm") { args.push(input.filePath); args.push("-o", output.filePath); if (input.cpp.debugInformation) { args.push("--debug"); args.push("-g"); } var warnings = input.cpp.warningLevel; if (warnings === "none") args.push("--no_warn"); var endianness = input.cpp.endianness; if (endianness) args.push((endianness === "little") ? "--littleend" : "--bigend"); allDefines.forEach(function(define) { var parts = define.split("="); args.push("--pd"); if (parts[1] === undefined) args.push(parts[0] + " SETA " + 1); else if (parts[1].contains("\"")) args.push(parts[0] + " SETS " + parts[1]); else args.push(parts[0] + " SETA " + parts[1]); }); args = args.concat(allIncludePaths.map(function(include) { return '-I' + include })); } args = args.concat(ModUtils.moduleProperty(input, "platformFlags", tag), ModUtils.moduleProperty(input, "flags", tag), ModUtils.moduleProperty(input, "driverFlags", tag)); return args; } function linkerFlags(project, product, input, outputs) { var args = []; var architecture = product.qbs.architecture; if (architecture === "mcs51") { var allObjectPaths = []; function addObjectPath(obj) { allObjectPaths.push(obj.filePath); } if (inputs.obj) inputs.obj.map(function(obj) { addObjectPath(obj) }); var libraryDependencies = collectLibraryDependencies(product); libraryDependencies.forEach(function(dep) { addObjectPath(dep); }) var adjusted = adjustPathsToWindowsSeparators(allObjectPaths); args = args.concat(adjusted.join(",")); // We need to wrap an output file name with quotes. Otherwise // the linker will ignore a specified file name. args.push("TO", '"' + FileInfo.toWindowsSeparators(outputs.application[0].filePath) + '"'); if (!product.cpp.generateMapFile) args.push("NOMAP"); } else if (architecture === "arm") { if (inputs.obj) args = args.concat(inputs.obj.map(function(obj) { return obj.filePath })); args.push("--output", outputs.application[0].filePath); if (product.cpp.generateMapFile) args.push("--list", outputs.map_file[0].filePath); var libraryPaths = product.cpp.libraryPaths; if (libraryPaths) args.push("--userlibpath=" + libraryPaths.join(",")); var libraryDependencies = collectLibraryDependencies(product); args = args.concat(libraryDependencies.map(function(dep) { return dep.filePath; })); var linkerScripts = inputs.linkerscript ? inputs.linkerscript.map(function(a) { return a.filePath; }) : []; for (i in linkerScripts) args.push("--scatter", linkerScripts[i]); if (product.cpp.entryPoint) args.push("--entry", product.cpp.entryPoint); var debugInformation = product.cpp.debugInformation; if (debugInformation !== undefined) args.push(debugInformation ? "--debug" : "--no_debug"); } args = args.concat(ModUtils.moduleProperty(product, "driverLinkerFlags")); return args; } function archiverFlags(project, product, input, outputs) { var args = []; var architecture = product.qbs.architecture; if (architecture === "mcs51") { args.push("TRANSFER"); var allObjectPaths = []; function addObjectPath(obj) { allObjectPaths.push(obj.filePath); } if (inputs.obj) inputs.obj.map(function(obj) { addObjectPath(obj) }); var adjusted = adjustPathsToWindowsSeparators(allObjectPaths); args = args.concat(adjusted.join(",")); // We need to wrap a output file name with quotes. Otherwise // the linker will ignore a specified file name. args.push("TO", '"' + FileInfo.toWindowsSeparators(outputs.staticlibrary[0].filePath) + '"'); } else if (architecture === "arm") { args.push("--create", outputs.staticlibrary[0].filePath); if (inputs.obj) args = args.concat(inputs.obj.map(function(obj) { return obj.filePath })); if (product.cpp.debugInformation) args.push("--debug_symbols"); } return args; } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = compilerFlags(project, product, input, output, explicitlyDependsOn); var compilerPath = input.cpp.compilerPath; var architecture = input.cpp.architecture; var cmd = new Command(compilerPath, args) cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.maxExitCode = getMaxExitCode(architecture); filterStdOutput(cmd); return [cmd]; } function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = assemblerFlags(project, product, input, output, explicitlyDependsOn); var assemblerPath = input.cpp.assemblerPath; var cmd = new Command(assemblerPath, args) cmd.description = "assembling " + input.fileName; cmd.highlight = "compiler"; filterStdOutput(cmd); return [cmd]; } function prepareLinker(project, product, inputs, outputs, input, output) { var primaryOutput = outputs.application[0]; var args = linkerFlags(project, product, input, outputs); var linkerPath = product.cpp.linkerPath; var cmd = new Command(linkerPath, args) cmd.description = "linking " + primaryOutput.fileName; cmd.highlight = "linker"; filterStdOutput(cmd); return [cmd]; } function prepareArchiver(project, product, inputs, outputs, input, output) { var args = archiverFlags(project, product, input, outputs); var archiverPath = product.cpp.archiverPath; var cmd = new Command(archiverPath, args) cmd.description = "linking " + output.fileName; cmd.highlight = "linker"; filterStdOutput(cmd); return [cmd]; } qbs-src-1.13.1/share/qbs/modules/cpp/keil.qbs000066400000000000000000000163611347155106100207350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 Denis Shienkov ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.PathTools import qbs.Probes import qbs.Utilities import "keil.js" as KEIL CppModule { condition: qbs.hostOS.contains("windows") && qbs.toolchain && qbs.toolchain.contains("keil") Probes.BinaryProbe { id: compilerPathProbe condition: !toolchainInstallPath && !_skipAllChecks names: ["c51"] } Probes.KeilProbe { id: keilProbe condition: !_skipAllChecks compilerFilePath: compilerPath } qbs.architecture: keilProbe.found ? keilProbe.architecture : original compilerVersionMajor: keilProbe.versionMajor compilerVersionMinor: keilProbe.versionMinor compilerVersionPatch: keilProbe.versionPatch endianness: keilProbe.endianness compilerDefinesByLanguage: [] property string toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined property string compilerExtension: qbs.hostOS.contains("windows") ? ".exe" : "" property bool generateMapFile: true PropertyOptions { name: "generateMapFile" description: "produce a linker list file (enabled by default)" } /* Work-around for QtCreator which expects these properties to exist. */ property string cCompilerName: compilerName property string cxxCompilerName: compilerName compilerName: { switch (qbs.architecture) { case "mcs51": return "c51" + compilerExtension; case "arm": return "armcc" + compilerExtension; } } compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) assemblerName: { switch (qbs.architecture) { case "mcs51": return "a51" + compilerExtension; case "arm": return "armasm" + compilerExtension; } } assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName) linkerName: { switch (qbs.architecture) { case "mcs51": return "bl51" + compilerExtension; case "arm": return "armlink" + compilerExtension; } } linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) property string archiverName: { switch (qbs.architecture) { case "mcs51": return "lib51" + compilerExtension; case "arm": return "armar" + compilerExtension; } } property string archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName) runtimeLibrary: "static" staticLibrarySuffix: { switch (qbs.architecture) { case "mcs51": return ".lib"; case "arm": return ".lib"; } } executableSuffix: { switch (qbs.architecture) { case "mcs51": return ".abs"; case "arm": return ".axf"; } } property string objectSuffix: { switch (qbs.architecture) { case "mcs51": return ".obj"; case "arm": return ".o"; } } imageFormat: { switch (qbs.architecture) { case "mcs51": // Keil OMF51 or OMF2 Object Module Format (which is an // extension of the original Intel OMF51). return "omf"; case "arm": return "elf"; } } enableExceptions: false enableRtti: false Rule { id: assembler inputs: ["asm"] Artifact { fileTags: ["obj"] filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + input.cpp.objectSuffix } prepare: KEIL.prepareAssembler.apply(KEIL, arguments); } FileTagger { condition: qbs.architecture === "mcs51"; patterns: ["*.a51", "*.A51"] fileTags: ["asm"] } FileTagger { condition: qbs.architecture === "arm"; patterns: "*.s" fileTags: ["asm"] } Rule { id: compiler inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] Artifact { fileTags: ["obj"] filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + input.cpp.objectSuffix } prepare: KEIL.prepareCompiler.apply(KEIL, arguments); } Rule { id: applicationLinker multiplex: true inputs: ["obj", "linkerscript"] outputFileTags: { var tags = ["application"]; if (product.moduleProperty("cpp", "generateMapFile")) tags.push("map_file"); return tags; } outputArtifacts: { var app = { fileTags: ["application"], filePath: FileInfo.joinPaths( product.destinationDirectory, PathTools.applicationFilePath(product)) }; var artifacts = [app]; if (product.cpp.generateMapFile) { artifacts.push({ fileTags: ["map_file"], filePath: FileInfo.joinPaths( product.destinationDirectory, product.targetName + ".map") }); } return artifacts; } prepare:KEIL.prepareLinker.apply(KEIL, arguments); } Rule { id: staticLibraryLinker multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary"] Artifact { fileTags: ["staticlibrary"] filePath: FileInfo.joinPaths( product.destinationDirectory, PathTools.staticLibraryFilePath(product)) } prepare: KEIL.prepareArchiver.apply(KEIL, arguments); } } qbs-src-1.13.1/share/qbs/modules/cpp/macos-gcc.qbs000066400000000000000000000040321347155106100216350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.ModUtils import qbs.Utilities DarwinGCC { priority: 1 condition: qbs.targetOS.contains('macos') && qbs.toolchain && qbs.toolchain.contains('gcc') targetSystem: "macosx" + (minimumMacosVersion || "") minimumDarwinVersion: minimumMacosVersion minimumDarwinVersionCompilerFlag: "-mmacosx-version-min" minimumDarwinVersionLinkerFlag: "-macosx_version_min" libcxxAvailable: base && minimumDarwinVersion && Utilities.versionCompare(minimumDarwinVersion, "10.7") >= 0 } qbs-src-1.13.1/share/qbs/modules/cpp/msvc.js000066400000000000000000000475361347155106100206200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Cpp = require("cpp.js"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Utilities = require("qbs.Utilities"); var WindowsUtils = require("qbs.WindowsUtils"); function handleCpuFeatures(input, flags) { if (!input.qbs.architecture) return; if (input.qbs.architecture.startsWith("x86")) { if (input.qbs.architecture === "x86") { var sse2 = input.cpufeatures.x86_sse2; if (sse2 === true) flags.push("/arch:SSE2"); if (sse2 === false) flags.push("/arch:IA32"); } if (input.cpufeatures.x86_avx === true) flags.push("/arch:AVX"); if (input.cpufeatures.x86_avx2 === true) flags.push("/arch:AVX2"); } else if (input.qbs.architecture.startsWith("arm")) { if (input.cpufeatures.arm_vfpv4 === true) flags.push("/arch:VFPv4"); if (input.cpp.machineType === "armv7ve") flags.push("/arch:ARMv7VE"); } } function hasCxx17Option(input) { // Probably this is not the earliest version to support the flag, but we have tested this one // and it's a pain to find out the exact minimum. return Utilities.versionCompare(input.cpp.compilerVersion, "19.12.25831") >= 0; } function addLanguageVersionFlag(input, args) { var cxxVersion = Cpp.languageVersion(input.cpp.cxxLanguageVersion, ["c++17", "c++14", "c++11", "c++98"], "C++"); if (!cxxVersion) return; // Visual C++ 2013, Update 3 var hasStdOption = Utilities.versionCompare(input.cpp.compilerVersion, "18.00.30723") >= 0; if (!hasStdOption) return; var flag; if (cxxVersion === "c++14") flag = "/std:c++14"; else if (cxxVersion === "c++17" && hasCxx17Option(input)) flag = "/std:c++17"; else if (cxxVersion !== "c++11" && cxxVersion !== "c++98") flag = "/std:c++latest"; if (flag) args.push(flag); } function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var i; var debugInformation = input.cpp.debugInformation; var args = ['/nologo', '/c'] handleCpuFeatures(input, args); // Determine which C-language we're compiling var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(Object.keys(outputs))); if (!["c", "cpp"].contains(tag)) throw ("unsupported source language"); var enableExceptions = input.cpp.enableExceptions; if (enableExceptions) { var ehModel = input.cpp.exceptionHandlingModel; switch (ehModel) { case "default": args.push("/EHsc"); // "Yes" in VS break; case "seh": args.push("/EHa"); // "Yes with SEH exceptions" in VS break; case "externc": args.push("/EHs"); // "Yes with Extern C functions" in VS break; } } var enableRtti = input.cpp.enableRtti; if (enableRtti !== undefined) { args.push(enableRtti ? "/GR" : "/GR-"); } switch (input.cpp.optimization) { case "small": args.push('/Os') break; case "fast": args.push('/O2') break; case "none": args.push("/Od"); break; } if (debugInformation) { if (product.cpp.separateDebugInformation) args.push('/Zi'); else args.push('/Z7'); } var rtl = product.cpp.runtimeLibrary; if (rtl) { rtl = (rtl === "static" ? "/MT" : "/MD"); if (product.qbs.enableDebugCode) rtl += "d"; args.push(rtl); } // warnings: var warningLevel = input.cpp.warningLevel; if (warningLevel === 'none') args.push('/w') if (warningLevel === 'all') args.push('/Wall') if (input.cpp.treatWarningsAsErrors) args.push('/WX') var allIncludePaths = []; var includePaths = input.cpp.includePaths; if (includePaths) allIncludePaths = allIncludePaths.uniqueConcat(includePaths); var systemIncludePaths = input.cpp.systemIncludePaths; if (systemIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths); for (i in allIncludePaths) args.push('/I' + FileInfo.toWindowsSeparators(allIncludePaths[i])) var allDefines = []; var platformDefines = input.cpp.platformDefines; if (platformDefines) allDefines = allDefines.uniqueConcat(platformDefines); var defines = input.cpp.defines; if (defines) allDefines = allDefines.uniqueConcat(defines); for (i in allDefines) args.push('/D' + allDefines[i].replace(/%/g, "%%")); var minimumWindowsVersion = product.cpp.minimumWindowsVersion; if (minimumWindowsVersion) { var hexVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'hex'); if (hexVersion) { var versionDefs = [ 'WINVER', '_WIN32_WINNT', '_WIN32_WINDOWS' ]; for (i in versionDefs) { args.push('/D' + versionDefs[i] + '=' + hexVersion); } } } if (product.cpp.debugInformation && product.cpp.separateDebugInformation) args.push("/Fd" + product.targetName + ".cl" + product.cpp.debugInfoSuffix); var objectMap = outputs.obj || outputs.intermediate_obj var objOutput = objectMap ? objectMap[0] : undefined args.push('/Fo' + FileInfo.toWindowsSeparators(objOutput.filePath)) args.push(FileInfo.toWindowsSeparators(input.filePath)) var prefixHeaders = product.cpp.prefixHeaders; for (i in prefixHeaders) args.push("/FI" + FileInfo.toWindowsSeparators(prefixHeaders[i])); // Language if (tag === "cpp") { args.push("/TP"); addLanguageVersionFlag(input, args); } else if (tag === "c") { args.push("/TC"); } // Whether we're compiling a precompiled header or normal source file var pchOutput = outputs[tag + "_pch"] ? outputs[tag + "_pch"][0] : undefined; var pchInputs = explicitlyDependsOn[tag + "_pch"]; if (pchOutput) { // create PCH args.push("/Yc"); args.push("/Fp" + FileInfo.toWindowsSeparators(pchOutput.filePath)); args.push("/Fo" + FileInfo.toWindowsSeparators(objOutput.filePath)); args.push(FileInfo.toWindowsSeparators(input.filePath)); } else if (pchInputs && pchInputs.length === 1 && ModUtils.moduleProperty(input, "usePrecompiledHeader", tag)) { // use PCH var pchSourceArtifacts = product.artifacts[tag + "_pch_src"]; if (pchSourceArtifacts && pchSourceArtifacts.length > 0) { var pchSourceFilePath = pchSourceArtifacts[0].filePath; var pchFilePath = FileInfo.toWindowsSeparators(pchInputs[0].filePath); args.push("/FI" + pchSourceFilePath); args.push("/Yu" + pchSourceFilePath); args.push("/Fp" + pchFilePath); } else { console.warning("products." + product.name + ".usePrecompiledHeader is true, " + "but there is no " + tag + "_pch_src artifact."); } } args = args.concat(ModUtils.moduleProperty(input, 'platformFlags'), ModUtils.moduleProperty(input, 'flags'), ModUtils.moduleProperty(input, 'platformFlags', tag), ModUtils.moduleProperty(input, 'flags', tag)); var compilerPath = product.cpp.compilerPath; var wrapperArgs = product.cpp.compilerWrapper; if (wrapperArgs && wrapperArgs.length > 0) { args.unshift(compilerPath); compilerPath = wrapperArgs.shift(); args = wrapperArgs.concat(args); } var cmd = new Command(compilerPath, args) cmd.description = (pchOutput ? 'pre' : '') + 'compiling ' + input.fileName; if (pchOutput) cmd.description += ' (' + tag + ')'; cmd.highlight = "compiler"; cmd.jobPool = "compiler"; cmd.workingDirectory = product.buildDirectory; cmd.responseFileUsagePrefix = '@'; // cl.exe outputs the cpp file name. We filter that out. cmd.inputFileName = input.fileName; cmd.relevantEnvironmentVariables = ["CL", "_CL_", "INCLUDE"]; cmd.stdoutFilterFunction = function(output) { return output.split(inputFileName + "\r\n").join(""); }; return [cmd]; } function collectLibraryDependencies(product) { var seen = {}; var result = []; function addFilePath(filePath, wholeArchive, productName) { result.push({ filePath: filePath, wholeArchive: wholeArchive, productName: productName }); } function addArtifactFilePaths(dep, artifacts) { if (!artifacts) return; var artifactFilePaths = artifacts.map(function(a) { return a.filePath; }); var wholeArchive = dep.parameters.cpp && dep.parameters.cpp.linkWholeArchive; var artifactsAreImportLibs = artifacts.length > 0 && artifacts[0].fileTags.contains("dynamiclibrary_import"); for (var i = 0; i < artifactFilePaths.length; ++i) { addFilePath(artifactFilePaths[i], wholeArchive, artifactsAreImportLibs ? dep.name : undefined); } } function addExternalLibs(obj) { if (!obj.cpp) return; function ensureArray(a) { return Array.isArray(a) ? a : []; } function sanitizedModuleListProperty(obj, moduleName, propertyName) { return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName)); } var externalLibs = [].concat( sanitizedModuleListProperty(obj, "cpp", "staticLibraries"), sanitizedModuleListProperty(obj, "cpp", "dynamicLibraries")); externalLibs.forEach(function (libName) { if (!libName.match(/\.lib$/i) && !libName.startsWith('@')) libName += ".lib"; addFilePath(libName, false); }); } function traverse(dep) { if (seen.hasOwnProperty(dep.name)) return; seen[dep.name] = true; if (dep.parameters.cpp && dep.parameters.cpp.link === false) return; var staticLibraryArtifacts = dep.artifacts["staticlibrary"]; var dynamicLibraryArtifacts = staticLibraryArtifacts ? null : dep.artifacts["dynamiclibrary_import"]; if (staticLibraryArtifacts) { dep.dependencies.forEach(traverse); addArtifactFilePaths(dep, staticLibraryArtifacts); addExternalLibs(dep); } else if (dynamicLibraryArtifacts) { addArtifactFilePaths(dep, dynamicLibraryArtifacts); } } product.dependencies.forEach(traverse); addExternalLibs(product); return result; } function linkerSupportsWholeArchive(product) { return Utilities.versionCompare(product.cpp.compilerVersion, "19.0.24215.1") >= 0 } function handleDiscardProperty(product, flags) { var discardUnusedData = product.cpp.discardUnusedData; if (discardUnusedData === true) flags.push("/OPT:REF"); else if (discardUnusedData === false) flags.push("/OPT:NOREF"); } function prepareLinker(project, product, inputs, outputs, input, output) { var i; var linkDLL = (outputs.dynamiclibrary ? true : false) var primaryOutput = (linkDLL ? outputs.dynamiclibrary[0] : outputs.application[0]) var debugInformation = product.cpp.debugInformation; var additionalManifestInputs = Array.prototype.map.call(inputs["native.pe.manifest"], function (a) { return a.filePath; }); var generateManifestFiles = !linkDLL && product.cpp.generateManifestFile; var canEmbedManifest = (product.cpp.compilerVersionMajor >= 17); // VS 2012 var args = ['/nologo'] if (linkDLL) { args.push('/DLL'); args.push('/IMPLIB:' + FileInfo.toWindowsSeparators(outputs.dynamiclibrary_import[0].filePath)); } if (debugInformation) { args.push("/DEBUG"); var debugInfo = outputs.debuginfo_app || outputs.debuginfo_dll; if (debugInfo) args.push("/PDB:" + debugInfo[0].fileName); } else { args.push('/INCREMENTAL:NO') } switch (product.qbs.architecture) { case "x86": args.push("/MACHINE:X86"); break; case "x86_64": args.push("/MACHINE:X64"); break; case "ia64": args.push("/MACHINE:IA64"); break; case "armv7": args.push("/MACHINE:ARM"); break; case "arm64": args.push("/MACHINE:ARM64"); break; } var requireAppContainer = product.cpp.requireAppContainer; if (requireAppContainer !== undefined) args.push("/APPCONTAINER" + (requireAppContainer ? "" : ":NO")); var minimumWindowsVersion = product.cpp.minimumWindowsVersion; var subsystemSwitch = undefined; if (minimumWindowsVersion || product.consoleApplication !== undefined) { // Ensure that we default to console if product.consoleApplication is undefined // since that could still be the case if only minimumWindowsVersion had been defined subsystemSwitch = product.consoleApplication === false ? '/SUBSYSTEM:WINDOWS' : '/SUBSYSTEM:CONSOLE'; } if (minimumWindowsVersion) { var subsystemVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'subsystem'); if (subsystemVersion) { subsystemSwitch += ',' + subsystemVersion; args.push('/OSVERSION:' + subsystemVersion); } } if (subsystemSwitch) args.push(subsystemSwitch); var linkerOutputNativeFilePath = FileInfo.toWindowsSeparators(primaryOutput.filePath); var manifestFileNames = []; if (generateManifestFiles) { if (canEmbedManifest) { args.push("/MANIFEST:embed"); additionalManifestInputs.forEach(function (manifestFileName) { args.push("/MANIFESTINPUT:" + manifestFileName); }); } else { linkerOutputNativeFilePath = FileInfo.toWindowsSeparators( FileInfo.path(primaryOutput.filePath) + "/intermediate." + primaryOutput.fileName); var manifestFileName = linkerOutputNativeFilePath + ".manifest"; args.push('/MANIFEST', '/MANIFESTFILE:' + manifestFileName); manifestFileNames = [manifestFileName].concat(additionalManifestInputs); } } var allInputs = inputs.obj || []; for (i in allInputs) { var fileName = FileInfo.toWindowsSeparators(allInputs[i].filePath) args.push(fileName) } var wholeArchiveSupported = linkerSupportsWholeArchive(product); var wholeArchiveRequested = false; var libDeps = collectLibraryDependencies(product); for (i = 0; i < libDeps.length; ++i) { var dep = libDeps[i]; args.push((wholeArchiveSupported && dep.wholeArchive ? "/WHOLEARCHIVE:" : "") + FileInfo.toWindowsSeparators(dep.filePath)); if (dep.wholeArchive) wholeArchiveRequested = true; } if (wholeArchiveRequested && !wholeArchiveSupported) { console.warn("Product '" + product.name + "' sets cpp.linkWholeArchive on a dependency, " + "but your linker does not support the /WHOLEARCHIVE option. " + "Please upgrade to Visual Studio 2015 Update 2 or higher."); } if (product.cpp.entryPoint) args.push("/ENTRY:" + product.cpp.entryPoint); args.push('/OUT:' + linkerOutputNativeFilePath) var libraryPaths = product.cpp.libraryPaths; if (libraryPaths) libraryPaths = [].uniqueConcat(libraryPaths); for (i in libraryPaths) { args.push('/LIBPATH:' + FileInfo.toWindowsSeparators(libraryPaths[i])) } handleDiscardProperty(product, args); var linkerFlags = product.cpp.platformLinkerFlags.concat(product.cpp.linkerFlags); args = args.concat(linkerFlags); if (product.cpp.allowUnresolvedSymbols) args.push("/FORCE:UNRESOLVED"); var linkerPath = product.cpp.linkerPath; var wrapperArgs = product.cpp.linkerWrapper; if (wrapperArgs && wrapperArgs.length > 0) { args.unshift(linkerPath); linkerPath = wrapperArgs.shift(); args = wrapperArgs.concat(args); } var commands = []; var warningCmd = new JavaScriptCommand(); warningCmd.silent = true; warningCmd.libDeps = libDeps; warningCmd.sourceCode = function() { for (var i = 0; i < libDeps.length; ++i) { if (!libDeps[i].productName || File.exists(libDeps[i].filePath)) continue; console.warn("Import library '" + FileInfo.toNativeSeparators(libDeps[i].filePath) + "' does not exist. This typically happens when a DLL does not " + "export any symbols. Please make sure the '" + libDeps[i].productName + "' library exports symbols, or, if you do not intend to actually " + "link against it, specify \"cpp.link: false\" in the Depends item."); } }; commands.push(warningCmd); var cmd = new Command(linkerPath, args) cmd.description = 'linking ' + primaryOutput.fileName; cmd.highlight = 'linker'; cmd.jobPool = "linker"; cmd.relevantEnvironmentVariables = ["LINK", "_LINK_", "LIB", "TMP"]; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath) cmd.responseFileUsagePrefix = '@'; cmd.stdoutFilterFunction = function(output) { res = output.replace(/^.*performing full link.*\s*/, ""); return res.replace(/^ *Creating library.*\r\n$/, ""); }; commands.push(cmd); if (generateManifestFiles && !canEmbedManifest) { var outputNativeFilePath = FileInfo.toWindowsSeparators(primaryOutput.filePath); cmd = new JavaScriptCommand(); cmd.src = linkerOutputNativeFilePath; cmd.dst = outputNativeFilePath; cmd.sourceCode = function() { File.copy(src, dst); } cmd.silent = true commands.push(cmd); args = ['/nologo', '/manifest'].concat(manifestFileNames); args.push("/outputresource:" + outputNativeFilePath + ";#" + (linkDLL ? "2" : "1")); cmd = new Command("mt.exe", args) cmd.description = 'embedding manifest into ' + primaryOutput.fileName; cmd.highlight = 'linker'; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath) commands.push(cmd); } return commands; } qbs-src-1.13.1/share/qbs/modules/cpp/qnx-qcc.qbs000066400000000000000000000071011347155106100213530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo UnixGCC { Depends { name: "qnx" } condition: qbs.targetOS.contains("qnx") && qbs.toolchain && qbs.toolchain.contains("qcc") priority: 1 distributionIncludePaths: FileInfo.joinPaths(qnx.targetDir, "usr", "include") toolchainInstallPath: FileInfo.joinPaths(qnx.hostDir, "usr", "bin") sysroot: qnx.targetDir sysrootFlags: sysroot ? [systemIncludeFlag + FileInfo.joinPaths(sysroot, "usr", "include")] : [] cCompilerName: "qcc" + compilerExtension cxxCompilerName: (qnx.qnx7 ? "q++" : "QCC") + compilerExtension targetDriverFlags: qnxTarget ? ["-V" + qnxTarget] : [] systemIncludeFlag: !qnx.qnx7 ? includeFlag : base property string qnxTarget: qbs.architecture ? qnx.compilerName + "_" + targetSystem + qnxTargetArchName : undefined property string qnxTargetArchName: { switch (qbs.architecture) { case "arm64": return "aarch64le"; case "armv7a": return "armv7le"; case "x86": case "x86_64": return qbs.architecture; } } // QNX doesn't support Objective-C or Objective-C++ and qcc/q++ don't use toolchainPrefix compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) compilerPathByLanguage: ({ "c": FileInfo.joinPaths(toolchainInstallPath, cCompilerName), "cpp": FileInfo.joinPaths(toolchainInstallPath, cxxCompilerName), "objc": undefined, "objcpp": undefined, "asm_cpp": FileInfo.joinPaths(toolchainInstallPath, cCompilerName) }) toolchainPrefix: target + "-" targetVendor: ["x86", "x86_64"].contains(qbs.architecture) ? "pc" : base targetSystem: "nto" targetAbi: "qnx" + qnx.version + (qnxTargetArchName === "armv7le" ? "eabi" : "") buildEnv: qnx.buildEnv probeEnv: buildEnv setupBuildEnvironment: { for (var key in product.cpp.buildEnv) { v = new ModUtils.EnvironmentVariable(key); v.value = product.cpp.buildEnv[key]; v.set(); } } } qbs-src-1.13.1/share/qbs/modules/cpp/setuprunenv.js000066400000000000000000000136471347155106100222420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var File = require("qbs.File"); var ModUtils = require("qbs.ModUtils"); // TODO: append/prepend functionality should go to qbs.Environment function addNewElement(list, elem) { if (!list.contains(elem)) list.push(elem); } function artifactDir(artifact) { if (!artifact.qbs.install) return FileInfo.path(artifact.filePath); return FileInfo.path(ModUtils.artifactInstalledFilePath(artifact)); } function addExternalLibPath(product, list, path) { addNewElement(list, path); if (product.qbs.hostOS.contains("windows") && FileInfo.fileName(path) === "lib") { var binPath = FileInfo.joinPaths(FileInfo.path(path), "bin"); if (File.exists(binPath)) addNewElement(list, binPath); } } function gatherPaths(product, libPaths, frameworkPaths, seenProducts) { if (seenProducts.contains(product.name)) return; seenProducts.push(product.name); // Gather explicitly given library paths. if (product.cpp && product.cpp.libraryPaths) product.cpp.libraryPaths.forEach(function(p) { addExternalLibPath(product, libPaths, p); }); if (product.cpp && product.cpp.frameworkPaths) product.cpp.frameworkPaths.forEach(function(p) { addNewElement(frameworkPaths, p); }); // Extract paths from dynamic libraries, if they are given as file paths. if (product.cpp && product.cpp.dynamicLibraries) { product.cpp.dynamicLibraries.forEach(function(dll) { if (FileInfo.isAbsolutePath(dll)) addExternalLibPath(product, libPaths, FileInfo.path(dll)); }); } // Traverse library dependencies. for (var i = 0; i < product.dependencies.length; ++i) { var dep = product.dependencies[i]; var dllSymlinkArtifacts = dep.artifacts["bundle.symlink.executable"]; if (dllSymlinkArtifacts) { var addArtifact = function(artifact) { addNewElement(frameworkPaths, FileInfo.path(artifactDir(artifact))); }; dllSymlinkArtifacts.forEach(addArtifact); // TODO: Will also catch applications. Can we prevent that? } else { addArtifact = function(artifact) { addNewElement(libPaths, artifactDir(artifact)); }; var dllArtifacts = dep.artifacts["dynamiclibrary"]; if (dllArtifacts) dllArtifacts.forEach(addArtifact); var loadableModuleArtifacts = dep.artifacts["loadablemodule"]; if (loadableModuleArtifacts) loadableModuleArtifacts.forEach(addArtifact); } if (!dep.hasOwnProperty("present")) // Recurse if the dependency is a product. TODO: Provide non-heuristic way to decide whether dependency is a product. gatherPaths(dep, libPaths, frameworkPaths, seenProducts); } } function setupRunEnvironment(product, config) { if (config.contains("ignore-lib-dependencies")) return; if (product.qbs.hostPlatform !== product.qbs.targetPlatform) return; var libPaths = []; var frameworkPaths = []; gatherPaths(product, libPaths, frameworkPaths, []); var runPaths = product.cpp ? product.cpp.systemRunPaths : undefined; if (runPaths && runPaths.length > 0) { var canonicalRunPaths = runPaths.map(function(p) { return File.canonicalFilePath(p); }); var filterFunc = function(libPath) { return !runPaths.contains(libPath) && !canonicalRunPaths.contains(File.canonicalFilePath(libPath)); }; libPaths = libPaths.filter(filterFunc); frameworkPaths = frameworkPaths.filter(filterFunc); } if (libPaths.length > 0) { var envVarName; if (product.qbs.targetOS.contains("windows")) envVarName = "PATH"; else if (product.qbs.targetOS.contains("macos")) envVarName = "DYLD_LIBRARY_PATH"; else envVarName = "LD_LIBRARY_PATH"; var envVar = new ModUtils.EnvironmentVariable(envVarName, product.qbs.pathListSeparator, product.qbs.hostOS.contains("windows")); libPaths.forEach(function(p) { envVar.prepend(p); }); envVar.set(); } if (product.qbs.targetOS.contains("macos") && frameworkPaths.length > 0) { envVar = new ModUtils.EnvironmentVariable("DYLD_FRAMEWORK_PATH", ':', false); frameworkPaths.forEach(function(p) { envVar.prepend(p); }); envVar.set(); } } qbs-src-1.13.1/share/qbs/modules/cpp/tvos-gcc.qbs000066400000000000000000000041641347155106100215340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ DarwinGCC { priority: 1 condition: qbs.targetOS.contains('tvos') && qbs.toolchain && qbs.toolchain.contains('gcc') targetSystem: "tvos" + (minimumTvosVersion || "") minimumDarwinVersion: minimumTvosVersion minimumDarwinVersionCompilerFlag: qbs.targetOS.contains("tvos-simulator") ? "-mtvos-simulator-version-min" : "-mtvos-version-min" minimumDarwinVersionLinkerFlag: qbs.targetOS.contains("tvos-simulator") ? "-tvos_simulator_version_min" : "-tvos_version_min" } qbs-src-1.13.1/share/qbs/modules/cpp/watchos-gcc.qbs000066400000000000000000000042701347155106100222070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ DarwinGCC { priority: 1 condition: qbs.targetOS.contains('watchos') && qbs.toolchain && qbs.toolchain.contains('gcc') targetSystem: "watchos" + (minimumWatchosVersion || "") minimumDarwinVersion: minimumWatchosVersion minimumDarwinVersionCompilerFlag: qbs.targetOS.contains("watchos-simulator") ? "-mwatchos-simulator-version-min" : "-mwatchos-version-min" minimumDarwinVersionLinkerFlag: qbs.targetOS.contains("watchos-simulator") ? "-watchos_simulator_version_min" : "-watchos_version_min" } qbs-src-1.13.1/share/qbs/modules/cpp/windows-mingw.qbs000066400000000000000000000143071347155106100226200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.ModUtils import qbs.TextFile import qbs.Utilities import qbs.WindowsUtils import "setuprunenv.js" as SetupRunEnv GenericGCC { condition: qbs.targetOS.contains("windows") && qbs.toolchain && qbs.toolchain.contains("mingw") priority: 0 staticLibraryPrefix: "lib" staticLibrarySuffix: ".a" dynamicLibrarySuffix: ".dll" executableSuffix: ".exe" debugInfoSuffix: ".debug" imageFormat: "pe" windowsApiCharacterSet: "unicode" platformDefines: base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet)) .concat("WIN32") probeEnv: buildEnv Properties { condition: product.multiplexByQbsProperties.contains("buildVariants") && qbs.buildVariants && qbs.buildVariants.length > 1 && qbs.buildVariant !== "release" && product.type.containsAny(["staticlibrary", "dynamiclibrary"]) variantSuffix: "d" } property string windresName: 'windres' property path windresPath: { return toolchainPathPrefix + windresName } setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, true); v.prepend(product.cpp.toolchainInstallPath); v.set(); } setupRunEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, true); v.prepend(product.cpp.toolchainInstallPath); v.set(); SetupRunEnv.setupRunEnvironment(product, config); } FileTagger { patterns: ["*.manifest"] fileTags: ["native.pe.manifest"] } Rule { inputs: ["native.pe.manifest"] multiplex: true outputFileTags: ["rc"] outputArtifacts: { if (product.type.containsAny(["application", "dynamiclibrary"])) { return [{ filePath: input.completeBaseName + ".rc", fileTags: ["rc"] }]; } return []; } prepare: { var inputList = inputs["native.pe.manifest"]; // TODO: Emulate manifest merging like Microsoft's mt.exe tool does if (inputList.length !== 1) { throw("The MinGW toolchain does not support manifest merging; " + "you may only specify a single manifest file to embed into your assembly."); } var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.productType = product.type; cmd.inputFilePath = inputList[0].filePath; cmd.outputFilePath = output.filePath; cmd.sourceCode = function() { var tf; try { tf = new TextFile(outputFilePath, TextFile.WriteOnly); if (productType.contains("application")) tf.write("1 "); // CREATEPROCESS_MANIFEST_RESOURCE_ID else if (productType.contains("dynamiclibrary")) tf.write("2 "); // ISOLATIONAWARE_MANIFEST_RESOURCE_ID tf.write("24 "); // RT_MANIFEST tf.writeLine(Utilities.cStringQuote(inputFilePath)); } finally { if (tf) tf.close(); } }; return [cmd]; } } FileTagger { patterns: ["*.rc"] fileTags: ["rc"] } Rule { inputs: ["rc"] auxiliaryInputs: ["hpp"] Artifact { filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + "_res.o" fileTags: ["obj"] } prepare: { var platformDefines = input.cpp.platformDefines; var defines = input.cpp.defines; var includePaths = input.cpp.includePaths; var systemIncludePaths = input.cpp.systemIncludePaths; var args = []; var i; for (i in platformDefines) { args.push('-D'); args.push(platformDefines[i]); } for (i in defines) { args.push('-D'); args.push(defines[i]); } for (i in includePaths) { args.push('-I'); args.push(includePaths[i]); } for (i in systemIncludePaths) { args.push('-I'); args.push(systemIncludePaths[i]); } args = args.concat(['-i', input.filePath, '-o', output.filePath]); var cmd = new Command(product.cpp.windresPath, args); cmd.description = 'compiling ' + input.fileName; cmd.highlight = 'compiler'; return cmd; } } } qbs-src-1.13.1/share/qbs/modules/cpp/windows-msvc.qbs000066400000000000000000000327761347155106100224610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.PathTools import qbs.Probes import qbs.Utilities import qbs.WindowsUtils import 'msvc.js' as MSVC CppModule { condition: qbs.hostOS.contains('windows') && qbs.targetOS.contains('windows') && qbs.toolchain && qbs.toolchain.contains('msvc') Probes.BinaryProbe { id: compilerPathProbe condition: !toolchainInstallPath && !_skipAllChecks names: ["cl"] } Probes.MsvcProbe { id: msvcProbe condition: !_skipAllChecks compilerFilePath: compilerPath enableDefinesByLanguage: enableCompilerDefinesByLanguage preferredArchitecture: qbs.architecture } qbs.architecture: msvcProbe.found ? msvcProbe.architecture : original compilerVersionMajor: msvcProbe.versionMajor compilerVersionMinor: msvcProbe.versionMinor compilerVersionPatch: msvcProbe.versionPatch compilerIncludePaths: msvcProbe.includePaths windowsApiCharacterSet: "unicode" platformDefines: { var defines = base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet)) .concat("WIN32"); var def = WindowsUtils.winapiFamilyDefine(windowsApiFamily); if (def) defines.push("WINAPI_FAMILY=WINAPI_FAMILY_" + def); (windowsApiAdditionalPartitions || []).map(function (name) { defines.push("WINAPI_PARTITION_" + WindowsUtils.winapiPartitionDefine(name) + "=1"); }); return defines; } platformCommonCompilerFlags: { var flags = base; if (compilerVersionMajor >= 18) // 2013 flags.push("/FS"); return flags; } compilerDefinesByLanguage: msvcProbe.compilerDefinesByLanguage warningLevel: "default" compilerName: "cl.exe" compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) assemblerName: { switch (qbs.architecture) { case "armv7": return "armasm.exe"; case "arm64": return "armasm64.exe"; case "ia64": return "ias.exe"; case "x86": return "ml.exe"; case "x86_64": return "ml64.exe"; } } linkerName: "link.exe" runtimeLibrary: "dynamic" separateDebugInformation: true property bool generateManifestFile: true property string toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined architecture: qbs.architecture endianness: "little" staticLibrarySuffix: ".lib" dynamicLibrarySuffix: ".dll" executableSuffix: ".exe" debugInfoSuffix: ".pdb" imageFormat: "pe" Properties { condition: product.multiplexByQbsProperties.contains("buildVariants") && qbs.buildVariants && qbs.buildVariants.length > 1 && qbs.buildVariant !== "release" && product.type.containsAny(["staticlibrary", "dynamiclibrary"]) variantSuffix: "d" } property var buildEnv: msvcProbe.buildEnv setupBuildEnvironment: { for (var key in product.cpp.buildEnv) { var v = new ModUtils.EnvironmentVariable(key, ';'); v.prepend(product.cpp.buildEnv[key]); v.set(); } } Rule { condition: useCPrecompiledHeader inputs: ["c_pch_src"] auxiliaryInputs: ["hpp"] Artifact { fileTags: ['obj'] filePath: Utilities.getHash(input.completeBaseName) + '_c.obj' } Artifact { fileTags: ['c_pch'] filePath: product.name + '_c.pch' } prepare: { return MSVC.prepareCompiler.apply(MSVC, arguments); } } Rule { condition: useCxxPrecompiledHeader inputs: ["cpp_pch_src"] explicitlyDependsOn: ["c_pch"] // to prevent vc--0.pdb conflict auxiliaryInputs: ["hpp"] Artifact { fileTags: ['obj'] filePath: Utilities.getHash(input.completeBaseName) + '_cpp.obj' } Artifact { fileTags: ['cpp_pch'] filePath: product.name + '_cpp.pch' } prepare: { return MSVC.prepareCompiler.apply(MSVC, arguments); } } Rule { name: "compiler" inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] explicitlyDependsOn: ["c_pch", "cpp_pch"] outputFileTags: ["obj", "intermediate_obj"] outputArtifacts: { var tags = input.fileTags.contains("cpp_intermediate_object") ? ["intermediate_obj"] : ["obj"]; return [{ fileTags: tags, filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + ".obj" }]; } prepare: { return MSVC.prepareCompiler.apply(MSVC, arguments); } } FileTagger { patterns: ["*.manifest"] fileTags: ["native.pe.manifest"] } Rule { name: "applicationLinker" multiplex: true inputs: ['obj', 'native.pe.manifest'] inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_app"] outputFileTags: ["application", "debuginfo_app"] outputArtifacts: { var app = { fileTags: ["application"], filePath: FileInfo.joinPaths( product.destinationDirectory, PathTools.applicationFilePath(product)) }; var artifacts = [app]; if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { artifacts.push({ fileTags: ["debuginfo_app"], filePath: app.filePath.substr(0, app.filePath.length - 4) + product.cpp.debugInfoSuffix }); } return artifacts; } prepare: { return MSVC.prepareLinker.apply(MSVC, arguments); } } Rule { name: "dynamicLibraryLinker" multiplex: true inputs: ['obj', 'native.pe.manifest'] inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_dll"] outputFileTags: ["dynamiclibrary", "dynamiclibrary_import", "debuginfo_dll"] outputArtifacts: { var artifacts = [ { fileTags: ["dynamiclibrary"], filePath: product.destinationDirectory + "/" + PathTools.dynamicLibraryFilePath(product) }, { fileTags: ["dynamiclibrary_import"], filePath: product.destinationDirectory + "/" + PathTools.importLibraryFilePath(product), alwaysUpdated: false } ]; if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { var lib = artifacts[0]; artifacts.push({ fileTags: ["debuginfo_dll"], filePath: lib.filePath.substr(0, lib.filePath.length - 4) + product.cpp.debugInfoSuffix }); } return artifacts; } prepare: { return MSVC.prepareLinker.apply(MSVC, arguments); } } Rule { name: "libtool" multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"] outputFileTags: ["staticlibrary", "debuginfo_cl"] outputArtifacts: { var artifacts = [ { fileTags: ["staticlibrary"], filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.staticLibraryFilePath(product)) } ]; if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { artifacts.push({ fileTags: ["debuginfo_cl"], filePath: product.targetName + ".cl" + product.cpp.debugInfoSuffix }); } return artifacts; } prepare: { var args = ['/nologo'] var lib = outputs["staticlibrary"][0]; var nativeOutputFileName = FileInfo.toWindowsSeparators(lib.filePath) args.push('/OUT:' + nativeOutputFileName) for (var i in inputs.obj) { var fileName = FileInfo.toWindowsSeparators(inputs.obj[i].filePath) args.push(fileName) } var cmd = new Command("lib.exe", args); cmd.description = 'creating ' + lib.fileName; cmd.highlight = 'linker'; cmd.jobPool = "linker"; cmd.workingDirectory = FileInfo.path(lib.filePath) cmd.responseFileUsagePrefix = '@'; return cmd; } } FileTagger { patterns: ["*.rc"] fileTags: ["rc"] } Rule { inputs: ["rc"] auxiliaryInputs: ["hpp"] Artifact { filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + ".res" fileTags: ["obj"] } prepare: { var platformDefines = input.cpp.platformDefines; var defines = input.cpp.defines; var includePaths = input.cpp.includePaths; var systemIncludePaths = input.cpp.systemIncludePaths; var args = []; var i; var hasNoLogo = product.cpp.compilerVersionMajor >= 16; // 2010 if (hasNoLogo) args.push("/nologo"); for (i in platformDefines) { args.push('/d'); args.push(platformDefines[i]); } for (i in defines) { args.push('/d'); args.push(defines[i]); } for (i in includePaths) { args.push('/i'); args.push(includePaths[i]); } for (i in systemIncludePaths) { args.push('/i'); args.push(systemIncludePaths[i]); } args = args.concat(['/fo', output.filePath, input.filePath]); var cmd = new Command('rc', args); cmd.description = 'compiling ' + input.fileName; cmd.highlight = 'compiler'; cmd.jobPool = "compiler"; if (!hasNoLogo) { // Remove the first two lines of stdout. That's the logo. cmd.stdoutFilterFunction = function(output) { var idx = 0; for (var i = 0; i < 3; ++i) idx = output.indexOf('\n', idx + 1); return output.substr(idx + 1); } } return cmd; } } FileTagger { patterns: "*.asm" fileTags: ["asm"] } Rule { inputs: ["asm"] Artifact { filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + ".obj" fileTags: ["obj"] } prepare: { var args = ["/nologo", "/c", "/Fo" + FileInfo.toWindowsSeparators(output.filePath), FileInfo.toWindowsSeparators(input.filePath)]; if (product.cpp.debugInformation) args.push("/Zi"); args = args.concat(ModUtils.moduleProperty(input, 'platformFlags', 'asm'), ModUtils.moduleProperty(input, 'flags', 'asm')); var cmd = new Command(product.cpp.assemblerPath, args); cmd.description = "assembling " + input.fileName; cmd.jobPool = "assembler"; cmd.inputFileName = input.fileName; cmd.stdoutFilterFunction = function(output) { var lines = output.split("\r\n").filter(function (s) { return !s.endsWith(inputFileName); }); return lines.join("\r\n"); }; return cmd; } } } qbs-src-1.13.1/share/qbs/modules/cpufeatures/000077500000000000000000000000001347155106100210375ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/cpufeatures/cpufeatures.qbs000066400000000000000000000011601347155106100240720ustar00rootroot00000000000000Module { property bool arm_neon property bool arm_vfpv4 property bool mips_dsp property bool mips_dspr2 property bool x86_avx property bool x86_avx2 property bool x86_avx512bw property bool x86_avx512cd property bool x86_avx512dq property bool x86_avx512er property bool x86_avx512f property bool x86_avx512ifma property bool x86_avx512pf property bool x86_avx512vbmi property bool x86_avx512vl property bool x86_f16c property bool x86_sse2 property bool x86_sse3 property bool x86_sse4_1 property bool x86_sse4_2 property bool x86_ssse3 } qbs-src-1.13.1/share/qbs/modules/dmg/000077500000000000000000000000001347155106100172605ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/dmg/DMGModule.qbs000066400000000000000000000125361347155106100215530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.DarwinTools import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Process import qbs.TextFile import "dmg.js" as Dmg Module { Depends { name: "xcode"; required: false } condition: qbs.hostOS.contains("darwin") && qbs.targetOS.contains("darwin") property string volumeName: product.targetName PropertyOptions { name: "volumeName" description: "the name of the disk image (displayed in Finder when mounted)" } property bool badgeVolumeIcon: false PropertyOptions { name: "badgeVolumeIcon" description: "whether to render the user-supplied icon on top of the " + "default volume icon instead of using it directly" } property string format: "UDBZ" PropertyOptions { name: "format" description: "the format to create the disk image in" } property int compressionLevel: qbs.buildVariant === "release" ? 9 : undefined PropertyOptions { name: "compressionLevel" description: "sets the zlib or bzip2 compression level for UDZO and UDBZ disk images" } property string textutilPath: "/usr/bin/textutil" property string hdiutilPath: "/usr/bin/hdiutil" property string dmgSuffix: ".dmg" property string sourceBase readonly property string pythonPath: File.canonicalFilePath(FileInfo.joinPaths(path, "..", "..", "python")) property string backgroundColor property int iconSize: 128 property int windowX: 100 property int windowY: 100 property int windowWidth: 640 property int windowHeight: 480 property var iconPositions property int iconX: windowWidth / 2 property int iconY: windowHeight / 2 property string defaultLicenseLocale property string licenseLocale property string licenseLanguageName property string licenseAgreeButtonText property string licenseDisagreeButtonText property string licensePrintButtonText property string licenseSaveButtonText property string licenseInstructionText FileTagger { patterns: [ "*.txt", "*.rtf", "*.html", "*.doc", "*.docx", "*.odt", "*.xml", "*.webarchive", "LICENSE" ] fileTags: ["dmg.license.input"] } FileTagger { patterns: ["*.icns"] fileTags: ["icns"] } FileTagger { patterns: ["*.tif", "*.tiff"] fileTags: ["tiff"] } Rule { inputs: ["dmg.license.input"] outputFileTags: ["dmg.license"] outputArtifacts: ([{ filePath: FileInfo.joinPaths(product.destinationDirectory, "licenses", FileInfo.relativePath(product.sourceDirectory, input.filePath) + ".rtf"), fileTags: ["dmg.license"], dmg: { licenseLocale: input.dmg.licenseLocale, licenseLanguageName: input.dmg.licenseLanguageName, licenseAgreeButtonText: input.dmg.licenseAgreeButtonText, licenseDisagreeButtonText: input.dmg.licenseDisagreeButtonText, licensePrintButtonText: input.dmg.licensePrintButtonText, licenseSaveButtonText: input.dmg.licenseSaveButtonText, licenseInstructionText: input.dmg.licenseInstructionText } }]) prepare: Dmg.prepareLicense.apply(Dmg, arguments) } Rule { multiplex: true inputs: ["dmg.input", "dmg.license", "icns", "tiff"] Artifact { fileTags: ["dmg.dmg"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + product.dmg.dmgSuffix) } prepare: Dmg.prepareDmg.apply(Dmg, arguments) } } qbs-src-1.13.1/share/qbs/modules/dmg/dmg.js000066400000000000000000000203241347155106100203660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var DarwinTools = require("qbs.DarwinTools"); var FileInfo = require("qbs.FileInfo"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); function localizationFromArtifact(input) { var locale = input.dmg.licenseLocale || DarwinTools.localizationKey(input.filePath); if (!locale) throw("Could not determine localization for license file: " + input.filePath); return locale; } function dmgbuildSettings(product, inputs) { var backgroundImages = inputs["tiff"]; var backgroundImage; if (backgroundImages) { if (backgroundImages.length > 1) throw new Error("only one background image may be specified"); backgroundImage = backgroundImages[0].filePath; } var volumeIcons = inputs["icns"]; var volumeIcon; if (volumeIcons) { if (volumeIcons.length > 1) throw new Error("only one volume icon may be specified"); volumeIcon = volumeIcons[0].filePath; } var licenseFileObjects = Array.prototype.map.call(inputs["dmg.license"], function (a) { return { "dmg": { "licenseLocale": localizationFromArtifact(a), "licenseLanguageName": a.dmg.licenseLanguageName, "licenseAgreeButtonText": a.dmg.licenseAgreeButtonText, "licenseDisagreeButtonText": a.dmg.licenseDisagreeButtonText, "licensePrintButtonText": a.dmg.licensePrintButtonText, "licenseSaveButtonText": a.dmg.licenseSaveButtonText, "licenseInstructionText": a.dmg.licenseInstructionText, }, "filePath": a.filePath }; }); function reduceLicensesForKey(licenseFileObjects, key) { return licenseFileObjects.reduce(function (accumulator, currentValue) { var locale = currentValue.dmg.licenseLocale; if (accumulator[locale]) throw new Error("Multiple license files for localization '" + locale + "'"); switch (key) { case "licenses": accumulator[locale] = currentValue.filePath; break; case "buttons": var texts = [ currentValue.dmg.licenseLanguageName, currentValue.dmg.licenseAgreeButtonText, currentValue.dmg.licenseDisagreeButtonText, currentValue.dmg.licensePrintButtonText, currentValue.dmg.licenseSaveButtonText, currentValue.dmg.licenseInstructionText ]; accumulator[locale] = texts.every(function (a) { return !!a; }) ? texts : undefined; break; } return accumulator; }, {}); } var contentsArray = Array.prototype.map.call(inputs["dmg.input"], function (a) { if (a.dmg.sourceBase && !a.filePath.startsWith(a.dmg.sourceBase)) { throw new Error("Cannot install '" + a.filePath + "', " + "because it doesn't start with the value of " + "dmg.sourceBase '" + a.dmg.sourceBase + "'."); } var isSymlink = a.fileTags.contains("dmg.input.symlink"); return { "x": a.dmg.iconX, "y": a.dmg.iconY, "type": isSymlink ? "link" : "file", "path": isSymlink ? a.dmg.symlinkTarget : a.filePath, "name": FileInfo.relativePath(a.dmg.sourceBase || FileInfo.path(a.filePath), a.filePath) }; }); Array.prototype.forEach.call(product.dmg.iconPositions, function (obj) { var existingIndex = -1; Array.prototype.forEach.call(contentsArray, function (contentsItem, i) { if (contentsItem["name"] === obj["path"]) existingIndex = i; }); if (existingIndex >= 0) { contentsArray[existingIndex]["x"] = obj["x"]; contentsArray[existingIndex]["y"] = obj["y"]; } else { contentsArray.push({ "type": "position", "name": obj["path"], // name => path is not a typo "path": obj["path"], "x": obj["x"], "y": obj["y"] }); } }); return { "title": product.dmg.volumeName, "icon": !product.dmg.badgeVolumeIcon ? volumeIcon : undefined, "badge-icon": product.dmg.badgeVolumeIcon ? volumeIcon : undefined, "background": backgroundImage, "background-color": product.dmg.backgroundColor, "icon-size": product.dmg.iconSize, "window": { "position": { "x": product.dmg.windowX, "y": product.dmg.windowY }, "size": { "width": product.dmg.windowWidth, "height": product.dmg.windowHeight } }, "format": product.dmg.format, "compression-level": product.dmg.compressionLevel, "license": { "default-language": product.dmg.defaultLicenseLocale, "licenses": reduceLicensesForKey(licenseFileObjects, "licenses"), "buttons": reduceLicensesForKey(licenseFileObjects, "buttons") }, "contents": contentsArray }; } function prepareLicense(project, product, inputs, outputs, input, output) { var cmd = new Command(product.dmg.textutilPath, [ "-convert", "rtf", "-strip", "-font", "Arial", "-output", output.filePath, "--", input.filePath ]); cmd.description = "converting " + input.fileName; return [cmd]; } function prepareDmg(project, product, inputs, outputs, input, output) { var i; var cmd; var cmds = []; var settingsJsonFilePath = FileInfo.joinPaths(product.destinationDirectory, "settings.json"); cmd = new JavaScriptCommand(); cmd.silent = true; cmd.settingsJSON = dmgbuildSettings(product, inputs); cmd.settingsJsonFilePath = settingsJsonFilePath; cmd.sourceCode = function () { var tf; try { tf = new TextFile(settingsJsonFilePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(settingsJSON, undefined, 4)); } finally { if (tf) tf.close(); } } cmds.push(cmd); // Create the actual DMG via dmgbuild cmd = new Command(FileInfo.joinPaths(product.qbs.libexecPath, "dmgbuild"), [product.dmg.volumeName, output.filePath, "--no-hidpi", // qbs handles this by itself "--settings", settingsJsonFilePath]); cmd.environment = ["PYTHONPATH=" + product.dmg.pythonPath]; cmd.description = "creating " + output.fileName; cmds.push(cmd); return cmds; } qbs-src-1.13.1/share/qbs/modules/ib/000077500000000000000000000000001347155106100171035ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/ib/IBModule.qbs000066400000000000000000000211451347155106100212550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.BundleTools import qbs.DarwinTools import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Process import 'ib.js' as Ib Module { Depends { name: "xcode"; required: false } Probe { id: ibProbe property string toolPath: ibtoolPath // input property string toolVersion // output configure: { toolVersion = Ib.ibtoolVersion(toolPath); found = true; } } condition: qbs.hostOS.contains("darwin") && qbs.targetOS.contains("darwin") property bool warnings: true property bool errors: true property bool notices: true property stringList flags // tiffutil specific property string tiffutilName: "tiffutil" property string tiffutilPath: FileInfo.joinPaths("/usr/bin", tiffutilName) property bool combineHidpiImages: true // iconutil specific property string iconutilName: "iconutil" property string iconutilPath: FileInfo.joinPaths("/usr/bin", iconutilName) // XIB/NIB specific property string ibtoolName: "ibtool" property string ibtoolPath: FileInfo.joinPaths(xcode.developerPath, "/usr/bin", ibtoolName) property bool flatten: true property string module property bool autoActivateCustomFonts: true // Asset catalog specific property string actoolName: xcode.present ? "actool" : "ictool" property string actoolPath: FileInfo.joinPaths(xcode.developerPath, "/usr/bin", actoolName) property string appIconName property string launchImageName property bool compressPngs: true // private properties property string outputFormat: "human-readable-text" property string tiffSuffix: ".tiff" property string appleIconSuffix: ".icns" property string compiledAssetCatalogSuffix: ".car" property string compiledNibSuffix: ".nib" property string compiledStoryboardSuffix: ".storyboardc" version: ibtoolVersion property string ibtoolVersion: ibProbe.toolVersion property var ibtoolVersionParts: ibtoolVersion ? ibtoolVersion.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int ibtoolVersionMajor: ibtoolVersionParts[0] property int ibtoolVersionMinor: ibtoolVersionParts[1] property int ibtoolVersionPatch: ibtoolVersionParts[2] property stringList targetDevices: xcode.present ? xcode.targetDevices : DarwinTools.targetDevices(qbs.targetOS) validate: { var validator = new ModUtils.PropertyValidator("ib"); validator.setRequiredProperty("ibtoolVersion", ibtoolVersion); validator.setRequiredProperty("ibtoolVersionMajor", ibtoolVersionMajor); validator.setRequiredProperty("ibtoolVersionMinor", ibtoolVersionMinor); validator.addVersionValidator("ibtoolVersion", ibtoolVersion, 2, 3); validator.addRangeValidator("ibtoolVersionMajor", ibtoolVersionMajor, 1); validator.addRangeValidator("ibtoolVersionMinor", ibtoolVersionMinor, 0); if (ibtoolVersionPatch !== undefined) validator.addRangeValidator("ibtoolVersionPatch", ibtoolVersionPatch, 0); validator.validate(); } FileTagger { patterns: ["*.png"] fileTags: ["png"] } FileTagger { patterns: ["*.iconset"] // bundle fileTags: ["iconset"] } FileTagger { patterns: ["*.nib", "*.xib"] fileTags: ["nib"] } FileTagger { patterns: ["*.storyboard"] fileTags: ["storyboard"] } FileTagger { patterns: ["*.xcassets"] // bundle fileTags: ["assetcatalog"] } Rule { multiplex: true inputs: ["png"] outputFileTags: ["tiff"] outputArtifacts: Ib.tiffutilArtifacts(product, inputs) prepare: Ib.prepareTiffutil.apply(Ib, arguments) } Rule { inputs: ["iconset"] outputFileTags: ["icns", "bundle.input"] outputArtifacts: ([{ filePath: FileInfo.joinPaths(product.destinationDirectory, input.completeBaseName + ModUtils.moduleProperty(product, "appleIconSuffix")), fileTags: ["icns", "bundle.input"], bundle: { _bundleFilePath: FileInfo.joinPaths(BundleTools.destinationDirectoryForResource(product, input), input.completeBaseName + ModUtils.moduleProperty(product, "appleIconSuffix")) } }]) prepare: { var args = ["--convert", "icns", "--output", output.filePath, input.filePath]; var cmd = new Command(ModUtils.moduleProperty(product, "iconutilPath"), args); cmd.description = "compiling " + input.fileName; return cmd; } } Rule { inputs: ["nib", "storyboard"] outputFileTags: { var tags = ["partial_infoplist"]; for (var i = 0; i < inputs.length; ++i) tags = tags.uniqueConcat(ModUtils.allFileTags(Ib.ibtoolFileTaggers(inputs[i]))); return tags; } outputArtifacts: Ib.ibtoolOutputArtifacts(product, inputs, input) prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "ibtoolPath"), Ib.ibtooldArguments(product, inputs, input, outputs)); cmd.description = "compiling " + input.fileName; // Also display the language name of the nib/storyboard being compiled if it has one var localizationKey = DarwinTools.localizationKey(input.filePath); if (localizationKey) cmd.description += ' (' + localizationKey + ')'; cmd.highlight = 'compiler'; // May not be strictly needed, but is set by some versions of Xcode if (input.fileTags.contains("storyboard")) cmd.environment.push("IBSC_MINIMUM_COMPATIBILITY_VERSION=" + (product.moduleProperty("cpp", "minimumDarwinVersion") || "")); cmd.stdoutFilterFunction = function(output) { return ""; }; return cmd; } } Rule { inputs: ["assetcatalog"] multiplex: true outputArtifacts: Ib.actoolOutputArtifacts(product, inputs) outputFileTags: ["bundle.input", "compiled_assetcatalog", "partial_infoplist"] prepare: { var mkdir = new JavaScriptCommand(); mkdir.silent = true; mkdir.sourceCode = function () { File.makePath(FileInfo.joinPaths(product.buildDirectory, "actool.dir")); }; var cmd = new Command(ModUtils.moduleProperty(product, "actoolPath"), Ib.ibtooldArguments(product, inputs, input, outputs)); cmd.description = inputs["assetcatalog"].map(function (input) { return "compiling " + input.fileName; }).join('\n'); cmd.highlight = "compiler"; cmd.stdoutFilterFunction = function(output) { return ""; }; return [mkdir, cmd]; } } } qbs-src-1.13.1/share/qbs/modules/ib/ib.js000066400000000000000000000350641347155106100200430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var BundleTools = require("qbs.BundleTools"); var DarwinTools = require("qbs.DarwinTools"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); var PropertyList = require("qbs.PropertyList"); function artifactsFromInputs(inputs) { var artifacts = []; for (var tag in inputs) { artifacts = artifacts.concat(inputs[tag]); } return artifacts; } function tiffutilScalesMap(inputs) { return artifactsFromInputs(inputs).map(function (a) { var m = a.filePath.match(/^(.+?)(@(\d+)x)?(\..+?)$/); var basePath = m[1]; var scale = m[2] || ""; var nscale = m[3]; var extension = m[4]; if (scale && scale < 1) throw new Error("Invalid scale '" + nscale + "' for image '" + a.filePath + "'"); return { basePath: basePath, extension: extension, scale: scale }; }).reduce(function (previous, current) { previous[current["basePath"]] = (previous[current["basePath"]] || []).concat([{ extension: current["extension"], scale: current["scale"] }]); return previous; }, {}); } function tiffutilOutputFilePath(product, basePath) { return FileInfo.joinPaths(product.destinationDirectory, "hidpi-images", FileInfo.relativePath(product.sourceDirectory, basePath) + product.ib.tiffSuffix); } function tiffutilArtifacts(product, inputs) { var artifacts = []; var map = tiffutilScalesMap(inputs); for (var key in map) { artifacts.push({ filePath: tiffutilOutputFilePath(product, key), fileTags: ["tiff"] }); } return artifacts; } function prepareTiffutil(project, product, inputs, outputs, input, output) { var cmds = []; var map = tiffutilScalesMap(inputs); for (var key in map) { var args = ["-cat" + (product.ib.combineHidpiImages ? "hidpicheck" : "")]; var count = 0; map[key].forEach(function (obj) { args.push(key + obj["scale"] + obj["extension"]); ++count; }); args.push("-out", tiffutilOutputFilePath(product, key)); var cmd = new Command(product.ib.tiffutilPath, args); cmd.description = "creating " + output.fileName; cmd.count = count; cmd.outputFilePath = output.filePath; cmd.stderrFilterFunction = function (output) { return output.replace(count + " images written to " + outputFilePath + ".", ""); }; cmds.push(cmd); } return cmds; } function ibtooldArguments(product, inputs, input, outputs, overrideOutput) { var i; var args = []; var allInputs = artifactsFromInputs(inputs); var outputFormat = ModUtils.moduleProperty(product, "outputFormat"); if (outputFormat) { if (!["binary1", "xml1", "human-readable-text"].contains(outputFormat)) throw("Invalid ibtoold output format: " + outputFormat + ". " + "Must be in [binary1, xml1, human-readable-text]."); args.push("--output-format", outputFormat); } var debugFlags = ["warnings", "errors", "notices"]; for (var j in debugFlags) { var flag = debugFlags[j]; if (ModUtils.modulePropertyFromArtifacts(product, allInputs, product.moduleName, flag)) { args.push("--" + flag); } } if (inputs.assetcatalog) { args.push("--platform", DarwinTools.applePlatformName( product.moduleProperty("qbs", "targetOS"), product.moduleProperty("xcode", "platformType"))); var appIconName = ModUtils.modulePropertyFromArtifacts(product, inputs.assetcatalog, product.moduleName, "appIconName"); if (appIconName) args.push("--app-icon", appIconName); var launchImageName = ModUtils.modulePropertyFromArtifacts(product, inputs.assetcatalog, product.moduleName, "launchImageName"); if (launchImageName) args.push("--launch-image", launchImageName); // Undocumented but used by Xcode (only for iOS?), probably runs pngcrush or equivalent if (ModUtils.modulePropertyFromArtifacts(product, inputs.assetcatalog, product.moduleName, "compressPngs")) args.push("--compress-pngs"); } else { var sysroot = product.moduleProperty("qbs", "sysroot"); if (sysroot) args.push("--sdk", sysroot); args.push("--flatten", ModUtils.modulePropertyFromArtifacts(product, allInputs, product.moduleName, "flatten") ? 'YES' : 'NO'); // --module and --auto-activate-custom-fonts were introduced in Xcode 6.0 if (ModUtils.moduleProperty(product, "ibtoolVersionMajor") >= 6) { var module = ModUtils.moduleProperty(product, "module"); if (module) args.push("--module", module); if (ModUtils.modulePropertyFromArtifacts(product, allInputs, product.moduleName, "autoActivateCustomFonts")) args.push("--auto-activate-custom-fonts"); } } // --minimum-deployment-target was introduced in Xcode 5.0 var minimumDarwinVersion = product.moduleProperty("cpp", "minimumDarwinVersion"); if (minimumDarwinVersion && ModUtils.moduleProperty(product, "ibtoolVersionMajor") >= 5) args.push("--minimum-deployment-target", minimumDarwinVersion); // --target-device and -output-partial-info-plist were introduced in Xcode 6.0 for ibtool if (ModUtils.moduleProperty(product, "ibtoolVersionMajor") >= 6 || inputs.assetcatalog) { args.push("--output-partial-info-plist", (outputs && outputs.partial_infoplist) ? outputs.partial_infoplist[0].filePath : "/dev/null"); // For iOS, we'd normally only output the devices specified in TARGETED_DEVICE_FAMILY // We can't get this info from Info.plist keys due to dependency order, so use the qbs prop var targetDevices = ModUtils.moduleProperty(product, "targetDevices"); for (i in targetDevices) { args.push("--target-device", targetDevices[i]); } } args = args.concat(ModUtils.modulePropertiesFromArtifacts(product, allInputs, product.moduleName, "flags")); if (overrideOutput) { args.push("--compile", overrideOutput); } else { if (outputs.compiled_assetcatalog) args.push("--compile", product.buildDirectory + "/actool.dir"); else // compiled_ibdoc args.push("--compile", product.buildDirectory + "/ibtool.dir/" + ibtoolCompiledDirSuffix(product, input)); } for (i in allInputs) args.push(allInputs[i].filePath); return args; } function ibtoolFileTaggers(fileTags) { var ext; if (fileTags.contains("nib") && !fileTags.contains("storyboard")) ext = "nib"; if (fileTags.contains("storyboard") && !fileTags.contains("nib")) ext = "storyboard"; if (!ext) throw "unknown ibtool input file tags: " + fileTags; var t = ["bundle.input", "compiled_ibdoc"]; return { ".nib": t.concat(["compiled_" + ext + (ext !== "nib" ? "_nib" : "")]), ".plist": t.concat(["compiled_" + ext + "_infoplist"]), ".storyboard": t.concat(["compiled_" + ext]) }; } function ibtoolCompiledDirSuffix(product, input) { var suffix = input.completeBaseName; if (input.fileTags.contains("nib")) suffix += ModUtils.moduleProperty(product, "compiledNibSuffix"); else if (input.fileTags.contains("storyboard")) suffix += ModUtils.moduleProperty(product, "compiledStoryboardSuffix"); return suffix; } function ibtoolOutputArtifacts(product, inputs, input) { var suffix = ibtoolCompiledDirSuffix(product, input); var tracker = new ModUtils.BlackboxOutputArtifactTracker(); tracker.hostOS = product.moduleProperty("qbs", "hostOS"); tracker.shellPath = product.moduleProperty("qbs", "shellPath"); tracker.fileTaggers = ibtoolFileTaggers(input.fileTags); tracker.command = ModUtils.moduleProperty(product, "ibtoolPath"); tracker.commandArgsFunction = function (outputDirectory) { // Last --output-format argument overrides any previous ones // Append the name of the base output since it can be either a file or a directory // in the case of XIB compilations return ibtooldArguments(product, inputs, input, undefined, FileInfo.joinPaths(outputDirectory, suffix)) .concat(["--output-format", "xml1"]); }; var ibtoolBuildDirectory = product.buildDirectory + "/ibtool.dir"; var main = BundleTools.destinationDirectoryForResource(product, input); var artifacts = tracker.artifacts(ibtoolBuildDirectory); if (product.moduleProperty("ib", "ibtoolVersionMajor") >= 6) { var prefix = input.fileTags.contains("storyboard") ? "SB" : ""; var path = FileInfo.joinPaths(product.destinationDirectory, input.completeBaseName + "-" + prefix + "PartialInfo.plist"); artifacts.push({ filePath: path, fileTags: ["partial_infoplist"] }); } // Let the output artifacts known the "main" output // This can be either a file or directory so the artifact might already exist in the output list for (var i = 0; i < artifacts.length; ++i) { if (artifacts[i].fileTags.contains("compiled_ibdoc")) artifacts[i].bundle = { _bundleFilePath: artifacts[i].filePath.replace(ibtoolBuildDirectory, main) }; } return artifacts; } function actoolOutputArtifacts(product, inputs) { // actool has no --dry-run option (rdar://21786925), // so compile to a fake temporary directory in order to extract the list of output files var tracker = new ModUtils.BlackboxOutputArtifactTracker(); tracker.hostOS = product.moduleProperty("qbs", "hostOS"); tracker.shellPath = product.moduleProperty("qbs", "shellPath"); tracker.command = ModUtils.moduleProperty(product, "actoolPath"); tracker.commandArgsFunction = function (outputDirectory) { // Last --output-format argument overrides any previous ones return ibtooldArguments(product, inputs, undefined, undefined, outputDirectory).concat(["--output-format", "xml1"]); }; tracker.processStdOutFunction = parseActoolOutput; var artifacts = tracker.artifacts(product.buildDirectory + "/actool.dir"); // Newer versions of actool don't generate *anything* if there's no input; // in that case a partial Info.plist would not have been generated either if (artifacts && artifacts.length > 0) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, "assetcatalog_generated_info.plist"), fileTags: ["partial_infoplist"] }); } for (var i = 0; i < artifacts.length; ++i) { if (artifacts[i].fileTags.contains("compiled_assetcatalog")) { artifacts[i].bundle = { _bundleFilePath: artifacts[i].filePath.replace( product.buildDirectory + "/actool.dir", BundleTools.destinationDirectoryForResource(product, inputs.assetcatalog[0])) }; } } return artifacts; } function parseActoolOutput(output) { var propertyList = new PropertyList(); try { propertyList.readFromString(output); var plist = propertyList.toObject(); if (plist) plist = plist["com.apple.actool.compilation-results"]; if (plist) { var artifacts = []; files = plist["output-files"]; for (var i in files) { if (files[i] === "/dev/null") continue; var tags = files[i].endsWith(".plist") ? ["partial_infoplist"] : ["bundle.input", "compiled_assetcatalog"]; artifacts.push({ // Even though we pass in a canonical base dir, the paths in the XML File // are non-canonical. See QBS-1417. filePath: FileInfo.canonicalPath(files[i]), fileTags: tags }); } return artifacts; } } finally { propertyList.clear(); } } function ibtoolVersion(ibtool) { var process; var version; try { process = new Process(); if (process.exec(ibtool, ["--version", "--output-format", "xml1"], true) !== 0) console.error(process.readStdErr()); var propertyList = new PropertyList(); try { propertyList.readFromString(process.readStdOut()); var plist = propertyList.toObject(); if (plist) plist = plist["com.apple.ibtool.version"]; if (plist) version = plist["short-bundle-version"]; } finally { propertyList.clear(); } } finally { process.close(); } return version; } qbs-src-1.13.1/share/qbs/modules/ico/000077500000000000000000000000001347155106100172635ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/ico/IcoModule.qbs000066400000000000000000000046261347155106100216620ustar00rootroot00000000000000import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Process import qbs.Utilities import "ico.js" as IcoUtils Module { Probes.BinaryProbe { id: icotoolProbe names: ["icotool"] } Probes.IcoUtilsVersionProbe { id: icotoolVersionProbe toolFilePath: icotoolFilePath } version: icotoolVersionProbe.version property int alphaThreshold property int cursorHotspotX property int cursorHotspotY property bool raw // private properties property string icotoolFilePath: icotoolProbe.filePath readonly property bool hasCursorHotspotBug: Utilities.versionCompare(version, "0.32") < 0 FileTagger { patterns: ["*.png"] fileTags: ["png"] } FileTagger { patterns: ["*.iconset"] // bundle fileTags: ["iconset"] } Rule { inputs: ["iconset"] Artifact { filePath: input.baseName + ".ico" fileTags: ["ico"] } prepare: IcoUtils.prepareIconset.apply(IcoUtils, arguments) } Rule { multiplex: true inputs: ["png"] Artifact { filePath: product.targetName + ".ico" fileTags: ["ico"] } prepare: IcoUtils.prepare.apply(IcoUtils, arguments) } Rule { inputs: ["iconset"] Artifact { filePath: input.baseName + ".cur" fileTags: ["cur"] } prepare: IcoUtils.prepareIconset.apply(IcoUtils, arguments) } Rule { multiplex: true inputs: ["png"] Artifact { filePath: product.targetName + ".cur" fileTags: ["cur"] } prepare: IcoUtils.prepare.apply(IcoUtils, arguments) } validate: { if (!icotoolFilePath) throw ModUtils.ModuleError("Could not find icotool in any of the following " + "locations:\n\t" + icotoolProbe.candidatePaths.join("\n\t") + "\nInstall the icoutils package on your platform."); if (!version) throw ModUtils.ModuleError("Could not determine icoutils package version."); var validator = new ModUtils.PropertyValidator("ico"); validator.setRequiredProperty("version", version); validator.addVersionValidator("version", version, 2, 3); return validator.validate() } } qbs-src-1.13.1/share/qbs/modules/ico/ico.js000066400000000000000000000076671347155106100204130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var Process = require("qbs.Process"); function prepareIconset(project, product, inputs, outputs, input, output) { inputs = File.directoryEntries(input.filePath, File.Files).map(function (p) { return { filePath: FileInfo.joinPaths(input.filePath, p), fileTags: p.endsWith(".png") ? ["png"] : [], ico: {} }; }); inputs = {"png": inputs.filter(function (a) { return a.fileTags.contains("png"); })}; input = undefined; return prepare(project, product, inputs, outputs, input, output); } function prepare(project, product, inputs, outputs, input, output) { var args = ["--create", "--output=" + output.filePath]; if (output.fileTags.contains("ico")) { args.push("--icon"); if (product.ico.alphaThreshold !== undefined) args.push("--alpha-threshold=" + product.ico.alphaThreshold); } var isCursor = output.fileTags.contains("cur"); if (isCursor) args.push("--cursor"); var hasMultipleImages = inputs["png"].length > 1; inputs["png"].map(function(inp) { if (isCursor) { var hasX = inp.ico.cursorHotspotX !== undefined; var hasY = inp.ico.cursorHotspotY !== undefined; if (hasX || hasY) { if (hasMultipleImages && product.ico.hasCursorHotspotBug) { console.warn("icotool " + product.ico.version + " does not support setting " + "the hotspot for cursor files with multiple images. Install " + "icoutils 0.32.0 or newer to use this feature."); } else { if (hasX) args.push("--hotspot-x=" + inp.ico.cursorHotspotX); if (hasY) args.push("--hotspot-y=" + inp.ico.cursorHotspotY); } } } if (inp.ico.raw) args.push("-r"); args.push(inp.filePath); }); var cmd = new Command(product.ico.icotoolFilePath, args); cmd.description = "creating " + output.fileName; return [cmd]; } function findIcoUtilsVersion(toolFilePath) { var p = new Process(); try { p.exec(toolFilePath, ["--version"]); var re = /^[a-z]+ \(icoutils\) ([0-9]+(?:\.[0-9]+){1,2})$/m; var match = p.readStdOut().trim().match(re); if (match !== null) return match[1]; } finally { p.close(); } } qbs-src-1.13.1/share/qbs/modules/innosetup/000077500000000000000000000000001347155106100205355ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/innosetup/InnoSetupModule.qbs000066400000000000000000000125601347155106100243420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.ModUtils import qbs.Probes Module { condition: qbs.targetOS.contains("windows") Probes.InnoSetupProbe { id: innoSetupProbe } property path toolchainInstallPath: innoSetupProbe.path version: innoSetupProbe.version property var versionParts: version ? version.split('.').map(function (item) { return parseInt(item, 10); }) : [] property int versionMajor: versionParts[0] property int versionMinor: versionParts[1] property int versionPatch: versionParts[2] property string compilerName: "ISCC.exe" property string compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) property bool verboseOutput: false PropertyOptions { name: "verboseOutput" description: "display verbose output from the Inno Setup compiler" } property pathList includePaths PropertyOptions { name: "includePaths" description: "directories to add to the include search path" } property stringList defines PropertyOptions { name: "defines" description: "variables that are defined when using the Inno Setup compiler" } property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional flags for the Inno Setup compiler" } readonly property string executableSuffix: ".exe" validate: { var validator = new ModUtils.PropertyValidator("innosetup"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("version", version); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); validator.addVersionValidator("version", version, 3, 3); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); validator.validate(); } // Inno Setup Script FileTagger { patterns: ["*.iss"] fileTags: ["innosetup.iss"] } Rule { id: innoSetupCompiler inputs: ["innosetup.iss"] auxiliaryInputs: ["installable"] Artifact { fileTags: ["innosetup.exe", "application"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ModUtils.moduleProperty(product, "executableSuffix")) } prepare: { var i; var args = [ "/O" + FileInfo.toNativeSeparators(FileInfo.path(output.filePath)), "/F" + FileInfo.toNativeSeparators(FileInfo.completeBaseName(output.fileName)) ]; if (!ModUtils.moduleProperty(product, "verboseOutput")) args.push("/Q"); var includePaths = ModUtils.moduleProperty(product, "includePaths"); for (i in includePaths) args.push("/I" + FileInfo.toNativeSeparators(includePaths[i])); // User-supplied defines var defines = ModUtils.moduleProperty(product, "defines"); for (i in defines) args.push("/D" + defines[i]); // User-supplied flags var flags = ModUtils.moduleProperty(product, "compilerFlags"); for (i in flags) args.push(flags[i]); args.push(FileInfo.toNativeSeparators(input.filePath)); var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args); cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.workingDirectory = FileInfo.path(input.filePath); return cmd; } } } qbs-src-1.13.1/share/qbs/modules/java/000077500000000000000000000000001347155106100174325ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/java/JavaModule.qbs000066400000000000000000000334641347155106100222020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Process import qbs.TextFile import qbs.Utilities import "utils.js" as JavaUtils Module { Probes.JdkProbe { id: jdk environmentPaths: (jdkPath ? [jdkPath] : []).concat(base) } Probes.JdkVersionProbe { id: jdkVersionProbe javac: compilerFilePath } property stringList additionalClassPaths property stringList additionalCompilerFlags property stringList additionalJarFlags property stringList bootClassPaths property string compilerFilePath: FileInfo.joinPaths(jdkPath, "bin", compilerName) property string compilerName: "javac" property bool enableWarnings: true property string interpreterFilePath : FileInfo.joinPaths(jdkPath, "bin", interpreterName) property string interpreterName: "java" property string jarFilePath: FileInfo.joinPaths(jdkPath, "bin", jarName) property string jarName: "jar" property string jarsignerFilePath: FileInfo.joinPaths(jdkPath, "bin", jarsignerName) property string jarsignerName: "jarsigner" property string keytoolFilePath: FileInfo.joinPaths(jdkPath, "bin", keytoolName) property string keytoolName: "keytool" property bool _tagJniHeaders: true property string jdkPath: jdk.path version: [compilerVersionMajor, compilerVersionMinor, compilerVersionPatch].join(".") property string compilerVersion: jdkVersionProbe.version ? jdkVersionProbe.version[1] : undefined property var compilerVersionParts: compilerVersion ? compilerVersion.split(/[\._]/).map(function(item) { return parseInt(item, 10); }) : [] property int compilerVersionMajor: compilerVersionParts[0] property int compilerVersionMinor: compilerVersionParts[1] property int compilerVersionPatch: compilerVersionParts[2] property int compilerVersionUpdate: compilerVersionParts[3] property string languageVersion PropertyOptions { name: "languageVersion" description: "Java language version to interpret source code as" } property string runtimeVersion PropertyOptions { name: "runtimeVersion" description: "version of the Java runtime to generate compatible bytecode for" } property var manifest: { return { "Manifest-Version": "1.0", "Class-Path": manifestClassPath ? manifestClassPath.join(" ") : undefined }; } PropertyOptions { name: "manifest" description: "properties to add to the manifest file when building a JAR" } PropertyOptions { name: "manifestFile" description: "Use files tagged \"java.manifest\" instead." removalVersion: "1.9" } property stringList manifestClassPath PropertyOptions { name: "manifestClassPath" description: "entries to add to the manifest's Class-Path when building a JAR" } property bool warningsAsErrors: false property pathList jdkIncludePaths: { var paths = []; if (isAppleJava) { paths.push(FileInfo.joinPaths(qbs.sysroot, "/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers")); } else { paths.push(FileInfo.joinPaths(jdkPath, "include")); var hostOS = qbs.hostOS.contains("windows") ? qbs.hostOS.concat(["win32"]) : qbs.hostOS; var platforms = ["win32", "darwin", "linux", "bsd", "solaris"]; for (var i = 0; i < platforms.length; ++i) { if (hostOS.contains(platforms[i])) { // Corresponds to JDK_INCLUDE_SUBDIR in the JDK Makefiles paths.push(FileInfo.joinPaths(jdkPath, "include", platforms[i])); break; } } } return paths; } // Internal properties property path classFilesDir: FileInfo.joinPaths(product.buildDirectory, "classes") property path internalClassFilesDir: FileInfo.joinPaths(product.buildDirectory, ".classes") property bool isAppleJava: qbs.hostOS.contains("darwin") && (compilerVersionMajor < 1 || (compilerVersionMajor === 1 && compilerVersionMinor < 7)) // https://developer.apple.com/library/content/documentation/Java/Conceptual/Java14Development/02-JavaDevTools/JavaDevTools.html // tools.jar does not exist. Classes usually located here are instead included in classes.jar. // The same is true for rt.jar, although not mentioned in the documentation property path classesJarPath: { if (isAppleJava) return FileInfo.joinPaths(jdkPath, "bundle", "Classes", "classes.jar"); } property path runtimeJarPath: { if (compilerVersionMajor >= 9) return undefined; if (classesJarPath) return classesJarPath; return FileInfo.joinPaths(jdkPath, "jre", "lib", "rt.jar"); } property path toolsJarPath: { if (compilerVersionMajor >= 9) return undefined; if (classesJarPath) return classesJarPath; return FileInfo.joinPaths(jdkPath, "lib", "tools.jar"); } validate: { var validator = new ModUtils.PropertyValidator("java"); validator.setRequiredProperty("jdkPath", jdkPath); validator.setRequiredProperty("compilerVersion", compilerVersion); validator.setRequiredProperty("compilerVersionParts", compilerVersionParts); validator.setRequiredProperty("compilerVersionMajor", compilerVersionMajor); validator.setRequiredProperty("compilerVersionMinor", compilerVersionMinor); if (Utilities.versionCompare(version, "9") < 0) validator.setRequiredProperty("compilerVersionUpdate", compilerVersionUpdate); validator.addVersionValidator("compilerVersion", compilerVersion ? compilerVersion.replace("_", ".") : undefined, 3, 4); validator.addRangeValidator("compilerVersionMajor", compilerVersionMajor, 1); validator.addRangeValidator("compilerVersionMinor", compilerVersionMinor, 0); validator.addRangeValidator("compilerVersionPatch", compilerVersionPatch, 0); if (Utilities.versionCompare(version, "9") < 0) validator.addRangeValidator("compilerVersionUpdate", compilerVersionUpdate, 0); validator.validate(); } FileTagger { patterns: "*.java" fileTags: ["java.java"] } FileTagger { patterns: ["*.mf"] fileTags: ["java.manifest"] } Group { name: "io.qt.qbs.internal.java-helper" files: { return JavaUtils.helperFullyQualifiedNames("java").map(function(name) { return FileInfo.joinPaths(path, name + ".java"); }); } fileTags: ["java.java-internal"] } Rule { multiplex: true inputs: ["java.java-internal"] outputFileTags: ["java.class-internal"] outputArtifacts: { return JavaUtils.helperOutputArtifacts(product); } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "compilerFilePath"), JavaUtils.javacArguments(product, inputs, JavaUtils.helperOverrideArgs(product, "javac"))); cmd.ignoreDryRun = true; cmd.silent = true; return [cmd]; } } Rule { multiplex: true inputs: ["java.java"] inputsFromDependencies: ["java.jar"] explicitlyDependsOn: ["java.class-internal"] outputFileTags: ["java.class"].concat(_tagJniHeaders ? ["hpp"] : []) // Annotations can produce additional java source files. Ignored for now. outputArtifacts: { var artifacts = JavaUtils.outputArtifacts(product, inputs); if (!product.java._tagJniHeaders) { for (var i = 0; i < artifacts.length; ++i) { var a = artifacts[i]; if (Array.isArray(a.fileTags)) a.fileTags = a.fileTags.filter(function(tag) { return tag != "hpp"; }); } } return artifacts; } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "compilerFilePath"), JavaUtils.javacArguments(product, inputs)); cmd.description = "Compiling Java sources"; cmd.highlight = "compiler"; return [cmd]; } } Rule { inputs: ["java.class", "java.manifest"] multiplex: true Artifact { fileTags: ["java.jar"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".jar") } prepare: { var i, key; var flags = "cf"; var args = [output.filePath]; var aggregateManifest = {}; var manifestFiles = (inputs["java.manifest"] || []).map(function (a) { return a.filePath; }); manifestFiles.forEach(function (manifestFile) { var mf = JavaUtils.manifestContents(manifestFile); for (key in mf) { if (mf.hasOwnProperty(key)) { var oldValue = aggregateManifest[key]; var newValue = mf[key]; if (oldValue !== undefined && oldValue !== newValue) { throw new Error("Conflicting values '" + oldValue + "' and '" + newValue + "' for manifest file key '" + key + "'"); } aggregateManifest[key] = newValue; } } }); // Add local key-value pairs (overrides equivalent keys specified in the file if // one was given) var manifest = product.java.manifest; for (key in manifest) { if (manifest.hasOwnProperty(key)) aggregateManifest[key] = manifest[key]; } for (key in aggregateManifest) { if (aggregateManifest.hasOwnProperty(key) && aggregateManifest[key] === undefined) delete aggregateManifest[key]; } // Use default manifest unless we actually have properties to set var needsManifestFile = manifestFiles.length > 0 || aggregateManifest !== {"Manifest-Version": "1.0"}; var manifestFile = FileInfo.joinPaths(product.buildDirectory, "manifest.mf"); var mf; try { mf = new TextFile(manifestFile, TextFile.WriteOnly); // Ensure that manifest version comes first mf.write("Manifest-Version: " + (aggregateManifest["Manifest-Version"] || "1.0") + "\n"); delete aggregateManifest["Manifest-Version"]; for (key in aggregateManifest) mf.write(key + ": " + aggregateManifest[key] + "\n"); mf.write("\n"); } finally { if (mf) { mf.close(); } } if (needsManifestFile) { flags += "m"; args.push(manifestFile); } var entryPoint = ModUtils.moduleProperty(product, "entryPoint"); var entryPoint = product.entryPoint; if (entryPoint) { flags += "e"; args.push(entryPoint); } args.unshift(flags); var otherFlags = ModUtils.moduleProperty(product, "additionalJarFlags"); if (otherFlags) args = args.concat(otherFlags); for (i in inputs["java.class"]) args.push(FileInfo.relativePath(ModUtils.moduleProperty(product, "classFilesDir"), inputs["java.class"][i].filePath)); var cmd = new Command(ModUtils.moduleProperty(product, "jarFilePath"), args); cmd.workingDirectory = ModUtils.moduleProperty(product, "classFilesDir"); cmd.description = "building " + FileInfo.fileName(output.fileName); cmd.highlight = "linker"; return cmd; } } } qbs-src-1.13.1/share/qbs/modules/java/io/000077500000000000000000000000001347155106100200415ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/java/io/qt/000077500000000000000000000000001347155106100204655ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/java/io/qt/qbs/000077500000000000000000000000001347155106100212525ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/java/io/qt/qbs/Artifact.java000066400000000000000000000050161347155106100236540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Artifact { private String filePath; private List fileTags; public Artifact(String filePath) { if (filePath == null) throw new IllegalArgumentException("filePath"); this.filePath = filePath; this.fileTags = new ArrayList(); } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; } public List getFileTags() { return Collections.unmodifiableList(fileTags); } public void setFileTags(List fileTags) { this.fileTags = new ArrayList(fileTags); } public void addFileTag(String fileTag) { this.fileTags.add(fileTag); } public void removeFileTag(String fileTag) { this.fileTags.remove(fileTag); } public void clearFileTags() { this.fileTags.clear(); } } qbs-src-1.13.1/share/qbs/modules/java/io/qt/qbs/ArtifactListJsonWriter.java000066400000000000000000000130271347155106100265400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.List; /** * This uses a custom JSON implementation because the Java Standard Library does * not yet have native support for JSON, and only minimal support is required * here. */ public class ArtifactListJsonWriter implements ArtifactListWriter { private static final int TAB_WIDTH = 4; // based on escapeString from qtbase/qjsonwriter.cpp private static String escapeString(String s) { String out = ""; for (int i = 0; i < s.length();) { int u = s.codePointAt(i); // unpaired surrogate if (u >= Character.MIN_SURROGATE && u <= Character.MAX_SURROGATE) { out += "\ufffd"; i += Character.charCount(u); continue; } if (u < 0x80) { if (u < 0x20 || u == 0x22 || u == 0x5c) { out += "\\"; switch (u) { case 0x22: out += "\""; break; case 0x5c: out += "\\"; break; case 0x8: out += "b"; break; case 0xc: out += "f"; break; case 0xa: out += "n"; break; case 0xd: out += "r"; break; case 0x9: out += "t"; break; default: out += "u"; out += "0"; out += "0"; String hex = Integer.toHexString(u); if (hex.length() == 1) out += "0"; out += hex; break; } } else { out += s.substring(i, i + Character.charCount(u)); } } else { out += s.substring(i, i + Character.charCount(u)); } i += Character.charCount(u); } return out; } private static void writeString(PrintStream printWriter, String s) { printWriter.print("\""); printWriter.print(escapeString(s)); printWriter.print("\""); } private static void writeIndent(PrintStream printWriter, int level) { for (int i = 0; i < level * TAB_WIDTH; ++i) { printWriter.print(" "); } } private static void writeArtifact(Artifact artifact, PrintStream printWriter, int indentLevel, Boolean comma) { writeIndent(printWriter, indentLevel++); printWriter.print("{\n"); writeIndent(printWriter, indentLevel); writeString(printWriter, "filePath"); printWriter.print(": "); writeString(printWriter, artifact.getFilePath()); printWriter.println(","); writeIndent(printWriter, indentLevel); writeString(printWriter, "fileTags"); printWriter.print(": ["); for (int i = 0; i < artifact.getFileTags().size(); ++i) { writeString(printWriter, artifact.getFileTags().get(i)); if (i != artifact.getFileTags().size() - 1) printWriter.print(", "); } printWriter.println("]"); writeIndent(printWriter, --indentLevel); printWriter.println("}" + (comma ? "," : "")); } @Override public void write(List artifacts, OutputStream outputStream) throws IOException { PrintStream printWriter = new PrintStream(outputStream); printWriter.print("[\n"); for (int i = 0; i < artifacts.size(); ++i) { writeArtifact(artifacts.get(i), printWriter, 1, i != artifacts.size() - 1); } printWriter.println("]"); } } qbs-src-1.13.1/share/qbs/modules/java/io/qt/qbs/ArtifactListWriter.java000066400000000000000000000033441347155106100257070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs; import java.io.IOException; import java.io.OutputStream; import java.util.List; public interface ArtifactListWriter { void write(List artifacts, OutputStream outputStream) throws IOException; } qbs-src-1.13.1/share/qbs/modules/java/io/qt/qbs/tools/000077500000000000000000000000001347155106100224125ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/java/io/qt/qbs/tools/JavaCompilerScannerTool.java000066400000000000000000000041201347155106100277760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools; import io.qt.qbs.tools.utils.JavaCompilerScanner; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; public class JavaCompilerScannerTool { public static void main(String[] args) { try { JavaCompilerScanner scanner = new JavaCompilerScanner(); int result = scanner.run(new ArrayList(Arrays.asList(args))); scanner.write(System.out); System.exit(result); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } } qbs-src-1.13.1/share/qbs/modules/java/io/qt/qbs/tools/utils/000077500000000000000000000000001347155106100235525ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/java/io/qt/qbs/tools/utils/JavaCompilerOptions.java000066400000000000000000000077101347155106100303520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools.utils; import javax.lang.model.SourceVersion; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class JavaCompilerOptions { private final List recognizedOptions; private final List classNames; private final List files; private JavaCompilerOptions(List recognizedOptions, List classNames, List files) { this.recognizedOptions = recognizedOptions; this.classNames = classNames; this.files = files; } public static JavaCompilerOptions parse(JavaCompiler compiler, JavaFileManager fileManager, String... arguments) { List recognizedOptions = new ArrayList(); List classNames = new ArrayList(); List files = new ArrayList(); for (int i = 0; i < arguments.length; ++i) { int argumentCount = compiler.isSupportedOption(arguments[i]); if (argumentCount < 0) argumentCount = fileManager.isSupportedOption(arguments[i]); if (argumentCount >= 0) { // isSupportedOption() returns 1 for -Xlint* in Java 9. Bug? if (arguments[i].startsWith("-Xlint")) argumentCount = 0; for (int j = 0; j < argumentCount + 1; ++j) { if (i + j >= arguments.length) { throw new IllegalArgumentException(arguments[i]); } recognizedOptions.add(arguments[i + j]); } i += argumentCount; } else { File file = new File(arguments[i]); if (file.exists()) files.add(file); else if (SourceVersion.isName(arguments[i])) classNames.add(arguments[i]); else throw new IllegalArgumentException(arguments[i]); } } return new JavaCompilerOptions(recognizedOptions, classNames, files); } public List getRecognizedOptions() { return Collections.unmodifiableList(recognizedOptions); } public List getFiles() { return Collections.unmodifiableList(files); } public List getClassNames() { return Collections.unmodifiableList(classNames); } } qbs-src-1.13.1/share/qbs/modules/java/io/qt/qbs/tools/utils/JavaCompilerScanner.java000066400000000000000000000110231347155106100303000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools.utils; import io.qt.qbs.*; import javax.tools.*; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.*; public class JavaCompilerScanner { private List artifacts = new ArrayList(); private ArtifactListWriter writer = new ArtifactListJsonWriter(); public List getArtifacts() { return this.artifacts; } public int run(List compilerArguments) { artifacts.clear(); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager standardFileManager = compiler .getStandardFileManager(null, null, null); final JavaFileManager fileManager = new ForwardingJavaFileManager( standardFileManager) { @Override public JavaFileObject getJavaFileForOutput( JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { JavaFileObject o = super.getJavaFileForOutput(location, className, kind, sibling); Artifact artifact = new Artifact(new File(o.toUri() .getSchemeSpecificPart()).toString()); if (kind.equals(JavaFileObject.Kind.CLASS)) { artifact.addFileTag("java.class"); } else if (kind.equals(JavaFileObject.Kind.SOURCE)) { artifact.addFileTag("java.java"); } artifacts.add(artifact); return new NullFileObject(o); } @Override public FileObject getFileForOutput( JavaFileManager.Location location, String packageName, String relativeName, FileObject sibling) throws IOException { FileObject o = super.getFileForOutput(location, packageName, relativeName, sibling); Artifact artifact = new Artifact(new File(o.toUri() .getSchemeSpecificPart()).toString()); if (o.getName().endsWith(".h")) { artifact.addFileTag("hpp"); } artifacts.add(artifact); return new NullFileObject(o); } }; final JavaCompilerOptions options = JavaCompilerOptions .parse(compiler, standardFileManager, compilerArguments .toArray(new String[compilerArguments.size()])); return compiler.getTask( null, fileManager, null, options.getRecognizedOptions(), options.getClassNames(), standardFileManager.getJavaFileObjectsFromFiles(options .getFiles())).call() ? 0 : 1; } public void write(OutputStream outputStream) throws IOException { writer.write(getArtifacts(), outputStream); } } qbs-src-1.13.1/share/qbs/modules/java/io/qt/qbs/tools/utils/NullFileObject.java000066400000000000000000000104021347155106100272530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools.utils; import javax.lang.model.element.Modifier; import javax.lang.model.element.NestingKind; import javax.tools.FileObject; import javax.tools.JavaFileObject; import java.io.*; import java.net.URI; /** * Represents a FileObject that discards its output when written. */ public class NullFileObject implements FileObject, JavaFileObject { FileObject obj; public NullFileObject(FileObject obj) { this.obj = obj; } @Override public URI toUri() { return obj.toUri(); } @Override public String getName() { return obj.getName(); } @Override public InputStream openInputStream() throws IOException { return obj.openInputStream(); } @Override public OutputStream openOutputStream() throws IOException { return new OutputStream() { @Override public void write(int b) throws IOException { } }; } @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException { return obj.openReader(ignoreEncodingErrors); } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return obj.getCharContent(ignoreEncodingErrors); } @Override public Writer openWriter() throws IOException { return new Writer() { @Override public void write(char[] cbuf, int off, int len) throws IOException { } @Override public void flush() throws IOException { } @Override public void close() throws IOException { } }; } @Override public long getLastModified() { return obj.getLastModified(); } @Override public boolean delete() { return true; } @Override public Kind getKind() { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).getKind(); } throw new UnsupportedOperationException(); } @Override public boolean isNameCompatible(String simpleName, Kind kind) { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).isNameCompatible(simpleName, kind); } throw new UnsupportedOperationException(); } @Override public NestingKind getNestingKind() { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).getNestingKind(); } throw new UnsupportedOperationException(); } @Override public Modifier getAccessLevel() { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).getAccessLevel(); } throw new UnsupportedOperationException(); } } qbs-src-1.13.1/share/qbs/modules/java/utils.js000066400000000000000000000327771347155106100211500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); var WindowsUtils = require("qbs.WindowsUtils"); function is64bitProcess() { var y = jdkRootRegistryKey(true); var n = jdkRootRegistryKey(false); y = Utilities.getNativeSetting(y + "\\" + Utilities.getNativeSetting(y, "CurrentVersion"), "JavaHome"); n = Utilities.getNativeSetting(n + "\\" + Utilities.getNativeSetting(n, "CurrentVersion"), "JavaHome"); return y !== n; } function useWow64Key(arch) { var wow64 = false; switch (arch) { case "x86_64": case "ia64": // QTBUG-3845 if (!is64bitProcess()) return undefined; break; case "x86": case "armv7": wow64 = is64bitProcess(); break; } return wow64; } function jdkRootRegistryKey(wow64) { // If an architecture is specified, search the appropriate key for that architecture, // on this version of Windows (i.e. WOW64 or not) if compatible, // otherwise get both keys since any JDK will be usable if (wow64 === undefined) return undefined; return FileInfo.toWindowsSeparators(FileInfo.joinPaths("HKEY_LOCAL_MACHINE", "SOFTWARE", (wow64 ? "Wow6432Node" : undefined), "JavaSoft", "Java Development Kit")); } function findJdkPath(hostOS, arch, environmentPaths, searchPaths) { var i; for (var key in environmentPaths) { if (environmentPaths[key]) { return environmentPaths[key]; } } if (hostOS.contains("windows")) { var rootKey = jdkRootRegistryKey(useWow64Key(arch)); if (rootKey) { var current = Utilities.getNativeSetting(rootKey, "CurrentVersion"); // 1.8 etc. if (current) { var home = Utilities.getNativeSetting([rootKey, current].join("\\"), "JavaHome"); if (home) { return home; } } } return undefined; } if (hostOS.contains("macos")) { var p = new Process(); try { // We filter by architecture here so that we'll get a compatible JVM for JNI use. var args = []; if (arch) { // Hardcoding apple/macosx/macho here is fine because we know we're on macOS args.push("--arch", Utilities.canonicalTargetArchitecture(arch, undefined, "apple", "macosx", "macho")); } // --failfast doesn't print the default JVM if nothing matches the filter(s). var status = p.exec("/usr/libexec/java_home", args.concat(["--failfast"])); return status === 0 ? p.readStdOut().trim() : undefined; } finally { p.close(); } } if (hostOS.contains("unix")) { var requiredTools = ["javac", "java", "jar"]; for (i = 0; i < searchPaths.length; ++i) { function fullToolPath(tool) { return FileInfo.joinPaths(searchPaths[i], "bin", tool); } if (requiredTools.map(function(p) { return fullToolPath(p); }) .every(function(p) { return File.exists(p); })) { return searchPaths[i]; } } return undefined; } } function findJdkVersion(compilerFilePath) { var p = new Process(); try { p.exec(compilerFilePath, ["-version"]); var re = /^javac (([0-9]+(?:\.[0-9]+){2,2})(_([0-9]+))?)$/m; var match = p.readStdErr().trim().match(re); if (!match) match = p.readStdOut().trim().match(re); if (match !== null) return match; } finally { p.close(); } } function supportsGeneratedNativeHeaderFiles(product) { var compilerVersionMajor = ModUtils.moduleProperty(product, "compilerVersionMajor"); if (compilerVersionMajor === 1) { if (ModUtils.moduleProperty(product, "compilerVersionMinor") >= 8) { return true; } } return compilerVersionMajor > 1; } function javacArguments(product, inputs, overrides) { function getModuleProperty(product, propertyName, overrides) { if (overrides && overrides[propertyName]) return overrides[propertyName]; return ModUtils.moduleProperty(product, propertyName); } function getModuleProperties(product, propertyName, overrides) { if (overrides && overrides[propertyName]) return overrides[propertyName]; return ModUtils.moduleProperty(product, propertyName); } var i; var outputDir = getModuleProperty(product, "classFilesDir", overrides); var classPaths = [outputDir]; var additionalClassPaths = getModuleProperties(product, "additionalClassPaths", overrides); if (additionalClassPaths) classPaths = classPaths.concat(additionalClassPaths); for (i in inputs["java.jar"]) classPaths.push(inputs["java.jar"][i].filePath); var debugArg = product.moduleProperty("qbs", "buildVariant") === "debug" ? "-g" : "-g:none"; var pathListSeparator = product.moduleProperty("qbs", "pathListSeparator"); var args = [ "-classpath", classPaths.join(pathListSeparator), "-s", product.buildDirectory, debugArg, "-d", outputDir ]; if (supportsGeneratedNativeHeaderFiles(product)) args.push("-h", product.buildDirectory); var runtimeVersion = getModuleProperty(product, "runtimeVersion", overrides); if (runtimeVersion) args.push("-target", runtimeVersion); var languageVersion = getModuleProperty(product, "languageVersion", overrides); if (languageVersion) args.push("-source", languageVersion); var bootClassPaths = getModuleProperties(product, "bootClassPaths", overrides); if (bootClassPaths && bootClassPaths.length > 0 && (!runtimeVersion || Utilities.versionCompare(runtimeVersion, "9") < 0)) { args.push("-bootclasspath", bootClassPaths.join(pathListSeparator)); } if (!getModuleProperty(product, "enableWarnings", overrides)) args.push("-nowarn"); if (getModuleProperty(product, "warningsAsErrors", overrides)) args.push("-Werror"); var otherFlags = getModuleProperties(product, "additionalCompilerFlags", overrides); if (otherFlags) args = args.concat(otherFlags); for (i in inputs["java.java"]) args.push(inputs["java.java"][i].filePath); for (i in inputs["java.java-internal"]) args.push(inputs["java.java-internal"][i].filePath); return args; } /** * Returns a list of fully qualified Java class names for the compiler helper tool. * * @param type @c java to return names of sources, @c to return names of compiled classes */ function helperFullyQualifiedNames(type) { var names = [ "io/qt/qbs/Artifact", "io/qt/qbs/ArtifactListJsonWriter", "io/qt/qbs/ArtifactListWriter", "io/qt/qbs/tools/JavaCompilerScannerTool", "io/qt/qbs/tools/utils/JavaCompilerOptions", "io/qt/qbs/tools/utils/JavaCompilerScanner", "io/qt/qbs/tools/utils/JavaCompilerScanner$1", "io/qt/qbs/tools/utils/NullFileObject", "io/qt/qbs/tools/utils/NullFileObject$1", "io/qt/qbs/tools/utils/NullFileObject$2", ]; if (type === "java") { return names.filter(function (name) { return !name.contains("$"); }); } else if (type === "class") { return names; } } function helperOutputArtifacts(product) { File.makePath(ModUtils.moduleProperty(product, "internalClassFilesDir")); return helperFullyQualifiedNames("class").map(function (name) { return { filePath: FileInfo.joinPaths(ModUtils.moduleProperty(product, "internalClassFilesDir"), name + ".class"), fileTags: ["java.class-internal"] }; }); } function helperOverrideArgs(product, tool) { var overrides = {}; if (tool === "javac") { // Build the helper tool with the same source and target version as the JDK it's being // compiled with. Both are irrelevant here since the resulting tool will only be run // with the same JDK as it was built with, and we know in advance the source is // compatible with all Java language versions from 1.6 and above. var jdkVersionArray = [product.java.compilerVersionMajor]; if (product.java.compilerVersionMajor < 9) jdkVersionArray.push(product.java.compilerVersionMinor); var jdkVersion = jdkVersionArray.join("."); overrides["languageVersion"] = jdkVersion; overrides["runtimeVersion"] = jdkVersion; // Build the helper tool's class files separately from the actual product's class files overrides["classFilesDir"] = ModUtils.moduleProperty(product, "internalClassFilesDir"); // Add tools.jar to the classpath as required for the tree scanner API var toolsJarPath = ModUtils.moduleProperty(product, "toolsJarPath"); if (toolsJarPath) overrides["additionalClassPaths"] = [toolsJarPath].concat( ModUtils.moduleProperty(product, "additionalClassPaths")); } // Inject the current JDK's runtime classes into the boot class path when building/running the // dependency scanner. This is normally not necessary but is important for Android platforms // where android.jar is the only JAR on the boot classpath and JSR 199 is unavailable. var rtJarPath = product.java.runtimeJarPath; overrides["bootClassPaths"] = (rtJarPath ? [rtJarPath] : []).concat( ModUtils.moduleProperty(product, "bootClassPaths")); return overrides; } function outputArtifacts(product, inputs) { // Handle the case where a product depends on Java but has no Java sources if (!inputs["java.java"] || inputs["java.java"].length === 0) return []; // We need to ensure that the output directory is created first, because the Java compiler // internally checks that it is present before performing any actions File.makePath(ModUtils.moduleProperty(product, "classFilesDir")); var process; try { process = new Process(); process.setWorkingDirectory( FileInfo.joinPaths(ModUtils.moduleProperty(product, "internalClassFilesDir"))); var sep = product.moduleProperty("qbs", "pathListSeparator"); var toolsJarPath = ModUtils.moduleProperty(product, "toolsJarPath"); var javaArgs = [ "-classpath", process.workingDirectory() + (toolsJarPath ? (sep + toolsJarPath) : ""), "io/qt/qbs/tools/JavaCompilerScannerTool", ]; process.exec(ModUtils.moduleProperty(product, "interpreterFilePath"), javaArgs .concat(javacArguments(product, inputs, helperOverrideArgs(product))), true); var out = JSON.parse(process.readStdOut()); console.error(process.readStdErr()); return out; } finally { if (process) process.close(); } } function manifestContents(filePath) { if (filePath === undefined) return undefined; var contents, file; try { file = new TextFile(filePath); contents = file.readAll(); } finally { if (file) { file.close(); } } if (contents) { var dict = {}; var lines = contents.split(/\r?\n/g).filter(function (line) { return line.length > 0; }); for (var i in lines) { var kv = lines[i].split(":"); if (kv.length !== 2) throw new Error("Syntax error in manifest file '" + filePath + "'; found \"" + lines[i] + "\" on line " + parseInt(i, 10) + "; expected format \"Key: Value\""); dict[kv[0].trim()] = kv[1].trim(); } return dict; } } qbs-src-1.13.1/share/qbs/modules/lex_yacc/000077500000000000000000000000001347155106100203005ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/lex_yacc/lexyacc.js000066400000000000000000000045211347155106100222700ustar00rootroot00000000000000var FileInfo = require("qbs.FileInfo"); var TextFile = require("qbs.TextFile"); function unquote(s) { return s.startsWith('"') && s.endsWith('"') ? s.substr(1, s.length - 2) : s; } function readLexOptions(filePath) { var result = {}; var f = new TextFile(filePath, TextFile.ReadOnly); var regex = /^%option\s+([^ \t=]+)(?:\s*=\s*(\S+))?/; while (!f.atEof()) { var line = f.readLine(); var m = regex.exec(line); if (!m) { if (line === "%%") break; continue; } result[m[1]] = m[2] || true; } f.close(); return result; } function lexOutputFilePath(input, posixFileName, options) { var outDir = input.lex_yacc.outputDir; var fileName; if (options.outfile) { fileName = unquote(options.outfile); } else if (options.prefix) { fileName = FileInfo.baseName(posixFileName) + '.' + unquote(options.prefix) + '.' + FileInfo.suffix(posixFileName); } else if (input.lex_yacc.uniqueSymbolPrefix) { fileName = input.baseName; fileName += posixFileName; } else { fileName = posixFileName; } return FileInfo.joinPaths(outDir, fileName); } function readYaccOptions(filePath) { var result = {}; var f = new TextFile(filePath, TextFile.ReadOnly); var regex = /^%output\s+(.+)/; while (!f.atEof()) { var line = f.readLine(); var m = regex.exec(line); if (!m) { if (line === "%%") break; continue; } result.output = m[1]; break; } f.close(); return result; } function yaccOutputFilePath(input, posixFileName, options) { var outDir = input.lex_yacc.outputDir; var fileName; if (options.output) { var outputFileName = unquote(options.output); var suffix = FileInfo.suffix(posixFileName); if (suffix === "c") { fileName = outputFileName; } else { fileName = FileInfo.completeBaseName(outputFileName) + '.' + suffix + FileInfo.suffix(outputFileName).slice(1); } } else if (input.lex_yacc.uniqueSymbolPrefix) { fileName = input.baseName + posixFileName.slice(1); } else { fileName = posixFileName; } return FileInfo.joinPaths(outDir, fileName); } qbs-src-1.13.1/share/qbs/modules/lex_yacc/lexyacc.qbs000066400000000000000000000075751347155106100224550ustar00rootroot00000000000000import "lexyacc.js" as HelperFunctions Module { Depends { name: "cpp" } property bool enableCompilerWarnings: false property string lexBinary: "lex" property string yaccBinary: "yacc" property string outputTag: "c" property bool uniqueSymbolPrefix: false property string lexOutputFilePath property string yaccOutputFilePath property stringList lexFlags: [] property stringList yaccFlags: [] readonly property string outputDir: product.buildDirectory + "/lexyacc" Rule { inputs: ["lex.input"] outputFileTags: [product.lex_yacc.outputTag] outputArtifacts: { var output = { fileTags: [product.lex_yacc.outputTag], lex_yacc: {}, }; var options = HelperFunctions.readLexOptions(input.filePath); if (!options.outfile && input.lex_yacc.lexOutputFilePath) { options.outfile = input.lex_yacc.lexOutputFilePath; output.lex_yacc.useOutfileFromModule = true; } output.filePath = HelperFunctions.lexOutputFilePath(input, "lex.yy.c", options); output.cpp = { includePaths: [].concat(input.cpp.includePaths, input.lex_yacc.outputDir), warningLevel: input.lex_yacc.enableCompilerWarnings ? "all" : "none", }; return [output]; } prepare: { var args = input.lex_yacc.lexFlags; if (output.lex_yacc.useOutfileFromModule) args.push("-o" + input.lex_yacc.lexOutputFilePath); else if (input.lex_yacc.uniqueSymbolPrefix) args.push("-P" + input.baseName, "-o" + output.filePath); args.push(input.filePath); var cmd = new Command(input.lex_yacc.lexBinary, args); cmd.workingDirectory = input.lex_yacc.outputDir; cmd.description = "generating " + output.fileName; return [cmd]; } } Rule { inputs: ["yacc.input"] outputFileTags: [product.lex_yacc.outputTag, "hpp"] outputArtifacts: { var src = { fileTags: [product.lex_yacc.outputTag], lex_yacc: {}, }; var options = HelperFunctions.readYaccOptions(input.filePath); if (!options.output && input.lex_yacc.yaccOutputFilePath) { options.output = input.lex_yacc.yaccOutputFilePath; src.lex_yacc.useOutputFromModule = true; } var hdr = { filePath: HelperFunctions.yaccOutputFilePath(input, "y.tab.h", options), fileTags: ["hpp"], }; src.filePath = HelperFunctions.yaccOutputFilePath(input, "y.tab.c", options); src.cpp = { includePaths: [].concat(input.cpp.includePaths, input.lex_yacc.outputDir), warningLevel: input.lex_yacc.enableCompilerWarnings ? "all" : "none", }; return [hdr, src]; } prepare: { var args = input.lex_yacc.yaccFlags; args.push("-d"); var impl = outputs[input.lex_yacc.outputTag][0]; if (impl.lex_yacc.useOutputFromModule) args.push("-o" + input.lex_yacc.yaccOutputFilePath); else if (input.lex_yacc.uniqueSymbolPrefix) args.push("-b", input.baseName, "-p", input.baseName); args.push(input.filePath); var cmd = new Command(input.lex_yacc.yaccBinary, args); cmd.workingDirectory = input.lex_yacc.outputDir; cmd.description = "generating " + impl.fileName + " and " + outputs["hpp"][0].fileName; return [cmd]; } } FileTagger { patterns: ["*.l"] fileTags: ["lex.input"]; } FileTagger { patterns: ["*.y"] fileTags: ["yacc.input"]; } } qbs-src-1.13.1/share/qbs/modules/nodejs/000077500000000000000000000000001347155106100177735ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/nodejs/NodeJS.qbs000066400000000000000000000142461347155106100216330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes Module { // JavaScript files which have been "processed" - currently this simply means "copied to output // directory" but might later include minification and obfuscation processing additionalProductTypes: ["nodejs_processed_js"].concat(applicationFile ? ["application"] : []) Probes.NodeJsProbe { id: nodejs searchPaths: toolchainInstallPath ? [toolchainInstallPath] : [] } Probes.NpmProbe { id: npm searchPaths: toolchainInstallPath ? [toolchainInstallPath] : [] interpreterPath: FileInfo.path(nodejs.filePath) } property path applicationFile PropertyOptions { name: "applicationFile" description: "file whose corresponding output will be executed when running the Node.js app" } Group { name: "Application file"; prefix: product.sourceDirectory + '/' files: nodejs.applicationFile ? [nodejs.applicationFile] : [] } property path toolchainInstallPath: { if (nodejs.path && npm.path && nodejs.path !== npm.path) throw("node and npm binaries do not belong to the same installation (" + nodejs.path + " vs " + npm.path + ")"); return nodejs.path || npm.path; } property path interpreterFileName: nodejs.fileName property path interpreterFilePath: nodejs.filePath property path packageManagerFileName: npm.fileName property path packageManagerFilePath: npm.filePath property path packageManagerBinPath: npm.npmBin property path packageManagerRootPath: npm.npmRoot property path packageManagerPrefixPath: npm.npmPrefix // private properties readonly property path compiledIntermediateDir: FileInfo.joinPaths(product.buildDirectory, "tmp", "nodejs.intermediate") setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, product.qbs.hostOS.contains("windows")); v.prepend(product.nodejs.toolchainInstallPath); v.set(); } setupRunEnvironment: { var v = new ModUtils.EnvironmentVariable("NODE_PATH", product.qbs.pathListSeparator, product.qbs.hostOS.contains("windows")); v.prepend(FileInfo.path(Environment.getEnv("QBS_RUN_FILE_PATH"))); v.set(); } FileTagger { patterns: ["*.js"] fileTags: ["js"] } validate: { var validator = new ModUtils.PropertyValidator("nodejs"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("interpreterFileName", interpreterFileName); validator.setRequiredProperty("interpreterFilePath", interpreterFilePath); validator.setRequiredProperty("packageManagerFileName", packageManagerFileName); validator.setRequiredProperty("packageManagerFilePath", packageManagerFilePath); validator.setRequiredProperty("packageManagerBinPath", packageManagerBinPath); validator.setRequiredProperty("packageManagerRootPath", packageManagerRootPath); validator.setRequiredProperty("packageManagerPrefixPath", packageManagerPrefixPath); validator.validate(); } Rule { inputs: ["js"] outputArtifacts: { var tags = ["nodejs_processed_js"]; if (input.fileTags.contains("application_js") || product.moduleProperty("nodejs", "applicationFile") === input.filePath) tags.push("application"); // Preserve directory structure of input files var intermediatePath = product.sourceDirectory; // Handle nodejs.compiledIntermediateDir (QBS-5 workaround) var compiled = product.moduleProperty("nodejs", "compiledIntermediateDir"); if (input.filePath.startsWith(compiled)) { intermediatePath = compiled; } intermediatePath = FileInfo.path(FileInfo.relativePath(intermediatePath, input.filePath)); return [{ filePath: FileInfo.joinPaths(product.destinationDirectory, intermediatePath, input.fileName), fileTags: tags }]; } outputFileTags: ["nodejs_processed_js", "application"] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "copying " + input.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } } qbs-src-1.13.1/share/qbs/modules/nodejs/nodejs.js000066400000000000000000000036021347155106100216140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var Process = require("qbs.Process"); function findLocation(packageManagerFilePath, location, nodejsPath) { var p = new Process(); try { if (nodejsPath) p.setEnv("PATH", nodejsPath); if (p.exec(packageManagerFilePath, [location, "-g"]) !== 0) console.error(p.readStdErr().trim()); return p.readStdOut().trim(); } finally { p.close(); } } qbs-src-1.13.1/share/qbs/modules/nsis/000077500000000000000000000000001347155106100174655ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/nsis/NSISModule.qbs000066400000000000000000000222771347155106100221300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Utilities Module { condition: qbs.targetOS.contains("windows") property path toolchainInstallPath: Utilities.getNativeSetting(registryKey) version: (versionMajor !== undefined && versionMinor !== undefined) ? (versionMajor + "." + versionMinor) : undefined property var versionParts: [ versionMajor, versionMinor, versionPatch, versionBuild ] property int versionMajor: Utilities.getNativeSetting(registryKey, "VersionMajor") property int versionMinor: Utilities.getNativeSetting(registryKey, "VersionMinor") property int versionPatch: Utilities.getNativeSetting(registryKey, "VersionBuild") property int versionBuild: Utilities.getNativeSetting(registryKey, "VersionRevision") property string compilerName: "makensis" property string compilerPath: compilerName property string warningLevel: "normal" PropertyOptions { name: "warningLevel" allowedValues: ["none", "normal", "errors", "warnings", "info", "all"] } property bool disableConfig: false PropertyOptions { name: "disableConfig" description: "disable inclusion of nsisconf.nsh" } property bool enableQbsDefines: true PropertyOptions { name: "enableQbsDefines" description: "built-in variables that are defined when using the NSIS compiler" } property stringList defines PropertyOptions { name: "defines" description: "variables that are defined when using the NSIS compiler" } property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional flags for the NSIS compiler" } property string compressor: "default" PropertyOptions { name: "compressor" description: "the compression algorithm used to compress files/data in the installer" allowedValues: ["default", "zlib", "zlib-solid", "bzip2", "bzip2-solid", "lzma", "lzma-solid"] } property string executableSuffix: ".exe" // Private properties property string registryKey: { if (!qbs.hostOS.contains("windows")) return undefined; var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS" ]; for (var i in keys) { if (Utilities.getNativeSetting(keys[i])) return keys[i]; } } validate: { var validator = new ModUtils.PropertyValidator("nsis"); // Only *require* the toolchain install path on Windows // On other (Unix-like) operating systems it'll probably be in the PATH if (qbs.targetOS.contains("windows")) validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); validator.setRequiredProperty("versionBuild", versionBuild); validator.addVersionValidator("version", version, 2, 4); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); validator.addRangeValidator("versionBuild", versionBuild, 0); validator.validate(); } setupBuildEnvironment: { if (toolchainInstallPath) { var v = new ModUtils.EnvironmentVariable("PATH", ";", true); v.prepend(product.nsis.toolchainInstallPath); v.prepend(FileInfo.joinPaths(product.nsis.toolchainInstallPath, "bin")); v.set(); } } // NSIS Script File FileTagger { patterns: ["*.nsi"] fileTags: ["nsi"] } // NSIS Header File FileTagger { patterns: ["*.nsh"] fileTags: ["nsh"] } Rule { id: nsisCompiler multiplex: true inputs: ["nsi"] auxiliaryInputs: ["installable"] Artifact { fileTags: ["nsissetup", "application"] filePath: product.destinationDirectory + "/" + product.targetName + ModUtils.moduleProperty(product, "executableSuffix") } prepare: { var i; var args = []; // Prefix character for makensis options var opt = product.moduleProperty("qbs", "hostOS").contains("windows") ? "/" : "-"; if (ModUtils.moduleProperty(product, "disableConfig")) { args.push(opt + "NOCONFIG"); } var warningLevel = ModUtils.moduleProperty(product, "warningLevel"); var warningLevels = ["none", "errors", "warnings", "info", "all"]; if (warningLevel !== "normal") { var level = warningLevels.indexOf(warningLevel); if (level < 0) { throw("Unexpected warning level '" + warningLevel + "'."); } else { args.push(opt + "V" + level); } } var enableQbsDefines = ModUtils.moduleProperty(product, "enableQbsDefines") if (enableQbsDefines) { var map = { "project.": project, "product.": product }; for (var prefix in map) { var obj = map[prefix]; for (var prop in obj) { var val = obj[prop]; if (typeof val !== 'function' && typeof val !== 'object' && !prop.startsWith("_")) { args.push(opt + "D" + prefix + prop + "=" + val); } } } // Users are likely to need this var arch = product.moduleProperty("qbs", "architecture"); args.push(opt + "Dqbs.architecture=" + arch); // Helper define for alternating between 32-bit and 64-bit logic if (arch === "x86_64" || arch === "ia64") { args.push(opt + "DWin64"); } } // User-supplied defines var defines = ModUtils.moduleProperty(product, "defines"); for (i in defines) { args.push(opt + "D" + defines[i]); } // User-supplied flags var flags = ModUtils.moduleProperty(product, "compilerFlags"); for (i in flags) { args.push(flags[i]); } // Override the compression algorithm if needed var compressor = ModUtils.moduleProperty(product, "compressor"); if (compressor !== "default") { var compressorFlag = opt + "XSetCompressor /FINAL "; if (compressor.endsWith("-solid")) { compressorFlag += "/SOLID "; } args.push(compressorFlag + compressor.split('-')[0]); } var inputFileNames = []; for (i in inputs.nsi) { inputFileNames.push(inputs.nsi[i].fileName); args.push(FileInfo.toNativeSeparators(inputs.nsi[i].filePath, product.moduleProperty("qbs", "hostOS"))); } // Output file name - this goes last to override any OutFile command in the script args.push(opt + "XOutFile " + output.filePath); var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args); cmd.description = "compiling " + inputFileNames.join(", "); cmd.highlight = "compiler"; cmd.workingDirectory = FileInfo.path(output.filePath); return cmd; } } } qbs-src-1.13.1/share/qbs/modules/pkgconfig/000077500000000000000000000000001347155106100204605ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/pkgconfig/pkgconfig.qbs000066400000000000000000000047021347155106100231410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import qbs import qbs.File import qbs.Probes Module { Probes.BinaryProbe { id: pkgconfigProbe names: "pkg-config" } property string executableFilePath: pkgconfigProbe.filePath property stringList libDirs property bool staticMode: false validate: { if (!executableFilePath) { throw "No pkg-config executable found. " + "Please set modules.pkgconfig.executableFilePath."; } if (!File.exists(executableFilePath)) throw "The pkg-config executable '" + executableFilePath + "' does not exist."; } } qbs-src-1.13.1/share/qbs/modules/protobuf/000077500000000000000000000000001347155106100203515ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/protobuf/cpp/000077500000000000000000000000001347155106100211335ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/protobuf/cpp/protobufcpp.qbs000066400000000000000000000026701347155106100242120ustar00rootroot00000000000000import qbs import qbs.File import qbs.FileInfo import qbs.Probes import "../protobufbase.qbs" as ProtobufBase import "../protobuf.js" as HelperFunctions ProtobufBase { property string includePath: includeProbe.path property string libraryPath: libraryProbe.path Depends { name: "cpp" } cpp.libraryPaths: [libraryPath] cpp.dynamicLibraries: qbs.targetOS.contains("unix") ? ["protobuf", "pthread"] : ["protobuf"] cpp.includePaths: [outputDir, includePath] Rule { inputs: ["protobuf.input"] outputFileTags: ["hpp", "cpp"] outputArtifacts: { return [ HelperFunctions.cppArtifact(input.protobuf.cpp, product, input, "hpp", ".pb.h"), HelperFunctions.cppArtifact(input.protobuf.cpp, product, input, "cpp", ".pb.cc") ]; } prepare: HelperFunctions.doPrepare(input.protobuf.cpp, product, input, outputs, "cpp") } validate: { baseValidate(); if (!HelperFunctions.checkPath(includePath)) throw "Can't find cpp protobuf include files. Please set the includePath property."; if (!HelperFunctions.checkPath(libraryPath)) throw "Can't find cpp protobuf library. Please set the libraryPath property."; } Probes.IncludeProbe { id: includeProbe names: "google/protobuf/message.h" } Probes.LibraryProbe { id: libraryProbe names: "protobuf" } } qbs-src-1.13.1/share/qbs/modules/protobuf/objc/000077500000000000000000000000001347155106100212665ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/protobuf/objc/protobufobjc.qbs000066400000000000000000000040661347155106100245010ustar00rootroot00000000000000import qbs import qbs.File import qbs.FileInfo import qbs.Probes import "../protobufbase.qbs" as ProtobufBase import "../protobuf.js" as HelperFunctions ProtobufBase { property string includePath: includeProbe.path property string libraryPath: libraryProbe.path property string frameworkPath: frameworkProbe.path Depends { name: "cpp" } // library build Properties { condition: !frameworkPath cpp.includePaths: [outputDir, includePath] cpp.libraryPaths: [libraryPath] cpp.frameworks: ["Foundation"] cpp.dynamicLibraries: ["ProtocolBuffers"] } // framework build Properties { condition: frameworkPath cpp.includePaths: [outputDir] cpp.frameworkPaths: [frameworkPath] cpp.frameworks: ["Foundation", "Protobuf"] cpp.defines: ["GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS"] } Rule { inputs: ["protobuf.input"] outputFileTags: ["hpp", "objc"] outputArtifacts: { return [ HelperFunctions.objcArtifact(input.protobuf.objc, product, input, "hpp", ".pbobjc.h"), HelperFunctions.objcArtifact(input.protobuf.objc, product, input, "objc", ".pbobjc.m") ]; } prepare: HelperFunctions.doPrepare(input.protobuf.objc, product, input, outputs, "objc") } validate: { baseValidate(); if (!HelperFunctions.checkPath(frameworkPath)) { if (!HelperFunctions.checkPath(includePath)) throw "Can't find objective-c protobuf include files. Please set the includePath or frameworkPath property."; if (!HelperFunctions.checkPath(libraryPath)) throw "Can't find objective-c protobuf library. Please set the libraryPath or frameworkPath property."; } } Probes.IncludeProbe { id: includeProbe names: "GPBMessage.h" } Probes.LibraryProbe { id: libraryProbe names: "ProtocolBuffers" } Probes.FrameworkProbe { id: frameworkProbe names: ["Protobuf"] } } qbs-src-1.13.1/share/qbs/modules/protobuf/protobuf.js000066400000000000000000000100101347155106100225370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov ** Contact: abbapoh@gmail.com ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var checkPath = function(path) { return path && File.exists(path) }; function toCamelCase(str){ return str.split('_').map(function(word, index) { // If it is the first word make sure to lowercase all the chars. if (index === 0) { return word.toLowerCase(); } // If it is not the first word only upper case the first char and lowercase the rest. return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); }).join(''); } function getOutputDir(module, product, input) { var outputDir = module.outputDir; var importPaths = module.importPaths; if (importPaths.length !== 0) { var canonicalInput = File.canonicalFilePath(FileInfo.path(input.filePath)); for (var i = 0; i < importPaths.length; ++i) { path = File.canonicalFilePath(importPaths[i]); if (canonicalInput.startsWith(path)) { return outputDir + "/" + FileInfo.relativePath(path, canonicalInput); } } } return outputDir; } function cppArtifact(module, product, input, tag, suffix) { var outputDir = getOutputDir(module, product, input); return { fileTags: [tag], filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix, cpp: { includePaths: [].concat(input.cpp.includePaths, outputDir), warningLevel: "none", } }; } function objcArtifact(module, product, input, tag, suffix) { var outputDir = getOutputDir(module, product, input); return { fileTags: [tag], filePath: outputDir + "/" + toCamelCase(FileInfo.baseName(input.fileName)) + suffix, cpp: { includePaths: [].concat(input.cpp.includePaths, outputDir), warningLevel: "none", } } } function doPrepare(module, product, input, outputs, lang) { var outputDir = module.outputDir; var args = []; args.push("--" + lang + "_out", outputDir); var importPaths = module.importPaths; if (importPaths.length === 0) importPaths = [FileInfo.path(input.filePath)]; importPaths.forEach(function(path) { if (!FileInfo.isAbsolutePath(path)) path = FileInfo.joinPaths(product.sourceDirectory, path); args.push("--proto_path", path); }); args.push(input.filePath); var cmd = new Command(module.protocBinary, args); cmd.highlight = "codegen"; cmd.description = "generating " + lang + " files for " + input.fileName; return [cmd]; } qbs-src-1.13.1/share/qbs/modules/protobuf/protobufbase.qbs000066400000000000000000000014271347155106100235570ustar00rootroot00000000000000import qbs import qbs.File import qbs.FileInfo import qbs.Probes import "protobuf.js" as HelperFunctions Module { property string protocBinary: protocProbe.filePath property pathList importPaths: [] property string outputDir: product.buildDirectory + "/protobuf" readonly property string protobufRoot: FileInfo.path(FileInfo.path(protocBinary)) readonly property var baseValidate: { return function() { if (!File.exists(protocBinary)) throw "Can't find protoc binary. Please set the protocBinary property or make sure it is found in PATH"; } } FileTagger { patterns: ["*.proto"] fileTags: ["protobuf.input"]; } Probes.BinaryProbe { id: protocProbe names: ["protoc"] } } qbs-src-1.13.1/share/qbs/modules/qbs/000077500000000000000000000000001347155106100172765ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/qbs/common.qbs000066400000000000000000000241501347155106100212770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.FileInfo import qbs.ModUtils import qbs.PathTools import qbs.Utilities Module { readonly property string configurationName: "default" property string defaultBuildVariant: { switch (configurationName.toLowerCase()) { case "release": return "release"; default: return "debug"; } } property string buildVariant: defaultBuildVariant property bool enableDebugCode: buildVariant == "debug" property bool debugInformation: (buildVariant == "debug") property string optimization: (buildVariant == "debug" ? "none" : "fast") readonly property string hostPlatform: undefined // set internally readonly property stringList hostOS: Utilities.canonicalPlatform(hostPlatform) property string hostOSVersion: { if (hostOS && hostOS.contains("macos")) { return Utilities.getNativeSetting("/System/Library/CoreServices/ServerVersion.plist", "ProductVersion") || Utilities.getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductVersion"); } else if (hostOS && hostOS.contains("windows")) { var version = Utilities.getNativeSetting(windowsRegistryKey, "CurrentVersion"); return version + "." + hostOSBuildVersion; } } property string hostOSBuildVersion: { if (hostOS.contains("macos")) { return Utilities.getNativeSetting("/System/Library/CoreServices/ServerVersion.plist", "ProductBuildVersion") || Utilities.getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductBuildVersion"); } else if (hostOS.contains("windows")) { return Utilities.getNativeSetting(windowsRegistryKey, "CurrentBuildNumber"); } } readonly property var hostOSVersionParts: hostOSVersion ? hostOSVersion.split('.').map(function(item) { return parseInt(item, 10); }) : [] readonly property int hostOSVersionMajor: hostOSVersionParts[0] || 0 readonly property int hostOSVersionMinor: hostOSVersionParts[1] || 0 readonly property int hostOSVersionPatch: hostOSVersionParts[2] || 0 property string targetPlatform: hostPlatform readonly property stringList targetOS: Utilities.canonicalPlatform(targetPlatform) property string pathListSeparator: hostOS.contains("windows") ? ";" : ":" property string pathSeparator: hostOS.contains("windows") ? "\\" : "/" property string nullDevice: hostOS.contains("windows") ? "NUL" : "/dev/null" property path shellPath: hostOS.contains("windows") ? windowsShellPath : "/bin/sh" property string profile: project.profile property string toolchainType: { if (targetOS.contains("windows")) return hostOS.contains("windows") ? "msvc" : "mingw"; if (targetOS.contains("darwin")) return hostOS.contains("macos") ? "xcode" : "clang"; if (targetOS.contains("freebsd")) return "clang"; if (targetOS.contains("qnx")) return "qcc"; if (targetOS.containsAny(["haiku", "vxworks", "unix"])) return "gcc"; } readonly property stringList toolchain: Utilities.canonicalToolchain(toolchainType) property string architecture property bool install: false property path installSourceBase property string installRoot: project.buildDirectory + "/install-root" property string installDir property string installPrefix: qbs.targetOS.contains("unix") ? "/usr/local" : "" property path sysroot PropertyOptions { name: "buildVariant" allowedValues: ['debug', 'release'] description: "name of the build variant" } PropertyOptions { name: "optimization" allowedValues: ['none', 'fast', 'small'] description: "optimization level" } validate: { var validator = new ModUtils.PropertyValidator("qbs"); validator.setRequiredProperty("hostOS", hostOS); validator.setRequiredProperty("targetOS", targetOS); validator.addCustomValidator("targetOS", targetOS, function (value) { if (!value || (value.contains("osx") && !value.contains("macos"))) return false; return true; }, "the value 'osx' has been replaced by 'macos'; use that instead and update " + "hostOS and targetOS condition checks in your project accordingly"); if (hostOS && (hostOS.contains("windows") || hostOS.contains("macos"))) { validator.setRequiredProperty("hostOSVersion", hostOSVersion, "could not detect host operating system version; " + "verify that system files and registry keys have not " + "been modified."); if (hostOSVersion) validator.addVersionValidator("hostOSVersion", hostOSVersion, 2, 4); validator.setRequiredProperty("hostOSBuildVersion", hostOSBuildVersion, "could not detect host operating system build version; " + "verify that system files or registry have not been " + "tampered with."); } validator.addCustomValidator("architecture", architecture, function (value) { return !architecture || architecture === Utilities.canonicalArchitecture(architecture); }, "'" + architecture + "' is invalid. You must use the canonical name '" + Utilities.canonicalArchitecture(architecture) + "'"); validator.addCustomValidator("toolchain", toolchain, function (value) { if (toolchain === undefined) return false; // cannot have null toolchain, empty is valid... for now var canonical = Utilities.canonicalToolchain.apply(Utilities, toolchain); for (var i = 0; i < Math.max(canonical.length, toolchain.length); ++i) { if (canonical[i] !== toolchain[i]) return false; } return true; }, "'" + toolchain + "' is invalid. You must use the canonical list '" + Utilities.canonicalToolchain.apply(Utilities, toolchain) + "'"); validator.addCustomValidator("toolchain", toolchain, function (value) { // None of the pairs listed here may appear in the same toolchain list. // Note that this check is applied AFTER canonicalization, so for example // {"clang", "msvc"} need not be checked, since a toolchain containing clang is // guaranteed to also contain gcc. var pairs = [ ["gcc", "msvc"], ["llvm", "mingw"] ]; var canonical = Utilities.canonicalToolchain.apply(Utilities, value); for (var i = 0; i < pairs.length; ++i) { if (canonical.contains(pairs[i][0]) && canonical.contains(pairs[i][1])) return false; } return true; }, "'" + toolchain + "' contains one or more mutually exclusive toolchain types."); validator.validate(); } // private properties property string windowsRegistryKey: "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion" property path windowsSystemRoot: FileInfo.fromWindowsSeparators(Utilities.getNativeSetting(windowsRegistryKey, "SystemRoot")) property path windowsShellPath: FileInfo.fromWindowsSeparators(Environment.getEnv("COMSPEC")) || FileInfo.joinPaths(windowsSystemRoot, "System32", "cmd.exe") property string windowsPathVariable: hostOS.contains("windows") ? "PATH" : "WINEPATH" property var commonRunEnvironment: ({}) setupRunEnvironment: { var env = product.qbs.commonRunEnvironment; for (var i in env) { var v = new ModUtils.EnvironmentVariable(i, product.qbs.pathListSeparator, product.qbs.hostOS.contains("windows")); v.value = env[i]; v.set(); } } // Properties that can be set for multiplexing products. property stringList profiles: [] property stringList architectures: [] property stringList buildVariants: [] // internal properties readonly property string version: [versionMajor, versionMinor, versionPatch].join(".") readonly property int versionMajor: undefined // set internally readonly property int versionMinor: undefined // set internally readonly property int versionPatch: undefined // set internally readonly property var multiplexMap: ({ profiles: "profile", architectures: "architecture", buildVariants: "buildVariant" }) } qbs-src-1.13.1/share/qbs/modules/qnx/000077500000000000000000000000001347155106100173175ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/qnx/qnx.qbs000066400000000000000000000120471347155106100206400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.Environment import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Utilities Module { Probes.PathProbe { id: qnxSdkProbe names: ["qnx700", "qnx660", "qnx650"] searchPaths: qbs.hostOS.contains("windows") ? [Environment.getEnv("USERPROFILE"), Environment.getEnv("SystemDrive")] : [Environment.getEnv("HOME"), "/opt"] } Probe { id: qnxTargetOsProbe property string qnxSdkDir: sdkDir property stringList targets: [] configure: { if (qnxSdkDir) { var validEntries = []; var entries = File.directoryEntries( FileInfo.joinPaths(qnxSdkDir, "target"), File.Dirs | File.NoDotAndDotDot); for (var i = 0; i < entries.length; ++i) { if (/^qnx[0-9]$/.test(entries[i])) validEntries.push(entries[i]); } validEntries.sort(); validEntries.reverse(); targets = validEntries; found = targets.length > 0; } else { found = false; } } } version: qnxSdkProbe.found ? qnxSdkProbe.fileName.substr(3, 3).split("").join(".") : undefined readonly property bool qnx7: version ? Utilities.versionCompare(version, "7") >= 0 : false property string sdkDir: qnxSdkProbe.filePath property string hostArch: qnx7 ? "x86_64" : "x86" property string hostOs: { if (qbs.hostOS.contains("linux")) return "linux"; if (qbs.hostOS.contains("macos")) return "darwin"; if (qbs.hostOS.contains("windows")) return qnx7 ? "win64" : "win32"; } property string targetOs: qnxTargetOsProbe.targets[0] property string compilerName: "gcc" property string configurationDir: FileInfo.joinPaths(Environment.getEnv("HOME"), ".qnx") property string hostDir: FileInfo.joinPaths(sdkDir, "host", hostOs, hostArch) property string targetDir: FileInfo.joinPaths(sdkDir, "target", targetOs) property var buildEnv: ({ "QNX_HOST": hostDir, "QNX_TARGET": targetDir, "QNX_CONFIGURATION": configurationDir }) qbs.sysroot: targetDir validate: { if (!sdkDir) { throw ModUtils.ModuleError("Could not find a QNX SDK in any of the following " + "locations:\n\t" + qnxSdkProbe.candidatePaths.join("\n\t") + "\nInstall the QNX SDK to one of the above locations, " + "or set the qnx.sdkDir property to a valid QNX SDK " + "location."); } if (!hostOs) { throw ModUtils.ModuleError("Host operating system '" + qbs.hostOS + "' is not supported by the QNX SDK."); } else if (!File.exists(hostDir)) { throw ModUtils.ModuleError("Detected host tools operating system '" + hostOs + "' and architecture '" + hostArch + "' directory is not " + "present in the QNX SDK installed at '" + sdkDir + "' in the expected location '" + hostDir + "'; did you forget to install it?"); } if (!targetOs) throw ModUtils.ModuleError("Could not find any QNX targets in '" + targetDir + "'"); } } qbs-src-1.13.1/share/qbs/modules/texttemplate/000077500000000000000000000000001347155106100212315ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/texttemplate/texttemplate.qbs000066400000000000000000000047311347155106100244650ustar00rootroot00000000000000import qbs.TextFile Module { property var dict: ({}) property string outputTag: "text" property string outputFileName FileTagger { patterns: ["*.in"] fileTags: ["texttemplate.input"] } Rule { inputs: ["texttemplate.input"] outputFileTags: [product.texttemplate.outputTag] outputArtifacts: [ { fileTags: [product.texttemplate.outputTag], filePath: input.texttemplate.outputFileName || input.completeBaseName } ] prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { try { var src = new TextFile(input.filePath, TextFile.ReadOnly); var dst = new TextFile(output.filePath, TextFile.WriteOnly); var rex = /\${(\$|\w+)}/g; var match; while (!src.atEof()) { rex.lastIndex = 0; var line = src.readLine(); var matches = []; while (match = rex.exec(line)) matches.push(match); for (var i = matches.length; --i >= 0;) { match = matches[i]; var replacement; if (match[1] === "$") { replacement = "$"; } else { replacement = input.texttemplate.dict[match[1]]; if (typeof replacement === "undefined") { throw new Error("Placeholder '" + match[1] + "' is not defined in textemplate.dict for '" + input.fileName + "'."); } } line = line.substr(0, match.index) + replacement + line.substr(match.index + match[0].length); } dst.writeLine(line); } } finally { if (src) src.close(); if (dst) dst.close(); } }; return [cmd]; } } } qbs-src-1.13.1/share/qbs/modules/typescript/000077500000000000000000000000001347155106100207175ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/typescript/TypeScriptModule.qbs000066400000000000000000000305761347155106100247150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Process import "typescript.js" as TypeScript Module { // Qbs does NOT support standalone TypeScript installations // (for example, %PROGRAMFILES%\Microsoft SDKs\TypeScript and some Debian and RPM packages), // because they do not include typescript.d.ts, which is necessary for building internal tools. // Only npm-based installations of TypeScript are supported (this is also the most common). Depends { name: "nodejs" } additionalProductTypes: ["compiled_typescript"] Probes.TypeScriptProbe { id: tsc interpreterPath: FileInfo.path(nodejs.interpreterFilePath) packageManagerBinPath: nodejs.packageManagerBinPath packageManagerRootPath: nodejs.packageManagerRootPath } property path toolchainInstallPath: tsc.path property path toolchainLibDirName: (versionMajor > 1 || (versionMajor === 1 && versionMinor >= 6)) ? "lib" : "bin" property path toolchainLibInstallPath: FileInfo.joinPaths(nodejs.packageManagerRootPath, "typescript", toolchainLibDirName) version: tsc.version ? tsc.version[2] : undefined property var versionParts: version ? version.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int versionMajor: versionParts[0] property int versionMinor: versionParts[1] property int versionPatch: versionParts[2] property int versionBuild: versionParts[3] property string versionSuffix: tsc.version ? tsc.version[3] : undefined property string compilerName: tsc.fileName property string compilerPath: tsc.filePath property string warningLevel: "normal" PropertyOptions { name: "warningLevel" description: "pedantic to warn on expressions and declarations with an implied 'any' type" allowedValues: ["normal", "pedantic"] } property string targetVersion PropertyOptions { name: "targetVersion" description: "ECMAScript target version" allowedValues: ["ES3", "ES5", "ES2015"] } property string moduleLoader PropertyOptions { name: "moduleLoader" allowedValues: ["commonjs", "amd"] } property bool stripComments: !qbs.debugInformation PropertyOptions { name: "stripComments" description: "whether to remove comments from the generated output" } property bool generateDeclarations: false PropertyOptions { name: "generateDeclarations" description: "whether to generate corresponding .d.ts files during compilation" } // In release mode, nodejs can/should default-enable minification and obfuscation, // making the source maps useless, so these default settings work out fine property bool generateSourceMaps: qbs.debugInformation PropertyOptions { name: "generateSourceMaps" description: "whether to generate corresponding .map files during compilation" } property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional flags for the TypeScript compiler" } property bool singleFile: false PropertyOptions { name: "singleFile" description: "whether to compile all source files to a single output file" } validate: { var interpreterMessage = "TypeScript requires the Node.js interpreter to be called 'node'."; if (File.exists("/etc/debian_version")) { interpreterMessage += " Did you forget to install the nodejs-legacy package? " + "See https://lists.debian.org/debian-devel-announce/2012/07/msg00002.html " + "for more information."; } var preValidator = new ModUtils.PropertyValidator("nodejs"); preValidator.addCustomValidator("interpreterFileName", nodejs.interpreterFileName, function (value) { return value === "node" + (qbs.hostOS.contains("windows") ? ".exe" : ""); }, interpreterMessage); preValidator.addCustomValidator("interpreterFilePath", nodejs.interpreterFilePath, function (value) { return value.endsWith(nodejs.interpreterFileName); }, interpreterMessage); preValidator.validate(); var validator = new ModUtils.PropertyValidator("typescript"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("compilerName", compilerName); validator.setRequiredProperty("compilerPath", compilerPath); validator.setRequiredProperty("version", version); validator.setRequiredProperty("versionParts", versionParts); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); validator.addVersionValidator("version", version, 3, 4); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); if (versionParts && versionParts.length >= 4) { validator.setRequiredProperty("versionBuild", versionBuild); validator.addRangeValidator("versionBuild", versionBuild, 0); } validator.validate(); } // TypeScript declaration files FileTagger { patterns: ["*.d.ts"] fileTags: ["typescript_declaration"] } // TypeScript source files FileTagger { patterns: ["*.ts"] fileTags: ["typescript"] } Group { name: "io.qt.qbs.internal.typescript-helper" files: [ FileInfo.joinPaths(path, "qbs-tsc-scan", "qbs-tsc-scan.ts"), FileInfo.joinPaths(typescript.toolchainLibInstallPath, "typescript.d.ts"), FileInfo.joinPaths(typescript.toolchainLibInstallPath, "..", "package.json") ] fileTags: ["typescript.typescript-internal"] } Rule { multiplex: true inputs: ["typescript.typescript-internal"] outputFileTags: ["typescript.compiled_typescript-internal"] outputArtifacts: { if (!TypeScript.supportsModernFeatures(product)) return []; return [{ filePath: FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "qbs-tsc-scan.ts"), fileTags: ["typescript.typescript-internal.copy"] }, { filePath: FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "node_modules", "typescript", "lib", "typescript.d.ts"), fileTags: ["typescript.typescript-internal.copy"] }, { filePath: FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "node_modules", "typescript", "package.json"), fileTags: ["typescript.typescript-internal.copy"] }, { filePath: FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "qbs-tsc-scan.js"), fileTags: ["typescript.compiled_typescript-internal"] }]; } prepare: { var inputPaths = inputs["typescript.typescript-internal"].map(function (input) { return input.filePath; }); var outputPaths = outputs["typescript.typescript-internal.copy"].map(function (output) { return output.filePath; }); var sortFunc = function (a, b) { return FileInfo.fileName(a).localeCompare(FileInfo.fileName(b)); }; var jcmd = new JavaScriptCommand(); jcmd.ignoreDryRun = true; jcmd.silent = true; jcmd.inputPaths = inputPaths.sort(sortFunc); jcmd.outputPaths = outputPaths.sort(sortFunc); jcmd.sourceCode = function() { for (var i = 0; i < inputPaths.length; ++i) File.copy(inputPaths[i], outputPaths[i]); }; var outDir = FileInfo.path( outputs["typescript.compiled_typescript-internal"][0].filePath); var args = ["--module", "commonjs", "--outDir", outDir].concat(outputPaths.filter(function (f) { return !f.endsWith(".json"); })); var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args); cmd.ignoreDryRun = true; cmd.silent = true; return [jcmd, cmd]; } } Rule { id: typescriptCompiler multiplex: true inputs: ["typescript"] inputsFromDependencies: ["typescript_declaration"] explicitlyDependsOn: ["typescript.compiled_typescript-internal"] outputArtifacts: TypeScript.outputArtifacts(product, inputs) outputFileTags: ["application_js", "compiled_typescript", "js", "source_map", "typescript_declaration"] prepare: { var cmd, cmds = []; cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), TypeScript.tscArguments(product, inputs)); cmd.description = "compiling " + (ModUtils.moduleProperty(product, "singleFile") ? outputs.compiled_typescript[0].fileName : inputs.typescript.map(function(obj) { return obj.fileName; }).join(", ")); cmd.highlight = "compiler"; cmds.push(cmd); // QBS-5 // Move the compiled JavaScript files compiled by TypeScript to an intermediate // directory so that the nodejs module can perform any necessary postprocessing // on the result. The nodejs module will move the files back to their original // locations after postprocessing. cmd = new JavaScriptCommand(); cmd.silent = true; cmd.outDir = product.buildDirectory; cmd.sourceCode = function() { for (var i = 0; i < outputs.compiled_typescript.length; ++i) { var output = outputs.compiled_typescript[i]; var intermediatePath = FileInfo.path(FileInfo.relativePath(product.moduleProperty("nodejs", "compiledIntermediateDir"), output.filePath)); var originalFilePath = FileInfo.joinPaths(outDir, intermediatePath, output.fileName); File.copy(originalFilePath, output.filePath); File.remove(originalFilePath); } }; cmds.push(cmd); return cmds; } } } qbs-src-1.13.1/share/qbs/modules/typescript/qbs-tsc-scan/000077500000000000000000000000001347155106100232155ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/typescript/qbs-tsc-scan/.gitignore000066400000000000000000000001611347155106100252030ustar00rootroot00000000000000# Visual Studio Code IDE tsconfig.json qbs-tsc-scan.js typings/node/node.d.ts typings/typescript/typescript.d.ts qbs-src-1.13.1/share/qbs/modules/typescript/qbs-tsc-scan/qbs-tsc-scan.ts000066400000000000000000000051671347155106100260740ustar00rootroot00000000000000import ts = require("typescript"); declare var process: any; export namespace io.qt.qbs { export class Artifact { filePath: string; fileTags: string[]; } export namespace tools { export namespace utils { function stringEndsWith(s: string, e: string) { return s.slice(-e.length) === e; } export function artifactFromFilePath(filePath: string): Artifact { var fileTags: string[] = []; if (stringEndsWith(filePath, ".js.map")) { fileTags.push("source_map"); } else if (stringEndsWith(filePath, ".js")) { fileTags.push("js", "compiled_typescript"); } else if (stringEndsWith(filePath, ".d.ts")) { fileTags.push("typescript_declaration"); } return { filePath: filePath, fileTags: fileTags }; } } function compileInternal(fileNames: string[], options: ts.CompilerOptions): qbs.Artifact[] { var outputArtifacts: qbs.Artifact[] = []; var program = ts.createProgram(fileNames, options); var emitResult = program.emit(undefined, filePath => { outputArtifacts.push(utils.artifactFromFilePath(filePath)); }); var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); allDiagnostics.forEach(diagnostic => { var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); if (diagnostic.file) { var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); console.error(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); } else { console.error(message); } }); return emitResult.emitSkipped ? undefined : outputArtifacts; } export function compile(commandLineArguments: string[]): qbs.Artifact[] { var parsedCommandLine = ts.parseCommandLine(commandLineArguments); return compileInternal(parsedCommandLine.fileNames, parsedCommandLine.options); } export function TypeScriptCompilerScannerToolMain(): void { var outputArtifacts = compile(process.argv.slice(2)); if (outputArtifacts !== undefined) { console.log(JSON.stringify(outputArtifacts)); } else { process.exit(1); } } } } io.qt.qbs.tools.TypeScriptCompilerScannerToolMain(); qbs-src-1.13.1/share/qbs/modules/typescript/typescript.js000066400000000000000000000246761347155106100235020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); var Process = require("qbs.Process"); function findTscVersion(compilerFilePath, nodejsPath) { var p = new Process(); try { if (nodejsPath) p.setEnv("PATH", nodejsPath); p.exec(compilerFilePath, ["--version"]); var re = /^(?:message TS6029: )?Version (([0-9]+(?:\.[0-9]+){1,3})(?:-(.+?))?)$/m; var match = p.readStdOut().trim().match(re); if (match !== null) return match; } finally { p.close(); } } function tscArguments(product, inputs) { var i; var args = []; if (ModUtils.moduleProperty(product, "warningLevel") === "pedantic") { args.push("--noImplicitAny"); } var targetVersion = ModUtils.moduleProperty(product, "targetVersion"); if (targetVersion) { args.push("--target"); args.push(targetVersion); } var moduleLoader = ModUtils.moduleProperty(product, "moduleLoader"); if (moduleLoader) { args.push("--module"); args.push(moduleLoader); } if (ModUtils.moduleProperty(product, "stripComments")) { args.push("--removeComments"); } if (ModUtils.moduleProperty(product, "generateDeclarations")) { args.push("--declaration"); } if (ModUtils.moduleProperty(product, "generateSourceMaps")) { args.push("--sourcemap"); } // User-supplied flags var flags = ModUtils.moduleProperty(product, "compilerFlags"); for (i in flags) { args.push(flags[i]); } if (supportsModernFeatures(product)) { args.push("--rootDir", product.sourceDirectory); } args.push("--outDir", product.buildDirectory); if (ModUtils.moduleProperty(product, "singleFile")) { args.push(outOption(product), FileInfo.joinPaths(product.destinationDirectory, product.targetName) + ".js"); } if (inputs.typescript_declaration) { for (i = 0; i < inputs.typescript_declaration.length; ++i) { args.push(inputs.typescript_declaration[i].filePath); } } if (inputs.typescript) { for (i = 0; i < inputs.typescript.length; ++i) { args.push(inputs.typescript[i].filePath); } } if (inputs["typescript.typescript-internal"]) { for (i = 0; i < inputs["typescript.typescript-internal"].length; ++i) { args.push(inputs["typescript.typescript-internal"][i].filePath); } } return args; } function outputArtifacts(product, inputs) { if (!supportsModernFeatures(product)) { console.warn("Qbs does not properly support TypeScript versions prior to 1.5 due to " + "severe limitations in dependency tracking. This is TypeScript version " + ModUtils.moduleProperty(product, "version") + ". It is strongly recommended " + "that you upgrade TypeScript, or continue at your own risk."); return legacyOutputArtifacts(product, inputs); } var process; try { process = new Process(); process.setEnv("NODE_PATH", [ ModUtils.moduleProperty(product, "toolchainInstallPath"), product.moduleProperty("nodejs", "packageManagerRootPath") ].join(product.moduleProperty("qbs", "pathListSeparator"))); process.exec(product.moduleProperty("nodejs", "interpreterFilePath"), [FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "qbs-tsc-scan.js")] .concat(tscArguments(product, inputs)), true); var artifacts = JSON.parse(process.readStdOut()); // Find and tag the "main" output file var applicationFile = product.moduleProperty("nodejs", "applicationFile"); if (applicationFile) { var i, appIndex = -1; if (product.moduleProperty("typescript", "singleFile")) { for (i = 0; i < artifacts.length; ++i) { if (artifacts[i].fileTags.contains("compiled_typescript")) { appIndex = i; break; } } } else { var expected = FileInfo.relativePath(product.sourceDirectory, applicationFile); if (!expected.endsWith(".ts")) // tsc doesn't allow this anyways, so it's a perfectly reasonable restriction throw "TypeScript source file name '" + applicationFile + "' does not end with .ts"; expected = expected.slice(0, -2) + "js"; for (i = 0; i < artifacts.length; ++i) { if (expected === FileInfo.relativePath(product.buildDirectory, artifacts[i].filePath)) { appIndex = i; break; } } } if (appIndex === -1 || !artifacts[appIndex].fileTags.contains("compiled_typescript")) throw "nodejs.applicationFile was set, but Qbs couldn't find the compiled " + "JavaScript file corresponding to '" + applicationFile + "'"; artifacts[appIndex].fileTags = artifacts[appIndex].fileTags.concat(["application_js"]); } return artifacts; } finally { if (process) process.close(); } } function legacyOutputArtifacts(product, inputs) { var artifacts = []; if (!inputs.typescript) { return artifacts; } var jsTags = ["js", "compiled_typescript"]; var filePath = FileInfo.joinPaths(product.destinationDirectory, product.targetName); if (product.moduleProperty("typescript", "singleFile")) { // We could check // if (product.moduleProperty("nodejs", "applicationFile") === inputs.typescript[i].filePath) // but since we're compiling to a single file there's no need to state it explicitly jsTags.push("application_js"); artifacts.push({fileTags: jsTags, filePath: FileInfo.joinPaths( product.moduleProperty("nodejs", "compiledIntermediateDir"), product.targetName + ".js")}); if (product.moduleProperty("typescript", "generateDeclarations")) { artifacts.push({fileTags: ["typescript_declaration"], filePath: filePath + ".d.ts"}); } if (product.moduleProperty("typescript", "generateSourceMaps")) { artifacts.push({fileTags: ["source_map"], filePath: filePath + ".js.map"}); } } else { for (var i = 0; i < inputs.typescript.length; ++i) { jsTags = ["js", "compiled_typescript"]; if (product.moduleProperty("nodejs", "applicationFile") === inputs.typescript[i].filePath) jsTags.push("application_js"); var intermediatePath = FileInfo.path(FileInfo.relativePath( product.sourceDirectory, inputs.typescript[i].filePath)); var baseName = FileInfo.baseName(inputs.typescript[i].fileName); filePath = FileInfo.joinPaths(product.destinationDirectory, intermediatePath, baseName); artifacts.push({fileTags: jsTags, filePath: FileInfo.joinPaths( product.moduleProperty("nodejs", "compiledIntermediateDir"), intermediatePath, baseName + ".js")}); if (product.moduleProperty("typescript", "generateDeclarations")) { artifacts.push({fileTags: ["typescript_declaration"], filePath: filePath + ".d.ts"}); } if (product.moduleProperty("typescript", "generateSourceMaps")) { artifacts.push({fileTags: ["source_map"], filePath: filePath + ".js.map"}); } } } return artifacts; } function outOption(product) { var compilerVersionMajor = ModUtils.moduleProperty(product, "versionMajor"); if (compilerVersionMajor === 1) { if (ModUtils.moduleProperty(product, "versionMinor") < 6) { return "--out"; } } return "--outFile"; } function supportsModernFeatures(product) { var compilerVersionMajor = ModUtils.moduleProperty(product, "versionMajor"); if (compilerVersionMajor === 1) { if (ModUtils.moduleProperty(product, "versionMinor") >= 5) { return true; } } return compilerVersionMajor > 1; } qbs-src-1.13.1/share/qbs/modules/vcs/000077500000000000000000000000001347155106100173045ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/vcs/vcs-module.qbs000066400000000000000000000120361347155106100220730ustar00rootroot00000000000000import qbs.File import qbs.FileInfo import qbs.Process import qbs.TextFile import qbs.Utilities Module { property string type: typeProbe.type property string repoDir: project.sourceDirectory property string toolFilePath: { if (type === "git") return "git"; if (type === "svn") return "svn"; } property string headerFileName: "vcs-repo-state.h" readonly property string repoState: gitProbe.repoState || subversionProbe.repoState // Internal readonly property string includeDir: FileInfo.joinPaths(product.buildDirectory, "vcs-include") readonly property string metaDataBaseDir: typeProbe.metaDataBaseDir PropertyOptions { name: "type" allowedValues: ["git", "svn"] description: "the version control system your project is using" } Depends { name: "cpp"; condition: headerFileName } Properties { condition: headerFileName cpp.includePaths: [includeDir] } Probe { id: typeProbe property string tool: toolFilePath property string theRepoDir: repoDir property string type property string metaDataBaseDir configure: { var detector = new Process(); try { detector.setWorkingDirectory(theRepoDir); if (detector.exec(tool || "git", ["rev-parse", "--git-dir"]) === 0) { found = true; type = "git"; metaDataBaseDir = detector.readStdOut().trim(); if (!FileInfo.isAbsolutePath(metaDataBaseDir)) metaDataBaseDir = FileInfo.joinPaths(theRepoDir, metaDataBaseDir); return; } if (detector.exec(tool || "svn", ["info", "--show-item", "wc-root", "--no-newline"]) === 0) { found = true type = "svn"; metaDataBaseDir = FileInfo.joinPaths(detector.readStdOut(), ".svn"); return; } else if (detector.exec(tool || "svn", ["info"]) === 0) { if (detector.exec(tool || "svn", ["--version", "--quiet"]) === 0 && Utilities.versionCompare(detector.readStdOut().trim(), "1.9") < 0) { throw "svn too old, version >= 1.9 required"; } } } finally { detector.close(); } } } Probe { id: gitProbe condition: type === "git" property string tool: toolFilePath property string theRepoDir: repoDir property string filePath: FileInfo.joinPaths(metaDataBaseDir, "logs/HEAD") property var timestamp: File.lastModified(filePath) property string repoState configure: { if (!File.exists(filePath)) return; // No commits yet. var proc = new Process(); try { proc.setWorkingDirectory(theRepoDir); proc.exec(tool, ["describe", "--always", "HEAD"], true); repoState = proc.readStdOut().trim(); if (repoState) found = true; } finally { proc.close(); } } } Probe { id: subversionProbe condition: type === "svn" property string tool: toolFilePath property string theRepoDir: repoDir property string filePath: FileInfo.joinPaths(metaDataBaseDir, "wc.db") property var timestamp: File.lastModified(filePath) property string repoState configure: { var proc = new Process(); try { proc.setWorkingDirectory(theRepoDir); proc.exec(tool, ["info", "-r", "HEAD", "--show-item", "revision", "--no-newline"], true); repoState = proc.readStdOut().trim(); if (repoState) found = true; } finally { proc.close(); } } } Rule { condition: headerFileName multiplex: true Artifact { filePath: FileInfo.joinPaths(product.vcs.includeDir, product.vcs.headerFileName) fileTags: ["hpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.highlight = "codegen"; cmd.repoState = product.vcs.repoState; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); try { f.writeLine("#ifndef VCS_REPO_STATE_H"); f.writeLine("#define VCS_REPO_STATE_H"); f.writeLine('#define VCS_REPO_STATE "' + (repoState ? repoState : "none") + '"') f.writeLine("#endif"); } finally { f.close(); } }; return [cmd]; } } } qbs-src-1.13.1/share/qbs/modules/wix/000077500000000000000000000000001347155106100173205ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/wix/WiXModule.qbs000066400000000000000000000416471347155106100217200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Utilities Module { condition: qbs.targetOS.contains("windows") Probes.WiXProbe { id: wixProbe } property path toolchainInstallPath: wixProbe.path property path toolchainInstallRoot: wixProbe.root version: wixProbe.version property var versionParts: version ? version.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int versionMajor: versionParts[0] property int versionMinor: versionParts[1] property int versionPatch: versionParts[2] property int versionBuild: versionParts[3] property string compilerName: "candle.exe" property string compilerPath: FileInfo.joinPaths(toolchainInstallRoot, compilerName) property string linkerName: "light.exe" property string linkerPath: FileInfo.joinPaths(toolchainInstallRoot, linkerName) property string warningLevel: "normal" PropertyOptions { name: "warningLevel" allowedValues: ["none", "normal", "pedantic"] } property bool debugInformation: qbs.debugInformation property bool treatWarningsAsErrors: false property bool verboseOutput: false PropertyOptions { name: "verboseOutput" description: "display verbose output from the compiler and linker" } property bool visualStudioCompatibility: true PropertyOptions { name: "visualStudioCompatibility" description: "whether to define most of the same variables as " + "Visual Studio when using the Candle compiler" } property bool enableQbsDefines: true PropertyOptions { name: "enableQbsDefines" description: "built-in variables that are defined when using the Candle compiler" } property pathList includePaths PropertyOptions { name: "includePaths" description: "directories to add to the include search path" } property stringList defines PropertyOptions { name: "defines" description: "variables that are defined when using the Candle compiler" } property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional flags for the Candle compiler" } property stringList linkerFlags PropertyOptions { name: "linkerFlags" description: "additional flags for the Light linker" } property stringList cultures PropertyOptions { name: "cultures" description: "the list of localizations to build the MSI for; leave undefined to build all localizations" } property stringList extensions: product.type.contains("wixsetup") ? ["WixBalExtension"] : [] // default to WiX Standard Bootstrapper extension // private properties property string targetSuffix: { if (product.type.contains("msi")) { return windowsInstallerSuffix; } else if (product.type.contains("wixsetup")) { return executableSuffix; } } // MSI/MSM package validation only works natively on Windows property bool enablePackageValidation: qbs.hostOS.contains("windows") property string executableSuffix: ".exe" property string windowsInstallerSuffix: ".msi" validate: { var validator = new ModUtils.PropertyValidator("wix"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("toolchainInstallRoot", toolchainInstallRoot); validator.setRequiredProperty("version", version); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); validator.addVersionValidator("version", version, 3, 4); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); if (versionParts && versionParts.length >= 4) { validator.setRequiredProperty("versionBuild", versionBuild); validator.addRangeValidator("versionBuild", versionBuild, 0); } validator.validate(); } setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, true); v.prepend(product.wix.toolchainInstallPath); v.prepend(product.wix.toolchainInstallRoot); v.set(); } // WiX Include Files FileTagger { patterns: ["*.wxi"] fileTags: ["wxi"] } // WiX Localization Files FileTagger { patterns: ["*.wxl"] fileTags: ["wxl"] } // WiX Source Files FileTagger { patterns: ["*.wxs"] fileTags: ["wxs"] } Rule { id: candleCompiler inputs: ["wxs"] auxiliaryInputs: ["wxi", "installable"] Artifact { fileTags: ["wixobj"] filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), FileInfo.baseName(input.fileName) + ".wixobj") } prepare: { var i; var args = ["-nologo"]; if (ModUtils.moduleProperty(input, "warningLevel") === "none") { args.push("-sw"); } else { if (ModUtils.moduleProperty(input, "warningLevel") === "pedantic") { args.push("-pedantic"); } if (ModUtils.moduleProperty(input, "treatWarningsAsErrors")) { args.push("-wx"); } } if (ModUtils.moduleProperty(input, "verboseOutput")) { args.push("-v"); } var arch = product.moduleProperty("qbs", "architecture"); // http://wixtoolset.org/documentation/manual/v3/xsd/wix/package.html switch (arch) { case "x86_64": arch = "x64"; break; case "armv7": case "armv7a": arch = "arm"; break; } // Visual Studio defines these variables along with various solution and project names and paths; // we'll pass most of them to ease compatibility between QBS and WiX projects originally created // using Visual Studio. The only definitions we don't pass are the ones which make no sense at all // in QBS, like the solution and project directories since they do not exist. if (ModUtils.moduleProperty(input, "visualStudioCompatibility")) { var toolchain = product.moduleProperty("qbs", "toolchain"); var toolchainInstallPath = product.moduleProperty("cpp", "toolchainInstallPath"); if (toolchain && toolchain.contains("msvc") && toolchainInstallPath) { var vcDir = toolchainInstallPath.replace(/[\\/]bin$/i, ""); var vcRootDir = vcDir.replace(/[\\/]VC$/i, ""); args.push("-dDevEnvDir=" + FileInfo.toWindowsSeparators(FileInfo.joinPaths(vcRootDir, 'Common7', 'IDE'))); } var buildVariant = product.moduleProperty("qbs", "buildVariant"); if (buildVariant === "debug") { args.push("-dDebug"); args.push("-dConfiguration=Debug"); } else if (buildVariant === "release") { // VS doesn't define "Release" args.push("-dConfiguration=Release"); } var productTargetExt = ModUtils.moduleProperty(input, "targetSuffix"); if (!productTargetExt) { throw("WiX: Unsupported product type '" + product.type + "'"); } var builtBinaryFilePath = FileInfo.joinPaths(product.destinationDirectory, product.targetName + productTargetExt); args.push("-dOutDir=" + FileInfo.toWindowsSeparators(FileInfo.path(builtBinaryFilePath))); // in VS, relative to the project file by default args.push("-dPlatform=" + (arch || "x86")); args.push("-dProjectName=" + project.name); args.push("-dTargetDir=" + FileInfo.toWindowsSeparators(FileInfo.path(builtBinaryFilePath))); // in VS, an absolute path args.push("-dTargetExt=" + productTargetExt); args.push("-dTargetFileName=" + product.targetName + productTargetExt); args.push("-dTargetName=" + product.targetName); args.push("-dTargetPath=" + FileInfo.toWindowsSeparators(builtBinaryFilePath)); } var includePaths = ModUtils.moduleProperty(input, "includePaths"); for (i in includePaths) { args.push("-I" + includePaths[i]); } var enableQbsDefines = ModUtils.moduleProperty(input, "enableQbsDefines") if (enableQbsDefines) { var map = { "project.": project, "product.": product }; for (var prefix in map) { var obj = map[prefix]; for (var prop in obj) { var val = obj[prop]; if (typeof val !== 'function' && typeof val !== 'object' && !prop.startsWith("_")) { args.push("-d" + prefix + prop + "=" + val); } } } // Helper define for alternating between 32-bit and 64-bit logic if (arch === "x64" || arch === "ia64") { args.push("-dWin64"); } } // User-supplied defines var defines = ModUtils.moduleProperty(input, "defines"); for (i in defines) { args.push("-d" + defines[i]); } // User-supplied flags var flags = ModUtils.moduleProperty(input, "compilerFlags"); for (i in flags) { args.push(flags[i]); } args.push("-out"); args.push(FileInfo.toWindowsSeparators(output.filePath)); if (arch) { args.push("-arch"); args.push(arch); } var extensions = ModUtils.moduleProperty(input, "extensions"); for (i in extensions) { args.push("-ext"); args.push(extensions[i]); } args.push(FileInfo.toWindowsSeparators(input.filePath)); var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args); cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.workingDirectory = FileInfo.path(output.filePath); // candle.exe outputs the file name. We filter that out. cmd.inputFileName = input.fileName; cmd.stdoutFilterFunction = function(output) { return output.split(inputFileName + "\r\n").join(""); }; return cmd; } } Rule { id: lightLinker multiplex: true inputs: ["wixobj", "wxl"] auxiliaryInputs: ["installable"] inputsFromDependencies: product.type.contains("wixsetup") ? ["msi"] : [] outputArtifacts: { var artifacts = []; if (product.type.contains("wixsetup")) { artifacts.push({ fileTags: ["wixsetup", "application"], filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ModUtils.moduleProperty(product, "executableSuffix")) }); } if (product.type.contains("msi")) { artifacts.push({ fileTags: ["msi"], filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ModUtils.moduleProperty(product, "windowsInstallerSuffix")) }); } if (ModUtils.moduleProperty(product, "debugInformation")) { artifacts.push({ fileTags: ["wixpdb"], filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".wixpdb") }); } return artifacts; } outputFileTags: ["application", "msi", "wixpdb", "wixsetup"] prepare: { var i; var primaryOutput; if (product.type.contains("wixsetup")) { primaryOutput = outputs.wixsetup[0]; } else if (product.type.contains("msi")) { primaryOutput = outputs.msi[0]; } else { throw("WiX: Unsupported product type '" + product.type + "'"); } var args = ["-nologo"]; if (!ModUtils.moduleProperty(product, "enablePackageValidation")) { args.push("-sval"); } if (ModUtils.moduleProperty(product, "warningLevel") === "none") { args.push("-sw"); } else { if (ModUtils.moduleProperty(product, "warningLevel") === "pedantic") { args.push("-pedantic"); } if (ModUtils.moduleProperty(product, "treatWarningsAsErrors")) { args.push("-wx"); } } if (ModUtils.moduleProperty(product, "verboseOutput")) { args.push("-v"); } args.push("-out"); args.push(FileInfo.toWindowsSeparators(primaryOutput.filePath)); if (ModUtils.moduleProperty(product, "debugInformation")) { args.push("-pdbout"); args.push(FileInfo.toWindowsSeparators(outputs.wixpdb[0].filePath)); } else { args.push("-spdb"); } var extensions = ModUtils.moduleProperty(product, "extensions"); for (i in extensions) { args.push("-ext"); args.push(extensions[i]); } for (i in inputs.wxl) { args.push("-loc"); args.push(FileInfo.toWindowsSeparators(inputs.wxl[i].filePath)); } if (product.type.contains("msi")) { var cultures = ModUtils.moduleProperty(product, "cultures"); args.push("-cultures:" + (cultures && cultures.length > 0 ? cultures.join(";") : "null")); } // User-supplied flags var flags = ModUtils.moduleProperty(product, "linkerFlags"); for (i in flags) { args.push(flags[i]); } for (i in inputs.wixobj) { args.push(FileInfo.toWindowsSeparators(inputs.wixobj[i].filePath)); } var cmd = new Command(ModUtils.moduleProperty(product, "linkerPath"), args); cmd.description = "linking " + primaryOutput.fileName; cmd.highlight = "linker"; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath); return cmd; } } } qbs-src-1.13.1/share/qbs/modules/xcode/000077500000000000000000000000001347155106100176135ustar00rootroot00000000000000qbs-src-1.13.1/share/qbs/modules/xcode/xcode.js000066400000000000000000000213601347155106100212550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var DarwinTools = require("qbs.DarwinTools"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); var PropertyList = require("qbs.PropertyList"); var Utilities = require("qbs.Utilities"); var XcodeArchSpecsReader = (function () { function XcodeArchSpecsReader(specsPath) { var plist = new PropertyList(); try { plist.readFromFile(specsPath); this.specsObject = plist.toObject(); } finally { plist.clear(); } } XcodeArchSpecsReader.prototype.getArchitectureSettings = function () { if (this.specsObject) { var names = []; for (var i = 0; i < this.specsObject.length; ++i) { var dict = this.specsObject[i]; var name = dict["ArchitectureSetting"]; if (name) names.push(name); } return names; } }; XcodeArchSpecsReader.prototype.getArchitectureSettingValue = function (settingName) { // settingName can be: ARCHS_STANDARD, ARCHS_STANDARD_32_BIT, ARCHS_STANDARD_64_BIT, // ARCHS_STANDARD_32_64_BIT, ARCHS_STANDARD_INCLUDING_64_BIT, or ARCHS_UNIVERSAL_IPHONE_OS. // NATIVE_ARCH_ACTUAL doesn't have a RealArchitectures property since it's determined by // Xcode programmatically. if (this.specsObject) { for (var i = 0; i < this.specsObject.length; ++i) { var dict = this.specsObject[i]; if (dict["ArchitectureSetting"] === settingName) { var realArchs = dict["RealArchitectures"]; if (realArchs) { var effectiveRealArchs = []; for (var j = 0; j < realArchs.length; ++j) { var re = /^\$\(([A-Za-z0-9_]+)\)$/; var match = realArchs[j].match(re); if (match) { var val = this.getArchitectureSettingValue(match[1]); // Don't silently omit values if missing. For example, if // ARCHS_FOO=[x86_64, $(ARCHS_BAR)], return 'undefined' instead of // simply [x86_64]. Not known to have any real world occurrences. if (!val) return undefined; Array.prototype.push.apply(effectiveRealArchs, val); } else { effectiveRealArchs.push(realArchs[j]); } } return effectiveRealArchs; } } } } }; return XcodeArchSpecsReader; }()); function sdkInfoList(sdksPath) { var sdkInfo = []; var sdks = File.directoryEntries(sdksPath, File.Dirs | File.NoDotAndDotDot); for (var i in sdks) { // SDK directory name must contain a version number; // we don't want the versionless iPhoneOS.sdk directory for example if (!sdks[i].match(/[0-9]+/)) continue; var settingsPlist = FileInfo.joinPaths(sdksPath, sdks[i], "SDKSettings.plist"); var propertyList = new PropertyList(); try { propertyList.readFromFile(settingsPlist); function checkPlist(plist) { if (!plist || !plist["CanonicalName"] || !plist["Version"]) return false; var re = /^([0-9]+)\.([0-9]+)$/; return plist["Version"].match(re); } var plist = propertyList.toObject(); if (!checkPlist(plist)) { console.warn("Skipping corrupted SDK installation: " + FileInfo.joinPaths(sdksPath, sdks[i])); continue; } sdkInfo.push(plist); } finally { propertyList.clear(); } } // Sort by SDK version number sdkInfo.sort(function (a, b) { var re = /^([0-9]+)\.([0-9]+)$/; a = a["Version"].match(re); if (a) a = {major: a[1], minor: a[2]}; b = b["Version"].match(re); if (b) b = {major: b[1], minor: b[2]}; if (a.major === b.major) return a.minor - b.minor; return a.major - b.major; }); return sdkInfo; } function findSigningIdentities(security, searchString) { var process; var identities; if (searchString) { try { process = new Process(); if (process.exec(security, ["find-identity", "-p", "codesigning", "-v"], true) !== 0) console.error(process.readStdErr()); var lines = process.readStdOut().split("\n"); for (var i in lines) { // e.g. 1) AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "Mac Developer: John Doe (XXXXXXXXXX) john.doe@example.org" var match = lines[i].match(/^\s*[0-9]+\)\s+([A-Fa-f0-9]{40})\s+"([^"]+)"$/); if (match !== null) { var hexId = match[1]; var displayName = match[2]; if (hexId === searchString || displayName.startsWith(searchString)) { if (!identities) identities = []; identities.push([hexId, displayName]); break; } } } } finally { process.close(); } } return identities; } function provisioningProfilePlistContents(filePath) { if (filePath === undefined) return undefined; var plist = new PropertyList(); try { plist.readFromFile(filePath); return plist.toObject(); } finally { plist.clear(); } } function archsSpecsPath(version, targetOS, platformType, platformPath, devicePlatformPath) { var _specsPluginBaseName; if (Utilities.versionCompare(version, "7") >= 0) { if (targetOS.contains("ios")) _specsPluginBaseName = "iOSPlatform"; if (targetOS.contains("tvos")) _specsPluginBaseName = "AppleTV"; if (targetOS.contains("watchos")) _specsPluginBaseName = "Watch"; } var _archSpecsDir = _specsPluginBaseName ? FileInfo.joinPaths(devicePlatformPath, "Developer", "Library", "Xcode", "PrivatePlugIns", "IDE" + _specsPluginBaseName + "SupportCore.ideplugin", "Contents", "Resources") : FileInfo.joinPaths(platformPath, "Developer", "Library", "Xcode", "Specifications"); var _archSpecsFileBaseName = targetOS.contains("ios") ? (targetOS.contains("ios-simulator") ? "iPhone Simulator " : "iPhoneOS") : DarwinTools.applePlatformDirectoryName(targetOS, platformType) + " "; if (_specsPluginBaseName) { switch (platformType) { case "device": return FileInfo.joinPaths(_archSpecsDir, "Device.xcspec"); case "simulator": return FileInfo.joinPaths(_archSpecsDir, "Simulator.xcspec"); } } return FileInfo.joinPaths(_archSpecsDir, _archSpecsFileBaseName + "Architectures.xcspec"); } qbs-src-1.13.1/share/qbs/modules/xcode/xcode.qbs000066400000000000000000000413621347155106100214320ustar00rootroot00000000000000import qbs.BundleTools import qbs.Environment import qbs.File import qbs.FileInfo import qbs.DarwinTools import qbs.ModUtils import qbs.Probes import qbs.PropertyList import 'xcode.js' as Xcode Module { id: xcodeModule Probes.XcodeProbe { id: xcodeProbe developerPath: xcodeModule.developerPath platformType: xcodeModule.platformType platformPath: xcodeModule.platformPath devicePlatformPath: xcodeModule.devicePlatformPath xcodebuildPath: xcodeModule.xcodebuildPath sdksPath: xcodeModule.sdksPath } condition: qbs.targetOS.contains("darwin") && qbs.toolchain && qbs.toolchain.contains("xcode") version: xcodeProbe.xcodeVersion property path developerPath: "/Applications/Xcode.app/Contents/Developer" property string sdk: DarwinTools.applePlatformName(qbs.targetOS, platformType) property stringList targetDevices: DarwinTools.targetDevices(qbs.targetOS) property string platformType: { if (qbs.targetOS.containsAny(["ios-simulator", "tvos-simulator", "watchos-simulator"])) return "simulator"; if (qbs.targetOS.containsAny(["ios", "tvos", "watchos"])) return "device"; } readonly property string sdkName: { if (_sdkSettings) { return _sdkSettings["CanonicalName"]; } } readonly property string sdkVersion: { if (_sdkSettings) { return _sdkSettings["Version"]; } } readonly property string latestSdkName: { if (_latestSdk) { return _latestSdk["CanonicalName"]; } } readonly property string latestSdkVersion: { if (_latestSdk) { return _latestSdk["Version"]; } } readonly property stringList availableSdkNames: { if (_availableSdks) { return _availableSdks.map(function (obj) { return obj["CanonicalName"]; }); } } readonly property stringList availableSdkVersions: { if (_availableSdks) { return _availableSdks.map(function (obj) { return obj["Version"]; }); } } property string signingIdentity readonly property string actualSigningIdentity: { if (_actualSigningIdentity && _actualSigningIdentity.length === 1) return _actualSigningIdentity[0][0]; } readonly property string actualSigningIdentityDisplayName: { if (_actualSigningIdentity && _actualSigningIdentity.length === 1) return _actualSigningIdentity[0][1]; } property string signingTimestamp: "none" property string provisioningProfile property string xcodebuildName: "xcodebuild" property string xcodebuildPath: FileInfo.joinPaths(developerPath, "usr", "bin", xcodebuildName) property string securityName: "security" property string securityPath: securityName property string codesignName: "codesign" property string codesignPath: codesignName property stringList codesignFlags readonly property path toolchainPath: FileInfo.joinPaths(toolchainsPath, "XcodeDefault" + ".xctoolchain") readonly property path platformPath: FileInfo.joinPaths(platformsPath, DarwinTools.applePlatformDirectoryName( qbs.targetOS, platformType) + ".platform") readonly property path devicePlatformPath: FileInfo.joinPaths( platformsPath, DarwinTools.applePlatformDirectoryName( qbs.targetOS, "device") + ".platform") readonly property path simulatorPlatformPath: FileInfo.joinPaths( platformsPath, DarwinTools.applePlatformDirectoryName( qbs.targetOS, "simulator") + ".platform") readonly property path sdkPath: FileInfo.joinPaths(sdksPath, DarwinTools.applePlatformDirectoryName( qbs.targetOS, platformType, sdkVersion) + ".sdk") // private properties readonly property path toolchainsPath: FileInfo.joinPaths(developerPath, "Toolchains") readonly property path platformsPath: FileInfo.joinPaths(developerPath, "Platforms") readonly property path sdksPath: FileInfo.joinPaths(platformPath, "Developer", "SDKs") readonly property path platformInfoPlist: FileInfo.joinPaths(platformPath, "Info.plist") readonly property path sdkSettingsPlist: FileInfo.joinPaths(sdkPath, "SDKSettings.plist") readonly property path toolchainInfoPlist: FileInfo.joinPaths(toolchainPath, "ToolchainInfo.plist") readonly property stringList _actualSigningIdentity: { if (/^[A-Fa-f0-9]{40}$/.test(signingIdentity)) { return signingIdentity; } var identities = Xcode.findSigningIdentities(securityPath, signingIdentity); if (identities && identities.length > 1) { throw "Signing identity '" + signingIdentity + "' is ambiguous"; } return identities; } property path provisioningProfilesPath: { return FileInfo.joinPaths(Environment.getEnv("HOME"), "Library/MobileDevice/Provisioning Profiles"); } readonly property stringList standardArchitectures: _architectureSettings["ARCHS_STANDARD"] readonly property var _architectureSettings: xcodeProbe.architectureSettings readonly property var _availableSdks: xcodeProbe.availableSdks readonly property var _latestSdk: _availableSdks[_availableSdks.length - 1] readonly property var _sdkSettings: { if (_availableSdks) { for (var i in _availableSdks) { if (_availableSdks[i]["Version"] === sdk) return _availableSdks[i]; if (_availableSdks[i]["CanonicalName"] === sdk) return _availableSdks[i]; } // Latest SDK available for the platform if (DarwinTools.applePlatformName(qbs.targetOS, platformType) === sdk) return _latestSdk; } } qbs.sysroot: sdkPath validate: { if (!_availableSdks) { throw "There are no SDKs available for this platform in the Xcode installation."; } if (!_sdkSettings) { throw "There is no matching SDK available for " + sdk + "."; } var validator = new ModUtils.PropertyValidator("xcode"); validator.setRequiredProperty("developerPath", developerPath); validator.setRequiredProperty("sdk", sdk); validator.setRequiredProperty("sdkName", sdkName); validator.setRequiredProperty("sdkVersion", sdkVersion); validator.setRequiredProperty("toolchainsPath", toolchainsPath); validator.setRequiredProperty("toolchainPath", toolchainPath); validator.setRequiredProperty("platformsPath", platformsPath); validator.setRequiredProperty("platformPath", platformPath); validator.setRequiredProperty("sdksPath", sdkPath); validator.setRequiredProperty("sdkPath", sdkPath); validator.addVersionValidator("sdkVersion", sdkVersion, 2, 2); validator.addCustomValidator("sdkName", sdkName, function (value) { return value === DarwinTools.applePlatformDirectoryName( qbs.targetOS, platformType, sdkVersion, false).toLowerCase(); }, "is '" + sdkName + "', but target OS is [" + qbs.targetOS.join(",") + "] and Xcode SDK version is '" + sdkVersion + "'"); validator.addCustomValidator("sdk", sdk, function (value) { return value === sdkName || (value + sdkVersion) === sdkName; }, "is '" + sdk + "', but canonical SDK name is '" + sdkName + "'"); validator.validate(); } property var buildEnv: { var env = { "DEVELOPER_DIR": developerPath, "SDKROOT": sdkPath }; var prefixes = [platformPath + "/Developer", toolchainPath, developerPath]; for (var i = 0; i < prefixes.length; ++i) { var codesign_allocate = prefixes[i] + "/usr/bin/codesign_allocate"; if (File.exists(codesign_allocate)) { env["CODESIGN_ALLOCATE"] = codesign_allocate; break; } } return env; } setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, false); v.prepend(product.xcode.platformPath + "/Developer/usr/bin"); v.prepend(product.xcode.developerPath + "/usr/bin"); v.set(); for (var key in product.xcode.buildEnv) { v = new ModUtils.EnvironmentVariable(key); v.value = product.xcode.buildEnv[key]; v.set(); } } Group { name: "Provisioning Profiles" prefix: xcode.provisioningProfilesPath + "/" files: ["*.mobileprovision", "*.provisionprofile"] fileTags: [] // HACK: provisioning profile handling is not yet ready and can break autotests } FileTagger { fileTags: ["xcode.entitlements"] patterns: ["*.entitlements"] } FileTagger { fileTags: ["xcode.provisioningprofile"] patterns: ["*.mobileprovision", "*.provisionprofile"] } Rule { inputs: ["xcode.provisioningprofile"] Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, "provisioning-profiles", input.fileName + ".xml") fileTags: ["xcode.provisioningprofile.data"] } prepare: { var cmds = []; var cmd = new Command("openssl", ["smime", "-verify", "-noverify", "-inform", "DER", "-in", input.filePath, "-out", output.filePath]); cmd.silent = true; cmd.stderrFilterFunction = function (output) { return output.replace("Verification successful\n", ""); }; cmds.push(cmd); cmd = new JavaScriptCommand(); cmd.silent = true; cmd.inputFilePath = input.filePath; cmd.outputFilePath = output.filePath; cmd.sourceCode = function() { var propertyList = new PropertyList(); try { propertyList.readFromFile(outputFilePath); propertyList.readFromObject({ data: propertyList.toObject(), fileName: FileInfo.fileName(inputFilePath), filePath: inputFilePath }); propertyList.writeToFile(outputFilePath, "xml1"); } finally { propertyList.clear(); } }; cmds.push(cmd); return cmds; } } Rule { multiplex: true inputs: ["xcode.provisioningprofile.data"] outputFileTags: ["xcode.provisioningprofile.main", "xcode.provisioningprofile.data.main"] outputArtifacts: { var artifacts = []; for (var i = 0; i < inputs["xcode.provisioningprofile.data"].length; ++i) { var dataFile = inputs["xcode.provisioningprofile.data"][i].filePath; var query = product.moduleProperty("xcode", "provisioningProfile"); var obj = Xcode.provisioningProfilePlistContents(dataFile); if (obj.data && (obj.data.UUID === query || obj.data.Name === query)) { console.log("Using provisioning profile: " + obj.filePath); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, obj.fileName), fileTags: ["xcode.provisioningprofile.main", obj.filePath] }); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, obj.fileName + ".xml"), fileTags: ["xcode.provisioningprofile.data.main", dataFile] }); } } return artifacts; } prepare: { var cmds = []; for (var tag in outputs) { for (var i = 0; i < outputs[tag].length; ++i) { var output = outputs[tag][i]; var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.inputFilePath = output.fileTags.filter(function(f) { return f.startsWith('/'); })[0] // QBS-754 cmd.outputFilePath = output.filePath; cmd.sourceCode = function() { File.copy(inputFilePath, outputFilePath); }; cmds.push(cmd); } } return cmds; } } Rule { inputs: ["xcode.entitlements", "xcode.provisioningprofile.data.main"] Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".xcent") fileTags: ["xcent", "bundle.input"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating entitlements"; cmd.highlight = "codegen"; cmd.bundleIdentifier = product.moduleProperty("bundle", "identifier"); cmd.signingEntitlements = inputs["xcode.entitlements"].map(function (a) { return a.filePath; }); cmd.platformPath = ModUtils.moduleProperty(product, "platformPath"); cmd.sdkPath = ModUtils.moduleProperty(product, "sdkPath"); cmd.sourceCode = function() { var i; var provData = Xcode.provisioningProfilePlistContents(input.filePath); if (provData) provData = provData.data; var aggregateEntitlements = {}; // Start building up an aggregate entitlements plist from the files in the SDKs, // which contain placeholders in the same manner as Info.plist function entitlementsFileContents(path) { return File.exists(path) ? BundleTools.infoPlistContents(path) : undefined; } var entitlementsSources = [ entitlementsFileContents(FileInfo.joinPaths(platformPath, "Entitlements.plist")), entitlementsFileContents(FileInfo.joinPaths(sdkPath, "Entitlements.plist")) ]; for (i = 0; i < signingEntitlements.length; ++i) { entitlementsSources.push(entitlementsFileContents(signingEntitlements[i])); } for (i = 0; i < entitlementsSources.length; ++i) { var contents = entitlementsSources[i]; for (var key in contents) { if (contents.hasOwnProperty(key)) aggregateEntitlements[key] = contents[key]; } } contents = provData["Entitlements"]; for (key in contents) { if (contents.hasOwnProperty(key) && !aggregateEntitlements.hasOwnProperty(key)) aggregateEntitlements[key] = contents[key]; } // Expand entitlements variables with data from the provisioning profile var env = { "AppIdentifierPrefix": provData["ApplicationIdentifierPrefix"] + ".", "CFBundleIdentifier": bundleIdentifier }; DarwinTools.expandPlistEnvironmentVariables(aggregateEntitlements, env, true); // Anything with an undefined or otherwise empty value should be removed // Only JSON-formatted plists can have null values, other formats error out // This also follows Xcode behavior DarwinTools.cleanPropertyList(aggregateEntitlements); var plist = new PropertyList(); try { plist.readFromObject(aggregateEntitlements); plist.writeToFile(outputs.xcent[0].filePath, "xml1"); } finally { plist.clear(); } }; return [cmd]; } } } qbs-src-1.13.1/share/share.qbs000066400000000000000000000113411347155106100160650ustar00rootroot00000000000000import qbs import qbs.File import qbs.FileInfo import qbs.TextFile import qbs.Utilities Product { name: "qbs resources" type: ["qbs qml type descriptions", "qbs qml type bundle"] Depends { name: "qbsbuildconfig" } Group { name: "Incredibuild" prefix: "../bin/" files: ["ibmsvc.xml", "ibqbs.bat"] fileTags: [] qbs.install: qbs.targetOS.contains("windows") qbs.installDir: qbsbuildconfig.appInstallDir } Group { name: "Python executables" files: ["../src/3rdparty/python/bin/dmgbuild"] fileTags: ["qbs resources"] qbs.install: true qbs.installDir: qbsbuildconfig.libexecInstallDir qbs.installSourceBase: "../src/3rdparty/python/bin" } Group { name: "Python packages" prefix: "../src/3rdparty/python/**/" files: ["*.py"] fileTags: ["qbs resources"] qbs.install: true qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share/qbs/python" qbs.installSourceBase: "../src/3rdparty/python/lib/python2.7/site-packages" } Group { name: "Imports" files: ["qbs/imports/qbs/**/*"] fileTags: ["qbs resources"] qbs.install: true qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share" qbs.installSourceBase: "." } Group { name: "Modules" files: ["qbs/modules/**/*"] fileTags: ["qbs resources"] qbs.install: true qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share" qbs.installSourceBase: "." } Group { name: "Module providers" files: ["qbs/module-providers/**/*"] fileTags: ["qbs resources"] qbs.install: true qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share" qbs.installSourceBase: "." } Group { name: "Examples as resources" files: ["../examples/**/*"] fileTags: [] qbs.install: true qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share/qbs" qbs.installSourceBase: ".." } Rule { condition: Utilities.versionCompare(product.qbs.version, "1.9.1") >= 0 multiplex: true Artifact { filePath: "qbs.qmltypes" fileTags: ["qbs qml type descriptions"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Generating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(Utilities.qmlTypeInfo()); } finally { if (tf) tf.close(); } }; return cmd; } } Rule { condition: Utilities.versionCompare(product.qbs.version, "1.9.1") >= 0 multiplex: true Artifact { filePath: "qbs-bundle.json" fileTags: ["qbs qml type bundle"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Generating " + output.fileName; cmd.highlight = "codegen"; cmd.sourceCode = function() { var tf; try { var imports = File.directoryEntries(FileInfo.joinPaths(product.sourceDirectory, "qbs", "imports", "qbs"), File.Dirs | File.NoDotAndDotDot).filter( function(i) { return i !== "base"; }).concat( Utilities.builtinExtensionNames()).map( function(i) { return "qbs." + i; }); imports.sort(); var obj = { "name": "qbs", "searchPaths": ["$(QBS_IMPORT_PATH)"], "installPaths": ["$(QBS_IMPORT_PATH)"], "implicitImports": ["__javascriptQt5__"], "supportedImports": ["qbs"].concat(imports) }; tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(obj, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } Group { name: "QML Type Info" fileTagsFilter: ["qbs qml type descriptions", "qbs qml type bundle"] qbs.install: true qbs.installDir: qbsbuildconfig.qmlTypeDescriptionsInstallDir } } qbs-src-1.13.1/src/000077500000000000000000000000001347155106100137415ustar00rootroot00000000000000qbs-src-1.13.1/src/3rdparty/000077500000000000000000000000001347155106100155115ustar00rootroot00000000000000qbs-src-1.13.1/src/3rdparty/python/000077500000000000000000000000001347155106100170325ustar00rootroot00000000000000qbs-src-1.13.1/src/3rdparty/python/.gitignore000066400000000000000000000000351347155106100210200ustar00rootroot00000000000000*.pyc *.dist-info *.egg-info qbs-src-1.13.1/src/3rdparty/python/bin/000077500000000000000000000000001347155106100176025ustar00rootroot00000000000000qbs-src-1.13.1/src/3rdparty/python/bin/dmgbuild000077500000000000000000000025501347155106100213210ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- from __future__ import unicode_literals from __future__ import print_function import dmgbuild import sys import argparse parser = argparse.ArgumentParser(description='Construct a disk image file.') parser.add_argument('volume_name', metavar='volume-name', help='The name to give to the volume (this will appear in the title bar when the user mounts the disk image).') parser.add_argument('filename', metavar='output.dmg', help='The filename of the disk image to create.') parser.add_argument('-s', '--settings', help='The path of the settings file.') parser.add_argument('-D', dest='defines', action='append', default=[], help='Define a value for the settings file (e.g. -Dfoo=bar).') parser.add_argument('--no-hidpi', dest='lookForHiDPI', action='store_false', default=True, help='Do not search for HiDPI versions of the background image (if specified)') args = parser.parse_args() defines = {} for d in args.defines: k,v = d.split('=', 1) k = k.strip() v = v.strip() if (v.startswith("'") and v.endswith("'")) \ or (v.startswith('"') and v.endswith('"')): v = v[1:-1] defines[k] = v dmgbuild.build_dmg(args.filename, args.volume_name, args.settings, defines=defines, lookForHiDPI=args.lookForHiDPI) qbs-src-1.13.1/src/3rdparty/python/lib/000077500000000000000000000000001347155106100176005ustar00rootroot00000000000000qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/000077500000000000000000000000001347155106100213505ustar00rootroot00000000000000qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/000077500000000000000000000000001347155106100240705ustar00rootroot00000000000000qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/biplist/000077500000000000000000000000001347155106100255365ustar00rootroot00000000000000qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/biplist/LICENSE000066400000000000000000000027461347155106100265540ustar00rootroot00000000000000Copyright (c) 2010, Andrew Wooster All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of biplist nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/biplist/__init__.py000066400000000000000000001107011347155106100276470ustar00rootroot00000000000000"""biplist -- a library for reading and writing binary property list files. Binary Property List (plist) files provide a faster and smaller serialization format for property lists on OS X. This is a library for generating binary plists which can be read by OS X, iOS, or other clients. The API models the plistlib API, and will call through to plistlib when XML serialization or deserialization is required. To generate plists with UID values, wrap the values with the Uid object. The value must be an int. To generate plists with NSData/CFData values, wrap the values with the Data object. The value must be a string. Date values can only be datetime.datetime objects. The exceptions InvalidPlistException and NotBinaryPlistException may be thrown to indicate that the data cannot be serialized or deserialized as a binary plist. Plist generation example: from biplist import * from datetime import datetime plist = {'aKey':'aValue', '0':1.322, 'now':datetime.now(), 'list':[1,2,3], 'tuple':('a','b','c') } try: writePlist(plist, "example.plist") except (InvalidPlistException, NotBinaryPlistException), e: print "Something bad happened:", e Plist parsing example: from biplist import * try: plist = readPlist("example.plist") print plist except (InvalidPlistException, NotBinaryPlistException), e: print "Not a plist:", e """ from collections import namedtuple import datetime import io import math import plistlib from struct import pack, unpack, unpack_from from struct import error as struct_error import sys import time try: unicode unicodeEmpty = r'' except NameError: unicode = str unicodeEmpty = '' try: long except NameError: long = int try: {}.iteritems iteritems = lambda x: x.iteritems() except AttributeError: iteritems = lambda x: x.items() __all__ = [ 'Uid', 'Data', 'readPlist', 'writePlist', 'readPlistFromString', 'writePlistToString', 'InvalidPlistException', 'NotBinaryPlistException' ] # Apple uses Jan 1, 2001 as a base for all plist date/times. apple_reference_date = datetime.datetime.utcfromtimestamp(978307200) class Uid(object): """Wrapper around integers for representing UID values. This is used in keyed archiving.""" integer = 0 def __init__(self, integer): self.integer = integer def __repr__(self): return "Uid(%d)" % self.integer def __eq__(self, other): if isinstance(self, Uid) and isinstance(other, Uid): return self.integer == other.integer return False def __cmp__(self, other): return self.integer - other.integer def __lt__(self, other): return self.integer < other.integer def __hash__(self): return self.integer def __int__(self): return int(self.integer) class Data(bytes): """Wrapper around bytes to distinguish Data values.""" class InvalidPlistException(Exception): """Raised when the plist is incorrectly formatted.""" class NotBinaryPlistException(Exception): """Raised when a binary plist was expected but not encountered.""" def readPlist(pathOrFile): """Raises NotBinaryPlistException, InvalidPlistException""" didOpen = False result = None if isinstance(pathOrFile, (bytes, unicode)): pathOrFile = open(pathOrFile, 'rb') didOpen = True try: reader = PlistReader(pathOrFile) result = reader.parse() except NotBinaryPlistException as e: try: pathOrFile.seek(0) result = None if hasattr(plistlib, 'loads'): contents = None if isinstance(pathOrFile, (bytes, unicode)): with open(pathOrFile, 'rb') as f: contents = f.read() else: contents = pathOrFile.read() result = plistlib.loads(contents) else: result = plistlib.readPlist(pathOrFile) result = wrapDataObject(result, for_binary=True) except Exception as e: raise InvalidPlistException(e) finally: if didOpen: pathOrFile.close() return result def wrapDataObject(o, for_binary=False): if isinstance(o, Data) and not for_binary: v = sys.version_info if not (v[0] >= 3 and v[1] >= 4): o = plistlib.Data(o) elif isinstance(o, (bytes, plistlib.Data)) and for_binary: if hasattr(o, 'data'): o = Data(o.data) elif isinstance(o, tuple): o = wrapDataObject(list(o), for_binary) o = tuple(o) elif isinstance(o, list): for i in range(len(o)): o[i] = wrapDataObject(o[i], for_binary) elif isinstance(o, dict): for k in o: o[k] = wrapDataObject(o[k], for_binary) return o def writePlist(rootObject, pathOrFile, binary=True): if not binary: rootObject = wrapDataObject(rootObject, binary) if hasattr(plistlib, "dump"): if isinstance(pathOrFile, (bytes, unicode)): with open(pathOrFile, 'wb') as f: return plistlib.dump(rootObject, f) else: return plistlib.dump(rootObject, pathOrFile) else: return plistlib.writePlist(rootObject, pathOrFile) else: didOpen = False if isinstance(pathOrFile, (bytes, unicode)): pathOrFile = open(pathOrFile, 'wb') didOpen = True writer = PlistWriter(pathOrFile) result = writer.writeRoot(rootObject) if didOpen: pathOrFile.close() return result def readPlistFromString(data): return readPlist(io.BytesIO(data)) def writePlistToString(rootObject, binary=True): if not binary: rootObject = wrapDataObject(rootObject, binary) if hasattr(plistlib, "dumps"): return plistlib.dumps(rootObject) elif hasattr(plistlib, "writePlistToBytes"): return plistlib.writePlistToBytes(rootObject) else: return plistlib.writePlistToString(rootObject) else: ioObject = io.BytesIO() writer = PlistWriter(ioObject) writer.writeRoot(rootObject) return ioObject.getvalue() def is_stream_binary_plist(stream): stream.seek(0) header = stream.read(7) if header == b'bplist0': return True else: return False PlistTrailer = namedtuple('PlistTrailer', 'offsetSize, objectRefSize, offsetCount, topLevelObjectNumber, offsetTableOffset') PlistByteCounts = namedtuple('PlistByteCounts', 'nullBytes, boolBytes, intBytes, realBytes, dateBytes, dataBytes, stringBytes, uidBytes, arrayBytes, setBytes, dictBytes') class PlistReader(object): file = None contents = '' offsets = None trailer = None currentOffset = 0 # Used to detect recursive object references. offsetsStack = [] def __init__(self, fileOrStream): """Raises NotBinaryPlistException.""" self.reset() self.file = fileOrStream def parse(self): return self.readRoot() def reset(self): self.trailer = None self.contents = '' self.offsets = [] self.currentOffset = 0 self.offsetsStack = [] def readRoot(self): result = None self.reset() # Get the header, make sure it's a valid file. if not is_stream_binary_plist(self.file): raise NotBinaryPlistException() self.file.seek(0) self.contents = self.file.read() if len(self.contents) < 32: raise InvalidPlistException("File is too short.") trailerContents = self.contents[-32:] try: self.trailer = PlistTrailer._make(unpack("!xxxxxxBBQQQ", trailerContents)) if pow(2, self.trailer.offsetSize*8) < self.trailer.offsetTableOffset: raise InvalidPlistException("Offset size insufficient to reference all objects.") if pow(2, self.trailer.objectRefSize*8) < self.trailer.offsetCount: raise InvalidPlistException("Too many offsets to represent in size of object reference representation.") offset_size = self.trailer.offsetSize * self.trailer.offsetCount offset = self.trailer.offsetTableOffset if offset + offset_size > pow(2, 64): raise InvalidPlistException("Offset table is excessively long.") if self.trailer.offsetSize > 16: raise InvalidPlistException("Offset size is greater than maximum integer size.") if self.trailer.objectRefSize == 0: raise InvalidPlistException("Object reference size is zero.") if offset >= len(self.contents) - 32: raise InvalidPlistException("Offset table offset is too large.") if offset < len("bplist00x"): raise InvalidPlistException("Offset table offset is too small.") if self.trailer.topLevelObjectNumber >= self.trailer.offsetCount: raise InvalidPlistException("Top level object number is larger than the number of objects.") offset_contents = self.contents[offset:offset+offset_size] offset_i = 0 offset_table_length = len(offset_contents) while offset_i < self.trailer.offsetCount: begin = self.trailer.offsetSize*offset_i end = begin+self.trailer.offsetSize if end > offset_table_length: raise InvalidPlistException("End of object is at invalid offset %d in offset table of length %d" % (end, offset_table_length)) tmp_contents = offset_contents[begin:end] tmp_sized = self.getSizedInteger(tmp_contents, self.trailer.offsetSize) self.offsets.append(tmp_sized) offset_i += 1 self.setCurrentOffsetToObjectNumber(self.trailer.topLevelObjectNumber) result = self.readObject() except TypeError as e: raise InvalidPlistException(e) return result def setCurrentOffsetToObjectNumber(self, objectNumber): if objectNumber > len(self.offsets) - 1: raise InvalidPlistException("Invalid offset number: %d" % objectNumber) self.currentOffset = self.offsets[objectNumber] if self.currentOffset in self.offsetsStack: raise InvalidPlistException("Recursive data structure detected in object: %d" % objectNumber) def beginOffsetProtection(self): self.offsetsStack.append(self.currentOffset) return self.currentOffset def endOffsetProtection(self, offset): try: index = self.offsetsStack.index(offset) self.offsetsStack = self.offsetsStack[:index] except ValueError as e: pass def readObject(self): protection = self.beginOffsetProtection() result = None tmp_byte = self.contents[self.currentOffset:self.currentOffset+1] if len(tmp_byte) != 1: raise InvalidPlistException("No object found at offset: %d" % self.currentOffset) marker_byte = unpack("!B", tmp_byte)[0] format = (marker_byte >> 4) & 0x0f extra = marker_byte & 0x0f self.currentOffset += 1 def proc_extra(extra): if extra == 0b1111: extra = self.readObject() return extra # bool, null, or fill byte if format == 0b0000: if extra == 0b0000: result = None elif extra == 0b1000: result = False elif extra == 0b1001: result = True elif extra == 0b1111: pass # fill byte else: raise InvalidPlistException("Invalid object found at offset: %d" % (self.currentOffset - 1)) # int elif format == 0b0001: result = self.readInteger(pow(2, extra)) # real elif format == 0b0010: result = self.readReal(extra) # date elif format == 0b0011 and extra == 0b0011: result = self.readDate() # data elif format == 0b0100: extra = proc_extra(extra) result = self.readData(extra) # ascii string elif format == 0b0101: extra = proc_extra(extra) result = self.readAsciiString(extra) # Unicode string elif format == 0b0110: extra = proc_extra(extra) result = self.readUnicode(extra) # uid elif format == 0b1000: result = self.readUid(extra) # array elif format == 0b1010: extra = proc_extra(extra) result = self.readArray(extra) # set elif format == 0b1100: extra = proc_extra(extra) result = set(self.readArray(extra)) # dict elif format == 0b1101: extra = proc_extra(extra) result = self.readDict(extra) else: raise InvalidPlistException("Invalid object found: {format: %s, extra: %s}" % (bin(format), bin(extra))) self.endOffsetProtection(protection) return result def readContents(self, length, description="Object contents"): end = self.currentOffset + length if end >= len(self.contents) - 32: raise InvalidPlistException("%s extends into trailer" % description) elif length < 0: raise InvalidPlistException("%s length is less than zero" % length) data = self.contents[self.currentOffset:end] return data def readInteger(self, byteSize): data = self.readContents(byteSize, "Integer") self.currentOffset = self.currentOffset + byteSize return self.getSizedInteger(data, byteSize, as_number=True) def readReal(self, length): to_read = pow(2, length) data = self.readContents(to_read, "Real") if length == 2: # 4 bytes result = unpack('>f', data)[0] elif length == 3: # 8 bytes result = unpack('>d', data)[0] else: raise InvalidPlistException("Unknown Real of length %d bytes" % to_read) return result def readRefs(self, count): refs = [] i = 0 while i < count: fragment = self.readContents(self.trailer.objectRefSize, "Object reference") ref = self.getSizedInteger(fragment, len(fragment)) refs.append(ref) self.currentOffset += self.trailer.objectRefSize i += 1 return refs def readArray(self, count): if not isinstance(count, (int, long)): raise InvalidPlistException("Count of entries in dict isn't of integer type.") result = [] values = self.readRefs(count) i = 0 while i < len(values): self.setCurrentOffsetToObjectNumber(values[i]) value = self.readObject() result.append(value) i += 1 return result def readDict(self, count): if not isinstance(count, (int, long)): raise InvalidPlistException("Count of keys/values in dict isn't of integer type.") result = {} keys = self.readRefs(count) values = self.readRefs(count) i = 0 while i < len(keys): self.setCurrentOffsetToObjectNumber(keys[i]) key = self.readObject() self.setCurrentOffsetToObjectNumber(values[i]) value = self.readObject() result[key] = value i += 1 return result def readAsciiString(self, length): if not isinstance(length, (int, long)): raise InvalidPlistException("Length of ASCII string isn't of integer type.") data = self.readContents(length, "ASCII string") result = unpack("!%ds" % length, data)[0] self.currentOffset += length return str(result.decode('ascii')) def readUnicode(self, length): if not isinstance(length, (int, long)): raise InvalidPlistException("Length of Unicode string isn't of integer type.") actual_length = length*2 data = self.readContents(actual_length, "Unicode string") self.currentOffset += actual_length return data.decode('utf_16_be') def readDate(self): data = self.readContents(8, "Date") x = unpack(">d", data)[0] if math.isnan(x): raise InvalidPlistException("Date is NaN") # Use timedelta to workaround time_t size limitation on 32-bit python. try: result = datetime.timedelta(seconds=x) + apple_reference_date except OverflowError: if x > 0: result = datetime.datetime.max else: result = datetime.datetime.min self.currentOffset += 8 return result def readData(self, length): if not isinstance(length, (int, long)): raise InvalidPlistException("Length of data isn't of integer type.") result = self.readContents(length, "Data") self.currentOffset += length return Data(result) def readUid(self, length): if not isinstance(length, (int, long)): raise InvalidPlistException("Uid length isn't of integer type.") return Uid(self.readInteger(length+1)) def getSizedInteger(self, data, byteSize, as_number=False): """Numbers of 8 bytes are signed integers when they refer to numbers, but unsigned otherwise.""" result = 0 if byteSize == 0: raise InvalidPlistException("Encountered integer with byte size of 0.") # 1, 2, and 4 byte integers are unsigned elif byteSize == 1: result = unpack('>B', data)[0] elif byteSize == 2: result = unpack('>H', data)[0] elif byteSize == 4: result = unpack('>L', data)[0] elif byteSize == 8: if as_number: result = unpack('>q', data)[0] else: result = unpack('>Q', data)[0] elif byteSize <= 16: # Handle odd-sized or integers larger than 8 bytes # Don't naively go over 16 bytes, in order to prevent infinite loops. result = 0 if hasattr(int, 'from_bytes'): result = int.from_bytes(data, 'big') else: for byte in data: if not isinstance(byte, int): # Python3.0-3.1.x return ints, 2.x return str byte = unpack_from('>B', byte)[0] result = (result << 8) | byte else: raise InvalidPlistException("Encountered integer longer than 16 bytes.") return result class HashableWrapper(object): def __init__(self, value): self.value = value def __repr__(self): return "" % [self.value] class BoolWrapper(object): def __init__(self, value): self.value = value def __repr__(self): return "" % self.value class FloatWrapper(object): _instances = {} def __new__(klass, value): # Ensure FloatWrapper(x) for a given float x is always the same object wrapper = klass._instances.get(value) if wrapper is None: wrapper = object.__new__(klass) wrapper.value = value klass._instances[value] = wrapper return wrapper def __repr__(self): return "" % self.value class StringWrapper(object): __instances = {} encodedValue = None encoding = None def __new__(cls, value): '''Ensure we only have a only one instance for any string, and that we encode ascii as 1-byte-per character when possible''' encodedValue = None for encoding in ('ascii', 'utf_16_be'): try: encodedValue = value.encode(encoding) except: pass if encodedValue is not None: if encodedValue not in cls.__instances: cls.__instances[encodedValue] = super(StringWrapper, cls).__new__(cls) cls.__instances[encodedValue].encodedValue = encodedValue cls.__instances[encodedValue].encoding = encoding return cls.__instances[encodedValue] raise ValueError('Unable to get ascii or utf_16_be encoding for %s' % repr(value)) def __len__(self): '''Return roughly the number of characters in this string (half the byte length)''' if self.encoding == 'ascii': return len(self.encodedValue) else: return len(self.encodedValue)//2 def __lt__(self, other): return self.encodedValue < other.encodedValue @property def encodingMarker(self): if self.encoding == 'ascii': return 0b0101 else: return 0b0110 def __repr__(self): return '' % (self.encoding, self.encodedValue) class PlistWriter(object): header = b'bplist00bybiplist1.0' file = None byteCounts = None trailer = None computedUniques = None writtenReferences = None referencePositions = None wrappedTrue = None wrappedFalse = None # Used to detect recursive object references. objectsStack = [] def __init__(self, file): self.reset() self.file = file self.wrappedTrue = BoolWrapper(True) self.wrappedFalse = BoolWrapper(False) def reset(self): self.byteCounts = PlistByteCounts(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) self.trailer = PlistTrailer(0, 0, 0, 0, 0) # A set of all the uniques which have been computed. self.computedUniques = set() # A list of all the uniques which have been written. self.writtenReferences = {} # A dict of the positions of the written uniques. self.referencePositions = {} self.objectsStack = [] def positionOfObjectReference(self, obj): """If the given object has been written already, return its position in the offset table. Otherwise, return None.""" return self.writtenReferences.get(obj) def writeRoot(self, root): """ Strategy is: - write header - wrap root object so everything is hashable - compute size of objects which will be written - need to do this in order to know how large the object refs will be in the list/dict/set reference lists - write objects - keep objects in writtenReferences - keep positions of object references in referencePositions - write object references with the length computed previously - computer object reference length - write object reference positions - write trailer """ output = self.header wrapped_root = self.wrapRoot(root) self.computeOffsets(wrapped_root, asReference=True, isRoot=True) self.trailer = self.trailer._replace(**{'objectRefSize':self.intSize(len(self.computedUniques))}) self.writeObjectReference(wrapped_root, output) output = self.writeObject(wrapped_root, output, setReferencePosition=True) # output size at this point is an upper bound on how big the # object reference offsets need to be. self.trailer = self.trailer._replace(**{ 'offsetSize':self.intSize(len(output)), 'offsetCount':len(self.computedUniques), 'offsetTableOffset':len(output), 'topLevelObjectNumber':0 }) output = self.writeOffsetTable(output) output += pack('!xxxxxxBBQQQ', *self.trailer) self.file.write(output) def beginRecursionProtection(self, obj): if not isinstance(obj, (set, dict, list, tuple)): return if id(obj) in self.objectsStack: raise InvalidPlistException("Recursive containers are not allowed in plists.") self.objectsStack.append(id(obj)) def endRecursionProtection(self, obj): if not isinstance(obj, (set, dict, list, tuple)): return try: index = self.objectsStack.index(id(obj)) self.objectsStack = self.objectsStack[:index] except ValueError as e: pass def wrapRoot(self, root): result = None self.beginRecursionProtection(root) if isinstance(root, bool): if root is True: result = self.wrappedTrue else: result = self.wrappedFalse elif isinstance(root, float): result = FloatWrapper(root) elif isinstance(root, set): n = set() for value in root: n.add(self.wrapRoot(value)) result = HashableWrapper(n) elif isinstance(root, dict): n = {} for key, value in iteritems(root): n[self.wrapRoot(key)] = self.wrapRoot(value) result = HashableWrapper(n) elif isinstance(root, list): n = [] for value in root: n.append(self.wrapRoot(value)) result = HashableWrapper(n) elif isinstance(root, tuple): n = tuple([self.wrapRoot(value) for value in root]) result = HashableWrapper(n) elif isinstance(root, (str, unicode)) and not isinstance(root, Data): result = StringWrapper(root) elif isinstance(root, bytes): result = Data(root) else: result = root self.endRecursionProtection(root) return result def incrementByteCount(self, field, incr=1): self.byteCounts = self.byteCounts._replace(**{field:self.byteCounts.__getattribute__(field) + incr}) def computeOffsets(self, obj, asReference=False, isRoot=False): def check_key(key): if key is None: raise InvalidPlistException('Dictionary keys cannot be null in plists.') elif isinstance(key, Data): raise InvalidPlistException('Data cannot be dictionary keys in plists.') elif not isinstance(key, StringWrapper): raise InvalidPlistException('Keys must be strings.') def proc_size(size): if size > 0b1110: size += self.intSize(size) return size # If this should be a reference, then we keep a record of it in the # uniques table. if asReference: if obj in self.computedUniques: return else: self.computedUniques.add(obj) if obj is None: self.incrementByteCount('nullBytes') elif isinstance(obj, BoolWrapper): self.incrementByteCount('boolBytes') elif isinstance(obj, Uid): size = self.intSize(obj.integer) self.incrementByteCount('uidBytes', incr=1+size) elif isinstance(obj, (int, long)): size = self.intSize(obj) self.incrementByteCount('intBytes', incr=1+size) elif isinstance(obj, FloatWrapper): size = self.realSize(obj) self.incrementByteCount('realBytes', incr=1+size) elif isinstance(obj, datetime.datetime): self.incrementByteCount('dateBytes', incr=2) elif isinstance(obj, Data): size = proc_size(len(obj)) self.incrementByteCount('dataBytes', incr=1+size) elif isinstance(obj, StringWrapper): size = proc_size(len(obj)) self.incrementByteCount('stringBytes', incr=1+size) elif isinstance(obj, HashableWrapper): obj = obj.value if isinstance(obj, set): size = proc_size(len(obj)) self.incrementByteCount('setBytes', incr=1+size) for value in obj: self.computeOffsets(value, asReference=True) elif isinstance(obj, (list, tuple)): size = proc_size(len(obj)) self.incrementByteCount('arrayBytes', incr=1+size) for value in obj: asRef = True self.computeOffsets(value, asReference=True) elif isinstance(obj, dict): size = proc_size(len(obj)) self.incrementByteCount('dictBytes', incr=1+size) for key, value in iteritems(obj): check_key(key) self.computeOffsets(key, asReference=True) self.computeOffsets(value, asReference=True) else: raise InvalidPlistException("Unknown object type: %s (%s)" % (type(obj).__name__, repr(obj))) def writeObjectReference(self, obj, output): """Tries to write an object reference, adding it to the references table. Does not write the actual object bytes or set the reference position. Returns a tuple of whether the object was a new reference (True if it was, False if it already was in the reference table) and the new output. """ position = self.positionOfObjectReference(obj) if position is None: self.writtenReferences[obj] = len(self.writtenReferences) output += self.binaryInt(len(self.writtenReferences) - 1, byteSize=self.trailer.objectRefSize) return (True, output) else: output += self.binaryInt(position, byteSize=self.trailer.objectRefSize) return (False, output) def writeObject(self, obj, output, setReferencePosition=False): """Serializes the given object to the output. Returns output. If setReferencePosition is True, will set the position the object was written. """ def proc_variable_length(format, length): result = b'' if length > 0b1110: result += pack('!B', (format << 4) | 0b1111) result = self.writeObject(length, result) else: result += pack('!B', (format << 4) | length) return result def timedelta_total_seconds(td): # Shim for Python 2.6 compatibility, which doesn't have total_seconds. # Make one argument a float to ensure the right calculation. return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10.0**6) / 10.0**6 if setReferencePosition: self.referencePositions[obj] = len(output) if obj is None: output += pack('!B', 0b00000000) elif isinstance(obj, BoolWrapper): if obj.value is False: output += pack('!B', 0b00001000) else: output += pack('!B', 0b00001001) elif isinstance(obj, Uid): size = self.intSize(obj.integer) output += pack('!B', (0b1000 << 4) | size - 1) output += self.binaryInt(obj.integer) elif isinstance(obj, (int, long)): byteSize = self.intSize(obj) root = math.log(byteSize, 2) output += pack('!B', (0b0001 << 4) | int(root)) output += self.binaryInt(obj, as_number=True) elif isinstance(obj, FloatWrapper): # just use doubles output += pack('!B', (0b0010 << 4) | 3) output += self.binaryReal(obj) elif isinstance(obj, datetime.datetime): try: timestamp = (obj - apple_reference_date).total_seconds() except AttributeError: timestamp = timedelta_total_seconds(obj - apple_reference_date) output += pack('!B', 0b00110011) output += pack('!d', float(timestamp)) elif isinstance(obj, Data): output += proc_variable_length(0b0100, len(obj)) output += obj elif isinstance(obj, StringWrapper): output += proc_variable_length(obj.encodingMarker, len(obj)) output += obj.encodedValue elif isinstance(obj, bytes): output += proc_variable_length(0b0101, len(obj)) output += obj elif isinstance(obj, HashableWrapper): obj = obj.value if isinstance(obj, (set, list, tuple)): if isinstance(obj, set): output += proc_variable_length(0b1100, len(obj)) else: output += proc_variable_length(0b1010, len(obj)) objectsToWrite = [] for objRef in sorted(obj) if isinstance(obj, set) else obj: (isNew, output) = self.writeObjectReference(objRef, output) if isNew: objectsToWrite.append(objRef) for objRef in objectsToWrite: output = self.writeObject(objRef, output, setReferencePosition=True) elif isinstance(obj, dict): output += proc_variable_length(0b1101, len(obj)) keys = [] values = [] objectsToWrite = [] for key, value in sorted(iteritems(obj)): keys.append(key) values.append(value) for key in keys: (isNew, output) = self.writeObjectReference(key, output) if isNew: objectsToWrite.append(key) for value in values: (isNew, output) = self.writeObjectReference(value, output) if isNew: objectsToWrite.append(value) for objRef in objectsToWrite: output = self.writeObject(objRef, output, setReferencePosition=True) return output def writeOffsetTable(self, output): """Writes all of the object reference offsets.""" all_positions = [] writtenReferences = list(self.writtenReferences.items()) writtenReferences.sort(key=lambda x: x[1]) for obj,order in writtenReferences: # Porting note: Elsewhere we deliberately replace empty unicdoe strings # with empty binary strings, but the empty unicode string # goes into writtenReferences. This isn't an issue in Py2 # because u'' and b'' have the same hash; but it is in # Py3, where they don't. if bytes != str and obj == unicodeEmpty: obj = b'' position = self.referencePositions.get(obj) if position is None: raise InvalidPlistException("Error while writing offsets table. Object not found. %s" % obj) output += self.binaryInt(position, self.trailer.offsetSize) all_positions.append(position) return output def binaryReal(self, obj): # just use doubles result = pack('>d', obj.value) return result def binaryInt(self, obj, byteSize=None, as_number=False): result = b'' if byteSize is None: byteSize = self.intSize(obj) if byteSize == 1: result += pack('>B', obj) elif byteSize == 2: result += pack('>H', obj) elif byteSize == 4: result += pack('>L', obj) elif byteSize == 8: if as_number: result += pack('>q', obj) else: result += pack('>Q', obj) elif byteSize <= 16: try: result = pack('>Q', 0) + pack('>Q', obj) except struct_error as e: raise InvalidPlistException("Unable to pack integer %d: %s" % (obj, e)) else: raise InvalidPlistException("Core Foundation can't handle integers with size greater than 16 bytes.") return result def intSize(self, obj): """Returns the number of bytes necessary to store the given integer.""" # SIGNED if obj < 0: # Signed integer, always 8 bytes return 8 # UNSIGNED elif obj <= 0xFF: # 1 byte return 1 elif obj <= 0xFFFF: # 2 bytes return 2 elif obj <= 0xFFFFFFFF: # 4 bytes return 4 # SIGNED # 0x7FFFFFFFFFFFFFFF is the max. elif obj <= 0x7FFFFFFFFFFFFFFF: # 8 bytes signed return 8 elif obj <= 0xffffffffffffffff: # 8 bytes unsigned return 16 else: raise InvalidPlistException("Core Foundation can't handle integers with size greater than 8 bytes.") def realSize(self, obj): return 8 qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/biplist/qt_attribution.json000066400000000000000000000007501347155106100315030ustar00rootroot00000000000000{ "Id": "biplist", "Name": "biplist", "QDocModule": "qbs", "QtUsage": "Used in the qbs dmg module for building Apple disk images.", "Description": "biplist is a library for reading/writing binary plists.", "Homepage": "https://bitbucket.org/wooster/biplist", "Version": "1.0.2", "License": "BSD 3-clause \"New\" or \"Revised\" License", "LicenseId": "BSD-3-Clause", "LicenseFile": "LICENSE", "Copyright": "Copyright (c) 2010, Andrew Wooster" } qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/000077500000000000000000000000001347155106100256575ustar00rootroot00000000000000qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/LICENSE000066400000000000000000000020451347155106100266650ustar00rootroot00000000000000Copyright (c) 2014 Alastair Houghton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/__init__.py000066400000000000000000000000641347155106100277700ustar00rootroot00000000000000from .core import build_dmg __all__ = ['dmgbuild'] qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/badge.py000066400000000000000000000140761347155106100273030ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals from Quartz import * import math _REMOVABLE_DISK_PATH = '/System/Library/Extensions/IOStorageFamily.kext/Contents/Resources/Removable.icns' def badge_disk_icon(badge_file, output_file): # Load the Removable disk icon url = CFURLCreateWithFileSystemPath(None, _REMOVABLE_DISK_PATH, kCFURLPOSIXPathStyle, False) backdrop = CGImageSourceCreateWithURL(url, None) backdropCount = CGImageSourceGetCount(backdrop) # Load the badge url = CFURLCreateWithFileSystemPath(None, badge_file, kCFURLPOSIXPathStyle, False) badge = CGImageSourceCreateWithURL(url, None) assert badge is not None, 'Unable to process image file: %s' % badge_file badgeCount = CGImageSourceGetCount(badge) # Set up a destination for our target url = CFURLCreateWithFileSystemPath(None, output_file, kCFURLPOSIXPathStyle, False) target = CGImageDestinationCreateWithURL(url, 'com.apple.icns', backdropCount, None) # Get the RGB colorspace rgbColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB) # Scale scale = 1.0 # Perspective transform corners = ((0.2, 0.95), (0.8, 0.95), (0.85, 0.35), (0.15, 0.35)) # Translation position = (0.5, 0.5) for n in range(backdropCount): props = CGImageSourceCopyPropertiesAtIndex(backdrop, n, None) width = props['PixelWidth'] height = props['PixelHeight'] dpi = props['DPIWidth'] depth = props['Depth'] # Choose the best sized badge image bestWidth = None bestHeight = None bestBadge = None bestDepth = None bestDPI = None for m in range(badgeCount): badgeProps = CGImageSourceCopyPropertiesAtIndex(badge, m, None) badgeWidth = badgeProps['PixelWidth'] badgeHeight = badgeProps['PixelHeight'] badgeDPI = badgeProps['DPIWidth'] badgeDepth = badgeProps['Depth'] if bestBadge is None or (badgeWidth <= width and (bestWidth > width or badgeWidth > bestWidth or (badgeWidth == bestWidth and badgeDPI == dpi and badgeDepth <= depth and (bestDepth is None or badgeDepth > bestDepth)))): bestBadge = m bestWidth = badgeWidth bestHeight = badgeHeight bestDPI = badgeDPI bestDepth = badgeDepth badgeImage = CGImageSourceCreateImageAtIndex(badge, bestBadge, None) badgeCI = CIImage.imageWithCGImage_(badgeImage) backgroundImage = CGImageSourceCreateImageAtIndex(backdrop, n, None) backgroundCI = CIImage.imageWithCGImage_(backgroundImage) compositor = CIFilter.filterWithName_('CISourceOverCompositing') lanczos = CIFilter.filterWithName_('CILanczosScaleTransform') perspective = CIFilter.filterWithName_('CIPerspectiveTransform') transform = CIFilter.filterWithName_('CIAffineTransform') lanczos.setValue_forKey_(badgeCI, kCIInputImageKey) lanczos.setValue_forKey_(scale * float(width)/bestWidth, kCIInputScaleKey) lanczos.setValue_forKey_(1.0, kCIInputAspectRatioKey) topLeft = (width * scale * corners[0][0], width * scale * corners[0][1]) topRight = (width * scale * corners[1][0], width * scale * corners[1][1]) bottomRight = (width * scale * corners[2][0], width * scale * corners[2][1]) bottomLeft = (width * scale * corners[3][0], width * scale * corners[3][1]) out = lanczos.valueForKey_(kCIOutputImageKey) if width >= 16: perspective.setValue_forKey_(out, kCIInputImageKey) perspective.setValue_forKey_(CIVector.vectorWithX_Y_(*topLeft), 'inputTopLeft') perspective.setValue_forKey_(CIVector.vectorWithX_Y_(*topRight), 'inputTopRight') perspective.setValue_forKey_(CIVector.vectorWithX_Y_(*bottomRight), 'inputBottomRight') perspective.setValue_forKey_(CIVector.vectorWithX_Y_(*bottomLeft), 'inputBottomLeft') out = perspective.valueForKey_(kCIOutputImageKey) tfm = NSAffineTransform.transform() tfm.translateXBy_yBy_(math.floor((position[0] - 0.5 * scale) * width), math.floor((position[1] - 0.5 * scale) * height)) transform.setValue_forKey_(out, kCIInputImageKey) transform.setValue_forKey_(tfm, 'inputTransform') out = transform.valueForKey_(kCIOutputImageKey) compositor.setValue_forKey_(out, kCIInputImageKey) compositor.setValue_forKey_(backgroundCI, kCIInputBackgroundImageKey) result = compositor.valueForKey_(kCIOutputImageKey) cgContext = CGBitmapContextCreate(None, width, height, 8, 0, rgbColorSpace, kCGImageAlphaPremultipliedLast) context = CIContext.contextWithCGContext_options_(cgContext, None) context.drawImage_inRect_fromRect_(result, ((0, 0), (width, height)), ((0, 0), (width, height))) image = CGBitmapContextCreateImage(cgContext) CGImageDestinationAddImage(target, image, props) CGImageDestinationFinalize(target) qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/colors.py000066400000000000000000000313761347155106100275440ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals import re import math class Color (object): def to_rgb(self): raise Exception('Must implement to_rgb() in subclasses') class RGB (Color): def __init__(self, r, g, b): self.r = r self.g = g self.b = b def to_rgb(self): return self class HSL (Color): def __init__(self, h, s, l): self.h = h self.s = s self.l = l @staticmethod def _hue_to_rgb(t1, t2, hue): if hue < 0: hue += 6 elif hue >= 6: hue -= 6 if hue < 1: return (t2 - t1) * hue + t1 elif hue < 3: return t2 elif hue < 4: return (t2 - t1) * (4 - hue) + t1 else: return t1 def to_rgb(self): hue = self.h / 60.0 if self.l <= 0.5: t2 = self.l * (self.s + 1) else: t2 = self.l + self.s - (self.l * self.s) t1 = self.l * 2 - t2 r = self._hue_to_rgb(t1, t2, hue + 2) g = self._hue_to_rgb(t1, t2, hue) b = self._hue_to_rgb(t1, t2, hue - 2) return RGB(r, g, b) class HWB (Color): def __init__(self, h, w, b): self.h = h self.w = w self.b = b @staticmethod def _hue_to_rgb(hue): if hue < 0: hue += 6 elif hue >= 6: hue -= 6 if hue < 1: return hue elif hue < 3: return 1 elif hue < 4: return (4 - hue) else: return 0 def to_rgb(self): hue = self.h / 60.0 t1 = 1 - self.w - self.b r = self._hue_to_rgb(hue + 2) * t1 + self.w g = self._hue_to_rgb(hue) * t1 + self.w b = self._hue_to_rgb(hue - 2) * t1 + self.w return RGB(r, g, b) class CMYK (Color): def __init__(self, c, m, y, k): self.c = c self.m = m self.y = y self.k = k def to_rgb(self): r = 1.0 - min(1.0, self.c + self.k) g = 1.0 - min(1.0, self.m + self.k) b = 1.0 - min(1.0, self.y + self.k) return RGB(r, g, b) class Gray (Color): def __init__(self, g): self.g = g def to_rgb(self): return RGB(g, g, g) _x11_colors = { 'aliceblue': (240, 248, 255), 'antiquewhite': (250, 235, 215), 'aqua': ( 0, 255, 255), 'aquamarine': (127, 255, 212), 'azure': (240, 255, 255), 'beige': (245, 245, 220), 'bisque': (255, 228, 196), 'black': ( 0, 0, 0), 'blanchedalmond': (255, 235, 205), 'blue': ( 0, 0, 255), 'blueviolet': (138, 43, 226), 'brown': (165, 42, 42), 'burlywood': (222, 184, 135), 'cadetblue': ( 95, 158, 160), 'chartreuse': (127, 255, 0), 'chocolate': (210, 105, 30), 'coral': (255, 127, 80), 'cornflowerblue': (100, 149, 237), 'cornsilk': (255, 248, 220), 'crimson': (220, 20, 60), 'cyan': ( 0, 255, 255), 'darkblue': ( 0, 0, 139), 'darkcyan': ( 0, 139, 139), 'darkgoldenrod': (184, 134, 11), 'darkgray': (169, 169, 169), 'darkgreen': ( 0, 100, 0), 'darkgrey': (169, 169, 169), 'darkkhaki': (189, 183, 107), 'darkmagenta': (139, 0, 139), 'darkolivegreen': ( 85, 107, 47), 'darkorange': (255, 140, 0), 'darkorchid': (153, 50, 204), 'darkred': (139, 0, 0), 'darksalmon': (233, 150, 122), 'darkseagreen': (143, 188, 143), 'darkslateblue': ( 72, 61, 139), 'darkslategray': ( 47, 79, 79), 'darkslategrey': ( 47, 79, 79), 'darkturquoise': ( 0, 206, 209), 'darkviolet': (148, 0, 211), 'deeppink': (255, 20, 147), 'deepskyblue': ( 0, 191, 255), 'dimgray': (105, 105, 105), 'dimgrey': (105, 105, 105), 'dodgerblue': ( 30, 144, 255), 'firebrick': (178, 34, 34), 'floralwhite': (255, 250, 240), 'forestgreen': ( 34, 139, 34), 'fuchsia': (255, 0, 255), 'gainsboro': (220, 220, 220), 'ghostwhite': (248, 248, 255), 'gold': (255, 215, 0), 'goldenrod': (218, 165, 32), 'gray': (128, 128, 128), 'grey': (128, 128, 128), 'green': ( 0, 128, 0), 'greenyellow': (173, 255, 47), 'honeydew': (240, 255, 240), 'hotpink': (255, 105, 180), 'indianred': (205, 92, 92), 'indigo': ( 75, 0, 130), 'ivory': (255, 255, 240), 'khaki': (240, 230, 140), 'lavender': (230, 230, 250), 'lavenderblush': (255, 240, 245), 'lawngreen': (124, 252, 0), 'lemonchiffon': (255, 250, 205), 'lightblue': (173, 216, 230), 'lightcoral': (240, 128, 128), 'lightcyan': (224, 255, 255), 'lightgoldenrodyellow': (250, 250, 210), 'lightgray': (211, 211, 211), 'lightgreen': (144, 238, 144), 'lightgrey': (211, 211, 211), 'lightpink': (255, 182, 193), 'lightsalmon': (255, 160, 122), 'lightseagreen': ( 32, 178, 170), 'lightskyblue': (135, 206, 250), 'lightslategray': (119, 136, 153), 'lightslategrey': (119, 136, 153), 'lightsteelblue': (176, 196, 222), 'lightyellow': (255, 255, 224), 'lime': ( 0, 255, 0), 'limegreen': ( 50, 205, 50), 'linen': (250, 240, 230), 'magenta': (255, 0, 255), 'maroon': (128, 0, 0), 'mediumaquamarine': (102, 205, 170), 'mediumblue': ( 0, 0, 205), 'mediumorchid': (186, 85, 211), 'mediumpurple': (147, 112, 219), 'mediumseagreen': ( 60, 179, 113), 'mediumslateblue': (123, 104, 238), 'mediumspringgreen': ( 0, 250, 154), 'mediumturquoise': ( 72, 209, 204), 'mediumvioletred': (199, 21, 133), 'midnightblue': ( 25, 25, 112), 'mintcream': (245, 255, 250), 'mistyrose': (255, 228, 225), 'moccasin': (255, 228, 181), 'navajowhite': (255, 222, 173), 'navy': ( 0, 0, 128), 'oldlace': (253, 245, 230), 'olive': (128, 128, 0), 'olivedrab': (107, 142, 35), 'orange': (255, 165, 0), 'orangered': (255, 69, 0), 'orchid': (218, 112, 214), 'palegoldenrod': (238, 232, 170), 'palegreen': (152, 251, 152), 'paleturquoise': (175, 238, 238), 'palevioletred': (219, 112, 147), 'papayawhip': (255, 239, 213), 'peachpuff': (255, 218, 185), 'peru': (205, 133, 63), 'pink': (255, 192, 203), 'plum': (221, 160, 221), 'powderblue': (176, 224, 230), 'purple': (128, 0, 128), 'red': (255, 0, 0), 'rosybrown': (188, 143, 143), 'royalblue': ( 65, 105, 225), 'saddlebrown': (139, 69, 19), 'salmon': (250, 128, 114), 'sandybrown': (244, 164, 96), 'seagreen': ( 46, 139, 87), 'seashell': (255, 245, 238), 'sienna': (160, 82, 45), 'silver': (192, 192, 192), 'skyblue': (135, 206, 235), 'slateblue': (106, 90, 205), 'slategray': (112, 128, 144), 'slategrey': (112, 128, 144), 'snow': (255, 250, 250), 'springgreen': ( 0, 255, 127), 'steelblue': ( 70, 130, 180), 'tan': (210, 180, 140), 'teal': ( 0, 128, 128), 'thistle': (216, 191, 216), 'tomato': (255, 99, 71), 'turquoise': ( 64, 224, 208), 'violet': (238, 130, 238), 'wheat': (245, 222, 179), 'white': (255, 255, 255), 'whitesmoke': (245, 245, 245), 'yellow': (255, 255, 0), 'yellowgreen': (154, 205, 50) } _ws_re = re.compile('\s+') _token_re = re.compile('[A-Za-z_][A-Za-z0-9_]*') _hex_re = re.compile('#([0-9a-f]{3}(?:[0-9a-f]{3})?)$') _number_re = re.compile('[0-9]*(\.[0-9]*)') class ColorParser (object): def __init__(self, s): self._string = s self._pos = 0 def skipws(self): m = _ws_re.match(self._string, self._pos) if m: self._pos = m.end(0) def expect(self, s, context=''): if len(self._string) - self._pos < len(s) \ or self._string[self._pos:self._pos + len(s)] != s: raise ValueError('bad color "%s" - expected "%s"%s' % (self._string, s, context)) self._pos += len(s) def expectEnd(self): if self._pos != len(self._string): raise ValueError('junk at end of color "%s"' % self._string) def getToken(self): m = _token_re.match(self._string, self._pos) if m: token = m.group(0) self._pos = m.end(0) return token return None def parseNumber(self, context=''): m = _number_re.match(self._string, self._pos) if m: self._pos = m.end(0) return float(m.group(0)) raise ValueError('bad color "%s" - expected a number%s' % (self._string, context)) def parseColor(self): self.skipws() token = self.getToken() if token: if token == 'rgb': return self.parseRGB() elif token == 'hsl': return self.parseHSL() elif token == 'hwb': return self.parseHWB() elif token == 'cmyk': return self.parseCMYK() elif token == 'gray' or token == 'grey': return self.parseGray() try: r, g, b = _x11_colors[token] except KeyError: raise ValueError('unknown color name "%s"' % token) self.expectEnd() return RGB(r / 255.0, g / 255.0, b / 255.0) m = _hex_re.match(self._string, self._pos) if m: hrgb = m.group(1) if len(hrgb) == 3: r = int('0x' + 2 * hrgb[0], 16) g = int('0x' + 2 * hrgb[1], 16) b = int('0x' + 2 * hrgb[2], 16) else: r = int('0x' + hrgb[0:2], 16) g = int('0x' + hrgb[2:4], 16) b = int('0x' + hrgb[4:6], 16) self._pos = m.end(0) self.skipws() self.expectEnd() return RGB(r / 255.0, g / 255.0, b / 255.0) raise ValueError('bad color syntax "%s"' % self._string) def parseRGB(self): self.expect('(', 'after "rgb"') self.skipws() r = self.parseValue() self.skipws() self.expect(',', 'in "rgb"') self.skipws() g = self.parseValue() self.skipws() self.expect(',', 'in "rgb"') self.skipws() b = self.parseValue() self.skipws() self.expect(')', 'at end of "rgb"') self.skipws() self.expectEnd() return RGB(r, g, b) def parseHSL(self): self.expect('(', 'after "hsl"') self.skipws() h = self.parseAngle() self.skipws() self.expect(',', 'in "hsl"') self.skipws() s = self.parseValue() self.skipws() self.expect(',', 'in "hsl"') self.skipws() l = self.parseValue() self.skipws() self.expect(')', 'at end of "hsl"') self.skipws() self.expectEnd() return HSL(h, s, l) def parseHWB(self): self.expect('(', 'after "hwb"') self.skipws() h = self.parseAngle() self.skipws() self.expect(',', 'in "hwb"') self.skipws() w = self.parseValue() self.skipws() self.expect(',', 'in "hwb"') self.skipws() b = self.parseValue() self.skipws() self.expect(')', 'at end of "hwb"') self.skipws() self.expectEnd() return HWB(h, w, b) def parseCMYK(self): self.expect('(', 'after "cmyk"') self.skipws() c = self.parseValue() self.skipws() self.expect(',', 'in "cmyk"') self.skipws() m = self.parseValue() self.skipws() self.expect(',', 'in "cmyk"') self.skipws() y = self.parseValue() self.skipws() self.expect(',', 'in "cmyk"') self.skipws() k = self.parseValue() self.skipws() self.expect(')', 'at end of "cmyk"') self.skipws() self.expectEnd() return CMYK(c, m, y, k) def parseGray(self): self.expect('(', 'after "gray"') self.skipws() g = self.parseValue() self.skipws() self.expect(')', 'at end of "gray') self.skipws() self.expectEnd() return Gray(g) def parseValue(self): n = self.parseNumber() self.skipws() if self._string[self._pos] == '%': n = n / 100.0 self.pos += 1 return n def parseAngle(self): n = self.parseNumber() self.skipws() tok = self.getToken() if tok == 'rad': n = n * 180.0 / math.pi elif tok == 'grad' or tok == 'gon': n = n * 0.9 elif tok != 'deg': raise ValueError('bad angle unit "%s"' % tok) return n _color_re = re.compile('\s*(#|rgb|hsl|hwb|cmyk|gray|grey|%s)' % '|'.join(_x11_colors.keys())) def isAColor(s): return _color_re.match(s) def parseColor(s): return ColorParser(s).parseColor() qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/core.py000066400000000000000000000512471347155106100271720ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals import os import pkg_resources import re import shutil import stat import subprocess import sys import tempfile import tokenize import json try: {}.iteritems iteritems = lambda x: x.iteritems() iterkeys = lambda x: x.iterkeys() except AttributeError: iteritems = lambda x: x.items() iterkeys = lambda x: x.keys() try: unicode except NameError: unicode = str import biplist from mac_alias import * from ds_store import * from . import colors from . import licensing try: from . import badge except ImportError: badge = None _hexcolor_re = re.compile(r'#[0-9a-f]{3}(?:[0-9a-f]{3})?') class DMGError(Exception): pass def hdiutil(cmd, *args, **kwargs): plist = kwargs.get('plist', True) all_args = ['/usr/bin/hdiutil', cmd] all_args.extend(args) if plist: all_args.append('-plist') p = subprocess.Popen(all_args, stdout=subprocess.PIPE, close_fds=True) output, errors = p.communicate() if plist: results = biplist.readPlistFromString(output) else: results = output retcode = p.wait() return retcode, results # On Python 2 we can just execfile() it, but Python 3 deprecated that def load_settings(filename, settings): if sys.version_info[0] == 2: execfile(filename, settings, settings) else: encoding = 'utf-8' with open(filename, 'rb') as fp: try: encoding = tokenize.detect_encoding(fp.readline)[0] except SyntaxError: pass with open(filename, 'r', encoding=encoding) as fp: exec(compile(fp.read(), filename, 'exec'), settings, settings) def load_json(filename, settings): """Read an appdmg .json spec. Uses the defaults for appdmg, rather than the usual defaults for dmgbuild. """ with open(filename, 'r') as fp: json_data = json.load(fp) if 'title' not in json_data: raise ValueError('missing \'title\' in JSON settings file') if 'contents' not in json_data: raise ValueError('missing \'contents\' in JSON settings file') settings['volume_name'] = json_data['title'] settings['icon'] = json_data.get('icon', None) settings['badge_icon'] = json_data.get('badge-icon', None) bk = json_data.get('background', None) if bk is None: bk = json_data.get('background-color', None) if bk is not None: settings['background'] = bk settings['icon_size'] = json_data.get('icon-size', 80) wnd = json_data.get('window', { 'position': (100, 100), 'size': (640, 480) }) pos = wnd.get('position', { 'x': 100, 'y': 100 }) siz = wnd.get('size', { 'width': 640, 'height': 480 }) settings['window_rect'] = ((pos.get('x', 100), pos.get('y', 100)), (siz.get('width', 640), siz.get('height', 480))) settings['format'] = json_data.get('format', 'UDZO') settings['compression_level'] = json_data.get('compression-level', None) settings['license'] = json_data.get('license', None) files = [] symlinks = {} icon_locations = {} for fileinfo in json_data.get('contents', []): if 'path' not in fileinfo: raise ValueError('missing \'path\' in contents in JSON settings file') if 'x' not in fileinfo: raise ValueError('missing \'x\' in contents in JSON settings file') if 'y' not in fileinfo: raise ValueError('missing \'y\' in contents in JSON settings file') kind = fileinfo.get('type', 'file') path = fileinfo['path'] name = fileinfo.get('name', os.path.basename(path.rstrip('/'))) if kind == 'file': files.append((path, name)) elif kind == 'link': symlinks[name] = path elif kind == 'position': pass icon_locations[name] = (fileinfo['x'], fileinfo['y']) settings['files'] = files settings['symlinks'] = symlinks settings['icon_locations'] = icon_locations def build_dmg(filename, volume_name, settings_file=None, settings={}, defines={}, lookForHiDPI=True): options = { # Default settings 'filename': filename, 'volume_name': volume_name, 'format': 'UDBZ', 'compression_level': None, 'size': None, 'files': [], 'symlinks': {}, 'icon': None, 'badge_icon': None, 'background': None, 'show_status_bar': False, 'show_tab_view': False, 'show_toolbar': False, 'show_pathbar': False, 'show_sidebar': False, 'sidebar_width': 180, 'arrange_by': None, 'grid_offset': (0, 0), 'grid_spacing': 100.0, 'scroll_position': (0.0, 0.0), 'show_icon_preview': False, 'show_item_info': False, 'label_pos': 'bottom', 'text_size': 16.0, 'icon_size': 128.0, 'include_icon_view_settings': 'auto', 'include_list_view_settings': 'auto', 'list_icon_size': 16.0, 'list_text_size': 12.0, 'list_scroll_position': (0, 0), 'list_sort_by': 'name', 'list_use_relative_dates': True, 'list_calculate_all_sizes': False, 'list_columns': ('name', 'date-modified', 'size', 'kind', 'date-added'), 'list_column_widths': { 'name': 300, 'date-modified': 181, 'date-created': 181, 'date-added': 181, 'date-last-opened': 181, 'size': 97, 'kind': 115, 'label': 100, 'version': 75, 'comments': 300, }, 'list_column_sort_directions': { 'name': 'ascending', 'date-modified': 'descending', 'date-created': 'descending', 'date-added': 'descending', 'date-last-opened': 'descending', 'size': 'descending', 'kind': 'ascending', 'label': 'ascending', 'version': 'ascending', 'comments': 'ascending', }, 'window_rect': ((100, 100), (640, 280)), 'default_view': 'icon-view', 'icon_locations': {}, 'license': None, 'defines': defines } # Execute the settings file if settings_file: # We now support JSON settings files using appdmg's format if settings_file.endswith('.json'): load_json(settings_file, options) else: load_settings(settings_file, options) # Add any overrides options.update(settings) # Set up the finder data bounds = options['window_rect'] bounds_string = '{{%s, %s}, {%s, %s}}' % (bounds[0][0], bounds[0][1], bounds[1][0], bounds[1][1]) bwsp = { 'ShowStatusBar': options['show_status_bar'], 'WindowBounds': bounds_string, 'ContainerShowSidebar': False, 'PreviewPaneVisibility': False, 'SidebarWidth': options['sidebar_width'], 'ShowTabView': options['show_tab_view'], 'ShowToolbar': options['show_toolbar'], 'ShowPathbar': options['show_pathbar'], 'ShowSidebar': options['show_sidebar'] } arrange_options = { 'name': 'name', 'date-modified': 'dateModified', 'date-created': 'dateCreated', 'date-added': 'dateAdded', 'date-last-opened': 'dateLastOpened', 'size': 'size', 'kind': 'kind', 'label': 'label', } icvp = { 'viewOptionsVersion': 1, 'backgroundType': 0, 'backgroundColorRed': 1.0, 'backgroundColorGreen': 1.0, 'backgroundColorBlue': 1.0, 'gridOffsetX': float(options['grid_offset'][0]), 'gridOffsetY': float(options['grid_offset'][1]), 'gridSpacing': float(options['grid_spacing']), 'arrangeBy': str(arrange_options.get(options['arrange_by'], 'none')), 'showIconPreview': options['show_icon_preview'] == True, 'showItemInfo': options['show_item_info'] == True, 'labelOnBottom': options['label_pos'] == 'bottom', 'textSize': float(options['text_size']), 'iconSize': float(options['icon_size']), 'scrollPositionX': float(options['scroll_position'][0]), 'scrollPositionY': float(options['scroll_position'][1]) } background = options['background'] columns = { 'name': 'name', 'date-modified': 'dateModified', 'date-created': 'dateCreated', 'date-added': 'dateAdded', 'date-last-opened': 'dateLastOpened', 'size': 'size', 'kind': 'kind', 'label': 'label', 'version': 'version', 'comments': 'comments' } default_widths = { 'name': 300, 'date-modified': 181, 'date-created': 181, 'date-added': 181, 'date-last-opened': 181, 'size': 97, 'kind': 115, 'label': 100, 'version': 75, 'comments': 300, } default_sort_directions = { 'name': 'ascending', 'date-modified': 'descending', 'date-created': 'descending', 'date-added': 'descending', 'date-last-opened': 'descending', 'size': 'descending', 'kind': 'ascending', 'label': 'ascending', 'version': 'ascending', 'comments': 'ascending', } lsvp = { 'viewOptionsVersion': 1, 'sortColumn': columns.get(options['list_sort_by'], 'name'), 'textSize': float(options['list_text_size']), 'iconSize': float(options['list_icon_size']), 'showIconPreview': options['show_icon_preview'], 'scrollPositionX': options['list_scroll_position'][0], 'scrollPositionY': options['list_scroll_position'][1], 'useRelativeDates': options['list_use_relative_dates'], 'calculateAllSizes': options['list_calculate_all_sizes'], } lsvp['columns'] = {} cndx = {} for n, column in enumerate(options['list_columns']): cndx[column] = n width = options['list_column_widths'].get(column, default_widths[column]) asc = 'ascending' == options['list_column_sort_directions'].get(column, default_sort_directions[column]) lsvp['columns'][columns[column]] = { 'index': n, 'width': width, 'identifier': columns[column], 'visible': True, 'ascending': asc } n = len(options['list_columns']) for k in iterkeys(columns): if cndx.get(k, None) is None: cndx[k] = n width = default_widths[k] asc = 'ascending' == default_sort_directions[k] lsvp['columns'][columns[column]] = { 'index': n, 'width': width, 'identifier': columns[column], 'visible': False, 'ascending': asc } n += 1 default_view = options['default_view'] views = { 'icon-view': b'icnv', 'column-view': b'clmv', 'list-view': b'Nlsv', 'coverflow': b'Flwv' } icvl = (b'type', views.get(default_view, 'icnv')) include_icon_view_settings = default_view == 'icon-view' \ or options['include_icon_view_settings'] not in \ ('auto', 'no', 0, False, None) include_list_view_settings = default_view in ('list-view', 'coverflow') \ or options['include_list_view_settings'] not in \ ('auto', 'no', 0, False, None) filename = options['filename'] volume_name = options['volume_name'] # Construct a writeable image to start with dirname, basename = os.path.split(os.path.realpath(filename)) if not basename.endswith('.dmg'): basename += '.dmg' writableFile = tempfile.NamedTemporaryFile(dir=dirname, prefix='.temp', suffix=basename) total_size = options['size'] if total_size == None: # Start with a size of 128MB - this way we don't need to calculate the # size of the background image, volume icon, and .DS_Store file (and # 128 MB should be well sufficient for even the most outlandish image # sizes, like an uncompressed 5K multi-resolution TIFF) total_size = 128 * 1024 * 1024 def roundup(x, n): return x if x % n == 0 else x + n - x % n for path in options['files']: if isinstance(path, tuple): path = path[0] if not os.path.islink(path) and os.path.isdir(path): for dirpath, dirnames, filenames in os.walk(path): for f in filenames: fp = os.path.join(dirpath, f) total_size += roundup(os.lstat(fp).st_size, 4096) else: total_size += roundup(os.lstat(path).st_size, 4096) for name,target in iteritems(options['symlinks']): total_size += 4096 total_size = str(max(total_size / 1024, 1024)) + 'K' ret, output = hdiutil('create', '-ov', '-volname', volume_name, '-fs', 'HFS+', '-fsargs', '-c c=64,a=16,e=16', '-size', total_size, writableFile.name) if ret: raise DMGError('Unable to create disk image') ret, output = hdiutil('attach', '-nobrowse', '-owners', 'off', '-noidme', writableFile.name) if ret: raise DMGError('Unable to attach disk image') try: for info in output['system-entities']: if info.get('mount-point', None): device = info['dev-entry'] mount_point = info['mount-point'] icon = options['icon'] if badge: badge_icon = options['badge_icon'] else: badge_icon = None icon_target_path = os.path.join(mount_point, '.VolumeIcon.icns') if icon: shutil.copyfile(icon, icon_target_path) elif badge_icon: badge.badge_disk_icon(badge_icon, icon_target_path) if icon or badge_icon: subprocess.call(['/usr/bin/SetFile', '-a', 'C', mount_point]) background_bmk = None if not isinstance(background, (str, unicode)): pass elif colors.isAColor(background): c = colors.parseColor(background).to_rgb() icvp['backgroundType'] = 1 icvp['backgroundColorRed'] = float(c.r) icvp['backgroundColorGreen'] = float(c.g) icvp['backgroundColorBlue'] = float(c.b) else: if os.path.isfile(background): # look to see if there are HiDPI resources available if lookForHiDPI is True: name, extension = os.path.splitext(os.path.basename(background)) orderedImages = [background] imageDirectory = os.path.dirname(background) if imageDirectory == '': imageDirectory = '.' for candidateName in os.listdir(imageDirectory): hasScale = re.match( '^(?P.+)@(?P\d+)x(?P\.\w+)$', candidateName) if hasScale and name == hasScale.group('name') and \ extension == hasScale.group('extension'): scale = int(hasScale.group('scale')) if len(orderedImages) < scale: orderedImages += [None] * (scale - len(orderedImages)) orderedImages[scale - 1] = os.path.join(imageDirectory, candidateName) if len(orderedImages) > 1: # compile the grouped tiff backgroundFile = tempfile.NamedTemporaryFile(suffix='.tiff') background = backgroundFile.name output = tempfile.TemporaryFile(mode='w+') try: subprocess.check_call( ['/usr/bin/tiffutil', '-cathidpicheck'] + list(filter(None, orderedImages)) + ['-out', background], stdout=output, stderr=output) except Exception as e: output.seek(0) raise ValueError( 'unable to compile combined HiDPI file "%s" got error: %s\noutput: %s' % (background, str(e), output.read())) _, kind = os.path.splitext(background) path_in_image = os.path.join(mount_point, '.background' + kind) shutil.copyfile(background, path_in_image) elif pkg_resources.resource_exists('dmgbuild', 'resources/' + background + '.tiff'): tiffdata = pkg_resources.resource_string( 'dmgbuild', 'resources/' + background + '.tiff') path_in_image = os.path.join(mount_point, '.background.tiff') with open(path_in_image, 'wb') as f: f.write(tiffdata) else: raise ValueError('background file "%s" not found' % background) alias = Alias.for_file(path_in_image) background_bmk = Bookmark.for_file(path_in_image) icvp['backgroundType'] = 2 icvp['backgroundImageAlias'] = biplist.Data(alias.to_bytes()) for f in options['files']: if isinstance(f, tuple): f_in_image = os.path.join(mount_point, f[1]) f = f[0] else: basename = os.path.basename(f.rstrip('/')) f_in_image = os.path.join(mount_point, basename) # use system ditto command to preserve code signing, etc. subprocess.call(['/usr/bin/ditto', f, f_in_image]) for name,target in iteritems(options['symlinks']): name_in_image = os.path.join(mount_point, name) os.symlink(target, name_in_image) userfn = options.get('create_hook', None) if callable(userfn): userfn(mount_point, options) image_dsstore = os.path.join(mount_point, '.DS_Store') with DSStore.open(image_dsstore, 'w+') as d: d['.']['vSrn'] = ('long', 1) d['.']['bwsp'] = bwsp if include_icon_view_settings: d['.']['icvp'] = icvp if background_bmk: d['.']['pBBk'] = background_bmk if include_list_view_settings: d['.']['lsvp'] = lsvp d['.']['icvl'] = icvl for k,v in iteritems(options['icon_locations']): d[k]['Iloc'] = v # Delete .Trashes, if it gets created shutil.rmtree(os.path.join(mount_point, '.Trashes'), True) except: # Always try to detach hdiutil('detach', '-force', device, plist=False) raise ret, output = hdiutil('detach', device, plist=False) if ret: hdiutil('detach', '-force', device, plist=False) raise DMGError('Unable to detach device cleanly') # Shrink the output to the minimum possible size ret, output = hdiutil('resize', '-quiet', '-sectors', 'min', writableFile.name, plist=False) if ret: raise DMGError('Unable to shrink') key_prefix = {'UDZO': 'zlib', 'UDBZ': 'bzip2', 'ULFO': 'lzfse'} compression_level = options['compression_level'] if options['format'] in key_prefix and compression_level: compression_args = [ '-imagekey', key_prefix[options['format']] + '-level=' + str(compression_level) ] else: compression_args = [] ret, output = hdiutil('convert', writableFile.name, '-format', options['format'], '-ov', '-o', filename, *compression_args) if ret: raise DMGError('Unable to convert') if options['license']: ret, output = hdiutil('unflatten', '-quiet', filename, plist=False) if ret: raise DMGError('Unable to unflatten to add license') licensing.add_license(filename, options['license']) ret, output = hdiutil('flatten', '-quiet', filename, plist=False) if ret: raise DMGError('Unable to flatten after adding license') qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/licensing.py000066400000000000000000000347641347155106100302220ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals import os import struct from .resources import * # ISO language and country codes to Macintosh Region codes (from Script.h) # == CFLocaleCreateCanonicalLocaleIdentifierFromScriptManagerCodes(NULL, # kTextLanguageDontCare, # ) region_codes = { "en_US": 0, "fr_FR": 1, "en_GB": 2, "de_DE": 3, "it_IT": 4, "nl_NL": 5, "nl_BE": 6, "sv_SE": 7, "es_ES": 8, "da_DK": 9, "pt_PT": 10, "fr_CA": 11, "nb_NO": 12, "he_IL": 13, "ja_JP": 14, "en_AU": 15, "ar": 16, "fi_FI": 17, "fr_CH": 18, "de_CH": 19, "el_GR": 20, "is_IS": 21, "mt_MT": 22, "el_CY": 23, "tr_TR": 24, "hi_IN": 33, "ur_PK": 34, "it_CH": 36, "ro_RO": 39, "grc": 40, "lt_LT": 41, "pl_PL": 42, "hu_HU": 43, "et_EE": 44, "lv_LV": 45, "se": 46, "fo_FO": 47, "fa_IR": 48, "ru_RU": 49, "ga_IE": 50, "ko_KR": 51, "zh_CN": 52, "zh_TW": 53, "th_TH": 54, "cs_CZ": 56, "sk_SK": 57, "bn": 60, "be_BY": 61, "uk_UA": 62, "sr_RS": 65, "sl_SI": 66, "mk_MK": 67, "hr_HR": 68, "pt_BR": 71, "bg_BG": 72, "ca_ES": 73, "gd": 75, "gv": 76, "br": 77, "iu_CA": 78, "cy": 79, "ga-Latg_IE": 81, "en_CA": 82, "dz_BT": 83, "hy_AM": 84, "ka_GE": 85, "es_419": 86, "to_TO": 88, "fr_001": 91, "de_AT": 92, "gu_IN": 94, "pa": 95, "ur_IN": 96, "vi_VN": 97, "fr_BE": 98, "uz_UZ": 99, "en_SG": 100, "nn_NO": 101, "af_ZA": 102, "eo": 103, "mr_IN": 104, "bo": 105, "ne_NP": 106, "kl": 107, "en_IE": 108 } # Map of region constants to script constants (from Script.h) # TextEncoding textEncoding; # GetTextEncodingFromScriptInfo(kTextScriptDontCare, kTextLanguageDontCare, , &textEncoding); # == GetTextEncodingBase(textEncoding); script_codes = { 0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 0, 11: 0, 12: 0, 13: 5, 14: 1, 15: 0, 16: 4, 17: 0, 18: 0, 19: 0, 20: 6, 21: 37, 22: 0, 23: 6, 24: 35, 25: 36, 26: 0, 27: 0, 30: 0, 31: 0, 32: 0, 33: 9, 34: 4, 35: 35, 36: 0, 37: 0, 39: 38, 40: 6, 41: 29, 42: 29, 43: 29, 44: 29, 45: 29, 46: 0, 47: 37, 48: 140, 49: 7, 50: 39, 51: 3, 52: 25, 53: 2, 54: 21, 56: 29, 57: 29, 59: 29, 60: 13, 61: 7, 62: 7, 64: 6, 65: 7, 66: 36, 67: 7, 68: 36, 70: 0, 71: 0, 72: 7, 73: 0, 75: 39, 76: 39, 77: 39, 78: 236, 79: 39, 81: 40, 82: 0, 83: 26, 84: 24, 85: 23, 86: 0, 88: 0, 91: 0, 92: 0, 94: 11, 95: 10, 96: 4, 97: 30, 98: 0, 99: 7, 100: 0, 101: 0, 102: 0, 103: 0, 104: 9, 105: 26, 106: 9, 107: 0, 108: 0 } # Map of TextEncodingBase constants to Python encoder names (from TextCommon.h) encodings_map = { 0: 'mac_roman', # kTextEncodingMacRoman 1: 'shift_jis', # kTextEncodingMacJapanese 2: 'big5', # kTextEncodingMacChineseTrad 3: 'euc_kr', # kTextEncodingMacKorean 4: 'mac_arabic', # kTextEncodingMacArabic 6: 'mac_greek', # kTextEncodingMacGreek 7: 'mac_cyrillic', # kTextEncodingMacCyrillic 21: 'iso8859_11', # kTextEncodingMacThai 25: 'euc-cn', # kTextEncodingMacChineseSimp 29: 'mac_centeuro', # kTextEncodingMacCentralEurRoman 35: 'mac_turkish', # kTextEncodingMacTurkish 36: 'mac_croatian', # kTextEncodingMacCroatian 37: 'mac_iceland', # kTextEncodingMacIcelandic 38: 'mac_romanian', # kTextEncodingMacRomanian 140: 'mac_farsi' # kTextEncodingMacFarsi } # Standard fonts fonts = { 'New York': 2, 'Geneva': 3, 'Monaco': 4, 'Venice': 5, 'London': 6, 'Athens': 7, 'San Francisco': 8, 'Toronto': 9, 'Cairo': 11, 'Los Angeles': 12, 'Times': 20, 'Helvetica': 21, 'Courier': 22, 'Symbol': 23, 'Mobile': 24 } # Buttons (these come from the SLAResources file which you can find in the SLA # SDK on developer.apple.com) default_buttons = { 0: ( b'English', b'Agree', b'Disagree', b'Print', b'Save', b'If you agree with the terms of this license, press "Agree" to ' b'install the software. If you do not agree, press "Disagree".' ), 3: ( b'Deutsch', b'Akzeptieren', b'Ablehnen', b'Drucken', b'Sichern...', b'Klicken Sie in \xd2Akzeptieren\xd3, wenn Sie mit den Bestimmungen des Software-Lizenzvertrags einverstanden sind. Falls nicht, bitte \xd2Ablehnen\xd3 anklicken. Sie k\x9annen die Software nur installieren, wenn Sie \xd2Akzeptieren\xd3 angeklickt haben.' ), 8: ( b'Espa\x96ol', b'Aceptar', b'No aceptar', b'Imprimir', b'Guardar...', b'Si est\x87 de acuerdo con los t\x8erminos de esta licencia, pulse "Aceptar" para instalar el software. En el supuesto de que no est\x8e de acuerdo con los t\x8erminos de esta licencia, pulse "No aceptar."' ), 1: ( b'Fran\x8dais', b'Accepter', b'Refuser', b'Imprimer', b'Enregistrer...', b'Si vous acceptez les termes de la pr\x8esente licence, cliquez sur "Accepter" afin d\'installer le logiciel. Si vous n\'\x90tes pas d\'accord avec les termes de la licence, cliquez sur "Refuser".' ), 4: ( b'Italiano', b'Accetto', b'Rifiuto', b'Stampa', b'Registra...', b'Se accetti le condizioni di questa licenza, fai clic su "Accetto" per installare il software. Altrimenti fai clic su "Rifiuto".' ), 14: ( b'Japanese', b'\x93\xaf\x88\xd3\x82\xb5\x82\xdc\x82\xb7', b'\x93\xaf\x88\xd3\x82\xb5\x82\xdc\x82\xb9\x82\xf1', b'\x88\xf3\x8d\xfc\x82\xb7\x82\xe9', b'\x95\xdb\x91\xb6...', b'\x96{\x83\\\x83t\x83g\x83E\x83G\x83A\x8eg\x97p\x8b\x96\x91\xf8\x8c_\x96\xf1\x82\xcc\x8f\xf0\x8c\x8f\x82\xc9\x93\xaf\x88\xd3\x82\xb3\x82\xea\x82\xe9\x8f\xea\x8d\x87\x82\xc9\x82\xcd\x81A\x83\\\x83t\x83g\x83E\x83G\x83A\x82\xf0\x83C\x83\x93\x83X\x83g\x81[\x83\x8b\x82\xb7\x82\xe9\x82\xbd\x82\xdf\x82\xc9\x81u\x93\xaf\x88\xd3\x82\xb5\x82\xdc\x82\xb7\x81v\x82\xf0\x89\x9f\x82\xb5\x82\xc4\x82\xad\x82\xbe\x82\xb3\x82\xa2\x81B\x81@\x93\xaf\x88\xd3\x82\xb3\x82\xea\x82\xc8\x82\xa2\x8f\xea\x8d\x87\x82\xc9\x82\xcd\x81A\x81u\x93\xaf\x88\xd3\x82\xb5\x82\xdc\x82\xb9\x82\xf1\x81v\x82\xf0\x89\x9f\x82\xb5\x82\xc4\x82\xad\x82\xbe\x82\xb3\x82\xa2\x81B' ), 5: ( b'Nederlands', b'Ja', b'Nee', b'Print', b'Bewaar...', b'Indien u akkoord gaat met de voorwaarden van deze licentie, kunt u op \'Ja\' klikken om de programmatuur te installeren. Indien u niet akkoord gaat, klikt u op \'Nee\'.' ), 7: ( b'Svensk', b'Godk\x8anns', b'Avb\x9ajs', b'Skriv ut', b'Spara...', b'Om Du godk\x8anner licensvillkoren klicka p\x8c "Godk\x8anns" f\x9ar att installera programprodukten. Om Du inte godk\x8anner licensvillkoren, klicka p\x8c "Avb\x9ajs".' ), 71: ( b'Portugu\x90s', b'Concordar', b'Discordar', b'Imprimir', b'Salvar...', b'Se est\x87 de acordo com os termos desta licen\x8da, pressione "Concordar" para instalar o software. Se n\x8bo est\x87 de acordo, pressione "Discordar".' ), 52: ( b'Simplified Chinese', b'\xcd\xac\xd2\xe2', b'\xb2\xbb\xcd\xac\xd2\xe2', b'\xb4\xf2\xd3\xa1', b'\xb4\xe6\xb4\xa2\xa1\xad', b'\xc8\xe7\xb9\xfb\xc4\xfa\xcd\xac\xd2\xe2\xb1\xbe\xd0\xed\xbf\xc9\xd0\xad\xd2\xe9\xb5\xc4\xcc\xf5\xbf\xee\xa3\xac\xc7\xeb\xb0\xb4\xa1\xb0\xcd\xac\xd2\xe2\xa1\xb1\xc0\xb4\xb0\xb2\xd7\xb0\xb4\xcb\xc8\xed\xbc\xfe\xa1\xa3\xc8\xe7\xb9\xfb\xc4\xfa\xb2\xbb\xcd\xac\xd2\xe2\xa3\xac\xc7\xeb\xb0\xb4\xa1\xb0\xb2\xbb\xcd\xac\xd2\xe2\xa1\xb1\xa1\xa3' ), 53: ( b'Traditional Chinese', b'\xa6P\xb7N', b'\xa4\xa3\xa6P\xb7N', b'\xa6C\xa6L', b'\xc0x\xa6s\xa1K', b'\xa6p\xaaG\xb1z\xa6P\xb7N\xa5\xbb\xb3\\\xa5i\xc3\xd2\xb8\xcc\xaa\xba\xb1\xf8\xb4\xda\xa1A\xbd\xd0\xab\xf6\xa1\xa7\xa6P\xb7N\xa1\xa8\xa5H\xa6w\xb8\xcb\xb3n\xc5\xe9\xa1C\xa6p\xaaG\xa4\xa3\xa6P\xb7N\xa1A\xbd\xd0\xab\xf6\xa1\xa7\xa4\xa3\xa6P\xb7N\xa1\xa8\xa1C' ), 9: ( b'Dansk', b'Enig', b'Uenig', b'Udskriv', b'Arkiver...', b'Hvis du accepterer betingelserne i licensaftalen, skal du klikke p\x8c \xd2Enig\xd3 for at installere softwaren. Klik p\x8c \xd2Uenig\xd3 for at annullere installeringen.' ), 17: ( b'Suomi', b'Hyv\x8aksyn', b'En hyv\x8aksy', b'Tulosta', b'Tallenna\xc9', b'Hyv\x8aksy lisenssisopimuksen ehdot osoittamalla \xd5Hyv\x8aksy\xd5. Jos et hyv\x8aksy sopimuksen ehtoja, osoita \xd5En hyv\x8aksy\xd5.' ), 51: ( b'Korean', b'\xb5\xbf\xc0\xc7', b'\xb5\xbf\xc0\xc7 \xbe\xc8\xc7\xd4', b'\xc7\xc1\xb8\xb0\xc6\xae', b'\xc0\xfa\xc0\xe5...', b'\xbb\xe7\xbf\xeb \xb0\xe8\xbe\xe0\xbc\xad\xc0\xc7 \xb3\xbb\xbf\xeb\xbf\xa1 \xb5\xbf\xc0\xc7\xc7\xcf\xb8\xe9, "\xb5\xbf\xc0\xc7" \xb4\xdc\xc3\xdf\xb8\xa6 \xb4\xad\xb7\xaf \xbc\xd2\xc7\xc1\xc6\xae\xbf\xfe\xbe\xee\xb8\xa6 \xbc\xb3\xc4\xa1\xc7\xcf\xbd\xca\xbd\xc3\xbf\xc0. \xb5\xbf\xc0\xc7\xc7\xcf\xc1\xf6 \xbe\xca\xb4\xc2\xb4\xd9\xb8\xe9, "\xb5\xbf\xc0\xc7 \xbe\xc8\xc7\xd4" \xb4\xdc\xc3\xdf\xb8\xa6 \xb4\xa9\xb8\xa3\xbd\xca\xbd\xc3\xbf\xc0.' ), 12: ( b'Norsk', b'Enig', b'Ikke enig', b'Skriv ut', b'Arkiver...', b'Hvis De er enig i bestemmelsene i denne lisensavtalen, klikker De p\x8c "Enig"-knappen for \x8c installere programvaren. Hvis De ikke er enig, klikker De p\x8c "Ikke enig".' ), } class LPicResource (Resource): def __init__(self, res_id, res_name, default_lang, lpic, res_attrs=0): data = [] data.append(struct.pack(b'>HH', default_lang, len(lpic))) for lang,rid,two_byte in lpic: data.append(struct.pack(b'>HHH', lang, rid, int(two_byte))) super(LPicResource, self).__init__(b'LPic', res_id, res_name, b''.join(data), res_attrs) def get_encoder_name(locale): if locale not in region_codes: raise Exception("Cannot determine region code for locale '%s'" % locale) region_code = region_codes[locale] if region_code not in script_codes: raise Exception("Cannot determine script code for locale '%s'" % locale) script_code = script_codes[region_code] if script_code not in encodings_map: raise Exception("Cannot determine Python encoder name for locale '%s' - " "encode the string data manually as a byte array instead" % locale) return encodings_map[script_code] def maybe_encode(s, encoding): if isinstance(s, bytes): return s return s.encode(encoding) def add_license(filename, license_info): """Add a license agreement to the specified disk image file, which should have been unflattened first.""" fork = ResourceFork.from_file(filename) default_lang = license_info.get('default-language', 'en_US') default_lang_id = region_codes.get(default_lang, 0) lpic = [] ndx = 1 for language,license_data in license_info['licenses'].items(): if language not in region_codes: raise Exception("Unknown language '" + language + "'. Valid languages are: " + ", ".join(sorted(region_codes.keys()))) encoding_name = get_encoder_name(language) lang_id = region_codes[language] is_two_byte = lang_id in (14, 51, 52, 53) # Japanese, Korean, SimpChinese, TradChinese if os.path.isfile(license_data): with open(license_data) as f: license_data = f.read() if license_data.startswith('{\\rtf1'): fork.add(Resource(b'RTF ', 5000 + ndx, language + ' SLA', str(license_data))) else: fork.add(TextResource(5000 + ndx, language + ' SLA', maybe_encode(license_data, encoding_name))) fork.add(StyleResource(5000 + ndx, language + ' SLA', [Style(0, 12, 9, Style.Helvetica, 0, 0, (0, 0, 0))])) buttons = license_info.get('buttons', {}).get(language, None) if buttons is None: buttons = default_buttons.get(lang_id, None) if buttons is None: buttons = default_buttons[0] buttons = [maybe_encode(b, encoding_name) for b in buttons] fork.add(StringListResource(5000 + ndx, language + ' Buttons', buttons)) lpic.append((lang_id, ndx, is_two_byte)) ndx += 1 fork.add(LPicResource(5000, None, default_lang_id, lpic)) fork.write_to_file(filename) qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/qt_attribution.json000066400000000000000000000006721347155106100316270ustar00rootroot00000000000000{ "Id": "dmgbuild", "Name": "dmgbuild", "QDocModule": "qbs", "QtUsage": "Used in the qbs dmg module for building Apple disk images.", "Description": "macOS command line utility to build disk images", "Homepage": "https://github.com/al45tair/dmgbuild", "Version": "1.3.1", "License": "MIT License", "LicenseId": "MIT", "LicenseFile": "LICENSE", "Copyright": "Copyright (c) 2014 Alastair Houghton" } qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/dmgbuild/resources.py000066400000000000000000000301471347155106100302500ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals import struct class Resource (object): def __init__(self, res_type, res_id, res_name, data=None, res_attrs=0): self.res_type = str(res_type) self.res_id = res_id if isinstance(res_name, basestring): res_name = str(res_name) self.res_name = res_name self.res_attrs = res_attrs if data is None: self.data = None self.data = str(data) self.data_offset = None self.name_offset = None def __repr__(self): return 'Resource(%r, %r, %r, data=%r, res_attrs=%r)' % (self.res_type, self.res_id, self.res_name, self.data, self.res_attrs) class TMPLResource (Resource): def __init__(self, res_id, res_name, tmpl, res_attrs=0): data = [] for name,typecode in tmpl: data.append(struct.pack(b'B', len(name))) data.append(str(name)) data.append(str(typecode)) super(TMPLResource, self).__init__(b'TMPL', res_id, res_name, b''.join(data), res_attrs) class StringListResource (Resource): def __init__(self, res_id, res_name, strings, res_attrs=0): data = [] data.append(struct.pack(b'>H', len(strings))) for s in strings: data.append(struct.pack(b'B', len(s))) data.append(str(s)) super(StringListResource, self).__init__(b'STR#', res_id, res_name, b''.join(data), res_attrs) class TextResource (Resource): def __init__(self, res_id, res_name, string, res_attrs=0): super(TextResource, self).__init__(b'TEXT', res_id, res_name, str(string), res_attrs) class Style (object): # Fonts NewYork = 2 Geneva = 3 Monaco = 4 Venice = 5 London = 6 Athens = 7 SanFrancisco = 8 Toronto = 9 Cairo = 11 LosAngeles = 12 Times = 20 Helvetica = 21 Courier = 22 Symbol = 23 Mobile = 24 # Styles Bold = 0x0100 Italic = 0x0200 Underline = 0x0400 Outline = 0x0800 Shadow = 0x1000 Condense = 0x2000 Expand = 0x4000 def __init__(self, start_character, height, ascent, font_id, face, size, color): self.start_character = start_character self.height = height self.ascent = ascent self.font_id = font_id self.face = face self.size = size self.color = color def __repr__(self): styles = [] if self.face & Style.Bold: styles.append('Style.Bold') if self.face & Style.Italic: styles.append('Style.Italic') if self.face & Style.Underline: styles.append('Style.Underline') if self.face & Style.Outline: styles.append('Style.Outline') if self.face & Style.Shadow: styles.append('Style.Shadow') if self.face & Style.Condense: styles.append('Style.Condense') if self.face & Style.Expand: styles.append('Style.Expand') if self.face & ~0x4f00: styles.append('%#06x' % (self.face & ~0x4f00)) if styles: styles = '|'.join(styles) else: styles = '0' font_revmap = { 2: 'Style.NewYork', 3: 'Style.Geneva', 4: 'Style.Monaco', 5: 'Style.Venice', 6: 'Style.London', 7: 'Style.Athens', 8: 'Style.SanFrancisco', 9: 'Style.Toronto', 11: 'Style.Cairo', 12: 'Style.LosAngeles', 20: 'Style.Times', 21: 'Style.Helvetica', 22: 'Style.Courier', 23: 'Style.Symbol', 24: 'Style.Mobile' } font = font_revmap.get(self.font_id, '%s' % self.font_id) return 'Style(%r, %r, %r, %s, %s, %r, %r)' % ( self.start_character, self.height, self.ascent, font, styles, self.size, self.color) class StyleResource (Resource): def __init__(self, res_id, res_name, styles, res_attrs=0): data = [] data.append(struct.pack(b'>H', len(styles))) for style in styles: data.append(struct.pack(b'>LHHHHHHHH', style.start_character, style.height, style.ascent, style.font_id, style.face, style.size, style.color[0], style.color[1], style.color[2])) super(StyleResource, self).__init__(b'styl', res_id, res_name, b''.join(data), res_attrs) class ResourceFork (object): def __init__(self, resources=None): self.types = {} self.attrs = 0 if resources is not None: for res in resources: self.add(res) @classmethod def from_data(clss, data): if len(data) < 16: raise ValueError('Bad resource data - data too short') # Read the header data_start, map_start, data_len, map_len = struct.unpack(b'>LLLL', data[0:16]) if data_start + data_len > len(data): raise ValueError('Bad resource data - data out of range') if map_start + map_len > len(data): raise ValueError('Bad resource data - map out of range') if map_len < 30: raise ValueError('Bad resource data - map too short') # Read the map header fork_attrs, type_offset, name_offset, max_type_ndx \ = struct.unpack(b'>HHHH', data[map_start + 22:map_start + 30]) num_types = max_type_ndx + 1 if type_offset + 8 * num_types > map_len: raise ValueError('Bad resource data - type data outside map') if name_offset > map_len: raise ValueError('Bad resource data - names outside map') type_offset += map_start name_offset += map_start result = ResourceFork() # Now read the type list for ntype in range(0, num_types): type_pos = 2 + type_offset + 8 * ntype res_type, max_item_ndx, ref_offset \ = struct.unpack(b'>4sHH', data[type_pos:type_pos+8]) num_items = max_item_ndx + 1 result.types[res_type] = [] ref_list_offset = type_offset + ref_offset if ref_list_offset + 12 * num_items > map_start + map_len: raise ValueError('Bad resource data - ref list outside map') for nitem in range(0, num_items): ref_elt = ref_list_offset + 12 * nitem res_id, res_name_offset, data_offset \ = struct.unpack(b'>hHL', data[ref_elt:ref_elt+8]) res_attrs = data_offset >> 24 data_offset &= 0xffffff if data_offset >= data_len: raise ValueError('Bad resource data - item data out of range') data_offset += data_start res_len = struct.unpack(b'>L', data[data_offset:data_offset+4])[0] if data_offset + res_len >= data_start + data_len: raise ValueError('Bad resource data - item data too large') res_data = data[data_offset + 4:data_offset + res_len + 4] if res_name_offset == 0xffff: res_name = None else: res_name_offset += name_offset if res_name_offset >= map_start + map_len: raise ValueError('Bad resource data - name out of range') res_name_len = struct.unpack(b'B', data[res_name_offset])[0] res_name = data[res_name_offset + 1:res_name_offset + res_name_len + 1] result.types[res_type].append(Resource(res_type, res_id, res_name, res_data, res_attrs)) return result @classmethod def from_file(clss, filename): with open(filename + '/..namedfork/rsrc', 'rb') as f: data = f.read() return clss.from_data(data) def to_data(self): data = [] data_len = 0 names = [] names_len = 0 types_len = len(self.types) * 8 types_data = [] reflist_data = [] reflist_len = 0 for res_type, items in self.types.items(): types_data.append(struct.pack(b'>4sHH', res_type, len(items) - 1, 2 + types_len + reflist_len)) for item in items: data_offset = data_len if item.res_name is None: name_offset = 65535 else: name_offset = names_len n = str(item.res_name) names.append(struct.pack(b'B', len(n)) + n) names_len += 1 + len(n) if item.data is None: data_len += 4 else: data_len += 4 + (len(item.data) + 3) & ~3 reflist_len += 12 reflist_data.append(struct.pack(b'>hHLL', item.res_id, name_offset, (item.res_attrs << 24) \ | data_offset, 0)) # Header data.append(struct.pack(b'>LLLL240s', 256, 256 + data_len, data_len, 30 + types_len + reflist_len + names_len, b'')) # Resource data for res_type, items in self.types.items(): for item in items: if item.data is None: dlen = 0 else: dlen = len(item.data) plen = (dlen + 3) & ~3 data.append(struct.pack(b'>L', dlen)) if item.data is not None: data.append(item.data) if plen != dlen: data.append(b'\0' * (plen - dlen)) # Resource map header data.append(struct.pack(b'>16sLHHHHH', b'', 0, 0, self.attrs, 28, 30 + types_len + reflist_len, len(self.types) - 1)) # Type list data.append(b''.join(types_data)) # Reference lists data.append(b''.join(reflist_data)) # Name list data.append(b''.join(names)) return b''.join(data) def write_to_file(self, filename): with open(filename + '/..namedfork/rsrc', 'wb') as f: f.write(self.to_data()) def __len__(self): return len(self.types) def __getitem__(self, key): return self.types[key] def __iter__(self): for res_type, items in self.types.items(): for item in items: yield item def __repr__(self): output = [] for item in self: output.append(repr(item)) return 'ResourceFork([%s])' % ', '.join(output) def add(self, res): if res.res_type in self.types: self.types[res.res_type].append(res) else: self.types[res.res_type] = [res] def remove(self, res): self.types[res.res_type].remove(res) qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/ds_store/000077500000000000000000000000001347155106100257125ustar00rootroot00000000000000qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/ds_store/LICENSE000066400000000000000000000020451347155106100267200ustar00rootroot00000000000000Copyright (c) 2014 Alastair Houghton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/ds_store/__init__.py000066400000000000000000000001201347155106100300140ustar00rootroot00000000000000from .store import DSStore, DSStoreEntry __all__ = ['DSStore', 'DSStoreEntry'] qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/ds_store/buddy.py000066400000000000000000000341141347155106100273760ustar00rootroot00000000000000# -*- coding: utf-8 -*- import os import bisect import struct import binascii try: {}.iterkeys iterkeys = lambda x: x.iterkeys() except AttributeError: iterkeys = lambda x: x.keys() try: unicode except NameError: unicode = str class BuddyError(Exception): pass class Block(object): def __init__(self, allocator, offset, size): self._allocator = allocator self._offset = offset self._size = size self._value = bytearray(allocator.read(offset, size)) self._pos = 0 self._dirty = False def __len__(self): return self._size def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() def close(self): if self._dirty: self.flush() def flush(self): if self._dirty: self._dirty = False self._allocator.write(self._offset, self._value) def invalidate(self): self._dirty = False def zero_fill(self): len = self._size - self._pos zeroes = b'\0' * len self._value[self._pos:self._size] = zeroes self._dirty = True def tell(self): return self._pos def seek(self, pos, whence=os.SEEK_SET): if whence == os.SEEK_CUR: pos += self._pos elif whence == os.SEEK_END: pos = self._size - pos if pos < 0 or pos > self._size: raise ValueError('Seek out of range in Block instance') self._pos = pos def read(self, size_or_format): if isinstance(size_or_format, (str, unicode, bytes)): size = struct.calcsize(size_or_format) fmt = size_or_format else: size = size_or_format fmt = None if self._size - self._pos < size: raise BuddyError('Unable to read %lu bytes in block' % size) data = self._value[self._pos:self._pos + size] self._pos += size if fmt is not None: if isinstance(data, bytearray): return struct.unpack_from(fmt, bytes(data)) else: return struct.unpack(fmt, data) else: return data def write(self, data_or_format, *args): if len(args): data = struct.pack(data_or_format, *args) else: data = data_or_format if self._pos + len(data) > self._size: raise ValueError('Attempt to write past end of Block') self._value[self._pos:self._pos + len(data)] = data self._pos += len(data) self._dirty = True def insert(self, data_or_format, *args): if len(args): data = struct.pack(data_or_format, *args) else: data = data_or_format del self._value[-len(data):] self._value[self._pos:self._pos] = data self._pos += len(data) self._dirty = True def delete(self, size): if self._pos + size > self._size: raise ValueError('Attempt to delete past end of Block') del self._value[self._pos:self._pos + size] self._value += b'\0' * size self._dirty = True def __str__(self): return binascii.b2a_hex(self._value) class Allocator(object): def __init__(self, the_file): self._file = the_file self._dirty = False self._file.seek(0) # Read the header magic1, magic2, offset, size, offset2, self._unknown1 \ = self.read(-4, '>I4sIII16s') if magic2 != b'Bud1' or magic1 != 1: raise BuddyError('Not a buddy file') if offset != offset2: raise BuddyError('Root addresses differ') self._root = Block(self, offset, size) # Read the block offsets count, self._unknown2 = self._root.read('>II') self._offsets = [] c = (count + 255) & ~255 while c: self._offsets += self._root.read('>256I') c -= 256 self._offsets = self._offsets[:count] # Read the TOC self._toc = {} count = self._root.read('>I')[0] for n in range(count): nlen = self._root.read('B')[0] name = bytes(self._root.read(nlen)) value = self._root.read('>I')[0] self._toc[name] = value # Read the free lists self._free = [] for n in range(32): count = self._root.read('>I') self._free.append(list(self._root.read('>%uI' % count))) @classmethod def open(cls, file_or_name, mode='r+'): if isinstance(file_or_name, (str, unicode)): if not 'b' in mode: mode = mode[:1] + 'b' + mode[1:] f = open(file_or_name, mode) else: f = file_or_name if 'w' in mode: # Create an empty file in this case f.truncate() # An empty root block needs 1264 bytes: # # 0 4 offset count # 4 4 unknown # 8 4 root block offset (2048) # 12 255 * 4 padding (offsets are in multiples of 256) # 1032 4 toc count (0) # 1036 228 free list # total 1264 # The free list will contain the following: # # 0 5 * 4 no blocks of width less than 5 # 20 6 * 8 1 block each of widths 5 to 10 # 68 4 no blocks of width 11 (allocated for the root) # 72 19 * 8 1 block each of widths 12 to 30 # 224 4 no blocks of width 31 # total 228 # # (The reason for this layout is that we allocate 2**5 bytes for # the header, which splits the initial 2GB region into every size # below 2**31, including *two* blocks of size 2**5, one of which # we take. The root block itself then needs a block of size # 2**11. Conveniently, each of these initial blocks will be # located at offset 2**n where n is its width.) # Write the header header = struct.pack(b'>I4sIII16s', 1, b'Bud1', 2048, 1264, 2048, b'\x00\x00\x10\x0c' b'\x00\x00\x00\x87' b'\x00\x00\x20\x0b' b'\x00\x00\x00\x00') f.write(header) f.write(b'\0' * 2016) # Write the root block free_list = [struct.pack(b'>5I', 0, 0, 0, 0, 0)] for n in range(5, 11): free_list.append(struct.pack(b'>II', 1, 2**n)) free_list.append(struct.pack(b'>I', 0)) for n in range(12, 31): free_list.append(struct.pack(b'>II', 1, 2**n)) free_list.append(struct.pack(b'>I', 0)) root = b''.join([struct.pack(b'>III', 1, 0, 2048 | 5), struct.pack(b'>I', 0) * 255, struct.pack(b'>I', 0)] + free_list) f.write(root) return Allocator(f) def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() def close(self): self.flush() self._file.close() def flush(self): if self._dirty: size = self._root_block_size() self.allocate(size, 0) with self.get_block(0) as rblk: self._write_root_block_into(rblk) addr = self._offsets[0] offset = addr & ~0x1f size = 1 << (addr & 0x1f) self._file.seek(0, os.SEEK_SET) self._file.write(struct.pack(b'>I4sIII16s', 1, b'Bud1', offset, size, offset, self._unknown1)) self._dirty = False self._file.flush() def read(self, offset, size_or_format): """Read data at `offset', or raise an exception. `size_or_format' may either be a byte count, in which case we return raw data, or a format string for `struct.unpack', in which case we work out the size and unpack the data before returning it.""" # N.B. There is a fixed offset of four bytes(!) self._file.seek(offset + 4, os.SEEK_SET) if isinstance(size_or_format, (str, unicode)): size = struct.calcsize(size_or_format) fmt = size_or_format else: size = size_or_format fmt = None ret = self._file.read(size) if len(ret) < size: ret += b'\0' * (size - len(ret)) if fmt is not None: if isinstance(ret, bytearray): ret = struct.unpack_from(fmt, bytes(ret)) else: ret = struct.unpack(fmt, ret) return ret def write(self, offset, data_or_format, *args): """Write data at `offset', or raise an exception. `data_or_format' may either be the data to write, or a format string for `struct.pack', in which case we pack the additional arguments and write the resulting data.""" # N.B. There is a fixed offset of four bytes(!) self._file.seek(offset + 4, os.SEEK_SET) if len(args): data = struct.pack(data_or_format, *args) else: data = data_or_format self._file.write(data) def get_block(self, block): try: addr = self._offsets[block] except IndexError: return None offset = addr & ~0x1f size = 1 << (addr & 0x1f) return Block(self, offset, size) def _root_block_size(self): """Return the number of bytes required by the root block.""" # Offsets size = 8 size += 4 * ((len(self._offsets) + 255) & ~255) # TOC size += 4 size += sum([5 + len(s) for s in self._toc]) # Free list size += sum([4 + 4 * len(fl) for fl in self._free]) return size def _write_root_block_into(self, block): # Offsets block.write('>II', len(self._offsets), self._unknown2) block.write('>%uI' % len(self._offsets), *self._offsets) extra = len(self._offsets) & 255 if extra: block.write(b'\0\0\0\0' * (256 - extra)) # TOC keys = list(self._toc.keys()) keys.sort() block.write('>I', len(keys)) for k in keys: block.write('B', len(k)) block.write(k) block.write('>I', self._toc[k]) # Free list for w, f in enumerate(self._free): block.write('>I', len(f)) if len(f): block.write('>%uI' % len(f), *f) def _buddy(self, offset, width): f = self._free[width] b = offset ^ (1 << width) try: ndx = f.index(b) except ValueError: ndx = None return (f, b, ndx) def _release(self, offset, width): # Coalesce while True: f,b,ndx = self._buddy(offset, width) if ndx is None: break offset &= b width += 1 del f[ndx] # Add to the list bisect.insort(f, offset) # Mark as dirty self._dirty = True def _alloc(self, width): w = width while not self._free[w]: w += 1 while w > width: offset = self._free[w].pop(0) w -= 1 self._free[w] = [offset, offset ^ (1 << w)] self._dirty = True return self._free[width].pop(0) def allocate(self, bytes, block=None): """Allocate or reallocate a block such that it has space for at least `bytes' bytes.""" if block is None: # Find the first unused block try: block = self._offsets.index(0) except ValueError: block = len(self._offsets) self._offsets.append(0) # Compute block width width = max(bytes.bit_length(), 5) addr = self._offsets[block] offset = addr & ~0x1f if addr: blkwidth = addr & 0x1f if blkwidth == width: return block self._release(offset, width) self._offsets[block] = 0 offset = self._alloc(width) self._offsets[block] = offset | width return block def release(self, block): addr = self._offsets[block] if addr: width = addr & 0x1f offset = addr & ~0x1f self._release(offset, width) if block == len(self._offsets): del self._offsets[block] else: self._offsets[block] = 0 def __len__(self): return len(self._toc) def __getitem__(self, key): if not isinstance(key, (str, unicode)): raise TypeError('Keys must be of string type') if not isinstance(key, bytes): key = key.encode('latin_1') return self._toc[key] def __setitem__(self, key, value): if not isinstance(key, (str, unicode)): raise TypeError('Keys must be of string type') if not isinstance(key, bytes): key = key.encode('latin_1') self._toc[key] = value self._dirty = True def __delitem__(self, key): if not isinstance(key, (str, unicode)): raise TypeError('Keys must be of string type') if not isinstance(key, bytes): key = key.encode('latin_1') del self._toc[key] self._dirty = True def iterkeys(self): return iterkeys(self._toc) def keys(self): return iterkeys(self._toc) def __iter__(self): return iterkeys(self._toc) def __contains__(self, key): return key in self._toc qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/ds_store/qt_attribution.json000066400000000000000000000006701347155106100316600ustar00rootroot00000000000000{ "Id": "ds_store", "Name": "ds_store", "QDocModule": "qbs", "QtUsage": "Used in the qbs dmg module for building Apple disk images.", "Description": "Manipulate Finder .DS_Store files from Python", "Homepage": "https://github.com/al45tair/ds_store", "Version": "1.1.2", "License": "MIT License", "LicenseId": "MIT", "LicenseFile": "LICENSE", "Copyright": "Copyright (c) 2014 Alastair Houghton" } qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/ds_store/store.py000066400000000000000000001302311347155106100274200ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals from __future__ import print_function from __future__ import division import binascii import struct import biplist import mac_alias try: next except NameError: next = lambda x: x.next() try: unicode except NameError: unicode = str from . import buddy class ILocCodec(object): @staticmethod def encode(point): return struct.pack(b'>IIII', point[0], point[1], 0xffffffff, 0xffff0000) @staticmethod def decode(bytesData): if isinstance(bytesData, bytearray): x, y = struct.unpack_from(b'>II', bytes(bytesData[:8])) else: x, y = struct.unpack(b'>II', bytesData[:8]) return (x, y) class PlistCodec(object): @staticmethod def encode(plist): return biplist.writePlistToString(plist) @staticmethod def decode(bytes): return biplist.readPlistFromString(bytes) class BookmarkCodec(object): @staticmethod def encode(bmk): return bmk.to_bytes() @staticmethod def decode(bytes): return mac_alias.Bookmark.from_bytes(bytes) # This list tells the code how to decode particular kinds of entry in the # .DS_Store file. This is really a convenience, and we currently only # support a tiny subset of the possible entry types. codecs = { b'Iloc': ILocCodec, b'bwsp': PlistCodec, b'lsvp': PlistCodec, b'lsvP': PlistCodec, b'icvp': PlistCodec, b'pBBk': BookmarkCodec } class DSStoreEntry(object): """Holds the data from an entry in a ``.DS_Store`` file. Note that this is not meant to represent the entry itself---i.e. if you change the type or value, your changes will *not* be reflected in the underlying file. If you want to make a change, you should either use the :class:`DSStore` object's :meth:`DSStore.insert` method (which will replace a key if it already exists), or the mapping access mode for :class:`DSStore` (often simpler anyway). """ def __init__(self, filename, code, typecode, value=None): if str != bytes and type(filename) == bytes: filename = filename.decode('utf-8') if not isinstance(code, bytes): code = code.encode('latin_1') self.filename = filename self.code = code self.type = typecode self.value = value @classmethod def read(cls, block): """Read a ``.DS_Store`` entry from the containing Block""" # First read the filename nlen = block.read(b'>I')[0] filename = block.read(2 * nlen).decode('utf-16be') # Next, read the code and type code, typecode = block.read(b'>4s4s') # Finally, read the data if typecode == b'bool': value = block.read(b'>?')[0] elif typecode == b'long' or typecode == b'shor': value = block.read(b'>I')[0] elif typecode == b'blob': vlen = block.read(b'>I')[0] value = block.read(vlen) codec = codecs.get(code, None) if codec: value = codec.decode(value) typecode = codec elif typecode == b'ustr': vlen = block.read(b'>I')[0] value = block.read(2 * vlen).decode('utf-16be') elif typecode == b'type': value = block.read(b'>4s')[0] elif typecode == b'comp' or typecode == b'dutc': value = block.read(b'>Q')[0] else: raise ValueError('Unknown type code "%s"' % typecode) return DSStoreEntry(filename, code, typecode, value) def __lt__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError('Can only compare against other DSStoreEntry objects') sfl = self.filename.lower() ofl = other.filename.lower() return (sfl < ofl or (self.filename == other.filename and self.code < other.code)) def __le__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError('Can only compare against other DSStoreEntry objects') sfl = self.filename.lower() ofl = other.filename.lower() return (sfl < ofl or (sfl == ofl and self.code <= other.code)) def __eq__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError('Can only compare against other DSStoreEntry objects') sfl = self.filename.lower() ofl = other.filename.lower() return (sfl == ofl and self.code == other.code) def __ne__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError('Can only compare against other DSStoreEntry objects') sfl = self.filename.lower() ofl = other.filename.lower() return (sfl != ofl or self.code != other.code) def __gt__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError('Can only compare against other DSStoreEntry objects') sfl = self.filename.lower() ofl = other.filename.lower() selfCode = self.code if str != bytes and type(selfCode) is bytes: selfCode = selfCode.decode('utf-8') otherCode = other.code if str != bytes and type(otherCode) is bytes: otherCode = otherCode.decode('utf-8') return (sfl > ofl or (sfl == ofl and selfCode > otherCode)) def __ge__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError('Can only compare against other DSStoreEntry objects') sfl = self.filename.lower() ofl = other.filename.lower() return (sfl > ofl or (sfl == ofl and self.code >= other.code)) def __cmp__(self, other): if not isinstance(other, DSStoreEntry): raise TypeError('Can only compare against other DSStoreEntry objects') r = cmp(self.filename.lower(), other.filename.lower()) if r: return r return cmp(self.code, other.code) def byte_length(self): """Compute the length of this entry, in bytes""" utf16 = self.filename.encode('utf-16be') l = 4 + len(utf16) + 8 if isinstance(self.type, unicode): entry_type = self.type.encode('latin_1') value = self.value elif isinstance(self.type, (bytes, str)): entry_type = self.type value = self.value else: entry_type = b'blob' value = self.type.encode(self.value) if entry_type == b'bool': l += 1 elif entry_type == b'long' or entry_type == b'shor': l += 4 elif entry_type == b'blob': l += 4 + len(value) elif entry_type == b'ustr': utf16 = value.encode('utf-16be') l += 4 + len(utf16) elif entry_type == b'type': l += 4 elif entry_type == b'comp' or entry_type == b'dutc': l += 8 else: raise ValueError('Unknown type code "%s"' % entry_type) return l def write(self, block, insert=False): """Write this entry to the specified Block""" if insert: w = block.insert else: w = block.write if isinstance(self.type, unicode): entry_type = self.type.encode('latin_1') value = self.value elif isinstance(self.type, (bytes, str)): entry_type = self.type value = self.value else: entry_type = b'blob' value = self.type.encode(self.value) utf16 = self.filename.encode('utf-16be') w(b'>I', len(utf16) // 2) w(utf16) w(b'>4s4s', self.code, entry_type) if entry_type == b'bool': w(b'>?', value) elif entry_type == b'long' or entry_type == b'shor': w(b'>I', value) elif entry_type == b'blob': w(b'>I', len(value)) w(value) elif entry_type == b'ustr': utf16 = value.encode('utf-16be') w(b'>I', len(utf16) // 2) w(utf16) elif entry_type == b'type': if isinstance(value, unicode): value = value.encode('latin_1') w(b'>4s', value) elif entry_type == b'comp' or entry_type == b'dutc': w(b'>Q', value) else: raise ValueError('Unknown type code "%s"' % entry_type) def __repr__(self): return '<%s %s>' % (self.filename, self.code) class DSStore(object): """Python interface to a ``.DS_Store`` file. Works by manipulating the file on the disk---so this code will work with ``.DS_Store`` files for *very* large directories. A :class:`DSStore` object can be used as if it was a mapping, e.g.:: d['foobar.dat']['Iloc'] will fetch the "Iloc" record for "foobar.dat", or raise :class:`KeyError` if there is no such record. If used in this manner, the :class:`DSStore` object will return (type, value) tuples, unless the type is "blob" and the module knows how to decode it. Currently, we know how to decode "Iloc", "bwsp", "lsvp", "lsvP" and "icvp" blobs. "Iloc" decodes to an (x, y) tuple, while the others are all decoded using ``biplist``. Assignment also works, e.g.:: d['foobar.dat']['note'] = ('ustr', u'Hello World!') as does deletion with ``del``:: del d['foobar.dat']['note'] This is usually going to be the most convenient interface, though occasionally (for instance when creating a new ``.DS_Store`` file) you may wish to drop down to using :class:`DSStoreEntry` objects directly.""" def __init__(self, store): self._store = store self._superblk = self._store['DSDB'] with self._get_block(self._superblk) as s: self._rootnode, self._levels, self._records, \ self._nodes, self._page_size = s.read(b'>IIIII') self._min_usage = 2 * self._page_size // 3 self._dirty = False @classmethod def open(cls, file_or_name, mode='r+', initial_entries=None): """Open a ``.DS_Store`` file; pass either a Python file object, or a filename in the ``file_or_name`` argument and a file access mode in the ``mode`` argument. If you are creating a new file using the "w" or "w+" modes, you may also specify a list of entries with which to initialise the file.""" store = buddy.Allocator.open(file_or_name, mode) if mode == 'w' or mode == 'w+': superblk = store.allocate(20) store['DSDB'] = superblk page_size = 4096 if not initial_entries: root = store.allocate(page_size) with store.get_block(root) as rootblk: rootblk.zero_fill() with store.get_block(superblk) as s: s.write(b'>IIIII', root, 0, 0, 1, page_size) else: # Make sure they're in sorted order initial_entries = list(initial_entries) initial_entries.sort() # Construct the tree current_level = initial_entries next_level = [] levels = [] ptr_size = 0 node_count = 0 while True: total = 8 nodes = [] node = [] for e in current_level: new_total = total + ptr_size + e.byte_length() if new_total > page_size: nodes.append(node) next_level.append(e) total = 8 node = [] else: total = new_total node.append(e) if node: nodes.append(node) node_count += len(nodes) levels.append(nodes) if len(nodes) == 1: break current_level = next_level next_level = [] ptr_size = 4 # Allocate nodes ptrs = [store.allocate(page_size) for n in range(node_count)] # Generate nodes pointers = [] prev_pointers = None for level in levels: ppndx = 0 lptrs = ptrs[-len(level):] del ptrs[-len(level):] for node in level: ndx = lptrs.pop(0) if prev_pointers is None: with store.get_block(ndx) as block: block.write(b'>II', 0, len(node)) for e in node: e.write(block) else: next_node = prev_pointers[ppndx + len(node)] node_ptrs = prev_pointers[ppndx:ppndx+len(node)] with store.get_block(ndx) as block: block.write(b'>II', next_node, len(node)) for ptr, e in zip(node_ptrs, node): block.write(b'>I', ptr) e.write(block) pointers.append(ndx) prev_pointers = pointers pointers = [] root = prev_pointers[0] with store.get_block(superblk) as s: s.write(b'>IIIII', root, len(levels), len(initial_entries), node_count, page_size) return DSStore(store) def _get_block(self, number): return self._store.get_block(number) def flush(self): """Flush any dirty data back to the file.""" if self._dirty: self._dirty = False with self._get_block(self._superblk) as s: s.write(b'>IIIII', self._rootnode, self._levels, self._records, self._nodes, self._page_size) self._store.flush() def close(self): """Flush dirty data and close the underlying file.""" self.flush() self._store.close() def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() # Internal B-Tree nodes look like this: # # [ next | count | (ptr0 | rec0) | (ptr1 | rec1) ... (ptrN | recN) ] # Leaf nodes look like this: # # [ 0 | count | rec0 | rec1 ... recN ] # Iterate over the tree, starting at `node' def _traverse(self, node): if node is None: node = self._rootnode with self._get_block(node) as block: next_node, count = block.read(b'>II') if next_node: for n in range(count): ptr = block.read(b'>I')[0] for e in self._traverse(ptr): yield e e = DSStoreEntry.read(block) yield e for e in self._traverse(next_node): yield e else: for n in range(count): e = DSStoreEntry.read(block) yield e # Display the data in `node' def _dump_node(self, node): with self._get_block(node) as block: next_node, count = block.read(b'>II') print('next: %u\ncount: %u\n' % (next_node, count)) for n in range(count): if next_node: ptr = block.read(b'>I')[0] print('%8u ' % ptr, end=' ') else: print(' ', end=' ') e = DSStoreEntry.read(block) print(e, ' (%u)' % e.byte_length()) print('used: %u' % block.tell()) # Display the data in the super block def _dump_super(self): print('root: %u\nlevels: %u\nrecords: %u\nnodes: %u\npage-size: %u' \ % (self._rootnode, self._levels, self._records, self._nodes, self._page_size)) # Splits entries across two blocks, returning one pivot # # Tries to balance the block usage across the two as best it can def _split2(self, blocks, entries, pointers, before, internal): left_block = blocks[0] right_block = blocks[1] count = len(entries) # Find the feasible splits best_split = None best_diff = None total = before[count] if 8 + total <= self._page_size: # We can use a *single* node for this best_split = count else: # Split into two nodes for n in range(1, count - 1): left_size = 8 + before[n] right_size = 8 + total - before[n + 1] if left_size > self._page_size: break if right_size > self._page_size: continue diff = abs(left_size - right_size) if best_split is None or diff < best_diff: best_split = n best_diff = diff if best_split is None: return None # Write the nodes left_block.seek(0) if internal: next_node = pointers[best_split] else: next_node = 0 left_block.write(b'>II', next_node, best_split) for n in range(best_split): if internal: left_block.write(b'>I', pointers[n]) entries[n].write(left_block) left_block.zero_fill() if best_split == count: return [] right_block.seek(0) if internal: next_node = pointers[count] else: next_node = 0 right_block.write(b'>II', next_node, count - best_split - 1) for n in range(best_split + 1, count): if internal: right_block.write(b'>I', pointers[n]) entries[n].write(right_block) right_block.zero_fill() pivot = entries[best_split] return [pivot] def _split(self, node, entry, right_ptr=0): self._nodes += 1 self._dirty = True new_right = self._store.allocate(self._page_size) with self._get_block(node) as block, \ self._get_block(new_right) as right_block: # First, measure and extract all the elements entry_size = entry.byte_length() entry_pos = None next_node, count = block.read(b'>II') if next_node: entry_size += 4 pointers = [] entries = [] before = [] total = 0 for n in range(count): pos = block.tell() if next_node: ptr = block.read(b'>I')[0] pointers.append(ptr) e = DSStoreEntry.read(block) if e > entry: entry_pos = n entries.append(entry) pointers.append(right_ptr) before.append(total) total += entry_size entries.append(e) before.append(total) total += block.tell() - pos before.append(total) if next_node: pointers.append(next_node) pivot = self._split2([block, right_block], entries, pointers, before, bool(next_node))[0] self._records += 1 self._nodes += 1 self._dirty = True return (pivot, new_right) # Allocate a new root node containing the element `pivot' and the pointers # `left' and `right' def _new_root(self, left, pivot, right): new_root = self._store.allocate(self._page_size) with self._get_block(new_root) as block: block.write(b'>III', right, 1, left) pivot.write(block) self._rootnode = new_root self._levels += 1 self._nodes += 1 self._dirty = True # Insert an entry into an inner node; `path' is the path from the root # to `node', not including `node' itself. `right_ptr' is the new node # pointer (inserted to the RIGHT of `entry') def _insert_inner(self, path, node, entry, right_ptr): with self._get_block(node) as block: next_node, count = block.read(b'>II') insert_pos = None insert_ndx = None n = 0 while n < count: pos = block.tell() ptr = block.read(b'>I')[0] e = DSStoreEntry.read(block) if e == entry: if n == count - 1: right_ptr = next_node next_node = ptr block_seek(pos) else: right_ptr = block.read(b'>I')[0] block.seek(pos + 4) insert_pos = pos insert_ndx = n block.delete(e.byte_length() + 4) count -= 1 self._records += 1 self._dirty = True continue elif insert_pos is None and e > entry: insert_pos = pos insert_ndx = n n += 1 if insert_pos is None: insert_pos = block.tell() insert_ndx = count remaining = self._page_size - block.tell() if remaining < entry.byte_length() + 4: pivot, new_right = self._split(node, entry, right_ptr) if path: self._insert_inner(path[:-1], path[-1], pivot, new_right) else: self._new_root(node, pivot, new_right) else: if insert_ndx == count: block.seek(insert_pos) block.write(b'>I', next_node) entry.write(block) next_node = right_ptr else: block.seek(insert_pos + 4) entry.write(block, True) block.insert('>I', right_ptr) block.seek(0) count += 1 block.write(b'>II', next_node, count) self._records += 1 self._dirty = True # Insert `entry' into the leaf node `node' def _insert_leaf(self, path, node, entry): with self._get_block(node) as block: next_node, count = block.read(b'>II') insert_pos = None insert_ndx = None n = 0 while n < count: pos = block.tell() e = DSStoreEntry.read(block) if e == entry: insert_pos = pos insert_ndx = n block.seek(pos) block.delete(e.byte_length()) count -= 1 self._records += 1 self._dirty = True continue elif insert_pos is None and e > entry: insert_pos = pos insert_ndx = n n += 1 if insert_pos is None: insert_pos = block.tell() insert_ndx = count remaining = self._page_size - block.tell() if remaining < entry.byte_length(): pivot, new_right = self._split(node, entry) if path: self._insert_inner(path[:-1], path[-1], pivot, new_right) else: self._new_root(node, pivot, new_right) else: block.seek(insert_pos) entry.write(block, True) block.seek(0) count += 1 block.write(b'>II', next_node, count) self._records += 1 self._dirty = True def insert(self, entry): """Insert ``entry`` (which should be a :class:`DSStoreEntry`) into the B-Tree.""" path = [] node = self._rootnode while True: with self._get_block(node) as block: next_node, count = block.read(b'>II') if next_node: for n in range(count): ptr = block.read(b'>I')[0] e = DSStoreEntry.read(block) if entry < e: next_node = ptr break elif entry == e: # If we find an existing entry the same, replace it self._insert_inner(path, node, entry, None) return path.append(node) node = next_node else: self._insert_leaf(path, node, entry) return # Return usage information for the specified `node' def _block_usage(self, node): with self._get_block(node) as block: next_node, count = block.read(b'>II') for n in range(count): if next_node: ptr = block.read(b'>I')[0] e = DSStoreEntry.read(block) used = block.tell() return (count, used) # Splits entries across three blocks, returning two pivots def _split3(self, blocks, entries, pointers, before, internal): count = len(entries) # Find the feasible splits best_split = None best_diff = None total = before[count] for n in range(1, count - 3): left_size = 8 + before[n] remaining = 16 + total - before[n + 1] if left_size > self._page_size: break if remaining > 2 * self._page_size: continue for m in range(n + 2, count - 1): mid_size = 8 + before[m] - before[n + 1] right_size = 8 + total - before[m + 1] if mid_size > self._page_size: break if right_size > self._page_size: continue diff = abs(left_size - mid_size) * abs(right_size - mid_size) if best_split is None or diff < best_diff: best_split = (n, m, count) best_diff = diff if best_split is None: return None # Write the nodes prev_split = -1 for block, split in zip(blocks, best_split): block.seek(0) if internal: next_node = pointers[split] else: next_node = 0 block.write(b'>II', next_node, split) for n in range(prev_split + 1, split): if internal: block.write(b'>I', pointers[n]) entries[n].write(block) block.zero_fill() prev_split = split return (entries[best_split[0]], entries[best_split[1]]) # Extract all of the entries from the specified list of `blocks', # separating them by the specified `pivots'. Also computes the # amount of space used before each entry. def _extract(self, blocks, pivots): pointers = [] entries = [] before = [] total = 0 ppivots = pivots + [None] for b,p in zip(blocks, ppivots): b.seek(0) next_node, count = b.read(b'>II') for n in range(count): pos = b.tell() if next_node: ptr = b.read(b'>I')[0] pointers.append(ptr) e = DSStoreEntry.read(b) entries.append(e) before.append(total) total += b.tell() - pos if next_node: pointers.append(next_node) if p: entries.append(p) before.append(total) total += p.byte_length() if next_node: total += 4 before.append(total) return (entries, pointers, before) # Rebalance the specified `node', whose path from the root is `path'. def _rebalance(self, path, node): # Can't rebalance the root if not path: return with self._get_block(node) as block: next_node, count = block.read(b'>II') with self._get_block(path[-1]) as parent: # Find the left and right siblings and respective pivots parent_next, parent_count = parent.read(b'>II') left_pos = None left_node = None left_pivot = None node_pos = None right_pos = None right_node = None right_pivot = None prev_e = prev_ptr = prev_pos = None for n in range(parent_count): pos = parent.tell() ptr = parent.read(b'>I')[0] e = DSStoreEntry.read(parent) if ptr == node: node_pos = pos right_pivot = e left_pos = prev_pos left_pivot = prev_e left_node = prev_ptr elif prev_ptr == node: right_node = ptr right_pos = pos break prev_e = e prev_ptr = ptr prev_pos = pos if parent_next == node: node_pos = parent.tell() left_pos = prev_pos left_pivot = prev_e left_node = prev_ptr elif right_node is None: right_node = parent_next right_pos = parent.tell() parent_used = parent.tell() if left_node and right_node: with self._get_block(left_node) as left, \ self._get_block(right_node) as right: blocks = [left, block, right] pivots = [left_pivot, right_pivot] entries, pointers, before = self._extract(blocks, pivots) # If there's a chance that we could use two pages instead # of three, go for it pivots = self._split2(blocks, entries, pointers, before, bool(next_node)) if pivots is None: ptrs = [left_node, node, right_node] pivots = self._split3(blocks, entries, pointers, before, bool(next_node)) else: if pivots: ptrs = [left_node, node] else: ptrs = [left_node] self._store.release(node) self._nodes -= 1 node = left_node self._store.release(right_node) self._nodes -= 1 self._dirty = True # Remove the pivots from the parent with self._get_block(path[-1]) as parent: if right_node == parent_next: parent.seek(left_pos) parent.delete(right_pos - left_pos) parent_next = left_node else: parent.seek(left_pos + 4) parent.delete(right_pos - left_pos) parent.seek(0) parent_count -= 2 parent.write(b'>II', parent_next, parent_count) self._records -= 2 # Replace with those in pivots for e,rp in zip(pivots, ptrs[1:]): self._insert_inner(path[:-1], path[-1], e, rp) elif left_node: with self._get_block(left_node) as left: blocks = [left, block] pivots = [left_pivot] entries, pointers, before = self._extract(blocks, pivots) pivots = self._split2(blocks, entries, pointers, before, bool(next_node)) # Remove the pivot from the parent with self._get_block(path[-1]) as parent: if node == parent_next: parent.seek(left_pos) parent.delete(node_pos - left_pos) parent_next = left_node else: parent.seek(left_pos + 4) parent.delete(node_pos - left_pos) parent.seek(0) parent_count -= 1 parent.write(b'>II', parent_next, parent_count) self._records -= 1 # Replace the pivot if pivots: self._insert_inner(path[:-1], path[-1], pivots[0], node) elif right_node: with self._get_block(right_node) as right: blocks = [block, right] pivots = [right_pivot] entries, pointers, before = self._extract(blocks, pivots) pivots = self._split2(blocks, entries, pointers, before, bool(next_node)) # Remove the pivot from the parent with self._get_block(path[-1]) as parent: if right_node == parent_next: parent.seek(pos) parent.delete(right_pos - node_pos) parent_next = node else: parent.seek(pos + 4) parent.delete(right_pos - node_pos) parent.seek(0) parent_count -= 1 parent.write(b'>II', parent_next, parent_count) self._records -= 1 # Replace the pivot if pivots: self._insert_inner(path[:-1], path[-1], pivots[0], right_node) if not path and not parent_count: self._store.release(path[-1]) self._nodes -= 1 self._dirty = True self._rootnode = node else: count, used = self._block_usage(path[-1]) if used < self._page_size // 2: self._rebalance(path[:-1], path[-1]) # Delete from the leaf node `node'. `filename_lc' has already been # lower-cased. def _delete_leaf(self, node, filename_lc, code): found = False with self._get_block(node) as block: next_node, count = block.read(b'>II') for n in range(count): pos = block.tell() e = DSStoreEntry.read(block) if e.filename.lower() == filename_lc \ and (code is None or e.code == code): block.seek(pos) block.delete(e.byte_length()) found = True # This does not affect the loop; THIS IS NOT A BUG count -= 1 self._records -= 1 self._dirty = True if found: used = block.tell() block.seek(0) block.write(b'>II', next_node, count) return used < self._page_size // 2 else: return False # Remove the largest entry from the subtree starting at `node' (with # path from root `path'). Returns a tuple (rebalance, entry) where # rebalance is either None if no rebalancing is required, or a # (path, node) tuple giving the details of the node to rebalance. def _take_largest(self, path, node): path = list(path) rebalance = None while True: with self._get_block(node) as block: next_node, count = block.read(b'>II') if next_node: path.append(node) node = next_node continue for n in range(count): pos = block.tell() e = DSStoreEntry.read(block) count -= 1 block.seek(0) block.write(b'>II', next_node, count) if pos < self._page_size // 2: rebalance = (path, node) break return rebalance, e # Delete an entry from an inner node, `node' def _delete_inner(self, path, node, filename_lc, code): rebalance = False with self._get_block(node) as block: next_node, count = block.read(b'>II') for n in range(count): pos = block.tell() ptr = block.read(b'>I')[0] e = DSStoreEntry.read(block) if e.filename.lower() == filename_lc \ and (code is None or e.code == code): # Take the largest from the left subtree rebalance, largest = self._take_largest(path, ptr) # Delete this entry if n == count - 1: right_ptr = next_node next_node = ptr block.seek(pos) else: right_ptr = block.read(b'>I')[0] block.seek(pos + 4) block.delete(e.byte_length() + 4) count -= 1 block.seek(0) block.write(b'>II', next_node, count) self._records -= 1 self._dirty = True break # Replace the pivot value self._insert_inner(path, node, largest, right_ptr) # Rebalance from the node we stole from if rebalance: self._rebalance(rebalance[0], rebalance[1]) return True return False def delete(self, filename, code): """Delete an item, identified by ``filename`` and ``code`` from the B-Tree.""" if isinstance(filename, DSStoreEntry): code = filename.code filename = filename.filename # If we're deleting *every* node for "filename", we must recurse if code is None: ###TODO: Fix this so we can do bulk deletes raise ValueError('You must delete items individually. Sorry') # Otherwise, we're deleting *one* specific node filename_lc = filename.lower() path = [] node = self._rootnode while True: with self._get_block(node) as block: next_node, count = block.read(b'>II') if next_node: for n in range(count): ptr = block.read(b'>I')[0] e = DSStoreEntry.read(block) e_lc = e.filename.lower() if filename_lc < e_lc \ or (filename_lc == e_lc and code < e.code): next_node = ptr break elif filename_lc == e_lc and code == e.code: self._delete_inner(path, node, filename_lc, code) return path.append(node) node = next_node else: if self._delete_leaf(node, filename_lc, code): self._rebalance(path, node) return # Find implementation def _find(self, node, filename_lc, code=None): if not isinstance(code, bytes): code = code.encode('latin_1') with self._get_block(node) as block: next_node, count = block.read(b'>II') if next_node: for n in range(count): ptr = block.read(b'>I')[0] e = DSStoreEntry.read(block) if filename_lc < e.filename.lower(): for e in self._find(ptr, filename_lc, code): yield e return elif filename_lc == e.filename.lower(): if code is None or (code and code < e.code): for e in self._find(ptr, filename_lc, code): yield e if code is None or code == e.code: yield e elif code < e.code: return for e in self._find(next_node, filename_lc, code): yield e else: for n in range(count): e = DSStoreEntry.read(block) if filename_lc == e.filename.lower(): if code is None or code == e.code: yield e elif code < e.code: return def find(self, filename, code=None): """Returns a generator that will iterate over matching entries in the B-Tree.""" if isinstance(filename, DSStoreEntry): code = filename.code filename = filename.filename filename_lc = filename.lower() return self._find(self._rootnode, filename_lc, code) def __len__(self): return self._records def __iter__(self): return self._traverse(self._rootnode) class Partial(object): """This is used to implement indexing.""" def __init__(self, store, filename): self._store = store self._filename = filename def __getitem__(self, code): if code is None: raise KeyError('no such key - [%s][None]' % self._filename) if not isinstance(code, bytes): code = code.encode('latin_1') try: item = next(self._store.find(self._filename, code)) except StopIteration: raise KeyError('no such key - [%s][%s]' % (self._filename, code)) if not isinstance(item.type, (bytes, str, unicode)): return item.value return (item.type, item.value) def __setitem__(self, code, value): if code is None: raise KeyError('bad key - [%s][None]' % self._filename) if not isinstance(code, bytes): code = code.encode('latin_1') codec = codecs.get(code, None) if codec: entry_type = codec entry_value = value else: entry_type = value[0] entry_value = value[1] self._store.insert(DSStoreEntry(self._filename, code, entry_type, entry_value)) def __delitem__(self, code): if code is None: raise KeyError('no such key - [%s][None]' % self._filename) self._store.delete(self._filename, code) def __iter__(self): for item in self._store.find(self._filename): yield item def __getitem__(self, filename): return self.Partial(self, filename) qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/000077500000000000000000000000001347155106100260015ustar00rootroot00000000000000qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/LICENSE000066400000000000000000000020451347155106100270070ustar00rootroot00000000000000Copyright (c) 2014 Alastair Houghton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/__init__.py000066400000000000000000000021561347155106100301160ustar00rootroot00000000000000from .alias import * from .bookmark import * __all__ = [ 'ALIAS_KIND_FILE', 'ALIAS_KIND_FOLDER', 'ALIAS_HFS_VOLUME_SIGNATURE', 'ALIAS_FIXED_DISK', 'ALIAS_NETWORK_DISK', 'ALIAS_400KB_FLOPPY_DISK', 'ALIAS_800KB_FLOPPY_DISK', 'ALIAS_1_44MB_FLOPPY_DISK', 'ALIAS_EJECTABLE_DISK', 'ALIAS_NO_CNID', 'kBookmarkPath', 'kBookmarkCNIDPath', 'kBookmarkFileProperties', 'kBookmarkFileName', 'kBookmarkFileID', 'kBookmarkFileCreationDate', 'kBookmarkTOCPath', 'kBookmarkVolumePath', 'kBookmarkVolumeURL', 'kBookmarkVolumeName', 'kBookmarkVolumeUUID', 'kBookmarkVolumeSize', 'kBookmarkVolumeCreationDate', 'kBookmarkVolumeProperties', 'kBookmarkContainingFolder', 'kBookmarkUserName', 'kBookmarkUID', 'kBookmarkWasFileReference', 'kBookmarkCreationOptions', 'kBookmarkURLLengths', 'kBookmarkSecurityExtension', 'AppleShareInfo', 'VolumeInfo', 'TargetInfo', 'Alias', 'Bookmark', 'Data', 'URL' ] qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/alias.py000066400000000000000000000534151347155106100274540ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals from __future__ import division import struct import datetime import io import re import os import os.path import stat import sys if sys.platform == 'darwin': from . import osx try: long except NameError: long = int from .utils import * ALIAS_KIND_FILE = 0 ALIAS_KIND_FOLDER = 1 ALIAS_HFS_VOLUME_SIGNATURE = b'H+' ALIAS_FIXED_DISK = 0 ALIAS_NETWORK_DISK = 1 ALIAS_400KB_FLOPPY_DISK = 2 ALIAS_800KB_FLOPPY_DISK = 3 ALIAS_1_44MB_FLOPPY_DISK = 4 ALIAS_EJECTABLE_DISK = 5 ALIAS_NO_CNID = 0xffffffff def encode_utf8(s): if isinstance(s, bytes): return s return s.encode('utf-8') def decode_utf8(s): if isinstance(s, bytes): return s.decode('utf-8') return s class AppleShareInfo (object): def __init__(self, zone=None, server=None, user=None): #: The AppleShare zone self.zone = zone #: The AFP server self.server = server #: The username self.user = user def __repr__(self): return 'AppleShareInfo(%r,%r,%r)' % (self.zone, self.server, self.user) class VolumeInfo (object): def __init__(self, name, creation_date, fs_type, disk_type, attribute_flags, fs_id, appleshare_info=None, driver_name=None, posix_path=None, disk_image_alias=None, dialup_info=None, network_mount_info=None): #: The name of the volume on which the target resides self.name = name #: The creation date of the target's volume self.creation_date = creation_date #: The filesystem type (a two character code, e.g. ``b'H+'`` for HFS+) self.fs_type = fs_type #: The type of disk; should be one of #: #: * ALIAS_FIXED_DISK #: * ALIAS_NETWORK_DISK #: * ALIAS_400KB_FLOPPY_DISK #: * ALIAS_800KB_FLOPPY_DISK #: * ALIAS_1_44MB_FLOPPY_DISK #: * ALIAS_EJECTABLE_DISK self.disk_type = disk_type #: Filesystem attribute flags (from HFS volume header) self.attribute_flags = attribute_flags #: Filesystem identifier self.fs_id = fs_id #: AppleShare information (for automatic remounting of network shares) #: *(optional)* self.appleshare_info = appleshare_info #: Driver name (*probably* contains a disk driver name on older Macs) #: *(optional)* self.driver_name = driver_name #: POSIX path of the mount point of the target's volume #: *(optional)* self.posix_path = posix_path #: :class:`Alias` object pointing at the disk image on which the #: target's volume resides *(optional)* self.disk_image_alias = disk_image_alias #: Dialup information (for automatic establishment of dialup connections) self.dialup_info = dialup_info #: Network mount information (for automatic remounting) self.network_mount_info = network_mount_info def __repr__(self): args = ['name', 'creation_date', 'fs_type', 'disk_type', 'attribute_flags', 'fs_id'] values = [] for a in args: v = getattr(self, a) values.append(repr(v)) kwargs = ['appleshare_info', 'driver_name', 'posix_path', 'disk_image_alias', 'dialup_info', 'network_mount_info'] for a in kwargs: v = getattr(self, a) if v is not None: values.append('%s=%r' % (a, v)) return 'VolumeInfo(%s)' % ','.join(values) class TargetInfo (object): def __init__(self, kind, filename, folder_cnid, cnid, creation_date, creator_code, type_code, levels_from=-1, levels_to=-1, folder_name=None, cnid_path=None, carbon_path=None, posix_path=None, user_home_prefix_len=None): #: Either ALIAS_KIND_FILE or ALIAS_KIND_FOLDER self.kind = kind #: The filename of the target self.filename = filename #: The CNID (Catalog Node ID) of the target's containing folder; #: CNIDs are similar to but different than traditional UNIX inode #: numbers self.folder_cnid = folder_cnid #: The CNID (Catalog Node ID) of the target self.cnid = cnid #: The target's *creation* date. self.creation_date = creation_date #: The target's Mac creator code (a four-character binary string) self.creator_code = creator_code #: The target's Mac type code (a four-character binary string) self.type_code = type_code #: The depth of the alias? Always seems to be -1 on OS X. self.levels_from = levels_from #: The depth of the target? Always seems to be -1 on OS X. self.levels_to = levels_to #: The (POSIX) name of the target's containing folder. *(optional)* self.folder_name = folder_name #: The path from the volume root as a sequence of CNIDs. *(optional)* self.cnid_path = cnid_path #: The Carbon path of the target *(optional)* self.carbon_path = carbon_path #: The POSIX path of the target relative to the volume root. Note #: that this may or may not have a leading '/' character, but it is #: always relative to the containing volume. *(optional)* self.posix_path = posix_path #: If the path points into a user's home folder, the number of folders #: deep that we go before we get to that home folder. *(optional)* self.user_home_prefix_len = user_home_prefix_len def __repr__(self): args = ['kind', 'filename', 'folder_cnid', 'cnid', 'creation_date', 'creator_code', 'type_code'] values = [] for a in args: v = getattr(self, a) values.append(repr(v)) if self.levels_from != -1: values.append('levels_from=%r' % self.levels_from) if self.levels_to != -1: values.append('levels_to=%r' % self.levels_to) kwargs = ['folder_name', 'cnid_path', 'carbon_path', 'posix_path', 'user_home_prefix_len'] for a in kwargs: v = getattr(self, a) values.append('%s=%r' % (a, v)) return 'TargetInfo(%s)' % ','.join(values) TAG_CARBON_FOLDER_NAME = 0 TAG_CNID_PATH = 1 TAG_CARBON_PATH = 2 TAG_APPLESHARE_ZONE = 3 TAG_APPLESHARE_SERVER_NAME = 4 TAG_APPLESHARE_USERNAME = 5 TAG_DRIVER_NAME = 6 TAG_NETWORK_MOUNT_INFO = 9 TAG_DIALUP_INFO = 10 TAG_UNICODE_FILENAME = 14 TAG_UNICODE_VOLUME_NAME = 15 TAG_HIGH_RES_VOLUME_CREATION_DATE = 16 TAG_HIGH_RES_CREATION_DATE = 17 TAG_POSIX_PATH = 18 TAG_POSIX_PATH_TO_MOUNTPOINT = 19 TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE = 20 TAG_USER_HOME_LENGTH_PREFIX = 21 class Alias (object): def __init__(self, appinfo=b'\0\0\0\0', version=2, volume=None, target=None, extra=[]): """Construct a new :class:`Alias` object with the specified contents.""" #: Application specific information (four byte byte-string) self.appinfo = appinfo #: Version (we support only version 2) self.version = version #: A :class:`VolumeInfo` object describing the target's volume self.volume = volume #: A :class:`TargetInfo` object describing the target self.target = target #: A list of extra `(tag, value)` pairs self.extra = list(extra) @classmethod def _from_fd(cls, b): appinfo, recsize, version = struct.unpack(b'>4shh', b.read(8)) if recsize < 150: raise ValueError('Incorrect alias length') if version != 2: raise ValueError('Unsupported alias version %u' % version) kind, volname, voldate, fstype, disktype, \ folder_cnid, filename, cnid, crdate, creator_code, type_code, \ levels_from, levels_to, volattrs, volfsid, reserved = \ struct.unpack(b'>h28pI2shI64pII4s4shhI2s10s', b.read(142)) voldate = mac_epoch + datetime.timedelta(seconds=voldate) crdate = mac_epoch + datetime.timedelta(seconds=crdate) alias = Alias() alias.appinfo = appinfo alias.volume = VolumeInfo (volname.decode().replace('/',':'), voldate, fstype, disktype, volattrs, volfsid) alias.target = TargetInfo (kind, filename.decode().replace('/',':'), folder_cnid, cnid, crdate, creator_code, type_code) alias.target.levels_from = levels_from alias.target.levels_to = levels_to tag = struct.unpack(b'>h', b.read(2))[0] while tag != -1: length = struct.unpack(b'>h', b.read(2))[0] value = b.read(length) if length & 1: b.read(1) if tag == TAG_CARBON_FOLDER_NAME: alias.target.folder_name = value.decode().replace('/',':') elif tag == TAG_CNID_PATH: alias.target.cnid_path = struct.unpack('>%uI' % (length // 4), value) elif tag == TAG_CARBON_PATH: alias.target.carbon_path = value elif tag == TAG_APPLESHARE_ZONE: if alias.volume.appleshare_info is None: alias.volume.appleshare_info = AppleShareInfo() alias.volume.appleshare_info.zone = value elif tag == TAG_APPLESHARE_SERVER_NAME: if alias.volume.appleshare_info is None: alias.volume.appleshare_info = AppleShareInfo() alias.volume.appleshare_info.server = value elif tag == TAG_APPLESHARE_USERNAME: if alias.volume.appleshare_info is None: alias.volume.appleshare_info = AppleShareInfo() alias.volume.appleshare_info.user = value elif tag == TAG_DRIVER_NAME: alias.volume.driver_name = value elif tag == TAG_NETWORK_MOUNT_INFO: alias.volume.network_mount_info = value elif tag == TAG_DIALUP_INFO: alias.volume.dialup_info = value elif tag == TAG_UNICODE_FILENAME: alias.target.filename = value[2:].decode('utf-16be') elif tag == TAG_UNICODE_VOLUME_NAME: alias.volume.name = value[2:].decode('utf-16be') elif tag == TAG_HIGH_RES_VOLUME_CREATION_DATE: seconds = struct.unpack(b'>Q', value)[0] / 65536.0 alias.volume.creation_date \ = mac_epoch + datetime.timedelta(seconds=seconds) elif tag == TAG_HIGH_RES_CREATION_DATE: seconds = struct.unpack(b'>Q', value)[0] / 65536.0 alias.target.creation_date \ = mac_epoch + datetime.timedelta(seconds=seconds) elif tag == TAG_POSIX_PATH: alias.target.posix_path = value.decode() elif tag == TAG_POSIX_PATH_TO_MOUNTPOINT: alias.volume.posix_path = value.decode() elif tag == TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE: alias.volume.disk_image_alias = Alias.from_bytes(value) elif tag == TAG_USER_HOME_LENGTH_PREFIX: alias.target.user_home_prefix_len = struct.unpack(b'>h', value)[0] else: alias.extra.append((tag, value)) tag = struct.unpack(b'>h', b.read(2))[0] return alias @classmethod def from_bytes(cls, bytes): """Construct an :class:`Alias` object given binary Alias data.""" with io.BytesIO(bytes) as b: return cls._from_fd(b) @classmethod def for_file(cls, path): """Create an :class:`Alias` that points at the specified file.""" if sys.platform != 'darwin': raise Exception('Not implemented (requires special support)') path = encode_utf8(path) a = Alias() # Find the filesystem st = osx.statfs(path) vol_path = st.f_mntonname # Grab its attributes attrs = [osx.ATTR_CMN_CRTIME, osx.ATTR_VOL_NAME, 0, 0, 0] volinfo = osx.getattrlist(vol_path, attrs, 0) vol_crtime = volinfo[0] vol_name = encode_utf8(volinfo[1]) # Also grab various attributes of the file attrs = [(osx.ATTR_CMN_OBJTYPE | osx.ATTR_CMN_CRTIME | osx.ATTR_CMN_FNDRINFO | osx.ATTR_CMN_FILEID | osx.ATTR_CMN_PARENTID), 0, 0, 0, 0] info = osx.getattrlist(path, attrs, osx.FSOPT_NOFOLLOW) if info[0] == osx.VDIR: kind = ALIAS_KIND_FOLDER else: kind = ALIAS_KIND_FILE cnid = info[3] folder_cnid = info[4] dirname, filename = os.path.split(path) if dirname == b'' or dirname == b'.': dirname = os.getcwd() foldername = os.path.basename(dirname) creation_date = info[1] if kind == ALIAS_KIND_FILE: creator_code = struct.pack(b'I', info[2].fileInfo.fileCreator) type_code = struct.pack(b'I', info[2].fileInfo.fileType) else: creator_code = b'\0\0\0\0' type_code = b'\0\0\0\0' a.target = TargetInfo(kind, filename, folder_cnid, cnid, creation_date, creator_code, type_code) a.volume = VolumeInfo(vol_name, vol_crtime, b'H+', ALIAS_FIXED_DISK, 0, b'\0\0') a.target.folder_name = foldername a.volume.posix_path = vol_path rel_path = os.path.relpath(path, vol_path) # Leave off the initial '/' if vol_path is '/' (no idea why) if vol_path == b'/': a.target.posix_path = rel_path else: a.target.posix_path = b'/' + rel_path # Construct the Carbon and CNID paths carbon_path = [] cnid_path = [] head, tail = os.path.split(rel_path) if not tail: head, tail = os.path.split(head) while head or tail: if head: attrs = [osx.ATTR_CMN_FILEID, 0, 0, 0, 0] info = osx.getattrlist(os.path.join(vol_path, head), attrs, 0) cnid_path.append(info[0]) carbon_tail = tail.replace(b':',b'/') carbon_path.insert(0, carbon_tail) head, tail = os.path.split(head) carbon_path = vol_name + b':' + b':\0'.join(carbon_path) a.target.carbon_path = carbon_path a.target.cnid_path = cnid_path return a def _to_fd(self, b): # We'll come back and fix the length when we're done pos = b.tell() b.write(struct.pack(b'>4shh', self.appinfo, 0, self.version)) carbon_volname = encode_utf8(self.volume.name).replace(b':',b'/') carbon_filename = encode_utf8(self.target.filename).replace(b':',b'/') voldate = (self.volume.creation_date - mac_epoch).total_seconds() crdate = (self.target.creation_date - mac_epoch).total_seconds() # NOTE: crdate should be in local time, but that's system dependent # (so doing so is ridiculous, and nothing could rely on it). b.write(struct.pack(b'>h28pI2shI64pII4s4shhI2s10s', self.target.kind, carbon_volname, int(voldate), self.volume.fs_type, self.volume.disk_type, self.target.folder_cnid, carbon_filename, self.target.cnid, int(crdate), self.target.creator_code, self.target.type_code, self.target.levels_from, self.target.levels_to, self.volume.attribute_flags, self.volume.fs_id, b'\0'*10)) # Excuse the odd order; we're copying Finder if self.target.folder_name: carbon_foldername = encode_utf8(self.target.folder_name)\ .replace(b':',b'/') b.write(struct.pack(b'>hh', TAG_CARBON_FOLDER_NAME, len(carbon_foldername))) b.write(carbon_foldername) if len(carbon_foldername) & 1: b.write(b'\0') b.write(struct.pack(b'>hhQhhQ', TAG_HIGH_RES_VOLUME_CREATION_DATE, 8, int(voldate * 65536), TAG_HIGH_RES_CREATION_DATE, 8, int(crdate * 65536))) if self.target.cnid_path: cnid_path = struct.pack('>%uI' % len(self.target.cnid_path), *self.target.cnid_path) b.write(struct.pack(b'>hh', TAG_CNID_PATH, len(cnid_path))) b.write(cnid_path) if self.target.carbon_path: carbon_path=encode_utf8(self.target.carbon_path) b.write(struct.pack(b'>hh', TAG_CARBON_PATH, len(carbon_path))) b.write(carbon_path) if len(carbon_path) & 1: b.write(b'\0') if self.volume.appleshare_info: ai = self.volume.appleshare_info if ai.zone: b.write(struct.pack(b'>hh', TAG_APPLESHARE_ZONE, len(ai.zone))) b.write(ai.zone) if len(ai.zone) & 1: b.write(b'\0') if ai.server: b.write(struct.pack(b'>hh', TAG_APPLESHARE_SERVER_NAME, len(ai.server))) b.write(ai.server) if len(ai.server) & 1: b.write(b'\0') if ai.username: b.write(struct.pack(b'>hh', TAG_APPLESHARE_USERNAME, len(ai.username))) b.write(ai.username) if len(ai.username) & 1: b.write(b'\0') if self.volume.driver_name: driver_name = encode_utf8(self.volume.driver_name) b.write(struct.pack(b'>hh', TAG_DRIVER_NAME, len(driver_name))) b.write(driver_name) if len(driver_name) & 1: b.write(b'\0') if self.volume.network_mount_info: b.write(struct.pack(b'>hh', TAG_NETWORK_MOUNT_INFO, len(self.volume.network_mount_info))) b.write(self.volume.network_mount_info) if len(self.volume.network_mount_info) & 1: b.write(b'\0') if self.volume.dialup_info: b.write(struct.pack(b'>hh', TAG_DIALUP_INFO, len(self.volume.network_mount_info))) b.write(self.volume.network_mount_info) if len(self.volume.network_mount_info) & 1: b.write(b'\0') utf16 = decode_utf8(self.target.filename)\ .replace(':','/').encode('utf-16-be') b.write(struct.pack(b'>hhh', TAG_UNICODE_FILENAME, len(utf16) + 2, len(utf16) // 2)) b.write(utf16) utf16 = decode_utf8(self.volume.name)\ .replace(':','/').encode('utf-16-be') b.write(struct.pack(b'>hhh', TAG_UNICODE_VOLUME_NAME, len(utf16) + 2, len(utf16) // 2)) b.write(utf16) if self.target.posix_path: posix_path = encode_utf8(self.target.posix_path) b.write(struct.pack(b'>hh', TAG_POSIX_PATH, len(posix_path))) b.write(posix_path) if len(posix_path) & 1: b.write(b'\0') if self.volume.posix_path: posix_path = encode_utf8(self.volume.posix_path) b.write(struct.pack(b'>hh', TAG_POSIX_PATH_TO_MOUNTPOINT, len(posix_path))) b.write(posix_path) if len(posix_path) & 1: b.write(b'\0') if self.volume.disk_image_alias: d = self.volume.disk_image_alias.to_bytes() b.write(struct.pack(b'>hh', TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE, len(d))) b.write(d) if len(d) & 1: b.write(b'\0') if self.target.user_home_prefix_len is not None: b.write(struct.pack(b'>hhh', TAG_USER_HOME_LENGTH_PREFIX, 2, self.target.user_home_prefix_len)) for t,v in self.extra: b.write(struct.pack(b'>hh', t, len(v))) b.write(v) if len(v) & 1: b.write(b'\0') b.write(struct.pack(b'>hh', -1, 0)) blen = b.tell() - pos b.seek(pos + 4, os.SEEK_SET) b.write(struct.pack(b'>h', blen)) def to_bytes(self): """Returns the binary representation for this :class:`Alias`.""" with io.BytesIO() as b: self._to_fd(b) return b.getvalue() def __str__(self): return '' % self.target.filename def __repr__(self): values = [] if self.appinfo != b'\0\0\0\0': values.append('appinfo=%r' % self.appinfo) if self.version != 2: values.append('version=%r' % self.version) if self.volume is not None: values.append('volume=%r' % self.volume) if self.target is not None: values.append('target=%r' % self.target) if self.extra: values.append('extra=%r' % self.extra) return 'Alias(%s)' % ','.join(values) qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/bookmark.py000066400000000000000000000603451347155106100301700ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # This file implements the Apple "bookmark" format, which is the replacement # for the old-fashioned alias format. The details of this format were # reverse engineered; some things are still not entirely clear. # from __future__ import unicode_literals, print_function import struct import uuid import datetime import os import sys import pprint try: from urlparse import urljoin except ImportError: from urllib.parse import urljoin if sys.platform == 'darwin': from . import osx def iteritems(x): return x.iteritems() try: unicode except NameError: unicode = str long = int xrange = range def iteritems(x): return x.items() from .utils import * BMK_DATA_TYPE_MASK = 0xffffff00 BMK_DATA_SUBTYPE_MASK = 0x000000ff BMK_STRING = 0x0100 BMK_DATA = 0x0200 BMK_NUMBER = 0x0300 BMK_DATE = 0x0400 BMK_BOOLEAN = 0x0500 BMK_ARRAY = 0x0600 BMK_DICT = 0x0700 BMK_UUID = 0x0800 BMK_URL = 0x0900 BMK_NULL = 0x0a00 BMK_ST_ZERO = 0x0000 BMK_ST_ONE = 0x0001 BMK_BOOLEAN_ST_FALSE = 0x0000 BMK_BOOLEAN_ST_TRUE = 0x0001 # Subtypes for BMK_NUMBER are really CFNumberType values kCFNumberSInt8Type = 1 kCFNumberSInt16Type = 2 kCFNumberSInt32Type = 3 kCFNumberSInt64Type = 4 kCFNumberFloat32Type = 5 kCFNumberFloat64Type = 6 kCFNumberCharType = 7 kCFNumberShortType = 8 kCFNumberIntType = 9 kCFNumberLongType = 10 kCFNumberLongLongType = 11 kCFNumberFloatType = 12 kCFNumberDoubleType = 13 kCFNumberCFIndexType = 14 kCFNumberNSIntegerType = 15 kCFNumberCGFloatType = 16 # Resource property flags (from CFURLPriv.h) kCFURLResourceIsRegularFile = 0x00000001 kCFURLResourceIsDirectory = 0x00000002 kCFURLResourceIsSymbolicLink = 0x00000004 kCFURLResourceIsVolume = 0x00000008 kCFURLResourceIsPackage = 0x00000010 kCFURLResourceIsSystemImmutable = 0x00000020 kCFURLResourceIsUserImmutable = 0x00000040 kCFURLResourceIsHidden = 0x00000080 kCFURLResourceHasHiddenExtension = 0x00000100 kCFURLResourceIsApplication = 0x00000200 kCFURLResourceIsCompressed = 0x00000400 kCFURLResourceIsSystemCompressed = 0x00000400 kCFURLCanSetHiddenExtension = 0x00000800 kCFURLResourceIsReadable = 0x00001000 kCFURLResourceIsWriteable = 0x00002000 kCFURLResourceIsExecutable = 0x00004000 kCFURLIsAliasFile = 0x00008000 kCFURLIsMountTrigger = 0x00010000 # Volume property flags (from CFURLPriv.h) kCFURLVolumeIsLocal = 0x1 # kCFURLVolumeIsAutomount = 0x2 # kCFURLVolumeDontBrowse = 0x4 # kCFURLVolumeIsReadOnly = 0x8 # kCFURLVolumeIsQuarantined = 0x10 kCFURLVolumeIsEjectable = 0x20 # kCFURLVolumeIsRemovable = 0x40 # kCFURLVolumeIsInternal = 0x80 # kCFURLVolumeIsExternal = 0x100 # kCFURLVolumeIsDiskImage = 0x200 # kCFURLVolumeIsFileVault = 0x400 kCFURLVolumeIsLocaliDiskMirror = 0x800 kCFURLVolumeIsiPod = 0x1000 # kCFURLVolumeIsiDisk = 0x2000 kCFURLVolumeIsCD = 0x4000 kCFURLVolumeIsDVD = 0x8000 kCFURLVolumeIsDeviceFileSystem = 0x10000 kCFURLVolumeSupportsPersistentIDs = 0x100000000 kCFURLVolumeSupportsSearchFS = 0x200000000 kCFURLVolumeSupportsExchange = 0x400000000 # reserved 0x800000000 kCFURLVolumeSupportsSymbolicLinks = 0x1000000000 kCFURLVolumeSupportsDenyModes = 0x2000000000 kCFURLVolumeSupportsCopyFile = 0x4000000000 kCFURLVolumeSupportsReadDirAttr = 0x8000000000 kCFURLVolumeSupportsJournaling = 0x10000000000 kCFURLVolumeSupportsRename = 0x20000000000 kCFURLVolumeSupportsFastStatFS = 0x40000000000 kCFURLVolumeSupportsCaseSensitiveNames = 0x80000000000 kCFURLVolumeSupportsCasePreservedNames = 0x100000000000 kCFURLVolumeSupportsFLock = 0x200000000000 kCFURLVolumeHasNoRootDirectoryTimes = 0x400000000000 kCFURLVolumeSupportsExtendedSecurity = 0x800000000000 kCFURLVolumeSupports2TBFileSize = 0x1000000000000 kCFURLVolumeSupportsHardLinks = 0x2000000000000 kCFURLVolumeSupportsMandatoryByteRangeLocks = 0x4000000000000 kCFURLVolumeSupportsPathFromID = 0x8000000000000 # reserved 0x10000000000000 kCFURLVolumeIsJournaling = 0x20000000000000 kCFURLVolumeSupportsSparseFiles = 0x40000000000000 kCFURLVolumeSupportsZeroRuns = 0x80000000000000 kCFURLVolumeSupportsVolumeSizes = 0x100000000000000 kCFURLVolumeSupportsRemoteEvents = 0x200000000000000 kCFURLVolumeSupportsHiddenFiles = 0x400000000000000 kCFURLVolumeSupportsDecmpFSCompression = 0x800000000000000 kCFURLVolumeHas64BitObjectIDs = 0x1000000000000000 kCFURLVolumePropertyFlagsAll = 0xffffffffffffffff BMK_URL_ST_ABSOLUTE = 0x0001 BMK_URL_ST_RELATIVE = 0x0002 # Bookmark keys # = 0x1003 kBookmarkPath = 0x1004 # Array of path components kBookmarkCNIDPath = 0x1005 # Array of CNIDs kBookmarkFileProperties = 0x1010 # (CFURL rp flags, # CFURL rp flags asked for, # 8 bytes NULL) kBookmarkFileName = 0x1020 kBookmarkFileID = 0x1030 kBookmarkFileCreationDate = 0x1040 # = 0x1054 # ? # = 0x1055 # ? # = 0x1056 # ? # = 0x1101 # ? # = 0x1102 # ? kBookmarkTOCPath = 0x2000 # A list of (TOC id, ?) pairs kBookmarkVolumePath = 0x2002 kBookmarkVolumeURL = 0x2005 kBookmarkVolumeName = 0x2010 kBookmarkVolumeUUID = 0x2011 # Stored (perversely) as a string kBookmarkVolumeSize = 0x2012 kBookmarkVolumeCreationDate = 0x2013 kBookmarkVolumeProperties = 0x2020 # (CFURL vp flags, # CFURL vp flags asked for, # 8 bytes NULL) kBookmarkVolumeIsRoot = 0x2030 # True if volume is FS root kBookmarkVolumeBookmark = 0x2040 # Embedded bookmark for disk image (TOC id) kBookmarkVolumeMountPoint = 0x2050 # A URL # = 0x2070 kBookmarkContainingFolder = 0xc001 # Index of containing folder in path kBookmarkUserName = 0xc011 # User that created bookmark kBookmarkUID = 0xc012 # UID that created bookmark kBookmarkWasFileReference = 0xd001 # True if the URL was a file reference kBookmarkCreationOptions = 0xd010 kBookmarkURLLengths = 0xe003 # See below # = 0xf017 # Localized name? # = 0xf022 kBookmarkSecurityExtension = 0xf080 # = 0xf081 # kBookmarkURLLengths is an array that is set if the URL encoded by the # bookmark had a base URL; in that case, each entry is the length of the # base URL in question. Thus a URL # # file:///foo/bar/baz blam/blat.html # # will result in [3, 2], while the URL # # file:///foo bar/baz blam blat.html # # would result in [1, 2, 1, 1] class Data (object): def __init__(self, bytedata=None): #: The bytes, stored as a byte string self.bytes = bytes(bytedata) def __repr__(self): return 'Data(%r)' % self.bytes class URL (object): def __init__(self, base, rel=None): if rel is not None: #: The base URL, if any (a :class:`URL`) self.base = base #: The rest of the URL (a string) self.relative = rel else: self.base = None self.relative = base @property def absolute(self): """Return an absolute URL.""" if self.base is None: return self.relative else: base_abs = self.base.absolute return urljoin(self.base.absolute, self.relative) def __repr__(self): return 'URL(%r)' % self.absolute class Bookmark (object): def __init__(self, tocs=None): if tocs is None: #: The TOCs for this Bookmark self.tocs = [] else: self.tocs = tocs @classmethod def _get_item(cls, data, hdrsize, offset): offset += hdrsize if offset > len(data) - 8: raise ValueError('Offset out of range') length,typecode = struct.unpack(b'd', databytes)[0]) return osx_epoch + secs elif dtype == BMK_BOOLEAN: if dsubtype == BMK_BOOLEAN_ST_TRUE: return True elif dsubtype == BMK_BOOLEAN_ST_FALSE: return False elif dtype == BMK_UUID: return uuid.UUID(bytes=databytes) elif dtype == BMK_URL: if dsubtype == BMK_URL_ST_ABSOLUTE: return URL(databytes.decode('utf-8')) elif dsubtype == BMK_URL_ST_RELATIVE: baseoff,reloff = struct.unpack(b' size: raise ValueError('Not a bookmark file (header size too large)') if size != len(data): raise ValueError('Not a bookmark file (truncated)') tocoffset, = struct.unpack(b' size - hdrsize \ or size - tocbase < 20: raise ValueError('TOC offset out of range') tocsize,tocmagic,tocid,nexttoc,toccount \ = struct.unpack(b' -0x80000000 and item < 0x7fffffff: result = struct.pack(b'd', float(secs.total_seconds())) elif isinstance(item, uuid.UUID): result = struct.pack(b' -1: sz = sz[:nul] return sz.decode('utf-8') def _decode_attrlist_result(buf, attrs, options): result = [] assert len(buf) >= 4 total_size = uint32_t.from_buffer(buf, 0).value assert total_size <= len(buf) offset = 4 # Common attributes if attrs[0] & ATTR_CMN_RETURNED_ATTRS: a = attribute_set_t.from_buffer(buf, offset) result.append(a) offset += sizeof (attribute_set_t) if not (options & FSOPT_PACK_INVAL_ATTRS): attrs = [a.commonattr, a.volattr, a.dirattr, a.fileattr, a.forkattr] if attrs[0] & ATTR_CMN_NAME: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset name = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) offset += sizeof (attrreference_t) result.append(name) if attrs[0] & ATTR_CMN_DEVID: a = dev_t.from_buffer(buf, offset) offset += sizeof(dev_t) result.append(a.value) if attrs[0] & ATTR_CMN_FSID: a = fsid_t.from_buffer(buf, offset) offset += sizeof(fsid_t) result.append(a) if attrs[0] & ATTR_CMN_OBJTYPE: a = fsobj_type_t.from_buffer(buf, offset) offset += sizeof(fsobj_type_t) result.append(a.value) if attrs[0] & ATTR_CMN_OBJTAG: a = fsobj_tag_t.from_buffer(buf, offset) offset += sizeof(fsobj_tag_t) result.append(a.value) if attrs[0] & ATTR_CMN_OBJID: a = fsobj_id_t.from_buffer(buf, offset) offset += sizeof(fsobj_id_t) result.append(a) if attrs[0] & ATTR_CMN_OBJPERMANENTID: a = fsobj_id_t.from_buffer(buf, offset) offset += sizeof(fsobj_id_t) result.append(a) if attrs[0] & ATTR_CMN_PAROBJID: a = fsobj_id_t.from_buffer(buf, offset) offset += sizeof(fsobj_id_t) result.append(a) if attrs[0] & ATTR_CMN_SCRIPT: a = text_encoding_t.from_buffer(buf, offset) offset += sizeof(text_encoding_t) result.append(a.value) if attrs[0] & ATTR_CMN_CRTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) if attrs[0] & ATTR_CMN_MODTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) if attrs[0] & ATTR_CMN_CHGTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) if attrs[0] & ATTR_CMN_ACCTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) if attrs[0] & ATTR_CMN_BKUPTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) if attrs[0] & ATTR_CMN_FNDRINFO: a = FinderInfo.from_buffer(buf, offset) offset += sizeof(FinderInfo) result.append(a) if attrs[0] & ATTR_CMN_OWNERID: a = uid_t.from_buffer(buf, offset) offset += sizeof(uid_t) result.append(a.value) if attrs[0] & ATTR_CMN_GRPID: a = gid_t.from_buffer(buf, offset) offset += sizeof(gid_t) result.append(a.value) if attrs[0] & ATTR_CMN_ACCESSMASK: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[0] & ATTR_CMN_FLAGS: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[0] & ATTR_CMN_USERACCESS: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[0] & ATTR_CMN_EXTENDED_SECURITY: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset offset += sizeof(attrreference_t) ec = uint32_t.from_buffer(buf, ofs + 36).value class kauth_acl(Structure): _fields_ = [('acl_entrycount', c_uint), ('acl_flags', c_uint), ('acl_ace', kauth_ace * ec)] class kauth_filesec(Structure): _fields_ = [('fsec_magic', c_uint), ('fsec_owner', guid_t), ('fsec_group', guid_t), ('fsec_acl', kauth_acl)] a = kauth_filesec.from_buffer(buf, ofs) result.append(a) if attrs[0] & ATTR_CMN_UUID: result.append(uuid.UUID(bytes=buf[offset:offset+16])) offset += sizeof(guid_t) if attrs[0] & ATTR_CMN_GRPUUID: result.append(uuid.UUID(bytes=buf[offset:offset+16])) offset += sizeof(guid_t) if attrs[0] & ATTR_CMN_FILEID: a = uint64_t.from_buffer(buf, offset) offset += sizeof(uint64_t) result.append(a.value) if attrs[0] & ATTR_CMN_PARENTID: a = uint64_t.from_buffer(buf, offset) offset += sizeof(uint64_t) result.append(a.value) if attrs[0] & ATTR_CMN_FULLPATH: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) offset += sizeof (attrreference_t) result.append(path) if attrs[0] & ATTR_CMN_ADDEDTIME: a = timespec.from_buffer(buf, offset) offset += sizeof(timespec) result.append(_datetime_from_timespec(a)) # Volume attributes if attrs[1] & ATTR_VOL_FSTYPE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_SIGNATURE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_SIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_SPACEFREE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_SPACEAVAIL: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_MINALLOCATION: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_ALLOCATIONCLUMP: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[1] & ATTR_VOL_IOBLOCKSIZE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_OBJCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_FILECOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_DIRCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_MAXOBJCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_MOUNTPOINT: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) offset += sizeof (attrreference_t) result.append(path) if attrs[1] & ATTR_VOL_NAME: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset name = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) offset += sizeof (attrreference_t) result.append(name) if attrs[1] & ATTR_VOL_MOUNTFLAGS: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[1] & ATTR_VOL_MOUNTEDDEVICE: a = attrreference_t.from_buffer(buf, offset) ofs = offset + a.attr_dataoffset path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) offset += sizeof (attrreference_t) result.append(path) if attrs[1] & ATTR_VOL_ENCODINGSUSED: a = c_ulonglong.from_buffer(buf, offset) offset += sizeof(c_ulonglong) result.append(a.value) if attrs[1] & ATTR_VOL_CAPABILITIES: a = vol_capabilities_attr_t.from_buffer(buf, offset) offset += sizeof(vol_capabilities_attr_t) result.append(a) if attrs[1] & ATTR_VOL_UUID: result.append(uuid.UUID(bytes=buf[offset:offset+16])) offset += sizeof(uuid_t) if attrs[1] & ATTR_VOL_ATTRIBUTES: a = vol_attributes_attr_t.from_buffer(buf, offset) offset += sizeof(vol_attributes_attr_t) result.append(a) # Directory attributes if attrs[2] & ATTR_DIR_LINKCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[2] & ATTR_DIR_ENTRYCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[2] & ATTR_DIR_MOUNTSTATUS: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) # File attributes if attrs[3] & ATTR_FILE_LINKCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_TOTALSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_ALLOCSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_IOBLOCKSIZE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_CLUMPSIZE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_DEVTYPE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_FILETYPE: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_FORKCOUNT: a = uint32_t.from_buffer(buf, offset) offset += sizeof(uint32_t) result.append(a.value) if attrs[3] & ATTR_FILE_DATALENGTH: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_DATAALLOCSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_DATAEXTENTS: a = extentrecord.from_buffer(buf, offset) offset += sizeof(extentrecord) result.append(a.value) if attrs[3] & ATTR_FILE_RSRCLENGTH: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_RSRCALLOCSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[3] & ATTR_FILE_RSRCEXTENTS: a = extentrecord.from_buffer(buf, offset) offset += sizeof(extentrecord) result.append(a.value) # Fork attributes if attrs[4] & ATTR_FORK_TOTALSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) if attrs[4] & ATTR_FORK_ALLOCSIZE: a = off_t.from_buffer(buf, offset) offset += sizeof(off_t) result.append(a.value) return result # Sadly, ctypes.get_errno() seems not to work __error = libc.__error __error.restype = POINTER(c_int) def _get_errno(): return __error().contents.value def getattrlist(path, attrs, options): if not isinstance(path, bytes): path = path.encode('utf-8') attrs = list(attrs) if attrs[1]: attrs[1] |= ATTR_VOL_INFO alist = attrlist(bitmapcount=5, commonattr=attrs[0], volattr=attrs[1], dirattr=attrs[2], fileattr=attrs[3], forkattr=attrs[4]) bufsize = _attrbuf_size(attrs) buf = create_string_buffer(bufsize) ret = _getattrlist(path, byref(alist), buf, bufsize, options | FSOPT_REPORT_FULLSIZE) if ret < 0: err = _get_errno() raise OSError(err, os.strerror(err), path) return _decode_attrlist_result(buf, attrs, options) def fgetattrlist(fd, attrs, options): if hasattr(fd, 'fileno'): fd = fd.fileno() attrs = list(attrs) if attrs[1]: attrs[1] |= ATTR_VOL_INFO alist = attrlist(bitmapcount=5, commonattr=attrs[0], volattr=attrs[1], dirattr=attrs[2], fileattr=attrs[3], forkattr=attrs[4]) bufsize = _attrbuf_size(attrs) buf = create_string_buffer(bufsize) ret = _fgetattrlist(fd, byref(alist), buf, bufsize, options | FSOPT_REPORT_FULLSIZE) if ret < 0: err = _get_errno() raise OSError(err, os.strerror(err)) return _decode_attrlist_result(buf, attrs, options) def statfs(path): if not isinstance(path, bytes): path = path.encode('utf-8') result = struct_statfs() ret = _statfs(path, byref(result)) if ret < 0: err = _get_errno() raise OSError(err, os.strerror(err), path) return result def fstatfs(fd): if hasattr(fd, 'fileno'): fd = fd.fileno() result = struct_statfs() ret = _fstatfs(fd, byref(result)) if ret < 0: err = _get_errno() raise OSError(err, os.strerror(err)) return result qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/qt_attribution.json000066400000000000000000000006751347155106100317540ustar00rootroot00000000000000{ "Id": "mac_alias", "Name": "mac_alias", "QDocModule": "qbs", "QtUsage": "Used in the qbs dmg module for building Apple disk images.", "Description": "Generate/parse Mac OS Alias records from Python", "Homepage": "https://github.com/al45tair/mac_alias", "Version": "2.0.6", "License": "MIT License", "LicenseId": "MIT", "LicenseFile": "LICENSE", "Copyright": "Copyright (c) 2014 Alastair Houghton" } qbs-src-1.13.1/src/3rdparty/python/lib/python2.7/site-packages/mac_alias/utils.py000066400000000000000000000007011347155106100275110ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals import datetime ZERO = datetime.timedelta(0) class UTC (datetime.tzinfo): def utcoffset(self, dt): return ZERO def dst(self, dt): return ZERO def tzname(self, dt): return 'UTC' utc = UTC() mac_epoch = datetime.datetime(1904,1,1,0,0,0,0,utc) unix_epoch = datetime.datetime(1970,1,1,0,0,0,0,utc) osx_epoch = datetime.datetime(2001,1,1,0,0,0,0,utc) qbs-src-1.13.1/src/app/000077500000000000000000000000001347155106100145215ustar00rootroot00000000000000qbs-src-1.13.1/src/app/app.pri000066400000000000000000000012401347155106100160120ustar00rootroot00000000000000include(../install_prefix.pri) QT = core TEMPLATE = app DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_PROCESS_COMBINED_ARGUMENT_START !isEmpty(QBS_APPS_DESTDIR):DESTDIR = $${QBS_APPS_DESTDIR} else:DESTDIR = ../../../bin !isEmpty(QBS_APPS_RPATH_DIR) { linux-*:QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,$${QBS_APPS_RPATH_DIR}\' macx:QMAKE_LFLAGS += -Wl,-rpath,$${QBS_APPS_RPATH_DIR} } CONFIG += console CONFIG -= app_bundle CONFIG += c++14 include($${PWD}/../lib/corelib/use_corelib.pri) include($${PWD}/shared/logging/logging.pri) !isEmpty(QBS_APPS_INSTALL_DIR):target.path = $${QBS_APPS_INSTALL_DIR} else:target.path = $${QBS_INSTALL_PREFIX}/bin INSTALLS += target qbs-src-1.13.1/src/app/app.pro000066400000000000000000000003011347155106100160150ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS =\ qbs\ qbs-create-project \ qbs-setup-android \ qbs-setup-toolchains \ qbs-setup-qt \ config !isEmpty(QT.widgets.name):SUBDIRS += config-ui qbs-src-1.13.1/src/app/apps.qbs000066400000000000000000000005211347155106100161710ustar00rootroot00000000000000import qbs Project { references: [ "config/config.qbs", "config-ui/config-ui.qbs", "qbs/qbs.qbs", "qbs-create-project/qbs-create-project.qbs", "qbs-setup-android/qbs-setup-android.qbs", "qbs-setup-qt/qbs-setup-qt.qbs", "qbs-setup-toolchains/qbs-setup-toolchains.qbs", ] } qbs-src-1.13.1/src/app/config-ui/000077500000000000000000000000001347155106100164015ustar00rootroot00000000000000qbs-src-1.13.1/src/app/config-ui/Info.plist000066400000000000000000000007061347155106100203540ustar00rootroot00000000000000 CFBundleIdentifier org.qt-project.qbs-config-ui CFBundleInfoDictionaryVersion 6.0 CFBundleName Qbs Settings LSUIElement 1 qbs-src-1.13.1/src/app/config-ui/commandlineparser.cpp000066400000000000000000000104741347155106100226160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include using qbs::Internal::Tr; static QString helpOptionShort() { return QStringLiteral("-h"); } static QString helpOptionLong() { return QStringLiteral("--help"); } static QString settingsDirOption() { return QStringLiteral("--settings-dir"); } static QString systemOption() { return QStringLiteral("--system"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.empty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_settingsDir.clear(); if (m_commandLine.empty()) return; const QString &arg = m_commandLine.front(); if (arg == helpOptionShort() || arg == helpOptionLong()) { m_commandLine.removeFirst(); m_helpRequested = true; } else if (arg == systemOption()) { m_commandLine.removeFirst(); m_settingsScope = qbs::Settings::SystemScope; } else if (arg == settingsDirOption()) { m_commandLine.removeFirst(); assignOptionArgument(settingsDirOption(), m_settingsDir); } if (!m_commandLine.empty()) complainAboutExtraArguments(); } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool displays qbs settings in a GUI.\n" "If you have more than a few settings, this might be preferable to " "plain \"qbs config\", as it presents a hierarchical view.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] [%5] [%3|%4]\n") .arg(m_command, settingsDirOption(), helpOptionShort(), helpOptionLong(), systemOption()); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-1.13.1/src/app/config-ui/commandlineparser.h000066400000000000000000000052651347155106100222650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_CONFIGUI_COMMANDLINEPARSER_H #define QBS_CONFIGUI_COMMANDLINEPARSER_H #include #include class CommandLineParser { public: void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } QString settingsDir() const { return m_settingsDir; } qbs::Settings::Scope settingsScope() const { return m_settingsScope; } QString usageString() const; private: [[noreturn]] void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); [[noreturn]] void complainAboutExtraArguments(); bool m_helpRequested; qbs::Settings::Scope m_settingsScope = qbs::Settings::UserScope; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Include guard qbs-src-1.13.1/src/app/config-ui/config-ui.pro000066400000000000000000000007121347155106100210030ustar00rootroot00000000000000include(../app.pri) CONFIG -= console QT += gui widgets TARGET = qbs-config-ui HEADERS += \ commandlineparser.h \ mainwindow.h SOURCES += \ commandlineparser.cpp \ main.cpp \ mainwindow.cpp OTHER_FILES += \ Info.plist osx { QMAKE_LFLAGS += -sectcreate __TEXT __info_plist $$shell_quote($$PWD/Info.plist) OBJECTIVE_SOURCES += fgapp.mm LIBS += -framework ApplicationServices -framework Cocoa } FORMS += mainwindow.ui qbs-src-1.13.1/src/app/config-ui/config-ui.qbs000066400000000000000000000012461347155106100207730ustar00rootroot00000000000000import qbs 1.0 QbsApp { Depends { name: "Qt.widgets" } name: "qbs-config-ui" consoleApplication: false files: [ "commandlineparser.cpp", "commandlineparser.h", "main.cpp", "mainwindow.cpp", "mainwindow.h", "mainwindow.ui", ] Group { condition: qbs.targetOS.contains("macos") files: [ "fgapp.mm", "Info.plist" ] } Properties { condition: qbs.targetOS.contains("macos") cpp.frameworks: ["ApplicationServices", "Cocoa"] } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } qbs-src-1.13.1/src/app/config-ui/fgapp.mm000066400000000000000000000042611347155106100200340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import #include extern "C" void qt_macos_forceTransformProcessToForegroundApplicationAndActivate() { [[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular]; [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; } qbs-src-1.13.1/src/app/config-ui/main.cpp000066400000000000000000000051221347155106100200310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "commandlineparser.h" #include #include #include #include #include using qbs::Internal::Tr; int main(int argc, char *argv[]) { QApplication app(argc, argv); CommandLineParser clParser; try { clParser.parse(app.arguments()); if (clParser.helpRequested()) { std::cout << qPrintable(clParser.usageString()); return EXIT_SUCCESS; } } catch (const qbs::ErrorInfo &error) { std::cerr << qPrintable(error.toString()); return EXIT_FAILURE; } MainWindow mw(clParser.settingsDir(), clParser.settingsScope()); mw.show(); return app.exec(); } qbs-src-1.13.1/src/app/config-ui/mainwindow.cpp000066400000000000000000000170731347155106100212710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include #include #include #include #include #include #include #include MainWindow::MainWindow(const QString &settingsDir, qbs::Settings::Scope scope, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); m_model = new qbs::SettingsModel(settingsDir, scope, this); ui->treeView->setModel(m_model); ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->treeView, &QTreeView::expanded, this, &MainWindow::adjustColumns); connect(ui->treeView, &QWidget::customContextMenuRequested, this, &MainWindow::provideContextMenu); adjustColumns(); QMenu * const fileMenu = menuBar()->addMenu(tr("&File")); QMenu * const viewMenu = menuBar()->addMenu(tr("&View")); const auto reloadAction = new QAction(tr("&Reload"), this); reloadAction->setShortcut(QKeySequence::Refresh); connect(reloadAction, &QAction::triggered, this, &MainWindow::reloadSettings); const auto saveAction = new QAction(tr("&Save"), this); saveAction->setShortcut(QKeySequence::Save); connect(saveAction, &QAction::triggered, this, &MainWindow::saveSettings); const auto expandAllAction = new QAction(tr("&Expand All"), this); expandAllAction->setShortcut(Qt::CTRL | Qt::Key_E); connect(expandAllAction, &QAction::triggered, this, &MainWindow::expandAll); const auto collapseAllAction = new QAction(tr("C&ollapse All"), this); collapseAllAction->setShortcut(Qt::CTRL | Qt::Key_O); connect(collapseAllAction, &QAction::triggered, this, &MainWindow::collapseAll); const auto exitAction = new QAction(tr("E&xit"), this); exitAction->setShortcut(QKeySequence::Quit); exitAction->setMenuRole(QAction::QuitRole); connect(exitAction, &QAction::triggered, this, &MainWindow::exit); fileMenu->addAction(reloadAction); fileMenu->addAction(saveAction); fileMenu->addSeparator(); fileMenu->addAction(exitAction); viewMenu->addAction(expandAllAction); viewMenu->addAction(collapseAllAction); ui->treeView->installEventFilter(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::adjustColumns() { for (int column = 0; column < m_model->columnCount(); ++column) ui->treeView->resizeColumnToContents(column); } void MainWindow::expandAll() { ui->treeView->expandAll(); adjustColumns(); } void MainWindow::collapseAll() { ui->treeView->collapseAll(); adjustColumns(); } void MainWindow::reloadSettings() { if (m_model->hasUnsavedChanges()) { const QMessageBox::StandardButton answer = QMessageBox::question(this, tr("Unsaved Changes"), tr("You have unsaved changes. Do you want to discard them?")); if (answer != QMessageBox::Yes) return; } m_model->reload(); } void MainWindow::saveSettings() { m_model->save(); } void MainWindow::exit() { if (m_model->hasUnsavedChanges()) { const QMessageBox::StandardButton answer = QMessageBox::question(this, tr("Unsaved Changes"), tr("You have unsaved changes. Do you want to save them now?")); if (answer == QMessageBox::Yes) m_model->save(); } qApp->quit(); } void MainWindow::provideContextMenu(const QPoint &pos) { const QModelIndex index = ui->treeView->indexAt(pos); if (index.isValid() && index.column() != m_model->keyColumn()) return; const QString settingsKey = m_model->data(index).toString(); QMenu contextMenu; QAction addKeyAction(this); QAction removeKeyAction(this); if (index.isValid()) { addKeyAction.setText(tr("Add new key below '%1'").arg(settingsKey)); removeKeyAction.setText(tr("Remove key '%1' and all its sub-keys").arg(settingsKey)); contextMenu.addAction(&addKeyAction); contextMenu.addAction(&removeKeyAction); } else { addKeyAction.setText(tr("Add new top-level key")); contextMenu.addAction(&addKeyAction); } const QAction *action = contextMenu.exec(ui->treeView->mapToGlobal(pos)); if (action == &addKeyAction) m_model->addNewKey(index); else if (action == &removeKeyAction) m_model->removeKey(index); } extern "C" void qt_macos_forceTransformProcessToForegroundApplicationAndActivate(); bool MainWindow::eventFilter(QObject *watched, QEvent *event) { if (ui->treeView->hasFocus() && event->type() == QEvent::KeyPress) { const auto keyEvent = static_cast(event); if (keyEvent->matches(QKeySequence::Delete)) { const QModelIndexList indexes = ui->treeView->selectionModel()->selectedRows(); if (indexes.size() == 1) { const QModelIndex index = indexes.front(); if (index.isValid()) { m_model->removeKey(index); return true; } } } } if (event->type() == QEvent::WindowActivate) { // Effectively delay the foreground process transformation from QApplication construction to // when the UI is shown - this prevents the application icon from popping up in the Dock // when running `qbs help`, and QCoreApplication::arguments() requires the application // object to be constructed, so it is not easily worked around #if defined(Q_OS_MACOS) || defined(Q_OS_OSX) qt_macos_forceTransformProcessToForegroundApplicationAndActivate(); #endif } return QMainWindow::eventFilter(watched, event); } qbs-src-1.13.1/src/app/config-ui/mainwindow.h000066400000000000000000000051631347155106100207330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include namespace qbs { class SettingsModel; } QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } class QPoint; QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(const QString &settingsDir, qbs::Settings::Scope scope, QWidget *parent = nullptr); ~MainWindow(); bool eventFilter(QObject *watched, QEvent *event); private: void adjustColumns(); void expandAll(); void collapseAll(); void reloadSettings(); void saveSettings(); void exit(); void provideContextMenu(const QPoint &pos); Ui::MainWindow *ui; qbs::SettingsModel *m_model; }; #endif // MAINWINDOW_H qbs-src-1.13.1/src/app/config-ui/mainwindow.ui000066400000000000000000000015141347155106100211150ustar00rootroot00000000000000 MainWindow 0 0 800 600 Qbs Settings 0 0 800 27 qbs-src-1.13.1/src/app/config/000077500000000000000000000000001347155106100157665ustar00rootroot00000000000000qbs-src-1.13.1/src/app/config/config.pro000066400000000000000000000003541347155106100177570ustar00rootroot00000000000000include(../app.pri) TARGET = qbs-config SOURCES += \ configcommandexecutor.cpp \ configcommandlineparser.cpp \ configmain.cpp HEADERS += \ configcommand.h \ configcommandexecutor.h \ configcommandlineparser.h qbs-src-1.13.1/src/app/config/config.qbs000066400000000000000000000004161347155106100177430ustar00rootroot00000000000000import qbs 1.0 QbsApp { name: "qbs-config" files: [ "configcommand.h", "configcommandexecutor.cpp", "configcommandexecutor.h", "configcommandlineparser.cpp", "configcommandlineparser.h", "configmain.cpp" ] } qbs-src-1.13.1/src/app/config/configcommand.h000066400000000000000000000043751347155106100207540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CONFIGCOMMAND_H #define CONFIGCOMMAND_H #include #include #include class ConfigCommand { public: enum Command { CfgSet, CfgUnset, CfgList, CfgExport, CfgImport, CfgNone }; ConfigCommand() : command(CfgNone) {} Command command; QStringList varNames; QString varValue; QString fileName; }; #endif // CONFIGCOMMAND_H qbs-src-1.13.1/src/app/config/configcommandexecutor.cpp000066400000000000000000000136751347155106100230710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "configcommandexecutor.h" #include "configcommand.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include using namespace qbs; ConfigCommandExecutor::ConfigCommandExecutor(Settings *settings, Settings::Scopes scope) : m_settings(settings), m_scope(scope) { if (m_scope == qbs::Settings::SystemScope) m_settings->setScopeForWriting(qbs::Settings::SystemScope); } void ConfigCommandExecutor::execute(const ConfigCommand &command) { switch (command.command) { case ConfigCommand::CfgList: printSettings(command); break; case ConfigCommand::CfgSet: setValue(command.varNames.front(), command.varValue); break; case ConfigCommand::CfgUnset: for (const QString &varName : command.varNames) m_settings->remove(varName); break; case ConfigCommand::CfgExport: exportSettings(command.fileName); break; case ConfigCommand::CfgImport: // Display old and new settings, in case import fails or user accidentally nukes everything printf("old "); // Will end up as "old settings:" printSettings(command); importSettings(command.fileName); printf("\nnew "); printSettings(command); break; case ConfigCommand::CfgNone: qFatal("%s: Impossible command value.", Q_FUNC_INFO); break; } } void ConfigCommandExecutor::setValue(const QString &key, const QString &rawInput) { m_settings->setValue(key, representationToSettingsValue(rawInput)); } void ConfigCommandExecutor::printSettings(const ConfigCommand &command) { if (command.varNames.empty()) { const auto keys = m_settings->allKeys(m_scope); for (const QString &key : keys) printOneSetting(key); } else { for (const QString &parentKey : command.varNames) { if (m_settings->value(parentKey, m_scope).isValid()) { // Key is a leaf. printOneSetting(parentKey); } else { // Key is a node. const auto keys = m_settings->allKeysWithPrefix(parentKey, m_scope); for (const QString &key : keys) printOneSetting(parentKey + QLatin1Char('.') + key); } } } } void ConfigCommandExecutor::printOneSetting(const QString &key) { printf("%s: %s\n", qPrintable(key), qPrintable(qbs::settingsValueToRepresentation(m_settings->value(key, m_scope)))); } void ConfigCommandExecutor::exportSettings(const QString &filename) { QFile file(filename); if (!file.open(QFile::Truncate | QFile::WriteOnly | QFile::Text)) { throw ErrorInfo(tr("Could not open file '%1' for writing: %2") .arg(QDir::toNativeSeparators(filename), file.errorString())); } QTextStream stream(&file); stream.setCodec("UTF-8"); const auto keys = m_settings->allKeys(m_scope); for (const QString &key : keys) stream << key << ": " << qbs::settingsValueToRepresentation(m_settings->value(key, m_scope)) << endl; } void ConfigCommandExecutor::importSettings(const QString &filename) { QFile file(filename); if (!file.open(QFile::ReadOnly | QFile::Text)) { throw ErrorInfo(tr("Could not open file '%1' for reading: %2") .arg(QDir::toNativeSeparators(filename), file.errorString())); } // Remove all current settings const auto keys = m_settings->allKeys(m_scope); for (const QString &key : keys) m_settings->remove(key); QTextStream stream(&file); stream.setCodec("UTF-8"); while (!stream.atEnd()) { QString line = stream.readLine(); int colon = line.indexOf(QLatin1Char(':')); if (colon >= 0 && !line.startsWith(QLatin1Char('#'))) { const QString key = line.left(colon).trimmed(); const QString value = line.mid(colon + 1).trimmed(); m_settings->setValue(key, representationToSettingsValue(value)); } } } qbs-src-1.13.1/src/app/config/configcommandexecutor.h000066400000000000000000000051251347155106100225250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CONFIGCOMMANDEXECUTOR_H #define CONFIGCOMMANDEXECUTOR_H #include #include class ConfigCommand; class ConfigCommandExecutor { Q_DECLARE_TR_FUNCTIONS(ConfigCommandExecutor) public: ConfigCommandExecutor(qbs::Settings *settings, qbs::Settings::Scopes scope); void execute(const ConfigCommand &command); private: void setValue(const QString &key, const QString &rawInput); void printSettings(const ConfigCommand &command); void printOneSetting(const QString &key); void exportSettings(const QString &filename); void importSettings(const QString &filename); qbs::Settings *m_settings; const qbs::Settings::Scopes m_scope; }; #endif // CONFIGCOMMANDEXECUTOR_H qbs-src-1.13.1/src/app/config/configcommandlineparser.cpp000066400000000000000000000143361347155106100233720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "configcommandlineparser.h" #include #include #include using namespace qbs; using namespace Internal; void ConfigCommandLineParser::parse(const QStringList &commandLine) { m_command = ConfigCommand(); m_helpRequested = false; m_settingsDir.clear(); m_commandLine = commandLine; if (m_commandLine.empty()) throw Error(Tr::tr("No parameters supplied.")); if (m_commandLine.size() == 1 && (m_commandLine.front() == QLatin1String("--help") || m_commandLine.front() == QLatin1String("-h"))) { m_helpRequested = true; return; } while (!m_commandLine.empty() && m_commandLine.front().startsWith(QLatin1String("--"))) { const QString arg = m_commandLine.takeFirst().mid(2); if (arg == QLatin1String("list")) setCommand(ConfigCommand::CfgList); else if (arg == QLatin1String("unset")) setCommand(ConfigCommand::CfgUnset); else if (arg == QLatin1String("export")) setCommand(ConfigCommand::CfgExport); else if (arg == QLatin1String("import")) setCommand(ConfigCommand::CfgImport); else if (arg == QLatin1String("settings-dir")) assignOptionArgument(arg, m_settingsDir); else if (arg == QLatin1String("user")) setScope(qbs::Settings::UserScope); else if (arg == QLatin1String("system")) setScope(qbs::Settings::SystemScope); else throw Error(Tr::tr("Unknown option for config command.")); } switch (command().command) { case ConfigCommand::CfgNone: if (m_commandLine.empty()) throw Error(Tr::tr("No parameters supplied.")); if (m_commandLine.size() > 2) throw Error(Tr::tr("Too many arguments.")); m_command.varNames << m_commandLine.front(); if (m_commandLine.size() == 1) { setCommand(ConfigCommand::CfgList); } else { m_command.varValue = m_commandLine.at(1); setCommand(ConfigCommand::CfgSet); } break; case ConfigCommand::CfgUnset: if (m_commandLine.empty()) throw Error(Tr::tr("Need name of variable to unset.")); m_command.varNames = m_commandLine; break; case ConfigCommand::CfgExport: if (m_commandLine.size() != 1) throw Error(Tr::tr("Need name of file to which to export.")); m_command.fileName = m_commandLine.front(); break; case ConfigCommand::CfgImport: if (m_commandLine.size() != 1) throw Error(Tr::tr("Need name of file from which to import.")); m_command.fileName = m_commandLine.front(); break; case ConfigCommand::CfgList: m_command.varNames = m_commandLine; break; default: break; } } void ConfigCommandLineParser::setCommand(ConfigCommand::Command command) { if (m_command.command != ConfigCommand::CfgNone) throw Error(Tr::tr("You cannot specify more than one command.")); m_command.command = command; } void ConfigCommandLineParser::setScope(Settings::Scope scope) { if (m_scope != qbs::Settings::allScopes()) throw Error(Tr::tr("The --user and --system options can only appear once.")); m_scope = scope; } void ConfigCommandLineParser::printUsage() const { puts("Usage:\n" " qbs config [--settings-dir \n" " qbs config [--settings-dir \n" " qbs config [--settings-dir " "\n" "Options:\n" " --list [ ...] list keys under key or all keys\n" " --user consider only user-level settings\n" " --system consider only system-level settings\n" " --unset remove key with given name\n" " --import import settings from given file\n" " --export export settings to given file\n"); } void ConfigCommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throw Error(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throw Error(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } qbs-src-1.13.1/src/app/config/configcommandlineparser.h000066400000000000000000000056451347155106100230420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef COMMANDLINEPARSER_H #define COMMANDLINEPARSER_H #include "configcommand.h" #include #include class ConfigCommandLineParser { public: void parse(const QStringList &commandLine); ConfigCommand command() const { return m_command; } qbs::Settings::Scopes scope() const { return m_scope; } QString settingsDir() const { return m_settingsDir; } bool helpRequested() const { return m_helpRequested; } void printUsage() const; class Error { public: Error(const QString &message) : m_message(message) { } QString message() const { return m_message; } private: QString m_message; }; private: void assignOptionArgument(const QString &option, QString &argument); void setCommand(ConfigCommand::Command command); void setScope(qbs::Settings::Scope scope); ConfigCommand m_command; qbs::Settings::Scopes m_scope = qbs::Settings::allScopes(); bool m_helpRequested; QString m_settingsDir; QStringList m_commandLine; }; #endif // COMMANDLINEPARSER_H qbs-src-1.13.1/src/app/config/configmain.cpp000066400000000000000000000056541347155106100206160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "configcommandlineparser.h" #include "configcommandexecutor.h" #include #include #include #include #include #include using qbs::Internal::Tr; using qbs::Settings; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); ConfigCommandLineParser parser; try { parser.parse(app.arguments().mid(1)); if (parser.helpRequested()) { std::cout << qPrintable(Tr::tr("This tool manages qbs settings.")) << std::endl; parser.printUsage(); return EXIT_SUCCESS; } Settings settings(parser.settingsDir()); ConfigCommandExecutor(&settings, parser.scope()).execute(parser.command()); } catch (const ConfigCommandLineParser::Error &e) { std::cerr << qPrintable(e.message()) << std::endl; parser.printUsage(); return EXIT_FAILURE; } catch (const qbs::ErrorInfo &e) { std::cerr << qPrintable(e.toString()) << std::endl; return EXIT_FAILURE; } } qbs-src-1.13.1/src/app/qbs-create-project/000077500000000000000000000000001347155106100202135ustar00rootroot00000000000000qbs-src-1.13.1/src/app/qbs-create-project/create-project-main.cpp000066400000000000000000000104761347155106100245600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "createproject.h" #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { using qbs::ErrorInfo; using qbs::Internal::Tr; QCoreApplication app(argc, argv); const QCommandLineOption flatOpt(QStringLiteral("flat"), Tr::tr("Do not create nested project files, even if there are subdirectories and " "the top-level directory does not contain any files.")); const QCommandLineOption whiteListOpt(QStringLiteral("whitelist"), Tr::tr("Only consider files whose names match these patterns. The list entries " "can contain wildcards and are separated by commas. By default, all files " "are considered."), QStringLiteral("whitelist")); const QCommandLineOption blackListOpt(QStringLiteral("blacklist"), Tr::tr("Ignore files whose names match these patterns. The list entries " "can contain wildcards and are separated by commas. By default, no files " "are ignored."), QStringLiteral("blacklist")); QCommandLineParser parser; parser.setApplicationDescription(Tr::tr("This tool creates a qbs project from an existing " "source tree.\nNote: The resulting project file(s) " "will likely require manual editing.")); parser.addOption(flatOpt); parser.addOption(whiteListOpt); parser.addOption(blackListOpt); parser.addHelpOption(); parser.process(app); const ProjectStructure projectStructure = parser.isSet(flatOpt) ? ProjectStructure::Flat : ProjectStructure::Composite; const QStringList whiteList = parser.value(whiteListOpt).split(QLatin1Char(','), QString::SkipEmptyParts); const QStringList blackList = parser.value(blackListOpt).split(QLatin1Char(','), QString::SkipEmptyParts); try { ProjectCreator().run(QDir::currentPath(), projectStructure, whiteList, blackList); } catch (const ErrorInfo &e) { std::cerr << qPrintable(Tr::tr("Error creating project: %1").arg(e.toString())) << std::endl; return 1; } } qbs-src-1.13.1/src/app/qbs-create-project/createproject.cpp000066400000000000000000000231771347155106100235630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "createproject.h" #include #include #include #include #include #include #include #include #include #include using qbs::ErrorInfo; using qbs::Internal::Tr; static const char *indent = " "; void ProjectCreator::run(const QString &topLevelDir, ProjectStructure projectStructure, const QStringList &whiteList, const QStringList &blackList) { m_projectStructure = projectStructure; for (const QString &s : whiteList) m_whiteList.push_back(QRegExp(s, Qt::CaseSensitive, QRegExp::Wildcard)); for (const QString &s : blackList) m_blackList.push_back(QRegExp(s, Qt::CaseSensitive, QRegExp::Wildcard)); m_topLevelProject.dirPath = topLevelDir; setupProject(&m_topLevelProject); serializeProject(m_topLevelProject); } void ProjectCreator::setupProject(Project *project) { QDirIterator dit(project->dirPath, QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); while (dit.hasNext()) { dit.next(); if (dit.fileInfo().isFile()) { if (dit.fileName().endsWith(QLatin1String(".qbs"))) throw ErrorInfo(Tr::tr("Project already contains qbs files, aborting.")); if (isSourceFile(dit.fileName())) project->fileNames << dit.fileName(); } else if (dit.fileInfo().isDir()) { ProjectPtr subProject(new Project); subProject->dirName = dit.fileName(); subProject->dirPath = dit.filePath(); setupProject(subProject.get()); if (!subProject->fileNames.empty() || !subProject->subProjects.empty()) project->subProjects.push_back(std::move(subProject)); } } project->fileNames.sort(); std::sort(project->subProjects.begin(), project->subProjects.end(), [](const ProjectPtr &p1, const ProjectPtr &p2) { return p1->dirName < p2->dirName; }); } void ProjectCreator::serializeProject(const ProjectCreator::Project &project) { const QString fileName = QFileInfo(project.dirPath).baseName() + QLatin1String(".qbs"); QFile projectFile(project.dirPath + QLatin1Char('/') + fileName); if (!projectFile.open(QIODevice::WriteOnly)) { throw ErrorInfo(Tr::tr("Failed to open '%1' for writing: %2") .arg(projectFile.fileName(), projectFile.errorString())); } QTextStream fileContents(&projectFile); fileContents.setCodec("UTF-8"); fileContents << "import qbs\n\n"; if (!project.fileNames.empty() || m_projectStructure == ProjectStructure::Flat) { fileContents << "Product {\n"; const ProductFlags productFlags = getFlags(project); if (productFlags.testFlag(IsApp)) { fileContents << indent << "type: [\"application\"]\n"; } else { fileContents << indent << "type: [\"unknown\"] // E.g. \"application\", " "\"dynamiclibrary\", \"staticlibrary\"\n"; } if (productFlags.testFlag(NeedsQt)) { fileContents << indent << "Depends {\n"; fileContents << indent << indent << "name: \"Qt\"\n"; fileContents << indent << indent << "submodules: [\"core\"] " "// Add more here if needed\n"; fileContents << indent << "}\n"; } else if (productFlags.testFlag(NeedsCpp)) { fileContents << indent << "Depends { name: \"cpp\" }\n"; } fileContents << indent << "files: [\n"; for (const QString &fileName : qAsConst(project.fileNames)) fileContents << indent << indent << qbs::toJSLiteral(fileName) << ",\n"; fileContents << indent << "]\n"; for (const ProjectPtr &p : project.subProjects) addGroups(fileContents, QDir(project.dirPath), *p); } else { fileContents << "Project {\n"; fileContents << indent << "references: [\n"; for (const ProjectPtr &p : project.subProjects) { serializeProject(*p); fileContents << indent << indent << qbs::toJSLiteral(QFileInfo(p->dirPath).fileName()) << ",\n"; } fileContents << indent << "]\n"; } fileContents << "}\n"; } void ProjectCreator::addGroups(QTextStream &stream, const QDir &baseDir, const ProjectCreator::Project &subProject) { stream << indent << "Group {\n"; stream << indent << indent << "name: " << qbs::toJSLiteral(QFileInfo(subProject.dirPath).fileName()) << "\n"; stream << indent << indent << "prefix: " << qbs::toJSLiteral(baseDir.relativeFilePath(subProject.dirPath) + QLatin1Char('/')) << '\n'; stream << indent << indent << "files: [\n"; for (const QString &fileName : qAsConst(subProject.fileNames)) stream << indent << indent << indent << qbs::toJSLiteral(fileName) << ",\n"; stream << indent << indent << "]\n"; stream << indent << "}\n"; for (const ProjectPtr &p : subProject.subProjects) addGroups(stream, baseDir, *p); } bool ProjectCreator::isSourceFile(const QString &fileName) { const auto isMatch = [fileName](const QRegExp &rex) { return rex.exactMatch(fileName); }; return !std::any_of(m_blackList.cbegin(), m_blackList.cend(), isMatch) && (m_whiteList.empty() || std::any_of(m_whiteList.cbegin(), m_whiteList.cend(), isMatch)); } ProjectCreator::ProductFlags ProjectCreator::getFlags(const ProjectCreator::Project &project) { ProductFlags flags; getFlagsFromFileNames(project, flags); if (flags.testFlag(IsApp) && flags.testFlag(NeedsQt)) return flags; if (!flags.testFlag(NeedsCpp)) return flags; getFlagsFromFileContents(project, flags); return flags; } void ProjectCreator::getFlagsFromFileNames(const ProjectCreator::Project &project, ProductFlags &flags) { for (const QString &fileName : qAsConst(project.fileNames)) { if (flags.testFlag(IsApp) && flags.testFlag(NeedsQt)) return; const QFileInfo fi(project.dirPath + QLatin1Char('/') + fileName); const QString &suffix = fi.suffix(); if (suffix == QLatin1String("qrc")) { flags |= NeedsQt; continue; } if (suffix == QLatin1String("cpp") || suffix == QLatin1String("c") || suffix == QLatin1String("m") || suffix == QLatin1String("mm")) { flags |= NeedsCpp; } if (flags.testFlag(NeedsCpp) && fi.completeBaseName() == QLatin1String("main")) flags |= IsApp; } for (const ProjectPtr &p : project.subProjects) { getFlagsFromFileNames(*p, flags); if (flags.testFlag(IsApp) && flags.testFlag(NeedsQt)) return; } } void ProjectCreator::getFlagsFromFileContents(const ProjectCreator::Project &project, ProductFlags &flags) { for (const QString &fileName : qAsConst(project.fileNames)) { QFile f (project.dirPath + QLatin1Char('/') + fileName); if (!f.open(QIODevice::ReadOnly)) { qDebug() << "Ignoring failure to read" << f.fileName(); continue; } while (!f.atEnd()) { const QByteArray &line = f.readLine(); if (line.contains("#include #include #include #include #include #include QT_BEGIN_NAMESPACE class QDir; class QTextStream; QT_END_NAMESPACE enum class ProjectStructure { Flat, Composite }; class ProjectCreator { public: void run(const QString &topLevelDir, ProjectStructure projectStructure, const QStringList &whiteList, const QStringList &blacklist); private: enum ProductFlag { IsApp = 1, NeedsCpp = 2, NeedsQt = 4 }; Q_DECLARE_FLAGS(ProductFlags, ProductFlag) struct Project; void setupProject(Project *project); void serializeProject(const Project &project); void addGroups(QTextStream &stream, const QDir &baseDir, const Project &subProject); bool isSourceFile(const QString &fileName); ProductFlags getFlags(const Project &project); void getFlagsFromFileNames(const Project &project, ProductFlags &flags); void getFlagsFromFileContents(const Project &project, ProductFlags &flags); using ProjectPtr = std::unique_ptr; struct Project { QString dirPath; QString dirName; QStringList fileNames; std::vector subProjects; }; Project m_topLevelProject; ProjectStructure m_projectStructure; QList m_whiteList; QList m_blackList; }; #endif // QBS_CREATEPROJECT_H qbs-src-1.13.1/src/app/qbs-create-project/qbs-create-project.pro000066400000000000000000000002241347155106100244250ustar00rootroot00000000000000include(../app.pri) TARGET = qbs-create-project HEADERS += \ createproject.h SOURCES += \ createproject.cpp \ create-project-main.cpp qbs-src-1.13.1/src/app/qbs-create-project/qbs-create-project.qbs000066400000000000000000000002441347155106100244140ustar00rootroot00000000000000import qbs QbsApp { name: "qbs-create-project" files: [ "createproject.cpp", "createproject.h", "create-project-main.cpp", ] } qbs-src-1.13.1/src/app/qbs-setup-android/000077500000000000000000000000001347155106100200625ustar00rootroot00000000000000qbs-src-1.13.1/src/app/qbs-setup-android/android-setup.cpp000066400000000000000000000237701347155106100233550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "android-setup.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using qbs::Internal::Tr; static QString qls(const char *s) { return QLatin1String(s); } static QStringList expectedArchs() { return {QStringLiteral("arm64"), QStringLiteral("armv7a"), QStringLiteral("x86"), QStringLiteral("x86_64")}; } static QString subProfileName(const QString &mainProfileName, const QString &arch) { return mainProfileName + QLatin1Char('-') + arch; } void setupSdk(qbs::Settings *settings, const QString &profileName, const QString &sdkDirPath) { if (!QDir(sdkDirPath).exists()) { throw ErrorInfo(Tr::tr("SDK directory '%1' does not exist.") .arg(QDir::toNativeSeparators(sdkDirPath))); } Profile profile(profileName, settings); profile.removeProfile(); if (!sdkDirPath.isEmpty()) profile.setValue(qls("Android.sdk.sdkDir"), QDir::cleanPath(sdkDirPath)); profile.setValue(qls("qbs.targetPlatform"), qls("android")); } static QString mapArch(const QString &androidName) { if (androidName == qls("arm64-v8a")) return qls("arm64"); if (androidName == qls("armeabi")) return qls("armv5te"); if (androidName == qls("armeabi-v7a")) return qls("armv7a"); return androidName; } struct QtAndroidInfo { bool isValid() const { return !arch.isEmpty(); } QString qmakePath; QString arch; QString platform; }; static QtAndroidInfo getInfoForQtDir(const QString &qtDir) { QtAndroidInfo info; info.qmakePath = qbs::Internal::HostOsInfo::appendExecutableSuffix(qtDir + qls("/bin/qmake")); if (!QFile::exists(info.qmakePath)) return info; QFile qdevicepri(qtDir + qls("/mkspecs/qdevice.pri")); if (!qdevicepri.open(QIODevice::ReadOnly)) return info; while (!qdevicepri.atEnd()) { const QByteArray line = qdevicepri.readLine().simplified(); const bool isArchLine = line.startsWith("DEFAULT_ANDROID_TARGET_ARCH"); const bool isPlatformLine = line.startsWith("DEFAULT_ANDROID_PLATFORM"); if (!isArchLine && !isPlatformLine) continue; const QList elems = line.split('='); if (elems.size() != 2) continue; const QString rhs = QString::fromLatin1(elems.at(1).trimmed()); if (isArchLine) info.arch = mapArch(rhs); else info.platform = rhs; } return info; } using QtInfoPerArch = QHash; static QtInfoPerArch getQtAndroidInfo(const QString &qtSdkDir) { QtInfoPerArch archs; if (qtSdkDir.isEmpty()) return archs; QStringList qtDirs(qtSdkDir); QDirIterator dit(qtSdkDir, QStringList() << QStringLiteral("android_*"), QDir::Dirs); while (dit.hasNext()) qtDirs << dit.next(); for (auto it = qtDirs.cbegin(); it != qtDirs.cend(); ++it) { const QtAndroidInfo info = getInfoForQtDir(*it); if (info.isValid()) archs.insert(info.arch, info); } return archs; } static QString maximumPlatform(const QString &platform1, const QString &platform2) { if (platform1.isEmpty()) return platform2; if (platform2.isEmpty()) return platform1; static const QString prefix = qls("android-"); const QString numberString1 = platform1.mid(prefix.size()); const QString numberString2 = platform2.mid(prefix.size()); bool ok; const int value1 = numberString1.toInt(&ok); if (!ok) { qWarning("Ignoring malformed Android platform string '%s'.", qPrintable(platform1)); return platform2; } const int value2 = numberString2.toInt(&ok); if (!ok) { qWarning("Ignoring malformed Android platform string '%s'.", qPrintable(platform2)); return platform1; } return prefix + QString::number(std::max(value1, value2)); } static QString getToolchainType(const QString &ndkDirPath) { QFile sourceProperties(ndkDirPath + qls("/source.properties")); if (!sourceProperties.open(QIODevice::ReadOnly)) return QStringLiteral("gcc"); // <= r10 while (!sourceProperties.atEnd()) { const QByteArray curLine = sourceProperties.readLine().simplified(); static const QByteArray prefix = "Pkg.Revision = "; if (!curLine.startsWith(prefix)) continue; qbs::Version ndkVersion = qbs::Version::fromString( QString::fromLatin1(curLine.mid(prefix.size()))); if (!ndkVersion.isValid()) { qWarning("Unexpected format of NDK revision string in '%s'", qPrintable(sourceProperties.fileName())); return QStringLiteral("clang"); } return qls(ndkVersion.majorVersion() >= 18 ? "clang" : "gcc"); } qWarning("No revision entry found in '%s'", qPrintable(sourceProperties.fileName())); return QStringLiteral("clang"); } static void setupNdk(qbs::Settings *settings, const QString &profileName, const QString &ndkDirPath, const QString &qtSdkDirPath) { if (!QDir(ndkDirPath).exists()) { throw ErrorInfo(Tr::tr("NDK directory '%1' does not exist.") .arg(QDir::toNativeSeparators(ndkDirPath))); } Profile mainProfile(profileName, settings); if (!ndkDirPath.isEmpty()) { mainProfile.setValue(qls("Android.ndk.ndkDir"), QDir::cleanPath(ndkDirPath)); mainProfile.setValue(qls("Android.sdk.ndkDir"), QDir::cleanPath(ndkDirPath)); } mainProfile.setValue(qls("qbs.toolchainType"), getToolchainType(ndkDirPath)); const QStringList archs = expectedArchs(); const QtInfoPerArch infoPerArch = getQtAndroidInfo(qtSdkDirPath); const QStringList archsForProfile = infoPerArch.empty() ? archs : QStringList(infoPerArch.keys()); if (archsForProfile.size() == 1) mainProfile.setValue(qls("qbs.architecture"), archsForProfile.front()); else mainProfile.setValue(qls("qbs.architectures"), archsForProfile); QStringList qmakeFilePaths; QString platform; for (const QString &arch : archs) { const QtAndroidInfo qtAndroidInfo = infoPerArch.value(arch); if (!qtAndroidInfo.isValid()) continue; const QString subProName = subProfileName(profileName, arch); const QString setupQtPath = qApp->applicationDirPath() + qls("/qbs-setup-qt"); QProcess setupQt; setupQt.start(setupQtPath, QStringList({ qtAndroidInfo.qmakePath, subProName })); if (!setupQt.waitForStarted()) { throw ErrorInfo(Tr::tr("Setting up Qt profile failed: '%1' " "could not be started.").arg(setupQtPath)); } if (!setupQt.waitForFinished()) { throw ErrorInfo(Tr::tr("Setting up Qt profile failed: Error running '%1' (%2)") .arg(setupQtPath, setupQt.errorString())); } if (setupQt.exitCode() != 0) { throw ErrorInfo(Tr::tr("Setting up Qt profile failed: '%1' returned with " "exit code %2.").arg(setupQtPath).arg(setupQt.exitCode())); } settings->sync(); qbs::Internal::TemporaryProfile p(subProName, settings); qmakeFilePaths << p.p.value(qls("moduleProviders.Qt.qmakeFilePaths")).toStringList(); platform = maximumPlatform(platform, qtAndroidInfo.platform); } if (!qmakeFilePaths.empty()) mainProfile.setValue(qls("moduleProviders.Qt.qmakeFilePaths"), qmakeFilePaths); if (!platform.isEmpty()) mainProfile.setValue(qls("Android.ndk.platform"), platform); } void setupAndroid(Settings *settings, const QString &profileName, const QString &sdkDirPath, const QString &ndkDirPath, const QString &qtSdkDirPath) { setupSdk(settings, profileName, sdkDirPath); setupNdk(settings, profileName, ndkDirPath, qtSdkDirPath); } qbs-src-1.13.1/src/app/qbs-setup-android/android-setup.h000066400000000000000000000043501347155106100230130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUP_ANDROID_SDKSETUP_H #define QBS_SETUP_ANDROID_SDKSETUP_H #include namespace qbs { class Settings; } QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE void setupAndroid(qbs::Settings *settings, const QString &profileName, const QString &sdkDirPath, const QString &ndkDirPath, const QString &qtSdkDirPath); #endif // Include guard. qbs-src-1.13.1/src/app/qbs-setup-android/commandlineparser.cpp000066400000000000000000000130651347155106100242760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include CommandLineParser::CommandLineParser() { } using qbs::Internal::Tr; static QString helpOptionShort() { return QStringLiteral("-h"); } static QString helpOptionLong() { return QStringLiteral("--help"); } static QString settingsDirOption() { return QStringLiteral("--settings-dir"); } static QString sdkDirOption() { return QStringLiteral("--sdk-dir"); } static QString ndkDirOption() { return QStringLiteral("--ndk-dir"); } static QString qtSdkDirOption() { return QStringLiteral("--qt-dir"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.empty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_sdkDir.clear(); m_ndkDir.clear(); m_profileName.clear(); m_settingsDir.clear(); if (m_commandLine.empty()) throwError(Tr::tr("No command-line arguments provided.")); while (!m_commandLine.empty()) { const QString arg = m_commandLine.front(); if (!arg.startsWith(QLatin1Char('-'))) break; m_commandLine.removeFirst(); if (arg == helpOptionShort() || arg == helpOptionLong()) m_helpRequested = true; else if (arg == settingsDirOption()) assignOptionArgument(settingsDirOption(), m_settingsDir); else if (arg == sdkDirOption()) assignOptionArgument(sdkDirOption(), m_sdkDir); else if (arg == ndkDirOption()) assignOptionArgument(ndkDirOption(), m_ndkDir); else if (arg == qtSdkDirOption()) assignOptionArgument(arg, m_qtSdkDir); else throwError(Tr::tr("Unknown option '%1'.").arg(arg)); } if (m_helpRequested) { if (!m_commandLine.empty()) complainAboutExtraArguments(); return; } switch (m_commandLine.size()) { case 0: throwError(Tr::tr("No profile name supplied.")); case 1: m_profileName = m_commandLine.takeFirst(); m_profileName.replace(QLatin1Char('.'), QLatin1Char('-')); break; default: complainAboutExtraArguments(); } } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool creates qbs profiles from Android SDK and NDK installations.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] [%3 ] [%4 ] [%5 ] " "\n") .arg(m_command, settingsDirOption(), ndkDirOption(), sdkDirOption(), qtSdkDirOption()); s += Tr::tr(" %1 %2|%3\n").arg(m_command, helpOptionShort(), helpOptionLong()); s += Tr::tr("If an NDK path is given, the profile will be suitable for use with Android " "projects that contain native C/C++ code.\n"); s += Tr::tr("If a Qt path is also given, the profile will be suitable for developing " "Qt applications for Android.\n"); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-1.13.1/src/app/qbs-setup-android/commandlineparser.h000066400000000000000000000055331347155106100237440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUP_ANDROID_COMMANDLINEPARSER_H #define QBS_SETUP_ANDROID_COMMANDLINEPARSER_H #include class CommandLineParser { public: CommandLineParser(); void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } QString sdkDir() const { return m_sdkDir; } QString ndkDir() const { return m_ndkDir; } QString qtSdkDir() const { return m_qtSdkDir; } QString profileName() const { return m_profileName; } QString settingsDir() const { return m_settingsDir; } QString usageString() const; private: [[noreturn]] void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); [[noreturn]] void complainAboutExtraArguments(); bool m_helpRequested; QString m_sdkDir; QString m_ndkDir; QString m_qtSdkDir; QString m_profileName; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Include guard. qbs-src-1.13.1/src/app/qbs-setup-android/main.cpp000066400000000000000000000053531347155106100215200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include "android-setup.h" #include #include #include #include #include #include int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); CommandLineParser clParser; try { clParser.parse(app.arguments()); if (clParser.helpRequested()) { std::cout << qPrintable(clParser.usageString()) << std::endl; return EXIT_SUCCESS; } qbs::Settings settings(clParser.settingsDir()); setupAndroid(&settings, clParser.profileName(), clParser.sdkDir(), clParser.ndkDir(), clParser.qtSdkDir()); } catch (const qbs::ErrorInfo &e) { std::cerr << qPrintable(qbs::Internal::Tr::tr("Error: %1").arg(e.toString())) << std::endl; return EXIT_FAILURE; } } qbs-src-1.13.1/src/app/qbs-setup-android/qbs-setup-android.exe.manifest000066400000000000000000000007331347155106100257360ustar00rootroot00000000000000 qbs-src-1.13.1/src/app/qbs-setup-android/qbs-setup-android.pro000066400000000000000000000002731347155106100241470ustar00rootroot00000000000000include(../app.pri) TARGET = qbs-setup-android SOURCES += \ android-setup.cpp \ commandlineparser.cpp \ main.cpp HEADERS += \ android-setup.h \ commandlineparser.h qbs-src-1.13.1/src/app/qbs-setup-android/qbs-setup-android.qbs000066400000000000000000000006101347155106100241270ustar00rootroot00000000000000import qbs QbsApp { name: "qbs-setup-android" files: [ "android-setup.cpp", "android-setup.h", "commandlineparser.cpp", "commandlineparser.h", "main.cpp", ] Group { name: "MinGW specific files" condition: qbs.toolchain.contains("mingw") files: ["qbs-setup-android.exe.manifest", "qbs-setup-android.rc"] } } qbs-src-1.13.1/src/app/qbs-setup-android/qbs-setup-android.rc000066400000000000000000000002251347155106100237500ustar00rootroot00000000000000#define RT_MANIFEST 24 #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "qbs-setup-android.exe.manifest" qbs-src-1.13.1/src/app/qbs-setup-qt/000077500000000000000000000000001347155106100170665ustar00rootroot00000000000000qbs-src-1.13.1/src/app/qbs-setup-qt/commandlineparser.cpp000066400000000000000000000124161347155106100233010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include using qbs::Internal::Tr; static QString helpOptionShort() { return QStringLiteral("-h"); } static QString helpOptionLong() { return QStringLiteral("--help"); } static QString detectOption() { return QStringLiteral("--detect"); } static QString settingsDirOption() { return QStringLiteral("--settings-dir"); } static QString systemOption() { return QStringLiteral("--system"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.empty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_autoDetectionMode = false; m_qmakePath.clear(); m_profileName.clear(); m_settingsDir.clear(); if (m_commandLine.empty()) throwError(Tr::tr("No command-line arguments provided.")); while (!m_commandLine.empty()) { const QString arg = m_commandLine.front(); if (!arg.startsWith(QLatin1Char('-'))) break; m_commandLine.removeFirst(); if (arg == helpOptionShort() || arg == helpOptionLong()) m_helpRequested = true; else if (arg == detectOption()) m_autoDetectionMode = true; else if (arg == systemOption()) m_settingsScope = qbs::Settings::SystemScope; else if (arg == settingsDirOption()) assignOptionArgument(settingsDirOption(), m_settingsDir); } if (m_helpRequested || m_autoDetectionMode) { if (!m_commandLine.empty()) complainAboutExtraArguments(); return; } switch (m_commandLine.size()) { case 0: case 1: throwError(Tr::tr("Not enough command-line arguments provided.")); case 2: m_qmakePath = m_commandLine.at(0); m_profileName = m_commandLine.at(1); break; default: complainAboutExtraArguments(); } } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool creates qbs profiles from Qt versions.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] [%4] %3\n") .arg(m_command, settingsDirOption(), detectOption(), systemOption()); s += Tr::tr(" %1 [%2 ] [%4] \n") .arg(m_command, settingsDirOption(), systemOption()); s += Tr::tr(" %1 %2|%3\n").arg(m_command, helpOptionShort(), helpOptionLong()); s += Tr::tr("The first form tries to auto-detect all known Qt versions, looking them up " "via the PATH environment variable.\n"); s += Tr::tr("The second form creates one profile for one Qt version."); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-1.13.1/src/app/qbs-setup-qt/commandlineparser.h000066400000000000000000000057111347155106100227460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #define QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #include #include class CommandLineParser { public: void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } bool autoDetectionMode() const { return m_autoDetectionMode; } QString qmakePath() const { return m_qmakePath; } QString profileName() const { return m_profileName; } QString settingsDir() const { return m_settingsDir; } qbs::Settings::Scope settingsScope() const { return m_settingsScope; } QString usageString() const; private: [[noreturn]] void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); [[noreturn]] void complainAboutExtraArguments(); bool m_helpRequested; bool m_autoDetectionMode; qbs::Settings::Scope m_settingsScope = qbs::Settings::UserScope; QString m_qmakePath; QString m_profileName; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Include guard qbs-src-1.13.1/src/app/qbs-setup-qt/main.cpp000066400000000000000000000107151347155106100205220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "setupqt.h" #include "commandlineparser.h" #include #include #include #include #include #include #include using namespace qbs; using Internal::Tr; int main(int argc, char *argv[]) { QCoreApplication application(argc, argv); try { CommandLineParser clParser; clParser.parse(application.arguments()); if (clParser.helpRequested()) { std::cout << qPrintable(clParser.usageString()) << std::endl; return EXIT_SUCCESS; } Settings settings(clParser.settingsDir()); settings.setScopeForWriting(clParser.settingsScope()); if (clParser.autoDetectionMode()) { // search all Qt's in path and dump their settings const std::vector qtEnvironments = SetupQt::fetchEnvironments(); if (qtEnvironments.empty()) { std::cout << qPrintable(Tr::tr("No Qt installations detected. " "No profiles created.")) << std::endl; } for (const QtEnvironment &qtEnvironment : qtEnvironments) { QString profileName = QLatin1String("qt-") + qtEnvironment.qtVersion.toString(); if (SetupQt::checkIfMoreThanOneQtWithTheSameVersion(qtEnvironment.qtVersion, qtEnvironments)) { QStringList prefixPathParts = QFileInfo(qtEnvironment.qmakeFilePath).path() .split(QLatin1Char('/'), QString::SkipEmptyParts); if (!prefixPathParts.empty()) profileName += QLatin1String("-") + prefixPathParts.last(); } SetupQt::saveToQbsSettings(profileName, qtEnvironment, &settings); } return EXIT_SUCCESS; } if (!SetupQt::isQMakePathValid(clParser.qmakePath())) { std::cerr << qPrintable(Tr::tr("'%1' does not seem to be a qmake executable.") .arg(clParser.qmakePath())) << std::endl; return EXIT_FAILURE; } const QtEnvironment qtEnvironment = SetupQt::fetchEnvironment(clParser.qmakePath()); QString profileName = clParser.profileName(); profileName.replace(QLatin1Char('.'), QLatin1Char('-')); SetupQt::saveToQbsSettings(profileName, qtEnvironment, &settings); return EXIT_SUCCESS; } catch (const ErrorInfo &e) { std::cerr << qPrintable(e.toString()) << std::endl; return EXIT_FAILURE; } } qbs-src-1.13.1/src/app/qbs-setup-qt/qbs-setup-qt.exe.manifest000066400000000000000000000007261347155106100237500ustar00rootroot00000000000000 qbs-src-1.13.1/src/app/qbs-setup-qt/qbs-setup-qt.pro000066400000000000000000000003231347155106100221530ustar00rootroot00000000000000include(../app.pri) TARGET = qbs-setup-qt SOURCES += \ commandlineparser.cpp \ main.cpp \ setupqt.cpp HEADERS += \ commandlineparser.h \ setupqt.h mingw { RC_FILE = qbs-setup-qt.rc } qbs-src-1.13.1/src/app/qbs-setup-qt/qbs-setup-qt.qbs000066400000000000000000000005611347155106100221440ustar00rootroot00000000000000import qbs 1.0 QbsApp { name: "qbs-setup-qt" files: [ "commandlineparser.cpp", "commandlineparser.h", "main.cpp", "setupqt.cpp", "setupqt.h" ] Group { name: "MinGW specific files" condition: qbs.toolchain.contains("mingw") files: ["qbs-setup-qt.exe.manifest", "qbs-setup-qt.rc"] } } qbs-src-1.13.1/src/app/qbs-setup-qt/qbs-setup-qt.rc000066400000000000000000000002201347155106100217530ustar00rootroot00000000000000#define RT_MANIFEST 24 #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "qbs-setup-qt.exe.manifest" qbs-src-1.13.1/src/app/qbs-setup-qt/setupqt.cpp000066400000000000000000000343561347155106100213120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "setupqt.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using Internal::none_of; using Internal::contains; using Internal::HostOsInfo; using Internal::Tr; static QStringList qmakeExecutableNames() { const QString baseName = HostOsInfo::appendExecutableSuffix(QStringLiteral("qmake")); QStringList lst(baseName); if (HostOsInfo::isLinuxHost()) { // Some distributions ship binaries called qmake-qt5 or qmake-qt4. lst << baseName + QLatin1String("-qt5") << baseName + QLatin1String("-qt4"); } return lst; } static QStringList collectQmakePaths() { const QStringList qmakeExeNames = qmakeExecutableNames(); QStringList qmakePaths; QByteArray environmentPath = qgetenv("PATH"); const QList environmentPaths = environmentPath.split(HostOsInfo::pathListSeparator().toLatin1()); for (const QByteArray &path : environmentPaths) { for (const QString &qmakeExecutableName : qmakeExeNames) { QFileInfo pathFileInfo(QDir(QLatin1String(path)), qmakeExecutableName); if (pathFileInfo.exists()) { QString qmakePath = pathFileInfo.absoluteFilePath(); if (!qmakePaths.contains(qmakePath)) qmakePaths.push_back(qmakePath); } } } return qmakePaths; } bool SetupQt::isQMakePathValid(const QString &qmakePath) { QFileInfo qmakeFileInfo(qmakePath); return qmakeFileInfo.exists() && qmakeFileInfo.isFile() && qmakeFileInfo.isExecutable(); } std::vector SetupQt::fetchEnvironments() { std::vector qtEnvironments; const auto qmakePaths = collectQmakePaths(); for (const QString &qmakePath : qmakePaths) { const QtEnvironment env = fetchEnvironment(qmakePath); if (none_of(qtEnvironments, [&env](const QtEnvironment &otherEnv) { return env.qmakeFilePath == otherEnv.qmakeFilePath; })) { qtEnvironments.push_back(env); } } return qtEnvironments; } // These functions work only for Qt from installer. static QStringList qbsToolchainFromDirName(const QString &dir) { if (dir.startsWith(QLatin1String("msvc"))) return {QStringLiteral("msvc")}; if (dir.startsWith(QLatin1String("mingw"))) return {QStringLiteral("mingw"), QStringLiteral("gcc")}; if (dir.startsWith(QLatin1String("clang"))) return {QStringLiteral("clang"), QStringLiteral("llvm"), QStringLiteral("gcc")}; if (dir.startsWith(QLatin1String("gcc"))) return {QStringLiteral("gcc")}; return {}; } static Version msvcVersionFromDirName(const QString &dir) { static const std::regex regexp("^msvc(\\d\\d\\d\\d).*$"); std::smatch match; const std::string dirString = dir.toStdString(); if (!std::regex_match(dirString, match, regexp)) return Version{}; QMap mapping{ std::make_pair("2005", "14"), std::make_pair("2008", "15"), std::make_pair("2010", "16"), std::make_pair("2012", "17"), std::make_pair("2013", "18"), std::make_pair("2015", "19"), std::make_pair("2017", "19.1") }; return Version::fromString(QString::fromStdString(mapping.value(match[1].str()))); } static QString archFromDirName(const QString &dir) { static const std::regex regexp("^[^_]+_(.*).*$"); std::smatch match; const std::string dirString = dir.toStdString(); if (!std::regex_match(dirString, match, regexp)) return {}; const QString arch = QString::fromStdString(match[1]); if (arch == QLatin1String("32")) return QStringLiteral("x86"); if (arch == QLatin1String("64")) return QStringLiteral("x86_64"); if (arch.contains(QLatin1String("arm64"))) return QStringLiteral("arm64"); return arch; } static QString platformFromDirName(const QString &dir) { if (dir.startsWith(QLatin1String("android"))) return QStringLiteral("android"); if (dir == QLatin1String("Boot2Qt")) return QStringLiteral("linux"); return QString::fromStdString(HostOsInfo::hostOSIdentifier()); } QtEnvironment SetupQt::fetchEnvironment(const QString &qmakePath) { QtEnvironment env; env.qmakeFilePath = qmakePath; QDir qtDir = QFileInfo(qmakePath).dir(); if (qtDir.dirName() == QLatin1String("bin")) { qtDir.cdUp(); env.qbsToolchain = qbsToolchainFromDirName(qtDir.dirName()); env.msvcVersion = msvcVersionFromDirName(qtDir.dirName()); env.architecture = archFromDirName(qtDir.dirName()); if (env.msvcVersion.isValid() && env.architecture.isEmpty()) env.architecture = QStringLiteral("x86"); env.targetPlatform = platformFromDirName(qtDir.dirName()); qtDir.cdUp(); env.qtVersion = Version::fromString(qtDir.dirName()); } return env; } static bool isToolchainProfile(const Profile &profile) { const auto actual = Internal::Set::fromList( profile.allKeys(Profile::KeySelectionRecursive)); Internal::Set expected = Internal::Set { QStringLiteral("qbs.toolchain") }; if (HostOsInfo::isMacosHost()) expected.insert(QStringLiteral("qbs.targetPlatform")); // match only Xcode profiles return Internal::Set(actual).unite(expected) == actual; } static bool isQtProfile(const Profile &profile) { if (!profile.value(QStringLiteral("moduleProviders.Qt.qmakeFilePaths")).toStringList() .empty()) { return true; } // For Profiles created with setup-qt < 5.13. const QStringList searchPaths = profile.value(QStringLiteral("preferences.qbsSearchPaths")).toStringList(); return std::any_of(searchPaths.cbegin(), searchPaths.cend(), [] (const QString &path) { return QFileInfo(path + QStringLiteral("/modules/Qt")).isDir(); }); } template bool areProfilePropertiesIncompatible(const T &set1, const T &set2) { // Two objects are only considered incompatible if they are both non empty and compare inequal // This logic is used for comparing target OS, toolchain lists, and architectures return set1.size() > 0 && set2.size() > 0 && set1 != set2; } enum Match { MatchFull, MatchPartial, MatchNone }; static Match compatibility(const QtEnvironment &env, const Profile &toolchainProfile) { Match match = MatchFull; const auto toolchainNames = Internal::Set::fromList( toolchainProfile.value(QStringLiteral("qbs.toolchain")).toStringList()); const auto qtToolchainNames = Internal::Set::fromList(env.qbsToolchain); if (areProfilePropertiesIncompatible(toolchainNames, qtToolchainNames)) { auto intersection = toolchainNames; intersection.intersect(qtToolchainNames); if (!intersection.empty()) match = MatchPartial; else return MatchNone; } const auto targetPlatform = toolchainProfile.value( QStringLiteral("qbs.targetPlatform")).toString(); if (!targetPlatform.isEmpty() && targetPlatform != env.targetPlatform) return MatchNone; const QString toolchainArchitecture = toolchainProfile.value(QStringLiteral("qbs.architecture")) .toString(); if (areProfilePropertiesIncompatible(canonicalArchitecture(env.architecture), canonicalArchitecture(toolchainArchitecture))) return MatchNone; if (env.msvcVersion.isValid()) { // We want to know for sure that MSVC compiler versions match, // because it's especially important for this toolchain const Version compilerVersion = Version::fromString( toolchainProfile.value(QStringLiteral("cpp.compilerVersion")).toString()); static const Version vs2017Version{19, 1}; if (env.msvcVersion >= vs2017Version) { if (env.msvcVersion.majorVersion() != compilerVersion.majorVersion() || compilerVersion < vs2017Version) { return MatchNone; } } else if (env.msvcVersion.majorVersion() != compilerVersion.majorVersion() || env.msvcVersion.minorVersion() != compilerVersion.minorVersion()) { return MatchNone; } } return match; } QString profileNameWithoutHostArch(const QString &profileName) { QString result; int i = profileName.indexOf(QLatin1Char('-')); if (i == -1) return result; ++i; int j = profileName.indexOf(QLatin1Char('_'), i); if (j == -1) return result; result = profileName.mid(0, i) + profileName.mid(j + 1); return result; } // "Compressing" MSVC profiles means that if MSVC2017-x64 and MSVC2017-x86_x64 fully match, // then we drop the crosscompiling toolchain MSVC2017-x86_x64. static void compressMsvcProfiles(QStringList &profiles) { auto it = std::remove_if(profiles.begin(), profiles.end(), [&profiles] (const QString &profileName) { int idx = profileName.indexOf(QLatin1Char('_')); if (idx == -1) return false; return contains(profiles, profileNameWithoutHostArch(profileName)); }); if (it != profiles.end()) profiles.erase(it, profiles.end()); } void SetupQt::saveToQbsSettings(const QString &qtVersionName, const QtEnvironment &qtEnvironment, Settings *settings) { const QString cleanQtVersionName = Profile::cleanName(qtVersionName); QString msg = QCoreApplication::translate("SetupQt", "Creating profile '%1'.") .arg(cleanQtVersionName); printf("%s\n", qPrintable(msg)); Profile profile(cleanQtVersionName, settings); profile.removeProfile(); profile.setValue(QStringLiteral("moduleProviders.Qt.qmakeFilePaths"), QStringList(qtEnvironment.qmakeFilePath)); if (!profile.baseProfile().isEmpty()) return; if (isToolchainProfile(profile)) return; QStringList fullMatches; QStringList partialMatches; const auto profileNames = settings->profiles(); for (const QString &profileName : profileNames) { const Profile otherProfile(profileName, settings); if (profileName == profile.name() || !isToolchainProfile(otherProfile) || isQtProfile(otherProfile)) continue; switch (compatibility(qtEnvironment, otherProfile)) { case MatchFull: fullMatches << profileName; break; case MatchPartial: partialMatches << profileName; break; default: break; } } if (fullMatches.size() > 1) compressMsvcProfiles(fullMatches); QString bestMatch; if (fullMatches.size() == 1) bestMatch = fullMatches.front(); else if (fullMatches.empty() && partialMatches.size() == 1) bestMatch = partialMatches.front(); if (bestMatch.isEmpty()) { QString message = Tr::tr("You may want to set up toolchain information " "for the generated Qt profile. "); if (!fullMatches.empty() || !partialMatches.empty()) { message += Tr::tr("Consider setting one of these profiles as this profile's base " "profile: %1.").arg((fullMatches + partialMatches) .join(QLatin1String(", "))); } qbsInfo() << message; } else { profile.setBaseProfile(bestMatch); qbsInfo() << Tr::tr("Setting profile '%1' as the base profile for this profile.") .arg(bestMatch); } } bool SetupQt::checkIfMoreThanOneQtWithTheSameVersion(const Version &qtVersion, const std::vector &qtEnvironments) { bool foundOneVersion = false; for (const QtEnvironment &qtEnvironment : qtEnvironments) { if (qtEnvironment.qtVersion == qtVersion) { if (foundOneVersion) return true; foundOneVersion = true; } } return false; } } // namespace qbs qbs-src-1.13.1/src/app/qbs-setup-qt/setupqt.h000066400000000000000000000055751347155106100207600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPQT_H #define QBS_SETUPQT_H #include #include #include #include #include namespace qbs { class Settings; class QtEnvironment { public: QString qmakeFilePath; QStringList qbsToolchain; QString architecture; QString targetPlatform; Version qtVersion; Version msvcVersion; }; class SetupQt { Q_DECLARE_TR_FUNCTIONS(SetupQt) public: static bool isQMakePathValid(const QString &qmakePath); static std::vector fetchEnvironments(); static QtEnvironment fetchEnvironment(const QString &qmakePath); static bool checkIfMoreThanOneQtWithTheSameVersion(const Version &qtVersion, const std::vector &qtEnvironments); static void saveToQbsSettings(const QString &qtVersionName, const QtEnvironment &qtEnvironment, Settings *settings); }; } // namespace qbs #endif // QBS_SETUPQT_H qbs-src-1.13.1/src/app/qbs-setup-toolchains/000077500000000000000000000000001347155106100206055ustar00rootroot00000000000000qbs-src-1.13.1/src/app/qbs-setup-toolchains/commandlineparser.cpp000066400000000000000000000134211347155106100250150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include using qbs::Internal::Tr; static QString helpOptionShort() { return QStringLiteral("-h"); } static QString helpOptionLong() { return QStringLiteral("--help"); } static QString detectOption() { return QStringLiteral("--detect"); } static QString typeOption() { return QStringLiteral("--type"); } static QString settingsDirOption() { return QStringLiteral("--settings-dir"); } static QString systemOption() { return QStringLiteral("--system"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.empty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_autoDetectionMode = false; m_compilerPath.clear(); m_toolchainType.clear(); m_profileName.clear(); m_settingsDir.clear(); if (m_commandLine.empty()) throwError(Tr::tr("No command-line arguments provided.")); while (!m_commandLine.empty()) { const QString arg = m_commandLine.front(); if (!arg.startsWith(QLatin1Char('-'))) break; m_commandLine.removeFirst(); if (arg == helpOptionShort() || arg == helpOptionLong()) m_helpRequested = true; else if (arg == detectOption()) m_autoDetectionMode = true; else if (arg == systemOption()) m_settingsScope = qbs::Settings::SystemScope; else if (arg == typeOption()) assignOptionArgument(typeOption(), m_toolchainType); else if (arg == settingsDirOption()) assignOptionArgument(settingsDirOption(), m_settingsDir); } if (m_helpRequested || m_autoDetectionMode) { if (!m_commandLine.empty()) complainAboutExtraArguments(); return; } switch (m_commandLine.size()) { case 0: case 1: throwError(Tr::tr("Not enough command-line arguments provided.")); case 2: m_compilerPath = m_commandLine.at(0); m_profileName = m_commandLine.at(1); m_profileName.replace(QLatin1Char('.'), QLatin1Char('-')); break; default: complainAboutExtraArguments(); } } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool creates qbs profiles from toolchains.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] [%4] %3\n") .arg(m_command, settingsDirOption(), detectOption(), systemOption()); s += Tr::tr(" %1 [%3 ] [%4] [%2 ] " " \n") .arg(m_command, typeOption(), settingsDirOption(), systemOption()); s += Tr::tr(" %1 %2|%3\n").arg(m_command, helpOptionShort(), helpOptionLong()); s += Tr::tr("The first form tries to auto-detect all known toolchains, looking them up " "via the PATH environment variable.\n"); s += Tr::tr("The second form creates one profile for one toolchain. It will attempt " "to find out the toolchain type automatically.\nIn case the compiler has " "an unusual file name, you may need to provide the '--type' option."); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-1.13.1/src/app/qbs-setup-toolchains/commandlineparser.h000066400000000000000000000060551347155106100244670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #define QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #include #include class CommandLineParser { public: void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } bool autoDetectionMode() const { return m_autoDetectionMode; } QString compilerPath() const { return m_compilerPath; } QString toolchainType() const { return m_toolchainType; } QString profileName() const { return m_profileName; } QString settingsDir() const { return m_settingsDir; } qbs::Settings::Scope settingsScope() const { return m_settingsScope; } QString usageString() const; private: [[noreturn]] void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); [[noreturn]] void complainAboutExtraArguments(); bool m_helpRequested; bool m_autoDetectionMode; qbs::Settings::Scope m_settingsScope = qbs::Settings::UserScope; QString m_compilerPath; QString m_toolchainType; QString m_profileName; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Include guard qbs-src-1.13.1/src/app/qbs-setup-toolchains/main.cpp000066400000000000000000000057501347155106100222440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include "probe.h" #include #include #include #include #include #include using qbs::Internal::Tr; using qbs::Settings; static void printUsage(const QString &usageString) { std::cout << qPrintable(usageString) << std::endl; } int main(int argc, char **argv) { QCoreApplication app(argc, argv); CommandLineParser clParser; try { clParser.parse(app.arguments()); if (clParser.helpRequested()) { printUsage(clParser.usageString()); return EXIT_SUCCESS; } Settings settings(clParser.settingsDir()); settings.setScopeForWriting(clParser.settingsScope()); if (clParser.autoDetectionMode()) { probe(&settings); return EXIT_SUCCESS; } createProfile(clParser.profileName(), clParser.toolchainType(), clParser.compilerPath(), &settings); } catch (const qbs::ErrorInfo &e) { std::cerr << qPrintable(e.toString()) << std::endl; return EXIT_FAILURE; } } qbs-src-1.13.1/src/app/qbs-setup-toolchains/msvcprobe.cpp000066400000000000000000000432741347155106100233230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "msvcprobe.h" #include "probe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using namespace qbs::Internal; using Internal::Tr; QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(WinSDK, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(MSVC, Q_MOVABLE_TYPE); QT_END_NAMESPACE // Not necessary but helps setup-qt automatically associate base profiles static void setQtHelperProperties(Profile &p, const MSVC *msvc) { QString targetArch = msvc->architecture.split(QLatin1Char('_')).last(); if (targetArch.isEmpty()) targetArch = QStringLiteral("x86"); if (targetArch == QStringLiteral("arm")) targetArch = QStringLiteral("armv7"); p.setValue(QStringLiteral("qbs.architecture"), canonicalArchitecture(targetArch)); p.setValue(QStringLiteral("cpp.compilerVersion"), msvc->compilerVersion.toString()); } static void addMSVCPlatform(Settings *settings, QList &profiles, QString name, MSVC *msvc) { qbsInfo() << Tr::tr("Setting up profile '%1'.").arg(name); Profile p(name, settings); p.removeProfile(); p.setValue(QStringLiteral("qbs.targetPlatform"), QStringLiteral("windows")); p.setValue(QStringLiteral("qbs.toolchain"), QStringList(QStringLiteral("msvc"))); p.setValue(QStringLiteral("cpp.toolchainInstallPath"), msvc->binPath); setQtHelperProperties(p, msvc); profiles.push_back(p); } struct MSVCArchInfo { QString arch; QString binPath; }; static std::vector findSupportedArchitectures(const MSVC &msvc) { std::vector result; auto addResult = [&result](const MSVCArchInfo &ai) { if (QFile::exists(ai.binPath + QLatin1String("/cl.exe"))) result.push_back(ai); }; if (msvc.internalVsVersion.majorVersion() < 15) { static const QStringList knownArchitectures = QStringList() << QStringLiteral("x86") << QStringLiteral("amd64_x86") << QStringLiteral("amd64") << QStringLiteral("x86_amd64") << QStringLiteral("ia64") << QStringLiteral("x86_ia64") << QStringLiteral("x86_arm") << QStringLiteral("amd64_arm"); for (const QString &knownArchitecture : knownArchitectures) { MSVCArchInfo ai; ai.arch = knownArchitecture; ai.binPath = msvc.binPathForArchitecture(knownArchitecture); addResult(ai); } } else { QDir vcInstallDir(msvc.vcInstallPath); const auto hostArchs = vcInstallDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); for (const QString &hostArch : hostArchs) { QDir subdir = vcInstallDir; if (!subdir.cd(hostArch)) continue; const QString shortHostArch = hostArch.mid(4).toLower(); const auto archs = subdir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); for (const QString &arch : archs) { MSVCArchInfo ai; ai.binPath = subdir.absoluteFilePath(arch); if (shortHostArch == arch) ai.arch = arch; else ai.arch = shortHostArch + QLatin1Char('_') + arch; addResult(ai); } } } return result; } static QString wow6432Key() { #ifdef Q_OS_WIN64 return QStringLiteral("\\Wow6432Node"); #else return {}; #endif } struct MSVCInstallInfo { QString version; QString installDir; }; static QString vswhereFilePath() { static const std::vector envVarCandidates{"ProgramFiles", "ProgramFiles(x86)"}; for (const char * const envVar : envVarCandidates) { const QString value = QDir::fromNativeSeparators(QString::fromLocal8Bit(qgetenv(envVar))); const QString cmd = value + QStringLiteral("/Microsoft Visual Studio/Installer/vswhere.exe"); if (QFileInfo(cmd).exists()) return cmd; } return {}; } enum class ProductType { VisualStudio, BuildTools }; static std::vector retrieveInstancesFromVSWhere(ProductType productType) { std::vector result; const QString cmd = vswhereFilePath(); if (cmd.isEmpty()) return result; QProcess vsWhere; QStringList args = productType == ProductType::VisualStudio ? QStringList({QStringLiteral("-all"), QStringLiteral("-legacy"), QStringLiteral("-prerelease")}) : QStringList({QStringLiteral("-products"), QStringLiteral("Microsoft.VisualStudio.Product.BuildTools")}); args << QStringLiteral("-format") << QStringLiteral("json") << QStringLiteral("-utf8"); vsWhere.start(cmd, args); if (!vsWhere.waitForStarted(-1)) return result; if (!vsWhere.waitForFinished(-1)) { qbsWarning() << Tr::tr("The vswhere tool failed to run: %1").arg(vsWhere.errorString()); return result; } if (vsWhere.exitCode() != 0) { qbsWarning() << Tr::tr("The vswhere tool failed to run: %1") .arg(QString::fromLocal8Bit(vsWhere.readAllStandardError())); return result; } QJsonParseError parseError; QJsonDocument jsonOutput = QJsonDocument::fromJson(vsWhere.readAllStandardOutput(), &parseError); if (parseError.error != QJsonParseError::NoError) { qbsWarning() << Tr::tr("The vswhere tool produced invalid JSON output: %1") .arg(parseError.errorString()); return result; } for (const QJsonValue &v : jsonOutput.array()) { const QJsonObject o = v.toObject(); MSVCInstallInfo info; info.version = o.value(QStringLiteral("installationVersion")).toString(); if (productType == ProductType::BuildTools) { // For build tools, the version is e.g. "15.8.28010.2036", rather than "15.0". const int dotIndex = info.version.indexOf(QLatin1Char('.')); if (dotIndex != -1) info.version = info.version.left(dotIndex); } info.installDir = o.value(QStringLiteral("installationPath")).toString(); if (!info.version.isEmpty() && !info.installDir.isEmpty()) result.push_back(info); } return result; } static std::vector installedMSVCsFromVsWhere() { const std::vector vsInstallations = retrieveInstancesFromVSWhere(ProductType::VisualStudio); const std::vector buildToolInstallations = retrieveInstancesFromVSWhere(ProductType::BuildTools); std::vector all; std::copy(vsInstallations.begin(), vsInstallations.end(), std::back_inserter(all)); std::copy(buildToolInstallations.begin(), buildToolInstallations.end(), std::back_inserter(all)); return all; } static std::vector installedMSVCsFromRegistry() { std::vector result; // Detect Visual Studio const QSettings vsRegistry( QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE") + wow6432Key() + QStringLiteral("\\Microsoft\\VisualStudio\\SxS\\VS7"), QSettings::NativeFormat); const auto vsNames = vsRegistry.childKeys(); for (const QString &vsName : vsNames) { MSVCInstallInfo entry; entry.version = vsName; entry.installDir = vsRegistry.value(vsName).toString(); result.push_back(entry); } // Detect Visual C++ Build Tools QSettings vcbtRegistry( QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE") + wow6432Key() + QStringLiteral("\\Microsoft\\VisualCppBuildTools"), QSettings::NativeFormat); const QStringList &vcbtRegistryChildGroups = vcbtRegistry.childGroups(); for (const QString &childGroup : vcbtRegistryChildGroups) { vcbtRegistry.beginGroup(childGroup); bool ok; int installed = vcbtRegistry.value(QStringLiteral("Installed")).toInt(&ok); if (ok && installed) { MSVCInstallInfo entry; entry.version = childGroup; const QSettings vsRegistry( QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE") + wow6432Key() + QStringLiteral("\\Microsoft\\VisualStudio\\") + childGroup + QStringLiteral("\\Setup\\VC"), QSettings::NativeFormat); entry.installDir = vsRegistry.value(QStringLiteral("ProductDir")).toString(); result.push_back(entry); } vcbtRegistry.endGroup(); } return result; } static std::vector installedMSVCs() { std::vector msvcs; std::vector installInfos = installedMSVCsFromVsWhere(); if (installInfos.empty()) installInfos = installedMSVCsFromRegistry(); for (const MSVCInstallInfo &installInfo : installInfos) { MSVC msvc; msvc.internalVsVersion = Version::fromString(installInfo.version, true); if (!msvc.internalVsVersion.isValid()) continue; QDir vsInstallDir(installInfo.installDir); msvc.vsInstallPath = vsInstallDir.absolutePath(); if (vsInstallDir.dirName() != QStringLiteral("VC") && !vsInstallDir.cd(QStringLiteral("VC"))) { continue; } msvc.version = QString::number(Internal::VisualStudioVersionInfo( msvc.internalVsVersion).marketingVersion()); if (msvc.version.isEmpty()) { qbsWarning() << Tr::tr("Unknown MSVC version %1 found.").arg(installInfo.version); continue; } if (msvc.internalVsVersion.majorVersion() < 15) { QDir vcInstallDir = vsInstallDir; if (!vcInstallDir.cd(QStringLiteral("bin"))) continue; msvc.vcInstallPath = vcInstallDir.absolutePath(); msvcs.push_back(msvc); } else { QDir vcInstallDir = vsInstallDir; vcInstallDir.cd(QStringLiteral("Tools/MSVC")); const auto vcVersionStrs = vcInstallDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); for (const QString &vcVersionStr : vcVersionStrs) { const Version vcVersion = Version::fromString(vcVersionStr); if (!vcVersion.isValid()) continue; QDir specificVcInstallDir = vcInstallDir; if (!specificVcInstallDir.cd(vcVersionStr) || !specificVcInstallDir.cd(QStringLiteral("bin"))) { continue; } msvc.vcInstallPath = specificVcInstallDir.absolutePath(); msvcs.push_back(msvc); } } } return msvcs; } void msvcProbe(Settings *settings, QList &profiles) { qbsInfo() << Tr::tr("Detecting MSVC toolchains..."); // 1) Installed SDKs preferred over standalone Visual studio std::vector winSDKs; WinSDK defaultWinSDK; const QSettings sdkRegistry(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE") + wow6432Key() + QLatin1String("\\Microsoft\\Microsoft SDKs\\Windows"), QSettings::NativeFormat); const QString defaultSdkPath = sdkRegistry.value(QStringLiteral("CurrentInstallFolder")).toString(); if (!defaultSdkPath.isEmpty()) { const auto sdkKeys = sdkRegistry.childGroups(); for (const QString &sdkKey : sdkKeys) { WinSDK sdk; sdk.version = sdkKey; sdk.vcInstallPath = sdkRegistry.value(sdkKey + QLatin1String("/InstallationFolder")).toString(); sdk.isDefault = (sdk.vcInstallPath == defaultSdkPath); if (sdk.vcInstallPath.isEmpty()) continue; if (sdk.vcInstallPath.endsWith(QLatin1Char('\\'))) sdk.vcInstallPath.chop(1); if (sdk.isDefault) defaultWinSDK = sdk; const auto ais = findSupportedArchitectures(sdk); for (const MSVCArchInfo &ai : ais) { WinSDK specificSDK = sdk; specificSDK.architecture = ai.arch; specificSDK.binPath = ai.binPath; winSDKs.push_back(specificSDK); } } } for (const WinSDK &sdk : qAsConst(winSDKs)) { qbsInfo() << Tr::tr(" Windows SDK %1 detected:\n" " installed in %2").arg(sdk.version, sdk.vcInstallPath); if (sdk.isDefault) qbsInfo() << Tr::tr(" This is the default SDK on this machine."); } // 2) Installed MSVCs std::vector msvcs; const auto instMsvcs = installedMSVCs(); for (const MSVC &msvc : instMsvcs) { if (msvc.internalVsVersion.majorVersion() < 15) { // Check existence of various install scripts const QString vcvars32bat = msvc.vcInstallPath + QLatin1String("/vcvars32.bat"); if (!QFileInfo(vcvars32bat).isFile()) continue; } const auto ais = findSupportedArchitectures(msvc); for (const MSVCArchInfo &ai : ais) { MSVC specificMSVC = msvc; specificMSVC.architecture = ai.arch; specificMSVC.binPath = ai.binPath; msvcs.push_back(specificMSVC); } } for (const MSVC &msvc : qAsConst(msvcs)) { qbsInfo() << Tr::tr(" MSVC %1 (%2) detected in\n" " %3").arg(msvc.version, msvc.architecture, QDir::toNativeSeparators(msvc.binPath)); } if (winSDKs.empty() && msvcs.empty()) { qbsInfo() << Tr::tr("Could not detect an installation of " "the Windows SDK or Visual Studio."); return; } qbsInfo() << Tr::tr("Detecting build environment..."); std::vector msvcPtrs; msvcPtrs.resize(winSDKs.size() + msvcs.size()); std::transform(winSDKs.begin(), winSDKs.end(), msvcPtrs.begin(), [] (WinSDK &sdk) -> MSVC * { return &sdk; }); std::transform(msvcs.begin(), msvcs.end(), msvcPtrs.begin() + winSDKs.size(), [] (MSVC &msvc) -> MSVC * { return &msvc; }); VsEnvironmentDetector envDetector; envDetector.start(msvcPtrs); for (WinSDK &sdk : winSDKs) { const QString name = QLatin1String("WinSDK") + sdk.version + QLatin1Char('-') + sdk.architecture; try { sdk.init(); addMSVCPlatform(settings, profiles, name, &sdk); } catch (const ErrorInfo &error) { qbsWarning() << Tr::tr("Failed to set up %1: %2").arg(name, error.toString()); } } for (MSVC &msvc : msvcs) { const QString name = QLatin1String("MSVC") + msvc.version + QLatin1Char('-') + msvc.architecture; try { msvc.init(); addMSVCPlatform(settings, profiles, name, &msvc); } catch (const ErrorInfo &error) { qbsWarning() << Tr::tr("Failed to set up %1: %2").arg(name, error.toString()); } } } void createMsvcProfile(const QString &profileName, const QString &compilerFilePath, Settings *settings) { MSVC msvc(compilerFilePath); msvc.init(); QList dummy; addMSVCPlatform(settings, dummy, profileName, &msvc); qbsInfo() << Tr::tr("Profile '%1' created for '%2'.") .arg(profileName, QDir::toNativeSeparators(compilerFilePath)); } qbs-src-1.13.1/src/app/qbs-setup-toolchains/msvcprobe.h000066400000000000000000000042741347155106100227650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MSVCPROBE_H #define MSVCPROBE_H #include namespace qbs { class Profile; class Settings; } void createMsvcProfile(const QString &profileName, const QString &compilerFilePath, qbs::Settings *settings); void msvcProbe(qbs::Settings *settings, QList &profiles); #endif // MSVCPROBE_H qbs-src-1.13.1/src/app/qbs-setup-toolchains/probe.cpp000066400000000000000000000433641347155106100224320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "probe.h" #include "msvcprobe.h" #include "xcodeprobe.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using Internal::HostOsInfo; using Internal::Tr; static QTextStream qStdout(stdout); static QTextStream qStderr(stderr); static QString findExecutable(const QString &fileName) { QString fullFileName = fileName; if (HostOsInfo::isWindowsHost() && !fileName.endsWith(QLatin1String(".exe"), Qt::CaseInsensitive)) { fullFileName += QLatin1String(".exe"); } const QString path = QString::fromLocal8Bit(qgetenv("PATH")); const auto ppaths = path.split(HostOsInfo::pathListSeparator()); for (const QString &ppath : ppaths) { const QString fullPath = ppath + QLatin1Char('/') + fullFileName; if (QFileInfo::exists(fullPath)) return QDir::cleanPath(fullPath); } return {}; } static QString qsystem(const QString &exe, const QStringList &args = QStringList()) { QProcess p; p.setProcessChannelMode(QProcess::MergedChannels); p.start(exe, args); if (!p.waitForStarted()) { throw qbs::ErrorInfo(Tr::tr("Failed to start compiler '%1': %2") .arg(exe, p.errorString())); } if (!p.waitForFinished(-1) || p.exitCode() != 0) throw qbs::ErrorInfo(Tr::tr("Failed to run compiler '%1': %2").arg(exe, p.errorString())); return QString::fromLocal8Bit(p.readAll()); } static QStringList validMinGWMachines() { // List of MinGW machine names (gcc -dumpmachine) recognized by Qbs return {QStringLiteral("mingw32"), QStringLiteral("mingw64"), QStringLiteral("i686-w64-mingw32"), QStringLiteral("x86_64-w64-mingw32"), QStringLiteral("i686-w64-mingw32.shared"), QStringLiteral("x86_64-w64-mingw32.shared"), QStringLiteral("i686-w64-mingw32.static"), QStringLiteral("x86_64-w64-mingw32.static"), QStringLiteral("i586-mingw32msvc"), QStringLiteral("amd64-mingw32msvc")}; } static QStringList knownIarCompilerNames() { return {QStringLiteral("icc8051"), QStringLiteral("iccarm"), QStringLiteral("iccavr")}; } static bool isIarCompiler(const QString &compilerName) { return Internal::any_of(knownIarCompilerNames(), [compilerName](const QString &knownName) { return compilerName.contains(knownName); }); } static QStringList knownKeilCompilerNames() { return {QStringLiteral("c51"), QStringLiteral("armcc")}; } static bool isKeilCompiler(const QString &compilerName) { return Internal::any_of(knownKeilCompilerNames(), [compilerName](const QString &knownName) { return compilerName.contains(knownName); }); } static QStringList toolchainTypeFromCompilerName(const QString &compilerName) { if (compilerName == QLatin1String("cl.exe")) return canonicalToolchain(QStringLiteral("msvc")); const auto types = { QStringLiteral("clang"), QStringLiteral("llvm"), QStringLiteral("mingw"), QStringLiteral("gcc") }; for (const auto &type : types) { if (compilerName.contains(type)) return canonicalToolchain(type); } if (compilerName == QLatin1String("g++")) return canonicalToolchain(QStringLiteral("gcc")); if (isIarCompiler(compilerName)) return canonicalToolchain(QStringLiteral("iar")); if (isKeilCompiler(compilerName)) return canonicalToolchain(QStringLiteral("keil")); return {}; } static QString gccMachineName(const QString &compilerFilePath) { return qsystem(compilerFilePath, QStringList() << QStringLiteral("-dumpmachine")).trimmed(); } static QStringList standardCompilerFileNames() { return {HostOsInfo::appendExecutableSuffix(QStringLiteral("gcc")), HostOsInfo::appendExecutableSuffix(QStringLiteral("g++")), HostOsInfo::appendExecutableSuffix(QStringLiteral("clang")), HostOsInfo::appendExecutableSuffix(QStringLiteral("clang++"))}; } static void setCommonProperties(Profile &profile, const QString &compilerFilePath, const QStringList &toolchainTypes) { const QFileInfo cfi(compilerFilePath); const QString compilerName = cfi.fileName(); if (toolchainTypes.contains(QStringLiteral("mingw"))) profile.setValue(QStringLiteral("qbs.targetPlatform"), QStringLiteral("windows")); const QString prefix = compilerName.left(compilerName.lastIndexOf(QLatin1Char('-')) + 1); if (!prefix.isEmpty()) profile.setValue(QStringLiteral("cpp.toolchainPrefix"), prefix); profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), cfi.absolutePath()); profile.setValue(QStringLiteral("qbs.toolchain"), toolchainTypes); const QString suffix = compilerName.right(compilerName.size() - prefix.size()); if (!standardCompilerFileNames().contains(suffix)) qWarning("%s", qPrintable( QStringLiteral("'%1' is not a standard compiler file name; " "you must set the cpp.cCompilerName and " "cpp.cxxCompilerName properties of this profile " "manually").arg(compilerName))); } class ToolPathSetup { public: ToolPathSetup(Profile *profile, const QString &path, const QString &toolchainPrefix) : m_profile(profile), m_compilerDirPath(path), m_toolchainPrefix(toolchainPrefix) { } void apply(const QString &toolName, const QString &propertyName) const { QString toolFileName = m_toolchainPrefix + HostOsInfo::appendExecutableSuffix(toolName); if (QFile::exists(m_compilerDirPath + QLatin1Char('/') + toolFileName)) return; const QString toolFilePath = findExecutable(toolFileName); if (toolFilePath.isEmpty()) { qWarning("%s", qPrintable(QStringLiteral("'%1' exists neither in '%2' nor in PATH.") .arg(toolFileName, m_compilerDirPath))); } m_profile->setValue(propertyName, toolFilePath); } private: Profile * const m_profile; QString m_compilerDirPath; QString m_toolchainPrefix; }; static bool doesProfileTargetOS(const Profile &profile, const QString &os) { const auto target = profile.value(QStringLiteral("qbs.targetPlatform")); if (target.isValid()) { return Internal::contains(HostOsInfo::canonicalOSIdentifiers( target.toString().toStdString()), os.toStdString()); } return Internal::contains(HostOsInfo::hostOSIdentifiers(), os.toStdString()); } static Profile createGccProfile(const QString &compilerFilePath, Settings *settings, const QStringList &toolchainTypes, const QString &profileName = QString()) { const QString machineName = gccMachineName(compilerFilePath); if (toolchainTypes.contains(QLatin1String("mingw"))) { if (!validMinGWMachines().contains(machineName)) { throw ErrorInfo(Tr::tr("Detected gcc platform '%1' is not supported.") .arg(machineName)); } } Profile profile(!profileName.isEmpty() ? profileName : machineName, settings); profile.removeProfile(); setCommonProperties(profile, compilerFilePath, toolchainTypes); // Check whether auxiliary tools reside within the toolchain's install path. // This might not be the case when using icecc or another compiler wrapper. const QString compilerDirPath = QFileInfo(compilerFilePath).absolutePath(); const ToolPathSetup toolPathSetup(&profile, compilerDirPath, profile.value(QStringLiteral("cpp.toolchainPrefix")) .toString()); toolPathSetup.apply(QStringLiteral("ar"), QStringLiteral("cpp.archiverPath")); toolPathSetup.apply(QStringLiteral("as"), QStringLiteral("cpp.assemblerPath")); toolPathSetup.apply(QStringLiteral("nm"), QStringLiteral("cpp.nmPath")); if (doesProfileTargetOS(profile, QStringLiteral("darwin"))) toolPathSetup.apply(QStringLiteral("dsymutil"), QStringLiteral("cpp.dsymutilPath")); else toolPathSetup.apply(QStringLiteral("objcopy"), QStringLiteral("cpp.objcopyPath")); toolPathSetup.apply(QStringLiteral("strip"), QStringLiteral("cpp.stripPath")); qStdout << Tr::tr("Profile '%1' created for '%2'.").arg(profile.name(), compilerFilePath) << endl; return profile; } static QString guessIarArchitecture(const QFileInfo &compiler) { const auto baseName = compiler.baseName(); if (baseName == QLatin1String("icc8051")) return QStringLiteral("mcs51"); if (baseName == QLatin1String("iccarm")) return QStringLiteral("arm"); if (baseName == QLatin1String("iccavr")) return QStringLiteral("avr"); return {}; } static Profile createIarProfile(const QFileInfo &compiler, Settings *settings, QString profileName = QString()) { const QString architecture = guessIarArchitecture(compiler); // In case the profile is auto-detected. if (profileName.isEmpty()) profileName = QLatin1String("iar-") + architecture; Profile profile(profileName, settings); profile.setValue(QLatin1String("cpp.toolchainInstallPath"), compiler.absolutePath()); profile.setValue(QLatin1String("qbs.toolchainType"), QLatin1String("iar")); if (!architecture.isEmpty()) profile.setValue(QLatin1String("qbs.architecture"), architecture); qStdout << Tr::tr("Profile '%1' created for '%2'.").arg( profile.name(), compiler.absoluteFilePath()) << endl; return profile; } static QString guessKeilArchitecture(const QFileInfo &compiler) { const auto baseName = compiler.baseName(); if (baseName == QLatin1String("c51")) return QStringLiteral("mcs51"); if (baseName == QLatin1String("armcc")) return QStringLiteral("arm"); return {}; } static Profile createKeilProfile(const QFileInfo &compiler, Settings *settings, QString profileName = QString()) { const QString architecture = guessKeilArchitecture(compiler); // In case the profile is auto-detected. if (profileName.isEmpty()) profileName = QLatin1String("keil-") + architecture; Profile profile(profileName, settings); profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath()); profile.setValue(QStringLiteral("qbs.toolchainType"), QStringLiteral("keil")); if (!architecture.isEmpty()) profile.setValue(QStringLiteral("qbs.architecture"), architecture); qStdout << Tr::tr("Profile '%1' created for '%2'.").arg( profile.name(), compiler.absoluteFilePath()) << endl; return profile; } static void gccProbe(Settings *settings, QList &profiles, const QString &compilerName) { qStdout << Tr::tr("Trying to detect %1...").arg(compilerName) << endl; const QString crossCompilePrefix = QString::fromLocal8Bit(qgetenv("CROSS_COMPILE")); const QString compilerFilePath = findExecutable(crossCompilePrefix + compilerName); QFileInfo cfi(compilerFilePath); if (!cfi.exists()) { qStderr << Tr::tr("%1 not found.").arg(compilerName) << endl; return; } const QString profileName = cfi.completeBaseName(); const QStringList toolchainTypes = toolchainTypeFromCompilerName(compilerName); profiles.push_back(createGccProfile(compilerFilePath, settings, toolchainTypes, profileName)); } static void mingwProbe(Settings *settings, QList &profiles) { // List of possible compiler binary names for this platform QStringList compilerNames; if (HostOsInfo::isWindowsHost()) { compilerNames << QStringLiteral("gcc"); } else { const auto machineNames = validMinGWMachines(); for (const QString &machineName : machineNames) { compilerNames << machineName + QLatin1String("-gcc"); } } for (const QString &compilerName : qAsConst(compilerNames)) { const QString gccPath = findExecutable(HostOsInfo::appendExecutableSuffix(compilerName)); if (!gccPath.isEmpty()) profiles.push_back(createGccProfile(gccPath, settings, canonicalToolchain(QStringLiteral("mingw")))); } } static void iarProbe(Settings *settings, QList &profiles) { qStdout << Tr::tr("Trying to detect IAR toolchains...") << endl; bool isFound = false; for (const QString &compilerName : knownIarCompilerNames()) { const QString iarPath = findExecutable(HostOsInfo::appendExecutableSuffix(compilerName)); if (!iarPath.isEmpty()) { const auto profile = createIarProfile(iarPath, settings); profiles.push_back(profile); isFound = true; } } if (!isFound) qStdout << Tr::tr("No IAR toolchains found.") << endl; } static void keilProbe(Settings *settings, QList &profiles) { qStdout << Tr::tr("Trying to detect KEIL toolchains...") << endl; bool isFound = false; for (const QString &compilerName : knownKeilCompilerNames()) { const QString keilPath = findExecutable(HostOsInfo::appendExecutableSuffix(compilerName)); if (!keilPath.isEmpty()) { const auto profile = createKeilProfile(keilPath, settings); profiles.push_back(profile); isFound = true; } } if (!isFound) qStdout << Tr::tr("No KEIL toolchains found.") << endl; } void probe(Settings *settings) { QList profiles; if (HostOsInfo::isWindowsHost()) { msvcProbe(settings, profiles); } else { gccProbe(settings, profiles, QStringLiteral("gcc")); gccProbe(settings, profiles, QStringLiteral("clang")); if (HostOsInfo::isMacosHost()) { xcodeProbe(settings, profiles); } } mingwProbe(settings, profiles); iarProbe(settings, profiles); keilProbe(settings, profiles); if (profiles.empty()) { qStderr << Tr::tr("Could not detect any toolchains. No profile created.") << endl; } else if (profiles.size() == 1 && settings->defaultProfile().isEmpty()) { const QString profileName = profiles.front().name(); qStdout << Tr::tr("Making profile '%1' the default.").arg(profileName) << endl; settings->setValue(QStringLiteral("defaultProfile"), profileName); } } void createProfile(const QString &profileName, const QString &toolchainType, const QString &compilerFilePath, Settings *settings) { QFileInfo compiler(compilerFilePath); if (compilerFilePath == compiler.fileName() && !compiler.exists()) compiler = QFileInfo(findExecutable(compilerFilePath)); if (!compiler.exists()) { throw qbs::ErrorInfo(Tr::tr("Compiler '%1' not found") .arg(compilerFilePath)); } QStringList toolchainTypes; if (toolchainType.isEmpty()) toolchainTypes = toolchainTypeFromCompilerName(compiler.fileName()); else toolchainTypes = canonicalToolchain(toolchainType); if (toolchainTypes.contains(QLatin1String("msvc"))) createMsvcProfile(profileName, compiler.absoluteFilePath(), settings); else if (toolchainTypes.contains(QLatin1String("gcc"))) createGccProfile(compiler.absoluteFilePath(), settings, toolchainTypes, profileName); else if (toolchainTypes.contains(QLatin1String("iar"))) createIarProfile(compiler, settings, profileName); else if (toolchainTypes.contains(QLatin1String("keil"))) createKeilProfile(compiler, settings, profileName); else throw qbs::ErrorInfo(Tr::tr("Cannot create profile: Unknown toolchain type.")); } qbs-src-1.13.1/src/app/qbs-setup-toolchains/probe.h000066400000000000000000000043511347155106100220700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROBE_H #define QBS_PROBE_H #include QT_BEGIN_NAMESPACE class QString; class QStringList; QT_END_NAMESPACE namespace qbs { class Settings; } void createProfile(const QString &profileName, const QString &toolchainType, const QString &compilerFilePath, qbs::Settings *settings); void probe(qbs::Settings *settings); #endif // Header guard qbs-src-1.13.1/src/app/qbs-setup-toolchains/qbs-setup-toolchains.exe.manifest000066400000000000000000000007361347155106100272070ustar00rootroot00000000000000 qbs-src-1.13.1/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro000066400000000000000000000004551347155106100254170ustar00rootroot00000000000000include(../app.pri) TARGET = qbs-setup-toolchains HEADERS += \ commandlineparser.h \ msvcprobe.h \ probe.h \ xcodeprobe.h SOURCES += \ commandlineparser.cpp \ main.cpp \ msvcprobe.cpp \ probe.cpp \ xcodeprobe.cpp mingw { RC_FILE = qbs-setup-toolchains.rc } qbs-src-1.13.1/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs000066400000000000000000000011021347155106100253720ustar00rootroot00000000000000import qbs 1.0 QbsApp { name: "qbs-setup-toolchains" cpp.dynamicLibraries: qbs.targetOS.contains("windows") ? base.concat("shell32") : base files: [ "commandlineparser.cpp", "commandlineparser.h", "main.cpp", "msvcprobe.cpp", "msvcprobe.h", "probe.cpp", "probe.h", "xcodeprobe.cpp", "xcodeprobe.h", ] Group { name: "MinGW specific files" condition: qbs.toolchain.contains("mingw") files: ["qbs-setup-toolchains.exe.manifest", "qbs-setup-toolchains.rc"] } } qbs-src-1.13.1/src/app/qbs-setup-toolchains/qbs-setup-toolchains.rc000066400000000000000000000002301347155106100252120ustar00rootroot00000000000000#define RT_MANIFEST 24 #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "qbs-setup-toolchains.exe.manifest" qbs-src-1.13.1/src/app/qbs-setup-toolchains/xcodeprobe.cpp000066400000000000000000000223421347155106100234460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "probe.h" #include "xcodeprobe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using Internal::Tr; namespace { static const QString defaultDeveloperPath = QStringLiteral("/Applications/Xcode.app/Contents/Developer"); static const std::regex defaultDeveloperPathRegex( "^/Applications/Xcode([a-zA-Z0-9 _-]+)\\.app/Contents/Developer$"); class XcodeProbe { public: XcodeProbe(qbs::Settings *settings, QList &profiles) : settings(settings), profiles(profiles) { } bool addDeveloperPath(const QString &path); void detectDeveloperPaths(); void setupDefaultToolchains(const QString &devPath, const QString &xCodeName); void detectAll(); private: qbs::Settings *settings; QList &profiles; QStringList developerPaths; }; bool XcodeProbe::addDeveloperPath(const QString &path) { if (path.isEmpty()) return false; QFileInfo pInfo(path); if (!pInfo.exists() || !pInfo.isDir()) return false; if (developerPaths.contains(path)) return false; developerPaths.push_back(path); qbsInfo() << Tr::tr("Added developer path %1").arg(path); return true; } void XcodeProbe::detectDeveloperPaths() { QProcess selectedXcode; QString program = QStringLiteral("/usr/bin/xcode-select"); QStringList arguments(QStringLiteral("--print-path")); selectedXcode.start(program, arguments, QProcess::ReadOnly); if (!selectedXcode.waitForFinished(-1) || selectedXcode.exitCode()) { qbsInfo() << Tr::tr("Could not detect selected Xcode with /usr/bin/xcode-select"); } else { QString path = QString::fromLocal8Bit(selectedXcode.readAllStandardOutput()); addDeveloperPath(path); } addDeveloperPath(defaultDeveloperPath); QProcess launchServices; program = QStringLiteral("/usr/bin/mdfind"); arguments = QStringList(QStringLiteral("kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode'")); launchServices.start(program, arguments, QProcess::ReadOnly); if (!launchServices.waitForFinished(-1) || launchServices.exitCode()) { qbsInfo() << Tr::tr("Could not detect additional Xcode installations with /usr/bin/mdfind"); } else { for (const QString &path : QString::fromLocal8Bit(launchServices.readAllStandardOutput()) .split(QLatin1Char('\n'), QString::SkipEmptyParts)) addDeveloperPath(path + QStringLiteral("/Contents/Developer")); } } static QString targetOS(const QString &applePlatformName) { if (applePlatformName == QStringLiteral("macosx")) return QStringLiteral("macos"); if (applePlatformName == QStringLiteral("iphoneos")) return QStringLiteral("ios"); if (applePlatformName == QStringLiteral("iphonesimulator")) return QStringLiteral("ios-simulator"); if (applePlatformName == QStringLiteral("appletvos")) return QStringLiteral("tvos"); if (applePlatformName == QStringLiteral("appletvsimulator")) return QStringLiteral("tvos-simulator"); if (applePlatformName == QStringLiteral("watchos")) return QStringLiteral("watchos"); if (applePlatformName == QStringLiteral("watchsimulator")) return QStringLiteral("watchos-simulator"); return {}; } static QStringList archList(const QString &applePlatformName) { QStringList archs; if (applePlatformName == QStringLiteral("macosx") || applePlatformName == QStringLiteral("iphonesimulator") || applePlatformName == QStringLiteral("appletvsimulator") || applePlatformName == QStringLiteral("watchsimulator")) { if (applePlatformName != QStringLiteral("appletvsimulator")) archs << QStringLiteral("x86"); if (applePlatformName != QStringLiteral("watchsimulator")) archs << QStringLiteral("x86_64"); } else if (applePlatformName == QStringLiteral("iphoneos") || applePlatformName == QStringLiteral("appletvos")) { if (applePlatformName != QStringLiteral("appletvos")) archs << QStringLiteral("armv7a"); archs << QStringLiteral("arm64"); } else if (applePlatformName == QStringLiteral("watchos")) { archs << QStringLiteral("armv7k"); } return archs; } void XcodeProbe::setupDefaultToolchains(const QString &devPath, const QString &xcodeName) { qbsInfo() << Tr::tr("Profile '%1' created for '%2'.").arg(xcodeName).arg(devPath); Profile installationProfile(xcodeName, settings); installationProfile.removeProfile(); installationProfile.setValue(QStringLiteral("qbs.toolchain"), QStringList() << QStringLiteral("xcode") << QStringLiteral("clang") << QStringLiteral("llvm") << QStringLiteral("gcc")); if (devPath != defaultDeveloperPath) installationProfile.setValue(QStringLiteral("xcode.developerPath"), devPath); profiles.push_back(installationProfile); QStringList platforms; platforms << QStringLiteral("macosx") << QStringLiteral("iphoneos") << QStringLiteral("iphonesimulator") << QStringLiteral("appletvos") << QStringLiteral("appletvsimulator") << QStringLiteral("watchos") << QStringLiteral("watchsimulator"); for (const QString &platform : platforms) { Profile platformProfile(xcodeName + QLatin1Char('-') + platform, settings); platformProfile.removeProfile(); platformProfile.setBaseProfile(installationProfile.name()); platformProfile.setValue(QStringLiteral("qbs.targetPlatform"), targetOS(platform)); profiles.push_back(platformProfile); for (const QString &arch : archList(platform)) { Profile archProfile(xcodeName + QLatin1Char('-') + platform + QLatin1Char('-') + arch, settings); archProfile.removeProfile(); archProfile.setBaseProfile(platformProfile.name()); archProfile.setValue(QStringLiteral("qbs.architecture"), qbs::canonicalArchitecture(arch)); profiles.push_back(archProfile); } } } void XcodeProbe::detectAll() { int i = 1; detectDeveloperPaths(); for (const QString &developerPath : developerPaths) { QString profileName = QStringLiteral("xcode"); if (developerPath != defaultDeveloperPath) { const auto devPath = developerPath.toStdString(); std::smatch match; if (std::regex_match(devPath, match, defaultDeveloperPathRegex)) profileName += QString::fromStdString(match[1]).toLower().replace(QLatin1Char(' '), QLatin1Char('-')); else profileName += QString::number(i++); } setupDefaultToolchains(developerPath, profileName); } } } // end anonymous namespace void xcodeProbe(qbs::Settings *settings, QList &profiles) { XcodeProbe probe(settings, profiles); probe.detectAll(); } qbs-src-1.13.1/src/app/qbs-setup-toolchains/xcodeprobe.h000066400000000000000000000040721347155106100231130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef XCODEPROBE_H #define XCODEPROBE_H #include namespace qbs { class Profile; class Settings; } void xcodeProbe(qbs::Settings *settings, QList &profiles); #endif // XCODEPROBE_H qbs-src-1.13.1/src/app/qbs/000077500000000000000000000000001347155106100153065ustar00rootroot00000000000000qbs-src-1.13.1/src/app/qbs/application.cpp000066400000000000000000000053501347155106100203200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "application.h" #include "commandlinefrontend.h" #include "ctrlchandler.h" namespace qbs { Application::Application(int &argc, char **argv) : QCoreApplication(argc, argv), m_clFrontend(nullptr), m_canceled(false) { setApplicationName(QStringLiteral("qbs")); setOrganizationName(QStringLiteral("QtProject")); setOrganizationDomain(QStringLiteral("qt-project.org")); } Application *Application::instance() { return qobject_cast(QCoreApplication::instance()); } void Application::setCommandLineFrontend(CommandLineFrontend *clFrontend) { installCtrlCHandler(); m_clFrontend = clFrontend; } /** * Interrupt the application. This is directly called from a signal handler. */ void Application::userInterrupt() { if (m_canceled) return; Q_ASSERT(m_clFrontend); m_canceled = true; m_clFrontend->cancel(); } } // namespace qbs qbs-src-1.13.1/src/app/qbs/application.h000066400000000000000000000045041347155106100177650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef APPLICATION_H #define APPLICATION_H #include namespace qbs { class CommandLineFrontend; class Application : public QCoreApplication { Q_OBJECT public: Application(int &argc, char **argv); static Application *instance(); void setCommandLineFrontend(CommandLineFrontend *clFrontend); void userInterrupt(); private: CommandLineFrontend *m_clFrontend; bool m_canceled; }; } // namespace qbs #endif // APPLICATION_H qbs-src-1.13.1/src/app/qbs/commandlinefrontend.cpp000066400000000000000000000654011347155106100220460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlinefrontend.h" #include "application.h" #include "consoleprogressobserver.h" #include "status.h" #include "parser/commandlineoption.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; CommandLineFrontend::CommandLineFrontend(const CommandLineParser &parser, Settings *settings, QObject *parent) : QObject(parent) , m_parser(parser) , m_settings(settings) , m_observer(nullptr) , m_cancelStatus(CancelStatusNone) , m_cancelTimer(new QTimer(this)) { } CommandLineFrontend::~CommandLineFrontend() { m_cancelTimer->stop(); } // Called from interrupt handler. Don't do anything non-trivial here. void CommandLineFrontend::cancel() { m_cancelStatus = CancelStatusRequested; } void CommandLineFrontend::checkCancelStatus() { switch (m_cancelStatus) { case CancelStatusNone: break; case CancelStatusRequested: m_cancelStatus = CancelStatusCanceling; m_cancelTimer->stop(); if (m_resolveJobs.empty() && m_buildJobs.empty()) std::exit(EXIT_FAILURE); for (AbstractJob * const job : qAsConst(m_resolveJobs)) job->cancel(); for (AbstractJob * const job : qAsConst(m_buildJobs)) job->cancel(); break; case CancelStatusCanceling: QBS_ASSERT(false, return); break; } } void CommandLineFrontend::start() { try { switch (m_parser.command()) { case RunCommandType: case ShellCommandType: if (m_parser.products().size() > 1) { throw ErrorInfo(Tr::tr("Invalid use of command '%1': Cannot use more than one " "product.\nUsage: %2") .arg(m_parser.commandName(), m_parser.commandDescription())); } Q_FALLTHROUGH(); case StatusCommandType: case InstallCommandType: case DumpNodesTreeCommandType: case ListProductsCommandType: if (m_parser.buildConfigurations().size() > 1) { QString error = Tr::tr("Invalid use of command '%1': There can be only one " "build configuration.\n").arg(m_parser.commandName()); error += Tr::tr("Usage: %1").arg(m_parser.commandDescription()); throw ErrorInfo(error); } break; default: break; } if (m_parser.showVersion()) { puts(QBS_VERSION); qApp->exit(EXIT_SUCCESS); return; } if (m_parser.showProgress()) m_observer = new ConsoleProgressObserver; SetupProjectParameters params; params.setEnvironment(QProcessEnvironment::systemEnvironment()); params.setProjectFilePath(m_parser.projectFilePath()); params.setDryRun(m_parser.dryRun()); params.setForceProbeExecution(m_parser.forceProbesExecution()); params.setWaitLockBuildGraph(m_parser.waitLockBuildGraph()); params.setFallbackProviderEnabled(!m_parser.disableFallbackProvider()); params.setLogElapsedTime(m_parser.logTime()); params.setSettingsDirectory(m_settings->baseDirectory()); params.setOverrideBuildGraphData(m_parser.command() == ResolveCommandType); params.setPropertyCheckingMode(ErrorHandlingMode::Strict); if (!m_parser.buildBeforeInstalling() || !m_parser.commandCanResolve()) params.setRestoreBehavior(SetupProjectParameters::RestoreOnly); const auto buildConfigs = m_parser.buildConfigurations(); for (const QVariantMap &buildConfig : buildConfigs) { QVariantMap userConfig = buildConfig; const QString configurationKey = QStringLiteral("qbs.configurationName"); const QString profileKey = QStringLiteral("qbs.profile"); const QString installRootKey = QStringLiteral("qbs.installRoot"); QString installRoot = userConfig.value(installRootKey).toString(); if (!installRoot.isEmpty() && QFileInfo(installRoot).isRelative()) { installRoot.prepend(QLatin1Char('/')).prepend(QDir::currentPath()); userConfig.insert(installRootKey, installRoot); } const QString configurationName = userConfig.take(configurationKey).toString(); const QString profileName = userConfig.take(profileKey).toString(); const Preferences prefs(m_settings); params.setSearchPaths(prefs.searchPaths(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_SEARCH_PATH)))); params.setPluginPaths(prefs.pluginPaths(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_PLUGINS_PATH)))); params.setLibexecPath(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_LIBEXEC_PATH))); params.setTopLevelProfile(profileName); params.setConfigurationName(configurationName); params.setBuildRoot(buildDirectory(profileName)); params.setOverriddenValues(userConfig); SetupProjectJob * const job = Project().setupProject(params, ConsoleLogger::instance().logSink(), this); connectJob(job); m_resolveJobs.push_back(job); } /* * Progress reporting on the terminal gets a bit tricky when resolving several projects * concurrently, since we cannot show multiple progress bars at the same time. Instead, * we just set the total effort to the number of projects and increase the progress * every time one of them finishes, ignoring the progress reports from the jobs themselves. * (Yes, that does mean it will take disproportionately long for the first progress * notification to arrive.) */ if (m_parser.showProgress() && resolvingMultipleProjects()) m_observer->initialize(tr("Setting up projects"), m_resolveJobs.size()); // Check every two seconds whether we received a cancel request. This value has been // experimentally found to be acceptable. // Note that this polling approach is not problematic here, since we are doing work anyway, // so there's no danger of waking up the processor for no reason. connect(m_cancelTimer, &QTimer::timeout, this, &CommandLineFrontend::checkCancelStatus); m_cancelTimer->start(2000); } catch (const ErrorInfo &error) { qbsError() << error.toString(); if (m_buildJobs.empty() && m_resolveJobs.empty()) { qApp->exit(EXIT_FAILURE); } else { cancel(); checkCancelStatus(); } } } void CommandLineFrontend::handleCommandDescriptionReport(const QString &highlight, const QString &message) { qbsInfo() << MessageTag(highlight) << message; } void CommandLineFrontend::handleJobFinished(bool success, AbstractJob *job) { try { job->deleteLater(); if (!success) { qbsError() << job->error().toString(); m_resolveJobs.removeOne(job); m_buildJobs.removeOne(job); if (m_resolveJobs.empty() && m_buildJobs.empty()) { qApp->exit(EXIT_FAILURE); return; } cancel(); } else if (SetupProjectJob * const setupJob = qobject_cast(job)) { m_resolveJobs.removeOne(job); m_projects.push_back(setupJob->project()); if (m_observer && resolvingMultipleProjects()) m_observer->incrementProgressValue(); if (m_resolveJobs.empty()) handleProjectsResolved(); } else if (qobject_cast(job)) { if (m_parser.command() == RunCommandType) qApp->exit(runTarget()); else qApp->quit(); } else { // Build or clean. m_buildJobs.removeOne(job); if (m_buildJobs.empty()) { switch (m_parser.command()) { case RunCommandType: case InstallCommandType: install(); break; case GenerateCommandType: generate(); // fall through case BuildCommandType: case CleanCommandType: qApp->exit(m_cancelStatus == CancelStatusNone ? EXIT_SUCCESS : EXIT_FAILURE); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Missing case in switch statement"); } } } } catch (const ErrorInfo &error) { qbsError() << error.toString(); qApp->exit(EXIT_FAILURE); } } void CommandLineFrontend::handleNewTaskStarted(const QString &description, int totalEffort) { // If the user does not want a progress bar, we just print the current activity. if (!m_parser.showProgress()) { if (!m_parser.logTime()) qbsInfo() << description; return; } if (isBuilding()) { m_totalBuildEffort += totalEffort; if (++m_buildEffortsRetrieved == m_buildEffortsNeeded) { m_observer->initialize(tr("Building"), m_totalBuildEffort); if (m_currentBuildEffort > 0) m_observer->setProgressValue(m_currentBuildEffort); } } else if (!resolvingMultipleProjects()) { m_observer->initialize(description, totalEffort); } } void CommandLineFrontend::handleTotalEffortChanged(int totalEffort) { // Can only happen when resolving. if (m_parser.showProgress() && !isBuilding() && !resolvingMultipleProjects()) m_observer->setMaximum(totalEffort); } void CommandLineFrontend::handleTaskProgress(int value, AbstractJob *job) { if (isBuilding()) { int ¤tJobEffort = m_buildEfforts[job]; m_currentBuildEffort += value - currentJobEffort; currentJobEffort = value; if (m_buildEffortsRetrieved == m_buildEffortsNeeded) m_observer->setProgressValue(m_currentBuildEffort); } else if (!resolvingMultipleProjects()) { m_observer->setProgressValue(value); } } void CommandLineFrontend::handleProcessResultReport(const qbs::ProcessResult &result) { bool hasOutput = !result.stdOut().empty() || !result.stdErr().empty(); if (!hasOutput && result.success()) return; LogWriter w = result.success() ? qbsInfo() : qbsError(); w << shellQuote(QDir::toNativeSeparators(result.executableFilePath()), result.arguments()) << (hasOutput ? QStringLiteral("\n") : QString()) << (result.stdOut().empty() ? QString() : result.stdOut().join(QLatin1Char('\n'))); if (!result.stdErr().empty()) w << result.stdErr().join(QLatin1Char('\n')) << MessageTag(QStringLiteral("stdErr")); } bool CommandLineFrontend::resolvingMultipleProjects() const { return isResolving() && m_resolveJobs.size() + m_projects.size() > 1; } bool CommandLineFrontend::isResolving() const { return !m_resolveJobs.empty(); } bool CommandLineFrontend::isBuilding() const { return !m_buildJobs.empty(); } CommandLineFrontend::ProductMap CommandLineFrontend::productsToUse() const { ProductMap products; QStringList productNames; const bool useAll = m_parser.products().empty(); for (const Project &project : qAsConst(m_projects)) { QList &productList = products[project]; const ProjectData projectData = project.projectData(); const auto products = projectData.allProducts(); for (const ProductData &product : products) { productNames << product.name(); if (useAll || m_parser.products().contains(product.name())) { productList.push_back(product); } } } const auto parsedProductNames = m_parser.products(); for (const QString &productName : parsedProductNames) { if (!productNames.contains(productName)) { QString msg; if (productNames.size() <= 10) { productNames.sort(); const QString available = productNames.join(QLatin1String("', '")); msg = Tr::tr("No such product '%1'. " "Available products: '%2'").arg(productName, available); } else { msg = Tr::tr("No such product '%1'. Use 'list-products' to see " "all available products.").arg(productName); } throw ErrorInfo(msg); } } return products; } void CommandLineFrontend::handleProjectsResolved() { if (m_cancelStatus != CancelStatusNone) throw ErrorInfo(Tr::tr("Execution canceled.")); switch (m_parser.command()) { case ResolveCommandType: qApp->quit(); break; case CleanCommandType: makeClean(); break; case ShellCommandType: qApp->exit(runShell()); break; case StatusCommandType: qApp->exit(printStatus(m_projects.front().projectData())); break; case GenerateCommandType: checkGeneratorName(); Q_FALLTHROUGH(); case BuildCommandType: build(); break; case InstallCommandType: case RunCommandType: if (m_parser.buildBeforeInstalling()) build(); else install(); break; case UpdateTimestampsCommandType: updateTimestamps(); qApp->quit(); break; case DumpNodesTreeCommandType: dumpNodesTree(); qApp->quit(); break; case ListProductsCommandType: listProducts(); qApp->quit(); break; case HelpCommandType: case VersionCommandType: Q_ASSERT_X(false, Q_FUNC_INFO, "Impossible."); } } void CommandLineFrontend::makeClean() { if (m_parser.products().empty()) { for (const Project &project : qAsConst(m_projects)) { m_buildJobs << project.cleanAllProducts(m_parser.cleanOptions(project.profile()), this); } } else { const ProductMap &products = productsToUse(); for (ProductMap::ConstIterator it = products.begin(); it != products.end(); ++it) { m_buildJobs.push_back(it.key().cleanSomeProducts( it.value(), m_parser.cleanOptions(it.key().profile()), this)); } } connectBuildJobs(); } int CommandLineFrontend::runShell() { ProductData productToRun; switch (m_parser.products().size()) { case 0: // No specific product, use project-global environment. break; case 1: productToRun = productsToUse().values().front().front(); break; default: throw ErrorInfo(Tr::tr("The command '%1' cannot take more than one product.")); } RunEnvironment runEnvironment = m_projects.front().getRunEnvironment(productToRun, m_parser.installOptions(m_projects.front().profile()), QProcessEnvironment::systemEnvironment(), QStringList(), m_settings); return runEnvironment.doRunShell(); } BuildOptions CommandLineFrontend::buildOptions(const Project &project) const { BuildOptions options = m_parser.buildOptions(m_projects.front().profile()); if (options.maxJobCount() <= 0) { const QString profileName = project.profile(); QBS_CHECK(!profileName.isEmpty()); options.setMaxJobCount(Preferences(m_settings, profileName).jobs()); } return options; } QString CommandLineFrontend::buildDirectory(const QString &profileName) const { QString buildDir = m_parser.projectBuildDirectory(); if (buildDir.isEmpty()) { buildDir = Preferences(m_settings, profileName).defaultBuildDirectory(); if (buildDir.isEmpty()) { qbsDebug() << "No project build directory given; using current directory."; buildDir = QDir::currentPath(); } else { qbsDebug() << "No project build directory given; using directory from preferences."; } } QString projectName(QFileInfo(m_parser.projectFilePath()).baseName()); buildDir.replace(BuildDirectoryOption::magicProjectString(), projectName); QString projectDir(QFileInfo(m_parser.projectFilePath()).path()); buildDir.replace(BuildDirectoryOption::magicProjectDirString(), projectDir); if (!QFileInfo(buildDir).isAbsolute()) buildDir = QDir::currentPath() + QLatin1Char('/') + buildDir; buildDir = QDir::cleanPath(buildDir); return buildDir; } void CommandLineFrontend::build() { if (m_parser.products().empty()) { const Project::ProductSelection productSelection = m_parser.withNonDefaultProducts() ? Project::ProductSelectionWithNonDefault : Project::ProductSelectionDefaultOnly; for (const Project &project : qAsConst(m_projects)) m_buildJobs << project.buildAllProducts(buildOptions(project), productSelection, this); } else { const ProductMap &products = productsToUse(); for (ProductMap::ConstIterator it = products.begin(); it != products.end(); ++it) m_buildJobs.push_back(it.key().buildSomeProducts(it.value(), buildOptions(it.key()), this)); } connectBuildJobs(); /* * Progress reporting for the build jobs works as follows: We know that for every job, * the newTaskStarted() signal is emitted exactly once (unless there's an error). So we add up * the respective total efforts as they come in. Once all jobs have reported their total * efforts, we can start the overall progress report. */ m_buildEffortsNeeded = m_buildJobs.size(); m_buildEffortsRetrieved = 0; m_totalBuildEffort = 0; m_currentBuildEffort = 0; } void CommandLineFrontend::checkGeneratorName() { const QString generatorName = m_parser.generateOptions().generatorName(); m_generator = ProjectGeneratorManager::findGenerator(generatorName); if (m_generator) return; const auto generatorNames = ProjectGeneratorManager::loadedGeneratorNames(); if (!generatorNames.empty()) { const QString generatorNamesString = generatorNames.join(QLatin1String("\n\t")); if (!generatorName.isEmpty()) { throw ErrorInfo(Tr::tr("No generator named '%1'. Available generators:\n\t%2") .arg(generatorName, generatorNamesString)); } throw ErrorInfo(Tr::tr("No generator specified. Available generators:\n\t%1") .arg(generatorNamesString)); } throw ErrorInfo(Tr::tr("No generator specified or no generators are available.")); } void CommandLineFrontend::generate() { QBS_CHECK(!!m_generator); const ErrorInfo error = m_generator->generate(m_projects, m_parser.buildConfigurations(), m_parser.installOptions(QString()), m_parser.settingsDir(), ConsoleLogger::instance(m_settings)); if (error.hasError()) throw error; } int CommandLineFrontend::runTarget() { const ProductData productToRun = getTheOneRunnableProduct(); const QString executableFilePath = productToRun.targetExecutable(); if (executableFilePath.isEmpty()) { throw ErrorInfo(Tr::tr("Cannot run: Product '%1' is not an application.") .arg(productToRun.name())); } RunEnvironment runEnvironment = m_projects.front().getRunEnvironment(productToRun, m_parser.installOptions(m_projects.front().profile()), QProcessEnvironment::systemEnvironment(), m_parser.runEnvConfig(), m_settings); return runEnvironment.doRunTarget(executableFilePath, m_parser.runArgs(), m_parser.dryRun()); } void CommandLineFrontend::updateTimestamps() { const ProductMap &products = productsToUse(); for (ProductMap::ConstIterator it = products.constBegin(); it != products.constEnd(); ++it) { Project p = it.key(); p.updateTimestamps(it.value()); } } void CommandLineFrontend::dumpNodesTree() { QFile stdOut; stdOut.open(stdout, QIODevice::WriteOnly); const ErrorInfo error = m_projects.front().dumpNodesTree(stdOut, productsToUse() .value(m_projects.front())); if (error.hasError()) throw error; } void CommandLineFrontend::listProducts() { const QList products = productsToUse().constBegin().value(); QStringList output; for (const ProductData &p : products) { QString productInfo = p.fullDisplayName(); if (!p.isEnabled()) productInfo.append(QLatin1Char(' ')).append(Tr::tr("[disabled]")); else if (!p.properties().value(QStringLiteral("builtByDefault")).toBool()) productInfo.append(QLatin1Char(' ')).append(Tr::tr("[not built by default]")); output += productInfo; } output.sort(); qbsInfo() << output.join(QLatin1Char('\n')); } void CommandLineFrontend::connectBuildJobs() { for (AbstractJob * const job : qAsConst(m_buildJobs)) connectBuildJob(job); } void CommandLineFrontend::connectBuildJob(AbstractJob *job) { connectJob(job); BuildJob *bjob = qobject_cast(job); if (!bjob) return; connect(bjob, &BuildJob::reportCommandDescription, this, &CommandLineFrontend::handleCommandDescriptionReport); connect(bjob, &BuildJob::reportProcessResult, this, &CommandLineFrontend::handleProcessResultReport); } void CommandLineFrontend::connectJob(AbstractJob *job) { connect(job, &AbstractJob::finished, this, &CommandLineFrontend::handleJobFinished); connect(job, &AbstractJob::taskStarted, this, &CommandLineFrontend::handleNewTaskStarted); connect(job, &AbstractJob::totalEffortChanged, this, &CommandLineFrontend::handleTotalEffortChanged); if (m_parser.showProgress()) { connect(job, &AbstractJob::taskProgress, this, &CommandLineFrontend::handleTaskProgress); } } ProductData CommandLineFrontend::getTheOneRunnableProduct() { QBS_CHECK(m_projects.size() == 1); // Has been checked earlier. if (m_parser.products().size() == 1) { const auto products = m_projects.front().projectData().allProducts(); for (const ProductData &p : products) { if (p.name() == m_parser.products().constFirst()) return p; } QBS_CHECK(false); } QBS_CHECK(m_parser.products().size() == 0); QList runnableProducts; const auto products = m_projects.front().projectData().allProducts(); for (const ProductData &p : products) { if (p.isRunnable()) runnableProducts.push_back(p); } if (runnableProducts.size() == 1) return runnableProducts.front(); if (runnableProducts.empty()) { throw ErrorInfo(Tr::tr("Cannot execute command '%1': Project has no runnable product.") .arg(m_parser.commandName())); } ErrorInfo error(Tr::tr("Ambiguous use of command '%1': No product given, but project " "has more than one runnable product.").arg(m_parser.commandName())); error.append(Tr::tr("Use the '--products' option with one of the following products:")); for (const ProductData &p : qAsConst(runnableProducts)) { QString productRepr = QLatin1String("\t") + p.name(); if (p.profile() != m_projects.front().profile()) { productRepr.append(QLatin1String(" [")).append(p.profile()) .append(QLatin1Char(']')); } error.append(productRepr); } throw error; } void CommandLineFrontend::install() { Q_ASSERT(m_projects.size() == 1); const Project project = m_projects.front(); InstallJob *installJob; if (m_parser.products().empty()) { const Project::ProductSelection productSelection = m_parser.withNonDefaultProducts() ? Project::ProductSelectionWithNonDefault : Project::ProductSelectionDefaultOnly; installJob = project.installAllProducts(m_parser.installOptions(project.profile()), productSelection); } else { const Project project = m_projects.front(); const ProductMap products = productsToUse(); installJob = project.installSomeProducts(products.value(project), m_parser.installOptions(project.profile())); } connectJob(installJob); } } // namespace qbs qbs-src-1.13.1/src/app/qbs/commandlinefrontend.h000066400000000000000000000106001347155106100215020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef COMMANDLINEFRONTEND_H #define COMMANDLINEFRONTEND_H #include "parser/commandlineparser.h" #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QTimer; QT_END_NAMESPACE namespace qbs { class AbstractJob; class ConsoleProgressObserver; class ErrorInfo; class ProcessResult; class ProjectGenerator; class Settings; class CommandLineFrontend : public QObject { Q_OBJECT public: explicit CommandLineFrontend(const CommandLineParser &parser, Settings *settings, QObject *parent = nullptr); ~CommandLineFrontend(); void cancel(); void start(); private: void handleCommandDescriptionReport(const QString &highlight, const QString &message); void handleJobFinished(bool success, qbs::AbstractJob *job); void handleNewTaskStarted(const QString &description, int totalEffort); void handleTotalEffortChanged(int totalEffort); void handleTaskProgress(int value, qbs::AbstractJob *job); void handleProcessResultReport(const qbs::ProcessResult &result); void checkCancelStatus(); using ProductMap = QHash>; ProductMap productsToUse() const; bool resolvingMultipleProjects() const; bool isResolving() const; bool isBuilding() const; void handleProjectsResolved(); void makeClean(); int runShell(); void build(); void checkGeneratorName(); void generate(); int runTarget(); void updateTimestamps(); void dumpNodesTree(); void listProducts(); void connectBuildJobs(); void connectBuildJob(AbstractJob *job); void connectJob(AbstractJob *job); ProductData getTheOneRunnableProduct(); void install(); BuildOptions buildOptions(const Project &project) const; QString buildDirectory(const QString &profileName) const; const CommandLineParser &m_parser; Settings * const m_settings; QList m_resolveJobs; QList m_buildJobs; QList m_projects; ConsoleProgressObserver *m_observer; enum CancelStatus { CancelStatusNone, CancelStatusRequested, CancelStatusCanceling }; CancelStatus m_cancelStatus; QTimer * const m_cancelTimer; int m_buildEffortsNeeded; int m_buildEffortsRetrieved; int m_totalBuildEffort; int m_currentBuildEffort; QHash m_buildEfforts; std::shared_ptr m_generator; }; } // namespace qbs #endif // COMMANDLINEFRONTEND_H qbs-src-1.13.1/src/app/qbs/consoleprogressobserver.cpp000066400000000000000000000100741347155106100230130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "consoleprogressobserver.h" #include #include #include namespace qbs { void ConsoleProgressObserver::initialize(const QString &task, int max) { m_maximum = max; m_value = 0; m_percentage = 0; m_hashesPrinted = 0; std::cout << task.toLocal8Bit().constData() << ": 0%" << std::flush; setMaximum(max); } void ConsoleProgressObserver::setMaximum(int maximum) { m_maximum = maximum; if (maximum == 0) { m_percentage = 100; updateProgressBarIfNecessary(); writePercentageString(); std::cout << std::endl; } } void ConsoleProgressObserver::setProgressValue(int value) { if (value > m_maximum || value <= m_value) return; // TODO: Should be an assertion, but the executor currently breaks it. m_value = value; const int newPercentage = (100 * m_value) / m_maximum; if (newPercentage == m_percentage) return; eraseCurrentPercentageString(); m_percentage = newPercentage; updateProgressBarIfNecessary(); writePercentageString(); if (m_value == m_maximum) std::cout << std::endl; else std::cout << std::flush; } void ConsoleProgressObserver::eraseCurrentPercentageString() { const int charsToErase = m_percentage == 0 ? 2 : m_percentage < 10 ? 3 : 4; const QByteArray backspaceCommand(charsToErase, '\b'); // Move cursor before the old percentage string. std::cout << backspaceCommand.constData(); // Erase old percentage string. std::cout << QByteArray(charsToErase, ' ').constData(); // Move cursor before the erased string. std::cout << backspaceCommand.constData(); } void ConsoleProgressObserver::updateProgressBarIfNecessary() { static const int TotalHashCount = 50; // Should fit on most terminals without a line break. const int hashesNeeded = (m_percentage * TotalHashCount) / 100; if (m_hashesPrinted < hashesNeeded) { std::cout << QByteArray(hashesNeeded - m_hashesPrinted, '#').constData(); m_hashesPrinted = hashesNeeded; } } void ConsoleProgressObserver::writePercentageString() { std::cout << QStringLiteral(" %1%").arg(m_percentage).toLocal8Bit().constData(); } } // namespace qbs qbs-src-1.13.1/src/app/qbs/consoleprogressobserver.h000066400000000000000000000047751347155106100224730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CONSOLEPROGRESSOBSERVER_H #define CONSOLEPROGRESSOBSERVER_H #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { class ConsoleProgressObserver { public: void initialize(const QString &task, int max); void setMaximum(int maximum); void setProgressValue(int value); void incrementProgressValue() { setProgressValue(m_value + 1); } private: void eraseCurrentPercentageString(); void updateProgressBarIfNecessary(); void writePercentageString(); int m_maximum; int m_value; int m_percentage; int m_hashesPrinted; }; } // namespace qbs #endif // CONSOLEPROGRESSOBSERVER_H qbs-src-1.13.1/src/app/qbs/ctrlchandler.cpp000066400000000000000000000047341347155106100204670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "application.h" static void cancel() { qbs::Application * const app = qbs::Application::instance(); if (app) app->userInterrupt(); } #if defined(Q_OS_WIN) && defined(Q_CC_MSVC) #include static BOOL WINAPI consoleCtrlHandlerRoutine(__in DWORD dwCtrlType) { Q_UNUSED(dwCtrlType); cancel(); return TRUE; } void installCtrlCHandler() { SetConsoleCtrlHandler(&consoleCtrlHandlerRoutine, TRUE); } #else #include static void sigIntHandler(int sig) { Q_UNUSED(sig); cancel(); } void installCtrlCHandler() { signal(SIGINT, sigIntHandler); } #endif qbs-src-1.13.1/src/app/qbs/ctrlchandler.h000066400000000000000000000037061347155106100201320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CTRLCHANDLER_H #define CTRLCHANDLER_H void installCtrlCHandler(); #endif // CTRLCHANDLER_H qbs-src-1.13.1/src/app/qbs/main.cpp000066400000000000000000000066061347155106100167460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "application.h" #include "commandlinefrontend.h" #include "qbstool.h" #include "parser/commandlineparser.h" #include "../shared/logging/consolelogger.h" #include #include #include using namespace qbs; static bool tryToRunTool(const QStringList &arguments, int &exitCode) { if (arguments.empty()) return false; QStringList toolArgs = arguments; const QString toolName = toolArgs.takeFirst(); if (toolName.startsWith(QLatin1Char('-'))) return false; return QbsTool::tryToRunTool(toolName, toolArgs, &exitCode); } int main(int argc, char *argv[]) { ConsoleLogger::instance(); try { Application app(argc, argv); QStringList arguments = app.arguments(); arguments.removeFirst(); int toolExitCode = 0; if (tryToRunTool(arguments, toolExitCode)) return toolExitCode; CommandLineParser parser; if (!parser.parseCommandLine(arguments)) return EXIT_FAILURE; if (parser.command() == HelpCommandType) { parser.printHelp(); return 0; } Settings settings(parser.settingsDir()); ConsoleLogger::instance().setSettings(&settings); CommandLineFrontend clFrontend(parser, &settings); app.setCommandLineFrontend(&clFrontend); QTimer::singleShot(0, &clFrontend, &CommandLineFrontend::start); return app.exec(); } catch (const ErrorInfo &error) { qbsError() << error.toString(); return EXIT_FAILURE; } } qbs-src-1.13.1/src/app/qbs/parser/000077500000000000000000000000001347155106100166025ustar00rootroot00000000000000qbs-src-1.13.1/src/app/qbs/parser/commandlineoption.cpp000066400000000000000000000550251347155106100230340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineoption.h" #include #include #include #include #include namespace qbs { using namespace Internal; CommandLineOption::~CommandLineOption() { } void CommandLineOption::parse(CommandType command, const QString &representation, QStringList &input) { m_command = command; doParse(representation, input); } CommandLineOption::CommandLineOption() : m_command(static_cast(-1)) { } QString CommandLineOption::getArgument(const QString &representation, QStringList &input) { if (input.empty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': Missing argument.\nUsage: %2") .arg(representation, description(command()))); } return input.takeFirst(); } QString FileOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tUse as the project file.\n" "\tIf is a directory and it contains a single file ending in '.qbs',\n" "\tthat file will be used.\n" "\tIf this option is not given at all, behavior is the same as for '-f .'.\n") .arg(longRepresentation(), shortRepresentation()); } QString FileOption::shortRepresentation() const { return QStringLiteral("-f"); } QString FileOption::longRepresentation() const { return QStringLiteral("--file"); } void FileOption::doParse(const QString &representation, QStringList &input) { m_projectFilePath = getArgument(representation, input); } QString BuildDirectoryOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tBuild in the given directory. The default value is the current directory\n" "\tunless preferences.defaultBuildDirectory is set.\n" "\tRelative paths will be interpreted relative to the current directory.\n" "\tIf the directory does not exist, it will be created. Use the following\n" "\tspecial values as placeholders:\n" "\t%3: name of the project file excluding the extension\n" "\t%4: directory containing the project file\n") .arg(longRepresentation(), shortRepresentation(), magicProjectString(), magicProjectDirString()); } QString BuildDirectoryOption::shortRepresentation() const { return QStringLiteral("-d"); } QString BuildDirectoryOption::longRepresentation() const { return QStringLiteral("--build-directory"); } QString BuildDirectoryOption::magicProjectString() { return QStringLiteral("@project"); } QString BuildDirectoryOption::magicProjectDirString() { return QStringLiteral("@path"); } void BuildDirectoryOption::doParse(const QString &representation, QStringList &input) { m_projectBuildDirectory = getArgument(representation, input); } QString GeneratorOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tUse the given build system generator.\n") .arg(longRepresentation(), shortRepresentation()); } QString GeneratorOption::shortRepresentation() const { return QStringLiteral("-g"); } QString GeneratorOption::longRepresentation() const { return QStringLiteral("--generator"); } void GeneratorOption::doParse(const QString &representation, QStringList &input) { m_generatorName = getArgument(representation, input); if (m_generatorName.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': No generator given.\nUsage: %2") .arg(representation, description(command()))); } } static QString loglevelLongRepresentation() { return QStringLiteral("--log-level"); } QString VerboseOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tBe more verbose. Increases the log level by one.\n" "\tThis option can be given more than once.\n" "\tExcessive occurrences have no effect.\n" "\tIf option '%3' appears anywhere on the command line in addition\n" "\tto this option, its value is taken as the base which to increase.\n") .arg(longRepresentation(), shortRepresentation(), loglevelLongRepresentation()); } QString VerboseOption::shortRepresentation() const { return QStringLiteral("-v"); } QString VerboseOption::longRepresentation() const { return QStringLiteral("--more-verbose"); } QString QuietOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tBe more quiet. Decreases the log level by one.\n" "\tThis option can be given more than once.\n" "\tExcessive occurrences have no effect.\n" "\tIf option '%3' appears anywhere on the command line in addition\n" "\tto this option, its value is taken as the base which to decrease.\n") .arg(longRepresentation(), shortRepresentation(), loglevelLongRepresentation()); } QString QuietOption::shortRepresentation() const { return QStringLiteral("-q"); } QString QuietOption::longRepresentation() const { return QStringLiteral("--less-verbose"); } QString JobsOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tUse concurrent build jobs. must be an integer greater than zero.\n" "\tThe default is the number of cores.\n") .arg(longRepresentation(), shortRepresentation()); } QString JobsOption::shortRepresentation() const { return QStringLiteral("-j"); } QString JobsOption::longRepresentation() const { return QStringLiteral("--jobs"); } void JobsOption::doParse(const QString &representation, QStringList &input) { const QString jobCountString = getArgument(representation, input); bool stringOk; m_jobCount = jobCountString.toInt(&stringOk); if (!stringOk || m_jobCount <= 0) throw ErrorInfo(Tr::tr("Invalid use of option '%1': Illegal job count '%2'.\nUsage: %3") .arg(representation, jobCountString, description(command()))); } QString KeepGoingOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tKeep going when errors occur (if at all possible).\n") .arg(longRepresentation(), shortRepresentation()); } QString KeepGoingOption::shortRepresentation() const { return QStringLiteral("-k"); } QString KeepGoingOption::longRepresentation() const { return QStringLiteral("--keep-going"); } QString DryRunOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tDry run. No commands will be executed and no permanent changes to the\n" "\tbuild graph will be done.\n") .arg(longRepresentation(), shortRepresentation()); } QString DryRunOption::shortRepresentation() const { return QStringLiteral("-n"); } QString DryRunOption::longRepresentation() const { return QStringLiteral("--dry-run"); } QString ForceProbesOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n" "\tForce re-execution of all Probe items' configure scripts, rather than using the\n" "\tcached data.\n") .arg(longRepresentation()); } QString ForceProbesOption::longRepresentation() const { return QStringLiteral("--force-probe-execution"); } QString NoInstallOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n" "\tDo not install any artifacts as part of the build process.\n") .arg(longRepresentation()); } QString NoInstallOption::longRepresentation() const { return QStringLiteral("--no-install"); } static QString logTimeRepresentation() { return QStringLiteral("--log-time"); } QString ShowProgressOption::description(CommandType command) const { Q_UNUSED(command); QString desc = Tr::tr("%1\n" "\tShow a progress bar. Implies '%2=%3'.\n").arg(longRepresentation(), loglevelLongRepresentation(), logLevelName(LoggerMinLevel)); return desc += Tr::tr("\tThis option is mutually exclusive with '%1'.\n") .arg(logTimeRepresentation()); } static QString showProgressRepresentation() { return QStringLiteral("--show-progress"); } QString ShowProgressOption::longRepresentation() const { return showProgressRepresentation(); } void StringListOption::doParse(const QString &representation, QStringList &input) { m_arguments = getArgument(representation, input).split(QLatin1Char(',')); if (m_arguments.empty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': Argument list must not be empty.\n" "Usage: %2").arg(representation, description(command()))); } for (const QString &element : qAsConst(m_arguments)) { if (element.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': Argument list must not contain " "empty elements.\nUsage: %2") .arg(representation, description(command()))); } } } QString ChangedFilesOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 [,...]\n" "\tAssume these and only these files have changed.\n").arg(longRepresentation()); } QString ChangedFilesOption::longRepresentation() const { return QStringLiteral("--changed-files"); } QString ProductsOption::description(CommandType command) const { const QString prefix = Tr::tr("%1|%2").arg(longRepresentation(), shortRepresentation()); switch (command) { case InstallCommandType: case RunCommandType: case ShellCommandType: return Tr::tr("%1 \n\tUse the specified product.\n").arg(prefix); default: return Tr::tr("%1 [,...]\n" "\tTake only the specified products into account.\n").arg(prefix); } } QString ProductsOption::shortRepresentation() const { return QStringLiteral("-p"); } QString ProductsOption::longRepresentation() const { return QStringLiteral("--products"); } static QStringList allLogLevelStrings() { QStringList result; for (int i = static_cast(LoggerMinLevel); i <= static_cast(LoggerMaxLevel); ++i) result << logLevelName(static_cast(i)); return result; } LogLevelOption::LogLevelOption() : m_logLevel(defaultLogLevel()) { } QString LogLevelOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tUse the specified log level.\n" "\tPossible values are '%2'.\n" "\tThe default is '%3'.\n").arg(longRepresentation(), allLogLevelStrings().join(QLatin1String("', '")), logLevelName(defaultLogLevel())); } QString LogLevelOption::longRepresentation() const { return loglevelLongRepresentation(); } void LogLevelOption::doParse(const QString &representation, QStringList &input) { const QString levelString = getArgument(representation, input); const QList levels = QList() << LoggerError << LoggerWarning << LoggerInfo << LoggerDebug << LoggerTrace; for (const LoggerLevel &l : levels) { if (logLevelName(l) == levelString) { m_logLevel = l; return; } } throw ErrorInfo(Tr::tr("Invalid use of option '%1': Unknown log level '%2'.\nUsage: %3") .arg(representation, levelString, description(command()))); } QString ForceTimeStampCheckOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tForce timestamp checks.\n" "\tInstead of using the file timestamps that are stored in the build graph,\n" "\tretrieve the timestamps from the file system.\n").arg(longRepresentation()); } QString ForceTimeStampCheckOption::longRepresentation() const { return QStringLiteral("--check-timestamps"); } QString ForceOutputCheckOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tForce transformer output artifact checks.\n" "\tVerify that the output artifacts declared by rules in the\n" "\tproject are actually created.\n").arg(longRepresentation()); } QString ForceOutputCheckOption::longRepresentation() const { return QStringLiteral("--check-outputs"); } QString BuildNonDefaultOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tBuild all products, even if their builtByDefault property is false.\n") .arg(longRepresentation()); } QString BuildNonDefaultOption::longRepresentation() const { return QStringLiteral("--all-products"); } InstallRootOption::InstallRootOption() : m_useSysroot(false) { } static QString magicSysrootString() { return QStringLiteral("@sysroot"); } QString InstallRootOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tInstall into the given directory.\n" "\tThe default value is '/%2'.\n" "\tIf the directory does not exist, it will be created. Use the special\n" "\tvalue '%3' to install into the sysroot (i.e. the value of the\n" "\tproperty qbs.sysroot).\n") .arg(longRepresentation(), InstallOptions::defaultInstallRoot(), magicSysrootString()); } QString InstallRootOption::longRepresentation() const { return QStringLiteral("--install-root"); } void InstallRootOption::doParse(const QString &representation, QStringList &input) { if (input.empty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: Argument expected.\n" "Usage: %2").arg(representation, description(command()))); } const QString installRoot = input.takeFirst(); if (installRoot == magicSysrootString()) m_useSysroot = true; else m_installRoot = installRoot; } QString RemoveFirstOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tRemove the installation base directory before installing.\n") .arg(longRepresentation()); } QString RemoveFirstOption::longRepresentation() const { return QStringLiteral("--clean-install-root"); } QString NoBuildOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tDo not build before installing.\n") .arg(longRepresentation()); } QString NoBuildOption::longRepresentation() const { return QStringLiteral("--no-build"); } QString LogTimeOption::description(CommandType command) const { Q_UNUSED(command); QString desc = Tr::tr("%1\n\tLog the time that the operations involved in this command take.\n") .arg(longRepresentation()); desc += Tr::tr("\tThis option is implied in log levels '%1' and higher.\n") .arg(logLevelName(LoggerDebug)); return desc += Tr::tr("\tThis option is mutually exclusive with '%1'.\n") .arg(showProgressRepresentation()); } QString LogTimeOption::shortRepresentation() const { return QStringLiteral("-t"); } QString LogTimeOption::longRepresentation() const { return logTimeRepresentation(); } SettingsDirOption::SettingsDirOption() { } QString SettingsDirOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tRead all settings (such as profile information) from the given directory.\n" "\tThe default value is system-specific (see the QSettings documentation).\n" "\tIf the directory does not exist, it will be created.\n") .arg(longRepresentation()); } QString SettingsDirOption::longRepresentation() const { return QStringLiteral("--settings-dir"); } void SettingsDirOption::doParse(const QString &representation, QStringList &input) { if (input.empty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: Argument expected.\n" "Usage: %2").arg(representation, description(command()))); } m_settingsDir = input.takeFirst(); } QString JobLimitsOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 :[,:...]\n" "\tSet pool-specific job limits.\n").arg(longRepresentation()); } QString JobLimitsOption::longRepresentation() const { return QStringLiteral("--job-limits"); } void JobLimitsOption::doParse(const QString &representation, QStringList &input) { if (input.empty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: Argument expected.\n" "Usage: %2").arg(representation, description(command()))); } const QString jobLimitsSpec = input.takeFirst(); const QStringList jobLimitStrings = jobLimitsSpec.split(QLatin1Char(',')); for (const QString &jobLimitString : jobLimitStrings) { const int sepIndex = jobLimitString.indexOf(QLatin1Char(':')); if (sepIndex <= 0 || sepIndex == jobLimitString.size() - 1) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: " "Invalid job limits specification '%2'.\n" "Usage: %3").arg(representation, jobLimitsSpec, description(command()))); } const QString pool = jobLimitString.left(sepIndex); const QString limitString = jobLimitString.mid(sepIndex + 1); bool isValidNumber; const int limit = limitString.toInt(&isValidNumber); if (!isValidNumber) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: '%2' is not a number.\n" "Usage: %3").arg(representation, limitString, description(command()))); } m_jobLimits.setJobLimit(pool, limit); } } QString RespectProjectJobLimitsOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tGive maximum priority to job limits defined inside the project.\n") .arg(longRepresentation()); } QString RespectProjectJobLimitsOption::longRepresentation() const { return QStringLiteral("--enforce-project-job-limits"); } CommandEchoModeOption::CommandEchoModeOption() { } QString CommandEchoModeOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tKind of output to show when executing commands.\n" "\tPossible values are '%2'.\n" "\tThe default is '%3'.\n") .arg(longRepresentation(), allCommandEchoModeStrings().join(QLatin1String("', '")), commandEchoModeName(defaultCommandEchoMode())); } QString CommandEchoModeOption::longRepresentation() const { return QStringLiteral("--command-echo-mode"); } CommandEchoMode CommandEchoModeOption::commandEchoMode() const { return m_echoMode; } void CommandEchoModeOption::doParse(const QString &representation, QStringList &input) { const QString mode = getArgument(representation, input); if (mode.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': No command echo mode given.\nUsage: %2") .arg(representation, description(command()))); } if (!allCommandEchoModeStrings().contains(mode)) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': " "Invalid command echo mode '%2' given.\nUsage: %3") .arg(representation, mode, description(command()))); } m_echoMode = commandEchoModeFromName(mode); } QString WaitLockOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tWait indefinitely for other processes to release the build graph lock.\n") .arg(longRepresentation()); } QString WaitLockOption::longRepresentation() const { return QStringLiteral("--wait-lock"); } QString DisableFallbackProviderOption::description(CommandType) const { return Tr::tr("%1\n\tDo not fall back to pkg-config if a dependency is not found.\n") .arg(longRepresentation()); } QString DisableFallbackProviderOption::longRepresentation() const { return QStringLiteral("--no-fallback-module-provider"); } QString RunEnvConfigOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tComma-separated list of strings to pass to all modules' " "setupRunEnvironment scripts.\n").arg(longRepresentation()); } QString RunEnvConfigOption::longRepresentation() const { return QStringLiteral("--setup-run-env-config"); } } // namespace qbs qbs-src-1.13.1/src/app/qbs/parser/commandlineoption.h000066400000000000000000000310041347155106100224700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_COMMANDLINEOPTION_H #define QBS_COMMANDLINEOPTION_H #include "commandtype.h" #include #include #include namespace qbs { class CommandLineOption { public: enum Type { FileOptionType, BuildDirectoryOptionType, LogLevelOptionType, VerboseOptionType, QuietOptionType, JobsOptionType, KeepGoingOptionType, DryRunOptionType, ForceProbesOptionType, ShowProgressOptionType, ChangedFilesOptionType, ProductsOptionType, NoInstallOptionType, InstallRootOptionType, RemoveFirstOptionType, NoBuildOptionType, ForceTimestampCheckOptionType, ForceOutputCheckOptionType, BuildNonDefaultOptionType, LogTimeOptionType, CommandEchoModeOptionType, SettingsDirOptionType, JobLimitsOptionType, RespectProjectJobLimitsOptionType, GeneratorOptionType, WaitLockOptionType, RunEnvConfigOptionType, DisableFallbackProviderType, }; virtual ~CommandLineOption(); virtual QString description(CommandType command) const = 0; virtual QString shortRepresentation() const = 0; virtual QString longRepresentation() const = 0; virtual bool canAppearMoreThanOnce() const { return false; } void parse(CommandType command, const QString &representation, QStringList &input); protected: CommandLineOption(); QString getArgument(const QString &representation, QStringList &input); CommandType command() const { return m_command; } private: virtual void doParse(const QString &representation, QStringList &input) = 0; CommandType m_command; }; class FileOption : public CommandLineOption { public: QString projectFilePath() const { return m_projectFilePath; } private: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; void doParse(const QString &representation, QStringList &input) override; private: QString m_projectFilePath; }; class BuildDirectoryOption : public CommandLineOption { public: QString projectBuildDirectory() const { return m_projectBuildDirectory; } static QString magicProjectString(); static QString magicProjectDirString(); private: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; void doParse(const QString &representation, QStringList &input) override; private: QString m_projectBuildDirectory; }; class GeneratorOption : public CommandLineOption { public: QString generatorName() const { return m_generatorName; } private: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; void doParse(const QString &representation, QStringList &input) override; private: QString m_generatorName; }; class CountingOption : public CommandLineOption { public: int count() const { return m_count; } protected: CountingOption() : m_count(0) {} private: bool canAppearMoreThanOnce() const override{ return true; } void doParse(const QString &, QStringList &) override { ++m_count; } int m_count; }; class VerboseOption : public CountingOption { QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class QuietOption : public CountingOption { QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class JobsOption : public CommandLineOption { public: JobsOption() : m_jobCount(0) {} int jobCount() const { return m_jobCount; } private: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; void doParse(const QString &representation, QStringList &input) override; int m_jobCount; }; class OnOffOption : public CommandLineOption { public: bool enabled() const { return m_enabled; } protected: OnOffOption() : m_enabled(false) {} private: void doParse(const QString &, QStringList &) override { m_enabled = true; } bool m_enabled; }; class KeepGoingOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class DryRunOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class ForceProbesOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class NoInstallOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class ShowProgressOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class ForceTimeStampCheckOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class ForceOutputCheckOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class BuildNonDefaultOption : public OnOffOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class StringListOption : public CommandLineOption { public: QStringList arguments() const { return m_arguments; } private: void doParse(const QString &representation, QStringList &input) override; QStringList m_arguments; }; class ChangedFilesOption : public StringListOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class ProductsOption : public StringListOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class RunEnvConfigOption : public StringListOption { QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class LogLevelOption : public CommandLineOption { public: LogLevelOption(); int logLevel() const { return m_logLevel; } private: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; void doParse(const QString &representation, QStringList &input) override; int m_logLevel; }; class InstallRootOption : public CommandLineOption { public: InstallRootOption(); QString installRoot() const { return m_installRoot; } bool useSysroot() const { return m_useSysroot; } QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; private: void doParse(const QString &representation, QStringList &input) override; QString m_installRoot; bool m_useSysroot; }; class RemoveFirstOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class NoBuildOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class LogTimeOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override; QString longRepresentation() const override; }; class CommandEchoModeOption : public CommandLineOption { public: CommandEchoModeOption(); QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; CommandEchoMode commandEchoMode() const; private: void doParse(const QString &representation, QStringList &input) override; CommandEchoMode m_echoMode = CommandEchoModeInvalid; }; class SettingsDirOption : public CommandLineOption { public: SettingsDirOption(); QString settingsDir() const { return m_settingsDir; } QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; private: void doParse(const QString &representation, QStringList &input) override; QString m_settingsDir; }; class JobLimitsOption : public CommandLineOption { public: JobLimits jobLimits() const { return m_jobLimits; } QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; private: void doParse(const QString &representation, QStringList &input) override; JobLimits m_jobLimits; }; class RespectProjectJobLimitsOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class WaitLockOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; class DisableFallbackProviderOption : public OnOffOption { public: QString description(CommandType command) const override; QString shortRepresentation() const override { return {}; } QString longRepresentation() const override; }; } // namespace qbs #endif // QBS_COMMANDLINEOPTION_H qbs-src-1.13.1/src/app/qbs/parser/commandlineoptionpool.cpp000066400000000000000000000243771347155106100237340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineoptionpool.h" namespace qbs { CommandLineOptionPool::~CommandLineOptionPool() { qDeleteAll(m_options); } CommandLineOption *CommandLineOptionPool::getOption(CommandLineOption::Type type) const { CommandLineOption *& option = m_options[type]; if (!option) { switch (type) { case CommandLineOption::FileOptionType: option = new FileOption; break; case CommandLineOption::BuildDirectoryOptionType: option = new BuildDirectoryOption; break; case CommandLineOption::LogLevelOptionType: option = new LogLevelOption; break; case CommandLineOption::VerboseOptionType: option = new VerboseOption; break; case CommandLineOption::QuietOptionType: option = new QuietOption; break; case CommandLineOption::JobsOptionType: option = new JobsOption; break; case CommandLineOption::KeepGoingOptionType: option = new KeepGoingOption; break; case CommandLineOption::DryRunOptionType: option = new DryRunOption; break; case CommandLineOption::ForceProbesOptionType: option = new ForceProbesOption; break; case CommandLineOption::ShowProgressOptionType: option = new ShowProgressOption; break; case CommandLineOption::ChangedFilesOptionType: option = new ChangedFilesOption; break; case CommandLineOption::ProductsOptionType: option = new ProductsOption; break; case CommandLineOption::NoInstallOptionType: option = new NoInstallOption; break; case CommandLineOption::InstallRootOptionType: option = new InstallRootOption; break; case CommandLineOption::RemoveFirstOptionType: option = new RemoveFirstOption; break; case CommandLineOption::NoBuildOptionType: option = new NoBuildOption; break; case CommandLineOption::ForceTimestampCheckOptionType: option = new ForceTimeStampCheckOption; break; case CommandLineOption::ForceOutputCheckOptionType: option = new ForceOutputCheckOption; break; case CommandLineOption::BuildNonDefaultOptionType: option = new BuildNonDefaultOption; break; case CommandLineOption::LogTimeOptionType: option = new LogTimeOption; break; case CommandLineOption::CommandEchoModeOptionType: option = new CommandEchoModeOption; break; case CommandLineOption::SettingsDirOptionType: option = new SettingsDirOption; break; case CommandLineOption::JobLimitsOptionType: option = new JobLimitsOption; break; case CommandLineOption::RespectProjectJobLimitsOptionType: option = new RespectProjectJobLimitsOption; break; case CommandLineOption::GeneratorOptionType: option = new GeneratorOption; break; case CommandLineOption::WaitLockOptionType: option = new WaitLockOption; break; case CommandLineOption::DisableFallbackProviderType: option = new DisableFallbackProviderOption; break; case CommandLineOption::RunEnvConfigOptionType: option = new RunEnvConfigOption; break; default: qFatal("Unknown option type %d", type); } } return option; } FileOption *CommandLineOptionPool::fileOption() const { return static_cast(getOption(CommandLineOption::FileOptionType)); } BuildDirectoryOption *CommandLineOptionPool::buildDirectoryOption() const { return static_cast(getOption(CommandLineOption::BuildDirectoryOptionType)); } LogLevelOption *CommandLineOptionPool::logLevelOption() const { return static_cast(getOption(CommandLineOption::LogLevelOptionType)); } VerboseOption *CommandLineOptionPool::verboseOption() const { return static_cast(getOption(CommandLineOption::VerboseOptionType)); } QuietOption *CommandLineOptionPool::quietOption() const { return static_cast(getOption(CommandLineOption::QuietOptionType)); } ShowProgressOption *CommandLineOptionPool::showProgressOption() const { return static_cast(getOption(CommandLineOption::ShowProgressOptionType)); } DryRunOption *CommandLineOptionPool::dryRunOption() const { return static_cast(getOption(CommandLineOption::DryRunOptionType)); } ForceProbesOption *CommandLineOptionPool::forceProbesOption() const { return static_cast(getOption(CommandLineOption::ForceProbesOptionType)); } ChangedFilesOption *CommandLineOptionPool::changedFilesOption() const { return static_cast(getOption(CommandLineOption::ChangedFilesOptionType)); } KeepGoingOption *CommandLineOptionPool::keepGoingOption() const { return static_cast(getOption(CommandLineOption::KeepGoingOptionType)); } JobsOption *CommandLineOptionPool::jobsOption() const { return static_cast(getOption(CommandLineOption::JobsOptionType)); } ProductsOption *CommandLineOptionPool::productsOption() const { return static_cast(getOption(CommandLineOption::ProductsOptionType)); } NoInstallOption *CommandLineOptionPool::noInstallOption() const { return static_cast(getOption(CommandLineOption::NoInstallOptionType)); } InstallRootOption *CommandLineOptionPool::installRootOption() const { return static_cast(getOption(CommandLineOption::InstallRootOptionType)); } RemoveFirstOption *CommandLineOptionPool::removeFirstoption() const { return static_cast(getOption(CommandLineOption::RemoveFirstOptionType)); } NoBuildOption *CommandLineOptionPool::noBuildOption() const { return static_cast(getOption(CommandLineOption::NoBuildOptionType)); } ForceTimeStampCheckOption *CommandLineOptionPool::forceTimestampCheckOption() const { return static_cast( getOption(CommandLineOption::ForceTimestampCheckOptionType)); } ForceOutputCheckOption *CommandLineOptionPool::forceOutputCheckOption() const { return static_cast( getOption(CommandLineOption::ForceOutputCheckOptionType)); } BuildNonDefaultOption *CommandLineOptionPool::buildNonDefaultOption() const { return static_cast( getOption(CommandLineOption::BuildNonDefaultOptionType)); } LogTimeOption *CommandLineOptionPool::logTimeOption() const { return static_cast(getOption(CommandLineOption::LogTimeOptionType)); } CommandEchoModeOption *CommandLineOptionPool::commandEchoModeOption() const { return static_cast( getOption(CommandLineOption::CommandEchoModeOptionType)); } SettingsDirOption *CommandLineOptionPool::settingsDirOption() const { return static_cast(getOption(CommandLineOption::SettingsDirOptionType)); } JobLimitsOption *CommandLineOptionPool::jobLimitsOption() const { return static_cast(getOption(CommandLineOption::JobLimitsOptionType)); } RespectProjectJobLimitsOption *CommandLineOptionPool::respectProjectJobLimitsOption() const { return static_cast( getOption(CommandLineOption::RespectProjectJobLimitsOptionType)); } GeneratorOption *CommandLineOptionPool::generatorOption() const { return static_cast(getOption(CommandLineOption::GeneratorOptionType)); } WaitLockOption *CommandLineOptionPool::waitLockOption() const { return static_cast(getOption(CommandLineOption::WaitLockOptionType)); } DisableFallbackProviderOption *CommandLineOptionPool::disableFallbackProviderOption() const { return static_cast( getOption(CommandLineOption::DisableFallbackProviderType)); } RunEnvConfigOption *CommandLineOptionPool::runEnvConfigOption() const { return static_cast(getOption(CommandLineOption::RunEnvConfigOptionType)); } } // namespace qbs qbs-src-1.13.1/src/app/qbs/parser/commandlineoptionpool.h000066400000000000000000000072051347155106100233700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_COMMANDLINEOPTIONPOOL_H #define QBS_COMMANDLINEOPTIONPOOL_H #include "commandlineoption.h" #include namespace qbs { class CommandLineOptionPool { public: ~CommandLineOptionPool(); CommandLineOption *getOption(CommandLineOption::Type type) const; FileOption *fileOption() const; BuildDirectoryOption *buildDirectoryOption() const; LogLevelOption *logLevelOption() const; VerboseOption *verboseOption() const; QuietOption *quietOption() const; ShowProgressOption *showProgressOption() const; DryRunOption *dryRunOption() const; ForceProbesOption *forceProbesOption() const; ChangedFilesOption *changedFilesOption() const; KeepGoingOption *keepGoingOption() const; JobsOption *jobsOption() const; ProductsOption *productsOption() const; NoInstallOption *noInstallOption() const; InstallRootOption *installRootOption() const; RemoveFirstOption *removeFirstoption() const; NoBuildOption *noBuildOption() const; ForceTimeStampCheckOption *forceTimestampCheckOption() const; ForceOutputCheckOption *forceOutputCheckOption() const; BuildNonDefaultOption *buildNonDefaultOption() const; LogTimeOption *logTimeOption() const; CommandEchoModeOption *commandEchoModeOption() const; SettingsDirOption *settingsDirOption() const; JobLimitsOption *jobLimitsOption() const; RespectProjectJobLimitsOption *respectProjectJobLimitsOption() const; GeneratorOption *generatorOption() const; WaitLockOption *waitLockOption() const; DisableFallbackProviderOption *disableFallbackProviderOption() const; RunEnvConfigOption *runEnvConfigOption() const; private: mutable QHash m_options; }; } // namespace qbs #endif // QBS_COMMANDLINEOPTIONPOOL_H qbs-src-1.13.1/src/app/qbs/parser/commandlineparser.cpp000066400000000000000000000532541347155106100230220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include "commandlineoption.h" #include "commandlineoptionpool.h" #include "commandpool.h" #include "parsercommand.h" #include "../qbstool.h" #include "../../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_UNIX #include #endif namespace qbs { using Internal::Tr; class CommandLineParser::CommandLineParserPrivate { public: CommandLineParserPrivate(); void doParse(); Command *commandFromString(const QString &commandString) const; QList allCommands() const; QString generalHelp() const; void setupProjectFile(); void setupBuildDirectory(); void setupProgress(); void setupLogLevel(); void setupBuildOptions(); void setupBuildConfigurations(); bool checkForExistingBuildConfiguration(const QList &buildConfigs, const QString &configurationName); bool withNonDefaultProducts() const; bool dryRun() const; QString settingsDir() const { return optionPool.settingsDirOption()->settingsDir(); } CommandEchoMode echoMode() const; QString propertyName(const QString &aCommandLineName) const; QStringList commandLine; Command *command; QString projectFilePath; QString projectBuildDirectory; BuildOptions buildOptions; QList buildConfigurations; CommandLineOptionPool optionPool; CommandPool commandPool; bool showProgress; bool logTime; }; CommandLineParser::CommandLineParser() : d(nullptr) { } CommandLineParser::~CommandLineParser() { delete d; } void CommandLineParser::printHelp() const { QTextStream stream(stdout); Q_ASSERT(d->command == d->commandPool.getCommand(HelpCommandType)); const auto helpCommand = static_cast(d->command); if (helpCommand->commandToDescribe().isEmpty()) { stream << "Qbs " QBS_VERSION ", a cross-platform build tool.\n"; stream << d->generalHelp(); } else { const Command * const commandToDescribe = d->commandFromString(helpCommand->commandToDescribe()); if (commandToDescribe) { stream << commandToDescribe->longDescription(); } else if (!QbsTool::tryToRunTool(helpCommand->commandToDescribe(), QStringList(QStringLiteral("--help")))) { throw ErrorInfo(Tr::tr("No such command '%1'.\n%2") .arg(helpCommand->commandToDescribe(), d->generalHelp())); } } } CommandType CommandLineParser::command() const { return d->command->type(); } QString CommandLineParser::projectFilePath() const { return d->projectFilePath; } QString CommandLineParser::projectBuildDirectory() const { return d->projectBuildDirectory; } BuildOptions CommandLineParser::buildOptions(const QString &profile) const { Settings settings(settingsDir()); Preferences preferences(&settings, profile); if (d->buildOptions.maxJobCount() <= 0) { d->buildOptions.setMaxJobCount(preferences.jobs()); } if (d->buildOptions.echoMode() < 0) { d->buildOptions.setEchoMode(preferences.defaultEchoMode()); } return d->buildOptions; } CleanOptions CommandLineParser::cleanOptions(const QString &profile) const { CleanOptions options; options.setDryRun(buildOptions(profile).dryRun()); options.setKeepGoing(buildOptions(profile).keepGoing()); options.setLogElapsedTime(logTime()); return options; } GenerateOptions CommandLineParser::generateOptions() const { GenerateOptions options; options.setGeneratorName(d->optionPool.generatorOption()->generatorName()); return options; } InstallOptions CommandLineParser::installOptions(const QString &profile) const { InstallOptions options; options.setRemoveExistingInstallation(d->optionPool.removeFirstoption()->enabled()); options.setInstallRoot(d->optionPool.installRootOption()->installRoot()); options.setInstallIntoSysroot(d->optionPool.installRootOption()->useSysroot()); if (!options.installRoot().isEmpty()) { QFileInfo fi(options.installRoot()); if (!fi.isAbsolute()) options.setInstallRoot(fi.absoluteFilePath()); } options.setDryRun(buildOptions(profile).dryRun()); options.setKeepGoing(buildOptions(profile).keepGoing()); options.setLogElapsedTime(logTime()); return options; } bool CommandLineParser::forceTimestampCheck() const { return d->optionPool.forceTimestampCheckOption()->enabled(); } bool CommandLineParser::forceOutputCheck() const { return d->optionPool.forceOutputCheckOption()->enabled(); } bool CommandLineParser::dryRun() const { return d->dryRun(); } bool CommandLineParser::forceProbesExecution() const { return d->optionPool.forceProbesOption()->enabled(); } bool CommandLineParser::waitLockBuildGraph() const { return d->optionPool.waitLockOption()->enabled(); } bool CommandLineParser::disableFallbackProvider() const { return d->optionPool.disableFallbackProviderOption()->enabled(); } bool CommandLineParser::logTime() const { return d->logTime; } bool CommandLineParser::withNonDefaultProducts() const { return d->withNonDefaultProducts(); } bool CommandLineParser::buildBeforeInstalling() const { return !d->optionPool.noBuildOption()->enabled(); } QStringList CommandLineParser::runArgs() const { Q_ASSERT(d->command->type() == RunCommandType); return static_cast(d->command)->targetParameters(); } QStringList CommandLineParser::products() const { return d->optionPool.productsOption()->arguments(); } QStringList CommandLineParser::runEnvConfig() const { return d->optionPool.runEnvConfigOption()->arguments(); } bool CommandLineParser::showProgress() const { return d->showProgress; } bool CommandLineParser::showVersion() const { return d->command->type() == VersionCommandType; } QString CommandLineParser::settingsDir() const { return d->settingsDir(); } QString CommandLineParser::commandName() const { return d->command->representation(); } bool CommandLineParser::commandCanResolve() const { return d->command->canResolve(); } QString CommandLineParser::commandDescription() const { return d->command->longDescription(); } static QString getBuildConfigurationName(const QVariantMap &buildConfig) { return buildConfig.value(QStringLiteral("qbs.configurationName")).toString(); } QList CommandLineParser::buildConfigurations() const { return d->buildConfigurations; } bool CommandLineParser::parseCommandLine(const QStringList &args) { delete d; d = new CommandLineParserPrivate; d->commandLine = args; try { d->doParse(); return true; } catch (const ErrorInfo &error) { qbsError() << error.toString(); return false; } } CommandLineParser::CommandLineParserPrivate::CommandLineParserPrivate() : command(nullptr), commandPool(optionPool), showProgress(false), logTime(false) { } void CommandLineParser::CommandLineParserPrivate::doParse() { if (commandLine.empty()) { // No command given, use default. command = commandPool.getCommand(BuildCommandType); } else { command = commandFromString(commandLine.front()); if (command) { commandLine.removeFirst(); } else { // No command given. if (commandLine.front() == QLatin1String("-h") || commandLine.front() == QLatin1String("--help")) { command = commandPool.getCommand(HelpCommandType); commandLine.takeFirst(); } else if (commandLine.front() == QLatin1String("-V") || commandLine.front() == QLatin1String("--version")) { command = commandPool.getCommand(VersionCommandType); commandLine.takeFirst(); } else { command = commandPool.getCommand(BuildCommandType); } } } command->parse(commandLine); if (command->type() == HelpCommandType || command->type() == VersionCommandType) return; setupBuildDirectory(); setupBuildConfigurations(); setupProjectFile(); setupProgress(); setupLogLevel(); setupBuildOptions(); } Command *CommandLineParser::CommandLineParserPrivate::commandFromString(const QString &commandString) const { const auto commands = allCommands(); for (Command * const command : commands) { if (command->representation() == commandString) return command; } return nullptr; } QList CommandLineParser::CommandLineParserPrivate::allCommands() const { return {commandPool.getCommand(GenerateCommandType), commandPool.getCommand(ResolveCommandType), commandPool.getCommand(BuildCommandType), commandPool.getCommand(CleanCommandType), commandPool.getCommand(RunCommandType), commandPool.getCommand(ShellCommandType), commandPool.getCommand(StatusCommandType), commandPool.getCommand(UpdateTimestampsCommandType), commandPool.getCommand(InstallCommandType), commandPool.getCommand(DumpNodesTreeCommandType), commandPool.getCommand(ListProductsCommandType), commandPool.getCommand(VersionCommandType), commandPool.getCommand(HelpCommandType)}; } static QString extractToolDescription(const QString &tool, const QString &output) { if (tool == QLatin1String("create-project")) { // This command uses QCommandLineParser, where the description is not in the first line. const int eol1Pos = output.indexOf(QLatin1Char('\n')); const int eol2Pos = output.indexOf(QLatin1Char('\n'), eol1Pos + 1); return output.mid(eol1Pos + 1, eol2Pos - eol1Pos - 1); } return output.left(output.indexOf(QLatin1Char('\n'))); } QString CommandLineParser::CommandLineParserPrivate::generalHelp() const { QString help = Tr::tr("Usage: qbs [command] [command parameters]\n"); help += Tr::tr("Built-in commands:\n"); const int rhsIndentation = 30; // Sorting the commands by name is nicer for the user. QMap commandMap; const auto commands = allCommands(); for (const Command * command : commands) commandMap.insert(command->representation(), command); for (const Command * command : qAsConst(commandMap)) { help.append(QLatin1String(" ")).append(command->representation()); const QString whitespace = QString(rhsIndentation - 2 - command->representation().size(), QLatin1Char(' ')); help.append(whitespace).append(command->shortDescription()).append(QLatin1Char('\n')); } QStringList toolNames = QbsTool::allToolNames(); toolNames.sort(); if (!toolNames.empty()) { help.append(QLatin1Char('\n')).append(Tr::tr("Auxiliary commands:\n")); for (const QString &toolName : qAsConst(toolNames)) { help.append(QLatin1String(" ")).append(toolName); const QString whitespace = QString(rhsIndentation - 2 - toolName.size(), QLatin1Char(' ')); QbsTool tool; tool.runTool(toolName, QStringList(QStringLiteral("--help"))); if (tool.exitCode() != 0) continue; const QString shortDescription = extractToolDescription(toolName, tool.stdOut()); help.append(whitespace).append(shortDescription).append(QLatin1Char('\n')); } } return help; } void CommandLineParser::CommandLineParserPrivate::setupProjectFile() { projectFilePath = optionPool.fileOption()->projectFilePath(); } void CommandLineParser::CommandLineParserPrivate::setupBuildDirectory() { projectBuildDirectory = optionPool.buildDirectoryOption()->projectBuildDirectory(); } void CommandLineParser::CommandLineParserPrivate::setupBuildOptions() { buildOptions.setDryRun(dryRun()); QStringList changedFiles = optionPool.changedFilesOption()->arguments(); QDir currentDir; for (QString &file : changedFiles) file = QDir::fromNativeSeparators(currentDir.absoluteFilePath(file)); buildOptions.setChangedFiles(changedFiles); buildOptions.setKeepGoing(optionPool.keepGoingOption()->enabled()); buildOptions.setForceTimestampCheck(optionPool.forceTimestampCheckOption()->enabled()); buildOptions.setForceOutputCheck(optionPool.forceOutputCheckOption()->enabled()); const JobsOption * jobsOption = optionPool.jobsOption(); buildOptions.setMaxJobCount(jobsOption->jobCount()); buildOptions.setLogElapsedTime(logTime); buildOptions.setEchoMode(echoMode()); buildOptions.setInstall(!optionPool.noInstallOption()->enabled()); buildOptions.setRemoveExistingInstallation(optionPool.removeFirstoption()->enabled()); buildOptions.setJobLimits(optionPool.jobLimitsOption()->jobLimits()); buildOptions.setProjectJobLimitsTakePrecedence( optionPool.respectProjectJobLimitsOption()->enabled()); buildOptions.setSettingsDirectory(settingsDir()); } void CommandLineParser::CommandLineParserPrivate::setupBuildConfigurations() { // first: configuration name, second: properties. // Empty configuration name used for global properties. using PropertyListItem = std::pair; QList propertiesPerConfiguration; const QString configurationNameKey = QStringLiteral("qbs.configurationName"); QString currentConfigurationName; QVariantMap currentProperties; const auto args = command->additionalArguments(); for (const QString &arg : args) { const int sepPos = arg.indexOf(QLatin1Char(':')); QBS_CHECK(sepPos > 0); const QString key = arg.left(sepPos); const QString rawValue = arg.mid(sepPos + 1); if (key == QLatin1String("config") || key == configurationNameKey) { propertiesPerConfiguration.push_back(std::make_pair(currentConfigurationName, currentProperties)); currentConfigurationName = rawValue; currentProperties.clear(); continue; } currentProperties.insert(propertyName(key), representationToSettingsValue(rawValue)); } propertiesPerConfiguration.push_back(std::make_pair(currentConfigurationName, currentProperties)); if (propertiesPerConfiguration.size() == 1) // No configuration name specified on command line. propertiesPerConfiguration.push_back(PropertyListItem(QStringLiteral("default"), QVariantMap())); const QVariantMap globalProperties = propertiesPerConfiguration.takeFirst().second; QList buildConfigs; for (const PropertyListItem &item : qAsConst(propertiesPerConfiguration)) { QVariantMap properties = item.second; for (QVariantMap::ConstIterator globalPropIt = globalProperties.constBegin(); globalPropIt != globalProperties.constEnd(); ++globalPropIt) { if (!properties.contains(globalPropIt.key())) properties.insert(globalPropIt.key(), globalPropIt.value()); } const QString configurationName = item.first; if (checkForExistingBuildConfiguration(buildConfigs, configurationName)) { qbsWarning() << Tr::tr("Ignoring redundant request to build for configuration '%1'.") .arg(configurationName); continue; } properties.insert(configurationNameKey, configurationName); buildConfigs.push_back(properties); } buildConfigurations = buildConfigs; } void CommandLineParser::CommandLineParserPrivate::setupProgress() { const ShowProgressOption * const option = optionPool.showProgressOption(); showProgress = option->enabled(); #ifdef Q_OS_UNIX if (showProgress && !isatty(STDOUT_FILENO)) { showProgress = false; qbsWarning() << Tr::tr("Ignoring option '%1', because standard output is " "not connected to a terminal.").arg(option->longRepresentation()); } #endif } void CommandLineParser::CommandLineParserPrivate::setupLogLevel() { const LogLevelOption * const logLevelOption = optionPool.logLevelOption(); const VerboseOption * const verboseOption = optionPool.verboseOption(); const QuietOption * const quietOption = optionPool.quietOption(); int logLevel = logLevelOption->logLevel(); logLevel += verboseOption->count(); logLevel -= quietOption->count(); if (showProgress && logLevel != LoggerMinLevel) { const bool logLevelWasSetByUser = logLevelOption->logLevel() != defaultLogLevel() || verboseOption->count() > 0 || quietOption->count() > 0; if (logLevelWasSetByUser) { qbsInfo() << Tr::tr("Setting log level to '%1', because option '%2'" " has been given.").arg(logLevelName(LoggerMinLevel), optionPool.showProgressOption()->longRepresentation()); } logLevel = LoggerMinLevel; } if (logLevel < LoggerMinLevel) { qbsWarning() << Tr::tr("Cannot decrease log level as much as specified; using '%1'.") .arg(logLevelName(LoggerMinLevel)); logLevel = LoggerMinLevel; } else if (logLevel > LoggerMaxLevel) { qbsWarning() << Tr::tr("Cannot increase log level as much as specified; using '%1'.") .arg(logLevelName(LoggerMaxLevel)); logLevel = LoggerMaxLevel; } logTime = optionPool.logTimeOption()->enabled(); if (showProgress && logTime) { qbsWarning() << Tr::tr("Options '%1' and '%2' are incompatible. Ignoring '%2'.") .arg(optionPool.showProgressOption()->longRepresentation(), optionPool.logTimeOption()->longRepresentation()); logTime = false; } ConsoleLogger::instance().logSink()->setLogLevel(static_cast(logLevel)); } QString CommandLineParser::CommandLineParserPrivate::propertyName(const QString &aCommandLineName) const { // Make fully-qualified, ie "platform" -> "qbs.platform" if (aCommandLineName.contains(QLatin1Char('.'))) return aCommandLineName; else return QLatin1String("qbs.") + aCommandLineName; } bool CommandLineParser::CommandLineParserPrivate::checkForExistingBuildConfiguration( const QList &buildConfigs, const QString &configurationName) { for (const QVariantMap &buildConfig : buildConfigs) { if (configurationName == getBuildConfigurationName(buildConfig)) return true; } return false; } bool CommandLineParser::CommandLineParserPrivate::withNonDefaultProducts() const { if (command->type() == GenerateCommandType) return true; return optionPool.buildNonDefaultOption()->enabled(); } bool CommandLineParser::CommandLineParserPrivate::dryRun() const { if (command->type() == GenerateCommandType || command->type() == ListProductsCommandType) return true; return optionPool.dryRunOption()->enabled(); } CommandEchoMode CommandLineParser::CommandLineParserPrivate::echoMode() const { if (command->type() == GenerateCommandType) return CommandEchoModeSilent; if (optionPool.commandEchoModeOption()->commandEchoMode() < CommandEchoModeInvalid) return optionPool.commandEchoModeOption()->commandEchoMode(); return defaultCommandEchoMode(); } } // namespace qbs qbs-src-1.13.1/src/app/qbs/parser/commandlineparser.h000066400000000000000000000067111347155106100224630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_COMMANDLINEPARSER_H #define QBS_COMMANDLINEPARSER_H #include "commandtype.h" #include #include namespace qbs { class BuildOptions; class CleanOptions; class GenerateOptions; class InstallOptions; class Settings; class CommandLineParser { Q_DISABLE_COPY(CommandLineParser) public: CommandLineParser(); ~CommandLineParser(); bool parseCommandLine(const QStringList &args); void printHelp() const; CommandType command() const; QString commandName() const; bool commandCanResolve() const; QString commandDescription() const; QString projectFilePath() const; QString projectBuildDirectory() const; BuildOptions buildOptions(const QString &profile) const; CleanOptions cleanOptions(const QString &profile) const; GenerateOptions generateOptions() const; InstallOptions installOptions(const QString &profile) const; bool forceTimestampCheck() const; bool forceOutputCheck() const; bool dryRun() const; bool forceProbesExecution() const; bool waitLockBuildGraph() const; bool disableFallbackProvider() const; bool logTime() const; bool withNonDefaultProducts() const; bool buildBeforeInstalling() const; QStringList runArgs() const; QStringList products() const; QStringList runEnvConfig() const; QList buildConfigurations() const; bool showProgress() const; bool showVersion() const; QString settingsDir() const; private: class CommandLineParserPrivate; CommandLineParserPrivate *d; }; } // namespace qbs #endif // QBS_COMMANDLINEPARSER_H qbs-src-1.13.1/src/app/qbs/parser/commandpool.cpp000066400000000000000000000072331347155106100216230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandpool.h" #include "parsercommand.h" namespace qbs { CommandPool::CommandPool(CommandLineOptionPool &optionPool) : m_optionPool(optionPool) { } CommandPool::~CommandPool() { qDeleteAll(m_commands); } qbs::Command *CommandPool::getCommand(CommandType type) const { Command *& command = m_commands[type]; if (!command) { switch (type) { case ResolveCommandType: command = new ResolveCommand(m_optionPool); break; case GenerateCommandType: command = new GenerateCommand(m_optionPool); break; case BuildCommandType: command = new BuildCommand(m_optionPool); break; case CleanCommandType: command = new CleanCommand(m_optionPool); break; case RunCommandType: command = new RunCommand(m_optionPool); break; case ShellCommandType: command = new ShellCommand(m_optionPool); break; case StatusCommandType: command = new StatusCommand(m_optionPool); break; case UpdateTimestampsCommandType: command = new UpdateTimestampsCommand(m_optionPool); break; case InstallCommandType: command = new InstallCommand(m_optionPool); break; case DumpNodesTreeCommandType: command = new DumpNodesTreeCommand(m_optionPool); break; case ListProductsCommandType: command = new ListProductsCommand(m_optionPool); break; case HelpCommandType: command = new HelpCommand(m_optionPool); break; case VersionCommandType: command = new VersionCommand(m_optionPool); break; } } return command; } } // namespace qbs qbs-src-1.13.1/src/app/qbs/parser/commandpool.h000066400000000000000000000045321347155106100212670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_COMMANDPOOL_H #define QBS_COMMANDPOOL_H #include "commandtype.h" #include namespace qbs { class Command; class CommandLineOptionPool; class CommandPool { Q_DISABLE_COPY(CommandPool) public: CommandPool(CommandLineOptionPool &optionPool); ~CommandPool(); Command *getCommand(CommandType type) const; private: CommandLineOptionPool &m_optionPool; mutable QHash m_commands; }; } // namespace qbs #endif // QBS_COMMANDPOOL_H qbs-src-1.13.1/src/app/qbs/parser/commandtype.h000066400000000000000000000043741347155106100213030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef COMMANDTYPE_H #define COMMANDTYPE_H namespace qbs { enum CommandType { ResolveCommandType, BuildCommandType, CleanCommandType, RunCommandType, ShellCommandType, StatusCommandType, UpdateTimestampsCommandType, DumpNodesTreeCommandType, InstallCommandType, HelpCommandType, GenerateCommandType, ListProductsCommandType, VersionCommandType, }; } // namespace qbs #endif // COMMANDTYPE_H qbs-src-1.13.1/src/app/qbs/parser/parser.pri000066400000000000000000000006251347155106100206150ustar00rootroot00000000000000SOURCES += \ $$PWD/commandlineparser.cpp \ $$PWD/commandpool.cpp \ $$PWD/commandlineoption.cpp \ $$PWD/commandlineoptionpool.cpp \ $$PWD/parsercommand.cpp HEADERS += \ $$PWD/commandlineparser.h \ $$PWD/commandpool.h \ $$PWD/commandlineoption.h \ $$PWD/commandlineoptionpool.h \ $$PWD/commandtype.h \ $$PWD/parsercommand.h include(../../../../qbs_version.pri) qbs-src-1.13.1/src/app/qbs/parser/parsercommand.cpp000066400000000000000000000475561347155106100221620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "parsercommand.h" #include "commandlineoption.h" #include "commandlineoptionpool.h" #include #include #include #include #include #include #include namespace qbs { using namespace Internal; Command::~Command() { } void Command::parse(QStringList &input) { while (!input.empty()) parseNext(input); } bool Command::canResolve() const { return supportedOptions().contains(CommandLineOption::FileOptionType); } void Command::parsePropertyAssignment(const QString &argument) { const auto throwError = [argument](const QString &msgTemplate) { ErrorInfo error(msgTemplate.arg(argument)); error.append(QLatin1String("Expected an assignment of the form :, " "profile: or config:.")); throw error; }; if (argument.startsWith(QLatin1Char('-'))) throwError(Tr::tr("Unexpected option '%1'.")); const int sepPos = argument.indexOf(QLatin1Char(':')); if (sepPos == -1) throwError(Tr::tr("Unexpected command line parameter '%1'.")); if (sepPos == 0) throwError(Tr::tr("Empty key not allowed in assignment '%1'.")); if (!canResolve() && argument.contains(QLatin1Char(':')) && !argument.startsWith(QLatin1String("config:"))) { throw ErrorInfo(Tr::tr("The '%1' command does not support property assignments.") .arg(representation())); } m_additionalArguments << argument; } QList Command::actualSupportedOptions() const { QList options = supportedOptions(); if (type() != HelpCommandType) options.push_back(CommandLineOption::SettingsDirOptionType); // Valid for almost all commands. return options; } void Command::parseOption(QStringList &input) { const QString optionString = input.front(); QBS_CHECK(optionString.startsWith(QLatin1Char('-'))); input.removeFirst(); if (optionString.size() == 1) throwError(Tr::tr("Empty options are not allowed.")); // Split up grouped short options. if (optionString.at(1) != QLatin1Char('-') && optionString.size() > 2) { QString parameter; for (int i = optionString.size(); --i > 0;) { const QChar c = optionString.at(i); if (c.isDigit()) { parameter.prepend(c); } else { if (!parameter.isEmpty()) { input.prepend(parameter); parameter.clear(); } input.prepend(QLatin1Char('-') + c); } } if (!parameter.isEmpty()) throwError(Tr::tr("Unknown numeric option '%1'.").arg(parameter)); return; } bool matchFound = false; const auto optionTypes = actualSupportedOptions(); for (const CommandLineOption::Type optionType : optionTypes) { CommandLineOption * const option = optionPool().getOption(optionType); if (option->shortRepresentation() != optionString && option->longRepresentation() != optionString) { continue; } if (contains(m_usedOptions, option) && !option->canAppearMoreThanOnce()) throwError(Tr::tr("Option '%1' cannot appear more than once.").arg(optionString)); option->parse(type(), optionString, input); m_usedOptions.insert(option); matchFound = true; break; } if (!matchFound) throwError(Tr::tr("Unknown option '%1'.").arg(optionString)); } void Command::parseNext(QStringList &input) { QBS_CHECK(!input.empty()); if (input.front().startsWith(QLatin1Char('-'))) parseOption(input); else parsePropertyAssignment(input.takeFirst()); } QString Command::supportedOptionsDescription() const { // Sorting the options by name is nicer for the user. QMap optionMap; const auto opTypes = actualSupportedOptions(); for (const CommandLineOption::Type opType : opTypes) { const CommandLineOption * const option = optionPool().getOption(opType); optionMap.insert(option->longRepresentation(), option); } QString s = Tr::tr("The possible options are:\n"); for (const CommandLineOption *option : qAsConst(optionMap)) s += option->description(type()); return s; } void Command::throwError(const QString &reason) { ErrorInfo error(Tr::tr("Invalid use of command '%1': %2").arg(representation(), reason)); error.append(Tr::tr("Type 'qbs help %1' to see how to use this command.") .arg(representation())); throw error; } QString ResolveCommand::shortDescription() const { return Tr::tr("Resolve a project without building it."); } QString ResolveCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [[config:] [:] ...] ...\n") .arg(representation()); description += Tr::tr("Resolves a project in one or more configuration(s).\n"); return description += supportedOptionsDescription(); } QString ResolveCommand::representation() const { return QStringLiteral("resolve"); } static QList resolveOptions() { return {CommandLineOption::FileOptionType, CommandLineOption::BuildDirectoryOptionType, CommandLineOption::LogLevelOptionType, CommandLineOption::VerboseOptionType, CommandLineOption::QuietOptionType, CommandLineOption::ShowProgressOptionType, CommandLineOption::DryRunOptionType, CommandLineOption::ForceProbesOptionType, CommandLineOption::LogTimeOptionType, CommandLineOption::DisableFallbackProviderType}; } QList ResolveCommand::supportedOptions() const { return resolveOptions(); } QString GenerateCommand::shortDescription() const { return Tr::tr("Generate project files for another build tool."); } QString GenerateCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [[config:] [:] ...] ...\n") .arg(representation()); description += Tr::tr("Generates files to build the project using another build tool.\n"); return description += supportedOptionsDescription(); } QString GenerateCommand::representation() const { return QStringLiteral("generate"); } QList GenerateCommand::supportedOptions() const { return {CommandLineOption::FileOptionType, CommandLineOption::BuildDirectoryOptionType, CommandLineOption::LogLevelOptionType, CommandLineOption::VerboseOptionType, CommandLineOption::QuietOptionType, CommandLineOption::ShowProgressOptionType, CommandLineOption::InstallRootOptionType, CommandLineOption::LogTimeOptionType, CommandLineOption::GeneratorOptionType}; } QString BuildCommand::shortDescription() const { return Tr::tr("Build (parts of) a project. This is the default command."); } QString BuildCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [[config:] [:] ...] ...\n") .arg(representation()); description += Tr::tr("Builds a project in one or more configuration(s).\n"); return description += supportedOptionsDescription(); } static QString buildCommandRepresentation() { return QStringLiteral("build"); } QString BuildCommand::representation() const { return buildCommandRepresentation(); } static QList buildOptions() { QList options = resolveOptions(); return options << CommandLineOption::KeepGoingOptionType << CommandLineOption::ProductsOptionType << CommandLineOption::ChangedFilesOptionType << CommandLineOption::ForceTimestampCheckOptionType << CommandLineOption::ForceOutputCheckOptionType << CommandLineOption::BuildNonDefaultOptionType << CommandLineOption::JobsOptionType << CommandLineOption::CommandEchoModeOptionType << CommandLineOption::NoInstallOptionType << CommandLineOption::RemoveFirstOptionType << CommandLineOption::JobLimitsOptionType << CommandLineOption::RespectProjectJobLimitsOptionType << CommandLineOption::WaitLockOptionType; } QList BuildCommand::supportedOptions() const { return buildOptions(); } QString CleanCommand::shortDescription() const { return Tr::tr("Remove the files generated during a build."); } QString CleanCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [config:] ...\n") .arg(representation()); description += Tr::tr("Removes build artifacts for the given configuration(s).\n"); return description += supportedOptionsDescription(); } QString CleanCommand::representation() const { return QStringLiteral("clean"); } QList CleanCommand::supportedOptions() const { return {CommandLineOption::BuildDirectoryOptionType, CommandLineOption::DryRunOptionType, CommandLineOption::KeepGoingOptionType, CommandLineOption::LogTimeOptionType, CommandLineOption::ProductsOptionType, CommandLineOption::QuietOptionType, CommandLineOption::SettingsDirOptionType, CommandLineOption::ShowProgressOptionType, CommandLineOption::VerboseOptionType}; } QString InstallCommand::shortDescription() const { return Tr::tr("Install (parts of) a project."); } QString InstallCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [[config:] [:] ...]\n") .arg(representation()); description += Tr::tr("Install all files marked as installable " "to their respective destinations.\n" "The project is built first, if necessary, unless the '%1' option " "is given.\n").arg(optionPool().noBuildOption()->longRepresentation()); return description += supportedOptionsDescription(); } QString InstallCommand::representation() const { return QStringLiteral("install"); } QList installOptions() { QList options = buildOptions() << CommandLineOption::InstallRootOptionType << CommandLineOption::NoBuildOptionType; options.removeOne(CommandLineOption::NoInstallOptionType); return options; } QList InstallCommand::supportedOptions() const { return installOptions(); } QString RunCommand::shortDescription() const { return QStringLiteral("Run an executable generated by building a project."); } QString RunCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [config:] [:] ... " "[ -- ]\n").arg(representation()); description += Tr::tr("Run the specified product's executable with the specified arguments.\n"); description += Tr::tr("If the project has only one product, the '%1' option may be omitted.\n") .arg(optionPool().productsOption()->longRepresentation()); description += Tr::tr("The product will be built if it is not up to date; " "see the '%2' command.\n").arg(buildCommandRepresentation()); return description += supportedOptionsDescription(); } QString RunCommand::representation() const { return QStringLiteral("run"); } QList RunCommand::supportedOptions() const { return QList() << installOptions() << CommandLineOption::RunEnvConfigOptionType; } void RunCommand::parseNext(QStringList &input) { QBS_CHECK(!input.empty()); if (input.front() != QLatin1String("--")) { Command::parseNext(input); return; } input.removeFirst(); m_targetParameters = input; input.clear(); } QString ShellCommand::shortDescription() const { return Tr::tr("Open a shell with a product's environment."); } QString ShellCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [config:] [:] ...\n") .arg(representation()); description += Tr::tr("Opens a shell in the same environment that a build with the given " "parameters would use.\n"); return description += supportedOptionsDescription(); } QString ShellCommand::representation() const { return QStringLiteral("shell"); } QList ShellCommand::supportedOptions() const { return {CommandLineOption::FileOptionType, CommandLineOption::BuildDirectoryOptionType, CommandLineOption::ProductsOptionType}; } QString StatusCommand::shortDescription() const { return Tr::tr("Show the status of files in the project directory."); } QString StatusCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [config:]\n") .arg(representation()); description += Tr::tr("Lists all the files in the project directory and shows whether " "they are known to qbs in the respective configuration.\n"); return description += supportedOptionsDescription(); } QString StatusCommand::representation() const { return QStringLiteral("status"); } QList StatusCommand::supportedOptions() const { return {CommandLineOption::BuildDirectoryOptionType}; } QString UpdateTimestampsCommand::shortDescription() const { return Tr::tr("Mark the build as up to date."); } QString UpdateTimestampsCommand::longDescription() const { QString description = Tr::tr( "qbs %1 [options] [config:] ...\n") .arg(representation()); description += Tr::tr("Update the timestamps of all build artifacts, causing the next " "builds of the project to do nothing if no updates to source files happen in between.\n" "This functionality is useful if you know that the current changes to source files " "are irrelevant to the build.\n" "NOTE: Doing this causes a discrepancy between the \"real world\" and the information " "in the build graph, so use with care.\n"); return description += supportedOptionsDescription(); } QString UpdateTimestampsCommand::representation() const { return QStringLiteral("update-timestamps"); } QList UpdateTimestampsCommand::supportedOptions() const { return {CommandLineOption::BuildDirectoryOptionType, CommandLineOption::LogLevelOptionType, CommandLineOption::VerboseOptionType, CommandLineOption::QuietOptionType, CommandLineOption::ProductsOptionType}; } QString DumpNodesTreeCommand::shortDescription() const { return Tr::tr("Dumps the nodes in the build graph to stdout."); } QString DumpNodesTreeCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [config:] ...\n") .arg(representation()); description += Tr::tr("Internal command; for debugging purposes only.\n"); return description += supportedOptionsDescription(); } QString DumpNodesTreeCommand::representation() const { return QStringLiteral("dump-nodes-tree"); } QList DumpNodesTreeCommand::supportedOptions() const { return {CommandLineOption::BuildDirectoryOptionType, CommandLineOption::ProductsOptionType}; } QString ListProductsCommand::shortDescription() const { return Tr::tr("Lists all products in the project, including sub-projects."); } QString ListProductsCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [[config:] " "[:] ...] ...\n").arg(representation()); return description += supportedOptionsDescription(); } QString ListProductsCommand::representation() const { return QStringLiteral("list-products"); } QList ListProductsCommand::supportedOptions() const { return {CommandLineOption::FileOptionType, CommandLineOption::BuildDirectoryOptionType}; } QString HelpCommand::shortDescription() const { return Tr::tr("Show general or command-specific help."); } QString HelpCommand::longDescription() const { QString description = Tr::tr("qbs %1 []\n").arg(representation()); return description += Tr::tr("Shows either the general help or a description of " "the given command.\n"); } QString HelpCommand::representation() const { return QStringLiteral("help"); } QList HelpCommand::supportedOptions() const { return {}; } void HelpCommand::parseNext(QStringList &input) { if (input.empty()) return; if (input.size() > 1) throwError(Tr::tr("Cannot describe more than one command.")); m_command = input.takeFirst(); QBS_CHECK(input.empty()); } QString VersionCommand::shortDescription() const { return Tr::tr("Print the Qbs version number to stdout."); } QString VersionCommand::longDescription() const { QString description = Tr::tr("qbs %1\n").arg(representation()); return description += Tr::tr("%1\n").arg(shortDescription()); } QString VersionCommand::representation() const { return QStringLiteral("show-version"); } QList VersionCommand::supportedOptions() const { return {}; } void VersionCommand::parseNext(QStringList &input) { QBS_CHECK(!input.empty()); throwError(Tr::tr("This command takes no arguments.")); } } // namespace qbs qbs-src-1.13.1/src/app/qbs/parser/parsercommand.h000066400000000000000000000217211347155106100216110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PARSER_COMMAND_H #define QBS_PARSER_COMMAND_H #include "commandlineoption.h" #include "commandtype.h" #include namespace qbs { class CommandLineOptionPool; class Command { public: virtual ~Command(); virtual CommandType type() const = 0; virtual QString shortDescription() const = 0; virtual QString longDescription() const = 0; virtual QString representation() const = 0; void parse(QStringList &input); QStringList additionalArguments() const { return m_additionalArguments; } bool canResolve() const; protected: Command(CommandLineOptionPool &optionPool) : m_optionPool(optionPool) {} const CommandLineOptionPool &optionPool() const { return m_optionPool; } QString supportedOptionsDescription() const; [[noreturn]] void throwError(const QString &reason); virtual void parseNext(QStringList &input); private: QList actualSupportedOptions() const; void parseOption(QStringList &input); void parsePropertyAssignment(const QString &argument); virtual QList supportedOptions() const = 0; QStringList m_additionalArguments; std::set m_usedOptions; const CommandLineOptionPool &m_optionPool; }; class ResolveCommand : public Command { public: ResolveCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return ResolveCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class GenerateCommand : public Command { public: GenerateCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return GenerateCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class BuildCommand : public Command { public: BuildCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return BuildCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class CleanCommand : public Command { public: CleanCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return CleanCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class InstallCommand : public Command { public: InstallCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return InstallCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class RunCommand : public Command { public: RunCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} QStringList targetParameters() const { return m_targetParameters; } private: CommandType type() const override { return RunCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; void parseNext(QStringList &input) override; QStringList m_targetParameters; }; class ShellCommand : public Command { public: ShellCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return ShellCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; // TODO: It seems wrong that a configuration has to be given here. Ideally, this command would just track *all* files regardless of conditions. Is that possible? class StatusCommand : public Command { public: StatusCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return StatusCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class UpdateTimestampsCommand : public Command { public: UpdateTimestampsCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return UpdateTimestampsCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class DumpNodesTreeCommand : public Command { public: DumpNodesTreeCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override{ return DumpNodesTreeCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class ListProductsCommand : public Command { public: ListProductsCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return ListProductsCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; }; class HelpCommand : public Command { public: HelpCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} QString commandToDescribe() const { return m_command; } private: CommandType type() const override { return HelpCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; void parseNext(QStringList &input) override; QString m_command; }; class VersionCommand : public Command { public: VersionCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const override { return VersionCommandType; } QString shortDescription() const override; QString longDescription() const override; QString representation() const override; QList supportedOptions() const override; void parseNext(QStringList &input) override; }; } // namespace qbs #endif // QBS_PARSER_COMMAND_H qbs-src-1.13.1/src/app/qbs/qbs.pro000066400000000000000000000016121347155106100166150ustar00rootroot00000000000000include(../app.pri) include(parser/parser.pri) TARGET = qbs SOURCES += main.cpp \ ctrlchandler.cpp \ application.cpp \ status.cpp \ consoleprogressobserver.cpp \ commandlinefrontend.cpp \ qbstool.cpp HEADERS += \ ctrlchandler.h \ application.h \ status.h \ consoleprogressobserver.h \ commandlinefrontend.h \ qbstool.h include(../../library_dirname.pri) isEmpty(QBS_RELATIVE_LIBEXEC_PATH) { win32:QBS_RELATIVE_LIBEXEC_PATH=. else:QBS_RELATIVE_LIBEXEC_PATH=../libexec/qbs } isEmpty(QBS_RELATIVE_PLUGINS_PATH):QBS_RELATIVE_PLUGINS_PATH=../$${QBS_LIBRARY_DIRNAME} isEmpty(QBS_RELATIVE_SEARCH_PATH):QBS_RELATIVE_SEARCH_PATH=.. DEFINES += QBS_RELATIVE_LIBEXEC_PATH=\\\"$${QBS_RELATIVE_LIBEXEC_PATH}\\\" DEFINES += QBS_RELATIVE_PLUGINS_PATH=\\\"$${QBS_RELATIVE_PLUGINS_PATH}\\\" DEFINES += QBS_RELATIVE_SEARCH_PATH=\\\"$${QBS_RELATIVE_SEARCH_PATH}\\\" qbs-src-1.13.1/src/app/qbs/qbs.qbs000066400000000000000000000025421347155106100166050ustar00rootroot00000000000000import qbs 1.0 import qbs.Utilities QbsApp { name: "qbs_app" Depends { name: "qbs resources" } targetName: "qbs" cpp.defines: base.concat([ "QBS_VERSION=" + Utilities.cStringQuote(qbsversion.version), "QBS_RELATIVE_LIBEXEC_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativeLibexecPath), "QBS_RELATIVE_SEARCH_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativeSearchPath), "QBS_RELATIVE_PLUGINS_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativePluginsPath), ]) files: [ "application.cpp", "application.h", "commandlinefrontend.cpp", "commandlinefrontend.h", "consoleprogressobserver.cpp", "consoleprogressobserver.h", "ctrlchandler.cpp", "ctrlchandler.h", "main.cpp", "qbstool.cpp", "qbstool.h", "status.cpp", "status.h", ] Group { name: "parser" prefix: name + '/' files: [ "commandlineoption.cpp", "commandlineoption.h", "commandlineoptionpool.cpp", "commandlineoptionpool.h", "commandlineparser.cpp", "commandlineparser.h", "commandpool.cpp", "commandpool.h", "commandtype.h", "parsercommand.cpp", "parsercommand.h", ] } } qbs-src-1.13.1/src/app/qbs/qbstool.cpp000066400000000000000000000077231347155106100175060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qbstool.h" #include #include #include #include #include #include static QString toolPrefix() { return QStringLiteral("qbs-"); } static QString qbsBinDir() { return QCoreApplication::applicationDirPath(); } static QString qbsToolFilePath(const QString &toolName) { return qbsBinDir() + QLatin1Char('/') + toolPrefix() + qbs::Internal::HostOsInfo::appendExecutableSuffix(toolName); } void QbsTool::runTool(const QString &toolName, const QStringList &arguments) { m_failedToStart = false; m_exitCode = -1; const QString filePath = qbsToolFilePath(toolName); const QFileInfo fi(filePath); if (!fi.exists() || !fi.isFile() || !fi.isExecutable()) { m_failedToStart = true; return; } QProcess toolProc; toolProc.start(filePath, arguments); if (!toolProc.waitForStarted()) m_failedToStart = true; toolProc.waitForFinished(-1); m_exitCode = toolProc.exitCode(); m_stdout = QString::fromLocal8Bit(toolProc.readAllStandardOutput()); m_stderr = QString::fromLocal8Bit(toolProc.readAllStandardError()); } bool QbsTool::tryToRunTool(const QString &toolName, const QStringList &arguments, int *exitCode) { QbsTool tool; tool.runTool(toolName, arguments); if (exitCode) *exitCode = tool.exitCode(); if (tool.failedToStart()) return false; std::cout << qPrintable(tool.stdOut()); std::cerr << qPrintable(tool.stdErr()); return true; } QStringList QbsTool::allToolNames() { const QString suffix = QLatin1String(QBS_HOST_EXE_SUFFIX); const QStringList toolFileNames = QDir(qbsBinDir()).entryList(QStringList(toolPrefix() + QStringLiteral("*%1").arg(suffix)), QDir::Files, QDir::Name); QStringList toolNames; const int prefixLength = toolPrefix().size(); for (const QString &toolFileName : toolFileNames) { toolNames << toolFileName.mid(prefixLength, toolFileName.size() - prefixLength - suffix.size()); } return toolNames; } qbs-src-1.13.1/src/app/qbs/qbstool.h000066400000000000000000000050111347155106100171370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_QBSTOOL_H #define QBS_QBSTOOL_H #include class QbsTool { public: void runTool(const QString &toolName, const QStringList &arguments); bool failedToStart() const { return m_failedToStart; } int exitCode() const { return m_exitCode; } QString stdOut() const { return m_stdout; } QString stdErr() const { return m_stderr; } static QStringList allToolNames(); static bool tryToRunTool(const QString &toolName, const QStringList &arguments, int *exitCode = 0); private: bool m_failedToStart; int m_exitCode; QString m_stdout; QString m_stderr; }; #endif // QBS_QBSTOOL_H qbs-src-1.13.1/src/app/qbs/status.cpp000066400000000000000000000153431347155106100173430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "status.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include namespace qbs { static QList createIgnoreList(const QString &projectRootPath) { QList ignoreRegularExpressionList { QRegExp(projectRootPath + QLatin1String("/build.*")), QRegExp(QStringLiteral("*.qbs"), Qt::CaseSensitive, QRegExp::Wildcard), QRegExp(QStringLiteral("*.pro"), Qt::CaseSensitive, QRegExp::Wildcard), QRegExp(QStringLiteral("*Makefile"), Qt::CaseSensitive, QRegExp::Wildcard), QRegExp(QStringLiteral("*.so*"), Qt::CaseSensitive, QRegExp::Wildcard), QRegExp(QStringLiteral("*.o"), Qt::CaseSensitive, QRegExp::Wildcard) }; QString ignoreFilePath = projectRootPath + QLatin1String("/.qbsignore"); QFile ignoreFile(ignoreFilePath); if (ignoreFile.open(QFile::ReadOnly)) { const QList ignoreTokenList = ignoreFile.readAll().split('\n'); for (const QByteArray &btoken : ignoreTokenList) { const QString token = QString::fromLatin1(btoken); if (token.left(1) == QLatin1String("/")) ignoreRegularExpressionList.push_back(QRegExp(projectRootPath + token + QLatin1String(".*"), Qt::CaseSensitive, QRegExp::RegExp2)); else if (!token.isEmpty()) ignoreRegularExpressionList.push_back(QRegExp(token, Qt::CaseSensitive, QRegExp::RegExp2)); } } return ignoreRegularExpressionList; } static QStringList allFilesInDirectoryRecursive(const QDir &rootDirecory, const QList &ignoreRegularExpressionList) { QStringList fileList; const auto fileInfos = rootDirecory.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, QDir::Name); for (const QFileInfo &fileInfo : fileInfos) { QString absoluteFilePath = fileInfo.absoluteFilePath(); bool inIgnoreList = false; for (const QRegExp &ignoreRegularExpression : ignoreRegularExpressionList) { if (ignoreRegularExpression.exactMatch(absoluteFilePath)) { inIgnoreList = true; break; } } if (!inIgnoreList) { if (fileInfo.isFile()) fileList.push_back(absoluteFilePath); else if (fileInfo.isDir()) fileList << allFilesInDirectoryRecursive(QDir(absoluteFilePath), ignoreRegularExpressionList); } } return fileList; } static QStringList allFilesInProject(const QString &projectRootPath) { QList ignoreRegularExpressionList = createIgnoreList(projectRootPath); return allFilesInDirectoryRecursive(QDir(projectRootPath), ignoreRegularExpressionList); } QStringList allFiles(const ProductData &product) { QStringList files; const auto groups = product.groups(); for (const GroupData &group : groups) files += group.allFilePaths(); return files; } int printStatus(const ProjectData &project) { const QString projectFilePath = project.location().filePath(); QString projectDirectory = QFileInfo(projectFilePath).dir().path(); int projectDirectoryPathLength = projectDirectory.length(); QStringList untrackedFilesInProject = allFilesInProject(projectDirectory); QStringList missingFiles; const auto products = project.allProducts(); for (const ProductData &product : products) { qbsInfo() << "\nProduct: " << product.name() << " (" << product.location().filePath() << ":" << product.location().line() << ")"; const auto groups = product.groups(); for (const GroupData &group : groups) { qbsInfo() << " Group: " << group.name() << " (" << group.location().filePath() << ":" << group.location().line() << ")"; QStringList sourceFiles = group.allFilePaths(); std::sort(sourceFiles.begin(), sourceFiles.end()); for (const QString &sourceFile : qAsConst(sourceFiles)) { if (!QFileInfo(sourceFile).exists()) missingFiles.push_back(sourceFile); qbsInfo() << " " << sourceFile.mid(projectDirectoryPathLength + 1); untrackedFilesInProject.removeOne(sourceFile); } } } qbsInfo() << "\nMissing files:"; for (const QString &untrackedFile : qAsConst(missingFiles)) qbsInfo() << " " << untrackedFile.mid(projectDirectoryPathLength + 1); qbsInfo() << "\nUntracked files:"; for (const QString &missingFile : qAsConst(untrackedFilesInProject)) qbsInfo() << " " << missingFile.mid(projectDirectoryPathLength + 1); return 0; } } // namespace qbs qbs-src-1.13.1/src/app/qbs/status.h000066400000000000000000000037751347155106100170160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef STATUS_H #define STATUS_H namespace qbs { class ProjectData; int printStatus(const ProjectData &project); } // namespace qbs #endif // STATUS_H qbs-src-1.13.1/src/app/shared/000077500000000000000000000000001347155106100157675ustar00rootroot00000000000000qbs-src-1.13.1/src/app/shared/logging/000077500000000000000000000000001347155106100174155ustar00rootroot00000000000000qbs-src-1.13.1/src/app/shared/logging/coloredoutput.cpp000066400000000000000000000073401347155106100230350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "coloredoutput.h" #include #ifdef Q_OS_WIN32 # include #endif #include #ifdef Q_OS_UNIX #include #endif void printfColored(TextColor color, const char *str, va_list vl) { fprintfColored(color, stdout, str, vl); } void printfColored(TextColor color, const char *str, ...) { va_list vl; va_start(vl, str); printfColored(color, str, vl); va_end(vl); } void fprintfColored(TextColor color, FILE *file, const char *str, va_list vl) { #if defined(Q_OS_UNIX) if (color != TextColorDefault && isatty(fileno(file))) { unsigned char bright = (color & TextColorBright) >> 3; fprintf(file, "\033[%d;%dm", bright, 30 + (color & ~TextColorBright)); vfprintf(file, str, vl); fprintf(stdout, "\033[0m"); fprintf(stderr, "\033[0m"); } else #elif defined(Q_OS_WIN32) HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbiInfo; if (color != TextColorDefault && hStdout != INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) { WORD bgrColor = ((color & 1) << 2) | (color & 2) | ((color & 4) >> 2); // BGR instead of RGB. if (color & TextColorBright) bgrColor += FOREGROUND_INTENSITY; SetConsoleTextAttribute(hStdout, (csbiInfo.wAttributes & 0xf0) | bgrColor); vfprintf(file, str, vl); SetConsoleTextAttribute(hStdout, csbiInfo.wAttributes); } else #endif { vfprintf(file, str, vl); } } void fprintfColored(TextColor color, FILE *file, const char *str, ...) { va_list vl; va_start(vl, str); fprintfColored(color, file, str, vl); va_end(vl); } bool terminalSupportsColor() { #if defined(Q_OS_UNIX) const QByteArray &term = qgetenv("TERM"); return !term.isEmpty() && term != "dumb"; #else return true; #endif } qbs-src-1.13.1/src/app/shared/logging/coloredoutput.h000066400000000000000000000061511347155106100225010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_COLOREDOUTPUT_H #define QBS_COLOREDOUTPUT_H #include #include // http://en.wikipedia.org/wiki/ANSI_escape_code#Colors enum TextColor { TextColorDefault = -1, TextColorBlack = 0, TextColorDarkRed = 1, TextColorDarkGreen = 2, TextColorDarkBlue = 4, TextColorDarkCyan = TextColorDarkGreen | TextColorDarkBlue, TextColorDarkMagenta = TextColorDarkRed | TextColorDarkBlue, TextColorDarkYellow = TextColorDarkRed | TextColorDarkGreen, TextColorGray = 7, TextColorBright = 8, TextColorRed = TextColorDarkRed | TextColorBright, TextColorGreen = TextColorDarkGreen | TextColorBright, TextColorBlue = TextColorDarkBlue | TextColorBright, TextColorCyan = TextColorDarkCyan | TextColorBright, TextColorMagenta = TextColorDarkMagenta | TextColorBright, TextColorYellow = TextColorDarkYellow | TextColorBright, TextColorWhite = TextColorGray | TextColorBright }; void printfColored(TextColor color, const char *str, va_list vl); void printfColored(TextColor color, const char *str, ...); void fprintfColored(TextColor color, FILE *file, const char *str, va_list vl); void fprintfColored(TextColor color, FILE *file, const char *str, ...); bool terminalSupportsColor(); #endif // QBS_COLOREDOUTPUT_H qbs-src-1.13.1/src/app/shared/logging/consolelogger.cpp000066400000000000000000000077061347155106100227750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "consolelogger.h" #include #include #include static QHash setupColorTable() { QHash colorTable; colorTable[QStringLiteral("compiler")] = TextColorDefault; colorTable[QStringLiteral("linker")] = TextColorDarkGreen; colorTable[QStringLiteral("codegen")] = TextColorDarkYellow; colorTable[QStringLiteral("filegen")] = TextColorDarkYellow; return colorTable; } ConsoleLogSink::ConsoleLogSink() : m_coloredOutputEnabled(true), m_enabled(true) { } void ConsoleLogSink::doPrintMessage(qbs::LoggerLevel level, const QString &message, const QString &tag) { if (!m_enabled) return; FILE * const file = level == qbs::LoggerInfo && tag != QStringLiteral("stdErr") ? stdout : stderr; const QString levelTag = logLevelTag(level); TextColor color = TextColorDefault; switch (level) { case qbs::LoggerError: color = TextColorRed; break; case qbs::LoggerWarning: color = TextColorYellow; break; default: break; } fprintfWrapper(color, file, levelTag.toLocal8Bit().constData()); static QHash colorTable = setupColorTable(); fprintfWrapper(colorTable.value(tag, TextColorDefault), file, "%s\n", message.toLocal8Bit().constData()); fflush(file); } void ConsoleLogSink::fprintfWrapper(TextColor color, FILE *file, const char *str, ...) { va_list vl; va_start(vl, str); if (m_coloredOutputEnabled && terminalSupportsColor()) fprintfColored(color, file, str, vl); else vfprintf(file, str, vl); va_end(vl); } ConsoleLogger &ConsoleLogger::instance(qbs::Settings *settings) { static ConsoleLogger logger(settings); return logger; } void ConsoleLogger::setSettings(qbs::Settings *settings) { if (settings) m_logSink.setColoredOutputEnabled(qbs::Preferences(settings).useColoredOutput()); } ConsoleLogger::ConsoleLogger(qbs::Settings *settings) : Logger(&m_logSink) { setSettings(settings); } qbs-src-1.13.1/src/app/shared/logging/consolelogger.h000066400000000000000000000063621347155106100224370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LOGSINK_H #define QBS_LOGSINK_H #include "coloredoutput.h" #include namespace qbs { class Settings; } class ConsoleLogSink : public qbs::ILogSink { public: ConsoleLogSink(); void setColoredOutputEnabled(bool enabled) { m_coloredOutputEnabled = enabled; } void setEnabled(bool enabled) { m_enabled = enabled; } private: void doPrintMessage(qbs::LoggerLevel level, const QString &message, const QString &tag); void fprintfWrapper(TextColor color, FILE *file, const char *str, ...); private: bool m_coloredOutputEnabled; bool m_enabled; }; class ConsoleLogger : public qbs::Internal::Logger { public: static ConsoleLogger &instance(qbs::Settings *settings = 0); ConsoleLogSink *logSink() { return &m_logSink; } void setSettings(qbs::Settings *settings); private: ConsoleLogger(qbs::Settings *settings); ConsoleLogSink m_logSink; }; inline qbs::Internal::LogWriter qbsError() { return ConsoleLogger::instance().qbsLog(qbs::LoggerError); } inline qbs::Internal::LogWriter qbsWarning() { return ConsoleLogger::instance().qbsWarning(); } inline qbs::Internal::LogWriter qbsInfo() { return ConsoleLogger::instance().qbsInfo(); } inline qbs::Internal::LogWriter qbsDebug() { return ConsoleLogger::instance().qbsDebug(); } inline qbs::Internal::LogWriter qbsTrace() { return ConsoleLogger::instance().qbsTrace(); } #endif // QBS_LOGSINK_H qbs-src-1.13.1/src/app/shared/logging/logging.pri000066400000000000000000000001621347155106100215560ustar00rootroot00000000000000HEADERS += $$PWD/consolelogger.h $$PWD/coloredoutput.h SOURCES += $$PWD/consolelogger.cpp $$PWD/coloredoutput.cpp qbs-src-1.13.1/src/install_prefix.pri000066400000000000000000000001031347155106100174720ustar00rootroot00000000000000unix: isEmpty(QBS_INSTALL_PREFIX): QBS_INSTALL_PREFIX = /usr/local qbs-src-1.13.1/src/lib/000077500000000000000000000000001347155106100145075ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/bundledlibs.pri000066400000000000000000000001331347155106100175070ustar00rootroot00000000000000!qbs_use_bundled_qtscript:!qtHaveModule(script) { CONFIG += qbs_use_bundled_qtscript } qbs-src-1.13.1/src/lib/corelib/000077500000000000000000000000001347155106100161265ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/corelib/api/000077500000000000000000000000001347155106100166775ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/corelib/api/api.pri000066400000000000000000000024121347155106100201630ustar00rootroot00000000000000include(../../../install_prefix.pri) HEADERS += \ $$PWD/internaljobs.h \ $$PWD/projectdata.h \ $$PWD/runenvironment.h \ $$PWD/jobs.h \ $$PWD/languageinfo.h \ $$PWD/project.h \ $$PWD/project_p.h \ $$PWD/propertymap_p.h \ $$PWD/projectdata_p.h \ $$PWD/rulecommand.h \ $$PWD/rulecommand_p.h \ $$PWD/transformerdata.h \ $$PWD/transformerdata_p.h SOURCES += \ $$PWD/internaljobs.cpp \ $$PWD/runenvironment.cpp \ $$PWD/projectdata.cpp \ $$PWD/jobs.cpp \ $$PWD/languageinfo.cpp \ $$PWD/project.cpp \ $$PWD/rulecommand.cpp \ $$PWD/transformerdata.cpp !qbs_no_dev_install { api_headers.files = \ $$PWD/jobs.h \ $$PWD/languageinfo.h \ $$PWD/project.h \ $$PWD/projectdata.h \ $$PWD/rulecommand.h \ $$PWD/runenvironment.h \ $$PWD/transformerdata.h api_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/api INSTALLS += api_headers } qbs_enable_project_file_updates { HEADERS += \ $$PWD/changeset.h \ $$PWD/projectfileupdater.h \ $$PWD/qmljsrewriter.h SOURCES += \ $$PWD/changeset.cpp \ $$PWD/projectfileupdater.cpp \ $$PWD/qmljsrewriter.cpp DEFINES += QBS_ENABLE_PROJECT_FILE_UPDATES } qbs-src-1.13.1/src/lib/corelib/api/changeset.cpp000066400000000000000000000252101347155106100213440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "changeset.h" #include namespace QbsQmlJS { ChangeSet::ChangeSet() : m_string(nullptr), m_cursor(nullptr), m_error(false) { } ChangeSet::ChangeSet(const QList &operations) : m_string(nullptr), m_cursor(nullptr), m_operationList(operations), m_error(false) { } static bool overlaps(int posA, int lengthA, int posB, int lengthB) { if (lengthB > 0) { return // right edge of B contained in A (posA < posB + lengthB && posA + lengthA >= posB + lengthB) // left edge of B contained in A || (posA <= posB && posA + lengthA > posB) // A contained in B || (posB < posA && posB + lengthB > posA + lengthA); } else { return (posB > posA && posB < posA + lengthA); } } bool ChangeSet::hasOverlap(int pos, int length) { QListIterator i(m_operationList); while (i.hasNext()) { const EditOp &cmd = i.next(); switch (cmd.type) { case EditOp::Replace: if (overlaps(pos, length, cmd.pos1, cmd.length1)) return true; break; case EditOp::Move: if (overlaps(pos, length, cmd.pos1, cmd.length1)) return true; if (cmd.pos2 > pos && cmd.pos2 < pos + length) return true; break; case EditOp::Insert: if (cmd.pos1 > pos && cmd.pos1 < pos + length) return true; break; case EditOp::Remove: if (overlaps(pos, length, cmd.pos1, cmd.length1)) return true; break; case EditOp::Flip: if (overlaps(pos, length, cmd.pos1, cmd.length1)) return true; if (overlaps(pos, length, cmd.pos2, cmd.length2)) return true; break; case EditOp::Copy: if (overlaps(pos, length, cmd.pos1, cmd.length1)) return true; if (cmd.pos2 > pos && cmd.pos2 < pos + length) return true; break; case EditOp::Unset: break; } } return false; } bool ChangeSet::empty() const { return m_operationList.empty(); } QList ChangeSet::operationList() const { return m_operationList; } void ChangeSet::clear() { m_string = nullptr; m_cursor = nullptr; m_operationList.clear(); m_error = false; } bool ChangeSet::replace_helper(int pos, int length, const QString &replacement) { if (hasOverlap(pos, length)) m_error = true; EditOp cmd(EditOp::Replace); cmd.pos1 = pos; cmd.length1 = length; cmd.text = replacement; m_operationList.push_back(cmd); return !m_error; } bool ChangeSet::move_helper(int pos, int length, int to) { if (hasOverlap(pos, length) || hasOverlap(to, 0) || overlaps(pos, length, to, 0)) m_error = true; EditOp cmd(EditOp::Move); cmd.pos1 = pos; cmd.length1 = length; cmd.pos2 = to; m_operationList.push_back(cmd); return !m_error; } bool ChangeSet::insert(int pos, const QString &text) { Q_ASSERT(pos >= 0); if (hasOverlap(pos, 0)) m_error = true; EditOp cmd(EditOp::Insert); cmd.pos1 = pos; cmd.text = text; m_operationList.push_back(cmd); return !m_error; } bool ChangeSet::replace(const Range &range, const QString &replacement) { return replace(range.start, range.end, replacement); } bool ChangeSet::remove(const Range &range) { return remove(range.start, range.end); } bool ChangeSet::move(const Range &range, int to) { return move(range.start, range.end, to); } bool ChangeSet::flip(const Range &range1, const Range &range2) { return flip(range1.start, range1.end, range2.start, range2.end); } bool ChangeSet::copy(const Range &range, int to) { return copy(range.start, range.end, to); } bool ChangeSet::replace(int start, int end, const QString &replacement) { return replace_helper(start, end - start, replacement); } bool ChangeSet::remove(int start, int end) { return remove_helper(start, end - start); } bool ChangeSet::move(int start, int end, int to) { return move_helper(start, end - start, to); } bool ChangeSet::flip(int start1, int end1, int start2, int end2) { return flip_helper(start1, end1 - start1, start2, end2 - start2); } bool ChangeSet::copy(int start, int end, int to) { return copy_helper(start, end - start, to); } bool ChangeSet::remove_helper(int pos, int length) { if (hasOverlap(pos, length)) m_error = true; EditOp cmd(EditOp::Remove); cmd.pos1 = pos; cmd.length1 = length; m_operationList.push_back(cmd); return !m_error; } bool ChangeSet::flip_helper(int pos1, int length1, int pos2, int length2) { if (hasOverlap(pos1, length1) || hasOverlap(pos2, length2) || overlaps(pos1, length1, pos2, length2)) m_error = true; EditOp cmd(EditOp::Flip); cmd.pos1 = pos1; cmd.length1 = length1; cmd.pos2 = pos2; cmd.length2 = length2; m_operationList.push_back(cmd); return !m_error; } bool ChangeSet::copy_helper(int pos, int length, int to) { if (hasOverlap(pos, length) || hasOverlap(to, 0) || overlaps(pos, length, to, 0)) m_error = true; EditOp cmd(EditOp::Copy); cmd.pos1 = pos; cmd.length1 = length; cmd.pos2 = to; m_operationList.push_back(cmd); return !m_error; } void ChangeSet::doReplace(const EditOp &replace_helper, QList *replaceList) { Q_ASSERT(replace_helper.type == EditOp::Replace); { QMutableListIterator i(*replaceList); while (i.hasNext()) { EditOp &c = i.next(); if (replace_helper.pos1 <= c.pos1) c.pos1 += replace_helper.text.size(); if (replace_helper.pos1 < c.pos1) c.pos1 -= replace_helper.length1; } } if (m_string) { m_string->replace(replace_helper.pos1, replace_helper.length1, replace_helper.text); } else if (m_cursor) { m_cursor->setPosition(replace_helper.pos1); m_cursor->setPosition(replace_helper.pos1 + replace_helper.length1, QTextCursor::KeepAnchor); m_cursor->insertText(replace_helper.text); } } void ChangeSet::convertToReplace(const EditOp &op, QList *replaceList) { EditOp replace1(EditOp::Replace); EditOp replace2(EditOp::Replace); switch (op.type) { case EditOp::Replace: replaceList->push_back(op); break; case EditOp::Move: replace1.pos1 = op.pos1; replace1.length1 = op.length1; replaceList->push_back(replace1); replace2.pos1 = op.pos2; replace2.text = textAt(op.pos1, op.length1); replaceList->push_back(replace2); break; case EditOp::Insert: replace1.pos1 = op.pos1; replace1.text = op.text; replaceList->push_back(replace1); break; case EditOp::Remove: replace1.pos1 = op.pos1; replace1.length1 = op.length1; replaceList->push_back(replace1); break; case EditOp::Flip: replace1.pos1 = op.pos1; replace1.length1 = op.length1; replace1.text = textAt(op.pos2, op.length2); replaceList->push_back(replace1); replace2.pos1 = op.pos2; replace2.length1 = op.length2; replace2.text = textAt(op.pos1, op.length1); replaceList->push_back(replace2); break; case EditOp::Copy: replace1.pos1 = op.pos2; replace1.text = textAt(op.pos1, op.length1); replaceList->push_back(replace1); break; case EditOp::Unset: break; } } bool ChangeSet::hadErrors() { return m_error; } void ChangeSet::apply(QString *s) { m_string = s; apply_helper(); m_string = nullptr; } void ChangeSet::apply(QTextCursor *textCursor) { m_cursor = textCursor; apply_helper(); m_cursor = nullptr; } QString ChangeSet::textAt(int pos, int length) { if (m_string) { return m_string->mid(pos, length); } else if (m_cursor) { m_cursor->setPosition(pos); m_cursor->setPosition(pos + length, QTextCursor::KeepAnchor); return m_cursor->selectedText(); } return {}; } void ChangeSet::apply_helper() { // convert all ops to replace QList replaceList; { while (!m_operationList.empty()) { const EditOp cmd(m_operationList.front()); m_operationList.removeFirst(); convertToReplace(cmd, &replaceList); } } // execute replaces if (m_cursor) m_cursor->beginEditBlock(); while (!replaceList.empty()) { const EditOp cmd(replaceList.front()); replaceList.removeFirst(); doReplace(cmd, &replaceList); } if (m_cursor) m_cursor->endEditBlock(); } } // namespace Internal { qbs-src-1.13.1/src/lib/corelib/api/changeset.h000066400000000000000000000102731347155106100210140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_CHANGESET_H #define QBS_CHANGESET_H #include #include QT_FORWARD_DECLARE_CLASS(QTextCursor) namespace QbsQmlJS { class ChangeSet { public: struct EditOp { enum Type { Unset, Replace, Move, Insert, Remove, Flip, Copy }; EditOp(): type(Unset), pos1(0), pos2(0), length1(0), length2(0) {} EditOp(Type t): type(t), pos1(0), pos2(0), length1(0), length2(0) {} Type type; int pos1; int pos2; int length1; int length2; QString text; }; struct Range { Range() : start(0), end(0) {} Range(int start, int end) : start(start), end(end) {} int start; int end; }; public: ChangeSet(); ChangeSet(const QList &operations); bool empty() const; QList operationList() const; void clear(); bool replace(const Range &range, const QString &replacement); bool remove(const Range &range); bool move(const Range &range, int to); bool flip(const Range &range1, const Range &range2); bool copy(const Range &range, int to); bool replace(int start, int end, const QString &replacement); bool remove(int start, int end); bool move(int start, int end, int to); bool flip(int start1, int end1, int start2, int end2); bool copy(int start, int end, int to); bool insert(int pos, const QString &text); bool hadErrors(); void apply(QString *s); void apply(QTextCursor *textCursor); private: // length-based API. bool replace_helper(int pos, int length, const QString &replacement); bool move_helper(int pos, int length, int to); bool remove_helper(int pos, int length); bool flip_helper(int pos1, int length1, int pos2, int length2); bool copy_helper(int pos, int length, int to); bool hasOverlap(int pos, int length); QString textAt(int pos, int length); void doReplace(const EditOp &replace, QList *replaceList); void convertToReplace(const EditOp &op, QList *replaceList); void apply_helper(); private: QString *m_string; QTextCursor *m_cursor; QList m_operationList; bool m_error; }; } // namespace QbsQmlJS #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/api/internaljobs.cpp000066400000000000000000000347341347155106100221100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "internaljobs.h" #include "jobs.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class JobObserver : public ProgressObserver { public: JobObserver(InternalJob *job) : m_canceled(false), m_job(job), m_timedLogger(nullptr) { } ~JobObserver() { delete m_timedLogger; } void cancel() { std::lock_guard lock(m_cancelMutex); m_canceled = true; } private: void initialize(const QString &task, int maximum) override { QBS_ASSERT(!m_timedLogger, delete m_timedLogger); if (m_job->timed()) m_timedLogger = new TimedActivityLogger(m_job->logger(), task, true); m_value = 0; m_maximum = maximum; emit m_job->newTaskStarted(task, maximum, m_job); } void setMaximum(int maximum) override { m_maximum = maximum; emit m_job->totalEffortChanged(maximum, m_job); } void setProgressValue(int value) override { //QBS_ASSERT(value >= m_value, qDebug("old value = %d, new value = %d", m_value, value)); //QBS_ASSERT(value <= m_maximum, qDebug("value = %d, maximum = %d", value, m_maximum)); m_value = value; if (value == m_maximum) { delete m_timedLogger; m_timedLogger = nullptr; } emit m_job->taskProgress(value, m_job); } int progressValue() override { return m_value; } int maximum() const override { return m_maximum; } bool canceled() const override { std::lock_guard lock(m_cancelMutex); return m_canceled; } int m_value; int m_maximum; mutable std::mutex m_cancelMutex; bool m_canceled; InternalJob * const m_job; TimedActivityLogger *m_timedLogger; }; InternalJob::InternalJob(const Logger &logger, QObject *parent) : QObject(parent) , m_observer(new JobObserver(this)) , m_ownsObserver(true) , m_logger(logger) , m_timed(false) { } InternalJob::~InternalJob() { if (m_ownsObserver) delete m_observer; } void InternalJob::cancel() { m_observer->cancel(); } void InternalJob::shareObserverWith(InternalJob *otherJob) { if (m_ownsObserver) { delete m_observer; m_ownsObserver = false; } m_observer = otherJob->m_observer; } void InternalJob::storeBuildGraph(const TopLevelProjectPtr &project) { try { doSanityChecks(project, logger()); TimedActivityLogger storeTimer(m_logger, Tr::tr("Storing build graph"), timed()); project->store(logger()); } catch (const ErrorInfo &error) { ErrorInfo fullError = this->error(); for (const ErrorItem &item : error.items()) fullError.append(item); setError(fullError); } } /** * Construct a new thread wrapper for a synchronous job. * This object takes over ownership of the synchronous job. */ InternalJobThreadWrapper::InternalJobThreadWrapper(InternalJob *synchronousJob, QObject *parent) : InternalJob(synchronousJob->logger(), parent) , m_job(synchronousJob) , m_running(false) { synchronousJob->shareObserverWith(this); m_job->moveToThread(&m_thread); connect(m_job, &InternalJob::finished, this, &InternalJobThreadWrapper::handleFinished); connect(m_job, &InternalJob::newTaskStarted, this, &InternalJob::newTaskStarted); connect(m_job, &InternalJob::taskProgress, this, &InternalJob::taskProgress); connect(m_job, &InternalJob::totalEffortChanged, this, &InternalJob::totalEffortChanged); connect(this, &InternalJobThreadWrapper::startRequested, m_job, &InternalJob::start); } InternalJobThreadWrapper::~InternalJobThreadWrapper() { if (m_running) { QEventLoop loop; connect(m_job, &InternalJob::finished, &loop, &QEventLoop::quit); cancel(); loop.exec(); } m_thread.quit(); m_thread.wait(); delete m_job; } void InternalJobThreadWrapper::start() { setTimed(m_job->timed()); m_thread.start(); m_running = true; QTimer::singleShot(0, this, &InternalJobThreadWrapper::startRequested); } void InternalJobThreadWrapper::handleFinished() { m_running = false; setError(m_job->error()); emit finished(this); } InternalSetupProjectJob::InternalSetupProjectJob(const Logger &logger) : InternalJob(logger) { } InternalSetupProjectJob::~InternalSetupProjectJob() { } void InternalSetupProjectJob::init(const TopLevelProjectPtr &existingProject, const SetupProjectParameters ¶meters) { m_existingProject = existingProject; m_parameters = parameters; setTimed(parameters.logElapsedTime()); } void InternalSetupProjectJob::reportError(const ErrorInfo &error) { setError(error); emit finished(this); } TopLevelProjectPtr InternalSetupProjectJob::project() const { return m_newProject; } void InternalSetupProjectJob::start() { BuildGraphLocker *bgLocker = m_existingProject ? m_existingProject->bgLocker : nullptr; bool deleteLocker = false; try { const ErrorInfo err = m_parameters.expandBuildConfiguration(); if (err.hasError()) throw err; const QString projectId = TopLevelProject::deriveId( m_parameters.finalBuildConfigurationTree()); const QString buildDir = TopLevelProject::deriveBuildDirectory(m_parameters.buildRoot(), projectId); if (m_existingProject && m_existingProject->buildDirectory != buildDir) m_existingProject.reset(); if (!m_existingProject) { bgLocker = new BuildGraphLocker(ProjectBuildData::deriveBuildGraphFilePath(buildDir, projectId), logger(), m_parameters.waitLockBuildGraph(), observer()); deleteLocker = true; } execute(); if (m_existingProject) { if (m_existingProject != m_newProject) m_existingProject->makeModuleProvidersNonTransient(); m_existingProject->bgLocker = nullptr; } m_newProject->bgLocker = bgLocker; deleteLocker = false; } catch (const ErrorInfo &error) { m_newProject.reset(); setError(error); // Delete the build graph locker if and only if we allocated it here. if (deleteLocker) delete bgLocker; } emit finished(this); } void InternalSetupProjectJob::execute() { RulesEvaluationContextPtr evalContext(new RulesEvaluationContext(logger())); evalContext->setObserver(observer()); switch (m_parameters.restoreBehavior()) { case SetupProjectParameters::ResolveOnly: resolveProjectFromScratch(evalContext->engine()); resolveBuildDataFromScratch(evalContext); break; case SetupProjectParameters::RestoreOnly: m_newProject = restoreProject(evalContext).loadedProject; break; case SetupProjectParameters::RestoreAndTrackChanges: { const BuildGraphLoadResult loadResult = restoreProject(evalContext); m_newProject = loadResult.newlyResolvedProject; if (!m_newProject) m_newProject = loadResult.loadedProject; if (!m_newProject) { resolveProjectFromScratch(evalContext->engine()); resolveBuildDataFromScratch(evalContext); } else { QBS_CHECK(m_newProject->buildData); } break; } } if (!m_parameters.dryRun()) storeBuildGraph(m_newProject); // The evalutation context cannot be re-used for building, which runs in a different thread. m_newProject->buildData->evaluationContext.reset(); } void InternalSetupProjectJob::resolveProjectFromScratch(ScriptEngine *engine) { Loader loader(engine, logger()); loader.setSearchPaths(m_parameters.searchPaths()); loader.setProgressObserver(observer()); m_newProject = loader.loadProject(m_parameters); QBS_CHECK(m_newProject); } void InternalSetupProjectJob::resolveBuildDataFromScratch(const RulesEvaluationContextPtr &evalContext) { TimedActivityLogger resolveLogger(logger(), QStringLiteral("Resolving build project"), timed()); BuildDataResolver(logger()).resolveBuildData(m_newProject, evalContext); } BuildGraphLoadResult InternalSetupProjectJob::restoreProject(const RulesEvaluationContextPtr &evalContext) { BuildGraphLoader bgLoader(logger()); const BuildGraphLoadResult loadResult = bgLoader.load(m_existingProject, m_parameters, evalContext); return loadResult; } BuildGraphTouchingJob::BuildGraphTouchingJob(const Logger &logger, QObject *parent) : InternalJob(logger, parent), m_dryRun(false) { } BuildGraphTouchingJob::~BuildGraphTouchingJob() { } void BuildGraphTouchingJob::setup(const TopLevelProjectPtr &project, const QList &products, bool dryRun) { m_project = project; m_products = products; m_dryRun = dryRun; } void BuildGraphTouchingJob::storeBuildGraph() { if (!m_dryRun && !error().isInternalError()) InternalJob::storeBuildGraph(m_project); } InternalBuildJob::InternalBuildJob(const Logger &logger, QObject *parent) : BuildGraphTouchingJob(logger, parent), m_executor(nullptr) { } void InternalBuildJob::build(const TopLevelProjectPtr &project, const QList &products, const BuildOptions &buildOptions) { setup(project, products, buildOptions.dryRun()); setTimed(buildOptions.logElapsedTime()); m_executor = new Executor(logger()); m_executor->setProject(project); m_executor->setProducts(std::vector(products.cbegin(), products.cend())); m_executor->setBuildOptions(buildOptions); m_executor->setProgressObserver(observer()); const auto executorThread = new QThread(this); m_executor->moveToThread(executorThread); connect(m_executor, &Executor::reportCommandDescription, this, &BuildGraphTouchingJob::reportCommandDescription); connect(m_executor, &Executor::reportProcessResult, this, &BuildGraphTouchingJob::reportProcessResult); connect(executorThread, &QThread::started, m_executor, &Executor::build); connect(m_executor, &Executor::finished, this, &InternalBuildJob::handleFinished); connect(m_executor, &QObject::destroyed, executorThread, &QThread::quit); connect(executorThread, &QThread::finished, this, &InternalBuildJob::emitFinished); executorThread->start(); } void InternalBuildJob::handleFinished() { setError(m_executor->error()); project()->buildData->evaluationContext.reset(); storeBuildGraph(); m_executor->deleteLater(); } void InternalBuildJob::emitFinished() { emit finished(this); } InternalCleanJob::InternalCleanJob(const Logger &logger, QObject *parent) : BuildGraphTouchingJob(logger, parent) { } void InternalCleanJob::init(const TopLevelProjectPtr &project, const QList &products, const CleanOptions &options) { setup(project, products, options.dryRun()); setTimed(options.logElapsedTime()); m_options = options; } void InternalCleanJob::start() { try { ArtifactCleaner cleaner(logger(), observer()); cleaner.cleanup(project(), products(), m_options); } catch (const ErrorInfo &error) { setError(error); } storeBuildGraph(); emit finished(this); } InternalInstallJob::InternalInstallJob(const Logger &logger) : InternalJob(logger) { } InternalInstallJob::~InternalInstallJob() { } void InternalInstallJob::init(const TopLevelProjectPtr &project, const std::vector &products, const InstallOptions &options) { m_project = project; m_products = products; m_options = options; setTimed(options.logElapsedTime()); } void InternalInstallJob::start() { try { ProductInstaller(m_project, m_products, m_options, observer(), logger()).install(); } catch (const ErrorInfo &error) { setError(error); } emit finished(this); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/api/internaljobs.h000066400000000000000000000151541347155106100215500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_INTERNALJOBS_H #define QBS_INTERNALJOBS_H #include #include #include #include #include #include #include #include #include #include #include namespace qbs { class ProcessResult; class Settings; namespace Internal { class BuildGraphLoadResult; class BuildGraphLocker; class Executor; class JobObserver; class ScriptEngine; class InternalJob : public QObject { Q_OBJECT friend class JobObserver; public: ~InternalJob(); void cancel(); virtual void start() {} ErrorInfo error() const { return m_error; } void setError(const ErrorInfo &error) { m_error = error; } Logger logger() const { return m_logger; } bool timed() const { return m_timed; } void shareObserverWith(InternalJob *otherJob); protected: explicit InternalJob(const Logger &logger, QObject *parent = nullptr); JobObserver *observer() const { return m_observer; } void setTimed(bool timed) { m_timed = timed; } void storeBuildGraph(const TopLevelProjectPtr &project); signals: void finished(Internal::InternalJob *job); void newTaskStarted(const QString &description, int totalEffort, Internal::InternalJob *job); void totalEffortChanged(int totalEffort, Internal::InternalJob *job); void taskProgress(int value, Internal::InternalJob *job); private: ErrorInfo m_error; JobObserver *m_observer; bool m_ownsObserver; Logger m_logger; bool m_timed; }; class InternalJobThreadWrapper : public InternalJob { Q_OBJECT public: InternalJobThreadWrapper(InternalJob *synchronousJob, QObject *parent = nullptr); ~InternalJobThreadWrapper(); void start() override; InternalJob *synchronousJob() const { return m_job; } signals: void startRequested(); private: void handleFinished(); QThread m_thread; InternalJob *m_job; bool m_running; }; class InternalSetupProjectJob : public InternalJob { Q_OBJECT public: InternalSetupProjectJob(const Logger &logger); ~InternalSetupProjectJob(); void init(const TopLevelProjectPtr &existingProject, const SetupProjectParameters ¶meters); void reportError(const ErrorInfo &error); TopLevelProjectPtr project() const; private: void start() override; void resolveProjectFromScratch(Internal::ScriptEngine *engine); void resolveBuildDataFromScratch(const RulesEvaluationContextPtr &evalContext); BuildGraphLoadResult restoreProject(const RulesEvaluationContextPtr &evalContext); void execute(); TopLevelProjectPtr m_existingProject; TopLevelProjectPtr m_newProject; SetupProjectParameters m_parameters; }; class BuildGraphTouchingJob : public InternalJob { Q_OBJECT public: const QList &products() const { return m_products; } const TopLevelProjectPtr &project() const { return m_project; } signals: void reportCommandDescription(const QString &highlight, const QString &message); void reportProcessResult(const qbs::ProcessResult &result); protected: BuildGraphTouchingJob(const Logger &logger, QObject *parent = nullptr); ~BuildGraphTouchingJob(); void setup(const TopLevelProjectPtr &project, const QList &products, bool dryRun); void storeBuildGraph(); private: TopLevelProjectPtr m_project; QList m_products; bool m_dryRun; }; class InternalBuildJob : public BuildGraphTouchingJob { Q_OBJECT public: InternalBuildJob(const Logger &logger, QObject *parent = nullptr); void build(const TopLevelProjectPtr &project, const QList &products, const BuildOptions &buildOptions); private: void handleFinished(); void emitFinished(); Executor *m_executor; }; class InternalCleanJob : public BuildGraphTouchingJob { Q_OBJECT public: InternalCleanJob(const Logger &logger, QObject *parent = nullptr); void init(const TopLevelProjectPtr &project, const QList &products, const CleanOptions &options); private: void start() override; CleanOptions m_options; }; class InternalInstallJob : public InternalJob { Q_OBJECT public: InternalInstallJob(const Logger &logger); ~InternalInstallJob(); void init(const TopLevelProjectPtr &project, const std::vector &products, const InstallOptions &options); private: void start() override; TopLevelProjectPtr m_project; std::vector m_products; InstallOptions m_options; }; } // namespace Internal } // namespace qbs #endif // QBS_INTERNALJOBS_H qbs-src-1.13.1/src/lib/corelib/api/jobs.cpp000066400000000000000000000330431347155106100203430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "jobs.h" #include "internaljobs.h" #include "project_p.h" #include #include #include #include #include namespace qbs { using namespace Internal; /*! * \class AbstractJob * \brief The \c AbstractJob class represents an operation relating to a \c Project. * Concrete child classes of \c AbstractJob are created by factory functions in the \c Project * class. The respective objects represent an operation that is started automatically * and is considered "running" until the \c finished() signal has been emitted. Afterwards, * callers can find out whether the operation was successful by calling \c hasError(). While * the operation is going on, progress information is being provided via \c taskStarted() and * \c taskProgress. * Note that though a job is being started automatically by its factory function, you are guaranteed * to recevieve all signals it emits if you connect to it right after getting the object from the * creating function. * \sa Project */ /*! * \enum AbstractJob::State * This enum type specifies which states a job can be in. * \value StateRunning The respective operation is ongoing. * \value StateCanceling The job has been requested to cancel via \c AbstractJob::cancel(), * but the \c AbstractJob::finished() signal has not been emitted yet. * \value StateFinished The operation has finished and the \c AbstractJob::finished() signal * has been emitted. */ /*! * \fn AbstractJob::State AbstractJob::state() const * \brief Returns the current state of the operation. */ /*! * \fn bool AbstractJob::hasError() const * \brief Returns true if the operation has finished with an error, otherwise returns false. * This function should not be called before the \c finished() signal has been emitted. */ /*! * \fn void AbstractJob::taskStarted(const QString &description, int maximumProgressValue, qbs::AbstractJob *job) * \brief Indicates that a new task has been started. * The \a description parameter is a string intended for presentation to a user. * The \a maximumProgressValue parameter indicates the maximum value to which subsequent values of * \c taskProgress() will go. * This signal is typically emitted exactly once for a job that finishes successfully. However, * operations might emit it several times if they are made up of subtasks whose overall effort * cannot be determined in advance. * \sa AbstractJob::taskProgress() */ /*! * \fn void taskProgress(int newProgressValue, qbs::AbstractJob *job) * \brief Indicates progress in executing the operation. * The \a newProgressValue parameter represents the current progress. It is always greater than * zero, strictly increasing and goes up to the \c maximumProgressValue argument of the last * call to \c taskStarted(). * \sa AbstractJob::taskStarted() */ /*! * \fn void finished(bool success, qbs::AbstractJob *job) * \brief Indicates that the operation has finished. * Check the \a success parameter to find out whether everything went fine or an error occurred. */ AbstractJob::AbstractJob(InternalJob *internalJob, QObject *parent) : QObject(parent), m_internalJob(internalJob) { m_internalJob->setParent(this); connect(m_internalJob, &InternalJob::newTaskStarted, this, &AbstractJob::handleTaskStarted, Qt::QueuedConnection); connect(m_internalJob, &InternalJob::totalEffortChanged, this, &AbstractJob::handleTotalEffortChanged); connect(m_internalJob, &InternalJob::taskProgress, this, &AbstractJob::handleTaskProgress, Qt::QueuedConnection); connect(m_internalJob, &InternalJob::finished, this, &AbstractJob::handleFinished); m_state = StateRunning; } bool AbstractJob::lockProject(const TopLevelProjectPtr &project) { // The API is not thread-safe, so we don't need a mutex here, as the API requests come in // synchronously. if (project->locked) { internalJob()->setError(tr("Cannot start a job while another one is in progress.")); QTimer::singleShot(0, this, [this] { emit finished(false, this); }); return false; } project->locked = true; m_project = project; return true; } void AbstractJob::unlockProject() { if (!m_project) return; QBS_ASSERT(m_project->locked, return); m_project->locked = false; } /*! * \brief Destroys the object, canceling the operation if necessary. */ AbstractJob::~AbstractJob() { m_internalJob->disconnect(this); cancel(); } /*! * \brief Returns the error which caused this operation to fail, if it did fail. */ ErrorInfo AbstractJob::error() const { if (m_error.hasError()) return m_error; return internalJob()->error(); } /*! * \brief Cancels this job. * Note that the job might not finish immediately. If you need to make sure it has actually * finished, wait for the \c finished() signal. * \sa AbstractJob::finished(AbstractJob *); */ void AbstractJob::cancel() { if (m_state != StateRunning) return; m_state = StateCanceling; internalJob()->cancel(); } void AbstractJob::handleTaskStarted(const QString &description, int maximumProgressValue) { emit taskStarted(description, maximumProgressValue, this); } void AbstractJob::handleTotalEffortChanged(int totalEffort) { emit totalEffortChanged(totalEffort, this); } void AbstractJob::handleTaskProgress(int newProgressValue) { emit taskProgress(newProgressValue, this); } void AbstractJob::handleFinished() { QBS_ASSERT(m_state != StateFinished, return); finish(); m_state = StateFinished; unlockProject(); emit finished(!error().hasError(), this); } /*! * \class SetupProjectJob * \brief The \c SetupProjectJob class represents an operation that reads a qbs project file and * creates a \c Project object from it. * Note that this job can emit the \c taskStarted() signal more than once. * \sa AbstractJob::taskStarted() */ SetupProjectJob::SetupProjectJob(const Logger &logger, QObject *parent) : AbstractJob(new InternalJobThreadWrapper(new InternalSetupProjectJob(logger)), parent) { if (logger.logSink()->logLevel() == LoggerDebug || logger.logSink()->logLevel() == LoggerTrace) QLoggingCategory::setFilterRules(QStringLiteral("qbs.*.debug=true")); } /*! * \brief Returns the project resulting from this operation. * Note that the result is undefined if the job did not finish successfully. * \sa AbstractJob::hasError() */ Project SetupProjectJob::project() const { auto const wrapper = qobject_cast(internalJob()); auto const job = qobject_cast(wrapper->synchronousJob()); return Project(job->project(), job->logger()); } void SetupProjectJob::resolve(const Project &existingProject, const SetupProjectParameters ¶meters) { m_existingProject = existingProject; const TopLevelProjectPtr &existingInternalProject = existingProject.d ? existingProject.d->internalProject : TopLevelProjectPtr(); if (existingInternalProject && !lockProject(existingInternalProject)) return; auto const wrapper = qobject_cast(internalJob()); auto const job = qobject_cast(wrapper->synchronousJob()); job->init(existingInternalProject, parameters); wrapper->start(); } void SetupProjectJob::reportError(const ErrorInfo &error) { auto const wrapper = qobject_cast(internalJob()); auto const job = qobject_cast(wrapper->synchronousJob()); job->reportError(error); } void SetupProjectJob::finish() { // If the new project was successfully created, invalidate the existing one. // The invariant is that there must always be at most one valid Project object // for the same build directory, so that exclusive ownership of the build graph lock // is ensured. // We also need to invalidate the project if an error has occurred after the build data was // already transferred. if (m_existingProject.isValid() && (!error().hasError() || !m_existingProject.d->internalProject->buildData)) { m_existingProject.d->internalProject.reset(); } } /*! * \class ProcessResult * \brief The \c ProcessResult class represents the result of one external program run by Qbs. * * The \c ProcessResult class represents all the information on one external program that was * run by Qbs. It includes the command line used to start the program, the working directory * as well as output and exit codes. */ /*! * \class BuildJob * \brief The \c BuildJob class represents a build operation. */ /*! * \fn void BuildJob::reportCommandDescription(const QString &highlight, const QString &message) * \brief Signals that a new command is being worked on. * The \a highlight parameter is used to decide on the colors and font styles to be used to * print the message. * The \a message parameter is the localized message to print. */ /*! * \fn void BuildJob::reportProcessResult(const qbs::ProcessResult &result) * \brief Signals that an external command has finished. * The \a result parameter contains all details on the process that was run by Qbs. */ BuildJob::BuildJob(const Logger &logger, QObject *parent) : AbstractJob(new InternalBuildJob(logger), parent) { connect(&LauncherInterface::instance(), &LauncherInterface::errorOccurred, this, &BuildJob::handleLauncherError); auto job = static_cast(internalJob()); connect(job, &BuildGraphTouchingJob::reportCommandDescription, this, &BuildJob::reportCommandDescription); connect(job, &BuildGraphTouchingJob::reportProcessResult, this, &BuildJob::reportProcessResult); } void BuildJob::build(const TopLevelProjectPtr &project, const QList &products, const BuildOptions &options) { if (!lockProject(project)) return; LauncherInterface::startLauncher(); qobject_cast(internalJob())->build(project, products, options); } void BuildJob::handleLauncherError(const ErrorInfo &error) { setError(error); cancel(); } void BuildJob::finish() { LauncherInterface::stopLauncher(); } /*! * \class CleanJob * \brief The \c CleanJob class represents an operation removing build artifacts. */ CleanJob::CleanJob(const Logger &logger, QObject *parent) : AbstractJob(new InternalJobThreadWrapper(new InternalCleanJob(logger)), parent) { } void CleanJob::clean(const TopLevelProjectPtr &project, const QList &products, const qbs::CleanOptions &options) { if (!lockProject(project)) return; auto wrapper = qobject_cast(internalJob()); qobject_cast(wrapper->synchronousJob())->init(project, products, options); wrapper->start(); } /*! * \class InstallJob * \brief The \c InstallJob class represents an operation installing files. */ InstallJob::InstallJob(const Logger &logger, QObject *parent) : AbstractJob(new InternalJobThreadWrapper(new InternalInstallJob(logger)), parent) { } void InstallJob::install(const TopLevelProjectPtr &project, const QList &products, const InstallOptions &options) { if (!lockProject(project)) return; auto wrapper = qobject_cast(internalJob()); auto installJob = qobject_cast(wrapper->synchronousJob()); installJob->init(project, std::vector(products.cbegin(), products.cend()), options); wrapper->start(); } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/api/jobs.h000066400000000000000000000124341347155106100200110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_JOBS_H #define QBS_JOBS_H #include "project.h" #include "../language/forward_decls.h" #include "../tools/error.h" #include "../tools/qbs_export.h" #include #include #include namespace qbs { class BuildOptions; class CleanOptions; class InstallOptions; class ProcessResult; class SetupProjectParameters; namespace Internal { class InternalJob; class Logger; class ProjectPrivate; } // namespace Internal class Project; class QBS_EXPORT AbstractJob : public QObject { Q_OBJECT public: ~AbstractJob(); enum State { StateRunning, StateCanceling, StateFinished }; State state() const { return m_state; } ErrorInfo error() const; public slots: void cancel(); protected: AbstractJob(Internal::InternalJob *internalJob, QObject *parent); Internal::InternalJob *internalJob() const { return m_internalJob; } bool lockProject(const Internal::TopLevelProjectPtr &project); void setError(const ErrorInfo &error) { m_error = error; } signals: void taskStarted(const QString &description, int maximumProgressValue, qbs::AbstractJob *job); void totalEffortChanged(int totalEffort, qbs::AbstractJob *job); void taskProgress(int newProgressValue, qbs::AbstractJob *job); void finished(bool success, qbs::AbstractJob *job); private: void handleTaskStarted(const QString &description, int maximumProgressValue); void handleTotalEffortChanged(int totalEffort); void handleTaskProgress(int newProgressValue); void handleFinished(); void unlockProject(); virtual void finish() { } Internal::InternalJob * const m_internalJob; Internal::TopLevelProjectPtr m_project; ErrorInfo m_error; State m_state; }; class QBS_EXPORT SetupProjectJob : public AbstractJob { Q_OBJECT friend class Project; public: Project project() const; private: SetupProjectJob(const Internal::Logger &logger, QObject *parent); void resolve(const Project &existingProject, const SetupProjectParameters ¶meters); void reportError(const ErrorInfo &error); void finish() override; Project m_existingProject; }; class QBS_EXPORT BuildJob : public AbstractJob { Q_OBJECT friend class Internal::ProjectPrivate; signals: void reportCommandDescription(const QString &highlight, const QString &message); void reportProcessResult(const qbs::ProcessResult &result); private: BuildJob(const Internal::Logger &logger, QObject *parent); void build(const Internal::TopLevelProjectPtr &project, const QList &products, const BuildOptions &options); void handleLauncherError(const ErrorInfo &error); void finish() override; }; class QBS_EXPORT CleanJob : public AbstractJob { Q_OBJECT friend class Internal::ProjectPrivate; private: CleanJob(const Internal::Logger &logger, QObject *parent); void clean(const Internal::TopLevelProjectPtr &project, const QList &products, const CleanOptions &options); }; class QBS_EXPORT InstallJob : public AbstractJob { Q_OBJECT friend class Internal::ProjectPrivate; private: InstallJob(const Internal::Logger &logger, QObject *parent); void install(const Internal::TopLevelProjectPtr &project, const QList &products, const InstallOptions &options); }; } // namespace qbs #endif // QBS_JOBS_H qbs-src-1.13.1/src/lib/corelib/api/languageinfo.cpp000066400000000000000000000125761347155106100220550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "languageinfo.h" #include #include #include #include namespace qbs { std::string LanguageInfo::qmlTypeInfo() { const Internal::BuiltinDeclarations &builtins = Internal::BuiltinDeclarations::instance(); // Header: std::string result; result.append("import QtQuick.tooling 1.0\n\n"); result.append("// This file describes the plugin-supplied types contained in the library.\n"); result.append("// It is used for QML tooling purposes only.\n\n"); result.append("Module {\n"); // Individual Components: auto typeNames = builtins.allTypeNames(); typeNames.sort(); for (const QString &typeName : qAsConst(typeNames)) { QByteArray utf8TypeName = typeName.toUtf8(); result.append(" Component {\n"); result.append(QByteArray(" name: \"") + utf8TypeName + QByteArray("\"\n")); result.append(" exports: [ \"qbs/"); result.append(utf8TypeName); result.append(" "); const auto v = builtins.languageVersion(); result.append(QStringLiteral("%1.%2") .arg(v.majorVersion()).arg(v.minorVersion()).toUtf8()); result.append("\" ]\n"); result.append(" prototype: \"QQuickItem\"\n"); Internal::ItemDeclaration itemDecl = builtins.declarationsForType(builtins.typeForName(typeName)); auto properties = itemDecl.properties(); std::sort(std::begin(properties), std::end(properties), [] (const Internal::PropertyDeclaration &a, const Internal::PropertyDeclaration &b) { return a.name() < b.name(); }); for (const Internal::PropertyDeclaration &property : qAsConst(properties)) { result.append(" Property { name: \""); result.append(property.name().toUtf8()); result.append("\"; "); switch (property.type()) { case qbs::Internal::PropertyDeclaration::UnknownType: result.append("type: \"unknown\""); break; case qbs::Internal::PropertyDeclaration::Boolean: result.append("type: \"bool\""); break; case qbs::Internal::PropertyDeclaration::Integer: result.append("type: \"int\""); break; case qbs::Internal::PropertyDeclaration::Path: result.append("type: \"string\""); break; case qbs::Internal::PropertyDeclaration::PathList: result.append("type: \"string\"; isList: true"); break; case qbs::Internal::PropertyDeclaration::String: result.append("type: \"string\""); break; case qbs::Internal::PropertyDeclaration::StringList: result.append("type: \"string\"; isList: true"); break; case qbs::Internal::PropertyDeclaration::Variant: result.append("type: \"QVariant\""); break; case qbs::Internal::PropertyDeclaration::VariantList: result.append("type: \"QVariantList\""); break; } result.append(" }\n"); // Property } result.append(" }\n"); // Component } // Footer: result.append("}\n"); // Module return result; } Version LanguageInfo::qbsVersion() { static const auto v = Version::fromString(QLatin1String(QBS_VERSION)); return v; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/api/languageinfo.h000066400000000000000000000042601347155106100215110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LANGUAGEINFO_H #define QBS_LANGUAGEINFO_H #include "../tools/qbs_export.h" #include namespace qbs { class Version; class QBS_EXPORT LanguageInfo { LanguageInfo() = delete; public: static std::string qmlTypeInfo(); static Version qbsVersion(); }; } // namespace qbs #endif // QBS_LANGUAGEINFO_H qbs-src-1.13.1/src/lib/corelib/api/project.cpp000066400000000000000000001570031347155106100210570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "project.h" #include "project_p.h" #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES #include "projectfileupdater.h" #endif #include "internaljobs.h" #include "jobs.h" #include "projectdata_p.h" #include "propertymap_p.h" #include "rulecommand_p.h" #include "runenvironment.h" #include "transformerdata_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static bool pluginsLoaded = false; static std::mutex pluginsLoadedMutex; static void loadPlugins(const QStringList &_pluginPaths, const Logger &logger) { std::lock_guard locker(pluginsLoadedMutex); if (pluginsLoaded) return; std::vector pluginPaths; for (const QString &pluginPath : _pluginPaths) { if (!FileInfo::exists(pluginPath)) { #ifndef QBS_STATIC_LIB logger.qbsWarning() << Tr::tr("Plugin path '%1' does not exist.") .arg(QDir::toNativeSeparators(pluginPath)); #endif } else { pluginPaths.push_back(pluginPath.toStdString()); } } auto pluginManager = QbsPluginManager::instance(); pluginManager->loadStaticPlugins(); pluginManager->loadPlugins(pluginPaths, logger); qRegisterMetaType("qbs::ErrorInfo"); qRegisterMetaType("qbs::ProcessResult"); qRegisterMetaType("Internal::InternalJob *"); qRegisterMetaType("qbs::AbstractJob *"); pluginsLoaded = true; } ProjectData ProjectPrivate::projectData() { m_projectData = ProjectData(); retrieveProjectData(m_projectData, internalProject); m_projectData.d->buildDir = internalProject->buildDirectory; return m_projectData; } static void addDependencies(QList &products) { for (int i = 0; i < products.size(); ++i) { const ResolvedProductPtr &product = products.at(i); for (const ResolvedProductPtr &dependency : qAsConst(product->dependencies)) { if (!products.contains(dependency)) products.push_back(dependency); } } } BuildJob *ProjectPrivate::buildProducts(const QList &products, const BuildOptions &options, bool needsDepencencyResolving, QObject *jobOwner) { QList productsToBuild = products; if (needsDepencencyResolving) addDependencies(productsToBuild); const auto job = new BuildJob(logger, jobOwner); job->build(internalProject, productsToBuild, options); QBS_ASSERT(job->state() == AbstractJob::StateRunning,); return job; } CleanJob *ProjectPrivate::cleanProducts(const QList &products, const CleanOptions &options, QObject *jobOwner) { const auto job = new CleanJob(logger, jobOwner); job->clean(internalProject, products, options); QBS_ASSERT(job->state() == AbstractJob::StateRunning,); return job; } InstallJob *ProjectPrivate::installProducts(const QList &products, const InstallOptions &options, bool needsDepencencyResolving, QObject *jobOwner) { QList productsToInstall = products; if (needsDepencencyResolving) addDependencies(productsToInstall); const auto job = new InstallJob(logger, jobOwner); job->install(internalProject, productsToInstall, options); QBS_ASSERT(job->state() == AbstractJob::StateRunning,); return job; } QList ProjectPrivate::internalProducts(const QList &products) const { QList internalProducts; for (const ProductData &product : products) { if (product.isEnabled()) internalProducts.push_back(internalProduct(product)); } return internalProducts; } static QList enabledInternalProducts(const ResolvedProjectConstPtr &project, bool includingNonDefault) { QList products; for (const ResolvedProductPtr &p : project->products) { if (p->enabled && (includingNonDefault || p->builtByDefault())) products.push_back(p); } for (const ResolvedProjectConstPtr &subProject : qAsConst(project->subProjects)) products << enabledInternalProducts(subProject, includingNonDefault); return products; } QList ProjectPrivate::allEnabledInternalProducts(bool includingNonDefault) const { return enabledInternalProducts(internalProject, includingNonDefault); } static bool matches(const ProductData &product, const ResolvedProductConstPtr &rproduct) { return product.name() == rproduct->name && product.multiplexConfigurationId() == rproduct->multiplexConfigurationId; } static ResolvedProductPtr internalProductForProject(const ResolvedProjectConstPtr &project, const ProductData &product) { for (const ResolvedProductPtr &resolvedProduct : project->products) { if (matches(product, resolvedProduct)) return resolvedProduct; } for (const ResolvedProjectConstPtr &subProject : qAsConst(project->subProjects)) { const ResolvedProductPtr &p = internalProductForProject(subProject, product); if (p) return p; } return {}; } ResolvedProductPtr ProjectPrivate::internalProduct(const ProductData &product) const { return internalProductForProject(internalProject, product); } ProductData ProjectPrivate::findProductData(const ProductData &product) const { for (const ProductData &p : m_projectData.allProducts()) { if (p.name() == product.name() && p.profile() == product.profile() && p.multiplexConfigurationId() == product.multiplexConfigurationId()) { return p; } } return {}; } QList ProjectPrivate::findProductsByName(const QString &name) const { QList list; for (const ProductData &p : m_projectData.allProducts()) { if (p.name() == name) list.push_back(p); } return list; } GroupData ProjectPrivate::findGroupData(const ProductData &product, const QString &groupName) const { for (const GroupData &g : product.groups()) { if (g.name() == groupName) return g; } return {}; } GroupData ProjectPrivate::createGroupDataFromGroup(const GroupPtr &resolvedGroup, const ResolvedProductConstPtr &product) { GroupData group; group.d->name = resolvedGroup->name; group.d->prefix = resolvedGroup->prefix; group.d->location = resolvedGroup->location; for (const SourceArtifactConstPtr &sa : resolvedGroup->files) { ArtifactData artifact = createApiSourceArtifact(sa); setupInstallData(artifact, product); group.d->sourceArtifacts.push_back(artifact); } if (resolvedGroup->wildcards) { for (const SourceArtifactConstPtr &sa : resolvedGroup->wildcards->files) { ArtifactData artifact = createApiSourceArtifact(sa); setupInstallData(artifact, product); group.d->sourceArtifactsFromWildcards.push_back(artifact); } } std::sort(group.d->sourceArtifacts.begin(), group.d->sourceArtifacts.end()); std::sort(group.d->sourceArtifactsFromWildcards.begin(), group.d->sourceArtifactsFromWildcards.end()); group.d->properties.d->m_map = resolvedGroup->properties; group.d->isEnabled = resolvedGroup->enabled; group.d->isValid = true; return group; } ArtifactData ProjectPrivate::createApiSourceArtifact(const SourceArtifactConstPtr &sa) { ArtifactData saApi; saApi.d->isValid = true; saApi.d->filePath = sa->absoluteFilePath; saApi.d->fileTags = sa->fileTags.toStringList(); saApi.d->isGenerated = false; saApi.d->isTargetArtifact = false; saApi.d->properties.d->m_map = sa->properties; return saApi; } ArtifactData ProjectPrivate::createArtifactData(const Artifact *artifact, const ResolvedProductConstPtr &product, const ArtifactSet &targetArtifacts) { ArtifactData ta; ta.d->filePath = artifact->filePath(); ta.d->fileTags = artifact->fileTags().toStringList(); ta.d->properties.d->m_map = artifact->properties; ta.d->isGenerated = artifact->artifactType == Artifact::Generated; ta.d->isTargetArtifact = targetArtifacts.contains(const_cast(artifact)); ta.d->isValid = true; setupInstallData(ta, product); return ta; } void ProjectPrivate::setupInstallData(ArtifactData &artifact, const ResolvedProductConstPtr &product) { artifact.d->installData.d->isValid = true; artifact.d->installData.d->isInstallable = artifact.properties().getModuleProperty( StringConstants::qbsModule(), StringConstants::installProperty()).toBool(); if (!artifact.d->installData.d->isInstallable) return; const QString installRoot = artifact.properties().getModuleProperty( StringConstants::qbsModule(), StringConstants::installRootProperty()).toString(); InstallOptions options; options.setInstallRoot(installRoot); artifact.d->installData.d->installRoot = installRoot; try { QString installFilePath = ProductInstaller::targetFilePath(product->topLevelProject(), product->sourceDirectory, artifact.filePath(), artifact.properties().d->m_map, options); if (!installRoot.isEmpty()) installFilePath.remove(0, installRoot.size()); artifact.d->installData.d->installFilePath = installFilePath; } catch (const ErrorInfo &e) { logger.printWarning(e); } } #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES void ProjectPrivate::addGroup(const ProductData &product, const QString &groupName) { if (groupName.isEmpty()) throw ErrorInfo(Tr::tr("Group has an empty name.")); if (!product.isValid()) throw ErrorInfo(Tr::tr("Product is invalid.")); QList products = findProductsByName(product.name()); if (products.empty()) throw ErrorInfo(Tr::tr("Product '%1' does not exist.").arg(product.name())); const QList resolvedProducts = internalProducts(products); QBS_CHECK(products.size() == resolvedProducts.size()); for (const GroupPtr &resolvedGroup : resolvedProducts.front()->groups) { if (resolvedGroup->name == groupName) { throw ErrorInfo(Tr::tr("Group '%1' already exists in product '%2'.") .arg(groupName, product.name()), resolvedGroup->location); } } ProjectFileGroupInserter groupInserter(products.front(), groupName); groupInserter.apply(); m_projectData.d.detach(); // The data we already gave out must stay as it is. updateInternalCodeLocations(internalProject, groupInserter.itemPosition(), groupInserter.lineOffset()); updateExternalCodeLocations(m_projectData, groupInserter.itemPosition(), groupInserter.lineOffset()); products = findProductsByName(products.front().name()); // These are new objects. QBS_CHECK(products.size() == resolvedProducts.size()); for (int i = 0; i < products.size(); ++i) { const GroupPtr resolvedGroup = ResolvedGroup::create(); resolvedGroup->location = groupInserter.itemPosition(); resolvedGroup->enabled = true; resolvedGroup->name = groupName; resolvedGroup->properties = resolvedProducts[i]->moduleProperties; resolvedGroup->overrideTags = false; resolvedProducts.at(i)->groups << resolvedGroup; QList &groupData = products.at(i).d->groups; groupData << createGroupDataFromGroup(resolvedGroup, resolvedProducts.at(i)); std::sort(groupData.begin(), groupData.end()); } } ProjectPrivate::GroupUpdateContext ProjectPrivate::getGroupContext(const ProductData &product, const GroupData &group) { GroupUpdateContext context; if (!product.isValid()) throw ErrorInfo(Tr::tr("Product is invalid.")); context.products = findProductsByName(product.name()); if (context.products.empty()) throw ErrorInfo(Tr::tr("Product '%1' does not exist.").arg(product.name())); context.resolvedProducts = internalProducts(context.products); const QString groupName = group.isValid() ? group.name() : product.name(); for (const ResolvedProductPtr &p : qAsConst(context.resolvedProducts)) { for (const GroupPtr &g : p->groups) { if (g->name == groupName) { context.resolvedGroups << g; break; } } } if (context.resolvedGroups.empty()) throw ErrorInfo(Tr::tr("Group '%1' does not exist.").arg(groupName)); for (const ProductData &p : qAsConst(context.products)) { const GroupData &g = findGroupData(p, groupName); QBS_CHECK(p.isValid()); context.groups << g; } QBS_CHECK(context.resolvedProducts.size() == context.products.size()); QBS_CHECK(context.resolvedProducts.size() == context.resolvedGroups.size()); QBS_CHECK(context.products.size() == context.groups.size()); return context; } static bool matchesWildcard(const QString &filePath, const GroupConstPtr &group) { if (!group->wildcards) return false; for (const QString &pattern : qAsConst(group->wildcards->patterns)) { QString fullPattern; if (QFileInfo(group->prefix).isAbsolute()) { fullPattern = group->prefix; } else { fullPattern = QFileInfo(group->location.filePath()).absolutePath() + QLatin1Char('/') + group->prefix; } fullPattern.append(QLatin1Char('/')).append(pattern); fullPattern = QDir::cleanPath(fullPattern); if (QRegExp(fullPattern, Qt::CaseSensitive, QRegExp::Wildcard).exactMatch(filePath)) return true; } return false; } ProjectPrivate::FileListUpdateContext ProjectPrivate::getFileListContext(const ProductData &product, const GroupData &group, const QStringList &filePaths, bool forAdding) { FileListUpdateContext filesContext; GroupUpdateContext &groupContext = filesContext.groupContext; groupContext = getGroupContext(product, group); if (filePaths.empty()) throw ErrorInfo(Tr::tr("No files supplied.")); QString prefix; for (int i = 0; i < groupContext.resolvedGroups.size(); ++i) { const GroupPtr &g = groupContext.resolvedGroups.at(i); if (!g->prefix.isEmpty() && !g->prefix.endsWith(QLatin1Char('/'))) throw ErrorInfo(Tr::tr("Group has non-directory prefix.")); if (i == 0) prefix = g->prefix; else if (prefix != g->prefix) throw ErrorInfo(Tr::tr("Cannot update: Group prefix depends on properties.")); } QString baseDirPath = QFileInfo(product.location().filePath()).dir().absolutePath() + QLatin1Char('/') + prefix; QDir baseDir(baseDirPath); for (const QString &filePath : filePaths) { const QString absPath = QDir::cleanPath(FileInfo::resolvePath(baseDirPath, filePath)); if (filesContext.absoluteFilePaths.contains(absPath)) throw ErrorInfo(Tr::tr("File '%1' appears more than once.").arg(absPath)); if (forAdding && !FileInfo(absPath).exists()) throw ErrorInfo(Tr::tr("File '%1' does not exist.").arg(absPath)); if (matchesWildcard(absPath, groupContext.resolvedGroups.front())) { filesContext.absoluteFilePathsFromWildcards << absPath; } else { filesContext.absoluteFilePaths << absPath; filesContext.relativeFilePaths << baseDir.relativeFilePath(absPath); } } return filesContext; } static SourceArtifactPtr createSourceArtifact(const QString &filePath, const ResolvedProductPtr &product, const GroupPtr &group, bool wildcard) { const SourceArtifactPtr artifact = ProjectResolver::createSourceArtifact(product, filePath, group, wildcard); ProjectResolver::applyFileTaggers(artifact, product); return artifact; } void ProjectPrivate::addFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths) { FileListUpdateContext filesContext = getFileListContext(product, group, filePaths, true); GroupUpdateContext &groupContext = filesContext.groupContext; // We do not check for entries in other groups, because such doublettes might be legitimate // due to conditions. for (const GroupPtr &group : qAsConst(groupContext.resolvedGroups)) { for (const QString &filePath : qAsConst(filesContext.absoluteFilePaths)) { for (const SourceArtifactConstPtr &sa : group->files) { if (sa->absoluteFilePath == filePath) { throw ErrorInfo(Tr::tr("File '%1' already exists in group '%2'.") .arg(filePath, group->name)); } } } } ProjectFileFilesAdder adder(groupContext.products.front(), group.isValid() ? groupContext.groups.front() : GroupData(), filesContext.relativeFilePaths); adder.apply(); m_projectData.d.detach(); updateInternalCodeLocations(internalProject, adder.itemPosition(), adder.lineOffset()); updateExternalCodeLocations(m_projectData, adder.itemPosition(), adder.lineOffset()); QHash> addedSourceArtifacts; for (int i = 0; i < groupContext.resolvedGroups.size(); ++i) { const ResolvedProductPtr &resolvedProduct = groupContext.resolvedProducts.at(i); const GroupPtr &resolvedGroup = groupContext.resolvedGroups.at(i); for (const QString &file : qAsConst(filesContext.absoluteFilePaths)) { const SourceArtifactPtr sa = createSourceArtifact(file, resolvedProduct, resolvedGroup, false); addedSourceArtifacts.insert(file, std::make_pair(sa, resolvedProduct)); } for (const QString &file : qAsConst(filesContext.absoluteFilePathsFromWildcards)) { QBS_CHECK(resolvedGroup->wildcards); const SourceArtifactPtr sa = createSourceArtifact(file, resolvedProduct, resolvedGroup, true); addedSourceArtifacts.insert(file, std::make_pair(sa, resolvedProduct)); } if (resolvedProduct->enabled) { for (const auto &pair : qAsConst(addedSourceArtifacts)) createArtifact(resolvedProduct, pair.first); } } doSanityChecks(internalProject, logger); QList sourceArtifacts; QList sourceArtifactsFromWildcards; for (const QString &fp : qAsConst(filesContext.absoluteFilePaths)) { const auto pair = addedSourceArtifacts.value(fp); const SourceArtifactConstPtr sa = pair.first; QBS_CHECK(sa); ArtifactData artifactData = createApiSourceArtifact(sa); setupInstallData(artifactData, pair.second); sourceArtifacts << artifactData; } for (const QString &fp : qAsConst(filesContext.absoluteFilePathsFromWildcards)) { const auto pair = addedSourceArtifacts.value(fp); const SourceArtifactConstPtr sa = pair.first; QBS_CHECK(sa); ArtifactData artifactData = createApiSourceArtifact(sa); setupInstallData(artifactData, pair.second); sourceArtifactsFromWildcards << artifactData; } for (const GroupData &g : qAsConst(groupContext.groups)) { g.d->sourceArtifacts << sourceArtifacts; std::sort(g.d->sourceArtifacts.begin(), g.d->sourceArtifacts.end()); g.d->sourceArtifactsFromWildcards << sourceArtifactsFromWildcards; std::sort(g.d->sourceArtifactsFromWildcards.begin(), g.d->sourceArtifactsFromWildcards.end()); } } void ProjectPrivate::removeFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths) { FileListUpdateContext filesContext = getFileListContext(product, group, filePaths, false); GroupUpdateContext &groupContext = filesContext.groupContext; if (!filesContext.absoluteFilePathsFromWildcards.empty()) { throw ErrorInfo(Tr::tr("The following files cannot be removed from the project file, " "because they match wildcard patterns: %1") .arg(filesContext.absoluteFilePathsFromWildcards.join(QLatin1String(", ")))); } QStringList filesNotFound = filesContext.absoluteFilePaths; std::vector sourceArtifacts; for (const SourceArtifactPtr &sa : groupContext.resolvedGroups.front()->files) { if (filesNotFound.removeOne(sa->absoluteFilePath)) sourceArtifacts << sa; } if (!filesNotFound.empty()) { throw ErrorInfo(Tr::tr("The following files are not known to qbs: %1") .arg(filesNotFound.join(QLatin1String(", ")))); } ProjectFileFilesRemover remover(groupContext.products.front(), group.isValid() ? groupContext.groups.front() : GroupData(), filesContext.relativeFilePaths); remover.apply(); for (int i = 0; i < groupContext.resolvedProducts.size(); ++i) { removeFilesFromBuildGraph(groupContext.resolvedProducts.at(i), sourceArtifacts); for (const SourceArtifactPtr &sa : sourceArtifacts) removeOne(groupContext.resolvedGroups.at(i)->files, sa); } doSanityChecks(internalProject, logger); m_projectData.d.detach(); updateInternalCodeLocations(internalProject, remover.itemPosition(), remover.lineOffset()); updateExternalCodeLocations(m_projectData, remover.itemPosition(), remover.lineOffset()); for (const GroupData &g : qAsConst(groupContext.groups)) { for (int i = g.d->sourceArtifacts.size() - 1; i >= 0; --i) { if (filesContext.absoluteFilePaths.contains(g.d->sourceArtifacts.at(i).filePath())) g.d->sourceArtifacts.removeAt(i); } } } void ProjectPrivate::removeGroup(const ProductData &product, const GroupData &group) { GroupUpdateContext context = getGroupContext(product, group); ProjectFileGroupRemover remover(context.products.front(), context.groups.front()); remover.apply(); for (int i = 0; i < context.resolvedProducts.size(); ++i) { const ResolvedProductPtr &product = context.resolvedProducts.at(i); const GroupPtr &group = context.resolvedGroups.at(i); removeFilesFromBuildGraph(product, group->allFiles()); const bool removed = removeOne(product->groups, group); QBS_CHECK(removed); } doSanityChecks(internalProject, logger); m_projectData.d.detach(); updateInternalCodeLocations(internalProject, remover.itemPosition(), remover.lineOffset()); updateExternalCodeLocations(m_projectData, remover.itemPosition(), remover.lineOffset()); for (int i = 0; i < context.products.size(); ++i) { const bool removed = context.products.at(i).d->groups.removeOne(context.groups.at(i)); QBS_CHECK(removed); } } #endif // QBS_ENABLE_PROJECT_FILE_UPDATES void ProjectPrivate::removeFilesFromBuildGraph(const ResolvedProductConstPtr &product, const std::vector &files) { if (!product->enabled) return; QBS_CHECK(internalProject->buildData); ArtifactSet allRemovedArtifacts; for (const SourceArtifactPtr &sa : files) { ArtifactSet removedArtifacts; Artifact * const artifact = lookupArtifact(product, sa->absoluteFilePath); if (artifact) { // Can be null if the executor has not yet applied the respective rule. internalProject->buildData->removeArtifactAndExclusiveDependents(artifact, logger, true, &removedArtifacts); } allRemovedArtifacts.unite(removedArtifacts); } EmptyDirectoriesRemover(product->topLevelProject(), logger) .removeEmptyParentDirectories(allRemovedArtifacts); qDeleteAll(allRemovedArtifacts); } static void updateLocationIfNecessary(CodeLocation &location, const CodeLocation &changeLocation, int lineOffset) { if (location.filePath() == changeLocation.filePath() && location.line() >= changeLocation.line()) { location = CodeLocation(location.filePath(), location.line() + lineOffset, location.column()); } } void ProjectPrivate::updateInternalCodeLocations(const ResolvedProjectPtr &project, const CodeLocation &changeLocation, int lineOffset) { if (lineOffset == 0) return; updateLocationIfNecessary(project->location, changeLocation, lineOffset); for (const ResolvedProjectPtr &subProject : qAsConst(project->subProjects)) updateInternalCodeLocations(subProject, changeLocation, lineOffset); for (const ResolvedProductPtr &product : project->products) { updateLocationIfNecessary(product->location, changeLocation, lineOffset); for (const GroupPtr &group : product->groups) updateLocationIfNecessary(group->location, changeLocation, lineOffset); for (const RulePtr &rule : qAsConst(product->rules)) { updateLocationIfNecessary(rule->prepareScript.location(), changeLocation, lineOffset); for (const RuleArtifactPtr &artifact : rule->artifacts) { for (auto &binding : artifact->bindings) { updateLocationIfNecessary(binding.location, changeLocation, lineOffset); } } } for (const ResolvedScannerConstPtr &scanner : product->scanners) { updateLocationIfNecessary(scanner->searchPathsScript.location(), changeLocation, lineOffset); updateLocationIfNecessary(scanner->scanScript.location(), changeLocation, lineOffset); } for (const ResolvedModuleConstPtr &module : product->modules) { updateLocationIfNecessary(module->setupBuildEnvironmentScript.location(), changeLocation, lineOffset); updateLocationIfNecessary(module->setupRunEnvironmentScript.location(), changeLocation, lineOffset); } } } void ProjectPrivate::updateExternalCodeLocations(const ProjectData &project, const CodeLocation &changeLocation, int lineOffset) { if (lineOffset == 0) return; updateLocationIfNecessary(project.d->location, changeLocation, lineOffset); for (const ProjectData &subProject : project.subProjects()) updateExternalCodeLocations(subProject, changeLocation, lineOffset); for (const ProductData &product : project.products()) { updateLocationIfNecessary(product.d->location, changeLocation, lineOffset); for (const GroupData &group : product.groups()) updateLocationIfNecessary(group.d->location, changeLocation, lineOffset); } } void ProjectPrivate::prepareChangeToProject() { if (internalProject->locked) throw ErrorInfo(Tr::tr("A job is currently in process.")); if (!m_projectData.isValid()) retrieveProjectData(m_projectData, internalProject); } RuleCommandList ProjectPrivate::ruleCommandListForTransformer(const Transformer *transformer) { RuleCommandList list; for (const AbstractCommandPtr &internalCommand : qAsConst(transformer->commands.commands())) { RuleCommand externalCommand; externalCommand.d->description = internalCommand->description(); externalCommand.d->extendedDescription = internalCommand->extendedDescription(); switch (internalCommand->type()) { case AbstractCommand::JavaScriptCommandType: { externalCommand.d->type = RuleCommand::JavaScriptCommandType; const JavaScriptCommandPtr &jsCmd = std::static_pointer_cast(internalCommand); externalCommand.d->sourceCode = jsCmd->sourceCode(); break; } case AbstractCommand::ProcessCommandType: { externalCommand.d->type = RuleCommand::ProcessCommandType; const ProcessCommandPtr &procCmd = std::static_pointer_cast(internalCommand); externalCommand.d->executable = procCmd->program(); externalCommand.d->arguments = procCmd->arguments(); externalCommand.d->workingDir = procCmd->workingDir(); externalCommand.d->environment = procCmd->environment(); break; } } list << externalCommand; } return list; } RuleCommandList ProjectPrivate::ruleCommands(const ProductData &product, const QString &inputFilePath, const QString &outputFileTag) { if (internalProject->locked) throw ErrorInfo(Tr::tr("A job is currently in process.")); const ResolvedProductConstPtr resolvedProduct = internalProduct(product); if (!resolvedProduct) throw ErrorInfo(Tr::tr("No such product '%1'.").arg(product.name())); if (!resolvedProduct->enabled) throw ErrorInfo(Tr::tr("Product '%1' is disabled.").arg(product.name())); QBS_CHECK(resolvedProduct->buildData); const ArtifactSet &outputArtifacts = resolvedProduct->buildData->artifactsByFileTag() .value(FileTag(outputFileTag.toLocal8Bit())); for (const Artifact * const outputArtifact : qAsConst(outputArtifacts)) { const TransformerConstPtr transformer = outputArtifact->transformer; if (!transformer) continue; for (const Artifact * const inputArtifact : qAsConst(transformer->inputs)) { if (inputArtifact->filePath() == inputFilePath) return ruleCommandListForTransformer(transformer.get()); } } throw ErrorInfo(Tr::tr("No rule was found that produces an artifact tagged '%1' " "from input file '%2'.").arg(outputFileTag, inputFilePath)); } ProjectTransformerData ProjectPrivate::transformerData() { if (!m_projectData.isValid()) retrieveProjectData(m_projectData, internalProject); ProjectTransformerData projectTransformerData; for (const ProductData &productData : m_projectData.allProducts()) { if (!productData.isEnabled()) continue; const ResolvedProductConstPtr product = internalProduct(productData); QBS_ASSERT(!!product, continue); QBS_ASSERT(!!product->buildData, continue); const ArtifactSet targetArtifacts = product->targetArtifacts(); Set allTransformers; for (const Artifact * const a : TypeFilter(product->buildData->allNodes())) { if (a->artifactType == Artifact::Generated) allTransformers.insert(a->transformer.get()); } if (allTransformers.empty()) continue; ProductTransformerData productTransformerData; for (const Transformer * const t : allTransformers) { TransformerData tData; Set allInputs; for (Artifact * const a : t->outputs) { tData.d->outputs << createArtifactData(a, product, targetArtifacts); for (const Artifact * const child : filterByType(a->children)) allInputs << child; for (Artifact * const a : RulesApplicator::collectAuxiliaryInputs(t->rule.get(), product.get())) { if (a->artifactType == Artifact::Generated) tData.d->inputs << createArtifactData(a, product, targetArtifacts); } } for (const Artifact * const input : allInputs) tData.d->inputs << createArtifactData(input, product, targetArtifacts); tData.d->commands = ruleCommandListForTransformer(t); productTransformerData << tData; } projectTransformerData << qMakePair(productData, productTransformerData); } return projectTransformerData; } static bool productIsRunnable(const ResolvedProductConstPtr &product) { const bool isBundle = product->moduleProperties->moduleProperty( QStringLiteral("bundle"), QStringLiteral("isBundle")).toBool(); return isRunnableArtifact(product->fileTags, isBundle); } static bool productIsMultiplexed(const ResolvedProductConstPtr &product) { return product->productProperties.value(StringConstants::multiplexedProperty()).toBool(); } void ProjectPrivate::retrieveProjectData(ProjectData &projectData, const ResolvedProjectConstPtr &internalProject) { projectData.d->name = internalProject->name; projectData.d->location = internalProject->location; projectData.d->enabled = internalProject->enabled; for (const ResolvedProductConstPtr &resolvedProduct : internalProject->products) { ProductData product; product.d->type = resolvedProduct->fileTags.toStringList(); product.d->name = resolvedProduct->name; product.d->targetName = resolvedProduct->targetName; product.d->version = resolvedProduct ->productProperties.value(StringConstants::versionProperty()).toString(); product.d->multiplexConfigurationId = resolvedProduct->multiplexConfigurationId; product.d->location = resolvedProduct->location; product.d->buildDirectory = resolvedProduct->buildDirectory(); product.d->isEnabled = resolvedProduct->enabled; product.d->isRunnable = productIsRunnable(resolvedProduct); product.d->isMultiplexed = productIsMultiplexed(resolvedProduct); product.d->properties = resolvedProduct->productProperties; product.d->moduleProperties.d->m_map = resolvedProduct->moduleProperties; for (const GroupPtr &resolvedGroup : resolvedProduct->groups) { if (resolvedGroup->targetOfModule.isEmpty()) product.d->groups << createGroupDataFromGroup(resolvedGroup, resolvedProduct); } if (resolvedProduct->enabled) { QBS_CHECK(resolvedProduct->buildData); const ArtifactSet targetArtifacts = resolvedProduct->targetArtifacts(); for (Artifact * const a : filterByType(resolvedProduct->buildData->allNodes())) { if (a->artifactType != Artifact::Generated) continue; product.d->generatedArtifacts << createArtifactData(a, resolvedProduct, targetArtifacts); } const AllRescuableArtifactData &rad = resolvedProduct->buildData->rescuableArtifactData(); for (auto it = rad.begin(); it != rad.end(); ++it) { ArtifactData ta; ta.d->filePath = it.key(); ta.d->fileTags = it.value().fileTags.toStringList(); ta.d->properties.d->m_map = it.value().properties; ta.d->isGenerated = true; ta.d->isTargetArtifact = resolvedProduct->fileTags.intersects(it.value().fileTags); ta.d->isValid = true; setupInstallData(ta, resolvedProduct); product.d->generatedArtifacts << ta; } } for (const ResolvedProductPtr &resolvedDependentProduct : qAsConst(resolvedProduct->dependencies)) { product.d->dependencies << resolvedDependentProduct->name; } std::sort(product.d->type.begin(), product.d->type.end()); std::sort(product.d->groups.begin(), product.d->groups.end()); std::sort(product.d->generatedArtifacts.begin(), product.d->generatedArtifacts.end()); product.d->isValid = true; projectData.d->products << product; } for (const ResolvedProjectConstPtr &internalSubProject : qAsConst(internalProject->subProjects)) { if (!internalSubProject->enabled) continue; ProjectData subProject; retrieveProjectData(subProject, internalSubProject); projectData.d->subProjects << subProject; } projectData.d->isValid = true; std::sort(projectData.d->products.begin(), projectData.d->products.end()); std::sort(projectData.d->subProjects.begin(), projectData.d->subProjects.end()); } } // namespace Internal using namespace Internal; /*! * \class Project * \brief The \c Project class provides services related to a qbs project. */ Project::Project(const TopLevelProjectPtr &internalProject, const Logger &logger) : d(new ProjectPrivate(internalProject, logger)) { } Project::Project(const Project &other) : d(other.d) { } Project::~Project() { } /*! * \brief Returns true if and only if this object was retrieved from a successful \c SetupProjectJob. * \sa SetupProjectJob */ bool Project::isValid() const { return d && d->internalProject; } /*! * \brief The top-level profile for building this project. */ QString Project::profile() const { QBS_ASSERT(isValid(), return {}); return d->internalProject->profile(); } Project &Project::operator=(const Project &other) { d = other.d; return *this; } /*! * \brief Sets up a \c Project from a source file, possibly re-using previously stored information. * The function will finish immediately, returning a \c SetupProjectJob which can be used to * track the results of the operation. * If the function is called on a valid \c Project object, the build graph will not be loaded * from a file, but will be taken from the existing project. In that case, if resolving * finishes successfully, the existing project will be invalidated. If resolving fails, qbs will * try to keep the existing project valid. However, under certain circumstances, resolving the new * project will fail at a time where existing project data has already been touched, in which case * the existing project has to be invalidated (this could be avoided, but it would hurt performance). * So after an unsuccessful re-resolve job, the existing project may or may not be valid anymore. * \note The qbs plugins will only be loaded once. As a result, the value of * \c parameters.pluginPaths will only have an effect the first time this function is called. * Similarly, the value of \c parameters.searchPaths will not have an effect if * a stored build graph is available. */ SetupProjectJob *Project::setupProject(const SetupProjectParameters ¶meters, ILogSink *logSink, QObject *jobOwner) { Logger logger(logSink); const auto job = new SetupProjectJob(logger, jobOwner); try { loadPlugins(parameters.pluginPaths(), logger); job->resolve(*this, parameters); QBS_ASSERT(job->state() == AbstractJob::StateRunning,); } catch (const ErrorInfo &error) { // Throwing from here would complicate the API, so let's report the error the same way // as all others, via AbstractJob::error(). job->reportError(error); } return job; } Project::Project() { } /*! * \brief Retrieves information for this project. * Call this function if you need insight into the project structure, e.g. because you want to know * which products or files are in it. */ ProjectData Project::projectData() const { QBS_ASSERT(isValid(), return {}); return d->projectData(); } RunEnvironment Project::getRunEnvironment(const ProductData &product, const InstallOptions &installOptions, const QProcessEnvironment &environment, const QStringList &setupRunEnvConfig, Settings *settings) const { const ResolvedProductPtr resolvedProduct = d->internalProduct(product); return RunEnvironment(resolvedProduct, d->internalProject, installOptions, environment, setupRunEnvConfig, settings, d->logger); } /*! * \enum Project::ProductSelection * This enum type specifies which products to include if "all" products are to be built. * \value Project::ProdProductSelectionDefaultOnly Indicates that only those products should be * built whose \c builtByDefault property * is \c true. * \value Project::ProdProductSelectionWithNonDefault Indicates that products whose * \c builtByDefault property is \c false should * also be built. */ /*! * \brief Causes all products of this project to be built, if necessary. * If and only if \c producSelection is \c Project::ProductSelectionWithNonDefault, products with * the \c builtByDefault property set to \c false will be built too. * The function will finish immediately, returning a \c BuildJob identifiying the operation. */ BuildJob *Project::buildAllProducts(const BuildOptions &options, ProductSelection productSelection, QObject *jobOwner) const { QBS_ASSERT(isValid(), return nullptr); const bool includingNonDefault = productSelection == ProductSelectionWithNonDefault; return d->buildProducts(d->allEnabledInternalProducts(includingNonDefault), options, !includingNonDefault, jobOwner); } /*! * \brief Causes the specified list of products to be built. * Use this function if you only want to build some products, not the whole project. If any of * the products in \a products depend on other products, those will also be built. * The function will finish immediately, returning a \c BuildJob identifiying the operation. */ BuildJob *Project::buildSomeProducts(const QList &products, const BuildOptions &options, QObject *jobOwner) const { QBS_ASSERT(isValid(), return nullptr); return d->buildProducts(d->internalProducts(products), options, true, jobOwner); } /*! * \brief Convenience function for \c buildSomeProducts(). * \sa Project::buildSomeProducts(). */ BuildJob *Project::buildOneProduct(const ProductData &product, const BuildOptions &options, QObject *jobOwner) const { return buildSomeProducts(QList() << product, options, jobOwner); } /*! * \brief Removes the build artifacts of all products in the project. * The function will finish immediately, returning a \c CleanJob identifiying this operation. * \sa Project::cleanSomeProducts() */ CleanJob *Project::cleanAllProducts(const CleanOptions &options, QObject *jobOwner) const { QBS_ASSERT(isValid(), return nullptr); return d->cleanProducts(d->allEnabledInternalProducts(true), options, jobOwner); } /*! * \brief Removes the build artifacts of the given products. * The function will finish immediately, returning a \c CleanJob identifiying this operation. */ CleanJob *Project::cleanSomeProducts(const QList &products, const CleanOptions &options, QObject *jobOwner) const { QBS_ASSERT(isValid(), return nullptr); return d->cleanProducts(d->internalProducts(products), options, jobOwner); } /*! * \brief Convenience function for \c cleanSomeProducts(). * \sa Project::cleanSomeProducts(). */ CleanJob *Project::cleanOneProduct(const ProductData &product, const CleanOptions &options, QObject *jobOwner) const { return cleanSomeProducts(QList() << product, options, jobOwner); } /*! * \brief Installs the installable files of all products in the project. * If and only if \c producSelection is \c Project::ProductSelectionWithNonDefault, products with * the \c builtByDefault property set to \c false will be installed too. * The function will finish immediately, returning an \c InstallJob identifiying this operation. */ InstallJob *Project::installAllProducts(const InstallOptions &options, ProductSelection productSelection, QObject *jobOwner) const { QBS_ASSERT(isValid(), return nullptr); const bool includingNonDefault = productSelection == ProductSelectionWithNonDefault; return d->installProducts(d->allEnabledInternalProducts(includingNonDefault), options, !includingNonDefault, jobOwner); } /*! * \brief Installs the installable files of the given products. * The function will finish immediately, returning an \c InstallJob identifiying this operation. */ InstallJob *Project::installSomeProducts(const QList &products, const InstallOptions &options, QObject *jobOwner) const { QBS_ASSERT(isValid(), return nullptr); return d->installProducts(d->internalProducts(products), options, true, jobOwner); } /*! * \brief Convenience function for \c installSomeProducts(). * \sa Project::installSomeProducts(). */ InstallJob *Project::installOneProduct(const ProductData &product, const InstallOptions &options, QObject *jobOwner) const { return installSomeProducts(QList() << product, options, jobOwner); } /*! * \brief Updates the timestamps of all build artifacts in the given products. * Afterwards, the build graph will have the same state as if a successful build had been done. */ void Project::updateTimestamps(const QList &products) { QBS_ASSERT(isValid(), return); TimestampsUpdater().updateTimestamps(d->internalProject, d->internalProducts(products), d->logger); } /*! * \brief Finds files generated from the given file in the given product. * If \a recursive is \c false, only files generated directly from \a file will be considered, * otherwise the generated files are collected recursively. * If \a tags is not empty, only generated files matching at least one of these tags will * be considered. */ QStringList Project::generatedFiles(const ProductData &product, const QString &file, bool recursive, const QStringList &tags) const { QBS_ASSERT(isValid(), return {}); const ResolvedProductConstPtr internalProduct = d->internalProduct(product); return internalProduct->generatedFiles(file, recursive, FileTags::fromStringList(tags)); } QVariantMap Project::projectConfiguration() const { QBS_ASSERT(isValid(), return {}); return d->internalProject->buildConfiguration(); } std::set Project::buildSystemFiles() const { QBS_ASSERT(isValid(), return {}); return d->internalProject->buildSystemFiles.toStdSet(); } RuleCommandList Project::ruleCommands(const ProductData &product, const QString &inputFilePath, const QString &outputFileTag, ErrorInfo *error) const { QBS_ASSERT(isValid(), return {}); QBS_ASSERT(product.isValid(), return {}); try { return d->ruleCommands(product, inputFilePath, outputFileTag); } catch (const ErrorInfo &e) { if (error) *error = e; return {}; } } ProjectTransformerData Project::transformerData(ErrorInfo *error) const { QBS_ASSERT(isValid(), return {}); try { return d->transformerData(); } catch (const ErrorInfo &e) { if (error) *error = e; return {}; } } ErrorInfo Project::dumpNodesTree(QIODevice &outDevice, const QList &products) { try { NodeTreeDumper(outDevice).start(d->internalProducts(products)); } catch (const ErrorInfo &e) { return e; } return {}; } Project::BuildGraphInfo Project::getBuildGraphInfo(const QString &bgFilePath, const QStringList &requestedProperties) { BuildGraphInfo info; try { const Internal::TopLevelProjectConstPtr project = BuildGraphLoader::loadProject(bgFilePath); info.bgFilePath = bgFilePath; info.overriddenProperties = project->overriddenValues; info.profileData = project->profileConfigs; std::vector> props; for (const QString &prop : requestedProperties) { QStringList components = prop.split(QLatin1Char('.')); const QString propName = components.takeLast(); props.push_back(std::make_pair(components.join(QLatin1Char('.')), propName)); } for (const ResolvedProductConstPtr &product : project->allProducts()) { if (props.empty()) break; if (product->profile() != project->profile()) continue; for (auto it = props.begin(); it != props.end();) { const QVariant value = product->moduleProperties->moduleProperty(it->first, it->second); if (value.isValid()) { info.requestedProperties.insert(it->first + QLatin1Char('.') + it->second, value); it = props.erase(it); } else { ++it; } } } } catch (const ErrorInfo &e) { info.error = e; } return info; } #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES /*! * \brief Adds a new empty group to the given product. * Returns an \c ErrorInfo object for which \c hasError() is false in case of a success * and true otherwise. In the latter case, the object will have a sensible description. * After calling this function, it is recommended to re-fetch the project data, as other * items can be affected. * \sa qbs::Project::projectData() */ ErrorInfo Project::addGroup(const ProductData &product, const QString &groupName) { try { QBS_CHECK(isValid()); d->prepareChangeToProject(); d->addGroup(product, groupName); d->internalProject->lastStartResolveTime = FileTime::currentTime(); d->internalProject->store(d->logger); return {}; } catch (ErrorInfo errorInfo) { errorInfo.prepend(Tr::tr("Failure adding group '%1' to product '%2'.") .arg(groupName, product.name())); return errorInfo; } } /*! * \brief Adds the given files to the given product. * If \c group is a default-constructed object, the files will be added to the product's * "files" property, otherwise to the one of \c group. * The file paths can be absolute or relative to the location of \c product (including a possible * prefix in the group). The project file will always contain relative paths. * After calling this function, it is recommended to re-fetch the project data, as other * items can be affected. * \sa qbs::Project::projectData() */ ErrorInfo Project::addFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths) { try { QBS_CHECK(isValid()); d->prepareChangeToProject(); d->addFiles(product, group, filePaths); d->internalProject->lastStartResolveTime = FileTime::currentTime(); d->internalProject->store(d->logger); return {}; } catch (ErrorInfo errorInfo) { errorInfo.prepend(Tr::tr("Failure adding files to product.")); return errorInfo; } } /*! * \brief Removes the given files from the given product. * If \c group is a default-constructed object, the files will be removed from the product's * "files" property, otherwise from the one of \c group. * The file paths can be absolute or relative to the location of \c product (including a possible * prefix in the group). * After calling this function, it is recommended to re-fetch the project data, as other * items can be affected. * \sa qbs::Project::projectData() */ ErrorInfo Project::removeFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths) { try { QBS_CHECK(isValid()); d->prepareChangeToProject(); d->removeFiles(product, group, filePaths); d->internalProject->lastStartResolveTime = FileTime::currentTime(); d->internalProject->store(d->logger); return {}; } catch (ErrorInfo errorInfo) { errorInfo.prepend(Tr::tr("Failure removing files from product '%1'.").arg(product.name())); return errorInfo; } } /*! * \brief Removes the given group from the given product. * After calling this function, it is recommended to re-fetch the project data, as other * items can be affected. * \sa qbs::Project::projectData() */ ErrorInfo Project::removeGroup(const ProductData &product, const GroupData &group) { try { QBS_CHECK(isValid()); d->prepareChangeToProject(); d->removeGroup(product, group); d->internalProject->lastStartResolveTime = FileTime::currentTime(); d->internalProject->store(d->logger); return {}; } catch (ErrorInfo errorInfo) { errorInfo.prepend(Tr::tr("Failure removing group '%1' from product '%2'.") .arg(group.name(), product.name())); return errorInfo; } } #endif // QBS_ENABLE_PROJECT_FILE_UPDATES } // namespace qbs qbs-src-1.13.1/src/lib/corelib/api/project.h000066400000000000000000000157471347155106100205340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROJECT_H #define QBS_PROJECT_H #include "rulecommand.h" #include "transformerdata.h" #include "../language/forward_decls.h" #include "../tools/error.h" #include "../tools/qbs_export.h" #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QIODevice; class QObject; class QProcessEnvironment; QT_END_NAMESPACE namespace qbs { class BuildJob; class BuildOptions; class CleanJob; class CleanOptions; class GroupData; class ILogSink; class InstallJob; class InstallOptions; class ProductData; class ProjectData; class RunEnvironment; class Settings; class SetupProjectJob; class SetupProjectParameters; namespace Internal { class Logger; class ProjectPrivate; } // namespace Internal; class QBS_EXPORT Project { friend class SetupProjectJob; friend uint qHash(const Project &p); public: SetupProjectJob *setupProject(const SetupProjectParameters ¶meters, ILogSink *logSink, QObject *jobOwner); Project(); Project(const Project &other); Project &operator=(const Project &other); ~Project(); bool isValid() const; QString profile() const; ProjectData projectData() const; RunEnvironment getRunEnvironment(const ProductData &product, const InstallOptions &installOptions, const QProcessEnvironment &environment, const QStringList &setupRunEnvConfig, Settings *settings) const; enum ProductSelection { ProductSelectionDefaultOnly, ProductSelectionWithNonDefault }; BuildJob *buildAllProducts(const BuildOptions &options, ProductSelection productSelection = ProductSelectionDefaultOnly, QObject *jobOwner = nullptr) const; BuildJob *buildSomeProducts(const QList &products, const BuildOptions &options, QObject *jobOwner = nullptr) const; BuildJob *buildOneProduct(const ProductData &product, const BuildOptions &options, QObject *jobOwner = nullptr) const; CleanJob *cleanAllProducts(const CleanOptions &options, QObject *jobOwner = nullptr) const; CleanJob *cleanSomeProducts(const QList &products, const CleanOptions &options, QObject *jobOwner = nullptr) const; CleanJob *cleanOneProduct(const ProductData &product, const CleanOptions &options, QObject *jobOwner = nullptr) const; InstallJob *installAllProducts(const InstallOptions &options, ProductSelection productSelection = ProductSelectionDefaultOnly, QObject *jobOwner = nullptr) const; InstallJob *installSomeProducts(const QList &products, const InstallOptions &options, QObject *jobOwner = nullptr) const; InstallJob *installOneProduct(const ProductData &product, const InstallOptions &options, QObject *jobOwner = nullptr) const; void updateTimestamps(const QList &products); bool operator==(const Project &other) const { return d.data() == other.d.data(); } QStringList generatedFiles(const ProductData &product, const QString &file, bool recursive, const QStringList &tags = QStringList()) const; QVariantMap projectConfiguration() const; std::set buildSystemFiles() const; RuleCommandList ruleCommands(const ProductData &product, const QString &inputFilePath, const QString &outputFileTag, ErrorInfo *error = nullptr) const; ProjectTransformerData transformerData(ErrorInfo *error = nullptr) const; ErrorInfo dumpNodesTree(QIODevice &outDevice, const QList &products); class BuildGraphInfo { public: QString bgFilePath; QVariantMap overriddenProperties; QVariantMap profileData; QVariantMap requestedProperties; ErrorInfo error; }; static BuildGraphInfo getBuildGraphInfo(const QString &bgFilePath, const QStringList &requestedProperties); #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES ErrorInfo addGroup(const ProductData &product, const QString &groupName); ErrorInfo addFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths); ErrorInfo removeFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths); ErrorInfo removeGroup(const ProductData &product, const GroupData &group); #endif // QBS_ENABLE_PROJECT_FILE_UPDATES private: Project(const Internal::TopLevelProjectPtr &internalProject, const Internal::Logger &logger); QExplicitlySharedDataPointer d; }; inline bool operator!=(const Project &p1, const Project &p2) { return !(p1 == p2); } inline uint qHash(const Project &p) { return QT_PREPEND_NAMESPACE(qHash)(p.d.data()); } } // namespace qbs #endif // QBS_PROJECT_H qbs-src-1.13.1/src/lib/corelib/api/project_p.h000066400000000000000000000142401347155106100210360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROJECT_P_H #define QBS_PROJECT_P_H #include "projectdata.h" #include "rulecommand.h" #include "transformerdata.h" #include #include #include #include namespace qbs { class BuildJob; class BuildOptions; class CleanJob; class CleanOptions; class InstallJob; class InstallOptions; namespace Internal { class ProjectPrivate : public QSharedData { public: ProjectPrivate(const TopLevelProjectPtr &internalProject, const Logger &logger) : internalProject(internalProject), logger(logger) { } ProjectData projectData(); BuildJob *buildProducts(const QList &products, const BuildOptions &options, bool needsDepencencyResolving, QObject *jobOwner); CleanJob *cleanProducts(const QList &products, const CleanOptions &options, QObject *jobOwner); InstallJob *installProducts(const QList &products, const InstallOptions &options, bool needsDepencencyResolving, QObject *jobOwner); QList internalProducts(const QList &products) const; QList allEnabledInternalProducts(bool includingNonDefault) const; ResolvedProductPtr internalProduct(const ProductData &product) const; ProductData findProductData(const ProductData &product) const; QList findProductsByName(const QString &name) const; GroupData findGroupData(const ProductData &product, const QString &groupName) const; GroupData createGroupDataFromGroup(const GroupPtr &resolvedGroup, const ResolvedProductConstPtr &product); ArtifactData createApiSourceArtifact(const SourceArtifactConstPtr &sa); ArtifactData createArtifactData(const Artifact *artifact, const ResolvedProductConstPtr &product, const ArtifactSet &targetArtifacts); void setupInstallData(ArtifactData &artifact, const ResolvedProductConstPtr &product); struct GroupUpdateContext { QList resolvedProducts; QList resolvedGroups; QList products; QList groups; }; struct FileListUpdateContext { GroupUpdateContext groupContext; QStringList absoluteFilePaths; QStringList relativeFilePaths; QStringList absoluteFilePathsFromWildcards; // Not included in the other two lists. }; GroupUpdateContext getGroupContext(const ProductData &product, const GroupData &group); FileListUpdateContext getFileListContext(const ProductData &product, const GroupData &group, const QStringList &filePaths, bool forAdding); void addGroup(const ProductData &product, const QString &groupName); void addFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths); void removeFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths); void removeGroup(const ProductData &product, const GroupData &group); void removeFilesFromBuildGraph(const ResolvedProductConstPtr &product, const std::vector &files); void updateInternalCodeLocations(const ResolvedProjectPtr &project, const CodeLocation &changeLocation, int lineOffset); void updateExternalCodeLocations(const ProjectData &project, const CodeLocation &changeLocation, int lineOffset); void prepareChangeToProject(); RuleCommandList ruleCommandListForTransformer(const Transformer *transformer); RuleCommandList ruleCommands(const ProductData &product, const QString &inputFilePath, const QString &outputFileTag); ProjectTransformerData transformerData(); TopLevelProjectPtr internalProject; Logger logger; private: void retrieveProjectData(ProjectData &projectData, const ResolvedProjectConstPtr &internalProject); ProjectData m_projectData; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/api/projectdata.cpp000066400000000000000000000547461347155106100217230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "projectdata.h" #include "projectdata_p.h" #include "propertymap_p.h" #include #include #include #include #include #include #include #include #include namespace qbs { /*! * \class GroupData * \brief The \c GroupData class corresponds to the Group item in a qbs source file. */ GroupData::GroupData() : d(new Internal::GroupDataPrivate) { } GroupData::GroupData(const GroupData &other) : d(other.d) { } GroupData &GroupData::operator=(const GroupData &other) { d = other.d; return *this; } GroupData::~GroupData() { } /*! * \brief Returns true if and only if the Group holds data that was initialized by Qbs. */ bool GroupData::isValid() const { return d->isValid; } /*! * \brief The location at which the group is defined in the respective source file. */ CodeLocation GroupData::location() const { return d->location; } /*! * \brief The name of the group. */ QString GroupData::name() const { return d->name; } /*! * \brief The prefix of the group. */ QString GroupData::prefix() const { return d->prefix; } /*! * \brief The files listed in the group item's "files" binding. * \note These do not include expanded wildcards. * \sa GroupData::sourceArtifactsFromWildcards */ QList GroupData::sourceArtifacts() const { return d->sourceArtifacts; } /*! * \brief The list of files resulting from expanding all wildcard patterns in the group. */ QList GroupData::sourceArtifactsFromWildcards() const { return d->sourceArtifactsFromWildcards; } /*! * \brief All files in this group, regardless of how whether they were given explicitly * or via wildcards. * \sa GroupData::sourceArtifacts * \sa GroupData::sourceArtifactsFromWildcards */ QList GroupData::allSourceArtifacts() const { return sourceArtifacts() + sourceArtifactsFromWildcards(); } /*! * \brief The set of properties valid in this group. * Typically, most of them are inherited from the respective \c Product. */ PropertyMap GroupData::properties() const { return d->properties; } /*! * \brief Returns true if this group is enabled in Qbs * This method returns the "condition" property of the \c Group definition. If the group is enabled * then the files in this group will be processed, provided the product it belongs to is also * enabled. * * Note that a group can be enabled, even if the product it belongs to is not. In this case * the files in the group will not be processed. * \sa ProductData::isEnabled() */ bool GroupData::isEnabled() const { QBS_ASSERT(isValid(), return false); return d->isEnabled; } /*! * \brief The paths of all files in this group. * \sa GroupData::allSourceArtifacts */ QStringList GroupData::allFilePaths() const { const QList &artifacts = allSourceArtifacts(); QStringList paths; paths.reserve(artifacts.size()); std::transform(artifacts.cbegin(), artifacts.cend(), std::back_inserter(paths), [](const ArtifactData &sa) { return sa.filePath(); }); return paths; } bool operator!=(const GroupData &lhs, const GroupData &rhs) { return !(lhs == rhs); } bool operator==(const GroupData &lhs, const GroupData &rhs) { if (!lhs.isValid() && !rhs.isValid()) return true; return lhs.isValid() == rhs.isValid() && lhs.name() == rhs.name() && lhs.location() == rhs.location() && lhs.sourceArtifactsFromWildcards() == rhs.sourceArtifactsFromWildcards() && lhs.sourceArtifacts() == rhs.sourceArtifacts() && lhs.properties() == rhs.properties() && lhs.isEnabled() == rhs.isEnabled(); } bool operator<(const GroupData &lhs, const GroupData &rhs) { return lhs.name() < rhs.name(); } /*! * \class ArtifactData * The \c ArtifactData class describes a file in a product. It is either a source file * or it gets generated during the build process. */ ArtifactData::ArtifactData() : d(new Internal::ArtifactDataPrivate) { } ArtifactData::ArtifactData(const ArtifactData &other) : d(other.d) { } ArtifactData &ArtifactData::operator=(const ArtifactData &other) { d = other.d; return *this; } ArtifactData::~ArtifactData() { } /*! * \brief Returns true if and only if this object holds data that was initialized by Qbs. */ bool ArtifactData::isValid() const { return d->isValid; } /*! * \brief The full path of this file. */ QString ArtifactData::filePath() const { return d->filePath; } /*! * \brief The tags of this file. * Typically, this list will contain just one element. */ QStringList ArtifactData::fileTags() const { return d->fileTags; } bool ArtifactData::isGenerated() const { return d->isGenerated; } /*! * \brief True if and only if this file is executable, * either natively or through an interpreter or shell. */ bool ArtifactData::isExecutable() const { const bool isBundle = d->properties.getModuleProperty( QStringLiteral("bundle"), QStringLiteral("isBundle")).toBool(); return Internal::isRunnableArtifact( Internal::FileTags::fromStringList(d->fileTags), isBundle); } /*! * \brief True if and only if this artifact is a target artifact of its product. */ bool ArtifactData::isTargetArtifact() const { QBS_ASSERT(isValid(), return false); return d->isTargetArtifact; } /*! * \brief The properties of this file. */ PropertyMap ArtifactData::properties() const { return d->properties; } /*! \brief The installation-related data of this artifact. */ InstallData ArtifactData::installData() const { return d->installData; } bool operator==(const ArtifactData &ad1, const ArtifactData &ad2) { return ad1.filePath() == ad2.filePath() && ad1.fileTags() == ad2.fileTags() && ad1.isGenerated() == ad2.isGenerated() && ad1.properties() == ad2.properties(); } bool operator!=(const ArtifactData &ta1, const ArtifactData &ta2) { return !(ta1 == ta2); } bool operator<(const ArtifactData &ta1, const ArtifactData &ta2) { return ta1.filePath() < ta2.filePath(); } /*! * \class InstallData * \brief The \c InstallData class provides the installation-related data of an artifact. */ InstallData::InstallData() : d(new Internal::InstallDataPrivate) { } InstallData::InstallData(const InstallData &other) : d(other.d) { } InstallData &InstallData::operator=(const InstallData &other) { d = other.d; return *this; } InstallData::~InstallData() { } /*! * \brief Returns true if and only if this object holds data that was initialized by Qbs. */ bool InstallData::isValid() const { return d->isValid; } /*! \brief Returns true if and only if \c{qbs.install} is \c true for the artifact. */ bool InstallData::isInstallable() const { QBS_ASSERT(isValid(), return false); return d->isInstallable; } /*! \brief Returns the directory into which the artifact will be installed. \note This is not necessarily the same as \c{qbs.installDir}, because \c{qbs.installSourceBase} might have been used. */ QString InstallData::installDir() const { QBS_ASSERT(isValid(), return {}); return Internal::FileInfo::path(installFilePath()); } /*! \brief Returns the installed file path of the artifact. */ QString InstallData::installFilePath() const { QBS_ASSERT(isValid(), return {}); return d->installFilePath; } /*! \brief Returns the value of \c{qbs.installRoot} for the artifact. */ QString InstallData::installRoot() const { QBS_ASSERT(isValid(), return {}); return d->installRoot; } /*! \brief Returns the local installation directory of the artifact, that is \c installDir() prepended by \c installRoot(). */ QString InstallData::localInstallDir() const { return QDir::cleanPath(installRoot() + QLatin1Char('/') + installDir()); } /*! \brief Returns the local installed file path of the artifact, that is \c installFilePath() prepended by \c installRoot(). */ QString InstallData::localInstallFilePath() const { return QDir::cleanPath(installRoot() + QLatin1Char('/') + installFilePath()); } /*! * \class ProductData * \brief The \c ProductData class corresponds to the Product item in a qbs source file. */ ProductData::ProductData() : d(new Internal::ProductDataPrivate) { } ProductData::ProductData(const ProductData &other) : d(other.d) { } ProductData &ProductData::operator=(const ProductData &other) { d = other.d; return *this; } ProductData::~ProductData() { } /*! * \brief Returns true if and only if the Product holds data that was initialized by Qbs. */ bool ProductData::isValid() const { return d->isValid; } /*! * \brief The product type, which is the list of file tags matching the product's target artifacts. */ QStringList ProductData::type() const { return d->type; } /*! * \brief The names of dependent products. */ QStringList ProductData::dependencies() const { return d->dependencies; } /*! * \brief The name of the product as given in the qbs source file. */ QString ProductData::name() const { return d->name; } /*! The name of the product as given in the qbs source file, plus information about which properties it was multiplexed on and the values of these properties. If the product was not multiplexed, the returned value is the same as \c name(). */ QString ProductData::fullDisplayName() const { return Internal::ResolvedProduct::fullDisplayName(name(), multiplexConfigurationId()); } /*! * \brief The base name of the product's target file as given in the qbs source file. */ QString ProductData::targetName() const { return d->targetName; } /*! * \brief The version number of the product. */ QString ProductData::version() const { return d->version; } /*! * \brief The profile this product will be built for. */ QString ProductData::profile() const { return d->moduleProperties.getModuleProperty( Internal::StringConstants::qbsModule(), Internal::StringConstants::profileProperty()).toString(); } QString ProductData::multiplexConfigurationId() const { return d->multiplexConfigurationId; } /*! * \brief The location at which the product is defined in the source file. */ CodeLocation ProductData::location() const { return d->location; } /*! * \brief The directory under which the product's generated artifacts are located. */ QString ProductData::buildDirectory() const { return d->buildDirectory; } /*! * \brief All artifacts that are generated when building this product. */ QList ProductData::generatedArtifacts() const { return d->generatedArtifacts; } /*! \brief This product's target artifacts. This is a subset of \c generatedArtifacts() */ QList ProductData::targetArtifacts() const { QList list; std::copy_if(d->generatedArtifacts.cbegin(), d->generatedArtifacts.cend(), std::back_inserter(list), [](const ArtifactData &a) { return a.isTargetArtifact(); }); return list; } /*! * \brief The list of artifacts in this product that are to be installed. */ QList ProductData::installableArtifacts() const { QList artifacts; for (const GroupData &g : groups()) { for (const ArtifactData &a : g.allSourceArtifacts()) { if (a.installData().isInstallable()) artifacts << a; } } for (const ArtifactData &a : generatedArtifacts()) { if (a.installData().isInstallable()) artifacts << a; } return artifacts; } /*! * \brief Returns the file path of the executable associated with this product. * If the product is not an application, an empty string is returned. */ QString ProductData::targetExecutable() const { QBS_ASSERT(isValid(), return {}); if (d->moduleProperties.getModuleProperty(QStringLiteral("bundle"), QStringLiteral("isBundle")).toBool()) { for (const ArtifactData &ta : targetArtifacts()) { if (ta.fileTags().contains(QLatin1String("bundle.application-executable"))) { if (ta.installData().isInstallable()) return ta.installData().localInstallFilePath(); return ta.filePath(); } } } for (const ArtifactData &ta : targetArtifacts()) { if (ta.isExecutable()) { if (ta.installData().isInstallable()) return ta.installData().localInstallFilePath(); return ta.filePath(); } } return {}; } /*! * \brief The list of \c GroupData in this product. */ QList ProductData::groups() const { return d->groups; } /*! * \brief The product properties. */ QVariantMap ProductData::properties() const { return d->properties; } /*! * \brief The set of properties inherited from dependent products and modules. */ PropertyMap ProductData::moduleProperties() const { return d->moduleProperties; } /*! * \brief Returns true if this Product is enabled in Qbs. * This method returns the \c condition property of the \c Product definition. If a product is * enabled, then it will be built in the current configuration. * \sa GroupData::isEnabled() */ bool ProductData::isEnabled() const { QBS_ASSERT(isValid(), return false); return d->isEnabled; } bool ProductData::isRunnable() const { QBS_ASSERT(isValid(), return false); return d->isRunnable; } bool ProductData::isMultiplexed() const { QBS_ASSERT(isValid(), return false); return d->isMultiplexed; } bool operator==(const ProductData &lhs, const ProductData &rhs) { if (!lhs.isValid() && !rhs.isValid()) return true; return lhs.isValid() == rhs.isValid() && lhs.name() == rhs.name() && lhs.targetName() == rhs.targetName() && lhs.type() == rhs.type() && lhs.version() == rhs.version() && lhs.dependencies() == rhs.dependencies() && lhs.profile() == rhs.profile() && lhs.multiplexConfigurationId() == rhs.multiplexConfigurationId() && lhs.location() == rhs.location() && lhs.groups() == rhs.groups() && lhs.generatedArtifacts() == rhs.generatedArtifacts() && lhs.properties() == rhs.properties() && lhs.moduleProperties() == rhs.moduleProperties() && lhs.isEnabled() == rhs.isEnabled() && lhs.isMultiplexed() == rhs.isMultiplexed(); } bool operator!=(const ProductData &lhs, const ProductData &rhs) { return !(lhs == rhs); } bool operator<(const ProductData &lhs, const ProductData &rhs) { const int nameCmp = lhs.name().compare(rhs.name()); if (nameCmp < 0) return true; if (nameCmp > 0) return false; return lhs.profile() < rhs.profile() && lhs.multiplexConfigurationId() < rhs.multiplexConfigurationId(); } /*! * \class ProjectData * \brief The \c ProjectData class corresponds to the \c Project item in a qbs source file. */ /*! * \fn QList ProjectData::products() const * \brief The products in this project. */ ProjectData::ProjectData() : d(new Internal::ProjectDataPrivate) { } ProjectData::ProjectData(const ProjectData &other) : d(other.d) { } ProjectData &ProjectData::operator =(const ProjectData &other) { d = other.d; return *this; } ProjectData::~ProjectData() { } /*! * \brief Returns true if and only if the Project holds data that was initialized by Qbs. */ bool ProjectData::isValid() const { return d->isValid; } /*! * \brief The name of this project. */ QString ProjectData::name() const { return d->name; } /*! * \brief The location at which the project is defined in a qbs source file. */ CodeLocation ProjectData::location() const { return d->location; } /*! * \brief Whether the project is enabled. * \note Disabled projects never have any products or sub-projects. */ bool ProjectData::isEnabled() const { QBS_ASSERT(isValid(), return false); return d->enabled; } /*! * \brief The base directory under which the build artifacts of this project will be created. * This is only valid for the top-level project. */ QString ProjectData::buildDirectory() const { return d->buildDir; } /*! * The products in this project. * \note This also includes disabled products. */ QList ProjectData::products() const { return d->products; } /*! * The sub-projects of this project. */ QList ProjectData::subProjects() const { return d->subProjects; } /*! * All products in this projects and its direct and indirect sub-projects. */ QList ProjectData::allProducts() const { QList productList = products(); for (const ProjectData &pd : subProjects()) productList << pd.allProducts(); return productList; } /*! * The artifacts of all products in this project that are to be installed. */ QList ProjectData::installableArtifacts() const { QList artifacts; for (const ProductData &p : allProducts()) artifacts << p.installableArtifacts(); return artifacts; } bool operator==(const ProjectData &lhs, const ProjectData &rhs) { if (!lhs.isValid() && !rhs.isValid()) return true; return lhs.isValid() == rhs.isValid() && lhs.isEnabled() == rhs.isEnabled() && lhs.name() == rhs.name() && lhs.buildDirectory() == rhs.buildDirectory() && lhs.location() == rhs.location() && lhs.subProjects() == rhs.subProjects() && lhs.products() == rhs.products(); } bool operator!=(const ProjectData &lhs, const ProjectData &rhs) { return !(lhs == rhs); } bool operator<(const ProjectData &lhs, const ProjectData &rhs) { return lhs.name() < rhs.name(); } /*! * \class PropertyMap * \brief The \c PropertyMap class represents the properties of a group or a product. */ PropertyMap::PropertyMap() : d(new Internal::PropertyMapPrivate) { static Internal::PropertyMapPtr defaultInternalMap = Internal::PropertyMapInternal::create(); d->m_map = defaultInternalMap; } PropertyMap::PropertyMap(const PropertyMap &other) : d(new Internal::PropertyMapPrivate(*other.d)) { } PropertyMap::~PropertyMap() { delete d; } PropertyMap &PropertyMap::operator =(const PropertyMap &other) { if (this != &other) { delete d; d = new Internal::PropertyMapPrivate(*other.d); } return *this; } /*! * \brief Returns the names of all properties. */ QStringList PropertyMap::allProperties() const { QStringList properties; for (QVariantMap::ConstIterator it = d->m_map->value().constBegin(); it != d->m_map->value().constEnd(); ++it) { if (!it.value().canConvert()) properties << it.key(); } return properties; } /*! * \brief Returns the value of the given property of a product or group. */ QVariant PropertyMap::getProperty(const QString &name) const { return d->m_map->value().value(name); } /*! * \brief Convenience wrapper around \c PropertyMap::getModuleProperty for properties of list type. * */ QStringList PropertyMap::getModulePropertiesAsStringList(const QString &moduleName, const QString &propertyName) const { const QVariantList &vl = d->m_map->moduleProperty(moduleName, propertyName).toList(); QStringList sl; for (const QVariant &v : vl) { QBS_ASSERT(v.canConvert(), continue); sl << v.toString(); } return sl; } /*! * \brief Returns the value of the given module property. */ QVariant PropertyMap::getModuleProperty(const QString &moduleName, const QString &propertyName) const { return d->m_map->moduleProperty(moduleName, propertyName); } static QString mapToString(const QVariantMap &map, const QString &prefix) { QStringList keys(map.keys()); std::sort(keys.begin(), keys.end()); QString stringRep; for (const QString &key : qAsConst(keys)) { const QVariant &val = map.value(key); if (val.type() == QVariant::Map) { stringRep += mapToString(val.value(), prefix + key + QLatin1Char('.')); } else { stringRep += QStringLiteral("%1%2: %3\n") .arg(prefix, key, toJSLiteral(val)); } } return stringRep; } QString PropertyMap::toString() const { return mapToString(d->m_map->value(), QString()); } bool operator==(const PropertyMap &pm1, const PropertyMap &pm2) { return *pm1.d->m_map == *pm2.d->m_map; } bool operator!=(const PropertyMap &pm1, const PropertyMap &pm2) { return !(*pm1.d->m_map == *pm2.d->m_map); } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/api/projectdata.h000066400000000000000000000172671347155106100213650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROJECTDATA_H #define QBS_PROJECTDATA_H #include "../tools/codelocation.h" #include "../tools/qbs_export.h" #include #include #include #include #include #include namespace qbs { namespace Internal { class ArtifactDataPrivate; class GroupDataPrivate; class InstallDataPrivate; class ProductDataPrivate; class ProjectPrivate; class ProjectDataPrivate; class PropertyMapPrivate; } // namespace Internal class PropertyMap; QBS_EXPORT bool operator==(const PropertyMap &pm1, const PropertyMap &pm2); QBS_EXPORT bool operator!=(const PropertyMap &pm1, const PropertyMap &pm2); class QBS_EXPORT PropertyMap { friend class Internal::ProjectPrivate; friend QBS_EXPORT bool operator==(const PropertyMap &, const PropertyMap &); friend QBS_EXPORT bool operator!=(const PropertyMap &, const PropertyMap &); public: PropertyMap(); PropertyMap(const PropertyMap &other); ~PropertyMap(); PropertyMap &operator =(const PropertyMap &other); QStringList allProperties() const; QVariant getProperty(const QString &name) const; QStringList getModulePropertiesAsStringList(const QString &moduleName, const QString &propertyName) const; QVariant getModuleProperty(const QString &moduleName, const QString &propertyName) const; // For debugging. QString toString() const; private: Internal::PropertyMapPrivate *d; }; class InstallData; class QBS_EXPORT ArtifactData { friend class Internal::ProjectPrivate; public: ArtifactData(); ArtifactData(const ArtifactData &other); ArtifactData &operator=(const ArtifactData &other); ~ArtifactData(); bool isValid() const; QString filePath() const; QStringList fileTags() const; bool isGenerated() const; bool isExecutable() const; bool isTargetArtifact() const; PropertyMap properties() const; InstallData installData() const; private: QExplicitlySharedDataPointer d; }; class QBS_EXPORT InstallData { friend class Internal::ProjectPrivate; public: InstallData(); InstallData(const InstallData &other); InstallData &operator=(const InstallData &other); ~InstallData(); bool isValid() const; bool isInstallable() const; QString installDir() const; QString installFilePath() const; QString installRoot() const; QString localInstallDir() const; QString localInstallFilePath() const; private: QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const ArtifactData &ta1, const ArtifactData &ta2); QBS_EXPORT bool operator!=(const ArtifactData &ta1, const ArtifactData &ta2); QBS_EXPORT bool operator<(const ArtifactData &ta1, const ArtifactData &ta2); class QBS_EXPORT GroupData { friend class Internal::ProjectPrivate; public: GroupData(); GroupData(const GroupData &other); GroupData &operator=(const GroupData &other); ~GroupData(); bool isValid() const; CodeLocation location() const; QString name() const; QString prefix() const; QList sourceArtifacts() const; QList sourceArtifactsFromWildcards() const; QList allSourceArtifacts() const; PropertyMap properties() const; bool isEnabled() const; QStringList allFilePaths() const; private: QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const GroupData &lhs, const GroupData &rhs); QBS_EXPORT bool operator!=(const GroupData &lhs, const GroupData &rhs); QBS_EXPORT bool operator<(const GroupData &lhs, const GroupData &rhs); class QBS_EXPORT ProductData { friend class Internal::ProjectPrivate; public: ProductData(); ProductData(const ProductData &other); ProductData &operator=(const ProductData &other); ~ProductData(); bool isValid() const; QStringList type() const; QStringList dependencies() const; QString name() const; QString fullDisplayName() const; QString targetName() const; QString version() const; QString profile() const; QString multiplexConfigurationId() const; CodeLocation location() const; QString buildDirectory() const; QList generatedArtifacts() const; QList targetArtifacts() const; QList installableArtifacts() const; QString targetExecutable() const; QList groups() const; QVariantMap properties() const; PropertyMap moduleProperties() const; bool isEnabled() const; bool isRunnable() const; bool isMultiplexed() const; private: QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const ProductData &lhs, const ProductData &rhs); QBS_EXPORT bool operator!=(const ProductData &lhs, const ProductData &rhs); QBS_EXPORT bool operator<(const ProductData &lhs, const ProductData &rhs); class QBS_EXPORT ProjectData { friend class Internal::ProjectPrivate; public: ProjectData(); ProjectData(const ProjectData &other); ProjectData &operator=(const ProjectData &other); ~ProjectData(); bool isValid() const; QString name() const; CodeLocation location() const; bool isEnabled() const; QString buildDirectory() const; QList products() const; QList subProjects() const; QList allProducts() const; QList installableArtifacts() const; private: QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const ProjectData &lhs, const ProjectData &rhs); QBS_EXPORT bool operator!=(const ProjectData &lhs, const ProjectData &rhs); QBS_EXPORT bool operator<(const ProjectData &lhs, const ProjectData &rhs); } // namespace qbs #endif // QBS_PROJECTDATA_H qbs-src-1.13.1/src/lib/corelib/api/projectdata_p.h000066400000000000000000000103421347155106100216670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROJECTDATA_P_H #define QBS_PROJECTDATA_P_H #include "projectdata.h" #include #include namespace qbs { namespace Internal { class InstallDataPrivate : public QSharedData { public: InstallDataPrivate() : isValid(false) {} QString installFilePath; QString installRoot; bool isValid; bool isInstallable; }; class ArtifactDataPrivate : public QSharedData { public: ArtifactDataPrivate() : isValid(false) {} QString filePath; QStringList fileTags; PropertyMap properties; InstallData installData; bool isValid; bool isGenerated; bool isTargetArtifact; }; class GroupDataPrivate : public QSharedData { public: GroupDataPrivate() : isValid(false) { } QString name; QString prefix; CodeLocation location; QList sourceArtifacts; QList sourceArtifactsFromWildcards; PropertyMap properties; bool isEnabled; bool isValid; }; class InstallableFilePrivate: public QSharedData { public: InstallableFilePrivate() : isValid(false) {} QString sourceFilePath; QString targetFilePath; QStringList fileTags; bool isValid; }; class ProductDataPrivate : public QSharedData { public: ProductDataPrivate() : isValid(false) { } QStringList type; QStringList dependencies; QString name; QString targetName; QString version; QString multiplexConfigurationId; CodeLocation location; QString buildDirectory; QList groups; QVariantMap properties; PropertyMap moduleProperties; QList generatedArtifacts; bool isEnabled; bool isRunnable; bool isMultiplexed; bool isValid; }; class ProjectDataPrivate : public QSharedData { public: ProjectDataPrivate() : isValid(false) { } QString name; CodeLocation location; bool enabled; bool isValid; QList products; QList subProjects; QString buildDir; }; inline bool isRunnableArtifact(const FileTags &fileTags, bool isBundle) { return (fileTags.contains("application") && (!isBundle || fileTags.contains("bundle.content"))) || fileTags.contains("bundle.application-executable") || fileTags.contains("android.apk") || fileTags.contains("msi"); } } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/api/projectfileupdater.cpp000066400000000000000000000530711347155106100233040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "projectfileupdater.h" #include "projectdata.h" #include "qmljsrewriter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace QbsQmlJS; using namespace AST; namespace qbs { namespace Internal { class ItemFinder : public Visitor { public: ItemFinder(const CodeLocation &cl) : m_cl(cl), m_item(nullptr) { } UiObjectDefinition *item() const { return m_item; } private: bool visit(UiObjectDefinition *ast) override { if (toCodeLocation(m_cl.filePath(), ast->firstSourceLocation()) == m_cl) { m_item = ast; return false; } return true; } const CodeLocation m_cl; UiObjectDefinition *m_item; }; class FilesBindingFinder : public Visitor { public: FilesBindingFinder(const UiObjectDefinition *startItem) : m_startItem(startItem), m_binding(nullptr) { } UiScriptBinding *binding() const { return m_binding; } private: bool visit(UiObjectDefinition *ast) override { // We start with the direct parent of the binding, so do not descend into any // other item. return ast == m_startItem; } bool visit(UiScriptBinding *ast) override { if (ast->qualifiedId->name.toString() != StringConstants::filesProperty()) return true; m_binding = ast; return false; } const UiObjectDefinition * const m_startItem; UiScriptBinding *m_binding; }; ProjectFileUpdater::ProjectFileUpdater(const QString &projectFile) : m_projectFile(projectFile) { } ProjectFileUpdater::LineEndingType ProjectFileUpdater::guessLineEndingType(const QByteArray &text) { char before = 0; int lfCount = 0; int crlfCount = 0; int i = text.indexOf('\n'); while (i != -1) { if (i > 0) before = text.at(i - 1); if (before == '\r') ++crlfCount; else ++lfCount; i = text.indexOf('\n', i + 1); } if (lfCount == 0 && crlfCount == 0) return UnknownLineEndings; if (crlfCount == 0) return UnixLineEndings; if (lfCount == 0) return WindowsLineEndings; return MixedLineEndings; } void ProjectFileUpdater::convertToUnixLineEndings(QByteArray *text, LineEndingType oldLineEndings) { if (oldLineEndings == UnixLineEndings) return; text->replace("\r\n", "\n"); } void ProjectFileUpdater::convertFromUnixLineEndings(QByteArray *text, LineEndingType newLineEndings) { if (newLineEndings == WindowsLineEndings || (newLineEndings != UnixLineEndings && HostOsInfo::isWindowsHost())) { text->replace('\n', "\r\n"); } } void ProjectFileUpdater::apply() { QFile file(m_projectFile); if (!file.open(QFile::ReadOnly)) { throw ErrorInfo(Tr::tr("File '%1' cannot be opened for reading: %2") .arg(m_projectFile, file.errorString())); } QByteArray rawContent = file.readAll(); const LineEndingType origLineEndingType = guessLineEndingType(rawContent); convertToUnixLineEndings(&rawContent, origLineEndingType); QString content = QString::fromUtf8(rawContent); file.close(); Engine engine; Lexer lexer(&engine); lexer.setCode(content, 1); Parser parser(&engine); if (!parser.parse()) { QList parserMessages = parser.diagnosticMessages(); if (!parserMessages.empty()) { ErrorInfo errorInfo; errorInfo.append(Tr::tr("Failure parsing project file.")); for (const DiagnosticMessage &msg : qAsConst(parserMessages)) errorInfo.append(msg.message, toCodeLocation(file.fileName(), msg.loc)); throw errorInfo; } } doApply(content, parser.ast()); if (!file.open(QFile::WriteOnly)) { throw ErrorInfo(Tr::tr("File '%1' cannot be opened for writing: %2") .arg(m_projectFile, file.errorString())); } file.resize(0); rawContent = content.toUtf8(); convertFromUnixLineEndings(&rawContent, origLineEndingType); file.write(rawContent); } ProjectFileGroupInserter::ProjectFileGroupInserter(const ProductData &product, const QString &groupName) : ProjectFileUpdater(product.location().filePath()) , m_product(product) , m_groupName(groupName) { } void ProjectFileGroupInserter::doApply(QString &fileContent, UiProgram *ast) { ItemFinder itemFinder(m_product.location()); ast->accept(&itemFinder); if (!itemFinder.item()) { throw ErrorInfo(Tr::tr("The project file parser failed to find the product item."), CodeLocation(projectFile())); } ChangeSet changeSet; Rewriter rewriter(fileContent, &changeSet, QStringList()); QString groupItemString; const int productItemIndentation = itemFinder.item()->qualifiedTypeNameId->firstSourceLocation().startColumn - 1; const int groupItemIndentation = productItemIndentation + 4; const QString groupItemIndentationString = QString(groupItemIndentation, QLatin1Char(' ')); groupItemString += groupItemIndentationString + QLatin1String("Group {\n"); groupItemString += groupItemIndentationString + groupItemIndentationString + QLatin1String("name: \"") + m_groupName + QLatin1String("\"\n"); groupItemString += groupItemIndentationString + groupItemIndentationString + QLatin1String("files: []\n"); groupItemString += groupItemIndentationString + QLatin1Char('}'); rewriter.addObject(itemFinder.item()->initializer, groupItemString); int lineOffset = 3 + 1; // Our text + a leading newline that is always added by the rewriter. const QList &editOps = changeSet.operationList(); QBS_CHECK(editOps.size() == 1); const ChangeSet::EditOp &insertOp = editOps.front(); setLineOffset(lineOffset); int insertionLine = fileContent.left(insertOp.pos1).count(QLatin1Char('\n')); for (int i = 0; i < insertOp.text.size() && insertOp.text.at(i) == QLatin1Char('\n'); ++i) ++insertionLine; // To account for newlines prepended by the rewriter. ++insertionLine; // To account for zero-based indexing. setItemPosition(CodeLocation(projectFile(), insertionLine, groupItemIndentation + 1)); changeSet.apply(&fileContent); } static QString getNodeRepresentation(const QString &fileContent, const QbsQmlJS::AST::Node *node) { const quint32 start = node->firstSourceLocation().offset; const quint32 end = node->lastSourceLocation().end(); return fileContent.mid(start, end - start); } static const ChangeSet::EditOp &getEditOp(const ChangeSet &changeSet) { const QList &editOps = changeSet.operationList(); QBS_CHECK(editOps.size() == 1); return editOps.front(); } static int getLineOffsetForChangedBinding(const ChangeSet &changeSet, const QString &oldRhs) { return getEditOp(changeSet).text.count(QLatin1Char('\n')) - oldRhs.count(QLatin1Char('\n')); } static int getBindingLine(const ChangeSet &changeSet, const QString &fileContent) { return fileContent.left(getEditOp(changeSet).pos1 + 1).count(QLatin1Char('\n')) + 1; } ProjectFileFilesAdder::ProjectFileFilesAdder(const ProductData &product, const GroupData &group, const QStringList &files) : ProjectFileUpdater(product.location().filePath()) , m_product(product) , m_group(group) , m_files(files) { } static QString &addToFilesRepr(QString &filesRepr, const QString &fileRepr, int indentation) { filesRepr += QString(indentation, QLatin1Char(' ')); filesRepr += fileRepr; filesRepr += QLatin1String(",\n"); return filesRepr; } static QString &addToFilesRepr(QString &filesRepr, const QStringList &filePaths, int indentation) { for (const QString &f : filePaths) addToFilesRepr(filesRepr, toJSLiteral(f), indentation); return filesRepr; } static QString &completeFilesRepr(QString &filesRepr, int indentation) { return filesRepr.prepend(QLatin1String("[\n")).append(QString(indentation, QLatin1Char(' '))) .append(QLatin1Char(']')); } void ProjectFileFilesAdder::doApply(QString &fileContent, UiProgram *ast) { if (m_files.empty()) return; QStringList sortedFiles = m_files; sortedFiles.sort(); // Find the item containing the "files" binding. ItemFinder itemFinder(m_group.isValid() ? m_group.location() : m_product.location()); ast->accept(&itemFinder); if (!itemFinder.item()) { throw ErrorInfo(Tr::tr("The project file parser failed to find the item."), CodeLocation(projectFile())); } const int itemIndentation = itemFinder.item()->qualifiedTypeNameId->firstSourceLocation().startColumn - 1; const int bindingIndentation = itemIndentation + 4; const int arrayElemIndentation = bindingIndentation + 4; // Now get the binding itself. FilesBindingFinder bindingFinder(itemFinder.item()); itemFinder.item()->accept(&bindingFinder); ChangeSet changeSet; Rewriter rewriter(fileContent, &changeSet, QStringList()); UiScriptBinding * const filesBinding = bindingFinder.binding(); if (filesBinding) { QString filesRepresentation; if (filesBinding->statement->kind != QbsQmlJS::AST::Node::Kind_ExpressionStatement) throw ErrorInfo(Tr::tr("JavaScript construct in source file is too complex.")); // TODO: rename, add new and concat. const auto exprStatement = static_cast(filesBinding->statement); switch (exprStatement->expression->kind) { case QbsQmlJS::AST::Node::Kind_ArrayLiteral: { auto elem = static_cast(exprStatement->expression)->elements; QStringList oldFileReprs; while (elem) { oldFileReprs << getNodeRepresentation(fileContent, elem->expression); elem = elem->next; } // Insert new files "sorted", but do not change the order of existing files. const QString firstNewFileRepr = toJSLiteral(sortedFiles.front()); while (!oldFileReprs.empty()) { if (oldFileReprs.front() > firstNewFileRepr) break; addToFilesRepr(filesRepresentation, oldFileReprs.takeFirst(), arrayElemIndentation); } addToFilesRepr(filesRepresentation, sortedFiles, arrayElemIndentation); while (!oldFileReprs.empty()) addToFilesRepr(filesRepresentation, oldFileReprs.takeFirst(), arrayElemIndentation); completeFilesRepr(filesRepresentation, bindingIndentation); break; } case QbsQmlJS::AST::Node::Kind_StringLiteral: { const auto existingElement = static_cast(exprStatement->expression)->value.toString(); sortedFiles << existingElement; sortedFiles.sort(); addToFilesRepr(filesRepresentation, sortedFiles, arrayElemIndentation); completeFilesRepr(filesRepresentation, bindingIndentation); break; } default: { // Note that we can often do better than simply concatenating: For instance, // in the case where the existing list is of the form ["a", "b"].concat(myProperty), // we could keep on parsing until we find the array literal and then merge it with // the new files, preventing cascading concat() calls. // But this is not essential and can be implemented when we have some downtime. const QString rhsRepr = getNodeRepresentation(fileContent, exprStatement->expression); addToFilesRepr(filesRepresentation, sortedFiles, arrayElemIndentation); completeFilesRepr(filesRepresentation, bindingIndentation); // It cannot be the other way around, since the existing right-hand side could // have string type. filesRepresentation += QStringLiteral(".concat(%1)").arg(rhsRepr); } } rewriter.changeBinding(itemFinder.item()->initializer, StringConstants::filesProperty(), filesRepresentation, Rewriter::ScriptBinding); } else { // Can happen for the product itself, for which the "files" binding is not mandatory. QString filesRepresentation; addToFilesRepr(filesRepresentation, sortedFiles, arrayElemIndentation); completeFilesRepr(filesRepresentation, bindingIndentation); const QString bindingString = QString(bindingIndentation, QLatin1Char(' ')) + StringConstants::filesProperty(); rewriter.addBinding(itemFinder.item()->initializer, bindingString, filesRepresentation, Rewriter::ScriptBinding); } setLineOffset(getLineOffsetForChangedBinding(changeSet, filesBinding ? getNodeRepresentation(fileContent, filesBinding->statement) : QString())); const int insertionLine = getBindingLine(changeSet, fileContent); const int insertionColumn = (filesBinding ? arrayElemIndentation : bindingIndentation) + 1; setItemPosition(CodeLocation(projectFile(), insertionLine, insertionColumn)); changeSet.apply(&fileContent); } ProjectFileFilesRemover::ProjectFileFilesRemover(const ProductData &product, const GroupData &group, const QStringList &files) : ProjectFileUpdater(product.location().filePath()) , m_product(product) , m_group(group) , m_files(files) { } void ProjectFileFilesRemover::doApply(QString &fileContent, UiProgram *ast) { if (m_files.empty()) return; // Find the item containing the "files" binding. ItemFinder itemFinder(m_group.isValid() ? m_group.location() : m_product.location()); ast->accept(&itemFinder); if (!itemFinder.item()) { throw ErrorInfo(Tr::tr("The project file parser failed to find the item."), CodeLocation(projectFile())); } // Now get the binding itself. FilesBindingFinder bindingFinder(itemFinder.item()); itemFinder.item()->accept(&bindingFinder); if (!bindingFinder.binding()) { throw ErrorInfo(Tr::tr("Could not find the 'files' binding in the project file."), m_product.location()); } if (bindingFinder.binding()->statement->kind != QbsQmlJS::AST::Node::Kind_ExpressionStatement) throw ErrorInfo(Tr::tr("JavaScript construct in source file is too complex.")); const CodeLocation bindingLocation = toCodeLocation(projectFile(), bindingFinder.binding()->firstSourceLocation()); ChangeSet changeSet; Rewriter rewriter(fileContent, &changeSet, QStringList()); const int itemIndentation = itemFinder.item()->qualifiedTypeNameId->firstSourceLocation().startColumn - 1; const int bindingIndentation = itemIndentation + 4; const int arrayElemIndentation = bindingIndentation + 4; const auto exprStatement = static_cast(bindingFinder.binding()->statement); switch (exprStatement->expression->kind) { case QbsQmlJS::AST::Node::Kind_ArrayLiteral: { QStringList filesToRemove = m_files; QStringList newFilesList; auto elem = static_cast(exprStatement->expression)->elements; while (elem) { if (elem->expression->kind != QbsQmlJS::AST::Node::Kind_StringLiteral) { throw ErrorInfo(Tr::tr("JavaScript construct in source file is too complex."), bindingLocation); } const auto existingFile = static_cast(elem->expression)->value.toString(); if (!filesToRemove.removeOne(existingFile)) newFilesList << existingFile; elem = elem->next; } if (!filesToRemove.empty()) { throw ErrorInfo(Tr::tr("The following files were not found in the 'files' list: %1") .arg(filesToRemove.join(QLatin1String(", "))), bindingLocation); } QString filesString; filesString += QLatin1String("[\n"); for (const QString &file : qAsConst(newFilesList)) { filesString += QString(arrayElemIndentation, QLatin1Char(' ')); filesString += QStringLiteral("\"%1\",\n").arg(file); } filesString += QString(bindingIndentation, QLatin1Char(' ')); filesString += QLatin1Char(']'); rewriter.changeBinding(itemFinder.item()->initializer, StringConstants::filesProperty(), filesString, Rewriter::ScriptBinding); break; } case QbsQmlJS::AST::Node::Kind_StringLiteral: { if (m_files.size() != 1) { throw ErrorInfo(Tr::tr("Was requested to remove %1 files, but there is only " "one in the list.").arg(m_files.size()), bindingLocation); } const auto existingFile = static_cast(exprStatement->expression)->value.toString(); if (existingFile != m_files.front()) { throw ErrorInfo(Tr::tr("File '%1' could not be found in the 'files' list.") .arg(m_files.front()), bindingLocation); } rewriter.changeBinding(itemFinder.item()->initializer, StringConstants::filesProperty(), StringConstants::emptyArrayValue(), Rewriter::ScriptBinding); break; } default: throw ErrorInfo(Tr::tr("JavaScript construct in source file is too complex."), bindingLocation); } setLineOffset(getLineOffsetForChangedBinding(changeSet, getNodeRepresentation(fileContent, exprStatement->expression))); const int bindingLine = getBindingLine(changeSet, fileContent); const int bindingColumn = (bindingFinder.binding() ? arrayElemIndentation : bindingIndentation) + 1; setItemPosition(CodeLocation(projectFile(), bindingLine, bindingColumn)); changeSet.apply(&fileContent); } ProjectFileGroupRemover::ProjectFileGroupRemover(const ProductData &product, const GroupData &group) : ProjectFileUpdater(product.location().filePath()) , m_product(product) , m_group(group) { } void ProjectFileGroupRemover::doApply(QString &fileContent, UiProgram *ast) { ItemFinder productFinder(m_product.location()); ast->accept(&productFinder); if (!productFinder.item()) { throw ErrorInfo(Tr::tr("The project file parser failed to find the product item."), CodeLocation(projectFile())); } ItemFinder groupFinder(m_group.location()); productFinder.item()->accept(&groupFinder); if (!groupFinder.item()) { throw ErrorInfo(Tr::tr("The project file parser failed to find the group item."), m_product.location()); } ChangeSet changeSet; Rewriter rewriter(fileContent, &changeSet, QStringList()); rewriter.removeObjectMember(groupFinder.item(), productFinder.item()); setItemPosition(m_group.location()); const QList &editOps = changeSet.operationList(); QBS_CHECK(editOps.size() == 1); const ChangeSet::EditOp &op = editOps.front(); const QString removedText = fileContent.mid(op.pos1, op.length1); setLineOffset(-removedText.count(QLatin1Char('\n'))); changeSet.apply(&fileContent); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/api/projectfileupdater.h000066400000000000000000000110531347155106100227430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROJECTFILEUPDATER_H #define QBS_PROJECTFILEUPDATER_H #include "projectdata.h" #include #include #include namespace QbsQmlJS { namespace AST { class UiProgram; } } namespace qbs { namespace Internal { class ProjectFileUpdater { public: void apply(); CodeLocation itemPosition() const { return m_itemPosition; } int lineOffset() const { return m_lineOffset; } protected: ProjectFileUpdater(const QString &projectFile); QString projectFile() const { return m_projectFile; } void setLineOffset(int offset) { m_lineOffset = offset; } void setItemPosition(const CodeLocation &cl) { m_itemPosition = cl; } private: virtual void doApply(QString &fileContent, QbsQmlJS::AST::UiProgram *ast) = 0; enum LineEndingType { UnknownLineEndings, UnixLineEndings, WindowsLineEndings, MixedLineEndings }; static LineEndingType guessLineEndingType(const QByteArray &text); static void convertToUnixLineEndings(QByteArray *text, LineEndingType oldLineEndings); static void convertFromUnixLineEndings(QByteArray *text, LineEndingType newLineEndings); const QString m_projectFile; CodeLocation m_itemPosition; int m_lineOffset; }; class ProjectFileGroupInserter : public ProjectFileUpdater { public: ProjectFileGroupInserter(const ProductData &product, const QString &groupName); private: void doApply(QString &fileContent, QbsQmlJS::AST::UiProgram *ast) override; const ProductData m_product; const QString m_groupName; }; class ProjectFileFilesAdder : public ProjectFileUpdater { public: ProjectFileFilesAdder(const ProductData &product, const GroupData &group, const QStringList &files); private: void doApply(QString &fileContent, QbsQmlJS::AST::UiProgram *ast) override; const ProductData m_product; const GroupData m_group; const QStringList m_files; }; class ProjectFileFilesRemover : public ProjectFileUpdater { public: ProjectFileFilesRemover(const ProductData &product, const GroupData &group, const QStringList &files); private: void doApply(QString &fileContent, QbsQmlJS::AST::UiProgram *ast) override; const ProductData m_product; const GroupData m_group; const QStringList m_files; }; class ProjectFileGroupRemover : public ProjectFileUpdater { public: ProjectFileGroupRemover(const ProductData &product, const GroupData &group); private: void doApply(QString &fileContent, QbsQmlJS::AST::UiProgram *ast) override; const ProductData m_product; const GroupData m_group; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/api/propertymap_p.h000066400000000000000000000041531347155106100217540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROPERTYMAP_P_H #define QBS_PROPERTYMAP_P_H #include namespace qbs { namespace Internal { class PropertyMapPrivate { public: PropertyMapPtr m_map; }; } // namespace Internal } // namespace qbs #endif // QBS_PROPERTYMAP_P_H qbs-src-1.13.1/src/lib/corelib/api/qmljsrewriter.cpp000066400000000000000000000636231347155106100223270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qmljsrewriter.h" #include #include #include #include namespace QbsQmlJS { using namespace AST; static QString toString(UiQualifiedId *qualifiedId, QChar delimiter = QLatin1Char('.')) { QString result; for (UiQualifiedId *iter = qualifiedId; iter; iter = iter->next) { if (iter != qualifiedId) result += delimiter; result += iter->name; } return result; } Rewriter::Rewriter(const QString &originalText, ChangeSet *changeSet, const QStringList &propertyOrder) : m_originalText(originalText) , m_changeSet(changeSet) , m_propertyOrder(propertyOrder) { Q_ASSERT(changeSet); } Rewriter::Range Rewriter::addBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &propertyValue, BindingType bindingType) { UiObjectMemberList *insertAfter = searchMemberToInsertAfter(ast->members, propertyName, m_propertyOrder); return addBinding(ast, propertyName, propertyValue, bindingType, insertAfter); } Rewriter::Range Rewriter::addBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &propertyValue, BindingType bindingType, UiObjectMemberList *insertAfter) { SourceLocation endOfPreviousMember; SourceLocation startOfNextMember; if (insertAfter == nullptr || insertAfter->member == nullptr) { // insert as first member endOfPreviousMember = ast->lbraceToken; if (ast->members && ast->members->member) startOfNextMember = ast->members->member->firstSourceLocation(); else startOfNextMember = ast->rbraceToken; } else { endOfPreviousMember = insertAfter->member->lastSourceLocation(); if (insertAfter->next && insertAfter->next->member) startOfNextMember = insertAfter->next->member->firstSourceLocation(); else startOfNextMember = ast->rbraceToken; } const bool isOneLiner = endOfPreviousMember.startLine == startOfNextMember.startLine; bool needsPreceedingSemicolon = false; bool needsTrailingSemicolon = false; if (isOneLiner) { if (insertAfter == nullptr) { // we're inserting after an lbrace if (ast->members) { // we're inserting before a member (and not the rbrace) needsTrailingSemicolon = bindingType == ScriptBinding; } } else { // we're inserting after a member, not after the lbrace if (endOfPreviousMember.isValid()) { // there already is a semicolon after the previous member if (insertAfter->next && insertAfter->next->member) { // and the after us there is a member, not an rbrace, so: needsTrailingSemicolon = bindingType == ScriptBinding; } } else { // there is no semicolon after the previous member (probably because there is an rbrace after us/it, so: needsPreceedingSemicolon = true; } } } QString newPropertyTemplate; switch (bindingType) { case ArrayBinding: newPropertyTemplate = QStringLiteral("%1: [\n%2\n]"); break; case ObjectBinding: newPropertyTemplate = QStringLiteral("%1: %2"); break; case ScriptBinding: newPropertyTemplate = QStringLiteral("%1: %2"); break; default: Q_ASSERT(!"unknown property type"); } if (isOneLiner) { if (needsPreceedingSemicolon) newPropertyTemplate.prepend(QLatin1Char(';')); newPropertyTemplate.prepend(QLatin1Char(' ')); if (needsTrailingSemicolon) newPropertyTemplate.append(QLatin1Char(';')); } else { newPropertyTemplate.prepend(QLatin1Char('\n')); } m_changeSet->insert(endOfPreviousMember.end(), newPropertyTemplate.arg(propertyName, propertyValue)); return {int(endOfPreviousMember.end()), int(endOfPreviousMember.end())}; } UiObjectMemberList *Rewriter::searchMemberToInsertAfter(UiObjectMemberList *members, const QStringList &propertyOrder) { const int objectDefinitionInsertionPoint = propertyOrder.indexOf(QString()); UiObjectMemberList *lastObjectDef = nullptr; UiObjectMemberList *lastNonObjectDef = nullptr; for (UiObjectMemberList *iter = members; iter; iter = iter->next) { UiObjectMember *member = iter->member; int idx = -1; if (cast(member)) lastObjectDef = iter; else if (auto arrayBinding = cast(member)) idx = propertyOrder.indexOf(toString(arrayBinding->qualifiedId)); else if (auto objectBinding = cast(member)) idx = propertyOrder.indexOf(toString(objectBinding->qualifiedId)); else if (auto scriptBinding = cast(member)) idx = propertyOrder.indexOf(toString(scriptBinding->qualifiedId)); else if (cast(member)) idx = propertyOrder.indexOf(QLatin1String("property")); if (idx < objectDefinitionInsertionPoint) lastNonObjectDef = iter; } if (lastObjectDef) return lastObjectDef; else return lastNonObjectDef; } UiArrayMemberList *Rewriter::searchMemberToInsertAfter(UiArrayMemberList *members, const QStringList &propertyOrder) { const int objectDefinitionInsertionPoint = propertyOrder.indexOf(QString()); UiArrayMemberList *lastObjectDef = nullptr; UiArrayMemberList *lastNonObjectDef = nullptr; for (UiArrayMemberList *iter = members; iter; iter = iter->next) { UiObjectMember *member = iter->member; int idx = -1; if (cast(member)) lastObjectDef = iter; else if (auto arrayBinding = cast(member)) idx = propertyOrder.indexOf(toString(arrayBinding->qualifiedId)); else if (auto objectBinding = cast(member)) idx = propertyOrder.indexOf(toString(objectBinding->qualifiedId)); else if (auto scriptBinding = cast(member)) idx = propertyOrder.indexOf(toString(scriptBinding->qualifiedId)); else if (cast(member)) idx = propertyOrder.indexOf(QLatin1String("property")); if (idx < objectDefinitionInsertionPoint) lastNonObjectDef = iter; } if (lastObjectDef) return lastObjectDef; else return lastNonObjectDef; } UiObjectMemberList *Rewriter::searchMemberToInsertAfter(UiObjectMemberList *members, const QString &propertyName, const QStringList &propertyOrder) { if (!members) return nullptr; // empty members QHash orderedMembers; for (UiObjectMemberList *iter = members; iter; iter = iter->next) { UiObjectMember *member = iter->member; if (auto arrayBinding = cast(member)) orderedMembers[toString(arrayBinding->qualifiedId)] = iter; else if (auto objectBinding = cast(member)) orderedMembers[toString(objectBinding->qualifiedId)] = iter; else if (cast(member)) orderedMembers[QString()] = iter; else if (auto scriptBinding = cast(member)) orderedMembers[toString(scriptBinding->qualifiedId)] = iter; else if (cast(member)) orderedMembers[QStringLiteral("property")] = iter; } int idx = propertyOrder.indexOf(propertyName); if (idx == -1) idx = propertyOrder.indexOf(QString()); if (idx == -1) idx = propertyOrder.size() - 1; for (; idx > 0; --idx) { const QString prop = propertyOrder.at(idx - 1); UiObjectMemberList *candidate = orderedMembers.value(prop, 0); if (candidate != nullptr) return candidate; } return nullptr; } void Rewriter::changeBinding(UiObjectInitializer *ast, const QString &propertyName, const QString &newValue, BindingType binding) { QString prefix, suffix; int dotIdx = propertyName.indexOf(QLatin1Char('.')); if (dotIdx != -1) { prefix = propertyName.left(dotIdx); suffix = propertyName.mid(dotIdx + 1); } for (UiObjectMemberList *members = ast->members; members; members = members->next) { UiObjectMember *member = members->member; // for non-grouped properties: if (isMatchingPropertyMember(propertyName, member)) { switch (binding) { case ArrayBinding: insertIntoArray(cast(member), newValue); break; case ObjectBinding: replaceMemberValue(member, newValue, false); break; case ScriptBinding: replaceMemberValue(member, newValue, nextMemberOnSameLine(members)); break; default: Q_ASSERT(!"Unhandled QmlRefactoring::PropertyType"); } break; // for grouped properties: } else if (!prefix.isEmpty()) { if (auto def = cast(member)) { if (toString(def->qualifiedTypeNameId) == prefix) changeBinding(def->initializer, suffix, newValue, binding); } } } } void Rewriter::replaceMemberValue(UiObjectMember *propertyMember, const QString &newValue, bool needsSemicolon) { QString replacement = newValue; int startOffset = -1; int endOffset = -1; if (auto objectBinding = AST::cast(propertyMember)) { startOffset = objectBinding->qualifiedTypeNameId->identifierToken.offset; endOffset = objectBinding->initializer->rbraceToken.end(); } else if (auto scriptBinding = AST::cast(propertyMember)) { startOffset = scriptBinding->statement->firstSourceLocation().offset; endOffset = scriptBinding->statement->lastSourceLocation().end(); } else if (auto arrayBinding = AST::cast(propertyMember)) { startOffset = arrayBinding->lbracketToken.offset; endOffset = arrayBinding->rbracketToken.end(); } else if (auto publicMember = AST::cast(propertyMember)) { if (publicMember->statement) { startOffset = publicMember->statement->firstSourceLocation().offset; if (publicMember->semicolonToken.isValid()) endOffset = publicMember->semicolonToken.end(); else endOffset = publicMember->statement->lastSourceLocation().offset; } else { startOffset = publicMember->lastSourceLocation().end(); endOffset = startOffset; if (publicMember->semicolonToken.isValid()) startOffset = publicMember->semicolonToken.offset; replacement.prepend(QStringLiteral(": ")); } } else { return; } if (needsSemicolon) replacement += QLatin1Char(';'); m_changeSet->replace(startOffset, endOffset, replacement); } bool Rewriter::isMatchingPropertyMember(const QString &propertyName, UiObjectMember *member) { if (auto publicMember = cast(member)) return publicMember->name == propertyName; else if (auto objectBinding = cast(member)) return toString(objectBinding->qualifiedId) == propertyName; else if (auto scriptBinding = cast(member)) return toString(scriptBinding->qualifiedId) == propertyName; else if (auto arrayBinding = cast(member)) return toString(arrayBinding->qualifiedId) == propertyName; else return false; } bool Rewriter::nextMemberOnSameLine(UiObjectMemberList *members) { if (members && members->next && members->next->member) return members->next->member->firstSourceLocation().startLine == members->member->lastSourceLocation().startLine; else return false; } void Rewriter::insertIntoArray(UiArrayBinding *ast, const QString &newValue) { if (!ast) return; UiObjectMember *lastMember = nullptr; for (UiArrayMemberList *iter = ast->members; iter; iter = iter->next) { lastMember = iter->member; } if (!lastMember) return; const int insertionPoint = lastMember->lastSourceLocation().end(); m_changeSet->insert(insertionPoint, QLatin1String(",\n") + newValue); } void Rewriter::removeBindingByName(UiObjectInitializer *ast, const QString &propertyName) { QString prefix; int dotIdx = propertyName.indexOf(QLatin1Char('.')); if (dotIdx != -1) prefix = propertyName.left(dotIdx); for (UiObjectMemberList *it = ast->members; it; it = it->next) { UiObjectMember *member = it->member; // run full name match (for ungrouped properties): if (isMatchingPropertyMember(propertyName, member)) { removeMember(member); // check for grouped properties: } else if (!prefix.isEmpty()) { if (auto def = cast(member)) { if (toString(def->qualifiedTypeNameId) == prefix) removeGroupedProperty(def, propertyName); } } } } void Rewriter::removeGroupedProperty(UiObjectDefinition *ast, const QString &propertyName) { int dotIdx = propertyName.indexOf(QLatin1Char('.')); if (dotIdx == -1) return; const QString propName = propertyName.mid(dotIdx + 1); UiObjectMember *wanted = nullptr; unsigned memberCount = 0; for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { ++memberCount; UiObjectMember *member = it->member; if (!wanted && isMatchingPropertyMember(propName, member)) wanted = member; } if (!wanted) return; if (memberCount == 1) removeMember(ast); else removeMember(wanted); } void Rewriter::removeMember(UiObjectMember *member) { int start = member->firstSourceLocation().offset; int end = member->lastSourceLocation().end(); includeSurroundingWhitespace(m_originalText, start, end); m_changeSet->remove(start, end); } bool Rewriter::includeSurroundingWhitespace(const QString &source, int &start, int &end) { bool includeStartingWhitespace = true; bool paragraphFound = false; bool paragraphSkipped = false; if (end >= 0) { QChar c = source.at(end); while (c.isSpace()) { ++end; if (c.unicode() == 10) { paragraphFound = true; paragraphSkipped = true; break; } else if (end == source.length()) { break; } c = source.at(end); } includeStartingWhitespace = paragraphFound; } paragraphFound = false; if (includeStartingWhitespace) { while (start > 0) { const QChar c = source.at(start - 1); if (c.unicode() == 10) { paragraphFound = true; break; } if (!c.isSpace()) break; --start; } } if (!paragraphFound && paragraphSkipped) //keep the line ending --end; return paragraphFound; } void Rewriter::includeLeadingEmptyLine(const QString &source, int &start) { QTextDocument doc(source); if (start == 0) return; if (doc.characterAt(start - 1) != QChar::ParagraphSeparator) return; QTextCursor tc(&doc); tc.setPosition(start); const int blockNr = tc.blockNumber(); if (blockNr == 0) return; const QTextBlock prevBlock = tc.block().previous(); const QString trimmedPrevBlockText = prevBlock.text().trimmed(); if (!trimmedPrevBlockText.isEmpty()) return; start = prevBlock.position(); } void Rewriter::includeEmptyGroupedProperty(UiObjectDefinition *groupedProperty, UiObjectMember *memberToBeRemoved, int &start, int &end) { if (groupedProperty->qualifiedTypeNameId && !groupedProperty->qualifiedTypeNameId->name.isEmpty() && groupedProperty->qualifiedTypeNameId->name.at(0).isLower()) { // grouped property UiObjectMemberList *memberIter = groupedProperty->initializer->members; while (memberIter) { if (memberIter->member != memberToBeRemoved) return; memberIter = memberIter->next; } start = groupedProperty->firstSourceLocation().begin(); end = groupedProperty->lastSourceLocation().end(); } } #if 0 UiObjectMemberList *QMLRewriter::searchMemberToInsertAfter(UiObjectMemberList *members, const QStringList &propertyOrder) { const int objectDefinitionInsertionPoint = propertyOrder.indexOf(QString()); UiObjectMemberList *lastObjectDef = nullptr; UiObjectMemberList *lastNonObjectDef = nullptr; for (UiObjectMemberList *iter = members; iter; iter = iter->next) { UiObjectMember *member = iter->member; int idx = -1; if (cast(member)) lastObjectDef = iter; else if (UiArrayBinding *arrayBinding = cast(member)) idx = propertyOrder.indexOf(toString(arrayBinding->qualifiedId)); else if (UiObjectBinding *objectBinding = cast(member)) idx = propertyOrder.indexOf(toString(objectBinding->qualifiedId)); else if (UiScriptBinding *scriptBinding = cast(member)) idx = propertyOrder.indexOf(toString(scriptBinding->qualifiedId)); else if (cast(member)) idx = propertyOrder.indexOf(QLatin1String("property")); if (idx < objectDefinitionInsertionPoint) lastNonObjectDef = iter; } if (lastObjectDef) return lastObjectDef; else return lastNonObjectDef; } UiObjectMemberList *QMLRewriter::searchMemberToInsertAfter(UiObjectMemberList *members, const QString &propertyName, const QStringList &propertyOrder) { if (!members) return nullptr; // empty members QHash orderedMembers; for (UiObjectMemberList *iter = members; iter; iter = iter->next) { UiObjectMember *member = iter->member; if (UiArrayBinding *arrayBinding = cast(member)) orderedMembers[toString(arrayBinding->qualifiedId)] = iter; else if (UiObjectBinding *objectBinding = cast(member)) orderedMembers[toString(objectBinding->qualifiedId)] = iter; else if (cast(member)) orderedMembers[QString()] = iter; else if (UiScriptBinding *scriptBinding = cast(member)) orderedMembers[toString(scriptBinding->qualifiedId)] = iter; else if (cast(member)) orderedMembers[QStringLiteral("property")] = iter; } int idx = propertyOrder.indexOf(propertyName); if (idx == -1) idx = propertyOrder.indexOf(QString()); if (idx == -1) idx = propertyOrder.size() - 1; for (; idx > 0; --idx) { const QString prop = propertyOrder.at(idx - 1); UiObjectMemberList *candidate = orderedMembers.value(prop, 0); if (candidate != 0) return candidate; } return nullptr; } #endif void Rewriter::appendToArrayBinding(UiArrayBinding *arrayBinding, const QString &content) { UiObjectMember *lastMember = nullptr; for (UiArrayMemberList *iter = arrayBinding->members; iter; iter = iter->next) if (iter->member) lastMember = iter->member; if (!lastMember) return; // an array binding cannot be empty, so there will (or should) always be a last member. const int insertionPoint = lastMember->lastSourceLocation().end(); m_changeSet->insert(insertionPoint, QLatin1String(",\n") + content); } Rewriter::Range Rewriter::addObject(UiObjectInitializer *ast, const QString &content) { UiObjectMemberList *insertAfter = searchMemberToInsertAfter(ast->members, m_propertyOrder); return addObject(ast, content, insertAfter); } Rewriter::Range Rewriter::addObject(UiObjectInitializer *ast, const QString &content, UiObjectMemberList *insertAfter) { int insertionPoint; QString textToInsert; if (insertAfter && insertAfter->member) { insertionPoint = insertAfter->member->lastSourceLocation().end(); textToInsert += QLatin1String("\n"); } else { insertionPoint = ast->lbraceToken.end(); } textToInsert += content; m_changeSet->insert(insertionPoint, QLatin1String("\n") + textToInsert); return Range(insertionPoint, insertionPoint); } Rewriter::Range Rewriter::addObject(UiArrayBinding *ast, const QString &content) { UiArrayMemberList *insertAfter = searchMemberToInsertAfter(ast->members, m_propertyOrder); return addObject(ast, content, insertAfter); } Rewriter::Range Rewriter::addObject(UiArrayBinding *ast, const QString &content, UiArrayMemberList *insertAfter) { int insertionPoint; QString textToInsert; if (insertAfter && insertAfter->member) { insertionPoint = insertAfter->member->lastSourceLocation().end(); textToInsert = QLatin1String(",\n") + content; } else { insertionPoint = ast->lbracketToken.end(); textToInsert += QLatin1String("\n") + content + QLatin1Char(','); } m_changeSet->insert(insertionPoint, textToInsert); return Range(insertionPoint, insertionPoint); } void Rewriter::removeObjectMember(UiObjectMember *member, UiObjectMember *parent) { int start = member->firstSourceLocation().offset; int end = member->lastSourceLocation().end(); if (auto parentArray = cast(parent)) { extendToLeadingOrTrailingComma(parentArray, member, start, end); } else { if (auto parentObjectDefinition = cast(parent)) includeEmptyGroupedProperty(parentObjectDefinition, member, start, end); includeSurroundingWhitespace(m_originalText, start, end); } includeLeadingEmptyLine(m_originalText, start); m_changeSet->remove(start, end); } void Rewriter::extendToLeadingOrTrailingComma(UiArrayBinding *parentArray, UiObjectMember *member, int &start, int &end) const { UiArrayMemberList *currentMember = nullptr; for (UiArrayMemberList *it = parentArray->members; it; it = it->next) { if (it->member == member) { currentMember = it; break; } } if (!currentMember) return; if (currentMember->commaToken.isValid()) { // leading comma start = currentMember->commaToken.offset; if (includeSurroundingWhitespace(m_originalText, start, end)) --end; } else if (currentMember->next && currentMember->next->commaToken.isValid()) { // trailing comma end = currentMember->next->commaToken.end(); includeSurroundingWhitespace(m_originalText, start, end); } else { // array with 1 element, so remove the complete binding start = parentArray->firstSourceLocation().offset; end = parentArray->lastSourceLocation().end(); includeSurroundingWhitespace(m_originalText, start, end); } } } // namespace QbsQmlJS qbs-src-1.13.1/src/lib/corelib/api/qmljsrewriter.h000066400000000000000000000125371347155106100217720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMLJSREWRITER_H #define QMLJSREWRITER_H #include "changeset.h" #include #include namespace QbsQmlJS { class Rewriter { public: enum BindingType { ScriptBinding, ObjectBinding, ArrayBinding }; using Range = ChangeSet::Range; public: Rewriter(const QString &originalText, ChangeSet *changeSet, const QStringList &propertyOrder); Range addBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &propertyValue, BindingType bindingType); Range addBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &propertyValue, BindingType bindingType, AST::UiObjectMemberList *insertAfter); void changeBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &newValue, BindingType binding); void removeBindingByName(AST::UiObjectInitializer *ast, const QString &propertyName); void appendToArrayBinding(AST::UiArrayBinding *arrayBinding, const QString &content); Range addObject(AST::UiObjectInitializer *ast, const QString &content); Range addObject(AST::UiObjectInitializer *ast, const QString &content, AST::UiObjectMemberList *insertAfter); Range addObject(AST::UiArrayBinding *ast, const QString &content); Range addObject(AST::UiArrayBinding *ast, const QString &content, AST::UiArrayMemberList *insertAfter); void removeObjectMember(AST::UiObjectMember *member, AST::UiObjectMember *parent); static AST::UiObjectMemberList *searchMemberToInsertAfter(AST::UiObjectMemberList *members, const QStringList &propertyOrder); static AST::UiArrayMemberList *searchMemberToInsertAfter(AST::UiArrayMemberList *members, const QStringList &propertyOrder); static AST::UiObjectMemberList *searchMemberToInsertAfter(AST::UiObjectMemberList *members, const QString &propertyName, const QStringList &propertyOrder); static bool includeSurroundingWhitespace(const QString &source, int &start, int &end); static void includeLeadingEmptyLine(const QString &source, int &start); static void includeEmptyGroupedProperty(AST::UiObjectDefinition *groupedProperty, AST::UiObjectMember *memberToBeRemoved, int &start, int &end); private: void replaceMemberValue(AST::UiObjectMember *propertyMember, const QString &newValue, bool needsSemicolon); static bool isMatchingPropertyMember(const QString &propertyName, AST::UiObjectMember *member); static bool nextMemberOnSameLine(AST::UiObjectMemberList *members); void insertIntoArray(AST::UiArrayBinding* ast, const QString &newValue); void removeMember(AST::UiObjectMember *member); void removeGroupedProperty(AST::UiObjectDefinition *ast, const QString &propertyName); void extendToLeadingOrTrailingComma(AST::UiArrayBinding *parentArray, AST::UiObjectMember *member, int &start, int &end) const; private: QString m_originalText; ChangeSet *m_changeSet; const QStringList m_propertyOrder; }; } // namespace QbsQmlJS #endif // QMLJSREWRITER_H qbs-src-1.13.1/src/lib/corelib/api/rulecommand.cpp000066400000000000000000000121141347155106100217100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "rulecommand.h" #include "rulecommand_p.h" #include namespace qbs { /*! * \class RuleCommand * \brief The \c RuleCommand class corresponds to a \c ProcessCommand or \c JavaScriptCommand * in \QBS. */ /*! * \enum RuleCommand::Type * This enum type represents the different kinds of commands. * \value ProcessCommandType For the \QBS type \c ProcessCommand, which represents a command * whose execution involves calling an executable. * \value JavaScriptCommandType For the \QBS type \c JavaScriptCommand, which represents a command * whose execution involves running a piece of JavaScript code inside \QBS. * \value InvalidType Used to mark \c RuleCommand objects as invalid. */ RuleCommand::RuleCommand() : d(new Internal::RuleCommandPrivate) { } RuleCommand::RuleCommand(const RuleCommand &other) : d(other.d) {} RuleCommand::~RuleCommand() { } RuleCommand& RuleCommand::operator=(const RuleCommand &other) { d = other.d; return *this; } /*! * Returns the type of this object. If the value is \c InvalidType, the object is invalid. */ RuleCommand::Type RuleCommand::type() const { return d->type; } /*! * Returns the human-readable description of this command that \QBS will print when * the command executed. */ QString RuleCommand::description() const { return d->description; } /*! * Returns the detailed description of this command that \QBS will print when * the command is executed. */ QString RuleCommand::extendedDescription() const { return d->extendedDescription; } /*! * Returns the source of the command if \c type() is \c JavaScriptCommandType. * If \c type() is anything else, the behavior of this function is undefined. */ QString RuleCommand::sourceCode() const { QBS_ASSERT(type() == JavaScriptCommandType, return {}); return d->sourceCode; } /*! * Returns the executable that will be called when the corresponding \c ProcessCommand * is executed. * If \c type() is not \c ProcessCommandType, the behavior of this function is undefined. */ QString RuleCommand::executable() const { QBS_ASSERT(type() == ProcessCommandType, return {}); return d->executable; } /*! * Returns the command-line arguments of the executable that will be called when the * corresponding \c ProcessCommand is executed. * If \c type() is not \c ProcessCommandType, the behavior of this function is undefined. */ QStringList RuleCommand::arguments() const { QBS_ASSERT(type() == ProcessCommandType, return {}); return d->arguments; } /*! * Returns the working directory of the executable that will be called when the * corresponding \c ProcessCommand is executed. * If \c type() is not \c ProcessCommandType, the behavior of this function is undefined. */ QString RuleCommand::workingDirectory() const { QBS_ASSERT(type() == ProcessCommandType, return {}); return d->workingDir; } /*! * Returns the environment of the executable that will be called when the * corresponding \c ProcessCommand is executed. * If \c type() is not \c ProcessCommandType, the behavior of this function is undefined. */ QProcessEnvironment RuleCommand::environment() const { QBS_ASSERT(type() == ProcessCommandType, return {}); return d->environment; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/api/rulecommand.h000066400000000000000000000056231347155106100213640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_RULECOMMAND_H #define QBS_RULECOMMAND_H #include #include #include QT_BEGIN_NAMESPACE class QProcessEnvironment; class QString; class QStringList; QT_END_NAMESPACE namespace qbs { namespace Internal { class ProjectPrivate; class RuleCommandPrivate; } class QBS_EXPORT RuleCommand { friend class Internal::ProjectPrivate; public: RuleCommand(); RuleCommand(const RuleCommand &other); ~RuleCommand(); RuleCommand &operator=(const RuleCommand &other); enum Type { ProcessCommandType, JavaScriptCommandType, InvalidType }; Type type() const; QString description() const; QString extendedDescription() const; QString sourceCode() const; QString executable() const; QStringList arguments() const; QString workingDirectory() const; QProcessEnvironment environment() const; private: QExplicitlySharedDataPointer d; }; using RuleCommandList = QList; } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/api/rulecommand_p.h000066400000000000000000000046641347155106100217070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_RULECOMMAND_P_H #define QBS_RULECOMMAND_P_H #include "rulecommand.h" #include #include namespace qbs { namespace Internal { class RuleCommandPrivate : public QSharedData { public: RuleCommandPrivate(): type(RuleCommand::InvalidType) {} RuleCommand::Type type; QString description; QString extendedDescription; QString sourceCode; QString executable; QStringList arguments; QString workingDir; QProcessEnvironment environment; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/api/runenvironment.cpp000066400000000000000000000477121347155106100225070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "runenvironment.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; class RunEnvironment::RunEnvironmentPrivate { public: RunEnvironmentPrivate(const ResolvedProductPtr &product, const TopLevelProjectConstPtr &project, const InstallOptions &installOptions, const QProcessEnvironment &environment, const QStringList &setupRunEnvConfig, Settings *settings, const Logger &logger) : resolvedProduct(product) , project(project) , installOptions(installOptions) , environment(environment) , setupRunEnvConfig(setupRunEnvConfig) , settings(settings) , logger(logger) , evalContext(this->logger) { } void checkProduct() { if (!resolvedProduct) throw ErrorInfo(Tr::tr("Cannot run: No such product.")); if (!resolvedProduct->enabled) { throw ErrorInfo(Tr::tr("Cannot run disabled product '%1'.") .arg(resolvedProduct->fullDisplayName())); } } const ResolvedProductPtr resolvedProduct; const TopLevelProjectConstPtr project; InstallOptions installOptions; const QProcessEnvironment environment; const QStringList setupRunEnvConfig; Settings * const settings; Logger logger; RulesEvaluationContext evalContext; }; RunEnvironment::RunEnvironment(const ResolvedProductPtr &product, const TopLevelProjectConstPtr &project, const InstallOptions &installOptions, const QProcessEnvironment &environment, const QStringList &setupRunEnvConfig, Settings *settings, const Logger &logger) : d(new RunEnvironmentPrivate(product, project, installOptions, environment, setupRunEnvConfig, settings, logger)) { } RunEnvironment::~RunEnvironment() { delete d; } int RunEnvironment::runShell(ErrorInfo *error) { try { return doRunShell(); } catch (const ErrorInfo &e) { if (error) *error = e; return -1; } } int RunEnvironment::runTarget(const QString &targetBin, const QStringList &arguments, bool dryRun, ErrorInfo *error) { try { return doRunTarget(targetBin, arguments, dryRun); } catch (const ErrorInfo &e) { if (error) *error = e; return -1; } } const QProcessEnvironment RunEnvironment::runEnvironment(ErrorInfo *error) const { try { return getRunEnvironment(); } catch (const ErrorInfo &e) { if (error) *error = e; return {}; } } const QProcessEnvironment RunEnvironment::buildEnvironment(ErrorInfo *error) const { try { return getBuildEnvironment(); } catch (const ErrorInfo &e) { if (error) *error = e; return {}; } } int RunEnvironment::doRunShell() { if (d->resolvedProduct) { EnvironmentScriptRunner(d->resolvedProduct.get(), &d->evalContext, d->project->environment).setupForBuild(); } const QString productId = d->resolvedProduct ? d->resolvedProduct->name : QString(); const QString configName = d->project->id(); if (productId.isEmpty()) { d->logger.qbsInfo() << Tr::tr("Starting shell for configuration '%1'.").arg(configName); } else { d->logger.qbsInfo() << Tr::tr("Starting shell for product '%1' in configuration '%2'.") .arg(productId, configName); } const QProcessEnvironment environment = d->resolvedProduct ? d->resolvedProduct->buildEnvironment : d->project->environment; #if defined(Q_OS_LINUX) clearenv(); #endif for (const QString &key : environment.keys()) qputenv(key.toLocal8Bit().constData(), environment.value(key).toLocal8Bit()); QString command; if (HostOsInfo::isWindowsHost()) { command = environment.value(QStringLiteral("COMSPEC")); if (command.isEmpty()) command = QStringLiteral("cmd"); const QString prompt = environment.value(QStringLiteral("PROMPT")); command += QLatin1String(" /k prompt [qbs] ") + prompt; } else { const QVariantMap qbsProps = (d->resolvedProduct ? d->resolvedProduct->moduleProperties->value() : d->project->buildConfiguration()) .value(StringConstants::qbsModule()).toMap(); const QString profileName = qbsProps.value(StringConstants::profileProperty()).toString(); command = Preferences(d->settings, profileName).shell(); if (command.isEmpty()) command = environment.value(QStringLiteral("SHELL"), QStringLiteral("/bin/sh")); // Yes, we have to use this procedure. PS1 is not inherited from the environment. const QString prompt = QLatin1String("qbs ") + configName + (!productId.isEmpty() ? QLatin1Char(' ') + productId : QString()) + QLatin1String(" $ "); QTemporaryFile envFile; if (envFile.open()) { if (command.endsWith(QLatin1String("bash"))) command += QLatin1String(" --posix"); // Teach bash some manners. const QString promptLine = QLatin1String("PS1='") + prompt + QLatin1String("'\n"); envFile.write(promptLine.toLocal8Bit()); envFile.close(); qputenv("ENV", envFile.fileName().toLocal8Bit()); } else { d->logger.qbsWarning() << Tr::tr("Setting custom shell prompt failed."); } } // We cannot use QProcess, since it does not do stdin forwarding. return system(command.toLocal8Bit().constData()); } static QString findExecutable(const QStringList &fileNames) { const QStringList path = QString::fromLocal8Bit(qgetenv("PATH")) .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); for (const QString &fileName : fileNames) { const QString exeFileName = HostOsInfo::appendExecutableSuffix(fileName); for (const QString &ppath : path) { const QString fullPath = ppath + QLatin1Char('/') + exeFileName; QFileInfo fi(fullPath); if (fi.exists() && fi.isFile() && fi.isExecutable()) return QDir::cleanPath(fullPath); } } return {}; } static std::string readAaptBadgingAttribute(const std::string &line) { std::regex re("^[A-Za-z\\-]+:\\s+name='(.+?)'.*$"); std::smatch match; if (std::regex_match(line, match, re)) return match[1]; return {}; } static QString findMainIntent(const QString &aapt, const QString &apkFilePath) { QString packageId; QString activity; QProcess aaptProcess; aaptProcess.start(aapt, QStringList() << QStringLiteral("dump") << QStringLiteral("badging") << apkFilePath); if (aaptProcess.waitForFinished(-1)) { for (auto line : aaptProcess.readAllStandardOutput().split('\n')) { if (line.startsWith(QByteArrayLiteral("package:"))) packageId = QString::fromStdString(readAaptBadgingAttribute(line.toStdString())); else if (line.startsWith(QByteArrayLiteral("launchable-activity:"))) activity = QString::fromStdString(readAaptBadgingAttribute(line.toStdString())); } } if (!packageId.isEmpty() && !activity.isEmpty()) return packageId + QStringLiteral("/") + activity; return {}; } void RunEnvironment::printStartInfo(const QProcess &proc, bool dryRun) { QString message = dryRun ? Tr::tr("Would start target.") : Tr::tr("Starting target."); message.append(QLatin1Char(' ')).append(Tr::tr("Full command line: %1") .arg(shellQuote(QStringList(QDir::toNativeSeparators(proc.program())) << proc.arguments()))); d->logger.qbsInfo() << message; } int RunEnvironment::doRunTarget(const QString &targetBin, const QStringList &arguments, bool dryRun) { d->checkProduct(); const QStringList targetOS = d->resolvedProduct->moduleProperties->qbsPropertyValue( QStringLiteral("targetOS")).toStringList(); const QStringList toolchain = d->resolvedProduct->moduleProperties->qbsPropertyValue( QStringLiteral("toolchain")).toStringList(); QString targetExecutable = targetBin; QStringList targetArguments = arguments; const QString completeSuffix = QFileInfo(targetBin).completeSuffix(); if (targetOS.contains(QLatin1String("android"))) { const auto aapt = d->resolvedProduct->moduleProperties->moduleProperty( QStringLiteral("Android.sdk"), QStringLiteral("aaptFilePath")).toString(); const auto intent = findMainIntent(aapt, targetBin); const auto sdkDir = d->resolvedProduct->moduleProperties->moduleProperty( QStringLiteral("Android.sdk"), QStringLiteral("sdkDir")).toString(); targetExecutable = sdkDir + QStringLiteral("/platform-tools/adb"); if (!dryRun) { QProcess process; process.setProcessChannelMode(QProcess::ForwardedChannels); process.start(targetExecutable, QStringList() << StringConstants::androidInstallCommand() << QStringLiteral("-r") // replace existing application << QStringLiteral("-t") // allow test packages << QStringLiteral("-d") // allow version code downgrade << targetBin); if (!process.waitForFinished(-1)) { if (process.error() == QProcess::FailedToStart) { throw ErrorInfo(Tr::tr("The process '%1' could not be started: %2") .arg(targetExecutable) .arg(process.errorString())); } else { d->logger.qbsWarning() << "QProcess error: " << process.errorString(); } return EXIT_FAILURE; } targetArguments << QStringList() << QStringLiteral("shell") << QStringLiteral("am") << QStringLiteral("start") << QStringLiteral("-W") // wait for launch to complete << QStringLiteral("-n") << intent; } } else if (targetOS.contains(QLatin1String("ios")) || targetOS.contains(QLatin1String("tvos"))) { const QString bundlePath = targetBin + StringConstants::slashDotDot(); if (targetOS.contains(QStringLiteral("ios-simulator")) || targetOS.contains(QStringLiteral("tvos-simulator"))) { const auto developerDir = d->resolvedProduct->moduleProperties->moduleProperty( StringConstants::xcode(), QStringLiteral("developerPath")).toString(); targetExecutable = developerDir + QStringLiteral("/usr/bin/simctl"); const auto simulatorId = QStringLiteral("booted"); // TODO: parameterize const auto bundleId = d->resolvedProduct->moduleProperties->moduleProperty( QStringLiteral("bundle"), QStringLiteral("identifier")).toString(); if (!dryRun) { QProcess process; process.setProcessChannelMode(QProcess::ForwardedChannels); process.start(targetExecutable, QStringList() << StringConstants::simctlInstallCommand() << simulatorId << QDir::cleanPath(bundlePath)); if (!process.waitForFinished(-1)) { if (process.error() == QProcess::FailedToStart) { throw ErrorInfo(Tr::tr("The process '%1' could not be started: %2") .arg(targetExecutable) .arg(process.errorString())); } return EXIT_FAILURE; } targetArguments << QStringList() << QStringLiteral("launch") << QStringLiteral("--console") << simulatorId << bundleId << arguments; } } else { if (QFileInfo(targetExecutable = findExecutable(QStringList() << QStringLiteral("iostool"))).isExecutable()) { targetArguments = QStringList() << QStringLiteral("-run") << QStringLiteral("-bundle") << QDir::cleanPath(bundlePath); if (!arguments.empty()) targetArguments << QStringLiteral("-extra-args") << arguments; } else if (QFileInfo(targetExecutable = findExecutable(QStringList() << QStringLiteral("ios-deploy"))).isExecutable()) { targetArguments = QStringList() << QStringLiteral("--no-wifi") << QStringLiteral("--noninteractive") << QStringLiteral("--bundle") << QDir::cleanPath(bundlePath); if (!arguments.empty()) targetArguments << QStringLiteral("--args") << arguments; } else { d->logger.qbsLog(LoggerError) << Tr::tr("No suitable deployment tools were found in the environment. " "Consider installing ios-deploy."); return EXIT_FAILURE; } } } else if (targetOS.contains(QLatin1String("windows"))) { if (completeSuffix == QLatin1String("msi")) { targetExecutable = QLatin1String("msiexec"); targetArguments.prepend(QDir::toNativeSeparators(targetBin)); targetArguments.prepend(QLatin1String("/package")); } // Run Windows executables through Wine when not on Windows if (!HostOsInfo::isWindowsHost()) { targetArguments.prepend(targetExecutable); targetExecutable = QStringLiteral("wine"); } } if (toolchain.contains(QLatin1String("mono"))) { targetArguments.prepend(targetExecutable); targetExecutable = QStringLiteral("mono"); } if (completeSuffix == QLatin1String("js")) { targetExecutable = d->resolvedProduct->moduleProperties->moduleProperty( QStringLiteral("nodejs"), QStringLiteral("interpreterFilePath")).toString(); if (targetExecutable.isEmpty()) // The Node.js binary is called nodejs on Debian/Ubuntu-family operating systems due to // conflict with another package containing a binary named node targetExecutable = findExecutable(QStringList() << QStringLiteral("nodejs") << QStringLiteral("node")); targetArguments.prepend(targetBin); } // Only check if the target is executable if we're not running it through another // known application such as msiexec or wine, as we can't check in this case anyways QFileInfo fi(targetExecutable); if (!dryRun && targetBin == targetExecutable && (!fi.isFile() || !fi.isExecutable())) { d->logger.qbsLog(LoggerError) << Tr::tr("File '%1' is not an executable.") .arg(QDir::toNativeSeparators(targetExecutable)); return EXIT_FAILURE; } QProcessEnvironment env = d->environment; env.insert(QStringLiteral("QBS_RUN_FILE_PATH"), targetBin); EnvironmentScriptRunner(d->resolvedProduct.get(), &d->evalContext, env) .setupForRun(d->setupRunEnvConfig); QProcess process; process.setProcessEnvironment(d->resolvedProduct->runEnvironment); process.setProcessChannelMode(QProcess::ForwardedChannels); process.setProgram(targetExecutable); process.setArguments(targetArguments); printStartInfo(process, dryRun); if (dryRun) return EXIT_SUCCESS; process.start(); if (!process.waitForFinished(-1)) { if (process.error() == QProcess::FailedToStart) { QString errorPrefixString; #ifdef Q_OS_UNIX if (QFileInfo(targetExecutable).isExecutable()) { const QString interpreter(shellInterpreter(targetExecutable)); if (!interpreter.isEmpty()) { errorPrefixString = Tr::tr("%1: bad interpreter: ").arg(interpreter); } } #endif throw ErrorInfo(Tr::tr("The process '%1' could not be started: %2") .arg(targetExecutable) .arg(errorPrefixString + process.errorString())); } else { d->logger.qbsWarning() << "QProcess error: " << process.errorString(); } return EXIT_FAILURE; } return process.exitCode(); } const QProcessEnvironment RunEnvironment::getRunEnvironment() const { d->checkProduct(); EnvironmentScriptRunner(d->resolvedProduct.get(), &d->evalContext, d->environment) .setupForRun(d->setupRunEnvConfig); return d->resolvedProduct->runEnvironment; } const QProcessEnvironment RunEnvironment::getBuildEnvironment() const { if (!d->resolvedProduct) return d->environment; EnvironmentScriptRunner(d->resolvedProduct.get(), &d->evalContext, d->environment) .setupForBuild(); return d->resolvedProduct->buildEnvironment; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/api/runenvironment.h000066400000000000000000000070631347155106100221470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_RUNENVIRONMENT_H #define QBS_RUNENVIRONMENT_H #include #include #include QT_BEGIN_NAMESPACE class QProcess; class QProcessEnvironment; class QString; class QStringList; QT_END_NAMESPACE namespace qbs { class ErrorInfo; class InstallOptions; class Settings; namespace Internal { class Logger; class ResolvedProduct; } // namespace Internal class QBS_EXPORT RunEnvironment { friend class CommandLineFrontend; friend class Project; friend class TestApi; public: ~RunEnvironment(); int runShell(ErrorInfo *error = nullptr); int runTarget(const QString &targetBin, const QStringList &arguments, bool dryRun, ErrorInfo *error = nullptr); const QProcessEnvironment runEnvironment(ErrorInfo *error = nullptr) const; const QProcessEnvironment buildEnvironment(ErrorInfo *error = nullptr) const; private: RunEnvironment(const Internal::ResolvedProductPtr &product, const Internal::TopLevelProjectConstPtr &project, const InstallOptions &installOptions, const QProcessEnvironment &environment, const QStringList &setupRunEnvConfig, Settings *settings, const Internal::Logger &logger); int doRunShell(); int doRunTarget(const QString &targetBin, const QStringList &arguments, bool dryRun); void printStartInfo(const QProcess &proc, bool dryRun); const QProcessEnvironment getRunEnvironment() const; const QProcessEnvironment getBuildEnvironment() const; class RunEnvironmentPrivate; RunEnvironmentPrivate * const d; }; } // namespace qbs #endif // QBS_RUNENVIRONMENT_H qbs-src-1.13.1/src/lib/corelib/api/transformerdata.cpp000066400000000000000000000047371347155106100226120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "transformerdata_p.h" #include namespace qbs { TransformerData::TransformerData() : d(new Internal::TransformerDataPrivate) { } TransformerData::TransformerData(const TransformerData &other) : d(other.d) {} TransformerData::~TransformerData() { } TransformerData& TransformerData::operator=(const TransformerData &other) { d = other.d; return *this; } QList TransformerData::inputs() const { return d->inputs; } QList TransformerData::outputs() const { return d->outputs; } RuleCommandList TransformerData::commands() const { return d->commands; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/api/transformerdata.h000066400000000000000000000053731347155106100222540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TRANSFORMERDATA_H #define QBS_TRANSFORMERDATA_H #include "projectdata.h" #include "rulecommand.h" #include #include #include namespace qbs { namespace Internal { class ProjectPrivate; class TransformerDataPrivate; } class QBS_EXPORT TransformerData { friend class Internal::ProjectPrivate; public: TransformerData(); TransformerData(const TransformerData &other); ~TransformerData(); TransformerData &operator=(const TransformerData &other); QList inputs() const; QList outputs() const; RuleCommandList commands() const; private: QExplicitlySharedDataPointer d; }; using ProductTransformerData = QList; using ProjectTransformerData = QList>; } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/api/transformerdata_p.h000066400000000000000000000043121347155106100225630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TRANSFORMERDATA_P_H #define QBS_TRANSFORMERDATA_P_H #include "transformerdata.h" namespace qbs { namespace Internal { class TransformerDataPrivate : public QSharedData { public: QList inputs; QList outputs; RuleCommandList commands; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/buildgraph/000077500000000000000000000000001347155106100202475ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp000066400000000000000000000062771347155106100257100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "abstractcommandexecutor.h" #include "rulecommands.h" #include "transformer.h" #include #include #include namespace qbs { namespace Internal { AbstractCommandExecutor::AbstractCommandExecutor(const Logger &logger, QObject *parent) : QObject(parent) , m_echoMode(defaultCommandEchoMode()) , m_command(nullptr) , m_transformer(nullptr) , m_mainThreadScriptEngine(nullptr) , m_dryRun(false) , m_logger(logger) { } void AbstractCommandExecutor::start(Transformer *transformer, AbstractCommand *cmd) { m_transformer = transformer; m_command = cmd; doSetup(); doReportCommandDescription(transformer->product()->fullDisplayName()); doStart(); } void AbstractCommandExecutor::doReportCommandDescription(const QString &productName) { if (m_command->isSilent() || m_echoMode == CommandEchoModeSilent) return; if (m_command->description().isEmpty()) { m_logger.printWarning( ErrorInfo(Tr::tr("Command is not marked silent, but has no description."), m_command->codeLocation())); } else { emit reportCommandDescription(m_command->highlight(), m_command->fullDescription(productName)); } } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/abstractcommandexecutor.h000066400000000000000000000070711347155106100253460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ABSTRACTCOMMANDEXECUTOR_H #define QBS_ABSTRACTCOMMANDEXECUTOR_H #include #include #include #include namespace qbs { class ErrorInfo; namespace Internal { class AbstractCommand; class ScriptEngine; class Transformer; class AbstractCommandExecutor : public QObject { Q_OBJECT public: explicit AbstractCommandExecutor(const Internal::Logger &logger, QObject *parent = nullptr); void setMainThreadScriptEngine(ScriptEngine *engine) { m_mainThreadScriptEngine = engine; } void setDryRunEnabled(bool enabled) { m_dryRun = enabled; } void setEchoMode(CommandEchoMode echoMode) { m_echoMode = echoMode; } virtual void cancel() = 0; void start(Transformer *transformer, AbstractCommand *cmd); signals: void reportCommandDescription(const QString &highlight, const QString &message); void finished(const qbs::ErrorInfo &err = ErrorInfo()); // !hasError() <=> command successful protected: virtual void doReportCommandDescription(const QString &productName); AbstractCommand *command() const { return m_command; } Transformer *transformer() const { return m_transformer; } ScriptEngine *scriptEngine() const { return m_mainThreadScriptEngine; } bool dryRun() const { return m_dryRun; } Internal::Logger logger() const { return m_logger; } CommandEchoMode m_echoMode; private: virtual void doSetup() { }; virtual void doStart() = 0; private: AbstractCommand *m_command; Transformer *m_transformer; ScriptEngine *m_mainThreadScriptEngine; bool m_dryRun; Internal::Logger m_logger; }; } // namespace Internal } // namespace qbs #endif // QBS_ABSTRACTCOMMANDEXECUTOR_H qbs-src-1.13.1/src/lib/corelib/buildgraph/artifact.cpp000066400000000000000000000135131347155106100225530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "artifact.h" #include "transformer.h" #include "buildgraphvisitor.h" #include "productbuilddata.h" #include "rulenode.h" #include #include #include #include namespace qbs { namespace Internal { Artifact::Artifact() { initialize(); } Artifact::~Artifact() { for (Artifact *p : parentArtifacts()) p->childrenAddedByScanner.remove(this); } void Artifact::accept(BuildGraphVisitor *visitor) { if (visitor->visit(this)) acceptChildren(visitor); visitor->endVisit(this); } QString Artifact::toString() const { return QLatin1String("ARTIFACT ") + filePath() + QLatin1String(" [") + (!product.expired() ? product->name : QLatin1String("")) + QLatin1Char(']'); } void Artifact::addFileTag(const FileTag &t) { m_fileTags += t; if (!product.expired() && product->buildData) { product->buildData->addFileTagToArtifact(this, t); if (product->fileTags.contains(t)) product->buildData->addRootNode(this); } } void Artifact::removeFileTag(const FileTag &t) { m_fileTags -= t; if (!product.expired() && product->buildData) { product->buildData->removeArtifactFromSetByFileTag(this, t); if (product->fileTags.contains(t) && !product->fileTags.intersects(m_fileTags)) product->buildData->removeFromRootNodes(this); } } void Artifact::setFileTags(const FileTags &newFileTags) { if (product.expired() || !product->buildData) { m_fileTags = newFileTags; return; } if (m_fileTags == newFileTags) return; const Set addedTags = newFileTags - m_fileTags; for (const FileTag &t : addedTags) addFileTag(t); const Set removedTags = m_fileTags - newFileTags; for (const FileTag &t : removedTags) removeFileTag(t); } RuleNode *Artifact::producer() const { if (artifactType == SourceFile) return nullptr; const auto ruleNodes = filterByType(children); QBS_CHECK(ruleNodes.begin() != ruleNodes.end()); return *ruleNodes.begin(); } void Artifact::initialize() { artifactType = Unknown; inputsScanned = false; timestampRetrieved = false; alwaysUpdated = true; oldDataPossiblyPresent = true; } const TypeFilter Artifact::parentArtifacts() const { return TypeFilter(parents); } const TypeFilter Artifact::childArtifacts() const { return TypeFilter(children); } void Artifact::onChildDisconnected(BuildGraphNode *child) { if (child->type() != BuildGraphNode::ArtifactNodeType) return; childrenAddedByScanner.remove(static_cast(child)); } void Artifact::load(PersistentPool &pool) { FileResourceBase::load(pool); BuildGraphNode::load(pool); children.load(pool); // restore parents of the loaded children for (auto it = children.constBegin(); it != children.constEnd(); ++it) (*it)->parents.insert(this); pool.load(childrenAddedByScanner); pool.load(fileDependencies); pool.load(properties); pool.load(targetOfModule); pool.load(transformer); pool.load(m_fileTags); pool.load(pureFileTags); pool.load(pureProperties); artifactType = static_cast(pool.load()); alwaysUpdated = pool.load(); oldDataPossiblyPresent = pool.load(); } void Artifact::store(PersistentPool &pool) { FileResourceBase::store(pool); BuildGraphNode::store(pool); // Do not store parents to avoid recursion. children.store(pool); pool.store(childrenAddedByScanner); pool.store(fileDependencies); pool.store(properties); pool.store(targetOfModule); pool.store(transformer); pool.store(m_fileTags); pool.store(pureFileTags); pool.store(pureProperties); pool.store(static_cast(artifactType)); pool.store(alwaysUpdated); pool.store(oldDataPossiblyPresent); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/artifact.h000066400000000000000000000131111347155106100222120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ARTIFACT_H #define QBS_ARTIFACT_H #include "filedependency.h" #include "buildgraphnode.h" #include "forward_decls.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { class Logger; class Artifact; using ArtifactSet = Set; /** * The Artifact class * * Let artifact P be the parent of artifact C. Thus C is child of P. * C produces P using the transformer P.transformer. * * */ class QBS_AUTOTEST_EXPORT Artifact : public FileResourceBase, public BuildGraphNode { public: Artifact(); ~Artifact(); Type type() const override { return ArtifactNodeType; } FileType fileType() const override { return FileTypeArtifact; } void accept(BuildGraphVisitor *visitor) override; QString toString() const override; void addFileTag(const FileTag &t); void removeFileTag(const FileTag &t); void setFileTags(const FileTags &newFileTags); const FileTags &fileTags() const { return m_fileTags; } RuleNode *producer() const; ArtifactSet childrenAddedByScanner; Set fileDependencies; TransformerPtr transformer; PropertyMapPtr properties; QString targetOfModule; // The tags set directly via an Artifact item or an outputArtifacts script, // not the result of file taggers or fileTagsFilter groups, nor the ones inherited from // the product. FileTags pureFileTags; // The properties attached directly to an artifact in an Artifact item or outputArtifacts // script. std::vector> pureProperties; enum ArtifactType { Unknown = 1, SourceFile = 2, Generated = 4 }; ArtifactType artifactType; bool inputsScanned : 1; // Do not serialize. Will be refreshed for every build. bool timestampRetrieved : 1; // Do not serialize. Will be refreshed for every build. bool alwaysUpdated : 1; bool oldDataPossiblyPresent : 1; void initialize(); const TypeFilter parentArtifacts() const; const TypeFilter childArtifacts() const; void onChildDisconnected(BuildGraphNode *child) override; bool isTargetOfModule() const { return !targetOfModule.isEmpty(); } void load(PersistentPool &pool) override; void store(PersistentPool &pool) override; private: FileTags m_fileTags; }; template<> inline QString Set::toString(Artifact * const &artifact) const { return artifact ? artifact->filePath() : QStringLiteral(""); } template<> inline const void *uniqueAddress(const Artifact *a) { return static_cast(a); } template<> inline bool hasDynamicType(const BuildGraphNode *n) { return n->type() == BuildGraphNode::ArtifactNodeType; } // debugging helper inline QString toString(Artifact::ArtifactType t) { switch (t) { case Artifact::SourceFile: return QStringLiteral("SourceFile"); case Artifact::Generated: return QStringLiteral("Generated"); case Artifact::Unknown: default: return QStringLiteral("Unknown"); } } // debugging helper inline QString toString(BuildGraphNode::BuildState s) { switch (s) { case BuildGraphNode::Untouched: return QStringLiteral("Untouched"); case BuildGraphNode::Buildable: return QStringLiteral("Buildable"); case BuildGraphNode::Building: return QStringLiteral("Building"); case BuildGraphNode::Built: return QStringLiteral("Built"); default: return QStringLiteral("Unknown"); } } } // namespace Internal } // namespace qbs #endif // QBS_ARTIFACT_H qbs-src-1.13.1/src/lib/corelib/buildgraph/artifactcleaner.cpp000066400000000000000000000177711347155106100241170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "artifactcleaner.h" #include "artifact.h" #include "artifactvisitor.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static void printRemovalMessage(const QString &path, bool dryRun, const Logger &logger) { if (dryRun) logger.qbsInfo() << Tr::tr("Would remove '%1'.").arg(path); else logger.qbsDebug() << "Removing '" << path << "'."; } static void invalidateArtifactTimestamp(Artifact *artifact) { if (artifact->timestamp().isValid()) { artifact->clearTimestamp(); artifact->product->topLevelProject()->buildData->setDirty(); } } static void removeArtifactFromDisk(Artifact *artifact, bool dryRun, const Logger &logger) { QFileInfo fileInfo(artifact->filePath()); if (!FileInfo::fileExists(fileInfo)) { if (!dryRun) invalidateArtifactTimestamp(artifact); return; } printRemovalMessage(fileInfo.filePath(), dryRun, logger); if (dryRun) return; invalidateArtifactTimestamp(artifact); QString errorMessage; if (!removeFileRecursion(fileInfo, &errorMessage)) throw ErrorInfo(errorMessage); } class CleanupVisitor : public ArtifactVisitor { public: CleanupVisitor(const CleanOptions &options, const ProgressObserver *observer, const Logger &logger) : ArtifactVisitor(Artifact::Generated) , m_options(options) , m_observer(observer) , m_logger(logger) , m_hasError(false) { } void visitProduct(const ResolvedProductPtr &product) { m_product = product; ArtifactVisitor::visitProduct(product); const AllRescuableArtifactData rescuableArtifactData = product->buildData->rescuableArtifactData(); for (auto it = rescuableArtifactData.begin(); it != rescuableArtifactData.end(); ++it) { Artifact tmp; tmp.product = product; tmp.setFilePath(it.key()); tmp.setTimestamp(it.value().timeStamp); removeArtifactFromDisk(&tmp, m_options.dryRun(), m_logger); product->buildData->removeFromRescuableArtifactData(it.key()); } } const Set &directories() const { return m_directories; } bool hasError() const { return m_hasError; } private: void doVisit(Artifact *artifact) override { if (m_observer->canceled()) throw ErrorInfo(Tr::tr("Cleaning up was canceled.")); if (artifact->product != m_product) return; try { removeArtifactFromDisk(artifact, m_options.dryRun(), m_logger); } catch (const ErrorInfo &error) { if (!m_options.keepGoing()) throw; m_logger.printWarning(error); m_hasError = true; } m_directories << artifact->dirPath(); } const CleanOptions m_options; const ProgressObserver * const m_observer; Logger m_logger; bool m_hasError; ResolvedProductConstPtr m_product; Set m_directories; }; ArtifactCleaner::ArtifactCleaner(const Logger &logger, ProgressObserver *observer) : m_logger(logger), m_observer(observer) { } void ArtifactCleaner::cleanup(const TopLevelProjectPtr &project, const QList &products, const CleanOptions &options) { m_hasError = false; const QString configString = Tr::tr(" for configuration %1").arg(project->id()); m_observer->initialize(Tr::tr("Cleaning up%1").arg(configString), products.size() + 1); Set directories; for (const ResolvedProductPtr &product : products) { CleanupVisitor visitor(options, m_observer, m_logger); visitor.visitProduct(product); directories.unite(visitor.directories()); if (visitor.hasError()) m_hasError = true; m_observer->incrementProgressValue(); } // Directories created during the build are not artifacts (TODO: should they be?), // so we have to clean them up manually. QList dirList = directories.toList(); for (int i = 0; i < dirList.size(); ++i) { const QString &dir = dirList.at(i); if (!dir.startsWith(project->buildDirectory)) continue; if (FileInfo(dir).exists()) removeEmptyDirectories(dir, options); if (dir != project->buildDirectory) { const QString parentDir = QDir::cleanPath(dir + StringConstants::slashDotDot()); if (parentDir != project->buildDirectory && !dirList.contains(parentDir)) dirList.push_back(parentDir); } } m_observer->incrementProgressValue(); if (m_hasError) throw ErrorInfo(Tr::tr("Failed to remove some files.")); m_observer->setFinished(); } void ArtifactCleaner::removeEmptyDirectories(const QString &rootDir, const CleanOptions &options, bool *isEmpty) { bool subTreeIsEmpty = true; QDirIterator it(rootDir, QDir::Files | QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot); while (it.hasNext()) { it.next(); if (!it.fileInfo().isSymLink() && it.fileInfo().isDir()) removeEmptyDirectories(it.filePath(), options, &subTreeIsEmpty); else subTreeIsEmpty = false; } if (subTreeIsEmpty) { printRemovalMessage(rootDir, options.dryRun(), m_logger); if (!QDir::root().rmdir(rootDir)) { ErrorInfo error(Tr::tr("Failure to remove empty directory '%1'.").arg(rootDir)); if (!options.keepGoing()) throw error; m_logger.printWarning(error); m_hasError = true; subTreeIsEmpty = false; } } if (!subTreeIsEmpty && isEmpty) *isEmpty = false; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/artifactcleaner.h000066400000000000000000000051671347155106100235600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ARTIFACTCLEANER_H #define QBS_ARTIFACTCLEANER_H #include #include #include namespace qbs { class CleanOptions; namespace Internal { class ProgressObserver; class ArtifactCleaner { public: ArtifactCleaner(const Logger &logger, ProgressObserver *observer); void cleanup(const TopLevelProjectPtr &project, const QList &products, const CleanOptions &options); private: void removeEmptyDirectories(const QString &rootDir, const CleanOptions &options, bool *isEmpty = nullptr); Logger m_logger; bool m_hasError; ProgressObserver *m_observer; }; } // namespace Internal } // namespace qbs #endif // QBS_ARTIFACTCLEANER_H qbs-src-1.13.1/src/lib/corelib/buildgraph/artifactsscriptvalue.cpp000066400000000000000000000204271347155106100252220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "artifactsscriptvalue.h" #include "artifact.h" #include "productbuilddata.h" #include "transformer.h" #include #include #include #include namespace qbs { namespace Internal { enum BuildGraphScriptValueCommonPropertyKeys : quint32 { CachedValueKey, FileTagKey, ProductPtrKey, }; class ArtifactsScriptClass : public QScriptClass { public: ArtifactsScriptClass(QScriptEngine *engine) : QScriptClass(engine) { } private: QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id) override { getProduct(object); qbsEngine()->setNonExistingArtifactSetRequested(m_product, name.toString()); return QScriptClass::queryProperty(object, name, flags, id); } QScriptClassPropertyIterator *newIterator(const QScriptValue &object) override { getProduct(object); qbsEngine()->setArtifactsEnumerated(m_product); return QScriptClass::newIterator(object); } void getProduct(const QScriptValue &object) { if (m_lastObjectId != object.objectId()) { m_lastObjectId = object.objectId(); m_product = reinterpret_cast( object.data().property(ProductPtrKey).toVariant().value()); } } ScriptEngine *qbsEngine() const { return static_cast(engine()); } qint64 m_lastObjectId = 0; const ResolvedProduct *m_product = nullptr; }; static bool isRelevantArtifact(const ResolvedProduct *, const Artifact *artifact) { return !artifact->isTargetOfModule(); } static bool isRelevantArtifact(const ResolvedModule *module, const Artifact *artifact) { return artifact->targetOfModule == module->name; } static ArtifactSetByFileTag artifactsMap(const ResolvedProduct *product) { return product->buildData->artifactsByFileTag(); } static ArtifactSetByFileTag artifactsMap(const ResolvedModule *module) { return artifactsMap(module->product); } static QScriptValue createArtifactsObject(const ResolvedProduct *product, ScriptEngine *engine) { QScriptClass *scriptClass = engine->artifactsScriptClass(); if (!scriptClass) { scriptClass = new ArtifactsScriptClass(engine); engine->setArtifactsScriptClass(scriptClass); } QScriptValue artifactsObj = engine->newObject(scriptClass); QScriptValue data = engine->newObject(); QVariant v; v.setValue(reinterpret_cast(product)); data.setProperty(ProductPtrKey, engine->newVariant(v)); artifactsObj.setData(data); return artifactsObj; } static QScriptValue createArtifactsObject(const ResolvedModule *, ScriptEngine *engine) { return engine->newObject(); } static bool checkAndSetArtifactsMapUpToDateFlag(const ResolvedProduct *p) { return p->buildData->checkAndSetJsArtifactsMapUpToDateFlag(); } static bool checkAndSetArtifactsMapUpToDateFlag(const ResolvedModule *) { return true; } static void registerArtifactsMapAccess(const ResolvedProduct *p, ScriptEngine *e, bool forceUpdate) { e->setArtifactsMapRequested(p, forceUpdate); } static void registerArtifactsMapAccess(const ResolvedModule *, ScriptEngine *, bool) {} static void registerArtifactsSetAccess(const ResolvedProduct *p, const FileTag &t, ScriptEngine *e) { e->setArtifactSetRequestedForTag(p, t); } static void registerArtifactsSetAccess(const ResolvedModule *, const FileTag &, ScriptEngine *) {} template static QScriptValue js_artifactsForFileTag( QScriptContext *ctx, ScriptEngine *engine, const ProductOrModule *productOrModule) { const FileTag fileTag = FileTag(ctx->callee().property(FileTagKey).toString().toUtf8()); registerArtifactsSetAccess(productOrModule, fileTag, engine); QScriptValue result = ctx->callee().property(CachedValueKey); if (result.isArray()) return result; auto artifacts = artifactsMap(productOrModule).value(fileTag); const auto filter = [productOrModule](const Artifact *a) { return !isRelevantArtifact(productOrModule, a); }; artifacts.erase(std::remove_if(artifacts.begin(), artifacts.end(), filter), artifacts.end()); result = engine->newArray(uint(artifacts.size())); ctx->callee().setProperty(CachedValueKey, result); int k = 0; for (const Artifact * const artifact : artifacts) result.setProperty(k++, Transformer::translateFileConfig(engine, artifact, QString())); return result; } template static QScriptValue js_artifacts( QScriptContext *ctx, ScriptEngine *engine, const ProductOrModule *productOrModule) { QScriptValue artifactsObj = ctx->callee().property(CachedValueKey); if (artifactsObj.isObject() && checkAndSetArtifactsMapUpToDateFlag(productOrModule)) { registerArtifactsMapAccess(productOrModule, engine, false); return artifactsObj; } registerArtifactsMapAccess(productOrModule, engine, true); artifactsObj = createArtifactsObject(productOrModule, engine); ctx->callee().setProperty(CachedValueKey, artifactsObj); const auto &map = artifactsMap(productOrModule); for (auto it = map.cbegin(); it != map.cend(); ++it) { const auto filter = [productOrModule](const Artifact *a) { return isRelevantArtifact(productOrModule, a); }; if (std::none_of(it.value().cbegin(), it.value().cend(), filter)) continue; QScriptValue fileTagFunc = engine->newFunction(&js_artifactsForFileTag, productOrModule); const QString fileTag = it.key().toString(); fileTagFunc.setProperty(FileTagKey, fileTag); artifactsObj.setProperty(fileTag, fileTagFunc, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::PropertyGetter); } return artifactsObj; } QScriptValue artifactsScriptValueForProduct(QScriptContext *ctx, ScriptEngine *engine, const ResolvedProduct *product) { return js_artifacts(ctx, engine, product); } QScriptValue artifactsScriptValueForModule(QScriptContext *ctx, ScriptEngine *engine, const ResolvedModule *module) { return js_artifacts(ctx, engine, module); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/artifactsscriptvalue.h000066400000000000000000000047571347155106100246770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ARTIFACTSSCRIPTVALUE_H #define QBS_ARTIFACTSSCRIPTVALUE_H #include #include QT_BEGIN_NAMESPACE class QScriptContext; QT_END_NAMESPACE namespace qbs { namespace Internal { class ScriptEngine; QScriptValue artifactsScriptValueForProduct(QScriptContext *ctx, ScriptEngine *engine, const ResolvedProduct *product); QScriptValue artifactsScriptValueForModule(QScriptContext *ctx, ScriptEngine *engine, const ResolvedModule *module); } // namespace Internal } // namespace qbs #endif // include guard qbs-src-1.13.1/src/lib/corelib/buildgraph/artifactvisitor.cpp000066400000000000000000000055311347155106100241740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "artifactvisitor.h" #include "artifact.h" #include "productbuilddata.h" #include #include #include namespace qbs { namespace Internal { ArtifactVisitor::ArtifactVisitor(int artifactType) : m_artifactType(artifactType) { } void ArtifactVisitor::visitProduct(const ResolvedProductConstPtr &product) { if (!product->buildData) return; for (BuildGraphNode *node : qAsConst(product->buildData->allNodes())) node->accept(this); } void ArtifactVisitor::visitProject(const ResolvedProjectConstPtr &project) { for (const ResolvedProductConstPtr &product : project->allProducts()) visitProduct(product); } bool ArtifactVisitor::visit(RuleNode *ruleNode) { Q_UNUSED(ruleNode); return false; } bool ArtifactVisitor::visit(Artifact *artifact) { QBS_CHECK(artifact); if (m_artifactType & artifact->artifactType) doVisit(artifact); return false; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/artifactvisitor.h000066400000000000000000000050441347155106100236400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ARTIFACTVISITOR_H #define QBS_ARTIFACTVISITOR_H #include "forward_decls.h" #include "buildgraphvisitor.h" #include #include namespace qbs { namespace Internal { class ArtifactVisitor : public BuildGraphVisitor { public: ArtifactVisitor(int artifactType); void visitProduct(const ResolvedProductConstPtr &product); void visitProject(const ResolvedProjectConstPtr &project); bool visit(RuleNode *ruleNode) override; bool visit(Artifact *artifact) override; private: virtual void doVisit(Artifact *artifact) = 0; const int m_artifactType; }; } // namespace Internal } // namespace qbs #endif // QBS_ARTIFACTVISITOR_H qbs-src-1.13.1/src/lib/corelib/buildgraph/buildgraph.cpp000066400000000000000000001125771347155106100231110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "buildgraph.h" #include "artifact.h" #include "artifactsscriptvalue.h" #include "cycledetector.h" #include "dependencyparametersscriptvalue.h" #include "projectbuilddata.h" #include "productbuilddata.h" #include "rulenode.h" #include "scriptclasspropertyiterator.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static QString childItemsProperty() { return QStringLiteral("childItems"); } static QString exportsProperty() { return QStringLiteral("exports"); } // TODO: Introduce productscriptvalue.{h,cpp}. static QScriptValue getDataForProductScriptValue(QScriptEngine *engine, const ResolvedProduct *product) { QScriptValue data = engine->newObject(); QVariant v; v.setValue(reinterpret_cast(product)); data.setProperty(ProductPtrKey, engine->newVariant(v)); return data; } class ProductPropertyScriptClass : public QScriptClass { public: ProductPropertyScriptClass(QScriptEngine *engine) : QScriptClass(engine) { } private: QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags, uint *) override { if (name == StringConstants::parametersProperty()) { m_result = object.data().property(DependencyParametersKey); return HandlesReadAccess; } if (name == StringConstants::moduleNameProperty()) { m_result = object.data().property(ModuleNameKey); return HandlesReadAccess; } if (name == StringConstants::dependenciesProperty() || name == StringConstants::artifactsProperty() || name == exportsProperty()) { // The prototype is not backed by a QScriptClass. m_result = object.prototype().property(name); return HandlesReadAccess; } getProduct(object); QBS_ASSERT(m_product, {}); const auto it = m_product->productProperties.find(name); // It is important that we reject unknown property names. Otherwise QtScript will forward // *everything* to us, including built-in stuff like the hasOwnProperty function. if (it == m_product->productProperties.cend()) return {}; qbsEngine()->addPropertyRequestedInScript(Property(m_product->uniqueName(), QString(), name, it.value(), Property::PropertyInProduct)); m_result = qbsEngine()->toScriptValue(it.value()); return HandlesReadAccess; } QScriptValue property(const QScriptValue &, const QScriptString &, uint) override { return m_result; } QScriptClassPropertyIterator *newIterator(const QScriptValue &object) override { getProduct(object); QBS_ASSERT(m_product, return nullptr); // These two are in the prototype and are thus common to all product script values. std::vector additionalProperties({StringConstants::artifactsProperty(), StringConstants::dependenciesProperty(), exportsProperty()}); // The "moduleName" convenience property is only available for the "main product" in a rule, // and the "parameters" property exists only for elements of the "dependencies" array for // which dependency parameters are present. if (object.data().property(ModuleNameKey).isValid()) additionalProperties.push_back(StringConstants::moduleNameProperty()); else if (object.data().property(DependencyParametersKey).isValid()) additionalProperties.push_back(StringConstants::parametersProperty()); return new ScriptClassPropertyIterator(object, m_product->productProperties, additionalProperties); } void getProduct(const QScriptValue &object) { if (m_lastObjectId != object.objectId()) { m_lastObjectId = object.objectId(); m_product = reinterpret_cast( object.data().property(ProductPtrKey).toVariant().value()); } } ScriptEngine *qbsEngine() const { return static_cast(engine()); } qint64 m_lastObjectId = 0; const ResolvedProduct *m_product = nullptr; QScriptValue m_result; }; static QScriptValue setupProjectScriptValue(ScriptEngine *engine, const ResolvedProjectConstPtr &project) { QScriptValue &obj = engine->projectScriptValue(project.get()); if (obj.isValid()) return obj; obj = engine->newObject(); obj.setProperty(StringConstants::filePathProperty(), project->location.filePath()); obj.setProperty(StringConstants::pathProperty(), FileInfo::path(project->location.filePath())); const QVariantMap &projectProperties = project->projectProperties(); for (QVariantMap::const_iterator it = projectProperties.begin(); it != projectProperties.end(); ++it) { engine->setObservedProperty(obj, it.key(), engine->toScriptValue(it.value())); } engine->observer()->addProjectObjectId(obj.objectId(), project->name); return obj; } static QScriptValue setupProductScriptValue(ScriptEngine *engine, const ResolvedProduct *product); class DependenciesFunction { public: DependenciesFunction(ScriptEngine *engine) : m_engine(engine) { } void init(QScriptValue &productScriptValue, QScriptValue &exportsScriptValue, const ResolvedProduct *product) { QScriptValue depfunc = m_engine->newFunction(&js_internalProductDependencies, product); productScriptValue.setProperty(StringConstants::dependenciesProperty(), depfunc, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::PropertyGetter); depfunc = m_engine->newFunction(&js_exportedProductDependencies, product); exportsScriptValue.setProperty(StringConstants::dependenciesProperty(), depfunc, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::PropertyGetter); } private: enum class DependencyType { Internal, Exported }; static QScriptValue js_productDependencies(QScriptContext *, ScriptEngine *engine, const ResolvedProduct *product, DependencyType depType) { QScriptValue result = engine->newArray(); quint32 idx = 0; const bool exportCase = depType == DependencyType::Exported; std::vector productDeps; if (exportCase) { if (!product->exportedModule.productDependencies.empty()) { const auto allProducts = product->topLevelProject()->allProducts(); const auto getProductForName = [&allProducts](const QString &name) { const auto cmp = [name](const ResolvedProductConstPtr &p) { return p->uniqueName() == name; }; const auto it = std::find_if(allProducts.cbegin(), allProducts.cend(), cmp); QBS_ASSERT(it != allProducts.cend(), return ResolvedProductPtr()); return *it; }; std::transform(product->exportedModule.productDependencies.cbegin(), product->exportedModule.productDependencies.cend(), std::back_inserter(productDeps), getProductForName); } } else { productDeps = product->dependencies; } for (const ResolvedProductPtr &dependency : qAsConst(productDeps)) { QScriptValue obj = engine->newObject(engine->productPropertyScriptClass()); obj.setPrototype(setupProductScriptValue(static_cast(engine), dependency.get())); const QVariantMap ¶ms = (exportCase ? product->exportedModule.dependencyParameters.value(dependency) : product->dependencyParameters.value(dependency)); QScriptValue data = getDataForProductScriptValue(engine, dependency.get()); data.setProperty(DependencyParametersKey, dependencyParametersValue( product->uniqueName(), dependency->name, params, engine)); obj.setData(data); result.setProperty(idx++, obj); } if (exportCase) { for (const ExportedModuleDependency &m : product->exportedModule.moduleDependencies) { QScriptValue obj = engine->newObject(); obj.setProperty(StringConstants::nameProperty(), m.name); QScriptValue exportsValue = engine->newObject(); obj.setProperty(exportsProperty(), exportsValue); exportsValue.setProperty(StringConstants::dependenciesProperty(), engine->newArray()); for (auto modIt = m.moduleProperties.begin(); modIt != m.moduleProperties.end(); ++modIt) { const QVariantMap entries = modIt.value().toMap(); if (entries.empty()) continue; QScriptValue moduleObj = engine->newObject(); ModuleProperties::setModuleScriptValue(exportsValue, moduleObj, modIt.key()); for (auto valIt = entries.begin(); valIt != entries.end(); ++valIt) moduleObj.setProperty(valIt.key(), engine->toScriptValue(valIt.value())); } result.setProperty(idx++, obj); } return result; } for (const ResolvedModuleConstPtr &dependency : product->modules) { if (dependency->isProduct) continue; QScriptValue obj = engine->newObject(engine->modulePropertyScriptClass()); obj.setPrototype(engine->moduleScriptValuePrototype(dependency.get())); // The prototype must exist already, because we set it up for all modules // of the product in ModuleProperties::init(). QBS_ASSERT(obj.prototype().isValid(), ;); const QVariantMap ¶ms = product->moduleParameters.value(dependency); QScriptValue data = getDataForModuleScriptValue(engine, product, nullptr, dependency.get()); data.setProperty(DependencyParametersKey, dependencyParametersValue( product->uniqueName(), dependency->name, params, engine)); obj.setData(data); result.setProperty(idx++, obj); } return result; } static QScriptValue js_internalProductDependencies(QScriptContext *ctx, ScriptEngine *engine, const ResolvedProduct * const product) { engine->addDependenciesArrayRequested(product); return js_productDependencies(ctx, engine, product, DependencyType::Internal); } static QScriptValue js_exportedProductDependencies(QScriptContext *ctx, ScriptEngine *engine, const ResolvedProduct * const product) { return js_productDependencies(ctx, engine, product, DependencyType::Exported); } ScriptEngine *m_engine; }; static QScriptValue setupExportedPropertyScriptValue(const ExportedProperty &property, ScriptEngine *engine) { QScriptValue propertyScriptValue = engine->newObject(); propertyScriptValue.setProperty(StringConstants::nameProperty(), property.fullName); propertyScriptValue.setProperty(StringConstants::typeProperty(), PropertyDeclaration::typeString(property.type)); propertyScriptValue.setProperty(StringConstants::sourceCodeProperty(), property.sourceCode); propertyScriptValue.setProperty(QStringLiteral("isBuiltin"), property.isBuiltin); return propertyScriptValue; } static void setupExportedPropertiesScriptValue(QScriptValue &parentObject, const std::vector &properties, ScriptEngine *engine) { QScriptValue propertiesScriptValue = engine->newArray(static_cast(properties.size())); parentObject.setProperty(QStringLiteral("properties"), propertiesScriptValue); quint32 arrayIndex = 0; for (const ExportedProperty &p : properties) { propertiesScriptValue.setProperty(arrayIndex++, setupExportedPropertyScriptValue(p, engine)); } } static QScriptValue setupExportedItemScriptValue(const ExportedItem *item, ScriptEngine *engine) { QScriptValue itemScriptValue = engine->newObject(); itemScriptValue.setProperty(StringConstants::nameProperty(), item->name); setupExportedPropertiesScriptValue(itemScriptValue, item->properties, engine); QScriptValue childrenScriptValue = engine->newArray(static_cast(item->children.size())); itemScriptValue.setProperty(childItemsProperty(), childrenScriptValue); quint32 arrayIndex = 0; for (const auto &childItem : item->children) { childrenScriptValue.setProperty(arrayIndex++, setupExportedItemScriptValue(childItem.get(), engine)); } return itemScriptValue; } static QScriptValue setupExportsScriptValue(const ExportedModule &module, ScriptEngine *engine) { QScriptValue exportsScriptValue = engine->newObject(); for (auto it = module.propertyValues.cbegin(); it != module.propertyValues.cend(); ++it) exportsScriptValue.setProperty(it.key(), engine->toScriptValue(it.value())); setupExportedPropertiesScriptValue(exportsScriptValue, module.m_properties, engine); QScriptValue childrenScriptValue = engine->newArray(static_cast(module.children.size())); exportsScriptValue.setProperty(childItemsProperty(), childrenScriptValue); quint32 arrayIndex = 0; for (const auto &exportedItem : module.children) { childrenScriptValue.setProperty(arrayIndex++, setupExportedItemScriptValue(exportedItem.get(), engine)); } QScriptValue importsScriptValue = engine->newArray(module.importStatements.size()); exportsScriptValue.setProperty(StringConstants::importsProperty(), importsScriptValue); arrayIndex = 0; for (const QString &importStatement : module.importStatements) importsScriptValue.setProperty(arrayIndex++, importStatement); for (auto it = module.modulePropertyValues.cbegin(); it != module.modulePropertyValues.cend(); ++it) { const QVariantMap entries = it.value().toMap(); if (entries.empty()) continue; QScriptValue moduleObject = engine->newObject(); ModuleProperties::setModuleScriptValue(exportsScriptValue, moduleObject, it.key()); for (auto valIt = entries.begin(); valIt != entries.end(); ++valIt) moduleObject.setProperty(valIt.key(), engine->toScriptValue(valIt.value())); } return exportsScriptValue; } static QScriptValue setupProductScriptValue(ScriptEngine *engine, const ResolvedProduct *product) { QScriptValue &productScriptValue = engine->productScriptValuePrototype(product); if (productScriptValue.isValid()) return productScriptValue; productScriptValue = engine->newObject(); ModuleProperties::init(productScriptValue, product); QScriptValue artifactsFunc = engine->newFunction(&artifactsScriptValueForProduct, product); productScriptValue.setProperty(StringConstants::artifactsProperty(), artifactsFunc, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::PropertyGetter); QScriptValue exportsScriptValue = setupExportsScriptValue(product->exportedModule, engine); DependenciesFunction(engine).init(productScriptValue, exportsScriptValue, product); engine->setObservedProperty(productScriptValue, exportsProperty(), exportsScriptValue); engine->observer()->addExportsObjectId(exportsScriptValue.objectId(), product); return productScriptValue; } void setupScriptEngineForFile(ScriptEngine *engine, const FileContextBaseConstPtr &fileContext, QScriptValue targetObject, const ObserveMode &observeMode) { engine->import(fileContext, targetObject, observeMode); JsExtensions::setupExtensions(fileContext->jsExtensions(), targetObject); } void setupScriptEngineForProduct(ScriptEngine *engine, ResolvedProduct *product, const ResolvedModule *module, QScriptValue targetObject, bool setBuildEnvironment) { QScriptValue projectScriptValue = setupProjectScriptValue(engine, product->project.lock()); targetObject.setProperty(StringConstants::projectVar(), projectScriptValue); if (setBuildEnvironment) { QVariant v; v.setValue(&product->buildEnvironment); engine->setProperty(StringConstants::qbsProcEnvVarInternal(), v); } QScriptClass *scriptClass = engine->productPropertyScriptClass(); if (!scriptClass) { scriptClass = new ProductPropertyScriptClass(engine); engine->setProductPropertyScriptClass(scriptClass); } QScriptValue productScriptValue = engine->newObject(scriptClass); productScriptValue.setPrototype(setupProductScriptValue(engine, product)); targetObject.setProperty(StringConstants::productVar(), productScriptValue); QScriptValue data = getDataForProductScriptValue(engine, product); // If the Rule is in a Module, set up the 'moduleName' property if (!module->name.isEmpty()) data.setProperty(ModuleNameKey, module->name); productScriptValue.setData(data); } bool findPath(BuildGraphNode *u, BuildGraphNode *v, QList &path) { if (u == v) { path.push_back(v); return true; } for (BuildGraphNode * const childNode : qAsConst(u->children)) { if (findPath(childNode, v, path)) { path.prepend(u); return true; } } return false; } /* * Creates the build graph edge p -> c, which represents the dependency "c must be built before p". */ void connect(BuildGraphNode *p, BuildGraphNode *c) { QBS_CHECK(p != c); qCDebug(lcBuildGraph).noquote() << "connect" << p->toString() << "->" << c->toString(); if (c->type() == BuildGraphNode::ArtifactNodeType) { auto const ac = static_cast(c); for (const Artifact *child : filterByType(p->children)) { if (child == ac) return; const bool filePathsMustBeDifferent = child->artifactType == Artifact::Generated || child->product == ac->product || child->artifactType != ac->artifactType; if (filePathsMustBeDifferent && child->filePath() == ac->filePath()) { throw ErrorInfo(QStringLiteral("%1 already has a child artifact %2 as " "different object.").arg(p->toString(), ac->filePath()), CodeLocation(), true); } } } p->children.insert(c); c->parents.insert(p); p->product->topLevelProject()->buildData->setDirty(); } static bool existsPath_impl(BuildGraphNode *u, BuildGraphNode *v, NodeSet *seen) { if (u == v) return true; if (!seen->insert(u).second) return false; for (BuildGraphNode * const childNode : qAsConst(u->children)) { if (existsPath_impl(childNode, v, seen)) return true; } return false; } static bool existsPath(BuildGraphNode *u, BuildGraphNode *v) { NodeSet seen; return existsPath_impl(u, v, &seen); } static QStringList toStringList(const QList &path) { QStringList lst; for (BuildGraphNode *node : path) lst << node->toString(); return lst; } bool safeConnect(Artifact *u, Artifact *v) { QBS_CHECK(u != v); qCDebug(lcBuildGraph) << "safeConnect:" << relativeArtifactFileName(u) << "->" << relativeArtifactFileName(v); if (existsPath(v, u)) { QList circle; findPath(v, u, circle); qCDebug(lcBuildGraph) << "safeConnect: circle detected " << toStringList(circle); return false; } connect(u, v); return true; } void disconnect(BuildGraphNode *u, BuildGraphNode *v) { qCDebug(lcBuildGraph).noquote() << "disconnect:" << u->toString() << v->toString(); u->children.remove(v); v->parents.remove(u); u->onChildDisconnected(v); } void removeGeneratedArtifactFromDisk(Artifact *artifact, const Logger &logger) { if (artifact->artifactType != Artifact::Generated) return; removeGeneratedArtifactFromDisk(artifact->filePath(), logger); } void removeGeneratedArtifactFromDisk(const QString &filePath, const Logger &logger) { QFile file(filePath); if (!file.exists()) return; logger.qbsDebug() << "removing " << filePath; if (!file.remove()) logger.qbsWarning() << QStringLiteral("Cannot remove '%1'.").arg(filePath); } QString relativeArtifactFileName(const Artifact *artifact) { const QString &buildDir = artifact->product->topLevelProject()->buildDirectory; QString str = artifact->filePath(); if (str.startsWith(buildDir)) str.remove(0, buildDir.size()); if (str.startsWith(QLatin1Char('/'))) str.remove(0, 1); return str; } Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const ProjectBuildData *projectBuildData, const QString &dirPath, const QString &fileName, bool compareByName) { const QList lookupResults = projectBuildData->lookupFiles(dirPath, fileName); for (QList::const_iterator it = lookupResults.constBegin(); it != lookupResults.constEnd(); ++it) { if ((*it)->fileType() != FileResourceBase::FileTypeArtifact) continue; auto artifact = static_cast(*it); if (compareByName ? artifact->product->uniqueName() == product->uniqueName() : artifact->product == product) { return artifact; } } return nullptr; } Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const QString &dirPath, const QString &fileName, bool compareByName) { return lookupArtifact(product, product->topLevelProject()->buildData.get(), dirPath, fileName, compareByName); } Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const QString &filePath, bool compareByName) { QString dirPath, fileName; FileInfo::splitIntoDirectoryAndFileName(filePath, &dirPath, &fileName); return lookupArtifact(product, dirPath, fileName, compareByName); } Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const ProjectBuildData *buildData, const QString &filePath, bool compareByName) { QString dirPath, fileName; FileInfo::splitIntoDirectoryAndFileName(filePath, &dirPath, &fileName); return lookupArtifact(product, buildData, dirPath, fileName, compareByName); } Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const Artifact *artifact, bool compareByName) { return lookupArtifact(product, artifact->dirPath(), artifact->fileName(), compareByName); } Artifact *createArtifact(const ResolvedProductPtr &product, const SourceArtifactConstPtr &sourceArtifact) { const auto artifact = new Artifact; artifact->artifactType = Artifact::SourceFile; setArtifactData(artifact, sourceArtifact); insertArtifact(product, artifact); return artifact; } void setArtifactData(Artifact *artifact, const SourceArtifactConstPtr &sourceArtifact) { artifact->targetOfModule = sourceArtifact->targetOfModule; artifact->setFilePath(sourceArtifact->absoluteFilePath); artifact->setFileTags(sourceArtifact->fileTags); artifact->properties = sourceArtifact->properties; } void updateArtifactFromSourceArtifact(const ResolvedProductPtr &product, const SourceArtifactConstPtr &sourceArtifact) { Artifact * const artifact = lookupArtifact(product, sourceArtifact->absoluteFilePath, false); QBS_CHECK(artifact); const FileTags oldFileTags = artifact->fileTags(); const QVariantMap oldModuleProperties = artifact->properties->value(); setArtifactData(artifact, sourceArtifact); if (oldFileTags != artifact->fileTags() || oldModuleProperties != artifact->properties->value()) { invalidateArtifactAsRuleInputIfNecessary(artifact); } } void insertArtifact(const ResolvedProductPtr &product, Artifact *artifact) { qCDebug(lcBuildGraph) << "insert artifact" << artifact->filePath(); QBS_CHECK(!artifact->product); QBS_CHECK(!artifact->filePath().isEmpty()); artifact->product = product; product->topLevelProject()->buildData->insertIntoLookupTable(artifact); product->buildData->addArtifact(artifact); } void provideFullFileTagsAndProperties(Artifact *artifact) { artifact->properties = artifact->product->moduleProperties; FileTags allTags = artifact->pureFileTags.empty() ? artifact->product->fileTagsForFileName(artifact->fileName()) : artifact->pureFileTags; for (const ArtifactPropertiesConstPtr &props : artifact->product->artifactProperties) { if (allTags.intersects(props->fileTagsFilter())) { artifact->properties = props->propertyMap(); allTags += props->extraFileTags(); break; } } artifact->setFileTags(allTags); // Let a positive value of qbs.install imply the file tag "installable". if (artifact->properties->qbsPropertyValue(StringConstants::installProperty()).toBool()) artifact->addFileTag("installable"); } void applyPerArtifactProperties(Artifact *artifact) { if (artifact->pureProperties.empty()) return; QVariantMap props = artifact->properties->value(); for (const auto &property : artifact->pureProperties) setConfigProperty(props, property.first, property.second); artifact->properties = artifact->properties->clone(); artifact->properties->setValue(props); } void updateGeneratedArtifacts(ResolvedProduct *product) { if (!product->buildData) return; for (Artifact * const artifact : filterByType(product->buildData->allNodes())) { if (artifact->artifactType == Artifact::Generated) { const FileTags oldFileTags = artifact->fileTags(); const QVariantMap oldModuleProperties = artifact->properties->value(); provideFullFileTagsAndProperties(artifact); applyPerArtifactProperties(artifact); if (oldFileTags != artifact->fileTags() || oldModuleProperties != artifact->properties->value()) { invalidateArtifactAsRuleInputIfNecessary(artifact); } } } } // This is needed for artifacts which are inputs to rules whose outputArtifacts script // returned an empty array for this input. Since there is no transformer, our usual change // tracking procedure will not notice if the artifact's file tags or module properties have // changed, so we need to force a re-run of the outputArtifacts script. void invalidateArtifactAsRuleInputIfNecessary(Artifact *artifact) { for (RuleNode * const parentRuleNode : filterByType(artifact->parents)) { if (!parentRuleNode->rule()->isDynamic()) continue; bool artifactNeedsExplicitInvalidation = true; for (Artifact * const output : filterByType(parentRuleNode->parents)) { if (output->children.contains(artifact) && !output->childrenAddedByScanner.contains(artifact)) { artifactNeedsExplicitInvalidation = false; break; } } if (artifactNeedsExplicitInvalidation) parentRuleNode->removeOldInputArtifact(artifact); } } static void doSanityChecksForProduct(const ResolvedProductConstPtr &product, const Set &allProducts, const Logger &logger) { qCDebug(lcBuildGraph) << "Sanity checking product" << product->uniqueName(); CycleDetector cycleDetector(logger); cycleDetector.visitProduct(product); const ProductBuildData * const buildData = product->buildData.get(); for (const ResolvedModuleConstPtr &m : product->modules) QBS_CHECK(m->product == product.get()); qCDebug(lcBuildGraph) << "enabled:" << product->enabled << "build data:" << buildData; if (product->enabled) QBS_CHECK(buildData); if (!product->buildData) return; for (BuildGraphNode * const node : qAsConst(buildData->rootNodes())) { qCDebug(lcBuildGraph).noquote() << "Checking root node" << node->toString(); QBS_CHECK(buildData->allNodes().contains(node)); } Set filePaths; for (BuildGraphNode * const node : qAsConst(buildData->allNodes())) { qCDebug(lcBuildGraph).noquote() << "Sanity checking node" << node->toString(); QBS_CHECK(node->product == product); for (const BuildGraphNode * const parent : qAsConst(node->parents)) QBS_CHECK(parent->children.contains(node)); for (BuildGraphNode * const child : qAsConst(node->children)) { QBS_CHECK(child->parents.contains(node)); QBS_CHECK(!child->product.expired()); QBS_CHECK(child->product->buildData); QBS_CHECK(child->product->buildData->allNodes().contains(child)); QBS_CHECK(allProducts.contains(child->product.lock())); } Artifact * const artifact = node->type() == BuildGraphNode::ArtifactNodeType ? static_cast(node) : nullptr; if (!artifact) { QBS_CHECK(node->type() == BuildGraphNode::RuleNodeType); auto const ruleNode = static_cast(node); QBS_CHECK(ruleNode->rule()); QBS_CHECK(ruleNode->rule()->product); QBS_CHECK(ruleNode->rule()->product == ruleNode->product.get()); QBS_CHECK(ruleNode->rule()->product == product.get()); QBS_CHECK(contains(product->rules, std::const_pointer_cast(ruleNode->rule()))); continue; } QBS_CHECK(product->topLevelProject()->buildData->fileDependencies.contains( artifact->fileDependencies)); QBS_CHECK(artifact->artifactType == Artifact::SourceFile || !filePaths.contains(artifact->filePath())); filePaths << artifact->filePath(); for (Artifact * const child : qAsConst(artifact->childrenAddedByScanner)) QBS_CHECK(artifact->children.contains(child)); const TransformerConstPtr transformer = artifact->transformer; if (artifact->artifactType == Artifact::SourceFile) continue; const auto parentRuleNodes = filterByType(artifact->children); QBS_CHECK(std::distance(parentRuleNodes.begin(), parentRuleNodes.end()) == 1); QBS_CHECK(transformer); QBS_CHECK(transformer->rule); QBS_CHECK(transformer->rule->product); QBS_CHECK(transformer->rule->product == artifact->product.get()); QBS_CHECK(transformer->rule->product == product.get()); QBS_CHECK(transformer->outputs.contains(artifact)); QBS_CHECK(contains(product->rules, std::const_pointer_cast(transformer->rule))); qCDebug(lcBuildGraph) << "The transformer has" << transformer->outputs.size() << "outputs."; ArtifactSet transformerOutputChildren; for (const Artifact * const output : qAsConst(transformer->outputs)) { QBS_CHECK(output->transformer == transformer); transformerOutputChildren.unite(ArtifactSet::filtered(output->children)); for (const Artifact *a : filterByType(output->children)) { for (const Artifact *other : filterByType(output->children)) { if (other != a && other->filePath() == a->filePath() && (other->artifactType != Artifact::SourceFile || a->artifactType != Artifact::SourceFile || other->product == a->product)) { throw ErrorInfo(QStringLiteral("There is more than one artifact for " "file '%1' in the child list for output '%2'.") .arg(a->filePath(), output->filePath()), CodeLocation(), true); } } } } if (lcBuildGraph().isDebugEnabled()) { qCDebug(lcBuildGraph) << "The transformer output children are:"; for (const Artifact * const a : qAsConst(transformerOutputChildren)) qCDebug(lcBuildGraph) << "\t" << a->fileName(); qCDebug(lcBuildGraph) << "The transformer inputs are:"; for (const Artifact * const a : qAsConst(transformer->inputs)) qCDebug(lcBuildGraph) << "\t" << a->fileName(); } QBS_CHECK(transformer->inputs.size() <= transformerOutputChildren.size()); for (Artifact * const transformerInput : qAsConst(transformer->inputs)) QBS_CHECK(transformerOutputChildren.contains(transformerInput)); transformer->artifactsMapRequestedInPrepareScript.doSanityChecks(); transformer->artifactsMapRequestedInCommands.doSanityChecks(); } } static void doSanityChecks(const ResolvedProjectPtr &project, const Set &allProducts, Set &productNames, const Logger &logger) { logger.qbsDebug() << "Sanity checking project '" << project->name << "'"; for (const ResolvedProjectPtr &subProject : qAsConst(project->subProjects)) doSanityChecks(subProject, allProducts, productNames, logger); for (const ResolvedProductConstPtr &product : project->products) { QBS_CHECK(product->project == project); QBS_CHECK(product->topLevelProject() == project->topLevelProject()); doSanityChecksForProduct(product, allProducts, logger); QBS_CHECK(!productNames.contains(product->uniqueName())); productNames << product->uniqueName(); } } void doSanityChecks(const ResolvedProjectPtr &project, const Logger &logger) { if (qEnvironmentVariableIsEmpty("QBS_SANITY_CHECKS")) return; Set productNames; const Set allProducts = Set::fromStdVector(project->allProducts()); doSanityChecks(project, allProducts, productNames, logger); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/buildgraph.h000066400000000000000000000114461347155106100225470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BUILDGRAPH_H #define QBS_BUILDGRAPH_H #include "forward_decls.h" #include #include #include #include namespace qbs { namespace Internal { class BuildGraphNode; class Logger; class ScriptEngine; class PrepareScriptObserver; Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const ProjectBuildData *projectBuildData, const QString &dirPath, const QString &fileName, bool compareByName = false); Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const QString &dirPath, const QString &fileName, bool compareByName = false); Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const ProjectBuildData *buildData, const QString &filePath, bool compareByName = false); Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const QString &filePath, bool compareByName = false); Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const Artifact *artifact, bool compareByName); Artifact *createArtifact(const ResolvedProductPtr &product, const SourceArtifactConstPtr &sourceArtifact); void setArtifactData(Artifact *artifact, const SourceArtifactConstPtr &sourceArtifact); void updateArtifactFromSourceArtifact(const ResolvedProductPtr &product, const SourceArtifactConstPtr &sourceArtifact); void insertArtifact(const ResolvedProductPtr &product, Artifact *artifact); void dumpProductBuildData(const ResolvedProductConstPtr &product); void provideFullFileTagsAndProperties(Artifact *artifact); void applyPerArtifactProperties(Artifact *artifact); void updateGeneratedArtifacts(ResolvedProduct *product); void invalidateArtifactAsRuleInputIfNecessary(Artifact *artifact); bool findPath(BuildGraphNode *u, BuildGraphNode *v, QList &path); void QBS_AUTOTEST_EXPORT connect(BuildGraphNode *p, BuildGraphNode *c); bool safeConnect(Artifact *u, Artifact *v); void removeGeneratedArtifactFromDisk(Artifact *artifact, const Logger &logger); void removeGeneratedArtifactFromDisk(const QString &filePath, const Logger &logger); void disconnect(BuildGraphNode *u, BuildGraphNode *v); void setupScriptEngineForFile(ScriptEngine *engine, const FileContextBaseConstPtr &fileContext, QScriptValue targetObject, const ObserveMode &observeMode); void setupScriptEngineForProduct(ScriptEngine *engine, ResolvedProduct *product, const ResolvedModule *module, QScriptValue targetObject, bool setBuildEnvironment); QString relativeArtifactFileName(const Artifact *artifact); // Debugging helpers void doSanityChecks(const ResolvedProjectPtr &project, const Logger &logger); } // namespace Internal } // namespace qbs #endif // QBS_BUILDGRAPH_H qbs-src-1.13.1/src/lib/corelib/buildgraph/buildgraph.pri000066400000000000000000000052701347155106100231100ustar00rootroot00000000000000include(../../../install_prefix.pri) SOURCES += \ $$PWD/abstractcommandexecutor.cpp \ $$PWD/artifact.cpp \ $$PWD/artifactcleaner.cpp \ $$PWD/artifactsscriptvalue.cpp \ $$PWD/artifactvisitor.cpp \ $$PWD/buildgraph.cpp \ $$PWD/buildgraphloader.cpp \ $$PWD/buildgraphnode.cpp \ $$PWD/cycledetector.cpp \ $$PWD/dependencyparametersscriptvalue.cpp \ $$PWD/depscanner.cpp \ $$PWD/emptydirectoriesremover.cpp \ $$PWD/environmentscriptrunner.cpp \ $$PWD/executor.cpp \ $$PWD/executorjob.cpp \ $$PWD/filedependency.cpp \ $$PWD/inputartifactscanner.cpp \ $$PWD/jscommandexecutor.cpp \ $$PWD/nodeset.cpp \ $$PWD/nodetreedumper.cpp \ $$PWD/processcommandexecutor.cpp \ $$PWD/productbuilddata.cpp \ $$PWD/productinstaller.cpp \ $$PWD/projectbuilddata.cpp \ $$PWD/qtmocscanner.cpp \ $$PWD/rawscanneddependency.cpp \ $$PWD/rawscanresults.cpp \ $$PWD/requestedartifacts.cpp \ $$PWD/requesteddependencies.cpp \ $$PWD/rulecommands.cpp \ $$PWD/rulegraph.cpp \ $$PWD/rulenode.cpp \ $$PWD/rulesapplicator.cpp \ $$PWD/rulesevaluationcontext.cpp \ $$PWD/timestampsupdater.cpp \ $$PWD/transformerchangetracking.cpp \ $$PWD/transformer.cpp HEADERS += \ $$PWD/abstractcommandexecutor.h \ $$PWD/artifact.h \ $$PWD/artifactcleaner.h \ $$PWD/artifactsscriptvalue.h \ $$PWD/artifactvisitor.h \ $$PWD/buildgraph.h \ $$PWD/buildgraphloader.h \ $$PWD/buildgraphnode.h \ $$PWD/buildgraphvisitor.h \ $$PWD/cycledetector.h \ $$PWD/dependencyparametersscriptvalue.h \ $$PWD/depscanner.h \ $$PWD/emptydirectoriesremover.h \ $$PWD/environmentscriptrunner.h \ $$PWD/executor.h \ $$PWD/executorjob.h \ $$PWD/filedependency.h \ $$PWD/forward_decls.h \ $$PWD/inputartifactscanner.h \ $$PWD/jscommandexecutor.h \ $$PWD/nodeset.h \ $$PWD/nodetreedumper.h \ $$PWD/processcommandexecutor.h \ $$PWD/productbuilddata.h \ $$PWD/productinstaller.h \ $$PWD/projectbuilddata.h \ $$PWD/qtmocscanner.h \ $$PWD/rawscanneddependency.h \ $$PWD/rawscanresults.h \ $$PWD/requestedartifacts.h \ $$PWD/requesteddependencies.h \ $$PWD/rescuableartifactdata.h \ $$PWD/rulecommands.h \ $$PWD/rulegraph.h \ $$PWD/rulenode.h \ $$PWD/rulesapplicator.h \ $$PWD/rulesevaluationcontext.h \ $$PWD/scriptclasspropertyiterator.h \ $$PWD/timestampsupdater.h \ $$PWD/transformerchangetracking.h \ $$PWD/transformer.h !qbs_no_dev_install { buildgraph_headers.files = $$PWD/forward_decls.h buildgraph_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/buildgraph INSTALLS += buildgraph_headers } qbs-src-1.13.1/src/lib/corelib/buildgraph/buildgraphloader.cpp000066400000000000000000001265741347155106100243020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "buildgraphloader.h" #include "buildgraph.h" #include "cycledetector.h" #include "emptydirectoriesremover.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "rulenode.h" #include "rulecommands.h" #include "rulesevaluationcontext.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { BuildGraphLoader::BuildGraphLoader(const Logger &logger) : m_logger(logger) { } BuildGraphLoader::~BuildGraphLoader() { qDeleteAll(m_objectsToDelete); } static void restoreBackPointers(const ResolvedProjectPtr &project) { for (const ResolvedProductPtr &product : project->products) { product->project = project; if (!product->buildData) continue; for (BuildGraphNode * const n : qAsConst(product->buildData->allNodes())) { if (n->type() == BuildGraphNode::ArtifactNodeType) { project->topLevelProject()->buildData ->insertIntoLookupTable(static_cast(n)); } } } for (const ResolvedProjectPtr &subProject : qAsConst(project->subProjects)) { subProject->parentProject = project; restoreBackPointers(subProject); } } BuildGraphLoadResult BuildGraphLoader::load(const TopLevelProjectPtr &existingProject, const SetupProjectParameters ¶meters, const RulesEvaluationContextPtr &evalContext) { m_parameters = parameters; m_result = BuildGraphLoadResult(); m_evalContext = evalContext; if (existingProject) { QBS_CHECK(existingProject->buildData); existingProject->buildData->evaluationContext = evalContext; if (!checkBuildGraphCompatibility(existingProject)) return m_result; m_result.loadedProject = existingProject; } else { loadBuildGraphFromDisk(); } if (!m_result.loadedProject) return m_result; if (parameters.restoreBehavior() == SetupProjectParameters::RestoreOnly) { for (const ErrorInfo &e : qAsConst(m_result.loadedProject->warningsEncountered)) m_logger.printWarning(e); return m_result; } QBS_CHECK(parameters.restoreBehavior() == SetupProjectParameters::RestoreAndTrackChanges); if (m_parameters.logElapsedTime()) { m_wildcardExpansionEffort = 0; m_propertyComparisonEffort = 0; } trackProjectChanges(); if (m_parameters.logElapsedTime()) { m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Wildcard expansion took %1.") .arg(elapsedTimeString(m_wildcardExpansionEffort)); m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Comparing property values took %1.") .arg(elapsedTimeString(m_propertyComparisonEffort)); } return m_result; } TopLevelProjectConstPtr BuildGraphLoader::loadProject(const QString &bgFilePath) { class LogSink : public ILogSink { void doPrintMessage(LoggerLevel, const QString &, const QString &) override { } } dummySink; Logger dummyLogger(&dummySink); BuildGraphLocker bgLocker(bgFilePath, dummyLogger, false, nullptr); PersistentPool pool(dummyLogger); pool.load(bgFilePath); const TopLevelProjectPtr project = TopLevelProject::create(); project->load(pool); project->setBuildConfiguration(pool.headData().projectConfig); return project; } void BuildGraphLoader::loadBuildGraphFromDisk() { const QString projectId = TopLevelProject::deriveId(m_parameters.finalBuildConfigurationTree()); const QString buildDir = TopLevelProject::deriveBuildDirectory(m_parameters.buildRoot(), projectId); const QString buildGraphFilePath = ProjectBuildData::deriveBuildGraphFilePath(buildDir, projectId); PersistentPool pool(m_logger); qCDebug(lcBuildGraph) << "trying to load:" << buildGraphFilePath; try { pool.load(buildGraphFilePath); } catch (const NoBuildGraphError &) { if (m_parameters.restoreBehavior() == SetupProjectParameters::RestoreOnly) throw; m_logger.qbsInfo() << Tr::tr("Build graph does not yet exist for configuration '%1'. " "Starting from scratch.").arg(m_parameters.configurationName()); return; } catch (const ErrorInfo &loadError) { if (!m_parameters.overrideBuildGraphData()) { ErrorInfo fullError = loadError; fullError.append(Tr::tr("Use the 'resolve' command to set up a new build graph.")); throw fullError; } m_logger.qbsWarning() << loadError.toString(); return; } const TopLevelProjectPtr project = TopLevelProject::create(); // TODO: Store some meta data that will enable us to show actual progress (e.g. number of products). m_evalContext->initializeObserver(Tr::tr("Restoring build graph from disk"), 1); project->load(pool); project->buildData->evaluationContext = m_evalContext; project->setBuildConfiguration(pool.headData().projectConfig); project->buildDirectory = buildDir; if (!checkBuildGraphCompatibility(project)) return; restoreBackPointers(project); project->buildData->setClean(); project->location = CodeLocation(m_parameters.projectFilePath(), project->location.line(), project->location.column()); m_result.loadedProject = project; m_evalContext->incrementProgressValue(); doSanityChecks(project, m_logger); } bool BuildGraphLoader::checkBuildGraphCompatibility(const TopLevelProjectConstPtr &project) { if (m_parameters.projectFilePath().isEmpty()) m_parameters.setProjectFilePath(project->location.filePath()); else Loader::setupProjectFilePath(m_parameters); if (QFileInfo(project->location.filePath()) == QFileInfo(m_parameters.projectFilePath())) return true; QString message = Tr::tr("Stored build graph at '%1' is for project file '%2', but " "input file is '%3'.") .arg(QDir::toNativeSeparators(project->buildGraphFilePath()), QDir::toNativeSeparators(project->location.filePath()), QDir::toNativeSeparators(m_parameters.projectFilePath())); if (m_parameters.overrideBuildGraphData()) { m_logger.qbsInfo() << message; return false; } message.append(QLatin1Char('\n')).append(Tr::tr("Use the 'resolve' command to enforce " "using a different project file.")); throw ErrorInfo(message); } static bool checkProductForChangedDependency(std::vector &changedProducts, Set &seenProducts, const ResolvedProductPtr &product) { if (seenProducts.contains(product)) return false; if (contains(changedProducts, product)) return true; for (const ResolvedProductPtr &dep : qAsConst(product->dependencies)) { if (checkProductForChangedDependency(changedProducts, seenProducts, dep)) { changedProducts << product; return true; } } seenProducts << product; return false; } // All products depending on changed products also become changed. Otherwise the output // artifacts of the rules taking the artifacts from the dependency as inputs will be // rebuilt due to their rule getting re-applied (as the rescued input artifacts will show // up as newly added) and no rescue data being available. static void makeChangedProductsListComplete(std::vector &changedProducts, const std::vector &allRestoredProducts) { Set seenProducts; for (const ResolvedProductPtr &p : allRestoredProducts) checkProductForChangedDependency(changedProducts, seenProducts, p); } static void updateProductAndRulePointers(const ResolvedProductPtr &newProduct) { std::unordered_map ruleMap; for (BuildGraphNode *node : qAsConst(newProduct->buildData->allNodes())) { node->product = newProduct; const auto findNewRule = [&ruleMap, &newProduct] (const RuleConstPtr &oldRule) -> RuleConstPtr { const auto it = ruleMap.find(oldRule); if (it != ruleMap.cend()) return it->second; for (const RuleConstPtr &r : qAsConst(newProduct->rules)) { if (*r == *oldRule) { ruleMap.insert(std::make_pair(oldRule, r)); return r; } } QBS_CHECK(false); return {}; }; if (node->type() == BuildGraphNode::RuleNodeType) { const auto ruleNode = static_cast(node); ruleNode->setRule(findNewRule(ruleNode->rule())); } else { QBS_CHECK(node->type() == BuildGraphNode::ArtifactNodeType); const auto artifact = static_cast(node); if (artifact->artifactType == Artifact::Generated) { QBS_CHECK(artifact->transformer); artifact->transformer->rule = findNewRule(artifact->transformer->rule); } } } } void BuildGraphLoader::trackProjectChanges() { TimedActivityLogger trackingTimer(m_logger, Tr::tr("Change tracking"), m_parameters.logElapsedTime()); const TopLevelProjectPtr &restoredProject = m_result.loadedProject; Set buildSystemFiles = restoredProject->buildSystemFiles; std::vector allRestoredProducts = restoredProject->allProducts(); std::vector changedProducts; bool reResolvingNecessary = false; if (!checkConfigCompatibility()) reResolvingNecessary = true; if (hasProductFileChanged(allRestoredProducts, restoredProject->lastStartResolveTime, buildSystemFiles, changedProducts)) { reResolvingNecessary = true; } // "External" changes, e.g. in the environment or in a JavaScript file, // can make the list of source files in a product change without the respective file // having been touched. In such a case, the build data for that product will have to be set up // anew. if (probeExecutionForced(restoredProject, allRestoredProducts) || hasBuildSystemFileChanged(buildSystemFiles, restoredProject.get()) || hasEnvironmentChanged(restoredProject) || hasCanonicalFilePathResultChanged(restoredProject) || hasFileExistsResultChanged(restoredProject) || hasDirectoryEntriesResultChanged(restoredProject) || hasFileLastModifiedResultChanged(restoredProject)) { reResolvingNecessary = true; } if (!reResolvingNecessary) { for (const ErrorInfo &e : qAsConst(restoredProject->warningsEncountered)) m_logger.printWarning(e); return; } restoredProject->buildData->setDirty(); markTransformersForChangeTracking(allRestoredProducts); if (!m_parameters.overrideBuildGraphData()) m_parameters.setEnvironment(restoredProject->environment); Loader ldr(m_evalContext->engine(), m_logger); ldr.setSearchPaths(m_parameters.searchPaths()); ldr.setProgressObserver(m_evalContext->observer()); ldr.setOldProjectProbes(restoredProject->probes); if (!m_parameters.forceProbeExecution()) ldr.setStoredModuleProviderInfo(restoredProject->moduleProviderInfo); ldr.setLastResolveTime(restoredProject->lastStartResolveTime); QHash> restoredProbes; for (const auto &restoredProduct : qAsConst(allRestoredProducts)) restoredProbes.insert(restoredProduct->uniqueName(), restoredProduct->probes); ldr.setOldProductProbes(restoredProbes); if (!m_parameters.overrideBuildGraphData()) ldr.setStoredProfiles(restoredProject->profileConfigs); m_result.newlyResolvedProject = ldr.loadProject(m_parameters); std::vector allNewlyResolvedProducts = m_result.newlyResolvedProject->allProducts(); for (const ResolvedProductPtr &cp : qAsConst(allNewlyResolvedProducts)) m_freshProductsByName.insert(cp->uniqueName(), cp); checkAllProductsForChanges(allRestoredProducts, changedProducts); std::shared_ptr oldBuildData; ChildListHash childLists; if (!changedProducts.empty()) { oldBuildData = std::make_shared(restoredProject->buildData.get()); for (const ResolvedProductConstPtr &product : qAsConst(allRestoredProducts)) { if (!product->buildData) continue; // If the product gets temporarily removed, its artifacts will get disconnected // and this structural information will no longer be directly available from them. for (const Artifact *a : filterByType(product->buildData->allNodes())) { childLists.insert(a, ChildrenInfo(ArtifactSet::filtered(a->children), a->childrenAddedByScanner)); } } } makeChangedProductsListComplete(changedProducts, allRestoredProducts); // Set up build data from scratch for all changed products. This does not necessarily // mean that artifacts will have to get rebuilt; whether this is necesessary will be decided // an a per-artifact basis by the Executor on the next build. QHash rescuableArtifactData; for (const ResolvedProductPtr &product : qAsConst(changedProducts)) { const QString name = product->uniqueName(); m_changedSourcesByProduct.erase(name); m_productsWhoseArtifactsNeedUpdate.remove(name); ResolvedProductPtr freshProduct = m_freshProductsByName.value(name); if (!freshProduct) continue; onProductRemoved(product, product->topLevelProject()->buildData.get(), false); if (product->buildData) { rescuableArtifactData.insert(product->uniqueName(), product->buildData->rescuableArtifactData()); } removeOne(allRestoredProducts, product); } // Move over restored build data to newly resolved project. m_result.newlyResolvedProject->buildData.swap(restoredProject->buildData); QBS_CHECK(m_result.newlyResolvedProject->buildData); m_result.newlyResolvedProject->buildData->setDirty(); for (auto it = allNewlyResolvedProducts.begin(); it != allNewlyResolvedProducts.end();) { const ResolvedProductPtr &newlyResolvedProduct = *it; auto k = std::find_if(allRestoredProducts.begin(), allRestoredProducts.end(), [&newlyResolvedProduct](const ResolvedProductPtr &restoredProduct) { return newlyResolvedProduct->uniqueName() == restoredProduct->uniqueName(); }); if (k == allRestoredProducts.end()) { ++it; } else { const ResolvedProductPtr &restoredProduct = *k; if (newlyResolvedProduct->enabled) newlyResolvedProduct->buildData.swap(restoredProduct->buildData); if (newlyResolvedProduct->buildData) updateProductAndRulePointers(newlyResolvedProduct); // Keep in list if build data still needs to be resolved. if (!newlyResolvedProduct->enabled || newlyResolvedProduct->buildData) it = allNewlyResolvedProducts.erase(it); allRestoredProducts.erase(k); } } // Products still left in the list do not exist anymore. for (const ResolvedProductPtr &removedProduct : qAsConst(allRestoredProducts)) { removeOne(changedProducts, removedProduct); onProductRemoved(removedProduct, m_result.newlyResolvedProject->buildData.get()); } // Products still left in the list need resolving, either because they are new // or because they are newly enabled. if (!allNewlyResolvedProducts.empty()) { BuildDataResolver bpr(m_logger); bpr.resolveProductBuildDataForExistingProject(m_result.newlyResolvedProject, allNewlyResolvedProducts); } for (auto it = m_changedSourcesByProduct.cbegin(); it != m_changedSourcesByProduct.cend(); ++it) { const ResolvedProductPtr product = m_freshProductsByName.value(it->first); QBS_CHECK(!!product); for (const SourceArtifactConstPtr &sa : it->second) updateArtifactFromSourceArtifact(product, sa); } for (const QString &productName : m_productsWhoseArtifactsNeedUpdate) { const ResolvedProductPtr product = m_freshProductsByName.value(productName); QBS_CHECK(!!product); updateGeneratedArtifacts(product.get()); } for (const ResolvedProductConstPtr &changedProduct : qAsConst(changedProducts)) { rescueOldBuildData(changedProduct, m_freshProductsByName.value(changedProduct->uniqueName()), childLists, rescuableArtifactData.value(changedProduct->uniqueName())); } EmptyDirectoriesRemover(m_result.newlyResolvedProject.get(), m_logger) .removeEmptyParentDirectories(m_artifactsRemovedFromDisk); for (FileResourceBase * const f : qAsConst(m_objectsToDelete)) { if (f->fileType() == FileResourceBase::FileTypeArtifact) static_cast(f)->product.reset(); // To help with the sanity checks. } doSanityChecks(m_result.newlyResolvedProject, m_logger); } bool BuildGraphLoader::probeExecutionForced( const TopLevelProjectConstPtr &restoredProject, const std::vector &restoredProducts) const { if (!m_parameters.forceProbeExecution()) return false; if (!restoredProject->probes.empty()) return true; for (const auto &p : qAsConst(restoredProducts)) { if (!p->probes.empty()) return true; } return false; } bool BuildGraphLoader::hasEnvironmentChanged(const TopLevelProjectConstPtr &restoredProject) const { if (!m_parameters.overrideBuildGraphData()) return false; QProcessEnvironment oldEnv = restoredProject->environment; QProcessEnvironment newEnv = m_parameters.adjustedEnvironment(); static const QString ldPreloadEnvVar = QStringLiteral("LD_PRELOAD"); // HACK. Valgrind screws up our null-build benchmarker otherwise. // TODO: Think about a (module-provided) whitelist. oldEnv.remove(ldPreloadEnvVar); newEnv.remove(ldPreloadEnvVar); if (oldEnv != newEnv) { qCDebug(lcBuildGraph) << "Set of environment variables changed. Must re-resolve project." << "\nold:" << restoredProject->environment.toStringList() << "\nnew:" << m_parameters.adjustedEnvironment().toStringList(); return true; } return false; } bool BuildGraphLoader::hasCanonicalFilePathResultChanged(const TopLevelProjectConstPtr &restoredProject) const { for (auto it = restoredProject->canonicalFilePathResults.constBegin(); it != restoredProject->canonicalFilePathResults.constEnd(); ++it) { if (QFileInfo(it.key()).canonicalFilePath() != it.value()) { qCDebug(lcBuildGraph) << "Canonical file path for file" << it.key() << "changed, must re-resolve project."; return true; } } return false; } bool BuildGraphLoader::hasFileExistsResultChanged(const TopLevelProjectConstPtr &restoredProject) const { for (QHash::ConstIterator it = restoredProject->fileExistsResults.constBegin(); it != restoredProject->fileExistsResults.constEnd(); ++it) { if (FileInfo(it.key()).exists() != it.value()) { qCDebug(lcBuildGraph) << "Existence check for file" << it.key() << "changed, must re-resolve project."; return true; } } return false; } bool BuildGraphLoader::hasDirectoryEntriesResultChanged(const TopLevelProjectConstPtr &restoredProject) const { for (auto it = restoredProject->directoryEntriesResults.constBegin(); it != restoredProject->directoryEntriesResults.constEnd(); ++it) { if (QDir(it.key().first).entryList(static_cast(it.key().second), QDir::Name) != it.value()) { qCDebug(lcBuildGraph) << "Entry list for directory" << it.key().first << static_cast(it.key().second) << "changed, must re-resolve project."; return true; } } return false; } bool BuildGraphLoader::hasFileLastModifiedResultChanged(const TopLevelProjectConstPtr &restoredProject) const { for (QHash::ConstIterator it = restoredProject->fileLastModifiedResults.constBegin(); it != restoredProject->fileLastModifiedResults.constEnd(); ++it) { if (FileInfo(it.key()).lastModified() != it.value()) { qCDebug(lcBuildGraph) << "Timestamp for file" << it.key() << "changed, must re-resolve project."; return true; } } return false; } bool BuildGraphLoader::hasProductFileChanged(const std::vector &restoredProducts, const FileTime &referenceTime, Set &remainingBuildSystemFiles, std::vector &changedProducts) { bool hasChanged = false; for (const ResolvedProductPtr &product : restoredProducts) { const QString filePath = product->location.filePath(); const FileInfo pfi(filePath); remainingBuildSystemFiles.remove(filePath); if (!pfi.exists()) { qCDebug(lcBuildGraph) << "A product was removed, must re-resolve project"; hasChanged = true; } else if (referenceTime < pfi.lastModified()) { qCDebug(lcBuildGraph) << "A product was changed, must re-resolve project"; hasChanged = true; } else if (!contains(changedProducts, product)) { bool foundMissingSourceFile = false; for (const QString &file : qAsConst(product->missingSourceFiles)) { if (FileInfo(file).exists()) { qCDebug(lcBuildGraph) << "Formerly missing file" << file << "in product" << product->name << "exists now, must re-resolve project"; foundMissingSourceFile = true; break; } } if (foundMissingSourceFile) { hasChanged = true; changedProducts.push_back(product); continue; } AccumulatingTimer wildcardTimer(m_parameters.logElapsedTime() ? &m_wildcardExpansionEffort : nullptr); for (const GroupPtr &group : product->groups) { if (!group->wildcards) continue; const bool reExpansionRequired = std::any_of( group->wildcards->dirTimeStamps.cbegin(), group->wildcards->dirTimeStamps.cend(), [](const std::pair &pair) { return FileInfo(pair.first).lastModified() > pair.second; }); if (!reExpansionRequired) continue; const Set files = group->wildcards->expandPatterns(group, FileInfo::path(group->location.filePath()), product->topLevelProject()->buildDirectory); Set wcFiles; for (const SourceArtifactConstPtr &sourceArtifact : group->wildcards->files) wcFiles += sourceArtifact->absoluteFilePath; if (files == wcFiles) continue; hasChanged = true; changedProducts.push_back(product); break; } } } return hasChanged; } bool BuildGraphLoader::hasBuildSystemFileChanged(const Set &buildSystemFiles, const TopLevelProject *restoredProject) { for (const QString &file : buildSystemFiles) { const FileInfo fi(file); if (!fi.exists()) { qCDebug(lcBuildGraph) << "Project file" << file << "no longer exists, must re-resolve project."; return true; } const auto generatedChecker = [&file, restoredProject](const ModuleProviderInfo &mpi) { return file.startsWith(mpi.outputDirPath(restoredProject->buildDirectory)); }; const bool fileWasCreatedByModuleProvider = any_of(restoredProject->moduleProviderInfo, generatedChecker); const FileTime referenceTime = fileWasCreatedByModuleProvider ? restoredProject->lastEndResolveTime : restoredProject->lastStartResolveTime; if (referenceTime < fi.lastModified()) { qCDebug(lcBuildGraph) << "Project file" << file << "changed, must re-resolve project."; return true; } } return false; } void BuildGraphLoader::markTransformersForChangeTracking( const std::vector &restoredProducts) { for (const ResolvedProductPtr &product : restoredProducts) { if (!product->buildData) continue; for (Artifact * const artifact : filterByType(product->buildData->allNodes())) { if (artifact->transformer) { artifact->transformer->prepareScriptNeedsChangeTracking = true; artifact->transformer->commandsNeedChangeTracking = true; } } } } void BuildGraphLoader::checkAllProductsForChanges( const std::vector &restoredProducts, std::vector &changedProducts) { for (const ResolvedProductPtr &restoredProduct : restoredProducts) { const ResolvedProductPtr newlyResolvedProduct = m_freshProductsByName.value(restoredProduct->uniqueName()); if (!newlyResolvedProduct) continue; if (newlyResolvedProduct->enabled != restoredProduct->enabled) { qCDebug(lcBuildGraph) << "Condition of product" << restoredProduct->uniqueName() << "was changed, must set up build data from scratch"; if (!contains(changedProducts, restoredProduct)) changedProducts << restoredProduct; continue; } if (checkProductForChanges(restoredProduct, newlyResolvedProduct)) { qCDebug(lcBuildGraph) << "Product" << restoredProduct->uniqueName() << "was changed, must set up build data from scratch"; if (!contains(changedProducts, restoredProduct)) changedProducts << restoredProduct; continue; } if (checkProductForChangesInSourceFiles(restoredProduct, newlyResolvedProduct)) { qCDebug(lcBuildGraph) << "File list of product" << restoredProduct->uniqueName() << "was changed."; if (!contains(changedProducts, restoredProduct)) changedProducts << restoredProduct; } } } bool BuildGraphLoader::checkProductForChangesInSourceFiles( const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct) { std::vector oldFiles = restoredProduct->allEnabledFiles(); std::vector newFiles = newlyResolvedProduct->allEnabledFiles(); // TODO: Also handle added and removed files in a fine-grained manner. if (oldFiles.size() != newFiles.size()) return true; static const auto cmp = [](const SourceArtifactConstPtr &a1, const SourceArtifactConstPtr &a2) { return a1->absoluteFilePath < a2->absoluteFilePath; }; std::sort(oldFiles.begin(), oldFiles.end(), cmp); std::sort(newFiles.begin(), newFiles.end(), cmp); std::vector changedFiles; for (int i = 0; i < int(oldFiles.size()); ++i) { const SourceArtifactConstPtr &oldFile = oldFiles.at(i); const SourceArtifactConstPtr &newFile = newFiles.at(i); if (oldFile->absoluteFilePath != newFile->absoluteFilePath) return true; if (*oldFile != *newFile) { qCDebug(lcBuildGraph) << "source artifact" << oldFile->absoluteFilePath << "changed"; changedFiles.push_back(newFile); } } if (!changedFiles.empty()) { m_changedSourcesByProduct.insert(std::make_pair(restoredProduct->uniqueName(), changedFiles)); } return false; } static bool dependenciesAreEqual(const ResolvedProductConstPtr &p1, const ResolvedProductConstPtr &p2) { if (p1->dependencies.size() != p2->dependencies.size()) return false; Set names1; Set names2; for (const ResolvedProductConstPtr &dep : qAsConst(p1->dependencies)) names1 << dep->uniqueName(); for (const ResolvedProductConstPtr &dep : qAsConst(p2->dependencies)) names2 << dep->uniqueName(); return names1 == names2; } bool BuildGraphLoader::checkProductForChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct) { // This check must come first, as it can prevent build data rescuing as a side effect. // TODO: Similar special checks must be done for Environment.getEnv() and File.exists() in // commands (or possibly it could be reasonable to just forbid such "dynamic" constructs // within commands). if (checkForPropertyChanges(restoredProduct, newlyResolvedProduct)) return true; if (!ruleListsAreEqual(restoredProduct->rules, newlyResolvedProduct->rules)) return true; if (!dependenciesAreEqual(restoredProduct, newlyResolvedProduct)) return true; return false; } bool BuildGraphLoader::checkProductForInstallInfoChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct) { // These are not requested from rules at build time, but we still need to take // them into account. const QStringList specialProperties = QStringList() << StringConstants::installProperty() << StringConstants::installDirProperty() << StringConstants::installPrefixProperty() << StringConstants::installRootProperty(); for (const QString &key : specialProperties) { if (restoredProduct->moduleProperties->qbsPropertyValue(key) != newlyResolvedProduct->moduleProperties->qbsPropertyValue(key)) { qCDebug(lcBuildGraph).noquote().nospace() << "Product property 'qbs." << key << "' changed."; return true; } } return false; } bool BuildGraphLoader::checkForPropertyChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct) { AccumulatingTimer propertyComparisonTimer(m_parameters.logElapsedTime() ? &m_propertyComparisonEffort: nullptr); qCDebug(lcBuildGraph) << "Checking for changes in properties requested in prepare scripts for " "product" << restoredProduct->uniqueName(); if (!restoredProduct->buildData) return false; if (restoredProduct->fileTags != newlyResolvedProduct->fileTags) { qCDebug(lcBuildGraph) << "Product type changed from" << restoredProduct->fileTags << "to" << newlyResolvedProduct->fileTags; return true; } if (checkProductForInstallInfoChanges(restoredProduct, newlyResolvedProduct)) return true; if (!artifactPropertyListsAreEqual(restoredProduct->artifactProperties, newlyResolvedProduct->artifactProperties)) { qCDebug(lcBuildGraph) << "a fileTagFilter group changed for product" << restoredProduct->uniqueName(); m_productsWhoseArtifactsNeedUpdate << restoredProduct->uniqueName(); } if (restoredProduct->moduleProperties != newlyResolvedProduct->moduleProperties) { qCDebug(lcBuildGraph) << "module properties changed for product" << restoredProduct->uniqueName(); m_productsWhoseArtifactsNeedUpdate << restoredProduct->uniqueName(); } return false; } void BuildGraphLoader::onProductRemoved(const ResolvedProductPtr &product, ProjectBuildData *projectBuildData, bool removeArtifactsFromDisk) { qCDebug(lcBuildGraph) << "product" << product->uniqueName() << "removed."; removeOne(product->project->products, product); if (product->buildData) { for (BuildGraphNode * const node : qAsConst(product->buildData->allNodes())) { if (node->type() == BuildGraphNode::ArtifactNodeType) { const auto artifact = static_cast(node); projectBuildData->removeArtifact(artifact, m_logger, removeArtifactsFromDisk, false); if (removeArtifactsFromDisk && artifact->artifactType == Artifact::Generated) m_artifactsRemovedFromDisk << artifact->filePath(); } else { for (BuildGraphNode * const parent : qAsConst(node->parents)) parent->children.remove(node); node->parents.clear(); for (BuildGraphNode * const child : qAsConst(node->children)) child->parents.remove(node); node->children.clear(); } } } } void BuildGraphLoader::replaceFileDependencyWithArtifact(const ResolvedProductPtr &fileDepProduct, FileDependency *filedep, Artifact *artifact) { qCDebug(lcBuildGraph) << "replace file dependency" << filedep->filePath() << "with artifact of type" << toString(artifact->artifactType); for (const ResolvedProductPtr &product : fileDepProduct->topLevelProject()->allProducts()) { if (!product->buildData) continue; for (Artifact *artifactInProduct : filterByType(product->buildData->allNodes())) { if (artifactInProduct->fileDependencies.remove(filedep)) connect(artifactInProduct, artifact); } } fileDepProduct->topLevelProject()->buildData->fileDependencies.remove(filedep); fileDepProduct->topLevelProject()->buildData->removeFromLookupTable(filedep); m_objectsToDelete << filedep; } bool BuildGraphLoader::checkConfigCompatibility() { const TopLevelProjectConstPtr restoredProject = m_result.loadedProject; if (m_parameters.topLevelProfile().isEmpty()) m_parameters.setTopLevelProfile(restoredProject->profile()); if (!m_parameters.overrideBuildGraphData()) { if (!m_parameters.overriddenValues().empty() && m_parameters.overriddenValues() != restoredProject->overriddenValues) { throw ErrorInfo(Tr::tr("Property values set on the command line differ from the " "ones used for the previous build. Use the 'resolve' command if " "you really want to rebuild with the new properties.")); } m_parameters.setOverriddenValues(restoredProject->overriddenValues); if (m_parameters.topLevelProfile() != restoredProject->profile()) { throw ErrorInfo(Tr::tr("The current profile is '%1', but profile '%2' was used " "when last building for configuration '%3'. Use the " "'resolve' command if you really want to rebuild with a " "different profile.") .arg(m_parameters.topLevelProfile(), restoredProject->profile(), m_parameters.configurationName())); } m_parameters.setTopLevelProfile(restoredProject->profile()); m_parameters.expandBuildConfiguration(); } if (!m_parameters.overrideBuildGraphData()) return true; if (m_parameters.finalBuildConfigurationTree() != restoredProject->buildConfiguration()) return false; Settings settings(m_parameters.settingsDirectory()); for (QVariantMap::ConstIterator it = restoredProject->profileConfigs.constBegin(); it != restoredProject->profileConfigs.constEnd(); ++it) { const Profile profile(it.key(), &settings); const QVariantMap buildConfig = SetupProjectParameters::expandedBuildConfiguration( profile, m_parameters.configurationName()); const QVariantMap newConfig = SetupProjectParameters::finalBuildConfigurationTree( buildConfig, m_parameters.overriddenValues()); if (newConfig != it.value()) return false; } return true; } void BuildGraphLoader::rescueOldBuildData(const ResolvedProductConstPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct, const ChildListHash &childLists, const AllRescuableArtifactData &existingRad) { QBS_CHECK(newlyResolvedProduct); if (!restoredProduct->buildData) return; if (!newlyResolvedProduct->buildData) newlyResolvedProduct->buildData.reset(new ProductBuildData); qCDebug(lcBuildGraph) << "rescue data of product" << restoredProduct->uniqueName(); QBS_CHECK(newlyResolvedProduct->buildData); QBS_CHECK(newlyResolvedProduct->buildData->rescuableArtifactData().empty()); newlyResolvedProduct->buildData->setRescuableArtifactData(existingRad); // This is needed for artifacts created by rules, which happens later in the executor. for (Artifact * const oldArtifact : filterByType(restoredProduct->buildData->allNodes())) { if (!oldArtifact->transformer) continue; Artifact * const newArtifact = lookupArtifact(newlyResolvedProduct, oldArtifact, false); if (!newArtifact) { RescuableArtifactData rad; rad.timeStamp = oldArtifact->timestamp(); rad.knownOutOfDate = oldArtifact->transformer->markedForRerun; rad.fileTags = oldArtifact->fileTags(); rad.properties = oldArtifact->properties; rad.commands = oldArtifact->transformer->commands; rad.propertiesRequestedInPrepareScript = oldArtifact->transformer->propertiesRequestedInPrepareScript; rad.propertiesRequestedInCommands = oldArtifact->transformer->propertiesRequestedInCommands; rad.propertiesRequestedFromArtifactInPrepareScript = oldArtifact->transformer->propertiesRequestedFromArtifactInPrepareScript; rad.propertiesRequestedFromArtifactInCommands = oldArtifact->transformer->propertiesRequestedFromArtifactInCommands; rad.importedFilesUsedInPrepareScript = oldArtifact->transformer->importedFilesUsedInPrepareScript; rad.importedFilesUsedInCommands = oldArtifact->transformer->importedFilesUsedInCommands; rad.depsRequestedInPrepareScript = oldArtifact->transformer->depsRequestedInPrepareScript; rad.depsRequestedInCommands = oldArtifact->transformer->depsRequestedInCommands; rad.artifactsMapRequestedInPrepareScript = oldArtifact->transformer->artifactsMapRequestedInPrepareScript; rad.artifactsMapRequestedInCommands = oldArtifact->transformer->artifactsMapRequestedInCommands; rad.exportedModulesAccessedInPrepareScript = oldArtifact->transformer->exportedModulesAccessedInPrepareScript; rad.exportedModulesAccessedInCommands = oldArtifact->transformer->exportedModulesAccessedInCommands; rad.lastCommandExecutionTime = oldArtifact->transformer->lastCommandExecutionTime; rad.lastPrepareScriptExecutionTime = oldArtifact->transformer->lastPrepareScriptExecutionTime; const ChildrenInfo &childrenInfo = childLists.value(oldArtifact); for (Artifact * const child : qAsConst(childrenInfo.children)) { rad.children.emplace_back(child->product->name, child->product->multiplexConfigurationId, child->filePath(), childrenInfo.childrenAddedByScanner.contains(child)); std::transform(oldArtifact->fileDependencies.cbegin(), oldArtifact->fileDependencies.cend(), std::back_inserter(rad.fileDependencies), std::mem_fn(&FileDependency::filePath)); } newlyResolvedProduct->buildData->addRescuableArtifactData(oldArtifact->filePath(), rad); } } } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/buildgraphloader.h000066400000000000000000000156261347155106100237420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BUILDGRAPHLOADER_H #define QBS_BUILDGRAPHLOADER_H #include "forward_decls.h" #include "artifact.h" #include "rescuableartifactdata.h" #include #include #include #include #include #include namespace qbs { namespace Internal { class FileDependency; class FileResourceBase; class FileTime; class Property; class BuildGraphLoadResult { public: TopLevelProjectPtr newlyResolvedProject; TopLevelProjectPtr loadedProject; }; class BuildGraphLoader { public: BuildGraphLoader(const Logger &logger); ~BuildGraphLoader(); BuildGraphLoadResult load(const TopLevelProjectPtr &existingProject, const SetupProjectParameters ¶meters, const RulesEvaluationContextPtr &evalContext); static TopLevelProjectConstPtr loadProject(const QString &bgFilePath); private: void loadBuildGraphFromDisk(); bool checkBuildGraphCompatibility(const TopLevelProjectConstPtr &project); void trackProjectChanges(); bool probeExecutionForced(const TopLevelProjectConstPtr &restoredProject, const std::vector &restoredProducts) const; bool hasEnvironmentChanged(const TopLevelProjectConstPtr &restoredProject) const; bool hasCanonicalFilePathResultChanged(const TopLevelProjectConstPtr &restoredProject) const; bool hasFileExistsResultChanged(const TopLevelProjectConstPtr &restoredProject) const; bool hasDirectoryEntriesResultChanged(const TopLevelProjectConstPtr &restoredProject) const; bool hasFileLastModifiedResultChanged(const TopLevelProjectConstPtr &restoredProject) const; bool hasProductFileChanged(const std::vector &restoredProducts, const FileTime &referenceTime, Set &remainingBuildSystemFiles, std::vector &productsWithChangedFiles); bool hasBuildSystemFileChanged(const Set &buildSystemFiles, const TopLevelProject *restoredProject); void markTransformersForChangeTracking(const std::vector &restoredProducts); void checkAllProductsForChanges(const std::vector &restoredProducts, std::vector &changedProducts); bool checkProductForChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct); bool checkProductForChangesInSourceFiles(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct); bool checkProductForInstallInfoChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct); bool checkForPropertyChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct); QVariantMap propertyMapByKind(const ResolvedProductConstPtr &product, const Property &property); void onProductRemoved(const ResolvedProductPtr &product, ProjectBuildData *projectBuildData, bool removeArtifactsFromDisk = true); bool checkForPropertyChanges(const TransformerPtr &restoredTrafo, const ResolvedProductPtr &freshProduct); bool checkForPropertyChange(const Property &restoredProperty, const QVariantMap &newProperties); void replaceFileDependencyWithArtifact(const ResolvedProductPtr &fileDepProduct, FileDependency *filedep, Artifact *artifact); bool checkConfigCompatibility(); struct ChildrenInfo { ChildrenInfo() {} ChildrenInfo(const ArtifactSet &c1, const ArtifactSet &c2) : children(c1), childrenAddedByScanner(c2) {} ArtifactSet children; ArtifactSet childrenAddedByScanner; }; using ChildListHash = QHash; void rescueOldBuildData(const ResolvedProductConstPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct, const ChildListHash &childLists, const AllRescuableArtifactData &existingRad); QMap m_freshProductsByName; RulesEvaluationContextPtr m_evalContext; SetupProjectParameters m_parameters; BuildGraphLoadResult m_result; Logger m_logger; QStringList m_artifactsRemovedFromDisk; std::unordered_map> m_changedSourcesByProduct; Set m_productsWhoseArtifactsNeedUpdate; qint64 m_wildcardExpansionEffort; qint64 m_propertyComparisonEffort; // These must only be deleted at the end so we can still peek into the old look-up table. QList m_objectsToDelete; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/buildgraph/buildgraphnode.cpp000066400000000000000000000055501347155106100237470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "buildgraphnode.h" #include "buildgraphvisitor.h" #include "projectbuilddata.h" #include #include #include #include #include namespace qbs { namespace Internal { BuildGraphNode::BuildGraphNode() : buildState(Untouched) { } BuildGraphNode::~BuildGraphNode() { for (BuildGraphNode *p : qAsConst(parents)) p->children.remove(this); for (BuildGraphNode *c : qAsConst(children)) c->parents.remove(this); } void BuildGraphNode::onChildDisconnected(BuildGraphNode *child) { Q_UNUSED(child); } void BuildGraphNode::acceptChildren(BuildGraphVisitor *visitor) { for (BuildGraphNode *child : qAsConst(children)) child->accept(visitor); } void BuildGraphNode::load(PersistentPool &pool) { serializationOp(pool); } void BuildGraphNode::store(PersistentPool &pool) { serializationOp(pool); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/buildgraphnode.h000066400000000000000000000064351347155106100234170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BUILDGRAPHNODE_H #define QBS_BUILDGRAPHNODE_H #include "nodeset.h" #include #include #include namespace qbs { namespace Internal { class BuildGraphVisitor; class BuildGraphNode { friend NodeSet; public: virtual ~BuildGraphNode(); NodeSet parents; NodeSet children; WeakPointer product; enum BuildState { Untouched = 0, Buildable, Building, Built }; BuildState buildState; // Do not serialize. Will be refreshed for every build. enum Type { ArtifactNodeType, RuleNodeType }; virtual Type type() const = 0; virtual void accept(BuildGraphVisitor *visitor) = 0; virtual QString toString() const = 0; virtual void onChildDisconnected(BuildGraphNode *child); bool isBuilt() const { return buildState == Built; } virtual void load(PersistentPool &pool); virtual void store(PersistentPool &pool); protected: explicit BuildGraphNode(); void acceptChildren(BuildGraphVisitor *visitor); // Do not store parents to avoid recursion. // Parents must be updated after loading all nodes. template void serializationOp(PersistentPool &pool) { pool.serializationOp(children); } }; } // namespace Internal } // namespace qbs #endif // QBS_BUILDGRAPHNODE_H qbs-src-1.13.1/src/lib/corelib/buildgraph/buildgraphvisitor.h000066400000000000000000000046761347155106100241760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BUILDGRAPHVISITOR_H #define QBS_BUILDGRAPHVISITOR_H namespace qbs { namespace Internal { class Artifact; class RuleNode; /*! * \brief The BuildGraphVisitor class * * The return value of a visit method indicates whether the children of the current node * are to be visited next. */ class BuildGraphVisitor { public: virtual bool visit(Artifact *) { return true; } virtual void endVisit(Artifact *) { } virtual bool visit(RuleNode *) { return true; } virtual void endVisit(RuleNode *) { } }; } // namespace Internal } // namespace qbs #endif // QBS_BUILDGRAPHVISITOR_H qbs-src-1.13.1/src/lib/corelib/buildgraph/cycledetector.cpp000066400000000000000000000066371347155106100236200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "cycledetector.h" #include "artifact.h" #include "buildgraph.h" #include "projectbuilddata.h" #include "rulenode.h" #include #include #include #include namespace qbs { namespace Internal { CycleDetector::CycleDetector(const Logger &logger) : m_parent(nullptr), m_logger(logger) { } void CycleDetector::visitProject(const TopLevelProjectConstPtr &project) { project->accept(this); } void CycleDetector::visitProduct(const ResolvedProductConstPtr &product) { product->accept(this); } bool CycleDetector::visit(Artifact *artifact) { return visitNode(artifact); } bool CycleDetector::visit(RuleNode *ruleNode) { return visitNode(ruleNode); } bool CycleDetector::visitNode(BuildGraphNode *node) { if (Q_UNLIKELY(m_nodesInCurrentPath.contains(node))) { ErrorInfo error(Tr::tr("Cycle in build graph detected.")); for (const BuildGraphNode * const n : cycle(node)) error.append(n->toString()); throw error; } if (m_allNodes.contains(node)) return false; m_nodesInCurrentPath += node; m_parent = node; for (BuildGraphNode * const child : qAsConst(node->children)) child->accept(this); m_nodesInCurrentPath -= node; m_allNodes += node; return false; } QList CycleDetector::cycle(BuildGraphNode *doubleEntry) { QList path; findPath(doubleEntry, m_parent, path); path.push_back(doubleEntry); return path; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/cycledetector.h000066400000000000000000000053151347155106100232550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_CYCLEDETECTOR_H #define QBS_CYCLEDETECTOR_H #include "buildgraphvisitor.h" #include "nodeset.h" #include #include namespace qbs { namespace Internal { class BuildGraphNode; class QBS_AUTOTEST_EXPORT CycleDetector : private BuildGraphVisitor { public: CycleDetector(const Logger &logger); void visitProject(const TopLevelProjectConstPtr &project); void visitProduct(const ResolvedProductConstPtr &product); private: bool visit(Artifact *artifact) override; bool visit(RuleNode *ruleNode) override; bool visitNode(BuildGraphNode *node); QList cycle(BuildGraphNode *doubleEntry); NodeSet m_allNodes; NodeSet m_nodesInCurrentPath; BuildGraphNode *m_parent; Logger m_logger; }; } // namespace Internal } // namespace qbs #endif // QBS_CYCLEDETECTOR_H qbs-src-1.13.1/src/lib/corelib/buildgraph/dependencyparametersscriptvalue.cpp000066400000000000000000000071271347155106100274460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "dependencyparametersscriptvalue.h" #include #include #include #include namespace qbs { namespace Internal { static QScriptValue toScriptValue(ScriptEngine *engine, const QString &productName, const QVariantMap &v, const QString &depName, const QualifiedId &moduleName) { QScriptValue obj = engine->newObject(); bool objIdAddedToObserver = false; for (auto it = v.begin(); it != v.end(); ++it) { if (it.value().type() == QVariant::Map) { obj.setProperty(it.key(), toScriptValue(engine, productName, it.value().toMap(), depName, QualifiedId(moduleName) << it.key())); } else { if (!objIdAddedToObserver) { objIdAddedToObserver = true; engine->observer()->addParameterObjectId(obj.objectId(), productName, depName, moduleName); } engine->setObservedProperty(obj, it.key(), engine->toScriptValue(it.value())); } } return obj; } static QScriptValue toScriptValue(ScriptEngine *scriptEngine, const QString &productName, const QVariantMap &v, const QString &depName) { return toScriptValue(scriptEngine, productName, v, depName, {}); } QScriptValue dependencyParametersValue(const QString &productName, const QString &dependencyName, const QVariantMap ¶metersMap, ScriptEngine *engine) { return toScriptValue(engine, productName, parametersMap, dependencyName); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/dependencyparametersscriptvalue.h000066400000000000000000000044771347155106100271200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_DEPENDENCYPARAMETERSSCRIPTVALUE_H #define QBS_DEPENDENCYPARAMETERSSCRIPTVALUE_H #include #include namespace qbs { namespace Internal { class ScriptEngine; QScriptValue dependencyParametersValue(const QString &productName, const QString &dependencyName, const QVariantMap ¶metersMap, ScriptEngine *engine); } // namespace Internal } // namespace qbs #endif // include guard qbs-src-1.13.1/src/lib/corelib/buildgraph/depscanner.cpp000066400000000000000000000222661347155106100231050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "depscanner.h" #include "artifact.h" #include "projectbuilddata.h" #include "buildgraph.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { QString DependencyScanner::id() const { if (m_id.isEmpty()) m_id = createId(); return m_id; } static QStringList collectCppIncludePaths(const QVariantMap &modules) { QStringList result; const QVariantMap cpp = modules.value(StringConstants::cppModule()).toMap(); if (cpp.empty()) return result; result << cpp.value(QStringLiteral("includePaths")).toStringList(); const bool useSystemHeaders = cpp.value(QStringLiteral("treatSystemHeadersAsDependencies")).toBool(); if (useSystemHeaders) { result << cpp.value(QStringLiteral("systemIncludePaths")).toStringList() << cpp.value(QStringLiteral("distributionIncludePaths")).toStringList() << cpp.value(QStringLiteral("compilerIncludePaths")).toStringList(); } result.removeDuplicates(); return result; } PluginDependencyScanner::PluginDependencyScanner(ScannerPlugin *plugin) : m_plugin(plugin) { } QStringList PluginDependencyScanner::collectSearchPaths(Artifact *artifact) { if (m_plugin->flags & ScannerUsesCppIncludePaths) return collectCppIncludePaths(artifact->properties->value()); return {}; } QStringList PluginDependencyScanner::collectDependencies(Artifact *artifact, FileResourceBase *file, const char *fileTags) { Q_UNUSED(artifact); Set result; QString baseDirOfInFilePath = file->dirPath(); const QString &filepath = file->filePath(); void *scannerHandle = m_plugin->open(filepath.utf16(), fileTags, ScanForDependenciesFlag); if (!scannerHandle) return {}; forever { int flags = 0; int length = 0; const char *szOutFilePath = m_plugin->next(scannerHandle, &length, &flags); if (szOutFilePath == nullptr) break; QString outFilePath = QString::fromLocal8Bit(szOutFilePath, length); if (outFilePath.isEmpty()) continue; if (flags & SC_LOCAL_INCLUDE_FLAG) { QString localFilePath = FileInfo::resolvePath(baseDirOfInFilePath, outFilePath); if (FileInfo::exists(localFilePath)) outFilePath = localFilePath; } result += outFilePath; } m_plugin->close(scannerHandle); return result.toList(); } bool PluginDependencyScanner::recursive() const { return m_plugin->flags & ScannerRecursiveDependencies; } const void *PluginDependencyScanner::key() const { return m_plugin; } QString PluginDependencyScanner::createId() const { return QString::fromLatin1(m_plugin->name); } bool PluginDependencyScanner::areModulePropertiesCompatible(const PropertyMapConstPtr &m1, const PropertyMapConstPtr &m2) const { // This changes when our C++ scanner starts taking defines into account. Q_UNUSED(m1); Q_UNUSED(m2); return true; } UserDependencyScanner::UserDependencyScanner(const ResolvedScannerConstPtr &scanner, ScriptEngine *engine) : m_scanner(scanner), m_engine(engine), m_product(nullptr) { m_global = m_engine->newObject(); m_global.setPrototype(m_engine->globalObject()); setupScriptEngineForFile(m_engine, m_scanner->scanScript.fileContext(), m_global, ObserveMode::Disabled); // TODO: QBS-1092 } QStringList UserDependencyScanner::collectSearchPaths(Artifact *artifact) { return evaluate(artifact, nullptr, m_scanner->searchPathsScript); } QStringList UserDependencyScanner::collectDependencies(Artifact *artifact, FileResourceBase *file, const char *fileTags) { Q_UNUSED(fileTags); return evaluate(artifact, file, m_scanner->scanScript); } bool UserDependencyScanner::recursive() const { return m_scanner->recursive; } const void *UserDependencyScanner::key() const { return m_scanner.get(); } QString UserDependencyScanner::createId() const { return m_scanner->scanScript.sourceCode(); } bool UserDependencyScanner::areModulePropertiesCompatible(const PropertyMapConstPtr &m1, const PropertyMapConstPtr &m2) const { // TODO: This should probably be made more fine-grained. Perhaps the Scanner item // could declare the relevant properties, or we could figure them out automatically // somehow. return m1 == m2 || *m1 == *m2; } class ScriptEngineActiveFlagGuard { ScriptEngine *m_engine; public: ScriptEngineActiveFlagGuard(ScriptEngine *engine) : m_engine(engine) { m_engine->setActive(true); } ~ScriptEngineActiveFlagGuard() { m_engine->setActive(false); } }; QStringList UserDependencyScanner::evaluate(const Artifact *artifact, const FileResourceBase *fileToScan, const PrivateScriptFunction &script) { ScriptEngineActiveFlagGuard guard(m_engine); if (artifact->product.get() != m_product) { m_product = artifact->product.get(); setupScriptEngineForProduct(m_engine, artifact->product.get(), m_scanner->module.get(), m_global, true); } QScriptValueList args; args.reserve(fileToScan ? 4 : 3); args.push_back(m_global.property(StringConstants::projectVar())); args.push_back(m_global.property(StringConstants::productVar())); args.push_back(Transformer::translateFileConfig(m_engine, artifact, m_scanner->module->name)); if (fileToScan) args.push_back(fileToScan->filePath()); m_engine->setGlobalObject(m_global); QScriptValue &function = script.scriptFunction; if (!function.isValid() || function.engine() != m_engine) { function = m_engine->evaluate(script.sourceCode()); if (Q_UNLIKELY(!function.isFunction())) throw ErrorInfo(Tr::tr("Invalid scan script."), script.location()); } QScriptValue result = function.call(QScriptValue(), args); m_engine->setGlobalObject(m_global.prototype()); m_engine->clearRequestedProperties(); if (Q_UNLIKELY(m_engine->hasErrorOrException(result))) { QString msg = Tr::tr("evaluating scan script: ") + m_engine->lastErrorString(result); const CodeLocation loc = m_engine->lastErrorLocation(result, script.location()); m_engine->clearExceptions(); throw ErrorInfo(msg, loc); } QStringList list; if (result.isArray()) { const int count = result.property(StringConstants::lengthProperty()).toInt32(); list.reserve(count); for (qint32 i = 0; i < count; ++i) { QScriptValue item = result.property(i); if (item.isValid() && !item.isUndefined()) list.push_back(item.toString()); } } return list; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/depscanner.h000066400000000000000000000111551347155106100225450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_DEPENDENCY_SCANNER_H #define QBS_DEPENDENCY_SCANNER_H #include #include #include #include #include class ScannerPlugin; namespace qbs { namespace Internal { class Artifact; class FileResourceBase; class Logger; class ScriptEngine; class DependencyScanner { public: virtual ~DependencyScanner() {} QString id() const; virtual QStringList collectSearchPaths(Artifact *artifact) = 0; virtual QStringList collectDependencies(Artifact *artifact, FileResourceBase *file, const char *fileTags) = 0; virtual bool recursive() const = 0; virtual const void *key() const = 0; virtual bool areModulePropertiesCompatible(const PropertyMapConstPtr &m1, const PropertyMapConstPtr &m2) const = 0; virtual bool cacheIsPerFile() const = 0; private: virtual QString createId() const = 0; mutable QString m_id; }; class PluginDependencyScanner : public DependencyScanner { public: PluginDependencyScanner(ScannerPlugin *plugin); private: QStringList collectSearchPaths(Artifact *artifact) override; QStringList collectDependencies(Artifact *artifact, FileResourceBase *file, const char *fileTags) override; bool recursive() const override; const void *key() const override; QString createId() const override; bool areModulePropertiesCompatible(const PropertyMapConstPtr &m1, const PropertyMapConstPtr &m2) const override; bool cacheIsPerFile() const override { return false; } ScannerPlugin* m_plugin; }; class UserDependencyScanner : public DependencyScanner { public: UserDependencyScanner(const ResolvedScannerConstPtr &scanner, ScriptEngine *engine); private: QStringList collectSearchPaths(Artifact *artifact) override; QStringList collectDependencies(Artifact *artifact, FileResourceBase *file, const char *fileTags) override; bool recursive() const override; const void *key() const override; QString createId() const override; bool areModulePropertiesCompatible(const PropertyMapConstPtr &m1, const PropertyMapConstPtr &m2) const override; bool cacheIsPerFile() const override { return true; } QStringList evaluate(const Artifact *artifact, const FileResourceBase *fileToScan, const PrivateScriptFunction &script); ResolvedScannerConstPtr m_scanner; ScriptEngine *m_engine; QScriptValue m_global; ResolvedProduct *m_product; }; } // namespace Internal } // namespace qbs #endif // QBS_DEPENDENCY_SCANNER_H qbs-src-1.13.1/src/lib/corelib/buildgraph/emptydirectoriesremover.cpp000066400000000000000000000101401347155106100257420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "emptydirectoriesremover.h" #include "artifact.h" #include #include #include namespace qbs { namespace Internal { EmptyDirectoriesRemover::EmptyDirectoriesRemover(const TopLevelProject *project, const Logger &logger) : m_project(project), m_logger(logger) { } void EmptyDirectoriesRemover::removeEmptyParentDirectories(const QStringList &artifactFilePaths) { m_dirsToRemove.clear(); m_handledDirs.clear(); for (const QString &filePath : artifactFilePaths) insertSorted(QFileInfo(filePath).absolutePath()); while (!m_dirsToRemove.empty()) removeDirIfEmpty(); } void EmptyDirectoriesRemover::removeEmptyParentDirectories(const ArtifactSet &artifacts) { QStringList filePaths; for (const Artifact * const a : artifacts) { if (a->artifactType == Artifact::Generated) filePaths << a->filePath(); } removeEmptyParentDirectories(filePaths); } // List is sorted so that "deeper" directories come first. void EmptyDirectoriesRemover::insertSorted(const QString &dirPath) { int i; for (i = 0; i < m_dirsToRemove.size(); ++i) { const QString &cur = m_dirsToRemove.at(i); if (dirPath == cur) return; if (dirPath.count(QLatin1Char('/')) > cur.count(QLatin1Char('/'))) break; } m_dirsToRemove.insert(i, dirPath); } void EmptyDirectoriesRemover::removeDirIfEmpty() { const QString dirPath = m_dirsToRemove.takeFirst(); m_handledDirs.insert(dirPath); QFileInfo fi(dirPath); if (fi.isSymLink() || !fi.exists() || !dirPath.startsWith(m_project->buildDirectory) || fi.filePath() == m_project->buildDirectory) { return; } QDir dir(dirPath); dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); if (dir.count() != 0) return; dir.cdUp(); if (!dir.rmdir(fi.fileName())) { m_logger.qbsWarning() << QStringLiteral("Cannot remove empty directory '%1'.") .arg(dirPath); return; } const QString parentDir = dir.path(); if (!m_handledDirs.contains(parentDir)) insertSorted(parentDir); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/emptydirectoriesremover.h000066400000000000000000000052111347155106100254120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_EMPTYDIRECTORIESREMOVER_H #define QBS_EMPTYDIRECTORIESREMOVER_H #include "forward_decls.h" #include #include #include namespace qbs { namespace Internal { class TopLevelProject; class EmptyDirectoriesRemover { public: EmptyDirectoriesRemover(const TopLevelProject *project, const Logger &logger); void removeEmptyParentDirectories(const QStringList &artifactFilePaths); void removeEmptyParentDirectories(const ArtifactSet &artifacts); private: void insertSorted(const QString &dirPath); void removeDirIfEmpty(); const TopLevelProject * const m_project; Logger m_logger; QStringList m_dirsToRemove; Set m_handledDirs; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/buildgraph/environmentscriptrunner.cpp000066400000000000000000000221211347155106100257740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "environmentscriptrunner.h" #include "buildgraph.h" #include "rulesevaluationcontext.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class EnvProvider { public: EnvProvider(ScriptEngine *engine, const QProcessEnvironment &originalEnv) : m_engine(engine), m_env(originalEnv) { QVariant v; v.setValue(&m_env); m_engine->setProperty(StringConstants::qbsProcEnvVarInternal(), v); } ~EnvProvider() { m_engine->setProperty(StringConstants::qbsProcEnvVarInternal(), QVariant()); } QProcessEnvironment alteredEnvironment() const { return m_env; } private: ScriptEngine * const m_engine; QProcessEnvironment m_env; }; static QList topSortModules(const QHash > &moduleChildren, const QList &modules, Set &seenModuleNames) { QList result; for (const ResolvedModule * const m : modules) { if (m->name.isNull()) continue; result << topSortModules(moduleChildren, moduleChildren.value(m), seenModuleNames); if (seenModuleNames.insert(m->name).second) result.push_back(m); } return result; } EnvironmentScriptRunner::EnvironmentScriptRunner(ResolvedProduct *product, RulesEvaluationContext *evalContext, const QProcessEnvironment &env) : m_product(product), m_evalContext(evalContext), m_env(env) { } void EnvironmentScriptRunner::setupForBuild() { // TODO: Won't this fail to take changed properties into account? We probably need // change tracking here as well. if (!m_product->buildEnvironment.isEmpty()) return; m_envType = BuildEnv; setupEnvironment(); } void EnvironmentScriptRunner::setupForRun(const QStringList &config) { m_envType = RunEnv; m_runEnvConfig = config; setupEnvironment(); } void EnvironmentScriptRunner::setupEnvironment() { const auto hasScript = [this](const ResolvedModuleConstPtr &m) { return !getScript(m.get()).sourceCode().isEmpty(); }; const bool hasAnyScripts = std::any_of(m_product->modules.cbegin(), m_product->modules.cend(), hasScript); if (!hasAnyScripts) return; QMap moduleMap; for (const ResolvedModuleConstPtr &module : m_product->modules) moduleMap.insert(module->name, module.get()); QHash > moduleParents; QHash > moduleChildren; for (const ResolvedModuleConstPtr &module : m_product->modules) { for (const QString &moduleName : qAsConst(module->moduleDependencies)) { const ResolvedModule * const depmod = moduleMap.value(moduleName); QBS_ASSERT(depmod, return); moduleParents[depmod].push_back(module.get()); moduleChildren[module.get()].push_back(depmod); } } QList rootModules; for (const ResolvedModuleConstPtr &module : m_product->modules) { if (moduleParents.value(module.get()).isEmpty()) { QBS_ASSERT(module, return); rootModules.push_back(module.get()); } } EnvProvider envProvider(engine(), m_env); Set seenModuleNames; const QList &topSortedModules = topSortModules(moduleChildren, rootModules, seenModuleNames); const QStringList scriptFunctionArgs = m_envType == BuildEnv ? ResolvedModule::argumentNamesForSetupBuildEnv() : ResolvedModule::argumentNamesForSetupRunEnv(); for (const ResolvedModule * const module : topSortedModules) { const PrivateScriptFunction &setupScript = getScript(module); if (setupScript.sourceCode().isEmpty()) continue; RulesEvaluationContext::Scope s(m_evalContext); QScriptValue envScriptContext = engine()->newObject(); envScriptContext.setPrototype(engine()->globalObject()); setupScriptEngineForProduct(engine(), m_product, module, envScriptContext, false); const QString &productKey = StringConstants::productVar(); const QString &projectKey = StringConstants::projectVar(); m_evalContext->scope().setProperty(productKey, envScriptContext.property(productKey)); m_evalContext->scope().setProperty(projectKey, envScriptContext.property(projectKey)); if (m_envType == RunEnv) { QScriptValue configArray = engine()->newArray(m_runEnvConfig.size()); for (int i = 0; i < m_runEnvConfig.size(); ++i) configArray.setProperty(i, QScriptValue(m_runEnvConfig.at(i))); m_evalContext->scope().setProperty(QStringLiteral("config"), configArray); } setupScriptEngineForFile(engine(), setupScript.fileContext(), m_evalContext->scope(), ObserveMode::Disabled); // TODO: Cache evaluate result QScriptValue fun = engine()->evaluate(setupScript.sourceCode(), setupScript.location().filePath(), setupScript.location().line()); QBS_CHECK(fun.isFunction()); const QScriptValueList svArgs = ScriptEngine::argumentList(scriptFunctionArgs, m_evalContext->scope()); const QScriptValue res = fun.call(QScriptValue(), svArgs); engine()->releaseResourcesOfScriptObjects(); if (Q_UNLIKELY(engine()->hasErrorOrException(res))) { const QString scriptName = m_envType == BuildEnv ? StringConstants::setupBuildEnvironmentProperty() : StringConstants::setupRunEnvironmentProperty(); throw ErrorInfo(Tr::tr("Error running %1 script for product '%2': %3") .arg(scriptName, m_product->fullDisplayName(), engine()->lastErrorString(res)), engine()->lastErrorLocation(res, setupScript.location())); } } const QProcessEnvironment &newEnv = envProvider.alteredEnvironment(); if (m_envType == BuildEnv) m_product->buildEnvironment = newEnv; else m_product->runEnvironment = newEnv; } ScriptEngine *EnvironmentScriptRunner::engine() const { return m_evalContext->engine(); } const PrivateScriptFunction &EnvironmentScriptRunner::getScript(const ResolvedModule *module) const { return m_envType == BuildEnv ? module->setupBuildEnvironmentScript : module->setupRunEnvironmentScript; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/environmentscriptrunner.h000066400000000000000000000054501347155106100254470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ENVIRONMENTSCRIPTRUNNER_H #define QBS_ENVIRONMENTSCRIPTRUNNER_H #include #include #include namespace qbs { namespace Internal { class RulesEvaluationContext; class ScriptEngine; class EnvironmentScriptRunner { public: EnvironmentScriptRunner(ResolvedProduct *product, RulesEvaluationContext *evalContext, const QProcessEnvironment &env); void setupForBuild(); void setupForRun(const QStringList &config); private: void setupEnvironment(); ScriptEngine *engine() const; const PrivateScriptFunction &getScript(const ResolvedModule *module) const; ResolvedProduct * const m_product; RulesEvaluationContext * const m_evalContext; const QProcessEnvironment m_env; QStringList m_runEnvConfig; enum EnvType { BuildEnv, RunEnv } m_envType; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/buildgraph/executor.cpp000066400000000000000000001442671347155106100226270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "executor.h" #include "buildgraph.h" #include "emptydirectoriesremover.h" #include "environmentscriptrunner.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "cycledetector.h" #include "executorjob.h" #include "inputartifactscanner.h" #include "productinstaller.h" #include "rescuableartifactdata.h" #include "rulecommands.h" #include "rulenode.h" #include "rulesevaluationcontext.h" #include "transformerchangetracking.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { bool Executor::ComparePriority::operator() (const BuildGraphNode *x, const BuildGraphNode *y) const { return x->product->buildData->buildPriority() < y->product->buildData->buildPriority(); } Executor::Executor(const Logger &logger, QObject *parent) : QObject(parent) , m_productInstaller(nullptr) , m_logger(logger) , m_progressObserver(nullptr) , m_state(ExecutorIdle) , m_cancelationTimer(new QTimer(this)) { m_inputArtifactScanContext = new InputArtifactScannerContext; m_cancelationTimer->setSingleShot(false); m_cancelationTimer->setInterval(1000); connect(m_cancelationTimer, &QTimer::timeout, this, &Executor::checkForCancellation); } Executor::~Executor() { // jobs must be destroyed before deleting the shared scan result cache for (ExecutorJob *job : qAsConst(m_availableJobs)) delete job; for (ExecutorJob *job : m_processingJobs.keys()) delete job; delete m_inputArtifactScanContext; delete m_productInstaller; } FileTime Executor::recursiveFileTime(const QString &filePath) const { FileTime newest; FileInfo fileInfo(filePath); if (!fileInfo.exists()) { const QString nativeFilePath = QDir::toNativeSeparators(filePath); m_logger.qbsWarning() << Tr::tr("File '%1' not found.").arg(nativeFilePath); return newest; } newest = std::max(fileInfo.lastModified(), fileInfo.lastStatusChange()); if (!fileInfo.isDir()) return newest; const QStringList dirContents = QDir(filePath) .entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); for (const QString &curFileName : dirContents) { const FileTime ft = recursiveFileTime(filePath + QLatin1Char('/') + curFileName); if (ft > newest) newest = ft; } return newest; } void Executor::retrieveSourceFileTimestamp(Artifact *artifact) const { QBS_CHECK(artifact->artifactType == Artifact::SourceFile); if (m_buildOptions.changedFiles().empty()) artifact->setTimestamp(recursiveFileTime(artifact->filePath())); else if (m_buildOptions.changedFiles().contains(artifact->filePath())) artifact->setTimestamp(FileTime::currentTime()); else if (!artifact->timestamp().isValid()) artifact->setTimestamp(recursiveFileTime(artifact->filePath())); artifact->timestampRetrieved = true; if (!artifact->timestamp().isValid()) throw ErrorInfo(Tr::tr("Source file '%1' has disappeared.").arg(artifact->filePath())); } void Executor::build() { try { m_partialBuild = m_productsToBuild.size() != m_allProducts.size(); doBuild(); } catch (const ErrorInfo &e) { handleError(e); } } void Executor::setProject(const TopLevelProjectPtr &project) { m_project = project; m_allProducts = project->allProducts(); m_projectsByName.clear(); m_projectsByName.insert(std::make_pair(project->name, project.get())); for (const ResolvedProjectPtr &p : project->allSubProjects()) m_projectsByName.insert(std::make_pair(p->name, p.get())); } void Executor::setProducts(const std::vector &productsToBuild) { m_productsToBuild = productsToBuild; m_productsByName.clear(); for (const ResolvedProductPtr &p : productsToBuild) m_productsByName.insert(std::make_pair(p->uniqueName(), p.get())); } class ProductPrioritySetter { const std::vector &m_allProducts; unsigned int m_priority; Set m_seenProducts; public: ProductPrioritySetter(const std::vector &allProducts) // TODO: Use only products to build? : m_allProducts(allProducts) { } void apply() { Set allDependencies; for (const ResolvedProductPtr &product : m_allProducts) { for (const ResolvedProductPtr &dep : product->dependencies) allDependencies += dep; } const Set rootProducts = Set::fromStdVector(m_allProducts) - allDependencies; m_priority = UINT_MAX; m_seenProducts.clear(); for (const ResolvedProductPtr &rootProduct : rootProducts) traverse(rootProduct); } private: void traverse(const ResolvedProductPtr &product) { if (!m_seenProducts.insert(product).second) return; for (const ResolvedProductPtr &dependency : qAsConst(product->dependencies)) traverse(dependency); if (!product->buildData) return; product->buildData->setBuildPriority(m_priority--); } }; void Executor::doBuild() { if (m_buildOptions.maxJobCount() <= 0) { m_buildOptions.setMaxJobCount(BuildOptions::defaultMaxJobCount()); qCDebug(lcExec) << "max job count not explicitly set, using value of" << m_buildOptions.maxJobCount(); } QBS_CHECK(m_state == ExecutorIdle); m_leaves = Leaves(); m_error.clear(); m_explicitlyCanceled = false; m_activeFileTags = FileTags::fromStringList(m_buildOptions.activeFileTags()); m_tagsOfFilesToConsider.clear(); m_tagsNeededForFilesToConsider.clear(); m_productsOfFilesToConsider.clear(); m_artifactsRemovedFromDisk.clear(); m_jobCountPerPool.clear(); setupJobLimits(); // TODO: The "filesToConsider" thing is badly designed; we should know exactly which artifact // it is. Remove this from the BuildOptions class and introduce Project::buildSomeFiles() // instead. const QStringList &filesToConsider = m_buildOptions.filesToConsider(); if (!filesToConsider.empty()) { for (const QString &fileToConsider : filesToConsider) { const QList &files = m_project->buildData->lookupFiles(fileToConsider); for (const FileResourceBase * const file : files) { if (file->fileType() != FileResourceBase::FileTypeArtifact) continue; auto const artifact = static_cast(file); if (contains(m_productsToBuild, artifact->product.lock())) { m_tagsOfFilesToConsider.unite(artifact->fileTags()); m_productsOfFilesToConsider << artifact->product.lock(); } } } } setState(ExecutorRunning); if (m_productsToBuild.empty()) { qCDebug(lcExec) << "No products to build, finishing."; QTimer::singleShot(0, this, &Executor::finish); // Don't call back on the caller. return; } doSanityChecks(); QBS_CHECK(!m_project->buildData->evaluationContext); m_project->buildData->evaluationContext = RulesEvaluationContextPtr(new RulesEvaluationContext(m_logger)); m_evalContext = m_project->buildData->evaluationContext; m_elapsedTimeRules = m_elapsedTimeScanners = m_elapsedTimeInstalling = 0; m_evalContext->engine()->enableProfiling(m_buildOptions.logElapsedTime()); InstallOptions installOptions; installOptions.setDryRun(m_buildOptions.dryRun()); installOptions.setInstallRoot(m_productsToBuild.front()->moduleProperties ->qbsPropertyValue(StringConstants::installRootProperty()).toString()); installOptions.setKeepGoing(m_buildOptions.keepGoing()); m_productInstaller = new ProductInstaller(m_project, m_productsToBuild, installOptions, m_progressObserver, m_logger); if (m_buildOptions.removeExistingInstallation()) m_productInstaller->removeInstallRoot(); addExecutorJobs(); syncFileDependencies(); prepareAllNodes(); prepareProducts(); setupRootNodes(); prepareReachableNodes(); setupProgressObserver(); initLeaves(); if (!scheduleJobs()) { qCDebug(lcExec) << "Nothing to do at all, finishing."; QTimer::singleShot(0, this, &Executor::finish); // Don't call back on the caller. } if (m_progressObserver) m_cancelationTimer->start(); } void Executor::setBuildOptions(const BuildOptions &buildOptions) { m_buildOptions = buildOptions; } void Executor::initLeaves() { updateLeaves(m_roots); } void Executor::updateLeaves(const NodeSet &nodes) { NodeSet seenNodes; for (BuildGraphNode * const node : nodes) updateLeaves(node, seenNodes); } void Executor::updateLeaves(BuildGraphNode *node, NodeSet &seenNodes) { if (!seenNodes.insert(node).second) return; // Artifacts that appear in the build graph after // prepareBuildGraph() has been called, must be initialized. if (node->buildState == BuildGraphNode::Untouched) { node->buildState = BuildGraphNode::Buildable; if (node->type() == BuildGraphNode::ArtifactNodeType) { auto const artifact = static_cast(node); if (artifact->artifactType == Artifact::SourceFile) retrieveSourceFileTimestamp(artifact); } } bool isLeaf = true; for (BuildGraphNode *child : qAsConst(node->children)) { if (child->buildState != BuildGraphNode::Built) { isLeaf = false; updateLeaves(child, seenNodes); } } if (isLeaf) { qCDebug(lcExec).noquote() << "adding leaf" << node->toString(); m_leaves.push(node); } } // Returns true if some artifacts are still waiting to be built or currently building. bool Executor::scheduleJobs() { QBS_CHECK(m_state == ExecutorRunning); std::vector delayedLeaves; while (!m_leaves.empty() && !m_availableJobs.empty()) { BuildGraphNode * const nodeToBuild = m_leaves.top(); m_leaves.pop(); switch (nodeToBuild->buildState) { case BuildGraphNode::Untouched: QBS_ASSERT(!"untouched node in leaves list", qDebug("%s", qPrintable(nodeToBuild->toString()))); break; case BuildGraphNode::Buildable: // This is the only state in which we want to build a node. // TODO: It's a bit annoying that we have to check this here already, when we // don't know whether the transformer needs to run at all. Investigate // moving the whole job allocation logic to runTransformer(). if (schedulingBlockedByJobLimit(nodeToBuild)) { qCDebug(lcExec).noquote() << "node delayed due to occupied job pool:" << nodeToBuild->toString(); delayedLeaves.push_back(nodeToBuild); } else { nodeToBuild->accept(this); } break; case BuildGraphNode::Building: qCDebug(lcExec).noquote() << nodeToBuild->toString(); qCDebug(lcExec) << "node is currently being built. Skipping."; break; case BuildGraphNode::Built: qCDebug(lcExec).noquote() << nodeToBuild->toString(); qCDebug(lcExec) << "node already built. Skipping."; break; } } for (BuildGraphNode * const delayedLeaf : delayedLeaves) m_leaves.push(delayedLeaf); return !m_leaves.empty() || !m_processingJobs.empty(); } bool Executor::schedulingBlockedByJobLimit(const BuildGraphNode *node) { if (node->type() != BuildGraphNode::ArtifactNodeType) return false; const Artifact * const artifact = static_cast(node); if (artifact->artifactType == Artifact::SourceFile) return false; const Transformer * const transformer = artifact->transformer.get(); for (const QString &jobPool : transformer->jobPools()) { const int currentJobCount = m_jobCountPerPool[jobPool]; if (currentJobCount == 0) continue; const auto jobLimitIsExceeded = [currentJobCount, jobPool, this](const Transformer *t) { const int maxJobCount = m_jobLimitsPerProduct.at(t->product().get()) .getLimit(jobPool); return maxJobCount > 0 && currentJobCount >= maxJobCount; }; // Different products can set different limits. The effective limit is the minimum of what // is set in this transformer's product and in the products of all currently // running transformers. if (jobLimitIsExceeded(transformer)) return true; for (const ExecutorJob * const runningJob : m_processingJobs.keys()) { if (!runningJob->jobPools().contains(jobPool)) continue; const Transformer * const runningTransformer = runningJob->transformer(); if (!runningTransformer) continue; // This can happen if the ExecutorJob has already finished. if (runningTransformer->product() == transformer->product()) continue; // We have already checked this product's job limit. if (jobLimitIsExceeded(runningTransformer)) return true; } } return false; } bool Executor::isUpToDate(Artifact *artifact) const { QBS_CHECK(artifact->artifactType == Artifact::Generated); qCDebug(lcUpToDateCheck) << "check" << artifact->filePath() << artifact->timestamp().toString(); if (m_buildOptions.forceTimestampCheck()) { artifact->setTimestamp(FileInfo(artifact->filePath()).lastModified()); qCDebug(lcUpToDateCheck) << "timestamp retrieved from filesystem:" << artifact->timestamp().toString(); } if (!artifact->timestamp().isValid()) { qCDebug(lcUpToDateCheck) << "invalid timestamp. Out of date."; return false; } for (Artifact *childArtifact : filterByType(artifact->children)) { QBS_CHECK(!childArtifact->alwaysUpdated || childArtifact->timestamp().isValid()); qCDebug(lcUpToDateCheck) << "child timestamp" << childArtifact->timestamp().toString() << childArtifact->filePath(); if (artifact->timestamp() < childArtifact->timestamp()) return false; } for (FileDependency *fileDependency : qAsConst(artifact->fileDependencies)) { if (!fileDependency->timestamp().isValid()) { qCDebug(lcUpToDateCheck) << "file dependency doesn't exist" << fileDependency->filePath(); return false; } qCDebug(lcUpToDateCheck) << "file dependency timestamp" << fileDependency->timestamp().toString() << fileDependency->filePath(); if (artifact->timestamp() < fileDependency->timestamp()) return false; } return true; } bool Executor::mustExecuteTransformer(const TransformerPtr &transformer) const { if (transformer->alwaysRun) return true; if (transformer->markedForRerun) { qCDebug(lcUpToDateCheck) << "explicitly marked for re-run."; return true; } bool hasAlwaysUpdatedArtifacts = false; bool hasUpToDateNotAlwaysUpdatedArtifacts = false; for (Artifact *artifact : qAsConst(transformer->outputs)) { if (isUpToDate(artifact)) { if (artifact->alwaysUpdated) hasAlwaysUpdatedArtifacts = true; else hasUpToDateNotAlwaysUpdatedArtifacts = true; } else if (artifact->alwaysUpdated || m_buildOptions.forceTimestampCheck()) { return true; } } if (commandsNeedRerun(transformer.get(), transformer->product().get(), m_productsByName, m_projectsByName)) { return true; } // If all artifacts in a transformer have "alwaysUpdated" set to false, that transformer is // run if and only if *all* of them are out of date. return !hasAlwaysUpdatedArtifacts && !hasUpToDateNotAlwaysUpdatedArtifacts; } void Executor::buildArtifact(Artifact *artifact) { qCDebug(lcExec) << relativeArtifactFileName(artifact); QBS_CHECK(artifact->buildState == BuildGraphNode::Buildable); if (artifact->artifactType != Artifact::SourceFile && !checkNodeProduct(artifact)) return; // skip artifacts without transformer if (artifact->artifactType != Artifact::Generated) { // For source artifacts, that were not reachable when initializing the build, we must // retrieve timestamps. This can happen, if a dependency that's added during the build // makes the source artifact reachable. if (artifact->artifactType == Artifact::SourceFile && !artifact->timestampRetrieved) retrieveSourceFileTimestamp(artifact); qCDebug(lcExec) << "artifact type" << toString(artifact->artifactType) << "Skipping."; finishArtifact(artifact); return; } // Every generated artifact must have a transformer. QBS_CHECK(artifact->transformer); potentiallyRunTransformer(artifact->transformer); } void Executor::executeRuleNode(RuleNode *ruleNode) { AccumulatingTimer rulesTimer(m_buildOptions.logElapsedTime() ? &m_elapsedTimeRules : nullptr); if (!checkNodeProduct(ruleNode)) return; QBS_CHECK(!m_evalContext->engine()->isActive()); RuleNode::ApplicationResult result; ruleNode->apply(m_logger, m_productsByName, m_projectsByName, &result); updateLeaves(result.createdArtifacts); updateLeaves(result.invalidatedArtifacts); m_artifactsRemovedFromDisk << result.removedArtifacts; if (m_progressObserver) { const int transformerCount = ruleNode->transformerCount(); if (transformerCount == 0) { m_progressObserver->incrementProgressValue(); } else { m_pendingTransformersPerRule.insert(std::make_pair(ruleNode->rule().get(), transformerCount)); } } finishNode(ruleNode); } void Executor::finishJob(ExecutorJob *job, bool success) { QBS_CHECK(job); QBS_CHECK(m_state != ExecutorIdle); const JobMap::Iterator it = m_processingJobs.find(job); QBS_CHECK(it != m_processingJobs.end()); const TransformerPtr transformer = it.value(); m_processingJobs.erase(it); m_availableJobs.push_back(job); updateJobCounts(transformer.get(), -1); if (success) { m_project->buildData->setDirty(); for (Artifact * const artifact : qAsConst(transformer->outputs)) { if (artifact->alwaysUpdated) { artifact->setTimestamp(FileTime::currentTime()); for (Artifact * const parent : artifact->parentArtifacts()) parent->transformer->markedForRerun = true; if (m_buildOptions.forceOutputCheck() && !m_buildOptions.dryRun() && !FileInfo(artifact->filePath()).exists()) { if (transformer->rule) { if (!transformer->rule->name.isEmpty()) { throw ErrorInfo(tr("Rule '%1' declares artifact '%2', " "but the artifact was not produced.") .arg(transformer->rule->name, artifact->filePath())); } throw ErrorInfo(tr("Rule declares artifact '%1', " "but the artifact was not produced.") .arg(artifact->filePath())); } throw ErrorInfo(tr("Transformer declares artifact '%1', " "but the artifact was not produced.") .arg(artifact->filePath())); } } else { artifact->setTimestamp(FileInfo(artifact->filePath()).lastModified()); } } finishTransformer(transformer); } if (!success && !m_buildOptions.keepGoing()) cancelJobs(); if (m_state == ExecutorRunning && m_progressObserver && m_progressObserver->canceled()) { qCDebug(lcExec) << "Received cancel request; canceling build."; m_explicitlyCanceled = true; cancelJobs(); } if (m_state == ExecutorCanceling) { if (m_processingJobs.empty()) { qCDebug(lcExec) << "All pending jobs are done, finishing."; finish(); } return; } if (!scheduleJobs()) { qCDebug(lcExec) << "Nothing left to build; finishing."; finish(); } } static bool allChildrenBuilt(BuildGraphNode *node) { return std::all_of(node->children.cbegin(), node->children.cend(), std::mem_fn(&BuildGraphNode::isBuilt)); } void Executor::finishNode(BuildGraphNode *leaf) { leaf->buildState = BuildGraphNode::Built; for (BuildGraphNode * const parent : qAsConst(leaf->parents)) { if (parent->buildState != BuildGraphNode::Buildable) { qCDebug(lcExec).noquote() << "parent" << parent->toString() << "build state:" << toString(parent->buildState); continue; } if (allChildrenBuilt(parent)) { m_leaves.push(parent); qCDebug(lcExec).noquote() << "finishNode adds leaf" << parent->toString() << toString(parent->buildState); } else { qCDebug(lcExec).noquote() << "parent" << parent->toString() << "build state:" << toString(parent->buildState); } } } void Executor::finishArtifact(Artifact *leaf) { QBS_CHECK(leaf); qCDebug(lcExec) << "finishArtifact" << relativeArtifactFileName(leaf); finishNode(leaf); } QString Executor::configString() const { return tr(" for configuration %1").arg(m_project->id()); } bool Executor::transformerHasMatchingOutputTags(const TransformerConstPtr &transformer) const { if (m_activeFileTags.empty()) return true; // No filtering requested. return std::any_of(transformer->outputs.cbegin(), transformer->outputs.cend(), [this](const Artifact *a) { return artifactHasMatchingOutputTags(a); }); } bool Executor::artifactHasMatchingOutputTags(const Artifact *artifact) const { return m_activeFileTags.intersects(artifact->fileTags()) || m_tagsNeededForFilesToConsider.intersects(artifact->fileTags()); } bool Executor::transformerHasMatchingInputFiles(const TransformerConstPtr &transformer) const { if (m_buildOptions.filesToConsider().empty()) return true; // No filtering requested. if (!m_productsOfFilesToConsider.contains(transformer->product())) return false; if (transformer->inputs.empty()) return true; for (const Artifact * const input : qAsConst(transformer->inputs)) { for (const QString &filePath : m_buildOptions.filesToConsider()) { if (input->filePath() == filePath || input->fileTags().intersects(m_tagsNeededForFilesToConsider)) { return true; } } } return false; } void Executor::setupJobLimits() { Settings settings(m_buildOptions.settingsDirectory()); for (const ResolvedProductConstPtr &p : m_productsToBuild) { const Preferences prefs(&settings, p->profile()); const JobLimits &jobLimitsFromSettings = prefs.jobLimits(); JobLimits effectiveJobLimits; if (m_buildOptions.projectJobLimitsTakePrecedence()) { effectiveJobLimits.update(jobLimitsFromSettings).update(m_buildOptions.jobLimits()) .update(p->jobLimits); } else { effectiveJobLimits.update(p->jobLimits).update(jobLimitsFromSettings) .update(m_buildOptions.jobLimits()); } m_jobLimitsPerProduct.insert(std::make_pair(p.get(), effectiveJobLimits)); } } void Executor::updateJobCounts(const Transformer *transformer, int diff) { for (const QString &jobPool : transformer->jobPools()) m_jobCountPerPool[jobPool] += diff; } void Executor::cancelJobs() { if (m_state == ExecutorCanceling) return; qCDebug(lcExec) << "Canceling all jobs."; setState(ExecutorCanceling); for (ExecutorJob *job : m_processingJobs.keys()) job->cancel(); } void Executor::setupProgressObserver() { if (!m_progressObserver) return; int totalEffort = 1; // For the effort after the last rule application; for (const ResolvedProductConstPtr &product : m_productsToBuild) { QBS_CHECK(product->buildData); const auto filtered = filterByType(product->buildData->allNodes()); totalEffort += std::distance(filtered.begin(), filtered.end()); } m_progressObserver->initialize(tr("Building%1").arg(configString()), totalEffort); } void Executor::doSanityChecks() { QBS_CHECK(m_project); QBS_CHECK(!m_productsToBuild.empty()); for (const ResolvedProductConstPtr &product : m_productsToBuild) { QBS_CHECK(product->buildData); QBS_CHECK(product->topLevelProject() == m_project.get()); } } void Executor::handleError(const ErrorInfo &error) { for (const ErrorItem &ei : error.items()) m_error.append(ei); if (m_processingJobs.empty()) finish(); else cancelJobs(); } void Executor::addExecutorJobs() { qCDebug(lcExec) << "preparing executor for" << m_buildOptions.maxJobCount() << "jobs in parallel"; for (int i = 1; i <= m_buildOptions.maxJobCount(); i++) { const auto job = new ExecutorJob(m_logger, this); job->setMainThreadScriptEngine(m_evalContext->engine()); job->setObjectName(QStringLiteral("J%1").arg(i)); job->setDryRun(m_buildOptions.dryRun()); job->setEchoMode(m_buildOptions.echoMode()); m_availableJobs.push_back(job); connect(job, &ExecutorJob::reportCommandDescription, this, &Executor::reportCommandDescription); connect(job, &ExecutorJob::reportProcessResult, this, &Executor::reportProcessResult); connect(job, &ExecutorJob::finished, this, &Executor::onJobFinished, Qt::QueuedConnection); } } void Executor::rescueOldBuildData(Artifact *artifact, bool *childrenAdded = nullptr) { if (childrenAdded) *childrenAdded = false; if (!artifact->oldDataPossiblyPresent) return; artifact->oldDataPossiblyPresent = false; if (artifact->artifactType != Artifact::Generated) return; ResolvedProduct * const product = artifact->product.get(); const RescuableArtifactData rad = product->buildData->removeFromRescuableArtifactData(artifact->filePath()); if (!rad.isValid()) return; qCDebug(lcBuildGraph) << "Attempting to rescue data of artifact" << artifact->fileName(); std::vector childrenToConnect; bool canRescue = artifact->transformer->commands == rad.commands; if (canRescue) { ResolvedProductPtr pseudoProduct = ResolvedProduct::create(); for (const RescuableArtifactData::ChildData &cd : rad.children) { pseudoProduct->name = cd.productName; pseudoProduct->multiplexConfigurationId = cd.productMultiplexId; Artifact * const child = lookupArtifact(pseudoProduct, m_project->buildData.get(), cd.childFilePath, true); if (artifact->children.contains(child)) continue; if (!child) { // If a child has disappeared, we must re-build even if the commands // are the same. Example: Header file included in cpp file does not exist anymore. canRescue = false; qCDebug(lcBuildGraph) << "Former child artifact" << cd.childFilePath << "does not exist anymore."; const RescuableArtifactData childRad = product->buildData->removeFromRescuableArtifactData(cd.childFilePath); if (childRad.isValid()) { m_artifactsRemovedFromDisk << artifact->filePath(); removeGeneratedArtifactFromDisk(cd.childFilePath, m_logger); } } if (!cd.addedByScanner) { // If an artifact has disappeared from the list of children, the commands // might need to run again. canRescue = false; qCDebug(lcBuildGraph) << "Former child artifact" << cd.childFilePath << "is no longer in the list of children"; } if (canRescue) childrenToConnect.push_back(child); } for (const QString &depPath : rad.fileDependencies) { const QList depList = m_project->buildData->lookupFiles(depPath); if (depList.empty()) { canRescue = false; qCDebug(lcBuildGraph) << "File dependency" << depPath << "not in the project's list of dependencies anymore."; break; } const auto depFinder = [](const FileResourceBase *f) { return f->fileType() == FileResourceBase::FileTypeDependency; }; const auto depIt = std::find_if(depList.cbegin(), depList.cend(), depFinder); if (depIt == depList.cend()) { canRescue = false; qCDebug(lcBuildGraph) << "File dependency" << depPath << "not in the project's list of dependencies anymore."; break; } artifact->fileDependencies.insert(static_cast(*depIt)); } if (canRescue) { const TypeFilter childArtifacts(artifact->children); const size_t newChildCount = childrenToConnect.size() + std::distance(childArtifacts.begin(), childArtifacts.end()); QBS_CHECK(newChildCount >= rad.children.size()); if (newChildCount > rad.children.size()) { canRescue = false; qCDebug(lcBuildGraph) << "Artifact has children not present in rescue data."; } } } else { qCDebug(lcBuildGraph) << "Transformer commands changed."; } if (canRescue) { artifact->transformer->propertiesRequestedInPrepareScript = rad.propertiesRequestedInPrepareScript; artifact->transformer->propertiesRequestedInCommands = rad.propertiesRequestedInCommands; artifact->transformer->propertiesRequestedFromArtifactInPrepareScript = rad.propertiesRequestedFromArtifactInPrepareScript; artifact->transformer->propertiesRequestedFromArtifactInCommands = rad.propertiesRequestedFromArtifactInCommands; artifact->transformer->importedFilesUsedInPrepareScript = rad.importedFilesUsedInPrepareScript; artifact->transformer->importedFilesUsedInCommands = rad.importedFilesUsedInCommands; artifact->transformer->depsRequestedInPrepareScript = rad.depsRequestedInPrepareScript; artifact->transformer->depsRequestedInCommands = rad.depsRequestedInCommands; artifact->transformer->artifactsMapRequestedInPrepareScript = rad.artifactsMapRequestedInPrepareScript; artifact->transformer->artifactsMapRequestedInCommands = rad.artifactsMapRequestedInCommands; artifact->transformer->exportedModulesAccessedInPrepareScript = rad.exportedModulesAccessedInPrepareScript; artifact->transformer->exportedModulesAccessedInCommands = rad.exportedModulesAccessedInCommands; artifact->transformer->lastCommandExecutionTime = rad.lastCommandExecutionTime; artifact->transformer->lastPrepareScriptExecutionTime = rad.lastPrepareScriptExecutionTime; artifact->transformer->commandsNeedChangeTracking = true; artifact->setTimestamp(rad.timeStamp); artifact->transformer->markedForRerun = artifact->transformer->markedForRerun || rad.knownOutOfDate; if (childrenAdded && !childrenToConnect.empty()) *childrenAdded = true; for (Artifact * const child : childrenToConnect) { if (safeConnect(artifact, child)) artifact->childrenAddedByScanner << child; } qCDebug(lcBuildGraph) << "Data was rescued."; } else { removeGeneratedArtifactFromDisk(artifact, m_logger); m_artifactsRemovedFromDisk << artifact->filePath(); qCDebug(lcBuildGraph) << "Data not rescued."; } } bool Executor::checkForUnbuiltDependencies(Artifact *artifact) { bool buildingDependenciesFound = false; NodeSet unbuiltDependencies; for (BuildGraphNode * const dependency : qAsConst(artifact->children)) { switch (dependency->buildState) { case BuildGraphNode::Untouched: case BuildGraphNode::Buildable: qCDebug(lcExec).noquote() << "unbuilt dependency:" << dependency->toString(); unbuiltDependencies += dependency; break; case BuildGraphNode::Building: { qCDebug(lcExec).noquote() << "dependency in state 'Building':" << dependency->toString(); buildingDependenciesFound = true; break; } case BuildGraphNode::Built: // do nothing break; } } if (!unbuiltDependencies.empty()) { artifact->inputsScanned = false; updateLeaves(unbuiltDependencies); return true; } if (buildingDependenciesFound) { artifact->inputsScanned = false; return true; } return false; } void Executor::potentiallyRunTransformer(const TransformerPtr &transformer) { for (Artifact * const output : qAsConst(transformer->outputs)) { // Rescuing build data can introduce new dependencies, potentially delaying execution of // this transformer. bool childrenAddedDueToRescue; rescueOldBuildData(output, &childrenAddedDueToRescue); if (childrenAddedDueToRescue && checkForUnbuiltDependencies(output)) return; } if (!transformerHasMatchingOutputTags(transformer)) { qCDebug(lcExec) << "file tags do not match. Skipping."; finishTransformer(transformer); return; } if (!transformerHasMatchingInputFiles(transformer)) { qCDebug(lcExec) << "input files do not match. Skipping."; finishTransformer(transformer); return; } const bool mustExecute = mustExecuteTransformer(transformer); if (mustExecute || m_buildOptions.forceTimestampCheck()) { for (Artifact * const output : qAsConst(transformer->outputs)) { // Scan all input artifacts. If new dependencies were found during scanning, delay // execution of this transformer. InputArtifactScanner scanner(output, m_inputArtifactScanContext, m_logger); AccumulatingTimer scanTimer(m_buildOptions.logElapsedTime() ? &m_elapsedTimeScanners : nullptr); scanner.scan(); scanTimer.stop(); if (scanner.newDependencyAdded() && checkForUnbuiltDependencies(output)) return; } } if (!mustExecute) { qCDebug(lcExec) << "Up to date. Skipping."; finishTransformer(transformer); return; } if (m_buildOptions.executeRulesOnly()) finishTransformer(transformer); else runTransformer(transformer); } void Executor::runTransformer(const TransformerPtr &transformer) { QBS_CHECK(transformer); // create the output directories if (!m_buildOptions.dryRun()) { for (Artifact * const output : qAsConst(transformer->outputs)) { QDir outDir = QFileInfo(output->filePath()).absoluteDir(); if (!outDir.exists() && !outDir.mkpath(StringConstants::dot())) { throw ErrorInfo(tr("Failed to create directory '%1'.") .arg(QDir::toNativeSeparators(outDir.absolutePath()))); } } } QBS_CHECK(!m_availableJobs.empty()); ExecutorJob *job = m_availableJobs.takeFirst(); for (Artifact * const artifact : qAsConst(transformer->outputs)) artifact->buildState = BuildGraphNode::Building; m_processingJobs.insert(job, transformer); updateJobCounts(transformer.get(), 1); job->run(transformer.get()); } void Executor::finishTransformer(const TransformerPtr &transformer) { transformer->markedForRerun = false; for (Artifact * const artifact : qAsConst(transformer->outputs)) { possiblyInstallArtifact(artifact); finishArtifact(artifact); } if (m_progressObserver) { const auto it = m_pendingTransformersPerRule.find(transformer->rule.get()); QBS_CHECK(it != m_pendingTransformersPerRule.cend()); if (--it->second == 0) { m_progressObserver->incrementProgressValue(); m_pendingTransformersPerRule.erase(it); } } } void Executor::possiblyInstallArtifact(const Artifact *artifact) { AccumulatingTimer installTimer(m_buildOptions.logElapsedTime() ? &m_elapsedTimeInstalling : nullptr); if (m_buildOptions.install() && !m_buildOptions.executeRulesOnly() && (m_activeFileTags.empty() || artifactHasMatchingOutputTags(artifact)) && artifact->properties->qbsPropertyValue(StringConstants::installProperty()) .toBool()) { m_productInstaller->copyFile(artifact); } } void Executor::onJobFinished(const qbs::ErrorInfo &err) { try { auto const job = qobject_cast(sender()); QBS_CHECK(job); if (m_evalContext->engine()->isActive()) { qCDebug(lcExec) << "Executor job finished while rule execution is pausing. " "Delaying slot execution."; QTimer::singleShot(0, job, [job, err] { job->finished(err); }); return; } if (err.hasError()) { if (m_buildOptions.keepGoing()) { ErrorInfo fullWarning(err); fullWarning.prepend(Tr::tr("Ignoring the following errors on user request:")); m_logger.printWarning(fullWarning); } else { if (!m_error.hasError()) m_error = err; // All but the first one could be due to canceling. } } finishJob(job, !err.hasError()); } catch (const ErrorInfo &error) { handleError(error); } } void Executor::checkForUnbuiltProducts() { if (m_buildOptions.executeRulesOnly()) return; QList unbuiltProducts; for (const ResolvedProductPtr &product : m_productsToBuild) { bool productBuilt = true; for (BuildGraphNode *rootNode : qAsConst(product->buildData->rootNodes())) { if (rootNode->buildState != BuildGraphNode::Built) { productBuilt = false; unbuiltProducts.push_back(product); break; } } if (productBuilt) { // Any element still left after a successful build has not been re-created // by any rule and therefore does not exist anymore as an artifact. const AllRescuableArtifactData rad = product->buildData->rescuableArtifactData(); for (auto it = rad.cbegin(); it != rad.cend(); ++it) { removeGeneratedArtifactFromDisk(it.key(), m_logger); product->buildData->removeFromRescuableArtifactData(it.key()); m_artifactsRemovedFromDisk << it.key(); } } } if (unbuiltProducts.empty()) { m_logger.qbsInfo() << Tr::tr("Build done%1.").arg(configString()); } else { m_error.append(Tr::tr("The following products could not be built%1:").arg(configString())); QStringList productNames; std::transform(unbuiltProducts.cbegin(), unbuiltProducts.cend(), std::back_inserter(productNames), [](const ResolvedProductConstPtr &p) { return p->fullDisplayName(); }); std::sort(productNames.begin(), productNames.end()); m_error.append(productNames.join(QLatin1String(", "))); } } bool Executor::checkNodeProduct(BuildGraphNode *node) { if (!m_partialBuild || contains(m_productsToBuild, node->product.lock())) return true; // TODO: Turn this into a warning once we have a reliable C++ scanner. qCDebug(lcExec).noquote() << "Ignoring node " << node->toString() << ", which belongs to a " "product that is not part of the list of products to build. " "Possible reasons are an erroneous project design or a false " "positive from a dependency scanner."; finishNode(node); return false; } void Executor::finish() { QBS_ASSERT(m_state != ExecutorIdle, /* ignore */); QBS_ASSERT(!m_evalContext || !m_evalContext->engine()->isActive(), /* ignore */); checkForUnbuiltProducts(); if (m_explicitlyCanceled) { QString message = Tr::tr(m_buildOptions.executeRulesOnly() ? "Rule execution canceled" : "Build canceled"); m_error.append(Tr::tr("%1%2.").arg(message, configString())); } setState(ExecutorIdle); if (m_progressObserver) { m_progressObserver->setFinished(); m_cancelationTimer->stop(); } EmptyDirectoriesRemover(m_project.get(), m_logger) .removeEmptyParentDirectories(m_artifactsRemovedFromDisk); if (m_buildOptions.logElapsedTime()) { m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Rule execution took %1.") .arg(elapsedTimeString(m_elapsedTimeRules)); m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Artifact scanning took %1.") .arg(elapsedTimeString(m_elapsedTimeScanners)); m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Installing artifacts took %1.") .arg(elapsedTimeString(m_elapsedTimeInstalling)); } emit finished(); } void Executor::checkForCancellation() { QBS_ASSERT(m_progressObserver, return); if (m_state == ExecutorRunning && m_progressObserver->canceled()) { cancelJobs(); if (m_evalContext->engine()->isActive()) m_evalContext->engine()->cancel(); } } bool Executor::visit(Artifact *artifact) { QBS_CHECK(artifact->buildState != BuildGraphNode::Untouched); buildArtifact(artifact); return false; } bool Executor::visit(RuleNode *ruleNode) { QBS_CHECK(ruleNode->buildState != BuildGraphNode::Untouched); executeRuleNode(ruleNode); return false; } /** * Sets the state of all artifacts in the graph to "untouched". * This must be done before doing a build. * * Retrieves the timestamps of source artifacts. * * This function also fills the list of changed source files. */ void Executor::prepareAllNodes() { for (const ResolvedProductPtr &product : m_allProducts) { if (product->enabled) { QBS_CHECK(product->buildData); for (BuildGraphNode * const node : qAsConst(product->buildData->allNodes())) node->buildState = BuildGraphNode::Untouched; } } for (const ResolvedProductPtr &product : m_productsToBuild) { QBS_CHECK(product->buildData); for (Artifact * const artifact : filterByType(product->buildData->allNodes())) prepareArtifact(artifact); } } void Executor::syncFileDependencies() { Set &globalFileDepList = m_project->buildData->fileDependencies; for (auto it = globalFileDepList.begin(); it != globalFileDepList.end(); ) { FileDependency * const dep = *it; FileInfo fi(dep->filePath()); if (fi.exists()) { dep->setTimestamp(fi.lastModified()); ++it; continue; } qCDebug(lcBuildGraph()) << "file dependency" << dep->filePath() << "no longer exists; " "removing from lookup table"; m_project->buildData->removeFromLookupTable(dep); bool isReferencedByArtifact = false; for (const ResolvedProductConstPtr &product : m_allProducts) { if (!product->buildData) continue; const auto artifactList = filterByType(product->buildData->allNodes()); isReferencedByArtifact = std::any_of(artifactList.begin(), artifactList.end(), [dep](const Artifact *a) { return a->fileDependencies.contains(dep); }); // TODO: Would it be safe to mark the artifact as "not up to date" here and clear // its list of file dependencies, rather than doing the check again in // isUpToDate()? if (isReferencedByArtifact) break; } if (!isReferencedByArtifact) { qCDebug(lcBuildGraph()) << "dependency is not referenced by any artifact, deleting"; it = globalFileDepList.erase(it); delete dep; } else { dep->clearTimestamp(); ++it; } } } void Executor::prepareArtifact(Artifact *artifact) { artifact->inputsScanned = false; artifact->timestampRetrieved = false; if (artifact->artifactType == Artifact::SourceFile) { retrieveSourceFileTimestamp(artifact); possiblyInstallArtifact(artifact); } } void Executor::setupForBuildingSelectedFiles(const BuildGraphNode *node) { if (node->type() != BuildGraphNode::RuleNodeType) return; if (m_buildOptions.filesToConsider().empty()) return; if (!m_productsOfFilesToConsider.contains(node->product.lock())) return; const auto ruleNode = static_cast(node); const Rule * const rule = ruleNode->rule().get(); if (rule->inputs.intersects(m_tagsOfFilesToConsider)) { FileTags otherInputs = rule->auxiliaryInputs; otherInputs.unite(rule->explicitlyDependsOn).subtract(rule->excludedInputs); m_tagsNeededForFilesToConsider.unite(otherInputs); } else if (rule->collectedOutputFileTags().intersects(m_tagsNeededForFilesToConsider)) { FileTags allInputs = rule->inputs; allInputs.unite(rule->auxiliaryInputs).unite(rule->explicitlyDependsOn) .subtract(rule->excludedInputs); m_tagsNeededForFilesToConsider.unite(allInputs); } } /** * Walk the build graph top-down from the roots and for each reachable node N * - mark N as buildable. */ void Executor::prepareReachableNodes() { for (BuildGraphNode * const root : qAsConst(m_roots)) prepareReachableNodes_impl(root); } void Executor::prepareReachableNodes_impl(BuildGraphNode *node) { setupForBuildingSelectedFiles(node); if (node->buildState != BuildGraphNode::Untouched) return; node->buildState = BuildGraphNode::Buildable; for (BuildGraphNode *child : qAsConst(node->children)) prepareReachableNodes_impl(child); } void Executor::prepareProducts() { ProductPrioritySetter prioritySetter(m_allProducts); prioritySetter.apply(); for (const ResolvedProductPtr &product : m_productsToBuild) { EnvironmentScriptRunner(product.get(), m_evalContext.get(), m_project->environment) .setupForBuild(); } } void Executor::setupRootNodes() { m_roots.clear(); for (const ResolvedProductPtr &product : m_productsToBuild) m_roots += product->buildData->rootNodes(); } void Executor::setState(ExecutorState s) { if (m_state == s) return; m_state = s; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/executor.h000066400000000000000000000162671347155106100222720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BUILDGRAPHEXECUTOR_H #define QBS_BUILDGRAPHEXECUTOR_H #include "forward_decls.h" #include "buildgraphvisitor.h" #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QTimer; QT_END_NAMESPACE namespace qbs { class ProcessResult; namespace Internal { class ExecutorJob; class FileTime; class InputArtifactScannerContext; class ProductInstaller; class ProgressObserver; class RuleNode; class Executor : public QObject, private BuildGraphVisitor { Q_OBJECT public: void build(); Executor(const Logger &logger, QObject *parent = nullptr); ~Executor(); void setProject(const TopLevelProjectPtr &project); void setProducts(const std::vector &productsToBuild); void setBuildOptions(const BuildOptions &buildOptions); void setProgressObserver(ProgressObserver *observer) { m_progressObserver = observer; } ErrorInfo error() const { return m_error; } signals: void reportCommandDescription(const QString &highlight, const QString &message); void reportProcessResult(const qbs::ProcessResult &result); void finished(); private: void onJobFinished(const qbs::ErrorInfo &err); void finish(); void checkForCancellation(); // BuildGraphVisitor implementation bool visit(Artifact *artifact) override; bool visit(RuleNode *ruleNode) override; enum ExecutorState { ExecutorIdle, ExecutorRunning, ExecutorCanceling }; struct ComparePriority { bool operator() (const BuildGraphNode *x, const BuildGraphNode *y) const; }; using Leaves = std::priority_queue, ComparePriority>; void doBuild(); void prepareAllNodes(); void syncFileDependencies(); void prepareArtifact(Artifact *artifact); void setupForBuildingSelectedFiles(const BuildGraphNode *node); void prepareReachableNodes(); void prepareReachableNodes_impl(BuildGraphNode *node); void prepareProducts(); void setupRootNodes(); void initLeaves(); void updateLeaves(const NodeSet &nodes); void updateLeaves(BuildGraphNode *node, NodeSet &seenNodes); bool scheduleJobs(); void buildArtifact(Artifact *artifact); void executeRuleNode(RuleNode *ruleNode); void finishJob(ExecutorJob *job, bool success); void finishNode(BuildGraphNode *leaf); void finishArtifact(Artifact *artifact); void setState(ExecutorState); void addExecutorJobs(); void cancelJobs(); void setupProgressObserver(); void doSanityChecks(); void handleError(const ErrorInfo &error); void rescueOldBuildData(Artifact *artifact, bool *childrenAdded); bool checkForUnbuiltDependencies(Artifact *artifact); void potentiallyRunTransformer(const TransformerPtr &transformer); void runTransformer(const TransformerPtr &transformer); void finishTransformer(const TransformerPtr &transformer); void possiblyInstallArtifact(const Artifact *artifact); void checkForUnbuiltProducts(); bool checkNodeProduct(BuildGraphNode *node); bool mustExecuteTransformer(const TransformerPtr &transformer) const; bool isUpToDate(Artifact *artifact) const; void retrieveSourceFileTimestamp(Artifact *artifact) const; FileTime recursiveFileTime(const QString &filePath) const; QString configString() const; bool transformerHasMatchingOutputTags(const TransformerConstPtr &transformer) const; bool artifactHasMatchingOutputTags(const Artifact *artifact) const; bool transformerHasMatchingInputFiles(const TransformerConstPtr &transformer) const; void setupJobLimits(); void updateJobCounts(const Transformer *transformer, int diff); bool schedulingBlockedByJobLimit(const BuildGraphNode *node); using JobMap = QHash; JobMap m_processingJobs; ProductInstaller *m_productInstaller; RulesEvaluationContextPtr m_evalContext; BuildOptions m_buildOptions; Logger m_logger; ProgressObserver *m_progressObserver; QList m_availableJobs; ExecutorState m_state; TopLevelProjectPtr m_project; std::vector m_productsToBuild; std::vector m_allProducts; std::unordered_map m_productsByName; std::unordered_map m_projectsByName; std::unordered_map m_jobCountPerPool; std::unordered_map m_jobLimitsPerProduct; std::unordered_map m_pendingTransformersPerRule; NodeSet m_roots; Leaves m_leaves; InputArtifactScannerContext *m_inputArtifactScanContext; ErrorInfo m_error; bool m_explicitlyCanceled; FileTags m_activeFileTags; FileTags m_tagsOfFilesToConsider; FileTags m_tagsNeededForFilesToConsider; QList m_productsOfFilesToConsider; QTimer * const m_cancelationTimer; QStringList m_artifactsRemovedFromDisk; bool m_partialBuild; qint64 m_elapsedTimeRules; qint64 m_elapsedTimeScanners; qint64 m_elapsedTimeInstalling; }; } // namespace Internal } // namespace qbs #endif // QBS_BUILDGRAPHEXECUTOR_H qbs-src-1.13.1/src/lib/corelib/buildgraph/executorjob.cpp000066400000000000000000000136061347155106100233120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "executorjob.h" #include "artifact.h" #include "jscommandexecutor.h" #include "processcommandexecutor.h" #include "rulecommands.h" #include "transformer.h" #include #include #include #include namespace qbs { namespace Internal { ExecutorJob::ExecutorJob(const Logger &logger, QObject *parent) : QObject(parent) , m_processCommandExecutor(new ProcessCommandExecutor(logger, this)) , m_jsCommandExecutor(new JsCommandExecutor(logger, this)) { connect(m_processCommandExecutor, &AbstractCommandExecutor::reportCommandDescription, this, &ExecutorJob::reportCommandDescription); connect(m_processCommandExecutor, &ProcessCommandExecutor::reportProcessResult, this, &ExecutorJob::reportProcessResult); connect(m_processCommandExecutor, &AbstractCommandExecutor::finished, this, &ExecutorJob::onCommandFinished); connect(m_jsCommandExecutor, &AbstractCommandExecutor::reportCommandDescription, this, &ExecutorJob::reportCommandDescription); connect(m_jsCommandExecutor, &AbstractCommandExecutor::finished, this, &ExecutorJob::onCommandFinished); reset(); } ExecutorJob::~ExecutorJob() { } void ExecutorJob::setMainThreadScriptEngine(ScriptEngine *engine) { m_processCommandExecutor->setMainThreadScriptEngine(engine); m_jsCommandExecutor->setMainThreadScriptEngine(engine); } void ExecutorJob::setDryRun(bool enabled) { m_processCommandExecutor->setDryRunEnabled(enabled); m_jsCommandExecutor->setDryRunEnabled(enabled); } void ExecutorJob::setEchoMode(CommandEchoMode echoMode) { m_processCommandExecutor->setEchoMode(echoMode); m_jsCommandExecutor->setEchoMode(echoMode); } void ExecutorJob::run(Transformer *t) { QBS_ASSERT(m_currentCommandIdx == -1, return); if (t->commands.empty()) { setFinished(); return; } t->propertiesRequestedInCommands.clear(); t->propertiesRequestedFromArtifactInCommands.clear(); t->importedFilesUsedInCommands.clear(); t->depsRequestedInCommands.clear(); t->artifactsMapRequestedInCommands.clear(); t->exportedModulesAccessedInCommands.clear(); t->lastCommandExecutionTime = FileTime::currentTime(); QBS_CHECK(!t->outputs.empty()); m_processCommandExecutor->setProcessEnvironment( (*t->outputs.cbegin())->product->buildEnvironment); m_transformer = t; m_jobPools = t->jobPools(); runNextCommand(); } void ExecutorJob::cancel() { if (!m_currentCommandExecutor) return; m_error = ErrorInfo(tr("Transformer execution canceled.")); m_currentCommandExecutor->cancel(); } void ExecutorJob::runNextCommand() { QBS_ASSERT(m_currentCommandIdx <= m_transformer->commands.size(), return); ++m_currentCommandIdx; if (m_currentCommandIdx >= m_transformer->commands.size()) { setFinished(); return; } const AbstractCommandPtr &command = m_transformer->commands.commandAt(m_currentCommandIdx); switch (command->type()) { case AbstractCommand::ProcessCommandType: m_currentCommandExecutor = m_processCommandExecutor; break; case AbstractCommand::JavaScriptCommandType: m_currentCommandExecutor = m_jsCommandExecutor; break; default: qFatal("Missing implementation for command type %d", command->type()); } m_currentCommandExecutor->start(m_transformer, command.get()); } void ExecutorJob::onCommandFinished(const ErrorInfo &err) { QBS_ASSERT(m_transformer, return); if (m_error.hasError()) { // Canceled? setFinished(); } else if (err.hasError()) { m_error = err; setFinished(); } else { runNextCommand(); } } void ExecutorJob::setFinished() { const ErrorInfo err = m_error; reset(); emit finished(err); } void ExecutorJob::reset() { m_transformer = nullptr; m_jobPools.clear(); m_currentCommandExecutor = nullptr; m_currentCommandIdx = -1; m_error.clear(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/executorjob.h000066400000000000000000000067351347155106100227640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_EXECUTORJOB_H #define QBS_EXECUTORJOB_H #include #include #include #include #include #include namespace qbs { class CodeLocation; class ProcessResult; namespace Internal { class AbstractCommandExecutor; class ProductBuildData; class JsCommandExecutor; class Logger; class ProcessCommandExecutor; class ScriptEngine; class Transformer; class ExecutorJob : public QObject { Q_OBJECT public: ExecutorJob(const Logger &logger, QObject *parent); ~ExecutorJob(); void setMainThreadScriptEngine(ScriptEngine *engine); void setDryRun(bool enabled); void setEchoMode(CommandEchoMode echoMode); void run(Transformer *t); void cancel(); const Transformer *transformer() const { return m_transformer; } Set jobPools() const { return m_jobPools; } signals: void reportCommandDescription(const QString &highlight, const QString &message); void reportProcessResult(const qbs::ProcessResult &result); void finished(const qbs::ErrorInfo &error = ErrorInfo()); // !hasError() <=> command successful private: void runNextCommand(); void onCommandFinished(const qbs::ErrorInfo &err); void setFinished(); void reset(); AbstractCommandExecutor *m_currentCommandExecutor; ProcessCommandExecutor *m_processCommandExecutor; JsCommandExecutor *m_jsCommandExecutor; Transformer *m_transformer; Set m_jobPools; int m_currentCommandIdx; ErrorInfo m_error; }; } // namespace Internal } // namespace qbs #endif // QBS_EXECUTORJOB_H qbs-src-1.13.1/src/lib/corelib/buildgraph/filedependency.cpp000066400000000000000000000055221347155106100237350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "filedependency.h" #include namespace qbs { namespace Internal { FileResourceBase::FileResourceBase() { } FileResourceBase::~FileResourceBase() { } void FileResourceBase::setTimestamp(const FileTime &t) { m_timestamp = t; } const FileTime &FileResourceBase::timestamp() const { return m_timestamp; } void FileResourceBase::setFilePath(const QString &filePath) { m_filePath = filePath; FileInfo::splitIntoDirectoryAndFileName(m_filePath, &m_dirPath, &m_fileName); } const QString &FileResourceBase::filePath() const { return m_filePath; } void FileResourceBase::load(PersistentPool &pool) { serializationOp(pool); FileInfo::splitIntoDirectoryAndFileName(m_filePath, &m_dirPath, &m_fileName); } void FileResourceBase::store(PersistentPool &pool) { serializationOp(pool); } FileDependency::FileDependency() { } FileDependency::~FileDependency() { } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/filedependency.h000066400000000000000000000062221347155106100234000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_FILEDEPENDENCY_H #define QBS_FILEDEPENDENCY_H #include #include namespace qbs { namespace Internal { class FileResourceBase { protected: FileResourceBase(); public: virtual ~FileResourceBase(); enum FileType { FileTypeDependency, FileTypeArtifact }; virtual FileType fileType() const = 0; void setTimestamp(const FileTime &t); const FileTime ×tamp() const; void clearTimestamp() { m_timestamp.clear(); } void setFilePath(const QString &filePath); const QString &filePath() const; QString dirPath() const { return m_dirPath.toString(); } QString fileName() const { return m_fileName.toString(); } virtual void load(PersistentPool &pool); virtual void store(PersistentPool &pool); private: template void serializationOp(PersistentPool &pool) { pool.serializationOp(m_filePath, m_timestamp); } FileTime m_timestamp; QString m_filePath; QStringRef m_dirPath; QStringRef m_fileName; }; class FileDependency : public FileResourceBase { public: FileDependency(); ~FileDependency(); FileType fileType() const override { return FileTypeDependency; } }; } // namespace Internal } // namespace qbs #endif // QBS_FILEDEPENDENCY_H qbs-src-1.13.1/src/lib/corelib/buildgraph/forward_decls.h000066400000000000000000000053561347155106100232470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BG_FORWARD_DECLS_H #define QBS_BG_FORWARD_DECLS_H #include namespace qbs { namespace Internal { class Artifact; class BuildGraphNode; class ProjectBuildData; class ProductBuildData; class RuleNode; class Transformer; using TransformerPtr = std::shared_ptr; using TransformerConstPtr = std::shared_ptr; class RulesEvaluationContext; using RulesEvaluationContextPtr = std::shared_ptr; class AbstractCommand; using AbstractCommandPtr = std::shared_ptr; class ProcessCommand; using ProcessCommandPtr = std::shared_ptr; class JavaScriptCommand; using JavaScriptCommandPtr = std::shared_ptr; template class Set; using ArtifactSet = Set; using NodeSet = Set; } // namespace Internal } // namespace qbs #endif // QBS_BG_FORWARD_DECLS_H qbs-src-1.13.1/src/lib/corelib/buildgraph/inputartifactscanner.cpp000066400000000000000000000375561347155106100252220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "inputartifactscanner.h" #include "artifact.h" #include "buildgraph.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "transformer.h" #include "depscanner.h" #include "rulesevaluationcontext.h" #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static void resolveDepencency(const RawScannedDependency &dependency, const ResolvedProduct *product, ResolvedDependency *result, const QString &baseDir = QString()) { QString absDirPath = baseDir.isEmpty() ? dependency.dirPath() : dependency.dirPath().isEmpty() ? baseDir : FileInfo::resolvePath(baseDir, dependency.dirPath()); if (!dependency.isClean()) absDirPath = QDir::cleanPath(absDirPath); ResolvedProject *project = product->project.get(); FileDependency *fileDependencyArtifact = nullptr; Artifact *dependencyInProduct = nullptr; Artifact *dependencyInOtherProduct = nullptr; for (FileResourceBase *lookupResult : project->topLevelProject() ->buildData->lookupFiles(absDirPath, dependency.fileName())) { switch (lookupResult->fileType()) { case FileResourceBase::FileTypeDependency: fileDependencyArtifact = static_cast(lookupResult); break; case FileResourceBase::FileTypeArtifact: { auto const foundArtifact = static_cast(lookupResult); if (foundArtifact->product == product) dependencyInProduct = foundArtifact; else dependencyInOtherProduct = foundArtifact; break; } } if (dependencyInProduct) break; } // prioritize found artifacts if ((result->file = dependencyInProduct) || (result->file = dependencyInOtherProduct) || (result->file = fileDependencyArtifact)) { result->filePath = result->file->filePath(); return; } const QString &absFilePath = baseDir.isEmpty() ? dependency.filePath() : absDirPath + QLatin1Char('/') + dependency.fileName(); // TODO: We probably need a flag that tells us whether directories are allowed. const FileInfo fi(absFilePath); if (fi.exists(absFilePath) && !fi.isDir()) result->filePath = absFilePath; } InputArtifactScanner::InputArtifactScanner(Artifact *artifact, InputArtifactScannerContext *ctx, const Logger &logger) : m_artifact(artifact), m_rawScanResults(artifact->product->topLevelProject()->buildData->rawScanResults), m_context(ctx), m_newDependencyAdded(false), m_logger(logger) { } void InputArtifactScanner::scan() { if (m_artifact->inputsScanned) return; qCDebug(lcDepScan) << "scan inputs for" << m_artifact->filePath() << m_artifact->fileTags() << "in product" << m_artifact->product->name; m_artifact->inputsScanned = true; // clear file dependencies; they will be regenerated m_artifact->fileDependencies.clear(); // Remove all connections to children that were added by the dependency scanner. // They will be regenerated. const Set childrenAddedByScanner = m_artifact->childrenAddedByScanner; m_artifact->childrenAddedByScanner.clear(); for (Artifact * const dependency : childrenAddedByScanner) disconnect(m_artifact, dependency); for (Artifact * const inputArtifact : qAsConst(m_artifact->transformer->inputs)) scanForFileDependencies(inputArtifact); } void InputArtifactScanner::scanForFileDependencies(Artifact *inputArtifact) { qCDebug(lcDepScan) << "input artifact" << inputArtifact->filePath() << inputArtifact->fileTags(); Set visitedFilePaths; QList filesToScan; filesToScan.push_back(inputArtifact); const Set scanners = scannersForArtifact(inputArtifact); if (scanners.empty()) return; m_fileTagsForScanner = inputArtifact->fileTags().toStringList().join(QLatin1Char(',')).toLatin1(); InputArtifactScannerContext::CacheItem *lastPerFileCacheItem = nullptr; InputArtifactScannerContext::CacheItem *lastPerPropsCacheItem = nullptr; while (!filesToScan.empty()) { FileResourceBase *fileToBeScanned = filesToScan.takeFirst(); const QString &filePathToBeScanned = fileToBeScanned->filePath(); if (!visitedFilePaths.insert(filePathToBeScanned).second) continue; for (DependencyScanner * const scanner : scanners) { InputArtifactScannerContext::CacheItem *cacheItem; if (scanner->cacheIsPerFile()) { if (!lastPerFileCacheItem) lastPerFileCacheItem = &m_context->cachePerFile[inputArtifact]; cacheItem = lastPerFileCacheItem; } else { if (!lastPerPropsCacheItem) { lastPerPropsCacheItem = &m_context->cachePerProperties [inputArtifact->properties]; } cacheItem = lastPerPropsCacheItem; } scanForScannerFileDependencies(scanner, inputArtifact, fileToBeScanned, scanner->recursive() ? &filesToScan : nullptr, (*cacheItem)[scanner->key()]); } } } Set InputArtifactScanner::scannersForArtifact(const Artifact *artifact) const { Set scanners; ResolvedProduct *product = artifact->product.get(); ScriptEngine *engine = product->topLevelProject()->buildData->evaluationContext->engine(); QHash &scannerCache = m_context->scannersCache[product]; for (const FileTag &fileTag : artifact->fileTags()) { InputArtifactScannerContext::DependencyScannerCacheItem &cache = scannerCache[fileTag]; if (!cache.valid) { cache.valid = true; for (ScannerPlugin *scanner : ScannerPluginManager::scannersForFileTag(fileTag)) { const auto pluginScanner = new PluginDependencyScanner(scanner); cache.scanners.push_back(DependencyScannerPtr(pluginScanner)); } for (const ResolvedScannerConstPtr &scanner : product->scanners) { if (scanner->inputs.contains(fileTag)) { cache.scanners.push_back(DependencyScannerPtr( new UserDependencyScanner(scanner, engine))); break; } } } for (const DependencyScannerPtr &scanner : qAsConst(cache.scanners)) scanners += scanner.get(); } return scanners; } void InputArtifactScanner::scanForScannerFileDependencies(DependencyScanner *scanner, Artifact *inputArtifact, FileResourceBase *fileToBeScanned, QList *filesToScan, InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache) { qCDebug(lcDepScan) << "file" << fileToBeScanned->filePath(); const bool cacheHit = cache.valid; if (!cacheHit) { cache.valid = true; cache.searchPaths = scanner->collectSearchPaths(inputArtifact); } qCDebug(lcDepScan) << "include paths (cache" << (cacheHit ? "hit)" : "miss)"); for (const QString &s : qAsConst(cache.searchPaths)) qCDebug(lcDepScan) << " " << s; const QString &filePathToBeScanned = fileToBeScanned->filePath(); RawScanResults::ScanData &scanData = m_rawScanResults.findScanData(fileToBeScanned, scanner, m_artifact->properties); if (scanData.lastScanTime < fileToBeScanned->timestamp()) { try { qCDebug(lcDepScan) << "scanning" << FileInfo::fileName(filePathToBeScanned); scanWithScannerPlugin(scanner, fileToBeScanned, &scanData.rawScanResult); scanData.lastScanTime = FileTime::currentTime(); } catch (const ErrorInfo &error) { m_logger.printWarning(error); return; } } resolveScanResultDependencies(inputArtifact, scanData.rawScanResult, filesToScan, cache); } void InputArtifactScanner::resolveScanResultDependencies(const Artifact *inputArtifact, const RawScanResult &scanResult, QList *artifactsToScan, InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache) { for (const RawScannedDependency &dependency : scanResult.deps) { const QString &dependencyFilePath = dependency.filePath(); InputArtifactScannerContext::ResolvedDependencyCacheItem &cachedResolvedDependencyItem = cache.resolvedDependenciesCache[dependency.dirPath()][dependency.fileName()]; ResolvedDependency &resolvedDependency = cachedResolvedDependencyItem.resolvedDependency; if (cachedResolvedDependencyItem.valid) { if (resolvedDependency.filePath.isEmpty()) goto unresolved; goto resolved; } cachedResolvedDependencyItem.valid = true; if (FileInfo::isAbsolute(dependencyFilePath)) { resolveDepencency(dependency, inputArtifact->product.get(), &resolvedDependency); if (resolvedDependency.filePath.isEmpty()) goto unresolved; goto resolved; } // try include paths for (const QString &includePath : cache.searchPaths) { resolveDepencency(dependency, inputArtifact->product.get(), &resolvedDependency, includePath); if (resolvedDependency.isValid()) goto resolved; } unresolved: qCWarning(lcDepScan) << "unresolved dependency " << dependencyFilePath; continue; resolved: handleDependency(resolvedDependency); if (artifactsToScan && resolvedDependency.file) { if (resolvedDependency.file->fileType() == FileResourceBase::FileTypeArtifact) { // Do not scan an artifact that is not built yet: Its contents might still change. auto const artifactDependency = static_cast(resolvedDependency.file); if (artifactDependency->artifactType == Artifact::SourceFile || artifactDependency->buildState == BuildGraphNode::Built) { artifactsToScan->push_back(artifactDependency); } } else { // Add file dependency to the next round of scanning. artifactsToScan->push_back(resolvedDependency.file); } } } } void InputArtifactScanner::handleDependency(ResolvedDependency &dependency) { const ResolvedProductPtr product = m_artifact->product.lock(); QBS_CHECK(m_artifact->artifactType == Artifact::Generated); QBS_CHECK(product); Artifact *artifactDependency = nullptr; FileDependency *fileDependency = nullptr; if (dependency.file) { switch (dependency.file->fileType()) { case FileResourceBase::FileTypeArtifact: artifactDependency = static_cast(dependency.file); break; case FileResourceBase::FileTypeDependency: fileDependency = static_cast(dependency.file); break; } } QBS_CHECK(!dependency.file || artifactDependency || fileDependency); if (!dependency.file) { // The dependency is an existing file but does not exist in the build graph. qCDebug(lcDepScan) << "add new file dependency" << dependency.filePath; fileDependency = new FileDependency(); dependency.file = fileDependency; fileDependency->setFilePath(dependency.filePath); product->topLevelProject()->buildData->insertFileDependency(fileDependency); } else if (fileDependency) { // The dependency exists in the project's list of file dependencies. qCDebug(lcDepScan) << "add existing file dependency" << dependency.filePath; } else if (artifactDependency->product == product) { // The dependency is in our product. qCDebug(lcDepScan) << "add artifact dependency" << dependency.filePath << "(from this product)"; } else { // The dependency is in some other product. ResolvedProduct * const otherProduct = artifactDependency->product; qCDebug(lcDepScan) << "add artifact dependency" << dependency.filePath << " (from product" << otherProduct->uniqueName() << ')'; } if (m_artifact == dependency.file) return; if (fileDependency) { m_artifact->fileDependencies << fileDependency; if (!fileDependency->timestamp().isValid()) fileDependency->setTimestamp(FileInfo(fileDependency->filePath()).lastModified()); } else { if (m_artifact->children.contains(artifactDependency)) return; if (safeConnect(m_artifact, artifactDependency)) m_artifact->childrenAddedByScanner += artifactDependency; m_newDependencyAdded = true; } } void InputArtifactScanner::scanWithScannerPlugin(DependencyScanner *scanner, FileResourceBase *fileToBeScanned, RawScanResult *scanResult) { scanResult->deps.clear(); const QStringList &dependencies = scanner->collectDependencies( m_artifact, fileToBeScanned, m_fileTagsForScanner.constData()); for (const QString &s : dependencies) scanResult->deps.push_back(RawScannedDependency(s)); } InputArtifactScannerContext::DependencyScannerCacheItem::DependencyScannerCacheItem() : valid(false) { } InputArtifactScannerContext::DependencyScannerCacheItem::~DependencyScannerCacheItem() { } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/inputartifactscanner.h000066400000000000000000000117331347155106100246540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_INPUTARTIFACTSCANNER_H #define QBS_INPUTARTIFACTSCANNER_H #include #include #include #include #include #include class ScannerPlugin; namespace qbs { namespace Internal { class Artifact; class FileResourceBase; class RawScanResult; class RawScanResults; class PropertyMapInternal; class DependencyScanner; using DependencyScannerPtr = std::shared_ptr; class ResolvedDependency { public: bool isValid() const { return !filePath.isNull(); } QString filePath; FileResourceBase *file = nullptr; }; class InputArtifactScannerContext { struct ResolvedDependencyCacheItem { ResolvedDependencyCacheItem() : valid(false) {} bool valid; ResolvedDependency resolvedDependency; }; using ResolvedDependenciesCache = QHash>; struct ScannerResolvedDependenciesCache { ScannerResolvedDependenciesCache() : valid(false) {} bool valid; QStringList searchPaths; ResolvedDependenciesCache resolvedDependenciesCache; }; struct DependencyScannerCacheItem { DependencyScannerCacheItem(); ~DependencyScannerCacheItem(); bool valid; QList scanners; }; using CacheItem = QHash; QHash cachePerProperties; QHash cachePerFile; QHash> scannersCache; friend class InputArtifactScanner; }; class InputArtifactScanner { public: InputArtifactScanner(Artifact *artifact, InputArtifactScannerContext *ctx, const Logger &logger); void scan(); bool newDependencyAdded() const { return m_newDependencyAdded; } private: void scanForFileDependencies(Artifact *inputArtifact); Set scannersForArtifact(const Artifact *artifact) const; void scanForScannerFileDependencies(DependencyScanner *scanner, Artifact *inputArtifact, FileResourceBase *fileToBeScanned, QList *filesToScan, InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache); void resolveScanResultDependencies(const Artifact *inputArtifact, const RawScanResult &scanResult, QList *artifactsToScan, InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache); void handleDependency(ResolvedDependency &dependency); void scanWithScannerPlugin(DependencyScanner *scanner, FileResourceBase *fileToBeScanned, RawScanResult *scanResult); Artifact * const m_artifact; RawScanResults &m_rawScanResults; InputArtifactScannerContext *const m_context; QByteArray m_fileTagsForScanner; bool m_newDependencyAdded; Logger m_logger; }; } // namespace Internal } // namespace qbs #endif // QBS_INPUTARTIFACTSCANNER_H qbs-src-1.13.1/src/lib/corelib/buildgraph/jscommandexecutor.cpp000066400000000000000000000227171347155106100245160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "jscommandexecutor.h" #include "artifact.h" #include "buildgraph.h" #include "rulecommands.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { struct JavaScriptCommandResult { bool success; QString errorMessage; CodeLocation errorLocation; }; class JsCommandExecutorThreadObject : public QObject { Q_OBJECT public: JsCommandExecutorThreadObject(const Logger &logger) : m_logger(logger) , m_scriptEngine(nullptr) { } const JavaScriptCommandResult &result() const { return m_result; } void cancel() { QBS_ASSERT(m_scriptEngine, return); m_scriptEngine->abortEvaluation(); } signals: void finished(); public: void start(const JavaScriptCommand *cmd, Transformer *transformer) { m_running = true; try { doStart(cmd, transformer); } catch (const qbs::ErrorInfo &error) { setError(error.toString(), cmd->codeLocation()); } m_running = false; emit finished(); } private: void doStart(const JavaScriptCommand *cmd, Transformer *transformer) { m_result.success = true; m_result.errorMessage.clear(); ScriptEngine * const scriptEngine = provideScriptEngine(); QScriptValue scope = scriptEngine->newObject(); scope.setPrototype(scriptEngine->globalObject()); m_scriptEngine->clearRequestedProperties(); setupScriptEngineForFile(scriptEngine, transformer->rule->prepareScript.fileContext(), scope, ObserveMode::Enabled); QScriptValue importScopeForSourceCode; if (!cmd->scopeName().isEmpty()) importScopeForSourceCode = scope.property(cmd->scopeName()); setupScriptEngineForProduct(scriptEngine, transformer->product().get(), transformer->rule->module.get(), scope, true); transformer->setupInputs(scope); transformer->setupOutputs(scope); transformer->setupExplicitlyDependsOn(scope); for (QVariantMap::const_iterator it = cmd->properties().constBegin(); it != cmd->properties().constEnd(); ++it) { scope.setProperty(it.key(), scriptEngine->toScriptValue(it.value())); } scriptEngine->setGlobalObject(scope); if (importScopeForSourceCode.isObject()) scriptEngine->currentContext()->pushScope(importScopeForSourceCode); scriptEngine->evaluate(cmd->sourceCode()); scriptEngine->releaseResourcesOfScriptObjects(); if (importScopeForSourceCode.isObject()) scriptEngine->currentContext()->popScope(); scriptEngine->setGlobalObject(scope.prototype()); transformer->propertiesRequestedInCommands += scriptEngine->propertiesRequestedInScript(); transformer->propertiesRequestedFromArtifactInCommands .unite(scriptEngine->propertiesRequestedFromArtifact()); const std::vector &importFilesUsedInCommand = scriptEngine->importedFilesUsedInScript(); transformer->importedFilesUsedInCommands.insert( transformer->importedFilesUsedInCommands.cend(), importFilesUsedInCommand.cbegin(), importFilesUsedInCommand.cend()); transformer->depsRequestedInCommands.add(scriptEngine->productsWithRequestedDependencies()); transformer->artifactsMapRequestedInCommands.unite(scriptEngine->requestedArtifacts()); for (const ResolvedProduct * const p : scriptEngine->requestedExports()) { transformer->exportedModulesAccessedInCommands.insert( std::make_pair(p->uniqueName(), p->exportedModule)); } scriptEngine->clearRequestedProperties(); if (scriptEngine->hasUncaughtException()) { // ### We don't know the line number of the command's sourceCode property assignment. setError(scriptEngine->uncaughtException().toString(), cmd->codeLocation()); } } void setError(const QString &errorMessage, const CodeLocation &codeLocation) { m_result.success = false; m_result.errorMessage = errorMessage; m_result.errorLocation = codeLocation; } ScriptEngine *provideScriptEngine() { if (!m_scriptEngine) m_scriptEngine = ScriptEngine::create(m_logger, EvalContext::JsCommand, this); return m_scriptEngine; } Logger m_logger; ScriptEngine *m_scriptEngine; JavaScriptCommandResult m_result; bool m_running = false; }; JsCommandExecutor::JsCommandExecutor(const Logger &logger, QObject *parent) : AbstractCommandExecutor(logger, parent) , m_thread(new QThread(this)) , m_objectInThread(new JsCommandExecutorThreadObject(logger)) , m_running(false) { m_objectInThread->moveToThread(m_thread); connect(m_objectInThread, &JsCommandExecutorThreadObject::finished, this, &JsCommandExecutor::onJavaScriptCommandFinished); connect(this, &JsCommandExecutor::startRequested, m_objectInThread, &JsCommandExecutorThreadObject::start); } JsCommandExecutor::~JsCommandExecutor() { waitForFinished(); delete m_objectInThread; m_thread->quit(); m_thread->wait(); } void JsCommandExecutor::doReportCommandDescription(const QString &productName) { if ((m_echoMode == CommandEchoModeCommandLine || m_echoMode == CommandEchoModeCommandLineWithEnvironment) && !command()->extendedDescription().isEmpty()) { emit reportCommandDescription(command()->highlight(), command()->extendedDescription()); return; } AbstractCommandExecutor::doReportCommandDescription(productName); } void JsCommandExecutor::waitForFinished() { if (!m_running) return; QEventLoop loop; connect(m_objectInThread, &JsCommandExecutorThreadObject::finished, &loop, &QEventLoop::quit); loop.exec(); } void JsCommandExecutor::doStart() { QBS_ASSERT(!m_running, return); m_thread->start(); if (dryRun() && !command()->ignoreDryRun()) { QTimer::singleShot(0, this, [this] { emit finished(); }); // Don't call back on the caller. return; } m_running = true; emit startRequested(jsCommand(), transformer()); } void JsCommandExecutor::cancel() { if (m_running && !dryRun()) QTimer::singleShot(0, m_objectInThread, [this] { m_objectInThread->cancel(); }); } void JsCommandExecutor::onJavaScriptCommandFinished() { m_running = false; const JavaScriptCommandResult &result = m_objectInThread->result(); ErrorInfo err; if (!result.success) { logger().qbsDebug() << "JS context:\n" << jsCommand()->properties(); logger().qbsDebug() << "JS code:\n" << jsCommand()->sourceCode(); err.append(result.errorMessage); // ### We don't know the line number of the command's sourceCode property assignment. err.appendBacktrace(QStringLiteral("JavaScriptCommand.sourceCode")); err.appendBacktrace(QStringLiteral("Rule.prepare"), result.errorLocation); } emit finished(err); } const JavaScriptCommand *JsCommandExecutor::jsCommand() const { return static_cast(command()); } } // namespace Internal } // namespace qbs #include "jscommandexecutor.moc" qbs-src-1.13.1/src/lib/corelib/buildgraph/jscommandexecutor.h000066400000000000000000000054531347155106100241610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_JSCOMMANDEXECUTOR_H #define QBS_JSCOMMANDEXECUTOR_H #include "abstractcommandexecutor.h" #include namespace qbs { class CodeLocation; namespace Internal { class JavaScriptCommand; class JsCommandExecutorThreadObject; class JsCommandExecutor : public AbstractCommandExecutor { Q_OBJECT public: explicit JsCommandExecutor(const Logger &logger, QObject *parent = nullptr); ~JsCommandExecutor(); signals: void startRequested(const JavaScriptCommand *cmd, Transformer *transformer); private: void onJavaScriptCommandFinished(); void doReportCommandDescription(const QString &productName) override; void doStart() override; void cancel() override; void waitForFinished(); const JavaScriptCommand *jsCommand() const; QThread *m_thread; JsCommandExecutorThreadObject *m_objectInThread; bool m_running; }; } // namespace Internal } // namespace qbs #endif // QBS_JSCOMMANDEXECUTOR_H qbs-src-1.13.1/src/lib/corelib/buildgraph/nodeset.cpp000066400000000000000000000051641347155106100224220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "nodeset.h" #include "artifact.h" #include "rulenode.h" #include #include namespace qbs { namespace Internal { BuildGraphNode *loadBuildGraphNode(PersistentPool &pool) { const auto t = pool.load(); BuildGraphNode *node = nullptr; switch (static_cast(t)) { case BuildGraphNode::ArtifactNodeType: node = pool.load(); break; case BuildGraphNode::RuleNodeType: node = pool.load(); break; } QBS_CHECK(node); return node; } void storeBuildGraphNode(PersistentPool &pool, const BuildGraphNode *node) { pool.store(static_cast(node->type())); pool.store(node); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/nodeset.h000066400000000000000000000076011347155106100220650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_NODESET_H #define QBS_NODESET_H #include #include namespace qbs { namespace Internal { class BuildGraphNode; BuildGraphNode *loadBuildGraphNode(PersistentPool &pool); void storeBuildGraphNode(PersistentPool &pool, const BuildGraphNode *node); using NodeSet = Set; template<> inline BuildGraphNode *NodeSet::loadElem(PersistentPool &pool) { return loadBuildGraphNode(pool); } template<> inline void NodeSet::storeElem(PersistentPool &pool, BuildGraphNode * const &node) const { storeBuildGraphNode(pool, node); } template class TypeFilter { const NodeSet &m_nodes; public: TypeFilter(const NodeSet &nodes) : m_nodes(nodes) { } class const_iterator : public std::iterator { const NodeSet &m_nodes; NodeSet::const_iterator m_it; public: const_iterator(const NodeSet &nodes, const NodeSet::const_iterator &it) : m_nodes(nodes), m_it(it) { while (m_it != m_nodes.constEnd() && !hasDynamicType(*m_it)) ++m_it; } bool operator==(const const_iterator &rhs) { return m_it == rhs.m_it; } bool operator!=(const const_iterator &rhs) { return !(*this == rhs); } const_iterator &operator++() { for (;;) { ++m_it; if (m_it == m_nodes.constEnd() || hasDynamicType(*m_it)) return *this; } } T *operator*() const { return static_cast(*m_it); } }; const_iterator begin() const { return const_iterator(m_nodes, m_nodes.constBegin()); } const_iterator end() const { return const_iterator(m_nodes, m_nodes.constEnd()); } }; template const TypeFilter filterByType(const NodeSet &nodes) { return TypeFilter(nodes); } } // namespace Internal } // namespace qbs #endif // QBS_NODESET_H qbs-src-1.13.1/src/lib/corelib/buildgraph/nodetreedumper.cpp000066400000000000000000000071701347155106100240020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "nodetreedumper.h" #include "artifact.h" #include "productbuilddata.h" #include "rulenode.h" #include #include #include namespace qbs { namespace Internal { static unsigned int indentWidth() { return 4; } NodeTreeDumper::NodeTreeDumper(QIODevice &outDevice) : m_outDevice(outDevice) { } void NodeTreeDumper::start(const QList &products) { m_indentation = 0; for (const ResolvedProductPtr &p : products) { if (!p->buildData) continue; m_currentProduct = p; for (Artifact * const root : p->buildData->rootArtifacts()) root->accept(this); m_visited.clear(); QBS_CHECK(m_indentation == 0); } } bool NodeTreeDumper::visit(Artifact *artifact) { return doVisit(artifact, artifact->fileName()); } void NodeTreeDumper::endVisit(Artifact *artifact) { Q_UNUSED(artifact); doEndVisit(); } bool NodeTreeDumper::visit(RuleNode *rule) { return doVisit(rule, rule->toString()); } void NodeTreeDumper::endVisit(RuleNode *rule) { Q_UNUSED(rule); doEndVisit(); } void NodeTreeDumper::doEndVisit() { unindent(); } void NodeTreeDumper::indent() { m_outDevice.write("\n"); m_indentation += indentWidth(); } void NodeTreeDumper::unindent() { m_indentation -= indentWidth(); } bool NodeTreeDumper::doVisit(BuildGraphNode *node, const QString &nodeRepr) { m_outDevice.write(indentation()); m_outDevice.write(nodeRepr.toLocal8Bit()); indent(); const bool wasVisited = !m_visited.insert(node).second; return !wasVisited && node->product == m_currentProduct; } QByteArray NodeTreeDumper::indentation() const { return QByteArray(m_indentation, ' '); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/nodetreedumper.h000066400000000000000000000054631347155106100234520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_NODETREEDUMPER_H #define QBS_NODETREEDUMPER_H #include "artifact.h" #include "buildgraphvisitor.h" #include #include QT_BEGIN_NAMESPACE class QIODevice; QT_END_NAMESPACE namespace qbs { namespace Internal { class NodeTreeDumper : public BuildGraphVisitor { public: NodeTreeDumper(QIODevice &outDevice); void start(const QList &products); private: bool visit(Artifact *artifact) override; void endVisit(Artifact *artifact) override; bool visit(RuleNode *rule) override; void endVisit(RuleNode *rule) override; void doEndVisit(); void indent(); void unindent(); bool doVisit(BuildGraphNode *node, const QString &nodeRepr); QByteArray indentation() const; QIODevice &m_outDevice; ResolvedProductPtr m_currentProduct; NodeSet m_visited; unsigned int m_indentation; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/buildgraph/processcommandexecutor.cpp000066400000000000000000000403631347155106100255550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "processcommandexecutor.h" #include "artifact.h" #include "rulecommands.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { ProcessCommandExecutor::ProcessCommandExecutor(const Logger &logger, QObject *parent) : AbstractCommandExecutor(logger, parent) { connect(&m_process, static_cast(&QbsProcess::error), this, &ProcessCommandExecutor::onProcessError); connect(&m_process, static_cast(&QbsProcess::finished), this, &ProcessCommandExecutor::onProcessFinished); } static QProcessEnvironment mergeEnvironments(const QProcessEnvironment &baseEnv, const QProcessEnvironment &additionalEnv) { QProcessEnvironment env = baseEnv; static const QStringList pathListVariables{ StringConstants::pathEnvVar(), QStringLiteral("LD_LIBRARY_PATH"), QStringLiteral("DYLD_LIBRARY_PATH"), QStringLiteral("DYLD_FRAMEWORK_PATH"), }; for (const QString &key : additionalEnv.keys()) { QString newValue = additionalEnv.value(key); if (pathListVariables.contains(key, HostOsInfo::fileNameCaseSensitivity())) { const QString &oldValue = baseEnv.value(key); if (!oldValue.isEmpty()) newValue.append(HostOsInfo::pathListSeparator()).append(oldValue); } env.insert(key, newValue); } return env; } void ProcessCommandExecutor::doSetup() { ProcessCommand * const cmd = processCommand(); const QString program = ExecutableFinder(transformer()->product(), transformer()->product()->buildEnvironment) .findExecutable(cmd->program(), cmd->workingDir()); cmd->clearRelevantEnvValues(); for (const QString &key : cmd->relevantEnvVars()) cmd->addRelevantEnvValue(key, transformer()->product()->buildEnvironment.value(key)); m_commandEnvironment = mergeEnvironments(m_buildEnvironment, cmd->environment()); m_program = program; m_arguments = cmd->arguments(); m_shellInvocation = shellQuote(QDir::toNativeSeparators(m_program), m_arguments); } void ProcessCommandExecutor::doStart() { QBS_ASSERT(m_process.state() == QProcess::NotRunning, return); const ProcessCommand * const cmd = processCommand(); m_process.setProcessEnvironment(m_commandEnvironment); QStringList arguments = m_arguments; if (dryRun() && !cmd->ignoreDryRun()) { QTimer::singleShot(0, this, [this] { emit finished(); }); // Don't call back on the caller. return; } const QString workingDir = QDir::fromNativeSeparators(cmd->workingDir()); if (!workingDir.isEmpty()) { FileInfo fi(workingDir); if (!fi.exists() || !fi.isDir()) { emit finished(ErrorInfo(Tr::tr("The working directory '%1' for process '%2' " "is invalid.").arg(QDir::toNativeSeparators(workingDir), QDir::toNativeSeparators(m_program)), cmd->codeLocation())); return; } } // Automatically use response files, if the command line gets to long. if (!cmd->responseFileUsagePrefix().isEmpty()) { const int commandLineLength = m_shellInvocation.length(); if (cmd->responseFileThreshold() >= 0 && commandLineLength > cmd->responseFileThreshold()) { qCDebug(lcExec) << QString::fromUtf8("Using response file. " "Threshold is %1. Command line length %2.") .arg(cmd->responseFileThreshold()).arg(commandLineLength); // The QTemporaryFile keeps a handle on the file, even if closed. // On Windows, some commands (e.g. msvc link.exe) won't accept that. // We need to delete the file manually, later. QTemporaryFile responseFile; responseFile.setAutoRemove(false); responseFile.setFileTemplate(QDir::tempPath() + QLatin1String("/qbsresp")); if (!responseFile.open()) { emit finished(ErrorInfo(Tr::tr("Cannot create response file '%1'.") .arg(responseFile.fileName()))); return; } for (int i = cmd->responseFileArgumentIndex(); i < cmd->arguments().size(); ++i) { const QString arg = cmd->arguments().at(i); if (arg.startsWith(cmd->responseFileUsagePrefix())) { QFile f(arg.mid(cmd->responseFileUsagePrefix().size())); if (!f.open(QIODevice::ReadOnly)) { emit finished(ErrorInfo(Tr::tr("Cannot open command file '%1'.") .arg(QDir::toNativeSeparators(f.fileName())))); return; } responseFile.write(f.readAll()); } else { responseFile.write(qbs::Internal::shellQuote(arg).toLocal8Bit()); } responseFile.write("\n"); } responseFile.close(); m_responseFileName = responseFile.fileName(); arguments = arguments.mid(0, std::min(cmd->responseFileArgumentIndex(), arguments.size())); arguments += QDir::toNativeSeparators(cmd->responseFileUsagePrefix() + responseFile.fileName()); } } qCDebug(lcExec) << "Running external process; full command line is:" << m_shellInvocation; const QProcessEnvironment &additionalVariables = cmd->environment(); qCDebug(lcExec) << "Additional environment:" << additionalVariables.toStringList(); m_process.setWorkingDirectory(workingDir); m_process.start(m_program, arguments); } void ProcessCommandExecutor::cancel() { // We don't want this command to be reported as failing, since we explicitly terminated it. disconnect(this, &ProcessCommandExecutor::reportProcessResult, nullptr, nullptr); m_process.cancel(); } QString ProcessCommandExecutor::filterProcessOutput(const QByteArray &_output, const QString &filterFunctionSource) { const QString output = QString::fromLocal8Bit(_output); if (filterFunctionSource.isEmpty()) return output; QScriptValue scope = scriptEngine()->newObject(); scope.setPrototype(scriptEngine()->globalObject()); for (QVariantMap::const_iterator it = command()->properties().constBegin(); it != command()->properties().constEnd(); ++it) { scope.setProperty(it.key(), scriptEngine()->toScriptValue(it.value())); } TemporaryGlobalObjectSetter tgos(scope); QScriptValue filterFunction = scriptEngine()->evaluate(QLatin1String("var f = ") + filterFunctionSource + QLatin1String("; f")); if (!filterFunction.isFunction()) { logger().printWarning(ErrorInfo(Tr::tr("Error in filter function: %1.\n%2") .arg(filterFunctionSource, filterFunction.toString()))); return output; } QScriptValue outputArg = scriptEngine()->newArray(1); outputArg.setProperty(0, scriptEngine()->toScriptValue(output)); QScriptValue filteredOutput = filterFunction.call(scriptEngine()->undefinedValue(), outputArg); if (scriptEngine()->hasErrorOrException(filteredOutput)) { logger().printWarning(ErrorInfo(Tr::tr("Error when calling output filter function: %1") .arg(scriptEngine()->lastErrorString(filteredOutput)), scriptEngine()->lastErrorLocation(filteredOutput))); return output; } return filteredOutput.toString(); } static QProcess::ProcessError saveToFile(const QString &filePath, const QByteArray &content) { QBS_ASSERT(!filePath.isEmpty(), return QProcess::WriteError); QFile f(filePath); if (!f.open(QIODevice::WriteOnly)) return QProcess::WriteError; if (f.write(content) != content.size()) return QProcess::WriteError; f.close(); return f.error() == QFileDevice::NoError ? QProcess::UnknownError : QProcess::WriteError; } void ProcessCommandExecutor::getProcessOutput(bool stdOut, ProcessResult &result) { QByteArray content; QString filterFunction; QString redirectPath; QStringList *target; if (stdOut) { content = m_process.readAllStandardOutput(); filterFunction = processCommand()->stdoutFilterFunction(); redirectPath = processCommand()->stdoutFilePath(); target = &result.d->stdOut; } else { content = m_process.readAllStandardError(); filterFunction = processCommand()->stderrFilterFunction(); redirectPath = processCommand()->stderrFilePath(); target = &result.d->stdErr; } QString contentString = filterProcessOutput(content, filterFunction); if (!redirectPath.isEmpty()) { const QProcess::ProcessError error = saveToFile(redirectPath, contentString.toLocal8Bit()); if (result.error() == QProcess::UnknownError && error != QProcess::UnknownError) result.d->error = error; } else { if (!contentString.isEmpty() && contentString.endsWith(QLatin1Char('\n'))) contentString.chop(1); *target = contentString.split(QLatin1Char('\n'), QString::SkipEmptyParts); } } void ProcessCommandExecutor::sendProcessOutput() { ProcessResult result; result.d->executableFilePath = m_program; result.d->arguments = m_arguments; result.d->workingDirectory = m_process.workingDirectory(); if (result.workingDirectory().isEmpty()) result.d->workingDirectory = QDir::currentPath(); result.d->exitCode = m_process.exitCode(); result.d->error = m_process.error(); QString errorString = m_process.errorString(); getProcessOutput(true, result); getProcessOutput(false, result); const bool processError = result.error() != QProcess::UnknownError; const bool failureExit = quint32(m_process.exitCode()) > quint32(processCommand()->maxExitCode()); result.d->success = !processError && !failureExit; emit reportProcessResult(result); if (Q_UNLIKELY(processError)) { emit finished(ErrorInfo(errorString)); } else if (Q_UNLIKELY(failureExit)) { emit finished(ErrorInfo(Tr::tr("Process failed with exit code %1.") .arg(m_process.exitCode()))); } else { emit finished(); } } void ProcessCommandExecutor::onProcessError() { if (scriptEngine()->isActive()) { qCDebug(lcExec) << "Command error while rule execution is pausing. " "Delaying slot execution."; QTimer::singleShot(0, this, &ProcessCommandExecutor::onProcessError); return; } switch (m_process.error()) { case QProcess::FailedToStart: { removeResponseFile(); const QString binary = QDir::toNativeSeparators(processCommand()->program()); QString errorPrefixString; #ifdef Q_OS_UNIX if (QFileInfo(binary).isExecutable()) { const QString interpreter(shellInterpreter(binary)); if (!interpreter.isEmpty()) { errorPrefixString = Tr::tr("%1: bad interpreter: ").arg(interpreter); } } #endif emit finished(ErrorInfo(Tr::tr("The process '%1' could not be started: %2. " "The full command line invocation was: %3") .arg(binary, errorPrefixString + m_process.errorString(), m_shellInvocation))); break; } case QProcess::Crashed: break; // Ignore. Will be handled by onProcessFinished(). default: logger().qbsWarning() << "QProcess error: " << m_process.errorString(); } } void ProcessCommandExecutor::onProcessFinished() { if (scriptEngine()->isActive()) { qCDebug(lcExec) << "Command finished while rule execution is pausing. " "Delaying slot execution."; QTimer::singleShot(0, this, &ProcessCommandExecutor::onProcessFinished); return; } removeResponseFile(); sendProcessOutput(); } static QString environmentVariableString(const QString &key, const QString &value) { QString str; if (HostOsInfo::isWindowsHost()) str += QStringLiteral("set "); str += shellQuote(key + QLatin1Char('=') + value); if (HostOsInfo::isWindowsHost()) str += QLatin1Char('\n'); else str += QLatin1Char(' '); return str; } void ProcessCommandExecutor::doReportCommandDescription(const QString &productName) { if (m_echoMode == CommandEchoModeCommandLine || m_echoMode == CommandEchoModeCommandLineWithEnvironment) { QString fullInvocation; if (m_echoMode == CommandEchoModeCommandLineWithEnvironment) { QStringList keys = m_commandEnvironment.keys(); keys.sort(); for (const QString &key : keys) fullInvocation += environmentVariableString(key, m_commandEnvironment.value(key)); } fullInvocation += m_shellInvocation; emit reportCommandDescription(command()->highlight(), !command()->extendedDescription().isEmpty() ? command()->extendedDescription() : fullInvocation); return; } AbstractCommandExecutor::doReportCommandDescription(productName); } void ProcessCommandExecutor::removeResponseFile() { if (m_responseFileName.isEmpty()) return; QFile::remove(m_responseFileName); m_responseFileName.clear(); } ProcessCommand *ProcessCommandExecutor::processCommand() const { return static_cast(command()); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/processcommandexecutor.h000066400000000000000000000064761347155106100252310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROCESSCOMMANDEXECUTOR_H #define QBS_PROCESSCOMMANDEXECUTOR_H #include "abstractcommandexecutor.h" #include #include namespace qbs { class ProcessResult; namespace Internal { class ProcessCommand; class ProcessCommandExecutor : public AbstractCommandExecutor { Q_OBJECT public: explicit ProcessCommandExecutor(const Internal::Logger &logger, QObject *parent = nullptr); void setProcessEnvironment(const QProcessEnvironment &processEnvironment) { m_buildEnvironment = processEnvironment; } signals: void reportProcessResult(const qbs::ProcessResult &result); private: void onProcessError(); void onProcessFinished(); void doSetup() override; void doReportCommandDescription(const QString &productName) override; void doStart() override; void cancel() override; void startProcessCommand(); QString filterProcessOutput(const QByteArray &output, const QString &filterFunctionSource); void getProcessOutput(bool stdOut, ProcessResult &result); void sendProcessOutput(); void removeResponseFile(); ProcessCommand *processCommand() const; private: QString m_program; QStringList m_arguments; QString m_shellInvocation; QbsProcess m_process; QProcessEnvironment m_buildEnvironment; QProcessEnvironment m_commandEnvironment; QString m_responseFileName; }; } // namespace Internal } // namespace qbs #endif // QBS_PROCESSCOMMANDEXECUTOR_H qbs-src-1.13.1/src/lib/corelib/buildgraph/productbuilddata.cpp000066400000000000000000000110351347155106100243050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "productbuilddata.h" #include "artifact.h" #include "projectbuilddata.h" #include "rulecommands.h" #include #include #include #include namespace qbs { namespace Internal { ProductBuildData::~ProductBuildData() { qDeleteAll(m_nodes); } const TypeFilter ProductBuildData::rootArtifacts() const { return TypeFilter(m_roots); } void ProductBuildData::addArtifact(Artifact *artifact) { QBS_CHECK(m_nodes.insert(artifact).second); addArtifactToSet(artifact); } void ProductBuildData::addArtifactToSet(Artifact *artifact) { std::lock_guard l(m_artifactsMapMutex); for (const FileTag &tag : artifact->fileTags()) { m_artifactsByFileTag[tag] += artifact; m_jsArtifactsMapUpToDate = false; } } void ProductBuildData::removeArtifact(Artifact *artifact) { m_roots.remove(artifact); m_nodes.remove(artifact); removeArtifactFromSet(artifact); } void ProductBuildData::removeArtifactFromSetByFileTag(Artifact *artifact, const FileTag &fileTag) { std::lock_guard l(m_artifactsMapMutex); const auto it = m_artifactsByFileTag.find(fileTag); if (it == m_artifactsByFileTag.end()) return; it->remove(artifact); if (it->empty()) m_artifactsByFileTag.erase(it); m_jsArtifactsMapUpToDate = false; } void ProductBuildData::addFileTagToArtifact(Artifact *artifact, const FileTag &tag) { std::lock_guard l(m_artifactsMapMutex); m_artifactsByFileTag[tag] += artifact; m_jsArtifactsMapUpToDate = false; } ArtifactSetByFileTag ProductBuildData::artifactsByFileTag() const { std::lock_guard l(m_artifactsMapMutex); return m_artifactsByFileTag; } void ProductBuildData::setRescuableArtifactData(const AllRescuableArtifactData &rad) { m_rescuableArtifactData = rad; } RescuableArtifactData ProductBuildData::removeFromRescuableArtifactData(const QString &filePath) { return m_rescuableArtifactData.take(filePath); } void ProductBuildData::addRescuableArtifactData(const QString &filePath, const RescuableArtifactData &rad) { m_rescuableArtifactData.insert(filePath, rad); } bool ProductBuildData::checkAndSetJsArtifactsMapUpToDateFlag() { std::lock_guard l(m_artifactsMapMutex); if (!m_jsArtifactsMapUpToDate) { m_jsArtifactsMapUpToDate = true; return false; } return true; } void ProductBuildData::removeArtifactFromSet(Artifact *artifact) { for (const FileTag &t : artifact->fileTags()) removeArtifactFromSetByFileTag(artifact, t); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/productbuilddata.h000066400000000000000000000110671347155106100237570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PRODUCTBUILDDATA_H #define QBS_PRODUCTBUILDDATA_H #include "artifact.h" #include "nodeset.h" #include "rescuableartifactdata.h" #include #include #include #include #include namespace qbs { namespace Internal { class Logger; using ArtifactSetByFileTag = QHash; class QBS_AUTOTEST_EXPORT ProductBuildData { public: ~ProductBuildData(); const TypeFilter rootArtifacts() const; const NodeSet &allNodes() const { return m_nodes; } const NodeSet &rootNodes() const { return m_roots; } void addNode(BuildGraphNode *node) { m_nodes.insert(node); } void addRootNode(BuildGraphNode *node) { m_roots.insert(node); } void removeFromRootNodes(BuildGraphNode *node) { m_roots.remove(node); } void addArtifact(Artifact *artifact); void addArtifactToSet(Artifact *artifact); void removeArtifact(Artifact *artifact); void removeArtifactFromSetByFileTag(Artifact *artifact, const FileTag &fileTag); void addFileTagToArtifact(Artifact *artifact, const FileTag &tag); ArtifactSetByFileTag artifactsByFileTag() const; AllRescuableArtifactData rescuableArtifactData() const { return m_rescuableArtifactData; } void setRescuableArtifactData(const AllRescuableArtifactData &rad); RescuableArtifactData removeFromRescuableArtifactData(const QString &filePath); void addRescuableArtifactData(const QString &filePath, const RescuableArtifactData &rad); unsigned int buildPriority() const { return m_buildPriority; } void setBuildPriority(unsigned int prio) { m_buildPriority = prio; } bool checkAndSetJsArtifactsMapUpToDateFlag(); template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(m_nodes, m_roots, m_rescuableArtifactData, m_artifactsByFileTag); } private: void removeArtifactFromSet(Artifact *artifact); NodeSet m_nodes; NodeSet m_roots; // After change tracking, this is the relevant data of artifacts that were in the build data // of the restored product, and will potentially be re-created by our rules. // If and when that happens, the relevant data will be copied over to the newly created // artifact. AllRescuableArtifactData m_rescuableArtifactData; // Do not store, initialized in executor. Higher prioritized artifacts are built first. unsigned int m_buildPriority; ArtifactSetByFileTag m_artifactsByFileTag; mutable std::mutex m_artifactsMapMutex; bool m_jsArtifactsMapUpToDate = true; }; } // namespace Internal } // namespace qbs #endif // QBS_PRODUCTBUILDDATA_H qbs-src-1.13.1/src/lib/corelib/buildgraph/productinstaller.cpp000066400000000000000000000260101347155106100243500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "productinstaller.h" #include "artifact.h" #include "productbuilddata.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { ProductInstaller::ProductInstaller(const TopLevelProjectPtr &project, const std::vector &products, const InstallOptions &options, ProgressObserver *observer, const Logger &logger) : m_project(project), m_products(products), m_options(options), m_observer(observer), m_logger(logger) { if (!m_options.installRoot().isEmpty()) { QFileInfo installRootFileInfo(m_options.installRoot()); QBS_ASSERT(installRootFileInfo.isAbsolute(), /* just complain */); if (m_options.removeExistingInstallation()) { const QString cfp = installRootFileInfo.canonicalFilePath(); if (cfp == QFileInfo(QDir::rootPath()).canonicalFilePath()) throw ErrorInfo(Tr::tr("Refusing to remove root directory.")); if (cfp == QFileInfo(QDir::homePath()).canonicalFilePath()) throw ErrorInfo(Tr::tr("Refusing to remove home directory.")); } return; } if (m_options.installIntoSysroot()) { if (m_options.removeExistingInstallation()) throw ErrorInfo(Tr::tr("Refusing to remove sysroot.")); } initInstallRoot(project.get(), m_options); } void ProductInstaller::install() { m_targetFilePathsMap.clear(); if (m_options.removeExistingInstallation()) removeInstallRoot(); QList artifactsToInstall; for (const ResolvedProductConstPtr &product : qAsConst(m_products)) { QBS_CHECK(product->buildData); for (const Artifact *artifact : filterByType(product->buildData->allNodes())) { if (artifact->properties->qbsPropertyValue(StringConstants::installProperty()).toBool()) artifactsToInstall.push_back(artifact); } } m_observer->initialize(Tr::tr("Installing"), artifactsToInstall.size()); for (const Artifact * const a : qAsConst(artifactsToInstall)) { copyFile(a); m_observer->incrementProgressValue(); } } QString ProductInstaller::targetFilePath(const TopLevelProject *project, const QString &productSourceDir, const QString &sourceFilePath, const PropertyMapConstPtr &properties, InstallOptions &options) { if (!properties->qbsPropertyValue(StringConstants::installProperty()).toBool()) return {}; const QString relativeInstallDir = properties->qbsPropertyValue(StringConstants::installDirProperty()).toString(); const QString installPrefix = properties->qbsPropertyValue(StringConstants::installPrefixProperty()).toString(); const QString installSourceBase = properties->qbsPropertyValue(StringConstants::installSourceBaseProperty()).toString(); initInstallRoot(project, options); QString targetDir = options.installRoot(); if (targetDir.isEmpty()) targetDir = properties->qbsPropertyValue(StringConstants::installRootProperty()).toString(); targetDir.append(QLatin1Char('/')).append(installPrefix) .append(QLatin1Char('/')).append(relativeInstallDir); targetDir = QDir::cleanPath(targetDir); QString targetFilePath; if (installSourceBase.isEmpty()) { if (!targetDir.startsWith(options.installRoot())) { throw ErrorInfo(Tr::tr("Cannot install '%1', because target directory '%2' " "is outside of install root '%3'") .arg(sourceFilePath, targetDir, options.installRoot())); } // This has the same effect as if installSourceBase would equal the directory of the file. targetFilePath = FileInfo::fileName(sourceFilePath); } else { const QString localAbsBasePath = FileInfo::resolvePath(QDir::cleanPath(productSourceDir), QDir::cleanPath(installSourceBase)); targetFilePath = sourceFilePath; if (!targetFilePath.startsWith(localAbsBasePath)) { throw ErrorInfo(Tr::tr("Cannot install '%1', because it doesn't start with the" " value of qbs.installSourceBase '%2'.").arg(sourceFilePath, localAbsBasePath)); } // Since there is a difference between X: and X:\\ on Windows, absolute paths can sometimes // end with a slash, so only remove an extra character if there is no ending slash targetFilePath.remove(0, localAbsBasePath.length() + (localAbsBasePath.endsWith(QLatin1Char('/')) ? 0 : 1)); } targetFilePath.prepend(targetDir + QLatin1Char('/')); return QDir::cleanPath(targetFilePath); } void ProductInstaller::initInstallRoot(const TopLevelProject *project, InstallOptions &options) { if (!options.installRoot().isEmpty()) return; options.setInstallRoot(effectiveInstallRoot(options, project)); } void ProductInstaller::removeInstallRoot() { const QString nativeInstallRoot = QDir::toNativeSeparators(m_options.installRoot()); if (m_options.dryRun()) { m_logger.qbsInfo() << Tr::tr("Would remove install root '%1'.").arg(nativeInstallRoot); return; } m_logger.qbsDebug() << QStringLiteral("Removing install root '%1'.") .arg(nativeInstallRoot); QString errorMessage; if (!removeDirectoryWithContents(m_options.installRoot(), &errorMessage)) { const QString fullErrorMessage = Tr::tr("Cannot remove install root '%1': %2") .arg(QDir::toNativeSeparators(m_options.installRoot()), errorMessage); handleError(fullErrorMessage); } } void ProductInstaller::copyFile(const Artifact *artifact) { if (m_observer->canceled()) { throw ErrorInfo(Tr::tr("Installation canceled for configuration '%1'.") .arg(m_products.front()->project->topLevelProject()->id())); } const QString targetFilePath = this->targetFilePath(m_project.get(), artifact->product->sourceDirectory, artifact->filePath(), artifact->properties, m_options); const QString targetDir = FileInfo::path(targetFilePath); const QString nativeFilePath = QDir::toNativeSeparators(artifact->filePath()); const QString nativeTargetDir = QDir::toNativeSeparators(targetDir); if (m_options.dryRun()) { m_logger.qbsDebug() << Tr::tr("Would copy file '%1' into target directory '%2'.") .arg(nativeFilePath, nativeTargetDir); return; } m_logger.qbsDebug() << QStringLiteral("Copying file '%1' into target directory '%2'.") .arg(nativeFilePath, nativeTargetDir); if (!QDir::root().mkpath(targetDir)) { handleError(Tr::tr("Directory '%1' could not be created.").arg(nativeTargetDir)); return; } QFileInfo fi(artifact->filePath()); if (fi.isDir() && !(HostOsInfo::isAnyUnixHost() && fi.isSymLink())) { m_logger.qbsWarning() << Tr::tr("Not recursively copying directory '%1' into target " "directory '%2'. Install the individual file artifacts " "instead.") .arg(nativeFilePath, nativeTargetDir); } if (m_targetFilePathsMap.contains(targetFilePath)) { // We only want this error message when installing artifacts pointing to different file // paths, to the same location. We do NOT want it when installing different artifacts // pointing to the same file, to the same location. This reduces unnecessary noise: for // example, when installing headers from a multiplexed product, the user does not need to // do extra work to ensure the files are installed by only one of the instances. if (artifact->filePath() != m_targetFilePathsMap[targetFilePath]) { handleError(Tr::tr("Cannot install files '%1' and '%2' to the same location '%3'. " "If you are attempting to install a directory hierarchy, consider " "using the qbs.installSourceBase property.") .arg(artifact->filePath(), m_targetFilePathsMap[targetFilePath], targetFilePath)); } } m_targetFilePathsMap.insert(targetFilePath, artifact->filePath()); QString errorMessage; if (!copyFileRecursion(artifact->filePath(), targetFilePath, true, false, &errorMessage)) handleError(Tr::tr("Installation error: %1").arg(errorMessage)); } void ProductInstaller::handleError(const QString &message) { if (!m_options.keepGoing()) throw ErrorInfo(message); m_logger.qbsWarning() << message; } } // namespace Intern } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/productinstaller.h000066400000000000000000000062161347155106100240230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PRODUCT_INSTALLER_H #define QBS_PRODUCT_INSTALLER_H #include "forward_decls.h" #include #include #include #include #include namespace qbs { namespace Internal { class ProgressObserver; class ProductInstaller { public: ProductInstaller(const TopLevelProjectPtr &project, const std::vector &products, const InstallOptions &options, ProgressObserver *observer, const Logger &logger); void install(); static QString targetFilePath(const TopLevelProject *project, const QString &productSourceDir, const QString &sourceFilePath, const PropertyMapConstPtr &properties, InstallOptions &options); static void initInstallRoot(const TopLevelProject *project, InstallOptions &options); void removeInstallRoot(); void copyFile(const Artifact *artifact); private: void handleError(const QString &message); const TopLevelProjectConstPtr m_project; const std::vector m_products; InstallOptions m_options; ProgressObserver * const m_observer; Logger m_logger; QHash m_targetFilePathsMap; }; } // namespace Internal } // namespace qbs #endif // Header guard qbs-src-1.13.1/src/lib/corelib/buildgraph/projectbuilddata.cpp000066400000000000000000000424121347155106100242760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "projectbuilddata.h" #include "artifact.h" #include "buildgraph.h" #include "buildgraphvisitor.h" #include "productbuilddata.h" #include "rulecommands.h" #include "rulegraph.h" #include "rulenode.h" #include "rulesevaluationcontext.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static Set findDependentProducts(const ResolvedProductPtr &product) { Set result; for (const ResolvedProductPtr &parent : product->topLevelProject()->allProducts()) { if (contains(parent->dependencies, product)) result += parent; } return result; } ProjectBuildData::ProjectBuildData(const ProjectBuildData *other) { // This is needed for temporary duplication of build data when doing change tracking. if (other) { *this = *other; m_doCleanupInDestructor = false; } } ProjectBuildData::~ProjectBuildData() { if (!m_doCleanupInDestructor) return; qDeleteAll(fileDependencies); } QString ProjectBuildData::deriveBuildGraphFilePath(const QString &buildDir, const QString &projectId) { return buildDir + QLatin1Char('/') + projectId + QStringLiteral(".bg"); } void ProjectBuildData::insertIntoLookupTable(FileResourceBase *fileres) { QList &lst = m_artifactLookupTable[fileres->fileName()][fileres->dirPath()]; const auto * const artifact = fileres->fileType() == FileResourceBase::FileTypeArtifact ? static_cast(fileres) : nullptr; if (artifact && artifact->artifactType == Artifact::Generated) { for (const auto *file : lst) { if (file->fileType() != FileResourceBase::FileTypeArtifact) continue; const auto * const otherArtifact = static_cast(file); ErrorInfo error; error.append(Tr::tr("Conflicting artifacts for file path '%1'.") .arg(artifact->filePath())); error.append(Tr::tr("The first artifact comes from product '%1'.") .arg(otherArtifact->product->fullDisplayName()), otherArtifact->product->location); error.append(Tr::tr("The second artifact comes from product '%1'.") .arg(artifact->product->fullDisplayName()), artifact->product->location); throw error; } } QBS_CHECK(!lst.contains(fileres)); lst.push_back(fileres); m_isDirty = true; } void ProjectBuildData::removeFromLookupTable(FileResourceBase *fileres) { m_artifactLookupTable[fileres->fileName()][fileres->dirPath()].removeOne(fileres); } QList ProjectBuildData::lookupFiles(const QString &filePath) const { QString dirPath, fileName; FileInfo::splitIntoDirectoryAndFileName(filePath, &dirPath, &fileName); return lookupFiles(dirPath, fileName); } QList ProjectBuildData::lookupFiles(const QString &dirPath, const QString &fileName) const { return m_artifactLookupTable.value(fileName).value(dirPath); } QList ProjectBuildData::lookupFiles(const Artifact *artifact) const { return lookupFiles(artifact->dirPath(), artifact->fileName()); } void ProjectBuildData::insertFileDependency(FileDependency *dependency) { fileDependencies += dependency; insertIntoLookupTable(dependency); } static void disconnectArtifactChildren(Artifact *artifact) { qCDebug(lcBuildGraph) << "disconnect children of" << relativeArtifactFileName(artifact); for (BuildGraphNode * const child : qAsConst(artifact->children)) child->parents.remove(artifact); artifact->children.clear(); artifact->childrenAddedByScanner.clear(); } static void disconnectArtifactParents(Artifact *artifact) { qCDebug(lcBuildGraph) << "disconnect parents of" << relativeArtifactFileName(artifact); for (BuildGraphNode * const parent : qAsConst(artifact->parents)) { parent->children.remove(artifact); if (parent->type() != BuildGraphNode::ArtifactNodeType) continue; auto const parentArtifact = static_cast(parent); QBS_CHECK(parentArtifact->transformer); parentArtifact->childrenAddedByScanner.remove(artifact); parentArtifact->transformer->inputs.remove(artifact); parentArtifact->transformer->explicitlyDependsOn.remove(artifact); } artifact->parents.clear(); } static void disconnectArtifact(Artifact *artifact) { disconnectArtifactChildren(artifact); disconnectArtifactParents(artifact); } /*! * Removes the artifact and all the artifacts that depend exclusively on it. * Example: if you remove a cpp artifact then the obj artifact is removed but * not the resulting application (if there's more then one cpp artifact). */ void ProjectBuildData::removeArtifactAndExclusiveDependents(Artifact *artifact, const Logger &logger, bool removeFromProduct, ArtifactSet *removedArtifacts) { if (removedArtifacts) removedArtifacts->insert(artifact); // Iterate over a copy of the artifact's parents, because we'll change // artifact->parents with the disconnect call. const NodeSet parentsCopy = artifact->parents; for (Artifact *parent : filterByType(parentsCopy)) { bool removeParent = false; disconnect(parent, artifact); if (parent->children.empty()) { removeParent = true; } else if (parent->transformer) { parent->transformer->inputs.remove(artifact); removeParent = parent->transformer->inputs.empty(); } if (removeParent) { removeArtifactAndExclusiveDependents(parent, logger, removeFromProduct, removedArtifacts); } else { parent->clearTimestamp(); } } const bool removeFromDisk = artifact->artifactType == Artifact::Generated; removeArtifact(artifact, logger, removeFromDisk, removeFromProduct); } static void removeFromRuleNodes(Artifact *artifact) { for (RuleNode * const ruleNode : filterByType(artifact->parents)) ruleNode->removeOldInputArtifact(artifact); } void ProjectBuildData::removeArtifact(Artifact *artifact, const Logger &logger, bool removeFromDisk, bool removeFromProduct) { qCDebug(lcBuildGraph) << "remove artifact" << relativeArtifactFileName(artifact); if (removeFromDisk) removeGeneratedArtifactFromDisk(artifact, logger); removeFromLookupTable(artifact); removeFromRuleNodes(artifact); disconnectArtifact(artifact); if (artifact->transformer) artifact->transformer->outputs.remove(artifact); if (removeFromProduct) artifact->product->buildData->removeArtifact(artifact); m_isDirty = false; } void ProjectBuildData::setDirty() { qCDebug(lcBuildGraph) << "Marking build graph as dirty"; m_isDirty = true; } void ProjectBuildData::setClean() { qCDebug(lcBuildGraph) << "Marking build graph as clean"; m_isDirty = false; } void ProjectBuildData::load(PersistentPool &pool) { serializationOp(pool); for (FileDependency * const dep : qAsConst(fileDependencies)) insertIntoLookupTable(dep); m_isDirty = false; } void ProjectBuildData::store(PersistentPool &pool) { serializationOp(pool); } BuildDataResolver::BuildDataResolver(const Logger &logger) : m_logger(logger) { } void BuildDataResolver::resolveBuildData(const TopLevelProjectPtr &resolvedProject, const RulesEvaluationContextPtr &evalContext) { QBS_CHECK(!resolvedProject->buildData); m_project = resolvedProject; resolvedProject->buildData.reset(new ProjectBuildData); resolvedProject->buildData->evaluationContext = evalContext; const std::vector &allProducts = resolvedProject->allProducts(); evalContext->initializeObserver(Tr::tr("Setting up build graph for configuration %1") .arg(resolvedProject->id()), int(allProducts.size()) + 1); for (const auto &rProduct : allProducts) { if (rProduct->enabled) resolveProductBuildData(rProduct); evalContext->incrementProgressValue(); } evalContext->incrementProgressValue(); doSanityChecks(resolvedProject, m_logger); } void BuildDataResolver::resolveProductBuildDataForExistingProject(const TopLevelProjectPtr &project, const std::vector &freshProducts) { m_project = project; for (const ResolvedProductPtr &product : freshProducts) { if (product->enabled) resolveProductBuildData(product); } QHash> dependencyMap; for (const ResolvedProductPtr &product : freshProducts) { if (!product->enabled) continue; QBS_CHECK(product->buildData); const Set dependents = findDependentProducts(product); for (const ResolvedProductPtr &dependentProduct : dependents) { if (!dependentProduct->enabled) continue; if (!contains(dependencyMap[dependentProduct], product)) dependencyMap[dependentProduct].push_back(product); } } for (auto it = dependencyMap.cbegin(); it != dependencyMap.cend(); ++it) { if (!contains(freshProducts, it.key())) connectRulesToDependencies(it.key(), it.value()); } } class CreateRuleNodes : public RuleGraphVisitor { public: CreateRuleNodes(const ResolvedProductPtr &product) : m_product(product) { } private: const ResolvedProductPtr &m_product; QHash m_nodePerRule; Set m_rulesOnPath; QList m_rulePath; void visit(const RuleConstPtr &parentRule, const RuleConstPtr &rule) override { if (!m_rulesOnPath.insert(rule.get()).second) { QString pathstr; for (const Rule *r : qAsConst(m_rulePath)) { pathstr += QLatin1Char('\n') + r->toString() + QLatin1Char('\t') + r->prepareScript.location().toString(); } throw ErrorInfo(Tr::tr("Cycle detected in rule dependencies: %1").arg(pathstr)); } m_rulePath.push_back(rule.get()); RuleNode *node = m_nodePerRule.value(rule); if (!node) { node = new RuleNode; m_nodePerRule.insert(rule, node); node->product = m_product; node->setRule(rule); m_product->buildData->addNode(node); qCDebug(lcBuildGraph).noquote() << "create" << node->toString() << "for product" << m_product->uniqueName(); } if (parentRule) { RuleNode *parent = m_nodePerRule.value(parentRule); QBS_CHECK(parent); connect(parent, node); } else { m_product->buildData->addRootNode(node); } } void endVisit(const RuleConstPtr &rule) override { m_rulesOnPath.remove(rule.get()); m_rulePath.removeLast(); } }; static bool areRulesCompatible(const RuleNode *ruleNode, const RuleNode *dependencyRule) { const FileTags outTags = dependencyRule->rule()->collectedOutputFileTags(); if (ruleNode->rule()->excludedInputs.intersects(outTags)) return false; if (ruleNode->rule()->inputsFromDependencies.intersects(outTags)) return true; if (!dependencyRule->product->fileTags.intersects(outTags)) return false; if (ruleNode->rule()->explicitlyDependsOnFromDependencies.intersects(outTags)) return true; return ruleNode->rule()->auxiliaryInputs.intersects(outTags); } void BuildDataResolver::resolveProductBuildData(const ResolvedProductPtr &product) { if (product->buildData) return; evalContext()->checkForCancelation(); product->buildData.reset(new ProductBuildData); ArtifactSetByFileTag artifactsPerFileTag; for (const auto &dependency : qAsConst(product->dependencies)) { QBS_CHECK(dependency->enabled); resolveProductBuildData(dependency); } //add qbsFile artifact Artifact *qbsFileArtifact = lookupArtifact(product, product->location.filePath()); if (!qbsFileArtifact) { qbsFileArtifact = new Artifact; qbsFileArtifact->artifactType = Artifact::SourceFile; qbsFileArtifact->setFilePath(product->location.filePath()); qbsFileArtifact->properties = product->moduleProperties; insertArtifact(product, qbsFileArtifact); } qbsFileArtifact->addFileTag("qbs"); artifactsPerFileTag["qbs"].insert(qbsFileArtifact); // read sources for (const SourceArtifactConstPtr &sourceArtifact : product->allEnabledFiles()) { QString filePath = sourceArtifact->absoluteFilePath; if (lookupArtifact(product, filePath)) continue; // ignore duplicate artifacts Artifact *artifact = createArtifact(product, sourceArtifact); for (const FileTag &fileTag : artifact->fileTags()) artifactsPerFileTag[fileTag].insert(artifact); } RuleGraph ruleGraph; ruleGraph.build(product->rules, product->fileTags); CreateRuleNodes crn(product); ruleGraph.accept(&crn); connectRulesToDependencies(product, product->dependencies); } static bool isRootRuleNode(RuleNode *ruleNode) { return ruleNode->product->buildData->rootNodes().contains(ruleNode); } void BuildDataResolver::connectRulesToDependencies(const ResolvedProductPtr &product, const std::vector &dependencies) { // Connect the rules of this product to the compatible rules of all product dependencies. // Rules that take "installable" artifacts are connected to all root rules of product // dependencies. std::vector ruleNodes; for (RuleNode *ruleNode : filterByType(product->buildData->allNodes())) ruleNodes.push_back(ruleNode); for (const ResolvedProductConstPtr &dep : dependencies) { if (!dep->buildData) continue; for (RuleNode *depRuleNode : filterByType(dep->buildData->allNodes())) { for (RuleNode *ruleNode : ruleNodes) { static const FileTag installableTag("installable"); if (areRulesCompatible(ruleNode, depRuleNode) || ((ruleNode->rule()->inputsFromDependencies.contains(installableTag) || ruleNode->rule()->auxiliaryInputs.contains(installableTag) || ruleNode->rule()->explicitlyDependsOnFromDependencies.contains( installableTag)) && isRootRuleNode(depRuleNode))) { connect(ruleNode, depRuleNode); } } } } } RulesEvaluationContextPtr BuildDataResolver::evalContext() const { return m_project->buildData->evaluationContext; } ScriptEngine *BuildDataResolver::engine() const { return evalContext()->engine(); } QScriptValue BuildDataResolver::scope() const { return evalContext()->scope(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/projectbuilddata.h000066400000000000000000000116001347155106100237360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROJECTBUILDDATA_H #define QBS_PROJECTBUILDDATA_H #include "forward_decls.h" #include "rawscanresults.h" #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class BuildGraphNode; class FileDependency; class FileResourceBase; class ScriptEngine; class QBS_AUTOTEST_EXPORT ProjectBuildData { public: ProjectBuildData(const ProjectBuildData *other = nullptr); ~ProjectBuildData(); static QString deriveBuildGraphFilePath(const QString &buildDir, const QString &projectId); void insertIntoLookupTable(FileResourceBase *fileres); void removeFromLookupTable(FileResourceBase *fileres); QList lookupFiles(const QString &filePath) const; QList lookupFiles(const QString &dirPath, const QString &fileName) const; QList lookupFiles(const Artifact *artifact) const; void insertFileDependency(FileDependency *dependency); void removeArtifactAndExclusiveDependents(Artifact *artifact, const Logger &logger, bool removeFromProduct = true, ArtifactSet *removedArtifacts = nullptr); void removeArtifact(Artifact *artifact, const Logger &logger, bool removeFromDisk = true, bool removeFromProduct = true); void setDirty(); void setClean(); bool isDirty() const { return m_isDirty; } Set fileDependencies; RawScanResults rawScanResults; // do not serialize: RulesEvaluationContextPtr evaluationContext; void load(PersistentPool &pool); void store(PersistentPool &pool); private: template void serializationOp(PersistentPool &pool) { pool.serializationOp(fileDependencies, rawScanResults); } using ResultsPerDirectory = QHash>; using ArtifactLookupTable = QHash; ArtifactLookupTable m_artifactLookupTable; bool m_doCleanupInDestructor = true; bool m_isDirty = true; }; class BuildDataResolver { public: BuildDataResolver(const Logger &logger); void resolveBuildData(const TopLevelProjectPtr &resolvedProject, const RulesEvaluationContextPtr &evalContext); void resolveProductBuildDataForExistingProject(const TopLevelProjectPtr &project, const std::vector &freshProducts); private: void resolveProductBuildData(const ResolvedProductPtr &product); void connectRulesToDependencies(const ResolvedProductPtr &product, const std::vector &dependencies); RulesEvaluationContextPtr evalContext() const; ScriptEngine *engine() const; QScriptValue scope() const; TopLevelProjectPtr m_project; Logger m_logger; }; } // namespace Internal } // namespace qbs #endif // QBS_PROJECTBUILDDATA_H qbs-src-1.13.1/src/lib/corelib/buildgraph/qtmocscanner.cpp000066400000000000000000000260561347155106100234610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtmocscanner.h" #include "artifact.h" #include "depscanner.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "rawscanresults.h" #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { struct CommonFileTags { const FileTag cpp = "cpp"; const FileTag cppCombine = "cpp.combine"; const FileTag hpp = "hpp"; const FileTag moc_cpp = "moc_cpp"; const FileTag moc_cpp_plugin = "moc_cpp_plugin"; const FileTag moc_hpp_plugin = "moc_hpp_plugin"; const FileTag moc_hpp = "moc_hpp"; const FileTag objcpp = "objcpp"; const FileTag objcppCombine = "objcpp.combine"; }; Q_GLOBAL_STATIC(CommonFileTags, commonFileTags) class QtScanner : public DependencyScanner { public: QtScanner(const DependencyScanner &actualScanner) : m_id(QStringLiteral("qt") + actualScanner.id()) {} private: QStringList collectSearchPaths(Artifact *) override { return {}; } QStringList collectDependencies(Artifact *, FileResourceBase *, const char *) override { return {}; } bool recursive() const override { return false; } const void *key() const override { return nullptr; } QString createId() const override { return m_id; } bool areModulePropertiesCompatible(const PropertyMapConstPtr &, const PropertyMapConstPtr &) const override { return true; } bool cacheIsPerFile() const override { return false; } const QString m_id; }; static QString qtMocScannerJsName() { return QStringLiteral("QtMocScanner"); } QtMocScanner::QtMocScanner(const ResolvedProductPtr &product, QScriptValue targetScriptValue) : m_tags(*commonFileTags()) , m_product(product) , m_targetScriptValue(targetScriptValue) { const auto engine = static_cast(targetScriptValue.engine()); QScriptValue scannerObj = engine->newObject(); targetScriptValue.setProperty(qtMocScannerJsName(), scannerObj); QScriptValue applyFunction = engine->newFunction(&js_apply, this); scannerObj.setProperty(QStringLiteral("apply"), applyFunction); } QtMocScanner::~QtMocScanner() { m_targetScriptValue.setProperty(qtMocScannerJsName(), QScriptValue()); } static RawScanResult runScanner(ScannerPlugin *scanner, const Artifact *artifact) { const QString &filepath = artifact->filePath(); QtScanner depScanner((PluginDependencyScanner(scanner))); RawScanResults &rawScanResults = artifact->product->topLevelProject()->buildData->rawScanResults; RawScanResults::ScanData &scanData = rawScanResults.findScanData(artifact, &depScanner, artifact->properties); if (scanData.lastScanTime < artifact->timestamp()) { FileTags tags = artifact->fileTags(); if (tags.contains(commonFileTags->cppCombine)) { tags.remove(commonFileTags->cppCombine); tags.insert(commonFileTags->cpp); } if (tags.contains(commonFileTags->objcppCombine)) { tags.remove(commonFileTags->objcppCombine); tags.insert(commonFileTags->objcpp); } const QByteArray tagsForScanner = tags.toStringList().join(QLatin1Char(',')).toLatin1(); void *opaq = scanner->open(filepath.utf16(), tagsForScanner.constData(), ScanForDependenciesFlag | ScanForFileTagsFlag); if (!opaq || !scanner->additionalFileTags) return scanData.rawScanResult; scanData.rawScanResult.additionalFileTags.clear(); scanData.rawScanResult.deps.clear(); int length = 0; const char **szFileTagsFromScanner = scanner->additionalFileTags(opaq, &length); if (szFileTagsFromScanner) { for (int i = length; --i >= 0;) scanData.rawScanResult.additionalFileTags += szFileTagsFromScanner[i]; } QString baseDirOfInFilePath = artifact->dirPath(); forever { int flags = 0; const char *szOutFilePath = scanner->next(opaq, &length, &flags); if (szOutFilePath == nullptr) break; QString includedFilePath = QString::fromLocal8Bit(szOutFilePath, length); if (includedFilePath.isEmpty()) continue; bool isLocalInclude = (flags & SC_LOCAL_INCLUDE_FLAG); if (isLocalInclude) { QString localFilePath = FileInfo::resolvePath(baseDirOfInFilePath, includedFilePath); if (FileInfo::exists(localFilePath)) includedFilePath = localFilePath; } scanData.rawScanResult.deps.push_back(RawScannedDependency(includedFilePath)); } scanner->close(opaq); scanData.lastScanTime = FileTime::currentTime(); } return scanData.rawScanResult; } void QtMocScanner::findIncludedMocCppFiles() { if (!m_includedMocCppFiles.empty()) return; qCDebug(lcMocScan) << "looking for included moc_XXX.cpp files"; static const FileTags mocCppTags = {m_tags.cpp, m_tags.objcpp}; for (Artifact *artifact : m_product->lookupArtifactsByFileTags(mocCppTags)) { const RawScanResult scanResult = runScanner(m_cppScanner, artifact); for (const RawScannedDependency &dependency : scanResult.deps) { QString includedFileName = dependency.fileName(); if (includedFileName.startsWith(QLatin1String("moc_")) && includedFileName.endsWith(QLatin1String(".cpp"))) { qCDebug(lcMocScan) << artifact->fileName() << "includes" << includedFileName; includedFileName.remove(0, 4); includedFileName.chop(4); m_includedMocCppFiles.insert(includedFileName, artifact->fileName()); } } } } QScriptValue QtMocScanner::js_apply(QScriptContext *ctx, QScriptEngine *engine, QtMocScanner *that) { QScriptValue input = ctx->argument(0); return that->apply(engine, attachedPointer(input)); } static QScriptValue scannerCountError(QScriptEngine *engine, size_t scannerCount, const QString &fileTag) { return engine->currentContext()->throwError( Tr::tr("There are %1 scanners for the file tag %2. " "Expected is exactly one.").arg(scannerCount).arg(fileTag)); } QScriptValue QtMocScanner::apply(QScriptEngine *engine, const Artifact *artifact) { if (!m_cppScanner) { auto scanners = ScannerPluginManager::scannersForFileTag(m_tags.cpp); if (scanners.size() != 1) return scannerCountError(engine, scanners.size(), m_tags.cpp.toString()); m_cppScanner = scanners.front(); } qCDebug(lcMocScan).noquote() << "scanning" << artifact->toString(); bool hasQObjectMacro = false; bool mustCompile = false; bool hasPluginMetaDataMacro = false; const bool isHeaderFile = artifact->fileTags().contains(m_tags.hpp); RawScanResult scanResult = runScanner(m_cppScanner, artifact); if (scanResult.additionalFileTags.empty() && artifact->fileTags().contains("mocable")) { if (isHeaderFile) { scanResult.additionalFileTags.insert(m_tags.moc_hpp); } else if (artifact->fileTags().contains(m_tags.cpp) || artifact->fileTags().contains(m_tags.cppCombine) || artifact->fileTags().contains(m_tags.objcpp) || artifact->fileTags().contains(m_tags.objcppCombine)) { scanResult.additionalFileTags.insert(m_tags.moc_cpp); } } if (!scanResult.additionalFileTags.empty()) { if (isHeaderFile) { if (scanResult.additionalFileTags.contains(m_tags.moc_hpp)) hasQObjectMacro = true; if (scanResult.additionalFileTags.contains(m_tags.moc_hpp_plugin)) { hasQObjectMacro = true; hasPluginMetaDataMacro = true; } findIncludedMocCppFiles(); if (!m_includedMocCppFiles.contains(FileInfo::completeBaseName(artifact->fileName()))) mustCompile = true; } else { if (scanResult.additionalFileTags.contains(m_tags.moc_cpp)) hasQObjectMacro = true; if (scanResult.additionalFileTags.contains(m_tags.moc_cpp_plugin)) { hasQObjectMacro = true; hasPluginMetaDataMacro = true; } } } qCDebug(lcMocScan) << "hasQObjectMacro:" << hasQObjectMacro << "mustCompile:" << mustCompile << "hasPluginMetaDataMacro:" << hasPluginMetaDataMacro; QScriptValue obj = engine->newObject(); obj.setProperty(QStringLiteral("hasQObjectMacro"), hasQObjectMacro); obj.setProperty(QStringLiteral("mustCompile"), mustCompile); obj.setProperty(QStringLiteral("hasPluginMetaDataMacro"), hasPluginMetaDataMacro); static_cast(engine)->setUsesIo(); return obj; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/qtmocscanner.h000066400000000000000000000054701347155106100231230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_QTMOCSCANNER_H #define QBS_QTMOCSCANNER_H #include #include #include #include QT_BEGIN_NAMESPACE class QScriptContext; QT_END_NAMESPACE class ScannerPlugin; namespace qbs { namespace Internal { class Artifact; struct CommonFileTags; class QtMocScanner { public: explicit QtMocScanner(const ResolvedProductPtr &product, QScriptValue targetScriptValue); ~QtMocScanner(); private: void findIncludedMocCppFiles(); static QScriptValue js_apply(QScriptContext *ctx, QScriptEngine *engine, QtMocScanner *that); QScriptValue apply(QScriptEngine *engine, const Artifact *artifact); const CommonFileTags &m_tags; const ResolvedProductPtr &m_product; QScriptValue m_targetScriptValue; QHash m_includedMocCppFiles; ScannerPlugin *m_cppScanner = nullptr; }; } // namespace Internal } // namespace qbs #endif // QBS_QTMOCSCANNER_H qbs-src-1.13.1/src/lib/corelib/buildgraph/rawscanneddependency.cpp000066400000000000000000000056051347155106100251450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "rawscanneddependency.h" #include namespace qbs { namespace Internal { RawScannedDependency::RawScannedDependency() : m_isClean(true) {} RawScannedDependency::RawScannedDependency(const QString &filePath) { FileInfo::splitIntoDirectoryAndFileName(filePath, &m_dirPath, &m_fileName); setClean(); } QString RawScannedDependency::filePath() const { return m_dirPath.isEmpty() ? m_fileName : m_dirPath + QLatin1Char('/') + m_fileName; } void RawScannedDependency::setClean() { m_isClean = !m_dirPath.contains(QLatin1Char('.')) && !m_dirPath.contains(QStringLiteral("//")); } void RawScannedDependency::load(PersistentPool &pool) { serializationOp(pool); setClean(); } void RawScannedDependency::store(PersistentPool &pool) { serializationOp(pool); } bool operator==(const RawScannedDependency &d1, const RawScannedDependency &d2) { return d1.dirPath() == d2.dirPath() && d1.fileName() == d2.fileName(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/rawscanneddependency.h000066400000000000000000000057561347155106100246210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_RAWSCANNEDDEPENDENCY_H #define QBS_RAWSCANNEDDEPENDENCY_H #include #include namespace qbs { namespace Internal { class PersistentPool; class RawScannedDependency { public: RawScannedDependency(); RawScannedDependency(const QString &filePath); QString filePath() const; const QString &dirPath() const { return m_dirPath; } const QString &fileName() const { return m_fileName; } bool isClean() const { return m_isClean; } bool isValid() const { return !m_fileName.isEmpty(); } void load(PersistentPool &pool); void store(PersistentPool &pool); private: void setClean(); template void serializationOp(PersistentPool &pool) { pool.serializationOp(m_dirPath, m_fileName); } QString m_dirPath; QString m_fileName; bool m_isClean; }; bool operator==(const RawScannedDependency &d1, const RawScannedDependency &d2); inline bool operator!=(const RawScannedDependency &d1, const RawScannedDependency &d2) { return !(d1 == d2); } } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/buildgraph/rawscanresults.cpp000066400000000000000000000054551347155106100240440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "rawscanresults.h" #include "filedependency.h" #include "depscanner.h" #include namespace qbs { namespace Internal { RawScanResults::ScanData &RawScanResults::findScanData( const FileResourceBase *file, const DependencyScanner *scanner, const PropertyMapConstPtr &moduleProperties) { std::vector &scanDataForFile = m_rawScanData[file->filePath()]; const QString &scannerId = scanner->id(); for (auto &scanData : scanDataForFile) { if (scannerId != scanData.scannerId) continue; if (!scanner->areModulePropertiesCompatible(moduleProperties, scanData.moduleProperties)) continue; return scanData; } ScanData newScanData; newScanData.scannerId = scannerId; newScanData.moduleProperties = moduleProperties; scanDataForFile.push_back(std::move(newScanData)); return scanDataForFile.back(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/rawscanresults.h000066400000000000000000000066501347155106100235070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_RAWSCANRESULTS_H #define QBS_RAWSCANRESULTS_H #include "rawscanneddependency.h" #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class DependencyScanner; class FileResourceBase; class RawScanResult { public: std::vector deps; FileTags additionalFileTags; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(deps, additionalFileTags); } }; class RawScanResults { public: struct ScanData { QString scannerId; PropertyMapConstPtr moduleProperties; FileTime lastScanTime; RawScanResult rawScanResult; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(scannerId, moduleProperties, lastScanTime, rawScanResult); } }; ScanData &findScanData( const FileResourceBase *file, const DependencyScanner *scanner, const PropertyMapConstPtr &moduleProperties); template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(m_rawScanData); } private: QHash> m_rawScanData; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/buildgraph/requestedartifacts.cpp000066400000000000000000000175441347155106100246700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "requestedartifacts.h" #include "productbuilddata.h" #include #include #include #include #include #include namespace qbs { namespace Internal { bool RequestedArtifacts::isUpToDate(const TopLevelProject *project) const { if (m_requestedArtifactsPerProduct.empty()) return true; const std::vector &allProducts = project->allProducts(); for (auto it = m_requestedArtifactsPerProduct.cbegin(); it != m_requestedArtifactsPerProduct.cend(); ++it) { const QString &productName = it->first; const auto findProduct = [productName](const ResolvedProductConstPtr &p) { return p->uniqueName() == productName; }; const auto productIt = std::find_if(allProducts.begin(), allProducts.end(), findProduct); if (productIt == allProducts.end()) { qCDebug(lcBuildGraph) << "artifacts map not up to date: product" << productName << "does not exist anymore"; return false; } if (!it->second.isUpToDate(productIt->get())) return false; } return true; } void RequestedArtifacts::setAllArtifactTags(const ResolvedProduct *product, bool forceUpdate) { RequestedArtifactsPerProduct &ra = m_requestedArtifactsPerProduct[product->uniqueName()]; if (!ra.allTags.empty() && !forceUpdate) return; ra.allTags.clear(); const ArtifactSetByFileTag artifactsMap = product->buildData->artifactsByFileTag(); for (auto it = artifactsMap.begin(); it != artifactsMap.end(); ++it) ra.allTags.insert(it.key().toString()); } void RequestedArtifacts::setArtifactsForTag(const ResolvedProduct *product, const FileTag &tag) { RequestedArtifactsPerProduct &ra = m_requestedArtifactsPerProduct[product->uniqueName()]; QBS_ASSERT(!ra.allTags.empty(), ;); Set &filePaths = ra.requestedTags[tag.toString()]; for (const Artifact * const a : product->buildData->artifactsByFileTag().value(tag)) filePaths.insert(a->filePath()); } void RequestedArtifacts::setNonExistingTagRequested(const ResolvedProduct *product, const QString &tag) { RequestedArtifactsPerProduct &ra = m_requestedArtifactsPerProduct[product->uniqueName()]; QBS_ASSERT(!ra.allTags.empty(), ;); Set &filePaths = ra.requestedTags[tag]; QBS_CHECK(filePaths.empty()); } void RequestedArtifacts::setArtifactsEnumerated(const ResolvedProduct *product) { m_requestedArtifactsPerProduct[product->uniqueName()].artifactsEnumerated = true; } void RequestedArtifacts::unite(const RequestedArtifacts &other) { for (auto it = other.m_requestedArtifactsPerProduct.begin(); it != other.m_requestedArtifactsPerProduct.end(); ++it) { m_requestedArtifactsPerProduct[it->first].unite(it->second); } } void RequestedArtifacts::doSanityChecks() const { for (auto it = m_requestedArtifactsPerProduct.cbegin(); it != m_requestedArtifactsPerProduct.cend(); ++it) { it->second.doSanityChecks(); } } void RequestedArtifacts::load(PersistentPool &pool) { serializationOp(pool); } void RequestedArtifacts::store(PersistentPool &pool) { serializationOp(pool); } bool RequestedArtifacts::RequestedArtifactsPerProduct::isUpToDate( const ResolvedProduct *product) const { if (!product->buildData) { qCDebug(lcBuildGraph) << "artifacts map not up to date: product" << product->uniqueName() << "is now disabled"; return false; } if (!artifactsEnumerated && requestedTags.empty()) return true; const ArtifactSetByFileTag currentArtifacts = product->buildData->artifactsByFileTag(); for (auto reqIt = requestedTags.cbegin(); reqIt != requestedTags.cend(); ++reqIt) { const FileTag tag = FileTag(reqIt->first.toUtf8()); const auto currentIt = currentArtifacts.constFind(tag); Set currentFilePathsForTag; if (currentIt != currentArtifacts.constEnd()) { for (const Artifact * const a : currentIt.value()) currentFilePathsForTag.insert(a->filePath()); } if (currentFilePathsForTag != reqIt->second) { qCDebug(lcBuildGraph) << "artifacts map not up to date: requested artifact set for " "file tag" << reqIt->first << "in product" << product->uniqueName() << "differs from the current one"; return false; } } if (!artifactsEnumerated) return true; Set currentTags; for (auto it = currentArtifacts.begin(); it != currentArtifacts.end(); ++it) currentTags.insert(it.key().toString()); if (currentTags != allTags) { qCDebug(lcBuildGraph) << "artifacts map not up to date: overall file tags differ for " << "product" << product->uniqueName(); return false; } return true; } void RequestedArtifacts::RequestedArtifactsPerProduct::unite( const RequestedArtifactsPerProduct &other) { if (allTags.empty()) { *this = other; return; } allTags = other.allTags; for (auto it = other.requestedTags.begin(); it != other.requestedTags.end(); ++it) requestedTags[it->first] = it->second; } void RequestedArtifacts::RequestedArtifactsPerProduct::doSanityChecks() const { for (auto it = requestedTags.begin(); it != requestedTags.end(); ++it) QBS_CHECK(allTags.contains(it->first) || it->second.empty()); } void RequestedArtifacts::RequestedArtifactsPerProduct::load(PersistentPool &pool) { serializationOp(pool); } void RequestedArtifacts::RequestedArtifactsPerProduct::store(PersistentPool &pool) { serializationOp(pool); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/requestedartifacts.h000066400000000000000000000073141347155106100243270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_REQUESTEDARTIFACTS_H #define QBS_REQUESTEDARTIFACTS_H #include #include #include #include #include namespace qbs { namespace Internal { class FileTag; class PersistentPool; class RequestedArtifacts { public: bool isUpToDate(const TopLevelProject *project) const; void clear() { m_requestedArtifactsPerProduct.clear(); } void setAllArtifactTags(const ResolvedProduct *product, bool forceUpdate); void setArtifactsForTag(const ResolvedProduct *product, const FileTag &tag); void setNonExistingTagRequested(const ResolvedProduct *product, const QString &tag); void setArtifactsEnumerated(const ResolvedProduct *product); void unite(const RequestedArtifacts &other); void doSanityChecks() const; void load(PersistentPool &pool); void store(PersistentPool &pool); template void serializationOp(PersistentPool &pool) { pool.serializationOp(m_requestedArtifactsPerProduct); } private: struct RequestedArtifactsPerProduct { Set allTags; std::unordered_map> requestedTags; bool artifactsEnumerated = false; bool isUpToDate(const ResolvedProduct *product) const; void unite(const RequestedArtifactsPerProduct &other); void doSanityChecks() const; template void serializationOp(PersistentPool &pool) { pool.serializationOp(allTags, requestedTags, artifactsEnumerated); } void load(PersistentPool &pool); void store(PersistentPool &pool); }; std::unordered_map m_requestedArtifactsPerProduct; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/buildgraph/requesteddependencies.cpp000066400000000000000000000066271347155106100253360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "requesteddependencies.h" #include #include #include namespace qbs { namespace Internal { static Set depNamesForProduct(const ResolvedProduct *p) { Set names; for (const ResolvedProductConstPtr &dep : p->dependencies) names.insert(dep->uniqueName()); for (const ResolvedModuleConstPtr &m : p->modules) { if (!m->isProduct) names.insert(m->name); } return names; } void RequestedDependencies::set(const Set &products) { m_depsPerProduct.clear(); add(products); } void RequestedDependencies::add(const Set &products) { for (const ResolvedProduct * const p : products) m_depsPerProduct[p->uniqueName()] = depNamesForProduct(p); } bool RequestedDependencies::isUpToDate(const TopLevelProject *project) const { if (m_depsPerProduct.empty()) return true; for (const ResolvedProductConstPtr &product : project->allProducts()) { const auto it = m_depsPerProduct.find(product->uniqueName()); if (it == m_depsPerProduct.cend()) continue; const Set newDepNames = depNamesForProduct(product.get()); if (newDepNames != it->second) { qCDebug(lcBuildGraph) << "dependencies list was accessed for product" << product->fullDisplayName() << "and dependencies have changed."; return false; } } return true; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/requesteddependencies.h000066400000000000000000000056171347155106100250010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_REQUESTEDDEPENDENCIES_H #define QBS_REQUESTEDDEPENDENCIES_H #include #include #include #include #include namespace qbs { namespace Internal { class RequestedDependencies { public: RequestedDependencies() = default; RequestedDependencies(const Set &products) { set(products); } void set(const Set &products); void add(const Set &products); void clear() { m_depsPerProduct.clear(); } bool isUpToDate(const TopLevelProject *project) const; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(m_depsPerProduct); } private: struct QStringHash { std::size_t operator()(const QString &s) const { return qHash(s); } }; std::unordered_map, QStringHash> m_depsPerProduct; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/buildgraph/rescuableartifactdata.h000066400000000000000000000127331347155106100247430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_RESCUABLEARTIFACTDATA_H #define QBS_RESCUABLEARTIFACTDATA_H #include "forward_decls.h" #include "requestedartifacts.h" #include "requesteddependencies.h" #include "rulecommands.h" #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class QBS_AUTOTEST_EXPORT RescuableArtifactData { public: template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(timeStamp, children, fileDependencies, knownOutOfDate, propertiesRequestedInPrepareScript, propertiesRequestedInCommands, propertiesRequestedFromArtifactInPrepareScript, propertiesRequestedFromArtifactInCommands, importedFilesUsedInPrepareScript, importedFilesUsedInCommands, depsRequestedInPrepareScript, depsRequestedInCommands, commands, artifactsMapRequestedInPrepareScript, artifactsMapRequestedInCommands, exportedModulesAccessedInPrepareScript, exportedModulesAccessedInCommands, lastPrepareScriptExecutionTime, lastCommandExecutionTime, fileTags, properties); } bool isValid() const { return !!properties; } struct ChildData { ChildData(const QString &n = QString(), const QString &m = QString(), const QString &c = QString(), bool byScanner = false) : productName(n), productMultiplexId(m), childFilePath(c), addedByScanner(byScanner) {} template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(productName, productMultiplexId, childFilePath, addedByScanner); } QString productName; QString productMultiplexId; QString childFilePath; bool addedByScanner; }; FileTime timeStamp; std::vector children; std::vector fileDependencies; // Per-Transformer data CommandList commands; PropertySet propertiesRequestedInPrepareScript; PropertySet propertiesRequestedInCommands; PropertyHash propertiesRequestedFromArtifactInPrepareScript; PropertyHash propertiesRequestedFromArtifactInCommands; std::vector importedFilesUsedInPrepareScript; std::vector importedFilesUsedInCommands; RequestedDependencies depsRequestedInPrepareScript; RequestedDependencies depsRequestedInCommands; RequestedArtifacts artifactsMapRequestedInPrepareScript; RequestedArtifacts artifactsMapRequestedInCommands; FileTime lastPrepareScriptExecutionTime; FileTime lastCommandExecutionTime; std::unordered_map exportedModulesAccessedInPrepareScript; std::unordered_map exportedModulesAccessedInCommands; bool knownOutOfDate = false; // Only needed for API purposes FileTags fileTags; PropertyMapPtr properties; }; using AllRescuableArtifactData = QHash; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/buildgraph/rulecommands.cpp000066400000000000000000000456441347155106100234610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "rulecommands.h" #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static QString argumentsProperty() { return QStringLiteral("arguments"); } static QString environmentProperty() { return QStringLiteral("environment"); } static QString extendedDescriptionProperty() { return QStringLiteral("extendedDescription"); } static QString highlightProperty() { return QStringLiteral("highlight"); } static QString ignoreDryRunProperty() { return QStringLiteral("ignoreDryRun"); } static QString maxExitCodeProperty() { return QStringLiteral("maxExitCode"); } static QString programProperty() { return QStringLiteral("program"); } static QString responseFileArgumentIndexProperty() { return QStringLiteral("responseFileArgumentIndex"); } static QString responseFileThresholdProperty() { return QStringLiteral("responseFileThreshold"); } static QString responseFileUsagePrefixProperty() { return QStringLiteral("responseFileUsagePrefix"); } static QString silentProperty() { return QStringLiteral("silent"); } static QString stderrFilePathProperty() { return QStringLiteral("stderrFilePath"); } static QString stderrFilterFunctionProperty() { return QStringLiteral("stderrFilterFunction"); } static QString stdoutFilePathProperty() { return QStringLiteral("stdoutFilePath"); } static QString stdoutFilterFunctionProperty() { return QStringLiteral("stdoutFilterFunction"); } static QString workingDirProperty() { return QStringLiteral("workingDirectory"); } static QString invokedSourceCode(const QScriptValue codeOrFunction) { const QString &code = codeOrFunction.toString(); return codeOrFunction.isFunction() ? QStringLiteral("(") + code + QStringLiteral(")()") : code; } AbstractCommand::AbstractCommand() : m_description(defaultDescription()), m_extendedDescription(defaultExtendedDescription()), m_highlight(defaultHighLight()), m_ignoreDryRun(defaultIgnoreDryRun()), m_silent(defaultIsSilent()) { } AbstractCommand::~AbstractCommand() { } bool AbstractCommand::equals(const AbstractCommand *other) const { return type() == other->type() && m_description == other->m_description && m_extendedDescription == other->m_extendedDescription && m_highlight == other->m_highlight && m_ignoreDryRun == other->m_ignoreDryRun && m_silent == other->m_silent && m_jobPool == other->m_jobPool && m_properties == other->m_properties; } void AbstractCommand::fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation) { m_description = scriptValue->property(StringConstants::descriptionProperty()).toString(); m_extendedDescription = scriptValue->property(extendedDescriptionProperty()).toString(); m_highlight = scriptValue->property(highlightProperty()).toString(); m_ignoreDryRun = scriptValue->property(ignoreDryRunProperty()).toBool(); m_silent = scriptValue->property(silentProperty()).toBool(); m_jobPool = scriptValue->property(StringConstants::jobPoolProperty()).toString(); m_codeLocation = codeLocation; m_predefinedProperties << StringConstants::descriptionProperty() << extendedDescriptionProperty() << highlightProperty() << ignoreDryRunProperty() << StringConstants::jobPoolProperty() << silentProperty(); } QString AbstractCommand::fullDescription(const QString &productName) const { return description() + QLatin1String(" [") + productName + QLatin1Char(']'); } void AbstractCommand::load(PersistentPool &pool) { serializationOp(pool); } void AbstractCommand::store(PersistentPool &pool) { serializationOp(pool); } void AbstractCommand::applyCommandProperties(const QScriptValue *scriptValue) { QScriptValueIterator it(*scriptValue); while (it.hasNext()) { it.next(); if (m_predefinedProperties.contains(it.name())) continue; const QVariant value = it.value().toVariant(); if (QMetaType::Type(value.type()) == QMetaType::QObjectStar || it.value().scriptClass() || it.value().data().isValid()) { throw ErrorInfo(Tr::tr("Property '%1' has a type unsuitable for storing in a command " "object.").arg(it.name()), m_codeLocation); } m_properties.insert(it.name(), value); } } static QScriptValue js_CommandBase(QScriptContext *context, QScriptEngine *engine) { QScriptValue cmd = context->thisObject(); QBS_ASSERT(context->isCalledAsConstructor(), cmd = engine->newObject()); cmd.setProperty(StringConstants::descriptionProperty(), engine->toScriptValue(AbstractCommand::defaultDescription())); cmd.setProperty(extendedDescriptionProperty(), engine->toScriptValue(AbstractCommand::defaultExtendedDescription())); cmd.setProperty(highlightProperty(), engine->toScriptValue(AbstractCommand::defaultHighLight())); cmd.setProperty(ignoreDryRunProperty(), engine->toScriptValue(AbstractCommand::defaultIgnoreDryRun())); cmd.setProperty(silentProperty(), engine->toScriptValue(AbstractCommand::defaultIsSilent())); return cmd; } static QScriptValue js_Command(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(!context->isCalledAsConstructor())) return context->throwError(Tr::tr("Command constructor called without new.")); static ProcessCommandPtr commandPrototype = ProcessCommand::create(); QScriptValue program = context->argument(0); if (program.isUndefined()) program = engine->toScriptValue(commandPrototype->program()); QScriptValue arguments = context->argument(1); if (arguments.isUndefined()) arguments = engine->toScriptValue(commandPrototype->arguments()); QScriptValue cmd = js_CommandBase(context, engine); cmd.setProperty(StringConstants::classNameProperty(), engine->toScriptValue(StringConstants::commandType())); cmd.setProperty(programProperty(), program); cmd.setProperty(argumentsProperty(), arguments); cmd.setProperty(workingDirProperty(), engine->toScriptValue(commandPrototype->workingDir())); cmd.setProperty(maxExitCodeProperty(), engine->toScriptValue(commandPrototype->maxExitCode())); cmd.setProperty(stdoutFilterFunctionProperty(), engine->toScriptValue(commandPrototype->stdoutFilterFunction())); cmd.setProperty(stderrFilterFunctionProperty(), engine->toScriptValue(commandPrototype->stderrFilterFunction())); cmd.setProperty(responseFileThresholdProperty(), engine->toScriptValue(commandPrototype->responseFileThreshold())); cmd.setProperty(responseFileArgumentIndexProperty(), engine->toScriptValue(commandPrototype->responseFileArgumentIndex())); cmd.setProperty(responseFileUsagePrefixProperty(), engine->toScriptValue(commandPrototype->responseFileUsagePrefix())); cmd.setProperty(stdoutFilePathProperty(), engine->toScriptValue(commandPrototype->stdoutFilePath())); cmd.setProperty(stderrFilePathProperty(), engine->toScriptValue(commandPrototype->stderrFilePath())); cmd.setProperty(environmentProperty(), engine->toScriptValue(commandPrototype->environment().toStringList())); cmd.setProperty(ignoreDryRunProperty(), engine->toScriptValue(commandPrototype->ignoreDryRun())); return cmd; } void ProcessCommand::setupForJavaScript(QScriptValue targetObject) { QBS_CHECK(targetObject.isObject()); QScriptValue ctor = targetObject.engine()->newFunction(js_Command, 2); targetObject.setProperty(StringConstants::commandType(), ctor); } ProcessCommand::ProcessCommand() : m_maxExitCode(0) , m_responseFileThreshold(defaultResponseFileThreshold()) , m_responseFileArgumentIndex(0) { } int ProcessCommand::defaultResponseFileThreshold() const { // TODO: Non-Windows platforms likely have their own limits. Investigate. return HostOsInfo::isWindowsHost() ? 31000 // 32000 minus "safety offset" : -1; } void ProcessCommand::getEnvironmentFromList(const QStringList &envList) { m_environment.clear(); for (const QString &env : envList) { const int equalsIndex = env.indexOf(QLatin1Char('=')); if (equalsIndex <= 0 || equalsIndex == env.size() - 1) continue; const QString &var = env.left(equalsIndex); const QString &value = env.mid(equalsIndex + 1); m_environment.insert(var, value); } } bool ProcessCommand::equals(const AbstractCommand *otherAbstractCommand) const { if (!AbstractCommand::equals(otherAbstractCommand)) return false; const auto other = static_cast(otherAbstractCommand); return m_program == other->m_program && m_arguments == other->m_arguments && m_workingDir == other->m_workingDir && m_maxExitCode == other->m_maxExitCode && m_stdoutFilterFunction == other->m_stdoutFilterFunction && m_stderrFilterFunction == other->m_stderrFilterFunction && m_responseFileThreshold == other->m_responseFileThreshold && m_responseFileArgumentIndex == other->m_responseFileArgumentIndex && m_responseFileUsagePrefix == other->m_responseFileUsagePrefix && m_stdoutFilePath == other->m_stdoutFilePath && m_stderrFilePath == other->m_stderrFilePath && m_relevantEnvVars == other->m_relevantEnvVars && m_relevantEnvValues == other->m_relevantEnvValues && m_environment == other->m_environment; } void ProcessCommand::fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation) { AbstractCommand::fillFromScriptValue(scriptValue, codeLocation); m_program = scriptValue->property(programProperty()).toString(); m_arguments = scriptValue->property(argumentsProperty()).toVariant().toStringList(); m_workingDir = scriptValue->property(workingDirProperty()).toString(); m_maxExitCode = scriptValue->property(maxExitCodeProperty()).toInt32(); // toString() is required, presumably due to QtScript bug that manifests itself on Windows const QScriptValue stdoutFilterFunction = scriptValue->property(stdoutFilterFunctionProperty()).toString(); m_stdoutFilterFunction = invokedSourceCode(stdoutFilterFunction); // toString() is required, presumably due to QtScript bug that manifests itself on Windows const QScriptValue stderrFilterFunction = scriptValue->property(stderrFilterFunctionProperty()).toString(); m_stderrFilterFunction = invokedSourceCode(stderrFilterFunction); m_relevantEnvVars = scriptValue->property(QStringLiteral("relevantEnvironmentVariables")) .toVariant().toStringList(); m_responseFileThreshold = scriptValue->property(responseFileThresholdProperty()) .toInt32(); m_responseFileArgumentIndex = scriptValue->property(responseFileArgumentIndexProperty()) .toInt32(); m_responseFileUsagePrefix = scriptValue->property(responseFileUsagePrefixProperty()) .toString(); QStringList envList = scriptValue->property(environmentProperty()).toVariant() .toStringList(); getEnvironmentFromList(envList); m_stdoutFilePath = scriptValue->property(stdoutFilePathProperty()).toString(); m_stderrFilePath = scriptValue->property(stderrFilePathProperty()).toString(); m_predefinedProperties << programProperty() << argumentsProperty() << workingDirProperty() << maxExitCodeProperty() << stdoutFilterFunctionProperty() << stderrFilterFunctionProperty() << responseFileThresholdProperty() << responseFileArgumentIndexProperty() << responseFileUsagePrefixProperty() << environmentProperty() << stdoutFilePathProperty() << stderrFilePathProperty(); applyCommandProperties(scriptValue); } QStringList ProcessCommand::relevantEnvVars() const { QStringList vars = m_relevantEnvVars; if (!FileInfo::isAbsolute(program())) vars << StringConstants::pathEnvVar(); return vars; } void ProcessCommand::addRelevantEnvValue(const QString &key, const QString &value) { m_relevantEnvValues.insert(key, value); } void ProcessCommand::load(PersistentPool &pool) { AbstractCommand::load(pool); serializationOp(pool); } void ProcessCommand::store(PersistentPool &pool) { AbstractCommand::store(pool); serializationOp(pool); } static QString currentImportScopeName(QScriptContext *context) { for (; context; context = context->parentContext()) { QScriptValue v = context->thisObject() .property(StringConstants::importScopeNamePropertyInternal()); if (v.isString()) return v.toString(); } return {}; } static QScriptValue js_JavaScriptCommand(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(!context->isCalledAsConstructor())) return context->throwError(Tr::tr("JavaScriptCommand constructor called without new.")); if (Q_UNLIKELY(context->argumentCount() != 0)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("JavaScriptCommand c'tor doesn't take arguments.")); } static JavaScriptCommandPtr commandPrototype = JavaScriptCommand::create(); QScriptValue cmd = js_CommandBase(context, engine); cmd.setProperty(StringConstants::classNameProperty(), engine->toScriptValue(StringConstants::javaScriptCommandType())); cmd.setProperty(StringConstants::sourceCodeProperty(), engine->toScriptValue(commandPrototype->sourceCode())); cmd.setProperty(StringConstants::importScopeNamePropertyInternal(), engine->toScriptValue(currentImportScopeName(context))); return cmd; } void JavaScriptCommand::setupForJavaScript(QScriptValue targetObject) { QBS_CHECK(targetObject.isObject()); QScriptValue ctor = targetObject.engine()->newFunction(js_JavaScriptCommand, 0); targetObject.setProperty(StringConstants::javaScriptCommandType(), ctor); } JavaScriptCommand::JavaScriptCommand() { } bool JavaScriptCommand::equals(const AbstractCommand *otherAbstractCommand) const { if (!AbstractCommand::equals(otherAbstractCommand)) return false; auto const other = static_cast(otherAbstractCommand); return m_sourceCode == other->m_sourceCode; } void JavaScriptCommand::fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation) { AbstractCommand::fillFromScriptValue(scriptValue, codeLocation); const QScriptValue importScope = scriptValue->property( StringConstants::importScopeNamePropertyInternal()); if (importScope.isString()) m_scopeName = importScope.toString(); const QScriptValue sourceCode = scriptValue->property(StringConstants::sourceCodeProperty()); m_sourceCode = invokedSourceCode(sourceCode); m_predefinedProperties << StringConstants::classNameProperty() << StringConstants::sourceCodeProperty() << StringConstants::importScopeNamePropertyInternal(); applyCommandProperties(scriptValue); } void JavaScriptCommand::load(PersistentPool &pool) { AbstractCommand::load(pool); serializationOp(pool); } void JavaScriptCommand::store(PersistentPool &pool) { AbstractCommand::store(pool); serializationOp(pool); } void CommandList::load(PersistentPool &pool) { m_commands.clear(); int count = pool.load(); m_commands.reserve(count); while (--count >= 0) { const auto cmdType = pool.load(); AbstractCommandPtr cmd; switch (cmdType) { case AbstractCommand::JavaScriptCommandType: cmd = pool.load(); break; case AbstractCommand::ProcessCommandType: cmd = pool.load(); break; default: QBS_CHECK(false); } addCommand(cmd); } } void CommandList::store(PersistentPool &pool) const { pool.store(m_commands.size()); for (const AbstractCommandPtr &cmd : m_commands) { pool.store(static_cast(cmd->type())); pool.store(cmd); } } bool operator==(const CommandList &l1, const CommandList &l2) { if (l1.size() != l2.size()) return false; for (int i = 0; i < l1.size(); ++i) if (!l1.commandAt(i)->equals(l2.commandAt(i).get())) return false; return true; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/rulecommands.h000066400000000000000000000214751347155106100231220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BUILDGRAPH_COMMAND_H #define QBS_BUILDGRAPH_COMMAND_H #include "forward_decls.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { class AbstractCommand { public: virtual ~AbstractCommand(); enum CommandType { ProcessCommandType, JavaScriptCommandType }; static QString defaultDescription() { return {}; } static QString defaultExtendedDescription() { return {}; } static QString defaultHighLight() { return {}; } static bool defaultIgnoreDryRun() { return false; } static bool defaultIsSilent() { return false; } virtual CommandType type() const = 0; virtual bool equals(const AbstractCommand *other) const; virtual void fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation); QString fullDescription(const QString &productName) const; const QString description() const { return m_description; } const QString extendedDescription() const { return m_extendedDescription; } const QString highlight() const { return m_highlight; } bool ignoreDryRun() const { return m_ignoreDryRun; } bool isSilent() const { return m_silent; } QString jobPool() const { return m_jobPool; } CodeLocation codeLocation() const { return m_codeLocation; } const QVariantMap &properties() const { return m_properties; } virtual void load(PersistentPool &pool); virtual void store(PersistentPool &pool); protected: AbstractCommand(); void applyCommandProperties(const QScriptValue *scriptValue); Set m_predefinedProperties; private: template void serializationOp(PersistentPool &pool) { pool.serializationOp(m_description, m_extendedDescription, m_highlight, m_ignoreDryRun, m_silent, m_codeLocation, m_jobPool, m_properties); } QString m_description; QString m_extendedDescription; QString m_highlight; bool m_ignoreDryRun; bool m_silent; CodeLocation m_codeLocation; QString m_jobPool; QVariantMap m_properties; }; class ProcessCommand : public AbstractCommand { public: static ProcessCommandPtr create() { return ProcessCommandPtr(new ProcessCommand); } static void setupForJavaScript(QScriptValue targetObject); CommandType type() const override { return ProcessCommandType; } bool equals(const AbstractCommand *otherAbstractCommand) const override; void fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation) override; const QString program() const { return m_program; } const QStringList arguments() const { return m_arguments; } const QString workingDir() const { return m_workingDir; } int maxExitCode() const { return m_maxExitCode; } QString stdoutFilterFunction() const { return m_stdoutFilterFunction; } QString stderrFilterFunction() const { return m_stderrFilterFunction; } int responseFileThreshold() const { return m_responseFileThreshold; } int responseFileArgumentIndex() const { return m_responseFileArgumentIndex; } QString responseFileUsagePrefix() const { return m_responseFileUsagePrefix; } QProcessEnvironment environment() const { return m_environment; } QStringList relevantEnvVars() const; void clearRelevantEnvValues() { m_relevantEnvValues.clear(); } void addRelevantEnvValue(const QString &key, const QString &value); QString relevantEnvValue(const QString &key) const { return m_relevantEnvValues.value(key); } QString stdoutFilePath() const { return m_stdoutFilePath; } QString stderrFilePath() const { return m_stderrFilePath; } void load(PersistentPool &pool) override; void store(PersistentPool &pool) override; private: ProcessCommand(); int defaultResponseFileThreshold() const; void getEnvironmentFromList(const QStringList &envList); template void serializationOp(PersistentPool &pool) { pool.serializationOp(m_program, m_arguments, m_environment, m_workingDir, m_stdoutFilterFunction, m_stderrFilterFunction, m_responseFileUsagePrefix, m_maxExitCode, m_responseFileThreshold, m_responseFileArgumentIndex, m_relevantEnvVars, m_relevantEnvValues, m_stdoutFilePath, m_stderrFilePath); } QString m_program; QStringList m_arguments; QString m_workingDir; int m_maxExitCode; QString m_stdoutFilterFunction; QString m_stderrFilterFunction; int m_responseFileThreshold; // When to use response files? In bytes of (program name + arguments). int m_responseFileArgumentIndex; QString m_responseFileUsagePrefix; QProcessEnvironment m_environment; QStringList m_relevantEnvVars; QProcessEnvironment m_relevantEnvValues; QString m_stdoutFilePath; QString m_stderrFilePath; }; class JavaScriptCommand : public AbstractCommand { public: static JavaScriptCommandPtr create() { return JavaScriptCommandPtr(new JavaScriptCommand); } static void setupForJavaScript(QScriptValue targetObject); CommandType type() const override { return JavaScriptCommandType; } bool equals(const AbstractCommand *otherAbstractCommand) const override; void fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation) override; const QString &scopeName() const { return m_scopeName; } const QString &sourceCode() const { return m_sourceCode; } void setSourceCode(const QString &str) { m_sourceCode = str; } void load(PersistentPool &pool) override; void store(PersistentPool &pool) override; private: JavaScriptCommand(); template void serializationOp(PersistentPool &pool) { pool.serializationOp(m_scopeName, m_sourceCode); } QString m_scopeName; QString m_sourceCode; }; class CommandList { public: bool empty() const { return m_commands.empty(); } int size() const { return m_commands.size(); } AbstractCommandPtr commandAt(int i) const { return m_commands.at(i); } const QList &commands() const { return m_commands; } void clear() { m_commands.clear(); } void addCommand(const AbstractCommandPtr &cmd) { m_commands.push_back(cmd); } void load(PersistentPool &pool); void store(PersistentPool &pool) const; private: QList m_commands; }; bool operator==(const CommandList &cl1, const CommandList &cl2); inline bool operator!=(const CommandList &cl1, const CommandList &cl2) { return !(cl1 == cl2); } } // namespace Internal } // namespace qbs #endif // QBS_BUILDGRAPH_COMMAND_H qbs-src-1.13.1/src/lib/corelib/buildgraph/rulegraph.cpp000066400000000000000000000125411347155106100227470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "rulegraph.h" #include #include #include #include namespace qbs { namespace Internal { RuleGraph::RuleGraph() { } void RuleGraph::build(const std::vector &rules, const FileTags &productFileTags) { QMap > inputFileTagToRule; m_rules.reserve(rules.size()); for (const RulePtr &rule : rules) { for (const FileTag &fileTag : rule->collectedOutputFileTags()) m_outputFileTagToRule[fileTag].push_back(rule.get()); insert(rule); } m_parents.resize(rules.size()); m_children.resize(rules.size()); for (const RuleConstPtr &rule : qAsConst(m_rules)) { FileTags inFileTags = rule->inputs; inFileTags += rule->auxiliaryInputs; inFileTags += rule->explicitlyDependsOn; for (const FileTag &fileTag : qAsConst(inFileTags)) { inputFileTagToRule[fileTag].push_back(rule.get()); for (const Rule * const producingRule : m_outputFileTagToRule.value(fileTag)) { if (!producingRule->collectedOutputFileTags().intersects( rule->excludedInputs)) { connect(rule.get(), producingRule); } } } } QList productRules; for (const FileTag &productFileTag : productFileTags) { QList rules = m_outputFileTagToRule.value(productFileTag); productRules << rules; //### check: the rule graph must be a in valid shape! } for (const Rule *r : qAsConst(productRules)) m_rootRules += r->ruleGraphId; } void RuleGraph::accept(RuleGraphVisitor *visitor) const { const RuleConstPtr nullParent; for (int rootIndex : qAsConst(m_rootRules)) traverse(visitor, nullParent, m_rules.at(rootIndex)); } void RuleGraph::dump() const { QByteArray indent; printf("---rule graph dump:\n"); Set rootRules; for (const RuleConstPtr &rule : qAsConst(m_rules)) if (m_parents[rule->ruleGraphId].empty()) rootRules += rule->ruleGraphId; for (int idx : qAsConst(rootRules)) dump_impl(indent, idx); } void RuleGraph::dump_impl(QByteArray &indent, int rootIndex) const { const RuleConstPtr r = m_rules[rootIndex]; printf("%s", indent.constData()); printf("%s", qPrintable(r->toString())); printf("\n"); indent.append(" "); for (int childIndex : qAsConst(m_children[rootIndex])) dump_impl(indent, childIndex); indent.chop(2); } int RuleGraph::insert(const RulePtr &rule) { rule->ruleGraphId = int(m_rules.size()); m_rules.push_back(rule); return rule->ruleGraphId; } void RuleGraph::connect(const Rule *creatingRule, const Rule *consumingRule) { int maxIndex = std::max(creatingRule->ruleGraphId, consumingRule->ruleGraphId); if (static_cast(m_parents.size()) <= maxIndex) { const int c = maxIndex + 1; m_parents.resize(c); m_children.resize(c); } m_parents[consumingRule->ruleGraphId].push_back(creatingRule->ruleGraphId); m_children[creatingRule->ruleGraphId].push_back(consumingRule->ruleGraphId); } void RuleGraph::traverse(RuleGraphVisitor *visitor, const RuleConstPtr &parentRule, const RuleConstPtr &rule) const { visitor->visit(parentRule, rule); for (int childIndex : m_children.at(rule->ruleGraphId)) traverse(visitor, rule, m_rules.at(childIndex)); visitor->endVisit(rule); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/rulegraph.h000066400000000000000000000061341347155106100224150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_RULEGRAPH_H #define QBS_RULEGRAPH_H #include #include #include #include #include #include #include namespace qbs { namespace Internal { class RuleGraphVisitor { public: virtual void visit(const RuleConstPtr &parentRule, const RuleConstPtr &rule) = 0; virtual void endVisit(const RuleConstPtr &rule) { Q_UNUSED(rule); } }; class RuleGraph { public: RuleGraph(); void build(const std::vector &rules, const FileTags &productFileTag); void accept(RuleGraphVisitor *visitor) const; void dump() const; private: void dump_impl(QByteArray &indent, int rootIndex) const; int insert(const RulePtr &rule); void connect(const Rule *creatingRule, const Rule *consumingRule); void traverse(RuleGraphVisitor *visitor, const RuleConstPtr &parentRule, const RuleConstPtr &rule) const; private: QMap > m_outputFileTagToRule; std::vector m_rules; std::vector< std::vector > m_parents; std::vector< std::vector > m_children; Set m_rootRules; }; } // namespace Internal } // namespace qbs #endif // QBS_RULEGRAPH_H qbs-src-1.13.1/src/lib/corelib/buildgraph/rulenode.cpp000066400000000000000000000312361347155106100225750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "rulenode.h" #include "buildgraph.h" #include "buildgraphvisitor.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "rulesapplicator.h" #include "transformer.h" #include "transformerchangetracking.h" #include #include #include #include #include namespace qbs { namespace Internal { RuleNode::RuleNode() { } RuleNode::~RuleNode() { } void RuleNode::accept(BuildGraphVisitor *visitor) { if (visitor->visit(this)) acceptChildren(visitor); visitor->endVisit(this); } QString RuleNode::toString() const { return QLatin1String("RULE ") + m_rule->toString() + QLatin1String(" [") + (!product.expired() ? product->name : QLatin1String("")) + QLatin1Char(']') + QLatin1String(" located at ") + m_rule->prepareScript.location().toString(); } void RuleNode::apply(const Logger &logger, const std::unordered_map &productsByName, const std::unordered_map &projectsByName, ApplicationResult *result) { ArtifactSet allCompatibleInputs = currentInputArtifacts(); const ArtifactSet explicitlyDependsOn = RulesApplicator::collectExplicitlyDependsOn(m_rule.get(), product.get()); const ArtifactSet auxiliaryInputs = RulesApplicator::collectAuxiliaryInputs(m_rule.get(), product.get()); const ArtifactSet addedInputs = allCompatibleInputs - m_oldInputArtifacts; const ArtifactSet removedInputs = m_oldInputArtifacts - allCompatibleInputs; const ArtifactSet changedInputs = changedInputArtifacts(allCompatibleInputs, explicitlyDependsOn, auxiliaryInputs); bool upToDate = changedInputs.empty() && addedInputs.empty() && removedInputs.empty(); qCDebug(lcBuildGraph).noquote().nospace() << "consider " << (m_rule->isDynamic() ? "dynamic " : "") << (m_rule->multiplex ? "multiplex " : "") << "rule node " << m_rule->toString() << "\n\tchanged: " << changedInputs.toString() << "\n\tcompatible: " << allCompatibleInputs.toString() << "\n\tadded: " << addedInputs.toString() << "\n\tremoved: " << removedInputs.toString(); ArtifactSet inputs = changedInputs; if (m_rule->multiplex) inputs = allCompatibleInputs; else inputs += addedInputs; for (Artifact * const input : allCompatibleInputs) { for (const Artifact * const output : input->parentArtifacts()) { if (output->transformer->rule != m_rule) continue; if (prepareScriptNeedsRerun(output->transformer.get(), output->transformer->product().get(), productsByName, projectsByName)) { upToDate = false; inputs += input; } break; } if (m_rule->multiplex) break; } // Handle rules without inputs: We want to run such a rule if and only if it has not run yet // or its transformer is not up to date regarding the prepare script. if (upToDate && (!m_rule->declaresInputs() || !m_rule->requiresInputs) && inputs.empty()) { bool hasOutputs = false; for (const Artifact * const output : filterByType(parents)) { if (output->transformer->rule != m_rule) continue; hasOutputs = true; if (prepareScriptNeedsRerun(output->transformer.get(), output->transformer->product().get(), productsByName, projectsByName)) { upToDate = false; break; } if (m_rule->multiplex) break; } if (!hasOutputs) upToDate = false; } if (upToDate) { qCDebug(lcExec) << "rule is up to date. Skipping."; return; } const bool mustApplyRule = !inputs.empty() || !m_rule->declaresInputs() || !m_rule->requiresInputs; // For a non-multiplex rule, the removal of an input always implies that the // corresponding outputs disappear. // For a multiplex rule, the outputs disappear only if *all* inputs are gone *and* // the rule requires inputs. This is exactly the opposite condition of whether to // re-apply the rule. const bool removedInputForcesOutputRemoval = !m_rule->multiplex || !mustApplyRule; ArtifactSet outputArtifactsToRemove; std::vector> connectionsToBreak; for (Artifact * const artifact : removedInputs) { if (!artifact) // dummy artifact continue; for (Artifact *parent : filterByType(artifact->parents)) { if (parent->transformer->rule != m_rule) { // parent was not created by our rule. continue; } // parent must always have a transformer, because it's generated. QBS_CHECK(parent->transformer); // artifact is a former input of m_rule and parent was created by m_rule // the inputs of the transformer must contain artifact QBS_CHECK(parent->transformer->inputs.contains(artifact)); if (removedInputForcesOutputRemoval) outputArtifactsToRemove += parent; else connectionsToBreak.push_back(std::make_pair(parent, artifact)); } disconnect(this, artifact); } for (const auto &connection : connectionsToBreak) disconnect(connection.first, connection.second); if (!outputArtifactsToRemove.empty()) { RulesApplicator::handleRemovedRuleOutputs(inputs, outputArtifactsToRemove, result->removedArtifacts, logger); } if (mustApplyRule) { RulesApplicator applicator(product.lock(), productsByName, projectsByName, logger); applicator.applyRule(this, inputs, explicitlyDependsOn); result->createdArtifacts = applicator.createdArtifacts(); result->invalidatedArtifacts = applicator.invalidatedArtifacts(); m_lastApplicationTime = FileTime::currentTime(); if (applicator.ruleUsesIo()) m_needsToConsiderChangedInputs = true; } else { qCDebug(lcExec).noquote() << "prepare script does not need to run"; } m_oldInputArtifacts = allCompatibleInputs; m_oldExplicitlyDependsOn = explicitlyDependsOn; m_oldAuxiliaryInputs = auxiliaryInputs; product->topLevelProject()->buildData->setDirty(); } void RuleNode::load(PersistentPool &pool) { BuildGraphNode::load(pool); serializationOp(pool); } void RuleNode::store(PersistentPool &pool) { BuildGraphNode::store(pool); serializationOp(pool); } int RuleNode::transformerCount() const { Set transformers; for (const Artifact * const output : filterByType(parents)) transformers.insert(output->transformer.get()); return transformers.size(); } ArtifactSet RuleNode::currentInputArtifacts() const { ArtifactSet s; for (const FileTag &t : qAsConst(m_rule->inputs)) { for (Artifact *artifact : product->lookupArtifactsByFileTag(t)) { if (artifact->isTargetOfModule()) continue; if (artifact->transformer && artifact->transformer->rule == m_rule) { // Do not add compatible artifacts as inputs that were created by this rule. // This can e.g. happen for the ["cpp", "hpp"] -> ["hpp", "cpp", "unmocable"] rule. continue; } if (artifact->fileTags().intersects(m_rule->excludedInputs)) continue; s += artifact; } } if (m_rule->inputsFromDependencies.empty()) return s; for (const FileTag &t : qAsConst(m_rule->inputsFromDependencies)) { for (Artifact *artifact : product->lookupArtifactsByFileTag(t)) { if (!artifact->isTargetOfModule()) continue; if (artifact->transformer && artifact->transformer->rule == m_rule) continue; if (artifact->fileTags().intersects(m_rule->excludedInputs)) continue; s += artifact; } } for (const ResolvedProductConstPtr &dep : qAsConst(product->dependencies)) { if (!dep->buildData) continue; for (Artifact * const a : filterByType(dep->buildData->allNodes())) { if (a->fileTags().intersects(m_rule->inputsFromDependencies) && !a->fileTags().intersects(m_rule->excludedInputs)) s += a; } } return s; } ArtifactSet RuleNode::changedInputArtifacts(const ArtifactSet &allCompatibleInputs, const ArtifactSet &explicitlyDependsOn, const ArtifactSet &auxiliaryInputs) const { ArtifactSet changedInputArtifacts; if (explicitlyDependsOn != m_oldExplicitlyDependsOn) return allCompatibleInputs; if (!m_needsToConsiderChangedInputs) return changedInputArtifacts; for (Artifact * const artifact : explicitlyDependsOn) { if (artifact->timestamp() > m_lastApplicationTime) return allCompatibleInputs; } if (auxiliaryInputs != m_oldAuxiliaryInputs) return allCompatibleInputs; for (Artifact * const artifact : auxiliaryInputs) { if (artifact->timestamp() > m_lastApplicationTime) return allCompatibleInputs; } for (Artifact * const artifact : allCompatibleInputs) { if (artifact->timestamp() > m_lastApplicationTime) changedInputArtifacts.insert(artifact); } return changedInputArtifacts; } void RuleNode::removeOldInputArtifact(Artifact *artifact) { if (m_oldInputArtifacts.remove(artifact)) { qCDebug(lcBuildGraph) << "remove old input" << artifact->filePath() << "from rule" << rule()->toString(); m_oldInputArtifacts.insert(nullptr); } if (m_oldExplicitlyDependsOn.remove(artifact)) { qCDebug(lcBuildGraph) << "remove old explicitlyDependsOn" << artifact->filePath() << "from rule" << rule()->toString(); m_oldExplicitlyDependsOn.insert(nullptr); } if (m_oldAuxiliaryInputs.remove(artifact)) { qCDebug(lcBuildGraph) << "remove old auxiliaryInput" << artifact->filePath() << "from rule" << rule()->toString(); m_oldAuxiliaryInputs.insert(nullptr); } } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/rulenode.h000066400000000000000000000106231347155106100222370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_RULENODE_H #define QBS_RULENODE_H #include "artifact.h" #include "buildgraphnode.h" #include "forward_decls.h" #include #include #include #include namespace qbs { namespace Internal { class Logger; class RuleNode : public BuildGraphNode { public: RuleNode(); ~RuleNode(); void setRule(const RuleConstPtr &rule) { m_rule = rule; } const RuleConstPtr &rule() const { return m_rule; } Type type() const override { return RuleNodeType; } void accept(BuildGraphVisitor *visitor) override; QString toString() const override; struct ApplicationResult { NodeSet createdArtifacts; NodeSet invalidatedArtifacts; QStringList removedArtifacts; }; void apply(const Logger &logger, const std::unordered_map &productsByName, const std::unordered_map &projectsByName, ApplicationResult *result); void removeOldInputArtifact(Artifact *artifact); void load(PersistentPool &pool) override; void store(PersistentPool &pool) override; int transformerCount() const; private: template void serializationOp(PersistentPool &pool) { pool.serializationOp(m_rule, m_oldInputArtifacts, m_oldExplicitlyDependsOn, m_oldAuxiliaryInputs, m_lastApplicationTime, m_needsToConsiderChangedInputs); } ArtifactSet currentInputArtifacts() const; ArtifactSet changedInputArtifacts(const ArtifactSet &allCompatibleInputs, const ArtifactSet &explicitlyDependsOn, const ArtifactSet &auxiliaryInputs) const; RuleConstPtr m_rule; // These three can contain null pointers, which represent a "dummy artifact" encoding // the information that an artifact that used to be in here has ceased to exist. // This is okay, because no code outside this class has access to these sets, so // we cannot break any assumptions about non-nullness. ArtifactSet m_oldInputArtifacts; ArtifactSet m_oldExplicitlyDependsOn; ArtifactSet m_oldAuxiliaryInputs; FileTime m_lastApplicationTime; bool m_needsToConsiderChangedInputs = false; }; template<> inline bool hasDynamicType(const BuildGraphNode *n) { return n->type() == BuildGraphNode::RuleNodeType; } } // namespace Internal } // namespace qbs #endif // QBS_RULENODE_H qbs-src-1.13.1/src/lib/corelib/buildgraph/rulesapplicator.cpp000066400000000000000000000726061347155106100241770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "rulesapplicator.h" #include "buildgraph.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "qtmocscanner.h" #include "rulecommands.h" #include "rulenode.h" #include "rulesevaluationcontext.h" #include "transformer.h" #include "transformerchangetracking.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { RulesApplicator::RulesApplicator( const ResolvedProductPtr &product, const std::unordered_map &productsByName, const std::unordered_map &projectsByName, const Logger &logger) : m_product(product) , m_productsByName(productsByName) , m_projectsByName(projectsByName) , m_mocScanner(nullptr) , m_logger(logger) { } RulesApplicator::~RulesApplicator() { delete m_mocScanner; } void RulesApplicator::applyRule(RuleNode *ruleNode, const ArtifactSet &inputArtifacts, const ArtifactSet &explicitlyDependsOn) { m_ruleNode = ruleNode; m_rule = ruleNode->rule(); QBS_CHECK(!inputArtifacts.empty() || !m_rule->declaresInputs() || !m_rule->requiresInputs); m_product->topLevelProject()->buildData->setDirty(); m_createdArtifacts.clear(); m_invalidatedArtifacts.clear(); m_removedArtifacts.clear(); m_explicitlyDependsOn = explicitlyDependsOn; RulesEvaluationContext::Scope s(evalContext().get()); m_completeInputSet = inputArtifacts; if (m_rule->name.startsWith(QLatin1String("QtCoreMocRule"))) { delete m_mocScanner; m_mocScanner = new QtMocScanner(m_product, scope()); } QScriptValue prepareScriptContext = engine()->newObject(); prepareScriptContext.setPrototype(engine()->globalObject()); setupScriptEngineForFile(engine(), m_rule->prepareScript.fileContext(), scope(), ObserveMode::Enabled); setupScriptEngineForProduct(engine(), m_product.get(), m_rule->module.get(), prepareScriptContext, true); engine()->clearUsesIo(); if (m_rule->multiplex) { // apply the rule once for a set of inputs doApply(inputArtifacts, prepareScriptContext); } else { // apply the rule once for each input for (Artifact * const inputArtifact : inputArtifacts) { ArtifactSet lst; lst += inputArtifact; doApply(lst, prepareScriptContext); } } if (engine()->usesIo()) m_ruleUsesIo = true; } void RulesApplicator::handleRemovedRuleOutputs(const ArtifactSet &inputArtifacts, const ArtifactSet &outputArtifactsToRemove, QStringList &removedArtifacts, const Logger &logger) { ArtifactSet artifactsToRemove; const TopLevelProject *project = nullptr; for (Artifact * const removedArtifact : outputArtifactsToRemove) { qCDebug(lcBuildGraph).noquote() << "dynamic rule removed output artifact" << removedArtifact->toString(); if (!project) project = removedArtifact->product->topLevelProject(); project->buildData->removeArtifactAndExclusiveDependents(removedArtifact, logger, true, &artifactsToRemove); } for (Artifact * const artifact : qAsConst(artifactsToRemove)) { QBS_CHECK(!inputArtifacts.contains(artifact)); removedArtifacts << artifact->filePath(); delete artifact; } } ArtifactSet RulesApplicator::collectAuxiliaryInputs(const Rule *rule, const ResolvedProduct *product) { return collectAdditionalInputs(rule->auxiliaryInputs, rule, product, CurrentProduct | Dependencies); } static void copyProperty(const QString &name, const QScriptValue &src, QScriptValue dst) { dst.setProperty(name, src.property(name)); } static QStringList toStringList(const ArtifactSet &artifacts) { QStringList lst; for (const Artifact * const artifact : artifacts) { const QString str = artifact->filePath() + QLatin1String(" [") + artifact->fileTags().toStringList().join(QLatin1String(", ")) + QLatin1Char(']'); lst << str; } return lst; } void RulesApplicator::doApply(const ArtifactSet &inputArtifacts, QScriptValue &prepareScriptContext) { evalContext()->checkForCancelation(); for (const Artifact *inputArtifact : inputArtifacts) QBS_CHECK(!inputArtifact->fileTags().intersects(m_rule->excludedInputs)); qCDebug(lcBuildGraph) << "apply rule" << m_rule->toString() << toStringList(inputArtifacts).join(QLatin1String(",\n ")); QList> ruleArtifactArtifactMap; QList outputArtifacts; m_transformer = Transformer::create(); m_transformer->rule = m_rule; m_transformer->inputs = inputArtifacts; m_transformer->explicitlyDependsOn = m_explicitlyDependsOn; m_transformer->alwaysRun = m_rule->alwaysRun; m_oldTransformer.reset(); engine()->clearRequestedProperties(); // create the output artifacts from the set of input artifacts m_transformer->setupInputs(prepareScriptContext); m_transformer->setupExplicitlyDependsOn(prepareScriptContext); copyProperty(StringConstants::inputsVar(), prepareScriptContext, scope()); copyProperty(StringConstants::inputVar(), prepareScriptContext, scope()); copyProperty(StringConstants::explicitlyDependsOnVar(), prepareScriptContext, scope()); copyProperty(StringConstants::productVar(), prepareScriptContext, scope()); copyProperty(StringConstants::projectVar(), prepareScriptContext, scope()); if (m_rule->isDynamic()) { outputArtifacts = runOutputArtifactsScript(inputArtifacts, ScriptEngine::argumentList(Rule::argumentNamesForOutputArtifacts(), scope())); } else { Set outputFilePaths; for (const RuleArtifactConstPtr &ruleArtifact : m_rule->artifacts) { const OutputArtifactInfo outputInfo = createOutputArtifactFromRuleArtifact( ruleArtifact, inputArtifacts, &outputFilePaths); if (!outputInfo.artifact) continue; outputArtifacts.push_back(outputInfo.artifact); ruleArtifactArtifactMap.push_back({ ruleArtifact.get(), outputInfo }); } if (m_rule->artifacts.empty()) { outputArtifacts.push_back(createOutputArtifactFromRuleArtifact( nullptr, inputArtifacts, &outputFilePaths).artifact); } } ArtifactSet newOutputs = ArtifactSet::fromList(outputArtifacts); const ArtifactSet oldOutputs = collectOldOutputArtifacts(inputArtifacts); handleRemovedRuleOutputs(m_completeInputSet, oldOutputs - newOutputs, m_removedArtifacts, m_logger); // The inputs become children of the rule node. Generated artifacts in the same product // already are children, because output artifacts become children of the producing // rule node's parent rule node. for (Artifact * const input : inputArtifacts) { if (input->artifactType == Artifact::SourceFile || input->product != m_ruleNode->product || input->producer()->rule()->collectedOutputFileTags().intersects( m_ruleNode->rule()->excludedInputs)) { connect(m_ruleNode, input); } else { QBS_CHECK(m_ruleNode->children.contains(input)); } } if (outputArtifacts.empty()) return; for (Artifact * const outputArtifact : qAsConst(outputArtifacts)) { for (Artifact * const dependency : qAsConst(m_transformer->explicitlyDependsOn)) connect(outputArtifact, dependency); } if (inputArtifacts != m_transformer->inputs) m_transformer->setupInputs(prepareScriptContext); // change the transformer outputs according to the bindings in Artifact QScriptValue scriptValue; if (!ruleArtifactArtifactMap.empty()) engine()->setGlobalObject(prepareScriptContext); for (auto it = ruleArtifactArtifactMap.crbegin(), end = ruleArtifactArtifactMap.crend(); it != end; ++it) { const RuleArtifact *ra = it->first; if (ra->bindings.empty()) continue; // expose attributes of this artifact const OutputArtifactInfo outputInfo = it->second; Artifact *outputArtifact = outputInfo.artifact; outputArtifact->properties = outputArtifact->properties->clone(); scope().setProperty(StringConstants::fileNameProperty(), engine()->toScriptValue(outputArtifact->filePath())); scope().setProperty(StringConstants::fileTagsProperty(), toScriptValue(engine(), outputArtifact->fileTags().toStringList())); QVariantMap artifactModulesCfg = outputArtifact->properties->value(); for (const auto &binding : ra->bindings) { scriptValue = engine()->evaluate(binding.code); if (Q_UNLIKELY(engine()->hasErrorOrException(scriptValue))) { QString msg = QStringLiteral("evaluating rule binding '%1': %2"); throw ErrorInfo(msg.arg(binding.name.join(QLatin1Char('.')), engine()->lastErrorString(scriptValue)), engine()->lastErrorLocation(scriptValue, binding.location)); } const QVariant value = scriptValue.toVariant(); setConfigProperty(artifactModulesCfg, binding.name, value); outputArtifact->pureProperties.push_back(std::make_pair(binding.name, value)); } outputArtifact->properties->setValue(artifactModulesCfg); if (!outputInfo.newlyCreated && (outputArtifact->fileTags() != outputInfo.oldFileTags || outputArtifact->properties->value() != outputInfo.oldProperties)) { invalidateArtifactAsRuleInputIfNecessary(outputArtifact); } } if (!ruleArtifactArtifactMap.empty()) engine()->setGlobalObject(prepareScriptContext.prototype()); m_transformer->setupOutputs(prepareScriptContext); m_transformer->createCommands(engine(), m_rule->prepareScript, ScriptEngine::argumentList(Rule::argumentNamesForPrepare(), prepareScriptContext)); if (Q_UNLIKELY(m_transformer->commands.empty())) throw ErrorInfo(Tr::tr("There is a rule without commands: %1.") .arg(m_rule->toString()), m_rule->prepareScript.location()); if (!m_oldTransformer || m_oldTransformer->outputs != m_transformer->outputs || m_oldTransformer->inputs != m_transformer->inputs || m_oldTransformer->explicitlyDependsOn != m_transformer->explicitlyDependsOn || m_oldTransformer->commands != m_transformer->commands || commandsNeedRerun(m_transformer.get(), m_product.get(), m_productsByName, m_projectsByName)) { for (Artifact * const output : outputArtifacts) { output->clearTimestamp(); m_invalidatedArtifacts += output; } } m_transformer->commandsNeedChangeTracking = false; } ArtifactSet RulesApplicator::collectOldOutputArtifacts(const ArtifactSet &inputArtifacts) const { ArtifactSet result; for (Artifact * const a : inputArtifacts) { for (Artifact *p : a->parentArtifacts()) { QBS_CHECK(p->transformer); if (p->transformer->rule == m_rule && p->transformer->inputs.contains(a)) result += p; } } return result; } ArtifactSet RulesApplicator::collectAdditionalInputs(const FileTags &tags, const Rule *rule, const ResolvedProduct *product, InputsSources inputsSources) { ArtifactSet artifacts; for (const FileTag &fileTag : tags) { for (Artifact *dependency : product->lookupArtifactsByFileTag(fileTag)) { // Skip excluded inputs. if (dependency->fileTags().intersects(rule->excludedInputs)) continue; // Two cases are considered: // 1) An artifact is considered a dependency when it's part of the current product. // 2) An artifact marked with filesAreTargets: true inside a Group inside of a // Module also ends up in the results returned by product->lookupArtifactsByFileTag, // so it should be considered conceptually as a "dependent product artifact". if ((inputsSources.testFlag(CurrentProduct) && !dependency->isTargetOfModule()) || (inputsSources.testFlag(Dependencies) && dependency->isTargetOfModule())) { artifacts << dependency; } } if (inputsSources.testFlag(Dependencies)) { for (const ResolvedProductConstPtr &depProduct : product->dependencies) { for (Artifact * const ta : depProduct->targetArtifacts()) { if (ta->fileTags().contains(fileTag) && !ta->fileTags().intersects(rule->excludedInputs)) { artifacts << ta; } } } } } return artifacts; } ArtifactSet RulesApplicator::collectExplicitlyDependsOn(const Rule *rule, const ResolvedProduct *product) { ArtifactSet first = collectAdditionalInputs( rule->explicitlyDependsOn, rule, product, CurrentProduct); ArtifactSet second = collectAdditionalInputs( rule->explicitlyDependsOnFromDependencies, rule, product, Dependencies); return first.unite(second); } RulesApplicator::OutputArtifactInfo RulesApplicator::createOutputArtifactFromRuleArtifact( const RuleArtifactConstPtr &ruleArtifact, const ArtifactSet &inputArtifacts, Set *outputFilePaths) { QString outputPath; FileTags fileTags; bool alwaysUpdated; if (ruleArtifact) { QScriptValue scriptValue = engine()->evaluate(ruleArtifact->filePath, ruleArtifact->filePathLocation.filePath(), ruleArtifact->filePathLocation.line()); if (Q_UNLIKELY(engine()->hasErrorOrException(scriptValue))) throw engine()->lastError(scriptValue, ruleArtifact->filePathLocation); outputPath = scriptValue.toString(); fileTags = ruleArtifact->fileTags; alwaysUpdated = ruleArtifact->alwaysUpdated; } else { outputPath = QStringLiteral("__dummyoutput__"); QByteArray hashInput = m_rule->toString().toLatin1(); for (const Artifact * const input : inputArtifacts) hashInput += input->filePath().toLatin1(); outputPath += QLatin1String(QCryptographicHash::hash(hashInput, QCryptographicHash::Sha1) .toHex().left(16)); fileTags = m_rule->outputFileTags; alwaysUpdated = false; } outputPath = FileInfo::resolvePath(m_product->buildDirectory(), outputPath); if (Q_UNLIKELY(!outputFilePaths->insert(outputPath).second)) { throw ErrorInfo(Tr::tr("Rule %1 already created '%2'.") .arg(m_rule->toString(), outputPath)); } return createOutputArtifact(outputPath, fileTags, alwaysUpdated, inputArtifacts); } RulesApplicator::OutputArtifactInfo RulesApplicator::createOutputArtifact(const QString &filePath, const FileTags &fileTags, bool alwaysUpdated, const ArtifactSet &inputArtifacts) { QString outputPath = filePath; // don't let the output artifact "escape" its build dir outputPath.replace(StringConstants::dotDot(), QStringLiteral("dotdot")); outputPath = resolveOutPath(outputPath); if (m_rule->isDynamic()) { const Set undeclaredTags = fileTags - m_rule->collectedOutputFileTags(); if (!undeclaredTags.empty()) { throw ErrorInfo(Tr::tr("Artifact '%1' has undeclared file tags [\"%2\"].") .arg(outputPath, undeclaredTags.toStringList() .join(QLatin1String("\",\""))), m_rule->prepareScript.location()); } } OutputArtifactInfo outputInfo; Artifact *& outputArtifact = outputInfo.artifact; outputArtifact = lookupArtifact(m_product, outputPath); outputInfo.newlyCreated = !outputArtifact; if (outputArtifact) { const Transformer * const transformer = outputArtifact->transformer.get(); if (transformer && transformer->rule != m_rule) { QString e = Tr::tr("Conflicting rules for producing %1 %2 \n") .arg(outputArtifact->filePath(), QLatin1Char('[') + outputArtifact->fileTags().toStringList().join(QLatin1String(", ")) + QLatin1Char(']')); QString str = QLatin1Char('[') + m_rule->inputs.toStringList().join(QLatin1String(", ")) + QLatin1String("] -> [") + outputArtifact->fileTags().toStringList() .join(QLatin1String(", ")) + QLatin1Char(']'); e += QStringLiteral(" while trying to apply: %1:%2:%3 %4\n") .arg(m_rule->prepareScript.location().filePath()) .arg(m_rule->prepareScript.location().line()) .arg(m_rule->prepareScript.location().column()) .arg(str); e += QStringLiteral(" was already defined in: %1:%2:%3 %4\n") .arg(transformer->rule->prepareScript.location().filePath()) .arg(transformer->rule->prepareScript.location().line()) .arg(transformer->rule->prepareScript.location().column()) .arg(str); throw ErrorInfo(e); } if (transformer && !m_rule->multiplex && transformer->inputs != inputArtifacts) { QBS_CHECK(inputArtifacts.size() == 1); QBS_CHECK(transformer->inputs.size() == 1); ErrorInfo error(Tr::tr("Conflicting instances of rule '%1':").arg(m_rule->toString()), m_rule->prepareScript.location()); error.append(Tr::tr("Output artifact '%1' is to be produced from input " "artifacts '%2' and '%3', but the rule is not a multiplex rule.") .arg(outputArtifact->filePath(), (*transformer->inputs.cbegin())->filePath(), (*inputArtifacts.cbegin())->filePath())); throw error; } m_transformer->rescueChangeTrackingData(outputArtifact->transformer); m_oldTransformer = outputArtifact->transformer; outputInfo.oldFileTags = outputArtifact->fileTags(); outputInfo.oldProperties = outputArtifact->properties->value(); } else { std::unique_ptr newArtifact(new Artifact); newArtifact->artifactType = Artifact::Generated; newArtifact->setFilePath(outputPath); insertArtifact(m_product, newArtifact.get()); m_createdArtifacts += newArtifact.get(); outputArtifact = newArtifact.release(); qCDebug(lcExec).noquote() << "rule created" << outputArtifact->toString(); connect(outputArtifact, m_ruleNode); } outputArtifact->alwaysUpdated = alwaysUpdated; outputArtifact->pureFileTags = fileTags; provideFullFileTagsAndProperties(outputArtifact); if (outputInfo.newlyCreated || outputInfo.oldFileTags != outputArtifact->fileTags()) { for (RuleNode * const parentRule : filterByType(m_ruleNode->parents)) connect(parentRule, outputArtifact); } for (Artifact * const inputArtifact : inputArtifacts) { QBS_CHECK(outputArtifact != inputArtifact); connect(outputArtifact, inputArtifact); } outputArtifact->transformer = m_transformer; m_transformer->outputs.insert(outputArtifact); QBS_CHECK(m_rule->multiplex || m_transformer->inputs.size() == 1); return outputInfo; } class RuleOutputArtifactsException : public ErrorInfo { public: using ErrorInfo::ErrorInfo; }; QList RulesApplicator::runOutputArtifactsScript(const ArtifactSet &inputArtifacts, const QScriptValueList &args) { QList lst; QScriptValue fun = engine()->evaluate(m_rule->outputArtifactsScript.sourceCode(), m_rule->outputArtifactsScript.location().filePath(), m_rule->outputArtifactsScript.location().line()); if (!fun.isFunction()) throw ErrorInfo(QStringLiteral("Function expected."), m_rule->outputArtifactsScript.location()); QScriptValue res = fun.call(QScriptValue(), args); engine()->releaseResourcesOfScriptObjects(); if (engine()->hasErrorOrException(res)) throw engine()->lastError(res, m_rule->outputArtifactsScript.location()); if (!res.isArray()) throw ErrorInfo(Tr::tr("Rule.outputArtifacts must return an array of objects."), m_rule->outputArtifactsScript.location()); const quint32 c = res.property(StringConstants::lengthProperty()).toUInt32(); for (quint32 i = 0; i < c; ++i) { try { lst.push_back(createOutputArtifactFromScriptValue(res.property(i), inputArtifacts)); } catch (const RuleOutputArtifactsException &roae) { ErrorInfo ei = roae; ei.prepend(Tr::tr("Error in Rule.outputArtifacts[%1]").arg(i), m_rule->outputArtifactsScript.location()); throw ei; } } return lst; } class ArtifactBindingsExtractor { struct Entry { Entry(const QString &module, const QString &name, const QVariant &value) : module(module), name(name), value(value) {} QString module; QString name; QVariant value; }; std::vector m_propertyValues; static Set getArtifactItemPropertyNames() { Set s; for (const PropertyDeclaration &pd : BuiltinDeclarations::instance().declarationsForType( ItemType::Artifact).properties()) { s.insert(pd.name()); } s.insert(StringConstants::explicitlyDependsOnProperty()); return s; } void extractPropertyValues(const QScriptValue &obj, const QString &moduleName = QString()) { QScriptValueIterator svit(obj); while (svit.hasNext()) { svit.next(); const QString name = svit.name(); if (moduleName.isEmpty()) { // Ignore property names that are part of the Artifact item. static const Set artifactItemPropertyNames = getArtifactItemPropertyNames(); if (artifactItemPropertyNames.contains(name)) continue; } const QScriptValue value = svit.value(); if (value.isObject() && !value.isArray() && !value.isError() && !value.isRegExp()) { QString newModuleName; if (!moduleName.isEmpty()) newModuleName.append(moduleName + QLatin1Char('.')); newModuleName.append(name); extractPropertyValues(value, newModuleName); } else { m_propertyValues.emplace_back(moduleName, name, value.toVariant()); } } } public: void apply(Artifact *outputArtifact, const QScriptValue &obj) { extractPropertyValues(obj); if (m_propertyValues.empty()) return; outputArtifact->properties = outputArtifact->properties->clone(); QVariantMap artifactCfg = outputArtifact->properties->value(); for (const auto &e : m_propertyValues) { const QStringList key{e.module, e.name}; setConfigProperty(artifactCfg, key, e.value); outputArtifact->pureProperties.push_back(std::make_pair(key, e.value)); } outputArtifact->properties->setValue(artifactCfg); } }; Artifact *RulesApplicator::createOutputArtifactFromScriptValue(const QScriptValue &obj, const ArtifactSet &inputArtifacts) { if (!obj.isObject()) { throw ErrorInfo(Tr::tr("Elements of the Rule.outputArtifacts array must be " "of Object type."), m_rule->outputArtifactsScript.location()); } const QString unresolvedFilePath = obj.property(StringConstants::filePathProperty()).toVariant().toString(); if (unresolvedFilePath.isEmpty()) { throw RuleOutputArtifactsException( Tr::tr("Property filePath must be a non-empty string.")); } const QString filePath = FileInfo::resolvePath(m_product->buildDirectory(), unresolvedFilePath); const FileTags fileTags = FileTags::fromStringList( obj.property(StringConstants::fileTagsProperty()).toVariant().toStringList()); const QVariant alwaysUpdatedVar = obj.property(StringConstants::alwaysUpdatedProperty()).toVariant(); const bool alwaysUpdated = alwaysUpdatedVar.isValid() ? alwaysUpdatedVar.toBool() : true; OutputArtifactInfo outputInfo = createOutputArtifact(filePath, fileTags, alwaysUpdated, inputArtifacts); if (outputInfo.artifact->fileTags().empty()) { // Check the file tags after file taggers were run. throw RuleOutputArtifactsException( Tr::tr("Property fileTags for artifact '%1' must be a non-empty string list. " "Alternatively, a FileTagger can be provided.") .arg(unresolvedFilePath)); } const FileTags explicitlyDependsOn = FileTags::fromStringList( obj.property(StringConstants::explicitlyDependsOnProperty()) .toVariant().toStringList()); for (const FileTag &tag : explicitlyDependsOn) { for (Artifact * const dependency : m_product->lookupArtifactsByFileTag(tag)) connect(outputInfo.artifact, dependency); } ArtifactBindingsExtractor().apply(outputInfo.artifact, obj); if (!outputInfo.newlyCreated && (outputInfo.artifact->fileTags() != outputInfo.oldFileTags || outputInfo.artifact->properties->value() != outputInfo.oldProperties)) { invalidateArtifactAsRuleInputIfNecessary(outputInfo.artifact); } return outputInfo.artifact; } QString RulesApplicator::resolveOutPath(const QString &path) const { QString buildDir = m_product->topLevelProject()->buildDirectory; QString result = FileInfo::resolvePath(buildDir, path); result = QDir::cleanPath(result); return result; } const RulesEvaluationContextPtr &RulesApplicator::evalContext() const { return m_product->topLevelProject()->buildData->evaluationContext; } ScriptEngine *RulesApplicator::engine() const { return evalContext()->engine(); } QScriptValue RulesApplicator::scope() const { return evalContext()->scope(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/rulesapplicator.h000066400000000000000000000132141347155106100236320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_RULESAPPLICATOR_H #define QBS_RULESAPPLICATOR_H #include "artifact.h" #include "forward_decls.h" #include "nodeset.h" #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class BuildGraphNode; class QtMocScanner; class ScriptEngine; class RulesApplicator { public: RulesApplicator(const ResolvedProductPtr &product, const std::unordered_map &productsByName, const std::unordered_map &projectsByName, const Logger &logger); ~RulesApplicator(); const NodeSet &createdArtifacts() const { return m_createdArtifacts; } const NodeSet &invalidatedArtifacts() const { return m_invalidatedArtifacts; } QStringList removedArtifacts() const { return m_removedArtifacts; } bool ruleUsesIo() const { return m_ruleUsesIo; } void applyRule(RuleNode *ruleNode, const ArtifactSet &inputArtifacts, const ArtifactSet &explicitlyDependsOn); static void handleRemovedRuleOutputs(const ArtifactSet &inputArtifacts, const ArtifactSet &artifactsToRemove, QStringList &removedArtifacts, const Logger &logger); static ArtifactSet collectAuxiliaryInputs(const Rule *rule, const ResolvedProduct *product); static ArtifactSet collectExplicitlyDependsOn(const Rule *rule, const ResolvedProduct *product); enum InputsSourceFlag { CurrentProduct = 1, Dependencies = 2 }; Q_DECLARE_FLAGS(InputsSources, InputsSourceFlag) private: void doApply(const ArtifactSet &inputArtifacts, QScriptValue &prepareScriptContext); ArtifactSet collectOldOutputArtifacts(const ArtifactSet &inputArtifacts) const; struct OutputArtifactInfo { Artifact *artifact = nullptr; bool newlyCreated = false; FileTags oldFileTags; QVariantMap oldProperties; }; OutputArtifactInfo createOutputArtifactFromRuleArtifact( const RuleArtifactConstPtr &ruleArtifact, const ArtifactSet &inputArtifacts, Set *outputFilePaths); OutputArtifactInfo createOutputArtifact(const QString &filePath, const FileTags &fileTags, bool alwaysUpdated, const ArtifactSet &inputArtifacts); QList runOutputArtifactsScript(const ArtifactSet &inputArtifacts, const QScriptValueList &args); Artifact *createOutputArtifactFromScriptValue(const QScriptValue &obj, const ArtifactSet &inputArtifacts); QString resolveOutPath(const QString &path) const; const RulesEvaluationContextPtr &evalContext() const; ScriptEngine *engine() const; QScriptValue scope() const; static ArtifactSet collectAdditionalInputs(const FileTags &tags, const Rule *rule, const ResolvedProduct *product, InputsSources inputsSources); const ResolvedProductPtr m_product; const std::unordered_map &m_productsByName; const std::unordered_map &m_projectsByName; ArtifactSet m_explicitlyDependsOn; NodeSet m_createdArtifacts; NodeSet m_invalidatedArtifacts; QStringList m_removedArtifacts; RuleNode *m_ruleNode = nullptr; RuleConstPtr m_rule; ArtifactSet m_completeInputSet; TransformerPtr m_transformer; TransformerConstPtr m_oldTransformer; QtMocScanner *m_mocScanner; Logger m_logger; bool m_ruleUsesIo = false; }; Q_DECLARE_OPERATORS_FOR_FLAGS(RulesApplicator::InputsSources) } // namespace Internal } // namespace qbs #endif // QBS_RULESAPPLICATOR_H qbs-src-1.13.1/src/lib/corelib/buildgraph/rulesevaluationcontext.cpp000066400000000000000000000077251347155106100256150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "rulesevaluationcontext.h" #include "artifact.h" #include "rulecommands.h" #include "transformer.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { RulesEvaluationContext::RulesEvaluationContext(const Logger &logger) : m_logger(logger), m_engine(ScriptEngine::create(m_logger, EvalContext::RuleExecution)), m_observer(nullptr), m_initScopeCalls(0) { m_prepareScriptScope = m_engine->newObject(); m_prepareScriptScope.setPrototype(m_engine->globalObject()); ProcessCommand::setupForJavaScript(m_prepareScriptScope); JavaScriptCommand::setupForJavaScript(m_prepareScriptScope); } RulesEvaluationContext::~RulesEvaluationContext() { delete m_engine; } void RulesEvaluationContext::initializeObserver(const QString &description, int maximumProgress) { if (m_observer) m_observer->initialize(description, maximumProgress); } void RulesEvaluationContext::incrementProgressValue() { if (m_observer) m_observer->incrementProgressValue(); } void RulesEvaluationContext::checkForCancelation() { if (Q_UNLIKELY(m_observer && m_observer->canceled())) throw ErrorInfo(Tr::tr("Build canceled.")); } void RulesEvaluationContext::initScope() { if (m_initScopeCalls++ > 0) return; m_engine->setActive(true); m_scope = m_engine->newObject(); m_scope.setPrototype(m_prepareScriptScope); m_engine->setGlobalObject(m_scope); } void RulesEvaluationContext::cleanupScope() { QBS_CHECK(m_initScopeCalls > 0); if (--m_initScopeCalls > 0) return; m_scope = QScriptValue(); m_engine->setGlobalObject(m_prepareScriptScope.prototype()); m_engine->setActive(false); } RulesEvaluationContext::Scope::Scope(RulesEvaluationContext *evalContext) : m_evalContext(evalContext) { evalContext->initScope(); } RulesEvaluationContext::Scope::~Scope() { m_evalContext->cleanupScope(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/rulesevaluationcontext.h000066400000000000000000000063301347155106100252510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_RULESEVALUATIONCONTEXT_H #define QBS_RULESEVALUATIONCONTEXT_H #include #include #include #include #include #include namespace qbs { namespace Internal { class ProgressObserver; class ScriptEngine; class RulesEvaluationContext { public: RulesEvaluationContext(const Logger &logger); ~RulesEvaluationContext(); class Scope { public: Scope(RulesEvaluationContext *evalContext); ~Scope(); private: RulesEvaluationContext * const m_evalContext; }; ScriptEngine *engine() const { return m_engine; } QScriptValue scope() const { return m_scope; } void setObserver(ProgressObserver *observer) { m_observer = observer; } ProgressObserver *observer() const { return m_observer; } void initializeObserver(const QString &description, int maximumProgress); void incrementProgressValue(); void checkForCancelation(); private: friend class Scope; void initScope(); void cleanupScope(); Logger m_logger; ScriptEngine * const m_engine; ProgressObserver *m_observer; unsigned int m_initScopeCalls; QScriptValue m_scope; QScriptValue m_prepareScriptScope; }; } // namespace Internal } // namespace qbs #endif // QBS_RULESEVALUATIONCONTEXT_H qbs-src-1.13.1/src/lib/corelib/buildgraph/scriptclasspropertyiterator.h000066400000000000000000000074421347155106100263400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SCRIPTCLASSPROPERTYITERATOR_H #define QBS_SCRIPTCLASSPROPERTYITERATOR_H #include #include #include #include #include #include #include namespace qbs { namespace Internal { class ScriptClassPropertyIterator : public QScriptClassPropertyIterator { public: ScriptClassPropertyIterator(const QScriptValue &object, const QVariantMap &properties, const std::vector &additionalProperties) : QScriptClassPropertyIterator(object), m_it(properties), m_additionalProperties(additionalProperties) { } private: bool hasNext() const override { return m_it.hasNext() || m_index < int(m_additionalProperties.size()) - 1; } bool hasPrevious() const override { return m_index > -1 || m_it.hasPrevious(); } void toFront() override { m_it.toFront(); m_index = -1; } void toBack() override { m_it.toBack(); m_index = int(m_additionalProperties.size()) - 1; } void next() override { QBS_ASSERT(hasNext(), return); if (m_it.hasNext()) m_it.next(); else ++m_index; } void previous() override { QBS_ASSERT(hasPrevious(), return); if (m_index >= 0) --m_index; if (m_index == -1) m_it.previous(); } QScriptString name() const override { const QString theName = m_index >= 0 && m_index < int(m_additionalProperties.size()) ? m_additionalProperties.at(m_index) : m_it.key(); return object().engine()->toStringHandle(theName); } QMapIterator m_it; const std::vector m_additionalProperties; int m_index = -1; }; } // namespace Internal } // namespace qbs #endif // QBS_SCRIPTCLASSPROPERTYITERATOR_H qbs-src-1.13.1/src/lib/corelib/buildgraph/timestampsupdater.cpp000066400000000000000000000067051347155106100245360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "timestampsupdater.h" #include "artifact.h" #include "artifactvisitor.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include #include #include #include #include namespace qbs { namespace Internal { class TimestampsUpdateVisitor : public ArtifactVisitor { public: TimestampsUpdateVisitor() : ArtifactVisitor(Artifact::Generated), m_now(FileTime::currentTime()) {} void visitProduct(const ResolvedProductConstPtr &product) { QBS_CHECK(product->buildData); ArtifactVisitor::visitProduct(product); // For target artifacts, we have to update the on-disk timestamp, because // the executor will look at it. for (Artifact * const targetArtifact : product->targetArtifacts()) { if (FileInfo(targetArtifact->filePath()).exists()) QFile(targetArtifact->filePath()).open(QIODevice::WriteOnly | QIODevice::Append); } } private: void doVisit(Artifact *artifact) override { if (FileInfo(artifact->filePath()).exists()) artifact->setTimestamp(m_now); } FileTime m_now; }; void TimestampsUpdater::updateTimestamps(const TopLevelProjectPtr &project, const QList &products, const Logger &logger) { TimestampsUpdateVisitor v; for (const ResolvedProductPtr &product : products) v.visitProduct(product); if (!products.empty()) project->buildData->setDirty(); project->store(logger); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/timestampsupdater.h000066400000000000000000000044261347155106100242010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TIMESTAMPSUPDATER_H #define TIMESTAMPSUPDATER_H #include #include namespace qbs { namespace Internal { class Logger; class TimestampsUpdater { public: void updateTimestamps(const TopLevelProjectPtr &project, const QList &products, const Logger &logger); }; } // namespace Internal } // namespace qbs #endif // TIMESTAMPSUPDATER_H qbs-src-1.13.1/src/lib/corelib/buildgraph/transformer.cpp000066400000000000000000000344351347155106100233260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "transformer.h" #include "artifact.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { Transformer::Transformer() : alwaysRun(false) { } Transformer::~Transformer() { } static QScriptValue js_baseName(QScriptContext *ctx, QScriptEngine *engine, const Artifact *artifact) { Q_UNUSED(ctx); Q_UNUSED(engine); return {FileInfo::baseName(artifact->filePath())}; } static QScriptValue js_completeBaseName(QScriptContext *ctx, QScriptEngine *engine, const Artifact *artifact) { Q_UNUSED(ctx); Q_UNUSED(engine); return {FileInfo::completeBaseName(artifact->filePath())}; } static QScriptValue js_baseDir(QScriptContext *ctx, QScriptEngine *engine, const Artifact *artifact) { Q_UNUSED(ctx); Q_UNUSED(engine); QString basedir; if (artifact->artifactType == Artifact::SourceFile) { QDir sourceDir(artifact->product->sourceDirectory); basedir = FileInfo::path(sourceDir.relativeFilePath(artifact->filePath())); } else { QDir buildDir(artifact->product->buildDirectory()); basedir = FileInfo::path(buildDir.relativeFilePath(artifact->filePath())); } return basedir; } static QScriptValue js_children(QScriptContext *ctx, QScriptEngine *engine, const Artifact *artifact) { Q_UNUSED(ctx); QScriptValue sv = engine->newArray(); uint idx = 0; for (const Artifact *child : artifact->childArtifacts()) { sv.setProperty(idx++, Transformer::translateFileConfig(static_cast(engine), child, QString())); } return sv; } static void setArtifactProperty(QScriptValue &obj, const QString &name, QScriptValue (*func)(QScriptContext *, QScriptEngine *, const Artifact *), const Artifact *artifact) { obj.setProperty(name, static_cast(obj.engine())->newFunction(func, artifact), QScriptValue::PropertyGetter); } QScriptValue Transformer::translateFileConfig(ScriptEngine *scriptEngine, const Artifact *artifact, const QString &defaultModuleName) { QScriptValue obj = scriptEngine->newObject(); attachPointerTo(obj, artifact); ModuleProperties::init(obj, artifact); obj.setProperty(StringConstants::fileNameProperty(), artifact->fileName()); obj.setProperty(StringConstants::filePathProperty(), artifact->filePath()); setArtifactProperty(obj, StringConstants::baseNameProperty(), js_baseName, artifact); setArtifactProperty(obj, StringConstants::completeBaseNameProperty(), js_completeBaseName, artifact); setArtifactProperty(obj, QStringLiteral("baseDir"), js_baseDir, artifact); setArtifactProperty(obj, QStringLiteral("children"), js_children, artifact); const QStringList fileTags = sorted(artifact->fileTags().toStringList()); scriptEngine->setObservedProperty(obj, StringConstants::fileTagsProperty(), scriptEngine->toScriptValue(fileTags)); scriptEngine->observer()->addArtifactId(obj.objectId()); if (!defaultModuleName.isEmpty()) obj.setProperty(StringConstants::moduleNameProperty(), defaultModuleName); return obj; } static bool compareByFilePath(const Artifact *a1, const Artifact *a2) { return a1->filePath() < a2->filePath(); } QScriptValue Transformer::translateInOutputs(ScriptEngine *scriptEngine, const ArtifactSet &artifacts, const QString &defaultModuleName) { using TagArtifactsMap = QMap>; TagArtifactsMap tagArtifactsMap; for (Artifact *artifact : artifacts) for (const FileTag &fileTag : artifact->fileTags()) tagArtifactsMap[fileTag.toString()].push_back(artifact); for (TagArtifactsMap::Iterator it = tagArtifactsMap.begin(); it != tagArtifactsMap.end(); ++it) std::sort(it.value().begin(), it.value().end(), compareByFilePath); QScriptValue jsTagFiles = scriptEngine->newObject(); for (TagArtifactsMap::const_iterator tag = tagArtifactsMap.constBegin(); tag != tagArtifactsMap.constEnd(); ++tag) { const QList &artifacts = tag.value(); QScriptValue jsFileConfig = scriptEngine->newArray(artifacts.size()); int i = 0; for (Artifact * const artifact : artifacts) { jsFileConfig.setProperty(i++, translateFileConfig(scriptEngine, artifact, defaultModuleName)); } jsTagFiles.setProperty(tag.key(), jsFileConfig); } return jsTagFiles; } ResolvedProductPtr Transformer::product() const { if (outputs.empty()) return {}; return (*outputs.cbegin())->product.lock(); } void Transformer::setupInputs(QScriptValue targetScriptValue, const ArtifactSet &inputs, const QString &defaultModuleName) { const auto scriptEngine = static_cast(targetScriptValue.engine()); QScriptValue scriptValue = translateInOutputs(scriptEngine, inputs, defaultModuleName); targetScriptValue.setProperty(StringConstants::inputsVar(), scriptValue); QScriptValue inputScriptValue; if (inputs.size() == 1) { Artifact *input = *inputs.cbegin(); const FileTags &fileTags = input->fileTags(); QBS_ASSERT(!fileTags.empty(), return); QScriptValue inputsForFileTag = scriptValue.property(fileTags.cbegin()->toString()); inputScriptValue = inputsForFileTag.property(0); } targetScriptValue.setProperty(StringConstants::inputVar(), inputScriptValue); } void Transformer::setupInputs(QScriptValue targetScriptValue) { setupInputs(targetScriptValue, inputs, rule->module->name); } void Transformer::setupOutputs(QScriptValue targetScriptValue) { const auto scriptEngine = static_cast(targetScriptValue.engine()); const QString &defaultModuleName = rule->module->name; QScriptValue scriptValue = translateInOutputs(scriptEngine, outputs, defaultModuleName); targetScriptValue.setProperty(StringConstants::outputsVar(), scriptValue); QScriptValue outputScriptValue; if (outputs.size() == 1) { Artifact *output = *outputs.cbegin(); const FileTags &fileTags = output->fileTags(); QBS_ASSERT(!fileTags.empty(), return); QScriptValue outputsForFileTag = scriptValue.property(fileTags.cbegin()->toString()); outputScriptValue = outputsForFileTag.property(0); } targetScriptValue.setProperty(StringConstants::outputVar(), outputScriptValue); } void Transformer::setupExplicitlyDependsOn(QScriptValue targetScriptValue) { const auto scriptEngine = static_cast(targetScriptValue.engine()); QScriptValue scriptValue = translateInOutputs(scriptEngine, explicitlyDependsOn, rule->module->name); targetScriptValue.setProperty(StringConstants::explicitlyDependsOnVar(), scriptValue); } AbstractCommandPtr Transformer::createCommandFromScriptValue(const QScriptValue &scriptValue, const CodeLocation &codeLocation) { AbstractCommandPtr cmdBase; if (scriptValue.isUndefined() || !scriptValue.isValid()) return cmdBase; QString className = scriptValue.property(StringConstants::classNameProperty()).toString(); if (className == StringConstants::commandType()) cmdBase = ProcessCommand::create(); else if (className == StringConstants::javaScriptCommandType()) cmdBase = JavaScriptCommand::create(); if (cmdBase) cmdBase->fillFromScriptValue(&scriptValue, codeLocation); if (className == StringConstants::commandType()) { auto procCmd = static_cast(cmdBase.get()); procCmd->clearRelevantEnvValues(); for (const QString &key : procCmd->relevantEnvVars()) procCmd->addRelevantEnvValue(key, product()->buildEnvironment.value(key)); } return cmdBase; } void Transformer::createCommands(ScriptEngine *engine, const PrivateScriptFunction &script, const QScriptValueList &args) { if (!script.scriptFunction.isValid() || script.scriptFunction.engine() != engine) { script.scriptFunction = engine->evaluate(script.sourceCode(), script.location().filePath(), script.location().line()); if (Q_UNLIKELY(!script.scriptFunction.isFunction())) throw ErrorInfo(Tr::tr("Invalid prepare script."), script.location()); } QScriptValue scriptValue = script.scriptFunction.call(QScriptValue(), args); engine->releaseResourcesOfScriptObjects(); propertiesRequestedInPrepareScript = engine->propertiesRequestedInScript(); propertiesRequestedFromArtifactInPrepareScript = engine->propertiesRequestedFromArtifact(); importedFilesUsedInPrepareScript = engine->importedFilesUsedInScript(); depsRequestedInPrepareScript = engine->requestedDependencies(); artifactsMapRequestedInPrepareScript = engine->requestedArtifacts(); lastPrepareScriptExecutionTime = FileTime::currentTime(); for (const ResolvedProduct * const p : engine->requestedExports()) { exportedModulesAccessedInPrepareScript.insert(std::make_pair(p->uniqueName(), p->exportedModule)); } engine->clearRequestedProperties(); if (Q_UNLIKELY(engine->hasErrorOrException(scriptValue))) throw engine->lastError(scriptValue, script.location()); commands.clear(); if (scriptValue.isArray()) { const int count = scriptValue.property(StringConstants::lengthProperty()).toInt32(); for (qint32 i = 0; i < count; ++i) { QScriptValue item = scriptValue.property(i); if (item.isValid() && !item.isUndefined()) { const AbstractCommandPtr cmd = createCommandFromScriptValue(item, script.location()); if (cmd) commands.addCommand(cmd); } } } else { const AbstractCommandPtr cmd = createCommandFromScriptValue(scriptValue, script.location()); if (cmd) commands.addCommand(cmd); } } void Transformer::rescueChangeTrackingData(const TransformerConstPtr &other) { if (!other) return; propertiesRequestedInPrepareScript = other->propertiesRequestedInPrepareScript; propertiesRequestedInCommands = other->propertiesRequestedInCommands; propertiesRequestedFromArtifactInPrepareScript = other->propertiesRequestedFromArtifactInPrepareScript; propertiesRequestedFromArtifactInCommands = other->propertiesRequestedFromArtifactInCommands; importedFilesUsedInPrepareScript = other->importedFilesUsedInPrepareScript; importedFilesUsedInCommands = other->importedFilesUsedInCommands; depsRequestedInPrepareScript = other->depsRequestedInPrepareScript; depsRequestedInCommands = other->depsRequestedInCommands; artifactsMapRequestedInPrepareScript = other->artifactsMapRequestedInPrepareScript; artifactsMapRequestedInCommands = other->artifactsMapRequestedInCommands; lastCommandExecutionTime = other->lastCommandExecutionTime; lastPrepareScriptExecutionTime = other->lastPrepareScriptExecutionTime; prepareScriptNeedsChangeTracking = other->prepareScriptNeedsChangeTracking; commandsNeedChangeTracking = other->commandsNeedChangeTracking; markedForRerun = other->markedForRerun; exportedModulesAccessedInPrepareScript = other->exportedModulesAccessedInPrepareScript; exportedModulesAccessedInCommands = other->exportedModulesAccessedInCommands; } Set Transformer::jobPools() const { Set pools; for (const AbstractCommandPtr &c : commands.commands()) { if (!c->jobPool().isEmpty()) pools.insert(c->jobPool()); } return pools; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/transformer.h000066400000000000000000000141611347155106100227650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TRANSFORMER_H #define QBS_TRANSFORMER_H #include "artifact.h" #include "forward_decls.h" #include "requestedartifacts.h" #include "requesteddependencies.h" #include "rulecommands.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { class Artifact; class AbstractCommand; class Rule; class Transformer { public: static TransformerPtr create() { return TransformerPtr(new Transformer); } ~Transformer(); ArtifactSet inputs; // Subset of "children of all outputs". ArtifactSet outputs; ArtifactSet explicitlyDependsOn; RuleConstPtr rule; CommandList commands; PropertySet propertiesRequestedInPrepareScript; PropertySet propertiesRequestedInCommands; QHash propertiesRequestedFromArtifactInPrepareScript; QHash propertiesRequestedFromArtifactInCommands; std::vector importedFilesUsedInPrepareScript; std::vector importedFilesUsedInCommands; RequestedDependencies depsRequestedInPrepareScript; RequestedDependencies depsRequestedInCommands; RequestedArtifacts artifactsMapRequestedInPrepareScript; RequestedArtifacts artifactsMapRequestedInCommands; FileTime lastPrepareScriptExecutionTime; FileTime lastCommandExecutionTime; std::unordered_map exportedModulesAccessedInPrepareScript; std::unordered_map exportedModulesAccessedInCommands; bool alwaysRun; bool prepareScriptNeedsChangeTracking = false; bool commandsNeedChangeTracking = false; bool markedForRerun = false; static QScriptValue translateFileConfig(ScriptEngine *scriptEngine, const Artifact *artifact, const QString &defaultModuleName); ResolvedProductPtr product() const; void setupInputs(QScriptValue targetScriptValue); void setupOutputs(QScriptValue targetScriptValue); void setupExplicitlyDependsOn(QScriptValue targetScriptValue); void createCommands(ScriptEngine *engine, const PrivateScriptFunction &script, const QScriptValueList &args); void rescueChangeTrackingData(const TransformerConstPtr &other); Set jobPools() const; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(rule, inputs, outputs, explicitlyDependsOn, propertiesRequestedInPrepareScript, propertiesRequestedInCommands, propertiesRequestedFromArtifactInPrepareScript, propertiesRequestedFromArtifactInCommands, importedFilesUsedInPrepareScript, importedFilesUsedInCommands, depsRequestedInPrepareScript, depsRequestedInCommands, commands, artifactsMapRequestedInPrepareScript, artifactsMapRequestedInCommands, lastPrepareScriptExecutionTime, lastCommandExecutionTime, exportedModulesAccessedInPrepareScript, exportedModulesAccessedInCommands, alwaysRun, prepareScriptNeedsChangeTracking, commandsNeedChangeTracking, markedForRerun); } private: Transformer(); AbstractCommandPtr createCommandFromScriptValue(const QScriptValue &scriptValue, const CodeLocation &codeLocation); static void setupInputs(QScriptValue targetScriptValue, const ArtifactSet &inputs, const QString &defaultModuleName); static QScriptValue translateInOutputs(ScriptEngine *scriptEngine, const ArtifactSet &artifacts, const QString &defaultModuleName); }; } // namespace Internal } // namespace qbs #endif // QBS_TRANSFORMER_H qbs-src-1.13.1/src/lib/corelib/buildgraph/transformerchangetracking.cpp000066400000000000000000000360741347155106100262200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "transformerchangetracking.h" #include "projectbuilddata.h" #include "requesteddependencies.h" #include "rulecommands.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class TrafoChangeTracker { public: TrafoChangeTracker(const Transformer *transformer, const ResolvedProduct *product, const std::unordered_map &productsByName, const std::unordered_map &projectsByName) : m_transformer(transformer), m_product(product), m_productsByName(productsByName), m_projectsByName(projectsByName) { } bool prepareScriptNeedsRerun() const; bool commandsNeedRerun() const; private: QVariantMap propertyMapByKind(const Property &property) const; bool checkForPropertyChange(const Property &restoredProperty, const QVariantMap &newProperties) const; bool checkForImportFileChange(const std::vector &importedFiles, const FileTime &referenceTime, const char *context) const; bool isExportedModuleUpToDate(const QString &productName, const ExportedModule &module) const; bool areExportedModulesUpToDate( const std::unordered_map exportedModules) const; const Artifact *getArtifact(const QString &filePath, const QString &productName) const; const ResolvedProduct *getProduct(const QString &name) const; const Transformer * const m_transformer; const ResolvedProduct * const m_product; const std::unordered_map &m_productsByName; const std::unordered_map &m_projectsByName; mutable const ResolvedProduct * m_lastProduct = nullptr; mutable const Artifact *m_lastArtifact = nullptr; }; template static QVariantMap getParameterValue( const QHash ¶meters, const QString &depName) { for (auto it = parameters.cbegin(); it != parameters.cend(); ++it) { if (it.key()->name == depName) return it.value(); } return {}; } QVariantMap TrafoChangeTracker::propertyMapByKind(const Property &property) const { switch (property.kind) { case Property::PropertyInModule: { const ResolvedProduct * const p = getProduct(property.productName); return p ? p->moduleProperties->value() : QVariantMap(); } case Property::PropertyInProduct: { const ResolvedProduct * const p = getProduct(property.productName); return p ? p->productProperties : QVariantMap(); } case Property::PropertyInProject: { if (property.productName == m_product->project->name) return m_product->project->projectProperties(); const auto it = m_projectsByName.find(property.productName); if (it != m_projectsByName.cend()) return it->second->projectProperties(); return {}; } case Property::PropertyInParameters: { const int sepIndex = property.moduleName.indexOf(QLatin1Char(':')); const QString depName = property.moduleName.left(sepIndex); const ResolvedProduct * const p = getProduct(property.productName); if (!p) return {}; QVariantMap v = getParameterValue(p->dependencyParameters, depName); if (!v.empty()) return v; return getParameterValue(p->moduleParameters, depName); } case Property::PropertyInArtifact: default: QBS_CHECK(false); } return {}; } bool TrafoChangeTracker::checkForPropertyChange(const Property &restoredProperty, const QVariantMap &newProperties) const { QVariant v; switch (restoredProperty.kind) { case Property::PropertyInProduct: case Property::PropertyInProject: v = newProperties.value(restoredProperty.propertyName); break; case Property::PropertyInModule: v = moduleProperty(newProperties, restoredProperty.moduleName, restoredProperty.propertyName); break; case Property::PropertyInParameters: { const int sepIndex = restoredProperty.moduleName.indexOf(QLatin1Char(':')); QualifiedId moduleName = QualifiedId::fromString(restoredProperty.moduleName.mid(sepIndex + 1)); QVariantMap map = newProperties; while (!moduleName.empty()) map = map.value(moduleName.takeFirst()).toMap(); v = map.value(restoredProperty.propertyName); break; } case Property::PropertyInArtifact: QBS_CHECK(false); } if (restoredProperty.value != v) { qCDebug(lcBuildGraph).noquote().nospace() << "Value for property '" << restoredProperty.moduleName << "." << restoredProperty.propertyName << "' has changed.\n" << "Old value was '" << restoredProperty.value << "'.\n" << "New value is '" << v << "'."; return true; } return false; } bool TrafoChangeTracker::checkForImportFileChange(const std::vector &importedFiles, const FileTime &referenceTime, const char *context) const { for (const QString &importedFile : importedFiles) { const FileInfo fi(importedFile); if (!fi.exists()) { qCDebug(lcBuildGraph) << context << "imported file" << importedFile << "is gone, need to re-run"; return true; } if (fi.lastModified() > referenceTime) { qCDebug(lcBuildGraph) << context << "imported file" << importedFile << "has been updated, need to re-run" << fi.lastModified() << referenceTime; return true; } } return false; } bool TrafoChangeTracker::isExportedModuleUpToDate(const QString &productName, const ExportedModule &module) const { const ResolvedProduct * const product = getProduct(productName); if (!product) { qCDebug(lcBuildGraph) << "product" << productName << "does not exist anymore, need to re-run"; return false; } if (product->exportedModule != module) { qCDebug(lcBuildGraph) << "exported module has changed for product" << productName << ", need to re-run"; return false; } return true; } bool TrafoChangeTracker::areExportedModulesUpToDate( const std::unordered_map exportedModules) const { for (auto it = exportedModules.begin(); it != exportedModules.end(); ++it) { if (!isExportedModuleUpToDate(it->first, it->second)) return false; } return true; } const Artifact *TrafoChangeTracker::getArtifact(const QString &filePath, const QString &productName) const { if (m_lastArtifact && m_lastArtifact->filePath() == filePath && m_lastArtifact->product.get()->uniqueName() == productName) { return m_lastArtifact; } const ResolvedProduct * const product = getProduct(productName); if (!product) return nullptr; const QList &candidates = product->topLevelProject()->buildData->lookupFiles(filePath); const Artifact *artifact = nullptr; for (const FileResourceBase * const candidate : candidates) { if (candidate->fileType() == FileResourceBase::FileTypeArtifact) { auto const a = static_cast(candidate); if (a->product.get() == product) { m_lastArtifact = artifact = a; break; } } } return artifact; } const ResolvedProduct *TrafoChangeTracker::getProduct(const QString &name) const { if (m_lastProduct && name == m_lastProduct->uniqueName()) return m_lastProduct; if (name == m_product->uniqueName()) { m_lastProduct = m_product; return m_product; } const auto it = m_productsByName.find(name); if (it != m_productsByName.cend()) { m_lastProduct = it->second; return it->second; } return nullptr; } bool TrafoChangeTracker::prepareScriptNeedsRerun() const { for (const Property &property : qAsConst(m_transformer->propertiesRequestedInPrepareScript)) { if (checkForPropertyChange(property, propertyMapByKind(property))) return true; } if (checkForImportFileChange(m_transformer->importedFilesUsedInPrepareScript, m_transformer->lastPrepareScriptExecutionTime, "prepare script")) { return true; } for (auto it = m_transformer->propertiesRequestedFromArtifactInPrepareScript.constBegin(); it != m_transformer->propertiesRequestedFromArtifactInPrepareScript.constEnd(); ++it) { for (const Property &property : qAsConst(it.value())) { const Artifact * const artifact = getArtifact(it.key(), property.productName); if (!artifact) return true; if (property.kind == Property::PropertyInArtifact) { if (sorted(artifact->fileTags().toStringList()) != property.value.toStringList()) return true; continue; } if (checkForPropertyChange(property, artifact->properties->value())) return true; } } if (!m_transformer->depsRequestedInPrepareScript.isUpToDate(m_product->topLevelProject())) return true; if (!m_transformer->artifactsMapRequestedInPrepareScript.isUpToDate( m_product->topLevelProject())) { return true; } if (!areExportedModulesUpToDate(m_transformer->exportedModulesAccessedInPrepareScript)) return true; return false; } bool TrafoChangeTracker::commandsNeedRerun() const { for (const Property &property : qAsConst(m_transformer->propertiesRequestedInCommands)) { if (checkForPropertyChange(property, propertyMapByKind(property))) return true; } QMap artifactMap; for (auto it = m_transformer->propertiesRequestedFromArtifactInCommands.cbegin(); it != m_transformer->propertiesRequestedFromArtifactInCommands.cend(); ++it) { for (const Property &property : qAsConst(it.value())) { const Artifact * const artifact = getArtifact(it.key(), property.productName); if (!artifact) return true; if (property.kind == Property::PropertyInArtifact) { if (sorted(artifact->fileTags().toStringList()) != property.value.toStringList()) return true; continue; } if (checkForPropertyChange(property, artifact->properties->value())) return true; } } if (checkForImportFileChange(m_transformer->importedFilesUsedInCommands, m_transformer->lastCommandExecutionTime, "command")) { return true; } if (!m_transformer->depsRequestedInCommands.isUpToDate(m_product->topLevelProject())) return true; if (!m_transformer->artifactsMapRequestedInCommands.isUpToDate(m_product->topLevelProject())) return true; if (!areExportedModulesUpToDate(m_transformer->exportedModulesAccessedInCommands)) return true; // TODO: Also track env access in JS commands and prepare scripts for (const AbstractCommandPtr &c : qAsConst(m_transformer->commands.commands())) { if (c->type() != AbstractCommand::ProcessCommandType) continue; const ProcessCommandPtr &processCmd = std::static_pointer_cast(c); for (const QString &var : processCmd->relevantEnvVars()) { const QString &oldValue = processCmd->relevantEnvValue(var); const QString &newValue = m_product->buildEnvironment.value(var); if (oldValue != newValue) { qCDebug(lcBuildGraph) << "need to re-run command: value of environment variable" << var << "changed from" << oldValue << "to" << newValue << "for command" << processCmd->program() << "in rule" << m_transformer->rule->toString(); return true; } } } return false; } bool prepareScriptNeedsRerun( Transformer *transformer, const ResolvedProduct *product, const std::unordered_map &productsByName, const std::unordered_map &projectsByName) { if (!transformer->prepareScriptNeedsChangeTracking) return false; transformer->prepareScriptNeedsChangeTracking = false; return TrafoChangeTracker(transformer, product, productsByName, projectsByName) .prepareScriptNeedsRerun(); } bool commandsNeedRerun(Transformer *transformer, const ResolvedProduct *product, const std::unordered_map &productsByName, const std::unordered_map &projectsByName) { if (!transformer->commandsNeedChangeTracking) return false; transformer->commandsNeedChangeTracking = false; return TrafoChangeTracker(transformer, product, productsByName, projectsByName) .commandsNeedRerun(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/buildgraph/transformerchangetracking.h000066400000000000000000000040611347155106100256540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TRANSFORMERCHANGETRACKING_H #define QBS_TRANSFORMERCHANGETRACKING_H #include "forward_decls.h" #include #include namespace qbs { namespace Internal { bool prepareScriptNeedsRerun( Transformer *transformer, const ResolvedProduct *product, const std::unordered_map &productsByName, const std::unordered_map &projectsByName); bool commandsNeedRerun(Transformer *transformer, const ResolvedProduct *product, const std::unordered_map &productsByName, const std::unordered_map &projectsByName); } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/corelib.pro000066400000000000000000000024341347155106100202720ustar00rootroot00000000000000TARGET = qbscore include(../library.pri) include(../bundledlibs.pri) qbs_use_bundled_qtscript { include(../scriptengine/use_scriptengine.pri) } else { QT += script } isEmpty(QBS_RELATIVE_LIBEXEC_PATH) { win32:QBS_RELATIVE_LIBEXEC_PATH=../bin else:QBS_RELATIVE_LIBEXEC_PATH=../libexec/qbs } DEFINES += QBS_RELATIVE_LIBEXEC_PATH=\\\"$${QBS_RELATIVE_LIBEXEC_PATH}\\\" QT += core-private network qbs_enable_project_file_updates: QT += gui INCLUDEPATH += $$PWD include(api/api.pri) include(buildgraph/buildgraph.pri) include(generators/generators.pri) include(jsextensions/jsextensions.pri) include(language/language.pri) include(logging/logging.pri) include(parser/parser.pri) include(tools/tools.pri) CONFIG(static, static|shared) { !isEmpty(QBS_PLUGINS_BUILD_DIR) { destdirPrefix = $${QBS_PLUGINS_BUILD_DIR} } else { destdirPrefix = $$shadowed($$PWD)/../../../$${QBS_LIBRARY_DIRNAME} } LIBS += -L$${destdirPrefix}/qbs/plugins -lqbs_cpp_scanner -lqbs_qt_scanner } win32:LIBS += -lpsapi -lshell32 HEADERS += \ qbs.h !qbs_no_dev_install { qbs_h.files = qbs.h qbs_h.path = $${QBS_INSTALL_PREFIX}/include/qbs use_pri.files = use_installed_corelib.pri ../../../qbs_version.pri use_pri.path = $${qbs_h.path} INSTALLS += qbs_h use_pri } qbs-src-1.13.1/src/lib/corelib/corelib.qbs000066400000000000000000000365361347155106100202710ustar00rootroot00000000000000import qbs 1.0 import qbs.Utilities QbsLibrary { Depends { name: "cpp" } Depends { name: "bundledqt" } Depends { name: "Qt"; submodules: ["core-private", "network", "xml"] } Depends { name: "Qt.script" condition: !qbsbuildconfig.useBundledQtScript required: false } Depends { name: "qbsscriptengine" condition: qbsbuildconfig.useBundledQtScript || !Qt.script.present } Depends { condition: qbsbuildconfig.enableProjectFileUpdates; name: "Qt.gui" } Depends { condition: staticBuild; productTypes: ["qbsplugin"] } name: "qbscore" property stringList bundledQtScriptIncludes: qbsbuildconfig.useBundledQtScript || !Qt.script.present ? qbsscriptengine.includePaths : [] cpp.includePaths: base.concat(bundledQtScriptIncludes).concat([ ".", "../.." // for the plugin headers ]) property stringList projectFileUpdateDefines: qbsbuildconfig.enableProjectFileUpdates ? ["QBS_ENABLE_PROJECT_FILE_UPDATES"] : [] property stringList enableUnitTestsDefines: qbsbuildconfig.enableUnitTests ? ["QBS_ENABLE_UNIT_TESTS"] : [] property stringList systemSettingsDirDefines: qbsbuildconfig.systemSettingsDir ? ['QBS_SYSTEM_SETTINGS_DIR="' + qbsbuildconfig.systemSettingsDir + '"'] : [] cpp.defines: base.concat([ "QBS_RELATIVE_LIBEXEC_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativeLibexecPath), "QBS_VERSION=" + Utilities.cStringQuote(version), ]).concat(projectFileUpdateDefines).concat(enableUnitTestsDefines) .concat(systemSettingsDirDefines) Properties { condition: qbs.targetOS.contains("windows") cpp.dynamicLibraries: base.concat(["Psapi", "shell32"]) } cpp.dynamicLibraries: base Properties { condition: qbs.targetOS.contains("darwin") cpp.frameworks: ["Foundation", "Security"] } Group { name: product.name files: ["qbs.h"] qbs.install: qbsbuildconfig.installApiHeaders qbs.installDir: headerInstallPrefix } Group { name: "project file updating" condition: qbsbuildconfig.enableProjectFileUpdates prefix: "api/" files: [ "changeset.cpp", "changeset.h", "projectfileupdater.cpp", "projectfileupdater.h", "qmljsrewriter.cpp", "qmljsrewriter.h", ] } Group { name: "api" prefix: name + '/' files: [ "internaljobs.cpp", "internaljobs.h", "jobs.cpp", "languageinfo.cpp", "project.cpp", "project_p.h", "projectdata.cpp", "projectdata_p.h", "propertymap_p.h", "rulecommand.cpp", "rulecommand_p.h", "runenvironment.cpp", "transformerdata.cpp", "transformerdata_p.h", ] } Group { name: "public api headers" qbs.install: qbsbuildconfig.installApiHeaders qbs.installDir: headerInstallPrefix + "/api" prefix: "api/" files: [ "jobs.h", "languageinfo.h", "project.h", "projectdata.h", "rulecommand.h", "runenvironment.h", "transformerdata.h", ] } Group { name: "buildgraph" prefix: name + '/' files: [ "abstractcommandexecutor.cpp", "abstractcommandexecutor.h", "artifact.cpp", "artifact.h", "artifactcleaner.cpp", "artifactcleaner.h", "artifactsscriptvalue.cpp", "artifactsscriptvalue.h", "artifactvisitor.cpp", "artifactvisitor.h", "buildgraph.cpp", "buildgraph.h", "buildgraphnode.cpp", "buildgraphnode.h", "buildgraphloader.cpp", "buildgraphloader.h", "buildgraphvisitor.h", "cycledetector.cpp", "cycledetector.h", "dependencyparametersscriptvalue.cpp", "dependencyparametersscriptvalue.h", "depscanner.cpp", "depscanner.h", "emptydirectoriesremover.cpp", "emptydirectoriesremover.h", "environmentscriptrunner.cpp", "environmentscriptrunner.h", "executor.cpp", "executor.h", "executorjob.cpp", "executorjob.h", "filedependency.cpp", "filedependency.h", "inputartifactscanner.cpp", "inputartifactscanner.h", "jscommandexecutor.cpp", "jscommandexecutor.h", "nodeset.cpp", "nodeset.h", "nodetreedumper.cpp", "nodetreedumper.h", "processcommandexecutor.cpp", "processcommandexecutor.h", "productbuilddata.cpp", "productbuilddata.h", "productinstaller.cpp", "productinstaller.h", "projectbuilddata.cpp", "projectbuilddata.h", "qtmocscanner.cpp", "qtmocscanner.h", "rawscanneddependency.cpp", "rawscanneddependency.h", "rawscanresults.cpp", "rawscanresults.h", "requestedartifacts.cpp", "requestedartifacts.h", "requesteddependencies.cpp", "requesteddependencies.h", "rescuableartifactdata.h", "rulecommands.cpp", "rulecommands.h", "rulegraph.cpp", "rulegraph.h", "rulenode.cpp", "rulenode.h", "rulesapplicator.cpp", "rulesapplicator.h", "rulesevaluationcontext.cpp", "rulesevaluationcontext.h", "scriptclasspropertyiterator.h", "timestampsupdater.cpp", "timestampsupdater.h", "transformer.cpp", "transformer.h", "transformerchangetracking.cpp", "transformerchangetracking.h", ] } Group { name: "public buildgraph headers" qbs.install: qbsbuildconfig.installApiHeaders qbs.installDir: headerInstallPrefix + "/buildgraph" files: "buildgraph/forward_decls.h" } Group { name: "generators" prefix: "generators/" files: [ "generatableprojectiterator.cpp", "generatableprojectiterator.h", "generator.cpp", "generatordata.cpp", "igeneratableprojectvisitor.h", ] } Group { name: "public generator headers" prefix: "generators/" qbs.install: qbsbuildconfig.installApiHeaders qbs.installDir: headerInstallPrefix + "/generators" files: [ "generator.h", "generatordata.h", ] } Group { name: "jsextensions" prefix: name + '/' files: [ "environmentextension.cpp", "file.cpp", "fileinfoextension.cpp", "jsextensions.cpp", "jsextensions.h", "moduleproperties.cpp", "moduleproperties.h", "process.cpp", "temporarydir.cpp", "textfile.cpp", "binaryfile.cpp", "utilitiesextension.cpp", "domxml.cpp", ] } Group { name: "jsextensions (Non-Darwin-specific)" prefix: "jsextensions/" condition: !qbs.targetOS.contains("darwin") files: [ "propertylist.cpp", ] } Group { name: "jsextensions (Darwin-specific)" prefix: "jsextensions/" condition: qbs.targetOS.contains("darwin") files: [ "propertylist.mm", "propertylistutils.h", "propertylistutils.mm", ] } Group { name: "language" prefix: name + '/' files: [ "artifactproperties.cpp", "artifactproperties.h", "astimportshandler.cpp", "astimportshandler.h", "astpropertiesitemhandler.cpp", "astpropertiesitemhandler.h", "asttools.cpp", "asttools.h", "builtindeclarations.cpp", "builtindeclarations.h", "deprecationinfo.h", "evaluationdata.h", "evaluator.cpp", "evaluator.h", "evaluatorscriptclass.cpp", "evaluatorscriptclass.h", "filecontext.cpp", "filecontext.h", "filecontextbase.cpp", "filecontextbase.h", "filetags.cpp", "filetags.h", "identifiersearch.cpp", "identifiersearch.h", "item.cpp", "item.h", "itemdeclaration.cpp", "itemdeclaration.h", "itemobserver.h", "itempool.cpp", "itempool.h", "itemreader.cpp", "itemreader.h", "itemreaderastvisitor.cpp", "itemreaderastvisitor.h", "itemreadervisitorstate.cpp", "itemreadervisitorstate.h", "itemtype.h", "jsimports.h", "language.cpp", "language.h", "loader.cpp", "loader.h", "moduleloader.cpp", "moduleloader.h", "modulemerger.cpp", "modulemerger.h", "moduleproviderinfo.h", "preparescriptobserver.cpp", "preparescriptobserver.h", "projectresolver.cpp", "projectresolver.h", "property.cpp", "property.h", "propertydeclaration.cpp", "propertydeclaration.h", "propertymapinternal.cpp", "propertymapinternal.h", "qualifiedid.cpp", "qualifiedid.h", "resolvedfilecontext.cpp", "resolvedfilecontext.h", "scriptengine.cpp", "scriptengine.h", "scriptimporter.cpp", "scriptimporter.h", "scriptpropertyobserver.cpp", "scriptpropertyobserver.h", "value.cpp", "value.h", ] } Group { name: "public language headers" qbs.install: qbsbuildconfig.installApiHeaders qbs.installDir: headerInstallPrefix + "/language" files: "language/forward_decls.h" } Group { name: "logging" prefix: name + '/' files: [ "categories.cpp", "categories.h", "ilogsink.cpp", "logger.cpp", "logger.h", "translator.h" ] } Group { name: "public logging headers" qbs.install: qbsbuildconfig.installApiHeaders qbs.installDir: headerInstallPrefix + "/logging" files: "logging/ilogsink.h" } Group { name: "parser" prefix: name + '/' files: [ "qmlerror.cpp", "qmlerror.h", "qmljsast.cpp", "qmljsast_p.h", "qmljsastfwd_p.h", "qmljsastvisitor.cpp", "qmljsastvisitor_p.h", "qmljsengine_p.cpp", "qmljsengine_p.h", "qmljsglobal_p.h", "qmljsgrammar.cpp", "qmljsgrammar_p.h", "qmljskeywords_p.h", "qmljslexer.cpp", "qmljslexer_p.h", "qmljsmemorypool_p.h", "qmljsparser.cpp", "qmljsparser_p.h" ] } Group { name: "tools" prefix: name + '/' files: [ "architectures.cpp", "buildgraphlocker.cpp", "buildgraphlocker.h", "buildoptions.cpp", "cleanoptions.cpp", "codelocation.cpp", "commandechomode.cpp", "dynamictypecheck.h", "error.cpp", "executablefinder.cpp", "executablefinder.h", "fileinfo.cpp", "fileinfo.h", "filesaver.cpp", "filesaver.h", "filetime.cpp", "filetime.h", "generateoptions.cpp", "hostosinfo.h", "id.cpp", "id.h", "iosutils.h", "joblimits.cpp", "jsliterals.cpp", "jsliterals.h", "installoptions.cpp", "launcherinterface.cpp", "launcherinterface.h", "launcherpackets.cpp", "launcherpackets.h", "launchersocket.cpp", "launchersocket.h", "msvcinfo.cpp", "msvcinfo.h", "pathutils.h", "persistence.cpp", "persistence.h", "preferences.cpp", "processresult.cpp", "processresult_p.h", "processutils.cpp", "processutils.h", "profile.cpp", "profiling.cpp", "profiling.h", "progressobserver.cpp", "progressobserver.h", "projectgeneratormanager.cpp", "qbsassert.cpp", "qbsassert.h", "qbspluginmanager.cpp", "qbspluginmanager.h", "qbsprocess.cpp", "qbsprocess.h", "qttools.cpp", "qttools.h", "scannerpluginmanager.cpp", "scannerpluginmanager.h", "scripttools.cpp", "scripttools.h", "set.h", "settings.cpp", "settingscreator.cpp", "settingscreator.h", "settingsmodel.cpp", "settingsrepresentation.cpp", "setupprojectparameters.cpp", "shellutils.cpp", "shellutils.h", "stlutils.h", "stringconstants.h", "stringutils.h", "toolchains.cpp", "version.cpp", "visualstudioversioninfo.cpp", "visualstudioversioninfo.h", "vsenvironmentdetector.cpp", "vsenvironmentdetector.h", "weakpointer.h", ] } Group { name: "public tools headers" prefix: "tools/" files: [ "architectures.h", "buildoptions.h", "cleanoptions.h", "codelocation.h", "commandechomode.h", "error.h", "generateoptions.h", "installoptions.h", "joblimits.h", "preferences.h", "processresult.h", "profile.h", "projectgeneratormanager.h", "qbs_export.h", "settings.h", "settingsmodel.h", "settingsrepresentation.h", "setupprojectparameters.h", "toolchains.h", "version.h", ] qbs.install: qbsbuildconfig.installApiHeaders qbs.installDir: headerInstallPrefix + "/tools" } Group { condition: qbs.targetOS.contains("macos") name: "tools (macOS)" prefix: "tools/" files: [ "applecodesignutils.cpp", "applecodesignutils.h" ] } Group { name: "use_installed.pri" files: [ "use_installed_corelib.pri", "../../../qbs_version.pri" ] qbs.install: qbsbuildconfig.installApiHeaders qbs.installDir: headerInstallPrefix } Export { Depends { name: "cpp" } cpp.defines: base.concat(product.projectFileUpdateDefines) } } qbs-src-1.13.1/src/lib/corelib/generators/000077500000000000000000000000001347155106100202775ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/corelib/generators/generatableprojectiterator.cpp000066400000000000000000000070441347155106100264220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "generatableprojectiterator.h" namespace qbs { GeneratableProjectIterator::GeneratableProjectIterator(const GeneratableProject &project) : project(project) { } void GeneratableProjectIterator::accept(IGeneratableProjectVisitor *visitor) { visitor->visitProject(project); QMapIterator it(project.projects); while (it.hasNext()) { it.next(); visitor->visitProject(it.value(), it.key()); } accept(project, GeneratableProjectData(), project, visitor); } void GeneratableProjectIterator::accept(const GeneratableProject &project, const GeneratableProjectData &parentProjectData, const GeneratableProjectData &projectData, IGeneratableProjectVisitor *visitor) { visitor->visitProjectData(project, parentProjectData, projectData); visitor->visitProjectData(project, projectData); QMapIterator it(projectData.data); while (it.hasNext()) { it.next(); visitor->visitProjectData(parentProjectData.data.value(it.key()), it.value(), it.key()); visitor->visitProjectData(it.value(), it.key()); } for (const auto &subProject : projectData.subProjects) { accept(project, projectData, subProject, visitor); } for (const auto &productDataMap : projectData.products) { visitor->visitProduct(project, projectData, productDataMap); QMapIterator it(productDataMap.data); while (it.hasNext()) { it.next(); visitor->visitProduct(it.value(), it.key()); } } } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/generators/generatableprojectiterator.h000066400000000000000000000047571347155106100260770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GENERATABLEPROJECTITERATOR_H #define GENERATABLEPROJECTITERATOR_H #include "generatordata.h" #include "igeneratableprojectvisitor.h" namespace qbs { class QBS_EXPORT GeneratableProjectIterator { GeneratableProject project; public: GeneratableProjectIterator(const GeneratableProject &project); void accept(IGeneratableProjectVisitor *visitor); private: void accept(const GeneratableProject &project, const GeneratableProjectData &parentProjectData, const GeneratableProjectData &projectData, IGeneratableProjectVisitor *visitor); }; } // namespace qbs #endif // GENERATABLEPROJECTITERATOR_H qbs-src-1.13.1/src/lib/corelib/generators/generator.cpp000066400000000000000000000204321347155106100227720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "generator.h" #include #include #include #include #include #include #include namespace qbs { class ProjectGeneratorPrivate { public: QList projects; QList buildConfigurations; InstallOptions installOptions; QString qbsSettingsDir; Internal::Logger logger = Internal::Logger(nullptr); }; ProjectGenerator::ProjectGenerator() : d(new ProjectGeneratorPrivate) { } ProjectGenerator::~ProjectGenerator() { delete d; } static QString _configurationName(const Project &project) { return project.projectConfiguration() .value(Internal::StringConstants::qbsModule()).toMap() .value(Internal::StringConstants::configurationNameProperty()).toString(); } static QString _configurationName(const QVariantMap &buildConfiguration) { return buildConfiguration.value(QStringLiteral("qbs.configurationName")).toString(); } ErrorInfo ProjectGenerator::generate(const QList &projects, const QList &buildConfigurations, const InstallOptions &installOptions, const QString &qbsSettingsDir, const Internal::Logger &logger) { d->projects = projects; std::sort(d->projects.begin(), d->projects.end(), [](const Project &a, const Project &b) { return _configurationName(a) < _configurationName(b); }); d->buildConfigurations = buildConfigurations; std::sort(d->buildConfigurations.begin(), d->buildConfigurations.end(), [](const QVariantMap &a, const QVariantMap &b) { return _configurationName(a) < _configurationName(b); }); d->installOptions = installOptions; d->qbsSettingsDir = qbsSettingsDir; d->logger = logger; try { generate(); } catch (const ErrorInfo &e) { return e; } return {}; } QList ProjectGenerator::projects() const { return d->projects; } QList ProjectGenerator::buildConfigurations() const { return d->buildConfigurations; } QVariantMap ProjectGenerator::buildConfiguration(const Project &project) const { int idx = d->projects.indexOf(project); if (idx < 0) return {}; return d->buildConfigurations.at(idx); } QStringList ProjectGenerator::buildConfigurationCommandLine(const Project &project) const { QVariantMap config = buildConfiguration(project); const QString name = config.take(QStringLiteral("qbs.configurationName")).toString(); if (name.isEmpty()) throw ErrorInfo(QStringLiteral("Can't find configuration name for project")); QStringList commandLineParameters; commandLineParameters += QStringLiteral("config:") + name; QMapIterator it(config); while (it.hasNext()) { it.next(); commandLineParameters += it.key() + QStringLiteral(":") + it.value().toString(); } return commandLineParameters; } // Count the number of products in the project (singular) // Precondition: each project data (i.e. per-configuration project data) // has the same number of products. static int _productCount(const QList &projects) { int count = -1; for (const auto &project : projects) { int oldCount = count; count = project.products().size(); QBS_CHECK(oldCount == -1 || oldCount == count); } return count; } static int _subprojectCount(const QList &projects) { int count = -1; for (const auto &project : projects) { int oldCount = count; count = project.subProjects().size(); QBS_CHECK(oldCount == -1 || oldCount == count); } return count; } static GeneratableProjectData _reduceProjectConfigurations( const QMap &map) { GeneratableProjectData gproject; // Add the project's project data for each configuration QMapIterator it(map); while (it.hasNext()) { it.next(); gproject.data.insert(it.key(), it.value()); } // Add the project's products... for (int i = 0; i < _productCount(map.values()); ++i) { GeneratableProductData prod; // once for each configuration QMapIterator it(map); while (it.hasNext()) { it.next(); prod.data.insert(it.key(), it.value().products().at(i)); } gproject.products.push_back(prod); } // Add the project's subprojects... for (int i = 0; i < _subprojectCount(map.values()); ++i) { QMap subprojectMap; // once for each configuration QMapIterator it(map); while (it.hasNext()) { it.next(); subprojectMap.insert(it.key(), it.value().subProjects().at(i)); } gproject.subProjects.push_back(_reduceProjectConfigurations(subprojectMap)); } return gproject; } const GeneratableProject ProjectGenerator::project() const { QMap rootProjects; GeneratableProject proj; for (const auto &project : projects()) { const QString configurationName = _configurationName(project); rootProjects.insert(configurationName, project.projectData()); proj.projects.insert(configurationName, project); proj.buildConfigurations.insert(configurationName, buildConfiguration(project)); proj.commandLines.insert(configurationName, buildConfigurationCommandLine(project)); } auto p = _reduceProjectConfigurations(rootProjects); proj.data = p.data; proj.products = p.products; proj.subProjects = p.subProjects; proj.installOptions = d->installOptions; return proj; } QFileInfo ProjectGenerator::qbsExecutableFilePath() const { const QString qbsInstallDir = QString::fromLocal8Bit(qgetenv("QBS_INSTALL_DIR")); auto file = QFileInfo(Internal::HostOsInfo::appendExecutableSuffix(!qbsInstallDir.isEmpty() ? qbsInstallDir + QLatin1String("/bin/qbs") : QCoreApplication::applicationDirPath() + QLatin1String("/qbs"))); QBS_CHECK(file.isAbsolute() && file.exists()); return file; } QString ProjectGenerator::qbsSettingsDir() const { return d->qbsSettingsDir; } const Internal::Logger &ProjectGenerator::logger() const { return d->logger; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/generators/generator.h000066400000000000000000000065701347155106100224460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GENERATORPLUGIN_H #define GENERATORPLUGIN_H #include "generatordata.h" #include #include namespace qbs { class ProjectGeneratorPrivate; /*! * \class ProjectGenerator * \brief The \c ProjectGenerator class is an abstract base class for generators which generate * arbitrary output given a resolved Qbs project. */ class QBS_EXPORT ProjectGenerator : public QObject { Q_OBJECT Q_DISABLE_COPY(ProjectGenerator) public: ~ProjectGenerator(); /*! * Returns the name of the generator used to create the external build system files. */ virtual QString generatorName() const = 0; ErrorInfo generate(const QList &projects, const QList &buildConfigurations, const InstallOptions &installOptions, const QString &qbsSettingsDir, const Internal::Logger &logger); const GeneratableProject project() const; QFileInfo qbsExecutableFilePath() const; QString qbsSettingsDir() const; protected: ProjectGenerator(); const Internal::Logger &logger() const; private: virtual void generate() = 0; QList projects() const; QList buildConfigurations() const; QVariantMap buildConfiguration(const Project &project) const; QStringList buildConfigurationCommandLine(const Project &project) const; ProjectGeneratorPrivate *d; }; } // namespace qbs #endif // GENERATORPLUGIN_H qbs-src-1.13.1/src/lib/corelib/generators/generatordata.cpp000066400000000000000000000125411347155106100236260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "generatordata.h" #include #include #include namespace qbs { QString GeneratableProductData::name() const { return uniqueValue(&ProductData::name, QStringLiteral("Products with different names per configuration are not " "compatible with this generator. " "Consider using the targetName property instead.")); } CodeLocation GeneratableProductData::location() const { return uniqueValue(&ProductData::location, QStringLiteral("GeneratableProductData::location: internal bug; this should not happen.")); } QStringList GeneratableProductData::dependencies() const { return uniqueValue(&ProductData::dependencies, QStringLiteral("Products with different dependency lists per configuration are not " "compatible with this generator.")); } QStringList GeneratableProductData::type() const { return uniqueValue(&ProductData::type, QStringLiteral("Products with different types per configuration are not " "compatible with this generator.")); } QString GeneratableProductData::buildDirectory() const { return uniqueValue(&ProductData::buildDirectory, QStringLiteral("GeneratableProductData::buildDirectory: " "internal bug; this should not happen.")); } QString GeneratableProjectData::name() const { return uniqueValue(&ProjectData::name, QStringLiteral("Projects with different names per configuration are not " "compatible with this generator.")); } CodeLocation GeneratableProjectData::location() const { CodeLocation location; QMapIterator it(data); while (it.hasNext()) { it.next(); CodeLocation oldLocation = location; location = it.value().location(); if (oldLocation.isValid() && oldLocation != location) throw ErrorInfo(QStringLiteral("Projects with different code locations " "per configuration are not compatible with this " "generator.")); } return location; } GeneratableProjectData::Id GeneratableProjectData::uniqueName() const { GeneratableProjectData::Id id; id.value = name() + QLatin1Char('-') + location().toString(); return id; } QDir GeneratableProject::baseBuildDirectory() const { Internal::Set baseBuildDirectory; QMapIterator it(data); while (it.hasNext()) { it.next(); QDir dir(it.value().buildDirectory()); dir.cdUp(); baseBuildDirectory.insert(dir.absolutePath()); } Q_ASSERT(baseBuildDirectory.size() == 1); return *baseBuildDirectory.begin(); } QFileInfo GeneratableProject::filePath() const { Internal::Set filePath; QMapIterator it(data); while (it.hasNext()) { it.next(); filePath.insert(it.value().location().filePath()); } Q_ASSERT(filePath.size() == 1); return *filePath.begin(); } bool GeneratableProject::hasMultipleConfigurations() const { return projects.size() > 1; } QStringList GeneratableProject::commandLine() const { QStringList combinedCommandLine; QMapIterator it(commandLines); while (it.hasNext()) { it.next(); combinedCommandLine << it.value(); } return combinedCommandLine; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/generators/generatordata.h000066400000000000000000000141341347155106100232730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef GENERATORDATA_H #define GENERATORDATA_H #include #include #include #include #include #include #include namespace qbs { using GeneratableProjectMap = QMap; template struct IMultiplexableContainer { QMap data; template T uniqueValue(const std::function &func, const QString &errorMessage) const { if (data.empty()) return T(); auto it = data.begin(), end = data.end(); auto value = func(*it++); for (; it != end; ++it) { if (value != func(*it)) throw ErrorInfo(errorMessage); } return value; } void forEach(const std::function &func) const { QMapIterator it(data); while (it.hasNext()) { it.next(); func(it.key(), it.value()); } } void forEach(const std::function &func) const { QMapIterator it(data); while (it.hasNext()) { it.next(); func(it.key().toStdString(), it.value()); } } const U operator[](const QString &configurationName) const { return data[configurationName]; } const U operator[](const std::string &configurationName) const { return data[QString::fromStdString(configurationName)]; } bool isValid() const { return !data.empty(); } protected: IMultiplexableContainer() { } }; struct QBS_EXPORT GeneratableProductData : public IMultiplexableContainer { QString name() const; CodeLocation location() const; QStringList dependencies() const; QStringList type() const; QString buildDirectory() const; }; struct QBS_EXPORT GeneratableProjectData : public IMultiplexableContainer { struct Id { private: friend struct GeneratableProjectData; Id() { } QString value; public: bool operator<(const Id &id) const { return value < id.value; } }; QList subProjects; QList products; QString name() const; CodeLocation location() const; Id uniqueName() const; }; struct QBS_EXPORT GeneratableProject : public GeneratableProjectData { GeneratableProjectMap projects; QMap buildConfigurations; QMap commandLines; InstallOptions installOptions; QDir baseBuildDirectory() const; QFileInfo filePath() const; bool hasMultipleConfigurations() const; QStringList commandLine() const; void forEach(const std::function &func) const { QMapIterator it(projects); while (it.hasNext()) { it.next(); func(it.key(), it.value()); } } void forEach(const std::function &func) const { QMapIterator it(projects); while (it.hasNext()) { it.next(); func(it.key().toStdString(), it.value()); } } const Project operator[](const QString &configurationName) const { return projects[configurationName]; } const Project operator[](const std::string &configurationName) const { return projects[QString::fromStdString(configurationName)]; } bool isValid() const { return !data.empty() && !projects.empty(); } const ProjectData projectData(const QString &configurationName) const { return data[configurationName]; } const ProjectData projectData(const std::string &configurationName) const { return data[QString::fromStdString(configurationName)]; } }; } // namespace qbs #endif // GENERATORDATA_H qbs-src-1.13.1/src/lib/corelib/generators/generators.pri000066400000000000000000000010111347155106100231550ustar00rootroot00000000000000include(../../../install_prefix.pri) SOURCES += \ $$PWD/generatableprojectiterator.cpp \ $$PWD/generator.cpp \ $$PWD/generatordata.cpp HEADERS += \ $$PWD/generatableprojectiterator.h \ $$PWD/generator.h \ $$PWD/generatordata.h \ $$PWD/igeneratableprojectvisitor.h !qbs_no_dev_install { generators_headers.files = \ $$PWD/generator.h \ $$PWD/generatordata.h generators_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/generators INSTALLS += generators_headers } qbs-src-1.13.1/src/lib/corelib/generators/igeneratableprojectvisitor.h000066400000000000000000000077131347155106100261110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef IGENERATABLEPROJECTVISITOR_H #define IGENERATABLEPROJECTVISITOR_H #include "generatordata.h" namespace qbs { class IGeneratableProjectVisitor { public: virtual ~IGeneratableProjectVisitor() { } // Collapsed configurations virtual void visitProject(const GeneratableProject &project) { Q_UNUSED(project); } virtual void visitProjectData(const GeneratableProject &project, const GeneratableProjectData &parentProjectData, const GeneratableProjectData &projectData) { Q_UNUSED(project); Q_UNUSED(parentProjectData); Q_UNUSED(projectData); } virtual void visitProjectData(const GeneratableProject &project, const GeneratableProjectData &projectData) { Q_UNUSED(project); Q_UNUSED(projectData); } virtual void visitProduct(const GeneratableProject &project, const GeneratableProjectData &projectData, const GeneratableProductData &productData) { Q_UNUSED(project); Q_UNUSED(projectData); Q_UNUSED(productData); } // Expanded configurations virtual void visitProject(const Project &project, const QString &configuration) { Q_UNUSED(project); Q_UNUSED(configuration); } virtual void visitProjectData(const ProjectData &parentProjectData, const ProjectData &projectData, const QString &configuration) { Q_UNUSED(parentProjectData); Q_UNUSED(projectData); Q_UNUSED(configuration); } virtual void visitProjectData(const ProjectData &projectData, const QString &configuration) { Q_UNUSED(projectData); Q_UNUSED(configuration); } virtual void visitProduct(const ProductData &productData, const QString &configuration) { Q_UNUSED(productData); Q_UNUSED(configuration); } }; } // namespace qbs #endif // IGENERATABLEPROJECTVISITOR_H qbs-src-1.13.1/src/lib/corelib/jsextensions/000077500000000000000000000000001347155106100206625ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/corelib/jsextensions/binaryfile.cpp000066400000000000000000000202631347155106100235150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 Sergey Belyashov ** Copyright (C) 2017 Denis Shienkov ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class BinaryFile : public QObject, public QScriptable, public ResourceAcquiringScriptObject { Q_OBJECT Q_ENUMS(OpenMode) public: enum OpenMode { ReadOnly = 1, WriteOnly = 2, ReadWrite = ReadOnly | WriteOnly }; static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); ~BinaryFile(); Q_INVOKABLE void close(); Q_INVOKABLE QString filePath(); Q_INVOKABLE bool atEof() const; Q_INVOKABLE qint64 size() const; Q_INVOKABLE void resize(qint64 size); Q_INVOKABLE qint64 pos() const; Q_INVOKABLE void seek(qint64 pos); Q_INVOKABLE QVariantList read(qint64 size); Q_INVOKABLE void write(const QVariantList &data); private: explicit BinaryFile(QScriptContext *context, const QString &filePath, OpenMode mode = ReadOnly); bool checkForClosed() const; // ResourceAcquiringScriptObject implementation void releaseResources() override; QFile *m_file = nullptr; }; QScriptValue BinaryFile::ctor(QScriptContext *context, QScriptEngine *engine) { BinaryFile *t = nullptr; switch (context->argumentCount()) { case 0: return context->throwError(Tr::tr("BinaryFile constructor needs " "path of file to be opened.")); case 1: t = new BinaryFile(context, context->argument(0).toString()); break; case 2: t = new BinaryFile(context, context->argument(0).toString(), static_cast(context->argument(1).toInt32())); break; default: return context->throwError(Tr::tr("BinaryFile constructor takes at most two parameters.")); } const auto se = static_cast(engine); se->addResourceAcquiringScriptObject(t); const DubiousContextList dubiousContexts { DubiousContext(EvalContext::PropertyEvaluation, DubiousContext::SuggestMoving) }; se->checkContext(QStringLiteral("qbs.BinaryFile"), dubiousContexts); se->setUsesIo(); return engine->newQObject(t, QScriptEngine::QtOwnership); } BinaryFile::~BinaryFile() { delete m_file; } BinaryFile::BinaryFile(QScriptContext *context, const QString &filePath, OpenMode mode) { Q_ASSERT(thisObject().engine() == engine()); QIODevice::OpenMode m = QIODevice::NotOpen; switch (mode) { case ReadWrite: m = QIODevice::ReadWrite; break; case ReadOnly: m = QIODevice::ReadOnly; break; case WriteOnly: m = QIODevice::WriteOnly; break; default: context->throwError(Tr::tr("Unable to open file '%1': Undefined mode '%2'") .arg(filePath, mode)); return; } m_file = new QFile(filePath); if (Q_UNLIKELY(!m_file->open(m))) { context->throwError(Tr::tr("Unable to open file '%1': %2") .arg(filePath, m_file->errorString())); delete m_file; m_file = nullptr; } } void BinaryFile::close() { if (checkForClosed()) return; m_file->close(); delete m_file; m_file = nullptr; } QString BinaryFile::filePath() { if (checkForClosed()) return {}; return QFileInfo(*m_file).absoluteFilePath(); } bool BinaryFile::atEof() const { if (checkForClosed()) return true; return m_file->atEnd(); } qint64 BinaryFile::size() const { if (checkForClosed()) return -1; return m_file->size(); } void BinaryFile::resize(qint64 size) { if (checkForClosed()) return; if (Q_UNLIKELY(!m_file->resize(size))) { context()->throwError(Tr::tr("Could not resize '%1': %2") .arg(m_file->fileName(), m_file->errorString())); } } qint64 BinaryFile::pos() const { if (checkForClosed()) return -1; return m_file->pos(); } void BinaryFile::seek(qint64 pos) { if (checkForClosed()) return; if (Q_UNLIKELY(!m_file->seek(pos))) { context()->throwError(Tr::tr("Could not seek '%1': %2") .arg(m_file->fileName(), m_file->errorString())); } } QVariantList BinaryFile::read(qint64 size) { if (checkForClosed()) return {}; const QByteArray bytes = m_file->read(size); if (Q_UNLIKELY(bytes.size() == 0 && m_file->error() != QFile::NoError)) { context()->throwError(Tr::tr("Could not read from '%1': %2") .arg(m_file->fileName(), m_file->errorString())); } QVariantList data; std::for_each(bytes.constBegin(), bytes.constEnd(), [&data](const char &c) { data.append(c); }); return data; } void BinaryFile::write(const QVariantList &data) { if (checkForClosed()) return; QByteArray bytes; std::for_each(data.constBegin(), data.constEnd(), [&bytes](const QVariant &v) { bytes.append(v.toUInt() & 0xFF); }); const qint64 size = m_file->write(bytes); if (Q_UNLIKELY(size == -1)) { context()->throwError(Tr::tr("Could not write to '%1': %2") .arg(m_file->fileName(), m_file->errorString())); } } bool BinaryFile::checkForClosed() const { if (m_file) return false; if (QScriptContext *ctx = context()) ctx->throwError(Tr::tr("Access to BinaryFile object that was already closed.")); return true; } void BinaryFile::releaseResources() { close(); deleteLater(); } } // namespace Internal } // namespace qbs void initializeJsExtensionBinaryFile(QScriptValue extensionObject) { using namespace qbs::Internal; QScriptEngine *engine = extensionObject.engine(); const QScriptValue obj = engine->newQMetaObject(&BinaryFile::staticMetaObject, engine->newFunction(&BinaryFile::ctor)); extensionObject.setProperty(QStringLiteral("BinaryFile"), obj); } Q_DECLARE_METATYPE(qbs::Internal::BinaryFile *) #include "binaryfile.moc" qbs-src-1.13.1/src/lib/corelib/jsextensions/domxml.cpp000066400000000000000000000371301347155106100226720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 BogDan Vatra ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class XmlDomDocument; class XmlDomNode: public QObject, public QScriptable { Q_OBJECT public: static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); Q_INVOKABLE bool isElement() const; Q_INVOKABLE bool isCDATASection() const; Q_INVOKABLE bool isText() const; Q_INVOKABLE QString attribute(const QString & name, const QString & defValue = QString()); Q_INVOKABLE void setAttribute(const QString & name, const QString & value); Q_INVOKABLE bool hasAttribute(const QString & name) const; Q_INVOKABLE QString tagName() const; Q_INVOKABLE void setTagName(const QString & name); Q_INVOKABLE QString text() const; Q_INVOKABLE QString data() const; Q_INVOKABLE void setData(const QString &v) const; Q_INVOKABLE void clear(); Q_INVOKABLE bool hasAttributes() const; Q_INVOKABLE bool hasChildNodes() const; Q_INVOKABLE QScriptValue parentNode() const; Q_INVOKABLE QScriptValue firstChild(const QString & tagName = QString()); Q_INVOKABLE QScriptValue lastChild(const QString & tagName = QString()) const; Q_INVOKABLE QScriptValue previousSibling(const QString & tagName = QString()) const; Q_INVOKABLE QScriptValue nextSibling(const QString & tagName = QString()) const; Q_INVOKABLE QScriptValue appendChild(QScriptValue newChild); Q_INVOKABLE QScriptValue insertBefore(const QScriptValue& newChild, const QScriptValue& refChild); Q_INVOKABLE QScriptValue insertAfter(const QScriptValue& newChild, const QScriptValue& refChild); Q_INVOKABLE QScriptValue replaceChild(const QScriptValue& newChild, const QScriptValue& oldChild); Q_INVOKABLE QScriptValue removeChild(const QScriptValue& oldChild); protected: friend class XmlDomDocument; XmlDomNode(const QDomNode &other = QDomNode()); QDomNode m_domNode; }; class XmlDomDocument: public XmlDomNode { Q_OBJECT public: static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); Q_INVOKABLE QScriptValue documentElement(); Q_INVOKABLE QScriptValue createElement(const QString & tagName); Q_INVOKABLE QScriptValue createCDATASection(const QString & value); Q_INVOKABLE QScriptValue createTextNode(const QString & value); Q_INVOKABLE bool setContent(const QString & content); Q_INVOKABLE QString toString(int indent = 1); Q_INVOKABLE void save(const QString & filePath, int indent = 1); Q_INVOKABLE void load(const QString & filePath); protected: XmlDomDocument(QScriptContext *context, const QString &name = QString()); private: QDomDocument m_domDocument; }; QScriptValue XmlDomDocument::ctor(QScriptContext *context, QScriptEngine *engine) { XmlDomDocument *xml = nullptr; switch (context->argumentCount()) { case 0: xml = new XmlDomDocument(context); break; case 1: xml = new XmlDomDocument(context, context->argument(0).toString()); break; default: return context->throwError(QStringLiteral("DomXml(QString file = QLatin1String(\"\"))")); } QScriptValue obj = engine->newQObject(xml, QScriptEngine::ScriptOwnership); static_cast(engine)->setUsesIo(); return obj; } QScriptValue XmlDomDocument::documentElement() { return engine()->newQObject(new XmlDomNode(m_domDocument.documentElement()), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomDocument::createElement(const QString &tagName) { return engine()->newQObject(new XmlDomNode(m_domDocument.createElement(tagName)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomDocument::createCDATASection(const QString &value) { return engine()->newQObject(new XmlDomNode(m_domDocument.createCDATASection(value)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomDocument::createTextNode(const QString &value) { return engine()->newQObject(new XmlDomNode(m_domDocument.createTextNode(value)), QScriptEngine::ScriptOwnership); } bool XmlDomDocument::setContent(const QString &content) { return m_domDocument.setContent(content); } QString XmlDomDocument::toString(int indent) { return m_domDocument.toString(indent); } void XmlDomDocument::save(const QString &filePath, int indent) { QFile f(filePath); if (!f.open(QIODevice::WriteOnly)) { context()->throwError(QStringLiteral("unable to open '%1'") .arg(filePath)); return; } QByteArray buff(m_domDocument.toByteArray(indent)); if (buff.size() != f.write(buff)) { context()->throwError(f.errorString()); f.close(); return; } f.close(); if (f.error() != QFile::NoError) context()->throwError(f.errorString()); } void XmlDomDocument::load(const QString &filePath) { QFile f(filePath); if (!f.open(QIODevice::ReadOnly)) { context()->throwError(QStringLiteral("unable to open '%1'") .arg(filePath)); return; } QString errorMsg; if (!m_domDocument.setContent(&f, &errorMsg)) { context()->throwError(errorMsg); return; } } XmlDomDocument::XmlDomDocument(QScriptContext *context, const QString &name):m_domDocument(name) { Q_UNUSED(context) m_domNode = m_domDocument; } QScriptValue XmlDomNode::ctor(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(context) return engine->newQObject(new XmlDomNode(), QScriptEngine::ScriptOwnership); } bool XmlDomNode::isElement() const { return m_domNode.isElement(); } bool XmlDomNode::isCDATASection() const { return m_domNode.isCDATASection(); } bool XmlDomNode::isText() const { return m_domNode.isText(); } QString XmlDomNode::attribute(const QString &name, const QString &defValue) { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName())); return defValue; } return el.attribute(name, defValue); } void XmlDomNode::setAttribute(const QString &name, const QString &value) { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName())); return; } el.setAttribute(name, value); } bool XmlDomNode::hasAttribute(const QString &name) const { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName())); return false; } return el.hasAttribute(name); } QString XmlDomNode::tagName() const { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName())); return {}; } return el.tagName(); } void XmlDomNode::setTagName(const QString &name) { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName())); return; } el.setTagName(name); } QString XmlDomNode::text() const { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QStringLiteral("Node '%1' is not an element node").arg(m_domNode.nodeName())); return {}; } return el.text(); } QString XmlDomNode::data() const { if (m_domNode.isText()) return m_domNode.toText().data(); if (m_domNode.isCDATASection()) return m_domNode.toCDATASection().data(); if (m_domNode.isCharacterData()) return m_domNode.toCharacterData().data(); context()->throwError(QStringLiteral("Node '%1' is not a character data node").arg(m_domNode.nodeName())); return {}; } void XmlDomNode::setData(const QString &v) const { if (m_domNode.isText()) return m_domNode.toText().setData(v); if (m_domNode.isCDATASection()) return m_domNode.toCDATASection().setData(v); if (m_domNode.isCharacterData()) return m_domNode.toCharacterData().setData(v); context()->throwError(QStringLiteral("Node '%1' is not a character data node").arg(m_domNode.nodeName())); return; } void XmlDomNode::clear() { m_domNode.clear(); } bool XmlDomNode::hasAttributes() const { return m_domNode.hasAttributes(); } bool XmlDomNode::hasChildNodes() const { return m_domNode.hasChildNodes(); } QScriptValue XmlDomNode::parentNode() const { return engine()->newQObject(new XmlDomNode(m_domNode.parentNode()), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::firstChild(const QString &tagName) { if (tagName.isEmpty()) return engine()->newQObject(new XmlDomNode(m_domNode.firstChild()), QScriptEngine::ScriptOwnership); return engine()->newQObject(new XmlDomNode(m_domNode.firstChildElement(tagName)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::lastChild(const QString &tagName) const { if (tagName.isEmpty()) return engine()->newQObject(new XmlDomNode(m_domNode.lastChild()), QScriptEngine::ScriptOwnership); return engine()->newQObject(new XmlDomNode(m_domNode.lastChildElement(tagName)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::previousSibling(const QString &tagName) const { if (tagName.isEmpty()) return engine()->newQObject(new XmlDomNode(m_domNode.previousSibling()), QScriptEngine::ScriptOwnership); return engine()->newQObject(new XmlDomNode(m_domNode.previousSiblingElement(tagName)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::nextSibling(const QString &tagName) const { if (tagName.isEmpty()) return engine()->newQObject(new XmlDomNode(m_domNode.nextSibling()), QScriptEngine::ScriptOwnership); return engine()->newQObject(new XmlDomNode(m_domNode.nextSiblingElement(tagName)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::appendChild(QScriptValue newChild) { auto newNode = qobject_cast(newChild.toQObject()); if (!newNode) { context()->throwError(QStringLiteral("First argument is not a XmlDomNode object")); return {}; } return engine()->newQObject(new XmlDomNode(m_domNode.appendChild(newNode->m_domNode)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::insertBefore(const QScriptValue &newChild, const QScriptValue &refChild) { auto newNode = qobject_cast(newChild.toQObject()); if (!newNode) { context()->throwError(QStringLiteral("First argument is not a XmlDomNode object")); return {}; } auto refNode = qobject_cast(refChild.toQObject()); if (!refNode) { context()->throwError(QStringLiteral("Second argument is not a XmlDomNode object")); return {}; } return engine()->newQObject(new XmlDomNode(m_domNode.insertBefore(newNode->m_domNode, refNode->m_domNode)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::insertAfter(const QScriptValue &newChild, const QScriptValue &refChild) { auto newNode = qobject_cast(newChild.toQObject()); if (!newNode) { context()->throwError(QStringLiteral("First argument is not a XmlDomNode object")); return {}; } auto refNode = qobject_cast(refChild.toQObject()); if (!refNode) { context()->throwError(QStringLiteral("Second argument is not a XmlDomNode object")); return {}; } return engine()->newQObject(new XmlDomNode(m_domNode.insertAfter(newNode->m_domNode, refNode->m_domNode)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::replaceChild(const QScriptValue &newChild, const QScriptValue &oldChild) { auto newNode = qobject_cast(newChild.toQObject()); if (!newNode) { context()->throwError(QStringLiteral("First argument is not a XmlDomNode object")); return {}; } auto oldNode = qobject_cast(oldChild.toQObject()); if (!oldNode) { context()->throwError(QStringLiteral("Second argument is not a XmlDomNode object")); return {}; } return engine()->newQObject(new XmlDomNode(m_domNode.replaceChild(newNode->m_domNode, oldNode->m_domNode)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::removeChild(const QScriptValue &oldChild) { auto oldNode = qobject_cast(oldChild.toQObject()); if (!oldNode) { context()->throwError(QStringLiteral("First argument is not a XmlDomNode object")); return {}; } return engine()->newQObject(new XmlDomNode(m_domNode.removeChild(oldNode->m_domNode)), QScriptEngine::ScriptOwnership); } XmlDomNode::XmlDomNode(const QDomNode &other) { m_domNode = other; } } // namespace Internal } // namespace qbs void initializeJsExtensionXml(QScriptValue extensionObject) { using namespace qbs::Internal; QScriptEngine *engine = extensionObject.engine(); QScriptValue docObj = engine->newQMetaObject(&XmlDomDocument::staticMetaObject, engine->newFunction(&XmlDomDocument::ctor)); QScriptValue nodeObj = engine->newQMetaObject(&XmlDomNode::staticMetaObject, engine->newFunction(&XmlDomNode::ctor)); QScriptValue contextObject = engine->newObject(); contextObject.setProperty(QStringLiteral("DomDocument"), docObj); contextObject.setProperty(QStringLiteral("DomElement"), nodeObj); extensionObject.setProperty(QStringLiteral("Xml"), contextObject); } Q_DECLARE_METATYPE(qbs::Internal::XmlDomDocument *) Q_DECLARE_METATYPE(qbs::Internal::XmlDomNode *) #include "domxml.moc" qbs-src-1.13.1/src/lib/corelib/jsextensions/environmentextension.cpp000066400000000000000000000162001347155106100256660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include namespace qbs { namespace Internal { class EnvironmentExtension : public QObject, QScriptable { Q_OBJECT public: void initializeJsExtensionEnvironment(QScriptValue extensionObject); static QScriptValue js_ctor(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_getEnv(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_putEnv(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_unsetEnv(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_currentEnv(QScriptContext *context, QScriptEngine *engine); }; QScriptValue EnvironmentExtension::js_ctor(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); return context->throwError(Tr::tr("'Environment' cannot be instantiated.")); } static QProcessEnvironment *getProcessEnvironment(QScriptContext *context, QScriptEngine *engine, const QString &func, bool doThrow = true) { QVariant v = engine->property(StringConstants::qbsProcEnvVarInternal()); auto procenv = reinterpret_cast(v.value()); if (!procenv && doThrow) throw context->throwError(QScriptContext::UnknownError, QStringLiteral("%1 can only be called from ").arg(func) + QStringLiteral("Module.setupBuildEnvironment and ") + QStringLiteral("Module.setupRunEnvironment")); return procenv; } QScriptValue EnvironmentExtension::js_getEnv(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() != 1)) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("getEnv expects 1 argument")); const QProcessEnvironment env = static_cast(engine)->environment(); const QProcessEnvironment *procenv = getProcessEnvironment(context, engine, QStringLiteral("getEnv"), false); if (!procenv) procenv = &env; const QString name = context->argument(0).toString(); const QString value = procenv->value(name); return value.isNull() ? engine->undefinedValue() : value; } QScriptValue EnvironmentExtension::js_putEnv(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() != 2)) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("putEnv expects 2 arguments")); getProcessEnvironment(context, engine, QStringLiteral("putEnv"))->insert( context->argument(0).toString(), context->argument(1).toString()); return engine->undefinedValue(); } QScriptValue EnvironmentExtension::js_unsetEnv(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() != 1)) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("unsetEnv expects 1 argument")); getProcessEnvironment(context, engine, QStringLiteral("unsetEnv"))->remove( context->argument(0).toString()); return engine->undefinedValue(); } QScriptValue EnvironmentExtension::js_currentEnv(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(context); const QProcessEnvironment env = static_cast(engine)->environment(); const QProcessEnvironment *procenv = getProcessEnvironment(context, engine, QStringLiteral("currentEnv"), false); if (!procenv) procenv = &env; QScriptValue envObject = engine->newObject(); for (const QString &key : procenv->keys()) { const QString keyName = HostOsInfo::isWindowsHost() ? key.toUpper() : key; envObject.setProperty(keyName, QScriptValue(procenv->value(key))); } return envObject; } } // namespace Internal } // namespace qbs void initializeJsExtensionEnvironment(QScriptValue extensionObject) { using namespace qbs::Internal; QScriptEngine *engine = extensionObject.engine(); QScriptValue environmentObj = engine->newQMetaObject(&EnvironmentExtension::staticMetaObject, engine->newFunction(&EnvironmentExtension::js_ctor)); environmentObj.setProperty(QStringLiteral("getEnv"), engine->newFunction(EnvironmentExtension::js_getEnv, 1)); environmentObj.setProperty(QStringLiteral("putEnv"), engine->newFunction(EnvironmentExtension::js_putEnv, 2)); environmentObj.setProperty(QStringLiteral("unsetEnv"), engine->newFunction(EnvironmentExtension::js_unsetEnv, 1)); environmentObj.setProperty(QStringLiteral("currentEnv"), engine->newFunction(EnvironmentExtension::js_currentEnv, 0)); extensionObject.setProperty(QStringLiteral("Environment"), environmentObj); } Q_DECLARE_METATYPE(qbs::Internal::EnvironmentExtension *) #include "environmentextension.moc" qbs-src-1.13.1/src/lib/corelib/jsextensions/file.cpp000066400000000000000000000273321347155106100223140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include namespace qbs { namespace Internal { class File : public QObject, QScriptable { Q_OBJECT public: enum Filter { Dirs = 0x001, Files = 0x002, Drives = 0x004, NoSymLinks = 0x008, AllEntries = Dirs | Files | Drives, TypeMask = 0x00f, Readable = 0x010, Writable = 0x020, Executable = 0x040, PermissionMask = 0x070, Modified = 0x080, Hidden = 0x100, System = 0x200, AccessMask = 0x3F0, AllDirs = 0x400, CaseSensitive = 0x800, NoDot = 0x2000, NoDotDot = 0x4000, NoDotAndDotDot = NoDot | NoDotDot, NoFilter = -1 }; Q_DECLARE_FLAGS(Filters, Filter) Q_ENUMS(Filter) static QScriptValue js_ctor(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_copy(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_exists(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_directoryEntries(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_lastModified(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_makePath(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_move(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_remove(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_canonicalFilePath(QScriptContext *context, QScriptEngine *engine); }; QScriptValue File::js_ctor(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); return context->throwError(Tr::tr("'File' cannot be instantiated.")); } QScriptValue File::js_copy(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 2)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("copy expects 2 arguments")); } const auto se = static_cast(engine); const DubiousContextList dubiousContexts({ DubiousContext(EvalContext::PropertyEvaluation), DubiousContext(EvalContext::RuleExecution, DubiousContext::SuggestMoving) }); se->checkContext(QStringLiteral("File.copy()"), dubiousContexts); const QString sourceFile = context->argument(0).toString(); const QString targetFile = context->argument(1).toString(); QString errorMessage; if (Q_UNLIKELY(!copyFileRecursion(sourceFile, targetFile, true, true, &errorMessage))) return context->throwError(errorMessage); return true; } QScriptValue File::js_exists(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("exist expects 1 argument")); } const QString filePath = context->argument(0).toString(); const bool exists = FileInfo::exists(filePath); const auto se = static_cast(engine); se->addFileExistsResult(filePath, exists); return exists; } QScriptValue File::js_directoryEntries(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 2)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("directoryEntries expects 2 arguments")); } const auto se = static_cast(engine); const DubiousContextList dubiousContexts({ DubiousContext(EvalContext::PropertyEvaluation, DubiousContext::SuggestMoving) }); se->checkContext(QStringLiteral("File.directoryEntries()"), dubiousContexts); const QString path = context->argument(0).toString(); const auto filters = static_cast(context->argument(1).toUInt32()); QDir dir(path); const QStringList entries = dir.entryList(filters, QDir::Name); se->addDirectoryEntriesResult(path, filters, entries); return qScriptValueFromSequence(engine, entries); } QScriptValue File::js_remove(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("remove expects 1 argument")); } const auto se = static_cast(engine); const DubiousContextList dubiousContexts({ DubiousContext(EvalContext::PropertyEvaluation) }); se->checkContext(QStringLiteral("File.remove()"), dubiousContexts); QString fileName = context->argument(0).toString(); QString errorMessage; if (Q_UNLIKELY(!removeFileRecursion(QFileInfo(fileName), &errorMessage))) return context->throwError(errorMessage); return true; } QScriptValue File::js_lastModified(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("File.lastModified() expects an argument")); } const QString filePath = context->argument(0).toString(); const FileTime timestamp = FileInfo(filePath).lastModified(); const auto se = static_cast(engine); se->addFileLastModifiedResult(filePath, timestamp); return timestamp.asDouble(); } QScriptValue File::js_makePath(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("makePath expects 1 argument")); } const auto se = static_cast(engine); const DubiousContextList dubiousContexts({ DubiousContext(EvalContext::PropertyEvaluation) }); se->checkContext(QStringLiteral("File.makePath()"), dubiousContexts); return QDir::root().mkpath(context->argument(0).toString()); } QScriptValue File::js_move(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 2)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("move expects 2 arguments")); } const auto se = static_cast(engine); const DubiousContextList dubiousContexts({ DubiousContext(EvalContext::PropertyEvaluation) }); se->checkContext(QStringLiteral("File.move()"), dubiousContexts); const QString sourceFile = context->argument(0).toString(); const QString targetFile = context->argument(1).toString(); const bool overwrite = context->argumentCount() > 2 ? context->argument(2).toBool() : true; if (Q_UNLIKELY(QFileInfo(sourceFile).isDir())) return context->throwError(QStringLiteral("Could not move '%1' to '%2': " "Source file path is a directory.") .arg(sourceFile, targetFile)); if (Q_UNLIKELY(QFileInfo(targetFile).isDir())) { return context->throwError(QStringLiteral("Could not move '%1' to '%2': " "Destination file path is a directory.") .arg(sourceFile, targetFile)); } QFile f(targetFile); if (overwrite && f.exists() && !f.remove()) return context->throwError(QStringLiteral("Could not move '%1' to '%2': %3") .arg(sourceFile, targetFile, f.errorString())); if (QFile::exists(targetFile)) return context->throwError(QStringLiteral("Could not move '%1' to '%2': " "Destination file exists.") .arg(sourceFile, targetFile)); QFile f2(sourceFile); if (Q_UNLIKELY(!f2.rename(targetFile))) return context->throwError(QStringLiteral("Could not move '%1' to '%2': %3") .arg(sourceFile, targetFile, f2.errorString())); return true; } QScriptValue File::js_canonicalFilePath(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("canonicalFilePath expects 1 argument")); } return QFileInfo(context->argument(0).toString()).canonicalFilePath(); } } // namespace Internal } // namespace qbs void initializeJsExtensionFile(QScriptValue extensionObject) { using namespace qbs::Internal; QScriptEngine *engine = extensionObject.engine(); QScriptValue fileObj = engine->newQMetaObject(&File::staticMetaObject, engine->newFunction(&File::js_ctor)); fileObj.setProperty(QStringLiteral("copy"), engine->newFunction(File::js_copy)); fileObj.setProperty(QStringLiteral("exists"), engine->newFunction(File::js_exists)); fileObj.setProperty(QStringLiteral("directoryEntries"), engine->newFunction(File::js_directoryEntries)); fileObj.setProperty(QStringLiteral("lastModified"), engine->newFunction(File::js_lastModified)); fileObj.setProperty(QStringLiteral("makePath"), engine->newFunction(File::js_makePath)); fileObj.setProperty(QStringLiteral("move"), engine->newFunction(File::js_move)); fileObj.setProperty(QStringLiteral("remove"), engine->newFunction(File::js_remove)); fileObj.setProperty(QStringLiteral("canonicalFilePath"), engine->newFunction(File::js_canonicalFilePath)); extensionObject.setProperty(QStringLiteral("File"), fileObj); } Q_DECLARE_METATYPE(qbs::Internal::File *) #include "file.moc" qbs-src-1.13.1/src/lib/corelib/jsextensions/fileinfoextension.cpp000066400000000000000000000351631347155106100251260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class FileInfoExtension : public QObject, QScriptable { Q_OBJECT public: static QScriptValue js_ctor(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_path(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_fileName(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_baseName(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_suffix(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_completeSuffix(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_canonicalPath(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_cleanPath(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_completeBaseName(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_relativePath(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_resolvePath(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_isAbsolutePath(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_toWindowsSeparators(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_fromWindowsSeparators(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_toNativeSeparators(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_fromNativeSeparators(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_joinPaths(QScriptContext *context, QScriptEngine *engine); }; QScriptValue FileInfoExtension::js_ctor(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); return context->throwError(Tr::tr("'FileInfo' cannot be instantiated.")); } QScriptValue FileInfoExtension::js_path(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("path expects 1 argument")); } HostOsInfo::HostOs hostOs = HostOsInfo::hostOs(); if (context->argumentCount() > 1) { hostOs = context->argument(1).toVariant().toStringList().contains(QLatin1String("windows")) ? HostOsInfo::HostOsWindows : HostOsInfo::HostOsOtherUnix; } return FileInfo::path(context->argument(0).toString(), hostOs); } QScriptValue FileInfoExtension::js_fileName(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("fileName expects 1 argument")); } return FileInfo::fileName(context->argument(0).toString()); } QScriptValue FileInfoExtension::js_baseName(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("baseName expects 1 argument")); } return FileInfo::baseName(context->argument(0).toString()); } QScriptValue FileInfoExtension::js_suffix(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("suffix expects 1 argument")); } return FileInfo::suffix(context->argument(0).toString()); } QScriptValue FileInfoExtension::js_completeSuffix(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("completeSuffix expects 1 argument")); } return FileInfo::completeSuffix(context->argument(0).toString()); } QScriptValue FileInfoExtension::js_canonicalPath(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("canonicalPath expects 1 argument")); } return QFileInfo(context->argument(0).toString()).canonicalFilePath(); } QScriptValue FileInfoExtension::js_cleanPath(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("cleanPath expects 1 argument")); } return QDir::cleanPath(context->argument(0).toString()); } QScriptValue FileInfoExtension::js_completeBaseName(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("completeBaseName expects 1 argument")); } return FileInfo::completeBaseName(context->argument(0).toString()); } QScriptValue FileInfoExtension::js_relativePath(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("relativePath expects 2 arguments")); } const QString baseDir = context->argument(0).toString(); const QString filePath = context->argument(1).toString(); if (!FileInfo::isAbsolute(baseDir)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("FileInfo.relativePath() expects an absolute path as " "its first argument, but it is '%1'.").arg(baseDir)); } if (!FileInfo::isAbsolute(filePath)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("FileInfo.relativePath() expects an absolute path as " "its second argument, but it is '%1'.").arg(filePath)); } return QDir(baseDir).relativeFilePath(filePath); } QScriptValue FileInfoExtension::js_resolvePath(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("resolvePath expects 2 arguments")); } const QString base = context->argument(0).toString(); const QString rel = context->argument(1).toString(); return FileInfo::resolvePath(base, rel); } QScriptValue FileInfoExtension::js_isAbsolutePath(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("isAbsolutePath expects 1 argument")); } HostOsInfo::HostOs hostOs = HostOsInfo::hostOs(); if (context->argumentCount() > 1) { hostOs = context->argument(1).toVariant().toStringList().contains(QLatin1String("windows")) ? HostOsInfo::HostOsWindows : HostOsInfo::HostOsOtherUnix; } return FileInfo::isAbsolute(context->argument(0).toString(), hostOs); } QScriptValue FileInfoExtension::js_toWindowsSeparators(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("toWindowsSeparators expects 1 argument")); } return context->argument(0).toString().replace(QLatin1Char('/'), QLatin1Char('\\')); } QScriptValue FileInfoExtension::js_fromWindowsSeparators(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("fromWindowsSeparators expects 1 argument")); } return context->argument(0).toString().replace(QLatin1Char('\\'), QLatin1Char('/')); } QScriptValue FileInfoExtension::js_toNativeSeparators(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("toNativeSeparators expects 1 argument")); } return QDir::toNativeSeparators(context->argument(0).toString()); } QScriptValue FileInfoExtension::js_fromNativeSeparators(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("fromNativeSeparators expects 1 argument")); } return QDir::fromNativeSeparators(context->argument(0).toString()); } QScriptValue FileInfoExtension::js_joinPaths(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); QStringList paths; for (int i = 0; i < context->argumentCount(); ++i) { const QScriptValue value = context->argument(i); if (!value.isUndefined() && !value.isNull()) { const QString arg = value.toString(); if (!arg.isEmpty()) paths.push_back(arg); } } return engine->toScriptValue(QString::fromStdString( std::regex_replace(paths.join(QLatin1Char('/')).toStdString(), std::regex("/{2,}"), std::string("/")))); } } // namespace Internal } // namespace qbs void initializeJsExtensionFileInfo(QScriptValue extensionObject) { using namespace qbs::Internal; QScriptEngine *engine = extensionObject.engine(); QScriptValue fileInfoObj = engine->newQMetaObject(&FileInfoExtension::staticMetaObject, engine->newFunction(&FileInfoExtension::js_ctor)); fileInfoObj.setProperty(StringConstants::fileInfoPath(), engine->newFunction(FileInfoExtension::js_path)); fileInfoObj.setProperty(StringConstants::fileInfoFileName(), engine->newFunction(FileInfoExtension::js_fileName)); fileInfoObj.setProperty(StringConstants::baseNameProperty(), engine->newFunction(FileInfoExtension::js_baseName)); fileInfoObj.setProperty(QStringLiteral("suffix"), engine->newFunction(FileInfoExtension::js_suffix)); fileInfoObj.setProperty(QStringLiteral("completeSuffix"), engine->newFunction(FileInfoExtension::js_completeSuffix)); fileInfoObj.setProperty(QStringLiteral("canonicalPath"), engine->newFunction(FileInfoExtension::js_canonicalPath)); fileInfoObj.setProperty(QStringLiteral("cleanPath"), engine->newFunction(FileInfoExtension::js_cleanPath)); fileInfoObj.setProperty(StringConstants::completeBaseNameProperty(), engine->newFunction(FileInfoExtension::js_completeBaseName)); fileInfoObj.setProperty(QStringLiteral("relativePath"), engine->newFunction(FileInfoExtension::js_relativePath)); fileInfoObj.setProperty(QStringLiteral("resolvePath"), engine->newFunction(FileInfoExtension::js_resolvePath)); fileInfoObj.setProperty(QStringLiteral("isAbsolutePath"), engine->newFunction(FileInfoExtension::js_isAbsolutePath)); fileInfoObj.setProperty(QStringLiteral("toWindowsSeparators"), engine->newFunction(FileInfoExtension::js_toWindowsSeparators)); fileInfoObj.setProperty(QStringLiteral("fromWindowsSeparators"), engine->newFunction(FileInfoExtension::js_fromWindowsSeparators)); fileInfoObj.setProperty(QStringLiteral("toNativeSeparators"), engine->newFunction(FileInfoExtension::js_toNativeSeparators)); fileInfoObj.setProperty(QStringLiteral("fromNativeSeparators"), engine->newFunction(FileInfoExtension::js_fromNativeSeparators)); fileInfoObj.setProperty(QStringLiteral("joinPaths"), engine->newFunction(FileInfoExtension::js_joinPaths)); extensionObject.setProperty(QStringLiteral("FileInfo"), fileInfoObj); } Q_DECLARE_METATYPE(qbs::Internal::FileInfoExtension *) #include "fileinfoextension.moc" qbs-src-1.13.1/src/lib/corelib/jsextensions/jsextensions.cpp000066400000000000000000000066341347155106100241330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "jsextensions.h" #include #include #include using InitializerMap = QMap; static InitializerMap setupMap() { #define INITIALIZER_NAME(name) initializeJsExtension##name #define ADD_JS_EXTENSION(name) \ void INITIALIZER_NAME(name)(QScriptValue); \ map.insert(QStringLiteral(#name), &INITIALIZER_NAME(name)) InitializerMap map; ADD_JS_EXTENSION(BinaryFile); ADD_JS_EXTENSION(Environment); ADD_JS_EXTENSION(File); ADD_JS_EXTENSION(FileInfo); ADD_JS_EXTENSION(Process); ADD_JS_EXTENSION(PropertyList); ADD_JS_EXTENSION(TemporaryDir); ADD_JS_EXTENSION(TextFile); ADD_JS_EXTENSION(Utilities); ADD_JS_EXTENSION(Xml); return map; } namespace qbs { namespace Internal { static InitializerMap &initializers() { static InitializerMap theMap = setupMap(); return theMap; } void JsExtensions::setupExtensions(const QStringList &names, QScriptValue scope) { for (const QString &name : names) initializers().value(name)(scope); } QScriptValue JsExtensions::loadExtension(QScriptEngine *engine, const QString &name) { if (!hasExtension(name)) return {}; QScriptValue extensionObj = engine->newObject(); initializers().value(name)(extensionObj); return extensionObj.property(name); } bool JsExtensions::hasExtension(const QString &name) { return initializers().contains(name); } QStringList JsExtensions::extensionNames() { return initializers().keys(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/jsextensions/jsextensions.h000066400000000000000000000046531347155106100235770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_JSEXTENSIONS_H #define QBS_JSEXTENSIONS_H #include #include QT_BEGIN_NAMESPACE class QScriptEngine; class QScriptValue; QT_END_NAMESPACE namespace qbs { namespace Internal { class JsExtensions { public: static void setupExtensions(const QStringList &names, QScriptValue scope); static QScriptValue loadExtension(QScriptEngine *engine, const QString &name); static bool hasExtension(const QString &name); static QStringList extensionNames(); }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/jsextensions/jsextensions.pri000066400000000000000000000011371347155106100241340ustar00rootroot00000000000000QT += xml HEADERS += \ $$PWD/moduleproperties.h \ $$PWD/jsextensions.h SOURCES += \ $$PWD/environmentextension.cpp \ $$PWD/file.cpp \ $$PWD/fileinfoextension.cpp \ $$PWD/temporarydir.cpp \ $$PWD/textfile.cpp \ $$PWD/binaryfile.cpp \ $$PWD/process.cpp \ $$PWD/moduleproperties.cpp \ $$PWD/domxml.cpp \ $$PWD/jsextensions.cpp \ $$PWD/utilitiesextension.cpp darwin { HEADERS += $$PWD/propertylistutils.h SOURCES += $$PWD/propertylist.mm $$PWD/propertylistutils.mm LIBS += -framework Foundation } else { SOURCES += $$PWD/propertylist.cpp } qbs-src-1.13.1/src/lib/corelib/jsextensions/moduleproperties.cpp000066400000000000000000000366221347155106100250010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "moduleproperties.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { QScriptValue getDataForModuleScriptValue(QScriptEngine *engine, const ResolvedProduct *product, const Artifact *artifact, const ResolvedModule *module) { QScriptValue data = engine->newObject(); data.setProperty(ModuleNameKey, module->name); QVariant v; v.setValue(reinterpret_cast(product)); data.setProperty(ProductPtrKey, engine->newVariant(v)); v.setValue(reinterpret_cast(artifact)); data.setProperty(ArtifactPtrKey, engine->newVariant(v)); return data; } static QScriptValue getModuleProperty(const ResolvedProduct *product, const Artifact *artifact, ScriptEngine *engine, const QString &moduleName, const QString &propertyName, bool *isPresent = nullptr) { const PropertyMapConstPtr &properties = artifact ? artifact->properties : product->moduleProperties; QVariant value; if (engine->isPropertyCacheEnabled()) value = engine->retrieveFromPropertyCache(moduleName, propertyName, properties); if (!value.isValid()) { value = properties->moduleProperty(moduleName, propertyName, isPresent); // Cache the variant value. We must not cache the QScriptValue here, because it's a // reference and the user might change the actual object. if (engine->isPropertyCacheEnabled()) engine->addToPropertyCache(moduleName, propertyName, properties, value); } else if (isPresent) { *isPresent = true; } const Property p(product->uniqueName(), moduleName, propertyName, value, Property::PropertyInModule); if (artifact) engine->addPropertyRequestedFromArtifact(artifact, p); else engine->addPropertyRequestedInScript(p); return engine->toScriptValue(value); } class ModulePropertyScriptClass : public QScriptClass { public: ModulePropertyScriptClass(QScriptEngine *engine) : QScriptClass(engine) { } private: QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id) override { Q_UNUSED(flags); Q_UNUSED(id); if (name == StringConstants::dependenciesProperty() || name == StringConstants::artifactsProperty()) { // The prototype is not backed by a QScriptClass. m_result = object.prototype().property(name); return HandlesReadAccess; } if (name == StringConstants::parametersProperty()) { m_result = object.data().property(DependencyParametersKey); return HandlesReadAccess; } setup(object); QBS_ASSERT(m_product || m_artifact, return {}); bool isPresent; m_result = getModuleProperty(m_product, m_artifact, static_cast(engine()), m_moduleName, name, &isPresent); // It is important that we reject unknown property names. Otherwise QtScript will forward // *everything* to us, including built-in stuff like the hasOwnProperty function. return isPresent ? HandlesReadAccess : QueryFlags(); } QScriptValue property(const QScriptValue &, const QScriptString &, uint) override { return m_result; } QScriptClassPropertyIterator *newIterator(const QScriptValue &object) override { setup(object); QBS_ASSERT(m_artifact || m_product, return nullptr); const PropertyMapInternal *propertyMap; std::vector additionalProperties({StringConstants::artifactsProperty(), StringConstants::dependenciesProperty()}); if (m_artifact) { propertyMap = m_artifact->properties.get(); } else { propertyMap = m_product->moduleProperties.get(); if (object.data().property(DependencyParametersKey).isValid()) additionalProperties.push_back(StringConstants::parametersProperty()); } return new ScriptClassPropertyIterator(object, propertyMap->value().value(m_moduleName).toMap(), additionalProperties); } void setup(const QScriptValue &object) { if (m_lastObjectId != object.objectId()) { m_lastObjectId = object.objectId(); const QScriptValue data = object.data(); QBS_ASSERT(data.isValid(), return); m_moduleName = data.property(ModuleNameKey).toString(); m_product = reinterpret_cast( data.property(ProductPtrKey).toVariant().value()); m_artifact = reinterpret_cast( data.property(ArtifactPtrKey).toVariant().value()); } } qint64 m_lastObjectId = 0; QString m_moduleName; const ResolvedProduct *m_product = nullptr; const Artifact *m_artifact = nullptr; QScriptValue m_result; }; static QString ptrKey() { return QStringLiteral("__internalPtr"); } static QString typeKey() { return QStringLiteral("__type"); } static QString artifactType() { return QStringLiteral("artifact"); } static QScriptValue js_moduleDependencies(QScriptContext *, ScriptEngine *engine, const ResolvedModule *module) { QScriptValue result = engine->newArray(); quint32 idx = 0; for (const QString &depName : qAsConst(module->moduleDependencies)) { for (const ResolvedModuleConstPtr &dep : module->product->modules) { if (dep->name != depName) continue; QScriptValue obj = engine->newObject(engine->modulePropertyScriptClass()); obj.setPrototype(engine->moduleScriptValuePrototype(dep.get())); QScriptValue data = getDataForModuleScriptValue(engine, module->product, nullptr, dep.get()); const QVariantMap ¶ms = module->product->moduleParameters.value(dep); data.setProperty(DependencyParametersKey, dependencyParametersValue( module->product->uniqueName(), dep->name, params, engine)); obj.setData(data); result.setProperty(idx++, obj); break; } } QBS_ASSERT(idx == quint32(module->moduleDependencies.size()),;); return result; } static QScriptValue setupModuleScriptValue(ScriptEngine *engine, const ResolvedModule *module) { QScriptValue &moduleScriptValue = engine->moduleScriptValuePrototype(module); if (moduleScriptValue.isValid()) return moduleScriptValue; moduleScriptValue = engine->newObject(); QScriptValue depfunc = engine->newFunction(&js_moduleDependencies, module); moduleScriptValue.setProperty(StringConstants::dependenciesProperty(), depfunc, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::PropertyGetter); QScriptValue artifactsFunc = engine->newFunction(&artifactsScriptValueForModule, module); moduleScriptValue.setProperty(StringConstants::artifactsProperty(), artifactsFunc, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::PropertyGetter); return moduleScriptValue; } void ModuleProperties::init(QScriptValue productObject, const ResolvedProduct *product) { init(productObject, product, StringConstants::productValue()); setupModules(productObject, product, nullptr); } void ModuleProperties::init(QScriptValue artifactObject, const Artifact *artifact) { init(artifactObject, artifact, artifactType()); const auto product = artifact->product; const QVariantMap productProperties { {StringConstants::buildDirectoryProperty(), product->buildDirectory()}, {StringConstants::destinationDirProperty(), product->destinationDirectory}, {StringConstants::nameProperty(), product->name}, {StringConstants::sourceDirectoryProperty(), product->sourceDirectory}, {StringConstants::targetNameProperty(), product->targetName}, {StringConstants::typeProperty(), sorted(product->fileTags.toStringList())} }; QScriptEngine * const engine = artifactObject.engine(); artifactObject.setProperty(StringConstants::productVar(), engine->toScriptValue(productProperties)); setupModules(artifactObject, artifact->product.get(), artifact); } void ModuleProperties::setModuleScriptValue(QScriptValue targetObject, const QScriptValue &moduleObject, const QString &moduleName) { auto const e = static_cast(targetObject.engine()); const QualifiedId name = QualifiedId::fromString(moduleName); QScriptValue obj = targetObject; for (int i = 0; i < name.size() - 1; ++i) { QScriptValue tmp = obj.property(name.at(i)); if (!tmp.isObject()) tmp = e->newObject(); obj.setProperty(name.at(i), tmp); obj = tmp; } obj.setProperty(name.last(), moduleObject); if (moduleName.size() > 1) targetObject.setProperty(moduleName, moduleObject); } void ModuleProperties::init(QScriptValue objectWithProperties, const void *ptr, const QString &type) { QScriptEngine * const engine = objectWithProperties.engine(); objectWithProperties.setProperty(QStringLiteral("moduleProperty"), engine->newFunction(ModuleProperties::js_moduleProperty, 2)); objectWithProperties.setProperty(ptrKey(), engine->toScriptValue(quintptr(ptr))); objectWithProperties.setProperty(typeKey(), type); } void ModuleProperties::setupModules(QScriptValue &object, const ResolvedProduct *product, const Artifact *artifact) { const auto engine = static_cast(object.engine()); QScriptClass *modulePropertyScriptClass = engine->modulePropertyScriptClass(); if (!modulePropertyScriptClass) { modulePropertyScriptClass = new ModulePropertyScriptClass(engine); engine->setModulePropertyScriptClass(modulePropertyScriptClass); } for (const auto &module : product->modules) { QScriptValue moduleObjectPrototype = setupModuleScriptValue(engine, module.get()); QScriptValue moduleObject = engine->newObject(modulePropertyScriptClass); moduleObject.setPrototype(moduleObjectPrototype); moduleObject.setData(getDataForModuleScriptValue(engine, product, artifact, module.get())); setModuleScriptValue(object, moduleObject, module->name); } } QScriptValue ModuleProperties::js_moduleProperty(QScriptContext *context, QScriptEngine *engine) { try { return moduleProperty(context, engine); } catch (const ErrorInfo &e) { return context->throwError(e.toString()); } } QScriptValue ModuleProperties::moduleProperty(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 2)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("Function moduleProperty() expects 2 arguments")); } const QScriptValue objectWithProperties = context->thisObject(); const QScriptValue typeScriptValue = objectWithProperties.property(typeKey()); if (Q_UNLIKELY(!typeScriptValue.isString())) { return context->throwError(QScriptContext::TypeError, QStringLiteral("Internal error: __type not set up")); } const QScriptValue ptrScriptValue = objectWithProperties.property(ptrKey()); if (Q_UNLIKELY(!ptrScriptValue.isNumber())) { return context->throwError(QScriptContext::TypeError, QStringLiteral("Internal error: __internalPtr not set up")); } const void *ptr = reinterpret_cast(qscriptvalue_cast(ptrScriptValue)); const ResolvedProduct *product = nullptr; const Artifact *artifact = nullptr; if (typeScriptValue.toString() == StringConstants::productValue()) { product = static_cast(ptr); } else if (typeScriptValue.toString() == artifactType()) { artifact = static_cast(ptr); product = artifact->product.get(); } else { return context->throwError(QScriptContext::TypeError, QStringLiteral("Internal error: invalid type")); } const auto qbsEngine = static_cast(engine); const QString moduleName = context->argument(0).toString(); const QString propertyName = context->argument(1).toString(); return getModuleProperty(product, artifact, qbsEngine, moduleName, propertyName); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/jsextensions/moduleproperties.h000066400000000000000000000064511347155106100244430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_MODULEPROPERTIES_H #define QBS_MODULEPROPERTIES_H #include #include #include #include namespace qbs { namespace Internal { class ScriptEngine; enum ModulePropertiesScriptValueCommonPropertyKeys : quint32 { ModuleNameKey, ProductPtrKey, ArtifactPtrKey, DependencyParametersKey, }; QScriptValue getDataForModuleScriptValue(QScriptEngine *engine, const ResolvedProduct *product, const Artifact *artifact, const ResolvedModule *module); class ModuleProperties { public: static void init(QScriptValue productObject, const ResolvedProduct *product); static void init(QScriptValue artifactObject, const Artifact *artifact); static void setModuleScriptValue(QScriptValue targetObject, const QScriptValue &moduleObject, const QString &moduleName); private: static void init(QScriptValue objectWithProperties, const void *ptr, const QString &type); static void setupModules(QScriptValue &object, const ResolvedProduct *product, const Artifact *artifact); static QScriptValue js_moduleProperty(QScriptContext *context, QScriptEngine *engine); static QScriptValue moduleProperty(QScriptContext *context, QScriptEngine *engine); }; } // namespace Internal } // namespace qbs #endif // QBS_MODULEPROPERTIES_H qbs-src-1.13.1/src/lib/corelib/jsextensions/process.cpp000066400000000000000000000256241347155106100230550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class Process : public QObject, public QScriptable, public ResourceAcquiringScriptObject { Q_OBJECT public: static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); Process(QScriptContext *context); ~Process(); Q_INVOKABLE QString getEnv(const QString &name); Q_INVOKABLE void setEnv(const QString &name, const QString &value); Q_INVOKABLE void setCodec(const QString &codec); Q_INVOKABLE QString workingDirectory(); Q_INVOKABLE void setWorkingDirectory(const QString &dir); Q_INVOKABLE bool start(const QString &program, const QStringList &arguments); Q_INVOKABLE int exec(const QString &program, const QStringList &arguments, bool throwOnError = false); Q_INVOKABLE void close(); Q_INVOKABLE bool waitForFinished(int msecs = 30000); Q_INVOKABLE void terminate(); Q_INVOKABLE void kill(); Q_INVOKABLE QString readLine(); Q_INVOKABLE bool atEnd() const; Q_INVOKABLE QString readStdOut(); Q_INVOKABLE QString readStdErr(); Q_INVOKABLE void closeWriteChannel(); Q_INVOKABLE void write(const QString &str); Q_INVOKABLE void writeLine(const QString &str); Q_INVOKABLE int exitCode() const; static QScriptValue js_shellQuote(QScriptContext *context, QScriptEngine *engine); private: QString findExecutable(const QString &filePath) const; // ResourceAcquiringScriptObject implementation void releaseResources() override; QProcess *m_qProcess; QProcessEnvironment m_environment; QString m_workingDirectory; QTextStream *m_textStream; }; QScriptValue Process::ctor(QScriptContext *context, QScriptEngine *engine) { Process *t; switch (context->argumentCount()) { case 0: t = new Process(context); break; default: return context->throwError(QStringLiteral("Process()")); } const auto se = static_cast(engine); se->addResourceAcquiringScriptObject(t); const DubiousContextList dubiousContexts ({ DubiousContext(EvalContext::PropertyEvaluation, DubiousContext::SuggestMoving) }); se->checkContext(QStringLiteral("qbs.Process"), dubiousContexts); QScriptValue obj = engine->newQObject(t, QScriptEngine::QtOwnership); // Get environment QVariant v = engine->property(StringConstants::qbsProcEnvVarInternal()); if (v.isNull()) { // The build environment is not initialized yet. // This can happen if one uses Process on the RHS of a binding like Group.name. t->m_environment = static_cast(engine)->environment(); } else { t->m_environment = QProcessEnvironment(*reinterpret_cast(v.value())); } se->setUsesIo(); return obj; } Process::~Process() { delete m_textStream; delete m_qProcess; } Process::Process(QScriptContext *context) { Q_UNUSED(context); Q_ASSERT(thisObject().engine() == engine()); m_qProcess = new QProcess; m_textStream = new QTextStream(m_qProcess); } QString Process::getEnv(const QString &name) { Q_ASSERT(thisObject().engine() == engine()); return m_environment.value(name); } void Process::setEnv(const QString &name, const QString &value) { Q_ASSERT(thisObject().engine() == engine()); m_environment.insert(name, value); } QString Process::workingDirectory() { Q_ASSERT(thisObject().engine() == engine()); return m_workingDirectory; } void Process::setWorkingDirectory(const QString &dir) { Q_ASSERT(thisObject().engine() == engine()); m_workingDirectory = dir; } bool Process::start(const QString &program, const QStringList &arguments) { Q_ASSERT(thisObject().engine() == engine()); if (!m_workingDirectory.isEmpty()) m_qProcess->setWorkingDirectory(m_workingDirectory); m_qProcess->setProcessEnvironment(m_environment); m_qProcess->start(findExecutable(program), arguments); return m_qProcess->waitForStarted(); } int Process::exec(const QString &program, const QStringList &arguments, bool throwOnError) { Q_ASSERT(thisObject().engine() == engine()); if (!start(findExecutable(program), arguments)) { if (throwOnError) { context()->throwError(Tr::tr("Error running '%1': %2") .arg(program, m_qProcess->errorString())); } return -1; } m_qProcess->closeWriteChannel(); m_qProcess->waitForFinished(-1); if (throwOnError) { if (m_qProcess->error() != QProcess::UnknownError && m_qProcess->error() != QProcess::Crashed) { context()->throwError(Tr::tr("Error running '%1': %2") .arg(program, m_qProcess->errorString())); } else if (m_qProcess->exitStatus() == QProcess::CrashExit || m_qProcess->exitCode() != 0) { QString errorMessage = m_qProcess->error() == QProcess::Crashed ? Tr::tr("Error running '%1': %2").arg(program, m_qProcess->errorString()) : Tr::tr("Process '%1' finished with exit code %2.").arg(program).arg( m_qProcess->exitCode()); const QString stdOut = readStdOut(); if (!stdOut.isEmpty()) errorMessage.append(Tr::tr(" The standard output was:\n")).append(stdOut); const QString stdErr = readStdErr(); if (!stdErr.isEmpty()) errorMessage.append(Tr::tr(" The standard error output was:\n")).append(stdErr); context()->throwError(errorMessage); } } if (m_qProcess->error() != QProcess::UnknownError) return -1; return m_qProcess->exitCode(); } void Process::close() { if (!m_qProcess) return; Q_ASSERT(thisObject().engine() == engine()); delete m_textStream; m_textStream = nullptr; delete m_qProcess; m_qProcess = nullptr; } bool Process::waitForFinished(int msecs) { Q_ASSERT(thisObject().engine() == engine()); if (m_qProcess->state() == QProcess::NotRunning) return true; return m_qProcess->waitForFinished(msecs); } void Process::terminate() { m_qProcess->terminate(); } void Process::kill() { m_qProcess->kill(); } void Process::setCodec(const QString &codec) { Q_ASSERT(thisObject().engine() == engine()); m_textStream->setCodec(qPrintable(codec)); } QString Process::readLine() { return m_textStream->readLine(); } bool Process::atEnd() const { return m_textStream->atEnd(); } QString Process::readStdOut() { return m_textStream->readAll(); } QString Process::readStdErr() { return m_textStream->codec()->toUnicode(m_qProcess->readAllStandardError()); } void Process::closeWriteChannel() { m_textStream->flush(); m_qProcess->closeWriteChannel(); } int Process::exitCode() const { return m_qProcess->exitCode(); } QString Process::findExecutable(const QString &filePath) const { ExecutableFinder exeFinder(ResolvedProductPtr(), m_environment); return exeFinder.findExecutable(filePath, m_workingDirectory); } void Process::releaseResources() { close(); deleteLater(); } void Process::write(const QString &str) { (*m_textStream) << str; } void Process::writeLine(const QString &str) { (*m_textStream) << str; if (HostOsInfo::isWindowsHost()) (*m_textStream) << '\r'; (*m_textStream) << '\n'; } QScriptValue Process::js_shellQuote(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 2)) { return context->throwError(QScriptContext::SyntaxError, QStringLiteral("shellQuote expects at least 2 arguments")); } const QString program = context->argument(0).toString(); const QStringList args = context->argument(1).toVariant().toStringList(); HostOsInfo::HostOs hostOs = HostOsInfo::hostOs(); if (context->argumentCount() > 2) { hostOs = context->argument(2).toVariant().toStringList().contains(QLatin1String("windows")) ? HostOsInfo::HostOsWindows : HostOsInfo::HostOsOtherUnix; } return engine->toScriptValue(shellQuote(program, args, hostOs)); } } // namespace Internal } // namespace qbs void initializeJsExtensionProcess(QScriptValue extensionObject) { using namespace qbs::Internal; QScriptEngine *engine = extensionObject.engine(); QScriptValue obj = engine->newQMetaObject(&Process::staticMetaObject, engine->newFunction(&Process::ctor)); extensionObject.setProperty(QStringLiteral("Process"), obj); obj.setProperty(QStringLiteral("shellQuote"), engine->newFunction(Process::js_shellQuote, 3)); } Q_DECLARE_METATYPE(qbs::Internal::Process *) #include "process.moc" qbs-src-1.13.1/src/lib/corelib/jsextensions/propertylist.cpp000066400000000000000000000042751347155106100241560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include void initializeJsExtensionPropertyList(QScriptValue extensionObject) { QScriptEngine *engine = extensionObject.engine(); QScriptValue obj = engine->newObject(); // provide a fake object extensionObject.setProperty(QStringLiteral("PropertyList"), obj); } qbs-src-1.13.1/src/lib/corelib/jsextensions/propertylist.h000066400000000000000000000076501347155106100236230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROPERTYLIST_H #define QBS_PROPERTYLIST_H #include // ### remove when qbs requires qbs 1.6 to build itself #if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) && defined(__APPLE__) && !defined(Q_OS_MAC) #define Q_OS_MAC #endif #ifndef Q_OS_MAC #include namespace qbs { namespace Internal { // provide a fake initializer for other platforms void initializeJsExtensionPropertyList(QScriptValue extensionObject) { // provide a fake object QScriptEngine *engine = extensionObject.engine(); extensionObject.setProperty(QLatin1String("PropertyList"), engine->newObject()); } } // namespace Internal } // namespace qbs #else // Q_OS_MAC #include #include #include #include #include namespace qbs { namespace Internal { void initializeJsExtensionPropertyList(QScriptValue extensionObject); class PropertyListPrivate; class PropertyList : public QObject, public QScriptable { Q_OBJECT public: static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); PropertyList(QScriptContext *context); ~PropertyList(); Q_INVOKABLE bool isEmpty() const; Q_INVOKABLE void clear(); Q_INVOKABLE void readFromObject(const QScriptValue &value); Q_INVOKABLE void readFromString(const QString &input); Q_INVOKABLE void readFromFile(const QString &filePath); Q_INVOKABLE void readFromData(const QByteArray &data); Q_INVOKABLE void writeToFile(const QString &filePath, const QString &plistFormat); Q_INVOKABLE QScriptValue format() const; Q_INVOKABLE QScriptValue toObject() const; Q_INVOKABLE QString toString(const QString &plistFormat) const; Q_INVOKABLE QString toXMLString() const; Q_INVOKABLE QString toJSON(const QString &style = QString()) const; private: PropertyListPrivate *d; }; } // namespace Internal } // namespace qbs Q_DECLARE_METATYPE(qbs::Internal::PropertyList *) #endif // Q_OS_MAC #endif // QBS_PROPERTYLIST_H qbs-src-1.13.1/src/lib/corelib/jsextensions/propertylist.mm000066400000000000000000000313711347155106100240020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include // Same values as CoreFoundation and Foundation APIs enum { QPropertyListOpenStepFormat = 1, QPropertyListXMLFormat_v1_0 = 100, QPropertyListBinaryFormat_v1_0 = 200, QPropertyListJSONFormat = 1000 // If this conflicts someday, just change it :) }; namespace qbs { namespace Internal { class PropertyListPrivate; class PropertyList : public QObject, public QScriptable { Q_OBJECT public: static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); PropertyList(QScriptContext *context); ~PropertyList(); Q_INVOKABLE bool isEmpty() const; Q_INVOKABLE void clear(); Q_INVOKABLE void readFromObject(const QScriptValue &value); Q_INVOKABLE void readFromString(const QString &input); Q_INVOKABLE void readFromFile(const QString &filePath); Q_INVOKABLE void readFromData(const QByteArray &data); Q_INVOKABLE void writeToFile(const QString &filePath, const QString &plistFormat); Q_INVOKABLE QScriptValue format() const; Q_INVOKABLE QScriptValue toObject() const; Q_INVOKABLE QString toString(const QString &plistFormat) const; Q_INVOKABLE QString toXMLString() const; Q_INVOKABLE QString toJSON(const QString &style = QString()) const; private: PropertyListPrivate *d; }; class PropertyListPrivate { public: PropertyListPrivate(); QVariant propertyListObject; int propertyListFormat; void readFromData(QScriptContext *context, QByteArray data); QByteArray writeToData(QScriptContext *context, const QString &format); }; QScriptValue PropertyList::ctor(QScriptContext *context, QScriptEngine *engine) { auto const se = static_cast(engine); const DubiousContextList dubiousContexts({ DubiousContext(EvalContext::PropertyEvaluation, DubiousContext::SuggestMoving) }); se->checkContext(QStringLiteral("qbs.PropertyList"), dubiousContexts); auto p = new PropertyList(context); QScriptValue obj = engine->newQObject(p, QScriptEngine::ScriptOwnership); return obj; } PropertyListPrivate::PropertyListPrivate() : propertyListObject(), propertyListFormat(0) { } PropertyList::~PropertyList() { delete d; } PropertyList::PropertyList(QScriptContext *context) : d(new PropertyListPrivate) { Q_UNUSED(context); Q_ASSERT(thisObject().engine() == engine()); } bool PropertyList::isEmpty() const { Q_ASSERT(thisObject().engine() == engine()); auto p = qscriptvalue_cast(thisObject()); return p->d->propertyListObject.isNull(); } void PropertyList::clear() { Q_ASSERT(thisObject().engine() == engine()); auto p = qscriptvalue_cast(thisObject()); p->d->propertyListObject = QVariant(); p->d->propertyListFormat = 0; } void PropertyList::readFromObject(const QScriptValue &value) { Q_ASSERT(thisObject().engine() == engine()); auto p = qscriptvalue_cast(thisObject()); p->d->propertyListObject = value.toVariant(); p->d->propertyListFormat = 0; // wasn't deserialized from any external format } void PropertyList::readFromString(const QString &input) { readFromData(input.toUtf8()); } void PropertyList::readFromFile(const QString &filePath) { Q_ASSERT(thisObject().engine() == engine()); auto p = qscriptvalue_cast(thisObject()); QFile file(filePath); if (file.open(QIODevice::ReadOnly)) { const QByteArray data = file.readAll(); if (file.error() == QFile::NoError) { p->d->readFromData(p->context(), data); return; } } p->context()->throwError(QStringLiteral("%1: %2").arg(filePath).arg(file.errorString())); } void PropertyList::readFromData(const QByteArray &data) { Q_ASSERT(thisObject().engine() == engine()); auto p = qscriptvalue_cast(thisObject()); p->d->readFromData(p->context(), data); } void PropertyList::writeToFile(const QString &filePath, const QString &plistFormat) { Q_ASSERT(thisObject().engine() == engine()); auto p = qscriptvalue_cast(thisObject()); QFile file(filePath); QByteArray data = p->d->writeToData(p->context(), plistFormat); if (Q_LIKELY(!data.isEmpty())) { if (file.open(QIODevice::WriteOnly) && file.write(data) == data.size()) { return; } } p->context()->throwError(QStringLiteral("%1: %2").arg(filePath).arg(file.errorString())); } QScriptValue PropertyList::format() const { Q_ASSERT(thisObject().engine() == engine()); auto p = qscriptvalue_cast(thisObject()); switch (p->d->propertyListFormat) { case QPropertyListOpenStepFormat: return QStringLiteral("openstep"); case QPropertyListXMLFormat_v1_0: return QStringLiteral("xml1"); case QPropertyListBinaryFormat_v1_0: return QStringLiteral("binary1"); case QPropertyListJSONFormat: return QStringLiteral("json"); default: return p->engine()->undefinedValue(); } } QScriptValue PropertyList::toObject() const { Q_ASSERT(thisObject().engine() == engine()); auto p = qscriptvalue_cast(thisObject()); return p->engine()->toScriptValue(p->d->propertyListObject); } QString PropertyList::toString(const QString &plistFormat) const { Q_ASSERT(thisObject().engine() == engine()); auto p = qscriptvalue_cast(thisObject()); if (plistFormat == QLatin1String("binary1")) { p->context()->throwError(QStringLiteral("Property list object cannot be converted to a " "string in the binary1 format; this format can only " "be written directly to a file")); return {}; } if (!isEmpty()) return QString::fromUtf8(p->d->writeToData(p->context(), plistFormat)); return {}; } QString PropertyList::toXMLString() const { return toString(QStringLiteral("xml1")); } QString PropertyList::toJSON(const QString &style) const { QString format = QLatin1String("json"); if (!style.isEmpty()) format += QLatin1String("-") + style; return toString(format); } } // namespace Internal } // namespace qbs #include "propertylistutils.h" namespace qbs { namespace Internal { void PropertyListPrivate::readFromData(QScriptContext *context, QByteArray data) { @autoreleasepool { NSPropertyListFormat format; int internalFormat = 0; NSString *errorString = nil; id plist = [NSPropertyListSerialization propertyListWithData:data.toNSData() options:0 format:&format error:nil]; if (plist) { internalFormat = format; } else { NSError *error = nil; plist = [NSJSONSerialization JSONObjectWithData:data.toNSData() options:0 error:&error]; if (Q_UNLIKELY(!plist)) { errorString = [error localizedDescription]; } else { internalFormat = QPropertyListJSONFormat; } } if (Q_UNLIKELY(!plist)) { context->throwError(QString::fromNSString(errorString)); } else { QVariant obj = QPropertyListUtils::fromPropertyList(plist); if (!obj.isNull()) { propertyListObject = obj; propertyListFormat = internalFormat; } else { context->throwError(QStringLiteral("error converting property list")); } } } } QByteArray PropertyListPrivate::writeToData(QScriptContext *context, const QString &format) { @autoreleasepool { NSError *error = nil; NSString *errorString = nil; NSData *data = nil; id obj = QPropertyListUtils::toPropertyList(propertyListObject); if (!obj) { context->throwError(QStringLiteral("error converting property list")); return QByteArray(); } if (format == QLatin1String("json") || format == QLatin1String("json-pretty") || format == QLatin1String("json-compact")) { if ([NSJSONSerialization isValidJSONObject:obj]) { error = nil; errorString = nil; const NSJSONWritingOptions options = format == QLatin1String("json-pretty") ? NSJSONWritingPrettyPrinted : 0; data = [NSJSONSerialization dataWithJSONObject:obj options:options error:&error]; if (Q_UNLIKELY(!data)) { errorString = [error localizedDescription]; } } else { errorString = @"Property list object cannot be converted to JSON data"; } } else if (format == QLatin1String("xml1") || format == QLatin1String("binary1")) { const NSPropertyListFormat plistFormat = format == QLatin1String("xml1") ? NSPropertyListXMLFormat_v1_0 : NSPropertyListBinaryFormat_v1_0; error = nil; errorString = nil; data = [NSPropertyListSerialization dataWithPropertyList:obj format:plistFormat options:0 error:&error]; if (Q_UNLIKELY(!data)) { errorString = [error localizedDescription]; } } else { errorString = [NSString stringWithFormat:@"Property lists cannot be written in the '%s' " @"format", format.toUtf8().constData()]; } if (Q_UNLIKELY(!data)) { context->throwError(QString::fromNSString(errorString)); } return QByteArray::fromNSData(data); } } } // namespace Internal } // namespace qbs void initializeJsExtensionPropertyList(QScriptValue extensionObject) { using namespace qbs::Internal; QScriptEngine *engine = extensionObject.engine(); QScriptValue obj = engine->newQMetaObject(&PropertyList::staticMetaObject, engine->newFunction(&PropertyList::ctor)); extensionObject.setProperty(QStringLiteral("PropertyList"), obj); } Q_DECLARE_METATYPE(qbs::Internal::PropertyList *) #include "propertylist.moc" qbs-src-1.13.1/src/lib/corelib/jsextensions/propertylistutils.h000066400000000000000000000051541347155106100247010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2014 Petroules Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QPROPERTYLISTUTILS_H #define QPROPERTYLISTUTILS_H #include #import #if !defined(__OBJC__) || !defined(__cplusplus) #error "This file must be included from Objective-C++" #endif class QPropertyListUtils { Q_DISABLE_COPY(QPropertyListUtils) public: static QVariant fromPropertyList(id plist); static id toPropertyList(const QVariant &map); private: QPropertyListUtils(); }; template QMap qHashToMap(const QHash &hash) { QMap map; QHashIterator i(hash); while (i.hasNext()) { i.next(); map.insert(i.key(), i.value()); } return map; } #endif // QPROPERTYLISTUTILS_H qbs-src-1.13.1/src/lib/corelib/jsextensions/propertylistutils.mm000066400000000000000000000163501347155106100250630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #import #include "propertylistutils.h" #include #include #include #include static QVariant fromObject(id obj); static QVariantMap fromDictionary(NSDictionary *dict); static QVariantList fromArray(NSArray *array); static QVariant fromObject(id obj) { QVariant value; if (!obj) { return value; } else if ([obj isKindOfClass:[NSDictionary class]]) { value = fromDictionary(obj); } else if ([obj isKindOfClass:[NSArray class]]) { value = fromArray(obj); } else if ([obj isKindOfClass:[NSString class]]) { value = QString::fromNSString(obj); } else if ([obj isKindOfClass:[NSData class]]) { value = QByteArray::fromNSData(obj); } else if ([obj isKindOfClass:[NSDate class]]) { value = QDateTime::fromNSDate(obj); } else if ([obj isKindOfClass:[NSNumber class]]) { if (strcmp([(NSNumber *)obj objCType], @encode(BOOL)) == 0) { value = static_cast([obj boolValue]); } else if (strcmp([(NSNumber *)obj objCType], @encode(signed char)) == 0) { value = [obj charValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(unsigned char)) == 0) { value = [obj unsignedCharValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(signed short)) == 0) { value = [obj shortValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(unsigned short)) == 0) { value = [obj unsignedShortValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(signed int)) == 0) { value = [obj intValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(unsigned int)) == 0) { value = [obj unsignedIntValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(signed long long)) == 0) { value = [obj longLongValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(unsigned long long)) == 0) { value = [obj unsignedLongLongValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(float)) == 0) { value = [obj floatValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(double)) == 0) { value = [obj doubleValue]; } else { // NSDecimal or unknown value = [obj doubleValue]; } } else if ([obj isKindOfClass:[NSNull class]]) { // A null variant, close enough... } else { // unknown } return value; } static QVariantMap fromDictionary(NSDictionary *dict) { QVariantMap map; for (NSString *key in dict) map[QString::fromNSString(key)] = fromObject([dict objectForKey:key]); return map; } static QVariantList fromArray(NSArray *array) { QVariantList list; for (id obj in array) list.push_back(fromObject(obj)); return list; } QVariant QPropertyListUtils::fromPropertyList(id plist) { return fromObject(plist); } static id toObject(const QVariant &variant); static NSDictionary *toDictionary(const QVariantMap &map); static NSArray *toArray(const QVariantList &list); static id toObject(const QVariant &variant) { if (variant.type() == QVariant::Hash) { return toDictionary(qHashToMap(variant.toHash())); } else if (variant.type() == QVariant::Map) { return toDictionary(variant.toMap()); } else if (variant.type() == QVariant::List) { return toArray(variant.toList()); } else if (variant.type() == QVariant::String) { return variant.toString().toNSString(); } else if (variant.type() == QVariant::ByteArray) { return variant.toByteArray().toNSData(); } else if (variant.type() == QVariant::Date || variant.type() == QVariant::DateTime) { return variant.toDateTime().toNSDate(); } else if (variant.type() == QVariant::Bool) { return variant.toBool() ? [NSNumber numberWithBool:YES] : [NSNumber numberWithBool:NO]; } else if (variant.type() == QVariant::Char || variant.type() == QVariant::Int) { return [NSNumber numberWithInt:variant.toInt()]; } else if (variant.type() == QVariant::UInt) { return [NSNumber numberWithUnsignedInt:variant.toUInt()]; } else if (variant.type() == QVariant::LongLong) { return [NSNumber numberWithLongLong:variant.toLongLong()]; } else if (variant.type() == QVariant::ULongLong) { return [NSNumber numberWithUnsignedLongLong:variant.toULongLong()]; } else if (variant.type() == QVariant::Double) { return [NSNumber numberWithDouble:variant.toDouble()]; } else { return [NSNull null]; } } static NSDictionary *toDictionary(const QVariantMap &map) { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; QMapIterator i(map); while (i.hasNext()) { i.next(); [dict setObject:toObject(i.value()) forKey:i.key().toNSString()]; } return [NSDictionary dictionaryWithDictionary:dict]; } static NSArray *toArray(const QVariantList &list) { NSMutableArray *array = [NSMutableArray array]; for (const QVariant &variant : list) [array addObject:toObject(variant)]; return [NSArray arrayWithArray:array]; } id QPropertyListUtils::toPropertyList(const QVariant &variant) { return toObject(variant); } qbs-src-1.13.1/src/lib/corelib/jsextensions/temporarydir.cpp000066400000000000000000000076641347155106100241240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static bool tempDirIsCanonical() { #if QT_VERSION >= 0x050c00 return true; #endif return false; } class TemporaryDir : public QObject, public QScriptable { Q_OBJECT public: static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); TemporaryDir(QScriptContext *context); Q_INVOKABLE bool isValid() const; Q_INVOKABLE QString path() const; Q_INVOKABLE bool remove(); private: QTemporaryDir dir; }; QScriptValue TemporaryDir::ctor(QScriptContext *context, QScriptEngine *engine) { const auto se = static_cast(engine); const DubiousContextList dubiousContexts({ DubiousContext(EvalContext::PropertyEvaluation, DubiousContext::SuggestMoving) }); se->checkContext(QStringLiteral("qbs.TemporaryDir"), dubiousContexts); const auto t = new TemporaryDir(context); QScriptValue obj = engine->newQObject(t, QScriptEngine::ScriptOwnership); return obj; } TemporaryDir::TemporaryDir(QScriptContext *context) { Q_UNUSED(context); dir.setAutoRemove(false); } bool TemporaryDir::isValid() const { return dir.isValid(); } QString TemporaryDir::path() const { return tempDirIsCanonical() ? dir.path() : QFileInfo(dir.path()).canonicalFilePath(); } bool TemporaryDir::remove() { return dir.remove(); } } // namespace Internal } // namespace qbs void initializeJsExtensionTemporaryDir(QScriptValue extensionObject) { using namespace qbs::Internal; QScriptEngine *engine = extensionObject.engine(); QScriptValue obj = engine->newQMetaObject(&TemporaryDir::staticMetaObject, engine->newFunction(&TemporaryDir::ctor)); extensionObject.setProperty(QStringLiteral("TemporaryDir"), obj); } #include "temporarydir.moc" qbs-src-1.13.1/src/lib/corelib/jsextensions/textfile.cpp000066400000000000000000000165541347155106100232250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class TextFile : public QObject, public QScriptable, public ResourceAcquiringScriptObject { Q_OBJECT Q_ENUMS(OpenMode) public: enum OpenMode { ReadOnly = 1, WriteOnly = 2, ReadWrite = ReadOnly | WriteOnly, Append = 4 }; static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); ~TextFile(); Q_INVOKABLE void close(); Q_INVOKABLE QString filePath(); Q_INVOKABLE void setCodec(const QString &codec); Q_INVOKABLE QString readLine(); Q_INVOKABLE QString readAll(); Q_INVOKABLE bool atEof() const; Q_INVOKABLE void truncate(); Q_INVOKABLE void write(const QString &str); Q_INVOKABLE void writeLine(const QString &str); private: TextFile(QScriptContext *context, const QString &filePath, OpenMode mode = ReadOnly, const QString &codec = QLatin1String("UTF8")); bool checkForClosed() const; // ResourceAcquiringScriptObject implementation void releaseResources() override; QFile *m_file; QTextStream *m_stream; }; QScriptValue TextFile::ctor(QScriptContext *context, QScriptEngine *engine) { TextFile *t; switch (context->argumentCount()) { case 0: return context->throwError(Tr::tr("TextFile constructor needs path of file to be opened.")); case 1: t = new TextFile(context, context->argument(0).toString()); break; case 2: t = new TextFile(context, context->argument(0).toString(), static_cast(context->argument(1).toInt32()) ); break; case 3: t = new TextFile(context, context->argument(0).toString(), static_cast(context->argument(1).toInt32()), context->argument(2).toString() ); break; default: return context->throwError(Tr::tr("TextFile constructor takes at most three parameters.")); } const auto se = static_cast(engine); se->addResourceAcquiringScriptObject(t); const DubiousContextList dubiousContexts({ DubiousContext(EvalContext::PropertyEvaluation, DubiousContext::SuggestMoving) }); se->checkContext(QStringLiteral("qbs.TextFile"), dubiousContexts); se->setUsesIo(); return engine->newQObject(t, QScriptEngine::QtOwnership); } TextFile::~TextFile() { delete m_stream; delete m_file; } TextFile::TextFile(QScriptContext *context, const QString &filePath, OpenMode mode, const QString &codec) { Q_UNUSED(codec) Q_ASSERT(thisObject().engine() == engine()); m_file = new QFile(filePath); m_stream = new QTextStream(m_file); QIODevice::OpenMode m = QIODevice::NotOpen; if (mode & ReadOnly) m |= QIODevice::ReadOnly; if (mode & WriteOnly) m |= QIODevice::WriteOnly; if (mode & Append) m |= QIODevice::Append; if (Q_UNLIKELY(!m_file->open(m))) { context->throwError(Tr::tr("Unable to open file '%1': %2") .arg(filePath, m_file->errorString())); delete m_file; m_file = nullptr; } } void TextFile::close() { if (checkForClosed()) return; delete m_stream; m_stream = nullptr; m_file->close(); delete m_file; m_file = nullptr; } QString TextFile::filePath() { if (checkForClosed()) return {}; return QFileInfo(*m_file).absoluteFilePath(); } void TextFile::setCodec(const QString &codec) { if (checkForClosed()) return; m_stream->setCodec(qPrintable(codec)); } QString TextFile::readLine() { if (checkForClosed()) return {}; return m_stream->readLine(); } QString TextFile::readAll() { if (checkForClosed()) return {}; return m_stream->readAll(); } bool TextFile::atEof() const { if (checkForClosed()) return true; return m_stream->atEnd(); } void TextFile::truncate() { if (checkForClosed()) return; m_file->resize(0); m_stream->reset(); } void TextFile::write(const QString &str) { if (checkForClosed()) return; (*m_stream) << str; } void TextFile::writeLine(const QString &str) { if (checkForClosed()) return; (*m_stream) << str; if (HostOsInfo::isWindowsHost()) (*m_stream) << '\r'; (*m_stream) << '\n'; } bool TextFile::checkForClosed() const { if (m_file) return false; QScriptContext *ctx = context(); if (ctx) ctx->throwError(Tr::tr("Access to TextFile object that was already closed.")); return true; } void TextFile::releaseResources() { close(); deleteLater(); } } // namespace Internal } // namespace qbs void initializeJsExtensionTextFile(QScriptValue extensionObject) { using namespace qbs::Internal; QScriptEngine *engine = extensionObject.engine(); QScriptValue obj = engine->newQMetaObject(&TextFile::staticMetaObject, engine->newFunction(&TextFile::ctor)); extensionObject.setProperty(QStringLiteral("TextFile"), obj); } Q_DECLARE_METATYPE(qbs::Internal::TextFile *) #include "textfile.moc" qbs-src-1.13.1/src/lib/corelib/jsextensions/utilitiesextension.cpp000066400000000000000000001004641347155106100253430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #if defined(Q_OS_MACOS) || defined(Q_OS_OSX) #include #endif #ifdef __APPLE__ #include #include #include #include #ifndef FAT_MAGIC_64 #define FAT_MAGIC_64 0xcafebabf #define FAT_CIGAM_64 0xbfbafeca struct fat_arch_64 { cpu_type_t cputype; cpu_subtype_t cpusubtype; uint64_t offset; uint64_t size; uint32_t align; uint32_t reserved; }; #endif #endif #ifdef Q_OS_WIN #include #include #endif #include #include #include #include #include #include #include namespace qbs { namespace Internal { class UtilitiesExtension : public QObject, QScriptable { Q_OBJECT public: static QScriptValue js_ctor(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_canonicalArchitecture(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_canonicalPlatform(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_canonicalTargetArchitecture(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_canonicalToolchain(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_cStringQuote(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_getHash(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_getNativeSetting(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_kernelVersion(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_nativeSettingGroups(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_rfc1034identifier(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_smimeMessageContent(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_certificateInfo(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_signingIdentities(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_msvcCompilerInfo(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_versionCompare(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_qmlTypeInfo(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_builtinExtensionNames(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_isSharedLibrary(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_getArchitecturesFromBinary(QScriptContext *context, QScriptEngine *engine); }; QScriptValue UtilitiesExtension::js_ctor(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); return context->throwError(Tr::tr("'Utilities' cannot be instantiated.")); } QScriptValue UtilitiesExtension::js_canonicalPlatform(QScriptContext *context, QScriptEngine *engine) { const QScriptValue value = context->argument(0); if (value.isUndefined() || value.isNull()) return value; if (context->argumentCount() == 1 && value.isString()) { return engine->toScriptValue([&value] { QStringList list; for (const auto &s : HostOsInfo::canonicalOSIdentifiers(value.toString().toStdString())) list.push_back(QString::fromStdString(s)); return list; }()); } return context->throwError(QScriptContext::SyntaxError, QStringLiteral("canonicalPlatform expects one argument of type string")); } QScriptValue UtilitiesExtension::js_canonicalTargetArchitecture(QScriptContext *context, QScriptEngine *engine) { const QScriptValue arch = context->argument(0); if (arch.isUndefined() || arch.isNull()) return arch; QScriptValue endianness = context->argument(1); if (endianness.isUndefined() || endianness.isNull()) endianness = QString(); const QScriptValue vendor = context->argument(2); const QScriptValue system = context->argument(3); const QScriptValue abi = context->argument(4); if (!arch.isString() || !endianness.isString() || !vendor.isString() || !system.isString() || !abi.isString()) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("canonicalTargetArchitecture expects 1 to 5 arguments of type string")); return engine->toScriptValue(canonicalTargetArchitecture(arch.toString(), endianness.toString(), vendor.toString(), system.toString(), abi.toString())); } QScriptValue UtilitiesExtension::js_canonicalArchitecture(QScriptContext *context, QScriptEngine *engine) { const QScriptValue value = context->argument(0); if (value.isUndefined() || value.isNull()) return value; if (context->argumentCount() == 1 && value.isString()) return engine->toScriptValue(canonicalArchitecture(value.toString())); return context->throwError(QScriptContext::SyntaxError, QStringLiteral("canonicalArchitecture expects one argument of type string")); } QScriptValue UtilitiesExtension::js_canonicalToolchain(QScriptContext *context, QScriptEngine *engine) { QStringList toolchain; for (int i = 0; i < context->argumentCount(); ++i) toolchain << context->argument(i).toString(); return engine->toScriptValue(canonicalToolchain(toolchain)); } // copied from src/corelib/tools/qtools_p.h Q_DECL_CONSTEXPR inline char toHexUpper(uint value) Q_DECL_NOTHROW { return "0123456789ABCDEF"[value & 0xF]; } Q_DECL_CONSTEXPR inline int fromHex(uint c) Q_DECL_NOTHROW { return ((c >= '0') && (c <= '9')) ? int(c - '0') : ((c >= 'A') && (c <= 'F')) ? int(c - 'A' + 10) : ((c >= 'a') && (c <= 'f')) ? int(c - 'a' + 10) : /* otherwise */ -1; } // copied from src/corelib/io/qdebug.cpp static inline bool isPrintable(uchar c) { return c >= ' ' && c < 0x7f; } // modified template static inline QString escapedString(const Char *begin, int length, bool isUnicode = true) { QChar quote(QLatin1Char('"')); QString out = quote; bool lastWasHexEscape = false; const Char *end = begin + length; for (const Char *p = begin; p != end; ++p) { // check if we need to insert "" to break an hex escape sequence if (Q_UNLIKELY(lastWasHexEscape)) { if (fromHex(*p) != -1) { // yes, insert it out += QLatin1Char('"'); out += QLatin1Char('"'); } lastWasHexEscape = false; } if (sizeof(Char) == sizeof(QChar)) { // Surrogate characters are category Cs (Other_Surrogate), so isPrintable = false for them int runLength = 0; while (p + runLength != end && isPrintable(p[runLength]) && p[runLength] != '\\' && p[runLength] != '"') ++runLength; if (runLength) { out += QString(reinterpret_cast(p), runLength); p += runLength - 1; continue; } } else if (isPrintable(*p) && *p != '\\' && *p != '"') { QChar c = QLatin1Char(*p); out += c; continue; } // print as an escape sequence (maybe, see below for surrogate pairs) int buflen = 2; ushort buf[sizeof "\\U12345678" - 1]; buf[0] = '\\'; switch (*p) { case '"': case '\\': buf[1] = *p; break; case '\b': buf[1] = 'b'; break; case '\f': buf[1] = 'f'; break; case '\n': buf[1] = 'n'; break; case '\r': buf[1] = 'r'; break; case '\t': buf[1] = 't'; break; default: if (!isUnicode) { // print as hex escape buf[1] = 'x'; buf[2] = toHexUpper(uchar(*p) >> 4); buf[3] = toHexUpper(uchar(*p)); buflen = 4; lastWasHexEscape = true; break; } if (QChar::isHighSurrogate(*p)) { if ((p + 1) != end && QChar::isLowSurrogate(p[1])) { // properly-paired surrogates uint ucs4 = QChar::surrogateToUcs4(*p, p[1]); if (isPrintable(ucs4)) { buf[0] = *p; buf[1] = p[1]; buflen = 2; } else { buf[1] = 'U'; buf[2] = '0'; // toHexUpper(ucs4 >> 32); buf[3] = '0'; // toHexUpper(ucs4 >> 28); buf[4] = toHexUpper(ucs4 >> 20); buf[5] = toHexUpper(ucs4 >> 16); buf[6] = toHexUpper(ucs4 >> 12); buf[7] = toHexUpper(ucs4 >> 8); buf[8] = toHexUpper(ucs4 >> 4); buf[9] = toHexUpper(ucs4); buflen = 10; } ++p; break; } // improperly-paired surrogates, fall through } buf[1] = 'u'; buf[2] = toHexUpper(ushort(*p) >> 12); buf[3] = toHexUpper(ushort(*p) >> 8); buf[4] = toHexUpper(*p >> 4); buf[5] = toHexUpper(*p); buflen = 6; } out += QString(reinterpret_cast(buf), buflen); } out += quote; return out; } QScriptValue UtilitiesExtension::js_cStringQuote(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, QStringLiteral("cStringQuote expects 1 argument")); } QString value = context->argument(0).toString(); return engine->toScriptValue(escapedString(reinterpret_cast(value.constData()), value.size())); } QScriptValue UtilitiesExtension::js_getHash(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, QStringLiteral("getHash expects 1 argument")); } const QByteArray input = context->argument(0).toString().toLatin1(); const QByteArray hash = QCryptographicHash::hash(input, QCryptographicHash::Sha1).toHex().left(16); return engine->toScriptValue(QString::fromLatin1(hash)); } QScriptValue UtilitiesExtension::js_getNativeSetting(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 1 || context->argumentCount() > 3)) { return context->throwError(QScriptContext::SyntaxError, QStringLiteral("getNativeSetting expects between 1 and 3 arguments")); } QString key = context->argumentCount() > 1 ? context->argument(1).toString() : QString(); // We'll let empty string represent the default registry value if (HostOsInfo::isWindowsHost() && key.isEmpty()) key = StringConstants::dot(); QVariant defaultValue = context->argumentCount() > 2 ? context->argument(2).toVariant() : QVariant(); QSettings settings(context->argument(0).toString(), QSettings::NativeFormat); QVariant value = settings.value(key, defaultValue); return value.isNull() ? engine->undefinedValue() : engine->toScriptValue(value); } QScriptValue UtilitiesExtension::js_kernelVersion(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(context); return engine->toScriptValue(QSysInfo::kernelVersion()); } QScriptValue UtilitiesExtension::js_nativeSettingGroups(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() != 1)) { return context->throwError(QScriptContext::SyntaxError, QStringLiteral("nativeSettingGroups expects 1 argument")); } QSettings settings(context->argument(0).toString(), QSettings::NativeFormat); return engine->toScriptValue(settings.childGroups()); } QScriptValue UtilitiesExtension::js_rfc1034identifier(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() != 1)) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("rfc1034Identifier expects 1 argument")); const QString identifier = context->argument(0).toString(); return engine->toScriptValue(HostOsInfo::rfc1034Identifier(identifier)); } /** * Reads the contents of the S/MIME message located at \p filePath. * An equivalent command line would be: * \code security cms -D -i -o \endcode * or: * \code openssl smime -verify -noverify -inform DER -in -out \endcode * * \note A provisioning profile is an S/MIME message whose contents are an XML property list, * so this method can be used to read such files. */ QScriptValue UtilitiesExtension::js_smimeMessageContent(QScriptContext *context, QScriptEngine *engine) { #if !defined(Q_OS_MACOS) && !defined(Q_OS_OSX) Q_UNUSED(engine); return context->throwError(QScriptContext::UnknownError, QStringLiteral("smimeMessageContent is not available on this platform")); #else if (Q_UNLIKELY(context->argumentCount() != 1)) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("smimeMessageContent expects 1 argument")); const QString filePath = context->argument(0).toString(); QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) return engine->undefinedValue(); QByteArray content = smimeMessageContent(file.readAll()); if (content.isEmpty()) return engine->undefinedValue(); return engine->toScriptValue(content); #endif } QScriptValue UtilitiesExtension::js_certificateInfo(QScriptContext *context, QScriptEngine *engine) { #if !defined(Q_OS_MACOS) && !defined(Q_OS_OSX) Q_UNUSED(engine); return context->throwError(QScriptContext::UnknownError, QStringLiteral("certificateInfo is not available on this platform")); #else if (Q_UNLIKELY(context->argumentCount() != 1)) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("certificateInfo expects 1 argument")); return engine->toScriptValue(certificateInfo(context->argument(0).toVariant().toByteArray())); #endif } // Rough command line equivalent: security find-identity -p codesigning -v QScriptValue UtilitiesExtension::js_signingIdentities(QScriptContext *context, QScriptEngine *engine) { #if !defined(Q_OS_MACOS) && !defined(Q_OS_OSX) Q_UNUSED(engine); return context->throwError(QScriptContext::UnknownError, QStringLiteral("signingIdentities is not available on this platform")); #else Q_UNUSED(context); return engine->toScriptValue(identitiesProperties()); #endif } QScriptValue UtilitiesExtension::js_msvcCompilerInfo(QScriptContext *context, QScriptEngine *engine) { #ifndef Q_OS_WIN Q_UNUSED(engine); return context->throwError(QScriptContext::UnknownError, QStringLiteral("msvcCompilerInfo is not available on this platform")); #else if (Q_UNLIKELY(context->argumentCount() < 1)) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("msvcCompilerInfo expects at least 1 argument")); const QString compilerFilePath = context->argument(0).toString(); const QString compilerLanguage = context->argumentCount() > 1 ? context->argument(1).toString() : QString(); MSVC::CompilerLanguage language; if (compilerLanguage == QStringLiteral("c")) language = MSVC::CLanguage; else if (compilerLanguage == StringConstants::cppLang()) language = MSVC::CPlusPlusLanguage; else return context->throwError(QScriptContext::TypeError, QStringLiteral("msvcCompilerInfo expects \"c\" or \"cpp\" as its second argument")); MSVC msvc(compilerFilePath); VsEnvironmentDetector envdetector; if (!envdetector.start(&msvc)) return context->throwError(QScriptContext::UnknownError, QStringLiteral("Detecting the MSVC build environment failed: ") + envdetector.errorString()); try { QVariantMap envMap; for (const QString &key : msvc.environment.keys()) envMap.insert(key, msvc.environment.value(key)); return engine->toScriptValue(QVariantMap { {QStringLiteral("buildEnvironment"), envMap}, {QStringLiteral("macros"), msvc.compilerDefines(compilerFilePath, language)}, }); } catch (const qbs::ErrorInfo &info) { return context->throwError(QScriptContext::UnknownError, info.toString()); } #endif } QScriptValue UtilitiesExtension::js_versionCompare(QScriptContext *context, QScriptEngine *engine) { if (context->argumentCount() == 2) { const QScriptValue value1 = context->argument(0); const QScriptValue value2 = context->argument(1); if (value1.isString() && value2.isString()) { const auto a = Version::fromString(value1.toString()); const auto b = Version::fromString(value2.toString()); return engine->toScriptValue(compare(a, b)); } } return context->throwError(QScriptContext::SyntaxError, QStringLiteral("versionCompare expects two arguments of type string")); } QScriptValue UtilitiesExtension::js_qmlTypeInfo(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(context); return engine->toScriptValue(QString::fromStdString(qbs::LanguageInfo::qmlTypeInfo())); } QScriptValue UtilitiesExtension::js_builtinExtensionNames(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(context); return engine->toScriptValue(JsExtensions::extensionNames()); } QScriptValue UtilitiesExtension::js_isSharedLibrary(QScriptContext *context, QScriptEngine *engine) { if (context->argumentCount() == 1) { const QScriptValue value = context->argument(0); if (value.isString()) return engine->toScriptValue(QLibrary::isLibrary(value.toString())); } return context->throwError(QScriptContext::SyntaxError, QStringLiteral("isSharedLibrary expects one argument of type string")); } #ifdef __APPLE__ template T readInt(QIODevice *ioDevice, bool *ok, bool swap, bool peek = false) { const auto bytes = peek ? ioDevice->peek(sizeof(T)) : ioDevice->read(sizeof(T)); if (bytes.size() != sizeof(T)) { if (ok) *ok = false; return T(); } if (ok) *ok = true; T n = *reinterpret_cast(bytes.constData()); return swap ? qbswap(n) : n; } static QString archName(cpu_type_t cputype, cpu_subtype_t cpusubtype) { switch (cputype) { case CPU_TYPE_X86: switch (cpusubtype) { case CPU_SUBTYPE_X86_ALL: return QStringLiteral("i386"); default: return {}; } case CPU_TYPE_X86_64: switch (cpusubtype) { case CPU_SUBTYPE_X86_64_ALL: return QStringLiteral("x86_64"); case CPU_SUBTYPE_X86_64_H: return QStringLiteral("x86_64h"); default: return {}; } case CPU_TYPE_ARM: switch (cpusubtype) { case CPU_SUBTYPE_ARM_V7: return QStringLiteral("armv7a"); case CPU_SUBTYPE_ARM_V7S: return QStringLiteral("armv7s"); case CPU_SUBTYPE_ARM_V7K: return QStringLiteral("armv7k"); default: return {}; } case CPU_TYPE_ARM64: switch (cpusubtype) { case CPU_SUBTYPE_ARM64_ALL: return QStringLiteral("arm64"); default: return {}; } default: return {}; } } static QStringList detectMachOArchs(QIODevice *device) { bool ok; bool foundMachO = false; qint64 pos = device->pos(); char ar_header[SARMAG]; if (device->read(ar_header, SARMAG) == SARMAG) { if (strncmp(ar_header, ARMAG, SARMAG) == 0) { while (!device->atEnd()) { static_assert(sizeof(ar_hdr) == 60, "sizeof(ar_hdr) != 60"); ar_hdr header; if (device->read(reinterpret_cast(&header), sizeof(ar_hdr)) != sizeof(ar_hdr)) return {}; // If the file name is stored in the "extended format" manner, // the real filename is prepended to the data section, so skip that many bytes int filenameLength = 0; if (strncmp(header.ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0) { char arName[sizeof(header.ar_name)] = { 0 }; memcpy(arName, header.ar_name + sizeof(AR_EFMT1) - 1, sizeof(header.ar_name) - (sizeof(AR_EFMT1) - 1) - 1); filenameLength = strtoul(arName, nullptr, 10); if (device->read(filenameLength).size() != filenameLength) return {}; } switch (readInt(device, nullptr, false, true)) { case MH_CIGAM: case MH_CIGAM_64: case MH_MAGIC: case MH_MAGIC_64: foundMachO = true; break; default: { // Skip the data and go to the next archive member... char szBuf[sizeof(header.ar_size) + 1] = { 0 }; memcpy(szBuf, header.ar_size, sizeof(header.ar_size)); int sz = static_cast(strtoul(szBuf, nullptr, 10)); if (sz % 2 != 0) ++sz; sz -= filenameLength; const auto data = device->read(sz); if (data.size() != sz) return {}; } } if (foundMachO) break; } } } // Wasn't an archive file, so try a fat file if (!foundMachO && !device->seek(pos)) return {}; pos = device->pos(); fat_header fatheader; fatheader.magic = readInt(device, nullptr, false); if (fatheader.magic == FAT_MAGIC || fatheader.magic == FAT_CIGAM || fatheader.magic == FAT_MAGIC_64 || fatheader.magic == FAT_CIGAM_64) { const bool swap = fatheader.magic == FAT_CIGAM || fatheader.magic == FAT_CIGAM_64; const bool is64bit = fatheader.magic == FAT_MAGIC_64 || fatheader.magic == FAT_CIGAM_64; fatheader.nfat_arch = readInt(device, &ok, swap); if (!ok) return {}; QStringList archs; for (uint32_t n = 0; n < fatheader.nfat_arch; ++n) { fat_arch_64 fatarch; static_assert(sizeof(fat_arch_64) == 32, "sizeof(fat_arch_64) != 32"); static_assert(sizeof(fat_arch) == 20, "sizeof(fat_arch) != 20"); const qint64 expectedBytes = is64bit ? sizeof(fat_arch_64) : sizeof(fat_arch); if (device->read(reinterpret_cast(&fatarch), expectedBytes) != expectedBytes) return {}; if (swap) { fatarch.cputype = qbswap(fatarch.cputype); fatarch.cpusubtype = qbswap(fatarch.cpusubtype); } const QString name = archName(fatarch.cputype, fatarch.cpusubtype); if (name.isEmpty()) { qWarning("Unknown cputype %d and cpusubtype %d", fatarch.cputype, fatarch.cpusubtype); return {}; } archs.push_back(name); } std::sort(archs.begin(), archs.end()); return archs; } // Wasn't a fat file, so we just read a thin Mach-O from the original offset if (!device->seek(pos)) return {}; bool swap = false; mach_header header; header.magic = readInt(device, nullptr, swap); switch (header.magic) { case MH_CIGAM: case MH_CIGAM_64: swap = true; break; case MH_MAGIC: case MH_MAGIC_64: break; default: return {}; } header.cputype = static_cast(readInt(device, &ok, swap)); if (!ok) return {}; header.cpusubtype = static_cast(readInt(device, &ok, swap)); if (!ok) return {}; const QString name = archName(header.cputype, header.cpusubtype); if (name.isEmpty()) { qWarning("Unknown cputype %d and cpusubtype %d", header.cputype, header.cpusubtype); return {}; } return {name}; } #endif QScriptValue UtilitiesExtension::js_getArchitecturesFromBinary(QScriptContext *context, QScriptEngine *engine) { if (context->argumentCount() != 1) { return context->throwError(QScriptContext::SyntaxError, QStringLiteral("getArchitecturesFromBinary expects exactly one argument")); } const QScriptValue arg = context->argument(0); if (!arg.isString()) { return context->throwError(QScriptContext::SyntaxError, QStringLiteral("getArchitecturesFromBinary expects a string argument")); } QStringList archs; #ifdef __APPLE__ QFile file(arg.toString()); if (!file.open(QIODevice::ReadOnly)) { return context->throwError(QScriptContext::SyntaxError, QStringLiteral("Failed to open file '%1': %2") .arg(file.fileName(), file.errorString())); } archs = detectMachOArchs(&file); #endif // __APPLE__ return engine->toScriptValue(archs); } } // namespace Internal } // namespace qbs void initializeJsExtensionUtilities(QScriptValue extensionObject) { using namespace qbs::Internal; QScriptEngine *engine = extensionObject.engine(); QScriptValue environmentObj = engine->newQMetaObject(&UtilitiesExtension::staticMetaObject, engine->newFunction(&UtilitiesExtension::js_ctor)); environmentObj.setProperty(QStringLiteral("canonicalArchitecture"), engine->newFunction(UtilitiesExtension::js_canonicalArchitecture, 1)); environmentObj.setProperty(QStringLiteral("canonicalPlatform"), engine->newFunction(UtilitiesExtension::js_canonicalPlatform, 1)); environmentObj.setProperty(QStringLiteral("canonicalTargetArchitecture"), engine->newFunction( UtilitiesExtension::js_canonicalTargetArchitecture, 4)); environmentObj.setProperty(QStringLiteral("canonicalToolchain"), engine->newFunction(UtilitiesExtension::js_canonicalToolchain)); environmentObj.setProperty(QStringLiteral("cStringQuote"), engine->newFunction(UtilitiesExtension::js_cStringQuote, 1)); environmentObj.setProperty(QStringLiteral("getHash"), engine->newFunction(UtilitiesExtension::js_getHash, 1)); environmentObj.setProperty(QStringLiteral("getNativeSetting"), engine->newFunction(UtilitiesExtension::js_getNativeSetting, 3)); environmentObj.setProperty(QStringLiteral("kernelVersion"), engine->newFunction(UtilitiesExtension::js_kernelVersion, 0)); environmentObj.setProperty(QStringLiteral("nativeSettingGroups"), engine->newFunction(UtilitiesExtension::js_nativeSettingGroups, 1)); environmentObj.setProperty(QStringLiteral("rfc1034Identifier"), engine->newFunction(UtilitiesExtension::js_rfc1034identifier, 1)); environmentObj.setProperty(QStringLiteral("smimeMessageContent"), engine->newFunction(UtilitiesExtension::js_smimeMessageContent, 1)); environmentObj.setProperty(QStringLiteral("certificateInfo"), engine->newFunction(UtilitiesExtension::js_certificateInfo, 1)); environmentObj.setProperty(QStringLiteral("signingIdentities"), engine->newFunction(UtilitiesExtension::js_signingIdentities, 0)); environmentObj.setProperty(QStringLiteral("msvcCompilerInfo"), engine->newFunction(UtilitiesExtension::js_msvcCompilerInfo, 1)); environmentObj.setProperty(QStringLiteral("versionCompare"), engine->newFunction(UtilitiesExtension::js_versionCompare, 2)); environmentObj.setProperty(QStringLiteral("qmlTypeInfo"), engine->newFunction(UtilitiesExtension::js_qmlTypeInfo, 0)); environmentObj.setProperty(QStringLiteral("builtinExtensionNames"), engine->newFunction(UtilitiesExtension::js_builtinExtensionNames, 0)); environmentObj.setProperty(QStringLiteral("isSharedLibrary"), engine->newFunction(UtilitiesExtension::js_isSharedLibrary, 1)); environmentObj.setProperty(QStringLiteral("getArchitecturesFromBinary"), engine->newFunction(UtilitiesExtension::js_getArchitecturesFromBinary, 1)); extensionObject.setProperty(QStringLiteral("Utilities"), environmentObj); } Q_DECLARE_METATYPE(qbs::Internal::UtilitiesExtension *) #include "utilitiesextension.moc" qbs-src-1.13.1/src/lib/corelib/language/000077500000000000000000000000001347155106100177115ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/corelib/language/artifactproperties.cpp000066400000000000000000000051471347155106100243360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "artifactproperties.h" #include namespace qbs { namespace Internal { ArtifactPropertiesPtr ArtifactProperties::create() { return ArtifactPropertiesPtr(new ArtifactProperties); } ArtifactProperties::ArtifactProperties() { } FileTags ArtifactProperties::extraFileTags() const { return m_extraFileTags; } void ArtifactProperties::addExtraFileTags(const FileTags &extraFileTags) { m_extraFileTags.unite(extraFileTags); } bool operator==(const ArtifactProperties &ap1, const ArtifactProperties &ap2) { return ap1.fileTagsFilter() == ap2.fileTagsFilter() && ap1.extraFileTags() == ap2.extraFileTags() && *ap1.propertyMap() == *ap2.propertyMap(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/artifactproperties.h000066400000000000000000000061221347155106100237750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ARTIFACTPROPERTIES_H #define QBS_ARTIFACTPROPERTIES_H #include "filetags.h" #include "forward_decls.h" #include namespace qbs { namespace Internal { class ArtifactProperties { public: static ArtifactPropertiesPtr create(); void setFileTagsFilter(const FileTags &filter) { m_fileTagsFilter = filter; } FileTags fileTagsFilter() const { return m_fileTagsFilter; } PropertyMapPtr propertyMap() const { return m_propertyMap; } void setPropertyMapInternal(const PropertyMapPtr &pmap) { m_propertyMap = pmap; } FileTags extraFileTags() const; void addExtraFileTags(const FileTags &extraFileTags); template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(m_fileTagsFilter, m_extraFileTags, m_propertyMap); } private: ArtifactProperties(); FileTags m_fileTagsFilter; FileTags m_extraFileTags; PropertyMapPtr m_propertyMap; }; bool operator==(const ArtifactProperties &ap1, const ArtifactProperties &ap2); inline bool operator!=(const ArtifactProperties &ap1, const ArtifactProperties &ap2) { return !(ap1 == ap2); } } // namespace Internal } // namespace qbs #endif // QBS_ARTIFACTPROPERTIES_H qbs-src-1.13.1/src/lib/corelib/language/astimportshandler.cpp000066400000000000000000000313451347155106100241660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "astimportshandler.h" #include "asttools.h" #include "builtindeclarations.h" #include "filecontext.h" #include "itemreadervisitorstate.h" #include "jsextensions/jsextensions.h" #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { ASTImportsHandler::ASTImportsHandler(ItemReaderVisitorState &visitorState, Logger &logger, const FileContextPtr &file) : m_visitorState(visitorState) , m_logger(logger) , m_file(file) , m_directory(FileInfo::path(m_file->filePath())) { } void ASTImportsHandler::handleImports(const QbsQmlJS::AST::UiImportList *uiImportList) { for (const QString &searchPath : m_file->searchPaths()) collectPrototypes(searchPath + QStringLiteral("/imports"), QString()); // files in the same directory are available as prototypes collectPrototypes(m_directory, QString()); bool baseImported = false; for (const auto *it = uiImportList; it; it = it->next) handleImport(it->import, &baseImported); if (!baseImported) { QStringRef qbsref(&StringConstants::qbsModule()); QbsQmlJS::AST::UiQualifiedId qbsURI(qbsref); qbsURI.finish(); QbsQmlJS::AST::UiImport imp(&qbsURI); handleImport(&imp, &baseImported); } for (auto it = m_jsImports.constBegin(); it != m_jsImports.constEnd(); ++it) m_file->addJsImport(it.value()); } void ASTImportsHandler::handleImport(const QbsQmlJS::AST::UiImport *import, bool *baseImported) { QStringList importUri; bool isBase = false; if (import->importUri) { importUri = toStringList(import->importUri); isBase = (importUri.size() == 1 && importUri.front() == StringConstants::qbsModule()) || (importUri.size() == 2 && importUri.front() == StringConstants::qbsModule() && importUri.last() == StringConstants::baseVar()); if (isBase) { *baseImported = true; checkImportVersion(import->versionToken); } else if (import->versionToken.length) { m_logger.printWarning(ErrorInfo(Tr::tr("Superfluous version specification."), toCodeLocation(m_file->filePath(), import->versionToken))); } } QString as; if (isBase) { if (Q_UNLIKELY(!import->importId.isNull())) { throw ErrorInfo(Tr::tr("Import of qbs.base must have no 'as '"), toCodeLocation(m_file->filePath(), import->importIdToken)); } } else { if (importUri.size() == 2 && importUri.front() == StringConstants::qbsModule()) { const QString extensionName = importUri.last(); if (JsExtensions::hasExtension(extensionName)) { if (Q_UNLIKELY(!import->importId.isNull())) { throw ErrorInfo(Tr::tr("Import of built-in extension '%1' " "must not have 'as' specifier.").arg(extensionName), toCodeLocation(m_file->filePath(), import->asToken)); } if (Q_UNLIKELY(m_file->jsExtensions().contains(extensionName))) { m_logger.printWarning(ErrorInfo(Tr::tr("Built-in extension '%1' already " "imported.").arg(extensionName), toCodeLocation(m_file->filePath(), import->importToken))); } else { m_file->addJsExtension(extensionName); } return; } } if (import->importId.isNull()) { if (!import->fileName.isNull()) { throw ErrorInfo(Tr::tr("File imports require 'as '"), toCodeLocation(m_file->filePath(), import->importToken)); } if (importUri.empty()) { throw ErrorInfo(Tr::tr("Invalid import URI."), toCodeLocation(m_file->filePath(), import->importToken)); } as = importUri.last(); } else { as = import->importId.toString(); } if (Q_UNLIKELY(JsExtensions::hasExtension(as))) throw ErrorInfo(Tr::tr("Cannot reuse the name of built-in extension '%1'.").arg(as), toCodeLocation(m_file->filePath(), import->importIdToken)); if (Q_UNLIKELY(!m_importAsNames.insert(as).second)) { throw ErrorInfo(Tr::tr("Cannot import into the same name more than once."), toCodeLocation(m_file->filePath(), import->importIdToken)); } } if (!import->fileName.isNull()) { QString filePath = FileInfo::resolvePath(m_directory, import->fileName.toString()); QFileInfo fi(filePath); if (Q_UNLIKELY(!fi.exists())) throw ErrorInfo(Tr::tr("Cannot find imported file %0.") .arg(QDir::toNativeSeparators(filePath)), CodeLocation(m_file->filePath(), import->fileNameToken.startLine, import->fileNameToken.startColumn)); filePath = fi.canonicalFilePath(); if (fi.isDir()) { collectPrototypesAndJsCollections(filePath, as, toCodeLocation(m_file->filePath(), import->fileNameToken)); } else { if (filePath.endsWith(QStringLiteral(".js"), Qt::CaseInsensitive)) { JsImport &jsImport = m_jsImports[as]; jsImport.scopeName = as; jsImport.filePaths.push_back(filePath); jsImport.location = toCodeLocation(m_file->filePath(), import->firstSourceLocation()); } else if (filePath.endsWith(QStringLiteral(".qbs"), Qt::CaseInsensitive)) { m_typeNameToFile.insert(QStringList(as), filePath); } else { throw ErrorInfo(Tr::tr("Can only import .qbs and .js files"), CodeLocation(m_file->filePath(), import->fileNameToken.startLine, import->fileNameToken.startColumn)); } } } else if (!importUri.empty()) { const QString importPath = isBase ? QStringLiteral("qbs/base") : importUri.join(QDir::separator()); bool found = m_typeNameToFile.contains(importUri); if (!found) { for (const QString &searchPath : m_file->searchPaths()) { const QFileInfo fi(FileInfo::resolvePath( FileInfo::resolvePath(searchPath, StringConstants::importsDir()), importPath)); if (fi.isDir()) { // ### versioning, qbsdir file, etc. const QString &resultPath = fi.absoluteFilePath(); collectPrototypesAndJsCollections(resultPath, as, toCodeLocation(m_file->filePath(), import->fileNameToken)); found = true; break; } } } if (Q_UNLIKELY(!found)) { throw ErrorInfo(Tr::tr("import %1 not found") .arg(importUri.join(QLatin1Char('.'))), toCodeLocation(m_file->filePath(), import->fileNameToken)); } } } Version ASTImportsHandler::readImportVersion(const QString &str, const CodeLocation &location) { const Version v = Version::fromString(str); if (Q_UNLIKELY(!v.isValid())) throw ErrorInfo(Tr::tr("Cannot parse version number in import statement."), location); if (Q_UNLIKELY(v.patchLevel() != 0)) { throw ErrorInfo(Tr::tr("Version number in import statement cannot have more than " "two components."), location); } return v; } bool ASTImportsHandler::addPrototype(const QString &fileName, const QString &filePath, const QString &as, bool needsCheck) { if (needsCheck && fileName.size() <= 4) return false; const QString componentName = fileName.left(fileName.size() - 4); // ### validate componentName if (needsCheck && !componentName.at(0).isUpper()) return false; QStringList prototypeName; if (!as.isEmpty()) prototypeName.push_back(as); prototypeName.push_back(componentName); if (!m_typeNameToFile.contains(prototypeName)) m_typeNameToFile.insert(prototypeName, filePath); return true; } void ASTImportsHandler::checkImportVersion(const QbsQmlJS::AST::SourceLocation &versionToken) const { if (!versionToken.length) return; const QString importVersionString = m_file->content().mid(versionToken.offset, versionToken.length); const Version importVersion = readImportVersion(importVersionString, toCodeLocation(m_file->filePath(), versionToken)); if (Q_UNLIKELY(importVersion != BuiltinDeclarations::instance().languageVersion())) throw ErrorInfo(Tr::tr("Incompatible qbs language version %1. This is version %2.").arg( importVersionString, BuiltinDeclarations::instance().languageVersion().toString()), toCodeLocation(m_file->filePath(), versionToken)); } void ASTImportsHandler::collectPrototypes(const QString &path, const QString &as) { QStringList fileNames; // Yes, file *names*. if (m_visitorState.findDirectoryEntries(path, &fileNames)) { for (const QString &fileName : qAsConst(fileNames)) addPrototype(fileName, path + QLatin1Char('/') + fileName, as, false); return; } QDirIterator dirIter(path, StringConstants::qbsFileWildcards()); while (dirIter.hasNext()) { const QString filePath = dirIter.next(); const QString fileName = dirIter.fileName(); if (addPrototype(fileName, filePath, as, true)) fileNames << fileName; } m_visitorState.cacheDirectoryEntries(path, fileNames); } void ASTImportsHandler::collectPrototypesAndJsCollections(const QString &path, const QString &as, const CodeLocation &location) { collectPrototypes(path, as); QDirIterator dirIter(path, StringConstants::jsFileWildcards()); while (dirIter.hasNext()) { dirIter.next(); JsImport &jsImport = m_jsImports[as]; if (jsImport.scopeName.isNull()) { jsImport.scopeName = as; jsImport.location = location; } jsImport.filePaths.push_back(dirIter.filePath()); } } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/astimportshandler.h000066400000000000000000000067341347155106100236370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ASTIMPORTSHANDLER_H #define QBS_ASTIMPORTSHANDLER_H #include "forward_decls.h" #include #include #include #include namespace qbs { class CodeLocation; class Version; namespace Internal { class ItemReaderVisitorState; class JsImport; class Logger; class ASTImportsHandler { public: ASTImportsHandler(ItemReaderVisitorState &visitorState, Logger &logger, const FileContextPtr &file); void handleImports(const QbsQmlJS::AST::UiImportList *uiImportList); QHash typeNameFileMap() const { return m_typeNameToFile; } private: static Version readImportVersion(const QString &str, const CodeLocation &location); bool addPrototype(const QString &fileName, const QString &filePath, const QString &as, bool needsCheck); void checkImportVersion(const QbsQmlJS::AST::SourceLocation &versionToken) const; void collectPrototypes(const QString &path, const QString &as); void collectPrototypesAndJsCollections(const QString &path, const QString &as, const CodeLocation &location); void handleImport(const QbsQmlJS::AST::UiImport *import, bool *baseImported); ItemReaderVisitorState &m_visitorState; Logger &m_logger; const FileContextPtr &m_file; const QString m_directory; QHash m_typeNameToFile; Set m_importAsNames; using JsImportsHash = QHash; JsImportsHash m_jsImports; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/language/astpropertiesitemhandler.cpp000066400000000000000000000172451347155106100255470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "astpropertiesitemhandler.h" #include "item.h" #include "value.h" #include #include #include #include namespace qbs { namespace Internal { ASTPropertiesItemHandler::ASTPropertiesItemHandler(Item *parentItem) : m_parentItem(parentItem) { } void ASTPropertiesItemHandler::handlePropertiesItems() { // TODO: Simply forbid Properties items to have child items and get rid of this check. if (m_parentItem->type() != ItemType::Properties) setupAlternatives(); } void ASTPropertiesItemHandler::setupAlternatives() { auto it = m_parentItem->m_children.begin(); while (it != m_parentItem->m_children.end()) { Item * const child = *it; bool remove = false; if (child->type() == ItemType::Properties) { handlePropertiesBlock(child); remove = m_parentItem->type() != ItemType::Export; } if (remove) it = m_parentItem->m_children.erase(it); else ++it; } } class PropertiesBlockConverter { public: PropertiesBlockConverter(const JSSourceValue::AltProperty &condition, const JSSourceValue::AltProperty &overrideListProperties, Item *propertiesBlockContainer, const Item *propertiesBlock) : m_propertiesBlockContainer(propertiesBlockContainer) , m_propertiesBlock(propertiesBlock) { m_alternative.condition = condition; m_alternative.overrideListProperties = overrideListProperties; } void apply() { doApply(m_propertiesBlockContainer, m_propertiesBlock); } private: JSSourceValue::Alternative m_alternative; Item * const m_propertiesBlockContainer; const Item * const m_propertiesBlock; void doApply(Item *outer, const Item *inner) { for (auto it = inner->properties().constBegin(); it != inner->properties().constEnd(); ++it) { if (inner == m_propertiesBlock && (it.key() == StringConstants::conditionProperty() || it.key() == StringConstants::overrideListPropertiesProperty())) { continue; } if (it.value()->type() == Value::ItemValueType) { Item * const innerVal = std::static_pointer_cast(it.value())->item(); ItemValuePtr outerVal = outer->itemProperty(it.key()); if (!outerVal) { outerVal = ItemValue::create(Item::create(outer->pool(), innerVal->type()), true); outer->setProperty(it.key(), outerVal); } doApply(outerVal->item(), innerVal); } else if (it.value()->type() == Value::JSSourceValueType) { const ValuePtr outerVal = outer->property(it.key()); if (Q_UNLIKELY(outerVal && outerVal->type() != Value::JSSourceValueType)) { throw ErrorInfo(Tr::tr("Incompatible value type in unconditional value at %1.") .arg(outerVal->location().toString())); } doApply(it.key(), outer, std::static_pointer_cast(outerVal), std::static_pointer_cast(it.value())); } else { QBS_CHECK(!"Unexpected value type in conditional value."); } } } void doApply(const QString &propertyName, Item *item, JSSourceValuePtr value, const JSSourceValuePtr &conditionalValue) { if (!value) { value = JSSourceValue::create(true); value->setFile(conditionalValue->file()); item->setProperty(propertyName, value); value->setSourceCode(QStringRef(&StringConstants::baseVar())); value->setSourceUsesBaseFlag(); } m_alternative.value = conditionalValue; value->addAlternative(m_alternative); } }; static JSSourceValue::AltProperty getPropertyData(const Item *propertiesItem, const QString &name) { const ValuePtr value = propertiesItem->property(name); if (!value) { if (name == StringConstants::conditionProperty()) { throw ErrorInfo(Tr::tr("Properties.condition must be provided."), propertiesItem->location()); } return JSSourceValue::AltProperty(StringConstants::falseValue(), propertiesItem->location()); } if (Q_UNLIKELY(value->type() != Value::JSSourceValueType)) { throw ErrorInfo(Tr::tr("Properties.%1 must be a value binding.").arg(name), propertiesItem->location()); } if (name == StringConstants::overrideListPropertiesProperty()) { const Item *parent = propertiesItem->parent(); while (parent) { if (parent->type() == ItemType::Product) break; parent = parent->parent(); } if (!parent) { throw ErrorInfo(Tr::tr("Properties.overrideListProperties can only be set " "in a Product item.")); } } const JSSourceValuePtr srcval = std::static_pointer_cast(value); return JSSourceValue::AltProperty(srcval->sourceCodeForEvaluation(), srcval->location()); } void ASTPropertiesItemHandler::handlePropertiesBlock(const Item *propertiesItem) { const auto condition = getPropertyData(propertiesItem, StringConstants::conditionProperty()); const auto overrideListProperties = getPropertyData(propertiesItem, StringConstants::overrideListPropertiesProperty()); PropertiesBlockConverter(condition, overrideListProperties, m_parentItem, propertiesItem).apply(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/astpropertiesitemhandler.h000066400000000000000000000044521347155106100252100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ASTPROPERTIESITEMHANDLER_H #define QBS_ASTPROPERTIESITEMHANDLER_H namespace qbs { namespace Internal { class Item; class ASTPropertiesItemHandler { public: ASTPropertiesItemHandler(Item *parentItem); void handlePropertiesItems(); private: void setupAlternatives(); void handlePropertiesBlock(const Item *propertiesItem); Item * const m_parentItem; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/language/asttools.cpp000066400000000000000000000055021347155106100222670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "asttools.h" #include namespace qbs { namespace Internal { QStringList toStringList(QbsQmlJS::AST::UiQualifiedId *qid) { QStringList result; for (; qid; qid = qid->next) result.push_back(qid->name.toString()); return result; } CodeLocation toCodeLocation(const QString &filePath, const QbsQmlJS::AST::SourceLocation &location) { return CodeLocation(filePath, location.startLine, location.startColumn); } QString textOf(const QString &source, QbsQmlJS::AST::Node *node) { if (!node) return {}; return source.mid(node->firstSourceLocation().begin(), node->lastSourceLocation().end() - node->firstSourceLocation().begin()); } QStringRef textRefOf(const QString &source, QbsQmlJS::AST::Node *node) { const quint32 firstBegin = node->firstSourceLocation().begin(); return source.midRef(firstBegin, node->lastSourceLocation().end() - firstBegin); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/asttools.h000066400000000000000000000046131347155106100217360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ASTTOOLS_H #define QBS_ASTTOOLS_H #include #include #include namespace qbs { namespace Internal { QStringList toStringList(QbsQmlJS::AST::UiQualifiedId *qid); CodeLocation toCodeLocation(const QString &filePath, const QbsQmlJS::AST::SourceLocation &location); QString textOf(const QString &source, QbsQmlJS::AST::Node *node); QStringRef textRefOf(const QString &source, QbsQmlJS::AST::Node *node); } // namespace Internal } // namespace qbs #endif // QBS_ASTTOOLS_H qbs-src-1.13.1/src/lib/corelib/language/builtindeclarations.cpp000066400000000000000000000664421347155106100244700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "builtindeclarations.h" #include "deprecationinfo.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { class AClassWithPublicConstructor : public BuiltinDeclarations { }; Q_GLOBAL_STATIC(AClassWithPublicConstructor, theInstance) const char QBS_LANGUAGE_VERSION[] = "1.0"; BuiltinDeclarations::BuiltinDeclarations() : m_languageVersion(Version::fromString(QLatin1String(QBS_LANGUAGE_VERSION))) , m_typeMap(std::initializer_list>({ { QStringLiteral("Artifact"), ItemType::Artifact }, { QStringLiteral("Depends"), ItemType::Depends }, { QStringLiteral("Export"), ItemType::Export }, { QStringLiteral("FileTagger"), ItemType::FileTagger }, { QStringLiteral("Group"), ItemType::Group }, { QStringLiteral("JobLimit"), ItemType::JobLimit }, { QStringLiteral("Module"), ItemType::Module }, { QStringLiteral("ModuleProvider"), ItemType::ModuleProvider }, { QStringLiteral("Parameter"), ItemType::Parameter }, { QStringLiteral("Parameters"), ItemType::Parameters }, { QStringLiteral("Probe"), ItemType::Probe }, { QStringLiteral("Product"), ItemType::Product }, { QStringLiteral("Profile"), ItemType::Profile }, { QStringLiteral("Project"), ItemType::Project }, { QStringLiteral("Properties"), ItemType::Properties }, // Callers have to handle the SubProject case. { QStringLiteral("PropertyOptions"), ItemType::PropertyOptions }, { QStringLiteral("Rule"), ItemType::Rule }, { QStringLiteral("Scanner"), ItemType::Scanner }, { QStringLiteral("SubProject"), ItemType::SubProject }, { QStringLiteral("Transformer"), ItemType::Transformer } })) { addArtifactItem(); addDependsItem(); addExportItem(); addFileTaggerItem(); addGroupItem(); addJobLimitItem(); addModuleItem(); addModuleProviderItem(); addProbeItem(); addProductItem(); addProfileItem(); addProjectItem(); addPropertiesItem(); addPropertyOptionsItem(); addRuleItem(); addSubprojectItem(); addTransformerItem(); addScannerItem(); } const BuiltinDeclarations &BuiltinDeclarations::instance() { return *theInstance; } Version BuiltinDeclarations::languageVersion() const { return m_languageVersion; } QStringList BuiltinDeclarations::allTypeNames() const { return m_typeMap.keys(); } ItemDeclaration BuiltinDeclarations::declarationsForType(ItemType type) const { return m_builtins.value(type); } ItemType BuiltinDeclarations::typeForName(const QString &typeName, const CodeLocation location) const { const auto it = m_typeMap.constFind(typeName); if (it == m_typeMap.constEnd()) throw ErrorInfo(Tr::tr("Unexpected item type '%1'.").arg(typeName), location); return it.value(); } QString BuiltinDeclarations::nameForType(ItemType itemType) const { // Iterating is okay here, as this mapping is not used in hot code paths. if (itemType == ItemType::PropertiesInSubProject) return QStringLiteral("Properties"); for (auto it = m_typeMap.constBegin(); it != m_typeMap.constEnd(); ++it) { if (it.value() == itemType) return it.key(); } QBS_CHECK(false); return {}; } QStringList BuiltinDeclarations::argumentNamesForScriptFunction(ItemType itemType, const QString &scriptName) const { const ItemDeclaration itemDecl = declarationsForType(itemType); for (const PropertyDeclaration &propDecl : itemDecl.properties()) { if (propDecl.name() == scriptName) return propDecl.functionArgumentNames(); } QBS_CHECK(false); return {}; } void BuiltinDeclarations::insert(const ItemDeclaration &decl) { m_builtins.insert(decl.type(), decl); } static PropertyDeclaration conditionProperty() { return PropertyDeclaration(StringConstants::conditionProperty(), PropertyDeclaration::Boolean, StringConstants::trueValue()); } static PropertyDeclaration alwaysRunProperty() { return PropertyDeclaration(StringConstants::alwaysRunProperty(), PropertyDeclaration::Boolean, StringConstants::falseValue()); } static PropertyDeclaration nameProperty() { return PropertyDeclaration(StringConstants::nameProperty(), PropertyDeclaration::String); } static PropertyDeclaration buildDirProperty() { return PropertyDeclaration(StringConstants::buildDirectoryProperty(), PropertyDeclaration::Path); } static PropertyDeclaration prepareScriptProperty() { PropertyDeclaration decl(StringConstants::prepareProperty(), PropertyDeclaration::Variant, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); decl.setFunctionArgumentNames( QStringList() << StringConstants::projectVar() << StringConstants::productValue() << StringConstants::inputsVar() << StringConstants::outputsVar() << StringConstants::inputVar() << StringConstants::outputVar() << StringConstants::explicitlyDependsOnVar()); return decl; } static PropertyDeclaration priorityProperty() { return {StringConstants::priorityProperty(), PropertyDeclaration::Integer}; } void BuiltinDeclarations::addArtifactItem() { ItemDeclaration item(ItemType::Artifact); PropertyDeclaration conditionDecl = conditionProperty(); conditionDecl.setDeprecationInfo(DeprecationInfo(Version(1, 4), Tr::tr("If you need " "dynamic artifacts, use the Rule.outputArtifacts script instead of Artifact items."))); item << conditionDecl; PropertyDeclaration fileNameDecl(StringConstants::fileNameProperty(), PropertyDeclaration::String); fileNameDecl.setDeprecationInfo(DeprecationInfo(Version(1, 4), Tr::tr("Please use 'filePath' instead."))); item << fileNameDecl; item << PropertyDeclaration(StringConstants::filePathProperty(), PropertyDeclaration::String); item << PropertyDeclaration(StringConstants::fileTagsProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::alwaysUpdatedProperty(), PropertyDeclaration::Boolean, StringConstants::trueValue()); insert(item); } void BuiltinDeclarations::addDependsItem() { ItemDeclaration item(ItemType::Depends); item << conditionProperty(); item << nameProperty(); item << PropertyDeclaration(StringConstants::submodulesProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::requiredProperty(), PropertyDeclaration::Boolean, StringConstants::trueValue()); item << PropertyDeclaration(StringConstants::versionAtLeastProperty(), PropertyDeclaration::String); item << PropertyDeclaration(StringConstants::versionBelowProperty(), PropertyDeclaration::String); item << PropertyDeclaration(StringConstants::profilesProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::productTypesProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::limitToSubProjectProperty(), PropertyDeclaration::Boolean, StringConstants::falseValue()); item << PropertyDeclaration(StringConstants::multiplexConfigurationIdsProperty(), PropertyDeclaration::StringList, QString(), PropertyDeclaration::ReadOnlyFlag); item << PropertyDeclaration(StringConstants::enableFallbackProperty(), PropertyDeclaration::Boolean, StringConstants::trueValue()); insert(item); } void BuiltinDeclarations::addExportItem() { ItemDeclaration item = moduleLikeItem(ItemType::Export); item << PropertyDeclaration(StringConstants::prefixMappingProperty(), PropertyDeclaration::Variant); auto allowedChildTypes = item.allowedChildTypes(); allowedChildTypes.insert(ItemType::Parameters); allowedChildTypes.insert(ItemType::Properties); item.setAllowedChildTypes(allowedChildTypes); insert(item); } void BuiltinDeclarations::addFileTaggerItem() { ItemDeclaration item(ItemType::FileTagger); item << conditionProperty(); item << PropertyDeclaration(StringConstants::patternsProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::fileTagsProperty(), PropertyDeclaration::StringList); item << priorityProperty(); insert(item); } void BuiltinDeclarations::addGroupItem() { ItemDeclaration item(ItemType::Group); item.setAllowedChildTypes({ ItemType::Group }); item << conditionProperty(); item << PropertyDeclaration(StringConstants::nameProperty(), PropertyDeclaration::String, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(StringConstants::filesProperty(), PropertyDeclaration::PathList, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(StringConstants::fileTagsFilterProperty(), PropertyDeclaration::StringList, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(StringConstants::excludeFilesProperty(), PropertyDeclaration::PathList, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(StringConstants::fileTagsProperty(), PropertyDeclaration::StringList, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(StringConstants::prefixProperty(), PropertyDeclaration::String, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(StringConstants::overrideTagsProperty(), PropertyDeclaration::Boolean, StringConstants::trueValue(), PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(StringConstants::filesAreTargetsProperty(), PropertyDeclaration::Boolean, StringConstants::falseValue(), PropertyDeclaration::PropertyNotAvailableInConfig); insert(item); } void BuiltinDeclarations::addJobLimitItem() { ItemDeclaration item(ItemType::JobLimit); item << conditionProperty(); item << PropertyDeclaration(StringConstants::jobPoolProperty(), PropertyDeclaration::String); item << PropertyDeclaration(StringConstants::jobCountProperty(), PropertyDeclaration::Integer); insert(item); } void BuiltinDeclarations::addModuleItem() { ItemDeclaration item = moduleLikeItem(ItemType::Module); item << priorityProperty(); insert(item); } void BuiltinDeclarations::addModuleProviderItem() { ItemDeclaration item(ItemType::ModuleProvider); item << nameProperty() << PropertyDeclaration(QStringLiteral("outputBaseDir"), PropertyDeclaration::String) << PropertyDeclaration(QStringLiteral("relativeSearchPaths"), PropertyDeclaration::StringList); insert(item); } ItemDeclaration BuiltinDeclarations::moduleLikeItem(ItemType type) { ItemDeclaration item(type); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << ItemType::Group << ItemType::Depends << ItemType::FileTagger << ItemType::JobLimit << ItemType::Rule << ItemType::Parameter << ItemType::Probe << ItemType::PropertyOptions << ItemType::Scanner); item << nameProperty(); item << conditionProperty(); PropertyDeclaration setupBuildEnvDecl(StringConstants::setupBuildEnvironmentProperty(), PropertyDeclaration::Variant, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); setupBuildEnvDecl.setFunctionArgumentNames(QStringList{StringConstants::projectVar(), StringConstants::productVar()}); item << setupBuildEnvDecl; PropertyDeclaration setupRunEnvDecl(StringConstants::setupRunEnvironmentProperty(), PropertyDeclaration::Variant, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); setupRunEnvDecl.setFunctionArgumentNames(QStringList{StringConstants::projectVar(), StringConstants::productVar()}); item << setupRunEnvDecl; item << PropertyDeclaration(StringConstants::validateProperty(), PropertyDeclaration::Boolean, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(StringConstants::additionalProductTypesProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::versionProperty(), PropertyDeclaration::String); item << PropertyDeclaration(StringConstants::presentProperty(), PropertyDeclaration::Boolean, StringConstants::trueValue()); return item; } void BuiltinDeclarations::addProbeItem() { ItemDeclaration item(ItemType::Probe); item << conditionProperty(); item << PropertyDeclaration(StringConstants::foundProperty(), PropertyDeclaration::Boolean, StringConstants::falseValue()); item << PropertyDeclaration(StringConstants::configureProperty(), PropertyDeclaration::Variant, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); insert(item); } void BuiltinDeclarations::addProductItem() { ItemDeclaration item(ItemType::Product); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << ItemType::Depends << ItemType::Group << ItemType::FileTagger << ItemType::JobLimit << ItemType::Export << ItemType::Probe << ItemType::Profile << ItemType::PropertyOptions << ItemType::Rule); item << conditionProperty(); item << PropertyDeclaration(StringConstants::typeProperty(), PropertyDeclaration::StringList, StringConstants::emptyArrayValue()); item << nameProperty(); item << PropertyDeclaration(StringConstants::builtByDefaultProperty(), PropertyDeclaration::Boolean, StringConstants::trueValue()); PropertyDeclaration profilesDecl(StringConstants::profilesProperty(), PropertyDeclaration::StringList); profilesDecl.setDeprecationInfo(DeprecationInfo(Version::fromString(QStringLiteral("1.9.0")), Tr::tr("Use qbs.profiles instead."))); item << profilesDecl; item << PropertyDeclaration(StringConstants::targetNameProperty(), PropertyDeclaration::String, QStringLiteral("new String(name)" ".replace(/[/\\\\?%*:|\"<>]/g, '_').valueOf()")); item << buildDirProperty(); item << PropertyDeclaration(StringConstants::destinationDirProperty(), PropertyDeclaration::String, StringConstants::buildDirectoryProperty()); item << PropertyDeclaration(StringConstants::consoleApplicationProperty(), PropertyDeclaration::Boolean); item << PropertyDeclaration(StringConstants::filesProperty(), PropertyDeclaration::PathList, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(StringConstants::excludeFilesProperty(), PropertyDeclaration::PathList, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(StringConstants::qbsSearchPathsProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::versionProperty(), PropertyDeclaration::String); item << PropertyDeclaration(StringConstants::multiplexByQbsPropertiesProperty(), PropertyDeclaration::StringList, QStringLiteral("[\"profiles\"]")); item << PropertyDeclaration(StringConstants::multiplexedTypeProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::aggregateProperty(), PropertyDeclaration::Boolean); item << PropertyDeclaration(StringConstants::multiplexedProperty(), PropertyDeclaration::Boolean, QString(), PropertyDeclaration::ReadOnlyFlag); item << PropertyDeclaration(StringConstants::multiplexConfigurationIdProperty(), PropertyDeclaration::String, QString(), PropertyDeclaration::ReadOnlyFlag); insert(item); } void BuiltinDeclarations::addProfileItem() { ItemDeclaration item(ItemType::Profile); item << conditionProperty(); item << nameProperty(); item << PropertyDeclaration(StringConstants::baseProfileProperty(), PropertyDeclaration::String); insert(item); } void BuiltinDeclarations::addProjectItem() { ItemDeclaration item(ItemType::Project); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << ItemType::Project << ItemType::PropertyOptions << ItemType::SubProject << ItemType::Product << ItemType::Profile << ItemType::Probe << ItemType::FileTagger << ItemType::JobLimit << ItemType::Rule); item << nameProperty(); item << conditionProperty(); item << buildDirProperty(); item << PropertyDeclaration(StringConstants::minimumQbsVersionProperty(), PropertyDeclaration::String); item << PropertyDeclaration(StringConstants::sourceDirectoryProperty(), PropertyDeclaration::Path); item << PropertyDeclaration(StringConstants::profileProperty(), PropertyDeclaration::String); item << PropertyDeclaration(StringConstants::referencesProperty(), PropertyDeclaration::PathList, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(StringConstants::qbsSearchPathsProperty(), PropertyDeclaration::StringList, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); insert(item); } void BuiltinDeclarations::addPropertiesItem() { ItemDeclaration item(ItemType::Properties); item << conditionProperty(); insert(item); } void BuiltinDeclarations::addPropertyOptionsItem() { ItemDeclaration item(ItemType::PropertyOptions); item << nameProperty(); item << PropertyDeclaration(StringConstants::allowedValuesProperty(), PropertyDeclaration::Variant); item << PropertyDeclaration(StringConstants::descriptionProperty(), PropertyDeclaration::String); item << PropertyDeclaration(StringConstants::removalVersionProperty(), PropertyDeclaration::String); insert(item); } void BuiltinDeclarations::addRuleItem() { ItemDeclaration item(ItemType::Rule); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << ItemType::Artifact); item << conditionProperty(); item << alwaysRunProperty(); item << PropertyDeclaration(StringConstants::multiplexProperty(), PropertyDeclaration::Boolean, StringConstants::falseValue()); item << PropertyDeclaration(StringConstants::requiresInputsProperty(), PropertyDeclaration::Boolean); item << nameProperty(); item << PropertyDeclaration(StringConstants::inputsProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::outputFileTagsProperty(), PropertyDeclaration::StringList); PropertyDeclaration outputArtifactsDecl(StringConstants::outputArtifactsProperty(), PropertyDeclaration::Variant, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); outputArtifactsDecl.setFunctionArgumentNames( QStringList() << StringConstants::projectVar() << StringConstants::productVar() << StringConstants::inputsVar() << StringConstants::inputVar()); item << outputArtifactsDecl; PropertyDeclaration usingsDecl(QStringLiteral("usings"), PropertyDeclaration::StringList); usingsDecl.setDeprecationInfo(DeprecationInfo(Version(1, 5), Tr::tr("Use 'inputsFromDependencies' instead"))); item << usingsDecl; item << PropertyDeclaration(StringConstants::inputsFromDependenciesProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::auxiliaryInputsProperty(), PropertyDeclaration::StringList); PropertyDeclaration excludedAuxInputs(StringConstants::excludedAuxiliaryInputsProperty(), PropertyDeclaration::StringList); excludedAuxInputs.setDeprecationInfo(DeprecationInfo(Version(1, 14), Tr::tr("Use 'excludedInputs' instead"))); item << excludedAuxInputs; item << PropertyDeclaration(StringConstants::excludedInputsProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::explicitlyDependsOnProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::explicitlyDependsOnFromDependenciesProperty(), PropertyDeclaration::StringList); item << prepareScriptProperty(); insert(item); } void BuiltinDeclarations::addSubprojectItem() { ItemDeclaration item(ItemType::SubProject); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << ItemType::Project // needed, because we're adding this internally << ItemType::PropertiesInSubProject << ItemType::PropertyOptions); item << conditionProperty(); item << PropertyDeclaration(StringConstants::filePathProperty(), PropertyDeclaration::Path); item << PropertyDeclaration(StringConstants::inheritPropertiesProperty(), PropertyDeclaration::Boolean, StringConstants::trueValue()); insert(item); } void BuiltinDeclarations::addTransformerItem() { ItemDeclaration item(ItemType::Transformer); item.setDeprecationInfo(DeprecationInfo(Version(1, 7), Tr::tr("Use the 'Rule' item instead."))); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << ItemType::Artifact); item << conditionProperty(); item << alwaysRunProperty(); item << PropertyDeclaration(StringConstants::inputsProperty(), PropertyDeclaration::PathList); item << prepareScriptProperty(); item << PropertyDeclaration(StringConstants::explicitlyDependsOnProperty(), PropertyDeclaration::StringList); insert(item); } void BuiltinDeclarations::addScannerItem() { ItemDeclaration item(ItemType::Scanner); item << conditionProperty(); item << PropertyDeclaration(StringConstants::inputsProperty(), PropertyDeclaration::StringList); item << PropertyDeclaration(StringConstants::recursiveProperty(), PropertyDeclaration::Boolean, StringConstants::falseValue()); PropertyDeclaration searchPaths(StringConstants::searchPathsProperty(), PropertyDeclaration::StringList); searchPaths.setFunctionArgumentNames( QStringList() << StringConstants::projectVar() << StringConstants::productVar() << StringConstants::inputVar()); item << searchPaths; PropertyDeclaration scan(StringConstants::scanProperty(), PropertyDeclaration::Variant, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); scan.setFunctionArgumentNames( QStringList() << StringConstants::projectVar() << StringConstants::productVar() << StringConstants::inputVar() << StringConstants::filePathVar()); item << scan; insert(item); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/builtindeclarations.h000066400000000000000000000067561347155106100241370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BUILTINDECLARATIONS_H #define QBS_BUILTINDECLARATIONS_H #include "itemdeclaration.h" #include "itemtype.h" #include #include #include #include #include namespace qbs { namespace Internal { class BuiltinDeclarations { public: static const BuiltinDeclarations &instance(); Version languageVersion() const; QStringList allTypeNames() const; ItemDeclaration declarationsForType(ItemType type) const; ItemType typeForName(const QString &typeName, const CodeLocation location = CodeLocation()) const; QString nameForType(ItemType itemType) const; QStringList argumentNamesForScriptFunction(ItemType itemType, const QString &scriptName) const; protected: BuiltinDeclarations(); private: void insert(const ItemDeclaration &decl); void addArtifactItem(); void addDependsItem(); void addExportItem(); void addFileTaggerItem(); void addGroupItem(); void addJobLimitItem(); void addModuleItem(); void addModuleProviderItem(); static ItemDeclaration moduleLikeItem(ItemType type); void addProbeItem(); void addProductItem(); void addProfileItem(); void addProjectItem(); void addPropertiesItem(); void addPropertyOptionsItem(); void addRuleItem(); void addSubprojectItem(); void addTransformerItem(); void addScannerItem(); const Version m_languageVersion; QMap m_builtins; const QHash m_typeMap; }; } // namespace Internal } // namespace qbs #endif // QBS_BUILTINDECLARATIONS_H qbs-src-1.13.1/src/lib/corelib/language/deprecationinfo.h000066400000000000000000000051761347155106100232440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_DEPRECATIONINFO_H #define QBS_DEPRECATIONINFO_H #include #include namespace qbs { namespace Internal { class DeprecationInfo { public: explicit DeprecationInfo(const Version &removalVersion, const QString &additionalUserInfo = QString()) : m_removalVersion(removalVersion) , m_additionalUserInfo(additionalUserInfo) {} DeprecationInfo() {} bool isValid() const { return m_removalVersion.isValid(); } Version removalVersion() const { return m_removalVersion; } QString additionalUserInfo() const { return m_additionalUserInfo; } private: Version m_removalVersion; QString m_additionalUserInfo; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/language/evaluationdata.h000066400000000000000000000044711347155106100230710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_EVALUATIONDATA_H #define QBS_EVALUATIONDATA_H #include #include #include #include namespace qbs { namespace Internal { class Evaluator; class Item; class EvaluationData { public: Evaluator *evaluator; const Item *item; mutable QHash valueCache; }; } // namespace Internal } // namespace qbs #endif // QBS_EVALUATIONDATA_H qbs-src-1.13.1/src/lib/corelib/language/evaluator.cpp000066400000000000000000000216541347155106100224270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "evaluator.h" #include "evaluationdata.h" #include "evaluatorscriptclass.h" #include "filecontext.h" #include "filetags.h" #include "item.h" #include "scriptengine.h" #include "value.h" #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { Evaluator::Evaluator(ScriptEngine *scriptEngine) : m_scriptEngine(scriptEngine) , m_scriptClass(new EvaluatorScriptClass(scriptEngine)) { } Evaluator::~Evaluator() { for (const auto &data : qAsConst(m_scriptValueMap)) delete attachedPointer(data); delete m_scriptClass; } QScriptValue Evaluator::property(const Item *item, const QString &name) { return scriptValue(item).property(name); } QScriptValue Evaluator::value(const Item *item, const QString &name, bool *propertyWasSet) { QScriptValue v; evaluateProperty(&v, item, name, propertyWasSet); return v; } bool Evaluator::boolValue(const Item *item, const QString &name, bool *propertyWasSet) { return value(item, name, propertyWasSet).toBool(); } int Evaluator::intValue(const Item *item, const QString &name, int defaultValue, bool *propertyWasSet) { QScriptValue v; if (!evaluateProperty(&v, item, name, propertyWasSet)) return defaultValue; return v.toInt32(); } FileTags Evaluator::fileTagsValue(const Item *item, const QString &name, bool *propertySet) { return FileTags::fromStringList(stringListValue(item, name, propertySet)); } QString Evaluator::stringValue(const Item *item, const QString &name, const QString &defaultValue, bool *propertyWasSet) { QScriptValue v; if (!evaluateProperty(&v, item, name, propertyWasSet)) return defaultValue; return v.toString(); } static QStringList toStringList(const QScriptValue &scriptValue) { if (scriptValue.isString()) { return {scriptValue.toString()}; } else if (scriptValue.isArray()) { QStringList lst; int i = 0; forever { QScriptValue elem = scriptValue.property(i++); if (!elem.isValid()) break; lst.push_back(elem.toString()); } return lst; } return {}; } QStringList Evaluator::stringListValue(const Item *item, const QString &name, bool *propertyWasSet) { QScriptValue v = property(item, name); handleEvaluationError(item, name, v); if (propertyWasSet) *propertyWasSet = isNonDefaultValue(item, name); return toStringList(v); } bool Evaluator::isNonDefaultValue(const Item *item, const QString &name) const { const ValueConstPtr v = item->property(name); return v && (v->type() != Value::JSSourceValueType || !static_cast(v.get())->isBuiltinDefaultValue()); } void Evaluator::convertToPropertyType(const PropertyDeclaration &decl, const CodeLocation &loc, QScriptValue &v) { m_scriptClass->convertToPropertyType(decl, loc, v); } QScriptValue Evaluator::scriptValue(const Item *item) { QScriptValue &scriptValue = m_scriptValueMap[item]; if (scriptValue.isObject()) { // already initialized return scriptValue; } const auto edata = new EvaluationData; edata->evaluator = this; edata->item = item; edata->item->setObserver(this); scriptValue = m_scriptEngine->newObject(m_scriptClass); attachPointerTo(scriptValue, edata); return scriptValue; } void Evaluator::onItemPropertyChanged(Item *item) { auto data = attachedPointer(m_scriptValueMap.value(item)); if (data) data->valueCache.clear(); } void Evaluator::handleEvaluationError(const Item *item, const QString &name, const QScriptValue &scriptValue) { throwOnEvaluationError(m_scriptEngine, scriptValue, [&item, &name] () { const ValueConstPtr &value = item->property(name); return value ? value->location() : CodeLocation(); }); } void Evaluator::setPathPropertiesBaseDir(const QString &dirPath) { m_scriptClass->setPathPropertiesBaseDir(dirPath); } void Evaluator::clearPathPropertiesBaseDir() { m_scriptClass->clearPathPropertiesBaseDir(); } bool Evaluator::evaluateProperty(QScriptValue *result, const Item *item, const QString &name, bool *propertyWasSet) { *result = property(item, name); handleEvaluationError(item, name, *result); if (propertyWasSet) *propertyWasSet = isNonDefaultValue(item, name); return result->isValid() && !result->isUndefined(); } Evaluator::FileContextScopes Evaluator::fileContextScopes(const FileContextConstPtr &file) { FileContextScopes &result = m_fileContextScopesMap[file]; if (!result.fileScope.isObject()) { if (file->idScope()) result.fileScope = scriptValue(file->idScope()); else result.fileScope = m_scriptEngine->newObject(); result.fileScope.setProperty(StringConstants::filePathGlobalVar(), file->filePath()); result.fileScope.setProperty(StringConstants::pathGlobalVar(), file->dirPath()); } if (!result.importScope.isObject()) { try { result.importScope = m_scriptEngine->newObject(); setupScriptEngineForFile(m_scriptEngine, file, result.importScope, ObserveMode::Enabled); } catch (const ErrorInfo &e) { result.importScope = m_scriptEngine->currentContext()->throwError(e.toString()); } } return result; } void Evaluator::setCachingEnabled(bool enabled) { m_scriptClass->setValueCacheEnabled(enabled); } PropertyDependencies Evaluator::propertyDependencies() const { return m_scriptClass->propertyDependencies(); } void Evaluator::clearPropertyDependencies() { m_scriptClass->clearPropertyDependencies(); } void throwOnEvaluationError(ScriptEngine *engine, const QScriptValue &scriptValue, const std::function &provideFallbackCodeLocation) { if (Q_LIKELY(!engine->hasErrorOrException(scriptValue))) return; QString message; QString filePath; int line = -1; const QScriptValue value = scriptValue.isError() ? scriptValue : engine->uncaughtException(); if (value.isError()) { QScriptValue v = value.property(QStringLiteral("message")); if (v.isString()) message = v.toString(); v = value.property(StringConstants::fileNameProperty()); if (v.isString()) filePath = v.toString(); v = value.property(QStringLiteral("lineNumber")); if (v.isNumber()) line = v.toInt32(); throw ErrorInfo(message, CodeLocation(filePath, line, -1, false)); } else { message = value.toString(); throw ErrorInfo(message, provideFallbackCodeLocation()); } } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/evaluator.h000066400000000000000000000115651347155106100220740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_EVALUATOR_H #define QBS_EVALUATOR_H #include "forward_decls.h" #include "itemobserver.h" #include "qualifiedid.h" #include #include #include namespace qbs { namespace Internal { class EvaluatorScriptClass; class FileTags; class Logger; class PropertyDeclaration; class ScriptEngine; class QBS_AUTOTEST_EXPORT Evaluator : private ItemObserver { friend class SVConverter; public: Evaluator(ScriptEngine *scriptEngine); virtual ~Evaluator(); ScriptEngine *engine() const { return m_scriptEngine; } QScriptValue property(const Item *item, const QString &name); QScriptValue value(const Item *item, const QString &name, bool *propertySet = nullptr); bool boolValue(const Item *item, const QString &name, bool *propertyWasSet = nullptr); int intValue(const Item *item, const QString &name, int defaultValue = 0, bool *propertyWasSet = nullptr); FileTags fileTagsValue(const Item *item, const QString &name, bool *propertySet = nullptr); QString stringValue(const Item *item, const QString &name, const QString &defaultValue = QString(), bool *propertyWasSet = nullptr); QStringList stringListValue(const Item *item, const QString &name, bool *propertyWasSet = nullptr); void convertToPropertyType(const PropertyDeclaration& decl, const CodeLocation &loc, QScriptValue &v); QScriptValue scriptValue(const Item *item); struct FileContextScopes { QScriptValue fileScope; QScriptValue importScope; }; FileContextScopes fileContextScopes(const FileContextConstPtr &file); void setCachingEnabled(bool enabled); PropertyDependencies propertyDependencies() const; void clearPropertyDependencies(); void handleEvaluationError(const Item *item, const QString &name, const QScriptValue &scriptValue); void setPathPropertiesBaseDir(const QString &dirPath); void clearPathPropertiesBaseDir(); bool isNonDefaultValue(const Item *item, const QString &name) const; private: void onItemPropertyChanged(Item *item) override; bool evaluateProperty(QScriptValue *result, const Item *item, const QString &name, bool *propertyWasSet); ScriptEngine *m_scriptEngine; EvaluatorScriptClass *m_scriptClass; mutable QHash m_scriptValueMap; mutable QHash m_fileContextScopesMap; }; void throwOnEvaluationError(ScriptEngine *engine, const QScriptValue &scriptValue, const std::function &provideFallbackCodeLocation); class EvalCacheEnabler { public: EvalCacheEnabler(Evaluator *evaluator) : m_evaluator(evaluator) { m_evaluator->setCachingEnabled(true); } ~EvalCacheEnabler() { m_evaluator->setCachingEnabled(false); } private: Evaluator * const m_evaluator; }; } // namespace Internal } // namespace qbs #endif // QBS_EVALUATOR_H qbs-src-1.13.1/src/lib/corelib/language/evaluatorscriptclass.cpp000066400000000000000000000673401347155106100247040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "evaluatorscriptclass.h" #include "evaluationdata.h" #include "evaluator.h" #include "filecontext.h" #include "item.h" #include "scriptengine.h" #include "propertydeclaration.h" #include "value.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class SVConverter : ValueHandler { EvaluatorScriptClass * const scriptClass; ScriptEngine * const engine; QScriptContext * const scriptContext; const QScriptValue * const object; Value * const valuePtr; const Item * const itemOfProperty; const QScriptString * const propertyName; const EvaluationData * const data; QScriptValue * const result; char pushedScopesCount; public: SVConverter(EvaluatorScriptClass *esc, const QScriptValue *obj, const ValuePtr &v, const Item *_itemOfProperty, const QScriptString *propertyName, const EvaluationData *data, QScriptValue *result) : scriptClass(esc) , engine(static_cast(esc->engine())) , scriptContext(esc->engine()->currentContext()) , object(obj) , valuePtr(v.get()) , itemOfProperty(_itemOfProperty) , propertyName(propertyName) , data(data) , result(result) , pushedScopesCount(0) { } void start() { valuePtr->apply(this); } private: friend class AutoScopePopper; class AutoScopePopper { public: AutoScopePopper(SVConverter *converter) : m_converter(converter) { } ~AutoScopePopper() { m_converter->popScopes(); } private: SVConverter *m_converter; }; void setupConvenienceProperty(const QString &conveniencePropertyName, QScriptValue *extraScope, const QScriptValue &scriptValue) { if (!extraScope->isObject()) *extraScope = engine->newObject(); const PropertyDeclaration::Type type = itemOfProperty->propertyDeclaration(propertyName->toString()).type(); const bool isArray = type == PropertyDeclaration::StringList || type == PropertyDeclaration::PathList || type == PropertyDeclaration::Variant // TODO: Why? || type == PropertyDeclaration::VariantList; QScriptValue valueToSet = scriptValue; if (isArray) { if (!valueToSet.isValid() || valueToSet.isUndefined()) valueToSet = engine->newArray(); } else if (!valueToSet.isValid()) { valueToSet = engine->undefinedValue(); } extraScope->setProperty(conveniencePropertyName, valueToSet); } std::pair createExtraScope(const JSSourceValue *value, Item *outerItem, QScriptValue *outerScriptValue) { std::pair result; auto &extraScope = result.first; result.second = true; if (value->sourceUsesBase()) { QScriptValue baseValue; if (value->baseValue()) { SVConverter converter(scriptClass, object, value->baseValue(), itemOfProperty, propertyName, data, &baseValue); converter.start(); } setupConvenienceProperty(StringConstants::baseVar(), &extraScope, baseValue); } if (value->sourceUsesOuter()) { QScriptValue v; if (outerItem) { v = data->evaluator->property(outerItem, *propertyName); if (engine->hasErrorOrException(v)) { extraScope = engine->lastErrorValue(v); result.second = false; return result; } } else if (outerScriptValue) { v = *outerScriptValue; } if (v.isValid()) setupConvenienceProperty(StringConstants::outerVar(), &extraScope, v); } if (value->sourceUsesOriginal()) { QScriptValue originalValue; if (data->item->propertyDeclaration(propertyName->toString()).isScalar()) { const Item *item = itemOfProperty; if (item->type() == ItemType::Module || item->type() == ItemType::Export) { const QString errorMessage = Tr::tr("The special value 'original' cannot " "be used on the right-hand side of a property declaration."); extraScope = engine->currentContext()->throwError(errorMessage); result.second = false; return result; } // TODO: Provide a dedicated item type for not-yet-instantiated things that // look like module instances in the AST visitor. if (item->type() == ItemType::ModuleInstance && !item->hasProperty(StringConstants::presentProperty())) { const QString errorMessage = Tr::tr("Trying to assign property '%1' " "on something that is not a module.").arg(propertyName->toString()); extraScope = engine->currentContext()->throwError(errorMessage); result.second = false; return result; } while (item->type() == ItemType::ModuleInstance) item = item->prototype(); if (item->type() != ItemType::Module && item->type() != ItemType::Export) { const QString errorMessage = Tr::tr("The special value 'original' can only " "be used with module properties."); extraScope = engine->currentContext()->throwError(errorMessage); result.second = false; return result; } SVConverter converter(scriptClass, object, item->property(*propertyName), item, propertyName, data, &originalValue); converter.start(); } else { originalValue = engine->newArray(0); } setupConvenienceProperty(StringConstants::originalVar(), &extraScope, originalValue); } return result; } void pushScope(const QScriptValue &scope) { if (scope.isObject()) { scriptContext->pushScope(scope); ++pushedScopesCount; } } void pushItemScopes(const Item *item) { const Item *scope = item->scope(); if (scope) { pushItemScopes(scope); pushScope(data->evaluator->scriptValue(scope)); } } void popScopes() { for (; pushedScopesCount; --pushedScopesCount) scriptContext->popScope(); } void handle(JSSourceValue *value) override { QScriptValue outerScriptValue; for (const JSSourceValue::Alternative &alternative : value->alternatives()) { if (alternative.value->sourceUsesOuter() && !data->item->outerItem() && !outerScriptValue.isValid()) { JSSourceValueEvaluationResult sver = evaluateJSSourceValue(value, nullptr); if (sver.hasError) { *result = sver.scriptValue; return; } outerScriptValue = sver.scriptValue; } JSSourceValueEvaluationResult sver = evaluateJSSourceValue(alternative.value.get(), data->item->outerItem(), &alternative, value, &outerScriptValue); if (!sver.tryNextAlternative || sver.hasError) { *result = sver.scriptValue; return; } } *result = evaluateJSSourceValue(value, data->item->outerItem()).scriptValue; } struct JSSourceValueEvaluationResult { QScriptValue scriptValue; bool tryNextAlternative = true; bool hasError = false; }; void injectErrorLocation(QScriptValue &sv, const CodeLocation &loc) { if (sv.isError() && !engine->lastErrorLocation(sv).isValid()) sv = engine->currentContext()->throwError(engine->lastError(sv, loc).toString()); } JSSourceValueEvaluationResult evaluateJSSourceValue(const JSSourceValue *value, Item *outerItem, const JSSourceValue::Alternative *alternative = nullptr, JSSourceValue *elseCaseValue = nullptr, QScriptValue *outerScriptValue = nullptr) { JSSourceValueEvaluationResult result; QBS_ASSERT(!alternative || value == alternative->value.get(), return result); AutoScopePopper autoScopePopper(this); auto maybeExtraScope = createExtraScope(value, outerItem, outerScriptValue); if (!maybeExtraScope.second) { result.scriptValue = maybeExtraScope.first; result.hasError = true; return result; } const Evaluator::FileContextScopes fileCtxScopes = data->evaluator->fileContextScopes(value->file()); if (fileCtxScopes.importScope.isError()) { result.scriptValue = fileCtxScopes.importScope; result.hasError = true; return result; } pushScope(fileCtxScopes.fileScope); pushItemScopes(data->item); if (itemOfProperty->type() != ItemType::ModuleInstance) { // Own properties of module instances must not have the instance itself in the scope. pushScope(*object); } if (value->definingItem()) pushItemScopes(value->definingItem()); pushScope(maybeExtraScope.first); pushScope(fileCtxScopes.importScope); if (alternative) { QScriptValue sv = engine->evaluate(alternative->condition.value); if (engine->hasErrorOrException(sv)) { result.scriptValue = sv; result.hasError = true; injectErrorLocation(result.scriptValue, alternative->condition.location); return result; } if (sv.toBool()) { // The condition is true. Continue evaluating the value. result.tryNextAlternative = false; } else { // The condition is false. Try the next alternative or the else value. result.tryNextAlternative = true; return result; } sv = engine->evaluate(alternative->overrideListProperties.value); if (engine->hasErrorOrException(sv)) { result.scriptValue = sv; result.hasError = true; injectErrorLocation(result.scriptValue, alternative->overrideListProperties.location); return result; } if (sv.toBool()) elseCaseValue->setIsExclusiveListValue(); } result.scriptValue = engine->evaluate(value->sourceCodeForEvaluation(), value->file()->filePath(), value->line()); return result; } void handle(ItemValue *value) override { *result = data->evaluator->scriptValue(value->item()); if (!result->isValid()) qDebug() << "SVConverter returned invalid script value."; } void handle(VariantValue *variantValue) override { *result = engine->toScriptValue(variantValue->value()); } }; bool debugProperties = false; enum QueryPropertyType { QPTDefault, QPTParentProperty }; EvaluatorScriptClass::EvaluatorScriptClass(ScriptEngine *scriptEngine) : QScriptClass(scriptEngine) , m_valueCacheEnabled(false) { } QScriptClass::QueryFlags EvaluatorScriptClass::queryProperty(const QScriptValue &object, const QScriptString &name, QScriptClass::QueryFlags flags, uint *id) { Q_UNUSED(flags); // We assume that it's safe to save the result of the query in a member of the scriptclass. // It must be cleared in the property method before doing any further lookup. QBS_ASSERT(m_queryResult.isNull(), return {}); if (debugProperties) qDebug() << "[SC] queryProperty " << object.objectId() << " " << name; auto const data = attachedPointer(object); const QString nameString = name.toString(); if (nameString == QStringLiteral("parent")) { *id = QPTParentProperty; m_queryResult.data = data; return QScriptClass::HandlesReadAccess; } *id = QPTDefault; if (!data) { if (debugProperties) qDebug() << "[SC] queryProperty: no data attached"; return {}; } return queryItemProperty(data, nameString); } QScriptClass::QueryFlags EvaluatorScriptClass::queryItemProperty(const EvaluationData *data, const QString &name, bool ignoreParent) { for (const Item *item = data->item; item; item = item->prototype()) { m_queryResult.value = item->ownProperty(name); if (m_queryResult.value) { m_queryResult.data = data; m_queryResult.itemOfProperty = item; return HandlesReadAccess; } } if (!ignoreParent && data->item && data->item->parent()) { if (debugProperties) qDebug() << "[SC] queryProperty: query parent"; EvaluationData parentdata = *data; parentdata.item = data->item->parent(); const QueryFlags qf = queryItemProperty(&parentdata, name, true); if (qf.testFlag(HandlesReadAccess)) { m_queryResult.foundInParent = true; m_queryResult.data = data; return qf; } } if (debugProperties) qDebug() << "[SC] queryProperty: no such property"; return {}; } QString EvaluatorScriptClass::resultToString(const QScriptValue &scriptValue) { return (scriptValue.isObject() ? QStringLiteral("[Object: ") + QString::number(scriptValue.objectId()) + QLatin1Char(']') : scriptValue.toVariant().toString()); } void EvaluatorScriptClass::collectValuesFromNextChain(const EvaluationData *data, QScriptValue *result, const QString &propertyName, const ValuePtr &value) { QScriptValueList lst; Set oldNextChain = m_currentNextChain; for (ValuePtr next = value; next; next = next->next()) m_currentNextChain.insert(next.get()); for (ValuePtr next = value; next; next = next->next()) { QScriptValue v = data->evaluator->property(next->definingItem(), propertyName); const auto se = static_cast(engine()); if (se->hasErrorOrException(v)) { *result = se->lastErrorValue(v); return; } if (v.isUndefined()) continue; lst << v; if (next->type() == Value::JSSourceValueType && std::static_pointer_cast(next)->isExclusiveListValue()) { lst = lst.mid(lst.length() - 2); break; } } m_currentNextChain = oldNextChain; *result = engine()->newArray(); quint32 k = 0; for (const QScriptValue &v : qAsConst(lst)) { QBS_ASSERT(!v.isError(), continue); if (v.isArray()) { const quint32 vlen = v.property(StringConstants::lengthProperty()).toInt32(); for (quint32 j = 0; j < vlen; ++j) result->setProperty(k++, v.property(j)); } else { result->setProperty(k++, v); } } } static QString overriddenSourceDirectory(const Item *item, const QString &defaultValue) { const VariantValuePtr v = item->variantProperty (StringConstants::qbsSourceDirPropertyInternal()); return v ? v->value().toString() : defaultValue; } static void makeTypeError(const ErrorInfo &error, QScriptValue &v) { v = v.engine()->currentContext()->throwError(QScriptContext::TypeError, error.toString()); } static void makeTypeError(const PropertyDeclaration &decl, const CodeLocation &location, QScriptValue &v) { const ErrorInfo error(Tr::tr("Value assigned to property '%1' does not have type '%2'.") .arg(decl.name(), decl.typeString()), location); makeTypeError(error, v); } static void convertToPropertyType_impl(const QString &pathPropertiesBaseDir, const Item *item, const PropertyDeclaration& decl, const CodeLocation &location, QScriptValue &v) { if (v.isUndefined() || v.isError()) return; QString srcDir; QString actualBaseDir; if (item && !pathPropertiesBaseDir.isEmpty()) { const VariantValueConstPtr itemSourceDir = item->variantProperty(QStringLiteral("sourceDirectory")); actualBaseDir = itemSourceDir ? itemSourceDir->value().toString() : pathPropertiesBaseDir; } switch (decl.type()) { case PropertyDeclaration::UnknownType: case PropertyDeclaration::Variant: break; case PropertyDeclaration::Boolean: if (!v.isBool()) v = v.toBool(); break; case PropertyDeclaration::Integer: if (!v.isNumber()) makeTypeError(decl, location, v); break; case PropertyDeclaration::Path: { if (!v.isString()) { makeTypeError(decl, location, v); break; } const QString srcDir = item ? overriddenSourceDirectory(item, actualBaseDir) : pathPropertiesBaseDir; if (!srcDir.isEmpty()) v = v.engine()->toScriptValue(QDir::cleanPath( FileInfo::resolvePath(srcDir, v.toString()))); break; } case PropertyDeclaration::String: if (!v.isString()) makeTypeError(decl, location, v); break; case PropertyDeclaration::PathList: srcDir = item ? overriddenSourceDirectory(item, actualBaseDir) : pathPropertiesBaseDir; // Fall-through. case PropertyDeclaration::StringList: { if (!v.isArray()) { QScriptValue x = v.engine()->newArray(1); x.setProperty(0, v); v = x; } const quint32 c = v.property(StringConstants::lengthProperty()).toUInt32(); for (quint32 i = 0; i < c; ++i) { QScriptValue elem = v.property(i); if (elem.isUndefined()) { ErrorInfo error(Tr::tr("Element at index %1 of list property '%2' is undefined. " "String expected.").arg(i).arg(decl.name()), location); makeTypeError(error, v); break; } if (elem.isNull()) { ErrorInfo error(Tr::tr("Element at index %1 of list property '%2' is null. " "String expected.").arg(i).arg(decl.name()), location); makeTypeError(error, v); break; } if (!elem.isString()) { ErrorInfo error(Tr::tr("Element at index %1 of list property '%2' does not have " "string type.").arg(i).arg(decl.name()), location); makeTypeError(error, v); break; } if (srcDir.isEmpty()) continue; elem = v.engine()->toScriptValue( QDir::cleanPath(FileInfo::resolvePath(srcDir, elem.toString()))); v.setProperty(i, elem); } break; } case PropertyDeclaration::VariantList: if (!v.isArray()) { QScriptValue x = v.engine()->newArray(1); x.setProperty(0, v); v = x; } break; } } void EvaluatorScriptClass::convertToPropertyType(const PropertyDeclaration &decl, const CodeLocation &loc, QScriptValue &v) { convertToPropertyType_impl(QString(), nullptr, decl, loc, v); } void EvaluatorScriptClass::convertToPropertyType(const Item *item, const PropertyDeclaration& decl, const Value *value, QScriptValue &v) { if (value->type() == Value::VariantValueType && v.isUndefined() && !decl.isScalar()) { v = v.engine()->newArray(); // QTBUG-51237 return; } convertToPropertyType_impl(m_pathPropertiesBaseDir, item, decl, value->location(), v); } class PropertyStackManager { public: PropertyStackManager(const Item *itemOfProperty, const QScriptString &name, const Value *value, std::stack &requestedProperties, PropertyDependencies &propertyDependencies) : m_requestedProperties(requestedProperties) { if (value->type() == Value::JSSourceValueType && (itemOfProperty->type() == ItemType::ModuleInstance || itemOfProperty->type() == ItemType::Module || itemOfProperty->type() == ItemType::Export)) { const VariantValueConstPtr varValue = itemOfProperty->variantProperty(StringConstants::nameProperty()); if (!varValue) return; m_stackUpdate = true; const QualifiedId fullPropName = QualifiedId::fromString(varValue->value().toString()) << name.toString(); if (!requestedProperties.empty()) propertyDependencies[fullPropName].insert(requestedProperties.top()); m_requestedProperties.push(fullPropName); } } ~PropertyStackManager() { if (m_stackUpdate) m_requestedProperties.pop(); } private: std::stack &m_requestedProperties; bool m_stackUpdate = false; }; QScriptValue EvaluatorScriptClass::property(const QScriptValue &object, const QScriptString &name, uint id) { const bool foundInParent = m_queryResult.foundInParent; const EvaluationData *data = m_queryResult.data; const Item * const itemOfProperty = m_queryResult.itemOfProperty; m_queryResult.foundInParent = false; m_queryResult.data = nullptr; m_queryResult.itemOfProperty = nullptr; QBS_ASSERT(data, {}); const auto qpt = static_cast(id); if (qpt == QPTParentProperty) { return data->item->parent() ? data->evaluator->scriptValue(data->item->parent()) : engine()->undefinedValue(); } ValuePtr value; m_queryResult.value.swap(value); QBS_ASSERT(value, return {}); QBS_ASSERT(m_queryResult.isNull(), return {}); if (debugProperties) qDebug() << "[SC] property " << name; PropertyStackManager propStackmanager(itemOfProperty, name, value.get(), m_requestedProperties, m_propertyDependencies); QScriptValue result; if (m_valueCacheEnabled) { result = data->valueCache.value(name); if (result.isValid()) { if (debugProperties) qDebug() << "[SC] cache hit " << name << ": " << resultToString(result); return result; } } if (value->next() && !m_currentNextChain.contains(value.get())) { collectValuesFromNextChain(data, &result, name.toString(), value); } else { QScriptValue parentObject; if (foundInParent) parentObject = data->evaluator->scriptValue(data->item->parent()); SVConverter converter(this, foundInParent ? &parentObject : &object, value, itemOfProperty, &name, data, &result); converter.start(); const PropertyDeclaration decl = data->item->propertyDeclaration(name.toString()); convertToPropertyType(data->item, decl, value.get(), result); } if (debugProperties) qDebug() << "[SC] cache miss " << name << ": " << resultToString(result); if (m_valueCacheEnabled) data->valueCache.insert(name, result); return result; } class EvaluatorScriptClassPropertyIterator : public QScriptClassPropertyIterator { public: EvaluatorScriptClassPropertyIterator(const QScriptValue &object, EvaluationData *data) : QScriptClassPropertyIterator(object), m_it(data->item->properties()) { } bool hasNext() const override { return m_it.hasNext(); } void next() override { m_it.next(); } bool hasPrevious() const override { return m_it.hasPrevious(); } void previous() override { m_it.previous(); } void toFront() override { m_it.toFront(); } void toBack() override { m_it.toBack(); } QScriptString name() const override { return object().engine()->toStringHandle(m_it.key()); } private: QMapIterator m_it; }; QScriptClassPropertyIterator *EvaluatorScriptClass::newIterator(const QScriptValue &object) { auto const data = attachedPointer(object); return data ? new EvaluatorScriptClassPropertyIterator(object, data) : nullptr; } void EvaluatorScriptClass::setValueCacheEnabled(bool enabled) { m_valueCacheEnabled = enabled; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/evaluatorscriptclass.h000077500000000000000000000114341347155106100243450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_EVALUATORSCRIPTCLASS_H #define QBS_EVALUATORSCRIPTCLASS_H #include "forward_decls.h" #include "qualifiedid.h" #include #include #include QT_BEGIN_NAMESPACE class QScriptContext; QT_END_NAMESPACE namespace qbs { namespace Internal { class EvaluationData; class Item; class PropertyDeclaration; class ScriptEngine; class EvaluatorScriptClass : public QScriptClass { public: EvaluatorScriptClass(ScriptEngine *scriptEngine); QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id) override; QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id) override; QScriptClassPropertyIterator *newIterator(const QScriptValue &object) override; void setValueCacheEnabled(bool enabled); void convertToPropertyType(const PropertyDeclaration& decl, const CodeLocation &loc, QScriptValue &v); PropertyDependencies propertyDependencies() const { return m_propertyDependencies; } void clearPropertyDependencies() { m_propertyDependencies.clear(); } void setPathPropertiesBaseDir(const QString &dirPath) { m_pathPropertiesBaseDir = dirPath; } void clearPathPropertiesBaseDir() { m_pathPropertiesBaseDir.clear(); } private: QueryFlags queryItemProperty(const EvaluationData *data, const QString &name, bool ignoreParent = false); static QString resultToString(const QScriptValue &scriptValue); void collectValuesFromNextChain(const EvaluationData *data, QScriptValue *result, const QString &propertyName, const ValuePtr &value); void convertToPropertyType(const Item *item, const PropertyDeclaration& decl, const Value *value, QScriptValue &v); struct QueryResult { QueryResult() : data(nullptr), itemOfProperty(nullptr) {} bool isNull() const { static const QueryResult pristine; return *this == pristine; } bool operator==(const QueryResult &rhs) const { return foundInParent == rhs.foundInParent && data == rhs.data && itemOfProperty == rhs.itemOfProperty && value == rhs.value; } bool foundInParent = false; const EvaluationData *data; const Item *itemOfProperty; // The item that owns the property. ValuePtr value; }; QueryResult m_queryResult; bool m_valueCacheEnabled; Set m_currentNextChain; PropertyDependencies m_propertyDependencies; std::stack m_requestedProperties; QString m_pathPropertiesBaseDir; }; } // namespace Internal } // namespace qbs #endif // QBS_EVALUATORSCRIPTCLASS_H qbs-src-1.13.1/src/lib/corelib/language/filecontext.cpp000066400000000000000000000043721347155106100227470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "filecontext.h" #include "item.h" namespace qbs { namespace Internal { FileContext::FileContext() : m_idScope(nullptr) { } FileContextPtr FileContext::create() { return FileContextPtr(new FileContext); } void FileContext::ensureIdScope(ItemPool *itemPool) { if (!m_idScope) m_idScope = Item::create(itemPool, ItemType::IdScope); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/filecontext.h000066400000000000000000000050151347155106100224070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_FILECONTEXT_H #define QBS_FILECONTEXT_H #include "filecontextbase.h" #include "forward_decls.h" #include namespace qbs { namespace Internal { class Item; class ItemPool; class FileContext : public FileContextBase { public: static FileContextPtr QBS_AUTOTEST_EXPORT create(); void setContent(const QString &content) { m_content = content; } const QString &content() const { return m_content; } Item *idScope() const { return m_idScope; } void ensureIdScope(ItemPool *itemPool); private: FileContext(); QString m_content; Item *m_idScope; }; } // namespace Internal } // namespace qbs #endif // QBS_FILECONTEXT_H qbs-src-1.13.1/src/lib/corelib/language/filecontextbase.cpp000066400000000000000000000041021347155106100235710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "filecontextbase.h" #include namespace qbs { namespace Internal { QString FileContextBase::dirPath() const { return FileInfo::path(m_filePath); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/filecontextbase.h000066400000000000000000000056601347155106100232500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_FILECONTEXTBASE_H #define QBS_FILECONTEXTBASE_H #include "jsimports.h" namespace qbs { namespace Internal { class FileContextBase { public: void setFilePath(const QString &filePath) { m_filePath = filePath; } QString filePath() const { return m_filePath; } void addJsImport(const JsImport &jsImport) { m_jsImports.push_back(jsImport); } const JsImports &jsImports() const { return m_jsImports; } void addJsExtension(const QString &extension) { m_jsExtensions << extension; } QStringList jsExtensions() const { return m_jsExtensions; } void setSearchPaths(const QStringList &paths) { m_searchPaths = paths; } QStringList searchPaths() const { return m_searchPaths; } QString dirPath() const; protected: FileContextBase() = default; FileContextBase(const FileContextBase &other) = default; FileContextBase(FileContextBase &&other) = default; QString m_filePath; JsImports m_jsImports; QStringList m_jsExtensions; QStringList m_searchPaths; }; } // namespace Internal } // namespace qbs #endif // QBS_FILECONTEXTBASE_H qbs-src-1.13.1/src/lib/corelib/language/filetags.cpp000066400000000000000000000060501347155106100222140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "filetags.h" #include #include namespace qbs { namespace Internal { void FileTag::clear() { Id::operator=(Id()); } void FileTag::store(PersistentPool &pool) const { pool.store(toString()); } void FileTag::load(PersistentPool &pool) { *this = FileTag(pool.load().toUtf8()); } QDebug operator<<(QDebug debug, const FileTag &tag) { QDebugStateSaver saver(debug); return debug.resetFormat().noquote() << tag.toString(); } FileTags FileTags::fromStringList(const QStringList &strings) { FileTags result; for (const QString &str : strings) result += FileTag(str.toUtf8()); return result; } LogWriter operator <<(LogWriter w, const FileTags &tags) { bool firstLoop = true; w.write('('); for (const FileTag &tag : tags) { if (firstLoop) firstLoop = false; else w.write(QStringLiteral(", ")); w.write(tag.toString()); } w.write(')'); return w; } QDebug operator<<(QDebug debug, const FileTags &tags) { QDebugStateSaver saver(debug); return debug.resetFormat().noquote() << tags.toStringList(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/filetags.h000066400000000000000000000057051347155106100216670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_FILETAGS_H #define QBS_FILETAGS_H #include #include #include #include namespace qbs { namespace Internal { class PersistentPool; class FileTag : public Id { public: FileTag() : Id() {} FileTag(const Id &other) : Id(other) {} FileTag(const char *str) : Id(str) {} explicit FileTag(const QByteArray &ba) : Id(ba) {} void clear(); void store(PersistentPool &pool) const; void load(PersistentPool &pool); }; template<> inline bool Set::sortAfterLoadRequired() const { return true; } QDebug operator<<(QDebug debug, const FileTag &tag); class FileTags : public Set { public: FileTags() : Set() {} FileTags(const std::initializer_list &list) : Set(list) {} static FileTags fromStringList(const QStringList &strings); }; LogWriter operator <<(LogWriter w, const FileTags &tags); QDebug operator<<(QDebug debug, const FileTags &tags); } // namespace Internal } // namespace qbs #endif // QBS_FILETAGS_H qbs-src-1.13.1/src/lib/corelib/language/forward_decls.h000066400000000000000000000130041347155106100226760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LANG_FORWARD_DECLS_H #define QBS_LANG_FORWARD_DECLS_H #include namespace qbs { namespace Internal { enum class ObserveMode; class Value; using ValuePtr = std::shared_ptr; using ValueConstPtr = std::shared_ptr; class ItemValue; using ItemValuePtr = std::shared_ptr; using ItemValueConstPtr = std::shared_ptr; class JSSourceValue; using JSSourceValuePtr = std::shared_ptr; using JSSourceValueConstPtr = std::shared_ptr; class VariantValue; using VariantValuePtr = std::shared_ptr; using VariantValueConstPtr = std::shared_ptr; class FileContext; using FileContextPtr = std::shared_ptr; using FileContextConstPtr = std::shared_ptr; class FileContextBase; using FileContextBasePtr = std::shared_ptr; using FileContextBaseConstPtr = std::shared_ptr; class Probe; using ProbePtr = std::shared_ptr; using ProbeConstPtr = std::shared_ptr; class PropertyMapInternal; using PropertyMapPtr = std::shared_ptr; using PropertyMapConstPtr = std::shared_ptr; class FileTagger; using FileTaggerPtr = std::shared_ptr; using FileTaggerConstPtr = std::shared_ptr; class ResolvedProduct; using ResolvedProductPtr = std::shared_ptr; using ResolvedProductConstPtr = std::shared_ptr; class ResolvedProject; using ResolvedProjectPtr = std::shared_ptr; using ResolvedProjectConstPtr = std::shared_ptr; class TopLevelProject; using TopLevelProjectPtr = std::shared_ptr; using TopLevelProjectConstPtr = std::shared_ptr; class ResolvedFileContext; using ResolvedFileContextPtr = std::shared_ptr; using ResolvedFileContextConstPtr = std::shared_ptr; class Rule; using RulePtr = std::shared_ptr; using RuleConstPtr = std::shared_ptr; class ResolvedScanner; using ResolvedScannerPtr = std::shared_ptr; using ResolvedScannerConstPtr = std::shared_ptr; class SourceArtifactInternal; using SourceArtifactPtr = std::shared_ptr; using SourceArtifactConstPtr = std::shared_ptr; class ScriptFunction; using ScriptFunctionPtr = std::shared_ptr; using ScriptFunctionConstPtr = std::shared_ptr; class PrivateScriptFunction; class RuleArtifact; using RuleArtifactPtr = std::shared_ptr; using RuleArtifactConstPtr = std::shared_ptr; class ResolvedModule; using ResolvedModulePtr = std::shared_ptr; using ResolvedModuleConstPtr = std::shared_ptr; class ResolvedGroup; using GroupPtr = std::shared_ptr; using GroupConstPtr = std::shared_ptr; class ArtifactProperties; using ArtifactPropertiesPtr = std::shared_ptr; using ArtifactPropertiesConstPtr = std::shared_ptr; class ExportedItem; using ExportedItemPtr = std::shared_ptr; class ExportedModule; class ExportedModuleDependency; class ExportedProperty; class PersistentPool; } // namespace Internal } // namespace qbs #ifdef QT_CORE_LIB #include namespace qbs { namespace Internal { template inline static uint qHash(const std::shared_ptr &p, uint seed = 0) { return ::qHash(p.get(), seed); } } // namespace Internal } // namespace qbs #endif #endif // QBS_LANG_FORWARD_DECLS_H qbs-src-1.13.1/src/lib/corelib/language/identifiersearch.cpp000066400000000000000000000053201347155106100237250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "identifiersearch.h" #include namespace qbs { namespace Internal { IdentifierSearch::IdentifierSearch() { } void IdentifierSearch::start(QbsQmlJS::AST::Node *node) { for (auto it = m_requests.cbegin(); it != m_requests.cend(); ++it) *it.value() = false; m_numberOfFoundIds = 0; node->accept(this); } void IdentifierSearch::add(const QString &name, bool *found) { m_requests.insert(name, found); } bool IdentifierSearch::preVisit(QbsQmlJS::AST::Node *) { return m_numberOfFoundIds < m_requests.size(); } bool IdentifierSearch::visit(QbsQmlJS::AST::IdentifierExpression *e) { bool *found = m_requests.value(e->name.toString()); if (found && !*found) { *found = true; m_numberOfFoundIds++; } return m_numberOfFoundIds < m_requests.size(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/identifiersearch.h000066400000000000000000000051221347155106100233720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_IDENTIFIERSEARCHVISITOR_H #define QBS_IDENTIFIERSEARCHVISITOR_H #include #include #include #include #include namespace qbs { namespace Internal { class QBS_AUTOTEST_EXPORT IdentifierSearch : private QbsQmlJS::AST::Visitor { public: IdentifierSearch(); void start(QbsQmlJS::AST::Node *node); void add(const QString &name, bool *found); private: bool preVisit(QbsQmlJS::AST::Node *) override; bool visit(QbsQmlJS::AST::IdentifierExpression *e) override; QMap m_requests; int m_numberOfFoundIds; }; } // namespace Internal } // namespace qbs #endif // QBS_IDENTIFIERSEARCHVISITOR_H qbs-src-1.13.1/src/lib/corelib/language/item.cpp000066400000000000000000000316271347155106100213640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "item.h" #include "builtindeclarations.h" #include "deprecationinfo.h" #include "filecontext.h" #include "itemobserver.h" #include "itempool.h" #include "value.h" #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { Item::Item(ItemPool *pool, ItemType type) : m_pool(pool) , m_observer(nullptr) , m_prototype(nullptr) , m_scope(nullptr) , m_outerItem(nullptr) , m_parent(nullptr) , m_type(type) { } Item *Item::create(ItemPool *pool, ItemType type) { return pool->allocateItem(type); } Item *Item::clone() const { Item *dup = create(pool(), type()); dup->m_id = m_id; dup->m_location = m_location; dup->m_prototype = m_prototype; dup->m_scope = m_scope; dup->m_outerItem = m_outerItem; dup->m_parent = m_parent; dup->m_file = m_file; dup->m_propertyDeclarations = m_propertyDeclarations; dup->m_modules = m_modules; dup->m_children.reserve(m_children.size()); for (const Item * const child : qAsConst(m_children)) { Item *clonedChild = child->clone(); clonedChild->m_parent = dup; dup->m_children.push_back(clonedChild); } for (PropertyMap::const_iterator it = m_properties.constBegin(); it != m_properties.constEnd(); ++it) { dup->m_properties.insert(it.key(), it.value()->clone()); } return dup; } QString Item::typeName() const { switch (type()) { case ItemType::IdScope: return QStringLiteral("[IdScope]"); case ItemType::ModuleInstance: return QStringLiteral("[ModuleInstance]"); case ItemType::ModuleParameters: return QStringLiteral("[ModuleParametersInstance]"); case ItemType::ModulePrefix: return QStringLiteral("[ModulePrefix]"); case ItemType::Outer: return QStringLiteral("[Outer]"); case ItemType::Scope: return QStringLiteral("[Scope]"); default: return BuiltinDeclarations::instance().nameForType(type()); } } bool Item::hasProperty(const QString &name) const { const Item *item = this; do { if (item->m_properties.contains(name)) return true; item = item->m_prototype; } while (item); return false; } bool Item::hasOwnProperty(const QString &name) const { return m_properties.contains(name); } ValuePtr Item::property(const QString &name) const { ValuePtr value; const Item *item = this; do { if ((value = item->m_properties.value(name))) break; item = item->m_prototype; } while (item); return value; } ValuePtr Item::ownProperty(const QString &name) const { return m_properties.value(name); } ItemValuePtr Item::itemProperty(const QString &name, const Item *itemTemplate) { return itemProperty(name, itemTemplate, ItemValueConstPtr()); } ItemValuePtr Item::itemProperty(const QString &name, const ItemValueConstPtr &value) { return itemProperty(name, value->item(), value); } ItemValuePtr Item::itemProperty(const QString &name, const Item *itemTemplate, const ItemValueConstPtr &itemValue) { const ValuePtr v = property(name); if (v && v->type() == Value::ItemValueType) return std::static_pointer_cast(v); if (!itemTemplate) return ItemValuePtr(); const bool createdByPropertiesBlock = itemValue && itemValue->createdByPropertiesBlock(); const ItemValuePtr result = ItemValue::create(Item::create(m_pool, itemTemplate->type()), createdByPropertiesBlock); setProperty(name, result); return result; } JSSourceValuePtr Item::sourceProperty(const QString &name) const { ValuePtr v = property(name); if (!v || v->type() != Value::JSSourceValueType) return JSSourceValuePtr(); return std::static_pointer_cast(v); } VariantValuePtr Item::variantProperty(const QString &name) const { ValuePtr v = property(name); if (!v || v->type() != Value::VariantValueType) return VariantValuePtr(); return std::static_pointer_cast(v); } bool Item::isOfTypeOrhasParentOfType(ItemType type) const { const Item *item = this; do { if (item->type() == type) return true; item = item->parent(); } while (item); return false; } PropertyDeclaration Item::propertyDeclaration(const QString &name, bool allowExpired) const { PropertyDeclaration decl = m_propertyDeclarations.value(name); if (decl.isValid()) return decl; if (allowExpired) { decl = m_expiredPropertyDeclarations.value(name); if (decl.isValid()) return decl; } return m_prototype ? m_prototype->propertyDeclaration(name) : decl; } void Item::addModule(const Item::Module &module) { const auto it = std::lower_bound(m_modules.begin(), m_modules.end(), module); QBS_CHECK(it == m_modules.end() || (module.name != it->name && module.item != it->item)); m_modules.insert(it, module); } void Item::setObserver(ItemObserver *observer) const { QBS_ASSERT(!observer || !m_observer, return); // warn if accidentally overwritten m_observer = observer; } void Item::setProperty(const QString &name, const ValuePtr &value) { m_properties.insert(name, value); if (m_observer) m_observer->onItemPropertyChanged(this); } void Item::dump() const { dump(0); } bool Item::isPresentModule() const { // Initial value is "true" as JS source, overwritten one is always QVariant(false). const ValueConstPtr v = property(StringConstants::presentProperty()); return v && v->type() == Value::JSSourceValueType; } void Item::setupForBuiltinType(Logger &logger) { const BuiltinDeclarations &builtins = BuiltinDeclarations::instance(); for (const PropertyDeclaration &pd : builtins.declarationsForType(type()).properties()) { m_propertyDeclarations.insert(pd.name(), pd); const ValuePtr value = m_properties.value(pd.name()); if (!value) { if (pd.isDeprecated()) continue; JSSourceValuePtr sourceValue = JSSourceValue::create(); sourceValue->setIsBuiltinDefaultValue(); sourceValue->setFile(file()); sourceValue->setSourceCode(pd.initialValueSource().isEmpty() ? QStringRef(&StringConstants::undefinedValue()) : QStringRef(&pd.initialValueSource())); m_properties.insert(pd.name(), sourceValue); } else if (pd.isDeprecated()) { const DeprecationInfo &di = pd.deprecationInfo(); if (di.removalVersion() <= LanguageInfo::qbsVersion()) { QString message = Tr::tr("The property '%1' is no longer valid for %2 items. " "It was removed in qbs %3.") .arg(pd.name(), typeName(), di.removalVersion().toString()); ErrorInfo error(message, value->location()); if (!di.additionalUserInfo().isEmpty()) error.append(di.additionalUserInfo()); throw error; } QString warning = Tr::tr("The property '%1' is deprecated and will be removed in " "qbs %2.").arg(pd.name(), di.removalVersion().toString()); ErrorInfo error(warning, value->location()); if (!di.additionalUserInfo().isEmpty()) error.append(di.additionalUserInfo()); logger.printWarning(error); } } } void Item::copyProperty(const QString &propertyName, Item *target) const { target->setProperty(propertyName, property(propertyName)); } static const char *valueType(const Value *v) { switch (v->type()) { case Value::JSSourceValueType: return "JS source"; case Value::ItemValueType: return "Item"; case Value::VariantValueType: return "Variant"; } return ""; // For dumb compilers. } void Item::dump(int indentation) const { const QByteArray indent(indentation, ' '); qDebug("%stype: %s, pointer value: %p", indent.constData(), qPrintable(typeName()), this); if (!m_properties.empty()) qDebug("%sproperties:", indent.constData()); for (auto it = m_properties.constBegin(); it != m_properties.constEnd(); ++it) { const QByteArray nextIndent(indentation + 4, ' '); qDebug("%skey: %s, value type: %s", nextIndent.constData(), qPrintable(it.key()), valueType(it.value().get())); switch (it.value()->type()) { case Value::JSSourceValueType: qDebug("%svalue: %s", nextIndent.constData(), qPrintable(std::static_pointer_cast(it.value())->sourceCodeForEvaluation())); break; case Value::ItemValueType: qDebug("%svalue:", nextIndent.constData()); std::static_pointer_cast(it.value())->item()->dump(indentation + 8); break; case Value::VariantValueType: qDebug("%svalue: %s", nextIndent.constData(), qPrintable(std::static_pointer_cast(it.value())->value().toString())); break; } } if (!m_children.empty()) qDebug("%schildren:", indent.constData()); for (const Item * const child : qAsConst(m_children)) child->dump(indentation + 4); if (prototype()) { qDebug("%sprototype:", indent.constData()); prototype()->dump(indentation + 4); } } void Item::removeProperty(const QString &name) { m_properties.remove(name); } Item *Item::child(ItemType type, bool checkForMultiple) const { Item *child = nullptr; for (Item * const currentChild : children()) { if (currentChild->type() == type) { if (!checkForMultiple) return currentChild; if (child) { ErrorInfo error(Tr::tr("Multiple instances of item '%1' found where at most one " "is allowed.") .arg(BuiltinDeclarations::instance().nameForType(type))); error.append(Tr::tr("First item"), child->location()); error.append(Tr::tr("Second item"), currentChild->location()); throw error; } child = currentChild; } } return child; } void Item::addChild(Item *parent, Item *child) { parent->m_children.push_back(child); child->setParent(parent); } void Item::removeChild(Item *parent, Item *child) { parent->m_children.removeOne(child); child->setParent(nullptr); } void Item::setPropertyDeclaration(const QString &name, const PropertyDeclaration &declaration) { if (declaration.isExpired()) { m_propertyDeclarations.remove(name); m_expiredPropertyDeclarations.insert(name, declaration); } else { m_propertyDeclarations.insert(name, declaration); } } void Item::setPropertyDeclarations(const Item::PropertyDeclarationMap &decls) { m_propertyDeclarations = decls; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/item.h000066400000000000000000000152741347155106100210310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ITEM_H #define QBS_ITEM_H #include "forward_decls.h" #include "itemtype.h" #include "propertydeclaration.h" #include "qualifiedid.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { class ItemObserver; class ItemPool; class Logger; class QBS_AUTOTEST_EXPORT Item : public QbsQmlJS::Managed { friend class ASTPropertiesItemHandler; friend class ItemPool; friend class ItemReaderASTVisitor; Q_DISABLE_COPY(Item) Item(ItemPool *pool, ItemType type); public: struct Module { Module() : item(nullptr), isProduct(false), required(true) {} QualifiedId name; Item *item; bool isProduct; bool required; QVariantMap parameters; VersionRange versionRange; }; using Modules = std::vector; using PropertyDeclarationMap = QMap; using PropertyMap = QMap; static Item *create(ItemPool *pool, ItemType type); Item *clone() const; ItemPool *pool() const { return m_pool; } const QString &id() const { return m_id; } const CodeLocation &location() const { return m_location; } Item *prototype() const { return m_prototype; } Item *scope() const { return m_scope; } Item *outerItem() const { return m_outerItem; } Item *parent() const { return m_parent; } const FileContextPtr &file() const { return m_file; } const QList &children() const { return m_children; } Item *child(ItemType type, bool checkForMultiple = true) const; const PropertyMap &properties() const { return m_properties; } const PropertyDeclarationMap &propertyDeclarations() const { return m_propertyDeclarations; } PropertyDeclaration propertyDeclaration(const QString &name, bool allowExpired = true) const; const Modules &modules() const { return m_modules; } void addModule(const Module &module); void removeModules() { m_modules.clear(); } void setModules(const Modules &modules) { m_modules = modules; } ItemType type() const { return m_type; } void setType(ItemType type) { m_type = type; } QString typeName() const; bool hasProperty(const QString &name) const; bool hasOwnProperty(const QString &name) const; ValuePtr property(const QString &name) const; ValuePtr ownProperty(const QString &name) const; ItemValuePtr itemProperty(const QString &name, const Item *itemTemplate = nullptr); ItemValuePtr itemProperty(const QString &name, const ItemValueConstPtr &value); JSSourceValuePtr sourceProperty(const QString &name) const; VariantValuePtr variantProperty(const QString &name) const; bool isOfTypeOrhasParentOfType(ItemType type) const; void setObserver(ItemObserver *observer) const; void setProperty(const QString &name, const ValuePtr &value); void setProperties(const PropertyMap &props) { m_properties = props; } void removeProperty(const QString &name); void setPropertyDeclaration(const QString &name, const PropertyDeclaration &declaration); void setPropertyDeclarations(const PropertyDeclarationMap &decls); void setLocation(const CodeLocation &location) { m_location = location; } void setPrototype(Item *prototype) { m_prototype = prototype; } void setFile(const FileContextPtr &file) { m_file = file; } void setId(const QString &id) { m_id = id; } void setScope(Item *item) { m_scope = item; } void setOuterItem(Item *item) { m_outerItem = item; } void setChildren(const QList &children) { m_children = children; } void setParent(Item *item) { m_parent = item; } void childrenReserve(int size) { m_children.reserve(size); } static void addChild(Item *parent, Item *child); static void removeChild(Item *parent, Item *child); void dump() const; bool isPresentModule() const; void setupForBuiltinType(Logger &logger); void copyProperty(const QString &propertyName, Item *target) const; private: ItemValuePtr itemProperty(const QString &name, const Item *itemTemplate, const ItemValueConstPtr &itemValue); void dump(int indentation) const; ItemPool *m_pool; mutable ItemObserver *m_observer; QString m_id; CodeLocation m_location; Item *m_prototype; Item *m_scope; Item *m_outerItem; Item *m_parent; QList m_children; FileContextPtr m_file; PropertyMap m_properties; PropertyDeclarationMap m_propertyDeclarations; PropertyDeclarationMap m_expiredPropertyDeclarations; Modules m_modules; ItemType m_type; }; inline bool operator<(const Item::Module &m1, const Item::Module &m2) { return m1.name < m2.name; } } // namespace Internal } // namespace qbs #endif // QBS_ITEM_H qbs-src-1.13.1/src/lib/corelib/language/itemdeclaration.cpp000066400000000000000000000045641347155106100235720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "itemdeclaration.h" namespace qbs { namespace Internal { ItemDeclaration::ItemDeclaration(ItemType type) : m_type(type) { } ItemDeclaration &ItemDeclaration::operator<<(const PropertyDeclaration &decl) { m_properties.push_back(decl); return *this; } bool ItemDeclaration::isChildTypeAllowed(ItemType type) const { if (m_type > ItemType::LastActualItem || type > ItemType::LastActualItem) return true; return m_allowedChildTypes.contains(type); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/itemdeclaration.h000066400000000000000000000061111347155106100232250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ITEMDECLARATION_H #define QBS_ITEMDECLARATION_H #include "deprecationinfo.h" #include "itemtype.h" #include "propertydeclaration.h" #include #include namespace qbs { namespace Internal { class ItemDeclaration { public: ItemDeclaration(ItemType type = ItemType::Unknown); ItemType type() const { return m_type; } using Properties = QList; void setProperties(const Properties &props) { m_properties = props; } Properties properties() const { return m_properties; } void setDeprecationInfo(const DeprecationInfo &di) { m_deprecationInfo = di; } DeprecationInfo deprecationInfo() const { return m_deprecationInfo; } ItemDeclaration &operator<<(const PropertyDeclaration &decl); using TypeNames = Set; void setAllowedChildTypes(const TypeNames &typeNames) { m_allowedChildTypes = typeNames; } const TypeNames &allowedChildTypes() const { return m_allowedChildTypes; } bool isChildTypeAllowed(ItemType type) const; private: ItemType m_type; Properties m_properties; TypeNames m_allowedChildTypes; DeprecationInfo m_deprecationInfo; }; } // namespace Internal } // namespace qbs #endif // QBS_ITEMDECLARATION_H qbs-src-1.13.1/src/lib/corelib/language/itemobserver.h000066400000000000000000000041551347155106100225750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ITEMOBSERVER_H #define QBS_ITEMOBSERVER_H namespace qbs { namespace Internal { class Item; class ItemObserver { public: virtual void onItemPropertyChanged(Item *item) = 0; }; } // namespace Internal } // namespace qbs #endif // QBS_ITEMOBSERVER_H qbs-src-1.13.1/src/lib/corelib/language/itempool.cpp000066400000000000000000000044331347155106100222510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "itempool.h" #include "item.h" namespace qbs { namespace Internal { ItemPool::ItemPool() { } ItemPool::~ItemPool() { for (ItemVector::const_iterator it = m_items.cbegin(); it != m_items.cend(); ++it) (*it)->~Item(); } Item *ItemPool::allocateItem(const ItemType &type) { const auto item = new (&m_pool) Item(this, type); m_items.push_back(item); return item; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/itempool.h000066400000000000000000000046041347155106100217160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ITEMPOOL_H #define QBS_ITEMPOOL_H #include #include #include namespace qbs { namespace Internal { class Item; enum class ItemType; class QBS_AUTOTEST_EXPORT ItemPool { Q_DISABLE_COPY(ItemPool) public: ItemPool(); ~ItemPool(); Item *allocateItem(const ItemType &type); private: QbsQmlJS::MemoryPool m_pool; using ItemVector = QList; ItemVector m_items; }; } // namespace Internal } // namespace qbs #endif // QBS_ITEMPOOL_H qbs-src-1.13.1/src/lib/corelib/language/itemreader.cpp000066400000000000000000000101401347155106100225320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "itemreader.h" #include "itemreadervisitorstate.h" #include #include #include namespace qbs { namespace Internal { static void makePathsCanonical(QStringList &paths) { auto it = std::remove_if(paths.begin(), paths.end(), [](QString &p) { p = QFileInfo(p).canonicalFilePath(); return p.isEmpty(); }); auto e = paths.end(); if (it != e) paths.erase(it, e); } ItemReader::ItemReader(Logger &logger) : m_visitorState(new ItemReaderVisitorState(logger)) { } ItemReader::~ItemReader() { delete m_visitorState; } void ItemReader::setSearchPaths(const QStringList &searchPaths) { m_searchPaths = searchPaths; makePathsCanonical(m_searchPaths); m_allSearchPaths.clear(); } void ItemReader::pushExtraSearchPaths(const QStringList &extraSearchPaths) { m_extraSearchPaths.push_back(extraSearchPaths); makePathsCanonical(m_extraSearchPaths.back()); m_allSearchPaths.clear(); } void ItemReader::popExtraSearchPaths() { m_extraSearchPaths.pop_back(); m_allSearchPaths.clear(); } std::vector ItemReader::extraSearchPathsStack() const { return m_extraSearchPaths; } void ItemReader::setExtraSearchPathsStack(const std::vector &s) { m_extraSearchPaths = s; m_allSearchPaths.clear(); } void ItemReader::clearExtraSearchPathsStack() { m_extraSearchPaths.clear(); m_allSearchPaths.clear(); } const QStringList &ItemReader::allSearchPaths() const { if (m_allSearchPaths.empty()) { std::for_each(m_extraSearchPaths.crbegin(), m_extraSearchPaths.crend(), [this] (const QStringList &paths) { m_allSearchPaths += paths; }); m_allSearchPaths += m_searchPaths; m_allSearchPaths.removeDuplicates(); } return m_allSearchPaths; } Item *ItemReader::readFile(const QString &filePath) { AccumulatingTimer readFileTimer(m_elapsedTime != -1 ? &m_elapsedTime : nullptr); return m_visitorState->readFile(filePath, allSearchPaths(), m_pool); } Set ItemReader::filesRead() const { return m_visitorState->filesRead(); } void ItemReader::setEnableTiming(bool on) { m_elapsedTime = on ? 0 : -1; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/itemreader.h000066400000000000000000000065621347155106100222140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ITEMREADER_H #define QBS_ITEMREADER_H #include "forward_decls.h" #include #include #include namespace qbs { namespace Internal { class Item; class ItemPool; class ItemReaderVisitorState; /* * Reads a qbs file and creates a tree of Item objects. * * In this stage the following steps are performed: * - The QML/JS parser creates the AST. * - The AST is converted to a tree of Item objects. * * This class is also responsible for the QMLish inheritance semantics. */ class ItemReader { public: ItemReader(Logger &logger); ~ItemReader(); void setPool(ItemPool *pool) { m_pool = pool; } void setSearchPaths(const QStringList &searchPaths); void pushExtraSearchPaths(const QStringList &extraSearchPaths); void popExtraSearchPaths(); std::vector extraSearchPathsStack() const; void setExtraSearchPathsStack(const std::vector &s); void clearExtraSearchPathsStack(); const QStringList &allSearchPaths() const; Item *readFile(const QString &filePath); Set filesRead() const; void setEnableTiming(bool on); qint64 elapsedTime() const { return m_elapsedTime; } private: ItemPool *m_pool = nullptr; QStringList m_searchPaths; std::vector m_extraSearchPaths; mutable QStringList m_allSearchPaths; ItemReaderVisitorState * const m_visitorState; qint64 m_elapsedTime = -1; }; } // namespace Internal } // namespace qbs #endif // QBS_ITEMREADER_H qbs-src-1.13.1/src/lib/corelib/language/itemreaderastvisitor.cpp000066400000000000000000000405121347155106100246700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "itemreaderastvisitor.h" #include "astimportshandler.h" #include "astpropertiesitemhandler.h" #include "asttools.h" #include "builtindeclarations.h" #include "filecontext.h" #include "identifiersearch.h" #include "item.h" #include "itemreadervisitorstate.h" #include "value.h" #include #include #include #include #include #include #include #include #include #include using namespace QbsQmlJS; namespace qbs { namespace Internal { ItemReaderASTVisitor::ItemReaderASTVisitor(ItemReaderVisitorState &visitorState, const FileContextPtr &file, ItemPool *itemPool, Logger &logger) : m_visitorState(visitorState) , m_file(file) , m_itemPool(itemPool) , m_logger(logger) { } bool ItemReaderASTVisitor::visit(AST::UiProgram *uiProgram) { ASTImportsHandler importsHandler(m_visitorState, m_logger, m_file); importsHandler.handleImports(uiProgram->imports); m_typeNameToFile = importsHandler.typeNameFileMap(); return true; } static ItemValuePtr findItemProperty(const Item *container, const Item *item) { ItemValuePtr itemValue; const auto &srcprops = container->properties(); auto it = std::find_if(srcprops.begin(), srcprops.end(), [item] (const ValuePtr &v) { return v->type() == Value::ItemValueType && std::static_pointer_cast(v)->item() == item; }); if (it != srcprops.end()) itemValue = std::static_pointer_cast(it.value()); return itemValue; } bool ItemReaderASTVisitor::visit(AST::UiObjectDefinition *ast) { const QString typeName = ast->qualifiedTypeNameId->name.toString(); const CodeLocation itemLocation = toCodeLocation(ast->qualifiedTypeNameId->identifierToken); const Item *baseItem = nullptr; Item *mostDerivingItem = nullptr; Item *item = Item::create(m_itemPool, ItemType::Unknown); item->setFile(m_file); item->setLocation(itemLocation); // Inheritance resolving, part 1: Find out our actual type name (needed for setting // up children and alternatives). const QStringList fullTypeName = toStringList(ast->qualifiedTypeNameId); const QString baseTypeFileName = m_typeNameToFile.value(fullTypeName); ItemType itemType; if (!baseTypeFileName.isEmpty()) { const bool isMostDerivingItem = (m_visitorState.mostDerivingItem() == nullptr); if (isMostDerivingItem) m_visitorState.setMostDerivingItem(item); mostDerivingItem = m_visitorState.mostDerivingItem(); baseItem = m_visitorState.readFile(baseTypeFileName, m_file->searchPaths(), m_itemPool); if (isMostDerivingItem) m_visitorState.setMostDerivingItem(nullptr); QBS_CHECK(baseItem->type() <= ItemType::LastActualItem); itemType = baseItem->type(); } else { if (fullTypeName.size() > 1) { throw ErrorInfo(Tr::tr("Invalid item '%1'. Did you mean to set a module property?") .arg(fullTypeName.join(QLatin1Char('.'))), itemLocation); } itemType = BuiltinDeclarations::instance().typeForName(typeName, itemLocation); checkDeprecationStatus(itemType, typeName, itemLocation); if (itemType == ItemType::Properties && m_item && m_item->type() == ItemType::SubProject) itemType = ItemType::PropertiesInSubProject; } item->m_type = itemType; if (m_item) Item::addChild(m_item, item); // Add this item to the children of the parent item. else m_item = item; // This is the root item. if (ast->initializer) { Item *mdi = m_visitorState.mostDerivingItem(); m_visitorState.setMostDerivingItem(nullptr); qSwap(m_item, item); const ItemType oldInstanceItemType = m_instanceItemType; if (itemType == ItemType::Parameters || itemType == ItemType::Depends) m_instanceItemType = ItemType::ModuleParameters; ast->initializer->accept(this); m_instanceItemType = oldInstanceItemType; qSwap(m_item, item); m_visitorState.setMostDerivingItem(mdi); } ASTPropertiesItemHandler(item).handlePropertiesItems(); // Inheritance resolving, part 2 (depends on alternatives having been set up). if (baseItem) { inheritItem(item, baseItem); if (baseItem->file()->idScope()) { // Make ids from the derived file visible in the base file. // ### Do we want to turn off this feature? It's QMLish but kind of strange. item->file()->ensureIdScope(m_itemPool); baseItem->file()->idScope()->setPrototype(item->file()->idScope()); // Replace the base item with the most deriving item. ItemValuePtr baseItemIdValue = findItemProperty(baseItem->file()->idScope(), baseItem); if (baseItemIdValue) baseItemIdValue->setItem(mostDerivingItem); } } else { // Only the item at the top of the inheritance chain is a built-in item. // We cannot do this in "part 1", because then the visitor would complain about duplicate // bindings. item->setupForBuiltinType(m_logger); } return false; } void ItemReaderASTVisitor::checkDuplicateBinding(Item *item, const QStringList &bindingName, const AST::SourceLocation &sourceLocation) { if (Q_UNLIKELY(item->hasOwnProperty(bindingName.last()))) { QString msg = Tr::tr("Duplicate binding for '%1'"); throw ErrorInfo(msg.arg(bindingName.join(QLatin1Char('.'))), toCodeLocation(sourceLocation)); } } bool ItemReaderASTVisitor::visit(AST::UiPublicMember *ast) { PropertyDeclaration p; if (Q_UNLIKELY(ast->name.isEmpty())) throw ErrorInfo(Tr::tr("public member without name")); if (Q_UNLIKELY(ast->memberType.isEmpty())) throw ErrorInfo(Tr::tr("public member without type")); if (Q_UNLIKELY(ast->type == AST::UiPublicMember::Signal)) throw ErrorInfo(Tr::tr("public member with signal type not supported")); p.setName(ast->name.toString()); p.setType(PropertyDeclaration::propertyTypeFromString(ast->memberType.toString())); if (p.type() == PropertyDeclaration::UnknownType) { throw ErrorInfo(Tr::tr("Unknown type '%1' in property declaration.") .arg(ast->memberType.toString()), toCodeLocation(ast->typeToken)); } if (Q_UNLIKELY(!ast->typeModifier.isEmpty())) { throw ErrorInfo(Tr::tr("public member with type modifier '%1' not supported").arg( ast->typeModifier.toString())); } if (ast->isReadonlyMember) p.setFlags(PropertyDeclaration::ReadOnlyFlag); m_item->m_propertyDeclarations.insert(p.name(), p); const JSSourceValuePtr value = JSSourceValue::create(); value->setFile(m_file); if (ast->statement) { handleBindingRhs(ast->statement, value); const QStringList bindingName(p.name()); checkDuplicateBinding(m_item, bindingName, ast->colonToken); } m_item->setProperty(p.name(), value); return false; } bool ItemReaderASTVisitor::visit(AST::UiScriptBinding *ast) { QBS_CHECK(ast->qualifiedId); QBS_CHECK(!ast->qualifiedId->name.isEmpty()); const QStringList bindingName = toStringList(ast->qualifiedId); if (bindingName.length() == 1 && bindingName.front() == QStringLiteral("id")) { const auto * const expStmt = AST::cast(ast->statement); if (Q_UNLIKELY(!expStmt)) throw ErrorInfo(Tr::tr("id: must be followed by identifier")); const auto * const idExp = AST::cast(expStmt->expression); if (Q_UNLIKELY(!idExp || idExp->name.isEmpty())) throw ErrorInfo(Tr::tr("id: must be followed by identifier")); m_item->m_id = idExp->name.toString(); m_file->ensureIdScope(m_itemPool); ItemValueConstPtr existingId = m_file->idScope()->itemProperty(m_item->id()); if (existingId) { ErrorInfo e(Tr::tr("The id '%1' is not unique.").arg(m_item->id())); e.append(Tr::tr("First occurrence is here."), existingId->item()->location()); e.append(Tr::tr("Next occurrence is here."), m_item->location()); throw e; } m_file->idScope()->setProperty(m_item->id(), ItemValue::create(m_item)); return false; } const JSSourceValuePtr value = JSSourceValue::create(); handleBindingRhs(ast->statement, value); Item * const targetItem = targetItemForBinding(bindingName, value); checkDuplicateBinding(targetItem, bindingName, ast->qualifiedId->identifierToken); targetItem->setProperty(bindingName.last(), value); return false; } bool ItemReaderASTVisitor::handleBindingRhs(AST::Statement *statement, const JSSourceValuePtr &value) { QBS_CHECK(statement); QBS_CHECK(value); if (AST::cast(statement)) value->m_flags |= JSSourceValue::HasFunctionForm; value->setFile(m_file); value->setSourceCode(textRefOf(m_file->content(), statement)); value->setLocation(statement->firstSourceLocation().startLine, statement->firstSourceLocation().startColumn); bool usesBase, usesOuter, usesOriginal; IdentifierSearch idsearch; idsearch.add(StringConstants::baseVar(), &usesBase); idsearch.add(StringConstants::outerVar(), &usesOuter); idsearch.add(StringConstants::originalVar(), &usesOriginal); idsearch.start(statement); if (usesBase) value->m_flags |= JSSourceValue::SourceUsesBase; if (usesOuter) value->m_flags |= JSSourceValue::SourceUsesOuter; if (usesOriginal) value->m_flags |= JSSourceValue::SourceUsesOriginal; return false; } CodeLocation ItemReaderASTVisitor::toCodeLocation(const AST::SourceLocation &location) const { return CodeLocation(m_file->filePath(), location.startLine, location.startColumn); } Item *ItemReaderASTVisitor::targetItemForBinding(const QStringList &bindingName, const JSSourceValueConstPtr &value) { Item *targetItem = m_item; const int c = bindingName.size() - 1; for (int i = 0; i < c; ++i) { ValuePtr v = targetItem->ownProperty(bindingName.at(i)); if (!v) { const ItemType itemType = i < c - 1 ? ItemType::ModulePrefix : m_instanceItemType; Item *newItem = Item::create(m_itemPool, itemType); newItem->setLocation(value->location()); v = ItemValue::create(newItem); targetItem->setProperty(bindingName.at(i), v); } if (Q_UNLIKELY(v->type() != Value::ItemValueType)) { QString msg = Tr::tr("Binding to non-item property."); throw ErrorInfo(msg, value->location()); } targetItem = std::static_pointer_cast(v)->item(); } return targetItem; } void ItemReaderASTVisitor::inheritItem(Item *dst, const Item *src) { int insertPos = 0; for (Item *child : qAsConst(src->m_children)) { dst->m_children.insert(insertPos++, child); child->m_parent = dst; } for (const PropertyDeclaration &pd : src->propertyDeclarations()) { if (pd.flags().testFlag(PropertyDeclaration::ReadOnlyFlag) && dst->hasOwnProperty(pd.name())) { throw ErrorInfo(Tr::tr("Cannot set read-only property '%1'.").arg(pd.name()), dst->property(pd.name())->location()); } dst->setPropertyDeclaration(pd.name(), pd); } for (auto it = src->properties().constBegin(); it != src->properties().constEnd(); ++it) { ValuePtr &v = dst->m_properties[it.key()]; if (!v) { v = it.value(); continue; } if (v->type() == Value::ItemValueType && it.value()->type() != Value::ItemValueType) throw ErrorInfo(Tr::tr("Binding to non-item property."), v->location()); if (v->type() != it.value()->type()) continue; switch (v->type()) { case Value::JSSourceValueType: { JSSourceValuePtr sv = std::static_pointer_cast(v); QBS_CHECK(!sv->baseValue()); const JSSourceValuePtr baseValue = std::static_pointer_cast(it.value()); sv->setBaseValue(baseValue); for (const JSSourceValue::Alternative &alt : sv->m_alternatives) alt.value->setBaseValue(baseValue); break; } case Value::ItemValueType: inheritItem(std::static_pointer_cast(v)->item(), std::static_pointer_cast(it.value())->item()); break; default: QBS_CHECK(!"unexpected value type"); } } } void ItemReaderASTVisitor::checkDeprecationStatus(ItemType itemType, const QString &itemName, const CodeLocation &itemLocation) { const ItemDeclaration itemDecl = BuiltinDeclarations::instance().declarationsForType(itemType); const DeprecationInfo &di = itemDecl.deprecationInfo(); if (!di.isValid()) return; if (di.removalVersion() <= LanguageInfo::qbsVersion()) { QString message = Tr::tr("The item '%1' cannot be used anymore. " "It was removed in qbs %2.") .arg(itemName, di.removalVersion().toString()); ErrorInfo error(message, itemLocation); if (!di.additionalUserInfo().isEmpty()) error.append(di.additionalUserInfo()); throw error; } QString warning = Tr::tr("The item '%1' is deprecated and will be removed in " "qbs %2.").arg(itemName, di.removalVersion().toString()); ErrorInfo error(warning, itemLocation); if (!di.additionalUserInfo().isEmpty()) error.append(di.additionalUserInfo()); m_logger.printWarning(error); } void ItemReaderASTVisitor::doCheckItemTypes(const Item *item) { const ItemDeclaration decl = BuiltinDeclarations::instance().declarationsForType(item->type()); for (const Item * const child : item->children()) { if (!decl.isChildTypeAllowed(child->type())) { throw ErrorInfo(Tr::tr("Items of type '%1' cannot contain items of type '%2'.") .arg(item->typeName(), child->typeName()), child->location()); } doCheckItemTypes(child); } } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/itemreaderastvisitor.h000066400000000000000000000074261347155106100243440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ITEMREADERASTVISITOR_H #define QBS_ITEMREADERASTVISITOR_H #include "forward_decls.h" #include "itemtype.h" #include #include #include #include namespace qbs { class CodeLocation; namespace Internal { class Item; class ItemPool; class ItemReaderVisitorState; class ItemReaderASTVisitor : public QbsQmlJS::AST::Visitor { public: ItemReaderASTVisitor(ItemReaderVisitorState &visitorState, const FileContextPtr &file, ItemPool *itemPool, Logger &logger); void checkItemTypes() { doCheckItemTypes(rootItem()); } Item *rootItem() const { return m_item; } private: bool visit(QbsQmlJS::AST::UiProgram *uiProgram) override; bool visit(QbsQmlJS::AST::UiObjectDefinition *ast) override; bool visit(QbsQmlJS::AST::UiPublicMember *ast) override; bool visit(QbsQmlJS::AST::UiScriptBinding *ast) override; bool handleBindingRhs(QbsQmlJS::AST::Statement *statement, const JSSourceValuePtr &value); CodeLocation toCodeLocation(const QbsQmlJS::AST::SourceLocation &location) const; void checkDuplicateBinding(Item *item, const QStringList &bindingName, const QbsQmlJS::AST::SourceLocation &sourceLocation); Item *targetItemForBinding(const QStringList &binding, const JSSourceValueConstPtr &value); static void inheritItem(Item *dst, const Item *src); void checkDeprecationStatus(ItemType itemType, const QString &itemName, const CodeLocation &itemLocation); void doCheckItemTypes(const Item *item); ItemReaderVisitorState &m_visitorState; const FileContextPtr m_file; ItemPool * const m_itemPool; Logger &m_logger; QHash m_typeNameToFile; Item *m_item = nullptr; ItemType m_instanceItemType = ItemType::ModuleInstance; }; } // namespace Internal } // namespace qbs #endif // QBS_ITEMREADERASTVISITOR_H qbs-src-1.13.1/src/lib/corelib/language/itemreadervisitorstate.cpp000066400000000000000000000144041347155106100252220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "itemreadervisitorstate.h" #include "asttools.h" #include "filecontext.h" #include "itemreaderastvisitor.h" #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class ASTCacheValueData : public QSharedData { Q_DISABLE_COPY(ASTCacheValueData) public: ASTCacheValueData() : ast(nullptr) , processing(false) { } QString code; QbsQmlJS::Engine engine; QbsQmlJS::AST::UiProgram *ast; bool processing; }; class ASTCacheValue { public: ASTCacheValue() : d(new ASTCacheValueData) { } ASTCacheValue(const ASTCacheValue &other) : d(other.d) { } void setProcessingFlag(bool b) { d->processing = b; } bool isProcessing() const { return d->processing; } void setCode(const QString &code) { d->code = code; } QString code() const { return d->code; } QbsQmlJS::Engine *engine() const { return &d->engine; } void setAst(QbsQmlJS::AST::UiProgram *ast) { d->ast = ast; } QbsQmlJS::AST::UiProgram *ast() const { return d->ast; } bool isValid() const { return d->ast; } private: QExplicitlySharedDataPointer d; }; class ItemReaderVisitorState::ASTCache : public QHash {}; ItemReaderVisitorState::ItemReaderVisitorState(Logger &logger) : m_logger(logger) , m_astCache(new ASTCache) { } ItemReaderVisitorState::~ItemReaderVisitorState() { delete m_astCache; } Item *ItemReaderVisitorState::readFile(const QString &filePath, const QStringList &searchPaths, ItemPool *itemPool) { ASTCacheValue &cacheValue = (*m_astCache)[filePath]; if (cacheValue.isValid()) { if (Q_UNLIKELY(cacheValue.isProcessing())) throw ErrorInfo(Tr::tr("Loop detected when importing '%1'.").arg(filePath)); } else { QFile file(filePath); if (Q_UNLIKELY(!file.open(QFile::ReadOnly))) throw ErrorInfo(Tr::tr("Cannot open '%1'.").arg(filePath)); m_filesRead.insert(filePath); QTextStream stream(&file); stream.setCodec("UTF-8"); const QString &code = stream.readAll(); QbsQmlJS::Lexer lexer(cacheValue.engine()); lexer.setCode(code, 1); QbsQmlJS::Parser parser(cacheValue.engine()); file.close(); if (!parser.parse()) { const QList &parserMessages = parser.diagnosticMessages(); if (Q_UNLIKELY(!parserMessages.empty())) { ErrorInfo err; for (const QbsQmlJS::DiagnosticMessage &msg : parserMessages) err.append(msg.message, toCodeLocation(filePath, msg.loc)); throw err; } } cacheValue.setCode(code); cacheValue.setAst(parser.ast()); } const FileContextPtr file = FileContext::create(); file->setFilePath(QFileInfo(filePath).absoluteFilePath()); file->setContent(cacheValue.code()); file->setSearchPaths(searchPaths); ItemReaderASTVisitor astVisitor(*this, file, itemPool, m_logger); { class ProcessingFlagManager { public: ProcessingFlagManager(ASTCacheValue &v) : m_cacheValue(v) { v.setProcessingFlag(true); } ~ProcessingFlagManager() { m_cacheValue.setProcessingFlag(false); } private: ASTCacheValue &m_cacheValue; } processingFlagManager(cacheValue); cacheValue.ast()->accept(&astVisitor); } astVisitor.checkItemTypes(); return astVisitor.rootItem(); } void ItemReaderVisitorState::cacheDirectoryEntries(const QString &dirPath, const QStringList &entries) { m_directoryEntries.insert(dirPath, entries); } bool ItemReaderVisitorState::findDirectoryEntries(const QString &dirPath, QStringList *entries) const { const auto it = m_directoryEntries.constFind(dirPath); if (it == m_directoryEntries.constEnd()) return false; *entries = it.value(); return true; } Item *ItemReaderVisitorState::mostDerivingItem() const { return m_mostDerivingItem; } void ItemReaderVisitorState::setMostDerivingItem(Item *item) { m_mostDerivingItem = item; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/itemreadervisitorstate.h000066400000000000000000000055421347155106100246720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ITEMREADERVISITORSTATE_H #define QBS_ITEMREADERVISITORSTATE_H #include #include #include namespace qbs { namespace Internal { class Item; class ItemPool; class ItemReaderVisitorState { public: ItemReaderVisitorState(Logger &logger); ~ItemReaderVisitorState(); Set filesRead() const { return m_filesRead; } Item *readFile(const QString &filePath, const QStringList &searchPaths, ItemPool *itemPool); void cacheDirectoryEntries(const QString &dirPath, const QStringList &entries); bool findDirectoryEntries(const QString &dirPath, QStringList *entries) const; Item *mostDerivingItem() const; void setMostDerivingItem(Item *item); private: Logger &m_logger; Set m_filesRead; QHash m_directoryEntries; Item *m_mostDerivingItem = nullptr; class ASTCache; ASTCache * const m_astCache; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/language/itemtype.h000066400000000000000000000053161347155106100217270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ITEMTYPE_H #define QBS_ITEMTYPE_H #include namespace qbs { namespace Internal { enum class ItemType { // Actual user-visible items. FirstActualItem, Artifact = FirstActualItem, Depends, Export, FileTagger, Group, JobLimit, Module, ModuleProvider, Parameter, Parameters, Probe, Product, Profile, Project, Properties, PropertiesInSubProject, PropertyOptions, Rule, Scanner, SubProject, Transformer, LastActualItem = Transformer, // Internal items created mainly by the module loader. IdScope, ModuleInstance, ModuleParameters, ModulePrefix, Outer, Scope, Unknown }; inline uint qHash(ItemType t) { return QT_PREPEND_NAMESPACE(qHash)(uint(t)); } } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/language/jsimports.h000066400000000000000000000057521347155106100221250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_JSIMPORTS_H #define QBS_JSIMPORTS_H #include #include #include #include #include namespace qbs { namespace Internal { /** * Represents JavaScript import of the form * import 'fileOrDirectory' as scopeName * * There can be several filenames per scope * if we import a whole directory. */ class JsImport { public: QString scopeName; QStringList filePaths; CodeLocation location; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(scopeName, filePaths, location); } }; inline uint qHash(const JsImport &jsi) { return qHash(jsi.scopeName); } inline bool operator<(const JsImport &lhs, const JsImport &rhs) { return lhs.scopeName < rhs.scopeName; } inline bool operator==(const JsImport &jsi1, const JsImport &jsi2) { return jsi1.scopeName == jsi2.scopeName && jsi1.filePaths.toSet() == jsi2.filePaths.toSet(); } using JsImports = std::vector; } // namespace Internal } // namespace qbs #endif // QBS_JSIMPORTS_H qbs-src-1.13.1/src/lib/corelib/language/language.cpp000066400000000000000000000750771347155106100222200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "language.h" #include "artifactproperties.h" #include "builtindeclarations.h" #include "propertymapinternal.h" #include "scriptengine.h" #include #include #include #include #include // TODO: Move to language? #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { template bool equals(const T *v1, const T *v2) { if (v1 == v2) return true; if (!v1 != !v2) return false; return *v1 == *v2; } /*! * \class FileTagger * \brief The \c FileTagger class maps 1:1 to the respective item in a qbs source file. */ FileTagger::FileTagger(const QStringList &patterns, const FileTags &fileTags, int priority) : m_fileTags(fileTags), m_priority(priority) { setPatterns(patterns); } void FileTagger::setPatterns(const QStringList &patterns) { m_patterns.clear(); for (const QString &pattern : patterns) { QBS_CHECK(!pattern.isEmpty()); m_patterns << QRegExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard); } } bool Probe::needsReconfigure(const FileTime &referenceTime) const { const auto criterion = [referenceTime](const QString &filePath) { FileInfo fi(filePath); return !fi.exists() || fi.lastModified() > referenceTime; }; return std::any_of(m_importedFilesUsed.cbegin(), m_importedFilesUsed.cend(), criterion); } /*! * \class SourceArtifact * \brief The \c SourceArtifact class represents a source file. * Everything except the file path is inherited from the surrounding \c ResolvedGroup. * (TODO: Not quite true. Artifacts in transformers will be generated by the transformer, but are * still represented as source artifacts. We may or may not want to change this; if we do, * SourceArtifact could simply have a back pointer to the group in addition to the file path.) * \sa ResolvedGroup */ /*! * \class ResolvedGroup * \brief The \c ResolvedGroup class corresponds to the Group item in a qbs source file. */ /*! * \variable ResolvedGroup::files * \brief The files listed in the group item's "files" binding. * Note that these do not include expanded wildcards. */ /*! * \variable ResolvedGroup::wildcards * \brief Represents the wildcard elements in this group's "files" binding. * If no wildcards are specified there, this variable is null. * \sa SourceWildCards */ /*! * \brief Returns all files specified in the group item as source artifacts. * This includes the expanded list of wildcards. */ std::vector ResolvedGroup::allFiles() const { std::vector lst = files; if (wildcards) lst << wildcards->files; return lst; } void ResolvedGroup::load(PersistentPool &pool) { serializationOp(pool); if (wildcards) wildcards->group = this; } void ResolvedGroup::store(PersistentPool &pool) { serializationOp(pool); } /*! * \class RuleArtifact * \brief The \c RuleArtifact class represents an Artifact item encountered in the context * of a Rule item. * When applying the rule, one \c Artifact object will be constructed from each \c RuleArtifact * object. During that process, the \c RuleArtifact's bindings are evaluated and the results * are inserted into the corresponding \c Artifact's properties. * \sa Rule */ /*! * \class ScriptFunction * \brief The \c ScriptFunction class represents the JavaScript code found in the "prepare" binding * of a \c Rule item in a qbs file. * \sa Rule */ ScriptFunction::ScriptFunction() { } ScriptFunction::~ScriptFunction() { } /*! * \variable ScriptFunction::script * \brief The actual Javascript code, taken verbatim from the qbs source file. */ /*! * \variable ScriptFunction::location * \brief The exact location of the script in the qbs source file. * This is mostly needed for diagnostics. */ bool ScriptFunction::isValid() const { return location.line() != -1; } bool operator==(const ScriptFunction &a, const ScriptFunction &b) { return a.sourceCode == b.sourceCode && a.location == b.location && equals(a.fileContext.get(), b.fileContext.get()); } QStringList ResolvedModule::argumentNamesForSetupBuildEnv() { static const QStringList argNames = BuiltinDeclarations::instance() .argumentNamesForScriptFunction(ItemType::Module, StringConstants::setupBuildEnvironmentProperty()); return argNames; } QStringList ResolvedModule::argumentNamesForSetupRunEnv() { static const QStringList argNames = BuiltinDeclarations::instance() .argumentNamesForScriptFunction(ItemType::Module, StringConstants::setupRunEnvironmentProperty()); return argNames; } bool operator==(const ResolvedModule &m1, const ResolvedModule &m2) { return m1.name == m2.name && m1.isProduct == m2.isProduct && m1.moduleDependencies.toSet() == m2.moduleDependencies.toSet() && m1.setupBuildEnvironmentScript == m2.setupBuildEnvironmentScript && m1.setupRunEnvironmentScript == m2.setupRunEnvironmentScript; } RulePtr Rule::clone() const { return std::make_shared(*this); } QStringList Rule::argumentNamesForOutputArtifacts() { static const QStringList argNames = BuiltinDeclarations::instance() .argumentNamesForScriptFunction(ItemType::Rule, StringConstants::outputArtifactsProperty()); return argNames; } QStringList Rule::argumentNamesForPrepare() { static const QStringList argNames = BuiltinDeclarations::instance() .argumentNamesForScriptFunction(ItemType::Rule, StringConstants::prepareProperty()); return argNames; } QString Rule::toString() const { QStringList outputTagsSorted = collectedOutputFileTags().toStringList(); outputTagsSorted.sort(); FileTags inputTags = inputs; inputTags.unite(inputsFromDependencies); QStringList inputTagsSorted = inputTags.toStringList(); inputTagsSorted.sort(); return QLatin1Char('[') + outputTagsSorted.join(QLatin1Char(',')) + QLatin1String("][") + inputTagsSorted.join(QLatin1Char(',')) + QLatin1Char(']'); } FileTags Rule::staticOutputFileTags() const { FileTags result; for (const RuleArtifactConstPtr &artifact : artifacts) result.unite(artifact->fileTags); return result; } FileTags Rule::collectedOutputFileTags() const { FileTags result = outputFileTags.empty() ? staticOutputFileTags() : outputFileTags; for (const auto &ap : product->artifactProperties) { if (ap->fileTagsFilter().intersects(result)) result += ap->extraFileTags(); } return result; } bool Rule::isDynamic() const { return outputArtifactsScript.isValid(); } bool Rule::declaresInputs() const { return !inputs.empty() || !inputsFromDependencies.empty(); } ResolvedProduct::ResolvedProduct() : enabled(true) { } ResolvedProduct::~ResolvedProduct() { } void ResolvedProduct::accept(BuildGraphVisitor *visitor) const { if (!buildData) return; for (BuildGraphNode * const node : qAsConst(buildData->rootNodes())) node->accept(visitor); } /*! * \brief Returns all files of all groups as source artifacts. * This includes the expanded list of wildcards. */ std::vector ResolvedProduct::allFiles() const { std::vector lst; for (const GroupConstPtr &group : groups) lst << group->allFiles(); return lst; } /*! * \brief Returns all files of all enabled groups as source artifacts. * \sa ResolvedProduct::allFiles() */ std::vector ResolvedProduct::allEnabledFiles() const { std::vector lst; for (const GroupConstPtr &group : groups) { if (group->enabled) lst << group->allFiles(); } return lst; } FileTags ResolvedProduct::fileTagsForFileName(const QString &fileName) const { FileTags result; std::unique_ptr priority; for (const FileTaggerConstPtr &tagger : qAsConst(fileTaggers)) { for (const QRegExp &pattern : tagger->patterns()) { if (FileInfo::globMatches(pattern, fileName)) { if (priority) { if (*priority != tagger->priority()) { // The taggers are expected to be sorted by priority. QBS_ASSERT(*priority > tagger->priority(), return result); return result; } } else { priority.reset(new int(tagger->priority())); } result.unite(tagger->fileTags()); break; } } } return result; } void ResolvedProduct::load(PersistentPool &pool) { serializationOp(pool); for (const RulePtr &rule : rules) rule->product = this; for (const ResolvedModulePtr &module : modules) module->product = this; } void ResolvedProduct::store(PersistentPool &pool) { serializationOp(pool); } ArtifactSet ResolvedProduct::lookupArtifactsByFileTag(const FileTag &tag) const { QBS_CHECK(buildData); return buildData->artifactsByFileTag().value(tag); } ArtifactSet ResolvedProduct::lookupArtifactsByFileTags(const FileTags &tags) const { QBS_CHECK(buildData); ArtifactSet set; for (const FileTag &tag : tags) set = set.unite(buildData->artifactsByFileTag().value(tag)); return set; } ArtifactSet ResolvedProduct::targetArtifacts() const { QBS_CHECK(buildData); ArtifactSet taSet; for (Artifact * const a : buildData->rootArtifacts()) { QBS_CHECK(a->fileTags().intersects(fileTags)); taSet << a; } return taSet; } TopLevelProject *ResolvedProduct::topLevelProject() const { return project->topLevelProject(); } QString ResolvedProduct::uniqueName(const QString &name, const QString &multiplexConfigurationId) { QString result = name; if (!multiplexConfigurationId.isEmpty()) result.append(QLatin1Char('.')).append(multiplexConfigurationId); return result; } QString ResolvedProduct::uniqueName() const { return uniqueName(name, multiplexConfigurationId); } QString ResolvedProduct::fullDisplayName(const QString &name, const QString &multiplexConfigurationId) { QString result = name; if (!multiplexConfigurationId.isEmpty()) result.append(QLatin1Char(' ')).append(multiplexIdToString(multiplexConfigurationId)); return result; } QString ResolvedProduct::fullDisplayName() const { return fullDisplayName(name, multiplexConfigurationId); } QString ResolvedProduct::profile() const { return moduleProperties->qbsPropertyValue(StringConstants::profileProperty()).toString(); } static QStringList findGeneratedFiles(const Artifact *base, bool recursive, const FileTags &tags) { QStringList result; for (const Artifact *parent : base->parentArtifacts()) { if (tags.empty() || parent->fileTags().intersects(tags)) result << parent->filePath(); if (recursive) result << findGeneratedFiles(parent, true, tags); } return result; } QStringList ResolvedProduct::generatedFiles(const QString &baseFile, bool recursive, const FileTags &tags) const { ProductBuildData *data = buildData.get(); if (!data) return {}; for (const Artifact *art : filterByType(data->allNodes())) { if (art->filePath() == baseFile) return findGeneratedFiles(art, recursive, tags); } return {}; } QString ResolvedProduct::deriveBuildDirectoryName(const QString &name, const QString &multiplexConfigurationId) { QString dirName = uniqueName(name, multiplexConfigurationId); const QByteArray hash = QCryptographicHash::hash(dirName.toUtf8(), QCryptographicHash::Sha1); return HostOsInfo::rfc1034Identifier(dirName) .append(QLatin1Char('.')) .append(QString::fromLatin1(hash.toHex().left(8))); } QString ResolvedProduct::buildDirectory() const { return productProperties.value(StringConstants::buildDirectoryProperty()).toString(); } bool ResolvedProduct::isInParentProject(const ResolvedProductConstPtr &other) const { for (const ResolvedProject *otherParent = other->project.get(); otherParent; otherParent = otherParent->parentProject.get()) { if (otherParent == project.get()) return true; } return false; } bool ResolvedProduct::builtByDefault() const { return productProperties.value(StringConstants::builtByDefaultProperty(), true).toBool(); } void ResolvedProduct::cacheExecutablePath(const QString &origFilePath, const QString &fullFilePath) { std::lock_guard locker(m_executablePathCacheLock); m_executablePathCache.insert(origFilePath, fullFilePath); } QString ResolvedProduct::cachedExecutablePath(const QString &origFilePath) const { std::lock_guard locker(m_executablePathCacheLock); return m_executablePathCache.value(origFilePath); } ResolvedProject::ResolvedProject() : enabled(true), m_topLevelProject(nullptr) { } ResolvedProject::~ResolvedProject() { } void ResolvedProject::accept(BuildGraphVisitor *visitor) const { for (const ResolvedProductPtr &product : products) product->accept(visitor); for (const ResolvedProjectPtr &subProject : qAsConst(subProjects)) subProject->accept(visitor); } TopLevelProject *ResolvedProject::topLevelProject() { if (m_topLevelProject) return m_topLevelProject; if (parentProject.expired()) { m_topLevelProject = static_cast(this); return m_topLevelProject; } m_topLevelProject = parentProject->topLevelProject(); return m_topLevelProject; } std::vector ResolvedProject::allSubProjects() const { std::vector projectList = subProjects; for (const ResolvedProjectConstPtr &subProject : subProjects) projectList << subProject->allSubProjects(); return projectList; } std::vector ResolvedProject::allProducts() const { std::vector productList = products; for (const ResolvedProjectConstPtr &subProject : qAsConst(subProjects)) productList << subProject->allProducts(); return productList; } void ResolvedProject::load(PersistentPool &pool) { serializationOp(pool); std::for_each(products.cbegin(), products.cend(), [](const ResolvedProductPtr &p) { if (!p->buildData) return; for (BuildGraphNode * const node : qAsConst(p->buildData->allNodes())) { node->product = p; // restore parent links for (BuildGraphNode * const child : qAsConst(node->children)) child->parents.insert(node); } }); } void ResolvedProject::store(PersistentPool &pool) { serializationOp(pool); } TopLevelProject::TopLevelProject() : bgLocker(nullptr), locked(false), lastStartResolveTime(FileTime::oldestTime()) { } TopLevelProject::~TopLevelProject() { cleanupModuleProviderOutput(); delete bgLocker; } QString TopLevelProject::deriveId(const QVariantMap &config) { const QVariantMap qbsProperties = config.value(StringConstants::qbsModule()).toMap(); const QString configurationName = qbsProperties.value( StringConstants::configurationNameProperty()).toString(); return configurationName; } QString TopLevelProject::deriveBuildDirectory(const QString &buildRoot, const QString &id) { return buildRoot + QLatin1Char('/') + id; } void TopLevelProject::setBuildConfiguration(const QVariantMap &config) { m_buildConfiguration = config; m_id = deriveId(config); } QString TopLevelProject::profile() const { return projectProperties().value(StringConstants::profileProperty()).toString(); } void TopLevelProject::makeModuleProvidersNonTransient() { for (ModuleProviderInfo &m : moduleProviderInfo) m.transientOutput = false; } QString TopLevelProject::buildGraphFilePath() const { return ProjectBuildData::deriveBuildGraphFilePath(buildDirectory, id()); } void TopLevelProject::store(Logger logger) { // TODO: Use progress observer here. if (!buildData) return; if (!buildData->isDirty()) { qCDebug(lcBuildGraph) << "build graph is unchanged in project" << id(); return; } makeModuleProvidersNonTransient(); const QString fileName = buildGraphFilePath(); qCDebug(lcBuildGraph) << "storing:" << fileName; PersistentPool pool(logger); PersistentPool::HeadData headData; headData.projectConfig = buildConfiguration(); pool.setHeadData(headData); pool.setupWriteStream(fileName); store(pool); pool.finalizeWriteStream(); buildData->setClean(); } void TopLevelProject::load(PersistentPool &pool) { ResolvedProject::load(pool); serializationOp(pool); QBS_CHECK(buildData); } void TopLevelProject::store(PersistentPool &pool) { ResolvedProject::store(pool); serializationOp(pool); } void TopLevelProject::cleanupModuleProviderOutput() { QString error; for (const ModuleProviderInfo &m : moduleProviderInfo) { if (m.transientOutput) { if (!removeDirectoryWithContents(m.outputDirPath(buildDirectory), &error)) qCWarning(lcBuildGraph) << "Error removing module provider output:" << error; } } QDir moduleProviderBaseDir(buildDirectory + QLatin1Char('/') + ModuleProviderInfo::outputBaseDirName()); if (moduleProviderBaseDir.exists() && moduleProviderBaseDir.isEmpty() && !removeDirectoryWithContents(moduleProviderBaseDir.path(), &error)) { qCWarning(lcBuildGraph) << "Error removing module provider output:" << error; } } /*! * \class SourceWildCards * \brief Objects of the \c SourceWildCards class result from giving wildcards in a * \c ResolvedGroup's "files" binding. * \sa ResolvedGroup */ /*! * \variable SourceWildCards::prefix * \brief Inherited from the \c ResolvedGroup * \sa ResolvedGroup */ /*! * \variable SourceWildCards::patterns * \brief All elements of the \c ResolvedGroup's "files" binding that contain wildcards. * \sa ResolvedGroup */ /*! * \variable SourceWildCards::excludePatterns * \brief Corresponds to the \c ResolvedGroup's "excludeFiles" binding. * \sa ResolvedGroup */ /*! * \variable SourceWildCards::files * \brief The \c SourceArtifacts resulting from the expanded list of matching files. */ Set SourceWildCards::expandPatterns(const GroupConstPtr &group, const QString &baseDir, const QString &buildDir) { Set files = expandPatterns(group, patterns, baseDir, buildDir); files -= expandPatterns(group, excludePatterns, baseDir, buildDir); return files; } Set SourceWildCards::expandPatterns(const GroupConstPtr &group, const QStringList &patterns, const QString &baseDir, const QString &buildDir) { Set files; QString expandedPrefix = group->prefix; if (expandedPrefix.startsWith(StringConstants::tildeSlash())) expandedPrefix.replace(0, 1, QDir::homePath()); for (QString pattern : patterns) { pattern.prepend(expandedPrefix); pattern.replace(QLatin1Char('\\'), QLatin1Char('/')); QStringList parts = pattern.split(QLatin1Char('/'), QString::SkipEmptyParts); if (FileInfo::isAbsolute(pattern)) { QString rootDir; if (HostOsInfo::isWindowsHost() && pattern.at(0) != QLatin1Char('/')) { rootDir = parts.takeFirst(); if (!rootDir.endsWith(QLatin1Char('/'))) rootDir.append(QLatin1Char('/')); } else { rootDir = QLatin1Char('/'); } expandPatterns(files, group, parts, rootDir, buildDir); } else { expandPatterns(files, group, parts, baseDir, buildDir); } } return files; } void SourceWildCards::expandPatterns(Set &result, const GroupConstPtr &group, const QStringList &parts, const QString &baseDir, const QString &buildDir) { // People might build directly in the project source directory. This is okay, since // we keep the build data in a "container" directory. However, we must make sure we don't // match any generated files therein as source files. if (baseDir.startsWith(buildDir)) return; dirTimeStamps.push_back({ baseDir, FileInfo(baseDir).lastModified() }); QStringList changed_parts = parts; bool recursive = false; QString part = changed_parts.takeFirst(); while (part == QStringLiteral("**")) { recursive = true; if (changed_parts.empty()) { part = StringConstants::star(); break; } part = changed_parts.takeFirst(); } const bool isDir = !changed_parts.empty(); const QString &filePattern = part; const QDirIterator::IteratorFlags itFlags = recursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; QDir::Filters itFilters = isDir ? QDir::Dirs : QDir::Files | QDir::System | QDir::Dirs; // This one is needed to get symbolic links to directories if (isDir && !FileInfo::isPattern(filePattern)) itFilters |= QDir::Hidden; if (filePattern != StringConstants::dotDot() && filePattern != StringConstants::dot()) itFilters |= QDir::NoDotAndDotDot; QDirIterator it(baseDir, QStringList(filePattern), itFilters, itFlags); while (it.hasNext()) { const QString filePath = it.next(); const QString parentDir = it.fileInfo().dir().path(); if (parentDir.startsWith(buildDir)) continue; // See above. if (!isDir && it.fileInfo().isDir() && !it.fileInfo().isSymLink()) continue; if (isDir) { expandPatterns(result, group, changed_parts, filePath, buildDir); } else { if (parentDir != baseDir) dirTimeStamps.push_back({parentDir, FileInfo(baseDir).lastModified()}); result += QDir::cleanPath(filePath); } } } template QMap listToMap(const L &list) { using V = typename L::value_type; QMap map; for (const V &elem : list) map.insert(keyFromElem(elem), elem); return map; } template bool listsAreEqual(const L &l1, const L &l2) { if (l1.size() != l2.size()) return false; using V = typename L::value_type; const QMap map1 = listToMap(l1); const QMap map2 = listToMap(l2); for (const QString &key : map1.keys()) { const V &value2 = map2.value(key); if (!value2) return false; if (!equals(map1.value(key).get(), value2.get())) return false; } return true; } QString keyFromElem(const SourceArtifactPtr &sa) { return sa->absoluteFilePath; } QString keyFromElem(const RulePtr &r) { QString key = r->toString() + r->prepareScript.sourceCode(); if (r->outputArtifactsScript.isValid()) key += r->outputArtifactsScript.sourceCode(); for (const auto &a : r->artifacts) key += a->filePath; return key; } QString keyFromElem(const ArtifactPropertiesPtr &ap) { QStringList lst = ap->fileTagsFilter().toStringList(); lst.sort(); return lst.join(QLatin1Char(',')); } bool operator==(const SourceArtifactInternal &sa1, const SourceArtifactInternal &sa2) { return sa1.absoluteFilePath == sa2.absoluteFilePath && sa1.fileTags == sa2.fileTags && sa1.overrideFileTags == sa2.overrideFileTags && sa1.targetOfModule == sa2.targetOfModule && *sa1.properties == *sa2.properties; } bool operator==(const Rule &r1, const Rule &r2) { if (r1.artifacts.size() != r2.artifacts.size()) return false; for (size_t i = 0; i < r1.artifacts.size(); ++i) { if (!equals(r1.artifacts.at(i).get(), r2.artifacts.at(i).get())) return false; } return r1.module->name == r2.module->name && r1.prepareScript == r2.prepareScript && r1.outputArtifactsScript == r2.outputArtifactsScript && r1.inputs == r2.inputs && r1.outputFileTags == r2.outputFileTags && r1.auxiliaryInputs == r2.auxiliaryInputs && r1.excludedInputs == r2.excludedInputs && r1.inputsFromDependencies == r2.inputsFromDependencies && r1.explicitlyDependsOn == r2.explicitlyDependsOn && r1.explicitlyDependsOnFromDependencies == r2.explicitlyDependsOnFromDependencies && r1.multiplex == r2.multiplex && r1.requiresInputs == r2.requiresInputs && r1.alwaysRun == r2.alwaysRun; } bool ruleListsAreEqual(const std::vector &l1, const std::vector &l2) { return listsAreEqual(l1, l2); } bool operator==(const RuleArtifact &a1, const RuleArtifact &a2) { return a1.filePath == a2.filePath && a1.fileTags == a2.fileTags && a1.alwaysUpdated == a2.alwaysUpdated && Set::fromStdVector(a1.bindings) == Set::fromStdVector(a2.bindings); } bool operator==(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2) { return b1.code == b2.code && b1.name == b2.name; } uint qHash(const RuleArtifact::Binding &b) { return qHash(std::make_pair(b.code, b.name.join(QLatin1Char(',')))); } bool artifactPropertyListsAreEqual(const std::vector &l1, const std::vector &l2) { return listsAreEqual(l1, l2); } QString multiplexIdToString(const QString &id) { return QString::fromUtf8(QByteArray::fromBase64(id.toUtf8())); } bool operator==(const PrivateScriptFunction &a, const PrivateScriptFunction &b) { return equals(a.m_sharedData.get(), b.m_sharedData.get()); } bool operator==(const ExportedProperty &p1, const ExportedProperty &p2) { return p1.fullName == p2.fullName && p1.type == p2.type && p1.sourceCode == p2.sourceCode && p1.isBuiltin == p2.isBuiltin; } bool operator==(const ExportedModuleDependency &d1, const ExportedModuleDependency &d2) { return d1.name == d2.name && d1.moduleProperties == d2.moduleProperties; } bool equals(const std::vector &l1, const std::vector &l2) { static const auto cmp = [](const ExportedItemPtr &p1, const ExportedItemPtr &p2) { return *p1 == *p2; }; return l1.size() == l2.size() && std::equal(l1.cbegin(), l1.cend(), l2.cbegin(), cmp); } bool operator==(const ExportedItem &i1, const ExportedItem &i2) { return i1.name == i2.name && i1.properties == i2.properties && equals(i1.children, i2.children); } bool operator==(const ExportedModule &m1, const ExportedModule &m2) { static const auto depMapsEqual = [](const QMap &m1, const QMap &m2) { if (m1.size() != m2.size()) return false; for (auto it1 = m1.cbegin(), it2 = m2.cbegin(); it1 != m1.cend(); ++it1, ++it2) { if (it1.key()->name != it2.key()->name) return false; if (it1.value() != it2.value()) return false; } return true; }; return m1.propertyValues == m2.propertyValues && m1.modulePropertyValues == m2.modulePropertyValues && equals(m1.children, m2.children) && m1.m_properties == m2.m_properties && m1.importStatements == m2.importStatements && m1.productDependencies.size() == m2.productDependencies.size() && m1.productDependencies == m2.productDependencies && depMapsEqual(m1.dependencyParameters, m2.dependencyParameters); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/language.h000066400000000000000000000631401347155106100216510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LANGUAGE_H #define QBS_LANGUAGE_H #include "filetags.h" #include "forward_decls.h" #include "jsimports.h" #include "moduleproviderinfo.h" #include "propertydeclaration.h" #include "resolvedfilecontext.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QScriptEngine; QT_END_NAMESPACE namespace qbs { namespace Internal { class BuildGraphLocker; class BuildGraphLoader; class BuildGraphVisitor; class FileTagger { public: static FileTaggerPtr create() { return FileTaggerPtr(new FileTagger); } static FileTaggerPtr create(const QStringList &patterns, const FileTags &fileTags, int priority) { return FileTaggerPtr(new FileTagger(patterns, fileTags, priority)); } const QList &patterns() const { return m_patterns; } const FileTags &fileTags() const { return m_fileTags; } int priority() const { return m_priority; } template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(m_patterns, m_fileTags, m_priority); } private: FileTagger(const QStringList &patterns, const FileTags &fileTags, int priority); FileTagger() {} void setPatterns(const QStringList &patterns); QList m_patterns; FileTags m_fileTags; int m_priority = 0; }; class Probe { public: static ProbePtr create() { return ProbePtr(new Probe); } static ProbeConstPtr create(const QString &globalId, const CodeLocation &location, bool condition, const QString &configureScript, const QVariantMap &properties, const QVariantMap &initialProperties, const std::vector &importedFilesUsed) { return ProbeConstPtr(new Probe(globalId, location, condition, configureScript, properties, initialProperties, importedFilesUsed)); } const QString &globalId() const { return m_globalId; } bool condition() const { return m_condition; } const QString &configureScript() const { return m_configureScript; } const QVariantMap &properties() const { return m_properties; } const QVariantMap &initialProperties() const { return m_initialProperties; } const std::vector &importedFilesUsed() const { return m_importedFilesUsed; } bool needsReconfigure(const FileTime &referenceTime) const; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(m_globalId, m_location, m_condition, m_configureScript, m_properties, m_initialProperties, m_importedFilesUsed); } private: Probe() {} Probe(const QString &globalId, const CodeLocation &location, bool condition, const QString &configureScript, const QVariantMap &properties, const QVariantMap &initialProperties, const std::vector &importedFilesUsed) : m_globalId(globalId) , m_location(location) , m_configureScript(configureScript) , m_properties(properties) , m_initialProperties(initialProperties) , m_importedFilesUsed(importedFilesUsed) , m_condition(condition) {} QString m_globalId; CodeLocation m_location; QString m_configureScript; QVariantMap m_properties; QVariantMap m_initialProperties; std::vector m_importedFilesUsed; bool m_condition; }; class RuleArtifact { public: static RuleArtifactPtr create() { return RuleArtifactPtr(new RuleArtifact); } QString filePath; FileTags fileTags; bool alwaysUpdated; CodeLocation location; CodeLocation filePathLocation; class Binding { public: QStringList name; QString code; CodeLocation location; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(name, code, location); } bool operator<(const Binding &other) const { if (name == other.name) { if (code == other.code) return location < other.location; return code < other.code; } return name < other.name; } }; std::vector bindings; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(filePath, fileTags, alwaysUpdated, location, filePathLocation, bindings); } private: RuleArtifact() : alwaysUpdated(true) {} }; uint qHash(const RuleArtifact::Binding &b); bool operator==(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2); inline bool operator!=(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2) { return !(b1 == b2); } bool operator==(const RuleArtifact &a1, const RuleArtifact &a2); inline bool operator!=(const RuleArtifact &a1, const RuleArtifact &a2) { return !(a1 == a2); } class SourceArtifactInternal { public: static SourceArtifactPtr create() { return SourceArtifactPtr(new SourceArtifactInternal); } bool isTargetOfModule() const { return !targetOfModule.isEmpty(); } QString absoluteFilePath; FileTags fileTags; bool overrideFileTags; QString targetOfModule; PropertyMapPtr properties; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(absoluteFilePath, fileTags, overrideFileTags, properties, targetOfModule); } private: SourceArtifactInternal() : overrideFileTags(true) {} }; bool operator==(const SourceArtifactInternal &sa1, const SourceArtifactInternal &sa2); inline bool operator!=(const SourceArtifactInternal &sa1, const SourceArtifactInternal &sa2) { return !(sa1 == sa2); } class SourceWildCards { public: Set expandPatterns(const GroupConstPtr &group, const QString &baseDir, const QString &buildDir); const ResolvedGroup *group = nullptr; // The owning group. QStringList patterns; QStringList excludePatterns; std::vector> dirTimeStamps; std::vector files; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(patterns, excludePatterns, dirTimeStamps, files); } private: Set expandPatterns(const GroupConstPtr &group, const QStringList &patterns, const QString &baseDir, const QString &buildDir); void expandPatterns(Set &result, const GroupConstPtr &group, const QStringList &parts, const QString &baseDir, const QString &buildDir); }; class QBS_AUTOTEST_EXPORT ResolvedGroup { public: static GroupPtr create() { return GroupPtr(new ResolvedGroup); } CodeLocation location; QString name; bool enabled; QString prefix; std::vector files; std::unique_ptr wildcards; PropertyMapPtr properties; FileTags fileTags; QString targetOfModule; bool overrideTags; std::vector allFiles() const; void load(PersistentPool &pool); void store(PersistentPool &pool); private: ResolvedGroup() : enabled(true) {} template void serializationOp(PersistentPool &pool) { pool.serializationOp(name, enabled, location, prefix, files, wildcards, properties, fileTags, targetOfModule, overrideTags); } }; class ScriptFunction { public: static ScriptFunctionPtr create() { return ScriptFunctionPtr(new ScriptFunction); } ~ScriptFunction(); QString sourceCode; CodeLocation location; ResolvedFileContextConstPtr fileContext; bool isValid() const; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(sourceCode, location, fileContext); } private: ScriptFunction(); }; bool operator==(const ScriptFunction &a, const ScriptFunction &b); inline bool operator!=(const ScriptFunction &a, const ScriptFunction &b) { return !(a == b); } bool operator==(const PrivateScriptFunction &a, const PrivateScriptFunction &b); class PrivateScriptFunction { friend bool operator==(const PrivateScriptFunction &a, const PrivateScriptFunction &b); public: void initialize(const ScriptFunctionPtr &sharedData) { m_sharedData = sharedData; } mutable QScriptValue scriptFunction; // not stored QString &sourceCode() const { return m_sharedData->sourceCode; } CodeLocation &location() const { return m_sharedData->location; } ResolvedFileContextConstPtr &fileContext() const { return m_sharedData->fileContext; } bool isValid() const { return m_sharedData->isValid(); } template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(m_sharedData); } private: ScriptFunctionPtr m_sharedData; }; bool operator==(const PrivateScriptFunction &a, const PrivateScriptFunction &b); inline bool operator!=(const PrivateScriptFunction &a, const PrivateScriptFunction &b) { return !(a == b); } class ResolvedModule { public: static ResolvedModulePtr create() { return ResolvedModulePtr(new ResolvedModule); } QString name; QStringList moduleDependencies; PrivateScriptFunction setupBuildEnvironmentScript; PrivateScriptFunction setupRunEnvironmentScript; ResolvedProduct *product = nullptr; bool isProduct; static QStringList argumentNamesForSetupBuildEnv(); static QStringList argumentNamesForSetupRunEnv(); template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(name, moduleDependencies, setupBuildEnvironmentScript, setupRunEnvironmentScript, isProduct); } private: ResolvedModule() {} }; bool operator==(const ResolvedModule &m1, const ResolvedModule &m2); inline bool operator!=(const ResolvedModule &m1, const ResolvedModule &m2) { return !(m1 == m2); } /** * Per default each rule is a "non-multiplex rule". * * A "multiplex rule" creates one transformer that takes all * input artifacts with the matching input file tag and creates * one or more artifacts. (e.g. linker rule) * * A "non-multiplex rule" creates one transformer per matching input file. */ class Rule { public: static RulePtr create() { return RulePtr(new Rule); } RulePtr clone() const; ResolvedProduct *product = nullptr; // The owning product. ResolvedModuleConstPtr module; QString name; PrivateScriptFunction prepareScript; FileTags outputFileTags; // unused, if artifacts is non-empty PrivateScriptFunction outputArtifactsScript; // unused, if artifacts is non-empty FileTags inputs; FileTags auxiliaryInputs; FileTags excludedInputs; FileTags inputsFromDependencies; FileTags explicitlyDependsOn; FileTags explicitlyDependsOnFromDependencies; bool multiplex; bool requiresInputs; std::vector artifacts; // unused, if outputFileTags/outputArtifactsScript is non-empty bool alwaysRun; // members that we don't need to save int ruleGraphId; static QStringList argumentNamesForOutputArtifacts(); static QStringList argumentNamesForPrepare(); QString toString() const; FileTags staticOutputFileTags() const; FileTags collectedOutputFileTags() const; bool isDynamic() const; bool declaresInputs() const; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(name, prepareScript, outputArtifactsScript, module, inputs, outputFileTags, auxiliaryInputs, excludedInputs, inputsFromDependencies, explicitlyDependsOn, explicitlyDependsOnFromDependencies, multiplex, requiresInputs, alwaysRun, artifacts); } private: Rule() : multiplex(false), alwaysRun(false), ruleGraphId(-1) {} }; bool operator==(const Rule &r1, const Rule &r2); inline bool operator!=(const Rule &r1, const Rule &r2) { return !(r1 == r2); } bool ruleListsAreEqual(const std::vector &l1, const std::vector &l2); class ResolvedScanner { public: static ResolvedScannerPtr create() { return ResolvedScannerPtr(new ResolvedScanner); } ResolvedModuleConstPtr module; FileTags inputs; bool recursive; PrivateScriptFunction searchPathsScript; PrivateScriptFunction scanScript; template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(module, inputs, recursive, searchPathsScript, scanScript); } private: ResolvedScanner() : recursive(false) {} }; class ExportedProperty { public: template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(fullName, type, sourceCode, isBuiltin); } QString fullName; PropertyDeclaration::Type type; QString sourceCode; bool isBuiltin = false; }; bool operator==(const ExportedProperty &p1, const ExportedProperty &p2); inline bool operator!=(const ExportedProperty &p1, const ExportedProperty &p2) { return !(p1 == p2); } class ExportedItem { public: template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(name, properties, children); } static ExportedItemPtr create() { return std::make_shared(); } QString name; std::vector properties; std::vector children; }; bool equals(const std::vector &l1, const std::vector &l2); bool operator==(const ExportedItem &i1, const ExportedItem &i2); inline bool operator!=(const ExportedItem &i1, const ExportedItem &i2) { return !(i1 == i2); } class ExportedModuleDependency { public: template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(name, moduleProperties); }; QString name; QVariantMap moduleProperties; }; bool operator==(const ExportedModuleDependency &d1, const ExportedModuleDependency &d2); inline bool operator!=(const ExportedModuleDependency &d1, const ExportedModuleDependency &d2) { return !(d1 == d2); } class ExportedModule { public: template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(propertyValues, modulePropertyValues, children, productDependencies, moduleDependencies, m_properties, dependencyParameters, importStatements); }; QVariantMap propertyValues; QVariantMap modulePropertyValues; std::vector children; std::vector productDependencies; std::vector moduleDependencies; std::vector m_properties; QMap dependencyParameters; QStringList importStatements; }; bool operator==(const ExportedModule &m1, const ExportedModule &m2); inline bool operator!=(const ExportedModule &m1, const ExportedModule &m2) { return !(m1 == m2); } class TopLevelProject; class ScriptEngine; class QBS_AUTOTEST_EXPORT ResolvedProduct { public: static ResolvedProductPtr create() { return ResolvedProductPtr(new ResolvedProduct); } ~ResolvedProduct(); bool enabled; FileTags fileTags; QString name; QString targetName; QString multiplexConfigurationId; QString sourceDirectory; QString destinationDirectory; CodeLocation location; WeakPointer project; QVariantMap productProperties; PropertyMapPtr moduleProperties; std::vector rules; std::vector dependencies; QHash dependencyParameters; std::vector fileTaggers; JobLimits jobLimits; std::vector modules; QHash moduleParameters; std::vector scanners; std::vector groups; std::vector probes; std::vector artifactProperties; QStringList missingSourceFiles; std::unique_ptr buildData; ExportedModule exportedModule; QProcessEnvironment buildEnvironment; // must not be saved QProcessEnvironment runEnvironment; // must not be saved void accept(BuildGraphVisitor *visitor) const; std::vector allFiles() const; std::vector allEnabledFiles() const; FileTags fileTagsForFileName(const QString &fileName) const; ArtifactSet lookupArtifactsByFileTag(const FileTag &tag) const; ArtifactSet lookupArtifactsByFileTags(const FileTags &tags) const; ArtifactSet targetArtifacts() const; TopLevelProject *topLevelProject() const; static QString uniqueName(const QString &name, const QString &multiplexConfigurationId); QString uniqueName() const; static QString fullDisplayName(const QString &name, const QString &multiplexConfigurationId); QString fullDisplayName() const; QString profile() const; QStringList generatedFiles(const QString &baseFile, bool recursive, const FileTags &tags) const; static QString deriveBuildDirectoryName(const QString &name, const QString &multiplexConfigurationId); QString buildDirectory() const; bool isInParentProject(const ResolvedProductConstPtr &other) const; bool builtByDefault() const; void cacheExecutablePath(const QString &origFilePath, const QString &fullFilePath); QString cachedExecutablePath(const QString &origFilePath) const; void load(PersistentPool &pool); void store(PersistentPool &pool); private: ResolvedProduct(); template void serializationOp(PersistentPool &pool) { pool.serializationOp(enabled, fileTags, name, multiplexConfigurationId, targetName, sourceDirectory, destinationDirectory, missingSourceFiles, location, productProperties, moduleProperties, rules, dependencies, dependencyParameters, fileTaggers, modules, moduleParameters, scanners, groups, artifactProperties, probes, exportedModule, buildData, jobLimits); } QHash m_executablePathCache; mutable std::mutex m_executablePathCacheLock; }; class QBS_AUTOTEST_EXPORT ResolvedProject { public: virtual ~ResolvedProject(); static ResolvedProjectPtr create() { return ResolvedProjectPtr(new ResolvedProject); } QString name; CodeLocation location; bool enabled; std::vector products; std::vector subProjects; WeakPointer parentProject; void accept(BuildGraphVisitor *visitor) const; void setProjectProperties(const QVariantMap &config) { m_projectProperties = config; } const QVariantMap &projectProperties() const { return m_projectProperties; } TopLevelProject *topLevelProject(); std::vector allSubProjects() const; std::vector allProducts() const; virtual void load(PersistentPool &pool); virtual void store(PersistentPool &pool); protected: ResolvedProject(); private: template void serializationOp(PersistentPool &pool) { pool.serializationOp(name, location, enabled, products, subProjects, m_projectProperties); } QVariantMap m_projectProperties; TopLevelProject *m_topLevelProject; }; class QBS_AUTOTEST_EXPORT TopLevelProject : public ResolvedProject { friend class BuildGraphLoader; public: ~TopLevelProject() override; static TopLevelProjectPtr create() { return TopLevelProjectPtr(new TopLevelProject); } static QString deriveId(const QVariantMap &config); static QString deriveBuildDirectory(const QString &buildRoot, const QString &id); QString buildDirectory; // Not saved QProcessEnvironment environment; std::vector probes; ModuleProviderInfoList moduleProviderInfo; QHash canonicalFilePathResults; // Results of calls to "File.canonicalFilePath()." QHash fileExistsResults; // Results of calls to "File.exists()". QHash, QStringList> directoryEntriesResults; // Results of calls to "File.directoryEntries()". QHash fileLastModifiedResults; // Results of calls to "File.lastModified()". std::unique_ptr buildData; BuildGraphLocker *bgLocker; // This holds the system-wide build graph file lock. bool locked; // This is the API-level lock for the project instance. Set buildSystemFiles; FileTime lastStartResolveTime; FileTime lastEndResolveTime; QList warningsEncountered; void setBuildConfiguration(const QVariantMap &config); const QVariantMap &buildConfiguration() const { return m_buildConfiguration; } QString id() const { return m_id; } QString profile() const; void makeModuleProvidersNonTransient(); QVariantMap profileConfigs; QVariantMap overriddenValues; QString buildGraphFilePath() const; void store(Logger logger); private: TopLevelProject(); template void serializationOp(PersistentPool &pool) { pool.serializationOp(m_id, canonicalFilePathResults, fileExistsResults, directoryEntriesResults, fileLastModifiedResults, environment, probes, profileConfigs, overriddenValues, buildSystemFiles, lastStartResolveTime, lastEndResolveTime, warningsEncountered, buildData, moduleProviderInfo); } void load(PersistentPool &pool) override; void store(PersistentPool &pool) override; void cleanupModuleProviderOutput(); QString m_id; QVariantMap m_buildConfiguration; }; bool artifactPropertyListsAreEqual(const std::vector &l1, const std::vector &l2); QString multiplexIdToString(const QString &id); } // namespace Internal } // namespace qbs QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(qbs::Internal::JsImport, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(qbs::Internal::RuleArtifact::Binding, Q_MOVABLE_TYPE); QT_END_NAMESPACE #endif // QBS_LANGUAGE_H qbs-src-1.13.1/src/lib/corelib/language/language.pri000066400000000000000000000044621347155106100222160ustar00rootroot00000000000000include(../../../install_prefix.pri) HEADERS += \ $$PWD/artifactproperties.h \ $$PWD/astimportshandler.h \ $$PWD/astpropertiesitemhandler.h \ $$PWD/asttools.h \ $$PWD/builtindeclarations.h \ $$PWD/deprecationinfo.h \ $$PWD/evaluationdata.h \ $$PWD/evaluator.h \ $$PWD/evaluatorscriptclass.h \ $$PWD/filecontext.h \ $$PWD/filecontextbase.h \ $$PWD/filetags.h \ $$PWD/forward_decls.h \ $$PWD/identifiersearch.h \ $$PWD/item.h \ $$PWD/itemdeclaration.h \ $$PWD/itemobserver.h \ $$PWD/itempool.h \ $$PWD/itemreader.h \ $$PWD/itemreaderastvisitor.h \ $$PWD/itemreadervisitorstate.h \ $$PWD/itemtype.h \ $$PWD/jsimports.h \ $$PWD/language.h \ $$PWD/loader.h \ $$PWD/moduleloader.h \ $$PWD/modulemerger.h \ $$PWD/moduleproviderinfo.h \ $$PWD/preparescriptobserver.h \ $$PWD/projectresolver.h \ $$PWD/property.h \ $$PWD/propertydeclaration.h \ $$PWD/propertymapinternal.h \ $$PWD/qualifiedid.h \ $$PWD/resolvedfilecontext.h \ $$PWD/scriptengine.h \ $$PWD/scriptimporter.h \ $$PWD/scriptpropertyobserver.h \ $$PWD/value.h SOURCES += \ $$PWD/artifactproperties.cpp \ $$PWD/astimportshandler.cpp \ $$PWD/astpropertiesitemhandler.cpp \ $$PWD/asttools.cpp \ $$PWD/builtindeclarations.cpp \ $$PWD/evaluator.cpp \ $$PWD/evaluatorscriptclass.cpp \ $$PWD/filecontext.cpp \ $$PWD/filecontextbase.cpp \ $$PWD/filetags.cpp \ $$PWD/identifiersearch.cpp \ $$PWD/item.cpp \ $$PWD/itemdeclaration.cpp \ $$PWD/itempool.cpp \ $$PWD/itemreader.cpp \ $$PWD/itemreaderastvisitor.cpp \ $$PWD/itemreadervisitorstate.cpp \ $$PWD/language.cpp \ $$PWD/loader.cpp \ $$PWD/moduleloader.cpp \ $$PWD/modulemerger.cpp \ $$PWD/preparescriptobserver.cpp \ $$PWD/scriptpropertyobserver.cpp \ $$PWD/projectresolver.cpp \ $$PWD/property.cpp \ $$PWD/propertydeclaration.cpp \ $$PWD/propertymapinternal.cpp \ $$PWD/qualifiedid.cpp \ $$PWD/resolvedfilecontext.cpp \ $$PWD/scriptengine.cpp \ $$PWD/scriptimporter.cpp \ $$PWD/value.cpp !qbs_no_dev_install { language_headers.files = $$PWD/forward_decls.h language_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/language INSTALLS += language_headers } qbs-src-1.13.1/src/lib/corelib/language/loader.cpp000066400000000000000000000205011347155106100216610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "loader.h" #include "evaluator.h" #include "language.h" #include "moduleloader.h" #include "projectresolver.h" #include "scriptengine.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { Loader::Loader(ScriptEngine *engine, const Logger &logger) : m_logger(logger) , m_progressObserver(nullptr) , m_engine(engine) { m_logger.storeWarnings(); } void Loader::setProgressObserver(ProgressObserver *observer) { m_progressObserver = observer; } void Loader::setSearchPaths(const QStringList &_searchPaths) { QStringList searchPaths; for (const QString &searchPath : _searchPaths) { if (!FileInfo::exists(searchPath)) { m_logger.qbsWarning() << Tr::tr("Search path '%1' does not exist.") .arg(QDir::toNativeSeparators(searchPath)); } else { searchPaths += searchPath; } } m_searchPaths = searchPaths; } void Loader::setOldProjectProbes(const std::vector &oldProbes) { m_oldProjectProbes = oldProbes; } void Loader::setOldProductProbes(const QHash> &oldProbes) { m_oldProductProbes = oldProbes; } void Loader::setStoredProfiles(const QVariantMap &profiles) { m_storedProfiles = profiles; } void Loader::setStoredModuleProviderInfo(const ModuleProviderInfoList &providerInfo) { m_storedModuleProviderInfo = providerInfo; } TopLevelProjectPtr Loader::loadProject(const SetupProjectParameters &_parameters) { SetupProjectParameters parameters = _parameters; if (parameters.topLevelProfile().isEmpty()) { Settings settings(parameters.settingsDirectory()); QString profileName = settings.defaultProfile(); if (profileName.isEmpty()) { m_logger.qbsDebug() << Tr::tr("No profile specified and no default profile exists. " "Using default property values."); profileName = Profile::fallbackName(); } parameters.setTopLevelProfile(profileName); parameters.expandBuildConfiguration(); } setupProjectFilePath(parameters); QBS_CHECK(QFileInfo(parameters.projectFilePath()).isAbsolute()); m_logger.qbsDebug() << "Using project file '" << QDir::toNativeSeparators(parameters.projectFilePath()) << "'."; m_engine->setEnvironment(parameters.adjustedEnvironment()); m_engine->clearExceptions(); m_engine->clearImportsCache(); m_engine->clearRequestedProperties(); m_engine->enableProfiling(parameters.logElapsedTime()); m_logger.clearWarnings(); EvalContextSwitcher evalContextSwitcher(m_engine, EvalContext::PropertyEvaluation); QTimer cancelationTimer; // At this point, we cannot set a sensible total effort, because we know nothing about // the project yet. That's why we use a placeholder here, so the user at least // sees that an operation is starting. The real total effort will be set later when // we have enough information. if (m_progressObserver) { m_progressObserver->initialize(Tr::tr("Resolving project for configuration %1") .arg(TopLevelProject::deriveId(parameters.finalBuildConfigurationTree())), 1); cancelationTimer.setSingleShot(false); QObject::connect(&cancelationTimer, &QTimer::timeout, [this]() { QBS_ASSERT(m_progressObserver, return); if (m_progressObserver->canceled()) m_engine->cancel(); }); cancelationTimer.start(1000); } const FileTime resolveTime = FileTime::currentTime(); Evaluator evaluator(m_engine); ModuleLoader moduleLoader(&evaluator, m_logger); moduleLoader.setProgressObserver(m_progressObserver); moduleLoader.setSearchPaths(m_searchPaths); moduleLoader.setOldProjectProbes(m_oldProjectProbes); moduleLoader.setOldProductProbes(m_oldProductProbes); moduleLoader.setLastResolveTime(m_lastResolveTime); moduleLoader.setStoredProfiles(m_storedProfiles); moduleLoader.setStoredModuleProviderInfo(m_storedModuleProviderInfo); const ModuleLoaderResult loadResult = moduleLoader.load(parameters); ProjectResolver resolver(&evaluator, loadResult, parameters, m_logger); resolver.setProgressObserver(m_progressObserver); const TopLevelProjectPtr project = resolver.resolve(); project->lastStartResolveTime = resolveTime; project->lastEndResolveTime = FileTime::currentTime(); // E.g. if the top-level project is disabled. if (m_progressObserver) m_progressObserver->setFinished(); return project; } void Loader::setupProjectFilePath(SetupProjectParameters ¶meters) { QString projectFilePath = parameters.projectFilePath(); if (projectFilePath.isEmpty()) projectFilePath = QDir::currentPath(); const QFileInfo projectFileInfo(projectFilePath); if (!projectFileInfo.exists()) throw ErrorInfo(Tr::tr("Project file '%1' cannot be found.").arg(projectFilePath)); if (projectFileInfo.isRelative()) projectFilePath = projectFileInfo.absoluteFilePath(); if (projectFileInfo.isFile()) { parameters.setProjectFilePath(projectFilePath); return; } if (!projectFileInfo.isDir()) throw ErrorInfo(Tr::tr("Project file '%1' has invalid type.").arg(projectFilePath)); const QStringList &actualFileNames = QDir(projectFilePath).entryList(StringConstants::qbsFileWildcards(), QDir::Files); if (actualFileNames.empty()) { QString error; if (parameters.projectFilePath().isEmpty()) error = Tr::tr("No project file given and none found in current directory.\n"); else error = Tr::tr("No project file found in directory '%1'.").arg(projectFilePath); throw ErrorInfo(error); } if (actualFileNames.size() > 1) { throw ErrorInfo(Tr::tr("More than one project file found in directory '%1'.") .arg(projectFilePath)); } projectFilePath.append(QLatin1Char('/')).append(actualFileNames.front()); projectFilePath = QDir::current().filePath(projectFilePath); projectFilePath = QDir::cleanPath(projectFilePath); parameters.setProjectFilePath(projectFilePath); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/loader.h000066400000000000000000000065421347155106100213370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LOADER_H #define QBS_LOADER_H #include "forward_decls.h" #include "moduleproviderinfo.h" #include #include #include namespace qbs { class Settings; class SetupProjectParameters; namespace Internal { class Logger; class ProgressObserver; class ScriptEngine; class QBS_AUTOTEST_EXPORT Loader { public: Loader(ScriptEngine *engine, const Logger &logger); void setProgressObserver(ProgressObserver *observer); void setSearchPaths(const QStringList &searchPaths); void setOldProjectProbes(const std::vector &oldProbes); void setOldProductProbes(const QHash> &oldProbes); void setLastResolveTime(const FileTime &time) { m_lastResolveTime = time; } void setStoredProfiles(const QVariantMap &profiles); void setStoredModuleProviderInfo(const ModuleProviderInfoList &providerInfo); TopLevelProjectPtr loadProject(const SetupProjectParameters ¶meters); static void setupProjectFilePath(SetupProjectParameters ¶meters); private: Logger m_logger; ProgressObserver *m_progressObserver; ScriptEngine * const m_engine; QStringList m_searchPaths; std::vector m_oldProjectProbes; QHash> m_oldProductProbes; ModuleProviderInfoList m_storedModuleProviderInfo; QVariantMap m_storedProfiles; FileTime m_lastResolveTime; }; } // namespace Internal } // namespace qbs #endif // QBS_LOADER_H qbs-src-1.13.1/src/lib/corelib/language/moduleloader.cpp000066400000000000000000005462751347155106100231140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "moduleloader.h" #include "builtindeclarations.h" #include "evaluator.h" #include "filecontext.h" #include "item.h" #include "itemreader.h" #include "language.h" #include "modulemerger.h" #include "qualifiedid.h" #include "scriptengine.h" #include "value.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static QString shadowProductPrefix() { return QStringLiteral("__shadow__"); } static void handlePropertyError(const ErrorInfo &error, const SetupProjectParameters ¶ms, Logger &logger) { if (params.propertyCheckingMode() == ErrorHandlingMode::Strict) throw error; logger.printWarning(error); } class ModuleLoader::ItemModuleList : public QList {}; static QString probeGlobalId(Item *probe) { QString id; for (Item *obj = probe; obj; obj = obj->prototype()) { if (!obj->id().isEmpty()) { id = obj->id(); break; } } if (id.isEmpty()) return {}; QBS_CHECK(probe->file()); return id + QLatin1Char('_') + probe->file()->filePath(); } class ModuleLoader::ProductSortByDependencies { public: ProductSortByDependencies(TopLevelProjectContext &tlp) : m_tlp(tlp) { } void apply() { QHash> productsMap; QList allProducts; for (ProjectContext * const projectContext : qAsConst(m_tlp.projects)) { for (auto &product : projectContext->products) { allProducts.push_back(&product); productsMap[product.name].push_back(&product); } } Set allDependencies; for (auto productContext : qAsConst(allProducts)) { auto &productDependencies = m_dependencyMap[productContext]; for (const auto &dep : qAsConst(productContext->info.usedProducts)) { QBS_CHECK(!dep.name.isEmpty()); const auto &deps = productsMap.value(dep.name); if (dep.profile == StringConstants::star()) { QBS_CHECK(!deps.empty()); for (ProductContext *depProduct : deps) { if (depProduct == productContext) continue; productDependencies.push_back(depProduct); allDependencies << depProduct; } } else { auto it = std::find_if(deps.begin(), deps.end(), [&dep] (ProductContext *p) { return p->multiplexConfigurationId == dep.multiplexConfigurationId; }); if (it == deps.end()) { QBS_CHECK(!productContext->multiplexConfigurationId.isEmpty()); const QString productName = ResolvedProduct::fullDisplayName( productContext->name, productContext->multiplexConfigurationId); const QString depName = ResolvedProduct::fullDisplayName( dep.name, dep.multiplexConfigurationId); throw ErrorInfo(Tr::tr("Dependency from product '%1' to product '%2' not " "fulfilled.").arg(productName, depName), productContext->item->location()); } productDependencies.push_back(*it); allDependencies << *it; } } } const Set rootProducts = Set::fromList(allProducts) - allDependencies; for (ProductContext * const rootProduct : rootProducts) traverse(rootProduct); if (m_sortedProducts.size() < allProducts.size()) { for (auto const product : qAsConst(allProducts)) { QList path; findCycle(product, path); } } QBS_CHECK(m_sortedProducts.size() == allProducts.size()); } // No product at position i has dependencies to a product at position j > i. const QList &sortedProducts() const { return m_sortedProducts; } private: void traverse(ModuleLoader::ProductContext *product) { if (!m_seenProducts.insert(product).second) return; for (const auto &dependency : m_dependencyMap.value(product)) traverse(dependency); m_sortedProducts << product; } void findCycle(ModuleLoader::ProductContext *product, QList &path) { if (path.contains(product)) { ErrorInfo error(Tr::tr("Cyclic dependencies detected.")); for (const auto * const p : path) error.append(p->name, p->item->location()); error.append(product->name, product->item->location()); throw error; } path << product; for (auto const dep : m_dependencyMap.value(product)) findCycle(dep, path); path.removeLast(); } TopLevelProjectContext &m_tlp; QHash> m_dependencyMap; Set m_seenProducts; QList m_sortedProducts; }; class SearchPathsManager { public: SearchPathsManager(ItemReader *itemReader, const QStringList &extraSearchPaths) : m_itemReader(itemReader) { m_itemReader->pushExtraSearchPaths(extraSearchPaths); } ~SearchPathsManager() { m_itemReader->popExtraSearchPaths(); } private: ItemReader * const m_itemReader; }; ModuleLoader::ModuleLoader(Evaluator *evaluator, Logger &logger) : m_pool(nullptr) , m_logger(logger) , m_progressObserver(nullptr) , m_reader(new ItemReader(logger)) , m_evaluator(evaluator) { } ModuleLoader::~ModuleLoader() { delete m_reader; } void ModuleLoader::setProgressObserver(ProgressObserver *progressObserver) { m_progressObserver = progressObserver; } void ModuleLoader::setSearchPaths(const QStringList &searchPaths) { m_reader->setSearchPaths(searchPaths); qCDebug(lcModuleLoader) << "initial search paths:" << searchPaths; } void ModuleLoader::setOldProjectProbes(const std::vector &oldProbes) { m_oldProjectProbes.clear(); for (const ProbeConstPtr& probe : oldProbes) m_oldProjectProbes[probe->globalId()] << probe; } void ModuleLoader::setOldProductProbes(const QHash> &oldProbes) { m_oldProductProbes = oldProbes; } void ModuleLoader::setStoredProfiles(const QVariantMap &profiles) { m_storedProfiles = profiles; } void ModuleLoader::setStoredModuleProviderInfo(const ModuleProviderInfoList &moduleProviderInfo) { m_moduleProviderInfo = moduleProviderInfo; } ModuleLoaderResult ModuleLoader::load(const SetupProjectParameters ¶meters) { TimedActivityLogger moduleLoaderTimer(m_logger, Tr::tr("ModuleLoader"), parameters.logElapsedTime()); qCDebug(lcModuleLoader) << "load" << parameters.projectFilePath(); m_parameters = parameters; m_modulePrototypes.clear(); m_modulePrototypeEnabledInfo.clear(); m_parameterDeclarations.clear(); m_disabledItems.clear(); m_reader->clearExtraSearchPathsStack(); m_reader->setEnableTiming(parameters.logElapsedTime()); m_elapsedTimeProbes = m_elapsedTimePrepareProducts = m_elapsedTimeHandleProducts = m_elapsedTimeProductDependencies = m_elapsedTimeTransitiveDependencies = m_elapsedTimePropertyChecking = 0; m_elapsedTimeProbes = 0; m_probesEncountered = m_probesRun = m_probesCachedCurrent = m_probesCachedOld = 0; m_settings.reset(new Settings(parameters.settingsDirectory())); for (const QString &key : m_parameters.overriddenValues().keys()) { static const QStringList prefixes({ StringConstants::projectPrefix(), QStringLiteral("projects"), QStringLiteral("products"), QStringLiteral("modules"), StringConstants::moduleProviders(), StringConstants::qbsModule()}); bool ok = false; for (const auto &prefix : prefixes) { if (key.startsWith(prefix + QLatin1Char('.'))) { ok = true; break; } } if (ok) { collectNameFromOverride(key); continue; } ErrorInfo e(Tr::tr("Property override key '%1' not understood.").arg(key)); e.append(Tr::tr("Please use one of the following:")); e.append(QLatin1Char('\t') + Tr::tr("projects..:value")); e.append(QLatin1Char('\t') + Tr::tr("products..:value")); e.append(QLatin1Char('\t') + Tr::tr("modules..:value")); e.append(QLatin1Char('\t') + Tr::tr("products..." ":value")); e.append(QLatin1Char('\t') + Tr::tr("moduleProviders.." ":value")); handlePropertyError(e, m_parameters, m_logger); } ModuleLoaderResult result; result.profileConfigs = m_storedProfiles; m_pool = result.itemPool.get(); m_reader->setPool(m_pool); const QStringList topLevelSearchPaths = parameters.finalBuildConfigurationTree() .value(StringConstants::projectPrefix()).toMap() .value(StringConstants::qbsSearchPathsProperty()).toStringList(); Item *root; { SearchPathsManager searchPathsManager(m_reader, topLevelSearchPaths); root = loadItemFromFile(parameters.projectFilePath(), CodeLocation()); if (!root) return ModuleLoaderResult(); } switch (root->type()) { case ItemType::Product: root = wrapInProjectIfNecessary(root); break; case ItemType::Project: break; default: throw ErrorInfo(Tr::tr("The top-level item must be of type 'Project' or 'Product', but it" " is of type '%1'.").arg(root->typeName()), root->location()); } const QString buildDirectory = TopLevelProject::deriveBuildDirectory(parameters.buildRoot(), TopLevelProject::deriveId(parameters.finalBuildConfigurationTree())); root->setProperty(StringConstants::sourceDirectoryProperty(), VariantValue::create(QFileInfo(root->file()->filePath()).absolutePath())); root->setProperty(StringConstants::buildDirectoryProperty(), VariantValue::create(buildDirectory)); root->setProperty(StringConstants::profileProperty(), VariantValue::create(m_parameters.topLevelProfile())); handleTopLevelProject(&result, root, buildDirectory, Set() << QDir::cleanPath(parameters.projectFilePath())); result.root = root; result.qbsFiles = m_reader->filesRead() - m_tempQbsFiles; for (auto it = m_localProfiles.cbegin(); it != m_localProfiles.cend(); ++it) result.profileConfigs.remove(it.key()); printProfilingInfo(); return result; } class PropertyDeclarationCheck : public ValueHandler { const Set &m_disabledItems; Set m_handledItems; std::vector m_parentItems; Item *m_currentModuleInstance = nullptr; QualifiedId m_currentModuleName; QString m_currentName; SetupProjectParameters m_params; Logger &m_logger; public: PropertyDeclarationCheck(const Set &disabledItems, const SetupProjectParameters ¶ms, Logger &logger) : m_disabledItems(disabledItems) , m_params(params) , m_logger(logger) { } void operator()(Item *item) { handleItem(item); } private: void handle(JSSourceValue *value) override { if (!value->createdByPropertiesBlock()) { const ErrorInfo error(Tr::tr("Property '%1' is not declared.") .arg(m_currentName), value->location()); handlePropertyError(error, m_params, m_logger); } } void handle(ItemValue *value) override { if (checkItemValue(value)) handleItem(value->item()); } bool checkItemValue(ItemValue *value) { // TODO: Remove once QBS-1030 is fixed. if (parentItem()->type() == ItemType::Artifact) return false; if (parentItem()->type() == ItemType::Properties) return false; if (parentItem()->isOfTypeOrhasParentOfType(ItemType::Export)) { // Export item prototypes do not have instantiated modules. // The module instances are where the Export is used. QBS_ASSERT(m_currentModuleInstance, return false); auto hasCurrentModuleName = [this](const Item::Module &m) { return m.name == m_currentModuleName; }; if (any_of(m_currentModuleInstance->modules(), hasCurrentModuleName)) return true; } // TODO: We really should have a dedicated item type for "pre-instantiated" item values // and only use ModuleInstance for actual module instances. const bool itemIsModuleInstance = value->item()->type() == ItemType::ModuleInstance && value->item()->hasProperty(StringConstants::presentProperty()); if (!itemIsModuleInstance && value->item()->type() != ItemType::ModulePrefix && (!parentItem()->file() || !parentItem()->file()->idScope() || !parentItem()->file()->idScope()->hasProperty(m_currentName)) && !value->createdByPropertiesBlock()) { CodeLocation location = value->location(); for (int i = int(m_parentItems.size() - 1); !location.isValid() && i >= 0; --i) location = m_parentItems.at(i)->location(); const ErrorInfo error(Tr::tr("Item '%1' is not declared. " "Did you forget to add a Depends item?") .arg(m_currentModuleName.toString()), location); handlePropertyError(error, m_params, m_logger); return false; } return true; } void handleItem(Item *item) { if (!m_handledItems.insert(item).second) return; if (m_disabledItems.contains(item) || (item->type() == ItemType::ModuleInstance && !item->isPresentModule()) || item->type() == ItemType::Properties // The Properties child of a SubProject item is not a regular item. || item->type() == ItemType::PropertiesInSubProject) { return; } // If a module was found but its validate script failed, only the canonical // module instance will have the "non-present" flag set, so we need to locate it. if (item->type() == ItemType::ModuleInstance) { const Item *productItem = nullptr; for (auto it = m_parentItems.rbegin(); it != m_parentItems.rend(); ++it) { if ((*it)->type() == ItemType::Product) { productItem = *it; break; } } if (productItem) { for (const Item::Module &m : productItem->modules()) { if (m.name == m_currentModuleName) { if (!m.item->isPresentModule()) return; break; } } } } m_parentItems.push_back(item); for (Item::PropertyMap::const_iterator it = item->properties().constBegin(); it != item->properties().constEnd(); ++it) { if (item->type() == ItemType::Product && it.key() == StringConstants::moduleProviders() && it.value()->type() == Value::ItemValueType) continue; const PropertyDeclaration decl = item->propertyDeclaration(it.key()); if (decl.isValid()) { if (!decl.isDeprecated()) continue; const DeprecationInfo &di = decl.deprecationInfo(); QString message; bool warningOnly; if (decl.isExpired()) { message = Tr::tr("The property '%1' can no longer be used. " "It was removed in Qbs %2.") .arg(decl.name(), di.removalVersion().toString()); warningOnly = false; } else { message = Tr::tr("The property '%1' is deprecated and will be removed " "in Qbs %2.").arg(decl.name(), di.removalVersion().toString()); warningOnly = true; } ErrorInfo error(message, it.value()->location()); if (!di.additionalUserInfo().isEmpty()) error.append(di.additionalUserInfo()); if (warningOnly) m_logger.printWarning(error); else handlePropertyError(error, m_params, m_logger); continue; } m_currentName = it.key(); const QualifiedId oldModuleName = m_currentModuleName; if (parentItem()->type() != ItemType::ModulePrefix) m_currentModuleName.clear(); m_currentModuleName.push_back(m_currentName); it.value()->apply(this); m_currentModuleName = oldModuleName; } m_parentItems.pop_back(); for (Item * const child : item->children()) { switch (child->type()) { case ItemType::Export: case ItemType::Depends: case ItemType::Parameter: case ItemType::Parameters: break; case ItemType::Group: if (item->type() == ItemType::Module || item->type() == ItemType::ModuleInstance) break; Q_FALLTHROUGH(); default: handleItem(child); } } // Properties that don't refer to an existing module with a matching Depends item // only exist in the prototype of an Export item, not in the instance. // Example 1 - setting a property of an unknown module: Export { abc.def: true } // Example 2 - setting a non-existing Export property: Export { blubb: true } if (item->type() == ItemType::ModuleInstance && item->prototype()) { Item *oldInstance = m_currentModuleInstance; m_currentModuleInstance = item; handleItem(item->prototype()); m_currentModuleInstance = oldInstance; } } void handle(VariantValue *) override { /* only created internally - no need to check */ } Item *parentItem() const { return m_parentItems.back(); } }; void ModuleLoader::handleTopLevelProject(ModuleLoaderResult *loadResult, Item *projectItem, const QString &buildDirectory, const Set &referencedFilePaths) { TopLevelProjectContext tlp; tlp.buildDirectory = buildDirectory; handleProject(loadResult, &tlp, projectItem, referencedFilePaths); checkProjectNamesInOverrides(tlp); collectProductsByName(tlp); checkProductNamesInOverrides(); adjustDependenciesForMultiplexing(tlp); m_dependencyResolvingPass = 1; for (ProjectContext * const projectContext : qAsConst(tlp.projects)) { m_reader->setExtraSearchPathsStack(projectContext->searchPathsStack); for (ProductContext &productContext : projectContext->products) { try { setupProductDependencies(&productContext, Set()); } catch (const ErrorInfo &err) { if (productContext.name.isEmpty()) throw err; handleProductError(err, &productContext); } for (std::size_t i = 0; i < productContext.newlyAddedModuleProviderSearchPaths.size(); ++i) m_reader->popExtraSearchPaths(); productContext.newlyAddedModuleProviderSearchPaths.clear(); } } if (!m_productsWithDeferredDependsItems.empty() || !m_exportsWithDeferredDependsItems.empty()) { collectProductsByType(tlp); m_dependencyResolvingPass = 2; // Doing the normalization for the Export items themselves (as opposed to doing it only // for the corresponding module instances) serves two purposes: // (1) It makes recursive use of Depends.productTypes via Export items work; otherwise, // we'd need an additional dependency resolving pass for every export level. // (2) The "expanded" Depends items are available to the Exporter.qbs module. for (Item * const exportItem : m_exportsWithDeferredDependsItems) normalizeDependencies(nullptr, DeferredDependsContext(nullptr, exportItem)); for (const auto &deferredDependsData : m_productsWithDeferredDependsItems) { ProductContext * const productContext = deferredDependsData.first; m_reader->setExtraSearchPathsStack(productContext->project->searchPathsStack); try { setupProductDependencies(productContext, deferredDependsData.second); } catch (const ErrorInfo &err) { handleProductError(err, productContext); } } } ProductSortByDependencies productSorter(tlp); productSorter.apply(); for (ProductContext * const p : productSorter.sortedProducts()) { try { handleProduct(p); if (p->name.startsWith(shadowProductPrefix())) tlp.probes << p->info.probes; } catch (const ErrorInfo &err) { handleProductError(err, p); } } loadResult->projectProbes = tlp.probes; loadResult->moduleProviderInfo = m_moduleProviderInfo; m_reader->clearExtraSearchPathsStack(); AccumulatingTimer timer(m_parameters.logElapsedTime() ? &m_elapsedTimePropertyChecking : nullptr); PropertyDeclarationCheck check(m_disabledItems, m_parameters, m_logger); check(projectItem); } void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, TopLevelProjectContext *topLevelProjectContext, Item *projectItem, const Set &referencedFilePaths) { QScopedPointer p(new ProjectContext); auto &projectContext = *p; projectContext.topLevelProject = topLevelProjectContext; projectContext.result = loadResult; ItemValuePtr itemValue = ItemValue::create(projectItem); projectContext.scope = Item::create(m_pool, ItemType::Scope); projectContext.scope->setFile(projectItem->file()); projectContext.scope->setProperty(StringConstants::projectVar(), itemValue); ProductContext dummyProductContext; dummyProductContext.project = &projectContext; dummyProductContext.moduleProperties = m_parameters.finalBuildConfigurationTree(); projectItem->addModule(loadBaseModule(&dummyProductContext, projectItem)); overrideItemProperties(projectItem, StringConstants::projectPrefix(), m_parameters.overriddenValuesTree()); projectContext.name = m_evaluator->stringValue(projectItem, StringConstants::nameProperty()); if (projectContext.name.isEmpty()) { projectContext.name = FileInfo::baseName(projectItem->location().filePath()); projectItem->setProperty(StringConstants::nameProperty(), VariantValue::create(projectContext.name)); } overrideItemProperties(projectItem, StringConstants::projectsOverridePrefix() + projectContext.name, m_parameters.overriddenValuesTree()); if (!checkItemCondition(projectItem)) { m_disabledProjects.insert(projectContext.name); return; } p.take(); topLevelProjectContext->projects.push_back(&projectContext); m_reader->pushExtraSearchPaths(readExtraSearchPaths(projectItem) << projectItem->file()->dirPath()); projectContext.searchPathsStack = m_reader->extraSearchPathsStack(); projectContext.item = projectItem; const QString minVersionStr = m_evaluator->stringValue(projectItem, StringConstants::minimumQbsVersionProperty(), QStringLiteral("1.3.0")); const Version minVersion = Version::fromString(minVersionStr); if (!minVersion.isValid()) { throw ErrorInfo(Tr::tr("The value '%1' of Project.minimumQbsVersion " "is not a valid version string.").arg(minVersionStr), projectItem->location()); } if (!m_qbsVersion.isValid()) m_qbsVersion = Version::fromString(QLatin1String(QBS_VERSION)); if (m_qbsVersion < minVersion) { throw ErrorInfo(Tr::tr("The project requires at least qbs version %1, but " "this is qbs version %2.").arg(minVersion.toString(), m_qbsVersion.toString())); } handleProfileItems(projectItem, &projectContext); QList multiplexedProducts; for (Item * const child : projectItem->children()) { child->setScope(projectContext.scope); if (child->type() == ItemType::Product) multiplexedProducts << multiplexProductItem(&dummyProductContext, child); } for (Item * const additionalProductItem : multiplexedProducts) Item::addChild(projectItem, additionalProductItem); resolveProbes(&dummyProductContext, projectItem); projectContext.topLevelProject->probes << dummyProductContext.info.probes; const QList originalChildren = projectItem->children(); for (Item * const child : originalChildren) { switch (child->type()) { case ItemType::Product: prepareProduct(&projectContext, child); break; case ItemType::SubProject: handleSubProject(&projectContext, child, referencedFilePaths); break; case ItemType::Project: copyProperties(projectItem, child); handleProject(loadResult, topLevelProjectContext, child, referencedFilePaths); break; default: break; } } const QStringList refs = m_evaluator->stringListValue( projectItem, StringConstants::referencesProperty()); const CodeLocation referencingLocation = projectItem->property(StringConstants::referencesProperty())->location(); QList additionalProjectChildren; for (const QString &filePath : refs) { try { additionalProjectChildren << loadReferencedFile(filePath, referencingLocation, referencedFilePaths, dummyProductContext); } catch (const ErrorInfo &error) { if (m_parameters.productErrorMode() == ErrorHandlingMode::Strict) throw; m_logger.printWarning(error); } } for (Item * const subItem : qAsConst(additionalProjectChildren)) { Item::addChild(projectContext.item, subItem); switch (subItem->type()) { case ItemType::Product: prepareProduct(&projectContext, subItem); break; case ItemType::Project: copyProperties(projectItem, subItem); handleProject(loadResult, topLevelProjectContext, subItem, Set(referencedFilePaths) << subItem->file()->filePath()); break; default: break; } } m_reader->popExtraSearchPaths(); } QString ModuleLoader::MultiplexInfo::toIdString(size_t row) const { const auto &mprow = table.at(row); QVariantMap multiplexConfiguration; for (size_t column = 0; column < mprow.size(); ++column) { const QString &propertyName = properties.at(column); const VariantValuePtr &mpvalue = mprow.at(column); multiplexConfiguration.insert(propertyName, mpvalue->value()); } return QString::fromUtf8(QJsonDocument::fromVariant(multiplexConfiguration) .toJson(QJsonDocument::Compact) .toBase64()); } void qbs::Internal::ModuleLoader::ModuleLoader::dump(const ModuleLoader::MultiplexInfo &mpi) { QStringList header; for (const auto &str : mpi.properties) header << str; qDebug() << header; for (const auto &row : mpi.table) { QVariantList values; for (const auto &elem : row) { values << elem->value(); } qDebug() << values; } } ModuleLoader::MultiplexTable ModuleLoader::combine(const MultiplexTable &table, const MultiplexRow &values) { MultiplexTable result; if (table.empty()) { result.resize(values.size()); for (size_t i = 0; i < values.size(); ++i) { MultiplexRow row; row.resize(1); row[0] = values.at(i); result[i] = row; } } else { for (const auto &row : table) { for (const auto &value : values) { MultiplexRow newRow = row; newRow.push_back(value); result.push_back(newRow); } } } return result; } ModuleLoader::MultiplexInfo ModuleLoader::extractMultiplexInfo(Item *productItem, Item *qbsModuleItem) { static const QString mpmKey = QStringLiteral("multiplexMap"); const QScriptValue multiplexMap = m_evaluator->value(qbsModuleItem, mpmKey); QStringList multiplexByQbsProperties = m_evaluator->stringListValue( productItem, StringConstants::multiplexByQbsPropertiesProperty()); MultiplexInfo multiplexInfo; multiplexInfo.aggregate = m_evaluator->boolValue( productItem, StringConstants::aggregateProperty()); const QString multiplexedType = m_evaluator->stringValue( productItem, StringConstants::multiplexedTypeProperty()); if (!multiplexedType.isEmpty()) multiplexInfo.multiplexedType = VariantValue::create(multiplexedType); Set uniqueMultiplexByQbsProperties; for (const QString &key : multiplexByQbsProperties) { const QString mappedKey = multiplexMap.property(key).toString(); if (mappedKey.isEmpty()) throw ErrorInfo(Tr::tr("There is no entry for '%1' in 'qbs.multiplexMap'.").arg(key)); if (!uniqueMultiplexByQbsProperties.insert(mappedKey).second) { throw ErrorInfo(Tr::tr("Duplicate entry '%1' in Product.%2.") .arg(mappedKey, StringConstants::multiplexByQbsPropertiesProperty()), productItem->location()); } const QScriptValue arr = m_evaluator->value(qbsModuleItem, key); if (arr.isUndefined()) continue; if (!arr.isArray()) throw ErrorInfo(Tr::tr("Property '%1' must be an array.").arg(key)); const quint32 arrlen = arr.property(StringConstants::lengthProperty()).toUInt32(); if (arrlen == 0) continue; MultiplexRow mprow; mprow.resize(arrlen); Set entriesForKey; for (quint32 i = 0; i < arrlen; ++i) { const QVariant value = arr.property(i).toVariant(); if (!entriesForKey.insert(value).second) { throw ErrorInfo(Tr::tr("Duplicate entry '%1' in qbs.%2.") .arg(value.toString(), key), productItem->location()); } mprow[i] = VariantValue::create(value); } multiplexInfo.table = combine(multiplexInfo.table, mprow); multiplexInfo.properties.push_back(mappedKey); } return multiplexInfo; } template T ModuleLoader::callWithTemporaryBaseModule(ProductContext *productContext, const F &func) { // Temporarily attach the qbs module here, in case we need to access one of its properties // to evaluate properties. const QString &qbsKey = StringConstants::qbsModule(); Item *productItem = productContext->item; ValuePtr qbsValue = productItem->property(qbsKey); // Retrieve now to restore later. if (qbsValue) qbsValue = qbsValue->clone(); const Item::Module qbsModule = loadBaseModule(productContext, productItem); productItem->addModule(qbsModule); auto &&result = func(qbsModule); // "Unload" the qbs module again. if (qbsValue) productItem->setProperty(qbsKey, qbsValue); else productItem->removeProperty(qbsKey); productItem->removeModules(); return std::forward(result); } QList ModuleLoader::multiplexProductItem(ProductContext *dummyContext, Item *productItem) { QString productName; dummyContext->item = productItem; auto extractMultiplexInfoFromProduct = [this, productItem, &productName](const Item::Module &qbsModule) { // Overriding the product item properties must be done here already, because multiplexing // properties might depend on product properties. const QString &nameKey = StringConstants::nameProperty(); productName = m_evaluator->stringValue(productItem, nameKey); if (productName.isEmpty()) { productName = FileInfo::completeBaseName(productItem->file()->filePath()); productItem->setProperty(nameKey, VariantValue::create(productName)); } overrideItemProperties(productItem, StringConstants::productsOverridePrefix() + productName, m_parameters.overriddenValuesTree()); return extractMultiplexInfo(productItem, qbsModule.item); }; const MultiplexInfo multiplexInfo = callWithTemporaryBaseModule(dummyContext, extractMultiplexInfoFromProduct); if (multiplexInfo.table.size() > 1) productItem->setProperty(StringConstants::multiplexedProperty(), VariantValue::trueValue()); VariantValuePtr productNameValue = VariantValue::create(productName); Item *aggregator = multiplexInfo.aggregate ? productItem->clone() : nullptr; QList additionalProductItems; std::vector multiplexConfigurationIdValues; for (size_t row = 0; row < multiplexInfo.table.size(); ++row) { Item *item = productItem; const auto &mprow = multiplexInfo.table.at(row); QBS_CHECK(mprow.size() == multiplexInfo.properties.size()); if (row > 0) { item = productItem->clone(); additionalProductItems.push_back(item); } const QString multiplexConfigurationId = multiplexInfo.toIdString(row); const VariantValuePtr multiplexConfigurationIdValue = VariantValue::create(multiplexConfigurationId); if (multiplexInfo.table.size() > 1 || aggregator) { multiplexConfigurationIdValues.push_back(multiplexConfigurationIdValue); item->setProperty(StringConstants::multiplexConfigurationIdProperty(), multiplexConfigurationIdValue); } if (multiplexInfo.multiplexedType) item->setProperty(StringConstants::typeProperty(), multiplexInfo.multiplexedType); for (size_t column = 0; column < mprow.size(); ++column) { Item *qbsItem = moduleInstanceItem(item, StringConstants::qbsModule()); const QString &propertyName = multiplexInfo.properties.at(column); const VariantValuePtr &mpvalue = mprow.at(column); qbsItem->setProperty(propertyName, mpvalue); } } if (aggregator) { additionalProductItems << aggregator; // Add dependencies to all multiplexed instances. for (const auto &v : multiplexConfigurationIdValues) { Item *dependsItem = Item::create(aggregator->pool(), ItemType::Depends); dependsItem->setProperty(StringConstants::nameProperty(), productNameValue); dependsItem->setProperty(StringConstants::multiplexConfigurationIdProperty(), v); dependsItem->setProperty(StringConstants::profilesProperty(), VariantValue::create(QStringList())); Item::addChild(aggregator, dependsItem); } } return additionalProductItems; } void ModuleLoader::normalizeDependencies(ProductContext *product, const DeferredDependsContext &dependsContext) { std::vector dependsItemsToAdd; std::vector dependsItemsToRemove; std::vector deferredDependsItems; for (Item *dependsItem : dependsContext.parentItem->children()) { if (dependsItem->type() != ItemType::Depends) continue; bool productTypesIsSet; const FileTags productTypes = m_evaluator->fileTagsValue(dependsItem, StringConstants::productTypesProperty(), &productTypesIsSet); if (productTypesIsSet) { bool nameIsSet; m_evaluator->stringValue(dependsItem, StringConstants::nameProperty(), QString(), &nameIsSet); // The second condition is for the case where the dependency comes from an Export item // that has itself been normalized in the mean time. if (nameIsSet && !dependsItem->variantProperty(StringConstants::nameProperty())) { throw ErrorInfo(Tr::tr("The 'productTypes' and 'name' properties are mutually " "exclusive."), dependsItem->location()); } bool submodulesPropertySet; m_evaluator->stringListValue( dependsItem, StringConstants::submodulesProperty(), &submodulesPropertySet); if (submodulesPropertySet) { throw ErrorInfo(Tr::tr("The 'productTypes' and 'subModules' properties are " "mutually exclusive."), dependsItem->location()); } // We ignore the "limitToSubProject" property for dependencies from Export items, // because we cannot make it work consistently, as the importing product is not // yet known when normalizing via an Export item. const bool limitToSubProject = dependsContext.parentItem->type() == ItemType::Product && m_evaluator->boolValue(dependsItem, StringConstants::limitToSubProjectProperty()); static const auto hasSameSubProject = [](const ProductContext &product, const ProductContext &other) { for (const Item *otherParent = other.item->parent(); otherParent; otherParent = otherParent->parent()) { if (otherParent == product.item->parent()) return true; } return false; }; std::vector matchingProducts; for (const FileTag &typeTag : productTypes) { const auto range = m_productsByType.equal_range(typeTag); for (auto it = range.first; it != range.second; ++it) { if (it->second != product && (!product || it->second->name != product->name) && (!limitToSubProject || hasSameSubProject(*product, *it->second))) { matchingProducts.push_back(it->second); } } } if (matchingProducts.empty()) { qCDebug(lcModuleLoader) << "Depends.productTypes does not match anything." << dependsItem->location(); dependsItemsToRemove.push_back(dependsItem); continue; } if (dependsContext.parentItem->type() != ItemType::Export) deferredDependsItems.push_back(dependsItem); for (std::size_t i = 1; i < matchingProducts.size(); ++i) { Item * const dependsClone = dependsItem->clone(); dependsClone->setProperty(StringConstants::nameProperty(), VariantValue::create(matchingProducts.at(i)->name)); dependsItemsToAdd.push_back(dependsClone); if (dependsContext.parentItem->type() != ItemType::Export) deferredDependsItems.push_back(dependsClone); } dependsItem->setProperty(StringConstants::nameProperty(), VariantValue::create(matchingProducts.front()->name)); } } for (Item * const newDependsItem : dependsItemsToAdd) Item::addChild(dependsContext.parentItem, newDependsItem); for (Item * const dependsItem : dependsItemsToRemove) Item::removeChild(dependsContext.parentItem, dependsItem); if (!deferredDependsItems.empty()) { auto &allDeferredDependsItems = product->deferredDependsItems[dependsContext.exportingProductItem]; allDeferredDependsItems.insert(allDeferredDependsItems.end(), deferredDependsItems.cbegin(), deferredDependsItems.cend()); } } void ModuleLoader::adjustDependenciesForMultiplexing(const TopLevelProjectContext &tlp) { for (const ProjectContext * const project : tlp.projects) { for (const ProductContext &product : project->products) adjustDependenciesForMultiplexing(product); } } void ModuleLoader::adjustDependenciesForMultiplexing(const ModuleLoader::ProductContext &product) { for (Item *dependsItem : product.item->children()) { if (dependsItem->type() == ItemType::Depends) adjustDependenciesForMultiplexing(product, dependsItem); } } void ModuleLoader::adjustDependenciesForMultiplexing(const ProductContext &product, Item *dependsItem) { const QString name = m_evaluator->stringValue(dependsItem, StringConstants::nameProperty()); const bool productIsMultiplexed = !product.multiplexConfigurationId.isEmpty(); if (name == product.name) { QBS_CHECK(!productIsMultiplexed); // This product must be an aggregator. return; } bool profilesPropertyIsSet; const QStringList profiles = m_evaluator->stringListValue(dependsItem, StringConstants::profilesProperty(), &profilesPropertyIsSet); const auto productRange = m_productsByName.equal_range(name); std::vector dependencies; bool hasNonMultiplexedDependency = false; for (auto it = productRange.first; it != productRange.second; ++it) { if (!it->second->multiplexConfigurationId.isEmpty()) { dependencies.push_back(it->second); if (productIsMultiplexed && !profilesPropertyIsSet) break; } else { hasNonMultiplexedDependency = true; break; } } // These are the allowed cases: // (1) Normal dependency with no multiplexing whatsoever. // (2) Both product and dependency are multiplexed. // (3) The product is not multiplexed, but the dependency is. // (3a) The dependency has an aggregator. We want to depend on the aggregator. // (3b) The dependency does not have an aggregator. We want to depend on all the // multiplexed variants. // (4) The product is multiplexed, but the dependency is not. This case is implicitly // handled, because we don't have to adapt any Depends items. // (5) The product is a "shadow product". In that case, we know which product // it should have a dependency on, and we make sure we depend on that. // (1) and (3a) if (!productIsMultiplexed && hasNonMultiplexedDependency) return; QStringList multiplexIds; const ShadowProductInfo shadowProductInfo = getShadowProductInfo(product); const bool isShadowProduct = shadowProductInfo.first && shadowProductInfo.second == name; for (const ProductContext *dependency : dependencies) { const bool depMatchesShadowProduct = isShadowProduct && dependency->item == product.item->parent(); const QString depMultiplexId = dependency->multiplexConfigurationId; if (depMatchesShadowProduct) { // (5) dependsItem->setProperty(StringConstants::multiplexConfigurationIdsProperty(), VariantValue::create(depMultiplexId)); multiplexIds.clear(); break; } if (productIsMultiplexed && !profilesPropertyIsSet) { // (2) const ValuePtr &multiplexId = product.item->property( StringConstants::multiplexConfigurationIdProperty()); dependsItem->setProperty(StringConstants::multiplexConfigurationIdsProperty(), multiplexId); break; } // (3b) (or (2) if Depends.profiles is set). const bool profileMatch = !profilesPropertyIsSet || profiles.empty() || profiles.contains(dependency->profileName); if (profileMatch) multiplexIds << depMultiplexId; } if (!multiplexIds.empty()) { dependsItem->setProperty(StringConstants::multiplexConfigurationIdsProperty(), VariantValue::create(multiplexIds)); } } void ModuleLoader::prepareProduct(ProjectContext *projectContext, Item *productItem) { AccumulatingTimer timer(m_parameters.logElapsedTime() ? &m_elapsedTimePrepareProducts : nullptr); checkCancelation(); qCDebug(lcModuleLoader) << "prepareProduct" << productItem->file()->filePath(); ProductContext productContext; productContext.item = productItem; productContext.project = projectContext; productContext.name = m_evaluator->stringValue(productItem, StringConstants::nameProperty()); QBS_CHECK(!productContext.name.isEmpty()); const ItemValueConstPtr qbsItemValue = productItem->itemProperty(StringConstants::qbsModule()); if (!!qbsItemValue && qbsItemValue->item()->hasProperty(StringConstants::profileProperty())) { qbsItemValue->item()->setProperty(StringConstants::nameProperty(), VariantValue::create(StringConstants::nameProperty())); auto evaluateQbsProfileProperty = [this](const Item::Module &qbsModule) { return m_evaluator->stringValue(qbsModule.item, StringConstants::profileProperty(), QString()); }; productContext.profileName = callWithTemporaryBaseModule(&productContext, evaluateQbsProfileProperty); } else { productContext.profileName = m_parameters.topLevelProfile(); } productContext.multiplexConfigurationId = m_evaluator->stringValue( productItem, StringConstants::multiplexConfigurationIdProperty()); QBS_CHECK(!productContext.profileName.isEmpty()); const auto it = projectContext->result->profileConfigs.constFind(productContext.profileName); if (it == projectContext->result->profileConfigs.constEnd()) { const Profile profile(productContext.profileName, m_settings.get(), m_localProfiles); if (!profile.exists()) { ErrorInfo error(Tr::tr("Profile '%1' does not exist.").arg(profile.name()), productItem->location()); handleProductError(error, &productContext); return; } const QVariantMap buildConfig = SetupProjectParameters::expandedBuildConfiguration( profile, m_parameters.configurationName()); productContext.moduleProperties = SetupProjectParameters::finalBuildConfigurationTree( buildConfig, m_parameters.overriddenValues()); projectContext->result->profileConfigs.insert(productContext.profileName, productContext.moduleProperties); } else { productContext.moduleProperties = it.value().toMap(); } initProductProperties(productContext); ItemValuePtr itemValue = ItemValue::create(productItem); productContext.scope = Item::create(m_pool, ItemType::Scope); productContext.scope->setProperty(StringConstants::productVar(), itemValue); productContext.scope->setFile(productItem->file()); productContext.scope->setScope(productContext.project->scope); const bool hasExportItems = mergeExportItems(productContext); setScopeForDescendants(productItem, productContext.scope); projectContext->products.push_back(productContext); if (!hasExportItems || getShadowProductInfo(productContext).first) return; // This "shadow product" exists only to pull in a dependency on the actual product // and nothing else, thus providing us with the pure environment that we need to // evaluate the product's exported properties in isolation in the project resolver. Item * const importer = Item::create(productItem->pool(), ItemType::Product); importer->setProperty(QStringLiteral("name"), VariantValue::create(shadowProductPrefix() + productContext.name)); importer->setFile(productItem->file()); importer->setLocation(productItem->location()); importer->setScope(projectContext->scope); importer->setupForBuiltinType(m_logger); Item * const dependsItem = Item::create(productItem->pool(), ItemType::Depends); dependsItem->setProperty(QStringLiteral("name"), VariantValue::create(productContext.name)); dependsItem->setProperty(QStringLiteral("required"), VariantValue::create(false)); dependsItem->setFile(importer->file()); dependsItem->setLocation(importer->location()); dependsItem->setupForBuiltinType(m_logger); Item::addChild(importer, dependsItem); Item::addChild(productItem, importer); prepareProduct(projectContext, importer); } void ModuleLoader::setupProductDependencies(ProductContext *productContext, const Set &deferredDependsContext) { if (m_dependencyResolvingPass == 2) { for (const DeferredDependsContext &ctx : deferredDependsContext) normalizeDependencies(productContext, ctx); for (const auto &deferralData : productContext->deferredDependsItems) { for (Item * const deferredDependsItem : deferralData.second) { // Dependencies from Export items are handled in addProductModuleDependencies(). if (deferredDependsItem->parent() == productContext->item) adjustDependenciesForMultiplexing(*productContext, deferredDependsItem); } } } AccumulatingTimer timer(m_parameters.logElapsedTime() ? &m_elapsedTimeProductDependencies : nullptr); checkCancelation(); Item *item = productContext->item; qCDebug(lcModuleLoader) << "setupProductDependencies" << productContext->name << productContext->item->location(); if (m_dependencyResolvingPass == 1) setSearchPathsForProduct(productContext); SearchPathsManager searchPathsManager(m_reader, productContext->searchPaths); DependsContext dependsContext; dependsContext.product = productContext; dependsContext.productDependencies = &productContext->info.usedProducts; resolveDependencies(&dependsContext, item, productContext); if (m_dependencyResolvingPass == 2 || !containsKey(m_productsWithDeferredDependsItems, productContext)) { addProductModuleDependencies(productContext); } productContext->project->result->productInfos.insert(item, productContext->info); } // Leaf modules first. // TODO: Can this be merged with addTransitiveDependencies? Looks suspiciously similar. void ModuleLoader::createSortedModuleList(const Item::Module &parentModule, Item::Modules &modules) { if (std::find_if(modules.cbegin(), modules.cend(), [parentModule](const Item::Module &m) { return m.name == parentModule.name;}) != modules.cend()) { return; } for (const Item::Module &dep : parentModule.item->modules()) createSortedModuleList(dep, modules); modules.push_back(parentModule); return; } Item::Modules ModuleLoader::modulesSortedByDependency(const Item *productItem) { QBS_CHECK(productItem->type() == ItemType::Product); Item::Modules sortedModules; const Item::Modules &unsortedModules = productItem->modules(); for (const Item::Module &module : unsortedModules) createSortedModuleList(module, sortedModules); QBS_CHECK(sortedModules.size() == unsortedModules.size()); // Make sure the top-level items stay the same. for (Item::Module &s : sortedModules) { for (const Item::Module &u : unsortedModules) { if (s.name == u.name) { s.item = u.item; break; } } } return sortedModules; } template bool insertIntoSet(Set &set, const T &value) { const auto insertionResult = set.insert(value); return insertionResult.second; } void ModuleLoader::setupReverseModuleDependencies(const Item::Module &module, ModuleDependencies &deps, QualifiedIdSet &seenModules) { if (!insertIntoSet(seenModules, module.name)) return; for (const Item::Module &m : module.item->modules()) { deps[m.name].insert(module.name); setupReverseModuleDependencies(m, deps, seenModules); } } ModuleLoader::ModuleDependencies ModuleLoader::setupReverseModuleDependencies(const Item *product) { ModuleDependencies deps; QualifiedIdSet seenModules; for (const Item::Module &m : product->modules()) setupReverseModuleDependencies(m, deps, seenModules); return deps; } void ModuleLoader::handleProduct(ModuleLoader::ProductContext *productContext) { AccumulatingTimer timer(m_parameters.logElapsedTime() ? &m_elapsedTimeHandleProducts : nullptr); if (productContext->info.delayedError.hasError()) return; Item * const item = productContext->item; m_reader->setExtraSearchPathsStack(productContext->project->searchPathsStack); SearchPathsManager searchPathsManager(m_reader, productContext->searchPaths); addTransitiveDependencies(productContext); // It is important that dependent modules are merged after their dependency, because // the dependent module's merger potentially needs to replace module items that were // set by the dependency module's merger (namely, scopes of defining items; see // ModuleMerger::replaceItemInScopes()). Item::Modules topSortedModules = modulesSortedByDependency(item); for (Item::Module &module : topSortedModules) ModuleMerger(m_logger, item, module).start(); // Re-sort the modules by name. This is more stable; see QBS-818. // The list of modules in the product now has the same order as before, // only the items have been replaced by their merged counterparts. Item::Modules lexicographicallySortedModules = topSortedModules; std::sort(lexicographicallySortedModules.begin(), lexicographicallySortedModules.end()); item->setModules(lexicographicallySortedModules); for (const Item::Module &module : topSortedModules) { if (!module.item->isPresentModule()) continue; try { resolveProbes(productContext, module.item); if (module.versionRange.minimum.isValid() || module.versionRange.maximum.isValid()) { if (module.versionRange.maximum.isValid() && module.versionRange.minimum >= module.versionRange.maximum) { throw ErrorInfo(Tr::tr("Impossible version constraint [%1,%2) set for module " "'%3'").arg(module.versionRange.minimum.toString(), module.versionRange.maximum.toString(), module.name.toString())); } const Version moduleVersion = Version::fromString( m_evaluator->stringValue(module.item, StringConstants::versionProperty())); if (moduleVersion < module.versionRange.minimum) { throw ErrorInfo(Tr::tr("Module '%1' has version %2, but it needs to be " "at least %3.").arg(module.name.toString(), moduleVersion.toString(), module.versionRange.minimum.toString())); } if (module.versionRange.maximum.isValid() && moduleVersion >= module.versionRange.maximum) { throw ErrorInfo(Tr::tr("Module '%1' has version %2, but it needs to be " "lower than %3.").arg(module.name.toString(), moduleVersion.toString(), module.versionRange.maximum.toString())); } } } catch (const ErrorInfo &error) { handleModuleSetupError(productContext, module, error); if (productContext->info.delayedError.hasError()) return; } } resolveProbes(productContext, item); // Module validation must happen in an extra pass, after all Probes have been resolved. EvalCacheEnabler cacheEnabler(m_evaluator); for (const Item::Module &module : topSortedModules) { if (!module.item->isPresentModule()) continue; try { m_evaluator->boolValue(module.item, StringConstants::validateProperty()); } catch (const ErrorInfo &error) { handleModuleSetupError(productContext, module, error); if (productContext->info.delayedError.hasError()) return; } } if (!checkItemCondition(item)) { const auto &exportsData = productContext->project->topLevelProject->productModules; for (auto it = exportsData.find(productContext->name); it != exportsData.end() && it.key() == productContext->name; ++it) { if (it.value().multiplexId == productContext->multiplexConfigurationId) { createNonPresentModule(productContext->name, QStringLiteral("disabled"), it.value().exportItem); break; } } } checkDependencyParameterDeclarations(productContext); copyGroupsFromModulesToProduct(*productContext); ModuleDependencies reverseModuleDeps; for (Item * const child : item->children()) { if (child->type() == ItemType::Group) { if (reverseModuleDeps.empty()) reverseModuleDeps = setupReverseModuleDependencies(item); handleGroup(productContext, child, reverseModuleDeps); } } productContext->project->result->productInfos.insert(item, productContext->info); } static Item *rootPrototype(Item *item) { Item *modulePrototype = item; while (modulePrototype->prototype()) modulePrototype = modulePrototype->prototype(); return modulePrototype; } class DependencyParameterDeclarationCheck { public: DependencyParameterDeclarationCheck(const QString &productName, const Item *productItem, const QHash &decls) : m_productName(productName), m_productItem(productItem), m_parameterDeclarations(decls) { } void operator()(const QVariantMap ¶meters) const { check(parameters, QualifiedId()); } private: void check(const QVariantMap ¶meters, const QualifiedId &moduleName) const { for (auto it = parameters.begin(); it != parameters.end(); ++it) { if (it.value().type() == QVariant::Map) { check(it.value().toMap(), QualifiedId(moduleName) << it.key()); } else { const auto &deps = m_productItem->modules(); auto m = std::find_if(deps.begin(), deps.end(), [&moduleName] (const Item::Module &module) { return module.name == moduleName; }); if (m == deps.end()) { const QualifiedId fullName = QualifiedId(moduleName) << it.key(); throw ErrorInfo(Tr::tr("Cannot set parameter '%1', " "because '%2' does not have a dependency on '%3'.") .arg(fullName.toString(), m_productName, moduleName.toString()), m_productItem->location()); } auto decls = m_parameterDeclarations.value(rootPrototype(m->item)); if (!decls.contains(it.key())) { const QualifiedId fullName = QualifiedId(moduleName) << it.key(); throw ErrorInfo(Tr::tr("Parameter '%1' is not declared.") .arg(fullName.toString()), m_productItem->location()); } } } } bool moduleExists(const QualifiedId &name) const { const auto &deps = m_productItem->modules(); return any_of(deps, [&name](const Item::Module &module) { return module.name == name; }); } const QString &m_productName; const Item *m_productItem; const QHash &m_parameterDeclarations; }; void ModuleLoader::checkDependencyParameterDeclarations(const ProductContext *productContext) const { DependencyParameterDeclarationCheck dpdc(productContext->name, productContext->item, m_parameterDeclarations); for (const Item::Module &dep : productContext->item->modules()) { if (!dep.parameters.empty()) dpdc(dep.parameters); } } void ModuleLoader::handleModuleSetupError(ModuleLoader::ProductContext *productContext, const Item::Module &module, const ErrorInfo &error) { if (module.required) { handleProductError(error, productContext); } else { qCDebug(lcModuleLoader()) << "non-required module" << module.name.toString() << "found, but not usable in product" << productContext->name << error.toString(); createNonPresentModule(module.name.toString(), QStringLiteral("failed validation"), module.item); } } void ModuleLoader::initProductProperties(const ProductContext &product) { QString buildDir = ResolvedProduct::deriveBuildDirectoryName(product.name, product.multiplexConfigurationId); buildDir = FileInfo::resolvePath(product.project->topLevelProject->buildDirectory, buildDir); product.item->setProperty(StringConstants::buildDirectoryProperty(), VariantValue::create(buildDir)); const QString sourceDir = QFileInfo(product.item->file()->filePath()).absolutePath(); product.item->setProperty(StringConstants::sourceDirectoryProperty(), VariantValue::create(sourceDir)); } void ModuleLoader::handleSubProject(ModuleLoader::ProjectContext *projectContext, Item *projectItem, const Set &referencedFilePaths) { qCDebug(lcModuleLoader) << "handleSubProject" << projectItem->file()->filePath(); Item * const propertiesItem = projectItem->child(ItemType::PropertiesInSubProject); if (!checkItemCondition(projectItem)) return; if (propertiesItem) { propertiesItem->setScope(projectItem); if (!checkItemCondition(propertiesItem)) return; } Item *loadedItem; QString subProjectFilePath; try { const QString projectFileDirPath = FileInfo::path(projectItem->file()->filePath()); const QString relativeFilePath = m_evaluator->stringValue(projectItem, StringConstants::filePathProperty()); subProjectFilePath = FileInfo::resolvePath(projectFileDirPath, relativeFilePath); if (referencedFilePaths.contains(subProjectFilePath)) throw ErrorInfo(Tr::tr("Cycle detected while loading subproject file '%1'.") .arg(relativeFilePath), projectItem->location()); loadedItem = loadItemFromFile(subProjectFilePath, projectItem->location()); } catch (const ErrorInfo &error) { if (m_parameters.productErrorMode() == ErrorHandlingMode::Strict) throw; m_logger.printWarning(error); return; } loadedItem = wrapInProjectIfNecessary(loadedItem); const bool inheritProperties = m_evaluator->boolValue( projectItem, StringConstants::inheritPropertiesProperty()); if (inheritProperties) copyProperties(projectItem->parent(), loadedItem); if (propertiesItem) { const Item::PropertyMap &overriddenProperties = propertiesItem->properties(); for (Item::PropertyMap::ConstIterator it = overriddenProperties.constBegin(); it != overriddenProperties.constEnd(); ++it) { loadedItem->setProperty(it.key(), overriddenProperties.value(it.key())); } } Item::addChild(projectItem, loadedItem); projectItem->setScope(projectContext->scope); handleProject(projectContext->result, projectContext->topLevelProject, loadedItem, Set(referencedFilePaths) << subProjectFilePath); } QList ModuleLoader::loadReferencedFile(const QString &relativePath, const CodeLocation &referencingLocation, const Set &referencedFilePaths, ModuleLoader::ProductContext &dummyContext) { QString absReferencePath = FileInfo::resolvePath(FileInfo::path(referencingLocation.filePath()), relativePath); if (FileInfo(absReferencePath).isDir()) { QString qbsFilePath; QDirIterator dit(absReferencePath, StringConstants::qbsFileWildcards()); while (dit.hasNext()) { if (!qbsFilePath.isEmpty()) { throw ErrorInfo(Tr::tr("Referenced directory '%1' contains more than one " "qbs file.").arg(absReferencePath), referencingLocation); } qbsFilePath = dit.next(); } if (qbsFilePath.isEmpty()) { throw ErrorInfo(Tr::tr("Referenced directory '%1' does not contain a qbs file.") .arg(absReferencePath), referencingLocation); } absReferencePath = qbsFilePath; } if (referencedFilePaths.contains(absReferencePath)) throw ErrorInfo(Tr::tr("Cycle detected while referencing file '%1'.").arg(relativePath), referencingLocation); Item * const subItem = loadItemFromFile(absReferencePath, referencingLocation); if (subItem->type() != ItemType::Project && subItem->type() != ItemType::Product) { ErrorInfo error(Tr::tr("Item type should be 'Product' or 'Project', but is '%1'.") .arg(subItem->typeName())); error.append(Tr::tr("Item is defined here."), subItem->location()); error.append(Tr::tr("File is referenced here."), referencingLocation); throw error; } subItem->setScope(dummyContext.project->scope); subItem->setParent(dummyContext.project->item); QList loadedItems; loadedItems << subItem; if (subItem->type() == ItemType::Product) { handleProfileItems(subItem, dummyContext.project); loadedItems << multiplexProductItem(&dummyContext, subItem); } return loadedItems; } void ModuleLoader::handleGroup(ProductContext *productContext, Item *groupItem, const ModuleDependencies &reverseDepencencies) { checkCancelation(); propagateModulesFromParent(productContext, groupItem, reverseDepencencies); checkItemCondition(groupItem); for (Item * const child : groupItem->children()) { if (child->type() == ItemType::Group) handleGroup(productContext, child, reverseDepencencies); } } void ModuleLoader::handleAllPropertyOptionsItems(Item *item) { QList childItems = item->children(); auto childIt = childItems.begin(); while (childIt != childItems.end()) { Item * const child = *childIt; if (child->type() == ItemType::PropertyOptions) { handlePropertyOptions(child); childIt = childItems.erase(childIt); } else { handleAllPropertyOptionsItems(child); ++childIt; } } item->setChildren(childItems); } void ModuleLoader::handlePropertyOptions(Item *optionsItem) { const QString name = m_evaluator->stringValue(optionsItem, StringConstants::nameProperty()); if (name.isEmpty()) { throw ErrorInfo(Tr::tr("PropertyOptions item needs a name property"), optionsItem->location()); } const QString description = m_evaluator->stringValue( optionsItem, StringConstants::descriptionProperty()); const auto removalVersion = Version::fromString(m_evaluator->stringValue(optionsItem, StringConstants::removalVersionProperty())); PropertyDeclaration decl = optionsItem->parent()->propertyDeclaration(name); if (!decl.isValid()) { decl.setName(name); decl.setType(PropertyDeclaration::Variant); } decl.setDescription(description); if (removalVersion.isValid()) { DeprecationInfo di(removalVersion, description); decl.setDeprecationInfo(di); } const ValuePtr property = optionsItem->parent()->property(name); if (!property && !decl.isExpired()) { throw ErrorInfo(Tr::tr("PropertyOptions item refers to non-existing property '%1'") .arg(name), optionsItem->location()); } if (property && decl.isExpired()) { ErrorInfo e(Tr::tr("Property '%1' was scheduled for removal in version %2, but " "is still present.") .arg(name).arg(removalVersion.toString()), property->location()); e.append(Tr::tr("Removal version for '%1' specified here.").arg(name), optionsItem->location()); m_logger.printWarning(e); } optionsItem->parent()->setPropertyDeclaration(name, decl); } static void mergeProperty(Item *dst, const QString &name, const ValuePtr &value) { if (value->type() == Value::ItemValueType) { const ItemValueConstPtr itemValue = std::static_pointer_cast(value); const Item * const valueItem = itemValue->item(); Item * const subItem = dst->itemProperty(name, itemValue)->item(); for (QMap::const_iterator it = valueItem->properties().constBegin(); it != valueItem->properties().constEnd(); ++it) mergeProperty(subItem, it.key(), it.value()); } else { // If the property already exists set up the base value. if (value->type() == Value::JSSourceValueType) { const auto jsValue = static_cast(value.get()); if (jsValue->isBuiltinDefaultValue()) return; const ValuePtr baseValue = dst->property(name); if (baseValue) { QBS_CHECK(baseValue->type() == Value::JSSourceValueType); const JSSourceValuePtr jsBaseValue = std::static_pointer_cast( baseValue->clone()); jsValue->setBaseValue(jsBaseValue); std::vector alternatives = jsValue->alternatives(); jsValue->clearAlternatives(); for (JSSourceValue::Alternative &a : alternatives) { a.value->setBaseValue(jsBaseValue); jsValue->addAlternative(a); } } } dst->setProperty(name, value); } } bool ModuleLoader::checkExportItemCondition(Item *exportItem, const ProductContext &productContext) { class ScopeHandler { public: ScopeHandler(Item *exportItem, const ProductContext &productContext, Item **cachedScopeItem) : m_exportItem(exportItem) { if (!*cachedScopeItem) *cachedScopeItem = Item::create(exportItem->pool(), ItemType::Scope); Item * const scope = *cachedScopeItem; QBS_CHECK(productContext.item->file()); scope->setFile(productContext.item->file()); scope->setScope(productContext.item); productContext.project->scope->copyProperty(StringConstants::projectVar(), scope); productContext.scope->copyProperty(StringConstants::productVar(), scope); QBS_CHECK(!exportItem->scope()); exportItem->setScope(scope); } ~ScopeHandler() { m_exportItem->setScope(nullptr); } private: Item * const m_exportItem; } scopeHandler(exportItem, productContext, &m_tempScopeItem); return checkItemCondition(exportItem); } ProbeConstPtr ModuleLoader::findOldProjectProbe( const QString &globalId, bool condition, const QVariantMap &initialProperties, const QString &sourceCode) const { if (m_parameters.forceProbeExecution()) return {}; for (const ProbeConstPtr &oldProbe : m_oldProjectProbes.value(globalId)) { if (probeMatches(oldProbe, condition, initialProperties, sourceCode, CompareScript::Yes)) return oldProbe; } return {}; } ProbeConstPtr ModuleLoader::findOldProductProbe( const QString &productName, bool condition, const QVariantMap &initialProperties, const QString &sourceCode) const { if (m_parameters.forceProbeExecution()) return {}; for (const ProbeConstPtr &oldProbe : m_oldProductProbes.value(productName)) { if (probeMatches(oldProbe, condition, initialProperties, sourceCode, CompareScript::Yes)) return oldProbe; } return {}; } ProbeConstPtr ModuleLoader::findCurrentProbe( const CodeLocation &location, bool condition, const QVariantMap &initialProperties) const { const QList &cachedProbes = m_currentProbes.value(location); for (const ProbeConstPtr &probe : cachedProbes) { if (probeMatches(probe, condition, initialProperties, QString(), CompareScript::No)) return probe; } return {}; } bool ModuleLoader::probeMatches(const ProbeConstPtr &probe, bool condition, const QVariantMap &initialProperties, const QString &configureScript, CompareScript compareScript) const { return probe->condition() == condition && probe->initialProperties() == initialProperties && (compareScript == CompareScript::No || (probe->configureScript() == configureScript && !probe->needsReconfigure(m_lastResolveTime))); } void ModuleLoader::printProfilingInfo() { if (!m_parameters.logElapsedTime()) return; m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Project file loading and parsing took %1.") .arg(elapsedTimeString(m_reader->elapsedTime())); m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Preparing products took %1.") .arg(elapsedTimeString(m_elapsedTimePrepareProducts)); m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Setting up product dependencies took %1.") .arg(elapsedTimeString(m_elapsedTimeProductDependencies)); m_logger.qbsLog(LoggerInfo, true) << "\t\t" << Tr::tr("Setting up transitive product dependencies took %1.") .arg(elapsedTimeString(m_elapsedTimeTransitiveDependencies)); m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Handling products took %1.") .arg(elapsedTimeString(m_elapsedTimeHandleProducts)); m_logger.qbsLog(LoggerInfo, true) << "\t\t" << Tr::tr("Running Probes took %1.") .arg(elapsedTimeString(m_elapsedTimeProbes)); m_logger.qbsLog(LoggerInfo, true) << "\t\t" << Tr::tr("%1 probes encountered, %2 configure scripts executed, " "%3 re-used from current run, %4 re-used from earlier run.") .arg(m_probesEncountered).arg(m_probesRun).arg(m_probesCachedCurrent) .arg(m_probesCachedOld); m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Property checking took %1.") .arg(elapsedTimeString(m_elapsedTimePropertyChecking)); } static void mergeParameters(QVariantMap &dst, const QVariantMap &src) { for (auto it = src.begin(); it != src.end(); ++it) { if (it.value().type() == QVariant::Map) { QVariant &vdst = dst[it.key()]; QVariantMap mdst = vdst.toMap(); mergeParameters(mdst, it.value().toMap()); vdst = mdst; } else { dst[it.key()] = it.value(); } } } static void adjustParametersScopes(Item *item, Item *scope) { if (item->type() == ItemType::ModuleParameters) { item->setScope(scope); return; } for (const auto &value : item->properties()) { if (value->type() != Value::ItemValueType) continue; adjustParametersScopes(std::static_pointer_cast(value)->item(), scope); } } bool ModuleLoader::mergeExportItems(const ProductContext &productContext) { std::vector exportItems; QList children = productContext.item->children(); for (int i = 0; i < children.size();) { Item * const child = children.at(i); if (child->type() == ItemType::Export) { exportItems.push_back(child); children.removeAt(i); } else { ++i; } } // Note that we do not return if there are no Export items: The "merged" item becomes the // "product module", which always needs to exist, regardless of whether the product sources // actually contain an Export item or not. if (!exportItems.empty()) productContext.item->setChildren(children); Item *merged = Item::create(productContext.item->pool(), ItemType::Export); const QString &nameKey = StringConstants::nameProperty(); const ValuePtr nameValue = VariantValue::create(productContext.name); merged->setProperty(nameKey, nameValue); Set filesWithExportItem; ProductModuleInfo pmi; bool hasDependenciesOnProductType = false; for (Item * const exportItem : qAsConst(exportItems)) { checkCancelation(); if (Q_UNLIKELY(filesWithExportItem.contains(exportItem->file()))) throw ErrorInfo(Tr::tr("Multiple Export items in one product are prohibited."), exportItem->location()); exportItem->setProperty(nameKey, nameValue); if (!checkExportItemCondition(exportItem, productContext)) continue; filesWithExportItem += exportItem->file(); for (Item * const child : exportItem->children()) { if (child->type() == ItemType::Parameters) { adjustParametersScopes(child, child); mergeParameters(pmi.defaultParameters, m_evaluator->scriptValue(child).toVariant().toMap()); } else { if (child->type() == ItemType::Depends) { bool productTypesIsSet; m_evaluator->stringValue(child, StringConstants::productTypesProperty(), QString(), &productTypesIsSet); if (productTypesIsSet) hasDependenciesOnProductType = true; } Item::addChild(merged, child); } } const Item::PropertyDeclarationMap &decls = exportItem->propertyDeclarations(); for (auto it = decls.constBegin(); it != decls.constEnd(); ++it) { const PropertyDeclaration &newDecl = it.value(); const PropertyDeclaration &existingDecl = merged->propertyDeclaration(it.key()); if (existingDecl.isValid() && existingDecl.type() != newDecl.type()) { ErrorInfo error(Tr::tr("Export item in inherited item redeclares property " "'%1' with different type.").arg(it.key()), exportItem->location()); handlePropertyError(error, m_parameters, m_logger); } merged->setPropertyDeclaration(newDecl.name(), newDecl); } for (QMap::const_iterator it = exportItem->properties().constBegin(); it != exportItem->properties().constEnd(); ++it) { mergeProperty(merged, it.key(), it.value()); } } merged->setFile(exportItems.empty() ? productContext.item->file() : exportItems.back()->file()); merged->setLocation(exportItems.empty() ? productContext.item->location() : exportItems.back()->location()); Item::addChild(productContext.item, merged); merged->setupForBuiltinType(m_logger); pmi.exportItem = merged; pmi.multiplexId = productContext.multiplexConfigurationId; productContext.project->topLevelProject->productModules.insert(productContext.name, pmi); if (hasDependenciesOnProductType) m_exportsWithDeferredDependsItems.insert(merged); return exportItems.size() > 0; } Item *ModuleLoader::loadItemFromFile(const QString &filePath, const CodeLocation &referencingLocation) { Item *item; try { item = m_reader->readFile(filePath); } catch (const ErrorInfo &e) { if (e.hasLocation()) throw; throw ErrorInfo(e.toString(), referencingLocation); } handleAllPropertyOptionsItems(item); return item; } void ModuleLoader::handleProfileItems(Item *item, ProjectContext *projectContext) { const std::vector profileItems = collectProfileItems(item, projectContext); for (Item * const profileItem : profileItems) { try { handleProfile(profileItem); } catch (const ErrorInfo &e) { handlePropertyError(e, m_parameters, m_logger); } } } std::vector ModuleLoader::collectProfileItems(Item *item, ProjectContext *projectContext) { QList childItems = item->children(); std::vector profileItems; Item * scope = item->type() == ItemType::Project ? projectContext->scope : nullptr; for (auto it = childItems.begin(); it != childItems.end();) { Item * const childItem = *it; if (childItem->type() == ItemType::Profile) { if (!scope) { const ItemValuePtr itemValue = ItemValue::create(item); scope = Item::create(m_pool, ItemType::Scope); scope->setProperty(StringConstants::productVar(), itemValue); scope->setFile(item->file()); scope->setScope(projectContext->scope); } childItem->setScope(scope); profileItems.push_back(childItem); it = childItems.erase(it); } else { if (childItem->type() == ItemType::Product) { for (Item * const profileItem : collectProfileItems(childItem, projectContext)) profileItems.push_back(profileItem); } ++it; } } if (!profileItems.empty()) item->setChildren(childItems); return profileItems; } void ModuleLoader::evaluateProfileValues(const QualifiedId &namePrefix, Item *item, Item *profileItem, QVariantMap &values) { const Item::PropertyMap &props = item->properties(); for (auto it = props.begin(); it != props.end(); ++it) { QualifiedId name = namePrefix; name << it.key(); switch (it.value()->type()) { case Value::ItemValueType: evaluateProfileValues(name, std::static_pointer_cast(it.value())->item(), profileItem, values); break; case Value::VariantValueType: values.insert(name.join(QLatin1Char('.')), std::static_pointer_cast(it.value())->value()); break; case Value::JSSourceValueType: item->setType(ItemType::ModulePrefix); // TODO: Introduce new item type if (item != profileItem) item->setScope(profileItem); values.insert(name.join(QLatin1Char('.')), m_evaluator->value(item, it.key()).toVariant()); break; } } } void ModuleLoader::handleProfile(Item *profileItem) { QVariantMap values; evaluateProfileValues(QualifiedId(), profileItem, profileItem, values); const bool condition = values.take(StringConstants::conditionProperty()).toBool(); if (!condition) return; const QString profileName = values.take(StringConstants::nameProperty()).toString(); if (profileName.isEmpty()) throw ErrorInfo(Tr::tr("Every Profile item must have a name"), profileItem->location()); if (profileName == Profile::fallbackName()) { throw ErrorInfo(Tr::tr("Reserved name '%1' cannot be used for an actual profile.") .arg(profileName), profileItem->location()); } if (m_localProfiles.contains(profileName)) { throw ErrorInfo(Tr::tr("Local profile '%1' redefined.").arg(profileName), profileItem->location()); } m_localProfiles.insert(profileName, values); } void ModuleLoader::collectNameFromOverride(const QString &overrideString) { static const auto extract = [](const QString &prefix, const QString &overrideString) { if (!overrideString.startsWith(prefix)) return QString(); const int startPos = prefix.length(); const int endPos = overrideString.lastIndexOf(StringConstants::dot()); if (endPos == -1) return QString(); return overrideString.mid(startPos, endPos - startPos); }; const QString &projectName = extract(StringConstants::projectsOverridePrefix(), overrideString); if (!projectName.isEmpty()) { m_projectNamesUsedInOverrides.insert(projectName); return; } const QString &productName = extract(StringConstants::productsOverridePrefix(), overrideString); if (!productName.isEmpty()) { m_productNamesUsedInOverrides.insert(productName.left( productName.indexOf(StringConstants::dot()))); return; } } void ModuleLoader::checkProjectNamesInOverrides(const ModuleLoader::TopLevelProjectContext &tlp) { for (const QString &projectNameInOverride : m_projectNamesUsedInOverrides) { if (m_disabledProjects.contains(projectNameInOverride)) continue; bool found = false; for (const ProjectContext * const p : tlp.projects) { if (p->name == projectNameInOverride) { found = true; break; } } if (!found) { handlePropertyError(Tr::tr("Unknown project '%1' in property override.") .arg(projectNameInOverride), m_parameters, m_logger); } } } void ModuleLoader::checkProductNamesInOverrides() { for (const QString &productNameInOverride : m_productNamesUsedInOverrides) { if (m_erroneousProducts.contains(productNameInOverride)) continue; bool found = false; for (auto it = m_productsByName.cbegin(); it != m_productsByName.cend(); ++it) { // In an override string such as "a.b.c:d, we cannot tell whether we have a product // "a" and a module "b.c" or a product "a.b" and a module "c", so we need to take // care not to emit false positives here. if (it->first == productNameInOverride || it->first.startsWith(productNameInOverride + StringConstants::dot())) { found = true; break; } } if (!found) { handlePropertyError(Tr::tr("Unknown product '%1' in property override.") .arg(productNameInOverride), m_parameters, m_logger); } } } void ModuleLoader::setSearchPathsForProduct(ModuleLoader::ProductContext *product) { product->searchPaths = readExtraSearchPaths(product->item); Settings settings(m_parameters.settingsDirectory()); const QVariantMap profileContents = product->project->result->profileConfigs .value(product->profileName).toMap(); const QStringList prefsSearchPaths = Preferences(&settings, profileContents).searchPaths(); const QStringList ¤tSearchPaths = m_reader->allSearchPaths(); for (const QString &p : prefsSearchPaths) { if (!currentSearchPaths.contains(p) && FileInfo(p).exists()) product->searchPaths << p; } // Existing module provider search paths are re-used if and only if the provider configuration // at setup time was the same as the current one for the respective module provider. if (!m_moduleProviderInfo.empty()) { const QVariantMap configForProduct = moduleProviderConfig(*product); for (const ModuleProviderInfo &c : m_moduleProviderInfo) { if (configForProduct.value(c.name.toString()).toMap() == c.config) { qCDebug(lcModuleLoader) << "re-using search paths" << c.searchPaths << "from module provider" << c.name << "for product" << product->name; product->knownModuleProviders.insert(c.name); product->searchPaths << c.searchPaths; } } } } ModuleLoader::ShadowProductInfo ModuleLoader::getShadowProductInfo( const ModuleLoader::ProductContext &product) const { const bool isShadowProduct = product.name.startsWith(shadowProductPrefix()); return std::make_pair(isShadowProduct, isShadowProduct ? product.name.mid(shadowProductPrefix().size()) : QString()); } void ModuleLoader::collectProductsByName(const TopLevelProjectContext &topLevelProject) { for (ProjectContext * const project : topLevelProject.projects) { for (ProductContext &product : project->products) m_productsByName.insert({ product.name, &product }); } } void ModuleLoader::collectProductsByType(const ModuleLoader::TopLevelProjectContext &topLevelProject) { for (ProjectContext * const project : topLevelProject.projects) { for (ProductContext &product : project->products) { try { const FileTags productTags = m_evaluator->fileTagsValue(product.item, StringConstants::typeProperty()); for (const FileTag &tag : productTags) m_productsByType.insert({ tag, &product}); } catch (const ErrorInfo &) { qCDebug(lcModuleLoader) << "product" << product.name << "has complex type " " and won't get an entry in the type map"; } } } } void ModuleLoader::propagateModulesFromParent(ProductContext *productContext, Item *groupItem, const ModuleDependencies &reverseDepencencies) { QBS_CHECK(groupItem->type() == ItemType::Group); QHash moduleInstancesForGroup; // Step 1: Instantiate the product's modules for the group. for (Item::Module m : groupItem->parent()->modules()) { Item *targetItem = moduleInstanceItem(groupItem, m.name); targetItem->setPrototype(m.item); Item * const moduleScope = Item::create(targetItem->pool(), ItemType::Scope); moduleScope->setFile(groupItem->file()); moduleScope->setProperties(m.item->scope()->properties()); // "project", "product", ids moduleScope->setScope(groupItem); targetItem->setScope(moduleScope); targetItem->setFile(m.item->file()); // "parent" should point to the group/artifact parent targetItem->setParent(groupItem->parent()); targetItem->setOuterItem(m.item); m.item = targetItem; groupItem->addModule(m); moduleInstancesForGroup.insert(m.name, targetItem); } // Step 2: Make the inter-module references point to the instances created in step 1. for (const Item::Module &module : groupItem->modules()) { Item::Modules adaptedModules; const Item::Modules &oldModules = module.item->prototype()->modules(); for (Item::Module depMod : oldModules) { depMod.item = moduleInstancesForGroup.value(depMod.name); adaptedModules << depMod; if (depMod.name.front() == module.name.front()) continue; const ItemValuePtr &modulePrefix = groupItem->itemProperty(depMod.name.front()); QBS_CHECK(modulePrefix); module.item->setProperty(depMod.name.front(), modulePrefix); } module.item->setModules(adaptedModules); } const QualifiedIdSet &propsSetInGroup = gatherModulePropertiesSetInGroup(groupItem); if (propsSetInGroup.empty()) return; productContext->info.modulePropertiesSetInGroups .insert(std::make_pair(groupItem, propsSetInGroup)); // Step 3: Adapt defining items in values. This is potentially necessary if module properties // get assigned on the group level. for (const Item::Module &module : groupItem->modules()) { const QualifiedIdSet &dependents = reverseDepencencies.value(module.name); Item::Modules dependentModules; dependentModules.reserve(int(dependents.size())); for (const QualifiedId &depName : dependents) { Item * const itemOfDependent = moduleInstancesForGroup.value(depName); QBS_CHECK(itemOfDependent); Item::Module depMod; depMod.name = depName; depMod.item = itemOfDependent; dependentModules << depMod; } adjustDefiningItemsInGroupModuleInstances(module, dependentModules); } } static Item *createReplacementForDefiningItem(const Item *definingItem, ItemType type) { Item *replacement = Item::create(definingItem->pool(), type); replacement->setLocation(definingItem->location()); definingItem->copyProperty(StringConstants::nameProperty(), replacement); return replacement; } void ModuleLoader::adjustDefiningItemsInGroupModuleInstances(const Item::Module &module, const Item::Modules &dependentModules) { if (!module.item->isPresentModule()) return; // There are three cases: // a) The defining item is the "main" module instance, i.e. the one instantiated in the // product directly (or a parent group). // b) The defining item refers to the module prototype (or the replacement of it // created in the module merger [for products] or in this function [for parent groups]). // c) The defining item is a different instance of the module, i.e. it was instantiated // in some other module. QHash definingItemReplacements; Item *modulePrototype = rootPrototype(module.item->prototype()); QBS_CHECK(modulePrototype->type() == ItemType::Module || modulePrototype->type() == ItemType::Export); const Item::PropertyDeclarationMap &propDecls = modulePrototype->propertyDeclarations(); for (const auto &decl : propDecls) { const QString &propName = decl.name(); // Module properties assigned in the group are not relevant here, as nothing // gets inherited in that case. In particular, setting a list property // overwrites the value from the product's (or parent group's) instance completely, // rather than appending to it (concatenation happens via outer.concat()). ValueConstPtr propValue = module.item->ownProperty(propName); if (propValue) continue; // Find the nearest prototype instance that has the value assigned. // The result is either an instance of a parent group (or the parent group's // parent group and so on) or the instance of the product or the module prototype. // In the latter case, we don't have to do anything. const Item *instanceWithProperty = module.item; int prototypeChainLen = 0; do { instanceWithProperty = instanceWithProperty->prototype(); QBS_CHECK(instanceWithProperty); ++prototypeChainLen; propValue = instanceWithProperty->ownProperty(propName); } while (!propValue); QBS_CHECK(propValue); if (propValue->type() != Value::JSSourceValueType) continue; bool hasDefiningItem = false; for (ValueConstPtr v = propValue; v && !hasDefiningItem; v = v->next()) hasDefiningItem = v->definingItem(); if (!hasDefiningItem) continue; const ValuePtr clonedValue = propValue->clone(); for (ValuePtr v = clonedValue; v; v = v->next()) { QBS_CHECK(v->definingItem()); Item *& replacement = definingItemReplacements[v->definingItem()]; static const QString caseA = QStringLiteral("__group_case_a"); if (v->definingItem() == instanceWithProperty || v->definingItem()->variantProperty(caseA)) { // Case a) // For values whose defining item is the product's (or parent group's) instance, // we take its scope and replace references to module instances with those from the // group's instance. This handles cases like the following: // Product { // name: "theProduct" // aModule.listProp: [name, otherModule.stringProp] // Group { name: "theGroup"; otherModule.stringProp: name } // ... // } // In the above example, aModule.listProp is set to ["theProduct", "theGroup"] // (plus potential values from the prototype and other module instances, // which are different Value objects in the "next chain"). if (!replacement) { replacement = createReplacementForDefiningItem(v->definingItem(), v->definingItem()->type()); Item * const scope = Item::create(v->definingItem()->pool(), ItemType::Scope); scope->setProperties(module.item->scope()->properties()); Item * const scopeScope = Item::create(v->definingItem()->pool(), ItemType::Scope); scopeScope->setProperties(v->definingItem()->scope()->scope()->properties()); scope->setScope(scopeScope); replacement->setScope(scope); const Item::PropertyMap &groupScopeProperties = module.item->scope()->scope()->properties(); for (auto propIt = groupScopeProperties.begin(); propIt != groupScopeProperties.end(); ++propIt) { if (propIt.value()->type() == Value::ItemValueType) scopeScope->setProperty(propIt.key(), propIt.value()); } } replacement->setPropertyDeclaration(propName, decl); replacement->setProperty(propName, v); replacement->setProperty(caseA, VariantValue::invalidValue()); } else if (v->definingItem()->type() == ItemType::Module) { // Case b) // For values whose defining item is the module prototype, we change the scope to // the group's instance, analogous to what we do in // ModuleMerger::appendPrototypeValueToNextChain(). QBS_CHECK(!decl.isScalar()); QBS_CHECK(!v->next()); Item *& replacement = definingItemReplacements[v->definingItem()]; if (!replacement) { replacement = createReplacementForDefiningItem(v->definingItem(), ItemType::Module); replacement->setScope(module.item); } QBS_CHECK(!replacement->hasOwnProperty(caseA)); qCDebug(lcModuleLoader).noquote().nospace() << "replacing defining item for prototype; module is " << module.name.toString() << module.item << ", property is " << propName << ", old defining item was " << v->definingItem() << " with scope" << v->definingItem()->scope() << ", new defining item is" << replacement << " with scope" << replacement->scope(); if (v->type() == Value::JSSourceValueType) { qCDebug(lcModuleLoader) << "value source code is" << std::static_pointer_cast(v)->sourceCode().toString(); } replacement->setPropertyDeclaration(propName, decl); replacement->setProperty(propName, v); } else { // Look for instance scopes of other module instances in defining items and // replace the affected values. // This is case c) as introduced above. See ModuleMerger::replaceItemInScopes() // for a detailed explanation. QBS_CHECK(v->definingItem()->scope() && v->definingItem()->scope()->scope()); bool found = false; for (const Item::Module &depMod : dependentModules) { const Item *depModPrototype = depMod.item->prototype(); for (int i = 1; i < prototypeChainLen; ++i) depModPrototype = depModPrototype->prototype(); if (v->definingItem()->scope()->scope() != depModPrototype) continue; found = true; Item *& replacement = definingItemReplacements[v->definingItem()]; if (!replacement) { replacement = createReplacementForDefiningItem(v->definingItem(), v->definingItem()->type()); replacement->setProperties(v->definingItem()->properties()); for (const auto &decl : v->definingItem()->propertyDeclarations()) replacement->setPropertyDeclaration(decl.name(), decl); replacement->setPrototype(v->definingItem()->prototype()); replacement->setScope(Item::create(v->definingItem()->pool(), ItemType::Scope)); replacement->scope()->setScope(depMod.item); } QBS_CHECK(!replacement->hasOwnProperty(caseA)); qCDebug(lcModuleLoader) << "reset instance scope of module" << depMod.name.toString() << "in property" << propName << "of module" << module.name; } QBS_CHECK(found); } QBS_CHECK(replacement); v->setDefiningItem(replacement); } module.item->setProperty(propName, clonedValue); } } void ModuleLoader::resolveDependencies(DependsContext *dependsContext, Item *item, ProductContext *productContext) { QBS_CHECK(m_dependencyResolvingPass == 1 || m_dependencyResolvingPass == 2); if (!productContext || m_dependencyResolvingPass == 1) { const Item::Module baseModule = loadBaseModule(dependsContext->product, item); item->addModule(baseModule); } // Resolve all Depends items. ItemModuleList loadedModules; QList dependsItemPerLoadedModule; ProductDependencies productDependencies; const auto handleDependsItem = [&](Item *child) { if (child->type() != ItemType::Depends) return; int lastModulesCount = loadedModules.size(); try { resolveDependsItem(dependsContext, child->parent(), child, &loadedModules, &productDependencies); } catch (const ErrorInfo &e) { if (!productContext) throw; handleProductError(e, productContext); } for (int i = lastModulesCount; i < loadedModules.size(); ++i) dependsItemPerLoadedModule.push_back(child); }; if (productContext && m_dependencyResolvingPass == 2) { for (const auto &deferData : productContext->deferredDependsItems) { dependsContext->exportingProductItem = deferData.first; for (Item * const dependsItem : deferData.second) handleDependsItem(dependsItem); } } else { for (Item * const child : item->children()) handleDependsItem(child); } QBS_CHECK(loadedModules.size() == dependsItemPerLoadedModule.size()); Item *lastDependsItem = nullptr; for (Item * const dependsItem : dependsItemPerLoadedModule) { if (dependsItem == lastDependsItem) continue; adjustParametersScopes(dependsItem, dependsItem); forwardParameterDeclarations(dependsItem, loadedModules); lastDependsItem = dependsItem; } for (int i = 0; i < loadedModules.size(); ++i) { Item::Module &module = loadedModules[i]; mergeParameters(module.parameters, extractParameters(dependsItemPerLoadedModule.at(i))); item->addModule(module); const QString moduleName = module.name.toString(); std::for_each(productDependencies.begin(), productDependencies.end(), [&module, &moduleName] (ModuleLoaderResult::ProductInfo::Dependency &dep) { if (dep.name == moduleName) dep.parameters = module.parameters; }); } dependsContext->productDependencies->insert( dependsContext->productDependencies->end(), productDependencies.cbegin(), productDependencies.cend()); } class RequiredChainManager { public: RequiredChainManager(std::vector &requiredChain, bool required) : m_requiredChain(requiredChain) { m_requiredChain.push_back(required); } ~RequiredChainManager() { m_requiredChain.pop_back(); } private: std::vector &m_requiredChain; }; void ModuleLoader::resolveDependsItem(DependsContext *dependsContext, Item *parentItem, Item *dependsItem, ItemModuleList *moduleResults, ProductDependencies *productResults) { checkCancelation(); if (!checkItemCondition(dependsItem)) { qCDebug(lcModuleLoader) << "Depends item disabled, ignoring."; return; } bool nameIsSet; const QString name = m_evaluator->stringValue(dependsItem, StringConstants::nameProperty(), QString(), &nameIsSet); bool submodulesPropertySet; const QStringList submodules = m_evaluator->stringListValue( dependsItem, StringConstants::submodulesProperty(), &submodulesPropertySet); if (submodules.empty() && submodulesPropertySet) { qCDebug(lcModuleLoader) << "Ignoring Depends item with empty submodules list."; return; } if (Q_UNLIKELY(submodules.size() > 1 && !dependsItem->id().isEmpty())) { QString msg = Tr::tr("A Depends item with more than one module cannot have an id."); throw ErrorInfo(msg, dependsItem->location()); } const FallbackMode fallbackMode = m_parameters.fallbackProviderEnabled() && m_evaluator->boolValue(dependsItem, StringConstants::enableFallbackProperty()) ? FallbackMode::Enabled : FallbackMode::Disabled; QList moduleNames; const QualifiedId nameParts = QualifiedId::fromString(name); if (submodules.empty()) { // Ignore explicit dependencies on the base module, which has already been loaded. if (name == StringConstants::qbsModule()) return; moduleNames << nameParts; } else { for (const QString &submodule : submodules) moduleNames << nameParts + QualifiedId::fromString(submodule); } Item::Module result; bool productTypesIsSet; m_evaluator->stringValue(dependsItem, StringConstants::productTypesProperty(), QString(), &productTypesIsSet); if (m_dependencyResolvingPass == 1 && productTypesIsSet) { qCDebug(lcModuleLoader) << "queuing product" << dependsContext->product->name << "for a second dependencies resolving pass"; m_productsWithDeferredDependsItems[dependsContext->product].insert( DeferredDependsContext(dependsContext->exportingProductItem, parentItem)); return; } const bool isRequired = !productTypesIsSet && m_evaluator->boolValue(dependsItem, StringConstants::requiredProperty()) && !contains(m_requiredChain, false); const Version minVersion = Version::fromString( m_evaluator->stringValue(dependsItem, StringConstants::versionAtLeastProperty())); const Version maxVersion = Version::fromString( m_evaluator->stringValue(dependsItem, StringConstants::versionBelowProperty())); const VersionRange versionRange(minVersion, maxVersion); QStringList multiplexConfigurationIds = m_evaluator->stringListValue( dependsItem, StringConstants::multiplexConfigurationIdsProperty()); if (multiplexConfigurationIds.empty()) multiplexConfigurationIds << QString(); for (const QualifiedId &moduleName : qAsConst(moduleNames)) { // Don't load the same module twice. Duplicate Depends statements can easily // happen due to inheritance. const auto it = std::find_if(moduleResults->begin(), moduleResults->end(), [moduleName](const Item::Module &m) { return m.name == moduleName; }); if (it != moduleResults->end()) { if (isRequired) it->required = true; it->versionRange.narrowDown(versionRange); continue; } QVariantMap defaultParameters; Item *moduleItem = loadModule(dependsContext->product, dependsContext->exportingProductItem, parentItem, dependsItem->location(), dependsItem->id(), moduleName, multiplexConfigurationIds.first(), fallbackMode, isRequired, &result.isProduct, &defaultParameters); if (!moduleItem) { const QString productName = ResolvedProduct::fullDisplayName( dependsContext->product->name, dependsContext->product->multiplexConfigurationId); if (!multiplexConfigurationIds.first().isEmpty()) { const QString depName = ResolvedProduct::fullDisplayName( moduleName.toString(), multiplexConfigurationIds.first()); throw ErrorInfo(Tr::tr("Dependency from product '%1' to product '%2' not " "fulfilled.").arg(productName, depName)); } ErrorInfo e(Tr::tr("Dependency '%1' not found for product '%2'.") .arg(moduleName.toString(), productName), dependsItem->location()); throw e; } if (result.isProduct && !m_dependsChain.empty() && !m_dependsChain.back().isProduct) { throw ErrorInfo(Tr::tr("Invalid dependency on product '%1': Modules cannot depend on " "products. You may want to turn your module into a product and " "add the dependency in that product's Export item.") .arg(moduleName.toString()), dependsItem->location()); } qCDebug(lcModuleLoader) << "module loaded:" << moduleName.toString(); result.name = moduleName; result.item = moduleItem; result.required = isRequired; result.parameters = defaultParameters; result.versionRange = versionRange; moduleResults->push_back(result); if (result.isProduct) { qCDebug(lcModuleLoader) << "product dependency loaded:" << moduleName.toString(); bool profilesPropertyWasSet = false; QStringList profiles = m_evaluator->stringListValue(dependsItem, StringConstants::profilesProperty(), &profilesPropertyWasSet); if (profiles.empty()) { if (profilesPropertyWasSet) profiles.push_back(StringConstants::star()); else profiles.push_back(QString()); } for (const QString &profile : qAsConst(profiles)) { for (const QString &multiplexId : multiplexConfigurationIds) { ModuleLoaderResult::ProductInfo::Dependency dependency; dependency.name = moduleName.toString(); dependency.profile = profile; dependency.multiplexConfigurationId = multiplexId; dependency.isRequired = isRequired; productResults->push_back(dependency); } } } } } void ModuleLoader::forwardParameterDeclarations(const Item *dependsItem, const ItemModuleList &modules) { for (auto it = dependsItem->properties().begin(); it != dependsItem->properties().end(); ++it) { if (it.value()->type() != Value::ItemValueType) continue; forwardParameterDeclarations(it.key(), std::static_pointer_cast(it.value())->item(), modules); } } void ModuleLoader::forwardParameterDeclarations(const QualifiedId &moduleName, Item *item, const ItemModuleList &modules) { auto it = std::find_if(modules.begin(), modules.end(), [&moduleName] (const Item::Module &m) { return m.name == moduleName; }); if (it != modules.end()) { item->setPropertyDeclarations(m_parameterDeclarations.value(rootPrototype(it->item))); } else { for (auto it = item->properties().begin(); it != item->properties().end(); ++it) { if (it.value()->type() != Value::ItemValueType) continue; forwardParameterDeclarations(QualifiedId(moduleName) << it.key(), std::static_pointer_cast(it.value())->item(), modules); } } } void ModuleLoader::resolveParameterDeclarations(const Item *module) { Item::PropertyDeclarationMap decls; const auto &moduleChildren = module->children(); for (Item *param : moduleChildren) { if (param->type() != ItemType::Parameter) continue; const auto paramDecls = param->propertyDeclarations(); for (auto it = paramDecls.begin(); it != paramDecls.end(); ++it) decls.insert(it.key(), it.value()); } m_parameterDeclarations.insert(module, decls); } static bool isItemValue(const ValuePtr &v) { return v->type() == Value::ItemValueType; } static Item::PropertyMap filterItemProperties(const Item::PropertyMap &properties) { Item::PropertyMap result; auto itEnd = properties.end(); for (auto it = properties.begin(); it != itEnd; ++it) { if (isItemValue(it.value())) result.insert(it.key(), it.value()); } return result; } static QVariantMap safeToVariant(const QScriptValue &v) { QVariantMap result; QScriptValueIterator it(v); while (it.hasNext()) { it.next(); QScriptValue u = it.value(); if (u.isError()) throw ErrorInfo(u.toString()); result[it.name()] = (u.isObject() && !u.isArray() && !u.isRegExp()) ? safeToVariant(u) : it.value().toVariant(); } return result; } QVariantMap ModuleLoader::extractParameters(Item *dependsItem) const { QVariantMap result; const Item::PropertyMap &itemProperties = filterItemProperties( rootPrototype(dependsItem)->properties()); if (itemProperties.empty()) return result; auto origProperties = dependsItem->properties(); dependsItem->setProperties(itemProperties); QScriptValue sv = m_evaluator->scriptValue(dependsItem); try { result = safeToVariant(sv); } catch (ErrorInfo ei) { ei.prepend(Tr::tr("Error in dependency parameter."), dependsItem->location()); throw ei; } dependsItem->setProperties(origProperties); return result; } [[noreturn]] static void throwModuleNamePrefixError(const QualifiedId &shortName, const QualifiedId &longName, const CodeLocation &codeLocation) { throw ErrorInfo(Tr::tr("The name of module '%1' is equal to the first component of the " "name of module '%2', which is not allowed") .arg(shortName.toString(), longName.toString()), codeLocation); } Item *ModuleLoader::moduleInstanceItem(Item *containerItem, const QualifiedId &moduleName) { QBS_CHECK(!moduleName.empty()); Item *instance = containerItem; for (int i = 0; i < moduleName.size(); ++i) { const QString &moduleNameSegment = moduleName.at(i); const ValuePtr v = instance->ownProperty(moduleName.at(i)); if (v && v->type() == Value::ItemValueType) { instance = std::static_pointer_cast(v)->item(); } else { const ItemType itemType = i < moduleName.size() - 1 ? ItemType::ModulePrefix : ItemType::ModuleInstance; auto newItem = Item::create(m_pool, itemType); instance->setProperty(moduleNameSegment, ItemValue::create(newItem)); instance = newItem; } if (i < moduleName.size() - 1) { if (instance->type() == ItemType::ModuleInstance) { QualifiedId conflictingName = QStringList(moduleName.mid(0, i + 1)); throwModuleNamePrefixError(conflictingName, moduleName, CodeLocation()); } QBS_CHECK(instance->type() == ItemType::ModulePrefix); } } QBS_CHECK(instance != containerItem); return instance; } ModuleLoader::ProductModuleInfo *ModuleLoader::productModule(ProductContext *productContext, const QString &name, const QString &multiplexId, bool &productNameMatch) { auto &exportsData = productContext->project->topLevelProject->productModules; const auto firstIt = exportsData.find(name); productNameMatch = firstIt != exportsData.end(); for (auto it = firstIt; it != exportsData.end() && it.key() == name; ++it) { if (it.value().multiplexId == multiplexId) return &it.value(); } if (multiplexId.isEmpty() && firstIt != exportsData.end()) return &firstIt.value(); return nullptr; } ModuleLoader::ProductContext *ModuleLoader::product(ProjectContext *projectContext, const QString &name) { auto itEnd = projectContext->products.end(); auto it = std::find_if(projectContext->products.begin(), itEnd, [&name] (const ProductContext &ctx) { return ctx.name == name; }); return it == itEnd ? nullptr : &*it; } ModuleLoader::ProductContext *ModuleLoader::product(TopLevelProjectContext *tlpContext, const QString &name) { ProductContext *result = nullptr; for (auto prj : tlpContext->projects) { result = product(prj, name); if (result) break; } return result; } class ModuleLoader::DependsChainManager { public: DependsChainManager(std::vector &dependsChain, const QualifiedId &module, const CodeLocation &dependsLocation) : m_dependsChain(dependsChain) { const bool alreadyInChain = std::any_of(dependsChain.cbegin(), dependsChain.cend(), [&module](const DependsChainEntry &e) { return e.name == module; }); if (alreadyInChain) { ErrorInfo error; error.append(Tr::tr("Cyclic dependencies detected:")); for (const DependsChainEntry &e : qAsConst(m_dependsChain)) error.append(e.name.toString(), e.location); error.append(module.toString(), dependsLocation); throw error; } m_dependsChain.emplace_back(module, dependsLocation); } ~DependsChainManager() { m_dependsChain.pop_back(); } private: std::vector &m_dependsChain; }; static bool isBaseModule(const QualifiedId &moduleName) { return moduleName.size() == 1 && moduleName.front() == StringConstants::qbsModule(); } class DelayedPropertyChanger { public: ~DelayedPropertyChanger() { applyNow(); } void setLater(Item *item, const QString &name, const ValuePtr &value) { QBS_CHECK(m_item == nullptr); m_item = item; m_name = name; m_value = value; } void removeLater(Item *item, const QString &name) { QBS_CHECK(m_item == nullptr); m_item = item; m_name = name; } void applyNow() { if (!m_item || m_name.isEmpty()) return; if (m_value) m_item->setProperty(m_name, m_value); else m_item->removeProperty(m_name); m_item = nullptr; m_name.clear(); m_value.reset(); } private: Item *m_item = nullptr; QString m_name; ValuePtr m_value; }; Item *ModuleLoader::loadModule(ProductContext *productContext, Item *exportingProductItem, Item *item, const CodeLocation &dependsItemLocation, const QString &moduleId, const QualifiedId &moduleName, const QString &multiplexId, FallbackMode fallbackMode, bool isRequired, bool *isProductDependency, QVariantMap *defaultParameters) { qCDebug(lcModuleLoader) << "loadModule name:" << moduleName.toString() << "id:" << moduleId; RequiredChainManager requiredChainManager(m_requiredChain, isRequired); DependsChainManager dependsChainManager(m_dependsChain, moduleName, dependsItemLocation); Item *moduleInstance = moduleId.isEmpty() ? moduleInstanceItem(item, moduleName) : moduleInstanceItem(item, QStringList(moduleId)); if (moduleInstance->scope()) return moduleInstance; // already handled if (Q_UNLIKELY(moduleInstance->type() == ItemType::ModulePrefix)) { for (const Item::Module &m : item->modules()) { if (m.name.front() == moduleName.front()) throwModuleNamePrefixError(moduleName, m.name, dependsItemLocation); } } QBS_CHECK(moduleInstance->type() == ItemType::ModuleInstance); // Prepare module instance for evaluating Module.condition. DelayedPropertyChanger delayedPropertyChanger; const QString &qbsModuleName = StringConstants::qbsModule(); if (!isBaseModule(moduleName)) { ItemValuePtr qbsProp = productContext->item->itemProperty(qbsModuleName); if (qbsProp) { ValuePtr qbsModuleValue = moduleInstance->ownProperty(qbsModuleName); if (qbsModuleValue) delayedPropertyChanger.setLater(moduleInstance, qbsModuleName, qbsModuleValue); else delayedPropertyChanger.removeLater(moduleInstance, qbsModuleName); moduleInstance->setProperty(qbsModuleName, qbsProp); } } Item *modulePrototype = nullptr; ProductModuleInfo * const pmi = productModule(productContext, moduleName.toString(), multiplexId, *isProductDependency); if (pmi) { m_dependsChain.back().isProduct = true; modulePrototype = pmi->exportItem; if (defaultParameters) *defaultParameters = pmi->defaultParameters; } else if (!*isProductDependency) { modulePrototype = searchAndLoadModuleFile(productContext, dependsItemLocation, moduleName, fallbackMode, isRequired, moduleInstance); } delayedPropertyChanger.applyNow(); if (!modulePrototype) return nullptr; instantiateModule(productContext, exportingProductItem, item, moduleInstance, modulePrototype, moduleName, pmi); return moduleInstance; } struct PrioritizedItem { PrioritizedItem(Item *item, int priority, int searchPathIndex) : item(item), priority(priority), searchPathIndex(searchPathIndex) { } Item *item = nullptr; int priority = 0; int searchPathIndex = 0; }; static Item *chooseModuleCandidate(const std::vector &candidates, const QString &moduleName) { auto maxIt = std::max_element(candidates.begin(), candidates.end(), [] (const PrioritizedItem &a, const PrioritizedItem &b) { if (a.priority < b.priority) return true; if (a.priority > b.priority) return false; return a.searchPathIndex > b.searchPathIndex; }); size_t nmax = std::count_if(candidates.begin(), candidates.end(), [maxIt] (const PrioritizedItem &i) { return i.priority == maxIt->priority && i.searchPathIndex == maxIt->searchPathIndex; }); if (nmax > 1) { ErrorInfo e(Tr::tr("There is more than one equally prioritized candidate for module '%1'.") .arg(moduleName)); for (size_t i = 0; i < candidates.size(); ++i) { const auto candidate = candidates.at(i); if (candidate.priority == maxIt->priority) { //: The %1 denotes the number of the candidate. e.append(Tr::tr("candidate %1").arg(i + 1), candidates.at(i).item->location()); } } throw e; } return maxIt->item; } Item *ModuleLoader::searchAndLoadModuleFile(ProductContext *productContext, const CodeLocation &dependsItemLocation, const QualifiedId &moduleName, FallbackMode fallbackMode, bool isRequired, Item *moduleInstance) { bool triedToLoadModule = false; const QString fullName = moduleName.toString(); std::vector candidates; const QStringList &searchPaths = m_reader->allSearchPaths(); bool matchingDirectoryFound = false; for (int i = 0; i < searchPaths.size(); ++i) { const QString &path = searchPaths.at(i); const QString dirPath = findExistingModulePath(path, moduleName); if (dirPath.isEmpty()) continue; matchingDirectoryFound = true; QStringList moduleFileNames = m_moduleDirListCache.value(dirPath); if (moduleFileNames.empty()) { QDirIterator dirIter(dirPath, StringConstants::qbsFileWildcards()); while (dirIter.hasNext()) moduleFileNames += dirIter.next(); m_moduleDirListCache.insert(dirPath, moduleFileNames); } for (const QString &filePath : qAsConst(moduleFileNames)) { triedToLoadModule = true; Item *module = loadModuleFile(productContext, fullName, isBaseModule(moduleName), filePath, &triedToLoadModule, moduleInstance); if (module) candidates.emplace_back(module, 0, i); if (!triedToLoadModule) m_moduleDirListCache[dirPath].removeOne(filePath); } } if (candidates.empty()) { if (!matchingDirectoryFound) { bool moduleAlreadyKnown = false; ModuleProviderResult result; for (QualifiedId providerName = moduleName; !providerName.empty(); providerName.pop_back()) { if (!productContext->knownModuleProviders.insert(providerName).second) { moduleAlreadyKnown = true; break; } qCDebug(lcModuleLoader) << "Module" << moduleName.toString() << "not found, checking for module providers"; result = findModuleProvider(providerName, *productContext, ModuleProviderLookup::Regular, dependsItemLocation); if (result.providerFound) break; } if (fallbackMode == FallbackMode::Enabled && !result.providerFound && !moduleAlreadyKnown) { qCDebug(lcModuleLoader) << "Specific module provider not found for" << moduleName.toString() << ", setting up fallback."; result = findModuleProvider(moduleName, *productContext, ModuleProviderLookup::Fallback, dependsItemLocation); } if (result.providerAddedSearchPaths) { qCDebug(lcModuleLoader) << "Re-checking for module" << moduleName.toString() << "with newly added search paths from module provider"; return searchAndLoadModuleFile(productContext, dependsItemLocation, moduleName, fallbackMode, isRequired, moduleInstance); } } if (!isRequired) return createNonPresentModule(fullName, QStringLiteral("not found"), nullptr); if (Q_UNLIKELY(triedToLoadModule)) throw ErrorInfo(Tr::tr("Module %1 could not be loaded.").arg(fullName), dependsItemLocation); return nullptr; } Item *moduleItem; if (candidates.size() == 1) { moduleItem = candidates.at(0).item; } else { for (auto &candidate : candidates) { candidate.priority = m_evaluator->intValue(candidate.item, StringConstants::priorityProperty(), candidate.priority); } moduleItem = chooseModuleCandidate(candidates, fullName); } const auto it = productContext->unknownProfilePropertyErrors.find(moduleItem); if (it != productContext->unknownProfilePropertyErrors.cend()) { const QString fullProductName = ResolvedProduct::fullDisplayName (productContext->name, productContext->multiplexConfigurationId); ErrorInfo error(Tr::tr("Loading module '%1' for product '%2' failed due to invalid values " "in profile '%3':").arg(fullName, fullProductName, productContext->profileName)); for (const ErrorInfo &e : it->second) error.append(e.toString()); handlePropertyError(error, m_parameters, m_logger); } return moduleItem; } // returns QVariant::Invalid for types that do not need conversion static QVariant::Type variantType(PropertyDeclaration::Type t) { switch (t) { case PropertyDeclaration::UnknownType: break; case PropertyDeclaration::Boolean: return QVariant::Bool; case PropertyDeclaration::Integer: return QVariant::Int; case PropertyDeclaration::Path: return QVariant::String; case PropertyDeclaration::PathList: return QVariant::StringList; case PropertyDeclaration::String: return QVariant::String; case PropertyDeclaration::StringList: return QVariant::StringList; case PropertyDeclaration::VariantList: return QVariant::List; case PropertyDeclaration::Variant: break; } return QVariant::Invalid; } static QVariant convertToPropertyType(const QVariant &v, PropertyDeclaration::Type t, const QStringList &namePrefix, const QString &key) { if (v.isNull() || !v.isValid()) return v; const QVariant::Type vt = variantType(t); if (vt == QVariant::Invalid) return v; // Handle the foo,bar,bla stringlist syntax. if (t == PropertyDeclaration::StringList && v.type() == QVariant::String) return v.toString().split(QLatin1Char(',')); QVariant c = v; if (!c.convert(vt)) { QStringList name = namePrefix; name << key; throw ErrorInfo(Tr::tr("Value '%1' of property '%2' has incompatible type.") .arg(v.toString(), name.join(QLatin1Char('.')))); } return c; } static Item *findDeepestModuleInstance(Item *instance) { while (instance->prototype() && instance->prototype()->type() == ItemType::ModuleInstance) instance = instance->prototype(); return instance; } Item *ModuleLoader::loadModuleFile(ProductContext *productContext, const QString &fullModuleName, bool isBaseModule, const QString &filePath, bool *triedToLoad, Item *moduleInstance) { checkCancelation(); qCDebug(lcModuleLoader) << "loadModuleFile" << fullModuleName << "from" << filePath; Item * const module = getModulePrototype(productContext, fullModuleName, filePath, triedToLoad); if (!module) return nullptr; const auto key = std::make_pair(module, productContext); const auto it = m_modulePrototypeEnabledInfo.find(key); if (it != m_modulePrototypeEnabledInfo.end()) { qCDebug(lcModuleLoader) << "prototype cache hit (level 2)"; return it.value() ? module : nullptr; } // Set the name before evaluating any properties. EvaluatorScriptClass reads the module name. module->setProperty(StringConstants::nameProperty(), VariantValue::create(fullModuleName)); Item *deepestModuleInstance = findDeepestModuleInstance(moduleInstance); Item *origDeepestModuleInstancePrototype = deepestModuleInstance->prototype(); deepestModuleInstance->setPrototype(module); bool enabled = checkItemCondition(moduleInstance, module); deepestModuleInstance->setPrototype(origDeepestModuleInstancePrototype); if (!enabled) { qCDebug(lcModuleLoader) << "condition of module" << fullModuleName << "is false"; m_modulePrototypeEnabledInfo.insert(key, false); return nullptr; } if (isBaseModule) setupBaseModulePrototype(module); else resolveParameterDeclarations(module); m_modulePrototypeEnabledInfo.insert(key, true); return module; } Item *ModuleLoader::getModulePrototype(ProductContext *productContext, const QString &fullModuleName, const QString &filePath, bool *triedToLoad) { auto &prototypeList = m_modulePrototypes[filePath]; for (const auto &prototype : prototypeList) { if (prototype.second == productContext->profileName) { qCDebug(lcModuleLoader) << "prototype cache hit (level 1)"; return prototype.first; } } Item * const module = loadItemFromFile(filePath, CodeLocation()); prototypeList.push_back(std::make_pair(module, productContext->profileName)); if (module->type() != ItemType::Module) { qCDebug(lcModuleLoader).nospace() << "Alleged module " << fullModuleName << " has type '" << module->typeName() << "', so it's not a module after all."; *triedToLoad = false; return nullptr; } // Module properties that are defined in the profile are used as default values. // This is the reason we need to have different items per profile. const QVariantMap profileModuleProperties = productContext->moduleProperties.value(fullModuleName).toMap(); for (QVariantMap::const_iterator vmit = profileModuleProperties.begin(); vmit != profileModuleProperties.end(); ++vmit) { if (Q_UNLIKELY(!module->hasProperty(vmit.key()))) { productContext->unknownProfilePropertyErrors[module].emplace_back (Tr::tr("Unknown property: %1.%2").arg(fullModuleName, vmit.key())); continue; } const PropertyDeclaration decl = module->propertyDeclaration(vmit.key()); VariantValuePtr v = VariantValue::create(convertToPropertyType(vmit.value(), decl.type(), QStringList(fullModuleName), vmit.key())); module->setProperty(vmit.key(), v); } return module; } Item::Module ModuleLoader::loadBaseModule(ProductContext *productContext, Item *item) { const QualifiedId baseModuleName(StringConstants::qbsModule()); Item::Module baseModuleDesc; baseModuleDesc.name = baseModuleName; baseModuleDesc.item = loadModule(productContext, nullptr, item, CodeLocation(), QString(), baseModuleName, QString(), FallbackMode::Disabled, true, &baseModuleDesc.isProduct, nullptr); if (productContext->item) { const Item * const qbsInstanceItem = moduleInstanceItem(productContext->item, baseModuleName); const Item::PropertyMap &props = qbsInstanceItem->properties(); for (auto it = props.cbegin(); it != props.cend(); ++it) { if (it.value()->type() == Value::VariantValueType) baseModuleDesc.item->setProperty(it.key(), it.value()); } } QBS_CHECK(!baseModuleDesc.isProduct); if (Q_UNLIKELY(!baseModuleDesc.item)) throw ErrorInfo(Tr::tr("Cannot load base qbs module.")); return baseModuleDesc; } void ModuleLoader::setupBaseModulePrototype(Item *prototype) { prototype->setProperty(QStringLiteral("hostPlatform"), VariantValue::create(QString::fromStdString( HostOsInfo::hostOSIdentifier()))); prototype->setProperty(QStringLiteral("libexecPath"), VariantValue::create(m_parameters.libexecPath())); const Version qbsVersion = LanguageInfo::qbsVersion(); prototype->setProperty(QStringLiteral("versionMajor"), VariantValue::create(qbsVersion.majorVersion())); prototype->setProperty(QStringLiteral("versionMinor"), VariantValue::create(qbsVersion.minorVersion())); prototype->setProperty(QStringLiteral("versionPatch"), VariantValue::create(qbsVersion.patchLevel())); } static void collectItemsWithId_impl(Item *item, QList *result) { if (!item->id().isEmpty()) result->push_back(item); for (Item * const child : item->children()) collectItemsWithId_impl(child, result); } static QList collectItemsWithId(Item *item) { QList result; collectItemsWithId_impl(item, &result); return result; } static std::vector> instanceItemProperties(Item *item) { std::vector> result; QualifiedId name; std::function f = [&] (Item *item) { for (auto it = item->properties().begin(); it != item->properties().end(); ++it) { if (it.value()->type() != Value::ItemValueType) continue; ItemValuePtr itemValue = std::static_pointer_cast(it.value()); if (!itemValue->item()) continue; name.push_back(it.key()); if (itemValue->item()->type() == ItemType::ModulePrefix) f(itemValue->item()); else result.push_back(std::make_pair(name, itemValue)); name.removeLast(); } }; f(item); return result; } void ModuleLoader::instantiateModule(ProductContext *productContext, Item *exportingProduct, Item *instanceScope, Item *moduleInstance, Item *modulePrototype, const QualifiedId &moduleName, ProductModuleInfo *productModuleInfo) { Item *deepestModuleInstance = findDeepestModuleInstance(moduleInstance); deepestModuleInstance->setPrototype(modulePrototype); const QString fullName = moduleName.toString(); const QString generalOverrideKey = QStringLiteral("modules.") + fullName; const QString perProductOverrideKey = StringConstants::productsOverridePrefix() + productContext->name + QLatin1Char('.') + fullName; for (Item *instance = moduleInstance; instance; instance = instance->prototype()) { overrideItemProperties(instance, generalOverrideKey, m_parameters.overriddenValuesTree()); if (fullName == QStringLiteral("qbs")) overrideItemProperties(instance, fullName, m_parameters.overriddenValuesTree()); overrideItemProperties(instance, perProductOverrideKey, m_parameters.overriddenValuesTree()); if (instance == deepestModuleInstance) break; } moduleInstance->setFile(modulePrototype->file()); moduleInstance->setLocation(modulePrototype->location()); QBS_CHECK(moduleInstance->type() == ItemType::ModuleInstance); // create module scope Item *moduleScope = Item::create(m_pool, ItemType::Scope); QBS_CHECK(instanceScope->file()); moduleScope->setFile(instanceScope->file()); moduleScope->setScope(instanceScope); QBS_CHECK(productContext->project->scope); productContext->project->scope->copyProperty(StringConstants::projectVar(), moduleScope); if (productContext->scope) productContext->scope->copyProperty(StringConstants::productVar(), moduleScope); else QBS_CHECK(fullName == StringConstants::qbsModule()); // Dummy product. if (productModuleInfo) { exportingProduct = productModuleInfo->exportItem->parent(); QBS_CHECK(exportingProduct); QBS_CHECK(exportingProduct->type() == ItemType::Product); } if (exportingProduct) { // TODO: For consistency with modules, it should be the other way around, i.e. // "exportingProduct" and just "product". moduleScope->setProperty(StringConstants::productVar(), ItemValue::create(exportingProduct)); moduleScope->setProperty(QStringLiteral("importingProduct"), ItemValue::create(productContext->item)); moduleScope->setProperty(StringConstants::projectVar(), ItemValue::create(exportingProduct->parent())); PropertyDeclaration pd(StringConstants::qbsSourceDirPropertyInternal(), PropertyDeclaration::String, QString(), PropertyDeclaration::PropertyNotAvailableInConfig); moduleInstance->setPropertyDeclaration(pd.name(), pd); ValuePtr v = exportingProduct ->property(StringConstants::sourceDirectoryProperty())->clone(); moduleInstance->setProperty(pd.name(), v); } moduleInstance->setScope(moduleScope); QHash prototypeInstanceMap; prototypeInstanceMap[modulePrototype] = moduleInstance; // create instances for every child of the prototype createChildInstances(moduleInstance, modulePrototype, &prototypeInstanceMap); // create ids from from the prototype in the instance if (modulePrototype->file()->idScope()) { for (Item * const itemWithId : collectItemsWithId(modulePrototype)) { Item *idProto = itemWithId; Item *idInstance = prototypeInstanceMap.value(idProto); QBS_ASSERT(idInstance, continue); ItemValuePtr idInstanceValue = ItemValue::create(idInstance); moduleScope->setProperty(itemWithId->id(), idInstanceValue); } } // For foo.bar in modulePrototype create an item foo in moduleInstance. for (const auto &iip : instanceItemProperties(modulePrototype)) { if (iip.second->item()->properties().empty()) continue; qCDebug(lcModuleLoader) << "The prototype of " << moduleName << " sets properties on " << iip.first.toString(); Item *item = moduleInstanceItem(moduleInstance, iip.first); item->setPrototype(iip.second->item()); if (iip.second->createdByPropertiesBlock()) { ItemValuePtr itemValue = moduleInstance->itemProperty(iip.first.front()); for (int i = 1; i < iip.first.size(); ++i) itemValue = itemValue->item()->itemProperty(iip.first.at(i)); itemValue->setCreatedByPropertiesBlock(true); } } // Resolve dependencies of this module instance. DependsContext dependsContext; dependsContext.product = productContext; dependsContext.exportingProductItem = exportingProduct; QBS_ASSERT(moduleInstance->modules().empty(), moduleInstance->removeModules()); if (productModuleInfo) { dependsContext.productDependencies = &productContext->productModuleDependencies[fullName]; resolveDependencies(&dependsContext, moduleInstance); } else if (!isBaseModule(moduleName)) { dependsContext.productDependencies = &productContext->info.usedProducts; resolveDependencies(&dependsContext, moduleInstance); } // Check readonly properties. const auto end = moduleInstance->properties().cend(); for (auto it = moduleInstance->properties().cbegin(); it != end; ++it) { const PropertyDeclaration &pd = moduleInstance->propertyDeclaration(it.key()); if (!pd.flags().testFlag(PropertyDeclaration::ReadOnlyFlag)) continue; throw ErrorInfo(Tr::tr("Cannot set read-only property '%1'.").arg(pd.name()), moduleInstance->property(pd.name())->location()); } } void ModuleLoader::createChildInstances(Item *instance, Item *prototype, QHash *prototypeInstanceMap) const { instance->childrenReserve(instance->children().size() + prototype->children().size()); for (Item * const childPrototype : prototype->children()) { Item *childInstance = Item::create(m_pool, childPrototype->type()); prototypeInstanceMap->insert(childPrototype, childInstance); childInstance->setPrototype(childPrototype); childInstance->setFile(childPrototype->file()); childInstance->setId(childPrototype->id()); childInstance->setLocation(childPrototype->location()); childInstance->setScope(instance->scope()); Item::addChild(instance, childInstance); createChildInstances(childInstance, childPrototype, prototypeInstanceMap); } } void ModuleLoader::resolveProbes(ProductContext *productContext, Item *item) { AccumulatingTimer probesTimer(m_parameters.logElapsedTime() ? &m_elapsedTimeProbes : nullptr); EvalContextSwitcher evalContextSwitcher(m_evaluator->engine(), EvalContext::ProbeExecution); for (Item * const child : item->children()) if (child->type() == ItemType::Probe) resolveProbe(productContext, item, child); } void ModuleLoader::resolveProbe(ProductContext *productContext, Item *parent, Item *probe) { qCDebug(lcModuleLoader) << "Resolving Probe at " << probe->location().toString(); ++m_probesEncountered; const QString &probeId = probeGlobalId(probe); if (Q_UNLIKELY(probeId.isEmpty())) throw ErrorInfo(Tr::tr("Probe.id must be set."), probe->location()); const JSSourceValueConstPtr configureScript = probe->sourceProperty(StringConstants::configureProperty()); QBS_CHECK(configureScript); if (Q_UNLIKELY(configureScript->sourceCode() == StringConstants::undefinedValue())) throw ErrorInfo(Tr::tr("Probe.configure must be set."), probe->location()); using ProbeProperty = std::pair; QList probeBindings; QVariantMap initialProperties; for (Item *obj = probe; obj; obj = obj->prototype()) { const Item::PropertyMap &props = obj->properties(); for (auto it = props.cbegin(); it != props.cend(); ++it) { const QString &name = it.key(); if (name == StringConstants::configureProperty()) continue; const QScriptValue value = m_evaluator->value(probe, name); probeBindings += ProbeProperty(name, value); if (name != StringConstants::conditionProperty()) initialProperties.insert(name, value.toVariant()); } } ScriptEngine * const engine = m_evaluator->engine(); QScriptValue configureScope; const bool condition = m_evaluator->boolValue(probe, StringConstants::conditionProperty()); const QString &sourceCode = configureScript->sourceCode().toString(); ProbeConstPtr resolvedProbe; if (parent->type() == ItemType::Project || productContext->name.startsWith(shadowProductPrefix())) { resolvedProbe = findOldProjectProbe(probeId, condition, initialProperties, sourceCode); } else { const QString &uniqueProductName = productContext->uniqueName(); resolvedProbe = findOldProductProbe(uniqueProductName, condition, initialProperties, sourceCode); } if (!resolvedProbe) { resolvedProbe = findCurrentProbe(probe->location(), condition, initialProperties); if (resolvedProbe) { qCDebug(lcModuleLoader) << "probe results cached from current run"; ++m_probesCachedCurrent; } } else { qCDebug(lcModuleLoader) << "probe results cached from earlier run"; ++m_probesCachedOld; } std::vector importedFilesUsedInConfigure; if (!condition) { qCDebug(lcModuleLoader) << "Probe disabled; skipping"; } else if (!resolvedProbe) { ++m_probesRun; qCDebug(lcModuleLoader) << "configure script needs to run"; const Evaluator::FileContextScopes fileCtxScopes = m_evaluator->fileContextScopes(configureScript->file()); engine->currentContext()->pushScope(fileCtxScopes.fileScope); engine->currentContext()->pushScope(fileCtxScopes.importScope); configureScope = engine->newObject(); for (const ProbeProperty &b : qAsConst(probeBindings)) configureScope.setProperty(b.first, b.second); engine->currentContext()->pushScope(configureScope); engine->clearRequestedProperties(); QScriptValue sv = engine->evaluate(configureScript->sourceCodeForEvaluation()); engine->currentContext()->popScope(); engine->currentContext()->popScope(); engine->currentContext()->popScope(); engine->releaseResourcesOfScriptObjects(); if (Q_UNLIKELY(engine->hasErrorOrException(sv))) throw ErrorInfo(engine->lastErrorString(sv), configureScript->location()); importedFilesUsedInConfigure = engine->importedFilesUsedInScript(); } else { importedFilesUsedInConfigure = resolvedProbe->importedFilesUsed(); } QVariantMap properties; for (const ProbeProperty &b : qAsConst(probeBindings)) { QVariant newValue; if (resolvedProbe) { newValue = resolvedProbe->properties().value(b.first); } else { if (condition) { QScriptValue v = configureScope.property(b.first); m_evaluator->convertToPropertyType(probe->propertyDeclaration( b.first), probe->location(), v); if (Q_UNLIKELY(engine->hasErrorOrException(v))) throw ErrorInfo(engine->lastError(v)); newValue = v.toVariant(); } else { newValue = initialProperties.value(b.first); } } if (newValue != b.second.toVariant()) probe->setProperty(b.first, VariantValue::create(newValue)); if (!resolvedProbe) properties.insert(b.first, newValue); } if (!resolvedProbe) { resolvedProbe = Probe::create(probeId, probe->location(), condition, sourceCode, properties, initialProperties, importedFilesUsedInConfigure); m_currentProbes[probe->location()] << resolvedProbe; } productContext->info.probes << resolvedProbe; } void ModuleLoader::checkCancelation() const { if (m_progressObserver && m_progressObserver->canceled()) { throw ErrorInfo(Tr::tr("Project resolving canceled for configuration %1.") .arg(TopLevelProject::deriveId(m_parameters.finalBuildConfigurationTree()))); } } bool ModuleLoader::checkItemCondition(Item *item, Item *itemToDisable) { if (m_evaluator->boolValue(item, StringConstants::conditionProperty())) return true; m_disabledItems += itemToDisable ? itemToDisable : item; return false; } QStringList ModuleLoader::readExtraSearchPaths(Item *item, bool *wasSet) { QStringList result; const QStringList paths = m_evaluator->stringListValue( item, StringConstants::qbsSearchPathsProperty(), wasSet); const JSSourceValueConstPtr prop = item->sourceProperty( StringConstants::qbsSearchPathsProperty()); // Value can come from within a project file or as an overridden value from the user // (e.g command line). const QString basePath = FileInfo::path(prop ? prop->file()->filePath() : m_parameters.projectFilePath()); for (const QString &path : paths) result += FileInfo::resolvePath(basePath, path); return result; } void ModuleLoader::copyProperties(const Item *sourceProject, Item *targetProject) { if (!sourceProject) return; const QList builtinProjectProperties = BuiltinDeclarations::instance() .declarationsForType(ItemType::Project).properties(); Set builtinProjectPropertyNames; for (const PropertyDeclaration &p : builtinProjectProperties) builtinProjectPropertyNames << p.name(); for (Item::PropertyDeclarationMap::ConstIterator it = sourceProject->propertyDeclarations().constBegin(); it != sourceProject->propertyDeclarations().constEnd(); ++it) { // We must not inherit built-in properties such as "name", // but there are exceptions. if (it.key() == StringConstants::qbsSearchPathsProperty() || it.key() == StringConstants::profileProperty() || it.key() == StringConstants::buildDirectoryProperty() || it.key() == StringConstants::sourceDirectoryProperty() || it.key() == StringConstants::minimumQbsVersionProperty()) { const JSSourceValueConstPtr &v = targetProject->sourceProperty(it.key()); QBS_ASSERT(v, continue); if (v->sourceCode() == StringConstants::undefinedValue()) sourceProject->copyProperty(it.key(), targetProject); continue; } if (builtinProjectPropertyNames.contains(it.key())) continue; if (targetProject->hasOwnProperty(it.key())) continue; // Ignore stuff the target project already has. targetProject->setPropertyDeclaration(it.key(), it.value()); sourceProject->copyProperty(it.key(), targetProject); } } Item *ModuleLoader::wrapInProjectIfNecessary(Item *item) { if (item->type() == ItemType::Project) return item; Item *prj = Item::create(item->pool(), ItemType::Project); Item::addChild(prj, item); prj->setFile(item->file()); prj->setLocation(item->location()); prj->setupForBuiltinType(m_logger); return prj; } QString ModuleLoader::findExistingModulePath(const QString &searchPath, const QualifiedId &moduleName) { QString dirPath = searchPath + QStringLiteral("/modules"); for (const QString &moduleNamePart : moduleName) { dirPath = FileInfo::resolvePath(dirPath, moduleNamePart); if (!FileInfo::exists(dirPath) || !FileInfo::isFileCaseCorrect(dirPath)) return {}; } return dirPath; } QVariantMap ModuleLoader::moduleProviderConfig(ModuleLoader::ProductContext &product) { if (product.moduleProviderConfigRetrieved) return product.theModuleProviderConfig; const ItemValueConstPtr configItemValue = product.item->itemProperty(StringConstants::moduleProviders()); if (configItemValue) { const std::function collectMap = [this, &product, &collectMap](const Item *item, QualifiedId name) { const Item::PropertyMap &props = item->properties(); for (auto it = props.begin(); it != props.end(); ++it) { QVariant value; switch (it.value()->type()) { case Value::ItemValueType: collectMap(static_cast(it.value().get())->item(), QualifiedId(name += it.key())); return; case Value::JSSourceValueType: value = m_evaluator->value(item, it.key()).toVariant(); break; case Value::VariantValueType: value = static_cast(it.value().get())->value(); break; } QVariantMap m = product.theModuleProviderConfig.value(name.toString()).toMap(); m.insert(it.key(), value); product.theModuleProviderConfig.insert(name.toString(), m); } }; collectMap(configItemValue->item(), QualifiedId()); } for (auto it = product.moduleProperties.begin(); it != product.moduleProperties.end(); ++it) { if (!it.key().startsWith(QStringLiteral("moduleProviders."))) continue; const QString provider = it.key().mid(QStringLiteral("moduleProviders.").size()); const QVariantMap providerConfigFromBuildConfig = it.value().toMap(); if (providerConfigFromBuildConfig.empty()) continue; QVariantMap currentMapForProvider = product.theModuleProviderConfig.value(provider).toMap(); for (auto propIt = providerConfigFromBuildConfig.begin(); propIt != providerConfigFromBuildConfig.end(); ++propIt) { currentMapForProvider.insert(propIt.key(), propIt.value()); } product.theModuleProviderConfig.insert(provider, currentMapForProvider); } product.moduleProviderConfigRetrieved = true; return product.theModuleProviderConfig; } ModuleLoader::ModuleProviderResult ModuleLoader::findModuleProvider(const QualifiedId &name, ModuleLoader::ProductContext &product, ModuleProviderLookup lookupType, const CodeLocation &dependsItemLocation) { for (const QString &path : m_reader->allSearchPaths()) { QString fullPath = FileInfo::resolvePath(path, QStringLiteral("module-providers")); switch (lookupType) { case ModuleProviderLookup::Regular: for (const QString &component : name) fullPath = FileInfo::resolvePath(fullPath, component); break; case ModuleProviderLookup::Fallback: fullPath = FileInfo::resolvePath(fullPath, QStringLiteral("__fallback")); break; } const QString providerFile = FileInfo::resolvePath(fullPath, QStringLiteral("provider.qbs")); if (!FileInfo::exists(providerFile)) { qCDebug(lcModuleLoader) << "No module provider found at" << providerFile; continue; } QTemporaryFile dummyItemFile; if (!dummyItemFile.open()) { throw ErrorInfo(Tr::tr("Failed to create temporary file for running module provider " "for dependency '%1': %2").arg(name.toString(), dummyItemFile.errorString())); } m_tempQbsFiles << dummyItemFile.fileName(); qCDebug(lcModuleLoader) << "Instantiating module provider at" << providerFile; const QString projectBuildDir = product.project->item->variantProperty( StringConstants::buildDirectoryProperty())->value().toString(); const QString searchPathBaseDir = ModuleProviderInfo::outputDirPath(projectBuildDir, name); const QVariant moduleConfig = moduleProviderConfig(product).value(name.toString()); QTextStream stream(&dummyItemFile); stream.setCodec("UTF-8"); stream << "import qbs.FileInfo" << endl; stream << "import qbs.Utilities" << endl; stream << "import '" << providerFile << "' as Provider" << endl; stream << "Provider {" << endl; stream << " name: " << toJSLiteral(name.toString()) << endl; stream << " property var config: (" << toJSLiteral(moduleConfig) << ')' << endl; stream << " outputBaseDir: FileInfo.joinPaths(baseDirPrefix, " " Utilities.getHash(JSON.stringify(config)))" << endl; stream << " property string baseDirPrefix: " << toJSLiteral(searchPathBaseDir) << endl; stream << " property stringList searchPaths: (relativeSearchPaths || [])" " .map(function(p) { return FileInfo.joinPaths(outputBaseDir, p); })" << endl; stream << "}" << endl; stream.flush(); Item * const providerItem = loadItemFromFile(dummyItemFile.fileName(), dependsItemLocation); if (providerItem->type() != ItemType::ModuleProvider) { throw ErrorInfo(Tr::tr("File '%1' declares an item of type '%2', " "but '%3' was expected.") .arg(providerFile, providerItem->typeName(), BuiltinDeclarations::instance().nameForType(ItemType::ModuleProvider))); } providerItem->setParent(product.item); const QVariantMap configMap = moduleConfig.toMap(); for (auto it = configMap.begin(); it != configMap.end(); ++it) { const PropertyDeclaration decl = providerItem->propertyDeclaration(it.key()); if (!decl.isValid()) { throw ErrorInfo(Tr::tr("No such property '%1' in module provider '%2'.") .arg(it.key(), name.toString())); } providerItem->setProperty(it.key(), VariantValue::create(it.value())); } EvalContextSwitcher contextSwitcher(m_evaluator->engine(), EvalContext::ModuleProvider); const QStringList searchPaths = m_evaluator->stringListValue(providerItem, QStringLiteral("searchPaths")); const auto addToGlobalInfo = [=] { m_moduleProviderInfo.emplace_back(ModuleProviderInfo(name, moduleConfig.toMap(), searchPaths, m_parameters.dryRun())); }; if (searchPaths.empty()) { qCDebug(lcModuleLoader) << "Module provider did run, but did not set up " "any modules."; addToGlobalInfo(); return {true, false}; } qCDebug(lcModuleLoader) << "Module provider added" << searchPaths.size() << "new search path(s)"; // (1) is needed so the immediate new look-up works. // (2) is needed so the next use of SearchPathManager considers the new paths. // (3) is needed for the code that removes the product-specific search paths when // product handling is done. // (4) is needed for possible re-use in subsequent products and builds. m_reader->pushExtraSearchPaths(searchPaths); // (1) product.searchPaths << searchPaths; // (2) product.newlyAddedModuleProviderSearchPaths.push_back(searchPaths); // (3) addToGlobalInfo(); // (4) return {true, true}; } return {}; } void ModuleLoader::setScopeForDescendants(Item *item, Item *scope) { for (Item * const child : item->children()) { child->setScope(scope); setScopeForDescendants(child, scope); } } void ModuleLoader::overrideItemProperties(Item *item, const QString &buildConfigKey, const QVariantMap &buildConfig) { const QVariant buildConfigValue = buildConfig.value(buildConfigKey); if (buildConfigValue.isNull()) return; const QVariantMap overridden = buildConfigValue.toMap(); for (QVariantMap::const_iterator it = overridden.constBegin(); it != overridden.constEnd(); ++it) { const PropertyDeclaration decl = item->propertyDeclaration(it.key()); if (!decl.isValid()) { ErrorInfo error(Tr::tr("Unknown property: %1.%2").arg(buildConfigKey, it.key())); handlePropertyError(error, m_parameters, m_logger); continue; } item->setProperty(it.key(), VariantValue::create(convertToPropertyType(it.value(), decl.type(), QStringList(buildConfigKey), it.key()))); } } void ModuleLoader::collectAllModules(Item *item, std::vector *modules) { for (const Item::Module &m : item->modules()) { if (moduleRepresentsDisabledProduct(m)) m.item->removeModules(); auto it = std::find_if(modules->begin(), modules->end(), [m] (const Item::Module &m2) { return m.name == m2.name; }); if (it != modules->end()) { // If a module is required somewhere, it is required in the top-level item. if (m.required) it->required = true; it->versionRange.narrowDown(m.versionRange); continue; } modules->push_back(m); collectAllModules(m.item, modules); } } std::vector ModuleLoader::allModules(Item *item) { std::vector lst; collectAllModules(item, &lst); return lst; } bool ModuleLoader::moduleRepresentsDisabledProduct(const Item::Module &module) { if (!module.isProduct) return false; const Item *exportItem = module.item->prototype(); while (exportItem && exportItem->type() != ItemType::Export) exportItem = exportItem->prototype(); QBS_CHECK(exportItem); Item * const productItem = exportItem->parent(); QBS_CHECK(productItem->type() == ItemType::Product); return m_disabledItems.contains(productItem) || !checkItemCondition(productItem); } void ModuleLoader::addProductModuleDependencies(ProductContext *productContext, const QString &name) { auto deps = productContext->productModuleDependencies.at(name); QList depsToAdd; const bool productIsMultiplexed = !productContext->multiplexConfigurationId.isEmpty(); for (auto &dep : deps) { const auto productRange = m_productsByName.equal_range(dep.name); std::vector dependencies; bool hasNonMultiplexedDependency = false; for (auto it = productRange.first; it != productRange.second; ++it) { if (!it->second->multiplexConfigurationId.isEmpty()) { dependencies.push_back(it->second); if (productIsMultiplexed && dep.profile.isEmpty()) break; } else { hasNonMultiplexedDependency = true; break; } } if (hasNonMultiplexedDependency) { depsToAdd.push_back(dep); continue; } for (std::size_t i = 0; i < dependencies.size(); ++i) { const bool profileMatch = dep.profile.isEmpty() || dep.profile == StringConstants::star() || dep.profile == dependencies.at(i)->profileName; if (i == 0) { if (productIsMultiplexed && dep.profile.isEmpty()) { const ValuePtr &multiplexConfigIdProp = productContext->item->property( StringConstants::multiplexConfigurationIdProperty()); dep.multiplexConfigurationId = std::static_pointer_cast( multiplexConfigIdProp)->value().toString(); depsToAdd.push_back(dep); break; } else if (profileMatch) { dep.multiplexConfigurationId = dependencies.at(i)->multiplexConfigurationId; depsToAdd.push_back(dep); } } else if (profileMatch) { ModuleLoaderResult::ProductInfo::Dependency newDependency = dep; newDependency.multiplexConfigurationId = dependencies.at(i)->multiplexConfigurationId; depsToAdd << newDependency; } } } productContext->info.usedProducts.insert(productContext->info.usedProducts.end(), depsToAdd.cbegin(), depsToAdd.cend()); } static void collectProductModuleDependencies(Item *item, Set &allDeps) { for (const Item::Module &m : item->modules()) { if (m.isProduct && allDeps.insert(m.name).second) collectProductModuleDependencies(m.item, allDeps); } } void ModuleLoader::addProductModuleDependencies(ModuleLoader::ProductContext *ctx) { Set deps; collectProductModuleDependencies(ctx->item, deps); for (const QualifiedId &dep : deps) addProductModuleDependencies(ctx, dep.toString()); } void ModuleLoader::addTransitiveDependencies(ProductContext *ctx) { AccumulatingTimer timer(m_parameters.logElapsedTime() ? &m_elapsedTimeTransitiveDependencies : nullptr); qCDebug(lcModuleLoader) << "addTransitiveDependencies"; std::vector transitiveDeps = allModules(ctx->item); std::sort(transitiveDeps.begin(), transitiveDeps.end()); for (const Item::Module &m : ctx->item->modules()) { auto it = std::lower_bound(transitiveDeps.begin(), transitiveDeps.end(), m); QBS_CHECK(it != transitiveDeps.end() && it->name == m.name); transitiveDeps.erase(it); } for (const Item::Module &module : qAsConst(transitiveDeps)) { if (module.isProduct) { ctx->item->addModule(module); } else { Item::Module dep; dep.item = loadModule(ctx, nullptr, ctx->item, ctx->item->location(), QString(), module.name, QString(), FallbackMode::Disabled, module.required, &dep.isProduct, &dep.parameters); if (!dep.item) { throw ErrorInfo(Tr::tr("Module '%1' not found when setting up transitive " "dependencies for product '%2'.").arg(module.name.toString(), ctx->name), ctx->item->location()); } dep.name = module.name; dep.required = module.required; dep.versionRange = module.versionRange; ctx->item->addModule(dep); } } } Item *ModuleLoader::createNonPresentModule(const QString &name, const QString &reason, Item *module) { qCDebug(lcModuleLoader) << "Non-required module '" << name << "' not loaded (" << reason << ")." << "Creating dummy module for presence check."; if (!module) { module = Item::create(m_pool, ItemType::ModuleInstance); module->setFile(FileContext::create()); module->setProperty(StringConstants::nameProperty(), VariantValue::create(name)); } module->setProperty(StringConstants::presentProperty(), VariantValue::falseValue()); return module; } void ModuleLoader::handleProductError(const ErrorInfo &error, ModuleLoader::ProductContext *productContext) { const bool alreadyHadError = productContext->info.delayedError.hasError(); if (!alreadyHadError) { productContext->info.delayedError.append(Tr::tr("Error while handling product '%1':") .arg(productContext->name), productContext->item->location()); } if (error.isInternalError()) { if (alreadyHadError) { qCDebug(lcModuleLoader()) << "ignoring subsequent internal error" << error.toString() << "in product" << productContext->name; return; } const auto &deps = productContext->productModuleDependencies; for (auto it = deps.cbegin(); it != deps.cend(); ++it) { const auto rangeForName = m_productsByName.equal_range(it->first); for (auto rangeIt = rangeForName.first; rangeIt != rangeForName.second; ++rangeIt) { const ProductContext * const dep = rangeIt->second; if (dep->info.delayedError.hasError()) { qCDebug(lcModuleLoader()) << "ignoring internal error" << error.toString() << "in product" << productContext->name << "assumed to be caused by erroneous dependency" << dep->name; return; } } } } for (const ErrorItem &ei : error.items()) productContext->info.delayedError.append(ei.description(), ei.codeLocation()); productContext->project->result->productInfos.insert(productContext->item, productContext->info); m_disabledItems << productContext->item; m_erroneousProducts.insert(productContext->name); } static void gatherAssignedProperties(ItemValue *iv, const QualifiedId &prefix, QualifiedIdSet &properties) { const Item::PropertyMap &props = iv->item()->properties(); for (auto it = props.cbegin(); it != props.cend(); ++it) { switch (it.value()->type()) { case Value::JSSourceValueType: properties << (QualifiedId(prefix) << it.key()); break; case Value::ItemValueType: if (iv->item()->type() == ItemType::ModulePrefix) { gatherAssignedProperties(std::static_pointer_cast(it.value()).get(), QualifiedId(prefix) << it.key(), properties); } break; default: break; } } } QualifiedIdSet ModuleLoader::gatherModulePropertiesSetInGroup(const Item *group) { QualifiedIdSet propsSetInGroup; const Item::PropertyMap &props = group->properties(); for (auto it = props.cbegin(); it != props.cend(); ++it) { if (it.value()->type() == Value::ItemValueType) { gatherAssignedProperties(std::static_pointer_cast(it.value()).get(), QualifiedId(it.key()), propsSetInGroup); } } return propsSetInGroup; } void ModuleLoader::markModuleTargetGroups(Item *group, const Item::Module &module) { QBS_CHECK(group->type() == ItemType::Group); if (m_evaluator->boolValue(group, StringConstants::filesAreTargetsProperty())) { group->setProperty(StringConstants::modulePropertyInternal(), VariantValue::create(module.name.toString())); } for (Item * const child : group->children()) markModuleTargetGroups(child, module); } void ModuleLoader::copyGroupsFromModuleToProduct(const ProductContext &productContext, const Item::Module &module, const Item *modulePrototype) { for (Item * const child : modulePrototype->children()) { if (child->type() == ItemType::Group) { Item * const clonedGroup = child->clone(); clonedGroup->setScope(productContext.scope); setScopeForDescendants(clonedGroup, productContext.scope); Item::addChild(productContext.item, clonedGroup); markModuleTargetGroups(clonedGroup, module); } } } void ModuleLoader::copyGroupsFromModulesToProduct(const ProductContext &productContext) { for (const Item::Module &module : productContext.item->modules()) { Item *prototype = module.item; bool modulePassedValidation; while ((modulePassedValidation = prototype->isPresentModule()) && prototype->prototype()) prototype = prototype->prototype(); if (modulePassedValidation) copyGroupsFromModuleToProduct(productContext, module, prototype); } } QString ModuleLoaderResult::ProductInfo::Dependency::uniqueName() const { return ResolvedProduct::uniqueName(name, multiplexConfigurationId); } QString ModuleLoader::ProductContext::uniqueName() const { return ResolvedProduct::uniqueName(name, multiplexConfigurationId); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/moduleloader.h000066400000000000000000000510761347155106100225470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_MODULELOADER_H #define QBS_MODULELOADER_H #include "filetags.h" #include "forward_decls.h" #include "item.h" #include "itempool.h" #include "moduleproviderinfo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { class CodeLocation; class Settings; namespace Internal { class Evaluator; class Item; class ItemReader; class ProgressObserver; class QualifiedId; using ModulePropertiesPerGroup = std::unordered_map; struct ModuleLoaderResult { ModuleLoaderResult() : itemPool(new ItemPool), root(nullptr) {} struct ProductInfo { struct Dependency { QString name; QString profile; // "*" <=> Match all profiles. QString multiplexConfigurationId; QVariantMap parameters; bool limitToSubProject = false; bool isRequired = true; QString uniqueName() const; }; std::vector probes; std::vector usedProducts; ModulePropertiesPerGroup modulePropertiesSetInGroups; ErrorInfo delayedError; }; std::shared_ptr itemPool; Item *root; QHash productInfos; std::vector projectProbes; ModuleProviderInfoList moduleProviderInfo; Set qbsFiles; QVariantMap profileConfigs; }; /* * Loader stage II. Responsible for * - loading modules and module dependencies, * - project references, * - Probe items. */ class ModuleLoader { public: ModuleLoader(Evaluator *evaluator, Logger &logger); ~ModuleLoader(); void setProgressObserver(ProgressObserver *progressObserver); void setSearchPaths(const QStringList &searchPaths); void setOldProjectProbes(const std::vector &oldProbes); void setOldProductProbes(const QHash> &oldProbes); void setLastResolveTime(const FileTime &time) { m_lastResolveTime = time; } void setStoredProfiles(const QVariantMap &profiles); void setStoredModuleProviderInfo(const ModuleProviderInfoList &moduleProviderInfo); Evaluator *evaluator() const { return m_evaluator; } ModuleLoaderResult load(const SetupProjectParameters ¶meters); private: class ProductSortByDependencies; class ContextBase { public: ContextBase() : item(nullptr), scope(nullptr) {} Item *item; Item *scope; QString name; }; class ProjectContext; using ProductDependencies = std::vector; // This is the data we need to store at the point where a dependency is deferred // in order to properly resolve the dependency in pass 2. struct DeferredDependsContext { DeferredDependsContext(Item *exportingProduct, Item *parent) : exportingProductItem(exportingProduct), parentItem(parent) {} Item *exportingProductItem = nullptr; Item *parentItem = nullptr; bool operator==(const DeferredDependsContext &other) const { return exportingProductItem == other.exportingProductItem && parentItem == other.parentItem; } bool operator<(const DeferredDependsContext &other) const { return parentItem < other.parentItem; } }; class ProductContext : public ContextBase { public: ProjectContext *project; ModuleLoaderResult::ProductInfo info; QString profileName; QString multiplexConfigurationId; QVariantMap moduleProperties; std::map productModuleDependencies; std::unordered_map> unknownProfilePropertyErrors; QStringList searchPaths; std::vector newlyAddedModuleProviderSearchPaths; Set knownModuleProviders; QVariantMap theModuleProviderConfig; bool moduleProviderConfigRetrieved = false; // The key corresponds to DeferredDependsContext.exportingProductItem, which is the // only value from that data structure that we still need here. std::unordered_map> deferredDependsItems; QString uniqueName() const; }; class TopLevelProjectContext; class ProjectContext : public ContextBase { public: TopLevelProjectContext *topLevelProject; ModuleLoaderResult *result; std::vector products; std::vector searchPathsStack; }; struct ProductModuleInfo { Item *exportItem = nullptr; QString multiplexId; QVariantMap defaultParameters; }; class TopLevelProjectContext { Q_DISABLE_COPY(TopLevelProjectContext) public: TopLevelProjectContext() {} ~TopLevelProjectContext() { qDeleteAll(projects); } std::vector projects; QMultiHash productModules; std::vector probes; QString buildDirectory; }; class DependsContext { public: ProductContext *product = nullptr; Item *exportingProductItem = nullptr; ProductDependencies *productDependencies; }; void handleTopLevelProject(ModuleLoaderResult *loadResult, Item *projectItem, const QString &buildDirectory, const Set &referencedFilePaths); void handleProject(ModuleLoaderResult *loadResult, TopLevelProjectContext *topLevelProjectContext, Item *projectItem, const Set &referencedFilePaths); using MultiplexRow = std::vector; using MultiplexTable = std::vector; struct MultiplexInfo { std::vector properties; MultiplexTable table; bool aggregate = false; VariantValuePtr multiplexedType; QString toIdString(size_t row) const; }; void dump(const MultiplexInfo &mpi); static MultiplexTable combine(const MultiplexTable &table, const MultiplexRow &values); MultiplexInfo extractMultiplexInfo(Item *productItem, Item *qbsModuleItem); QList multiplexProductItem(ProductContext *dummyContext, Item *productItem); void normalizeDependencies(ProductContext *product, const DeferredDependsContext &dependsContext); void adjustDependenciesForMultiplexing(const TopLevelProjectContext &tlp); void adjustDependenciesForMultiplexing(const ProductContext &product); void adjustDependenciesForMultiplexing(const ProductContext &product, Item *dependsItem); void prepareProduct(ProjectContext *projectContext, Item *productItem); void setupProductDependencies(ProductContext *productContext, const Set &deferredDependsContext); void handleProduct(ProductContext *productContext); void checkDependencyParameterDeclarations(const ProductContext *productContext) const; void handleModuleSetupError(ProductContext *productContext, const Item::Module &module, const ErrorInfo &error); void initProductProperties(const ProductContext &product); void handleSubProject(ProjectContext *projectContext, Item *projectItem, const Set &referencedFilePaths); QList loadReferencedFile(const QString &relativePath, const CodeLocation &referencingLocation, const Set &referencedFilePaths, ProductContext &dummyContext); void handleAllPropertyOptionsItems(Item *item); void handlePropertyOptions(Item *optionsItem); using ModuleDependencies = QHash; void setupReverseModuleDependencies(const Item::Module &module, ModuleDependencies &deps, QualifiedIdSet &seenModules); ModuleDependencies setupReverseModuleDependencies(const Item *product); void handleGroup(ProductContext *productContext, Item *groupItem, const ModuleDependencies &reverseDepencencies); void propagateModulesFromParent(ProductContext *productContext, Item *groupItem, const ModuleDependencies &reverseDepencencies); void adjustDefiningItemsInGroupModuleInstances(const Item::Module &module, const Item::Modules &dependentModules); bool mergeExportItems(const ProductContext &productContext); void resolveDependencies(DependsContext *dependsContext, Item *item, ProductContext *productContext = nullptr); class ItemModuleList; void resolveDependsItem(DependsContext *dependsContext, Item *parentItem, Item *dependsItem, ItemModuleList *moduleResults, ProductDependencies *productResults); void forwardParameterDeclarations(const Item *dependsItem, const ItemModuleList &modules); void forwardParameterDeclarations(const QualifiedId &moduleName, Item *item, const ItemModuleList &modules); void resolveParameterDeclarations(const Item *module); QVariantMap extractParameters(Item *dependsItem) const; Item *moduleInstanceItem(Item *containerItem, const QualifiedId &moduleName); static ProductModuleInfo *productModule(ProductContext *productContext, const QString &name, const QString &multiplexId, bool &productNameMatch); static ProductContext *product(ProjectContext *projectContext, const QString &name); static ProductContext *product(TopLevelProjectContext *tlpContext, const QString &name); enum class FallbackMode { Enabled, Disabled }; Item *loadModule(ProductContext *productContext, Item *exportingProductItem, Item *item, const CodeLocation &dependsItemLocation, const QString &moduleId, const QualifiedId &moduleName, const QString &multiplexId, FallbackMode fallbackMode, bool isRequired, bool *isProductDependency, QVariantMap *defaultParameters); Item *searchAndLoadModuleFile(ProductContext *productContext, const CodeLocation &dependsItemLocation, const QualifiedId &moduleName, FallbackMode fallbackMode, bool isRequired, Item *moduleInstance); Item *loadModuleFile(ProductContext *productContext, const QString &fullModuleName, bool isBaseModule, const QString &filePath, bool *triedToLoad, Item *moduleInstance); Item *getModulePrototype(ProductContext *productContext, const QString &fullModuleName, const QString &filePath, bool *triedToLoad); Item::Module loadBaseModule(ProductContext *productContext, Item *item); void setupBaseModulePrototype(Item *prototype); template T callWithTemporaryBaseModule(ProductContext *productContext, const F &func); void instantiateModule(ProductContext *productContext, Item *exportingProductItem, Item *instanceScope, Item *moduleInstance, Item *modulePrototype, const QualifiedId &moduleName, ProductModuleInfo *productModuleInfo); void createChildInstances(Item *instance, Item *prototype, QHash *prototypeInstanceMap) const; void resolveProbes(ProductContext *productContext, Item *item); void resolveProbe(ProductContext *productContext, Item *parent, Item *probe); void checkCancelation() const; bool checkItemCondition(Item *item, Item *itemToDisable = nullptr); QStringList readExtraSearchPaths(Item *item, bool *wasSet = nullptr); void copyProperties(const Item *sourceProject, Item *targetProject); Item *wrapInProjectIfNecessary(Item *item); static QString findExistingModulePath(const QString &searchPath, const QualifiedId &moduleName); enum class ModuleProviderLookup { Regular, Fallback }; struct ModuleProviderResult { ModuleProviderResult() = default; ModuleProviderResult(bool ran, bool added) : providerFound(ran), providerAddedSearchPaths(added) {} bool providerFound = false; bool providerAddedSearchPaths = false; }; ModuleProviderResult findModuleProvider(const QualifiedId &name, ProductContext &product, ModuleProviderLookup lookupType, const CodeLocation &dependsItemLocation); QVariantMap moduleProviderConfig(ProductContext &product); static void setScopeForDescendants(Item *item, Item *scope); void overrideItemProperties(Item *item, const QString &buildConfigKey, const QVariantMap &buildConfig); void addProductModuleDependencies(ProductContext *ctx, const QString &name); void addProductModuleDependencies(ProductContext *ctx); void addTransitiveDependencies(ProductContext *ctx); Item *createNonPresentModule(const QString &name, const QString &reason, Item *module); void copyGroupsFromModuleToProduct(const ProductContext &productContext, const Item::Module &module, const Item *modulePrototype); void copyGroupsFromModulesToProduct(const ProductContext &productContext); void markModuleTargetGroups(Item *group, const Item::Module &module); bool checkExportItemCondition(Item *exportItem, const ProductContext &productContext); ProbeConstPtr findOldProjectProbe(const QString &globalId, bool condition, const QVariantMap &initialProperties, const QString &sourceCode) const; ProbeConstPtr findOldProductProbe(const QString &productName, bool condition, const QVariantMap &initialProperties, const QString &sourceCode) const; ProbeConstPtr findCurrentProbe(const CodeLocation &location, bool condition, const QVariantMap &initialProperties) const; enum class CompareScript { No, Yes }; bool probeMatches(const ProbeConstPtr &probe, bool condition, const QVariantMap &initialProperties, const QString &configureScript, CompareScript compareScript) const; void printProfilingInfo(); void handleProductError(const ErrorInfo &error, ProductContext *productContext); QualifiedIdSet gatherModulePropertiesSetInGroup(const Item *group); Item *loadItemFromFile(const QString &filePath, const CodeLocation &referencingLocation); void collectProductsByName(const TopLevelProjectContext &topLevelProject); void collectProductsByType(const TopLevelProjectContext &topLevelProject); void handleProfileItems(Item *item, ProjectContext *projectContext); std::vector collectProfileItems(Item *item, ProjectContext *projectContext); void evaluateProfileValues(const QualifiedId &namePrefix, Item *item, Item *profileItem, QVariantMap &values); void handleProfile(Item *profileItem); void collectNameFromOverride(const QString &overrideString); void checkProjectNamesInOverrides(const TopLevelProjectContext &tlp); void checkProductNamesInOverrides(); void setSearchPathsForProduct(ProductContext *product); Item::Modules modulesSortedByDependency(const Item *productItem); void createSortedModuleList(const Item::Module &parentModule, Item::Modules &modules); void collectAllModules(Item *item, std::vector *modules); std::vector allModules(Item *item); bool moduleRepresentsDisabledProduct(const Item::Module &module); using ShadowProductInfo = std::pair; ShadowProductInfo getShadowProductInfo(const ProductContext &product) const; ItemPool *m_pool; Logger &m_logger; ProgressObserver *m_progressObserver; ItemReader *m_reader; Evaluator *m_evaluator; QMap m_moduleDirListCache; // The keys are file paths, the values are module prototype items accompanied by a profile. std::unordered_map>> m_modulePrototypes; // The keys are module prototypes and products, the values specify whether the module's // condition is true for that product. QHash, bool> m_modulePrototypeEnabledInfo; QHash m_parameterDeclarations; Set m_disabledItems; std::vector m_requiredChain; struct DependsChainEntry { DependsChainEntry(const QualifiedId &name, const CodeLocation &location) : name(name), location(location) { } QualifiedId name; CodeLocation location; bool isProduct = false; }; class DependsChainManager; std::vector m_dependsChain; QHash> m_oldProjectProbes; QHash> m_oldProductProbes; FileTime m_lastResolveTime; QHash> m_currentProbes; QVariantMap m_storedProfiles; QVariantMap m_localProfiles; std::multimap m_productsByName; std::multimap m_productsByType; std::unordered_map> m_productsWithDeferredDependsItems; Set m_exportsWithDeferredDependsItems; ModuleProviderInfoList m_moduleProviderInfo; Set m_tempQbsFiles; SetupProjectParameters m_parameters; std::unique_ptr m_settings; Version m_qbsVersion; Item *m_tempScopeItem = nullptr; qint64 m_elapsedTimeProbes; qint64 m_elapsedTimePrepareProducts; qint64 m_elapsedTimeProductDependencies; qint64 m_elapsedTimeTransitiveDependencies; qint64 m_elapsedTimeHandleProducts; qint64 m_elapsedTimePropertyChecking; quint64 m_probesEncountered; quint64 m_probesRun; quint64 m_probesCachedCurrent; quint64 m_probesCachedOld; Set m_projectNamesUsedInOverrides; Set m_productNamesUsedInOverrides; Set m_disabledProjects; Set m_erroneousProducts; int m_dependencyResolvingPass = 0; }; } // namespace Internal } // namespace qbs QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(qbs::Internal::ModuleLoaderResult::ProductInfo, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(qbs::Internal::ModuleLoaderResult::ProductInfo::Dependency, Q_MOVABLE_TYPE); QT_END_NAMESPACE #endif // QBS_MODULELOADER_H qbs-src-1.13.1/src/lib/corelib/language/modulemerger.cpp000066400000000000000000000270141347155106100231100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "modulemerger.h" #include "value.h" #include #include #include #include #include namespace qbs { namespace Internal { ModuleMerger::ModuleMerger(Logger &logger, Item *root, Item::Module &moduleToMerge) : m_logger(logger) , m_rootItem(root) , m_mergedModule(moduleToMerge) , m_required(moduleToMerge.required) , m_isBaseModule(moduleToMerge.name.first() == StringConstants::qbsModule()) , m_versionRange(moduleToMerge.versionRange) { QBS_CHECK(moduleToMerge.item->type() == ItemType::ModuleInstance); } void ModuleMerger::replaceItemInValues(QualifiedId moduleName, Item *containerItem, Item *toReplace) { QBS_CHECK(!moduleName.empty()); QBS_CHECK(containerItem != m_mergedModule.item); const QString moduleNamePrefix = moduleName.takeFirst(); const Item::PropertyMap &properties = containerItem->properties(); for (auto it = properties.begin(); it != properties.end(); ++it) { if (it.key() != moduleNamePrefix) continue; Value * const val = it.value().get(); QBS_CHECK(val); QBS_CHECK(val->type() == Value::ItemValueType); const auto itemVal = static_cast(val); if (moduleName.empty()) { QBS_CHECK(itemVal->item() == toReplace); itemVal->setItem(m_mergedModule.item); } else { replaceItemInValues(moduleName, itemVal->item(), toReplace); } } } void ModuleMerger::replaceItemInScopes(Item *toReplace) { // In insertProperties(), we potentially call setDefiningItem() with the "wrong" // (to-be-replaced) module instance as an argument. If such module instances // are dependencies of other modules, they have the depending module's instance // as their "instance scope", which is the scope of their scope. This function takes // care that the "wrong" definingItem of values in sub-modules still has the "right" // instance scope, namely our merged module instead of some other instance. for (const Item::Module &module : toReplace->modules()) { for (const ValuePtr &property : module.item->properties()) { ValuePtr v = property; do { if (v->definingItem() && v->definingItem()->scope() && v->definingItem()->scope()->scope() == toReplace) { v->definingItem()->scope()->setScope(m_mergedModule.item); } v = v->next(); } while (v); } } } void ModuleMerger::start() { Item::Module m; m.item = m_rootItem; const Item::PropertyMap props = dfs(m, Item::PropertyMap()); if (m_required) m_mergedModule.required = true; m_mergedModule.versionRange.narrowDown(m_versionRange); Item::PropertyMap mergedProps = m_mergedModule.item->properties(); Item *moduleProto = m_mergedModule.item->prototype(); while (moduleProto->prototype()) moduleProto = moduleProto->prototype(); for (auto it = props.constBegin(); it != props.constEnd(); ++it) { appendPrototypeValueToNextChain(moduleProto, it.key(), it.value()); mergedProps[it.key()] = it.value(); } m_mergedModule.item->setProperties(mergedProps); for (Item *moduleInstanceContainer : qAsConst(m_moduleInstanceContainers)) { Item::Modules modules; for (const Item::Module &dep : moduleInstanceContainer->modules()) { const bool isTheModule = dep.name == m_mergedModule.name; Item::Module m = dep; if (isTheModule && m.item != m_mergedModule.item) { QBS_CHECK(m.item->type() == ItemType::ModuleInstance); replaceItemInValues(m.name, moduleInstanceContainer, m.item); replaceItemInScopes(m.item); m.item = m_mergedModule.item; if (m_required) m.required = true; m.versionRange.narrowDown(m_versionRange); } modules << m; } moduleInstanceContainer->setModules(modules); } } Item::PropertyMap ModuleMerger::dfs(const Item::Module &m, Item::PropertyMap props) { Item *moduleInstance = nullptr; size_t numberOfOutprops = m.item->modules().size(); for (const Item::Module &dep : m.item->modules()) { if (dep.name == m_mergedModule.name) { --numberOfOutprops; moduleInstance = dep.item; insertProperties(&props, moduleInstance, ScalarProperties); m_moduleInstanceContainers << m.item; if (dep.required) m_required = true; m_versionRange.narrowDown(dep.versionRange); break; } } std::vector outprops; outprops.reserve(numberOfOutprops); for (const Item::Module &dep : m.item->modules()) { if (dep.item != moduleInstance) outprops.push_back(dfs(dep, props)); } if (!outprops.empty()) { props = outprops.front(); for (size_t i = 1; i < outprops.size(); ++i) mergeOutProps(&props, outprops.at(i)); } if (moduleInstance) insertProperties(&props, moduleInstance, ListProperties); const bool isNonPresentModule = m.item->type() != ItemType::Product && !m.item->isPresentModule(); return isNonPresentModule ? Item::PropertyMap() : props; } void ModuleMerger::mergeOutProps(Item::PropertyMap *dst, const Item::PropertyMap &src) { for (auto it = src.constBegin(); it != src.constEnd(); ++it) { ValuePtr &v = (*dst)[it.key()]; if (!v) { v = it.value(); QBS_ASSERT(it.value(), continue); continue; } if (v->type() != Value::JSSourceValueType) continue; if (it.value()->type() != Value::JSSourceValueType) continue; // possible conflict const JSSourceValuePtr dstVal = std::static_pointer_cast(v); JSSourceValuePtr srcVal = std::static_pointer_cast(it.value()); const PropertyDeclaration pd = m_decls.value(srcVal); QBS_CHECK(pd.isValid()); if (pd.isScalar()) { if (dstVal->sourceCode() != srcVal->sourceCode()) { m_logger.qbsWarning() << Tr::tr("Conflicting scalar values at %1 and %2.").arg( dstVal->location().toString(), srcVal->location().toString()); // TODO: yield error with a hint how to solve the conflict. } v = it.value(); } else { lastInNextChain(dstVal)->setNext(srcVal); } } } void ModuleMerger::insertProperties(Item::PropertyMap *dst, Item *srcItem, PropertiesType type) { Set &seenInstances = type == ScalarProperties ? m_seenInstancesTopDown : m_seenInstancesBottomUp; Item *origSrcItem = srcItem; do { if (seenInstances.insert(srcItem).second) { for (Item::PropertyMap::const_iterator it = srcItem->properties().constBegin(); it != srcItem->properties().constEnd(); ++it) { const ValuePtr &srcVal = it.value(); if (srcVal->type() == Value::ItemValueType) continue; if (it.key() == StringConstants::qbsSourceDirPropertyInternal()) continue; const PropertyDeclaration srcDecl = srcItem->propertyDeclaration(it.key()); if (!srcDecl.isValid() || srcDecl.isScalar() != (type == ScalarProperties)) continue; // Scalar variant values could stem from product multiplexing, in which case // the merged qbs module instance needs to get that value. if (srcVal->type() == Value::VariantValueType && (!srcDecl.isScalar() || !m_isBaseModule)) { continue; } ValuePtr &v = (*dst)[it.key()]; if (v && type == ScalarProperties) continue; ValuePtr clonedVal = srcVal->clone(); m_decls[clonedVal] = srcDecl; clonedVal->setDefiningItem(origSrcItem); if (v) { QBS_CHECK(!clonedVal->next()); clonedVal->setNext(v); } v = clonedVal; } } srcItem = srcItem->prototype(); } while (srcItem && srcItem->type() == ItemType::ModuleInstance); } void ModuleMerger::appendPrototypeValueToNextChain(Item *moduleProto, const QString &propertyName, const ValuePtr &sv) { const PropertyDeclaration pd = m_mergedModule.item->propertyDeclaration(propertyName); if (pd.isScalar()) return; if (!m_clonedModulePrototype) { m_clonedModulePrototype = Item::create(moduleProto->pool(), ItemType::Module); m_clonedModulePrototype->setScope(m_mergedModule.item); m_clonedModulePrototype->setLocation(moduleProto->location()); moduleProto->copyProperty(StringConstants::nameProperty(), m_clonedModulePrototype); } const ValuePtr &protoValue = moduleProto->property(propertyName); QBS_CHECK(protoValue); const ValuePtr clonedValue = protoValue->clone(); lastInNextChain(sv)->setNext(clonedValue); clonedValue->setDefiningItem(m_clonedModulePrototype); m_clonedModulePrototype->setPropertyDeclaration(propertyName, pd); m_clonedModulePrototype->setProperty(propertyName, clonedValue); } ValuePtr ModuleMerger::lastInNextChain(const ValuePtr &v) { ValuePtr n = v; while (n->next()) n = n->next(); return n; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/modulemerger.h000066400000000000000000000064441347155106100225610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_MODULEMERGER_H #define QBS_MODULEMERGER_H #include "item.h" #include "qualifiedid.h" #include #include #include #include namespace qbs { namespace Internal { class ModuleMerger { public: ModuleMerger(Logger &logger, Item *root, Item::Module &moduleToMerge); void start(); private: Item::PropertyMap dfs(const Item::Module &m, Item::PropertyMap props); void mergeOutProps(Item::PropertyMap *dst, const Item::PropertyMap &src); void appendPrototypeValueToNextChain(Item *moduleProto, const QString &propertyName, const ValuePtr &sv); static ValuePtr lastInNextChain(const ValuePtr &v); enum PropertiesType { ScalarProperties, ListProperties }; void insertProperties(Item::PropertyMap *dst, Item *srcItem, PropertiesType type); void replaceItemInValues(QualifiedId moduleName, Item *containerItem, Item *toReplace); void replaceItemInScopes(Item *toReplace); Logger &m_logger; Item * const m_rootItem; Item::Module &m_mergedModule; Item *m_clonedModulePrototype = nullptr; QHash m_decls; Set m_seenInstancesTopDown; Set m_seenInstancesBottomUp; Set m_moduleInstanceContainers; bool m_required; const bool m_isBaseModule; VersionRange m_versionRange; }; } // namespace Internal } // namespace qbs #endif // QBS_MODULEMERGER_H qbs-src-1.13.1/src/lib/corelib/language/moduleproviderinfo.h000066400000000000000000000064131347155106100240020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_MODULEPROVIDERINFO_H #define QBS_MODULEPROVIDERINFO_H #include "qualifiedid.h" #include #include #include #include namespace qbs { namespace Internal { class ModuleProviderInfo { public: ModuleProviderInfo() = default; ModuleProviderInfo(const QualifiedId &name, const QVariantMap &config, const QStringList &searchPaths, bool transientOutput) : name(name), config(config), searchPaths(searchPaths), transientOutput(transientOutput) {} static QString outputBaseDirName() { return QStringLiteral("genmodules"); } static QString outputDirPath(const QString &baseDir, const QualifiedId &name) { return baseDir + QLatin1Char('/') + outputBaseDirName() + QLatin1Char('/') + name.toString(); } QString outputDirPath(const QString &baseDir) const { return outputDirPath(baseDir, name); } template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(reinterpret_cast(name), config, searchPaths); } QualifiedId name; QVariantMap config; QStringList searchPaths; bool transientOutput = false; // Not to be serialized. }; using ModuleProviderInfoList = std::vector; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/language/preparescriptobserver.cpp000066400000000000000000000076311347155106100250570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "preparescriptobserver.h" #include "property.h" #include "scriptengine.h" #include #include #include #include #include #include namespace qbs { namespace Internal { PrepareScriptObserver::PrepareScriptObserver(ScriptEngine *engine, UnobserveMode unobserveMode) : ScriptPropertyObserver(engine, unobserveMode) { } void PrepareScriptObserver::onPropertyRead(const QScriptValue &object, const QString &name, const QScriptValue &value) { const auto objectId = object.objectId(); const auto projectIt = m_projectObjectIds.find(objectId); if (projectIt != m_projectObjectIds.cend()) { engine()->addPropertyRequestedInScript( Property(projectIt->second, QString(), name, value.toVariant(), Property::PropertyInProject)); return; } if (m_importIds.contains(objectId)) { engine()->addImportRequestedInScript(object.objectId()); return; } const auto exportsIt = m_exportsObjectIds.find(value.objectId()); if (exportsIt != m_exportsObjectIds.cend()) { engine()->addRequestedExport(exportsIt->second); return; } const auto it = m_parameterObjects.find(objectId); if (it != m_parameterObjects.cend()) { engine()->addPropertyRequestedInScript( Property(it->second.first, it->second.second, name, value.toVariant(), Property::PropertyInParameters)); } if (name == StringConstants::fileTagsProperty() && m_artifactIds.contains(objectId)) { const Artifact * const artifact = attachedPointer(object); QBS_CHECK(artifact); const Property p(artifact->product->uniqueName(), QString(), name, value.toVariant(), Property::PropertyInArtifact); engine()->addPropertyRequestedFromArtifact(artifact, p); } } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/preparescriptobserver.h000066400000000000000000000072621347155106100245240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PREPARESCRIPTOBSERVER_H #define QBS_PREPARESCRIPTOBSERVER_H #include "qualifiedid.h" #include "scriptpropertyobserver.h" #include #include #include namespace qbs { namespace Internal { class ResolvedProduct; class ScriptEngine; class PrepareScriptObserver : public ScriptPropertyObserver { public: PrepareScriptObserver(ScriptEngine *engine, UnobserveMode unobserveMode); void addProjectObjectId(qint64 projectId, const QString &projectName) { m_projectObjectIds.insert(std::make_pair(projectId, projectName)); } void addExportsObjectId(qint64 exportsId, const ResolvedProduct *product) { m_exportsObjectIds.insert(std::make_pair(exportsId, product)); } void addArtifactId(qint64 artifactId) { m_artifactIds.insert(artifactId); } bool addImportId(qint64 importId) { return m_importIds.insert(importId).second; } void clearImportIds() { m_importIds.clear(); } void addParameterObjectId(qint64 id, const QString &productName, const QString &depName, const QualifiedId &moduleName) { const QString depAndModuleName = depName + QLatin1Char(':') + moduleName.toString(); const auto value = std::make_pair(productName, depAndModuleName); m_parameterObjects.insert(std::make_pair(id, value)); } private: void onPropertyRead(const QScriptValue &object, const QString &name, const QScriptValue &value) override; std::unordered_map m_projectObjectIds; std::unordered_map> m_parameterObjects; std::unordered_map m_exportsObjectIds; Set m_importIds; Set m_artifactIds; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/language/projectresolver.cpp000066400000000000000000002373221347155106100236560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "projectresolver.h" #include "artifactproperties.h" #include "builtindeclarations.h" #include "evaluator.h" #include "filecontext.h" #include "item.h" #include "language.h" #include "propertymapinternal.h" #include "resolvedfilecontext.h" #include "scriptengine.h" #include "value.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { extern bool debugProperties; static const FileTag unknownFileTag() { static const FileTag tag("unknown-file-tag"); return tag; } struct ProjectResolver::ProjectContext { ProjectContext *parentContext = nullptr; ResolvedProjectPtr project; std::vector fileTaggers; std::vector rules; JobLimits jobLimits; ResolvedModulePtr dummyModule; }; struct ProjectResolver::ProductContext { ResolvedProductPtr product; QString buildDirectory; Item *item; using ArtifactPropertiesInfo = std::pair>; QHash artifactPropertiesPerFilter; ProjectResolver::FileLocations sourceArtifactLocations; GroupConstPtr currentGroup; }; struct ProjectResolver::ModuleContext { ResolvedModulePtr module; JobLimits jobLimits; }; class CancelException { }; ProjectResolver::ProjectResolver(Evaluator *evaluator, const ModuleLoaderResult &loadResult, const SetupProjectParameters &setupParameters, Logger &logger) : m_evaluator(evaluator) , m_logger(logger) , m_engine(m_evaluator->engine()) , m_progressObserver(nullptr) , m_setupParams(setupParameters) , m_loadResult(loadResult) { QBS_CHECK(FileInfo::isAbsolute(m_setupParams.buildRoot())); } ProjectResolver::~ProjectResolver() { } void ProjectResolver::setProgressObserver(ProgressObserver *observer) { m_progressObserver = observer; } static void checkForDuplicateProductNames(const TopLevelProjectConstPtr &project) { const std::vector allProducts = project->allProducts(); for (size_t i = 0; i < allProducts.size(); ++i) { const ResolvedProductConstPtr product1 = allProducts.at(i); const QString productName = product1->uniqueName(); for (size_t j = i + 1; j < allProducts.size(); ++j) { const ResolvedProductConstPtr product2 = allProducts.at(j); if (product2->uniqueName() == productName) { ErrorInfo error; error.append(Tr::tr("Duplicate product name '%1'.").arg(product1->name)); error.append(Tr::tr("First product defined here."), product1->location); error.append(Tr::tr("Second product defined here."), product2->location); throw error; } } } } TopLevelProjectPtr ProjectResolver::resolve() { TimedActivityLogger projectResolverTimer(m_logger, Tr::tr("ProjectResolver"), m_setupParams.logElapsedTime()); qCDebug(lcProjectResolver) << "resolving" << m_loadResult.root->file()->filePath(); m_productContext = nullptr; m_moduleContext = nullptr; m_elapsedTimeModPropEval = m_elapsedTimeAllPropEval = m_elapsedTimeGroups = 0; TopLevelProjectPtr tlp; try { tlp = resolveTopLevelProject(); printProfilingInfo(); } catch (const CancelException &) { throw ErrorInfo(Tr::tr("Project resolving canceled for configuration '%1'.") .arg(TopLevelProject::deriveId(m_setupParams.finalBuildConfigurationTree()))); } return tlp; } void ProjectResolver::checkCancelation() const { if (m_progressObserver && m_progressObserver->canceled()) throw CancelException(); } QString ProjectResolver::verbatimValue(const ValueConstPtr &value, bool *propertyWasSet) const { QString result; if (value && value->type() == Value::JSSourceValueType) { const JSSourceValueConstPtr sourceValue = std::static_pointer_cast( value); result = sourceCodeForEvaluation(sourceValue); if (propertyWasSet) *propertyWasSet = !sourceValue->isBuiltinDefaultValue(); } else { if (propertyWasSet) *propertyWasSet = false; } return result; } QString ProjectResolver::verbatimValue(Item *item, const QString &name, bool *propertyWasSet) const { return verbatimValue(item->property(name), propertyWasSet); } void ProjectResolver::ignoreItem(Item *item, ProjectContext *projectContext) { Q_UNUSED(item); Q_UNUSED(projectContext); } static void makeSubProjectNamesUniqe(const ResolvedProjectPtr &parentProject) { Set subProjectNames; Set projectsInNeedOfNameChange; for (const ResolvedProjectPtr &p : qAsConst(parentProject->subProjects)) { if (!subProjectNames.insert(p->name).second) projectsInNeedOfNameChange << p; makeSubProjectNamesUniqe(p); } while (!projectsInNeedOfNameChange.empty()) { auto it = projectsInNeedOfNameChange.begin(); while (it != projectsInNeedOfNameChange.end()) { const ResolvedProjectPtr p = *it; p->name += QLatin1Char('_'); if (subProjectNames.insert(p->name).second) { it = projectsInNeedOfNameChange.erase(it); } else { ++it; } } } } TopLevelProjectPtr ProjectResolver::resolveTopLevelProject() { if (m_progressObserver) m_progressObserver->setMaximum(m_loadResult.productInfos.size()); const TopLevelProjectPtr project = TopLevelProject::create(); project->buildDirectory = TopLevelProject::deriveBuildDirectory(m_setupParams.buildRoot(), TopLevelProject::deriveId(m_setupParams.finalBuildConfigurationTree())); project->buildSystemFiles = m_loadResult.qbsFiles; project->profileConfigs = m_loadResult.profileConfigs; project->probes = m_loadResult.projectProbes; project->moduleProviderInfo = m_loadResult.moduleProviderInfo; ProjectContext projectContext; projectContext.project = project; resolveProject(m_loadResult.root, &projectContext); ErrorInfo accumulatedErrors; for (const ErrorInfo &e : m_queuedErrors) appendError(accumulatedErrors, e); if (accumulatedErrors.hasError()) throw accumulatedErrors; project->setBuildConfiguration(m_setupParams.finalBuildConfigurationTree()); project->overriddenValues = m_setupParams.overriddenValues(); project->canonicalFilePathResults = m_engine->canonicalFilePathResults(); project->fileExistsResults = m_engine->fileExistsResults(); project->directoryEntriesResults = m_engine->directoryEntriesResults(); project->fileLastModifiedResults = m_engine->fileLastModifiedResults(); project->environment = m_engine->environment(); project->buildSystemFiles.unite(m_engine->imports()); makeSubProjectNamesUniqe(project); resolveProductDependencies(projectContext); collectExportedProductDependencies(); checkForDuplicateProductNames(project); for (const ResolvedProductPtr &product : project->allProducts()) { if (!product->enabled) continue; applyFileTaggers(product); matchArtifactProperties(product, product->allEnabledFiles()); // Let a positive value of qbs.install imply the file tag "installable". for (const SourceArtifactPtr &artifact : product->allFiles()) { if (artifact->properties->qbsPropertyValue(StringConstants::installProperty()).toBool()) artifact->fileTags += "installable"; } } project->warningsEncountered = m_logger.warnings(); return project; } void ProjectResolver::resolveProject(Item *item, ProjectContext *projectContext) { checkCancelation(); if (projectContext->parentContext) projectContext->project->enabled = projectContext->parentContext->project->enabled; projectContext->project->location = item->location(); try { resolveProjectFully(item, projectContext); } catch (const ErrorInfo &error) { if (!projectContext->project->enabled) { qCDebug(lcProjectResolver) << "error resolving project" << projectContext->project->location << error.toString(); return; } if (m_setupParams.productErrorMode() == ErrorHandlingMode::Strict) throw; m_logger.printWarning(error); } } void ProjectResolver::resolveProjectFully(Item *item, ProjectResolver::ProjectContext *projectContext) { projectContext->project->enabled = projectContext->project->enabled && m_evaluator->boolValue(item, StringConstants::conditionProperty()); projectContext->project->name = m_evaluator->stringValue(item, StringConstants::nameProperty()); if (projectContext->project->name.isEmpty()) projectContext->project->name = FileInfo::baseName(item->location().filePath()); // FIXME: Must also be changed in item? QVariantMap projectProperties; if (!projectContext->project->enabled) { projectProperties.insert(StringConstants::profileProperty(), m_evaluator->stringValue(item, StringConstants::profileProperty())); projectContext->project->setProjectProperties(projectProperties); return; } projectContext->dummyModule = ResolvedModule::create(); for (Item::PropertyDeclarationMap::const_iterator it = item->propertyDeclarations().constBegin(); it != item->propertyDeclarations().constEnd(); ++it) { if (it.value().flags().testFlag(PropertyDeclaration::PropertyNotAvailableInConfig)) continue; const ValueConstPtr v = item->property(it.key()); QBS_ASSERT(v && v->type() != Value::ItemValueType, continue); projectProperties.insert(it.key(), m_evaluator->value(item, it.key()).toVariant()); } projectContext->project->setProjectProperties(projectProperties); static const ItemFuncMap mapping = { { ItemType::Project, &ProjectResolver::resolveProject }, { ItemType::SubProject, &ProjectResolver::resolveSubProject }, { ItemType::Product, &ProjectResolver::resolveProduct }, { ItemType::Probe, &ProjectResolver::ignoreItem }, { ItemType::FileTagger, &ProjectResolver::resolveFileTagger }, { ItemType::JobLimit, &ProjectResolver::resolveJobLimit }, { ItemType::Rule, &ProjectResolver::resolveRule }, { ItemType::PropertyOptions, &ProjectResolver::ignoreItem } }; for (Item * const child : item->children()) { try { callItemFunction(mapping, child, projectContext); } catch (const ErrorInfo &e) { m_queuedErrors.push_back(e); } } for (const ResolvedProductPtr &product : projectContext->project->products) postProcess(product, projectContext); } void ProjectResolver::resolveSubProject(Item *item, ProjectResolver::ProjectContext *projectContext) { ProjectContext subProjectContext = createProjectContext(projectContext); Item * const projectItem = item->child(ItemType::Project); if (projectItem) { resolveProject(projectItem, &subProjectContext); return; } // No project item was found, which means the project was disabled. subProjectContext.project->enabled = false; Item * const propertiesItem = item->child(ItemType::PropertiesInSubProject); if (propertiesItem) { subProjectContext.project->name = m_evaluator->stringValue(propertiesItem, StringConstants::nameProperty()); } } class ProjectResolver::ProductContextSwitcher { public: ProductContextSwitcher(ProjectResolver *resolver, ProductContext *newContext, ProgressObserver *progressObserver) : m_resolver(resolver), m_progressObserver(progressObserver) { QBS_CHECK(!m_resolver->m_productContext); m_resolver->m_productContext = newContext; } ~ProductContextSwitcher() { if (m_progressObserver) m_progressObserver->incrementProgressValue(); m_resolver->m_productContext = nullptr; } private: ProjectResolver * const m_resolver; ProgressObserver * const m_progressObserver; }; void ProjectResolver::resolveProduct(Item *item, ProjectContext *projectContext) { checkCancelation(); m_evaluator->clearPropertyDependencies(); ProductContext productContext; productContext.item = item; ResolvedProductPtr product = ResolvedProduct::create(); product->enabled = projectContext->project->enabled; product->moduleProperties = PropertyMapInternal::create(); product->project = projectContext->project; productContext.product = product; product->location = item->location(); ProductContextSwitcher contextSwitcher(this, &productContext, m_progressObserver); try { resolveProductFully(item, projectContext); } catch (const ErrorInfo &e) { QString mainErrorString = !product->name.isEmpty() ? Tr::tr("Error while handling product '%1':").arg(product->name) : Tr::tr("Error while handling product:"); ErrorInfo fullError(mainErrorString, item->location()); appendError(fullError, e); if (!product->enabled) { qCDebug(lcProjectResolver) << fullError.toString(); return; } if (m_setupParams.productErrorMode() == ErrorHandlingMode::Strict) throw fullError; m_logger.printWarning(fullError); m_logger.printWarning(ErrorInfo(Tr::tr("Product '%1' had errors and was disabled.") .arg(product->name), item->location())); product->enabled = false; } } void ProjectResolver::resolveProductFully(Item *item, ProjectContext *projectContext) { const ResolvedProductPtr product = m_productContext->product; m_productItemMap.insert(product, item); projectContext->project->products.push_back(product); product->name = m_evaluator->stringValue(item, StringConstants::nameProperty()); // product->buildDirectory() isn't valid yet, because the productProperties map is not ready. m_productContext->buildDirectory = m_evaluator->stringValue(item, StringConstants::buildDirectoryProperty()); product->multiplexConfigurationId = m_evaluator->stringValue(item, StringConstants::multiplexConfigurationIdProperty()); qCDebug(lcProjectResolver) << "resolveProduct" << product->uniqueName(); m_productsByName.insert(product->uniqueName(), product); product->enabled = product->enabled && m_evaluator->boolValue(item, StringConstants::conditionProperty()); ModuleLoaderResult::ProductInfo &pi = m_loadResult.productInfos[item]; if (pi.delayedError.hasError()) { ErrorInfo errorInfo; // First item is "main error", gets prepended again in the catch clause. const QList &items = pi.delayedError.items(); for (int i = 1; i < items.size(); ++i) errorInfo.append(items.at(i)); pi.delayedError.clear(); throw errorInfo; } gatherProductTypes(product.get(), item); product->targetName = m_evaluator->stringValue(item, StringConstants::targetNameProperty()); product->sourceDirectory = m_evaluator->stringValue( item, StringConstants::sourceDirectoryProperty()); product->destinationDirectory = m_evaluator->stringValue( item, StringConstants::destinationDirProperty()); if (product->destinationDirectory.isEmpty()) { product->destinationDirectory = m_productContext->buildDirectory; } else { product->destinationDirectory = FileInfo::resolvePath( product->topLevelProject()->buildDirectory, product->destinationDirectory); } product->probes = pi.probes; createProductConfig(product.get()); product->productProperties.insert(StringConstants::destinationDirProperty(), product->destinationDirectory); ModuleProperties::init(m_evaluator->scriptValue(item), product.get()); QList subItems = item->children(); const ValuePtr filesProperty = item->property(StringConstants::filesProperty()); if (filesProperty) { Item *fakeGroup = Item::create(item->pool(), ItemType::Group); fakeGroup->setFile(item->file()); fakeGroup->setLocation(item->location()); fakeGroup->setScope(item); fakeGroup->setProperty(StringConstants::nameProperty(), VariantValue::create(product->name)); fakeGroup->setProperty(StringConstants::filesProperty(), filesProperty); fakeGroup->setProperty(StringConstants::excludeFilesProperty(), item->property(StringConstants::excludeFilesProperty())); fakeGroup->setProperty(StringConstants::overrideTagsProperty(), VariantValue::falseValue()); fakeGroup->setupForBuiltinType(m_logger); subItems.prepend(fakeGroup); } static const ItemFuncMap mapping = { { ItemType::Depends, &ProjectResolver::ignoreItem }, { ItemType::Rule, &ProjectResolver::resolveRule }, { ItemType::FileTagger, &ProjectResolver::resolveFileTagger }, { ItemType::JobLimit, &ProjectResolver::resolveJobLimit }, { ItemType::Group, &ProjectResolver::resolveGroup }, { ItemType::Product, &ProjectResolver::resolveShadowProduct }, { ItemType::Export, &ProjectResolver::resolveExport }, { ItemType::Probe, &ProjectResolver::ignoreItem }, { ItemType::PropertyOptions, &ProjectResolver::ignoreItem } }; for (Item * const child : qAsConst(subItems)) callItemFunction(mapping, child, projectContext); for (const ProjectContext *p = projectContext; p; p = p->parentContext) { JobLimits tempLimits = p->jobLimits; product->jobLimits = tempLimits.update(product->jobLimits); } resolveModules(item, projectContext); for (const FileTag &t : qAsConst(product->fileTags)) m_productsByType[t].push_back(product); } void ProjectResolver::resolveModules(const Item *item, ProjectContext *projectContext) { JobLimits jobLimits; for (const Item::Module &m : item->modules()) resolveModule(m.name, m.item, m.isProduct, m.parameters, jobLimits, projectContext); for (int i = 0; i < jobLimits.count(); ++i) { const JobLimit &moduleJobLimit = jobLimits.jobLimitAt(i); if (m_productContext->product->jobLimits.getLimit(moduleJobLimit.pool()) == -1) m_productContext->product->jobLimits.setJobLimit(moduleJobLimit); } } void ProjectResolver::resolveModule(const QualifiedId &moduleName, Item *item, bool isProduct, const QVariantMap ¶meters, JobLimits &jobLimits, ProjectContext *projectContext) { checkCancelation(); if (!item->isPresentModule()) return; ModuleContext * const oldModuleContext = m_moduleContext; ModuleContext moduleContext; moduleContext.module = ResolvedModule::create(); m_moduleContext = &moduleContext; const ResolvedModulePtr &module = moduleContext.module; module->name = moduleName.toString(); module->isProduct = isProduct; module->product = m_productContext->product.get(); module->setupBuildEnvironmentScript.initialize( scriptFunctionValue(item, StringConstants::setupBuildEnvironmentProperty())); module->setupRunEnvironmentScript.initialize( scriptFunctionValue(item, StringConstants::setupRunEnvironmentProperty())); for (const Item::Module &m : item->modules()) { if (m.item->isPresentModule()) module->moduleDependencies += m.name.toString(); } m_productContext->product->modules.push_back(module); if (!parameters.empty()) m_productContext->product->moduleParameters[module] = parameters; static const ItemFuncMap mapping { { ItemType::Group, &ProjectResolver::ignoreItem }, { ItemType::Rule, &ProjectResolver::resolveRule }, { ItemType::FileTagger, &ProjectResolver::resolveFileTagger }, { ItemType::JobLimit, &ProjectResolver::resolveJobLimit }, { ItemType::Scanner, &ProjectResolver::resolveScanner }, { ItemType::PropertyOptions, &ProjectResolver::ignoreItem }, { ItemType::Depends, &ProjectResolver::ignoreItem }, { ItemType::Parameter, &ProjectResolver::ignoreItem }, { ItemType::Properties, &ProjectResolver::ignoreItem }, { ItemType::Probe, &ProjectResolver::ignoreItem } }; for (Item *child : item->children()) callItemFunction(mapping, child, projectContext); for (int i = 0; i < moduleContext.jobLimits.count(); ++i) { const JobLimit &newJobLimit = moduleContext.jobLimits.jobLimitAt(i); const int oldLimit = jobLimits.getLimit(newJobLimit.pool()); if (oldLimit == -1 || oldLimit > newJobLimit.limit()) jobLimits.setJobLimit(newJobLimit); } m_moduleContext = oldModuleContext; } void ProjectResolver::gatherProductTypes(ResolvedProduct *product, Item *item) { product->fileTags = m_evaluator->fileTagsValue(item, StringConstants::typeProperty()); for (const Item::Module &m : item->modules()) { if (m.item->isPresentModule()) { product->fileTags += m_evaluator->fileTagsValue(m.item, StringConstants::additionalProductTypesProperty()); } } item->setProperty(StringConstants::typeProperty(), VariantValue::create(sorted(product->fileTags.toStringList()))); } SourceArtifactPtr ProjectResolver::createSourceArtifact(const ResolvedProductPtr &rproduct, const QString &fileName, const GroupPtr &group, bool wildcard, const CodeLocation &filesLocation, FileLocations *fileLocations, ErrorInfo *errorInfo) { const QString &baseDir = FileInfo::path(group->location.filePath()); const QString absFilePath = QDir::cleanPath(FileInfo::resolvePath(baseDir, fileName)); if (!wildcard && !FileInfo(absFilePath).exists()) { if (errorInfo) errorInfo->append(Tr::tr("File '%1' does not exist.").arg(absFilePath), filesLocation); rproduct->missingSourceFiles << absFilePath; return {}; } if (group->enabled && fileLocations) { CodeLocation &loc = (*fileLocations)[std::make_pair(group->targetOfModule, absFilePath)]; if (loc.isValid()) { if (errorInfo) { errorInfo->append(Tr::tr("Duplicate source file '%1'.").arg(absFilePath)); errorInfo->append(Tr::tr("First occurrence is here."), loc); errorInfo->append(Tr::tr("Next occurrence is here."), filesLocation); } return {}; } loc = filesLocation; } SourceArtifactPtr artifact = SourceArtifactInternal::create(); artifact->absoluteFilePath = absFilePath; artifact->fileTags = group->fileTags; artifact->overrideFileTags = group->overrideTags; artifact->properties = group->properties; artifact->targetOfModule = group->targetOfModule; (wildcard ? group->wildcards->files : group->files).push_back(artifact); return artifact; } static QualifiedIdSet propertiesToEvaluate(const QList &initialProps, const PropertyDependencies &deps) { QList remainingProps = initialProps; QualifiedIdSet allProperties; while (!remainingProps.empty()) { const QualifiedId prop = remainingProps.takeFirst(); const auto insertResult = allProperties.insert(prop); if (!insertResult.second) continue; for (const QualifiedId &directDep : deps.value(prop)) remainingProps.push_back(directDep); } return allProperties; } QVariantMap ProjectResolver::resolveAdditionalModuleProperties(const Item *group, const QVariantMap ¤tValues) { // Step 1: Retrieve the properties directly set in the group const ModulePropertiesPerGroup &mp = m_loadResult.productInfos.value(m_productContext->item) .modulePropertiesSetInGroups; const auto it = mp.find(group); if (it == mp.end()) return {}; const QualifiedIdSet &propsSetInGroup = it->second; // Step 2: Gather all properties that depend on these properties. const QualifiedIdSet &propsToEval = propertiesToEvaluate(propsSetInGroup.toList(), m_evaluator->propertyDependencies()); // Step 3: Evaluate all these properties and replace their values in the map QVariantMap modulesMap = currentValues; QHash propsPerModule; for (auto fullPropName : propsToEval) { const QString moduleName = QualifiedId(fullPropName.mid(0, fullPropName.size() - 1)).toString(); propsPerModule[moduleName] << fullPropName.last(); } EvalCacheEnabler cachingEnabler(m_evaluator); m_evaluator->setPathPropertiesBaseDir(m_productContext->product->sourceDirectory); for (const Item::Module &module : group->modules()) { const QString &fullModName = module.name.toString(); const QStringList propsForModule = propsPerModule.take(fullModName); if (propsForModule.empty()) continue; QVariantMap reusableValues = modulesMap.value(fullModName).toMap(); for (const QString &prop : qAsConst(propsForModule)) reusableValues.remove(prop); modulesMap.insert(fullModName, evaluateProperties(module.item, module.item, reusableValues, true, true)); } m_evaluator->clearPathPropertiesBaseDir(); return modulesMap; } void ProjectResolver::resolveGroup(Item *item, ProjectContext *projectContext) { checkCancelation(); const bool parentEnabled = m_productContext->currentGroup ? m_productContext->currentGroup->enabled : m_productContext->product->enabled; const bool isEnabled = parentEnabled && m_evaluator->boolValue(item, StringConstants::conditionProperty()); try { resolveGroupFully(item, projectContext, isEnabled); } catch (const ErrorInfo &error) { if (!isEnabled) { qCDebug(lcProjectResolver) << "error resolving group at" << item->location() << error.toString(); return; } if (m_setupParams.productErrorMode() == ErrorHandlingMode::Strict) throw; m_logger.printWarning(error); } } void ProjectResolver::resolveGroupFully(Item *item, ProjectResolver::ProjectContext *projectContext, bool isEnabled) { AccumulatingTimer groupTimer(m_setupParams.logElapsedTime() ? &m_elapsedTimeGroups : nullptr); const auto getGroupPropertyMap = [this, item](const ArtifactProperties *existingProps) { PropertyMapPtr moduleProperties; bool newPropertyMapRequired = false; if (existingProps) moduleProperties = existingProps->propertyMap(); if (!moduleProperties) { newPropertyMapRequired = true; moduleProperties = m_productContext->currentGroup ? m_productContext->currentGroup->properties : m_productContext->product->moduleProperties; } const QVariantMap newModuleProperties = resolveAdditionalModuleProperties(item, moduleProperties->value()); if (!newModuleProperties.empty()) { if (newPropertyMapRequired) moduleProperties = PropertyMapInternal::create(); moduleProperties->setValue(newModuleProperties); } return moduleProperties; }; QStringList files = m_evaluator->stringListValue(item, StringConstants::filesProperty()); bool fileTagsSet; const FileTags fileTags = m_evaluator->fileTagsValue(item, StringConstants::fileTagsProperty(), &fileTagsSet); const QStringList fileTagsFilter = m_evaluator->stringListValue(item, StringConstants::fileTagsFilterProperty()); if (!fileTagsFilter.empty()) { if (Q_UNLIKELY(!files.empty())) throw ErrorInfo(Tr::tr("Group.files and Group.fileTagsFilters are exclusive."), item->location()); if (!isEnabled) return; ProductContext::ArtifactPropertiesInfo &apinfo = m_productContext->artifactPropertiesPerFilter[fileTagsFilter]; if (apinfo.first) { const auto it = std::find_if(apinfo.second.cbegin(), apinfo.second.cend(), [item](const CodeLocation &loc) { return item->location().filePath() == loc.filePath(); }); if (it != apinfo.second.cend()) { ErrorInfo error(Tr::tr("Conflicting fileTagsFilter in Group items.")); error.append(Tr::tr("First item"), *it); error.append(Tr::tr("Second item"), item->location()); throw error; } } else { apinfo.first = ArtifactProperties::create(); apinfo.first->setFileTagsFilter(FileTags::fromStringList(fileTagsFilter)); m_productContext->product->artifactProperties.push_back(apinfo.first); } apinfo.second.push_back(item->location()); apinfo.first->setPropertyMapInternal(getGroupPropertyMap(apinfo.first.get())); apinfo.first->addExtraFileTags(fileTags); return; } QStringList patterns; for (int i = files.size(); --i >= 0;) { if (FileInfo::isPattern(files[i])) patterns.push_back(files.takeAt(i)); } GroupPtr group = ResolvedGroup::create(); bool prefixWasSet = false; group->prefix = m_evaluator->stringValue(item, StringConstants::prefixProperty(), QString(), &prefixWasSet); if (!prefixWasSet && m_productContext->currentGroup) group->prefix = m_productContext->currentGroup->prefix; if (!group->prefix.isEmpty()) { for (auto it = files.rbegin(), end = files.rend(); it != end; ++it) it->prepend(group->prefix); } group->location = item->location(); group->enabled = isEnabled; group->properties = getGroupPropertyMap(nullptr); group->fileTags = fileTags; group->overrideTags = m_evaluator->boolValue(item, StringConstants::overrideTagsProperty()); if (group->overrideTags && fileTagsSet) { if (group->fileTags.empty() ) group->fileTags.insert(unknownFileTag()); } else if (m_productContext->currentGroup) { group->fileTags.unite(m_productContext->currentGroup->fileTags); } const CodeLocation filesLocation = item->property(StringConstants::filesProperty())->location(); const VariantValueConstPtr moduleProp = item->variantProperty( StringConstants::modulePropertyInternal()); if (moduleProp) group->targetOfModule = moduleProp->value().toString(); ErrorInfo fileError; if (!patterns.empty()) { group->wildcards = std::unique_ptr(new SourceWildCards); SourceWildCards *wildcards = group->wildcards.get(); wildcards->group = group.get(); wildcards->excludePatterns = m_evaluator->stringListValue( item, StringConstants::excludeFilesProperty()); wildcards->patterns = patterns; const Set files = wildcards->expandPatterns(group, FileInfo::path(item->file()->filePath()), projectContext->project->topLevelProject()->buildDirectory); for (const QString &fileName : files) createSourceArtifact(m_productContext->product, fileName, group, true, filesLocation, &m_productContext->sourceArtifactLocations, &fileError); } for (const QString &fileName : files) { createSourceArtifact(m_productContext->product, fileName, group, false, filesLocation, &m_productContext->sourceArtifactLocations, &fileError); } if (fileError.hasError()) { if (group->enabled) { if (m_setupParams.productErrorMode() == ErrorHandlingMode::Strict) throw ErrorInfo(fileError); m_logger.printWarning(fileError); } else { qCDebug(lcProjectResolver) << "error for disabled group:" << fileError.toString(); } } group->name = m_evaluator->stringValue(item, StringConstants::nameProperty()); if (group->name.isEmpty()) group->name = Tr::tr("Group %1").arg(m_productContext->product->groups.size()); m_productContext->product->groups.push_back(group); class GroupContextSwitcher { public: GroupContextSwitcher(ProductContext &context, const GroupConstPtr &newGroup) : m_context(context), m_oldGroup(context.currentGroup) { m_context.currentGroup = newGroup; } ~GroupContextSwitcher() { m_context.currentGroup = m_oldGroup; } private: ProductContext &m_context; const GroupConstPtr m_oldGroup; }; GroupContextSwitcher groupSwitcher(*m_productContext, group); for (Item * const childItem : item->children()) resolveGroup(childItem, projectContext); } void ProjectResolver::adaptExportedPropertyValues(const Item *shadowProductItem) { ExportedModule &m = m_productContext->product->exportedModule; const QVariantList prefixList = m.propertyValues.take( StringConstants::prefixMappingProperty()).toList(); const QString shadowProductName = m_evaluator->stringValue( shadowProductItem, StringConstants::nameProperty()); const QString shadowProductBuildDir = m_evaluator->stringValue( shadowProductItem, StringConstants::buildDirectoryProperty()); QVariantMap prefixMap; for (const QVariant &v : prefixList) { const QVariantMap o = v.toMap(); prefixMap.insert(o.value(QStringLiteral("prefix")).toString(), o.value(QStringLiteral("replacement")).toString()); } const auto valueRefersToImportingProduct = [shadowProductName, shadowProductBuildDir](const QString &value) { return value.toLower().contains(shadowProductName.toLower()) || value.contains(shadowProductBuildDir); }; static const auto stringMapper = [](const QVariantMap &mappings, const QString &value) -> QString { for (auto it = mappings.cbegin(); it != mappings.cend(); ++it) { if (value.startsWith(it.key())) return it.value().toString() + value.mid(it.key().size()); } return value; }; const auto stringListMapper = [&valueRefersToImportingProduct]( const QVariantMap &mappings, const QStringList &value) -> QStringList { QStringList result; result.reserve(value.size()); for (const QString &s : value) { if (!valueRefersToImportingProduct(s)) result.push_back(stringMapper(mappings, s)); } return result; }; const std::function mapper = [&stringListMapper, &mapper]( const QVariantMap &mappings, const QVariant &value) -> QVariant { switch (static_cast(value.type())) { case QMetaType::QString: return stringMapper(mappings, value.toString()); case QMetaType::QStringList: return stringListMapper(mappings, value.toStringList()); case QMetaType::QVariantMap: { QVariantMap m = value.toMap(); for (auto it = m.begin(); it != m.end(); ++it) it.value() = mapper(mappings, it.value()); return m; } default: return value; } }; for (auto it = m.propertyValues.begin(); it != m.propertyValues.end(); ++it) it.value() = mapper(prefixMap, it.value()); for (auto it = m.modulePropertyValues.begin(); it != m.modulePropertyValues.end(); ++it) it.value() = mapper(prefixMap, it.value()); for (ExportedModuleDependency &dep : m.moduleDependencies) { for (auto it = dep.moduleProperties.begin(); it != dep.moduleProperties.end(); ++it) it.value() = mapper(prefixMap, it.value()); } } void ProjectResolver::collectExportedProductDependencies() { ResolvedProductPtr dummyProduct = ResolvedProduct::create(); dummyProduct->enabled = false; for (const auto &exportingProductInfo : qAsConst(m_productExportInfo)) { const ResolvedProductPtr exportingProduct = exportingProductInfo.first; if (!exportingProduct->enabled) continue; Item * const importingProductItem = exportingProductInfo.second; std::vector directDepNames; for (const Item::Module &m : importingProductItem->modules()) { if (m.name.toString() == exportingProduct->name) { for (const Item::Module &dep : m.item->modules()) { if (dep.isProduct) directDepNames.push_back(dep.name.toString()); } break; } } const ModuleLoaderResult::ProductInfo &importingProductInfo = m_loadResult.productInfos.value(importingProductItem); const ProductDependencyInfos &depInfos = getProductDependencies(dummyProduct, importingProductInfo); for (const auto &dep : depInfos.dependencies) { if (dep.product == exportingProduct) continue; // Filter out indirect dependencies. // TODO: Depends items using "profile" or "productTypes" will not work. if (!contains(directDepNames, dep.product->name)) continue; if (!contains(exportingProduct->exportedModule.productDependencies, dep.product->uniqueName())) { exportingProduct->exportedModule.productDependencies.push_back( dep.product->uniqueName()); } if (!dep.parameters.isEmpty()) { exportingProduct->exportedModule.dependencyParameters.insert(dep.product, dep.parameters); } } auto &productDeps = exportingProduct->exportedModule.productDependencies; std::sort(productDeps.begin(), productDeps.end()); } } void ProjectResolver::resolveShadowProduct(Item *item, ProjectResolver::ProjectContext *) { if (!m_productContext->product->enabled) return; for (const auto &m : item->modules()) { if (m.name.toString() != m_productContext->product->name) continue; collectPropertiesForExportItem(m.item); for (const auto &dep : m.item->modules()) collectPropertiesForModuleInExportItem(dep); break; } try { adaptExportedPropertyValues(item); } catch (const ErrorInfo &) {} m_productExportInfo.push_back(std::make_pair(m_productContext->product, item)); } void ProjectResolver::setupExportedProperties(const Item *item, const QString &namePrefix, std::vector &properties) { const auto &props = item->properties(); for (auto it = props.cbegin(); it != props.cend(); ++it) { const QString qualifiedName = namePrefix.isEmpty() ? it.key() : namePrefix + QLatin1Char('.') + it.key(); if ((item->type() == ItemType::Export || item->type() == ItemType::Properties) && qualifiedName == StringConstants::prefixMappingProperty()) { continue; } const ValuePtr &v = it.value(); if (v->type() == Value::ItemValueType) { setupExportedProperties(std::static_pointer_cast(v)->item(), qualifiedName, properties); continue; } ExportedProperty exportedProperty; exportedProperty.fullName = qualifiedName; exportedProperty.type = item->propertyDeclaration(it.key()).type(); if (v->type() == Value::VariantValueType) { exportedProperty.sourceCode = toJSLiteral( std::static_pointer_cast(v)->value()); } else { QBS_CHECK(v->type() == Value::JSSourceValueType); const JSSourceValue * const sv = static_cast(v.get()); exportedProperty.sourceCode = sv->sourceCode().toString(); } const ItemDeclaration itemDecl = BuiltinDeclarations::instance().declarationsForType(item->type()); PropertyDeclaration propertyDecl; for (const PropertyDeclaration &decl : itemDecl.properties()) { if (decl.name() == it.key()) { propertyDecl = decl; exportedProperty.isBuiltin = true; break; } } // Do not add built-in properties that were left at their default value. if (!exportedProperty.isBuiltin || m_evaluator->isNonDefaultValue(item, it.key())) properties.push_back(exportedProperty); } // Order the list of properties, so the output won't look so random. static const auto less = [](const ExportedProperty &p1, const ExportedProperty &p2) -> bool { const int p1ComponentCount = p1.fullName.count(QLatin1Char('.')); const int p2ComponentCount = p2.fullName.count(QLatin1Char('.')); if (p1.isBuiltin && !p2.isBuiltin) return true; if (!p1.isBuiltin && p2.isBuiltin) return false; if (p1ComponentCount < p2ComponentCount) return true; if (p1ComponentCount > p2ComponentCount) return false; return p1.fullName < p2.fullName; }; std::sort(properties.begin(), properties.end(), less); } static bool usesImport(const ExportedProperty &prop, const QRegExp ®ex) { return regex.indexIn(prop.sourceCode) != -1; } static bool usesImport(const ExportedItem &item, const QRegExp ®ex) { return any_of(item.properties, [regex](const ExportedProperty &p) { return usesImport(p, regex); }) || any_of(item.children, [regex](const ExportedItemPtr &child) { return usesImport(*child, regex); }); } static bool usesImport(const ExportedModule &module, const QString &name) { // Imports are used in three ways: // (1) var f = new TextFile(...); // (2) var path = FileInfo.joinPaths(...) // (3) var obj = DataCollection; const QString pattern = QStringLiteral("\\b%1\\b"); const QRegExp regex(pattern.arg(name)); // std::regex is much slower return any_of(module.m_properties, [regex](const ExportedProperty &p) { return usesImport(p, regex); }) || any_of(module.children, [regex](const ExportedItemPtr &child) { return usesImport(*child, regex); }); } static QString getLineAtLocation(const CodeLocation &loc, const QString &content) { int pos = 0; int currentLine = 1; while (currentLine < loc.line()) { while (content.at(pos++) != QLatin1Char('\n')) ; ++currentLine; } const int eolPos = content.indexOf(QLatin1Char('\n'), pos); return content.mid(pos, eolPos - pos); } void ProjectResolver::resolveExport(Item *exportItem, ProjectContext *) { ExportedModule &exportedModule = m_productContext->product->exportedModule; setupExportedProperties(exportItem, QString(), exportedModule.m_properties); static const auto cmpFunc = [](const ExportedProperty &p1, const ExportedProperty &p2) { return p1.fullName < p2.fullName; }; std::sort(exportedModule.m_properties.begin(), exportedModule.m_properties.end(), cmpFunc); for (const Item * const child : exportItem->children()) exportedModule.children.push_back(resolveExportChild(child, exportedModule)); for (const JsImport &jsImport : exportItem->file()->jsImports()) { if (usesImport(exportedModule, jsImport.scopeName)) { exportedModule.importStatements << getLineAtLocation(jsImport.location, exportItem->file()->content()); } } for (const QString &builtinImport: JsExtensions::extensionNames()) { if (usesImport(exportedModule, builtinImport)) exportedModule.importStatements << QStringLiteral("import qbs.") + builtinImport; } exportedModule.importStatements.sort(); } // TODO: This probably wouldn't be necessary if we had item serialization. std::unique_ptr ProjectResolver::resolveExportChild(const Item *item, const ExportedModule &module) { std::unique_ptr exportedItem(new ExportedItem); // This is the type of the built-in base item. It may turn out that we need to support // derived items under Export. In that case, we probably need a new Item member holding // the original type name. exportedItem->name = item->typeName(); for (const Item * const child : item->children()) exportedItem->children.push_back(resolveExportChild(child, module)); setupExportedProperties(item, QString(), exportedItem->properties); return exportedItem; } QString ProjectResolver::sourceCodeAsFunction(const JSSourceValueConstPtr &value, const PropertyDeclaration &decl) const { QString &scriptFunction = m_scriptFunctions[std::make_pair(value->sourceCode(), decl.functionArgumentNames())]; if (!scriptFunction.isNull()) return scriptFunction; const QString args = decl.functionArgumentNames().join(QLatin1Char(',')); if (value->hasFunctionForm()) { // Insert the argument list. scriptFunction = value->sourceCodeForEvaluation(); scriptFunction.insert(10, args); // Remove the function application "()" that has been // added in ItemReaderASTVisitor::visitStatement. scriptFunction.chop(2); } else { scriptFunction = QLatin1String("(function(") + args + QLatin1String("){return ") + value->sourceCode().toString() + QLatin1String(";})"); } return scriptFunction; } QString ProjectResolver::sourceCodeForEvaluation(const JSSourceValueConstPtr &value) const { QString &code = m_sourceCode[value->sourceCode()]; if (!code.isNull()) return code; code = value->sourceCodeForEvaluation(); return code; } ScriptFunctionPtr ProjectResolver::scriptFunctionValue(Item *item, const QString &name) const { JSSourceValuePtr value = item->sourceProperty(name); ScriptFunctionPtr &script = m_scriptFunctionMap[value ? value->location() : CodeLocation()]; if (!script.get()) { script = ScriptFunction::create(); const PropertyDeclaration decl = item->propertyDeclaration(name); script->sourceCode = sourceCodeAsFunction(value, decl); script->location = value->location(); script->fileContext = resolvedFileContext(value->file()); } return script; } ResolvedFileContextPtr ProjectResolver::resolvedFileContext(const FileContextConstPtr &ctx) const { ResolvedFileContextPtr &result = m_fileContextMap[ctx]; if (!result) result = ResolvedFileContext::create(*ctx); return result; } void ProjectResolver::resolveRule(Item *item, ProjectContext *projectContext) { checkCancelation(); if (!m_evaluator->boolValue(item, StringConstants::conditionProperty())) return; RulePtr rule = Rule::create(); // read artifacts bool hasArtifactChildren = false; for (Item * const child : item->children()) { if (Q_UNLIKELY(child->type() != ItemType::Artifact)) { throw ErrorInfo(Tr::tr("'Rule' can only have children of type 'Artifact'."), child->location()); } hasArtifactChildren = true; resolveRuleArtifact(rule, child); } rule->name = m_evaluator->stringValue(item, StringConstants::nameProperty()); rule->prepareScript.initialize(scriptFunctionValue(item, StringConstants::prepareProperty())); rule->outputArtifactsScript.initialize(scriptFunctionValue( item, StringConstants::outputArtifactsProperty())); rule->outputFileTags = m_evaluator->fileTagsValue( item, StringConstants::outputFileTagsProperty()); if (rule->outputArtifactsScript.isValid()) { if (hasArtifactChildren) throw ErrorInfo(Tr::tr("The Rule.outputArtifacts script is not allowed in rules " "that contain Artifact items."), item->location()); } if (!hasArtifactChildren && rule->outputFileTags.empty()) { throw ErrorInfo(Tr::tr("A rule needs to have Artifact items or a non-empty " "outputFileTags property."), item->location()); } rule->multiplex = m_evaluator->boolValue(item, StringConstants::multiplexProperty()); rule->alwaysRun = m_evaluator->boolValue(item, StringConstants::alwaysRunProperty()); rule->inputs = m_evaluator->fileTagsValue(item, StringConstants::inputsProperty()); rule->inputsFromDependencies = m_evaluator->fileTagsValue(item, StringConstants::inputsFromDependenciesProperty()); bool requiresInputsSet = false; rule->requiresInputs = m_evaluator->boolValue(item, StringConstants::requiresInputsProperty(), &requiresInputsSet); if (!requiresInputsSet) rule->requiresInputs = rule->declaresInputs(); rule->auxiliaryInputs = m_evaluator->fileTagsValue(item, StringConstants::auxiliaryInputsProperty()); rule->excludedInputs = m_evaluator->fileTagsValue(item, StringConstants::excludedInputsProperty()); if (rule->excludedInputs.empty()) { rule->excludedInputs = m_evaluator->fileTagsValue( item, StringConstants::excludedAuxiliaryInputsProperty()); } rule->explicitlyDependsOn = m_evaluator->fileTagsValue(item, StringConstants::explicitlyDependsOnProperty()); rule->explicitlyDependsOnFromDependencies = m_evaluator->fileTagsValue( item, StringConstants::explicitlyDependsOnFromDependenciesProperty()); rule->module = m_moduleContext ? m_moduleContext->module : projectContext->dummyModule; if (!rule->multiplex && !rule->declaresInputs()) { throw ErrorInfo(Tr::tr("Rule has no inputs, but is not a multiplex rule."), item->location()); } if (!rule->multiplex && !rule->requiresInputs) { throw ErrorInfo(Tr::tr("Rule.requiresInputs is false for non-multiplex rule."), item->location()); } if (!rule->declaresInputs() && rule->requiresInputs) { throw ErrorInfo(Tr::tr("Rule.requiresInputs is true, but the rule " "does not declare any input tags."), item->location()); } if (m_productContext) { rule->product = m_productContext->product.get(); m_productContext->product->rules.push_back(rule); } else { projectContext->rules.push_back(rule); } } void ProjectResolver::resolveRuleArtifact(const RulePtr &rule, Item *item) { RuleArtifactPtr artifact = RuleArtifact::create(); rule->artifacts.push_back(artifact); artifact->location = item->location(); if (const auto sourceProperty = item->sourceProperty(StringConstants::filePathProperty())) artifact->filePathLocation = sourceProperty->location(); artifact->filePath = verbatimValue(item, StringConstants::filePathProperty()); artifact->fileTags = m_evaluator->fileTagsValue(item, StringConstants::fileTagsProperty()); artifact->alwaysUpdated = m_evaluator->boolValue(item, StringConstants::alwaysUpdatedProperty()); QualifiedIdSet seenBindings; for (Item *obj = item; obj; obj = obj->prototype()) { for (QMap::const_iterator it = obj->properties().constBegin(); it != obj->properties().constEnd(); ++it) { if (it.value()->type() != Value::ItemValueType) continue; resolveRuleArtifactBinding(artifact, std::static_pointer_cast(it.value())->item(), QStringList(it.key()), &seenBindings); } } } void ProjectResolver::resolveRuleArtifactBinding(const RuleArtifactPtr &ruleArtifact, Item *item, const QStringList &namePrefix, QualifiedIdSet *seenBindings) { for (QMap::const_iterator it = item->properties().constBegin(); it != item->properties().constEnd(); ++it) { const QStringList name = QStringList(namePrefix) << it.key(); if (it.value()->type() == Value::ItemValueType) { resolveRuleArtifactBinding(ruleArtifact, std::static_pointer_cast(it.value())->item(), name, seenBindings); } else if (it.value()->type() == Value::JSSourceValueType) { const auto insertResult = seenBindings->insert(name); if (!insertResult.second) continue; JSSourceValuePtr sourceValue = std::static_pointer_cast(it.value()); RuleArtifact::Binding rab; rab.name = name; rab.code = sourceCodeForEvaluation(sourceValue); rab.location = sourceValue->location(); ruleArtifact->bindings.push_back(rab); } else { QBS_ASSERT(!"unexpected value type", continue); } } } void ProjectResolver::resolveFileTagger(Item *item, ProjectContext *projectContext) { checkCancelation(); if (!m_evaluator->boolValue(item, StringConstants::conditionProperty())) return; std::vector &fileTaggers = m_productContext ? m_productContext->product->fileTaggers : projectContext->fileTaggers; const QStringList patterns = m_evaluator->stringListValue(item, StringConstants::patternsProperty()); if (patterns.empty()) throw ErrorInfo(Tr::tr("FileTagger.patterns must be a non-empty list."), item->location()); const FileTags fileTags = m_evaluator->fileTagsValue(item, StringConstants::fileTagsProperty()); if (fileTags.empty()) throw ErrorInfo(Tr::tr("FileTagger.fileTags must not be empty."), item->location()); for (const QString &pattern : patterns) { if (pattern.isEmpty()) throw ErrorInfo(Tr::tr("A FileTagger pattern must not be empty."), item->location()); } const int priority = m_evaluator->intValue(item, StringConstants::priorityProperty()); fileTaggers.push_back(FileTagger::create(patterns, fileTags, priority)); } void ProjectResolver::resolveJobLimit(Item *item, ProjectResolver::ProjectContext *projectContext) { if (!m_evaluator->boolValue(item, StringConstants::conditionProperty())) return; const QString jobPool = m_evaluator->stringValue(item, StringConstants::jobPoolProperty()); if (jobPool.isEmpty()) throw ErrorInfo(Tr::tr("A JobLimit item needs to have a non-empty '%1' property.") .arg(StringConstants::jobPoolProperty()), item->location()); bool jobCountWasSet; const int jobCount = m_evaluator->intValue(item, StringConstants::jobCountProperty(), -1, &jobCountWasSet); if (!jobCountWasSet) { throw ErrorInfo(Tr::tr("A JobLimit item needs to have a '%1' property.") .arg(StringConstants::jobCountProperty()), item->location()); } if (jobCount < 0) { throw ErrorInfo(Tr::tr("A JobLimit item must have a non-negative '%1' property.") .arg(StringConstants::jobCountProperty()), item->location()); } JobLimits &jobLimits = m_moduleContext ? m_moduleContext->jobLimits : m_productContext ? m_productContext->product->jobLimits : projectContext->jobLimits; JobLimit jobLimit(jobPool, jobCount); const int oldLimit = jobLimits.getLimit(jobPool); if (oldLimit == -1 || oldLimit > jobCount) jobLimits.setJobLimit(jobLimit); } void ProjectResolver::resolveScanner(Item *item, ProjectResolver::ProjectContext *projectContext) { checkCancelation(); if (!m_evaluator->boolValue(item, StringConstants::conditionProperty())) { qCDebug(lcProjectResolver) << "scanner condition is false"; return; } ResolvedScannerPtr scanner = ResolvedScanner::create(); scanner->module = m_moduleContext ? m_moduleContext->module : projectContext->dummyModule; scanner->inputs = m_evaluator->fileTagsValue(item, StringConstants::inputsProperty()); scanner->recursive = m_evaluator->boolValue(item, StringConstants::recursiveProperty()); scanner->searchPathsScript.initialize(scriptFunctionValue( item, StringConstants::searchPathsProperty())); scanner->scanScript.initialize(scriptFunctionValue(item, StringConstants::scanProperty())); m_productContext->product->scanners.push_back(scanner); } ProjectResolver::ProductDependencyInfos ProjectResolver::getProductDependencies( const ResolvedProductConstPtr &product, const ModuleLoaderResult::ProductInfo &productInfo) { ProductDependencyInfos result; result.dependencies.reserve(productInfo.usedProducts.size()); for (const auto &dependency : productInfo.usedProducts) { QBS_CHECK(!dependency.name.isEmpty()); if (dependency.profile == StringConstants::star()) { for (const ResolvedProductPtr &p : qAsConst(m_productsByName)) { if (p->name != dependency.name || p == product || !p->enabled || (dependency.limitToSubProject && !product->isInParentProject(p))) { continue; } result.dependencies.emplace_back(p, dependency.parameters); } } else { ResolvedProductPtr usedProduct = m_productsByName.value(dependency.uniqueName()); const QString depDisplayName = ResolvedProduct::fullDisplayName(dependency.name, dependency.multiplexConfigurationId); if (!usedProduct) { throw ErrorInfo(Tr::tr("Product '%1' depends on '%2', which does not exist.") .arg(product->fullDisplayName(), depDisplayName), product->location); } if (!dependency.profile.isEmpty() && usedProduct->profile() != dependency.profile) { usedProduct.reset(); for (const ResolvedProductPtr &p : qAsConst(m_productsByName)) { if (p->name == dependency.name && p->profile() == dependency.profile) { usedProduct = p; break; } } if (!usedProduct) { throw ErrorInfo(Tr::tr("Product '%1' depends on '%2', which does not exist " "for the requested profile '%3'.") .arg(product->fullDisplayName(), depDisplayName, dependency.profile), product->location); } } if (!usedProduct->enabled) { if (!dependency.isRequired) continue; ErrorInfo e; e.append(Tr::tr("Product '%1' depends on '%2',") .arg(product->name, usedProduct->name), product->location); e.append(Tr::tr("but product '%1' is disabled.").arg(usedProduct->name), usedProduct->location); if (m_setupParams.productErrorMode() == ErrorHandlingMode::Strict) throw e; result.hasDisabledDependency = true; } result.dependencies.emplace_back(usedProduct, dependency.parameters); } } return result; } void ProjectResolver::matchArtifactProperties(const ResolvedProductPtr &product, const std::vector &artifacts) { for (const SourceArtifactPtr &artifact : artifacts) { for (const ArtifactPropertiesConstPtr &artifactProperties : product->artifactProperties) { if (!artifact->isTargetOfModule() && artifact->fileTags.intersects(artifactProperties->fileTagsFilter())) { artifact->properties = artifactProperties->propertyMap(); } } } } void ProjectResolver::printProfilingInfo() { if (!m_setupParams.logElapsedTime()) return; m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("All property evaluation took %1.") .arg(elapsedTimeString(m_elapsedTimeAllPropEval)); m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Module property evaluation took %1.") .arg(elapsedTimeString(m_elapsedTimeModPropEval)); m_logger.qbsLog(LoggerInfo, true) << "\t" << Tr::tr("Resolving groups (without module property " "evaluation) took %1.") .arg(elapsedTimeString(m_elapsedTimeGroups)); } class TempScopeSetter { public: TempScopeSetter(Item * item, Item *newScope) : m_item(item), m_oldScope(item->scope()) { item->setScope(newScope); } ~TempScopeSetter() { m_item->setScope(m_oldScope); } private: Item * const m_item; Item * const m_oldScope; }; void ProjectResolver::collectPropertiesForExportItem(Item *productModuleInstance) { if (!productModuleInstance->isPresentModule()) return; Item * const exportItem = productModuleInstance->prototype(); QBS_CHECK(exportItem && exportItem->type() == ItemType::Export); TempScopeSetter tempScopeSetter(exportItem, productModuleInstance->scope()); const ItemDeclaration::Properties exportDecls = BuiltinDeclarations::instance() .declarationsForType(ItemType::Export).properties(); ExportedModule &exportedModule = m_productContext->product->exportedModule; const auto &props = exportItem->properties(); for (auto it = props.begin(); it != props.end(); ++it) { const auto match = [it](const PropertyDeclaration &decl) { return decl.name() == it.key(); }; if (it.key() != StringConstants::prefixMappingProperty() && std::find_if(exportDecls.begin(), exportDecls.end(), match) != exportDecls.end()) { continue; } if (it.value()->type() == Value::ItemValueType) { collectPropertiesForExportItem(it.key(), it.value(), productModuleInstance, exportedModule.modulePropertyValues); } else { evaluateProperty(exportItem, it.key(), it.value(), exportedModule.propertyValues, false); } } } // Collects module properties assigned to in other (higher-level) modules. void ProjectResolver::collectPropertiesForModuleInExportItem(const Item::Module &module) { if (!module.item->isPresentModule()) return; ExportedModule &exportedModule = m_productContext->product->exportedModule; if (module.isProduct || module.name.first() == StringConstants::qbsModule()) return; const auto checkName = [module](const ExportedModuleDependency &d) { return module.name.toString() == d.name; }; if (any_of(exportedModule.moduleDependencies, checkName)) return; Item *modulePrototype = module.item->prototype(); while (modulePrototype && modulePrototype->type() != ItemType::Module) modulePrototype = modulePrototype->prototype(); if (!modulePrototype) // Can happen for broken products in relaxed mode. return; TempScopeSetter tempScopeSetter(modulePrototype, module.item->scope()); const Item::PropertyMap &props = modulePrototype->properties(); ExportedModuleDependency dep; dep.name = module.name.toString(); for (auto it = props.begin(); it != props.end(); ++it) { if (it.value()->type() == Value::ItemValueType) collectPropertiesForExportItem(it.key(), it.value(), module.item, dep.moduleProperties); } exportedModule.moduleDependencies.push_back(dep); for (const auto &dep : module.item->modules()) collectPropertiesForModuleInExportItem(dep); } static bool hasDependencyCycle(Set *checked, Set *branch, const ResolvedProductPtr &product, ErrorInfo *error) { if (branch->contains(product.get())) return true; if (checked->contains(product.get())) return false; checked->insert(product.get()); branch->insert(product.get()); for (const ResolvedProductPtr &dep : qAsConst(product->dependencies)) { if (hasDependencyCycle(checked, branch, dep, error)) { error->prepend(dep->name, dep->location); return true; } } branch->remove(product.get()); return false; } using DependencyMap = QHash>; void gatherDependencies(ResolvedProduct *product, DependencyMap &dependencies) { if (dependencies.contains(product)) return; Set &productDeps = dependencies[product]; for (const ResolvedProductPtr &dep : qAsConst(product->dependencies)) { productDeps << dep.get(); gatherDependencies(dep.get(), dependencies); productDeps += dependencies.value(dep.get()); } } static DependencyMap allDependencies(const std::vector &products) { DependencyMap dependencies; for (const ResolvedProductPtr &product : products) gatherDependencies(product.get(), dependencies); return dependencies; } void ProjectResolver::resolveProductDependencies(const ProjectContext &projectContext) { // Resolve all inter-product dependencies. const std::vector allProducts = projectContext.project->allProducts(); bool disabledDependency = false; for (const ResolvedProductPtr &rproduct : allProducts) { if (!rproduct->enabled) continue; Item *productItem = m_productItemMap.value(rproduct); const ModuleLoaderResult::ProductInfo &productInfo = m_loadResult.productInfos.value(productItem); const ProductDependencyInfos &depInfos = getProductDependencies(rproduct, productInfo); if (depInfos.hasDisabledDependency) disabledDependency = true; for (const auto &dep : depInfos.dependencies) { if (!contains(rproduct->dependencies, dep.product)) rproduct->dependencies.push_back(dep.product); if (!dep.parameters.empty()) rproduct->dependencyParameters.insert(dep.product, dep.parameters); } } // Check for cyclic dependencies. Set checked; for (const ResolvedProductPtr &rproduct : allProducts) { Set branch; ErrorInfo error; if (hasDependencyCycle(&checked, &branch, rproduct, &error)) { error.prepend(rproduct->name, rproduct->location); error.prepend(Tr::tr("Cyclic dependencies detected.")); throw error; } } // Mark all products as disabled that have a disabled dependency. if (disabledDependency && m_setupParams.productErrorMode() == ErrorHandlingMode::Relaxed) { const DependencyMap allDeps = allDependencies(allProducts); DependencyMap allDepsReversed; for (auto it = allDeps.constBegin(); it != allDeps.constEnd(); ++it) { for (ResolvedProduct *dep : qAsConst(it.value())) allDepsReversed[dep] << it.key(); } for (auto it = allDepsReversed.constBegin(); it != allDepsReversed.constEnd(); ++it) { if (it.key()->enabled) continue; for (ResolvedProduct * const dependingProduct : qAsConst(it.value())) { if (dependingProduct->enabled) { m_logger.qbsWarning() << Tr::tr("Disabling product '%1', because it depends on " "disabled product '%2'.") .arg(dependingProduct->name, it.key()->name); dependingProduct->enabled = false; } } } } } void ProjectResolver::postProcess(const ResolvedProductPtr &product, ProjectContext *projectContext) const { product->fileTaggers << projectContext->fileTaggers; std::sort(std::begin(product->fileTaggers), std::end(product->fileTaggers), [] (const FileTaggerConstPtr &a, const FileTaggerConstPtr &b) { return a->priority() > b->priority(); }); for (const RulePtr &rule : projectContext->rules) { RulePtr clonedRule = rule->clone(); clonedRule->product = product.get(); product->rules.push_back(clonedRule); } } void ProjectResolver::applyFileTaggers(const ResolvedProductPtr &product) const { for (const SourceArtifactPtr &artifact : product->allEnabledFiles()) applyFileTaggers(artifact, product); } void ProjectResolver::applyFileTaggers(const SourceArtifactPtr &artifact, const ResolvedProductConstPtr &product) { if (!artifact->overrideFileTags || artifact->fileTags.empty()) { const QString fileName = FileInfo::fileName(artifact->absoluteFilePath); const FileTags fileTags = product->fileTagsForFileName(fileName); artifact->fileTags.unite(fileTags); if (artifact->fileTags.empty()) artifact->fileTags.insert(unknownFileTag()); qCDebug(lcProjectResolver) << "adding file tags" << artifact->fileTags << "to" << fileName; } } QVariantMap ProjectResolver::evaluateModuleValues(Item *item, bool lookupPrototype) { AccumulatingTimer modPropEvalTimer(m_setupParams.logElapsedTime() ? &m_elapsedTimeModPropEval : nullptr); QVariantMap moduleValues; for (const Item::Module &module : item->modules()) { if (!module.item->isPresentModule()) continue; const QString fullName = module.name.toString(); moduleValues[fullName] = evaluateProperties(module.item, lookupPrototype, true); } return moduleValues; } QVariantMap ProjectResolver::evaluateProperties(Item *item, bool lookupPrototype, bool checkErrors) { const QVariantMap tmplt; return evaluateProperties(item, item, tmplt, lookupPrototype, checkErrors); } QVariantMap ProjectResolver::evaluateProperties(const Item *item, const Item *propertiesContainer, const QVariantMap &tmplt, bool lookupPrototype, bool checkErrors) { AccumulatingTimer propEvalTimer(m_setupParams.logElapsedTime() ? &m_elapsedTimeAllPropEval : nullptr); QVariantMap result = tmplt; for (QMap::const_iterator it = propertiesContainer->properties().begin(); it != propertiesContainer->properties().end(); ++it) { checkCancelation(); evaluateProperty(item, it.key(), it.value(), result, checkErrors); } return lookupPrototype && propertiesContainer->prototype() ? evaluateProperties(item, propertiesContainer->prototype(), result, true, checkErrors) : result; } void ProjectResolver::evaluateProperty(const Item *item, const QString &propName, const ValuePtr &propValue, QVariantMap &result, bool checkErrors) { switch (propValue->type()) { case Value::ItemValueType: { // Ignore items. Those point to module instances // and are handled in evaluateModuleValues(). break; } case Value::JSSourceValueType: { if (result.contains(propName)) break; const PropertyDeclaration pd = item->propertyDeclaration(propName); if (pd.flags().testFlag(PropertyDeclaration::PropertyNotAvailableInConfig)) { break; } const QScriptValue scriptValue = m_evaluator->property(item, propName); if (checkErrors && Q_UNLIKELY(m_evaluator->engine()->hasErrorOrException(scriptValue))) { throw ErrorInfo(m_evaluator->engine()->lastError(scriptValue, propValue->location())); } // NOTE: Loses type information if scriptValue.isUndefined == true, // as such QScriptValues become invalid QVariants. QVariant v; if (scriptValue.isFunction()) { v = scriptValue.toString(); } else { v = scriptValue.toVariant(); QVariantMap m = v.toMap(); if (m.contains(StringConstants::importScopeNamePropertyInternal())) { QVariantMap tmp = m; m = scriptValue.prototype().toVariant().toMap(); for (auto it = tmp.begin(); it != tmp.end(); ++it) m.insert(it.key(), it.value()); v = m; } } if (pd.type() == PropertyDeclaration::Path && v.isValid()) { v = v.toString(); } else if (pd.type() == PropertyDeclaration::PathList || pd.type() == PropertyDeclaration::StringList) { v = v.toStringList(); } else if (pd.type() == PropertyDeclaration::VariantList) { v = v.toList(); } result[propName] = v; break; } case Value::VariantValueType: { if (result.contains(propName)) break; VariantValuePtr vvp = std::static_pointer_cast(propValue); QVariant v = vvp->value(); if (v.isNull() && !item->propertyDeclaration(propName).isScalar()) // QTBUG-51237 v = QStringList(); result[propName] = v; break; } } } void ProjectResolver::collectPropertiesForExportItem(const QualifiedId &moduleName, const ValuePtr &value, Item *moduleInstance, QVariantMap &moduleProps) { QBS_CHECK(value->type() == Value::ItemValueType); Item * const itemValueItem = std::static_pointer_cast(value)->item(); if (itemValueItem->type() == ItemType::ModuleInstance) { struct EvalPreparer { EvalPreparer(Item *valueItem, Item *moduleInstance, const QualifiedId &moduleName) : valueItem(valueItem), oldScope(valueItem->scope()), hadName(!!valueItem->variantProperty(StringConstants::nameProperty())) { valueItem->setScope(moduleInstance); if (!hadName) { // EvaluatorScriptClass expects a name here. valueItem->setProperty(StringConstants::nameProperty(), VariantValue::create(moduleName.toString())); } } ~EvalPreparer() { valueItem->setScope(oldScope); if (!hadName) valueItem->setProperty(StringConstants::nameProperty(), VariantValuePtr()); } Item * const valueItem; Item * const oldScope; const bool hadName; }; EvalPreparer ep(itemValueItem, moduleInstance, moduleName); moduleProps.insert(moduleName.toString(), evaluateProperties(itemValueItem, false, false)); return; } QBS_CHECK(itemValueItem->type() == ItemType::ModulePrefix); const Item::PropertyMap &props = itemValueItem->properties(); for (auto it = props.begin(); it != props.end(); ++it) { QualifiedId fullModuleName = moduleName; fullModuleName << it.key(); collectPropertiesForExportItem(fullModuleName, it.value(), moduleInstance, moduleProps); } } void ProjectResolver::createProductConfig(ResolvedProduct *product) { EvalCacheEnabler cachingEnabler(m_evaluator); m_evaluator->setPathPropertiesBaseDir(m_productContext->product->sourceDirectory); product->moduleProperties->setValue(evaluateModuleValues(m_productContext->item)); product->productProperties = evaluateProperties(m_productContext->item, m_productContext->item, QVariantMap(), true, true); m_evaluator->clearPathPropertiesBaseDir(); } void ProjectResolver::callItemFunction(const ItemFuncMap &mappings, Item *item, ProjectContext *projectContext) { const ItemFuncPtr f = mappings.value(item->type()); QBS_CHECK(f); if (item->type() == ItemType::Project) { ProjectContext subProjectContext = createProjectContext(projectContext); (this->*f)(item, &subProjectContext); } else { (this->*f)(item, projectContext); } } ProjectResolver::ProjectContext ProjectResolver::createProjectContext(ProjectContext *parentProjectContext) const { ProjectContext subProjectContext; subProjectContext.parentContext = parentProjectContext; subProjectContext.project = ResolvedProject::create(); parentProjectContext->project->subProjects.push_back(subProjectContext.project); subProjectContext.project->parentProject = parentProjectContext->project; return subProjectContext; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/projectresolver.h000066400000000000000000000224711347155106100233200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef PROJECTRESOLVER_H #define PROJECTRESOLVER_H #include "filetags.h" #include "itemtype.h" #include "moduleloader.h" #include "qualifiedid.h" #include #include #include #include #include #include #include namespace qbs { class JobLimits; namespace Internal { class Evaluator; class Item; class ProgressObserver; class ScriptEngine; class ProjectResolver { public: ProjectResolver(Evaluator *evaluator, const ModuleLoaderResult &loadResult, const SetupProjectParameters &setupParameters, Logger &logger); ~ProjectResolver(); void setProgressObserver(ProgressObserver *observer); TopLevelProjectPtr resolve(); static void applyFileTaggers(const SourceArtifactPtr &artifact, const ResolvedProductConstPtr &product); using FileLocations = QHash, CodeLocation>; static SourceArtifactPtr createSourceArtifact(const ResolvedProductPtr &rproduct, const QString &fileName, const GroupPtr &group, bool wildcard, const CodeLocation &filesLocation = CodeLocation(), FileLocations *fileLocations = nullptr, ErrorInfo *errorInfo = nullptr); private: struct ProjectContext; struct ProductContext; struct ModuleContext; class ProductContextSwitcher; void checkCancelation() const; QString verbatimValue(const ValueConstPtr &value, bool *propertyWasSet = nullptr) const; QString verbatimValue(Item *item, const QString &name, bool *propertyWasSet = nullptr) const; ScriptFunctionPtr scriptFunctionValue(Item *item, const QString &name) const; ResolvedFileContextPtr resolvedFileContext(const FileContextConstPtr &ctx) const; void ignoreItem(Item *item, ProjectContext *projectContext); TopLevelProjectPtr resolveTopLevelProject(); void resolveProject(Item *item, ProjectContext *projectContext); void resolveProjectFully(Item *item, ProjectContext *projectContext); void resolveSubProject(Item *item, ProjectContext *projectContext); void resolveProduct(Item *item, ProjectContext *projectContext); void resolveProductFully(Item *item, ProjectContext *projectContext); void resolveModules(const Item *item, ProjectContext *projectContext); void resolveModule(const QualifiedId &moduleName, Item *item, bool isProduct, const QVariantMap ¶meters, JobLimits &jobLimits, ProjectContext *projectContext); void gatherProductTypes(ResolvedProduct *product, Item *item); QVariantMap resolveAdditionalModuleProperties(const Item *group, const QVariantMap ¤tValues); void resolveGroup(Item *item, ProjectContext *projectContext); void resolveGroupFully(Item *item, ProjectContext *projectContext, bool isEnabled); void resolveShadowProduct(Item *item, ProjectContext *); void resolveExport(Item *exportItem, ProjectContext *); std::unique_ptr resolveExportChild(const Item *item, const ExportedModule &module); void resolveRule(Item *item, ProjectContext *projectContext); void resolveRuleArtifact(const RulePtr &rule, Item *item); void resolveRuleArtifactBinding(const RuleArtifactPtr &ruleArtifact, Item *item, const QStringList &namePrefix, QualifiedIdSet *seenBindings); void resolveFileTagger(Item *item, ProjectContext *projectContext); void resolveJobLimit(Item *item, ProjectContext *projectContext); void resolveScanner(Item *item, ProjectContext *projectContext); void resolveProductDependencies(const ProjectContext &projectContext); void postProcess(const ResolvedProductPtr &product, ProjectContext *projectContext) const; void applyFileTaggers(const ResolvedProductPtr &product) const; QVariantMap evaluateModuleValues(Item *item, bool lookupPrototype = true); QVariantMap evaluateProperties(Item *item, bool lookupPrototype, bool checkErrors); QVariantMap evaluateProperties(const Item *item, const Item *propertiesContainer, const QVariantMap &tmplt, bool lookupPrototype, bool checkErrors); void evaluateProperty(const Item *item, const QString &propName, const ValuePtr &propValue, QVariantMap &result, bool checkErrors); void createProductConfig(ResolvedProduct *product); ProjectContext createProjectContext(ProjectContext *parentProjectContext) const; void adaptExportedPropertyValues(const Item *shadowProductItem); void collectExportedProductDependencies(); struct ProductDependencyInfo { ProductDependencyInfo(const ResolvedProductPtr &product, const QVariantMap ¶meters = QVariantMap()) : product(product), parameters(parameters) { } ResolvedProductPtr product; QVariantMap parameters; }; struct ProductDependencyInfos { std::vector dependencies; bool hasDisabledDependency = false; }; ProductDependencyInfos getProductDependencies(const ResolvedProductConstPtr &product, const ModuleLoaderResult::ProductInfo &productInfo); QString sourceCodeAsFunction(const JSSourceValueConstPtr &value, const PropertyDeclaration &decl) const; QString sourceCodeForEvaluation(const JSSourceValueConstPtr &value) const; static void matchArtifactProperties(const ResolvedProductPtr &product, const std::vector &artifacts); void printProfilingInfo(); void collectPropertiesForExportItem(Item *productModuleInstance); void collectPropertiesForModuleInExportItem(const Item::Module &module); void collectPropertiesForExportItem(const QualifiedId &moduleName, const ValuePtr &value, Item *moduleInstance, QVariantMap &moduleProps); void setupExportedProperties(const Item *item, const QString &namePrefix, std::vector &properties); Evaluator *m_evaluator; Logger &m_logger; ScriptEngine *m_engine; ProgressObserver *m_progressObserver; ProductContext *m_productContext; ModuleContext *m_moduleContext; QMap m_productsByName; QHash > m_productsByType; QHash m_productItemMap; mutable QHash m_fileContextMap; mutable QHash m_scriptFunctionMap; mutable QHash, QString> m_scriptFunctions; mutable QHash m_sourceCode; const SetupProjectParameters &m_setupParams; ModuleLoaderResult m_loadResult; Set m_groupLocationWarnings; std::vector> m_productExportInfo; std::vector m_queuedErrors; qint64 m_elapsedTimeModPropEval; qint64 m_elapsedTimeAllPropEval; qint64 m_elapsedTimeGroups; typedef void (ProjectResolver::*ItemFuncPtr)(Item *item, ProjectContext *projectContext); using ItemFuncMap = QMap; void callItemFunction(const ItemFuncMap &mappings, Item *item, ProjectContext *projectContext); }; } // namespace Internal } // namespace qbs #endif // PROJECTRESOLVER_H qbs-src-1.13.1/src/lib/corelib/language/property.cpp000066400000000000000000000045531347155106100223100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "property.h" namespace qbs { namespace Internal { bool operator<(const Property &p1, const Property &p2) { int cmpResult = QString::compare(p1.productName, p2.productName); if (cmpResult < 0) return true; if (cmpResult > 0) return false; cmpResult = QString::compare(p1.moduleName, p2.moduleName); if (cmpResult < 0) return true; if (cmpResult > 0) return false; return p1.propertyName < p2.propertyName; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/property.h000066400000000000000000000066351347155106100217600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROPERTY_H #define QBS_PROPERTY_H #include #include #include #include namespace qbs { namespace Internal { class Property { public: enum Kind { PropertyInModule, PropertyInProduct, PropertyInProject, PropertyInParameters, PropertyInArtifact, }; Property() : kind(PropertyInModule) { } Property(const QString &product, const QString &module, const QString &property, const QVariant &v, Kind k) : productName(product), moduleName(module), propertyName(property), value(v), kind(k) { } template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(productName, moduleName, propertyName, value, kind); } QString productName; // In case of kind == PropertyInProject, this is the project name. QString moduleName; QString propertyName; QVariant value; Kind kind; }; inline bool operator==(const Property &p1, const Property &p2) { return p1.productName == p2.productName && p1.moduleName == p2.moduleName && p1.propertyName == p2.propertyName; } bool operator<(const Property &p1, const Property &p2); inline uint qHash(const Property &p) { return QT_PREPEND_NAMESPACE(qHash)(p.productName + p.moduleName + p.propertyName); } using PropertySet = Set; using PropertyHash = QHash; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/language/propertydeclaration.cpp000066400000000000000000000157171347155106100245220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "propertydeclaration.h" #include "deprecationinfo.h" #include #include #include #include namespace qbs { namespace Internal { class PropertyDeclarationData : public QSharedData { public: PropertyDeclarationData() : type(PropertyDeclaration::UnknownType) , flags(PropertyDeclaration::DefaultFlags) { } QString name; PropertyDeclaration::Type type; PropertyDeclaration::Flags flags; QString description; QString initialValueSource; QStringList functionArgumentNames; DeprecationInfo deprecationInfo; }; PropertyDeclaration::PropertyDeclaration() : d(new PropertyDeclarationData) { } PropertyDeclaration::PropertyDeclaration(const QString &name, Type type, const QString &initialValue, Flags flags) : d(new PropertyDeclarationData) { d->name = name; d->type = type; d->initialValueSource = initialValue; d->flags = flags; } PropertyDeclaration::PropertyDeclaration(const PropertyDeclaration &other) : d(other.d) { } PropertyDeclaration::~PropertyDeclaration() { } PropertyDeclaration &PropertyDeclaration::operator=(const PropertyDeclaration &other) { d = other.d; return *this; } bool PropertyDeclaration::isValid() const { return d && d->type != UnknownType; } bool PropertyDeclaration::isScalar() const { // ### Should be determined by a PropertyOption in the future. return d->type != PathList && d->type != StringList && d->type != VariantList; } static QString boolString() { return QStringLiteral("bool"); } static QString intString() { return QStringLiteral("int"); } static QString pathListString() { return QStringLiteral("pathList"); } static QString stringString() { return QStringLiteral("string"); } static QString stringListString() { return QStringLiteral("stringList"); } static QString varString() { return QStringLiteral("var"); } static QString variantString() { return QStringLiteral("variant"); } static QString varListString() { return QStringLiteral("varList"); } PropertyDeclaration::Type PropertyDeclaration::propertyTypeFromString(const QString &typeName) { if (typeName == boolString()) return PropertyDeclaration::Boolean; if (typeName == intString()) return PropertyDeclaration::Integer; if (typeName == StringConstants::pathType()) return PropertyDeclaration::Path; if (typeName == pathListString()) return PropertyDeclaration::PathList; if (typeName == stringString()) return PropertyDeclaration::String; if (typeName == stringListString()) return PropertyDeclaration::StringList; if (typeName == varString() || typeName == variantString()) return PropertyDeclaration::Variant; if (typeName == varListString()) return PropertyDeclaration::VariantList; return PropertyDeclaration::UnknownType; } QString PropertyDeclaration::typeString() const { return typeString(type()); } QString PropertyDeclaration::typeString(PropertyDeclaration::Type t) { switch (t) { case Boolean: return boolString(); case Integer: return intString(); case Path: return StringConstants::pathType(); case PathList: return pathListString(); case String: return stringString(); case StringList: return stringListString(); case Variant: return variantString(); case VariantList: return varListString(); case UnknownType: return QStringLiteral("unknown"); } Q_UNREACHABLE(); // For stupid compilers. } const QString &PropertyDeclaration::name() const { return d->name; } void PropertyDeclaration::setName(const QString &name) { d->name = name; } PropertyDeclaration::Type PropertyDeclaration::type() const { return d->type; } void PropertyDeclaration::setType(PropertyDeclaration::Type t) { d->type = t; } PropertyDeclaration::Flags PropertyDeclaration::flags() const { return d->flags; } void PropertyDeclaration::setFlags(Flags f) { d->flags = f; } const QString &PropertyDeclaration::description() const { return d->description; } void PropertyDeclaration::setDescription(const QString &str) { d->description = str; } const QString &PropertyDeclaration::initialValueSource() const { return d->initialValueSource; } void PropertyDeclaration::setInitialValueSource(const QString &str) { d->initialValueSource = str; } const QStringList &PropertyDeclaration::functionArgumentNames() const { return d->functionArgumentNames; } void PropertyDeclaration::setFunctionArgumentNames(const QStringList &lst) { d->functionArgumentNames = lst; } bool PropertyDeclaration::isDeprecated() const { return d->deprecationInfo.isValid(); } bool PropertyDeclaration::isExpired() const { return isDeprecated() && deprecationInfo().removalVersion() <= LanguageInfo::qbsVersion(); } const DeprecationInfo &PropertyDeclaration::deprecationInfo() const { return d->deprecationInfo; } void PropertyDeclaration::setDeprecationInfo(const DeprecationInfo &deprecationInfo) { d->deprecationInfo = deprecationInfo; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/propertydeclaration.h000066400000000000000000000075611347155106100241650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROPERTYDECLARATION_H #define QBS_PROPERTYDECLARATION_H #include #include QT_BEGIN_NAMESPACE class QStringList; QT_END_NAMESPACE namespace qbs { namespace Internal { class DeprecationInfo; class PropertyDeclarationData; class PropertyDeclaration { public: enum Type { UnknownType, Boolean, Integer, Path, PathList, String, StringList, Variant, VariantList, }; enum Flag { DefaultFlags = 0, ReadOnlyFlag = 0x1, PropertyNotAvailableInConfig = 0x2 // Is this property part of a project, product or file configuration? }; Q_DECLARE_FLAGS(Flags, Flag) PropertyDeclaration(); PropertyDeclaration(const QString &name, Type type, const QString &initialValue = QString(), Flags flags = DefaultFlags); PropertyDeclaration(const PropertyDeclaration &other); ~PropertyDeclaration(); PropertyDeclaration &operator=(const PropertyDeclaration &other); bool isValid() const; bool isScalar() const; static Type propertyTypeFromString(const QString &typeName); QString typeString() const; static QString typeString(Type t); const QString &name() const; void setName(const QString &name); Type type() const; void setType(Type t); Flags flags() const; void setFlags(Flags f); const QString &description() const; void setDescription(const QString &str); const QString &initialValueSource() const; void setInitialValueSource(const QString &str); const QStringList &functionArgumentNames() const; void setFunctionArgumentNames(const QStringList &lst); bool isDeprecated() const; bool isExpired() const; const DeprecationInfo &deprecationInfo() const; void setDeprecationInfo(const DeprecationInfo &deprecationInfo); private: QSharedDataPointer d; }; } // namespace Internal } // namespace qbs #endif // QBS_PROPERTYDECLARATION_H qbs-src-1.13.1/src/lib/corelib/language/propertymapinternal.cpp000066400000000000000000000100251347155106100245320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "propertymapinternal.h" #include #include #include namespace qbs { namespace Internal { /*! * \class PropertyMapInternal * \brief The \c PropertyMapInternal class contains a set of properties and their values. * An instance of this class is attached to every \c ResolvedProduct. * \c ResolvedGroups inherit their properties from the respective \c ResolvedProduct, \c SourceArtifacts * inherit theirs from the respective \c ResolvedGroup. \c ResolvedGroups can override the value of an * inherited property, \c SourceArtifacts cannot. If a property value is overridden, a new * \c PropertyMapInternal object is allocated, otherwise the pointer is shared. * \sa ResolvedGroup * \sa ResolvedProduct * \sa SourceArtifact */ PropertyMapInternal::PropertyMapInternal() { } PropertyMapInternal::PropertyMapInternal(const PropertyMapInternal &other) : m_value(other.m_value) { } QVariant PropertyMapInternal::moduleProperty(const QString &moduleName, const QString &key, bool *isPresent) const { return ::qbs::Internal::moduleProperty(m_value, moduleName, key, isPresent); } QVariant PropertyMapInternal::qbsPropertyValue(const QString &key) const { return moduleProperty(StringConstants::qbsModule(), key); } QVariant PropertyMapInternal::property(const QStringList &name) const { return getConfigProperty(m_value, name); } void PropertyMapInternal::setValue(const QVariantMap &map) { m_value = map; } QVariant moduleProperty(const QVariantMap &properties, const QString &moduleName, const QString &key, bool *isPresent) { const auto moduleIt = properties.find(moduleName); if (moduleIt == properties.end()) { if (isPresent) *isPresent = false; return {}; } const QVariantMap &moduleMap = moduleIt.value().toMap(); const auto propertyIt = moduleMap.find(key); if (propertyIt == moduleMap.end()) { if (isPresent) *isPresent = false; return {}; } if (isPresent) *isPresent = true; return propertyIt.value(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/propertymapinternal.h000066400000000000000000000067351347155106100242140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROPERTYMAPINTERNAL_H #define QBS_PROPERTYMAPINTERNAL_H #include "forward_decls.h" #include #include #include namespace qbs { namespace Internal { class QBS_AUTOTEST_EXPORT PropertyMapInternal { public: static PropertyMapPtr create() { return PropertyMapPtr(new PropertyMapInternal); } PropertyMapPtr clone() const { return PropertyMapPtr(new PropertyMapInternal(*this)); } const QVariantMap &value() const { return m_value; } QVariant moduleProperty(const QString &moduleName, const QString &key, bool *isPresent = nullptr) const; QVariant qbsPropertyValue(const QString &key) const; // Convenience function. QVariant property(const QStringList &name) const; void setValue(const QVariantMap &value); template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(m_value); } private: friend bool operator==(const PropertyMapInternal &lhs, const PropertyMapInternal &rhs); PropertyMapInternal(); PropertyMapInternal(const PropertyMapInternal &other); QVariantMap m_value; }; inline bool operator==(const PropertyMapInternal &lhs, const PropertyMapInternal &rhs) { return lhs.m_value == rhs.m_value; } QVariant QBS_AUTOTEST_EXPORT moduleProperty(const QVariantMap &properties, const QString &moduleName, const QString &key, bool *isPresent = nullptr); } // namespace Internal } // namespace qbs #endif // QBS_PROPERTYMAPINTERNAL_H qbs-src-1.13.1/src/lib/corelib/language/qualifiedid.cpp000066400000000000000000000045721347155106100227050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qualifiedid.h" #include namespace qbs { namespace Internal { QualifiedId::QualifiedId() { } QualifiedId::QualifiedId(const QString &singlePartName) : QStringList(singlePartName) { } QualifiedId::QualifiedId(const QStringList &nameParts) : QStringList(nameParts) { } QualifiedId QualifiedId::fromString(const QString &str) { return QualifiedId(str.split(QLatin1Char('.'))); } QString QualifiedId::toString() const { return join(QLatin1Char('.')); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/qualifiedid.h000066400000000000000000000051451347155106100223470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_QUALIFIEDID_H #define QBS_QUALIFIEDID_H #include #include #include namespace qbs { namespace Internal { class QBS_AUTOTEST_EXPORT QualifiedId : public QStringList { public: QualifiedId(); QualifiedId(const QString &singlePartName); QualifiedId(const QStringList &nameParts); static QualifiedId fromString(const QString &str); QString toString() const; }; inline uint qHash(const QualifiedId &qid) { return qHash(qid.toString()); } using QualifiedIdSet = Set; // Values are the properties with a dependency on the key property using PropertyDependencies = QHash; } // namespace Internal } // namespace qbs #endif // QBS_QUALIFIEDID_H qbs-src-1.13.1/src/lib/corelib/language/resolvedfilecontext.cpp000066400000000000000000000045511347155106100245120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "resolvedfilecontext.h" #include "jsimports.h" #include namespace qbs { namespace Internal { ResolvedFileContext::ResolvedFileContext(const FileContextBase &ctx) : FileContextBase(ctx) { } bool operator==(const ResolvedFileContext &a, const ResolvedFileContext &b) { return a.filePath() == b.filePath() && a.jsExtensions().toSet() == b.jsExtensions().toSet() && sorted(a.jsImports()) == sorted(b.jsImports()); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/resolvedfilecontext.h000066400000000000000000000056571347155106100241670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_RESOLVEDFILECONTEXT_H #define QBS_RESOLVEDFILECONTEXT_H #include "forward_decls.h" #include "filecontextbase.h" #include namespace qbs { namespace Internal { class ResolvedFileContext : public FileContextBase { public: static ResolvedFileContextPtr create() { return ResolvedFileContextPtr(new ResolvedFileContext); } static ResolvedFileContextPtr create(const FileContextBase &baseContext) { return ResolvedFileContextPtr(new ResolvedFileContext(baseContext)); } template void completeSerializationOp(PersistentPool &pool) { pool.serializationOp(m_filePath, m_jsExtensions, m_searchPaths, m_jsImports); } private: ResolvedFileContext() {} ResolvedFileContext(const FileContextBase &ctx); }; bool operator==(const ResolvedFileContext &a, const ResolvedFileContext &b); inline bool operator!=(const ResolvedFileContext &a, const ResolvedFileContext &b) { return !(a == b); } } // namespace Internal } // namespace qbs #endif // QBS_RESOLVEDFILECONTEXT_H qbs-src-1.13.1/src/lib/corelib/language/scriptengine.cpp000066400000000000000000000761261347155106100231230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "scriptengine.h" #include "filecontextbase.h" #include "jsimports.h" #include "propertymapinternal.h" #include "scriptimporter.h" #include "preparescriptobserver.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static QString getterFuncHelperProperty() { return QStringLiteral("qbsdata"); } const bool debugJSImports = false; bool operator==(const ScriptEngine::PropertyCacheKey &lhs, const ScriptEngine::PropertyCacheKey &rhs) { return lhs.m_propertyMap == rhs.m_propertyMap && lhs.m_moduleName == rhs.m_moduleName && lhs.m_propertyName == rhs.m_propertyName; } static inline uint combineHash(uint h1, uint h2, uint seed) { // stolen from qHash(QPair) return ((h1 << 16) | (h1 >> 16)) ^ h2 ^ seed; } uint qHash(const ScriptEngine::PropertyCacheKey &k, uint seed = 0) { return combineHash(qHash(k.m_moduleName), combineHash(qHash(k.m_propertyName), qHash(k.m_propertyMap), seed), seed); } std::mutex ScriptEngine::m_creationDestructionMutex; ScriptEngine::ScriptEngine(Logger &logger, EvalContext evalContext, QObject *parent) : QScriptEngine(parent), m_scriptImporter(new ScriptImporter(this)), m_modulePropertyScriptClass(nullptr), m_propertyCacheEnabled(true), m_active(false), m_logger(logger), m_evalContext(evalContext), m_observer(new PrepareScriptObserver(this, UnobserveMode::Disabled)) { setProcessEventsInterval(1000); // For the cancelation mechanism to work. m_cancelationError = currentContext()->throwValue(tr("Execution canceled")); QScriptValue objectProto = globalObject().property(QStringLiteral("Object")); m_definePropertyFunction = objectProto.property(QStringLiteral("defineProperty")); QBS_ASSERT(m_definePropertyFunction.isFunction(), /* ignore */); m_emptyFunction = evaluate(QStringLiteral("(function(){})")); QBS_ASSERT(m_emptyFunction.isFunction(), /* ignore */); // Initially push a new context to turn off scope chain insanity mode. QScriptEngine::pushContext(); installQbsBuiltins(); extendJavaScriptBuiltins(); } ScriptEngine *ScriptEngine::create(Logger &logger, EvalContext evalContext, QObject *parent) { std::lock_guard lock(m_creationDestructionMutex); return new ScriptEngine(logger, evalContext, parent); } ScriptEngine::~ScriptEngine() { m_creationDestructionMutex.lock(); connect(this, &QObject::destroyed, std::bind(&std::mutex::unlock, &m_creationDestructionMutex)); releaseResourcesOfScriptObjects(); delete (m_scriptImporter); if (m_elapsedTimeImporting != -1) { m_logger.qbsLog(LoggerInfo, true) << Tr::tr("Setting up imports took %1.") .arg(elapsedTimeString(m_elapsedTimeImporting)); } delete m_modulePropertyScriptClass; delete m_productPropertyScriptClass; } void ScriptEngine::import(const FileContextBaseConstPtr &fileCtx, QScriptValue &targetObject, ObserveMode observeMode) { installImportFunctions(); m_currentDirPathStack.push(FileInfo::path(fileCtx->filePath())); m_extensionSearchPathsStack.push(fileCtx->searchPaths()); m_observeMode = observeMode; for (const JsImport &jsImport : fileCtx->jsImports()) import(jsImport, targetObject); if (m_observeMode == ObserveMode::Enabled) { for (QScriptValue &sv : m_requireResults) observeImport(sv); m_requireResults.clear(); } m_currentDirPathStack.pop(); m_extensionSearchPathsStack.pop(); uninstallImportFunctions(); } void ScriptEngine::import(const JsImport &jsImport, QScriptValue &targetObject) { QBS_ASSERT(targetObject.isObject(), return); QBS_ASSERT(targetObject.engine() == this, return); if (debugJSImports) qDebug() << "[ENGINE] import into " << jsImport.scopeName; QScriptValue jsImportValue = m_jsImportCache.value(jsImport); if (jsImportValue.isValid()) { if (debugJSImports) qDebug() << "[ENGINE] " << jsImport.filePaths << " (cache hit)"; } else { if (debugJSImports) qDebug() << "[ENGINE] " << jsImport.filePaths << " (cache miss)"; jsImportValue = newObject(); for (const QString &filePath : jsImport.filePaths) importFile(filePath, jsImportValue); m_jsImportCache.insert(jsImport, jsImportValue); std::vector &filePathsForScriptValue = m_filePathsPerImport[jsImportValue.objectId()]; for (const QString &fp : jsImport.filePaths) filePathsForScriptValue.push_back(fp); } QScriptValue sv = newObject(); sv.setPrototype(jsImportValue); sv.setProperty(StringConstants::importScopeNamePropertyInternal(), jsImport.scopeName); targetObject.setProperty(jsImport.scopeName, sv); if (m_observeMode == ObserveMode::Enabled) observeImport(jsImportValue); } void ScriptEngine::observeImport(QScriptValue &jsImport) { if (!m_observer->addImportId(jsImport.objectId())) return; QScriptValueIterator it(jsImport); while (it.hasNext()) { it.next(); if (it.flags() & QScriptValue::PropertyGetter) continue; QScriptValue property = it.value(); if (!property.isFunction()) continue; setObservedProperty(jsImport, it.name(), property); } } void ScriptEngine::clearImportsCache() { m_jsImportCache.clear(); } void ScriptEngine::checkContext(const QString &operation, const DubiousContextList &dubiousContexts) { for (const DubiousContext &info : dubiousContexts) { if (info.context != evalContext()) continue; QString warning; switch (info.context) { case EvalContext::PropertyEvaluation: warning = Tr::tr("Suspicious use of %1 during property evaluation.").arg(operation); if (info.suggestion == DubiousContext::SuggestMoving) warning += QLatin1Char(' ') + Tr::tr("Should this call be in a Probe instead?"); break; case EvalContext::RuleExecution: warning = Tr::tr("Suspicious use of %1 during rule execution.").arg(operation); if (info.suggestion == DubiousContext::SuggestMoving) { warning += QLatin1Char(' ') + Tr::tr("Should this call be in a JavaScriptCommand instead?"); } break; case EvalContext::ModuleProvider: case EvalContext::ProbeExecution: case EvalContext::JsCommand: QBS_ASSERT(false, continue); break; } m_logger.printWarning(ErrorInfo(warning, currentContext()->backtrace())); return; } } void ScriptEngine::addPropertyRequestedFromArtifact(const Artifact *artifact, const Property &property) { m_propertiesRequestedFromArtifact[artifact->filePath()] << property; } void ScriptEngine::addImportRequestedInScript(qint64 importValueId) { // Import list is assumed to be small, so let's not use a set. if (!contains(m_importsRequestedInScript, importValueId)) m_importsRequestedInScript.push_back(importValueId); } std::vector ScriptEngine::importedFilesUsedInScript() const { std::vector files; for (qint64 usedImport : m_importsRequestedInScript) { const auto it = m_filePathsPerImport.find(usedImport); QBS_CHECK(it != m_filePathsPerImport.cend()); const std::vector &filePathsForImport = it->second; for (const QString &fp : filePathsForImport) if (!contains(files, fp)) files.push_back(fp); } return files; } void ScriptEngine::enableProfiling(bool enable) { m_elapsedTimeImporting = enable ? 0 : -1; } void ScriptEngine::addToPropertyCache(const QString &moduleName, const QString &propertyName, const PropertyMapConstPtr &propertyMap, const QVariant &value) { m_propertyCache.insert(PropertyCacheKey(moduleName, propertyName, propertyMap), value); } QVariant ScriptEngine::retrieveFromPropertyCache(const QString &moduleName, const QString &propertyName, const PropertyMapConstPtr &propertyMap) { return m_propertyCache.value(PropertyCacheKey(moduleName, propertyName, propertyMap)); } void ScriptEngine::defineProperty(QScriptValue &object, const QString &name, const QScriptValue &descriptor) { QScriptValue arguments = newArray(); arguments.setProperty(0, object); arguments.setProperty(1, name); arguments.setProperty(2, descriptor); QScriptValue result = m_definePropertyFunction.call(QScriptValue(), arguments); QBS_ASSERT(!hasErrorOrException(result), qDebug() << name << result.toString()); } static QScriptValue js_observedGet(QScriptContext *context, QScriptEngine *, ScriptPropertyObserver * const observer) { const QScriptValue data = context->callee().property(getterFuncHelperProperty()); const QScriptValue value = data.property(2); observer->onPropertyRead(data.property(0), data.property(1).toVariant().toString(), value); return value; } void ScriptEngine::setObservedProperty(QScriptValue &object, const QString &name, const QScriptValue &value) { QScriptValue data = newArray(); data.setProperty(0, object); data.setProperty(1, name); data.setProperty(2, value); QScriptValue getterFunc = newFunction(js_observedGet, static_cast(m_observer.get())); getterFunc.setProperty(getterFuncHelperProperty(), data); object.setProperty(name, getterFunc, QScriptValue::PropertyGetter); if (m_observer->unobserveMode() == UnobserveMode::Enabled) m_observedProperties.emplace_back(object, name, value); } void ScriptEngine::unobserveProperties() { for (auto &elem : m_observedProperties) { QScriptValue &object = std::get<0>(elem); const QString &name = std::get<1>(elem); const QScriptValue &value = std::get<2>(elem); object.setProperty(name, QScriptValue(), QScriptValue::PropertyGetter); object.setProperty(name, value, QScriptValue::PropertyFlags()); } m_observedProperties.clear(); } static QScriptValue js_deprecatedGet(QScriptContext *context, QScriptEngine *qtengine) { const auto engine = static_cast(qtengine); const QScriptValue data = context->callee().property(getterFuncHelperProperty()); engine->logger().qbsWarning() << ScriptEngine::tr("Property %1 is deprecated. Please use %2 instead.").arg( data.property(0).toString(), data.property(1).toString()); return data.property(2); } void ScriptEngine::setDeprecatedProperty(QScriptValue &object, const QString &oldName, const QString &newName, const QScriptValue &value) { QScriptValue data = newArray(); data.setProperty(0, oldName); data.setProperty(1, newName); data.setProperty(2, value); QScriptValue getterFunc = newFunction(js_deprecatedGet); getterFunc.setProperty(getterFuncHelperProperty(), data); object.setProperty(oldName, getterFunc, QScriptValue::PropertyGetter | QScriptValue::SkipInEnumeration); } QProcessEnvironment ScriptEngine::environment() const { return m_environment; } void ScriptEngine::setEnvironment(const QProcessEnvironment &env) { m_environment = env; } void ScriptEngine::importFile(const QString &filePath, QScriptValue &targetObject) { AccumulatingTimer importTimer(m_elapsedTimeImporting != -1 ? &m_elapsedTimeImporting : nullptr); QScriptValue &evaluationResult = m_jsFileCache[filePath]; if (evaluationResult.isValid()) { ScriptImporter::copyProperties(evaluationResult, targetObject); return; } QFile file(filePath); if (Q_UNLIKELY(!file.open(QFile::ReadOnly))) throw ErrorInfo(tr("Cannot open '%1'.").arg(filePath)); QTextStream stream(&file); stream.setCodec("UTF-8"); const QString sourceCode = stream.readAll(); file.close(); m_currentDirPathStack.push(FileInfo::path(filePath)); evaluationResult = m_scriptImporter->importSourceCode(sourceCode, filePath, targetObject); m_currentDirPathStack.pop(); } static QString findExtensionDir(const QStringList &searchPaths, const QString &extensionPath) { for (const QString &searchPath : searchPaths) { const QString dirPath = searchPath + QStringLiteral("/imports/") + extensionPath; QFileInfo fi(dirPath); if (fi.exists() && fi.isDir()) return dirPath; } return {}; } static QScriptValue mergeExtensionObjects(const QScriptValueList &lst) { QScriptValue result; for (const QScriptValue &v : lst) { if (!result.isValid()) { result = v; continue; } QScriptValueIterator svit(v); while (svit.hasNext()) { svit.next(); result.setProperty(svit.name(), svit.value()); } } return result; } static QScriptValue loadInternalExtension(QScriptContext *context, ScriptEngine *engine, const QString &uri) { const QString name = uri.mid(4); // remove the "qbs." part QScriptValue extensionObj = JsExtensions::loadExtension(engine, name); if (!extensionObj.isValid()) { return context->throwError(ScriptEngine::tr("loadExtension: " "cannot load extension '%1'.").arg(uri)); } return extensionObj; } QScriptValue ScriptEngine::js_loadExtension(QScriptContext *context, QScriptEngine *qtengine) { if (context->argumentCount() < 1) { return context->throwError( ScriptEngine::tr("The loadExtension function requires " "an extension name.")); } const auto engine = static_cast(qtengine); ErrorInfo deprWarning(Tr::tr("The loadExtension() function is deprecated and will be " "removed in a future version of Qbs. Use require() " "instead."), context->backtrace()); engine->logger().printWarning(deprWarning); return js_require(context, qtengine); } QScriptValue ScriptEngine::js_loadFile(QScriptContext *context, QScriptEngine *qtengine) { if (context->argumentCount() < 1) { return context->throwError( ScriptEngine::tr("The loadFile function requires a file path.")); } const auto engine = static_cast(qtengine); ErrorInfo deprWarning(Tr::tr("The loadFile() function is deprecated and will be " "removed in a future version of Qbs. Use require() " "instead."), context->backtrace()); engine->logger().printWarning(deprWarning); return js_require(context, qtengine); } QScriptValue ScriptEngine::js_require(QScriptContext *context, QScriptEngine *qtengine) { const auto engine = static_cast(qtengine); if (context->argumentCount() < 1) { return context->throwError( ScriptEngine::tr("The require function requires a module name or path.")); } const QString moduleName = context->argument(0).toString(); // First try to load a named module if the argument doesn't look like a file path if (!moduleName.contains(QLatin1Char('/'))) { if (engine->m_extensionSearchPathsStack.empty()) return context->throwError( ScriptEngine::tr("require: internal error. No search paths.")); const QString uri = moduleName; if (engine->m_logger.debugEnabled()) { engine->m_logger.qbsDebug() << "[require] loading extension " << uri; } QString uriAsPath = uri; uriAsPath.replace(QLatin1Char('.'), QLatin1Char('/')); const QStringList searchPaths = engine->m_extensionSearchPathsStack.top(); const QString dirPath = findExtensionDir(searchPaths, uriAsPath); if (dirPath.isEmpty()) { if (uri.startsWith(QStringLiteral("qbs."))) return loadInternalExtension(context, engine, uri); } else { QDirIterator dit(dirPath, StringConstants::jsFileWildcards(), QDir::Files | QDir::Readable); QScriptValueList values; std::vector filePaths; try { while (dit.hasNext()) { const QString filePath = dit.next(); if (engine->m_logger.debugEnabled()) { engine->m_logger.qbsDebug() << "[require] importing file " << filePath; } QScriptValue obj = engine->newObject(); engine->importFile(filePath, obj); values << obj; filePaths.push_back(filePath); } } catch (const ErrorInfo &e) { return context->throwError(e.toString()); } if (!values.empty()) { const QScriptValue mergedValue = mergeExtensionObjects(values); engine->m_requireResults.push_back(mergedValue); engine->m_filePathsPerImport[mergedValue.objectId()] = filePaths; return mergedValue; } } // The module name might be a file name component, which is assumed to be to a JavaScript // file located in the current directory search path; try that next } if (engine->m_currentDirPathStack.empty()) { return context->throwError( ScriptEngine::tr("require: internal error. No current directory.")); } QScriptValue result; try { const QString filePath = FileInfo::resolvePath(engine->m_currentDirPathStack.top(), moduleName); result = engine->newObject(); engine->importFile(filePath, result); static const QString scopeNamePrefix = QStringLiteral("_qbs_scope_"); const QString scopeName = scopeNamePrefix + QString::number(qHash(filePath), 16); result.setProperty(StringConstants::importScopeNamePropertyInternal(), scopeName); context->thisObject().setProperty(scopeName, result); engine->m_requireResults.push_back(result); engine->m_filePathsPerImport[result.objectId()] = { filePath }; } catch (const ErrorInfo &e) { result = context->throwError(e.toString()); } return result; } QScriptClass *ScriptEngine::modulePropertyScriptClass() const { return m_modulePropertyScriptClass; } void ScriptEngine::setModulePropertyScriptClass(QScriptClass *modulePropertyScriptClass) { m_modulePropertyScriptClass = modulePropertyScriptClass; } void ScriptEngine::addResourceAcquiringScriptObject(ResourceAcquiringScriptObject *obj) { m_resourceAcquiringScriptObjects.push_back(obj); } void ScriptEngine::releaseResourcesOfScriptObjects() { if (m_resourceAcquiringScriptObjects.empty()) return; std::for_each(m_resourceAcquiringScriptObjects.begin(), m_resourceAcquiringScriptObjects.end(), std::mem_fn(&ResourceAcquiringScriptObject::releaseResources)); m_resourceAcquiringScriptObjects.clear(); } void ScriptEngine::addCanonicalFilePathResult(const QString &filePath, const QString &resultFilePath) { if (gatherFileResults()) m_canonicalFilePathResult.insert(filePath, resultFilePath); } void ScriptEngine::addFileExistsResult(const QString &filePath, bool exists) { if (gatherFileResults()) m_fileExistsResult.insert(filePath, exists); } void ScriptEngine::addDirectoryEntriesResult(const QString &path, QDir::Filters filters, const QStringList &entries) { if (gatherFileResults()) { m_directoryEntriesResult.insert( std::pair(path, static_cast(filters)), entries); } } void ScriptEngine::addFileLastModifiedResult(const QString &filePath, const FileTime &fileTime) { if (gatherFileResults()) m_fileLastModifiedResult.insert(filePath, fileTime); } Set ScriptEngine::imports() const { Set filePaths; for (auto it = m_jsImportCache.cbegin(); it != m_jsImportCache.cend(); ++it) { const JsImport &jsImport = it.key(); for (const QString &filePath : jsImport.filePaths) filePaths << filePath; } for (auto it = m_filePathsPerImport.cbegin(); it != m_filePathsPerImport.cend(); ++it) { for (const QString &fp : it->second) filePaths << fp; } return filePaths; } QScriptValueList ScriptEngine::argumentList(const QStringList &argumentNames, const QScriptValue &context) { QScriptValueList result; for (const auto &name : argumentNames) result += context.property(name); return result; } CodeLocation ScriptEngine::lastErrorLocation(const QScriptValue &v, const CodeLocation &fallbackLocation) const { const QScriptValue &errorVal = lastErrorValue(v); const CodeLocation errorLoc(errorVal.property(StringConstants::fileNameProperty()).toString(), errorVal.property(QStringLiteral("lineNumber")).toInt32(), errorVal.property(QStringLiteral("expressionCaretOffset")).toInt32(), false); return errorLoc.isValid() ? errorLoc : fallbackLocation; } ErrorInfo ScriptEngine::lastError(const QScriptValue &v, const CodeLocation &fallbackLocation) const { const QString msg = lastErrorString(v); CodeLocation errorLocation = lastErrorLocation(v); if (errorLocation.isValid()) return ErrorInfo(msg, errorLocation); const QStringList backtrace = uncaughtExceptionBacktraceOrEmpty(); if (!backtrace.empty()) { ErrorInfo e(msg, backtrace); if (e.hasLocation()) return e; } return ErrorInfo(msg, fallbackLocation); } void ScriptEngine::cancel() { QTimer::singleShot(0, this, [this] { abort(); }); } void ScriptEngine::abort() { abortEvaluation(m_cancelationError); } bool ScriptEngine::gatherFileResults() const { return evalContext() == EvalContext::PropertyEvaluation || evalContext() == EvalContext::ProbeExecution; } class JSTypeExtender { public: JSTypeExtender(ScriptEngine *engine, const QString &typeName) : m_engine(engine) { m_proto = engine->globalObject().property(typeName) .property(QStringLiteral("prototype")); QBS_ASSERT(m_proto.isObject(), return); m_descriptor = engine->newObject(); } void addFunction(const QString &name, const QString &code) { QScriptValue f = m_engine->evaluate(code); QBS_ASSERT(f.isFunction(), return); m_descriptor.setProperty(QStringLiteral("value"), f); m_engine->defineProperty(m_proto, name, m_descriptor); } private: ScriptEngine *const m_engine; QScriptValue m_proto; QScriptValue m_descriptor; }; static QScriptValue js_consoleError(QScriptContext *context, QScriptEngine *engine, Logger *logger) { if (Q_UNLIKELY(context->argumentCount() != 1)) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("console.error() expects 1 argument")); logger->qbsLog(LoggerError) << context->argument(0).toString(); return engine->undefinedValue(); } static QScriptValue js_consoleWarn(QScriptContext *context, QScriptEngine *engine, Logger *logger) { if (Q_UNLIKELY(context->argumentCount() != 1)) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("console.warn() expects 1 argument")); logger->qbsWarning() << context->argument(0).toString(); return engine->undefinedValue(); } static QScriptValue js_consoleInfo(QScriptContext *context, QScriptEngine *engine, Logger *logger) { if (Q_UNLIKELY(context->argumentCount() != 1)) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("console.info() expects 1 argument")); logger->qbsInfo() << context->argument(0).toString(); return engine->undefinedValue(); } static QScriptValue js_consoleDebug(QScriptContext *context, QScriptEngine *engine, Logger *logger) { if (Q_UNLIKELY(context->argumentCount() != 1)) return context->throwError(QScriptContext::SyntaxError, QStringLiteral("console.debug() expects 1 argument")); logger->qbsDebug() << context->argument(0).toString(); return engine->undefinedValue(); } static QScriptValue js_consoleLog(QScriptContext *context, QScriptEngine *engine, Logger *logger) { return js_consoleDebug(context, engine, logger); } void ScriptEngine::installQbsBuiltins() { globalObject().setProperty(StringConstants::qbsModule(), m_qbsObject = newObject()); globalObject().setProperty(QStringLiteral("console"), m_consoleObject = newObject()); installConsoleFunction(QStringLiteral("debug"), &js_consoleDebug); installConsoleFunction(QStringLiteral("error"), &js_consoleError); installConsoleFunction(QStringLiteral("info"), &js_consoleInfo); installConsoleFunction(QStringLiteral("log"), &js_consoleLog); installConsoleFunction(QStringLiteral("warn"), &js_consoleWarn); } void ScriptEngine::extendJavaScriptBuiltins() { JSTypeExtender arrayExtender(this, QStringLiteral("Array")); arrayExtender.addFunction(QStringLiteral("contains"), QStringLiteral("(function(e){return this.indexOf(e) !== -1;})")); arrayExtender.addFunction(QStringLiteral("containsAll"), QStringLiteral("(function(e){var $this = this;" "return e.every(function (v) { return $this.contains(v) });})")); arrayExtender.addFunction(QStringLiteral("containsAny"), QStringLiteral("(function(e){var $this = this;" "return e.some(function (v) { return $this.contains(v) });})")); arrayExtender.addFunction(QStringLiteral("uniqueConcat"), QStringLiteral("(function(other){" "var r = this.concat();" "var s = {};" "r.forEach(function(x){ s[x] = true; });" "other.forEach(function(x){" "if (!s[x]) {" "s[x] = true;" "r.push(x);" "}" "});" "return r;})")); JSTypeExtender stringExtender(this, QStringLiteral("String")); stringExtender.addFunction(QStringLiteral("contains"), QStringLiteral("(function(e){return this.indexOf(e) !== -1;})")); stringExtender.addFunction(QStringLiteral("startsWith"), QStringLiteral("(function(e){return this.slice(0, e.length) === e;})")); stringExtender.addFunction(QStringLiteral("endsWith"), QStringLiteral("(function(e){return this.slice(-e.length) === e;})")); } void ScriptEngine::installFunction(const QString &name, int length, QScriptValue *functionValue, FunctionSignature f, QScriptValue *targetObject = nullptr) { if (!functionValue->isValid()) *functionValue = newFunction(f, length); (targetObject ? *targetObject : globalObject()).setProperty(name, *functionValue); } void ScriptEngine::installQbsFunction(const QString &name, int length, FunctionSignature f) { QScriptValue functionValue; installFunction(name, length, &functionValue, f, &m_qbsObject); } void ScriptEngine::installConsoleFunction(const QString &name, QScriptValue (*f)(QScriptContext *, QScriptEngine *, Logger *)) { m_consoleObject.setProperty(name, newFunction(f, &m_logger)); } static QString loadFileString() { return QStringLiteral("loadFile"); } static QString loadExtensionString() { return QStringLiteral("loadExtension"); } static QString requireString() { return QStringLiteral("require"); } void ScriptEngine::installImportFunctions() { installFunction(loadFileString(), 1, &m_loadFileFunction, js_loadFile); installFunction(loadExtensionString(), 1, &m_loadExtensionFunction, js_loadExtension); installFunction(requireString(), 1, &m_requireFunction, js_require); } void ScriptEngine::uninstallImportFunctions() { globalObject().setProperty(loadFileString(), QScriptValue()); globalObject().setProperty(loadExtensionString(), QScriptValue()); globalObject().setProperty(requireString(), QScriptValue()); } ScriptEngine::PropertyCacheKey::PropertyCacheKey(const QString &moduleName, const QString &propertyName, const PropertyMapConstPtr &propertyMap) : m_moduleName(moduleName), m_propertyName(propertyName), m_propertyMap(propertyMap) { } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/scriptengine.h000066400000000000000000000371751347155106100225710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SCRIPTENGINE_H #define QBS_SCRIPTENGINE_H #include "forward_decls.h" #include "property.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class Artifact; class JsImport; class PrepareScriptObserver; class ScriptImporter; class ScriptPropertyObserver; enum class EvalContext { PropertyEvaluation, ProbeExecution, ModuleProvider, RuleExecution, JsCommand }; class DubiousContext { public: enum Suggestion { NoSuggestion, SuggestMoving }; DubiousContext(EvalContext c, Suggestion s = NoSuggestion) : context(c), suggestion(s) { } EvalContext context; Suggestion suggestion; }; using DubiousContextList = std::vector; /* * ScriptObject that acquires resources, for example a file handle. * The ScriptObject should have QtOwnership and deleteLater() itself in releaseResources. */ class ResourceAcquiringScriptObject { public: virtual void releaseResources() = 0; }; enum class ObserveMode { Enabled, Disabled }; class QBS_AUTOTEST_EXPORT ScriptEngine : public QScriptEngine { Q_OBJECT ScriptEngine(Logger &logger, EvalContext evalContext, QObject *parent = nullptr); public: static ScriptEngine *create(Logger &logger, EvalContext evalContext, QObject *parent = nullptr); ~ScriptEngine(); Logger &logger() const { return m_logger; } void import(const FileContextBaseConstPtr &fileCtx, QScriptValue &targetObject, ObserveMode observeMode); void clearImportsCache(); void setEvalContext(EvalContext c) { m_evalContext = c; } EvalContext evalContext() const { return m_evalContext; } void checkContext(const QString &operation, const DubiousContextList &dubiousContexts); void addPropertyRequestedInScript(const Property &property) { m_propertiesRequestedInScript += property; } void addDependenciesArrayRequested(const ResolvedProduct *p) { m_productsWithRequestedDependencies.insert(p); } void setArtifactsMapRequested(const ResolvedProduct *product, bool forceUpdate) { m_requestedArtifacts.setAllArtifactTags(product, forceUpdate); } void setArtifactSetRequestedForTag(const ResolvedProduct *product, const FileTag &tag) { m_requestedArtifacts.setArtifactsForTag(product, tag); } void setNonExistingArtifactSetRequested(const ResolvedProduct *product, const QString &tag) { m_requestedArtifacts.setNonExistingTagRequested(product, tag); } void setArtifactsEnumerated(const ResolvedProduct *product) { m_requestedArtifacts.setArtifactsEnumerated(product); } void addPropertyRequestedFromArtifact(const Artifact *artifact, const Property &property); void addRequestedExport(const ResolvedProduct *product) { m_requestedExports.insert(product); } void clearRequestedProperties() { m_propertiesRequestedInScript.clear(); m_propertiesRequestedFromArtifact.clear(); m_importsRequestedInScript.clear(); m_productsWithRequestedDependencies.clear(); m_requestedArtifacts.clear(); m_requestedExports.clear(); } PropertySet propertiesRequestedInScript() const { return m_propertiesRequestedInScript; } QHash propertiesRequestedFromArtifact() const { return m_propertiesRequestedFromArtifact; } Set productsWithRequestedDependencies() const { return m_productsWithRequestedDependencies; } RequestedDependencies requestedDependencies() const { return RequestedDependencies(m_productsWithRequestedDependencies); } RequestedArtifacts requestedArtifacts() const { return m_requestedArtifacts; } Set requestedExports() const { return m_requestedExports; } void addImportRequestedInScript(qint64 importValueId); std::vector importedFilesUsedInScript() const; void setUsesIo() { m_usesIo = true; } void clearUsesIo() { m_usesIo = false; } bool usesIo() const { return m_usesIo; } void enableProfiling(bool enable); void setPropertyCacheEnabled(bool enable) { m_propertyCacheEnabled = enable; } bool isPropertyCacheEnabled() const { return m_propertyCacheEnabled; } void addToPropertyCache(const QString &moduleName, const QString &propertyName, const PropertyMapConstPtr &propertyMap, const QVariant &value); QVariant retrieveFromPropertyCache(const QString &moduleName, const QString &propertyName, const PropertyMapConstPtr &propertyMap); void defineProperty(QScriptValue &object, const QString &name, const QScriptValue &descriptor); void setObservedProperty(QScriptValue &object, const QString &name, const QScriptValue &value); void unobserveProperties(); void setDeprecatedProperty(QScriptValue &object, const QString &name, const QString &newName, const QScriptValue &value); PrepareScriptObserver *observer() const { return m_observer.get(); } QProcessEnvironment environment() const; void setEnvironment(const QProcessEnvironment &env); void addCanonicalFilePathResult(const QString &filePath, const QString &resultFilePath); void addFileExistsResult(const QString &filePath, bool exists); void addDirectoryEntriesResult(const QString &path, QDir::Filters filters, const QStringList &entries); void addFileLastModifiedResult(const QString &filePath, const FileTime &fileTime); QHash canonicalFilePathResults() const { return m_canonicalFilePathResult; } QHash fileExistsResults() const { return m_fileExistsResult; } QHash, QStringList> directoryEntriesResults() const { return m_directoryEntriesResult; } QHash fileLastModifiedResults() const { return m_fileLastModifiedResult; } Set imports() const; static QScriptValueList argumentList(const QStringList &argumentNames, const QScriptValue &context); QStringList uncaughtExceptionBacktraceOrEmpty() const { return hasUncaughtException() ? uncaughtExceptionBacktrace() : QStringList(); } bool hasErrorOrException(const QScriptValue &v) const { return v.isError() || hasUncaughtException(); } QScriptValue lastErrorValue(const QScriptValue &v) const { return v.isError() ? v : uncaughtException(); } QString lastErrorString(const QScriptValue &v) const { return lastErrorValue(v).toString(); } CodeLocation lastErrorLocation(const QScriptValue &v, const CodeLocation &fallbackLocation = CodeLocation()) const; ErrorInfo lastError(const QScriptValue &v, const CodeLocation &fallbackLocation = CodeLocation()) const; void cancel(); // The active flag is different from QScriptEngine::isEvaluating. // It is set and cleared externally for example by the rule execution code. bool isActive() const { return m_active; } void setActive(bool on) { m_active = on; } using QScriptEngine::newFunction; template ::value>, typename = std::enable_if_t::value>, typename = std::enable_if_t>::value> > QScriptValue newFunction(QScriptValue (*signature)(QScriptContext *, E, T), T arg) { return QScriptEngine::newFunction( reinterpret_cast(signature), reinterpret_cast(const_cast< std::add_pointer_t< std::remove_const_t< std::remove_pointer_t>>>(arg))); } QScriptClass *modulePropertyScriptClass() const; void setModulePropertyScriptClass(QScriptClass *modulePropertyScriptClass); QScriptClass *productPropertyScriptClass() const { return m_productPropertyScriptClass; } void setProductPropertyScriptClass(QScriptClass *productPropertyScriptClass) { m_productPropertyScriptClass = productPropertyScriptClass; } QScriptClass *artifactsScriptClass() const { return m_artifactsScriptClass; } void setArtifactsScriptClass(QScriptClass *artifactsScriptClass) { m_artifactsScriptClass = artifactsScriptClass; } void addResourceAcquiringScriptObject(ResourceAcquiringScriptObject *obj); void releaseResourcesOfScriptObjects(); QScriptValue &productScriptValuePrototype(const ResolvedProduct *product) { return m_productScriptValues[product]; } QScriptValue &projectScriptValue(const ResolvedProject *project) { return m_projectScriptValues[project]; } QScriptValue &moduleScriptValuePrototype(const ResolvedModule *module) { return m_moduleScriptValues[module]; } private: QScriptValue newFunction(FunctionWithArgSignature signature, void *arg) Q_DECL_EQ_DELETE; void abort(); bool gatherFileResults() const; void installQbsBuiltins(); void extendJavaScriptBuiltins(); void installFunction(const QString &name, int length, QScriptValue *functionValue, FunctionSignature f, QScriptValue *targetObject); void installQbsFunction(const QString &name, int length, FunctionSignature f); void installConsoleFunction(const QString &name, QScriptValue (*f)(QScriptContext *, QScriptEngine *, Logger *)); void installImportFunctions(); void uninstallImportFunctions(); void import(const JsImport &jsImport, QScriptValue &targetObject); void observeImport(QScriptValue &jsImport); void importFile(const QString &filePath, QScriptValue &targetObject); static QScriptValue js_loadExtension(QScriptContext *context, QScriptEngine *qtengine); static QScriptValue js_loadFile(QScriptContext *context, QScriptEngine *qtengine); static QScriptValue js_require(QScriptContext *context, QScriptEngine *qtengine); class PropertyCacheKey { public: PropertyCacheKey(const QString &moduleName, const QString &propertyName, const PropertyMapConstPtr &propertyMap); private: const QString m_moduleName; const QString m_propertyName; const PropertyMapConstPtr m_propertyMap; friend bool operator==(const PropertyCacheKey &lhs, const PropertyCacheKey &rhs); friend uint qHash(const ScriptEngine::PropertyCacheKey &k, uint seed); }; friend bool operator==(const PropertyCacheKey &lhs, const PropertyCacheKey &rhs); friend uint qHash(const ScriptEngine::PropertyCacheKey &k, uint seed); static std::mutex m_creationDestructionMutex; ScriptImporter *m_scriptImporter; QScriptClass *m_modulePropertyScriptClass; QScriptClass *m_productPropertyScriptClass = nullptr; QScriptClass *m_artifactsScriptClass = nullptr; QHash m_jsImportCache; std::unordered_map m_jsFileCache; bool m_propertyCacheEnabled; bool m_active; QHash m_propertyCache; PropertySet m_propertiesRequestedInScript; QHash m_propertiesRequestedFromArtifact; Logger &m_logger; QScriptValue m_definePropertyFunction; QScriptValue m_emptyFunction; QProcessEnvironment m_environment; QHash m_canonicalFilePathResult; QHash m_fileExistsResult; QHash, QStringList> m_directoryEntriesResult; QHash m_fileLastModifiedResult; std::stack m_currentDirPathStack; std::stack m_extensionSearchPathsStack; QScriptValue m_loadFileFunction; QScriptValue m_loadExtensionFunction; QScriptValue m_requireFunction; QScriptValue m_qbsObject; QScriptValue m_consoleObject; QScriptValue m_cancelationError; qint64 m_elapsedTimeImporting = -1; bool m_usesIo = false; EvalContext m_evalContext; std::vector m_resourceAcquiringScriptObjects; const std::unique_ptr m_observer; std::vector> m_observedProperties; std::vector m_requireResults; std::unordered_map> m_filePathsPerImport; std::vector m_importsRequestedInScript; Set m_productsWithRequestedDependencies; RequestedArtifacts m_requestedArtifacts; Set m_requestedExports; ObserveMode m_observeMode = ObserveMode::Disabled; std::unordered_map m_productScriptValues; std::unordered_map m_projectScriptValues; std::unordered_map m_moduleScriptValues; }; class EvalContextSwitcher { public: EvalContextSwitcher(ScriptEngine *engine, EvalContext newContext) : m_engine(engine), m_oldContext(engine->evalContext()) { engine->setEvalContext(newContext); } ~EvalContextSwitcher() { m_engine->setEvalContext(m_oldContext); } private: ScriptEngine * const m_engine; const EvalContext m_oldContext; }; } // namespace Internal } // namespace qbs #endif // QBS_SCRIPTENGINE_H qbs-src-1.13.1/src/lib/corelib/language/scriptimporter.cpp000066400000000000000000000121701347155106100235040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "scriptimporter.h" #include "evaluator.h" #include "scriptengine.h" #include #include #include #include #include #include namespace qbs { namespace Internal { class IdentifierExtractor : private QbsQmlJS::AST::Visitor { public: void start(QbsQmlJS::AST::Node *node) { m_first = true; m_barrier = false; m_suffix += QLatin1String("\nreturn {"); if (node) node->accept(this); m_suffix += QLatin1String("}})()"); } const QString &suffix() const { return m_suffix; } private: bool visit(QbsQmlJS::AST::SourceElements *) override { // Only consider the top level of source elements. if (m_barrier) return false; m_barrier = true; return true; } void endVisit(QbsQmlJS::AST::SourceElements *) override { m_barrier = false; } bool visit(QbsQmlJS::AST::FunctionSourceElement *fse) override { add(fse->declaration->name); return false; } bool visit(QbsQmlJS::AST::VariableDeclaration *vd) override { add(vd->name); return false; } void add(const QStringRef &name) { if (m_first) { m_first = false; m_suffix.reserve(m_suffix.length() + name.length() * 2 + 1); } else { m_suffix.reserve(m_suffix.length() + name.length() * 2 + 2); m_suffix += QLatin1Char(','); } m_suffix += name; m_suffix += QLatin1Char(':'); m_suffix += name; } bool m_first; bool m_barrier; QString m_suffix; }; ScriptImporter::ScriptImporter(ScriptEngine *scriptEngine) : m_engine(scriptEngine) { } QScriptValue ScriptImporter::importSourceCode(const QString &sourceCode, const QString &filePath, QScriptValue &targetObject) { Q_ASSERT(targetObject.isObject()); // The targetObject doesn't get overwritten but enhanced by the contents of the .js file. // This is necessary for library imports that consist of multiple js files. QString &code = m_sourceCodeCache[filePath]; if (code.isEmpty()) { QbsQmlJS::Engine engine; QbsQmlJS::Lexer lexer(&engine); lexer.setCode(sourceCode, 1, false); QbsQmlJS::Parser parser(&engine); if (!parser.parseProgram()) { throw ErrorInfo(parser.errorMessage(), CodeLocation(filePath, parser.errorLineNumber(), parser.errorColumnNumber())); } IdentifierExtractor extractor; extractor.start(parser.rootNode()); code = QLatin1String("(function(){\n") + sourceCode + extractor.suffix(); } QScriptValue result = m_engine->evaluate(code, filePath, 0); throwOnEvaluationError(m_engine, result, [&filePath] () { return CodeLocation(filePath, 0); }); copyProperties(result, targetObject); return result; } void ScriptImporter::copyProperties(const QScriptValue &src, QScriptValue &dst) { QScriptValueIterator it(src); while (it.hasNext()) { it.next(); dst.setProperty(it.name(), it.value()); } } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/scriptimporter.h000066400000000000000000000046751347155106100231640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SCRIPTIMPORTER_H #define SCRIPTIMPORTER_H #include #include namespace qbs { namespace Internal { class ScriptEngine; class ScriptImporter { public: ScriptImporter(ScriptEngine *scriptEngine); QScriptValue importSourceCode(const QString &sourceCode, const QString &filePath, QScriptValue &targetObject); static void copyProperties(const QScriptValue &src, QScriptValue &dst); private: ScriptEngine *m_engine; QHash m_sourceCodeCache; }; } // namespace Internal } // namespace qbs #endif // SCRIPTIMPORTER_H qbs-src-1.13.1/src/lib/corelib/language/scriptpropertyobserver.cpp000066400000000000000000000042051347155106100252770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "scriptpropertyobserver.h" #include "scriptengine.h" namespace qbs { namespace Internal { ScriptPropertyObserver::~ScriptPropertyObserver() { if (m_unobserveMode == UnobserveMode::Enabled) m_engine->unobserveProperties(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/scriptpropertyobserver.h000066400000000000000000000054421347155106100247500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SCRIPTPROPERTYOBSERVER_H #define QBS_SCRIPTPROPERTYOBSERVER_H #include QT_BEGIN_NAMESPACE class QScriptValue; class QString; QT_END_NAMESPACE namespace qbs { namespace Internal { class ScriptEngine; enum class UnobserveMode { Enabled, Disabled }; class ScriptPropertyObserver { public: ScriptPropertyObserver(ScriptEngine *engine, UnobserveMode unobserveMode) : m_engine(engine), m_unobserveMode(unobserveMode) {} UnobserveMode unobserveMode() const { return m_unobserveMode; } virtual ~ScriptPropertyObserver(); virtual void onPropertyRead(const QScriptValue &object, const QString &name, const QScriptValue &value) = 0; protected: ScriptEngine * engine() const { return m_engine; } private: ScriptEngine * const m_engine; const UnobserveMode m_unobserveMode; }; } // namespace Internal } // namespace qbs #endif // QBS_SCRIPTPROPERTYOBSERVER_H qbs-src-1.13.1/src/lib/corelib/language/value.cpp000066400000000000000000000141331347155106100215330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "value.h" #include "filecontext.h" #include "item.h" #include #include namespace qbs { namespace Internal { Value::Value(Type t, bool createdByPropertiesBlock) : m_type(t), m_definingItem(nullptr), m_createdByPropertiesBlock(createdByPropertiesBlock) { } Value::Value(const Value &other) : m_type(other.m_type), m_definingItem(other.m_definingItem), m_next(other.m_next ? other.m_next->clone() : ValuePtr()), m_createdByPropertiesBlock(other.m_createdByPropertiesBlock) { } Value::~Value() { } Item *Value::definingItem() const { return m_definingItem; } void Value::setDefiningItem(Item *item) { m_definingItem = item; } ValuePtr Value::next() const { return m_next; } void Value::setNext(const ValuePtr &next) { QBS_ASSERT(next.get() != this, return); QBS_CHECK(type() != VariantValueType); m_next = next; } JSSourceValue::JSSourceValue(bool createdByPropertiesBlock) : Value(JSSourceValueType, createdByPropertiesBlock) , m_line(-1) , m_column(-1) { } JSSourceValue::JSSourceValue(const JSSourceValue &other) : Value(other) { m_sourceCode = other.m_sourceCode; m_line = other.m_line; m_column = other.m_column; m_file = other.m_file; m_flags = other.m_flags; m_baseValue = other.m_baseValue ? std::static_pointer_cast(other.m_baseValue->clone()) : JSSourceValuePtr(); m_alternatives.reserve(other.m_alternatives.size()); for (const Alternative &otherAlt : other.m_alternatives) m_alternatives.push_back(otherAlt.clone()); } JSSourceValuePtr JSSourceValue::create(bool createdByPropertiesBlock) { return JSSourceValuePtr(new JSSourceValue(createdByPropertiesBlock)); } JSSourceValue::~JSSourceValue() { } ValuePtr JSSourceValue::clone() const { return JSSourceValuePtr(new JSSourceValue(*this)); } QString JSSourceValue::sourceCodeForEvaluation() const { if (!hasFunctionForm()) return m_sourceCode.toString(); // rewrite blocks to be able to use return statements in property assignments static const QString prefix = QStringLiteral("(function()"); static const QString suffix = QStringLiteral(")()"); return prefix + m_sourceCode.toString() + suffix; } void JSSourceValue::setLocation(int line, int column) { m_line = line; m_column = column; } CodeLocation JSSourceValue::location() const { return CodeLocation(m_file->filePath(), m_line, m_column); } void JSSourceValue::setHasFunctionForm(bool b) { if (b) m_flags |= HasFunctionForm; else m_flags &= ~HasFunctionForm; } void JSSourceValue::clearAlternatives() { m_alternatives.clear(); } void JSSourceValue::setDefiningItem(Item *item) { Value::setDefiningItem(item); for (const JSSourceValue::Alternative &a : m_alternatives) a.value->setDefiningItem(item); } ItemValue::ItemValue(Item *item, bool createdByPropertiesBlock) : Value(ItemValueType, createdByPropertiesBlock) , m_item(item) { QBS_CHECK(m_item); } ItemValuePtr ItemValue::create(Item *item, bool createdByPropertiesBlock) { return ItemValuePtr(new ItemValue(item, createdByPropertiesBlock)); } ValuePtr ItemValue::clone() const { return create(m_item->clone(), createdByPropertiesBlock()); } VariantValue::VariantValue(const QVariant &v) : Value(VariantValueType, false) , m_value(v) { } VariantValuePtr VariantValue::create(const QVariant &v) { if (!v.isValid()) return invalidValue(); if (static_cast(v.type()) == QMetaType::Bool) return v.toBool() ? VariantValue::trueValue() : VariantValue::falseValue(); return VariantValuePtr(new VariantValue(v)); } ValuePtr VariantValue::clone() const { return VariantValuePtr(new VariantValue(*this)); } const VariantValuePtr &VariantValue::falseValue() { static const VariantValuePtr v = VariantValuePtr(new VariantValue(false)); return v; } const VariantValuePtr &VariantValue::trueValue() { static const VariantValuePtr v = VariantValuePtr(new VariantValue(true)); return v; } const VariantValuePtr &VariantValue::invalidValue() { static const VariantValuePtr v = VariantValuePtr(new VariantValue(QVariant())); return v; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/language/value.h000066400000000000000000000166001347155106100212010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_VALUE_H #define QBS_VALUE_H #include "forward_decls.h" #include #include #include namespace qbs { namespace Internal { class Item; class ValueHandler; class Value { public: enum Type { JSSourceValueType, ItemValueType, VariantValueType }; Value(Type t, bool createdByPropertiesBlock); Value(const Value &other); virtual ~Value(); Type type() const { return m_type; } virtual void apply(ValueHandler *) = 0; virtual ValuePtr clone() const = 0; virtual CodeLocation location() const { return {}; } Item *definingItem() const; virtual void setDefiningItem(Item *item); ValuePtr next() const; void setNext(const ValuePtr &next); bool createdByPropertiesBlock() const { return m_createdByPropertiesBlock; } void setCreatedByPropertiesBlock(bool b) { m_createdByPropertiesBlock = b; } void clearCreatedByPropertiesBlock() { m_createdByPropertiesBlock = false; } private: Type m_type; Item *m_definingItem; ValuePtr m_next; bool m_createdByPropertiesBlock; }; class ValueHandler { public: virtual void handle(JSSourceValue *value) = 0; virtual void handle(ItemValue *value) = 0; virtual void handle(VariantValue *value) = 0; }; class JSSourceValue : public Value { friend class ItemReaderASTVisitor; JSSourceValue(bool createdByPropertiesBlock); JSSourceValue(const JSSourceValue &other); enum Flag { NoFlags = 0x00, SourceUsesBase = 0x01, SourceUsesOuter = 0x02, SourceUsesOriginal = 0x04, HasFunctionForm = 0x08, ExclusiveListValue = 0x10, BuiltinDefaultValue = 0x20, }; Q_DECLARE_FLAGS(Flags, Flag) public: static JSSourceValuePtr QBS_AUTOTEST_EXPORT create(bool createdByPropertiesBlock = false); ~JSSourceValue(); void apply(ValueHandler *handler) override { handler->handle(this); } ValuePtr clone() const override; void setSourceCode(const QStringRef &sourceCode) { m_sourceCode = sourceCode; } const QStringRef &sourceCode() const { return m_sourceCode; } QString sourceCodeForEvaluation() const; void setLocation(int line, int column); int line() const { return m_line; } int column() const { return m_column; } CodeLocation location() const override; void setFile(const FileContextPtr &file) { m_file = file; } const FileContextPtr &file() const { return m_file; } void setSourceUsesBaseFlag() { m_flags |= SourceUsesBase; } bool sourceUsesBase() const { return m_flags.testFlag(SourceUsesBase); } bool sourceUsesOuter() const { return m_flags.testFlag(SourceUsesOuter); } bool sourceUsesOriginal() const { return m_flags.testFlag(SourceUsesOriginal); } bool hasFunctionForm() const { return m_flags.testFlag(HasFunctionForm); } void setHasFunctionForm(bool b); void setIsExclusiveListValue() { m_flags |= ExclusiveListValue; } bool isExclusiveListValue() { return m_flags.testFlag(ExclusiveListValue); } void setIsBuiltinDefaultValue() { m_flags |= BuiltinDefaultValue; } bool isBuiltinDefaultValue() const { return m_flags.testFlag(BuiltinDefaultValue); } const JSSourceValuePtr &baseValue() const { return m_baseValue; } void setBaseValue(const JSSourceValuePtr &v) { m_baseValue = v; } struct Alternative { struct PropertyData { PropertyData() = default; PropertyData(const QString &v, const CodeLocation &l) : value(v), location(l) {} QString value; CodeLocation location; }; Alternative() { } Alternative(const PropertyData &c, const PropertyData &o, const JSSourceValuePtr &v) : condition(c), overrideListProperties(o), value(v) {} Alternative clone() const { return Alternative(condition, overrideListProperties, std::static_pointer_cast(value->clone())); } PropertyData condition; PropertyData overrideListProperties; JSSourceValuePtr value; }; using AltProperty = Alternative::PropertyData; const std::vector &alternatives() const { return m_alternatives; } void addAlternative(const Alternative &alternative) { m_alternatives.push_back(alternative); } void clearAlternatives(); void setDefiningItem(Item *item) override; private: QStringRef m_sourceCode; int m_line; int m_column; FileContextPtr m_file; Flags m_flags; JSSourceValuePtr m_baseValue; std::vector m_alternatives; }; class ItemValue : public Value { ItemValue(Item *item, bool createdByPropertiesBlock); public: static ItemValuePtr create(Item *item, bool createdByPropertiesBlock = false); Item *item() const { return m_item; } void setItem(Item *item) { m_item = item; } private: void apply(ValueHandler *handler) override { handler->handle(this); } ValuePtr clone() const override; Item *m_item; }; class VariantValue : public Value { VariantValue(const QVariant &v); public: static VariantValuePtr create(const QVariant &v = QVariant()); void apply(ValueHandler *handler) override { handler->handle(this); } ValuePtr clone() const override; const QVariant &value() const { return m_value; } static const VariantValuePtr &falseValue(); static const VariantValuePtr &trueValue(); static const VariantValuePtr &invalidValue(); private: QVariant m_value; }; } // namespace Internal } // namespace qbs #endif // QBS_VALUE_H qbs-src-1.13.1/src/lib/corelib/logging/000077500000000000000000000000001347155106100175545ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/corelib/logging/categories.cpp000066400000000000000000000047311347155106100224120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "categories.h" namespace qbs { namespace Internal { Q_LOGGING_CATEGORY(lcBuildGraph, "qbs.buildgraph", QtCriticalMsg) Q_LOGGING_CATEGORY(lcDepScan, "qbs.depscan", QtCriticalMsg) Q_LOGGING_CATEGORY(lcExec, "qbs.exec", QtCriticalMsg) Q_LOGGING_CATEGORY(lcMocScan, "qbs.mocscan", QtCriticalMsg) Q_LOGGING_CATEGORY(lcModuleLoader, "qbs.moduleloader", QtCriticalMsg) Q_LOGGING_CATEGORY(lcPluginManager, "qbs.pluginmanager", QtCriticalMsg) Q_LOGGING_CATEGORY(lcProjectResolver, "qbs.projectresolver", QtCriticalMsg) Q_LOGGING_CATEGORY(lcUpToDateCheck, "qbs.uptodate", QtCriticalMsg) } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/logging/categories.h000066400000000000000000000045451347155106100220620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CATEGORIES_H #define CATEGORIES_H #include namespace qbs { namespace Internal { Q_DECLARE_LOGGING_CATEGORY(lcBuildGraph) Q_DECLARE_LOGGING_CATEGORY(lcDepScan) Q_DECLARE_LOGGING_CATEGORY(lcExec) Q_DECLARE_LOGGING_CATEGORY(lcMocScan) Q_DECLARE_LOGGING_CATEGORY(lcModuleLoader) Q_DECLARE_LOGGING_CATEGORY(lcPluginManager) Q_DECLARE_LOGGING_CATEGORY(lcProjectResolver) Q_DECLARE_LOGGING_CATEGORY(lcUpToDateCheck) } // namespace Internal } // namespace qbs #endif // CATEGORIES_H qbs-src-1.13.1/src/lib/corelib/logging/ilogsink.cpp000066400000000000000000000071051347155106100221020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "ilogsink.h" #include #include #include namespace qbs { QString logLevelTag(LoggerLevel level) { if (level == LoggerInfo) return {}; QString str = logLevelName(level).toUpper(); if (!str.isEmpty()) str.append(QLatin1String(": ")); return str; } QString logLevelName(LoggerLevel level) { switch (level) { case qbs::LoggerError: return QStringLiteral("error"); case qbs::LoggerWarning: return QStringLiteral("warning"); case qbs::LoggerInfo: return QStringLiteral("info"); case qbs::LoggerDebug: return QStringLiteral("debug"); case qbs::LoggerTrace: return QStringLiteral("trace"); default: break; } return {}; } class ILogSink::ILogSinkPrivate { public: LoggerLevel logLevel; std::mutex mutex; }; ILogSink::ILogSink() : d(new ILogSinkPrivate) { d->logLevel = defaultLogLevel(); } ILogSink::~ILogSink() { delete d; } void ILogSink::setLogLevel(LoggerLevel level) { d->logLevel = level; } LoggerLevel ILogSink::logLevel() const { return d->logLevel; } void ILogSink::printWarning(const ErrorInfo &warning) { if (willPrint(LoggerWarning)) { d->mutex.lock(); doPrintWarning(warning); d->mutex.unlock(); } } void ILogSink::printMessage(LoggerLevel level, const QString &message, const QString &tag, bool force) { if (force || willPrint(level)) { d->mutex.lock(); doPrintMessage(level, message, tag); d->mutex.unlock(); } } void ILogSink::doPrintWarning(const ErrorInfo &warning) { doPrintMessage(LoggerWarning, warning.toString(), QString()); } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/logging/ilogsink.h000066400000000000000000000060741347155106100215530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ILOGSINK_H #define QBS_ILOGSINK_H #include "../tools/qbs_export.h" #include namespace qbs { class ErrorInfo; enum LoggerLevel { LoggerMinLevel, LoggerError = LoggerMinLevel, LoggerWarning, LoggerInfo, LoggerDebug, LoggerTrace, LoggerMaxLevel = LoggerTrace }; inline LoggerLevel defaultLogLevel() { return LoggerInfo; } QBS_EXPORT QString logLevelTag(LoggerLevel level); QBS_EXPORT QString logLevelName(LoggerLevel level); class QBS_EXPORT ILogSink { Q_DISABLE_COPY(ILogSink) public: ILogSink(); virtual ~ILogSink(); void setLogLevel(LoggerLevel level); LoggerLevel logLevel() const; bool willPrint(LoggerLevel level) const { return level <= logLevel(); } void printWarning(const ErrorInfo &warning); void printMessage(LoggerLevel level, const QString &message, const QString &tag = QString(), bool force = false); private: virtual void doPrintWarning(const ErrorInfo &warning); virtual void doPrintMessage(LoggerLevel level, const QString &message, const QString &tag) = 0; class ILogSinkPrivate; ILogSinkPrivate * const d; }; } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/logging/logger.cpp000066400000000000000000000132711347155106100215430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #if defined(_MSC_VER) && _MSC_VER > 0 #define _CRT_SECURE_NO_WARNINGS #endif #include "logger.h" #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { LogWriter::LogWriter(ILogSink *logSink, LoggerLevel level, bool force) : m_logSink(logSink), m_level(level), m_force(force) {} LogWriter::LogWriter(const LogWriter &other) : m_logSink(other.m_logSink) , m_level(other.m_level) , m_message(other.m_message) , m_tag(other.m_tag) , m_force(other.m_force) { other.m_message.clear(); } LogWriter::~LogWriter() { if (!m_message.isEmpty()) m_logSink->printMessage(m_level, m_message, m_tag, m_force); } const LogWriter &LogWriter::operator=(const LogWriter &other) { m_logSink = other.m_logSink; m_level = other.m_level; m_message = other.m_message; m_tag = other.m_tag; m_force = other.m_force; other.m_message.clear(); return *this; } void LogWriter::write(char c) { write(QLatin1Char(c)); } void LogWriter::write(const char *str) { write(QLatin1String(str)); } void LogWriter::write(const QChar &c) { if (m_force || m_logSink->logLevel() >= m_level) m_message.append(c); } void LogWriter::write(const QString &message) { if (m_force || m_logSink->logLevel() >= m_level) m_message += message; } void LogWriter::setMessageTag(const QString &tag) { m_tag = tag; } LogWriter operator<<(LogWriter w, const char *str) { w.write(str); return w; } LogWriter operator<<(LogWriter w, const QByteArray &byteArray) { w.write(byteArray.data()); return w; } LogWriter operator<<(LogWriter w, const QString &str) { w.write(str); return w; } LogWriter operator<<(LogWriter w, const QStringList &strList) { w.write('['); for (int i = 0; i < strList.size(); ++i) { w.write(strList.at(i)); if (i != strList.size() - 1) w.write(QStringLiteral(", ")); } w.write(']'); return w; } LogWriter operator<<(LogWriter w, const Internal::Set &strSet) { bool firstLoop = true; w.write('('); for (const QString &str : strSet) { if (firstLoop) firstLoop = false; else w.write(QStringLiteral(", ")); w.write(str); } w.write(')'); return w; } LogWriter operator<<(LogWriter w, const QVariant &variant) { QString str = QLatin1String(variant.typeName()) + QLatin1Char('('); if (variant.type() == QVariant::List) { bool firstLoop = true; for (const QVariant &item : variant.toList()) { str += item.toString(); if (firstLoop) firstLoop = false; else str += QLatin1String(", "); } } else { str += variant.toString(); } str += QLatin1Char(')'); w.write(str); return w; } LogWriter operator<<(LogWriter w, int n) { return w << QString::number(n); } LogWriter operator<<(LogWriter w, qint64 n) { return w << QString::number(n); } LogWriter operator<<(LogWriter w, bool b) { return w << QString::fromLatin1(b ? "true" : "false"); } LogWriter operator<<(LogWriter w, const MessageTag &tag) { w.setMessageTag(tag.tag()); return w; } Logger::Logger(ILogSink *logger) : m_logSink(logger) { } bool Logger::debugEnabled() const { return m_logSink->willPrint(LoggerDebug); } bool Logger::traceEnabled() const { return m_logSink->willPrint(LoggerTrace); } void Logger::printWarning(const ErrorInfo &warning) { if (m_storeWarnings) m_warnings.push_back(warning); logSink()->printWarning(warning); } LogWriter Logger::qbsLog(LoggerLevel level, bool force) const { return LogWriter(m_logSink, level, force); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/logging/logger.h000066400000000000000000000112471347155106100212110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LOGGER_H #define QBS_LOGGER_H #include "ilogsink.h" #include #include #include #include #include QT_BEGIN_NAMESPACE class QVariant; QT_END_NAMESPACE namespace qbs { namespace Internal { template class Set; // Note that while these classes are not part of the API, we export some stuff for use by // our command line tools for the sake of a uniform logging approach. class QBS_EXPORT LogWriter { public: LogWriter(ILogSink *logSink, LoggerLevel level, bool force = false); // log writer has move semantics and the last instance of // a << chain prints the accumulated data LogWriter(const LogWriter &other); ~LogWriter(); const LogWriter &operator=(const LogWriter &other); void write(char c); void write(const char *str); void write(const QChar &c); void write(const QString &message); void setMessageTag(const QString &tag); private: ILogSink *m_logSink; LoggerLevel m_level; mutable QString m_message; QString m_tag; bool m_force; }; class QBS_EXPORT MessageTag { public: explicit MessageTag(const QString &tag) : m_tag(tag) {} const QString &tag() const { return m_tag; } private: QString m_tag; }; QBS_EXPORT LogWriter operator<<(LogWriter w, const char *str); QBS_EXPORT LogWriter operator<<(LogWriter w, const QByteArray &byteArray); QBS_EXPORT LogWriter operator<<(LogWriter w, const QString &str); QBS_EXPORT LogWriter operator<<(LogWriter w, const QStringList &strList); QBS_EXPORT LogWriter operator<<(LogWriter w, const Internal::Set &strSet); QBS_EXPORT LogWriter operator<<(LogWriter w, const QVariant &variant); QBS_EXPORT LogWriter operator<<(LogWriter w, int n); QBS_EXPORT LogWriter operator<<(LogWriter w, qint64 n); QBS_EXPORT LogWriter operator<<(LogWriter w, bool b); QBS_EXPORT LogWriter operator<<(LogWriter w, const MessageTag &tag); class QBS_EXPORT Logger { public: Logger(ILogSink *logSink = 0); ILogSink *logSink() const { return m_logSink; } bool debugEnabled() const; bool traceEnabled() const; void printWarning(const ErrorInfo &warning); QList warnings() const { return m_warnings; } void clearWarnings() { m_warnings.clear(); } void storeWarnings() { m_storeWarnings = true; } LogWriter qbsLog(LoggerLevel level, bool force = false) const; LogWriter qbsWarning() const { return qbsLog(LoggerWarning); } LogWriter qbsInfo() const { return qbsLog(LoggerInfo); } LogWriter qbsDebug() const { return qbsLog(LoggerDebug); } LogWriter qbsTrace() const { return qbsLog(LoggerTrace); } private: ILogSink *m_logSink; QList m_warnings; bool m_storeWarnings = false; }; } // namespace Internal } // namespace qbs #endif // QBS_LOGGER_H qbs-src-1.13.1/src/lib/corelib/logging/logging.pri000066400000000000000000000006221347155106100217160ustar00rootroot00000000000000include(../../../install_prefix.pri) HEADERS += \ $$PWD/categories.h \ $$PWD/logger.h \ $$PWD/translator.h \ $$PWD/ilogsink.h SOURCES += \ $$PWD/categories.cpp \ $$PWD/logger.cpp \ $$PWD/ilogsink.cpp !qbs_no_dev_install { logging_headers.files = $$PWD/ilogsink.h logging_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/logging INSTALLS += logging_headers } qbs-src-1.13.1/src/lib/corelib/logging/translator.h000066400000000000000000000043051347155106100221200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TRANSLATOR_H #define QBS_TRANSLATOR_H #include #include namespace qbs { namespace Internal { class QBS_EXPORT Tr // Name intended to be short. Exported for use by command line tools. { Q_DECLARE_TR_FUNCTIONS(Qbs) }; } // namespace Internal } // namespace qbs #endif // QBS_TRANSLATOR_H qbs-src-1.13.1/src/lib/corelib/parser/000077500000000000000000000000001347155106100174225ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/corelib/parser/parser.pri000066400000000000000000000010251347155106100214300ustar00rootroot00000000000000HEADERS += \ $$PWD/qmljsast_p.h \ $$PWD/qmljsastfwd_p.h \ $$PWD/qmljsastvisitor_p.h \ $$PWD/qmljsengine_p.h \ $$PWD/qmljsgrammar_p.h \ $$PWD/qmljslexer_p.h \ $$PWD/qmljsmemorypool_p.h \ $$PWD/qmljsparser_p.h \ $$PWD/qmljsglobal_p.h \ $$PWD/qmlerror.h \ $$PWD/qmljskeywords_p.h \ SOURCES += \ $$PWD/qmljsast.cpp \ $$PWD/qmljsastvisitor.cpp \ $$PWD/qmljsengine_p.cpp \ $$PWD/qmljsgrammar.cpp \ $$PWD/qmljslexer.cpp \ $$PWD/qmljsparser.cpp \ $$PWD/qmlerror.cpp \ qbs-src-1.13.1/src/lib/corelib/parser/qmlerror.cpp000066400000000000000000000162431347155106100217770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qmlerror.h" #include #include #include #include namespace QbsQmlJS { /*! \class QmlError \since 5.0 \inmodule QtQml \brief The QmlError class encapsulates a QML error. QmlError includes a textual description of the error, as well as location information (the file, line, and column). The toString() method creates a single-line, human-readable string containing all of this information, for example: \code file:///home/user/test.qml:7:8: Invalid property assignment: double expected \endcode You can use qDebug() or qWarning() to output errors to the console. This method will attempt to open the file indicated by the error and include additional contextual information. \code file:///home/user/test.qml:7:8: Invalid property assignment: double expected y: "hello" ^ \endcode Note that the QtQuick 1 version is named QDeclarativeError \sa QQuickView::errors(), QmlComponent::errors() */ class QmlErrorPrivate { public: QmlErrorPrivate(); QUrl url; QString description; int line; int column; }; QmlErrorPrivate::QmlErrorPrivate() : line(-1), column(-1) { } /*! Creates an empty error object. */ QmlError::QmlError() : d(nullptr) { } /*! Creates a copy of \a other. */ QmlError::QmlError(const QmlError &other) : d(nullptr) { *this = other; } /*! Assigns \a other to this error object. */ QmlError &QmlError::operator=(const QmlError &other) { if (!other.d) { delete d; d = nullptr; } else { if (!d) d = new QmlErrorPrivate; d->url = other.d->url; d->description = other.d->description; d->line = other.d->line; d->column = other.d->column; } return *this; } /*! \internal */ QmlError::~QmlError() { delete d; d = nullptr; } /*! Returns true if this error is valid, otherwise false. */ bool QmlError::isValid() const { return d != nullptr; } /*! Returns the url for the file that caused this error. */ QUrl QmlError::url() const { if (d) return d->url; else return {}; } /*! Sets the \a url for the file that caused this error. */ void QmlError::setUrl(const QUrl &url) { if (!d) d = new QmlErrorPrivate; d->url = url; } /*! Returns the error description. */ QString QmlError::description() const { if (d) return d->description; else return {}; } /*! Sets the error \a description. */ void QmlError::setDescription(const QString &description) { if (!d) d = new QmlErrorPrivate; d->description = description; } /*! Returns the error line number. */ int QmlError::line() const { if (d) return d->line; else return -1; } /*! Sets the error \a line number. */ void QmlError::setLine(int line) { if (!d) d = new QmlErrorPrivate; d->line = line; } /*! Returns the error column number. */ int QmlError::column() const { if (d) return d->column; else return -1; } /*! Sets the error \a column number. */ void QmlError::setColumn(int column) { if (!d) d = new QmlErrorPrivate; d->column = column; } /*! Returns the error as a human readable string. */ QString QmlError::toString() const { QString rv; if (url().isEmpty()) { rv = QStringLiteral(""); } else if (line() != -1) { rv = url().toString() + QLatin1Char(':') + QString::number(line()); if (column() != -1) rv += QLatin1Char(':') + QString::number(column()); } else { rv = url().toString(); } rv += QLatin1String(": ") + description(); return rv; } } // namespace QbsQmlJS QT_BEGIN_NAMESPACE using namespace QbsQmlJS; /*! \relates QmlError \fn QDebug operator<<(QDebug debug, const QmlError &error) Outputs a human readable version of \a error to \a debug. */ QDebug operator<<(QDebug debug, const QmlError &error) { debug << qPrintable(error.toString()); QUrl url = error.url(); if (error.line() > 0 && url.scheme() == QLatin1String("file")) { QString file = url.toLocalFile(); QFile f(file); if (f.open(QIODevice::ReadOnly)) { QByteArray data = f.readAll(); QTextStream stream(data, QIODevice::ReadOnly); #ifndef QT_NO_TEXTCODEC stream.setCodec("UTF-8"); #endif const QString code = stream.readAll(); const QStringList lines = code.split(QLatin1Char('\n')); if (lines.size() >= error.line()) { const QString &line = lines.at(error.line() - 1); debug << "\n " << qPrintable(line); if (error.column() > 0) { int column = std::max(0, error.column() - 1); column = std::min(column, line.length()); QByteArray ind; ind.reserve(column); for (int i = 0; i < column; ++i) { const QChar ch = line.at(i); if (ch.isSpace()) ind.append(ch.unicode()); else ind.append(' '); } ind.append('^'); debug << "\n " << ind.constData(); } } } } return debug; } QT_END_NAMESPACE qbs-src-1.13.1/src/lib/corelib/parser/qmlerror.h000066400000000000000000000052631347155106100214440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QQMLERROR_H #define QQMLERROR_H #include #include QT_BEGIN_NAMESPACE class QDebug; QT_END_NAMESPACE namespace QbsQmlJS { class QmlErrorPrivate; class QmlError { public: QmlError(); QmlError(const QmlError &); QmlError &operator=(const QmlError &); ~QmlError(); bool isValid() const; QUrl url() const; void setUrl(const QUrl &); QString description() const; void setDescription(const QString &); int line() const; void setLine(int); int column() const; void setColumn(int); QString toString() const; private: QmlErrorPrivate *d; }; } // namespace QbsQmlJS QT_BEGIN_NAMESPACE QDebug operator<<(QDebug debug, const QbsQmlJS::QmlError &error); Q_DECLARE_TYPEINFO(QbsQmlJS::QmlError, Q_MOVABLE_TYPE); QT_END_NAMESPACE #endif // QQMLERROR_H qbs-src-1.13.1/src/lib/corelib/parser/qmljs.g000066400000000000000000002434621347155106100207330ustar00rootroot00000000000000----------------------------------------------------------------------------- -- -- Copyright (C) 2016 The Qt Company Ltd. -- Contact: https://www.qt.io/licensing/ -- -- This file is part of Qbs. -- -- $QT_BEGIN_LICENSE:LGPL$ -- Commercial License Usage -- Licensees holding valid commercial Qt licenses may use this file in -- accordance with the commercial license agreement provided with the -- Software or, alternatively, in accordance with the terms contained in -- a written agreement between you and The Qt Company. For licensing terms -- and conditions see https://www.qt.io/terms-conditions. For further -- information use the contact form at https://www.qt.io/contact-us. -- -- GNU Lesser General Public License Usage -- Alternatively, this file may be used under the terms of the GNU Lesser -- General Public License version 3 as published by the Free Software -- Foundation and appearing in the file LICENSE.LGPL3 included in the -- packaging of this file. Please review the following information to -- ensure the GNU Lesser General Public License version 3 requirements -- will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -- -- GNU General Public License Usage -- Alternatively, this file may be used under the terms of the GNU -- General Public License version 2.0 or (at your option) the GNU General -- Public license version 3 or any later version approved by the KDE Free -- Qt Foundation. The licenses are as published by the Free Software -- Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -- included in the packaging of this file. Please review the following -- information to ensure the GNU General Public License requirements will -- be met: https://www.gnu.org/licenses/gpl-2.0.html and -- https://www.gnu.org/licenses/gpl-3.0.html. -- -- $QT_END_LICENSE$ -- ----------------------------------------------------------------------------- %parser QmlJSGrammar %decl qmljsparser_p.h %impl qdeclarativejsparser.cpp %expect 2 %expect-rr 2 %token T_AND "&" T_AND_AND "&&" T_AND_EQ "&=" %token T_BREAK "break" T_CASE "case" T_CATCH "catch" %token T_COLON ":" T_COMMA "," T_CONTINUE "continue" %token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/" %token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "." %token T_ELSE "else" T_EQ "=" T_EQ_EQ "==" %token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for" %token T_FUNCTION "function" T_GE ">=" T_GT ">" %token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>" %token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if" %token T_IN "in" T_INSTANCEOF "instanceof" T_LBRACE "{" %token T_LBRACKET "[" T_LE "<=" T_LPAREN "(" %token T_LT "<" T_LT_LT "<<" T_LT_LT_EQ "<<=" %token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--" %token T_NEW "new" T_NOT "!" T_NOT_EQ "!=" %token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|" %token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+" %token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?" %token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%" %token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")" %token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*" %token T_STAR_EQ "*=" T_STRING_LITERAL "string literal" %token T_PROPERTY "property" T_SIGNAL "signal" T_READONLY "readonly" %token T_SWITCH "switch" T_THIS "this" T_THROW "throw" %token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof" %token T_VAR "var" T_VOID "void" T_WHILE "while" %token T_WITH "with" T_XOR "^" T_XOR_EQ "^=" %token T_NULL "null" T_TRUE "true" T_FALSE "false" %token T_CONST "const" %token T_DEBUGGER "debugger" %token T_RESERVED_WORD "reserved word" %token T_MULTILINE_STRING_LITERAL "multiline string literal" %token T_COMMENT "comment" --- context keywords. %token T_PUBLIC "public" %token T_IMPORT "import" %token T_AS "as" %token T_ON "on" %token T_ERROR --- feed tokens %token T_FEED_UI_PROGRAM %token T_FEED_UI_OBJECT_MEMBER %token T_FEED_JS_STATEMENT %token T_FEED_JS_EXPRESSION %token T_FEED_JS_SOURCE_ELEMENT %token T_FEED_JS_PROGRAM %nonassoc SHIFT_THERE %nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY %nonassoc REDUCE_HERE %start TopLevel /./**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include "qmljsengine_p.h" #include "qmljslexer_p.h" #include "qmljsast_p.h" #include "qmljsmemorypool_p.h" ./ /:/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMLJSPARSER_P_H #define QMLJSPARSER_P_H #include "qmljsglobal_p.h" #include "qmljsgrammar_p.h" #include "qmljsast_p.h" #include "qmljsengine_p.h" #include #include QT_QML_BEGIN_NAMESPACE namespace QmlJS { class Engine; class QML_PARSER_EXPORT Parser: protected $table { public: union Value { int ival; double dval; AST::ArgumentList *ArgumentList; AST::CaseBlock *CaseBlock; AST::CaseClause *CaseClause; AST::CaseClauses *CaseClauses; AST::Catch *Catch; AST::DefaultClause *DefaultClause; AST::ElementList *ElementList; AST::Elision *Elision; AST::ExpressionNode *Expression; AST::Finally *Finally; AST::FormalParameterList *FormalParameterList; AST::FunctionBody *FunctionBody; AST::FunctionDeclaration *FunctionDeclaration; AST::Node *Node; AST::PropertyName *PropertyName; AST::PropertyNameAndValueList *PropertyNameAndValueList; AST::SourceElement *SourceElement; AST::SourceElements *SourceElements; AST::Statement *Statement; AST::StatementList *StatementList; AST::Block *Block; AST::VariableDeclaration *VariableDeclaration; AST::VariableDeclarationList *VariableDeclarationList; AST::UiProgram *UiProgram; AST::UiImportList *UiImportList; AST::UiImport *UiImport; AST::UiParameterList *UiParameterList; AST::UiPublicMember *UiPublicMember; AST::UiObjectDefinition *UiObjectDefinition; AST::UiObjectInitializer *UiObjectInitializer; AST::UiObjectBinding *UiObjectBinding; AST::UiScriptBinding *UiScriptBinding; AST::UiArrayBinding *UiArrayBinding; AST::UiObjectMember *UiObjectMember; AST::UiObjectMemberList *UiObjectMemberList; AST::UiArrayMemberList *UiArrayMemberList; AST::UiQualifiedId *UiQualifiedId; }; public: Parser(Engine *engine); ~Parser(); // parse a UI program bool parse() { return parse(T_FEED_UI_PROGRAM); } bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); } bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); } bool parseProgram() { return parse(T_FEED_JS_PROGRAM); } AST::UiProgram *ast() const { return AST::cast(program); } AST::Statement *statement() const { if (! program) return 0; return program->statementCast(); } AST::ExpressionNode *expression() const { if (! program) return 0; return program->expressionCast(); } AST::UiObjectMember *uiObjectMember() const { if (! program) return 0; return program->uiObjectMemberCast(); } AST::Node *rootNode() const { return program; } QList diagnosticMessages() const { return diagnostic_messages; } inline DiagnosticMessage diagnosticMessage() const { foreach (const DiagnosticMessage &d, diagnostic_messages) { if (d.kind != DiagnosticMessage::Warning) return d; } return DiagnosticMessage(); } inline QString errorMessage() const { return diagnosticMessage().message; } inline int errorLineNumber() const { return diagnosticMessage().loc.startLine; } inline int errorColumnNumber() const { return diagnosticMessage().loc.startColumn; } protected: bool parse(int startToken); void reallocateStack(); inline Value &sym(int index) { return sym_stack [tos + index - 1]; } inline QStringRef &stringRef(int index) { return string_stack [tos + index - 1]; } inline AST::SourceLocation &loc(int index) { return location_stack [tos + index - 1]; } AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); protected: Engine *driver; MemoryPool *pool; int tos; int stack_size; Value *sym_stack; int *state_stack; AST::SourceLocation *location_stack; QStringRef *string_stack; AST::Node *program; // error recovery enum { TOKEN_BUFFER_SIZE = 3 }; struct SavedToken { int token; double dval; AST::SourceLocation loc; QStringRef spell; }; double yylval; QStringRef yytokenspell; AST::SourceLocation yylloc; AST::SourceLocation yyprevlloc; SavedToken token_buffer[TOKEN_BUFFER_SIZE]; SavedToken *first_token; SavedToken *last_token; QList diagnostic_messages; }; } // end of namespace QmlJS :/ /. #include "qmljsparser_p.h" #include // // This file is automatically generated from qmljs.g. // Changes will be lost. // using namespace QmlJS; QT_QML_BEGIN_NAMESPACE void Parser::reallocateStack() { if (! stack_size) stack_size = 128; else stack_size <<= 1; sym_stack = reinterpret_cast (realloc(sym_stack, stack_size * sizeof(Value))); state_stack = reinterpret_cast (realloc(state_stack, stack_size * sizeof(int))); location_stack = reinterpret_cast (realloc(location_stack, stack_size * sizeof(AST::SourceLocation))); string_stack = reinterpret_cast (realloc(string_stack, stack_size * sizeof(QStringRef))); } Parser::Parser(Engine *engine): driver(engine), pool(engine->pool()), tos(0), stack_size(0), sym_stack(0), state_stack(0), location_stack(0), string_stack(0), first_token(0), last_token(0) { } Parser::~Parser() { if (stack_size) { free(sym_stack); free(state_stack); free(location_stack); free(string_stack); } } static inline AST::SourceLocation location(Lexer *lexer) { AST::SourceLocation loc; loc.offset = lexer->tokenOffset(); loc.length = lexer->tokenLength(); loc.startLine = lexer->tokenStartLine(); loc.startColumn = lexer->tokenStartColumn(); return loc; } AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) { QVarLengthArray nameIds; QVarLengthArray locations; AST::ExpressionNode *it = expr; while (AST::FieldMemberExpression *m = AST::cast(it)) { nameIds.append(m->name); locations.append(m->identifierToken); it = m->base; } if (AST::IdentifierExpression *idExpr = AST::cast(it)) { AST::UiQualifiedId *q = new (pool) AST::UiQualifiedId(idExpr->name); q->identifierToken = idExpr->identifierToken; AST::UiQualifiedId *currentId = q; for (int i = nameIds.size() - 1; i != -1; --i) { currentId = new (pool) AST::UiQualifiedId(currentId, nameIds[i]); currentId->identifierToken = locations[i]; } return currentId->finish(); } return 0; } bool Parser::parse(int startToken) { Lexer *lexer = driver->lexer(); bool hadErrors = false; int yytoken = -1; int action = 0; token_buffer[0].token = startToken; first_token = &token_buffer[0]; last_token = &token_buffer[1]; tos = -1; program = 0; do { if (++tos == stack_size) reallocateStack(); state_stack[tos] = action; _Lcheck_token: if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { yyprevlloc = yylloc; if (first_token == last_token) { yytoken = lexer->lex(); yylval = lexer->tokenValue(); yytokenspell = lexer->tokenSpell(); yylloc = location(lexer); } else { yytoken = first_token->token; yylval = first_token->dval; yytokenspell = first_token->spell; yylloc = first_token->loc; ++first_token; } } action = t_action(action, yytoken); if (action > 0) { if (action != ACCEPT_STATE) { yytoken = -1; sym(1).dval = yylval; stringRef(1) = yytokenspell; loc(1) = yylloc; } else { --tos; return ! hadErrors; } } else if (action < 0) { const int r = -action - 1; tos -= rhs[r]; switch (r) { ./ -------------------------------------------------------------------------------------------------------- -- Declarative UI -------------------------------------------------------------------------------------------------------- TopLevel: T_FEED_UI_PROGRAM UiProgram ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ TopLevel: T_FEED_JS_STATEMENT Statement ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ TopLevel: T_FEED_JS_EXPRESSION Expression ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ TopLevel: T_FEED_JS_SOURCE_ELEMENT SourceElement ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ TopLevel: T_FEED_JS_PROGRAM Program ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ UiProgram: UiImportListOpt UiRootMember ; /. case $rule_number: { sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiImportList, sym(2).UiObjectMemberList->finish()); } break; ./ UiImportListOpt: Empty ; UiImportListOpt: UiImportList ; /. case $rule_number: { sym(1).Node = sym(1).UiImportList->finish(); } break; ./ UiImportList: UiImport ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImport); } break; ./ UiImportList: UiImportList UiImport ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImportList, sym(2).UiImport); } break; ./ ImportId: MemberExpression ; UiImport: UiImportHead T_AUTOMATIC_SEMICOLON ; UiImport: UiImportHead T_SEMICOLON ; /. case $rule_number: { sym(1).UiImport->semicolonToken = loc(2); } break; ./ UiImport: UiImportHead T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON ; UiImport: UiImportHead T_NUMERIC_LITERAL T_SEMICOLON ; /. case $rule_number: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->semicolonToken = loc(3); } break; ./ UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ; UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_SEMICOLON ; /. case $rule_number: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->asToken = loc(3); sym(1).UiImport->importIdToken = loc(4); sym(1).UiImport->importId = stringRef(4); sym(1).UiImport->semicolonToken = loc(5); } break; ./ UiImport: UiImportHead T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ; UiImport: UiImportHead T_AS JsIdentifier T_SEMICOLON ; /. case $rule_number: { sym(1).UiImport->asToken = loc(2); sym(1).UiImport->importIdToken = loc(3); sym(1).UiImport->importId = stringRef(3); sym(1).UiImport->semicolonToken = loc(4); } break; ./ UiImportHead: T_IMPORT ImportId ; /. case $rule_number: { AST::UiImport *node = 0; if (AST::StringLiteral *importIdLiteral = AST::cast(sym(2).Expression)) { node = new (pool) AST::UiImport(importIdLiteral->value); node->fileNameToken = loc(2); } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) { node = new (pool) AST::UiImport(qualifiedId); node->fileNameToken = loc(2); } sym(1).Node = node; if (node) { node->importToken = loc(1); } else { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), QLatin1String("Expected a qualified name id or a string literal"))); return false; // ### remove me } } break; ./ Empty: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ UiRootMember: UiObjectDefinition ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; ./ UiObjectMemberList: UiObjectMember ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; ./ UiObjectMemberList: UiObjectMemberList UiObjectMember ; /. case $rule_number: { AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList( sym(1).UiObjectMemberList, sym(2).UiObjectMember); sym(1).Node = node; } break; ./ UiArrayMemberList: UiObjectDefinition ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember); } break; ./ UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ; /. case $rule_number: { AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList( sym(1).UiArrayMemberList, sym(3).UiObjectMember); node->commaToken = loc(2); sym(1).Node = node; } break; ./ UiObjectInitializer: T_LBRACE T_RBRACE ; /. case $rule_number: { AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)0); node->lbraceToken = loc(1); node->rbraceToken = loc(2); sym(1).Node = node; } break; ./ UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ; /. case $rule_number: { AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish()); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; ./ UiObjectDefinition: UiQualifiedId UiObjectInitializer ; /. case $rule_number: { AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId, sym(2).UiObjectInitializer); sym(1).Node = node; } break; ./ UiObjectMember: UiObjectDefinition ; UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; /. case $rule_number: { AST::UiArrayBinding *node = new (pool) AST::UiArrayBinding( sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish()); node->colonToken = loc(2); node->lbracketToken = loc(3); node->rbracketToken = loc(5); sym(1).Node = node; } break; ./ UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ; /. case $rule_number: { AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); sym(1).Node = node; } break; ./ UiObjectMember: UiQualifiedId T_ON UiQualifiedId UiObjectInitializer ; /. case $rule_number: { AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); node->hasOnToken = true; sym(1).Node = node; } break; ./ UiScriptStatement: Block ; UiScriptStatement: EmptyStatement ; UiScriptStatement: ExpressionStatement ; UiScriptStatement: IfStatement ; UiScriptStatement: WithStatement ; UiScriptStatement: SwitchStatement ; UiScriptStatement: TryStatement ; UiObjectMember: UiQualifiedId T_COLON UiScriptStatement ; /. case $rule_number: { AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding( sym(1).UiQualifiedId, sym(3).Statement); node->colonToken = loc(2); sym(1).Node = node; } break; ./ UiPropertyType: T_VAR ; UiPropertyType: T_RESERVED_WORD ; UiPropertyType: T_IDENTIFIER ; UiParameterListOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ UiParameterListOpt: UiParameterList ; /. case $rule_number: { sym(1).Node = sym(1).UiParameterList->finish (); } break; ./ UiParameterList: UiPropertyType JsIdentifier ; /. case $rule_number: { AST::UiParameterList *node = new (pool) AST::UiParameterList(stringRef(1), stringRef(2)); node->propertyTypeToken = loc(1); node->identifierToken = loc(2); sym(1).Node = node; } break; ./ UiParameterList: UiParameterList T_COMMA UiPropertyType JsIdentifier ; /. case $rule_number: { AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, stringRef(3), stringRef(4)); node->commaToken = loc(2); node->identifierToken = loc(4); sym(1).Node = node; } break; ./ UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(2); node->parameters = sym(4).UiParameterList; node->semicolonToken = loc(6); sym(1).Node = node; } break; ./ UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_SEMICOLON ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); node->identifierToken = loc(6); node->semicolonToken = loc(7); sym(1).Node = node; } break; ./ UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_SEMICOLON ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->semicolonToken = loc(4); sym(1).Node = node; } break; ./ UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_SEMICOLON ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4)); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->semicolonToken = loc(5); sym(1).Node = node; } break; ./ UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3), sym(5).Statement); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->colonToken = loc(4); sym(1).Node = node; } break; ./ UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isReadonlyMember = true; node->readonlyToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); sym(1).Node = node; } break; ./ UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); sym(1).Node = node; } break; ./ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); node->identifierToken = loc(6); node->semicolonToken = loc(7); // insert a fake ';' before ':' AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6)); propertyName->identifierToken = loc(6); propertyName->next = 0; AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding( propertyName, sym(9).UiArrayMemberList->finish()); binding->colonToken = loc(7); binding->lbracketToken = loc(8); binding->rbracketToken = loc(10); node->binding = binding; sym(1).Node = node; } break; ./ UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON UiQualifiedId UiObjectInitializer ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->semicolonToken = loc(4); // insert a fake ';' before ':' AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3)); propertyName->identifierToken = loc(3); propertyName->next = 0; AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( propertyName, sym(5).UiQualifiedId, sym(6).UiObjectInitializer); binding->colonToken = loc(4); node->binding = binding; sym(1).Node = node; } break; ./ UiObjectMember: FunctionDeclaration ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; ./ UiObjectMember: VariableStatement ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; ./ JsIdentifier: T_IDENTIFIER; JsIdentifier: T_PROPERTY ; JsIdentifier: T_SIGNAL ; JsIdentifier: T_READONLY ; JsIdentifier: T_ON ; -------------------------------------------------------------------------------------------------------- -- Expressions -------------------------------------------------------------------------------------------------------- PrimaryExpression: T_THIS ; /. case $rule_number: { AST::ThisExpression *node = new (pool) AST::ThisExpression(); node->thisToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: JsIdentifier ; /. case $rule_number: { AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_NULL ; /. case $rule_number: { AST::NullExpression *node = new (pool) AST::NullExpression(); node->nullToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_TRUE ; /. case $rule_number: { AST::TrueLiteral *node = new (pool) AST::TrueLiteral(); node->trueToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_FALSE ; /. case $rule_number: { AST::FalseLiteral *node = new (pool) AST::FalseLiteral(); node->falseToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_NUMERIC_LITERAL ; /. case $rule_number: { AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval); node->literalToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_MULTILINE_STRING_LITERAL ; /.case $rule_number:./ PrimaryExpression: T_STRING_LITERAL ; /. case $rule_number: { AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1)); node->literalToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_DIVIDE_ ; /: #define J_SCRIPT_REGEXPLITERAL_RULE1 $rule_number :/ /. case $rule_number: { bool rx = lexer->scanRegExp(Lexer::NoPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); return false; // ### remove me } loc(1).length = lexer->tokenLength(); yylloc = loc(1); // adjust the location of the current token AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_DIVIDE_EQ ; /: #define J_SCRIPT_REGEXPLITERAL_RULE2 $rule_number :/ /. case $rule_number: { bool rx = lexer->scanRegExp(Lexer::EqualPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); return false; } loc(1).length = lexer->tokenLength(); yylloc = loc(1); // adjust the location of the current token AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACKET T_RBRACKET ; /. case $rule_number: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACKET Elision T_RBRACKET ; /. case $rule_number: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ; /. case $rule_number: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ; /. case $rule_number: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); node->commaToken = loc(3); node->rbracketToken = loc(4); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ; /. case $rule_number: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); node->commaToken = loc(3); node->rbracketToken = loc(5); sym(1).Node = node; } break; ./ -- PrimaryExpression: T_LBRACE T_RBRACE ; -- /. -- case $rule_number: { -- sym(1).Node = new (pool) AST::ObjectLiteral(); -- } break; -- ./ PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ; /. case $rule_number: { AST::ObjectLiteral *node = 0; if (sym(2).Node) node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); else node = new (pool) AST::ObjectLiteral(); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACE PropertyNameAndValueList T_COMMA T_RBRACE ; /. case $rule_number: { AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); node->lbraceToken = loc(1); node->rbraceToken = loc(4); sym(1).Node = node; } break; ./ PrimaryExpression: T_LPAREN Expression T_RPAREN ; /. case $rule_number: { AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; } break; ./ UiQualifiedId: MemberExpression ; /. case $rule_number: { if (AST::ArrayMemberExpression *mem = AST::cast(sym(1).Expression)) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, QLatin1String("Ignored annotation"))); sym(1).Expression = mem->base; } if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) { sym(1).UiQualifiedId = qualifiedId; } else { sym(1).UiQualifiedId = 0; diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), QLatin1String("Expected a qualified name id"))); return false; // ### recover } } break; ./ ElementList: AssignmentExpression ; /. case $rule_number: { sym(1).Node = new (pool) AST::ElementList((AST::Elision *) 0, sym(1).Expression); } break; ./ ElementList: Elision AssignmentExpression ; /. case $rule_number: { sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression); } break; ./ ElementList: ElementList T_COMMA AssignmentExpression ; /. case $rule_number: { AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; ./ ElementList: ElementList T_COMMA Elision AssignmentExpression ; /. case $rule_number: { AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; ./ Elision: T_COMMA ; /. case $rule_number: { AST::Elision *node = new (pool) AST::Elision(); node->commaToken = loc(1); sym(1).Node = node; } break; ./ Elision: Elision T_COMMA ; /. case $rule_number: { AST::Elision *node = new (pool) AST::Elision(sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; ./ PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ; /. case $rule_number: { AST::PropertyNameAndValueList *node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; ./ PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ; /. case $rule_number: { AST::PropertyNameAndValueList *node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; ./ PropertyName: T_IDENTIFIER %prec SHIFT_THERE ; /. case $rule_number: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; ./ PropertyName: T_SIGNAL ; /.case $rule_number:./ PropertyName: T_PROPERTY ; /. case $rule_number: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; ./ PropertyName: T_STRING_LITERAL ; /. case $rule_number: { AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; ./ PropertyName: T_NUMERIC_LITERAL ; /. case $rule_number: { AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; ./ PropertyName: ReservedIdentifier ; /. case $rule_number: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; ./ ReservedIdentifier: T_BREAK ; ReservedIdentifier: T_CASE ; ReservedIdentifier: T_CATCH ; ReservedIdentifier: T_CONTINUE ; ReservedIdentifier: T_DEFAULT ; ReservedIdentifier: T_DELETE ; ReservedIdentifier: T_DO ; ReservedIdentifier: T_ELSE ; ReservedIdentifier: T_FALSE ; ReservedIdentifier: T_FINALLY ; ReservedIdentifier: T_FOR ; ReservedIdentifier: T_FUNCTION ; ReservedIdentifier: T_IF ; ReservedIdentifier: T_IN ; ReservedIdentifier: T_INSTANCEOF ; ReservedIdentifier: T_NEW ; ReservedIdentifier: T_NULL ; ReservedIdentifier: T_RETURN ; ReservedIdentifier: T_SWITCH ; ReservedIdentifier: T_THIS ; ReservedIdentifier: T_THROW ; ReservedIdentifier: T_TRUE ; ReservedIdentifier: T_TRY ; ReservedIdentifier: T_TYPEOF ; ReservedIdentifier: T_VAR ; ReservedIdentifier: T_VOID ; ReservedIdentifier: T_WHILE ; ReservedIdentifier: T_CONST ; ReservedIdentifier: T_DEBUGGER ; ReservedIdentifier: T_RESERVED_WORD ; ReservedIdentifier: T_WITH ; PropertyIdentifier: JsIdentifier ; PropertyIdentifier: ReservedIdentifier ; MemberExpression: PrimaryExpression ; MemberExpression: FunctionExpression ; MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ; /. case $rule_number: { AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; ./ MemberExpression: MemberExpression T_DOT PropertyIdentifier ; /. case $rule_number: { AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; ./ MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; /. case $rule_number: { AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); node->rparenToken = loc(5); sym(1).Node = node; } break; ./ NewExpression: MemberExpression ; NewExpression: T_NEW NewExpression ; /. case $rule_number: { AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; ./ CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; /. case $rule_number: { AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ; /. case $rule_number: { AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ; /. case $rule_number: { AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; ./ CallExpression: CallExpression T_DOT PropertyIdentifier ; /. case $rule_number: { AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; ./ ArgumentListOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ ArgumentListOpt: ArgumentList ; /. case $rule_number: { sym(1).Node = sym(1).ArgumentList->finish(); } break; ./ ArgumentList: AssignmentExpression ; /. case $rule_number: { sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression); } break; ./ ArgumentList: ArgumentList T_COMMA AssignmentExpression ; /. case $rule_number: { AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; ./ LeftHandSideExpression: NewExpression ; LeftHandSideExpression: CallExpression ; PostfixExpression: LeftHandSideExpression ; PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ; /. case $rule_number: { AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; ./ PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ; /. case $rule_number: { AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; ./ UnaryExpression: PostfixExpression ; UnaryExpression: T_DELETE UnaryExpression ; /. case $rule_number: { AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_VOID UnaryExpression ; /. case $rule_number: { AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_TYPEOF UnaryExpression ; /. case $rule_number: { AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_PLUS_PLUS UnaryExpression ; /. case $rule_number: { AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_MINUS_MINUS UnaryExpression ; /. case $rule_number: { AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_PLUS UnaryExpression ; /. case $rule_number: { AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_MINUS UnaryExpression ; /. case $rule_number: { AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_TILDE UnaryExpression ; /. case $rule_number: { AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_NOT UnaryExpression ; /. case $rule_number: { AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; ./ MultiplicativeExpression: UnaryExpression ; MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ AdditiveExpression: MultiplicativeExpression ; AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ ShiftExpression: AdditiveExpression ; ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: ShiftExpression ; RelationalExpression: RelationalExpression T_LT ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: RelationalExpression T_GT ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: RelationalExpression T_LE ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: RelationalExpression T_GE ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: RelationalExpression T_IN ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpressionNotIn: ShiftExpression ; RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpression: RelationalExpression ; EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpressionNotIn: RelationalExpressionNotIn ; EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseANDExpression: EqualityExpression ; BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseANDExpressionNotIn: EqualityExpressionNotIn ; BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseXORExpression: BitwiseANDExpression ; BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ; BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseORExpression: BitwiseXORExpression ; BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ; BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ LogicalANDExpression: BitwiseORExpression ; LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ; LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ LogicalORExpression: LogicalANDExpression ; LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ LogicalORExpressionNotIn: LogicalANDExpressionNotIn ; LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ ConditionalExpression: LogicalORExpression ; ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ; /. case $rule_number: { AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; ./ ConditionalExpressionNotIn: LogicalORExpressionNotIn ; ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ; /. case $rule_number: { AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; ./ AssignmentExpression: ConditionalExpression ; AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ AssignmentExpressionNotIn: ConditionalExpressionNotIn ; AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ AssignmentOperator: T_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::Assign; } break; ./ AssignmentOperator: T_STAR_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceMul; } break; ./ AssignmentOperator: T_DIVIDE_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceDiv; } break; ./ AssignmentOperator: T_REMAINDER_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceMod; } break; ./ AssignmentOperator: T_PLUS_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceAdd; } break; ./ AssignmentOperator: T_MINUS_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceSub; } break; ./ AssignmentOperator: T_LT_LT_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceLeftShift; } break; ./ AssignmentOperator: T_GT_GT_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceRightShift; } break; ./ AssignmentOperator: T_GT_GT_GT_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceURightShift; } break; ./ AssignmentOperator: T_AND_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceAnd; } break; ./ AssignmentOperator: T_XOR_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceXor; } break; ./ AssignmentOperator: T_OR_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceOr; } break; ./ Expression: AssignmentExpression ; Expression: Expression T_COMMA AssignmentExpression ; /. case $rule_number: { AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; ./ ExpressionOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ ExpressionOpt: Expression ; ExpressionNotIn: AssignmentExpressionNotIn ; ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ; /. case $rule_number: { AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; ./ ExpressionNotInOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ ExpressionNotInOpt: ExpressionNotIn ; Statement: Block ; Statement: VariableStatement ; Statement: EmptyStatement ; Statement: ExpressionStatement ; Statement: IfStatement ; Statement: IterationStatement ; Statement: ContinueStatement ; Statement: BreakStatement ; Statement: ReturnStatement ; Statement: WithStatement ; Statement: LabelledStatement ; Statement: SwitchStatement ; Statement: ThrowStatement ; Statement: TryStatement ; Statement: DebuggerStatement ; Block: T_LBRACE StatementListOpt T_RBRACE ; /. case $rule_number: { AST::Block *node = new (pool) AST::Block(sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; ./ StatementList: Statement ; /. case $rule_number: { sym(1).Node = new (pool) AST::StatementList(sym(1).Statement); } break; ./ StatementList: StatementList Statement ; /. case $rule_number: { sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement); } break; ./ StatementListOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ StatementListOpt: StatementList ; /. case $rule_number: { sym(1).Node = sym(1).StatementList->finish (); } break; ./ VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ; /. case $rule_number: { AST::VariableStatement *node = new (pool) AST::VariableStatement( sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ VariableDeclarationKind: T_CONST ; /. case $rule_number: { sym(1).ival = T_CONST; } break; ./ VariableDeclarationKind: T_VAR ; /. case $rule_number: { sym(1).ival = T_VAR; } break; ./ VariableDeclarationList: VariableDeclaration ; /. case $rule_number: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; ./ VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ; /. case $rule_number: { AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList( sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; ./ VariableDeclarationListNotIn: VariableDeclarationNotIn ; /. case $rule_number: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; ./ VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ; /. case $rule_number: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; ./ VariableDeclaration: JsIdentifier InitialiserOpt ; /. case $rule_number: { AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; ./ VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ; /. case $rule_number: { AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; ./ Initialiser: T_EQ AssignmentExpression ; /. case $rule_number: { // ### TODO: AST for initializer sym(1) = sym(2); } break; ./ InitialiserOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ InitialiserOpt: Initialiser ; InitialiserNotIn: T_EQ AssignmentExpressionNotIn ; /. case $rule_number: { // ### TODO: AST for initializer sym(1) = sym(2); } break; ./ InitialiserNotInOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ InitialiserNotInOpt: InitialiserNotIn ; EmptyStatement: T_SEMICOLON ; /. case $rule_number: { AST::EmptyStatement *node = new (pool) AST::EmptyStatement(); node->semicolonToken = loc(1); sym(1).Node = node; } break; ./ ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ExpressionStatement: Expression T_SEMICOLON ; /. case $rule_number: { AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; ./ IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ; /. case $rule_number: { AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); node->elseToken = loc(6); sym(1).Node = node; } break; ./ IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ; /. case $rule_number: { AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ; /. case $rule_number: { AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); node->lparenToken = loc(4); node->rparenToken = loc(6); node->semicolonToken = loc(7); sym(1).Node = node; } break; ./ IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ; /. case $rule_number: { AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; /. case $rule_number: { AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->firstSemicolonToken = loc(4); node->secondSemicolonToken = loc(6); node->rparenToken = loc(8); sym(1).Node = node; } break; ./ IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; /. case $rule_number: { AST::LocalForStatement *node = new (pool) AST::LocalForStatement( sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->varToken = loc(3); node->firstSemicolonToken = loc(5); node->secondSemicolonToken = loc(7); node->rparenToken = loc(9); sym(1).Node = node; } break; ./ IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ; /. case $rule_number: { AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->inToken = loc(4); node->rparenToken = loc(6); sym(1).Node = node; } break; ./ IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ; /. case $rule_number: { AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement( sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->varToken = loc(3); node->inToken = loc(5); node->rparenToken = loc(7); sym(1).Node = node; } break; ./ ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ContinueStatement: T_CONTINUE T_SEMICOLON ; /. case $rule_number: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; ./ ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ; /. case $rule_number: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2)); node->continueToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon BreakStatement: T_BREAK T_SEMICOLON ; /. case $rule_number: { AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; ./ BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ; /. case $rule_number: { AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2)); node->breakToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ; /. case $rule_number: { AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ; /. case $rule_number: { AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ; /. case $rule_number: { AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ; /. case $rule_number: { AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; ./ CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ; /. case $rule_number: { AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; } break; ./ CaseClauses: CaseClause ; /. case $rule_number: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause); } break; ./ CaseClauses: CaseClauses CaseClause ; /. case $rule_number: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause); } break; ./ CaseClausesOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ CaseClausesOpt: CaseClauses ; /. case $rule_number: { sym(1).Node = sym(1).CaseClauses->finish (); } break; ./ CaseClause: T_CASE Expression T_COLON StatementListOpt ; /. case $rule_number: { AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; } break; ./ DefaultClause: T_DEFAULT T_COLON StatementListOpt ; /. case $rule_number: { AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; ./ LabelledStatement: T_SIGNAL T_COLON Statement ; /.case $rule_number:./ LabelledStatement: T_PROPERTY T_COLON Statement ; /. case $rule_number: { AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; ./ LabelledStatement: T_IDENTIFIER T_COLON Statement ; /. case $rule_number: { AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; ./ ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ThrowStatement: T_THROW Expression T_SEMICOLON ; /. case $rule_number: { AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ TryStatement: T_TRY Block Catch ; /. case $rule_number: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; ./ TryStatement: T_TRY Block Finally ; /. case $rule_number: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; ./ TryStatement: T_TRY Block Catch Finally ; /. case $rule_number: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; ./ Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ; /. case $rule_number: { AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); node->identifierToken = loc(3); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ Finally: T_FINALLY Block ; /. case $rule_number: { AST::Finally *node = new (pool) AST::Finally(sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; ./ DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon DebuggerStatement: T_DEBUGGER T_SEMICOLON ; /. case $rule_number: { AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement(); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; ./ FunctionDeclaration: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; /. case $rule_number: { AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); node->lparenToken = loc(3); node->rparenToken = loc(5); node->lbraceToken = loc(6); node->rbraceToken = loc(8); sym(1).Node = node; } break; ./ FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; /. case $rule_number: { AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); if (! stringRef(2).isNull()) node->identifierToken = loc(2); node->lparenToken = loc(3); node->rparenToken = loc(5); node->lbraceToken = loc(6); node->rbraceToken = loc(8); sym(1).Node = node; } break; ./ FormalParameterList: JsIdentifier ; /. case $rule_number: { AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; ./ FormalParameterList: FormalParameterList T_COMMA JsIdentifier ; /. case $rule_number: { AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3)); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; ./ FormalParameterListOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ FormalParameterListOpt: FormalParameterList ; /. case $rule_number: { sym(1).Node = sym(1).FormalParameterList->finish (); } break; ./ FunctionBodyOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ FunctionBodyOpt: FunctionBody ; FunctionBody: SourceElements ; /. case $rule_number: { sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ()); } break; ./ Program: Empty ; Program: SourceElements ; /. case $rule_number: { sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ()); } break; ./ SourceElements: SourceElement ; /. case $rule_number: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement); } break; ./ SourceElements: SourceElements SourceElement ; /. case $rule_number: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement); } break; ./ SourceElement: Statement ; /. case $rule_number: { sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement); } break; ./ SourceElement: FunctionDeclaration ; /. case $rule_number: { sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration); } break; ./ IdentifierOpt: ; /. case $rule_number: { stringRef(1) = QStringRef(); } break; ./ IdentifierOpt: JsIdentifier ; PropertyNameAndValueListOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ PropertyNameAndValueListOpt: PropertyNameAndValueList ; /. } // switch action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); } // if } while (action != 0); if (first_token == last_token) { const int errorState = state_stack[tos]; // automatic insertion of `;' if (yytoken != -1 && t_action(errorState, T_AUTOMATIC_SEMICOLON) && lexer->canInsertAutomaticSemicolon(yytoken)) { SavedToken &tk = token_buffer[0]; tk.token = yytoken; tk.dval = yylval; tk.spell = yytokenspell; tk.loc = yylloc; yylloc = yyprevlloc; yylloc.offset += yylloc.length; yylloc.startColumn += yylloc.length; yylloc.length = 0; //const QString msg = qApp->translate("QmlParser", "Missing `;'"); //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); first_token = &token_buffer[0]; last_token = &token_buffer[1]; yytoken = T_SEMICOLON; yylval = 0; action = errorState; goto _Lcheck_token; } hadErrors = true; token_buffer[0].token = yytoken; token_buffer[0].dval = yylval; token_buffer[0].spell = yytokenspell; token_buffer[0].loc = yylloc; token_buffer[1].token = yytoken = lexer->lex(); token_buffer[1].dval = yylval = lexer->tokenValue(); token_buffer[1].spell = yytokenspell = lexer->tokenSpell(); token_buffer[1].loc = yylloc = location(lexer); if (t_action(errorState, yytoken)) { QString msg; int token = token_buffer[0].token; if (token < 0 || token >= TERMINAL_COUNT) msg = qApp->translate("QmlParser", "Syntax error"); else msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); action = errorState; goto _Lcheck_token; } static int tokens[] = { T_PLUS, T_EQ, T_COMMA, T_COLON, T_SEMICOLON, T_RPAREN, T_RBRACKET, T_RBRACE, T_NUMERIC_LITERAL, T_IDENTIFIER, T_LPAREN, T_LBRACKET, T_LBRACE, EOF_SYMBOL }; for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { int a = t_action(errorState, *tk); if (a > 0 && t_action(a, yytoken)) { const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = *tk; yylval = 0; yylloc = token_buffer[0].loc; yylloc.length = 0; first_token = &token_buffer[0]; last_token = &token_buffer[2]; action = errorState; goto _Lcheck_token; } } for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION || tk == T_FEED_JS_SOURCE_ELEMENT) continue; int a = t_action(errorState, tk); if (a > 0 && t_action(a, yytoken)) { const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = tk; yylval = 0; yylloc = token_buffer[0].loc; yylloc.length = 0; action = errorState; goto _Lcheck_token; } } const QString msg = qApp->translate("QmlParser", "Syntax error"); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); } return false; } QT_QML_END_NAMESPACE ./ /: QT_QML_END_NAMESPACE #endif // QMLJSPARSER_P_H :/ qbs-src-1.13.1/src/lib/corelib/parser/qmljsast.cpp000066400000000000000000000431771347155106100220000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qmljsast_p.h" #include "qmljsastvisitor_p.h" namespace QbsQmlJS { namespace AST { void Node::accept(Visitor *visitor) { if (visitor->preVisit(this)) { accept0(visitor); } visitor->postVisit(this); } void Node::accept(Node *node, Visitor *visitor) { if (node) node->accept(visitor); } ExpressionNode *Node::expressionCast() { return nullptr; } BinaryExpression *Node::binaryExpressionCast() { return nullptr; } Statement *Node::statementCast() { return nullptr; } UiObjectMember *Node::uiObjectMemberCast() { return nullptr; } ExpressionNode *ExpressionNode::expressionCast() { return this; } BinaryExpression *BinaryExpression::binaryExpressionCast() { return this; } Statement *Statement::statementCast() { return this; } UiObjectMember *UiObjectMember::uiObjectMemberCast() { return this; } void NestedExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void ThisExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void IdentifierExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void NullExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void TrueLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void FalseLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void StringLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void NumericLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void RegExpLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ArrayLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(elements, visitor); accept(elision, visitor); } visitor->endVisit(this); } void ObjectLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(properties, visitor); } visitor->endVisit(this); } void ElementList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (ElementList *it = this; it; it = it->next) { accept(it->elision, visitor); accept(it->expression, visitor); } } visitor->endVisit(this); } void Elision::accept0(Visitor *visitor) { if (visitor->visit(this)) { // ### } visitor->endVisit(this); } void PropertyNameAndValueList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (PropertyNameAndValueList *it = this; it; it = it->next) { accept(it->name, visitor); accept(it->value, visitor); } } visitor->endVisit(this); } void IdentifierPropertyName::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void StringLiteralPropertyName::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void NumericLiteralPropertyName::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ArrayMemberExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); accept(expression, visitor); } visitor->endVisit(this); } void FieldMemberExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); } visitor->endVisit(this); } void NewMemberExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); accept(arguments, visitor); } visitor->endVisit(this); } void NewExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void CallExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); accept(arguments, visitor); } visitor->endVisit(this); } void ArgumentList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (ArgumentList *it = this; it; it = it->next) { accept(it->expression, visitor); } } visitor->endVisit(this); } void PostIncrementExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); } visitor->endVisit(this); } void PostDecrementExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); } visitor->endVisit(this); } void DeleteExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void VoidExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void TypeOfExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void PreIncrementExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void PreDecrementExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void UnaryPlusExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void UnaryMinusExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void TildeExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void NotExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void BinaryExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(left, visitor); accept(right, visitor); } visitor->endVisit(this); } void ConditionalExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(ok, visitor); accept(ko, visitor); } visitor->endVisit(this); } void Expression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(left, visitor); accept(right, visitor); } visitor->endVisit(this); } void Block::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statements, visitor); } visitor->endVisit(this); } void StatementList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (StatementList *it = this; it; it = it->next) { accept(it->statement, visitor); } } visitor->endVisit(this); } void VariableStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(declarations, visitor); } visitor->endVisit(this); } void VariableDeclarationList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (VariableDeclarationList *it = this; it; it = it->next) { accept(it->declaration, visitor); } } visitor->endVisit(this); } void VariableDeclaration::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void EmptyStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ExpressionStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void IfStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(ok, visitor); accept(ko, visitor); } visitor->endVisit(this); } void DoWhileStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); accept(expression, visitor); } visitor->endVisit(this); } void WhileStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void ForStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(initialiser, visitor); accept(condition, visitor); accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void LocalForStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(declarations, visitor); accept(condition, visitor); accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void ForEachStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(initialiser, visitor); accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void LocalForEachStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(declaration, visitor); accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void ContinueStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void BreakStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ReturnStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void WithStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void SwitchStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(block, visitor); } visitor->endVisit(this); } void CaseBlock::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(clauses, visitor); accept(defaultClause, visitor); accept(moreClauses, visitor); } visitor->endVisit(this); } void CaseClauses::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (CaseClauses *it = this; it; it = it->next) { accept(it->clause, visitor); } } visitor->endVisit(this); } void CaseClause::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(statements, visitor); } visitor->endVisit(this); } void DefaultClause::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statements, visitor); } visitor->endVisit(this); } void LabelledStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); } visitor->endVisit(this); } void ThrowStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void TryStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); accept(catchExpression, visitor); accept(finallyExpression, visitor); } visitor->endVisit(this); } void Catch::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); } visitor->endVisit(this); } void Finally::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); } visitor->endVisit(this); } void FunctionDeclaration::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(formals, visitor); accept(body, visitor); } visitor->endVisit(this); } void FunctionExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(formals, visitor); accept(body, visitor); } visitor->endVisit(this); } void FormalParameterList::accept0(Visitor *visitor) { if (visitor->visit(this)) { // ### } visitor->endVisit(this); } void FunctionBody::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(elements, visitor); } visitor->endVisit(this); } void Program::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(elements, visitor); } visitor->endVisit(this); } void SourceElements::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (SourceElements *it = this; it; it = it->next) { accept(it->element, visitor); } } visitor->endVisit(this); } void FunctionSourceElement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(declaration, visitor); } visitor->endVisit(this); } void StatementSourceElement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); } visitor->endVisit(this); } void DebuggerStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void UiProgram::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(imports, visitor); accept(members, visitor); } visitor->endVisit(this); } void UiPublicMember::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); accept(binding, visitor); } visitor->endVisit(this); } void UiObjectDefinition::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(qualifiedTypeNameId, visitor); accept(initializer, visitor); } visitor->endVisit(this); } void UiObjectInitializer::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(members, visitor); } visitor->endVisit(this); } void UiObjectBinding::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(qualifiedId, visitor); accept(qualifiedTypeNameId, visitor); accept(initializer, visitor); } visitor->endVisit(this); } void UiScriptBinding::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(qualifiedId, visitor); accept(statement, visitor); } visitor->endVisit(this); } void UiArrayBinding::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(qualifiedId, visitor); accept(members, visitor); } visitor->endVisit(this); } void UiObjectMemberList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (UiObjectMemberList *it = this; it; it = it->next) accept(it->member, visitor); } visitor->endVisit(this); } void UiArrayMemberList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (UiArrayMemberList *it = this; it; it = it->next) accept(it->member, visitor); } visitor->endVisit(this); } void UiQualifiedId::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void UiImport::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(importUri, visitor); } visitor->endVisit(this); } void UiImportList::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(import, visitor); accept(next, visitor); } visitor->endVisit(this); } void UiSourceElement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(sourceElement, visitor); } visitor->endVisit(this); } } // namespace AST } // namespace QbsQmlJS qbs-src-1.13.1/src/lib/corelib/parser/qmljsast_p.h000066400000000000000000002004741347155106100217570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMLJSAST_P_H #define QMLJSAST_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qmljsastvisitor_p.h" #include "qmljsglobal_p.h" #include "qmljsmemorypool_p.h" #include namespace QbsQmlJS { #define QMLJS_DECLARE_AST_NODE(name) \ enum { K = Kind_##name }; namespace QSOperator // ### rename { enum Op { Add, And, InplaceAnd, Assign, BitAnd, BitOr, BitXor, InplaceSub, Div, InplaceDiv, Equal, Ge, Gt, In, InplaceAdd, InstanceOf, Le, LShift, InplaceLeftShift, Lt, Mod, InplaceMod, Mul, InplaceMul, NotEqual, Or, InplaceOr, RShift, InplaceRightShift, StrictEqual, StrictNotEqual, Sub, URShift, InplaceURightShift, InplaceXor }; } // namespace QSOperator namespace AST { template _T1 cast(_T2 *ast) { if (ast && ast->kind == static_cast<_T1>(nullptr)->K) return static_cast<_T1>(ast); return nullptr; } class QML_PARSER_EXPORT Node: public Managed { public: enum Kind { Kind_Undefined, Kind_ArgumentList, Kind_ArrayLiteral, Kind_ArrayMemberExpression, Kind_BinaryExpression, Kind_Block, Kind_BreakStatement, Kind_CallExpression, Kind_CaseBlock, Kind_CaseClause, Kind_CaseClauses, Kind_Catch, Kind_ConditionalExpression, Kind_ContinueStatement, Kind_DebuggerStatement, Kind_DefaultClause, Kind_DeleteExpression, Kind_DoWhileStatement, Kind_ElementList, Kind_Elision, Kind_EmptyStatement, Kind_Expression, Kind_ExpressionStatement, Kind_FalseLiteral, Kind_FieldMemberExpression, Kind_Finally, Kind_ForEachStatement, Kind_ForStatement, Kind_FormalParameterList, Kind_FunctionBody, Kind_FunctionDeclaration, Kind_FunctionExpression, Kind_FunctionSourceElement, Kind_IdentifierExpression, Kind_IdentifierPropertyName, Kind_IfStatement, Kind_LabelledStatement, Kind_LocalForEachStatement, Kind_LocalForStatement, Kind_NewExpression, Kind_NewMemberExpression, Kind_NotExpression, Kind_NullExpression, Kind_NumericLiteral, Kind_NumericLiteralPropertyName, Kind_ObjectLiteral, Kind_PostDecrementExpression, Kind_PostIncrementExpression, Kind_PreDecrementExpression, Kind_PreIncrementExpression, Kind_Program, Kind_PropertyName, Kind_PropertyNameAndValueList, Kind_RegExpLiteral, Kind_ReturnStatement, Kind_SourceElement, Kind_SourceElements, Kind_StatementList, Kind_StatementSourceElement, Kind_StringLiteral, Kind_StringLiteralPropertyName, Kind_SwitchStatement, Kind_ThisExpression, Kind_ThrowStatement, Kind_TildeExpression, Kind_TrueLiteral, Kind_TryStatement, Kind_TypeOfExpression, Kind_UnaryMinusExpression, Kind_UnaryPlusExpression, Kind_VariableDeclaration, Kind_VariableDeclarationList, Kind_VariableStatement, Kind_VoidExpression, Kind_WhileStatement, Kind_WithStatement, Kind_NestedExpression, Kind_UiArrayBinding, Kind_UiImport, Kind_UiImportList, Kind_UiObjectBinding, Kind_UiObjectDefinition, Kind_UiObjectInitializer, Kind_UiObjectMemberList, Kind_UiArrayMemberList, Kind_UiProgram, Kind_UiParameterList, Kind_UiPublicMember, Kind_UiQualifiedId, Kind_UiScriptBinding, Kind_UiSourceElement }; inline Node() : kind(Kind_Undefined) {} // NOTE: node destructors are never called, // instead we block free the memory // (see the NodePool class) virtual ~Node() {} virtual ExpressionNode *expressionCast(); virtual BinaryExpression *binaryExpressionCast(); virtual Statement *statementCast(); virtual UiObjectMember *uiObjectMemberCast(); void accept(Visitor *visitor); static void accept(Node *node, Visitor *visitor); inline static void acceptChild(Node *node, Visitor *visitor) { return accept(node, visitor); } // ### remove virtual void accept0(Visitor *visitor) = 0; virtual SourceLocation firstSourceLocation() const = 0; virtual SourceLocation lastSourceLocation() const = 0; // attributes int kind; }; class QML_PARSER_EXPORT ExpressionNode: public Node { public: ExpressionNode() {} virtual ExpressionNode *expressionCast(); }; class QML_PARSER_EXPORT Statement: public Node { public: Statement() {} virtual Statement *statementCast(); }; class QML_PARSER_EXPORT NestedExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NestedExpression) NestedExpression(ExpressionNode *expression) : expression(expression) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lparenToken; } virtual SourceLocation lastSourceLocation() const { return rparenToken; } // attributes ExpressionNode *expression; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT ThisExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(ThisExpression) ThisExpression() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return thisToken; } virtual SourceLocation lastSourceLocation() const { return thisToken; } // attributes SourceLocation thisToken; }; class QML_PARSER_EXPORT IdentifierExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(IdentifierExpression) IdentifierExpression(const QStringRef &n): name (n) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return identifierToken; } virtual SourceLocation lastSourceLocation() const { return identifierToken; } // attributes QStringRef name; SourceLocation identifierToken; }; class QML_PARSER_EXPORT NullExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NullExpression) NullExpression() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return nullToken; } virtual SourceLocation lastSourceLocation() const { return nullToken; } // attributes SourceLocation nullToken; }; class QML_PARSER_EXPORT TrueLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(TrueLiteral) TrueLiteral() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return trueToken; } virtual SourceLocation lastSourceLocation() const { return trueToken; } // attributes SourceLocation trueToken; }; class QML_PARSER_EXPORT FalseLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(FalseLiteral) FalseLiteral() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return falseToken; } virtual SourceLocation lastSourceLocation() const { return falseToken; } // attributes SourceLocation falseToken; }; class QML_PARSER_EXPORT NumericLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NumericLiteral) NumericLiteral(double v): value(v) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return literalToken; } virtual SourceLocation lastSourceLocation() const { return literalToken; } // attributes: double value; SourceLocation literalToken; }; class QML_PARSER_EXPORT StringLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(StringLiteral) StringLiteral(const QStringRef &v): value (v) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return literalToken; } virtual SourceLocation lastSourceLocation() const { return literalToken; } // attributes: QStringRef value; SourceLocation literalToken; }; class QML_PARSER_EXPORT RegExpLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(RegExpLiteral) RegExpLiteral(const QStringRef &p, int f): pattern (p), flags (f) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return literalToken; } virtual SourceLocation lastSourceLocation() const { return literalToken; } // attributes: QStringRef pattern; int flags; SourceLocation literalToken; }; class QML_PARSER_EXPORT ArrayLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(ArrayLiteral) ArrayLiteral(Elision *e): elements (nullptr), elision (e) { kind = K; } ArrayLiteral(ElementList *elts): elements (elts), elision (nullptr) { kind = K; } ArrayLiteral(ElementList *elts, Elision *e): elements (elts), elision (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lbracketToken; } virtual SourceLocation lastSourceLocation() const { return rbracketToken; } // attributes ElementList *elements; Elision *elision; SourceLocation lbracketToken; SourceLocation commaToken; SourceLocation rbracketToken; }; class QML_PARSER_EXPORT ObjectLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(ObjectLiteral) ObjectLiteral(): properties (nullptr) { kind = K; } ObjectLiteral(PropertyNameAndValueList *plist): properties (plist) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lbraceToken; } virtual SourceLocation lastSourceLocation() const { return rbraceToken; } // attributes PropertyNameAndValueList *properties; SourceLocation lbraceToken; SourceLocation rbraceToken; }; class QML_PARSER_EXPORT Elision: public Node { public: QMLJS_DECLARE_AST_NODE(Elision) Elision(): next (this) { kind = K; } Elision(Elision *previous) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return commaToken; } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : commaToken; } inline Elision *finish () { Elision *front = next; next = nullptr; return front; } // attributes Elision *next; SourceLocation commaToken; }; class QML_PARSER_EXPORT ElementList: public Node { public: QMLJS_DECLARE_AST_NODE(ElementList) ElementList(Elision *e, ExpressionNode *expr): elision (e), expression (expr), next (this) { kind = K; } ElementList(ElementList *previous, Elision *e, ExpressionNode *expr): elision (e), expression (expr) { kind = K; next = previous->next; previous->next = this; } inline ElementList *finish () { ElementList *front = next; next = nullptr; return front; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { if (elision) return elision->firstSourceLocation(); return expression->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (next) return next->lastSourceLocation(); return expression->lastSourceLocation(); } // attributes Elision *elision; ExpressionNode *expression; ElementList *next; SourceLocation commaToken; }; class QML_PARSER_EXPORT PropertyName: public Node { public: QMLJS_DECLARE_AST_NODE(PropertyName) PropertyName() { kind = K; } virtual SourceLocation firstSourceLocation() const { return propertyNameToken; } virtual SourceLocation lastSourceLocation() const { return propertyNameToken; } // attributes SourceLocation propertyNameToken; }; class QML_PARSER_EXPORT PropertyNameAndValueList: public Node { public: QMLJS_DECLARE_AST_NODE(PropertyNameAndValueList) PropertyNameAndValueList(PropertyName *n, ExpressionNode *v): name (n), value (v), next (this) { kind = K; } PropertyNameAndValueList(PropertyNameAndValueList *previous, PropertyName *n, ExpressionNode *v): name (n), value (v) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return name->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (next) return next->lastSourceLocation(); return value->lastSourceLocation(); } inline PropertyNameAndValueList *finish () { PropertyNameAndValueList *front = next; next = nullptr; return front; } // attributes PropertyName *name; ExpressionNode *value; PropertyNameAndValueList *next; SourceLocation colonToken; SourceLocation commaToken; }; class QML_PARSER_EXPORT IdentifierPropertyName: public PropertyName { public: QMLJS_DECLARE_AST_NODE(IdentifierPropertyName) IdentifierPropertyName(const QStringRef &n): id (n) { kind = K; } virtual void accept0(Visitor *visitor); // attributes QStringRef id; }; class QML_PARSER_EXPORT StringLiteralPropertyName: public PropertyName { public: QMLJS_DECLARE_AST_NODE(StringLiteralPropertyName) StringLiteralPropertyName(const QStringRef &n): id (n) { kind = K; } virtual void accept0(Visitor *visitor); // attributes QStringRef id; }; class QML_PARSER_EXPORT NumericLiteralPropertyName: public PropertyName { public: QMLJS_DECLARE_AST_NODE(NumericLiteralPropertyName) NumericLiteralPropertyName(double n): id (n) { kind = K; } virtual void accept0(Visitor *visitor); // attributes double id; }; class QML_PARSER_EXPORT ArrayMemberExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(ArrayMemberExpression) ArrayMemberExpression(ExpressionNode *b, ExpressionNode *e): base (b), expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return base->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return rbracketToken; } // attributes ExpressionNode *base; ExpressionNode *expression; SourceLocation lbracketToken; SourceLocation rbracketToken; }; class QML_PARSER_EXPORT FieldMemberExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(FieldMemberExpression) FieldMemberExpression(ExpressionNode *b, const QStringRef &n): base (b), name (n) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return base->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return identifierToken; } // attributes ExpressionNode *base; QStringRef name; SourceLocation dotToken; SourceLocation identifierToken; }; class QML_PARSER_EXPORT NewMemberExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NewMemberExpression) NewMemberExpression(ExpressionNode *b, ArgumentList *a): base (b), arguments (a) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return newToken; } virtual SourceLocation lastSourceLocation() const { return rparenToken; } // attributes ExpressionNode *base; ArgumentList *arguments; SourceLocation newToken; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT NewExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NewExpression) NewExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return newToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation newToken; }; class QML_PARSER_EXPORT CallExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(CallExpression) CallExpression(ExpressionNode *b, ArgumentList *a): base (b), arguments (a) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return base->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return rparenToken; } // attributes ExpressionNode *base; ArgumentList *arguments; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT ArgumentList: public Node { public: QMLJS_DECLARE_AST_NODE(ArgumentList) ArgumentList(ExpressionNode *e): expression (e), next (this) { kind = K; } ArgumentList(ArgumentList *previous, ExpressionNode *e): expression (e) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return expression->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (next) return next->lastSourceLocation(); return expression->lastSourceLocation(); } inline ArgumentList *finish () { ArgumentList *front = next; next = nullptr; return front; } // attributes ExpressionNode *expression; ArgumentList *next; SourceLocation commaToken; }; class QML_PARSER_EXPORT PostIncrementExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(PostIncrementExpression) PostIncrementExpression(ExpressionNode *b): base (b) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return base->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return incrementToken; } // attributes ExpressionNode *base; SourceLocation incrementToken; }; class QML_PARSER_EXPORT PostDecrementExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(PostDecrementExpression) PostDecrementExpression(ExpressionNode *b): base (b) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return base->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return decrementToken; } // attributes ExpressionNode *base; SourceLocation decrementToken; }; class QML_PARSER_EXPORT DeleteExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(DeleteExpression) DeleteExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return deleteToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation deleteToken; }; class QML_PARSER_EXPORT VoidExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(VoidExpression) VoidExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return voidToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation voidToken; }; class QML_PARSER_EXPORT TypeOfExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(TypeOfExpression) TypeOfExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return typeofToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation typeofToken; }; class QML_PARSER_EXPORT PreIncrementExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(PreIncrementExpression) PreIncrementExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return incrementToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation incrementToken; }; class QML_PARSER_EXPORT PreDecrementExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(PreDecrementExpression) PreDecrementExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return decrementToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation decrementToken; }; class QML_PARSER_EXPORT UnaryPlusExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(UnaryPlusExpression) UnaryPlusExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return plusToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation plusToken; }; class QML_PARSER_EXPORT UnaryMinusExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(UnaryMinusExpression) UnaryMinusExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return minusToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation minusToken; }; class QML_PARSER_EXPORT TildeExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(TildeExpression) TildeExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return tildeToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation tildeToken; }; class QML_PARSER_EXPORT NotExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NotExpression) NotExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return notToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation notToken; }; class QML_PARSER_EXPORT BinaryExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(BinaryExpression) BinaryExpression(ExpressionNode *l, int o, ExpressionNode *r): left (l), op (o), right (r) { kind = K; } virtual BinaryExpression *binaryExpressionCast(); virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return left->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return right->lastSourceLocation(); } // attributes ExpressionNode *left; int op; ExpressionNode *right; SourceLocation operatorToken; }; class QML_PARSER_EXPORT ConditionalExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(ConditionalExpression) ConditionalExpression(ExpressionNode *e, ExpressionNode *t, ExpressionNode *f): expression (e), ok (t), ko (f) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return expression->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return ko->lastSourceLocation(); } // attributes ExpressionNode *expression; ExpressionNode *ok; ExpressionNode *ko; SourceLocation questionToken; SourceLocation colonToken; }; class QML_PARSER_EXPORT Expression: public ExpressionNode // ### rename { public: QMLJS_DECLARE_AST_NODE(Expression) Expression(ExpressionNode *l, ExpressionNode *r): left (l), right (r) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return left->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return right->lastSourceLocation(); } // attributes ExpressionNode *left; ExpressionNode *right; SourceLocation commaToken; }; class QML_PARSER_EXPORT Block: public Statement { public: QMLJS_DECLARE_AST_NODE(Block) Block(StatementList *slist): statements (slist) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lbraceToken; } virtual SourceLocation lastSourceLocation() const { return rbraceToken; } // attributes StatementList *statements; SourceLocation lbraceToken; SourceLocation rbraceToken; }; class QML_PARSER_EXPORT StatementList: public Node { public: QMLJS_DECLARE_AST_NODE(StatementList) StatementList(Statement *stmt): statement (stmt), next (this) { kind = K; } StatementList(StatementList *previous, Statement *stmt): statement (stmt) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return statement->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : statement->lastSourceLocation(); } inline StatementList *finish () { StatementList *front = next; next = nullptr; return front; } // attributes Statement *statement; StatementList *next; }; class QML_PARSER_EXPORT VariableStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(VariableStatement) VariableStatement(VariableDeclarationList *vlist): declarations (vlist) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return declarationKindToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes VariableDeclarationList *declarations; SourceLocation declarationKindToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT VariableDeclaration: public Node { public: QMLJS_DECLARE_AST_NODE(VariableDeclaration) VariableDeclaration(const QStringRef &n, ExpressionNode *e): name (n), expression (e), readOnly(false) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return identifierToken; } virtual SourceLocation lastSourceLocation() const { return expression ? expression->lastSourceLocation() : identifierToken; } // attributes QStringRef name; ExpressionNode *expression; bool readOnly; SourceLocation identifierToken; }; class QML_PARSER_EXPORT VariableDeclarationList: public Node { public: QMLJS_DECLARE_AST_NODE(VariableDeclarationList) VariableDeclarationList(VariableDeclaration *decl): declaration (decl), next (this) { kind = K; } VariableDeclarationList(VariableDeclarationList *previous, VariableDeclaration *decl): declaration (decl) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return declaration->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (next) return next->lastSourceLocation(); return declaration->lastSourceLocation(); } inline VariableDeclarationList *finish (bool readOnly) { VariableDeclarationList *front = next; next = nullptr; if (readOnly) { VariableDeclarationList *vdl; for (vdl = front; vdl != nullptr; vdl = vdl->next) vdl->declaration->readOnly = true; } return front; } // attributes VariableDeclaration *declaration; VariableDeclarationList *next; SourceLocation commaToken; }; class QML_PARSER_EXPORT EmptyStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(EmptyStatement) EmptyStatement() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return semicolonToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes SourceLocation semicolonToken; }; class QML_PARSER_EXPORT ExpressionStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ExpressionStatement) ExpressionStatement(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return expression->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes ExpressionNode *expression; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT IfStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(IfStatement) IfStatement(ExpressionNode *e, Statement *t, Statement *f = 0): expression (e), ok (t), ko (f) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return ifToken; } virtual SourceLocation lastSourceLocation() const { if (ko) return ko->lastSourceLocation(); return ok->lastSourceLocation(); } // attributes ExpressionNode *expression; Statement *ok; Statement *ko; SourceLocation ifToken; SourceLocation lparenToken; SourceLocation rparenToken; SourceLocation elseToken; }; class QML_PARSER_EXPORT DoWhileStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(DoWhileStatement) DoWhileStatement(Statement *stmt, ExpressionNode *e): statement (stmt), expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return doToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes Statement *statement; ExpressionNode *expression; SourceLocation doToken; SourceLocation whileToken; SourceLocation lparenToken; SourceLocation rparenToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT WhileStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(WhileStatement) WhileStatement(ExpressionNode *e, Statement *stmt): expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return whileToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes ExpressionNode *expression; Statement *statement; SourceLocation whileToken; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT ForStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ForStatement) ForStatement(ExpressionNode *i, ExpressionNode *c, ExpressionNode *e, Statement *stmt): initialiser (i), condition (c), expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return forToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes ExpressionNode *initialiser; ExpressionNode *condition; ExpressionNode *expression; Statement *statement; SourceLocation forToken; SourceLocation lparenToken; SourceLocation firstSemicolonToken; SourceLocation secondSemicolonToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT LocalForStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(LocalForStatement) LocalForStatement(VariableDeclarationList *vlist, ExpressionNode *c, ExpressionNode *e, Statement *stmt): declarations (vlist), condition (c), expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return forToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes VariableDeclarationList *declarations; ExpressionNode *condition; ExpressionNode *expression; Statement *statement; SourceLocation forToken; SourceLocation lparenToken; SourceLocation varToken; SourceLocation firstSemicolonToken; SourceLocation secondSemicolonToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT ForEachStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ForEachStatement) ForEachStatement(ExpressionNode *i, ExpressionNode *e, Statement *stmt): initialiser (i), expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return forToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes ExpressionNode *initialiser; ExpressionNode *expression; Statement *statement; SourceLocation forToken; SourceLocation lparenToken; SourceLocation inToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT LocalForEachStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(LocalForEachStatement) LocalForEachStatement(VariableDeclaration *v, ExpressionNode *e, Statement *stmt): declaration (v), expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return forToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes VariableDeclaration *declaration; ExpressionNode *expression; Statement *statement; SourceLocation forToken; SourceLocation lparenToken; SourceLocation varToken; SourceLocation inToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT ContinueStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ContinueStatement) ContinueStatement(const QStringRef &l = QStringRef()): label (l) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return continueToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes QStringRef label; SourceLocation continueToken; SourceLocation identifierToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT BreakStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(BreakStatement) BreakStatement(const QStringRef &l): label (l) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return breakToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes QStringRef label; SourceLocation breakToken; SourceLocation identifierToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT ReturnStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ReturnStatement) ReturnStatement(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return returnToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes ExpressionNode *expression; SourceLocation returnToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT WithStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(WithStatement) WithStatement(ExpressionNode *e, Statement *stmt): expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return withToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes ExpressionNode *expression; Statement *statement; SourceLocation withToken; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT CaseBlock: public Node { public: QMLJS_DECLARE_AST_NODE(CaseBlock) CaseBlock(CaseClauses *c, DefaultClause *d = 0, CaseClauses *r = 0): clauses (c), defaultClause (d), moreClauses (r) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lbraceToken; } virtual SourceLocation lastSourceLocation() const { return rbraceToken; } // attributes CaseClauses *clauses; DefaultClause *defaultClause; CaseClauses *moreClauses; SourceLocation lbraceToken; SourceLocation rbraceToken; }; class QML_PARSER_EXPORT SwitchStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(SwitchStatement) SwitchStatement(ExpressionNode *e, CaseBlock *b): expression (e), block (b) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return switchToken; } virtual SourceLocation lastSourceLocation() const { return block->rbraceToken; } // attributes ExpressionNode *expression; CaseBlock *block; SourceLocation switchToken; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT CaseClause: public Node { public: QMLJS_DECLARE_AST_NODE(CaseClause) CaseClause(ExpressionNode *e, StatementList *slist): expression (e), statements (slist) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return caseToken; } virtual SourceLocation lastSourceLocation() const { return statements ? statements->lastSourceLocation() : colonToken; } // attributes ExpressionNode *expression; StatementList *statements; SourceLocation caseToken; SourceLocation colonToken; }; class QML_PARSER_EXPORT CaseClauses: public Node { public: QMLJS_DECLARE_AST_NODE(CaseClauses) CaseClauses(CaseClause *c): clause (c), next (this) { kind = K; } CaseClauses(CaseClauses *previous, CaseClause *c): clause (c) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return clause->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : clause->lastSourceLocation(); } inline CaseClauses *finish () { CaseClauses *front = next; next = nullptr; return front; } //attributes CaseClause *clause; CaseClauses *next; }; class QML_PARSER_EXPORT DefaultClause: public Node { public: QMLJS_DECLARE_AST_NODE(DefaultClause) DefaultClause(StatementList *slist): statements (slist) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return defaultToken; } virtual SourceLocation lastSourceLocation() const { return statements ? statements->lastSourceLocation() : colonToken; } // attributes StatementList *statements; SourceLocation defaultToken; SourceLocation colonToken; }; class QML_PARSER_EXPORT LabelledStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(LabelledStatement) LabelledStatement(const QStringRef &l, Statement *stmt): label (l), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return identifierToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes QStringRef label; Statement *statement; SourceLocation identifierToken; SourceLocation colonToken; }; class QML_PARSER_EXPORT ThrowStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ThrowStatement) ThrowStatement(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return throwToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes ExpressionNode *expression; SourceLocation throwToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT Catch: public Node { public: QMLJS_DECLARE_AST_NODE(Catch) Catch(const QStringRef &n, Block *stmt): name (n), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return catchToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes QStringRef name; Block *statement; SourceLocation catchToken; SourceLocation lparenToken; SourceLocation identifierToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT Finally: public Node { public: QMLJS_DECLARE_AST_NODE(Finally) Finally(Block *stmt): statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return finallyToken; } virtual SourceLocation lastSourceLocation() const { return statement ? statement->lastSourceLocation() : finallyToken; } // attributes Block *statement; SourceLocation finallyToken; }; class QML_PARSER_EXPORT TryStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(TryStatement) TryStatement(Statement *stmt, Catch *c, Finally *f): statement (stmt), catchExpression (c), finallyExpression (f) { kind = K; } TryStatement(Statement *stmt, Finally *f): statement (stmt), catchExpression (nullptr), finallyExpression (f) { kind = K; } TryStatement(Statement *stmt, Catch *c): statement (stmt), catchExpression (c), finallyExpression (nullptr) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return tryToken; } virtual SourceLocation lastSourceLocation() const { if (finallyExpression) return finallyExpression->statement->rbraceToken; else if (catchExpression) return catchExpression->statement->rbraceToken; return statement->lastSourceLocation(); } // attributes Statement *statement; Catch *catchExpression; Finally *finallyExpression; SourceLocation tryToken; }; class QML_PARSER_EXPORT FunctionExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(FunctionExpression) FunctionExpression(const QStringRef &n, FormalParameterList *f, FunctionBody *b): name (n), formals (f), body (b) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return functionToken; } virtual SourceLocation lastSourceLocation() const { return rbraceToken; } // attributes QStringRef name; FormalParameterList *formals; FunctionBody *body; SourceLocation functionToken; SourceLocation identifierToken; SourceLocation lparenToken; SourceLocation rparenToken; SourceLocation lbraceToken; SourceLocation rbraceToken; }; class QML_PARSER_EXPORT FunctionDeclaration: public FunctionExpression { public: QMLJS_DECLARE_AST_NODE(FunctionDeclaration) FunctionDeclaration(const QStringRef &n, FormalParameterList *f, FunctionBody *b): FunctionExpression(n, f, b) { kind = K; } virtual void accept0(Visitor *visitor); }; class QML_PARSER_EXPORT FormalParameterList: public Node { public: QMLJS_DECLARE_AST_NODE(FormalParameterList) FormalParameterList(const QStringRef &n): name (n), next (this) { kind = K; } FormalParameterList(FormalParameterList *previous, const QStringRef &n): name (n) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return identifierToken; } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : identifierToken; } inline FormalParameterList *finish () { FormalParameterList *front = next; next = nullptr; return front; } // attributes QStringRef name; FormalParameterList *next; SourceLocation commaToken; SourceLocation identifierToken; }; class QML_PARSER_EXPORT SourceElement: public Node { public: QMLJS_DECLARE_AST_NODE(SourceElement) inline SourceElement() { kind = K; } }; class QML_PARSER_EXPORT SourceElements: public Node { public: QMLJS_DECLARE_AST_NODE(SourceElements) SourceElements(SourceElement *elt): element (elt), next (this) { kind = K; } SourceElements(SourceElements *previous, SourceElement *elt): element (elt) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return element->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : element->lastSourceLocation(); } inline SourceElements *finish () { SourceElements *front = next; next = nullptr; return front; } // attributes SourceElement *element; SourceElements *next; }; class QML_PARSER_EXPORT FunctionBody: public Node { public: QMLJS_DECLARE_AST_NODE(FunctionBody) FunctionBody(SourceElements *elts): elements (elts) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return elements ? elements->firstSourceLocation() : SourceLocation(); } virtual SourceLocation lastSourceLocation() const { return elements ? elements->lastSourceLocation() : SourceLocation(); } // attributes SourceElements *elements; }; class QML_PARSER_EXPORT Program: public Node { public: QMLJS_DECLARE_AST_NODE(Program) Program(SourceElements *elts): elements (elts) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return elements ? elements->firstSourceLocation() : SourceLocation(); } virtual SourceLocation lastSourceLocation() const { return elements ? elements->lastSourceLocation() : SourceLocation(); } // attributes SourceElements *elements; }; class QML_PARSER_EXPORT FunctionSourceElement: public SourceElement { public: QMLJS_DECLARE_AST_NODE(FunctionSourceElement) FunctionSourceElement(FunctionDeclaration *f): declaration (f) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return declaration->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return declaration->lastSourceLocation(); } // attributes FunctionDeclaration *declaration; }; class QML_PARSER_EXPORT StatementSourceElement: public SourceElement { public: QMLJS_DECLARE_AST_NODE(StatementSourceElement) StatementSourceElement(Statement *stmt): statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return statement->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes Statement *statement; }; class QML_PARSER_EXPORT DebuggerStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(DebuggerStatement) DebuggerStatement() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return debuggerToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes SourceLocation debuggerToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT UiQualifiedId: public Node { public: QMLJS_DECLARE_AST_NODE(UiQualifiedId) UiQualifiedId(const QStringRef &name) : next(this), name(name) { kind = K; } UiQualifiedId(UiQualifiedId *previous, const QStringRef &name) : name(name) { kind = K; next = previous->next; previous->next = this; } UiQualifiedId *finish() { UiQualifiedId *head = next; next = nullptr; return head; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return identifierToken; } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : identifierToken; } // attributes UiQualifiedId *next; QStringRef name; SourceLocation identifierToken; }; class QML_PARSER_EXPORT UiImport: public Node { public: QMLJS_DECLARE_AST_NODE(UiImport) UiImport(const QStringRef &fileName) : fileName(fileName), importUri(nullptr) { kind = K; } UiImport(UiQualifiedId *uri) : importUri(uri) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return importToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes QStringRef fileName; UiQualifiedId *importUri; QStringRef importId; SourceLocation importToken; SourceLocation fileNameToken; SourceLocation versionToken; SourceLocation asToken; SourceLocation importIdToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT UiImportList: public Node { public: QMLJS_DECLARE_AST_NODE(UiImportList) UiImportList(UiImport *import) : import(import), next(this) { kind = K; } UiImportList(UiImportList *previous, UiImport *import) : import(import) { kind = K; next = previous->next; previous->next = this; } UiImportList *finish() { UiImportList *head = next; next = nullptr; return head; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return import->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : import->lastSourceLocation(); } // attributes UiImport *import; UiImportList *next; }; class QML_PARSER_EXPORT UiObjectMember: public Node { public: virtual SourceLocation firstSourceLocation() const = 0; virtual SourceLocation lastSourceLocation() const = 0; virtual UiObjectMember *uiObjectMemberCast(); }; class QML_PARSER_EXPORT UiObjectMemberList: public Node { public: QMLJS_DECLARE_AST_NODE(UiObjectMemberList) UiObjectMemberList(UiObjectMember *member) : next(this), member(member) { kind = K; } UiObjectMemberList(UiObjectMemberList *previous, UiObjectMember *member) : member(member) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return member->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : member->lastSourceLocation(); } UiObjectMemberList *finish() { UiObjectMemberList *head = next; next = nullptr; return head; } // attributes UiObjectMemberList *next; UiObjectMember *member; }; class QML_PARSER_EXPORT UiProgram: public Node { public: QMLJS_DECLARE_AST_NODE(UiProgram) UiProgram(UiImportList *imports, UiObjectMemberList *members) : imports(imports), members(members) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { if (imports) return imports->firstSourceLocation(); else if (members) return members->firstSourceLocation(); return SourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (members) return members->lastSourceLocation(); else if (imports) return imports->lastSourceLocation(); return SourceLocation(); } // attributes UiImportList *imports; UiObjectMemberList *members; }; class QML_PARSER_EXPORT UiArrayMemberList: public Node { public: QMLJS_DECLARE_AST_NODE(UiArrayMemberList) UiArrayMemberList(UiObjectMember *member) : next(this), member(member) { kind = K; } UiArrayMemberList(UiArrayMemberList *previous, UiObjectMember *member) : member(member) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return member->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : member->lastSourceLocation(); } UiArrayMemberList *finish() { UiArrayMemberList *head = next; next = nullptr; return head; } // attributes UiArrayMemberList *next; UiObjectMember *member; SourceLocation commaToken; }; class QML_PARSER_EXPORT UiObjectInitializer: public Node { public: QMLJS_DECLARE_AST_NODE(UiObjectInitializer) UiObjectInitializer(UiObjectMemberList *members) : members(members) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lbraceToken; } virtual SourceLocation lastSourceLocation() const { return rbraceToken; } // attributes SourceLocation lbraceToken; UiObjectMemberList *members; SourceLocation rbraceToken; }; class QML_PARSER_EXPORT UiParameterList: public Node { public: QMLJS_DECLARE_AST_NODE(UiParameterList) UiParameterList(const QStringRef &t, const QStringRef &n): type (t), name (n), next (this) { kind = K; } UiParameterList(UiParameterList *previous, const QStringRef &t, const QStringRef &n): type (t), name (n) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *) {} virtual SourceLocation firstSourceLocation() const { return propertyTypeToken; } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : identifierToken; } inline UiParameterList *finish () { UiParameterList *front = next; next = nullptr; return front; } // attributes QStringRef type; QStringRef name; UiParameterList *next; SourceLocation commaToken; SourceLocation propertyTypeToken; SourceLocation identifierToken; }; class QML_PARSER_EXPORT UiPublicMember: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiPublicMember) UiPublicMember(const QStringRef &memberType, const QStringRef &name) : type(Property), memberType(memberType), name(name), statement(nullptr), binding(nullptr), isDefaultMember(false), isReadonlyMember(false), parameters(nullptr) { kind = K; } UiPublicMember(const QStringRef &memberType, const QStringRef &name, Statement *statement) : type(Property), memberType(memberType), name(name), statement(statement), binding(nullptr), isDefaultMember(false), isReadonlyMember(false), parameters(nullptr) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { if (defaultToken.isValid()) return defaultToken; else if (readonlyToken.isValid()) return readonlyToken; return propertyToken; } virtual SourceLocation lastSourceLocation() const { if (binding) return binding->lastSourceLocation(); if (statement) return statement->lastSourceLocation(); return semicolonToken; } // attributes enum { Signal, Property } type; QStringRef typeModifier; QStringRef memberType; QStringRef name; Statement *statement; // initialized with a JS expression UiObjectMember *binding; // initialized with a QML object or array. bool isDefaultMember; bool isReadonlyMember; UiParameterList *parameters; SourceLocation defaultToken; SourceLocation readonlyToken; SourceLocation propertyToken; SourceLocation typeModifierToken; SourceLocation typeToken; SourceLocation identifierToken; SourceLocation colonToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT UiObjectDefinition: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiObjectDefinition) UiObjectDefinition(UiQualifiedId *qualifiedTypeNameId, UiObjectInitializer *initializer) : qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return qualifiedTypeNameId->identifierToken; } virtual SourceLocation lastSourceLocation() const { return initializer->rbraceToken; } // attributes UiQualifiedId *qualifiedTypeNameId; UiObjectInitializer *initializer; }; class QML_PARSER_EXPORT UiSourceElement: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiSourceElement) UiSourceElement(Node *sourceElement) : sourceElement(sourceElement) { kind = K; } virtual SourceLocation firstSourceLocation() const { if (FunctionDeclaration *funDecl = cast(sourceElement)) return funDecl->firstSourceLocation(); else if (VariableStatement *varStmt = cast(sourceElement)) return varStmt->firstSourceLocation(); return SourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (FunctionDeclaration *funDecl = cast(sourceElement)) return funDecl->lastSourceLocation(); else if (VariableStatement *varStmt = cast(sourceElement)) return varStmt->lastSourceLocation(); return SourceLocation(); } virtual void accept0(Visitor *visitor); // attributes Node *sourceElement; }; class QML_PARSER_EXPORT UiObjectBinding: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiObjectBinding) UiObjectBinding(UiQualifiedId *qualifiedId, UiQualifiedId *qualifiedTypeNameId, UiObjectInitializer *initializer) : qualifiedId(qualifiedId), qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer), hasOnToken(false) { kind = K; } virtual SourceLocation firstSourceLocation() const { if (hasOnToken && qualifiedTypeNameId) return qualifiedTypeNameId->identifierToken; return qualifiedId->identifierToken; } virtual SourceLocation lastSourceLocation() const { return initializer->rbraceToken; } virtual void accept0(Visitor *visitor); // attributes UiQualifiedId *qualifiedId; UiQualifiedId *qualifiedTypeNameId; UiObjectInitializer *initializer; SourceLocation colonToken; bool hasOnToken; }; class QML_PARSER_EXPORT UiScriptBinding: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiScriptBinding) UiScriptBinding(UiQualifiedId *qualifiedId, Statement *statement) : qualifiedId(qualifiedId), statement(statement) { kind = K; } virtual SourceLocation firstSourceLocation() const { return qualifiedId->identifierToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } virtual void accept0(Visitor *visitor); // attributes UiQualifiedId *qualifiedId; Statement *statement; SourceLocation colonToken; }; class QML_PARSER_EXPORT UiArrayBinding: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiArrayBinding) UiArrayBinding(UiQualifiedId *qualifiedId, UiArrayMemberList *members) : qualifiedId(qualifiedId), members(members) { kind = K; } virtual SourceLocation firstSourceLocation() const { return qualifiedId->identifierToken; } virtual SourceLocation lastSourceLocation() const { return rbracketToken; } virtual void accept0(Visitor *visitor); // attributes UiQualifiedId *qualifiedId; UiArrayMemberList *members; SourceLocation colonToken; SourceLocation lbracketToken; SourceLocation rbracketToken; }; } // namespace AST } // namespace QbsQmlJS #endif qbs-src-1.13.1/src/lib/corelib/parser/qmljsastfwd_p.h000066400000000000000000000116441347155106100224570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMLJSAST_FWD_P_H #define QMLJSAST_FWD_P_H #include "qmljsglobal_p.h" #include // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // namespace QbsQmlJS { namespace AST { class SourceLocation { public: SourceLocation(quint32 offset = 0, quint32 length = 0, quint32 line = 0, quint32 column = 0) : offset(offset), length(length), startLine(line), startColumn(column) { } bool isValid() const { return length != 0; } quint32 begin() const { return offset; } quint32 end() const { return offset + length; } // attributes // ### encode quint32 offset; quint32 length; quint32 startLine; quint32 startColumn; }; class Visitor; class Node; class ExpressionNode; class Statement; class ThisExpression; class IdentifierExpression; class NullExpression; class TrueLiteral; class FalseLiteral; class NumericLiteral; class StringLiteral; class RegExpLiteral; class ArrayLiteral; class ObjectLiteral; class ElementList; class Elision; class PropertyNameAndValueList; class PropertyName; class IdentifierPropertyName; class StringLiteralPropertyName; class NumericLiteralPropertyName; class ArrayMemberExpression; class FieldMemberExpression; class NewMemberExpression; class NewExpression; class CallExpression; class ArgumentList; class PostIncrementExpression; class PostDecrementExpression; class DeleteExpression; class VoidExpression; class TypeOfExpression; class PreIncrementExpression; class PreDecrementExpression; class UnaryPlusExpression; class UnaryMinusExpression; class TildeExpression; class NotExpression; class BinaryExpression; class ConditionalExpression; class Expression; // ### rename class Block; class StatementList; class VariableStatement; class VariableDeclarationList; class VariableDeclaration; class EmptyStatement; class ExpressionStatement; class IfStatement; class DoWhileStatement; class WhileStatement; class ForStatement; class LocalForStatement; class ForEachStatement; class LocalForEachStatement; class ContinueStatement; class BreakStatement; class ReturnStatement; class WithStatement; class SwitchStatement; class CaseBlock; class CaseClauses; class CaseClause; class DefaultClause; class LabelledStatement; class ThrowStatement; class TryStatement; class Catch; class Finally; class FunctionDeclaration; class FunctionExpression; class FormalParameterList; class FunctionBody; class Program; class SourceElements; class SourceElement; class FunctionSourceElement; class StatementSourceElement; class DebuggerStatement; class NestedExpression; // ui elements class UiProgram; class UiImportList; class UiImport; class UiPublicMember; class UiObjectDefinition; class UiObjectInitializer; class UiObjectBinding; class UiScriptBinding; class UiSourceElement; class UiArrayBinding; class UiObjectMember; class UiObjectMemberList; class UiArrayMemberList; class UiQualifiedId; } // namespace AST } // namespace QbsQmlJS #endif qbs-src-1.13.1/src/lib/corelib/parser/qmljsastvisitor.cpp000066400000000000000000000040031347155106100234010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qmljsastvisitor_p.h" namespace QbsQmlJS { namespace AST { Visitor::Visitor() { } Visitor::~Visitor() { } } // namespace AST } // namespace QbsQmlJS qbs-src-1.13.1/src/lib/corelib/parser/qmljsastvisitor_p.h000066400000000000000000000274231347155106100234000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMLJSASTVISITOR_P_H #define QMLJSASTVISITOR_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qmljsastfwd_p.h" #include "qmljsglobal_p.h" #include namespace QbsQmlJS { namespace AST { class QBS_AUTOTEST_EXPORT Visitor { public: Visitor(); virtual ~Visitor(); virtual bool preVisit(Node *) { return true; } virtual void postVisit(Node *) {} // Ui virtual bool visit(UiProgram *) { return true; } virtual bool visit(UiImportList *) { return true; } virtual bool visit(UiImport *) { return true; } virtual bool visit(UiPublicMember *) { return true; } virtual bool visit(UiSourceElement *) { return true; } virtual bool visit(UiObjectDefinition *) { return true; } virtual bool visit(UiObjectInitializer *) { return true; } virtual bool visit(UiObjectBinding *) { return true; } virtual bool visit(UiScriptBinding *) { return true; } virtual bool visit(UiArrayBinding *) { return true; } virtual bool visit(UiObjectMemberList *) { return true; } virtual bool visit(UiArrayMemberList *) { return true; } virtual bool visit(UiQualifiedId *) { return true; } virtual void endVisit(UiProgram *) {} virtual void endVisit(UiImportList *) {} virtual void endVisit(UiImport *) {} virtual void endVisit(UiPublicMember *) {} virtual void endVisit(UiSourceElement *) {} virtual void endVisit(UiObjectDefinition *) {} virtual void endVisit(UiObjectInitializer *) {} virtual void endVisit(UiObjectBinding *) {} virtual void endVisit(UiScriptBinding *) {} virtual void endVisit(UiArrayBinding *) {} virtual void endVisit(UiObjectMemberList *) {} virtual void endVisit(UiArrayMemberList *) {} virtual void endVisit(UiQualifiedId *) {} // QbsQmlJS virtual bool visit(ThisExpression *) { return true; } virtual void endVisit(ThisExpression *) {} virtual bool visit(IdentifierExpression *) { return true; } virtual void endVisit(IdentifierExpression *) {} virtual bool visit(NullExpression *) { return true; } virtual void endVisit(NullExpression *) {} virtual bool visit(TrueLiteral *) { return true; } virtual void endVisit(TrueLiteral *) {} virtual bool visit(FalseLiteral *) { return true; } virtual void endVisit(FalseLiteral *) {} virtual bool visit(StringLiteral *) { return true; } virtual void endVisit(StringLiteral *) {} virtual bool visit(NumericLiteral *) { return true; } virtual void endVisit(NumericLiteral *) {} virtual bool visit(RegExpLiteral *) { return true; } virtual void endVisit(RegExpLiteral *) {} virtual bool visit(ArrayLiteral *) { return true; } virtual void endVisit(ArrayLiteral *) {} virtual bool visit(ObjectLiteral *) { return true; } virtual void endVisit(ObjectLiteral *) {} virtual bool visit(ElementList *) { return true; } virtual void endVisit(ElementList *) {} virtual bool visit(Elision *) { return true; } virtual void endVisit(Elision *) {} virtual bool visit(PropertyNameAndValueList *) { return true; } virtual void endVisit(PropertyNameAndValueList *) {} virtual bool visit(NestedExpression *) { return true; } virtual void endVisit(NestedExpression *) {} virtual bool visit(IdentifierPropertyName *) { return true; } virtual void endVisit(IdentifierPropertyName *) {} virtual bool visit(StringLiteralPropertyName *) { return true; } virtual void endVisit(StringLiteralPropertyName *) {} virtual bool visit(NumericLiteralPropertyName *) { return true; } virtual void endVisit(NumericLiteralPropertyName *) {} virtual bool visit(ArrayMemberExpression *) { return true; } virtual void endVisit(ArrayMemberExpression *) {} virtual bool visit(FieldMemberExpression *) { return true; } virtual void endVisit(FieldMemberExpression *) {} virtual bool visit(NewMemberExpression *) { return true; } virtual void endVisit(NewMemberExpression *) {} virtual bool visit(NewExpression *) { return true; } virtual void endVisit(NewExpression *) {} virtual bool visit(CallExpression *) { return true; } virtual void endVisit(CallExpression *) {} virtual bool visit(ArgumentList *) { return true; } virtual void endVisit(ArgumentList *) {} virtual bool visit(PostIncrementExpression *) { return true; } virtual void endVisit(PostIncrementExpression *) {} virtual bool visit(PostDecrementExpression *) { return true; } virtual void endVisit(PostDecrementExpression *) {} virtual bool visit(DeleteExpression *) { return true; } virtual void endVisit(DeleteExpression *) {} virtual bool visit(VoidExpression *) { return true; } virtual void endVisit(VoidExpression *) {} virtual bool visit(TypeOfExpression *) { return true; } virtual void endVisit(TypeOfExpression *) {} virtual bool visit(PreIncrementExpression *) { return true; } virtual void endVisit(PreIncrementExpression *) {} virtual bool visit(PreDecrementExpression *) { return true; } virtual void endVisit(PreDecrementExpression *) {} virtual bool visit(UnaryPlusExpression *) { return true; } virtual void endVisit(UnaryPlusExpression *) {} virtual bool visit(UnaryMinusExpression *) { return true; } virtual void endVisit(UnaryMinusExpression *) {} virtual bool visit(TildeExpression *) { return true; } virtual void endVisit(TildeExpression *) {} virtual bool visit(NotExpression *) { return true; } virtual void endVisit(NotExpression *) {} virtual bool visit(BinaryExpression *) { return true; } virtual void endVisit(BinaryExpression *) {} virtual bool visit(ConditionalExpression *) { return true; } virtual void endVisit(ConditionalExpression *) {} virtual bool visit(Expression *) { return true; } virtual void endVisit(Expression *) {} virtual bool visit(Block *) { return true; } virtual void endVisit(Block *) {} virtual bool visit(StatementList *) { return true; } virtual void endVisit(StatementList *) {} virtual bool visit(VariableStatement *) { return true; } virtual void endVisit(VariableStatement *) {} virtual bool visit(VariableDeclarationList *) { return true; } virtual void endVisit(VariableDeclarationList *) {} virtual bool visit(VariableDeclaration *) { return true; } virtual void endVisit(VariableDeclaration *) {} virtual bool visit(EmptyStatement *) { return true; } virtual void endVisit(EmptyStatement *) {} virtual bool visit(ExpressionStatement *) { return true; } virtual void endVisit(ExpressionStatement *) {} virtual bool visit(IfStatement *) { return true; } virtual void endVisit(IfStatement *) {} virtual bool visit(DoWhileStatement *) { return true; } virtual void endVisit(DoWhileStatement *) {} virtual bool visit(WhileStatement *) { return true; } virtual void endVisit(WhileStatement *) {} virtual bool visit(ForStatement *) { return true; } virtual void endVisit(ForStatement *) {} virtual bool visit(LocalForStatement *) { return true; } virtual void endVisit(LocalForStatement *) {} virtual bool visit(ForEachStatement *) { return true; } virtual void endVisit(ForEachStatement *) {} virtual bool visit(LocalForEachStatement *) { return true; } virtual void endVisit(LocalForEachStatement *) {} virtual bool visit(ContinueStatement *) { return true; } virtual void endVisit(ContinueStatement *) {} virtual bool visit(BreakStatement *) { return true; } virtual void endVisit(BreakStatement *) {} virtual bool visit(ReturnStatement *) { return true; } virtual void endVisit(ReturnStatement *) {} virtual bool visit(WithStatement *) { return true; } virtual void endVisit(WithStatement *) {} virtual bool visit(SwitchStatement *) { return true; } virtual void endVisit(SwitchStatement *) {} virtual bool visit(CaseBlock *) { return true; } virtual void endVisit(CaseBlock *) {} virtual bool visit(CaseClauses *) { return true; } virtual void endVisit(CaseClauses *) {} virtual bool visit(CaseClause *) { return true; } virtual void endVisit(CaseClause *) {} virtual bool visit(DefaultClause *) { return true; } virtual void endVisit(DefaultClause *) {} virtual bool visit(LabelledStatement *) { return true; } virtual void endVisit(LabelledStatement *) {} virtual bool visit(ThrowStatement *) { return true; } virtual void endVisit(ThrowStatement *) {} virtual bool visit(TryStatement *) { return true; } virtual void endVisit(TryStatement *) {} virtual bool visit(Catch *) { return true; } virtual void endVisit(Catch *) {} virtual bool visit(Finally *) { return true; } virtual void endVisit(Finally *) {} virtual bool visit(FunctionDeclaration *) { return true; } virtual void endVisit(FunctionDeclaration *) {} virtual bool visit(FunctionExpression *) { return true; } virtual void endVisit(FunctionExpression *) {} virtual bool visit(FormalParameterList *) { return true; } virtual void endVisit(FormalParameterList *) {} virtual bool visit(FunctionBody *) { return true; } virtual void endVisit(FunctionBody *) {} virtual bool visit(Program *) { return true; } virtual void endVisit(Program *) {} virtual bool visit(SourceElements *) { return true; } virtual void endVisit(SourceElements *) {} virtual bool visit(FunctionSourceElement *) { return true; } virtual void endVisit(FunctionSourceElement *) {} virtual bool visit(StatementSourceElement *) { return true; } virtual void endVisit(StatementSourceElement *) {} virtual bool visit(DebuggerStatement *) { return true; } virtual void endVisit(DebuggerStatement *) {} }; } // namespace AST } // namespace QbsQmlJS #endif // QMLJSASTVISITOR_P_H qbs-src-1.13.1/src/lib/corelib/parser/qmljsengine_p.cpp000066400000000000000000000110451347155106100227620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qmljsengine_p.h" #include "qmljsglobal_p.h" #include #include #include namespace QbsQmlJS { static int toDigit(char c) { if ((c >= '0') && (c <= '9')) return c - '0'; else if ((c >= 'a') && (c <= 'z')) return 10 + c - 'a'; else if ((c >= 'A') && (c <= 'Z')) return 10 + c - 'A'; return -1; } double integerFromString(const char *buf, int size, int radix) { if (size == 0) return qSNaN(); double sign = 1.0; int i = 0; if (buf[0] == '+') { ++i; } else if (buf[0] == '-') { sign = -1.0; ++i; } if (((size-i) >= 2) && (buf[i] == '0')) { if (((buf[i+1] == 'x') || (buf[i+1] == 'X')) && (radix < 34)) { if ((radix != 0) && (radix != 16)) return 0; radix = 16; i += 2; } else { if (radix == 0) { radix = 8; ++i; } } } else if (radix == 0) { radix = 10; } int j = i; for ( ; i < size; ++i) { int d = toDigit(buf[i]); if ((d == -1) || (d >= radix)) break; } double result; if (j == i) { if (!qstrcmp(buf, "Infinity")) result = qInf(); else result = qSNaN(); } else { result = 0; double multiplier = 1; for (--i ; i >= j; --i, multiplier *= radix) result += toDigit(buf[i]) * multiplier; } result *= sign; return result; } double integerFromString(const QString &str, int radix) { QByteArray ba = str.trimmed().toLatin1(); return integerFromString(ba.constData(), ba.size(), radix); } Engine::Engine() : _lexer(nullptr), _directives(nullptr) { } Engine::~Engine() { } void Engine::setCode(const QString &code) { _code = code; } void Engine::addComment(int pos, int len, int line, int col) { if (len > 0) _comments.append(QbsQmlJS::AST::SourceLocation(pos, len, line, col)); } QList Engine::comments() const { return _comments; } Lexer *Engine::lexer() const { return _lexer; } void Engine::setLexer(Lexer *lexer) { _lexer = lexer; } void Engine::setDirectives(Directives *directives) { _directives = directives; } Directives *Engine::directives() const { return _directives; } MemoryPool *Engine::pool() { return &_pool; } QStringRef Engine::newStringRef(const QString &text) { const int pos = _extraCode.length(); _extraCode += text; return _extraCode.midRef(pos, text.length()); } QStringRef Engine::newStringRef(const QChar *chars, int size) { return newStringRef(QString(chars, size)); } } // end of namespace QbsQmlJS qbs-src-1.13.1/src/lib/corelib/parser/qmljsengine_p.h000066400000000000000000000072541347155106100224360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMLJSENGINE_P_H #define QMLJSENGINE_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qmljsglobal_p.h" #include "qmljsastfwd_p.h" #include "qmljsmemorypool_p.h" #include #include #include namespace QbsQmlJS { class Lexer; class Directives; class MemoryPool; class QML_PARSER_EXPORT DiagnosticMessage { public: enum Kind { Warning, Error }; DiagnosticMessage() : kind(Error) {} DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message) : kind(kind), loc(loc), message(message) {} bool isWarning() const { return kind == Warning; } bool isError() const { return kind == Error; } Kind kind; AST::SourceLocation loc; QString message; }; class QBS_AUTOTEST_EXPORT Engine { Lexer *_lexer; Directives *_directives; MemoryPool _pool; QList _comments; QString _extraCode; QString _code; public: Engine(); ~Engine(); void setCode(const QString &code); void addComment(int pos, int len, int line, int col); QList comments() const; Lexer *lexer() const; void setLexer(Lexer *lexer); void setDirectives(Directives *directives); Directives *directives() const; MemoryPool *pool(); inline QStringRef midRef(int position, int size) { return _code.midRef(position, size); } QStringRef newStringRef(const QString &s); QStringRef newStringRef(const QChar *chars, int size); }; double integerFromString(const char *buf, int size, int radix); } // end of namespace QbsQmlJS #endif // QMLJSENGINE_P_H qbs-src-1.13.1/src/lib/corelib/parser/qmljsglobal_p.h000066400000000000000000000051451347155106100224260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMLJSGLOBAL_P_H #define QMLJSGLOBAL_P_H #include // Force QML_PARSER_EXPORT to be always empty. #ifndef QT_CREATOR # define QT_CREATOR #endif #ifdef QML_BUILD_STATIC_LIB # undef QML_BUILD_STATIC_LIB #endif #define QML_BUILD_STATIC_LIB 1 #ifdef QT_CREATOR # ifdef QMLJS_BUILD_DIR # define QML_PARSER_EXPORT Q_DECL_EXPORT # elif QML_BUILD_STATIC_LIB # define QML_PARSER_EXPORT # else # define QML_PARSER_EXPORT Q_DECL_IMPORT # endif // QMLJS_BUILD_DIR #else // !QT_CREATOR # if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB) // QmlDevTools is a static library # define QML_PARSER_EXPORT # else # define QML_PARSER_EXPORT Q_AUTOTEST_EXPORT # endif #endif // QT_CREATOR #endif // QMLJSGLOBAL_P_H qbs-src-1.13.1/src/lib/corelib/parser/qmljsgrammar.cpp000066400000000000000000001265621347155106100226370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // This file was generated by qlalr - DO NOT EDIT! #include "qmljsgrammar_p.h" namespace QbsQmlJS { const char *const QmlJSGrammar::spell [] = { "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ",", "continue", "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===", "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier", "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=", "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=", "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return", ")", ";", 0, "*", "*=", "string literal", "property", "signal", "readonly", "switch", "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^", "^=", "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "comment", "public", "import", "as", "on", 0, 0, 0, 0, 0, 0, 0, 0, 0}; const short QmlJSGrammar::lhs [] = { 102, 102, 102, 102, 102, 102, 103, 109, 109, 112, 112, 114, 113, 113, 113, 113, 113, 113, 113, 113, 116, 111, 110, 119, 119, 120, 120, 121, 121, 118, 107, 107, 107, 107, 123, 123, 123, 123, 123, 123, 123, 107, 131, 131, 131, 132, 132, 133, 133, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 117, 117, 117, 117, 117, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 122, 138, 138, 138, 138, 137, 137, 140, 140, 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 144, 144, 115, 115, 115, 115, 115, 147, 147, 148, 148, 148, 148, 146, 146, 149, 149, 150, 150, 151, 151, 151, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 153, 153, 153, 153, 154, 154, 154, 155, 155, 155, 155, 156, 156, 156, 156, 156, 156, 156, 157, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 159, 159, 159, 159, 159, 160, 160, 161, 161, 162, 162, 163, 163, 164, 164, 165, 165, 166, 166, 167, 167, 168, 168, 169, 169, 170, 170, 171, 171, 141, 141, 172, 172, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 105, 105, 174, 174, 175, 175, 176, 176, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 124, 185, 185, 184, 184, 135, 135, 186, 186, 187, 187, 189, 189, 188, 190, 193, 191, 191, 194, 192, 192, 125, 126, 126, 127, 127, 177, 177, 177, 177, 177, 177, 177, 178, 178, 178, 178, 179, 179, 179, 179, 180, 180, 128, 129, 195, 195, 198, 198, 196, 196, 199, 197, 181, 181, 181, 182, 182, 130, 130, 130, 200, 201, 183, 183, 134, 145, 205, 205, 202, 202, 203, 203, 206, 108, 108, 207, 207, 106, 106, 204, 204, 139, 139, 208}; const short QmlJSGrammar::rhs [] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 2, 2, 3, 3, 5, 5, 4, 4, 2, 0, 1, 1, 2, 1, 3, 2, 3, 2, 1, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 0, 1, 2, 4, 6, 6, 3, 3, 7, 7, 4, 4, 5, 5, 5, 6, 6, 10, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 5, 3, 4, 3, 1, 1, 2, 3, 4, 1, 2, 3, 5, 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, 4, 3, 5, 1, 2, 4, 4, 4, 3, 0, 1, 1, 3, 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 5, 1, 5, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 0, 1, 3, 3, 1, 1, 1, 3, 1, 3, 2, 2, 2, 0, 1, 2, 0, 1, 1, 2, 2, 7, 5, 7, 7, 5, 9, 10, 7, 8, 2, 2, 3, 3, 2, 2, 3, 3, 3, 3, 5, 5, 3, 5, 1, 2, 0, 1, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 2, 2, 2, 8, 8, 1, 3, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 0, 1, 2}; const short QmlJSGrammar::action_default [] = { 0, 0, 22, 0, 0, 0, 22, 0, 175, 242, 206, 214, 210, 154, 226, 202, 3, 139, 73, 155, 218, 222, 143, 172, 153, 158, 138, 192, 179, 0, 80, 81, 76, 345, 67, 347, 0, 0, 0, 0, 78, 0, 0, 74, 77, 71, 0, 0, 68, 70, 69, 79, 72, 0, 75, 0, 0, 168, 0, 0, 155, 174, 157, 156, 0, 0, 0, 170, 171, 169, 173, 0, 203, 0, 0, 0, 0, 193, 0, 0, 0, 0, 0, 0, 183, 0, 0, 0, 177, 178, 176, 181, 185, 184, 182, 180, 195, 194, 196, 0, 211, 0, 207, 0, 0, 149, 136, 148, 137, 105, 106, 107, 132, 108, 133, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 134, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 135, 0, 0, 147, 243, 150, 0, 151, 0, 152, 146, 0, 239, 232, 230, 237, 238, 236, 235, 241, 234, 233, 231, 240, 227, 0, 215, 0, 0, 219, 0, 0, 223, 0, 0, 149, 141, 0, 140, 0, 145, 159, 0, 346, 334, 335, 0, 332, 0, 333, 0, 336, 250, 257, 256, 264, 252, 0, 253, 337, 0, 344, 254, 255, 260, 258, 341, 338, 343, 261, 0, 272, 0, 0, 0, 0, 345, 67, 0, 347, 68, 244, 286, 69, 0, 0, 0, 273, 0, 0, 262, 263, 0, 251, 259, 287, 288, 331, 342, 0, 302, 303, 304, 305, 0, 298, 299, 300, 301, 328, 329, 0, 0, 0, 0, 0, 291, 292, 248, 246, 208, 216, 212, 228, 204, 249, 0, 155, 220, 224, 197, 186, 0, 0, 205, 0, 0, 0, 0, 198, 0, 0, 0, 0, 0, 190, 188, 191, 189, 187, 200, 199, 201, 0, 213, 0, 209, 0, 247, 155, 0, 229, 244, 245, 0, 244, 0, 0, 294, 0, 0, 0, 296, 0, 217, 0, 0, 221, 0, 0, 225, 284, 0, 276, 285, 279, 0, 283, 0, 244, 277, 0, 244, 0, 0, 295, 0, 0, 0, 297, 346, 334, 0, 0, 336, 0, 330, 0, 320, 0, 0, 0, 290, 0, 289, 0, 348, 0, 104, 266, 269, 0, 105, 272, 108, 133, 110, 111, 76, 115, 116, 67, 117, 120, 74, 77, 68, 244, 69, 79, 123, 72, 125, 75, 127, 128, 273, 130, 131, 135, 0, 97, 0, 0, 99, 103, 101, 88, 100, 102, 0, 98, 87, 267, 265, 143, 144, 149, 0, 142, 0, 319, 0, 306, 307, 0, 318, 0, 0, 0, 309, 314, 312, 315, 0, 0, 313, 314, 0, 310, 0, 311, 268, 317, 0, 268, 316, 0, 321, 322, 0, 268, 323, 324, 0, 0, 325, 0, 0, 0, 326, 327, 161, 160, 0, 0, 0, 293, 0, 0, 0, 308, 281, 274, 0, 282, 278, 0, 280, 270, 0, 271, 275, 91, 0, 0, 95, 82, 0, 84, 93, 0, 85, 94, 96, 86, 92, 83, 0, 89, 165, 163, 167, 164, 162, 166, 339, 6, 340, 4, 2, 65, 90, 0, 0, 68, 70, 69, 31, 5, 0, 66, 0, 45, 44, 43, 0, 0, 58, 0, 59, 35, 36, 37, 38, 40, 41, 62, 39, 0, 45, 0, 0, 0, 0, 0, 54, 0, 55, 0, 0, 26, 0, 0, 63, 27, 0, 30, 28, 24, 0, 29, 25, 0, 56, 0, 57, 143, 0, 60, 64, 0, 0, 0, 0, 61, 0, 52, 46, 53, 47, 0, 0, 0, 0, 49, 0, 50, 51, 48, 0, 0, 143, 268, 0, 0, 42, 105, 272, 108, 133, 110, 111, 76, 115, 116, 67, 117, 120, 74, 77, 68, 244, 69, 79, 123, 72, 125, 75, 127, 128, 273, 130, 131, 135, 0, 32, 33, 0, 34, 8, 0, 10, 0, 9, 0, 1, 21, 12, 0, 13, 0, 14, 0, 19, 20, 0, 15, 16, 0, 17, 18, 11, 23, 7, 349}; const short QmlJSGrammar::goto_default [] = { 7, 625, 207, 196, 205, 508, 496, 624, 643, 495, 623, 621, 626, 22, 622, 18, 507, 549, 539, 546, 541, 526, 191, 195, 197, 201, 233, 208, 230, 530, 570, 569, 200, 232, 26, 474, 473, 356, 355, 9, 354, 357, 107, 17, 145, 24, 13, 144, 19, 25, 57, 23, 8, 28, 27, 269, 15, 263, 10, 259, 12, 261, 11, 260, 20, 267, 21, 268, 14, 262, 258, 299, 411, 264, 265, 202, 193, 192, 204, 203, 229, 194, 360, 359, 231, 463, 462, 321, 322, 465, 324, 464, 323, 419, 423, 426, 422, 421, 441, 442, 185, 199, 181, 184, 198, 206, 0}; const short QmlJSGrammar::action_index [] = { 404, 1275, 2411, 2411, 2509, 1000, 68, 92, 90, -102, 88, 62, 60, 256, -102, 298, 86, -102, -102, 638, 83, 134, 172, 219, -102, -102, -102, 454, 194, 1275, -102, -102, -102, 381, -102, 2215, 1555, 1275, 1275, 1275, -102, 790, 1275, -102, -102, -102, 1275, 1275, -102, -102, -102, -102, -102, 1275, -102, 1275, 1275, -102, 1275, 1275, 102, 217, -102, -102, 1275, 1275, 1275, -102, -102, -102, 204, 1275, 304, 1275, 1275, 1275, 1275, 539, 1275, 1275, 1275, 1275, 1275, 1275, 308, 1275, 1275, 1275, 103, 131, 135, 308, 210, 225, 216, 308, 444, 390, 434, 1275, 82, 1275, 100, 2117, 1275, 1275, -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, 139, 1275, -102, -102, 91, 10, -102, 1275, -102, -102, 1275, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, 1275, 26, 1275, 1275, 69, 66, 1275, -102, 2117, 1275, 1275, -102, 97, -102, 44, -102, -102, 67, -102, 297, 78, 24, -102, 291, -102, 36, 2411, -102, -102, -102, -102, -102, 234, -102, -102, 12, -102, -102, -102, -102, -102, -102, 2411, -102, -102, 464, -102, 461, 115, 2509, 42, 381, 58, 46, 2705, 70, 1275, -102, 74, 57, 1275, 65, -102, 59, 61, -102, -102, 367, -102, -102, -102, -102, -102, -102, 106, -102, -102, -102, -102, 87, -102, -102, -102, -102, -102, -102, 56, 55, 1275, 99, 84, -102, -102, 1461, -102, 75, 48, 52, -102, 306, 72, 53, 579, 77, 110, 370, 230, 381, 1275, 286, 1275, 1275, 1275, 1275, 380, 1275, 1275, 1275, 1275, 1275, 184, 169, 166, 190, 198, 460, 363, 353, 1275, 50, 1275, 63, 1275, -102, 638, 1275, -102, 1275, 64, 39, 1275, 30, 2509, -102, 1275, 173, 2509, -102, 1275, 79, 1275, 1275, 81, 80, 1275, -102, 71, 149, 32, -102, -102, 1275, -102, 381, 1275, -102, 73, 1275, 76, 2509, -102, 1275, 142, 2509, -102, -16, 381, -42, -12, 2411, -39, -102, 2509, -102, 1275, 154, 2509, 14, 2509, -102, 20, 16, -32, -102, -102, 2509, -51, 519, -4, 511, 136, 1275, 2509, -2, -35, 395, -1, -27, 908, 4, 6, -102, 1370, -102, 0, -36, 27, 1275, 47, 22, 1275, 45, 1275, 21, 17, 1275, -102, 2313, 144, -102, -102, -102, -102, -102, -102, 1275, -102, -102, -102, -102, 274, -102, 1275, -21, -102, 2509, -102, 138, -102, -102, 2509, -102, 1275, 132, 5, -102, 40, -102, 41, 101, 1275, -102, 38, 34, -102, -38, -102, 2509, -102, 105, 2509, -102, 245, -102, -102, 96, 2509, 11, -102, -7, -11, -102, 352, 8, 18, -102, -102, -102, -102, 1275, 129, 2509, -102, 1275, 130, 2509, -102, 49, -102, 226, -102, -102, 1275, -102, -102, 362, -102, -102, -102, 107, 1837, -102, -102, 1649, -102, -102, 1743, -102, -102, -102, -102, -102, -102, 114, -102, -102, -102, -102, -102, -102, -102, -102, -102, 2411, -102, -102, -102, 94, 9, 818, 189, -10, 31, -102, -102, 223, -102, 191, -102, -102, -102, 300, 178, -102, 1928, -102, -102, -102, -102, -102, -102, -102, -102, -102, 257, -25, 381, 195, -22, 305, 240, -102, -6, -102, 818, 127, -102, -18, 818, -102, -102, 1184, -102, -102, -102, 1092, -102, -102, 237, -102, 1928, -102, 294, -8, -102, -102, 176, 381, 19, 1928, -102, 165, -102, 174, -102, 2, -52, 381, 183, 381, -102, 117, -102, -102, -102, 2019, 880, 285, 2607, 1555, 3, -102, 522, 35, 453, 108, 1275, 2509, 51, 23, 475, 54, -17, 700, 7, 43, -102, 1370, -102, 28, -3, 33, 1275, 37, 15, 1275, 25, 1275, 1, 13, 124, -102, -102, 29, -102, -102, 728, -102, 250, -43, 627, -102, -102, 231, 372, -102, 222, -102, 111, -102, -102, 381, -102, -102, 104, -102, -102, -102, -102, -102, -102, -107, 9, -103, 2, 5, 266, 1, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -39, -107, -107, -107, -107, -107, -107, -107, -107, -107, 86, -107, -107, -107, 8, -107, -107, -22, 19, 71, 174, -107, 186, 171, -107, -107, -107, 184, 178, -107, -107, -107, -107, -107, 144, -107, 124, 150, -107, 165, 161, -107, -107, -107, -107, 156, 160, 157, -107, -107, -107, -107, 147, -107, 142, 135, 179, 166, -107, 177, 170, 117, 72, 134, 92, -107, 75, 94, 66, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 181, -107, 106, -107, 143, 78, 55, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -5, -107, -107, -107, -107, -107, 54, -107, -107, 51, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 114, -107, 113, 38, -107, -107, 41, -107, 231, 63, 112, -107, -107, -107, -107, -107, -107, -107, -107, 30, -107, -107, -107, 52, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 36, -107, -107, 45, -107, 42, -107, 40, -107, 80, -107, -107, 77, -107, 88, -107, -107, -107, 83, 74, -107, -107, -107, -107, -107, -10, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 23, -107, -107, -107, -107, 100, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 4, 223, -107, 230, 236, 222, 205, -107, 127, 125, 115, 96, 102, -107, -107, -107, -107, -107, -107, -107, -107, 234, -107, 215, -107, 199, -107, -107, 197, -107, 190, -107, -107, 163, -107, 90, -107, 0, -107, -1, -107, 203, -107, 189, 211, -107, -107, 195, -107, -107, -107, -107, -107, -107, 191, -107, 98, 119, -107, -107, 95, -107, 81, -107, 79, -107, 82, -107, -107, 101, -107, -107, -16, -107, -107, 53, -107, 46, -107, 57, -107, 59, -107, -107, -107, -107, -107, -107, 35, -107, 33, -107, 39, -107, 89, 67, -107, -107, 58, -107, -107, 84, -107, -107, -107, 73, -107, -107, -107, -107, 65, -107, 43, 93, -107, 109, -107, -107, 49, -107, 47, -107, -107, -107, -107, -107, -107, -107, 50, -107, -107, -107, -107, -107, -107, 108, -107, -107, 61, -107, -107, -107, -107, 62, -107, 68, -107, -107, -107, -107, -107, -23, -107, 69, -107, -19, -107, -107, -107, -107, 97, -107, -107, 99, -107, -107, -107, -107, -107, 60, -61, -107, -107, 34, -107, 37, -107, 29, -107, -107, -107, -107, 32, -107, 76, -107, 44, -107, 56, -107, -107, -107, -107, -107, -107, 31, -107, -107, 116, -107, -107, -107, -107, -6, -107, -107, 70, -107, -107, 64, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 193, -107, -107, -107, -107, -107, 7, -107, -107, -107, -107, -107, -107, -107, -20, -107, -107, -107, -7, -107, -107, 290, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -2, -25, -107, -15, -107, -107, -107, -107, 172, -107, -107, -107, 287, -107, -107, 288, -107, -107, -107, 291, -107, -107, -107, -107, 336, -107, -107, 20, -107, -107, 15, 3, -107, 304, -107, -107, -107, 24, -107, -107, -107, 28, 21, 26, -107, -107, -107, -107, -107, 320, 104, -107, 13, 381, -3, -107, 6, -107, 10, -107, 167, 22, -107, -107, 12, -107, -107, 87, -107, -107, -107, 25, -107, -107, -107, -107, 11, -107, 14, 85, -107, 121, -107, -107, -107, -107, -107, 27, -107, -107, 17, -107, -107, 18, 91, -107, -107, -107, 16, -107, -107, -107, -107, -107, -107, -4, -107, -107, -107, -107, -107, -107, -107, -107, -107}; const short QmlJSGrammar::action_info [] = { 416, 257, 533, -132, 403, -113, 346, -102, 575, 348, 572, -121, 531, -103, -121, 545, 345, 430, 342, 348, 340, 343, 440, 401, 391, 545, 563, 389, 538, 446, 352, 444, -129, 416, -124, -102, 545, 453, 420, 408, -124, 431, -132, 424, -126, 424, 424, 620, 440, 457, -103, 440, -129, 457, -126, 440, 560, 453, -113, 257, 565, 346, 545, 335, 272, 346, 466, 236, 448, 190, 149, 164, 141, 170, 99, 511, 272, 409, 257, 312, 296, 414, 348, 312, 189, 164, 187, 318, 325, 71, 306, 252, 644, 416, 141, 453, 292, 457, 440, 147, 304, 71, 443, 183, 179, 141, 0, 141, 0, 172, 99, 427, 434, 141, 301, 477, 444, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 292, 173, 294, 58, 294, 542, 251, 331, 542, 333, 141, 141, 101, 141, 59, 0, 58, 62, 256, 255, 141, 247, 246, 141, 399, 0, 177, 59, 63, 428, 327, 620, 254, 314, 101, 141, 478, 315, 640, 639, 242, 241, 249, 248, 58, 634, 633, 488, 58, 249, 248, 577, 576, 615, 141, 59, 543, 166, 518, 59, 172, 167, 455, 459, 85, 418, 86, 85, 142, 86, 249, 248, 413, 412, 567, 337, 512, 87, 512, 173, 87, 174, 85, 328, 86, 512, 0, 350, 85, 64, 86, 529, 85, 512, 86, 87, 85, 512, 86, 568, 566, 87, 64, 579, 64, 87, 310, 469, 85, 87, 86, 0, 519, 517, 85, 141, 86, 554, 0, 172, 536, 87, 514, 85, 514, 86, 141, 87, 85, 545, 86, 514, 0, 513, 65, 513, 87, 514, 173, 514, 66, 87, 513, 514, 103, 172, 0, 65, 513, 65, 513, 0, 0, 66, 513, 66, 637, 636, 0, 0, 470, 468, 172, 104, 173, 105, 406, 0, 235, 234, 630, 555, 553, 172, 537, 535, 0, 274, 275, 438, 437, 173, 172, 406, 631, 629, 635, 0, 580, 73, 74, -90, 173, 34, 174, 73, 74, 274, 275, 34, -90, 173, 34, 174, 276, 277, 85, 34, 86, 0, 0, 0, 0, 0, 628, 0, 75, 76, 0, 87, 0, 0, 75, 76, 276, 277, 0, 0, 0, 0, 48, 50, 49, 0, 0, 0, 48, 50, 49, 48, 50, 49, 0, 0, 48, 50, 49, 0, 0, 279, 280, 0, 0, 0, 34, 0, 45, 0, 281, 279, 280, 282, 45, 283, 34, 45, 279, 280, 281, 34, 45, 282, 0, 283, 34, 281, 279, 280, 282, 0, 283, 0, 0, 34, 0, 281, 78, 79, 282, 0, 283, 48, 50, 49, 80, 81, 0, 34, 82, 0, 83, 48, 50, 49, -345, 0, 48, 50, 49, 0, 0, 48, 50, 49, 0, 0, 0, 45, 0, 0, 48, 50, 49, 0, 0, 0, 0, 45, 0, 0, 78, 79, 45, 0, 48, 50, 49, 45, 80, 81, 78, 79, 82, 0, 83, 0, 45, 0, 80, 81, 78, 79, 82, 0, 83, 34, 279, 280, 80, 81, 45, 0, 82, 34, 83, 281, 34, 0, 282, 0, 283, 6, 5, 4, 1, 3, 2, 34, 0, 0, 0, 0, 0, 0, -345, 0, 0, 245, 244, 0, 0, 0, 48, 50, 49, 245, 244, 0, 240, 239, 48, 50, 49, 48, 50, 49, 0, 0, 0, 0, 0, 0, 0, 34, 48, 50, 49, 0, 45, 0, 0, 34, 0, 0, 34, 0, 45, 0, 0, 45, 0, 0, 0, 0, 0, 78, 79, 0, 0, 0, 45, 0, 0, 80, 81, 245, 244, 82, 0, 83, 48, 50, 49, 240, 239, 151, 240, 239, 48, 50, 49, 48, 50, 49, 0, 152, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 45, 0, 154, 0, 155, 0, 0, 308, 45, 0, 0, 45, 0, 0, 0, 156, 0, 157, 62, 0, 0, 0, 0, 0, 0, 158, 0, 0, 159, 63, 0, 0, 0, 0, 160, 0, 30, 31, 151, 0, 161, 0, 0, 0, 0, 0, 33, 0, 152, 0, 0, 0, 153, 34, 0, 0, 162, 35, 36, 0, 37, 154, 0, 155, 0, 0, 0, 503, 0, 0, 0, 44, 0, 0, 156, 0, 157, 62, 0, 0, 0, 0, 0, 0, 158, 0, 0, 159, 63, 51, 48, 50, 49, 160, 52, 0, 0, 0, 0, 161, 0, 0, 0, 0, 0, 43, 54, 32, 0, 30, 31, 40, 0, 0, 0, 162, 45, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 30, 31, 0, 41, 0, 0, 0, 44, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 51, 48, 50, 49, 0, 52, 503, 0, 0, 0, 44, 0, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 51, 48, 50, 49, 0, 52, 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, 43, 54, 32, 33, 0, 0, 40, 0, 0, 0, 34, 45, 0, 0, 35, 36, 0, 37, 0, 0, 0, 30, 31, 0, 41, 0, 0, 0, 44, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 51, 48, 50, 49, 0, 52, 503, 0, 0, 0, 44, 0, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 51, 48, 50, 49, 0, 52, 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, 43, 54, 32, 33, 0, 0, 40, 0, 0, 0, 34, 45, 0, 0, 35, 36, 0, 37, 0, 0, 0, 30, 31, 0, 503, 0, 0, 0, 44, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 51, 48, 50, 49, 0, 52, 41, 0, 0, 0, 44, 0, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 51, 48, 50, 49, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 502, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 0, 0, 0, 503, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 504, 506, 505, 0, 52, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 43, 54, 32, 210, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 502, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 0, 0, 0, 503, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 550, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 504, 506, 505, 0, 52, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 43, 54, 32, 210, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 502, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 0, 0, 0, 503, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 547, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 504, 506, 505, 0, 52, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 43, 54, 32, 210, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, -122, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 271, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 475, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 476, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 475, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 481, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 483, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 484, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 483, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 486, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 217, 0, 0, 218, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 51, 48, 50, 49, 223, 52, 0, 53, 225, 55, 0, 56, 0, 228, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 217, 0, 0, 582, 583, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 51, 48, 50, 49, 223, 52, 0, 53, 225, 55, 0, 56, 0, 228, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, 118, 0, 0, 0, 120, 121, 122, 0, 0, 0, 0, 0, 0, 34, 123, 124, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 0, 0, 0, 48, 50, 49, 130, 131, 132, 0, 134, 135, 136, 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, 128, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, 118, 0, 0, 0, 120, 121, 122, 0, 0, 0, 0, 0, 0, 393, 123, 124, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 0, 0, 398, 395, 397, 0, 130, 131, 132, 0, 134, 135, 136, 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, 118, 0, 0, 0, 120, 121, 122, 0, 0, 0, 0, 0, 0, 393, 123, 124, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 394, 0, 0, 0, 0, 0, 0, 0, 396, 0, 0, 0, 129, 0, 0, 0, 0, 0, 398, 395, 397, 0, 130, 131, 132, 0, 134, 135, 136, 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 0, 211, 0, 29, 30, 31, 213, 0, 0, 0, 0, 0, 0, 214, 215, 0, 0, 0, 0, 0, 0, 216, 217, 0, 0, 218, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 220, 0, 221, 0, 0, 0, 51, 219, 222, 49, 223, 52, 224, 53, 225, 55, 226, 56, 227, 228, 0, 0, 43, 54, 32, 210, 212, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 0, 211, 0, 29, 30, 31, 213, 0, 0, 0, 0, 0, 0, 214, 33, 0, 0, 0, 0, 0, 0, 216, 217, 0, 0, 218, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 220, 0, 221, 0, 0, 0, 51, 219, 222, 49, 223, 52, 224, 53, 225, 55, 226, 56, 227, 228, 0, 0, 43, 54, 32, 210, 212, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 586, 110, 111, 0, 0, 588, 115, 590, 30, 31, 591, 0, 118, 0, 0, 0, 120, 593, 594, 0, 0, 0, 0, 0, 0, 595, 596, 124, 125, 218, 36, 0, 37, 0, 0, 0, 38, 0, 39, 597, 42, 0, 0, 599, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 601, 0, 221, 0, 0, 0, 603, 600, 602, 49, 604, 605, 606, 53, 608, 609, 610, 611, 612, 613, 0, 0, 598, 607, 592, 587, 589, 128, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 361, 110, 111, 0, 0, 363, 115, 365, 30, 31, 366, 0, 118, 0, 0, 0, 120, 368, 369, 0, 0, 0, 0, 0, 0, 370, 371, 124, 125, 218, 36, 0, 37, 0, 0, 0, 38, 0, 39, 372, 42, 0, 0, 374, 0, 0, 0, 46, 0, 47, 0, -268, 0, 0, 0, 376, 0, 221, 0, 0, 0, 378, 375, 377, 49, 379, 380, 381, 53, 383, 384, 385, 386, 387, 388, 0, 0, 373, 382, 367, 362, 364, 128, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 534, 311, 497, 309, 532, 461, 498, 499, 516, 515, 619, 638, 16, 552, 436, 358, 616, 472, 562, 320, 528, 238, 487, 182, 250, 243, 253, 182, 302, 641, 627, 632, 150, 485, 143, 454, 439, 402, 445, 559, 237, 574, 250, 578, 561, 186, 618, 458, 238, 349, 573, 449, 447, 571, 243, 347, 450, 243, 460, 351, 238, 353, 358, 410, 415, 439, 176, 188, 436, 250, 467, 417, 433, 182, 425, 429, 302, 169, 456, 358, 171, 140, 336, 334, 338, 344, 436, 392, 390, 400, 163, 302, 307, 148, 146, 339, 439, 404, 302, 358, 404, 358, 0, 482, 501, 480, 0, 642, 0, 479, 0, 0, 0, 320, 60, 0, 186, 501, 90, 60, 60, 489, 302, 60, 617, 93, 0, 88, 0, 405, 0, 461, 405, 60, 60, 451, 180, 60, 0, 180, 60, 60, 60, 451, 60, 95, 89, 146, 266, 287, 60, 146, 407, 270, 60, 288, 178, 60, 106, 452, 0, 60, 60, 60, 102, 60, 302, 332, 286, 60, 92, 452, 60, 60, 451, 60, 165, 168, 285, 432, 284, 435, 60, 60, 108, 501, 329, 94, 540, 96, 60, 330, 60, 302, 494, 60, 77, 237, 60, 404, 452, 341, 471, 72, 60, 60, 67, 69, 60, 60, 68, 0, 70, 60, 60, 60, 61, 180, 60, 60, 98, 491, 60, 91, 490, 60, 60, 60, 493, 60, 84, 405, 60, 97, 492, 305, 0, 60, 0, 298, 0, 100, 270, 298, 270, 298, 106, 298, 270, 0, 270, 60, 270, 60, 316, 0, 270, 0, 270, 298, 291, 326, 303, 60, 270, 319, 313, 300, 270, 297, 60, 60, 108, 175, 295, 270, 270, 290, 60, 501, 273, 317, 60, 270, 60, 278, 509, 270, 0, 270, 0, 289, 0, 548, 0, 293, 551, 0, 500, 510, 501, 501, 0, 544, 501, 0, 0, 0, 509, 0, 0, 509, 520, 521, 522, 523, 527, 524, 525, 0, 500, 510, 0, 500, 510, 564, 520, 521, 522, 523, 527, 524, 525, 581, 0, 0, 0, 0, 0, 0, 584, 585, 520, 521, 522, 523, 527, 524, 525, 556, 0, 0, 0, 0, 0, 0, 557, 558, 520, 521, 522, 523, 527, 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 556, 0, 0, 540, 0, 614, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; const short QmlJSGrammar::action_check [] = { 36, 36, 24, 7, 55, 7, 7, 7, 60, 36, 8, 7, 37, 7, 7, 33, 55, 55, 60, 36, 36, 33, 33, 55, 8, 33, 7, 7, 34, 36, 16, 20, 7, 36, 7, 7, 33, 36, 33, 60, 7, 7, 7, 5, 7, 5, 5, 90, 33, 36, 7, 33, 7, 36, 7, 33, 66, 36, 7, 36, 29, 7, 33, 31, 1, 7, 17, 55, 60, 33, 60, 2, 8, 7, 48, 66, 1, 7, 36, 2, 8, 7, 36, 2, 60, 2, 8, 7, 17, 1, 60, 36, 0, 36, 8, 36, 48, 36, 33, 8, 61, 1, 6, 36, 60, 8, -1, 8, -1, 15, 48, 10, 7, 8, 61, 8, 20, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, 48, 34, 79, 40, 79, 8, 77, 61, 8, 60, 8, 8, 79, 8, 51, -1, 40, 42, 61, 62, 8, 61, 62, 8, 7, -1, 56, 51, 53, 55, 8, 90, 60, 50, 79, 8, 56, 54, 61, 62, 61, 62, 61, 62, 40, 61, 62, 60, 40, 61, 62, 61, 62, 56, 8, 51, 56, 50, 7, 51, 15, 54, 60, 60, 25, 60, 27, 25, 56, 27, 61, 62, 61, 62, 36, 60, 29, 38, 29, 34, 38, 36, 25, 61, 27, 29, -1, 60, 25, 12, 27, 29, 25, 29, 27, 38, 25, 29, 27, 61, 62, 38, 12, 7, 12, 38, 60, 8, 25, 38, 27, -1, 61, 62, 25, 8, 27, 7, -1, 15, 7, 38, 75, 25, 75, 27, 8, 38, 25, 33, 27, 75, -1, 86, 57, 86, 38, 75, 34, 75, 63, 38, 86, 75, 15, 15, -1, 57, 86, 57, 86, -1, -1, 63, 86, 63, 61, 62, -1, -1, 61, 62, 15, 34, 34, 36, 36, -1, 61, 62, 47, 61, 62, 15, 61, 62, -1, 18, 19, 61, 62, 34, 15, 36, 61, 62, 91, -1, 92, 18, 19, 33, 34, 29, 36, 18, 19, 18, 19, 29, 33, 34, 29, 36, 45, 46, 25, 29, 27, -1, -1, -1, -1, -1, 91, -1, 45, 46, -1, 38, -1, -1, 45, 46, 45, 46, -1, -1, -1, -1, 66, 67, 68, -1, -1, -1, 66, 67, 68, 66, 67, 68, -1, -1, 66, 67, 68, -1, -1, 23, 24, -1, -1, -1, 29, -1, 92, -1, 32, 23, 24, 35, 92, 37, 29, 92, 23, 24, 32, 29, 92, 35, -1, 37, 29, 32, 23, 24, 35, -1, 37, -1, -1, 29, -1, 32, 23, 24, 35, -1, 37, 66, 67, 68, 31, 32, -1, 29, 35, -1, 37, 66, 67, 68, 36, -1, 66, 67, 68, -1, -1, 66, 67, 68, -1, -1, -1, 92, -1, -1, 66, 67, 68, -1, -1, -1, -1, 92, -1, -1, 23, 24, 92, -1, 66, 67, 68, 92, 31, 32, 23, 24, 35, -1, 37, -1, 92, -1, 31, 32, 23, 24, 35, -1, 37, 29, 23, 24, 31, 32, 92, -1, 35, 29, 37, 32, 29, -1, 35, -1, 37, 94, 95, 96, 97, 98, 99, 29, -1, -1, -1, -1, -1, -1, 36, -1, -1, 61, 62, -1, -1, -1, 66, 67, 68, 61, 62, -1, 61, 62, 66, 67, 68, 66, 67, 68, -1, -1, -1, -1, -1, -1, -1, 29, 66, 67, 68, -1, 92, -1, -1, 29, -1, -1, 29, -1, 92, -1, -1, 92, -1, -1, -1, -1, -1, 23, 24, -1, -1, -1, 92, -1, -1, 31, 32, 61, 62, 35, -1, 37, 66, 67, 68, 61, 62, 3, 61, 62, 66, 67, 68, 66, 67, 68, -1, 13, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, 92, -1, 26, -1, 28, -1, -1, 31, 92, -1, -1, 92, -1, -1, -1, 39, -1, 41, 42, -1, -1, -1, -1, -1, -1, 49, -1, -1, 52, 53, -1, -1, -1, -1, 58, -1, 12, 13, 3, -1, 64, -1, -1, -1, -1, -1, 22, -1, 13, -1, -1, -1, 17, 29, -1, -1, 80, 33, 34, -1, 36, 26, -1, 28, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, 39, -1, 41, 42, -1, -1, -1, -1, -1, -1, 49, -1, -1, 52, 53, 65, 66, 67, 68, 58, 70, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, 81, 82, 83, -1, 12, 13, 87, -1, -1, -1, 80, 92, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 12, 13, -1, 43, -1, -1, -1, 47, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, 65, 66, 67, 68, -1, 70, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, 65, 66, 67, 68, -1, 70, -1, -1, -1, 12, 13, -1, -1, -1, -1, -1, 81, 82, 83, 22, -1, -1, 87, -1, -1, -1, 29, 92, -1, -1, 33, 34, -1, 36, -1, -1, -1, 12, 13, -1, 43, -1, -1, -1, 47, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, 65, 66, 67, 68, -1, 70, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, 65, 66, 67, 68, -1, 70, -1, -1, -1, 12, 13, -1, -1, -1, -1, -1, 81, 82, 83, 22, -1, -1, 87, -1, -1, -1, 29, 92, -1, -1, 33, 34, -1, 36, -1, -1, -1, 12, 13, -1, 43, -1, -1, -1, 47, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, 65, 66, 67, 68, -1, 70, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, 75, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, -1, 72, 73, 74, -1, 76, -1, 78, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, -1, 72, 73, 74, -1, 76, -1, 78, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, -1, -1, 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, 55, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 2, 105, 3, 29, 15, 4, 2, 15, 29, 9, 15, 3, 15, 3, 2, 19, 39, 15, 15, 13, 15, 3, 15, 2, 15, 3, 15, 3, 11, 13, 15, 71, 39, 39, 3, 22, 2, 99, 19, 4, 15, 2, 15, 29, 15, 19, 3, 15, 3, 29, 22, 15, 29, 15, 2, 22, 15, 2, 2, 15, 2, 2, 2, 2, 22, 3, 15, 3, 2, 39, 3, 3, 15, 97, 94, 3, 39, 2, 2, 39, 3, 3, 2, 2, 101, 3, 40, 39, 39, 39, 3, 2, 39, 39, 15, 22, 13, 3, 2, 13, 2, -1, 39, 13, 35, -1, 16, -1, 39, -1, -1, -1, 15, 48, -1, 15, 13, 52, 48, 48, 50, 3, 48, 20, 53, -1, 52, -1, 45, -1, 15, 45, 48, 48, 50, 50, 48, -1, 50, 48, 48, 48, 50, 48, 53, 52, 39, 48, 53, 48, 39, 44, 53, 48, 53, 44, 48, 15, 50, -1, 48, 48, 48, 58, 48, 3, 72, 53, 48, 53, 50, 48, 48, 50, 48, 62, 64, 53, 82, 53, 82, 48, 48, 41, 13, 88, 53, 16, 54, 48, 72, 48, 3, 50, 48, 54, 4, 48, 13, 50, 100, 86, 56, 48, 48, 50, 50, 48, 48, 50, -1, 51, 48, 48, 48, 51, 50, 48, 48, 54, 50, 48, 53, 50, 48, 48, 48, 50, 48, 53, 45, 48, 54, 50, 72, -1, 48, -1, 48, -1, 60, 53, 48, 53, 48, 15, 48, 53, -1, 53, 48, 53, 48, 65, -1, 53, -1, 53, 48, 55, 70, 72, 48, 53, 70, 63, 70, 53, 70, 48, 48, 41, 42, 59, 53, 53, 55, 48, 13, 57, 70, 48, 53, 48, 55, 20, 53, -1, 53, -1, 55, -1, 5, -1, 61, 5, -1, 32, 33, 13, 13, -1, 16, 13, -1, -1, -1, 20, -1, -1, 20, 22, 23, 24, 25, 26, 27, 28, -1, 32, 33, -1, 32, 33, 21, 22, 23, 24, 25, 26, 27, 28, 13, -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, 28, 13, -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, 28, -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, 13, -1, -1, 16, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -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}; } // namespace QbsQmlJS qbs-src-1.13.1/src/lib/corelib/parser/qmljsgrammar_p.h000066400000000000000000000126411347155106100226130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of other Qt classes. This header file may change from version to // version without notice, or even be removed. // // We mean it. // // This file was generated by qlalr - DO NOT EDIT! #ifndef QMLJSGRAMMAR_P_H #define QMLJSGRAMMAR_P_H #include "qmljsglobal_p.h" #include namespace QbsQmlJS { class QML_PARSER_EXPORT QmlJSGrammar { public: enum VariousConstants { EOF_SYMBOL = 0, REDUCE_HERE = 101, SHIFT_THERE = 100, T_AND = 1, T_AND_AND = 2, T_AND_EQ = 3, T_AS = 91, T_AUTOMATIC_SEMICOLON = 62, T_BREAK = 4, T_CASE = 5, T_CATCH = 6, T_COLON = 7, T_COMMA = 8, T_COMMENT = 88, T_CONST = 84, T_CONTINUE = 9, T_DEBUGGER = 85, T_DEFAULT = 10, T_DELETE = 11, T_DIVIDE_ = 12, T_DIVIDE_EQ = 13, T_DO = 14, T_DOT = 15, T_ELSE = 16, T_EQ = 17, T_EQ_EQ = 18, T_EQ_EQ_EQ = 19, T_ERROR = 93, T_FALSE = 83, T_FEED_JS_EXPRESSION = 97, T_FEED_JS_PROGRAM = 99, T_FEED_JS_SOURCE_ELEMENT = 98, T_FEED_JS_STATEMENT = 96, T_FEED_UI_OBJECT_MEMBER = 95, T_FEED_UI_PROGRAM = 94, T_FINALLY = 20, T_FOR = 21, T_FUNCTION = 22, T_GE = 23, T_GT = 24, T_GT_GT = 25, T_GT_GT_EQ = 26, T_GT_GT_GT = 27, T_GT_GT_GT_EQ = 28, T_IDENTIFIER = 29, T_IF = 30, T_IMPORT = 90, T_IN = 31, T_INSTANCEOF = 32, T_LBRACE = 33, T_LBRACKET = 34, T_LE = 35, T_LPAREN = 36, T_LT = 37, T_LT_LT = 38, T_LT_LT_EQ = 39, T_MINUS = 40, T_MINUS_EQ = 41, T_MINUS_MINUS = 42, T_MULTILINE_STRING_LITERAL = 87, T_NEW = 43, T_NOT = 44, T_NOT_EQ = 45, T_NOT_EQ_EQ = 46, T_NULL = 81, T_NUMERIC_LITERAL = 47, T_ON = 92, T_OR = 48, T_OR_EQ = 49, T_OR_OR = 50, T_PLUS = 51, T_PLUS_EQ = 52, T_PLUS_PLUS = 53, T_PROPERTY = 66, T_PUBLIC = 89, T_QUESTION = 54, T_RBRACE = 55, T_RBRACKET = 56, T_READONLY = 68, T_REMAINDER = 57, T_REMAINDER_EQ = 58, T_RESERVED_WORD = 86, T_RETURN = 59, T_RPAREN = 60, T_SEMICOLON = 61, T_SIGNAL = 67, T_STAR = 63, T_STAR_EQ = 64, T_STRING_LITERAL = 65, T_SWITCH = 69, T_THIS = 70, T_THROW = 71, T_TILDE = 72, T_TRUE = 82, T_TRY = 73, T_TYPEOF = 74, T_VAR = 75, T_VOID = 76, T_WHILE = 77, T_WITH = 78, T_XOR = 79, T_XOR_EQ = 80, ACCEPT_STATE = 644, RULE_COUNT = 349, STATE_COUNT = 645, TERMINAL_COUNT = 102, NON_TERMINAL_COUNT = 107, GOTO_INDEX_OFFSET = 645, GOTO_INFO_OFFSET = 2807, GOTO_CHECK_OFFSET = 2807 }; static const char *const spell []; static const short lhs []; static const short rhs []; static const short goto_default []; static const short action_default []; static const short action_index []; static const short action_info []; static const short action_check []; static inline int nt_action (int state, int nt) { const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt; if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt) return goto_default [nt]; return action_info [GOTO_INFO_OFFSET + yyn]; } static inline int t_action (int state, int token) { const int yyn = action_index [state] + token; if (yyn < 0 || action_check [yyn] != token) return - action_default [state]; return action_info [yyn]; } }; } // namespace QbsQmlJS #endif // QMLJSGRAMMAR_P_H qbs-src-1.13.1/src/lib/corelib/parser/qmljskeywords_p.h000066400000000000000000000535711347155106100230430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMLJSKEYWORDS_P_H #define QMLJSKEYWORDS_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // namespace QbsQmlJS { static inline int classify2(const QChar *s, bool qmlMode) { if (s[0].unicode() == 'a') { if (s[1].unicode() == 's') { return qmlMode ? Lexer::T_AS : Lexer::T_RESERVED_WORD; } } else if (s[0].unicode() == 'd') { if (s[1].unicode() == 'o') { return Lexer::T_DO; } } else if (s[0].unicode() == 'i') { if (s[1].unicode() == 'f') { return Lexer::T_IF; } else if (s[1].unicode() == 'n') { return Lexer::T_IN; } } else if (qmlMode && s[0].unicode() == 'o') { if (s[1].unicode() == 'n') { return Lexer::T_ON; } } return Lexer::T_IDENTIFIER; } static inline int classify3(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'f') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'r') { return Lexer::T_FOR; } } } else if (s[0].unicode() == 'i') { if (s[1].unicode() == 'n') { if (s[2].unicode() == 't') { return Lexer::T_INT; } } } else if (s[0].unicode() == 'n') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'w') { return Lexer::T_NEW; } } } else if (s[0].unicode() == 't') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'y') { return Lexer::T_TRY; } } } else if (s[0].unicode() == 'v') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 'r') { return Lexer::T_VAR; } } } return Lexer::T_IDENTIFIER; } static inline int classify4(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'b') { if (s[1].unicode() == 'y') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'e') { return Lexer::T_BYTE; } } } } else if (s[0].unicode() == 'c') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 's') { if (s[3].unicode() == 'e') { return Lexer::T_CASE; } } } else if (s[1].unicode() == 'h') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 'r') { return Lexer::T_CHAR; } } } } else if (s[0].unicode() == 'e') { if (s[1].unicode() == 'l') { if (s[2].unicode() == 's') { if (s[3].unicode() == 'e') { return Lexer::T_ELSE; } } } else if (s[1].unicode() == 'n') { if (s[2].unicode() == 'u') { if (s[3].unicode() == 'm') { return Lexer::T_ENUM; } } } } else if (s[0].unicode() == 'g') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'o') { return Lexer::T_GOTO; } } } } else if (s[0].unicode() == 'l') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'g') { return Lexer::T_LONG; } } } } else if (s[0].unicode() == 'n') { if (s[1].unicode() == 'u') { if (s[2].unicode() == 'l') { if (s[3].unicode() == 'l') { return Lexer::T_NULL; } } } } else if (s[0].unicode() == 't') { if (s[1].unicode() == 'h') { if (s[2].unicode() == 'i') { if (s[3].unicode() == 's') { return Lexer::T_THIS; } } } else if (s[1].unicode() == 'r') { if (s[2].unicode() == 'u') { if (s[3].unicode() == 'e') { return Lexer::T_TRUE; } } } } else if (s[0].unicode() == 'v') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'i') { if (s[3].unicode() == 'd') { return Lexer::T_VOID; } } } } else if (s[0].unicode() == 'w') { if (s[1].unicode() == 'i') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'h') { return Lexer::T_WITH; } } } } return Lexer::T_IDENTIFIER; } static inline int classify5(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'b') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'e') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 'k') { return Lexer::T_BREAK; } } } } } else if (s[0].unicode() == 'c') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'c') { if (s[4].unicode() == 'h') { return Lexer::T_CATCH; } } } } else if (s[1].unicode() == 'l') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 's') { if (s[4].unicode() == 's') { return Lexer::T_CLASS; } } } } else if (s[1].unicode() == 'o') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 's') { if (s[4].unicode() == 't') { return Lexer::T_CONST; } } } } } else if (s[0].unicode() == 'f') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 'l') { if (s[3].unicode() == 's') { if (s[4].unicode() == 'e') { return Lexer::T_FALSE; } } } } else if (s[1].unicode() == 'i') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 'l') { return Lexer::T_FINAL; } } } } else if (s[1].unicode() == 'l') { if (s[2].unicode() == 'o') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 't') { return Lexer::T_FLOAT; } } } } } else if (s[0].unicode() == 's') { if (s[1].unicode() == 'h') { if (s[2].unicode() == 'o') { if (s[3].unicode() == 'r') { if (s[4].unicode() == 't') { return Lexer::T_SHORT; } } } } else if (s[1].unicode() == 'u') { if (s[2].unicode() == 'p') { if (s[3].unicode() == 'e') { if (s[4].unicode() == 'r') { return Lexer::T_SUPER; } } } } } else if (s[0].unicode() == 't') { if (s[1].unicode() == 'h') { if (s[2].unicode() == 'r') { if (s[3].unicode() == 'o') { if (s[4].unicode() == 'w') { return Lexer::T_THROW; } } } } } else if (s[0].unicode() == 'w') { if (s[1].unicode() == 'h') { if (s[2].unicode() == 'i') { if (s[3].unicode() == 'l') { if (s[4].unicode() == 'e') { return Lexer::T_WHILE; } } } } } return Lexer::T_IDENTIFIER; } static inline int classify6(const QChar *s, bool qmlMode) { if (s[0].unicode() == 'd') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'l') { if (s[3].unicode() == 'e') { if (s[4].unicode() == 't') { if (s[5].unicode() == 'e') { return Lexer::T_DELETE; } } } } } else if (s[1].unicode() == 'o') { if (s[2].unicode() == 'u') { if (s[3].unicode() == 'b') { if (s[4].unicode() == 'l') { if (s[5].unicode() == 'e') { return Lexer::T_DOUBLE; } } } } } } else if (s[0].unicode() == 'e') { if (s[1].unicode() == 'x') { if (s[2].unicode() == 'p') { if (s[3].unicode() == 'o') { if (s[4].unicode() == 'r') { if (s[5].unicode() == 't') { return Lexer::T_EXPORT; } } } } } } else if (s[0].unicode() == 'i') { if (s[1].unicode() == 'm') { if (s[2].unicode() == 'p') { if (s[3].unicode() == 'o') { if (s[4].unicode() == 'r') { if (s[5].unicode() == 't') { return qmlMode ? Lexer::T_IMPORT : Lexer::T_RESERVED_WORD; } } } } } } else if (s[0].unicode() == 'n') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'i') { if (s[4].unicode() == 'v') { if (s[5].unicode() == 'e') { return Lexer::T_NATIVE; } } } } } } else if (s[0].unicode() == 'p') { if (s[1].unicode() == 'u') { if (s[2].unicode() == 'b') { if (s[3].unicode() == 'l') { if (s[4].unicode() == 'i') { if (s[5].unicode() == 'c') { return qmlMode ? Lexer::T_PUBLIC : Lexer::T_RESERVED_WORD; } } } } } } else if (s[0].unicode() == 'r') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'u') { if (s[4].unicode() == 'r') { if (s[5].unicode() == 'n') { return Lexer::T_RETURN; } } } } } } else if (s[0].unicode() == 's') { if (qmlMode && s[1].unicode() == 'i') { if (s[2].unicode() == 'g') { if (s[3].unicode() == 'n') { if (s[4].unicode() == 'a') { if (s[5].unicode() == 'l') { return Lexer::T_SIGNAL; } } } } } else if (s[1].unicode() == 't') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'i') { if (s[5].unicode() == 'c') { return Lexer::T_STATIC; } } } } } else if (s[1].unicode() == 'w') { if (s[2].unicode() == 'i') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'c') { if (s[5].unicode() == 'h') { return Lexer::T_SWITCH; } } } } } } else if (s[0].unicode() == 't') { if (s[1].unicode() == 'h') { if (s[2].unicode() == 'r') { if (s[3].unicode() == 'o') { if (s[4].unicode() == 'w') { if (s[5].unicode() == 's') { return Lexer::T_THROWS; } } } } } else if (s[1].unicode() == 'y') { if (s[2].unicode() == 'p') { if (s[3].unicode() == 'e') { if (s[4].unicode() == 'o') { if (s[5].unicode() == 'f') { return Lexer::T_TYPEOF; } } } } } } return Lexer::T_IDENTIFIER; } static inline int classify7(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'b') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'o') { if (s[3].unicode() == 'l') { if (s[4].unicode() == 'e') { if (s[5].unicode() == 'a') { if (s[6].unicode() == 'n') { return Lexer::T_BOOLEAN; } } } } } } } else if (s[0].unicode() == 'd') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'f') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 'u') { if (s[5].unicode() == 'l') { if (s[6].unicode() == 't') { return Lexer::T_DEFAULT; } } } } } } } else if (s[0].unicode() == 'e') { if (s[1].unicode() == 'x') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'e') { if (s[4].unicode() == 'n') { if (s[5].unicode() == 'd') { if (s[6].unicode() == 's') { return Lexer::T_EXTENDS; } } } } } } } else if (s[0].unicode() == 'f') { if (s[1].unicode() == 'i') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 'l') { if (s[5].unicode() == 'l') { if (s[6].unicode() == 'y') { return Lexer::T_FINALLY; } } } } } } } else if (s[0].unicode() == 'p') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 'c') { if (s[3].unicode() == 'k') { if (s[4].unicode() == 'a') { if (s[5].unicode() == 'g') { if (s[6].unicode() == 'e') { return Lexer::T_PACKAGE; } } } } } } else if (s[1].unicode() == 'r') { if (s[2].unicode() == 'i') { if (s[3].unicode() == 'v') { if (s[4].unicode() == 'a') { if (s[5].unicode() == 't') { if (s[6].unicode() == 'e') { return Lexer::T_PRIVATE; } } } } } } } return Lexer::T_IDENTIFIER; } static inline int classify8(const QChar *s, bool qmlMode) { if (s[0].unicode() == 'a') { if (s[1].unicode() == 'b') { if (s[2].unicode() == 's') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'r') { if (s[5].unicode() == 'a') { if (s[6].unicode() == 'c') { if (s[7].unicode() == 't') { return Lexer::T_ABSTRACT; } } } } } } } } else if (s[0].unicode() == 'c') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'i') { if (s[5].unicode() == 'n') { if (s[6].unicode() == 'u') { if (s[7].unicode() == 'e') { return Lexer::T_CONTINUE; } } } } } } } } else if (s[0].unicode() == 'd') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'b') { if (s[3].unicode() == 'u') { if (s[4].unicode() == 'g') { if (s[5].unicode() == 'g') { if (s[6].unicode() == 'e') { if (s[7].unicode() == 'r') { return Lexer::T_DEBUGGER; } } } } } } } } else if (s[0].unicode() == 'f') { if (s[1].unicode() == 'u') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'c') { if (s[4].unicode() == 't') { if (s[5].unicode() == 'i') { if (s[6].unicode() == 'o') { if (s[7].unicode() == 'n') { return Lexer::T_FUNCTION; } } } } } } } } else if (qmlMode && s[0].unicode() == 'p') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'o') { if (s[3].unicode() == 'p') { if (s[4].unicode() == 'e') { if (s[5].unicode() == 'r') { if (s[6].unicode() == 't') { if (s[7].unicode() == 'y') { return Lexer::T_PROPERTY; } } } } } } } } else if (qmlMode && s[0].unicode() == 'r') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 'd') { if (s[4].unicode() == 'o') { if (s[5].unicode() == 'n') { if (s[6].unicode() == 'l') { if (s[7].unicode() == 'y') { return Lexer::T_READONLY; } } } } } } } } else if (s[0].unicode() == 'v') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'l') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 't') { if (s[5].unicode() == 'i') { if (s[6].unicode() == 'l') { if (s[7].unicode() == 'e') { return Lexer::T_VOLATILE; } } } } } } } } return Lexer::T_IDENTIFIER; } static inline int classify9(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'i') { if (s[1].unicode() == 'n') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'e') { if (s[4].unicode() == 'r') { if (s[5].unicode() == 'f') { if (s[6].unicode() == 'a') { if (s[7].unicode() == 'c') { if (s[8].unicode() == 'e') { return Lexer::T_INTERFACE; } } } } } } } } } else if (s[0].unicode() == 'p') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'o') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'e') { if (s[5].unicode() == 'c') { if (s[6].unicode() == 't') { if (s[7].unicode() == 'e') { if (s[8].unicode() == 'd') { return Lexer::T_PROTECTED; } } } } } } } } } else if (s[0].unicode() == 't') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 'n') { if (s[4].unicode() == 's') { if (s[5].unicode() == 'i') { if (s[6].unicode() == 'e') { if (s[7].unicode() == 'n') { if (s[8].unicode() == 't') { return Lexer::T_TRANSIENT; } } } } } } } } } return Lexer::T_IDENTIFIER; } static inline int classify10(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'i') { if (s[1].unicode() == 'm') { if (s[2].unicode() == 'p') { if (s[3].unicode() == 'l') { if (s[4].unicode() == 'e') { if (s[5].unicode() == 'm') { if (s[6].unicode() == 'e') { if (s[7].unicode() == 'n') { if (s[8].unicode() == 't') { if (s[9].unicode() == 's') { return Lexer::T_IMPLEMENTS; } } } } } } } } } else if (s[1].unicode() == 'n') { if (s[2].unicode() == 's') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'a') { if (s[5].unicode() == 'n') { if (s[6].unicode() == 'c') { if (s[7].unicode() == 'e') { if (s[8].unicode() == 'o') { if (s[9].unicode() == 'f') { return Lexer::T_INSTANCEOF; } } } } } } } } } } return Lexer::T_IDENTIFIER; } static inline int classify12(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 's') { if (s[1].unicode() == 'y') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'c') { if (s[4].unicode() == 'h') { if (s[5].unicode() == 'r') { if (s[6].unicode() == 'o') { if (s[7].unicode() == 'n') { if (s[8].unicode() == 'i') { if (s[9].unicode() == 'z') { if (s[10].unicode() == 'e') { if (s[11].unicode() == 'd') { return Lexer::T_SYNCHRONIZED; } } } } } } } } } } } } return Lexer::T_IDENTIFIER; } int Lexer::classify(const QChar *s, int n, bool qmlMode) { switch (n) { case 2: return classify2(s, qmlMode); case 3: return classify3(s, qmlMode); case 4: return classify4(s, qmlMode); case 5: return classify5(s, qmlMode); case 6: return classify6(s, qmlMode); case 7: return classify7(s, qmlMode); case 8: return classify8(s, qmlMode); case 9: return classify9(s, qmlMode); case 10: return classify10(s, qmlMode); case 12: return classify12(s, qmlMode); default: return Lexer::T_IDENTIFIER; } // switch } } // namespace QbsQmlJS #endif // QMLJSKEYWORDS_P_H qbs-src-1.13.1/src/lib/corelib/parser/qmljslexer.cpp000066400000000000000000001002721347155106100223160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qmljslexer_p.h" #include "qmljsengine_p.h" #include "qmljsmemorypool_p.h" #include #include #include QT_BEGIN_NAMESPACE Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok); QT_END_NAMESPACE namespace QbsQmlJS { static int regExpFlagFromChar(const QChar &ch) { switch (ch.unicode()) { case 'g': return Lexer::RegExp_Global; case 'i': return Lexer::RegExp_IgnoreCase; case 'm': return Lexer::RegExp_Multiline; } return 0; } static unsigned char convertHex(ushort c) { if (c >= '0' && c <= '9') return (c - '0'); else if (c >= 'a' && c <= 'f') return (c - 'a' + 10); else return (c - 'A' + 10); } static QChar convertHex(QChar c1, QChar c2) { return {(convertHex(c1.unicode()) << 4) + convertHex(c2.unicode())}; } static QChar convertUnicode(QChar c1, QChar c2, QChar c3, QChar c4) { return QChar((convertHex(c3.unicode()) << 4) + convertHex(c4.unicode()), (convertHex(c1.unicode()) << 4) + convertHex(c2.unicode())); } Lexer::Lexer(Engine *engine) : _engine(engine) , _codePtr(nullptr) , _lastLinePtr(nullptr) , _tokenLinePtr(nullptr) , _tokenStartPtr(nullptr) , _char(QLatin1Char('\n')) , _errorCode(NoError) , _currentLineNumber(0) , _tokenValue(0) , _parenthesesState(IgnoreParentheses) , _parenthesesCount(0) , _stackToken(-1) , _patternFlags(0) , _tokenKind(0) , _tokenLength(0) , _tokenLine(0) , _validTokenText(false) , _prohibitAutomaticSemicolon(false) , _restrictedKeyword(false) , _terminator(false) , _followsClosingBrace(false) , _delimited(true) , _qmlMode(true) { if (engine) engine->setLexer(this); } bool Lexer::qmlMode() const { return _qmlMode; } QString Lexer::code() const { return _code; } void Lexer::setCode(const QString &code, int lineno, bool qmlMode) { if (_engine) _engine->setCode(code); _qmlMode = qmlMode; _code = code; _tokenText.clear(); _tokenText.reserve(1024); _errorMessage.clear(); _tokenSpell = QStringRef(); _codePtr = code.unicode(); _lastLinePtr = _codePtr; _tokenLinePtr = _codePtr; _tokenStartPtr = _codePtr; _char = QLatin1Char('\n'); _errorCode = NoError; _currentLineNumber = lineno; _tokenValue = 0; // parentheses state _parenthesesState = IgnoreParentheses; _parenthesesCount = 0; _stackToken = -1; _patternFlags = 0; _tokenLength = 0; _tokenLine = lineno; _validTokenText = false; _prohibitAutomaticSemicolon = false; _restrictedKeyword = false; _terminator = false; _followsClosingBrace = false; _delimited = true; } void Lexer::scanChar() { _char = *_codePtr++; if (_char == QLatin1Char('\n')) { _lastLinePtr = _codePtr; // points to the first character after the newline ++_currentLineNumber; } } int Lexer::lex() { const int previousTokenKind = _tokenKind; _tokenSpell = QStringRef(); _tokenKind = scanToken(); _tokenLength = _codePtr - _tokenStartPtr - 1; _delimited = false; _restrictedKeyword = false; _followsClosingBrace = (previousTokenKind == T_RBRACE); // update the flags switch (_tokenKind) { case T_LBRACE: case T_SEMICOLON: case T_COLON: _delimited = true; break; case T_IF: case T_FOR: case T_WHILE: case T_WITH: _parenthesesState = CountParentheses; _parenthesesCount = 0; break; case T_DO: _parenthesesState = BalancedParentheses; break; case T_CONTINUE: case T_BREAK: case T_RETURN: case T_THROW: _restrictedKeyword = true; break; } // switch // update the parentheses state switch (_parenthesesState) { case IgnoreParentheses: break; case CountParentheses: if (_tokenKind == T_RPAREN) { --_parenthesesCount; if (_parenthesesCount == 0) _parenthesesState = BalancedParentheses; } else if (_tokenKind == T_LPAREN) { ++_parenthesesCount; } break; case BalancedParentheses: _parenthesesState = IgnoreParentheses; break; } // switch return _tokenKind; } bool Lexer::isUnicodeEscapeSequence(const QChar *chars) { if (isHexDigit(chars[0]) && isHexDigit(chars[1]) && isHexDigit(chars[2]) && isHexDigit(chars[3])) return true; return false; } QChar Lexer::decodeUnicodeEscapeCharacter(bool *ok) { if (_char == QLatin1Char('u') && isUnicodeEscapeSequence(&_codePtr[0])) { scanChar(); // skip u const QChar c1 = _char; scanChar(); const QChar c2 = _char; scanChar(); const QChar c3 = _char; scanChar(); const QChar c4 = _char; scanChar(); if (ok) *ok = true; return convertUnicode(c1, c2, c3, c4); } *ok = false; return {}; } int Lexer::scanToken() { if (_stackToken != -1) { int tk = _stackToken; _stackToken = -1; return tk; } _terminator = false; again: _validTokenText = false; _tokenLinePtr = _lastLinePtr; while (_char.isSpace()) { if (_char == QLatin1Char('\n')) { _tokenLinePtr = _codePtr; if (_restrictedKeyword) { // automatic semicolon insertion _tokenLine = _currentLineNumber; _tokenStartPtr = _codePtr - 1; // ### TODO: insert it before the optional \r sequence. return T_SEMICOLON; } else { _terminator = true; syncProhibitAutomaticSemicolon(); } } scanChar(); } _tokenStartPtr = _codePtr - 1; _tokenLine = _currentLineNumber; if (_char.isNull()) return EOF_SYMBOL; const QChar ch = _char; scanChar(); switch (ch.unicode()) { case '~': return T_TILDE; case '}': return T_RBRACE; case '|': if (_char == QLatin1Char('|')) { scanChar(); return T_OR_OR; } else if (_char == QLatin1Char('=')) { scanChar(); return T_OR_EQ; } return T_OR; case '{': return T_LBRACE; case '^': if (_char == QLatin1Char('=')) { scanChar(); return T_XOR_EQ; } return T_XOR; case ']': return T_RBRACKET; case '[': return T_LBRACKET; case '?': return T_QUESTION; case '>': if (_char == QLatin1Char('>')) { scanChar(); if (_char == QLatin1Char('>')) { scanChar(); if (_char == QLatin1Char('=')) { scanChar(); return T_GT_GT_GT_EQ; } return T_GT_GT_GT; } else if (_char == QLatin1Char('=')) { scanChar(); return T_GT_GT_EQ; } return T_GT_GT; } else if (_char == QLatin1Char('=')) { scanChar(); return T_GE; } return T_GT; case '=': if (_char == QLatin1Char('=')) { scanChar(); if (_char == QLatin1Char('=')) { scanChar(); return T_EQ_EQ_EQ; } return T_EQ_EQ; } return T_EQ; case '<': if (_char == QLatin1Char('=')) { scanChar(); return T_LE; } else if (_char == QLatin1Char('<')) { scanChar(); if (_char == QLatin1Char('=')) { scanChar(); return T_LT_LT_EQ; } return T_LT_LT; } return T_LT; case ';': return T_SEMICOLON; case ':': return T_COLON; case '/': if (_char == QLatin1Char('*')) { scanChar(); while (!_char.isNull()) { if (_char == QLatin1Char('*')) { scanChar(); if (_char == QLatin1Char('/')) { scanChar(); if (_engine) { _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 4, tokenStartLine(), tokenStartColumn() + 2); } goto again; } } else { scanChar(); } } } else if (_char == QLatin1Char('/')) { while (!_char.isNull() && _char != QLatin1Char('\n')) { scanChar(); } if (_engine) { _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 2, tokenStartLine(), tokenStartColumn() + 2); } goto again; } if (_char == QLatin1Char('=')) { scanChar(); return T_DIVIDE_EQ; } return T_DIVIDE_; case '.': if (_char.isDigit()) { QVarLengthArray chars; chars.append(ch.unicode()); // append the `.' while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); } if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && _codePtr[1].isDigit())) { chars.append(_char.unicode()); scanChar(); // consume `e' if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { chars.append(_char.unicode()); scanChar(); // consume the sign } while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); } } } chars.append('\0'); const char *begin = chars.constData(); const char *end = nullptr; bool ok = false; _tokenValue = qstrtod(begin, &end, &ok); if (end - begin != chars.size() - 1) { _errorCode = IllegalExponentIndicator; _errorMessage = QCoreApplication::translate("QmlParser", "Illegal syntax for exponential number"); return T_ERROR; } return T_NUMERIC_LITERAL; } return T_DOT; case '-': if (_char == QLatin1Char('=')) { scanChar(); return T_MINUS_EQ; } else if (_char == QLatin1Char('-')) { scanChar(); if (_terminator && !_delimited && !_prohibitAutomaticSemicolon) { _stackToken = T_MINUS_MINUS; return T_SEMICOLON; } return T_MINUS_MINUS; } return T_MINUS; case ',': return T_COMMA; case '+': if (_char == QLatin1Char('=')) { scanChar(); return T_PLUS_EQ; } else if (_char == QLatin1Char('+')) { scanChar(); if (_terminator && !_delimited && !_prohibitAutomaticSemicolon) { _stackToken = T_PLUS_PLUS; return T_SEMICOLON; } return T_PLUS_PLUS; } return T_PLUS; case '*': if (_char == QLatin1Char('=')) { scanChar(); return T_STAR_EQ; } return T_STAR; case ')': return T_RPAREN; case '(': return T_LPAREN; case '&': if (_char == QLatin1Char('=')) { scanChar(); return T_AND_EQ; } else if (_char == QLatin1Char('&')) { scanChar(); return T_AND_AND; } return T_AND; case '%': if (_char == QLatin1Char('=')) { scanChar(); return T_REMAINDER_EQ; } return T_REMAINDER; case '!': if (_char == QLatin1Char('=')) { scanChar(); if (_char == QLatin1Char('=')) { scanChar(); return T_NOT_EQ_EQ; } return T_NOT_EQ; } return T_NOT; case '\'': case '"': { const QChar quote = ch; bool multilineStringLiteral = false; const QChar *startCode = _codePtr; if (_engine) { while (!_char.isNull()) { if (_char == QLatin1Char('\n') || _char == QLatin1Char('\\')) { break; } else if (_char == quote) { _tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode); scanChar(); return T_STRING_LITERAL; } scanChar(); } } _validTokenText = true; _tokenText.resize(0); startCode--; while (startCode != _codePtr - 1) _tokenText += *startCode++; while (! _char.isNull()) { if (_char == QLatin1Char('\n')) { multilineStringLiteral = true; _tokenText += _char; scanChar(); } else if (_char == quote) { scanChar(); if (_engine) _tokenSpell = _engine->newStringRef(_tokenText); return multilineStringLiteral ? T_MULTILINE_STRING_LITERAL : T_STRING_LITERAL; } else if (_char == QLatin1Char('\\')) { scanChar(); QChar u; bool ok = false; switch (_char.unicode()) { // unicode escape sequence case 'u': u = decodeUnicodeEscapeCharacter(&ok); if (! ok) u = _char; break; // hex escape sequence case 'x': case 'X': if (isHexDigit(_codePtr[0]) && isHexDigit(_codePtr[1])) { scanChar(); const QChar c1 = _char; scanChar(); const QChar c2 = _char; scanChar(); u = convertHex(c1, c2); } else { u = _char; } break; // single character escape sequence case '\\': u = QLatin1Char('\\'); scanChar(); break; case '\'': u = QLatin1Char('\''); scanChar(); break; case '\"': u = QLatin1Char('\"'); scanChar(); break; case 'b': u = QLatin1Char('\b'); scanChar(); break; case 'f': u = QLatin1Char('\f'); scanChar(); break; case 'n': u = QLatin1Char('\n'); scanChar(); break; case 'r': u = QLatin1Char('\r'); scanChar(); break; case 't': u = QLatin1Char('\t'); scanChar(); break; case 'v': u = QLatin1Char('\v'); scanChar(); break; case '0': if (! _codePtr[1].isDigit()) { scanChar(); u = QLatin1Char('\0'); } else { // ### parse deprecated octal escape sequence ? u = _char; } break; case '\r': while (_char == QLatin1Char('\r')) scanChar(); if (_char == QLatin1Char('\n')) { u = _char; scanChar(); } else { u = QLatin1Char('\n'); } break; case '\n': u = _char; scanChar(); break; default: // non escape character u = _char; scanChar(); } _tokenText += u; } else { _tokenText += _char; scanChar(); } } _errorCode = UnclosedStringLiteral; _errorMessage = QCoreApplication::translate("QmlParser", "Unclosed string at end of line"); return T_ERROR; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return scanNumber(ch); default: if (ch.isLetter() || ch == QLatin1Char('$') || ch == QLatin1Char('_') || (ch == QLatin1Char('\\') && _char == QLatin1Char('u'))) { bool identifierWithEscapeChars = false; if (ch == QLatin1Char('\\')) { identifierWithEscapeChars = true; _tokenText.resize(0); bool ok = false; _tokenText += decodeUnicodeEscapeCharacter(&ok); _validTokenText = true; if (! ok) { _errorCode = IllegalUnicodeEscapeSequence; _errorMessage = QCoreApplication::translate("QmlParser", "Illegal unicode escape sequence"); return T_ERROR; } } while (true) { if (_char.isLetterOrNumber() || _char == QLatin1Char('$') || _char == QLatin1Char('_')) { if (identifierWithEscapeChars) _tokenText += _char; scanChar(); } else if (_char == QLatin1Char('\\') && _codePtr[0] == QLatin1Char('u')) { if (! identifierWithEscapeChars) { identifierWithEscapeChars = true; _tokenText.resize(0); _tokenText.insert(0, _tokenStartPtr, _codePtr - _tokenStartPtr - 1); _validTokenText = true; } scanChar(); // skip '\\' bool ok = false; _tokenText += decodeUnicodeEscapeCharacter(&ok); if (! ok) { _errorCode = IllegalUnicodeEscapeSequence; _errorMessage = QCoreApplication::translate("QmlParser", "Illegal unicode escape sequence"); return T_ERROR; } } else { _tokenLength = _codePtr - _tokenStartPtr - 1; int kind = T_IDENTIFIER; if (! identifierWithEscapeChars) kind = classify(_tokenStartPtr, _tokenLength, _qmlMode); if (_engine) { if (kind == T_IDENTIFIER && identifierWithEscapeChars) _tokenSpell = _engine->newStringRef(_tokenText); else _tokenSpell = _engine->midRef(_tokenStartPtr - _code.unicode(), _tokenLength); } return kind; } } } break; } return T_ERROR; } int Lexer::scanNumber(QChar ch) { if (ch != QLatin1Char('0')) { double integer = ch.unicode() - '0'; QChar n = _char; const QChar *code = _codePtr; while (n.isDigit()) { integer = integer * 10 + (n.unicode() - '0'); n = *code++; } if (n != QLatin1Char('.') && n != QLatin1Char('e') && n != QLatin1Char('E')) { if (code != _codePtr) { _codePtr = code - 1; scanChar(); } _tokenValue = integer; return T_NUMERIC_LITERAL; } } QVarLengthArray chars; chars.append(ch.unicode()); if (ch == QLatin1Char('0') && (_char == QLatin1Char('x') || _char == QLatin1Char('X'))) { // parse hex integer literal chars.append(_char.unicode()); scanChar(); // consume `x' while (isHexDigit(_char)) { chars.append(_char.unicode()); scanChar(); } _tokenValue = integerFromString(chars.constData(), chars.size(), 16); return T_NUMERIC_LITERAL; } // decimal integer literal while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); // consume the digit } if (_char == QLatin1Char('.')) { chars.append(_char.unicode()); scanChar(); // consume `.' while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); } if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && _codePtr[1].isDigit())) { chars.append(_char.unicode()); scanChar(); // consume `e' if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { chars.append(_char.unicode()); scanChar(); // consume the sign } while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); } } } } else if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && _codePtr[1].isDigit())) { chars.append(_char.unicode()); scanChar(); // consume `e' if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { chars.append(_char.unicode()); scanChar(); // consume the sign } while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); } } } if (chars.size() == 1) { // if we ended up with a single digit, then it was a '0' _tokenValue = 0; return T_NUMERIC_LITERAL; } chars.append('\0'); const char *begin = chars.constData(); const char *end = nullptr; bool ok = false; _tokenValue = qstrtod(begin, &end, &ok); if (end - begin != chars.size() - 1) { _errorCode = IllegalExponentIndicator; _errorMessage = QCoreApplication::translate("QmlParser", "Illegal syntax for exponential number"); return T_ERROR; } return T_NUMERIC_LITERAL; } bool Lexer::scanRegExp(RegExpBodyPrefix prefix) { _tokenText.resize(0); _validTokenText = true; _patternFlags = 0; if (prefix == EqualPrefix) _tokenText += QLatin1Char('='); while (true) { switch (_char.unicode()) { case 0: // eof case '\n': case '\r': // line terminator _errorMessage = QCoreApplication::translate("QmlParser", "Unterminated regular expression literal"); return false; case '/': scanChar(); // scan the flags _patternFlags = 0; while (isIdentLetter(_char)) { int flag = regExpFlagFromChar(_char); if (flag == 0) { _errorMessage = QCoreApplication::translate("QmlParser", "Invalid regular expression flag '%0'") .arg(QChar(_char)); return false; } _patternFlags |= flag; scanChar(); } _tokenLength = _codePtr - _tokenStartPtr - 1; return true; case '\\': // regular expression backslash sequence _tokenText += _char; scanChar(); if (_char.isNull() || isLineTerminator()) { _errorMessage = QCoreApplication::translate("QmlParser", "Unterminated regular expression backslash sequence"); return false; } _tokenText += _char; scanChar(); break; case '[': // regular expression class _tokenText += _char; scanChar(); while (! _char.isNull() && ! isLineTerminator()) { if (_char == QLatin1Char(']')) break; else if (_char == QLatin1Char('\\')) { // regular expression backslash sequence _tokenText += _char; scanChar(); if (_char.isNull() || isLineTerminator()) { _errorMessage = QCoreApplication::translate("QmlParser", "Unterminated regular expression backslash sequence"); return false; } _tokenText += _char; scanChar(); } else { _tokenText += _char; scanChar(); } } if (_char != QLatin1Char(']')) { _errorMessage = QCoreApplication::translate("QmlParser", "Unterminated regular expression class"); return false; } _tokenText += _char; scanChar(); // skip ] break; default: _tokenText += _char; scanChar(); } // switch } // while return false; } bool Lexer::isLineTerminator() const { return (_char == QLatin1Char('\n') || _char == QLatin1Char('\r')); } bool Lexer::isIdentLetter(QChar ch) { // ASCII-biased, since all reserved words are ASCII, aand hence the // bulk of content to be parsed. if ((ch >= QLatin1Char('a') && ch <= QLatin1Char('z')) || (ch >= QLatin1Char('A') && ch <= QLatin1Char('Z')) || ch == QLatin1Char('$') || ch == QLatin1Char('_')) return true; if (ch.unicode() < 128) return false; return ch.isLetterOrNumber(); } bool Lexer::isDecimalDigit(ushort c) { return (c >= '0' && c <= '9'); } bool Lexer::isHexDigit(QChar c) { return ((c >= QLatin1Char('0') && c <= QLatin1Char('9')) || (c >= QLatin1Char('a') && c <= QLatin1Char('f')) || (c >= QLatin1Char('A') && c <= QLatin1Char('F'))); } bool Lexer::isOctalDigit(ushort c) { return (c >= '0' && c <= '7'); } int Lexer::tokenEndLine() const { return _currentLineNumber; } int Lexer::tokenEndColumn() const { return _codePtr - _lastLinePtr; } QString Lexer::tokenText() const { if (_validTokenText) return _tokenText; if (_tokenKind == T_STRING_LITERAL) return QString(_tokenStartPtr + 1, _tokenLength - 2); return QString(_tokenStartPtr, _tokenLength); } Lexer::Error Lexer::errorCode() const { return _errorCode; } QString Lexer::errorMessage() const { return _errorMessage; } void Lexer::syncProhibitAutomaticSemicolon() { if (_parenthesesState == BalancedParentheses) { // we have seen something like "if (foo)", which means we should // never insert an automatic semicolon at this point, since it would // then be expanded into an empty statement (ECMA-262 7.9.1) _prohibitAutomaticSemicolon = true; _parenthesesState = IgnoreParentheses; } else { _prohibitAutomaticSemicolon = false; } } bool Lexer::prevTerminator() const { return _terminator; } bool Lexer::followsClosingBrace() const { return _followsClosingBrace; } bool Lexer::canInsertAutomaticSemicolon(int token) const { return token == T_RBRACE || token == EOF_SYMBOL || _terminator || _followsClosingBrace; } bool Lexer::scanDirectives(Directives *directives) { if (_qmlMode) { // the directives are a Javascript-only extension. return false; } lex(); // fetch the first token if (_tokenKind != T_DOT) return true; do { lex(); // skip T_DOT const int lineNumber = tokenStartLine(); if (! (_tokenKind == T_IDENTIFIER || _tokenKind == T_RESERVED_WORD)) return false; // expected a valid QML/JS directive const QString directiveName = tokenText(); if (! (directiveName == QLatin1String("pragma") || directiveName == QLatin1String("import"))) return false; // not a valid directive name // it must be a pragma or an import directive. if (directiveName == QLatin1String("pragma")) { // .pragma library if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("library"))) return false; // expected `library // we found a .pragma library directive directives->pragmaLibrary(); } else { Q_ASSERT(directiveName == QLatin1String("import")); lex(); // skip .import QString pathOrUri; QString version; bool fileImport = false; // file or uri import if (_tokenKind == T_STRING_LITERAL) { // .import T_STRING_LITERAL as T_IDENTIFIER fileImport = true; pathOrUri = tokenText(); } else if (_tokenKind == T_IDENTIFIER) { // .import T_IDENTIFIER (. T_IDENTIFIER)* T_NUMERIC_LITERAL as T_IDENTIFIER pathOrUri = tokenText(); lex(); // skip the first T_IDENTIFIER for (; _tokenKind == T_DOT; lex()) { if (lex() != T_IDENTIFIER) return false; pathOrUri += QLatin1Char('.'); pathOrUri += tokenText(); } if (_tokenKind != T_NUMERIC_LITERAL) return false; // expected the module version number version = tokenText(); } // // recognize the mandatory `as' followed by the module name // if (! (lex() == T_RESERVED_WORD && tokenText() == QLatin1String("as"))) return false; // expected `as' if (lex() != T_IDENTIFIER) return false; // expected module name const QString module = tokenText(); if (fileImport) directives->importFile(pathOrUri, module); else directives->importModule(pathOrUri, version, module); } if (tokenStartLine() != lineNumber) return false; // the directives cannot span over multiple lines // fetch the first token after the .pragma/.import directive lex(); } while (_tokenKind == T_DOT); return true; } } // namespace QbsQmlJS #include "qmljskeywords_p.h" qbs-src-1.13.1/src/lib/corelib/parser/qmljslexer_p.h000066400000000000000000000153471347155106100223120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMLJSLEXER_P_H #define QMLJSLEXER_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qmljsglobal_p.h" #include "qmljsgrammar_p.h" #include #include namespace QbsQmlJS { class Engine; class QML_PARSER_EXPORT Directives { public: virtual ~Directives() {} virtual void pragmaLibrary() { } virtual void importFile(const QString &jsfile, const QString &module) { Q_UNUSED(jsfile); Q_UNUSED(module); } virtual void importModule(const QString &uri, const QString &version, const QString &module) { Q_UNUSED(uri); Q_UNUSED(version); Q_UNUSED(module); } }; class QBS_AUTOTEST_EXPORT Lexer: public QmlJSGrammar { public: enum { T_ABSTRACT = T_RESERVED_WORD, T_BOOLEAN = T_RESERVED_WORD, T_BYTE = T_RESERVED_WORD, T_CHAR = T_RESERVED_WORD, T_CLASS = T_RESERVED_WORD, T_DOUBLE = T_RESERVED_WORD, T_ENUM = T_RESERVED_WORD, T_EXPORT = T_RESERVED_WORD, T_EXTENDS = T_RESERVED_WORD, T_FINAL = T_RESERVED_WORD, T_FLOAT = T_RESERVED_WORD, T_GOTO = T_RESERVED_WORD, T_IMPLEMENTS = T_RESERVED_WORD, T_INT = T_RESERVED_WORD, T_INTERFACE = T_RESERVED_WORD, T_LET = T_RESERVED_WORD, T_LONG = T_RESERVED_WORD, T_NATIVE = T_RESERVED_WORD, T_PACKAGE = T_RESERVED_WORD, T_PRIVATE = T_RESERVED_WORD, T_PROTECTED = T_RESERVED_WORD, T_SHORT = T_RESERVED_WORD, T_STATIC = T_RESERVED_WORD, T_SUPER = T_RESERVED_WORD, T_SYNCHRONIZED = T_RESERVED_WORD, T_THROWS = T_RESERVED_WORD, T_TRANSIENT = T_RESERVED_WORD, T_VOLATILE = T_RESERVED_WORD, T_YIELD = T_RESERVED_WORD }; enum Error { NoError, IllegalCharacter, UnclosedStringLiteral, IllegalEscapeSequence, IllegalUnicodeEscapeSequence, UnclosedComment, IllegalExponentIndicator, IllegalIdentifier }; enum RegExpBodyPrefix { NoPrefix, EqualPrefix }; enum RegExpFlag { RegExp_Global = 0x01, RegExp_IgnoreCase = 0x02, RegExp_Multiline = 0x04 }; public: Lexer(Engine *engine); bool qmlMode() const; QString code() const; void setCode(const QString &code, int lineno, bool qmlMode = true); int lex(); bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix); bool scanDirectives(Directives *directives); int regExpFlags() const { return _patternFlags; } QString regExpPattern() const { return _tokenText; } int tokenKind() const { return _tokenKind; } int tokenOffset() const { return _tokenStartPtr - _code.unicode(); } int tokenLength() const { return _tokenLength; } int tokenStartLine() const { return _tokenLine; } int tokenStartColumn() const { return _tokenStartPtr - _tokenLinePtr + 1; } int tokenEndLine() const; int tokenEndColumn() const; inline QStringRef tokenSpell() const { return _tokenSpell; } double tokenValue() const { return _tokenValue; } QString tokenText() const; Error errorCode() const; QString errorMessage() const; bool prevTerminator() const; bool followsClosingBrace() const; bool canInsertAutomaticSemicolon(int token) const; enum ParenthesesState { IgnoreParentheses, CountParentheses, BalancedParentheses }; protected: int classify(const QChar *s, int n, bool qmlMode); private: inline void scanChar(); int scanToken(); int scanNumber(QChar ch); bool isLineTerminator() const; static bool isIdentLetter(QChar c); static bool isDecimalDigit(ushort c); static bool isHexDigit(QChar c); static bool isOctalDigit(ushort c); static bool isUnicodeEscapeSequence(const QChar *chars); void syncProhibitAutomaticSemicolon(); QChar decodeUnicodeEscapeCharacter(bool *ok); private: Engine *_engine; QString _code; QString _tokenText; QString _errorMessage; QStringRef _tokenSpell; const QChar *_codePtr; const QChar *_lastLinePtr; const QChar *_tokenLinePtr; const QChar *_tokenStartPtr; QChar _char; Error _errorCode; int _currentLineNumber; double _tokenValue; // parentheses state ParenthesesState _parenthesesState; int _parenthesesCount; int _stackToken; int _patternFlags; int _tokenKind; int _tokenLength; int _tokenLine; bool _validTokenText; bool _prohibitAutomaticSemicolon; bool _restrictedKeyword; bool _terminator; bool _followsClosingBrace; bool _delimited; bool _qmlMode; }; } // namespace QbsQmlJS #endif // LEXER_H qbs-src-1.13.1/src/lib/corelib/parser/qmljsmemorypool_p.h000066400000000000000000000107261347155106100233710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMLJSMEMORYPOOL_P_H #define QMLJSMEMORYPOOL_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qmljsglobal_p.h" #include #include #include #include namespace QbsQmlJS { class QML_PARSER_EXPORT MemoryPool : public QSharedData { MemoryPool(const MemoryPool &other); void operator =(const MemoryPool &other); public: MemoryPool() : _blocks(nullptr), _allocatedBlocks(0), _blockCount(-1), _ptr(nullptr), _end(nullptr) { } ~MemoryPool() { if (_blocks) { for (int i = 0; i < _allocatedBlocks; ++i) { if (char *b = _blocks[i]) free(b); } free(_blocks); } } inline void *allocate(size_t size) { size = (size + 7) & ~7; if (_ptr && (_ptr + size < _end)) { void *addr = _ptr; _ptr += size; return addr; } return allocate_helper(size); } void reset() { _blockCount = -1; _ptr = _end = nullptr; } private: void *allocate_helper(size_t size) { Q_ASSERT(size < BLOCK_SIZE); if (++_blockCount == _allocatedBlocks) { if (! _allocatedBlocks) _allocatedBlocks = DEFAULT_BLOCK_COUNT; else _allocatedBlocks *= 2; _blocks = (char **) realloc(_blocks, sizeof(char *) * _allocatedBlocks); for (int index = _blockCount; index < _allocatedBlocks; ++index) _blocks[index] = nullptr; } char *&block = _blocks[_blockCount]; if (! block) block = (char *) malloc(BLOCK_SIZE); _ptr = block; _end = _ptr + BLOCK_SIZE; void *addr = _ptr; _ptr += size; return addr; } private: char **_blocks; int _allocatedBlocks; int _blockCount; char *_ptr; char *_end; enum { BLOCK_SIZE = 8 * 1024, DEFAULT_BLOCK_COUNT = 8 }; }; class QML_PARSER_EXPORT Managed { Managed(const Managed &other); void operator = (const Managed &other); public: Managed() {} ~Managed() {} void *operator new(size_t size, MemoryPool *pool) { return pool->allocate(size); } void operator delete(void *) {} void operator delete(void *, MemoryPool *) {} }; } // namespace QbsQmlJS #endif qbs-src-1.13.1/src/lib/corelib/parser/qmljsparser.cpp000066400000000000000000001404411347155106100224750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include "qmljsengine_p.h" #include "qmljslexer_p.h" #include "qmljsast_p.h" #include "qmljsmemorypool_p.h" #include "qmljsparser_p.h" #include // // This file is automatically generated from qmljs.g. // Changes will be lost. // namespace QbsQmlJS { void Parser::reallocateStack() { if (! stack_size) stack_size = 128; else stack_size <<= 1; sym_stack = reinterpret_cast (realloc(sym_stack, stack_size * sizeof(Value))); state_stack = reinterpret_cast (realloc(state_stack, stack_size * sizeof(int))); location_stack = reinterpret_cast (realloc(location_stack, stack_size * sizeof(AST::SourceLocation))); string_stack = reinterpret_cast (realloc( static_cast(string_stack), stack_size * sizeof(QStringRef))); } Parser::Parser(Engine *engine): driver(engine), pool(engine->pool()), tos(0), stack_size(0), sym_stack(nullptr), state_stack(nullptr), location_stack(nullptr), string_stack(nullptr), program(nullptr), first_token(nullptr), last_token(nullptr) { } Parser::~Parser() { if (stack_size) { free(sym_stack); free(state_stack); free(location_stack); free(string_stack); } } static inline AST::SourceLocation location(Lexer *lexer) { AST::SourceLocation loc; loc.offset = lexer->tokenOffset(); loc.length = lexer->tokenLength(); loc.startLine = lexer->tokenStartLine(); loc.startColumn = lexer->tokenStartColumn(); return loc; } AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) { QVarLengthArray nameIds; QVarLengthArray locations; AST::ExpressionNode *it = expr; while (AST::FieldMemberExpression *m = AST::cast(it)) { nameIds.append(m->name); locations.append(m->identifierToken); it = m->base; } if (AST::IdentifierExpression *idExpr = AST::cast(it)) { const auto q = new (pool) AST::UiQualifiedId(idExpr->name); q->identifierToken = idExpr->identifierToken; AST::UiQualifiedId *currentId = q; for (int i = nameIds.size() - 1; i != -1; --i) { currentId = new (pool) AST::UiQualifiedId(currentId, nameIds[i]); currentId->identifierToken = locations[i]; } return currentId->finish(); } return nullptr; } bool Parser::parse(int startToken) { Lexer *lexer = driver->lexer(); bool hadErrors = false; int yytoken = -1; int action = 0; token_buffer[0].token = startToken; first_token = &token_buffer[0]; if (startToken == T_FEED_JS_PROGRAM) { Directives ignoreDirectives; Directives *directives = driver->directives(); if (!directives) directives = &ignoreDirectives; lexer->scanDirectives(directives); token_buffer[1].token = lexer->tokenKind(); token_buffer[1].dval = lexer->tokenValue(); token_buffer[1].loc = location(lexer); token_buffer[1].spell = lexer->tokenSpell(); last_token = &token_buffer[2]; } else { last_token = &token_buffer[1]; } tos = -1; program = nullptr; do { if (++tos == stack_size) reallocateStack(); state_stack[tos] = action; _Lcheck_token: if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { yyprevlloc = yylloc; if (first_token == last_token) { yytoken = lexer->lex(); yylval = lexer->tokenValue(); yytokenspell = lexer->tokenSpell(); yylloc = location(lexer); } else { yytoken = first_token->token; yylval = first_token->dval; yytokenspell = first_token->spell; yylloc = first_token->loc; ++first_token; } } action = t_action(action, yytoken); if (action > 0) { if (action != ACCEPT_STATE) { yytoken = -1; sym(1).dval = yylval; stringRef(1) = yytokenspell; loc(1) = yylloc; } else { --tos; return ! hadErrors; } } else if (action < 0) { const int r = -action - 1; tos -= rhs[r]; switch (r) { case 0: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 1: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 2: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 3: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 4: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 5: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 6: { sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiImportList, sym(2).UiObjectMemberList->finish()); } break; case 8: { sym(1).Node = sym(1).UiImportList->finish(); } break; case 9: { sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImport); } break; case 10: { sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImportList, sym(2).UiImport); } break; case 13: { sym(1).UiImport->semicolonToken = loc(2); } break; case 15: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->semicolonToken = loc(3); } break; case 17: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->asToken = loc(3); sym(1).UiImport->importIdToken = loc(4); sym(1).UiImport->importId = stringRef(4); sym(1).UiImport->semicolonToken = loc(5); } break; case 19: { sym(1).UiImport->asToken = loc(2); sym(1).UiImport->importIdToken = loc(3); sym(1).UiImport->importId = stringRef(3); sym(1).UiImport->semicolonToken = loc(4); } break; case 20: { AST::UiImport *node = nullptr; if (const auto importIdLiteral = AST::cast(sym(2).Expression)) { node = new (pool) AST::UiImport(importIdLiteral->value); node->fileNameToken = loc(2); } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) { node = new (pool) AST::UiImport(qualifiedId); node->fileNameToken = loc(2); } sym(1).Node = node; if (node) { node->importToken = loc(1); } else { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), QStringLiteral("Expected a qualified name id or a string literal"))); return false; // ### remove me } } break; case 21: { sym(1).Node = nullptr; } break; case 22: { sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; case 23: { sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; case 24: { const auto node = new (pool) AST:: UiObjectMemberList( sym(1).UiObjectMemberList, sym(2).UiObjectMember); sym(1).Node = node; } break; case 25: { sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember); } break; case 26: { const auto node = new (pool) AST::UiArrayMemberList( sym(1).UiArrayMemberList, sym(3).UiObjectMember); node->commaToken = loc(2); sym(1).Node = node; } break; case 27: { const auto node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)0); node->lbraceToken = loc(1); node->rbraceToken = loc(2); sym(1).Node = node; } break; case 28: { const auto node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish()); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 29: { const auto node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId, sym(2).UiObjectInitializer); sym(1).Node = node; } break; case 31: { const auto node = new (pool) AST::UiArrayBinding( sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish()); node->colonToken = loc(2); node->lbracketToken = loc(3); node->rbracketToken = loc(5); sym(1).Node = node; } break; case 32: { const auto node = new (pool) AST::UiObjectBinding( sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); sym(1).Node = node; } break; case 33: { const auto node = new (pool) AST::UiObjectBinding( sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); node->hasOnToken = true; sym(1).Node = node; } break; case 41: { const auto node = new (pool) AST::UiScriptBinding( sym(1).UiQualifiedId, sym(3).Statement); node->colonToken = loc(2); sym(1).Node = node; } break; case 45: { sym(1).Node = nullptr; } break; case 46: { sym(1).Node = sym(1).UiParameterList->finish (); } break; case 47: { const auto node = new (pool) AST::UiParameterList(stringRef(1), stringRef(2)); node->propertyTypeToken = loc(1); node->identifierToken = loc(2); sym(1).Node = node; } break; case 48: { const auto node = new (pool) AST::UiParameterList(sym(1).UiParameterList, stringRef(3), stringRef(4)); node->commaToken = loc(2); node->identifierToken = loc(4); sym(1).Node = node; } break; case 50: { const auto node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(2); node->parameters = sym(4).UiParameterList; node->semicolonToken = loc(6); sym(1).Node = node; } break; case 52: { const auto node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 54: { const auto node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); node->identifierToken = loc(6); node->semicolonToken = loc(7); sym(1).Node = node; } break; case 56: { const auto node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->semicolonToken = loc(4); sym(1).Node = node; } break; case 58: { const auto node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4)); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->semicolonToken = loc(5); sym(1).Node = node; } break; case 59: { const auto node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3), sym(5).Statement); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->colonToken = loc(4); sym(1).Node = node; } break; case 60: { const auto node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isReadonlyMember = true; node->readonlyToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); sym(1).Node = node; } break; case 61: { const auto node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); sym(1).Node = node; } break; case 62: { const auto node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); node->identifierToken = loc(6); node->semicolonToken = loc(7); // insert a fake ';' before ':' const auto propertyName = new (pool) AST::UiQualifiedId(stringRef(6)); propertyName->identifierToken = loc(6); propertyName->next = nullptr; const auto binding = new (pool) AST::UiArrayBinding( propertyName, sym(9).UiArrayMemberList->finish()); binding->colonToken = loc(7); binding->lbracketToken = loc(8); binding->rbracketToken = loc(10); node->binding = binding; sym(1).Node = node; } break; case 63: { const auto node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->semicolonToken = loc(4); // insert a fake ';' before ':' const auto propertyName = new (pool) AST::UiQualifiedId(stringRef(3)); propertyName->identifierToken = loc(3); propertyName->next = nullptr; const auto binding = new (pool) AST::UiObjectBinding( propertyName, sym(5).UiQualifiedId, sym(6).UiObjectInitializer); binding->colonToken = loc(4); node->binding = binding; sym(1).Node = node; } break; case 64: { sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; case 65: { sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; case 71: { const auto node = new (pool) AST::ThisExpression(); node->thisToken = loc(1); sym(1).Node = node; } break; case 72: { const auto node = new (pool) AST::IdentifierExpression(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; case 73: { const auto node = new (pool) AST::NullExpression(); node->nullToken = loc(1); sym(1).Node = node; } break; case 74: { const auto node = new (pool) AST::TrueLiteral(); node->trueToken = loc(1); sym(1).Node = node; } break; case 75: { const auto node = new (pool) AST::FalseLiteral(); node->falseToken = loc(1); sym(1).Node = node; } break; case 76: { const auto node = new (pool) AST::NumericLiteral(sym(1).dval); node->literalToken = loc(1); sym(1).Node = node; } break; case 77: case 78: { const auto node = new (pool) AST::StringLiteral(stringRef(1)); node->literalToken = loc(1); sym(1).Node = node; } break; case 79: { bool rx = lexer->scanRegExp(Lexer::NoPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); return false; // ### remove me } loc(1).length = lexer->tokenLength(); yylloc = loc(1); // adjust the location of the current token const auto node = new (pool) AST::RegExpLiteral( driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; case 80: { bool rx = lexer->scanRegExp(Lexer::EqualPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); return false; } loc(1).length = lexer->tokenLength(); yylloc = loc(1); // adjust the location of the current token const auto node = new (pool) AST::RegExpLiteral( driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; case 81: { const auto node = new (pool) AST::ArrayLiteral((AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; } break; case 82: { const auto node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; case 83: { const auto node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; case 84: { const auto node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); node->commaToken = loc(3); node->rbracketToken = loc(4); sym(1).Node = node; } break; case 85: { const auto node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); node->commaToken = loc(3); node->rbracketToken = loc(5); sym(1).Node = node; } break; case 86: { AST::ObjectLiteral *node = nullptr; if (sym(2).Node) node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); else node = new (pool) AST::ObjectLiteral(); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 87: { const auto node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); node->lbraceToken = loc(1); node->rbraceToken = loc(4); sym(1).Node = node; } break; case 88: { const auto node = new (pool) AST::NestedExpression(sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; } break; case 89: { if (const auto *mem = AST::cast(sym(1).Expression)) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, QStringLiteral("Ignored annotation"))); sym(1).Expression = mem->base; } if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) { sym(1).UiQualifiedId = qualifiedId; } else { sym(1).UiQualifiedId = nullptr; diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), QStringLiteral("Expected a qualified name id"))); return false; // ### recover } } break; case 90: { sym(1).Node = new (pool) AST::ElementList((AST::Elision *) 0, sym(1).Expression); } break; case 91: { sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression); } break; case 92: { const auto node = new (pool) AST::ElementList(sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 93: { const auto node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 94: { const auto node = new (pool) AST::Elision(); node->commaToken = loc(1); sym(1).Node = node; } break; case 95: { const auto node = new (pool) AST::Elision(sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; case 96: { const auto node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; case 97: { const auto node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; case 98: { const auto node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 99: case 100: { const auto node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 101: { const auto node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 102: { const auto node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 103: { const auto node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 139: { const auto node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; case 140: { const auto node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; case 141: { const auto node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); node->rparenToken = loc(5); sym(1).Node = node; } break; case 143: { const auto node = new (pool) AST::NewExpression(sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; case 144: { const auto node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 145: { const auto node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 146: { const auto node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; case 147: { const auto node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; case 148: { sym(1).Node = nullptr; } break; case 149: { sym(1).Node = sym(1).ArgumentList->finish(); } break; case 150: { sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression); } break; case 151: { const auto node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 155: { const auto node = new (pool) AST::PostIncrementExpression(sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; case 156: { const auto node = new (pool) AST::PostDecrementExpression(sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; case 158: { const auto node = new (pool) AST::DeleteExpression(sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; case 159: { const auto node = new (pool) AST::VoidExpression(sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; case 160: { const auto node = new (pool) AST::TypeOfExpression(sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; case 161: { const auto node = new (pool) AST::PreIncrementExpression(sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; case 162: { const auto node = new (pool) AST::PreDecrementExpression(sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; case 163: { const auto node = new (pool) AST::UnaryPlusExpression(sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; case 164: { const auto node = new (pool) AST::UnaryMinusExpression(sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; case 165: { const auto node = new (pool) AST::TildeExpression(sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; case 166: { const auto node = new (pool) AST::NotExpression(sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; case 168: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 169: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 170: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 172: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 173: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 175: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 176: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 177: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 179: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 180: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 181: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 182: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 183: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 184: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 186: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 187: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 188: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 189: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 190: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 192: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 193: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 194: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 195: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 197: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 198: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 199: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 200: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 202: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 204: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 206: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 208: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 210: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 212: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 214: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 216: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 218: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 220: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 222: { const auto node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; case 224: { const auto node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; case 226: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 228: { const auto node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 229: { sym(1).ival = QSOperator::Assign; } break; case 230: { sym(1).ival = QSOperator::InplaceMul; } break; case 231: { sym(1).ival = QSOperator::InplaceDiv; } break; case 232: { sym(1).ival = QSOperator::InplaceMod; } break; case 233: { sym(1).ival = QSOperator::InplaceAdd; } break; case 234: { sym(1).ival = QSOperator::InplaceSub; } break; case 235: { sym(1).ival = QSOperator::InplaceLeftShift; } break; case 236: { sym(1).ival = QSOperator::InplaceRightShift; } break; case 237: { sym(1).ival = QSOperator::InplaceURightShift; } break; case 238: { sym(1).ival = QSOperator::InplaceAnd; } break; case 239: { sym(1).ival = QSOperator::InplaceXor; } break; case 240: { sym(1).ival = QSOperator::InplaceOr; } break; case 242: { const auto node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 243: { sym(1).Node = nullptr; } break; case 246: { const auto node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 247: { sym(1).Node = nullptr; } break; case 264: { const auto node = new (pool) AST::Block(sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 265: { sym(1).Node = new (pool) AST::StatementList(sym(1).Statement); } break; case 266: { sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement); } break; case 267: { sym(1).Node = nullptr; } break; case 268: { sym(1).Node = sym(1).StatementList->finish (); } break; case 270: { const auto node = new (pool) AST::VariableStatement( sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 271: { sym(1).ival = T_CONST; } break; case 272: { sym(1).ival = T_VAR; } break; case 273: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; case 274: { const auto node = new (pool) AST::VariableDeclarationList( sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; case 275: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; case 276: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; case 277: { const auto node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; case 278: { const auto node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; case 279: { // ### TODO: AST for initializer sym(1) = sym(2); } break; case 280: { sym(1).Node = nullptr; } break; case 282: { // ### TODO: AST for initializer sym(1) = sym(2); } break; case 283: { sym(1).Node = nullptr; } break; case 285: { const auto node = new (pool) AST::EmptyStatement(); node->semicolonToken = loc(1); sym(1).Node = node; } break; case 287: { const auto node = new (pool) AST::ExpressionStatement(sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 288: { const auto node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); node->elseToken = loc(6); sym(1).Node = node; } break; case 289: { const auto node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 291: { const auto node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); node->lparenToken = loc(4); node->rparenToken = loc(6); node->semicolonToken = loc(7); sym(1).Node = node; } break; case 292: { const auto node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 293: { const auto node = new (pool) AST::ForStatement(sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->firstSemicolonToken = loc(4); node->secondSemicolonToken = loc(6); node->rparenToken = loc(8); sym(1).Node = node; } break; case 294: { const auto node = new (pool) AST::LocalForStatement( sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->varToken = loc(3); node->firstSemicolonToken = loc(5); node->secondSemicolonToken = loc(7); node->rparenToken = loc(9); sym(1).Node = node; } break; case 295: { const auto node = new (pool) AST::ForEachStatement(sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->inToken = loc(4); node->rparenToken = loc(6); sym(1).Node = node; } break; case 296: { const auto node = new (pool) AST::LocalForEachStatement( sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->varToken = loc(3); node->inToken = loc(5); node->rparenToken = loc(7); sym(1).Node = node; } break; case 298: { const auto node = new (pool) AST::ContinueStatement(); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 300: { const auto node = new (pool) AST::ContinueStatement(stringRef(2)); node->continueToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 302: { const auto node = new (pool) AST::BreakStatement(QStringRef()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 304: { const auto node = new (pool) AST::BreakStatement(stringRef(2)); node->breakToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 306: { const auto node = new (pool) AST::ReturnStatement(sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 307: { const auto node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 308: { const auto node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 309: { const auto node = new (pool) AST::CaseBlock(sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 310: { const auto node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; } break; case 311: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause); } break; case 312: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause); } break; case 313: { sym(1).Node = nullptr; } break; case 314: { sym(1).Node = sym(1).CaseClauses->finish (); } break; case 315: { const auto node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; } break; case 316: { const auto node = new (pool) AST::DefaultClause(sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; case 317: case 318: { const auto node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; case 319: { const auto node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; case 321: { const auto node = new (pool) AST::ThrowStatement(sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 322: { const auto node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; case 323: { const auto node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; case 324: { const auto node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; case 325: { const auto node = new (pool) AST::Catch(stringRef(3), sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); node->identifierToken = loc(3); node->rparenToken = loc(4); sym(1).Node = node; } break; case 326: { const auto node = new (pool) AST::Finally(sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; case 328: { const auto node = new (pool) AST::DebuggerStatement(); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 329: { const auto node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); node->lparenToken = loc(3); node->rparenToken = loc(5); node->lbraceToken = loc(6); node->rbraceToken = loc(8); sym(1).Node = node; } break; case 330: { const auto node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); if (! stringRef(2).isNull()) node->identifierToken = loc(2); node->lparenToken = loc(3); node->rparenToken = loc(5); node->lbraceToken = loc(6); node->rbraceToken = loc(8); sym(1).Node = node; } break; case 331: { const auto node = new (pool) AST::FormalParameterList(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; case 332: { const auto node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3)); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; case 333: { sym(1).Node = nullptr; } break; case 334: { sym(1).Node = sym(1).FormalParameterList->finish (); } break; case 335: { sym(1).Node = nullptr; } break; case 337: { sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ()); } break; case 339: { sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ()); } break; case 340: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement); } break; case 341: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement); } break; case 342: { sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement); } break; case 343: { sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration); } break; case 344: { stringRef(1) = QStringRef(); } break; case 346: { sym(1).Node = nullptr; } break; } // switch action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); } // if } while (action != 0); if (first_token == last_token) { const int errorState = state_stack[tos]; // automatic insertion of `;' if (yytoken != -1 && t_action(errorState, T_AUTOMATIC_SEMICOLON) && lexer->canInsertAutomaticSemicolon(yytoken)) { SavedToken &tk = token_buffer[0]; tk.token = yytoken; tk.dval = yylval; tk.spell = yytokenspell; tk.loc = yylloc; yylloc = yyprevlloc; yylloc.offset += yylloc.length; yylloc.startColumn += yylloc.length; yylloc.length = 0; //const QString msg = qApp->translate("QmlParser", "Missing `;'"); //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); first_token = &token_buffer[0]; last_token = &token_buffer[1]; yytoken = T_SEMICOLON; yylval = 0; action = errorState; goto _Lcheck_token; } hadErrors = true; token_buffer[0].token = yytoken; token_buffer[0].dval = yylval; token_buffer[0].spell = yytokenspell; token_buffer[0].loc = yylloc; token_buffer[1].token = yytoken = lexer->lex(); token_buffer[1].dval = yylval = lexer->tokenValue(); token_buffer[1].spell = yytokenspell = lexer->tokenSpell(); token_buffer[1].loc = yylloc = location(lexer); if (t_action(errorState, yytoken)) { QString msg; int token = token_buffer[0].token; if (token < 0 || token >= TERMINAL_COUNT) msg = qApp->translate("QmlParser", "Syntax error"); else msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); action = errorState; goto _Lcheck_token; } static int tokens[] = { T_PLUS, T_EQ, T_COMMA, T_COLON, T_SEMICOLON, T_RPAREN, T_RBRACKET, T_RBRACE, T_NUMERIC_LITERAL, T_IDENTIFIER, T_LPAREN, T_LBRACKET, T_LBRACE, EOF_SYMBOL }; for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { int a = t_action(errorState, *tk); if (a > 0 && t_action(a, yytoken)) { const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = *tk; yylval = 0; yylloc = token_buffer[0].loc; yylloc.length = 0; first_token = &token_buffer[0]; last_token = &token_buffer[2]; action = errorState; goto _Lcheck_token; } } for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION || tk == T_FEED_JS_SOURCE_ELEMENT) continue; int a = t_action(errorState, tk); if (a > 0 && t_action(a, yytoken)) { const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = tk; yylval = 0; yylloc = token_buffer[0].loc; yylloc.length = 0; action = errorState; goto _Lcheck_token; } } const QString msg = qApp->translate("QmlParser", "Syntax error"); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); } return false; } } // namespace QbsQmlJS qbs-src-1.13.1/src/lib/corelib/parser/qmljsparser_p.h000066400000000000000000000156661347155106100224730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // // // This file is automatically generated from qmljs.g. // Changes will be lost. // #ifndef QMLJSPARSER_P_H #define QMLJSPARSER_P_H #include "qmljsglobal_p.h" #include "qmljsgrammar_p.h" #include "qmljsast_p.h" #include "qmljsengine_p.h" #include #include #include namespace QbsQmlJS { class Engine; class QBS_AUTOTEST_EXPORT Parser: protected QmlJSGrammar { public: union Value { int ival; double dval; AST::ArgumentList *ArgumentList; AST::CaseBlock *CaseBlock; AST::CaseClause *CaseClause; AST::CaseClauses *CaseClauses; AST::Catch *Catch; AST::DefaultClause *DefaultClause; AST::ElementList *ElementList; AST::Elision *Elision; AST::ExpressionNode *Expression; AST::Finally *Finally; AST::FormalParameterList *FormalParameterList; AST::FunctionBody *FunctionBody; AST::FunctionDeclaration *FunctionDeclaration; AST::Node *Node; AST::PropertyName *PropertyName; AST::PropertyNameAndValueList *PropertyNameAndValueList; AST::SourceElement *SourceElement; AST::SourceElements *SourceElements; AST::Statement *Statement; AST::StatementList *StatementList; AST::Block *Block; AST::VariableDeclaration *VariableDeclaration; AST::VariableDeclarationList *VariableDeclarationList; AST::UiProgram *UiProgram; AST::UiImportList *UiImportList; AST::UiImport *UiImport; AST::UiParameterList *UiParameterList; AST::UiPublicMember *UiPublicMember; AST::UiObjectDefinition *UiObjectDefinition; AST::UiObjectInitializer *UiObjectInitializer; AST::UiObjectBinding *UiObjectBinding; AST::UiScriptBinding *UiScriptBinding; AST::UiArrayBinding *UiArrayBinding; AST::UiObjectMember *UiObjectMember; AST::UiObjectMemberList *UiObjectMemberList; AST::UiArrayMemberList *UiArrayMemberList; AST::UiQualifiedId *UiQualifiedId; }; public: Parser(Engine *engine); ~Parser(); // parse a UI program bool parse() { return parse(T_FEED_UI_PROGRAM); } bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); } bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); } bool parseProgram() { return parse(T_FEED_JS_PROGRAM); } AST::UiProgram *ast() const { return AST::cast(program); } AST::Statement *statement() const { if (! program) return nullptr; return program->statementCast(); } AST::ExpressionNode *expression() const { if (! program) return nullptr; return program->expressionCast(); } AST::UiObjectMember *uiObjectMember() const { if (! program) return nullptr; return program->uiObjectMemberCast(); } AST::Node *rootNode() const { return program; } QList diagnosticMessages() const { return diagnostic_messages; } inline DiagnosticMessage diagnosticMessage() const { foreach (const DiagnosticMessage &d, diagnostic_messages) { if (d.kind != DiagnosticMessage::Warning) return d; } return DiagnosticMessage(); } inline QString errorMessage() const { return diagnosticMessage().message; } inline int errorLineNumber() const { return diagnosticMessage().loc.startLine; } inline int errorColumnNumber() const { return diagnosticMessage().loc.startColumn; } protected: bool parse(int startToken); void reallocateStack(); inline Value &sym(int index) { return sym_stack [tos + index - 1]; } inline QStringRef &stringRef(int index) { return string_stack [tos + index - 1]; } inline AST::SourceLocation &loc(int index) { return location_stack [tos + index - 1]; } AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); protected: Engine *driver; MemoryPool *pool; int tos; int stack_size; Value *sym_stack; int *state_stack; AST::SourceLocation *location_stack; QStringRef *string_stack; AST::Node *program; // error recovery enum { TOKEN_BUFFER_SIZE = 3 }; struct SavedToken { int token; double dval; AST::SourceLocation loc; QStringRef spell; }; double yylval; QStringRef yytokenspell; AST::SourceLocation yylloc; AST::SourceLocation yyprevlloc; SavedToken token_buffer[TOKEN_BUFFER_SIZE]; SavedToken *first_token; SavedToken *last_token; QList diagnostic_messages; }; } // end of namespace QbsQmlJS #define J_SCRIPT_REGEXPLITERAL_RULE1 79 #define J_SCRIPT_REGEXPLITERAL_RULE2 80 #endif // QMLJSPARSER_P_H qbs-src-1.13.1/src/lib/corelib/qbs.h000066400000000000000000000052451347155106100170720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_H #define QBS_H #include "api/jobs.h" #include "api/languageinfo.h" #include "api/project.h" #include "api/projectdata.h" #include "api/rulecommand.h" #include "api/runenvironment.h" #include "logging/ilogsink.h" #include "tools/architectures.h" #include "tools/buildoptions.h" #include "tools/cleanoptions.h" #include "tools/codelocation.h" #include "tools/commandechomode.h" #include "tools/error.h" #include "tools/generateoptions.h" #include "tools/installoptions.h" #include "tools/preferences.h" #include "tools/processresult.h" #include "tools/profile.h" #include "tools/projectgeneratormanager.h" #include "tools/settings.h" #include "tools/settingsmodel.h" #include "tools/settingsrepresentation.h" #include "tools/setupprojectparameters.h" #include "tools/toolchains.h" #include "tools/version.h" #endif // QBS_H qbs-src-1.13.1/src/lib/corelib/tools/000077500000000000000000000000001347155106100172665ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/corelib/tools/applecodesignutils.cpp000066400000000000000000000136571347155106100237040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "applecodesignutils.h" #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { QByteArray smimeMessageContent(const QByteArray &data) { QCFType decoder = NULL; if (CMSDecoderCreate(&decoder) != noErr) return {}; if (CMSDecoderUpdateMessage(decoder, data.constData(), data.size()) != noErr) return {}; if (CMSDecoderFinalizeMessage(decoder) != noErr) return {}; QCFType content = NULL; if (CMSDecoderCopyContent(decoder, &content) != noErr) return {}; return QByteArray::fromCFData(content); } QVariantMap certificateInfo(const QByteArray &data) { const QSslCertificate cert(data, QSsl::Der); // Also potentially useful, but these are for signing pkgs which aren't used here // 1.2.840.113635.100.4.9 - 3rd Party Mac Developer Installer: // 1.2.840.113635.100.4.13 - Developer ID Installer: for (const auto &extension : cert.extensions()) { if (extension.name() == QStringLiteral("extendedKeyUsage")) { if (!extension.value().toStringList().contains(QStringLiteral("Code Signing"))) return {}; } } const auto subjectInfo = [](const QSslCertificate &cert) { QVariantMap map; for (const auto &attr : cert.subjectInfoAttributes()) map.insert(QString::fromUtf8(attr), cert.subjectInfo(attr).front()); return map; }; return { {QStringLiteral("SHA1"), cert.digest(QCryptographicHash::Sha1).toHex().toUpper()}, {QStringLiteral("subjectInfo"), subjectInfo(cert)}, {QStringLiteral("validBefore"), cert.effectiveDate()}, {QStringLiteral("validAfter"), cert.expiryDate()} }; } QVariantMap identitiesProperties() { // Apple documentation states that the Sec* family of functions are not thread-safe on macOS // https://developer.apple.com/library/mac/documentation/Security/Reference/certifkeytrustservices/ static std::mutex securityMutex; std::lock_guard locker(securityMutex); Q_UNUSED(locker); const void *keys[] = {kSecClass, kSecMatchLimit, kSecAttrCanSign}; const void *values[] = {kSecClassIdentity, kSecMatchLimitAll, kCFBooleanTrue}; QCFType query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); QCFType result = NULL; if (SecItemCopyMatching(query, &result) != errSecSuccess) return {}; QVariantMap items; const auto tryAppend = [&](SecIdentityRef identity) { if (!identity) return; QCFType certificate = NULL; if (SecIdentityCopyCertificate(identity, &certificate) != errSecSuccess) return; QCFType certificateData = SecCertificateCopyData(certificate); if (!certificateData) return; auto props = certificateInfo(QByteArray::fromRawCFData(certificateData)); if (!props.empty()) items.insert(props[QStringLiteral("SHA1")].toString(), props); }; if (CFGetTypeID(result) == SecIdentityGetTypeID()) { tryAppend((SecIdentityRef)result.operator const void *()); } else if (CFGetTypeID(result) == CFArrayGetTypeID()) { for (CFIndex i = 0; i < CFArrayGetCount((CFArrayRef)result.operator const void *()); ++i) tryAppend((SecIdentityRef)CFArrayGetValueAtIndex(result.as(), i)); } return items; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/applecodesignutils.h000066400000000000000000000043411347155106100233370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_APPLECODESIGNUTILS_H #define QBS_APPLECODESIGNUTILS_H #include "qbs_export.h" #include namespace qbs { namespace Internal { QByteArray smimeMessageContent(const QByteArray &data); QVariantMap certificateInfo(const QByteArray &data); QVariantMap identitiesProperties(); } // namespace Internal } // namespace qbs #endif // QBS_APPLECODESIGNUTILS_H qbs-src-1.13.1/src/lib/corelib/tools/architectures.cpp000066400000000000000000000134161347155106100226440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "architectures.h" #include "stringconstants.h" #include #include namespace qbs { using namespace Internal; QString canonicalTargetArchitecture(const QString &architecture, const QString &endianness, const QString &vendor, const QString &system, const QString &abi) { const QString arch = canonicalArchitecture(architecture); const bool isApple = (vendor == QStringLiteral("apple") || system == QStringLiteral("darwin") || system == QStringLiteral("macosx") || system == QStringLiteral("ios") || system == QStringLiteral("tvos") || system == QStringLiteral("watchos") || abi == QStringLiteral("macho")); const bool isQnx = (system == QStringLiteral("nto") || abi.startsWith(QStringLiteral("qnx"))); if (arch == QStringLiteral("armv7a")) { if (isApple) return StringConstants::armv7Arch(); if (isQnx) return StringConstants::armArch(); } if (arch == StringConstants::arm64Arch() && isQnx) return StringConstants::aarch64Arch(); if (arch == StringConstants::x86Arch()) { if (isQnx) return StringConstants::i586Arch(); return StringConstants::i386Arch(); } if (arch == StringConstants::mipsArch() || arch == StringConstants::mips64Arch()) { if (endianness == QStringLiteral("big")) return arch + QStringLiteral("eb"); if (endianness == QStringLiteral("little")) return arch + QStringLiteral("el"); } if (arch == StringConstants::ppcArch()) return StringConstants::powerPcArch(); if (arch == StringConstants::ppc64Arch() && endianness == QStringLiteral("little")) return arch + QStringLiteral("le"); return arch; } QString canonicalArchitecture(const QString &architecture) { QMap archMap; archMap.insert(StringConstants::x86Arch(), QStringList() << StringConstants::i386Arch() << QStringLiteral("i486") << StringConstants::i586Arch() << QStringLiteral("i686") << QStringLiteral("ia32") << QStringLiteral("ia-32") << QStringLiteral("x86_32") << QStringLiteral("x86-32") << QStringLiteral("intel32") << QStringLiteral("mingw32")); archMap.insert(StringConstants::x86_64Arch(), QStringList() << QStringLiteral("x86-64") << QStringLiteral("x64") << StringConstants::amd64Arch() << QStringLiteral("ia32e") << QStringLiteral("em64t") << QStringLiteral("intel64") << QStringLiteral("mingw64")); archMap.insert(StringConstants::arm64Arch(), QStringList() << StringConstants::aarch64Arch()); archMap.insert(QStringLiteral("ia64"), QStringList() << QStringLiteral("ia-64") << QStringLiteral("itanium")); archMap.insert(StringConstants::ppcArch(), QStringList() << StringConstants::powerPcArch()); archMap.insert(StringConstants::ppc64Arch(), QStringList() << QStringLiteral("ppc64le") << QStringLiteral("powerpc64") << QStringLiteral("powerpc64le")); archMap.insert(StringConstants::mipsArch(), QStringList() << QStringLiteral("mipseb") << QStringLiteral("mipsel")); archMap.insert(StringConstants::mips64Arch(), QStringList() << QStringLiteral("mips64eb") << QStringLiteral("mips64el")); QMapIterator i(archMap); while (i.hasNext()) { i.next(); if (i.value().contains(architecture.toLower())) return i.key(); } return architecture; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/architectures.h000066400000000000000000000046741347155106100223170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ARCHITECTURES_H #define QBS_ARCHITECTURES_H #include "qbs_export.h" #include namespace qbs { QBS_EXPORT QString canonicalTargetArchitecture(const QString &architecture, const QString &endianness, const QString &vendor, const QString &system, const QString &abi); QBS_EXPORT QString canonicalArchitecture(const QString &architecture); } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/tools/buildgraphlocker.cpp000066400000000000000000000141761347155106100233240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "buildgraphlocker.h" #include "error.h" #include "hostosinfo.h" #include "processutils.h" #include "progressobserver.h" #include "stringconstants.h" #include #include #include #include #include namespace qbs { namespace Internal { DirectoryManager::DirectoryManager(const QString &dir, const Logger &logger) : m_dir(dir), m_logger(logger) { rememberCreatedDirectories(); } DirectoryManager::~DirectoryManager() { removeEmptyCreatedDirectories(); } void DirectoryManager::rememberCreatedDirectories() { QString parentDir = m_dir; while (!QFileInfo::exists(parentDir)) { m_createdParentDirs.push(parentDir); parentDir = QDir::cleanPath(parentDir + StringConstants::slashDotDot()); } } void DirectoryManager::removeEmptyCreatedDirectories() { QDir root = QDir::root(); while (!m_createdParentDirs.empty()) { const QString parentDir = m_createdParentDirs.front(); m_createdParentDirs.pop(); QDirIterator it(parentDir, QDir::AllEntries | QDir::NoDotAndDotDot | QDir::System, QDirIterator::Subdirectories); if (it.hasNext()) break; if (!root.rmdir(parentDir) && m_logger.logSink()) { m_logger.printWarning(ErrorInfo(Tr::tr("Failed to remove empty directory '%1'.") .arg(parentDir))); } } } static void tryCreateBuildDirectory(const QString &buildDir, const QString &buildGraphFilePath) { if (!QDir::root().mkpath(buildDir)) { throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': Failed to create directory.") .arg(buildGraphFilePath)); } } static bool appNamesAreEqual(const QString &app1, const QString &app2) { return QString::compare(app1, app2, HostOsInfo::fileNameCaseSensitivity()) == 0; } BuildGraphLocker::BuildGraphLocker(const QString &buildGraphFilePath, const Logger &logger, bool waitIndefinitely, ProgressObserver *observer) : m_lockFile(buildGraphFilePath + QStringLiteral(".lock")) , m_logger(logger) , m_dirManager(QFileInfo(buildGraphFilePath).absolutePath(), logger) { if (waitIndefinitely) m_logger.qbsDebug() << "Waiting to acquire lock file..."; m_lockFile.setStaleLockTime(0); int attemptsToGetInfo = 0; do { if (observer && observer->canceled()) break; tryCreateBuildDirectory(m_dirManager.dir(), buildGraphFilePath); if (m_lockFile.tryLock(250)) return; switch (m_lockFile.error()) { case QLockFile::LockFailedError: { if (waitIndefinitely) continue; qint64 pid; QString hostName; QString appName; if (m_lockFile.getLockInfo(&pid, &hostName, &appName)) { if (appNamesAreEqual(appName, processNameByPid(pid))) { throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': " "Already locked by '%2' (PID %3).") .arg(buildGraphFilePath, appName).arg(pid)); } // The process id was reused by some other process. m_logger.qbsInfo() << Tr::tr("Removing stale lock file."); m_lockFile.removeStaleLockFile(); } break; } case QLockFile::PermissionError: throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': Permission denied.") .arg(buildGraphFilePath)); case QLockFile::UnknownError: case QLockFile::NoError: throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1' (reason unknown).") .arg(buildGraphFilePath)); } } while (++attemptsToGetInfo < 10 || waitIndefinitely); // This very unlikely case arises if tryLock() repeatedly returns LockFailedError // with the subsequent getLockInfo() failing as well. throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1' (reason unknown).") .arg(buildGraphFilePath)); } BuildGraphLocker::~BuildGraphLocker() { m_lockFile.unlock(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/buildgraphlocker.h000066400000000000000000000054601347155106100227650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BUILDGRAPHLOCKER_H #define QBS_BUILDGRAPHLOCKER_H #include #include #include #include namespace qbs { namespace Internal { class ProgressObserver; class DirectoryManager { public: DirectoryManager(const QString &dir, const Logger &logger); ~DirectoryManager(); QString dir() const { return m_dir; } private: void rememberCreatedDirectories(); void removeEmptyCreatedDirectories(); std::queue m_createdParentDirs; const QString m_dir; Logger m_logger; }; class BuildGraphLocker { public: explicit BuildGraphLocker(const QString &buildGraphFilePath, const Logger &logger, bool waitIndefinitely, ProgressObserver *observer); ~BuildGraphLocker(); private: QLockFile m_lockFile; Logger m_logger; DirectoryManager m_dirManager; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/tools/buildoptions.cpp000066400000000000000000000267551347155106100225240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "buildoptions.h" #include #include namespace qbs { namespace Internal { class BuildOptionsPrivate : public QSharedData { public: BuildOptionsPrivate() : maxJobCount(0), dryRun(false), keepGoing(false), forceTimestampCheck(false), forceOutputCheck(false), logElapsedTime(false), echoMode(defaultCommandEchoMode()), install(true), removeExistingInstallation(false), onlyExecuteRules(false) { } QStringList changedFiles; QStringList filesToConsider; QStringList activeFileTags; JobLimits jobLimits; QString settingsDir; int maxJobCount; bool dryRun; bool keepGoing; bool forceTimestampCheck; bool forceOutputCheck; bool logElapsedTime; CommandEchoMode echoMode; bool install; bool removeExistingInstallation; bool onlyExecuteRules; bool jobLimitsFromProjectTakePrecedence = false; }; } // namespace Internal /*! * \class BuildOptions * \brief The \c BuildOptions class comprises parameters that influence the behavior of * build and clean operations. */ /*! * \brief Creates a \c BuildOptions object and initializes its members to sensible default values. */ BuildOptions::BuildOptions() : d(new Internal::BuildOptionsPrivate) { } BuildOptions::BuildOptions(const BuildOptions &other) : d(other.d) { } BuildOptions &BuildOptions::operator=(const BuildOptions &other) { d = other.d; return *this; } BuildOptions::~BuildOptions() { } /*! * \brief If non-empty, qbs pretends that only these files have changed. * By default, this list is empty. */ QStringList BuildOptions::changedFiles() const { return d->changedFiles; } /*! * \brief If the given list is empty, qbs will pretend only the listed files are changed. * \note The list elements must be absolute file paths. */ void BuildOptions::setChangedFiles(const QStringList &changedFiles) { d->changedFiles = changedFiles; } /*! * \brief The list of files to consider. * \sa setFilesToConsider. * By default, this list is empty. */ QStringList BuildOptions::filesToConsider() const { return d->filesToConsider; } /*! * \brief If the given list is non-empty, qbs will run only commands whose rule has at least one * of these files as an input. * \note The list elements must be absolute file paths. */ void BuildOptions::setFilesToConsider(const QStringList &files) { d->filesToConsider = files; } /*! * \brief The list of active file tags. * \sa setActiveFileTags */ QStringList BuildOptions::activeFileTags() const { return d->activeFileTags; } /*! * \brief Set the list of active file tags. * If this list is non-empty, then every transformer with non-matching output file tags is skipped. * E.g. call \c setFilesToConsider() with "foo.cpp" and \c setActiveFileTags() with "obj" to * run the compiler on foo.cpp without further processing like linking. * \sa activeFileTags */ void BuildOptions::setActiveFileTags(const QStringList &fileTags) { d->activeFileTags = fileTags; } /*! * \brief Returns the default value for \c maxJobCount. * This value will be used when \c maxJobCount has not been set explicitly. */ int BuildOptions::defaultMaxJobCount() { return QThread::idealThreadCount(); } /*! * \brief Returns the maximum number of build commands to run concurrently. * If the value is not valid (i.e. <= 0), a sensible one will be derived at build time * from the number of available processor cores at build time. * The default is 0. * \sa BuildOptions::defaultMaxJobCount */ int BuildOptions::maxJobCount() const { return d->maxJobCount; } /*! * \brief Controls how many build commands can be run in parallel. * A value <= 0 leaves the decision to qbs. */ void BuildOptions::setMaxJobCount(int jobCount) { d->maxJobCount = jobCount; } /*! * \brief The base directory for qbs settings. * This value is used to locate profiles and preferences. */ QString BuildOptions::settingsDirectory() const { return d->settingsDir; } /*! * \brief Sets the base directory for qbs settings. * \param settingsBaseDir Will be used to locate profiles and preferences. */ void BuildOptions::setSettingsDirectory(const QString &settingsBaseDir) { d->settingsDir = settingsBaseDir; } JobLimits BuildOptions::jobLimits() const { return d->jobLimits; } void BuildOptions::setJobLimits(const JobLimits &jobLimits) { d->jobLimits = jobLimits; } bool BuildOptions::projectJobLimitsTakePrecedence() const { return d->jobLimitsFromProjectTakePrecedence; } void BuildOptions::setProjectJobLimitsTakePrecedence(bool toggle) { d->jobLimitsFromProjectTakePrecedence = toggle; } /*! * \brief Returns true iff qbs will not actually execute any commands, but just show what * would happen. * The default is false. */ bool BuildOptions::dryRun() const { return d->dryRun; } /*! * \brief Controls whether qbs will actually build something. * If the argument is true, qbs will just emit information about what it would do. Otherwise, * the build is actually done. * \note After you build with this setting enabled, the next call to \c build() on the same * \c Project object will do nothing, since the internal state needs to be updated the same way * as if an actual build had happened. You'll need to create a new \c Project object to do * a real build afterwards. */ void BuildOptions::setDryRun(bool dryRun) { d->dryRun = dryRun; } /*! * \brief Returns true iff a build will continue after an error. * E.g. a failed compile command will result in a warning message being printed, instead of * stopping the build process right away. However, there might still be fatal errors after which the * build process cannot continue. * The default is \c false. */ bool BuildOptions::keepGoing() const { return d->keepGoing; } /*! * \brief Controls whether a qbs will try to continue building after an error has occurred. */ void BuildOptions::setKeepGoing(bool keepGoing) { d->keepGoing = keepGoing; } /*! * \brief Returns true if qbs is to use physical timestamps instead of the timestamps stored in the * build graph. * The default is \c false. */ bool BuildOptions::forceTimestampCheck() const { return d->forceTimestampCheck; } /*! * \brief Controls whether qbs should use physical timestamps for up-to-date checks. */ void BuildOptions::setForceTimestampCheck(bool enabled) { d->forceTimestampCheck = enabled; } /*! * \brief Returns true if qbs will test whether rules actually create their * declared output artifacts. * The default is \c false. */ bool BuildOptions::forceOutputCheck() const { return d->forceOutputCheck; } /*! * \brief Controls whether qbs should test whether rules actually create their * declared output artifacts. Enabling this may introduce some small I/O overhead during the build. */ void BuildOptions::setForceOutputCheck(bool enabled) { d->forceOutputCheck = enabled; } /*! * \brief Returns true iff the time the operation takes will be logged. * The default is \c false. */ bool BuildOptions::logElapsedTime() const { return d->logElapsedTime; } /*! * \brief Controls whether the build time will be measured and logged. */ void BuildOptions::setLogElapsedTime(bool log) { d->logElapsedTime = log; } /*! * \brief The kind of output that is displayed when executing commands. */ CommandEchoMode BuildOptions::echoMode() const { return d->echoMode; } /*! * \brief Controls the kind of output that is displayed when executing commands. */ void BuildOptions::setEchoMode(CommandEchoMode echoMode) { d->echoMode = echoMode; } /*! * \brief Returns true iff installation should happen as part of the build. * The default is \c true. */ bool BuildOptions::install() const { return d->install; } /*! * \brief Controls whether to install artifacts as part of the build process. */ void BuildOptions::setInstall(bool install) { d->install = install; } /*! * \brief Returns true iff an existing installation will be removed prior to building. * The default is false. */ bool BuildOptions::removeExistingInstallation() const { return d->removeExistingInstallation; } /*! * Controls whether to remove an existing installation before installing. * \note qbs may do some safety checks and refuse to remove certain directories such as * a user's home directory. You should still be careful with this option, since it * deletes recursively. */ void BuildOptions::setRemoveExistingInstallation(bool removeExisting) { d->removeExistingInstallation = removeExisting; } /*! * \brief Returns true iff instead of a full build, only the rules of the project will be run. * The default is false. */ bool BuildOptions::executeRulesOnly() const { return d->onlyExecuteRules; } /*! * If \a onlyRules is \c true, then no artifacts are built, but only rules are being executed. * \note If the project contains highly dynamic rules that depend on output artifacts of child * rules being already present, then the associated build job may fail even though * the project is perfectly valid. Callers need to take this into consideration. */ void BuildOptions::setExecuteRulesOnly(bool onlyRules) { d->onlyExecuteRules = onlyRules; } bool operator==(const BuildOptions &bo1, const BuildOptions &bo2) { return bo1.changedFiles() == bo2.changedFiles() && bo1.dryRun() == bo2.dryRun() && bo1.keepGoing() == bo2.keepGoing() && bo1.logElapsedTime() == bo2.logElapsedTime() && bo1.echoMode() == bo2.echoMode() && bo1.maxJobCount() == bo2.maxJobCount() && bo1.install() == bo2.install() && bo1.removeExistingInstallation() == bo2.removeExistingInstallation(); } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/buildoptions.h000066400000000000000000000077131347155106100221620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BUILDOPTIONS_H #define QBS_BUILDOPTIONS_H #include "qbs_export.h" #include "commandechomode.h" #include "joblimits.h" #include QT_BEGIN_NAMESPACE class QStringList; QT_END_NAMESPACE namespace qbs { namespace Internal { class BuildOptionsPrivate; } class QBS_EXPORT BuildOptions { public: BuildOptions(); BuildOptions(const BuildOptions &other); BuildOptions &operator=(const BuildOptions &other); ~BuildOptions(); QStringList filesToConsider() const; void setFilesToConsider(const QStringList &files); QStringList changedFiles() const; void setChangedFiles(const QStringList &changedFiles); QStringList activeFileTags() const; void setActiveFileTags(const QStringList &fileTags); static int defaultMaxJobCount(); int maxJobCount() const; void setMaxJobCount(int jobCount); QString settingsDirectory() const; void setSettingsDirectory(const QString &settingsBaseDir); JobLimits jobLimits() const; void setJobLimits(const JobLimits &jobLimits); bool projectJobLimitsTakePrecedence() const; void setProjectJobLimitsTakePrecedence(bool toggle); bool dryRun() const; void setDryRun(bool dryRun); bool keepGoing() const; void setKeepGoing(bool keepGoing); bool forceTimestampCheck() const; void setForceTimestampCheck(bool enabled); bool forceOutputCheck() const; void setForceOutputCheck(bool enabled); bool logElapsedTime() const; void setLogElapsedTime(bool log); CommandEchoMode echoMode() const; void setEchoMode(CommandEchoMode echoMode); bool install() const; void setInstall(bool install); bool removeExistingInstallation() const; void setRemoveExistingInstallation(bool removeExisting); bool executeRulesOnly() const; void setExecuteRulesOnly(bool onlyRules); private: QSharedDataPointer d; }; bool operator==(const BuildOptions &bo1, const BuildOptions &bo2); inline bool operator!=(const BuildOptions &bo1, const BuildOptions &bo2) { return !(bo1 == bo2); } } // namespace qbs #endif // QBS_BUILDOPTIONS_H qbs-src-1.13.1/src/lib/corelib/tools/cleanoptions.cpp000066400000000000000000000110631347155106100224710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "cleanoptions.h" #include namespace qbs { namespace Internal { class CleanOptionsPrivate : public QSharedData { public: CleanOptionsPrivate() : dryRun(false), keepGoing(false), logElapsedTime(false) { } bool dryRun; bool keepGoing; bool logElapsedTime; }; } /*! * \class CleanOptions * \brief The \c CleanOptions class comprises parameters that influence the behavior of * cleaning operations. */ /*! * \enum CleanOptions::CleanType * This enum type specifies which kind of build artifacts to remove. * \value CleanupAll Indicates that all files created by the build process should be removed. * \value CleanupTemporaries Indicates that only intermediate build artifacts should be removed. * If, for example, the product to clean up for is a Linux shared library, the .so file * would be left on the disk, but the .o files would be removed. */ CleanOptions::CleanOptions() : d(new Internal::CleanOptionsPrivate) { } CleanOptions::CleanOptions(const CleanOptions &other) : d(other.d) { } CleanOptions::CleanOptions(CleanOptions &&other) Q_DECL_NOEXCEPT = default; CleanOptions &CleanOptions::operator=(const CleanOptions &other) { d = other.d; return *this; } CleanOptions &CleanOptions::operator=(CleanOptions &&other) Q_DECL_NOEXCEPT = default; CleanOptions::~CleanOptions() { } /*! * \brief Returns true iff qbs will not actually remove any files, but just show what would happen. * The default is false. */ bool CleanOptions::dryRun() const { return d->dryRun; } /*! * \brief Controls whether clean-up will actually take place. * If the argument is true, then qbs will emit information about which files would be removed * instead of actually doing it. */ void CleanOptions::setDryRun(bool dryRun) { d->dryRun = dryRun; } /*! * Returns true iff clean-up will continue if an error occurs. * The default is false. */ bool CleanOptions::keepGoing() const { return d->keepGoing; } /*! * \brief Controls whether to abort on errors. * If the argument is true, then if a file cannot be removed e.g. due to a permission problem, * a warning will be printed and the clean-up will continue. If the argument is false, * then the clean-up will abort immediately in case of an error. */ void CleanOptions::setKeepGoing(bool keepGoing) { d->keepGoing = keepGoing; } /*! * \brief Returns true iff the time the operation takes will be logged. * The default is false. */ bool CleanOptions::logElapsedTime() const { return d->logElapsedTime; } /*! * \brief Controls whether the clean-up time will be measured and logged. */ void CleanOptions::setLogElapsedTime(bool log) { d->logElapsedTime = log; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/cleanoptions.h000066400000000000000000000051771347155106100221470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_CLEANOPTIONS_H #define QBS_CLEANOPTIONS_H #include "qbs_export.h" #include namespace qbs { namespace Internal { class CleanOptionsPrivate; } class QBS_EXPORT CleanOptions { public: CleanOptions(); CleanOptions(const CleanOptions &other); CleanOptions(CleanOptions &&other) Q_DECL_NOEXCEPT; CleanOptions &operator=(const CleanOptions &other); CleanOptions &operator=(CleanOptions &&other) Q_DECL_NOEXCEPT; ~CleanOptions(); bool dryRun() const; void setDryRun(bool dryRun); bool keepGoing() const; void setKeepGoing(bool keepGoing); bool logElapsedTime() const; void setLogElapsedTime(bool log); private: QSharedDataPointer d; }; } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/tools/codelocation.cpp000066400000000000000000000114351347155106100224410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "codelocation.h" #include #include #include #include #include #include #include #include namespace qbs { class CodeLocation::CodeLocationPrivate : public QSharedData { public: void load(Internal::PersistentPool &pool) { pool.load(filePath); pool.load(line); pool.load(column); } void store(Internal::PersistentPool &pool) const { pool.store(filePath); pool.store(line); pool.store(column); } QString filePath; int line; int column; }; CodeLocation::CodeLocation() { } CodeLocation::CodeLocation(const QString &aFilePath, int aLine, int aColumn, bool checkPath) : d(new CodeLocationPrivate) { QBS_ASSERT(!checkPath || Internal::FileInfo::isAbsolute(aFilePath), qDebug() << aFilePath); d->filePath = aFilePath; d->line = aLine; d->column = aColumn; } CodeLocation::CodeLocation(const CodeLocation &other) : d(other.d) { } CodeLocation &CodeLocation::operator=(const CodeLocation &other) { d = other.d; return *this; } CodeLocation::~CodeLocation() { } QString CodeLocation::filePath() const { return d ? d->filePath : QString(); } int CodeLocation::line() const { return d ? d->line : -1; } int CodeLocation::column() const { return d ? d->column : -1; } bool CodeLocation::isValid() const { return !filePath().isEmpty(); } QString CodeLocation::toString() const { QString str; if (isValid()) { str = QDir::toNativeSeparators(filePath()); QString lineAndColumn; if (line() > 0 && !str.contains(QRegExp(QStringLiteral(":[0-9]+$")))) lineAndColumn += QLatin1Char(':') + QString::number(line()); if (column() > 0 && !str.contains(QRegExp(QStringLiteral(":[0-9]+:[0-9]+$")))) lineAndColumn += QLatin1Char(':') + QString::number(column()); str += lineAndColumn; } return str; } void CodeLocation::load(Internal::PersistentPool &pool) { const bool isValid = pool.load(); if (!isValid) return; d = new CodeLocationPrivate; pool.load(*d); } void CodeLocation::store(Internal::PersistentPool &pool) const { if (d) { pool.store(true); pool.store(*d); } else { pool.store(false); } } bool operator==(const CodeLocation &cl1, const CodeLocation &cl2) { if (cl1.d == cl2.d) return true; return cl1.filePath() == cl2.filePath() && cl1.line() == cl2.line() && cl1.column() == cl2.column(); } bool operator!=(const CodeLocation &cl1, const CodeLocation &cl2) { return !(cl1 == cl2); } QDebug operator<<(QDebug debug, const CodeLocation &location) { return debug << location.toString(); } bool operator<(const CodeLocation &cl1, const CodeLocation &cl2) { return cl1.toString() < cl2.toString(); } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/codelocation.h000066400000000000000000000064101347155106100221030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SOURCELOCATION_H #define QBS_SOURCELOCATION_H #include "qbs_export.h" #include #include QT_BEGIN_NAMESPACE class QDataStream; class QString; QT_END_NAMESPACE namespace qbs { namespace Internal { class PersistentPool; } class QBS_EXPORT CodeLocation { friend QBS_EXPORT bool operator==(const CodeLocation &cl1, const CodeLocation &cl2); public: CodeLocation(); explicit CodeLocation(const QString &aFilePath, int aLine = -1, int aColumn = -1, bool checkPath = true); CodeLocation(const CodeLocation &other); CodeLocation &operator=(const CodeLocation &other); ~CodeLocation(); QString filePath() const; int line() const; int column() const; bool isValid() const; QString toString() const; void load(Internal::PersistentPool &pool); void store(Internal::PersistentPool &pool) const; private: class CodeLocationPrivate; QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const CodeLocation &cl1, const CodeLocation &cl2); QBS_EXPORT bool operator!=(const CodeLocation &cl1, const CodeLocation &cl2); QBS_EXPORT bool operator<(const CodeLocation &cl1, const CodeLocation &cl2); inline uint qHash(const CodeLocation &cl) { return qHash(cl.toString()); } QDebug operator<<(QDebug debug, const CodeLocation &location); } // namespace qbs #endif // QBS_SOURCELOCATION_H qbs-src-1.13.1/src/lib/corelib/tools/commandechomode.cpp000066400000000000000000000071601347155106100231200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandechomode.h" #include #include /*! * \enum CommandEchoMode * This enum type specifies the kind of output to display when executing commands. * \value CommandEchoModeSilent Indicates that no output will be printed. * \value CommandEchoModeSummary Indicates that descriptions will be printed. * \value CommandEchoModeCommandLine Indidcates that full command line invocations will be printed. * \value CommandEchoModeCommandLineWithEnvironment Indidcates that full command line invocations, * including environment variables, will be printed. */ namespace qbs { CommandEchoMode defaultCommandEchoMode() { return CommandEchoModeSummary; } QString commandEchoModeName(CommandEchoMode mode) { switch (mode) { case CommandEchoModeSilent: return QStringLiteral("silent"); case CommandEchoModeSummary: return QStringLiteral("summary"); case CommandEchoModeCommandLine: return QStringLiteral("command-line"); case CommandEchoModeCommandLineWithEnvironment: return QStringLiteral("command-line-with-environment"); default: break; } return {}; } CommandEchoMode commandEchoModeFromName(const QString &name) { CommandEchoMode mode = defaultCommandEchoMode(); for (int i = 0; i < CommandEchoModeInvalid; ++i) { if (commandEchoModeName(static_cast(i)) == name) { mode = static_cast(i); break; } } return mode; } QStringList allCommandEchoModeStrings() { QStringList result; for (int i = 0; i < CommandEchoModeInvalid; ++i) result << commandEchoModeName(static_cast(i)); return result; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/commandechomode.h000066400000000000000000000050641347155106100225660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_COMMANDECHOMODE_H #define QBS_COMMANDECHOMODE_H #include "qbs_export.h" #include QT_BEGIN_NAMESPACE class QString; class QStringList; QT_END_NAMESPACE namespace qbs { enum CommandEchoMode { CommandEchoModeSilent, CommandEchoModeSummary, CommandEchoModeCommandLine, CommandEchoModeCommandLineWithEnvironment, CommandEchoModeInvalid, }; QBS_EXPORT CommandEchoMode defaultCommandEchoMode(); QBS_EXPORT QString commandEchoModeName(CommandEchoMode mode); QBS_EXPORT CommandEchoMode commandEchoModeFromName(const QString &name); QBS_EXPORT QStringList allCommandEchoModeStrings(); } // namespace qbs #endif // QBS_COMMANDECHOMODE_H qbs-src-1.13.1/src/lib/corelib/tools/dynamictypecheck.h000066400000000000000000000035221347155106100227650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_DYNAMICTYPECHECK_H #define QBS_DYNAMICTYPECHECK_H namespace qbs { namespace Internal { // Generic implementation would use dynamic_cast. Don't implement unless it becomes necessary. template inline bool hasDynamicType(const StaticType *); } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/tools/error.cpp000066400000000000000000000204041347155106100211230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "error.h" #include "persistence.h" #include "qttools.h" #include #include #include #include #include namespace qbs { class ErrorItem::ErrorItemPrivate : public QSharedData { public: template void serializationOp(Internal::PersistentPool &pool) { pool.serializationOp(description, codeLocation, isBacktraceItem); } void load(Internal::PersistentPool &pool) { serializationOp(pool); } void store(Internal::PersistentPool &pool) { serializationOp(pool); } QString description; CodeLocation codeLocation; bool isBacktraceItem = false; }; /*! * \class ErrorData * \brief The \c ErrorData class describes (part of) an error resulting from a qbs operation. * It is always delivered as part of an \c Error. * \sa Error */ ErrorItem::ErrorItem() : d(new ErrorItemPrivate) { } ErrorItem::ErrorItem(const QString &description, const CodeLocation &codeLocation, bool isBacktraceItem) : d(new ErrorItemPrivate) { d->description = description; d->codeLocation = codeLocation; d->isBacktraceItem = isBacktraceItem; } ErrorItem::ErrorItem(const ErrorItem &rhs) : d(rhs.d) { } ErrorItem &ErrorItem::operator=(const ErrorItem &other) { d = other.d; return *this; } ErrorItem::~ErrorItem() { } QString ErrorItem::description() const { return d->description; } CodeLocation ErrorItem::codeLocation() const { return d->codeLocation; } bool ErrorItem::isBacktraceItem() const { return d->isBacktraceItem; } void ErrorItem::load(Internal::PersistentPool &pool) { pool.load(*d); } void ErrorItem::store(Internal::PersistentPool &pool) const { pool.store(*d); } /*! * \fn const QString &ErrorData::description() const * \brief A general description of the error. */ /*! * \fn const QString &ErrorData::codeLocation() const * \brief The location at which file in which the error occurred. * \note This information might not be applicable, in which case location().isValid() returns false */ /*! * \brief A full textual description of the error using all available information. */ QString ErrorItem::toString() const { QString str = codeLocation().toString(); if (!str.isEmpty()) str += QLatin1Char(' '); return str += description(); } class ErrorInfo::ErrorInfoPrivate : public QSharedData { public: ErrorInfoPrivate() : internalError(false) { } template void completeSerializationOp(Internal::PersistentPool &pool) { pool.serializationOp(items, internalError); } QList items; bool internalError; }; /*! * \class Error * \brief Represents an error resulting from a qbs operation. * It is made up of one or more \c ErrorData objects. * \sa ErrorData */ ErrorInfo::ErrorInfo() : d(new ErrorInfoPrivate) { } ErrorInfo::ErrorInfo(const ErrorInfo &rhs) : d(rhs.d) { } ErrorInfo::ErrorInfo(const QString &description, const CodeLocation &location, bool internalError) : d(new ErrorInfoPrivate) { append(description, location); d->internalError = internalError; } ErrorInfo::ErrorInfo(const QString &description, const QStringList &backtrace) : d(new ErrorInfoPrivate) { append(description); for (const QString &traceLine : backtrace) { static const std::regex regexp("^(.+) at (.+):(\\-?[0-9]+)$"); std::smatch match; const std::string tl = traceLine.toStdString(); if (std::regex_match(tl, match, regexp)) { const QString message = QString::fromStdString(match[1]), file = QString::fromStdString(match[2]), line = QString::fromStdString(match[3]); const CodeLocation location(file, line.toInt()); appendBacktrace(message, location); } } } ErrorInfo &ErrorInfo::operator =(const ErrorInfo &other) { d = other.d; return *this; } ErrorInfo::~ErrorInfo() { } void ErrorInfo::appendBacktrace(const QString &description, const CodeLocation &location) { d->items.push_back(ErrorItem(description, location, true)); } void ErrorInfo::append(const ErrorItem &item) { d->items.push_back(item); } void ErrorInfo::append(const QString &description, const CodeLocation &location) { d->items.push_back(ErrorItem(description, location)); } void ErrorInfo::prepend(const QString &description, const CodeLocation &location) { d->items.prepend(ErrorItem(description, location)); } /*! * \brief A list of concrete error description. * Most often, there will be one element in this list, but there can be more e.g. to illustrate * how an error condition propagates through several source files. */ QList ErrorInfo::items() const { return d->items; } void ErrorInfo::clear() { d->items.clear(); } /*! * \brief A complete textual description of the error. * All "sub-errors" will be represented. * \sa Error::entries() */ QString ErrorInfo::toString() const { QStringList lines; for (const ErrorItem &e : qAsConst(d->items)) { if (e.isBacktraceItem()) { QString line; if (!e.description().isEmpty()) line.append(QStringLiteral(" at %1").arg(e.description())); if (e.codeLocation().isValid()) line.append(QStringLiteral(" in %1").arg(e.codeLocation().toString())); if (!line.isEmpty()) lines.push_back(QLatin1Char('\t') + line); } else { lines.push_back(e.toString()); } } return lines.join(QLatin1Char('\n')); } /*! * \brief Returns true if this error represents a bug in qbs, false otherwise. */ bool ErrorInfo::isInternalError() const { return d->internalError; } bool ErrorInfo::hasLocation() const { return std::any_of(d->items.cbegin(), d->items.cend(), [](const ErrorItem &ei) { return ei.codeLocation().isValid(); }); } void ErrorInfo::load(Internal::PersistentPool &pool) { pool.load(*d); } void ErrorInfo::store(Internal::PersistentPool &pool) const { pool.store(*d); } void appendError(ErrorInfo &dst, const ErrorInfo &src) { const QList &sourceItems = src.items(); for (const ErrorItem &item : sourceItems) dst.append(item); } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/error.h000066400000000000000000000102551347155106100205730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_ERROR #define QBS_ERROR #include "codelocation.h" #include #include #include QT_BEGIN_NAMESPACE template class QList; class QString; class QStringList; QT_END_NAMESPACE namespace qbs { namespace Internal { class PersistentPool; } class CodeLocation; class QBS_EXPORT ErrorItem { friend class ErrorInfo; public: ErrorItem(); ErrorItem(const ErrorItem &rhs); ErrorItem &operator=(const ErrorItem &other); ~ErrorItem(); QString description() const; CodeLocation codeLocation() const; QString toString() const; bool isBacktraceItem() const; void load(Internal::PersistentPool &pool); void store(Internal::PersistentPool &pool) const; private: ErrorItem(const QString &description, const CodeLocation &codeLocation, bool isBacktraceItem = false); class ErrorItemPrivate; QExplicitlySharedDataPointer d; }; class QBS_EXPORT ErrorInfo { public: ErrorInfo(); ErrorInfo(const ErrorInfo &rhs); ErrorInfo(const QString &description, const CodeLocation &location = CodeLocation(), bool internalError = false); ErrorInfo(const QString &description, const QStringList &backtrace); ErrorInfo &operator=(const ErrorInfo &other); ~ErrorInfo(); void appendBacktrace(const QString &description, const CodeLocation &location = CodeLocation()); void append(const ErrorItem &item); void append(const QString &description, const CodeLocation &location = CodeLocation()); void prepend(const QString &description, const CodeLocation &location = CodeLocation()); QList items() const; bool hasError() const { return !items().empty(); } void clear(); QString toString() const; bool isInternalError() const; bool hasLocation() const; void load(Internal::PersistentPool &pool); void store(Internal::PersistentPool &pool) const; private: class ErrorInfoPrivate; QSharedDataPointer d; }; void appendError(ErrorInfo &dst, const ErrorInfo &src); inline uint qHash(const ErrorInfo &e) { return qHash(e.toString()); } inline bool operator==(const ErrorInfo &e1, const ErrorInfo &e2) { return e1.toString() == e2.toString(); } } // namespace qbs Q_DECLARE_METATYPE(qbs::ErrorInfo) #endif // QBS_ERROR qbs-src-1.13.1/src/lib/corelib/tools/executablefinder.cpp000066400000000000000000000127051347155106100233100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "executablefinder.h" #include "fileinfo.h" #include "hostosinfo.h" #include "qttools.h" #include "stringconstants.h" #include #include namespace qbs { namespace Internal { static QStringList populateExecutableSuffixes() { QStringList result; result << QString(); if (HostOsInfo::isWindowsHost()) { result << QStringLiteral(".com") << QStringLiteral(".exe") << QStringLiteral(".bat") << QStringLiteral(".cmd"); } return result; } QStringList ExecutableFinder::m_executableSuffixes = populateExecutableSuffixes(); ExecutableFinder::ExecutableFinder(const ResolvedProductPtr &m_product, const QProcessEnvironment &env) : m_product(m_product) , m_environment(env) { } QString ExecutableFinder::findExecutable(const QString &path, const QString &workingDirPath) { QString filePath = QDir::fromNativeSeparators(path); //if (FileInfo::fileName(filePath) == filePath) if (!FileInfo::isAbsolute(filePath)) return findInPath(filePath, workingDirPath); else if (HostOsInfo::isWindowsHost()) return findBySuffix(filePath); return filePath; } QString ExecutableFinder::findBySuffix(const QString &filePath) const { QString fullProgramPath = cachedFilePath(filePath); if (!fullProgramPath.isEmpty()) return fullProgramPath; fullProgramPath = filePath; qCDebug(lcExec) << "looking for executable by suffix" << fullProgramPath; const QString emptyDirectory; candidateCheck(emptyDirectory, fullProgramPath, fullProgramPath); cacheFilePath(filePath, fullProgramPath); return fullProgramPath; } bool ExecutableFinder::candidateCheck(const QString &directory, const QString &program, QString &fullProgramPath) const { for (const QString &suffix : qAsConst(m_executableSuffixes)) { QString candidate = directory + program + suffix; qCDebug(lcExec) << "candidate:" << candidate; QFileInfo fi(candidate); if (fi.isFile() && fi.isExecutable()) { fullProgramPath = candidate; return true; } } return false; } QString ExecutableFinder::findInPath(const QString &filePath, const QString &workingDirPath) const { QString fullProgramPath = cachedFilePath(filePath); if (!fullProgramPath.isEmpty()) return fullProgramPath; fullProgramPath = filePath; qCDebug(lcExec) << "looking for executable in PATH" << fullProgramPath; QStringList pathEnv = m_environment.value(StringConstants::pathEnvVar()) .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); if (HostOsInfo::isWindowsHost()) pathEnv.prepend(StringConstants::dot()); for (QString directory : qAsConst(pathEnv)) { if (directory == StringConstants::dot()) directory = workingDirPath; if (!directory.isEmpty()) { const QChar lastChar = directory.at(directory.size() - 1); if (lastChar != QLatin1Char('/') && lastChar != QLatin1Char('\\')) directory.append(QLatin1Char('/')); } if (candidateCheck(directory, fullProgramPath, fullProgramPath)) break; } cacheFilePath(filePath, fullProgramPath); return fullProgramPath; } QString ExecutableFinder::cachedFilePath(const QString &filePath) const { return m_product ? m_product->cachedExecutablePath(filePath) : QString(); } void ExecutableFinder::cacheFilePath(const QString &filePath, const QString &fullFilePath) const { if (m_product) m_product->cacheExecutablePath(filePath, fullFilePath); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/executablefinder.h000066400000000000000000000056311347155106100227550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_EXECUTABLEFINDER_H #define QBS_EXECUTABLEFINDER_H #include #include namespace qbs { namespace Internal { /*! * \brief Helper class for finding an executable in the PATH of the build environment. */ class ExecutableFinder { public: ExecutableFinder(const ResolvedProductPtr &product, const QProcessEnvironment &env); QString findExecutable(const QString &path, const QString &workingDirPath); private: static QStringList m_executableSuffixes; QString findBySuffix(const QString &filePath) const; bool candidateCheck(const QString &directory, const QString &program, QString &fullProgramPath) const; QString findInPath(const QString &filePath, const QString &workingDirPath) const; QString cachedFilePath(const QString &filePath) const; void cacheFilePath(const QString &filePaht, const QString &filePath) const; ResolvedProductPtr m_product; const QProcessEnvironment &m_environment; }; } // namespace Internal } // namespace qbs #endif // QBS_EXECUTABLEFINDER_H qbs-src-1.13.1/src/lib/corelib/tools/fileinfo.cpp000066400000000000000000000435561347155106100216020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "fileinfo.h" #include #include #include #include #include #include #include #include #if defined(Q_OS_UNIX) #include #include #include #elif defined(Q_OS_WIN) #include #endif namespace qbs { namespace Internal { QString FileInfo::fileName(const QString &fp) { int last = fp.lastIndexOf(QLatin1Char('/')); if (last < 0) return fp; return fp.mid(last + 1); } QString FileInfo::baseName(const QString &fp) { QString fn = fileName(fp); int dot = fn.indexOf(QLatin1Char('.')); if (dot < 0) return fn; return fn.mid(0, dot); } QString FileInfo::completeBaseName(const QString &fp) { QString fn = fileName(fp); int dot = fn.lastIndexOf(QLatin1Char('.')); if (dot < 0) return fn; return fn.mid(0, dot); } QString FileInfo::suffix(const QString &fp) { QString fn = fileName(fp); int dot = fn.lastIndexOf(QLatin1Char('.')); if (dot < 0) return fn; return fn.mid(dot + 1); } QString FileInfo::completeSuffix(const QString &fp) { QString fn = fileName(fp); int dot = fn.indexOf(QLatin1Char('.')); if (dot < 0) return fn; return fn.mid(dot + 1); } QString FileInfo::path(const QString &fp, HostOsInfo::HostOs hostOs) { if (fp.isEmpty()) return {}; int last = fp.lastIndexOf(QLatin1Char('/')); if (last < 0) return StringConstants::dot(); QString p = QDir::cleanPath(fp.mid(0, last)); if (p.isEmpty() || (hostOs == HostOsInfo::HostOsWindows && p.length() == 2 && p.at(0).isLetter() && p.at(1) == QLatin1Char(':'))) { // Make sure we don't return Windows drive roots without an ending slash. // Those paths are considered relative. p.append(QLatin1Char('/')); } return p; } void FileInfo::splitIntoDirectoryAndFileName(const QString &filePath, QString *dirPath, QString *fileName) { int idx = filePath.lastIndexOf(QLatin1Char('/')); if (idx < 0) { dirPath->clear(); *fileName = filePath; return; } *dirPath = filePath.left(idx); *fileName = filePath.mid(idx + 1); } void FileInfo::splitIntoDirectoryAndFileName(const QString &filePath, QStringRef *dirPath, QStringRef *fileName) { int idx = filePath.lastIndexOf(QLatin1Char('/')); if (idx < 0) { dirPath->clear(); *fileName = QStringRef(&filePath); return; } *dirPath = filePath.leftRef(idx); *fileName = filePath.midRef(idx + 1); } bool FileInfo::exists(const QString &fp) { return FileInfo(fp).exists(); } // Whether a path is the special "current drive path" path type, // which is neither truly relative nor absolute static bool isCurrentDrivePath(const QString &path, HostOsInfo::HostOs hostOs) { return hostOs == HostOsInfo::HostOsWindows ? path.size() == 2 && path.at(1) == QLatin1Char(':') && path.at(0).isLetter() : false; } // from creator/src/shared/proparser/ioutils.cpp bool FileInfo::isAbsolute(const QString &path, HostOsInfo::HostOs hostOs) { const int n = path.size(); if (n == 0) return false; const QChar at0 = path.at(0); if (at0 == QLatin1Char('/')) return true; if (hostOs == HostOsInfo::HostOsWindows) { if (at0 == QLatin1Char('\\')) return true; // Unlike QFileInfo, this won't accept a relative path with a drive letter. // Such paths result in a royal mess anyway ... if (n >= 3 && path.at(1) == QLatin1Char(':') && at0.isLetter() && (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\'))) return true; } return false; } bool FileInfo::isPattern(const QString &str) { return isPattern(QStringRef(&str)); } bool FileInfo::isPattern(const QStringRef &str) { for (const QChar &ch : str) { if (ch == QLatin1Char('*') || ch == QLatin1Char('?') || ch == QLatin1Char(']') || ch == QLatin1Char('[')) { return true; } } return false; } /** * Concatenates the paths \a base and \a rel. * Base must be an absolute path. * Double dots at the start of \a rel are handled. * This function assumes that both paths are clean, that is they don't contain * double slashes or redundant dot parts. */ QString FileInfo::resolvePath(const QString &base, const QString &rel, HostOsInfo::HostOs hostOs) { QBS_ASSERT(isAbsolute(base, hostOs) && !isCurrentDrivePath(rel, hostOs), qDebug("base: %s, rel: %s", qPrintable(base), qPrintable(rel)); return {}); if (isAbsolute(rel, hostOs)) return rel; if (rel.size() == 1 && rel.at(0) == QLatin1Char('.')) return base; if (rel.size() == 1 && rel.at(0) == QLatin1Char('~')) return QDir::homePath(); if (rel.startsWith(StringConstants::tildeSlash())) return QDir::homePath() + rel.mid(1); QString r = base; if (r.endsWith(QLatin1Char('/'))) r.chop(1); QString s = rel; while (s.startsWith(QStringLiteral("../"))) { s.remove(0, 3); int idx = r.lastIndexOf(QLatin1Char('/')); if (idx >= 0) r.truncate(idx); } if (s == StringConstants::dotDot()) { int idx = r.lastIndexOf(QLatin1Char('/')); if (idx >= 0) r.truncate(idx); s.clear(); } if (!s.isEmpty() || isCurrentDrivePath(r, hostOs)) { r.reserve(r.length() + 1 + s.length()); r += QLatin1Char('/'); r += s; } return r; } bool FileInfo::globMatches(const QRegExp ®exp, const QString &fileName) { const QString pattern = regexp.pattern(); // May be it's simple wildcard, i.e. "*.cpp"? if (pattern.startsWith(QLatin1Char('*')) && !isPattern(pattern.midRef(1))) { // Yes, it's rather simple to just check the extension return fileName.endsWith(pattern.midRef(1)); } return regexp.exactMatch(fileName); } #ifdef Q_OS_WIN static QString prependLongPathPrefix(const QString &absolutePath) { QString nativePath = QDir::toNativeSeparators(absolutePath); if (nativePath.startsWith(QStringLiteral("\\\\"))) nativePath.remove(0, 1).prepend(QLatin1String("UNC")); nativePath.prepend(QLatin1String("\\\\?\\")); return nativePath; } #endif bool FileInfo::isFileCaseCorrect(const QString &filePath) { #if defined(Q_OS_WIN) // QFileInfo::canonicalFilePath() does not return the real case of the file path on Windows. QFileInfo fi(filePath); const QString absolute = prependLongPathPrefix(fi.absoluteFilePath()); WIN32_FIND_DATA fd; HANDLE hFindFile = ::FindFirstFile((wchar_t*)absolute.utf16(), &fd); if (hFindFile == INVALID_HANDLE_VALUE) return false; const QString actualFileName = QString::fromWCharArray(fd.cFileName); FindClose(hFindFile); return actualFileName == fi.fileName(); #elif defined(Q_OS_DARWIN) QFileInfo fi(filePath); return fi.fileName() == fileName(fi.canonicalFilePath()); #else Q_UNUSED(filePath) return true; #endif } bool FileInfo::fileExists(const QFileInfo &fi) { return fi.isSymLink() || fi.exists(); } #if defined(Q_OS_WIN) #define z(x) reinterpret_cast(const_cast(&x)) FileInfo::FileInfo(const QString &fileName) { static_assert(sizeof(FileInfo::InternalStatType) == sizeof(WIN32_FILE_ATTRIBUTE_DATA), "FileInfo::InternalStatType has wrong size."); QString filePath = fileName; // The extended-length path prefix cannot be used with a relative path, so make it absolute if (!isAbsolute(filePath)) filePath = QDir::currentPath() + QDir::separator() + filePath; filePath = prependLongPathPrefix(QDir::cleanPath(filePath)); if (!GetFileAttributesEx(reinterpret_cast(filePath.utf16()), GetFileExInfoStandard, &m_stat)) { ZeroMemory(z(m_stat), sizeof(WIN32_FILE_ATTRIBUTE_DATA)); z(m_stat)->dwFileAttributes = INVALID_FILE_ATTRIBUTES; } } bool FileInfo::exists() const { return z(m_stat)->dwFileAttributes != INVALID_FILE_ATTRIBUTES; } FileTime FileInfo::lastModified() const { const FileTime::InternalType* ft_it; ft_it = reinterpret_cast(&z(m_stat)->ftLastWriteTime); return {*ft_it}; } FileTime FileInfo::lastStatusChange() const { return lastModified(); } bool FileInfo::isDir() const { return exists() && z(m_stat)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; } static QString resolveSymlinks(const QString &fileName) { QFileInfo fi(fileName); while (fi.isSymLink()) fi.setFile(fi.dir(), fi.symLinkTarget()); return fi.absoluteFilePath(); } QString applicationDirPath() { static const QString appDirPath = FileInfo::path(resolveSymlinks(QCoreApplication::applicationFilePath())); return appDirPath; } #elif defined(Q_OS_UNIX) FileInfo::FileInfo(const QString &fileName) { if (stat(fileName.toLocal8Bit(), &m_stat) == -1) { m_stat.st_mtime = 0; m_stat.st_mode = 0; } } bool FileInfo::exists() const { return m_stat.st_mode != 0; } FileTime FileInfo::lastModified() const { #if APPLE_STAT_TIMESPEC return m_stat.st_mtimespec; #elif HAS_CLOCK_GETTIME return m_stat.st_mtim; #else return m_stat.st_mtime; #endif } FileTime FileInfo::lastStatusChange() const { #if APPLE_STAT_TIMESPEC return m_stat.st_ctimespec; #elif HAS_CLOCK_GETTIME return m_stat.st_ctim; #else return m_stat.st_ctime; #endif } bool FileInfo::isDir() const { return S_ISDIR(m_stat.st_mode); } #endif // adapted from qtc/plugins/vcsbase/cleandialog.cpp bool removeFileRecursion(const QFileInfo &f, QString *errorMessage) { if (!FileInfo::fileExists(f)) return true; if (f.isDir() && !f.isSymLink()) { const QDir dir(f.absoluteFilePath()); // QDir::System is needed for broken symlinks. for (const QFileInfo &fi : dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System)) removeFileRecursion(fi, errorMessage); QDir parent = f.absoluteDir(); if (!parent.rmdir(f.fileName())) { errorMessage->append(Tr::tr("The directory %1 could not be deleted."). arg(QDir::toNativeSeparators(f.absoluteFilePath()))); return false; } } else { QFile file(f.absoluteFilePath()); file.setPermissions(f.permissions() | QFile::WriteUser); if (!file.remove()) { if (!errorMessage->isEmpty()) errorMessage->append(QLatin1Char('\n')); errorMessage->append(Tr::tr("The file %1 could not be deleted."). arg(QDir::toNativeSeparators(f.absoluteFilePath()))); return false; } } return true; } bool removeDirectoryWithContents(const QString &path, QString *errorMessage) { QFileInfo f(path); if (f.exists() && !f.isDir()) { *errorMessage = Tr::tr("%1 is not a directory.").arg(QDir::toNativeSeparators(path)); return false; } return removeFileRecursion(f, errorMessage); } /*! * Returns the stored link target of the symbolic link \a{filePath}. * Unlike QFileInfo::symLinkTarget, this will not make the link target an absolute path. */ static QByteArray storedLinkTarget(const QString &filePath) { QByteArray result; #ifdef Q_OS_UNIX const QByteArray nativeFilePath = QFile::encodeName(filePath); ssize_t len; while (true) { struct stat sb; if (lstat(nativeFilePath.constData(), &sb)) { qWarning("storedLinkTarget: lstat for %s failed with error code %d", nativeFilePath.constData(), errno); return {}; } result.resize(sb.st_size); len = readlink(nativeFilePath.constData(), result.data(), sb.st_size + 1); if (len < 0) { qWarning("storedLinkTarget: readlink for %s failed with error code %d", nativeFilePath.constData(), errno); return {}; } if (len < sb.st_size) { result.resize(len); break; } if (len == sb.st_size) break; } #else Q_UNUSED(filePath); #endif // Q_OS_UNIX return result; } static bool createSymLink(const QByteArray &path1, const QString &path2) { #ifdef Q_OS_UNIX const QByteArray newPath = QFile::encodeName(path2); unlink(newPath.constData()); return symlink(path1.constData(), newPath.constData()) == 0; #else Q_UNUSED(path1); Q_UNUSED(path2); return false; #endif // Q_OS_UNIX } /*! Copies the directory specified by \a srcFilePath recursively to \a tgtFilePath. \a tgtFilePath will contain the target directory, which will be created. Example usage: \code QString error; book ok = Utils::FileUtils::copyRecursively("/foo/bar", "/foo/baz", &error); if (!ok) qDebug() << error; \endcode This will copy the contents of /foo/bar into to the baz directory under /foo, which will be created in the process. \return Whether the operation succeeded. \note Function was adapted from qtc/src/libs/fileutils.cpp */ bool copyFileRecursion(const QString &srcFilePath, const QString &tgtFilePath, bool preserveSymLinks, bool copyDirectoryContents, QString *errorMessage) { QFileInfo srcFileInfo(srcFilePath); QFileInfo tgtFileInfo(tgtFilePath); const QString targetDirPath = tgtFileInfo.absoluteDir().path(); if (!QDir::root().mkpath(targetDirPath)) { *errorMessage = Tr::tr("The directory '%1' could not be created.") .arg(QDir::toNativeSeparators(targetDirPath)); return false; } if (HostOsInfo::isAnyUnixHost() && preserveSymLinks && srcFileInfo.isSymLink()) { // For now, disable symlink preserving copying on Windows. // MS did a good job to prevent people from using symlinks - even if they are supported. if (!createSymLink(storedLinkTarget(srcFilePath), tgtFilePath)) { *errorMessage = Tr::tr("The symlink '%1' could not be created.") .arg(tgtFilePath); return false; } } else if (srcFileInfo.isDir()) { if (copyDirectoryContents) { QDir sourceDir(srcFilePath); const QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); for (const QString &fileName : fileNames) { const QString newSrcFilePath = srcFilePath + QLatin1Char('/') + fileName; const QString newTgtFilePath = tgtFilePath + QLatin1Char('/') + fileName; if (!copyFileRecursion(newSrcFilePath, newTgtFilePath, preserveSymLinks, copyDirectoryContents, errorMessage)) return false; } } else { if (tgtFileInfo.exists() && srcFileInfo.lastModified() <= tgtFileInfo.lastModified()) return true; return QDir::root().mkpath(tgtFilePath); } } else { if (tgtFileInfo.exists() && srcFileInfo.lastModified() <= tgtFileInfo.lastModified()) return true; QFile file(srcFilePath); QFile targetFile(tgtFilePath); if (targetFile.exists()) { targetFile.setPermissions(targetFile.permissions() | QFile::WriteUser); if (!targetFile.remove()) { *errorMessage = Tr::tr("Could not remove file '%1'. %2") .arg(QDir::toNativeSeparators(tgtFilePath), targetFile.errorString()); } } if (!file.copy(tgtFilePath)) { *errorMessage = Tr::tr("Could not copy file '%1' to '%2'. %3") .arg(QDir::toNativeSeparators(srcFilePath), QDir::toNativeSeparators(tgtFilePath), file.errorString()); return false; } } return true; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/fileinfo.h000066400000000000000000000101731347155106100212340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_FILEINFO_H #define QBS_FILEINFO_H #include "filetime.h" #include "hostosinfo.h" #include "qbs_export.h" #if defined(Q_OS_UNIX) #include #endif #include QT_FORWARD_DECLARE_CLASS(QFileInfo) namespace qbs { namespace Internal { class QBS_AUTOTEST_EXPORT FileInfo { public: FileInfo(const QString &fileName); bool exists() const; FileTime lastModified() const; FileTime lastStatusChange() const; bool isDir() const; static QString fileName(const QString &fp); static QString baseName(const QString &fp); static QString completeBaseName(const QString &fp); static QString suffix(const QString &fp); static QString completeSuffix(const QString &fp); static QString path(const QString &fp, HostOsInfo::HostOs hostOs = HostOsInfo::hostOs()); static void splitIntoDirectoryAndFileName(const QString &filePath, QString *dirPath, QString *fileName); static void splitIntoDirectoryAndFileName(const QString &filePath, QStringRef *dirPath, QStringRef *fileName); static bool exists(const QString &fp); static bool isAbsolute(const QString &fp, HostOsInfo::HostOs hostOs = HostOsInfo::hostOs()); static bool isPattern(const QStringRef &str); static bool isPattern(const QString &str); static QString resolvePath(const QString &base, const QString &rel, HostOsInfo::HostOs hostOs = HostOsInfo::hostOs()); static bool globMatches(const QRegExp &pattern, const QString &subject); static bool isFileCaseCorrect(const QString &filePath); // Symlink-correct check. static bool fileExists(const QFileInfo &fi); private: #if defined(Q_OS_WIN) struct InternalStatType { quint8 z[36]; }; #elif defined(Q_OS_UNIX) using InternalStatType = struct stat; #else # error unknown platform #endif InternalStatType m_stat; }; bool removeFileRecursion(const QFileInfo &f, QString *errorMessage); // FIXME: Used by tests. bool QBS_EXPORT removeDirectoryWithContents(const QString &path, QString *errorMessage); bool QBS_EXPORT copyFileRecursion(const QString &sourcePath, const QString &targetPath, bool preserveSymLinks, bool copyDirectoryContents, QString *errorMessage); } // namespace Internal } // namespace qbs #endif qbs-src-1.13.1/src/lib/corelib/tools/filesaver.cpp000066400000000000000000000074571347155106100217670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "filesaver.h" #include "stlutils.h" #include #include #include namespace qbs { namespace Internal { FileSaver::FileSaver(const std::string &filePath, bool overwriteIfUnchanged) : m_filePath(filePath), m_overwriteIfUnchanged(overwriteIfUnchanged) { } std::ostream *FileSaver::device() { return m_memoryDevice.get(); } bool FileSaver::open() { if (!m_overwriteIfUnchanged) { std::ifstream file(utf8_to_native_path(m_filePath)); if (file.is_open()) m_oldFileContents.assign(std::istreambuf_iterator(file), std::istreambuf_iterator()); else m_oldFileContents.clear(); } m_memoryDevice = std::make_shared(); return true; } bool FileSaver::commit() { if (!device()) return false; device()->flush(); if (!device()->good()) return false; const std::string newFileContents = m_memoryDevice->str(); if (!m_overwriteIfUnchanged && m_oldFileContents == newFileContents) return true; // no need to write unchanged data const std::string tempFilePath = m_filePath + "~"; std::ofstream tempFile(utf8_to_native_path(tempFilePath)); if (!tempFile.is_open()) return false; tempFile.write(newFileContents.data(), newFileContents.size()); tempFile.close(); if (!tempFile.good()) return false; if (Internal::rename(tempFilePath, m_filePath) != 0) { if (errno != EEXIST) return false; if (Internal::unlink(m_filePath) != 0) return false; return Internal::rename(tempFilePath, m_filePath) == 0; } return true; } bool FileSaver::write(const std::vector &data) { return fwrite(data, device()); } bool FileSaver::write(const std::string &data) { return fwrite(data, device()); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/filesaver.h000066400000000000000000000051641347155106100214250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FILESAVER_H #define FILESAVER_H #include "qbs_export.h" #include #include #include #include namespace qbs { namespace Internal { /*! * QSaveFile wrapper which doesn't update the target file if the contents are unchanged. */ class QBS_EXPORT FileSaver { public: FileSaver(const std::string &filePath, bool overwriteIfUnchanged = false); std::ostream *device(); bool open(); bool commit(); bool write(const std::vector &data); bool write(const std::string &data); private: std::string m_oldFileContents; std::shared_ptr m_memoryDevice; const std::string m_filePath; const bool m_overwriteIfUnchanged; }; } // namespace Internal } // namespace qbs #endif // FILESAVER_H qbs-src-1.13.1/src/lib/corelib/tools/filetime.cpp000066400000000000000000000137131347155106100215750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "filetime.h" #include #ifdef Q_OS_WIN #include #else #include #endif namespace qbs { namespace Internal { #ifdef APPLE_CUSTOM_CLOCK_GETTIME #include #ifndef CLOCK_REALTIME #define CLOCK_REALTIME 0 #endif // clk_id isn't used, only the CLOCK_REALTIME case is implemented. int clock_gettime(int /*clk_id*/, struct timespec *t) { struct timeval tv; // Resolution of gettimeofday is 1000nsecs = 1 microsecond. int ret = gettimeofday(&tv, NULL); t->tv_sec = tv.tv_sec; t->tv_nsec = tv.tv_usec * 1000; return ret; } #endif FileTime::FileTime() { #ifdef Q_OS_WIN static_assert(sizeof(FileTime::InternalType) == sizeof(FILETIME), "FileTime::InternalType has wrong size."); m_fileTime = 0; #elif HAS_CLOCK_GETTIME m_fileTime = {0, 0}; #else m_fileTime = 0; #endif } FileTime::FileTime(const FileTime::InternalType &ft) : m_fileTime(ft) { #if HAS_CLOCK_GETTIME if (m_fileTime.tv_sec == 0) m_fileTime.tv_nsec = 0; // stat() sets only the first member to 0 for non-existing files. #endif } int FileTime::compare(const FileTime &other) const { #ifdef Q_OS_WIN auto const t1 = reinterpret_cast(&m_fileTime); auto const t2 = reinterpret_cast(&other.m_fileTime); return CompareFileTime(t1, t2); #elif HAS_CLOCK_GETTIME if (m_fileTime.tv_sec < other.m_fileTime.tv_sec) return -1; if (m_fileTime.tv_sec > other.m_fileTime.tv_sec) return 1; if (m_fileTime.tv_nsec < other.m_fileTime.tv_nsec) return -1; if (m_fileTime.tv_nsec > other.m_fileTime.tv_nsec) return 1; return 0; #else if (m_fileTime < other.m_fileTime) return -1; if (m_fileTime > other.m_fileTime) return 1; return 0; #endif } void FileTime::clear() { #if HAS_CLOCK_GETTIME m_fileTime = { 0, 0 }; #else m_fileTime = 0; #endif } bool FileTime::isValid() const { return *this != FileTime(); } FileTime FileTime::currentTime() { #ifdef Q_OS_WIN FileTime result; SYSTEMTIME st; GetSystemTime(&st); auto const ft = reinterpret_cast(&result.m_fileTime); SystemTimeToFileTime(&st, ft); return result; #elif defined APPLE_CUSTOM_CLOCK_GETTIME InternalType t; // Explicitly use our custom version, so that we don't get an additional unresolved symbol on a // system that actually provides one, but isn't used due to the minimium deployment target // being lower. qbs::Internal::clock_gettime(CLOCK_REALTIME, &t); return t; #elif HAS_CLOCK_GETTIME InternalType t; clock_gettime(CLOCK_REALTIME, &t); return t; #else return time(nullptr); #endif } FileTime FileTime::oldestTime() { #ifdef Q_OS_WIN SYSTEMTIME st = { 1601, 1, 5, 2, 0, 0, 0, 0 }; FileTime result; auto const ft = reinterpret_cast(&result.m_fileTime); SystemTimeToFileTime(&st, ft); return result; #elif HAS_CLOCK_GETTIME return FileTime({1, 0}); #else return 1; #endif } double FileTime::asDouble() const { #if HAS_CLOCK_GETTIME return static_cast(m_fileTime.tv_sec); #else return static_cast(m_fileTime); #endif } QString FileTime::toString() const { #ifdef Q_OS_WIN auto const ft = reinterpret_cast(&m_fileTime); SYSTEMTIME stUTC, stLocal; FileTimeToSystemTime(ft, &stUTC); SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal); const QString result = QStringLiteral("%1.%2.%3 %4:%5:%6") .arg(stLocal.wDay, 2, 10, QLatin1Char('0')).arg(stLocal.wMonth, 2, 10, QLatin1Char('0')).arg(stLocal.wYear) .arg(stLocal.wHour, 2, 10, QLatin1Char('0')).arg(stLocal.wMinute, 2, 10, QLatin1Char('0')).arg(stLocal.wSecond, 2, 10, QLatin1Char('0')); return result; #else QDateTime dt; #if HAS_CLOCK_GETTIME dt.setMSecsSinceEpoch(m_fileTime.tv_sec * 1000 + m_fileTime.tv_nsec / 1000000); #else dt.setTime_t(m_fileTime); #endif return dt.toString(Qt::ISODateWithMs); #endif } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/filetime.h000066400000000000000000000101501347155106100212320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_FILETIME_H #define QBS_FILETIME_H #include "persistence.h" #include #include #if defined(Q_OS_UNIX) && !defined(__APPLE__) #include #define HAS_CLOCK_GETTIME (_POSIX_C_SOURCE >= 199309L) #endif // Q_OS_UNIX #ifdef __APPLE__ #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 // macOS 10.12+ ships clock_gettime. #else // We implement our own clock_gettime. #define APPLE_CUSTOM_CLOCK_GETTIME 1 #endif // __MAC_OS_X_VERSION_MIN_REQUIRED // Either way we have a clock_gettime in the end. #define HAS_CLOCK_GETTIME 1 // Apple stat struct has slightly different names for time fields. #define APPLE_STAT_TIMESPEC 1 #endif // __APPLE__ namespace qbs { namespace Internal { class QBS_AUTOTEST_EXPORT FileTime { public: #if defined(Q_OS_UNIX) #if HAS_CLOCK_GETTIME using InternalType = timespec; #else using InternalType = time_t; #endif // HAS_CLOCK_GETTIME #elif defined(Q_OS_WIN) using InternalType = quint64; #else # error unknown platform #endif FileTime(); FileTime(const InternalType &ft); bool operator<(const FileTime &rhs) const { return compare(rhs) < 0; } bool operator>(const FileTime &rhs) const { return compare(rhs) > 0; } bool operator<=(const FileTime &rhs) const { return !operator>(rhs); } bool operator>=(const FileTime &rhs) const { return !operator<(rhs); } bool operator==(const FileTime &rhs) const { return compare(rhs) == 0; } bool operator!= (const FileTime &rhs) const { return !operator==(rhs); } int compare(const FileTime &other) const; void clear(); bool isValid() const; QString toString() const; static FileTime currentTime(); static FileTime oldestTime(); double asDouble() const; template void completeSerializationOp(PersistentPool &pool) { #if HAS_CLOCK_GETTIME pool.serializationOp(m_fileTime.tv_sec, m_fileTime.tv_nsec); #else pool.serializationOp(m_fileTime); #endif } private: InternalType m_fileTime; }; } // namespace Internal } // namespace qbs QT_BEGIN_NAMESPACE inline QDebug operator<<(QDebug dbg, const qbs::Internal::FileTime &t) { dbg.nospace() << t.toString(); return dbg.space(); } QT_END_NAMESPACE #endif // QBS_FILETIME_H qbs-src-1.13.1/src/lib/corelib/tools/generateoptions.cpp000066400000000000000000000060721347155106100232050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "generateoptions.h" #include #include namespace qbs { namespace Internal { class GenerateOptionsPrivate : public QSharedData { public: GenerateOptionsPrivate() : generatorName() {} QString generatorName; }; } // namespace Internal /*! * \class GenerateOptions * \brief The \c GenerateOptions class comprises parameters that influence the behavior of * generate operations. */ GenerateOptions::GenerateOptions() : d(new Internal::GenerateOptionsPrivate) { } GenerateOptions::GenerateOptions(const GenerateOptions &other) : d(other.d) { } GenerateOptions &GenerateOptions::operator=(const GenerateOptions &other) { d = other.d; return *this; } GenerateOptions::~GenerateOptions() { } /*! * Returns the name of the generator used to create the external build system files. * The default is empty. */ QString GenerateOptions::generatorName() const { return d->generatorName; } /*! * \brief Sets the name of the generator used to create the external build system files. */ void GenerateOptions::setGeneratorName(const QString &generatorName) { d->generatorName = generatorName; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/generateoptions.h000066400000000000000000000050351347155106100226500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_GENERATEOPTIONS_H #define QBS_GENERATEOPTIONS_H #include "qbs_export.h" #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { namespace Internal { class GenerateOptionsPrivate; } class QBS_EXPORT GenerateOptions { public: GenerateOptions(); GenerateOptions(const GenerateOptions &other); GenerateOptions &operator=(const GenerateOptions &other); ~GenerateOptions(); QString generatorName() const; void setGeneratorName(const QString &generatorName); private: QSharedDataPointer d; }; } // namespace qbs #endif // QBS_GENERATEOPTIONS_H qbs-src-1.13.1/src/lib/corelib/tools/hostosinfo.h000066400000000000000000000206201347155106100216320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_HOSTOSINFO_H #define QBS_HOSTOSINFO_H #include "qbs_export.h" #include "stlutils.h" #include "version.h" #include #include #include #include #include #if defined(Q_OS_WIN) #define QBS_HOST_EXE_SUFFIX ".exe" #define QBS_HOST_DYNAMICLIB_PREFIX "" #define QBS_HOST_DYNAMICLIB_SUFFIX ".dll" #elif defined(Q_OS_DARWIN) #define QBS_HOST_EXE_SUFFIX "" #define QBS_HOST_DYNAMICLIB_PREFIX "lib" #define QBS_HOST_DYNAMICLIB_SUFFIX ".dylib" #else #define QBS_HOST_EXE_SUFFIX "" #define QBS_HOST_DYNAMICLIB_PREFIX "lib" #define QBS_HOST_DYNAMICLIB_SUFFIX ".so" #endif // Q_OS_WIN namespace qbs { namespace Internal { class QBS_EXPORT HostOsInfo // Exported for use by command-line tools. { public: // Add more as needed. enum HostOs { HostOsWindows, HostOsLinux, HostOsMacos, HostOsOtherUnix, HostOsOther }; static inline std::string hostOSIdentifier(); static inline std::vector hostOSIdentifiers(); static inline std::vector canonicalOSIdentifiers(const std::string &os); static inline HostOs hostOs(); static inline Version hostOsVersion() { Version v; if (HostOsInfo::isWindowsHost()) { QSettings settings(QStringLiteral("HKEY_LOCAL_MACHINE\\Software\\" "Microsoft\\Windows NT\\CurrentVersion"), QSettings::NativeFormat); v = v.fromString(settings.value(QStringLiteral("CurrentVersion")).toString() + QLatin1Char('.') + settings.value(QStringLiteral("CurrentBuildNumber")).toString()); Q_ASSERT(v.isValid()); } else if (HostOsInfo::isMacosHost()) { QSettings settings(QStringLiteral("/System/Library/CoreServices/SystemVersion.plist"), QSettings::NativeFormat); v = v.fromString(settings.value(QStringLiteral("ProductVersion")).toString()); Q_ASSERT(v.isValid()); } return v; } static bool isWindowsHost() { return hostOs() == HostOsWindows; } static bool isLinuxHost() { return hostOs() == HostOsLinux; } static bool isMacosHost() { return hostOs() == HostOsMacos; } static inline bool isAnyUnixHost(); static inline QString rfc1034Identifier(const QString &str); static QString appendExecutableSuffix(const QString &executable) { QString finalName = executable; if (isWindowsHost()) finalName += QLatin1String(QBS_HOST_EXE_SUFFIX); return finalName; } static QString dynamicLibraryName(const QString &libraryBaseName) { return QLatin1String(QBS_HOST_DYNAMICLIB_PREFIX) + libraryBaseName + QLatin1String(QBS_HOST_DYNAMICLIB_SUFFIX); } static Qt::CaseSensitivity fileNameCaseSensitivity() { return isWindowsHost() ? Qt::CaseInsensitive: Qt::CaseSensitive; } static QString libraryPathEnvironmentVariable() { if (isWindowsHost()) return QStringLiteral("PATH"); if (isMacosHost()) return QStringLiteral("DYLD_LIBRARY_PATH"); return QStringLiteral("LD_LIBRARY_PATH"); } static QChar pathListSeparator(HostOsInfo::HostOs hostOs = HostOsInfo::hostOs()) { return hostOs == HostOsWindows ? QLatin1Char(';') : QLatin1Char(':'); } static QChar pathSeparator(HostOsInfo::HostOs hostOs = HostOsInfo::hostOs()) { return hostOs == HostOsWindows ? QLatin1Char('\\') : QLatin1Char('/'); } static Qt::KeyboardModifier controlModifier() { return isMacosHost() ? Qt::MetaModifier : Qt::ControlModifier; } }; std::string HostOsInfo::hostOSIdentifier() { #if defined(__APPLE__) return "macos"; #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) return "windows"; #elif defined(_AIX) return "aix"; #elif defined(hpux) || defined(__hpux) return "hpux"; #elif defined(__sun) || defined(sun) return "solaris"; #elif defined(__linux__) || defined(__linux) return "linux"; #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) return "freebsd"; #elif defined(__NetBSD__) return "netbsd"; #elif defined(__OpenBSD__) return "openbsd"; #elif defined(__GNU__) return "hurd"; #elif defined(__HAIKU__) return "haiku"; #else #warning "Qbs has not been ported to this OS - see http://qbs.io/" return ""; #endif } std::vector HostOsInfo::hostOSIdentifiers() { return canonicalOSIdentifiers(hostOSIdentifier()); } std::vector HostOsInfo::canonicalOSIdentifiers(const std::string &name) { std::vector list { name }; if (contains(std::vector {"ios-simulator"}, name)) list << canonicalOSIdentifiers("ios"); if (contains(std::vector {"tvos-simulator"}, name)) list << canonicalOSIdentifiers("tvos"); if (contains(std::vector {"watchos-simulator"}, name)) list << canonicalOSIdentifiers("watchos"); if (contains(std::vector {"macos", "ios", "tvos", "watchos"}, name)) list << canonicalOSIdentifiers("darwin"); if (contains(std::vector {"darwin", "freebsd", "netbsd", "openbsd"}, name)) list << canonicalOSIdentifiers("bsd"); if (contains(std::vector {"android"}, name)) list << canonicalOSIdentifiers("linux"); // Note: recognized non-Unix platforms include: windows, haiku, vxworks if (contains(std::vector { "bsd", "aix", "hpux", "solaris", "linux", "hurd", "qnx", "integrity"}, name)) list << canonicalOSIdentifiers("unix"); return list; } HostOsInfo::HostOs HostOsInfo::hostOs() { #if defined(Q_OS_WIN) return HostOsWindows; #elif defined(Q_OS_LINUX) return HostOsLinux; #elif defined(Q_OS_DARWIN) return HostOsMacos; #elif defined(Q_OS_UNIX) return HostOsOtherUnix; #else return HostOsOther; #endif } bool HostOsInfo::isAnyUnixHost() { #ifdef Q_OS_UNIX return true; #else return false; #endif } QString HostOsInfo::rfc1034Identifier(const QString &str) { QString s = str; for (QChar &ch : s) { const char c = ch.toLatin1(); const bool okChar = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.'; if (!okChar) ch = QChar::fromLatin1('-'); } return s; } } // namespace Internal } // namespace qbs #endif // QBS_HOSTOSINFO_H qbs-src-1.13.1/src/lib/corelib/tools/id.cpp000066400000000000000000000155301347155106100203720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "id.h" #include "qbsassert.h" #include #include #include #include namespace qbs { namespace Internal { /*! \class qbs::Internal::Id \brief The class Id encapsulates an identifier that is unique within a specific running process, using the qbs library. \c{Id} is used as facility to identify objects of interest in a more typesafe and faster manner than a plain \c QString or \c QByteArray would provide. An id is internally represented as a 32 bit integer (its \c UID) and associated with a plain 7-bit-clean ASCII name used for display and persistency. This class is copied from Qt Creator. */ class StringHolder { public: StringHolder() : n(0), str(nullptr) {} StringHolder(const char *s, int length) : n(length), str(s) { if (!n) length = n = qstrlen(s); h = 0; while (length--) { h = (h << 4) + *s++; h ^= (h & 0xf0000000) >> 23; h &= 0x0fffffff; } } int n; const char *str; uint h; }; static bool operator==(const StringHolder &sh1, const StringHolder &sh2) { // sh.n is unlikely to discriminate better than the hash. return sh1.h == sh2.h && sh1.str && sh2.str && strcmp(sh1.str, sh2.str) == 0; } static uint qHash(const StringHolder &sh) { return sh.h; } struct IdCache : public QHash { #ifndef QBS_ALLOW_STATIC_LEAKS ~IdCache() { for (IdCache::iterator it = begin(); it != end(); ++it) delete[](const_cast(it.key().str)); } #endif }; static int firstUnusedId = Id::IdsPerPlugin * Id::ReservedPlugins; static QHash stringFromId; static IdCache idFromString; static std::mutex mutex; static QByteArray getStringFromId(int id) { std::lock_guard lock(mutex); return stringFromId.value(id).str; } static int theId(const char *str, int n = 0) { QBS_ASSERT(str && *str, return 0); StringHolder sh(str, n); std::lock_guard lock(mutex); int res = idFromString.value(sh, 0); if (res == 0) { res = firstUnusedId++; sh.str = qstrdup(sh.str); idFromString[sh] = res; stringFromId[res] = sh; } return res; } static int theId(const QByteArray &ba) { return theId(ba.constData(), ba.size()); } /*! \fn qbs::Internal::Id(int uid) \brief Constructs an id given a UID. The UID is an integer value that is unique within the running process. It is the callers responsibility to ensure the uniqueness of the passed integer. The recommended approach is to use \c{registerId()} with an value taken from the plugin's private range. \sa registerId() */ /*! Constructs an id given its associated name. The internal representation will be unspecified, but consistent within a process. */ Id::Id(const char *name) : m_id(theId(name, 0)) {} /*! \overload */ Id::Id(const QByteArray &name) : m_id(theId(name)) {} /*! Returns an internal representation of the id. */ QByteArray Id::name() const { return getStringFromId(m_id); } /*! Returns a string representation of the id suitable for UI display. This should not be used to create a persistent version of the Id, use \c{toSetting()} instead. \sa fromString(), toSetting() */ QString Id::toString() const { return QString::fromUtf8(getStringFromId(m_id)); } /*! Returns a persistent value representing the id which is suitable to be stored in QSettings. \sa fromSetting() */ QVariant Id::toSetting() const { return QString::fromUtf8(getStringFromId(m_id)); } /*! Reconstructs an id from a persistent value. \sa toSetting() */ Id Id::fromSetting(const QVariant &variant) { const QByteArray ba = variant.toString().toUtf8(); if (ba.isEmpty()) return {}; return {theId(ba)}; } /*! Constructs a derived id. This can be used to construct groups of ids logically belonging together. The associated internal name will be generated by appending \c{suffix}. */ Id Id::withSuffix(int suffix) const { const QByteArray ba = name() + QByteArray::number(suffix); return {ba.constData()}; } /*! \overload */ Id Id::withSuffix(const char *suffix) const { const QByteArray ba = name() + suffix; return {ba.constData()}; } /*! Constructs a derived id. This can be used to construct groups of ids logically belonging together. The associated internal name will be generated by prepending \c{prefix}. */ Id Id::withPrefix(const char *prefix) const { const QByteArray ba = prefix + name(); return {ba.constData()}; } bool Id::operator==(const char *name) const { const char *string = getStringFromId(m_id); if (string && name) return strcmp(string, name) == 0; else return false; } bool Id::alphabeticallyBefore(Id other) const { return toString().compare(other.toString(), Qt::CaseInsensitive) < 0; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/id.h000066400000000000000000000066441347155106100200450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TOOLS_ID_H #define QBS_TOOLS_ID_H #include "qbs_export.h" #include #include #include namespace qbs { namespace Internal { class QBS_AUTOTEST_EXPORT Id { public: enum { IdsPerPlugin = 10000, ReservedPlugins = 1000 }; Id() : m_id(0) {} Id(int uid) : m_id(uid) {} Id(const char *name); explicit Id(const QByteArray &name); Id withSuffix(int suffix) const; Id withSuffix(const char *name) const; Id withPrefix(const char *name) const; QByteArray name() const; QString toString() const; // Avoid. QVariant toSetting() const; // Good to use. bool isValid() const { return m_id; } bool operator==(Id id) const { return m_id == id.m_id; } bool operator==(const char *name) const; bool operator!=(Id id) const { return m_id != id.m_id; } bool operator!=(const char *name) const { return !operator==(name); } bool operator<(Id id) const { return m_id < id.m_id; } bool operator>(Id id) const { return m_id > id.m_id; } bool alphabeticallyBefore(Id other) const; int uniqueIdentifier() const { return m_id; } static Id fromUniqueIdentifier(int uid) { return Id(uid); } static Id fromSetting(const QVariant &variant); // Good to use. private: // Intentionally unimplemented Id(const QLatin1String &); int m_id; }; inline uint qHash(const Id &id) { return id.uniqueIdentifier(); } } // namespace Internal } // namespace qbs Q_DECLARE_METATYPE(qbs::Internal::Id) Q_DECLARE_METATYPE(QList) #endif // QBS_TOOLS_ID_H qbs-src-1.13.1/src/lib/corelib/tools/installoptions.cpp000066400000000000000000000155271347155106100230660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "installoptions.h" #include "language/language.h" #include #include #include namespace qbs { namespace Internal { class InstallOptionsPrivate : public QSharedData { public: InstallOptionsPrivate() : useSysroot(false), removeExisting(false), dryRun(false), keepGoing(false), logElapsedTime(false) {} QString installRoot; bool useSysroot; bool removeExisting; bool dryRun; bool keepGoing; bool logElapsedTime; }; QString effectiveInstallRoot(const InstallOptions &options, const TopLevelProject *project) { const QString installRoot = options.installRoot(); if (!installRoot.isEmpty()) return installRoot; if (options.installIntoSysroot()) { return project->buildConfiguration().value(StringConstants::qbsModule()).toMap() .value(QStringLiteral("sysroot")).toString(); } return project->buildConfiguration().value(StringConstants::qbsModule()).toMap() .value(StringConstants::installRootProperty()).toString(); } } // namespace Internal /*! * \class InstallOptions * \brief The \c InstallOptions class comprises parameters that influence the behavior of * install operations. */ InstallOptions::InstallOptions() : d(new Internal::InstallOptionsPrivate) { } InstallOptions::InstallOptions(const InstallOptions &other) : d(other.d) { } InstallOptions::InstallOptions(InstallOptions &&other) Q_DECL_NOEXCEPT = default; InstallOptions &InstallOptions::operator=(const InstallOptions &other) { d = other.d; return *this; } InstallOptions &InstallOptions::operator=(InstallOptions &&other) Q_DECL_NOEXCEPT = default; InstallOptions::~InstallOptions() { } /*! * \brief The default install root, relative to the build directory. */ QString InstallOptions::defaultInstallRoot() { return QStringLiteral("install-root"); } /*! * Returns the base directory for the installation. * The \c qbs.installPrefix path is relative to this root. If the string is empty, either the value of * qbs.sysroot or "/install-root" will be used, depending on what \c installIntoSysroot() * returns. * The default is empty. */ QString InstallOptions::installRoot() const { return d->installRoot; } /*! * \brief Sets the base directory for the installation. * \note The argument must either be an empty string or an absolute path to a directory * (which might not yet exist, in which case it will be created). */ void InstallOptions::setInstallRoot(const QString &installRoot) { d->installRoot = QDir::cleanPath(installRoot); if (!QDir(installRoot).isRoot()) { while (d->installRoot.endsWith(QLatin1Char('/'))) d->installRoot.chop(1); } } /*! * Returns whether to use the sysroot as the default install root. * The default is false. */ bool InstallOptions::installIntoSysroot() const { return d->useSysroot; } void InstallOptions::setInstallIntoSysroot(bool useSysroot) { d->useSysroot = useSysroot; } /*! * \brief Returns true iff an existing installation will be removed prior to installing. * The default is false. */ bool InstallOptions::removeExistingInstallation() const { return d->removeExisting; } /*! * Controls whether to remove an existing installation before installing. * \note qbs may do some safety checks and refuse to remove certain directories such as * a user's home directory. You should still be careful with this option, since it * deletes recursively. */ void InstallOptions::setRemoveExistingInstallation(bool removeExisting) { d->removeExisting = removeExisting; } /*! * \brief Returns true iff qbs will not actually copy any files, but just show what would happen. * The default is false. */ bool InstallOptions::dryRun() const { return d->dryRun; } /*! * \brief Controls whether installation will actually take place. * If the argument is true, then qbs will emit information about which files would be copied * instead of actually doing it. */ void InstallOptions::setDryRun(bool dryRun) { d->dryRun = dryRun; } /*! * Returns true iff installation will continue if an error occurs. * The default is false. */ bool InstallOptions::keepGoing() const { return d->keepGoing; } /*! * \brief Controls whether to abort on errors. * If the argument is true, then if a file cannot be copied e.g. due to a permission problem, * a warning will be printed and the installation will continue. If the argument is false, * then the installation will abort immediately in case of an error. */ void InstallOptions::setKeepGoing(bool keepGoing) { d->keepGoing = keepGoing; } /*! * \brief Returns true iff the time the operation takes will be logged. * The default is false. */ bool InstallOptions::logElapsedTime() const { return d->logElapsedTime; } /*! * \brief Controls whether the installation time will be measured and logged. */ void InstallOptions::setLogElapsedTime(bool logElapsedTime) { d->logElapsedTime = logElapsedTime; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/installoptions.h000066400000000000000000000062571347155106100225330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_INSTALLOPTIONS_H #define QBS_INSTALLOPTIONS_H #include "qbs_export.h" #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { class InstallOptions; namespace Internal { class InstallOptionsPrivate; class TopLevelProject; QString effectiveInstallRoot(const InstallOptions &options, const TopLevelProject *project); } class QBS_EXPORT InstallOptions { public: InstallOptions(); InstallOptions(const InstallOptions &other); InstallOptions(InstallOptions &&other) Q_DECL_NOEXCEPT; InstallOptions &operator=(const InstallOptions &other); InstallOptions &operator=(InstallOptions &&other) Q_DECL_NOEXCEPT; ~InstallOptions(); static QString defaultInstallRoot(); QString installRoot() const; void setInstallRoot(const QString &installRoot); bool installIntoSysroot() const; void setInstallIntoSysroot(bool useSysroot); bool removeExistingInstallation() const; void setRemoveExistingInstallation(bool removeExisting); bool dryRun() const; void setDryRun(bool dryRun); bool keepGoing() const; void setKeepGoing(bool keepGoing); bool logElapsedTime() const; void setLogElapsedTime(bool logElapsedTime); private: QSharedDataPointer d; }; } // namespace qbs #endif // QBS_INSTALLOPTIONS_H qbs-src-1.13.1/src/lib/corelib/tools/iosutils.h000066400000000000000000000067741347155106100213300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_IOSUTILS_H #define QBS_IOSUTILS_H #include #include #include #if defined(_WIN32) && defined(_MSC_VER) #include #include #define QBS_RENAME_IMPL ::_wrename #define QBS_UNLINK_IMPL ::_wunlink using qbs_filesystem_path_string_type = std::wstring; #else #include #define QBS_RENAME_IMPL ::rename #define QBS_UNLINK_IMPL ::unlink using qbs_filesystem_path_string_type = std::string; #endif namespace qbs { namespace Internal { static inline bool fwrite(const char *values, size_t nitems, std::ostream *stream) { if (!stream) return false; stream->write(values, nitems); return stream->good(); } template bool fwrite(const C &container, std::ostream *stream) { return fwrite(&*(std::begin(container)), container.size(), stream); } static inline bool fwrite(const char *s, std::ostream *stream) { return fwrite(s, strlen(s), stream); } static inline qbs_filesystem_path_string_type utf8_to_native_path(const std::string &str) { #if defined(_WIN32) && defined(_MSC_VER) std::wstring_convert> converter; return converter.from_bytes(str); #else return str; #endif } static inline int rename(const std::string &oldName, const std::string &newName) { const auto wOldName = utf8_to_native_path(oldName); const auto wNewName = utf8_to_native_path(newName); return QBS_RENAME_IMPL(wOldName.c_str(), wNewName.c_str()); } static inline int unlink(const std::string &name) { const auto wName = utf8_to_native_path(name); return QBS_UNLINK_IMPL(wName.c_str()); } } // namespace Internal } // namespace qbs #endif // QBS_IOSUTILS_H qbs-src-1.13.1/src/lib/corelib/tools/joblimits.cpp000066400000000000000000000122101347155106100217620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "joblimits.h" #include #include #include namespace qbs { namespace Internal { static int transformLimit(int limitFromUser) { return limitFromUser == 0 ? std::numeric_limits::max() : limitFromUser < -1 ? -1 : limitFromUser; } class JobLimitPrivate : public QSharedData { public: JobLimitPrivate(const QString &pool, int limit) : jobLimit(std::make_pair(pool, transformLimit(limit))) { } template void serializationOp(PersistentPool &pool) { pool.serializationOp(jobLimit); } std::pair jobLimit; }; class JobLimitsPrivate : public QSharedData { public: template void serializationOp(PersistentPool &pool) { pool.serializationOp(jobLimits); } std::vector jobLimits; }; } // namespace Internal JobLimit::JobLimit() : JobLimit(QString(), -1) { } JobLimit::JobLimit(const QString &pool, int limit) : d(new Internal::JobLimitPrivate(pool, limit)) { } JobLimit::JobLimit(const JobLimit &other) : d(other.d) { } JobLimit &JobLimit::operator=(const JobLimit &other) { d = other.d; return *this; } JobLimit::~JobLimit() {} QString JobLimit::pool() const { return d->jobLimit.first; } int JobLimit::limit() const { return d->jobLimit.second; } void JobLimit::load(Internal::PersistentPool &pool) { d->serializationOp(pool); } void JobLimit::store(Internal::PersistentPool &pool) { d->serializationOp(pool); } JobLimits::JobLimits() : d(new Internal::JobLimitsPrivate) { } JobLimits::JobLimits(const JobLimits &other) : d(other.d) { } JobLimits &JobLimits::operator=(const JobLimits &other) { d = other.d; return *this; } JobLimits::~JobLimits() {} void JobLimits::setJobLimit(const JobLimit &limit) { for (std::size_t i = 0; i < d->jobLimits.size(); ++i) { JobLimit ¤tLimit = d->jobLimits.at(i); if (currentLimit.pool() == limit.pool()) { if (currentLimit.limit() != limit.limit()) currentLimit = limit; return; } } d->jobLimits.push_back(limit); } void JobLimits::setJobLimit(const QString &pool, int limit) { setJobLimit(JobLimit(pool, limit)); } int JobLimits::getLimit(const QString &pool) const { for (const JobLimit &l : d->jobLimits) { if (l.pool() == pool) return l.limit(); } return -1; } bool JobLimits::isEmpty() const { return d->jobLimits.empty(); } int JobLimits::count() const { return d->jobLimits.size(); } JobLimit JobLimits::jobLimitAt(int i) const { return d->jobLimits.at(i); } JobLimits &JobLimits::update(const JobLimits &other) { if (isEmpty()) { *this = other; } else { for (int i = 0; i < other.count(); ++i) { const JobLimit &l = other.jobLimitAt(i); if (l.limit() != -1) setJobLimit(l); } } return *this; } void JobLimits::load(Internal::PersistentPool &pool) { d->serializationOp(pool); } void JobLimits::store(Internal::PersistentPool &pool) { d->serializationOp(pool); } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/joblimits.h000066400000000000000000000063411347155106100214370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_JOB_LIMITS_H #define QBS_JOB_LIMITS_H #include "qbs_export.h" #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { namespace Internal { class JobLimitPrivate; class JobLimitsPrivate; class PersistentPool; } class QBS_EXPORT JobLimit { public: JobLimit(); JobLimit(const QString &pool, int limit); JobLimit(const JobLimit &other); JobLimit &operator=(const JobLimit &other); ~JobLimit(); QString pool() const; int limit() const; void load(Internal::PersistentPool &pool); void store(Internal::PersistentPool &pool); private: QSharedDataPointer d; }; class QBS_EXPORT JobLimits { public: JobLimits(); JobLimits(const JobLimits &other); JobLimits &operator=(const JobLimits &other); ~JobLimits(); void setJobLimit(const JobLimit &limit); void setJobLimit(const QString &pool, int limit); int getLimit(const QString &pool) const; bool hasLimit(const QString &pool) const { return getLimit(pool) != -1; } bool isEmpty() const; int count() const; JobLimit jobLimitAt(int i) const; JobLimits &update(const JobLimits &other); void load(Internal::PersistentPool &pool); void store(Internal::PersistentPool &pool); private: QSharedDataPointer d; }; } // namespace qbs #endif // include guard qbs-src-1.13.1/src/lib/corelib/tools/jsliterals.cpp000066400000000000000000000074331347155106100221550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "jsliterals.h" #include #include namespace qbs { QString toJSLiteral(const bool b) { return b ? Internal::StringConstants::trueValue() : Internal::StringConstants::falseValue(); } QString toJSLiteral(const QString &str) { QString js = str; js.replace(QRegExp(QLatin1String("([\\\\\"])")), QLatin1String("\\\\1")); js.prepend(QLatin1Char('"')); js.append(QLatin1Char('"')); return js; } QString toJSLiteral(const QStringList &strs) { QString js = QStringLiteral("["); for (int i = 0; i < strs.size(); ++i) { if (i != 0) js.append(QLatin1String(", ")); js.append(toJSLiteral(strs.at(i))); } js.append(QLatin1Char(']')); return js; } QString toJSLiteral(const QVariant &val) { if (!val.isValid()) return Internal::StringConstants::undefinedValue(); if (val.type() == QVariant::List || val.type() == QVariant::StringList) { QString res; for (const QVariant &child : val.toList()) { if (res.length()) res.append(QLatin1String(", ")); res.append(toJSLiteral(child)); } res.prepend(QLatin1Char('[')); res.append(QLatin1Char(']')); return res; } if (val.type() == QVariant::Map) { const QVariantMap &vm = val.toMap(); QString str = QStringLiteral("{"); for (QVariantMap::const_iterator it = vm.begin(); it != vm.end(); ++it) { if (it != vm.begin()) str += QLatin1Char(','); str += toJSLiteral(it.key()) + QLatin1Char(':') + toJSLiteral(it.value()); } str += QLatin1Char('}'); return str; } if (val.type() == QVariant::Bool) return toJSLiteral(val.toBool()); if (val.canConvert(QVariant::String)) return toJSLiteral(val.toString()); return QStringLiteral("Unconvertible type %1").arg(QLatin1String(val.typeName())); } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/jsliterals.h000066400000000000000000000044301347155106100216140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_JSLITERALS_H #define QBS_JSLITERALS_H #include "qbs_export.h" #include #include #include namespace qbs { QBS_EXPORT QString toJSLiteral(const bool b); QBS_EXPORT QString toJSLiteral(const QString &str); QBS_EXPORT QString toJSLiteral(const QStringList &strs); QBS_EXPORT QString toJSLiteral(const QVariant &val); } // namespace qbs #endif // QBS_JSLITERALS_H qbs-src-1.13.1/src/lib/corelib/tools/launcherinterface.cpp000066400000000000000000000127061347155106100234620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "launcherinterface.h" #include "launcherpackets.h" #include "launchersocket.h" #include "qbsassert.h" #include #include #include #include #include #include #include #ifdef Q_OS_UNIX #include #endif namespace qbs { namespace Internal { class LauncherProcess : public QProcess { public: LauncherProcess(QObject *parent) : QProcess(parent) { } private: void setupChildProcess() override { #ifdef Q_OS_UNIX const pid_t pid = static_cast(processId()); setpgid(pid, pid); #endif } }; static QString launcherSocketName() { return QStringLiteral("qbs_processlauncher-%1") .arg(QString::number(qApp->applicationPid())); } LauncherInterface::LauncherInterface() : m_server(new QLocalServer(this)), m_socket(new LauncherSocket(this)) { QObject::connect(m_server, &QLocalServer::newConnection, this, &LauncherInterface::handleNewConnection); } LauncherInterface &LauncherInterface::instance() { static LauncherInterface p; return p; } LauncherInterface::~LauncherInterface() { m_server->disconnect(); } void LauncherInterface::doStart() { if (++m_startRequests > 1) return; const QString &socketName = launcherSocketName(); QLocalServer::removeServer(socketName); if (!m_server->listen(socketName)) { emit errorOccurred(ErrorInfo(m_server->errorString())); return; } m_process = new LauncherProcess(this); connect(m_process, static_cast(&QProcess::error), this, &LauncherInterface::handleProcessError); connect(m_process, static_cast(&QProcess::finished), this, &LauncherInterface::handleProcessFinished); connect(m_process, &QProcess::readyReadStandardError, this, &LauncherInterface::handleProcessStderr); m_process->start(qApp->applicationDirPath() + QLatin1Char('/') + QLatin1String(QBS_RELATIVE_LIBEXEC_PATH) + QLatin1String("/qbs_processlauncher"), QStringList(m_server->fullServerName())); } void LauncherInterface::doStop() { if (--m_startRequests > 0) return; m_server->close(); if (!m_process) return; m_process->disconnect(); if (m_socket->isReady()) m_socket->shutdown(); m_process->waitForFinished(3000); m_process->deleteLater(); m_process = nullptr; } void LauncherInterface::handleNewConnection() { QLocalSocket * const socket = m_server->nextPendingConnection(); if (!socket) return; m_server->close(); m_socket->setSocket(socket); } void LauncherInterface::handleProcessError() { if (m_process->error() == QProcess::FailedToStart) { const QString launcherPathForUser = QDir::toNativeSeparators(QDir::cleanPath(m_process->program())); emit errorOccurred(ErrorInfo(Tr::tr("Failed to start process launcher at '%1': %2") .arg(launcherPathForUser, m_process->errorString()))); } } void LauncherInterface::handleProcessFinished() { emit errorOccurred(ErrorInfo(Tr::tr("Process launcher closed unexpectedly: %1") .arg(m_process->errorString()))); } void LauncherInterface::handleProcessStderr() { qDebug() << "[launcher]" << m_process->readAllStandardError(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/launcherinterface.h000066400000000000000000000055661347155106100231350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LAUNCHERINTERFACE_H #define QBS_LAUNCHERINTERFACE_H #include QT_BEGIN_NAMESPACE class QLocalServer; QT_END_NAMESPACE namespace qbs { class ErrorInfo; namespace Internal { class LauncherProcess; class LauncherSocket; class LauncherInterface : public QObject { Q_OBJECT public: static LauncherInterface &instance(); ~LauncherInterface(); static void startLauncher() { instance().doStart(); } static void stopLauncher() { instance().doStop(); } static LauncherSocket *socket() { return instance().m_socket; } signals: void errorOccurred(const ErrorInfo &error); private: LauncherInterface(); void doStart(); void doStop(); void handleNewConnection(); void handleProcessError(); void handleProcessFinished(); void handleProcessStderr(); QLocalServer * const m_server; LauncherSocket * const m_socket; LauncherProcess * m_process = nullptr; int m_startRequests = 0; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/tools/launcherpackets.cpp000066400000000000000000000124661347155106100231570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "launcherpackets.h" #include #include namespace qbs { namespace Internal { LauncherPacket::~LauncherPacket() { } QByteArray LauncherPacket::serialize() const { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); stream << static_cast(0) << static_cast(type) << token; doSerialize(stream); stream.device()->reset(); stream << static_cast(data.size() - sizeof(int)); return data; } void LauncherPacket::deserialize(const QByteArray &data) { QDataStream stream(data); doDeserialize(stream); } StartProcessPacket::StartProcessPacket(quintptr token) : LauncherPacket(LauncherPacketType::StartProcess, token) { } void StartProcessPacket::doSerialize(QDataStream &stream) const { stream << command << arguments << workingDir << env; } void StartProcessPacket::doDeserialize(QDataStream &stream) { stream >> command >> arguments >> workingDir >> env; } StopProcessPacket::StopProcessPacket(quintptr token) : LauncherPacket(LauncherPacketType::StopProcess, token) { } void StopProcessPacket::doSerialize(QDataStream &stream) const { Q_UNUSED(stream); } void StopProcessPacket::doDeserialize(QDataStream &stream) { Q_UNUSED(stream); } ProcessErrorPacket::ProcessErrorPacket(quintptr token) : LauncherPacket(LauncherPacketType::ProcessError, token) { } void ProcessErrorPacket::doSerialize(QDataStream &stream) const { stream << static_cast(error) << errorString; } void ProcessErrorPacket::doDeserialize(QDataStream &stream) { quint8 e; stream >> e; error = static_cast(e); stream >> errorString; } ProcessFinishedPacket::ProcessFinishedPacket(quintptr token) : LauncherPacket(LauncherPacketType::ProcessFinished, token) { } void ProcessFinishedPacket::doSerialize(QDataStream &stream) const { stream << errorString << stdOut << stdErr << static_cast(exitStatus) << static_cast(error) << exitCode; } void ProcessFinishedPacket::doDeserialize(QDataStream &stream) { stream >> errorString >> stdOut >> stdErr; quint8 val; stream >> val; exitStatus = static_cast(val); stream >> val; error = static_cast(val); stream >> exitCode; } ShutdownPacket::ShutdownPacket() : LauncherPacket(LauncherPacketType::Shutdown, 0) { } void ShutdownPacket::doSerialize(QDataStream &stream) const { Q_UNUSED(stream); } void ShutdownPacket::doDeserialize(QDataStream &stream) { Q_UNUSED(stream); } void PacketParser::setDevice(QIODevice *device) { m_stream.setDevice(device); m_sizeOfNextPacket = -1; } bool PacketParser::parse() { static const int commonPayloadSize = static_cast(1 + sizeof(quintptr)); if (m_sizeOfNextPacket == -1) { if (m_stream.device()->bytesAvailable() < static_cast(sizeof m_sizeOfNextPacket)) return false; m_stream >> m_sizeOfNextPacket; if (m_sizeOfNextPacket < commonPayloadSize) throw InvalidPacketSizeException(m_sizeOfNextPacket); } if (m_stream.device()->bytesAvailable() < m_sizeOfNextPacket) return false; quint8 type; m_stream >> type; m_type = static_cast(type); m_stream >> m_token; m_packetData = m_stream.device()->read(m_sizeOfNextPacket - commonPayloadSize); m_sizeOfNextPacket = -1; return true; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/launcherpackets.h000066400000000000000000000115501347155106100226150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LAUNCHERPACKETS_H #define QBS_LAUNCHERPACKETS_H #include #include #include QT_BEGIN_NAMESPACE class QByteArray; QT_END_NAMESPACE namespace qbs { namespace Internal { enum class LauncherPacketType { Shutdown, StartProcess, StopProcess, ProcessError, ProcessFinished }; class PacketParser { public: class InvalidPacketSizeException { public: InvalidPacketSizeException(int size) : size(size) { } const int size; }; void setDevice(QIODevice *device); bool parse(); LauncherPacketType type() const { return m_type; } quintptr token() const { return m_token; } const QByteArray &packetData() const { return m_packetData; } private: QDataStream m_stream; LauncherPacketType m_type; quintptr m_token; QByteArray m_packetData; int m_sizeOfNextPacket = -1; }; class LauncherPacket { public: virtual ~LauncherPacket(); template static Packet extractPacket(quintptr token, const QByteArray &data) { Packet p(token); p.deserialize(data); return p; } QByteArray serialize() const; void deserialize(const QByteArray &data); const LauncherPacketType type; const quintptr token; protected: LauncherPacket(LauncherPacketType type, quintptr token) : type(type), token(token) { } private: virtual void doSerialize(QDataStream &stream) const = 0; virtual void doDeserialize(QDataStream &stream) = 0; }; class StartProcessPacket : public LauncherPacket { public: StartProcessPacket(quintptr token); QString command; QStringList arguments; QString workingDir; QStringList env; private: void doSerialize(QDataStream &stream) const override; void doDeserialize(QDataStream &stream) override; }; class StopProcessPacket : public LauncherPacket { public: StopProcessPacket(quintptr token); private: void doSerialize(QDataStream &stream) const override; void doDeserialize(QDataStream &stream) override; }; class ShutdownPacket : public LauncherPacket { public: ShutdownPacket(); private: void doSerialize(QDataStream &stream) const override; void doDeserialize(QDataStream &stream) override; }; class ProcessErrorPacket : public LauncherPacket { public: ProcessErrorPacket(quintptr token); QProcess::ProcessError error; QString errorString; private: void doSerialize(QDataStream &stream) const override; void doDeserialize(QDataStream &stream) override; }; class ProcessFinishedPacket : public LauncherPacket { public: ProcessFinishedPacket(quintptr token); QString errorString; QByteArray stdOut; QByteArray stdErr; QProcess::ExitStatus exitStatus; QProcess::ProcessError error; int exitCode; private: void doSerialize(QDataStream &stream) const override; void doDeserialize(QDataStream &stream) override; }; } // namespace Internal } // namespace qbs Q_DECLARE_METATYPE(qbs::Internal::LauncherPacketType); #endif // Include guard qbs-src-1.13.1/src/lib/corelib/tools/launchersocket.cpp000066400000000000000000000114471347155106100230130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "launchersocket.h" #include "qbsassert.h" #include "qttools.h" #include #include #include namespace qbs { namespace Internal { LauncherSocket::LauncherSocket(QObject *parent) : QObject(parent) { qRegisterMetaType(); qRegisterMetaType("quintptr"); } void LauncherSocket::sendData(const QByteArray &data) { if (!isReady()) return; std::lock_guard locker(m_requestsMutex); m_requests.push_back(data); if (m_requests.size() == 1) QTimer::singleShot(0, this, &LauncherSocket::handleRequests); } void LauncherSocket::shutdown() { QBS_ASSERT(m_socket, return); m_socket->disconnect(); m_socket->write(ShutdownPacket().serialize()); m_socket->waitForBytesWritten(1000); m_socket->deleteLater(); m_socket = nullptr; } void LauncherSocket::setSocket(QLocalSocket *socket) { QBS_ASSERT(!m_socket, return); m_socket = socket; m_packetParser.setDevice(m_socket); connect(m_socket, static_cast(&QLocalSocket::error), this, &LauncherSocket::handleSocketError); connect(m_socket, &QLocalSocket::readyRead, this, &LauncherSocket::handleSocketDataAvailable); connect(m_socket, &QLocalSocket::disconnected, this, &LauncherSocket::handleSocketDisconnected); emit ready(); } void LauncherSocket::handleSocketError() { if (m_socket->error() != QLocalSocket::PeerClosedError) handleError(Tr::tr("Socket error: %1").arg(m_socket->errorString())); } void LauncherSocket::handleSocketDataAvailable() { try { if (!m_packetParser.parse()) return; } catch (const PacketParser::InvalidPacketSizeException &e) { handleError(Tr::tr("Internal protocol error: invalid packet size %1.").arg(e.size)); return; } switch (m_packetParser.type()) { case LauncherPacketType::ProcessError: case LauncherPacketType::ProcessFinished: emit packetArrived(m_packetParser.type(), m_packetParser.token(), m_packetParser.packetData()); break; default: handleError(Tr::tr("Internal protocol error: invalid packet type %1.") .arg(static_cast(m_packetParser.type()))); return; } handleSocketDataAvailable(); } void LauncherSocket::handleSocketDisconnected() { handleError(Tr::tr("Launcher socket closed unexpectedly")); } void LauncherSocket::handleError(const QString &error) { m_socket->disconnect(); m_socket->deleteLater(); m_socket = nullptr; emit errorOccurred(error); } void LauncherSocket::handleRequests() { std::lock_guard locker(m_requestsMutex); for (const QByteArray &request : qAsConst(m_requests)) m_socket->write(request); m_requests.clear(); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/launchersocket.h000066400000000000000000000057611347155106100224620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LAUNCHERSOCKET_H #define QBS_LAUNCHERSOCKET_H #include "launcherpackets.h" #include #include #include QT_BEGIN_NAMESPACE class QLocalSocket; QT_END_NAMESPACE namespace qbs { namespace Internal { class LauncherInterface; class LauncherSocket : public QObject { Q_OBJECT friend class LauncherInterface; public: bool isReady() const { return m_socket; } void sendData(const QByteArray &data); signals: void ready(); void errorOccurred(const QString &error); void packetArrived(qbs::Internal::LauncherPacketType type, quintptr token, const QByteArray &payload); private: LauncherSocket(QObject *parent); void setSocket(QLocalSocket *socket); void shutdown(); void handleSocketError(); void handleSocketDataAvailable(); void handleSocketDisconnected(); void handleError(const QString &error); void handleRequests(); QLocalSocket *m_socket = nullptr; PacketParser m_packetParser; std::vector m_requests; std::mutex m_requestsMutex; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/tools/msvcinfo.cpp000066400000000000000000000216441347155106100216250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "msvcinfo.h" #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN #include #endif #include #include using namespace qbs; using namespace qbs::Internal; static std::recursive_mutex envMutex; static QString mkStr(const char *s) { return QString::fromLocal8Bit(s); } static QString mkStr(const QByteArray &ba) { return mkStr(ba.constData()); } class TemporaryEnvChanger { public: TemporaryEnvChanger(const QProcessEnvironment &envChanges) : m_locker(envMutex) { QProcessEnvironment currentEnv = QProcessEnvironment::systemEnvironment(); for (const QString &key : envChanges.keys()) { m_changesToRestore.insert(key, currentEnv.value(key)); qputenv(qPrintable(key), qPrintable(envChanges.value(key))); } } ~TemporaryEnvChanger() { for (const QString &key : m_changesToRestore.keys()) qputenv(qPrintable(key), qPrintable(m_changesToRestore.value(key))); } private: QProcessEnvironment m_changesToRestore; std::lock_guard m_locker; }; static QByteArray runProcess(const QString &exeFilePath, const QStringList &args, const QProcessEnvironment &env = QProcessEnvironment(), bool allowFailure = false, const QByteArray &pipeData = QByteArray()) { TemporaryEnvChanger envChanger(env); QProcess process; process.start(exeFilePath, args); if (!process.waitForStarted()) throw ErrorInfo(mkStr("Could not start %1 (%2)").arg(exeFilePath, process.errorString())); if (!pipeData.isEmpty()) { process.write(pipeData); process.closeWriteChannel(); } if (!process.waitForFinished(-1) || process.exitStatus() != QProcess::NormalExit) throw ErrorInfo(mkStr("Could not run %1 (%2)").arg(exeFilePath, process.errorString())); if (process.exitCode() != 0 && !allowFailure) { ErrorInfo e(mkStr("Process '%1' failed with exit code %2.") .arg(exeFilePath).arg(process.exitCode())); const QByteArray stdErr = process.readAllStandardError(); if (!stdErr.isEmpty()) e.append(mkStr("stderr was: %1").arg(mkStr(stdErr))); const QByteArray stdOut = process.readAllStandardOutput(); if (!stdOut.isEmpty()) e.append(mkStr("stdout was: %1").arg(mkStr(stdOut))); throw e; } return process.readAllStandardOutput().trimmed(); } class DummyFile { public: DummyFile(const QString &fp) : filePath(fp) { } ~DummyFile() { QFile::remove(filePath); } const QString filePath; }; #ifdef Q_OS_WIN static QStringList parseCommandLine(const QString &commandLine) { QStringList list; const auto buf = new wchar_t[commandLine.size() + 1]; buf[commandLine.toWCharArray(buf)] = 0; int argCount = 0; LPWSTR *args = CommandLineToArgvW(buf, &argCount); if (!args) throw ErrorInfo(mkStr("Could not parse command line arguments: ") + commandLine); for (int i = 0; i < argCount; ++i) list.push_back(QString::fromWCharArray(args[i])); delete[] buf; return list; } #endif static QVariantMap getMsvcDefines(const QString &compilerFilePath, const QProcessEnvironment &compilerEnv, MSVC::CompilerLanguage language) { #ifdef Q_OS_WIN QString backendSwitch, languageSwitch; switch (language) { case MSVC::CLanguage: backendSwitch = QStringLiteral("/B1"); languageSwitch = QStringLiteral("/TC"); break; case MSVC::CPlusPlusLanguage: backendSwitch = QStringLiteral("/Bx"); languageSwitch = QStringLiteral("/TP"); break; } const QByteArray commands("set MSC_CMD_FLAGS\n"); QStringList out = QString::fromLocal8Bit(runProcess(compilerFilePath, QStringList() << QStringLiteral("/nologo") << backendSwitch << QString::fromWCharArray(_wgetenv(L"COMSPEC")) << QStringLiteral("/c") << languageSwitch << QStringLiteral("NUL"), compilerEnv, true, commands)).split(QLatin1Char('\n')); auto findResult = std::find_if(out.cbegin(), out.cend(), [] (const QString &line) { return line.startsWith(QLatin1String("MSC_CMD_FLAGS=")); }); if (findResult == out.cend()) { throw ErrorInfo(QStringLiteral("Unexpected compiler frontend output: ") + out.join(QLatin1Char('\n'))); } QVariantMap map; const QStringList args = parseCommandLine(findResult->trimmed()); for (const QString &arg : args) { if (!arg.startsWith(QStringLiteral("-D"))) continue; int idx = arg.indexOf(QLatin1Char('='), 2); if (idx > 2) map.insert(arg.mid(2, idx - 2), arg.mid(idx + 1)); else map.insert(arg.mid(2), QVariant()); } return map; #else Q_UNUSED(compilerFilePath); Q_UNUSED(compilerEnv); Q_UNUSED(language); return {}; #endif } void MSVC::init() { determineCompilerVersion(); } QString MSVC::binPathForArchitecture(const QString &arch) const { QString archSubDir; if (arch != StringConstants::x86Arch()) archSubDir = arch; return QDir::cleanPath(vcInstallPath + QLatin1Char('/') + pathPrefix + QLatin1Char('/') + archSubDir); } static QString clExeSuffix() { return QStringLiteral("/cl.exe"); } QString MSVC::clPathForArchitecture(const QString &arch) const { return binPathForArchitecture(arch) + clExeSuffix(); } QVariantMap MSVC::compilerDefines(const QString &compilerFilePath, MSVC::CompilerLanguage language) const { return getMsvcDefines(compilerFilePath, environment, language); } void MSVC::determineCompilerVersion() { QString cppFilePath; { QTemporaryFile cppFile(QDir::tempPath() + QLatin1String("/qbsXXXXXX.cpp")); cppFile.setAutoRemove(false); if (!cppFile.open()) { throw ErrorInfo(mkStr("Could not create temporary file (%1)") .arg(cppFile.errorString())); } cppFilePath = cppFile.fileName(); cppFile.write("_MSC_FULL_VER"); cppFile.close(); } DummyFile fileDeleter(cppFilePath); std::lock_guard locker(envMutex); const QByteArray origPath = qgetenv("PATH"); qputenv("PATH", environment.value(StringConstants::pathEnvVar()).toLatin1() + ';' + origPath); QByteArray versionStr = runProcess( binPath + clExeSuffix(), QStringList() << QStringLiteral("/nologo") << QStringLiteral("/EP") << QDir::toNativeSeparators(cppFilePath)); qputenv("PATH", origPath); compilerVersion = Version(versionStr.mid(0, 2).toInt(), versionStr.mid(2, 2).toInt(), versionStr.mid(4).toInt()); } qbs-src-1.13.1/src/lib/corelib/tools/msvcinfo.h000066400000000000000000000072271347155106100212730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_MSVCINFO_H #define QBS_MSVCINFO_H #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { /** * Represents one MSVC installation for one specific target architecture. * There are potentially multiple MSVCs in one Visual Studio installation. */ class MSVC { public: enum CompilerLanguage { CLanguage = 0, CPlusPlusLanguage = 1 }; QString version; Version internalVsVersion; Version compilerVersion; QString vsInstallPath; QString vcInstallPath; QString binPath; QString pathPrefix; QString architecture; QProcessEnvironment environment; MSVC() { } MSVC(const QString &clPath) { QDir parentDir = QFileInfo(clPath).dir(); binPath = parentDir.absolutePath(); QString parentDirName = parentDir.dirName().toLower(); if (parentDirName == QLatin1String("bin")) parentDirName = QStringLiteral("x86"); else parentDir.cdUp(); architecture = parentDirName; vcInstallPath = parentDir.path(); } QBS_EXPORT void init(); QBS_EXPORT QString binPathForArchitecture(const QString &arch) const; QBS_EXPORT QString clPathForArchitecture(const QString &arch) const; QBS_EXPORT QVariantMap compilerDefines(const QString &compilerFilePath, CompilerLanguage language) const; private: void determineCompilerVersion(); }; class WinSDK : public MSVC { public: bool isDefault; WinSDK() { pathPrefix = QStringLiteral("bin"); } }; } // namespace Internal } // namespace qbs #endif // QBS_MSVCINFO_H qbs-src-1.13.1/src/lib/corelib/tools/pathutils.h000066400000000000000000000046321347155106100214610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PATHUTILS_H #define QBS_PATHUTILS_H #include "hostosinfo.h" #include "qbs_export.h" namespace qbs { namespace Internal { class QBS_EXPORT PathUtils { public: static QString toNativeSeparators(const QString &s, HostOsInfo::HostOs os = HostOsInfo::hostOs()) { QString value = s; if (os == HostOsInfo::HostOsWindows) value.replace(QLatin1Char('/'), HostOsInfo::pathSeparator(os)); return value; } }; } // namespace Internal } // namespace qbs #endif // QBS_PATHUTILS_H qbs-src-1.13.1/src/lib/corelib/tools/persistence.cpp000066400000000000000000000167151347155106100223300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "persistence.h" #include "fileinfo.h" #include #include #include namespace qbs { namespace Internal { static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE-126"; NoBuildGraphError::NoBuildGraphError(const QString &filePath) : ErrorInfo(Tr::tr("Build graph not found for configuration '%1'. Expected location was '%2'.") .arg(FileInfo::completeBaseName(filePath), QDir::toNativeSeparators(filePath))) { } PersistentPool::PersistentPool(Logger &logger) : m_logger(logger) { Q_UNUSED(m_logger); m_stream.setVersion(QDataStream::Qt_4_8); } PersistentPool::~PersistentPool() { closeStream(); } void PersistentPool::load(const QString &filePath) { std::unique_ptr file(new QFile(filePath)); if (!file->exists()) throw NoBuildGraphError(filePath); if (!file->open(QFile::ReadOnly)) { throw ErrorInfo(Tr::tr("Could not open open build graph file '%1': %2") .arg(filePath, file->errorString())); } m_stream.setDevice(file.get()); QByteArray magic; m_stream >> magic; if (magic != QBS_PERSISTENCE_MAGIC) { m_stream.setDevice(nullptr); throw ErrorInfo(Tr::tr("Cannot use stored build graph at '%1': Incompatible file format. " "Expected magic token '%2', got '%3'.") .arg(filePath, QLatin1String(QBS_PERSISTENCE_MAGIC), QString::fromLatin1(magic))); } m_stream >> m_headData.projectConfig; file.release(); m_loadedRaw.clear(); m_loaded.clear(); m_storageIndices.clear(); m_stringStorage.clear(); m_inverseStringStorage.clear(); } void PersistentPool::setupWriteStream(const QString &filePath) { QString dirPath = FileInfo::path(filePath); if (!FileInfo::exists(dirPath) && !QDir().mkpath(dirPath)) { throw ErrorInfo(Tr::tr("Failure storing build graph: Cannot create directory '%1'.") .arg(dirPath)); } if (QFile::exists(filePath) && !QFile::remove(filePath)) { throw ErrorInfo(Tr::tr("Failure storing build graph: Cannot remove old file '%1'") .arg(filePath)); } QBS_CHECK(!QFile::exists(filePath)); std::unique_ptr file(new QFile(filePath)); if (!file->open(QFile::WriteOnly)) { throw ErrorInfo(Tr::tr("Failure storing build graph: " "Cannot open file '%1' for writing: %2").arg(filePath, file->errorString())); } m_stream.setDevice(file.release()); m_stream << QByteArray(qstrlen(QBS_PERSISTENCE_MAGIC), 0) << m_headData.projectConfig; m_lastStoredObjectId = 0; m_lastStoredStringId = 0; m_lastStoredEnvId = 0; m_lastStoredStringListId = 0; } void PersistentPool::finalizeWriteStream() { if (m_stream.status() != QDataStream::Ok) throw ErrorInfo(Tr::tr("Failure serializing build graph.")); m_stream.device()->seek(0); m_stream << QByteArray(QBS_PERSISTENCE_MAGIC); if (m_stream.status() != QDataStream::Ok) throw ErrorInfo(Tr::tr("Failure serializing build graph.")); const auto file = static_cast(m_stream.device()); if (!file->flush()) { file->close(); file->remove(); throw ErrorInfo(Tr::tr("Failure serializing build graph: %1").arg(file->errorString())); } } void PersistentPool::closeStream() { delete m_stream.device(); m_stream.setDevice(nullptr); } void PersistentPool::storeVariant(const QVariant &variant) { const quint32 type = static_cast(variant.type()); m_stream << type; switch (type) { case QMetaType::QString: store(variant.toString()); break; case QMetaType::QStringList: store(variant.toStringList()); break; case QMetaType::QVariantList: store(variant.toList()); break; case QMetaType::QVariantMap: store(variant.toMap()); break; default: m_stream << variant; } } QVariant PersistentPool::loadVariant() { const quint32 type = load(); QVariant value; switch (type) { case QMetaType::QString: value = load(); break; case QMetaType::QStringList: value = load(); break; case QMetaType::QVariantList: value = load(); break; case QMetaType::QVariantMap: value = load(); break; default: m_stream >> value; } return value; } void PersistentPool::clear() { m_loaded.clear(); m_storageIndices.clear(); m_stringStorage.clear(); m_inverseStringStorage.clear(); } void PersistentPool::doLoadValue(QString &s) { m_stream >> s; } void PersistentPool::doLoadValue(QStringList &l) { int size; m_stream >> size; for (int i = 0; i < size; ++i) l << load(); } void PersistentPool::doLoadValue(QProcessEnvironment &env) { const QStringList keys = load(); for (const QString &key : keys) env.insert(key, load()); } void PersistentPool::doStoreValue(const QString &s) { m_stream << s; } void PersistentPool::doStoreValue(const QStringList &l) { m_stream << l.size(); for (const QString &s : l) store(s); } void PersistentPool::doStoreValue(const QProcessEnvironment &env) { const QStringList &keys = env.keys(); store(keys); for (const QString &key : keys) store(env.value(key)); } const PersistentPool::PersistentObjectId PersistentPool::ValueNotFoundId; const PersistentPool::PersistentObjectId PersistentPool::EmptyValueId; } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/persistence.h000066400000000000000000000403361347155106100217710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PERSISTENCE #define QBS_PERSISTENCE #include "error.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class NoBuildGraphError : public ErrorInfo { public: NoBuildGraphError(const QString &filePath); }; template struct PPHelper; class PersistentPool { public: PersistentPool(Logger &logger); ~PersistentPool(); class HeadData { public: QVariantMap projectConfig; }; template void store(const T &value, const Types &...args) { PPHelper::store(value, this); store(args...); } template void load(T &value, Types &...args) { PPHelper::load(value, this); load(args...); } template T load() { T tmp; PPHelper::load(tmp, this); return tmp; } enum OpType { Store, Load }; template struct OpTypeHelper { }; template struct OpTypeHelper { static void serializationOp(PersistentPool *pool, const T &value, const Types &...args) { pool->store(value, args...); } }; template struct OpTypeHelper { static void serializationOp(PersistentPool *pool, T &value, Types &...args) { pool->load(value, args...); } }; template void serializationOp(const T &value, const Types &...args) { OpTypeHelper::serializationOp(this, value, args...); } template void serializationOp(T &value, Types &...args) { OpTypeHelper::serializationOp(this, value, args...); } void load(const QString &filePath); void setupWriteStream(const QString &filePath); void finalizeWriteStream(); void closeStream(); void clear(); const HeadData &headData() const { return m_headData; } void setHeadData(const HeadData &hd) { m_headData = hd; } private: using PersistentObjectId = int; template T *idLoad(); template std::shared_ptr idLoadS(); template T idLoadValue(); void doLoadValue(QString &s); void doLoadValue(QStringList &l); void doLoadValue(QProcessEnvironment &env); template void storeSharedObject(const T *object); void storeVariant(const QVariant &variant); QVariant loadVariant(); template void idStoreValue(const T &value); void doStoreValue(const QString &s); void doStoreValue(const QStringList &l); void doStoreValue(const QProcessEnvironment &env); template std::vector &idStorage(); template QHash &idMap(); template PersistentObjectId &lastStoredId(); // Recursion termination void store() {} void load() {} static const PersistentObjectId ValueNotFoundId = -1; static const PersistentObjectId EmptyValueId = -2; QDataStream m_stream; HeadData m_headData; std::vector m_loadedRaw; std::vector> m_loaded; QHash m_storageIndices; PersistentObjectId m_lastStoredObjectId; std::vector m_stringStorage; QHash m_inverseStringStorage; PersistentObjectId m_lastStoredStringId; std::vector m_envStorage; QHash m_inverseEnvStorage; PersistentObjectId m_lastStoredEnvId; std::vector m_stringListStorage; QHash m_inverseStringListStorage; PersistentObjectId m_lastStoredStringListId; Logger &m_logger; template friend struct PPHelper; }; template inline const void *uniqueAddress(const T *t) { return t; } template inline void PersistentPool::storeSharedObject(const T *object) { if (!object) { m_stream << -1; return; } const void * const addr = uniqueAddress(object); PersistentObjectId id = m_storageIndices.value(addr, -1); if (id < 0) { id = m_lastStoredObjectId++; m_storageIndices.insert(addr, id); m_stream << id; store(*object); } else { m_stream << id; } } template inline T *PersistentPool::idLoad() { PersistentObjectId id; m_stream >> id; if (id < 0) return nullptr; if (id < static_cast(m_loadedRaw.size())) return static_cast(m_loadedRaw.at(id)); auto i = m_loadedRaw.size(); m_loadedRaw.resize(id + 1); for (; i < m_loadedRaw.size(); ++i) m_loadedRaw[i] = nullptr; const auto t = new T; m_loadedRaw[id] = t; load(*t); return t; } template<> inline std::vector &PersistentPool::idStorage() { return m_stringStorage; } template<> inline QHash &PersistentPool::idMap() { return m_inverseStringStorage; } template<> inline PersistentPool::PersistentObjectId &PersistentPool::lastStoredId() { return m_lastStoredStringId; } template<> inline std::vector &PersistentPool::idStorage() { return m_stringListStorage; } template<> inline QHash &PersistentPool::idMap() { return m_inverseStringListStorage; } template<> inline PersistentPool::PersistentObjectId &PersistentPool::lastStoredId() { return m_lastStoredStringListId; } template<> inline std::vector &PersistentPool::idStorage() { return m_envStorage; } template<> inline QHash &PersistentPool::idMap() { return m_inverseEnvStorage; } template<> inline PersistentPool::PersistentObjectId &PersistentPool::lastStoredId() { return m_lastStoredEnvId; } template inline std::shared_ptr PersistentPool::idLoadS() { PersistentObjectId id; m_stream >> id; if (id < 0) return std::shared_ptr(); if (id < static_cast(m_loaded.size())) return std::static_pointer_cast(m_loaded.at(id)); m_loaded.resize(id + 1); const std::shared_ptr t = T::create(); m_loaded[id] = t; load(*t); return t; } template inline T PersistentPool::idLoadValue() { int id; m_stream >> id; if (id == EmptyValueId) return T(); QBS_CHECK(id >= 0); if (id >= static_cast(idStorage().size())) { T value; doLoadValue(value); idStorage().resize(id + 1); idStorage()[id] = value; return value; } return idStorage().at(id); } template void PersistentPool::idStoreValue(const T &value) { if (value.isEmpty()) { m_stream << EmptyValueId; return; } int id = idMap().value(value, ValueNotFoundId); if (id < 0) { id = lastStoredId()++; idMap().insert(value, id); m_stream << id; doStoreValue(value); } else { m_stream << id; } } // We need a helper class template, because we require partial specialization for some of // the aggregate types, which is not possible with function templates. // The generic implementation assumes that T is of class type and has load() and store() // member functions. template struct PPHelper { static void store(const T &object, PersistentPool *pool) { const_cast(object).store(*pool); } static void load(T &object, PersistentPool *pool) { object.load(*pool); } }; /***** Specializations of Helper class *****/ template struct PPHelper)>::value>> { static void store(const T &value, PersistentPool *pool) { const_cast(value).template completeSerializationOp(*pool); } static void load(T &value, PersistentPool *pool) { value.template completeSerializationOp(*pool); } }; template struct PPHelper::value>> { static void store(const T &value, PersistentPool *pool) { pool->m_stream << value; } static void load(T &value, PersistentPool *pool) { pool->m_stream >> value; } }; template<> struct PPHelper { static void store(long value, PersistentPool *pool) { pool->m_stream << qint64(value); } static void load(long &value, PersistentPool *pool) { qint64 v; pool->m_stream >> v; value = long(v); } }; template struct PPHelper::value>> { using U = std::underlying_type_t; static void store(const T &value, PersistentPool *pool) { pool->m_stream << static_cast(value); } static void load(T &value, PersistentPool *pool) { pool->m_stream >> reinterpret_cast(value); } }; template struct PPHelper> { static void store(const std::shared_ptr &value, PersistentPool *pool) { pool->store(value.get()); } static void load(std::shared_ptr &value, PersistentPool *pool) { value = pool->idLoadS>(); } }; template struct PPHelper> { static void store(const std::unique_ptr &value, PersistentPool *pool) { pool->store(value.get()); } static void load(std::unique_ptr &ptr, PersistentPool *pool) { ptr.reset(pool->idLoad>()); } }; template struct PPHelper { static void store(const T *value, PersistentPool *pool) { pool->storeSharedObject(value); } static void load(T* &value, PersistentPool *pool) { value = pool->idLoad(); } }; template struct PPHelper::value || std::is_same::value || std::is_same::value>> { static void store(const T &v, PersistentPool *pool) { pool->idStoreValue(v); } static void load(T &v, PersistentPool *pool) { v = pool->idLoadValue(); } }; template<> struct PPHelper { static void store(const QVariant &v, PersistentPool *pool) { pool->storeVariant(v); } static void load(QVariant &v, PersistentPool *pool) { v = pool->loadVariant(); } }; template<> struct PPHelper { static void store(const QRegExp &re, PersistentPool *pool) { pool->store(re.pattern()); } static void load(QRegExp &re, PersistentPool *pool) { re.setPattern(pool->load()); } }; template struct PPHelper> { static void store(const std::pair &pair, PersistentPool *pool) { pool->store(pair.first); pool->store(pair.second); } static void load(std::pair &pair, PersistentPool *pool) { pool->load(pair.first); pool->load(pair.second); } }; template struct PPHelper> { using Int = typename QFlags::Int; static void store(const QFlags &flags, PersistentPool *pool) { pool->store(flags); } static void load(QFlags &flags, PersistentPool *pool) { flags = QFlags(pool->load()); } }; template struct IsSimpleContainer : std::false_type { }; template struct IsSimpleContainer> : std::true_type { }; template struct IsSimpleContainer> : std::true_type { }; template struct PPHelper::value>> { static void store(const T &container, PersistentPool *pool) { pool->store(int(container.size())); for (auto it = container.cbegin(); it != container.cend(); ++it) pool->store(*it); } static void load(T &container, PersistentPool *pool) { const int count = pool->load(); container.clear(); container.reserve(count); for (int i = count; --i >= 0;) container.push_back(pool->load()); } }; template struct IsKeyValueContainer : std::false_type { }; template struct IsKeyValueContainer> : std::true_type { }; template struct IsKeyValueContainer> : std::true_type { }; template struct PPHelper::value>> { static void store(const T &container, PersistentPool *pool) { pool->store(container.size()); for (auto it = container.cbegin(); it != container.cend(); ++it) { pool->store(it.key()); pool->store(it.value()); } } static void load(T &container, PersistentPool *pool) { container.clear(); const int count = pool->load(); for (int i = 0; i < count; ++i) { const auto &key = pool->load(); const auto &value = pool->load(); container.insert(key, value); } } }; template struct PPHelper> { static void store(const std::unordered_map &map, PersistentPool *pool) { pool->store(quint32(map.size())); for (auto it = map.cbegin(); it != map.cend(); ++it) pool->store(*it); } static void load(std::unordered_map &map, PersistentPool *pool) { map.clear(); const auto count = pool->load(); for (std::size_t i = 0; i < count; ++i) map.insert(pool->load>()); } }; } // namespace Internal } // namespace qbs #endif qbs-src-1.13.1/src/lib/corelib/tools/preferences.cpp000066400000000000000000000160641347155106100223020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "preferences.h" #include "buildoptions.h" #include "hostosinfo.h" #include "profile.h" #include "stringconstants.h" namespace qbs { /*! * \class Preferences * \brief The \c Preferences class gives access to all general qbs preferences. * If a non-empty \c profileName is given, the profile's preferences take precedence over global * ones. Otherwise, the global preferences are used. */ Preferences::Preferences(Settings *settings, const QString &profileName) : m_settings(settings), m_profile(profileName) { } Preferences::Preferences(Settings *settings, const QVariantMap &profileContents) : m_settings(settings), m_profileContents(profileContents) { } /*! * \brief Returns true <=> colored output should be used for printing messages. * This is only relevant for command-line frontends. */ bool Preferences::useColoredOutput() const { return getPreference(QStringLiteral("useColoredOutput"), true).toBool(); } /*! * \brief Returns the number of parallel jobs to use for building. * Uses a sensible default value if there is no such setting. */ int Preferences::jobs() const { return getPreference(QStringLiteral("jobs"), BuildOptions::defaultMaxJobCount()).toInt(); } /*! * \brief Returns the shell to use for the "qbs shell" command. * This is only relevant for command-line frontends. */ QString Preferences::shell() const { return getPreference(QStringLiteral("shell")).toString(); } /*! * \brief Returns the default build directory used by Qbs if none is specified. */ QString Preferences::defaultBuildDirectory() const { return getPreference(QStringLiteral("defaultBuildDirectory")).toString(); } /*! * \brief Returns the default echo mode used by Qbs if none is specified. */ CommandEchoMode Preferences::defaultEchoMode() const { return commandEchoModeFromName(getPreference(QStringLiteral("defaultEchoMode")).toString()); } /*! * \brief Returns the list of paths where qbs looks for modules and imports. * In addition to user-supplied locations, they will also be looked up at \c{baseDir}/share/qbs. */ QStringList Preferences::searchPaths(const QString &baseDir) const { return pathList(Internal::StringConstants::qbsSearchPathsProperty(), baseDir + QLatin1String("/share/qbs")); } /*! * \brief Returns the list of paths where qbs looks for plugins. * In addition to user-supplied locations, they will be looked up at \c{baseDir}/qbs/plugins. */ QStringList Preferences::pluginPaths(const QString &baseDir) const { return pathList(QStringLiteral("pluginsPath"), baseDir + QStringLiteral("/qbs/plugins")); } /*! * \brief Returns the per-pool job limits. */ JobLimits Preferences::jobLimits() const { const QString prefix = QStringLiteral("preferences.jobLimit"); JobLimits limits; for (const QString &key : m_settings->allKeysWithPrefix(prefix, Settings::allScopes())) { limits.setJobLimit(key, m_settings->value(prefix + QLatin1Char('.') + key, Settings::allScopes()).toInt()); } const QString fullPrefix = prefix + QLatin1Char('.'); if (!m_profile.isEmpty()) { Profile p(m_profile, m_settings, m_profileContents); for (const QString &key : p.allKeys(Profile::KeySelectionRecursive)) { if (!key.startsWith(fullPrefix)) continue; const QString jobPool = key.mid(fullPrefix.size()); const int limit = p.value(key).toInt(); if (limit >= 0) limits.setJobLimit(jobPool, limit); } } return limits; } QVariant Preferences::getPreference(const QString &key, const QVariant &defaultValue) const { static const QString keyPrefix = QStringLiteral("preferences"); const QString fullKey = keyPrefix + QLatin1Char('.') + key; const bool isSearchPaths = key == Internal::StringConstants::qbsSearchPathsProperty(); if (!m_profile.isEmpty()) { QVariant value = Profile(m_profile, m_settings).value(fullKey); if (value.isValid()) { if (isSearchPaths) { // Merge with top-level value. value = value.toStringList() + m_settings->value( fullKey, scopesForSearchPaths()).toStringList(); } return value; } } QVariant value = m_profileContents.value(keyPrefix).toMap().value(key); if (value.isValid()) { if (isSearchPaths) {// Merge with top-level value value = value.toStringList() + m_settings->value( fullKey, scopesForSearchPaths()).toStringList(); } return value; } return m_settings->value(fullKey, isSearchPaths ? scopesForSearchPaths() : Settings::allScopes(), defaultValue); } QStringList Preferences::pathList(const QString &key, const QString &defaultValue) const { QStringList paths = getPreference(key).toStringList(); paths << defaultValue; return paths; } bool Preferences::ignoreSystemSearchPaths() const { return getPreference(QStringLiteral("ignoreSystemSearchPaths")).toBool(); } Settings::Scopes Preferences::scopesForSearchPaths() const { return ignoreSystemSearchPaths() ? Settings::UserScope : Settings::allScopes(); } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/preferences.h000066400000000000000000000060311347155106100217400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PREFERENCES_H #define QBS_PREFERENCES_H #include "qbs_export.h" #include "commandechomode.h" #include "joblimits.h" #include "settings.h" #include #include namespace qbs { class Settings; class QBS_EXPORT Preferences { public: explicit Preferences(Settings *settings, const QString &profileName = QString()); Preferences(Settings *settings, const QVariantMap &profileContents); bool useColoredOutput() const; int jobs() const; QString shell() const; QString defaultBuildDirectory() const; CommandEchoMode defaultEchoMode() const; QStringList searchPaths(const QString &baseDir = QString()) const; QStringList pluginPaths(const QString &baseDir = QString()) const; JobLimits jobLimits() const; private: QVariant getPreference(const QString &key, const QVariant &defaultValue = QVariant()) const; QStringList pathList(const QString &key, const QString &defaultValue) const; bool ignoreSystemSearchPaths() const; Settings::Scopes scopesForSearchPaths() const; Settings *m_settings; QString m_profile; QVariantMap m_profileContents; }; } // namespace qbs #endif // Header guard qbs-src-1.13.1/src/lib/corelib/tools/processresult.cpp000066400000000000000000000071021347155106100227070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "processresult.h" #include "processresult_p.h" /*! * \class SetupProjectParameters * \brief The \c ProcessResult class describes a finished qbs process command. */ namespace qbs { ProcessResult::ProcessResult() : d(new Internal::ProcessResultPrivate) { } ProcessResult::ProcessResult(const ProcessResult &other) : d(other.d) { } ProcessResult &ProcessResult::operator=(const ProcessResult &other) { d = other.d; return *this; } ProcessResult::~ProcessResult() { } /*! * \brief Returns true iff the command finished successfully. */ bool ProcessResult::success() const { return d->success; } /*! * \brief Returns the file path of the executable that was run. */ QString ProcessResult::executableFilePath() const { return d->executableFilePath; } /*! * \brief Returns the command-line arguments with which the command was invoked. */ QStringList ProcessResult::arguments() const { return d->arguments; } /*! * \brief Returns the working directory of the invoked command. */ QString ProcessResult::workingDirectory() const { return d->workingDirectory; } /*! * \brief Returns the error status of the process. If no error occurred, the value * is \c Process::UnknownError. */ QProcess::ProcessError ProcessResult::error() const { return d->error; } /*! * \brief Returns the exit code of the command. */ int ProcessResult::exitCode() const { return d->exitCode; } /*! * \brief Returns the data the command wrote to the standard output channel. */ QStringList ProcessResult::stdOut() const { return d->stdOut; } /*! * \brief Returns the data the command wrote to the standard error channel. */ QStringList ProcessResult::stdErr() const { return d->stdErr; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/processresult.h000066400000000000000000000055501347155106100223610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROCESSRESULT_H #define QBS_PROCESSRESULT_H #include "qbs_export.h" #include #include #include QT_BEGIN_NAMESPACE class QString; class QStringList; QT_END_NAMESPACE namespace qbs { namespace Internal { class ProcessCommandExecutor; class ProcessResultPrivate; } class QBS_EXPORT ProcessResult { friend class qbs::Internal::ProcessCommandExecutor; public: ProcessResult(); ProcessResult(const ProcessResult &other); ProcessResult &operator=(const ProcessResult &other); ~ProcessResult(); bool success() const; QString executableFilePath() const; QStringList arguments() const; QString workingDirectory() const; QProcess::ProcessError error() const; int exitCode() const; QStringList stdOut() const; QStringList stdErr() const; private: QExplicitlySharedDataPointer d; }; } // namespace qbs Q_DECLARE_METATYPE(qbs::ProcessResult) #endif // QBS_PROCESSRESULT_H qbs-src-1.13.1/src/lib/corelib/tools/processresult_p.h000066400000000000000000000045641347155106100227040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROCESSRESULT_P_H #define QBS_PROCESSRESULT_P_H #include #include #include namespace qbs { namespace Internal { class ProcessResultPrivate : public QSharedData { public: bool success; QString executableFilePath; QStringList arguments; QString workingDirectory; QProcess::ProcessError error; int exitCode; QStringList stdOut; QStringList stdErr; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/tools/processutils.cpp000066400000000000000000000107051347155106100225340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "processutils.h" #if defined(Q_OS_WIN) # define PSAPI_VERSION 1 // To use GetModuleFileNameEx from Psapi.lib on all Win versions. # include # include #elif defined(Q_OS_DARWIN) # include #elif defined(Q_OS_LINUX) # include "fileinfo.h" # include # include #elif defined(Q_OS_BSD4) # include # include # include # include # if !defined(Q_OS_NETBSD) # include # endif #else # error Missing implementation of processNameByPid for this platform. #endif namespace qbs { namespace Internal { QString processNameByPid(qint64 pid) { #if defined(Q_OS_WIN) HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, DWORD(pid)); if (!hProcess) return {}; wchar_t buf[UNICODE_STRING_MAX_CHARS]; const DWORD length = GetModuleFileNameEx(hProcess, NULL, buf, sizeof(buf) / sizeof(wchar_t)); CloseHandle(hProcess); if (!length) return {}; QString name = QString::fromWCharArray(buf, length); int i = name.lastIndexOf(QLatin1Char('\\')); if (i >= 0) name.remove(0, i + 1); i = name.lastIndexOf(QLatin1Char('.')); if (i >= 0) name.truncate(i); return name; #elif defined(Q_OS_DARWIN) char name[1024]; proc_name(pid, name, sizeof(name) / sizeof(char)); return QString::fromUtf8(name); #elif defined(Q_OS_LINUX) char exePath[64]; char buf[PATH_MAX]; memset(buf, 0, sizeof(buf)); sprintf(exePath, "/proc/%lld/exe", pid); readlink(exePath, buf, sizeof(buf)); return FileInfo::fileName(QString::fromUtf8(buf)); #elif defined(Q_OS_BSD4) # if defined(Q_OS_NETBSD) struct kinfo_proc2 kp; int mib[6] = { CTL_KERN, KERN_PROC2, KERN_PROC_PID, (int)pid, sizeof(struct kinfo_proc2), 1 }; # elif defined(Q_OS_OPENBSD) struct kinfo_proc kp; int mib[6] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid, sizeof(struct kinfo_proc), 1 }; # else struct kinfo_proc kp; int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid }; # endif size_t len = sizeof(kp); u_int mib_len = sizeof(mib)/sizeof(u_int); if (sysctl(mib, mib_len, &kp, &len, NULL, 0) < 0) return {}; # if defined(Q_OS_OPENBSD) || defined(Q_OS_NETBSD) if (kp.p_pid != pid) return {}; QString name = QFile::decodeName(kp.p_comm); # else if (kp.ki_pid != pid) return {}; QString name = QFile::decodeName(kp.ki_comm); # endif return name; #else Q_UNUSED(pid); return {}; #endif } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/processutils.h000066400000000000000000000042331347155106100222000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROCESSUTILS_H #define QBS_PROCESSUTILS_H #include #include #include namespace qbs { namespace Internal { QString QBS_AUTOTEST_EXPORT processNameByPid(qint64 pid); } // namespace Internal } // namespace qbs #endif // QBS_PROCESSUTILS_H qbs-src-1.13.1/src/lib/corelib/tools/profile.cpp000066400000000000000000000174011347155106100214350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "profile.h" #include "qbsassert.h" #include "settings.h" #include "stringconstants.h" #include #include namespace qbs { /*! * \class Profile * \brief The \c Profile class gives access to the settings of a given profile. */ /*! * \enum Profile::KeySelection * This enum type specifies whether to enumerate keys recursively. * \value KeySelectionRecursive Indicates that key enumeration should happen recursively, i.e. * it should go up the base profile chain. * \value KeySelectionNonRecursive Indicates that only keys directly attached to a profile * should be listed. */ /*! * \brief Creates an object giving access to the settings for profile \c name. */ Profile::Profile(const QString &name, Settings *settings, const QVariantMap &profiles) : m_name(name), m_settings(settings), m_values(profiles.value(name).toMap()), m_profiles(profiles) { QBS_ASSERT(name == cleanName(name), return); } bool Profile::exists() const { return m_name == fallbackName() || !m_values.empty() || !m_settings->allKeysWithPrefix(profileKey(), Settings::allScopes()).empty(); } /*! * \brief Returns the value for property \c key in this profile. */ QVariant Profile::value(const QString &key, const QVariant &defaultValue, ErrorInfo *error) const { try { return possiblyInheritedValue(key, defaultValue, QStringList()); } catch (const ErrorInfo &e) { if (error) *error = e; return {}; } } /*! * \brief Gives value \c value to the property \c key in this profile. */ void Profile::setValue(const QString &key, const QVariant &value) { m_settings->setValue(fullyQualifiedKey(key), value); if (key == baseProfileKey()) { QBS_ASSERT(value.toString() == cleanName(value.toString()), return); } } /*! * \brief Removes a key and the associated value from this profile. */ void Profile::remove(const QString &key) { m_settings->remove(fullyQualifiedKey(key)); } /*! * \brief Returns the name of this profile. */ QString Profile::name() const { return m_name; } /*! * \brief Returns all property keys in this profile. * If and only if selection is Profile::KeySelectionRecursive, this will also list keys defined * in base profiles. */ QStringList Profile::allKeys(KeySelection selection, ErrorInfo *error) const { try { return allKeysInternal(selection, QStringList()); } catch (const ErrorInfo &e) { if (error) *error = e; return {}; } } /*! * \brief Returns the name of this profile's base profile. * The returned value is empty if the profile does not have a base profile. */ QString Profile::baseProfile() const { return localValue(baseProfileKey()).toString(); } /*! * \brief Sets a new base profile for this profile. */ void Profile::setBaseProfile(const QString &baseProfile) { setValue(baseProfileKey(), baseProfile); } /*! * \brief Removes this profile's base profile setting. */ void Profile::removeBaseProfile() { remove(baseProfileKey()); } /*! * \brief Removes this profile from the settings. */ void Profile::removeProfile() { m_settings->remove(profileKey()); } /*! * \brief Returns a string suitiable as a profile name. * Removes all dots and replaces them with hyphens. */ QString Profile::cleanName(const QString &name) { QString newName = name; return newName.replace(QLatin1Char('.'), QLatin1Char('-')); } QString Profile::profileKey() const { return Internal::StringConstants::profilesSettingsPrefix() + m_name; } QString Profile::baseProfileKey() { return Internal::StringConstants::baseProfileProperty(); } void Profile::checkBaseProfileExistence(const Profile &baseProfile) const { if (!baseProfile.exists()) throw ErrorInfo(Internal::Tr::tr("Profile \"%1\" has a non-existent base profile \"%2\".").arg( name(), baseProfile.name())); } QVariant Profile::localValue(const QString &key) const { QVariant val = m_values.value(key); if (!val.isValid()) val = m_settings->value(fullyQualifiedKey(key), Settings::allScopes()); return val; } QString Profile::fullyQualifiedKey(const QString &key) const { return profileKey() + QLatin1Char('.') + key; } QVariant Profile::possiblyInheritedValue(const QString &key, const QVariant &defaultValue, QStringList profileChain) const { extendAndCheckProfileChain(profileChain); const QVariant v = localValue(key); if (v.isValid()) return v; const QString baseProfileName = baseProfile(); if (baseProfileName.isEmpty()) return defaultValue; Profile parentProfile(baseProfileName, m_settings, m_profiles); checkBaseProfileExistence(parentProfile); return parentProfile.possiblyInheritedValue(key, defaultValue, profileChain); } QStringList Profile::allKeysInternal(Profile::KeySelection selection, QStringList profileChain) const { extendAndCheckProfileChain(profileChain); QStringList keys = m_values.keys(); if (keys.empty()) keys = m_settings->allKeysWithPrefix(profileKey(), Settings::allScopes()); if (selection == KeySelectionNonRecursive) return keys; const QString baseProfileName = baseProfile(); if (baseProfileName.isEmpty()) return keys; Profile parentProfile(baseProfileName, m_settings, m_profiles); checkBaseProfileExistence(parentProfile); keys += parentProfile.allKeysInternal(KeySelectionRecursive, profileChain); keys.removeDuplicates(); keys.removeOne(baseProfileKey()); keys.sort(); return keys; } void Profile::extendAndCheckProfileChain(QStringList &chain) const { chain << m_name; if (Q_UNLIKELY(chain.count(m_name) > 1)) { throw ErrorInfo(Internal::Tr::tr("Circular profile inheritance. Cycle is '%1'.") .arg(chain.join(QLatin1String(" -> ")))); } } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/profile.h000066400000000000000000000075561347155106100211140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROFILE_H #define QBS_PROFILE_H #include "qbs_export.h" #include #include QT_BEGIN_NAMESPACE class QStringList; QT_END_NAMESPACE namespace qbs { class ErrorInfo; class Settings; class QBS_EXPORT Profile { public: Profile(const QString &name, Settings *settings, const QVariantMap &profiles = QVariantMap()); bool exists() const; QVariant value(const QString &key, const QVariant &defaultValue = QVariant(), ErrorInfo *error = nullptr) const; void setValue(const QString &key, const QVariant &value); void remove(const QString &key); QString name() const; QString baseProfile() const; void setBaseProfile(const QString &baseProfile); void removeBaseProfile(); void removeProfile(); enum KeySelection { KeySelectionRecursive, KeySelectionNonRecursive }; QStringList allKeys(KeySelection selection, ErrorInfo *error = nullptr) const; static QString cleanName(const QString &name); static QString fallbackName() { return QStringLiteral("none"); } private: static QString baseProfileKey(); void checkBaseProfileExistence(const Profile &baseProfile) const; QString profileKey() const; QVariant localValue(const QString &key) const; QString fullyQualifiedKey(const QString &key) const; QVariant possiblyInheritedValue(const QString &key, const QVariant &defaultValue, QStringList profileChain) const; QStringList allKeysInternal(KeySelection selection, QStringList profileChain) const; void extendAndCheckProfileChain(QStringList &chain) const; QString m_name; Settings *m_settings; QVariantMap m_values; QVariantMap m_profiles; }; namespace Internal { // Exported for autotests. class QBS_EXPORT TemporaryProfile { public: TemporaryProfile(const QString &name, Settings *settings) : p(name, settings) {} ~TemporaryProfile() { p.removeProfile(); } Profile p; }; } // namespace Internal } // namespace qbs #endif // Header guard qbs-src-1.13.1/src/lib/corelib/tools/profiling.cpp000066400000000000000000000073441347155106100217730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "profiling.h" #include #include #include namespace qbs { namespace Internal { class TimedActivityLogger::TimedActivityLoggerPrivate { public: Logger logger; QString activity; QElapsedTimer timer; }; TimedActivityLogger::TimedActivityLogger(const Logger &logger, const QString &activity, bool enabled) : d(nullptr) { if (!enabled) return; d = new TimedActivityLoggerPrivate; d->logger = logger; d->activity = activity; d->logger.qbsLog(LoggerInfo, true) << Tr::tr("Starting activity '%2'.").arg(activity); d->timer.start(); } void TimedActivityLogger::finishActivity() { if (!d) return; const QString timeString = elapsedTimeString(d->timer.elapsed()); d->logger.qbsLog(LoggerInfo, true) << Tr::tr("Activity '%2' took %3.").arg(d->activity, timeString); delete d; d = nullptr; } TimedActivityLogger::~TimedActivityLogger() { finishActivity(); } AccumulatingTimer::AccumulatingTimer(qint64 *elapsedTime) : m_elapsedTime(elapsedTime) { if (elapsedTime) m_timer.start(); } AccumulatingTimer::~AccumulatingTimer() { stop(); } void AccumulatingTimer::stop() { if (!m_timer.isValid()) return; *m_elapsedTime += m_timer.elapsed(); m_timer.invalidate(); } QString elapsedTimeString(qint64 elapsedTimeInMs) { qint64 ms = elapsedTimeInMs; qint64 s = ms/1000; ms -= s*1000; qint64 m = s/60; s -= m*60; const qint64 h = m/60; m -= h*60; QString timeString = QStringLiteral("%1ms").arg(ms); if (h || m || s) timeString.prepend(QStringLiteral("%1s, ").arg(s)); if (h || m) timeString.prepend(QStringLiteral("%1m, ").arg(m)); if (h) timeString.prepend(QStringLiteral("%1h, ").arg(h)); return timeString; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/profiling.h000066400000000000000000000051401347155106100214300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROFILING_H #define QBS_PROFILING_H #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { namespace Internal { class Logger; QString elapsedTimeString(qint64 elapsedTimeInMs); class TimedActivityLogger { public: TimedActivityLogger(const Logger &logger, const QString &activity, bool enabled); void finishActivity(); ~TimedActivityLogger(); private: class TimedActivityLoggerPrivate; TimedActivityLoggerPrivate *d; }; class AccumulatingTimer { public: AccumulatingTimer(qint64 *elapsedTime); ~AccumulatingTimer(); void stop(); private: QElapsedTimer m_timer; qint64 * const m_elapsedTime; }; } // namespace Internal } // namespace qbs #endif // Header guard qbs-src-1.13.1/src/lib/corelib/tools/progressobserver.cpp000066400000000000000000000101251347155106100234050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "progressobserver.h" namespace qbs { namespace Internal { /*! * \class ProgressObserver * The \c ProgressObserver class is used in long running qbs operations. It serves two purposes: * Firstly, it allows operations to indicate progress to a client. Secondly, a client can * signal to an operation that is should exit prematurely. * Clients of the qbs library are supposed to subclass this class and implement the virtual * functions in a way that lets users know about the current operation and its progress. */ /*! * \fn virtual void initialize(const QString &task, int maximum) = 0 * \brief Indicates that a new operation is starting. * Library code calls this function to indicate that it is starting a new task. * The \a task parameter is a textual description of that task suitable for presentation to a user. * The \a maximum parameter is an estimate of the maximum effort the operation is going to take. * This is helpful if the client wants to set up some sort of progress bar showing the * percentage of the work already done. */ /*! * \fn virtual void setProgressValue(int value) = 0 * \brief Sets the new progress value. * Library code calls this function to indicate that the current operation has progressed. * It will try hard to ensure that \a value will not exceed \c maximum(). * \sa ProgressObserver::maximum(). */ /*! * \fn virtual int progressValue() = 0 * \brief The current progress value. * Will typically reflect the \a value from the last call to \c setProgressValue() and should not * exceed \c maximum(). * \sa setProgressvalue() * \sa maximum() */ void ProgressObserver::incrementProgressValue(int increment) { setProgressValue(progressValue() + increment); } /*! * \fn virtual bool canceled() const = 0 * \brief Indicates whether the current operation should be canceled. * Library code will periodically call this function and abort the current operation * if it returns true. */ /*! * \fn virtual int maximum() const = 0 * \brief The expected maximum progress value. * This will typically be the value of \c maximum passed to \c initialize(). * \sa ProgressObserver::initialize() */ void ProgressObserver::setFinished() { setProgressValue(maximum()); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/progressobserver.h000066400000000000000000000051251347155106100230560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROGRESSOBSERVER_H #define QBS_PROGRESSOBSERVER_H #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { namespace Internal { class ProgressObserver { public: virtual ~ProgressObserver() { } virtual void initialize(const QString &task, int maximum) = 0; virtual void setProgressValue(int value) = 0; virtual int progressValue() = 0; virtual bool canceled() const = 0; virtual void setMaximum(int maximum) = 0; virtual int maximum() const = 0; void incrementProgressValue(int increment = 1); // Call this to ensure that the progress bar always goes to 100%. void setFinished(); }; } // namespace Internal } // namespace qbs #endif // QBS_PROGRESSOBSERVER_H qbs-src-1.13.1/src/lib/corelib/tools/projectgeneratormanager.cpp000066400000000000000000000056551347155106100247150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "projectgeneratormanager.h" #include #include #include #include #include #include namespace qbs { using namespace Internal; ProjectGeneratorManager::~ProjectGeneratorManager() { } ProjectGeneratorManager *ProjectGeneratorManager::instance() { static ProjectGeneratorManager generatorPlugin; return &generatorPlugin; } ProjectGeneratorManager::ProjectGeneratorManager() { } QStringList ProjectGeneratorManager::loadedGeneratorNames() { return instance()->m_generators.keys(); } std::shared_ptr ProjectGeneratorManager::findGenerator(const QString &generatorName) { return instance()->m_generators.value(generatorName); } void ProjectGeneratorManager::registerGenerator(const std::shared_ptr &generator) { if (!findGenerator(generator->generatorName())) instance()->m_generators.insert(generator->generatorName(), generator); } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/projectgeneratormanager.h000066400000000000000000000052071347155106100243530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PROJECTGENERATORMANAGER_H #define QBS_PROJECTGENERATORMANAGER_H #include #include #include QT_BEGIN_NAMESPACE class QStringList; QT_END_NAMESPACE namespace qbs { class ProjectGenerator; class QBS_EXPORT ProjectGeneratorManager { public: ~ProjectGeneratorManager(); static ProjectGeneratorManager *instance(); static QStringList loadedGeneratorNames(); static std::shared_ptr findGenerator(const QString &generatorName); static void registerGenerator(const std::shared_ptr &generator); private: ProjectGeneratorManager(); private: QMap > m_generators; }; } // namespace qbs #endif qbs-src-1.13.1/src/lib/corelib/tools/qbs_export.h000066400000000000000000000054501347155106100216310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_EXPORT_H #define QBS_EXPORT_H #if defined(_WIN32) || defined(WIN32) # define QBS_DECL_EXPORT __declspec(dllexport) # define QBS_DECL_IMPORT __declspec(dllimport) #else # define QBS_DECL_EXPORT __attribute__((visibility("default"))) # define QBS_DECL_IMPORT __attribute__((visibility("default"))) # endif #ifdef QBS_STATIC_LIB # define QBS_EXPORT # define QBS_AUTOTEST_EXPORT #else # ifdef QBS_LIBRARY # define QBS_EXPORT QBS_DECL_EXPORT # ifdef QBS_ENABLE_UNIT_TESTS # define QBS_AUTOTEST_EXPORT QBS_DECL_EXPORT # else # define QBS_AUTOTEST_EXPORT # endif # else # define QBS_EXPORT QBS_DECL_IMPORT # ifdef QBS_ENABLE_UNIT_TESTS # define QBS_AUTOTEST_EXPORT QBS_DECL_IMPORT # else # define QBS_AUTOTEST_EXPORT # endif # endif #endif #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(disable: 4251) #endif #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/tools/qbsassert.cpp000066400000000000000000000046031347155106100220040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qbsassert.h" #include "error.h" #include namespace qbs { namespace Internal { void writeAssertLocation(const char *condition, const char *file, int line) { qDebug("SOFT ASSERT: %s in %s:%d", condition, file, line); } void throwAssertLocation(const char *condition, const char *file, int line) { throw ErrorInfo(QStringLiteral("ASSERT: %1").arg(QLatin1String(condition)), CodeLocation(QString::fromLocal8Bit(file), line, -1, false), true); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/qbsassert.h000066400000000000000000000053331347155106100214520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_QBSASSERT_H #define QBS_QBSASSERT_H #include "qbs_export.h" namespace qbs { namespace Internal { QBS_EXPORT void writeAssertLocation(const char *condition, const char *file, int line); [[noreturn]] QBS_EXPORT void throwAssertLocation(const char *condition, const char *file, int line); } // namespace Internal } // namespace qbs #define QBS_ASSERT(cond, action)\ if (Q_LIKELY(cond)) {} else {\ ::qbs::Internal::writeAssertLocation(#cond, __FILE__, __LINE__); action;\ } do {} while (0) // The do {} while (0) is here to enforce the use of a semicolon after QBS_ASSERT. // action can also be continue or break. Copied from qtcassert.h in Qt Creator. #define QBS_CHECK(cond)\ do {\ if (Q_LIKELY(cond)) {} else {\ ::qbs::Internal::throwAssertLocation(#cond, __FILE__, __LINE__);\ }\ } while (0) #endif // QBS_QBSASSERT_H qbs-src-1.13.1/src/lib/corelib/tools/qbspluginmanager.cpp000066400000000000000000000124531347155106100233360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qbspluginmanager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { struct QbsPlugin { QbsPluginLoadFunction load; QbsPluginUnloadFunction unload; bool loaded; }; class QbsPluginManagerPrivate { public: std::vector staticPlugins; std::vector libs; }; QbsPluginManager::QbsPluginManager() : d(new QbsPluginManagerPrivate) { } QbsPluginManager::~QbsPluginManager() { unloadStaticPlugins(); for (QLibrary * const lib : qAsConst(d->libs)) { auto unload = reinterpret_cast(lib->resolve("QbsPluginUnload")); if (unload) unload(); lib->unload(); delete lib; } } QbsPluginManager *QbsPluginManager::instance() { static QbsPluginManager instance; return &instance; } void QbsPluginManager::registerStaticPlugin(QbsPluginLoadFunction load, QbsPluginUnloadFunction unload) { if (none_of(d->staticPlugins, [&load](const QbsPlugin &p) { return p.load == load; })) d->staticPlugins.push_back(QbsPlugin { load, unload, false }); } void QbsPluginManager::loadStaticPlugins() { for (const auto &plugin : d->staticPlugins) { if (!plugin.loaded && plugin.load) plugin.load(); } } void QbsPluginManager::unloadStaticPlugins() { for (auto &plugin : d->staticPlugins) { if (plugin.loaded && plugin.unload) plugin.unload(); } d->staticPlugins.clear(); } void QbsPluginManager::loadPlugins(const std::vector &pluginPaths, const Logger &logger) { QStringList filters; if (HostOsInfo::isWindowsHost()) filters << QStringLiteral("*.dll"); else if (HostOsInfo::isMacosHost()) filters << QStringLiteral("*.bundle") << QStringLiteral("*.dylib"); else filters << QStringLiteral("*.so"); for (const std::string &pluginPath : pluginPaths) { const QString qtPluginPath = QString::fromStdString(pluginPath); qCDebug(lcPluginManager) << "loading plugins from" << QDir::toNativeSeparators(qtPluginPath); QDirIterator it(qtPluginPath, filters, QDir::Files); while (it.hasNext()) { const QString fileName = it.next(); std::unique_ptr lib(new QLibrary(fileName)); if (!lib->load()) { logger.qbsWarning() << Tr::tr("plugin manager: Cannot load plugin '%1': %2") .arg(QDir::toNativeSeparators(fileName), lib->errorString()); continue; } auto load = reinterpret_cast(lib->resolve("QbsPluginLoad")); if (load) { load(); qCDebug(lcPluginManager) << "plugin" << QDir::toNativeSeparators(fileName) << "loaded."; d->libs.push_back(lib.release()); } else { logger.qbsWarning() << Tr::tr("plugin manager: not a qbs plugin"); } } } } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/qbspluginmanager.h000066400000000000000000000060671347155106100230070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PLUGINS_H #define QBS_PLUGINS_H #include "qbs_export.h" #include #include #include namespace qbs { namespace Internal { class Logger; typedef void (*QbsPluginLoadFunction)(); typedef void (*QbsPluginUnloadFunction)(); class QbsPluginManagerPrivate; class QBS_EXPORT QbsPluginManager { public: ~QbsPluginManager(); static QbsPluginManager *instance(); void registerStaticPlugin(QbsPluginLoadFunction, QbsPluginUnloadFunction); void loadStaticPlugins(); void unloadStaticPlugins(); void loadPlugins(const std::vector &paths, const Logger &logger); protected: QbsPluginManager(); private: std::unique_ptr d; }; } // namespace Internal } // namespace qbs #ifdef QBS_STATIC_LIB #define QBS_REGISTER_STATIC_PLUGIN(exportmacro, name, load, unload) \ static auto qbs_static_plugin_register##name = [] { \ qbs::Internal::QbsPluginManager::instance()->registerStaticPlugin(load, unload); \ return true; \ }(); #else #define QBS_REGISTER_STATIC_PLUGIN(exportmacro, name, load, unload) \ exportmacro void QbsPluginLoad() { load(); } \ exportmacro void QbsPluginUnload() { unload(); } #endif #endif qbs-src-1.13.1/src/lib/corelib/tools/qbsprocess.cpp000066400000000000000000000131161347155106100221600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qbsprocess.h" #include "launcherinterface.h" #include "launchersocket.h" #include "qbsassert.h" #include #include #include namespace qbs { namespace Internal { QbsProcess::QbsProcess(QObject *parent) : QObject(parent) { connect(LauncherInterface::socket(), &LauncherSocket::ready, this, &QbsProcess::handleSocketReady); connect(LauncherInterface::socket(), &LauncherSocket::errorOccurred, this, &QbsProcess::handleSocketError); connect(LauncherInterface::socket(), &LauncherSocket::packetArrived, this, &QbsProcess::handlePacket); } void QbsProcess::start(const QString &command, const QStringList &arguments) { if (m_socketError) { m_error = QProcess::FailedToStart; emit error(m_error); return; } m_command = command; m_arguments = arguments; m_state = QProcess::Starting; if (LauncherInterface::socket()->isReady()) doStart(); } void QbsProcess::doStart() { m_state = QProcess::Running; StartProcessPacket p(token()); p.command = m_command; p.arguments = m_arguments; p.env = m_environment.toStringList(); p.workingDir = m_workingDirectory; sendPacket(p); } void QbsProcess::cancel() { switch (m_state) { case QProcess::NotRunning: break; case QProcess::Starting: m_errorString = Tr::tr("Process canceled before it was started."); m_error = QProcess::FailedToStart; m_state = QProcess::NotRunning; emit error(m_error); break; case QProcess::Running: sendPacket(StopProcessPacket(token())); break; } } QByteArray QbsProcess::readAllStandardOutput() { return readAndClear(m_stdout); } QByteArray QbsProcess::readAllStandardError() { return readAndClear(m_stderr); } void QbsProcess::sendPacket(const LauncherPacket &packet) { LauncherInterface::socket()->sendData(packet.serialize()); } QByteArray QbsProcess::readAndClear(QByteArray &data) { const QByteArray tmp = data; data.clear(); return tmp; } void QbsProcess::handlePacket(LauncherPacketType type, quintptr token, const QByteArray &payload) { if (token != this->token()) return; switch (type) { case LauncherPacketType::ProcessError: handleErrorPacket(payload); break; case LauncherPacketType::ProcessFinished: handleFinishedPacket(payload); break; default: QBS_ASSERT(false, break); } } void QbsProcess::handleSocketReady() { m_socketError = false; if (m_state == QProcess::Starting) doStart(); } void QbsProcess::handleSocketError(const QString &message) { m_socketError = true; m_errorString = Tr::tr("Internal socket error: %1").arg(message); if (m_state != QProcess::NotRunning) { m_state = QProcess::NotRunning; m_error = QProcess::FailedToStart; emit error(m_error); } } void QbsProcess::handleErrorPacket(const QByteArray &packetData) { QBS_ASSERT(m_state != QProcess::NotRunning, return); const auto packet = LauncherPacket::extractPacket(token(), packetData); m_error = packet.error; m_errorString = packet.errorString; m_state = QProcess::NotRunning; emit error(m_error); } void QbsProcess::handleFinishedPacket(const QByteArray &packetData) { QBS_ASSERT(m_state == QProcess::Running, return); m_state = QProcess::NotRunning; const auto packet = LauncherPacket::extractPacket(token(), packetData); m_exitCode = packet.exitCode; m_stdout = packet.stdOut; m_stderr = packet.stdErr; m_errorString = packet.errorString; emit finished(m_exitCode); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/qbsprocess.h000066400000000000000000000076161347155106100216350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_QBSPROCESS_H #define QBS_QBSPROCESS_H #include "launcherpackets.h" #include #include #include #include namespace qbs { namespace Internal { class QbsProcess : public QObject { Q_OBJECT public: explicit QbsProcess(QObject *parent = nullptr); QProcess::ProcessState state() const { return m_state; } void setProcessEnvironment(const QProcessEnvironment &env) { m_environment = env; } void setWorkingDirectory(const QString &workingDir) { m_workingDirectory = workingDir; } QString workingDirectory() const { return m_workingDirectory; } void start(const QString &command, const QStringList &arguments); void cancel(); QByteArray readAllStandardOutput(); QByteArray readAllStandardError(); int exitCode() const { return m_exitCode; } QProcess::ProcessError error() const { return m_error; } QString errorString() const { return m_errorString; } signals: void error(QProcess::ProcessError error); void finished(int exitCode); private: void doStart(); void sendPacket(const LauncherPacket &packet); QByteArray readAndClear(QByteArray &data); void handleSocketError(const QString &message); void handlePacket(qbs::Internal::LauncherPacketType type, quintptr token, const QByteArray &payload); void handleErrorPacket(const QByteArray &packetData); void handleFinishedPacket(const QByteArray &packetData); void handleSocketReady(); quintptr token() const { return reinterpret_cast(this); } QString m_command; QStringList m_arguments; QProcessEnvironment m_environment; QString m_workingDirectory; QByteArray m_stdout; QByteArray m_stderr; QString m_errorString; QProcess::ProcessError m_error = QProcess::UnknownError; QProcess::ProcessState m_state = QProcess::NotRunning; int m_exitCode; int m_connectionAttempts = 0; bool m_socketError = false; }; } // namespace Internal } // namespace qbs #endif // QBSPROCESS_H qbs-src-1.13.1/src/lib/corelib/tools/qttools.cpp000066400000000000000000000042631347155106100215040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qttools.h" #include QT_BEGIN_NAMESPACE uint qHash(const QStringList &list) { uint s = 0; for (const QString &n : list) s ^= qHash(n) + 0x9e3779b9 + (s << 6) + (s >> 2); return s; } uint qHash(const QProcessEnvironment &env) { return qHash(env.toStringList()); } QT_END_NAMESPACE qbs-src-1.13.1/src/lib/corelib/tools/qttools.h000066400000000000000000000044531347155106100211520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBSQTTOOLS_H #define QBSQTTOOLS_H #include #include #include QT_BEGIN_NAMESPACE class QProcessEnvironment; QT_END_NAMESPACE namespace std { template<> struct hash { std::size_t operator()(const QString &s) const { return qHash(s); } }; } QT_BEGIN_NAMESPACE uint qHash(const QStringList &list); uint qHash(const QProcessEnvironment &env); QT_END_NAMESPACE #endif // QBSQTTOOLS_H qbs-src-1.13.1/src/lib/corelib/tools/scannerpluginmanager.cpp000066400000000000000000000060331347155106100241770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "scannerpluginmanager.h" #include #include namespace qbs { namespace Internal { class ScannerPluginManagerPrivate { public: std::map> scannerPlugins; }; ScannerPluginManager::~ScannerPluginManager() { } ScannerPluginManager *ScannerPluginManager::instance() { static ScannerPluginManager scannerPlugin; return &scannerPlugin; } ScannerPluginManager::ScannerPluginManager() : d(new ScannerPluginManagerPrivate) { } std::vector ScannerPluginManager::scannersForFileTag(const FileTag &fileTag) { auto it = instance()->d->scannerPlugins.find(fileTag); if (it != instance()->d->scannerPlugins.cend()) return it->second; return {}; } void ScannerPluginManager::registerPlugins(ScannerPlugin **plugins) { for (int i = 0; plugins[i] != nullptr; ++i) { const FileTags &fileTags = FileTags::fromStringList( QString::fromLatin1(plugins[i]->fileTags).split(QLatin1Char(','))); for (const FileTag &tag : fileTags) d->scannerPlugins[tag].push_back(plugins[i]); } } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/scannerpluginmanager.h000066400000000000000000000047661347155106100236570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_PLUGINS_SCANNER_H #define QBS_PLUGINS_SCANNER_H #include "qbs_export.h" #include #include class ScannerPlugin; namespace qbs { namespace Internal { class FileTag; class ScannerPluginManagerPrivate; class QBS_EXPORT ScannerPluginManager { public: ~ScannerPluginManager(); static ScannerPluginManager *instance(); static std::vector scannersForFileTag(const FileTag &fileTag); void registerPlugins(ScannerPlugin **plugins); private: ScannerPluginManager(); std::unique_ptr d; }; } // namespace Internal } // namespace qbs #endif // QBS_PLUGINS_SCANNER_H qbs-src-1.13.1/src/lib/corelib/tools/scripttools.cpp000066400000000000000000000057151347155106100223670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "scripttools.h" #include #include namespace qbs { namespace Internal { void setConfigProperty(QVariantMap &cfg, const QStringList &name, const QVariant &value) { if (name.length() == 1) { cfg.insert(name.front(), value); } else { QVariant &subCfg = cfg[name.front()]; QVariantMap subCfgMap = subCfg.toMap(); setConfigProperty(subCfgMap, name.mid(1), value); subCfg = subCfgMap; } } QVariant getConfigProperty(const QVariantMap &cfg, const QStringList &name) { if (name.length() == 1) return cfg.value(name.front()); else return getConfigProperty(cfg.value(name.front()).toMap(), name.mid(1)); } TemporaryGlobalObjectSetter::TemporaryGlobalObjectSetter(const QScriptValue &object) { QScriptEngine *engine = object.engine(); m_oldGlobalObject = engine->globalObject(); engine->setGlobalObject(object); } TemporaryGlobalObjectSetter::~TemporaryGlobalObjectSetter() { m_oldGlobalObject.engine()->setGlobalObject(m_oldGlobalObject); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/scripttools.h000066400000000000000000000064331347155106100220320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SCRIPTTOOLS_H #define QBS_SCRIPTTOOLS_H #include #include #include #include #include #include namespace qbs { namespace Internal { template QScriptValue toScriptValue(QScriptEngine *scriptEngine, const C &container) { QScriptValue v = scriptEngine->newArray(container.size()); int i = 0; for (const typename C::value_type &item : container) v.setProperty(i++, scriptEngine->toScriptValue(item)); return v; } void setConfigProperty(QVariantMap &cfg, const QStringList &name, const QVariant &value); QVariant QBS_AUTOTEST_EXPORT getConfigProperty(const QVariantMap &cfg, const QStringList &name); template void attachPointerTo(QScriptValue &scriptValue, T *ptr) { QVariant v; v.setValue(reinterpret_cast(ptr)); scriptValue.setData(scriptValue.engine()->newVariant(v)); } template T *attachedPointer(const QScriptValue &scriptValue) { const quintptr ptr = scriptValue.data().toVariant().value(); return reinterpret_cast(ptr); } class TemporaryGlobalObjectSetter { public: TemporaryGlobalObjectSetter(const QScriptValue &object); ~TemporaryGlobalObjectSetter(); private: QScriptValue m_oldGlobalObject; }; } // namespace Internal } // namespace qbs #endif // QBS_SCRIPTTOOLS_H qbs-src-1.13.1/src/lib/corelib/tools/set.h000066400000000000000000000337471347155106100202500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SET_H #define QBS_SET_H #include #include #ifdef QT_CORE_LIB #include #include #endif #include #include #include #include #include #include namespace qbs { namespace Internal { template class Set; template Set operator&(const Set &set1, const Set &set2); template Set operator-(const Set &set1, const Set &set2); namespace helper { template struct SortAfterLoad { static const bool required = false; }; template struct SortAfterLoad { static const bool required = true; }; template struct SortAfterLoad> { static const bool required = true; }; } template class Set { public: using const_iterator = typename std::vector::const_iterator; using iterator = typename std::vector::iterator; using reverse_iterator = typename std::vector::reverse_iterator; using const_reverse_iterator = typename std::vector::const_reverse_iterator; using size_type = typename std::vector::size_type; using value_type = T; using difference_type = typename std::vector::difference_type; using pointer = typename std::vector::pointer; using const_pointer = typename std::vector::const_pointer; using reference = typename std::vector::reference; using const_reference = typename std::vector::const_reference; iterator begin() { return m_data.begin(); } iterator end() { return m_data.end(); } reverse_iterator rbegin() { return m_data.rbegin(); } reverse_iterator rend() { return m_data.rend(); } const_reverse_iterator rbegin() const { return m_data.rbegin(); } const_reverse_iterator rend() const { return m_data.rend(); } const_reverse_iterator crbegin() const { return m_data.crbegin(); } const_reverse_iterator crend() const { return m_data.crend(); } const_iterator begin() const { return m_data.begin(); } const_iterator end() const { return m_data.end(); } const_iterator cbegin() const { return m_data.cbegin(); } const_iterator cend() const { return m_data.cend(); } const_iterator constBegin() const { return m_data.cbegin(); } const_iterator constEnd() const { return m_data.cend(); } Set() { } Set(const std::initializer_list &list); Set &unite(const Set &other); Set &operator+=(const Set &other) { return unite(other); } Set &operator|=(const Set &other) { return unite(other); } Set &subtract(const Set &other); Set &operator-=(const Set &other) { return subtract(other); } Set &intersect(const Set &other); Set &operator&=(const Set &other) { return intersect(other); } Set &operator&=(const T &v) { return intersect(Set{ v }); } iterator find(const T &v) { return std::find(m_data.begin(), m_data.end(), v); } const_iterator find(const T &v) const { return std::find(m_data.cbegin(), m_data.cend(), v); } std::pair insert(const T &v); Set &operator+=(const T &v) { insert(v); return *this; } Set &operator|=(const T &v) { return operator+=(v); } Set &operator<<(const T &v) { return operator+=(v); } bool contains(const T &v) const { return std::binary_search(cbegin(), cend(), v); } bool contains(const Set &other) const; bool empty() const { return m_data.empty(); } size_type size() const { return m_data.size(); } size_type capacity() const { return m_data.capacity(); } bool intersects(const Set &other) const; bool remove(const T &v); void operator-=(const T &v) { remove(v); } iterator erase(iterator it) { return m_data.erase(it); } iterator erase(iterator first, iterator last) { return m_data.erase(first, last); } void clear() { m_data.clear(); } void reserve(size_type size) { m_data.reserve(size); } void swap(Set &other) { m_data.swap(other.m_data); } void load(PersistentPool &pool); void store(PersistentPool &pool) const; #ifdef QT_CORE_LIB QStringList toStringList() const; QString toString(const T& value) const { return value.toString(); } QString toString() const; static Set fromList(const QList &list); QList toList() const; #endif static Set fromStdVector(const std::vector &vector); static Set fromStdSet(const std::set &set); std::set toStdSet() const; template static Set filtered(const Set &s); bool operator==(const Set &other) const { return m_data == other.m_data; } bool operator!=(const Set &other) const { return m_data != other.m_data; } private: friend Set operator&<>(const Set &set1, const Set &set2); friend Set operator-<>(const Set &set1, const Set &set2); void sort() { std::sort(m_data.begin(), m_data.end()); } T loadElem(PersistentPool &pool) { return pool.load(); } void storeElem(PersistentPool &pool, const T &v) const { pool.store(v); } bool sortAfterLoadRequired() const { return helper::SortAfterLoad::required; } iterator asMutableIterator(const_iterator cit); std::vector m_data; }; template Set::Set(const std::initializer_list &list) : m_data(list) { sort(); const auto last = std::unique(m_data.begin(), m_data.end()); m_data.erase(last, m_data.end()); } template Set &Set::intersect(const Set &other) { iterator it = begin(); const_iterator otherIt = other.cbegin(); while (it != end()) { if (otherIt == other.cend()) { m_data.erase(it, end()); break; } if (*it < *otherIt) { it = erase(it); continue; } if (!(*otherIt < *it)) ++it; ++otherIt; } return *this; } template std::pair::iterator, bool> Set::insert(const T &v) { const auto it = std::lower_bound(m_data.begin(), m_data.end(), v); if (it == m_data.end() || v < *it) return std::make_pair(m_data.insert(it, v), true); return std::make_pair(it, false); } template bool Set::contains(const Set &other) const { const_iterator it = cbegin(); const_iterator otherIt = other.cbegin(); while (otherIt != other.cend()) { if (it == cend() || *otherIt < *it) return false; if (!(*it < *otherIt)) ++otherIt; ++it; } return true; } template bool Set::intersects(const Set &other) const { auto it = cbegin(); auto itOther = other.cbegin(); while (it != cend() && itOther != other.cend()) { if (*it < *itOther) ++it; else if (*itOther < *it) ++itOther; else return true; } return false; } template Set &Set::unite(const Set &other) { if (other.empty()) return *this; if (empty()) { m_data = other.m_data; return *this; } auto lowerBound = m_data.begin(); for (auto otherIt = other.cbegin(); otherIt != other.cend(); ++otherIt) { lowerBound = std::lower_bound(lowerBound, m_data.end(), *otherIt); if (lowerBound == m_data.end()) { m_data.reserve(size() + std::distance(otherIt, other.cend())); std::copy(otherIt, other.cend(), std::back_inserter(m_data)); return *this; } if (*otherIt < *lowerBound) lowerBound = m_data.insert(lowerBound, *otherIt); } return *this; } template bool Set::remove(const T &v) { const auto it = std::lower_bound(m_data.cbegin(), m_data.cend(), v); if (it != m_data.cend() && !(v < *it)) { m_data.erase(asMutableIterator(it)); return true; } return false; } template void Set::load(PersistentPool &pool) { clear(); int i = pool.load(); reserve(i); for (; --i >= 0;) m_data.push_back(loadElem(pool)); if (sortAfterLoadRequired()) sort(); } template void Set::store(PersistentPool &pool) const { pool.store(static_cast(size())); std::for_each(m_data.cbegin(), m_data.cend(), std::bind(&Set::storeElem, this, std::ref(pool), std::placeholders::_1)); } #ifdef QT_CORE_LIB template QStringList Set::toStringList() const { QStringList sl; sl.reserve(int(size())); std::transform(cbegin(), cend(), std::back_inserter(sl), [this](const T &e) { return toString(e); }); return sl; } template QString Set::toString() const { return QLatin1Char('[') + toStringList().join(QLatin1String(", ")) + QLatin1Char(']'); } template<> inline QString Set::toString(const QString &value) const { return value; } template Set Set::fromList(const QList &list) { Set s; std::copy(list.cbegin(), list.cend(), std::back_inserter(s.m_data)); s.sort(); return s; } template QList Set::toList() const { QList list; std::copy(m_data.cbegin(), m_data.cend(), std::back_inserter(list)); return list; } #endif template Set Set::fromStdVector(const std::vector &vector) { Set s; std::copy(vector.cbegin(), vector.cend(), std::back_inserter(s.m_data)); s.sort(); return s; } template Set Set::fromStdSet(const std::set &set) { Set s; std::copy(set.cbegin(), set.cend(), std::back_inserter(s.m_data)); return s; } template std::set Set::toStdSet() const { std::set set; for (auto it = cbegin(); it != cend(); ++it) set.insert(*it); return set; } template typename Set::iterator Set::asMutableIterator(typename Set::const_iterator cit) { const auto offset = std::distance(cbegin(), cit); return begin() + offset; } template template Set Set::filtered(const Set &s) { static_assert(std::is_pointer::value, "Set::filtered() assumes pointer types"); static_assert(std::is_pointer::value, "Set::filtered() assumes pointer types"); Set filteredSet; for (auto &u : s) { if (hasDynamicType>(u)) filteredSet.m_data.push_back(static_cast(u)); } return filteredSet; } template Set &Set::subtract(const Set &other) { if (empty() || other.empty()) return *this; auto lowerBound = m_data.begin(); for (auto otherIt = other.cbegin(); otherIt != other.cend(); ++otherIt) { lowerBound = std::lower_bound(lowerBound, m_data.end(), *otherIt); if (lowerBound == m_data.end()) return *this; if (!(*otherIt < *lowerBound)) lowerBound = m_data.erase(lowerBound); } return *this; } template Set operator+(const Set &set1, const Set &set2) { Set result = set1; return result += set2; } template Set operator|(const Set &set1, const Set &set2) { return set1 + set2; } template Set operator-(const Set &set1, const Set &set2) { if (set1.empty() || set2.empty()) return set1; Set result; auto it1 = set1.cbegin(); auto it2 = set2.cbegin(); while (it1 != set1.cend()) { if (it2 == set2.cend()) { std::copy(it1, set1.cend(), std::back_inserter(result.m_data)); break; } if (*it1 < *it2) { result.m_data.push_back(*it1++); } else if (*it2 < *it1) { ++it2; } else { ++it1; ++it2; } } return result; } template Set operator&(const Set &set1, const Set &set2) { Set result; auto it1 = set1.cbegin(); auto it2 = set2.cbegin(); while (it1 != set1.cend() && it2 != set2.cend()) { if (*it1 < *it2) { ++it1; continue; } if (*it2 < *it1) { ++it2; continue; } result.m_data.push_back(*it1); ++it1; ++it2; } return result; } } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/tools/settings.cpp000066400000000000000000000204021347155106100216300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "settings.h" #include "error.h" #include "profile.h" #include "settingscreator.h" #include #include #include #include #include namespace qbs { using namespace Internal; QString Settings::defaultSystemSettingsBaseDir() { switch (HostOsInfo::hostOs()) { case HostOsInfo::HostOsWindows: { const char key[] = "ALLUSERSAPPDATA"; if (qEnvironmentVariableIsSet(key)) return QLatin1String(key); return QStringLiteral("C:/ProgramData"); } case HostOsInfo::HostOsMacos: return QStringLiteral("/Library/Application Support"); case HostOsInfo::HostOsLinux: case HostOsInfo::HostOsOtherUnix: return QStringLiteral("/etc/xdg"); default: return {}; } } static QString systemSettingsBaseDir() { #ifdef QBS_ENABLE_UNIT_TESTS const char key[] = "QBS_AUTOTEST_SYSTEM_SETTINGS_DIR"; if (qEnvironmentVariableIsSet(key)) return QLatin1String(qgetenv(key)); #endif #ifdef QBS_SYSTEM_SETTINGS_DIR return QLatin1String(QBS_SYSTEM_SETTINGS_DIR); #else return Settings::defaultSystemSettingsBaseDir() + QStringLiteral("/qbs"); #endif } Settings::Settings(const QString &baseDir) : Settings(baseDir, systemSettingsBaseDir()) { } Settings::Settings(const QString &baseDir, const QString &systemBaseDir) : m_settings(SettingsCreator(baseDir).getQSettings()), m_systemSettings(new QSettings(systemBaseDir + QStringLiteral("/qbs.conf"), QSettings::IniFormat)), m_baseDir(baseDir) { // Actual qbs settings are stored transparently within a group, because QSettings // can see non-qbs fallback settings e.g. from QtProject that we're not interested in. m_settings->beginGroup(QStringLiteral("org/qt-project/qbs")); } Settings::~Settings() { delete m_settings; delete m_systemSettings; } QVariant Settings::value(const QString &key, Scopes scopes, const QVariant &defaultValue) const { QVariant userValue; if (scopes & UserScope) userValue = m_settings->value(internalRepresentation(key)); QVariant systemValue; if (scopes & SystemScope) systemValue = m_systemSettings->value(internalRepresentation(key)); if (!userValue.isValid()) { if (systemValue.isValid()) return systemValue; return defaultValue; } if (!systemValue.isValid()) return userValue; if (static_cast(userValue.type()) == QMetaType::QStringList) return userValue.toStringList() + systemValue.toStringList(); if (static_cast(userValue.type()) == QMetaType::QVariantList) return userValue.toList() + systemValue.toList(); return userValue; } QStringList Settings::allKeys(Scopes scopes) const { QStringList keys; if (scopes & UserScope) keys = m_settings->allKeys(); if (scopes & SystemScope) keys += m_systemSettings->allKeys(); fixupKeys(keys); return keys; } QStringList Settings::directChildren(const QString &parentGroup, Scope scope) const { QSettings * const settings = settingsForScope(scope); settings->beginGroup(internalRepresentation(parentGroup)); QStringList children = settings->childGroups(); children << settings->childKeys(); settings->endGroup(); fixupKeys(children); return children; } QStringList Settings::allKeysWithPrefix(const QString &group, Scopes scopes) const { QStringList keys; if (scopes & UserScope) { m_settings->beginGroup(internalRepresentation(group)); keys = m_settings->allKeys(); m_settings->endGroup(); } if (scopes & SystemScope) { m_systemSettings->beginGroup(internalRepresentation(group)); keys += m_systemSettings->allKeys(); m_systemSettings->endGroup(); } fixupKeys(keys); return keys; } void Settings::setValue(const QString &key, const QVariant &value) { if (key.startsWith(StringConstants::profilesSettingsPrefix() + Profile::fallbackName())) { throw ErrorInfo(Tr::tr("Invalid use of special profile name '%1'.") .arg(Profile::fallbackName())); } targetForWriting()->setValue(internalRepresentation(key), value); checkForWriteError(); } void Settings::remove(const QString &key) { targetForWriting()->remove(internalRepresentation(key)); checkForWriteError(); } void Settings::clear() { targetForWriting()->clear(); checkForWriteError(); } void Settings::sync() { targetForWriting()->sync(); } QString Settings::defaultProfile() const { return value(QStringLiteral("defaultProfile"), allScopes()).toString(); } QStringList Settings::profiles() const { QStringList result; if (m_scopeForWriting == UserScope) { m_settings->beginGroup(StringConstants::profilesSettingsKey()); result = m_settings->childGroups(); m_settings->endGroup(); } m_systemSettings->beginGroup(StringConstants::profilesSettingsKey()); result += m_systemSettings->childGroups(); m_systemSettings->endGroup(); result.removeDuplicates(); return result; } QString Settings::fileName() const { return targetForWriting()->fileName(); } QString Settings::internalRepresentation(const QString &externalKey) const { QString internalKey = externalKey; return internalKey.replace(QLatin1Char('.'), QLatin1Char('/')); } QString Settings::externalRepresentation(const QString &internalKey) const { QString externalKey = internalKey; return externalKey.replace(QLatin1Char('/'), QLatin1Char('.')); } void Settings::fixupKeys(QStringList &keys) const { keys.sort(); keys.removeDuplicates(); for (auto &key : keys) key = externalRepresentation(key); } QSettings *Settings::settingsForScope(Settings::Scope scope) const { return scope == UserScope ? m_settings : m_systemSettings; } QSettings *Settings::targetForWriting() const { return settingsForScope(m_scopeForWriting); } void Settings::checkForWriteError() { if (m_scopeForWriting == SystemScope && m_systemSettings->status() == QSettings::NoError) { sync(); if (m_systemSettings->status() == QSettings::AccessError) throw ErrorInfo(Tr::tr("Failure writing system settings file '%1': " "You do not have permission to write to that location.") .arg(fileName())); } } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/settings.h000066400000000000000000000075551347155106100213130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETTINGS_H #define QBS_SETTINGS_H #include "qbs_export.h" #include #include QT_BEGIN_NAMESPACE class QSettings; class QStringList; QT_END_NAMESPACE namespace qbs { class QBS_EXPORT Settings { public: // The "pure" base directory without any version scope. Empty string means "system default". Settings(const QString &baseDir); Settings(const QString &baseDir, const QString &systemBaseDir); ~Settings(); enum Scope { UserScope = 0x1, SystemScope = 0x2 }; Q_DECLARE_FLAGS(Scopes, Scope) static Scopes allScopes() { return {UserScope, SystemScope}; } QVariant value(const QString &key, Scopes scopes, const QVariant &defaultValue = QVariant()) const; QStringList allKeys(Scopes scopes) const; QStringList directChildren(const QString &parentGroup, Scope scope) const; // Keys and groups. QStringList allKeysWithPrefix(const QString &group, Scopes scopes) const; void setValue(const QString &key, const QVariant &value); void remove(const QString &key); void clear(); void sync(); void setScopeForWriting(Scope scope) { m_scopeForWriting = scope; } Scope scopeForWriting() const { return m_scopeForWriting; } QString defaultProfile() const; QStringList profiles() const; QString fileName() const; QString baseDirectory() const { return m_baseDir; } // As passed into the constructor. static QString defaultSystemSettingsBaseDir(); private: QString internalRepresentation(const QString &externalKey) const; QString externalRepresentation(const QString &internalKey) const; void fixupKeys(QStringList &keys) const; QSettings *settingsForScope(Scope scope) const; QSettings *targetForWriting() const; void checkForWriteError(); QSettings * const m_settings; QSettings * const m_systemSettings; const QString m_baseDir; Scope m_scopeForWriting = UserScope; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Settings::Scopes) } // namespace qbs #endif // QBS_SETTINGS_H qbs-src-1.13.1/src/lib/corelib/tools/settingscreator.cpp000066400000000000000000000140341347155106100232140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "settingscreator.h" #include "fileinfo.h" #include "hostosinfo.h" #include #include #include #include namespace qbs { namespace Internal { static QSettings::Format format() { return HostOsInfo::isWindowsHost() ? QSettings::IniFormat : QSettings::NativeFormat; } SettingsCreator::SettingsCreator(const QString &baseDir) : m_settingsBaseDir(baseDir), m_qbsVersion(Version::fromString(QLatin1String(QBS_VERSION))) { } QSettings *SettingsCreator::getQSettings() { createQSettings(); migrate(); return m_settings.release(); } void SettingsCreator::migrate() { if (!m_settings->allKeys().empty()) // We already have settings for this qbs version. return; m_settings.reset(); // Find settings from highest qbs version lower than this one and copy all settings data. const Version thePredecessor = predecessor(); QString oldSettingsDir = m_settingsBaseDir; if (thePredecessor.isValid()) oldSettingsDir.append(QLatin1String("/qbs/")).append(thePredecessor.toString()); QString oldProfilesDir = oldSettingsDir; if (!thePredecessor.isValid()) oldProfilesDir += QLatin1String("/qbs"); oldProfilesDir += QLatin1String("/profiles"); const QString newProfilesDir = m_newSettingsDir + QLatin1String("/profiles"); QString errorMessage; if (QFileInfo(oldProfilesDir).exists() && !copyFileRecursion(oldProfilesDir, newProfilesDir, false, true, &errorMessage)) { qWarning() << "Error in settings migration: " << errorMessage; } const QString oldSettingsFilePath = oldSettingsDir + QLatin1Char('/') + m_settingsFileName; if (QFileInfo(oldSettingsFilePath).exists() && (!QDir::root().mkpath(m_newSettingsDir) || !QFile::copy(oldSettingsFilePath, m_newSettingsFilePath))) { qWarning() << "Error in settings migration: Could not copy" << oldSettingsFilePath << "to" << m_newSettingsFilePath; } // Adapt all paths in settings that point to the old location. At the time of this writing, // that's only preferences.qbsSearchPaths as written by libqtprofilesetup, but we don't want // to hardcode that here. m_settings.reset(new QSettings(m_newSettingsFilePath, format())); for (const QString &key : m_settings->allKeys()) { QVariant v = m_settings->value(key); if (v.type() == QVariant::String) { QString s = v.toString(); if (s.contains(oldProfilesDir)) m_settings->setValue(key, s.replace(oldProfilesDir, newProfilesDir)); } else if (v.type() == QVariant::StringList) { const QStringList oldList = v.toStringList(); QStringList newList; for (const QString &oldString : oldList) { QString newString = oldString; newList << newString.replace(oldProfilesDir, newProfilesDir); } if (newList != oldList) m_settings->setValue(key, newList); } } } void SettingsCreator::createQSettings() { std::unique_ptr tmp(m_settingsBaseDir.isEmpty() ? new QSettings(format(), QSettings::UserScope, QStringLiteral("QtProject"), QStringLiteral("qbs")) : new QSettings(m_settingsBaseDir + QLatin1String("/qbs.conf"), format())); const QFileInfo fi(tmp->fileName()); m_settingsBaseDir = fi.path(); m_newSettingsDir = m_settingsBaseDir + QLatin1String("/qbs/") + m_qbsVersion.toString(); m_settingsFileName = fi.fileName(); m_newSettingsFilePath = m_newSettingsDir + QLatin1Char('/') + m_settingsFileName; m_settings.reset(new QSettings(m_newSettingsFilePath, tmp->format())); } Version SettingsCreator::predecessor() const { QDirIterator dit(m_settingsBaseDir + QLatin1String("/qbs")); Version thePredecessor; while (dit.hasNext()) { dit.next(); const auto currentVersion = Version::fromString(dit.fileName()); if (currentVersion > thePredecessor && currentVersion < m_qbsVersion) thePredecessor = currentVersion; } return thePredecessor; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/settingscreator.h000066400000000000000000000050361347155106100226630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETTINGSCREATOR_H #define QBS_SETTINGSCREATOR_H #include "version.h" #include #include QT_BEGIN_NAMESPACE class QSettings; QT_END_NAMESPACE namespace qbs { namespace Internal { class SettingsCreator { public: SettingsCreator(const QString &baseDir); QSettings *getQSettings(); private: void migrate(); void createQSettings(); Version predecessor() const; QString m_settingsBaseDir; QString m_newSettingsDir; QString m_settingsFileName; QString m_newSettingsFilePath; std::unique_ptr m_settings; const Version m_qbsVersion; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/tools/settingsmodel.cpp000066400000000000000000000301211347155106100226500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "settingsmodel.h" #include "settingsrepresentation.h" #include #include #include #include #include #include #ifdef QT_GUI_LIB #include #endif #include namespace qbs { namespace Internal { struct Node { Node() : parent(nullptr), isFromSettings(true) {} ~Node() { qDeleteAll(children); } QString uniqueChildName() const; bool hasDirectChildWithName(const QString &name) const; QString name; QString value; Node *parent; QList children; bool isFromSettings; }; QString Node::uniqueChildName() const { QString newName = QStringLiteral("newkey"); bool unique; do { unique = true; for (const Node *childNode : qAsConst(children)) { if (childNode->name == newName) { unique = false; newName += QLatin1Char('_'); break; } } } while (!unique); return newName; } bool Node::hasDirectChildWithName(const QString &name) const { for (const Node * const child : qAsConst(children)) { if (child->name == name) return true; } return false; } } // namespace Internal using Internal::Node; class SettingsModel::SettingsModelPrivate { public: SettingsModelPrivate() : dirty(false), editable(true) {} void readSettings(); void addNodeFromSettings(Node *parentNode, const QString &fullyQualifiedName); void addNode(Node *parentNode, const QString ¤tNamePart, const QStringList &restOfName, const QVariant &value); void doSave(const Node *node, const QString &prefix); Node *indexToNode(const QModelIndex &index); Settings::Scope scope() const { return settings->scopeForWriting(); } Node rootNode; std::unique_ptr settings; QVariantMap additionalProperties; bool dirty; bool editable; }; SettingsModel::SettingsModel(const QString &settingsDir, Settings::Scope scope, QObject *parent) : QAbstractItemModel(parent), d(new SettingsModelPrivate) { d->settings.reset(new qbs::Settings(settingsDir)); d->settings->setScopeForWriting(scope); d->readSettings(); } SettingsModel::~SettingsModel() { delete d; } void SettingsModel::reload() { beginResetModel(); d->readSettings(); endResetModel(); } void SettingsModel::save() { if (!d->dirty) return; d->settings->clear(); d->doSave(&d->rootNode, QString()); d->dirty = false; } void SettingsModel::updateSettingsDir(const QString &settingsDir) { const Settings::Scope scope = d->scope(); beginResetModel(); d->settings.reset(new qbs::Settings(settingsDir)); d->settings->setScopeForWriting(scope); d->readSettings(); endResetModel(); } void SettingsModel::addNewKey(const QModelIndex &parent) { Node *parentNode = d->indexToNode(parent); if (!parentNode) return; const auto newNode = new Node; newNode->parent = parentNode; newNode->name = parentNode->uniqueChildName(); beginInsertRows(parent, parentNode->children.size(), parentNode->children.size()); parentNode->children << newNode; endInsertRows(); d->dirty = true; } void SettingsModel::removeKey(const QModelIndex &index) { Node * const node = d->indexToNode(index); if (!node || node == &d->rootNode) return; const int positionInParent = node->parent->children.indexOf(node); beginRemoveRows(parent(index), positionInParent, positionInParent); node->parent->children.removeAt(positionInParent); delete node; endRemoveRows(); d->dirty = true; } bool SettingsModel::hasUnsavedChanges() const { return d->dirty; } void SettingsModel::setEditable(bool isEditable) { d->editable = isEditable; } void SettingsModel::setAdditionalProperties(const QVariantMap &properties) { d->additionalProperties = properties; reload(); } Qt::ItemFlags SettingsModel::flags(const QModelIndex &index) const { if (!index.isValid()) return Qt::NoItemFlags; const Qt::ItemFlags flags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); if (index.column() == keyColumn()) { if (d->editable) return flags | Qt::ItemIsEditable; return flags; } if (index.column() == valueColumn()) { const Node * const node = d->indexToNode(index); if (!node) return Qt::NoItemFlags; // Only leaf nodes have values. return d->editable && node->children.empty() ? flags | Qt::ItemIsEditable : flags; } return {}; } QVariant SettingsModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation != Qt::Horizontal) return {}; if (role != Qt::DisplayRole) return {}; if (section == keyColumn()) return tr("Key"); if (section == valueColumn()) return tr("Value"); return {}; } int SettingsModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return 2; } int SettingsModel::rowCount(const QModelIndex &parent) const { if (parent.column() > 0) return 0; const Node * const node = d->indexToNode(parent); Q_ASSERT(node); return node->children.size(); } QVariant SettingsModel::data(const QModelIndex &index, int role) const { if (role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::ForegroundRole) return {}; const Node * const node = d->indexToNode(index); if (!node) return {}; if (role == Qt::ForegroundRole) { #ifdef QT_GUI_LIB if (index.column() == valueColumn() && !node->isFromSettings) return QBrush(Qt::red); #endif return {}; } if (index.column() == keyColumn()) return node->name; if (index.column() == valueColumn() && node->children.empty()) return node->value; return {}; } bool SettingsModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid() || role != Qt::EditRole) return false; Node * const node = d->indexToNode(index); if (!node) return false; const QString valueString = value.toString(); QString *toChange = nullptr; if (index.column() == keyColumn() && !valueString.isEmpty() && !node->parent->hasDirectChildWithName(valueString) && !(node->parent->parent == &d->rootNode && node->parent->name == Internal::StringConstants::profilesSettingsKey() && valueString == Profile::fallbackName())) { toChange = &node->name; } else if (index.column() == valueColumn() && valueString != node->value) { toChange = &node->value; } if (toChange) { *toChange = valueString; emit dataChanged(index, index); d->dirty = true; } return toChange; } QModelIndex SettingsModel::index(int row, int column, const QModelIndex &parent) const { const Node * const parentNode = d->indexToNode(parent); Q_ASSERT(parentNode); if (parentNode->children.size() <= row) return {}; return createIndex(row, column, parentNode->children.at(row)); } QModelIndex SettingsModel::parent(const QModelIndex &child) const { const auto childNode = static_cast(child.internalPointer()); Q_ASSERT(childNode); Node * const parentNode = childNode->parent; if (parentNode == &d->rootNode) return {}; const Node * const grandParentNode = parentNode->parent; Q_ASSERT(grandParentNode); return createIndex(grandParentNode->children.indexOf(parentNode), 0, parentNode); } void SettingsModel::SettingsModelPrivate::readSettings() { qDeleteAll(rootNode.children); rootNode.children.clear(); for (const QString &topLevelKey : settings->directChildren(QString(), scope())) addNodeFromSettings(&rootNode, topLevelKey); for (QVariantMap::ConstIterator it = additionalProperties.constBegin(); it != additionalProperties.constEnd(); ++it) { const QStringList nameAsList = it.key().split(QLatin1Char('.'), QString::SkipEmptyParts); addNode(&rootNode, nameAsList.front(), nameAsList.mid(1), it.value()); } dirty = false; } static Node *createNode(Node *parentNode, const QString &name) { const auto node = new Node; node->name = name; node->parent = parentNode; parentNode->children.push_back(node); return node; } void SettingsModel::SettingsModelPrivate::addNodeFromSettings(Node *parentNode, const QString &fullyQualifiedName) { const QString &nodeName = fullyQualifiedName.mid(fullyQualifiedName.lastIndexOf(QLatin1Char('.')) + 1); Node * const node = createNode(parentNode, nodeName); node->value = settingsValueToRepresentation(settings->value(fullyQualifiedName, scope())); for (const QString &childKey : settings->directChildren(fullyQualifiedName, scope())) addNodeFromSettings(node, fullyQualifiedName + QLatin1Char('.') + childKey); dirty = true; } void SettingsModel::SettingsModelPrivate::addNode(qbs::Internal::Node *parentNode, const QString ¤tNamePart, const QStringList &restOfName, const QVariant &value) { Node *currentNode = nullptr; for (Node * const n : qAsConst(parentNode->children)) { if (n->name == currentNamePart) { currentNode = n; break; } } if (!currentNode) currentNode = createNode(parentNode, currentNamePart); if (restOfName.empty()) { currentNode->value = settingsValueToRepresentation(value); currentNode->isFromSettings = false; } else { addNode(currentNode, restOfName.front(), restOfName.mid(1), value); } } void SettingsModel::SettingsModelPrivate::doSave(const Node *node, const QString &prefix) { if (node->children.empty()) { settings->setValue(prefix + node->name, representationToSettingsValue(node->value)); return; } const QString newPrefix = prefix + node->name + QLatin1Char('.'); for (const Node * const child : qAsConst(node->children)) doSave(child, newPrefix); } Node *SettingsModel::SettingsModelPrivate::indexToNode(const QModelIndex &index) { return index.isValid() ? static_cast(index.internalPointer()) : &rootNode; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/settingsmodel.h000066400000000000000000000067751347155106100223370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETTINGSMODEL_H #define QBS_SETTINGSMODEL_H #include #include #include #include namespace qbs { class QBS_EXPORT SettingsModel : public QAbstractItemModel { Q_OBJECT public: SettingsModel(const QString &settingsDir, Settings::Scope scope, QObject *parent = nullptr); ~SettingsModel(); int keyColumn() const { return 0; } int valueColumn() const { return 1; } bool hasUnsavedChanges() const; void setEditable(bool isEditable); void setAdditionalProperties(const QVariantMap &properties); // Flat map. void reload(); void save(); void updateSettingsDir(const QString &settingsDir); void addNewKey(const QModelIndex &parent); void removeKey(const QModelIndex &index); Qt::ItemFlags flags(const QModelIndex &index) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex &child) const override; private: class SettingsModelPrivate; SettingsModelPrivate * const d; }; } // namespace qbs #endif // QBS_SETTINGSMODEL_H qbs-src-1.13.1/src/lib/corelib/tools/settingsrepresentation.cpp000066400000000000000000000060751347155106100246250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "settingsrepresentation.h" #include "jsliterals.h" #include #include namespace qbs { QString settingsValueToRepresentation(const QVariant &value) { return toJSLiteral(value); } static QVariant variantFromString(const QString &str, bool &ok) { // ### use Qt5's JSON reader at some point. QScriptEngine engine; QScriptValue sv = engine.evaluate(QLatin1String("(function(){return ") + str + QLatin1String(";})()")); ok = !sv.isError(); return sv.toVariant(); } QVariant representationToSettingsValue(const QString &representation) { bool ok; QVariant variant = variantFromString(representation, ok); // We have no floating-point properties, so this is most likely intended to be a string. if (static_cast(variant.type()) == QMetaType::Float || static_cast(variant.type()) == QMetaType::Double) { variant = variantFromString(QLatin1Char('"') + representation + QLatin1Char('"'), ok); } if (ok) return variant; // If it's not valid JavaScript, interpret the value as a string. return representation; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/settingsrepresentation.h000066400000000000000000000043551347155106100242710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETTINGSREPRESENTATION_H #define QBS_SETTINGSREPRESENTATION_H #include #include #include namespace qbs { QBS_EXPORT QString settingsValueToRepresentation(const QVariant &value); QBS_EXPORT QVariant representationToSettingsValue(const QString &representation); } // namespace qbs #endif // QBS_SETTINGSREPRESENTATION_H qbs-src-1.13.1/src/lib/corelib/tools/setupprojectparameters.cpp000066400000000000000000000500201347155106100246020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "setupprojectparameters.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { /*! * \class SetupProjectParameters * \brief The \c SetupProjectParameters class comprises data required to set up a qbs project. */ class SetupProjectParametersPrivate : public QSharedData { public: SetupProjectParametersPrivate() : overrideBuildGraphData(false) , dryRun(false) , logElapsedTime(false) , forceProbeExecution(false) , waitLockBuildGraph(false) , restoreBehavior(SetupProjectParameters::RestoreAndTrackChanges) , propertyCheckingMode(ErrorHandlingMode::Relaxed) , productErrorMode(ErrorHandlingMode::Strict) { } QString projectFilePath; QString topLevelProfile; QString configurationName; QString buildRoot; QStringList searchPaths; QStringList pluginPaths; QString libexecPath; QString settingsBaseDir; QVariantMap overriddenValues; QVariantMap buildConfiguration; mutable QVariantMap buildConfigurationTree; mutable QVariantMap overriddenValuesTree; mutable QVariantMap finalBuildConfigTree; bool overrideBuildGraphData; bool dryRun; bool logElapsedTime; bool forceProbeExecution; bool waitLockBuildGraph; bool fallbackProviderEnabled = true; SetupProjectParameters::RestoreBehavior restoreBehavior; ErrorHandlingMode propertyCheckingMode; ErrorHandlingMode productErrorMode; QProcessEnvironment environment; }; } // namespace Internal SetupProjectParameters::SetupProjectParameters() : d(new Internal::SetupProjectParametersPrivate) { } SetupProjectParameters::SetupProjectParameters(const SetupProjectParameters &other) : d(other.d) { } SetupProjectParameters::~SetupProjectParameters() { } SetupProjectParameters &SetupProjectParameters::operator=(const SetupProjectParameters &other) { d = other.d; return *this; } /*! * \brief Returns the name of the top-level profile for building the project. */ QString SetupProjectParameters::topLevelProfile() const { return d->topLevelProfile; } /*! * \brief Sets the top-level profile for building the project. */ void SetupProjectParameters::setTopLevelProfile(const QString &profile) { d->buildConfigurationTree.clear(); d->finalBuildConfigTree.clear(); d->topLevelProfile = profile; } /*! * Returns the name of the current project build configuration. */ QString SetupProjectParameters::configurationName() const { return d->configurationName; } /*! * Sets the name of the current project build configuration to an arbitrary user-specified name, * \a configurationName. */ void SetupProjectParameters::setConfigurationName(const QString &configurationName) { d->buildConfigurationTree.clear(); d->finalBuildConfigTree.clear(); d->configurationName = configurationName; } /*! * \brief Returns the absolute path to the qbs project file. * This file typically has a ".qbs" suffix. */ QString SetupProjectParameters::projectFilePath() const { return d->projectFilePath; } /*! * \brief Sets the path to the main project file. * \note The argument must be an absolute file path. */ void SetupProjectParameters::setProjectFilePath(const QString &projectFilePath) { d->projectFilePath = projectFilePath; const QString canonicalProjectFilePath = QFileInfo(d->projectFilePath).canonicalFilePath(); if (!canonicalProjectFilePath.isEmpty()) d->projectFilePath = canonicalProjectFilePath; } /*! * \brief Returns the base path of where to put the build artifacts and store the build graph. */ QString SetupProjectParameters::buildRoot() const { return d->buildRoot; } /*! * \brief Sets the base path of where to put the build artifacts and store the build graph. * The same base path can be used for several build profiles of the same project without them * interfering with each other. * It might look as if this parameter would not be needed at the time of setting up the project, * but keep in mind that the project information could already exist on disk, in which case * loading it will be much faster than setting up the project from scratch. * \note The argument must be an absolute path to a directory. */ void SetupProjectParameters::setBuildRoot(const QString &buildRoot) { d->buildRoot = buildRoot; // Calling mkpath() may be necessary to get the canonical build root, but if we do it, // it must be reverted immediately afterwards as not to create directories needlessly, // e.g in the case of a dry run build. Internal::DirectoryManager dirManager(buildRoot, Internal::Logger()); // We don't do error checking here, as this is not a convenient place to report an error. // If creation of the build directory is not possible, we will get sensible error messages // later, e.g. from the code that attempts to store the build graph. QDir::root().mkpath(buildRoot); const QString canonicalBuildRoot = QFileInfo(d->buildRoot).canonicalFilePath(); if (!canonicalBuildRoot.isEmpty()) d->buildRoot = canonicalBuildRoot; } /*! * \brief Where to look for modules and items to import. */ QStringList SetupProjectParameters::searchPaths() const { return d->searchPaths; } /*! * \brief Sets the information about where to look for modules and items to import. * \note The elements of the list must be absolute paths to directories. */ void SetupProjectParameters::setSearchPaths(const QStringList &searchPaths) { d->searchPaths = searchPaths; } /*! * \brief Where to look for plugins. */ QStringList SetupProjectParameters::pluginPaths() const { return d->pluginPaths; } /*! * \brief Sets the information about where to look for plugins. * \note The elements of the list must be absolute paths to directories. */ void SetupProjectParameters::setPluginPaths(const QStringList &pluginPaths) { d->pluginPaths = pluginPaths; } /*! * \brief Where to look for internal binaries. */ QString SetupProjectParameters::libexecPath() const { return d->libexecPath; } /*! * \brief Sets the information about where to look for internal binaries. * \note \p libexecPath must be an absolute path. */ void SetupProjectParameters::setLibexecPath(const QString &libexecPath) { d->libexecPath = libexecPath; } /*! * \brief The base directory for qbs settings. * This value is used to locate profiles and preferences. */ QString SetupProjectParameters::settingsDirectory() const { return d->settingsBaseDir; } /*! * \brief Sets the base directory for qbs settings. * \param settingsBaseDir Will be used to locate profiles and preferences. */ void SetupProjectParameters::setSettingsDirectory(const QString &settingsBaseDir) { d->settingsBaseDir = settingsBaseDir; } /*! * Returns the overridden values of the build configuration. */ QVariantMap SetupProjectParameters::overriddenValues() const { return d->overriddenValues; } /*! * Set the overridden values of the build configuration. */ void SetupProjectParameters::setOverriddenValues(const QVariantMap &values) { d->overriddenValues = values; d->overriddenValuesTree.clear(); d->finalBuildConfigTree.clear(); } static void provideValuesTree(const QVariantMap &values, QVariantMap *valueTree) { if (!valueTree->empty() || values.empty()) return; valueTree->clear(); for (QVariantMap::const_iterator it = values.constBegin(); it != values.constEnd(); ++it) { const QString name = it.key(); int idx = name.lastIndexOf(QLatin1Char('.')); const QStringList nameElements = (idx == -1) ? QStringList() << name : QStringList() << name.left(idx) << name.mid(idx + 1); Internal::setConfigProperty(*valueTree, nameElements, it.value()); } } QVariantMap SetupProjectParameters::overriddenValuesTree() const { provideValuesTree(d->overriddenValues, &d->overriddenValuesTree); return d->overriddenValuesTree; } /*! * \brief Returns the build configuration. * Overridden values are not taken into account. */ QVariantMap SetupProjectParameters::buildConfiguration() const { return d->buildConfiguration; } /*! * \brief Returns the build configuration in tree form. * Overridden values are not taken into account. */ QVariantMap SetupProjectParameters::buildConfigurationTree() const { provideValuesTree(d->buildConfiguration, &d->buildConfigurationTree); return d->buildConfigurationTree; } static QVariantMap expandedBuildConfigurationInternal(const Profile &profile, const QString &configurationName) { QVariantMap buildConfig; // (1) Values from profile, if given. if (profile.exists() && profile.name() != Profile::fallbackName()) { ErrorInfo err; const QStringList profileKeys = profile.allKeys(Profile::KeySelectionRecursive, &err); if (err.hasError()) throw err; if (profileKeys.empty()) throw ErrorInfo(Internal::Tr::tr("Unknown or empty profile '%1'.").arg(profile.name())); for (const QString &profileKey : profileKeys) { buildConfig.insert(profileKey, profile.value(profileKey, QVariant(), &err)); if (err.hasError()) throw err; } } // (2) Build configuration name. if (configurationName.isEmpty()) throw ErrorInfo(Internal::Tr::tr("No build configuration name set.")); buildConfig.insert(QStringLiteral("qbs.configurationName"), configurationName); return buildConfig; } QVariantMap SetupProjectParameters::expandedBuildConfiguration(const Profile &profile, const QString &configurationName, ErrorInfo *errorInfo) { try { return expandedBuildConfigurationInternal(profile, configurationName); } catch (const ErrorInfo &err) { if (errorInfo) *errorInfo = err; return {}; } } /*! * \brief Expands the build configuration. * * Expansion is the process by which the build configuration is completed based on the settings * in \c settingsDirectory(). E.g. the information configured in a profile is filled into the build * configuration by this step. * * This method returns an Error. The list of entries in this error will be empty is the * expansion was successful. */ ErrorInfo SetupProjectParameters::expandBuildConfiguration() { ErrorInfo err; Settings settings(d->settingsBaseDir); Profile profile(topLevelProfile(), &settings); QVariantMap expandedConfig = expandedBuildConfiguration(profile, configurationName(), &err); if (err.hasError()) return err; if (d->buildConfiguration != expandedConfig) { d->buildConfigurationTree.clear(); d->buildConfiguration = expandedConfig; } return err; } QVariantMap SetupProjectParameters::finalBuildConfigurationTree(const QVariantMap &buildConfig, const QVariantMap &overriddenValues) { QVariantMap flatBuildConfig = buildConfig; for (QVariantMap::ConstIterator it = overriddenValues.constBegin(); it != overriddenValues.constEnd(); ++it) { flatBuildConfig.insert(it.key(), it.value()); } QVariantMap buildConfigTree; provideValuesTree(flatBuildConfig, &buildConfigTree); return buildConfigTree; } /*! * \brief Returns the build configuration in tree form, with overridden values taken into account. */ QVariantMap SetupProjectParameters::finalBuildConfigurationTree() const { if (d->finalBuildConfigTree.empty()) { d->finalBuildConfigTree = finalBuildConfigurationTree(buildConfiguration(), overriddenValues()); } return d->finalBuildConfigTree; } /*! * \brief if true, qbs will not store the build graph of the resolved project. */ bool SetupProjectParameters::dryRun() const { return d->dryRun; } /*! * \brief Controls whether the build graph will be stored. * If the argument is true, qbs will not store the build graph after resolving the project. * The default is false. */ void SetupProjectParameters::setDryRun(bool dryRun) { d->dryRun = dryRun; } /*! * \brief Returns true iff the time the operation takes should be logged */ bool SetupProjectParameters::logElapsedTime() const { return d->logElapsedTime; } /*! * Controls whether to log the time taken up for resolving the project. * The default is false. */ void SetupProjectParameters::setLogElapsedTime(bool logElapsedTime) { d->logElapsedTime = logElapsedTime; } /*! * \brief Returns true iff probes should be re-run. */ bool SetupProjectParameters::forceProbeExecution() const { return d->forceProbeExecution; } /*! * Controls whether to re-run probes even if they do not appear to be outdated. * This option only has an effect if \c restoreBehavior() is \c RestoreAndTrackChanges. */ void SetupProjectParameters::setForceProbeExecution(bool force) { d->forceProbeExecution = force; } /*! * \brief Returns true if qbs should wait for the build graph lock to become available, * otherwise qbs will exit immediately if the lock cannot be acquired. */ bool SetupProjectParameters::waitLockBuildGraph() const { return d->waitLockBuildGraph; } /*! * Controls whether to wait indefinitely for the build graph lock to be released. * This allows multiple conflicting qbs processes to be spawned simultaneously. */ void SetupProjectParameters::setWaitLockBuildGraph(bool wait) { d->waitLockBuildGraph = wait; } /*! * \brief Returns true if qbs should fall back to pkg-config if a dependency is not found. */ bool SetupProjectParameters::fallbackProviderEnabled() const { return d->fallbackProviderEnabled; } /*! * Controls whether to fall back to pkg-config if a dependency is not found. */ void SetupProjectParameters::setFallbackProviderEnabled(bool enable) { d->fallbackProviderEnabled = enable; } /*! * \brief Gets the environment used while resolving the project. */ QProcessEnvironment SetupProjectParameters::environment() const { return d->environment; } /*! * \brief Sets the environment used while resolving the project. */ void SetupProjectParameters::setEnvironment(const QProcessEnvironment &env) { d->environment = env; } QProcessEnvironment SetupProjectParameters::adjustedEnvironment() const { QProcessEnvironment result = environment(); const QVariantMap environmentFromProfile = buildConfigurationTree().value(QStringLiteral("buildEnvironment")).toMap(); for (QVariantMap::const_iterator it = environmentFromProfile.begin(); it != environmentFromProfile.end(); ++it) { result.insert(it.key(), it.value().toString()); } return result; } /*! * \enum SetupProjectParamaters::RestoreBehavior * This enum type specifies how to deal with existing on-disk build information. * \value RestoreOnly Indicates that a stored build graph is to be loaded and the information * therein assumed to be up to date. It is then considered an error if no * such build graph exists. * \value ResolveOnly Indicates that no attempt should be made to restore an existing build graph. * Instead, the project is to be resolved from scratch. * \value RestoreAndTrackChanges Indicates that the build graph should be restored from disk * if possible and otherwise set up from scratch. In the first case, * (parts of) the project might still be re-resolved if certain * parameters have changed (e.g. environment variables used in the * project files). */ /*! * Returns information about how restored build data will be handled. */ SetupProjectParameters::RestoreBehavior SetupProjectParameters::restoreBehavior() const { return d->restoreBehavior; } /*! * Controls how restored build data will be handled. */ void SetupProjectParameters::setRestoreBehavior(SetupProjectParameters::RestoreBehavior behavior) { d->restoreBehavior = behavior; } /*! * Returns true if and only if environment, project file path and overridden property values * should be taken from this object even if a build graph already exists. * If this function returns \c false and a build graph exists, then it is an error to provide a * project file path or overridden property values that differ from the respective values * in the build graph. */ bool SetupProjectParameters::overrideBuildGraphData() const { return d->overrideBuildGraphData; } /*! * If \c doOverride is true, then environment, project file path and overridden property values * are taken from this object rather than from the build graph. * The default is \c false. */ void SetupProjectParameters::setOverrideBuildGraphData(bool doOverride) { d->overrideBuildGraphData = doOverride; } /*! * \enum ErrorHandlingMode * This enum type specifies how \QBS should behave if errors occur during project resolving. * \value ErrorHandlingMode::Strict Project resolving will stop with an error message. * \value ErrorHandlingMode::Relaxed Project resolving will continue (if possible), and a warning * will be printed. */ /*! * Indicates how to handle unknown properties. */ ErrorHandlingMode SetupProjectParameters::propertyCheckingMode() const { return d->propertyCheckingMode; } /*! * Controls how to handle unknown properties. * The default is \c PropertyCheckingRelaxed. */ void SetupProjectParameters::setPropertyCheckingMode(ErrorHandlingMode mode) { d->propertyCheckingMode = mode; } /*! * \brief Indicates how errors occurring during product resolving are handled. */ ErrorHandlingMode SetupProjectParameters::productErrorMode() const { return d->productErrorMode; } /*! * \brief Specifies whether an error occurring during product resolving should be fatal or not. * \note Not all errors can be ignored; this setting is mainly intended for things such as * missing dependencies or references to non-existing source files. */ void SetupProjectParameters::setProductErrorMode(ErrorHandlingMode mode) { d->productErrorMode = mode; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/setupprojectparameters.h000066400000000000000000000121501347155106100242510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SETUPPROJECTPARAMETERS_H #define QBS_SETUPPROJECTPARAMETERS_H #include "qbs_export.h" #include #include QT_BEGIN_NAMESPACE class QProcessEnvironment; class QStringList; using QVariantMap = QMap; QT_END_NAMESPACE namespace qbs { class Profile; class Settings; namespace Internal { class SetupProjectParametersPrivate; } enum class ErrorHandlingMode { Strict, Relaxed }; class QBS_EXPORT SetupProjectParameters { public: SetupProjectParameters(); SetupProjectParameters(const SetupProjectParameters &other); ~SetupProjectParameters(); SetupProjectParameters &operator=(const SetupProjectParameters &other); QString topLevelProfile() const; void setTopLevelProfile(const QString &profile); QString configurationName() const; void setConfigurationName(const QString &configurationName); QString projectFilePath() const; void setProjectFilePath(const QString &projectFilePath); QString buildRoot() const; void setBuildRoot(const QString &buildRoot); QStringList searchPaths() const; void setSearchPaths(const QStringList &searchPaths); QStringList pluginPaths() const; void setPluginPaths(const QStringList &pluginPaths); QString libexecPath() const; void setLibexecPath(const QString &libexecPath); QString settingsDirectory() const; void setSettingsDirectory(const QString &settingsBaseDir); QVariantMap overriddenValues() const; void setOverriddenValues(const QVariantMap &values); QVariantMap overriddenValuesTree() const; static QVariantMap expandedBuildConfiguration(const Profile &profile, const QString &configurationName, ErrorInfo *errorInfo = nullptr); ErrorInfo expandBuildConfiguration(); QVariantMap buildConfiguration() const; QVariantMap buildConfigurationTree() const; static QVariantMap finalBuildConfigurationTree(const QVariantMap &buildConfig, const QVariantMap &overriddenValues); QVariantMap finalBuildConfigurationTree() const; bool overrideBuildGraphData() const; void setOverrideBuildGraphData(bool doOverride); bool dryRun() const; void setDryRun(bool dryRun); bool logElapsedTime() const; void setLogElapsedTime(bool logElapsedTime); bool forceProbeExecution() const; void setForceProbeExecution(bool force); bool waitLockBuildGraph() const; void setWaitLockBuildGraph(bool wait); bool fallbackProviderEnabled() const; void setFallbackProviderEnabled(bool enable); QProcessEnvironment environment() const; void setEnvironment(const QProcessEnvironment &env); QProcessEnvironment adjustedEnvironment() const; enum RestoreBehavior { RestoreOnly, ResolveOnly, RestoreAndTrackChanges }; RestoreBehavior restoreBehavior() const; void setRestoreBehavior(RestoreBehavior behavior); ErrorHandlingMode propertyCheckingMode() const; void setPropertyCheckingMode(ErrorHandlingMode mode); ErrorHandlingMode productErrorMode() const; void setProductErrorMode(ErrorHandlingMode mode); private: QSharedDataPointer d; }; } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/tools/shellutils.cpp000066400000000000000000000206551347155106100221720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "shellutils.h" #include "pathutils.h" #include #include #include namespace qbs { namespace Internal { QString shellInterpreter(const QString &filePath) { QFile file(filePath); if (file.open(QIODevice::ReadOnly)) { QTextStream ts(&file); const QString shebang = ts.readLine(); if (shebang.startsWith(QLatin1String("#!"))) { return (shebang.mid(2).split(QRegExp(QStringLiteral("\\s")), QString::SkipEmptyParts) << QString()).front(); } } return {}; } // isSpecialChar, hasSpecialChars, shellQuoteUnix, shellQuoteWin: // all from qtbase/qmake/library/ioutils.cpp inline static bool isSpecialChar(ushort c, const uchar (&iqm)[16]) { if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)))) return true; return false; } inline static bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16]) { for (auto it = arg.crbegin(), end = arg.crend(); it != end; ++it) { if (isSpecialChar(it->unicode(), iqm)) return true; } return false; } static QString shellQuoteUnix(const QString &arg) { // Chars that should be quoted (TM). This includes: static const uchar iqm[] = { 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78 }; // 0-32 \'"$`<>|;&(){}*?#!~[] if (!arg.length()) return QStringLiteral("''"); QString ret(arg); if (hasSpecialChars(ret, iqm)) { ret.replace(QLatin1Char('\''), QLatin1String("'\\''")); ret.prepend(QLatin1Char('\'')); ret.append(QLatin1Char('\'')); } return ret; } static QString shellQuoteWin(const QString &arg) { // Chars that should be quoted (TM). This includes: // - control chars & space // - the shell meta chars "&()<>^| // - the potential separators ,;= static const uchar iqm[] = { 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10 }; // Shell meta chars that need escaping. static const uchar ism[] = { 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10 }; // &()<>^| if (!arg.length()) return QStringLiteral("\"\""); QString ret(arg); if (hasSpecialChars(ret, iqm)) { // The process-level standard quoting allows escaping quotes with backslashes (note // that backslashes don't escape themselves, unless they are followed by a quote). // Consequently, quotes are escaped and their preceding backslashes are doubled. ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\"")); // Trailing backslashes must be doubled as well, as they are followed by a quote. ret.replace(QRegExp(QLatin1String("(\\\\+)$")), QLatin1String("\\1\\1")); // However, the shell also interprets the command, and no backslash-escaping exists // there - a quote always toggles the quoting state, but is nonetheless passed down // to the called process verbatim. In the unquoted state, the circumflex escapes // meta chars (including itself and quotes), and is removed from the command. bool quoted = true; for (int i = 0; i < ret.length(); i++) { QChar c = ret.unicode()[i]; if (c.unicode() == '"') quoted = !quoted; else if (!quoted && isSpecialChar(c.unicode(), ism)) ret.insert(i++, QLatin1Char('^')); } if (!quoted) ret.append(QLatin1Char('^')); ret.append(QLatin1Char('"')); ret.prepend(QLatin1Char('"')); } return ret; } QString shellQuote(const QString &arg, HostOsInfo::HostOs os) { return os == HostOsInfo::HostOsWindows ? shellQuoteWin(arg) : shellQuoteUnix(arg); } std::string shellQuote(const std::string &arg, HostOsInfo::HostOs os) { return shellQuote(QString::fromStdString(arg), os).toStdString(); } QString shellQuote(const QStringList &args, HostOsInfo::HostOs os) { QString result; if (!args.empty()) { result += shellQuote(args.at(0), os); for (int i = 1; i < args.size(); ++i) result += QLatin1Char(' ') + shellQuote(args.at(i), os); } return result; } std::string shellQuote(const std::vector &args, HostOsInfo::HostOs os) { std::string result; if (!args.empty()) { auto it = args.cbegin(); const auto end = args.cend(); result += shellQuote(*it++, os); for (; it != end; ++it) { result.push_back(' '); result.append(shellQuote(*it, os)); } } return result; } QString shellQuote(const QString &program, const QStringList &args, HostOsInfo::HostOs os) { QString result = shellQuote(program, os); if (!args.empty()) result += QLatin1Char(' ') + shellQuote(args, os); return result; } void CommandLine::setProgram(const QString &program, bool raw) { m_program = program; m_isRawProgram = raw; } void CommandLine::setProgram(const std::string &program, bool raw) { m_program = QString::fromStdString(program); m_isRawProgram = raw; } void CommandLine::appendArgument(const QString &value) { m_arguments.push_back(value); } void CommandLine::appendArgument(const std::string &value) { m_arguments.push_back(QString::fromStdString(value)); } void CommandLine::appendArguments(const QList &args) { for (const QString &arg : args) appendArgument(arg); } void CommandLine::appendRawArgument(const QString &value) { Argument arg(value); arg.shouldQuote = false; m_arguments.push_back(arg); } void CommandLine::appendRawArgument(const std::string &value) { appendRawArgument(QString::fromStdString(value)); } void CommandLine::appendPathArgument(const QString &value) { Argument arg(value); arg.isFilePath = true; m_arguments.push_back(arg); } void CommandLine::clearArguments() { m_arguments.clear(); } QString CommandLine::toCommandLine(HostOsInfo::HostOs os) const { QString result = PathUtils::toNativeSeparators(m_program, os); if (!m_isRawProgram) result = shellQuote(result, os); for (const Argument &arg : m_arguments) { const QString value = arg.isFilePath ? PathUtils::toNativeSeparators(arg.value, os) : arg.value; result += QLatin1Char(' ') + (arg.shouldQuote ? shellQuote(value, os) : value); } return result; } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/shellutils.h000066400000000000000000000072741347155106100216410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_SHELLUTILS_H #define QBS_SHELLUTILS_H #include "qbs_export.h" #include "hostosinfo.h" #include #include namespace qbs { namespace Internal { QBS_EXPORT QString shellInterpreter(const QString &filePath); QBS_EXPORT std::string shellQuote(const std::string &arg, HostOsInfo::HostOs os = HostOsInfo::hostOs()); QBS_EXPORT QString shellQuote(const QString &arg, HostOsInfo::HostOs os = HostOsInfo::hostOs()); QBS_EXPORT QString shellQuote(const QStringList &args, HostOsInfo::HostOs os = HostOsInfo::hostOs()); QBS_EXPORT std::string shellQuote(const std::vector &args, HostOsInfo::HostOs os = HostOsInfo::hostOs()); QBS_EXPORT QString shellQuote(const QString &program, const QStringList &args, HostOsInfo::HostOs os = HostOsInfo::hostOs()); class QBS_EXPORT CommandLine { public: void setProgram(const QString &program, bool raw = false); void setProgram(const std::string &program, bool raw = false); void appendArgument(const QString &value); void appendArgument(const std::string &value); void appendArguments(const QList &args); void appendRawArgument(const QString &value); void appendRawArgument(const std::string &value); void appendPathArgument(const QString &value); void clearArguments(); QString toCommandLine(HostOsInfo::HostOs os = HostOsInfo::hostOs()) const; private: struct Argument { Argument(const QString &value = QString()) : value(value) { } QString value; bool isFilePath = false; bool shouldQuote = true; }; bool m_isRawProgram; QString m_program; std::vector m_arguments; }; } // namespace Internal } // namespace qbs #endif // QBS_SHELLUTILS_H qbs-src-1.13.1/src/lib/corelib/tools/stlutils.h000066400000000000000000000073001347155106100213220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_STLUTILS_H #define QBS_STLUTILS_H #include #include namespace qbs { namespace Internal { template C sorted(const C &container) { C result = container; std::sort(std::begin(result), std::end(result)); return result; } template bool contains(const C &container, const typename C::value_type &v) { const auto &end = container.cend(); return std::find(container.cbegin(), end, v) != end; } template bool containsKey(const C &container, const typename C::key_type &v) { const auto &end = container.cend(); return container.find(v) != end; } template bool removeOne(C &container, const typename C::value_type &v) { auto end = std::end(container); auto it = std::find(std::begin(container), end, v); if (it == end) return false; container.erase(it); return true; } template void removeAll(C &container, const typename C::value_type &v) { container.erase(std::remove(std::begin(container), std::end(container), v), std::end(container)); } template bool any_of(const Container &container, const UnaryPredicate &predicate) { return std::any_of(std::begin(container), std::end(container), predicate); } template bool none_of(const Container &container, const UnaryPredicate &predicate) { return std::none_of(std::begin(container), std::end(container), predicate); } template C &operator<<(C &container, const typename C::value_type &v) { container.push_back(v); return container; } template C &operator<<(C &container, const C &other) { container.insert(container.end(), other.cbegin(), other.cend()); return container; } } // namespace Internal } // namespace qbs #endif // QBS_STLUTILS_H qbs-src-1.13.1/src/lib/corelib/tools/stringconstants.h000066400000000000000000000276521347155106100227160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_STRINGCONSTANTS_H #define QBS_STRINGCONSTANTS_H #include #define QBS_CONSTANT(type, name, value) \ static const type &name() { \ static const type var{QLatin1String(value)}; \ return var; \ } #define QBS_STRING_CONSTANT(name, value) QBS_CONSTANT(QString, name, value) #define QBS_STRINGLIST_CONSTANT(name, value) QBS_CONSTANT(QStringList, name, value) namespace qbs { namespace Internal { class StringConstants { public: static const QString &cppModule() { return cpp(); } static const QString &qbsModule() { return qbs(); } QBS_STRING_CONSTANT(aggregateProperty, "aggregate") QBS_STRING_CONSTANT(additionalProductTypesProperty, "additionalProductTypes") QBS_STRING_CONSTANT(allowedValuesProperty, "allowedValues") QBS_STRING_CONSTANT(alwaysUpdatedProperty, "alwaysUpdated") QBS_STRING_CONSTANT(alwaysRunProperty, "alwaysRun") QBS_STRING_CONSTANT(artifactsProperty, "artifacts") QBS_STRING_CONSTANT(auxiliaryInputsProperty, "auxiliaryInputs") QBS_STRING_CONSTANT(baseNameProperty, "baseName") QBS_STRING_CONSTANT(baseProfileProperty, "baseProfile") QBS_STRING_CONSTANT(buildDirectoryProperty, "buildDirectory") QBS_STRING_CONSTANT(builtByDefaultProperty, "builtByDefault") QBS_STRING_CONSTANT(classNameProperty, "className") QBS_STRING_CONSTANT(completeBaseNameProperty, "completeBaseName") QBS_STRING_CONSTANT(conditionProperty, "condition") QBS_STRING_CONSTANT(configurationNameProperty, "configurationName") QBS_STRING_CONSTANT(configureProperty, "configure") QBS_STRING_CONSTANT(consoleApplicationProperty, "consoleApplication") QBS_STRING_CONSTANT(dependenciesProperty, "dependencies") QBS_STRING_CONSTANT(descriptionProperty, "description") QBS_STRING_CONSTANT(destinationDirProperty, "destinationDirectory") QBS_STRING_CONSTANT(excludeFilesProperty, "excludeFiles") QBS_STRING_CONSTANT(excludedAuxiliaryInputsProperty, "excludedAuxiliaryInputs") QBS_STRING_CONSTANT(excludedInputsProperty, "excludedInputs") static const QString &explicitlyDependsOnProperty() { return explicitlyDependsOn(); } static const QString &explicitlyDependsOnFromDependenciesProperty() { return explicitlyDependsOnFromDependencies(); } QBS_STRING_CONSTANT(enableFallbackProperty, "enableFallback") static const QString &fileNameProperty() { return fileName(); } static const QString &filePathProperty() { return filePath(); } static const QString &filePathVar() { return filePath(); } QBS_STRING_CONSTANT(fileTagsFilterProperty, "fileTagsFilter") QBS_STRING_CONSTANT(fileTagsProperty, "fileTags") QBS_STRING_CONSTANT(filesProperty, "files") QBS_STRING_CONSTANT(filesAreTargetsProperty, "filesAreTargets") QBS_STRING_CONSTANT(foundProperty, "found") QBS_STRING_CONSTANT(imports, "imports") static const QString &importsDir() { return imports(); } static const QString &importsProperty() { return imports(); } QBS_STRING_CONSTANT(inheritPropertiesProperty, "inheritProperties") static const QString &inputsProperty() { return inputs(); } QBS_STRING_CONSTANT(inputsFromDependenciesProperty, "inputsFromDependencies") static const QString &installProperty() { return install(); } QBS_STRING_CONSTANT(installRootProperty, "installRoot") QBS_STRING_CONSTANT(installPrefixProperty, "installPrefix") QBS_STRING_CONSTANT(installDirProperty, "installDir") QBS_STRING_CONSTANT(installSourceBaseProperty, "installSourceBase") QBS_STRING_CONSTANT(jobCountProperty, "jobCount") QBS_STRING_CONSTANT(jobPoolProperty, "jobPool") QBS_STRING_CONSTANT(lengthProperty, "length") QBS_STRING_CONSTANT(limitToSubProjectProperty, "limitToSubProject") QBS_STRING_CONSTANT(minimumQbsVersionProperty, "minimumQbsVersion") QBS_STRING_CONSTANT(moduleNameProperty, "moduleName") QBS_STRING_CONSTANT(moduleProviders, "moduleProviders") QBS_STRING_CONSTANT(multiplexByQbsPropertiesProperty, "multiplexByQbsProperties") QBS_STRING_CONSTANT(multiplexConfigurationIdProperty, "multiplexConfigurationId") QBS_STRING_CONSTANT(multiplexConfigurationIdsProperty, "multiplexConfigurationIds") QBS_STRING_CONSTANT(multiplexProperty, "multiplex") QBS_STRING_CONSTANT(multiplexedProperty, "multiplexed") QBS_STRING_CONSTANT(multiplexedTypeProperty, "multiplexedType") QBS_STRING_CONSTANT(nameProperty, "name") QBS_STRING_CONSTANT(outputArtifactsProperty, "outputArtifacts") QBS_STRING_CONSTANT(outputFileTagsProperty, "outputFileTags") QBS_STRING_CONSTANT(overrideTagsProperty, "overrideTags") QBS_STRING_CONSTANT(overrideListPropertiesProperty, "overrideListProperties") QBS_STRING_CONSTANT(parametersProperty, "parameters") static const QString &pathProperty() { return path(); } QBS_STRING_CONSTANT(patternsProperty, "patterns") QBS_STRING_CONSTANT(prefixMappingProperty, "prefixMapping") QBS_STRING_CONSTANT(prefixProperty, "prefix") QBS_STRING_CONSTANT(prepareProperty, "prepare") QBS_STRING_CONSTANT(presentProperty, "present") QBS_STRING_CONSTANT(priorityProperty, "priority") QBS_STRING_CONSTANT(profileProperty, "profile") static const QString &profilesProperty() { return profiles(); } QBS_STRING_CONSTANT(productTypesProperty, "productTypes") QBS_STRING_CONSTANT(qbsSearchPathsProperty, "qbsSearchPaths") QBS_STRING_CONSTANT(referencesProperty, "references") QBS_STRING_CONSTANT(recursiveProperty, "recursive") QBS_STRING_CONSTANT(requiredProperty, "required") QBS_STRING_CONSTANT(requiresInputsProperty, "requiresInputs") QBS_STRING_CONSTANT(removalVersionProperty, "removalVersion") QBS_STRING_CONSTANT(scanProperty, "scan") QBS_STRING_CONSTANT(searchPathsProperty, "searchPaths") QBS_STRING_CONSTANT(setupBuildEnvironmentProperty, "setupBuildEnvironment") QBS_STRING_CONSTANT(setupRunEnvironmentProperty, "setupRunEnvironment") QBS_STRING_CONSTANT(sourceCodeProperty, "sourceCode") QBS_STRING_CONSTANT(sourceDirectoryProperty, "sourceDirectory") QBS_STRING_CONSTANT(submodulesProperty, "submodules") QBS_STRING_CONSTANT(targetNameProperty, "targetName") QBS_STRING_CONSTANT(typeProperty, "type") QBS_STRING_CONSTANT(validateProperty, "validate") QBS_STRING_CONSTANT(versionProperty, "version") QBS_STRING_CONSTANT(versionAtLeastProperty, "versionAtLeast") QBS_STRING_CONSTANT(versionBelowProperty, "versionBelow") QBS_STRING_CONSTANT(importScopeNamePropertyInternal, "_qbs_importScopeName") QBS_STRING_CONSTANT(modulePropertyInternal, "__module") QBS_STRING_CONSTANT(qbsSourceDirPropertyInternal, "_qbs_sourceDir") static const char *qbsProcEnvVarInternal() { return "_qbs_procenv"; } static const QString &projectPrefix() { return project(); } static const QString &productValue() { return product(); } QBS_STRING_CONSTANT(projectsOverridePrefix, "projects.") QBS_STRING_CONSTANT(productsOverridePrefix, "products.") QBS_STRING_CONSTANT(baseVar, "base") static const QString &explicitlyDependsOnVar() { return explicitlyDependsOn(); } QBS_STRING_CONSTANT(inputVar, "input") static const QString &inputsVar() { return inputs(); } QBS_STRING_CONSTANT(originalVar, "original") QBS_STRING_CONSTANT(outerVar, "outer") QBS_STRING_CONSTANT(outputVar, "output") QBS_STRING_CONSTANT(outputsVar, "outputs") static const QString &productVar() { return product(); } static const QString &projectVar() { return project(); } static const QString &filePathGlobalVar() { return filePath(); } static const QString &pathGlobalVar() { return path(); } static const QString &pathType() { return path(); } static const QString &fileInfoFileName() { return fileName(); } static const QString &fileInfoPath() { return path(); } static const QString &androidInstallCommand() { return install(); } static const QString &simctlInstallCommand() { return install(); } static const QString &profilesSettingsKey() { return profiles(); } QBS_STRING_CONSTANT(emptyArrayValue, "[]") QBS_STRING_CONSTANT(falseValue, "false") QBS_STRING_CONSTANT(trueValue, "true") QBS_STRING_CONSTANT(undefinedValue, "undefined") QBS_STRING_CONSTANT(javaScriptCommandType, "JavaScriptCommand") QBS_STRING_CONSTANT(commandType, "Command") QBS_STRING_CONSTANT(pathEnvVar, "PATH") QBS_STRING_CONSTANT(dot, ".") QBS_STRING_CONSTANT(dotDot, "..") QBS_STRING_CONSTANT(slashDotDot, "/..") QBS_STRING_CONSTANT(star, "*") QBS_STRING_CONSTANT(tildeSlash, "~/") QBS_STRINGLIST_CONSTANT(qbsFileWildcards, "*.qbs") QBS_STRINGLIST_CONSTANT(jsFileWildcards, "*.js") static const QString &cppLang() { return cpp(); } QBS_STRING_CONSTANT(xcode, "xcode") QBS_STRING_CONSTANT(aarch64Arch, "aarch64") QBS_STRING_CONSTANT(amd64Arch, "amd64") QBS_STRING_CONSTANT(armArch, "arm") QBS_STRING_CONSTANT(arm64Arch, "arm64") QBS_STRING_CONSTANT(armv7Arch, "armv7") QBS_STRING_CONSTANT(i386Arch, "i386") QBS_STRING_CONSTANT(i586Arch, "i586") QBS_STRING_CONSTANT(mipsArch, "mips") QBS_STRING_CONSTANT(mips64Arch, "mips64") QBS_STRING_CONSTANT(powerPcArch, "powerpc") QBS_STRING_CONSTANT(ppcArch, "ppc") QBS_STRING_CONSTANT(ppc64Arch, "ppc64") QBS_STRING_CONSTANT(x86Arch, "x86") QBS_STRING_CONSTANT(x86_64Arch, "x86_64") QBS_STRING_CONSTANT(profilesSettingsPrefix, "profiles.") private: QBS_STRING_CONSTANT(cpp, "cpp") QBS_STRING_CONSTANT(explicitlyDependsOn, "explicitlyDependsOn") QBS_STRING_CONSTANT(explicitlyDependsOnFromDependencies, "explicitlyDependsOnFromDependencies") QBS_STRING_CONSTANT(fileName, "fileName") QBS_STRING_CONSTANT(filePath, "filePath") QBS_STRING_CONSTANT(inputs, "inputs") QBS_STRING_CONSTANT(install, "install") QBS_STRING_CONSTANT(path, "path") QBS_STRING_CONSTANT(product, "product") QBS_STRING_CONSTANT(profiles, "profiles") QBS_STRING_CONSTANT(project, "project") QBS_STRING_CONSTANT(qbs, "qbs") }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/lib/corelib/tools/stringutils.h000066400000000000000000000102221347155106100220230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_STRINGUTILS_H #define QBS_STRINGUTILS_H #include #include #include #include namespace qbs { namespace Internal { template typename C::value_type join(const C &container, const typename C::value_type &separator) { typename C::value_type out; if (!container.empty()) { auto it = container.cbegin(); auto end = container.cend(); out.append(*it++); for (; it != end; ++it) { out.append(separator); out.append(*it); } } return out; } template typename C::value_type join(const C &container, typename C::value_type::value_type separator) { typename C::value_type s; s.push_back(separator); return join(container, s); } static inline std::string trimmed(const std::string &s) { // trim from start static const auto ltrim = [](std::string &s) -> std::string & { s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); return s; }; // trim from end static const auto rtrim = [](std::string &s) -> std::string & { s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); return s; }; // trim from both ends static const auto trim = [](std::string &s) -> std::string & { return ltrim(rtrim(s)); }; std::string copy = s; return trim(copy); } static inline bool startsWith(const std::string &subject, const std::string &s) { if (s.size() <= subject.size()) return std::equal(s.begin(), s.end(), subject.begin()); return false; } static inline bool startsWith(const std::string &subject, char c) { std::string s; s.push_back(c); return startsWith(subject, s); } static inline bool endsWith(const std::string &subject, const std::string &s) { if (s.size() <= subject.size()) return std::equal(s.rbegin(), s.rend(), subject.rbegin()); return false; } static inline bool endsWith(const std::string &subject, char c) { std::string s; s.push_back(c); return endsWith(subject, s); } } // namespace Internal } // namespace qbs #ifdef Q_DECLARE_METATYPE Q_DECLARE_METATYPE(std::string) #endif #endif // QBS_STRINGUTILS_H qbs-src-1.13.1/src/lib/corelib/tools/toolchains.cpp000066400000000000000000000105351347155106100221410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "toolchains.h" #include "stringconstants.h" #include #include namespace qbs { namespace Internal { static const QString clangToolchain() { return QStringLiteral("clang"); } static const QString gccToolchain() { return QStringLiteral("gcc"); } static const QString llvmToolchain() { return QStringLiteral("llvm"); } static const QString mingwToolchain() { return QStringLiteral("mingw"); } } using namespace Internal; QStringList canonicalToolchain(const QStringList &toolchain) { static const QStringList knownToolchains { StringConstants::xcode(), clangToolchain(), llvmToolchain(), mingwToolchain(), gccToolchain(), QStringLiteral("msvc") }; // Canonicalize each toolchain in the toolchain list, // which gets us the aggregate canonicalized (unsorted) list QStringList toolchains; for (const QString &toolchainName : toolchain) toolchains << canonicalToolchain(toolchainName); toolchains.removeDuplicates(); // Find all known toolchains in the canonicalized list, // removing them from the main list as we go. QStringList usedKnownToolchains; for (int i = 0; i < toolchains.size(); ++i) { if (knownToolchains.contains(toolchains[i])) { usedKnownToolchains << toolchains[i]; toolchains.removeAt(i--); } } // Sort the list of known toolchains into their canonical order. std::sort(usedKnownToolchains.begin(), usedKnownToolchains.end(), []( const QString &a, const QString &b) { return knownToolchains.indexOf(a) < knownToolchains.indexOf(b); }); // Re-add the known toolchains to the main list (the custom ones go first). toolchains << usedKnownToolchains; // The toolchain list still needs further validation as it may contain mututally exclusive // toolchain types (for example, llvm and msvc). return toolchains; } QStringList canonicalToolchain(const QString &name) { const QString &toolchainName = name.toLower(); QStringList toolchains(toolchainName); if (toolchainName == StringConstants::xcode()) toolchains << canonicalToolchain(clangToolchain()); else if (toolchainName == clangToolchain()) toolchains << canonicalToolchain(llvmToolchain()); else if (toolchainName == llvmToolchain() || toolchainName == mingwToolchain()) { toolchains << canonicalToolchain(QStringLiteral("gcc")); } return toolchains; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/toolchains.h000066400000000000000000000042351347155106100216060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TOOLCHAINS_H #define QBS_TOOLCHAINS_H #include "qbs_export.h" #include namespace qbs { QBS_EXPORT QStringList canonicalToolchain(const QStringList &toolchain); QBS_EXPORT QStringList canonicalToolchain(const QString &toolchainName); } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/lib/corelib/tools/tools.pri000066400000000000000000000076111347155106100211470ustar00rootroot00000000000000include(../../../install_prefix.pri) INCLUDEPATH += $$PWD/../.. # for plugins QBS_SYSTEM_SETTINGS_DIR = $$(QBS_SYSTEM_SETTINGS_DIR) !isEmpty(QBS_SYSTEM_SETTINGS_DIR) { DEFINES += QBS_SYSTEM_SETTINGS_DIR=\\\"$$QBS_SYSTEM_SETTINGS_DIR\\\" } HEADERS += \ $$PWD/architectures.h \ $$PWD/buildgraphlocker.h \ $$PWD/codelocation.h \ $$PWD/commandechomode.h \ $$PWD/dynamictypecheck.h \ $$PWD/error.h \ $$PWD/executablefinder.h \ $$PWD/fileinfo.h \ $$PWD/filesaver.h \ $$PWD/filetime.h \ $$PWD/generateoptions.h \ $$PWD/id.h \ $$PWD/iosutils.h \ $$PWD/joblimits.h \ $$PWD/jsliterals.h \ $$PWD/launcherinterface.h \ $$PWD/launcherpackets.h \ $$PWD/launchersocket.h \ $$PWD/msvcinfo.h \ $$PWD/persistence.h \ $$PWD/scannerpluginmanager.h \ $$PWD/scripttools.h \ $$PWD/set.h \ $$PWD/settings.h \ $$PWD/settingsmodel.h \ $$PWD/settingsrepresentation.h \ $$PWD/pathutils.h \ $$PWD/preferences.h \ $$PWD/profile.h \ $$PWD/profiling.h \ $$PWD/processresult.h \ $$PWD/processresult_p.h \ $$PWD/processutils.h \ $$PWD/progressobserver.h \ $$PWD/projectgeneratormanager.h \ $$PWD/qbspluginmanager.h \ $$PWD/qbsprocess.h \ $$PWD/shellutils.h \ $$PWD/stlutils.h \ $$PWD/stringutils.h \ $$PWD/toolchains.h \ $$PWD/hostosinfo.h \ $$PWD/buildoptions.h \ $$PWD/installoptions.h \ $$PWD/cleanoptions.h \ $$PWD/setupprojectparameters.h \ $$PWD/weakpointer.h \ $$PWD/qbs_export.h \ $$PWD/qbsassert.h \ $$PWD/qttools.h \ $$PWD/settingscreator.h \ $$PWD/stringconstants.h \ $$PWD/version.h \ $$PWD/visualstudioversioninfo.h \ $$PWD/vsenvironmentdetector.h SOURCES += \ $$PWD/architectures.cpp \ $$PWD/buildgraphlocker.cpp \ $$PWD/codelocation.cpp \ $$PWD/commandechomode.cpp \ $$PWD/error.cpp \ $$PWD/executablefinder.cpp \ $$PWD/fileinfo.cpp \ $$PWD/filesaver.cpp \ $$PWD/filetime.cpp \ $$PWD/generateoptions.cpp \ $$PWD/id.cpp \ $$PWD/joblimits.cpp \ $$PWD/jsliterals.cpp \ $$PWD/launcherinterface.cpp \ $$PWD/launcherpackets.cpp \ $$PWD/launchersocket.cpp \ $$PWD/msvcinfo.cpp \ $$PWD/persistence.cpp \ $$PWD/scannerpluginmanager.cpp \ $$PWD/scripttools.cpp \ $$PWD/settings.cpp \ $$PWD/settingsmodel.cpp \ $$PWD/settingsrepresentation.cpp \ $$PWD/preferences.cpp \ $$PWD/processresult.cpp \ $$PWD/processutils.cpp \ $$PWD/profile.cpp \ $$PWD/profiling.cpp \ $$PWD/progressobserver.cpp \ $$PWD/projectgeneratormanager.cpp \ $$PWD/qbspluginmanager.cpp \ $$PWD/qbsprocess.cpp \ $$PWD/shellutils.cpp \ $$PWD/buildoptions.cpp \ $$PWD/installoptions.cpp \ $$PWD/cleanoptions.cpp \ $$PWD/setupprojectparameters.cpp \ $$PWD/qbsassert.cpp \ $$PWD/qttools.cpp \ $$PWD/settingscreator.cpp \ $$PWD/toolchains.cpp \ $$PWD/version.cpp \ $$PWD/visualstudioversioninfo.cpp \ $$PWD/vsenvironmentdetector.cpp osx { HEADERS += $$PWD/applecodesignutils.h SOURCES += $$PWD/applecodesignutils.cpp LIBS += -framework Security } !qbs_no_dev_install { tools_headers.files = \ $$PWD/architectures.h \ $$PWD/buildoptions.h \ $$PWD/cleanoptions.h \ $$PWD/codelocation.h \ $$PWD/commandechomode.h \ $$PWD/error.h \ $$PWD/generateoptions.h \ $$PWD/installoptions.h \ $$PWD/joblimits.h \ $$PWD/preferences.h \ $$PWD/processresult.h \ $$PWD/profile.h \ $$PWD/projectgeneratormanager.h \ $$PWD/qbs_export.h \ $$PWD/settings.h \ $$PWD/settingsmodel.h \ $$PWD/settingsrepresentation.h \ $$PWD/setupprojectparameters.h \ $$PWD/toolchains.h \ $$PWD/version.h tools_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/tools INSTALLS += tools_headers } qbs-src-1.13.1/src/lib/corelib/tools/version.cpp000066400000000000000000000111201347155106100214520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "version.h" #include #include namespace qbs { Version::Version(int major, int minor, int patch, int buildNr) : m_major(major), m_minor(minor), m_patch(patch), m_build(buildNr) { } int Version::majorVersion() const { return m_major; } void Version::setMajorVersion(int major) { m_major = major; } int Version::minorVersion() const { return m_minor; } void Version::setMinorVersion(int minor) { m_minor = minor; } int Version::patchLevel() const { return m_patch; } void Version::setPatchLevel(int patch) { m_patch = patch; } int Version::buildNumber() const { return m_build; } void Version::setBuildNumber(int nr) { m_build = nr; } Version Version::fromString(const QString &versionString, bool buildNumberAllowed) { QString pattern = QStringLiteral("(\\d+)"); // At least one number. for (int i = 0; i < 2; ++i) pattern += QStringLiteral("(?:\\.(\\d+))?"); // Followed by a dot and a number up to two times. if (buildNumberAllowed) pattern += QStringLiteral("(?:[-.](\\d+))?"); // And possibly a dash or dot followed by the build number. QRegExp rex(pattern); if (!rex.exactMatch(versionString)) return Version{}; const int majorNr = rex.cap(1).toInt(); const int minorNr = rex.captureCount() >= 2 ? rex.cap(2).toInt() : 0; const int patchNr = rex.captureCount() >= 3 ? rex.cap(3).toInt() : 0; const int buildNr = rex.captureCount() >= 4 ? rex.cap(4).toInt() : 0; return Version{majorNr, minorNr, patchNr, buildNr}; } QString Version::toString() const { QString s; if (m_build) s.sprintf("%d.%d.%d-%d", m_major, m_minor, m_patch, m_build); else s.sprintf("%d.%d.%d", m_major, m_minor, m_patch); return s; } int compare(const Version &lhs, const Version &rhs) { if (lhs.majorVersion() < rhs.majorVersion()) return -1; if (lhs.majorVersion() > rhs.majorVersion()) return 1; if (lhs.minorVersion() < rhs.minorVersion()) return -1; if (lhs.minorVersion() > rhs.minorVersion()) return 1; if (lhs.patchLevel() < rhs.patchLevel()) return -1; if (lhs.patchLevel() > rhs.patchLevel()) return 1; if (lhs.buildNumber() < rhs.buildNumber()) return -1; if (lhs.buildNumber() > rhs.buildNumber()) return 1; return 0; } VersionRange::VersionRange(const Version &minVersion, const Version &maxVersion) : minimum(minVersion), maximum(maxVersion) { } VersionRange &VersionRange::narrowDown(const VersionRange &other) { if (other.minimum > minimum) minimum = other.minimum; if (other.maximum.isValid() && other.maximum < maximum) maximum = other.maximum; return *this; } } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/version.h000066400000000000000000000072001347155106100211230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_VERSION_H #define QBS_VERSION_H #include "qbs_export.h" #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { class QBS_EXPORT Version { public: explicit Version(int majorVersion = 0, int minorVersion = 0, int patchLevel = 0, int buildNr = 0); bool isValid() const { return m_major || m_minor || m_patch || m_build; } int majorVersion() const; void setMajorVersion(int majorVersion); int minorVersion() const; void setMinorVersion(int minorVersion); int patchLevel() const; void setPatchLevel(int patchLevel); int buildNumber() const; void setBuildNumber(int nr); static Version fromString(const QString &versionString, bool buildNumberAllowed = false); QString toString() const; private: int m_major; int m_minor; int m_patch; int m_build; }; class VersionRange { public: VersionRange() = default; VersionRange(const Version &minVersion, const Version &maxVersion); Version minimum; Version maximum; // exclusive VersionRange &narrowDown(const VersionRange &other); }; QBS_EXPORT int compare(const Version &lhs, const Version &rhs); inline bool operator==(const Version &lhs, const Version &rhs) { return compare(lhs, rhs) == 0; } inline bool operator!=(const Version &lhs, const Version &rhs) { return !operator==(lhs, rhs); } inline bool operator<(const Version &lhs, const Version &rhs) { return compare(lhs, rhs) < 0; } inline bool operator>(const Version &lhs, const Version &rhs) { return compare(lhs, rhs) > 0; } inline bool operator<=(const Version &lhs, const Version &rhs) { return !operator>(lhs, rhs); } inline bool operator>=(const Version &lhs, const Version &rhs) { return !operator<(lhs, rhs); } } // namespace qbs #endif // QBS_VERSION_H qbs-src-1.13.1/src/lib/corelib/tools/visualstudioversioninfo.cpp000066400000000000000000000132171347155106100250130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "visualstudioversioninfo.h" #include #include #include namespace qbs { namespace Internal { VisualStudioVersionInfo::VisualStudioVersionInfo() { } VisualStudioVersionInfo::VisualStudioVersionInfo(const Version &version) : m_version(version) { QBS_CHECK(version.minorVersion() == 0 || version == Version(7, 1) || version.majorVersion() >= 15); } std::set VisualStudioVersionInfo::knownVersions() { static const std::set known = { Version(15), Version(14), Version(12), Version(11), Version(10), Version(9), Version(8), Version(7, 1), Version(7), Version(6) }; return known; } bool VisualStudioVersionInfo::operator<(const VisualStudioVersionInfo &other) const { return m_version < other.m_version; } bool VisualStudioVersionInfo::operator==(const VisualStudioVersionInfo &other) const { return m_version == other.m_version; } bool VisualStudioVersionInfo::usesMsBuild() const { return m_version.majorVersion() >= 10; } bool VisualStudioVersionInfo::usesVcBuild() const { return m_version.majorVersion() <= 9; } bool VisualStudioVersionInfo::usesSolutions() const { return m_version.majorVersion() >= 7; } Version VisualStudioVersionInfo::version() const { return m_version; } int VisualStudioVersionInfo::marketingVersion() const { switch (m_version.majorVersion()) { case 6: return 6; case 7: switch (m_version.minorVersion()) { case 0: return 2002; case 1: return 2003; default: Q_UNREACHABLE(); } break; case 8: return 2005; case 9: return 2008; case 10: return 2010; case 11: return 2012; case 12: return 2013; case 14: return 2015; case 15: return 2017; default: qWarning() << QStringLiteral("unrecognized Visual Studio version: ") << m_version.toString(); return 0; } } QString VisualStudioVersionInfo::solutionVersion() const { // Visual Studio 2012 finally stabilized the solution version if (m_version >= Version(11)) return QStringLiteral("12.00"); if (m_version >= Version(8)) return QStringLiteral("%1.00").arg(m_version.majorVersion() + 1); if (m_version >= Version(7, 1)) return QStringLiteral("8.00"); if (m_version >= Version(7)) return QStringLiteral("7.00"); // these versions do not use solution files // Visual Studio 6 uses .dsw files which are format version 6.00 but these are different Q_ASSERT(!usesSolutions()); Q_UNREACHABLE(); } QString VisualStudioVersionInfo::toolsVersion() const { // "https://msdn.microsoft.com/en-us/library/bb383796.aspx" // Starting in Visual Studio 2013, the MSBuild Toolset version is the same as the Visual Studio // version number"... again if (m_version >= Version(12)) return QStringLiteral("%1.0").arg(m_version.majorVersion()); if (m_version >= Version(10)) return QStringLiteral("4.0"); // pre-MSBuild return QStringLiteral("%1,00").arg(m_version.majorVersion()); } QString VisualStudioVersionInfo::platformToolsetVersion() const { static std::pair table[] = { {16, QStringLiteral("v142")}, // VS 2019 {15, QStringLiteral("v141")} // VS 2017 }; for (auto p : table) { if (p.first == m_version.majorVersion()) return p.second; } return QStringLiteral("v%1").arg(m_version.majorVersion() * 10); } quint32 qHash(const VisualStudioVersionInfo &info) { return qHash(info.version().toString()); } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/visualstudioversioninfo.h000066400000000000000000000055431347155106100244630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_VISUALSTUDIOVERSIONINFO_H #define QBS_VISUALSTUDIOVERSIONINFO_H #include "qbs_export.h" #include #include #include namespace qbs { namespace Internal { class QBS_EXPORT VisualStudioVersionInfo { public: VisualStudioVersionInfo(); VisualStudioVersionInfo(const Version &version); static std::set knownVersions(); bool operator<(const VisualStudioVersionInfo &other) const; bool operator==(const VisualStudioVersionInfo &other) const; bool usesMsBuild() const; bool usesVcBuild() const; bool usesSolutions() const; Version version() const; int marketingVersion() const; QString solutionVersion() const; QString toolsVersion() const; QString platformToolsetVersion() const; private: Version m_version; }; quint32 qHash(const VisualStudioVersionInfo &info); } // namespace Internal } // namespace qbs #endif // QBS_VISUALSTUDIOVERSIONINFO_H qbs-src-1.13.1/src/lib/corelib/tools/vsenvironmentdetector.cpp000066400000000000000000000226541347155106100244520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "vsenvironmentdetector.h" #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN #include #include #endif namespace qbs { namespace Internal { static QString windowsSystem32Path() { #ifdef Q_OS_WIN wchar_t str[UNICODE_STRING_MAX_CHARS]; if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, 0, str))) return QString::fromUtf16(reinterpret_cast(str)); #endif return {}; } VsEnvironmentDetector::VsEnvironmentDetector() : m_windowsSystemDirPath(windowsSystem32Path()) { } bool VsEnvironmentDetector::start(MSVC *msvc) { return start(std::vector{ msvc }); } bool VsEnvironmentDetector::start(std::vector msvcs) { std::sort(msvcs.begin(), msvcs.end(), [] (const MSVC *a, const MSVC *b) -> bool { return a->vcInstallPath < b->vcInstallPath; }); std::vector compatibleMSVCs; QString lastVcInstallPath; bool someMSVCDetected = false; for (MSVC * const msvc : msvcs) { if (lastVcInstallPath != msvc->vcInstallPath) { lastVcInstallPath = msvc->vcInstallPath; if (!compatibleMSVCs.empty()) { if (startDetection(compatibleMSVCs)) someMSVCDetected = true; compatibleMSVCs.clear(); } } compatibleMSVCs.push_back(msvc); } if (startDetection(compatibleMSVCs)) someMSVCDetected = true; return someMSVCDetected; } QString VsEnvironmentDetector::findVcVarsAllBat(const MSVC &msvc, std::vector &searchedPaths) const { // ### We can only rely on MSVC.vcInstallPath being set // when this is called from utilitiesextension.cpp :-( // If we knew the vsInstallPath at this point we could just use that // instead of searching for vcvarsall.bat candidates. QDir dir(msvc.vcInstallPath); for (;;) { if (!dir.cdUp()) return {}; if (dir.dirName() == QLatin1String("VC")) break; } const QString vcvarsallbat = QStringLiteral("vcvarsall.bat"); QString path = vcvarsallbat; QString fullPath = dir.absoluteFilePath(path); if (dir.exists(path)) return fullPath; else searchedPaths.push_back(fullPath); path = QStringLiteral("Auxiliary/Build/") + vcvarsallbat; fullPath = dir.absoluteFilePath(path); if (dir.exists(path)) return fullPath; else searchedPaths.push_back(fullPath); return {}; } bool VsEnvironmentDetector::startDetection(const std::vector &compatibleMSVCs) { std::vector searchedPaths; const QString vcvarsallbat = findVcVarsAllBat(**compatibleMSVCs.begin(), searchedPaths); if (vcvarsallbat.isEmpty()) { if (!searchedPaths.empty()) { m_errorString = Tr::tr( "Cannot find 'vcvarsall.bat' at any of the following locations:\n\t") + join(searchedPaths, QStringLiteral("\n\t")); } else { m_errorString = Tr::tr("Cannot find 'vcvarsall.bat'."); } return false; } QTemporaryFile tmpFile(QDir::tempPath() + QLatin1Char('/') + QStringLiteral("XXXXXX.bat")); if (!tmpFile.open()) { m_errorString = Tr::tr("Cannot open temporary file '%1' for writing.").arg( tmpFile.fileName()); return false; } writeBatchFile(&tmpFile, vcvarsallbat, compatibleMSVCs); tmpFile.flush(); QProcess process; static const QString shellFilePath = QStringLiteral("cmd.exe"); process.start(shellFilePath, QStringList() << QStringLiteral("/C") << tmpFile.fileName()); if (!process.waitForStarted()) { m_errorString = Tr::tr("Failed to start '%1'.").arg(shellFilePath); return false; } process.waitForFinished(-1); if (process.exitStatus() != QProcess::NormalExit) { m_errorString = Tr::tr("Process '%1' did not exit normally.").arg(shellFilePath); return false; } if (process.exitCode() != 0) { m_errorString = Tr::tr("Failed to detect Visual Studio environment."); return false; } parseBatOutput(process.readAllStandardOutput(), compatibleMSVCs); return true; } static void batClearVars(QTextStream &s, const QStringList &varnames) { for (const QString &varname : varnames) s << "set " << varname << '=' << endl; } static void batPrintVars(QTextStream &s, const QStringList &varnames) { for (const QString &varname : varnames) s << "echo " << varname << "=%" << varname << '%' << endl; } static QString vcArchitecture(const MSVC *msvc) { QString vcArch = msvc->architecture; if (msvc->architecture == StringConstants::armv7Arch()) vcArch = StringConstants::armArch(); if (msvc->architecture == StringConstants::x86_64Arch()) vcArch = StringConstants::amd64Arch(); for (const QString &hostPrefix : QStringList({StringConstants::x86Arch(), QStringLiteral("amd64_"), QStringLiteral("x86_")})) { if (QFile::exists(msvc->clPathForArchitecture(hostPrefix + vcArch))) { vcArch.prepend(hostPrefix); break; } } return vcArch; } void VsEnvironmentDetector::writeBatchFile(QIODevice *device, const QString &vcvarsallbat, const std::vector &msvcs) const { const QStringList varnames = QStringList() << StringConstants::pathEnvVar() << QStringLiteral("INCLUDE") << QStringLiteral("LIB") << QStringLiteral("WindowsSdkDir") << QStringLiteral("WindowsSDKVersion") << QStringLiteral("VSINSTALLDIR"); QTextStream s(device); s << "@echo off" << endl; for (const MSVC *msvc : msvcs) { s << "echo --" << msvc->architecture << "--" << endl << "setlocal" << endl; batClearVars(s, varnames); s << "set PATH=" << m_windowsSystemDirPath << endl; // vcvarsall.bat needs tools from here s << "call \"" << vcvarsallbat << "\" " << vcArchitecture(msvc) << " || exit /b 1" << endl; batPrintVars(s, varnames); s << "endlocal" << endl; } } void VsEnvironmentDetector::parseBatOutput(const QByteArray &output, std::vector msvcs) { QString arch; QProcessEnvironment *targetEnv = nullptr; for (QByteArray line : output.split('\n')) { line = line.trimmed(); if (line.isEmpty()) continue; if (line.startsWith("--") && line.endsWith("--")) { line.remove(0, 2); line.chop(2); arch = QString::fromLocal8Bit(line); targetEnv = &msvcs.front()->environment; msvcs.erase(msvcs.begin()); } else { int idx = line.indexOf('='); if (idx < 0) continue; QBS_CHECK(targetEnv); const QString name = QString::fromLocal8Bit(line.left(idx)); QString value = QString::fromLocal8Bit(line.mid(idx + 1)); if (name.compare(StringConstants::pathEnvVar(), Qt::CaseInsensitive) == 0) value.remove(m_windowsSystemDirPath); if (value.endsWith(QLatin1Char(';'))) value.chop(1); if (value.endsWith(QLatin1Char('\\'))) value.chop(1); targetEnv->insert(name, value); } } } } // namespace Internal } // namespace qbs qbs-src-1.13.1/src/lib/corelib/tools/vsenvironmentdetector.h000066400000000000000000000054701347155106100241140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_VSENVIRONMENTDETECTOR_H #define QBS_VSENVIRONMENTDETECTOR_H #include "qbs_export.h" #include "msvcinfo.h" #include QT_BEGIN_NAMESPACE class QIODevice; QT_END_NAMESPACE namespace qbs { namespace Internal { class MSVC; class QBS_EXPORT VsEnvironmentDetector { public: VsEnvironmentDetector(); bool start(MSVC *msvc); bool start(std::vector msvcs); QString errorString() const { return m_errorString; } private: QString findVcVarsAllBat(const MSVC &msvc, std::vector &searchedPaths) const; bool startDetection(const std::vector &compatibleMSVCs); void writeBatchFile(QIODevice *device, const QString &vcvarsallbat, const std::vector &msvcs) const; void parseBatOutput(const QByteArray &output, std::vector msvcs); const QString m_windowsSystemDirPath; QString m_errorString; }; } // namespace Internal } // namespace qbs #endif // QBS_VSENVIRONMENTDETECTOR_H qbs-src-1.13.1/src/lib/corelib/tools/weakpointer.h000066400000000000000000000066771347155106100220070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_WEAKPOINTER_H #define QBS_WEAKPOINTER_H #include namespace qbs { namespace Internal { template class WeakPointer : public std::weak_ptr { public: WeakPointer() : std::weak_ptr() {} WeakPointer(const std::shared_ptr &sharedPointer) : std::weak_ptr(sharedPointer) {} template WeakPointer(const std::shared_ptr &sp) : std::weak_ptr(sp) { } T *get() const { auto p = std::weak_ptr::lock(); return p.get(); } operator bool() const { return !std::weak_ptr::expired(); } bool operator!() const { return std::weak_ptr::expired(); } operator T*() const { return checkedData(); } T *operator->() const { return checkedData(); } T operator*() const { return *checkedData(); } private: T *checkedData() const { T * const d = get(); Q_ASSERT(d); // Calling code is not expecting this situation. return d; } }; template bool operator==(const WeakPointer &a, const WeakPointer &b) { return a.get() == b.get(); } template bool operator!=(const WeakPointer &a, const WeakPointer &b) { return a.get() != b.get(); } template bool operator==(const WeakPointer &a, const std::shared_ptr &b) { return a.lock() == b; } template bool operator!=(const WeakPointer &a, const std::shared_ptr &b) { return a.lock() != b; } } // namespace Internal } // namespace qbs #endif // QBS_WEAKPOINTER_H qbs-src-1.13.1/src/lib/corelib/use_corelib.pri000066400000000000000000000021731347155106100211400ustar00rootroot00000000000000include(../../../qbs_version.pri) include(../../library_dirname.pri) isEmpty(QBSLIBDIR) { QBSLIBDIR = $$OUT_PWD/../../../$${QBS_LIBRARY_DIRNAME} } unix { LIBS += -L$$QBSLIBDIR -lqbscore } isEmpty(QBS_RPATH): QBS_RPATH = ../$$QBS_LIBRARY_DIRNAME !qbs_disable_rpath { linux-*: QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,\$\$ORIGIN/$${QBS_RPATH}\' macx: QMAKE_LFLAGS += -Wl,-rpath,@loader_path/$${QBS_RPATH} } !CONFIG(static, static|shared) { QBSCORELIBSUFFIX = $$QBS_VERSION_MAJ } win32 { CONFIG(debug, debug|release) { QBSCORELIB = qbscored$$QBSCORELIBSUFFIX } CONFIG(release, debug|release) { QBSCORELIB = qbscore$$QBSCORELIBSUFFIX } msvc { LIBS += /LIBPATH:$$QBSLIBDIR QBSCORELIB = $${QBSCORELIB}.lib LIBS += Shell32.lib } else { LIBS += -L$${QBSLIBDIR} QBSCORELIB = lib$${QBSCORELIB} } LIBS += $$QBSCORELIB } INCLUDEPATH += \ $$PWD CONFIG(static, static|shared) { DEFINES += QBS_STATIC_LIB } qbs_enable_project_file_updates:DEFINES += QBS_ENABLE_PROJECT_FILE_UPDATES qbs_enable_unit_tests:DEFINES += QBS_ENABLE_UNIT_TESTS qbs-src-1.13.1/src/lib/corelib/use_installed_corelib.pri000066400000000000000000000015621347155106100232000ustar00rootroot00000000000000include(qbs_version.pri) QBSLIBDIR=$${PWD}/../../lib unix { LIBS += -L$$QBSLIBDIR -lqbscore } !qbs_disable_rpath:unix:QMAKE_LFLAGS += -Wl,-rpath,$${QBSLIBDIR} !CONFIG(static, static|shared) { QBSCORELIBSUFFIX = $$QBS_VERSION_MAJ } win32 { CONFIG(debug, debug|release) { QBSCORELIB = qbscored$$QBSCORELIBSUFFIX } CONFIG(release, debug|release) { QBSCORELIB = qbscore$$QBSCORELIBSUFFIX } msvc { LIBS += /LIBPATH:$$QBSLIBDIR QBSCORELIB = $${QBSCORELIB}.lib LIBS += Shell32.lib } else { LIBS += -L$${QBSLIBDIR} QBSCORELIB = lib$${QBSCORELIB} } LIBS += $$QBSCORELIB } INCLUDEPATH += $${PWD} CONFIG(static, static|shared) { DEFINES += QBS_STATIC_LIB } qbs_enable_project_file_updates:DEFINES += QBS_ENABLE_PROJECT_FILE_UPDATES qbs_enable_unit_tests:DEFINES += QBS_ENABLE_UNIT_TESTS qbs-src-1.13.1/src/lib/library.pri000066400000000000000000000027131347155106100166720ustar00rootroot00000000000000include(../library_dirname.pri) include(../install_prefix.pri) TEMPLATE = lib QT = core !isEmpty(QBS_DLLDESTDIR):DLLDESTDIR = $${QBS_DLLDESTDIR} else:DLLDESTDIR = ../../../bin !isEmpty(QBS_DESTDIR):DESTDIR = $${QBS_DESTDIR} else:DESTDIR = ../../../$${QBS_LIBRARY_DIRNAME} CONFIG(static, static|shared) { DEFINES += QBS_STATIC_LIB } else { DEFINES += QBS_LIBRARY } DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_PROCESS_COMBINED_ARGUMENT_START qbs_enable_unit_tests:DEFINES += QBS_ENABLE_UNIT_TESTS INCLUDEPATH += $${PWD}/../ contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols win32:CONFIG(debug, debug|release):TARGET = $${TARGET}d CONFIG(debug, debug|release):DEFINES += QT_STRICT_ITERATORS CONFIG += c++14 CONFIG += create_prl qbs_disable_rpath { osx:QMAKE_LFLAGS_SONAME = -Wl,-install_name,$$QBS_INSTALL_PREFIX/$$QBS_LIBRARY_DIRNAME/ } else { osx:QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/ } include(../../qbs_version.pri) VERSION = $${QBS_VERSION} linux { # Turn off absurd qmake's soname "logic" and directly add the linker flag. QMAKE_LFLAGS_SONAME = QMAKE_LFLAGS = -Wl,-soname=lib$${TARGET}.so.$${QBS_VERSION_MAJ}.$${QBS_VERSION_MIN} } win32 { dlltarget.path = $${QBS_INSTALL_PREFIX}/bin INSTALLS += dlltarget } !win32|!qbs_no_dev_install { !isEmpty(QBS_LIB_INSTALL_DIR): \ target.path = $${QBS_LIB_INSTALL_DIR} else: \ target.path = $${QBS_INSTALL_PREFIX}/$${QBS_LIBRARY_DIRNAME} INSTALLS += target } qbs-src-1.13.1/src/lib/libs.qbs000066400000000000000000000001701347155106100161450ustar00rootroot00000000000000import qbs Project { references: [ "corelib/corelib.qbs", "scriptengine/scriptengine.qbs", ] } qbs-src-1.13.1/src/lib/scriptengine/000077500000000000000000000000001347155106100172015ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/scriptengine/include/000077500000000000000000000000001347155106100206245ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/scriptengine/include/QtScript/000077500000000000000000000000001347155106100223755ustar00rootroot00000000000000qbs-src-1.13.1/src/lib/scriptengine/include/QtScript/qtscriptglobal.h000066400000000000000000000037521347155106100256070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_QTSCRIPTGLOBAL_H #define QBS_QTSCRIPTGLOBAL_H #define Q_SCRIPT_EXPORT #define Q_SCRIPTTOOLS_EXPORT #endif // include guard qbs-src-1.13.1/src/lib/scriptengine/scriptengine.pro000066400000000000000000000053761347155106100224300ustar00rootroot00000000000000TARGET = qbsscriptengine include(../library.pri) INSTALLS = QT = core-private DEFINES += QT_BUILD_SCRIPT_LIB DEFINES += JSC=QTJSC jscyyparse=qtjscyyparse jscyylex=qtjscyylex jscyyerror=qtjscyyerror WTF=QTWTF DEFINES += QT_NO_USING_NAMESPACE CONFIG += building-libs CONFIG += staticlib GENERATED_SOURCES_DIR = generated CONFIG += QTDIR_build include(../../shared/qtscript/src/3rdparty/javascriptcore/WebKit.pri) # Disable a few warnings on Windows. # These are in addition to the ones disabled in WebKit.pri msvc: QMAKE_CXXFLAGS += -wd4396 -wd4099 else: QMAKE_CXXFLAGS += -Wno-deprecated # We cannot afford -O0 for QtScript even in debug builds. QMAKE_CXXFLAGS_DEBUG += -O2 darwin { DEFINES += ENABLE_JSC_MULTIPLE_THREADS=0 contains(QT_CONFIG, coreservices) { LIBS_PRIVATE += -framework CoreServices } else { LIBS_PRIVATE += -framework CoreFoundation } } win32 { LIBS += -lwinmm } # Suppress 'LEAK' messages (see QTBUG-18201) DEFINES += LOG_DISABLED=1 JAVASCRIPTCORE_JIT = no include(../../shared/qtscript/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri) # This line copied from WebCore.pro DEFINES += WTF_USE_JAVASCRIPTCORE_BINDINGS=1 WTF_CHANGES=1 CONFIG(release, debug|release): DEFINES += NDEBUG # Avoid JSC C API functions being exported. DEFINES += JS_NO_EXPORT !build_pass { qtPrepareTool(QMAKE_SYNCQT, syncqt, , system) QMAKE_SYNCQT += \ -minimal -version $$[QT_VERSION] \ -outdir $$system_quote($$system_path($$OUT_PWD)) \ $$system_quote($$system_path($$clean_path($$PWD/../../shared/qtscript))) !system($$QMAKE_SYNCQT): error("Failed to execute syncqt for the bundled QtScript module.") } INCLUDEPATH += \ $$PWD/include \ $$OUT_PWD/include \ $$OUT_PWD/include/QtScript/$$[QT_VERSION]/QtScript \ $$PWD/../../shared/qtscript/src/script \ $$PWD/../../shared/qtscript/src/script/api include(../../shared/qtscript/src/script/api/api.pri) include(../../shared/qtscript/src/script/parser/parser.pri) BRIDGESRCDIR = ../../shared/qtscript/src/script/bridge SOURCES += \ $$BRIDGESRCDIR/qscriptactivationobject.cpp \ $$BRIDGESRCDIR/qscriptclassobject.cpp \ $$BRIDGESRCDIR/qscriptfunction.cpp \ $$BRIDGESRCDIR/qscriptglobalobject.cpp \ $$BRIDGESRCDIR/qscriptobject.cpp \ $$BRIDGESRCDIR/qscriptqobject.cpp \ $$BRIDGESRCDIR/qscriptstaticscopeobject.cpp \ $$BRIDGESRCDIR/qscriptvariant.cpp HEADERS += \ $$BRIDGESRCDIR/qscriptactivationobject_p.h \ $$BRIDGESRCDIR/qscriptclassobject_p.h \ $$BRIDGESRCDIR/qscriptfunction_p.h \ $$BRIDGESRCDIR/qscriptglobalobject_p.h \ $$BRIDGESRCDIR/qscriptobject_p.h \ $$BRIDGESRCDIR/qscriptqobject_p.h \ $$BRIDGESRCDIR/qscriptstaticscopeobject_p.h \ $$BRIDGESRCDIR/qscriptvariant_p.h qbs-src-1.13.1/src/lib/scriptengine/scriptengine.qbs000066400000000000000000000417341347155106100224130ustar00rootroot00000000000000import qbs import qbs.File import qbs.FileInfo import qbs.Process Project { QbsLibrary { condition: qbsbuildconfig.useBundledQtScript || !Qt.script.present Depends { name: "Qt.script" condition: !qbsbuildconfig.useBundledQtScript required: false } Depends { name: "QtScriptFwdHeaders" } Depends { name: "cpp" } Depends { name: "Qt"; submodules: ["core-private"] } type: ["staticlibrary"] name: "qbsscriptengine" generatePkgConfigFile: false generateQbsModule: false property bool useSystemMalloc: !qbs.targetOS.contains("macos") && !qbs.targetOS.contains("unix") property string qtscriptPath: "../../shared/qtscript/src/" cpp.includePaths: { var result = base.concat( ".", "include" ); var jscBaseDir = qtscriptPath + "3rdparty/javascriptcore"; result.push(jscBaseDir); jscBaseDir += "/JavaScriptCore"; result.push(jscBaseDir); var jscSubDirs = [ "assembler", "bytecode", "bytecompiler", "debugger", "interpreter", "jit", "parser", "pcre", "profiler", "runtime", "wrec", "wtf", "wtf/unicode", "yarr", "API", "ForwardingHeaders", "generated"]; result = result.concat(jscSubDirs.map(function(s) { return jscBaseDir + '/' + s; })); result.push(qtscriptPath + "script"); result.push(qtscriptPath + "script/api"); result.push(qtscriptPath + "script/parser"); result = result.concat(QtScriptFwdHeaders.publicIncludePaths, QtScriptFwdHeaders.privateIncludePaths); return result; } cpp.defines: { var result = base.concat([ "QT_BUILD_SCRIPT_LIB", "QT_NO_USING_NAMESPACE", "JSC=QTJSC", "jscyyparse=qtjscyyparse", "jscyylex=qtjscyylex", "jscyyerror=qtjscyyerror", "WTF=QTWTF", "LOG_DISABLED=1", "WTF_USE_JAVASCRIPTCORE_BINDINGS=1", "WTF_CHANGES=1", "JS_NO_EXPORT"]); if (qbs.buildVariant != "debug") result.push("NDEBUG"); if (qbs.targetOS.contains("macos")) result.push("ENABLE_JSC_MULTIPLE_THREADS=0"); // JavaScriptCore result.push("BUILDING_QT__", "BUILDING_JavaScriptCore", "BUILDING_WTF", "ENABLE_JIT=0", "ENABLE_YARR_JIT=0", "ENABLE_YARR=0"); if (qbs.targetOS.contains("windows")) { // Prevent definition of min, max macros in windows.h result.push("NOMINMAX"); // Enables rand_s result.push("_CRT_RAND_S"); } // WebKit result.push("WTF_USE_ACCELERATED_COMPOSITING"); if (useSystemMalloc) result.push("USE_SYSTEM_MALLOC"); return result; } cpp.cxxFlags: { var result = base; if (qbs.toolchain.contains("gcc")) { result.push("-fno-strict-aliasing", "-Wall", "-Wreturn-type", "-Wcast-align", "-Wchar-subscripts", "-Wformat-security", "-Wreturn-type", "-Wno-unused-parameter", "-Wno-sign-compare", "-Wno-switch", "-Wno-switch-enum", "-Wundef", "-Wmissing-noreturn", "-Winit-self", "-Wno-deprecated", "-Wno-suggest-attribute=noreturn", "-Wno-nonnull-compare"); } else if (qbs.toolchain.contains("msvc")) { result.push("-wd4291", "-wd4344", "-wd4396", "-wd4503", "-wd4800", "-wd4819", "-wd4996"); } if (qbs.targetOS.contains("unix")) result.push("-pthread"); return result; } cpp.warningLevel: "none" cpp.optimization: "fast" // We cannot afford -O0 for QtScript even in debug builds. Properties { condition: qbs.targetOS.contains("unix") cpp.dynamicLibraries: base.concat(["pthread"]) } Group { name: "pcre" prefix: qtscriptPath + "3rdparty/javascriptcore/JavaScriptCore/pcre/" files: [ "pcre_compile.cpp", "pcre_exec.cpp", "pcre_tables.cpp", "pcre_ucp_searchfuncs.cpp", "pcre_xclass.cpp", ] } Group { name: "system malloc replacement" prefix: qtscriptPath + "3rdparty/javascriptcore/JavaScriptCore/" condition: !useSystemMalloc files: [ "wtf/TCSystemAlloc.cpp", ] } Group { name: "JavaScriptCore" prefix: qtscriptPath + "3rdparty/javascriptcore/JavaScriptCore/" files: [ "API/JSBase.cpp", "API/JSCallbackConstructor.cpp", "API/JSCallbackFunction.cpp", "API/JSCallbackObject.cpp", "API/JSClassRef.cpp", "API/JSContextRef.cpp", "API/JSObjectRef.cpp", "API/JSStringRef.cpp", "API/JSValueRef.cpp", "API/OpaqueJSString.cpp", "assembler/ARMAssembler.cpp", "assembler/MacroAssemblerARM.cpp", "bytecode/CodeBlock.cpp", "bytecode/JumpTable.cpp", "bytecode/Opcode.cpp", "bytecode/SamplingTool.cpp", "bytecode/StructureStubInfo.cpp", "bytecompiler/BytecodeGenerator.cpp", "bytecompiler/NodesCodegen.cpp", "debugger/DebuggerActivation.cpp", "debugger/DebuggerCallFrame.cpp", "debugger/Debugger.cpp", "generated/Grammar.cpp", "interpreter/CallFrame.cpp", "interpreter/Interpreter.cpp", "interpreter/RegisterFile.cpp", "parser/Lexer.cpp", "parser/Nodes.cpp", "parser/ParserArena.cpp", "parser/Parser.cpp", "profiler/Profile.cpp", "profiler/ProfileGenerator.cpp", "profiler/ProfileNode.cpp", "profiler/Profiler.cpp", "runtime/ArgList.cpp", "runtime/Arguments.cpp", "runtime/ArrayConstructor.cpp", "runtime/ArrayPrototype.cpp", "runtime/BooleanConstructor.cpp", "runtime/BooleanObject.cpp", "runtime/BooleanPrototype.cpp", "runtime/CallData.cpp", "runtime/Collector.cpp", "runtime/CommonIdentifiers.cpp", "runtime/Completion.cpp", "runtime/ConstructData.cpp", "runtime/DateConstructor.cpp", "runtime/DateConversion.cpp", "runtime/DateInstance.cpp", "runtime/DatePrototype.cpp", "runtime/ErrorConstructor.cpp", "runtime/Error.cpp", "runtime/ErrorInstance.cpp", "runtime/ErrorPrototype.cpp", "runtime/ExceptionHelpers.cpp", "runtime/Executable.cpp", "runtime/FunctionConstructor.cpp", "runtime/FunctionPrototype.cpp", "runtime/GetterSetter.cpp", "runtime/GlobalEvalFunction.cpp", "runtime/Identifier.cpp", "runtime/InitializeThreading.cpp", "runtime/InternalFunction.cpp", "runtime/JSActivation.cpp", "runtime/JSAPIValueWrapper.cpp", "runtime/JSArray.cpp", "runtime/JSByteArray.cpp", "runtime/JSCell.cpp", "runtime/JSFunction.cpp", "runtime/JSGlobalData.cpp", "runtime/JSGlobalObject.cpp", "runtime/JSGlobalObjectFunctions.cpp", "runtime/JSImmediate.cpp", "runtime/JSLock.cpp", "runtime/JSNotAnObject.cpp", "runtime/JSNumberCell.cpp", "runtime/JSObject.cpp", "runtime/JSONObject.cpp", "runtime/JSPropertyNameIterator.cpp", "runtime/JSStaticScopeObject.cpp", "runtime/JSString.cpp", "runtime/JSValue.cpp", "runtime/JSVariableObject.cpp", "runtime/JSWrapperObject.cpp", "runtime/LiteralParser.cpp", "runtime/Lookup.cpp", "runtime/MarkStackPosix.cpp", "runtime/MarkStackSymbian.cpp", "runtime/MarkStackWin.cpp", "runtime/MarkStack.cpp", "runtime/MathObject.cpp", "runtime/NativeErrorConstructor.cpp", "runtime/NativeErrorPrototype.cpp", "runtime/NumberConstructor.cpp", "runtime/NumberObject.cpp", "runtime/NumberPrototype.cpp", "runtime/ObjectConstructor.cpp", "runtime/ObjectPrototype.cpp", "runtime/Operations.cpp", "runtime/PropertyDescriptor.cpp", "runtime/PropertyNameArray.cpp", "runtime/PropertySlot.cpp", "runtime/PrototypeFunction.cpp", "runtime/RegExpConstructor.cpp", "runtime/RegExp.cpp", "runtime/RegExpObject.cpp", "runtime/RegExpPrototype.cpp", "runtime/ScopeChain.cpp", "runtime/SmallStrings.cpp", "runtime/StringConstructor.cpp", "runtime/StringObject.cpp", "runtime/StringPrototype.cpp", "runtime/StructureChain.cpp", "runtime/Structure.cpp", "runtime/TimeoutChecker.cpp", "runtime/UString.cpp", "runtime/UStringImpl.cpp", "wtf/Assertions.cpp", "wtf/ByteArray.cpp", "wtf/CurrentTime.cpp", "wtf/DateMath.cpp", "wtf/dtoa.cpp", "wtf/FastMalloc.cpp", "wtf/HashTable.cpp", "wtf/MainThread.cpp", "wtf/qt/MainThreadQt.cpp", "wtf/qt/ThreadingQt.cpp", "wtf/RandomNumber.cpp", "wtf/RefCountedLeakCounter.cpp", "wtf/ThreadingNone.cpp", "wtf/Threading.cpp", "wtf/TypeTraits.cpp", "wtf/unicode/CollatorDefault.cpp", "wtf/unicode/icu/CollatorICU.cpp", "wtf/unicode/UTF8.cpp", ] } Group { name: "api" prefix: qtscriptPath + "script/api/" files: [ "qscriptable.cpp", "qscriptable.h", "qscriptable_p.h", "qscriptclass.cpp", "qscriptclass.h", "qscriptclasspropertyiterator.cpp", "qscriptclasspropertyiterator.h", "qscriptcontext.cpp", "qscriptcontext.h", "qscriptcontextinfo.cpp", "qscriptcontextinfo.h", "qscriptcontext_p.h", "qscriptengineagent.cpp", "qscriptengineagent.h", "qscriptengineagent_p.h", "qscriptengine.cpp", "qscriptengine.h", "qscriptengine_p.h", "qscriptextensioninterface.h", "qscriptextensionplugin.cpp", "qscriptextensionplugin.h", "qscriptprogram.cpp", "qscriptprogram.h", "qscriptprogram_p.h", "qscriptstring.cpp", "qscriptstring.h", "qscriptstring_p.h", "qscriptvalue.cpp", "qscriptvalue.h", "qscriptvalueiterator.cpp", "qscriptvalueiterator.h", "qscriptvalue_p.h", "qtscriptglobal.h", ] } Group { name: "bridge" prefix: qtscriptPath + "script/bridge/" files: [ "qscriptactivationobject.cpp", "qscriptactivationobject_p.h", "qscriptclassobject.cpp", "qscriptclassobject_p.h", "qscriptfunction.cpp", "qscriptfunction_p.h", "qscriptglobalobject.cpp", "qscriptglobalobject_p.h", "qscriptobject.cpp", "qscriptobject_p.h", "qscriptqobject.cpp", "qscriptqobject_p.h", "qscriptstaticscopeobject.cpp", "qscriptstaticscopeobject_p.h", "qscriptvariant.cpp", "qscriptvariant_p.h", ] } Group { name: "parser" prefix: qtscriptPath + "script/parser/" files: [ "qscriptast.cpp", "qscriptastfwd_p.h", "qscriptast_p.h", "qscriptastvisitor.cpp", "qscriptastvisitor_p.h", "qscriptgrammar.cpp", "qscriptgrammar_p.h", "qscriptlexer.cpp", "qscriptlexer_p.h", "qscriptsyntaxchecker.cpp", "qscriptsyntaxchecker_p.h", ] } Export { Depends { name: "QtScriptFwdHeaders" } Depends { name: "cpp" } property stringList includePaths: [product.sourceDirectory + "/include"] .concat(QtScriptFwdHeaders.publicIncludePaths) Properties { condition: qbs.targetOS.contains("unix") cpp.dynamicLibraries: base.concat(["pthread"]) } Properties { condition: qbs.targetOS.contains("windows") cpp.dynamicLibraries: base.concat(["winmm"]) } } } Product { type: ["hpp"] name: "QtScriptFwdHeaders" Depends { name: "Qt.core" } Group { files: [ "../../shared/qtscript/src/script/api/*.h" ] fileTags: ["qtscriptheader"] } Rule { multiplex: true inputs: ["qtscriptheader"] Artifact { filePath: "include/QtScript/qscriptengine.h" fileTags: ["hpp"] } prepare: { var syncQtPath = FileInfo.joinPaths(product.Qt.core.binPath, "syncqt.pl"); if (!File.exists(syncQtPath)) { // syncqt.pl is not in Qt's bin path. We might have a developer build. // As we don't provide QT_HOST_BINS/src in our Qt modules we must // kindly ask qmake. var qmake = FileInfo.joinPaths(product.Qt.core.binPath, "qmake" + product.cpp.executableSuffix); var p = new Process(); if (p.exec(qmake, ["-query", "QT_HOST_BINS/src"]) !== 0) throw new Error("Error while querying qmake."); syncQtPath = FileInfo.joinPaths(p.readStdOut().replace(/\r?\n/, ''), "syncqt.pl"); } var qtScriptSrcPath = FileInfo.cleanPath( FileInfo.path(inputs["qtscriptheader"][0].filePath) + "/../../.."); console.info("qtScriptSrcPath: " + qtScriptSrcPath); var cmd = new Command("perl", [ syncQtPath, "-minimal", "-version", product.Qt.core.version, "-outdir", FileInfo.cleanPath( FileInfo.path(output.filePath) + "/../.."), qtScriptSrcPath ]); cmd.description = "Create forwarding headers for the bundled QtScript module."; return cmd; } } Export { Depends { name: "Qt.core" } property stringList publicIncludePaths: [ FileInfo.joinPaths(product.buildDirectory, "include") ] property stringList privateIncludePaths: [ FileInfo.joinPaths(product.buildDirectory, "include", "QtScript", Qt.core.version, "QtScript") ] } } } qbs-src-1.13.1/src/lib/scriptengine/use_scriptengine.pri000066400000000000000000000004751347155106100232710ustar00rootroot00000000000000!qbs_do_not_link_bundled_qtscript { include(../../library_dirname.pri) isEmpty(QBSLIBDIR) { QBSLIBDIR = $$shadowed($$PWD/../../../$${QBS_LIBRARY_DIRNAME}) } LIBS += -L$$QBSLIBDIR -lqbsscriptengine$$qtPlatformTargetSuffix() } INCLUDEPATH += \ $$PWD/include \ $$shadowed($$PWD/include) qbs-src-1.13.1/src/libexec/000077500000000000000000000000001347155106100153545ustar00rootroot00000000000000qbs-src-1.13.1/src/libexec/libexec.pri000066400000000000000000000005421347155106100175040ustar00rootroot00000000000000include(../install_prefix.pri) win32:LIBEXEC_BASE_DIR=bin else:LIBEXEC_BASE_DIR=libexec/qbs !isEmpty(QBS_LIBEXEC_DESTDIR):DESTDIR=$${QBS_LIBEXEC_DESTDIR} else:DESTDIR=../../../$$LIBEXEC_BASE_DIR !isEmpty(QBS_LIBEXEC_INSTALL_DIR):target.path = $${QBS_LIBEXEC_INSTALL_DIR} else:target.path = $${QBS_INSTALL_PREFIX}/$$LIBEXEC_BASE_DIR INSTALLS += target qbs-src-1.13.1/src/libexec/libexec.pro000066400000000000000000000000631347155106100175100ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS += qbs_processlauncher qbs-src-1.13.1/src/libexec/libexec.qbs000066400000000000000000000001471347155106100175000ustar00rootroot00000000000000import qbs Project { references: [ "qbs_processlauncher/qbs_processlauncher.qbs", ] } qbs-src-1.13.1/src/libexec/qbs_processlauncher/000077500000000000000000000000001347155106100214215ustar00rootroot00000000000000qbs-src-1.13.1/src/libexec/qbs_processlauncher/launcherlogging.cpp000066400000000000000000000037461347155106100253070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "launcherlogging.h" namespace qbs { namespace Internal { Q_LOGGING_CATEGORY(launcherLog, "qbs.launcher", QtWarningMsg) } } qbs-src-1.13.1/src/libexec/qbs_processlauncher/launcherlogging.h000066400000000000000000000045011347155106100247420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LAUCHERLOGGING_H #define QBS_LAUCHERLOGGING_H #include #include namespace qbs { namespace Internal { Q_DECLARE_LOGGING_CATEGORY(launcherLog) template void logDebug(const T &msg) { qCDebug(launcherLog) << msg; } template void logWarn(const T &msg) { qCWarning(launcherLog) << msg; } template void logError(const T &msg) { qCCritical(launcherLog) << msg; } } } #endif // Include guard qbs-src-1.13.1/src/libexec/qbs_processlauncher/launchersockethandler.cpp000066400000000000000000000226631347155106100265060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "launchersockethandler.h" #include "launcherlogging.h" #include #include #include #include namespace qbs { namespace Internal { class Process : public QProcess { Q_OBJECT public: Process(quintptr token, QObject *parent = nullptr) : QProcess(parent), m_token(token), m_stopTimer(new QTimer(this)) { m_stopTimer->setSingleShot(true); connect(m_stopTimer, &QTimer::timeout, this, &Process::cancel); } void cancel() { switch (m_stopState) { case StopState::Inactive: m_stopState = StopState::Terminating; m_stopTimer->start(3000); terminate(); break; case StopState::Terminating: m_stopState = StopState::Killing; m_stopTimer->start(3000); kill(); break; case StopState::Killing: m_stopState = StopState::Inactive; emit failedToStop(); break; } } void stopStopProcedure() { m_stopState = StopState::Inactive; m_stopTimer->stop(); } quintptr token() const { return m_token; } signals: void failedToStop(); private: const quintptr m_token; QTimer * const m_stopTimer; enum class StopState { Inactive, Terminating, Killing } m_stopState = StopState::Inactive; }; LauncherSocketHandler::LauncherSocketHandler(const QString &serverPath, QObject *parent) : QObject(parent), m_serverPath(serverPath), m_socket(new QLocalSocket(this)) { m_packetParser.setDevice(m_socket); } LauncherSocketHandler::~LauncherSocketHandler() { m_socket->disconnect(); if (m_socket->state() != QLocalSocket::UnconnectedState) { logWarn("socket handler destroyed while connection was active"); m_socket->close(); } for (auto it = m_processes.cbegin(); it != m_processes.cend(); ++it) it.value()->disconnect(); } void LauncherSocketHandler::start() { connect(m_socket, &QLocalSocket::disconnected, this, &LauncherSocketHandler::handleSocketClosed); connect(m_socket, &QLocalSocket::readyRead, this, &LauncherSocketHandler::handleSocketData); connect(m_socket, static_cast(&QLocalSocket::error), this, &LauncherSocketHandler::handleSocketError); m_socket->connectToServer(m_serverPath); } void LauncherSocketHandler::handleSocketData() { try { if (!m_packetParser.parse()) return; } catch (const PacketParser::InvalidPacketSizeException &e) { logWarn(QStringLiteral("Internal protocol error: invalid packet size %1.") .arg(e.size)); return; } switch (m_packetParser.type()) { case LauncherPacketType::StartProcess: handleStartPacket(); break; case LauncherPacketType::StopProcess: handleStopPacket(); break; case LauncherPacketType::Shutdown: handleShutdownPacket(); return; default: logWarn(QStringLiteral("Internal protocol error: invalid packet type %1.") .arg(static_cast(m_packetParser.type()))); return; } handleSocketData(); } void LauncherSocketHandler::handleSocketError() { if (m_socket->error() != QLocalSocket::PeerClosedError) { logError(QStringLiteral("socket error: %1").arg(m_socket->errorString())); m_socket->disconnect(); qApp->quit(); } } void LauncherSocketHandler::handleSocketClosed() { for (auto it = m_processes.cbegin(); it != m_processes.cend(); ++it) { if (it.value()->state() != QProcess::NotRunning) { logWarn("client closed connection while process still running"); break; } } m_socket->disconnect(); qApp->quit(); } void LauncherSocketHandler::handleProcessError() { Process * proc = senderProcess(); if (proc->error() != QProcess::FailedToStart) return; proc->stopStopProcedure(); ProcessErrorPacket packet(proc->token()); packet.error = proc->error(); packet.errorString = proc->errorString(); sendPacket(packet); } void LauncherSocketHandler::handleProcessFinished() { Process * proc = senderProcess(); proc->stopStopProcedure(); ProcessFinishedPacket packet(proc->token()); packet.error = proc->error(); packet.errorString = proc->errorString(); packet.exitCode = proc->exitCode(); packet.exitStatus = proc->exitStatus(); packet.stdErr = proc->readAllStandardError(); packet.stdOut = proc->readAllStandardOutput(); sendPacket(packet); } void LauncherSocketHandler::handleStopFailure() { // Process did not react to a kill signal. Rare, but not unheard of. // Forget about the associated Process object and report process exit to the client. Process * proc = senderProcess(); proc->disconnect(); m_processes.remove(proc->token()); ProcessFinishedPacket packet(proc->token()); packet.error = QProcess::Crashed; packet.exitCode = -1; packet.exitStatus = QProcess::CrashExit; packet.stdErr = proc->readAllStandardError(); packet.stdOut = proc->readAllStandardOutput(); sendPacket(packet); } void LauncherSocketHandler::handleStartPacket() { Process *& process = m_processes[m_packetParser.token()]; if (!process) process = setupProcess(m_packetParser.token()); if (process->state() != QProcess::NotRunning) { logWarn("got start request while process was running"); return; } const auto packet = LauncherPacket::extractPacket( m_packetParser.token(), m_packetParser.packetData()); process->setEnvironment(packet.env); process->setWorkingDirectory(packet.workingDir); process->start(packet.command, packet.arguments); } void LauncherSocketHandler::handleStopPacket() { Process * const process = m_processes.value(m_packetParser.token()); if (!process) { logWarn("got stop request for unknown process"); return; } if (process->state() == QProcess::NotRunning) { // This can happen if the process finishes on its own at about the same time the client // sends the request. logDebug("got stop request when process was not running"); return; } process->cancel(); } void LauncherSocketHandler::handleShutdownPacket() { logDebug("got shutdown request, closing down"); for (auto it = m_processes.cbegin(); it != m_processes.cend(); ++it) { it.value()->disconnect(); if (it.value()->state() != QProcess::NotRunning) { logWarn("got shutdown request while process was running"); it.value()->terminate(); } } m_socket->disconnect(); qApp->quit(); } void LauncherSocketHandler::sendPacket(const LauncherPacket &packet) { m_socket->write(packet.serialize()); } Process *LauncherSocketHandler::setupProcess(quintptr token) { const auto p = new Process(token, this); connect(p, static_cast(&QProcess::error), this, &LauncherSocketHandler::handleProcessError); connect(p, static_cast(&QProcess::finished), this, &LauncherSocketHandler::handleProcessFinished); connect(p, &Process::failedToStop, this, &LauncherSocketHandler::handleStopFailure); return p; } Process *LauncherSocketHandler::senderProcess() const { return static_cast(sender()); } } // namespace Internal } // namespace qbs #include qbs-src-1.13.1/src/libexec/qbs_processlauncher/launchersockethandler.h000066400000000000000000000057301347155106100261470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_LAUNCHERSOCKETHANDLER_H #define QBS_LAUNCHERSOCKETHANDLER_H #include #include #include #include QT_BEGIN_NAMESPACE class QLocalSocket; QT_END_NAMESPACE namespace qbs { namespace Internal { class Process; class LauncherSocketHandler : public QObject { Q_OBJECT public: explicit LauncherSocketHandler(const QString &socketPath, QObject *parent = nullptr); ~LauncherSocketHandler(); void start(); private: void handleSocketData(); void handleSocketError(); void handleSocketClosed(); void handleProcessError(); void handleProcessFinished(); void handleStopFailure(); void handleStartPacket(); void handleStopPacket(); void handleShutdownPacket(); void sendPacket(const LauncherPacket &packet); Process *setupProcess(quintptr token); Process *senderProcess() const; const QString m_serverPath; QLocalSocket * const m_socket; PacketParser m_packetParser; QHash m_processes; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.13.1/src/libexec/qbs_processlauncher/processlauncher-main.cpp000066400000000000000000000052001347155106100262440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "launcherlogging.h" #include "launchersockethandler.h" #include #include #ifdef Q_OS_WIN #include BOOL WINAPI consoleCtrlHandler(DWORD) { // Ignore Ctrl-C / Ctrl-Break. Qbs will tell us to exit gracefully. return TRUE; } #endif int main(int argc, char *argv[]) { #ifdef Q_OS_WIN SetConsoleCtrlHandler(consoleCtrlHandler, TRUE); #endif QCoreApplication app(argc, argv); if (app.arguments().size() != 2) { qbs::Internal::logError("Need exactly one argument (path to socket)"); return 1; } qbs::Internal::LauncherSocketHandler launcher(app.arguments().constLast()); QTimer::singleShot(0, &launcher, &qbs::Internal::LauncherSocketHandler::start); return app.exec(); } qbs-src-1.13.1/src/libexec/qbs_processlauncher/qbs_processlauncher.pro000066400000000000000000000006551347155106100262160ustar00rootroot00000000000000include(../libexec.pri) TARGET = qbs_processlauncher CONFIG += console c++14 CONFIG -= app_bundle QT = core network TOOLS_DIR = $$PWD/../../lib/corelib/tools INCLUDEPATH += $$TOOLS_DIR HEADERS += \ launcherlogging.h \ launchersockethandler.h \ $$TOOLS_DIR/launcherpackets.h SOURCES += \ launcherlogging.cpp \ launchersockethandler.cpp \ processlauncher-main.cpp \ $$TOOLS_DIR/launcherpackets.cpp qbs-src-1.13.1/src/libexec/qbs_processlauncher/qbs_processlauncher.qbs000066400000000000000000000017401347155106100261770ustar00rootroot00000000000000import qbs import qbs.FileInfo QbsProduct { type: "application" name: "qbs_processlauncher" consoleApplication: true Depends { name: "Qt.network" } cpp.includePaths: base.concat(pathToProtocolSources) files: [ "launcherlogging.cpp", "launcherlogging.h", "launchersockethandler.cpp", "launchersockethandler.h", "processlauncher-main.cpp", ] property string pathToProtocolSources: sourceDirectory + "/../../lib/corelib/tools" Group { name: "protocol sources" prefix: pathToProtocolSources + '/' files: [ "launcherpackets.cpp", "launcherpackets.h", ] } Group { fileTagsFilter: product.type .concat(qbs.buildVariant === "debug" ? ["debuginfo_app"] : []) qbs.install: true qbs.installDir: targetInstallDir qbs.installSourceBase: buildDirectory } targetInstallDir: qbsbuildconfig.libexecInstallDir } qbs-src-1.13.1/src/library_dirname.pri000066400000000000000000000000671347155106100176230ustar00rootroot00000000000000isEmpty(QBS_LIBRARY_DIRNAME):QBS_LIBRARY_DIRNAME = lib qbs-src-1.13.1/src/packages/000077500000000000000000000000001347155106100155175ustar00rootroot00000000000000qbs-src-1.13.1/src/packages/archive/000077500000000000000000000000001347155106100171405ustar00rootroot00000000000000qbs-src-1.13.1/src/packages/archive/archive.qbs000066400000000000000000000154761347155106100213050ustar00rootroot00000000000000import qbs import qbs.FileInfo import qbs.ModUtils import qbs.Process import qbs.TextFile QbsProduct { Depends { name: "qbs_processlauncher" } Depends { name: "qbscore" } Depends { name: "bundledqt" } Depends { name: "qbs documentation" } Depends { name: "qbs resources" } Depends { name: "qbs man page"; condition: qbs.targetOS.contains("unix") } Depends { productTypes: ["qbsapplication", "qbsplugin"] } Depends { name: "archiver" } property stringList windeployqtArgs: [ "--no-svg", "--no-system-d3d-compiler", "--no-angle", "--no-compiler-runtime", "--no-opengl-sw", ] // List of path prefixes to be excluded from the generated archive property stringList excludedPathPrefixes: [ "bin/icudt", "bin/icuin", "bin/icuuc", "bin/iconengines/", "bin/imageformats/", ] property bool includeTopLevelDir: false condition: qbs.targetOS.containsAny(["windows", "macos"]) builtByDefault: false name: "qbs archive" type: ["archiver.archive"] targetName: "qbs-" + qbs.targetOS[0] + "-" + qbs.architecture + "-" + qbsversion.version destinationDirectory: project.buildDirectory archiver.type: qbs.targetOS.contains("windows") ? "zip" : "tar" Properties { condition: includeTopLevelDir archiver.workingDirectory: qbs.installRoot + "/.." } archiver.workingDirectory: qbs.installRoot Group { name: "Licenses" prefix: "../../../" files: [ "LGPL_EXCEPTION.txt", "LICENSE.LGPLv3", "LICENSE.LGPLv21", "LICENSE.GPL3-EXCEPT", ] qbs.install: true qbs.installDir: "share/doc/qbs" } Rule { condition: qbs.targetOS.contains("windows") multiplex: true inputsFromDependencies: ["installable"] Artifact { filePath: "windeployqt.json" fileTags: ["dependencies.json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "windeployqt"; cmd.outputFilePath = output.filePath; cmd.installRoot = product.moduleProperty("qbs", "installRoot"); cmd.windeployqtArgs = product.windeployqtArgs; cmd.binaryFilePaths = inputs.installable.filter(function (artifact) { return artifact.fileTags.contains("application") || artifact.fileTags.contains("dynamiclibrary"); }).map(function(a) { return ModUtils.artifactInstalledFilePath(a); }); cmd.binaryFilePaths.sort(function(a1, a2) { if (a1.contains("qbs.exe")) return -1; if (a2.contains("qbs.exe")) return 1; return 0; }); cmd.extendedDescription = FileInfo.joinPaths( product.moduleProperty("Qt.core", "binPath"), "windeployqt") + ".exe " + ["--json"].concat(cmd.windeployqtArgs).concat(cmd.binaryFilePaths).join(" "); cmd.sourceCode = function () { var out; var process; try { process = new Process(); process.exec(FileInfo.joinPaths(product.moduleProperty("Qt.core", "binPath"), "windeployqt"), ["--json"] .concat(windeployqtArgs).concat(binaryFilePaths), true); out = process.readStdOut(); } finally { if (process) process.close(); } var tf; try { tf = new TextFile(outputFilePath, TextFile.WriteOnly); tf.write(out); } finally { if (tf) tf.close(); } }; return [cmd]; } } Rule { multiplex: true inputs: ["dependencies.json", "installable"] inputsFromDependencies: ["installable"] Artifact { filePath: "list.txt" fileTags: ["archiver.input-list"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.excludedPathPrefixes = product.excludedPathPrefixes; cmd.inputFilePaths = inputs.installable.map(function(a) { return ModUtils.artifactInstalledFilePath(a); }); cmd.outputFilePath = output.filePath; cmd.baseDirectory = product.moduleProperty("archiver", "workingDirectory"); cmd.sourceCode = function() { var tf; for (var i = 0; i < (inputs["dependencies.json"] || []).length; ++i) { try { tf = new TextFile(inputs["dependencies.json"][i].filePath, TextFile.ReadOnly); inputFilePaths = inputFilePaths.concat( JSON.parse(tf.readAll())["files"].map(function (obj) { return FileInfo.joinPaths( FileInfo.fromWindowsSeparators(obj.target), FileInfo.fileName( FileInfo.fromWindowsSeparators( obj.source))); })); } finally { if (tf) tf.close(); } } inputFilePaths.sort(); try { tf = new TextFile(outputFilePath, TextFile.ReadWrite); for (var i = 0; i < inputFilePaths.length; ++i) { var ignore = false; var relativePath = FileInfo.relativePath(baseDirectory, inputFilePaths[i]); for (var j = 0; j < excludedPathPrefixes.length; ++j) { if (relativePath.startsWith(excludedPathPrefixes[j])) { ignore = true; break; } } // QTBUG-65916 var fileName = FileInfo.fileName(inputFilePaths[i]); if (fileName.endsWith(".qm") && !fileName.startsWith("qt_")) ignore = true; if (!ignore) tf.writeLine(relativePath); } } finally { if (tf) tf.close(); } }; return [cmd]; } } } qbs-src-1.13.1/src/packages/chocolatey/000077500000000000000000000000001347155106100176515ustar00rootroot00000000000000qbs-src-1.13.1/src/packages/chocolatey/chocolatey.qbs000066400000000000000000000116731347155106100225220ustar00rootroot00000000000000import qbs import qbs.Environment import qbs.File import qbs.FileInfo import qbs.Probes import qbs.TextFile import qbs.Utilities import qbs.Xml Product { Depends { name: "qbsversion" } Probes.BinaryProbe { id: choco condition: qbs.targetOS.contains("windows") names: ["choco"] platformPaths: { // TODO: Change to platformSearchPaths in qbs 1.15 var chocolateyInstall = Environment.getEnv("ChocolateyInstall"); if (chocolateyInstall) return [FileInfo.joinPaths(chocolateyInstall, "bin")]; else return [FileInfo.joinPaths(Environment.getEnv("PROGRAMDATA"), "chocolatey", "bin")]; } } condition: choco.found builtByDefault: false name: "qbs chocolatey" type: ["chocolatey.nupkg"] targetName: "qbs." + qbsversion.version destinationDirectory: project.buildDirectory property string chocoFilePath: choco.filePath Group { files: ["qbs.nuspec"] fileTags: ["chocolatey.nuspec"] } Group { files: ["chocolateyinstall.ps1"] fileTags: ["powershell.source"] } Group { files: ["../../../changelogs/*"] fileTags: ["changelog"] } Rule { inputs: ["chocolatey.nuspec", "powershell.source", "changelog"] multiplex: true Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".nupkg") fileTags: ["chocolatey.nupkg"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.qbsVersion = product.qbsversion.version; cmd.powershellFilePath = inputs["powershell.source"][0].filePath; cmd.nuspecFileName = inputs["chocolatey.nuspec"][0].fileName; cmd.nuspecFilePath = inputs["chocolatey.nuspec"][0].filePath; cmd.chocoBuildDirectory = FileInfo.joinPaths(product.buildDirectory, "choco"); cmd.chocoOutDirectory = FileInfo.path(outputs["chocolatey.nupkg"][0].filePath); cmd.changelogs = (inputs["changelog"] || []).map(function (a) { return { filePath: a.filePath, version: a.fileName.replace(/^changes-([0-9](\.[0-9]+)*)(\.md)?$/, "$1") }; }).sort(function(a, b) { return Utilities.versionCompare(b.version, a.version); }); cmd.sourceCode = function () { File.makePath(chocoBuildDirectory); File.makePath(FileInfo.joinPaths(chocoBuildDirectory, "tools")); var tf = new TextFile(FileInfo.joinPaths( chocoBuildDirectory, "tools", "chocolateyinstall.ps1"), TextFile.WriteOnly); try { tf.writeLine("$qbsVersion = '" + qbsVersion + "'"); tf.writeLine(""); var tf2 = new TextFile(powershellFilePath, TextFile.ReadOnly); try { tf.write(tf2.readAll()); } finally { tf2.close(); } } finally { tf.close(); } var doc = new Xml.DomDocument(); doc.load(nuspecFilePath); var versionNode = doc.createElement("version"); versionNode.appendChild(doc.createTextNode(qbsVersion)); var releaseNotesNode = doc.createElement("releaseNotes"); var releaseNotesText = ""; changelogs.map(function (changelog) { releaseNotesText += "qbs " + changelog.version + "\n\n"; var tf = new TextFile(changelog.filePath, TextFile.ReadOnly); try { releaseNotesText += tf.readAll() + "\n"; } finally { tf.close(); } }); releaseNotesNode.appendChild(doc.createTextNode(releaseNotesText.trim())); var metadataNode = doc.documentElement().firstChild("metadata"); metadataNode.appendChild(versionNode); metadataNode.appendChild(releaseNotesNode); doc.save(FileInfo.joinPaths(chocoBuildDirectory, nuspecFileName)); }; var cmd2 = new Command(product.chocoFilePath, ["pack", FileInfo.joinPaths(cmd.chocoBuildDirectory, cmd.nuspecFileName), "--limitoutput", "--outputdirectory", cmd.chocoOutDirectory]); cmd2.description = "choco pack " + inputs["chocolatey.nuspec"][0].fileName; return [cmd, cmd2]; } } } qbs-src-1.13.1/src/packages/chocolatey/chocolateyinstall.ps1000066400000000000000000000015541347155106100240240ustar00rootroot00000000000000$ErrorActionPreference = 'Stop' $qbsBaseUrl = "https://download.qt.io/official_releases/qbs/$qbsVersion" $checksumType = 'md5' $checksums = @{} ForEach ($line in (New-Object Net.WebClient).DownloadString("$qbsBaseUrl/${checksumType}sums.txt").Split(` "`n", [System.StringSplitOptions]::RemoveEmptyEntries)) { $items = $line.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries) $checksums.Add($items[1], $items[0]) } $qbs32 = "qbs-windows-x86-$qbsVersion.zip" $qbs64 = "qbs-windows-x86_64-$qbsVersion.zip" Install-ChocolateyZipPackage ` -PackageName 'qbs' ` -Url "$qbsBaseUrl/$qbs32" ` -UnzipLocation "$(Split-Path -parent $MyInvocation.MyCommand.Definition)" ` -Url64bit "$qbsBaseUrl/$qbs64" ` -Checksum $checksums[$qbs32] ` -ChecksumType $checksumType ` -Checksum64 $checksums[$qbs64] ` -ChecksumType64 $checksumType qbs-src-1.13.1/src/packages/chocolatey/qbs.nuspec000066400000000000000000000026311347155106100216570ustar00rootroot00000000000000 qbs Qbs Qt Project qbs Build tool that helps simplify the build process for developing projects across multiple platforms. Qbs is a tool that helps simplify the build process for developing projects across multiple platforms. https://wiki.qt.io/Qbs https://code.qt.io/cgit/qbs/qbs.git https://code.qt.io/cgit/qbs/qbs.git https://doc.qt.io/qbs/ http://lists.qt-project.org/mailman/listinfo/qbs https://bugreports.qt.io/browse/QBS qbs qt build © 2017 The Qt Company Ltd. http://doc.qt.io/qt-5/licensing.html false https://d3hp9ud7yvwzy0.cloudfront.net/wp-content/uploads/2015/02/Qt-logo-medium.png qbs-src-1.13.1/src/packages/packages.qbs000066400000000000000000000005551347155106100200110ustar00rootroot00000000000000import qbs Project { references: [ "archive/archive.qbs", "chocolatey/chocolatey.qbs", ] // Virtual product for building all possible packagings Product { Depends { name: "qbs archive"; required: false } Depends { name: "qbs chocolatey"; required: false } name: "dist" builtByDefault: false } } qbs-src-1.13.1/src/plugins/000077500000000000000000000000001347155106100154225ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/generator/000077500000000000000000000000001347155106100174105ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/generator/clangcompilationdb/000077500000000000000000000000001347155106100232415ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/generator/clangcompilationdb/clangcompilationdb.pro000066400000000000000000000003541347155106100276160ustar00rootroot00000000000000include(../../plugins.pri) TARGET = clangcompilationdbgenerator QT = core HEADERS += \ $$PWD/clangcompilationdbgenerator.h SOURCES += \ $$PWD/clangcompilationdbgenerator.cpp \ $$PWD/clangcompilationdbgeneratorplugin.cpp qbs-src-1.13.1/src/plugins/generator/clangcompilationdb/clangcompilationdb.qbs000066400000000000000000000004031347155106100275760ustar00rootroot00000000000000import qbs import "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { name: "clangcompilationdbgenerator" files: [ "clangcompilationdbgenerator.cpp", "clangcompilationdbgenerator.h", "clangcompilationdbgeneratorplugin.cpp" ] } qbs-src-1.13.1/src/plugins/generator/clangcompilationdb/clangcompilationdbgenerator.cpp000066400000000000000000000137221347155106100315120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "clangcompilationdbgenerator.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; const QString ClangCompilationDatabaseGenerator::DefaultDatabaseFileName = QStringLiteral("compile_commands.json"); ClangCompilationDatabaseGenerator::ClangCompilationDatabaseGenerator() { } QString ClangCompilationDatabaseGenerator::generatorName() const { return QStringLiteral("clangdb"); } void ClangCompilationDatabaseGenerator::generate() { for (const Project &theProject : project().projects.values()) { QJsonArray database; const ProjectData projectData = theProject.projectData(); const QString buildDir = projectData.buildDirectory(); for (const ProductData &productData : projectData.allProducts()) { for (const GroupData &groupData : productData.groups()) { for (const ArtifactData &sourceArtifact : groupData.allSourceArtifacts()) { if (!hasValidInputFileTag(sourceArtifact.fileTags())) continue; const QString filePath = sourceArtifact.filePath(); ErrorInfo errorInfo; const RuleCommandList rules = theProject.ruleCommands(productData, filePath, QStringLiteral("obj"), &errorInfo); if (errorInfo.hasError()) throw errorInfo; for (const RuleCommand &rule : rules) { if (rule.type() != RuleCommand::ProcessCommandType) continue; database.push_back(createEntry(filePath, buildDir, rule)); } } } } writeProjectDatabase(QDir(buildDir).filePath(DefaultDatabaseFileName), database); } } // See http://clang.llvm.org/docs/JSONCompilationDatabase.html QJsonObject ClangCompilationDatabaseGenerator::createEntry(const QString &filePath, const QString &buildDir, const RuleCommand &ruleCommand) { QString workDir = ruleCommand.workingDirectory(); if (workDir.isEmpty()) workDir = buildDir; const QStringList arguments = QStringList() << ruleCommand.executable() << ruleCommand.arguments(); const QJsonObject object = { { QStringLiteral("directory"), QJsonValue(workDir) }, { QStringLiteral("arguments"), QJsonArray::fromStringList(arguments) }, { QStringLiteral("file"), QJsonValue(filePath) } }; return object; } void ClangCompilationDatabaseGenerator::writeProjectDatabase(const QString &filePath, const QJsonArray &entries) { const QJsonDocument database(entries); QFile databaseFile(filePath); if (!databaseFile.open(QFile::WriteOnly)) throw ErrorInfo(Tr::tr("Cannot open '%1' for writing: %2") .arg(filePath) .arg(databaseFile.errorString())); if (databaseFile.write(database.toJson()) == -1) throw ErrorInfo(Tr::tr("Error while writing '%1': %2") .arg(filePath) .arg(databaseFile.errorString())); } bool ClangCompilationDatabaseGenerator::hasValidInputFileTag(const QStringList &fileTags) const { static const QStringList validFileTags = { QStringLiteral("c"), QStringLiteral("cpp"), QStringLiteral("objc"), QStringLiteral("objcpp") }; for (const QString &tag : fileTags) { if (validFileTags.contains(tag)) return true; } return false; } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/clangcompilationdb/clangcompilationdbgenerator.h000066400000000000000000000051711347155106100311560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_CLANGCOMPILATIONDATABASEGENERATOR_H #define QBS_CLANGCOMPILATIONDATABASEGENERATOR_H #include namespace qbs { class SourceArtifact; class ProjectData; class ClangCompilationDatabaseGenerator : public ProjectGenerator { public: ClangCompilationDatabaseGenerator(); private: QString generatorName() const override; void generate() override; static const QString DefaultDatabaseFileName; QJsonObject createEntry(const QString &filePath, const QString &buildDir, const RuleCommand &ruleCommand); void writeProjectDatabase(const QString &filePath, const QJsonArray &entries); bool hasValidInputFileTag(const QStringList &fileTags) const; }; } // namespace qbs #endif // QBS_VISUALSTUDIOGENERATOR_H qbs-src-1.13.1/src/plugins/generator/clangcompilationdb/clangcompilationdbgeneratorplugin.cpp000066400000000000000000000050621347155106100327270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "clangcompilationdbgenerator.h" #include #include static void QbsClangDbGeneratorPluginLoad() { qbs::ProjectGeneratorManager::registerGenerator( std::make_shared()); } static void QbsClangDbGeneratorPluginUnload() { } #ifndef GENERATOR_EXPORT #if defined(WIN32) || defined(_WIN32) #define GENERATOR_EXPORT __declspec(dllexport) #else #define GENERATOR_EXPORT __attribute__((visibility("default"))) #endif #endif QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, QbsClangDbGeneratorPlugin, QbsClangDbGeneratorPluginLoad, QbsClangDbGeneratorPluginUnload) qbs-src-1.13.1/src/plugins/generator/generator.pro000066400000000000000000000001171347155106100221170ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS = clangcompilationdb makefilegenerator visualstudio qbs-src-1.13.1/src/plugins/generator/makefilegenerator/000077500000000000000000000000001347155106100230745ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/generator/makefilegenerator/makefilegenerator.cpp000066400000000000000000000412211347155106100272640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "makefilegenerator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; QString qbs::MakefileGenerator::generatorName() const { return QStringLiteral("makefile"); } static QString quote(const QString &s) { QString quoted = shellQuote(s); quoted.replace(QLatin1Char('$'), QLatin1String("$$")); // For make quoted.replace(QLatin1String("$$(SRCDIR)"), QLatin1String("$(SRCDIR)")); quoted.replace(QLatin1String("$$(BUILD_ROOT)"), QLatin1String("$(BUILD_ROOT)")); quoted.replace(QLatin1String("$$(INSTALL_ROOT)"), QLatin1String("$(INSTALL_ROOT)")); return quoted; } enum class TargetType { Product, Path }; static QString makeValidTargetName(const QString &name, TargetType targetType) { QString modifiedName = name; switch (targetType) { case TargetType::Product: { static const QRegularExpression illegalChar(QStringLiteral("[^_.0-9A-Za-z]")); modifiedName.replace(illegalChar, QStringLiteral("_")); break; } case TargetType::Path: if (HostOsInfo::isWindowsHost()) { modifiedName = QDir::toNativeSeparators(modifiedName); modifiedName = quote(modifiedName); } else { modifiedName.replace(QLatin1Char(' '), QStringLiteral("\\ ")); } } return modifiedName; } static QString makeValidTargetName(const ProductData &product) { QString name = makeValidTargetName(product.name(), TargetType::Product); if (!product.multiplexConfigurationId().isEmpty()) name.append(QLatin1Char('_')).append(product.multiplexConfigurationId()); return name; } using PrefixSpec = std::pair; static QString replacePrefix(const QString &path, const std::vector &candidates) { for (const PrefixSpec &prefixSpec : candidates) { if (path.startsWith(prefixSpec.first) && (path.size() == prefixSpec.first.size() || path.at(prefixSpec.first.size()) == QLatin1Char('/'))) { QString p = path; return p.replace(0, prefixSpec.first.size(), QLatin1String("$(") + prefixSpec.second + QLatin1Char(')')); } } return path; } static QString bruteForcePathReplace(const QString &value, const QString &srcDir, const QString &buildDir, const QString &installRoot) { QString transformedValue = value; if (!installRoot.isEmpty()) transformedValue.replace(installRoot, QStringLiteral("$(INSTALL_ROOT)")); transformedValue.replace(buildDir, QStringLiteral("$(BUILD_ROOT)")); transformedValue.replace(srcDir, QStringLiteral("$(SRCDIR)")); return transformedValue; } static QString mkdirCmdLine(const QString &dir) { if (HostOsInfo::isWindowsHost()) return QStringLiteral("if not exist %1 mkdir %1 & if not exist %1 exit 1").arg(dir); return QStringLiteral("mkdir -p ") + dir; } static QString installFileCommand() { return HostOsInfo::isWindowsHost() ? QStringLiteral("copy /Y") : QStringLiteral("install -m 644 -p"); } static QString installProgramCommand() { return HostOsInfo::isWindowsHost() ? installFileCommand() : QStringLiteral("install -m 755 -p"); } static QString removeCommand() { return HostOsInfo::isWindowsHost() ? QStringLiteral("del") : QStringLiteral("rm -f"); } void qbs::MakefileGenerator::generate() { for (const Project &theProject : project().projects.values()) { const QString makefileFilePath = theProject.projectData().buildDirectory() + QLatin1String("/Makefile"); QFile makefile(makefileFilePath); if (!makefile.open(QIODevice::WriteOnly)) { throw ErrorInfo(Tr::tr("Failed to create '%1': %2") .arg(makefileFilePath, makefile.errorString())); } QTextStream stream(&makefile); ErrorInfo error; ProjectTransformerData projectTransformerData = theProject.transformerData(&error); if (error.hasError()) throw error; stream << "# This file was generated by qbs" << "\n\n"; stream << "INSTALL_FILE = " << installFileCommand() << '\n'; stream << "INSTALL_PROGRAM = " << installProgramCommand() << '\n'; stream << "RM = " << removeCommand() << '\n'; stream << '\n'; const ProjectData projectData = theProject.projectData(); const QString srcDir = QFileInfo(projectData.location().filePath()).path(); if (srcDir.contains(QLatin1Char(' '))) { throw ErrorInfo(Tr::tr("The project directory '%1' contains space characters, which" "is not supported by this generator.").arg(srcDir)); } stream << "SRCDIR = " << QDir::toNativeSeparators(srcDir) << '\n'; const QString buildDir = projectData.buildDirectory(); if (buildDir.contains(QLatin1Char(' '))) { throw ErrorInfo(Tr::tr("The build directory '%1' contains space characters, which" "is not supported by this generator.").arg(buildDir)); } stream << "BUILD_ROOT = " << QDir::toNativeSeparators(buildDir) << '\n'; QString installRoot; const QList allInstallables = projectData.installableArtifacts(); if (!allInstallables.empty()) { installRoot = allInstallables.first().installData().installRoot(); if (installRoot.contains(QLatin1Char(' '))) { throw ErrorInfo(Tr::tr("The install root '%1' contains space characters, which" "is not supported by this generator.").arg(installRoot)); } stream << "INSTALL_ROOT = " << QDir::toNativeSeparators(installRoot) << '\n'; } stream << "\nall:\n"; const std::vector srcDirPrefixSpecs{std::make_pair(srcDir, QStringLiteral("SRCDIR"))}; const auto prefixifiedSrcDirPath = [&srcDirPrefixSpecs](const QString &path) { return replacePrefix(path, srcDirPrefixSpecs); }; const std::vector buildRootPrefixSpecs{ std::make_pair(buildDir, QStringLiteral("BUILD_ROOT"))}; const auto prefixifiedBuildDirPath = [&buildRootPrefixSpecs](const QString &path) { return replacePrefix(path, buildRootPrefixSpecs); }; const std::vector installRootPrefixSpecs{ std::make_pair(installRoot, QStringLiteral("INSTALL_ROOT"))}; const auto prefixifiedInstallDirPath = [&installRoot, &installRootPrefixSpecs](const QString &path) { if (installRoot.isEmpty()) return path; return replacePrefix(path, installRootPrefixSpecs); }; const auto transformedOutputFilePath = [=](const ArtifactData &output) { return makeValidTargetName(prefixifiedBuildDirPath(output.filePath()), TargetType::Path); }; const auto transformedInputFilePath = [=](const ArtifactData &input) { return makeValidTargetName(prefixifiedSrcDirPath(input.filePath()), TargetType::Path); }; const auto transformedArtifactFilePath = [=](const ArtifactData &artifact) { return artifact.isGenerated() ? transformedOutputFilePath(artifact) : transformedInputFilePath(artifact); }; QStringList allTargets; QStringList allDefaultTargets; QStringList filesCreatedByJsCommands; bool jsCommandsEncountered = false; for (const auto &d : projectTransformerData) { const ProductData productData = d.first; const QString productTarget = makeValidTargetName(productData); const ProductTransformerData productTransformerData = d.second; const bool builtByDefault = productData.properties().value( StringConstants::builtByDefaultProperty()).toBool(); if (builtByDefault) allDefaultTargets.push_back(productTarget); allTargets.push_back(productTarget); stream << productTarget << ':'; for (const ArtifactData &ta : productData.targetArtifacts()) stream << ' ' << transformedOutputFilePath(ta); stream << '\n'; for (const TransformerData &transformerData : productTransformerData) { stream << transformedOutputFilePath(transformerData.outputs().constFirst()) << ":"; for (const ArtifactData &input : transformerData.inputs()) stream << ' ' << transformedArtifactFilePath(input); stream << '\n'; Set createdDirs; for (const ArtifactData &output : transformerData.outputs()) { const QString outputDir = QFileInfo(output.filePath()).path(); if (createdDirs.insert(outputDir).second) stream << "\t" << mkdirCmdLine(QDir::toNativeSeparators( prefixifiedBuildDirPath(outputDir))) << '\n'; } bool processCommandEncountered = false; for (const RuleCommand &command : transformerData.commands()) { if (command.type() == RuleCommand::JavaScriptCommandType) { jsCommandsEncountered = true; continue; } processCommandEncountered = true; stream << '\t' << QDir::toNativeSeparators( quote(bruteForcePathReplace(command.executable(), srcDir, buildDir, installRoot))); // TODO: Optionally use environment? for (const QString &arg : command.arguments()) { stream << ' ' << quote(bruteForcePathReplace(arg, srcDir, buildDir, installRoot)); } stream << '\n'; } for (int i = 1; i < transformerData.outputs().size(); ++i) { stream << transformedOutputFilePath(transformerData.outputs().at(i)) << ": " << transformedOutputFilePath(transformerData.outputs().at(i-1)) << '\n'; } if (!processCommandEncountered && builtByDefault) { for (const ArtifactData &output : transformerData.outputs()) filesCreatedByJsCommands.push_back(output.filePath()); } } stream << "install-" << productTarget << ": " << productTarget << '\n'; Set createdDirs; for (const ArtifactData &artifact : productData.installableArtifacts()) { const QString &outputDir = artifact.installData().localInstallDir(); if (outputDir.contains(QLatin1Char(' '))) { logger().qbsWarning() << Tr::tr("Skipping installation of '%1', because " "target directory '%2' contains spaces.") .arg(artifact.filePath(), outputDir); continue; } if (createdDirs.insert(outputDir).second) stream << "\t" << mkdirCmdLine(QDir::toNativeSeparators( prefixifiedInstallDirPath(outputDir))) << '\n'; const QFileInfo fileInfo(artifact.filePath()); const QString transformedInputFilePath = QDir::toNativeSeparators((artifact.isGenerated() ? prefixifiedBuildDirPath(fileInfo.path()) : prefixifiedSrcDirPath(fileInfo.path())) + QLatin1Char('/') + quote(fileInfo.fileName())); const QString transformedOutputDir = QDir::toNativeSeparators(prefixifiedInstallDirPath( artifact.installData().localInstallDir())); stream << "\t" << (artifact.isExecutable() ? "$(INSTALL_PROGRAM) " : "$(INSTALL_FILE) ") << transformedInputFilePath << ' ' << transformedOutputDir << '\n'; } stream << "clean-" << productTarget << ":\n"; for (const ArtifactData &artifact : productData.generatedArtifacts()) { const QFileInfo fileInfo(artifact.filePath()); const QString transformedFilePath = QDir::toNativeSeparators( prefixifiedBuildDirPath(fileInfo.path()) + QLatin1Char('/') + quote(fileInfo.fileName())); stream << '\t'; if (HostOsInfo::isWindowsHost()) stream << '-'; stream << "$(RM) " << transformedFilePath << '\n'; } } stream << "all:"; for (const QString &target : allDefaultTargets) stream << ' ' << target; stream << '\n'; stream << "install:"; for (const QString &target : allDefaultTargets) stream << ' ' << "install-" << target; stream << '\n'; stream << "clean:"; for (const QString &target : allTargets) stream << ' ' << "clean-" << target; stream << '\n'; if (!filesCreatedByJsCommands.empty()) { logger().qbsWarning() << Tr::tr("Some rules used by this project are not " "Makefile-compatible, because they depend entirely on JavaScriptCommands. " "The build is probably not fully functional. " "Affected build artifacts:\n\t%1") .arg(filesCreatedByJsCommands.join(QLatin1String("\n\t"))); } else if (jsCommandsEncountered) { logger().qbsWarning() << Tr::tr("Some rules in this project use JavaScriptCommands, " "which cannot be converted to Makefile-compatible constructs. The build may " "not be fully functional."); } logger().qbsInfo() << Tr::tr("Makefile successfully generated at '%1'.") .arg(makefileFilePath); } } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/makefilegenerator/makefilegenerator.h000066400000000000000000000042051347155106100267320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_MAKEFILEGENERATOR_H #define QBS_MAKEFILEGENERATOR_H #include namespace qbs { class MakefileGenerator : public ProjectGenerator { QString generatorName() const override; void generate() override; }; } // namespace qbs #endif // Include guard. qbs-src-1.13.1/src/plugins/generator/makefilegenerator/makefilegenerator.pro000066400000000000000000000003041347155106100272770ustar00rootroot00000000000000include(../../plugins.pri) TARGET = makefilegenerator QT = core HEADERS += \ $$PWD/makefilegenerator.h SOURCES += \ $$PWD/makefilegenerator.cpp \ $$PWD/makefilegeneratorplugin.cpp qbs-src-1.13.1/src/plugins/generator/makefilegenerator/makefilegenerator.qbs000066400000000000000000000003341347155106100272670ustar00rootroot00000000000000import qbs import "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { name: "makefilegenerator" files: [ "makefilegenerator.cpp", "makefilegenerator.h", "makefilegeneratorplugin.cpp", ] } qbs-src-1.13.1/src/plugins/generator/makefilegenerator/makefilegeneratorplugin.cpp000066400000000000000000000050161347155106100305050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "makefilegenerator.h" #include #include static void MakefileGeneratorPluginLoad() { qbs::ProjectGeneratorManager::registerGenerator( std::make_shared()); } static void MakefileGeneratorPluginUnload() { } #ifndef GENERATOR_EXPORT #if defined(WIN32) || defined(_WIN32) #define GENERATOR_EXPORT __declspec(dllexport) #else #define GENERATOR_EXPORT __attribute__((visibility("default"))) #endif #endif QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, MakefileGeneratorPlugin, MakefileGeneratorPluginLoad, MakefileGeneratorPluginUnload) qbs-src-1.13.1/src/plugins/generator/visualstudio/000077500000000000000000000000001347155106100221435ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/generator/visualstudio/io/000077500000000000000000000000001347155106100225525ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/generator/visualstudio/io/msbuildprojectwriter.cpp000066400000000000000000000204111347155106100275370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildprojectwriter.h" #include "../msbuild/imsbuildnodevisitor.h" #include "../msbuild/msbuildimport.h" #include "../msbuild/msbuildimportgroup.h" #include "../msbuild/msbuilditem.h" #include "../msbuild/msbuilditemdefinitiongroup.h" #include "../msbuild/msbuilditemgroup.h" #include "../msbuild/msbuilditemmetadata.h" #include "../msbuild/msbuildproject.h" #include "../msbuild/msbuildproperty.h" #include "../msbuild/msbuildpropertygroup.h" #include namespace qbs { static const QString kMSBuildSchemaURI = QStringLiteral("http://schemas.microsoft.com/developer/msbuild/2003"); class MSBuildProjectWriterPrivate : public IMSBuildNodeVisitor { public: std::ostream *device; QByteArray buffer; std::unique_ptr writer; void visitStart(const MSBuildImport *import) override; void visitEnd(const MSBuildImport *import) override; void visitStart(const MSBuildImportGroup *importGroup) override; void visitEnd(const MSBuildImportGroup *importGroup) override; void visitStart(const MSBuildItem *item) override; void visitEnd(const MSBuildItem *item) override; void visitStart(const MSBuildItemDefinitionGroup *itemDefinitionGroup) override; void visitEnd(const MSBuildItemDefinitionGroup *itemDefinitionGroup) override; void visitStart(const MSBuildItemGroup *itemGroup) override; void visitEnd(const MSBuildItemGroup *itemGroup) override; void visitStart(const MSBuildItemMetadata *itemMetadata) override; void visitEnd(const MSBuildItemMetadata *itemMetadata) override; void visitStart(const MSBuildProject *project) override; void visitEnd(const MSBuildProject *project) override; void visitStart(const MSBuildProperty *property) override; void visitEnd(const MSBuildProperty *property) override; void visitStart(const MSBuildPropertyGroup *propertyGroup) override; void visitEnd(const MSBuildPropertyGroup *propertyGroup) override; }; MSBuildProjectWriter::MSBuildProjectWriter(std::ostream *device) : d(new MSBuildProjectWriterPrivate) { d->device = device; d->writer.reset(new QXmlStreamWriter(&d->buffer)); d->writer->setAutoFormatting(true); } MSBuildProjectWriter::~MSBuildProjectWriter() { delete d; } bool MSBuildProjectWriter::write(const MSBuildProject *project) { d->buffer.clear(); d->writer->writeStartDocument(); project->accept(d); d->writer->writeEndDocument(); if (d->writer->hasError()) return false; d->device->write(&*std::begin(d->buffer), d->buffer.size()); return d->device->good(); } void MSBuildProjectWriterPrivate::visitStart(const MSBuildImport *import) { writer->writeStartElement(QStringLiteral("Import")); writer->writeAttribute(QStringLiteral("Project"), import->project()); if (!import->condition().isEmpty()) writer->writeAttribute(QStringLiteral("Condition"), import->condition()); } void MSBuildProjectWriterPrivate::visitEnd(const MSBuildImport *) { writer->writeEndElement(); } void MSBuildProjectWriterPrivate::visitStart(const MSBuildImportGroup *importGroup) { writer->writeStartElement(QStringLiteral("ImportGroup")); if (!importGroup->condition().isEmpty()) writer->writeAttribute(QStringLiteral("Condition"), importGroup->condition()); if (!importGroup->label().isEmpty()) writer->writeAttribute(QStringLiteral("Label"), importGroup->label()); } void MSBuildProjectWriterPrivate::visitEnd(const MSBuildImportGroup *) { writer->writeEndElement(); } void MSBuildProjectWriterPrivate::visitStart(const MSBuildItem *item) { writer->writeStartElement(item->name()); if (!item->include().isEmpty()) writer->writeAttribute(QStringLiteral("Include"), item->include()); } void MSBuildProjectWriterPrivate::visitEnd(const MSBuildItem *) { writer->writeEndElement(); } void MSBuildProjectWriterPrivate::visitStart(const MSBuildItemDefinitionGroup *itemDefinitionGroup) { writer->writeStartElement(QStringLiteral("ItemDefinitionGroup")); if (!itemDefinitionGroup->condition().isEmpty()) writer->writeAttribute(QStringLiteral("Condition"), itemDefinitionGroup->condition()); } void MSBuildProjectWriterPrivate::visitEnd(const MSBuildItemDefinitionGroup *) { writer->writeEndElement(); } void MSBuildProjectWriterPrivate::visitStart(const MSBuildItemGroup *itemGroup) { writer->writeStartElement(QStringLiteral("ItemGroup")); if (!itemGroup->condition().isEmpty()) writer->writeAttribute(QStringLiteral("Condition"), itemGroup->condition()); if (!itemGroup->label().isEmpty()) writer->writeAttribute(QStringLiteral("Label"), itemGroup->label()); } void MSBuildProjectWriterPrivate::visitEnd(const MSBuildItemGroup *) { writer->writeEndElement(); } void MSBuildProjectWriterPrivate::visitStart(const MSBuildItemMetadata *itemMetadata) { QString stringValue; if (itemMetadata->value().type() == QVariant::Bool) { stringValue = itemMetadata->value().toBool() ? QStringLiteral("True") : QStringLiteral("False"); } else { stringValue = itemMetadata->value().toString(); } writer->writeTextElement(itemMetadata->name(), stringValue); } void MSBuildProjectWriterPrivate::visitEnd(const MSBuildItemMetadata *) { } void MSBuildProjectWriterPrivate::visitStart(const MSBuildProject *project) { writer->writeStartElement(QStringLiteral("Project")); if (!project->defaultTargets().isEmpty()) writer->writeAttribute(QStringLiteral("DefaultTargets"), project->defaultTargets()); if (!project->toolsVersion().isEmpty()) writer->writeAttribute(QStringLiteral("ToolsVersion"), project->toolsVersion()); writer->writeAttribute(QStringLiteral("xmlns"), kMSBuildSchemaURI); } void MSBuildProjectWriterPrivate::visitEnd(const MSBuildProject *) { writer->writeEndElement(); } void MSBuildProjectWriterPrivate::visitStart(const MSBuildProperty *property) { QString stringValue; if (property->value().type() == QVariant::Bool) stringValue = property->value().toBool() ? QStringLiteral("True") : QStringLiteral("False"); else stringValue = property->value().toString(); writer->writeTextElement(property->name(), stringValue); } void MSBuildProjectWriterPrivate::visitEnd(const MSBuildProperty *) { } void MSBuildProjectWriterPrivate::visitStart(const MSBuildPropertyGroup *propertyGroup) { writer->writeStartElement(QStringLiteral("PropertyGroup")); if (!propertyGroup->condition().isEmpty()) writer->writeAttribute(QStringLiteral("Condition"), propertyGroup->condition()); if (!propertyGroup->label().isEmpty()) writer->writeAttribute(QStringLiteral("Label"), propertyGroup->label()); } void MSBuildProjectWriterPrivate::visitEnd(const MSBuildPropertyGroup *) { writer->writeEndElement(); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/io/msbuildprojectwriter.h000066400000000000000000000037351347155106100272160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDPROJECTWRITER_H #define MSBUILDPROJECTWRITER_H #include #include namespace qbs { class MSBuildProject; class MSBuildProjectWriterPrivate; class MSBuildProjectWriter { Q_DISABLE_COPY(MSBuildProjectWriter) public: explicit MSBuildProjectWriter(std::ostream *device); ~MSBuildProjectWriter(); bool write(const MSBuildProject *project); private: MSBuildProjectWriterPrivate *d; }; } // namespace qbs #endif // MSBUILDPROJECTWRITER_H qbs-src-1.13.1/src/plugins/generator/visualstudio/io/visualstudiosolutionwriter.cpp000066400000000000000000000130071347155106100310440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "visualstudiosolutionwriter.h" #include "../solution/visualstudiosolutionfileproject.h" #include "../solution/visualstudiosolutionfolderproject.h" #include "../solution/visualstudiosolutionglobalsection.h" #include "../solution/visualstudiosolution.h" #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; class VisualStudioSolutionWriterPrivate { public: std::ostream *device; std::string baseDir; }; VisualStudioSolutionWriter::VisualStudioSolutionWriter(std::ostream *device) : d(new VisualStudioSolutionWriterPrivate) { d->device = device; } VisualStudioSolutionWriter::~VisualStudioSolutionWriter() { } std::string VisualStudioSolutionWriter::projectBaseDirectory() const { return d->baseDir; } void VisualStudioSolutionWriter::setProjectBaseDirectory(const std::string &dir) { d->baseDir = dir; } bool VisualStudioSolutionWriter::write(const VisualStudioSolution *solution) { auto &out = *d->device; out << u8"Microsoft Visual Studio Solution File, Format Version " << solution->versionInfo().solutionVersion().toStdString() << u8"\n# Visual Studio " << solution->versionInfo().version().majorVersion() << u8"\n"; for (const auto &project : solution->fileProjects()) { auto projectFilePath = project->filePath().toStdString(); // Try to make the project file path relative to the // solution file path if we're writing to a file device if (!d->baseDir.empty()) { const QDir solutionDir(QString::fromStdString(d->baseDir)); projectFilePath = Internal::PathUtils::toNativeSeparators( solutionDir.relativeFilePath(QString::fromStdString(projectFilePath)), Internal::HostOsInfo::HostOsWindows).toStdString(); } out << u8"Project(\"" << project->projectTypeGuid().toString().toStdString() << u8"\") = \"" << QFileInfo(QString::fromStdString(projectFilePath)).baseName().toStdString() << u8"\", \"" << projectFilePath << u8"\", \"" << project->guid().toString().toStdString() << u8"\"\n"; const auto dependencies = solution->dependencies(project); if (!dependencies.empty()) { out << u8"\tProjectSection(ProjectDependencies) = postProject\n"; for (const auto &dependency : dependencies) out << u8"\t\t" << dependency->guid().toString().toStdString() << u8" = " << dependency->guid().toString().toStdString() << u8"\n"; out << u8"\tEndProjectSection\n"; } out << u8"EndProject\n"; } for (const auto &project : solution->folderProjects()) { out << u8"Project(\"" << project->projectTypeGuid().toString().toStdString() << u8"\") = \"" << project->name().toStdString() << u8"\", \"" << project->name().toStdString() << u8"\", \"" << project->guid().toString().toStdString() << u8"\"\n"; out << u8"EndProject\n"; } out << u8"Global\n"; for (const auto &globalSection : solution->globalSections()) { out << u8"\tGlobalSection(" << globalSection->name().toStdString() << u8") = " << (globalSection->isPost() ? u8"postSolution" : u8"preSolution") << u8"\n"; for (const auto &property : globalSection->properties()) out << u8"\t\t" << property.first.toStdString() << u8" = " << property.second.toStdString() << u8"\n"; out << u8"\tEndGlobalSection\n"; } out << u8"EndGlobal\n"; return out.good(); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/io/visualstudiosolutionwriter.h000066400000000000000000000044321347155106100305130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef VISUALSTUDIOSOLUTIONWRITER_H #define VISUALSTUDIOSOLUTIONWRITER_H #include #include #include #include namespace qbs { namespace Internal { class VisualStudioVersionInfo; } class VisualStudioSolution; class VisualStudioSolutionWriterPrivate; class VisualStudioSolutionWriter { Q_DISABLE_COPY(VisualStudioSolutionWriter) public: explicit VisualStudioSolutionWriter(std::ostream *device); ~VisualStudioSolutionWriter(); std::string projectBaseDirectory() const; void setProjectBaseDirectory(const std::string &dir); bool write(const VisualStudioSolution *solution); private: void addDefaultGlobalSections(); std::unique_ptr d; }; } // namespace qbs #endif // VISUALSTUDIOSOLUTIONWRITER_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/000077500000000000000000000000001347155106100236025ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/imsbuildgroup.cpp000066400000000000000000000040351347155106100271750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "imsbuildgroup.h" #include "msbuildproject.h" namespace qbs { class IMSBuildGroupPrivate { public: QString condition; }; IMSBuildGroup::IMSBuildGroup(MSBuildProject *parent) : QObject(parent) , d(new IMSBuildGroupPrivate) { } IMSBuildGroup::~IMSBuildGroup() { } QString IMSBuildGroup::condition() const { return d->condition; } void IMSBuildGroup::setCondition(const QString &condition) { d->condition = condition; } IMSBuildItemGroup::IMSBuildItemGroup(MSBuildProject *parent) : IMSBuildGroup(parent) { } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/imsbuildgroup.h000066400000000000000000000041521347155106100266420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef IMSBUILDGROUP_H #define IMSBUILDGROUP_H #include #include namespace qbs { class MSBuildProject; class IMSBuildGroupPrivate; class IMSBuildGroup : public QObject { Q_OBJECT public: explicit IMSBuildGroup(MSBuildProject *parent = nullptr); virtual ~IMSBuildGroup(); QString condition() const; void setCondition(const QString &condition); private: std::unique_ptr d; }; class IMSBuildItemGroup : public IMSBuildGroup { Q_OBJECT public: explicit IMSBuildItemGroup(MSBuildProject *parent = nullptr); }; } // namespace qbs #endif // IMSBUILDGROUP_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/imsbuildnode.cpp000066400000000000000000000031111347155106100267600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "imsbuildnode.h" namespace qbs { IMSBuildNode::~IMSBuildNode() { } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/imsbuildnode.h000066400000000000000000000033571347155106100264410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef IMSBUILDNODE_H #define IMSBUILDNODE_H namespace qbs { class IMSBuildNodeVisitor; class IMSBuildNode { public: virtual ~IMSBuildNode(); virtual void accept(IMSBuildNodeVisitor *visitor) const = 0; }; } // namespace qbs #endif // IMSBUILDNODE_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/imsbuildnodevisitor.h000066400000000000000000000061671347155106100300630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef IMSBUILDNODEVISITOR_H #define IMSBUILDNODEVISITOR_H namespace qbs { class MSBuildImport; class MSBuildImportGroup; class MSBuildItem; class MSBuildItemDefinitionGroup; class MSBuildItemGroup; class MSBuildItemMetadata; class MSBuildProject; class MSBuildProperty; class MSBuildPropertyGroup; class IMSBuildNodeVisitor { public: virtual ~IMSBuildNodeVisitor() {} virtual void visitStart(const MSBuildImport *import) = 0; virtual void visitEnd(const MSBuildImport *import) = 0; virtual void visitStart(const MSBuildImportGroup *importGroup) = 0; virtual void visitEnd(const MSBuildImportGroup *importGroup) = 0; virtual void visitStart(const MSBuildItem *item) = 0; virtual void visitEnd(const MSBuildItem *item) = 0; virtual void visitStart(const MSBuildItemDefinitionGroup *itemDefinitionGroup) = 0; virtual void visitEnd(const MSBuildItemDefinitionGroup *itemDefinitionGroup) = 0; virtual void visitStart(const MSBuildItemGroup *itemGroup) = 0; virtual void visitEnd(const MSBuildItemGroup *itemGroup) = 0; virtual void visitStart(const MSBuildItemMetadata *itemMetadata) = 0; virtual void visitEnd(const MSBuildItemMetadata *itemMetadata) = 0; virtual void visitStart(const MSBuildProject *project) = 0; virtual void visitEnd(const MSBuildProject *project) = 0; virtual void visitStart(const MSBuildProperty *property) = 0; virtual void visitEnd(const MSBuildProperty *property) = 0; virtual void visitStart(const MSBuildPropertyGroup *propertyGroup) = 0; virtual void visitEnd(const MSBuildPropertyGroup *propertyGroup) = 0; }; } // namespace qbs #endif // IMSBUILDNODEVISITOR_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/imsbuildproperty.cpp000066400000000000000000000043771347155106100277360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "imsbuildproperty.h" namespace qbs { class IMSBuildPropertyPrivate { public: QString condition; QString name; QVariant value; }; IMSBuildProperty::IMSBuildProperty(QObject *parent) : QObject(parent) , d(new IMSBuildPropertyPrivate) { } IMSBuildProperty::~IMSBuildProperty() { } QString IMSBuildProperty::condition() const { return d->condition; } void IMSBuildProperty::setCondition(const QString &condition) { d->condition = condition; } QString IMSBuildProperty::name() const { return d->name; } void IMSBuildProperty::setName(const QString &name) { d->name = name; } QVariant IMSBuildProperty::value() const { return d->value; } void IMSBuildProperty::setValue(const QVariant &value) { d->value = value; } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/imsbuildproperty.h000066400000000000000000000042131347155106100273700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef IMSBUILDPROPERTY_H #define IMSBUILDPROPERTY_H #include #include #include namespace qbs { class IMSBuildPropertyPrivate; class IMSBuildProperty : public QObject { Q_OBJECT protected: explicit IMSBuildProperty(QObject *parent = nullptr); public: virtual ~IMSBuildProperty(); QString condition() const; void setCondition(const QString &condition); QString name() const; void setName(const QString &name); QVariant value() const; void setValue(const QVariant &value); private: std::unique_ptr d; }; } // namespace qbs #endif // IMSBUILDPROPERTY_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/000077500000000000000000000000001347155106100247235ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildclcompile.cpp000066400000000000000000000033631347155106100307630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildclcompile.h" namespace qbs { static const QString MSBuildClCompileItemName = QStringLiteral("ClCompile"); MSBuildClCompile::MSBuildClCompile(IMSBuildItemGroup *parent) : MSBuildFileItem(MSBuildClCompileItemName, parent) { } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildclcompile.h000066400000000000000000000034621347155106100304300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDCLCOMPILE_H #define MSBUILDCLCOMPILE_H #include "msbuildfileitem.h" namespace qbs { class MSBuildClCompile : public MSBuildFileItem { Q_OBJECT Q_DISABLE_COPY(MSBuildClCompile) public: explicit MSBuildClCompile(IMSBuildItemGroup *parent = nullptr); }; } // namespace qbs #endif // MSBUILDCLCOMPILE_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildclinclude.cpp000066400000000000000000000033631347155106100307560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildclinclude.h" namespace qbs { static const QString MSBuildClIncludeItemName = QStringLiteral("ClInclude"); MSBuildClInclude::MSBuildClInclude(IMSBuildItemGroup *parent) : MSBuildFileItem(MSBuildClIncludeItemName, parent) { } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildclinclude.h000066400000000000000000000034621347155106100304230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDCLINCLUDE_H #define MSBUILDCLINCLUDE_H #include "msbuildfileitem.h" namespace qbs { class MSBuildClInclude : public MSBuildFileItem { Q_OBJECT Q_DISABLE_COPY(MSBuildClInclude) public: explicit MSBuildClInclude(IMSBuildItemGroup *parent = nullptr); }; } // namespace qbs #endif // MSBUILDCLINCLUDE_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildfileitem.cpp000066400000000000000000000045451347155106100306150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildfileitem.h" #include "../msbuilditemmetadata.h" namespace qbs { class MSBuildFileItemPrivate { public: std::unique_ptr filter; }; MSBuildFileItem::MSBuildFileItem(const QString &name, IMSBuildItemGroup *parent) : MSBuildItem(name, parent) , d(new MSBuildFileItemPrivate) { d->filter.reset(new MSBuildItemMetadata(QStringLiteral("Filter"), QVariant())); } MSBuildFileItem::~MSBuildFileItem() { } QString MSBuildFileItem::filePath() const { return include(); } void MSBuildFileItem::setFilePath(const QString &filePath) { setInclude(filePath); } QString MSBuildFileItem::filterName() const { return d->filter->value().toString(); } void MSBuildFileItem::setFilterName(const QString &filterName) { d->filter->setValue(filterName); d->filter->setParent(!filterName.isEmpty() ? this : nullptr); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildfileitem.h000066400000000000000000000040611347155106100302530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDFILEITEM_H #define MSBUILDFILEITEM_H #include "../msbuilditem.h" namespace qbs { class MSBuildFileItemPrivate; class MSBuildFileItem : public MSBuildItem { public: virtual ~MSBuildFileItem(); QString filePath() const; void setFilePath(const QString &filePath); QString filterName() const; void setFilterName(const QString &filterName); protected: explicit MSBuildFileItem(const QString &name, IMSBuildItemGroup *parent = nullptr); private: std::unique_ptr d; }; } // namespace qbs #endif // MSBUILDFILEITEM_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildfilter.cpp000066400000000000000000000073061347155106100303020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildfilter.h" #include "../msbuilditemmetadata.h" #include #include namespace qbs { static const QString MSBuildFilterItemName = QStringLiteral("Filter"); class MSBuildFilterPrivate { public: QUuid identifier; QList extensions; bool parseFiles = true; bool sourceControlFiles = true; MSBuildItemMetadata *identifierMetadata; MSBuildItemMetadata *extensionsMetadata; }; MSBuildFilter::MSBuildFilter(IMSBuildItemGroup *parent) : MSBuildItem(MSBuildFilterItemName, parent) , d(new MSBuildFilterPrivate) { d->identifierMetadata = new MSBuildItemMetadata(QStringLiteral("UniqueIdentifier"), QVariant(), this); d->extensionsMetadata = new MSBuildItemMetadata(QStringLiteral("Extensions"), QVariant(), this); setIdentifier(QUuid::createUuid()); } MSBuildFilter::MSBuildFilter(const QString &name, const QList &extensions, IMSBuildItemGroup *parent) : MSBuildFilter(parent) { setInclude(name); setExtensions(extensions); } MSBuildFilter::~MSBuildFilter() { } QUuid MSBuildFilter::identifier() const { return d->identifier; } void MSBuildFilter::setIdentifier(const QUuid &identifier) { d->identifier = identifier; d->identifierMetadata->setValue(identifier.toString()); } QList MSBuildFilter::extensions() const { return d->extensions; } void MSBuildFilter::setExtensions(const QList &extensions) { d->extensions = extensions; d->extensionsMetadata->setValue(QStringList(extensions).join( Internal::HostOsInfo::pathListSeparator( Internal::HostOsInfo::HostOsWindows))); } bool MSBuildFilter::parseFiles() const { return d->parseFiles; } void MSBuildFilter::setParseFiles(bool parseFiles) { d->parseFiles = parseFiles; } bool MSBuildFilter::sourceControlFiles() const { return d->sourceControlFiles; } void MSBuildFilter::setSourceControlFiles(bool sourceControlFiles) { d->sourceControlFiles = sourceControlFiles; } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildfilter.h000066400000000000000000000045251347155106100277470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDFILTER_H #define MSBUILDFILTER_H #include "../msbuilditem.h" namespace qbs { class IMSBuildItemGroup; class MSBuildFilterPrivate; class MSBuildFilter : public MSBuildItem { Q_OBJECT public: explicit MSBuildFilter(IMSBuildItemGroup *parent = nullptr); MSBuildFilter(const QString &name, const QList &extensions, IMSBuildItemGroup *parent = nullptr); ~MSBuildFilter(); QUuid identifier() const; void setIdentifier(const QUuid &identifier); QList extensions() const; void setExtensions(const QList &extensions); bool parseFiles() const; void setParseFiles(bool parseFiles); bool sourceControlFiles() const; void setSourceControlFiles(bool sourceControlFiles); private: std::unique_ptr d; }; } // namespace qbs #endif // MSBUILDFILTER_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildlink.cpp000066400000000000000000000033601347155106100277460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildlink.h" #include "../imsbuildgroup.h" namespace qbs { static const QString MSBuildLinkItemName = QStringLiteral("Link"); MSBuildLink::MSBuildLink(IMSBuildItemGroup *parent) : MSBuildItem(MSBuildLinkItemName, parent) { } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildlink.h000066400000000000000000000034111347155106100274100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDLINK_H #define MSBUILDLINK_H #include "../msbuilditem.h" namespace qbs { class IMSBuildItemGroup; class MSBuildLink : public MSBuildItem { Q_OBJECT public: explicit MSBuildLink(IMSBuildItemGroup *parent = nullptr); }; } // namespace qbs #endif // MSBUILDLINK_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildnone.cpp000066400000000000000000000032241347155106100277470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildnone.h" namespace qbs { MSBuildNone::MSBuildNone(IMSBuildItemGroup *parent) : MSBuildFileItem(QStringLiteral("None"), parent) { } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/items/msbuildnone.h000066400000000000000000000034241347155106100274160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDNONE_H #define MSBUILDNONE_H #include "msbuildfileitem.h" namespace qbs { class MSBuildNone : public MSBuildFileItem { Q_OBJECT Q_DISABLE_COPY(MSBuildNone) public: explicit MSBuildNone(IMSBuildItemGroup *parent = nullptr); }; } // namespace qbs #endif // MSBUILDNONE_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuildimport.cpp000066400000000000000000000046451347155106100272110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildimport.h" #include "imsbuildnodevisitor.h" #include "msbuildimportgroup.h" #include "msbuildproject.h" namespace qbs { class MSBuildImportPrivate { public: QString project; QString condition; }; MSBuildImport::MSBuildImport(MSBuildProject *parent) : QObject(parent) , d(new MSBuildImportPrivate) { } MSBuildImport::MSBuildImport(MSBuildImportGroup *parent) : QObject(parent) , d(new MSBuildImportPrivate) { } MSBuildImport::~MSBuildImport() { } QString MSBuildImport::project() const { return d->project; } void MSBuildImport::setProject(const QString &project) { d->project = project; } QString MSBuildImport::condition() const { return d->condition; } void MSBuildImport::setCondition(const QString &condition) { d->condition = condition; } void MSBuildImport::accept(IMSBuildNodeVisitor *visitor) const { visitor->visitStart(this); visitor->visitEnd(this); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuildimport.h000066400000000000000000000046041347155106100266510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDIMPORT_H #define MSBUILDIMPORT_H #include #include "imsbuildnode.h" #include namespace qbs { class MSBuildImportGroup; class MSBuildImportPrivate; class MSBuildProject; /*! * \brief The MSBuildImport class represents an MSBuild Import element. * * https://msdn.microsoft.com/en-us/library/92x05xfs.aspx */ class MSBuildImport : public QObject, public IMSBuildNode { Q_OBJECT Q_DISABLE_COPY(MSBuildImport) public: explicit MSBuildImport(MSBuildProject *parent); explicit MSBuildImport(MSBuildImportGroup *parent); virtual ~MSBuildImport(); QString project() const; void setProject(const QString &project); QString condition() const; void setCondition(const QString &condition); void accept(IMSBuildNodeVisitor *visitor) const; private: std::unique_ptr d; }; } // namespace qbs #endif // MSBUILDIMPORT_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuildimportgroup.cpp000066400000000000000000000044521347155106100302620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildimportgroup.h" #include "imsbuildnodevisitor.h" #include "msbuildimport.h" namespace qbs { class MSBuildImportGroupPrivate { public: QString label; }; MSBuildImportGroup::MSBuildImportGroup(MSBuildProject *parent) : IMSBuildGroup(parent) , d(new MSBuildImportGroupPrivate) { } MSBuildImportGroup::~MSBuildImportGroup() { } QString MSBuildImportGroup::label() const { return d->label; } void MSBuildImportGroup::setLabel(const QString &label) { d->label = label; } void MSBuildImportGroup::accept(IMSBuildNodeVisitor *visitor) const { visitor->visitStart(this); for (const auto &child : children()) { if (const MSBuildImport *import = qobject_cast(child)) import->accept(visitor); } visitor->visitEnd(this); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuildimportgroup.h000066400000000000000000000044171347155106100277300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDIMPORTGROUP_H #define MSBUILDIMPORTGROUP_H #include "imsbuildgroup.h" #include "imsbuildnode.h" namespace qbs { class MSBuildProject; class MSBuildImportGroupPrivate; /*! * \brief The MSBuildImportGroup class represents an MSBuild ImportGroup element. * * https://msdn.microsoft.com/en-us/library/ff606262.aspx */ class MSBuildImportGroup : public IMSBuildGroup, public IMSBuildNode { Q_OBJECT Q_DISABLE_COPY(MSBuildImportGroup) public: explicit MSBuildImportGroup(MSBuildProject *parent = nullptr); virtual ~MSBuildImportGroup(); QString label() const; void setLabel(const QString &label); void accept(IMSBuildNodeVisitor *visitor) const; private: std::unique_ptr d; }; } // namespace qbs #endif // MSBUILDIMPORTGROUP_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuilditem.cpp000066400000000000000000000052371347155106100266330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuilditem.h" #include "imsbuildnodevisitor.h" #include "msbuilditemdefinitiongroup.h" #include "msbuilditemgroup.h" #include "msbuilditemmetadata.h" namespace qbs { class MSBuildItemPrivate { public: QString name = QStringLiteral("Item"); QString include; }; MSBuildItem::MSBuildItem(const QString &name, IMSBuildItemGroup *parent) : QObject(parent) , d(new MSBuildItemPrivate) { setName(name); } MSBuildItem::~MSBuildItem() { } QString MSBuildItem::name() const { return d->name; } void MSBuildItem::setName(const QString &name) { d->name = name; } QString MSBuildItem::include() const { return d->include; } void MSBuildItem::setInclude(const QString &include) { d->include = include; } void MSBuildItem::appendProperty(const QString &name, const QVariant &value) { new MSBuildItemMetadata(name, value, this); } void MSBuildItem::accept(IMSBuildNodeVisitor *visitor) const { visitor->visitStart(this); for (const auto &child : children()) { if (MSBuildItemMetadata *itemMetadata = qobject_cast(child)) itemMetadata->accept(visitor); } visitor->visitEnd(this); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuilditem.h000066400000000000000000000046231347155106100262760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDITEM_H #define MSBUILDITEM_H #include #include "imsbuildnode.h" #include namespace qbs { class IMSBuildItemGroup; class MSBuildItemDefinitionGroup; class MSBuildItemGroup; class MSBuildItemPrivate; /*! * \brief The MSBuildItem class represents an MSBuild Item element. * * https://msdn.microsoft.com/en-us/library/ms164283.aspx */ class MSBuildItem : public QObject, public IMSBuildNode { Q_OBJECT public: explicit MSBuildItem(const QString &name, IMSBuildItemGroup *parent = nullptr); virtual ~MSBuildItem(); QString name() const; void setName(const QString &name); QString include() const; void setInclude(const QString &include); void appendProperty(const QString &name, const QVariant &value); void accept(IMSBuildNodeVisitor *visitor) const; private: std::unique_ptr d; }; } // namespace qbs #endif // MSBUILDITEM_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuilditemdefinitiongroup.cpp000066400000000000000000000041071347155106100317540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuilditemdefinitiongroup.h" #include "imsbuildnodevisitor.h" #include "msbuilditem.h" namespace qbs { MSBuildItemDefinitionGroup::MSBuildItemDefinitionGroup(MSBuildProject *parent) : IMSBuildItemGroup(parent) { } MSBuildItemDefinitionGroup::~MSBuildItemDefinitionGroup() { } void MSBuildItemDefinitionGroup::accept(IMSBuildNodeVisitor *visitor) const { visitor->visitStart(this); for (const auto &child : children()) { if (const auto item = qobject_cast(child)) item->accept(visitor); } visitor->visitEnd(this); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuilditemdefinitiongroup.h000066400000000000000000000042531347155106100314230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDITEMDEFINITIONGROUP_H #define MSBUILDITEMDEFINITIONGROUP_H #include "imsbuildgroup.h" #include "imsbuildnode.h" namespace qbs { class MSBuildProject; class MSBuildItemDefinitionGroupPrivate; /*! * \brief The MSBuildItemDefinitionGroup class represents an MSBuild ItemDefinitionGroup element. * * https://msdn.microsoft.com/en-us/library/bb629392.aspx */ class MSBuildItemDefinitionGroup : public IMSBuildItemGroup, public IMSBuildNode { Q_OBJECT public: explicit MSBuildItemDefinitionGroup(MSBuildProject *parent = nullptr); ~MSBuildItemDefinitionGroup(); void accept(IMSBuildNodeVisitor *visitor) const; }; } // namespace qbs #endif // MSBUILDITEMDEFINITIONGROUP_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuilditemgroup.cpp000066400000000000000000000044351347155106100277070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuilditemgroup.h" #include "imsbuildnodevisitor.h" #include "msbuilditem.h" #include namespace qbs { class MSBuildItemGroupPrivate { public: QString label; }; MSBuildItemGroup::MSBuildItemGroup(MSBuildProject *parent) : IMSBuildItemGroup(parent) , d(new MSBuildItemGroupPrivate) { } MSBuildItemGroup::~MSBuildItemGroup() { } QString MSBuildItemGroup::label() const { return d->label; } void MSBuildItemGroup::setLabel(const QString &label) { d->label = label; } void MSBuildItemGroup::accept(IMSBuildNodeVisitor *visitor) const { visitor->visitStart(this); for (const auto &child : children()) { if (const MSBuildItem *item = qobject_cast(child)) item->accept(visitor); } visitor->visitEnd(this); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuilditemgroup.h000066400000000000000000000044101347155106100273450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDITEMGROUP_H #define MSBUILDITEMGROUP_H #include "imsbuildgroup.h" #include "imsbuildnode.h" #include namespace qbs { class MSBuildProject; class MSBuildItemGroupPrivate; /*! * \brief The MSBuildItemGroup class represents an MSBuild ItemGroup element. * * https://msdn.microsoft.com/en-us/library/646dk05y.aspx */ class MSBuildItemGroup : public IMSBuildItemGroup, public IMSBuildNode { Q_OBJECT Q_DISABLE_COPY(MSBuildItemGroup) public: explicit MSBuildItemGroup(MSBuildProject *parent = nullptr); ~MSBuildItemGroup(); QString label() const; void setLabel(const QString &label); void accept(IMSBuildNodeVisitor *visitor) const; private: std::unique_ptr d; }; } // namespace qbs #endif // MSBUILDITEMGROUP_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuilditemmetadata.cpp000066400000000000000000000040621347155106100303270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuilditemmetadata.h" #include "imsbuildnodevisitor.h" #include "msbuilditem.h" namespace qbs { MSBuildItemMetadata::MSBuildItemMetadata(MSBuildItem *parent) : IMSBuildProperty(parent) { } MSBuildItemMetadata::MSBuildItemMetadata(const QString &name, const QVariant &value, MSBuildItem *parent) : MSBuildItemMetadata(parent) { setName(name); setValue(value); } void MSBuildItemMetadata::accept(IMSBuildNodeVisitor *visitor) const { visitor->visitStart(this); visitor->visitEnd(this); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuilditemmetadata.h000066400000000000000000000043331347155106100277750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDITEMMETADATA_H #define MSBUILDITEMMETADATA_H #include "imsbuildproperty.h" #include "imsbuildnode.h" namespace qbs { class MSBuildItem; /*! * \brief The MSBuildItemMetadata class represents an MSBuild ItemMetadata element. * * https://msdn.microsoft.com/en-us/library/ms164284.aspx */ class MSBuildItemMetadata : public IMSBuildProperty, public IMSBuildNode { Q_OBJECT Q_DISABLE_COPY(MSBuildItemMetadata) public: explicit MSBuildItemMetadata(MSBuildItem *parent = nullptr); MSBuildItemMetadata(const QString &name, const QVariant &value = QVariant(), MSBuildItem *parent = nullptr); void accept(IMSBuildNodeVisitor *visitor) const; }; } // namespace qbs #endif // MSBUILDITEMMETADATA_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuildproject.cpp000066400000000000000000000061071347155106100273400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildproject.h" #include "imsbuildnodevisitor.h" #include "msbuildimport.h" #include "msbuildimportgroup.h" #include "msbuilditemdefinitiongroup.h" #include "msbuilditemgroup.h" #include "msbuildpropertygroup.h" namespace qbs { class MSBuildProjectPrivate { public: QString defaultTargets; QString toolsVersion; }; MSBuildProject::MSBuildProject(QObject *parent) : QObject(parent) , d(new MSBuildProjectPrivate) { } MSBuildProject::~MSBuildProject() { } QString MSBuildProject::defaultTargets() const { return d->defaultTargets; } void MSBuildProject::setDefaultTargets(const QString &defaultTargets) { d->defaultTargets = defaultTargets; } QString MSBuildProject::toolsVersion() const { return d->toolsVersion; } void MSBuildProject::setToolsVersion(const QString &toolsVersion) { d->toolsVersion = toolsVersion; } void MSBuildProject::accept(IMSBuildNodeVisitor *visitor) const { visitor->visitStart(this); for (const auto &child : children()) { if (const auto node = qobject_cast(child)) node->accept(visitor); else if (const auto node = qobject_cast(child)) node->accept(visitor); else if (const auto node = qobject_cast(child)) node->accept(visitor); else if (const auto node = qobject_cast(child)) node->accept(visitor); else if (const auto node = qobject_cast(child)) node->accept(visitor); } visitor->visitEnd(this); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuildproject.h000066400000000000000000000045011347155106100270010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDPROJECT_H #define MSBUILDPROJECT_H #include #include "imsbuildnode.h" #include namespace qbs { class MSBuildProjectPrivate; /*! * \brief The MSBuildProject class represents an MSBuild Project element. * * https://msdn.microsoft.com/en-us/library/bcxfsh87.aspx */ class MSBuildProject : public QObject, public IMSBuildNode { Q_OBJECT Q_DISABLE_COPY(MSBuildProject) public: explicit MSBuildProject(QObject *parent = nullptr); ~MSBuildProject(); QString defaultTargets() const; void setDefaultTargets(const QString &defaultTargets); QString toolsVersion() const; void setToolsVersion(const QString &toolsVersion); void accept(IMSBuildNodeVisitor *visitor) const; private: std::unique_ptr d; }; } // namespace qbs #endif // MSBUILDPROJECT_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuildproperty.cpp000066400000000000000000000040511347155106100275520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildproperty.h" #include "imsbuildnodevisitor.h" #include "msbuildpropertygroup.h" namespace qbs { MSBuildProperty::MSBuildProperty(MSBuildPropertyGroup *parent) : IMSBuildProperty(parent) { } MSBuildProperty::MSBuildProperty(const QString &name, const QVariant &value, MSBuildPropertyGroup *parent) : MSBuildProperty(parent) { setName(name); setValue(value); } void MSBuildProperty::accept(IMSBuildNodeVisitor *visitor) const { visitor->visitStart(this); visitor->visitEnd(this); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuildproperty.h000066400000000000000000000042521347155106100272220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDPROPERTY_H #define MSBUILDPROPERTY_H #include "imsbuildproperty.h" #include "imsbuildnode.h" namespace qbs { class MSBuildPropertyGroup; /*! * \brief The MSBuildProperty class represents an MSBuild Property element. * * https://msdn.microsoft.com/en-us/library/ms164288.aspx */ class MSBuildProperty : public IMSBuildProperty, public IMSBuildNode { Q_OBJECT public: explicit MSBuildProperty(MSBuildPropertyGroup *parent = nullptr); MSBuildProperty(const QString &name, const QVariant &value = QVariant(), MSBuildPropertyGroup *parent = nullptr); void accept(IMSBuildNodeVisitor *visitor) const; }; } // namespace qbs #endif // MSBUILDPROPERTY_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuildpropertygroup.cpp000066400000000000000000000047401347155106100306340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildpropertygroup.h" #include "imsbuildnodevisitor.h" #include "msbuildproperty.h" namespace qbs { class MSBuildPropertyGroupPrivate { public: QString condition; QString label; }; MSBuildPropertyGroup::MSBuildPropertyGroup(MSBuildProject *parent) : IMSBuildGroup(parent) , d(new MSBuildPropertyGroupPrivate) { } MSBuildPropertyGroup::~MSBuildPropertyGroup() { } QString MSBuildPropertyGroup::label() const { return d->label; } void MSBuildPropertyGroup::setLabel(const QString &label) { d->label = label; } void MSBuildPropertyGroup::appendProperty(const QString &name, const QVariant &value) { new MSBuildProperty(name, value, this); } void MSBuildPropertyGroup::accept(IMSBuildNodeVisitor *visitor) const { visitor->visitStart(this); for (const auto &child : children()) { if (const MSBuildProperty *property = qobject_cast(child)) property->accept(visitor); } visitor->visitEnd(this); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuild/msbuildpropertygroup.h000066400000000000000000000045431347155106100303020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDPROPERTYGROUP_H #define MSBUILDPROPERTYGROUP_H #include "imsbuildgroup.h" #include "imsbuildnode.h" namespace qbs { class MSBuildProject; class MSBuildPropertyGroupPrivate; /*! * \brief The MSBuildPropertyGroup class represents an MSBuild PropertyGroup element. * * https://msdn.microsoft.com/en-us/library/t4w159bs.aspx */ class MSBuildPropertyGroup : public IMSBuildGroup, public IMSBuildNode { Q_OBJECT Q_DISABLE_COPY(MSBuildPropertyGroup) public: explicit MSBuildPropertyGroup(MSBuildProject *parent = nullptr); ~MSBuildPropertyGroup(); QString label() const; void setLabel(const QString &label); void appendProperty(const QString &name, const QVariant &value); void accept(IMSBuildNodeVisitor *visitor) const; private: std::unique_ptr d; }; } // namespace qbs #endif // MSBUILDPROPERTYGROUP_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildfiltersproject.cpp000066400000000000000000000146001347155106100272670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildfiltersproject.h" #include "msbuild/msbuilditemgroup.h" #include "msbuild/items/msbuildclcompile.h" #include "msbuild/items/msbuildclinclude.h" #include "msbuild/items/msbuildfilter.h" #include "msbuild/items/msbuildnone.h" #include #include #include namespace qbs { namespace { static QStringList sourceFileExtensions() { return {QStringLiteral("c"), QStringLiteral("C"), QStringLiteral("cpp"), QStringLiteral("cxx"), QStringLiteral("c++"), QStringLiteral("cc"), QStringLiteral("cs"), QStringLiteral("def"), QStringLiteral("java"), QStringLiteral("m"), QStringLiteral("mm")}; } static QStringList headerFileExtensions() { return {QStringLiteral("h"), QStringLiteral("H"), QStringLiteral("hpp"), QStringLiteral("hxx"), QStringLiteral("h++")}; } static std::vector defaultItemGroupFilters(IMSBuildItemGroup *parent = nullptr) { const auto sourceFilter = new MSBuildFilter(QStringLiteral("Source Files"), sourceFileExtensions(), parent); const auto headerFilter = new MSBuildFilter(QStringLiteral("Header Files"), headerFileExtensions(), parent); const auto formFilter = new MSBuildFilter(QStringLiteral("Form Files"), QStringList() << QStringLiteral("ui"), parent); const auto resourceFilter = new MSBuildFilter(QStringLiteral("Resource Files"), QStringList() << QStringLiteral("qrc") << QStringLiteral("rc") << QStringLiteral("*"), parent); resourceFilter->setParseFiles(false); const auto generatedFilter = new MSBuildFilter(QStringLiteral("Generated Files"), QStringList() << QStringLiteral("moc"), parent); generatedFilter->setSourceControlFiles(false); const auto translationFilter = new MSBuildFilter(QStringLiteral("Translation Files"), QStringList() << QStringLiteral("ts"), parent); translationFilter->setParseFiles(false); return std::vector { sourceFilter, headerFilter, formFilter, resourceFilter, generatedFilter, translationFilter }; } static bool matchesFilter(const MSBuildFilter *filter, const QString &filePath) { return filter->extensions().contains(QFileInfo(filePath).completeSuffix()); } } MSBuildFiltersProject::MSBuildFiltersProject(const GeneratableProductData &product, QObject *parent) : MSBuildProject(parent) { // Normally this would be versionInfo.toolsVersion() but for some reason it seems // filters projects are always v4.0 setToolsVersion(QStringLiteral("4.0")); const auto itemGroup = new MSBuildItemGroup(this); const auto filterOptions = defaultItemGroupFilters(); for (const auto options : filterOptions) { const auto filter = new MSBuildFilter(options->include(), options->extensions(), itemGroup); filter->appendProperty(QStringLiteral("ParseFiles"), options->parseFiles()); filter->appendProperty(QStringLiteral("SourceControlFiles"), options->sourceControlFiles()); } Internal::Set allFiles; for (const auto &productData : product.data.values()) { for (const auto &groupData : productData.groups()) if (groupData.isEnabled()) allFiles.unite(Internal::Set::fromList(groupData.allFilePaths())); } MSBuildItemGroup *headerFilesGroup = nullptr; MSBuildItemGroup *sourceFilesGroup = nullptr; MSBuildItemGroup *filesGroup = nullptr; for (const auto &filePath : allFiles) { MSBuildFileItem *fileItem = nullptr; for (const MSBuildFilter *options : filterOptions) { if (matchesFilter(options, filePath)) { if (options->include() == QStringLiteral("Header Files")) { if (!headerFilesGroup) headerFilesGroup = new MSBuildItemGroup(this); fileItem = new MSBuildClInclude(headerFilesGroup); } else if (options->include() == QStringLiteral("Source Files")) { if (!sourceFilesGroup) sourceFilesGroup = new MSBuildItemGroup(this); fileItem = new MSBuildClCompile(sourceFilesGroup); } if (fileItem) { fileItem->setFilterName(options->include()); break; } } } if (!fileItem) { if (!filesGroup) filesGroup = new MSBuildItemGroup(this); fileItem = new MSBuildNone(filesGroup); } fileItem->setFilePath(filePath); } qDeleteAll(filterOptions); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildfiltersproject.h000066400000000000000000000037761347155106100267500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDFILTERSPROJECT_H #define MSBUILDFILTERSPROJECT_H #include "msbuild/msbuildproject.h" #include #include namespace qbs { class MSBuildFilter; class MSBuildFiltersProject : public MSBuildProject { Q_OBJECT Q_DISABLE_COPY(MSBuildFiltersProject) public: explicit MSBuildFiltersProject(const GeneratableProductData &product, QObject *parent = nullptr); }; } // namespace qbs #endif // MSBUILDFILTERSPROJECT_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildqbsgenerateproject.cpp000066400000000000000000000060671347155106100301270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildqbsgenerateproject.h" #include "msbuild/msbuildimport.h" #include "msbuild/msbuildproperty.h" #include "msbuild/msbuildpropertygroup.h" #include #include #include namespace qbs { MSBuildQbsGenerateProject::MSBuildQbsGenerateProject( const GeneratableProject &project, const Internal::VisualStudioVersionInfo &versionInfo, VisualStudioGenerator *parent) : MSBuildTargetProject(project, versionInfo, parent) { const auto cppDefaultProps = new MSBuildImport(this); cppDefaultProps->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.Default.props")); const auto group = new MSBuildPropertyGroup(this); group->setLabel(QStringLiteral("Configuration")); group->appendProperty(QStringLiteral("PlatformToolset"), versionInfo.platformToolsetVersion()); group->appendProperty(QStringLiteral("ConfigurationType"), QStringLiteral("Makefile")); const auto params = Internal::shellQuote(project.commandLine(), Internal::HostOsInfo::HostOsWindows); group->appendProperty(QStringLiteral("NMakeBuildCommandLine"), QStringLiteral("$(QbsGenerateCommandLine) ") + params); const auto cppProps = new MSBuildImport(this); cppProps->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.props")); const auto import = new MSBuildImport(this); import->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.targets")); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildqbsgenerateproject.h000066400000000000000000000041241347155106100275640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDQBSGENERATEPROJECT_H #define MSBUILDQBSGENERATEPROJECT_H #include "msbuildtargetproject.h" #include #include namespace qbs { class MSBuildQbsGenerateProject : public MSBuildTargetProject { Q_OBJECT Q_DISABLE_COPY(MSBuildQbsGenerateProject) public: MSBuildQbsGenerateProject(const GeneratableProject &project, const Internal::VisualStudioVersionInfo &versionInfo, VisualStudioGenerator *parent = nullptr); }; } // namespace qbs #endif // MSBUILDQBSGENERATEPROJECT_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildqbsproductproject.cpp000066400000000000000000000501471347155106100300130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildqbsproductproject.h" #include "msbuild/msbuildimport.h" #include "msbuild/msbuildimportgroup.h" #include "msbuild/msbuilditemdefinitiongroup.h" #include "msbuild/msbuilditemgroup.h" #include "msbuild/msbuilditemmetadata.h" #include "msbuild/msbuildproperty.h" #include "msbuild/msbuildpropertygroup.h" #include "msbuild/items/msbuildclcompile.h" #include "msbuild/items/msbuildclinclude.h" #include "msbuild/items/msbuildlink.h" #include "msbuild/items/msbuildnone.h" #include "msbuildutils.h" #include "visualstudiogenerator.h" #include #include #include #include #include #include #include namespace qbs { using namespace Internal; MSBuildQbsProductProject::MSBuildQbsProductProject( const GeneratableProject &project, const GeneratableProductData &product, const Internal::VisualStudioVersionInfo &versionInfo, VisualStudioGenerator *parent) : MSBuildTargetProject(project, versionInfo, parent) { Q_ASSERT(project.projects.size() == project.commandLines.size()); Q_ASSERT(project.projects.size() == product.data.size()); const int count = std::max(project.projects.size(), product.data.size()); globalsPropertyGroup()->appendProperty(QStringLiteral("QbsProductName"), product.name()); const auto cppDefaultProps = new MSBuildImport(this); cppDefaultProps->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.Default.props")); for (int i = 0; i < count; ++i) { addConfiguration( project, project.projects.values().at(i), product.data.values().at(i), project.commandLines.values().at(i)); } const auto cppProps = new MSBuildImport(this); cppProps->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.props")); for (int i = 0; i < count; ++i) addItemDefGroup(project.projects.values().at(i), product.data.values().at(i)); addFiles(project, product); } static QString productTargetPath(const qbs::ProductData &productData) { const QString fullPath = productData.targetExecutable(); if (!fullPath.isEmpty()) return QFileInfo(fullPath).absolutePath(); return productData.properties().value(QStringLiteral("buildDirectory")).toString(); } static bool listEnvironmentVariableContainsValue(const QString &environmentVariable, const QString &value) { return environmentVariable.contains(QLatin1Char(';') + value + QLatin1Char(';')) || environmentVariable.startsWith(value + QLatin1Char(';')) || environmentVariable.endsWith(QLatin1Char(';') + value); } void MSBuildQbsProductProject::addConfiguration(const GeneratableProject &project, const Project &buildTask, const ProductData &productData, const QStringList &buildConfigurationCommandLine) { const auto targetDir = Internal::PathUtils::toNativeSeparators( productTargetPath(productData), Internal::HostOsInfo::HostOsWindows); auto configurationDir = Internal::PathUtils::toNativeSeparators( project.baseBuildDirectory().absolutePath() + QLatin1Char('\\') + MSBuildUtils::configurationName(buildTask), Internal::HostOsInfo::HostOsWindows); auto relativeTargetDir = targetDir; if (targetDir.startsWith(configurationDir)) relativeTargetDir = QStringLiteral("$(SolutionDir)$(Configuration)") + relativeTargetDir.mid(configurationDir.size()); const auto properties = productData.moduleProperties(); const bool debugBuild = properties.getModuleProperty(StringConstants::qbsModule(), QStringLiteral("debugInformation")) .toBool(); const auto includePaths = QStringList() << properties.getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("includePaths")) << properties.getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("systemIncludePaths")); const auto cppDefines = properties .getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("defines")); const auto sep = Internal::HostOsInfo::pathListSeparator(Internal::HostOsInfo::HostOsWindows); const auto propertyGroup1 = new MSBuildPropertyGroup(this); propertyGroup1->setCondition(MSBuildUtils::buildTaskCondition(buildTask)); propertyGroup1->setLabel(QStringLiteral("Configuration")); propertyGroup1->appendProperty(QStringLiteral("UseDebugLibraries"), debugBuild ? QStringLiteral("true") : QStringLiteral("false")); // General - General // We need a trailing backslash for $(OutDir); See also the VS documentation: // https://docs.microsoft.com/en-us/cpp/ide/common-macros-for-build-commands-and-properties propertyGroup1->appendProperty(QStringLiteral("OutDir"), relativeTargetDir + QLatin1Char('\\')); propertyGroup1->appendProperty(QStringLiteral("TargetName"), productData.targetName()); propertyGroup1->appendProperty(QStringLiteral("PlatformToolset"), versionInfo().platformToolsetVersion()); propertyGroup1->appendProperty(QStringLiteral("ConfigurationType"), QStringLiteral("Makefile")); // VS possible values: Unicode|MultiByte|NotSet propertyGroup1->appendProperty(QStringLiteral("CharacterSet"), properties.getModuleProperty(QStringLiteral("cpp"), QStringLiteral("windowsApiCharacterSet")) == QStringLiteral("unicode") ? QStringLiteral("MultiByte") : QStringLiteral("NotSet")); // Debugging propertyGroup1->appendProperty(QStringLiteral("DebuggerFlavor"), QStringLiteral("WindowsLocalDebugger")); propertyGroup1->appendProperty(QStringLiteral("LocalDebuggerCommand"), QStringLiteral("$(OutDir)$(TargetName)$(TargetExt)")); propertyGroup1->appendProperty(QStringLiteral("LocalDebuggerWorkingDirectory"), QStringLiteral("$(OutDir)")); auto env = buildTask.getRunEnvironment(productData, project.installOptions, QProcessEnvironment(), QStringList(), nullptr) .runEnvironment(); if (!env.isEmpty()) { const auto systemEnv = QProcessEnvironment::systemEnvironment(); for (const auto &key : systemEnv.keys()) { if (!env.contains(key)) continue; // Don't duplicate keys from the system environment if (env.value(key) == systemEnv.value(key)) { env.remove(key); continue; } // Cleverly concatenate list variables to avoid duplicating system environment const QString systemValue = systemEnv.value(key); QString overriddenValue = env.value(key); if (listEnvironmentVariableContainsValue(overriddenValue, systemValue)) { env.insert(key, overriddenValue.replace(systemValue, QLatin1Char('%') + key + QLatin1Char('%'))); } QString installRoot = project.installOptions.installRoot(); if (!installRoot.isEmpty()) { if (listEnvironmentVariableContainsValue(overriddenValue, installRoot)) { env.insert(key, overriddenValue.replace(installRoot, QStringLiteral("$(QbsInstallRoot)"))); } } else { installRoot = Internal::PathUtils::toNativeSeparators( QDir(buildTask.projectData().buildDirectory()).absoluteFilePath( project.installOptions.defaultInstallRoot()), Internal::HostOsInfo::HostOsWindows); if (listEnvironmentVariableContainsValue(overriddenValue, installRoot)) { env.insert(key, overriddenValue.replace(installRoot, QStringLiteral("$(SolutionDir)$(Configuration)\\install-root"))); } } } propertyGroup1->appendProperty(QStringLiteral("LocalDebuggerEnvironment"), env.toStringList().join(QLatin1String("\n"))); } // NMake - General // Skip configuration name, that's handled in qbs-shared.props const auto params = Internal::shellQuote(buildConfigurationCommandLine.mid(1), Internal::HostOsInfo::HostOsWindows); propertyGroup1->appendProperty(QStringLiteral("NMakeBuildCommandLine"), QStringLiteral("$(QbsBuildCommandLine) ") + params); propertyGroup1->appendProperty(QStringLiteral("NMakeReBuildCommandLine"), QStringLiteral("$(QbsReBuildCommandLine) ") + params); propertyGroup1->appendProperty(QStringLiteral("NMakeCleanCommandLine"), QStringLiteral("$(QbsCleanCommandLine) ") + params); propertyGroup1->appendProperty(QStringLiteral("NMakeOutput"), QStringLiteral("$(OutDir)$(TargetName)$(TargetExt)")); // NMake - IntelliSense propertyGroup1->appendProperty(QStringLiteral("NMakePreprocessorDefinitions"), cppDefines.join(sep)); propertyGroup1->appendProperty(QStringLiteral("NMakeIncludeSearchPath"), includePaths.join(sep)); } static QString subsystemVersion(const QString &version) { const auto v = Version::fromString(version); return QStringLiteral("%1.%2").arg( QString::number(v.majorVersion()), QString::number(v.minorVersion()).rightJustified(2, QLatin1Char('0'))); } void MSBuildQbsProductProject::addItemDefGroup(const Project &project, const ProductData &productData) { const auto properties = productData.moduleProperties(); const bool consoleApp = productData.properties().value(QStringLiteral("consoleApplication")) .toBool(); const bool debugBuild = properties.getModuleProperty(StringConstants::qbsModule(), QStringLiteral("debugInformation")) .toBool(); const auto optimizationLevel = properties.getModuleProperty(StringConstants::qbsModule(), QStringLiteral("optimization")) .toString(); const auto warningLevel = properties.getModuleProperty(StringConstants::qbsModule(), QStringLiteral("warningLevel")) .toString(); const auto includePaths = QStringList() << properties.getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("includePaths")) << properties.getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("systemIncludePaths")); const auto cppDefines = properties.getModulePropertiesAsStringList( QStringLiteral("cpp"), QStringLiteral("defines")); const auto sep = Internal::HostOsInfo::pathListSeparator(Internal::HostOsInfo::HostOsWindows); const auto itemDefGroup = new MSBuildItemDefinitionGroup(this); itemDefGroup->setCondition(MSBuildUtils::buildTaskCondition(project)); const auto compile = new MSBuildClCompile(itemDefGroup); // C++ - General compile->appendProperty(QStringLiteral("AdditionalIncludeDirectories"), includePaths.join(sep) + sep + QStringLiteral("%(AdditionalIncludeDirectories)")); if (warningLevel == QStringLiteral("none")) compile->appendProperty(QStringLiteral("WarningLevel"), QStringLiteral("TurnOffAllWarnings")); else if (warningLevel == QStringLiteral("all")) compile->appendProperty(QStringLiteral("WarningLevel"), QStringLiteral("EnableAllWarnings")); else compile->appendProperty(QStringLiteral("WarningLevel"), QStringLiteral("Level3")); // this is VS default. // C++ - Optimization compile->appendProperty(QStringLiteral("Optimization"), optimizationLevel == QStringLiteral("none") ? QStringLiteral("Disabled") : QStringLiteral("MaxSpeed")); // C++ - Preprocessor compile->appendProperty(QStringLiteral("PreprocessorDefinitions"), cppDefines.join(sep) + sep + QStringLiteral("%(PreprocessorDefinitions)")); // C++ - Code Generation compile->appendProperty(QStringLiteral("RuntimeLibrary"), debugBuild ? QStringLiteral("MultiThreadedDebugDLL") : QStringLiteral("MultiThreadedDLL")); const auto link = new MSBuildLink(itemDefGroup); // Linker - General link->appendProperty(QStringLiteral("AdditionalLibraryDirectories"), properties.getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("libraryPaths")).join(sep)); // Linker - Input link->appendProperty(QStringLiteral("AdditionalDependencies"), properties.getModulePropertiesAsStringList(QStringLiteral("cpp"), QStringLiteral("staticLibraries")).join(sep) + sep + QStringLiteral("%(AdditionalDependencies)")); // Linker - Debugging link->appendProperty(QStringLiteral("GenerateDebugInformation"), debugBuild ? QStringLiteral("true") : QStringLiteral("false")); // Linker - System link->appendProperty(QStringLiteral("SubSystem"), consoleApp ? QStringLiteral("Console") : QStringLiteral("Windows")); const auto subsysVersion = properties.getModuleProperty( QStringLiteral("cpp"), QStringLiteral("minimumWindowsVersion")).toString(); if (!subsysVersion.isEmpty()) link->appendProperty(QStringLiteral("MinimumRequiredVersion"), subsystemVersion(subsysVersion)); // Linker - Optimization link->appendProperty(QStringLiteral("OptimizeReferences"), debugBuild ? QStringLiteral("false") : QStringLiteral("true")); } static MSBuildFileItem *fileItemForFileTags(const QList &fileTags, IMSBuildItemGroup *parent = nullptr) { if (fileTags.contains(QStringLiteral("hpp"))) return new MSBuildClInclude(parent); if (fileTags.contains(QStringLiteral("c")) || fileTags.contains(QStringLiteral("cpp"))) return new MSBuildClCompile(parent); return new MSBuildNone(parent); } void MSBuildQbsProductProject::addFiles(const GeneratableProject &project, const GeneratableProductData &product) { const auto itemGroup = new MSBuildItemGroup(this); addQbsFile(project, product, itemGroup); std::map sourceFileNodes; std::map sourceFileEnabledConfigurations; // Create a ClCompile item for each source file, keeping track of which configurations that // file's containing group is enabled in QMapIterator productDataIt(product.data); while (productDataIt.hasNext()) { productDataIt.next(); for (const auto &group : productDataIt.value().groups()) { for (const auto &sourceArtifact : group.allSourceArtifacts()) { const auto filePath = sourceArtifact.filePath(); if (sourceFileNodes.find(filePath) == sourceFileNodes.end()) { sourceFileNodes.insert({ filePath, fileItemForFileTags(sourceArtifact.fileTags(), itemGroup) }); } auto fileItem = sourceFileNodes[filePath]; QString path = project.baseBuildDirectory().relativeFilePath(filePath); // The path still might not be relative (for example if the file item is // located on a different drive) if (QFileInfo(path).isRelative()) path = QStringLiteral("$(ProjectDir)") + path; fileItem->setFilePath(path); if (group.isEnabled()) sourceFileEnabledConfigurations[filePath] << productDataIt.key(); } } } // Add ExcludedFromBuild item metadata to each file for each configuration // where that file's containing group is disabled for (const auto &sourceFileNode : sourceFileNodes) { QMapIterator projIt(project.projects); while (projIt.hasNext()) { projIt.next(); if (!sourceFileEnabledConfigurations[sourceFileNode.first].contains(projIt.key())) { const auto metadata = new MSBuildItemMetadata( QStringLiteral("ExcludedFromBuild"), QStringLiteral("true"), sourceFileNode.second); metadata->setCondition(QStringLiteral("'$(Configuration)|$(Platform)'=='") + MSBuildUtils::fullName(projIt.value()) + QStringLiteral("'")); } } } const auto import = new MSBuildImport(this); import->setProject(QStringLiteral("$(VCTargetsPath)\\Microsoft.Cpp.targets")); } void MSBuildQbsProductProject::addQbsFile(const GeneratableProject &project, const GeneratableProductData &product, MSBuildItemGroup *itemGroup) { const auto fileItem = new MSBuildNone(itemGroup); QString path = project.baseBuildDirectory().relativeFilePath(product.location().filePath()); // The path still might not be relative (for example if the file item is // located on a different drive) if (QFileInfo(path).isRelative()) path = QStringLiteral("$(ProjectDir)") + path; fileItem->setFilePath(path); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildqbsproductproject.h000066400000000000000000000056161347155106100274610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDQBSPRODUCTPROJECT_H #define MSBUILDQBSPRODUCTPROJECT_H #include "msbuildtargetproject.h" #include #include #include namespace qbs { class MSBuildImportGroup; class MSBuildItemGroup; class MSBuildProperty; class VisualStudioGenerator; class MSBuildQbsProductProject : public MSBuildTargetProject { Q_OBJECT Q_DISABLE_COPY(MSBuildQbsProductProject) public: MSBuildQbsProductProject(const GeneratableProject &project, const GeneratableProductData &product, const Internal::VisualStudioVersionInfo &versionInfo, VisualStudioGenerator *parent = nullptr); private: using ProjectConfigurations = QHash>; void addConfiguration(const GeneratableProject &project, const Project &buildTask, const ProductData &productData, const QStringList &buildConfigurationCommandLine); void addItemDefGroup(const Project &project, const ProductData &productData); void addFiles(const GeneratableProject &project, const GeneratableProductData &product); void addQbsFile(const GeneratableProject &project, const GeneratableProductData &product, MSBuildItemGroup *itemGroup); }; } // namespace qbs #endif // MSBUILDQBSPRODUCTPROJECT_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildsharedsolutionpropertiesproject.cpp000066400000000000000000000161421347155106100330020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildsharedsolutionpropertiesproject.h" #include "msbuild/msbuildpropertygroup.h" #include #include #include namespace qbs { static QString qbsCommandLine(const GeneratableProject &project, const QString &subCommand, const QString &qbsSettingsDir, const Internal::VisualStudioVersionInfo &versionInfo) { auto addEnvironmentVariableArgument = [](Internal::CommandLine &cl, const QString &var, const QString &prefix = QString()) { cl.appendRawArgument(QStringLiteral("\"%1$(%2)\"").arg(prefix, var)); }; auto realSubCommand = subCommand; if (subCommand == QStringLiteral("rebuild")) realSubCommand = QStringLiteral("build"); // "path/to/qbs.exe" {build|clean} // --settings-dir "path/to/settings/directory/" // -f "path/to/project.qbs" -d "/build/directory/" // -p product_name [[configuration key:value]...] Internal::CommandLine commandLine; commandLine.setProgram(QStringLiteral("\"$(QbsExecutablePath)\""), true); commandLine.appendArgument(realSubCommand); if (!qbsSettingsDir.isEmpty()) { commandLine.appendArgument(QStringLiteral("--settings-dir")); addEnvironmentVariableArgument(commandLine, QStringLiteral("QbsSettingsDir")); } commandLine.appendArgument(QStringLiteral("-f")); addEnvironmentVariableArgument(commandLine, QStringLiteral("QbsProjectFile")); commandLine.appendArgument(QStringLiteral("-d")); addEnvironmentVariableArgument(commandLine, QStringLiteral("QbsBuildDir")); if (subCommand == QStringLiteral("generate")) { commandLine.appendArgument(QStringLiteral("-g")); commandLine.appendArgument(QStringLiteral("visualstudio%1") .arg(versionInfo.marketingVersion())); } else { commandLine.appendArgument(QStringLiteral("-p")); addEnvironmentVariableArgument(commandLine, QStringLiteral("QbsProductName")); commandLine.appendArgument(QStringLiteral("--wait-lock")); } if (realSubCommand == QStringLiteral("build") && !project.installOptions.installRoot().isEmpty()) { commandLine.appendArgument(QStringLiteral("--install-root")); addEnvironmentVariableArgument(commandLine, QStringLiteral("QbsInstallRoot")); } if (realSubCommand == QStringLiteral("build") && subCommand == QStringLiteral("rebuild")) { commandLine.appendArgument(QStringLiteral("--check-timestamps")); commandLine.appendArgument(QStringLiteral("--force-probe-execution")); } addEnvironmentVariableArgument(commandLine, QStringLiteral("Configuration"), QStringLiteral("config:")); return commandLine.toCommandLine(Internal::HostOsInfo::HostOsWindows); } MSBuildSharedSolutionPropertiesProject::MSBuildSharedSolutionPropertiesProject( const Internal::VisualStudioVersionInfo &versionInfo, const GeneratableProject &project, const QFileInfo &qbsExecutable, const QString &qbsSettingsDir) { setDefaultTargets(QStringLiteral("Build")); setToolsVersion(versionInfo.toolsVersion()); const auto group = new MSBuildPropertyGroup(this); group->setLabel(QStringLiteral("UserMacros")); // Order's important here... a variable must be listed before one that uses it group->appendProperty(QStringLiteral("QbsExecutablePath"), QStringLiteral("$(QbsExecutableDir)") + qbsExecutable.fileName()); if (!project.installOptions.installRoot().isEmpty()) { group->appendProperty(QStringLiteral("QbsInstallRoot"), Internal::PathUtils::toNativeSeparators( project.installOptions.installRoot(), Internal::HostOsInfo::HostOsWindows)); } group->appendProperty(QStringLiteral("QbsProjectFile"), QStringLiteral("$(QbsProjectDir)") + project.filePath().fileName()); // Trailing '.' is not a typo. It prevents the trailing slash from combining with the closing // quote to form an escape sequence. Unfortunately, Visual Studio expands variables *before* // passing them to the underlying command shell, so there's not much we can do with regard to // doing it "properly". Setting environment variables through MSBuild and using them in place // of actual arguments does not work either, as Visual Studio apparently expands the environment // variables as well, before passing them to the underlying shell. group->appendProperty(QStringLiteral("QbsBuildDir"), QStringLiteral("$(SolutionDir).")); group->appendProperty(QStringLiteral("QbsBuildCommandLine"), qbsCommandLine(project, QStringLiteral("build"), qbsSettingsDir, versionInfo)); group->appendProperty(QStringLiteral("QbsReBuildCommandLine"), qbsCommandLine(project, QStringLiteral("rebuild"), qbsSettingsDir, versionInfo)); group->appendProperty(QStringLiteral("QbsCleanCommandLine"), qbsCommandLine(project, QStringLiteral("clean"), qbsSettingsDir, versionInfo)); group->appendProperty(QStringLiteral("QbsGenerateCommandLine"), qbsCommandLine(project, QStringLiteral("generate"), qbsSettingsDir, versionInfo)); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildsharedsolutionpropertiesproject.h000066400000000000000000000043161347155106100324470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDSHAREDSOLUTIONPROPERTIESPROJECT_H #define MSBUILDSHAREDSOLUTIONPROPERTIESPROJECT_H #include "msbuild/msbuildproject.h" #include #include namespace qbs { class MSBuildSharedSolutionPropertiesProject : public MSBuildProject { Q_OBJECT Q_DISABLE_COPY(MSBuildSharedSolutionPropertiesProject) public: MSBuildSharedSolutionPropertiesProject(const Internal::VisualStudioVersionInfo &versionInfo, const GeneratableProject &project, const QFileInfo &qbsExecutable, const QString &qbsSettingsDir); }; } // namespace qbs #endif // MSBUILDSHAREDSOLUTIONPROPERTIESPROJECT_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildsolutionpropertiesproject.cpp000066400000000000000000000056351347155106100316200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildsolutionpropertiesproject.h" #include "msbuild/msbuildpropertygroup.h" #include #include namespace qbs { MSBuildSolutionPropertiesProject::MSBuildSolutionPropertiesProject( const Internal::VisualStudioVersionInfo &versionInfo, const GeneratableProject &project, const QFileInfo &qbsExecutable, const QString &qbsSettingsDir) { setDefaultTargets(QStringLiteral("Build")); setToolsVersion(versionInfo.toolsVersion()); const auto group = new MSBuildPropertyGroup(this); group->setLabel(QStringLiteral("UserMacros")); static const auto win = Internal::HostOsInfo::HostOsWindows; group->appendProperty(QStringLiteral("QbsExecutableDir"), Internal::PathUtils::toNativeSeparators(qbsExecutable.path(), win) + Internal::HostOsInfo::pathSeparator(win)); group->appendProperty(QStringLiteral("QbsProjectDir"), Internal::PathUtils::toNativeSeparators(project.filePath().path(), win) + Internal::HostOsInfo::pathSeparator(win)); if (!qbsSettingsDir.isEmpty()) { group->appendProperty(QStringLiteral("QbsSettingsDir"), Internal::PathUtils::toNativeSeparators(qbsSettingsDir, win) + Internal::HostOsInfo::pathSeparator(win) + QLatin1Char('.')); } } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildsolutionpropertiesproject.h000066400000000000000000000043421347155106100312570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDSOLUTIONPROPERTIESPROJECT_H #define MSBUILDSOLUTIONPROPERTIESPROJECT_H #include "msbuild/msbuildproject.h" #include #include #include namespace qbs { class MSBuildSolutionPropertiesProject : public MSBuildProject { Q_OBJECT Q_DISABLE_COPY(MSBuildSolutionPropertiesProject) public: MSBuildSolutionPropertiesProject(const Internal::VisualStudioVersionInfo &versionInfo, const GeneratableProject &project, const QFileInfo &qbsExecutable, const QString &qbsSettingsDir); }; } // namespace qbs #endif // MSBUILDSOLUTIONPROPERTIESPROJECT_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildtargetproject.cpp000066400000000000000000000117131347155106100271070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildtargetproject.h" #include "msbuildutils.h" #include "visualstudiogenerator.h" #include "msbuild/msbuildimport.h" #include "msbuild/msbuildimportgroup.h" #include "msbuild/msbuilditem.h" #include "msbuild/msbuilditemgroup.h" #include "msbuild/msbuildproperty.h" #include "msbuild/msbuildpropertygroup.h" namespace qbs { class MSBuildTargetProjectPrivate { public: MSBuildTargetProjectPrivate(const Internal::VisualStudioVersionInfo &versionInfo) : versionInfo(versionInfo) {} MSBuildPropertyGroup *globalsPropertyGroup; MSBuildProperty *projectGuidProperty; const Internal::VisualStudioVersionInfo &versionInfo; }; MSBuildTargetProject::MSBuildTargetProject(const GeneratableProject &project, const Internal::VisualStudioVersionInfo &versionInfo, VisualStudioGenerator *parent) : MSBuildProject(parent) , d(new MSBuildTargetProjectPrivate(versionInfo)) { setDefaultTargets(QStringLiteral("Build")); setToolsVersion(versionInfo.toolsVersion()); const auto projectConfigurationsGroup = new MSBuildItemGroup(this); projectConfigurationsGroup->setLabel(QStringLiteral("ProjectConfigurations")); QMapIterator it(project.projects); while (it.hasNext()) { it.next(); const auto item = new MSBuildItem(QStringLiteral("ProjectConfiguration"), projectConfigurationsGroup); item->setInclude(MSBuildUtils::fullName(it.value())); item->appendProperty(QStringLiteral("Configuration"), it.key()); item->appendProperty(QStringLiteral("Platform"), MSBuildUtils::platform(it.value())); } d->globalsPropertyGroup = new MSBuildPropertyGroup(this); d->globalsPropertyGroup->setLabel(QStringLiteral("Globals")); d->projectGuidProperty = new MSBuildProperty(QStringLiteral("ProjectGuid"), QUuid::createUuid().toString(), d->globalsPropertyGroup); // Trigger creation of the property sheets ImportGroup propertySheetsImportGroup(); } MSBuildTargetProject::~MSBuildTargetProject() { } const Internal::VisualStudioVersionInfo &MSBuildTargetProject::versionInfo() const { return d->versionInfo; } QUuid MSBuildTargetProject::guid() const { return {d->projectGuidProperty->value().toString()}; } void MSBuildTargetProject::setGuid(const QUuid &guid) { d->projectGuidProperty->setValue(guid.toString()); } MSBuildPropertyGroup *MSBuildTargetProject::globalsPropertyGroup() { return d->globalsPropertyGroup; } MSBuildImportGroup *MSBuildTargetProject::propertySheetsImportGroup() { MSBuildImportGroup *importGroup = nullptr; for (const auto &child : children()) { if (auto group = qobject_cast(child)) { if (group->label() == QStringLiteral("PropertySheets")) { importGroup = group; break; } } } if (!importGroup) { importGroup = new MSBuildImportGroup(this); importGroup->setLabel(QStringLiteral("PropertySheets")); } return importGroup; } void MSBuildTargetProject::appendPropertySheet(const QString &path, bool optional) { const auto import = new MSBuildImport(propertySheetsImportGroup()); import->setProject(path); if (optional) import->setCondition(QStringLiteral("Exists('%1')").arg(path)); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildtargetproject.h000066400000000000000000000050711347155106100265540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDTARGETPROJECT_H #define MSBUILDTARGETPROJECT_H #include "msbuild/msbuildproject.h" #include #include namespace qbs { class MSBuildImportGroup; class MSBuildPropertyGroup; class MSBuildTargetProjectPrivate; class VisualStudioGenerator; class MSBuildTargetProject : public MSBuildProject { Q_OBJECT Q_DISABLE_COPY(MSBuildTargetProject) protected: MSBuildTargetProject(const GeneratableProject &project, const Internal::VisualStudioVersionInfo &versionInfo, VisualStudioGenerator *parent = nullptr); public: ~MSBuildTargetProject(); const Internal::VisualStudioVersionInfo &versionInfo() const; QUuid guid() const; void setGuid(const QUuid &guid); MSBuildPropertyGroup *globalsPropertyGroup(); MSBuildImportGroup *propertySheetsImportGroup(); void appendPropertySheet(const QString &path, bool optional = false); private: std::unique_ptr d; }; } // namespace qbs #endif // MSBUILDTARGETPROJECT_H qbs-src-1.13.1/src/plugins/generator/visualstudio/msbuildutils.h000066400000000000000000000102401347155106100250310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSBUILDUTILS_H #define MSBUILDUTILS_H #include namespace qbs { class MSBuildUtils { public: static QString _qbsArchitecture(const qbs::Project &project) { return project.projectConfiguration() .value(QStringLiteral("qbs")).toMap() .value(QStringLiteral("architecture")).toString(); } static const QString visualStudioArchitectureName(const QString &qbsArch, bool useDisplayName) { if (qbsArch == QStringLiteral("x86") && useDisplayName) return qbsArch; // map of qbs architecture names to MSBuild architecture names static const QMap map { {QStringLiteral("x86"), QStringLiteral("Win32")}, {QStringLiteral("x86_64"), QStringLiteral("x64")}, {QStringLiteral("ia64"), QStringLiteral("Itanium")}, {QStringLiteral("arm"), QStringLiteral("ARM")}, {QStringLiteral("arm64"), QStringLiteral("ARM64")} }; return map[qbsArch]; } static QString configurationName(const qbs::Project &project) { return project.projectConfiguration() .value(QStringLiteral("qbs")).toMap() .value(QStringLiteral("configurationName")).toString(); } static QString displayPlatform(const qbs::Project &project) { const auto architecture = _qbsArchitecture(project); auto displayPlatform = visualStudioArchitectureName(architecture, true); if (displayPlatform.isEmpty()) displayPlatform = architecture; return displayPlatform; } static QString platform(const qbs::Project &project) { const auto architecture = _qbsArchitecture(project); auto platform = visualStudioArchitectureName(architecture, false); if (platform.isEmpty()) { qWarning() << "WARNING: Unsupported architecture \"" << architecture << "\"; using \"Win32\" platform."; platform = QStringLiteral("Win32"); } return platform; } static QString fullDisplayName(const qbs::Project &project) { return QStringLiteral("%1|%2") .arg(configurationName(project)) .arg(displayPlatform(project)); } static QString fullName(const qbs::Project &project) { return QStringLiteral("%1|%2").arg(configurationName(project)).arg(platform(project)); } static QString buildTaskCondition(const Project &buildTask) { return QStringLiteral("'$(Configuration)|$(Platform)'=='") + MSBuildUtils::fullName(buildTask) + QStringLiteral("'"); } }; } // namespace qbs #endif // MSBUILDUTILS_H qbs-src-1.13.1/src/plugins/generator/visualstudio/solution/000077500000000000000000000000001347155106100240175ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/generator/visualstudio/solution/ivisualstudiosolutionproject.cpp000066400000000000000000000043351347155106100326200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "ivisualstudiosolutionproject.h" namespace qbs { class IVisualStudioSolutionProjectPrivate { public: QUuid guid = QUuid::createUuid(); QString name; QString filePath; }; IVisualStudioSolutionProject::IVisualStudioSolutionProject(QObject *parent) : QObject(parent) , d(new IVisualStudioSolutionProjectPrivate) { } IVisualStudioSolutionProject::~IVisualStudioSolutionProject() { } QUuid IVisualStudioSolutionProject::guid() const { return d->guid; } void IVisualStudioSolutionProject::setGuid(const QUuid &guid) { d->guid = guid; } QString IVisualStudioSolutionProject::name() const { return d->name; } void IVisualStudioSolutionProject::setName(const QString &name) { d->name = name; } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/solution/ivisualstudiosolutionproject.h000066400000000000000000000043421347155106100322630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef IVISUALSTUDIOSOLUTIONPROJECT_H #define IVISUALSTUDIOSOLUTIONPROJECT_H #include #include #include #include namespace qbs { class IVisualStudioSolutionProjectPrivate; class IVisualStudioSolutionProject : public QObject { Q_OBJECT protected: explicit IVisualStudioSolutionProject(QObject *parent = nullptr); public: virtual ~IVisualStudioSolutionProject(); virtual QUuid projectTypeGuid() const = 0; QUuid guid() const; void setGuid(const QUuid &guid); virtual QString name() const; void setName(const QString &name); private: std::unique_ptr d; }; } // namespace qbs #endif // IVISUALSTUDIOSOLUTIONPROJECT_H qbs-src-1.13.1/src/plugins/generator/visualstudio/solution/visualstudiosolution.cpp000066400000000000000000000101101347155106100310440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "visualstudiosolution.h" #include "visualstudiosolutionfileproject.h" #include "visualstudiosolutionfolderproject.h" #include #include namespace qbs { class VisualStudioSolutionPrivate { public: VisualStudioSolutionPrivate(const Internal::VisualStudioVersionInfo &versionInfo) : versionInfo(versionInfo) { } const Internal::VisualStudioVersionInfo versionInfo; QList projects; QMap> dependencies; QList globalSections; }; VisualStudioSolution::VisualStudioSolution(const Internal::VisualStudioVersionInfo &versionInfo, QObject *parent) : QObject(parent) , d(new VisualStudioSolutionPrivate(versionInfo)) { } VisualStudioSolution::~VisualStudioSolution() { } Internal::VisualStudioVersionInfo VisualStudioSolution::versionInfo() const { return d->versionInfo; } QList VisualStudioSolution::projects() const { return d->projects; } QList VisualStudioSolution::fileProjects() const { QList list; for (const auto &project : d->projects) if (auto fileProject = qobject_cast(project)) list.push_back(fileProject); return list; } QList VisualStudioSolution::folderProjects() const { QList list; for (const auto &project : d->projects) if (auto folderProject = qobject_cast(project)) list.push_back(folderProject); return list; } void VisualStudioSolution::appendProject(IVisualStudioSolutionProject *project) { d->projects.push_back(project); } QList VisualStudioSolution::dependencies( VisualStudioSolutionFileProject *project) const { return d->dependencies.value(project); } void VisualStudioSolution::addDependency(VisualStudioSolutionFileProject *project, VisualStudioSolutionFileProject *dependency) { d->dependencies[project].push_back(dependency); } QList VisualStudioSolution::globalSections() const { return d->globalSections; } void VisualStudioSolution::appendGlobalSection(VisualStudioSolutionGlobalSection *globalSection) { d->globalSections.push_back(globalSection); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/solution/visualstudiosolution.h000066400000000000000000000061531347155106100305250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef VISUALSTUDIOSOLUTION_H #define VISUALSTUDIOSOLUTION_H #include #include namespace qbs { namespace Internal { class VisualStudioVersionInfo; } class MSBuildProject; class IVisualStudioSolutionProject; class VisualStudioSolutionFileProject; class VisualStudioSolutionFolderProject; class VisualStudioSolutionGlobalSection; class VisualStudioSolutionPrivate; class VisualStudioSolution : public QObject { Q_OBJECT Q_DISABLE_COPY(VisualStudioSolution) public: explicit VisualStudioSolution(const Internal::VisualStudioVersionInfo &versionInfo, QObject *parent = nullptr); ~VisualStudioSolution(); Internal::VisualStudioVersionInfo versionInfo() const; QList projects() const; QList fileProjects() const; QList folderProjects() const; void appendProject(IVisualStudioSolutionProject *project); void removeProject(const IVisualStudioSolutionProject *project); void clearProjects(); QList dependencies( VisualStudioSolutionFileProject *project) const; void addDependency(VisualStudioSolutionFileProject *project, VisualStudioSolutionFileProject *dependency); QList globalSections() const; void appendGlobalSection(VisualStudioSolutionGlobalSection *globalSection); private: void addDefaultGlobalSections(); std::unique_ptr d; }; } // namespace qbs #endif // VISUALSTUDIOSOLUTION_H qbs-src-1.13.1/src/plugins/generator/visualstudio/solution/visualstudiosolutionfileproject.cpp000066400000000000000000000051261347155106100333060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "visualstudiosolutionfileproject.h" #include namespace qbs { class VisualStudioSolutionFileProjectPrivate { public: QString filePath; }; VisualStudioSolutionFileProject::VisualStudioSolutionFileProject(const QString &filePath, QObject *parent) : IVisualStudioSolutionProject(parent) , d(new VisualStudioSolutionFileProjectPrivate) { setFilePath(filePath); } VisualStudioSolutionFileProject::~VisualStudioSolutionFileProject() { } QString VisualStudioSolutionFileProject::name() const { const auto projectName = IVisualStudioSolutionProject::name(); if (projectName.isEmpty()) return QFileInfo(filePath()).baseName(); return projectName; } QUuid VisualStudioSolutionFileProject::projectTypeGuid() const { return QStringLiteral("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"); // C++ } QString VisualStudioSolutionFileProject::filePath() const { return d->filePath; } void VisualStudioSolutionFileProject::setFilePath(const QString &filePath) { d->filePath = filePath; } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/solution/visualstudiosolutionfileproject.h000066400000000000000000000043571347155106100327600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef VISUALSTUDIOSOLUTIONFILEPROJECT_H #define VISUALSTUDIOSOLUTIONFILEPROJECT_H #include #include "ivisualstudiosolutionproject.h" #include namespace qbs { class VisualStudioSolutionFileProjectPrivate; class VisualStudioSolutionFileProject : public IVisualStudioSolutionProject { Q_OBJECT public: explicit VisualStudioSolutionFileProject(const QString &filePath, QObject *parent = nullptr); ~VisualStudioSolutionFileProject(); QString name() const override; QString filePath() const; void setFilePath(const QString &filePath); QUuid projectTypeGuid() const override; private: std::unique_ptr d; }; } // namespace qbs #endif // VISUALSTUDIOSOLUTIONFILEPROJECT_H qbs-src-1.13.1/src/plugins/generator/visualstudio/solution/visualstudiosolutionfolderproject.cpp000066400000000000000000000035531347155106100336440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "visualstudiosolutionfolderproject.h" #include namespace qbs { VisualStudioSolutionFolderProject::VisualStudioSolutionFolderProject(QObject *parent) : IVisualStudioSolutionProject(parent) { } QUuid VisualStudioSolutionFolderProject::projectTypeGuid() const { return QStringLiteral("{2150E333-8FDC-42A3-9474-1A3956D46DE8}"); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/solution/visualstudiosolutionfolderproject.h000066400000000000000000000036611347155106100333110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef VISUALSTUDIOSOLUTIONFOLDERPROJECT_H #define VISUALSTUDIOSOLUTIONFOLDERPROJECT_H #include #include "ivisualstudiosolutionproject.h" namespace qbs { class VisualStudioSolutionFolderProject : public IVisualStudioSolutionProject { Q_OBJECT public: explicit VisualStudioSolutionFolderProject(QObject *parent); QUuid projectTypeGuid() const override; }; } // namespace qbs #endif // VISUALSTUDIOSOLUTIONFOLDERPROJECT_H qbs-src-1.13.1/src/plugins/generator/visualstudio/solution/visualstudiosolutionglobalsection.cpp000066400000000000000000000053061347155106100336250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "visualstudiosolutionglobalsection.h" #include #include namespace qbs { class VisualStudioSolutionGlobalSectionPrivate { public: QString name; std::vector> properties; bool post = false; }; VisualStudioSolutionGlobalSection::VisualStudioSolutionGlobalSection(const QString &name, QObject *parent) : QObject(parent) , d(new VisualStudioSolutionGlobalSectionPrivate) { setName(name); } VisualStudioSolutionGlobalSection::~VisualStudioSolutionGlobalSection() { } QString VisualStudioSolutionGlobalSection::name() const { return d->name; } void VisualStudioSolutionGlobalSection::setName(const QString &name) { d->name = name; } bool VisualStudioSolutionGlobalSection::isPost() const { return d->post; } void VisualStudioSolutionGlobalSection::setPost(bool post) { d->post = post; } std::vector > VisualStudioSolutionGlobalSection::properties() const { return d->properties; } void VisualStudioSolutionGlobalSection::appendProperty(const QString &key, const QString &value) { d->properties.push_back({ key, value }); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/solution/visualstudiosolutionglobalsection.h000066400000000000000000000045221347155106100332710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef VISUALSTUDIOSOLUTIONGLOBALSECTION_H #define VISUALSTUDIOSOLUTIONGLOBALSECTION_H #include #include namespace qbs { class VisualStudioSolutionGlobalSectionPrivate; class VisualStudioSolutionGlobalSection : public QObject { Q_OBJECT Q_DISABLE_COPY(VisualStudioSolutionGlobalSection) public: explicit VisualStudioSolutionGlobalSection(const QString &name, QObject *parent = nullptr); ~VisualStudioSolutionGlobalSection(); QString name() const; void setName(const QString &name); bool isPost() const; void setPost(bool post); std::vector > properties() const; void appendProperty(const QString &key, const QString &value); private: std::unique_ptr d; }; } // namespace qbs #endif // VISUALSTUDIOSOLUTIONGLOBALSECTION_H qbs-src-1.13.1/src/plugins/generator/visualstudio/visualstudio.pro000066400000000000000000000061741347155106100254300ustar00rootroot00000000000000include(../../plugins.pri) include(../../../shared/json/json.pri) TARGET = visualstudiogenerator QT = core HEADERS += \ $$PWD/msbuildfiltersproject.h \ $$PWD/msbuildqbsgenerateproject.h \ $$PWD/msbuildqbsproductproject.h \ $$PWD/msbuildsharedsolutionpropertiesproject.h \ $$PWD/msbuildsolutionpropertiesproject.h \ $$PWD/msbuildtargetproject.h \ $$PWD/msbuildutils.h \ $$PWD/visualstudiogenerator.h \ $$PWD/visualstudioguidpool.h SOURCES += \ $$PWD/msbuildfiltersproject.cpp \ $$PWD/msbuildqbsgenerateproject.cpp \ $$PWD/msbuildqbsproductproject.cpp \ $$PWD/msbuildsharedsolutionpropertiesproject.cpp \ $$PWD/msbuildsolutionpropertiesproject.cpp \ $$PWD/msbuildtargetproject.cpp \ $$PWD/visualstudiogenerator.cpp \ $$PWD/visualstudiogeneratorplugin.cpp \ $$PWD/visualstudioguidpool.cpp HEADERS += \ $$PWD/solution/ivisualstudiosolutionproject.h \ $$PWD/solution/visualstudiosolutionfileproject.h \ $$PWD/solution/visualstudiosolutionfolderproject.h \ $$PWD/solution/visualstudiosolution.h \ $$PWD/solution/visualstudiosolutionglobalsection.h \ SOURCES += \ $$PWD/solution/ivisualstudiosolutionproject.cpp \ $$PWD/solution/visualstudiosolutionfileproject.cpp \ $$PWD/solution/visualstudiosolutionfolderproject.cpp \ $$PWD/solution/visualstudiosolution.cpp \ $$PWD/solution/visualstudiosolutionglobalsection.cpp HEADERS += \ $$PWD/msbuild/imsbuildgroup.h \ $$PWD/msbuild/imsbuildnode.h \ $$PWD/msbuild/imsbuildnodevisitor.h \ $$PWD/msbuild/imsbuildproperty.h \ $$PWD/msbuild/msbuildimport.h \ $$PWD/msbuild/msbuildimportgroup.h \ $$PWD/msbuild/msbuilditem.h \ $$PWD/msbuild/msbuilditemdefinitiongroup.h \ $$PWD/msbuild/msbuilditemgroup.h \ $$PWD/msbuild/msbuilditemmetadata.h \ $$PWD/msbuild/msbuildproject.h \ $$PWD/msbuild/msbuildproperty.h \ $$PWD/msbuild/msbuildpropertygroup.h SOURCES += \ $$PWD/msbuild/imsbuildgroup.cpp \ $$PWD/msbuild/imsbuildnode.cpp \ $$PWD/msbuild/imsbuildproperty.cpp \ $$PWD/msbuild/msbuildimport.cpp \ $$PWD/msbuild/msbuildimportgroup.cpp \ $$PWD/msbuild/msbuilditem.cpp \ $$PWD/msbuild/msbuilditemdefinitiongroup.cpp \ $$PWD/msbuild/msbuilditemgroup.cpp \ $$PWD/msbuild/msbuilditemmetadata.cpp \ $$PWD/msbuild/msbuildproject.cpp \ $$PWD/msbuild/msbuildproperty.cpp \ $$PWD/msbuild/msbuildpropertygroup.cpp HEADERS += \ $$PWD/msbuild/items/msbuildclcompile.h \ $$PWD/msbuild/items/msbuildclinclude.h \ $$PWD/msbuild/items/msbuildfileitem.h \ $$PWD/msbuild/items/msbuildfilter.h \ $$PWD/msbuild/items/msbuildlink.h \ $$PWD/msbuild/items/msbuildnone.h SOURCES += \ $$PWD/msbuild/items/msbuildclcompile.cpp \ $$PWD/msbuild/items/msbuildclinclude.cpp \ $$PWD/msbuild/items/msbuildfileitem.cpp \ $$PWD/msbuild/items/msbuildfilter.cpp \ $$PWD/msbuild/items/msbuildlink.cpp \ $$PWD/msbuild/items/msbuildnone.cpp HEADERS += \ $$PWD/io/msbuildprojectwriter.h \ $$PWD/io/visualstudiosolutionwriter.h SOURCES += \ $$PWD/io/msbuildprojectwriter.cpp \ $$PWD/io/visualstudiosolutionwriter.cpp qbs-src-1.13.1/src/plugins/generator/visualstudio/visualstudio.qbs000066400000000000000000000064631347155106100254160ustar00rootroot00000000000000import qbs import "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { Depends { name: "qbsjson" } name: "visualstudiogenerator" files: ["visualstudiogeneratorplugin.cpp"] Group { name: "Visual Studio generator" files: [ "msbuildfiltersproject.cpp", "msbuildfiltersproject.h", "msbuildqbsgenerateproject.cpp", "msbuildqbsgenerateproject.h", "msbuildqbsproductproject.cpp", "msbuildqbsproductproject.h", "msbuildsharedsolutionpropertiesproject.cpp", "msbuildsharedsolutionpropertiesproject.h", "msbuildsolutionpropertiesproject.cpp", "msbuildsolutionpropertiesproject.h", "msbuildtargetproject.cpp", "msbuildtargetproject.h", "msbuildutils.h", "visualstudiogenerator.cpp", "visualstudiogenerator.h", "visualstudioguidpool.cpp", "visualstudioguidpool.h", ] } Group { name: "Solution Object Model" prefix: "solution/" files: [ "ivisualstudiosolutionproject.cpp", "ivisualstudiosolutionproject.h", "visualstudiosolutionfileproject.cpp", "visualstudiosolutionfileproject.h", "visualstudiosolutionfolderproject.cpp", "visualstudiosolutionfolderproject.h", "visualstudiosolution.cpp", "visualstudiosolution.h", "visualstudiosolutionglobalsection.cpp", "visualstudiosolutionglobalsection.h", ] } Group { name: "MSBuild Object Model" prefix: "msbuild/" files: [ "imsbuildgroup.cpp", "imsbuildgroup.h", "imsbuildnode.cpp", "imsbuildnode.h", "imsbuildnodevisitor.h", "imsbuildproperty.cpp", "imsbuildproperty.h", "msbuildimport.cpp", "msbuildimport.h", "msbuildimportgroup.cpp", "msbuildimportgroup.h", "msbuilditem.cpp", "msbuilditem.h", "msbuilditemdefinitiongroup.cpp", "msbuilditemdefinitiongroup.h", "msbuilditemgroup.cpp", "msbuilditemgroup.h", "msbuilditemmetadata.cpp", "msbuilditemmetadata.h", "msbuildproject.cpp", "msbuildproject.h", "msbuildproperty.cpp", "msbuildproperty.h", "msbuildpropertygroup.cpp", "msbuildpropertygroup.h", ] } Group { name: "MSBuild Object Model Items" prefix: "msbuild/items/" files: [ "msbuildclcompile.cpp", "msbuildclcompile.h", "msbuildclinclude.cpp", "msbuildclinclude.h", "msbuildfileitem.cpp", "msbuildfileitem.h", "msbuildfilter.cpp", "msbuildfilter.h", "msbuildlink.cpp", "msbuildlink.h", "msbuildnone.cpp", "msbuildnone.h", ] } Group { name: "Visual Studio Object Model I/O" prefix: "io/" files: [ "msbuildprojectwriter.cpp", "msbuildprojectwriter.h", "visualstudiosolutionwriter.cpp", "visualstudiosolutionwriter.h", ] } } qbs-src-1.13.1/src/plugins/generator/visualstudio/visualstudiogenerator.cpp000066400000000000000000000363661347155106100273270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msbuildfiltersproject.h" #include "msbuildqbsgenerateproject.h" #include "msbuildsharedsolutionpropertiesproject.h" #include "msbuildsolutionpropertiesproject.h" #include "msbuildqbsproductproject.h" #include "msbuildutils.h" #include "visualstudiogenerator.h" #include "visualstudioguidpool.h" #include "msbuild/msbuildpropertygroup.h" #include "msbuild/msbuildproject.h" #include "solution/visualstudiosolution.h" #include "solution/visualstudiosolutionfileproject.h" #include "solution/visualstudiosolutionglobalsection.h" #include "solution/visualstudiosolutionfolderproject.h" #include "io/msbuildprojectwriter.h" #include "io/visualstudiosolutionwriter.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; class VisualStudioGeneratorPrivate { friend class SolutionDependenciesVisitor; public: VisualStudioGeneratorPrivate(const Internal::VisualStudioVersionInfo &versionInfo) : versionInfo(versionInfo) {} Internal::VisualStudioVersionInfo versionInfo; std::shared_ptr guidPool; std::shared_ptr solution; QString solutionFilePath; QMap> msbuildProjects; QMap solutionProjects; QMap solutionFolders; QList> propertySheetNames; void reset(); }; void VisualStudioGeneratorPrivate::reset() { guidPool.reset(); solution.reset(); solutionFilePath.clear(); msbuildProjects.clear(); solutionProjects.clear(); solutionFolders.clear(); propertySheetNames.clear(); } class SolutionDependenciesVisitor : public IGeneratableProjectVisitor { public: SolutionDependenciesVisitor(VisualStudioGenerator *generator) : generator(generator) { } void visitProject(const GeneratableProject &project) override { Q_UNUSED(project); nestedProjects = new VisualStudioSolutionGlobalSection( QStringLiteral("NestedProjects"), generator->d->solution.get()); generator->d->solution->appendGlobalSection(nestedProjects); } void visitProjectData(const GeneratableProject &project, const GeneratableProjectData &parentProjectData, const GeneratableProjectData &projectData) override { Q_UNUSED(project); // The root project will have a null GeneratableProjectData // as its parent object (so skip giving it a parent folder) if (!parentProjectData.name().isEmpty()) { nestedProjects->appendProperty( generator->d->solutionFolders.value(projectData.uniqueName())->guid() .toString(), generator->d->solutionFolders.value(parentProjectData.uniqueName())->guid() .toString()); } } void visitProduct(const GeneratableProject &project, const GeneratableProjectData &projectData, const GeneratableProductData &productData) override { Q_UNUSED(project); Q_UNUSED(projectData); for (const auto &dep : productData.dependencies()) { generator->d->solution->addDependency( generator->d->solutionProjects.value(productData.name()), generator->d->solutionProjects.value(dep)); } nestedProjects->appendProperty( generator->d->solutionProjects.value(productData.name())->guid().toString(), generator->d->solutionFolders.value(projectData.uniqueName())->guid() .toString()); } private: VisualStudioGenerator *generator; VisualStudioSolutionGlobalSection *nestedProjects; }; VisualStudioGenerator::VisualStudioGenerator(const VisualStudioVersionInfo &versionInfo) : d(new VisualStudioGeneratorPrivate(versionInfo)) { if (d->versionInfo.usesVcBuild()) throw ErrorInfo(Tr::tr("VCBuild (Visual Studio 2008 and below) is not supported")); else if (!d->versionInfo.usesMsBuild()) throw ErrorInfo(Tr::tr("Unknown/unsupported build engine")); Q_ASSERT(d->versionInfo.usesSolutions()); } VisualStudioGenerator::~VisualStudioGenerator() { } QString VisualStudioGenerator::generatorName() const { return QStringLiteral("visualstudio%1").arg(d->versionInfo.marketingVersion()); } void VisualStudioGenerator::addPropertySheets(const GeneratableProject &project) { { const auto fileName = QStringLiteral("qbs.props"); d->propertySheetNames.push_back({ fileName, true }); d->msbuildProjects.insert(project.baseBuildDirectory().absoluteFilePath(fileName), std::make_shared( d->versionInfo, project, qbsExecutableFilePath(), qbsSettingsDir())); } { const auto fileName = QStringLiteral("qbs-shared.props"); d->propertySheetNames.push_back({ fileName, false }); d->msbuildProjects.insert(project.baseBuildDirectory().absoluteFilePath(fileName), std::make_shared( d->versionInfo, project, qbsExecutableFilePath(), qbsSettingsDir())); } } void VisualStudioGenerator::addPropertySheets( const std::shared_ptr &targetProject) { for (const auto &pair : d->propertySheetNames) { targetProject->appendPropertySheet( QStringLiteral("$(SolutionDir)\\") + pair.first, pair.second); } } static QString targetFilePath(const QString &baseName, const QString &baseBuildDirectory) { return QDir(baseBuildDirectory).absoluteFilePath(baseName + QStringLiteral(".vcxproj")); } static QString targetFilePath(const GeneratableProductData &product, const QString &baseBuildDirectory) { return targetFilePath(product.name(), baseBuildDirectory); } static void addDefaultGlobalSections(const GeneratableProject &topLevelProject, VisualStudioSolution *solution) { const auto configurationPlatformsSection = new VisualStudioSolutionGlobalSection( QStringLiteral("SolutionConfigurationPlatforms"), solution); solution->appendGlobalSection(configurationPlatformsSection); for (const auto &qbsProject : topLevelProject.projects) configurationPlatformsSection->appendProperty(MSBuildUtils::fullName(qbsProject), MSBuildUtils::fullName(qbsProject)); const auto projectConfigurationPlatformsSection = new VisualStudioSolutionGlobalSection( QStringLiteral("ProjectConfigurationPlatforms"), solution); solution->appendGlobalSection(projectConfigurationPlatformsSection); projectConfigurationPlatformsSection->setPost(true); for (const auto project : solution->projects()) { for (const auto &qbsProject : topLevelProject.projects) { projectConfigurationPlatformsSection->appendProperty( QStringLiteral("%1.%2.ActiveCfg") .arg(project->guid().toString()) .arg(MSBuildUtils::fullDisplayName(qbsProject)), MSBuildUtils::fullName(qbsProject)); projectConfigurationPlatformsSection->appendProperty( QStringLiteral("%1.%2.Build.0") .arg(project->guid().toString()) .arg(MSBuildUtils::fullDisplayName(qbsProject)), MSBuildUtils::fullName(qbsProject)); } } const auto solutionPropsSection = new VisualStudioSolutionGlobalSection( QStringLiteral("SolutionProperties"), solution); solution->appendGlobalSection(solutionPropsSection); solutionPropsSection->appendProperty(QStringLiteral("HideSolutionNode"), QStringLiteral("FALSE")); } static void writeProjectFiles(const QMap> &projects) { // Write out all the MSBuild project files to disk QMapIterator> it(projects); while (it.hasNext()) { it.next(); const auto projectFilePath = it.key(); Internal::FileSaver file(projectFilePath.toStdString()); if (!file.open()) throw ErrorInfo(Tr::tr("Cannot open %s for writing").arg(projectFilePath)); std::shared_ptr project = it.value(); MSBuildProjectWriter writer(file.device()); if (!(writer.write(project.get()) && file.commit())) throw ErrorInfo(Tr::tr("Failed to generate %1").arg(projectFilePath)); } } static void writeSolution(const std::shared_ptr &solution, const QString &solutionFilePath, const Internal::Logger &logger) { Internal::FileSaver file(solutionFilePath.toStdString()); if (!file.open()) throw ErrorInfo(Tr::tr("Cannot open %s for writing").arg(solutionFilePath)); VisualStudioSolutionWriter writer(file.device()); writer.setProjectBaseDirectory(QFileInfo(solutionFilePath).path().toStdString()); if (!(writer.write(solution.get()) && file.commit())) throw ErrorInfo(Tr::tr("Failed to generate %1").arg(solutionFilePath)); logger.qbsInfo() << Tr::tr("Generated %1").arg(QFileInfo(solutionFilePath).fileName()); } void VisualStudioGenerator::generate() { GeneratableProjectIterator it(project()); it.accept(this); addDefaultGlobalSections(project(), d->solution.get()); // Second pass: connection solution project interdependencies and project nesting hierarchy SolutionDependenciesVisitor solutionDependenciesVisitor(this); it.accept(&solutionDependenciesVisitor); writeProjectFiles(d->msbuildProjects); writeSolution(d->solution, d->solutionFilePath, logger()); d->reset(); } void VisualStudioGenerator::visitProject(const GeneratableProject &project) { addPropertySheets(project); const auto buildDir = project.baseBuildDirectory(); d->guidPool = std::make_shared( buildDir.absoluteFilePath(project.name() + QStringLiteral(".guid.txt")).toStdString()); d->solutionFilePath = buildDir.absoluteFilePath(project.name() + QStringLiteral(".sln")); d->solution = std::make_shared(d->versionInfo); // Create a helper project to re-run qbs generate const auto qbsGenerate = QStringLiteral("qbs-generate"); const auto projectFilePath = targetFilePath(qbsGenerate, buildDir.absolutePath()); const auto relativeProjectFilePath = QFileInfo(d->solutionFilePath).dir() .relativeFilePath(projectFilePath); auto targetProject = std::make_shared(project, d->versionInfo); targetProject->setGuid(d->guidPool->drawProductGuid(relativeProjectFilePath.toStdString())); d->msbuildProjects.insert(projectFilePath, targetProject); addPropertySheets(targetProject); const auto solutionProject = new VisualStudioSolutionFileProject( targetFilePath(qbsGenerate, project.baseBuildDirectory().absolutePath()), d->solution.get()); solutionProject->setGuid(targetProject->guid()); d->solution->appendProject(solutionProject); d->solutionProjects.insert(qbsGenerate, solutionProject); } void VisualStudioGenerator::visitProjectData(const GeneratableProject &project, const GeneratableProjectData &projectData) { Q_UNUSED(project); const auto solutionFolder = new VisualStudioSolutionFolderProject(d->solution.get()); solutionFolder->setName(projectData.name()); d->solution->appendProject(solutionFolder); QBS_CHECK(!d->solutionFolders.contains(projectData.uniqueName())); d->solutionFolders.insert(projectData.uniqueName(), solutionFolder); } void VisualStudioGenerator::visitProduct(const GeneratableProject &project, const GeneratableProjectData &projectData, const GeneratableProductData &productData) { Q_UNUSED(projectData); const auto projectFilePath = targetFilePath(productData, project.baseBuildDirectory().absolutePath()); const auto relativeProjectFilePath = QFileInfo(d->solutionFilePath) .dir().relativeFilePath(projectFilePath); auto targetProject = std::make_shared(project, productData, d->versionInfo); targetProject->setGuid(d->guidPool->drawProductGuid(relativeProjectFilePath.toStdString())); addPropertySheets(targetProject); d->msbuildProjects.insert(projectFilePath, targetProject); d->msbuildProjects.insert(projectFilePath + QStringLiteral(".filters"), std::make_shared(productData)); const auto solutionProject = new VisualStudioSolutionFileProject( targetFilePath(productData, project.baseBuildDirectory().absolutePath()), d->solution.get()); solutionProject->setGuid(targetProject->guid()); d->solution->appendProject(solutionProject); d->solutionProjects.insert(productData.name(), solutionProject); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/visualstudiogenerator.h000066400000000000000000000061361347155106100267640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_VISUALSTUDIOGENERATOR_H #define QBS_VISUALSTUDIOGENERATOR_H #include #include #include #include "visualstudioguidpool.h" #include #include #include namespace qbs { namespace Internal { class VisualStudioVersionInfo; } class MSBuildProject; class MSBuildTargetProject; class VisualStudioGeneratorPrivate; class VisualStudioSolution; class VisualStudioSolutionFileProject; class VisualStudioSolutionFolderProject; class VisualStudioGenerator : public ProjectGenerator, private IGeneratableProjectVisitor { friend class SolutionDependenciesVisitor; public: explicit VisualStudioGenerator(const Internal::VisualStudioVersionInfo &versionInfo); ~VisualStudioGenerator(); QString generatorName() const override; void generate() override; private: virtual void visitProject(const GeneratableProject &project) override; virtual void visitProjectData(const GeneratableProject &project, const GeneratableProjectData &projectData) override; virtual void visitProduct(const GeneratableProject &project, const GeneratableProjectData &projectData, const GeneratableProductData &productData) override; void addPropertySheets(const GeneratableProject &project); void addPropertySheets(const std::shared_ptr &targetProject); std::unique_ptr d; }; } // namespace qbs #endif // QBS_VISUALSTUDIOGENERATOR_H qbs-src-1.13.1/src/plugins/generator/visualstudio/visualstudiogeneratorplugin.cpp000066400000000000000000000053121347155106100305310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "visualstudiogenerator.h" #include #include static void QbsVisualStudioGeneratorPluginLoad() { for (const auto &info : qbs::Internal::VisualStudioVersionInfo::knownVersions()) { if (info.usesMsBuild()) qbs::ProjectGeneratorManager::registerGenerator( std::make_shared(info)); } } static void QbsVisualStudioGeneratorPluginUnload() { } #ifndef GENERATOR_EXPORT #if defined(WIN32) || defined(_WIN32) #define GENERATOR_EXPORT __declspec(dllexport) #else #define GENERATOR_EXPORT __attribute__((visibility("default"))) #endif #endif QBS_REGISTER_STATIC_PLUGIN(extern "C" GENERATOR_EXPORT, QbsVisualStudioGeneratorPlugin, QbsVisualStudioGeneratorPluginLoad, QbsVisualStudioGeneratorPluginUnload) qbs-src-1.13.1/src/plugins/generator/visualstudio/visualstudioguidpool.cpp000066400000000000000000000064461347155106100271570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "visualstudioguidpool.h" #include #include #include #include #include #include #include using namespace Json; namespace qbs { class VisualStudioGuidPoolPrivate { public: std::string storeFilePath; std::map productGuids; }; VisualStudioGuidPool::VisualStudioGuidPool(const std::string &storeFilePath) : d(std::make_shared()) { // Read any existing GUIDs from the on-disk store std::ifstream file(Internal::utf8_to_native_path(d->storeFilePath = storeFilePath)); if (file.is_open()) { const auto data = JsonDocument::fromJson(std::string { std::istreambuf_iterator(file), std::istreambuf_iterator() }).object(); for (auto it = data.constBegin(), end = data.constEnd(); it != end; ++it) { d->productGuids.insert({ it.key(), QUuid(QString::fromStdString(it.value().toString())) }); } } } VisualStudioGuidPool::~VisualStudioGuidPool() { Internal::FileSaver file(d->storeFilePath); if (file.open()) { JsonObject productData; for (const auto &it : d->productGuids) productData.insert(it.first, it.second.toString().toStdString()); const auto data = JsonDocument(productData).toJson(); file.write(std::vector { data.cbegin(), data.cend() }); file.commit(); } } QUuid VisualStudioGuidPool::drawProductGuid(const std::string &productName) { if (d->productGuids.find(productName) == d->productGuids.cend()) d->productGuids.insert({ productName, QUuid::createUuid() }); return d->productGuids.at(productName); } } // namespace qbs qbs-src-1.13.1/src/plugins/generator/visualstudio/visualstudioguidpool.h000066400000000000000000000044151347155106100266160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef VISUALSTUDIOGUIDPOOL_H #define VISUALSTUDIOGUIDPOOL_H #include #include namespace qbs { class VisualStudioGuidPoolPrivate; /*! * Provides persistent storage for GUIDs related to Visual Studio project file nodes. * These are stored on disk separately from project files and so allow projects to be * regenerated while retaining the same GUIDs. This helps avoid unnecessary project * reloads in Visual Studio, and helps ease source control usage. */ class VisualStudioGuidPool { public: explicit VisualStudioGuidPool(const std::string &storeFilePath); ~VisualStudioGuidPool(); QUuid drawProductGuid(const std::string &productName); private: std::shared_ptr d; }; } // namespace qbs #endif // VISUALSTUDIOGUIDPOOL_H qbs-src-1.13.1/src/plugins/plugins.pri000066400000000000000000000013311347155106100176150ustar00rootroot00000000000000include(../library_dirname.pri) include(../install_prefix.pri) !isEmpty(QBS_PLUGINS_BUILD_DIR) { destdirPrefix = $${QBS_PLUGINS_BUILD_DIR} } else { destdirPrefix = $$shadowed($$PWD)/../../$${QBS_LIBRARY_DIRNAME} } DESTDIR = $${destdirPrefix}/qbs/plugins isEmpty(QBSLIBDIR): QBSLIBDIR = $$OUT_PWD/../../../../$${QBS_LIBRARY_DIRNAME} isEmpty(QBS_RPATH): QBS_RPATH = ../.. include($${PWD}/../lib/corelib/use_corelib.pri) TEMPLATE = lib CONFIG += c++14 CONFIG += create_prl unix: CONFIG += plugin !isEmpty(QBS_PLUGINS_INSTALL_DIR): \ installPrefix = $${QBS_PLUGINS_INSTALL_DIR} else: \ installPrefix = $${QBS_INSTALL_PREFIX}/$${QBS_LIBRARY_DIRNAME} target.path = $${installPrefix}/qbs/plugins INSTALLS += target qbs-src-1.13.1/src/plugins/plugins.pro000066400000000000000000000000571347155106100176270ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS = generator scanner qbs-src-1.13.1/src/plugins/plugins.qbs000066400000000000000000000004621347155106100176140ustar00rootroot00000000000000import qbs Project { name: "qbs plugins" references: [ "generator/clangcompilationdb/clangcompilationdb.qbs", "generator/makefilegenerator/makefilegenerator.qbs", "generator/visualstudio/visualstudio.qbs", "scanner/cpp/cpp.qbs", "scanner/qt/qt.qbs" ] } qbs-src-1.13.1/src/plugins/qbsplugin.qbs000066400000000000000000000022441347155106100201370ustar00rootroot00000000000000import qbs import qbs.FileInfo QbsProduct { property bool isForDarwin: qbs.targetOS.contains("darwin") property bool staticBuild: Qt.core.staticBuild || qbsbuildconfig.staticBuild Depends { name: "cpp" } Depends { name: "bundle"; condition: isForDarwin } Depends { name: "Qt.core" } Depends { name: "qbsbuildconfig" } Depends { name: "qbscore"; condition: !staticBuild } type: (staticBuild ? ["staticlibrary"] : [isForDarwin ? "loadablemodule" : "dynamiclibrary"]) .concat(["qbsplugin"]) Properties { condition: staticBuild cpp.defines: ["QBS_STATIC_LIB"] } cpp.includePaths: base.concat(["../../../lib/corelib"]) cpp.visibility: "minimal" Group { fileTagsFilter: [isForDarwin ? "loadablemodule" : "dynamiclibrary"] .concat(qbs.buildVariant === "debug" ? [isForDarwin ? "debuginfo_loadablemodule" : "debuginfo_dll"] : []) qbs.install: true qbs.installDir: targetInstallDir qbs.installSourceBase: buildDirectory } targetInstallDir: qbsbuildconfig.pluginsInstallDir Properties { condition: isForDarwin bundle.isBundle: false } } qbs-src-1.13.1/src/plugins/scanner/000077500000000000000000000000001347155106100170535ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/scanner/cpp/000077500000000000000000000000001347155106100176355ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/scanner/cpp/CPlusPlusForwardDeclarations.h000066400000000000000000000113071347155106100255600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H #define CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H #include #include #ifndef CPLUSPLUS_WITHOUT_QT # include //# if defined(CPLUSPLUS_BUILD_LIB) //# define CPLUSPLUS_EXPORT Q_DECL_EXPORT //# elif defined(CPLUSPLUS_BUILD_STATIC_LIB) //# define CPLUSPLUS_EXPORT //# else //# define CPLUSPLUS_EXPORT Q_DECL_IMPORT //# endif //#else # define CPLUSPLUS_EXPORT #endif namespace CPlusPlus { class TranslationUnit; class Control; class MemoryPool; class DiagnosticClient; class Identifier; class Literal; class StringLiteral; class NumericLiteral; class SymbolTable; // names class NameVisitor; class Name; class Identifier; class TemplateNameId; class DestructorNameId; class OperatorNameId; class ConversionNameId; class QualifiedNameId; class SelectorNameId; // types class TypeMatcher; class FullySpecifiedType; class TypeVisitor; class Type; class UndefinedType; class VoidType; class IntegerType; class FloatType; class PointerToMemberType; class PointerType; class ReferenceType; class ArrayType; class NamedType; // symbols class SymbolVisitor; class Symbol; class Scope; class UsingNamespaceDirective; class UsingDeclaration; class Declaration; class Argument; class TypenameArgument; class Function; class Namespace; class NamespaceAlias; class Template; class BaseClass; class Block; class Class; class Enum; class ForwardClassDeclaration; class Token; // Objective-C symbols class ObjCBaseClass; class ObjCBaseProtocol; class ObjCClass; class ObjCForwardClassDeclaration; class ObjCProtocol; class ObjCForwardProtocolDeclaration; class ObjCMethod; class ObjCPropertyDeclaration; } // end of namespace CPlusPlus #endif // CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H qbs-src-1.13.1/src/plugins/scanner/cpp/Lexer.cpp000066400000000000000000000427361347155106100214340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "Lexer.h" #include namespace CPlusPlus { Lexer::Lexer(const char *firstChar, const char *lastChar) : _state(State_Default), _flags(0), _currentLine(1) { setSource(firstChar, lastChar); } Lexer::~Lexer() { } void Lexer::setSource(const char *firstChar, const char *lastChar) { _firstChar = firstChar; _lastChar = lastChar; _currentChar = _firstChar - 1; _tokenStart = _currentChar; _yychar = '\n'; } void Lexer::setStartWithNewline(bool enabled) { if (enabled) _yychar = '\n'; else _yychar = ' '; } int Lexer::state() const { return _state; } void Lexer::setState(int state) { _state = state; } bool Lexer::qtMocRunEnabled() const { return f._qtMocRunEnabled; } void Lexer::setQtMocRunEnabled(bool onoff) { f._qtMocRunEnabled = onoff; } bool Lexer::cxx0xEnabled() const { return f._cxx0xEnabled; } void Lexer::setCxxOxEnabled(bool onoff) { f._cxx0xEnabled = onoff; } bool Lexer::objCEnabled() const { return f._objCEnabled; } void Lexer::setObjCEnabled(bool onoff) { f._objCEnabled = onoff; } bool Lexer::isIncremental() const { return f._isIncremental; } void Lexer::setIncremental(bool isIncremental) { f._isIncremental = isIncremental; } bool Lexer::scanCommentTokens() const { return f._scanCommentTokens; } void Lexer::setScanCommentTokens(bool onoff) { f._scanCommentTokens = onoff; } void Lexer::setScanAngleStringLiteralTokens(bool onoff) { f._scanAngleStringLiteralTokens = onoff; } void Lexer::pushLineStartOffset() { ++_currentLine; } unsigned Lexer::tokenOffset() const { return _tokenStart - _firstChar; } unsigned Lexer::tokenLength() const { return _currentChar - _tokenStart; } const char *Lexer::tokenBegin() const { return _tokenStart; } const char *Lexer::tokenEnd() const { return _currentChar; } unsigned Lexer::currentLine() const { return _currentLine; } void Lexer::scan(Token *tok) { tok->reset(); scan_helper(tok); tok->f.length = _currentChar - _tokenStart; } void Lexer::scan_helper(Token *tok) { _Lagain: while (_yychar && std::isspace(_yychar)) { if (_yychar == '\n') { tok->f.joined = false; tok->f.newline = true; } else { tok->f.whitespace = true; } yyinp(); } tok->lineno = _currentLine; _tokenStart = _currentChar; tok->offset = _currentChar - _firstChar; if (_state == State_MultiLineComment || _state == State_MultiLineDoxyComment) { const int originalState = _state; if (! _yychar) { tok->f.kind = T_EOF_SYMBOL; return; } while (_yychar) { if (_yychar != '*') yyinp(); else { yyinp(); if (_yychar == '/') { yyinp(); _state = State_Default; break; } } } if (! f._scanCommentTokens) goto _Lagain; else if (originalState == State_MultiLineComment) tok->f.kind = T_COMMENT; else tok->f.kind = T_DOXY_COMMENT; return; // done } if (! _yychar) { tok->f.kind = T_EOF_SYMBOL; return; } unsigned char ch = _yychar; yyinp(); switch (ch) { case '\\': while (_yychar != '\n' && std::isspace(_yychar)) yyinp(); // ### assert(! _yychar || _yychar == '\n'); if (_yychar == '\n') { tok->f.joined = true; tok->f.newline = false; yyinp(); } goto _Lagain; case '"': case '\'': { const char quote = ch; tok->f.kind = quote == '"' ? T_STRING_LITERAL : T_CHAR_LITERAL; while (_yychar && _yychar != quote) { if (_yychar == '\n') break; else if (_yychar != '\\') yyinp(); else { yyinp(); // skip `\\' if (_yychar) yyinp(); } } // assert(_yychar == quote); if (_yychar == quote) yyinp(); } break; case '{': tok->f.kind = T_LBRACE; break; case '}': tok->f.kind = T_RBRACE; break; case '[': tok->f.kind = T_LBRACKET; break; case ']': tok->f.kind = T_RBRACKET; break; case '#': if (_yychar == '#') { tok->f.kind = T_POUND_POUND; yyinp(); } else { tok->f.kind = T_POUND; } break; case '(': tok->f.kind = T_LPAREN; break; case ')': tok->f.kind = T_RPAREN; break; case ';': tok->f.kind = T_SEMICOLON; break; case ':': if (_yychar == ':') { yyinp(); tok->f.kind = T_COLON_COLON; } else { tok->f.kind = T_COLON; } break; case '.': if (_yychar == '*') { yyinp(); tok->f.kind = T_DOT_STAR; } else if (_yychar == '.') { yyinp(); // ### assert(_yychar); if (_yychar == '.') { yyinp(); tok->f.kind = T_DOT_DOT_DOT; } else { tok->f.kind = T_ERROR; } } else if (std::isdigit(_yychar)) { do { if (_yychar == 'e' || _yychar == 'E') { yyinp(); if (_yychar == '-' || _yychar == '+') { yyinp(); // ### assert(std::isdigit(_yychar)); } } else if (std::isalnum(_yychar) || _yychar == '.') { yyinp(); } else { break; } } while (_yychar); tok->f.kind = T_NUMERIC_LITERAL; } else { tok->f.kind = T_DOT; } break; case '?': tok->f.kind = T_QUESTION; break; case '+': if (_yychar == '+') { yyinp(); tok->f.kind = T_PLUS_PLUS; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_PLUS_EQUAL; } else { tok->f.kind = T_PLUS; } break; case '-': if (_yychar == '-') { yyinp(); tok->f.kind = T_MINUS_MINUS; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_MINUS_EQUAL; } else if (_yychar == '>') { yyinp(); if (_yychar == '*') { yyinp(); tok->f.kind = T_ARROW_STAR; } else { tok->f.kind = T_ARROW; } } else { tok->f.kind = T_MINUS; } break; case '*': if (_yychar == '=') { yyinp(); tok->f.kind = T_STAR_EQUAL; } else { tok->f.kind = T_STAR; } break; case '/': if (_yychar == '/') { yyinp(); bool doxy = false; if (_yychar == '/' || _yychar == '!') { yyinp(); if (_yychar == '<') yyinp(); if (_yychar != '\n' && std::isspace(_yychar)) doxy = true; } while (_yychar && _yychar != '\n') yyinp(); if (! f._scanCommentTokens) goto _Lagain; tok->f.kind = doxy ? T_CPP_DOXY_COMMENT : T_CPP_COMMENT; } else if (_yychar == '*') { yyinp(); bool doxy = false; if (_yychar == '*' || _yychar == '!') { const char ch = _yychar; yyinp(); if (ch == '*' && _yychar == '/') goto _Ldone; if (_yychar == '<') yyinp(); if (! _yychar || std::isspace(_yychar)) doxy = true; } while (_yychar) { if (_yychar != '*') { yyinp(); } else { yyinp(); if (_yychar == '/') break; } } _Ldone: if (_yychar) yyinp(); else _state = doxy ? State_MultiLineDoxyComment : State_MultiLineComment; if (! f._scanCommentTokens) goto _Lagain; tok->f.kind = doxy ? T_DOXY_COMMENT : T_COMMENT; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_SLASH_EQUAL; } else { tok->f.kind = T_SLASH; } break; case '%': if (_yychar == '=') { yyinp(); tok->f.kind = T_PERCENT_EQUAL; } else { tok->f.kind = T_PERCENT; } break; case '^': if (_yychar == '=') { yyinp(); tok->f.kind = T_CARET_EQUAL; } else { tok->f.kind = T_CARET; } break; case '&': if (_yychar == '&') { yyinp(); tok->f.kind = T_AMPER_AMPER; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_AMPER_EQUAL; } else { tok->f.kind = T_AMPER; } break; case '|': if (_yychar == '|') { yyinp(); tok->f.kind = T_PIPE_PIPE; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_PIPE_EQUAL; } else { tok->f.kind = T_PIPE; } break; case '~': if (_yychar == '=') { yyinp(); tok->f.kind = T_TILDE_EQUAL; } else { tok->f.kind = T_TILDE; } break; case '!': if (_yychar == '=') { yyinp(); tok->f.kind = T_EXCLAIM_EQUAL; } else { tok->f.kind = T_EXCLAIM; } break; case '=': if (_yychar == '=') { yyinp(); tok->f.kind = T_EQUAL_EQUAL; } else { tok->f.kind = T_EQUAL; } break; case '<': if (f._scanAngleStringLiteralTokens) { //const char *yytext = _currentChar; while (_yychar && _yychar != '>') yyinp(); //int yylen = _currentChar - yytext; // ### assert(_yychar == '>'); if (_yychar == '>') yyinp(); tok->f.kind = T_ANGLE_STRING_LITERAL; } else if (_yychar == '<') { yyinp(); if (_yychar == '=') { yyinp(); tok->f.kind = T_LESS_LESS_EQUAL; } else tok->f.kind = T_LESS_LESS; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_LESS_EQUAL; } else { tok->f.kind = T_LESS; } break; case '>': if (_yychar == '>') { yyinp(); if (_yychar == '=') { yyinp(); tok->f.kind = T_GREATER_GREATER_EQUAL; } else tok->f.kind = T_LESS_LESS; tok->f.kind = T_GREATER_GREATER; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_GREATER_EQUAL; } else { tok->f.kind = T_GREATER; } break; case ',': tok->f.kind = T_COMMA; break; default: { if (f._objCEnabled) { if (ch == '@' && _yychar >= 'a' && _yychar <= 'z') { //const char *yytext = _currentChar; do { yyinp(); if (! (isalnum(_yychar) || _yychar == '_' || _yychar == '$')) break; } while (_yychar); // const int yylen = _currentChar - yytext; //tok->f.kind = classifyObjCAtKeyword(yytext, yylen); /// ### FIXME break; } else if (ch == '@' && _yychar == '"') { // objc @string literals ch = _yychar; yyinp(); tok->f.kind = T_AT_STRING_LITERAL; //const char *yytext = _currentChar; while (_yychar && _yychar != '"') { if (_yychar != '\\') yyinp(); else { yyinp(); // skip `\\' if (_yychar) yyinp(); } } // assert(_yychar == '"'); //int yylen = _currentChar - yytext; if (_yychar == '"') yyinp(); break; } } if (ch == 'L' && (_yychar == '"' || _yychar == '\'')) { // wide char/string literals ch = _yychar; yyinp(); const char quote = ch; tok->f.kind = quote == '"' ? T_WIDE_STRING_LITERAL : T_WIDE_CHAR_LITERAL; //const char *yytext = _currentChar; while (_yychar && _yychar != quote) { if (_yychar != '\\') yyinp(); else { yyinp(); // skip `\\' if (_yychar) yyinp(); } } // assert(_yychar == quote); //int yylen = _currentChar - yytext; if (_yychar == quote) yyinp(); } else if (std::isalpha(ch) || ch == '_' || ch == '$') { //const char *yytext = _currentChar - 1; while (std::isalnum(_yychar) || _yychar == '_' || _yychar == '$') yyinp(); //int yylen = _currentChar - yytext; tok->f.kind = T_IDENTIFIER; break; } else if (std::isdigit(ch)) { //const char *yytext = _currentChar - 1; while (_yychar) { if (_yychar == 'e' || _yychar == 'E') { yyinp(); if (_yychar == '-' || _yychar == '+') { yyinp(); // ### assert(std::isdigit(_yychar)); } } else if (std::isalnum(_yychar) || _yychar == '.') { yyinp(); } else { break; } } //int yylen = _currentChar - yytext; tok->f.kind = T_NUMERIC_LITERAL; break; } else { tok->f.kind = T_ERROR; break; } } // default } // switch } } qbs-src-1.13.1/src/plugins/scanner/cpp/Lexer.h000066400000000000000000000125231347155106100210700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef CPLUSPLUS_LEXER_H #define CPLUSPLUS_LEXER_H #include "CPlusPlusForwardDeclarations.h" #include "Token.h" namespace CPlusPlus { class CPLUSPLUS_EXPORT Lexer { Lexer(const Lexer &other); void operator =(const Lexer &other); public: enum State { State_Default, State_MultiLineComment, State_MultiLineDoxyComment }; Lexer(const char *firstChar, const char *lastChar); ~Lexer(); bool qtMocRunEnabled() const; void setQtMocRunEnabled(bool onoff); bool cxx0xEnabled() const; void setCxxOxEnabled(bool onoff); bool objCEnabled() const; void setObjCEnabled(bool onoff); void scan(Token *tok); inline void operator()(Token *tok) { scan(tok); } unsigned tokenOffset() const; unsigned tokenLength() const; const char *tokenBegin() const; const char *tokenEnd() const; unsigned currentLine() const; bool scanCommentTokens() const; void setScanCommentTokens(bool onoff); bool scanAngleStringLiteralTokens() const; void setScanAngleStringLiteralTokens(bool onoff); void setStartWithNewline(bool enabled); int state() const; void setState(int state); bool isIncremental() const; void setIncremental(bool isIncremental); private: void scan_helper(Token *tok); void setSource(const char *firstChar, const char *lastChar); static int classify(const char *string, int length, bool q, bool cxx0x); static int classifyObjCAtKeyword(const char *s, int n); static int classifyOperator(const char *string, int length); inline void yyinp() { if (++_currentChar == _lastChar) _yychar = 0; else { _yychar = *_currentChar; if (_yychar == '\n') pushLineStartOffset(); } } void pushLineStartOffset(); private: struct Flags { unsigned _isIncremental: 1; unsigned _scanCommentTokens: 1; unsigned _scanAngleStringLiteralTokens: 1; unsigned _qtMocRunEnabled: 1; unsigned _cxx0xEnabled: 1; unsigned _objCEnabled: 1; }; const char *_firstChar; const char *_currentChar; const char *_lastChar; const char *_tokenStart; unsigned char _yychar; int _state; union { unsigned _flags; Flags f; }; unsigned _currentLine; }; } // end of namespace CPlusPlus #endif // CPLUSPLUS_LEXER_H qbs-src-1.13.1/src/plugins/scanner/cpp/Token.cpp000066400000000000000000000140051347155106100214210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "Token.h" #ifndef CPLUSPLUS_NO_PARSER # include "Literals.h" #endif using namespace CPlusPlus; static const char *token_names[] = { (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), ("<@string literal>"), (""), ("&"), ("&&"), ("&="), ("->"), ("->*"), ("^"), ("^="), (":"), ("::"), (","), ("/"), ("/="), ("."), ("..."), (".*"), ("="), ("=="), ("!"), ("!="), (">"), (">="), (">>"), (">>="), ("{"), ("["), ("<"), ("<="), ("<<"), ("<<="), ("("), ("-"), ("-="), ("--"), ("%"), ("%="), ("|"), ("|="), ("||"), ("+"), ("+="), ("++"), ("#"), ("##"), ("?"), ("}"), ("]"), (")"), (";"), ("*"), ("*="), ("~"), ("~="), ("asm"), ("auto"), ("bool"), ("break"), ("case"), ("catch"), ("char"), ("class"), ("const"), ("const_cast"), ("continue"), ("default"), ("delete"), ("do"), ("double"), ("dynamic_cast"), ("else"), ("enum"), ("explicit"), ("export"), ("extern"), ("false"), ("float"), ("for"), ("friend"), ("goto"), ("if"), ("inline"), ("int"), ("long"), ("mutable"), ("namespace"), ("new"), ("operator"), ("private"), ("protected"), ("public"), ("register"), ("reinterpret_cast"), ("return"), ("short"), ("signed"), ("sizeof"), ("static"), ("static_cast"), ("struct"), ("switch"), ("template"), ("this"), ("throw"), ("true"), ("try"), ("typedef"), ("typeid"), ("typename"), ("union"), ("unsigned"), ("using"), ("virtual"), ("void"), ("volatile"), ("wchar_t"), ("while"), // gnu ("__attribute__"), ("__typeof__"), // objc @keywords ("@catch"), ("@class"), ("@compatibility_alias"), ("@defs"), ("@dynamic"), ("@encode"), ("@end"), ("@finally"), ("@implementation"), ("@interface"), ("@not_keyword"), ("@optional"), ("@package"), ("@private"), ("@property"), ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"), ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"), // Qt keywords ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"), ("Q_FOREACH"), ("Q_D"), ("Q_Q"), ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_INTERFACES"), ("Q_ENUMS"), ("Q_FLAGS"), ("Q_PRIVATE_SLOT"), ("Q_DECLARE_INTERFACE"), ("Q_OBJECT"), ("Q_GADGET"), ("Q_NAMESPACE"), }; Token::Token() : flags(0), offset(0), ptr(nullptr) { } Token::~Token() { } void Token::reset() { flags = 0; offset = 0; ptr = nullptr; } const char *Token::name(int kind) { return token_names[kind]; } #ifndef CPLUSPLUS_NO_PARSER const char *Token::spell() const { switch (f.kind) { case T_IDENTIFIER: return identifier->chars(); case T_NUMERIC_LITERAL: case T_CHAR_LITERAL: case T_STRING_LITERAL: case T_AT_STRING_LITERAL: case T_ANGLE_STRING_LITERAL: case T_WIDE_CHAR_LITERAL: case T_WIDE_STRING_LITERAL: return literal->chars(); default: return token_names[f.kind]; } // switch } #endif qbs-src-1.13.1/src/plugins/scanner/cpp/Token.h000066400000000000000000000220071347155106100210670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef CPLUSPLUS_TOKEN_H #define CPLUSPLUS_TOKEN_H #include "CPlusPlusForwardDeclarations.h" namespace CPlusPlus { enum Kind { T_EOF_SYMBOL = 0, T_ERROR, T_CPP_COMMENT, T_CPP_DOXY_COMMENT, T_COMMENT, T_DOXY_COMMENT, T_IDENTIFIER, T_FIRST_LITERAL, T_NUMERIC_LITERAL = T_FIRST_LITERAL, T_CHAR_LITERAL, T_WIDE_CHAR_LITERAL, T_STRING_LITERAL, T_WIDE_STRING_LITERAL, T_AT_STRING_LITERAL, T_ANGLE_STRING_LITERAL, T_LAST_LITERAL = T_ANGLE_STRING_LITERAL, T_FIRST_OPERATOR, T_AMPER = T_FIRST_OPERATOR, T_AMPER_AMPER, T_AMPER_EQUAL, T_ARROW, T_ARROW_STAR, T_CARET, T_CARET_EQUAL, T_COLON, T_COLON_COLON, T_COMMA, T_SLASH, T_SLASH_EQUAL, T_DOT, T_DOT_DOT_DOT, T_DOT_STAR, T_EQUAL, T_EQUAL_EQUAL, T_EXCLAIM, T_EXCLAIM_EQUAL, T_GREATER, T_GREATER_EQUAL, T_GREATER_GREATER, T_GREATER_GREATER_EQUAL, T_LBRACE, T_LBRACKET, T_LESS, T_LESS_EQUAL, T_LESS_LESS, T_LESS_LESS_EQUAL, T_LPAREN, T_MINUS, T_MINUS_EQUAL, T_MINUS_MINUS, T_PERCENT, T_PERCENT_EQUAL, T_PIPE, T_PIPE_EQUAL, T_PIPE_PIPE, T_PLUS, T_PLUS_EQUAL, T_PLUS_PLUS, T_POUND, T_POUND_POUND, T_QUESTION, T_RBRACE, T_RBRACKET, T_RPAREN, T_SEMICOLON, T_STAR, T_STAR_EQUAL, T_TILDE, T_TILDE_EQUAL, T_LAST_OPERATOR = T_TILDE_EQUAL, T_FIRST_KEYWORD, T_ASM = T_FIRST_KEYWORD, T_AUTO, T_BOOL, T_BREAK, T_CASE, T_CATCH, T_CHAR, T_CLASS, T_CONST, T_CONST_CAST, T_CONTINUE, T_DEFAULT, T_DELETE, T_DO, T_DOUBLE, T_DYNAMIC_CAST, T_ELSE, T_ENUM, T_EXPLICIT, T_EXPORT, T_EXTERN, T_FALSE, T_FLOAT, T_FOR, T_FRIEND, T_GOTO, T_IF, T_INLINE, T_INT, T_LONG, T_MUTABLE, T_NAMESPACE, T_NEW, T_OPERATOR, T_PRIVATE, T_PROTECTED, T_PUBLIC, T_REGISTER, T_REINTERPRET_CAST, T_RETURN, T_SHORT, T_SIGNED, T_SIZEOF, T_STATIC, T_STATIC_CAST, T_STRUCT, T_SWITCH, T_TEMPLATE, T_THIS, T_THROW, T_TRUE, T_TRY, T_TYPEDEF, T_TYPEID, T_TYPENAME, T_UNION, T_UNSIGNED, T_USING, T_VIRTUAL, T_VOID, T_VOLATILE, T_WCHAR_T, T_WHILE, T___ATTRIBUTE__, T___TYPEOF__, // obj c++ @ keywords T_FIRST_OBJC_AT_KEYWORD, T_AT_CATCH = T_FIRST_OBJC_AT_KEYWORD, T_AT_CLASS, T_AT_COMPATIBILITY_ALIAS, T_AT_DEFS, T_AT_DYNAMIC, T_AT_ENCODE, T_AT_END, T_AT_FINALLY, T_AT_IMPLEMENTATION, T_AT_INTERFACE, T_AT_NOT_KEYWORD, T_AT_OPTIONAL, T_AT_PACKAGE, T_AT_PRIVATE, T_AT_PROPERTY, T_AT_PROTECTED, T_AT_PROTOCOL, T_AT_PUBLIC, T_AT_REQUIRED, T_AT_SELECTOR, T_AT_SYNCHRONIZED, T_AT_SYNTHESIZE, T_AT_THROW, T_AT_TRY, T_LAST_OBJC_AT_KEYWORD = T_AT_TRY, T_FIRST_QT_KEYWORD, // Qt keywords T_SIGNAL = T_FIRST_QT_KEYWORD, T_SLOT, T_Q_SIGNAL, T_Q_SLOT, T_Q_SIGNALS, T_Q_SLOTS, T_Q_FOREACH, T_Q_D, T_Q_Q, T_Q_INVOKABLE, T_Q_PROPERTY, T_Q_INTERFACES, T_Q_ENUMS, T_Q_FLAGS, T_Q_PRIVATE_SLOT, T_Q_DECLARE_INTERFACE, T_Q_OBJECT, T_Q_GADGET, T_Q_NAMESPACE, T_LAST_KEYWORD = T_Q_NAMESPACE, // aliases T_OR = T_PIPE_PIPE, T_AND = T_AMPER_AMPER, T_NOT = T_EXCLAIM, T_XOR = T_CARET, T_BITOR = T_PIPE, T_COMPL = T_TILDE, T_OR_EQ = T_PIPE_EQUAL, T_AND_EQ = T_AMPER_EQUAL, T_BITAND = T_AMPER, T_NOT_EQ = T_EXCLAIM_EQUAL, T_XOR_EQ = T_CARET_EQUAL, T___ASM = T_ASM, T___ASM__ = T_ASM, T_TYPEOF = T___TYPEOF__, T___TYPEOF = T___TYPEOF__, T___INLINE = T_INLINE, T___INLINE__ = T_INLINE, T___CONST = T_CONST, T___CONST__ = T_CONST, T___VOLATILE = T_VOLATILE, T___VOLATILE__ = T_VOLATILE, T___ATTRIBUTE = T___ATTRIBUTE__ }; class CPLUSPLUS_EXPORT Token { public: Token(); ~Token(); inline bool is(unsigned k) const { return f.kind == k; } inline bool isNot(unsigned k) const { return f.kind != k; } #ifndef CPLUSPLUS_NO_PARSER const char *spell() const; #endif void reset(); inline unsigned kind() const { return f.kind; } inline bool newline() const { return f.newline; } inline bool whitespace() const { return f.whitespace; } inline bool joined() const { return f.joined; } inline bool expanded() const { return f.expanded; } inline bool generated() const { return f.generated; } inline unsigned length() const { return f.length; } inline unsigned begin() const { return offset; } inline unsigned end() const { return offset + f.length; } inline bool isLiteral() const { return f.kind >= T_FIRST_LITERAL && f.kind <= T_LAST_LITERAL; } inline bool isOperator() const { return f.kind >= T_FIRST_OPERATOR && f.kind <= T_LAST_OPERATOR; } inline bool isKeyword() const { return f.kind >= T_FIRST_KEYWORD && f.kind < T_FIRST_QT_KEYWORD; } inline bool isComment() const { return f.kind == T_COMMENT || f.kind == T_DOXY_COMMENT || f.kind == T_CPP_COMMENT || f.kind == T_CPP_DOXY_COMMENT; } inline bool isObjCAtKeyword() const { return f.kind >= T_FIRST_OBJC_AT_KEYWORD && f.kind <= T_LAST_OBJC_AT_KEYWORD; } static const char *name(int kind); public: struct Flags { unsigned kind : 8; unsigned newline : 1; unsigned whitespace : 1; unsigned joined : 1; unsigned expanded : 1; unsigned generated : 1; unsigned pad : 3; unsigned length : 16; }; union { unsigned flags; Flags f; }; unsigned offset; union { void *ptr; #ifndef CPLUSPLUS_NO_PARSER const Literal *literal; const NumericLiteral *number; const StringLiteral *string; const Identifier *identifier; #endif unsigned close_brace; unsigned lineno; }; }; } // end of namespace CPlusPlus #endif // CPLUSPLUS_TOKEN_H qbs-src-1.13.1/src/plugins/scanner/cpp/cpp.pro000066400000000000000000000003651347155106100211450ustar00rootroot00000000000000include(../../plugins.pri) DEFINES += CPLUSPLUS_NO_PARSER TARGET = qbs_cpp_scanner QT = core HEADERS += CPlusPlusForwardDeclarations.h Lexer.h Token.h ../scanner.h \ cpp_global.h SOURCES += Lexer.cpp Token.cpp \ cppscanner.cpp qbs-src-1.13.1/src/plugins/scanner/cpp/cpp.qbs000066400000000000000000000005611347155106100211300ustar00rootroot00000000000000import qbs 1.0 import "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { cpp.defines: base.concat(["CPLUSPLUS_NO_PARSER"]) name: "qbs_cpp_scanner" files: [ "../scanner.h", "CPlusPlusForwardDeclarations.h", "Lexer.cpp", "Lexer.h", "Token.cpp", "Token.h", "cpp_global.h", "cppscanner.cpp" ] } qbs-src-1.13.1/src/plugins/scanner/cpp/cpp_global.h000066400000000000000000000041101347155106100221040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CPP_GLOBAL_H #define CPP_GLOBAL_H #if defined(WIN32) || defined(_WIN32) #define CPPSCANNER_EXPORT __declspec(dllexport) #else #define CPPSCANNER_EXPORT __attribute__((visibility("default"))) #endif #endif // CPP_GLOBAL_H qbs-src-1.13.1/src/plugins/scanner/cpp/cppscanner.cpp000066400000000000000000000243611347155106100225030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../scanner.h" #include "cpp_global.h" #include "Lexer.h" using namespace CPlusPlus; #include #include #ifdef Q_OS_UNIX #include #include #include #include #include #else #include #endif #include #include #include #include #include struct ScanResult { char *fileName; unsigned int size; int flags; }; struct Opaq { enum FileType { FT_UNKNOWN, FT_HPP, FT_CPP, FT_C, FT_OBJC, FT_OBJCPP, FT_RC }; Opaq() : #ifdef Q_OS_UNIX fd(0), mapl(0), #endif fileContent(nullptr), fileType(FT_UNKNOWN), hasQObjectMacro(false), hasPluginMetaDataMacro(false), currentResultIndex(0) {} ~Opaq() { #ifdef Q_OS_UNIX if (fileContent) munmap(fileContent, mapl); if (fd) close(fd); #endif } #ifdef Q_OS_WIN QFile file; #endif #ifdef Q_OS_UNIX int fd; size_t mapl; #endif QString fileName; char *fileContent; FileType fileType; QList includedFiles; bool hasQObjectMacro; bool hasPluginMetaDataMacro; int currentResultIndex; }; class TokenComparator { const char * const m_fileContent; public: TokenComparator(const char *fileContent) : m_fileContent(fileContent) { } bool equals(const Token &tk, const QLatin1Literal &literal) const { return static_cast(tk.length()) == literal.size() && memcmp(m_fileContent + tk.begin(), literal.data(), literal.size()) == 0; } }; static void scanCppFile(void *opaq, CPlusPlus::Lexer &yylex, bool scanForFileTags, bool scanForDependencies) { const QLatin1Literal includeLiteral("include"); const QLatin1Literal importLiteral("import"); const QLatin1Literal defineLiteral("define"); const QLatin1Literal qobjectLiteral("Q_OBJECT"); const QLatin1Literal qgadgetLiteral("Q_GADGET"); const QLatin1Literal qnamespaceLiteral("Q_NAMESPACE"); const QLatin1Literal pluginMetaDataLiteral("Q_PLUGIN_METADATA"); const auto opaque = static_cast(opaq); const TokenComparator tc(opaque->fileContent); Token tk; Token oldTk; ScanResult scanResult; yylex(&tk); while (tk.isNot(T_EOF_SYMBOL)) { if (tk.newline() && tk.is(T_POUND)) { yylex(&tk); if (scanForDependencies && !tk.newline() && tk.is(T_IDENTIFIER)) { if (tc.equals(tk, includeLiteral) || tc.equals(tk, importLiteral)) { yylex.setScanAngleStringLiteralTokens(true); yylex(&tk); yylex.setScanAngleStringLiteralTokens(false); if (!tk.newline() && (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL))) { scanResult.size = tk.length() - 2; if (tk.is(T_STRING_LITERAL)) scanResult.flags = SC_LOCAL_INCLUDE_FLAG; else scanResult.flags = SC_GLOBAL_INCLUDE_FLAG; scanResult.fileName = opaque->fileContent + tk.begin() + 1; opaque->includedFiles.push_back(scanResult); } } } } else if (tk.is(T_IDENTIFIER)) { if (scanForFileTags) { if (oldTk.is(T_IDENTIFIER) && tc.equals(oldTk, defineLiteral)) { // Someone was clever and redefined Q_OBJECT or Q_PLUGIN_METADATA. // Example: iplugin.h in Qt Creator. } else { if (tc.equals(tk, qobjectLiteral) || tc.equals(tk, qgadgetLiteral) || tc.equals(tk, qnamespaceLiteral)) { opaque->hasQObjectMacro = true; } else if (tc.equals(tk, pluginMetaDataLiteral)) { opaque->hasPluginMetaDataMacro = true; } if (!scanForDependencies && opaque->hasQObjectMacro && (opaque->hasPluginMetaDataMacro || opaque->fileType == Opaq::FT_CPP || opaque->fileType == Opaq::FT_OBJCPP)) break; } } } oldTk = tk; yylex(&tk); } } static void *openScanner(const unsigned short *filePath, const char *fileTags, int flags) { std::unique_ptr opaque(new Opaq); opaque->fileName = QString::fromUtf16(filePath); const int fileTagsLength = static_cast(std::strlen(fileTags)); const QList &tagList = QByteArray::fromRawData(fileTags, fileTagsLength).split(','); if (tagList.contains("hpp")) opaque->fileType = Opaq::FT_HPP; else if (tagList.contains("cpp")) opaque->fileType = Opaq::FT_CPP; else if (tagList.contains("objcpp")) opaque->fileType = Opaq::FT_OBJCPP; else opaque->fileType = Opaq::FT_UNKNOWN; size_t mapl = 0; #ifdef Q_OS_UNIX QString filePathS = opaque->fileName; opaque->fd = open(qPrintable(filePathS), O_RDONLY); if (opaque->fd == -1) { opaque->fd = 0; return nullptr; } struct stat s; int r = fstat(opaque->fd, &s); if (r != 0) return nullptr; mapl = s.st_size; opaque->mapl = mapl; void *vmap = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, opaque->fd, 0); if (vmap == MAP_FAILED) return nullptr; #else opaque->file.setFileName(opaque->fileName); if (!opaque->file.open(QFile::ReadOnly)) return nullptr; uchar *vmap = opaque->file.map(0, opaque->file.size()); mapl = opaque->file.size(); #endif if (!vmap) return nullptr; opaque->fileContent = reinterpret_cast(vmap); // Check for UTF-8 Byte Order Mark (BOM). Skip if found. if (mapl >= 3 && opaque->fileContent[0] == char(0xef) && opaque->fileContent[1] == char(0xbb) && opaque->fileContent[2] == char(0xbf)) { opaque->fileContent += 3; mapl -= 3; } CPlusPlus::Lexer lex(opaque->fileContent, opaque->fileContent + mapl); scanCppFile(opaque.get(), lex, flags & ScanForFileTagsFlag, flags & ScanForDependenciesFlag); return opaque.release(); } static void closeScanner(void *ptr) { const auto opaque = static_cast(ptr); delete opaque; } static const char *next(void *opaq, int *size, int *flags) { const auto opaque = static_cast(opaq); if (opaque->currentResultIndex < opaque->includedFiles.size()) { const ScanResult &result = opaque->includedFiles.at(opaque->currentResultIndex); ++opaque->currentResultIndex; *size = result.size; *flags = result.flags; return result.fileName; } *size = 0; *flags = 0; return nullptr; } static const char **additionalFileTags(void *opaq, int *size) { static const char *thMocCpp[] = { "moc_cpp" }; static const char *thMocHpp[] = { "moc_hpp" }; static const char *thMocPluginHpp[] = { "moc_hpp_plugin" }; static const char *thMocPluginCpp[] = { "moc_cpp_plugin" }; const auto opaque = static_cast(opaq); if (opaque->hasQObjectMacro) { *size = 1; switch (opaque->fileType) { case Opaq::FT_CPP: case Opaq::FT_OBJCPP: return opaque->hasPluginMetaDataMacro ? thMocPluginCpp : thMocCpp; case Opaq::FT_HPP: return opaque->hasPluginMetaDataMacro ? thMocPluginHpp : thMocHpp; default: break; } } *size = 0; return nullptr; } ScannerPlugin includeScanner = { "include_scanner", "cpp,cpp_pch_src,c,c_pch_src,objcpp,objcpp_pch_src,objc,objc_pch_src,rc", openScanner, closeScanner, next, additionalFileTags, ScannerUsesCppIncludePaths | ScannerRecursiveDependencies }; ScannerPlugin *cppScanners[] = { &includeScanner, NULL }; static void QbsCppScannerPluginLoad() { qbs::Internal::ScannerPluginManager::instance()->registerPlugins(cppScanners); } static void QbsCppScannerPluginUnload() { } QBS_REGISTER_STATIC_PLUGIN(extern "C" CPPSCANNER_EXPORT, QbsCppScannerPlugin, QbsCppScannerPluginLoad, QbsCppScannerPluginUnload) qbs-src-1.13.1/src/plugins/scanner/qt/000077500000000000000000000000001347155106100174775ustar00rootroot00000000000000qbs-src-1.13.1/src/plugins/scanner/qt/qt.pro000066400000000000000000000001671347155106100206510ustar00rootroot00000000000000include(../../plugins.pri) TARGET = qbs_qt_scanner QT = core HEADERS += ../scanner.h SOURCES += \ qtscanner.cpp qbs-src-1.13.1/src/plugins/scanner/qt/qt.qbs000066400000000000000000000002471347155106100206350ustar00rootroot00000000000000import qbs 1.0 import "../../qbsplugin.qbs" as QbsPlugin QbsPlugin { name: "qbs_qt_scanner" files: [ "../scanner.h", "qtscanner.cpp" ] } qbs-src-1.13.1/src/plugins/scanner/qt/qtscanner.cpp000066400000000000000000000127641347155106100222130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #if defined(WIN32) || defined(_WIN32) #define SCANNER_EXPORT __declspec(dllexport) #else #define SCANNER_EXPORT __attribute__((visibility("default"))) #endif #include "../scanner.h" #include #include #include #ifdef Q_OS_UNIX #include #include #include #include #include #else #include #endif #include #include #include struct OpaqQrc { #ifdef Q_OS_UNIX int fd; int mapl; #else QFile *file; #endif char *map; QXmlStreamReader *xml; QByteArray current; OpaqQrc() #ifdef Q_OS_UNIX : fd (0), #else : file(nullptr), #endif map(nullptr), xml(nullptr) {} ~OpaqQrc() { #ifdef Q_OS_UNIX if (map) munmap (map, mapl); if (fd) close (fd); #else delete file; #endif delete xml; } }; static void *openScannerQrc(const unsigned short *filePath, const char *fileTags, int flags) { Q_UNUSED(flags); Q_UNUSED(fileTags); std::unique_ptr opaque(new OpaqQrc); #ifdef Q_OS_UNIX QString filePathS = QString::fromUtf16(filePath); opaque->fd = open(qPrintable(filePathS), O_RDONLY); if (opaque->fd == -1) { opaque->fd = 0; return nullptr; } struct stat s; int r = fstat(opaque->fd, &s); if (r != 0) return nullptr; const int fileSize = static_cast(s.st_size); opaque->mapl = fileSize; void *map = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, opaque->fd, 0); if (map == nullptr) return nullptr; #else opaque->file = new QFile(QString::fromUtf16(filePath)); if (!opaque->file->open(QFile::ReadOnly)) return nullptr; const int fileSize = opaque->file->size(); uchar *map = opaque->file->map(0, fileSize); if (!map) return nullptr; #endif opaque->map = reinterpret_cast(map); opaque->xml = new QXmlStreamReader(QByteArray::fromRawData(opaque->map, fileSize)); return static_cast(opaque.release()); } static void closeScannerQrc(void *ptr) { const auto opaque = static_cast(ptr); delete opaque; } static const char *nextQrc(void *opaq, int *size, int *flags) { const auto o = static_cast(opaq); while (!o->xml->atEnd()) { o->xml->readNext(); switch (o->xml->tokenType()) { case QXmlStreamReader::StartElement: if (o->xml->name() == QLatin1String("file")) { o->current = o->xml->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).toUtf8(); *flags = SC_LOCAL_INCLUDE_FLAG; *size = o->current.size(); return o->current.data(); } break; case QXmlStreamReader::EndDocument: return nullptr; default: break; } } return nullptr; } static const char **additionalFileTagsQrc(void *, int *size) { *size = 0; return nullptr; } ScannerPlugin qrcScanner = { "qt_qrc_scanner", "qrc", openScannerQrc, closeScannerQrc, nextQrc, additionalFileTagsQrc, NoScannerFlags }; ScannerPlugin *qtScanners[] = {&qrcScanner, NULL}; static void QbsQtScannerPluginLoad() { qbs::Internal::ScannerPluginManager::instance()->registerPlugins(qtScanners); } static void QbsQtScannerPluginUnload() { } QBS_REGISTER_STATIC_PLUGIN(extern "C" SCANNER_EXPORT, QbsQtScannerPlugin, QbsQtScannerPluginLoad, QbsQtScannerPluginUnload) qbs-src-1.13.1/src/plugins/scanner/scanner.h000066400000000000000000000063621347155106100206640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SCANNER_H #define SCANNER_H #ifdef __cplusplus extern "C" { #endif #define SC_LOCAL_INCLUDE_FLAG 0x1 #define SC_GLOBAL_INCLUDE_FLAG 0x2 enum OpenScannerFlags { ScanForDependenciesFlag = 0x01, ScanForFileTagsFlag = 0x02 }; /** * Open a file that's going to be scanned. * The file path encoding is UTF-16 on all platforms. * The file tags are in CSV format. * * Returns a scanner handle. */ typedef void *(*scanOpen_f) (const unsigned short *filePath, const char *fileTags, int flags); /** * Closes the given scanner handle. */ typedef void (*scanClose_f) (void *opaq); /** * Return the next result (filename) of the scan. */ typedef const char *(*scanNext_f) (void *opaq, int *size, int *flags); /** * Returns a list of type hints for the scanned file. * May return null. * * Example: if a C++ header file contains Q_OBJECT, * the type hint 'moc_hpp' is returned. */ typedef const char** (*scanAdditionalFileTags_f) (void *opaq, int *size); enum ScannerFlags { NoScannerFlags = 0x00, ScannerUsesCppIncludePaths = 0x01, ScannerRecursiveDependencies = 0x02 }; class ScannerPlugin { public: const char *name; const char *fileTags; // CSV scanOpen_f open; scanClose_f close; scanNext_f next; scanAdditionalFileTags_f additionalFileTags; int flags; }; #ifdef __cplusplus } #endif #endif // SCANNER_H qbs-src-1.13.1/src/plugins/scanner/scanner.pro000066400000000000000000000000451347155106100212250ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS = cpp qt qbs-src-1.13.1/src/shared/000077500000000000000000000000001347155106100152075ustar00rootroot00000000000000qbs-src-1.13.1/src/shared/bundledqt/000077500000000000000000000000001347155106100171715ustar00rootroot00000000000000qbs-src-1.13.1/src/shared/bundledqt/bundledqt.qbs000066400000000000000000000063461347155106100216730ustar00rootroot00000000000000import qbs import qbs.FileInfo Product { Depends { name: "qbsbuildconfig" } Depends { name: "Qt"; submodules: ["core", "gui", "network", "printsupport", "widgets", "xml"] } Depends { name: "Qt.script"; required: false } property bool deployQt: qbsbuildconfig.enableBundledQt && qbs.targetOS.contains("macos") && Qt.core.qtConfig.contains("rpath") property bool deployDebugLibraries: qbs.buildVariant === "debug" || (qbs.buildVariants && qbs.buildVariants.contains("debug")) readonly property string qtDebugLibrarySuffix: { if (qbs.targetOS.contains("windows")) return "d"; if (qbs.targetOS.contains("darwin")) return "_debug"; return ""; } Group { condition: deployQt && !Qt.core.staticBuild name: "qt.conf" files: ["qt.conf"] qbs.install: true qbs.installDir: qbsbuildconfig.appInstallDir } Group { condition: deployQt name: "Qt libraries" files: !Qt.core.staticBuild ? Array.prototype.concat.apply( [], Object.getOwnPropertyNames(Qt).map(function(mod) { if (mod === "script" && !Qt[mod].present) return []; if (!Qt[mod].hasLibrary) return []; var fp = Qt[mod].libFilePathRelease; var fpd = Qt.core.frameworkBuild ? fp + qtDebugLibrarySuffix : Qt[mod].libFilePathDebug; var list = [fp]; if (deployDebugLibraries && qtDebugLibrarySuffix) list.push(fpd); if (Qt.core.frameworkBuild) { var suffix = ".framework/"; var frameworkPath = fp.substr(0, fp.lastIndexOf(suffix) + suffix.length - 1); var versionsPath = frameworkPath + "/Versions"; var versionPath = versionsPath + "/" + Qt.core.versionMajor; list.push(frameworkPath + "/Resources"); list.push(versionPath + "/Resources/Info.plist"); list.push(versionPath + "/" + FileInfo.fileName(fp)); if (deployDebugLibraries && qtDebugLibrarySuffix) list.push(versionPath + "/" + FileInfo.fileName(fpd)); if (qbsbuildconfig.installApiHeaders) { list.push(frameworkPath + "/Headers"); list.push(versionPath + "/Headers/**"); } } return list; })) : [] qbs.install: true qbs.installDir: qbsbuildconfig.libInstallDir qbs.installSourceBase: Qt.core.libPath } Group { condition: deployQt prefix: Qt.core.pluginPath + "/" name: "QPA plugin" files: !Qt.core.staticBuild ? Array.prototype.concat.apply([], [""].concat( deployDebugLibraries && qtDebugLibrarySuffix ? [qtDebugLibrarySuffix] : []).map( function(suffix) { return ["platforms/" + cpp.dynamicLibraryPrefix + (Qt.gui.defaultQpaPlugin || "qcocoa") + suffix + cpp.dynamicLibrarySuffix]; })) : [] qbs.install: true qbs.installDir: "plugins" qbs.installSourceBase: prefix } } qbs-src-1.13.1/src/shared/bundledqt/qt.conf000066400000000000000000000000241347155106100204600ustar00rootroot00000000000000[Paths] Prefix = .. qbs-src-1.13.1/src/shared/json/000077500000000000000000000000001347155106100161605ustar00rootroot00000000000000qbs-src-1.13.1/src/shared/json/README.md000066400000000000000000000001361347155106100174370ustar00rootroot00000000000000This is QJson without Qt, to be used in circumstances where a Qt dependency is not desirable. qbs-src-1.13.1/src/shared/json/json.cpp000066400000000000000000003705461347155106100176540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "json.h" //#define PARSER_DEBUG #ifdef PARSER_DEBUG static int indent = 0; #define BEGIN std::cerr << std::string(4*indent++, ' ').data() << " pos=" << current #define END --indent #define DEBUG std::cerr << std::string(4*indent, ' ').data() #else #define BEGIN if (1) ; else std::cerr #define END do {} while (0) #define DEBUG if (1) ; else std::cerr #endif static const int nestingLimit = 1024; namespace Json { namespace Internal { /* This defines a binary data structure for Json data. The data structure is optimised for fast reading and minimum allocations. The whole data structure can be mmap'ed and used directly. In most cases the binary structure is not as space efficient as a utf8 encoded text representation, but much faster to access. The size requirements are: String: 4 bytes header + 2*(string.length()) Values: 4 bytes + size of data (size can be 0 for some data) bool: 0 bytes double: 8 bytes (0 if integer with less than 27bits) string: see above array: size of array object: size of object Array: 12 bytes + 4*length + size of Value data Object: 12 bytes + 8*length + size of Key Strings + size of Value data For an example such as { // object: 12 + 5*8 = 52 "firstName": "John", // key 12, value 8 = 20 "lastName" : "Smith", // key 12, value 8 = 20 "age" : 25, // key 8, value 0 = 8 "address" : // key 12, object below = 140 { // object: 12 + 4*8 "streetAddress": "21 2nd Street", // key 16, value 16 "city" : "New York", // key 8, value 12 "state" : "NY", // key 8, value 4 "postalCode" : "10021" // key 12, value 8 }, // object total: 128 "phoneNumber": // key: 16, value array below = 172 [ // array: 12 + 2*4 + values below: 156 { // object 12 + 2*8 "type" : "home", // key 8, value 8 "number": "212 555-1234" // key 8, value 16 }, // object total: 68 { // object 12 + 2*8 "type" : "fax", // key 8, value 8 "number": "646 555-4567" // key 8, value 16 } // object total: 68 ] // array total: 156 } // great total: 412 bytes The uncompressed text file used roughly 500 bytes, so in this case we end up using about the same space as the text representation. Other measurements have shown a slightly bigger binary size than a compact text representation where all possible whitespace was stripped out. */ class Array; class Object; class Value; class Entry; template class qle_bitfield { public: uint32_t val; enum { mask = ((1u << width) - 1) << pos }; void operator=(uint32_t t) { uint32_t i = val; i &= ~mask; i |= t << pos; val = i; } operator uint32_t() const { uint32_t t = val; t &= mask; t >>= pos; return t; } bool operator!() const { return !operator uint32_t(); } bool operator==(uint32_t t) { return uint32_t(*this) == t; } bool operator!=(uint32_t t) { return uint32_t(*this) != t; } bool operator<(uint32_t t) { return uint32_t(*this) < t; } bool operator>(uint32_t t) { return uint32_t(*this) > t; } bool operator<=(uint32_t t) { return uint32_t(*this) <= t; } bool operator>=(uint32_t t) { return uint32_t(*this) >= t; } void operator+=(uint32_t i) { *this = (uint32_t(*this) + i); } void operator-=(uint32_t i) { *this = (uint32_t(*this) - i); } }; template class qle_signedbitfield { public: uint32_t val; enum { mask = ((1u << width) - 1) << pos }; void operator=(int t) { uint32_t i = val; i &= ~mask; i |= t << pos; val = i; } operator int() const { uint32_t i = val; i <<= 32 - width - pos; int t = (int) i; t >>= pos; return t; } bool operator!() const { return !operator int(); } bool operator==(int t) { return int(*this) == t; } bool operator!=(int t) { return int(*this) != t; } bool operator<(int t) { return int(*this) < t; } bool operator>(int t) { return int(*this) > t; } bool operator<=(int t) { return int(*this) <= t; } bool operator>=(int t) { return int(*this) >= t; } void operator+=(int i) { *this = (int(*this) + i); } void operator-=(int i) { *this = (int(*this) - i); } }; using offset = uint32_t; // round the size up to the next 4 byte boundary int alignedSize(int size) { return (size + 3) & ~3; } static int qStringSize(const std::string &ba) { int l = 4 + static_cast(ba.length()); return alignedSize(l); } // returns INT_MAX if it can't compress it into 28 bits static int compressedNumber(double d) { // this relies on details of how ieee floats are represented const int exponent_off = 52; const uint64_t fraction_mask = 0x000fffffffffffffull; const uint64_t exponent_mask = 0x7ff0000000000000ull; uint64_t val; memcpy (&val, &d, sizeof(double)); int exp = (int)((val & exponent_mask) >> exponent_off) - 1023; if (exp < 0 || exp > 25) return INT_MAX; uint64_t non_int = val & (fraction_mask >> exp); if (non_int) return INT_MAX; bool neg = (val >> 63) != 0; val &= fraction_mask; val |= ((uint64_t)1 << 52); int res = (int)(val >> (52 - exp)); return neg ? -res : res; } static void toInternal(char *addr, const char *data, int size) { memcpy(addr, &size, 4); memcpy(addr + 4, data, size); } class String { public: String(const char *data) { d = (Data *)data; } struct Data { int length; char utf8[1]; }; Data *d; void operator=(const std::string &ba) { d->length = static_cast(ba.length()); memcpy(d->utf8, ba.data(), ba.length()); } bool operator==(const std::string &ba) const { return toString() == ba; } bool operator!=(const std::string &str) const { return !operator==(str); } bool operator>=(const std::string &str) const { // ### return toString() >= str; } bool operator==(const String &str) const { if (d->length != str.d->length) return false; return !memcmp(d->utf8, str.d->utf8, d->length); } bool operator<(const String &other) const; bool operator>=(const String &other) const { return !(*this < other); } std::string toString() const { return std::string(d->utf8, d->length); } }; bool String::operator<(const String &other) const { int alen = d->length; int blen = other.d->length; int l = std::min(alen, blen); char *a = d->utf8; char *b = other.d->utf8; while (l-- && *a == *b) a++,b++; if (l==-1) return (alen < blen); return (unsigned char)(*a) < (unsigned char)(*b); } static void copyString(char *dest, const std::string &str) { String string(dest); string = str; } /* Base is the base class for both Object and Array. Both classe work more or less the same way. The class starts with a header (defined by the struct below), then followed by data (the data for values in the Array case and Entry's (see below) for objects. After the data a table follows (tableOffset points to it) containing Value objects for Arrays, and offsets from the beginning of the object to Entry's in the case of Object. Entry's in the Object's table are lexicographically sorted by key in the table(). This allows the usage of a binary search over the keys in an Object. */ class Base { public: uint32_t size; union { uint32_t _dummy; qle_bitfield<0, 1> is_object; qle_bitfield<1, 31> length; }; offset tableOffset; // content follows here bool isObject() const { return !!is_object; } bool isArray() const { return !isObject(); } offset *table() const { return (offset *) (((char *) this) + tableOffset); } int reserveSpace(uint32_t dataSize, int posInTable, uint32_t numItems, bool replace); void removeItems(int pos, int numItems); }; class Object : public Base { public: Entry *entryAt(int i) const { return reinterpret_cast(((char *)this) + table()[i]); } int indexOf(const std::string &key, bool *exists); bool isValid() const; }; class Value { public: enum { MaxSize = (1<<27) - 1 }; union { uint32_t _dummy; qle_bitfield<0, 3> type; qle_bitfield<3, 1> intValue; qle_bitfield<4, 1> _; // Ex-latin1Key qle_bitfield<5, 27> value; // Used as offset in case of Entry(?) qle_signedbitfield<5, 27> int_value; }; char *data(const Base *b) const { return ((char *)b) + value; } int usedStorage(const Base *b) const; bool toBoolean() const { return value != 0; } double toDouble(const Base *b) const; std::string toString(const Base *b) const; Base *base(const Base *b) const; bool isValid(const Base *b) const; static int requiredStorage(JsonValue &v, bool *compressed); static uint32_t valueToStore(const JsonValue &v, uint32_t offset); static void copyData(const JsonValue &v, char *dest, bool compressed); }; class Array : public Base { public: Value at(int i) const { return *(Value *) (table() + i); } Value &operator[](int i) { return *(Value *) (table() + i); } bool isValid() const; }; class Entry { public: Value value; // key // value data follows key int size() const { int s = sizeof(Entry); s += sizeof(uint32_t) + (*(int *) ((const char *)this + sizeof(Entry))); return alignedSize(s); } int usedStorage(Base *b) const { return size() + value.usedStorage(b); } String shallowKey() const { return {(const char *)this + sizeof(Entry)}; } std::string key() const { return shallowKey().toString(); } bool operator==(const std::string &key) const; bool operator!=(const std::string &key) const { return !operator==(key); } bool operator>=(const std::string &key) const { return shallowKey() >= key; } bool operator==(const Entry &other) const; bool operator>=(const Entry &other) const; }; bool operator<(const std::string &key, const Entry &e) { return e >= key; } class Header { public: uint32_t tag; // 'qbjs' uint32_t version; // 1 Base *root() { return (Base *)(this + 1); } }; double Value::toDouble(const Base *b) const { // assert(type == JsonValue::Double); if (intValue) return int_value; double d; memcpy(&d, (const char *)b + value, 8); return d; } std::string Value::toString(const Base *b) const { String s(data(b)); return s.toString(); } Base *Value::base(const Base *b) const { // assert(type == JsonValue::Array || type == JsonValue::Object); return reinterpret_cast(data(b)); } class AtomicInt { public: bool ref() { return ++x != 0; } bool deref() { return --x != 0; } int load() { return x.load(std::memory_order_seq_cst); } private: std::atomic x { 0 }; }; class SharedString { public: AtomicInt ref; std::string s; }; class Data { public: enum Validation { Unchecked, Validated, Invalid }; AtomicInt ref; int alloc; union { char *rawData; Header *header; }; uint32_t compactionCounter : 31; uint32_t ownsData : 1; Data(char *raw, int a) : alloc(a), rawData(raw), compactionCounter(0), ownsData(true) { } Data(int reserved, JsonValue::Type valueType) : rawData(nullptr), compactionCounter(0), ownsData(true) { // assert(valueType == JsonValue::Array || valueType == JsonValue::Object); alloc = sizeof(Header) + sizeof(Base) + reserved + sizeof(offset); header = (Header *)malloc(alloc); header->tag = JsonDocument::BinaryFormatTag; header->version = 1; Base *b = header->root(); b->size = sizeof(Base); b->is_object = (valueType == JsonValue::Object); b->tableOffset = sizeof(Base); b->length = 0; } ~Data() { if (ownsData) free(rawData); } uint32_t offsetOf(const void *ptr) const { return (uint32_t)(((char *)ptr - rawData)); } JsonObject toObject(Object *o) const { return JsonObject(const_cast(this), o); } JsonArray toArray(Array *a) const { return JsonArray(const_cast(this), a); } Data *clone(Base *b, int reserve = 0) { int size = sizeof(Header) + b->size; if (b == header->root() && ref.load() == 1 && alloc >= size + reserve) return this; if (reserve) { if (reserve < 128) reserve = 128; size = std::max(size + reserve, size *2); } char *raw = (char *)malloc(size); memcpy(raw + sizeof(Header), b, b->size); Header *h = (Header *)raw; h->tag = JsonDocument::BinaryFormatTag; h->version = 1; const auto d = new Data(raw, size); d->compactionCounter = (b == header->root()) ? compactionCounter : 0; return d; } void compact(); bool valid() const; private: Data(const Data &); void operator=(const Data &); }; void objectToJson(const Object *o, std::string &json, int indent, bool compact = false); void arrayToJson(const Array *a, std::string &json, int indent, bool compact = false); class Parser { public: Parser(const char *json, int length); JsonDocument parse(JsonParseError *error); class ParsedObject { public: ParsedObject(Parser *p, int pos) : parser(p), objectPosition(pos) { offsets.reserve(64); } void insert(uint32_t offset); Parser *parser; int objectPosition; std::vector offsets; Entry *entryAt(size_t i) const { return reinterpret_cast(parser->data + objectPosition + offsets[i]); } }; private: void eatBOM(); bool eatSpace(); char nextToken(); bool parseObject(); bool parseArray(); bool parseMember(int baseOffset); bool parseString(); bool parseEscapeSequence(); bool parseValue(Value *val, int baseOffset); bool parseNumber(Value *val, int baseOffset); void addChar(char c) { const int pos = reserveSpace(1); data[pos] = c; } const char *head; const char *json; const char *end; char *data; int dataLength; int current; int nestingLevel; JsonParseError::ParseError lastError; int reserveSpace(int space) { if (current + space >= dataLength) { dataLength = 2*dataLength + space; data = (char *)realloc(data, dataLength); } int pos = current; current += space; return pos; } }; } // namespace Internal using namespace Internal; /*! \class JsonValue \inmodule QtCore \ingroup json \ingroup shared \reentrant \since 5.0 \brief The JsonValue class encapsulates a value in JSON. A value in JSON can be one of 6 basic types: JSON is a format to store structured data. It has 6 basic data types: \list \li bool JsonValue::Bool \li double JsonValue::Double \li string JsonValue::String \li array JsonValue::Array \li object JsonValue::Object \li null JsonValue::Null \endlist A value can represent any of the above data types. In addition, JsonValue has one special flag to represent undefined values. This can be queried with isUndefined(). The type of the value can be queried with type() or accessors like isBool(), isString(), and so on. Likewise, the value can be converted to the type stored in it using the toBool(), toString() and so on. Values are strictly typed internally and contrary to QVariant will not attempt to do any implicit type conversions. This implies that converting to a type that is not stored in the value will return a default constructed return value. \section1 JsonValueRef JsonValueRef is a helper class for JsonArray and JsonObject. When you get an object of type JsonValueRef, you can use it as if it were a reference to a JsonValue. If you assign to it, the assignment will apply to the element in the JsonArray or JsonObject from which you got the reference. The following methods return JsonValueRef: \list \li \l {JsonArray}::operator[](int i) \li \l {JsonObject}::operator[](const QString & key) const \endlist \sa {JSON Support in Qt}, {JSON Save Game Example} */ /*! Creates a JsonValue of type \a type. The default is to create a Null value. */ JsonValue::JsonValue(Type type) : ui(0), d(nullptr), t(type) { } /*! \internal */ JsonValue::JsonValue(Internal::Data *data, Internal::Base *base, const Internal::Value &v) : d(nullptr), t((Type)(uint32_t)v.type) { switch (t) { case Undefined: case Null: dbl = 0; break; case Bool: b = v.toBoolean(); break; case Double: dbl = v.toDouble(base); break; case String: { stringData = new Internal::SharedString; stringData->s = v.toString(base); stringData->ref.ref(); break; } case Array: case Object: d = data; this->base = v.base(base); break; } if (d) d->ref.ref(); } /*! Creates a value of type Bool, with value \a b. */ JsonValue::JsonValue(bool b) : d(nullptr), t(Bool) { this->b = b; } /*! Creates a value of type Double, with value \a n. */ JsonValue::JsonValue(double n) : d(nullptr), t(Double) { this->dbl = n; } /*! \overload Creates a value of type Double, with value \a n. */ JsonValue::JsonValue(int n) : d(nullptr), t(Double) { this->dbl = n; } /*! \overload Creates a value of type Double, with value \a n. NOTE: the integer limits for IEEE 754 double precision data is 2^53 (-9007199254740992 to +9007199254740992). If you pass in values outside this range expect a loss of precision to occur. */ JsonValue::JsonValue(int64_t n) : d(nullptr), t(Double) { this->dbl = double(n); } /*! Creates a value of type String, with value \a s. */ JsonValue::JsonValue(const std::string &s) : d(nullptr), t(String) { stringData = new Internal::SharedString; stringData->s = s; stringData->ref.ref(); } JsonValue::JsonValue(const char *s) : d(nullptr), t(String) { stringData = new Internal::SharedString; stringData->s = s; stringData->ref.ref(); } /*! Creates a value of type Array, with value \a a. */ JsonValue::JsonValue(const JsonArray &a) : d(a.d), t(Array) { base = a.a; if (d) d->ref.ref(); } /*! Creates a value of type Object, with value \a o. */ JsonValue::JsonValue(const JsonObject &o) : d(o.d), t(Object) { base = o.o; if (d) d->ref.ref(); } /*! Destroys the value. */ JsonValue::~JsonValue() { if (t == String && stringData && !stringData->ref.deref()) free(stringData); if (d && !d->ref.deref()) delete d; } /*! Creates a copy of \a other. */ JsonValue::JsonValue(const JsonValue &other) : t(other.t) { d = other.d; ui = other.ui; if (d) d->ref.ref(); if (t == String && stringData) stringData->ref.ref(); } /*! Assigns the value stored in \a other to this object. */ JsonValue &JsonValue::operator=(const JsonValue &other) { if (t == String && stringData && !stringData->ref.deref()) free(stringData); t = other.t; dbl = other.dbl; if (d != other.d) { if (d && !d->ref.deref()) delete d; d = other.d; if (d) d->ref.ref(); } if (t == String && stringData) stringData->ref.ref(); return *this; } /*! \fn bool JsonValue::isNull() const Returns \c true if the value is null. */ /*! \fn bool JsonValue::isBool() const Returns \c true if the value contains a boolean. \sa toBool() */ /*! \fn bool JsonValue::isDouble() const Returns \c true if the value contains a double. \sa toDouble() */ /*! \fn bool JsonValue::isString() const Returns \c true if the value contains a string. \sa toString() */ /*! \fn bool JsonValue::isArray() const Returns \c true if the value contains an array. \sa toArray() */ /*! \fn bool JsonValue::isObject() const Returns \c true if the value contains an object. \sa toObject() */ /*! \fn bool JsonValue::isUndefined() const Returns \c true if the value is undefined. This can happen in certain error cases as e.g. accessing a non existing key in a JsonObject. */ /*! \enum JsonValue::Type This enum describes the type of the JSON value. \value Null A Null value \value Bool A boolean value. Use toBool() to convert to a bool. \value Double A double. Use toDouble() to convert to a double. \value String A string. Use toString() to convert to a QString. \value Array An array. Use toArray() to convert to a JsonArray. \value Object An object. Use toObject() to convert to a JsonObject. \value Undefined The value is undefined. This is usually returned as an error condition, when trying to read an out of bounds value in an array or a non existent key in an object. */ /*! Returns the type of the value. \sa JsonValue::Type */ /*! Converts the value to a bool and returns it. If type() is not bool, the \a defaultValue will be returned. */ bool JsonValue::toBool(bool defaultValue) const { if (t != Bool) return defaultValue; return b; } /*! Converts the value to an int and returns it. If type() is not Double or the value is not a whole number, the \a defaultValue will be returned. */ int JsonValue::toInt(int defaultValue) const { if (t == Double && int(dbl) == dbl) return int(dbl); return defaultValue; } /*! Converts the value to a double and returns it. If type() is not Double, the \a defaultValue will be returned. */ double JsonValue::toDouble(double defaultValue) const { if (t != Double) return defaultValue; return dbl; } /*! Converts the value to a QString and returns it. If type() is not String, the \a defaultValue will be returned. */ std::string JsonValue::toString(const std::string &defaultValue) const { if (t != String) return defaultValue; return stringData->s; } /*! Converts the value to an array and returns it. If type() is not Array, the \a defaultValue will be returned. */ JsonArray JsonValue::toArray(const JsonArray &defaultValue) const { if (!d || t != Array) return defaultValue; return JsonArray(d, static_cast(base)); } /*! \overload Converts the value to an array and returns it. If type() is not Array, a \l{JsonArray::}{JsonArray()} will be returned. */ JsonArray JsonValue::toArray() const { return toArray(JsonArray()); } /*! Converts the value to an object and returns it. If type() is not Object, the \a defaultValue will be returned. */ JsonObject JsonValue::toObject(const JsonObject &defaultValue) const { if (!d || t != Object) return defaultValue; return JsonObject(d, static_cast(base)); } /*! \overload Converts the value to an object and returns it. If type() is not Object, the \l {JsonObject::}{JsonObject()} will be returned. */ JsonObject JsonValue::toObject() const { return toObject({}); } /*! Returns \c true if the value is equal to \a other. */ bool JsonValue::operator==(const JsonValue &other) const { if (t != other.t) return false; switch (t) { case Undefined: case Null: break; case Bool: return b == other.b; case Double: return dbl == other.dbl; case String: return toString() == other.toString(); case Array: if (base == other.base) return true; if (!base) return !other.base->length; if (!other.base) return !base->length; return JsonArray(d, static_cast(base)) == JsonArray(other.d, static_cast(other.base)); case Object: if (base == other.base) return true; if (!base) return !other.base->length; if (!other.base) return !base->length; return JsonObject(d, static_cast(base)) == JsonObject(other.d, static_cast(other.base)); } return true; } /*! Returns \c true if the value is not equal to \a other. */ bool JsonValue::operator!=(const JsonValue &other) const { return !(*this == other); } /*! \internal */ void JsonValue::detach() { if (!d) return; Internal::Data *x = d->clone(base); x->ref.ref(); if (!d->ref.deref()) delete d; d = x; base = static_cast(d->header->root()); } /*! \class JsonValueRef \inmodule QtCore \reentrant \brief The JsonValueRef class is a helper class for JsonValue. \internal \ingroup json When you get an object of type JsonValueRef, if you can assign to it, the assignment will apply to the character in the string from which you got the reference. That is its whole purpose in life. You can use it exactly in the same way as a reference to a JsonValue. The JsonValueRef becomes invalid once modifications are made to the string: if you want to keep the character, copy it into a JsonValue. Most of the JsonValue member functions also exist in JsonValueRef. However, they are not explicitly documented here. */ JsonValueRef &JsonValueRef::operator=(const JsonValue &val) { if (is_object) o->setValueAt(index, val); else a->replace(index, val); return *this; } JsonValueRef &JsonValueRef::operator=(const JsonValueRef &ref) { if (is_object) o->setValueAt(index, ref); else a->replace(index, ref); return *this; } JsonArray JsonValueRef::toArray() const { return toValue().toArray(); } JsonObject JsonValueRef::toObject() const { return toValue().toObject(); } JsonValue JsonValueRef::toValue() const { if (!is_object) return a->at(index); return o->valueAt(index); } /*! \class JsonArray \inmodule QtCore \ingroup json \ingroup shared \reentrant \since 5.0 \brief The JsonArray class encapsulates a JSON array. A JSON array is a list of values. The list can be manipulated by inserting and removing JsonValue's from the array. A JsonArray can be converted to and from a QVariantList. You can query the number of entries with size(), insert(), and removeAt() entries from it and iterate over its content using the standard C++ iterator pattern. JsonArray is an implicitly shared class and shares the data with the document it has been created from as long as it is not being modified. You can convert the array to and from text based JSON through JsonDocument. \sa {JSON Support in Qt}, {JSON Save Game Example} */ /*! \typedef JsonArray::Iterator Qt-style synonym for JsonArray::iterator. */ /*! \typedef JsonArray::ConstIterator Qt-style synonym for JsonArray::const_iterator. */ /*! \typedef JsonArray::size_type Typedef for int. Provided for STL compatibility. */ /*! \typedef JsonArray::value_type Typedef for JsonValue. Provided for STL compatibility. */ /*! \typedef JsonArray::difference_type Typedef for int. Provided for STL compatibility. */ /*! \typedef JsonArray::pointer Typedef for JsonValue *. Provided for STL compatibility. */ /*! \typedef JsonArray::const_pointer Typedef for const JsonValue *. Provided for STL compatibility. */ /*! \typedef JsonArray::reference Typedef for JsonValue &. Provided for STL compatibility. */ /*! \typedef JsonArray::const_reference Typedef for const JsonValue &. Provided for STL compatibility. */ /*! Creates an empty array. */ JsonArray::JsonArray() : d(nullptr), a(nullptr) { } JsonArray::JsonArray(std::initializer_list args) : d(nullptr), a(nullptr) { for (auto i = args.begin(); i != args.end(); ++i) append(*i); } /*! \fn JsonArray::JsonArray(std::initializer_list args) \since 5.4 Creates an array initialized from \a args initialization list. JsonArray can be constructed in a way similar to JSON notation, for example: \code JsonArray array = { 1, 2.2, QString() }; \endcode */ /*! \internal */ JsonArray::JsonArray(Internal::Data *data, Internal::Array *array) : d(data), a(array) { // assert(data); // assert(array); d->ref.ref(); } /*! Deletes the array. */ JsonArray::~JsonArray() { if (d && !d->ref.deref()) delete d; } /*! Creates a copy of \a other. Since JsonArray is implicitly shared, the copy is shallow as long as the object doesn't get modified. */ JsonArray::JsonArray(const JsonArray &other) { d = other.d; a = other.a; if (d) d->ref.ref(); } /*! Assigns \a other to this array. */ JsonArray &JsonArray::operator=(const JsonArray &other) { if (d != other.d) { if (d && !d->ref.deref()) delete d; d = other.d; if (d) d->ref.ref(); } a = other.a; return *this; } /*! \fn JsonArray &JsonArray::operator+=(const JsonValue &value) Appends \a value to the array, and returns a reference to the array itself. \since 5.3 \sa append(), operator<<() */ /*! \fn JsonArray JsonArray::operator+(const JsonValue &value) const Returns an array that contains all the items in this array followed by the provided \a value. \since 5.3 \sa operator+=() */ /*! \fn JsonArray &JsonArray::operator<<(const JsonValue &value) Appends \a value to the array, and returns a reference to the array itself. \since 5.3 \sa operator+=(), append() */ /*! Returns the number of values stored in the array. */ int JsonArray::size() const { if (!d) return 0; return (int)a->length; } /*! \fn JsonArray::count() const Same as size(). \sa size() */ /*! Returns \c true if the object is empty. This is the same as size() == 0. \sa size() */ bool JsonArray::isEmpty() const { if (!d) return true; return !a->length; } /*! Returns a JsonValue representing the value for index \a i. The returned JsonValue is \c Undefined, if \a i is out of bounds. */ JsonValue JsonArray::at(int i) const { if (!a || i < 0 || i >= (int)a->length) return {JsonValue::Undefined}; return {d, a, a->at(i)}; } /*! Returns the first value stored in the array. Same as \c at(0). \sa at() */ JsonValue JsonArray::first() const { return at(0); } /*! Returns the last value stored in the array. Same as \c{at(size() - 1)}. \sa at() */ JsonValue JsonArray::last() const { return at(a ? (a->length - 1) : 0); } /*! Inserts \a value at the beginning of the array. This is the same as \c{insert(0, value)} and will prepend \a value to the array. \sa append(), insert() */ void JsonArray::prepend(const JsonValue &value) { insert(0, value); } /*! Inserts \a value at the end of the array. \sa prepend(), insert() */ void JsonArray::append(const JsonValue &value) { insert(a ? (int)a->length : 0, value); } /*! Removes the value at index position \a i. \a i must be a valid index position in the array (i.e., \c{0 <= i < size()}). \sa insert(), replace() */ void JsonArray::removeAt(int i) { if (!a || i < 0 || i >= (int)a->length) return; detach(); a->removeItems(i, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(a->length) / 2u) compact(); } /*! \fn void JsonArray::removeFirst() Removes the first item in the array. Calling this function is equivalent to calling \c{removeAt(0)}. The array must not be empty. If the array can be empty, call isEmpty() before calling this function. \sa removeAt(), removeLast() */ /*! \fn void JsonArray::removeLast() Removes the last item in the array. Calling this function is equivalent to calling \c{removeAt(size() - 1)}. The array must not be empty. If the array can be empty, call isEmpty() before calling this function. \sa removeAt(), removeFirst() */ /*! Removes the item at index position \a i and returns it. \a i must be a valid index position in the array (i.e., \c{0 <= i < size()}). If you don't use the return value, removeAt() is more efficient. \sa removeAt() */ JsonValue JsonArray::takeAt(int i) { if (!a || i < 0 || i >= (int)a->length) return {JsonValue::Undefined}; JsonValue v(d, a, a->at(i)); removeAt(i); // detaches return v; } /*! Inserts \a value at index position \a i in the array. If \a i is \c 0, the value is prepended to the array. If \a i is size(), the value is appended to the array. \sa append(), prepend(), replace(), removeAt() */ void JsonArray::insert(int i, const JsonValue &value) { // assert (i >= 0 && i <= (a ? (int)a->length : 0)); JsonValue val = value; bool compressed; int valueSize = Internal::Value::requiredStorage(val, &compressed); detach(valueSize + sizeof(Internal::Value)); if (!a->length) a->tableOffset = sizeof(Internal::Array); int valueOffset = a->reserveSpace(valueSize, i, 1, false); if (!valueOffset) return; Internal::Value &v = (*a)[i]; v.type = (val.t == JsonValue::Undefined ? JsonValue::Null : val.t); v.intValue = compressed; v.value = Internal::Value::valueToStore(val, valueOffset); if (valueSize) Internal::Value::copyData(val, (char *)a + valueOffset, compressed); } /*! \fn JsonArray::iterator JsonArray::insert(iterator before, const JsonValue &value) Inserts \a value before the position pointed to by \a before, and returns an iterator pointing to the newly inserted item. \sa erase(), insert() */ /*! \fn JsonArray::iterator JsonArray::erase(iterator it) Removes the item pointed to by \a it, and returns an iterator pointing to the next item. \sa removeAt() */ /*! Replaces the item at index position \a i with \a value. \a i must be a valid index position in the array (i.e., \c{0 <= i < size()}). \sa operator[](), removeAt() */ void JsonArray::replace(int i, const JsonValue &value) { // assert (a && i >= 0 && i < (int)(a->length)); JsonValue val = value; bool compressed; int valueSize = Internal::Value::requiredStorage(val, &compressed); detach(valueSize); if (!a->length) a->tableOffset = sizeof(Internal::Array); int valueOffset = a->reserveSpace(valueSize, i, 1, true); if (!valueOffset) return; Internal::Value &v = (*a)[i]; v.type = (val.t == JsonValue::Undefined ? JsonValue::Null : val.t); v.intValue = compressed; v.value = Internal::Value::valueToStore(val, valueOffset); if (valueSize) Internal::Value::copyData(val, (char *)a + valueOffset, compressed); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(a->length) / 2u) compact(); } /*! Returns \c true if the array contains an occurrence of \a value, otherwise \c false. \sa count() */ bool JsonArray::contains(const JsonValue &value) const { for (int i = 0; i < size(); i++) { if (at(i) == value) return true; } return false; } /*! Returns the value at index position \a i as a modifiable reference. \a i must be a valid index position in the array (i.e., \c{0 <= i < size()}). The return value is of type JsonValueRef, a helper class for JsonArray and JsonObject. When you get an object of type JsonValueRef, you can use it as if it were a reference to a JsonValue. If you assign to it, the assignment will apply to the character in the JsonArray of JsonObject from which you got the reference. \sa at() */ JsonValueRef JsonArray::operator[](int i) { // assert(a && i >= 0 && i < (int)a->length); return {this, i}; } /*! \overload Same as at(). */ JsonValue JsonArray::operator[](int i) const { return at(i); } /*! Returns \c true if this array is equal to \a other. */ bool JsonArray::operator==(const JsonArray &other) const { if (a == other.a) return true; if (!a) return !other.a->length; if (!other.a) return !a->length; if (a->length != other.a->length) return false; for (int i = 0; i < (int)a->length; ++i) { if (JsonValue(d, a, a->at(i)) != JsonValue(other.d, other.a, other.a->at(i))) return false; } return true; } /*! Returns \c true if this array is not equal to \a other. */ bool JsonArray::operator!=(const JsonArray &other) const { return !(*this == other); } /*! \fn JsonArray::iterator JsonArray::begin() Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the array. \sa constBegin(), end() */ /*! \fn JsonArray::const_iterator JsonArray::begin() const \overload */ /*! \fn JsonArray::const_iterator JsonArray::constBegin() const Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the array. \sa begin(), constEnd() */ /*! \fn JsonArray::iterator JsonArray::end() Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last item in the array. \sa begin(), constEnd() */ /*! \fn const_iterator JsonArray::end() const \overload */ /*! \fn JsonArray::const_iterator JsonArray::constEnd() const Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last item in the array. \sa constBegin(), end() */ /*! \fn void JsonArray::push_back(const JsonValue &value) This function is provided for STL compatibility. It is equivalent to \l{JsonArray::append()}{append(value)} and will append \a value to the array. */ /*! \fn void JsonArray::push_front(const JsonValue &value) This function is provided for STL compatibility. It is equivalent to \l{JsonArray::prepend()}{prepend(value)} and will prepend \a value to the array. */ /*! \fn void JsonArray::pop_front() This function is provided for STL compatibility. It is equivalent to removeFirst(). The array must not be empty. If the array can be empty, call isEmpty() before calling this function. */ /*! \fn void JsonArray::pop_back() This function is provided for STL compatibility. It is equivalent to removeLast(). The array must not be empty. If the array can be empty, call isEmpty() before calling this function. */ /*! \fn bool JsonArray::empty() const This function is provided for STL compatibility. It is equivalent to isEmpty() and returns \c true if the array is empty. */ /*! \class JsonArray::iterator \inmodule QtCore \brief The JsonArray::iterator class provides an STL-style non-const iterator for JsonArray. JsonArray::iterator allows you to iterate over a JsonArray and to modify the array item associated with the iterator. If you want to iterate over a const JsonArray, use JsonArray::const_iterator instead. It is generally a good practice to use JsonArray::const_iterator on a non-const JsonArray as well, unless you need to change the JsonArray through the iterator. Const iterators are slightly faster and improves code readability. The default JsonArray::iterator constructor creates an uninitialized iterator. You must initialize it using a JsonArray function like JsonArray::begin(), JsonArray::end(), or JsonArray::insert() before you can start iterating. Most JsonArray functions accept an integer index rather than an iterator. For that reason, iterators are rarely useful in connection with JsonArray. One place where STL-style iterators do make sense is as arguments to \l{generic algorithms}. Multiple iterators can be used on the same array. However, be aware that any non-const function call performed on the JsonArray will render all existing iterators undefined. \sa JsonArray::const_iterator */ /*! \typedef JsonArray::iterator::iterator_category A synonym for \e {std::random_access_iterator_tag} indicating this iterator is a random access iterator. */ /*! \typedef JsonArray::iterator::difference_type \internal */ /*! \typedef JsonArray::iterator::value_type \internal */ /*! \typedef JsonArray::iterator::reference \internal */ /*! \typedef JsonArray::iterator::pointer \internal */ /*! \fn JsonArray::iterator::iterator() Constructs an uninitialized iterator. Functions like operator*() and operator++() should not be called on an uninitialized iterator. Use operator=() to assign a value to it before using it. \sa JsonArray::begin(), JsonArray::end() */ /*! \fn JsonArray::iterator::iterator(JsonArray *array, int index) \internal */ /*! \fn JsonValueRef JsonArray::iterator::operator*() const Returns a modifiable reference to the current item. You can change the value of an item by using operator*() on the left side of an assignment. The return value is of type JsonValueRef, a helper class for JsonArray and JsonObject. When you get an object of type JsonValueRef, you can use it as if it were a reference to a JsonValue. If you assign to it, the assignment will apply to the character in the JsonArray of JsonObject from which you got the reference. */ /*! \fn JsonValueRef *JsonArray::iterator::operator->() const Returns a pointer to a modifiable reference to the current item. */ /*! \fn JsonValueRef JsonArray::iterator::operator[](int j) const Returns a modifiable reference to the item at offset \a j from the item pointed to by this iterator (the item at position \c{*this + j}). This function is provided to make JsonArray iterators behave like C++ pointers. The return value is of type JsonValueRef, a helper class for JsonArray and JsonObject. When you get an object of type JsonValueRef, you can use it as if it were a reference to a JsonValue. If you assign to it, the assignment will apply to the character in the JsonArray of JsonObject from which you got the reference. \sa operator+() */ /*! \fn bool JsonArray::iterator::operator==(const iterator &other) const \fn bool JsonArray::iterator::operator==(const const_iterator &other) const Returns \c true if \a other points to the same item as this iterator; otherwise returns \c false. \sa operator!=() */ /*! \fn bool JsonArray::iterator::operator!=(const iterator &other) const \fn bool JsonArray::iterator::operator!=(const const_iterator &other) const Returns \c true if \a other points to a different item than this iterator; otherwise returns \c false. \sa operator==() */ /*! \fn bool JsonArray::iterator::operator<(const iterator& other) const \fn bool JsonArray::iterator::operator<(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is less than the item pointed to by the \a other iterator. */ /*! \fn bool JsonArray::iterator::operator<=(const iterator& other) const \fn bool JsonArray::iterator::operator<=(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is less than or equal to the item pointed to by the \a other iterator. */ /*! \fn bool JsonArray::iterator::operator>(const iterator& other) const \fn bool JsonArray::iterator::operator>(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is greater than the item pointed to by the \a other iterator. */ /*! \fn bool JsonArray::iterator::operator>=(const iterator& other) const \fn bool JsonArray::iterator::operator>=(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is greater than or equal to the item pointed to by the \a other iterator. */ /*! \fn JsonArray::iterator &JsonArray::iterator::operator++() The prefix ++ operator, \c{++it}, advances the iterator to the next item in the array and returns an iterator to the new current item. Calling this function on JsonArray::end() leads to undefined results. \sa operator--() */ /*! \fn JsonArray::iterator JsonArray::iterator::operator++(int) \overload The postfix ++ operator, \c{it++}, advances the iterator to the next item in the array and returns an iterator to the previously current item. */ /*! \fn JsonArray::iterator &JsonArray::iterator::operator--() The prefix -- operator, \c{--it}, makes the preceding item current and returns an iterator to the new current item. Calling this function on JsonArray::begin() leads to undefined results. \sa operator++() */ /*! \fn JsonArray::iterator JsonArray::iterator::operator--(int) \overload The postfix -- operator, \c{it--}, makes the preceding item current and returns an iterator to the previously current item. */ /*! \fn JsonArray::iterator &JsonArray::iterator::operator+=(int j) Advances the iterator by \a j items. If \a j is negative, the iterator goes backward. \sa operator-=(), operator+() */ /*! \fn JsonArray::iterator &JsonArray::iterator::operator-=(int j) Makes the iterator go back by \a j items. If \a j is negative, the iterator goes forward. \sa operator+=(), operator-() */ /*! \fn JsonArray::iterator JsonArray::iterator::operator+(int j) const Returns an iterator to the item at \a j positions forward from this iterator. If \a j is negative, the iterator goes backward. \sa operator-(), operator+=() */ /*! \fn JsonArray::iterator JsonArray::iterator::operator-(int j) const Returns an iterator to the item at \a j positions backward from this iterator. If \a j is negative, the iterator goes forward. \sa operator+(), operator-=() */ /*! \fn int JsonArray::iterator::operator-(iterator other) const Returns the number of items between the item pointed to by \a other and the item pointed to by this iterator. */ /*! \class JsonArray::const_iterator \inmodule QtCore \brief The JsonArray::const_iterator class provides an STL-style const iterator for JsonArray. JsonArray::const_iterator allows you to iterate over a JsonArray. If you want to modify the JsonArray as you iterate over it, use JsonArray::iterator instead. It is generally a good practice to use JsonArray::const_iterator on a non-const JsonArray as well, unless you need to change the JsonArray through the iterator. Const iterators are slightly faster and improves code readability. The default JsonArray::const_iterator constructor creates an uninitialized iterator. You must initialize it using a JsonArray function like JsonArray::constBegin(), JsonArray::constEnd(), or JsonArray::insert() before you can start iterating. Most JsonArray functions accept an integer index rather than an iterator. For that reason, iterators are rarely useful in connection with JsonArray. One place where STL-style iterators do make sense is as arguments to \l{generic algorithms}. Multiple iterators can be used on the same array. However, be aware that any non-const function call performed on the JsonArray will render all existing iterators undefined. \sa JsonArray::iterator */ /*! \fn JsonArray::const_iterator::const_iterator() Constructs an uninitialized iterator. Functions like operator*() and operator++() should not be called on an uninitialized iterator. Use operator=() to assign a value to it before using it. \sa JsonArray::constBegin(), JsonArray::constEnd() */ /*! \fn JsonArray::const_iterator::const_iterator(const JsonArray *array, int index) \internal */ /*! \typedef JsonArray::const_iterator::iterator_category A synonym for \e {std::random_access_iterator_tag} indicating this iterator is a random access iterator. */ /*! \typedef JsonArray::const_iterator::difference_type \internal */ /*! \typedef JsonArray::const_iterator::value_type \internal */ /*! \typedef JsonArray::const_iterator::reference \internal */ /*! \typedef JsonArray::const_iterator::pointer \internal */ /*! \fn JsonArray::const_iterator::const_iterator(const const_iterator &other) Constructs a copy of \a other. */ /*! \fn JsonArray::const_iterator::const_iterator(const iterator &other) Constructs a copy of \a other. */ /*! \fn JsonValue JsonArray::const_iterator::operator*() const Returns the current item. */ /*! \fn JsonValue *JsonArray::const_iterator::operator->() const Returns a pointer to the current item. */ /*! \fn JsonValue JsonArray::const_iterator::operator[](int j) const Returns the item at offset \a j from the item pointed to by this iterator (the item at position \c{*this + j}). This function is provided to make JsonArray iterators behave like C++ pointers. \sa operator+() */ /*! \fn bool JsonArray::const_iterator::operator==(const const_iterator &other) const Returns \c true if \a other points to the same item as this iterator; otherwise returns \c false. \sa operator!=() */ /*! \fn bool JsonArray::const_iterator::operator!=(const const_iterator &other) const Returns \c true if \a other points to a different item than this iterator; otherwise returns \c false. \sa operator==() */ /*! \fn bool JsonArray::const_iterator::operator<(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is less than the item pointed to by the \a other iterator. */ /*! \fn bool JsonArray::const_iterator::operator<=(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is less than or equal to the item pointed to by the \a other iterator. */ /*! \fn bool JsonArray::const_iterator::operator>(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is greater than the item pointed to by the \a other iterator. */ /*! \fn bool JsonArray::const_iterator::operator>=(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is greater than or equal to the item pointed to by the \a other iterator. */ /*! \fn JsonArray::const_iterator &JsonArray::const_iterator::operator++() The prefix ++ operator, \c{++it}, advances the iterator to the next item in the array and returns an iterator to the new current item. Calling this function on JsonArray::end() leads to undefined results. \sa operator--() */ /*! \fn JsonArray::const_iterator JsonArray::const_iterator::operator++(int) \overload The postfix ++ operator, \c{it++}, advances the iterator to the next item in the array and returns an iterator to the previously current item. */ /*! \fn JsonArray::const_iterator &JsonArray::const_iterator::operator--() The prefix -- operator, \c{--it}, makes the preceding item current and returns an iterator to the new current item. Calling this function on JsonArray::begin() leads to undefined results. \sa operator++() */ /*! \fn JsonArray::const_iterator JsonArray::const_iterator::operator--(int) \overload The postfix -- operator, \c{it--}, makes the preceding item current and returns an iterator to the previously current item. */ /*! \fn JsonArray::const_iterator &JsonArray::const_iterator::operator+=(int j) Advances the iterator by \a j items. If \a j is negative, the iterator goes backward. \sa operator-=(), operator+() */ /*! \fn JsonArray::const_iterator &JsonArray::const_iterator::operator-=(int j) Makes the iterator go back by \a j items. If \a j is negative, the iterator goes forward. \sa operator+=(), operator-() */ /*! \fn JsonArray::const_iterator JsonArray::const_iterator::operator+(int j) const Returns an iterator to the item at \a j positions forward from this iterator. If \a j is negative, the iterator goes backward. \sa operator-(), operator+=() */ /*! \fn JsonArray::const_iterator JsonArray::const_iterator::operator-(int j) const Returns an iterator to the item at \a j positions backward from this iterator. If \a j is negative, the iterator goes forward. \sa operator+(), operator-=() */ /*! \fn int JsonArray::const_iterator::operator-(const_iterator other) const Returns the number of items between the item pointed to by \a other and the item pointed to by this iterator. */ /*! \internal */ void JsonArray::detach(uint32_t reserve) { if (!d) { d = new Internal::Data(reserve, JsonValue::Array); a = static_cast(d->header->root()); d->ref.ref(); return; } if (reserve == 0 && d->ref.load() == 1) return; Internal::Data *x = d->clone(a, reserve); x->ref.ref(); if (!d->ref.deref()) delete d; d = x; a = static_cast(d->header->root()); } /*! \internal */ void JsonArray::compact() { if (!d || !d->compactionCounter) return; detach(); d->compact(); a = static_cast(d->header->root()); } /*! \class JsonObject \inmodule QtCore \ingroup json \ingroup shared \reentrant \since 5.0 \brief The JsonObject class encapsulates a JSON object. A JSON object is a list of key value pairs, where the keys are unique strings and the values are represented by a JsonValue. A JsonObject can be converted to and from a QVariantMap. You can query the number of (key, value) pairs with size(), insert(), and remove() entries from it and iterate over its content using the standard C++ iterator pattern. JsonObject is an implicitly shared class, and shares the data with the document it has been created from as long as it is not being modified. You can convert the object to and from text based JSON through JsonDocument. \sa {JSON Support in Qt}, {JSON Save Game Example} */ /*! \typedef JsonObject::Iterator Qt-style synonym for JsonObject::iterator. */ /*! \typedef JsonObject::ConstIterator Qt-style synonym for JsonObject::const_iterator. */ /*! \typedef JsonObject::key_type Typedef for QString. Provided for STL compatibility. */ /*! \typedef JsonObject::mapped_type Typedef for JsonValue. Provided for STL compatibility. */ /*! \typedef JsonObject::size_type Typedef for int. Provided for STL compatibility. */ /*! Constructs an empty JSON object. \sa isEmpty() */ JsonObject::JsonObject() : d(nullptr), o(nullptr) { } JsonObject::JsonObject(std::initializer_list > args) : d(nullptr), o(nullptr) { for (auto i = args.begin(); i != args.end(); ++i) insert(i->first, i->second); } /*! \fn JsonObject::JsonObject(std::initializer_list > args) \since 5.4 Constructs a JsonObject instance initialized from \a args initialization list. For example: \code JsonObject object { {"property1", 1}, {"property2", 2} }; \endcode */ /*! \internal */ JsonObject::JsonObject(Internal::Data *data, Internal::Object *object) : d(data), o(object) { // assert(d); // assert(o); d->ref.ref(); } /*! This method replaces part of the JsonObject(std::initializer_list> args) body. The constructor needs to be inline, but we do not want to leak implementation details of this class. \note this method is called for an uninitialized object \internal */ /*! Destroys the object. */ JsonObject::~JsonObject() { if (d && !d->ref.deref()) delete d; } /*! Creates a copy of \a other. Since JsonObject is implicitly shared, the copy is shallow as long as the object does not get modified. */ JsonObject::JsonObject(const JsonObject &other) { d = other.d; o = other.o; if (d) d->ref.ref(); } /*! Assigns \a other to this object. */ JsonObject &JsonObject::operator=(const JsonObject &other) { if (d != other.d) { if (d && !d->ref.deref()) delete d; d = other.d; if (d) d->ref.ref(); } o = other.o; return *this; } /*! Returns a list of all keys in this object. The list is sorted lexographically. */ JsonObject::Keys JsonObject::keys() const { Keys keys; if (!d) return keys; keys.reserve(o->length); for (uint32_t i = 0; i < o->length; ++i) { Internal::Entry *e = o->entryAt(i); keys.push_back(e->key().data()); } return keys; } /*! Returns the number of (key, value) pairs stored in the object. */ int JsonObject::size() const { if (!d) return 0; return o->length; } /*! Returns \c true if the object is empty. This is the same as size() == 0. \sa size() */ bool JsonObject::isEmpty() const { if (!d) return true; return !o->length; } /*! Returns a JsonValue representing the value for the key \a key. The returned JsonValue is JsonValue::Undefined if the key does not exist. \sa JsonValue, JsonValue::isUndefined() */ JsonValue JsonObject::value(const std::string &key) const { if (!d) return {JsonValue::Undefined}; bool keyExists; int i = o->indexOf(key, &keyExists); if (!keyExists) return {JsonValue::Undefined}; return {d, o, o->entryAt(i)->value}; } /*! Returns a JsonValue representing the value for the key \a key. This does the same as value(). The returned JsonValue is JsonValue::Undefined if the key does not exist. \sa value(), JsonValue, JsonValue::isUndefined() */ JsonValue JsonObject::operator[](const std::string &key) const { return value(key); } /*! Returns a reference to the value for \a key. The return value is of type JsonValueRef, a helper class for JsonArray and JsonObject. When you get an object of type JsonValueRef, you can use it as if it were a reference to a JsonValue. If you assign to it, the assignment will apply to the element in the JsonArray or JsonObject from which you got the reference. \sa value() */ JsonValueRef JsonObject::operator[](const std::string &key) { // ### somewhat inefficient, as we lookup the key twice if it doesn't yet exist bool keyExists = false; int index = o ? o->indexOf(key, &keyExists) : -1; if (!keyExists) { iterator i = insert(key, JsonValue()); index = i.i; } return {this, index}; } /*! Inserts a new item with the key \a key and a value of \a value. If there is already an item with the key \a key, then that item's value is replaced with \a value. Returns an iterator pointing to the inserted item. If the value is JsonValue::Undefined, it will cause the key to get removed from the object. The returned iterator will then point to end(). \sa remove(), take(), JsonObject::iterator, end() */ JsonObject::iterator JsonObject::insert(const std::string &key, const JsonValue &value) { if (value.t == JsonValue::Undefined) { remove(key); return end(); } JsonValue val = value; bool isIntValue; int valueSize = Internal::Value::requiredStorage(val, &isIntValue); int valueOffset = sizeof(Internal::Entry) + Internal::qStringSize(key); int requiredSize = valueOffset + valueSize; detach(requiredSize + sizeof(Internal::offset)); // offset for the new index entry if (!o->length) o->tableOffset = sizeof(Internal::Object); bool keyExists = false; int pos = o->indexOf(key, &keyExists); if (keyExists) ++d->compactionCounter; uint32_t off = o->reserveSpace(requiredSize, pos, 1, keyExists); if (!off) return end(); Internal::Entry *e = o->entryAt(pos); e->value.type = val.t; e->value.intValue = isIntValue; e->value.value = Internal::Value::valueToStore(val, static_cast((char *)e - (char *)o) + valueOffset); Internal::copyString((char *)(e + 1), key); if (valueSize) Internal::Value::copyData(val, (char *)e + valueOffset, isIntValue); if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) compact(); return {this, pos}; } /*! Removes \a key from the object. \sa insert(), take() */ void JsonObject::remove(const std::string &key) { if (!d) return; bool keyExists; int index = o->indexOf(key, &keyExists); if (!keyExists) return; detach(); o->removeItems(index, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) compact(); } /*! Removes \a key from the object. Returns a JsonValue containing the value referenced by \a key. If \a key was not contained in the object, the returned JsonValue is JsonValue::Undefined. \sa insert(), remove(), JsonValue */ JsonValue JsonObject::take(const std::string &key) { if (!o) return {JsonValue::Undefined}; bool keyExists; int index = o->indexOf(key, &keyExists); if (!keyExists) return {JsonValue::Undefined}; JsonValue v(d, o, o->entryAt(index)->value); detach(); o->removeItems(index, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) compact(); return v; } /*! Returns \c true if the object contains key \a key. \sa insert(), remove(), take() */ bool JsonObject::contains(const std::string &key) const { if (!o) return false; bool keyExists; o->indexOf(key, &keyExists); return keyExists; } /*! Returns \c true if \a other is equal to this object. */ bool JsonObject::operator==(const JsonObject &other) const { if (o == other.o) return true; if (!o) return !other.o->length; if (!other.o) return !o->length; if (o->length != other.o->length) return false; for (uint32_t i = 0; i < o->length; ++i) { Internal::Entry *e = o->entryAt(i); JsonValue v(d, o, e->value); if (other.value(e->key()) != v) return false; } return true; } /*! Returns \c true if \a other is not equal to this object. */ bool JsonObject::operator!=(const JsonObject &other) const { return !(*this == other); } /*! Removes the (key, value) pair pointed to by the iterator \a it from the map, and returns an iterator to the next item in the map. \sa remove() */ JsonObject::iterator JsonObject::erase(JsonObject::iterator it) { // assert(d && d->ref.load() == 1); if (it.o != this || it.i < 0 || it.i >= (int)o->length) return {this, int(o->length)}; int index = it.i; o->removeItems(index, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) compact(); // iterator hasn't changed return it; } /*! Returns an iterator pointing to the item with key \a key in the map. If the map contains no item with key \a key, the function returns end(). */ JsonObject::iterator JsonObject::find(const std::string &key) { bool keyExists = false; int index = o ? o->indexOf(key, &keyExists) : 0; if (!keyExists) return end(); detach(); return {this, index}; } /*! \fn JsonObject::const_iterator JsonObject::find(const QString &key) const \overload */ /*! Returns a const iterator pointing to the item with key \a key in the map. If the map contains no item with key \a key, the function returns constEnd(). */ JsonObject::const_iterator JsonObject::constFind(const std::string &key) const { bool keyExists = false; int index = o ? o->indexOf(key, &keyExists) : 0; if (!keyExists) return end(); return {this, index}; } /*! \fn int JsonObject::count() const \overload Same as size(). */ /*! \fn int JsonObject::length() const \overload Same as size(). */ /*! \fn JsonObject::iterator JsonObject::begin() Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the object. \sa constBegin(), end() */ /*! \fn JsonObject::const_iterator JsonObject::begin() const \overload */ /*! \fn JsonObject::const_iterator JsonObject::constBegin() const Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the object. \sa begin(), constEnd() */ /*! \fn JsonObject::iterator JsonObject::end() Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last item in the object. \sa begin(), constEnd() */ /*! \fn JsonObject::const_iterator JsonObject::end() const \overload */ /*! \fn JsonObject::const_iterator JsonObject::constEnd() const Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last item in the object. \sa constBegin(), end() */ /*! \fn bool JsonObject::empty() const This function is provided for STL compatibility. It is equivalent to isEmpty(), returning \c true if the object is empty; otherwise returning \c false. */ /*! \class JsonObject::iterator \inmodule QtCore \ingroup json \reentrant \since 5.0 \brief The JsonObject::iterator class provides an STL-style non-const iterator for JsonObject. JsonObject::iterator allows you to iterate over a JsonObject and to modify the value (but not the key) stored under a particular key. If you want to iterate over a const JsonObject, you should use JsonObject::const_iterator. It is generally good practice to use JsonObject::const_iterator on a non-const JsonObject as well, unless you need to change the JsonObject through the iterator. Const iterators are slightly faster, and improve code readability. The default JsonObject::iterator constructor creates an uninitialized iterator. You must initialize it using a JsonObject function like JsonObject::begin(), JsonObject::end(), or JsonObject::find() before you can start iterating. Multiple iterators can be used on the same object. Existing iterators will however become dangling once the object gets modified. \sa JsonObject::const_iterator, {JSON Support in Qt}, {JSON Save Game Example} */ /*! \typedef JsonObject::iterator::difference_type \internal */ /*! \typedef JsonObject::iterator::iterator_category A synonym for \e {std::bidirectional_iterator_tag} indicating this iterator is a bidirectional iterator. */ /*! \typedef JsonObject::iterator::reference \internal */ /*! \typedef JsonObject::iterator::value_type \internal */ /*! \fn JsonObject::iterator::iterator() Constructs an uninitialized iterator. Functions like key(), value(), and operator++() must not be called on an uninitialized iterator. Use operator=() to assign a value to it before using it. \sa JsonObject::begin(), JsonObject::end() */ /*! \fn JsonObject::iterator::iterator(JsonObject *obj, int index) \internal */ /*! \fn QString JsonObject::iterator::key() const Returns the current item's key. There is no direct way of changing an item's key through an iterator, although it can be done by calling JsonObject::erase() followed by JsonObject::insert(). \sa value() */ /*! \fn JsonValueRef JsonObject::iterator::value() const Returns a modifiable reference to the current item's value. You can change the value of an item by using value() on the left side of an assignment. The return value is of type JsonValueRef, a helper class for JsonArray and JsonObject. When you get an object of type JsonValueRef, you can use it as if it were a reference to a JsonValue. If you assign to it, the assignment will apply to the element in the JsonArray or JsonObject from which you got the reference. \sa key(), operator*() */ /*! \fn JsonValueRef JsonObject::iterator::operator*() const Returns a modifiable reference to the current item's value. Same as value(). The return value is of type JsonValueRef, a helper class for JsonArray and JsonObject. When you get an object of type JsonValueRef, you can use it as if it were a reference to a JsonValue. If you assign to it, the assignment will apply to the element in the JsonArray or JsonObject from which you got the reference. \sa key() */ /*! \fn JsonValueRef *JsonObject::iterator::operator->() const Returns a pointer to a modifiable reference to the current item. */ /*! \fn bool JsonObject::iterator::operator==(const iterator &other) const \fn bool JsonObject::iterator::operator==(const const_iterator &other) const Returns \c true if \a other points to the same item as this iterator; otherwise returns \c false. \sa operator!=() */ /*! \fn bool JsonObject::iterator::operator!=(const iterator &other) const \fn bool JsonObject::iterator::operator!=(const const_iterator &other) const Returns \c true if \a other points to a different item than this iterator; otherwise returns \c false. \sa operator==() */ /*! \fn JsonObject::iterator JsonObject::iterator::operator++() The prefix ++ operator, \c{++i}, advances the iterator to the next item in the object and returns an iterator to the new current item. Calling this function on JsonObject::end() leads to undefined results. \sa operator--() */ /*! \fn JsonObject::iterator JsonObject::iterator::operator++(int) \overload The postfix ++ operator, \c{i++}, advances the iterator to the next item in the object and returns an iterator to the previously current item. */ /*! \fn JsonObject::iterator JsonObject::iterator::operator--() The prefix -- operator, \c{--i}, makes the preceding item current and returns an iterator pointing to the new current item. Calling this function on JsonObject::begin() leads to undefined results. \sa operator++() */ /*! \fn JsonObject::iterator JsonObject::iterator::operator--(int) \overload The postfix -- operator, \c{i--}, makes the preceding item current and returns an iterator pointing to the previously current item. */ /*! \fn JsonObject::iterator JsonObject::iterator::operator+(int j) const Returns an iterator to the item at \a j positions forward from this iterator. If \a j is negative, the iterator goes backward. \sa operator-() */ /*! \fn JsonObject::iterator JsonObject::iterator::operator-(int j) const Returns an iterator to the item at \a j positions backward from this iterator. If \a j is negative, the iterator goes forward. \sa operator+() */ /*! \fn JsonObject::iterator &JsonObject::iterator::operator+=(int j) Advances the iterator by \a j items. If \a j is negative, the iterator goes backward. \sa operator-=(), operator+() */ /*! \fn JsonObject::iterator &JsonObject::iterator::operator-=(int j) Makes the iterator go back by \a j items. If \a j is negative, the iterator goes forward. \sa operator+=(), operator-() */ /*! \class JsonObject::const_iterator \inmodule QtCore \ingroup json \since 5.0 \brief The JsonObject::const_iterator class provides an STL-style const iterator for JsonObject. JsonObject::const_iterator allows you to iterate over a JsonObject. If you want to modify the JsonObject as you iterate over it, you must use JsonObject::iterator instead. It is generally good practice to use JsonObject::const_iterator on a non-const JsonObject as well, unless you need to change the JsonObject through the iterator. Const iterators are slightly faster and improve code readability. The default JsonObject::const_iterator constructor creates an uninitialized iterator. You must initialize it using a JsonObject function like JsonObject::constBegin(), JsonObject::constEnd(), or JsonObject::find() before you can start iterating. Multiple iterators can be used on the same object. Existing iterators will however become dangling if the object gets modified. \sa JsonObject::iterator, {JSON Support in Qt}, {JSON Save Game Example} */ /*! \typedef JsonObject::const_iterator::difference_type \internal */ /*! \typedef JsonObject::const_iterator::iterator_category A synonym for \e {std::bidirectional_iterator_tag} indicating this iterator is a bidirectional iterator. */ /*! \typedef JsonObject::const_iterator::reference \internal */ /*! \typedef JsonObject::const_iterator::value_type \internal */ /*! \fn JsonObject::const_iterator::const_iterator() Constructs an uninitialized iterator. Functions like key(), value(), and operator++() must not be called on an uninitialized iterator. Use operator=() to assign a value to it before using it. \sa JsonObject::constBegin(), JsonObject::constEnd() */ /*! \fn JsonObject::const_iterator::const_iterator(const JsonObject *obj, int index) \internal */ /*! \fn JsonObject::const_iterator::const_iterator(const iterator &other) Constructs a copy of \a other. */ /*! \fn QString JsonObject::const_iterator::key() const Returns the current item's key. \sa value() */ /*! \fn JsonValue JsonObject::const_iterator::value() const Returns the current item's value. \sa key(), operator*() */ /*! \fn JsonValue JsonObject::const_iterator::operator*() const Returns the current item's value. Same as value(). \sa key() */ /*! \fn JsonValue *JsonObject::const_iterator::operator->() const Returns a pointer to the current item. */ /*! \fn bool JsonObject::const_iterator::operator==(const const_iterator &other) const \fn bool JsonObject::const_iterator::operator==(const iterator &other) const Returns \c true if \a other points to the same item as this iterator; otherwise returns \c false. \sa operator!=() */ /*! \fn bool JsonObject::const_iterator::operator!=(const const_iterator &other) const \fn bool JsonObject::const_iterator::operator!=(const iterator &other) const Returns \c true if \a other points to a different item than this iterator; otherwise returns \c false. \sa operator==() */ /*! \fn JsonObject::const_iterator JsonObject::const_iterator::operator++() The prefix ++ operator, \c{++i}, advances the iterator to the next item in the object and returns an iterator to the new current item. Calling this function on JsonObject::end() leads to undefined results. \sa operator--() */ /*! \fn JsonObject::const_iterator JsonObject::const_iterator::operator++(int) \overload The postfix ++ operator, \c{i++}, advances the iterator to the next item in the object and returns an iterator to the previously current item. */ /*! \fn JsonObject::const_iterator &JsonObject::const_iterator::operator--() The prefix -- operator, \c{--i}, makes the preceding item current and returns an iterator pointing to the new current item. Calling this function on JsonObject::begin() leads to undefined results. \sa operator++() */ /*! \fn JsonObject::const_iterator JsonObject::const_iterator::operator--(int) \overload The postfix -- operator, \c{i--}, makes the preceding item current and returns an iterator pointing to the previously current item. */ /*! \fn JsonObject::const_iterator JsonObject::const_iterator::operator+(int j) const Returns an iterator to the item at \a j positions forward from this iterator. If \a j is negative, the iterator goes backward. This operation can be slow for large \a j values. \sa operator-() */ /*! \fn JsonObject::const_iterator JsonObject::const_iterator::operator-(int j) const Returns an iterator to the item at \a j positions backward from this iterator. If \a j is negative, the iterator goes forward. This operation can be slow for large \a j values. \sa operator+() */ /*! \fn JsonObject::const_iterator &JsonObject::const_iterator::operator+=(int j) Advances the iterator by \a j items. If \a j is negative, the iterator goes backward. This operation can be slow for large \a j values. \sa operator-=(), operator+() */ /*! \fn JsonObject::const_iterator &JsonObject::const_iterator::operator-=(int j) Makes the iterator go back by \a j items. If \a j is negative, the iterator goes forward. This operation can be slow for large \a j values. \sa operator+=(), operator-() */ /*! \internal */ void JsonObject::detach(uint32_t reserve) { if (!d) { d = new Internal::Data(reserve, JsonValue::Object); o = static_cast(d->header->root()); d->ref.ref(); return; } if (reserve == 0 && d->ref.load() == 1) return; Internal::Data *x = d->clone(o, reserve); x->ref.ref(); if (!d->ref.deref()) delete d; d = x; o = static_cast(d->header->root()); } /*! \internal */ void JsonObject::compact() { if (!d || !d->compactionCounter) return; detach(); d->compact(); o = static_cast(d->header->root()); } /*! \internal */ std::string JsonObject::keyAt(int i) const { // assert(o && i >= 0 && i < (int)o->length); Internal::Entry *e = o->entryAt(i); return e->key(); } /*! \internal */ JsonValue JsonObject::valueAt(int i) const { if (!o || i < 0 || i >= (int)o->length) return {JsonValue::Undefined}; Internal::Entry *e = o->entryAt(i); return {d, o, e->value}; } /*! \internal */ void JsonObject::setValueAt(int i, const JsonValue &val) { // assert(o && i >= 0 && i < (int)o->length); Internal::Entry *e = o->entryAt(i); insert(e->key(), val); } /*! \class JsonDocument \inmodule QtCore \ingroup json \ingroup shared \reentrant \since 5.0 \brief The JsonDocument class provides a way to read and write JSON documents. JsonDocument is a class that wraps a complete JSON document and can read and write this document both from a UTF-8 encoded text based representation as well as Qt's own binary format. A JSON document can be converted from its text-based representation to a JsonDocument using JsonDocument::fromJson(). toJson() converts it back to text. The parser is very fast and efficient and converts the JSON to the binary representation used by Qt. Validity of the parsed document can be queried with !isNull() A document can be queried as to whether it contains an array or an object using isArray() and isObject(). The array or object contained in the document can be retrieved using array() or object() and then read or manipulated. A document can also be created from a stored binary representation using fromBinaryData() or fromRawData(). \sa {JSON Support in Qt}, {JSON Save Game Example} */ /*! * Constructs an empty and invalid document. */ JsonDocument::JsonDocument() : d(nullptr) { } /*! * Creates a JsonDocument from \a object. */ JsonDocument::JsonDocument(const JsonObject &object) : d(nullptr) { setObject(object); } /*! * Constructs a JsonDocument from \a array. */ JsonDocument::JsonDocument(const JsonArray &array) : d(nullptr) { setArray(array); } /*! \internal */ JsonDocument::JsonDocument(Internal::Data *data) : d(data) { // assert(d); d->ref.ref(); } /*! Deletes the document. Binary data set with fromRawData is not freed. */ JsonDocument::~JsonDocument() { if (d && !d->ref.deref()) delete d; } /*! * Creates a copy of the \a other document. */ JsonDocument::JsonDocument(const JsonDocument &other) { d = other.d; if (d) d->ref.ref(); } /*! * Assigns the \a other document to this JsonDocument. * Returns a reference to this object. */ JsonDocument &JsonDocument::operator=(const JsonDocument &other) { if (d != other.d) { if (d && !d->ref.deref()) delete d; d = other.d; if (d) d->ref.ref(); } return *this; } /*! \enum JsonDocument::DataValidation This value is used to tell JsonDocument whether to validate the binary data when converting to a JsonDocument using fromBinaryData() or fromRawData(). \value Validate Validate the data before using it. This is the default. \value BypassValidation Bypasses data validation. Only use if you received the data from a trusted place and know it's valid, as using of invalid data can crash the application. */ /*! Creates a JsonDocument that uses the first \a size bytes from \a data. It assumes \a data contains a binary encoded JSON document. The created document does not take ownership of \a data and the caller has to guarantee that \a data will not be deleted or modified as long as any JsonDocument, JsonObject or JsonArray still references the data. \a data has to be aligned to a 4 byte boundary. \a validation decides whether the data is checked for validity before being used. By default the data is validated. If the \a data is not valid, the method returns a null document. Returns a JsonDocument representing the data. \sa rawData(), fromBinaryData(), isNull(), DataValidation */ JsonDocument JsonDocument::fromRawData(const char *data, int size, DataValidation validation) { if (std::uintptr_t(data) & 3) { std::cerr <<"JsonDocument::fromRawData: data has to have 4 byte alignment\n"; return {}; } const auto d = new Internal::Data((char *)data, size); d->ownsData = false; if (validation != BypassValidation && !d->valid()) { delete d; return {}; } return {d}; } /*! Returns the raw binary representation of the data \a size will contain the size of the returned data. This method is useful to e.g. stream the JSON document in it's binary form to a file. */ const char *JsonDocument::rawData(int *size) const { if (!d) { *size = 0; return nullptr; } *size = d->alloc; return d->rawData; } /*! Creates a JsonDocument from \a data. \a validation decides whether the data is checked for validity before being used. By default the data is validated. If the \a data is not valid, the method returns a null document. \sa toBinaryData(), fromRawData(), isNull(), DataValidation */ JsonDocument JsonDocument::fromBinaryData(const std::string &data, DataValidation validation) { if (data.size() < (int)(sizeof(Internal::Header) + sizeof(Internal::Base))) return {}; Internal::Header h; memcpy(&h, data.data(), sizeof(Internal::Header)); Internal::Base root; memcpy(&root, data.data() + sizeof(Internal::Header), sizeof(Internal::Base)); // do basic checks here, so we don't try to allocate more memory than we can. if (h.tag != JsonDocument::BinaryFormatTag || h.version != 1u || sizeof(Internal::Header) + root.size > (uint32_t)data.size()) return {}; const uint32_t size = sizeof(Internal::Header) + root.size; char *raw = (char *)malloc(size); if (!raw) return {}; memcpy(raw, data.data(), size); const auto d = new Internal::Data(raw, size); if (validation != BypassValidation && !d->valid()) { delete d; return {}; } return {d}; } /*! \enum JsonDocument::JsonFormat This value defines the format of the JSON byte array produced when converting to a JsonDocument using toJson(). \value Indented Defines human readable output as follows: \code { "Array": [ true, 999, "string" ], "Key": "Value", "null": null } \endcode \value Compact Defines a compact output as follows: \code {"Array":[true,999,"string"],"Key":"Value","null":null} \endcode */ /*! Converts the JsonDocument to a UTF-8 encoded JSON document in the provided \a format. \sa fromJson(), JsonFormat */ #ifndef QT_JSON_READONLY std::string JsonDocument::toJson(JsonFormat format) const { std::string json; if (!d) return json; if (d->header->root()->isArray()) Internal::arrayToJson(static_cast(d->header->root()), json, 0, (format == Compact)); else Internal::objectToJson(static_cast(d->header->root()), json, 0, (format == Compact)); return json; } #endif /*! Parses a UTF-8 encoded JSON document and creates a JsonDocument from it. \a json contains the json document to be parsed. The optional \a error variable can be used to pass in a JsonParseError data structure that will contain information about possible errors encountered during parsing. \sa toJson(), JsonParseError */ JsonDocument JsonDocument::fromJson(const std::string &json, JsonParseError *error) { Internal::Parser parser(json.data(), static_cast(json.length())); return parser.parse(error); } /*! Returns \c true if the document doesn't contain any data. */ bool JsonDocument::isEmpty() const { if (!d) return true; return false; } /*! Returns a binary representation of the document. The binary representation is also the native format used internally in Qt, and is very efficient and fast to convert to and from. The binary format can be stored on disk and interchanged with other applications or computers. fromBinaryData() can be used to convert it back into a JSON document. \sa fromBinaryData() */ std::string JsonDocument::toBinaryData() const { if (!d || !d->rawData) return std::string(); return std::string(d->rawData, d->header->root()->size + sizeof(Internal::Header)); } /*! Returns \c true if the document contains an array. \sa array(), isObject() */ bool JsonDocument::isArray() const { if (!d) return false; Internal::Header *h = (Internal::Header *)d->rawData; return h->root()->isArray(); } /*! Returns \c true if the document contains an object. \sa object(), isArray() */ bool JsonDocument::isObject() const { if (!d) return false; Internal::Header *h = (Internal::Header *)d->rawData; return h->root()->isObject(); } /*! Returns the JsonObject contained in the document. Returns an empty object if the document contains an array. \sa isObject(), array(), setObject() */ JsonObject JsonDocument::object() const { if (d) { Internal::Base *b = d->header->root(); if (b->isObject()) return JsonObject(d, static_cast(b)); } return {}; } /*! Returns the JsonArray contained in the document. Returns an empty array if the document contains an object. \sa isArray(), object(), setArray() */ JsonArray JsonDocument::array() const { if (d) { Internal::Base *b = d->header->root(); if (b->isArray()) return JsonArray(d, static_cast(b)); } return {}; } /*! Sets \a object as the main object of this document. \sa setArray(), object() */ void JsonDocument::setObject(const JsonObject &object) { if (d && !d->ref.deref()) delete d; d = object.d; if (!d) { d = new Internal::Data(0, JsonValue::Object); } else if (d->compactionCounter || object.o != d->header->root()) { JsonObject o(object); if (d->compactionCounter) o.compact(); else o.detach(); d = o.d; d->ref.ref(); return; } d->ref.ref(); } /*! Sets \a array as the main object of this document. \sa setObject(), array() */ void JsonDocument::setArray(const JsonArray &array) { if (d && !d->ref.deref()) delete d; d = array.d; if (!d) { d = new Internal::Data(0, JsonValue::Array); } else if (d->compactionCounter || array.a != d->header->root()) { JsonArray a(array); if (d->compactionCounter) a.compact(); else a.detach(); d = a.d; d->ref.ref(); return; } d->ref.ref(); } /*! Returns \c true if the \a other document is equal to this document. */ bool JsonDocument::operator==(const JsonDocument &other) const { if (d == other.d) return true; if (!d || !other.d) return false; if (d->header->root()->isArray() != other.d->header->root()->isArray()) return false; if (d->header->root()->isObject()) return JsonObject(d, static_cast(d->header->root())) == JsonObject(other.d, static_cast(other.d->header->root())); else return JsonArray(d, static_cast(d->header->root())) == JsonArray(other.d, static_cast(other.d->header->root())); } /*! \fn bool JsonDocument::operator!=(const JsonDocument &other) const returns \c true if \a other is not equal to this document */ /*! returns \c true if this document is null. Null documents are documents created through the default constructor. Documents created from UTF-8 encoded text or the binary format are validated during parsing. If validation fails, the returned document will also be null. */ bool JsonDocument::isNull() const { return (d == 0); } static void objectContentToJson(const Object *o, std::string &json, int indent, bool compact); static void arrayContentToJson(const Array *a, std::string &json, int indent, bool compact); static uint8_t hexdig(uint32_t u) { return (u < 0xa ? '0' + u : 'a' + u - 0xa); } static std::string escapedString(const std::string &in) { std::string ba; ba.reserve(in.length()); auto src = in.begin(); auto end = in.end(); while (src != end) { uint8_t u = (*src++); if (u < 0x20 || u == 0x22 || u == 0x5c) { ba.push_back('\\'); switch (u) { case 0x22: ba.push_back('"'); break; case 0x5c: ba.push_back('\\'); break; case 0x8: ba.push_back('b'); break; case 0xc: ba.push_back('f'); break; case 0xa: ba.push_back('n'); break; case 0xd: ba.push_back('r'); break; case 0x9: ba.push_back('t'); break; default: ba.push_back('u'); ba.push_back('0'); ba.push_back('0'); ba.push_back(hexdig(u>>4)); ba.push_back(hexdig(u & 0xf)); } } else { ba.push_back(u); } } return ba; } static void valueToJson(const Base *b, const Value &v, std::string &json, int indent, bool compact) { JsonValue::Type type = (JsonValue::Type)(uint32_t)v.type; switch (type) { case JsonValue::Bool: json += v.toBoolean() ? "true" : "false"; break; case JsonValue::Double: { const double d = v.toDouble(b); if (std::isfinite(d)) { // +2 to format to ensure the expected precision const int n = std::numeric_limits::digits10 + 2; char buf[30] = {0}; sprintf(buf, "%.*g", n, d); // Hack: if (buf[0] == '-' && buf[1] == '0' && buf[2] == '\0') json += "0"; else json += buf; } else { json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4) } break; } case JsonValue::String: json += '"'; json += escapedString(v.toString(b)); json += '"'; break; case JsonValue::Array: json += compact ? "[" : "[\n"; arrayContentToJson(static_cast(v.base(b)), json, indent + (compact ? 0 : 1), compact); json += std::string(4*indent, ' '); json += ']'; break; case JsonValue::Object: json += compact ? "{" : "{\n"; objectContentToJson(static_cast(v.base(b)), json, indent + (compact ? 0 : 1), compact); json += std::string(4*indent, ' '); json += '}'; break; case JsonValue::Null: default: json += "null"; } } static void arrayContentToJson(const Array *a, std::string &json, int indent, bool compact) { if (!a || !a->length) return; std::string indentString(4*indent, ' '); uint32_t i = 0; while (1) { json += indentString; valueToJson(a, a->at(i), json, indent, compact); if (++i == a->length) { if (!compact) json += '\n'; break; } json += compact ? "," : ",\n"; } } static void objectContentToJson(const Object *o, std::string &json, int indent, bool compact) { if (!o || !o->length) return; std::string indentString(4*indent, ' '); uint32_t i = 0; while (1) { Entry *e = o->entryAt(i); json += indentString; json += '"'; json += escapedString(e->key()); json += compact ? "\":" : "\": "; valueToJson(o, e->value, json, indent, compact); if (++i == o->length) { if (!compact) json += '\n'; break; } json += compact ? "," : ",\n"; } } namespace Internal { void objectToJson(const Object *o, std::string &json, int indent, bool compact) { json.reserve(json.size() + (o ? (int)o->size : 16)); json += compact ? "{" : "{\n"; objectContentToJson(o, json, indent + (compact ? 0 : 1), compact); json += std::string(4*indent, ' '); json += compact ? "}" : "}\n"; } void arrayToJson(const Array *a, std::string &json, int indent, bool compact) { json.reserve(json.size() + (a ? (int)a->size : 16)); json += compact ? "[" : "[\n"; arrayContentToJson(a, json, indent + (compact ? 0 : 1), compact); json += std::string(4*indent, ' '); json += compact ? "]" : "]\n"; } } /*! \class JsonParseError \inmodule QtCore \ingroup json \ingroup shared \reentrant \since 5.0 \brief The JsonParseError class is used to report errors during JSON parsing. \sa {JSON Support in Qt}, {JSON Save Game Example} */ /*! \enum JsonParseError::ParseError This enum describes the type of error that occurred during the parsing of a JSON document. \value NoError No error occurred \value UnterminatedObject An object is not correctly terminated with a closing curly bracket \value MissingNameSeparator A comma separating different items is missing \value UnterminatedArray The array is not correctly terminated with a closing square bracket \value MissingValueSeparator A colon separating keys from values inside objects is missing \value IllegalValue The value is illegal \value TerminationByNumber The input stream ended while parsing a number \value IllegalNumber The number is not well formed \value IllegalEscapeSequence An illegal escape sequence occurred in the input \value IllegalUTF8String An illegal UTF8 sequence occurred in the input \value UnterminatedString A string wasn't terminated with a quote \value MissingObject An object was expected but couldn't be found \value DeepNesting The JSON document is too deeply nested for the parser to parse it \value DocumentTooLarge The JSON document is too large for the parser to parse it \value GarbageAtEnd The parsed document contains additional garbage characters at the end */ /*! \variable JsonParseError::error Contains the type of the parse error. Is equal to JsonParseError::NoError if the document was parsed correctly. \sa ParseError, errorString() */ /*! \variable JsonParseError::offset Contains the offset in the input string where the parse error occurred. \sa error, errorString() */ using namespace Internal; Parser::Parser(const char *json, int length) : head(json), json(json), data(nullptr), dataLength(0), current(0), nestingLevel(0), lastError(JsonParseError::NoError) { end = json + length; } /* begin-array = ws %x5B ws ; [ left square bracket begin-object = ws %x7B ws ; { left curly bracket end-array = ws %x5D ws ; ] right square bracket end-object = ws %x7D ws ; } right curly bracket name-separator = ws %x3A ws ; : colon value-separator = ws %x2C ws ; , comma Insignificant whitespace is allowed before or after any of the six structural characters. ws = *( %x20 / ; Space %x09 / ; Horizontal tab %x0A / ; Line feed or New line %x0D ; Carriage return ) */ enum { Space = 0x20, Tab = 0x09, LineFeed = 0x0a, Return = 0x0d, BeginArray = 0x5b, BeginObject = 0x7b, EndArray = 0x5d, EndObject = 0x7d, NameSeparator = 0x3a, ValueSeparator = 0x2c, Quote = 0x22 }; void Parser::eatBOM() { // eat UTF-8 byte order mark if (end - json > 3 && (unsigned char)json[0] == 0xef && (unsigned char)json[1] == 0xbb && (unsigned char)json[2] == 0xbf) json += 3; } bool Parser::eatSpace() { while (json < end) { if (*json > Space) break; if (*json != Space && *json != Tab && *json != LineFeed && *json != Return) break; ++json; } return (json < end); } char Parser::nextToken() { if (!eatSpace()) return 0; char token = *json++; switch (token) { case BeginArray: case BeginObject: case NameSeparator: case ValueSeparator: case EndArray: case EndObject: eatSpace(); case Quote: break; default: token = 0; break; } return token; } /* JSON-text = object / array */ JsonDocument Parser::parse(JsonParseError *error) { #ifdef PARSER_DEBUG indent = 0; std::cerr << ">>>>> parser begin"; #endif // allocate some space dataLength = static_cast(std::max(end - json, std::ptrdiff_t(256))); data = (char *)malloc(dataLength); // fill in Header data Header *h = (Header *)data; h->tag = JsonDocument::BinaryFormatTag; h->version = 1u; current = sizeof(Header); eatBOM(); char token = nextToken(); DEBUG << std::hex << (uint32_t)token; if (token == BeginArray) { if (!parseArray()) goto error; } else if (token == BeginObject) { if (!parseObject()) goto error; } else { lastError = JsonParseError::IllegalValue; goto error; } eatSpace(); if (json < end) { lastError = JsonParseError::GarbageAtEnd; goto error; } END; { if (error) { error->offset = 0; error->error = JsonParseError::NoError; } const auto d = new Data(data, current); return {d}; } error: #ifdef PARSER_DEBUG std::cerr << ">>>>> parser error"; #endif if (error) { error->offset = static_cast(json - head); error->error = lastError; } free(data); return {}; } void Parser::ParsedObject::insert(uint32_t offset) { const Entry *newEntry = reinterpret_cast(parser->data + objectPosition + offset); size_t min = 0; size_t n = offsets.size(); while (n > 0) { size_t half = n >> 1; size_t middle = min + half; if (*entryAt(middle) >= *newEntry) { n = half; } else { min = middle + 1; n -= half + 1; } } if (min < offsets.size() && *entryAt(min) == *newEntry) { offsets[min] = offset; } else { offsets.insert(offsets.begin() + min, offset); } } /* object = begin-object [ member *( value-separator member ) ] end-object */ bool Parser::parseObject() { if (++nestingLevel > nestingLimit) { lastError = JsonParseError::DeepNesting; return false; } int objectOffset = reserveSpace(sizeof(Object)); BEGIN << "parseObject pos=" << objectOffset << current << json; ParsedObject parsedObject(this, objectOffset); char token = nextToken(); while (token == Quote) { int off = current - objectOffset; if (!parseMember(objectOffset)) return false; parsedObject.insert(off); token = nextToken(); if (token != ValueSeparator) break; token = nextToken(); if (token == EndObject) { lastError = JsonParseError::MissingObject; return false; } } DEBUG << "end token=" << token; if (token != EndObject) { lastError = JsonParseError::UnterminatedObject; return false; } DEBUG << "numEntries" << parsedObject.offsets.size(); int table = objectOffset; // finalize the object if (parsedObject.offsets.size()) { int tableSize = static_cast(parsedObject.offsets.size()) * sizeof(uint32_t); table = reserveSpace(tableSize); memcpy(data + table, &*parsedObject.offsets.begin(), tableSize); } Object *o = (Object *)(data + objectOffset); o->tableOffset = table - objectOffset; o->size = current - objectOffset; o->is_object = true; o->length = static_cast(parsedObject.offsets.size()); DEBUG << "current=" << current; END; --nestingLevel; return true; } /* member = string name-separator value */ bool Parser::parseMember(int baseOffset) { int entryOffset = reserveSpace(sizeof(Entry)); BEGIN << "parseMember pos=" << entryOffset; if (!parseString()) return false; char token = nextToken(); if (token != NameSeparator) { lastError = JsonParseError::MissingNameSeparator; return false; } Value val; if (!parseValue(&val, baseOffset)) return false; // finalize the entry Entry *e = (Entry *)(data + entryOffset); e->value = val; END; return true; } /* array = begin-array [ value *( value-separator value ) ] end-array */ bool Parser::parseArray() { BEGIN << "parseArray"; if (++nestingLevel > nestingLimit) { lastError = JsonParseError::DeepNesting; return false; } int arrayOffset = reserveSpace(sizeof(Array)); std::vector values; values.reserve(64); if (!eatSpace()) { lastError = JsonParseError::UnterminatedArray; return false; } if (*json == EndArray) { nextToken(); } else { while (1) { Value val; if (!parseValue(&val, arrayOffset)) return false; values.push_back(val); char token = nextToken(); if (token == EndArray) break; else if (token != ValueSeparator) { if (!eatSpace()) lastError = JsonParseError::UnterminatedArray; else lastError = JsonParseError::MissingValueSeparator; return false; } } } DEBUG << "size =" << values.size(); int table = arrayOffset; // finalize the object if (values.size()) { int tableSize = static_cast(values.size() * sizeof(Value)); table = reserveSpace(tableSize); memcpy(data + table, values.data(), tableSize); } Array *a = (Array *)(data + arrayOffset); a->tableOffset = table - arrayOffset; a->size = current - arrayOffset; a->is_object = false; a->length = static_cast(values.size()); DEBUG << "current=" << current; END; --nestingLevel; return true; } /* value = false / null / true / object / array / number / string */ bool Parser::parseValue(Value *val, int baseOffset) { BEGIN << "parse Value" << json; val->_dummy = 0; switch (*json++) { case 'n': if (end - json < 4) { lastError = JsonParseError::IllegalValue; return false; } if (*json++ == 'u' && *json++ == 'l' && *json++ == 'l') { val->type = JsonValue::Null; DEBUG << "value: null"; END; return true; } lastError = JsonParseError::IllegalValue; return false; case 't': if (end - json < 4) { lastError = JsonParseError::IllegalValue; return false; } if (*json++ == 'r' && *json++ == 'u' && *json++ == 'e') { val->type = JsonValue::Bool; val->value = true; DEBUG << "value: true"; END; return true; } lastError = JsonParseError::IllegalValue; return false; case 'f': if (end - json < 5) { lastError = JsonParseError::IllegalValue; return false; } if (*json++ == 'a' && *json++ == 'l' && *json++ == 's' && *json++ == 'e') { val->type = JsonValue::Bool; val->value = false; DEBUG << "value: false"; END; return true; } lastError = JsonParseError::IllegalValue; return false; case Quote: { val->type = JsonValue::String; if (current - baseOffset >= Value::MaxSize) { lastError = JsonParseError::DocumentTooLarge; return false; } val->value = current - baseOffset; if (!parseString()) return false; val->intValue = false; DEBUG << "value: string"; END; return true; } case BeginArray: val->type = JsonValue::Array; if (current - baseOffset >= Value::MaxSize) { lastError = JsonParseError::DocumentTooLarge; return false; } val->value = current - baseOffset; if (!parseArray()) return false; DEBUG << "value: array"; END; return true; case BeginObject: val->type = JsonValue::Object; if (current - baseOffset >= Value::MaxSize) { lastError = JsonParseError::DocumentTooLarge; return false; } val->value = current - baseOffset; if (!parseObject()) return false; DEBUG << "value: object"; END; return true; case EndArray: lastError = JsonParseError::MissingObject; return false; default: --json; if (!parseNumber(val, baseOffset)) return false; DEBUG << "value: number"; END; } return true; } /* number = [ minus ] int [ frac ] [ exp ] decimal-point = %x2E ; . digit1-9 = %x31-39 ; 1-9 e = %x65 / %x45 ; e E exp = e [ minus / plus ] 1*DIGIT frac = decimal-point 1*DIGIT int = zero / ( digit1-9 *DIGIT ) minus = %x2D ; - plus = %x2B ; + zero = %x30 ; 0 */ bool Parser::parseNumber(Value *val, int baseOffset) { BEGIN << "parseNumber" << json; val->type = JsonValue::Double; const char *start = json; bool isInt = true; // minus if (json < end && *json == '-') ++json; // int = zero / ( digit1-9 *DIGIT ) if (json < end && *json == '0') { ++json; } else { while (json < end && *json >= '0' && *json <= '9') ++json; } // frac = decimal-point 1*DIGIT if (json < end && *json == '.') { isInt = false; ++json; while (json < end && *json >= '0' && *json <= '9') ++json; } // exp = e [ minus / plus ] 1*DIGIT if (json < end && (*json == 'e' || *json == 'E')) { isInt = false; ++json; if (json < end && (*json == '-' || *json == '+')) ++json; while (json < end && *json >= '0' && *json <= '9') ++json; } if (json >= end) { lastError = JsonParseError::TerminationByNumber; return false; } if (isInt) { char *endptr = const_cast(json); long long int n = strtoll(start, &endptr, 0); if (endptr != start && n < (1<<25) && n > -(1<<25)) { val->int_value = int(n); val->intValue = true; END; return true; } } char *endptr = const_cast(json); double d = strtod(start, &endptr); if (start == endptr || std::isinf(d)) { lastError = JsonParseError::IllegalNumber; return false; } int pos = reserveSpace(sizeof(double)); memcpy(data + pos, &d, sizeof(double)); if (current - baseOffset >= Value::MaxSize) { lastError = JsonParseError::DocumentTooLarge; return false; } val->value = pos - baseOffset; val->intValue = false; END; return true; } /* string = quotation-mark *char quotation-mark char = unescaped / escape ( %x22 / ; " quotation mark U+0022 %x5C / ; \ reverse solidus U+005C %x2F / ; / solidus U+002F %x62 / ; b backspace U+0008 %x66 / ; f form feed U+000C %x6E / ; n line feed U+000A %x72 / ; r carriage return U+000D %x74 / ; t tab U+0009 %x75 4HEXDIG ) ; uXXXX U+XXXX escape = %x5C ; \ quotation-mark = %x22 ; " unescaped = %x20-21 / %x23-5B / %x5D-10FFFF */ static bool addHexDigit(char digit, uint32_t *result) { *result <<= 4; if (digit >= '0' && digit <= '9') *result |= (digit - '0'); else if (digit >= 'a' && digit <= 'f') *result |= (digit - 'a') + 10; else if (digit >= 'A' && digit <= 'F') *result |= (digit - 'A') + 10; else return false; return true; } bool Parser::parseEscapeSequence() { DEBUG << "scan escape" << (char)*json; const char escaped = *json++; switch (escaped) { case '"': addChar('"'); break; case '\\': addChar('\\'); break; case '/': addChar('/'); break; case 'b': addChar(0x8); break; case 'f': addChar(0xc); break; case 'n': addChar(0xa); break; case 'r': addChar(0xd); break; case 't': addChar(0x9); break; case 'u': { uint32_t c = 0; if (json > end - 4) return false; for (int i = 0; i < 4; ++i) { if (!addHexDigit(*json, &c)) return false; ++json; } if (c < 0x80) { addChar(c); break; } if (c < 0x800) { addChar(192 + c / 64); addChar(128 + c % 64); break; } if (c - 0xd800u < 0x800) { return false; } if (c < 0x10000) { addChar(224 + c / 4096); addChar(128 + c / 64 % 64); addChar(128 + c % 64); break; } if (c < 0x110000) { addChar(240 + c / 262144); addChar(128 + c / 4096 % 64); addChar(128 + c / 64 % 64); addChar(128 + c % 64); break; } return false; } default: // this is not as strict as one could be, but allows for more Json files // to be parsed correctly. addChar(escaped); break; } return true; } bool Parser::parseString() { const char *inStart = json; // First try quick pass without escapes. if (true) { while (1) { if (json >= end) { ++json; lastError = JsonParseError::UnterminatedString; return false; } const char c = *json; if (c == '"') { // write string length and padding. const int len = static_cast(json - inStart); const int pos = reserveSpace(4 + alignedSize(len)); toInternal(data + pos, inStart, len); END; ++json; return true; } if (c == '\\') break; ++json; } } // Try again with escapes. const int outStart = reserveSpace(4); json = inStart; while (1) { if (json >= end) { ++json; lastError = JsonParseError::UnterminatedString; return false; } if (*json == '"') { ++json; // write string length and padding. *(int *)(data + outStart) = current - outStart - 4; reserveSpace((4 - current) & 3); END; return true; } if (*json == '\\') { ++json; if (json >= end || !parseEscapeSequence()) { lastError = JsonParseError::IllegalEscapeSequence; return false; } } else { addChar(*json++); } } } namespace Internal { static const Base emptyArray = {sizeof(Base), {0}, 0}; static const Base emptyObject = {sizeof(Base), {0}, 0}; void Data::compact() { // assert(sizeof(Value) == sizeof(offset)); if (!compactionCounter) return; Base *base = header->root(); int reserve = 0; if (base->is_object) { const auto o = static_cast(base); for (int i = 0; i < (int)o->length; ++i) reserve += o->entryAt(i)->usedStorage(o); } else { const auto a = static_cast(base); for (int i = 0; i < (int)a->length; ++i) reserve += (*a)[i].usedStorage(a); } int size = sizeof(Base) + reserve + base->length*sizeof(offset); int alloc = sizeof(Header) + size; Header *h = (Header *) malloc(alloc); h->tag = JsonDocument::BinaryFormatTag; h->version = 1; Base *b = h->root(); b->size = size; b->is_object = header->root()->is_object; b->length = base->length; b->tableOffset = reserve + sizeof(Array); int offset = sizeof(Base); if (b->is_object) { const auto o = static_cast(base); const auto no = static_cast(b); for (int i = 0; i < (int)o->length; ++i) { no->table()[i] = offset; const Entry *e = o->entryAt(i); Entry *ne = no->entryAt(i); int s = e->size(); memcpy(ne, e, s); offset += s; int dataSize = e->value.usedStorage(o); if (dataSize) { memcpy((char *)no + offset, e->value.data(o), dataSize); ne->value.value = offset; offset += dataSize; } } } else { const auto a = static_cast(base); const auto na = static_cast(b); for (int i = 0; i < (int)a->length; ++i) { const Value &v = (*a)[i]; Value &nv = (*na)[i]; nv = v; int dataSize = v.usedStorage(a); if (dataSize) { memcpy((char *)na + offset, v.data(a), dataSize); nv.value = offset; offset += dataSize; } } } // assert(offset == (int)b->tableOffset); free(header); header = h; this->alloc = alloc; compactionCounter = 0; } bool Data::valid() const { if (header->tag != JsonDocument::BinaryFormatTag || header->version != 1u) return false; bool res = false; if (header->root()->is_object) res = static_cast(header->root())->isValid(); else res = static_cast(header->root())->isValid(); return res; } int Base::reserveSpace(uint32_t dataSize, int posInTable, uint32_t numItems, bool replace) { // assert(posInTable >= 0 && posInTable <= (int)length); if (size + dataSize >= Value::MaxSize) { fprintf(stderr, "Json: Document too large to store in data structure %d %d %d\n", (uint32_t)size, dataSize, Value::MaxSize); return 0; } offset off = tableOffset; // move table to new position if (replace) { memmove((char *)(table()) + dataSize, table(), length*sizeof(offset)); } else { memmove((char *)(table() + posInTable + numItems) + dataSize, table() + posInTable, (length - posInTable)*sizeof(offset)); memmove((char *)(table()) + dataSize, table(), posInTable*sizeof(offset)); } tableOffset += dataSize; for (int i = 0; i < (int)numItems; ++i) table()[posInTable + i] = off; size += dataSize; if (!replace) { length += numItems; size += numItems * sizeof(offset); } return off; } void Base::removeItems(int pos, int numItems) { // assert(pos >= 0 && pos <= (int)length); if (pos + numItems < (int)length) memmove(table() + pos, table() + pos + numItems, (length - pos - numItems)*sizeof(offset)); length -= numItems; } int Object::indexOf(const std::string &key, bool *exists) { int min = 0; int n = length; while (n > 0) { int half = n >> 1; int middle = min + half; if (*entryAt(middle) >= key) { n = half; } else { min = middle + 1; n -= half + 1; } } if (min < (int)length && *entryAt(min) == key) { *exists = true; return min; } *exists = false; return min; } bool Object::isValid() const { if (tableOffset + length*sizeof(offset) > size) return false; std::string lastKey; for (uint32_t i = 0; i < length; ++i) { offset entryOffset = table()[i]; if (entryOffset + sizeof(Entry) >= tableOffset) return false; Entry *e = entryAt(i); int s = e->size(); if (table()[i] + s > tableOffset) return false; std::string key = e->key(); if (key < lastKey) return false; if (!e->value.isValid(this)) return false; lastKey = key; } return true; } bool Array::isValid() const { if (tableOffset + length*sizeof(offset) > size) return false; for (uint32_t i = 0; i < length; ++i) { if (!at(i).isValid(this)) return false; } return true; } bool Entry::operator==(const std::string &key) const { return shallowKey() == key; } bool Entry::operator==(const Entry &other) const { return shallowKey() == other.shallowKey(); } bool Entry::operator>=(const Entry &other) const { return shallowKey() >= other.shallowKey(); } int Value::usedStorage(const Base *b) const { int s = 0; switch (type) { case JsonValue::Double: if (intValue) break; s = sizeof(double); break; case JsonValue::String: { char *d = data(b); s = sizeof(int) + (*(int *)d); break; } case JsonValue::Array: case JsonValue::Object: s = base(b)->size; break; case JsonValue::Null: case JsonValue::Bool: default: break; } return alignedSize(s); } bool Value::isValid(const Base *b) const { int offset = 0; switch (type) { case JsonValue::Double: if (intValue) break; // fall through case JsonValue::String: case JsonValue::Array: case JsonValue::Object: offset = value; break; case JsonValue::Null: case JsonValue::Bool: default: break; } if (!offset) return true; if (offset + sizeof(uint32_t) > b->tableOffset) return false; int s = usedStorage(b); if (!s) return true; if (s < 0 || offset + s > (int)b->tableOffset) return false; if (type == JsonValue::Array) return static_cast(base(b))->isValid(); if (type == JsonValue::Object) return static_cast(base(b))->isValid(); return true; } /*! \internal */ int Value::requiredStorage(JsonValue &v, bool *compressed) { *compressed = false; switch (v.t) { case JsonValue::Double: if (Internal::compressedNumber(v.dbl) != INT_MAX) { *compressed = true; return 0; } return sizeof(double); case JsonValue::String: { std::string s = v.toString().data(); *compressed = false; return Internal::qStringSize(s); } case JsonValue::Array: case JsonValue::Object: if (v.d && v.d->compactionCounter) { v.detach(); v.d->compact(); v.base = static_cast(v.d->header->root()); } return v.base ? v.base->size : sizeof(Internal::Base); case JsonValue::Undefined: case JsonValue::Null: case JsonValue::Bool: break; } return 0; } /*! \internal */ uint32_t Value::valueToStore(const JsonValue &v, uint32_t offset) { switch (v.t) { case JsonValue::Undefined: case JsonValue::Null: break; case JsonValue::Bool: return v.b; case JsonValue::Double: { int c = Internal::compressedNumber(v.dbl); if (c != INT_MAX) return c; } // fall through case JsonValue::String: case JsonValue::Array: case JsonValue::Object: return offset; } return 0; } /*! \internal */ void Value::copyData(const JsonValue &v, char *dest, bool compressed) { switch (v.t) { case JsonValue::Double: if (!compressed) memcpy(dest, &v.ui, 8); break; case JsonValue::String: { std::string str = v.toString(); Internal::copyString(dest, str); break; } case JsonValue::Array: case JsonValue::Object: { const Internal::Base *b = v.base; if (!b) b = (v.t == JsonValue::Array ? &emptyArray : &emptyObject); memcpy(dest, b, b->size); break; } default: break; } } } // namespace Internal } // namespace Json qbs-src-1.13.1/src/shared/json/json.h000066400000000000000000000500401347155106100173010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef JSON_H #define JSON_H #include #include #include #include namespace Json { class JsonArray; class JsonObject; namespace Internal { class Data; class Base; class Object; class Header; class Array; class Value; class Entry; class SharedString; class Parser; } class JsonValue { public: enum Type { Null = 0x0, Bool = 0x1, Double = 0x2, String = 0x3, Array = 0x4, Object = 0x5, Undefined = 0x80 }; JsonValue(Type = Null); JsonValue(bool b); JsonValue(double n); JsonValue(int n); JsonValue(int64_t n); JsonValue(const std::string &s); JsonValue(const char *s); JsonValue(const JsonArray &a); JsonValue(const JsonObject &o); ~JsonValue(); JsonValue(const JsonValue &other); JsonValue &operator =(const JsonValue &other); Type type() const { return t; } bool isNull() const { return t == Null; } bool isBool() const { return t == Bool; } bool isDouble() const { return t == Double; } bool isString() const { return t == String; } bool isArray() const { return t == Array; } bool isObject() const { return t == Object; } bool isUndefined() const { return t == Undefined; } bool toBool(bool defaultValue = false) const; int toInt(int defaultValue = 0) const; double toDouble(double defaultValue = 0) const; std::string toString(const std::string &defaultValue = std::string()) const; JsonArray toArray() const; JsonArray toArray(const JsonArray &defaultValue) const; JsonObject toObject() const; JsonObject toObject(const JsonObject &defaultValue) const; bool operator==(const JsonValue &other) const; bool operator!=(const JsonValue &other) const; private: // avoid implicit conversions from char * to bool JsonValue(const void *) : t(Null) {} friend class Internal::Value; friend class JsonArray; friend class JsonObject; JsonValue(Internal::Data *d, Internal::Base *b, const Internal::Value& v); void detach(); union { uint64_t ui; bool b; double dbl; Internal::SharedString *stringData; Internal::Base *base; }; Internal::Data *d; // needed for Objects and Arrays Type t; }; class JsonValueRef { public: JsonValueRef(JsonArray *array, int idx) : a(array), is_object(false), index(idx) {} JsonValueRef(JsonObject *object, int idx) : o(object), is_object(true), index(idx) {} operator JsonValue() const { return toValue(); } JsonValueRef &operator=(const JsonValue &val); JsonValueRef &operator=(const JsonValueRef &val); JsonValue::Type type() const { return toValue().type(); } bool isNull() const { return type() == JsonValue::Null; } bool isBool() const { return type() == JsonValue::Bool; } bool isDouble() const { return type() == JsonValue::Double; } bool isString() const { return type() == JsonValue::String; } bool isArray() const { return type() == JsonValue::Array; } bool isObject() const { return type() == JsonValue::Object; } bool isUndefined() const { return type() == JsonValue::Undefined; } std::string toString() const { return toValue().toString(); } JsonArray toArray() const; JsonObject toObject() const; bool toBool(bool defaultValue = false) const { return toValue().toBool(defaultValue); } int toInt(int defaultValue = 0) const { return toValue().toInt(defaultValue); } double toDouble(double defaultValue = 0) const { return toValue().toDouble(defaultValue); } std::string toString(const std::string &defaultValue) const { return toValue().toString(defaultValue); } bool operator==(const JsonValue &other) const { return toValue() == other; } bool operator!=(const JsonValue &other) const { return toValue() != other; } private: JsonValue toValue() const; union { JsonArray *a; JsonObject *o; }; uint32_t is_object : 1; uint32_t index : 31; }; class JsonValuePtr { JsonValue value; public: explicit JsonValuePtr(const JsonValue& val) : value(val) {} JsonValue& operator*() { return value; } JsonValue* operator->() { return &value; } }; class JsonValueRefPtr { JsonValueRef valueRef; public: JsonValueRefPtr(JsonArray *array, int idx) : valueRef(array, idx) {} JsonValueRefPtr(JsonObject *object, int idx) : valueRef(object, idx) {} JsonValueRef& operator*() { return valueRef; } JsonValueRef* operator->() { return &valueRef; } }; class JsonArray { public: JsonArray(); JsonArray(std::initializer_list args); ~JsonArray(); JsonArray(const JsonArray &other); JsonArray &operator=(const JsonArray &other); int size() const; int count() const { return size(); } bool isEmpty() const; JsonValue at(int i) const; JsonValue first() const; JsonValue last() const; void prepend(const JsonValue &value); void append(const JsonValue &value); void removeAt(int i); JsonValue takeAt(int i); void removeFirst() { removeAt(0); } void removeLast() { removeAt(size() - 1); } void insert(int i, const JsonValue &value); void replace(int i, const JsonValue &value); bool contains(const JsonValue &element) const; JsonValueRef operator[](int i); JsonValue operator[](int i) const; bool operator==(const JsonArray &other) const; bool operator!=(const JsonArray &other) const; class const_iterator; class iterator { public: JsonArray *a; int i; using iterator_category = std::random_access_iterator_tag; using difference_type = int; using value_type = JsonValue; using reference = JsonValueRef; using pointer = JsonValueRefPtr; iterator() : a(nullptr), i(0) { } explicit iterator(JsonArray *array, int index) : a(array), i(index) { } JsonValueRef operator*() const { return JsonValueRef(a, i); } JsonValueRefPtr operator->() const { return JsonValueRefPtr(a, i); } JsonValueRef operator[](int j) const { return JsonValueRef(a, i + j); } bool operator==(const iterator &o) const { return i == o.i; } bool operator!=(const iterator &o) const { return i != o.i; } bool operator<(const iterator& other) const { return i < other.i; } bool operator<=(const iterator& other) const { return i <= other.i; } bool operator>(const iterator& other) const { return i > other.i; } bool operator>=(const iterator& other) const { return i >= other.i; } bool operator==(const const_iterator &o) const { return i == o.i; } bool operator!=(const const_iterator &o) const { return i != o.i; } bool operator<(const const_iterator& other) const { return i < other.i; } bool operator<=(const const_iterator& other) const { return i <= other.i; } bool operator>(const const_iterator& other) const { return i > other.i; } bool operator>=(const const_iterator& other) const { return i >= other.i; } iterator &operator++() { ++i; return *this; } iterator operator++(int) { iterator n = *this; ++i; return n; } iterator &operator--() { i--; return *this; } iterator operator--(int) { iterator n = *this; i--; return n; } iterator &operator+=(int j) { i+=j; return *this; } iterator &operator-=(int j) { i-=j; return *this; } iterator operator+(int j) const { return iterator(a, i+j); } iterator operator-(int j) const { return iterator(a, i-j); } int operator-(iterator j) const { return i - j.i; } }; friend class iterator; class const_iterator { public: const JsonArray *a; int i; using iterator_category = std::random_access_iterator_tag; using difference_type = std::ptrdiff_t; using value_type = JsonValue; using reference = JsonValue; using pointer = JsonValuePtr; const_iterator() : a(nullptr), i(0) { } explicit const_iterator(const JsonArray *array, int index) : a(array), i(index) { } const_iterator(const iterator &o) : a(o.a), i(o.i) {} JsonValue operator*() const { return a->at(i); } JsonValuePtr operator->() const { return JsonValuePtr(a->at(i)); } JsonValue operator[](int j) const { return a->at(i+j); } bool operator==(const const_iterator &o) const { return i == o.i; } bool operator!=(const const_iterator &o) const { return i != o.i; } bool operator<(const const_iterator& other) const { return i < other.i; } bool operator<=(const const_iterator& other) const { return i <= other.i; } bool operator>(const const_iterator& other) const { return i > other.i; } bool operator>=(const const_iterator& other) const { return i >= other.i; } const_iterator &operator++() { ++i; return *this; } const_iterator operator++(int) { const_iterator n = *this; ++i; return n; } const_iterator &operator--() { i--; return *this; } const_iterator operator--(int) { const_iterator n = *this; i--; return n; } const_iterator &operator+=(int j) { i+=j; return *this; } const_iterator &operator-=(int j) { i-=j; return *this; } const_iterator operator+(int j) const { return const_iterator(a, i+j); } const_iterator operator-(int j) const { return const_iterator(a, i-j); } int operator-(const_iterator j) const { return i - j.i; } }; friend class const_iterator; // stl style iterator begin() { detach(); return iterator(this, 0); } const_iterator begin() const { return const_iterator(this, 0); } const_iterator constBegin() const { return const_iterator(this, 0); } iterator end() { detach(); return iterator(this, size()); } const_iterator end() const { return const_iterator(this, size()); } const_iterator constEnd() const { return const_iterator(this, size()); } iterator insert(iterator before, const JsonValue &value) { insert(before.i, value); return before; } iterator erase(iterator it) { removeAt(it.i); return it; } void push_back(const JsonValue &t) { append(t); } void push_front(const JsonValue &t) { prepend(t); } void pop_front() { removeFirst(); } void pop_back() { removeLast(); } bool empty() const { return isEmpty(); } using size_type = int ; using value_type = JsonValue; using pointer = value_type *; using const_pointer = const value_type *; using reference = JsonValueRef; using const_reference = JsonValue; using difference_type = int; private: friend class Internal::Data; friend class JsonValue; friend class JsonDocument; JsonArray(Internal::Data *data, Internal::Array *array); void compact(); void detach(uint32_t reserve = 0); Internal::Data *d; Internal::Array *a; }; class JsonObject { public: JsonObject(); JsonObject(std::initializer_list > args); ~JsonObject(); JsonObject(const JsonObject &other); JsonObject &operator =(const JsonObject &other); using Keys = std::vector; Keys keys() const; int size() const; int count() const { return size(); } int length() const { return size(); } bool isEmpty() const; JsonValue value(const std::string &key) const; JsonValue operator[] (const std::string &key) const; JsonValueRef operator[] (const std::string &key); void remove(const std::string &key); JsonValue take(const std::string &key); bool contains(const std::string &key) const; bool operator==(const JsonObject &other) const; bool operator!=(const JsonObject &other) const; class const_iterator; class iterator { friend class const_iterator; friend class JsonObject; JsonObject *o; int i; public: using iterator_category = std::bidirectional_iterator_tag; using difference_type = int; using value_type = JsonValue; using reference = JsonValueRef; iterator() : o(nullptr), i(0) {} iterator(JsonObject *obj, int index) : o(obj), i(index) {} std::string key() const { return o->keyAt(i); } JsonValueRef value() const { return JsonValueRef(o, i); } JsonValueRef operator*() const { return JsonValueRef(o, i); } JsonValueRefPtr operator->() const { return JsonValueRefPtr(o, i); } bool operator==(const iterator &other) const { return i == other.i; } bool operator!=(const iterator &other) const { return i != other.i; } iterator &operator++() { ++i; return *this; } iterator operator++(int) { iterator r = *this; ++i; return r; } iterator &operator--() { --i; return *this; } iterator operator--(int) { iterator r = *this; --i; return r; } iterator operator+(int j) const { iterator r = *this; r.i += j; return r; } iterator operator-(int j) const { return operator+(-j); } iterator &operator+=(int j) { i += j; return *this; } iterator &operator-=(int j) { i -= j; return *this; } public: bool operator==(const const_iterator &other) const { return i == other.i; } bool operator!=(const const_iterator &other) const { return i != other.i; } }; friend class iterator; class const_iterator { friend class iterator; const JsonObject *o; int i; public: using iterator_category = std::bidirectional_iterator_tag; using difference_type = int; using value_type = JsonValue; using reference = JsonValue; const_iterator() : o(nullptr), i(0) {} const_iterator(const JsonObject *obj, int index) : o(obj), i(index) {} const_iterator(const iterator &other) : o(other.o), i(other.i) {} std::string key() const { return o->keyAt(i); } JsonValue value() const { return o->valueAt(i); } JsonValue operator*() const { return o->valueAt(i); } JsonValuePtr operator->() const { return JsonValuePtr(o->valueAt(i)); } bool operator==(const const_iterator &other) const { return i == other.i; } bool operator!=(const const_iterator &other) const { return i != other.i; } const_iterator &operator++() { ++i; return *this; } const_iterator operator++(int) { const_iterator r = *this; ++i; return r; } const_iterator &operator--() { --i; return *this; } const_iterator operator--(int) { const_iterator r = *this; --i; return r; } const_iterator operator+(int j) const { const_iterator r = *this; r.i += j; return r; } const_iterator operator-(int j) const { return operator+(-j); } const_iterator &operator+=(int j) { i += j; return *this; } const_iterator &operator-=(int j) { i -= j; return *this; } bool operator==(const iterator &other) const { return i == other.i; } bool operator!=(const iterator &other) const { return i != other.i; } }; friend class const_iterator; // STL style iterator begin() { detach(); return iterator(this, 0); } const_iterator begin() const { return const_iterator(this, 0); } const_iterator constBegin() const { return const_iterator(this, 0); } iterator end() { detach(); return iterator(this, size()); } const_iterator end() const { return const_iterator(this, size()); } const_iterator constEnd() const { return const_iterator(this, size()); } iterator erase(iterator it); // more Qt iterator find(const std::string &key); const_iterator find(const std::string &key) const { return constFind(key); } const_iterator constFind(const std::string &key) const; iterator insert(const std::string &key, const JsonValue &value); // STL compatibility using mapped_type = JsonValue; using key_type = std::string; using size_type = int; bool empty() const { return isEmpty(); } private: friend class Internal::Data; friend class JsonValue; friend class JsonDocument; friend class JsonValueRef; JsonObject(Internal::Data *data, Internal::Object *object); void detach(uint32_t reserve = 0); void compact(); std::string keyAt(int i) const; JsonValue valueAt(int i) const; void setValueAt(int i, const JsonValue &val); Internal::Data *d; Internal::Object *o; }; struct JsonParseError { enum ParseError { NoError = 0, UnterminatedObject, MissingNameSeparator, UnterminatedArray, MissingValueSeparator, IllegalValue, TerminationByNumber, IllegalNumber, IllegalEscapeSequence, IllegalUTF8String, UnterminatedString, MissingObject, DeepNesting, DocumentTooLarge, GarbageAtEnd }; int offset; ParseError error; }; class JsonDocument { public: static const uint32_t BinaryFormatTag = ('q') | ('b' << 8) | ('j' << 16) | ('s' << 24); JsonDocument(); explicit JsonDocument(const JsonObject &object); explicit JsonDocument(const JsonArray &array); ~JsonDocument(); JsonDocument(const JsonDocument &other); JsonDocument &operator =(const JsonDocument &other); enum DataValidation { Validate, BypassValidation }; static JsonDocument fromRawData(const char *data, int size, DataValidation validation = Validate); const char *rawData(int *size) const; static JsonDocument fromBinaryData(const std::string &data, DataValidation validation = Validate); std::string toBinaryData() const; enum JsonFormat { Indented, Compact }; static JsonDocument fromJson(const std::string &json, JsonParseError *error = nullptr); std::string toJson(JsonFormat format = Indented) const; bool isEmpty() const; bool isArray() const; bool isObject() const; JsonObject object() const; JsonArray array() const; void setObject(const JsonObject &object); void setArray(const JsonArray &array); bool operator==(const JsonDocument &other) const; bool operator!=(const JsonDocument &other) const { return !(*this == other); } bool isNull() const; private: friend class JsonValue; friend class Internal::Data; friend class Internal::Parser; JsonDocument(Internal::Data *data); Internal::Data *d; }; } // namespace Json #endif // JSON_H qbs-src-1.13.1/src/shared/json/json.pri000066400000000000000000000001071347155106100176430ustar00rootroot00000000000000INCLUDEPATH += $$PWD HEADERS += $$PWD/json.h SOURCES += $$PWD/json.cpp qbs-src-1.13.1/src/shared/json/json.qbs000066400000000000000000000004661347155106100176460ustar00rootroot00000000000000import qbs StaticLibrary { name: "qbsjson" Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++14" cpp.minimumMacosVersion: "10.7" files: [ "json.cpp", "json.h", ] Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory] } } qbs-src-1.13.1/src/shared/qtscript/000077500000000000000000000000001347155106100170605ustar00rootroot00000000000000qbs-src-1.13.1/src/src.qbs000066400000000000000000000004111347155106100152330ustar00rootroot00000000000000import qbs Project { references: [ "app/apps.qbs", "lib/libs.qbs", "libexec/libexec.qbs", "packages/packages.qbs", "plugins/plugins.qbs", "shared/json/json.qbs", "shared/bundledqt/bundledqt.qbs", ] } qbs-src-1.13.1/static-res.pro000066400000000000000000000050541347155106100157560ustar00rootroot00000000000000TEMPLATE = aux !isEmpty(QBS_APPS_DESTDIR): qbsbindir = $${QBS_APPS_DESTDIR} else: qbsbindir = bin envSpec = unix:qbs_disable_rpath { !isEmpty(QBS_DESTDIR): qbslibdir = $$QBS_DESTDIR else: qbslibdir = $$OUT_PWD/lib macos: envVar = DYLD_LIBRARY_PATH else: envVar = LD_LIBRARY_PATH oldVal = $$getenv($$envVar) newVal = $$qbslibdir !isEmpty(oldVal): newVal = $$newVal:$$oldVal envSpec = $$envVar=$$newVal } builddirname = qbsres typedescdir = share/qbs/qml-type-descriptions typedescdir_src = $$builddirname/default/install-root/$$typedescdir !isEmpty(QBS_QML_TYPE_DESCRIPTIONS_BUILD_DIR): \ typedescdir_dst = $$QBS_QML_TYPE_DESCRIPTIONS_BUILD_DIR else:!isEmpty(QBS_RESOURCES_BUILD_DIR): \ typedescdir_dst = $$QBS_RESOURCES_BUILD_DIR/$$typedescdir else: \ typedescdir_dst = $$typedescdir qbsres.target = $$builddirname/default/default.bg qbsres.commands = \ $$envSpec $$shell_quote($$shell_path($$qbsbindir/qbs)) \ build \ --settings-dir $$shell_quote($$builddirname/settings) \ -f $$shell_quote($$PWD/qbs.qbs) \ -d $$shell_quote($$builddirname) \ -p $$shell_quote("qbs resources") \ qbs.installPrefix:undefined \ project.withCode:false \ project.withDocumentation:false \ profile:none qbsqmltypes.target = $$typedescdir_dst/qbs.qmltypes qbsqmltypes.commands = \ $$sprintf($$QMAKE_MKDIR_CMD, \ $$shell_quote($$shell_path($$typedescdir_dst))) $$escape_expand(\\n\\t) \ $$QMAKE_COPY \ $$shell_quote($$shell_path($$typedescdir_src/qbs.qmltypes)) \ $$shell_quote($$shell_path($$typedescdir_dst/qbs.qmltypes)) qbsqmltypes.depends += qbsres qbsbundle.target = $$typedescdir_dst/qbs-bundle.json qbsbundle.commands = \ $$sprintf($$QMAKE_MKDIR_CMD, \ $$shell_quote($$shell_path($$typedescdir_dst))) $$escape_expand(\\n\\t) \ $$QMAKE_COPY \ $$shell_quote($$shell_path($$typedescdir_src/qbs-bundle.json)) \ $$shell_quote($$shell_path($$typedescdir_dst/qbs-bundle.json)) qbsbundle.depends += qbsres QMAKE_EXTRA_TARGETS += qbsres qbsqmltypes qbsbundle PRE_TARGETDEPS += $$qbsqmltypes.target $$qbsbundle.target include(src/install_prefix.pri) qbstypedescfiles.files = $$qbsqmltypes.target $$qbsbundle.target !isEmpty(QBS_QML_TYPE_DESCRIPTIONS_INSTALL_DIR): \ installPrefix = $${QBS_QML_TYPE_DESCRIPTIONS_INSTALL_DIR} else:!isEmpty(QBS_RESOURCES_INSTALL_DIR): \ installPrefix = $${QBS_RESOURCES_INSTALL_DIR}/$$typedescdir else: \ installPrefix = $${QBS_INSTALL_PREFIX}/$$typedescdir qbstypedescfiles.path = $${installPrefix} INSTALLS += qbstypedescfiles qbs-src-1.13.1/static.pro000066400000000000000000000061311347155106100151640ustar00rootroot00000000000000TEMPLATE = aux DATA_DIRS = share/qbs/imports share/qbs/modules share/qbs/module-providers PYTHON_DATA_DIRS = src/3rdparty/python/lib win32:DATA_FILES = $$PWD/bin/ibmsvc.xml $$PWD/bin/ibqbs.bat LIBEXEC_FILES = $$PWD/src/3rdparty/python/bin/dmgbuild # For use in custom compilers which just copy files defineReplace(stripSrcDir) { return($$relative_path($$absolute_path($$1, $$OUT_PWD), $$_PRO_FILE_PWD_)) } defineReplace(stripPythonSrcDir) { return($$relative_path($$absolute_path($$1, $$OUT_PWD), \ $$_PRO_FILE_PWD_/src/3rdparty/python/lib/python2.7/site-packages)) } for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) for(file, files):!exists($$file/*):FILES += $$file } FILES += $$DATA_FILES for(data_dir, PYTHON_DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) for(file, files):!exists($$file/*):PYTHON_FILES += $$file } PYTHON_FILES += $$PYTHON_DATA_FILES OTHER_FILES += $$FILES $$LIBEXEC_FILES !isEqual(PWD, $$OUT_PWD)|!isEmpty(QBS_RESOURCES_BUILD_DIR) { copy2build.input = FILES !isEmpty(QBS_RESOURCES_BUILD_DIR): \ copy2build.output = $${QBS_RESOURCES_BUILD_DIR}/${QMAKE_FUNC_FILE_IN_stripSrcDir} else: \ copy2build.output = ${QMAKE_FUNC_FILE_IN_stripSrcDir} copy2build.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} copy2build.name = COPY ${QMAKE_FILE_IN} copy2build.CONFIG += no_link target_predeps QMAKE_EXTRA_COMPILERS += copy2build } copy2build_python.input = PYTHON_FILES !isEmpty(QBS_RESOURCES_BUILD_DIR): \ copy2build_python.output = \ $${QBS_RESOURCES_BUILD_DIR}/share/qbs/python/${QMAKE_FUNC_FILE_IN_stripPythonSrcDir} else: \ copy2build_python.output = share/qbs/python/${QMAKE_FUNC_FILE_IN_stripPythonSrcDir} copy2build_python.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} copy2build_python.name = COPY ${QMAKE_FILE_IN} copy2build_python.CONFIG += no_link target_predeps QMAKE_EXTRA_COMPILERS += copy2build_python libexec_copy.input = LIBEXEC_FILES !isEmpty(QBS_LIBEXEC_DESTDIR): \ libexec_copy.output = $${QBS_LIBEXEC_DESTDIR}/${QMAKE_FILE_IN_BASE}${QMAKE_FILE_EXT} else: \ libexec_copy.output = libexec/qbs/${QMAKE_FILE_IN_BASE}${QMAKE_FILE_EXT} libexec_copy.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} libexec_copy.name = COPY ${QMAKE_FILE_IN} libexec_copy.CONFIG += no_link target_predeps QMAKE_EXTRA_COMPILERS += libexec_copy include(src/install_prefix.pri) share.files = share/qbs !isEmpty(QBS_RESOURCES_INSTALL_DIR): \ installPrefix = $${QBS_RESOURCES_INSTALL_DIR} else: \ installPrefix = $${QBS_INSTALL_PREFIX} share.path = $${installPrefix}/share examples.files = examples examples.path = $${share.path}/qbs python_bin.files = $$files(src/3rdparty/python/bin/*) !isEmpty(QBS_LIBEXEC_INSTALL_DIR): \ python_bin.path = $${QBS_LIBEXEC_INSTALL_DIR} else: \ python_bin.path = $${QBS_INSTALL_PREFIX}/libexec/qbs python.files = $$files(src/3rdparty/python/lib/python2.7/site-packages/*.py, true) python.base = $$PWD/src/3rdparty/python/lib/python2.7/site-packages python.path = $${share.path}/qbs/python INSTALLS += share examples python_bin python qbs-src-1.13.1/tests/000077500000000000000000000000001347155106100143145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/000077500000000000000000000000001347155106100152645ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/000077500000000000000000000000001347155106100160355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/api.pro000066400000000000000000000016131347155106100173310ustar00rootroot00000000000000TARGET = tst_api HEADERS = tst_api.h SOURCES = tst_api.cpp include(../../../src/library_dirname.pri) isEmpty(QBS_RELATIVE_LIBEXEC_PATH) { win32:QBS_RELATIVE_LIBEXEC_PATH=. else:QBS_RELATIVE_LIBEXEC_PATH=../libexec/qbs } isEmpty(QBS_RELATIVE_PLUGINS_PATH):QBS_RELATIVE_PLUGINS_PATH=../$${QBS_LIBRARY_DIRNAME} isEmpty(QBS_RELATIVE_SEARCH_PATH):QBS_RELATIVE_SEARCH_PATH=.. DEFINES += QBS_RELATIVE_LIBEXEC_PATH=\\\"$${QBS_RELATIVE_LIBEXEC_PATH}\\\" DEFINES += QBS_RELATIVE_PLUGINS_PATH=\\\"$${QBS_RELATIVE_PLUGINS_PATH}\\\" DEFINES += QBS_RELATIVE_SEARCH_PATH=\\\"$${QBS_RELATIVE_SEARCH_PATH}\\\" qbs_enable_project_file_updates:DEFINES += QBS_ENABLE_PROJECT_FILE_UPDATES include(../auto.pri) DATA_DIRS = testdata for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES qbs-src-1.13.1/tests/auto/api/api.qbs000066400000000000000000000013121347155106100173120ustar00rootroot00000000000000import qbs import qbs.Utilities QbsAutotest { testName: "api" files: ["../shared.h", "tst_api.h", "tst_api.cpp"] cpp.defines: base.concat([ "SRCDIR=" + Utilities.cStringQuote(path), "QBS_RELATIVE_LIBEXEC_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativeLibexecPath), "QBS_RELATIVE_SEARCH_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativeSearchPath), "QBS_RELATIVE_PLUGINS_PATH=" + Utilities.cStringQuote(qbsbuildconfig.relativePluginsPath) ]).concat(qbsbuildconfig.enableProjectFileUpdates ? ["QBS_ENABLE_PROJECT_FILE_UPDATES"] : []) Group { name: "testdata" prefix: "testdata/" files: ["**/*"] fileTags: [] } } qbs-src-1.13.1/tests/auto/api/testdata/000077500000000000000000000000001347155106100176465ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/QBS-728/000077500000000000000000000000001347155106100206115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/QBS-728/QBS-728.qbs000066400000000000000000000002621347155106100222630ustar00rootroot00000000000000Product { property bool isBlubbOS: qbs.targetOS.contains("blubb-OS") qbs.profiles: isBlubbOS ? ["blubb-profile"] : [project.profile] qbs.architecture: "blubb-arch" } qbs-src-1.13.1/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/000077500000000000000000000000001347155106100252375ustar00rootroot00000000000000add-qobject-macro-to-cpp-file.qbs000066400000000000000000000001051347155106100332540ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/add-qobject-macro-to-cpp-fileQtApplication { files: ["main.cpp", "object.h", "object.cpp"] } qbs-src-1.13.1/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/main.cpp000066400000000000000000000024301347155106100266660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.h" int main() { Object o; o.f(); } qbs-src-1.13.1/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/object.cpp000066400000000000000000000025671347155106100272230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.h" #include // class InternalClass : public QObject // { // Q_OBJECT // }; void Object::f() { } // #include "object.moc" qbs-src-1.13.1/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/object.h000066400000000000000000000024031347155106100266550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ class Object { public: void f(); }; qbs-src-1.13.1/tests/auto/api/testdata/added-file-persistent/000077500000000000000000000000001347155106100240225ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/added-file-persistent/added-file-persistent.qbs000066400000000000000000000001231347155106100307010ustar00rootroot00000000000000CppApplication { files: [ 'main.cpp', /* 'file.cpp' */ ] } qbs-src-1.13.1/tests/auto/api/testdata/added-file-persistent/file.cpp000066400000000000000000000023501347155106100254450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f() { } qbs-src-1.13.1/tests/auto/api/testdata/added-file-persistent/main.cpp000066400000000000000000000023721347155106100254560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f(); int main() { f(); } qbs-src-1.13.1/tests/auto/api/testdata/app-without-sources/000077500000000000000000000000001347155106100236105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/app-without-sources/a.c000066400000000000000000000023641347155106100242010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int foo() { return 42; } qbs-src-1.13.1/tests/auto/api/testdata/app-without-sources/app-without-sources.qbs000066400000000000000000000012361347155106100302630ustar00rootroot00000000000000Project { StaticLibrary { name: "a" Depends { name: "cpp" } files: [ "a.c", ] } StaticLibrary { name: "b" Depends { name: "a" } Depends { name: "cpp" } files: [ "b.c", ] } CppApplication { name: "appWithoutSources" consoleApplication: true // HACK: cpp.entryPoint currently not working 100% with gcc Properties { condition: qbs.toolchain.contains("msvc") cpp.entryPoint: "main" } cpp.entryPoint: undefined Depends { name: "a" } Depends { name: "b" } } } qbs-src-1.13.1/tests/auto/api/testdata/app-without-sources/b.c000066400000000000000000000024621347155106100242010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int foo(); // defined in a.cpp int main() { return foo(); } qbs-src-1.13.1/tests/auto/api/testdata/base-properties/000077500000000000000000000000001347155106100227525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/base-properties/imports/000077500000000000000000000000001347155106100244475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/base-properties/imports/Bar.qbs000066400000000000000000000001061347155106100256570ustar00rootroot00000000000000Product { Depends { name: "cpp" } cpp.defines: ["FROM_BAR"] } qbs-src-1.13.1/tests/auto/api/testdata/base-properties/imports/Foo.qbs000066400000000000000000000001511347155106100256760ustar00rootroot00000000000000Bar { type: "application" consoleApplication: true cpp.defines: base.concat(["FROM_FOO"]) } qbs-src-1.13.1/tests/auto/api/testdata/base-properties/main.cpp000066400000000000000000000026141347155106100244050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef FROM_FOO #error FROM_FOO missing! #endif #ifndef FROM_BAR #error FROM_BAR missing! #endif #ifndef FROM_PRJ #error FROM_PRJ missing! #endif int main() { return 0; } qbs-src-1.13.1/tests/auto/api/testdata/base-properties/prj.qbs000066400000000000000000000002101347155106100242450ustar00rootroot00000000000000import "imports/Foo.qbs" as Foo Project { Foo { cpp.defines: base.concat(["FROM_PRJ"]); files: "main.cpp" } } qbs-src-1.13.1/tests/auto/api/testdata/build-error-code-location/000077500000000000000000000000001347155106100246125ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/build-error-code-location/build-error-code-location.qbs000066400000000000000000000002521347155106100322640ustar00rootroot00000000000000Product { name: "p" type: ["p.out"] Rule { multiplex: true outputFileTags: ["p.out"] outputArtifacts: { } prepare: {} } } qbs-src-1.13.1/tests/auto/api/testdata/build-properties-source/000077500000000000000000000000001347155106100244355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/build-properties-source/build-properties-source.qbs000066400000000000000000000006031347155106100317320ustar00rootroot00000000000000Project { Product { type: "application" consoleApplication: true name: "HelloWorld" Depends { name: 'cpp' } Properties { condition: qbs.toolchain.contains("gcc") cpp.cxxFlags: "-march=native" } Group { cpp.defines: ['WORLD="BANANA"'] files : [ "main.cpp" ] } } } qbs-src-1.13.1/tests/auto/api/testdata/build-properties-source/main.cpp000066400000000000000000000025211347155106100260650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #ifndef WORLD # error WORLD is not defined #endif int main() { puts("Hello " WORLD "!"); } qbs-src-1.13.1/tests/auto/api/testdata/build-single-file/000077500000000000000000000000001347155106100231415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/build-single-file/build-single-file.qbs000066400000000000000000000013631347155106100271460ustar00rootroot00000000000000import qbs.TextFile CppApplication { consoleApplication: true files: ["ignored1.cpp", "ignored2.cpp", "compiled.cpp"] cpp.includePaths: [buildDirectory] Group { files: ["pch.h"] fileTags: ["cpp_pch_src"] } install: true installDir: "" Rule { multiplex: true Artifact { filePath: "generated.h" fileTags: ["hpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var header = new TextFile(output.filePath, TextFile.WriteOnly); header.close(); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/api/testdata/build-single-file/compiled.cpp000066400000000000000000000024311347155106100254410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include void f() { std::cout << "test"; } qbs-src-1.13.1/tests/auto/api/testdata/build-single-file/ignored1.cpp000066400000000000000000000000001347155106100253430ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/build-single-file/ignored2.cpp000066400000000000000000000000001347155106100253440ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/build-single-file/pch.h000066400000000000000000000000241347155106100240600ustar00rootroot00000000000000#include qbs-src-1.13.1/tests/auto/api/testdata/buildgraph-info/000077500000000000000000000000001347155106100227205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/buildgraph-info/buildgraph-info.qbs000066400000000000000000000000531347155106100264770ustar00rootroot00000000000000Product { qbs.shellPath: "/bin/bash" } qbs-src-1.13.1/tests/auto/api/testdata/buildgraph-locking/000077500000000000000000000000001347155106100234135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/buildgraph-locking/buildgraph-locking.qbs000066400000000000000000000000141347155106100276620ustar00rootroot00000000000000Project { } qbs-src-1.13.1/tests/auto/api/testdata/change-dependent-lib/000077500000000000000000000000001347155106100236035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/change-dependent-lib/change-dependent-lib.qbs000066400000000000000000000010021347155106100302400ustar00rootroot00000000000000Project { Application { name : "HelloWorld" Group { files : [ "main.cpp" ] } Depends { name: "cpp" } Depends { name: "mylib" } } DynamicLibrary { name : "mylib" version: "1.2.3" Group { files : [ "mylib.cpp" ] } Depends { name: "cpp" } cpp.defines: ["XXXX"] Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } } qbs-src-1.13.1/tests/auto/api/testdata/change-dependent-lib/main.cpp000066400000000000000000000025701347155106100252370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_IMPORT int mylib_hello(); int main() { puts("application says hello!"); return mylib_hello(); } qbs-src-1.13.1/tests/auto/api/testdata/change-dependent-lib/mylib.cpp000066400000000000000000000025301347155106100254230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_EXPORT int mylib_hello() { puts("mylib says hello!"); return 0; } qbs-src-1.13.1/tests/auto/api/testdata/check-outputs/000077500000000000000000000000001347155106100224445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/check-outputs/check-outputs.qbs000066400000000000000000000015261347155106100257550ustar00rootroot00000000000000import qbs.File Project { Product { type: 'application' consoleApplication: true Group { files: 'foo.txt' fileTags: ['text'] } Depends { name: 'cpp' } } Rule { inputs: ['text'] Artifact { fileTags: ['cpp'] filePath: input.baseName + '.cpp' } Artifact { fileTags: ['ghost'] filePath: input.baseName + '.ghost' } prepare: { var cmd = new JavaScriptCommand(); cmd.inp = inputs["text"][0].filePath; cmd.out = outputs["cpp"][0].filePath; cmd.description = "generating " + outputs["cpp"][0].fileName; cmd.sourceCode = function() { File.copy(inp, out); }; return cmd; } } } qbs-src-1.13.1/tests/auto/api/testdata/check-outputs/foo.txt000066400000000000000000000000311347155106100237620ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.13.1/tests/auto/api/testdata/codegen/000077500000000000000000000000001347155106100212525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/codegen/codegen.qbs000066400000000000000000000052361347155106100233730ustar00rootroot00000000000000import qbs.FileInfo Project { property string name: 'codegen' property string osSpecificName: name.toUpperCase() + '_' + qbs.targetPlatform.toUpperCase() Product { type: 'application' consoleApplication: true name: project.name property var replacements: ({ NUMBERTYPE: "int", STRINGTYPE: "char **", FUNCTIONNAME: "main" }) Group { files: 'foo.txt' fileTags: ['text'] } Depends { name: 'cpp' } Depends { name: 'Qt.core' } } Rule { inputs: ['text'] Artifact { fileTags: ['cpp'] filePath: input.baseName + '.cpp' } prepare: { function expandMacros(str, table) { var rex = /\$\w+/; var m = rex.exec(str); while (m != null) { str = str.substr(0, m.index) + table[m[0].substr(1)] + str.substr(m.index + m[0].length); m = rex.exec(str); } return str; } // check whether multipart module name translation is working var actual = product.moduleProperty("Qt.core", "mocName"); if (!actual || !actual.contains("moc")) throw "multipart module name translation is broken"; // check whether we can access project properties here var expected = "CODEGEN_" + product.moduleProperty("qbs", "targetPlatform").toUpperCase(); if (project.osSpecificName !== expected) throw "Wrong project property value: " + project.osSpecificName + "\nexpected: " + expected; var code = '$NUMBERTYPE $FUNCTIONNAME($NUMBERTYPE, $STRINGTYPE) { return 0; }'; code = expandMacros(code, product.replacements); var args = ['echo ' + code + '>' + output.filePath] var cmd if (product.moduleProperty("qbs", "hostOS").contains('windows')) { cmd = new Command(product.qbs.windowsShellPath, ['/C'].concat(args)); } else { args[0] = args[0].replace(/\(/g, '\\(') args[0] = args[0].replace(/\)/g, '\\)') args[0] = args[0].replace(/;/g, '\\;') cmd = new Command(product.qbs.shellPath, ['-c'].concat(args)) } cmd.description = 'generate\t' + FileInfo.fileName(output.filePath); cmd.highlight = 'codegen'; return cmd; } } } qbs-src-1.13.1/tests/auto/api/testdata/codegen/foo.txt000066400000000000000000000000141347155106100225710ustar00rootroot00000000000000Hello World qbs-src-1.13.1/tests/auto/api/testdata/command-extraction/000077500000000000000000000000001347155106100234425ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/command-extraction/command-extraction.qbs000066400000000000000000000000511347155106100277410ustar00rootroot00000000000000CppApplication { files: "main.cpp" } qbs-src-1.13.1/tests/auto/api/testdata/command-extraction/main.cpp000066400000000000000000000023511347155106100250730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/api/testdata/dependency-on-multiplexed-type/000077500000000000000000000000001347155106100257075ustar00rootroot00000000000000dependency-on-multiplexed-type.qbs000066400000000000000000000005471347155106100344060ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/dependency-on-multiplexed-typeimport qbs Project { Product { name: "dep"; type: "x" } Product { name: "p1" multiplexByQbsProperties: "architectures" qbs.architectures: ["a", "b"] aggregate: true Depends { productTypes: "x" } multiplexedType: "x" } Product { name: "p2" Depends { productTypes: "x" } } } qbs-src-1.13.1/tests/auto/api/testdata/disabled-product/000077500000000000000000000000001347155106100230735ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/disabled-product/disabled-product.qbs000066400000000000000000000002351347155106100270270ustar00rootroot00000000000000CppApplication { condition: false files: "main.cpp" Group { condition: qbs.targetOS.contains("stuff") qbs.install: false } } qbs-src-1.13.1/tests/auto/api/testdata/disabled-product/main.cpp000066400000000000000000000000231347155106100245160ustar00rootroot00000000000000thiswillnotcompile qbs-src-1.13.1/tests/auto/api/testdata/disabled-project/000077500000000000000000000000001347155106100230615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/disabled-project/disabled-project.qbs000066400000000000000000000001511347155106100270000ustar00rootroot00000000000000import qbs.File Project { condition: File.exists("blubb"); references: "blubb/nosuchfile.qbs" } qbs-src-1.13.1/tests/auto/api/testdata/disabled_install_group/000077500000000000000000000000001347155106100243575ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/disabled_install_group/disabled_install_group.qbs000066400000000000000000000002601347155106100315750ustar00rootroot00000000000000CppApplication { consoleApplication: true files: "main.cpp" Group { condition: false qbs.install: true fileTagsFilter: product.type } } qbs-src-1.13.1/tests/auto/api/testdata/disabled_install_group/main.cpp000066400000000000000000000023521347155106100260110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-1.13.1/tests/auto/api/testdata/duplicate-product-names/000077500000000000000000000000001347155106100243775ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/duplicate-product-names/explicit.qbs000066400000000000000000000001461347155106100267300ustar00rootroot00000000000000Project { Product { name: "blubb" } Product { name: "blubb" } Product { name: "blubb" } } qbs-src-1.13.1/tests/auto/api/testdata/duplicate-product-names/implicit-indirect.qbs000066400000000000000000000001211347155106100305110ustar00rootroot00000000000000Project { references: ["subdir1/subproject.qbs", "subdir2/subproject.qbs"] } qbs-src-1.13.1/tests/auto/api/testdata/duplicate-product-names/implicit.qbs000066400000000000000000000000741347155106100267210ustar00rootroot00000000000000Project { Product { } Product { } Product { } } qbs-src-1.13.1/tests/auto/api/testdata/duplicate-product-names/subdir1/000077500000000000000000000000001347155106100257505ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/duplicate-product-names/subdir1/subproject.qbs000066400000000000000000000000141347155106100306320ustar00rootroot00000000000000Product { } qbs-src-1.13.1/tests/auto/api/testdata/duplicate-product-names/subdir2/000077500000000000000000000000001347155106100257515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/duplicate-product-names/subdir2/subproject.qbs000066400000000000000000000000141347155106100306330ustar00rootroot00000000000000Product { } qbs-src-1.13.1/tests/auto/api/testdata/empty-filetag-list/000077500000000000000000000000001347155106100233665ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/empty-filetag-list/dontcompilethis.cpp000066400000000000000000000000211347155106100272700ustar00rootroot00000000000000This is not C++. qbs-src-1.13.1/tests/auto/api/testdata/empty-filetag-list/empty-filetag-list.qbs000066400000000000000000000001371347155106100276160ustar00rootroot00000000000000CppApplication { Group { files: "dontcompilethis.cpp" fileTags: [] } } qbs-src-1.13.1/tests/auto/api/testdata/empty-submodules-list/000077500000000000000000000000001347155106100241355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/empty-submodules-list/empty-submodules-list.qbs000066400000000000000000000001241347155106100311300ustar00rootroot00000000000000CppApplication { Depends { name: "dummy" submodules: [] } } qbs-src-1.13.1/tests/auto/api/testdata/enable-and-disable-product/000077500000000000000000000000001347155106100247135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/enable-and-disable-product/enable-and-disable-product.qbs000066400000000000000000000002751347155106100324730ustar00rootroot00000000000000CppApplication { property string prop: undefined // Influences source artifact properties and the product condition condition: prop cpp.visibility: prop files: "main.cpp" } qbs-src-1.13.1/tests/auto/api/testdata/enable-and-disable-product/main.cpp000066400000000000000000000023511347155106100263440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/api/testdata/error-in-setup-run-environment/000077500000000000000000000000001347155106100257055ustar00rootroot00000000000000error-in-setup-run-environment.qbs000066400000000000000000000000641347155106100343740ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/error-in-setup-run-environmentCppApplication { Depends { name: "mymodule" } } qbs-src-1.13.1/tests/auto/api/testdata/error-in-setup-run-environment/modules/000077500000000000000000000000001347155106100273555ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/error-in-setup-run-environment/modules/mymodule/000077500000000000000000000000001347155106100312105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/error-in-setup-run-environment/modules/mymodule/mymodule.qbs000066400000000000000000000000751347155106100335540ustar00rootroot00000000000000Module { setupRunEnvironment: { trallala } } qbs-src-1.13.1/tests/auto/api/testdata/excluded-inputs/000077500000000000000000000000001347155106100227635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/excluded-inputs/excluded-inputs.qbs000066400000000000000000000072131347155106100266120ustar00rootroot00000000000000import qbs.File import qbs.TextFile Project { Product { name: "dep" type: "the_tag" Rule { multiplex: true Artifact { filePath: "file1.txt" fileTags: "the_tag" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.writeLine("the_content"); f.close(); }; return cmd; } } Rule { inputs: "the_tag" excludedInputs: "the_other_tag" Artifact { filePath: "file2.txt" fileTags: "the_other_tag" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); var f = new TextFile(output.filePath, TextFile.Append); f.writeLine("the_other_content"); f.close(); }; return cmd; } } Group { fileTagsFilter: "the_other_tag" fileTags: "the_tag" } } Product { name: "p" type: "p_type" Depends { name: "dep" } Rule { multiplex: true inputsFromDependencies: "the_tag" Artifact { filePath: "dummy1.txt" fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName;; if (!inputs["the_tag"] || inputs["the_tag"].length != 2) throw "Huch?"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } Rule { multiplex: true inputsFromDependencies: "the_tag" excludedInputs: "the_other_tag" Artifact { filePath: "dummy2.txt" fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName;; if (!inputs["the_tag"] || inputs["the_tag"].length != 1) throw "Huch?"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } Rule { multiplex: true explicitlyDependsOnFromDependencies: "the_tag" excludedAuxiliaryInputs: "the_other_tag" Artifact { filePath: "dummy3.txt" fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; if (!explicitlyDependsOn["the_tag"] || explicitlyDependsOn["the_tag"].length != 1) throw "Huch?"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } } } qbs-src-1.13.1/tests/auto/api/testdata/explicitly-depends-on/000077500000000000000000000000001347155106100240665ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/explicitly-depends-on/a.in000066400000000000000000000000001347155106100246240ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/explicitly-depends-on/b.in000066400000000000000000000000001347155106100246250ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/explicitly-depends-on/c.in000066400000000000000000000000001347155106100246260ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/explicitly-depends-on/compiler.cpp000066400000000000000000000002621347155106100264040ustar00rootroot00000000000000#include #include int main(int argc, char *argv[]) { assert(argc == 3); std::ofstream target(argv[2]); assert(target); target << argv[1]; } qbs-src-1.13.1/tests/auto/api/testdata/explicitly-depends-on/explicitly-depends-on.qbs000066400000000000000000000035221347155106100310170ustar00rootroot00000000000000import qbs.FileInfo import qbs.TextFile Project { CppApplication { name: "compiler" files: ["compiler.cpp"] Group { fileTagsFilter: ["application"] fileTags: ["compiler"] } } Product { name: "p" type: ["mytype"] Depends { name: "compiler" } Depends { name: "cpp" } Rule { inputs: ["mytype.in"] explicitlyDependsOnFromDependencies: ["compiler"] Artifact { filePath: input.fileName + ".out" fileTags: product.type } prepare: { var compiler = explicitlyDependsOn["compiler"][0].filePath; var cmd = new Command(compiler, [input.filePath, output.filePath]); cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; return [cmd]; } } Rule { multiplex: true explicitlyDependsOnFromDependencies: ["compiler"] Artifact { filePath: "compiler-name.txt" fileTags: product.type } prepare: { var nameCmd = new JavaScriptCommand(); nameCmd.description = "writing compiler name"; nameCmd.sourceCode = function() { var compiler = explicitlyDependsOn["compiler"][0].filePath; var file = new TextFile(output.filePath, TextFile.WriteOnly); file.write("compiler file name: " + FileInfo.baseName(compiler)); file.close(); } return [nameCmd]; } } FileTagger { patterns: "*.in" fileTags: ["mytype.in"] } files: ["a.in", "b.in", "c.in"] } } qbs-src-1.13.1/tests/auto/api/testdata/export-item-with-group/000077500000000000000000000000001347155106100242265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/export-item-with-group/export-item-with-group.qbs000066400000000000000000000004131347155106100313130ustar00rootroot00000000000000Project { Product { name: "dep" Export { Depends { name: "cpp" } Group { files: ["main.cpp"] } } } Application { name: "app" consoleApplication: true Depends { name: "dep" } } } qbs-src-1.13.1/tests/auto/api/testdata/export-item-with-group/main.cpp000066400000000000000000000023521347155106100256600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-1.13.1/tests/auto/api/testdata/export-simple/000077500000000000000000000000001347155106100224565ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/export-simple/export-simple.qbs000066400000000000000000000020371347155106100257770ustar00rootroot00000000000000Project { Application { name : "HelloWorld" destinationDirectory: "bin" Group { files : [ "main.cpp" ] } Depends { name: "cpp" } Depends { name: 'dummy' } } Product { name: 'dummy' Group { files: 'main.cpp' qbs.install: true } Export { Depends { name: 'dummy2' } Properties { // QBS-550 condition: false qbs.optimization: "ludicrous speed" } } } Product { name: 'dummy2' Group { files: 'lib1.cpp' qbs.install: true } Export { Depends { name: 'lib1' } } } DynamicLibrary { name : "lib1" destinationDirectory: "bin" Group { files : [ "lib1.cpp" ] } Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } } qbs-src-1.13.1/tests/auto/api/testdata/export-simple/lib1.cpp000066400000000000000000000025251347155106100240150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_EXPORT int lib1_hello() { puts("lib1 says hello!"); return 0; } qbs-src-1.13.1/tests/auto/api/testdata/export-simple/main.cpp000066400000000000000000000025651347155106100241160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_IMPORT int lib1_hello(); int main() { puts("application says hello!"); return lib1_hello(); } qbs-src-1.13.1/tests/auto/api/testdata/export-with-recursive-depends/000077500000000000000000000000001347155106100255655ustar00rootroot00000000000000export-with-recursive-depends.qbs000066400000000000000000000003631347155106100341360ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/export-with-recursive-dependsProject { CppApplication { name: "app1" files: "main1.cpp" Export { Depends { name: "module1" } } } CppApplication { name: "app2" Depends { name: "app1" } files: "main2.cpp" } } qbs-src-1.13.1/tests/auto/api/testdata/export-with-recursive-depends/main1.cpp000066400000000000000000000023511347155106100272770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/api/testdata/export-with-recursive-depends/main2.cpp000066400000000000000000000024161347155106100273020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { #ifndef HAS_FOO blubb(); #endif } qbs-src-1.13.1/tests/auto/api/testdata/export-with-recursive-depends/modules/000077500000000000000000000000001347155106100272355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/export-with-recursive-depends/modules/module1/000077500000000000000000000000001347155106100306035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/export-with-recursive-depends/modules/module1/module1.qbs000066400000000000000000000000531347155106100326560ustar00rootroot00000000000000Module { Depends { name: "module2" } } qbs-src-1.13.1/tests/auto/api/testdata/export-with-recursive-depends/modules/module2/000077500000000000000000000000001347155106100306045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/export-with-recursive-depends/modules/module2/module2.qbs000066400000000000000000000001041347155106100326550ustar00rootroot00000000000000Module { Depends { name: "cpp" } cpp.defines: ["HAS_FOO"] } qbs-src-1.13.1/tests/auto/api/testdata/fallback-gcc/000077500000000000000000000000001347155106100221375ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/fallback-gcc/fallback-gcc.qbs000066400000000000000000000010631347155106100251370ustar00rootroot00000000000000CppApplication { name: "app" cpp._skipAllChecks: true Profile { name: "unixProfile" qbs.targetOS: ["unix"] qbs.toolchain: ["gcc"] // qbs.targetPlatform: "unix" // qbs.toolchainType: "gcc" } Profile { name: "gccProfile" qbs.targetOS: [] qbs.toolchain: ["gcc"] // qbs.targetPlatform: undefined // qbs.toolchainType: "gcc" } multiplexByQbsProperties: ["profiles"] qbs.profiles: ["unixProfile", "gccProfile"] } qbs-src-1.13.1/tests/auto/api/testdata/file-tagger/000077500000000000000000000000001347155106100220345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/file-tagger/bla.txt000066400000000000000000000002131347155106100233270ustar00rootroot00000000000000#include class MyObject : public QObject { Q_OBJECT }; int main() { MyObject obj; return 0; } #include "bla.moc" qbs-src-1.13.1/tests/auto/api/testdata/file-tagger/moc_cpp.qbs000066400000000000000000000020301347155106100241560ustar00rootroot00000000000000import qbs.TextFile import qbs.FileInfo Project { Product { type: "application" consoleApplication: true name: "moc_cpp" Depends { name: "Qt.core" } Group { files: 'bla.txt' fileTags: ['text'] } } Rule { inputs: ['text'] Artifact { fileTags: ['cpp'] filePath: input.baseName + '.cpp' } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function () { var file = new TextFile(input.filePath, TextFile.ReadOnly); var text = file.readAll(); file.close(); file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(text); file.close(); } cmd.description = 'generating ' + FileInfo.fileName(output.filePath); cmd.highlight = 'codegen'; return cmd; } } } qbs-src-1.13.1/tests/auto/api/testdata/filetagsfilter_override/000077500000000000000000000000001347155106100245515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/filetagsfilter_override/InstalledApp.qbs000066400000000000000000000002701347155106100276370ustar00rootroot00000000000000CppApplication { type: "application" consoleApplication: true Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "hurz" } } qbs-src-1.13.1/tests/auto/api/testdata/filetagsfilter_override/filetagsfilter_override.qbs000066400000000000000000000003051347155106100321610ustar00rootroot00000000000000import "InstalledApp.qbs" as InstalledApp InstalledApp { files: "main.cpp" Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "habicht" } } qbs-src-1.13.1/tests/auto/api/testdata/filetagsfilter_override/main.cpp000066400000000000000000000023511347155106100262020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/api/testdata/generated-files-list/000077500000000000000000000000001347155106100236555ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/generated-files-list/generated-files-list.qbs000066400000000000000000000004611347155106100303740ustar00rootroot00000000000000CppApplication { Depends { name: "Qt.widgets" } consoleApplication: true cpp.cxxLanguageVersion: "c++11" cpp.debugInformation: false cpp.separateDebugInformation: false files: [ "main.cpp", "mainwindow.cpp", "mainwindow.h", "mainwindow.ui" ] } qbs-src-1.13.1/tests/auto/api/testdata/generated-files-list/main.cpp000066400000000000000000000026071347155106100253120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } qbs-src-1.13.1/tests/auto/api/testdata/generated-files-list/mainwindow.cpp000066400000000000000000000026661347155106100265470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } qbs-src-1.13.1/tests/auto/api/testdata/generated-files-list/mainwindow.h000066400000000000000000000030501347155106100262000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H qbs-src-1.13.1/tests/auto/api/testdata/generated-files-list/mainwindow.ui000066400000000000000000000011661347155106100263740ustar00rootroot00000000000000 MainWindow 0 0 400 300 MainWindow qbs-src-1.13.1/tests/auto/api/testdata/infinite-loop-js/000077500000000000000000000000001347155106100230345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/infinite-loop-js/infinite-loop.qbs000066400000000000000000000006551347155106100263250ustar00rootroot00000000000000Product { type: "mytype" Rule { multiplex: true Artifact { filePath: "output.txt" fileTags: "mytype" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Running infinite loop"; cmd.sourceCode = function() { while (true) ; } return cmd; } } } qbs-src-1.13.1/tests/auto/api/testdata/infinite-loop-process/000077500000000000000000000000001347155106100240765ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs000066400000000000000000000011551347155106100273630ustar00rootroot00000000000000Project { CppApplication { type: "application" consoleApplication: true // suppress bundle generation files: "main.cpp" name: "infinite-loop" } Product { type: "mytype" name: "caller" Depends { name: "infinite-loop" } Rule { inputsFromDependencies: "application" outputFileTags: "mytype" prepare: { var cmd = new Command(inputs["application"][0].filePath); cmd.description = "Calling application that runs forever"; return cmd; } } } } qbs-src-1.13.1/tests/auto/api/testdata/infinite-loop-process/main.cpp000066400000000000000000000025131347155106100255270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main() { std::this_thread::sleep_for(std::chrono::seconds(700)); } qbs-src-1.13.1/tests/auto/api/testdata/infinite-loop-resolving/000077500000000000000000000000001347155106100244305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/infinite-loop-resolving/infinite-loop-resolving.qbs000066400000000000000000000000701347155106100317160ustar00rootroot00000000000000Product { type: { while (true); return "Haha!"; } } qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/000077500000000000000000000000001347155106100244535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/imports/000077500000000000000000000000001347155106100261505ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/imports/Foo.qbs000066400000000000000000000001361347155106100274020ustar00rootroot00000000000000Product { type: "application" consoleApplication: true Depends { name: 'bli' } } qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/main.cpp000066400000000000000000000024531347155106100261070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef HAVE_BLI #error HAVE_BLI missing! #endif int main() { return 0; } qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/prj.qbs000066400000000000000000000002671347155106100257620ustar00rootroot00000000000000import "imports/Foo.qbs" as Foo Project { qbsSearchPaths: "subdir" Project { qbsSearchPaths: "subdir2" Foo { files: "main.cpp" } } } qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/000077500000000000000000000000001347155106100257435ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/modules/000077500000000000000000000000001347155106100274135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/modules/bli/000077500000000000000000000000001347155106100301615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/modules/bli/m.qbs000066400000000000000000000001061347155106100311210ustar00rootroot00000000000000Module { Depends {name : "cpp" } cpp.defines: ["HAVE_BLI"] } qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/000077500000000000000000000000001347155106100260255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/modules/000077500000000000000000000000001347155106100274755ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/modules/bla/000077500000000000000000000000001347155106100302335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/modules/bla/m.qbs000066400000000000000000000001061347155106100311730ustar00rootroot00000000000000Module { Depends {name : "cpp" } cpp.defines: ["HAVE_BLA"] } qbs-src-1.13.1/tests/auto/api/testdata/installed-artifact/000077500000000000000000000000001347155106100234205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/installed-artifact/installed-artifact.qbs000066400000000000000000000011041347155106100276750ustar00rootroot00000000000000 Project { CppApplication { name: "other app" files: ["main.cpp"] } CppApplication { name: "installedApp" type: "application" consoleApplication: true Depends { name: "other app" } Group { files: "main.cpp" qbs.install: true qbs.installDir: "src" } qbs.installPrefix: "/usr" install: true installDir: "bin" Group { fileTagsFilter: "obj" qbs.install: true qbs.installDir: "objects" } } } qbs-src-1.13.1/tests/auto/api/testdata/installed-artifact/main.cpp000066400000000000000000000023511347155106100250510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/api/testdata/is-runnable/000077500000000000000000000000001347155106100220655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/is-runnable/is-runnable.qbs000066400000000000000000000003431347155106100250130ustar00rootroot00000000000000Project { CppApplication { name: "app" } DynamicLibrary { name: "lib" Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } } qbs-src-1.13.1/tests/auto/api/testdata/lib-same-source/000077500000000000000000000000001347155106100226355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/lib-same-source/lib-same-source.qbs000066400000000000000000000006111347155106100263310ustar00rootroot00000000000000Project { Product { type: "application" consoleApplication: true name : "HelloWorldApp" Depends { name: 'cpp' } Group { files : [ "main.cpp" ] } } Product { type: "staticlibrary" name : "HelloWorldLib" Depends { name: 'cpp' } Group { files : [ "main.cpp" ] } } } qbs-src-1.13.1/tests/auto/api/testdata/lib-same-source/main.cpp000066400000000000000000000024301347155106100242640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { puts("Hello WOrld!"); } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/000077500000000000000000000000001347155106100252365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/dynamic1.cpp000066400000000000000000000002571347155106100274530ustar00rootroot00000000000000#include #include "../dllexport.h" void static1_hello(); DLL_EXPORT int dynamic1_hello() { static1_hello(); puts("dynamic1 says hello!"); return 0; } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/dynamic2.cpp000066400000000000000000000002511347155106100274460ustar00rootroot00000000000000#include "../dllexport.h" #include "static2.h" #include DLL_EXPORT void dynamic2_hello() { TestMe tm; tm.hello(); puts("dynamic2 says hello!"); } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/link-dynamiclibs-staticlibs.qbs000066400000000000000000000020121347155106100333300ustar00rootroot00000000000000Project { Application { name : "HelloWorld" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "dynamic1" } } DynamicLibrary { name : "dynamic1" files : [ "dynamic1.cpp" ] Depends { name: "cpp" } Depends { name: "static1" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } StaticLibrary { name: "static1" files: [ "static1.cpp" ] Depends { name: "cpp" } Depends { name: "dynamic2" } } DynamicLibrary { name: "dynamic2" files: [ "dynamic2.cpp" ] Depends { name: "cpp" } Depends { name: "static2" } cpp.visibility: 'hidden' Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } StaticLibrary { name: "static2" files: [ "static2.cpp", "static2.h" ] Depends { name: "cpp" } } } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/main.cpp000066400000000000000000000002721347155106100266670ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_IMPORT int dynamic1_hello(); int main() { int result = dynamic1_hello(); puts("application says hello!"); return result; } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/static1.cpp000066400000000000000000000002411347155106100273070ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_IMPORT void dynamic2_hello(); void static1_hello() { dynamic2_hello(); puts("static1 says hello!"); } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/static2.cpp000066400000000000000000000001511347155106100273100ustar00rootroot00000000000000#include "static2.h" #include void TestMe::hello() const { puts("static2 says hello!"); } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs-staticlibs/static2.h000066400000000000000000000001541347155106100267600ustar00rootroot00000000000000#ifndef STATIC2_H #define STATIC2_H class TestMe { public: void hello() const; }; #endif // STATIC2_H qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs/000077500000000000000000000000001347155106100230775ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs/lib1.cpp000066400000000000000000000026061347155106100244360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_IMPORT void lib2_hello(); DLL_EXPORT int lib1_hello() { puts("lib1 says hello!"); lib2_hello(); return 0; } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs/lib2.cpp000066400000000000000000000025721347155106100244410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_IMPORT void lib3_hello(); DLL_EXPORT void lib2_hello() { puts("lib2 says hello!"); lib3_hello(); } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs/lib3.cpp000066400000000000000000000026521347155106100244410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #include DLL_EXPORT void lib3_hello() { puts("lib3 says hello!"); } DLL_EXPORT char* lib3_greeting() { static char greeting[] = "hello"; return greeting; } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs/lib4.cpp000066400000000000000000000026141347155106100244400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib4.h" TestMe::TestMe() { } void TestMe::hello1() const { puts("lib4 says hello!"); } void TestMe::hello2Impl() const { puts("lib4 says hello inline!"); } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs/lib4.h000066400000000000000000000030751347155106100241070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef LIB4_H #define LIB4_H #include "../dllexport.h" #include #ifdef TEST_LIB # define LIB_EXPORT DLL_EXPORT #else # define LIB_EXPORT DLL_IMPORT #endif class LIB_EXPORT TestMe { public: TestMe(); void hello1() const; inline void hello2() const { hello2Impl(); } private: void hello2Impl() const; }; #endif // LIB4_H qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs/link-dynamiclibs.qbs000066400000000000000000000031171347155106100270410ustar00rootroot00000000000000Project { Application { name : "HelloWorld" Group { files : [ "main.cpp" ] } Depends { name: "cpp" } Depends { name: "lib1" } Depends { name: "lib4" } } DynamicLibrary { name : "lib1" Group { files : [ "lib1.cpp" ] } Depends { name: "cpp" } Depends { name: "lib2" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } DynamicLibrary { name : "lib2" cpp.visibility: 'default' Group { files : [ "lib2.cpp" ] } Depends { name: "cpp" } Depends { name: "lib3" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } DynamicLibrary { name : "lib3" cpp.visibility: 'hidden' Group { files : [ "lib3.cpp" ] } Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } DynamicLibrary { name : "lib4" cpp.visibility: 'hiddenInlines' cpp.defines: "TEST_LIB" Group { files : [ "lib4.h", "lib4.cpp" ] } Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory] } } } qbs-src-1.13.1/tests/auto/api/testdata/link-dynamiclibs/main.cpp000066400000000000000000000026441347155106100245350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include DLL_IMPORT int lib1_hello(); int main() { puts("application says hello!"); TestMe test; test.hello1(); test.hello2(); return lib1_hello(); } qbs-src-1.13.1/tests/auto/api/testdata/link-static-lib/000077500000000000000000000000001347155106100226345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/link-static-lib/helper1/000077500000000000000000000000001347155106100241745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/link-static-lib/helper1/helper1.cpp000066400000000000000000000024761347155106100262510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "helper1.h" #include int getSomeNumber() { return 12 * getOddNumber(); } qbs-src-1.13.1/tests/auto/api/testdata/link-static-lib/helper1/helper1.h000066400000000000000000000024441347155106100257110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef HELPER1_H #define HELPER1_H extern int getSomeNumber(); #endif qbs-src-1.13.1/tests/auto/api/testdata/link-static-lib/helper2/000077500000000000000000000000001347155106100241755ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/link-static-lib/helper2/helper2.cpp000066400000000000000000000024271347155106100262470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "helper2.h" int getOddNumber() { return 13; } qbs-src-1.13.1/tests/auto/api/testdata/link-static-lib/helper2/helper2.h000066400000000000000000000024431347155106100257120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef HELPER2_H #define HELPER2_H extern int getOddNumber(); #endif qbs-src-1.13.1/tests/auto/api/testdata/link-static-lib/link-static-lib.qbs000066400000000000000000000020241347155106100263270ustar00rootroot00000000000000Project { Product { type: "application" consoleApplication: true name: "HelloWorld" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "mystaticlib" } } StaticLibrary { name : "mystaticlib" files : [ "mystaticlib.cpp" ] Depends { name: "cpp" } Depends { name: "helper1" } } StaticLibrary { name : "helper1" files : [ "helper1/helper1.h", "helper1/helper1.cpp" ] Depends { name: "cpp" } Depends { name: "helper2" } Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory + '/helper1'] } } StaticLibrary { name : "helper2" files : [ "helper2/helper2.h", "helper2/helper2.cpp" ] Depends { name: "cpp" } Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory + '/helper2'] } } } qbs-src-1.13.1/tests/auto/api/testdata/link-static-lib/main.cpp000066400000000000000000000024351347155106100242700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int bla(); int main() { return bla(); } qbs-src-1.13.1/tests/auto/api/testdata/link-static-lib/mystaticlib.cpp000066400000000000000000000025641347155106100256730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int bla() { int n = getSomeNumber(); printf("Hello World! The magic number is %d.", n); return n; } qbs-src-1.13.1/tests/auto/api/testdata/link-static-lib/mystaticlibhelper.cpp000066400000000000000000000024061347155106100270660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int helper_function() { return 156; } qbs-src-1.13.1/tests/auto/api/testdata/link-staticlib-dynamiclib/000077500000000000000000000000001347155106100246705ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/link-staticlib-dynamiclib/link-staticlib-dynamiclib.qbs000066400000000000000000000006761347155106100324320ustar00rootroot00000000000000Project { CppApplication { Depends { name: "mystaticlib" } name: "app" consoleApplication: true files: ["main.cpp"] } StaticLibrary { Depends { name: "cpp" } Depends { name: "mydynamiclib" } name: "mystaticlib" files: ["mystaticlib.cpp"] } DynamicLibrary { name: "mydynamiclib" Depends { name: "cpp" } files: ["mydynamiclib.cpp"] } } qbs-src-1.13.1/tests/auto/api/testdata/link-staticlib-dynamiclib/main.cpp000066400000000000000000000001021347155106100263110ustar00rootroot00000000000000int static_foo(); int main() { return static_foo() - 156; } qbs-src-1.13.1/tests/auto/api/testdata/link-staticlib-dynamiclib/mydynamiclib.cpp000066400000000000000000000001071347155106100300530ustar00rootroot00000000000000#include "../dllexport.h" DLL_EXPORT int dynamic_foo() { return 12; } qbs-src-1.13.1/tests/auto/api/testdata/link-staticlib-dynamiclib/mystaticlib.cpp000066400000000000000000000001521347155106100277160ustar00rootroot00000000000000#include "../dllexport.h" DLL_IMPORT int dynamic_foo(); int static_foo() { return dynamic_foo() * 13; } qbs-src-1.13.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/000077500000000000000000000000001347155106100252365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/dynamic1.cpp000066400000000000000000000002661347155106100274530ustar00rootroot00000000000000#include "../dllexport.h" #include "static2.h" #include DLL_EXPORT int dynamic1_hello() { TestMe tm; tm.hello(); puts("dynamic1 says hello!"); return 1; } qbs-src-1.13.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/dynamic2.cpp000066400000000000000000000001651347155106100274520ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_EXPORT void dynamic2_hello() { puts("dynamic2 says hello!"); } qbs-src-1.13.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/link-staticlibs-dynamiclibs.qbs000066400000000000000000000020121347155106100333300ustar00rootroot00000000000000Project { Application { name : "HelloWorld" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "static1" } } StaticLibrary { name: "static1" files: [ "static1.cpp" ] Depends { name: "cpp" } Depends { name: "dynamic1" } } DynamicLibrary { name : "dynamic1" files : [ "dynamic1.cpp" ] Depends { name: "cpp" } Depends { name: "static2" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } StaticLibrary { name: "static2" files: [ "static2.cpp", "static2.h" ] Depends { name: "cpp" } Depends { name: "dynamic2" } } DynamicLibrary { name: "dynamic2" files: [ "dynamic2.cpp" ] Depends { name: "cpp" } cpp.visibility: 'hidden' Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } } qbs-src-1.13.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/main.cpp000066400000000000000000000002021347155106100266600ustar00rootroot00000000000000#include void static1_hello(); int main() { static1_hello(); puts("application says hello!"); return 0; } qbs-src-1.13.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/static1.cpp000066400000000000000000000002601347155106100273100ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_IMPORT int dynamic1_hello(); void static1_hello() { int n = dynamic1_hello(); printf("static%d says hello!\n", n); } qbs-src-1.13.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/static2.cpp000066400000000000000000000002741347155106100273160ustar00rootroot00000000000000#include "../dllexport.h" #include "static2.h" #include DLL_IMPORT void dynamic2_hello(); void TestMe::hello() const { dynamic2_hello(); puts("static2 says hello!"); } qbs-src-1.13.1/tests/auto/api/testdata/link-staticlibs-dynamiclibs/static2.h000066400000000000000000000001541347155106100267600ustar00rootroot00000000000000#ifndef STATIC2_H #define STATIC2_H class TestMe { public: void hello() const; }; #endif // STATIC2_H qbs-src-1.13.1/tests/auto/api/testdata/local-profiles/000077500000000000000000000000001347155106100225615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/local-profiles/local-profiles.qbs000066400000000000000000000023371347155106100262100ustar00rootroot00000000000000Project { property string windowsProfile: "windowsProfile" property bool enableProfiles property string mingwToolchain: "mingw" property string mingwProfile: "mingwProfile" Profile { name: windowsProfile qbs.targetPlatform: "windows" } Profile { name: project.mingwProfile condition: enableProfiles baseProfile: project.windowsProfile qbs.toolchainType: project.mingwToolchain } Application { name: "app" Depends { name: "cpp"; required: false } aggregate: false multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] qbs.profile: project.mingwProfile } DynamicLibrary { name: "lib" Depends { name: "cpp"; required: false } property string clangToolchain: "clang" property string clangProfileName: "clangProfile" Profile { name: product.clangProfileName condition: project.enableProfiles qbs.targetPlatform: "linux" qbs.toolchainType: product.clangToolchain } multiplexByQbsProperties: ["profiles"] qbs.profiles: [project.mingwProfile, "clangProfile"] } } qbs-src-1.13.1/tests/auto/api/testdata/lots-of-dots/000077500000000000000000000000001347155106100222005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/lots-of-dots/dotty.matrix.ui000066400000000000000000000006541347155106100252120ustar00rootroot00000000000000 Form 0 0 400 300 Form qbs-src-1.13.1/tests/auto/api/testdata/lots-of-dots/lots-of-dots.qbs000066400000000000000000000005331347155106100252420ustar00rootroot00000000000000Project { QtGuiApplication { type: "application" consoleApplication: true name: "lots.of.dots" cpp.cxxLanguageVersion: "c++11" files : [ "m.a.i.n.cpp", "object.narf.h", "object.narf.cpp", "polka.dots.qrc", "dotty.matrix.ui" ] } } qbs-src-1.13.1/tests/auto/api/testdata/lots-of-dots/m.a.i.n.cpp000066400000000000000000000025311347155106100240430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.narf.h" #include #include int main() { ObjectNarf obj; puts("..."); } qbs-src-1.13.1/tests/auto/api/testdata/lots-of-dots/object.narf.cpp000066400000000000000000000025111347155106100250760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.narf.h" #include ObjectNarf::ObjectNarf(QObject *parent) : QObject(parent) {} qbs-src-1.13.1/tests/auto/api/testdata/lots-of-dots/object.narf.h000066400000000000000000000026011347155106100245430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECT_H #define OBJECT_H #include class ObjectNarf : public QObject { Q_OBJECT public: ObjectNarf(QObject *parent = nullptr); }; #endif qbs-src-1.13.1/tests/auto/api/testdata/lots-of-dots/polka.dots.qrc000066400000000000000000000001441347155106100247640ustar00rootroot00000000000000 m.a.i.n.cpp qbs-src-1.13.1/tests/auto/api/testdata/missing-qobject-header/000077500000000000000000000000001347155106100241725ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/missing-qobject-header/main.cpp000066400000000000000000000024301347155106100256210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "myobject.h" int main() { MyObject().func(); } qbs-src-1.13.1/tests/auto/api/testdata/missing-qobject-header/myobject.cpp000066400000000000000000000024141347155106100265130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "myobject.h" void MyObject::func() { } qbs-src-1.13.1/tests/auto/api/testdata/missing-qobject-header/myobject.h000066400000000000000000000024741347155106100261660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { Q_OBJECT public: void func(); }; qbs-src-1.13.1/tests/auto/api/testdata/missing-source-file/000077500000000000000000000000001347155106100235325ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/missing-source-file/file1.txt000066400000000000000000000000001347155106100252610ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/missing-source-file/file2.txt.missing000066400000000000000000000000001347155106100267320ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/missing-source-file/file3.txt000066400000000000000000000000001347155106100252630ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/missing-source-file/missing-source-file.qbs000066400000000000000000000001361347155106100301250ustar00rootroot00000000000000Product { files: [ "file1.txt", "file2.txt", "file3.txt", ] } qbs-src-1.13.1/tests/auto/api/testdata/moc-cpp/000077500000000000000000000000001347155106100212045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/moc-cpp/bla.cpp000066400000000000000000000025461347155106100224550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { Q_OBJECT }; int main() { MyObject obj; return 0; } #include "bla.moc" qbs-src-1.13.1/tests/auto/api/testdata/moc-cpp/moc-cpp.qbs000066400000000000000000000003121347155106100232450ustar00rootroot00000000000000Project { Product { type: "application" consoleApplication: true name: "moc_cpp" Depends { name: "Qt.core" } files: ["bla.cpp"] } } qbs-src-1.13.1/tests/auto/api/testdata/moc-hpp-included/000077500000000000000000000000001347155106100227765ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/moc-hpp-included/moc-hpp-included.qbs000066400000000000000000000005711347155106100266400ustar00rootroot00000000000000Project { Product { type: "application" consoleApplication: true name: "moc_hpp_included" Depends { name: "Qt.core" } cpp.cxxLanguageVersion: "c++11" files: ["object.cpp", "object.h"] Group { condition: qbs.targetOS.contains("darwin") files: ["object2.mm", "object2.h"] } } } qbs-src-1.13.1/tests/auto/api/testdata/moc-hpp-included/object.cpp000066400000000000000000000026241347155106100247540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.h" Object::Object(QObject *parent) : QObject(parent) {} #include "moc_object.cpp" #include int main() { Object obj; printf("Hello World\n"); } qbs-src-1.13.1/tests/auto/api/testdata/moc-hpp-included/object.h000066400000000000000000000025711347155106100244220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECT_H #define OBJECT_H #include class Object : public QObject { Q_OBJECT public: Object(QObject *parent = nullptr); }; #endif qbs-src-1.13.1/tests/auto/api/testdata/moc-hpp-included/object2.h000066400000000000000000000025751347155106100245100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECT2_H #define OBJECT2_H #include class Object2 : public QObject { Q_OBJECT public: Object2(QObject *parent = nullptr); }; #endif qbs-src-1.13.1/tests/auto/api/testdata/moc-hpp-included/object2.mm000066400000000000000000000003151347155106100246600ustar00rootroot00000000000000#include "object2.h" Object2::Object2(QObject *parent) : QObject(parent) {} #include "moc_object2.cpp" #include int main2() { Object2 obj; printf("Hello World\n"); return 0; } qbs-src-1.13.1/tests/auto/api/testdata/moc-hpp/000077500000000000000000000000001347155106100212115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/moc-hpp/moc-hpp.qbs000066400000000000000000000004221347155106100232610ustar00rootroot00000000000000Project { Product { type: "application" consoleApplication: true name: "moc_hpp" Depends { name: "Qt.core" } cpp.cxxLanguageVersion: "c++11" files : [ "object.h", "object.cpp" ] } } qbs-src-1.13.1/tests/auto/api/testdata/moc-hpp/object.cpp000066400000000000000000000025711347155106100231700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.h" #include Object::Object(QObject *parent) : QObject(parent) {} int main() { Object obj; printf("Hello World\n"); } qbs-src-1.13.1/tests/auto/api/testdata/moc-hpp/object.h000066400000000000000000000025711347155106100226350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECT_H #define OBJECT_H #include class Object : public QObject { Q_OBJECT public: Object(QObject *parent = nullptr); }; #endif qbs-src-1.13.1/tests/auto/api/testdata/multi-arch/000077500000000000000000000000001347155106100217135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/multi-arch/host+target.input000066400000000000000000000000001347155106100252210ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/multi-arch/host-tool.input000066400000000000000000000000001347155106100247120ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/multi-arch/multi-arch.qbs000066400000000000000000000027361347155106100244770ustar00rootroot00000000000000import qbs.FileInfo import qbs.TextFile Project { property string hostProfile property string targetProfile Product { property stringList myProfiles name: "p1" type: "output" qbs.profiles: myProfiles ? myProfiles : [project.targetProfile, project.hostProfile] Group { files: "host+target.input" fileTags: "input" } qbs.installPrefix: "" Group { fileTagsFilter: "output" qbs.install: true qbs.installDir: qbs.profile } } Product { name: "p2" type: "output" qbs.profiles: [project.hostProfile] Group { files: "host-tool.input" fileTags: "input" } qbs.installPrefix: "" Group { fileTagsFilter: "output" qbs.install: true qbs.installDir: qbs.profile } } Rule { inputs: "input" Artifact { filePath: FileInfo.baseName(input.fileName) + ".output" fileTags: "output" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); file.write(product.moduleProperty("qbs", "architecture")); file.close(); } return cmd; } } } qbs-src-1.13.1/tests/auto/api/testdata/multiplexing/000077500000000000000000000000001347155106100223675ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/multiplexing/foo.txt000066400000000000000000000000301347155106100237040ustar00rootroot00000000000000Behold! I am the input. qbs-src-1.13.1/tests/auto/api/testdata/multiplexing/multiplexing.qbs000066400000000000000000000105541347155106100256240ustar00rootroot00000000000000import qbs.TextFile Project { Project { name: "subproject 1" Product { name: "multiplex-using-export" type: ["reversed-text"] files: ["foo.txt"] multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] Depends { name: "multiplex-with-export" } } Product { name: "multiplex-without-aggregator-2-depend-on-non-multiplexed" type: ["reversed-text"] files: ["foo.txt"] multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] Depends { name: "no-multiplexing" } } Product { name: "multiplex-with-aggregator-2" type: ["reversed-text"] files: ["foo.txt"] aggregate: true multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] qbs.architecture: "Atari ST" } Product { name: "multiplex-with-aggregator-2-dependent" Depends { name: "multiplex-with-aggregator-2" } type: ["something"] files: ["foo.txt"] } Product { name: "non-multiplexed-with-dependencies-on-multiplexed" Depends { name: "multiplex-without-aggregator-2" } } Product { name: "non-multiplexed-with-dependencies-on-multiplexed-via-export1" Depends { name: "multiplex-with-export" } } Product { name: "non-multiplexed-with-dependencies-on-multiplexed-via-export2" Depends { name: "nonmultiplex-with-export" } } Product { name: "non-multiplexed-with-dependencies-on-aggregation-via-export" Depends { name: "nonmultiplex-exporting-aggregation" } } } Project { name: "subproject 2" Product { name: "no-multiplexing" type: ["reversed-text"] files: ["foo.txt"] } Product { name: "multiplex-without-aggregator-2" type: ["reversed-text"] files: ["foo.txt"] multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] } Product { name: "multiplex-with-export" type: ["reversed-text"] files: ["foo.txt"] multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] Export { Depends { name: "multiplex-without-aggregator-2" } } } Product { name: "nonmultiplex-with-export" type: ["reversed-text"] files: ["foo.txt"] Export { Depends { name: "multiplex-without-aggregator-2" } } } Product { name: "nonmultiplex-exporting-aggregation" type: ["reversed-text"] files: ["foo.txt"] Export { Depends { name: "multiplex-with-aggregator-2" } } } Product { name: "multiplex-without-aggregator-4" type: ["reversed-text"] files: ["foo.txt"] multiplexByQbsProperties: ["architectures", "buildVariants"] qbs.architectures: ["TRS-80", "C64"] qbs.buildVariants: ["debug", "release"] } } Product { name: "aggregate-with-dependencies-on-aggregation-via-export" Depends { name: "nonmultiplex-exporting-aggregation" } aggregate: true multiplexByQbsProperties: ["architectures"] qbs.architectures: ["TRS-80", "C64"] qbs.architecture: "Atari ST" } FileTagger { patterns: ["*.txt"] fileTags: ["text"] } Rule { inputs: ["text"] Artifact { filePath: input.baseName + ".txet" fileTags: ["reversed-text"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "reversing text"; cmd.sourceCode = function() { var tf = new TextFile(input.filePath, TextFile.ReadOnly); var content = tf.readAll(); tf.close(); tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.write(content.split("").reverse().join("")); tf.close(); }; return cmd; } } } qbs-src-1.13.1/tests/auto/api/testdata/new-output-artifact-in-dependency/000077500000000000000000000000001347155106100263105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/new-output-artifact-in-dependency/lib.cpp000066400000000000000000000024151347155106100275640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" DLL_EXPORT void f() {} qbs-src-1.13.1/tests/auto/api/testdata/new-output-artifact-in-dependency/main.cpp000066400000000000000000000024021347155106100277360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ //void f(); int main() { // f(); } new-output-artifact-in-dependency.qbs000066400000000000000000000005311347155106100354010ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/new-output-artifact-in-dependencyProject { DynamicLibrary { //Depends { name: "cpp" } name: "lib" files: "lib.cpp" Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } CppApplication { name: "app" files: "main.cpp" Depends { name: "lib" } } } qbs-src-1.13.1/tests/auto/api/testdata/new-pattern-match/000077500000000000000000000000001347155106100232045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/new-pattern-match/new-pattern-match.qbs000066400000000000000000000000371347155106100272510ustar00rootroot00000000000000Product { files: "*.txt" } qbs-src-1.13.1/tests/auto/api/testdata/nonexistingprojectproperties/000077500000000000000000000000001347155106100257175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/nonexistingprojectproperties/invalidaccessfromproduct.qbs000066400000000000000000000000541347155106100335220ustar00rootroot00000000000000Project { Product { type: project.blubb } } qbs-src-1.13.1/tests/auto/api/testdata/nonexistingprojectproperties/nonexistingprojectproperties.qbs000066400000000000000000000000141347155106100344720ustar00rootroot00000000000000Project { } qbs-src-1.13.1/tests/auto/api/testdata/objc/000077500000000000000000000000001347155106100205635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/objc/main.mm000066400000000000000000000007201347155106100220410ustar00rootroot00000000000000#import #include int main(int argc, char **argv) { // We support both C++ std::cout << "Hello from C++" << std::endl; // And Objective-C NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]; NSString *productVersion = [version objectForKey:@"ProductVersion"]; NSLog(@"Hello, macOS %@!", productVersion); // So it's Objective-C++ } qbs-src-1.13.1/tests/auto/api/testdata/objc/objc.qbs000066400000000000000000000002331347155106100222050ustar00rootroot00000000000000Project { CppApplication { condition: qbs.targetOS.contains("macos") files: "main.mm" cpp.frameworks: [ "Foundation" ] } } qbs-src-1.13.1/tests/auto/api/testdata/precompiled-header-dynamic/000077500000000000000000000000001347155106100250215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/precompiled-header-dynamic/autogen.h.in000066400000000000000000000000241347155106100272350ustar00rootroot00000000000000inline void f() { } qbs-src-1.13.1/tests/auto/api/testdata/precompiled-header-dynamic/main.cpp000066400000000000000000000023631347155106100264550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { f(); } qbs-src-1.13.1/tests/auto/api/testdata/precompiled-header-dynamic/pch.h000066400000000000000000000023601347155106100257450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "autogen.h" qbs-src-1.13.1/tests/auto/api/testdata/precompiled-header-dynamic/precompiled-header-dynamic.qbs000066400000000000000000000012741347155106100327070ustar00rootroot00000000000000import qbs.File CppApplication { name: "MyApp" consoleApplication: true cpp.includePaths: [product.buildDirectory] Group { files: ["pch.h"] fileTags: ["cpp_pch_src"] } Group { files: ["autogen.h.in"] fileTags: ["hpp.in"] } files: ["main.cpp"] Rule { inputs: ["hpp.in"] Artifact { filePath: "autogen.h" fileTags: ["hpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return [cmd]; } } } qbs-src-1.13.1/tests/auto/api/testdata/precompiled-header-new/000077500000000000000000000000001347155106100241665ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/precompiled-header-new/main.cpp000066400000000000000000000033421347155106100256200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "myobject.h" #include #include #include using namespace std; int main() { MyObject obj; list lst; lst.push_back(1); lst.push_back(2); lst.push_back(3); lst.push_back(4); lst.push_back(5); lst.push_back(6); lst.push_back(7); lst.push_back(8); lst.push_back(9); reverse(lst.begin(), lst.end()); for (list::iterator it=lst.begin(); it != lst.end(); ++it) cout << *it << ", "; cout << endl; return 0; } qbs-src-1.13.1/tests/auto/api/testdata/precompiled-header-new/myobject.cpp000066400000000000000000000026351347155106100265140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "myobject.h" MyObject::MyObject() { std::cout << "MyObject::MyObject()\n"; } MyObject::~MyObject() { std::cout << "MyObject::~MyObject()" << std::endl; } qbs-src-1.13.1/tests/auto/api/testdata/precompiled-header-new/myobject.h000066400000000000000000000025101347155106100261510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MYOBJECT_H #define MYOBJECT_H class MyObject { public: MyObject(); ~MyObject(); }; #endif qbs-src-1.13.1/tests/auto/api/testdata/precompiled-header-new/precompiled-header-new.qbs000066400000000000000000000003541347155106100312170ustar00rootroot00000000000000CppApplication { name: "MyApp" consoleApplication: true Group { name: "precompiled headers" files: ["stable.h"] fileTags: ["cpp_pch_src"] } files: ["myobject.h", "main.cpp", "myobject.cpp"] } qbs-src-1.13.1/tests/auto/api/testdata/precompiled-header-new/stable.h000066400000000000000000000025361347155106100256170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /* Add C includes here */ #if defined __cplusplus /* Add C++ includes here */ # include # include #endif qbs-src-1.13.1/tests/auto/api/testdata/process-result/000077500000000000000000000000001347155106100226405ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/process-result/main.cpp000066400000000000000000000025701347155106100242740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int main(int argc, char *argv[]) { std::cout << "stdout"; std::cerr << "stderr"; return atoi(argv[1]); } qbs-src-1.13.1/tests/auto/api/testdata/process-result/process-result.qbs000066400000000000000000000016131347155106100263420ustar00rootroot00000000000000Project { CppApplication { name: "app" files: ["main.cpp"] } Product { name: "app-caller" type: "mytype" Depends { name: "app" } Depends { name: "cpp" } property bool redirectStdout property bool redirectStderr property int argument Rule { inputsFromDependencies: ["application"] outputFileTags: "mytype" prepare: { var cmd = new Command(inputs["application"][0].filePath, [product.argument]); if (product.redirectStdout) cmd.stdoutFilePath = product.buildDirectory + "/stdout.txt"; if (product.redirectStderr) cmd.stderrFilePath = product.buildDirectory + "/stderr.txt"; cmd.description = "Building app-caller"; return [cmd]; } } } } qbs-src-1.13.1/tests/auto/api/testdata/productNameWithDots/000077500000000000000000000000001347155106100236155ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/productNameWithDots/app.cpp000066400000000000000000000023641347155106100251060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/api/testdata/productNameWithDots/lib.cpp000066400000000000000000000023511347155106100250700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void foo() {} qbs-src-1.13.1/tests/auto/api/testdata/productNameWithDots/productNameWithDots.qbs000066400000000000000000000004221347155106100302710ustar00rootroot00000000000000Project { CppApplication { name: "myapp" consoleApplication: true Depends { name: "foo.bar.bla" } files: ["app.cpp"] } StaticLibrary { Depends { name: "cpp" } name: "foo.bar.bla" files: ["lib.cpp"] } } qbs-src-1.13.1/tests/auto/api/testdata/project-data-after-product-invalidation/000077500000000000000000000000001347155106100274575ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-data-after-product-invalidation/file.cpp000066400000000000000000000023501347155106100311020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f() { } qbs-src-1.13.1/tests/auto/api/testdata/project-data-after-product-invalidation/main.cpp000066400000000000000000000023511347155106100311100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} project-data-after-product-invalidation.qbs000066400000000000000000000001451347155106100377200ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-data-after-product-invalidationCppApplication { name: "theProduct" files: [ "file.cpp", "main.cpp", ] } qbs-src-1.13.1/tests/auto/api/testdata/project-editing/000077500000000000000000000000001347155106100227355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-editing/existingfile1.txt000066400000000000000000000000001347155106100262370ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-editing/existingfile2.txt000066400000000000000000000000001347155106100262400ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-editing/existingfile3.txt000066400000000000000000000000001347155106100262410ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-editing/file.cpp000066400000000000000000000023321347155106100243600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-1.13.1/tests/auto/api/testdata/project-editing/file.h000066400000000000000000000023321347155106100240250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-1.13.1/tests/auto/api/testdata/project-editing/main.cpp000066400000000000000000000023321347155106100243650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-1.13.1/tests/auto/api/testdata/project-editing/newfile1.txt000066400000000000000000000000001347155106100251760ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-editing/newfile2.txt000066400000000000000000000000001347155106100251770ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-editing/newfile3.txt000066400000000000000000000000001347155106100252000ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-editing/newfile4.txt000066400000000000000000000000001347155106100252010ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-editing/project-editing.qbs000066400000000000000000000013701347155106100265340ustar00rootroot00000000000000CppApplication { Group { name: "Existing Group 1" files: ["existingfile1.txt"] } property string aFile: "existingfile2.txt" Group { name: "Existing Group 2" files: product.aFile } Group { name: "Existing Group 3" files: { var file = "existingfile3.txt"; return file; } } Group { name: "Existing Group 4" prefix: "subdir/" files: [] } Group { name: "Existing Group 5" prefix: "blubb" files: [] } Group { name: "Group with wildcards" files: "*.klaus" } Group { name: "Other group with wildcards" files: "*.wildcard" } files: "main.cpp" } qbs-src-1.13.1/tests/auto/api/testdata/project-editing/project-with-no-files.qbs000066400000000000000000000000771347155106100276010ustar00rootroot00000000000000CppApplication { Group { files: "file.cpp" } } qbs-src-1.13.1/tests/auto/api/testdata/project-editing/subdir/000077500000000000000000000000001347155106100242255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-editing/subdir/file.txt000066400000000000000000000000001347155106100256730ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-editing/test.wildcard000066400000000000000000000000001347155106100254150ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-invalidation/000077500000000000000000000000001347155106100237735ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-invalidation/project.early-error.qbs000066400000000000000000000000731347155106100304120ustar00rootroot00000000000000Product { type: "mytype" files: "nosuchfile.txt" } qbs-src-1.13.1/tests/auto/api/testdata/project-invalidation/project.late-error.qbs000066400000000000000000000002721347155106100302240ustar00rootroot00000000000000Product { type: "mytype" Rule { inputs: ["mytype"] Artifact { filePath: "blubb" fileTags: "mytype" } prepare: [] } } qbs-src-1.13.1/tests/auto/api/testdata/project-invalidation/project.no-error.qbs000066400000000000000000000000371347155106100277120ustar00rootroot00000000000000Product { type: "mytype" } qbs-src-1.13.1/tests/auto/api/testdata/project-locking/000077500000000000000000000000001347155106100227405ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-locking/project-locking.qbs000066400000000000000000000000141347155106100265340ustar00rootroot00000000000000Project { } qbs-src-1.13.1/tests/auto/api/testdata/project-properties-by-name/000077500000000000000000000000001347155106100250345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-properties-by-name/main1.cpp000066400000000000000000000025051347155106100265470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SUB1 #error "Missing define" #endif #ifdef SUB2 #error "Extraneous define" #endif int main() { } qbs-src-1.13.1/tests/auto/api/testdata/project-properties-by-name/main2.cpp000066400000000000000000000025051347155106100265500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SUB2 #error "Missing define" #endif #ifdef SUB1 #error "Extraneous define" #endif int main() { } qbs-src-1.13.1/tests/auto/api/testdata/project-properties-by-name/project-properties-by-name.qbs000066400000000000000000000007101347155106100327270ustar00rootroot00000000000000Project { name: "toplevel" property stringList theDefines: [] Project { name: "subproject1" CppApplication { name: "subproduct1" files: ["main1.cpp"] cpp.defines: project.theDefines } } Project { name: "subproject2" CppApplication { name: "subproduct2" files: ["main2.cpp"] cpp.defines: project.theDefines } } } qbs-src-1.13.1/tests/auto/api/testdata/project-with-properties-item/000077500000000000000000000000001347155106100254135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/project-with-properties-item/project-with-properties-item.qbs000066400000000000000000000003461347155106100336720ustar00rootroot00000000000000Project { property string binPath: "/usr/bin" property string libPath: "/usr/lib" Properties { condition: qbs.targetOS.contains("macos") binPath: "/Users/boo" libPath: "/Libraries/foo" } } qbs-src-1.13.1/tests/auto/api/testdata/projectd000066400000000000000000000000001347155106100213710ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/properties-blocks/000077500000000000000000000000001347155106100233155ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/properties-blocks/main.cpp000066400000000000000000000030071347155106100247450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #ifndef HAVE_MAIN_CPP # error missing define HAVE_MAIN_CPP #endif #ifndef DEFINE_IN_PROPERTIES # error missing define DEFINE_IN_PROPERTIES #endif int main() { #ifdef _DEBUG puts("Hello World! (debug version)"); #else puts("Hello World! (release version)"); #endif } qbs-src-1.13.1/tests/auto/api/testdata/properties-blocks/properties-blocks.qbs000066400000000000000000000010351347155106100274720ustar00rootroot00000000000000Product { Depends { name: 'cpp' } Properties { condition: true type: 'application' consoleApplication: true name: 'HelloWorld' } Properties { condition: name == 'HelloWorld' cpp.defines: ['DEFINE_IN_PROPERTIES'] } Properties { condition: qbs.targetOS.contains("weird") cpp.staticLibraries: "abc" } Group { cpp.defines: outer.concat(['HAVE_MAIN_CPP', cpp.debugInformation ? '_DEBUG' : '_RELEASE']) files: ['main.cpp'] } } qbs-src-1.13.1/tests/auto/api/testdata/qt5-plugin/000077500000000000000000000000001347155106100216535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/qt5-plugin/echointerface.h000066400000000000000000000031221347155106100246210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef ECHOINTERFACE_H #define ECHOINTERFACE_H #include //! [0] class EchoInterface { public: virtual ~EchoInterface() {} virtual QString echo(const QString &message) = 0; }; QT_BEGIN_NAMESPACE #define EchoInterface_iid "org.qt-project.Qt.Examples.EchoInterface" Q_DECLARE_INTERFACE(EchoInterface, EchoInterface_iid) QT_END_NAMESPACE //! [0] #endif qbs-src-1.13.1/tests/auto/api/testdata/qt5-plugin/echoplugin.cpp000066400000000000000000000024751347155106100245240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "echoplugin.h" QString EchoPlugin::echo(const QString &message) { return message; } qbs-src-1.13.1/tests/auto/api/testdata/qt5-plugin/echoplugin.h000066400000000000000000000031031347155106100241560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef ECHOPLUGIN_H #define ECHOPLUGIN_H #include #include #include "echointerface.h" class EchoPlugin : public QObject, EchoInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.EchoInterface" FILE "echoplugin.json") Q_INTERFACES(EchoInterface) public: QString echo(const QString &message); }; #endif qbs-src-1.13.1/tests/auto/api/testdata/qt5-plugin/echoplugin.json.source000066400000000000000000000000031347155106100261730ustar00rootroot00000000000000{} qbs-src-1.13.1/tests/auto/api/testdata/qt5-plugin/echoplugin_dummy.cpp000066400000000000000000000023571347155106100257360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void dummyFunc() {} qbs-src-1.13.1/tests/auto/api/testdata/qt5-plugin/qt5-plugin.qbs000066400000000000000000000022431347155106100243700ustar00rootroot00000000000000import qbs.base import qbs.File import qbs.FileInfo DynamicLibrary { name: "echoplugin" Depends { name: "Qt.core" } Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } Group { condition: Qt.core.versionMajor >= 5 files: [ "echoplugin.h", "echoplugin.cpp", ] } Group { condition: Qt.core.versionMajor >= 5 files: ["echoplugin.json.source"] fileTags: ["json_in"] } Group { condition: Qt.core.versionMajor < 5 files: "echoplugin_dummy.cpp" } cpp.includePaths: buildDirectory Rule { condition: Qt.core.versionMajor >= 5 inputs: ["json_in"] Artifact { filePath: "echoplugin.json" fileTags: ["qt_plugin_metadata"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + FileInfo.fileName(output.filePath); cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } qbs-src-1.13.1/tests/auto/api/testdata/rc/000077500000000000000000000000001347155106100202525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/rc/main.cpp000066400000000000000000000023701347155106100217040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/api/testdata/rc/rc.qbs000066400000000000000000000003201347155106100213600ustar00rootroot00000000000000Application { type: "application" consoleApplication: true name: "rctest" Depends { name: 'cpp' } cpp.includePaths: "subdir" files: [ "main.cpp", "test.rc" ] } qbs-src-1.13.1/tests/auto/api/testdata/rc/subdir/000077500000000000000000000000001347155106100215425ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/rc/subdir/rc-include.h000066400000000000000000000000001347155106100237260ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/rc/test.rc000066400000000000000000000006211347155106100215560ustar00rootroot00000000000000#define IDR_VERSION1 1 #include IDR_VERSION1 VERSIONINFO FILEVERSION 1,0,0,0 PRODUCTVERSION 1,0,0,0 FILEOS 0x00000004 FILETYPE 0x00000000 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "FFFF0000" BEGIN VALUE "FileVersion", "1.0.0.0\0" VALUE "ProductVersion", "1.0.0.0\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0xFFFF, 0x0000 END END qbs-src-1.13.1/tests/auto/api/testdata/recursive-wildcards/000077500000000000000000000000001347155106100236275ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/recursive-wildcards/dir/000077500000000000000000000000001347155106100244055ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/recursive-wildcards/dir/file1.txt000066400000000000000000000000001347155106100261340ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/recursive-wildcards/dir/subdir/000077500000000000000000000000001347155106100256755ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/recursive-wildcards/dir/subdir/file2.txt000066400000000000000000000000001347155106100274250ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/recursive-wildcards/recursive-wildcards.qbs000066400000000000000000000002101347155106100303100ustar00rootroot00000000000000Product { qbs.installPrefix: "" Group { files: "dir/**" qbs.install: true qbs.installDir: "dir" } } qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/000077500000000000000000000000001347155106100241775ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/ambiguousdir/000077500000000000000000000000001347155106100266715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/ambiguousdir/p1.qbs000066400000000000000000000000001347155106100277060ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/ambiguousdir/p2.qbs000066400000000000000000000000001347155106100277070ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/cycle.qbs000066400000000000000000000002131347155106100260010ustar00rootroot00000000000000Project { property string productName: "p1" Product { name: project.productName } references: ["referenced-file-errors.qbs"] } qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/emptydir/000077500000000000000000000000001347155106100260345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/emptydir/.gitignore000066400000000000000000000000001347155106100300120ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/modules/000077500000000000000000000000001347155106100256475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/modules/brokenmodule/000077500000000000000000000000001347155106100303355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/modules/brokenmodule/brokenmodule.qbs000066400000000000000000000000341347155106100335270ustar00rootroot00000000000000Module { syntax error } qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/okay.qbs000066400000000000000000000000271347155106100256500ustar00rootroot00000000000000Product { name: "p2" } qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/okay2.qbs000066400000000000000000000000271347155106100257320ustar00rootroot00000000000000Product { name: "p4" } qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/referenced-file-errors.qbs000066400000000000000000000007411347155106100312410ustar00rootroot00000000000000Project { references: [ "ambiguousdir", "cycle.qbs", "emptydir", "nosuchfile.qbs", "okay.qbs", "wrongtype.qbs", ] SubProject { filePath: "cycle.qbs" Properties { productName: "p3" } } SubProject { filePath: "nosuchfile.qbs" } SubProject { filePath: "okay2.qbs" } Product { name: "p5" Depends { name: "brokenmodule" } } } qbs-src-1.13.1/tests/auto/api/testdata/referenced-file-errors/wrongtype.qbs000066400000000000000000000000131347155106100267360ustar00rootroot00000000000000Module { } qbs-src-1.13.1/tests/auto/api/testdata/references/000077500000000000000000000000001347155106100217675ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/references/invalid1.qbs000066400000000000000000000000641347155106100242050ustar00rootroot00000000000000Project { references: "subdir-with-no-project" }qbs-src-1.13.1/tests/auto/api/testdata/references/invalid2.qbs000066400000000000000000000000731347155106100242060ustar00rootroot00000000000000Project { references: "subdir-with-multiple-projects" }qbs-src-1.13.1/tests/auto/api/testdata/references/subdir-with-multiple-projects/000077500000000000000000000000001347155106100277105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/references/subdir-with-multiple-projects/subproject1.qbs000066400000000000000000000000001347155106100326460ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/references/subdir-with-multiple-projects/subproject2.qbs000066400000000000000000000000001347155106100326470ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/references/subdir-with-multiple-projects/subproject3.qbs000066400000000000000000000000001347155106100326500ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/references/subdir-with-no-project/000077500000000000000000000000001347155106100263065ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/references/subdir-with-no-project/test.txt000066400000000000000000000000001347155106100300140ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/references/subdir-with-one-project/000077500000000000000000000000001347155106100264535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/references/subdir-with-one-project/p.qbs000066400000000000000000000000141347155106100274140ustar00rootroot00000000000000Project { } qbs-src-1.13.1/tests/auto/api/testdata/references/subdir-with-one-project/test.txt000066400000000000000000000000001347155106100301610ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/references/valid.qbs000066400000000000000000000000661347155106100235770ustar00rootroot00000000000000Project { references: "subdir-with-one-project" } qbs-src-1.13.1/tests/auto/api/testdata/relaxed-mode-recovery/000077500000000000000000000000001347155106100240505ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/relaxed-mode-recovery/relaxed-mode-recovery.qbs000066400000000000000000000003111347155106100307540ustar00rootroot00000000000000Project { Product { name: "dep" Export { Depends { name: "blubb" } } } Product { name: "p1"; Depends { name: "dep" } } Product { name: "p2"; Depends { name: "dep" } } } qbs-src-1.13.1/tests/auto/api/testdata/remove-file-dependency/000077500000000000000000000000001347155106100241745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/remove-file-dependency/main.cpp000066400000000000000000000025321347155106100256260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "someheader.h" #include int main() { printf("The magic value is %d.\n", magicValue()); return 0; } qbs-src-1.13.1/tests/auto/api/testdata/remove-file-dependency/removeFileDependency.qbs000066400000000000000000000002021347155106100307710ustar00rootroot00000000000000CppApplication { files: ["main.cpp"] // Do not reference header files here to force them to be FileDependency objects. } qbs-src-1.13.1/tests/auto/api/testdata/remove-file-dependency/someheader.h000066400000000000000000000024031347155106100264600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ inline int magicValue() { return 156; } qbs-src-1.13.1/tests/auto/api/testdata/rename-product/000077500000000000000000000000001347155106100225735ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/rename-product/lib.cpp000066400000000000000000000024151347155106100240470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" MY_EXPORT void f() { } qbs-src-1.13.1/tests/auto/api/testdata/rename-product/main.cpp000066400000000000000000000023761347155106100242330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f(); int main() { f(); } qbs-src-1.13.1/tests/auto/api/testdata/rename-product/rename.qbs000066400000000000000000000006271347155106100245560ustar00rootroot00000000000000Project { CppApplication { Depends { name: "TheLib" } cpp.defines: "MY_EXPORT=" files: "main.cpp" } DynamicLibrary { name: "TheLib" Depends { name: "cpp" } cpp.defines: "MY_EXPORT=DLL_EXPORT" files: "lib.cpp" Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } } qbs-src-1.13.1/tests/auto/api/testdata/rename-target-artifact/000077500000000000000000000000001347155106100241745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/rename-target-artifact/lib.cpp000066400000000000000000000024151347155106100254500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" MY_EXPORT void f() { } qbs-src-1.13.1/tests/auto/api/testdata/rename-target-artifact/main.cpp000066400000000000000000000023761347155106100256340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f(); int main() { f(); } qbs-src-1.13.1/tests/auto/api/testdata/rename-target-artifact/rename.qbs000066400000000000000000000007751347155106100261630ustar00rootroot00000000000000Project { CppApplication { Depends { name: "TheLib" } cpp.defines: "MY_EXPORT=" qbs.buildVariant: "release" files: "main.cpp" } DynamicLibrary { name: "TheLib" targetName: "the_lib" Depends { name: "cpp" } cpp.defines: "MY_EXPORT=DLL_EXPORT" qbs.buildVariant: "release" files: "lib.cpp" Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } } qbs-src-1.13.1/tests/auto/api/testdata/restored-warnings/000077500000000000000000000000001347155106100233235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/restored-warnings/file.cpp000066400000000000000000000000141347155106100247410ustar00rootroot00000000000000void f() {} qbs-src-1.13.1/tests/auto/api/testdata/restored-warnings/main.cpp000066400000000000000000000000161347155106100247500ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/api/testdata/restored-warnings/restored-warnings.qbs000066400000000000000000000003531347155106100275100ustar00rootroot00000000000000import qbs.Process 1.5 CppApplication { name: "theProduct" property bool moreFiles: false cpp.blubb: true files: ["file.cpp", "main.cpp"] Group { condition: moreFiles files: ["blubb.cpp"] } } qbs-src-1.13.1/tests/auto/api/testdata/rule-conflict/000077500000000000000000000000001347155106100224145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/rule-conflict/main.cpp000066400000000000000000000023511347155106100240450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/api/testdata/rule-conflict/pch1.h000066400000000000000000000023321347155106100234200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-1.13.1/tests/auto/api/testdata/rule-conflict/pch2.h000066400000000000000000000023321347155106100234210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-1.13.1/tests/auto/api/testdata/rule-conflict/rule-conflict.qbs000066400000000000000000000002311347155106100256650ustar00rootroot00000000000000CppApplication { files: "main.cpp" Group { name: "pch files" files: ["pch1.h", "pch2.h"] fileTags: "cpp_pch_src" } } qbs-src-1.13.1/tests/auto/api/testdata/run-disabled-product/000077500000000000000000000000001347155106100236755ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/run-disabled-product/run-disabled-product.qbs000066400000000000000000000000701347155106100304300ustar00rootroot00000000000000CppApplication { name: "app" condition: false } qbs-src-1.13.1/tests/auto/api/testdata/same-base-name/000077500000000000000000000000001347155106100224215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/same-base-name/lib.c000066400000000000000000000024731347155106100233410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include extern void printHelloC() { printf("Hello from C in " __FILE__ "\n"); } qbs-src-1.13.1/tests/auto/api/testdata/same-base-name/lib.cpp000066400000000000000000000025241347155106100236760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include extern "C" void printHelloCpp() { std::cout << "Hello from C++ in " << __FILE__ << std::endl; } qbs-src-1.13.1/tests/auto/api/testdata/same-base-name/lib.m000066400000000000000000000001671347155106100233510ustar00rootroot00000000000000#import extern void printHelloObjc() { NSLog(@"Hello from Objective-C in " __FILE__); } qbs-src-1.13.1/tests/auto/api/testdata/same-base-name/lib.mm000066400000000000000000000002721347155106100235230ustar00rootroot00000000000000#include #import extern "C" void printHelloObjcpp() { NSLog(@"Hello from Objective-C++..."); std::cout << "...in " __FILE__ << std::endl; } qbs-src-1.13.1/tests/auto/api/testdata/same-base-name/main.c000066400000000000000000000027661347155106100235240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ extern void printHelloC(); extern void printHelloCpp(); #ifdef __APPLE__ extern void printHelloObjc(); extern void printHelloObjcpp(); #endif int main() { printHelloC(); printHelloCpp(); #ifdef __APPLE__ printHelloObjc(); printHelloObjcpp(); #endif return 0; } qbs-src-1.13.1/tests/auto/api/testdata/same-base-name/same-base-name.qbs000066400000000000000000000012301347155106100256770ustar00rootroot00000000000000Project { CppApplication { type: "application" consoleApplication: true Depends { name: "basenamelib" } name: "basename" files: "main.c" } StaticLibrary { Depends { name: "cpp" } name: "basenamelib" files: [ "lib.c", "lib.cpp" ] Group { condition: qbs.targetOS.contains("darwin") files: [ "lib.m", "lib.mm" ] } Export { Depends { name: "cpp" } cpp.frameworks: qbs.targetOS.contains("darwin") ? "Foundation" : undefined } } } qbs-src-1.13.1/tests/auto/api/testdata/simple-probe/000077500000000000000000000000001347155106100222445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/simple-probe/main.cpp000066400000000000000000000023641347155106100237010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/api/testdata/simple-probe/simple-probe.qbs000066400000000000000000000012201347155106100253440ustar00rootroot00000000000000import qbs.Probes CppApplication { Probe { id: probe1 property string someString configure: { someString = "one"; found = true; } } Probe { id: probe2 configure: { found = false; } } type: ["application"] name: "MyApp" consoleApplication: { if (!probe1.found) throw "probe1 not found"; if (probe2.found) throw "probe2 unexpectedly found"; if (probe1.someString !== "one") throw "probe1.someString expected to be \"one\"." return true } files: ["main.cpp"] } qbs-src-1.13.1/tests/auto/api/testdata/soft-dependency/000077500000000000000000000000001347155106100227355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/soft-dependency/main.cpp000066400000000000000000000024031347155106100243640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { thisShouldNotLink(); } qbs-src-1.13.1/tests/auto/api/testdata/soft-dependency/soft-dependency.qbs000066400000000000000000000002651347155106100265360ustar00rootroot00000000000000CppApplication { Depends { name: "nosuchmodule" required: false } Properties { condition: nosuchmodule.present files: "main.cpp" } } qbs-src-1.13.1/tests/auto/api/testdata/source-file-in-build-dir/000077500000000000000000000000001347155106100243405ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/source-file-in-build-dir/file.cpp000066400000000000000000000023521347155106100257650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-1.13.1/tests/auto/api/testdata/source-file-in-build-dir/source-file-in-build-dir.qbs000066400000000000000000000011271347155106100315420ustar00rootroot00000000000000import qbs.TextFile CppApplication { name: "theProduct" type: base.concat(["dummy"]) Rule { multiplex: true Artifact { filePath: "generated.cpp" fileTags: ["dummy"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return [cmd]; } } Group { name: "the group" files: "**/*.cpp" } } qbs-src-1.13.1/tests/auto/api/testdata/static-lib-deps/000077500000000000000000000000001347155106100226325ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/static-lib-deps/a1.cpp000066400000000000000000000024431347155106100236420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include void a1() { std::cout << "a1" << std::endl; } qbs-src-1.13.1/tests/auto/api/testdata/static-lib-deps/a2.cpp000066400000000000000000000024431347155106100236430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include void a2() { std::cout << "a2" << std::endl; } qbs-src-1.13.1/tests/auto/api/testdata/static-lib-deps/b.cpp000066400000000000000000000023771347155106100235700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void a1(); void b() { a1(); } qbs-src-1.13.1/tests/auto/api/testdata/static-lib-deps/c.cpp000066400000000000000000000023771347155106100235710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void a2(); void c() { a2(); } qbs-src-1.13.1/tests/auto/api/testdata/static-lib-deps/d.cpp000066400000000000000000000035741347155106100235720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef WITH_PTHREAD #include #elif defined(WITH_LEX_YACC) extern "C" int yywrap(void); extern "C" void yyerror(char const *s); extern void printGreeting(); #elif defined(WITH_SETUPAPI) #include #include #endif void b(); void c(); int d() { b(); c(); #ifdef WITH_PTHREAD pthread_t self = pthread_self(); return static_cast(self); #elif defined(WITH_LEX_YACC) yywrap(); yyerror("no error"); printGreeting(); return 0; #elif defined(WITH_SETUPAPI) CABINET_INFO ci; ci.SetId = 0; SetupIterateCabinet(L"invalid-file-path", 0, NULL, NULL); return ci.SetId; #else return 0; #endif } qbs-src-1.13.1/tests/auto/api/testdata/static-lib-deps/d.mm000066400000000000000000000002751347155106100234140ustar00rootroot00000000000000#import void printGreeting() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSLog (@"Hello darkness, my old friend!"); [pool drain]; } qbs-src-1.13.1/tests/auto/api/testdata/static-lib-deps/e.cpp000066400000000000000000000024021347155106100235600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int d(); int e() { return d(); } qbs-src-1.13.1/tests/auto/api/testdata/static-lib-deps/main.cpp000066400000000000000000000024051347155106100242630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int e(); int main() { return e(); } qbs-src-1.13.1/tests/auto/api/testdata/static-lib-deps/static-lib-deps.qbs000066400000000000000000000034341347155106100263310ustar00rootroot00000000000000Project { StaticLibrary { name: "a" Depends { name: "cpp" } files: [ "a1.cpp", "a2.cpp", ] } StaticLibrary { name: "b" Depends { name: "cpp" } Depends { name: "a" } files: [ "b.cpp", ] } StaticLibrary { name: "c" Depends { name: "cpp" } Depends { name: "a" } files: [ "c.cpp", ] } StaticLibrary { name: "d" Depends { name: "cpp" } Depends { name: "b" } Depends { name: "c" } files: [ "d.cpp", ] Group { condition: qbs.targetOS.contains("macos") files: ["d.mm"] } Properties { condition: qbs.targetOS.contains("windows") cpp.defines: ["WITH_SETUPAPI"] cpp.staticLibraries: ["setupapi"] } Properties { condition: qbs.targetOS.contains("macos") cpp.defines: ["WITH_LEX_YACC"] cpp.staticLibraries: ["l", "y"] cpp.frameworks: ["Foundation"] } Properties { condition: qbs.targetOS.contains("linux") cpp.defines: ["WITH_PTHREAD"] cpp.staticLibraries: ["pthread"] } } StaticLibrary { name: "e" Depends { name: "cpp" } Depends { name: "d" } files: [ "e.cpp", ] } CppApplication { name: "staticLibDeps" type: "application" consoleApplication: true Depends { name: "e" } Properties { condition: qbs.targetOS.contains("linux") cpp.driverFlags: ["-static"] } files: [ "main.cpp", ] } } qbs-src-1.13.1/tests/auto/api/testdata/subprojects/000077500000000000000000000000001347155106100222115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/subprojects/resources/000077500000000000000000000000001347155106100242235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/subprojects/resources/imports/000077500000000000000000000000001347155106100257205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/subprojects/resources/imports/LibraryType/000077500000000000000000000000001347155106100301665ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/subprojects/resources/imports/LibraryType/type.js000066400000000000000000000000551347155106100315050ustar00rootroot00000000000000function type() { return "dynamiclibrary"; } qbs-src-1.13.1/tests/auto/api/testdata/subprojects/resources/modules/000077500000000000000000000000001347155106100256735ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/subprojects/resources/modules/QtCoreDepender/000077500000000000000000000000001347155106100305375ustar00rootroot00000000000000qtcoredepender.qbs000066400000000000000000000000551347155106100341730ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/subprojects/resources/modules/QtCoreDependerModule { Depends { name: "cute.core" } } qbs-src-1.13.1/tests/auto/api/testdata/subprojects/resources/modules/cute/000077500000000000000000000000001347155106100266335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/subprojects/resources/modules/cute/core/000077500000000000000000000000001347155106100275635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/subprojects/resources/modules/cute/core/core.qbs000066400000000000000000000001041347155106100312150ustar00rootroot00000000000000Module { Depends { name: "cpp" } cpp.includePaths: [path] } qbs-src-1.13.1/tests/auto/api/testdata/subprojects/resources/modules/cute/core/cuteglobal.h000066400000000000000000000000411347155106100320500ustar00rootroot00000000000000#define Q_DECL_EXPORT DLL_EXPORT qbs-src-1.13.1/tests/auto/api/testdata/subprojects/subproject1/000077500000000000000000000000001347155106100244525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/subprojects/subproject1/main.cpp000066400000000000000000000023761347155106100261120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f(); int main() { f(); } qbs-src-1.13.1/tests/auto/api/testdata/subprojects/subproject2/000077500000000000000000000000001347155106100244535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/subprojects/subproject2/subproject2.qbs000066400000000000000000000005101347155106100274200ustar00rootroot00000000000000Project { name: "subproject2" property string libNamePrefix: "test" SubProject { filePath: "subproject3/subproject3.qbs" inheritProperties: true Properties { name: "overridden name" condition: qbs.targetOS.length > 0 libNameSuffix: "Lib" } } } qbs-src-1.13.1/tests/auto/api/testdata/subprojects/subproject2/subproject3/000077500000000000000000000000001347155106100267165ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/subprojects/subproject2/subproject3/subproject3.qbs000066400000000000000000000006311347155106100316700ustar00rootroot00000000000000import LibraryType Project { condition: false property string libNameSuffix: "blubb" Product { name: project.libNamePrefix + project.libNameSuffix type: LibraryType.type() Depends { name: "cpp" } Depends { name: "QtCoreDepender" } cpp.defines: "MY_EXPORT=Q_DECL_EXPORT" files: "testlib.cpp" Export { Depends { name: "cute.core" } } } } qbs-src-1.13.1/tests/auto/api/testdata/subprojects/subproject2/subproject3/testlib.cpp000066400000000000000000000024521347155106100310730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "../../../dllexport.h" MY_EXPORT void f() {} qbs-src-1.13.1/tests/auto/api/testdata/subprojects/toplevelproject.qbs000066400000000000000000000005511347155106100261420ustar00rootroot00000000000000Project { name: "top level project" references: ["subproject2"] Project { condition: true name: "app-project" CppApplication { name: "app" Depends { name: "testLib" } cpp.defines: "MY_EXPORT=" files: "subproject1/main.cpp" } } qbsSearchPaths: ["resources"] } qbs-src-1.13.1/tests/auto/api/testdata/target-artifact-status/000077500000000000000000000000001347155106100242505ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/target-artifact-status/target-artifact-status.qbs000066400000000000000000000014121347155106100313570ustar00rootroot00000000000000import qbs.TextFile Product { name: "p" type: "p_type" property bool enableTagging Rule { multiplex: true Artifact { filePath: "a1"; fileTags: "p_type" } Artifact { filePath: "a2"; fileTags: "x" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating outputs"; cmd.sourceCode = function() { var f = new TextFile(outputs.p_type[0].filePath, TextFile.WriteOnly); f.close(); f = new TextFile(outputs.x[0].filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } Group { condition: enableTagging fileTagsFilter: "x" fileTags: "p_type" } } qbs-src-1.13.1/tests/auto/api/testdata/tool-in-module/000077500000000000000000000000001347155106100225125ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/tool-in-module/use-outside-project/000077500000000000000000000000001347155106100264245ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/tool-in-module/use-outside-project/modules/000077500000000000000000000000001347155106100300745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/tool-in-module/use-outside-project/modules/thetool/000077500000000000000000000000001347155106100315525ustar00rootroot00000000000000thetool.qbs000066400000000000000000000014251347155106100336620ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/tool-in-module/use-outside-project/modules/thetoolimport qbs.FileInfo Module { Depends { name: "cpp" } Group { name: "thetool binary" files: FileInfo.cleanPath(FileInfo.joinPaths(path, "..", "..", "thetool" + (qbs.hostOS.contains("windows") ? ".exe" : ""))); fileTags: ["thetool.thetool"] filesAreTargets: true } Rule { multiplex: true explicitlyDependsOnFromDependencies: ["thetool.thetool"] Artifact { filePath: "tool-output.txt" fileTags: ["thetool.output"] } prepare: { var cmd = new Command(explicitlyDependsOn["thetool.thetool"][0].filePath, output.filePath); cmd.description = "running the tool"; return [cmd]; } } } qbs-src-1.13.1/tests/auto/api/testdata/tool-in-module/use-outside-project/use-outside-project.qbs000066400000000000000000000001521347155106100330430ustar00rootroot00000000000000Product { name: "user-outside-project" type: ["thetool.output"] Depends { name: "thetool" } } qbs-src-1.13.1/tests/auto/api/testdata/tool-in-module/use-within-project/000077500000000000000000000000001347155106100262525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/tool-in-module/use-within-project/main.cpp000066400000000000000000000002671347155106100277070ustar00rootroot00000000000000#include #include int main(int argc, char *argv[]) { assert(argc == 2); std::ofstream file(argv[1]); assert(file.is_open()); file << "content"; } qbs-src-1.13.1/tests/auto/api/testdata/tool-in-module/use-within-project/tool-input.txt000066400000000000000000000000001347155106100311130ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/tool-in-module/use-within-project/use-within-project.qbs000066400000000000000000000020531347155106100325210ustar00rootroot00000000000000Project { CppApplication { name: "thetool" consoleApplication: true files: "main.cpp" install: true installDir: "" qbs.installPrefix: "" Group { fileTagsFilter: ["application"] fileTags: ["thetool.thetool"] } Export { Depends { name: "cpp" } Rule { multiplex: true explicitlyDependsOnFromDependencies: ["thetool.thetool"] Artifact { filePath: "tool-output.txt" fileTags: ["thetool.output"] } prepare: { var cmd = new Command(explicitlyDependsOn["thetool.thetool"][0].filePath, output.filePath); cmd.description = "running the tool"; return [cmd]; } } } } Product { name: "user-in-project" type: ["thetool.output"] Depends { name: "thetool" } } } qbs-src-1.13.1/tests/auto/api/testdata/transformer-data/000077500000000000000000000000001347155106100231175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/transformer-data/transformer-data.qbs000066400000000000000000000016311347155106100271000ustar00rootroot00000000000000import qbs.File import qbs.TextFile Product { type: ["theType"] Rule { multiplex: true Artifact { filePath: "artifact1" fileTags: ["type1"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return [cmd]; } } Rule { inputs: ["type1"] Artifact { filePath: "artifact2" fileTags: ["theType"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/api/testdata/transformers/000077500000000000000000000000001347155106100223735ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/transformers/main.cpp000066400000000000000000000043731347155106100240320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include using namespace std; bool displayTextFile(const string &dirPath, const string &fileName) { string fullPath = dirPath + fileName; ifstream istream(fullPath.c_str()); if (!istream.is_open()) { cout << "Cannot open " << fileName << endl; return false; } cout << "---" << fileName << "---" << endl; char buf[256]; unsigned int i = 1; while (istream.good()) { istream.getline(buf, sizeof(buf)); cout << i++ << ": " << buf << endl; } return true; } int main(int, char **argv) { string appPath(argv[0]); size_t i = appPath.find_last_of('/'); if (i == string::npos) i = appPath.find_last_of('\\'); if (i == string::npos) // No path, plain executable was called appPath.clear(); else appPath.resize(i + 1); if (!displayTextFile(appPath, "foo.txt")) return 1; if (!displayTextFile(appPath, "bar.txt")) return 2; cout << "-------------" << endl; return 0; } qbs-src-1.13.1/tests/auto/api/testdata/transformers/transformers.qbs000066400000000000000000000056101347155106100256310ustar00rootroot00000000000000import qbs.File import qbs.TextFile import qbs.Xml import qbs.FileInfo Project { Product { name: "HelloWorld" type: "application" consoleApplication: true Group { files: ["main.cpp"] fileTags: ["main"] } Depends { name: "cpp" } Rule { // no inputs -> just a generator multiplex: true Artifact { filePath: "foo.txt" fileTags: "text" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating foo.txt"; cmd.highlight = "linker"; cmd.sourceCode = function () { File.remove(output.filePath); var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("Dear Sir/Madam,\n\n"); f.write("this is a generated file.\n\n\n"); f.write("Best Regards and Mellow Greetings,\nYour Build Tool.\n"); f.close(); } return cmd; } } Rule { multiplex: true // no inputs -> just a generator Artifact { filePath: "foo.xml" fileTags: "xml" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating foo.xml"; cmd.highlight = "linker"; cmd.sourceCode = function () { File.remove(output.filePath); var doc = new Xml.DomDocument(); var root = doc.createElement("root"); doc.appendChild(root); var tag = doc.createElement("Greeting"); root.appendChild(tag); tag.appendChild(doc.createTextNode("text node")); doc.save(output.filePath); } return cmd; } } Rule { inputs: ["main"] Artifact { filePath: "bar.txt" fileTags: "text" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating bar.txt"; cmd.highlight = "linker"; cmd.inputFileName = input.filePath; cmd.sourceCode = function() { File.remove(output.filePath); var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("Dear Sir/Madam,\n\n"); f.write("this file was generated from " + inputFileName + ".\n\n\n"); f.write("Best Regards and Mellow Greetings,\nYour Build Tool.\n"); f.close(); } return cmd; } } } } qbs-src-1.13.1/tests/auto/api/testdata/two-default-property-values/000077500000000000000000000000001347155106100252605ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/two-default-property-values/modules/000077500000000000000000000000001347155106100267305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/two-default-property-values/modules/mymodule/000077500000000000000000000000001347155106100305635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/two-default-property-values/modules/mymodule/mymodule.qbs000066400000000000000000000011431347155106100331240ustar00rootroot00000000000000import qbs.TextFile Module { property string direct property string indirect: direct ? "set" : "unset" Rule { inputs: ["txt"] Artifact { filePath: product.moduleProperty("mymodule", "indirect") fileTags: ["mymodule"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/api/testdata/two-default-property-values/modules/myothermodule/000077500000000000000000000000001347155106100316255ustar00rootroot00000000000000myothermodule.qbs000066400000000000000000000000541347155106100351510ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/two-default-property-values/modules/myothermoduleModule { Depends { name: "mymodule" } } qbs-src-1.13.1/tests/auto/api/testdata/two-default-property-values/test.txt000066400000000000000000000000001347155106100267660ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/two-default-property-values/two-default-property-values.qbs000066400000000000000000000003651347155106100334050ustar00rootroot00000000000000Product { name: "two-default-property-values" type: "mymodule" Depends { name: "mymodule" } Depends { name: "myothermodule" } mymodule.direct: "dummy" Group { files: ["test.txt"] fileTags: ["txt"] } } qbs-src-1.13.1/tests/auto/api/testdata/type-change/000077500000000000000000000000001347155106100220525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/type-change/main.cpp000066400000000000000000000023511347155106100235030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/api/testdata/type-change/type-change.qbs000066400000000000000000000001311347155106100247600ustar00rootroot00000000000000Product { files: "main.cpp" Depends { name: "cpp" } // type: "application" } qbs-src-1.13.1/tests/auto/api/testdata/uic/000077500000000000000000000000001347155106100204265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/api/testdata/uic/bla.cpp000066400000000000000000000024661347155106100217000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "bla.h" int main() { Ui::MainWindow mainWindow; Q_UNUSED(mainWindow); } qbs-src-1.13.1/tests/auto/api/testdata/uic/bla.h000066400000000000000000000023531347155106100213400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "ui.h" qbs-src-1.13.1/tests/auto/api/testdata/uic/ui.h000066400000000000000000000023561347155106100212220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "ui_ui.h" qbs-src-1.13.1/tests/auto/api/testdata/uic/ui.ui000066400000000000000000000012641347155106100214050ustar00rootroot00000000000000 MainWindow 0 0 800 600 MainWindow 0 0 800 25 qbs-src-1.13.1/tests/auto/api/testdata/uic/uic.qbs000066400000000000000000000003511347155106100217140ustar00rootroot00000000000000Project { QtGuiApplication { type: "application" consoleApplication: true name: "ui" files: [ "bla.cpp", "bla.h", "ui.ui", "ui.h" ] } } qbs-src-1.13.1/tests/auto/api/tst_api.cpp000066400000000000000000004056161347155106100202200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_api.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VERIFY_NO_ERROR(errorInfo) \ QVERIFY2(!errorInfo.hasError(), qPrintable(errorInfo.toString())) #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(m_workingDataDir) class LogSink: public qbs::ILogSink { public: QString output; void doPrintWarning(const qbs::ErrorInfo &error) { qDebug("%s", qPrintable(error.toString())); warnings.push_back(error); } void doPrintMessage(qbs::LoggerLevel, const QString &message, const QString &) { output += message; } QList warnings; }; class BuildDescriptionReceiver : public QObject { Q_OBJECT public: QString descriptions; QStringList descriptionLines; void handleDescription(const QString &, const QString &description) { descriptions += description; descriptionLines << description; } }; class ProcessResultReceiver : public QObject { Q_OBJECT public: QString output; std::vector results; void handleProcessResult(const qbs::ProcessResult &result) { results.push_back(result); output += result.stdErr().join(QLatin1Char('\n')); output += result.stdOut().join(QLatin1Char('\n')); } }; class TaskReceiver : public QObject { Q_OBJECT public: QString taskDescriptions; void handleTaskStart(const QString &task) { taskDescriptions += task; } }; static void removeBuildDir(const qbs::SetupProjectParameters ¶ms) { QString message; const QString dir = params.buildRoot() + '/' + params.configurationName(); if (!qbs::Internal::removeDirectoryWithContents(dir, &message)) qFatal("Could not remove build dir: %s", qPrintable(message)); } static bool waitForFinished(qbs::AbstractJob *job, int timeout = 0) { if (job->state() == qbs::AbstractJob::StateFinished) return true; QEventLoop loop; QObject::connect(job, &qbs::AbstractJob::finished, &loop, &QEventLoop::quit); if (timeout > 0) { QTimer timer; QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit); timer.setSingleShot(true); timer.start(timeout); loop.exec(); return timer.isActive(); // Timer ended the loop <=> job did not finish. } loop.exec(); return true; } TestApi::TestApi() : m_logSink(new LogSink) , m_sourceDataDir(QDir::cleanPath(SRCDIR "/testdata")) , m_workingDataDir(testWorkDir(QStringLiteral("api"))) { } TestApi::~TestApi() { delete m_logSink; } void TestApi::initTestCase() { QString errorMessage; qbs::Internal::removeDirectoryWithContents(m_workingDataDir, &errorMessage); QVERIFY2(qbs::Internal::copyFileRecursion(m_sourceDataDir, m_workingDataDir, false, true, &errorMessage), qPrintable(errorMessage)); QVERIFY(copyDllExportHeader(m_sourceDataDir, m_workingDataDir)); } void TestApi::init() { m_logSink->warnings.clear(); m_logSink->setLogLevel(qbs::LoggerInfo); } void TestApi::addQObjectMacroToCppFile() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("add-qobject-macro-to-cpp-file", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!receiver.descriptions.contains("moc"), qPrintable(receiver.descriptions)); receiver.descriptions.clear(); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("object.cpp", "// ", ""); errorInfo = doBuildProject("add-qobject-macro-to-cpp-file", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("moc"), qPrintable(receiver.descriptions)); } static bool isAboutUndefinedSymbols(const QString &_message) { const QString message = _message.toLower(); return message.contains("undefined") || message.contains("unresolved"); } void TestApi::addedFilePersistent() { // On the initial run, linking will fail. const QString relProjectFilePath = "added-file-persistent"; ProcessResultReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject(relProjectFilePath, 0, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable((receiver.output))); receiver.output.clear(); // Add a file. qbs must schedule it for rule application on the next build. WAIT_FOR_NEW_TIMESTAMP(); const qbs::SetupProjectParameters params = defaultSetupParameters(relProjectFilePath); REPLACE_IN_FILE(params.projectFilePath(), "/* 'file.cpp' */", "'file.cpp'"); std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); setupJob.reset(nullptr); // Remove the file again. qbs must unschedule the rule application again. // Consequently, the linking step must fail as in the initial run. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(params.projectFilePath(), "'file.cpp'", "/* 'file.cpp' */"); errorInfo = doBuildProject(relProjectFilePath, 0, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable((receiver.output))); // Add the file again. qbs must schedule it for rule application on the next build. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(params.projectFilePath(), "/* 'file.cpp' */", "'file.cpp'"); setupJob.reset(qbs::Project().setupProject(params, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); setupJob.reset(nullptr); // qbs must remember that a file was scheduled for rule application. The build must then // succeed, as now all necessary symbols are linked in. errorInfo = doBuildProject(relProjectFilePath); VERIFY_NO_ERROR(errorInfo); } void TestApi::baseProperties() { const qbs::ErrorInfo errorInfo = doBuildProject("base-properties/prj.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::buildGraphInfo() { SettingsPtr s = settings(); qbs::Internal::TemporaryProfile p("bgInfoProfile", s.get()); p.p.setValue("qbs.targetPlatform", "xenix"); qbs::SetupProjectParameters setupParams = defaultSetupParameters("buildgraph-info"); setupParams.setTopLevelProfile(p.p.name()); setupParams.setOverriddenValues({std::make_pair("qbs.architecture", "arm")}); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const QString bgFilePath = setupParams.buildRoot() + QLatin1Char('/') + relativeBuildGraphFilePath(); QVERIFY2(QFileInfo::exists(bgFilePath), qPrintable(bgFilePath)); qbs::Project::BuildGraphInfo bgInfo = qbs::Project::getBuildGraphInfo(bgFilePath, QStringList()); QVERIFY(bgInfo.error.hasError()); // Build graph is still locked. setupJob.reset(nullptr); const QStringList requestedProperties({"qbs.architecture", "qbs.shellPath", "qbs.targetPlatform"}); bgInfo = qbs::Project::getBuildGraphInfo(bgFilePath, requestedProperties); QVERIFY2(!bgInfo.error.hasError(), qPrintable(bgInfo.error.toString())); QCOMPARE(bgFilePath, bgInfo.bgFilePath); QCOMPARE(bgInfo.profileData.size(), 1); QCOMPARE(bgInfo.profileData.value(p.p.name()).toMap().size(), 1); QCOMPARE(bgInfo.profileData.value(p.p.name()).toMap().value("qbs").toMap().value( "targetPlatform"), p.p.value("qbs.targetPlatform")); QCOMPARE(bgInfo.overriddenProperties, setupParams.overriddenValues()); QCOMPARE(bgInfo.requestedProperties.size(), requestedProperties.size()); QCOMPARE(bgInfo.requestedProperties.value("qbs.architecture").toString(), QString("arm")); QCOMPARE(bgInfo.requestedProperties.value("qbs.shellPath").toString(), QString("/bin/bash")); QCOMPARE(bgInfo.requestedProperties.value("qbs.targetPlatform").toString(), QString("xenix")); } void TestApi::buildErrorCodeLocation() { const qbs::ErrorInfo errorInfo = doBuildProject("build-error-code-location/build-error-code-location.qbs"); QVERIFY(errorInfo.hasError()); const qbs::ErrorItem errorItem = errorInfo.items().front(); QCOMPARE(errorItem.description(), QString("Rule.outputArtifacts must return an array of objects.")); const qbs::CodeLocation errorLoc = errorItem.codeLocation(); QCOMPARE(QFileInfo(errorLoc.filePath()).fileName(), QString("build-error-code-location.qbs")); QCOMPARE(errorLoc.line(), 7); QCOMPARE(errorLoc.column(), 26); } void TestApi::buildGraphLocking() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("buildgraph-locking"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const qbs::Project project = setupJob->project(); Q_UNUSED(project); // Case 1: Setting up a competing project from scratch. setupJob.reset(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY2(setupJob->error().toString().contains("lock"), qPrintable(setupJob->error().toString())); // Case 2: Setting up a non-competing project and then making it competing. qbs::SetupProjectParameters setupParams2 = setupParams; setupParams2.setBuildRoot(setupParams.buildRoot() + "/2"); setupJob.reset(qbs::Project().setupProject(setupParams2, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const QString buildDirName = relativeBuildDir(setupParams2.configurationName()); const QString lockFile = setupParams2.buildRoot() + '/' + buildDirName + '/' + buildDirName + ".bg.lock"; QVERIFY2(QFileInfo(lockFile).isFile(), qPrintable(lockFile)); qbs::Project project2 = setupJob->project(); QVERIFY(project2.isValid()); setupJob.reset(project2.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY2(setupJob->error().toString().contains("lock"), qPrintable(setupJob->error().toString())); QVERIFY2(QFileInfo(lockFile).isFile(), qPrintable(lockFile)); // Case 3: Changing the build directory of an existing project to something non-competing. qbs::SetupProjectParameters setupParams3 = setupParams2; setupParams3.setBuildRoot(setupParams.buildRoot() + "/3"); setupJob.reset(qbs::Project().setupProject(setupParams3, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); project2 = qbs::Project(); QVERIFY2(!QFileInfo(lockFile).exists(), qPrintable(lockFile)); const QString newLockFile = setupParams3.buildRoot() + '/' + buildDirName + '/' + buildDirName + ".bg.lock"; QVERIFY2(QFileInfo(newLockFile).isFile(), qPrintable(newLockFile)); qbs::Project project3 = setupJob->project(); QVERIFY(project3.isValid()); // Case 4: Changing the build directory again, but cancelling the job. setupJob.reset(project3.setupProject(setupParams2, m_logSink, 0)); QThread::sleep(1); setupJob->cancel(); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY2(!QFileInfo(lockFile).exists(), qPrintable(lockFile)); QVERIFY2(QFileInfo(newLockFile).isFile(), qPrintable(newLockFile)); setupJob.reset(nullptr); project3 = qbs::Project(); QVERIFY2(!QFileInfo(newLockFile).exists(), qPrintable(newLockFile)); } void TestApi::buildProject() { QFETCH(QString, projectSubDir); QFETCH(QString, productFileName); const QString projectFilePath = projectSubDir + QLatin1Char('/') + projectSubDir + QLatin1String(".qbs"); qbs::SetupProjectParameters params = defaultSetupParameters(projectFilePath); removeBuildDir(params); qbs::ErrorInfo errorInfo = doBuildProject(projectFilePath); VERIFY_NO_ERROR(errorInfo); QVERIFY(regularFileExists(relativeBuildGraphFilePath())); if (!productFileName.isEmpty()) { QVERIFY2(regularFileExists(productFileName), qPrintable(productFileName)); QVERIFY2(QFile::remove(productFileName), qPrintable(productFileName)); } WAIT_FOR_NEW_TIMESTAMP(); qbs::BuildOptions options; options.setForceTimestampCheck(true); errorInfo = doBuildProject(projectFilePath, 0, 0, 0, options); VERIFY_NO_ERROR(errorInfo); if (!productFileName.isEmpty()) QVERIFY2(regularFileExists(productFileName), qPrintable(productFileName)); QVERIFY(regularFileExists(relativeBuildGraphFilePath())); } void TestApi::buildProject_data() { QTest::addColumn("projectSubDir"); QTest::addColumn("productFileName"); QTest::newRow("BPs in Sources") << QString("build-properties-source") << relativeExecutableFilePath("HelloWorld"); QTest::newRow("code generator") << QString("codegen") << relativeExecutableFilePath("codegen"); QTest::newRow("link static libs") << QString("link-static-lib") << relativeExecutableFilePath("HelloWorld"); QTest::newRow("link staticlib dynamiclib") << QString("link-staticlib-dynamiclib") << relativeExecutableFilePath("app"); QTest::newRow("precompiled header new") << QString("precompiled-header-new") << relativeExecutableFilePath("MyApp"); QTest::newRow("precompiled header dynamic") << QString("precompiled-header-dynamic") << relativeExecutableFilePath("MyApp"); QTest::newRow("lots of dots") << QString("lots-of-dots") << relativeExecutableFilePath("lots.of.dots"); QTest::newRow("Qt5 plugin") << QString("qt5-plugin") << relativeProductBuildDir("echoplugin") + '/' + qbs::Internal::HostOsInfo::dynamicLibraryName("echoplugin"); QTest::newRow("Q_OBJECT in source") << QString("moc-cpp") << relativeExecutableFilePath("moc_cpp"); QTest::newRow("Q_OBJECT in header") << QString("moc-hpp") << relativeExecutableFilePath("moc_hpp"); QTest::newRow("Q_OBJECT in header, moc_XXX.cpp included") << QString("moc-hpp-included") << relativeExecutableFilePath("moc_hpp_included"); QTest::newRow("app and lib with same source file") << QString("lib-same-source") << relativeExecutableFilePath("HelloWorldApp"); QTest::newRow("source files with the same base name but different extensions") << QString("same-base-name") << relativeExecutableFilePath("basename"); QTest::newRow("static library dependencies") << QString("static-lib-deps") << relativeExecutableFilePath("staticLibDeps"); QTest::newRow("simple probes") << QString("simple-probe") << relativeExecutableFilePath("MyApp"); QTest::newRow("application without sources") << QString("app-without-sources") << relativeExecutableFilePath("appWithoutSources"); QTest::newRow("productNameWithDots") << QString("productNameWithDots") << relativeExecutableFilePath("myapp"); QTest::newRow("only default properties") << QString("two-default-property-values") << relativeProductBuildDir("two-default-property-values") + "/set"; QTest::newRow("Export item with Group") << QString("export-item-with-group") << relativeExecutableFilePath("app"); QTest::newRow("QBS-728") << QString("QBS-728") << QString(); } void TestApi::buildProjectDryRun() { QFETCH(QString, projectSubDir); QFETCH(QString, productFileName); const QString projectFilePath = projectSubDir + QLatin1Char('/') + projectSubDir + QLatin1String(".qbs"); qbs::SetupProjectParameters params = defaultSetupParameters(projectFilePath); removeBuildDir(params); qbs::BuildOptions options; options.setDryRun(true); const qbs::ErrorInfo errorInfo = doBuildProject(projectFilePath, 0, 0, 0, options); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!QFileInfo::exists(relativeBuildDir()), qPrintable(QDir(relativeBuildDir()) .entryList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::System).join(", "))); } void TestApi::buildProjectDryRun_data() { return buildProject_data(); } void TestApi::buildSingleFile() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("build-single-file"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); qbs::BuildOptions options; options.setFilesToConsider(QStringList(setupParams.buildRoot() + "/compiled.cpp")); options.setActiveFileTags(QStringList("obj")); m_logSink->setLogLevel(qbs::LoggerMaxLevel); std::unique_ptr buildJob(project.buildAllProducts(options)); BuildDescriptionReceiver receiver; connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription, &receiver, &BuildDescriptionReceiver::handleDescription); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QCOMPARE(receiver.descriptions.count("compiling"), 2); QCOMPARE(receiver.descriptions.count("precompiling"), 1); QVERIFY2(receiver.descriptions.contains("generating generated.h"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling compiled.cpp"), qPrintable(receiver.descriptions)); } void TestApi::canonicalToolchainList() { // All the known toolchain lists should be equal QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode", "clang", "llvm", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang", "llvm", "gcc"})), QStringList({"clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm", "gcc"})), QStringList({"llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"mingw", "gcc"})), QStringList({"mingw", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc"})), QStringList({"gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"msvc"})), QStringList({"msvc"})); // Single names should canonicalize to the known lists QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang"})), QStringList({"clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm"})), QStringList({"llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"mingw"})), QStringList({"mingw", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc"})), QStringList({"gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"msvc"})), QStringList({"msvc"})); // Missing some in the middle QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode", "llvm", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode", "clang", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang", "llvm"})), QStringList({"clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang", "gcc"})), QStringList({"clang", "llvm", "gcc"})); // Sorted wrong, missing some in the middle QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "llvm", "clang", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang", "gcc", "llvm", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm", "clang", "xcode", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "llvm", "clang"})), QStringList({"clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "clang", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "llvm"})), QStringList({"llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "mingw"})), QStringList({"mingw", "gcc"})); // Duplicates QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "llvm", "clang", "xcode", "xcode", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"clang", "gcc", "llvm", "clang", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm", "clang", "clang", "xcode", "xcode", "gcc"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm", "clang", "gcc", "llvm", "clang"})), QStringList({"clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"xcode", "gcc", "clang", "gcc", "clang", "xcode"})), QStringList({"xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm", "gcc", "llvm", "llvm"})), QStringList({"llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain(QStringList({"gcc", "gcc", "gcc", "mingw"})), QStringList({"mingw", "gcc"})); // Custom insanity QCOMPARE(qbs::canonicalToolchain( QStringList({"crazy", "gcc", "llvm", "clang", "xcode", "insane"})), QStringList({"crazy", "insane", "xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain( QStringList({"crazy", "gcc", "llvm", "clang", "xcode", "insane", "crazy"})), QStringList({"crazy", "insane", "xcode", "clang", "llvm", "gcc"})); QCOMPARE(qbs::canonicalToolchain( QStringList({"crazy", "insane", "gcc", "trade", "llvm", "clang", "xcode", "insane", "mark", "crazy"})), QStringList({"crazy", "insane", "trade", "mark", "xcode", "clang", "llvm", "gcc"})); } void TestApi::checkOutputs() { QFETCH(bool, check); qbs::SetupProjectParameters params = defaultSetupParameters("/check-outputs"); qbs::BuildOptions options; options.setForceOutputCheck(check); removeBuildDir(params); qbs::ErrorInfo errorInfo = doBuildProject("/check-outputs", 0, 0, 0, options); if (check) QVERIFY(errorInfo.hasError()); else VERIFY_NO_ERROR(errorInfo); } void TestApi::checkOutputs_data() { QTest::addColumn("check"); QTest::newRow("checked outputs") << true; QTest::newRow("unchecked outputs") << false; } qbs::GroupData findGroup(const qbs::ProductData &product, const QString &name) { const auto groups = product.groups(); for (const qbs::GroupData &g : groups) { if (g.name() == name) return g; } return qbs::GroupData(); } #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES static qbs::Project::ProductSelection defaultProducts() { return qbs::Project::ProductSelectionDefaultOnly; } static void printProjectData(const qbs::ProjectData &project) { const auto products = project.products(); for (const qbs::ProductData &p : products) { qDebug(" Product '%s' at %s", qPrintable(p.name()), qPrintable(p.location().toString())); const auto groups = p.groups(); for (const qbs::GroupData &g : groups) { qDebug(" Group '%s' at %s", qPrintable(g.name()), qPrintable(g.location().toString())); qDebug(" Files: %s", qPrintable(g.allFilePaths().join(QLatin1String(", ")))); } } } void TestApi::changeContent() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-editing"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::Project project = job->project(); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); qbs::ProductData product = projectData.allProducts().front(); QVERIFY(product.groups().size() >= 8); // Error handling: Invalid product. qbs::ErrorInfo errorInfo = project.addGroup(qbs::ProductData(), "blubb"); QVERIFY(errorInfo.hasError()); QVERIFY(errorInfo.toString().contains("invalid")); // Error handling: Empty group name. errorInfo = project.addGroup(product, QString()); QVERIFY(errorInfo.hasError()); QVERIFY(errorInfo.toString().contains("empty")); errorInfo = project.addGroup(product, "New Group 1"); VERIFY_NO_ERROR(errorInfo); errorInfo = project.addGroup(product, "New Group 2"); VERIFY_NO_ERROR(errorInfo); // Error handling: Group already inserted. errorInfo = project.addGroup(product, "New Group 1"); QVERIFY(errorInfo.hasError()); QVERIFY(errorInfo.toString().contains("already")); // Error handling: Add list of files with double entries. errorInfo = project.addFiles(product, qbs::GroupData(), QStringList() << "file.cpp" << "file.cpp"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("more than once"), qPrintable(errorInfo.toString())); // Add files to empty array literal. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); QVERIFY(product.groups().size() >= 10); qbs::GroupData group = findGroup(product, "New Group 1"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "file.h" << "file.cpp"); VERIFY_NO_ERROR(errorInfo); // Error handling: Add the same file again. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); QVERIFY(product.groups().size() >= 10); group = findGroup(product, "New Group 1"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "file.cpp"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("already"), qPrintable(errorInfo.toString())); // Remove one of the newly added files again. errorInfo = project.removeFiles(product, group, QStringList("file.h")); VERIFY_NO_ERROR(errorInfo); // Error handling: Try to remove the same file again. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); QVERIFY(product.groups().size() >= 10); group = findGroup(product, "New Group 1"); QVERIFY(group.isValid()); errorInfo = project.removeFiles(product, group, QStringList() << "file.h"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("not known"), qPrintable(errorInfo.toString())); // Error handling: Try to remove a file from a complex list. group = findGroup(product, "Existing Group 2"); QVERIFY(group.isValid()); errorInfo = project.removeFiles(product, group, QStringList() << "existingfile2.txt"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("complex"), qPrintable(errorInfo.toString())); // Remove file from product's 'files' binding. errorInfo = project.removeFiles(product, qbs::GroupData(), QStringList("main.cpp")); VERIFY_NO_ERROR(errorInfo); // Add file to non-empty array literal. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); group = findGroup(product, "Existing Group 1"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile1.txt"); VERIFY_NO_ERROR(errorInfo); // Add files to list represented as a single string. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); errorInfo = project.addFiles(product, qbs::GroupData(), QStringList() << "newfile2.txt"); VERIFY_NO_ERROR(errorInfo); // Add files to list represented as an identifier. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); group = findGroup(product, "Existing Group 2"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile3.txt"); VERIFY_NO_ERROR(errorInfo); // Add files to list represented as a block of code (not yet implemented). projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); group = findGroup(product, "Existing Group 3"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile4.txt"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("complex"), qPrintable(errorInfo.toString())); // Add file to group with directory prefix. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); group = findGroup(product, "Existing Group 4"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "file.txt"); VERIFY_NO_ERROR(errorInfo); // Error handling: Add file to group with non-directory prefix. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); group = findGroup(product, "Existing Group 5"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile1.txt"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("prefix"), qPrintable(errorInfo.toString())); // Remove group. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); group = findGroup(product, "Existing Group 5"); QVERIFY(group.isValid()); errorInfo = project.removeGroup(product, group); VERIFY_NO_ERROR(errorInfo); projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); QVERIFY(projectData.products().front().groups().size() >= 9); // Error handling: Try to remove the same group again. errorInfo = project.removeGroup(product, group); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("does not exist"), qPrintable(errorInfo.toString())); // Add a file to a group where the file name is already matched by a wildcard. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); group = findGroup(product, "Group with wildcards"); QVERIFY(group.isValid()); QFile newFile("koerper.klaus"); QVERIFY2(newFile.open(QIODevice::WriteOnly), qPrintable(newFile.errorString())); newFile.close(); errorInfo = project.addFiles(product, group, QStringList() << newFile.fileName()); VERIFY_NO_ERROR(errorInfo); projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); group = findGroup(product, "Group with wildcards"); QVERIFY(group.isValid()); QCOMPARE(group.sourceArtifactsFromWildcards().size(), 1); QCOMPARE(group.sourceArtifactsFromWildcards().front().filePath(), QFileInfo(newFile).absoluteFilePath()); // Error checking: Try to remove a file that originates from a wildcard pattern. projectData = project.projectData(); QVERIFY(projectData.products().size() == 1); product = projectData.products().front(); group = findGroup(product, "Other group with wildcards"); QVERIFY(group.isValid()); errorInfo = project.removeFiles(product, group, QStringList() << "test.wildcard"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("pattern"), qPrintable(errorInfo.toString())); // Check whether building will take the added and removed cpp files into account. // This must not be moved below the re-resolving test!!! qbs::BuildOptions buildOptions; buildOptions.setDryRun(true); BuildDescriptionReceiver rcvr; std::unique_ptr buildJob(project.buildAllProducts(buildOptions, defaultProducts(), this)); connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription, &rcvr, &BuildDescriptionReceiver::handleDescription); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QVERIFY(rcvr.descriptions.contains("compiling file.cpp")); QVERIFY(!rcvr.descriptions.contains("compiling main.cpp")); // Now check whether the data updates were done correctly. projectData = project.projectData(); job.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project(); qbs::ProjectData newProjectData = project.projectData(); // Can't use Project::operator== here, as the target artifacts will differ due to the build // not having run yet. bool projectDataMatches = newProjectData.products().size() == 1 && projectData.products().size() == 1 && newProjectData.products().front().groups() == projectData.products().front().groups(); if (!projectDataMatches) { qDebug("This is the assumed project:"); printProjectData(projectData); qDebug("This is the actual project:"); printProjectData(newProjectData); } QVERIFY(projectDataMatches); // Will fail if e.g. code locations don't match. // Now try building again and check if the newly resolved product behaves the same way. buildJob.reset(project.buildAllProducts(buildOptions, defaultProducts(), this)); connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription, &rcvr, &BuildDescriptionReceiver::handleDescription); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QVERIFY(rcvr.descriptions.contains("compiling file.cpp")); QVERIFY(!rcvr.descriptions.contains("compiling main.cpp")); // Now, after the build, the project data must be entirely identical. QVERIFY(projectData == project.projectData()); // Error handling: Try to change the project during a build. buildJob.reset(project.buildAllProducts(buildOptions, defaultProducts(), this)); errorInfo = project.addGroup(newProjectData.products().front(), "blubb"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("in process"), qPrintable(errorInfo.toString())); waitForFinished(buildJob.get()); errorInfo = project.addGroup(newProjectData.products().front(), "blubb"); VERIFY_NO_ERROR(errorInfo); project = qbs::Project(); job.reset(nullptr); buildJob.reset(nullptr); removeBuildDir(setupParams); // Add a file to the top level of a product that does not have a "files" binding yet. setupParams.setProjectFilePath(QDir::cleanPath(m_workingDataDir + "/project-editing/project-with-no-files.qbs")); job.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project(); projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); product = projectData.allProducts().front(); errorInfo = project.addFiles(product, qbs::GroupData(), QStringList("main.cpp")); VERIFY_NO_ERROR(errorInfo); projectData = project.projectData(); rcvr.descriptions.clear(); buildJob.reset(project.buildAllProducts(buildOptions, defaultProducts(), this)); connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription, &rcvr, &BuildDescriptionReceiver::handleDescription); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QVERIFY(rcvr.descriptions.contains("compiling main.cpp")); job.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); // Can't use Project::operator== here, as the target artifacts will differ due to the build // not having run yet. newProjectData = job->project().projectData(); projectDataMatches = newProjectData.products().size() == 1 && projectData.products().size() == 1 && newProjectData.products().front().groups() == projectData.products().front().groups(); if (!projectDataMatches) { printProjectData(projectData); qDebug("\n====\n"); printProjectData(newProjectData); } QVERIFY(projectDataMatches); } #endif // QBS_ENABLE_PROJECT_FILE_UPDATES void TestApi::commandExtraction() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("/command-extraction"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); qbs::ProductData productData = projectData.allProducts().front(); qbs::ErrorInfo errorInfo; const QString projectDirPath = QDir::cleanPath(QFileInfo(setupParams.projectFilePath()).path()); const QString sourceFilePath = projectDirPath + "/main.cpp"; // Before the first build, no rules exist. qbs::RuleCommandList commands = project.ruleCommands(productData, sourceFilePath, "obj", &errorInfo); QCOMPARE(commands.size(), 0); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("No rule"), qPrintable(errorInfo.toString())); qbs::BuildOptions options; options.setDryRun(true); std::unique_ptr buildJob(project.buildAllProducts(options)); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); productData = projectData.allProducts().front(); errorInfo = qbs::ErrorInfo(); // After the build, the compile command must be found. commands = project.ruleCommands(productData, sourceFilePath, "obj", &errorInfo); QCOMPARE(commands.size(), 1); QVERIFY2(!errorInfo.hasError(), qPrintable(errorInfo.toString())); const qbs::RuleCommand command = commands.front(); QCOMPARE(command.type(), qbs::RuleCommand::ProcessCommandType); QVERIFY(!command.executable().isEmpty()); QVERIFY(!command.arguments().empty()); } void TestApi::dependencyOnMultiplexedType() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("/dependency-on-multiplexed-type"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); qbs::ProjectData projectData = project.projectData(); const QList allProducts = projectData.allProducts(); QCOMPARE(allProducts.size(), 5); int depCount = 0; int p1Count = 0; int p2Count = 0; for (const qbs::ProductData &p : allProducts) { if (p.name() == "dep") { ++depCount; QCOMPARE(p.dependencies().size(), 0); } else if (p.name() == "p1") { ++p1Count; if (p.multiplexConfigurationId().isEmpty()) // aggregate QCOMPARE(p.dependencies().size(), 3); else QCOMPARE(p.dependencies().size(), 1); } else { QVERIFY(p.name() == "p2"); ++p2Count; // FIXME: This is an odd effect of our current algorithm: We collect the products // matching the requested type and add Depends items with their names ("p1" in // this case). Later, the algorithm checking for compatibility regarding the // multiplexing axes picks the aggregate. However, the aggregate does not have // a matching type... It's not entirely clear what the real expected // result should be here. QCOMPARE(p.dependencies().size(), 2); } } std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); } void TestApi::changeDependentLib() { qbs::ErrorInfo errorInfo = doBuildProject("change-dependent-lib"); VERIFY_NO_ERROR(errorInfo); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("change-dependent-lib.qbs", "cpp.defines: [\"XXXX\"]", "cpp.defines: [\"ABCD\"]"); errorInfo = doBuildProject("change-dependent-lib"); VERIFY_NO_ERROR(errorInfo); } void TestApi::enableAndDisableProduct() { BuildDescriptionReceiver bdr; qbs::ErrorInfo errorInfo = doBuildProject("enable-and-disable-product", &bdr); VERIFY_NO_ERROR(errorInfo); QVERIFY(!bdr.descriptions.contains("compiling")); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile("enable-and-disable-product.qbs"); QVERIFY(projectFile.open(QIODevice::ReadWrite)); QByteArray content = projectFile.readAll(); content.replace("undefined", "'hidden'"); projectFile.resize(0); projectFile.write(content); projectFile.close(); bdr.descriptions.clear(); errorInfo = doBuildProject("enable-and-disable-product", &bdr); VERIFY_NO_ERROR(errorInfo); QVERIFY(bdr.descriptions.contains("linking")); WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QVERIFY(projectFile.open(QIODevice::ReadWrite)); content = projectFile.readAll(); content.replace("'hidden'", "undefined"); projectFile.resize(0); projectFile.write(content); projectFile.close(); bdr.descriptions.clear(); errorInfo = doBuildProject("enable-and-disable-product", &bdr); VERIFY_NO_ERROR(errorInfo); QVERIFY(!bdr.descriptions.contains("compiling")); } void TestApi::errorInSetupRunEnvironment() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("error-in-setup-run-environment"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::Project project = job->project(); QVERIFY(project.isValid()); QCOMPARE(project.projectData().products().size(), 1); const qbs::ProductData product = project.projectData().products().front(); bool exceptionCaught = false; try { const SettingsPtr s = settings(); qbs::RunEnvironment runEnv = project.getRunEnvironment(product, qbs::InstallOptions(), QProcessEnvironment(), QStringList(), s.get()); qbs::ErrorInfo error; const QProcessEnvironment env = runEnv.runEnvironment(&error); QVERIFY(error.hasError()); QVERIFY(error.toString().contains("trallala")); } catch (const qbs::ErrorInfo &) { exceptionCaught = true; } QVERIFY(!exceptionCaught); } void TestApi::excludedInputs() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("excluded-inputs"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::Project project = job->project(); std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(job->error().toString())); QVERIFY(project.isValid()); QCOMPARE(project.projectData().products().size(), 2); qbs::ProductData depProduct; qbs::ProductData pProduct; for (qbs::ProductData &p : project.projectData().products()) { if (p.name() == "dep") depProduct = p; else if (p.name() == "p") pProduct = p; } QVERIFY(depProduct.isValid()); QVERIFY(pProduct.isValid()); int theTagCount = 0; for (const qbs::ArtifactData &artifact : depProduct.targetArtifacts()) { if (!artifact.fileTags().contains("the_tag")) continue; ++theTagCount; QFile f(artifact.filePath()); QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString())); const QByteArray content = f.readAll(); QVERIFY2(content.contains("the_content"), content.constData()); QCOMPARE(artifact.fileTags().contains("the_other_tag"), content.contains("the_other_content")); } QCOMPARE(theTagCount, 2); int dummyCount = 0; for (const qbs::ArtifactData &artifact : pProduct.targetArtifacts()) { QFileInfo fi(artifact.filePath()); QVERIFY2(fi.exists(), qPrintable(fi.filePath())); if (fi.fileName().startsWith("dummy")) ++dummyCount; } QCOMPARE(dummyCount, 3); } static qbs::ErrorInfo forceRuleEvaluation(const qbs::Project project) { qbs::BuildOptions buildOptions; buildOptions.setDryRun(true); std::unique_ptr buildJob(project.buildAllProducts(buildOptions)); waitForFinished(buildJob.get()); return buildJob->error(); } void TestApi::disabledInstallGroup() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("disabled_install_group"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::Project project = job->project(); const qbs::ErrorInfo errorInfo = forceRuleEvaluation(project); VERIFY_NO_ERROR(errorInfo); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); qbs::ProductData product = projectData.allProducts().front(); const QList targets = product.targetArtifacts(); QCOMPARE(targets.size(), 1); QVERIFY(targets.front().isGenerated()); QVERIFY(targets.front().isExecutable()); QVERIFY(targets.front().isTargetArtifact()); QCOMPARE(projectData.installableArtifacts().size(), 0); QCOMPARE(product.targetExecutable(), targets.front().filePath()); } void TestApi::disabledProduct() { const qbs::ErrorInfo errorInfo = doBuildProject("disabled-product"); VERIFY_NO_ERROR(errorInfo); } void TestApi::disabledProject() { const qbs::ErrorInfo errorInfo = doBuildProject("disabled-project"); VERIFY_NO_ERROR(errorInfo); } void TestApi::duplicateProductNames() { QFETCH(QString, projectFileName); const qbs::ErrorInfo errorInfo = doBuildProject("duplicate-product-names/" + projectFileName); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Duplicate product name"), qPrintable(errorInfo.toString())); } void TestApi::duplicateProductNames_data() { QTest::addColumn("projectFileName"); QTest::newRow("Names explicitly set") << QString("explicit.qbs"); QTest::newRow("Unnamed products in same file") << QString("implicit.qbs"); QTest::newRow("Unnamed products in files of the same name") << QString("implicit-indirect.qbs"); } void TestApi::emptyFileTagList() { const qbs::ErrorInfo errorInfo = doBuildProject("empty-filetag-list"); VERIFY_NO_ERROR(errorInfo); } void TestApi::emptySubmodulesList() { const qbs::ErrorInfo errorInfo = doBuildProject("empty-submodules-list"); VERIFY_NO_ERROR(errorInfo); } void TestApi::explicitlyDependsOn() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("explicitly-depends-on", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("compiling compiler.cpp"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling a.in"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling b.in"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling c.in"), qPrintable(receiver.descriptions)); QFile txtFile(relativeProductBuildDir("p") + "/compiler-name.txt"); QVERIFY2(txtFile.open(QIODevice::ReadOnly), qPrintable(txtFile.errorString())); const QByteArray content = txtFile.readAll(); QCOMPARE(content, QByteArray("compiler file name: compiler")); receiver.descriptions.clear(); errorInfo = doBuildProject("explicitly-depends-on", &receiver); QVERIFY2(!receiver.descriptions.contains("compiling compiler.cpp"), qPrintable(receiver.descriptions)); QVERIFY2(!receiver.descriptions.contains("compiling a.in"), qPrintable(receiver.descriptions)); QVERIFY2(!receiver.descriptions.contains("compiling b.in"), qPrintable(receiver.descriptions)); QVERIFY2(!receiver.descriptions.contains("compiling c.in"), qPrintable(receiver.descriptions)); VERIFY_NO_ERROR(errorInfo); WAIT_FOR_NEW_TIMESTAMP(); touch("compiler.cpp"); waitForFileUnlock(); errorInfo = doBuildProject("explicitly-depends-on", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("compiling compiler.cpp"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling a.in"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling b.in"), qPrintable(receiver.descriptions)); QVERIFY2(receiver.descriptions.contains("compiling c.in"), qPrintable(receiver.descriptions)); } void TestApi::exportSimple() { const qbs::ErrorInfo errorInfo = doBuildProject("export-simple"); VERIFY_NO_ERROR(errorInfo); } void TestApi::exportWithRecursiveDepends() { const qbs::ErrorInfo errorInfo = doBuildProject("export-with-recursive-depends"); VERIFY_NO_ERROR(errorInfo); } void TestApi::fallbackGcc() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("fallback-gcc/fallback-gcc.qbs"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, nullptr)); waitForFinished(job.get()); VERIFY_NO_ERROR(job->error()); qbs::ProjectData project = job->project().projectData(); QVERIFY(project.isValid()); QList products = project.allProducts(); QCOMPARE(products.size(), 2); for (const qbs::ProductData &p : qAsConst(products)) { if (p.profile() == "unixProfile") { qbs::PropertyMap moduleProps = p.moduleProperties(); QCOMPARE(moduleProps.getModuleProperty("qbs", "targetOS").toStringList(), QStringList({"unix"})); QCOMPARE(moduleProps.getModuleProperty("qbs", "toolchain").toStringList(), QStringList({"gcc"})); QCOMPARE(QFileInfo(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString()) .completeBaseName(), QString("g++")); QCOMPARE(moduleProps.getModuleProperty("cpp", "dynamicLibrarySuffix").toString(), QString(".so")); } else { QCOMPARE(p.profile(), QString("gccProfile")); qbs::PropertyMap moduleProps = p.moduleProperties(); QCOMPARE(moduleProps.getModuleProperty("qbs", "targetOS").toStringList(), QStringList()); QCOMPARE(moduleProps.getModuleProperty("qbs", "toolchain").toStringList(), QStringList({"gcc"})); QCOMPARE(QFileInfo(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString()) .completeBaseName(), QString("g++")); QCOMPARE(moduleProps.getModuleProperty("cpp", "dynamicLibrarySuffix").toString(), QString()); } } } void TestApi::fileTagger() { BuildDescriptionReceiver receiver; const qbs::ErrorInfo errorInfo = doBuildProject("file-tagger/moc_cpp.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("moc bla.cpp"), qPrintable(receiver.descriptions)); } void TestApi::fileTagsFilterOverride() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("filetagsfilter_override"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::Project project = job->project(); const qbs::ErrorInfo errorInfo = forceRuleEvaluation(project); VERIFY_NO_ERROR(errorInfo); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); const qbs::ProductData product = projectData.allProducts().front(); QList installableFiles = product.installableArtifacts(); QCOMPARE(installableFiles.size(), 1); QVERIFY(installableFiles.front().installData().installFilePath().contains("habicht")); } void TestApi::generatedFilesList() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("generated-files-list"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); QVERIFY(waitForFinished(setupJob.get())); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); qbs::BuildOptions options; options.setExecuteRulesOnly(true); const std::unique_ptr buildJob(project.buildAllProducts(options)); QVERIFY(waitForFinished(buildJob.get())); VERIFY_NO_ERROR(buildJob->error()); const qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.products().size(), 1); const qbs::ProductData product = projectData.products().front(); QString uiFilePath; QVERIFY(product.generatedArtifacts().size() >= 6); const auto artifacts = product.generatedArtifacts(); for (const qbs::ArtifactData &a : artifacts) { QVERIFY(a.isGenerated()); QFileInfo fi(a.filePath()); using qbs::Internal::HostOsInfo; const QStringList possibleFileNames = QStringList() << "main.cpp.o" << "main.cpp.obj" << "mainwindow.cpp.o" << "mainwindow.cpp.obj" << "moc_mainwindow.cpp" << "moc_mainwindow.cpp.o" << "moc_mainwindow.cpp.obj" << "ui_mainwindow.h" << HostOsInfo::appendExecutableSuffix("generated-files-list"); QVERIFY2(possibleFileNames.contains(fi.fileName()) || fi.fileName().endsWith(".plist") || fi.fileName().contains("qt_plugin_import"), qPrintable(fi.fileName())); } const auto groups = product.groups(); for (const qbs::GroupData &group : groups) { const auto artifacts = group.sourceArtifacts(); for (const qbs::ArtifactData &a : artifacts) { QVERIFY(!a.isGenerated()); QVERIFY(!a.isTargetArtifact()); if (a.fileTags().contains(QLatin1String("ui"))) { uiFilePath = a.filePath(); break; } } if (!uiFilePath.isEmpty()) break; } QVERIFY(!uiFilePath.isEmpty()); const QStringList directParents = project.generatedFiles(product, uiFilePath, false); QCOMPARE(directParents.size(), 1); const QFileInfo uiHeaderFileInfo(directParents.front()); QCOMPARE(uiHeaderFileInfo.fileName(), QStringLiteral("ui_mainwindow.h")); QVERIFY(!uiHeaderFileInfo.exists()); const QStringList allParents = project.generatedFiles(product, uiFilePath, true); QCOMPARE(allParents.size(), 3); } void TestApi::infiniteLoopBuilding() { QFETCH(QString, projectDirName); qbs::SetupProjectParameters setupParams = defaultSetupParameters(projectDirName + "/infinite-loop.qbs"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); const std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); QTimer::singleShot(1000, buildJob.get(), &qbs::AbstractJob::cancel); QVERIFY(waitForFinished(buildJob.get(), testTimeoutInMsecs())); QVERIFY(buildJob->error().hasError()); } void TestApi::infiniteLoopBuilding_data() { QTest::addColumn("projectDirName"); QTest::newRow("JS Command") << QString("infinite-loop-js"); QTest::newRow("Process Command") << QString("infinite-loop-process"); } void TestApi::infiniteLoopResolving() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("infinite-loop-resolving"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); QTimer::singleShot(1000, setupJob.get(), &qbs::AbstractJob::cancel); QVERIFY(waitForFinished(setupJob.get(), testTimeoutInMsecs())); QVERIFY2(setupJob->error().toString().toLower().contains("cancel"), qPrintable(setupJob->error().toString())); } void TestApi::inheritQbsSearchPaths() { const QString projectFilePath = "inherit-qbs-search-paths/prj.qbs"; qbs::ErrorInfo errorInfo = doBuildProject(projectFilePath); VERIFY_NO_ERROR(errorInfo); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile(m_workingDataDir + '/' + projectFilePath); QVERIFY(projectFile.open(QIODevice::ReadWrite)); QByteArray content = projectFile.readAll(); content.replace("qbsSearchPaths: \"subdir\"", "//qbsSearchPaths: \"subdir\""); projectFile.resize(0); projectFile.write(content); projectFile.close(); errorInfo = doBuildProject(projectFilePath); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Dependency 'bli' not found"), qPrintable(errorInfo.toString())); QVariantMap overriddenValues; overriddenValues.insert("project.qbsSearchPaths", QStringList() << m_workingDataDir + "/inherit-qbs-search-paths/subdir"); errorInfo = doBuildProject(projectFilePath, 0, 0, 0, qbs::BuildOptions(), overriddenValues); VERIFY_NO_ERROR(errorInfo); } template typename T::value_type findElem(const T &list, Pred p) { const auto it = std::find_if(list.cbegin(), list.cend(), p); return it == list.cend() ? typename T::value_type() : *it; } void TestApi::installableFiles() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("installed-artifact"); QVariantMap overriddenValues; overriddenValues.insert(QStringLiteral("qbs.installRoot"), QStringLiteral("/tmp")); setupParams.setOverriddenValues(overriddenValues); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::Project project = job->project(); const qbs::ErrorInfo errorInfo = forceRuleEvaluation(project); VERIFY_NO_ERROR(errorInfo); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 2); qbs::ProductData product = findElem(projectData.allProducts(), [](const qbs::ProductData &p) { return p.name() == QLatin1String("installedApp"); }); QVERIFY(product.isValid()); const QList beforeInstallableFiles = product.installableArtifacts(); QCOMPARE(beforeInstallableFiles.size(), 3); for (const qbs::ArtifactData &f : beforeInstallableFiles) { if (!QFileInfo(f.filePath()).fileName().startsWith("main")) { QVERIFY(f.isExecutable()); QString expectedTargetFilePath = qbs::Internal::HostOsInfo ::appendExecutableSuffix(QStringLiteral("/tmp/usr/bin/installedApp")); QCOMPARE(f.installData().localInstallFilePath(), expectedTargetFilePath); QCOMPARE(product.targetExecutable(), expectedTargetFilePath); break; } } setupParams = defaultSetupParameters("recursive-wildcards"); setupParams.setOverriddenValues(overriddenValues); job.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project(); projectData = project.projectData(); QCOMPARE(projectData.allProducts().size(), 1); product = projectData.allProducts().front(); const QList afterInstallableFiles = product.installableArtifacts(); QCOMPARE(afterInstallableFiles.size(), 2); for (const qbs::ArtifactData &f : afterInstallableFiles) QVERIFY(!f.isExecutable()); QCOMPARE(afterInstallableFiles.front().installData().localInstallFilePath(), QLatin1String("/tmp/dir/file1.txt")); QCOMPARE(afterInstallableFiles.last().installData().localInstallFilePath(), QLatin1String("/tmp/dir/file2.txt")); } void TestApi::isRunnable() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("is-runnable"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::Project project = job->project(); const QList products = project.projectData().products(); QCOMPARE(products.size(), 2); for (const qbs::ProductData &p : products) { QVERIFY2(p.name() == "app" || p.name() == "lib", qPrintable(p.name())); if (p.name() == "app") QVERIFY(p.isRunnable()); else QVERIFY(!p.isRunnable()); } } void TestApi::linkDynamicLibs() { const qbs::ErrorInfo errorInfo = doBuildProject("link-dynamiclibs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::linkDynamicAndStaticLibs() { BuildDescriptionReceiver bdr; qbs::BuildOptions options; options.setEchoMode(qbs::CommandEchoModeCommandLine); const qbs::ErrorInfo errorInfo = doBuildProject("link-dynamiclibs-staticlibs", &bdr, nullptr, nullptr, options); VERIFY_NO_ERROR(errorInfo); // The dependent static libs should not appear in the link command for the executable. const SettingsPtr s = settings(); const qbs::Profile buildProfile(profileName(), s.get()); if (buildProfile.value("qbs.toolchain").toStringList().contains("gcc")) { static const std::regex appLinkCmdRex(" -o [^ ]*/HelloWorld" QBS_HOST_EXE_SUFFIX " "); QString appLinkCmd; for (const QString &line : qAsConst(bdr.descriptionLines)) { const auto ln = line.toStdString(); if (std::regex_search(ln, appLinkCmdRex)) { appLinkCmd = line; break; } } QVERIFY(!appLinkCmd.isEmpty()); QVERIFY(!appLinkCmd.contains("static1")); QVERIFY(!appLinkCmd.contains("static2")); } } void TestApi::linkStaticAndDynamicLibs() { BuildDescriptionReceiver bdr; qbs::BuildOptions options; options.setEchoMode(qbs::CommandEchoModeCommandLine); const qbs::ErrorInfo errorInfo = doBuildProject("link-staticlibs-dynamiclibs", &bdr, nullptr, nullptr, options); VERIFY_NO_ERROR(errorInfo); // The dependencies libdynamic1.so and libstatic2.a must not appear in the link command for the // executable. The -rpath-link line for libdynamic1.so must be there. const SettingsPtr s = settings(); const qbs::Profile buildProfile(profileName(), s.get()); if (buildProfile.value("qbs.toolchain").toStringList().contains("gcc")) { static const std::regex appLinkCmdRex(" -o [^ ]*/HelloWorld" QBS_HOST_EXE_SUFFIX " "); QString appLinkCmd; for (const QString &line : qAsConst(bdr.descriptionLines)) { const auto ln = line.toStdString(); if (std::regex_search(ln, appLinkCmdRex)) { appLinkCmd = line; break; } } QVERIFY(!appLinkCmd.isEmpty()); std::string targetPlatform = buildProfile.value("qbs.targetPlatform") .toString().toStdString(); std::vector targetOS = qbs::Internal::HostOsInfo::canonicalOSIdentifiers( targetPlatform); if (!qbs::Internal::contains(targetOS, "darwin") && !qbs::Internal::contains(targetOS, "windows")) { const std::regex rpathLinkRex("-rpath-link=\\S*/" + relativeProductBuildDir("dynamic2").toStdString()); const auto ln = appLinkCmd.toStdString(); QVERIFY(std::regex_search(ln, rpathLinkRex)); } QVERIFY(!appLinkCmd.contains("libstatic2.a")); QVERIFY(!appLinkCmd.contains("libdynamic2.so")); } } void TestApi::listBuildSystemFiles() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("subprojects/toplevelproject.qbs"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const auto buildSystemFiles = qbs::Internal::Set::fromStdSet( job->project().buildSystemFiles()); QVERIFY(buildSystemFiles.contains(setupParams.projectFilePath())); QVERIFY(buildSystemFiles.contains(setupParams.buildRoot() + "/subproject2/subproject2.qbs")); QVERIFY(buildSystemFiles.contains(setupParams.buildRoot() + "/subproject2/subproject3/subproject3.qbs")); } void TestApi::localProfiles() { QFETCH(bool, enableProfiles); qbs::SetupProjectParameters setupParams = defaultSetupParameters("local-profiles/local-profiles.qbs"); setupParams.setOverriddenValues( {std::make_pair(QString("project.enableProfiles"), enableProfiles)}); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); QString taskDescriptions; const auto taskDescHandler = [&taskDescriptions](const QString &desc, int, qbs::AbstractJob *) { taskDescriptions += '\n' + desc; }; connect(job.get(), &qbs::AbstractJob::taskStarted, taskDescHandler); waitForFinished(job.get()); const QString error = job->error().toString(); QVERIFY2(job->error().hasError() == !enableProfiles, qPrintable(error)); if (!enableProfiles) { QVERIFY2(error.contains("does not exist"), qPrintable(error)); return; } QVERIFY2(taskDescriptions.contains("Resolving"), qPrintable(taskDescriptions)); qbs::ProjectData project = job->project().projectData(); QList products = project.allProducts(); QCOMPARE(products.size(), 4); qbs::ProductData libMingw; qbs::ProductData libClang; qbs::ProductData appDebug; qbs::ProductData appRelease; for (const qbs::ProductData &p : qAsConst(products)) { if (p.name() == "lib") { if (p.profile() == "mingwProfile") libMingw = p; else if (p.profile() == "clangProfile") libClang = p; } else if (p.name() == "app") { const QString buildVariant = p.moduleProperties().getModuleProperty("qbs", "buildVariant").toString(); if (buildVariant == "debug") appDebug = p; else if (buildVariant == "release") appRelease = p; } } QVERIFY(libMingw.isValid()); QVERIFY((libClang.isValid())); QVERIFY(appDebug.isValid()); QVERIFY(appRelease.isValid()); QCOMPARE(appDebug.profile(), QLatin1String("mingwProfile")); QCOMPARE(appRelease.profile(), QLatin1String("mingwProfile")); qbs::PropertyMap moduleProps = libMingw.moduleProperties(); QCOMPARE(moduleProps.getModuleProperty("qbs", "targetOS").toStringList(), QStringList({"windows"})); QCOMPARE(moduleProps.getModuleProperty("qbs", "toolchain").toStringList(), QStringList({"mingw", "gcc"})); if (moduleProps.getModuleProperty("cpp", "present").toBool()) { QCOMPARE(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString(), QString("g++")); } moduleProps = libClang.moduleProperties(); QCOMPARE(moduleProps.getModuleProperty("qbs", "targetOS").toStringList(), QStringList({"linux", "unix"})); QCOMPARE(moduleProps.getModuleProperty("qbs", "toolchain").toStringList(), QStringList({"clang", "llvm", "gcc"})); if (moduleProps.getModuleProperty("cpp", "present").toBool()) { QCOMPARE(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString(), QString("clang++")); } moduleProps = appDebug.moduleProperties(); if (moduleProps.getModuleProperty("cpp", "present").toBool()) QCOMPARE(moduleProps.getModuleProperty("cpp", "optimization").toString(), QString("none")); moduleProps = appRelease.moduleProperties(); if (moduleProps.getModuleProperty("cpp", "present").toBool()) QCOMPARE(moduleProps.getModuleProperty("cpp", "optimization").toString(), QString("fast")); taskDescriptions.clear(); job.reset(qbs::Project().setupProject(setupParams, m_logSink, 0)); connect(job.get(), &qbs::AbstractJob::taskStarted, taskDescHandler); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); QVERIFY2(!taskDescriptions.contains("Resolving"), qPrintable(taskDescriptions)); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile(setupParams.projectFilePath()); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); QByteArray content = projectFile.readAll(); content.replace("\"clang\"", "\"gcc\""); projectFile.resize(0); projectFile.write(content); projectFile.close(); job.reset(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project().projectData(); products = project.allProducts(); QCOMPARE(products.size(), 4); int clangProfiles = 0; for (const qbs::ProductData &p : qAsConst(products)) { if (p.profile() == "clangProfile") { ++clangProfiles; moduleProps = p.moduleProperties(); if (moduleProps.getModuleProperty("cpp", "present").toBool()) { QCOMPARE(moduleProps.getModuleProperty("cpp", "cxxCompilerName").toString(), QString("g++")); } } } QCOMPARE(clangProfiles, 1); } void TestApi::localProfiles_data() { QTest::addColumn("enableProfiles"); QTest::newRow("profiles enabled") << true; QTest::newRow("profiles disabled") << false; } void TestApi::missingSourceFile() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("missing-source-file/missing-source-file.qbs"); setupParams.setProductErrorMode(qbs::ErrorHandlingMode::Relaxed); m_logSink->setLogLevel(qbs::LoggerMinLevel); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::ProjectData project = job->project().projectData(); QCOMPARE(project.allProducts().size(), 1); qbs::ProductData product = project.allProducts().front(); QCOMPARE(product.groups().size(), 1); qbs::GroupData group = product.groups().front(); QCOMPARE(group.allSourceArtifacts().size(), 2); QFile::rename("file2.txt.missing", "file2.txt"); job.reset(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project().projectData(); QCOMPARE(project.allProducts().size(), 1); product = project.allProducts().front(); QCOMPARE(product.groups().size(), 1); group = product.groups().front(); QCOMPARE(group.allSourceArtifacts().size(), 3); } void TestApi::mocCppIncluded() { // Initial build. qbs::ErrorInfo errorInfo = doBuildProject("moc-hpp-included"); VERIFY_NO_ERROR(errorInfo); // Touch header and try again. WAIT_FOR_NEW_TIMESTAMP(); QFile headerFile("object.h"); QVERIFY2(headerFile.open(QIODevice::WriteOnly | QIODevice::Append), qPrintable(headerFile.errorString())); headerFile.write("\n"); headerFile.close(); errorInfo = doBuildProject("moc-hpp-included"); VERIFY_NO_ERROR(errorInfo); // Touch cpp file and try again. WAIT_FOR_NEW_TIMESTAMP(); QFile cppFile("object.cpp"); QVERIFY2(cppFile.open(QIODevice::WriteOnly | QIODevice::Append), qPrintable(cppFile.errorString())); cppFile.write("\n"); cppFile.close(); errorInfo = doBuildProject("moc-hpp-included"); VERIFY_NO_ERROR(errorInfo); } void TestApi::multiArch() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("multi-arch"); const SettingsPtr s = settings(); qbs::Internal::TemporaryProfile tph("host", s.get()); qbs::Profile hostProfile = tph.p; hostProfile.setValue("qbs.architecture", "host-arch"); qbs::Internal::TemporaryProfile tpt("target", s.get()); qbs::Profile targetProfile = tpt.p; targetProfile.setValue("qbs.architecture", "target-arch"); QVariantMap overriddenValues; overriddenValues.insert("project.hostProfile", hostProfile.name()); overriddenValues.insert("project.targetProfile", targetProfile.name()); setupParams.setOverriddenValues(overriddenValues); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); QCOMPARE(project.profile(), profileName()); const QList &products = project.projectData().products(); QCOMPARE(products.size(), 3); QList hostProducts; QList targetProducts; for (const qbs::ProductData &p : products) { QVERIFY2(p.profile() == hostProfile.name() || p.profile() == targetProfile.name(), qPrintable(p.profile())); if (p.profile() == hostProfile.name()) hostProducts.push_back(p); else targetProducts.push_back(p); } QCOMPARE(hostProducts.size(), 2); QCOMPARE(targetProducts.size(), 1); QCOMPARE(targetProducts.front().name(), QLatin1String("p1")); QStringList hostProductNames = QStringList() << hostProducts.front().name() << hostProducts.last().name(); QCOMPARE(hostProductNames.count("p1"), 1); QCOMPARE(hostProductNames.count("p2"), 1); const QString p1HostMultiplexCfgId = hostProducts.at(0).multiplexConfigurationId(); const QString p2HostMultiplexCfgId = hostProducts.at(1).multiplexConfigurationId(); const QString p1TargetMultiplexCfgId = targetProducts.at(0).multiplexConfigurationId(); std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); const QString outputBaseDir = setupParams.buildRoot() + '/'; QFile p1HostArtifact(outputBaseDir + relativeProductBuildDir("p1", QString(), p1HostMultiplexCfgId) + "/host+target.output"); QVERIFY2(p1HostArtifact.exists(), qPrintable(p1HostArtifact.fileName())); QVERIFY2(p1HostArtifact.open(QIODevice::ReadOnly), qPrintable(p1HostArtifact.errorString())); QCOMPARE(p1HostArtifact.readAll().constData(), "host-arch"); QFile p1TargetArtifact(outputBaseDir + relativeProductBuildDir("p1", QString(), p1TargetMultiplexCfgId) + "/host+target.output"); QVERIFY2(p1TargetArtifact.exists(), qPrintable(p1TargetArtifact.fileName())); QVERIFY2(p1TargetArtifact.open(QIODevice::ReadOnly), qPrintable(p1TargetArtifact.errorString())); QCOMPARE(p1TargetArtifact.readAll().constData(), "target-arch"); QFile p2Artifact(outputBaseDir + relativeProductBuildDir("p2", QString(), p2HostMultiplexCfgId) + "/host-tool.output"); QVERIFY2(p2Artifact.exists(), qPrintable(p2Artifact.fileName())); QVERIFY2(p2Artifact.open(QIODevice::ReadOnly), qPrintable(p2Artifact.errorString())); QCOMPARE(p2Artifact.readAll().constData(), "host-arch"); const QString installRoot = outputBaseDir + relativeBuildDir() + '/' + qbs::InstallOptions::defaultInstallRoot(); std::unique_ptr installJob(project.installAllProducts(qbs::InstallOptions())); waitForFinished(installJob.get()); QVERIFY2(!installJob->error().hasError(), qPrintable(installJob->error().toString())); QFile p1HostArtifactInstalled(installRoot + "/host/host+target.output"); QVERIFY2(p1HostArtifactInstalled.exists(), qPrintable(p1HostArtifactInstalled.fileName())); QFile p1TargetArtifactInstalled(installRoot + "/target/host+target.output"); QVERIFY2(p1TargetArtifactInstalled.exists(), qPrintable(p1TargetArtifactInstalled.fileName())); QFile p2ArtifactInstalled(installRoot + "/host/host-tool.output"); QVERIFY2(p2ArtifactInstalled.exists(), qPrintable(p2ArtifactInstalled.fileName())); // Error check: Try to build for the same profile twice. overriddenValues.insert("project.targetProfile", hostProfile.name()); setupParams.setOverriddenValues(overriddenValues); setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY2(setupJob->error().toString().contains("Duplicate entry 'host' in qbs.profiles."), qPrintable(setupJob->error().toString())); // Error check: Try to build for the same profile twice, this time attaching // the properties via the product name. overriddenValues.remove(QStringLiteral("project.targetProfile")); overriddenValues.insert("products.p1.myProfiles", targetProfile.name() + ',' + targetProfile.name()); setupParams.setOverriddenValues(overriddenValues); setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY2(setupJob->error().toString().contains("Duplicate entry 'target' in qbs.profiles."), qPrintable(setupJob->error().toString())); } struct ProductDataSelector { void clear() { name.clear(); qbsProperties.clear(); } bool matches(const qbs::ProductData &p) const { return name == p.name() && qbsPropertiesMatch(p); } bool qbsPropertiesMatch(const qbs::ProductData &p) const { for (auto it = qbsProperties.begin(); it != qbsProperties.end(); ++it) { if (it.value() != p.moduleProperties().getModuleProperty("qbs", it.key())) return false; } return true; } QString name; QVariantMap qbsProperties; }; static qbs::ProductData takeMatchingProduct(QList &products, const ProductDataSelector &s) { qbs::ProductData result; auto it = std::find_if(products.begin(), products.end(), [&s] (const qbs::ProductData &pd) { return s.matches(pd); }); if (it != products.end()) { result = *it; products.erase(it); } return result; } void TestApi::multiplexing() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("multiplexing"); std::unique_ptr setupJob( qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); QList products = project.projectData().allProducts(); qbs::ProductData product; ProductDataSelector selector; selector.name = "no-multiplexing"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "multiplex-without-aggregator-2"; selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "multiplex-with-export"; selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "nonmultiplex-with-export"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "nonmultiplex-exporting-aggregation"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "multiplex-using-export"; selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.clear(); selector.name = "multiplex-without-aggregator-2-depend-on-non-multiplexed"; selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 1); selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 1); selector.clear(); selector.name = "multiplex-without-aggregator-4"; selector.qbsProperties["architecture"] = "C64"; selector.qbsProperties["buildVariant"] = "debug"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.qbsProperties["buildVariant"] = "release"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.qbsProperties["architecture"] = "TRS-80"; selector.qbsProperties["buildVariant"] = "debug"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.qbsProperties["buildVariant"] = "release"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QVERIFY(product.dependencies().empty()); selector.clear(); selector.name = "multiplex-with-aggregator-2"; selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 0); selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 0); selector.qbsProperties["architecture"] = "Atari ST"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.clear(); selector.name = "multiplex-with-aggregator-2-dependent"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 1); selector.clear(); selector.name = "non-multiplexed-with-dependencies-on-multiplexed"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.clear(); selector.name = "non-multiplexed-with-dependencies-on-multiplexed-via-export1"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 4); selector.clear(); selector.name = "non-multiplexed-with-dependencies-on-multiplexed-via-export2"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 3); selector.clear(); selector.name = "non-multiplexed-with-dependencies-on-aggregation-via-export"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(!product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.clear(); selector.name = "aggregate-with-dependencies-on-aggregation-via-export"; selector.qbsProperties["architecture"] = "C64"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.qbsProperties["architecture"] = "TRS-80"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 2); selector.qbsProperties["architecture"] = "Atari ST"; product = takeMatchingProduct(products, selector); QVERIFY(product.isValid()); QVERIFY(product.isMultiplexed()); QCOMPARE(product.dependencies().size(), 4); QVERIFY(products.empty()); } void TestApi::newOutputArtifactInDependency() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("new-output-artifact-in-dependency", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.descriptions.contains("linking app")); const QByteArray linkingLibString = QByteArray("linking ") + qbs::Internal::HostOsInfo::dynamicLibraryName("lib").toLatin1(); QVERIFY(!receiver.descriptions.contains(linkingLibString)); receiver.descriptions.clear(); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile("new-output-artifact-in-dependency.qbs"); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); QByteArray contents = projectFile.readAll(); contents.replace("//Depends", "Depends"); projectFile.resize(0); projectFile.write(contents); projectFile.close(); errorInfo = doBuildProject("new-output-artifact-in-dependency", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.descriptions.contains("linking app")); QVERIFY(receiver.descriptions.contains(linkingLibString)); } void TestApi::newPatternMatch() { TaskReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("new-pattern-match", 0, 0, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.taskDescriptions.contains("Resolving"), qPrintable(m_logSink->output)); receiver.taskDescriptions.clear(); errorInfo = doBuildProject("new-pattern-match", 0, 0, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(!receiver.taskDescriptions.contains("Resolving")); WAIT_FOR_NEW_TIMESTAMP(); QFile f("test.txt"); QVERIFY2(f.open(QIODevice::WriteOnly), qPrintable(f.errorString())); f.close(); errorInfo = doBuildProject("new-pattern-match", 0, 0, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.taskDescriptions.contains("Resolving")); receiver.taskDescriptions.clear(); errorInfo = doBuildProject("new-pattern-match", 0, 0, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(!receiver.taskDescriptions.contains("Resolving")); WAIT_FOR_NEW_TIMESTAMP(); f.remove(); errorInfo = doBuildProject("new-pattern-match", 0, 0, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.taskDescriptions.contains("Resolving")); } void TestApi::nonexistingProjectPropertyFromProduct() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("nonexistingprojectproperties"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QEXPECT_FAIL("", "QBS-432", Abort); QVERIFY(job->error().hasError()); QVERIFY2(job->error().toString().contains(QLatin1String("blubb")), qPrintable(job->error().toString())); } void TestApi::nonexistingProjectPropertyFromCommandLine() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("nonexistingprojectproperties"); removeBuildDir(setupParams); QVariantMap projectProperties; projectProperties.insert(QStringLiteral("project.blubb"), QStringLiteral("true")); setupParams.setOverriddenValues(projectProperties); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY(job->error().hasError()); QVERIFY2(job->error().toString().contains(QLatin1String("blubb")), qPrintable(job->error().toString())); } void TestApi::objC() { const qbs::ErrorInfo errorInfo = doBuildProject("objc"); VERIFY_NO_ERROR(errorInfo); } void TestApi::projectDataAfterProductInvalidation() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-data-after-" "product-invalidation/project-data-after-product-invalidation.qbs"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); QVERIFY(project.isValid()); QCOMPARE(project.projectData().products().size(), 1); QVERIFY(project.projectData().products().front().generatedArtifacts().empty()); std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QCOMPARE(project.projectData().products().size(), 1); const qbs::ProductData productAfterBulding = project.projectData().products().front(); QVERIFY(!productAfterBulding.generatedArtifacts().empty()); QFile projectFile(setupParams.projectFilePath()); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); QByteArray content = projectFile.readAll(); QVERIFY(!content.isEmpty()); content.replace("\"file.cpp", "// \"file.cpp"); projectFile.resize(0); projectFile.write(content); projectFile.flush(); setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); QVERIFY(!project.isValid()); project = setupJob->project(); QVERIFY(project.isValid()); QCOMPARE(project.projectData().products().size(), 1); QVERIFY(project.projectData().products().front().generatedArtifacts() == productAfterBulding.generatedArtifacts()); buildJob.reset(project.buildAllProducts(qbs::BuildOptions())); waitForFinished(buildJob.get()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QCOMPARE(project.projectData().products().size(), 1); QVERIFY(project.projectData().products().front().generatedArtifacts() != productAfterBulding.generatedArtifacts()); } void TestApi::processResult() { waitForFileUnlock(); removeBuildDir(defaultSetupParameters("process-result")); QFETCH(int, expectedExitCode); QFETCH(bool, redirectStdout); QFETCH(bool, redirectStderr); QVariantMap overridden; overridden.insert("products.app-caller.argument", expectedExitCode); overridden.insert("products.app-caller.redirectStdout", redirectStdout); overridden.insert("products.app-caller.redirectStderr", redirectStderr); ProcessResultReceiver resultReceiver; const qbs::ErrorInfo errorInfo = doBuildProject("process-result", nullptr, &resultReceiver, nullptr, qbs::BuildOptions(), overridden); QCOMPARE(expectedExitCode != 0, errorInfo.hasError()); QVERIFY(resultReceiver.results.size() > 1); const qbs::ProcessResult &result = resultReceiver.results.back(); QVERIFY2(result.executableFilePath().contains("app"), qPrintable(result.executableFilePath())); QCOMPARE(expectedExitCode, result.exitCode()); QCOMPARE(expectedExitCode == 0, result.success()); QCOMPARE(result.error(), QProcess::UnknownError); struct CheckParams { CheckParams(bool r, const QString &f, const QByteArray &c, const QStringList &co) : redirect(r), fileName(f), expectedContent(c), consoleOutput(co) {} bool redirect; QString fileName; QByteArray expectedContent; const QStringList consoleOutput; }; const std::vector checkParams({ CheckParams(redirectStdout, "stdout.txt", "stdout", result.stdOut()), CheckParams(redirectStderr, "stderr.txt", "stderr", result.stdErr()) }); for (const CheckParams &p : checkParams) { QFile f(relativeProductBuildDir("app-caller") + '/' + p.fileName); QCOMPARE(f.exists(), p.redirect); if (p.redirect) { QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString())); QCOMPARE(f.readAll(), p.expectedContent); QCOMPARE(p.consoleOutput, QStringList()); } else { QCOMPARE(p.consoleOutput.join("").toLocal8Bit(), p.expectedContent); } } } void TestApi::processResult_data() { QTest::addColumn("expectedExitCode"); QTest::addColumn("redirectStdout"); QTest::addColumn("redirectStderr"); QTest::newRow("success, no redirection") << 0 << false << false; QTest::newRow("success, stdout redirection") << 0 << true << false; QTest::newRow("failure, stderr redirection") << 1 << false << true; } void TestApi::projectInvalidation() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-invalidation"); QVERIFY(QFile::copy("project.no-error.qbs", "project-invalidation.qbs")); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); QVERIFY(project.isValid()); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("project.early-error.qbs", "project-invalidation.qbs"); setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY(project.isValid()); // Error in Loader, old project still valid. WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("project.late-error.qbs", "project-invalidation.qbs"); setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY(setupJob->error().hasError()); QVERIFY(!project.isValid()); // Error in build data re-resolving, old project not valid anymore. } void TestApi::projectLocking() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-locking"); std::unique_ptr setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); std::unique_ptr setupJob2(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob2.get()); QVERIFY(setupJob2->error().hasError()); QVERIFY2(setupJob2->error().toString() .contains("Cannot start a job while another one is in progress."), qPrintable(setupJob2->error().toString())); waitForFinished(setupJob.get()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); } void TestApi::projectPropertiesByName() { const QString projectFile = "project-properties-by-name/project-properties-by-name.qbs"; qbs::ErrorInfo errorInfo = doBuildProject(projectFile); QVERIFY(errorInfo.hasError()); QVariantMap overridden; overridden.insert("project.theDefines", QStringList() << "SUB1" << "SUB2"); errorInfo = doBuildProject(projectFile, 0, 0, 0, qbs::BuildOptions(), overridden); QVERIFY(errorInfo.hasError()); overridden.clear(); overridden.insert("projects.subproject1.theDefines", QStringList() << "SUB1"); errorInfo = doBuildProject(projectFile, 0, 0, 0, qbs::BuildOptions(), overridden); QVERIFY(errorInfo.hasError()); overridden.insert("projects.subproject2.theDefines", QStringList() << "SUB2"); errorInfo = doBuildProject(projectFile, 0, 0, 0, qbs::BuildOptions(), overridden); VERIFY_NO_ERROR(errorInfo); } void TestApi::projectWithPropertiesItem() { const qbs::ErrorInfo errorInfo = doBuildProject("project-with-properties-item"); VERIFY_NO_ERROR(errorInfo); } void TestApi::propertiesBlocks() { const qbs::ErrorInfo errorInfo = doBuildProject("properties-blocks"); VERIFY_NO_ERROR(errorInfo); } void TestApi::rc() { BuildDescriptionReceiver bdr; ProcessResultReceiver prr; const auto buildRc = [this, &bdr, &prr]() { bdr.descriptions.clear(); bdr.descriptionLines.clear(); prr.output.clear(); prr.results.clear(); const qbs::ErrorInfo errorInfo = doBuildProject("rc", &bdr, &prr); if (errorInfo.hasError()) qDebug() << prr.output; return errorInfo; }; const auto rcFileWasCompiled = [&bdr]() { return bdr.descriptions.contains("compiling test.rc"); }; qbs::ErrorInfo error = buildRc(); VERIFY_NO_ERROR(error); QCOMPARE(rcFileWasCompiled(), qbs::Internal::HostOsInfo::isWindowsHost()); WAIT_FOR_NEW_TIMESTAMP(); error = buildRc(); VERIFY_NO_ERROR(error); QVERIFY(!rcFileWasCompiled()); touch("subdir/rc-include.h"); error = buildRc(); VERIFY_NO_ERROR(error); QCOMPARE(rcFileWasCompiled(), qbs::Internal::HostOsInfo::isWindowsHost()); } void TestApi::referencedFileErrors() { QFETCH(bool, relaxedMode); qbs::SetupProjectParameters params = defaultSetupParameters("referenced-file-errors"); params.setDryRun(true); params.setProductErrorMode(relaxedMode ? qbs::ErrorHandlingMode::Relaxed : qbs::ErrorHandlingMode::Strict); m_logSink->setLogLevel(qbs::LoggerMinLevel); std::unique_ptr job(qbs::Project().setupProject(params, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(job->error().hasError() != relaxedMode, qPrintable(job->error().toString())); const qbs::Project project = job->project(); QCOMPARE(project.isValid(), relaxedMode); if (!relaxedMode) return; const QList products = project.projectData().allProducts(); QCOMPARE(products.size(), 5); for (const qbs::ProductData &p : products) QCOMPARE(p.isEnabled(), p.name() != "p5"); } void TestApi::referencedFileErrors_data() { QTest::addColumn("relaxedMode"); QTest::newRow("strict mode") << false; QTest::newRow("relaxed mode") << true; } qbs::SetupProjectParameters TestApi::defaultSetupParameters(const QString &projectFileOrDir) const { QFileInfo fi(m_workingDataDir + QLatin1Char('/') + projectFileOrDir); QString projectDirPath; QString projectFilePath; if (fi.isDir()) { projectDirPath = fi.absoluteFilePath(); projectFilePath = projectDirPath + QLatin1Char('/') + projectFileOrDir + QStringLiteral(".qbs"); } else { projectDirPath = fi.absolutePath(); projectFilePath = fi.absoluteFilePath(); } qbs::SetupProjectParameters setupParams; setupParams.setEnvironment(QProcessEnvironment::systemEnvironment()); setupParams.setProjectFilePath(projectFilePath); setupParams.setPropertyCheckingMode(qbs::ErrorHandlingMode::Strict); setupParams.setOverrideBuildGraphData(true); QDir::setCurrent(projectDirPath); setupParams.setBuildRoot(projectDirPath); const SettingsPtr s = settings(); const qbs::Preferences prefs(s.get(), profileName()); setupParams.setSearchPaths(prefs.searchPaths(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_SEARCH_PATH)))); setupParams.setPluginPaths(prefs.pluginPaths(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_PLUGINS_PATH)))); setupParams.setLibexecPath(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_LIBEXEC_PATH))); setupParams.setTopLevelProfile(profileName()); setupParams.setConfigurationName(QStringLiteral("default")); setupParams.setSettingsDirectory(settings()->baseDirectory()); return setupParams; } void TestApi::references() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("references/invalid1.qbs"); const QString projectDir = QDir::cleanPath(m_workingDataDir + "/references"); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY(job->error().hasError()); QString errorString = job->error().toString(); QVERIFY2(errorString.contains("does not contain"), qPrintable(errorString)); setupParams.setProjectFilePath(projectDir + QLatin1String("/invalid2.qbs")); job.reset(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY(job->error().hasError()); errorString = job->error().toString(); QVERIFY2(errorString.contains("contains more than one"), qPrintable(errorString)); setupParams.setProjectFilePath(projectDir + QLatin1String("/valid.qbs")); job.reset(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::ProjectData topLevelProject = job->project().projectData(); QCOMPARE(topLevelProject.subProjects().size(), 1); const QString subProjectFileName = QFileInfo(topLevelProject.subProjects().front().location().filePath()).fileName(); QCOMPARE(subProjectFileName, QString("p.qbs")); } void TestApi::relaxedModeRecovery() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("relaxed-mode-recovery"); setupParams.setProductErrorMode(qbs::ErrorHandlingMode::Relaxed); setupParams.setPropertyCheckingMode(qbs::ErrorHandlingMode::Relaxed); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); if (m_logSink->warnings.size() != 4) { const auto errors = m_logSink->warnings; for (const qbs::ErrorInfo &error : errors) qDebug() << error.toString(); } QCOMPARE(m_logSink->warnings.size(), 4); const auto errors = m_logSink->warnings; for (const qbs::ErrorInfo &error : errors) { QVERIFY2(!error.toString().contains("ASSERT") && (error.toString().contains("Dependency 'blubb' not found") || error.toString().contains("Product 'p1' had errors and was disabled") || error.toString().contains("Product 'p2' had errors and was disabled")), qPrintable(error.toString())); } } void TestApi::renameProduct() { // Initial run. qbs::ErrorInfo errorInfo = doBuildProject("rename-product/rename.qbs"); VERIFY_NO_ERROR(errorInfo); // Rename lib and adapt Depends item. WAIT_FOR_NEW_TIMESTAMP(); QFile f("rename.qbs"); QVERIFY(f.open(QIODevice::ReadWrite)); QByteArray contents = f.readAll(); contents.replace("TheLib", "thelib"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("rename-product/rename.qbs"); VERIFY_NO_ERROR(errorInfo); // Rename lib and don't adapt Depends item. WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(f.open(QIODevice::ReadWrite)); contents = f.readAll(); const int libNameIndex = contents.lastIndexOf("thelib"); QVERIFY(libNameIndex != -1); contents.replace(libNameIndex, 6, "TheLib"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("rename-product/rename.qbs"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Dependency 'thelib' not found"), qPrintable(errorInfo.toString())); } void TestApi::renameTargetArtifact() { // Initial run. BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("rename-target-artifact/rename.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); QCOMPARE(receiver.descriptions.count("linking"), 2); receiver.descriptions.clear(); // Rename library file name. WAIT_FOR_NEW_TIMESTAMP(); QFile f("rename.qbs"); QVERIFY(f.open(QIODevice::ReadWrite)); QByteArray contents = f.readAll(); contents.replace("the_lib", "TheLib"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("rename-target-artifact/rename.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); QCOMPARE(receiver.descriptions.count("linking"), 2); } void TestApi::removeFileDependency() { qbs::ErrorInfo errorInfo = doBuildProject("remove-file-dependency/removeFileDependency.qbs"); VERIFY_NO_ERROR(errorInfo); QFile::remove("someheader.h"); ProcessResultReceiver receiver; errorInfo = doBuildProject("remove-file-dependency/removeFileDependency.qbs", 0, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(receiver.output.contains("someheader.h"), qPrintable(receiver.output)); } void TestApi::resolveProject() { QFETCH(QString, projectSubDir); QFETCH(QString, productFileName); const qbs::SetupProjectParameters params = defaultSetupParameters(projectSubDir); removeBuildDir(params); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, 0)); waitForFinished(setupJob.get()); VERIFY_NO_ERROR(setupJob->error()); QVERIFY2(!QFile::exists(productFileName), qPrintable(productFileName)); QVERIFY(regularFileExists(relativeBuildGraphFilePath())); } void TestApi::resolveProject_data() { return buildProject_data(); } void TestApi::resolveProjectDryRun() { QFETCH(QString, projectSubDir); QFETCH(QString, productFileName); qbs::SetupProjectParameters params = defaultSetupParameters(projectSubDir); params.setDryRun(true); removeBuildDir(params); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, 0)); waitForFinished(setupJob.get()); VERIFY_NO_ERROR(setupJob->error()); QVERIFY2(!QFile::exists(productFileName), qPrintable(productFileName)); QVERIFY(!regularFileExists(relativeBuildGraphFilePath())); } void TestApi::resolveProjectDryRun_data() { return resolveProject_data(); } void TestApi::restoredWarnings() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("restored-warnings"); setupParams.setPropertyCheckingMode(qbs::ErrorHandlingMode::Relaxed); setupParams.setProductErrorMode(qbs::ErrorHandlingMode::Relaxed); // Initial resolving: Errors are new. std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); job.reset(nullptr); QCOMPARE(m_logSink->warnings.toSet().size(), 2); const auto beforeErrors = m_logSink->warnings; for (const qbs::ErrorInfo &e : beforeErrors) { const QString msg = e.toString(); QVERIFY2(msg.contains("Superfluous version") || msg.contains("Property 'blubb' is not declared"), qPrintable(msg)); } m_logSink->warnings.clear(); // Re-resolving with no changes: Errors come from the stored build graph. job.reset(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); job.reset(nullptr); QCOMPARE(m_logSink->warnings.toSet().size(), 2); m_logSink->warnings.clear(); // Re-resolving with changes: Errors come from the re-resolving, stored ones must be suppressed. QVariantMap overridenValues; overridenValues.insert("products.theProduct.moreFiles", true); setupParams.setOverriddenValues(overridenValues); job.reset(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); job.reset(nullptr); QCOMPARE(m_logSink->warnings.toSet().size(), 3); // One more for the additional group const auto afterErrors = m_logSink->warnings; for (const qbs::ErrorInfo &e : afterErrors) { const QString msg = e.toString(); QVERIFY2(msg.contains("Superfluous version") || msg.contains("Property 'blubb' is not declared") || msg.contains("blubb.cpp' does not exist"), qPrintable(msg)); } m_logSink->warnings.clear(); } void TestApi::ruleConflict() { const qbs::ErrorInfo errorInfo = doBuildProject("rule-conflict"); QVERIFY(errorInfo.hasError()); const QString errorString = errorInfo.toString(); QVERIFY2(errorString.contains("conflict") && errorString.contains("pch1.h") && errorString.contains("pch2.h"), qPrintable(errorString)); } void TestApi::runEnvForDisabledProduct() { const qbs::SetupProjectParameters params = defaultSetupParameters("run-disabled-product/run-disabled-product.qbs"); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, 0)); QVERIFY(waitForFinished(setupJob.get())); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const qbs::Project project = setupJob->project(); const std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); QVERIFY(waitForFinished(buildJob.get())); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); const qbs::ProjectData projectData = project.projectData(); const QList products = projectData.products(); QCOMPARE(products.size(), 1); const qbs::ProductData product = products.front(); qbs::RunEnvironment runEnv = project.getRunEnvironment( product, qbs::InstallOptions(), QProcessEnvironment(), QStringList(), settings().get()); qbs::ErrorInfo runError; const QProcessEnvironment env = runEnv.runEnvironment(&runError); QVERIFY2(runError.toString().contains("Cannot run disabled product 'app'"), qPrintable(runError.toString())); runError.clear(); runEnv.runTarget(QString(), QStringList(), true, &runError); QVERIFY2(runError.toString().contains("Cannot run disabled product 'app'"), qPrintable(runError.toString())); } void TestApi::softDependency() { const qbs::ErrorInfo errorInfo = doBuildProject("soft-dependency"); VERIFY_NO_ERROR(errorInfo); } void TestApi::sourceFileInBuildDir() { VERIFY_NO_ERROR(doBuildProject("source-file-in-build-dir")); qbs::SetupProjectParameters setupParams = defaultSetupParameters("source-file-in-build-dir"); const QString generatedFile = relativeProductBuildDir("theProduct") + "/generated.cpp"; QVERIFY2(regularFileExists(generatedFile), qPrintable(generatedFile)); std::unique_ptr job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.get()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::ProjectData projectData = job->project().projectData(); QCOMPARE(projectData.allProducts().size(), 1); const qbs::ProductData product = projectData.allProducts().front(); QCOMPARE(product.profile(), profileName()); const qbs::GroupData group = findGroup(product, "the group"); QVERIFY(group.isValid()); QCOMPARE(group.allFilePaths().size(), 1); } void TestApi::subProjects() { const qbs::SetupProjectParameters params = defaultSetupParameters("subprojects/toplevelproject.qbs"); removeBuildDir(params); // Check all three types of subproject creation, plus property overrides. qbs::ErrorInfo errorInfo = doBuildProject("subprojects/toplevelproject.qbs"); VERIFY_NO_ERROR(errorInfo); // Disabling both the project with the dependency and the one with the dependent // should not cause an error. WAIT_FOR_NEW_TIMESTAMP(); QFile f(params.projectFilePath()); QVERIFY(f.open(QIODevice::ReadWrite)); QByteArray contents = f.readAll(); contents.replace("condition: true", "condition: false"); f.resize(0); f.write(contents); f.close(); f.setFileName(params.buildRoot() + "/subproject2/subproject2.qbs"); QVERIFY(f.open(QIODevice::ReadWrite)); contents = f.readAll(); contents.replace("condition: qbs.targetOS.length > 0", "condition: false"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("subprojects/toplevelproject.qbs"); VERIFY_NO_ERROR(errorInfo); // Disabling the project with the dependency only is an error. // This tests also whether changes in sub-projects are detected. WAIT_FOR_NEW_TIMESTAMP(); f.setFileName(params.projectFilePath()); QVERIFY(f.open(QIODevice::ReadWrite)); contents = f.readAll(); contents.replace("condition: false", "condition: true"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("subprojects/toplevelproject.qbs"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Dependency 'testLib' not found"), qPrintable(errorInfo.toString())); } void TestApi::targetArtifactStatus_data() { QTest::addColumn("enableTagging"); QTest::newRow("tagging off") << false; QTest::newRow("tagging on") << true; QTest::newRow("tagging off again") << false; } void TestApi::targetArtifactStatus() { QFETCH(bool, enableTagging); qbs::SetupProjectParameters params = defaultSetupParameters("target-artifact-status/target-artifact-status.qbs"); params.setOverriddenValues({std::make_pair("products.p.enableTagging", enableTagging)}); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, 0)); waitForFinished(setupJob.get()); VERIFY_NO_ERROR(setupJob->error()); const qbs::Project project = setupJob->project(); QVERIFY(project.isValid()); const std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); QVERIFY(waitForFinished(buildJob.get())); VERIFY_NO_ERROR(buildJob->error()); const qbs::ProjectData projectData = project.projectData(); const QList products = projectData.products(); QCOMPARE(products.size(), 1); const qbs::ProductData product = products.front(); QCOMPARE(product.targetArtifacts().size(), enableTagging ? 2 : 1); } void TestApi::toolInModule() { QVariantMap overrides({std::make_pair("qbs.installRoot", m_workingDataDir + "/tool-in-module/use-outside-project")}); const qbs::ErrorInfo error = doBuildProject("tool-in-module/use-within-project/use-within-project.qbs", nullptr, nullptr, nullptr, qbs::BuildOptions(), overrides); QVERIFY2(!error.hasError(), qPrintable(error.toString())); const QString toolOutput = relativeProductBuildDir("user-in-project") + "/tool-output.txt"; QVERIFY2(QFile::exists(toolOutput), qPrintable(toolOutput)); const qbs::SetupProjectParameters params = defaultSetupParameters("tool-in-module/use-outside-project/use-outside-project.qbs"); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, 0)); QVERIFY(waitForFinished(setupJob.get())); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const qbs::Project project = setupJob->project(); const qbs::ProjectData projectData = project.projectData(); const QList products = projectData.products(); QCOMPARE(products.size(), 1); const qbs::ProductData product = products.front(); for (const qbs::GroupData &group : product.groups()) QVERIFY(group.name() != "thetool binary"); const std::unique_ptr buildJob(setupJob->project() .buildAllProducts(qbs::BuildOptions())); QVERIFY(waitForFinished(buildJob.get())); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); const QString toolOutput2 = relativeProductBuildDir("user-outside-project") + "/tool-output.txt"; QVERIFY2(QFile::exists(toolOutput2), qPrintable(toolOutput2)); } void TestApi::trackAddQObjectHeader() { const qbs::SetupProjectParameters params = defaultSetupParameters("missing-qobject-header/missingheader.qbs"); QFile qbsFile(params.projectFilePath()); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("import qbs.base 1.0\nCppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp']\n}"); qbsFile.close(); ProcessResultReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs", 0, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable(receiver.output)); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("import qbs.base 1.0\nCppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp','myobject.h']\n}"); qbsFile.close(); errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::trackRemoveQObjectHeader() { const qbs::SetupProjectParameters params = defaultSetupParameters("missing-qobject-header/missingheader.qbs"); removeBuildDir(params); QFile qbsFile(params.projectFilePath()); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("import qbs.base 1.0\nCppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp','myobject.h']\n}"); qbsFile.close(); qbs::ErrorInfo errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs"); VERIFY_NO_ERROR(errorInfo); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("import qbs.base 1.0\nCppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp']\n}"); qbsFile.close(); ProcessResultReceiver receiver; errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs", 0, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable(receiver.output)); } void TestApi::transformerData() { const qbs::SetupProjectParameters params = defaultSetupParameters("transformer-data/transformer-data.qbs"); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, 0)); QVERIFY(waitForFinished(setupJob.get())); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const qbs::Project project = setupJob->project(); const std::unique_ptr buildJob(project.buildAllProducts(qbs::BuildOptions())); QVERIFY(waitForFinished(buildJob.get())); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); qbs::ErrorInfo error; const qbs::ProjectTransformerData projectTData = project.transformerData(&error); QVERIFY2(!error.hasError(), qPrintable(error.toString())); QCOMPARE(projectTData.size(), 1); const qbs::ProductTransformerData productTData = projectTData.first().second; QCOMPARE(productTData.size(), 2); bool firstTransformerFound = false; bool secondTransformerFound = false; for (const qbs::TransformerData &tData : productTData) { if (tData.inputs().empty()) { firstTransformerFound = true; QCOMPARE(tData.outputs().size(), 1); QCOMPARE(QFileInfo(tData.outputs().first().filePath()).fileName(), QString("artifact1")); QCOMPARE(tData.commands().size(), 1); QCOMPARE(tData.commands().first().type(), qbs::RuleCommand::JavaScriptCommandType); } else { secondTransformerFound = true; QCOMPARE(tData.inputs().size(), 1); QCOMPARE(QFileInfo(tData.inputs().first().filePath()).fileName(), QString("artifact1")); QCOMPARE(tData.outputs().size(), 1); QCOMPARE(QFileInfo(tData.outputs().first().filePath()).fileName(), QString("artifact2")); QCOMPARE(tData.commands().size(), 1); QCOMPARE(tData.commands().first().type(), qbs::RuleCommand::JavaScriptCommandType); } } QVERIFY(firstTransformerFound); QVERIFY(secondTransformerFound); } void TestApi::transformers() { const qbs::ErrorInfo errorInfo = doBuildProject("transformers/transformers.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::typeChange() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("type-change", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile("type-change.qbs"); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); QByteArray content = projectFile.readAll(); content.replace("//", ""); projectFile.resize(0); projectFile.write(content); projectFile.close(); errorInfo = doBuildProject("type-change", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); } void TestApi::uic() { const qbs::ErrorInfo errorInfo = doBuildProject("uic"); VERIFY_NO_ERROR(errorInfo); } qbs::ErrorInfo TestApi::doBuildProject( const QString &projectFilePath, BuildDescriptionReceiver *buildDescriptionReceiver, ProcessResultReceiver *procResultReceiver, TaskReceiver *taskReceiver, const qbs::BuildOptions &options, const QVariantMap overriddenValues) { qbs::SetupProjectParameters params = defaultSetupParameters(projectFilePath); params.setOverriddenValues(overriddenValues); params.setDryRun(options.dryRun()); const std::unique_ptr setupJob(qbs::Project().setupProject(params, m_logSink, 0)); if (taskReceiver) { connect(setupJob.get(), &qbs::AbstractJob::taskStarted, taskReceiver, &TaskReceiver::handleTaskStart); } waitForFinished(setupJob.get()); if (setupJob->error().hasError()) return setupJob->error(); const std::unique_ptr buildJob(setupJob->project().buildAllProducts(options)); if (buildDescriptionReceiver) { connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription, buildDescriptionReceiver, &BuildDescriptionReceiver::handleDescription); } if (procResultReceiver) { connect(buildJob.get(), &qbs::BuildJob::reportProcessResult, procResultReceiver, &ProcessResultReceiver::handleProcessResult); } waitForFinished(buildJob.get()); return buildJob->error(); } QTEST_MAIN(TestApi) #include "tst_api.moc" qbs-src-1.13.1/tests/auto/api/tst_api.h000066400000000000000000000122411347155106100176510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TST_API_H #define QBS_TST_API_H #include #include #include namespace qbs { class ErrorInfo; class SetupProjectParameters; } class BuildDescriptionReceiver; class LogSink; class ProcessResultReceiver; class TaskReceiver; class TestApi : public QObject { Q_OBJECT public: TestApi(); ~TestApi(); private slots: void initTestCase(); void init(); void addQObjectMacroToCppFile(); void addedFilePersistent(); void baseProperties(); void buildErrorCodeLocation(); void buildGraphInfo(); void buildGraphLocking(); void buildProject(); void buildProject_data(); void buildProjectDryRun(); void buildProjectDryRun_data(); void buildSingleFile(); void canonicalToolchainList(); #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES void changeContent(); #endif void changeDependentLib(); void checkOutputs(); void checkOutputs_data(); void commandExtraction(); void dependencyOnMultiplexedType(); void disabledInstallGroup(); void disabledProduct(); void disabledProject(); void duplicateProductNames(); void duplicateProductNames_data(); void emptyFileTagList(); void emptySubmodulesList(); void enableAndDisableProduct(); void errorInSetupRunEnvironment(); void excludedInputs(); void explicitlyDependsOn(); void exportSimple(); void exportWithRecursiveDepends(); void fallbackGcc(); void fileTagger(); void fileTagsFilterOverride(); void generatedFilesList(); void infiniteLoopBuilding(); void infiniteLoopBuilding_data(); void infiniteLoopResolving(); void inheritQbsSearchPaths(); void installableFiles(); void isRunnable(); void linkDynamicLibs(); void linkDynamicAndStaticLibs(); void linkStaticAndDynamicLibs(); void listBuildSystemFiles(); void localProfiles(); void localProfiles_data(); void missingSourceFile(); void mocCppIncluded(); void multiArch(); void multiplexing(); void newOutputArtifactInDependency(); void newPatternMatch(); void nonexistingProjectPropertyFromCommandLine(); void nonexistingProjectPropertyFromProduct(); void objC(); void projectDataAfterProductInvalidation(); void processResult(); void processResult_data(); void projectInvalidation(); void projectLocking(); void projectPropertiesByName(); void projectWithPropertiesItem(); void propertiesBlocks(); void rc(); void referencedFileErrors(); void referencedFileErrors_data(); void references(); void relaxedModeRecovery(); void removeFileDependency(); void renameProduct(); void renameTargetArtifact(); void resolveProject(); void resolveProject_data(); void resolveProjectDryRun(); void resolveProjectDryRun_data(); void restoredWarnings(); void ruleConflict(); void runEnvForDisabledProduct(); void softDependency(); void sourceFileInBuildDir(); void subProjects(); void targetArtifactStatus_data(); void targetArtifactStatus(); void toolInModule(); void trackAddQObjectHeader(); void trackRemoveQObjectHeader(); void transformerData(); void transformers(); void typeChange(); void uic(); private: qbs::SetupProjectParameters defaultSetupParameters(const QString &projectFileOrDir) const; qbs::ErrorInfo doBuildProject(const QString &projectFilePath, BuildDescriptionReceiver *buildDescriptionReceiver = 0, ProcessResultReceiver *procResultReceiver = 0, TaskReceiver *taskReceiver = 0, const qbs::BuildOptions &options = qbs::BuildOptions(), const QVariantMap overriddenValues = QVariantMap()); LogSink * const m_logSink; const QString m_sourceDataDir; const QString m_workingDataDir; }; #endif // Include guard. qbs-src-1.13.1/tests/auto/auto.pri000066400000000000000000000011741347155106100167530ustar00rootroot00000000000000TEMPLATE = app DESTDIR = ../../../bin DEFINES += SRCDIR=\\\"$$_PRO_FILE_PWD_\\\" qbs_test_suite_name = $$replace(_PRO_FILE_, ^.*/([^/.]+)\\.pro$, \\1) qbs_test_suite_name = $$upper($$replace(qbs_test_suite_name, -, _)) DEFINES += QBS_TEST_SUITE_NAME=\\\"$${qbs_test_suite_name}\\\" INCLUDEPATH += $$PWD/../../src $$PWD/../../src/app/shared QT = core testlib CONFIG += testcase console CONFIG -= app_bundle CONFIG += c++14 target.CONFIG += no_default_install dev_lib_frameworks=$$QMAKE_XCODE_DEVELOPER_PATH/Library/Frameworks exists($$dev_lib_frameworks): LIBS += -F$$dev_lib_frameworks include(../../src/lib/corelib/use_corelib.pri) qbs-src-1.13.1/tests/auto/auto.pro000066400000000000000000000006131347155106100167560ustar00rootroot00000000000000TEMPLATE=subdirs qbs_enable_unit_tests { SUBDIRS += \ buildgraph \ language \ tools \ } SUBDIRS += \ cmdlineparser \ blackbox/blackbox.pro \ blackbox/blackbox-android.pro \ blackbox/blackbox-apple.pro \ blackbox/blackbox-clangdb.pro \ blackbox/blackbox-java.pro \ blackbox/blackbox-joblimits.pro \ blackbox/blackbox-qt.pro \ api qbs-src-1.13.1/tests/auto/auto.qbs000066400000000000000000000007701347155106100167470ustar00rootroot00000000000000import qbs Project { name: "Autotests" references: [ "api/api.qbs", "blackbox/blackbox.qbs", "blackbox/blackbox-android.qbs", "blackbox/blackbox-apple.qbs", "blackbox/blackbox-clangdb.qbs", "blackbox/blackbox-java.qbs", "blackbox/blackbox-joblimits.qbs", "blackbox/blackbox-qt.qbs", "buildgraph/buildgraph.qbs", "cmdlineparser/cmdlineparser.qbs", "language/language.qbs", "tools/tools.qbs", ] } qbs-src-1.13.1/tests/auto/blackbox/000077500000000000000000000000001347155106100170515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/blackbox-android.pro000066400000000000000000000007641347155106100230050ustar00rootroot00000000000000TARGET = tst_blackbox-android HEADERS = tst_blackboxandroid.h tst_blackboxbase.h SOURCES = tst_blackboxandroid.cpp tst_blackboxbase.cpp OBJECTS_DIR = android MOC_DIR = $${OBJECTS_DIR}-moc include(../auto.pri) DATA_DIRS = testdata-android ../find for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES DISTFILES += \ testdata/texttemplate/expected-output-one.txt qbs-src-1.13.1/tests/auto/blackbox/blackbox-android.qbs000066400000000000000000000010051347155106100227570ustar00rootroot00000000000000import qbs.Utilities QbsAutotest { testName: "blackbox-android" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-android/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackboxandroid.cpp", "tst_blackboxandroid.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-1.13.1/tests/auto/blackbox/blackbox-apple.pro000066400000000000000000000006631347155106100224640ustar00rootroot00000000000000TARGET = tst_blackbox-apple HEADERS = tst_blackboxapple.h tst_blackboxbase.h SOURCES = tst_blackboxapple.cpp tst_blackboxbase.cpp OBJECTS_DIR = apple MOC_DIR = $${OBJECTS_DIR}-moc include(../auto.pri) QT += xml DATA_DIRS = testdata-apple ../find for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES qbs-src-1.13.1/tests/auto/blackbox/blackbox-apple.qbs000066400000000000000000000010341347155106100224420ustar00rootroot00000000000000import qbs.Utilities QbsAutotest { testName: "blackbox-apple" Depends { name: "Qt.xml" } Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-apple/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxapple.cpp", "tst_blackboxapple.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-1.13.1/tests/auto/blackbox/blackbox-clangdb.pro000066400000000000000000000006321347155106100227510ustar00rootroot00000000000000TARGET = tst_blackbox-clangdb HEADERS = tst_blackboxbase.h tst_clangdb.h SOURCES = tst_blackboxbase.cpp tst_clangdb.cpp OBJECTS_DIR = clangdb MOC_DIR = $${OBJECTS_DIR}-moc include(../auto.pri) DATA_DIRS = testdata-clangdb for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES qbs-src-1.13.1/tests/auto/blackbox/blackbox-clangdb.qbs000066400000000000000000000007701347155106100227410ustar00rootroot00000000000000import qbs.Utilities QbsAutotest { testName: "blackbox-clangdb" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-clangdb/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_clangdb.cpp", "tst_clangdb.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-1.13.1/tests/auto/blackbox/blackbox-java.pro000066400000000000000000000006431347155106100223020ustar00rootroot00000000000000TARGET = tst_blackbox-java HEADERS = tst_blackboxjava.h tst_blackboxbase.h SOURCES = tst_blackboxjava.cpp tst_blackboxbase.cpp OBJECTS_DIR = java MOC_DIR = $${OBJECTS_DIR}-moc include(../auto.pri) DATA_DIRS = testdata-java ../find for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES qbs-src-1.13.1/tests/auto/blackbox/blackbox-java.qbs000066400000000000000000000007711347155106100222710ustar00rootroot00000000000000import qbs.Utilities QbsAutotest { testName: "blackbox-java" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-java/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackboxjava.cpp", "tst_blackboxjava.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-1.13.1/tests/auto/blackbox/blackbox-joblimits.pro000066400000000000000000000006441347155106100233560ustar00rootroot00000000000000TARGET = tst_blackbox-joblimits HEADERS = tst_blackboxbase.h SOURCES = tst_blackboxjoblimits.cpp tst_blackboxbase.cpp OBJECTS_DIR = joblimits MOC_DIR = $${OBJECTS_DIR}-moc include(../auto.pri) DATA_DIRS = testdata-joblimits ../find for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES qbs-src-1.13.1/tests/auto/blackbox/blackbox-joblimits.qbs000066400000000000000000000007521347155106100233430ustar00rootroot00000000000000import qbs.Utilities QbsAutotest { testName: "blackbox-joblimits" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-joblimits/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackboxjoblimits.cpp", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-1.13.1/tests/auto/blackbox/blackbox-qt.pro000066400000000000000000000006311347155106100220020ustar00rootroot00000000000000TARGET = tst_blackbox-qt HEADERS = tst_blackboxqt.h tst_blackboxbase.h SOURCES = tst_blackboxqt.cpp tst_blackboxbase.cpp OBJECTS_DIR = qt MOC_DIR = $${OBJECTS_DIR}-moc include(../auto.pri) DATA_DIRS = testdata-qt ../find for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES qbs-src-1.13.1/tests/auto/blackbox/blackbox-qt.qbs000066400000000000000000000007611347155106100217730ustar00rootroot00000000000000import qbs.Utilities QbsAutotest { testName: "blackbox-qt" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "testdata" prefix: "testdata-qt/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackboxqt.cpp", "tst_blackboxqt.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) } qbs-src-1.13.1/tests/auto/blackbox/blackbox.pro000066400000000000000000000007261347155106100213650ustar00rootroot00000000000000TARGET = tst_blackbox HEADERS = tst_blackbox.h tst_blackboxbase.h SOURCES = tst_blackbox.cpp tst_blackboxbase.cpp OBJECTS_DIR = generic MOC_DIR = $${OBJECTS_DIR}-moc qbs_enable_unit_tests:DEFINES += QBS_ENABLE_UNIT_TESTS include(../auto.pri) QT += xml DATA_DIRS = testdata ../find for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES qbs-src-1.13.1/tests/auto/blackbox/blackbox.qbs000066400000000000000000000012441347155106100213460ustar00rootroot00000000000000import qbs.Utilities QbsAutotest { testName: "blackbox" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } Group { name: "find" prefix: "find/" files: ["**/*"] fileTags: [] } Group { name: "testdata" prefix: "testdata/" files: ["**/*"] fileTags: [] } files: [ "../shared.h", "tst_blackboxbase.cpp", "tst_blackboxbase.h", "tst_blackbox.cpp", "tst_blackbox.h", ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) .concat(qbsbuildconfig.enableUnitTests ? ["QBS_ENABLE_UNIT_TESTS"] : []) } qbs-src-1.13.1/tests/auto/blackbox/find/000077500000000000000000000000001347155106100177715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/find/find-android.qbs000066400000000000000000000030011347155106100230300ustar00rootroot00000000000000import qbs.TextFile Product { property string packageName: "" qbs.targetPlatform: "android" Depends { name: "Android.sdk"; required: false } Depends { name: "Android.ndk"; required: false } type: ["json"] Rule { multiplex: true Artifact { filePath: ["android.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; if (product.moduleProperty("Android.sdk", "present")) { tools["sdk"] = product.moduleProperty("Android.sdk", "sdkDir"); tools["sdk-build-tools-dx"] = product.Android.sdk.dxFilePath; } if (product.moduleProperty("Android.ndk", "present")) { tools["ndk"] = product.moduleProperty("Android.ndk", "ndkDir"); tools["ndk-samples"] = product.Android.ndk.ndkSamplesDir; } if (product.java && product.java.present) tools["jar"] = product.java.jarFilePath; var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/find/find-jdk.qbs000066400000000000000000000021371347155106100221710ustar00rootroot00000000000000import qbs.TextFile Product { Depends { name: "java"; required: false } type: ["json"] Rule { multiplex: true Artifact { filePath: ["jdk.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; if (product.moduleProperty("java", "present")) { tools["javac"] = product.moduleProperty("java", "compilerFilePath"); tools["java"] = product.moduleProperty("java", "interpreterFilePath"); tools["jar"] = product.moduleProperty("java", "jarFilePath"); } var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/find/find-nodejs.qbs000066400000000000000000000016751347155106100227110ustar00rootroot00000000000000import qbs.TextFile Product { Depends { name: "nodejs"; required: false } type: ["json"] Rule { multiplex: true Artifact { filePath: ["nodejs.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; if (product.moduleProperty("nodejs", "present")) { tools["node"] = product.moduleProperty("nodejs", "interpreterFilePath"); } var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/find/find-typescript.qbs000066400000000000000000000017651347155106100236350ustar00rootroot00000000000000import qbs.TextFile Product { Depends { name: "nodejs"; required: false } Depends { name: "typescript"; required: false } type: ["json"] Rule { multiplex: true Artifact { filePath: ["typescript.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; if (product.moduleProperty("typescript", "present")) { tools["tsc"] = product.moduleProperty("typescript", "compilerPath"); } var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/find/find-xcode.qbs000066400000000000000000000022261347155106100225220ustar00rootroot00000000000000import qbs.TextFile Product { Depends { name: "xcode"; required: false } type: ["json"] Rule { multiplex: true Artifact { filePath: ["xcode.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; if (product.moduleProperty("xcode", "present")) { var keys = [ "developerPath", "version" ]; for (var i = 0; i < keys.length; ++i) { var key = keys[i]; tools[key] = product.xcode[key]; } } var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/000077500000000000000000000000001347155106100223005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/aidl/000077500000000000000000000000001347155106100232115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/aidl/AndroidManifest.xml000066400000000000000000000007431347155106100270060ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata-android/aidl/aidl.qbs000066400000000000000000000002411347155106100246260ustar00rootroot00000000000000Application { name: "io.qbs.aidltest" Android.sdk.aidlSearchPaths: path files: [ "AndroidManifest.xml", "io/qbs/aidltest/*", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/aidl/io/000077500000000000000000000000001347155106100236205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/aidl/io/qbs/000077500000000000000000000000001347155106100244055ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/aidl/io/qbs/aidltest/000077500000000000000000000000001347155106100262165ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/aidl/io/qbs/aidltest/Interface1.aidl000066400000000000000000000002251347155106100310310ustar00rootroot00000000000000package io.qbs.aidltest; import io.qbs.aidltest.Interface2; interface Interface1 { void doSomething(in Interface2 param1, in Bundle param2); } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/aidl/io/qbs/aidltest/Interface2.aidl000066400000000000000000000001301347155106100310250ustar00rootroot00000000000000package io.qbs.aidltest; interface Interface2 { void someFunc(in Bundle params); } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/aidl/io/qbs/aidltest/MainActivity.java000066400000000000000000000006141347155106100314630ustar00rootroot00000000000000package io.qbs.aidltest; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView label = new TextView(this); label.setText("Hello world!"); setContentView(label); } } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/000077500000000000000000000000001347155106100252125ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/libdependency.so000066400000000000000000000000001347155106100303500ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/minimal-native.qbs000066400000000000000000000006541347155106100306400ustar00rootroot00000000000000CppApplication { name: "minimalnative" qbs.buildVariant: "release" Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } Android.sdk.packageName: "my.minimalnative" Android.sdk.apkBaseName: name Android.ndk.appStl: "stlport_shared" files: "src/main/native/native.c" Group { files: "libdependency.so" fileTags: "android.nativelibrary" } } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/src/000077500000000000000000000000001347155106100260015ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/000077500000000000000000000000001347155106100267255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/AndroidManifest.xml000066400000000000000000000007441347155106100325230ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/java/000077500000000000000000000000001347155106100276465ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/java/my/000077500000000000000000000000001347155106100302735ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/java/my/minimal/000077500000000000000000000000001347155106100317215ustar00rootroot00000000000000MinimalNative.java000066400000000000000000000007061347155106100352450ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/java/my/minimalpackage minimalnative; import android.app.Activity; import android.widget.TextView; import android.os.Bundle; public class MinimalNative extends Activity { @Override public void onCreate(Bundle savedInstanceState) { TextView tv = new TextView(this); tv.setText(stringFromNative()); setContentView(tv); } public native String stringFromNative(); static { System.loadLibrary("minimal"); } } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/000077500000000000000000000000001347155106100302135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c000066400000000000000000000003151347155106100316440ustar00rootroot00000000000000#include #include jstring Java_minimalnative_MinimalNative_stringFromNative(JNIEnv* env, jobject thiz) { return (*env)->NewStringUTF(env, "This message comes from native code."); } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/000077500000000000000000000000001347155106100273175ustar00rootroot00000000000000multiple-apks-per-project.qbs000066400000000000000000000001141347155106100347620ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-projectProject { references: [ "product1", "product2", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/000077500000000000000000000000001347155106100310605ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/product1.qbs000066400000000000000000000021041347155106100333250ustar00rootroot00000000000000Project { DynamicLibrary { Depends { name: "Android.ndk" } Depends { name: "cpp" } name: "p1lib1" files: ["src/main/jni/lib1.cpp"] qbs.targetPlatform: "android" Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" qbs.architectures: !qbs.architecture ? ["armv7a", "x86"] : undefined cpp.useRPaths: false } DynamicLibrary { Depends { name: "Android.ndk" } Depends { name: "cpp" } name: "p1lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } Application { name: "twolibs1" Android.sdk.apkBaseName: name Android.sdk.packageName: "io.qt.dummy1" Depends { productTypes: ["android.nativelibrary"] limitToSubProject: true } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/000077500000000000000000000000001347155106100316475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/000077500000000000000000000000001347155106100325735ustar00rootroot00000000000000AndroidManifest.xml000066400000000000000000000014511347155106100363060ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main java/000077500000000000000000000000001347155106100334355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/mainio/000077500000000000000000000000001347155106100340445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/javaqt/000077500000000000000000000000001347155106100344705ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/iodummy1/000077500000000000000000000000001347155106100357045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/io/qtDummy.java000066400000000000000000000007071347155106100376460ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/java/io/qt/dummy1package io.qt.dummy1; import android.app.Activity; import android.os.Build; import java.util.Arrays; import java.util.List; public class Dummy extends Activity { static { List abis = Arrays.asList(Build.SUPPORTED_ABIS); if (abis.contains("x86") || abis.contains("mips")) { System.loadLibrary("p1lib1"); } if (abis.contains("armeabi")) { System.loadLibrary("p1lib2"); } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/jni/000077500000000000000000000000001347155106100333535ustar00rootroot00000000000000lib1.cpp000066400000000000000000000023471347155106100346350ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/jni/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f() {} lib2.cpp000066400000000000000000000023471347155106100346360ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/jni/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void g() {} qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/res/000077500000000000000000000000001347155106100333645ustar00rootroot00000000000000values/000077500000000000000000000000001347155106100346045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/resstrings.xml000066400000000000000000000001051347155106100370130ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/res/values dummy1 qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/000077500000000000000000000000001347155106100310615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/product2.qbs000066400000000000000000000014411347155106100333320ustar00rootroot00000000000000Project { DynamicLibrary { Depends { name: "cpp" } name: "p2lib1" files: ["src/main/jni/lib1.cpp"] qbs.targetPlatform: "android" cpp.useRPaths: false } DynamicLibrary { Depends { name: "Android.ndk" } Depends { name: "cpp" } name: "p2lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" } Application { name: "twolibs2" Android.sdk.apkBaseName: name Android.sdk.packageName: "io.qt.dummy2" Depends { productTypes: ["android.nativelibrary"] limitToSubProject: true } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/000077500000000000000000000000001347155106100316505ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/000077500000000000000000000000001347155106100325745ustar00rootroot00000000000000AndroidManifest.xml000066400000000000000000000014511347155106100363070ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main java/000077500000000000000000000000001347155106100334365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/mainio/000077500000000000000000000000001347155106100340455ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/javaqt/000077500000000000000000000000001347155106100344715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/iodummy2/000077500000000000000000000000001347155106100357065ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/io/qtDummy.java000066400000000000000000000006001347155106100376400ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/java/io/qt/dummy2package io.qt.dummy2; import android.app.Activity; import android.os.Build; import java.util.Arrays; import java.util.List; public class Dummy extends Activity { static { List abis = Arrays.asList(Build.SUPPORTED_ABIS); if (abis.contains("armeabi")) { System.loadLibrary("p2lib1"); System.loadLibrary("p2lib2"); } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/jni/000077500000000000000000000000001347155106100333545ustar00rootroot00000000000000lib1.cpp000066400000000000000000000023471347155106100346360ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/jni/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f() {} lib2.cpp000066400000000000000000000023471347155106100346370ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/jni/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void g() {} qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/000077500000000000000000000000001347155106100264175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/io/000077500000000000000000000000001347155106100270265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/io/qbs/000077500000000000000000000000001347155106100276135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/io/qbs/lib3/000077500000000000000000000000001347155106100304445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/io/qbs/lib3/lib3.java000066400000000000000000000001211347155106100321320ustar00rootroot00000000000000package io.qbs.lib3; public class lib3 { public static void foo() { } } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/lib4.java000066400000000000000000000000261347155106100301120ustar00rootroot00000000000000public class lib4 { } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/lib5.java000066400000000000000000000000261347155106100301130ustar00rootroot00000000000000public class lib5 { } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/lib6.java000066400000000000000000000000261347155106100301140ustar00rootroot00000000000000public class lib6 { } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/lib7.java000066400000000000000000000000261347155106100301150ustar00rootroot00000000000000public class lib7 { } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/lib8.java000066400000000000000000000000261347155106100301160ustar00rootroot00000000000000public class lib8 { } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/multiple-libs-per-apk.qbs000066400000000000000000000046351347155106100332550ustar00rootroot00000000000000Project { DynamicLibrary { Depends { name: "Android.ndk" } Depends { name: "cpp" } name: "lib1" files: ["src/main/jni/lib1.cpp"] qbs.targetPlatform: "android" Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } DynamicLibrary { Depends { name: "Android.ndk" } Depends { name: "cpp" } name: "lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false Depends { name: "lib6" } Depends { name: "lib8" } name: "lib3" files: ["io/qbs/lib3/lib3.java"] } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false name: "lib4" files: ["lib4.java"] } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false name: "lib5" files: ["lib5.java"] } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false name: "lib6" files: ["lib6.java"] } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false name: "lib7" files: ["lib7.java"] } JavaJarFile { Depends { name: "Android.sdk" } Android.sdk.packageName: undefined Android.sdk.automaticSources: false Depends { name: "lib7"; Android.sdk.embedJar: false } name: "lib8" files: ["lib8.java"] } Application { name: "twolibs" Android.sdk.apkBaseName: name Android.sdk.packageName: "io.qt.dummy" Depends { productTypes: ["android.nativelibrary"] } Depends { name: "lib3"; Android.sdk.embedJar: true } Depends { name: "lib4"; Android.sdk.embedJar: false } Depends { name: "lib5" } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/000077500000000000000000000000001347155106100272065ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/000077500000000000000000000000001347155106100301325ustar00rootroot00000000000000AndroidManifest.xml000066400000000000000000000014501347155106100336440ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/java/000077500000000000000000000000001347155106100310535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/java/io/000077500000000000000000000000001347155106100314625ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/java/io/qt/000077500000000000000000000000001347155106100321065ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/java/io/qt/dummy/000077500000000000000000000000001347155106100332415ustar00rootroot00000000000000Dummy.java000066400000000000000000000006501347155106100351210ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/java/io/qt/dummypackage io.qt.dummy; import android.app.Activity; import android.os.Build; import io.qbs.lib3.lib3; import java.util.Arrays; import java.util.List; public class Dummy extends Activity { static { List abis = Arrays.asList(Build.SUPPORTED_ABIS); if (abis.contains("armeabi")) { System.loadLibrary("lib1"); System.loadLibrary("lib2"); } lib3.foo(); } } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/jni/000077500000000000000000000000001347155106100307125ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/jni/lib1.cpp000066400000000000000000000023471347155106100322530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f() {} qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/jni/lib2.cpp000066400000000000000000000023471347155106100322540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void g() {} qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/res/000077500000000000000000000000001347155106100307235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/res/values/000077500000000000000000000000001347155106100322225ustar00rootroot00000000000000strings.xml000066400000000000000000000001041347155106100343510ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/res/values dummy qbs-src-1.13.1/tests/auto/blackbox/testdata-android/no-native/000077500000000000000000000000001347155106100242005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/no-native/no-native.qbs000066400000000000000000000003361347155106100266110ustar00rootroot00000000000000Application { qbs.targetPlatform: "android" name: "com.example.android.basicmediadecoder" Android.sdk.sourceSetDir: Android.sdk.sdkDir + "/samples/android-BasicMediaDecoder/Application/src/main" } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/qml-app/000077500000000000000000000000001347155106100236475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/qml-app/main.cpp000066400000000000000000000011101347155106100252700ustar00rootroot00000000000000#include #include int main(int argc, char *argv[]) { if (qEnvironmentVariableIsEmpty("QTGLESSTREAM_DISPLAY")) { qputenv("QT_QPA_EGLFS_PHYSICAL_WIDTH", QByteArray("213")); qputenv("QT_QPA_EGLFS_PHYSICAL_HEIGHT", QByteArray("120")); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); } QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/qml-app/main.qml000066400000000000000000000002111347155106100253000ustar00rootroot00000000000000import QtQuick 2.6 import QtQuick.Window 2.2 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/qml-app/qml-app.qbs000066400000000000000000000006371347155106100257330ustar00rootroot00000000000000QtApplication { name: "qmlapp" Depends { name: "Qt.quick" } Depends { name: "Qt.android_support" } Properties { condition: qbs.targetOS.contains("android") Qt.android_support.extraPrefixDirs: path } Android.sdk.packageName: "my.qmlapp" Android.sdk.apkBaseName: name property stringList qmlImportPaths: path files: [ "main.cpp", "qml.qrc", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata-android/qml-app/qml.qrc000066400000000000000000000001271347155106100251470ustar00rootroot00000000000000 main.qml qbs-src-1.13.1/tests/auto/blackbox/testdata-android/qml-app/src/000077500000000000000000000000001347155106100244365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/qml-app/src/main/000077500000000000000000000000001347155106100253625ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml000066400000000000000000000124351347155106100311600ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata-android/qml-app/src/main/assets/000077500000000000000000000000001347155106100266645ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/qml-app/src/main/assets/dummyasset.txt000066400000000000000000000000001347155106100316060ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/teapot/000077500000000000000000000000001347155106100235745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-android/teapot/teapot.qbs000066400000000000000000000113441347155106100256020ustar00rootroot00000000000000import qbs.File Project { minimumQbsVersion: qbs.version StaticLibrary { name: "native-glue" qbs.targetPlatform: "android" cpp.warningLevel: "none" Depends { name: "cpp" } Group { id: glue_sources prefix: Android.ndk.ndkDir + "/sources/android/native_app_glue/" files: ["*.c", "*.h"] } Export { Depends { name: "cpp" } cpp.includePaths: [glue_sources.prefix] cpp.dynamicLibraries: ["log"] } } StaticLibrary { name: "ndk-helper" qbs.targetPlatform: "android" cpp.warningLevel: "none" Depends { name: "Android.ndk" } Depends { name: "cpp" } Depends { name: "native-glue" } Probe { id: ndkHelperProbe property string ndkDir: Android.ndk.ndkDir property string samplesDir: Android.ndk.ndkSamplesDir property string dir configure: { var paths = [samplesDir + "/teapots/common/ndk_helper/", ndkDir + "/sources/android/ndk_helper/"]; for (var i = 0; i < paths.length; ++i) { if (File.exists(paths[i])) { dir = paths[i]; break; } } } } Group { id: ndkhelper_sources prefix: ndkHelperProbe.dir files: ["*.cpp", "*.h"].concat( !File.exists(ndkHelperProbe.dir + "/gl3stub.cpp") ? ["gl3stub.c"] : []) } Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "gnustl_shared" cpp.cxxLanguageVersion: "c++11" Export { Depends { name: "cpp" } cpp.includePaths: [ndkhelper_sources.prefix] cpp.dynamicLibraries: ["log", "android", "EGL", "GLESv2"] } } StaticLibrary { name: "android_cpufeatures" qbs.targetPlatform: "android" Depends { name: "cpp" } Group { id: cpufeatures_sources prefix: Android.ndk.ndkDir + "/sources/android/cpufeatures/" files: ["*.c", "*.h"] } Export { Depends { name: "cpp" } cpp.includePaths: [cpufeatures_sources.prefix] cpp.dynamicLibraries: ["dl"] } } CppApplication { name: "TeapotNativeActivity" qbs.targetPlatform: "android" Depends { name: "Android.ndk" } Depends { name: "cpp" } Depends { name: "android_cpufeatures" } Depends { name: "native-glue" } Depends { name: "ndk-helper" } Probe { id: teapotProbe property string samplesDir: Android.sdk.ndkSamplesDir property string dir configure: { var paths = ["/teapots/classic-teapot/src/main", "/Teapot/app/src/main", "/Teapot"]; for (var i = 0; i < paths.length; ++i) { if (File.exists(samplesDir + paths[i])) { dir = samplesDir + paths[i]; break; } } } } Probe { id: teapotProbeJni property string samplesDir: Android.ndk.ndkSamplesDir property string jniDir configure: { var paths = ["/teapots/classic-teapot/src/main/cpp/", "/Teapot/app/src/main/jni/", "/Teapot/jni/"]; for (var i = 0; i < paths.length; ++i) { if (File.exists(samplesDir + paths[i])) { jniDir = samplesDir + paths[i]; break; } } } } Group { name: "C++ sources" prefix: teapotProbeJni.jniDir files: [ "TeapotNativeActivity.cpp", "TeapotRenderer.cpp", "TeapotRenderer.h", "teapot.inl", ] } FileTagger { patterns: ["*.inl"]; fileTags: ["hpp"] } Android.sdk.apkBaseName: name Android.sdk.packageName: "com.sample.teapot" Android.sdk.sourceSetDir: teapotProbe.dir Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "gnustl_shared" cpp.cxxLanguageVersion: "c++11" cpp.dynamicLibraries: ["log", "android", "EGL", "GLESv2"] cpp.useRPaths: false // Export ANativeActivity_onCreate(), // Refer to: https://github.com/android-ndk/ndk/issues/381 cpp.linkerFlags: ["-u", "ANativeActivity_onCreate"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/000077500000000000000000000000001347155106100217615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/000077500000000000000000000000001347155106100272225ustar00rootroot00000000000000aggregateDependencyLinking.qbs000066400000000000000000000015661347155106100351230ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/aggregateDependencyLinkingimport qbs Project { minimumQbsVersion: "1.8" StaticLibrary { name: "multi_arch_lib" files: ["lib.c"] Depends { name: "cpp" } Depends { name: "bundle" } bundle.isBundle: false // This will generate 2 multiplex configs and an aggregate. qbs.architectures: ["x86", "x86_64"] qbs.buildVariant: "debug" } CppApplication { name: "just_app" files: ["app.c"] // This should link only against the aggregate static library, and not against // the {debug, x86_64} variant, or worse - against both the single arch variant // and the lipo-ed one. Depends { name: "multi_arch_lib" } Depends { name: "bundle" } bundle.isBundle: false qbs.architecture: "x86_64" qbs.buildVariant: "debug" multiplexByQbsProperties: [] } } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/app.c000066400000000000000000000001551347155106100301470ustar00rootroot00000000000000extern int foo(); int main(int argc, char *argv[]) { (void) argc; (void) argv; return foo(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/lib.c000066400000000000000000000002441347155106100301340ustar00rootroot00000000000000#include int foo() { #ifdef __i386__ printf("Hello from i386\n"); #endif #ifdef __x86_64__ printf("Hello from x86_64\n"); #endif return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/000077500000000000000000000000001347155106100236275ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs000066400000000000000000000036271347155106100262140ustar00rootroot00000000000000Project { AppleApplicationDiskImage { Depends { name: "myapp" } Depends { name: "ib" } dmg.volumeName: "My Great App" dmg.iconSize: 128 dmg.windowWidth: 640 dmg.windowHeight: 280 files: [ "white.iconset", ] } CppApplication { name: "myapp" targetName: "My Great App" files: ["main.c"] install: true } AppleDiskImage { name: "hellodmg" targetName: "hellodmg-1.0" + (qbs.architecture ? "-" + qbs.architecture : "") dmg.volumeName: "Hello DMG" files: [ "hello.icns", "hello.tif" ] Group { files: ["en_US.lproj/eula.txt"] fileTags: ["dmg.input", "dmg.license.input"] dmg.iconX: 320 dmg.iconY: 240 dmg.licenseLocale: "en_US" } Group { files: ["*.lproj/**"] excludeFiles: ["en_US.lproj/eula.txt"] } } AppleDiskImage { name: "green" dmg.backgroundColor: "green" } AppleDiskImage { name: "german" dmg.defaultLicenseLocale: "de_DE" Group { files: ["*.lproj/**"] } } AppleDiskImage { name: "custom-buttons" Group { files: ["ru_RU.lproj/eula.txt"] dmg.licenseLocale: "sv_SE" // override auto-detected ru_RU with sv_SE dmg.licenseLanguageName: "Swedish, not Russian" dmg.licenseAgreeButtonText: "Of course" dmg.licenseDisagreeButtonText: "Never!" dmg.licensePrintButtonText: "Make Paper" dmg.licenseSaveButtonText: "Make Bits" dmg.licenseInstructionText: "Do please agree to the license!" } Group { files: ["*.lproj/**"] excludeFiles: ["ru_RU.lproj/eula.txt"] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/de_DE.lproj/000077500000000000000000000000001347155106100257145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/de_DE.lproj/eula.txt000066400000000000000000000002461347155106100274050ustar00rootroot00000000000000FIKTIVE UNTERNEHMEN SOFTWARE BEISPIEL VEREINBARUNG Sie stimmen zu, dass Sie nicht mit dieser App auf Atomwaffen zu machen. Sie bestätigen, dass Qbs das Beste ist. qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/en_GB.lproj/000077500000000000000000000000001347155106100257265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/en_GB.lproj/eula.txt000066400000000000000000000002251347155106100274140ustar00rootroot00000000000000FICTIONAL CORPORATION SOFTWARE EXAMPLE AGREEMENT You agree that you will not use this app to make nuclear weapons. You agree that Qbs is the best. qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/en_US.lproj/000077500000000000000000000000001347155106100257655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/en_US.lproj/eula.txt000066400000000000000000000002251347155106100274530ustar00rootroot00000000000000FICTIONAL CORPORATION SOFTWARE EXAMPLE AGREEMENT You agree that you will not use this app to make nuclear weapons. You agree that Qbs is the best. qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/fr_FR.lproj/000077500000000000000000000000001347155106100257525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/fr_FR.lproj/eula.txt000066400000000000000000000002701347155106100274400ustar00rootroot00000000000000SOCIÉTÉ FICTIONNEL EXEMPLE D'ACCORD DU LOGICIEL Vous vous engagez à ne pas utiliser cette application pour fabriquer des armes nucléaires. Vous acceptez que Qbs est le meilleur. qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/hello.icns000066400000000000000000052421431347155106100256230ustar00rootroot00000000000000icnsDcTOC hic08Ðaic10 Ègic13Ðaic096/ic12›ic079êil32Šl8mkic11 Þis32os8mkic146/ic08Ða‰PNG  IHDRÓ?1 AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs  šœ@IDATxlÝÛ¶m[Q¬a@DQÄ…÷$ä– @»¢<°¿ÚþÞcÖ5¦YÊN¢FFFfm½>æš,Ü_þ×ý×?ýéO_úÒ—¾üå/ÿÙŸýÙÿþïÿ:~å+_ •D¤#PDbÄÿ÷k‘>kGb-;&ˆ—E<Á¬±Ål›ŒLùÕ¯~ó?ÿó?²Þ‰»Á=ñ>â+Õ˜m]Ü”š…l…öJ?ÿó?ïHlC9^n7$PÉ#²Êß±®MIŸF5ÛdZf›S`ä@Õ˜Fâ'¦¥U‰á¦¨>ÝçiÃÿõ_ÿÕ2r|z`]i0‚lj]H¥í°ã|²2´Þ#åxdþYÉJ¬äaÇz1ÂÄîÈ–ì8üà?P¨3 k#Ñ@‹ÖY Yd“"åÝ!Ï–V,ÑqOßImÂ+ŽB¯¬ã(ý<į´^<Œ]°]KÆ áÚa?Q²#gYÔ¤?FÏz*ÍI 2l Ðó¹mo²¹ÚS #/2™ >»¾°®¶]»RëÉ‘€È¶ªc%&{••hº©jÌi~¾/ú|/ ‰iäÚ,òéxý˜¥¬$;–›Õu <³ÅhÙãJ€Ü2L#‹Ó¶2•®Í¤À£?î]ö‰âo‡ÄrzÙSö¼*µÊd÷Ù9À³ ³*(]~Ó}?Yl]‰ÓDêðºð¢Û!g¢ŠÇÈáÖ^ËJª­Ñožx e›l%&â6Ñ.b4ž…žèóU #¦.Y‹À¬±cz¼#ÙGýÄíÅTøÈÚ‘yâóÁJøJr&•ä@ž.âQLà!gBƒ„3 |£[&™RžôÄ—#ù;ªš0: ¸€µÐŸO‹¨Íìú´¼>þLI‘5`:‘ŽÞoŸÍÄÓ[Â0ÎÙÆc1Pä)k‘‘”#jíwßù ëA‹z»Q4€¡²è´ÆÃ‹ËHÜùÀAyûÀóe-=<Ù£K#{†Ú)‹&Â@'v¤,ÃiÚª®ôø4F×È$ã;ŽÉ“2 »H¸)ô@žø5jùãÿ(÷Vô(ÄHâÆ!¼ÄõûRJéñ»i²¦Ëø4·!Æ1¦a¤ ÏgP9Çšs!ʱžd¶tt+Ù©„T…§É§+µ}™g-;fèØ8ÙZ½(µgN ôx׋Jò‡.¢q)Ó?•O%½x$†ÿÜWÂw”{@#*•‰Ü8Êž3¥‡&’9а¯ 2nŽ¢F“¾[çœ2>Í2@³Ý‹‰€…‰0 üÐ÷Op+c íRŽ¢MŒYÉ6ÝÏÍJ=“Ƨ¯„ L™çª5ÚR©'ðÂD¡K®å!Ž$ð¹Än :Ç©áŽc“ã3>Ʊg¤Ý~X )×xj8òÀcͰ{>Å×ëÈŒ@{âùªµGnP¨Vò’aˬØÂªÓðB·¡Ue-M”ÃHÑ-²Ú Ø”ºš ›•ŒÏ<){ždx‚rGRFb"µ ÀªòžjKbXKƒÒ;™§l¥p;4}³"u äôøJõªô¨NŠ”ã•j”EŸõÚiŽôOý| "F^tG2‚ó‡fúôžÄ— >RgÃtù´º#Y9=MoUü®‘FŸÀ3~{ˆ›•Rnçz7:sEL(UÀœ¦{5înɳì²Aµ Xh7‚Ìíž²7U5fV@!«Ë&ùÙëõåJISc#00¢Ñ+uG ÀJÖNvzÞ#”0a¹jzÇÜÚ[’`Ëk™>²¾ÒÔ^‰’¬Kä¿)ñ)ïÌg-@7ªËãÅX/¼@öj²láÈ!|÷jÐWþð‡?(¼ÏßNÖŒ©¡æÛN©IÇòùxÌ ÈDvì¡è­]&˜&ò¬öDǪÂ*7ß1Þ-Y˜ h€fHi+Qo#d‘ÉZ0ð¬<)Çl$Óä¬WUŽiCLwÇ“‰d‘å1MAb„£mex$ŒŒ™(«&㵎6´Ì>šSmÖi{ÏêÑE/;¶I¶å·KV©Fæºz†µÇÓ¬V’‰}F{’í¦ øS¢ì b>YËvh´#™^GÀy~F?žÏÒ1²a3Ò`¹šiÚfÃTuÙø6¬…˜‰,v½j ˜¬x´çí Û¤5šÞДñòvÎD.È2§É6°j#ä"Ô˜œ»ÚZVÅÀeÊnãØ\G˜F~9ÿéCp+ÓT‚UÅ£=†ý’dë˜&°j]ÍBô^…µ^ < $(e sßÐfaD¯° µèÂÀ²§Çhþô?ôknÇde½í“3Ãð”ùŽwÄÈz-CV»Þפ¦ ‹|g×Ñ}|ÍóTëÂôS˜¾1Zƒ'[U ·l¢¶"È¿FX‹èHŸ8ÞQɺ*É·y2™€RÕnu1Ôˆ¬×±FYlbsã7¯ÑQ.RzDF›"L½d|TUë*#²–fŬ% %2®kx `¨ ¬E¬%G‘ÌhѪ< &ÈZ -p] îAÞ-øô·§Þ¬ò̇,pV|Þ½m¥ÇÃ@¶ÓwÄOiXqÜjî¶jmæ¸jŒèò. ÚJ€R³e¥LrPrìuìÛ¢‰ª‘€?Pù}°êÍ`KÖÜ@ãháJ@UVJ{« xbjI&Û'F¦.5Ã]2Á‰›˜+ŒÛeŽì90lÕ|â³Ê¤'ÉM`ôŸ3ªø6nhâ0AÆ€‡ÉêJ/·CdʧfSú $5XÔÙBkö…=/d<±‘OÓydñaÀ7©J†‘Š4·¯LC ãad&˜/òqT*OýÓŸší[õzÛãijL +É"܆€À´ ”Cß^Jò.Õñv£Çëq 9TÕŠdå¹ |‘R& ã›%´mL0}Lƒï» ÛÈ'=’C-ô}uÎ9qdžk×;“Z6ëö_o†L€²®$×wN&ŸwqÒØ^DX©þmOéÏŽ‚ *ÐÍËJxd Á…kãÅÈ4>E@î¡'H³Œä`FØX×#]5–•2|èOïžSU%0‰ì.‘rß­DÚÓ×%= «z-Xãð‡#žX—)õbš‚gUc²0åùGÉj= M• ÎN¿è3Í~èó¶¹I—ñÈTE³“9rë)Äg…¼J¬Ô~ª hDÌ]M¿Í7Ñ?±ô@[ Ý´7‚ ÏÒïŸÀ™71g홫x-áJÝ(=>C—Ši¼GAÓ [2™.³G‘aæ˜567CUÇ Í°Ñ° Û2âHUL½öõCŽÉó^^#±ØtXWn³ª×ш­¡7¥Œ¼§ÇgâÃuÜ@ãÆÕÛÐÈVª…gVÍê=‰œ ÝF“þð‡9) rÙ5ªÊ˜Œ€ûE×UI5±0~íJd‘Rî&eUz½zz8%CŽjÃ܈{dªÄÞ¡ûAÓz&”&ú€Í¥l(MǶ}<ÎæÀµ/ß2;ä@0«zÝÇVuž¦c¶eGì'$’ŒóVD]M¬š§×$˜ù6líår%Cíý|æÀ™  q9l½zå6Qª1óô0Ix<½´ô¬T9w”'CÂŽ× ,·FÇ9gr÷ªžN¡0 ÐßÑâˆÞ_Õ0†E2S'î]Ìdzú´7^¾I¼¡{ÿ€<ËëÚ•ŒhI°à&€Z$[É{ÓQo&«”˜üñŽ ¼F;–‘™Oå•ê­„ Ô~ŒñÏî¯o¸².¹õ²Û5#ðÌGx9R 8ölÓq g’Ì*âR:R’ ‚b³T+Gbz7}ÿ*ͦÐÓ8Æ8úÔ`ʇ{ñ«æ¯…À3z’øZb³dŒcþð)áÏ?yäË"©¶÷ÔijðÓFIÃOS{@#ðûßÿ¾¿Ñtù^¾º4Šu!ÉdnBInVz½HØŸû[òô?A‰ÍMö*<&0gh碣ªcƒ`ng‰ç‡¡Ï8A¶YÑ;¦Œ—óÔ¦tkxí€hPkI¯±#Y )Ï ¾?Ú“Á;æÐ>™g›æÞ$ >YþáJri2¡¹Ž¾Í^ÜkhÉó±o%¥x½Ù: OÏ›Ö8Ùr%þu-¯ñ.ÁZDû”9Äh©ëüA?öÙÿüsOdž¥“{ ­Õºû„¸/8ˆÆi$Ëœ°Ï¯Ñiâa ¡µä#gRéÞm†r^{;ë²p¸^y‰³j Ì¡PÒ(2ìvµ;’Õ+kÇËIJpŒ—s9+|%âB‰l-^®Ež,œ›B +Å”#,O€„SÊðýb´õŽ”ϰ÷£xèóßK›ÎCCÿh_(«zkÄœ§ðþÐçàÉà÷´›ž§jǧû$J™r‚Fà1‚ùü)U•ΖýøÖOÌÆ8z4®3\5™l€l‰@ÇäFÀ uUµI7Ÿ‰Þ}[hÉYho¾Ïÿ¸ž”XûH¶¯ È•Föø¬aüa²Y«ÖÞÂ1=€ÜPÇFáHXI/ýS<)Cþ™L`ÕĬ­TTÊ¡çF Sõ6\ P•ý'H#'¨jbGÁÓ1Ž‘w 8AÓ‹|º”õVMOÖs¸Í‘oDÈQµ)i`½ËÍ-GžûÏ™¨†{Ò½^¹×6­cÏÈJW&]!^©.d‹Éê’+µäVl Müä8êUÚОƒý[,7šd­4¬ZØ¿«=Â×—¨’c‚Å0q”Ûœ¦j¯E¤ên—ìfتz{˜ø]$ ¯w –Ï?Ù­¤‘sè±9ûh'`¨$ÂHÙCk(¦Qæ€Ñ§)µËh§Âéåöì c>L¯Ï![¸8ë.jN¡W­¹*Œo¡p;ÁµlLLʬzRd÷ýéMGÊn’y äŸ!A‘`ùç HÙµ7š@‰¦ŒQš3Ûp%Uí‚Æ«lÃe]JpY—0"gÀq 4ÓðGýŽHV¸U™·ölU‘™ëª±zJ"M`XïS|}”fÕŽ×ë(’àï ¾’œ3ü<Ÿú§dnú“õ¸Êí  #zsD$A&1X‰,ž¾Woí²ó§oÇΤ\v“:«Â5“Åp%’IÇ||U‰HkµYæx]rèèAÐÔN†,À™8Æ$¨1¼v†°Y2q|£ËUu9úÚvŒÑ8Ùœ9 E×ÑØ`‘IGz±àÊ|z>”˜œéË5†É´¤Áúà`šF`æ–¿ê6dáæº4â—ã1íÓQ·-ºð=¢ª¨÷¶¥\XžÀÏa2|é3Ì-¬ªÔ‡‚É'ññ…* ýõ?€p uNºa^‚«R¹IxæϱñJŽá9!Ròðr| ½€}×ÊE]SÔ‹'Ç:[¥ü1yæ37bTj=2-µ÷FÚAi–úThjlnKnI):Êl“±ê— ÃLÈ”tõôÇvƒãsM8ò1> ÆO ]PUäœ,M*OØÐZns‘µlVWèH“­œl]ÓÇL ˆ™4˜m̪Ž3lVG Å–ïÑEö`wÌs-ŽçU;ÿñ¼s¤¢‘²ð9eêÓb‘24£öŽr2 °×EÆóŸ¸…w EÿÂ)>>”¬0°Ì§ª®1k<÷yªs „‰c(¹ÝSyöÒãýÝ+MæëÂÓÜV™´€,òi“•ªÊÂ>§íŸ·÷Üš+t íý¬ÖU愇 r Ë6Avlt»¹`-•Ò„9ª”F+‰z×…¡‰ºÑãu‰ëòX?V^›­ªª« «>ò“s³áöÄèê¬ ›Þ|ýfÏñJê8/ïD¯E^ £äEfp¶x~ljŸX 9ÖÒô|Õëç#¦ì˜Ö%|ð¢éÌñr-ùË ‰$ã0Cà±H²H&°\ G¼–B ¾Æ<ß•Oˆ R¯«õ{²7“Cüåz[㩜R ”ïcŸ)RËÊ"ÏÄÂȪvëxËôRö´É¬­Š|™øPŠ=Öåzjk­Z"¹‹d6вu3QJ騽-{Žø42Ùž©£Rʪ™›UÐÎŽ‘-O†Ÿ¬éJ5”Ébd³ä‰Ûa;·UÓÛÊ ýY<žíVÝ€ê Y;Ä/#[u ¥­æ WŠ/cDš²c#wîI¦—‹ùô:ö$æ)«&ˆ!¨=O]ŽÉ€p˜ e¹’Œ§9„e2{ûcŒöHLß&üZ`¶µ4+ ,à¶:íH$;w[å˜tJ€ ìäØl.ÕÒ0UXŽz øcôþÁudRdAÐPØnŽJržpS<‹•Zæn¬…C#”r–•ÀG5· ªÊJțӧّ27Œ’iúŽÄ´@]ý“\KZj—»T¼,ª–ûäÈð²ÈJUðlJ]0AÓU§T] O÷§¤%²öGòZc˜C@ì:‹l%™2¼1[Lµ‹TН%¦·ÈÝ7…¾Ø¸Ž[Éqƒò™òõ]²ÎyÝ.ªø,º•c/¥?~à[«Ü¨/¹.œØ*gÞ~òžÿâ6“ˆZÔ±ÐÛñ{"ÜbäB ©Ë±^ ò¥xŽJ™´¤5îjÓ(a`Éa½ít¤ï˜ ‡€Ô¸R„x&JÂñ™ðú³VÕáæf.ÇÔ Z#óm¿ÀŽ”¢v`V‘’•*XTÚwSkËû—_àlk)kœ çãw Åd)#·ªã°^¸Ÿ‡^?Ǭ ÓÀ;jG–çÿjé?båýj†5°¨di1™’h°a¢'â^“ÙLïH¹^@(=/ÿ¬dþM$‡ô>uçܺlY¤œ2FY)-,ÀJÆÅYëýsŽï˜C&Uù3l(IŒ„×É6q²™hŸµw_ÇÚ-JŽöc#“-o·d5Ê0 ë½/Ÿyï7ÞMYÍV®*ÏÆdBÓe%ŒÒŽÖH_îžIVÍÒèØ2p†} yÎ)Ò ±È°‰x¸C¾þT!þ>¼D©?x9š! óò@¬·×àP#e¸=äÙâU16]µÈ12®xÇ»‹^µY9« ?‡Ç÷‰{Õ”²J˜ƒ…_Ò÷¿ÂA•!¾¼¹Ž.Hyö~Â'Úoâun1%ÛFĨ¦ÇMTêßJ a bdkÇ'ƈ)a|Ù·a8Ü·$ ^c?TŽ¢ëlÏr½ù9ÆÈzª€ÒÄLð¶Ì™Þ1ŽtÌm|sWÊ6ÜQþôæUã( δåXLѱR™‘’Æþtëè¡8î'[•2Y‰FÔ%ϳ_A)ñ+¥¯Eæ Ô'T¯c¶Á>ã“ɵËÜüÀ4¢ÕöaBà —rÍlÛ$1,Š^”ÆáõŠf1r‚øJÆ ¹<Ï‘µSÖU ž@Ö¾å“MбõÚáé>IKÎ.+bš{wmÐfÕ/t 2ŒY€#Y»=Ås¿R 5Èl‚ „Ì®‰)ð‹Fœ×HÄÚ¸¼Ï>ÁÛäh,-ãÉðZàî´\äªè!V]£c?94•ùIëjÛ­×Î|dG2ÓáÚÃxÛÖ{?V ™Üˆ5n.ç¬4¨–ö—MÏVuþiZVr ™žóçÊJôd ŠŒaB ó$kVÙÑ•‰i*}È-,ÓËL;ÂU÷u†\»ܱv8½FCÅS?ûTê:4m[ÙºrÓ^hìš›K©”ì&7‚@Ko²X‹êzÏÇé,7޳ꀪf^6îû’l-JazYDŽÇÔ4ƒ8º·’>>F®·¹›ô(' 赘ËÛ‹&Î6O<Ã}¯oÛ¶Ò¢T¤”ÛDôÇcšÛ,ëP"“Çå ‚ôxXÖ˜aw—E-ô4é)Ÿâù@ï¸I¸’^&pkl(f†dý”–IÖÐY)aÄ=4ŸZ(UeÑÎ97ýi}ÝŸLI¯ w¯¶]Wy•n¬¤7®H¶UÏÆj•ÕŒ ÍH¸Ïƒ»?ô·z“hˆE½›¡«Æ1ÉtÜÒTÕRµ}"åÇì$_H•b&8çIS´§ÜÎõâ9×…Ñ+“8´IÇœk[éÐ+˜¨Öµ»#õæ/*2 FbÇZQ—Mf;çªzáë%X¯ÆÂÐzÉê ¨âéåwqÄs–‰k÷m‚ ÷ÛèÏýñ·sr+©ºQ½1Jô02YÃö1w‚Zî®.B¦Ÿ^ž”ÊÄ1¯ʨ[…ºU2j!Ù½U°FÙ³d=dÏb-|¾0õy ZîGÖBÌ‘ù4h‡öIÀ\P6V]tÔËÎ$ãÈPÐËU?üûÄä|£§Ilz¿Rš¥”mSº«ž;Ò³Ú†Äu1© hJæÄíÖJ•(|,OY¯¬Ý/hRve8qΪ÷‘¿£,2Ÿ,ÿ™tl"eÕÑQ¯ªÀÚ&H£Ü¸ë7:qírÊ[Ÿ8A×ló5&6¥ žÁÏËP6Ågo·cÎå³.ߣþ¹‚ GÓQ£°lž7 ãªÓ+ñ©7CùOì…è¨Åå“þÐ"º6A ´¡ZZ£×nJ-{ò‘U•,­AŽ­!wlP™i‡lsƒ‘íÖ2» A±ýßÄëñ&“­¤4çø|dË´çÜp™y€R(ebCÊžg#fî$Ã0ïsáÓ=‡Jµ0¤Ç‹Ú‰aß#ELJù”•€¬”ª§«O3O™F%Y`˜ø¼Æ¬ x½…t¤·ÇzðéI…•ªêí p4É­bžúIÚóϰö˜2˜è3¦´·Ì_0§ïߥñ3¶oâ|r€luÅsÈÖ‘@éq}½.dípor·kéú”@ž›¸^2çz{¤ù;ji.<ÍÜ8Ö¨«‡–?Ò‘a2¿Y¹¤ª€ñcxŸ/2戞0´Ÿê-CÎy<9ÿœaK CClJÕâ•Òì8óÀ]…‘)ç ž=¸F2Øò¶Â$[¶žWEéÞÓ±û~á'LOÑêÙ5 O_‰RîY§1Æ ŒP|v<[B vL&±ª—),‹>¿6‘ko 8´pL ß8’¬Ú'Ëʱª ÝtÕÌ‘®) dæÕÑn‘rQ—¬TÆëÛðxž‰sÈs½€–¶ºIb»—.2 M¥ÄµW’•<Òn‘2r²¦G’µ’ªØ8UG¥‡> Ö(<ù®ö’dU^U+̺¤%óTj\€ƒ£§áâ1d)Óß]¯Y hÌ:‰ÇÈÆ›Ž¢£ñ@˪M­ëvƒUmiP³˜$`#ÓÄ÷MÿÈÏÿmˆFÓЛÕ'½®ª–¹­ˆ Ti¶@³æÐo‘õ&ƒ›B g•Ò±èH@);òT‚ V½v+©¶›,^Fï«^™¾%a@Ÿ­q{Q0Mo[½ùlÀÏm÷R¥l¾rÞh‚¬šžàö¯q2¥U•zÁSV%–ó´LäŽMÌSK×o¥”Jâ˜>†þ°&^Îá8'ꬹH¡`d¯ ÿc'=Y‰£ÜOMŒûˆV× «ôU¹äÖa-€,sKïh›ˆµ3O¯‘L‹è޹%@V•+ñ©KU|‚”ké(/Ⱥ ÍzUk ÜímN9ÆclgX¨ æóp/¾éh*¥ôx="dæHWðiö!æƒxYÌ  ¼ ¥ù0ù^¥œ5b dŸu†ùÔ%Û¡AuÍ„’ƒLv¤™CÇ‘ÉTsãÃ<Ï4ñåó²fZöÜwaм2¹×=k¹cp,ÈŒé2eüo˺Æ×»*Q#“‰c’­dåƒ×Úpû˾çÈ€².Á–(ÉÈŽäÓܲ¦xoÒ´Þí†÷<1‘wæ#2)chžÊ Ô…l32‡ÖVêès„wM8†É”HŸ ýžIž]Yµe¦TÀø2FȘÜÚ'&eUÊièÅJøÞÚ@C[#šòÁ°)Y5·-µÓ,ÙO§Ôw@jº:}„š Àw? ªŽÈ^S]ÚÉ6&, ¥ªit‰ÌY%Ã86+2F;žF[d•2§?î蓶ðÝ«~wÁ ÂYñð6z¿‘Ä)p¤—'ƒEâãþ$˜­¢£^ ¾' œæ÷‡*¾.27ªSÆÄ˜}æ6!p,FRb”ºìd¬s¦d;ç£1ÆëѸ<7:AG]>zwá3¯C¶v;ˆô2üyûëÍð&1¯¶6P»g(;úó“`aFÕŒn;ýü {!èHÑ`9 ê‘ Ǫ̑ݳY÷= ƒ×¸j'KéØh‘uÉÙê+‚ø4Ès‹w)Çþßý5Á¤O1«®{ r†&†Jöȡ.SeG¡¥®ûšêDÊĽ…tÍV)Y¶¬ô"›î+ÑÄÈ­1ÐÙ"é‹lcjQEæ ˆô›eŸG#TeÊpûgX °LÆŸ¦vÇJ«bºT¥–_;Y¡ú…wÛÞõga¡>ø£~®az w Ó®F65¥R ±Õùã1ŽeQãcð…_‘ùgظºð5öCجdV6¹™êdåºu½Ñí<[2½n‡½ëŽd C•&Ë37í¥XKØ‘FL#&îX;LÐÁˆFäPµÆeb|2z¼˜'Æl«•n?1™P’ë•Ež¯ß¶Ê(ßô=&5ýËUeŸw¾5k™õí“©öYÖ‚í!‹4ÈÜa]é'H&÷\2y Nòɵ³F Ðgûy•ƒ “iÂêrìÂÌÆ‹66ÏgÌv¨«}hÒøöþ½OçKËñƒ .æªÛ6 ²Þªp†”=–‰gËpLHãþû]½ª 2lx?$÷3Ç·UVJý>Ä ½ÛÙ2"dGƒ0­´¡Jz³“hL¶m–j©*7ѸÌãÏç¯rï7æƒcrÚ8׫…æKƉIß¼Èá} 57[™ Mã:NãØæ£/ðÖ«J–2ª¨‹s¥™;’Õ ´Œ}ï+ÆQU$Îg-ù+Í0ÁUZ׎[)+þY5h¶ù éëõÙmO8A{nôýSŸ·¶AMYWË;zbp“:öU1Ë™ÈvkP-­¤ Š4"1]ÀTâëUjùõ&#Ð(‰õbfUéÓ©î)Dézä,ô(ÉŽy)å‹ìJÚ‘»s-}*µÈ_©YåÖ§ih1 B¶Uík‰¼5[ã~¢<5&¾ó>l»Y”í@Fü#A-H/D†² ‘ñº,GzDŸ—0‚¦xÖÏßã~€³R[!û,»it”»OÁ³ÞîÈg…ì( G¶ÄÂQÆÈ™ÇÀ"@Êd‡}ø0^ØÓ±p$¸qþOßIJ2rüÄJ6tä–ÌÓ±)ç ìª w¤n^¾™ndzÙûä“èKÂQäLÓ§Ò‡Ôì>xæ@xHÌ•’!>à1¦“탡W’Ÿî×׆m¦F™ œmz¸‰îe#RûéeL6+L|>pË4±RyækÉJµˆ'ëÊŽb‘m·&nz#â‘=I¹M䬺K½˜‰f™¢]VòZ¦)‰Çð$km¸®ª”%ÇÏKH½ر.G¼¼hçŽ0Y'jt‘À|¦Çœï‰ÛÚQ¹kàyÉt“5à>f'ç“CÈ»Æ÷7­^V›eŽOà@–-†ÎV‹ÆJès¢I k #}fŽ[&[Œ_4ûÀ¢5âåôûMÒ/(Ëw™²•bö`;ÒØ°¡güûm«kW#ÞãjmŒ ×Kœm]ø=XLšGþzùvG€’FUvÜÓÈo\™OúcT;—•€òĘÈñ³wÌ!g¤­v#¸Md‚Ö¶ùq Ÿ=½Üøà#¿Þï Î4¨:MLÇEÖ…¹”·1€ÙBÉzMaí¦ â¬dX¸L]»ƒRnueeVúªp¼£’ì!ÂîXî)Gæ&/4žžâ³³²¼^ÇÉ'ˆ„E¼^ÏA`jß >Æzæûú¶vìÉÔ~h7¢¡YÁ ý•®®ø˜°®=¢¦ð4ÞtÊöÙ”˜ã¡ºSf~/IÊî>[佯Öž²#É`¥Þ–œÛ0%¾+Ð`ÎAƒ‹y2Œ©¦YÀÈpJ‰É—#f¤’PâŒÏAÆ´J²£~Ëjqh([f³”r“²åµJâ˜>O!,«Šx9,O|¯:ÙªµäÓÐiŽïÛ9ÁY&ü5†é;öbµլȚR&ÆC‰Ó”»2Ç1écdÇÏŸ$g¤_È@ÓÝ»é€vA&m2fSúÝ®JÖP€§)Ž….‚zø óI¶¼‰5ÒäIm÷šO@unÌ{D+9äsîãÌÍ´mïÌ1Gd?¸ÈÅfo¤’S0á Ì=V¥†1‚ÒçíKNªµ+¥|T'µ€|/Ùè”]|S”º&¦v <Ï4™Èªa†Ê€Òìqy”eš˜à‘Y}Ј qŸ_ô[oŸ>åvÃǨÖëxw9“õ$«–Uźö¨zªº0ª€Ü¶äJ˜LæßM7H¯Bèx¥â™л)0¦Ræ0}_(@ÊHÙ17+ÑÀ•^? ÷ÔIL4âÕö`dó€{!îJQc A2· ›p2$ Úµ.ÿíD|GÙ¬¬àû÷f¤•èkámøT^Z w”UÃF‡µä&‡å#èÖ ë…3$}üu9Vj;òt”»ZKÂuÉ‚Lf"(ËOå4:&ÀäS»£má<É0°L¨=‡Lâ³Ú ‰{þ~ž)ÙÎa•ÞÃÙt@°º?k²²}úÎ"ÜÐp™Ø;9Y|WCP¾þ•),‘ànj Yô쀶! sNùùTê¢t«˜Çì IUÉ b¡»sã>ïŠQm㎲õ¶O“§#ÏÄ{{5kOÖ 6üœaëû‰Õ<bL¹ó4¬éiœ¦ö¹) %Ùç‚71-há(öp:n:«<aC¶€ï]X•Ó“1Iܶen@qË0Ùæyïß•_/MW*ò‡õê"Ûæü.ÞM1íCY— WmîKŒD³Ç õÖ~ty…‘Çéx¢ðø=KO ¬ )¯1Y/}a<¦{z±2—=ˆ6“‰= ˜²)h"“9#q> ß4“•5ª–i`¼£Ñö´dL$Ûܸõ0b&>’g @¤7zÊúœËµìvHá(zVrVü‘MÙÜ % Y<+|ŸŽ’#>9€¡i\&2r 9æl“|l3LŸ ºœ2r#€b2ÀP$e¤ìØ-"iªâ#åO3ÅšI{)),aõU1ù6ƒ#ê L{·éX¤4Y´÷ãq~“µÓBŽœRÖÞoG¸>Àü³íÎa&Är 󋜫#óª™o:F¨â|#Ú$Y9hn7z ^ÍÒÜ”2ñ¦×ˆÜáÄkD›ÔRÞ’Žp2¹v›øßÊÁ¦l¨WH–&±öÝÂ1¥ks‘ô{p2¶~ºè;¶ÕpíKÓÓÎ?¼å#ëÝn¤J¹ö6‰¤QrG½‹JH‹dr€r]«¾þ ‚³Ó`^‹ðÏIÄJ=_XI.ªÎ¤c%-™T½Iiﻤ×èd5b˜ }lÂ'½%8ÚjCk÷i5z?f<ÍJ™XûÁô}ÇÔ[i™­öÌ[rW£Ñ®„É¿cþgÿí©‹¾Þa] úÐN#´ãWâÐ2rn²v>€•(§Ñ^#æX¼]-17/w¬´Œ.‘8ãøµ0i%]FUpˆ·<&“žCŒê£=Ë„ÛJ&Æ ˜låÄ1³:‡¨ 7#5‹f( ŸåU½ÍÃçX£j@NpúŸ¸?òª²¨šX¶FHÉQæoJ8XlnXf%×ÊðíÖ³Å`¡KfÕÐ<Ë•Ü=^ûi{âŒ|ÂɪŽ-¦£}\á-9Ï ÓVûá$˜ÏlõZÉ’˜ü{P)•ðMÉ_‰LµK)‰ý4Hø)ž·V ΰYŽ™;k\WŒ¬K¤ot%̪”0C¶|ÇJÈÆ!¹Õ(·LþŽ·'²™á§Y"Tjý0޳Р{¾z¸IÄ"\ußràvÀˆ »äªR¯hJ{ÂIÐzad-Oý•0! h?^×–j‚H™øþqÔïGÌAÐ÷ªeÛ#²†cëÑÃñÇD&bÓÃ7Ȉ˜Ž·~æ°¨§÷Þt›¤qT…Ƥ?åçFr ãÏÅÞ_™MT=žÒixŽé'@êJVN&ûàÆ´d½J"†°óýL"×r—8ogšY”"fþ¹ÉöD ‚Þ´×/ŽXåÝMYÐa*Á;ªJwø‘¼.ß#[‚ƇdE-E²ª²# žÎO_„•)s[/¾Û’²÷UÔ(§ È‚‰G'Ûôø=;UÇž€#™Ìñ8¾§?õ×'­…lJÇ;(»Iíp%ÕJ²¨jº¿ÓìH è‘2ÜGœC£4F²eÕgÇóƤqlP#À…#™pÜë”æ¬ò|‡â ¬D£ôê|_6d&õFjøŽ@8M-À’>åÉ*9Ÿ‡–Oßô•±«¿%ôŽ>k¿žÈ,Èq,ž]ñ@Çe ™œ,%¾à„Ï“y&½ï`ÒÃö<µw(5÷ÔÚ¤®&<Ùݸ.@dP†˜œ¨&·V¯øÝV¦§XYïÚæI)ð1ðZ"g¤Ò¦œž'0žiA/#ŸÖ—§cŸbíUÉö=DÌ¡–­3·>ckôLñ•¸‰p½|0ðç¯ÎJ«W»£ÜÝן¦­tù+þ^äï ¶­,Æô 憫n´’È3ÜóO£D°¯9#DÏgÙDšynC qþ~†³z ^ÿ÷Â0zeCÉ”àZZfwI˜¯±ñZê (ÝzäLÖ¥óËBìlé¶qU.¹÷ªuÕ&qð©E;¼ê|R:ª†iì™Ã `aº¼)Ã@›—gˆgè.Í•o‡fÕ›•ª…­ÑsËßž0eÑ ½è.2ž&qíµð÷ܲ5]>=ÙÓzR›ÒÚ‰s£qäp+­9+ Rc¤LÙ1Û ½A%±¬šXÎPFdK l˜[¤jkh:’™â1Î' וÃ#Óåcô|*r%¹7xНo¦œ1›>ŸÄw)½ªP5ÝóMà¸o 8žáÄ@þª"YW2Ù¥¸±ÝÐÖÆÔ+‹ª9ï è5TdN6§Aý 5&HÏ$2çã@¦PíØ(~¿¾`]vÈg£Ì×›•`˜hº•O–f~îf¥ßÂuÑçš«±®Ó±€ÐPO9Lƒ!ÈdíJv}ZÏ3Âô#žÃ@V¦{òõÒÔN ”ðYÕ¾·g$Á4ZÈû "x‘žÀªÇú7Ô.ºTäϜׯ$M¯ ¬ê('ö̉aÙ“¥™¾®†zVE†UéóÜ29Ⱥ6&vÄz©h-¬œo:y‘xÇfÌeü.†É Ëy—Ar(Â4ÞQ æÖ¼;Ϊö‘7¢Òãñ…ÔÜ5ùOßCáfsâø~o(¥oã½dÓ‘™È½‹4@V2YÊlëfîÕ5“îˆ `Zòž”yÇéäÏ$ºv—)‘mŽ2åíyo¥ôaPË´¥È6Yɹ’ëç?Ÿ{¤£ cmЙqý²ÊÓóН(¼M87(|¾Ú;4n ´m•0±,²ËDi-É€"Ü*e|ÃHÇáÙ’Éðå>鎖ñ"z”3¹ßK#* G1°•0ps½âyjšb4,kÙ']{¶ ˜4(œ(Î6¹c¥2SžÒ8—ÝJýå_þeÇ­„$î˜# ÁÄQ„» >M¥zæ áíð˜½Þ$‡˜ “É"CUíp+e¥êX#¦’\4&£ÑK#‘)c¶9Põðþ_Ñl˜Em‰rL/oXâÙ‘Á‚¦ROgÇ›B#öaÄG¶¼¡7ÙÆUš¨Ýs/ZÀ×áJÀÞÈÄM¿+^»^`»d|7UåÆƒï¨&nº¼§q3Yqée±{Á{Dm‚ дp½íó8½^èð69¾×«æ+Àÿ,¸Í)Ûjž›ÕæŽöÏPv›NãˆçùŒ:¯S¤L™²q1²cÌÓq|:N<ÛGxÆY5ñUã ,ÜÎ1<‘›Eù釦šrî2S¤ðJÉ7±£ q$X aäÚ·¼šü‘°Ðg¥$´àeá‰`´Ã40ñÓºíI);Îv¿â™oJnòJ@VüaÑý¨´IJÕzå|˜·áøÇã¤Z²…Ìbî8“» o4²”Ý¢+`”ZàLº¶ÊŠØ™½LÖ5-¼^¡« PÍ¿¹ºt‰¤#a>rÏÿöäL–RnP½faÖ2MË'nb†°8%«Fç)¿^÷3ªYã:iº*‹é§$»•6)•êu„[(½|‹kiï5jašLú´´+mмüÅœ®îßò—ý}à¿üNéʬ ÚVpâ42F(Íí¬øþ\µÞ4y&#@Š$N «Î¿có‘û€Èjì6M½ãå.˜3ìúçãvèÅÂp«—V®¼[;È)É:b6ø¢UᛇÛ\n%‚Üê‚3Ú¤Ë:¶L2¤cæöÏÄÄ­7°vàxr÷¹„+ Å|õ M²á†åpkŸ‰ª.+„§ÇÃd•âÏŒ÷£ Èý¦fÒ†²Àë¹Àd›aX© Uõú¼ûƒòþ;ŒÒÝ¥eLU#WA#vL¼·*A›lŠM`¥97¨õà>lGøÎô÷8¸êÚ«&˼%\t&žyz¥¬¶^L9C‚;²•‘2“pxG@u‚–¹e½Ü§ç½-¥£Mì0ë ȧíýíF‰yýËa [-£ÚÒqWµRÞµaïzš6˜&FµÞdy–9abÙOx]L¼©Öà âÕ™•&xǵ×x†½¿ÀŒqô6ða»R]1#itqà›n(àXLFÌÁQnzúHŸkdǘ;šÞE"³%ÆOìhmÇLdâ0} =,ÂJd™4«å Ö…éXK]€¡Ê¨%CXÀ²ªœIä°cŒöd@]•æ†ë ۄ¹4ªf‹Ù øëQvÈ4¦¶æ-G¶nFº|xÚ…ª÷— fâûÕBüôDÖWšLÓƒL§LæX(²&&`+·6ê«"iðŽ"Mí9Ü|J™ ¿¡Ùn¨Ò>dWÒ×^žÃ]]o¶rs;¶ð˜ÖÛCsTºò­±L/€voœMh˜w²iÚŠXDÎMW?ØU3‡Ï˜çQ‡e-| Ç7<_ê¹Å8îæð8O-eb8OU;«æé¨$õ~úï>Cmu™¢Œ7x[®Ô`™RÆËÂÔÄ9DÎín‡Í-kézôµËm•3¿‘‘K‹Û$\ M@&s@Gƒ`ÙqLÓïc¿ÝjLo «Ö h¡T-çì úLμg¥s^cÇJua8d…é.s¼p-¶)@˜˜ [ŒLl *bÊ>Çû‡'˜mnO÷iŸ§£ÒnFæ´X@N™,ÏH¨«? SFÊL ØSr|¥.Žä Ëçwô ¸8x¢f(±Ø§˜&k%š¬'ÈÇQ¤l„¡˜Ö­4%¾p|½›;2`z&kß8-ÍŠÏg2 ÍÝN ·Y9ȶÞl”þrX× [Ãè 4÷¬[ܸIJ¨Öµ+d^v)/͘&îÉàÃLºA¤Fd§å8½k:öÄ@J°˜Hãš‘¸öðrâ|Âr‘Lp‡[ôÖˆ.h)Ý©<¿†Æ~YgJÙx÷wL|,ž Û&’cVã§!PZÆ'ö‰3wÄ-”˜EfÞD<®‹¸õÖUîeu©ôµë™”sˆ¤IéÈD¬7P#çôŽ€ÀrØ>;EæpCe˜C>yb]éáªrãÊ|dd&åziFdè:Öy€F;Ÿ¶÷çBÓq½•+eŽZ¨%¹[¬ñÿH äIϤ. ,øG:˪Ýèl¿†zR”“â‹úç󉦲k?U4e·J¬´ÈËäv† „Æ@UÇÚïí Éd¶i"ûtvÔøÚó^ΡvÕ¸™M$ÐRP÷1½J²0ºý•V «’…Ë”ôHžrs;ÞÛ®¥ö|f èUUŠŽšmÇž®¦#="YdÅ^8î=mKO£Úæ)µ'Te2EU-…ýsèÈ'½–ÄILи€F¥”ÃJŸr`ü|*i4E¨qd₎!ñ@S>•³ðÚ«§Üô×?ŠD°LýЯ”iŽJ›PŒ!°ecrȰýn›?%AWòáºZö6ô;ù÷éN–!™ h ½Ž~ü ˜Óg®”Ax›ÓïÈJ­DFP´0+@¼éó©Ð;Sbn>A+…[Ø@hÌ6,ï8ê’y&4)0]“›cžå-ÓÉ#?€³®¹GJ/2´$R nŸõvÇF뢤Á»2,òð4ÛÓ‰ÉüÃzJ]<Ù2 x¶y¶‘a¥'› eº ü…?Í è¶ÝKƒ7¾m{_±ªËˆ[l˜£R«È”2䔹µåĪܞԖ1‹¸^™#’Œ¸5ZŸ¤#Y4ˆFnFw¤qFnóøÇæõ;AU`dUÑ1Ÿ^ná63&ük‘Í=Íï—IŸ&2MׄUáéÙæ/˜ÙÖÃSTªK&x÷ÿL“L&h dQ)P®½ÑshÖixÿñ†•Þv3ð úƒ¸R&ñdÚ æœÓèL@IDATq+9Þ>Ä妫z,Äð¬š. ¤’´;âz3,[C)ßæñ-°;2é.3ÁÜíñ2^d è‚…ܺ²#e®ÅbýŸu\ÞÉG¦”³•…#™q@Y£ì£A®«{ah]ù´½MjTíÉÌŠX©ˆŒO'òÎùÓLÄè™r7££ ¬.š™)%£.@7U¾=;êy¶óTïX™¬Ä¹–pb%¡äXè²O<ÆQ<7xý¹S5¾eà~<˜>F;€—E½™ µ¤L@ìØÓ A¦/w”õf‹lÖ6Ä<3ÏP$œ?>s@Éþ&ªæ`%/ë”ñJ=@<,4ÊyÎÌPË#?kQÊ>«Àé¿k¤I–›Æ”ÞQ®à¨‹pG]˜Ö^WÇɲªÄ0Æñx=Ÿ‚ìe%çãjމl§Çáõ æØO»Ä}Øk¤Ñ(³Ý~Ž1‘ÝY5“à`ÖZ2Œ©½’¿®ŽSBKª÷£1B;A¹/¿ŽzUÛvÓ³Ò’@µbb «ÕÈ*Oú¢^h n‡áYå£ÔQ бòؼ~ø»/A0A GÖÞ>,üÖFæœaú» ®äîÛ¨±;fE©Z´O‚Ä4=F¶4@@)¼5Ö®ZWUÊZ( Gb¼(tçyFÊs Dn?ÿº¼¤d9%`‘R™ÊŽ:½^ƒädð°à k$Nƒõ«:ůJ<.O8®àš›¦öƽzž‡ÐtLšÀŽZ ¿þõ¯ÿÕ_ý•ŸÞE~ýë_ÿîw¿£$h °¿]—u+ÁŒŒ±¶h$AG-yŽéH ÐôSm\Ô1󜑎‰ ºä>Sü™ú¼3Lи۪q1ÄL`Žäãƒl´Ò®Ð†|ÒW¢lÕæ:¶#>ÏZnOS´Çg«*žù¯×&ìáP ÊH½¯Ç”KpG9¾ Z1œ˜]²ÇùFvª|2IV)¬40q¤,"{ pÏ‘ÛÝÅÐ1[¥ZÒp¨J0ÿÀZöèñÙÆdùìrn!¼ñþ€ñ×ý×¾TTÿñÿ¡‘qY©ÆŽ3ÑÈDö UKú_'þû¿ÿ»Ê×…Ù‹ÒþæáMd#{,›‚¡w̪^8ýÖ”ü¸Kõ¦dÛ“w$K¯È\£h.PW¥Zmâ(”¶ ÜÚkLÓ±)–©+L#E½å Ü& "F —rÕóèó•³H4_)÷ ëмMðŽôyîˆÔëÈh£*TE $P²+2 €ßëÊè¢L&7ˆeá<>¤èå´ãµˆ6);fŸò;ÌUj[¿!ó›ßpÈ'>!†Æ&ÚýÆøÆ7¾á—†5æÿö;ÿùíoûÿ=Q—F»5ˆC³LfNÉ­¯7$,O³Mæ³[0Ú‰‹aD³XMsW›Ž™˜CäUŒ£„-¦%±ÜžÉcÖ«´FØVMtã+idâLà¢*iúù1êŒjpjd?"Û ª6rËÕ¥$§×C)7, oKÛ3ÄèUÂ8Âû´ŽxLXnõi2œ&WÍñ6á»–X(‰ u¹ Ð.”:*ÑÃ2_öþÅ /™¯çÿüÏÿˆ³r»cqý¥ç†ÏLïßüÍß|ó›ß´‰#AÎŽw÷ÿðÖþ·û7Ž.KÌ*ÞGÛH-ƒUï}b(ÂÌk¾÷½ïµ &g&?ùÉO\VÆË9|.øï|G©czЉe˜¶bRŒltwŒ Ï-O›à= —å–¡|ïS#RË.è8~žUÏÀ¨ÚtÆTÒ Ø¸jÃZès<« ´Ã2ÕÀ¬ª*¥oŠ|w5ݳz 0Ƌ޻ð4ñj!ó á'þ€ª½ÄVíc¨^¸é~„¼²¾°Ðþ‹_ü‚ƒåŽ&Î'€^ýo}ë[|üðüìg?ce´[æ^ m—µø}âå#k¥F0ŽãÃ@wä92[ï ’/ #û‘sÙMXÀÉxÚ£½.8&ÿ0éÇûöñÐ42©=q Ë·R©ª¬ÄP¶[šŽ•úŒðH;´FÙ†4°ÜMÁÀª½!½ ¯w%‘€:6 ¯n/˜ ®”H@TJ™ àƒÀQcU@`ûA¿aΟ"|f^¯þ$]—LàcóÆ{ÛÜP¶"¹K©ÂxÏ¥·Ä{é4BéW¿ú•?’0¤É ™Éœ10²ìh Ëÿýßÿ=^e&^ýî’•ç韛Mü—ù—´/\í·¿ý­ ÙŠZªö`]bU`í‘F$ó#71Àmï¥Ëþíßþíô?ÿùÏ™‡ì³îé|ˆ¿ûÝï~þö»Ÿ¢d¡§­cð}<I Úò‚¬š'±–3à=‚•*M<ÁªiúS|þÀ$ºìÒ…Ûö°X°«9_L$%2F¦Çxd –d"×Ò¬J1ŸgUÂï÷lëâ†µÈÆyѽd½ô}¿òï3ökak7”ŸÞ•"½ þîåSbè%á>†ékÛA{OI;€ÄL¼ý€e~úÓŸúGÛóá€Ñ®ôË_þÒ×'æn™'cë(¹ÉZda™@̽UV d®ÏŠÒgäë?|O÷04q¼.>F8öÂŽxŠŸó»öð}ý·’Ü>Å0wô|¼‹HÇ^Jžš&:R–‘pGL&)‘ÛSðÁ“Ùú0ª•^ÿ¦C+*dä’aYOãÉDýx$™Ü׃1Éú2Hœ ¼Ë0Ýdé[#†+Ï·?‚[ƒ¬ ö õOnt;x¬ÄýÚ_{›e†€^?]ŽJ><ï%`“Zd¶ª˜îR©£)‚¦? ÷' ß~„ú9Ô"šE&`-²Yæ6Ú±èoT»Ô›{ý¸òÑ.«*uì.‘+m7 ¥Ü«fº<_óøæö`=1Êá˜y<OÕ׿ã?B¾. rh >«a>˜žO×ì3ýào ûë„*Y]@ŸEækl%-ª˜Oÿ Py=-ª9Ó²#~ŽH÷—ÙiÇÈ/;Äc´ÈéUç³÷Þk±Þ4Þ 6b-Vr¥Ö&Μ™ÒD€²M\áÿñ}‡!u±íþcd⺄F %[GŒq}ñ;{õ½IHÑ,9±Œ”côú-ñý￟X|j±µ4B6qoO$=‡J€# P¯M0 +¨z¶÷w§zs?1¹É¢Ëš¢Ô¼_tý¼Mü¹ÑŒÑÚ˜v“kwGÀ24é-É_0G*&˜¾çÓ5U5Láw¤a¥2 zþ CÊÑO°$YƒsÄ0MŒ'†e;xXf`"ñÄÝ<7üºÒ8>ï¢ïãÍ›þ’oq¯…ðe?£#k1³Âl í»?Ü ÖN÷ÏÿüÏûô‡(o¿Ä|–ékÁt@DzP¾ò}rÓ¥ « Ëí?7µç~ô#g®ÑÛƒ§ïRîÛ¥üvK€QòØ“ñ×Þ”Äø ¨ ¿ñöôÞõ/ùÇôÆ%[»N£µ ]5ºõç?Bž†~ízM)Û-ðL>dÁ' s¸+Ää`\›Ô˜¾é˜Ž ôŽ ¨º‹AŽ4°5þÂ**«:õ'r¥@ó’Á-§´-û™i^&ª@Œ<\»c퀗ÞÓôÁm)kñ§pß(~)÷齯{R4s³µ9Fci¨ªU`;øÀý'`#~üã÷ÈêÒ1Ÿ{·Üðþ’ÇïC™gÒªJ˜Bc½üc¯>MŒÜW/fÎïîO¿ßÉTi Ç‘vJí¯d¨ªŒ¬x\~Yõ㺀<¿µÎ¢×»»F‚žs-4žÏÛv -ªípß/h”ä.•tTËö7%qšpþê¢ÑÞ“ÏGcÕ2Rèrä>ÿ@à,³ÃÙÕ‰OPud[&ƒû$Úo²ª2>+K´\wðêûM*Ÿ ÞAïûÞGâ`¶€Åºƒ£ß”H¥Z›¢ ôÛ™@¨–•|ŸýÓ?ýÓý·fùÚn²]pM¼ù¯Ç­M¼^¦JÞ˜Q­=7X–Y €F»X øÿ|ÝQ®4MR¤áafXÛÁºûšŒæ‰|ëØ‰Îú—ˆö077÷ˆŒÌʪóuƒY Ÿåã£[`Êi.Å”¬Õ­½!Ö›OVÔÑ×öSäwpt<þÑÆãÛv£i¥nû×%º^Œ£J¹úY°J„ÁiBžø\Vàö ¿-±8>Χ Ñ”“¶'¤¦VôN¬îy‰sn9ÉÝÄMzzèg…m …!¬bF>æƒC®ï|WÂSÿ>ˆåzÅ÷ ñº_­„t¢ošðN?ÇW‹8«ÛãZå3;ø·û·÷óÏé÷ìÚÒ0[ðÉ;:ýó}Qqô}ëà‡N(އµüFàr£Ù˜p/Bš—U´t8ÓLx"M† 4..Zó¢S††ã£¯DÓÙ_þòns 8åæ·çùF:hß¿\¹ÛE×_Ãý4B¡Y‰®#„râô[ˆ±-‚ ˜"pXk‰‚h¬Äh¦­HÑ»ÿ÷ç’å@³tá išJŠJV ‡ U&‘%ò[ B²8^y ΧÞó£ï)‚–8˜ø8ñ-Íc¾î‰»œ¥‹êÜk«¿zMÓK‹Çvƒ&qS¹ÕMdâ²D]NŸ!ûò g7@‚%–ÕXüDRˆÜ¾©È1ÞüZZJÍòcZQ¾)§+²6€µ ¡Ã‡xÜøí?ÎFn&‹Ì_ÊýL¡Àœþî8N¿Ë×ÞJg‘ãèkÃb[d"ø¢pÈÛþ ZÓt6Šo!BE…*Íù|(0ÝZaMÒÇ {èòI°"­ÍTÇ%JÌ¥ì+ãëÁÖ_ˆó‘µAd¹MBë AœHŽQ®1gEE=õ÷7m0wΞý5o¬„h¹Æ‡{Ú&‚àÜÓé‘&ä;Ÿ ~äF u>5NvZ|¬¢Õµ„{XK¦t”ŽlÊø@Fª1ΑhDŠn ß/?=¹;‘åªU"ÂLùù>ô^×N´÷U"úOJÅïþëœH]݉ªcr¶35 ÊÉRà·´M%²¦FFÇ(— Ñl-Æß_m×rŒÒàÉ5uúMíã¢u³qäê­pú¦Øþö¹gg‰ZéF¦GæÛµ¢mƒüÒGHEÖ=ɰ-ujß§ßãÊé_‡ÄµQ! 5MŒ²(óâëô#Çtú=ùDRWVŽÚ“ýÑY3˜R(@Ê•¨>«hOwSEás’ªU–…ÀWÔ”ƒÆ€!ž;÷§_éúß ²ü.4¤ÛâòùÆ_âFé~ø/ÑX]óíÈ=…#ËÒÛº…0Kƒ%‚ÙT:2B‚œš99׉O’ƒœ~Sþï¯@j´ÑPVN¾PSi–ÚEåŠ?Ž©”8MœB§ÿu z )#3 zÕÇ”?ñ6nI!†ãô]°ÒëJÝšéͧ(£ã[¯¬”§SEc+å´-¤˜‡Ÿþ×§¿¿—¥fL$&?©Sì¯OĈPuµX`‰áFíV 'Rè(D*A|Îÿôòãý9k{‰Ü&·(Çwß×åÃt y$y¨!˜"+=) i8¿æ![E¾,ȲL;⥴?qlW¹¦õI¡Òð!ù8§NœQþij¬0¿üNyµ‡p ‘ Õ¦Î™¿¨ÑÃãõþ-êGž?ÿù϶¯ŠÓ7%’¡1¾hÆGh#ô .ò¢¥Ù Â#s"žXÞzëí®"Ô´µlªŠt?û½ô{ü£©’IlC\9~­W—GÖ ÇTŒ¬ÆÊrûA)=~)i–R–¡žùSÖar¼¸CDgª8»Mij^o‰7.$‘ˆûß7·¥çôòC_:-K Ü8 )&Nͤ^ÊVA 30eø8·)&…áðË2å´±‹ž7Z¬KR¾é$8M·;•Älm¥ˆæFâ°h¢Þ˜=;U oô³ƒ—»Ó¾#—BÕÃøÍÄá“5å-‘pé¦ßŸ9žÜ.[‰•–B-uY…B„<ùèH0¿x:ýåF6ŠE{™1M3©OöšÖjãÄ9©!ß~j@ÕK1¶4Û¥ø¦mÇï ¯×N –à@ ³ª¯1‰¦kïû_=ìB£ º®äšÖ‘]‹šAc4Ë ¿Ç% D3R3]o¦ùqÖ0æ8Bð§ÎçÑ–lš'öJF]ÇHÌ4‡Ad15VÆGîœ'õômŒ^_À)ñÓ…˜Ò™tdÈëN TÃÐpz®Ô0ZŠ@Ðz}òjô‰ß{‹éYÏ£Y“²¤C$rÒ4õ³ 4eõÃÑéãçÓ/SQ´=Mø¤*$jzrÇùˆ\Tˆ ¡€€ 1Ògqš‚ŒÃa•+K´Nôÿý'[÷°­À_Š,ûÐ\W>@^;‰ß?›K!&©a׈A˜Ƙ- ®D|Ñ*š¶Š'ã³{ A0Ö•!fše¥–²åä4ê ³—+ÎçÚˆ6ÞB+£×8D™e wR9Õ.';×íÿþ_»ÿúé èÙïà´‰üÒ©µàB[¨Ñ7ÑüÇô©"å.ma­MŠ<±|jÿôrþÓ7 ß¶Cä²ü”ùÕ­ £eúÞâô«ÓÛZ?›V×È„YY5°(§«®"ÿµ.Y†ÃÇ9ûû³Ã¦”#Ä1B¢ñ¥,1Ú:Áøå'Zí]5ƒ@L…ÊâàÛÈ·ˆ/Qß?ü»üÅ&šø–F9ž`EM×0'°QbÖ´ýI>Nk4ÝN‡ƒ‰ +>gþÄõ#שÛ=iz.F9…MWN:Â=ªäœÕБxnwé“’8¾¿?ôVbãÿ÷{û—X‰ðê+J¡…‰n ¸g0Çûè]¹‡J ¢l+Ô—º™[È(ÔÞIä‡4öí¹• Ñ÷©åÀÌ€ Á¹ID"GnÜ!àëð¡ÿî*°,¸(ƒÔ^̦&šf¡ùJô„"…ƒ)TÿBøïÕœþž>»jåìR.×XÃFÓÿÿ-„³–(Ô˜NtE§M6eB¥ ©VmÞcõÓÁÀ»É¢«˜¬‘µ] ðVÍÿ| Tu•LÙB z£dN&‹Sˆ#T[ø¦žÁ¶ f£­÷’xY•+÷«X™Oߥrÿ8¥ÛèžÜ¢•úþÁÛçu]ÆÁ´­ÂX¢!ˆ¶}륜¦PÿÊMÑhðR9 Ò.…ƒ_h›%¶„I'žlRùƳðq—®4…lþþ¥F:ƽüô´–˜Èr5Àòì÷1¸ôœ~ùÑrü.Ò.)ÜkD`ð“ùó¤·"ÎøEuB3©µ‘~âh²ø¢œˆY‡BÝ@H¥O¡ØæVá¶R]><­Ê˜j% ǑȄê¸>åï?šxü·N„,…²èh‘Ï 7fÊáWÔÅó)TQQ…â Àý™Ö4fcW=åÖÛ(ÚqW:µ×·g—Ü'ÏjÝkä·"|¦±ê6]4ÐTÿ•S‹cd-'‘Àü²–‹Y4qÓ{±@QÆùÃ'wO‚cú öÔh+ÊåxÛü~ùñ‚—ŸåjûÔ»º|'ž¥–Ÿ,eN­5Í&h,QoeŽRø-?Ó¥êâ“âqèœÛ—W>¹xÕ3Š"1ÎýAV~µG[yj|Ř¯M¯oNÀ^ë>)%8²ªUW¦Æj!°¢¦…€¬Ò.Ø÷n¿x HÁgäê†ç ™*íôß÷Wꪋ24)¦Û½©2eOͳã@£kbÊŒ@-ÄFu]ÊÂL!‘²âDŽ â+ÐÿôäNAnå8úOÐØm€ãQâŠS‡FÊ632+DDé:é°š²¢Ñºè'ï3D h^iˆ©ºlM ,Ë´êÃ9•Fàl¥² ¢ÎU¬ eÖë¡ s¬­d>›Š\ÌšVÒTU·1f£‡¨‡ÐRo£·ÎuB§ÞpªXÑ ! 3„@ˆoÛ~²¬V£,oÍ,"wjhUDstî긯ε¡í‘Cêa >:\¦ŠZ~ÍhCÈh´Á†4M¡4-ÄÑÂ@¹ýï—ŸÝÆ©U‘ –V ˜²EÙÉï[È›¤—XEK_4“•Øâ$^‡8-‡CĨ„89F8KÜØ¾-T4AÑôãð¿ü:QKJœOs ™hK p=åKæ@’¨û#ÿˆšª!!Î|S'»b½…?ÄsvSûnc‡µŽ,˜¦À‡hÆñ¿_ý]õ~õES½fê¿KU'GÁ·ÆûÛ3~?ûTÒvç§–8ŸHH…Z`ˆ­íBKd|N%8ëJ 0)¹¦ñçAP’Ìö_QXišýò#*¥6€k M!ó)ú} ÙI0šD”ãÈb¦RäºâšSä?zŸ#Ø34F„ï»x«™ñ3!´dù•F(%f;fÚ7~¹˜í-þûõÎ\IðKNZQ83å#p2Y¦ÈE1ù·iEºÄÊ IÌš–©`+A@vñ¼°z­Oyµ<¹»®áFïþbÇXçD\*â}Å÷òzåõéá w¢m0üJÐY.Çæb µ!qd Í…7Jg-œç³Ê5m”^J¡|!Íð“’îàÞŸ`h¬'÷” ®§)3ߣùIý öÊn´|Ñm…D~ïÉBµTši–80gxk7­=>æödN𦷵À[?²Y{R.÷Ü÷üžbDZZ¯ r8¾tßY|í \B‘9L.¯. ;3õÒŒ3*|+O”ßö!D+™Tpé98Œ?~ˆ±§rOñ·#'íI4ºÀN¿/Ó˜¦˜¿_~üÜÔï6zÖU‚F×ÞTlÍCœþJ×j¼˜ókøtó³ÔÐ1Ŭ(ç{.²P4cŸÈ@œÆœ©á°tøé<ðð³B6Gõìü§…¸‰X¾¢]ÇÒák‰ïòYz+ð= X%L+¡-Ù´”ÉrÚCL!SÆß(En¡Ô„L“¢Ü”ásòMYÓÆ4Ã[]È­O…ª•Aѳ鬘î_’F Ëf*‘o„í]…êmgM»º§Æc¶ž`U4î’,Eˆ ¿,~ß̼ÎkÌèô»Jiì¯ eA꟣16$ÐK³ _nüþ© ë o¬4ŸÕm ' 1ÊbOüwP]¨(_ Z>ûÇÈ*$…o9@)Oð“͈óýGwY½üœª?V @úü¡ï7I·ÝÒf]Y¯©Ñ{f¹p§¿ö( Aâ—Ò5*Î()gñkB–ùÈ»ÄàU阉âàÓÉÁ1UThʉ>ò„™VŒ±«gÊ1ZU•†p2xe6ý‰œÿôœnÔt©ŽÄÄ·Mt€3)5_È73'Õ/Ùíñ¥ÿò#×ÒaâK¤ÈEëMôüÑø¯ÿlì«ó¾c”^?]`HFs» !¹+òY¥9âJçÔÕúÁ¤¶•¾ºE­ÂTZoß/?Ò×Ö ÖƒÏN^ÛtTñ|ù~ùqúêüÕêÓÑç$ì:Ö¤(„U4²BÌ=€ª¾+U:‚¡Î40\ú¤8;±Ï•+AÖVÍ)—ÄL?¿HŒ·ZõÁ6Õ Z m»‡ˆ{à'ïü§L!˜Rh Œi¦S:‡Å·þ4ëw$_Ågß/?ýÙ A¢±tªbìbC4ìÁÿRpyzàÉ=M?Ư“]žÉŠ ¹ ê3­„¨n¥ùž¦ü³OoÊ™t!£iR¦SS̲8zàsU(ñï_~| ZHR’K!ƒWÔ”Úk+D½>õ,¨a êJ1Z D¢ôµÍiù_ ŸÕ¼Íaùµ$-Mº»Ë˜ø“úÙ.úhBÉršÖíP3œ|)M?OÜ&Ôc4¦›¨òxà—‚hÌ/w Ǩ•”åim³ÖŸÐD¢ mµRjÂñ_f‡üå/Á1åÛ>Ÿ×íQú®:5ÕM§V ^|Í|ÿÙ¸ß:ð×ê²JIJ –Dø#‹cÄÉF(¤CÌ…šn䌃¦D†C8ß/?-!“¥£Ó#ÊL¦þðå§ŸNÉ¿~ Hé3áQúÜÿ÷wH\Õª®D¸æ=k,šmLSÈ=f\:)K†dð*žæžöb¶-üé 55b)üoº'ñ ¨FhH •‘mUøÎ_ ŸS±¤ø¾ªÚÁ@£SâR‰¶œ;—o[‘E5ñ¡üÿðVõ_ÿõ_ŠÚ !„ïW Óo×Z …•€ Ôg¥=ðîWѾ:—µã•Bu+]ˆßi’8$š>…ø4YE9ñç¤<N"UXQ%ä†ß…ÔUåû7ûý„Îzã/—Z¾Áf¾~FCv u•ðYR@—©ÕIÇJ¼©Qç«ËaËzÄÎܪM%¶^£ÓYkÇ)T¹dqL‡T1M,ðsmš?äÏŃ@bIä»á…4”Â@S¡åx·ìm®¿4¹ñúã”­ë —è“Ý à\zõW½ã%‹¾ã[.~ækïîÛ)¶=¢ Cæ}÷õêïÎéaü'õ¬eéù¬fš:È#˜:µpˆöFˆÉ3 M¦ùê–x§‹†/ôýäöòÓï8,Mmäè\cüBF{ò‡ßl»KSz Gñ9OÆB[‡¡QŸ‡÷³pS&¤ydB>¤¬ž %.K”>“"ÄZ8$N#üa¡ˉÙþ1mŠ€v>k oLq9œh˜B¦’!|  ³Ë@ðý;dSÏ~>šfŸ @HåRKJ!‹øÎ¨kéµÇop]‰–!Ñ3ïõòCÁ‹‚Ñ ™)P-NjÎ ä¶¾:w1AFh-¶‹OÐ(º)BG‰òM³DòÓ`BL‰s2!S7?q'Ùub‹öp†ûå'ñºJä³… ôhCžìÏÐ-d5ŸO!ÿû=âIÕ|å´]9mCL–ƒé UÉHªåR4"ÀeUÔ˜SÝü;Û¥DL‰@cýp¦@vôÕk—w-¡HUB…0ÓùåYÛ‘ÓR‘MK7ÖŠKâñìÔzå@ð¼ñ\÷1mý>â¸:ArÀýñÅK‘{/l¢¿tþáÍ _‡,’ K(‹cºfZ¿ àÓ£UŸ5<&×§G >¬Dݶ¿‘ÑLSã¨ÎéYnº, 1Û™dãË 4Í7íº„ o!r9˜p4 ù¾­böÂ'˜•µ±–ŒîŸ×'!Îþì¥P¯”%’²v#<þ4ÃBí‰>CíÖŽY™¸§³´Åb"Ф&³ så—¿B)×’Z¿ŸUBÅ`iqNÏ=ž"4¼ë]täNÄqwš]_…ý[G܃¡¢UA¶ÝÎb7Œ)Y%Œì>ñ^¤é gR´º9J`¶S¥ÝcËå ôòS!×Ùþ˜ÒÑÀÊñYå&~WÁiÊ)‹¬‹mùFmÔƒr~Ýrj­=Ž,)8™N8¢ÈBL{ß·±ÛÞB0åªUiYøùœÖâqÓU¨“Æ®TÇCîÎÉV”B­I±Éæ×€•*a¥Öû°Î¢4é3)]”U‡h¾VSFH¹åÛ‡8z`”Mç2æˆ  ±عË)\=x¢|¡¦÷(äâÓrÍtÆøÈ¥,·ô r™Y)Drj€‚.ɦ)K´gƒ-ã§ãÕÈžÞýð)øL@È7æ¿hM·ÆE½ìú€ªPcu¡-ãÉ2ˆ¨“a¤)„Ã6mÉ]?‡À³ÖÍã¸û|#âŽ%ë¿O¼²(Ô''Ùœ@ˆ{Øûç¶~ù¹{(Z.Ÿ#Ê8útúk`"ó*h+ZZ|¾”Ãä7ŠL¼ÑcN{¬Ë×qG6µRÿÈÔÂ]eÛîf“B_Å4ë-eˆÝã7½G)¦•3fË i-]¯Ý uñZ¡´ÂÒØìùÏ8ŒVN­;4r…ˆë[bU×Pšh޵©©ö‘C-_¢¨S’P–'Ê÷ËΟþô'Z"‡Q#žÍwÿxpÖF£ô~쓈”k\bS!޶PØrð8nW=;ýrPƒÈp {]ùû¿ÿû6ÐzÇÿ÷_éÓŒoš¯(ò÷ËUì/h9ùÆÛ ZzÝB@Ú‰LcšR3…k€c!.7Gc)Cˆ›´Øþµ\·´ÓŸH›ãëŸÿš5K0ºß¤ÓIœ‹ÌQ% T¥ŠÀÛ²4­%N׈“,ä¯Uâ³$„£VÞXHNëµ$­3ѺÙf)c:é4!8øFœUŒ‡/„³í®«Fg·D´™ô]B:N´rùãphêm¯I ygp+ …Й“ßÒ€9tÖC;;©²ßþ8 *šzÔõx–ûÄÏ)Ù6:b zðìô?NýO³©\Î÷ËpÚ„7nS:9)¨îM2ÎFMêA¤¶r·d¸U— bêÙÔW;>ÄÓÝ ic[ °–hz¿ý»¿û»D< {IDc)s$®zK§ÈÖ*?Á>S4uéœÃ€ç?­KlÆ‘cV ÇH‡‰òEÌ%§ÙÆ-ÔñjyMŒ#‹£Iίï@¸Ír>7º`.[:O Õª\`E9.¹—Ëñ‰ï•L:}äêÖÃÝ\‡Ú®óµD3ÚÆz ìYè˜*qÉˆÚ N Ø”,gV{q€Ñ8µT¢·ˆÝ3KìÉíXCÖŒ¬ SŽÐaýÞŠý \9|L=p:=œ¤€]2Aë>OÙåîÁRnLéîUŸT½ Ò÷ÓˆOEBÈ#Õ€(…¶¨Ò¦E1»ME‘e•r$ž6Ek*wšçC ”®QíH«ªLiFœI U “4fÇ/„–¦('Ø'F¹UœoŠŒ¢Å-l )—öû·j‰.¼D&±>ù;Q~j¨ïsãYÿ8jÍHñw1äš¶.~ScûðŸ'Q«½]÷+° ¼Ý@¨PÝ"ß øí@R+ÁÉÇÿ~ù± %’ª‘6ÍÁ’x_Êz«½•ºK»j•–ÎI‡‚iÛ"e ¾—onö6)Ï#ÿë ´ÈÆÔ8iú´@Èuq9‰(‡ÖÈóSCà+Ñ‚£VŪá…Ò±E…€ŸYË)- ãÊàñÕF™å§;f`:h)Ѳ[ …øéç‹r˜DScï‹ nôÑéq’Ž-_bš òýú$·å«·eqزª55w2)øhÈ@Çð8ìdÄP¥¨1'¾Ýp=z]® ¾s¼]š~QSm|?¹éÛ²‚ƒ_!ÓUliBômEšû9)†I§Ñ”nä{ê;ýá¦6Ó³?…{ªùõ <óuÙ{,áû¤THcYÑv†/ÊGàò×­]Æ1Nç|Ou*Y¦˜i ºc%›._n)nD•Á_O8°*OÐXÌŠ\é4=-^O,LO/?Œ‰­ízq©¾_Ÿ<8éø¸°ŠÈ:©O£¶[fͬPM®ù¢štú‰˜ÒüóŸÿ¬I„diÂYRÄ}úGïKB>òÌñ Ò·£Éê¶\‡æUÄØeBæè™9²¯—Ì^~*¤Ö#ðy_’Rÿ@:Æs+ê?îZôÒÇ/œš‘á—˜o\Wp&…õa%ª¢±ëX3´¥óãmŒ Ÿ*bú9ÔŸ_BCÛ ¶)•Ê¢ÅI¢Júþn®JáùvBÝâ|ˆ§ÒjU®Ñ^—Ré4m·¬[ ¹ÃEùšt©–›ãÁéóz‘9Ô9BÀj 7å³¢ý¾ÇZœ~%î£ßYÇ×’Ñcï>Í}ý­¨1A†ïSåûådzß*ÚÞÚ–X Yp`SÁïG‰¨[hµîêº(¢|·r«pŸ[/r¦sozB '“%ʯŽi>Ú'óù½9îÛϯy‰5OPb²tX|#Í3"Ј&ëÅ Œÿy·©-Ð΄¡ÓåÐÂÑ"‡ÕB¡(¿@“k¬°éVd¥s²)HtJöЉ–í#›Žê–/«êuÕ£Bï$?Ùç?)”¥çD€µ´)~8'ß4_”ßÔp:CD½{ö§ÖX-~o>û]r3÷ ž`µÊmWûJ¡Ñ#Ómciîp²) q¤W‹¸)ŸˆÍñø-?ÅzïXŸÆtl g`—Oç÷é—îô×jm—^VUè³8¾¬jìr㘢±S`;SH ÑOÌhùES¨t~d>+øy["-@…A·T`Šð„:ÁœœUªc÷1§\ã “)מ Õ™1«÷:@Ž«ëñ_'q_ÑÚ KÍXi‰‰CHÝÚD(øñ§öâ'•O‡ÓÎŒbŒÙ(Êññr½v”‰·øµ‘¦º–ì_w#Èuˆ/cw!xYœpOnf:£ì †)‚gs»Á‡3› ±~)BNÿëäu át¡óÓá§fª+÷ùý:JÁݾ*]ßD€/§Nh~?ú.$ÝZjÛ¸­“HM¢^'>Bý¿XöpT¥B1!|fÊâX x´ ­ðÌì!žÜ°hF™ÆSêÙ/£þŠJ)”“l:Æ'ãl1Žg•k0úDÓñKQ޾ÓϹC|½²*ZµºZœp§MÑ—‚Ç^ÍÛMÌßMy6Yn‚q€iVB4š_úïï”^º9eaœªóåº[‘÷ñ2BŸ4ÝTñ1—È1­É:±÷ÁEëåÇ{ZAX)­‘BŸ-pˆ64o½ñ ”~ã:wì2:øk)GŠZ‰äèÍ]!K'~Í ´F¡LþU¥þídjE%rð3j¦]ˆá¿÷ɯäÂFZ ­ §å–X¤M·ù[ ÜÉj×ð›BT1¶~¹6å~²’bNXo|:Ä)¶~0Eáß)Db¢áårZ©P‚pþ–ÏgU9Åž?¦Þ§ßY웉ҢõÀ§`ê!‡Ü£ÎeóAáçð ‘Åyä~‹Ê1~¿ü8µž”—X«F&ÅH$‚)Ú÷÷¨¾?´áÈh®…QKÉò)SWÄ™ó¦w ü˜ó×›^L‰"ùR8‰4µL;ÿÑ8ÿé%ÊcÑsÁgÂtnN>‹Ò†ÏC÷ž“€Ìô_-þ˜œå#°ö~n€ “¨!F*À,霙tÝôJƒlÚˆÐ2„HU5°\Qf»¢À¥shvñ¾_~ºð²âO_¡á¢²Mߟ¶N¿“ÚNI‰YÝ»¸Þ2Ñí ¼Z^@_¯ÔÎtÔÞÔ\]/ͽ7»Ø^xœ:ÝüœuÎgôÕåÐñxÝÃ@'o…"ãsl ¡çüûåG~²Ô€(÷™Úàäk  $JÓoh¯¯à>EýòS§– -|ˇ´9^]8·ÑQÝûŒ{ÀDÛ-ßB^;ã™èq ONo_h¤T×vmðKçÔƒi‡ªP)ç^/ß\¸ä„²ÀÆ–¡’8¦ ùgç~¢µn:"ÈLÂøp‚cŽç‡ç6¾Ý‘'nÔ~j…øBß @7€q¥K„pT§Æ©C 'q!NQ‡£7œŒ¬ÃÍOÙÈ:ú½{tb<õ‰LS•–Ò´ºÒ_ÇŽ¾'wÈÚ Vœ;ÀÊqàj šQ Ï‘MeñívE™ëñÜÆ–å*¸Û…€ø@ŽŽ¾5êÊó¨ÏÀtŒŽ¾»‘ ÐeKÝÞîl¦ôî@Yz³ 3ˆÇ‡¨´rH×C ¡ÆÃ9âM$oaÅ„Ššr°é²¦ñùr‹ZáIxLôÖ„A’¥cŠl𠱬F8Có¼éyyGí kS뤳BªSàÛ²ïŸì5+E-Yõã2ÔR¹é‹âÔäZ ñºÿQªtB.KÓ; ¸´®™Óß«&q0Ié–²†»ØRêÐSÀáCžQHJÍ×v>Μ4!òú˜ÚFï`BÓ)QѺÒO Aú(~µ¡¥ë92&e ©”MgÙ–`æ¬[/ïuÿùŸÿÙ× 5æ£q> 0}V ‡Ó¬4„q€¬)§UTHÔ4DâçøÎ‘V*^i!Ô8Æ8!GFà§ *åÔ.¼"T-Ž)Ð:/y·N¯×‘é-e"¦¢Ý™n€—ˆ¨ƒ(ªDd~×òtö_´9h‰@âK÷ {=SqGÓ…ß¹ÇtÈ5Oë´hÇ=Áv£6Z—ÑT!µÜ`¯*¢Þˆ´dNR5™ 0 ßIz½v Å‘‚Æ5@3YHÞuÈñæÍb¾R–˜ˆiZú¯iÃic1qÜZN¹ûMÛ!VáylqÒ©m»jKqˆT®EáD[ét€‘Ï PÂÂÛ…ä¶;Mã·õùpÑŸ‘’%šŸÓ˜¸9ßœ?—D–iyìÝ×ÒýV¨rMÝüU‘G¨ M‚®ð6|‡²uÕ‘N'‘tŒ)ç-ˆ¦Äëþ„«è_8ºlÈ.•cÚ›`ÎtZlÝv]%Öª)߇LYáÆn§6ÁtÑd! r´DÇçÏëƒîÕßy’"Ý”qªž#HŠÚ뛘7Õ2ÅﱘlþeÊ÷Fúº²êü¢µÁa=5\)¾,!޶p!ú¦[é:²tŒYdü¤BŒŸL''‰%çÈ—Ã*)!|L •75š²üøý#kÊðCªeôä~ _ýö*õ´vúY 5¾¢ÀŠêóõuÓ-䈃Ì"[]--ä!òúÊZ\ |>¾ÜîK€µÇ™Çyõ³çfäœÆµDŸE¦i:½­e:…ÊhÊ>¦KôoJ®%…[ä¢9£IaøFe8F›¾5„ãCäÖ¢ÑIú~¸z¦zè€Æ$È©Ÿª„P«MÎk¯qàÔ„œ¾[ˆŽ,cNͤŒv–ñœ08'qç²…D3îÛ-ši´ù혱,ûÁˆ“ñ+ˆãåçUÅk±/FШŽ—:!ep ÑÙ}½º y½^.>¤ërW—Ûnpþp±öŸÅ$Ò*BjÆHĬ²Ï´E9tÜKp~ ¦rùéëУÇA«b!«^ÊÈÓ©>‡!°ß× Pù‹ WIN×ïä=Ƭ6?‹á!žærÚˆ`²£—¨Š'Ä÷õ?³«"‘fj‰Ð‘.d¬Ÿ8|‡›ÕÀFOf*…Žê¦R¤3åßS )²›êõDTËѤ9|8Î1ÅÙØ®B„XéÕýè=ð?ƒ¿Zj£û'ñ% Aý]C¼ºx«–K ‡#«|&Ý”óhœöëGd¸»AbÛŽÏI$M~:¦õSԾݿȉúRg$Åh.1¿6íÕ¶k¸t¥r…Œ«Ë×@UDK<¥ýŸ ˆñÅJ€´ÈBòÉÅéÁY)᩹_·¤¤¦<…r×(‚'Öë×:Q{ä9ŒP­Ös UÈ®ˆ·ç85ÐHÊ~í™XKÈH-™²9Vd]^Ï8á4{ùAk[£uÙv pø5Ì(+šÿýÓï—7Onã´ Yó˵.š‘×÷›ÓßÎp0YÕ‰°Ô ¬Öïź,¶¿,¹4'¿¡Í4Jy=þ=ûm¦¨Á¸'=5ø4…ÁSæÿ…Ù˜@Ž\äøF4«ˆi¬[Ì©}~-ºpɦ+9Ÿ“œ”]ÔEñ³…¨Ùh#“8fS4ŽjFÛ\3Fdo>^Ù%bŽ&eËã µRRƒH±G“šãú‘e ¦#«ÄJˆrò»£¢ÑtªÔšZNšñíÏîócâ¬VÌôÛ%âJ|¿¹Ù¿9¢I¯‰§ÅŸ‹Ê)Ôèäûç/ ^üZ_ncW§>‰8ý:¹/G!Ÿ!@äÞ!ùÈvé´òs?¯·]5ú^Æî­³"w£µ1eñ7&²)ñ¢ÈLEuºZH""‘«4 ù|³ˆ§ROšu&g ž¢È˜ÑõÚ¥#à3Ózå´›B6èuÍ\°~^ßøŒ”Œ”ăçëöÞî'ï ž^#S ®™Àh@âüB½G!x£à×ÌÆ½—’ÅtUcÄubL0ŽA–¾ŠîØþ{âÝu+!äAДüE‰4]9}~€¸K}ÝÔ rf+Øúi?… :ñ/U÷£ûjáxfÝ3gyÏ YTbSNHÊ­Q?÷{£º~‡&+ŽDNþ*¶ä¢{SÈÎÜ @ÆÄ¿§iV÷ÁûÍÖŽí·¬8‰`š¬`f*:ŸƒcŒÜ4D?ÄÓÏÁŒœžŽêÍÎGºASçìUØ‘õ…NËÓÂá0Þ‰øZ7Ú/¸ZU¥<_Ô§í½A8N¿ ÖÎ"¤¹~î=’-[Vå/×õ.QQ#ZÌ”‡#ólñ´­½Qø¡ÓbU_"§CÀ©«t"„$2YÓ‘âØF;à%Ǔދ0£3ç ªûtw.*DZ–š DÖ§Íôp%2Nß}ëÁ˜ÇîEƒpôÖéw}õzý‹7*g9Ö¾ÒuU?¢¬•ý!ÂEÁg¦”é ÔÆJ‹R+k~=Ã9«•S"f:Ë¥ Ìî”àñ#œ'R¼ÛǶŕ™¢}‡û‘Î+»ýÂd~²°é­*5|ŽQ´sӦȅLÖ§m‰é~ϼÓÓÏÅîJK©Ÿ¦DLÝZÆÈôSn…ÀiæLÇ4Ÿ“2§Š‘ù-ÇÑô§{—Í[ÄNLœt4Ca¸Ö'sbZ¸1²*·ƒëýÄsÑAy}°îg [fjM‰­yÛèôû‡4š®môS£¾±êu2\zÏ~¤¹hNßY]MSRª´Š-ŠÈ6Óêö>†FÙÛ?œ‚‘Å—Ø´[…¸idz¨qW''ü-^HzÑÈ鹟çJ‹AÆã@Œù9X*¶øõèÃ×ÍS++¥©VnÐj½kîTIô1Ò{¿¬t8mŠ©ôû‰k T:gâYð—!«nÅ É7¶jxÕ9nr/¯N¿‡(½4 †$…`¥ùÛ‡XÈBø ±]ô=üW‡=þéðïÜêîØÉuÛÇo9ü">£È¾¾JÙO#ÉÊms$¶êú‘Õ#L¹^óð…^‹E+^­´Nn°r>CvN0ýCË”¸5Î!«}‡ÁJ9¦R¦\3ø]£ø¢ Èò›"‡ ·Ì¢ËJÙô¼¡êi9bã6®0¾GÎJÎÑz䮦iÑœ¢j._+#X³€6h+¯ÊDÂÉ2>ë2P $µ×­e¥_QL)åB8í_ƦhfO/§¿{’`´Yu…’…'.g8á@d÷•OQGó?þã?Œ¸2Çã?2j[cššÄi­Ú³Ç=æ.šŽæ%ÖOk2ÜÍé#Îr¾waÂ%²ép½§“ên¬¥q8-°/f>Be•˜ “Yæê>”ÏÉ‚ñ#—ÞÞÆjsÆi±À4«ej“'•Î9¯0/dÒ2•ß (ô‡fõ”º,›ˆ_ÊzÞ8ý=ÚIùÊåô{àá˜"i·tcåÈvkÕ^µø+’²Ê5.¢Dc 4jU¢çÓß³ÙGvýËú֬њ'Ø’l嚊:厾pàË¡f[L…Œ¦'vY´¶·¨1PŠ6ÛˆiˆÐ%s^ѵ±hœOá¨Õ -–î„8pêÊpœ'cïši£!Õ+=…²à@Æqô÷“°‡“£ï9'DY þšŽÒž~„t!2ܪtUç¹D˜~^ÿîYb{çHÿ¼½p€*GÓG¶Ë¯°–øvйÜÂ+熱>B"ú‘U«ùVíAËé[~ueIç³jõ QÊÆ!eŠãP:a^~\×¢E‰2kDà$èójiú@é>=¬ñOú“¿¬J(­®×'÷ØZR·«\Eœ®ˆ©\|Nßš¤hÌÅí;Œþ!øÆõRˆŽ»q„œúá»CZ°ÝhED ñ7e«Â‰3¿,ÓsÜVf£0§d $Äü°`»w-û> âO™ŽƒâôDѽO †³CŒV }ŽÒ9|!û«„_Wp»lºZí£h·¨Ñ¶¦iä«å¦ÁÜ>Š:šô‰ä¡•¬¶«ˆ¬ ²‹ê‘/q²n3÷¿@–ÎAæ[¯Æéuì›®¤O¡5âsœ×ûW ­«ê‰»E¦Ï7އ¹mè·Éeiã¾|@+uÿøöä²YÀŒøz³Û|«›š— ^Tb×BÁ2þî@‰VŠvzú9Žd‰ÛdÆ/”Ó"XÈ(Ë΄7Bº.ùpS~ |L͘ß8µÿóOÿôOu EÍjtx4K%Íñ,´5vÓè²AØZG+…޳5.›+až+ž¯NÃ4á4¥ˆjΆäˆÚÜd£Õ[QYDÔª„)C¾ŸÖ¦ÈêE+A îÎô„ ßé´áS3br¾©O-Y>£fJÇ¡4å kÕ½äe€yÇP´ß@žŒ“’ZSüëá]®@IDATèÀ¥L§ÇŠ)²uùs¡ÏO²N-C #±•&ҳ܆Ã%šê !M"®S7¹û6ñšiŒI™ñÝQVÇ'èZ“J0²¢ ¡•òõì⺦ÙÒH%ظhåŒ3%*‡sûM£ñ“åäÃ9Æô7 D>¼Ÿ,Ñ¿ùçþgM/ðA´L£æØñtM™D£ ÆzH8vǨ׊O V !»Ã8B¬K˜¬kCMîÓçùÄà(Ç0Œµ*E ˆh|¹ñ9@ŽDuíñg]xéøÚvV,)žmžýÉ•olE|‰²¼XÚd9š¯.…Dœž^û&jQ5œ¦‘”±År¤û†@Y禎‘í"¥s/×Í©Ojq(Ô§¢Úðs~ï™B…ï†$âVT‚‚rkTˆTÕ¿©³KZÚGSwpY™ÃÒªö\\!âÝ-ÓDÎ7¶Þ¦ÈjáoB€4«ÒˆSȘ¥¼ñ4ýœ–¢öAQ²¦8¥ço½ó¯ÿú¯ƒjÈH% £´±í-¦Ø1å—‚o\!#ÃOS³»ÂÈŸ~ÓøêBš·mPx¾…jñã$M”¹x>ñ«’¾(œ²: ½™ˆ¢=IŸLjë0¾)C³äVMJnQmX©sÀ8i'Å©DN‰5ƒfjÝ“œ3„©CronN‚Ò8pcÖn,Ä‘èõ`&µ¨f¬TW.J大C³ÓR¦èJ¤`¥ ºî85FJoîs¯R‹¦“È4‹*QÑøYóóù¥0¿qäjáUo]@›À8Èj¡1 $çoþå_þ¥‰±uËhZ2Pšõ«Ç©@·ÄÈ«95nz:I…çñ ù–fŸæ@¶ÍBËÊ LÁ£hñŠæxDõåôU¢+ÇQ"Y£ÄôóM·d>«½üŠòoàh|V‡%b–¨ Ä4‘]9Ó–³*¥—ed F4†&Ë(¤"'ŠlZ'hK¤Ÿ#+}øQŒß¢Œ6ÇÈj \Vz~S4üp>PÖMã™ÃÇl¬VÑeÅL_hÑ[¿BõIxŽrãÃ;v«©çÔøi †‡àH,«ÅgðI• !UÑÄùB¢|Íh;þê–ˆ\n`‹â‡Ë-kÊÑŒcŽl¯hfeád@£ƒoª±À_’6’³ì ׇ|9EáSZ¡ÆEM#7Â1{Ï–hzw@Ÿ©…ߎ†,”P÷5ödœ!)¹]<ˆ”m_®éº… rLÑNìy=HŸcÊÉG¨z|~ûÐÎnOLk_b‚ÆRà‰#]¹hB-¤ŠõƒIy¥…˜išRrŒCL‰cÒ‰/´0ù-y'BX ¥ „WÝXów4>¦¢ðV±D‡¥od¦B®)~;nl‡›¦ÆÇ¡9'ÁhJ˪PÈÆÏ× &¿…åC¤qŒIçiÅás”¯­ú4Ö‡lü5‘#ÄAS+ZRáU‘Û”ÂÚãgBÒwú—ÈÏn!HúS¾Œí”§@=‡+‘šq¸+=µJ ŽVâ“qRæHAnZ–ÒÈ‘YSx¾1?ÙÃx4»R…hš†Ô9ͬ®±«_•ÚˆçäÿìØ–Ÿx´ü*brÆŸÎdCîK¥Ü%˜‚i~ES€°DîfBVy~k„Üþç­€b'X[þg£cëCÔ› GI ¡¬燗‹`šT!x+Ì1ÂO ŸTgjsðe­_¨¨‘xM"ÄDЀi›XõÕ…`ÊZ•²„2œå—kd@#²©U7­+ÎE‘ I±Ÿ|N«ª™øF–HY¦9F>2gÓ:‰vòŸ”c…e¥çGƒÜü{Z!dú| é9…²Šë'ÄȪˡP kïY ­·‡ûWç„8­Ïõ?)¡E'^Å©iRb†¼«ÀŠ~>p9r0*YTô Ç®ØÆrã;m¦8%*…¯9õŒá­g%ÐDm "(TÅbò‚)#•AàËŠfÄ1Ös#$/ÄnÐTtä'þ9p…žF>+ÕymÁ¦Ñ&^ÛÖÅjµ®ž.>ÖÏôÉJLJpÊâgk>üÙøñU„÷PUÏ+ÚÓ !~ üV4¼Ä½swסE02)Õ ¯¿ZºjÒ’΀ÀZ©)Ž){"Ÿ'œ­±jÀ™`¹˜˜JóÃ9íñªWÀ^LE2ë·ón¡6údþ<óp(˜V›ÎüLm™\&T!cüѳ¸Ÿ•?ô³Ž£AÖênÑð•0•¥íÚƒC&¿&#Üx @Ú¬åÖUEn›fÍÔ€ÄRÒ4â°é óþÊA“S´ÕÕ-påàjA’’ a²B œ¦èÝ šëH ž>æ6çfF0²6“>§æU¯.$ß”ÕÐFIá|Ó…›¸¬m¬ÐRÔb)ë$ИΖ0…%ä×ÒKóóO H0Òx, S ©;Ua>«Å|8i>&~û+„ áËJßhZ¡U1Ŭâhpü»ládM…êßhg¥Ä¬–~jÀˆ`ZKi¥@ª ”˯ŠP"¥Ì/%0¿»a9•6åÜkR-c$°ëZ.ÁÖɤ¤#Ä1…76”Þp —+‹’rÓüEk¦¢,Aná„s:!j^]¸ø¦éá8ésZ Š#ó¬r‰ï0¬ |d4#Ã1ž‡½€ÑDaá$Lå˜Ö:‡gÍ™RXíŠ!3:¬bpfJŠSÑrÚ'øûËq¹åsJ¬áÈ©Q /dš¾,!£ÐH¤Ü|SCfù|‰6$e4Vbj‘ùé+j£"ˢ×­U˜Âo9Gô§deµ!9pŽ'¾\úªCLceIÙŠòE38Žr)¤(Qh‰œhdV'œ89‰C(äÃós$ŠÖ°VM'u+cÂÓ.+?§*ü9¢í[[*”Ý]A>Onì2æ‹©:‰š‚Çá¬cæ«KÑø¥SFæ³zÕß*N9Φ#‹Ÿµk1¦p+Q?ø¦§ØÏ]W“ÃË2âäãp¤*|­:Ü/°*ñ· ¦1Ã¥°¥C-}#…¦ò“ͳ1µ¦¤LÑ”órÊ…›Òœ>~ӻʘ¦8r9LKÆWˆå'~†¢õ ʈÜ6¯J4# '0f´F!`µNÉŸ‹Å i™r5cd‰5í•û<´P[d¤©t9m«L*egp)ÒCøú0¶;ðѧÃÓ=¤©±¢ÈÀ]¶”k,qS Ʀqöªc*%ªRÊÆÚ0®‡ÓJJŸd¦mVâ­K9#„‰‘?+ÚJGîYK…p"ß["d¬D D"ãT‘BÑœ®§\8Ú6vuá0Yš¢ü”ø×G`RTìs&©øS…·¾lä×dcâ7NVž ‡­:ÿ©|†ds€#ó»ú'ÿçÉ2çä?V«F«0–ò¹óƶJP’s„BÈ7ROÖl%6áÛµeE(‘Ïè$Þñ2ž2¥P­ÆÈF–2"AScWˆOÄÚXY¦5&¿*gd!ÕdE]Q‚±&©±8ÑLEéh f ˜€¦ÚN³>#ð“:Ëøù¸ƒÆâ´ðjJIa!Ì™NÐŒ:)K“MS(ÎÚ.d*e~´¦F—lHU(çˆ&¥JWv"þÕãÈK™2Ç!1ª®D \ 8KŸs¯9YNV”_ú9p¯Â¿1Õž©ãÒVcYÈB«Šz¹,µJLY<?eŽ'º…õܪ9! kZÖr©Ù;œš\Š©Í‰ÀÉp"W´c!ÕÛÜñ+ÃÑpè3 Ñ´èdÃñCJä6„ØXÊ£ý¹ÌHMºÒ¦Ê±[/%‡³”MBj¦Vn~úø¤¦Ö ²ê|)BíRS¾Ã8B¬åĬÖdK $¾U(H„Õ^jRrKÙBª2©Deq*Í)å³Y/* T}t"—OH 'hê¤n!@´Ö_"¦)ýRŒ Ó$e4m²²bâ×dxã³{¿×¡Æ6rò“ª 19)¬BzcRJå1`m䊎̑ )«BÕ­JRÆ»::±Vº'ÂêÆ¬Ä¶º©Zh1ÓŒ\~4#S%&M⨻¥!ô|Qèè>WMKgÈó¥³¶+Ü´,UЊrž&®S"úÊ…„K"aÑHÁÖsBà¦ÆMó‘ÂHI˜Ÿ„ñ.mP•eµMÈÌ4‡TVbY!²nàÄ„ eA’ÅéÓ0~)|'#¤%”[!¥@¦ÏǓӊ0Y·´hÓ9MÂÓ¯´i"ÈÈùUÒâ¯íZ­+‹¦åO™œg¾P7Œ”À©Iis88OÒéÝ ùzרhd».8•Hsåà²Új>Ç~Šž—•àdùøœJ+ºZq 7¹”euÐo>å@ãùHÕ“ph>„\K=‚GòiÎÁd¢$Ñd¢ò6 A—«µ…mPé™”Fäú6-±røÀ²ò19ɦì:ŸÃgs˜~ˆÈ꯶Õ%^´*!F"²±ÏÁj¥F̵Tóh¥¤ÌG{Úùôƒ KtcVn*Ô4² bÉpj)‘Ô*]o1£ ݲé'N6rŽPÌRT„WN­Š7“A²hR€ÈF=¼‡¹)Â8þÑ8ÿù$}6'…éÜx²Ÿÿ¾ÂÍXÆ)ø,²zÈBÑŠ*Ö†P ‚ññ]"0¤ÒÆ›èñ“¿D‚|¹Dà}P_'ÿg‰ —ÕÃL¢,†ó4õ;E7/ËNĨgYÑšº%&ˆ­”tÐrR3â„ÔX„ÓñÓs/u| [cKˆf„´>{ò>÷?P.¿ýÉW·¥Áç#cÖyQc½)]‰Dâ´Þ‰´ÿRpB¦¬fL™\{¥%ø8ñ… ¢h!8üù*‰Y"­%ÂFN½qd±RhÖy8“/dZÖçl€˜äHÆT8ñ„L_Î8p¶&šJA°­Ö 'QÆgÍÁ©­¶L®i¹¥$lï„"ŒÓ´¢µÑO“™V ˆ°m-¼D¸©”rËJ„_Ôˆ€–™*h]œ4‘#Ü:[±¢wnK–…@DˆÕRS¹ h¤P´ºeAšNʳômB馉EËMÜÈtbŒÓ3"}QN·1¿f  /H0ãäW?&ñ›Ð*D¥§É7Öqû/Ë´ºqÎÝYf•$ÜÒ@QÔ¡¦hµkª§r‹ò'²bm\”a6Bêc )åÕâ3¸[hå&ØÖ P Æø[pé@é­—>ƒ$rà|`: Á!÷£±Äiògøª§I^i–Rt4 –ÎW(…pé‘Ó,½f\´\ÎÀ¦‰$+W]Hú@=˜õ€¿h‚F„…v!Ò¬Ѳ’5ͺ|QÆAbÌ 1¦SȈŒPJR3Ѧ¸t×+Â#ÿÙ7>ZˆèùhÂa]cŽ!†½2¦BøEÛ)`H`äŽ „C§tYišF¦ÉWº«Îç´fä– ¤)12¼\#<°¢p‰øiq 1¥W%¿®(«Åçsdi¡Ž©Äh¦K7J‰&dúª˜TãºJ¹n“ÂÙò!¦hÒLD¨B…¤ÀÛO8kR’5bFM¹©ÿr‚Ž©§¯ñå ¬jéà@šBª„ˆÄl<5ž*éð•ÞÛ—” =¬Ïð(}ðÐRFJ b€çT »M1]—‡ñcÉápdmåM±€ü—‘ 'Ëò7BèHy‚¿»Y«eÈ%;Í:¬V¥EM‡Ûâ¢ðžUµ`u©á0œðµWi´é1WH(ƒ'H„ñ­MÏåcÊyˆ2>…¤ð·Ò[¡8Û(ƒ ³B9åÖ( ä×[!´E+ÙIÇ” ÷“2Áì¡|ŽS䙸¢:AKyÑ”ÛÉD ‘«bl&^b Ä‰Eÿæßþíß,‰®ù­Ë+3BrFŨ¬é¤ÓµG]BÈüÔDÕŠ a/)µ¤qDk '¿imœäŸ›'ÎDjO¨@]õ`KgãI{6´¥áÀùÓ—²æùÑpê¤ñhý2H>òŸa‚ñïD´å[‚d»‘T#¼MNd#çÔøë›-Ä-g`ULk¬.:\?|ähL™Êú\õ 5¶éâoš³étˆÏe«ÅO GKá|xæ§Ð8)þùZ€ÚþbD€äO‹“…W2gå«þ"Ç7ž²ß(ÞTúhü@Q–r‡Ã-f~„¥$Ž6~:'ù§z×OJK€§6‘RFÛ¾‘ee!;—¦ðùÔNÎL‰¤"*qg]ˆ/“Z'Ï´DQ`m$Ž0Íeqt’2¿–&[¢‚35H{U(Z5Å42ÓÔŠòsŠ6â KÉ1ÆJvYi&~—¨«KÁääÃ9–g)!Û%d«Àÿ´e^srøõT~«ýî?r¿+©Œ±¢ýK²huÀgµ[ß|V•Ò8E#MYuñÃ9)‡ Q3 Ùðý7"ˆŽ€“_‰M—˜ÈÓÂçpW"Ĥ·]¶‚¥#]¡ÕâÄ|2>]a® '+e뇡Ÿ½Ub”ìÓà%Þ"°)HydÎò×0MÎðJIYã¯JÌtà¦FRñof$…F9ƒ›¦C!‘jÝé “qª…Ï7íZWáa}î˜ÑŒ‡´4‹­^Scõ´(4‚dS´pŽƒ^а¡VUTV!Žþš6Â1k©¹Àq(À&]4BMò뇃–)+Úz¨+`OkÓZ…ÔC½E+]ˆQÛ8ütóóøiíMR–Bÿa'7²PQ#BX«ue¢ÜæDF3%e\J»QõÕ’ŽÐ4…5LŠƒcíâ¯V¡»"¿i„І§#zxÑâ8›Ö¹*ëÏj.…•ÛUæ¯4¾¯|ÃK/š2Âù|¬›ØÂŰsŒÌ´zMIì‡àT@ˆ™)K7Å `J|8ßTõã—.+fÑDR+4$p#‡)Qé˜4MKiÜÖG~’þ`@¾Õ6åÐâd µ«Õ–˜Ão9¦åÖRÄd…8øøŒ~!Q7-dš²‘Õ ‚eÞÌøÆÙÝ3)äF"üh!˜mÚøt–ÏçtlLWt ¢ìÎÂmO8w–PK‡Szü€å%R«ç‡^v‡k%ܸV¢Ýx>BMHŒCS"p-Bú «D4V[hS‚<”ã$¾û­{¡qEM+aŒSÈhÙzˆŸ&0¾Qt);(‹ÆßuÅd®çhMù dÍ'%¿–ÒÁLvâO/)ø²¢Ub#'Md;ƒVVUª '‚&´Š)”;‘MñmQ?š%"1ÍFÌ0–8šh| GF~ýðY´‘9¢…V¥éðU\]kÐØ8‹ …˜6ž_Ç Ô½.ï&Æ»…j"ñÞñp MQ1 W¯ZŠcôâßÛD6M3B ùU䬖‘Q2ä­°ÕÚx Hïx¥i”+´D)8v"±,`‡­ŽtZ:SÛ~öE?ýŠ&ËJäP˜,P®i¯”ÀB)›fëY.~=´«D˜Bá|`µR³]uþÐ9@‰Õ• )7rȈP!‰˜üø˜ Ñ!gÓRæOÂÏ–â³IñjÇôáž!#°N8Jó£Uóó Z7|á©ìHn5m!?YEsfwU)Mãð™,&ÔG„¬z]ÈØÃ{½ÍÑI)F:)ÙÊÕ*A8AL~%á@¡“ù<´j£©S.Ë…d8Z²uÀœ cÄI–Ï)úè}.U ‘ÝBÚötʲùõX?q~›Æ‰““ÚöD]ÑÒ: –©èÝ3ä.WÏÀÌ4§\>r=/”`SÊ©µ|8Û´ÒÑŠ­‡×*…'郘"”øòÑ RÊú}ZIi·iÝT¥„*3½0!´–ZýoG¨æ’MP7í{äÀ.•º•KÓÎL·T>DÔ3ž9¢õ“BQãÓ¤ +ß4YcÓRâÂg8­Bi¸á-*ø &Q”Ãà*5oŒžBäú7zm]‚ÆÔÐê­ºFÈ©÷sŒîÆÒl 7šæ—ÈÏFS ²1GT]åì‰Z[&g²M!h|Yþ_:|jü*xÕO„fð‰‹®"¤fº²çß«Tæîbª c¶ü¶Œ „´¨Uñ+IÔ›Lx„r]NWåv¤w^Ò,…FS²Ò' Y '¿hmX­)kÁ˜ó$? 1‹®¦Ëâ¼rÕ¢)„ÀŽîÏUŒOÒJ98|æ矄'?¿~Dm#Z›Ð5Be"8Y‰Æ¦mÅȘRè@Œ8cÆ$?ÿcÉBE[_º¬­q)B“m±u»1…’…#@j¦­(jÌIª•B**1ÿ~v€Sÿ8ü˜%X)ÔÎŽC›—;°´ª‚˜Ê 4ÍšRch,%ùŽ8¼‡HÁ/¥.qÑ8‘Öcø«y8& ¤èü¥À#@øÆŒŸHÍläÀ MñYޱܭ¨h:-6ßvÅAà”È/jÊÙG¿Š ùjaúÿždOÖ$›ZšÈ¬º…Ô­%|¹ÞŽL…ê‡ÃªX­t€õóSç³-§Bœ|4NÑR¨UˆäéësЛëSîkšl%R€°4‘ë™S”ÃÌT ),¾ñcÂ|ìjä«%ИÏQÅØBJ‰áóß°–cžé;Ò¨B a5íüäÿJ·Ô“5šÊbmAø¶#¾h ¢YY@!þ¢9Cì~«-D°Þ8ËÂY à‹ñ8D@ã³ÈÆõnzëÔ¤lQŽÐÔD¥›вZÊÝŠ¦ümÜÑv-Ç­CÑÿÿã-úª‘¦è +å0¨$Ì3g™’‰A¾`èw‹ïÏϦoUíF7Ž,³í3rTÞqn˜¶J¬ÈB£¥/›÷ëÙÂx4¯8F Y&è饬±*1ùHã´kYn“<¯üÈ EþJF gîˆTŠo–oFì5ù\R¸¶RüŒ«Ê6`Ú±ýè‹ø·«Çù3¨ö.Ü›­—¾Ò¾Ç×Í êVVe"ó7K¨æC‰”3L@Lƒq”7pÔh™pú|RΙÉüôcšÛ±q]ÃA4¢åõ #ðÌ»­Râ6±'%‡ãu¿yùqάªr%&í|†]±MZ¦£Ühæ”}y¾2šdr-²ÐE–a&1)[2Y5^Æ4]œÀhwÁÈ09Õ™ÀmØKÖ訴öd¿âÀÐÈíìCêØ’ùÔÕç§Ñò ÅøžG#"û -Ímù~ùK#tiÏA“¿ÜˆJWrrniòÔ„æ&ø¿]í@ЬZÒgEÀÁ]oô×L+iòîX)ç®‰ÔØhâÀF;6N R»_pÉ‘>xû U[¸ŒêËÔÞÂo/þߥFÛ­’¬QWÇlÏ—,*n¤c3äDËÉbâÓv•‘‰#Í=U8U$†™xSjéBÒˆiT¦/’°#Àž2=L#Ÿ†û‰â…ÑŽíÓ&²õdÕ¾¢ÚÜ rÓÕ¬ÆÉ»ò¬+‡»\»£ê|fE @@™?ì}Êp·H–R)[/·y&&}ñâ½.2 ·F¥e†ª¢ÝÈ`ÛÈÊ1rGŒvy‹)Mtä<%àX ‘¦`Ž—&@ßËÓVøz¨Š”cÎ ¬£d¢È—‘¼âéYkq¬:€·Pp@UÐ×RŽl rb HIãª}º²%€—óIßn1}Ú½ õÊÍÒ«ê(k„e9×õý”B¡íàÈE$­Ú$•;zF|r¨*·R˜M¯K4ÑåOÖÿnO“’£ªÙñ­æVnÜ ýAQ{½eŒ–2€,Rš)(OV;Ò¸•øhÙ³½NßWHU-âüûºí˜¡ýç¬X6”ÆóÜ4}ß­Z‹’£¼µ}4ÜÒèíóÍPW²ÆíØg¤Ô—Y-=‡¦Ó« ŸÌá"2+¥Kœ­(a >ÏËÙôÄkÔnºŸ9g2Y潊.Å™þ•Á5gãþÒ k¨Ü•ÃEÀ]c+Þú'X©^úYa(ù§DüGU{¢qLàiÒ;fŸ˜rb<Ò”‘€£ç3{{‘”>²—HœÀñá(”äxbѳÚgo—’iL¿MßÐöÇL\•R É-Ì#i*cÈzh¯3¬—€~’á]-7X»L“y•ÎeîÓÀ "5vdX‰FtU±A”¢*ñžçÓtœíªF¯7 Vª÷LºËí ×^®¥Ló:Ãß7޼z@y)ª¶rŽô[Ù‹åYÀdu…×¹1϶7äÏÇ‘IO³ˆ’ „Û0+@>ª-I üQƒY/,Të-×Û\ÕÈ+ü_ ÿ›ÕQî:Èuå6Á<1Ÿ€Ç¢±¯U˜ÀJÛÄ£ˆi%Í*¨úžº. ­VÒÂÊ%ÊZ .ÊÞ >Msçœa_} éì!t´­ªpì90Öëâ)Ó˜¸qô4}Qm¥L¶^üJ™ë"CæüæÃ mÂm{”é”Ê,jÃXhSÄÇå¾Ö]8M½‚ù½UÇdª>û$SÒ SNžs;“UãÈÄîø¨”Þjz²øå˜¦GšÎ_‹¼#¬J†Y•²[øÂ371R¤Ù‡]üÕ×µÝvSbÏʱç“ L Ä0¤WzõýìQ£lP[½íH½y¶‰L°.†®ïH¶MrË&‡ŽbhúQø®š-™3wYÌE+…‘¬"É-÷1a|"çU@U~ñõpi€Nšk¬JO“U½² ÐÕ*2&¹,Ú©Cæ½°jS`]¦„ûð„§d²ŒOÌŸ8¾Ñd9A@IÀ†ÊLG MäÈÄËY%–Å«dˆ©ýå_X[»1ôáL:ºMž4rkàý›Ä{ιÕ8¥ž­÷Òwb3gN™&CGñê»OÓÛüªþùWQ¶Æ†6â•…)i&,Fl"íéˆHšü‘ç^j«AYÄÔ“Fß ÀmÀ4AcÚŒ `Ò*@ÊÚ#«Ú j4…­£È$Xoû¤t¤é›&q¤,b´ÀlÅu=ˆ^&À„iÌ…%Lwj¿œœ­Æª›¢Z°*ˆÉ€í£” 0+LïGïV³"öxs#®W£‹èŠñމfØ8ž>sGÊ=Ûº´«¶ÕdµW"sœ¬ž ò,§É]°v>âýsI— ñßtêc¢LÖ]à4‘ybâeúwFïùààV€Ÿ®H±Öu„•ä’…ˆ ™´Üx2|‘ŒL2_K]vÄ-™¯°•«:âû#•\I/œçvÆÀHµ[ËŽá^©~P®¤q)ˆ·€Gjî.’CË=ó°£’Þ}º¶uÜWTHƒˆ³ÕÛ‰§TYåZ”à4²è˜~†ÈÚmÒ†Ú]özå¬Ýz™ÏYc äv‡œ•DL³ì©öÄÚ‡`] *㉛˜&+b>²c Ÿå-ÙÐzaa%-çy%ÒÓ×\d¦ó­i!¤#™ÆÄkI0£1Yi‰'Æd˜?œFžg‚eJQ# ¡H¹Æ¬”ÌÝß–zi4&id %ÐÏè@†È€A¦ïÓ‹JeGS˜pˆ©Ý1&PV¢yùŽœœà?ÿù‰aY¨ÞÉgÖ«ör(°í 7 ¨Q®¤]8š‹ ô0=@z˜“C«ºjÉ?^ÎMKÌgJ>˜ZšFa½F³ªZ/2@‰Ï?Ì9=¦ ÎgJ|3üžÎ¯å{“zLµÁªamGØYüãø[Ù¼Ö…wCâ‘o/ìr—¬Ð»•Tõö õ«*(‘éiDšÈ½1xúF8*]ƒsG%9°ü¿çíá2LжX½=®h±kyÌ{i`LxWhzÇ j®L_ Gí—>@(¥l®@ ¸Üõ;bì3g·æƒ”‘VjÿãþûR5gdGsD¿5ôvÓîÒíÚ¸MÑ¢ºö&¾Õ<¹M¶€mø§ÅQ4ñ¬õ‹ï/Á)\¬#,*ÉU»€£7°‘€°´Y¹vVª‘sp™RmÈŠ-ŸÄ@nÉv´ÈZ(UáZð/Ø|h„–¾„(#U…Æu-Uc’Õ¯ô~ùqN $h½ ÚA{ñåÅÓh̤GíH¦êÈg†Y9ç&¦!vÌÍ«–I%VMÔ+RÈñ@b< EŽ<¢ûdävªžÂï f®—Ï@†mK£$á|R&“[ž&* 0Uÿç”PÞ¼c¥•ð1òë¢Ú$dŸ€µÔ¥4 ¦)5Òs&§í÷u¸òT¥ï›ŠwH4I@é9ÒôÇ.œ3ÍÜøhU•ª6—lJšªr¸‰ e"å¶ðªʦìS@ôüñžR]°.¶dÈz᎘°Ühí•4ªÖˆá‹6™fLsu‰ÈÌ3ùƒ_zŒFY´Ì»*AÕºhj‘Û$^_©Í嶺öŸ?Üs›Ã€Þc´sý²Í®zt77ïx<[8Á”½7È èõL…’54ŠºšŽ€U‰¯êÈ´ ‹0ÛöDÎô4u%ÎsüH`㪲í=SâüG`D¶º9«H½µÜ]Î2ž˜Ü†;R LXν6¨µ÷ðGÖ… Н„|¹9ÊñÇ$YW« i8׋ñŸ.†1Â’®²‰Ju5ˆ3M̹Òï—T˜å; î±| ®³ž ²ãfOÖo3ŒÀп™ « @d®´#iÒ—i„jÙsuÚÜQÕJÉz½0ølY‰MW®EàÆVUÔȳ}zjñJ“aêݬ9—[Å”1ýŠÝYðâ—Av´€Ð.7V¥÷ly-¹Éµô;Ç6÷‚~ÑN ”IØQ„Ó;f.ð>f’Ò±vù]¯ët5 åû{9÷ʶF‚Ÿ'€ó‰ÄØd³ö³õdq^Gêfˆ¬1MM 3B¦0VìøvÁªÄ¢j½²À4.LéS ÆÜz@øM¡¯½–¾šK¦$+½-°¸Æç‘ÑèJ·@dSd¡…F•X¤t¬ÚÆx·ì™x¶ÚÇ÷ÙÀ^2½ [‘ Œj÷í8¦Osnò8o™¦Ùe¬ hçô Â8ʙҠí Eµ#ü~"Y)Õâ(®Á?Ž96tÙ”wnιÞL0³m½ºä¬4ô° Sr÷ô°È è(kÁŸ=¨«5 +0Öè¬õ‘myt¿/Y Øp‚˜¶Œ™,#z T‰ÑïsjÃÖ­½.¼ðæ!‰óŸ xæp²²«¿ ¯öûMË6¡ÄgËóÔ8Ø>¹l§áPLÌA/YàW?ƒà2«”14Z¬£¿5M™¿,òW"ËŽJvY#ú{Wo¿#žÐHܰÐXd3¡$ ¶U È€°Aª5F:¶[‚æò¤iªÞĺÖÒÊdáªùôTÖÿù5h­^g ]ÚÁÇXW•²·²*A%]¢ç8q ñ‘2Œ÷Á¸@‚ ¦ª®å¸ü>*¥ #-³ç»®5ö…§é؈|:VåÉv#|Gs ©4>PöQsiÒta¹…ä–ˆÉA&nœR?eβH Tˆ#m²§#óqÁ‹vã@  ¬Ë1ÏØ¥ÚÖ‘‡ª „˽LðÈÜÀ®So¥L*Á@sÓ¬Z{GXœQ×P§…˜€¬ä¼ÂïG4/Ök$ÈGÝ'p†ýB—»­P•oÓ÷>1o™óxîÊ­^ÕÄ=Jšö);Ö.k‰Ô²)VEŠã~´*7ߢún‘3ÁÚ‡w/ʦ´ŒÌªÝh½àuÁ‚¡¯½Ân€€æ@ú”¼F$ÐMÓ´~û×KY8æ ì²y:úù¶ÞŸüŸ¯=ëe%Ó×%ïÖ°ÈÁ”ŽH™>¥A ×E°Ñ ¸ãøÄ•Â]‡ƒF9ð àMI|¾³Z‚iò/«Â€à›¦'ž©ÔÆYÉ}Gˆ» ]‰×3Û í4¹y_1U1º­”ÌGÕ Ä‘°eઽî bÛª2Ì„ëm.ܱg¢±w"Ù[ÍS©ã–ßÚýxÐÂ4"\îi¿!°@wÁߎóÓ÷]Hß`U2¹°O+Q¾`Ï I™s)'Î3Y¾Gš¦ÅZC à0ÏebGÕ Úa ¨N–á^µq”@ŸÎºˆ óÏAþ¾»äÕ¸ò à½X¹`·WînŸE¬j8«3û÷S5¦¨®Ý1‡‹qªËH‹U­«œ ÎÙ’õ:¶Ïô˜½Í«º 0B Ï7ÂHo›À‘YßJ¯Xµrãö¸™`Ü4e-án6…žRÐX Ã2¦jí5Îs>³eR£.‘ÀChJ¥H™§¬…²A¯s¼/cþhÉåÙnVæŽ4È…£YJ˜mW>ºçÏÒÛ}Y£ÃuQ^+ä÷mc=…‚lW¿¯ð'ìŒøº°£8Í¿ŸÛš§WØCµu[ôÊÏçT‹,r(µ À1™)¬Žî÷,,óg¨R#åkn²È¡éÄ<Ý}Åu…·†£ÑÞÂЫ$gEïØooâ•„®š )Ž›U FxÉšÅÁþiâ[?ÓŽ)»²ÞÜ€>”Žª‚>²ýk”3lŸd0¾ÞxË\›ÿIiäœSZòa•­Û b‘ ’c;Ýâ÷ÂäPo|ºŠ™¤ì»¾®ÖÐ’~?RŽá£«# ÈÎPµ@Ì£h‰ÆqAfdä(WÂJ5ÆÔB#0JÉ<{G“ÍßsL/#EwÐLÓ ÈF§Çion-{çðZvGš3ì÷yžõÛÙÇ,c¶?æÅ±¸{Ò¼æ£ÑÕKL¦Ñ¡*ÏΤŽâF jÌF¬·†Ó¬Ô†›ëï"1@»bVÕ›3Æt퀄R`]J°ÐX/c<ýi¾ËAã"¾Ý'p7BÕÑ£Võ`ñVª_K&_c tÎÇò®Õ5ú`*U•{¾5ë­½\/Ü6­u¿+ ;·À4œµ·+€·nãÚ[©PZ¤Ä¯7#ÿFTÂ;2ÔÛ¬P¼½ÄM¤ÄSâ{Ñá˜Lä}ý´ &M†‰·óþÇ<’’~h=˜&q>Û QÉÖC¦vÕUÀ¥%¡TtqX YaêíÝZתÀÌWÕ5“¦¤‘g8¾‰ÇXr‚¬lîkظJõ}C{)ÙbÎÍý£—À0=«1ZP« bd^Y¤Ï§] 6;½ª_/ÓYOÓ;±é5zôÄ"$1MWúl€ø<éV…sèÖ˜¢ª’ckÔ+#1nç4ÞfáY Ì6II,â õÈš.ã‹dF«†‹¶‚µä€{VJM¯±<¥â[9C@ ?FoY¯,r+ Ld@£jí@Šf‚@þyb¹õK-¸#ÞÇ׎Ä4ôJN FU´ÞsF¸ÜDøŸÿš…¿¾hS{d¹ÔN`*Áú½mñëÊŽåz»€yŽãÿ ê"S¢LŸs>žæ._;Í&zÃÖ¨K¼#ÂñZÂÚå<+…eo¶* ±ÞÞO) Œ.Õ øû’ ©·ý òl–L‰<þß×mæÆéâ §Ôkh”<™f%“12ÿU 2ºÃÜÈR(Áã· U|+M†)ðÛÓñWüþyÆü¾ÿ¦¡÷„û(]Jx’ÈÚ·¡q˜×­=O¶[Î\¶üÑø?=5›$0²0žÚ*úÛ ¹È ž yøôe†òŸ0CœÃoþ?ÿÄ;Ì?Ǿ[äfI³˜8&ža™TåûôŽ•âçÙÅ3¡©ÐÛ³V² YÊW Rl¥–©En\aEÙ\”ªbÊ0=8“®C2&>GŒ’˜aŒãJªþå³¶ÛdJÝ1™!`†¦Þ÷viTÓïYeB\ä ka%úa#j§ä häJ”pßµ14 •;Ê0¨ëÍUÏŸµ³¤Vvô‰‡zõØÏeG ¦1bSðª)Ó(UM)ã#Ûª¶ddË·pþ˜HGJOÿÞ«jþôžlþ¯¾}æÆ¡*Pc&›BÐWÓØSêÉ8f¸vGzÇz ²H 7ZÎ6 ‡ÙVª1¼%„ lP¶} ­J³R<v)G¸¨±/F—PÚ>5æ¬D zSjQ97¶˜Ó ½|Ú1ZèÇ)WÚ»N§øÕS¶v½íL0·Zz¾Y ™OÇf!s¶À*%Læ(ÓäLädcÉôrÓØ·ªjLÓ8XÔÎSôÌÓ;U³íêéåö'+a@̼FG€›|BÁa³ã(âå»Ïyâô[‹ ß«ý?O¯q>µ;2¾?eÞ¬ÄVô ‰Fl‡ ]ÚÉj)§OÞ†)À4rU¦G·¦_æ0™3Ù¾­6¨?|6”žÃ<ë­½Yù‡É€>ªZÚ$7Jíù››‰<ŒƒêÚmÈ©=^æÓh™Æ¿ÖQ—£¥£Ô˜[x펔åÛô¥1@8°LǤRÁ!²c·»Ü!…•Ö•ž† WCóú¨æ£Ö›?,ßûMÿûK0‘žr5#€:s)ã‘ô}<0>&ýÚë-Ó\Ë“0i¦Ú591¾’cw®‰¬!ãE&fUŠ”së= n2zGí"LC 2‘˜Ú÷öLÚû$ê2·’#ÐæÈÝßSÅà±ÞºÊÚ9Ë4” r\ÈŸÀWE†ͪENC Ë…o.[[/ÜU²dnu©¾£ã“)Õ%'Ë!OdbY8âÝe¶@ô])+b¼Œ—7 Î!AaàÏDçGçSÈîR éU$;Ïí´ *o³l{ž>™’'ރȆ¶: g²œ«ÂÀÄp¦ÜtUw—™ïÚ0Ù«ÁäÀ­ªãÛ¾YwÂÙªA@æõ¦tÄ3® 'ð2ƃ­·ÏÛ11’I½0}LiàŽ”"Ÿ%¸­”<=³Âs0«/?dük{½OªªÔ2z‘ܫʪ9$ŽAö‘9öç<Zë’û_{0m˜ìØÜñ@¹Ý4v£· †gïMêX-Ǽ0i;þŽÈ-AœÀUù„ŸÙ÷‰÷èÝsIŒõdØ>s¦'ÎM©jnHÕr¶²Y~ñM 3ÄÈŽü'´ ärãûœõž%~ŸëÄÌžøÖÏcÜ"1(Á<÷c^Œ^|–žŒÜ89}nã[és<ûöO¯ŠÙ§ÿjˆ³]V%kçU‘”DVÃV2KhßÓ¶|;ãé ß|#E>®¬T¼Û—?¶‚LÆræôŽ”WrEÎ…Z¬ æ˜i.“J_ÛÓ$«¤±ã¬rC¶„ö¶Ç›xš[bDSh¬ž2+g%¸Èví›bOÎŽ¢ÅÚ¤™¸>e%YµôVÂÀMQa°5¦O,cz†yÒÔÒQ•æÚ|>úމכ cú2ðúÀ¢*çŽ1án±­2ï( ‘XUðÁH ;¾ná¿ Ü]d dÕzÄŽkgŸ¬R_p&ÄÀ¦Ô’ƧyÜÕôÊo3ý¯šé¬;Âzï¾/GX¹ÄŽ)ë­šyŒu)ëM&¿ cþõÒ›.€”€G¿‚°ù«ú&½®x¥ÂQÌ­‡x‡|ÏWµçC?Yß¡É0祸_*¬ñÜ8ŒjÏ&™Ü ³7%ì(ªf‹/"UÍ’‘4} #1‚21>e]“9öÁ2ߣÓÀ\ºDW¾sN„}­*­=~ÇWt}#ÄëxJÀóïSÖøÏwPmŠSë)úTò¾¾ƒ72Jí[ѰÜðí$#E©‡Ø}wDÊ—É3%@&k‡wáHyËØðÊÞ½à9G†)O™ÞÑGNײ)˜¶"@ wLƒÑî§[>kßh#arëÉÄ«¹ÞG“RÖΙ!}-mB#2'SÚ½xÒ œÕ™tyY—ª,˜¸‹ ñ2™¦{QbÈzVU7"Í58©ÅÞ‘ÙÞ±ßè‰shâHzŒ07ÓÚ˜ Î7ž²å0¢½‘ðÔ» àÁÑTµÄé¹Vóž^{¸U(™ x›tl |K6¨R$F ‡”Ëkñô›’ƒ^{ji[2A€'€Ëñ瘃üŽcE)㙄ßÞÍJI¶j`S´ç“f†[5+Ï¿Aëý÷Üž*esÛei0±¾Ë5V¢O‰ÿÉ¿÷>Û sÓÄ=mL«b2Ç„eʶMï(ÈôÖ£*Z¬g²c²2ç}mc¶s&˜FÿE$g.ïCéýžúÌü½¦HÍýX ³vÔKÐ17£*àŽ²ªøévešIDATäÙæ3< ÀAn½ÉÙêöøÎ°ß·Æ j½ Ò\íYh¹R$¦až"L€w”_ñ•RP­]ÉžL¬}&Zʪ½v˜¾ŒÉ`æ™ÈÒ#aÜ5ôlp™¦³ªå0ÍÖÓûs Yi-É­A“³ÜÜdilXxIXÁ^§­ÇVÐ×[£Œ´|¥Ä¢RL™&Þ1æ 2æmÉÐÂÖHF&;¿ÃÂòú7`Ö—S®ÅñU:¶M¤#e]}œ h&”Ç;¦·r½À«oú¦(mz éa·¨½or®ÓCÐÅέÑ=8íõÖˆLƒÜ¬Ë=OÇ [€¸Ð®T–W0 o.™3 [%Œ[8‘ù;jÙ¬p&rwQ½ zá-“9æŒÉ„¦/Ë”»&àñ"íz䑪4ñ}á¥\×ÄëÝ>9üá[#‡Ä3‰ÔH#ÿóÛ5WXmßB²Àˆ|‘yazúªW{RóZ(²ÆjÄ;Îà3r?½ôÕ8} 4¨)dïÙ™ËÚ'°“mø ’)¥Tʪ¯ŸªæöU1ɺf¶1Ë5&^K;4‹’gWƒ¶J€ÀªqOIVÊ@Î-¢j#’y_ÉÚ_UUº§èdÓtBµ£®d5*Õ+G’ Xc e-Ħ +Ñ#1"󑎹ÍgVÄÉÖ‚Éçûëvg¢WGݺñ4€É4@ ôD]Snd`ƒáµtÁB©À{4¹Å—[ÌD`z þ5‡wœ'†R»wEvœÉ4£«ö¹Ö%#U±OþskŒ)]Ší€^Ñ à¸iäé‰ñÍÂo( ôn…IÙhøOµv2æç—çÞöõ¬J“l A-˜ÄL¦Ë1Y ͆«†ÝŸ Ã#€ŽµÃv{¼%HQã2MJ@{†i "p4¢‡žçJ 1Ž2 –+ñlÛ5ÚN¶| >·¾=÷çF†åzmÕ 1o‡ªóÙ1 ×8ÃË„-LfúV­Ô±ö=s-Ã@J]¼¡=|J¼ kÛ×N ‘O‚üåÖ«Öâ¸F¤£ÿ}Ø2ª·åSÖˆ´U³0"\æùý~=¶~mîÆÝߥºXRU+u™6Àl>Ž2e»†ãkOœ oL¼û$C ˜F„½þ¤FfhÉ4W{¦·a÷Œäl\GÁ6"C™^5åŸõȲ•[&qssÃrÐà¼ö›Å÷xóAáueÉD¸‹¬7ò4ü>¤’cKfظFçF†”x-øžÆKÆ÷ûŸü Q?}b<Ò%cv  ßM+E¤Ùòc2ƒòt„÷[{ãOL ýYô†#>üýrÐ9V.ºðÖ¥f§4 —²R ÕN¬w‚ùŒÑž›Û"õÒ``þã¯ä©õ,8´d]¾x²2…ç;¥*[A ëåüjÚ­öùר 9>“9BiU Íå>Üc11±#M¤¡HGzït¤#2Y¥i±Uko(Ð%ð0F{šª‘ᦄÓ÷L´¨*µ¾–¦ÀÉAI¿,1ï;¯30ðÖ’ŒO·ÈV1ôÄ«nPšåïçç&Yö’½ßß%ànÎ1` ¡Ë¼|ðù°ÕXÑk/(½y?âü“RVd½ÜŒh þŒÿ}±æ_#²®ªxíLÖ¤QMïØE0¯é•f;‡@Kªç™O-¦Jþ(S¸^¹x}°ésØE´4 iP Ôò^I¶X#æ?±eÚ'Ï6ÜЙ¬Jì÷9Â\ÁÁþ‚€9¦)ŽYmbüÈmKã(hbd±ã¶B’UBj\‰8&Rþ/…!‰f‡Þ>IEND®B`‚ic10 Èg‰PNG  IHDRð¼Ô AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs%%IR$ð@IDATxlÝ[¶dG‘„aŠjî°ãqYŒ•7†ÁU $¾ˆ?Ój÷Y˜››{ÄÞ™çTIMúÓŸþôïÿûûßÿþ7ß|ó¯ýë?øÁ·ß~kûéÓ'¼­õ»ï¾ûáø½ï}ø|I!£ÿß äR´²ÿüç?­x¶|¬Ñ2Áçù£ýˆ ”‚³oÅX™ä9ç[z–²€1¬j5ÕÑúõ×_kª—Õl‰­ŽIÐV•íìq Wnf¶ZˆN'…QÛ¶FY%“5d3TËÙaSv)­ByàCöJŽç³Vw2ÃX›9Açrä¶²º37@¤ÃÒ JYg„ÿñôDØj§¶I¤hÄ{Às½È§–];Y&÷R¿ùÉO~¢‹”Ûè’ lûô$V"‹ì%áFÖØ¦¢á“u"%Æî ²&‘ÍÄæl0k†JD0LÔ;Eo F–íiðé“#à)Ù”¬»›¡!ÎJVÈÂÄ(0lÛZ¯÷ù\óYÁ”§æ>‚OüãÝW-u*¡ÒWª­J-g€YJ.ªFJÙº‘ÎvG}½ ™ÔâÞÏùx0g«ÊÉõ2œ’æ¶â µ sƒ¥´°vþç½È&¨¼10ÊYé¸×EêCÖÖ0fkU=Eµ1Ô(€†!U!ÆUÙÂøŠÂ^bÀ×¢1ž§’fþ;êÅ™FÖZÀ›„,Èò´œsÞW‰¬9{eÿüç?Y¹imÅÚmHq°Úê»'Uwž€ØHméõ’U‹É¡Ëq|ÏB ŽéÇ6åOúSÃPö˜4ªiÏ…²#äV­—jb¤>¶•Rµ‡U­Q5ÍóYB\x|‚¸©j*¥¾3Êv^[$%Ð<ôÝ' *A#‘u±ü] Ò$Ž 0ìq¬EçEÊrf…¬4€’l×ׄ‰ûùÌ*ˆV²™‰=“4UnV2AÖ¹LËA9< k~‡u„žc-h˜ð´mrV«ªpo妪㤉ÛjKfåÆ![è†yV…Lßœ)­¶N¡¶y¬†©ÖÀÎ[¹ñ¶ùX)•˜¡1`d%lU5Ls)ÀÍô}é)¡™²T+sAÙ6+[âšâö&ý mùtó]u2ú”Jà^Åø9ë+r3³,Œa¨¤¦@&V‘¦Qmµsj[Q‰vxx}m›ps–U’ÃÓSwñv}¬š‡Û=+²NïûªdK©ÐE6[ó\Õëw}µÄ†'ckíö`æ¶L0§`…é ÍHy’Á|hºá=’? ^Va&ÈóWÕoÒøŽ)k[3jd­Q¯+E %™ð¤Z`xʦìJaÙz¥iBM•È*!ÐhTšÜÈR",ål‰3ÏáJ^ ÞÝd“iZ¡µ˜S>·p†Ö@ÕênªµnΤ/.vþ|”[ŸÇlV“R6Ò´€rÀaºRYA_­“NÓ‰0úv“J:TwBY#dÀ Þ„pz}a¤•2ÆCϹW¯K£jJÐÙUIõ54-qº õRb©º49=Òº,½‘Ô*ÑÂ*Ë@ʪ£Õlãa)>ôR"VÕjJpy_`cØ‘9wϪÔJi!zÄ¿øÅ/UYYµëŠÔ s5dwEÌùl*o%VËŠOkjÛ„ 6›Q=zx2Y³õzd(ËAp¦23``¡©­ª­#";ðù«¯¾BñmÏÅ.KN•°”À?»šOoRJØžþ7ðÔFj‘g>MàPë&#è #æÁ_Ê`˜Sš­‘0JhR"Ÿ!uv£î†áFÏDV— ó·XY)éä—!N½FR=)ØÊ¸»âFOœ^ àtýz÷·¿ýØV¡•RÐÈ7<ÿT( (O#{D÷#§ä9€yLÛ=ªr7 ØÒ¨5§BØEÙv?¶jñ{_õR…¡‘µ%p Ñ£±å™-™yàfk­dµ þVœ¿uÓ—••¬•c%ØðJJ!ÝF€ 6ŒÖܺYÛž ÖJ¬ =‘4 ¿©8U™Øò)42 ¬Ê$RÒÌø®w¤ ¬û>JÈŒ«Õޏ)þ<­_J ·*§X•º?J¾eÌæì•$`+ð4ª`|S5´ Æ?§JÖ'¢Bšu—…Û–ÕËËïŒnµ›i*J ÿ.¼7A­ÏˆŽSÇ<•õ㬅I”ÓKu'º(¡©…Öj­maóÀjuǯ#;+|G ÞÅjJ#”™t d@ª¸Â󆳒bâË_ ðá*èiè­Fâüö8_ †WXljmc¬HÑIUqp9¶R¶RóRm ·¥tŸM‚Mn$VLú£ïN‚ÎÞ¡RÊÖˆŸ¦›oH%ÌelxgÇèØA|KÃL )UB‘‰U`˜8…tñ½—¦WE•r‘˜¿Pµ#g‹I¦s½Ï»MŒéí2¾Sׂ)œ4ÏÙÄd²Æ“­¯!‘²FÙšʾ™(×¥Z¸.émV†¶ôü›?Óº‡º¶™Ðˆ~à•wR˜In€•••À*´ÃH#{CÜ?sÝõÒ‚³ƒ4!ezÎ=&'•R+èyZi¬$Œtd=\­§”‚Ûæ/ëÍQXGãq¶Å‹¬Rê.ų«¦ÏʶۥT€+‰!6RURâ4¸b¤’ÙÆ«5²’Z«2›ÕÖu¹FØqÈðôWˆ!æY•rÛÈÚ!…mC1ôü?ÿú×¿Ž¢vMÌ…»u$`,ŒJY››×€[³dšá¹­±Î|¬=r‚ú*ÉÐ ÷¤Æ3ÆèYnì 5:[µ°~±0F½[)õM)Ë 3ÏÎb ä~:Ó÷ZKy0L²µb„^0žÌ̆Ç4Ï”>ó7<¯ l%à 6-Ry®AM¥Ž¬¾9 ›ÇŠGæ¦ öÜÍïZÜmdÕÓÉgU‚U}»%«@ðìrl«í7<[xYVÊ3dî¥7䳬J0d¢ÀŠÇ(t·Áy§8Ÿ¥ÍoÔóÑyÿ ;ËZ–UxŽtZ˜‡F¡-ðο~<¨Õ«Üfà_¹™Õv±Ö>LdÀ™4¹ŽLœ1ÛR°›¡7C+…Ü`¶Vb@9,Û£O†I¹rí¤0•›Öw“aXÝ¿Ü %†§ë,»p&‚‰ µ³Ò Œ.ÜàRfàã0²E†…R #ÕQÕq|Ï4!™‘`« @æ0@š‰söp‘úÚŠ iÚš™›B&İ褔H[b+7²‚@ðT¢£SèHŠï×]GS‚´"­O†ÏvÆàÓÊ–LV#ÀV-lý0m²¬d»ºŽ ¼PhÃôòäo[ùÖÚ¥DŠ®h­;7ü3Ū.Rž{ßHÈ3\_z[Ø0e¥I™¸g×ûŒÑ®ñL¥Jm2[xnHÛ ÑIekZG]„[š‰lï*À>Ÿn¸ášDá3ÅMÇd²”¶©šîþ1¥`)‡²*Û˜Ú5˜™Í€± 7•-^èkÕš§¾—; ñ† Óà‘"½Žø ­ <™.1ÉôŠïãÉV¶{¤gkU°©ÚÖÚeÎo+:š?Jô”œ3'¶5¡Šæ—jB> ùÈÂËî‰Èº@þVáæiøãÙÖbÃTNC€¤Çܺ×/²º(ÑÎ%ÐxdÈMH?gJÙºøÆÈÜV9^V82½X6C)ÊÆXI×eYMe÷#e)•ÃR4u÷³&=”FÐ#%€x°Ê:Ã}'~NEÙµ#é5í~òϰ‘Ô óXi¤š Px&¸34^ouVxdþ0±³­E/%[2‚ž»Iœº^›_U3½·³âÆoå#0¶Ú +\Kc[&R­T¸ÆH”,ËÃ* † Æ‹ÎX•UŠXøV)ã)·VNï}øü»ßý.¯.MÝiÚx¡^eó«®x@êúþ­!ô+¥\Ø µ"ŸÖã{›âF2oË6qÎ×ãå#EÉ™À´ %l‘NìÕ—2ÃLRcèm•¤Q¨ [z<€!#Τ1lUÄÖÚ集›·ª*zX*¥Z<þ¬DLÃ4g—#[SZ1<{j¾’ØÖè~ôòµÂ£VIzà •pHÜlVgÁgkËÄÖŠ!P°¬‚'gÀK¦høºøWVôuC °ÇD tçŒÁÇXÃïî°Áê;ÑV_Y>VúÜJ™M¹”‘:æfS.+j¡Ê§´`bá,V[<¥ZÉ¡”.|`Y²¶†¯Ø*éÛŽç™­£È›ëB¦g"´Æ§$ckH!{G~ý›VÕÖ.gâH7V“Ži{ÍÎ ¹RlÆ5šfOªSÐL¯Dt? [2+¬–ØÚäÜ܉°¥R5Ò‚‰*Œ×YyÓâ1R•àºXy(ÜÀ^B²” LÛ<] ^Ž ð‘åÌÇKR¹&A)¼˜a“/ÅJ—FBv"Àa­RÄÅ0Þ=@ªa*|kÏ©Ó[Y™“€² ‘jMb+¤Žúý#m3pƒÉTRǪ`UɦÁP.ðk4¶ÃŠîa¯2†¶0P÷µhKé,‰ázI…w3¶†¡ ØÂmáŒË¬<##b²’5\‰•B$gz‡Br¸ÕǯJIV ,‹Ü ¶Jr¦”òâ)deªP")1°f)+†yþ0Ïl­ª–eu3ç3ØO†™3é˜Vb±r؜ⴹoÑæä&(›G ['J ×ìõ#;^­…­ÚF%ΗÂýZ°­$“úb8×ö JõD0œ•+™ÐȪEšÆ¶Âø.ÄÊÙañV¼lÀ¹6OÎY&[‘ÆOáx[€›ñ²5X¤!1ɬZ“™täem“X1ú&lñ9ØŠ|z¦¾´óe˜ Ò Jø¤ìß\%ÆtQ^•F¥”ÒKù±¾·ûQÅèû“XS'M°c"›3-Ã9›A‰µ¦”MΤ_fðZUo5@ ÷˜:˳¬ÊÁõêhb¸Ç¡‘ÀÔØâa…Ù‚[þH¸¨°S‡ËžqïP2M•3İ2Õµ|½~“Qâ•càÎ4F|•[Ù¶âéµ s@-zç!ŠD)¨?øÆteŒlkÙŠ1 U¸ö”14Žê¿öîíñf”r/MFf\«È01fÀhaµmT%ôpnV˜¡ªžñ¨cµuñ;%%R91RôÁàßHkQ¶yàü†nÏÇʇ›0ž­ ÈikµUÞ-M_£†aK¹ªuix< UÈ&NØ&ÓÔUÀü‘Zc(Ü‹èÓÛT4}kŸ܇Rá!;° ú2™s„ÂîC`+ôÕÝ–U³ÁP•óüÉ f¥®Æ=×Åð‘7yž>†ÀÕZðYwXJh”?}“˜Š§m‚Öe›Áø§¦#ÌP;c ™4²¦ixÛëé(I̦u1*¤ÂZRüEwˆWXy ¥Â®Ô D™mX1ÝC%¶No¥/J±’ÕËV;W]ßÞ‡°•,8=Æ=°²  õ ¥”¬Ö–fåÍÓ$J²U¥´šÇ©­f™³ÕHSϪªF•[…ÙŸLŠ'™ÚÊa”ºpŽ©cLzµÀµ<³µÅ _úËÎÞØø@VV©šZe­õ"륪idJåÎë¹H1—Âä Û %§Ž0qCZÕâs–j %H‘¬-ÜéJ…} €5§{îAôôëî Ê1”—‰l‘Rd&õbˆiª¥Tù´æW"”xO`¶°Ö>ŠË7ƒT¨ŠooÛË6Y…x§ÛZl<嬈™7v&Ü6|YV¢ÉeЉ¥Èl¥©µ°º2)?ˆ­µs½°T%§Ç}aX‰{èó…ß³ Æ4Þ1½Aйš&låcUU—NW#)ãÕkµ‰›­á‰ÕvKVOèo] ´°®#Lo­„výõDV|‚L4ñ4(ht$èV‹L©„†Ò[¡>Mãm§¬‰–§Úz‰sÆJA£ ŸRZxÁj„äé3pfÛOdRJ ˜•¬õÍ}¹UL l€”;’ài£våL܉­Âô° Š1Ò¡e“©Jf­…¦Í£–2Œ´%°Õš8¦ŸAH·¡¾Ô‡ª¢;>M S°5Ló4ƒ¾Ï ^(o­L>ÿö·¿uøŽGAÝL9 p$¶²Öõ ‹±†94tÛø†Àÿìg?ëOÀLú€Qt¯±.3¤‘Mb%VâÊø‹†‰×åŽy攢¼’òLoÕn«T½ðL&ÏJú~¡¬ªr‚…”r'bE¼O#¾{3sVüUq°fhEž£Þȶ”ÏÐÊ$BÁªÈAaꢵL\GbµLðJȬª”àeuAз%@Z™x;ë®D¶Ö4Yü˜¶4¢FJôÒg$€IÙlÖÈ@nFB*7^}·J n˪¬Â»‘m[2ÝËÂ< ÖLð#õ µ¶R™¨ºÂ×ÒÙK±Jœ&ª¶ò¥—7¿¾Íà\R)7‰áe…l¸*b†•Ðã׿cª ìMð3µ1z7zÊÊ)iTyÄ}µ®ÙËÓAl…¾²&!Ãë¸g*Û<¤–' XÚp-ø 9˜°CÉæO©c€Qµp!µÈà¶ùØ*a«ä&Ï“ mùKùÉj…ýdÚØ<7óóQHÖkGƒoë*`µ¶d¨—•¦#t4‱{¬JðÀ„‡U.ðJDGëDU5vYŒ¸ÆçSVØrài ó¬)À—%«$7+•§Uʪ$½T@¶ª+tv†é«%À€ÎS­çâ…„ÝMÈR6aÃÈÒpMV‰¬¬‚>+²¶&ˆ³²Š|²å@Ó°ÛšS!¥U0TXS¤ZAìý¡l¯÷ëý¯_¹™(e;¦- [[¤.Él;‚1èì*¯e]‚I/3ÃŽÓØ¾‹êå¶s°6 Ô:¸rdÄÄo<¬ èm}(ôÊʶQ;Èf–e%û¡…Q1ÏTVôjY}î‚ }ÐæÄ+Ü…Ø*iøÌU‘U«c%R”ð¶ÞC†dx lk:²BíbÔfªÀÔ"<âùéë ¹½ÎhÄ'&g)åHú<·ÍvH_‚¤L¯GJ&ÕâsÛ¶›×7&%7[c ò'„Ùê.Û„ô^9X(Ô¨•˜†ÞJ³ZsV¯ À§<^7›*k­0R;Ú”V£&« cáÑWh~¤hN¤¾£ n<«± „²ÕrÃÀ ÝvbJ ™¬- Qµd ]8 4ám â«Êsš¶¹5¼”¼ZȦ:è<öDZ²#íÌH¸Cv0ÛL)pgè<È?ìõ®JïÜ+¥{Ñ kÄoknó°µ Ô–U…¯»™tãˆRÚÖÔ NŸs¶d"ÿ›T¿BYæ½Iš®Q†dªÂ×òÜžà@r膑ôÄïVçŸNjNw%Ó¯ÐV¨­ O_ÇÎo<ÙÈzQ6 #[-¤ès“enmå9Ó‹%21}<*Û&çLÀ¹§#kÛ0V¤ªºôa€?Ð`¶RÔN6lËĜܚ¶.ÝÒ6¦¬0[kÁÍvþ4p‘¬¬^ÈL˜;cÝ­ ЖÀœU5ƒ5¬¼û¡¶xUô€J[ ˜eñJ:K©ü×ÅkIO£ Õœm­RuiÚ K ú²)HÀÓ4¥ fV Sv Œ Ø`ÆJ`íàp[ë­8‹”U¯Üô¬4zY æ»Û†¬6¬‹×¬ßþëþüŠç£|}U_ÇŒl TÁ"çªlÙºíçYúNP(‹_ È\ “ ­°”ÓÁŽ9Mæ•Ãj“Éç–†X)°bˆïŠº.Û&ÏvÛÀÅvÇ”<‘5ek‹L£Wžµ¶ÄÍéËß3Mœ²“Â@÷P¥dógÁP/QkJ€IdÇDz•Å>¬Âµ4 `3½¿0]r7’³BØê1‡œãŸ!LR nj÷Ä•ã…òRĵf%«°³Ð°Â\˳T 0$Àì=q“XE“ø¤¨‚Eg‘ 0i€¶rîËI™Æª/AL[ÐÅVT˜¸“²]÷ZØŒFpnÚ¶pU¹ÙâU™ L†z¶d)á F™¬‹µ6r<½Fj¿ü€N”°ÖOeêñ= 8 <#µ”‘;ûú\“¨JúæCÜa0@½`…Ķª(½7@½ZiJ©ê'tåVþ4²4n4Üd <€[+M2dþ‘ÍŒq…=¹Lâ×1²r‘@åñëJµJš*¸Í&ÀÄ<&Ìöÿí©a…”øÚqÀÄ+±%³v´d¶<ÃV3ÐÄØ †#Ð3ÇÛÂ"M¦ÔKÄ·¶µú„øs#Ò ~c3pÔw<&ƈÛö|}Œ¤i’ø‚€´Â‚Ië5> ¦oÀ[z½D8.Ò«Ü’žF9¦Zk¸Zb[ÓKШOO€aYž)­¶B¶Ÿå0ÒÏ~YŒBŒ5¥Fxá6Žé=T˜ƒ€­duQÛ§ÏÓtvÙ.`ȧÖ@nø°5.ˆ‹Äu¿—znU*¦¦z¥ÙTf#ë­ ö†¼¬ï‰è]~†ñã¥bàÉg‡ÒI&V‚Ôª„ Ö42óôÖŽCÎ!ñÜ|ðVJÝ­ ‹RYñ·m]_²™)9,(mAS¹-ÃþŒÎí¥{Ÿš-Yë.$ ²Âñ®E;>ë²òHYŒ,OØ c†!¦ŸÓÔ¥V…)ÔJÅ÷(ñÎ(•^µUJ•”¦OÀ$?ç^¼’ŽIo+h(k‘ÞÖ›&ƪœF lµ:Ô<#iÔú’)Aš°e¶4; LÓë þ@¶Šçê£T¯ºäI“­”ÚnFy,øPÖk…ªê•8“&q( ÌS‰Iô¶ôœ­H‘!Fʇ:q:ÀÇðV)Ę̭†¼£¥i6UÆØâU‰€†-++¬Š¦i­ =2þ²B “ Ð…0”Š—bÒÑ€‚`ÙLxš0™°õI‰¯]<ì>q2j'ãï,᪻"‡ ¨Uó¡·*‘j«VªòÌ-†‰é ¬l‘•›UÔ˪;M]º(٪匧Œä™ÀŠ·” —Åt Î|”çƒ'ȹUª¾¹Y…T¶éÝÆëÇ“a-¬”°d¶< PJ•­BL²ø[t–^HdÏ"3¨ê ™`ÔŠÆ£¶ª¬H+ÀZ !•#br8ÿ3 6ÕXg‘®U.Е#F•8}ÞÛNäÐè™ôòeb5Sµ²±r!ÛÙCâkÔÀHáºUyÕÊZÅ&!PBó[stiM+AÚŠ dù䙃- ª¬azŽ=ŽL¤¤)0E‡…ñò­:ÿ,e¤³ ÊœdŽñóÞÚ¡34œOÎ}·Â²j›Ù0iÊêÅMùy*7[ó ¬„„aÛ9ÛÂþWd»"·´S ÛšÖ¹Ž§ï>þVЭ…áRÁ´‚ Rß”‡ÆÃg+¥–U蟂x©â¶=粅ƨÄõ­Q#u´xbz^.ÄTgèûG)M^¡@¶ò'«u§ ë«Êï¸4ý¨¸6ç €F­všªµ-r³Ê b¸ƒØRÒ#1BJyÔïWšLÈâ³"6›ƒDâ+?.÷–ZgbÛœ'ý~±19`8dbÛ&i0&ºS4RzŒ­1lï€gÂuq®Kª¸ö§œ¿«)2kΘfˆ‰´6 ºŸ¡cþ­”â)k°œU­EUNaÍg…¹Õ¥ŽR¢ùÓÃåÞ^U3`d­X¶r ŒIY•m†€ ÑW T.•ÌŠÉn+«d†×à|úÈD|U¶«ºÉ³P¦‘‚ 0+)GîÔ°#då™–ªª1`®]Ö³î®`)<@©¶oK²fˆá磤Kk[©žió×&ÓÎ÷!ç´*YšÎUÊç˜Zøö š }™W¢–›”µ.J+¥5+€æ¼¾ÉÒu±ÚªÕ"F!\£”}Ä0BŠ9e×h;ÃL”¸7#‹ÄÐ÷Cµ•Ãm)Ôs##¨VŠ_Ö¶±ÆvQ#[z¸0Ì|”¬Š¡!‰eóW. ph Àb c÷tX¥A欋³pè[¦¹ƒœËLo% Ï*[¼lÑ.Ê_íx4ýÜ‘ê¹XMÒ‘ª©À7pkÛœ10ÍŒ´Õ½ìkä¬0‘ziMÉŠˆ·åótîP52U½Öϧ ¯÷ëÇåܤhjÇVáZôÁ—"ð¾YUYu±kÙͬõÚÉæF™‡µ@zˆ94†>Ì¿— S%kÏc®ªÃêÕUä_!H4-YñÀùFm&i.é$•Ù”ês·"éUñ’5 Òÿr…%Ë¡l½`«ròÐ|‘²uáÖ„˜H2ž"ÀYìÖhðkÑ#i”Øf{‹ÎãÏ\ VµB':=î«Ü‰”È’‰ÊY d[2Øq€²V[>4@ó +Á$°½Ý^ŸØJb`QyØš¹“οTïn·¡D¶áS2$³Ï$pc»lµŽŸÆ ¸ÈdãI%hHξh¬xJ%x«m·T«ÁdYõ%îë©1Z Ï™ q&¾³˜tždÖnž !‘ÂÖw™rB%M1d¶cªÊG¶7s]*<=î…çÜœ˜af|Ý‘…Z|¥¾ ®Ùÿû™!Kl•JS-F/n|žµ)9»a+hˆmM¢„žØjK€±l© È âŽÐYÉv 4ẚ™ST»’RdÄe›V*²Ûs ÊÆÈc«ªÁ(¬¹QÚŠ&d‹‡tif¤¨<ÆjkÅs€½¨+CVÂUH™líÆÓJ–•­rL˜ ,+‚4£JYÅ cŒAFoÛãfˆY ¬¤ÈÇjr§+kU’•ôùUX/è#“!m3¡aÕµÈÚZ á]2¤F ¹Z€²1Xù-¨må ŸX9«ôiê^–ƒÀ#w"'AödiÎ@¿úÕ¯På*Ëù ©ÝS)%õÃצ¶²™´ªºó#çp&CO¢^°ë 7*ìô¶b€¹væáFìyäÚÜO…ª9!а€Ó¯» Ícµ ¡„[¼äøp¥LHc+¤0Bíð‡TåÖxå £Ê×e…p>;².Uõæ5^M»%CàÞqÎR+ò” P67ŒmV˜g-R_þx—LæýîÓekøn¿¿éI†ÉJ-¤džgk-A4 ‡L8(ilUaž²”¹…wbAœm>VUx%ÖŽ¿Ù0VÙ¬NýdíŠ nßÛ.Ó`J¡©F¶æ±%€;&à2 XI%«£a²ÊÁÊ–²U!ŒLFi‹Ä„žÈx«B‘€@ZU ŒÇW®‰æ`²êDÇ÷þÐMÓߌ Iùl´.€lOv ÚÕÝ‹T ²[²å&â5ÍÖö4¾‡Âèž!+aI&*Ñk™ \}‘‰­…yÞºs®4²J5gYzÙªVn›2Æv©äja-dÍ6ÁS,+êN  ÃeåP»@)W3©¤*JäÙ†RE2¸*€ ’¦l…R¶fÓ½Zk˜Àý÷åœØšÉЄjiØVØöÐ״縳¨…³"£五B–'€)´ëKï–žEÖ)\i?Ú0”M%¥m²ª&‘%@µ—»?Ý/Ù)üëA-:K¶¾s¤º“ÊMÂJèÂJÇ”xJ©NZ¶FcÛ–¬F°¦ÅØâÝeçÂdÂC&Õ¥Q Û«[BÆÔˆX(DbD‡jB|)dÙdu—ŠeßÄFsÇ—Å߉Nw`z[ÊÎ^m²NT!ž€ÌV¶Ÿ›”¨ÜJæ°dUe^U%iÈ”‹'Ùö93g$1ÀÝXï^¹­j¶›A– S6ÀGªÛàœy¼±¥€}wLâôçä÷OÂV‚œ{å”cÈ®äËKeÔ˜¬Èh(m;c‚d&H«òΫ0¦mß ÍŒ'ƒóÉ„ “ƒ,CY[`†m§¡TKàŒ>° ¬¯U&•9eL€Rô˜¤jÄMÔE6ÐTù<³ùgâ°çß(àÕªð = 5€úçÐãe²N¬ÄÄ9ú"m“aŠ4¦c mÍoÍ'½u­a² ­0%2^G¿q6 CßJŸX•”¾€R#Ok¯ˆlGHLf+ð4¶­²Zà³’µ†©E Œ©K&øªˆSZ+LF€éÞ6¨07 ™TC"µ#HL/¤œ—;Kør_>ºxå^ÀûÕ°’ºÈbÜüÜ4ůš{4Û i´³ÎLªzÃó4É|¬z»àœ›ÙŸ ûéYÖR¹v1¡ÄÖ¡d¹!a…x+,š¿É ¦1[ÛèQß²Vo/óR½ó<;ŽÚçaâoÏóI¬oƒiÄgçêÒ¹Ú6 ‡l˜úl}vµZ¸­•¸QÍpé/ïÞsÙŽCÃÓmcÔvÒ†lød²l}TmSÚÖ ¨½°U^à1õÒ¥-âmÅ-z½Q•#;²BÊ4úÖ Ëa«‹¶MûÃZKñ„¹Uµ-’¡m“XõµV%+%Æ(˜ô˃@b:]¸^„2X9ÒÌKi*‹±Ør¶ºIbµ”VOª«È“ÞéaRµP¾v·â,…òž©O\-dýâëZ§Ç7ƒ- ˜³!óiBh€uWޱpaKo­`‹±„»¸ZJg´}?˜çiR¡,€'VX»ÖÄÈR”·§—Ђ¦çrÚÜkl¶n’-”UØvXUš¬€fž!½Â†Éðôx?Ç;Âù[cì°Ÿÿûßgdm”m3ºçŽþtAºòâžžR —Qî›E7µ#M@3ž²Rœó—e™PâHVX¶Ö‰á<[W˳ J ‹¯i+8 ‹Z×·5)€íHV‰¸Ñx·0¶záãªhz<¥6Y…Õ*Ç줶BŠg%esÈŽF&ÇÛŠžK?·A°i÷«å‰ñ­Mk•Âóð÷@çÙöL|ÿÖ ¦¼ÝÎRŠ2™­€}AÈ*IܨÚQ"“IÁY™ÙgS*Y+O¼rÛl[›_*IY ç°•² ½„-¾“ÒYÁxJµº¸ÕªFÚÒ$¶rëý_¿õÈ“5€vD¿ˆiuQ¢Ë'®<¥mãQ6ö¬âUij*ÙÖ4‚+Œ-¬Š(ËÒ”2‰Þ¶ãÞ|ä†gcêžåi”÷Br†y*qW4ä€ÉÍvJ¶ý-K?~lÉ8qk¤*Ñxñé°€Žm ”TµÃJq@X#Y±óV•¬Tx<2¦ñ`½¸Y¥JØ`KfïÖibZÉj”Ûg¯Ü(Ó$Fvp%낱UŽÓ¨ÍÓ{ÛÅRbˆ½HUákaU+¥u}aJ©É´ðЙ ÄsÈ&ÁÈR–‚ó†¦räu:­uì…4^O¶ÜTi¯‘Ë¢Ö;27L2Y]6an¢Qe¯ÇY0 €¦¯ ‹¥ïrl°µ³(„µd°µÂú¶eÞGIU«rC Yk†yZÍ–a²üÉên‹‡1dE&);^#@$1ÏúÚÈ:2F”%r#`X ÃZ”ÅÀ@žÝ†3Àšg'ê°LfH¼¾“C½à¦}‚xzž3Q‚‘ñV$FRv]ólª40±i”8>œ,s«­ŠÚ#;/ÐåçL¦£î@+0s-êE †9XEU²€¬•žOæðN‡ĘdJª¥”²&¶ OùáMP(ÅV¤¯/Ÿ¬ÌLc;Y¼T ^ël™».½(a¼10{lÕâM[…HzkL©Vsà«JcÛOü|rè=ð¢#ã+[&V‘ØV—N†‰Ü½ñÁ4Mâ0øÃêaåxê®;‘€;Ø@dš\Ìm‹çû¢iPÍðHà À6¦ÿíŽRJ臓y æ)•y‡ae»Ã+QHÌ_Š2ƒ¯ÄHpÑHø.Eùó 4àÐÜv¨b}:0¡QÒ)dŶHåôZGfˆ±@Ç[1#³²ít©–'½”o[$™³¦ÀÈœ šG9¼kDz;­Ü„*Ñx‘•ÓïG)Fj+ÀP(Ä[ëþä‘ùǧñèu‡‘Z}&é “ôŽ$«µ¬­ ·ÿk†ü+'Æ’!' `Š”÷ôç·ÛæTHPvyúÝ0°N 'n­)}W-ËdÃÓ`ºÕ.m#5¶ÚÏ­£6«@%p?õÕ;ÿf¨V!%™­”m}1c•—8˜&¥ÂÊ­ñ­x@h—¦ª 1blµÐI3ìU‘RÜ:ó¶1¶¯iÞ% ¬ó¤T"êH4sŒ½FÀ+lÎx)2!Kc XEÓÒËÚZáŽl[£ú¶*¯o)«8FW<[Ý»=ë4“ú:FZñÌ#á&·MÏ0Æx›A©iµL|~;#æõzÍjG/6$}c#a-bxºˆ ‚2¦Y u,[ªÖÙ`u±í’½$þª’¸*>d° ]lY™‡²¦”Ûž—ÞVÜêó…ï6lÉR*)l}(¬YÑàéµã†4¤í)»!h")…^”eñ4«`«‹TŒ,†³óbLM­Rº[ÍŒçìfâWŽ ñµh#­LªuÃj‰ ðH)˜ çc[mÓ†!‹0°Û ë‹Äl’ÆH Å“s ¾ͰB&bÎøe• ÙÄœaV‰ÈV²¹UN¹Z%bLʲÅ0ÌÄ 'Xk  ,U¶Ø…gÒ«Nc›sÊ é‘ ÏV ¶ºö@²™dÓPŠ4¾—Ÿs¯ƃNð¬‚ùp󮞼GFRÊÃlëÞ–• ТIÊÂøp©+<ÏYV)Œ­Õ6 øÕþ¾¨eÔ1¼’ôÕ¶j$˜ôwÿyN,Å™ÞcêÛÀýÐdëC*+EF³«[y2zHúZ#Ç|Îl»1ο¨¸Uq7,¨s·v›YXaµ­R ÍÚ—ˆ­ 8$Þ7w3µf×¢óÛfbí<JíØR•c6'²+–ZAV˜^Íj›n«¯ƒP RʳB6~†Í™ ²9)çÞ§œËÂlsV› óF*Ec+ðãeãµäSÒàoÝëç–# 7’ÙŽ@p¥H”(šFVØ0|êB k•ÝØÛÆKÀÈjõº#µîh†|d ‚ú¶•5¦@¼& P ß6}&ÈÒW6’PKÐÚfÓ…C3ÞJÏ3Æy‘ÂÑzXºÇÊË¶â… >˜ÖÄ4AÎ•ÐØ 3 [< PÓy"‡RÖ¬<·ªíhôpóÀô¶éP›8Ÿü[ÀšI¤ZJÑ`ÊE½êÂS¶Cm‡­ª Ì­¯  ÖT¥”˜'Fy¼Ž}SRj­×ºr¼iz—ÜH@UͰSŽÀÇÌ‚xÑq¬4¥Ö—¶*dX ¥€­ø@}'ÞÀ€ ä<ÛÊmc8ÓÔ@º™”°ŸL4ºXmoéYˆÃÝ€.ËRJMO)œ±±Kaz|}ùÔ¢¾”4ls†‰ Zm í’-¦*[A,¸™*UʪzW­H ÙlU¬d¯åëAµÅÚVXÓù×bb²‚Œ³Á¤„ŽJ0xø9†-rÝSÚÒX9TÒï&'J££¬ƒ×ˆ~&f ±Í'@PwYLsƶø¬2i†šÊv(Ý1ùtðÆóq®‹*†Y5,RÊ Ðg“ÈRZ}f™Èò§ì"E7çÆà‰˜@UÌŸ[¸Á€æ³U+„l…»–æŒî8V<“²yZw4VMB ¤D¸IÖ«d1Wõú0ÉV oHÓ2DV+Ä÷tð>Ý®ÎJOC KÈ”­) UV¡l¥FVc[“ÕîúC!ÅgCŽ¡¯$‚ªøÓð´µÂÍC–yÀÈdÈJèÙ6¹5@Hõ‚ù˜ô7ª”3IÖ µ  “UUG`zX¬°;,Û´ûl ço•¥_6’Ò${ á~<4X­[9tX†M˜¦^1Íi•ª{ŒÚ #%âÍ ­Õ`ÂYˆ Œ“¥´"¥V‘Ê×ûÏB‘²)ȹ,[󾄫¾Äaqo9%ã±*ÕH ¬ªâÉh\;ä_j­Éh¬d3¡Äðé\x&m›“^ÔÈ–Æ:Ð01Y•bâ°ÚÙú"0üanü¥`dL&;xÿQ–Žui …¶VJ)¶Ä§£C¥G® H0e)J]¬‰kGY Sá5­E½d1 ÛV2€¡,±PnÝIÃ4µk[µ‚  [Y²Jlc¶ÍÛZ(DfB&`×à)gE: 0U%ÀõŠ©)|ýŽOþÝ’Z‘ž)2±b4êN*W›!&e`¬@IÆßºƒÀ sÛT6Fz}kT—VzåBª¦i*ñ›‡ª5šÏëõŽñ©©Â%ó¬dºÔÂýcv n óu”š²±ñJ`ï$1}¶ù¤ÏG#z¼Ð ÎÜg­CµJ€‚U¶ôªxbÜ0HOÜqbÄmx&§I€!£ÑÚº*1Œ)¬Ýõ8Waë·gz€@k) 7 !‘}e‘‰Ê @ƵZ·àÉàĪZ£FM¹ƒ¨¶ÉßÊí(Þo)7£V]¤šçªÎÒ5$†²QÓã‘akå P»RiêõäëK#ª²&Ž±Ú M¥6F¤5‡R‘4sšP ”·Z[ó21·½ã`ºgµîI2é‘‘ÁRÍ ªµÕ%¸ªJÙ‹DS «Üd 3Cj!…‡;ÀHÍReÏ9ïwQC"{W‘fÛYJ<@ÆV¬Y†H¶1 J©0V¸í5>‹íœ#Éró\yÚò”ŠLßÌÇëš{Àµ°m@Ƕ ÆHÏŠÞ׫­.Jˆ‘eSb²*K/‹Ä¶ø°µ’&Ÿ É#R‹U…³©doN—P#b)çê¶‚Ìv­?ÌüÖ¿*yÐHUyê•^ðÄ*ºIdzä¦Lœ2«­Õ²Z«Z;U<‘”4”B‰Ë¤‡_½ï“¢˜€ª<•¨…P;ÎÊöv8w•Y³)¡´-`åîGáø=rV4¶j9ÇpÎÜJÌ!R! Dme‘ME¯cgOS^4C@%‡Ê¤a\fVVµB¡UÖª¶h‹If8[¹5a²;™¡-@£» —MßH†OÆC (iêØu5v#Y¥*„ù‹¶d1[æR¶i0‹|¤Ê’I‘ǶÃñyg¥/ ÅÁA"+<=Þ“cœK#$“gǰ•Œ`€R¡ŸgRü­M‹¶Ba8‡îD—øLÚv!ñ•à3)…Ĉ¶ˆƒQ èydÉ8(œ m¶JNåý8ï5Ø@˜ŒC[…ümÄõÚf°š/è;—lµ@)+ŸL¬šbå€-¡)Ì,…¹³ëŸ£,çµk€fS…'¶ ²0-œ¡­ãeñ¬š­ù?˜Ó [ME&ž•ógÅÓäBïb1½N‘€T퀷ì”Yiá÷$¨ªPU}­"O`&Ð#YÝÒsŠ:ZUýÏÂRÇ÷†¾•Ø=K""ÓHhTа"]N>p?h*±¦áÓ[{'sSÛœ¶9«úÝ9rAÖy1j1Ög$À®PÉž`]ºÃp%ªè…,2žfðwåÖH> dcp€É6ŒÂ©YO§;C2úæg"k~ŒUkÍœ©Pßæ·úaâoÅë]¢y–0!¨JV—áâÿ#Es P¨\ha¼×äœ9–c¤lv+»nçŽÈ"§”â`›ƒ,¦HkdW¾‡UæñÖX-X»n™!ÒÔV˶XE¼5&1ì"Fª¶§·…[ D3'«†€LØ–ê=!¸§9—“i‘ÆôJ``ÎHaÊË\¶ki»Qm…T®0¼ª|d¯ôºW5½­”­.ª Fl«ŠU>Vl¥¿ÄyEUQ €= ºØάï«Ã>3(ÛöÜ¿ÔeKì% ÀdÖ:®»²Ât.†kQm‡RKÌD–¦;©;² Ù<€msoÉùeèéO ˆ³Õ±BzUÂVи[ÊF2ÈMÊa)1×ò¼?LÊâ Te ÐŒ©ŠïKY·æ D`ÒÃÊ…î²M(«„T#!oõ9æ³—l-âK¥,ŨWn×ø8 U³.×2«4ÊsÀ˜€¸¯)‚îÙc‚ÉhŽÍoµ­—Ôdibi¬ôHV°Ù`±×U '¶)Û"aþE¼ªîÓðZˆi»wV%[wx2 ÃîÈ[¡#¥í5>oNþ¹Y¹E&~~ÙX2ÛΕgµ·Ïi$€¾BL Y3 +ùàÖÇå}áJ²ðçÛ‡º3ÙÂÚͶià]ÊÄ“åNæ–¾ÞEþéçÐ#­•Ô·t6šU5J,Å3™T o@[Ñ0€ªZ¸DÑ¿4G¸y3ÒØJ5ƒÀ-:éú¶Æ?É©=½ß?lcV%²L8èˆlûÈée‹L@\‰U•µ8 î“êÌO±%à úHã+a…¡é'´ÖA W˜g$>óãu¿³d<¥úvè7¹®ˆ 18ÈÀ“Ä, &%¸%æ€$°6\_LYmÍÃDªX(%4³U`ð²™´f‹$hM¹1nó×·¿’ct•®‹FGÛ®ÑÃJXÙ–µ%P‹YkµÏ›1F¨mN ­µ1²âãiÒä–^mƒÅ[ù[‰ Dµ<-`+j`"c:]½0 ÙYlk-¼Û\ŽU¶Zš)YÁ]æ?lÝÑ’l9‘¬ácÖwƒñ˜ ¼ivF<[&ZÃÖ ÕwáÁ-e†øZH•=3Ýß`è½Ä[z?!¤øWÒŠ!&‰É`)œߟë i[*$Jqý>w>òí9™nmá~„ïý°ƒ¨ÅØêØ UÁúŠÊÉÊz½zYÎVm‰ 0ô¥²•$ƒ…Ž 3!ëG¬­ñ˜°2In@cl%kžÛ•3¯M- {è,xq9OÈ\y©SBO\ ¾*YÁc†“:ªZck$ÌÚ%PÅ@ @d×B—œ­¢l-Xa8Ó%b>#iò_Ù$dls¨Ê–Õ0=œ³U`ê[ájïŸ"=Jd@zkQ¡+"†®FÖ%™F¢¦¶̳Q ¤D]”ÀÍÙI1¶(i’åoµ¥7€·ÑêɦT‹W›IúÌãóá<€¶uÔ.½ÚÊ £‹UÙH¶ªdsCòAVÙ@Œ­©Ff2±m÷ã»ÝÑè™g¢Q€F£A¿ ÕÒÃmÉs‡i1FÂá[ôùÜI±ê>+§t¯¼vʽÈ|:)¬™ó îMþ?Ø+EßÁSí'¢­¨uÃ0ˆ>óD’á+Ñ®*n}_HÑM63™È#E ´â“欄CÊ­™µ×XXPÆ+‡5’jž0çþÄKL)Õ˯;|ƽÑÀVú~c3a;g€‰ YkçR2po”°¦)+¤Ô4½G |G Zï8¥ˆKY6<™¶Hzæâm§ÖV­¬U#…•;81=e[n×é“} á¦8p#朕•O˜hìúR ß´]RV¤Üä&º#ËZ1 i¥ÄÑþŠÉl€Üæ:ÒH),Ô’ÁéeÛ&öŽÙ"mµö¼D UÉ¶Ý žKµô¢,†¿í§ë÷eVžY­›#lënµ0+^#å•D†‘uTÁ«Êw«$ÍIV-F_J[š&1Œì…‘ÂÛ&V Ôq¼­ Ç„9+a’CÎe JªBö©Qxʲž1Á|l ^ø”°T9¤q.½¤ð¿üíoÓC3:îõÎÚŠ¬P®l'´…¥ªb•¯m]«R’>1¥mó¶ñJªª¾cä 7¦‡­P/«B)‘çs|¿¤”xÞ”ý€©+%o¨¾.²ÄÈž–Qy)%âö?HÕ¹-À¡;—ÍO¼Uà­•§sn-uµŸ×"½•UæðJ0¶ú6ÏÈÖZÖJ *}8Xµ(U!=NçèÕZ•µî€B¡Dx:b&øµCvÿYÙRp˜&AÝ­”j­Z(¿­ÎA`b‚•`ðjiP W[ %¶}„Âe­ÂÇLV ‡øÌmu “1'« þ–~^`UuDΙXkJ%¦*@dð’s¾h8(ìÔ4•`üí«ŸaǯœØü•cÜž5+©.Àð‰ß¦â&8HͶ¦« ïÓGf[*C++&@üœ•„Ì|äm{îP*ÌÁµŽÃÊ¡B¤)éÒ¶²¢ iæ #ùLÚR4•Ûºd[cà†,C[2ÛF*…©…­{°Òw-׿·wUV̘ ã\=‹€‰mÝëxmN£z Œÿ?ÅÌñ ­pÎë>gnæi›3¥€›Ä-˜£Ül²ô0[[g‡ßZÛT©åƒÒX+)Ei[6%†¾±d<Í•¦mYÊ&l%nHJÀ‚­ýÕðj1"C&"&x³¿_çÌךI•Ù7šdHw½HúÜ|!øô5ƒñ€0 œ,ìz9p£lN]h´ð=µ²x ½ÚF²UUÔEjâå“m—¦ÊV$°¬ a<[áÒÃf‹™>’!P4AYÉm{du(e­0} L\Ö‘{jøRÊe #à:f¥<Þ6Ù;dV4ó [KUbÍg&¶®H£À`Ï¥’x­)u쀵®êÇðªPU@PŠ6CnT6>Y<àPÊ×é·ïÏkÿ[ húùª¼~‚O¯DY/üÞµF– î¶R°Kaú°T%Õ{eû>ßÎ…ÌÍ6š°•eÛ¥ ÔŠ™2`ോaˤãNj«V¬û|0f2J¶˜VêÜȯ¿þ ‘ÂÚ“N—); Óæ€3ÊÞ(”iÜ`!Ûœ~÷=#Ãäo5 YžÖ@¼U‰‰@1Ãk|Jâ1¦ŸssNÐÛ ¦B%éÎÁš …_•BŸ"#›9°F•(¤¬o$F„Uɘ3ý½%U€5¾-L,*¬{þ×ïótb”ϰ^UÁ®Ñª¼ ekaT·wF¹¡ã+ )µ°MC#…,’¦rí0yÆ“Ùz•¥’å)+ªÊж•$ÞCi›æùvlL¿ù½C6Œ5óÆH¿‘¤0 tœ9Ã^H¶²N¡µHTpÀðTî¾Ö`ÑðdøÚYE²0˜Ô7Py½à½¬4U_~Þï Úò(uTÂG;€C3d…/Ôv¢e%² 1|RZÛ²‚Ù`LnÉøÍ­’™Ä+oZ%ù4­íô@wøÞP¨ˆä@l‹ge c`ú¶۠™XJ/Û1@S½`Î {Iúê¨vÇ—Õ¢Ù¤þùD¶†_CÁGmwΧ±3ÄËöÇ-`z]Od%mém ˜>Æ*èoݹ([ï5[«{&èõÜ2±]J¹ `Á¤šx³!Õ&²…+4€°õˆ»áªa  G*¯PÊV À)%4²¥ïÚñ°Ö]q[‚[úÙÔÈàáZlaU d·•Rˆ©]×óö­uãU¢  µT5ÉÎX A†k±OJµ ™cëÝ+Å_À&u×®©`ñ•œ±ñ¢y I³,ÿªxj'\µvªlÓr“BnTË_(·nK&0d«JÓöÔܨ{n†Á¹ë™ï¬ÐíÑä‰ab+R2ðÞpX iˆ¶^0´’Ákˆ1»“Ê—=mî§•9|«Ž°/‡ýë_€,™ZÙ[q0Õ)g”*GJ)´.2OcåCÌ9lÀ©i;«È†yIøÌÛÒ ËÍêz›“IÝUº˜d¿ôçz¥Ö‘Ï”d]ì{ü¦Õ½+†ŒæßGi}REæHJ%@Ým»jÓë%S9 P*ÏT«ªmŒµ->ç_þüç?“bKäem…Q“K0¶‚ã•äÓ”V?óÜ‚K¡á —µÊæ‚·4mëR÷Ö”²"+Ì¢cW%[$–*^²ï2L%)sFÎ¥ ¨Öqô‚éÐñ‘ôVdp:…@Vo—éëe”"L\tEpWÚ‹âöl¥D…€yö[f>ѬhxYÏ…˜@Ø2ì¡Àd5LµÖ;Ý磞†ÀŸÁ4µˆ)Å­«.Å c[}·àéûÄAÖºU”€ÚRp]¶v²>{xغÚ˜«õ:"ã ´®Pk£&Pxý~S;Ý^i)ÑÚ´å×þür¶Á'¥•¦sµ¾“3!À4 @#”;ïÿüÏÿôg’¶JLIƒ¦ŽV[ú +é)¨Õ.ý³\§ó¶‰@4F0!#®¯ð¶‘J(ù¬ ˆ‘ÄUÁ”øÊÕjc¤æÌ “¿lMž¾_ 1…B«ÂÖZÀÊ‘¢.Vd¸ñඬ ÂùÀYÑhä¿`—¸îùhaK&hlû{YY|§€ñ^0@Ö“¢„R—l2

]Ô*lU•U%dR™¼2X[ªWˆ~ówå ­²uÌÖZdžé#Õv •÷Q"*9ï…¤—ÌÇLˆ J]ÉY¤˜ XU$ (9¹?ýéOGû½,y‰Ó†f]± ²4t?·|õg¥¤ªVg¾uŸZ2VLL¦ÜUvÚ •H $†F9=ICÓÏmš2¤Ç—ÂÛÖÓ´5J\w|Ñ¢F@)@‰ÖuGÚ: …¤3ùëeÍ xÙüMkηW8MU‰a]ÊZ‘VŒèGòôLUJ¶›ÏÊZU>ž }ÇiYA†§ùdˆñÖY—@v†¸c ÓÀJ¬"7?a¼éÁ¥O¦ug‰´æ$p^˜¦7MvÓÞnŸYtLì~ ß¶&émï\Rœá”AFßV Ƴ!m›¶†]—B«mn™¯o²j¥¸a¸1¹=Ï—i”#7R%¶ô†9ëE†ÕÖ«• ´’mx ”*Y)q=βZd*¯û¬´Ã¯öŽöÛ·^n×þÆ…Z­çˆÆÂôÂÓ÷³Í¶Q­³šƒÊJVN6žaC¦±-8¼`ÙLx2AÒPnrY'ía!eMT¥£–’ÞY8‰]rJUJ­5F–s Ð$¶Ù1¥jÚœ ˜4†Ádw¢™twž=¥è‘Ö¢ÙÊ´•jìCGnzSØVÖVÐø Ë~Ú|'i0ö1¯$M3XE…+÷ð'÷ýÆV«°5nÛœVí„ÂnÆjË,lNµUa´k›¡UmzÊãþýR’jlŒBë9ö}ÐyÊfˆŒ¸å“ÿ”ë"‹!«#ÒÖê®°¨–™5 ™l3XÉʪ•…eaÑðcl¥hüêï~jQ‰5©–3F !Ÿ Ã#•Ó`ÒÀZUá{¥inþÍVp€Û¶4°•ÀÖZ ãe^SæÆÐ…„½rÄiÞr©¦j0š&Ic+Ö¨¦¥ØEš rJÛw‚©¯Ò¿ÿif²¢á™Ó÷uÝãnZX-¥ XÓHëe£æLÏiņ‚fU+‰iû6ªPI>*äg¦ûµÎ§ÛP›Æq”wLÚyÊÂÍ/ ðÏ!™mŒ-1zi àÍ£…mnÞðÄÖÙÊr¶¥‰”E*ìk*çüš-E°al55@¼•2GÖ¶Ž<µhHü¹:Hd#-GZàÖNÐC¤Á'S(ˆ;3^ÔC#k[ûJ˜ ùÔÕäI#+‰Yáióý ª=|ÆúVU< ¨ÒÈ3OY©F*µñA™CÛÖÚ튇çcžœÜ¶*¡Iõ¾¦çI©HµHX-s!›ÏR˜‚À»ŒÂÆèÉæ‰1¶rÛcT’9̧aJÑçC_;å4H%p }mkÃS&®ÕVµËߊÉ-µ.×㜮¼FüEgÇÜþ¿½´¶ÍÚüïÿú¦KðÊ”óLðd°^xØÊö=>~ShÑÊÏŠGò‘ÍD¶*þ>Æ4¶¬ð§ý Û¬…Vt$17b‚ý8aB=¾^[+}1nx'ê>ûû¶ÆN“[½l) lU M‘% JG+špžm1 cèE…ÀĘb €±ÎÉ:Âeù ‘½êýw­ðM%[!A}s€if{;|–.Ć@Uô=_Œ°®„LØjÈ*J¬»™ ñýÊ…Ô”½.Þ ì‘¢ì†Év¼Âf»Ú³$Àsð;SÇ{‚úv¤HÙq:Å›"載 ˆ™èˆ0"°¾xa;†Øqg!³e´å 3ªêrzÿ›¤¬*A`Ers">“a`Y+½˜3™-½·y“çÙÁç7"­vZ»L]d+±íRΘž8L[µË@÷H Ìg†›²: 1¦Ù”S L&u‘ýªác‚TÞoóF…nµ€mÚUΊrW‰¨i'€|Ì©‹mâÏ åG‚J‰¬ß :dÖ˜,‹VÌJ TKVEZ¢¯c%d¾k0΋¦¯ª^È”¶²BÇks.¢îß>ç?‘Öñ•X™¨ê9%Дg˜X Xd’ƒ-çFŠ©OÎøRdYý7ÈÍšUó¨¢ge[Êí4çÛˆÒÀR‚¸ Ào`$OÛ¦²šó–žñ`Y÷Vi×S³U‹OÐÁj‘MüèU;]Þaò¯°10 ™ÔŽÀ¨j6`[)[ʵ iõMA +€5Êʺ,ÞÖÊ3PÖGBmå!]BÕÖˆawR£¬ª‚Éò¤ñVw¼ÚæO?B†¶"Mó$ã&0KÑÛÿ1ÑîUb}Îáj™××éÌÙ¶ŽùÊF¦çÐòƒAVIÈ ÊîÒô‚›¹¾¢•¹ `bUð9ê÷ÛF‹dVæuimK¹¦°rÛÙRŠÜø []  Dên«Pùjkmx<¼¨WMm;@\#)·å,…V[d†¶ªÚ¦ÇTB`a0¸÷Ymæx…°”ÂæÜŸdºùZLc+(Õ†êeK£o¿áÕƒ¾R˜> +¯D Ph™äœILç%àÙ1ɪýïõúýöV7§’Ê%VSõÔnX¶Ö­mu·5˜À슪e…™“Áô¶ ÓÌ™o¼ÜF^ƒÏ’Ï”¶cÖE!]ʨ¿‰€iJÁ²RΈ|Gè‡&€¤¤±žNß c• nÇlJ<àïWÙ¥éÞC'êºUªaY¶øÝ§”ðáJfò•cê¨D¡*Û"œ¿’ÆÊ*+« ËÞ>g©µ¬B«.ÕÚj¿Õ¶ˆ‘j~d}ñ€Úæä 4€un”¶ F?d4"ga sÂ=¸÷P°p󲞋.ckeÕ%ØÂzõåO›¥Âe #å, V5¼Ù&Ð:¦É‡L*,Ëžç{!xA#› ©¬ºKm[ßw$ÙJ\‘¬«ÅTÈ“–Eš‡UWšg¯MF êneËATÂ3l¥÷ÔJ#››FÊó„·}‡Q[‹Âf€«ÍÓÚlil»( Z«Ö 0eY³©ÅH!› ®…”°µÊJeÒÚVVÐ#µ¦DƒÙ’ýò—¿ü% ºÊºJ$]"kFmÉ€pÀ¢û­*ž£\UÎ@½R ÒÚo!yvB%x+%ÞŸ‘[†uéTM•3M}mipS®°­–ÅÓ[ëÎ'mnm›2Y©Æ€ñ‚ØV-FfEÜ”#•K àu&è8§Á½|LÃ×IÕ•œŸ£¶akª6’ráVYQÒÓ¼¦’ù¨/žÒV–‰HèÙURy+g¡mg¡¿÷¤³dËÙhàL6XÃdU/ž¶‚Ni¥©W‚iôÈÞÀ„åç`÷=Q‹Ï ²ÙÖ7±-P#úLš¼Ö 7$ÁRpž˜%\ë² má†!°´jz3Ÿ¯'¤_J9£ûô_àÜqªM·­E¿²˜I,ʪõ)æÆV¶ ¥:# Ò³ííÒ—Ì–³UÖg¿Óám3y{‘5$·x̵ÿ|ºiÞ<ønIGz/6[ú4ÖøÜjšmõÊ#%rpRŒ{SK â<,š­BkÇDÖ³Ú€ٛƟž#²­ ç‘45Â(OoE•þmÊ“&>L– @¿6+Ì4d4àPäIà•?J0¢±_ÜØZÛºV¶ÖÆp¦±2·J"*¿"[ñÄ‘aÛ^-Ï+s“#¹‘aðu×QJ•m AJÛx[±ÉÛ¾Ì+S• ITe‹ÔÔT>‘£õÙÜIÍ \Êa‘™dk­œ@d²5[T!ûÙŠäÀSTpîN¤Yቯño•2²*Ÿ²FêÞæ™3eÁ°ÒK™0[næä–Þ¦pÇwÕlñ9àeaú|néç‹TJ»œ3§±@ lò˜iÁöRÕt< 2: ÜÀf yõ÷«þœüF$Hð¡¾8&A…|[«¬™­Â jõÂSÚZñÈ>¶pkzšâÔß PŽ8¿zyÛV@Ô%YÃÄÐdKc£Ú6'æVBƒ'€…rk3´äÉêJþã•k‚Y?†æY_nŽfk g +I†™sd/p]ølæLê•?¦Q‘áÀ¢* Ü1)yî0Ö~®i 7Œ’&´n< [M‰ì—¿þõ¯z¹,/«­Uƒ:å… õaãšÃ6“dª”kit Û´õÝáó£)UJ˜àPí¶œ‰ñ­²;[šÖ&‘úŠøn-^G­;lckM‰!6då ³3Úâ‹‘¶™ÍÖ é9÷»¬™Ã|+$9[]Bn0¥Ô[§l†[zŽÓV¶‡Èa· #¥8«u€mÎV!Å_dˆôÔ\ZM n¶}-ÚjD °J†a’mÎõ’%#N–mJ%”°,þ­R‚ßœ¶)š3½-0†R£«:|>€u9ùÔVW¥hÎ<+Á$Cšs8ÙJòq§å÷×z2M»–Sy·ª =Sú<<2>7)<aBFJ kÛx[€²¦­x ÈÍjK ˜Š>+@w©H€Àaó¯Ä*«:Po ”3XkÀ‹.#ŨJ°HiU%…Ÿ ¼,ÌÍX•lJ[¶ ¥4:ŽßP"Vž¾#dlfbl- x[%¶•·mÍ$^Ój¥>9Ó¹h»3r†‘MY΀ñÚJ•%H,%`]Ku©ÊJP ±­ Y e{4”øLjQ¡Oˆº1µ]uÊFBVr¬ŸÏ³©\ˆY30‡i"­Ý[Ue‘ñ¥š¹Ôpz2àVE¬±U`"ém­RÂx†è™xLŽv+>šª0d=YbJ|> U5²y¬=ŽÞÃ=²®.=™àÃä5Ô ŸmJ+†Fx~µ%SÈð¶ÍIÆÊÐÚ“u.«øz|&TNCß0pí&ÎG•”©èÅÆ€W.»Q‘4µƒ™ˆ4^P:¬±ñ9 ƒ-½Ƙþ(bÛHÂêÞ2?³Þ [¥šV—& àC2½t)kåÓÃÅÓ`€ªðmQy¿t"mÉÜèi¬ñYÕ.sJÑÌVé¼ o«„I©†ÁH@¡K&«‘*)}1( TUa<ÛHX#†ã¦5•^­‘ùÔ(Ÿqx®»mg¬{sb¾~çt¢É‰ñ¶™ õYëæi¤.Dª‡e›m†01k!ekŒ K)쥢Éè3M3ø_BŒ´5!+AI V'ˆ$.l‘ `$Y7Ó¶ËÑÑ R†Oß m³ê­›UcÔ®¯ªp&°ZšÆ°ŽÓUTB)J5’F ²Á”JÙFÍ9Ðí0Ö…›Àˆa€ƒ•¬*Ÿ5‚ |ågÙldpdâu3+dWJ [9HÕnYJ|¤µZþjE¶ÖL€3Ç÷ÓšmžMG¦´]÷píhRª¢|{á× çä£õ»…c€á3ß=‘5ràª>÷ QOs7`Œ”Rp™ƒT‘2™€ñŸ&¯0r&ùÌ ²…½N9´UÞ© üs<©¬v=#<=2šš‰•L̳,¥0ya«mJ[˜§ ÓÂÚ¥õª“•U%ë½µU%Û?²#®ÖéˆÍ¼^x¸_É”ˆŽÔ½1tl¤&©é è /l9¶é‘³%†E…­µ:ÓÜ›´nŒ4ey2—uê#ýÊdñ®ŽX4‰,R¯dx2½€­Kª!oѲۦ¯Ê¹ºÞdª(‘VšEYµÌ…’Êñ¥ô²­˜w6ιRp½šyå¶œ[…^<Eéb(š-žf˜½ÀtYz²¹UÂÁg!¥•¦w¸OJžˆ³"°]YÁÙj+›ì&??•ënE:‚ï+†Î Z«j~[>RHžÖމ!H\Ó<‘5Ê<“p‡u¢ù…ÊÎÁÊo’ ]L#ÒT%+0}¬*a‹)T‰aY#a*”µEî°î#:xåZ…ÔZ¥lY]úÞÚl lakcx¶<™Àš2·¶¥‡½Q¥|1 ·w¬1RZy7*C@pJ0E²s†{ šÌmVzQêè¾@-Û¬€Ó}N°ªÄ >ÿÀ E9R·Ð¥à›µ!ºÓ|k)â]"M‡Q\™+øç?ÿ™&}YX¸M§]—¾Œˆ›ÄJlZ퉬Ä0~°ÖîýÞüçeÒOz¤îÔŸŠôuᙕ.«Ú¬ÙÔÒ ­²¢³G†„§±Â|ªvóbrHß h$Û=à]Zí¦'ƒ*s8[ÇÐ ÓÀfè @µ²Í¬ÑŽƒR¥m¶4=>)ØZßN×äîP`dµîñe΄^¬dÌ1V“3†[[&Êm€Ä3cT!é5‚ñÕv„œ]&[…ôñV[%ýù!Yk“À¢^UÙ2µÓ]i«„Æ©1zÅ[‘VUÇî±·Ò 8(q†„û¢‰±(Édã9¾F²¹µ¥ìZÞª†g›Iz†ɹßÅ—RÂPjg d’gúÆÓÝð¬ÆJé®ê¥6’Ò`ÂÁl)a Ç ·Íªm­­¶ü­:ð@ç%€YYi¬"ç^ƒÍ–•,F700OÓ 1“î$)kÛ$L_;Reéš;ÅYò9¦_²±ÕòÑW Ðl€VøLùýyÙ{˜[úã~õï]Ê¿ZÏL÷’­²j+±¶Î 0ObøLüý6¤a0óÉmžÚ&nÛÀVµ3'Àˆaµ4ZüûßÿÆw9ç n$V‹GWE‰t« 1Íc¥ñt\޳àm ­us® [ªx -ð¶øÈ¶ ¥´ö¦õÁ³^UÁ”4Â‡ŽžCcàiL¥D0))»Àçð!¶m 8ÒV”¢1OÎ01«}ƒÑ“ `¡¶”@¯(Ry¶VaË6CwëDY!Y9—¨£m-†•ïDdHU‚~%Hبøæiµ]-$s¤µ©d¶HQÓJ¦ižÙ"Hâ3Ç}жBÖ<ãm‘MX [zŒ¾>ž.„¦ïy¤ K`­œhk¶µC¬×ò,­™“¥´n`‚æð9+yq)¤l†@[² ª Ò*4º‡øŒ 7U)‡%èØIñÜ\QÓ6›vÑ ¶]o¼@•¨¼ªÖH†Úq¦¼À·âÓÅbròLF ÒšÌZyþ­Jš³!k*Yáôm¥[«”|ÅÏjÏ(yæß<ñ3q¢fî !8à{¬»ÞšJycùdeU›ÿ9,h˜ó<Ø»ÚùH…­Äªv([Mä™ÀÚ Jda²Þ1 ålcëV²Ú:žƒ=öšÒ# S/%V‚”ÒW£x_ ýVŠw:" … ³VXÇ&¬5F´’­°xcKYe­R]T½¤š³u©*Ûõ +ÇD¦•·b’I>¶BUλR ±‘Σ½wh<†B6P£J`€˜Õš–ÒQVà»äœùH%L‚7æNwX¡v•·¦Z)å"Ͳñ•èt 3èÅCœyc¯6g©lñ…@Ju¬‘•ìÌq5+…µ(K&h<â®Ý0^¹f«Q}›<1FJØêÛDɬ ­LdJl)5͹Z«hTY…¶}*'°µ¶)‘§þ2áª0 f2^J»îðT~cžR½F•¬)s¡Pj÷ ›-% ›Noír¶­„gnNÊp­eéù]”TžYꕉ€RInJ!U6Ö4”µø¦LÏÁxV½ˆ+·Ö¯ª '9Håi…µ+e+h)cdùûßÿÎ×ßÇϤÂ1d½¸æ”ùÞÄÃ4¹l3U¨ ˜’^ÊêT"Z&F@‘'%Ï 9DV"KVTnK)•2lµ@£&€}/ô/}*D’oV3Á”MÆ'ç^”þªVX#Uë@WøùšÖÚ0˜4V%U43¨<†>qݽE²UÌ‘µ®JJ”¯,’¶2´å ÚâõbÕ$æd‚F„ñýdp$¦Û¶ÍvœRnÕÖW·UÑHGSV Üp#Y…mµ0ÁÜŒ$Ûû@–aáÎe¯°ù­‹¬¬1sÀí¼ö µƒe[¥œÚê÷ åæ‘0F c%îà1¶4Ö<¥Û1jcæ€é4e9Ð88†,+)ÛºÃÞ<+IiݤB©Ê7¡l#å6AÃh$8Æð&ƒ îyq€à‰Õú`î“X +¾gt"7‰¿M>ß]É^r[]zÕɘaLgTE,ÊÚ¶Ù—í\áiUlw"£ÖŽßkÚã{ ™*‡òÁN,EÏ#C*lÝ¥š³±;‹5“¶9üò믿æ(ÊÂ*8v*¼2Aƒð—8K§Ú4 ‘dÐÁ M#” Y¢oÀ¿÷P ð®lÛÆÃRÑJ€l÷ ;š™’ {ÎMŠg†Êa'gí¼?¬TYpw¢„ØÛÈAÐËÂ0”'óÎøaCIc†3ú½åR¯~ƒCCZ•HõèñZpÛ'̪ eÓd[¡Õo€æQÒ̺`Ô:²òzÊÎÎ÷·°¶Æ#0I‘#%Ø×1ÆÓGö5Ñј ÎÜ<@)'Âh¡Äuñ„óWÒy ÒXɬùp¨œ#”ÀH&²Äi09§ùLs·Yß±J‰küÛ'çÌë‹!ÓB4ù­;ÿN°Û(ËDIãɶÄÙ:—ÀÀsð8(=Ga?üúNɳ.ôÌ1d®àü”/#e»¨„ƒ ^ÖÖ„˜øa…AªSïodç ¨bUdåDFu¤³À"sÌûNÂ<­ S4I/^U² cÅÿþ÷¿à;ÛF´5?ЄŽÀœÀV¨eÕ¹Èƶ¬*b[¶VKƜɭøüMaß0þÀF™†Þ¹jdå B]ÔR6‰•i%ê6Âøz•ð§aØ#iÜ3ÒebXÉr`÷vÁÈjó$¶%P’^ð)ã)ÃÄ‚LÇÄf£¯©cÖÂ*»i•¬Üåä4U×kà.if‚³•^»d”›r«. h %©¢m`liH‘à 1ËIô8º4˜0A¼rẠ)¥ª­&0óÛxe·Ž°’2d/Ò–ÕÜð•X›-O6%ÉÊqÌY¤,E¦)@Ê*Rò¥:8†›,F”=W&EÀdƒ5 %Oà{æàkH³©*Çgˆœù8QåË"zyv|„SKÙöšZE—ÓªJ‹x«ãÔ(Ìg `k$ *…¶Õ"Å|€RÛ„Ê•4’l©Æ6[ ¹Ñˆ<ÕÒ7††až¥&fHùζ©ÒÐgÛª—ÁÓ3òJØöad(ïh4Jš¡{–Z¯f¶Ö%óZ—Úç<É8ˆ;Âù~Æ7aUÖĦ:WóýÃ0Ÿd|¸…ù”ôx² Ó¯PªÙâÕ:~¤5@‰õ;#²‡»¦UÙÒÈöNšä”ÿíoúq_:trtNkŸÓIŒ(ÕpR bs¿¬¥6«­½ ì³á»8F 3œË¸ÃJìüfÐÂÁºÙ›ÿü„›Uwg*b$ `¶ÂÍ`ee0 s*'°:cŸy²0’Œ¹móÈæ<Ùq¼Q‰• 5¥dC"× ¨ÅàyæŸÆº^4æT‚ìAT’gc›\P ÊÄV…•tuV>ÄÊ»(@T"uŠ¿½’!ÓBUQφ—ª¶§/»#HµÅ¼µÇîk®JJÇþ±)ÌÍð™L h'å RV…HJ%­«²bd­M—€«­ ÊŸ^Ê(&Ókb%BJàéú—ÇÐÇKZDXôò+I&S¶eãó‚W+…4ž­Ž(ÛZEzÙ¶·É¹®~³QRU'MÏ“Ì*5°í\­1VænÞúÎ\GJdn&˜43,E`+%X‰ú*l zªê%ëH²R0¶4V¤•F•ÚÖ®ÂRô‰¬z }*' L0†X¡F5åSÈ"[s  7 SÄôP¤hVnë8IJÓïûçU$FHå8‘ÃªÂØödil}‘Ê" àVÿö]Dƒá(Lf .RYa:i<Û3Ö}dNa»#TKVäV9F#bÓZaÙHXÀùÆ´pFJ‰vWõyÐðNö‡¨‡~ʸL¸Fi`Ý™+箽îH†ÈRMh Ô×únGæ ׂg˜&g[¡œ igZL)GØC”¢)ËŠF40p-?O3>†sÀJl[­I€úršî Pض.1Fm#É6amit±6’TÀ„`´ó›I¤,iæÆfôDZmÉð¶bO¹Z+†‰‡Nã&'00ž@ÔÝ¡ô"[HÁ–F/‚4¥¬ÈOb[«e·Áެ°Û¦¬2>eÛ:&°"Oï{m1¯gURl‡éaäæwKe¥*7LÏý燉-…ñ s¶À¹¨c%kQ‰-¨ÊÖý>•ÊÕšÇcÈjQ¹µG)µ.BJDZˆ´ÕÈv/ ¬*Ù²Í&…QhÛüš6›òF"èÕÚg“¸»U˜£ é}FÊ10ÙÈÍ)Û;Sk+Y3̼ZÃã;Ùn€ln•w=ÿ¦æ¶ùl˜¦#! Ì „J…lsRæuoL@³ †õâãs®B-TÐËbô­5ÜÕZá{ÆXùÐÄ‚CzWŸÉñù× išœ’@ªÚ†WkB«À[é­“É*·Æ$K ãAQFÒ À+"´s¶UÑFTn6óÃ]µŽIŒ© )Œg+[Ç45’4’RX*½T¤õ¸ÜOuë”l«M K žÙ6­³Ø²µšÙx4tÏ÷…ůQ)`k‡Ò‹‰-ñ&¬P#]ˆµÊÓV¡Tï€-qA#à S/[²7îÅ~y¥—²ê¶-F­ÈÈi`€³˜ ")uÙ½JeKã!*'ÈSJ¦o¥lÝ"«Í\¶*üËZeÛZÓì®*d"ª"ø¤Õ–oå`TXÊ[ªÜï°’@ä†i8(1 7$ÆVÀRÍi‹§Ç$¨6ž¡€‰ñ …0VXIšÖds΄F(§RZý˜ äæDÆ ¨WcÛz;,=lõŒ2ïŒîA fæô¶²lãaƒõYˆa +YêeÛøÀ­9´%” Ù9÷ÖÕ_ +bẴ°ÒL0Óv«”¶3g’ìíH†Ëšº–>òM›€Ø–° J«,˜ë[ L1}€ÌröÈlÉlMέß+0Äùôr†Éøw|ÊÎ +têúªš Ÿ¡ïÀÌÍ`uLþ>­¬¤",+8÷VàYͤl+^ÀÚÁ·Û¹ŸFʪEµëûj ?ž^¡mΑ¶¬¬üªÞH‰•7á|ðÂV”cË„¦IÚâ1ͯLSÀ²p%óŒ¬pÙ†d¢¤­µm‰m…vôJ“õž[i< þ eëÕ*c%á¶Ä…-aª¤¬õ@jZ!±l3˜æÐë¤QÃWÞ—*¼•,Y…ýbÀ­X¡œ´70±B ÕpM•‘rÛîJǽ']‘‘UíÔÚþòÇ?þ‘…´á:g—nmt:ÙLaÀ–2»4V&¥â ôÞe%ÛitïR0†¶RÎ&¨; ÖnŒf¶UÕT&Ü ¬Ê$BG ±àe`%xA¬ªÚœ^y™·MÙØ0n;&M[æÂ£/àÂ5e¨V4I ¼•¬aC¶¦„sâ>EzJL¡nËS‰vÈ¢©4m°ët–ñõ"ÆÀ¯ÌVSbYi0žl…e5…ûlw´¬Îom`íT½wb+6ÃÓ‰¬Ê™ûf÷sNV¼§HÌœŒX¶’dçþ>JæJ\­#´Íð”"€­˜Úáÿ{-2¡©<Æa뙹Z 0¤ñ¶( 9[é¥èa‚@z‚4R4½`‘UÑ×Q–'’ÎAÌÊÚ^$³Âdº7€U ÿ0O§Ï©0CzâàZž›ª„TØbUÈWÌãÅôr:[b}ФòÑØMÊ’aævÛžãÇ·¥9`6|)Ûåø.A¹¬B“æ´Â^Z%4NGCgÒH°·ºrçÊ:K/KÇ!PuY£²™ß‡|>n‰ZØ[ °å[9@;z) kÄw.@¾¬cv(<¦.î I¦¶¬UÈb¬‰5d¨6ÿHk“DZŸ0çH>FÊÊ… <’L¹ÁlLžFZ5MÓ¨Ví0›0[ÿ~ÛÊ{=Ò3¡oͧ—$±ÿ:Ò,ê^—l­M®#¬Qo/OŒng@ÊÖynáûO~ü Ze• Œð½@£"7+’ÒŠdo*U>û1o÷†Lv›|ެÜVÈ ÈÄ e¥º·”MH ˆ­ôÍOVm&ÃÉ(›Ê„; M­™ge ¨ŠŒY¯²™Ãø&Lðú˜Š Ç Umç‰T"¤Dæ¬àN ·¥èó$Ð׊좜®-%~O‡À"@–­v}³Ý¶ñ~¬Ìc×ËõÕ‚ùJj”f<@¬oíà¶ +s÷[ìmoòNáP™ÌÍ·SÝe•[ñ"༲1õ…Í€´Õ%™-°µ’RÚ‘¥Ïß<ùœÿ#°rìøvõÝò:eD€©GkY3)1 ˆ‰¼ùÏ“¨c 0†Ã$ö´EöCQ­T‡OcTÀ‘øÔ¢éoïzZ) zØÆÆTHLÃS¢É_w2XtVUÖYÑ”¢ ·"Z 7[Ø*®÷ù{¸s©Ò”XÊj[±'Ò0˜lé3±&c%…? ®­7L9 ¶æ/ëžUÁJ 0@oÛšsO FVw£…À̰ßH˜à­µÓÝ‘ÝöLêk=C|?®€î]K˜€yþzhøXkí€RZ7ù±û=@À@M‘µ¦*¥o­›çU˜«Âwl2üéñýÂÀ¹00óá½N “êWÃô«¶VYb«àÉ¡#HÙÖú4{psò¤¡—â€ì~šú¿Bó;O<%†rÇÄX!’FIq†¸¡ªT}ës·U¨âÜÙyC†R$œZa†VŒ•^$SBÀ§ ‘Rð•œ[õšé# ·*ñíLàõ“}ôÌFprÞÚÌVƒ- OÖqªÅWE™>Ÿô:Š· [Óö0­«p(bžYtÒ 9h‘ (IÜ1ë¢ÖÍ€!ܺ"LU½fHYd¼*óô¤hð¶¹ÕѶ×õ\ž ´åou̘ L,(sÀŒŒJ ¼ÂNÍSÈ"Å)¸A,jdZ}mešªnzÕ/Ë@YÊL(‘a«HC[m9À)³ÝYlËZ#­ÌñÚ`$oª®ÚO+¶¢‘ªµ %Ȱªj­‚¾0A£Nc‹ì)p¬\1ÍívÎ.¤leG*ÌŒWå]b[;|…YÙÈÖbÝ'S•ržô²¹Õ7¤#´`­cÜÐlªÜ€WCÌÍ# &k¼nn;@YpÓ—LÀ d‚PÞûi»r ç¤™Išµîy™–¬#tW;—Úé›vÛÿ3•fnµf[Õæq:X–RT•/b* ǯ¾‰­i’É&nþ4H-Ⱦ/˜ÒÊ6±52+8s ‘€üÖ dhÕÑC¯Dk†Üd/OÁØxÙßlxØ32^@'ŠQkn6…¶|úøËf¥üß<²xzÛjd+ª`„Td½bàñçÿŒå `8ëëð¹zwé+nÖdLÆsPÒÝ5ÓÎCÓ(çlmP4ƒ­‘šuÊjaVþ&ßH…¶xÎ0‰ã;×ç_)Afõ«@Y2-:)+zÑx€y:Ž„B©ĶãÃÖbbÛÜ0VRS&;2>sì\wsvÀ¬¤0"1À¶St´RV·DS;k&;o)žRYm<µH)LUæL`Í Êe­akåHM…r>YU;PâÁu´6gÜDc»·Jðž/Ríµ¶Ê®<7+!Å­ ±ºOkÎ4Yð¶Æ`¨í p‘[M3ÁóDz­J„©¤¼þ3zKÙ*ñøè;©•¾ç[¡[êÕ0­˜lŒhHkÇçIÐoÆŒ0”PZeuÁÃ1¶1²€ò¦¦ÊùpènU§øûKÏdµSkëŒA•;aÒ©¥4ZÆÐxúôç%ûþ¢£)ç<• ë÷-L¯ŠÂ²Mskx…a ¬œ^KÃÜ›¡7 œ2ñM~~' xCÊœLðLà `ŸùîwÙXIã]×iùýΩ‹Ù€jÉLƒ f˜¾çµˆd(v ôpß“•°Mp…Ÿ·"f”˜Öu/ÛœRN!Åm<Œ$ˆñNزòvÁ]¸Qế`¸ÖZ`ÚvŠ.¤ÛëÒà&q±ëÛÖ®}SQŒ,g@h!0oÓæ”•¢D Ø…ï`ÆP6€cfnà&'PÛ¶”íëÌP $@,•§±ñlùô¯íȲÊ'gëZK5-Ðg0çJrà†l€|lcl e⦒m$)ØH|Š¿d|”-uL¿ŸV¶ÍÜãKf­lCß÷£$K™¡µÍ$sÖµíDdyZ¿6ç?3ck*a$&Àz…3Ù+mæ ÐhWpjÎJ Y©lñ€vRÓ``…Öƒ%Ã3I¯Òùô*Ú"Õ"ó¡H¡DxUòÁÔ%úC™ln}®3¯œ9% P X¡H€iKi…×”m%)mk4O†H—‰)eËä“òß0;éÖn™"/Íö$àšõ³±Æ0Ùdb)¶S¯²Wu «Õ·Öúb²¥Â]š=6ΆÇ󧯑•lÊbzZÁ¾2”Û†I¯–ÆÃb¼ªU€¾Vø=cL2«’ÓãûÊæÐºtÒÎN`¥QÕ`Ó—Í™¸ѯJªX @Öo]YÁôʯiO_6[6CÊ ­ÈxÎá}¿kGÀS(߇ S—lcÂÖl‡†­­¸6Ÿ==ÆaÝ¿O¦ßçš6Í”«rŠcñýúଋ<ÿÎX•m×Î"åRfóp Sþ¸Ø¬ª¥É ­¹)!耽E iœeM+¤p÷ÓIÏaîkÙVV-Y†V&¯F Ã!ž˜i«¤èeñ„s¨67……B˜XêKŸÿ´=缂~ã÷«€Çäy™“ód=@ Iì)Kogk?Ü1Û†³……„’Æ®ß v¨1ÂÖ4€'èད)è¨ÖÚ„•ll<¦×îZOúE$ÀVH­)±”ɭȶz!<\•Ï[O¶ÁʼÑY04˜p(|ÑxÌ›Ê*̘­[ „¤©7¤T§@^ãÿúØd˜Ië1½¶|„ò40¾ô糊©µKÐ]S-êXÓU%³v´&¬2ÏÌŠ)ïž“|t䀷mm%9àÕ"¦mÔ«,ž³ «K†² ̵9>HتđÛzQ½ “5O[[g[+lBc¨å$ÃgK±ø€óºg[Y¡{µ¯Sç2^&V‚ ‰mÉ0”¶Z[eñeÓWŽ™OVdç¥ 5mkµí³z[2UÎK ~‚&ìP fª( zpMm+¬µk±UŨ–Æ6Ï~Uμi¤vý&¢Tk*n¾ÃYÁ½lËÒd^—ab¸•†§ŽÊÃ97g+±.xþ‚X(@æ²¢á €”T\ùç%‘ÍŠ-¾¿®†E…•ØÊÂJÝÎçiÎþ 2ÙV]QL3x½=))…øšr¶­;R`¬ÕþtII 7¤*4Øäz9,@à)GèoÂúÒh Ëvp¶¶ ãáŸx˜†gÏ¢©:Zo‘•ƒ‘4õ¯ ®|×›¾Èl¥l‰3„ù#c½xZ¥tWU#[%ES í™äVSšxk8ñ-úV«µvmµVKʶ* sUhµ¥ç?[/ÔZ ‘È_ oë§ìù4­ y,n §4R¦{Ø0YuëÒ¶ƒ¼2Û®®/møGÀM¸«dL´Û#…XÊÃÂsóàl³%Û19à ›9òü×±5Ðüª¼$>ÕJÑ‹ÌSª"«.j4% +ô% /e˼WQI˜¬·ãHƒ¡@¯Yx>mÍ&« o%f®\Óf“M `2ïJõÜJU{þg@³¨LA5óíRôV —Evï–/™áRÖÆ·ÁVJ9¸UʳO)E lEJk‡±eèWòùob´–Jcebë‘Ãu϶Q¥T²Q‘â½8µæLßA†ëeë„ÂR€T‘3f3Ähá]¡i»B½XáPJ¡U`hDÀ)üÍ¥Ïg¼Â¾1óDMBæåÃð‰il‘Reë"%0l›¿1h+[»•„ åÝmY|a›í)»Ó’MY-e³¹Š4àcqÿcJ‡ô›v%„dÖu¤4Xâ9¼¶uÉP÷4Æ›&†àãA+ɳ÷6±Ú•ÔPå½I©™X•`˜?,qÙ CFSJ¹íîO)•@Ö¶Èït?=Œ”RÆ8r}Ùi´ãÏÁ*¤lë½êíåã¼}üB–­C1gÒ ¨j‹WEÓél ½l¥Dn%Ö‚Ÿ‘F2ƒH¯Ü„W¯øN$…•KÁ#0™7*½aªÂ r°æ eø¬¸¥ä†»4µÍ ¼:õåÎÍ3j1@W‘Ø!Ï”÷ FjÑÓéé ºó £5ÒíY™$Vh«‹,=C¼y¦i*-ÜÀm­mul’¦U¾-7²VþÀ iòL cnVÊdp7–†³^L:Ž*X áVb‘CkÍÐmilã‘·èT) ç¦i|)|g”‚¥„I¬`¼à¬ÑNVV WB)VÎxæ a8}‰ì‰ã“Íp-$ÏV³h›CØ:ŸÞ®Æk&FÂû˜›¡ÿ&’§@c•eE)òéBò‘Õ·.˜u©Jy…RdÈ”•ØzÜlj-Ûñ1Jl‘d‘‰{g¤YÑH;²Ô‹†¿”ô•U¶vUå9 Ûˆ±6sVRôݧÔúfk[*±me]2ÞV¨íêÚv‡È³â‘c*·Vè8á4Äd:š¦ïÂe‘s”+4pGæ\jÃÛ¦±*©]z3t- ɼvñž¬ð fõL3ä 0lé­ï1kÔT9§OÙ`Ö@óø[Y]ºsV3ÁÃZÃR§ì¶³Ja˜[».n9Ó`¬¾ü¼PŽäSyb[@4üIýóŸÿ´iûì =4Yh€¬øš|Zâ³ ÐpSkËM-1Ò¶˜8Ò*([euôë)@“§)ѱ‘²¶Öõ{™Ý…”hÎøºÓ Mâ1Ù®*þÚ|¾> )ðµ~S1™ð^3CÓ`åÕô%Èç­ÅcØjæé×麼mfsl9äsç=ߤ¾¿`%Mo`úx«Âl[u¤/bèñ¶ª-×4²’Ú׳r×ÎX|í?²×°.ÖæDΜð‚ƒ›1[) BÛ·ðLsO„çOS$¬ª±s˜-1ÜVªKvöj•¸|ó䃧Óý…ƒ@­ªFâP`ÈêK©<œÌ*«3½•æ q?9T^ SV¡`^2¦ídøaÛ>_^3át¥£áÉ„.daël2áKPIb‘¦SXE—€ç¿ÇÄ[UIi è À«…â›Á*eíö @Sªç¹5˜¾²}eJ¸5¿UU2dÃs“EbŒAvs¿ýŒŠ _îÌY¡µ“æÖMÎàÓéê®EY hË [@ÈÖK¹kO;l…ÍY_&%²Ä&¶×ìch<È£ïD”ª¬7I¬&”Z€lq¼¾¡l äÙ“âf›ƒ,[$¦™5°,† QVÉ0=»lEciju±òu‘¥m­™ÇX ~%0>·°­¾ ¬ôý R9%OcÓ¤· ʦ½Î=ÔH•ld¸íÒqèÅ”üãjg€ÝO«gJÓ$»ÙJ#j=`K dJ­Ûâ ÃYjÏÈûc+ªò%ãhþÿûßUõµÓCaHß³3a]”ïŒ5êàV¡jcTnÛËÜÙ™ÌVyzš¦rùyjJF̳¾M^ɪ²²6^Ð…: Œlá¶Ì RZg’϶4aS¢BÎ¥ÚÂÌÀ¦-bøÛV®vÙ|ÑHø°òÙj$Ñu7I3¤L†„meØ ôÖ9ˆB«× Bž@AÖä€Èßv¥ ‘@U°µzÕ)µóèÚÒhĹB©Bë kªŸB¯‘µ€îÇxª’¢ß`©X£4‰ñ½–µ ì8L"1¹i­Vߘ¥´ O|'²R»ºZð™‰*˜’›P÷ah ¸s©z‡‘Å×Î*l94Fâ‘¶‰Uy|˜÷beë•Þ<>”†‘ZH)´b§ÄDZñ²ñÊshòJ83‰^ªª&W‹‡ª¬Ü2D® ð‘<—­P;‚ºÀHÑ!…+ò:+› dØq01 ª'xåG6€Lð”Ý@†ÄÎ_ñfS¶ê çYíip#ˆ¡¤i¼æ/˹hKOIà %‰¯k!è€ aäºcøøB¤÷~â™T‹¯Ðâa@;¸ÀLóàs‹´í,Ö -üLÌÀ„&s@8ìµ<ž¶V3Äâ(.Y÷NÔJ¹Iʲ5 \JVk$àÛ‰ ’‘u´â­¢ÖÍÉ“¬…¥nlV5%‘V‚Ln·Ï•«µ&°ö<2­1@Crc ¼£œ ”UØÊ.0p+@¯PÇšÆg¥ÿÖ|¶ÒÀbsã#¥°wµò;5h0©š6F¤µÂmÕÖQaÎRÀOVwºsvY¶dBÊOX÷‰'dÓgE3€ïqÇTb-®ß§5+dõØZ]ÐçÈüPãáÚêb«Q§³EV¸@“KÕbkM­{My6¡*XÅØên£Ü§ÀU@_[”%¶‘b¥ #EC à…v| š*LTÑ(¤©]/yÓ6R µyæ–²-“¶€*åÆÃèe­ <>™ÛÈÓÚx™¼U˜&Œl0Ø´x]z7*ÄY2c»ó–µv¢®ôË# ‡ÂöZžg¡Ê*˜ËVcªj’+9ǵ(‹ì•ãf<—0 >™Uªl½¬”ÜLc1Ï“ %¦¿âñn`+dUm37C—¦<k) FxzCæ k [ûcÆüiØâÕnTJ±ª0Ï£Fn02µ"ÞŠaë&«MP‹˜0>“j‘âüÏ€Ú{“lŽë}S{שMŒ7à¦0\˜¦„Ç ~—ÎqÚªˆÓ7œ ™ª›ÊëÒ·îóÅW“ØÚvn lƒ M8ÞV¡U$À»aÛ¨—­UP¶ºþ°Êñ¶Â{"_)dRéÛÖ/F²&«±B‚°UªòVU#›˜ƒÃ[»Êd9˜„›±åFcÏJ£ŠC² SëhÊøº+IÏÃd”i´ À) ÀB*€Ù´ñÖ§q"7Э¢”,l0YÑÁó©;@cu̺#‹côýNÊvÉÝañ •óŸ§rb+™î›³^bl_V%¼ô†a®œR %W{>á͆OÜé& “š¶Ö|bT U¶ ‰›Y_M…¸GI—Íjž•—eKãÜä‰aà5lk%.«vÀ0R¶²x…ü‘¢RÀox“ XíRÈR”l{îŽ ²¶ôÀÊ¥æ¦)ŸnÆÃ"3¥¦V²”Jl?¦&wÆÏoºÐÏožþïdÍÖ¹1‘……ÄÚ#Ã#­Í<@°l“S¬¦ÖîªB†Rk-E ¯HÑ$`[Ê%ÀyZ‘™#ÑR¢£é9g.›˜&ÆÖ ”YÀÛîCi5R¼”@Z•[õ²*LfÈ—$ ä©„­gÁ§rc%ëiбVX_«@æi=-op+Öñ›ù|ꢜ@¬ È À'ÐižH8Þ #«Š,‹fbë>w4`>da⬜d‘iò¯—•ÌZ­5q—Ö`²„­Me¥×à³y”ÓtÕ5•å† …Bë‚Ǭ#^`ê½K™ßn‘˜úú¹·7CU>†”4]{>­Éà› ô¢1² –e C«r!e+dëNKÑ”Š¡lþZ;&;´Í ©< à¤>zœÇ¤áÈꦩv4²gÐÝFMdUYÆJŸÏNÚ¹[ñî\Ð÷5¢ ¬Ê0@gá“Ûœ¥(90,E“¬³à»bš¿ÖJ´ i0då¶ÄÍÄ)†émé[1b%@C:JÕ•LL™Ø*ÛË©é{(˜ƒÖ: )­ _S&4ÊÝ$†Æ–¸)+rM+¤é¤¶ ä[‹WžÃ¬€4²p­§1¶‘üöO[Äh«ÄjËPÛÓ °? î-­£µ.îÅsÈ­y*yõøF®ïŸþö·¿‘Ê©×Ïè¶²/)dF[ÕÃ)ë䨙æ6AÇ«0e© ò©¶KÁ” MÎÁv?½-}wACŸ³…‘4ÂõY3ïU³%#@ºwäÑ}Cy7ΰ1Þ¦TªD "Û”máÌ®62L&f7ü¥ÿxâWþ¶€ñb&˜yö¥:yœ”’ Ǭ¶gª ïeënÅ‹õª ÷þt¥;x…²°Ö¥­ò&‡ßÈ![Z`XYeÇÉœÒ*”ž4­@%ù/…ÜlÊùø8¸¢LȶVX0fh°Ûùü7³%­déSZ›RÈP»¶¬ê{ÜïËi€!™Ø#ôƒ­iés ÛÑêKà50äþÒ/XI±²ª­þô»£*¡áôÂßdhJ`%”øv£Ĭ0²4Â`µFnZ|%Wr†©Ü6±-2ýËTØx²@%4€¦=šÜ*_S +U”Æv¼3:,¥lZm{C²’߿;—-åRH“s$Y]¬dá•(±6•³ÀEãÀ«Ý#àÙ´ÖºTHI§Ì¹ÙÂÄ&h°zÅïìiÈ:QÛ4aUewÒi¤t”&±ÒpXçSö•I%æàh͓޴”båq€*`ådÈ%OL“Lézs|†¹½æ¦‹ì¶w¶ÕZ»ÛœÉ„ŽsޱbDÛa]¦çÐØV¼­ó4¶Umx]ú·#0.¤†²mg·Ȳ‚‹x/ê¶ên•Ým§Ä+´HÓlÔWÖ‰(•øØ’Á&!nžªÂõ¢É?`Å“ùºëNl½ÒÍVë²?Õ”LtQ R;cä ` z3iÚdV>ô²3„iâ×"Mç’ªH9@æ,eá)ùÀ¦j ‚‚¦hK$n$Ù˜n¸Ü篻(¥0s[¶b$ƹI‘ÕÖŸÈÍ Sjd†ÝpØà¯¶ Uµæ,ðšøJ`ñêa©Z[ðÉÜ °0 \¶÷*ç lù0¡¯ ÆÔ% † ÓŸŽTõEÝV©Lja›ÉVŒT|-JÁÂH>æa÷&u~ÄžsßëX±#ù€Q‹Ô¦=¬¬’ø:)ç%lwMÈ”K½2©NBŸsVý"B)~VÛ­4€Éi€VUî¼Fëþ‚Í€U1áÐ+n~$ÐýÀ›*`m†ñ¶áWÌßYeëÅ™, Fô†`\…”#Þ´žµB³á)«­‹µ®Çù''5Ê„qóNAϧ£)Y­ì÷ø~€‘ñ±rØ5rP‚!îc°ê·ÿ®CÐTR@k½ØÒãéSÂ)åËRÇÜà†·íï %ô¦%¦iH†¯g‡Êp'U¨œL‰”m+@S‹ »FUíã;òçÆJÌV0éþÿ¡Òîÿ–Gò¤ôkí°4îœÆj»Sl`àíkKLYwÓ6OcKi]m†Í™XÖ+¤q<,%l…FÊ?Ïž…U*gYÀ¶*ú&Ab`1Ÿðåδx˜²ÛHŸøMåi%Ð.ðú¯Å<׈ž91ÆÝ- &+|dÅZGέr$f8M$^ÀœáÖ²mÓ ˜¶d^ʳšÛ¨ éBTÓgÒ½åöbLÊõu!=Y À ˆì1ÿú׿ú3@UÖ‚ /ÐÅÖ&v1 ~oµQg d¦÷Ó£Lfë΄¹7Ù¶í~øt3I‰ ´µzÕïIµJö¶7$1’ƒ¾0=O@U]Èla”é+±¦©粬ð²‚s+CV¶€ ¶íÁ4LbÙSù?ר ÑÂ?á!á i¡|[ʶŽ9Á9BV`Ðé(¥ªE&Ò(kŽWnp Æë¤­”ôuL@Œ´"­'+ ¦*¤aœCC¶Á‘L¬ôV)åuÌÖZäo4‘zõ>4 r¾EgàÈ4za?«j­óˆU‘áûS^‰ÂN”yåµHÿãœÌºyvj׎o$7y~00PÞuÛ:éç+Õ;”™¨@Öp²ùb€Ød•¼«ì[R/Œ'ºßKÌc“dEÓ•ÇýûBÖS‹›ü|Àd9àû•%L€gŽ_U˜ Kȳ^ÖÎe$²L¢ò™l)J‘¦1:+ ¤à<ÓŸ²ïóÓ‚RÈZ=VÊEž€T«,O÷Èø,0În{ÚÜF˪¤rþÙ’á­ZœÞwTåɲÖ}až^§ôVáÔÈNݧñ÷<ÛZ»ŠLJ©ªcåVUÓ˜Ž‘ª©-`Ýül ÖîAþd)[ù¤¨c׈4¶B3haõ²5F—# H%uíÏ©ÃVa›†¡£a¥D.y2Ù>³YñeÊ1 Øö¼˜+gŽ7a¤_…aŒ¬êÒ$mùôï i˜à;²ŽH¡JJt!¾4ê•L/k¶°*ÇÑÚ¶š$+«¦‚µ|”Ø @*~ÛÎÕVyŒ'VÕÖÍtH¡„9Ò ¨2žcmHg ”¢wÆ UaÌCƒ¬e[&Êmc´rV©*O%MÈóþþ›£CÖnú˜Ä›Í–3 qzþ;°¾Rü13áàBnÑQÆ7ç ‘ñÉàzY2=ð2È”øS©#gñò’YeB67ü²ùǸŸª¸Ñô8à 2±.r°ty!™”D>•X¥˜÷¼Â•$NŸ,fVÉüeXéÎ-²BLí¦L†Ìó'û’°GIàÑ{K½{@ì#æ³L–§^{úõUÕ7½BJàmQwëÆ“m‹Y$ÛYlsë¬yÒÏ|+i¢‡ªø¶ýÖ« æmm3´òÜ€qÛ 'Óô¸ÁÌ€T`꫊DŽ#á4ÄÑàk”>Ûµ¶ÅŒÌT@& ™?Ûº“å0¾Âq>]‹­Pµõ‡!nÅð«Ìßµ¦sÂLP­I“mâüM²#ÃÞ1¯¢!;;†¸réÕíDx¡ÖZGMme›Öu5ÆM_æ7¤ÉÁ¨ä§9q++³Á+áƒ4 Òq’Qî,iªJL >gU7M)…Ž XTN(GŠ €o˜ ÆGJ YµôRÀŸþþ÷¿K¼-§¸9Jaê¤X 1…-±àÅ1ÓÄdHXÔR P\§3zU&e‚IJ|¤RÖ.qWã‘ÆhË•B0Á;c²îBªG"K£\À14H‚ÏÐßÇÀ@RVAP¿[Híˆñ÷ÂÎ ´9Úê.Æ“iQëœaYQ»ZÐp6sǧٔȎCc«H e0k†e•cxšÄ@‰T]jáJòé~ˆ!+¤f{ó¤h ÓÿØsY†x«.¢*©NižR;Z@ hæÊ[ïŸ9i"3„é­âkpÉlkÔv“«Åàý‚…!¶uúZUarë°H‡­£§P²¾Ädm“ø"«]Ùm™çoÕº×`30RJZ7?F/ÎuÄĬøeë˜@à&6&²ózÊÆÎf½”pŽAÚÒøKG«B¼à3@p?Ÿk%ïUÈ âw0²*¥„(ª¥ÙÆ7?HX4­Õ«Ž×Â…÷ÚÓ0iæK@ÓëѶ— ~õ9œQ¾Á§yá2ðÿÆ4RFm›~ΚI õŒ·žCÞZ˜ÓÑT’É„!²s­¶{@b½•$Oš˜+<‹l­a»’ÄHÀªµT¯ºZd«ÞV¼å²½Æ&Ç×nš®ÚLhÄu:“7›ÔÊaY« ôVn¢Z©–²¦r[qm>‹!›³òXbžœ‰›ÊÚ¶‘l¥Þñò9î_Þ¹‡O›ûÝ’ç™øþX¤ÄÍ`µM¦E†Ä±Â7  o+U Œ7XÎdød½m†Umøú6Fí1’LµoSw«jøkp¤*‰É'l­•Òëm­£µã«•…k¡8ÿG`u²Ç*öÒ—æ"”Ñ,Ö P(ÙG‰-° Ì­p†p[J@V_¢ÃÇguµgÛÚÅŒ—R%øXñu©3ÁýÁ_k¥ú9š R#“äÃA¨ám¯ñ‰¬ª"“iÊpw%‹œÿ…‡Eš|(ùlÅçlÔÓ«%+:Bú¾ïºçôHVM¶{ |Äl‘>–¦î²Ä²n®]&ÓH…)i€é»UÖ¶Ó!•;Tßæé€LÀM[‰-²“Y×—æý¾uø½$9¼k%õÂf6R¿*eÛÀÖHg¹'ûü¼Y9A‡âSI[&˜'%º^d-z”]s…øRù+ñ묵­Iê’Æj;O&5UW¨*sÊÞ J)ʺO % V‹JµªbØ“M“Oµ½<”H«­Ö ËÆ«j¶ ‘·ç#Ê.`¬R‘›ÃÓê®Õß— Ù} æà>ßKKFyŽq‡·"ù·èo†ÝLžÉ*I©„¾.›3A…°u]¸Õe£¶Õ”• ¤ß›@Öÿ"¥JªH/› í7y.?ÆjTå"Æ6«£¸¡ )츅­J¬²·É/Œmd‚ôH‡âЖ “®E ÿ 1MÕ«{oåóô™x²+!cXp¨°-YCj‡o‹­µm<¼ûïËÓ¯=}(2·v–Ó(cêÈg™m;]çbI æŸFv3gku–^aÃôB¹ƒÛ/[•µÛ8 FÝY;¦9¢ìqý~c Õ–›5üfͱŸ,™FÚ…Èž¹˜sÙ=Ëø}«ÚZSªâ! ,´hTâ:Ênþð°…·5[JkåZtõŽVkÙ0¡µÚ¹)‘m[Ê0È&{;Ò5•êB¿_ˆº#Y¤©rU0R»:¡“æ&?oê§ëý²ND@Ÿ[Ø–ÄJc€Žœ¡3š²§ë÷/B:¥±+Ï­Úl‰ÉðÊ+Ä ‘¿íÀpíll3±Tž§mQ/«ûÑT–°u‡ÊÖV¶Ášã80Ò*[G¼ò˜|ð¢¯! ¥ÂȬ¬5ÍD*†¬Áò±Õ n[?D;Qž~EÆžd‘sÆÀRøe›\ C<Àœlg§gë_úô›7M±;±…i’)ó×¥±¹ ©ÄxqµgaÒ¨L4‚}­!iT9]a€¶VšÄ6l…Ö4“ÝžŸ;‘j€À4¶ÂV6le5±Id f.뇱éÑH7)ë15¿ô$ÆÓ梲m­di§ª©0°*wޝœ¦îUqÃk§/ÀXE‡ŠÌ–2c[y¹Á…B¤˜ °UÞTñWrUõ +O@{Q]\VU‚æT[ŠFÊ%Ç#Åþ,Û0pe %Rá-úüŠiæî–LÊ*[‰­,¬#,¤0L„‘’É&ˆA.b2¤‰ÖÂCaØq'³Úê2+Ýa|—éhLFHÑÛ®EÓb:‚mþMþVû:ÔWÉÌÌc¤vo9Þ6 PÕÃmŒž™oE¼mΔ€•Lª-«æ¤7|‰¬³ï¼@&ô ÖÕFÒpözvUH@IDAT= ¸í¬¼{ÙêKy¬jUÑô Âs.˜÷ÔhZeñ•Øê%ÅDV„ñ°*!•É|¼Ô:²­ `q >Þ–ÆåœŸúùÚ×R}ÞV©%GYúìZ§±&KŒ·Æ«re/OF€!h*¾}¸•˜Œ¾’Z·n’s˜+^}˜j¶­ÜD3dïv]ÔÒXÍ#hr£¯Ö}â¨j[J<&€¼óžÛ^/P¯]Î[)“剷ÍAU)­Éné×#X»J¤T Ó û–„1b>ÜÈðE˜ áiÂZ4Y]h0ù„«"P•›, \ªÏƒÒ– ^&‰[× #¦Qå¼Öe‰«µ’µC)âi–襄‘HóˆRze»ŽK,kU›Œ>å˜îæ•nÒM¡©$· a‘- J0ÙpÛMH–s3t]Þ+%¨Kn çÍÁʹ'’¡-=·æ Çwp¤ H©‹ïSÔ®”ª¶€ÃÊVëì@ߘ•T• -s`kG`Hã€mU±µ"ÿóŸÿDZºÚîÇV­ –Ü¥íÚé%…‰¬õ|Y‘UÛ²|ˆE¶Êݧ¾ZLv%¨»-Y<ÙmþùêekÍÙ®õÚ)OÙ•Âouåܲr£,liØæ–`š¶RyZa¤ Ó+̧™¥D)¶@ÙaYL­¶ €ä0P¡5îY³µkjŒúbðÝÒ•|µ?SIÌG;[šfPÞûœ§»Ý€é׈’¾Iòd‹¤iŒŸ³ÐdÛ<õ ×ÅZ «¥áxdùx¼{p%¹mDæÍZ§W$°î\‰Oñ-×"l¥±vä²ÝÞEu°pWùÃôu»:[ÈÞd€Fðdh[—ª`´ oŒw¼µŽ¹%ˆ”­/P‹ö•ÄÈ*éà=MŸYL|Ýu©]%jÓ“uÆuqÆaâ Ól1OÙ¶@$@)Jé K%€Ç kóöõtzU2·Úz@³ZÓz.0«‚)ÄHíJa ßÌnƒ9†z¬¶5BbˆgÕéò„µ€ ¡·b¬#&"«°©¦¯C½r³’í,¶²ª`‚¶0çZÃ(kMp>í9vNpïèÔø,ðp0oì„‘õ£ð‚Aï` £›xÎjy %²’n0O2å9-±­òfHl‹”uØL¬ YJ²è²"“Ť±íqʺÀ!Í`õ!Ô¢ßr0=?@­î~ÇÐ(϶Â÷ªá.AJ bÐ7P`ª5‰#mÍ)*¡‘…E3¶•TÞÚÀ²ºXÓSÆóWâ8RlÅwœ3ž,= ¨K²|¬HVd@Ø6ÐIµjA/˜d.µ©j]Gšôù4X…x‘,ÜZ6%Æ–asælY‰,ÐZ¹©„¦ãž›Ÿ œÏĶ=Jzš•Kå`…}3Z&ÈÍ:V‹ïwk7#/UU¤lUK/+l•ˆ¥h¬øR° 1€æ‘Å·ö°˜ôhh®÷ù:†É¦ñ_§–Å0ÌÙ*N¿ï·e[ëC2.³×O!%l;ˆ aŒòî À¨µ… êp›CƒQÖ4ÏcýD#=Ä9,‡¿¦ü£Þ©Ï/è€,F € à-€1š*¬6ÐØ²ôžš.Z&V¸áMe«–Õ¾|:lÓR …²ƒØ [Ê´RU!YšWõYî8Ÿ ¦ÊémÍ H›³•SÓ4¶Jð‰ÉÖÓ*ò´ ‚¢­•ÌÚ¡Ú*©6«úªÂ랎W‚­”ÁЬ„¾¬­°-K ¼I„ uì%äO†W‚Ä‘©Èp2V¦Of-N¿;^˜¡&šÀ; ÏTI FZu±J5Rç ³zŽÞ XVÐ×Ó0ü«ÂÈÚRƼӎT"ˆµ®$`ÔÌ­ÄR™Ûv JSe•3A¶”.!’gÿ”r÷I?[ñ1lµ^_)˜O-Δ?ñžQŠL(É܃ài²zÉjd%®¶Ó­y,n;«r!KÆV`ëh¶1+±U’³vøp_JVXk[dúÀø&<3Ý©^75-eÝV9L@ï-ŠGÚêXûA¸"'j%‚™é['¢'++…)E© Æ–^À<Éð½°,\J–ŒÕFl¹•Ú$øRÊ‹ü­Óøb´~åŸßÇϪ!¥˜U`šdHVñª2olÙý½ØùÚr6ê¤tŒ:3l [ÁÈö'JµJå³ÕF6Ù+ã¯W¶œ)»kØ 4™ø˜g+ýje=r ˜^ ™XUuËÈj‘”õ…»ÕVHí«M9¦Ö@G#àÆDŒÔZVÊ0éyÖ4ØÃþ·qÈVósè~‚OVÌf€;cŒ4 o>0[Ù&l“27|ÿ„tMñH+“·¯BÎUYa%^eïtb|íˆëˆ4õm¤p)8ÐÌlºöʹ5m‡êºè7Ic3™lXaÎ3i YŒ5šÙâa­{™«ª°U! J–Òv“Ã.Dª·ÑVœâ £@hd€@Ìô¶0A…0F¡£»òd)“¥ô‡O…†žÌTï?_ß½BdÄ9À aÀ:`k€˜ÖÆ&®)7n>@zÀ”r]”¶Ú^ ŸÍVygÔŽÒòr+L` ÐÜ(Ùl¯ÁYú\˺%Yâªtøâµ… Ý·Râ­¶ >ÅßÏB‚ί¼°Fá.@xG"Ai[Ó­kت£’Í–¹#°j[Ê<^ënL;ÁÇåH…é™|µ¬0yÞ¢S%&ƒvºS|‰<—~?VŒïFõ¥çƒœ‰mþš¾ß¶I¬âô¸¯„¦D†É°Ž«¨°i‘ÕcÄ|ÊúÖNࢼóbÎß7ÓoœÎ耘Ý3 z¤ÂÙÖtY/zAßûƒïÆ2Ä VøúZß+mNbåVV²ê¥®°ŽÖkùyÛ7*P‹üÕða"29 DäÜŠÉ$ÐÁ͆ìµl6«”îî*Ãx[XªZx†z•eÎS-}Ú®u†Öfs?ÜŠ”Ýsné» %|È 21ܺ|#¥0¼òSöߟ)2½ܵÀ ­ {z1*Ç[ xµ#áWSGLóÈ*D‹¶xMǧT[9>ežÍ3±Âôf”$Æ0xŸÇqêa²íYÈSn XÌPS·Të”ï½ü•4['³*ñ­Ø1yÚZñæv;Ÿ R” MK&dm#3ì,1Ö‚¬rÀŠ©{[Œ[ÓGÂLY™$¥ ¥zzgÎa¤%LF- P@–¢¬¾i T•'«lWÕïFéa3ç¡îÀzåœL­S(gØ'°Ún$%¶&ðlF Y¬Šg¶xú”YaȦ”m›³ÀÖ¯M7ž¾°R˜~QS’‰¬h°ôxg¤ïѸ4·•ʪ°KhH+½¤Œ·ðÂV„Þš…¬ÚÒT`¼Iuo-e”¦-›‰vHŒ¬”µl‡’u ZÓÐM’Þ*¤Ê¶r 7¤¤š$9çºï2SNÜ–`eØåChí3èDôаM)Uw@ þ<#mYÙn¼R‘Ê [nÓÔKÓÆÀ …" Õ `Â~Þ`X)MÜ–sð fU‰µÎd¯‰FJhþ­bè6dµh¥Av30qµ)cº¸ `KPw+^aÛx+Y£ï{ÏôšºmUd­HâoŸóŸ™Ç„ ^’ª"_=¦l‚×-¾gmµ•í ƒÉ->ܘd¥´¥œÎ×¥ÃJQ6ÉëY•,}ÌLletK”B‰ên x…l‰½]›„²¤hl ªU%µ-C#† Ê_97]¤0°r87J˜ M“m)L…ÚNz;Ÿ –jª™”j€º”b%UÔHùüWžÌ:ÀDUó€Rtü4¶¬ê…± çß#>5O0¤$À±ê V‹©c[k@ ¥”*_ æÙÓ$è\Ú5Lb|ðíNÖk| HV>>s«¼µ£ôd‰Û^Ï…TÈPjI$v|†9c2wFÀ{…hrÈ­Z‚™,‹ÙYpæ±å¹©è™ €çLñÃ4›d0†ƒ­’àÎH ©²Vˆ¶AÛÖ¶VÄùXÉð4Ib¤ÐÝʳyfÎÖƒËæL€ÊoMéaÈ&6*Ò–†UJ ƒc6*`k$»‚Îy§>?ÑçLßA8¬ ‘uôe‚†9ðF†yRnfb[+A]¬ÙZ‹ø^‹µRÈ[a“`jÍ|&˜f¶Ò ©d máÖ”]‚^H†™Ã5LµÜ¤šxæ"òb<ß)ýrO,[G©.!ž¦saTašZ[µÈ\ßÚ1‰Œ·-jãÎá}CdSabJëŽ9CÊLR¶ãaów“0Jã5!ÃÄÖøZ·mÅ,êRyVœ ÿ£'¨ß]ùAµ»LAŸyx'ÅÃ3„1·âü{LºÿˆÆH˜ËbÒ'Ã9Ã?|Ù÷hmKåfÅ;¯Sh‘›µ7mWÝym9ˆdémòé=„cŽîûEF/hœTÞš¾­*‚­·ôó%¨JHyiÝŒªÞašr¶º(þ4ÄJÌìöÞ!ó§D®—í¢¾l1 Ö¨ zL]Åê9+#Á Pw…¶‰MÞ´éÃd@˜Ha” ¡#×7%~΀&².Æ}ü+\ïÙñlíÖ“L [AF´Î6›ûQV»þÙKJV€BVdð çIIˆœm§ HÍNŸø”=7&¥—µÚ¶)ùˆNÑõ¦,ÛŠùÖ·w‹wiLl™À¢K ó)5Ÿu/Vb› †snVíd{š²^*#¹v¤õžæós‡’̪Šf†0Ù:ÖBÓH% 0Þ1Y£+-:f¤æsãÙ„²°µòp+©é²€Ð%• Ó–©ôÅX³¦‰!˜´5‰ðªSÈôLàœ'½2Obš•ÔQVTe¥O@)–ÊÇš_6½¤0 £aô ÐoSµxñ”|‚ƒÈ­I–’¥VV1§ìûÖ±i LÿPάvjx&ë¥V´ w„—T%øKuj³)Ñ è™`t´MÓ Ê*r#€[û £LŒÔ=ÙÄÍÖù3OãC˧i3dBÐ'vùÖdUUî8ægˆlË‹<)ûRBÌ<°íFUR¶™Û†ÏÊG![¯-«V²†O€FªVE ÔFZk‡Ì¤‘V"›&ì°BªB ðŠµ³íàR…¾ó'@fîme•$¨¼-¦ .ðdËÕ`aY…VL¶.Íڟбl²‰ÕJ‘½&×%K¹O&}>™+¡écåŒùËJ‰Ÿa"e©£eø“"9¸€XT»,¦‘0pú5 ¤é&;qM«"‹‘Ý|¶¶”ðÌ)Ó¯¶¦­Ä”ªjj­ÜÊÖZyY%”˜u¬©µX9%1iËÊš25CYÇDö4ã=,†0²gâ†Ì°îÇè{ø°XÐ(myzUà?ýãÿ J}öÏ«S™”~bŸ¾U*e†»©}½;jŸ}»—98dW€”#˜ Œµ‹.kK#Ta(G}§-5³)·}­d©ŽÆdCÆXE-2ß:’­ƒ°^ð}àŸÆÚä¦f8€éI•eU­lŒ72O ~| `kW”O&É`@/G ´N,õFn˜4ŽÐWÌ{R½ÍÃÜ6O@Ôn¸ñ ‡é…âœi0Ö†±J¥ÙšOÝWEæŒR‹õt·JXN‡Õ:²ŸcûœžƒÀÛ6XåĦ*&mâ"fÓæ`Û«eë*Ì_ |ï†-,¸Ù’!P/XJ¬#Ü—  _JIàgK#%ø×âØ}¿%d‘u¡Q[Ö× €Ñ ð‡d¦JÐÌ •Xs¦‡4C©¢dï¼3vL&JêÒ$j „-‡¶p½¬eÕ"&–í†km%î}ЈxæMXíÄ×ïóh6‡5…‰óQOÙ+êÒrÞØéiè‘k™óJr®Ä:>€©u8ÀM-ˆ©v[£ÊÚH˜Ò fÛqxbÈšªk¬Dk@Ôך'Fm[ŒÀ´6@V;ª3í+3OÃk$• Œ\/|7MbÛJòDr3F0YW•U˜’^UÛ ½º˜&I@ÃÍÏ@½ôa4Vz«MÇ¡0i—`JÀS®©¯OßÖÂ)+'`•9“ui$n1V²Íl­p`%óa.4*è«­,&@S/³ÍL_-€™¿½Àª—Zù•…–ÂŒø—j-›pš•d‚§TÛ#F*q·Ê3èÍN¶*Œv”u©‘l¬pó¼%øÆ[ ¦4F_[k%Ö+üœ}íh Œ™»·p'mUÛœÄ0·¶ÙÂÛvðôNÔ‹€¸ÀhÔ¥ÝÒ?R CV#Ê Ó¡dWheXá:Æ+¬$7Û†”]#sâ&RÇN¡ª¬ãt¥kY‘ µ5µ·ß/®„I©?ýíoƒnÓó&uÎ5«$Ð2™õøÝˆ¹­ÏME6.R3$³ÍS{¿x ª*ìHÕ*ßTÊ™¤IOÓÛ†˜o‹ s n’†Ùšæ=¸‘ò‘j` P•Õ¶Q¤VL23ÃVA“&€*ïMµEªeÔ%`ýºî`[²œH¢è gÀÂbQPŒ{K'ÂRÕí•ÉÜÜÜ¥{#ÞËŠ"ÿ&Ô‰Ùf½*ÑBÄ—ŠIœa­Ó`º+WÑ„ô‘3iÈÕÚz{ªŠZÀRýý &s ÌÙ€)5å6¦VŒlGÞô§ ­‚rÙÖ¨Ö°ƒtç}%€ Þª„Uú••BÿÇ_@Õ*¬–˜’IW ¨ªP—RH%ÂÖÊS(¿Üç}8³Þ© O϶-qJåºÔ÷zœEÊ[)M3¯Äбæ#Øf¥0l-2>+zc`J‘ÙZ;T¸” .}‘i'SKÖT<‘Óoù¤ù qÇ[‹^²f®VhÎiZ «l²UËÄoEý’¤0¥iÉšyc¨}µÁêRGšºl%°¤ÊrØZ¥Ä‹©„ &3žÚ•4­ZÊVLb«PžUYµ€ª©• ˆi6²½±Ý€T3ïÚkw:}R‹¶6OZ©±KmòñªÌ᳓Ñ[åEÎR¶‰1gˆo´µÔŒÙÚ R˜d]ˆŽÀZàSÒà­¦Šl6žräĶ €5òq`å­³íáJû©]|Ï¢1Ôþ2íõû¹(Ó4jݵӫ‹ÂgÅ–¤ªøLÂõmxLAP À&«©ùað#Uí2'ØÁ‘Ä¥€’€u9M¸TäRHó”Å/dÓÏJIáf”O†L¦<\m&­K­/ضÖÛÌ{g`JÛ¨ V’^J„ÓHaL¸yš–†Àê˜l­Ý3ÆÍ$ÃX1 Î0’?ðÇmúHCV/]DåÖFmµ«Í£VÅÊÌ\ùY:fÀºÂމ^2=CÎR¶yÎø?O=“Y妪/^Ì-gk3ÄÃ@ä«Çw3 hd= dóÛJ) $h€d1+·•µ6^¬œ ÌèK¦T/©¿ÿþ»ß õ½êÙ‰|ëùóÆoò,ªÐ×i©ÎðžMJ£œB–ILg AöU&0C‡± ¼ˆ·Â‘ám«âvÔ÷ ÉÜeMadŒ@ YLKxÁ„˜@æo=î7à‚LìDÄ id»½€f ÀO¯j%o‹á©÷ƒ3ÆJàïZxv$Ïߪ#säŽMœ¾iYáÃd°Z[OÊÖ]ÁH%À9)ŸÆOtŒm²]d#Áùp”ÃM¸Ôº3AÖ®ìfšs@¿ÁbÈ0  i‘}¦”Ùê%à_=e-ˆ;PÉzÙv'®·ÛN3ž¹øó$¾E­uil[¯–òÆn0ãÝ{ÅÛ #j ¨… t1!Ðë´1”‹Ä×ãóé£ÔÙ„™7XVªP¶TJ˜¡5 ÃTˆ/U¶B[Ó(š­Áò‰‘zgn[‹Þ¢ÜhªUÅiÛSPrÚ#[;‚bµ)‘=ëx[¼°_›Ï©ch2\¶1– 0qŸ ¯¤I¤„Ž,Õš[[Œ-kÅÖÅ£)E™xgìè r4J_y%²&î»h ’^¬Lót"¶9$@îc¤®ÇçÚ»OH… ô¥é#lŒ|VäS#ÛôLƒƒ¦>Vwà;c L6=\¬‹­.ë5HVvL¶sðÁÓX²¦†ok… ü™àêK#g8Œa˜'È3¾•Cž²+L‰#ºI&ðÌU‘a¬0±UÄcÜ|˜Ã1ºÁGÓHÁ1ëÔh@iÌÇåû²!iDx¹IÙö£g‚›aä&^K²Ü¤´˜Rm¯ÓÇMi“R!¬°Ø ¤A2ɦ|·1²…l Þ–}a[GšWI<ý ÜzÒ·u#©[ÃûhXaLgéi*Ä7˜Inõç¼mi€Ì‡}`ù û¶QE#ˇÛß~û uÐýˆ.(“ªß@•HŒ¨À×F¡mCªÂ_öêúj !P[»ôp_.xwA¬pþ¶©++&ó!(0²µËÙ`|d#g›§Fs“EÚZ•Ì –ª;Ÿ°µ¦e•ˆHk˜2,*¸ÁýœXaK¥œ¸>ßAÚŽW%â«"ˆï°Rn ž¦Q»¥Ç´ÚZ×7L9C²Þ-&e­"í(÷ 0]`š5Mö® è+<¦78û'ÞT½Q˜H s«-«Æž'ŸR²mr±ã ˜? q)@mÎy®]|-`|)«ZbVV]8ÃþTFœ?€§Tˆ‰þ5Å£¦o ½:Q$¼¬Z˜¹µF|ôÝl€l>d˜K c]DÞäÏOÊM¦Ê—@7ãaé"Uqíd¥0=‚¦­)\¨%£é +úü³§-q¿îÀ¤D&Aà˜ Ì À[w]°Ižè ræ&ÈZs¨WUpïÀÊY)—}ú)(õºÍ3[zŒš§W+Ãó„‰4²BëºÃÈ6'·¾Ó«59Þ6+[QëÈ ƒ¤äÓHñÌ_­*¤ ïȶó*D˜YS…€ ®êÈFÖ¢¬5Þ:¦*«¾Ä¢™ï­œE ÉÙq@ *´åVUš¶Î‚t(%Ä.Á–MâkvRT;°–%Ö£DÀx@ÒÍ÷tJ5õ0·Ë}þ7~¶ ¯\a-L‹Ü”ÀÈœ(Ï9[X­Á¤0Vã1¬l­þžhŒ&¡Q(0l•z#fó´ÕhÊZ+É9%hM£¤Å̳B)÷cVæ0YÑaë²r‚²ZX þfž­rY2À*[‰‘ ,«d´ªhèád¤{>ÄxV¾a¬”µ#h›C£&SÅg!%’½$1’›µÀ´Í'R‰¦V)ƒ €a·Jg Há‘dÈdFª,78HÎ à£Älµl}×ÑV¹- Äef¾ÖxÁ_ÖÚS†ûD—JO)%2 K1‰ªHk§PÂ\tÆLl)¥ªÒÔËjK¦Ü(mEål$ ˜ &e<JYd8¸m KV®Ýq¼_µƒñªlùtáHßMĶNÁ·;ð*ժʿÖM¢ omÛJÐ Vºg‡Ý* ©”m—V(°ºÂó8”#¥àf^#@¤´ØjdUÕZ‰r €a|bJ[ç ´=¹{F…@7smΧ [|¯Æ:æÍV(;·yF6’,€©ElE-òwä¾rÓŸck ø¢ á#{ýÀ[ô焺cˆßàf{]X‹p[¶•,»*†NÔ‹Ô`ˆдŸ[M­ùKáé ÷ówÀÞ„UɦTKP!`; @6²^˜¨°¾¥b†¹)ác¤’ºx$Í<Óar09œC‚l}:Ÿb€-ϾâªÍ¿vþ’€(¬W&õŠ/ |ÛÌÇ ð”Ú6+¿U4Éúh¯)ñzEO-YÊšJ‰N$[ Wû©Á¹¬u“lZƒ¥Çl1”½{D7ÈÒÀs˜g>­šÒ„ssÏ< i+¤hZab©w†xkírƒë[ ÌŠ (k­¶²H[Ðw†9HÍ9[«‘ð” 7P/…õÂ+¯cÙn«Jß.~¬¨¢™ˆšæÃgú列˜aÛ|<,)Uf~kç†ÔÎ$BI¡Š LÀÁ›ã_ã[¢­5=%,øÓ[+4<ܶãÐìÍ¡!À+Á³Jl«—#4ÈÿøÇ?(ìE5V¸©Ž·q¯ð,ø,zÕvé‘e&ØÕ·Ÿè¯ðzÙ ØÚÖ¨ÁšóJ΂ßíô`I‰á'ë´ºKÑ7öÌbhŒ±.™gÅM`”P€m (´Ö1qWO cµ¹a„¬• 1P-Ð6}ÙÓéF]ÀüÃøèÈ‘é™ÈjÔs„…9ÍcE’Ñ“q»ØϪ¦Ê¬ªz±úÓd¶ÕâeE¿å#Ù2¡¶"«ºÄœ)o#[“”ª+¤l·7°TBOVíÄ¢ÇI£ÄíYÊsè6ºU6XšF"p˜†'A¼­îéù·µb”WâÆ²²J %Yµ%.J‘õ!RŽGÃ&‡åaYXßf0XÛ4ÓïWI „TÃÀÖ—œsâ­œ3Ï?,•9 Q§Á½¬¼FÄÂV”Ýä@¶jemé­^ĘHŒ€ó‘êzÕâmÙÂÖ¶J[+C…Ýíôx¤Žû7긾²ð¶€’¯öüó&Ï䵿©VèutW`» Êæó)¸ƒÑ›–Uç’å ©d€{€=Ù|l²€­7ÓÚSÀªÛnBk ñÊ‘”Zx(ô¾Ä»d3!h˜&̪IÜL}yªRoK,º¼*)«(«¯jVx¤uJâV( 1‡•Ï!œœÛNW•l©j™chÖ%Ac»^ú›Ebíhl¥[×åZ¹Ò0M˜•.ÄUa–JVXG[¼¨€¾†!0gµ4ñV¼,«NÑ#šÁ*(UÉšß;‘K¨;q[â”9à1Ùâ…m)+¾T$&mŒ,¶ù#ÍIS£È<ëB¼™ª(Éê¾LŽ'ÛØ:ŠÜÚVÞÖºÓøc!Ð%äŸ'¬V!1ÆJ¼`¢Jä‰'n"kÝãw/]Š ê8e†²@n‰mRÆ# ó;>YJY£jÔ–F‰Çj­;óf°º[Ể1É£Ù`™ÛÎ<=±¶Ö|€píØú°À}ùÃæ½{01¡¦ÔåX|Ÿ&©‘ : >}B3¤”"¶%æÉ$’¸¶E)bÛš†mOïÿý4•ÇÈžÆ÷f®êsöšÊvEi`‘¬rÃ¯Ö ˜³îÈú¤d˜‰mY‚h©ªl5Ê c«ÊvçêÝî€ÒØÂ…¾YuKù§÷àºs†º‰Êm½]u‘%ƒß-åf†¥b¬ú£{Ûi0ùËâ‘ôžcÊ oÅçyU;+ÝEâ3Äý(Y †òÔ‚3¥Wñu躪" Ó:s¤¨uþ}|ôbgÛüî$gbV3É¡m>V‰´®ðrç–8X PV ‰©ömLÏÇC÷gcÿêúJ åxk7³ƒHeK,{µ+Çá)ôDºUå|ºµ4Mxþ`ƒ¢Ã–h)<ÌBdm5œŸ©@¼’žSá5ÓOs¶µÂÜN{AièE ½Ž"g< e |¬ÃÐÓèXuIO@Œ¬H«’ïD‚ZçFO6J 8Ûpúbr˜Ò¶Z+,²î;…l¡ æfºb¡ðœ…Ì‘7€†x7Ü%ó©6ÏÆCÒ#­‚¶ª¢éµƒë˜y'²fh…5å–9YMM>Y¶ÄdÑ“U"•¿­ŽÍ¿.¶&%à …‹ m‘%К ÿJ¯JósçÉyåõ•r¥Öï8缂ÌÊÖªpŒU˜­†Ìª$ åƒÊÓŠ)²jž…ª^Ÿ/_HUH%]8\£î–²â›3Þª°Gl[VdŽFΓL¯<7<,zëæbµ9dRI)XÜÒÏãƒÉdKÁjYYý&[_¼Q­ /[äFSêKŸÆLÏ“˜'Þ/aÖ¯A—Ð)è'A/ €ïµleárêÕʶòÛzúFJ×nE[YômÇgÒSHƒ:µÞ–¬òª€døÌ)‘oÜêóe»BÊlÇØ"Um­ Cã•Oƒ©Wk •$Ãx{ÕºÉæÉmž§\Àü…l¨PŠ[Ïæ/8çÙ–@#z+†Œ€O˜ó:ÆÔˆ”m'æ°Hf•å@/å±ÂZªiáf#6Xé«}­b¤¯K#¨…«À²Ê1X÷l­¯¦ƒ4LæYám‡€5Ò*ø«êEeØÛ¾¯‹z)8PÒ‹LVØòi¿!HÁ¦í~|•5yâzÁy²­ÿ†ìÍ ©x «ñR¶øÎh¤Ê‘@û–Ø'T!±ie[;/R¬iµ‰ñla—6X þÃa>°ÿ7w¥ÖUXó'[Îù¼ÙùTEˆ½ü˜^•ÛTL8Ky(HÛ©[G€‘² )1¥FR•X×B¹À,”TK+$ȼªôÝ›ªdVOÄY(Ê ‘JºL†ªàj)¥ˆEŒ-=™ve1R™XJ%³6e ÞSÐÊ3´Zóo»Z ^æ‰4§Þ/%ŽÜEz1l (,luyõdRå²_áy”¹%@HÙ2?ÿPÒ¦´¿TÚ*=-ù:†¹Y(±²‹§‘ÊÓJ©„Fv&¶R”²€r«Ÿ¾>lÛ”ËÚº 4jÉà<ñ9hZ ¶¬iÁª¦V© ø™aþ(eñ•À›¡­ ´Ú 8C˜R•õª~.ñö€ioÝç60bRV¶†8‹²lá¦".»^UáÓXu‘}ƒOUºãpWÖ ;BnH†V…¦Þ![JŒ ¶ÖÎû@ß“BfKÜ»¡F`†»ŠF*k=¾ßHœ'[ÇWiÕÔ 3Ì m ¸YÍlT|W1 –r>0FSQ!P¶m8Y-è¥OÙ[z^xÀI] ^xëîžwUömŠiŒ&¤ôæ'HÙ04ݶ^ Шo7\mŸG&l­Þÿy&Ð]•Õ–‰Uè#E x|™¸îüE©Àj¯ÁY\E_L Ý =) TËóÜH`mT©U!雜9@#Ü!~Îl`U:ºÛz!»|X Îäí"+î8«<ãK5Xæh³ZmÀŠÞØžKÛ. æ¦VÀu‰´f¶Î>2©æÁ3i»iá>”B[µ•[WÛÌ4pcÃŽP ò­­Qå­› ˆq^Ai’HÓÖš¾Ið‘­xšÅ©¶Ræ±*‰„}ŽŠ.-ÁÆ{ a²sòñ÷Il•w‡œiˆ1ÖŽ#™X +ŸÈ¶yVÒœ `â"ÏÌ1 Sâm¹/ê…§·¥Ì0¥¬¨ Ž“ ÀDZ9(,Nå÷½=nè«Åí`BÜ+¡Ü©jDZ%8 ¾/6¦-YY‚Óéo÷/wþ9YVc ÿØ"¾9=š¦JÖÀ^åÆN“¹Tƒ!cÈ"­<‘‹UÝ•haë=I€!þË_þòŸÿü'}Me›d¶”5í ôDÝ;e/aʆ¬\ë~Õq"äP¨„ÌJh—€¡ÀÔOÌÊŠÁ³z« …鉜sVfn‹W…TBÖUÉ|äo6àŽóùÏÌ«b‚„;5Ì!äi|[7  ÜUÀÄÉ®ãÄ4Ã;Ùü4Ö1fæù̿ɻ@)[zóWe¥DzF~R;95Âw'ÍGVÞÕEVÀËÆÛâÙOyœýk@—Ó&Jª¥ms«1â¼Þ¯ƒ6AÖsç£Ü–[ÎVX°‚ý<XõØè‘˜fÐ]ð´Uh$ÛcC þ€Âƶ…›¤¬Hлw&V2$OŸ­FYáß@ÚR …uËÚ.E©EVUÁ1gŽï÷ò5û,H dXØRXùÄеèÞ _—•pP…×·ùÛ ¯Q$}¥\pjkG‰l€›ÿüR‹ÉÉÁ–òÎ~~ß…ÃÃ%Àk—U§k° C–I‘aXh­ÙZ¹µmUeÇc`]:Z&°ÐÎëç¾ ÇÃe¶Jê¾?ÛÒ[“˜¡×,qnHåZü.-L `úLÈ8xí})cŒÔ ÃL(ÓRZÓK9ËÆë‘@“Ægè?XÐ(ê®PµCYs#ÐWÊ6FS$e+€Ùv`ÒÌp¡)¥Ô:,\¤ìª)_²Ÿ P–¬TzÖ¢­T㞉4BÆ cŒú²Åh„¹Ú#Æ[ ¤ÂL>¾÷…^Ón^•²µíÇë¹´Ê•pvz«H™ç[›!ÂFÂôÐ[+lr«WÕ:g€ ² ržOÇ!˳Ùâi˜»º«Ô4€Àä³µò»@z¶p§[ €7[2}mé'¸ƒŸ%k¸µŽ#µVnfå \ÓÄyf^áz!Ó€I>™ô‰yËm¯öómÙÑÏJ_a+q&øÚÑhZ+ML-š¼9› C#+(3äæU÷Ýo]I†dŽ µTc$Èj3ž5=¬„L<2‡2O#Ù6 ±#ÕYSë@3HÑćmÓLÙ”¼2¤­ŽëkÛÑL˜§ÕœŽVm¤™É Ù|œ´ÑX šÐw»/a}+ÁkM 07 v l…™mUMß½iÑå—Ͷ¾¨!eÊ:WÓb8`r–Åtê:Z‘a%Uµ¥,«\ØÊúpJ[Ù&iàÆ —êË¿.4”4Ŷ¬Nï{ÃJlczo»Rú"ëî8ý°öÂwÃRMK@ïr0™W‚$ÈÊŠ4Þ má]ËÄH¸52ÌÙ6+’CÇÄ;>?CØH~}²6O+*úNáŠbÜ’_'¤ÈÔZkAFÐHWÑö´ûë_ÿÊ‹‹µb˜NêÌE}[ʘ~Óê9Õ,}žÖŽW×Z7¢,ÌV˜ÆºcóÁÔ´Tþj¥(õµ|hšŠ Âª…Yu F~Ò|ð…-p韩 ˜”¢‰l03HÁõm˜ÄVAßä­L<`S >&!€­Y÷oKÌ¡¾ÄRÞf³ƒ«’"«„@dU ŸÆ#0XzØ’‚kšÖ.Ó‹¨sNr_&+ƒ‡É`Œ^<‘LøgX¶-žRÔq+MUchN³ïÁW˜[ÙƲĮŽœ†!s^­_ŸYÉ.t79¥à`+`…4Jºm)˜' /@ ’¸Ù*i*<@#‹¤çÓWYVÊi càû ­ =¦Ž²=¯¯üç¥I5­ =Ûš6!°6'[²õAРι‘(¶òÉÍVÖ6Ÿæ$ο™­/v!‘Û:ç~zpœ¥šÙ0Ä0+^¶;·Õ%q-lá"¬P(QËÍjK©c81&ÿL¤€ «µ%†? îÑEznHúî§,œ`$ž†XºKUÕãh{?™h'Ía«ÓuK•­†›ºÊd4ñÖÆè–dsHö®ñ|Ãsp]Êm*Oÿ¶ƒ7' ºðL*± žR¬jš¾±­uA¦±’UÚ1q@”µÖ4f‚´bˆ·­oUH‘¸ÃjAŸU‡íYD÷ù%À > Åúr ÃS:N­eû¯ÐHšæOÉ-²©d}åfN©O\¶Õ6ÆZaé›Dy©ù¤'¶¦/eu4ÌÛ®³äi#jJÜGP›`LVÈ@“Ão · Ó‹Ä­ŽÆVªÖÍÜÀt4[J©í[Q orVÉ€¶ëU—ºÓˆ¬òÇÖNZ Œ.M¥NãqÀ”dYѶë,UmbÊ>õÊ››Ô^ž~´ñð"ýŽÈÒ7 Ï+<‹¦µ¦ .k•G}ƒ¦ c.ˆ›Jž2ÏÜ(Mn¶¾CÌVU-( ”Ûv?|*,k%(ðB/¹ãGŒÂª6F˜¿°,¼•¡-+_m©²a&«¦é[±Z¸Qé+﹬äÊ??ï4®® ‘UÈMªŸ×ÊêHlKl­c½¶Ïáý[€Ô0RlÏWÚV(H.]„-@ÐãÑÛVy2×gÊSsÏ +§Q³š¦}Q*QHSa%dÊ#3X:I@IDATˆ†l½NǪƒ46}…4ù$n*óweN‘¾adÅÌÊ_XIÊñGqß}!OšŸ ‰¤R"±1úæÊ¶&ê ÈZ+,Å̵0„i}…WÌöÒŸßDUÕˆ (öX›°F +ñÔ*™ró¸Þ&©„Ʀɹ*kÛM8&€Uaà•ßÌÏ/&Ùèø&¡ÔÔ$”m dßÂÜZe{½ ¼¬¢ç…‰){áùsæ)ÕyeiZ·å€$¦TÛ;ŒÌÜ {?ºdæž ªRT±m$¤ QŽ”VµZ°•²­Êé´V([!\9ž¸Ÿy͆gÕÑ:£ªægˆ'Ø ù`¤š¿‘³iutÀþöÏ¿vÕÒk'l4O–Þªm5s12À\HQ &ÀŠ wÛÄ® ãYä e¿Âe1‘ÙZ5¥LlÛ‰^}+’¬ÓeÒ…H]ƒÓŽÛipǮШ< ¤\)O“¡UHYijÑHï$x‘³•§µW(™­òÖ™ÃRZ0Át„.°# +¯KkóÀgÄ{3ĶN!¥{U˜"J[XÄ7•Ú•¬]$M§*·Öt&9,RÚJ @Sæm4ú20b×K ÷PÔ6ŒUH1‘"P'î7<=¾Z)Q÷V[íÔŠ¶pÊ& #%Þ´­µÐ¥yˆE…VX0`KŸÛÄØ;cõîåÐ0R=”;éçw”L¬ÍS#kþÖð t´išnÓm‹Í\‰¦]Z)d@Iþ²^]+Æ·“_{“™ÀNÚGŒFyæLdà Åli„*WaÝ3Mo+ ‹ ™¤çÌø¥¾Ânî92á VVLæJ¤ø˜ß7›-lLh„’Ui­W«­’RÉð†«œZ;L¿éMÅAÕé}yôebL7ùy „^PThUU6)Ûxݧִ Êzš”ÆcK#H­;ÃyžÞß'UwÊÄÖu¬;«™ è‹ï5 ç¬uJk@‹dª0œ †¤lë.áÌt£9Ù*ì\d$10ÛjOë¿ÿýïå<i3I×/jHqéc;»L­&²SµU(`-ëÍ–¶2÷ÔÄ–L¡1â­:t*Û|Xá¹¥´Å§ì½Q‰‡óÁÕÃÎÄØ¶BUž&óf0½Ô·îü³¾†\¹SsÈD‹ eB8>ííÿù{&¶V|}›ÍV¯jey®5[MoŸÏïJ( “ú"k×qu©™PBL† i北E2TõÚҬʾ:{µh„Á„¦€K Ü¢Ïó­þ¼ÓȦ­‹ µZSÊâ ¶kt¢†Io• »Íz9dÙÉ2o 7 YcàUÁ¼¤„ZbódR¹ùû£*'0 ¬»_j¡ )ø'†iŠF̧B]’PN3XøShOœ¾ÉõUUwSÊⵆZ;rƒYc¬ ÒŠdå¹jÁÇy¸ûɪª†ÑPËAÔS”…9—Šáƒ´ Up#9)Lƒ, ›–òSïÛ©¬TšjÃ[‘oÄ+©‘h ”r[íD’okݵkÏÄjÈHU™·»IQß49ÀH«’œÛ*$€Ý!`+´‹ðVd½r‹©Kk¶wê3¶-^æ8~¯"1`%`nôÆnÈ4°õh¬ùWeeˆ4›lOCßÀ°јëôy%TiÊ!ÒJV¬ï²cÒc`Y‘^iž†O“¿&™ñ µ˜Þ7bJŒ93©ÛZäÖŠ!vÒR» -8Ï6~J8K‘©… b|ôlÕJÙ*!Þ‡Qªá¥6C嘀vël);žy§$++•ÆV_kž ˆR48^­-¥À´&˜g‚H‚¶ »–•J^öÎÒåøˆÍ“ ¯¤*<ÛwæÎÛÖĪ’uÏùøžÙ4Ì9«Óï^ò|l¥h„çÎðJ>í´1Sm0ÇÇÈ?ˆÖÒŽdÑ—È®/w6˜µSVLˆm)Oúû³Ù©»û ‹:R*á`›5 PÀu¿®Ÿ'|rHy ®Ì€·{Û®L•±y4Öp]0<ãÉ:HO&`qú݈=©*`…Ûò!Žéìx¿h¤ÜšVIS‘¹sU@3¥r¶öË’†9½ïÍ+ܵo#U²V¼¯'µ@ïç÷£‹×ygAÂl‰Ó7Ø×éóÁÞö¬lWˆlívRd-Œ- Ð L¤LÕ·RVm/6¾*s⻩‚8&“§©£±8ÉJ6yæ¶"žoÝïô™ Õ¬y²Í ö•PflLí¦7F½²JPŒÀ40gµRHŒîÂãv|<²I\[â ë¨]¶ä‚!œ3†™3™ûrSûßÿþ÷<²•BzÉ3g[ AÀšs3'¨D•”*ëD1dLàÙkבû€ˆº Û nV¤*±l†ñÜÚZÓT¥#àÆÃP6›#ðqoodJ@Š^ÐÛjwnùû·9î¹³ÐËjÁ‡Ø‰‰i [ Û%Âx¶…BÎp§³ÒW…_»ÄjGbdéŬÒcVÑH€1¬L¦çvº‘”U"`“Ø2Œ‡+É!^¡må㛹(eÍÙZs[ v~Óe2¤­¨v+½.ùxd>)ÉNj¥llJ2ˆÍFÖËÜ…4’f/0̧B-¨‹U!’àô¸÷Ö×N£–b¢$«]¦­òx¸Î›¡B&ý±4BkSµe"‹¿ªÏãª$ò ÷˜šÂzí®²ÂÐX3©FÆX‹dTyÕÚ„]²;q´w$†”4xM߃$c»,`K¯c#¹ RJº1[dÓv.©dµà°YÎ@MÍcl+dB é¹`̬6±ŽÎÛ6Ãd²º^²1 f äbJµ;µ¬-%ÆØºØ&æIèñ§ßõ‰ì¤ÄO€)ÀÍœÁ$M/$q×Õ0ô‚¬.°Z)Œ*Ûž»mŒr$AÇÌJj%ªrY!þ ɇ›  hÌi•CìíJ™[3ÄX)ñ@Ž„¹-4s`(l&l»ã›Êåc”ï®Èr;Å÷Z”+!ð'pXßRVµ•[M%ÔØÊÖè(n‹ÖÊu'ðÄÓ¯J¶GÀVJ•ÖÃVm s[­‘BysZmh„O†Ï §WÎ?qMÕÊbD ›± ¸És¶U«Pøª~þê™”P"€™ÀJ̤$Xhl«ðþx|ô¾çÉ"wv<½‚egÕ¹b4jkÍAIØÝB² hÄÖÖºje­uÇóì cÒs¦¬Ðê,ÉÇ™Xy¸F¶ª¬ ƒvbVéë22ó)ñ æy²êDÀ(¯…’:rP%ê5@I_I)°z:d|[k%<­"¥­·=R#€Øe ŸÆwf©f^G9c–jZþô5Í“†OM­"M“Hj­kš¾/2¯¶K3$®V‹J²ÂÖæ·ÒP*4 YwàÙ:T<%²zJš¢r-€9¯cnúv‡Ä,ªª¼Ž øÓ›°ÁÈDR”¶ cÚ•³ÅXsKcm`+-ggTKÖÀ@[ˆºó¶É<_PÉX¤lÛ10¶½´˜3¥™LÈß*EFcmlÌ.?‡lemÃ@]Úš0k2Y$YïI>RÂü êBàÂGŠ,«Î‚Éð¥LV¶RV¥ð ` ØX;šÉÕº ó  Û€i„lnU^MV¶V%V¯eæpŸ¸x…›Ý–Œ¦¦ÀŽ “iAÖ$¬¼p¿Ñ‘=z2ú ›Š8«PEYÀš¶ P$NÆÇü½üá¾ióÑ7@¦–¡*ŒÈ¼1Ö[+¡dÈv<&«43ÔKI[óÐ`|Z)ͦ°v4$,M?»]ˆ^ ¯¯Zž˜J¬cM1Ä WhoÛH˜Þ “~akNþH‚xX 2X¨ÕËZ`v¶š6Œr¼âsˆ‡ódÂÁ6YšÓæk˦‹ƒ;ˆ5%$“lcKŸîÇwŠvdH@¯Zpk¤È§Ëq'Rµ{g;ƒÞW„°v: &:i`àf>Å$>êZ O ¡õá,n{…m 4Ê?·¶la%V3óÁØz(j;þ1½O§h¤Ž©ªxÍ Ò”ª4ã£Å¹ÄçCÇMª9­jç¯C =ÌlñY¶WK ‡ÕÈnK\#@©5å¿ÿýoæd²xŒè[‘¦Á¤``D[k#a¦1g­óÄÛ’ßÒRÛRp#½þpgéBˆ‚•ƒ`4 “¶u‰´ò²V#õj)·upw¨uV¿’·]µÌu—¬H&ÊyŠî°¬+2ñ™àûËY¤B@¸8s%dZóRÀÛ”a[”¦¤ï„<Ïctöóøß <ÅÞ¹Z$¦§é¾ê¢Eç,%+”{@o˜-qëÿç†Ïg¯NÇA:>7`)V̺ €On>n•R‚t.nH‘ž&ÃÁRÇúû¢(4 “H[˜Æ*ð¬¸Á‚ ÿ…åæÄhê{pÛÎØãæ^ífоNg1|bn‘H8[â ðü¥0 L³à ”ç“C+±H90¶šS9[-üyF»þ¤Šl šn˜l¥º4[µÍŸ¾ßøÝ†ZÀyv[L23Ør°µ7íÌm7F37OJU7¡-Ï ûÏ+\£7‰ÆZp`%e¥Ab †ÜˆeÑÖÙÉR¦I`Eªõ‡p«)+…4R R iK¿q<†F;ç¥ÑTJS@*+MwN&l+„‘µ%®]µzÙv-Z¨Õ×V„‰ zA&åhÕ(°—Ç Ó·r6Þ×és²d‘€è“ Cgl6nsÆW»±™49MAó–˜ÖZVJ¸[&0ÀíÍœ;ÇÐó1 ØÒÀUQöja:¸Â@&ø¬l›\aUd›Á#%2éZc`V9´…ÉÉ!ÃÜ2œ@¶*0Yn;^)Û:’d¬àZt¯†åpÊ€u¶x²žšòxUøµÆìÁ#êÎõU"øÐàaÀð@—€ šPŠs­}©ûB|è€TRU‚p]¶N¦¤*åu÷j‘i—!,è»: žØýKy ]Ëý~TÊÞÎ+ÇoKy[}^d}& é6’íÕ]Oce•˜F ѵ° ¤•,eµžÐYd9×q•x2z+ò8Þu3®">½Õ%t?ÜØšMØö_TS [­cl…™3Ô·v&äKÁByª:À§±«ÂP^û³ÐcF6^»´”ÔëÖ[¡‹h€JˆE|¯kn45ݹY¥^ „Óð´5ž¦ð>,wŠscªàJdMþ§?ý‰Rwd‚ìI©‚•3Ÿ8PSXyæ­ù s%Hú†ÊÒÃM»ZJ˜2=b”µ¶í;<} ¬éç‡Í÷÷6n||l9äCãXÉ*q@‹ôVÊiJmgo]ï*@¨JÏvV²°T Yælk¾¦‰ ŸwÿÙ£S{4”d€¯ Y¸ÎÐB*pp+’37Ûax&&¨#BŒ^²pcÇtØLæ!7Ê°¬0|š€©,h’q«c QÃôÓàFl°<­R½ÀQr¶j‡ô¢²ÍXª*§ € Q— mée3䲃{˜Ód([‘kVµ–ªmØ„94|%9X鉳µÊN +lëO#â{Ž›ÙÙË&+‹ñ‚alÅéq¯îüùU@ÚyŒ"€ŒRtj¼%Ý&¾×êç#ÉD|ÊvMRÊûª}íŒËœ‰¾|øˆL¬Øv˰ ‰¤øÈê⣕9 P¶•!@¦¨<™_}˜À ÔŒ ó¬”)‚@Ø–R 9gl6boõYÊvVª”[»d"d÷áÌÜš9ÏÌ×Z-,A SH†lH«aüθ„Ì+ä°»š‡4V8†”¹ ½Tžø&‘-dZó©…ÆJ/R2—µ­ªnæHҴæS «À(TÂÁ w Äñ«µ¥±–jβ ù(䃱”4fÀ䙆ìv>ƒÁšr¶nùN"¥dþ¶ÞUZÔ+C-h^T%Õx ½uÙÁ¥ˆ¥ÍÙëí‘FVà9k$ˆ­Ä"C \ЍPvàÊÉ*=[úZ7pÛyd‹0Ð`ºÈ’5Ã;*,dK5FVÞÆÚI MñÄan}‡\ƒŸ_”²R‹JØ&“åi*« í÷-(Ê1½ù‘ÚÑ+ô d¢¤`PÖÔÀd¸qèÒ:Až@ïPäÉèØÌYÅÃY“4@µÁͨÊ0Œm$åè15ÀÌ ¶f%Õ{ø:«"jÎZ[Ï@÷êê›ç ÍIc+Ô¶­SÊÊÜZ™Ø’ ˜&æÔ_}% F(ñáĶõŸ¹l|%œR÷l×}…†WKiN¤µm㩘¢´°U¹7åVdãÁï=³%e­P à²u«ÕŽÆql›hkæ†!Ve5ðJ`ƒåÖ„Røµæ„é90ôù¢ÁXÃLt$ž>b µÖ4j¬(¥{Ÿ\²¦v훳­¡|&ÕjŠdX•,Þü\ V‹¬Ð—€ùñ ó4‰,[ÿýY€b’³•>L ô  )o‹þ;f’˜†Q-)¶ëí×Eünµ;´ UÖJàŽðÔßñ×±”’5­W>H@Ú©&Îͪŗ²*IoΪ0e;Ñ”.­‘ÁúýGJ¨Â×·àLZs¦ì•ëhÛ„fKv¼¾¿ðìh¥ºÀÙꘀž Ÿ­½^½$”ôšKuŠ^ƒ%ÎÇ*μfV¯“•Ûù·)S j¸Æ°²~>IuBÃ-àÄÕÚö¦fÒªEwÊÄèx$¥9zq Ô2Ĉœ3—R²LTÙò1aw×uø {zÛ^¤šæC™¹C iªw Pªµ§–¹1”+¡„AV‹æìtp´¦´Ö½ì=ÐçG2¾á»|ž ëE<}Ç)‹$¨»aÒó¼òó˜0S½#È6Lb> ó Y52X¸¬• 7ëÞ$Ì»an™œQî×¾âQÖªÊaUÁR”†¶Öž> … `R‚FJ¹IoE:K%¶)V‘>™-@“œ9ÐØuLfÌïifÃôCøñûï¿gdÓÜ,0Ö˜}?Ö{]µ,0@U€ª˜.NU-¯_¬MCà …1вUåÉDÌVEìåë—Nå k!•‰-ÀŸ>`mBÌ êÅ<š*€‚®Â–¡­rn¯KÛ²@åJ V![dGvê¬le¥æÜ–OnJúµ¬¦ âü#­¶ôn©.ÕRr³Êv:€ÙuÛM¢ùª1“¥Z+t{ ™ÃkÁGU·µR ¶ÊbrC–åp%Ÿï…°•U%€?G%æ#ÅÇx0«ô²µÆ¨êdÌ1Õ6¶TJ«”-=ËLo;Oüømû°0q JšÄvJÖPÞI)ÁÔ+ç1ó¬Äœ>Gª8ć lÃÍ–•ãHux Öº×´›ÁÛ0ŸV€ƒµñÂLÛdeM‹¯/ÛÀëC“Œ@ °10ÙVÊV8W2½ÊVž¦—ÿu.[_Y%L"óÁt(̲•œ–߯-† Y«1DsÚÊZy"›YIŸ&5’òg!% sÆ/”ç†QkÛš›Ö&G дSL ²NDC a…ƨŬdÍ#EY [2L½¿ÓÒc*™µ»"^GsRÒ [†²V‘í¶@8C‚¶Wûs‘Õ†oÝçn€ÈÖdÝ0ŒÌœÒl¹¥ÄÛ6'Ì6Mšï¼S"»F%HnŸsM¥zú :F(xä¢^³rà 2[7¼¿’ãàD™Û¦´vážC)Góƶ-…,îtg<üB‹<¤ãèˆC@ŒZOÀY Ù)“½ŒÓ)I–ƒ•,Ÿ¾æÙ‡n]ª Ü +[…ncS©_—J6 ðÞFše•ËFZÕ¦çìÅëò1+v–®¥Ú9§¤‘M)Õ¨¶Â¶€‰».˜IüúÀZEÎHúU9ŽT$`+ÕÝ!vŸ§þÎàŒÕvánŒÏF*ÔËZª9»ù÷hº2)kÄð‹–Z­³ê±j] %Yk2˜sbš;õY`)z€ cB)[¶ùØ.•£]²VÛR” mûßçœÿ P9¬ º©†PP?‚†ã¥= ¤-l¾”¦¡xØ*åkH ’¿ßØèa¼;»;A‰ì¬DŒµÐŽL- 1‡®FVp³š3Òx¶dB‰µ-\/k>x Á¶ ̇ غӋ_¬¶˜T˜!¦ñÚ2´å`Z ÂÆÎö¸¿š&$£±íæH-,Þ3ò¬u¤Z…{)9°²À­h£$YMy ©Aζd³”­¦—>Ë4o9Þ¶{èºÈ0 mÌ“ GÓÖšÌ*+Úæ¦ @Z7ÿ5;0$LïiVåø9T^kXS‚Là µºOYQ  èþ½3pƒ)ç"·d+©¶V7 6’~Ï¡’Ö”ŠéàÀ°*Íɼ¯YØV‘˜†Rß_BöŽüùF¶%XmgÙY``« ÁØêÎ#¬RÈîê}nàÌw#pL\w®VUÁ<Ùñý¾–˜®T‰ÎÇæfUÈ €Cë²~~w“9T¨Äö~«}þ^™§’Våš$ŸF‚Y%ãÐä¶=£Ö3ý}šï4yEÓÒøK …€È\ŠCú¦•Ò öå€w{4Èžû©¼O‡c0-*î8Çî›î–ÈêE²Z˜€¬»ÌöޤpG¨–¶V˜ÎVÛ{ôJ5ª…ñ€ea% +) ‹jënÝ'&}£f7Œ*zÀüû<ʆ9çifµH2óЋRu‡\ ¶«Å(±ê[;XÐãÉâ+ÑhWÝQ’·îø¨Í _#d`³5™*'²J­Œ‘í xñv±Mc-èyZÊsPIik °1`š&OÓÌÆ6}bš;ËY0BÆÃeù¬6Až=ÁJªr·¦…ÛÂÄÍi†):–%{O-Û0²dY1±¥,eíYÈC*µ”e‘m™l’îêœèŸÿü'äëC u5L饼(4¬hb€Ÿˆ€,7+·Óà^·‘êI̪.¶É´”Vd¸¾Ž§İN ¤¯6[©†Ä˜¼’)d4 @Sm+žsÃ$ï)>sk}c¶Íé¤áF²ºüÌ+/«<ÀE‘q¨WÝ­ w01AJÛ¤r¼GS ¢*¤ ³JñïzµÆ´ÅóAêŠL®Kí6•mL† s3gá™-2µ¬0ÿÃ×,Iv;^héux¥ðÃÛ;Gø#ÿ* §å{sAH$2ÉsªºG²,âYÈ [UÄ MGÞüo¿ØÍ?«*d<=_SÁ#2œ¹­¬5rU 2Ϊz—€¶M~»}þÝ|>HJåÕöÍKP#@pଜiÅØ6Ì$e%ÙVh•íÔïÙuL¦œŒQn[ao*)$™/0"ܪp.èÅ;Þ<…T%¶ßŠóWÛŽfíõ³îޔؒÉVeB%u™Ùm~º;x[—6$úžKØ¡¸Áô?¬:¯”àI Ð$ºD6lTaÛÍàw2Û‚² ñ+=Ð$pþÖJL¿ª^ŒPH£°ÕÅªŠ¸ÈHæ ȺWb+¥ÊEu¶"}¶ÖZ·U+6ÿ¬0°Ú×)è+ÉÓ);¸>ü¶1ã9h$88ãipßm[šöÁÇ“a®üó+2’IÓ’Á¢*)üÇâyçñàÐW’‰l½€k|n€þmë‹÷’eÈG*¾sá3§ï ž¦—ÇããÐ[JÙã–í ßVŸxµØ<1@a€šÚ¶1VJdð¤1P ’̶`›Hi°BЋ$ [yúE O¤µ€‘”ªø¤_žVå=ÏâEnñMžRaþ)߉`Y½Tu½¨rÏ¢TÎÊe‘j ÆJc¥±2‰§”M¼‘ê(ÒT«Š¦”yjg%ˆ§W[yâR)ëÅÊý('³*Áˆ~bVë+%+%ÄÁheÛ/¤Pˆ´eÛÒá­lSÊ:N<óØêbµ%«c3Ç”uØù`l+dEÙ¼9{=rÀßž§©,\ª­U4’c&ÎoËÄ・:©áÍÐ™È CÚŽXÑ•,XYmã5ª/r&°ÚÎNæÁÙ2ɹ²úãÿø‡´¿]ÄQÚjŠ,ºGÛzXÅAkCï¨ëoùÃôUòŒç¬©ŠDŒ•XHy<¶üµ÷îHİ”5qÊ1µ°ƒFª€Èè»’9ÐAgš;OcÈ" 8 [Œl˜x¤’W#»k,ŧxÈ^Ó²3‰´5§’xV¶¥”à}cÚúŸñ¡!°ÕÚ 7XÌúv@¤ëR•Ï™ãûzM!¸ù#VgÎƈ°•˜ŒyÎÀÓz¦js¨ªå3ã½U[ÔîbËæ£ ¯‘èÝøÔÜ Ñô5_‹}y™YaV;¦93—•Ú1»ašæÁ§§‘r¢ÆÈ)(wð¶Jv©fFÖ«™oéçK0žj•ÔÚÖœª„™#µ?b æà5MY_>…m>mO§ûØJ9Z¶¶øÆ 4Œ5²r8žSÇ€ 픕ÒäÓ*U¶·¥Kx•™Ô4XIåut.…ÖH2·mkŒ »||©¾òaE3Uº ÌBçšÖEÊÀ0Ð+]/VzIô0ASYsæ¶ùÓÐËróÝkMÐk¬ÜV!¥`í®0ôZP60†ÞšÛúF6‰,ÃlanÉjá²üm¡Ô õJIO@_ RÀVYJxz [©+<IF K ‚fèh= ª’ÁÉlöµKöƒ”K•­]­«­åÆúr# [i.ñù振Jª‹2Ì¿¾•¬’Þê!&PÕ2[?Ö•ïsT­UŠC­a)€ÍŒÇÔÙ!UÙÞÒ³”"fn;[#ͧÉ)ÊÄAš lz‚æOÜx°Ã*”=]o#b¼ŸÖÞù^<%R ©dª¢¬¶5 LŸ2~ÇÄ [¡–¿ÁTÙ6IÙV “«=K¶€¬BYÂél)ñV²Z³íC™ƒµG©<}3ç©vGhªÚqº¬…,†^¸I× Í“¦¬­*?lÉš–`—/«°.3'Ë¿L# PvQQ À ]ʶ½’Ïw]š74sÌç>’'7¶¶Äu)µ¹ñ:©U$¨)‡=ëôñ°'èÈî„¿Œ`HЯ²=J€†Á«l«£ªðZ"Ò‘½ÞpJÛÎEÐÁµ“2‰Ö:&h6©Zw˜>ÿ7 D| ç0ŠI[ë×8 <@¯ea«ª±T¹Y¼ijÖXV) ™”¨—ÚÌe¬`2Ѱ [¢rb‘àÃÙò=ªœ‰1ªu˜3Í÷û4@ƒ§˜0 s À[ RÆ[ Py˜ X8E .ðªŠ<áÈdÖ†I¯<0g[% ð¬eS¶òî'™,ÐÅÓ´µ:2å^JÙV`ÃÇt¨Z4ü”¶‚yO ó'VåÝiÛ$é‡7F­ÖV˜ ÌÁïà¢×2%’?1 š³˜aœZß <Äù·í xÁ™ç±¾Sñ²NÑ$0…•XÓ¨ )EoHÑlj2½¦¶Jêâ¡ëk DÚ6êu:­¥ú¥3Ïþ5åd½ç8‡ÆSàSG+¥Utùz…i[oþ·E•HL@¬\/dUá¶²”ø†IlÍÑÈV¶–ê2}åñ]]x-<£~‹ÒQÊ%ˆ)ÙR > eà ÍiuÉ¿ùûõB_¡À¶@&ûÀ,ŸÚ±Õ±;!¶RùX‰i¼34ɾÜq?àe{çé‰ÓpNÙZ#¸aÎybÊá>§Éð @¯# Ó±»"@b€Œ §Ÿ #Ë&K_“¾FÙÒã :W î9`(Ebd)ÛÈÖ²ÖÙY´œ·*†˜4ÝvÓ¶ÒH©¥Ç¸4i $0ªˆ!Qmþd0.xŒ··,ÛRÉð{ ÝL† I#øì¹Ñ”Úš>ž?  Hß̳ŠÜS°íÈæoàÊ™Wk UázY»J)4+¬ ÏZìÈš#‰®ªñ`¼¬˜ÀPGÚbl…-±­€EM1MØüYäÖ$ĶF p¶•"Ë_mØV0éKÎêŽsþ™¤BXíkØ»áÃÎ/T1‰‡ñb_zlmëH̶.]&‚kszQ˜È@GPåDzI9,d“å¶*â4Ùr &%¶ëÎS\ã3s©n`z¼-Y­[õŠg²—¥²Â+ñX+d«„V%µ¾ëCL ‹Þs§T%vJ†dRïÚCÓÛE¦V ׎L– s¤­Ázp02=,›æÜ£ÿ »¤r0Ò W@š:S-OÙók 1’8k 3óTbh«À‹&Ž©*Þª*œ†›.)7 C4>“ÍÐÌßlôH ¬ª*Tk<ú ðjò”Õ+MnpnL”¨­2¥Â¦Ê¶Û«J 1A%CYÀg¸ïå—² ¨XéËV- «¶ +Ä;±m‡"èAXŠÌ¿°÷ÞØÊÖˆyµV8€c­]%¶B»H2&d…КFЧB ~%V•ž91L™Of#Ë4N´Ö¾þzˆ1Z™4’a`>­æÉskL+U07kÂ^~©²»íi‡yªà8ûb$èŒS²ª¶Öðf¨»ÕäÖš–å°²Ö«¾”¶ÌûšÈ¹›é8ôB!òå1›|†M¥øÀo;šdzØ^îónd®P•©rH\/O Höò!+ðºÙ¬ /ËS¬°7Ì+Î?ÏJôu9#‰òLLàYÛfEÕ¶™mµð¶Ú4ë„é™X•DzXa”›¤^m1FÂ󜳔è¤5Ãø°€Q[—^€ÈÖŽOClÕZGã)4¼£Ö·ñ­$1·Ê3|¿pZ_ +c UVÎRs SÐ8È)øF?•à*1g-ø÷“úzœ¿6ÆV ²µ-Ì 9dë—*©îzQ £ ©x%j+”Å·…•póY;[‘ Hoek-èÉ´”dk¥Q²“ÓT’Õpã-‹gh­¶^›Ÿ Ÿ°Ž4¢o n²¢©ðuÁäƒà`ËV¯š’¤ÂÄyVÅO¬ÜJÀAŠ&+_Tn¹Rùôñþt^&RsëP†I_ªÂܤlñ¶jémM…¹aà<¥‘•,°o [ÈZa+ï›§ø{¥NW/ Öz)'³%¬°i¥ 8Ÿô²Éô‚™ É¿ÆK‘µw¥­ÇâÛù d9Xáz5O-X5†^Ë"‰ñ‚¸Âª8‹¶ “ÌZ Ì09O)†ÚYeXÓtdà&?/g3}²5U¥‹wÌ ó|mÛrñ4ë¸;QŽ÷ôsˆ¯—÷v†²Ýpþ @¯‹QÞiV@„o‚ÍÁúÒs ñåbEš2Ͻ+›U67L‡‰É )8K”—8Œy`'D T"Õ3ÐK•­ „Éj¡¶¯NüN¬+±…wÞ0·.®F²f¨ÆHdŽó_—&SB£ÖÀ=°i€æ!cEi åµ³’åO#ÅG`l»Š”¶Ê3'°dýgžð¶Ö‚ ¿ÿTn5[n]Åâ¼|BI³©²­äf>Ÿ„úæ WÒÕm$†îAYßµ„m²+1<¬µÐÔ6Mâ ¤¤ÁkmÛÍ [ÕÊ66ünë[êÇ*U¬…-Ãæœ8†-˜“Éš¼K³mÚH+Æœ”p)ŒHÀðMe /hJ:,RÖÅV{µŸ Ìù4x>‰dÄÊS£§Æg2ApK?¯"F­À+‘J`]m‚欶¬U*O¸½ƒà#m &d5íZ”t“ª¤¬”ù´U2O|dµp]â­Ê»„dÆhKÆÙ`ekd7œCÓj¡D¹¯J€¬”ãKuó@$àúNμCÕ%kW' Ê#vHž Ïß„‰ë+U_%x˜Þ`azÛ™Ò*êh­ÿJTÉ 38£mqzßXŠƒªVþ)­lé)[1”ÈZ¨µ•Mi PÇLÔ"u·6snù(¤  a<¬„OšÄ¦Ç w©¬-2œÕ<Í Ú‰jÓsHÃ(¥ŽÇœ9ýw ¤_P*³¤ÈÂNEæGÚ-=K£h“ ÃÐj«ZibÊâ Û—·ÕBIúü1‰ñÄ•XsdaLVazÌ@b©@<1ÿÊ1¹Y1”µ†Eþ40”^4ɬþgï„°—›^Ê繇m›'‘íq¿G–Uuÿó9W­P*Û¬lñÍlxä¬Tá­H³QJõËF ÆïégBÿB ªRü1Õ²µ%®c«,R‰X­TV’³¾º+Ï„>[J'•µ­» Ïö ÁpVµãh»ójmëh%S‚oU+2‰$ˆÿf3Ääè)`1cØÒb‘E:¾±«‚ŸÆJ#+ÕÚ­’a*t®ý¬ˆb(+ÁpËŸLÈ&0”’Rûòm¼)»XVdÜ2„1,¦ÖÖÌÎ9ÄÐ4R½Z1´Âœ›§™½ RÉ”4‰ÔÊe£P ;>åºTnfLÎÄ¢Wbbˆ›ÆØŠªè1áîªyœi]Ç4¶]#)ÑKðÇt? ¥D‘2§'B W®o¸ )ãUá­¶µ>Fßû>¸ïOš¬˜pRÊ'ÐWÈ*§RY)Lo›P “ÅXY%p¯ Y¶”RÎRB ÎÜ–8²¬©Œp^$Τ,¥·ÚŠs Ì"7µ•—M0|Μ•Ó;#²‘È`;8g }ùÃñ•)aÏŽ'#凗uÓ"5’­Š•ŒôëÉïç;±O=²À÷ÁÉÇðT([¹5`Ä%² ESñ¤i°&‰1 ž¬# +ä€Q+tÔZ• ´ö"dÖó•TŽ„ žŸI 2|ã‚ >â4j0Ù{áôdèf0[$±Z¸òd|náô¯¦rŒ„ÏA …Âa»ÌU¥i²~F‚¾vÝRj'’ÂäÙ<Ö¶l[@ ¬…޶€mg9ãs†•xFJdZÐ…°õ¨Eý”ÁV¯QÿþLT½ L†'ެA¾Çôû?2‰9 ®­”Hæ&Õû G¶âßm¿ør湦&Y>7…³­ÿÍm8RvÁŸU]”ÇϤ­,Ш$™³HÕ¿’.½9)]fcÓ›ï©û;ñ™d^ îz ±•ð~kXÉz.Me¥×%šÎK†¹É صĸؿýíoþkPbÙJ¬ú2t—åÙ@*×T(é ÙŠ‘RkK¯ “¾³ÔÅjB]Èt4ªÔª’‚1᜕xÝQ6%As¤•Æë Ã%­R—8LVñï6MÙÎUG«^&?wý¼Š”]š¬Ÿ a¤ÚÊ1¹¹£úÖ€‘›?}×bl[-¬0Míl›}õ(qÛ¬(ivX$‡®ÈÍà ÌÓúºI‰î0^-†³-ëéú½ÀpLOCßð»czCVSU€É™ç/ ¨ù`ÖƧDV$Ÿø˜ém½íN¡‹6^O¤k±¦WK@¦°#¸FSY ð{p”pCsdhT«’>_0¾cja +´ nc¦Œ¤I¦ˆO§kU!’aƒQJÙŠ[÷©Í>ó›Uåª"­Jà9œ³HÁù+uV…±b¬”JÊÂ.ÇÊÓ#8m¾O ˜Uå}#»U¾-Yå 5¶&TBÐT[‘džcÝAÌÐVÉôÉJ­6ómZà_r¸ñŽÁÐíáU_bkÊ×§SÐSr0§mùd@IDAT‹26q[)¼Ú,EÐÙ¯OövwÒš°"Âl)FÂ¥ŽânñªD å‹+´êB)à ["Ã+ì6l_·Ñ“’Ý dû„¡ÚÊ­¶™Ó}«À®È}v{ uIYw…E-Xu{H rd_’¬ð§ÖÜDÇi ½0›àà )e°”~I€1ýŸvyjT«•è•“aG#v.i`Kd¶VY‡BZ±r[¡^²k­¯ ˰-L¦$2gX!ebJL+>P‰­¨^¶R¢ò1ª0VA)€n€˜ƒïyz)&.`–BÎ!óôeaVôd²”xë@¤Ös£l†1•w3²x¡ªBÎcÈx+O©f°Æs‹—"ƒkgNQ¡goT2±9³²žï£Ú[³6‡ëc °ð3²bÊÅZ6 Œ§ákËPmñ°s~õR›• È“ H•,[¤^@âšú°á™k$è1>Wq‡GR+%¹­/‡ðd”4BÊj[_ÛÍÓ Ú­£4婼¯©Bâ.¡Úf`»I(‘‚‰•XI&°sc®äó–諼™e‰e1RòD0¥•Ào'~'öÐ}æ×EmUzÁžeS1¯ F4C«-ÿdÀ¶›™’9Ÿ0 5O3`ò$à“ÕŽ`Vë^y¿;·eˤT‚ Ü&Y¹ìkØü‚[zŽ_p+ÛUèKÐE5vVÄRV2ÑVaÿY7šRMž¡rãŬ©#2[€£¶ÚÒÄÓÀV13„‘u©Êú?r˜‡¡\ð4€qŸ5jZdåUYiÂ;Ž-,Ç÷FˆÏ;fGc‹Wbí2kT-%YPZ«­#åz• %¶ýœ“ŠÑ6‰U(·JŽHaþ §]˜Ø*ìŠ èÈ3=ÆV)±0s`žõÊÓJ/ p£ñ‘©„ ™y2üµÿµ`r6=±­l¹4•c~d+GR¦w:$Ü)¤ÔιIÍ¡¤ï™nCI/<0=`ӊɶkÉjz©NÄi ³´Å˜¤À76+ÀWŸIvÚáϪ@-’›­”U´µ¾@UGs®4+Ô–Í-ÿÊsÀü%1œ¾ežgW‡á »Ø;×Y¸!eõ­„žg­kÔ¨#KÙþ?üRɬBakiu„F’zÛÉâ×y«í¼™'(ëø¶Ä€Cñ?f°Õ"Ù ‘žo÷¦¶|7“>Y«*-ðLDíÚZÓø¥¨Ö=‘:Ji¡“Æ*Õf’(i6kÿA)k/Œv Á0ñ¶R<ÇÀNÔÀ›‡9$H\aÃà&èSYIß]RbŒòpkCælU‚¬"qåHÖ+°å#à4Ö©=2¸r2Ùj+ÉÄJ€/•C)Lµ®¨î¶"Ÿôø€UÈú0ŸV‡ÊYJ Ã|àî®D­@Z«¢Lcuiý­v˜¾OeT¢ªs3’¾¶uìP4ù#M^Š/<Ù^$âfèai}¾‰¼XÚËõÔõøÊÌ¡¥•QÅVÖ1Húz[‘j1ÞE©ÚàÒd7)åÌ F^ÕY0Vë̳’ÊDJybÊĶÂdÀÚb`ÃãÉ:Eà”ݾ)­²]V[»+<-l›8})<½ió§Qk[wJ¶ÓÓ¬ ¨6& F/µHbX9° “²Ò$ëaÕ×Ú“%À» …ô” \fØO±è?µ›r€"ŸšÂÙAJ›9çxŒ¾ü9wQaï¡TLz¸ZæÝ‡uï,Lj h( #˜s³åV¹îÞmšù„+4ydš òäßÑz”:Ö”-¸ÍŸ8½¾Áð}Ž”µ°²ª ‡djF ’À&¶:Š×‡ÉZÀd­·â”TÈþøç?ÿ™W‡oÊè@%ÒJÍ£¼Ì”L–C—%[ À‚œç¶«Ì _/>0±µ^R–_Š /†õY¢±¥‘‚s“…E×d 첊ÑNV\ïóeD֢֜¸Ù^×3m8ò=KÒÐ7R—Æ‹´V%›8so ¥Ó)"aµ,ð"V"þæÏVîaù³`¿X÷—U­áj;»m>DÊ­RñiÜCgI!7MadCöjj;¸^¢« „‰V•aµ<ò øàÏ )e»7bÙÖ.$PIk¼¾Gú ùð8®!{ÜÝg³áFp€y 3øRèN”wX¤Ð޲{£ Nåeš‚.ÅÇ`H©†ÁÌ0O†Ä‘p‚|` Ž&áœ8fM•S”uu<ÓI©œkDÐÙÛ²¢Ì–JĺÈJLà.A6Ux«­rØJptj<²¾o LJ«èµq«mÓWëàüE½p2xn_Õo½>ß 3™˜‰°Ý9[‘¥´è\Ûj‡QbHÏ¢ŽÑ÷ûªF²¢ò:4¼ÚÞ4¾y$1À+ìÔ€àœCGnEV(·ºCåôÕ*y«ò±ãSª§8/ÓˆKž» uTÀ?“R6ýĶ©Šï½µùKógÎYa†V©ZI™[ ðÌcX#ßb çOHùÜZ#­ÈU9Œ²mâªð¬nþ,R¢F‰WHc<óÍöÖvÌ|fK®µ¬mQ .•\#-¤¬¶)å½n@»4xUĵ&vº®ï×Ù É0V§ä€iŠî3fY[!kÕ‘Fð‘dœ¥˜èŽGJáÉê^ëÈ|ð"CJÃdÀjUõmD¹^R¶5R^kH8Œ‰¤ ·6' „‰¶V­mfh’l½–4ÕêE&å3!.Ø^3ƒãÀÊ}jŽãóNâ;‹¬`Eï\4x«ÚþDQUš P ¤*äË×_!ÐevF[µ•’ÉVb+ÎX×?ÃÄ0’À¨4ªl¥€nF4€,È"­ ‚æ±äV£—ÉÞvU M¿B¸1ÞKRª#4|SÑæÊ¶Õ“¿ÂP›MgWÓè%¼˜Ì9À&$àl üXë‚4VµJŠë}`Þa•ÐPfEözn[_)3W{zܶ:Eíèk×Ñlñp>Êe ð^ѵùXb±Ž0ÒÖš8‰‘Ú…TåD¯^38…±3oM£67²æÇ˜Ù¶sÑp°¨Ì¡*ÌFU;Lðöªãèž®TÝa½úÙ4&½T§¤ªÂÔÝêµ1LÙœe{ ¦,ÒœdÎ21&O÷㫾ï"ÙÎÈàÉ¡kÁðu—"Ž´†!•Ì ›ç”ݶæ;™ã¼ý¤&HÃc2¨’ÅÇØõ2UVpÓ:Køôû~—¾nó!#¦Áð?C\+[n§om{¦¼ót·HÁØf˜ÃÆpL$ÍÚÝ??zúøwQ ›œ§1»—¶ª&7jb¶d]H)å¬t lmb)bÛRJÂs£‰l`ëÆ£tRÛÕ²b(Òà5Ub$bÙ¶ ÒÍ€¬K2%mãiq¶4ÙxØß(TÒ» H)£F1J€ Çhänë‹´Õ«­“&kæFJ µ¦Ž,ÖZaíæVaM­ÍßðÊé+ßßl-¥œ§ ÃæÁ)i˜m‚FM/«\ÖÑ[3—¢7ª³dn=/¿ä^¿¼ÔÓ1íEÔ¬2.9f‡WÕª½TßSªðL8P&€™ØRÊ:-¾”m†@‘&¨“¨ÊðZ$(¥Eå¶;TgÄT`LbK“‰m¤¬È“U&Ro}›_ã=Z¼lŸs©&Ì¡•à¼áÉÛ Ÿ îü¬¼”d™#öÍOÌGT.›@! éZ¤jħçBP;©4¬v„f0j&)P•ÔȤ•FÀª*ÌÄ*<ñÜtñíŸ>C ÚÊaâÊ ýôJf`ÏŠn~-4…‘W¡l-0ô¶ LFõ0qå9›Ao¸TƒiÑ‹²»î&  \‰¤ÈDX˜þIÁ;áÕ~ÆË<½gÁ\‰µ£Uh%Pe0í ãKñ7|]L%ÈZÄdí¬!»C)-|+¯‘µÃö#„F­h© €)˜mÁŠÀª]Ê4«Z/úÆÓˆ˜LªûémQBcµ•¥q3˜}ûKÑczÊd¬¶ /¥Š¾Ó1)²¥iÛnFÖëQU½0dÖÁ}]èSÓÚYu'æ`ÑéJÙ7ó Ò0U-›†^ʪ£v¾¾”mYèE Ør«°¥”šG-l•͇ jTÏ'œ-FÄl˜|¬˜Î´UÅYk<¦µŽkͲ› Ã+§¤Y×%«²°vJDüÖômÃ<+q“4§mÇÜTuÏy™Pš¶©Ü[µÉ £;†Àë„$k©ZÞ[VpWAƒ!H“À™ç“§lÇIcÅ#õe«‹èËŠÌçO Ø£ï)¬<ó¶­Í™Ì ßT °Säÿ¦è;ˆ”ZûóOæÁqÝ;Z_阙Ðçb"`Jµp…< ü˜ð)¹üÓØJUˆáiÛYà ñbÛ®­î¶†É­rd7†¤$y†3ën«0e)†õRE#XÁœ l‰á<› Gjﮈ d¥šŽl¼¶ô¢9‡¥ÔŠ—/; +¸u©ôHa +0ƒƒ+o*-fr‹>?, ÐÌwгde壄€3 4pæžEwk•¥¦4¦9­xUž‰mkVÝjcWÂDp Rx ý¬2”U.•Fötõ!Wâx\L øèÊæŽÍ lezŒ¾§RÛ+’ FÊ]ÖmfK ª«‘5†,²ãI‘EZmÓÀª*ÇÛV(¥œƒm3Lƒ‘µúnZJ¡ªm#q”d˜²íJ-O2 r Ûž:ŒËæ3gßS¡l3Ô‘Cch‡Åµ<žkwÛýäi%³Ö(LÌÓ)Tä@àKÊY˜Ô±?¹öJ(If¤¦j­\Ê¶ŽµcU‹hà4 ð9ØÊÂÞ}rCºáFEÊŠL”Ê oTãõÂÈÖ‘èh9g‹õm0ëbÔÎÙ0ÃîÄ¿)a7£*™­Üß®Ðnf…ëHÎpo 8ižéµÀ“)oÀZv·-j´I²ª¼î·çç× n¸î”`€ÞÚlH`}“Y1‡^¶+WÕY2omÂwUU/ ‡Õ–ž ™¸™[Éh:¦î=ˆÄx…e=,Ø•æ7gά¸UÉÌ à>βñ|Z j‘5É_çLl¶¿:(‘ÅËg…äÖ3퀬ֵµHf$©‚gÛRµPU‰*Ñú¼à)TâÒ~|ÆÓ+$¨ ƶϬ ~Ó¦D2ÏÙJ`»!ià¦Í S Ýÿô‘‰'òt]ô+U‹æÄÔnkí¬½ æÏÓ¨&AîLvjb$F÷:ª]#€€¬TSýè®Pw‚ Sn­E¬Öš ²SW»'ˆŒ±* ©¤#Xièyж®ºWnMßa æ¢ì°ÃÆCÖÈ<¥4’j$·‚RÊŠô²ÑÀ9ZçÙoÊœ]£Ö ¦ŠUb¸©l Z‰u”²-h„9ûâ%X–q×¢£­.Öœ*ÄFú°ôUS;$1LimfJ`&P"ë•-&e«¬à“LfÍ$.¥²ª‰Î=—¥ò$v^¸Kè•èb•H¥O†oÚZ°UX2cà³²…Eå¬ÈlÓ[Kµæ \ÌG¯LdaƒÉÒ(›¸*ø†^øúV[÷õbß0xÓ"ýÖØ%V·!ˆÓ×.ÿÜbŒjNAŒïÆXñ_aúl‘"Eó`cÊéEb$FÜ¢so˜c;eš­i~ýcÐ×¢·“‚…éÅ–]¦¥Z‘j tàŒq`%Õ&°b”†ÓËïIuTKLÐè0R4P­rÁ™¬I(»k[AÖí+”Š TNfµÅg¨‘-~þ¶‚¬Á¤q>R"RG)«î§3Ð`*¡áƒ±z“}Æ×½×»_†¸U« °å¶•¾Fåß–ÒÖj«…(eËAÊ*ðjØbhO$Y<âmŒ•Æy¼*åd°¨/rg¯J#ÙÜ”ËιZ²”¶Ãúæl{û«md[ë Úþ¨íz3i$ÃdR„ã¨r„ ™0líÙ»®ºt^|‰©Eä …Œ©Žy{õ úÉ®°SÖ41 ð´þÀ?+©¾=R6MJÛÆŽGVB0¹Úµ¨Äj;L)Ú6¶r‹¿ùÏoDRæL\6+¸F™ °ÝÍÈ6€r)¼mO °Ö·Úôn’ rëÛ¦©©Úa€RdH°ãÔ]¡,Y Ob™3|º«15žŠí~°õȽӆ­ÄùæË &îbÕ •¸AÏišÍçGß–ü#*̶Ã5e«D9ÐÄaÛWŸIU¥dß9ašLrðÓ·Qý ζ'r-•×¥r…5r2Ø¡¤`)'R輯›ò”J¬”ݘr|nÄ¢FsË¿Bµøëô±n¤ZÄ…TU:jäà˜žކÁ¶~$Àû^ ƒ¥ÜØÄü1dëC€¶õôKYžæqcÝs7&+¥¶Âkóùé‹©5@CÉ91¾£5¶­0Û¬²EbTm†—/›yØ„Äî®*´f«‘Z)Ê‚RJ‰ã8”’~¬:‚*Á¹¾ÖȶvŒ*>b…•󯑭ÃvÞ¬8‹ég»FR°BÆø+±Mlx+(ò¤lÛ¶†Á4ƒ10O¤’@>ÙÖHv[XUþH€æG£ª¤š*™&s½]ˆ¾ÈœgeªxϨGS «-™àcÔ|bLÕ¶’Ž D¶ñªU§è\Ž”tϰÐ.åÔð½0ïT”¬Z«ª]ƒÍ°$MŸMæÍ‰ìh1‘d",«\ ÃVVáíð|Ä5ø<Á0 ¾×€`ÛœùT ¬š6rd…±Vò?Ë¥øÓd¢Ë«¼9oT)X”5-ÆÞ $C<dƒuä†!“"‹¬K)¸P~ÜŸÀoþ¦i¶Z9ËŠÜØ™EÆ$ƒ‘ m›¿ÉËšV»4d°€¬”Óu–¾¯tÁ#i¬ŒüÛv-É6Pð†Bú^EžL6¡eó¨µÍ À烶Èjmi™X¯ðó¶ËêkUbÍöýã;T ÿJl)ËæÀ\Š e2Û—WRV!ü6¥´>œ†~æµFÒˆ GZ…Âj³ÅPf7ÒÑ=ß3Jr§ÌIp¯Šîý½’~SbÐð$^ȤɇñMØ;=`Kiå `ȪCå‰fÛ/ÙÚæ`+ÔmKµæ >Vµ"ÏŽ©¶‡"Ë!ЇE^9%’ƒr×"›3,`+ý>wd‡Tž¦v9×´ÓØ”ÃÍZ9RêuXI¤íÛe$À­ÔçÄÆõAí¨|;€6¤¶Ö0Ç¢Æ[e•SYwo³xb²VY¯šŸâ¢_˜ü=ƒdRëU£oó_3ð±I(YU[÷娑dEWiUŽ1§èi™é3 ›„ ?Rʲ¢Äl ˜þN}Z'àÖ ×‚¸§m}ÒpPR˜¤ah¤D‡úæÏ_«mßV @ÞÚ1ÏÙÌÑÕƒ÷&õ2u€€U±~D“ 4V 8ÔO‡±ºúÞ0)|«Ãûïõ£Ý‚ ê¸TŒµóo«%™k²võ€ØÌpO¥r[]ôíO–®Â6R Û`›!¦;á Õ³é·aUÚa &s4…¥`ÁÁ¶ÛÐEÀ JåY+“°m}+·eÒxyÂ]…”°]m¶ø4˜‰a)Ûž,ŒÑÌ×ìTe‚Oßù }}¥D©˜zÅOFŒéê;€¦•r3`´³ X&ðì¤0 W‚á#”[)©6G¶"èû¡õrºâ;“'óJ¬°ìd@¸.8A’ )[sÊ·Ò6=@ÖVá<1ÜÜO¥z¥¯ñǼ¬ÍÛBí¥(KqvÌaEÀ¿×ÞgǓŧﰲ˜ú*¤‡‘4ñ֑À S°òDò'V‹— çf¥$ëÅð—5a/›ì;¥¬±­Fº ¼ãsДî d)9Ó[ñ©ÐÖÚT²õBʺ(_A¨]]žÌ•lžÀ6†½“ÖÝV—Zð虜Ä]±Tc´b6sŸ÷«)çÙÚâsS;fð—ÕTÖ*KŒ´íD0¾È<%RV`6°-ÆÚœ9¢WÈ'ÃxµÂyûÂGÂl)kákÝ$j;µª 4ùŒ§OP» ÉØr¥læk­eþ¨y×΂áÌM,Û ñl)“áÀ,Ò›æ#(ï£a†>¼”݃µBVÓÉ!åÙ¾ Íþœm{-s¶p+7-zçt]Ì+Ï[ñó#‰lÂ4|”ïBæßUФˆ­fã ‹Ûp'Í“ l¥!&³ŠšÚ^§Ï÷U¤•Àœ7†?C Zc½¥È.ªÙ”ä <ýÛ&Là¶ôm™¡Y_8+Ø€éÛô2¸:¼*ÎÉ&ÀË )‘³^pþ‰;½m˜À³Å7d-¬/8[ Ðx‹TñqW€T3õ%*·ÂRÇîkÈ$AŸ_˜UÙNa›FaµÍÖÌ=£Ž@àÍQîåa%˜ä e«ŠØ€ÀÝsK”J¸u™ô”d@C¢a¬ hbÊæ ËÂRb q$€ÑŽžFëÏmv}~—•ÆÖ5##’*®>¯R”ÙÙš¸¸ã‰WU³n™Œ¡çê§Z—Xk÷ˆÇ(´ªÝ /Èj+¥àÐ]”ª†a»ß+a[Ø®µOP&ªéñÍÐæ)˜èeë)Ã+|ÅyøžI`UkU $Pòv¬µÕÑ6F-ÚÆ7 ¾ŽÖ¡Ú&oT3tQÕö¡&PnEš‡FØÆRH¹%2«äcÍ¡›Ôw@­-%†y#Y黲ê*LåA g^Ó”ÍÃ$sÓ†µÈÙJiUEÓ:MçÒ…s© á¶R=[â&$`ÌVSd½¡J6’Ñ,ʲê€me•W‹©i)ÀHeóÁÐÃx++ ¬ÜVÖç“LVH僴ÍYU—€·§àœÆ°–U³ê¤¶EÙ>ò< ÞkÁØ*‰'vE|zÂHt@c”SjÔ$ï`)i šUaàµÆv"Yš¶jmá0ÙÂ"l%¬¬]û%Îs!kZY)Û *ij]-¬j7°.MNVŠ HV@'m»S˜dÙHb¤­ðŒà Y²”m¯ö¼0€Ïh˜ñMe 6M)û%Î_oÅçíb[Þ¥‰•Ù&0O|2©ct£òæ¤OYjd¼O™ØŠôji^^Ê6AøÝzˆ#jÔ¢µ-œ¬—d¤§PGÎæùQH,‹¯/¬0?à´ƒ‘oU%ñ†ÇÔÀ þ9Ü|TKÕ‚íœñZ¹UX+‚4Uá‰Ãeé s§Àç›Wc?`‰*»†gâ1ȶÀ¬U›@íLRzï½µ¢«§X鎴0·ú®{©‘¶; /YX#ÙÍÉÊ +,KÖðm 8Ð4mWOS!ЙØ  j“ÔQ Áº'noUu²˜ZOi¿i˜ýÙXa÷#¥©¬I˜ô«¿ù£|²iÑTªj§Ö´È~§×‚RŠyJ[â40[%¾£‘m§Ö.[[µ¦`˜žyJµ4kÑå#Ud ¾ç™J5 œ`o)«< ÌÐw/€t.÷_ ·šÖÎJPàÓgE)Ëg[ œE¶y¬«"ÀÛ–‚±QµPÛ?ÛðÄø°mçÊÉîÒ¤à”æá ž bšP(¤j„¡ ã+´…­‚¿2™žƒŽ5•mª”R^#U=”ãøý t42¯™[GÀs£‡1xQ­l ÐéŒA¦‹UUC¶°¢ôò“mÎÄÖA„yVµR]²ÕHSe«Là¥jxúfNùžH éS‰„Õf¨|MÕ†G )…Y¹’˜j'•2¦‘4µ­õΕ¼}my*Œ$€ÙZ;ÆYšf‘Ÿ³-'í/RVTÀSò$[_p+~ÝÒdLJ¥÷Pl»d -@oÕBJÀFRŸ,‡$6˜S#ç#e˧µ1fXy+R¤Œ#m9ÛjúZ¥oBÔ”²ªÊ».ϧ-@\!1²ù3´J2Ì­Õéð“ôÉ"“åÀ³±¥!«ÊVŠÆg!œEåý@ICÆ´zj•ØJJ±U¨ŠÆ67+œ½* ˜€÷î•­fxUŸ_BT%°Â‚’ À /Fv3˜@2Û@÷cÔ~¾ÑTvø¨ÆÊ®¡ßõíJ³ëÓ€L­UÊŽ©Öv†HÙ¶°wN)´®ÄÄÕ>`] e§­pµme‚n SÛâ»,L§Û…b”ZÛŠ•+^aׂ/Õœ” ù ;‚¾˜Ä²*¨#¼ñÒ`vëå£;FÐ(Gr«¯,¤¬ÎpßßÒ¿ëëPR9·Ãç¥\I@/[õ ·µx ¬Vñ̽–xÓn`d†‰a̧•©ð&Ï ñJÄ‹ búWøƒÿduou ¿. ßænÿóìÂV‚Z(a⇮lo”*‚š&³%ÆTbUÕ)¬pâºÔ‚g/OÇ!°=ã~·«*/ `_Cù¬EÖ:êÞT¯, ¦îµ³öÔ*,ËÖa­&ÉÇyÌLrÖ(Ð$Ý ÆïД3‘¥äFPÐ`ÀÜïX€ÙNj°.Y­PkNš¶ 4€*½%[χÃÆÔÅš h˜jÛ6L8+µŒyd·•Bjd-ªµ"{¬õa’O³)ÇOÀ\‰TY†ÞÒ4HŒíº4’,gVÖôÄniS5j‰)• +) -Xy@– ¿›)ØŠR¹*$Ü#S…Ä4Iæ§ìþñ`)†”¬x­æì6ðÄA•U‰UßÒb|}mxVÎ^ÕÕ~ÞRšŽfÙÆ H¼Ô;À45µ[udkH€Àc„-¶1ª?àÁ.,'òùògfó$¶ôh8d›^ªñêk»hú”mÉš­y¬}íøˆÁjÍÃ?P/¼hB@Š•”@R´½Â£z%¸ %¥€aU¹+MΛ-Ù;ù4H%ô1M›¿UV˜‡?·‹!½”µ—¤kŸ±n(ñWåYd1𲘬tÉIPaÛ0%°rÛÂ$ôßÝçë%ç áf¦‘…-P;˜ s‘hΆyÉ«ú|™p`^Ö*6Œg'ëhÈüm«µ-0@-ÊZ{”ª:Z…•œß£¥le‰ÝaŸM™¬V ”UÎiTÛªdÅiö}W©"ìŒÄà€™OYë€rbí€ÄRš¶Öb×¥¤Â¦…9 m™üùçŸ>ð\Ú;L=€¦”¢€z«ÐÀжU±ƒ]"™Ó–ÃÈd•×SwúÎÐçĶF3×½ÂziÇÜÊ¡vV‘a`3°ºÉÏõÁlÕ6›5O«Ôë_áÆV7@™`[m€¹ZÎ]ézQ )Œã(k ¤ï®¬˜4ª”[å9Øj'XÁ4eîû¡å@œ!²7P[wk˜²Ž¶°[øÌý}Ê}%§Ó·WbÙŠg[ÓÀÊóEUÖk|Rĵ8§}>ég˜&}ïRÎ5ª0qÊ­š&ƸbW¨Q…ÍFóFY e|ßÝxŒI|:úUR–C2-ºa2z«,rn1•à÷óÞœ²ÜqiÚ@¼³Àjµ¾Àl m+çv|¯3½­ TÎ\uV¶ ¾í@Û”Üð½uµÎM­ Ivz|C¹ÁT©U7X¶V©"«í²llÕ*dÎÁêø"™m%æ‘Jš³F¶aJ eµõÍÀe4@Vš2ÄÓãéX¡mg$ c.®ê4%#¹I¬(‘9Ã^¶Ù'wc²îA¹çŒÙ<¬»(†»7µ¶²ô…­¨0±^Õx(þ›µ¶Ì…BJzJYXDr.lÌÖ€T²zÁ˜LضÅèå·m+R!šZsØz3g¡ñ@U€\È25…eýBß0ýê/eÛG (³ÔæOV9FÈjT¶uÛÄ+´mZ ñòŸ'¥ai OPÉ. _S¤ ·"×÷T~Ž$NÖNÇŠ³8ÓÿÄnÛëäËP91°Â+¸^V&#sF4F}òޢjµCR&¶b*7˜` ÿôHŒŽ¶‚•p3ù[4,;qVH½à4ÃmÇ“YyY«¨OLCùòa«¬H./Oƒé8pž oëÖ€“º“0~>†iž©æ·yâu¤äcÕqV›snöûªà1`ÒV ·Ÿ`ÝÉ8X›ª÷Ö¶P5 e…ybª2y&­²Õ‘F  L)Uùcd‹q埅’Þ¸Þ·™ Ï™‰¾Vçßi€I‰€ëùëeŠù1Y^Jvµ<=†ÆÅ§±m´€±R"áþǪàúÖî]ãûl‡­ZÓ$c¥ÎxY c6Ãd·âóµÒyRVØÌ•,›@!¾ÓZ³r[רŠ™_S+=>ÿa%RVUÄuIƲRÂ6ÿׂ$°*O\ÓxÑMexµ¶€¾Jd­‚²’•‚ï•%>5‰Ð›çÕʲ-j' „eµkxø}=”ä“úHLd£ÂÎ µ0Æ6ƶ'èZz.>? ³B]`¡¤›ά߿WªÇáCy“Ÿ&0Ãj½*ü9P&{ÇÛé /kË­G¦ €¯E÷CÀV ýÿêüwcšÙÊÇ$õÝÍ(db$0s[%%Å5åûû¶d½K¬®äó×]9[>ôu¹ó~¾’ÈŒ$h¬¶€•Ò*͉ñ¤8¼[Êx2éÚa¼9¿©Ú½%÷Ömàú.¤#3)”Ë ãìM¨j³¥áPÐ[vÛ•ËrP(Ká#)‘‚)òÇÀÈœsCÚXô\Œ¡I`¥©6L£OqÏ.í4»í¬u! ¬œs²€ŒpU;=¾`‘asrVØ ©V‹”°H¦¬š¿ç¶¾Ú„‰mÕV X9·&7AsvaJ<¦zn®0mÕÂ^¤nLyæ¹É’Ä;~ AGÎç]ñVaf)ÀÊ­£q³¥éZ¬fÀÐtÉuôǤ²¶¢“ h¤ÖTd½áȶÌáÊën©Mo¼øùð}dùtQ)×Àˆ¬º+퀵ãæQ[$.•Ì7OUR”|ÒÔÂm ’ I P4!Þ*KÓÊŠ+üüïL`VÆ Xñ+©i>¡µBëf:2À­BVôøüáDšÖf³*7ƒ3{ʹÙVµŽ¶¯ œƒU–ÓšÉ+V«‹Ð¢•RU†Í£ûxï˜mc”ïkJß ²È4¯£w»ÚRuߨÊD %¾ªª2•L×…¯Q³)$“Ê'óÆð¸ãéÊ YÁ?4ÊX×I&°ŽMÅŒßRüýïGù.ðû·‹èºs—rWÌ«xh6YÖ²UUnÛ±mà 5jâ&³åœÌJf›-,”ˆlM8 OóFø´{xuT(è«¥(ÇÓ\³ÏÒ‰Ú4̲IJ5…|*±R–5¿Tó ¤0=9J¸Kïì¶dV©Ùvù€ßK¬u*tR_$æÃà‘ˆ)¥<²{0Rϧl+’Un;Øš #à3Ó¥€1p² ×ÿ>¼p‚RynHØ)ÌÜÏ3·ä¡§á,5gbU®ZxA³aºdŒ#fÐ+—ºÕGy&»ÎÖÈK|¾ÓQ6,Oˆ ÛÂ+äcëÈê’lœ=ËQµÁZóÇÛZ‰û†XpÀ[‹²îÙ7`&kšm>]N&ÊÕâm²”ÊÉ`£|y !3,«¤.¶šv3™ 1e´ÍC&”(ì ‘ÍpÏôù2¥ðF<ù$è\u—J–¾Säiæ¦ÍÜv<œ> yLŽL¬EGS‰„ß}Ícøem}‘þûßÿö÷ :ÁÄH+U” 7l¶pÙpdØZœMÒ˜&ÑB î¤V±­Wdåd37úŠÊɲµm ªÖ¶ ÒÀ=¦jÉðEƒYû¤·%ÐBÐ4j²N„!†ñ~¦¼o,FGb$™-Ð])©jz]ò_ßôRV[‘OcÛ*áH½núÊšï•Ê*·JȇNš³Um˜LJ—ÈwŒÔ«±í½iúÊ6@ ‡ø ú‹×-ÆšÌJÙ$KjÚ´iˆ]» fh 2d7N# ¸µcliˆ70 ˆsh6s«;džHØ$Ȱ’sŸ˜3ßï_¤²iò¡¡ì»âZø¬Ieûù7€ÿõ¯ùq(]ËŒlÙÑÙ†•ÁUÂ5ÃÌ.†IVN¢+†&™r2)¼—LÖð˜ª*±ÖÔŠïîL„FHž‚ÀÙú—«ðµNCÐ zI)Ás¨Qn ÖÉ*×þŒ©5àƒÑPØ05­D-ÎçøÞ‹5!¶6‰{° óäÏíY*¶x[¸¯Q)[dþ›dO¡vø ÐxkhUµ-0\yÌHMk÷‚ÚÑè7ØJñ;ldVªUnØaÓXýØö£ “lëZݺ)wëD»LYÑH ÙfØ])DvÉÖÅ–›À¨ÚªÜœÇôž·vü)a2<\Gbµ¥T9)ž¦,%ŒLŒÀÐ$³õ!·Ú2áf`k¯„¸© €L°Caðd40ÒœmÏIîß"E&+¤Ö0,Ì f‹5‚ñ”J<8â0¾±Ôš²­i«²€9_î¼G€ÙåK)´•jgAjÚÇ/:`†ô€US‘ídUÉbø$PÞ®Qµ²@“¼`U¹±Rˆtinïô¾§VÒŸRl³¢xa «Ô&,õ_¾î&I²ÜHÖè †$wÉ ÿJȽs&ÕòL¤A…ššš÷ºGdV‘M‰”²êNc ‘¶ï–2”r?V&é3±bÒWbyµ§€­R"ßÉaôšI ú5õp+,•[c`ÔbÔšY—”â^°¥ÁÏP9LOdeíÉ"iT™0M­WŽ\Wµ”|xâa$I¤8Pæ@ÓÇ­7ÓVw)€FUÃÏ*gkoN³³¬|§àiWª‘û=@Éæ@îëûà0°I¬9Xc"ÕrÀPÂú ¸­•!FJ\úÜLzV1¬iÌi[–8Ì|€ôÿÿ•¥h»•3Ã`jg€Þ Ön£ñª¢O0 z)·ÑTm­¢.d]@)Ù¾Äl+dH6M/YåÇîJÀæW›ÌÊÄ$MÎiýÖy`d2 ­UUå4²Â—s…ð`€ÄKåsÊ®Ø;W³áµhr-„ù ©—T_z¬d­J¼è œ Íð”‰5ňæ±V‹Y ¦0‘Ö”VK&®äV¸Z3°Å0™ƒWXGn4k‡gbkå È–F­l$†€a—@c+»£qHI0 ÖVnµFÂZæýŒI€—óºèX¦iÛ6aU1Õ61²^å‹ë›&gÙúZÅÌY‰j)E]"[çVUFkáÜGT ’ÏûY#)[2V7ókžd¬RÖ1 ñíy–ÊëNC/»á÷ºIò¡ñÄ­ôf0+…•sVB¼Q+Œ¤©5€/š„mâ4H¯œ&sÁÙ”íÇôûɪÄú–ØÒcÜvžŒ•Јc ['9k'V.kíÈ{c‘ ¼#0ø¨U"ð m[¹‰˜”kj¼î°2`gçÖÆH‰×nkÕ}…¶aå dÕ2¼çû=}ÛÄÑo½k¤¼kTÛž¥ª<áæ¬WߟÇë«Éßš`íTÁ›JÖ֓ұǟÆêî{Žæ é –ð˜;¶>³@ƒµ:#ŸÚah„ó^ãÏ‚'¨Ð…“eÎŽhz7Cï£Ú`RkàÉGap34[+~By†”çÙÙèÔˆÖs”ï·°J8kv§É÷+²ÆôÆWEÆÍ8ö±»a«=O%°+ȩΠÏðôû¾‰k×Ì)­H¶ûraž[%VJž½,ñ U¸×÷v>²ÆC†_=F`TÅwR†Ep^A`Û 0ÞÖñµK&%`èÛåð¯P¸ªØ pz@w^[µ'"Ãb~â‘Ã1Ö7ÊZ‹†¬õ<ée#W‹i˜˜¶ÍÙÀø•8Z‡JlxQG7 îý}qâdp÷I)L4BJÙvŸV Á&©|zbYµ”V_VRVJ@H‘ÑäGz èa¼ç«d†1”˜ª|R`QùlU -¤¬…o=¶ù«ê}hÔÈë÷ëoß3§üÚÏH3)$09íŽ ‹‘g {ŸžŽEV&éPJLˆ1p  „meU%F*1I3ØÊÚÖTGÀuÑH©âOÀGª'ÛAh”“Ù6@2ŒTLUH¸ÈFò02ÞVm4Mc-¤¬”†•gb 2´mþ›ù|YUÞÕzýº"©Æ`Ò— Ö‘€Œ>ŸÉhRÖ:+Y¼ƒH¹X¤I0x†¶RÛJ¤<}Œ,’C%²RøLJ¥!0*Û²ª”Ãm•íh\ ̪ùÕV^•^;q-Ïm0ÉÜ%ô€Ϫ¬µvVå4œ?Íȹ™î/ léó1lÍM-\9ÃæQ˜áÜš_U_*˜­UV-l] Ï0’^``ÿ†}‘°HÙ0¾1(݉µùë‚¡§4Ímæ˜7(·¥´}™Rj )¾SÓïDÙNÄXV(ol8­ ±µâ‰Å|š!Þé¯ê#+[I|+þÚ~_GÒÔÂÊ “¿­pÕ1)7ƒF–ÆÛŠî$ÒË9Cï¼° ¶5L[«í† §±æ 7†Çª*l¯‡5ÊÄü (u¯iš ¹uÄYY)½Wd²}vñ™KÑ´VÈ_ Ü0 ënËßV¬cš xʺ+-ôVþH *«l&p‡jòþd … m}»º`¬Yi7¾OVYüBù Q4•ÃÒTƒ’ ¾9dØØMcmÚ¶R€ò4R¶Uñ ¬„ì·¿þõ¯¤®Òyõ*®,w2`×ú•ª„!+÷•°…­œÓhçäÌÛvËœ¯}>Ê‘iÔ…)mÅ)»17àËZúª|„ó’z5Œ¯µÎ.‹„ó‘áÆJªB<7 Fù(lþw %²È…ÛòÒÀ¦‡œ•lU¥ˆ'ëΩîõæI°!1Lüö–?çJrãS//ƒw©ÒmØÊŠäl$‚ÈÌuÏP—Zc¤D&)€OYŠJ¤69¦½÷ÙJv@oò¬¬_ïóø8“ÕšH†ÔÅ ÐG–µ µÍ/eKcÍA €1áKâ…k7­[åßlɺ7ÙŽ ½- ‘5Ûm;x‚WI–¸u[ž œ¼”DSí¶1µ ÞÖÔA¤š¹ïÛÙL¤¬¯­­T±a:²f$€OÙ%¤qGöV|>)ßû•—µÒ “[V•»|!oKV;ü)þ2Ha[y²˜‚wWõ9lÙÊ6~&¦l•ºzѳðZY¯«M+[kA#•§*A¦JV*¬ˆè{uçP–P¥U¸C7f‹çHÃ!Á½éóèØbdÉÜ liúòôR!¨JfÕ+LFa[Á¶’†ÁØJÒÛ ‰QHl+¤DV¶eÕ®|z€2>óq)µN `‚ðœëeKÜÿ÷¡1¾h”;²»êrðœùûEÑ*d)]T˜ÐWtÛúƯi|úæï‘ÁR ©0ýaþñdê³-íÿ9)@”µÕ(˜Ûýܦ!0¶•#E¾HÏŠ²/d¯¬C‚Æù†SÞd]UüéO²RöÅJÐ$}ÂaQ••7«Ö•X19PJYݯ„RTHŒéÒ3‘Ú#§ÊoÅy LòÁÔÈAh"3·b¬%‡d•ÄX ¬úf°v-Ê©¶@ŠªjÇM`l}ð0øøç¿ 9øfI–9ý†…l“XE[ Ã]Ë|تÜ*"þöç… ã™›v² z@¦%µ–UbZFèKǶoœZHÕˆ^ VË 67k) %å^¹ž¾ìë–-F6Ì#œ+O|k§ŠyM}Öê"%(Ên[ßëwîÊ–­,°-æÉ€O€÷?e-ðj­¶ÀHU×ï,HkÃÝæ†¤„ý®)ÕÙJj]­•̧¾FÒ÷VËÂLŒJ ‰µypW[¶V[Á¿!)g‚ñXmùãi„¼™2À„&+gì›7F‰B8åµùø°Ê°rXT%…l‹™ì§ Ôš† V‚ÉÁ[gζŽÃÇ躩B ÉA‰•lW*…‰t ·­W÷/Õç…¾ï|}1dRœµ0sÓ€¨¯Âð{dU¶Z°êƒs+>‹BÙ.ÄTza2é‰ÏªêcÍ¢oƒ|0LVÞ%ÄXZ;ˆÖÆž[wEidM‘d‰éº[ÊxMé½-ÄN ‚à5WBO¼ÓÁd5r zÛ[n£¶.ÖÐH²¥`­¥6€.0¾î‰éiά·o[‚?ÿùÏž¾¶²žþUñ’YgÂ9sš²l'›òǨ¶s0ÙaÒ¿UÃd)ux ƒôÔ²û$.DÖÀ³"ÀXÅÈÌm‘ùWÆ/®0~µi¬»X6aÜsþ»äÞ )Œ±ÍŸóî²H&Üàü1ñ o‡O—Fêi¢z”ˆ¶K)ôå £ŸHÁ&e/$üΣ¤¦Fk¤€•Þª<½•³Ï`L¶Þ´}ñÚæSk…"e ©8Ôb[úJb¶­ÊvøyÁ¡Qi“ì&?‹²«šmJÛR1Ö.¹¦:¾%Zh×¥ÁRÄ¦Ä ØïÞ Ü§²ñ:2s)Vê«)¸!ka+FæÀ‰F²˜÷)ù׿þÅT}GâÞÿ"_½Õ6†¬ÃpÁ§Ù*©ý&äïU¸™ó¹U¯ÄÐç(7ºP ‡>•«íŽ$lù`è9ã cêB&ª^²Ÿ=ô²¥œtø”Ý@RZ³mìº|%ç+@0ŸÒHøºK‰ü[•˧W.:–ÅÜ̹4˜8F9žgUîÐóÒ±ÿîW2%‚R¶#d%o›O|ØÚ¨ËbÖ° „㕤 ë(lEæV (¤T5˜ishK€ñb UéØÝÚŠÈÍ–˜•Âl'@VˆÑ—`2ØxùX „l‚zñoËVÖJÙŸr)ólù3LÓZ üõ>?†ñNÔ pΓL Éí*7šÆ³60@ìú…L™U 9[a@G¡pa›€&¬V6±ñð…l¯l£Èbúù÷=Ða§ÖPÂYÔÔ*VG³–¹Ç:Ôe àg †2A¯Êñq9²Ý­ñÈdɬ‡L¬R s渓tR5%À3±UÞHÛ¨l%S£Kæo)¸;$J1欤IòqF|…¦d É[¸0•€=àº~~‹¥ÌœC €Ô¨P˜…ad…ªâ»„øJv"JU¦Åð‡1«˜(‘Ò±*¸ª¬”jj«DÊ=µL¬€i²Åôkn’á9(¯¤Vb¡VÊ<@ƒÙ6‰r«,&[c×YYáj­ ­½„RÊeù„ÛþqÕâ8ÞÓÉ2±"&”bÛA¸™öĺ!)ɬ¶þ7@{¶"[@Þvi*©ÚI)·Ú €@Ä´-eŇ•›­1ÌŒÏðTÞP(2\ùH’p+G³Ö`n`YX¤×nÇÁèHКÜum[ë;Ñÿt$ˆLÐððk¨¯­¦€”•LdÞxùÐèÛ ›ÜCÉJoÛª#“|Vž³µF4ÀVH/KoÕ]ŠmÏ@bÈ*Ï)`È€Z€8“|àÄ7`ˆ«Âg‚T¨ûæeé½ÿ•̳”â­†´7,¦¯ F¯‚,ewR £{çõq঑À«:ÿ«=Íî#ÖèŶ% z[³ñì“%+`¤JY‰»® ÷ý¿ÂîJG 1‡ Èpí˜Ô—Ù¨SºF‚4 ïÈÍðÛ?ÿùO:”ö}àýú’{)½m+€Ùá)sÄÛ6bí1Â@‘BÛR€Úpµ4˜°¬¨)ÐÜHÊü3Ÿ1’gWÖ×}…4µ¶b%RðÔÂêÞ­kÃxÒd>MÞ‹¥JTÅ9ÏZ4ŒÕ6 @y+>ßw°š?ò¥Vk {.€a†/˜Ha™¨\ h6cwºŽ#Õ1Ï ¿PQˆì€ )m,®ñq.êë.È<¶]WƒuÃÕ�§¦ôµ%¦ôÊÑØZ9ç@ Wb»¾)×Ô”ü)cUb¥¬]˜À®WΉÃM8Ù<ÜÎuß'Ø'¥‘ü™ÛœôRuäßå#©a í&ifkW—rYž¢™­‰&^~)i†F…‘É*ÄÛ*±í6¶M¦ö=5¥’já¾(‘™˜°G#¤öÐùü0¯¬sYa>ï1³mNoTm}qqæàŒ½/•le•RvÛb8™íšêâ/ØlëHŸÃ@÷ck b“cl$kJŒ,XMÞ¶ù½ödªtÁ$ÛxA r°ÊZ=$Lcù1¶"LÈd(4X>@1±­òà`f¸î¨ƒçé,‰ÕŠ®‹¬ØWõëÑÐcÌе¨²´*¬™!X¡¬mLÀJlf‘ØÚSÀHu kª-å°Ä™è2žÊ­"~U²Öp‘,ÃLNñ£„ \ˆIºµWòy”m7gµ|R!àD]зOßÕ©s¶6a³©j<ð”ʤ¿$N£„¦aZm›ª-mLåëÕ¥jæ ˆß„¶¿Û¸ªÓo==î¯vV©u¯Ýd)»ØkùùL±u^_hBGqýΗ¼”èJ•ç EÖ‹²i9TUëÆnÚOAyž¶aY2«UÕ«FpMKYuAÒ5ÊfU °"ÇóD:¦¾1\Îÿ1í«p.‚Â( :•••]ßk‘µQ’’Œ!¦´ðì­JÜadÉ蚎C&`S¬dF¢L¼ugûáùª“7"­B#Ö¦¬P‹.DªLlÔ®+}•ØòÉ0ó‡ÿ²j­BIæÙ"1­H-ðÝÒü›j?uhšŸ­ß&Žô3T®ÐjKc`À–ÌVÇŽ€,R†›'fÖÈ‚‰Έ¡1Oæ”ce$¶ÀxnÊiø8¦’é󆧌¤tdµ”VÀM¢„@Yn1Wr¦* 3IOœfÎM‘ýúâ¼J\/ÏFšO<±9*±v.µþ‰<¥\ãm§¬£•/*4†Ž‚&LF £`ÕÉ «TúÆ9t@Ýt\[X•'ÀÁl1 5%“ª¶™g)ÛÍ (Ä[S. ¿AF#4ÂW¥5C¡°Ã6 1²+†ÃAy&VzÇôŒÒ{Uú8Lf›³FÚá;c&kT/[šÆƒ‰»(Yv9¶4 ³0JÚšVŰÙrÃØ"K)WU_¼™À¥Èò™‰­ÞW1¬”K€•—d…Ñ‹¾ ‚ŒC˜ŒC#¶‰ÝÛ†ýÎ¥œ¹mcØ &Jÿ¾¢•›FVAÌVÖ3ŠÌPŠ­U–CU<é{1ð²—€Y¹ux€PÂ$±¦)ñL6UƒÙÊ ŸY§öÁMÕG¦r†JqVë8NjÚzÙÈ2ñD4‚„4Bž¿ßÕK9Y[@fèî£J póëF6Oc(1R%R›j†H±°³\îؾâæl5’ ¶1Ð$Z'À4m ^Ǻ¤ èn¥ÀÌyŠ•ÄW‹ß¹ð Êsµ9X5B&N¶T`µ²ê²RE²rœV|â¾|zjþªèɼR=;[8R#¯+‚ÜøxŽï`µ–m[z«À¸=k}1ù4dúÚ…É,®ÍǪ” ÿ&Œ…W‹­vm•'³M&…t"ñ92¬iUbKÓA(ùPòüÌw µ¶u{xþp½NP 5C[Ø$á• .µ®ÄZð§Tb o0nèîPH˜@! Û¨ àË#ÅP¶1³mÊÄH¡/±_¼­Îî&ÍoûÛßöH*°ú #X‹Ú`„'áñUHè“°¬¿TSH‰I²­3윲¢ÂÎFÉÜQAY¸2M¥ŒD¼*4į³Òp“IŸ¸#`ʪ0¶ÈÄÝCV)Ó$0U)UY«jføs†ûi¯CfŒÛ#h`àÕÀ‚¾Ð lfÀ…ë® ±â­ UY+cïÀPª¢Ì6#èsK‰/ð¹5›*1 CXSWAÐTÜX¥ß PªU%+ˆ»ØÜ˜²‚’.¶ÖÞ ÄÊ¥ÈòÄ“Ix1CoMÌŠFU½Jm#­¶‹x@Ræ'óÍΑðp¤a«ðù¢I–§I(¥X5U“ìÕµ³pºçR \Çõݨ‘U!±ZíôÊäŒuÿXÅYÖÚü0½”BëUëÍCóÖ¢vôÈV a1å &ÒÙmû© Ä¤P$v“4|¬¯£`jÚVŒî­‘”fÒ©;x$Lì§L w„HØÁ½oz•%HÓ *ì±24¡TGP뇬ÚNÑð½rpÓʶj àøœÕ¶RºFç%Ƭ VtÀL` Vªî@rV.`|†²Ö µ€…ZX!1L¯µ1¤àÍߣ¤¹EŸß6ò9m.oK_÷ 1º[UѤïi’adS‹{ØH%RȪ²í°W{¾â*!5¼­“öL•Ç×z]=`Cz]»¤îVŒlV¶²‰ïtGÐxÀ/ÁZ›¡—_Vè˄܊糳gR·ô˜w´˜ñHÓ¿ó„ñf¨ ¥îH[—Ó$0¾»r™œ;‚‘+gV; †¦Ž •sS2™=ÒjzY$€$Ó#ê¢#àbib€0UpÓêEÐ÷m˜ r³jZ Ö.Mãuðdšâù+Yk¸k!@6 ¥RZ9“±²Åg8©is`+ªRR´­D–2q}›?[ÝEüuú¸EÖ—òÖÍ`[_ Ãi*´&…oÿÏé”m¶Êž8qåla'²up{…Æãî5 t4JA)4€”­¦ª„«¬B‚°Z2̹ˆï?›mnUËÌmrÛd¬ðgšûE¶Åk'ØŠuÄpS¨/p%ŸÌÕgð5Ìjø>­<;ˆl¯÷;ƒž˜›ÐëNq¾HÉÌYw @Ê0¥¶ˆ+Ç{ÃmÂ"Ÿ4 ëec]/âKN¿ŸÖ •s£Ñâý"r.“4ÃüÕæ`E–%ËS9˜m%pçJ°’JCfèŸuóirâ>¿ç¼„W ¥Ÿ•(w+iÓ+vÛ,2•¢éö«ÅWΓ8f‘›Udn%æo­£•>>Ù®@/)ß#Væ²ðW)È®5™­ÛIÆÜ¶ˆiŨ€Žµ¶bº¯›üüÉ3&™çÁ¶ÚÈÖºÇç¿.µèhuÔÅ$«këþ݃ÞÈf¨]†@ zÝgÈ­±10Ag‡óÇ+|ñRã6[]ƒ¬¨i&…­¦Vá-Ê¡µ¿å"klnÖ‚›Qs‹ôÈ&¯V @ÖÂV ëdº'ðÖü+Ñ%}¬« £·ºˆ×_–˜‰•¹5´Õ. `ë¤VÙ…BVºó÷"…­ÍÙaçàÕÖ.=1Ïn›&¬D_V}("w9ï$”²Ìëclʑҫ1L|â²aY})…ö½ÁMG pj+Æ:±,&«Äª2Ôοê*ëã$®Ðé´€y®…¬°Í!¾gŒƒ/=…œLVE¬¦ªg·²œE€CX!“4VÚ <çVJ)ÛSCy‰á½4²é)}î V—ÖjÉd1½;ñåÓ÷*+2<`]IÛJ:‘÷°Ž3o 1 `Õ.s¸Ž¶0‡Ú1,TIÕZ¶îRø²°×Œ'ƒ­Ø0éms37$ f½*—ÕZaÊ<ãÕFZEs‰c"çÖ6AÎJ‚žÓ¹0Íæàø£b åd½ÞÎ^¯ῪÏýÛÖŽ@p¦çÜuÁ[˜Á*›•-ÁVn²é 8‹:âÇÃĆônðçÓ»Á_(D&V.ˆ­1œéÉj‡oBŒMµLàºÐëÕ´de´•²¬lsØ&EJ-™m&m›DVðáL Ðê\H%‚Œ‰á8¾/F¤@bÔr lkµÅ‹Àx !;Ü–L¯d0PäPJ;)aX¡lÓôõÈZeϪ£•rßróaÂÖ©ûý÷ß©íË%•s`¼bX–—Tç¯^?3½ !èi¤Úî`€’‘ÃiÛµfÈdzŒY÷d®0íÛÉÈœ¿PòǨ]V ÉLb d¢¤ì%˜î7Û|¬½L9TXSå‘ lfL¤*¤µKð#°Öé‘nžIb  e—JÏ¡úîĶ›”j `MÜ%Þ@°ÅçiÅðù˜Êé‹” “ÀîtZ¬By}i©0CL-ð™Ûv"÷œ­T³%õµí!1Ò‹ÁGŠXem¥¼çªlUVU"7­[Ê4ªÒ4 DZìâMÂÁŠlT]ȸáKQjä×S27Æ¡ñÈ:ÞŸM’‰iÄdÄLüÆ ¬¬¯ÈŠLUo,F_åšFyVHÙpÎVµU)‘}mÕÚ/’¬¬Õæf›9+¼Ø-Áª pêœÉÆ-ÉÂRÖëñ)lÂÖœSú|íÔî°¿û (Û¡¬é4sï€&RVY…3ë%mYyjaZ³å)ÅÐÚ¨9To‹4ÖÚ•Ú 8¾õÍO «*)àCÊx[J>FŒOãMÛ5^Ë£ìliDgÄ·e8X-PUŒ´•š->+WÄ­™iðÉòŸI|)bbzdm ïÇ™µ.Äú6[‚æa…¡QŪvæEo0 Ðd‹I¬¼ã̃Q"óÉÓ–ØJ£0Û•×NáôæL†¤LŒéÞJµbDgÁPZUõ˜€®H#2¬ÙZbº±ºX)éù:Z¶æw!°à£Kn~ûŸ­OG<’žaž­šj×w`Cê‚éËÙjzÀÚ0mc’)•'³b¬"U¹Ù­akÛd™[m¥Èdm«Ä˜ž ‘4ù[ÉrŽÜ7Cߪ8¨¢„­‚R^ÀÌ|æüwî\L•ÀÖZ÷ª¬¢9kaË's«Ú•Û&¦DÎð ôýU°—S ½¬¾x­"[2`F³Ž ë¸îªÊöˆë‹É6g%˜0>Û×äLy­¬R|¼ØS"s®ÊH|‡C&²RÆ‹±bª²œW$ÃÔ…O% i­0`Žöö…+„òwmÎ<ñ§÷=ã…›¿ÖkQÊ„ÀŽÓg“#”ð´=ÿÀè²°Â}$²õÏÇ á# eas1*”™`úÊØ4ÊÓw xn0†L–•5Á‹ÉÎèwZ%°§X¹Z%ღÙؘEb[ ³PγQ¥DåõâìtV…sVÅ¡ÏFïz¶iªžØ³´ætØ4²½»<¥&+2SÙn†º ék!E€Il‹·MÙÖŠIéPzÅd %4o`„”v½ÙºˆÊÕnÔšfn*åµ` T˜ 1²’~]ÓBªðÄ0Vj›ÄµÛ’4ÖÝ0M ½X  Z$ÐêÛoÏõÕQäOæ'“¨{>Í#•Ò wN·9#ÕVÎ?e‚&Q^à5°vjkÉ»m<…WÜSÇq^šxŒ*í9¯“>FIóô ¢­’Ng-X!­²æl¶dšÂ"óðt·¶ª4RëÉMÀ åþjû,Ûv¨dHž"C .4ªÐHjÛ2G J…¶V¸;„zΕdHo¶ ´ÝI• É̬ªÂxV5ª{µ ÙðÄjcò±–jlkàƒ­mMW¥E­ñÂqbœ¨aØâ¹Uâ>ûã+…VJ+XRž]SɲjfV²Ä ñgÊïµÓË"U €R mɘ ÕZuxš'g l}»ØóaU s©leñ™øMâNd¥ô"NÓä™d] ³Pv'im’üÍ4‰¯‘¬gNðšïtÍã.  瀵vµu±l‰×” !kj-åZV• ¾.ÖÍæBð<™7€*%f ©DjY%Ý-ºy÷–˜Àµ3'óÚ k'‹)˜)á&&s«XL€Q"Øz¬†§#mW X»:ÙEÓ<‰ñ‚¬¾M(%¯Êš¦ŽeÙ6Ißç¶QÕ i¤”a) C½²ò$ÀÀ])%ÌiŒ&¡É­SD¦´ÊƬ0`*!ëñYESÕÎ*‰ë˜2s)¡œ’Uz½ø4­ìJR4ÈV>¾ŽðÌ;89Ra¡/ð€Õ«B̰l¼”’šIiK Èš PR/²Jô"ÍCœ>P‹zÁnx²vŸÄ²H€-`J¼¨…Wέ¥¬9œÊ‹M¥QÃp óÁ3éå1ü런c!5"5ÀÚGÔ(xõx$_Y[J©|‘b[ü™ñûÝ ¹¶eüdH¸oV%¢óh ©5 [»| †\a$FÀ?ÉPpãÓUvM)oÝ) g¦ï÷²ójgU(K)X9K•̇Òß%¶Òh'Ëжª|ˆwíid [žžwÎj1üv!õEŠFµêheÛç~nôpk$«æ±ªÝYlɬdø4ºÛn¼È‡¸#{Óâ1Ãxó |¬•K¥T…×NDö>wWa%µhrã‡Â ï¼_¯Ûâeua‚æÙÀY2%f³&Æ7€Tƒ¥±šVTØý¸|7#µv†Ï‡m>;£­¬Bƒ‰Ži€€*J†€‹”V|>Îb«J–¬ƒÀÚái0V‰7ÌVàÕÒô»Îªº‡u ~­i)M­6’@ÉG¶`‹ß0mµp@£Ö ©Pè%ˆ lçlUV½Ì`•Èœ+Ÿ[t¶d˜søû©ÌiKc ÕÈPÊT¶BŠ>ì0ø·Qz<7k]*üÑ‘’[)ºÀ™ûiá,²+o+›­­{s±º#•Su´ÅÓxz4 ª0ñ¬ ¥ hJlÜ`k7£YYLäÖºç@&8\Õ秆TC"ó´·ÕçKÒV*sJeiT‚Þ©S|ß4§àIé¿ b<ÑTN$2^gãÑ»gµµÈJ‹Ê#Ua >Ç +T—²ÚÝ}%OýšXªCáÒ‹Sw$±­²jžf€uXõâ&«°m˜ œŽÆšUSá ¤€i˜ Ó˜ vÃÖ4/RØ<¶Þ®J¶æ±ÕKI#5ƒf>Aµù[u·Æt]jQwæ²ÓÔÔV‹ª0”Í€Ù6l5}>­2¤ST˜Y%ÍÀ–Ùê¯YM¨@¨µV¶•%ŽD­“åßýwZ§TKÐ`4¸, Ÿ¬ê’,¬êÜøý£ZÌ_ë<#sÀH)DÄR#éXkØç¹*‚B‡fë/#z7ô4µ&˶5¾*« 3Œ€Úu„¥TÙf5·>ת0}Xˆ+lH+ÆÑ:A3ÑÎVJ—f†eµî¬ˆ³%Pb ¸(Ý}ô@ ¤ø¤T^G€©Äj@/€@ U•å@ܘ&9ÿŸ€‰ä)†åD^\zŠ*KaÈŒˆQ.b,’€’IUÊ1M@9PïQ7kpP¥nÈÌ›£ÓÝ•² )…­@¤µòd«U!‹™r9½³[Ϊê^!F˜™a ¤þò—¿ÐôßGÄp–ÅÓÂյ9Ãç/û’i¤âÉ„n‡Ž0˜[/7A>Vo?&‰ç“ÞúÇ`¨Ü¨;‘r‘2Ò–³_û¶°ªÖFÂc´s||UVh¯_×B e¥ ÷í[k¯kƒ%fÒÙ«"+8‘3賜@9Üå$ÖšokZªå¯/e)5ú"[«µÂåû¡ØsïħT%p}+‘Å÷p}QÖâ:=c5’’.PG)«FÝq†u©sŒrÀ ÓË ˜]&’¸C%ËAVt/žkì dvvCˆü­A¬àFÓï°©ÚJ Ó´åcÎNDÓÅ" lñ[b]L%9à§ébm9¨åàQZi”ô’ØÊZe²Æˆ´"k”¢Ä7À È,ŒGXîHad&^Öx¶®¬BÃÜq²â@ÖåÈ ×¥ÖãËGÓLb‚˜ˆ¦’‚ã lk _Õgq´šöŽe[U« j)ó007¸-±ÀkW£!;%r[‡bå™X;¾r Ïpæë•Cçâ K/`‡’}®¾ 6AoÑÊa«çø€s¦Q«°#´v|dY%1ª*±Êj¤Öã«*¤,£#¸!¥r³º¢ºÈÖÉ™ÌÚ‘3‘"Seë»=™›±eh%«;gú̓§¤ïeÛÀ€ÙðªÅÛŠá³-vê¶ahšü-'ˆ\ªŽZdµì¬¤š“ƒ/(ó‹x½œ×ªEŒ•ãÔ®ÎVð'håSt4YÛLúö#CÊâ5êŸWçg.Õ‡‹R!MVÞ<€’bh€ô²€* Žl²p†­‘½ÃH¡Äš2pØ ×H lNï|wª@æ¬(7ÛäF\ëHæ•¿­‰›¼ƒ|\îAÈúÐi'ÔÊÖN ÐK óOC JÔHªlæ¥*žfƒ²u_9RøùØ#ÖNª‡ÎÄýðh°[‚Ó°²ÕÂÖléÉš°ˆK¥9ÿŸ€™ÚQdš‘^•5HãTêáªô )“YÞÅŗ‹°’îÔ6`ÍxO¢Ã`ªÅïR0^!l0kŽÉŸŸ žÀ”’õ´®¯,Pdý±Í)½5M_”„[רmppo}†˜žeÇ”… î³”£)÷¶úuŸ3ç Êö*%0VάØÀjBš&QE€/¦®åç&sŽŸɤwYÖ¶PŽ)`d­}séÕÕá‘|z•}0™ a>­RU)Ù#úž‚AÂÉ&hY|þ r×c ÁŸ¾>¶Fåì˜sKP_¸a€Ù¶v¶=nÛª´«g…ç–2lBYæZãÝ<ÏRz«ÈÐ"s¯–¯ZÝó·²¢Q K5sVñ°Øó§ÇÇü˜D¯œ ´3­­ùEJ+ðguû|U¢Q•ÔÓx[cd1­ #Ùr¶j¡´Ê"Ú ˜²9§'«#FØf[—•>A`ž²¶páÝöÇ¡U*`%Î?œ‰µa¡]­ºg׋$ sXY'êÎ; 1AßúÛ‘’ÞlY¶éwcJºŠ>ÔZd2+YnVÑT¶dùdØ`J*šárçÁdò1¹Ù*›ŸR_+±á‚Œ¿áw]ª0¢9Éèsˆ·VŪ¯b—©ŠÌÖÚØZsÄ"2žµ³Mf 饈•Åg¹KJYEÙ”ÛfÂO ¤l3‘õôu—"ë%ÇÜy ü#«–Xm€¡­’@4§ v"¶þÒÇÀKáeakn€Ib”ëKŒ‰ÄcðĘÎ4Œ¬²bd›ÄöÔ?¯S²L(˶5U ZYAOf[*䔵ÓY\îr*Ÿ›Ôip5O%>³lÉ04ñ »:ü¥´ tp«¨ 7ØÊ@”íUY÷™?,»ñ ]>+Af‹oN T§ÎdåÜvüf–ʪy2ì xAi­¶±¥6ájSÚŠ0Òoòø+ü|¯N&KÙ`H¿Š8š-q)¤°ebmZÀÙ1Ä5‚ÑÃ(]@̧àÙ6=¼ííóž²BY¯q§°ÅÃ{%*ÏÖH@½b °’276þÌã¿PA+Vtõì(ly)6Ä4祸?BàÅ-ý|VûØcT½>ÌOãï a|¿€™«åYy`£ÚpšÉÔžQ¾Ÿš|š$œ 5DÙ-[d‘þ»;ÿ™2P¶’~ú:NÍiëÛ¿,OCªÅl†æ·b6Ìéq/ßÓb¥ÊVJ­GÓgÖm“e‚Ùløž)dkÙFíÑTX–ëšRÚ®0+þôVʉMk+›€Ü$`–Šg`¬ÎëÝ^•4˜Ö”†^ë{ç× [Ù¬n«Ï¯z9He­E)ØHü}ä|ÀÞÃJÑHMŸ ·~ pêžIkJ*´v Í¡ªî¡Ë'VUªªFÊÊѤh8È [1ËZsÃ×S…LzF=/ÎŽÐÙZݪZ‚ yîVùd%E#d1msp{ZHá›V9 pê¿?³×1!Û„WxšPiÄèÎÓÌp>rÛJ0Ü8TÅÖl­Ü¬xÃûÀZÕVn•í€Êá²%¹Y›ÜŠôf–ºŸ¥î6ÝM_îm+´¦ÎÜ„9ÓÀÎd¶qCLæèàÞÓç‹0†Æ£¹Qö©ñáˆZ³Í¹dÀZ4’Õ ¢Q¥â+×ËVTB[AX*†x$Œ<•W?Ÿ”3·ÕZ¶`(°u"k¼‡IY¼*OÁÖcÍ3ža³!·‡gÕ{‚QbËJUÍïÔ% e÷ÇÖã ÃÀRLjñÚªâOOIoþF¢iT áëXk$}Œîl‰Yaš–Þ–^6}VVd¸K¦ÔÎд„ÏÍðLúnÔ—’¦¦R¶Zã^ `+l oóªà¶ `UM`¤ZUBVÄàºL™ 2O²R9À€*|úRã»'ªE+qVÖ.ŠÙ¨.VÀ9×e¶xJÑ$Ž/…dÕý«²Å{‡2)‘žsLùÐôæ(TE0=L†¯{[+†I>áj&¶:xg‡E>€ªÜ:µ9Œ­ÕHÆ S;kg9^÷€e‰kÈœ¸ÂO»°•!ýš®o‚²¬„á­žŽïR<Zñ™¸.»ÀZÃÄ¢rJ8s)G€§ÌÓÐX¯ÁçÚkêQª’õmS÷n#½”À7éÕ2I¯AsÊja ä` °=°á¥’‹ª‡›²Š…£Óüþ}†™)Ü×ùÜxåýˆj[€†  lcê¨$&:ÀÓ‘dÉrÈÐÖldÙ‰®ÓYˆ­/9XEó"Ø Ðh (^Œ±åo5Œ0 Vý{ä~Òû—üXÉ’éÕ=«MoEJ)Ö4=žq&¶‚f2ÛÓ–>ù!ë¾{£¡GºsDƒå 7ƒZÌfvä&Þ.ýªDÆYª{îg@ÿhXŠ+²*$б~ Ó›­^Í ›AÐ{Á¬Yú0XjƒÙŠe ”è.ò· ¶V…&/«*1^¹P*FöŽs^#Y ƒŒ™LÕâÎG–R r$pJXÉ6|d¶Z$e†˜ÀÁ­ ‹”L€ ýšëÚMÛãPþÕž^F"ãÐÑT 0‚Æ´…É€ P‹[t.ÍH¹Áj½÷ isFf+%øÈ¢h˜ä¬;½¨°a¤´eR¹1XUãaJØUð‘uuý@•¬R™‰æ¸_ÿÖf p«>ì7ùùZG6M@¹vº8#¦yŒGÙ0+ož¶JêEÙ²B+ÃZÀPE¬K)Ê>\Þp)áD¶¬0”•[aåRú¶ ³È€rXŠ j'‹„1€¸ÉϗƶéÉÄU}–ª2™ÆÖ$mÓÁ&Çë¾ÉŒá!•ù@2‡Wb¥!v)R°¬Ÿ¬F¦¥ï ë´ÈND¯ÖvA çÜ10¶ÞáRB!Æ@êr%ç]aåcì~õoKܹªÕRÛqGàcÃÛŠiz™#¥V•!ÿE)+7‘@/øºžÅ_–¹È6XÀ”³˜ߴܺC)o°ãS27ƒ ì÷•§‡ŽOiKüvaE¬¼.Êemñ|z:¶xŒÔ/U ÑédEÀx€lk€?PëzõP@ª˜ƒ­^²€ŽèŒ4x«@j‡'6€â‘¶­Y•2²ª.S¶T2åR0IȰFV1^ÀoÿªpS±â`«ªB«?§õ,dbê{»_,LÌ D6-Ùô0Ú¬„-g \m­•Û^Éáó „ÉÑ0¯gV­JÄl›Ù0ù7’Uª#Tëµô«<1ž˜k =,ÐàaÎý}¼­vgÄï'¨vV¼S»üiXÕô°Zšëq^-í1«ê8 Ó•bÒkG€,ËMj·4l šyÏt¯Š›!Ú5Ïíüë·>L„lÀšFU%•7F87JÛª0K™§TY+â4º›Ü¶‘J0‰ï,²ªY7 Ñy#5RëÒÆ4ÏÄÖ*ØÛZq$ jŠ÷C!%‡J„¦Â´xz2?éÍ“þÚ|~¨)$V%“ÙFª1ÆŠér*±&¸=Ϩü›¤Öž~%”ÊÓ[ÉÖ‘Fmå §ªÕh­µð™RŽiå@OLV!¾vñV@ž@óïZ*ŸæÊ¾FmW«JÇÈ W©(gÅMàÍIo›¾¦m§qo²”V×ë*Èd­Ç÷Ž0[aëV{.bL+€Ñ:åúÊ&0$ Á Êf7M_”p¼5ÿ4¬Æ)b)²JÃÓô|‘½ ݃”Ú&QB [•c«D$+e«EÆŸ!î ðœ“,|Ug ã%æ 5íÐàeû<ÊJY;`âõ¥„ ˜`LV¶R" Á™ã è%d)Š4: ¼­•ƵiÊbÒžìö9c¤TÁºd®ÐV [ÎLúü~þKÀì(Ôç{õŸe‘ €Î£MXºv¼Hmêu4B‰HlûÇX­×‹ ±ÓöA‰G®Q]êÈsÈ‘ô¶•‚F­T[£]Ì®;^9ñª¶¥ór´3°×ÝyÛÍïDü1ÒðWe[Ø ˜I½Ona>üU1‘Jd­UE¦gèg‰”*µVÙ.™‰ XdbýŽvN*0¢vm›D $7zÎZØê ØæO,*W‚ï©Hµ*a÷KåCÆJ [€f†daκϹòÏZã­&Á¢St™ÈJðsÐ72åÖx2UZt9 a#õø`zJ2¸‡·¥šI2L-0p% ‘¹µ&K _ÊŠ±æxQ•× ïïÊÖöRuáuÌáGS¤h0%yÒsÖEÔ"`5• HimùHÑéJ <&Á©¿2“c‡ÚÁ«y”ˆdýžã=Ü«ªÜJ¦µµø5R Iö#µ¾4™oe…´ŽQž)[¶"‡>ζUµ3d“dÏÓ6ÆÍØŠj°¬G¹-7Y È Øv½îe~Ñ—µE¦§éA´ÍÊ„il»êzÙZÕîÂé¬Õ¬ÐVœÈ(S#§Yý¬,¬e¹ÈZ1ÕVUm’5wÛ²<½)šÒ38ýotfÐ1¬<1uO¿ã%h˜Ü^ @!­IŒ/µîUt +¡e•¶ù(,‹¶ï]mÈÎèøemk×ÿâMVÆ£÷ùÉIŒ´6 ,º"%é×&&š"S*á`ÍüNtæ,h*á0™ó*§¤A†+|Ëɬ4Ez0°B8m†ÆÀ Ln@Te5‰ò4¶©œ¬­±]—,ˆšòw3œidùÔ×–2½uc«’R5Ÿ¬šR¼…¶5Bš'ÜíÕ¢ÂõMOVÐH­{ Ü©XIVdËÄx¶€ö³Ó*k›ÞªÖH]QÊÄÖIÖŠQ¾áÜI#½‚Êù«-[wív9x” Sbˆ)°-C82±òæQè0TcÈŠÊÊmn@óÉd”pÛªŒQ£ÄÙ6 ,µBú²@}+!žIædçý¾¿<½JV"“”j14Ý<<dƒÑרT<’xw8ÏøùðJf ÐpÖQ¹w ¦ÉM?ýŽŸ‰B)a«6O·AVYÁ°‹¢§l$Uv™Äx€Cšcñ„Z‚Ró)¯Kµ²‚>²mµV|Ù ÓlÍ)›³*¸vpC®;¬èW‚á#0nï=ˆ’§Hê¿_\JÚºÀ?íü‘C©fVècåu øöžFaƒå¿#ì€øÜ¤žJ¬ø<ÆfK#θ÷&ûI¯^awb`[¸ÉáºÔËŠcˆmã_Ó«ú\#õeÒj+½¸s› ´Nó’³Í¡V¤â­pï)âEY±#ä4UÛ¯êü'™Qõ’â`- ¨âƒ´Vž ¬„€8eÀʾK£,K‰·rÄ«o%ôaBÉ&±­u¶wà ?_§Ä‚¿BÙRÀÀ"¦h„^šîíJL@¼1|óU• `HÜV*絶圀f…UY‘giÅëkR0¢¬ ÃR—>—ì,5B’a2$†Y9 Ð3‚«%£ÁWUÓÖåýÈv¢ºàKéµl¡–Ì6bµVÙR<áJ•0R§“&ÀÃVšóyoOTd]c¸­N"Lf+ _çá Õ¹IùUéóFYÊVcécïÑTË@IDAT6±ÙŸÿüg&msÐÈ ½@æ&Ó]ª 怤%A˜&@´5jn‘†Qsȳ## ¤l©ÿsÍYª3Ú*Ô¥‘\š¯r)Mûã27˜žÀ[»…î )Ë)Õ‘‰¥D])þaJ2Ñ¡˜dÞ¨½:0¾àOlÛxëN ³ZGæ ¥>M ûdäÓ`8µZó8ˆÙZ¥ü7´im;lc[ç‚¡m½(›PSQ/ÙM€´À?î3RSIÖ¨ÿ®;Htí¶•(ÚH/3MÇ™|ð¹¥zŒœ], Ï‘î}vc É3ÚbæÝêY«ÍdƒEUoS%uÉv…]…¦²ßngøŽ¨;Æ–Æ*4‚­]T7à>¥XñÇ8šƒF— ;m3Ó0w"µV%e°Éðød@_9—m$í6•^R ÌPì•à#%TUØófõº’söÀô1MUJë‘“àó„…ÙÛË=†²çÒ6=q`žµËGŠ•µƒw™—JœIo+láVÛ|¦žBú”˜@2kèŒ.™ÀûàHXùÒ¶ñʪ´é÷Ë-ÆqªêÓm˜î‡›r|ÎÖ_Êv8Æš¿•yÛYJ|âaYa†Â0}Š‡Ê–†¾{SNŒ™O£„¬mk%¬Äª(áÿú ?}ù[=Î}®»:[d¿î›Ö`œ•àa\k@HYk ÷(uïSyGû|'“q柞­ì¦UO€×‹@6ÒÚåfÐÈÀÉ: =ñN¤¶È¿F /Å“ B)¼rz¸oN2½¬Ó4˜yÔJa9cR‰!kJƒ´r{+’‰lÕbdRÊ‘¶1¥v±ò¯Åå>¿äŒGÖ×HJéb<+\ `Vü•$ãÀ¸%©3â÷ëIáp†¸o~Ìæä¬D# ²Fm §´'àÙN¬\d…TBƒq(…¶:ʦožôuž¾v¬j‰»“ª*Ü Æx™ËòÇÈöªtº‘xøõ +шŽûi™[Su²º#e•M¥]ÏNw$œ˜Ȫé+𢑪ºY%R‹[tžg©>bøÝRóëŽ!“bÛHl«kï Ÿc}ÇSR‹ ©öœÅ¿@¡~‰ÆõîxgQI]WbŒuÇ€…*+Ò-Sú^Û›?‹¬F”S—<[3d®WnJNûÛ®C"™T"E)åó 8?%>MÝ1PÕ"AY%ݵUx”ÈNaþl¯¤³T‹Ù%kgëPœõm«¢¡O‰aomZÇÔ®;Q(l¯Ù¹ ¡Dìhy*'xA ð ÿë¥$NVÖšs]œ+g+ÞªÀ°”©š¹1jG $[k@¸jVH `åМpÙÀ™þûÜ*—ítV©ky~åË6¥P%Ùp%‘ òÉÁx4=Íß · œÆg•­KèRA 3ÂL›3 œ¡I¹¨W&9¬Ð›Æ˜L_q ýj³µVˆgN œOÂýúS¥/F-%²QUÜ ¤m‘-PÎØ—ƒ,«4ôl§TµHà&ON–mLʪZé;xç­#hí ‰i…Jf¥ówÎn¯ùÉàÕ‡5ª}“[7¹™Iš¼ÔÜšM Ÿl*«kÄÀj¹t)‘#bên«ŠÞýû}43ГÙ´Mvêo(ÁäL\tŠºcd»“xu•T5[|ð"Aµ­¥(󩪵#4B&NiËÁAò”ú&OYG^H7iKÙj¾ŸbÝI/9óüõúÿ‚¿na+ˆ1ñ+Äs3^ gJàCjKÓà )kòü Ó4?‚ºçiUR¾cúÁ­°*‡†?7qN~¯ZJ½ck%PVbZL[ !E J€:êÎ ÙxÖa g¨n’ð;aþ=ÙJ8×(?sžý8&“‚ÕîY#™UbxQª›m2€‰‹µ²UPæ@ƒÉ³#ÐÛj-0"r|87x•¾¯°ÓYµ³æÙ-©¢¬]†ô¢Â<ÁèÏïH ¸+X¯°Eþjê¥Õ¡l×’¦v E…%F8M$ž»µbnݧvå9»«ÂVG…ÆÈ*“·*õx¤Ut™µ³fËŠ, ÔÝ chDåµ CÉÓJiŒ^•º8Û”sæP/+YcÓÀý솰¥×ŽLà1¶ºô¹ž9 ¥„Éù€½i˜vŸçì€[ÕXEÓ4¬“~~¨„;¼8ñõø¸!µÎÙªVø{@\y…²1ú6!^pãd2C­uW+œ¹Q™$¨#¬\ÐH …­ÕZmɺV1åz”R4:»û·ð»d-DµVY[Ý΂<ã~ï6+ÛÄÀ5øLh«°ã$ÐW Ū2ÁkTÖÙ ð‚!l•RÒêSaþV|Û¦µª-kë•ZÇ ­¹ZÓ²•º®Ü”L#kY‚¬¤(™t«x¯ ,LÏA`ÂH[Uùd’[%p)²Ä1H¡PPöPhê‹)eÍMjæ ‘¢ìuú\)Òðé "&e…ó'†¥€¾‰ÕZ‘v!p1ö“Ùªª{¯bdíæì˜l‘nú|YÜ·z]ðÌYe[9=²òxVÕÊagaèë"^‰ÁÄz‘e%%Úbèm›­ñ’e‹nÅç)À™«ÍÌ6±¦îÄõ²5$#TY;KÝÕf‚ì}SÂÍÖ*%ࢾ6€ % såJr8-ï$˜ôKBIG€æ¶Ád™ $2Y—\÷ÍF‰´ %²D¯\äÃdAÞðj#‰ÓÈkV¹aˆ ©fFÖq *+e…°H` Ë ™Øz3mº¼ü9ê}Ä\Ö• { i8°²ÍÄ*ºgµïåà« ÀmÙ)à Çà¹ñÇÈ Ûe еT~zïÁMìD/˜¨%€ Ÿ/¤ZAÜGÃÓ ”½ R°¬”’^«l¶²ÒÌ3¦ÂdºØºCX ÎÍ uçÜ1m»ÆÏF † Ü$Úå³”¤«¥Wkµ-KМ1M§”šRÔ¢Z¶d¢!‰cZs®ÄqÜÆñe•[;…r€lå§Í€F‰¨EÛdL¬È1”Yåi‘ÕZêqRÊe3ÁÙ ¤ÙÚÄUu ݦíFJ¯\„ó$ÂVµf6’÷ÖcnÑçûÖ‘ùJÁv7©¼™‘á9ÔŶ٘` >J0²¯-^à­MBß“¥'–*[Y@¦¬W«-ñºS Jpcn-(kT‰« # ä,*‘¥Ïs‰/€)+·U¥dÝ¥øO/Û‘ùÿ㯿þò9«‚>á€m¡™âÛôÅõ®Ä6A-ùrðT´WN/´_Ø*”¥ªE*·TÁ€”Fa©²Öœ‰)é‘Í–ažôRVYáê•´5,kàXe 3É“NUÏp{Kb¤ª²Mf«Å©ù^]Jå1&pGÓëH¿O¹p·½^µkÅç¬DØâj;s¸y®ñYʶm‚!WÃSö¯.¦BÖ”@£^Aåó\kd&JÖ¨ñðdÊ+„ù4v ¬£*”m—eˆ‘ÚüpY@ª#×w€éD€-<ý Ó'“m6[ñŽa;çLrHÓJ£W¯(Ÿî-Ÿ¦m† 3ÁÛÆÃª6¡­Z&˜VÏÅ*ÊVÞª5+8@$æÃÄÖcxbà=e$ðµPF°MŸ­”ª•ÂðÌ _÷€•#KÞvÇÄô¦Xa©Ú•’UÒ*ë,âÚ|>­æÏG(Ï!çÈda+½Ó9µ{*é¼R¶ôñm1+Û¶†É)•3’ &ÀmŒ*G³-à€=\V¹¥É¬¥®ä¼T€U;k!ƒõ²®ê-|Ë YóüØ]ój1@“Ðó‡ ÊNƒQÒÌÈáj½rçqÞëš'M$@fÕ…2ÏuŒGŠŽ‰JràJÎÒшEã¹vÛôy ²xçyöýeÔO£ÊœV)$|z|ߤ`Å ˆ1‡Øo ¹Õ£ÐGÏ/îôHúª¬ÇýV‰-Û yžf÷éàmi¤èã¿Á€ëw:öK¥ZU•”µÚ‰@ +[©€¼.¶és£ÁˆÊ‘a«T/üj1 8ì)P"7öN‡Ìœ3=þªmõ (U97v“àG¦y}tìhJô"h  ñUm6ÉS! ´`Y…< ;Ñ[•‡L¬dN àó!+kÎÄ_ô ï³5^÷ÀÍTià&W(‰{‡™à}‹®£ZÃd"ÅÇTJ໵±msNy%pb&Yà¶:Šj•Òt.½m†H¸™×Óqž‰v²Ö™ð„E­)ÓdhÛ¶O¤ñT¥iR×ìð½þñ¯ý«´=@!ç®k‰pm"õˆiËÅpN«\a T xÑñÔEJ‰ïsïÁ=Âñ¿Ïˆ©Ð—ž¿-2O&¬”çIÐØÈ¬®Íùe¥¯ê!Áñ³­jb>]Û4µË¿ßÌ”µk[0C&³Ê¹ÙtRwÀÿúûp™TUÇü[«Ò%Œ”VÒHï`™ÈR6ƒìܬ^½±U!ÞÚ‰ÆØ"=ÍZÃE-`)˜Œ³ªÚaF9ÃÉà”¶œEßÀ+ »É?$¦™YÁ]i %FØ €Y#Ì߲˼uçÛ³IÊ91 …#c¼´HQß:šG ccUrwLƒiWÇ^Z Æ À¬/€qÉ9×¥‹Ê?ÜH”¦R"ÕlV]â3‘íê*LL TÙꨢ•ËÞŸ7J!,UI˜L­ Rºô‹ˆ-qdãÉ ³YÇ9àÉ6^ä­8Ï]¶ 0sz‘•Ù<@¼µÚ¶Jl;xþóA²@AX@Š˜I½Ü«iðn€ymÎTn‹$¨5 ~}3!®m_’4¯Œ©5±è°@Ós†ßÈ'Vbѹ¬Èæ£-⬤`A‰hÎ_vVo9L“8GkB)€¹•Æœñ€›9sßW1© Y¹:ún£ %p#UH)`¤àc] ˆ™g[/U°gM0ϬZ‘ÊûêÀôV(ÉÜ0µS~r^¶³ ÐP*¯p@Ô"¦#܆§µ.˜p>î ãh «µŽ§,hÊÚjsƒ¶{ù} ˆE-h`ædV¤u…RçŸè:Šþʵˆ‡1™4^ƒi¬cUFjHYMê=AU×!q}k¤™anib¬‰É`Gà9TYŒ XKµ¶møÚá#·õ²Œ]Ib‚=G|Øç®óæCYInVÓbÞïÌRZô-Ô‘›ÓJo­uJ[bxÎ@ä€lL\¦›·ÆçPî°¯n@ÕJù¾“J·k8Q}ÀÔšYßd½“ª¸³¢\U-l›³.M5©nRmž`¸ÉsV+`dÁœ­µèKL-Y>R [¡ªÖ€­*YHg¹’£Á#ÀÁZS€UæJ(i¬ÌO [EJ¦ïù>g´åéÑLÓjs[wž¢G̰ãàé³R%ekÅ€ ¿«®¶FRÜ`« ‡fbÊNtN*Þ6qVÚÕqžm«‚3ɹBÎβŸ"W÷@ÕFÖÚŠ‘åÆ èøMbÅÓOLƒi›&¿Pg"ÛÀ3éi2—"ë}ˆß ¼d£–²RzÖá94O·-•@Ó¥&“ª{£fË)lñ#×颚4¨Êƶ¨–#š6çN¡„mæil Šú2\k8Þª‹¾"^j1·1õ²Í|·/eUe%íÝè&7d—f)Q•’Æ 4‰µgMFoËM-YÛ.§±kš3L™­9é­¶ÍÃad7V6ž¬@¾<Üßüç.<F1^ð·z¾=M˜‰ì®Úöèžu5e8Oƒt¡Ì¿V)oþóë`…þžúJvÉè»êÜlûì«ò\«*¥ 6Fw¤iVuX>a >d&q-€Z'“º’3[ü®|)ŒªJj ˦„kZÛ&Ñ% ¶¦·æ,ÛA”t:|µ1•и¨¥ª% X‰Å¬øsëO¦+‚Zo»ùÈ&P¥\ À™ …€@*é»FêE¯|2ÛR˜f¨jünfYOM‹ Ã[ µ€µ*@VÓ<­ÍÀÛ† ­pCˆ—Œ1óÊe#­Èøf³R.KÙ·{ÎÓ–¦s)4¼ Oc›C]ê+Ûö4»×kͰ¾›0GD½dûWÝTåÏ¡gÄÁ>˜ ¶yê2sâ°•9%0‡&™¿-Ü×7áì˜æ” •ã{Km;à ¤VK Ù‚ž=¶êkªº²þ/ïüMFÓJ‰4Öbå_âü5+-`‚"2Þ¢mk4R·ª¤Ÿ&n³i»+YÀ0ç Ý'ÎÇ– nTÝÍ€²¶x¡ªÙ`þ›01fWªIFƒÏǪ ÃzÔÀÈR†µ)1•·¥ÄLY¶ªðk^‰Õä²-ôðëÐU95 ¡#Ü 4žB|Ìž¯â ñÀÀ=»:×HÝ…mçU˜-RV)¯êÈ’e›&&"‡ôÍ–˜,2¥ùe“µÎ “˜[ÙNDF/eBŒ-«fl黢¬Ý’ìœÏˆ÷ ªÏTÌЪÙš­ò Y/‡V³I¡D¦X0*(l‘ÊhlßW–F•ƒ )'!0~í›’#Ê"é›C¹*]ló(cXZS4o#…|©YeÒ„R![8@£ Ï3å÷[ [)³"PBìÛ~Ÿ žr²L0øª²RØ‘¥ÌSw¿¥õ0"+W$ú{ÌĪŒ‘U÷gb ØVÎ3Ûdúv:$eYüîÐ4h_—Èü·Òð1g6FV¦’ ±ëª‘’¾ˆ‘4¶Vµ[RHÁ°€³ò?‡©Åƨ¯|q ÎsTh5€€'Þx¥Â¨Vª“"cË /l ¶ÎÖ„)=zÿ ­}§8ÿ¶¢!É:Päç4Ï'ýüE¡”âòÜ…ØêXV ˜À‘^²Ê³²%fN°TßqǬj£Ñp°Ý]5 â·®ŠÉdo nŒ)~dÍö’Sjꀞ _D<ÏH;æ²a3Ôkclg ½¦É¤^ôR1(¬µG ä-ÌÖªûx[‘ÀDmcè‹q«²p— ÔÈŠï¤ ñBӞ¦BÎ$Ÿ­€ÈHI ôzŒ 诋îQ"U4šæÖl²¢Z|ÛZHa¤Àt-U)éìšê’ ™í”|ÊZá10Á_*g)§l-µ5AÛ9èk{ZÞ_wÜOßê>þpUVX­s‘ýçb`“¼Î˜Ž„9 &ÁÁЬJøÈòºpå½Nî ±ÙÈ0Ê ”[é) Žõµµ"e¹ÁVQw2XJ$kKÏÖ»zIùè1Oï–#¥¶îÀÉ­maÁybzL K vá¥àº´*!CÆ“UžÎ Á§­”0†Zä1§ã–>Jo¶–¢×"åøÜ¤#X)má K!;Ú }‚M Å;*’ƒp¢a”µ°ödɤ„}ÜÆà])½-±ï@ddž²'Ø`V‚M$¶ŠLÖØSf¢#·7ja pPxÎé(ÕÀ]¯.5J@‰·`€Îh¶ 1¢™OC^³³Ð'KÙ$0[|-êØTY…kT¡5}@*†nÀÚ`ù¯KÎùtU;/CO°,RUæž#qJ<•Ù5gþ9¯¦iæƒ1'R$àcØÛÒ•šÁª¤k*i˜º¤TÕ`4ñ³ÍðW‚‘ª#F¨m2“ÚI[ X…ëR9²/‚ô9O‰Œ?F7b"­ ¦¼o3åù[™»„J‰œiîíYu÷78hº®uÏÉV‰m€§`%%8”%ÀgkDïC·î¼Mˆ$nþ¦²-‹¤@þµkf[ c%%F²¶eè{Þ×K7LV•B‘?¿yhÄÒØÖu‘²¥Áˆ+ÿ|öYø\h*k-¬Wûù™¥<ÿ¾ÙÞ·ÄÍ¿Qé;)$ì\‰¥[ÓpÐÒÚ…HúJÁu´5›ò¶Ù6Xšž/¾­ü9ÔE¶36€ HOi»v|ÒRÖ‚&°ìÀWrþZkbæ#‰­p÷ßVMYêLúß³j)5M²ÎIgàÙ494 ài”DZñû˜ÙÊ npþ™´Ö:YGó›b½C-àEŒA@Æ$™Tü˜x+FëjáfhÅ >¶@ÙJøH ‡¶|ÚIU$‡ùWßðp[n˜ºtUedBV—f°U˜nÚf˰’î¡Ë±%–˜RjçÙ·!b¡jþ}D{CúoGÐð$žgojæxY)2œû¤á™ÄVYU”Æ5±8ˆ¶eØÚÌLÚé'nÈïý‹¬ÞœˆV ¸šÌ»Ï9¨¥˜Z,P4ÀÙš¸,s1¨„.…i[9²sÊ~ öqã‰XÓzy².@*À¼‘ˆ»®RHç%|ûg8R"[)óäÓÊ °Š4‰ÛbgÛksfª?•÷°ÍVy…Éêˆ7>˜Ó6Ûn†ž§¸þ,¢TÙ7œm÷PMÿÞ³1z7hl¸Õ¹û™&“N çÜð:61F­™i`ü€Ì­]w2ŒžÙVneU‹)­d.'² üZU[ J7á&)ù¤’Ö4ú£;mG€5jïsÃ_Õ9¦g?óe1Í\аñÈꛟ`[µHˆ>Yµ#º(}¶@#P•ˆ¬WÝ‘‚§Â %n«ÏWAÃX«í‰Øº²º(IfžjÓÃñu &Jè)Œ,’RØæ–¯O|¦Äaª¬øpVÊ t™sd¹å£Ü¶o¡²V·§PJИÓW†FpÈ$ŒWH© “íõøünY¹B†½Q˜Ú•ª)-|zÜ`ÎÁA8E¸ë²*•›ám«j6ëÚÅŒä ð½.bAƒ—5Ò²H)[)aß‘?/˜mY6`Mie‫z;Ö"ÆjTJ/¶’n†y¶%ôlw>bs¾‡ÂgRa¸Áè‹j­y"ÉDŒõ ­m)=n+Ù׿SeË&×éóåЛÉAvžLz^” ¹òd€h¤ _®$ ÿ¶ ]©­Q»[ ­ '®E…ÿø÷¿ÿ­G P›I ©”4aO±*YÑû-ÅšÃ+¶¡O@OVy)<€)lkèTNòfyJsHLïDÛÒx0jeaâs€o9€<¿?2Œ+‘M†1f2XÐ7°¤l¶H3ø›„¡*ž}6ÂdƆ•ˆ.9Ì P§'†#1¢9§ygК€g7C#ÌlËAÈFΧF¶¥š)´«£rµ‚kv>À”Uià+ï7¡UUH#êÒxþîàÛßå¬@)+d­µF—Ⱥϳù‘ò²¶V©°ñ0&´òÄ„«ª/1@A|íŒ Ô«r2¼B¡°˜ÆöŽüyúßüçV¥(yj$Â|0×ïÏGŒ2ÿÞŸ²™+,k…Þ=Œ‘ú¯{–­o“¨õésùHïªð0’&²ƒÈ’Ev^Œ’OÃ`oá#ˆm)iÒ7>’f‚¥*Ls\¾>9¯o¼#7›UJž2qäzÉî³×1e+/N×ïï—Æé¬uï˜ZGžfßÏ ­*àf> }äip ¹%hr+ÃHÊ<­ 醲Rd0pδ¦m…‰Õz:@β¶HÛFJ¯#­¶ S#©¶Î^mU²âŶã&Ï– •U< 0½Gq¯ÑÞg«Â^N|]0JzˆKÉâ8ÔÚõ˜êÕúúŒ¯v倓 嵃‘úš £…mUȶÓt«o#>™#“ÙŠÆ£°Ê SßôÖ®i€œ• …m`[2ØZ$€uL`¤^Ö…-M†>[ g[…î|&y&€9tºÊs˜x©Í<™¾)mÇ(ÉÖä‘Vå¶R9X½ ðb$nM Ç'cÒ„D£éÇ7)2±‘6°{pÿýü" äP‹yÒDv“dÍ ô©‰GVh+U4«¶ IÖ;¿'Kƒ¡y™õb¿m#uc˜ü­Í™ ƈ9è+t±–ºÄY²rµRið¶1¢S$ÓŒÄÓhW!c[!,˜b })@j& 0UÙ†Ø62¥µaj]6Y̦•z••—µ²M™s<,åñu®žòÖÛè!*ìÅH°ŽjáÖ •µ8ÿ@Ù¼j#¨ihÙ¹¬qYÍ“éËÚ`ÑÝñik­p[æjÅRpdæp/.A)ðûöÌ¿vJYÊU!;辺V[$OM¬V ÓU¼&Èô 3©]‡Z—¶Üjj ˲â\-F#¹Ñ[¥^L€ÉŸžÆÖÚ„•ÈáÀ»r[_Ä3§¬Ü(*Ǭ5P8ˆH†¡$‹Ü·¼mZç á|-ŠYI©’ê~l•TÒÿÈ¡íüÕò·Ö芺œÆ+eåSq€Bè•[ªB²NaeÞ–¸b„¥€1ÞU4;…,R6A>0>Üu)!Ut¼­JÁȲ™Àuì¥jà™ÐdbµÎ«¥çz ){ZÞÓ…ýÁ€’Œ˜¹c<Ò¶¦)mñ²•K)¬£’L¶GS¡­"À'[yµúÆÈvŸ?ΫÒž³*óˆ (›²-`µñÍc+õbŒ¬¢‘f8Ϥ€{ ‰u!똶†q󮽪d™[™ccЉ̳òÞ^UØÌ‰ã‘UÍO`ÝØ¥’!ù …duGö MDŠp£r[X–žI¶‘˜æôø¾ízñ‘*dmA‡lËòŽßúºU$AzWu~”¥d…l+²^—þ“*+µ aoè¸p2Ø„†¡ñˆTÞºm/•m]øluº¶µ£gÛ=¬¼["ËÍüyn†)³µ2!  m‘þÖŒ­¯k×…¬;1\ÀZÄÈæã†×÷r€Þ³éÞÌ4M¢Š·ºÔâV¾UÉâ™°òi€ª’)I`›sUp)|ÃØ²“Å›á<¥hlZžB[k“tÀôMX¯´*wÛK’áü›¤iŒÊM%ˆm3§i<€y>­¶1¥6IYÛ½™Éšn €^‚˜€• HYnE)ë¶²•P"ô&ÃkA3C ËDµ^eµ®<÷]]b”šÖ•´­iæUaD²ZuwŠ4uäÀÃ?Ù¶¥š–¦ª)LOŸ-A¤vV…‘Ý<\ >ç4éÝ£ÊZm™¼†ñ>}È”çsç¿lCª bÁÔHŠ:Yc,ú ö,§ì}¢ì<ÄUÕFa2e ­(1ÚI)¤_k[d|²L"µˆø˜ÇV•ŒU©Öf7¡µ¬BŠ`혭“u{52À”@wëûpW]Ã'†Òðdz ¼µ{ÈC£cd[šF’Âü=ðß«×:½µÀ)MU [$Ïw¥˜Çꆔ¤m)Ûô™Üüç»Æ÷`GÓ°6CÃdãUi“ óÛù7<¦¨ÄjŒÿ ¬JìYP*—Z¡­¶é­&¬WsòQ[{ ²0sÀ§.ÌÏSØÒ42Y¶Ö|áz!3Q˹Zik-ðZx2‘êL›ÀVÐX}L0”NalU¶ H–æP6¥Ëi¬Rxd­1°.Öøl3©ÖZ•Ô”ëˆ µ°’ñ7³Œ­°í8²0ÃyÊ"+oªYI©2Ìœ×wd […bš…¡¹™3¡Ë [kg%0O|Û:âÛò”EÆ[ñHA£QŸ‘id‘²®‚@Ha0ÀäeªÅœ÷BzCz·1¯Ø´&w„ÏßáÖ‹ FÖÇå¿«Ò#ßal)ÚÆtöxLž‘+i›§Ö¦µÊöÐñ«2?«.ª‡Þ‰²¢\pØa‘i”s{‡,e¥çim¶=S¤›ìršÖš yš¬¤˜èßTR¶b“¶gU¥…µÉ1J¬4È0°kQ^ÈJÙæßYàž²-Ü–,ç<ÖnïCYbnõ¢ñõbEZI„‚i¸í“!¥D2æ‰ó¤™ãE­eSbÊrËŠ^–!†&@¸Æ(Åad}Û®5’Fä™md8%ì}ËÚÖ½6€Fd‹ìfnŸóp ”ã1‰­e­¥d¯ÇÇÇ9çiÕ‘LT˜¡­”ÂHú"}šü1ÂT=xÃÁxJümrº„²m†µ“™4FÖnVJ²@[UÅÄ`ÁÓZ#kÛe¥/†À‰„SâZæg¾ë–’µ6ÃÈÄRøÍÀ9Œ'°µæïƼ!ÎUªÂô4¶0%†D*ÂVÙ®=FJ±Büçd[½¯/,ðjº…Söý"¨ìLém€)Ô Ó1Úf˜¹5À¥0é÷šýùŽÐÅ™ý7ÎiŒÇœIdÓò¡„ ˜ÆÚxâ=‘-ŸÙÚø£þ^®-¾-`ËßÊY;@£9t ¿‹ø¿B3$1Ab2%uAò´µ’ùÒ¬EþpÑ)àÒ$ñ•|Þr[µ"M— #¾Ž#üzG9óJ´ÀÄg2™Ï ir¤Àˆ‰1pdJÏÅ`ôêPgב¦Ún nN&Fm6Yy|¸Á¬”øYm+o° Môhâ«ZyWÍc ÉtQ‚o5R|]dÙVbÍg¤’R•ÃRÉJ­o We†]å‚OÊÎÒ=7‰µ.Äø>0=[zŸâ¶U÷/i(ô€’™p†ô¶²fnÅ/ŸU…0eÙF²Fnæ|6s€­XV•­UÖV%’•W«ÇŠ_È 2& îÁ:žX¶îæä†±x2…‰SΜ ,€TkŒJNñ ¤¿’ÅdÞ0xñÚÒÛÊ @V¡°5Xbá+Ô3BÇèŽjëtš*×é\¤VÙ½Jlèþ ÖZ_ïC…&úf" ˜²B«l…ÖBmïpz‚µ&à@ ³Õ‰±Ò#›_*&[!51‡H%E&¢ÁZU1‘%S¤-€RÚFJVe«]7öγU¹èêÂJ“ðçÃVÔ×úÓ—X U lUýL;·²VzÁY=k>ÈR5ÂÓˆH?0{y`$¥uÀöô¸E07Ú5a€ÒÖTB¹ŸP3g[#k²Î².ù·åœ†öâen+Ö‚Æ•`SYmÇØ³õÏ<ͦÜ„×õ˜è‚¤@¬c×Ë!Ãî°%`Hn²Re3³²½–g|MUVüJFÖNy'0 +l€žB–*Òã¦1ª-5’@vFúd%üÜdmUá³²RË|Í®SIâ té–ƹ”÷ï ÷1ÍvóŸÏE˜¤'£S6ŸZÇ준(e-«Æw]HæHQÓž2LÖËö¶ðUŒOi•ÚÑ2ÜåzORZõµzåŒæç¿P3,‘â®Þ¶zã{K0}ô‘PÕXƒLÜCßÛ´lb|]9(´¾ç”Õ—Œ@àœ?fï+^ä€o6[sö·$e›M‰È¤2-0?“ÈšÄ*%4ÄpÓ^ú3ŒC•e…0™Tµ¥lèûÒÀÈýd…EG®Y­ðXܧØAdN¡ÊÙËâFÄ0œÚŠ”þjÏ’•, åÒšá¸ÜX¹]”köùš€Ý +Ú†e­xÌ9ü½1÷ïrú*ÑÅ {ȺüaOÍñyÒtg‚ï·RMk‘çÖeJØ6¡^x«.J’Ün‡ó¬M%‹·!&+<,”µvp­ã›Ÿ9 ­]TUÖÑHÛ‚ƒ¨Q ‡ªðJòÑt“‰34¿Bd})m¥„ZÙáøl#}*= ŒTåÀú¦7szΠɲR°kÚñ#'è8H‘¹’þW¹¶B•XJj‡ÙÙÀ±»YµK©BvEe¥˜ÛêÜ0¥+]»Æ D6 àk¡#'@2±òÉ¿Éu¬‹mw^£4S&¶Žy;"o£¾±Ó¨2ÕÖìÙšD•T[Ù” ‹ >¥ª42^-Ò*Ô’u±H[$F0´E¶”[E¯Áçã\Š’Un[«{®‹Ÿ½T ‘»ùüs«Äj[¶”î¶a‚>>¬r“"®Ð¶‘èùé~4Ô OŒTÈÊÀZä‰ibØÀU±ÊÍJv.â *LF¹ÀÃ?å •ï\Ü•™^I†µ†9tWRµÆ¸m§±¬lùûm[ PÕ¡*§Á‹ºÖ4P‰ª¬t¹Þç©yoµ(l•7' ÷Gåm)­B ¾‡’s¶™X hZ[Ý׺9­"±h[ë à+,[ ¼­8Wÿ•8=e‘à ?_ñ iµUN§aŒ& #…’Öך@-P +wc®®4óQÅä[w¦Z–Æ Ð<V…+úõ 4^<¦+â‰Ù;y§8 Òj€j'F*AêÕ<”^_k†EÛãx mM®D9Fa¡Qk%sÌ.AÖñôdÂTV$, lÍ!±mÃïG­R(ñѳ 1¼8e§¸–D_½¨µ¬­,k«A¥ÂÖì:bH¨åÀß#Aò1™ÖÚò”-¥¤ÙdE]à&É8ÆÙX)áÙlx€-¬­¬mVL05ÍÄZGd¤ò”µ¦‘ºÛΦºˆ°lçRÂÍꧬ¯@ªãtH£6¬‘Úl‰ñ0‡[›“Ubñ¥Ú6¿Ö”ÖÝŒn7Ùõ2—]£ºóaxÏÝŽ$Ëæ@Ó$µ–ÂTn̵ë¶m;2 nKS/åõŠGbTY›p˜Œom~ “4[eE>LÌ S¦'ˇhN²[t¦*‹W¥ÖC„eó1†-̧'¶4Ä4…Ÿ®lA#U i¶ÊùT%E†©Va€?l¶?kÙ“i¥Áïtmýs)‡’êk3`ŠN¾ØÓÈêP´­ÐÚ¨ ™Ó4‘”˜l»OŒ”ð©Ç³MleeëW)M1=°m“Xë(„yêehHxåøVLµª„­2˜àÖÌ™à}üéi´³uÿ¾ l)ñ˜¥TË™›l½VQÓÓû[V óoUU¡u©Ì«âC‰©èYÓ¸L¶µË“ി߇uL «K)3;]z +²¦µ ¶-Ûx|Ddn¶¥ÔŠWÜõÖ‚†'†ž&+FU§‹'ÀЋ ªzm›IXHuJÀVw6@‚üÓ7³MLŒP‹ÔBð„ÛZ‰€^tXnR 1¶^øô°È€ƒW®o %¶È=1PØfî©Á}9HÁõRN¿UH‘Ã@SQÀäš6äj‰ñÈšvLYÓ²ïxÀ^3¡„½Ÿ]²¾<1¶¥¾ë’ÕŽ ó•4¶lÎ }‡T'3‚ è¤Rô­ë0ئe%h¬²B•-€ìh¦ÈÜmw@bøH«m§–åÆœÀgµ‘³mÓÏ?CJU²ñµ®»B)a[¹IÈ0d²ñY `ž|Ê&ƒÛf¢ÜV*ÉJíR²yb€œU½æž‚”©Å˦T¢\ÄîG–?\kkÙ.äï]d‰ÙªUXm%ÈZXùô™š’@Ïj$—¦’þfþ<-ÞM àRU-0Üj-% ‡5:¿Ž˜ÆÞ†ZÀÂÒa€ºîåi¶Åtó®y¤÷ócM™¡­!›ÓH¶Z/Þ0¤Ìspjšž#žL!ÍIÐY²}M0b“ÀJ„©¬máŽ@V ¨{—i ¿î¼YÑ„sÎ)0¦—>ƒ•妶.@J S¶<_Föèžo´Eë[ñ~0§OS6gL¯I<ŽÈ‰õ­¤(WKߨ}½häY$ˆWÂG¹˜-Ü„²;,†`²V [±ja‡â +ê¥]­ [M¥&V \ÏÉÞúLu3ü€eÜØ 3`"¹™ ža7Ó–ao- q—70Áœ_[2|£ÒÍ(Œ¯Ð:q<ó·DëÊ o‹„Õf[¯®Ë3\aÃ#+RÚÝ9Xè^Äp<ò0†Ø‘¹ÁL¤®ÁçU‡çVÊZ¡”WÑV MVUñg‹d‹Èò‰¯S6Ašš6Ìèj”B¹¾]&¾ª|¬{ ‰­4‰šÄhʪUë‚ìauX[@ÈÂjï÷LÎxY>2€„}äuáÓ¹©*@lµÄ¥²²Ú?SliTMC‰·J ÷U4˜U*[ë‚?>W¯Ò½©ŠA¶=hÀ‡¿ŸDxV#æ ððÝ€Á6rÙÍß;£VÐtc@[&€ªÂV” C nªH‚“š. >®' ^aÏhªøÉ*ÉÁZmިɪ…1°XIÛÖ>hR¶¹^ÁÜ  ]áUÆ® À bÓÔˆƒHF Ø(wêª:Qc”¢—ÂX=5þ‘žÏ:çß#Sh˪Ô’©ͰUjÿ™?bL3Ô—¡kÔ+÷Þ&£ß0Ê™Õ.¥-¥”C –EÖCÿ㯿þ"’NATãwÇ*›OÔg >ò]º”±8H aKP8$¾sâ…­”U!1Œä3¸6g Ýýžê`®F•’&Üu(irk†uÄw_5j«V zxÝcº%xA P¯ZÓHÕÑ*ÚúÖ Žˆóq:µø¾Ö“UâùPÖQ¹ ±4…’}@—œaz>d·ô³TnHcPP"+„éIX; í»&Nƒï€ï` ͆ñEúia,¤˜ ±ä¦2-LãE•UEVIØ–[ÎÕ*¯ +l 2äxÎp$LÃÓÖq"m» ²® ãi›2FU£ EO öAˆÙÙóé€ =§áÙxÆÃcˆÓï{¥WòyKsK£d€Æ¶Ÿ o<âF s¾§£°UX‹†orØ—šF¶Í¤ŽL”c¬¢mnÚª"a`úZ¤T>%MÛî!l<@JT8}ã%ãµÖŽ|‰³(!(:Z† Yþµ A~+Îë —JÜ'½’î$¦B<`í †1g[«Y>ž BX/dq*/cUÈÓ[×ÿÚÞV$èšSJ9ƪEa¯ŠÕ¶¨ ’[˜CV™Ìüj!`’óÿDgSe:‡ÑFp‘Ò&Tœ»”€¥(# Ö_6Aï:F V.By]”+l+…´6Øéqßu&4~ï÷} Ø2,`¤*¸`‚d"4•¤¬ð1½YŒ*aÛól•LˆÎ¢\6·~Æt{é—²¥ì¤Àl5åà—Wk4ÒÊmáR¬„.VŒUªyâ#ëbU+¬¶eâl‘HéVî´ráf@ÚòœŒ¹ ×½ «}×xkMÛv¢‘uáÚZûLM k‹µƒ› `²->Ž7Ò4¢íšrCZ=\šÌ§Á¸gb+°•ÔiËŠƒU!¦*@¨õÐ˪…—M¿¬w,ÛLdÏôøÏþÓ¸*ÑÄDÂÖÊhë”Ù¥Yo[¤*)ˆG@IDAT+2`Mãä5Ò©;^Àj~Ï–êoü#ûRžRŠÞʳ[°í„ZàßÕ¶V¯ ^$Ækzæ¸a‹+'KfžšJupÀ¡¬ªÈ:/e†˜Z;ÔleE(ß é5Ϭү5®öVœß)k”Jò$Õ6³¾ Œ·%«¤ñÔVØJ#2±Ž„ÛúL*RºR˜+9 ÌGJGkžs™!¥üXµúL+¬Q«òbJµHŒhk]Uïý¡7°w¬ëô*z] [<Ûx+#œÔœ¬èaVRî6Akå°¬Öd«Ué+©EÃÀÀÛWá9Ø |)²qq3–—„WeBØ$V¸‘xÓXj°æÑ—¿³ÀHÙÞÛÄLÔr“"v-*/T²b-d;H­¥ÚÖTöÙ´x-¤xÖ£– °ÍÐ*xâ5Å›ÜV¨mY© ½™7D [¶SVeX9=ÿfÊ ƒ·Å+‡(Dò´ÝWŸ’¢Fe €0ž€gåò©…c&Û€ØkF \;zJ©ÚÙ >YIµ•Õhc_Õyñ¯>Ü9˜Éàô:Z 4Ê|¤räôeözä)ÛÇ–ÓýXkÝð÷Üçu²µ49l$YÄc" *qi°O–? ÂÄ'™mY 7¯°7- [ÙÜj¡<Ÿ¥Ô"{@ ñô|ðÒHi`Y¡£h¶â뮩Á0Ûy)—‚‘ EVb<ßØÖŸAl¥´ö2GæÿT5óÉ(i š¢a¾»s¨ '®‹µ‡NO`x%õm› öò¬u©º¨"àÓÙW¸›ù‰ [|‘ã+±jÁ‡³’Õ—¸H¼”§ö>³5  ïEí 1°ª¬àȶj|€eÔëH 0Ÿó?‚(ª§VlkÝI±9Ô' 2aˆF‘™Ëæ&˳ù”·â<`A£Kyù<]¸Ï•Ô&¬•˜I ÕÖ7gæR]kµº‡iš¼yô ЈÎâBóÁha%h0«P5vÙª"óhý^Ø'ªSGU &…iìuO£Q ¥¸­ÎEÕ±ƒèÛÛàê«Ê¡­Ñ ñ•d XÙšæ#ö¶HÙJ nüŒ„ÃX)×K-\S@ŠàžµT×X*¥5žXŠF¡91À -ÄnCa-*Éœ‰ Á¶@ó,¶-CÙÆ¶JÑÈŠ¦*kKl¶Ü`|¿aHyšË(+·%°˜ÌHPª±+ìt5í6àdRñ懲­ÚŸ@x µrÓÑÌÆb›oŒl`(Qk+TÉz±ÛÊJašÉS-ž’-^¬µT¤hàœk÷6•µUX;[%­y6Fíê8ÃRVSeÛ¶ôz¡KÎ}6KÉ" hÔ z¤5Û¬\ *Œð¯õ»( ½ÂÓã> >¼ÀHõ *¿ÝNkßäª8{?m+´¦—ÂG2L VÖÚ²°l|À*˶*)8}ÎUYóòÔ‘ÌV¡ Á6O¼­€ûbä/ˆujš,ž-·#ºA ˆ•”V™k$a‹×QøÒइë‹ÉÐV¨Jdá&Ñ©6ò܇¨JJÉÚâm=èž mnN7ç©¿Ñ£¥:ˆj„”4Ùiö½(ÙlŒ²¨*7bۢ뢡ÇÔô›<}Ëem•8}ÑyÍÓ ™tŠÍ„­ô&¬En‘õ’"ƒYž¹-‹Í µmªJœIcÄÐ3>¼†¯WþægU¹ g›X9@³ah`z©Â¶è˜VÁGV¯Ìëˆ_ %²9ð÷)ÈY;2zïÌôŸNÏC©V!Í.œL;Î@&[æ^Âx[æ0Abh›ƒí¬dE†áÄéanéiD[YSYû–ÃÛ:Ú•œ‘”8 È8[ekD#â¶óRÖ±^á.^d¢³Ö ÕxêžØÚV l¶måy¦N ÊTª„”µi‘µÈÊA2ït”pz[b«Pnµœ1s[í5ÿ˜¤fhÕH»5Šù²“S/4ð)'l•¹ êmaóÙªâRh/¼¬ÄªXu6$|óŸŸ"jùuÎJêÕÚ<°HÌ„C¸¾94€‘Z¤¯u©õÍ­óšÀpP ÷ƒG¹­Â5Í  WÈœ#âé…^!ý°*wiluÄ“u…€¬èó/gÃÖ‚ÐrèJ­d}äTÙzÝæ£D£3ÜOa'ÍYU@áîDIÎõ¥×ګ¡¾¶ÊLÒØÖ#l•ĤÌ!e)i´šîêx:N2k›ÖðÝ|ÎLjô³’ÕÎדT%Zð¯§è~ˆa“4`KÖ ”J3äÓŸOxvŸ†'`Ðè(…iŒšâëh[/€›ˆ )[ÊHY<Üö«ú#þaÞmV19°À<=h-šVªÚvÛÆ³ ä¦<>ÐJãÿô ÿ'«Ê+Yßm›Ç$]^ ±.¶ÍÅ[CUoEâ]H€¦G)«ÉÄÑàºàÞØ”‘<ëem*YU=k%ƒd+3—R2žþÖBA mتJJDb`×ÕÑd©]$SI#u lùXeið5êûP¹ªrd«¿+,Uwzµ4¹!ï†OÑx¶R9[ECzã9¼gLpìn••CóÇÐ SÑ}â1R¶Vc èøBs¢xkš«ý¿õBæ–ƒBb] #h¤`-d=boTí˜_ÕGYyJ¡VîÇÖ–m…¥l‰á†q´ihG_•UÉ&éï:u‡f£ìì4w„óš5'«™ E÷3òŸÁèeº˜G#˜C—d ,Õ„ñÖÊ­†i$×bk$]øÏ‘@rÐ… £Yá™”O“®¨!e.ÎùsƈFº ÏñÖ±u´¦G:žC%éñÊc¬HQ‹¶VÛdRm[ms#8e߬-ÏL–ÚäÙ§¹u§£ ïv.|ó' ”ò¤±À7‰•Ò–¯—­h$Œ·¥´<”çŸÈ1U&îí§³ýèî/|õ&KÏ Ö¸«±Í7«Là^唎Q¶^3·UÎ*Fk²f…miÊbÑFÍÓeá¾}%V¼Ž€’æ¤ÞZÙ†¼Ç\ÖxÎ.š“F/)Çì¤VÖZÈÚfbÅ Rh|œ`_ÀLªÕKUÃÐØ Ub¿ˆ463üê‘Ü’i!d[3ñaÖÆ’2«ÖÆCŠf´RŠ›¾ôYm­l‰cà•w'¶R¸U&úrÁ“±RØ´ô²š0¯œƒ°¥/l+œ?Ð$ý4"ã“-¥m«B`AÐ;>±Ùø²5‚ñJ)Ä8H€ 2O *VO©K§CΙÆ¦ÇwX a¬‹ZTõC¶Í6ì|*Ñ¥iµ0§SôP0°lz[bóTØð¢¶ò² ðk±5AàsN©*C@t™SÚ"9Īv{À†©–^ÄcTª„”Z̓‡xâȪ@ï=lÍ*>[«ë5 C<qzÙ1Ý&­ã¨RnÅW" ‹NØ(¶U%4õÝ¢¶‘ú@ám¥¾Eg¤®%™µ‚ÂÿÇ×lÙrKxè<ðòòûø¤¿*NÑpoD(222¥ª½»Ï1$7€Àñ9°ªy•îý„ÛZÉè…Ý ÌG”ÍŸLG¸ÿjY-êh‰ñ”Ë*Ñ´QI*}e+Ô–5‰ò¥\‹‘0‘™c%M•`¢‘ÞÃÕŽ8½AcÝÌœ1"¥ÕUtتÊ*á\•U\×_/f&§Í}4S‘f¦if$&OX*7kú¶ÙªRb-…l¶Í@V•ÈÖJf[mà¤ßû Xº@¿)òq?¶œU ¯íyï½Ñ³e.Û0UŠƒ€›@x]‘=5ÛRé­RÊñp1ÍáùÔÀ ¬œþ›Šçåp¿–Ïg3A$[>”ØÏ#µ{ç#Y­• âkG˜›m]œ:±-ö¾Á=ýdªx¦¾X ¼î4° JGÀ*Ë0YJ+Ø äY­r•›ÕžO²Y¢©¬p—°îyF2)˜T…ªFõšçœI+fÛ@åjm™Xa‘ÀyZ+DôV7O¯¯1·õr"eÝF©la@¸"=5[8[]hs ~J$ÏJðªhš­y~ûûï¿]…\ÓHç®h ›,‹”xz<€·r”Â$ã hï#Oâ ¥”ï¿n9çÜ"Uål (”²¦·âµ³²ÍÙŠ×=`[UcàsS(¶­ižµ–âæ©>.WVPö)’õ‰m«ÉÙ¶*w }ªaVd²YUn’Na[ÊŠ)˜Û YæE “¶RáÉ̃áÐ%ô# N™  ˆ‘¸Úõj†”ÝO+Y¡ PÂ3=Œ´v9ÇM®;€¤DVmñ|Z¥€ âµ0­«c.õ=EÝÉVƒI+žÆs±…E|í*l¶.h;#YXyã°…­²ªòÇ(´n+[àÍϧw s‡:SÙ ¼r+¥Pó' '«j+Ø6 †máï·pÙ!e›ÙE¹¶Ç÷ŽjKÉ$1R;2+Ò*Û4¬¬u'Ò"Y‡Rk[ @Vaí’ÙvÕ4âŒx<ÃK)©<§i%¦”òFÕ7ñV)|[€>ýÞ㉘\Àl•È^ÔÊ¥æ£\lK™þ8Þªžo¤Dºù4¶xc<²áñ4 ÛNLV/«”/U@ß<¬l3TBCXïiÎ7›¬Søq¥ª¨¯ÓIa2T%vdkMi6Û SJyóé»®¬¸)œ?eÛ|l“)ÁcN «k­/Y­³ÒÔߌÂZS*”íÞÚ2¯¤9aáºe#îÄÊM‹îªñ|Xa6’¦"Û2QÇÛç¼Zm Râ¯êù8'«EXÇÖx Zívœ4Ù*Q+%h`úܬ Ù¡òü¶S’)VõÚOƪ‹uKn®;A‘-‡dH&ù«•mNßT|Âé5{¾ȸ1ñ€¤¼ð~ë0½”•[†áæŒ!P[ËÚµž²÷«&O஬Bë•ôb¬ãLJÓz!³2¤ZÉTuö¯§’.§”mµÄ®ÅJŒ1L)7€Þ ØÒðgB)à`QŠƒTk&R»]¤h¤¬²•dåDHÝ¥¬xÛ|êb§®Kµ&£D¦¯¶.°`X z¸-lpݵ«QJÛëñ,•ÞJ/$è#‰k`¬¢I€¯Œ©ŠI“ô86IÙR‰@ÊÒ«ÂR=/æxb|J©j­®m](½{ªš éé;æ·?þø 9s¾Š1DÕ¯lÏXvÕ²öxm¬‚@Y@0À²R‰YUšHY©1¶º´­nkrÎnO…é{;Mn˜ÄR ég˜­ZX¹UâFµEbDŒÐô"‹q97sfp>ÍV‰µ¬œmóñÄóé‡k×úVÕ«Ð ñ7a+;CŒ-‡›<ð È¿¿ˆ‹L8˜Äo&ñ–(±%`ÒÓÇÐ ¥€œs o*@;dY¤-“ªÛRÖ"¦’13©¯lãµðˆEnœAäk|þS¹¬8M#5p§à\¶#[SêU;ž¢£Q¶Ëf®ÊHÌklY)«-^6 |wH°×òÛ/Ìo­ª9Õx+ç¶¥¬²Ilab혜ùîãV8ˆu#…éuTh+l šÖñ¶µ¨£—¬ªxõ0Éúø$æ,”°²vXå²¶J݃lóà ƒ)¥€ú*ÉG–²cb2A’e› 7Ù<³²e(Òäœ-C£Öq¡ÚŽÆ\–ƒ•ß5i04¾hÌ"ÞvÃa©:fb$|zäiËDw2Ÿz%׿y¦øô[UÑï˜@gÏ­­sÙælE¶ÝH ib|ž”ð i*Ä+¡·uE@Jâsé÷§Ib>u,EÏ-ÿZÈŠp½hªŠ‡òOØæëbUb5F[øºž‡¦w.Ñ6X¡GoÍpzŒ.Lðlé1²€@ª"€™7sUư*±bèi¬dµ¶²5²¦Ï­B»FY‘¶æñc¥u”RôHñrσh…e­™LvÇ<ïçï¿ÿ^y…š`|)µFÕ±!;¦í<;Æ`²Ý¤Ú†ÁPpÀ®¢”_C“!”Æ®×#IÊ6FT…ÉÍÚ´”H ûáëK@VbUk%¬Ä9È:”˜X*F ܹRª]¸´Rô°5ÿ1U1QçLÙ<éa¼5`›ªªdªDVkÁYmM1€¯ @¹••,¼³²ºY«*k©*C”ã‘@µ1ÖJÒÀ² ƒ}ri:‘-A!;0 :;PS€àÇ6滪rF&½ µë8¾9¥t‡¯l)&²l›“ s¸yÔ YÁS•TO­.xÏâü@²ªt*{BÚTIÝ—lsÐHÕ£ãHù*¡¡—M©½”­è¹fµ9>V> +·]¯H³ÕN SŒ‘åßõe˜'¾­l%»Ž|Ú6›ÁºÇ&…*Êf˜ ;Üxn,½BžH 7˜X»f\{)%¶u+§ì¤ YÊV­v4ÕÖwÛYÉFb6›Il×±. E‡ÒeQV 7>À:²ôR†lemEl™TB,jÔÖ´C¡Ö14 â¯ñóÉÇÓPÞ¢ç§ãùù&"–êð€_ʦ•ƒ»ØœMH¦*ŸÖ.±l©:n­ÅWÖTÝÉæÿêK–¬IŒˆ­Òó4!Md·!P%+ªB®EM­1Jˆm½{ÕvÞleÉdÖgb!ÛÙ“Y‘4HUœÞœÜÍÀ3- ÜOÄR¶¬:£`†ß.4BIU ½˜Ôš•l÷/Û`Éð‰Ž&› +JP 6 ¬æ ˆ1¾›AX14áÊÏ¥ °ƒÀô¬ªRnþªbÒ“I©Ò‹€¹m—Ћe»„|ÔúÔW¢‘*Äw„:Ú¦¯# Ãú&ÃSšÁV6&%ÀœÀH@©yª2C[/aåJ…ý- ªÁr@ªµe Ð7@ÀË~ý (­H¶MO|²ÚÙþ(Çh7Ò67-zßü;#k’ÐJ Ð4UØHÈ"1Yb«Ú©;i>ÄÂ:ú_Cù oHzU®Ý=\ƒç_ÿ%+2ìŠÔv¨uX)—…óTÛïì@&ÊßH×ÒØp!›~nÊa¡¤*8=[íl× OƒñÐkJàD·ôùÀf%‹´è™`èØÖ~Ç|.kQG)>ÂöT¾¨ÐgÀ<»%²ù˜ÇYdâÙŠ<;>‡Â–ãSdR‰UÁ4Z·Þ)Îo$ãáx Ì$ŸH&†¶Ù6R°*]xª‚Ûëq>¢ø Q!7ŸÃž^Uªò3çQòyóÏbF*ùŠçà34€ñ`ÀZŠƒ^"æ’Ø‹ÚÙ3Qø}ÍÚv¨ÜÈèùtX[!›¹¾"7@£U±Âà› ÀÇ0Tž›ÚzI™¶Q‘ Åd€ˆlZU³ ù7'’½mYβ鳭Њd(Ö:Ð-áùdb…Y97µ¢­TÝmáRùpðjmUÛ‘»JzÁÉÊ6“ë HžÄ|0Rp2C 05òɪ{åHñCƒÑTyç寻Àc:‘•'+A¹€Ú¯!Y“(‡Ö)ʆYÉj—›US©¯^–¬‘êb»¯k ‡J8‹˜”­HU@£*6^‚Î[k…]E2åJš v‚¦vùà1Ý6ÜßbªU.èEJ)‡Rk+˜cRßÄÖ i_Àø[z®´’¶0dCŽTˆT(húí­Zn·ÿóeK0s)£R: œ¿5Yf%[áÈlÓ8iJë|–U‹7ªáwôHµ{.§É‰mé¿«­BæÙÎ'çº#ÀpvW’•¬°ÄÔH¶ÛÎL‰r7æž `©kpµó аMÀ Ù$±@:{<@Ó5UhUÞ¶€•2`­˜Ò601Î3}3PâeÕÊv®|ð¢¿í®Ä$ÀÃô X 2L<2g©& i˜l9ðTØðß @Y|]²²r“jûMám9k!œÔ:±”PUí•üÊ")õ¤<î½ =©†ä@Ö pUyÖ=A-ð  VÖâ ­ûñ^TÀ«"Ùª"YÕ:]‚z!ã)ñßÕVwñ(l¼¾‡5âÆ +iŒf³Šºä¦¤Kva¡Äuw^«àÙ Üî§ÏÂoÿú׿jPÂc`”T™À‹/€Y¤1#ÛUí÷ic5“U‰3‹¬leË$€Of`K£EÓÅTŇƒ)è tÁc²J&åØVí¡¼‹ë… ë8Öët¬ `_+[JV;…-sZ]ã-:2[JÁ¹²Â®nã¢/‚Jl•V+"›gc¸¥NGŒ %p§º"Ý™³Õ‹ €‘Ü80”µM©¶"s¶pr°µÖ‹‰¨©•³B¶°—ÄA`Îøô)s½[g*~(‘c |cèµaÊ`Dç5 °Qe› wغ·Ž‘¥x%U±¤2´ŠdHÊÝO7#¥„ÆßQùMÈÖýÔˆž•vV[Jk%€‡Ëz+±Åí€lÛR ŸmβR°”²Ú3÷û-U™ÁäÞX%p-JÁ^381À!O-`¼­°Š2ÁM8”ãha‹W˜¸ùáÄ”ÊOå <tŸe»±æIƒ‰µ@êe$_p/L/Õ ¸B†}˜ßÍË6<Ö”sU²4ü…ªÄd1™›Ó‰ÈʶÍ!7¼-¬PÀè“ÅG­Ö’eU_¤rX(±=w6Œ-«ºx”°!­W~^?æxz˜,Ш­È@>Ù®)‡0CÂôH4^åÖsÕ¬¤4µÚvº|ø” ÊœRIïdžÈ¦å£0U<1bžõ"îAã‰Ý0ÂÛê×Ò¥:Q&NTí¦jÁ\Šá ×:ÿÒ7§u³‡GÙH悬y4⃑%xÛ{åç×îÞv0 RÙx+ý i¤6ÙHž¥šÊêDcêè¤ÕZ¥&.«KïïÖ §Á¶QË2T.€˜ñ”ßQ»gï÷%íV™ØÙ´[˜›TsÃàEs†k$›ØV(HØðÖj‘0å=Ó¯¿…Dư…²ôÄ@-@å #T%ƒ3)ÛêøN×s/KÖw©*í¬ið°õ ôd¸¬-Ûp:S­oG nfHªµH)ß/`hd«ÍÊ(ªšà›JÀP‹Ä|øc§Fá=G…H%­¶ªF¡Ü[§ræ#eKcµµæ¯œ¿ÐÔ…»ÕiŽàÏ?ÿÌ (£“°­’—š5N@ÉñŒv£c(¡\{Í$óaèEW ›Ï6 ’?21[XÐ4²©È8ä¦)hºeí”O©–Å7m²úJˆl«Š±ªN`uûLJž'’9ÓÿAB)b6<²CõkGw(+”Ó”…Q–ÆÕéÕä º+¤J«’Lò±vY€ƒQ«êö™gŸ^Én†mV[ Q+Y/ Ø<½ƒhäw,{€¦Q•4¢BÛE½lKÙšÙJÜ%à YÀeÍ&«Š21ýLˆã«•²…QÖTmUuÀJœ­ñÈÙvåug(%hægL ßÌp/RÌZËrãIàsvFLcÐãe)…ÂÀV ±ÀlÚôñ|:šmþ¶ù7IVëÕÖð1j%‚¾“¦ñܹøDdë 4õjŒ 9”jK ˜X1×¶vaY&^òÈZûˆíTù<‰á¦RÕÖ<=ÛôVaJ)¶ÚuçõÅL̰?èJ5&™C ØÊoa,ŽôÉêÒ홳¼-~ím;E­gnÔxžß”Q¿!kkí,+`  µ! 8 4Û×VVà7‰;$h¼ÜTY‘ÜRæ:½QVùLdxª­Ü¶És°íCÑdØ´ÖM®–€PÂßÊÁZT#[ÔBÊ0ÖjÓpdÎ!½‘ß·0}šè˪%hN«÷Lϯ¶œ1VQ¯Æ–zÇ-2ž}jG,*—ú1‡L”'#ôM¹g‘¬97Ìd²µ!Ó("µS76¬¦é#–^!e¶À¹Þ¿þú‹JmõË+5 $k‘RÍ÷$p)O.™•¥Ëª¼ªÈÝ…ŸR¼•íisŸ}$sÖ&^w «ÌÍ–f²jµóˆKÕÌ%ÖN”'@RbŠð|2>akVñnœ>%`K`§öQw3Èî-™œ0€÷‹ÝC½¸À]~DZÅk‡Ä0iÅÀVQ¹­Ø#nr«9ñÚÝü*´r3À?·J¤ð ÓXñ ^Õja¤UwÀa„¦ÁβVŒÀÈü¥¸ÍIÊÄ•'ÊÕÙZ‘ùàN‰ÜñMX7d¼Bb§9Ëf‹o’õÊValÕfœÀ*ðÕJe‹„­ÍsD¯~³az4”dZø¯ é˜Vâ²V˜†R¡­, Q­CÐ8]¶V½¬²‘­ù°rL)cÎù³ÂÔ“9†@ |ˆGºi”þJ aAƤí< #˜°•­5ò ̉iæïÛ”V Íʵ£0«4ùt±§Ç}ÐRLÒæ5ÊY¶R”•LÓ–[·m«8ÿ•Ø*±%Hð5%|X8sð8ÎD!P»†éÛ›L£æÈ0‚-Ù¶ ð9Ô´^ª*ìhëHy…í0›ß56?An­Û蘲±5ŒUèkM–ÒÈ%l$UóWÞ1°hÔf»–g¡„á"‡ª¬é{˜t"_*=Þñ…Xý÷¾Xñ×Th!u†xTÉr8CÜsqÈĉD•¬* Z&‘V>¦ÕK-ܪüÌô~ÉtAÊÂÊk „ëÕ²øá0±ª4sÌ<‘YudRH…þ‚ƒ­‘Àüôõµ4¢áeÕZ)}iYóó©$’¬ lžL(“µ¦„ñðÈaLVµ°Ú24XÑW"ÒYðfv@U²Û<š¦Y/Uad¸UÕ4óúÈϳîmuì8”xÚîg’¬T¸ùÇ•)7­ò…Ád…ÛFÒ%aV½ŽL™f2UÖªò¬ÜJßä=Ç4œëhkX ‹µlÍ)+¥ü”øßH¨MÐd¶*¦"áj`%SBƺ*«îzŸ·ª¾kžsÎPa¡\Ôxéç?ùtBûdVVç<Ÿ¿nǤTNfT³I)TÒ]H”ÀZ¨-0‘JjÝÙ·Ì,ð"í\²wKŠ’’o%Yz<Ò<€T‚ÚÕ½B%™¸s>jmÉ3vî‰á‰©­‰m•Xý½ãÚŽÜ—^†™¬)½@ €^5EòÇV—ãæá²V曳ùm3ñ?BµÝOnx«hˤ¾­Hg”û‚´e]5½­cí5KÀ<7…@ÖÎ/”t4]lñ¦À™§àöê {pJ`åV—C†q'jc4ª©z•$0[]rPÞF‰ÀäÄ[™ÓÛ•hÔ‘fÖÅlúÖ‹Œ€R /ÊZ „l…µ 3@‚&¡Ü0þ /8 ­ZØ2¹ôUI…É£âç,›¹ee `”t· 0BÊ0RHÝ1€­¯Gîs/å¤pJnjm»UÜ‚²0Oµ cmB€‰Ûº“Uh·…½·ÿ«JÝu¬‹Ð FГ Ýë•Ic(²#ÀdéoæÜ^}éE“Y14Ê ç_;[µñ€IðOi ðDRöFeNO&Eà¤ÈóOìõ µÏvã`W'šfjÖRLd1•À49+±@EzÇù¨ÊÊŽ“YªÏaãa€V2Xjw½²Ã!’¦cFJ™&ãÇÐY‘¹µî áVYz8€ðJ¤a'°Ò3!`NÐ1smk…Û~õ°oŸÌe»Uþ}ÅÛÂ< j¦¿òkâΕÆô4«JPy³éH  ÙJ¤¶úZùÛ¦çàÓ‡,àUZÐðQÅ6Œ¶#OË÷&—U%\&Ãx eÃ8ÜS£!€1x³ÁMR/<ÒÊa-f+• ¨EVVíd¥‡¹•ó˜ R2œx¶xŒ‡‰Eƒ:¬ª³v@2Øêª×ò;ò§ät9påNjxš¤v×éXõ°ŽÅûÅÈ2¡W ÐñœábÒ(Ñ™¿u À0[«P¨Dt·lë Ö47å@âlakýv ¯€Ù$e­Ì‹Þ(&ž)ÆTR‰Õ$¹Â&Avj«Ð‚ÒÀ4Mžl+²yt!óz{ÿH ɤ áÀJÇŽ9O YgA–½ÍOwþzYC–C  hxdb«TS5¤mšYL&ôZk:}©D!AM›“'A?•øì®`!El%¶íPp]ÆÐÀ)Y¶ÍàNlýH–Ẍّ́<ÜÁ™0lHLdÝ‘€,1¬QæHn"5 7y–¶a`þ˜¦Åµòw(©< Ù 1‘=L¬ôêÄô_q¬²¬tïÉÚ}êùä`›OâZ`¤Ôr|04‹¬J„’ÄùÃHâÈõ²EVeÛR%š@ötüB"o¼‚H¼¨•@Ê ã†rú[ínéyëúLŸU™™3t:%”ÎÙ)D­‘”Ìë‚a…ÙæLV÷H[Ÿ\“ÈbZ•t ”•”4l19`àu‘Rkí¢0²ù{áñʳ⠻•ªo]T™ŠCC¶’m0À6&¿•X wQ¶xM­œ¥r¶øî0™l§3˜ä¢04:†×š@yú|Èl‹RVnÝ0 Xk´¦e­¦âÀV‰HF/xÖ·?^~bå4J6ÕpM¿G†¹¾þ @›µaͨ^¹;vÓìnJ©ôLT‰{œ³TåänÖªI€oëxå™dž C YÁñ¥`L¸›Ê`šZã'ÀÀ¬âmc¬ô˜¶ ´âëˆSs??¬ ƒ!³ÚZ1@ŒíBÉ<¿úH²ªZ'¨¯•Ó|ŵ«îÞ:…mÊæ0&^p+6[üVUôNäÙùÆÑ¢Ÿ¶xU{&”"PÒË0O€aO¶aV¾Çm 2å <Û”¶HLƒÑnu ãm˜ ,¦ZkϽê¨D š~%ðÖü•À9 m1Ô>|2”ÊŸXÀB6 VàÎSSk!ûÂç—B“w ¬`%ÊùÀùg(+…”…#SÚæé8g²j‘`)@¹ãè…i0åµÀäŒçFl› C¦’Ø {aòOSm_éÄHk€^Ðó1^)µÙÒ$0•lþÙøˆ²‘¬ ò7 O«± xW'°…Ùò‡ üë…!h0<دMi¤DgLpч‰-O£—ªŸƒlcØÊ˜ÒAh:~[LAFXZ. #UEjG¿¦ÊᢦV‘a<çÌó/&Ø)$sz)wÕxÉX cE’õø¾íNûñV¸­S¨mž.Î >¥§L€q¥&šÍÚv>”4ž‹BO¿y¤„­Ñc3t¶[«mNIC `!¥…?vZ;Ū²Ô…‰žÀ7†ªÜl›ÓÌÀBJPZ)…ÔåÎ=T9¯.-¬ Oll‚þbضOä€áI ÔŶ m—Šáœyšzõ Ø Ì™òÎ9ç¶²ªxfn­LCÜ@Jk1ma½œB‰çh‡ÜÌÃx3{4@m)EžX”µrÐT;): LÎÈï„M‚Égcj¹•òù j´Ž”4¶E…4JDÃð [“á2±Ù00 ÒÊjLå±Û®Ë jçM«£r×Ç“Á¿ýãÿ `䇱„[vkÍa¥sY7 ýCOÐ[%«ÄŠWÐ}ìáqžõªn+UÔK¹-CkLMëòHïw1ÿÈ|È€†ìÍH[·„ì°V˜ S ¤œž'C“8å¬DÛRd@HeR㲉ÓÔBÖËCà®”WØAN§ÿ|ju¤Á«2FŒr‘¿[ÒE [k†»·Ä `ÙÈ­õÍ2±­(eÝ6†@jDVû-‡¥ÄR°|¡'³ɤÁºmäJt±m€Öe;ißzɤXõ3 CÀ°GÓE²u'À¨òP:KCªR"Å$¥/œ³ÂSò±&[žJZ¥²²•­»B'ˆçoŒUŠp:kµdHk×Ï`¤ª¦š­w£i³²*ÌŸ8Y©ºcê‹õâYV‰¨E8ñnÏ11™ a±{`âº%åe+™ìÌaŒT3˜¾ 0¶fP›^Jàmkáºht_ [Á™ ²³¸=…Óu±úqÆÆ£áæL˜Ã)ú±¬òºH ú=\!M¤µîSšAyVR¦uvt´šbÀö{Æü³µVضã7†´À;‹· L6ç:v$·þ8š‰­ªÎ’Æ¶y‘0=óüUek€Æ³ý¦ò”å P–ȧòø˜†á@³¹Áò©Üç©Ez…øYaµÈºX b&âG O`U+d»[8[©/“^ŠUUuìÙQvR˜ÚõANß[úuþ“²¨ L©Ö)XÓzí¼ö²¶Rþ›]d.„C]šœÌÇØR*IÐÖê+H¹L¬¶•Ä“R0Cå cÅc¬jµ°"»z©4ZÓ8ó¦ÂÛ"1®¨Q“d(•[[¸ÙÒ4œykóPd4EÃÀ«ÚÆX*%L-Ö=†mºÕÖ”x—ïèaúø lÖz—FF¬¤ñ¬UµÊJÍ'˜UóT"ÕT‘<Ê.?\j÷æåñS IcUÞ0j›“ßÛËC¥,«|V ÉâilaYÔΪW[«v”½Eja††l*[×K¦„’¬’>h²ÈF=…þ-@t¾8JP idÖxÏ€{OÂX¥˜ŠÆ¥c”4·ú5™Õd²÷tÏ?¦DJZ3”j[™#‹Ìá:H„Eø´å†ažÌ*8Ô¨¬õk.E“ƒè*±;g…ÕFëûlÈšÄ6ÀÍ<ïq%V<™Z½ 2£â}õð*”õ:® ®Œá`ÕŚɆ$¨¾¦Rõ%¶N‡!°µÒ#«I¬"eØZ÷y’yšÙV˜6€ÈßœdÚõ,øˆ¶ú’)ÝIçÂÓ 5­ÅÎ;Û F™m&0óc­–§2¤ÚðjW%V‚oëáæ´bhº=¸Gp=Î"%€”Vé~øÛ‚ƒÚ}nmÏ»x¢t«óT’³•L­Ba +±jÑ1‰¥ ÖY*T…orÊefJ>ô²VAYÊZª¦Õ‚­”­¿ÜŠQe¤Ÿy²úgbûˆÁ«ôj`[-D#IÁM°Å«-øW`  —µÈò4ªr3†ia@ª.²EÃÈ¢,À³1.ý|ÀùÄ[•;¯/XXÔIÃ$¦99à›‰Iå?xŒðq3³Ú²;`÷ïûß¡’åÖ´ºxåúD×]¶.V†§!ÆÊ§HYT‹lMl ÄÀ ¤¨ И¹-ó^'že‰a¬µ[+¾¶¥ÁTÕÀ4¬¬uAºx3H±Â |]84É VAßxJ*oxž½T5m sƒUUhK/¤Äí||hü+„+9g‚ÆŠ‘í€mÁ³ì–-|»îkÁ Ó–‰@ Vé1FÒ–ÛRð©y»Ç[1œ­ëÛœ”8©Ž–8Ãu XC6A]¼í<áod‚™£\‹dø[ÝËζ¬`íc §$F 'bl €ÖTL°-”ª;=+%øž¾;É¡Q™ˆ gÞW©dyv-Ú©1Í6ÏzYõU[V‰€wW1™[ùÓ›PGßxV +0ùÔ6ÀîêjŸßI`üšÖ®U-s‡«Âe›ÊvíJ 8‡fhM©£­QÓ¶ù$°b˜”²¶MâÚÝ€ɲÂÏœ¬BÊ€ì­><±øŠ¥0Š/l‘RÞ±ÊÓ4˲n€‰TpæS ££*L-0¢”Áð~‡Ç4$¾¿wc’L­1Îÿ O…S•ýùÀ|Hgfa>¡€FR,xmˇ¦­°B‘³UتÁ —åVSLæHþxAcŲx˜U½X¥Q›†€Làa؆s §Ç,uNûÎw4«^M›O%V[&ˆ“a¿Ñâ){é›ÃöZX}ôZÀzóH&½”ÙbºsJ¼FÖ@˜^ îV3´åŒ¿{+{ÚÜ·JŠ@вòÜðe+·ýZ)1?F•ÕÀ9â¬l÷Yê,Y¥¯/ÌR ÓÊ™Õ6 \– Y8‘I0ÊL,ds~…ÏVІ *® ³Xm¶¶R9§©P#«ñÌà°4щVhK¦ª 0ܺ«ïçË94010Ïl•3ì&maëJ½LØßÇtW¶D “Æhræ1@c¥©;¬ ˜“é Y!uÇÎeÅ×±Cb +¤•s3ã1ª0µîÈV1^¶Ho•*Âe_î¸ ]°ucú†±6¥B[+€¬K¦o놽“O­ctÁ8QJ­‘Ì1\¶FÍS Icå_aL[Ê.™8 ó4xßB—žF8…YÃ(i Ûš:Ú«šê(Þ+"CÊ¦ï˜Ø^K@IDAT1Lœ’ÒÉDtíH81`•X­¬Œ+‚»±3Ü}0À~·Ì IÿÛŸþ)§Ms  ×+^:]å°¬°­1™ƒ‘ÑpÂÛN4žÆý6œò;Cå ¥„mchÎÍœÊÉæ–'7g))¸Y•o=ìËT.+Ü×ümiî,g™þK–5 ¸ÖÚ„L¤ð½[&(ýÁ€F/bÇi%k€oËa×åIWN/êh%k55†M²æ¡ÔiåYÄ#Ì©¹¢ËÌ™›lG†,ŽÓE*Ä4< 0¾ ÒxÌ•g~ú½…”‚ÆŠ¼»³U ½:5¬»'Ȫy£Â•  CÄÜ)žåô¸Q‚lmÑu¨ÝXåRxçjló$¦k RI ¿’Ìix¦i<7œ˜¿à#8ˆ ‘J¬¹}[w3Mb `ÒW¶ëf¡°*å_«ÚeK¼l%BV¤Ô±-%`xíü¨êg–lR <ÇJzókU/'1PS 4™X¿Afªæ¡¬Ê‘sXJ92«™'F[_À}}¶}:˜(©)` Ë*æ¶Â ”²rhKïN<_nÍã¤Õ‰Œ˜0 MÊ¥”j†dÓ—µ€ Zm¿ŸÌlL:ŽvÛbÔ¶B¡•ž›¬j÷ÃYtvÙÞ}"õbÕkIÉŠ- ,•aÀzšý¯(•ÌDvß©:²50†•’¾÷ Vžè6lù7‰ZbXÔÔš!N gðdîàJº ¯¬Êš’&€Y Y1ÿ4¶ërN{ÿ]ÊÚ=oKÌçü€> %]è'ôÀ[‘V  °6—jõk«HLSœf÷}Uf¢ˆ­¥èea %M&W&JÅ4fVg‚{Â&¯¼µTÙÀŠÌœOŸs¯£µ³æ¶©Èb`þ¶p8ÃU˜®Å“†‘m= e§âŒT‹i<ŒyÀ~ý‘}K6‰•ƒ±i÷ÈtOƒ¶m$%˜î¶9ã“­oŸU$&2g À6^mLz|2¼f³ºm/^‰™ç0&ìd3!ÆÀúú({¯üwàÚn ½V«‹¬‘%5¥„70,ø«*Ú*´%^ ØH@ƒWÔ/+lF6òÛ#»Öë⌎F¹*VµhU(š­ Ù3ÚEõ2ãÉ„IúŽã ¶GÏ¿U¥´ÜñOS±E÷è\W-ðWõ|Šu!6¿Žº÷¨œŒØÀÖ<õeO“¿”@ÚZñ1þÝW"&ñøS|c €hÛ{h›?`NðÂ]&=¦Zbq]O¡q¹çrÊN〠}HɸY{ÐøKMYk— „†ÕZUÝëK)¤¬˜.¿âx«’ª¬ˆ8+Î…Öþ›£ÛÖ†”Ís{>O‰mãI)´=Í>/g%s¨¼*…é;]ÊÞOÎÍÏ ·åcÛØÁ#,Œm˜ùÈf…10bo`ƒÉä|ì>!Û®òÌ9¸¨îª*kA Ô]m¸ªRVÛÎ’¹­ ”2!ÐHŽƒï~š^áó‘ì°J Ÿ;…sÀg…Q(e=wt#«È9Ðã­ÿ“!ž ±ƒð£—í)Tkkò>éý›¾ðªDJ[…¶d— ûÒð‘qq¤ïÏS ÛË=/¬Ð RÝÉ #Ûñµ‹W«EÃãÖY³•D¼­`[G+^LÓ–¦‡åæ‰oÑùUÞéðºÐÛZÛ¦±úªD~K¦I°.œÓ7 1fSxwç®Vh UÌ'l‘Óç‰×W »=xA4­¶5ªÆ tF— r¦¯YW¨ÅÀ"O€²mü@>F¾æ¶ßà™¦U ˜'ÌPÀ:‚dÞ%%ž¬&ާì™ö”­jl—&k+:Z7@)ŒÉj3¯–@#©²MˆìÝî='hø¬lÆö·þóŸÕwº¼äL“i=J‘é‘Ä#ãmñÖÍÝˤïAšIVSÛJ⬤ÜTV)|77I$ž¦ZnYYa‚­¥ð"qάÈ`G6!læ^e%x«¾ª²ª¶91@Ýëuíÿ£…¬ÈÁ‹îÔ¶]/Ð0fèfvܤðü#•ôä4%¶•"³Â†¶>9° ©/¥ÒŶ©¶ÅPòÉ™¾穉lewµÈ²”Ùu2ç#¥Ð0Ä@kil rK™ e¶°Ö˜H%º ÜßýÓÀEóL 5¾iÏÚ}¦AblEÃ×"&ÃÍj»5 <ÍæOF¿”]²Áh( r±Z ¥lwhû-ÁÛ šÞ nc¤nOS)Û9ÎNÖuñ¤Tá+̶¬Fx¸ÐNÀø‚˜g¿âgEOWÈÙM ²Sk«2OL2µˆlU%þ'ÖHÊ*ûÿOP®… V#˜Àvód•8ML½È¦üjR¶:]êµî Ú²]YÉ_ü&’9¾É1C…ÈîÄVäÐd ½?H×b­?%²Ù.ÉГUU#L$uAþ1™hT òæÜê8ù«ˆÉ`}«…‘9Ÿ î`•k ˆŽÓ»(¸ïÙJ]ƒs´'ëÅMðÔô»Êfe%«)Lߨߕ82ü¹”÷‹ðÚpP ‚~X8ŽP.+EF&¨]&z øš7Y €Œ¯ê ÏÀ¶•0š™ƒ^µËÆE•m*³Ùls6*s_ ç‰ðñeâ[𦍗©lá;àY”XùÔ VÛ1lH–Ø È¹ùÃäÉ0ídõRÞ¨¶Ê[ÿ{BU}§5[nÄaš ÀÛØœœ#­¢©jGø1žg— QÊ ,h`ƒ³FÃñu± †Hµ”ÝX£"‹fHfL†Ïd¤TCZaÃóQ8ÞÖ„ª-Ë­c¶ÚJu'œ‰Ó7R%² ¤0ù[E© ¾5¦M¢—WkVÕÊ*õTUžÒÚ @0AÓFr6›w†8@Îhxü77g’‰¾4üÁ›IóŸ?P(î‹«ØÖL HibdP&–í×å¶B{«>x宩#)—¨’JÀd<2|ß‘*ç¹1ð›ܶÂãoòù,Å“›­^ªDšÊ× ÓMñÈ"[3·áªè¯’m£”UVGñ`L¢œ@U>Úu^²²Ñ̪àÄ5úVÁœ­ pëž×îJó!èhLða$™µë’>ÌÙ¶¾)‰‘|}›0eY)Aß¹üŽ®Þ=<-‡&„É`ÑýÀœ¬*-™Xû_VKYéÕfØ •d(+Õ0Äʵ Ä×ÜV‰•,e8“˜UŒ^œEb«ò‚f-ðBIåy®ïÈ@›žr!‹ÔQÝÒH—ì D6Œ#K©íìHØ` [¯ƒÔ¢;!è{¤TþY­/’Ȱ-½^@-òDrÓÑxô Ó¥º¨|2Œá€´ MÃÉV2AüV`X9¬DÇük}nðý¥¶ÏÑ&¿=OUó¯w’lÝ3϶ô)1µ»ç¤ˆéqè›’l†f€¥¬Ý†»âFYdõÕËv–šÖNS-\öžòüÉÀhm*Y[þJh²OL š¤lí¬xnMNóÌ<}¶5²U…áÐ6å4î–?² L³vdîSd2ÿܬ"s ñ2x+Û~~ý7Áõ8K¸”Õ6¦Q“ÅÜ̯ödMb»‘TuoÖZ8,sÃô¡kHŒpÌ9gb%s.åï³õ»¯l$€± ú0o~J[dd­îÓ…—µÂ|’ÙÒl›FTN&²[-‹÷ËFµ¦5ªU0!“mÎ á:JÅ(œ±¬mµï­¨œR¨ X9wÉŽ& ¨¯••-}ÙÜ0À²úV²² ªÂ c£¶’4Ýÿ¹…÷—‚~7SËÊx:+µ¢ù+¹¥Ï/HZt'u¹=ŸïdÙE)©o[žR¦•زêÛ•Sš îl•dk5-†C׋”jéu@)+ÄÚÚé[ÉjçFüík+VhìðæÄcοˆNWáE´jFTûŠ“f§‡È @¦ÁÀåñLV ‡¡Ùñ0½úJê dhË„à<óÉJÙjQµÍÌa&1i’-k«…àa#ñ1Uþ½g˜ ž~}Û*Ĉú¶­Ò3ë±aø{‘ yröKp&j3°­WâºÃB kíâé,ÕU¨-Òk½Á0Ìcˆ”Ò–Bc[¯ñãL¶;©/}M3·ª çc `´ £D/d[<[kO™^6Þ`€¬• FÍY¯nչϘU%< V “!²¾ÖR¶²ù0¹ùg€ñ•×" ó”ÆÀôÚ•äfýF…Ö‘LòYU©¯fb ™¾ÙþOm¶Jz»æÀ¹ŽôÕÚŠóî¾ÿ¨Z@ªa®êùÎR¸m¸5O—¬©o"€ƒàà*h\‹©b`ÀŠWXÌMj¸^mɤ¾ÿA[špÎ+”]Ê„ñÈŽÙƒƒ¿&9`L27×Åg¤T˜43ïs‡”ªuzU3¡ïN|#æȤvõÅäF@ÔÂj[$«ÄÓ¡çOƒi ë+l9ØVØx¯Íó²©ÂçI¹?„gÒÀßî+dË'fíl+ÄäcÎFŠWbÈÞ" 6äÿ壪CQÖ”§ç Ó6XÁëþµÚüj ¤D>ÛÒ wœ|vœ²#5º¾gí8M™ÀÀ”²9‘nMbU+0•h!ÔJYEüfk[)n¢T€ØÖJƇIYxd½leaQÉ”‰ úfX¬^V¹3ž!‹pÎ4uUaã)ÙaéÝáköüj«„XŠÒs·ÝäH·‡¬¯ucdž³GHõ=¦„a}+á)†ÛNóWÒ/g†gå'—Ö “’ ïÆŽÑ;°ªÆî°xž˜+y…áÃR¬ÀPÄH‘ [b¤ØâmóTu+žK…é­ÄÊi6€B*IPG¶]ÑZpè,Jd+¤‡¥ê[—ܤr°mBå%þ;9«²€m­¢mkYëÜú2ד‰ÛU0¡·vœ¹a`§kg*Ûô+,k噸Ûët3ùúÀ›™8}sv«˜m·gÌù€bil¸ñ—ƒTèG œ¼ÿ¬úYU!e; †¾O,ð²:5w†x{ïñ3¿Îû‘gàÚ÷™±-b`>ÌÁxN„qÒm{ñ ûhGZÅfhL?m»±®Há§÷÷CT¡\Å|to˜R²Õ‹YÅ(©µm «­ø7å×£.Vžid>eaQŠ [Y­e{¾˜WY÷ u ¯oèk¼U¡1‚g·!Õ6ÐýX{…*´U·µb"ñã€låàïS/ TÈ @DZç&e[*[ÃÖþèHy†¸A©FUš9ã+L¾©(ëˆ XðíÌÆAIÙŠz½«¬­àÆ2é»B-¦*/­« ñíg-¦¬µ ØxÙâ#9c"[¿EŸáÉ0Ké›é74k¿'3@‡¢ÁS)0p&y憩oä ŒÈ¶ÚÍ“§³÷d3·%èVÅ!Y#ÑØö»Ph”¯Êö—?ýéOŠé°õ3«„‚¼à÷ûÅöÌ{##2ÚXp>¥¦:$ÿÚU¸ â):‰2VÃ*®ð?ÄÈdg ˜ð+õÙ*!®i28ïhaëL”î×uÁ^bÊÌa-ºúzõn w½¦ +©{&RÝXVR¬‰†9žc¿­PBÓÊ!fž[Î:Æ”Ô7gu»¥TUðC,0Yu½pïBtL‚·æcm@ J²ÜjÚÁ ÒH˜'»™ãÓTákÑc*iBY3X•KÖm#F‰-,t‰© ™X*l}KªJ<ÿÕªf’þ­âãŽÜAÒÃÎëôÊ©u™®(s)š.hŒMn›RI'’R"Ù¢'À÷¤d¹©MÖAªÂôŒ²µUâ{_V‰-·Q_þ¹µ” +U3ÙÍÿúóIâæT®WV™è`r˜mÛZ„fb wW¹5¶'JtœÒ¶C1•ݼ,r>°Gٴٖʼ•ƒÚköëßH‘!•wXµ1ıT†d@VxY)['²Ú ‚RZçØöঠԔ d̶9ÿØ’ YS«y˜ÌG/AÆœ|Êbθ÷öÜDJ «¶˜. ‰Q.¤àÞPHŒÉ'œ2üŠ1‰^ ÈGyá\Ïû 2Ïdjè L§ë\úâwÆJø$³ÊÚ6^[âÉJmH÷,´0$¾¦ÙôH˜&ÙLÔb 1(‹ áü+,¥‘¬h+¥QØH@G&²çØ_9 ©÷~T­Q#ŬK¶Jdë‚ÙTÀ¦ÚAxÑúRÂÙ„õÝJ@fTÒëE,&«;¦ïŠFªöôû~lYQ6‰Õƒ³E Û”p?gçO#Å ”RáHŒ*ŒƒX‰­4H?nh00è¤AÞÓŸ¯)ÀJL ýö›JÊUôÃK­ù•àé+Ñ·*Y@¶ÐZÈnÛœo¡R¤1O&Õ"‰e­x Ãæ×ËÖ`dÍ“Ob©H@¹P˜É˜ì ’9¦­Ÿ!™*«”FmÇD6ÀÛÓÌÈ<­ç¨4`D„­ G[k¯…il¥èë-e;Y)[YnÄÂÖíD¦, 3Ô+`…¥\À”sÛ” Û˜@åµF(Y6A© üd¥—Òéš`Ì.¹órsF!+*ÏÁEeî饬0O©KyÙja@‰@¶4°P˜2Œ×Ū}þWxÒ´6’Õ<)ù¨ÊCˆi¶U‹€5°F03éÒ0ÖJ|ÈZ÷JÈêîJ½!Y%¶JÕN‰m ²Z@UŒ¾}„’Ye‘"Loçµ¥okÍ ü¤ )Ú¦o+˰SO“À*e5™uå/ªp@2Ù¶šE­¶F1ɬ+$è%ĸÏ“$CŠÌÕ*áìV{I~; fb°U  …,å!Å“@–ßÃõb$¦OSwV ”«µјd V4†š2© `Þ$µ†gøíðùP0¡4 0e©°vvÙÞ:µl+s)k׋M›Y)—#jA/¤R6ƒ¬m7)›rÝÓ뵪&«$+²æÑòÅR Ù I†çÄWhí9nª”ÄÙâ1Bmnx÷t"‹¦Û«™õÊ*÷F‰¯Öz-?Ÿ#‚ÜÊꢊ Û 1FÒqÇL?[>¢ªp0¶päR•Ç[ÉŠfÓK4Få°Á¶» dÙÞã¹Ì­þ|»¸ î}°Õ‘2ÿ5²ÉÓCŸØ¶±µ±ÉÌ›_•€³Âd9ä KãÄj)KáÓO¶m%¶i·¾øÍ·åL©WþÚÁÂz·a‹÷ ¹áUÁÏ?²ƒóW ×N¼·¨F|€Ê ˜­J©Æ«R‹cwA¸÷ !9$PK¦^{ú¶ÎE–FIo,€!«,ÌS;kà &ÞTÍLŒ4<^ä4²T$}d’¹-à JÔZ ðÈäilz‘¬¿ï ñ­²]Ž­”m+&»"ü¶áH†QN ʶF:Ïž½Å·%muì’s€ä­%ÄN´ƒ7<·lé›Ä–Æ…Ì£WJU ¥4ÅØæÀD$3†,, `µQøË_þò”2F€5‘öñµ$å¨ µÏ…LÄ' dØ@ ‘MCVI§êN†©Q«1¤Æš0%fÜ6¡T¤5l%l¥©"­ ÖV5+/:…ÁÆpÃç‰wãV[—‰a‹T•¦Á2”Ío ¨]‹Sÿ}êgˆ{®ZX{Õ*)KÜ FJÀfˆI¯#P¯º[ß-±mµ3¤¶4VÛÖ²ùúj Œ]yúœ­ž‹yË6ük5&%±ñtT;7ÓØÉ`×¶ðÇ@J4­F2™OàŸåVœûp‰Ê»ùepúUÅßü¯—¶-œ>ÒºFe³rR‘ÒðÞëjá®n)z«²•yÊòy¿>Öº^ý+z²R«mËÐUø¾ܼªž>gLö82ÁkÇ6bUÄ u˜ ¬jÑ6ª Ë"ÕŠj‘€•§Æ#ic¤¬†ÇÀVÛ‚9&ý—û|¤ðkÁŸ˜m [ÊÎU/)âRÙÖ—†’>×åG¯MÂÒJƒZÙ}èRšÊZEbdkgeeUR LÓlÓL¼6öÊÉn;0Ãlã‰ñ¬ªêétRïÅ#MU LFc ˆæ϶@ŒZU=ˆÚah˜àA|Í~u³%ÃÓXaLضÀRæ`f}­u©¤q©{¸Õ f« ˜ŒI— ¯Ð6®±òH2xMma1¸óbÚ҈ȲgEƼçBÙlÊ1¶p† ÔŽ/›-¨Q«s%NŸ@ RS«È\Ê$“¾Xd9¸óJÊÒ‹=bkФ¤=‚¾Çüøâ€Oˆ±"»aàß÷ÍzÚ<Á3ÿÉ$•×ËjZ©² [²÷˜¶ñjÍf¥$[yš1R—aXé‹HL`[YøLöý¼ÔÑq¸ùÕFß9žL‰à†øX1ª0×Ô‚ÒÏ©æ!èEÀŠÌV—R™¢” ¶Í*‡Ü0yÖ”b%4JÚÊRæ‘*‹Œw1ÎÒm³Â$tKL„Ùxâ=PJ!íÍŸ—™Uµ]šZ‘Oz@žÿˆ¥qCç"‡17_ÙµWU×úåƒÔiµ¶Í¤¤*SZ1€P%ˆ­k$€à–~>B/Î\m&VQ»kùYÆ«í"1¾*ÌÆÃÔ  Ù$Ý`ú;ò™v!Þµ0„=›ìŒëXw2@ÔÔV¨ê¡”R‚|5 1çm>5W ¬,PG)“gR †’l/ŽË½s«òVÊÀÆZ¨ªK Ma‹¯0 Ô7L™Œ•‘”[½¾HŒ-A³åiTfHÀS‰T…»ÚÈ0e…mVk•"ë 0i’Ù2‘* ¿[$Y©Y5'ç9Á<×âüÝ’ÈÜóÝy+ܵÈ*ÄÄ«*Taª²ê…'‹êùNB°¨ÜöŽöùÝ6g%L*œŒÎS €¡O™¸B)€ iÅÛ9—b”µÊ %záÓ÷›kA¦¿Úó‹¸móÏ Î<™m…yv® »j|¿s²êÈ•ÌGžy_ܲ šA–’À`ÖbSI%V^ªëÂÏÖ®hzÇú{ÞLrP‹W» lk•ê°)›§•^V‰”S[a)ú.¶ß–0”€á«©\ØÆÀª¬ô‡ï˜¬B–¡è©…ñnR‰˜•Tú•`:,€LÙª¡¬0E×õóyÇ#E‚3ÐéSðü#M—¬ë‚ʾ'iNYXð«6½-€‰‡wL%Ó»°•RµÒkm<#‘៚˜L¬:Šj#õ¥ÊçSðýà¼ì «J@>§T‰Î…,õ£Ð04ÊeßIè=ÐH<µÂÙü'à™#d…=/™Ôi[97z¶­€¬°5Ù°ÏEæ€/"Ä.³¦™ã‰a¬‘uר³ûÎÑ)àÊa YåiêòúÀô+é8c6Ù @GS‹pX‰ 3Ja¬;2`¼ø3ýóám)‚ «¬ajÑLPÖ0eÉtì€ÓàŠJðdÀ:†KÑôàɦç'Ž”U¢E7SR¼7pÚy’RkcË$þíËïEÔ…¬ùÉ”çS»ô CPmëž²œeyò4^v`%4•9D¶¥ªhL’aúÜd§ßÀ¶ýÕ2 ÜŸ€û5ËC'Ã3\äÃVÌsÙ”UN9þÖýZضóNX_>‚F¯L9²#×%Ãxâ>ꕬ4ûÛ ¬%Ú1Çìºöî!MØã«µZ¶H…VimžÖ Ãl9X]uµ™Ôº]æ²¶jÆ»>Ÿ/¤Â…­¨ .¥Ð#ŽÇ\ÕgàHkÃ[ f5Û”·Ùk˜!=“º·Ja^2±ªŽÓÿ$Žž9è°ázuÕRÊ1¶Ö]]Ób4R€°¯VóQk«Ö¢oÓéhð2ÙÈ\¹€òrÞ?8XDz׺!¹õ[NJ‚°”m­O{" ¾K+kÈ WKï RcÒ\ùÑ _qþbÃÛªŒº³œ®÷kÓ:²vl…IÇd;l3or©5ÍG_]´ÃŸß°åIPnkª /Ù6ç ¤”‡ñæ©\#íÊâ3ð&I£J-’-²Zé5µbªD&¯ŒÕLdyÊvdÀVÛ+5½l†¡–F¡^ ×Hjþ@[@4†UÛKŸ+¬«…uOÉYßô®ÎIùD¬¯-œÞ‡…R!&¼ªÄVÁÆ*rn +9¼>”y(»1d¯VJ;˾V°aæHŸ²ñÈxζ³ê8jÝCd>Ê ƒŒ·UXx·³ÅÛZ™É¥òÁ°í'Íš"7’LIžáf{/AÉk[bå9w3p3ï¢lY+`¶¶‰­‚Õ¶§æÆË«Á_ÀH@U €1ᕜ/¢°{𻇤G-ÜG #çÜ4€àfÝ®Xà5È+ À‹,š ÇJÑŠd[aÃÐH©m d˜óV`1ý«D¶ ´j!2—€ñ® gШJ´ ‘Ú`HØ*JÑdu¬Ÿ»k<âkƒÌÁ3p«0Aš¦*k­œ³ë’¢AÚ¬ÚÖ+ò¸Ü£â†Ç×=+>‡˜EÓæÃ?¥, €ÓãûZ¯ê· Qß.MK‰ì ¦a…¯ð8¬OHé ûxÀJ"aV²€Šlµ ¥hòŒqÿ€ë¥Ü0¦ñ²×û×›T"º ë ÚþX›P»€U¼#å?[Ùê"»v@âÈJFî€õÂÏŠá|êîZ6FßÈ *É £Ãp@ªè#Ü 4@š˜¶V&ôÖÝ™p½f M¼1 E¤Z¢aJY›–>¦ÂÈÖª8 ^ëJʶbíÈÞ ¤Çx+˜Ð˜ÙÊ8¦F™#sN&•žÀÚµ»º3©jµJ2Á%V%¯\w =M“o9ˆ¬-@,üŒ;N å+@æv\n¡Iht××ÚIidN×i˶ «­)RJI@v˜ )T!EÃÐK•Õ] “Ñs&6L&%`+‡ô£Zâ ’U»v>½¨+d%™×¨^x…Õ CIf¬r«)¥ ñu‡÷€úFÂØVÛJ¦œmàš}n2ec¸ )%Ç÷–Øv ¥ƒLœÒö …5¼NŸÓÕw#e˜®ãº+›ÊŽ1g—ƒœºçXGU„'P;$@àê#¦:ãZL€ É"9´UR6v30`m¼µ¶È ikŒ²¹ÑpVÛYÅ$–jZ…«%R}ÖŠf+±!ÓÚª¤lb I™92Ð*”j¥”ÒÑ`µÄ‚€x-fXÊ6Æzå§éRÀ²5ŠÑˆÌê þXÕqVE™LÓãþýðâ»4 ‚Êã£Òw[[šb¶¶oªÛÕÑT­¶d|å/ȹñó$ÐÙðm\i2©îÁV9ŒéªcÖš› Ìñ­b¡–ƺª˜¾¬âÚ…dÍŠ¸±ÏW'ÄLÜŸÿ×<¶4èâš#R›@͘Ú"9ù:ë/œµ4"ht+fk ·­È‚R¬]ÓO-(U!Í÷W¿¶OöØ=\¡mU¹•µJa6\Êó©iǬ‹Ö¾Ô¬É¬µx»T°¯?) oúöÿ*+‡Æ¨;¬.#»ddâ4­˜f°m†ªˆñ}Æ0Âv¶1¶ª#l•J–ᔵn%XÓ ‰Ñêf¬d®«Úü»1ÉÜVVÊ #»a&j9ä´ÖÈjë}£éS‘aM7gš½K¬ÒTË /–²ÈŠH˜€•€#a^|%ŸOòo•yæV!‡Ï(÷Þ®‚ ¿ŽëÕ•Í0MÀµt|YU‚Ó‹$+ZXñʦ’Â#1‘¶ âô4BS[þ ÷n«¶ª& ,E&È#ÖëÅ4¢*|W¤¼ƒ§òkìãfBU^åÉdG‚WX Y/¡E&d t¼h0² #ÓçCymÎow[SµB•ÀÃx¸ªzÏ•ã4@fîÚ)•Ð`œIxš0d]¬BŠ!ÐeÂÕbj}DW¦¶‘¶Ý¯¶Jj!¥jak¤ •Û¾!eÛaÛôÖÄs.‹tF§ÈPVض" çÑÔŠdVí*Çw!ÈÆ>v÷n9ôdc¶ÒwáåªX1Dž_µ=t Ù¶BL ò¶²¬xJ5˜lמÕ`:œR­*ÌŽP»4R¶ª„«£Éª)Û8Ã¥0}š’Õ"ÍÞ|¼`’¹µ™uL܃pšÄkQÇÝ™ P+èiÖJà×kO?Û™×ÈÚ Çèþkn«P¡»- «—#ó¡Çàá€5¾q&¶À0M[¶~ÜÃUuŠVdc›AVà­¬¬5ÂäCc$n¢Öi8¤$Kl;ILд°g§LL&tIc%&PÈDžØ0˜þ¥ ÆTr¬ïe¦7<=«x Ž€m…„íΕ›U9}b[ب¸!mµ«£¬PIÃY ‰Iß0Öà Jk)%¥"{+|¨e­¶Üº˜L ̦íWe¼,™pF¼ÿ’*e¤¦%ó)ál›GVèk%f"ÛÌç©Ý PÎ43‚ek‰É—¬Ÿ"ùZ1”d°H‰á,żÿ5+)æÉêˆ!k}¼mú `»¦pÊ ç@,ñ]DW ¯(eÔ¶­‰&˜>°ÙdcÇIm¥´àf…eÀÊZ$³¤ÔºUUÈÄÈLiLu‹>3#ÛV%[¡mÊm1‘Öš*±6§œ2¼-A½0bJâÅoïÙeÛZsÀ˜pÎóAºÏ†· [Ùðž`úl‘‚€s„)ñ|¬:RZÃR›Ÿø5gE³uLM§æ0’X”’êøº!›jUËþ¬”w´ÙVe›¿-ÐÖ1‰m;2²Ï¸W®{ÆH @xñÆ4@Ùlkgàœ# )QI—cLßôd$[# YUknÖܪj{<\•l1™Z[!ÕÀu”ªÑRýö©Qß«²+éªuø[‰;8-±BßQÌC£DP¦©Ï„ lÇ$°å&5YŒ£vR"ÖÕzdjµeme­êð">¸B@ª*@¶*]*¬]åÄEµïl†§Ë&Î f^Há1ª\NÝ»XJKJ A©*@\ØÖ€¦lÓGÎÏêKÑà5…;ød”Yå¶á1­Ê›*gÁðñà0píøäO#Uv£¦DÒÜäY2ȇXJ-±áyâ7Ò©¼ƒ½g‰i€M“ÓØ*OÐÊ C ;»/v²†oæf ·ª «%P‹Pß#úÐñš”Ÿ~)ÎHÛŽfK {[ =íïð™dŽÑ(¦ÕHùs+v:V>ãZ9)Àèu¥qEÙâm÷F­c½îMü_ߪWí6ŒBæzúÝ_F›SŠà†ÇXµË\¡-ˆ¬D6Rv[s:éx׈¡iÂØœ¶ ;2O-tV<Œ«âOßYDåáwÅ+ä à¶éa Qó´%ÃpÞ$Ê1)¯Á1ì ù(Áv.«g@¡—¼¯L¼•¥ì°š:¬•ÞÖJ¦``+sL¼­ÉmhŒîù‡Ã/ÿû߉(¤z\`«‰õö+Ff§Ÿ­h‚š5 RV­»:ÐÐH 2nz—oØf… [ñ4¢b"¹é%¥‘YÑk—Þ…NL/lcêB¶vF%°2Arn>£\Þù‘$f"Nïß|ïàkW¡Ùú.è×…H½´€‡àÓa]€žh %ÞÚ£\@Öºø·È¬¬ýŽSI<¬… 0j¶ß¢ó. $€¯6¥­Ô|Ú&°Æ;‚¨Ü݆-2AV˜ÈõÒîývÀwQôöŒŒÍD!1 Scu·æœ>R6r+žÛÓãûc@Iå   £ãL€áüsÎ~™Ð¨Âæ¯c+F訖&«&±•Š'fâÈnC–ªAU‰7’-’OÁ¸€W‹Ù6B½^7XßJ÷É…µ0aÀ çL>]o£¥hÓe²ÛèŠZ T)Ñ”RI©×O†1 †²,€Ê»: œ²ïIÙd¤­µa:¬‰i¶L`%01ó®Bk¼ÎȺ¼½ÕÖ”^À…¬è,ñÖêëxb@È*o ò_þð‡?×oH7¢U±3˜Û¿ ´Ö‰ G2€Uu|¤-^K«Bïbö” ^døšÀˆlE#ákd2«À˜ª¬™¦ÖåF€ÔŸ¸09\§ÏB ¤hŽçmíZe‘Sª'›°m (±%ó“ž­yDU¦•%ãé¿°â›j‹i…Jè [ 6-L³Øv@j[9X›³ t½©N]—xk%” [sS’!ˆ$ )ñ=¯xþdS–%Æ4Ùñú¾¶u± Ûîçv8Ó6y·×ErHT{L¿¶/æ)i|¿F=ʾˆ{FɶҼ·mŸØH<\—æLY•³øc¤s4Ƚ &÷ž´%cBŸ-òm”gLGKfež•lÛÆ«D*0ΑZ‹fËÁjÛ ôµ³ÆcÔ ] ©¢-™-™À¬ÊƒÆ°M@£— Æ%Øj+a¨Ê3¦F°+AÙ™¯Ïmz]0BagñVÈÒ›ªT¶¶œ†`–šó½“+ÿL›†l>€ÀÊîD¹Juœ¦MÙð°¼1€ùTk%°¦‰Tµ§ŒQbÍ¿Q“•Z_[×Ò`dU1¸Y7I&`‰³Ý–•à©°ãU¥ÁÔS`6psªº+šf õe…L#E 7d€OÛ4R¸Ï ¬¨|&s¨/Aja¤@¶#ä7áªÒwÀœ7¤Reë2)Ñ¡š–mÍŸ£`n$o¸°ÁÏɪUØ$¶ fM_¯PžÌ–ì¿…)ådB‰Iò4d} ¤(;­oQŒ-A¤vEåßÝùxþ8”*ëZC Ð=)¡]«ÐWÃR°^Ië ¥ Ïζ )JÀZÐ ³ÝÉr˜‰ª ²j›,Oba6[ ³0ìÓ§i'²Â4­ýå¬IŽÅ÷›\mg$àYmãÑl &šŽ!X4ž•†^ÀVŒ°-*/…IYÇÈZmŒdÍÌÀx.4ÞvŒ-ìì½lñ°ß÷š°’°lM¢³3!BÖ‘Ž@†ï,ò1&©‹Öx«ÈÄz¾X¹ôe gê ýÍt^I 2¡¬ñÖ¶ÄÊõk>¼HtªÖ›9#ÊÆä–¹g …·í=£ÇdR‰¬Ž˜ÞqD)ÃÐ7I¶M"›•*Çì¤ð&i¶¶üÙå •Û¶°¨ÐZ—¶¦ªQ÷ÃmÇ©¤F4zÍÉœCÙ¾§ªM)[*Ù&yòm9ÿÀo¶Q'0!s/FW$K&¤ÜªÕÑleW¬‘”Ñ.ÕaB­‚›”àë‚ÉÜVJm)åR¶&4^-àž»mVu!0'µR§ÙóM‘²ñè ‚—©—µ,«²­xŒÖµHÖH«úzŸâ¼$ŒŒoB+O+²¦Üªz ðÞ Ýý— ON ¯–ÃÎÞvQ”¶Ä<רò3Ç÷+R¶è,ÍÀRJZs³bÊ’ €`GÀ¤i•5’B†˜H&9õý‰m¥”ØnxgIÖjë[Ë¿ƒ¦Éœ“,«­¾½H”uôgb`<0^9PžÆh‹”ÂL3±²®‚lzÀ «%#@ŠJˆ…€: 5ÒJ@ßYÚ&£Édž!ë¢dÍœ[­ka.ü®ôRjyZáF‹¥0ýÑŽc L0`³ññàš‡ŒØäž->Œ ›ßßïâ‘0™ gh¼¶7 ´2pÓâÆ6laŒ-@ ªMÓVÓܺ^M¯ðÓ4‡Z7d« Ó”µNèûƒQŽYЄÞ¨æA šd0<ÐvUnµsa”{LÄn>Ude5­D†em¯ð³´åÖ¾ª ÞÚ‘@<Ûœ«B] ì¤É¬«u„41½?º#§—ê–6•.L8c–ª5¦ŽMÅÿÌôýP ×ûüqöLµÖÔ·ò.Ù/W 7¾‘ƒ•§B€VN3™g[|% Lù#h0–ÚÑlòº bCZù!Ë0pÙfs Û5ŒU %sbªJ)…i$]xÂj‰…ŒGÆ °µF²ReK…ÕÖ½.¥`×®DSäÿ’†i$@v;œIü,æP9Y/ͣljj¦nBVL|Uâ Òh§g¤ Àp“Åcš HÉí—¿ýíotšqTéã K»kêHÌmqÞ'‘)ÀšFŠ€i…² ð¾j Øbd§OlÛE‚†'ýéñ5§äÓeÕˆ€˜[ Ã¬„ Occ¼^.(ƶÒ7 &0瀛­1”H©Å š5J†d Ȇ­d ýÕ¾vÛ@£&´"­N¡©*8ÿ­È:ïn†²GY;Yt„˜¿¶ÃÍ6¥”aÝOP7¼{ÐÎ$J´Ã[sã‰iZѹ¦œ~Ù[tôLfk+¶íŒj3Ì¿^˜‰1] ½#”BÚª}ýáÊ¥t±ÚÖÑÀX„(´­cÎ{.Ⱥd­i”Œ ”…Û’r“Õ)RÖÔÖ¡hnæ,ª2×Ú–ØV(‡ÛJÙžNÏ‹]ŠùVK/h²Eê‹™^ɶ§Í Vþ™X¡’ôY)Až!¾ïj¯™­—<òänäó¶øfÎyé™÷©÷á’òÜ+q9¶œõ¢ä7@ëóæÜ¨²¢Ã†‰¥C q¼µñzk²VCö3¼!=7Ñ´JÈd•#8l[Ê*( bÀÊJ)õÂgbí Á¨…«‚µX‹Hbà#_&^ài0‚³É1¦²Í¡Âɤ<‹æ8t„kvF倧dX¹F” UE¦ßíù²r½nÏÍ–LÔeM›³Q_œ[ ϪÊĦ’m˜Èw8ÒªJëN/¥VÀ²T2“˜4ɬLX!ÖôRáR¶Ä½f ¬˜"Æ;ãYÐ#¯ÁgÉÁœ²)KÀ…-M²0% k5ç¹îo )¿O#™4R°õ3+¶"Ûü~ˆ)sh2“WbÕ¨’ÖRª(•¤!ÃØ"ÃxÁ*Û|d‘ÕNÆ/)< P.ÙÊ?Cy3ñ§Ç•½¸1ú À7%VAÜ`‘V”B£V$eb¸³Û&¦Äá, 0LY½V«ªƒŸÊï—­»ÏÒV +l&ÞF«ƒ`2”½6gŒ,?“É&¦Ü.Â@IDAT\U…5ÚÐTÇÈ/Ô" †aÛpbå‘nZ|g!ÈMn¤4˜¥/"?jD_ 1’²T½)«”·â×…x£v@-X UÆ#°6¦J%¿üñ”C¹5ýøLŠ”§®¬ášF| *X‰Wܶ»&®\ Ù… f›†a-L,òWBO™Æ0O/ ×÷w¿ûmÿëC†©œÛzè«âaÛÍC#US}K‘UÛ¶I0×à<¿ÂØ@b‡ô¿9+ï”×ÂýãÍlKYdKÃ_!eÎ`$VXS[©e2¡¡¬Ä:€äÙ“ _ÿã·%ý4ÍÊJ–‰“Ã"½•gŒî˜eãÃRÝ’F¤oåL âw€H3K湋ƒ±»ö½Ü8ç dJÌ:œ¥r<~³‘ZÌy¶Ú˜J€/÷1·å +€7a+€×rUnÞ<²•HÁNªŠæÌ}_]äü¹çLªìô§ë÷SF)k˶F¶^æúþúãÓ¶^¬È”ˆÚy žQãI5@)XÔQ¡ ™Ç¤ÄˆÆ³ª"&à)xÚ*©£UÅ@ŠŒÞËÀçõùn±%fx‹”VLžMr3gÉ<‘5Ï4¶d4;>,´sud°•ÌêZð¢mµÖ4¬J%ÃÙ”0 e’dô< ÙÎnT ©ª•Ú6`ͳ-ÏÀ«ÜTÈžÅJÖš•h0ÊÌ]`%öÅB Œ,1>`Õ¶î[1ME ~l¥„vžµlOÐß¿Ô77VÅ58‹í ÕM.åêÄu¤ÙÑhÆçÌ ”µÒ[c`oBU)³µæIFï–¬fH“‰Z3À@%4•·ªmkA&%(ÕZ] F*ÿ:ÚöÍ™Iâdõ:.·ªz n[Žl2@Dš„ éP:Ú*ɪ¯V‰r¼lU×ò,“É Œ)êØªÊY¼i3Ù­8ž4ÇëÖf‚ÙͰڜ™¯ÅªšJ%òöÿ|r3or)ÀqÜRšÚe(+E kEvWpžFj*[€3MÊóŒ” s M!eÛ´=¯4V‚LZ™‹Uü8)“ÜhÊ&€¥˜wêÏïýž»7Yиv‘ôL„”îHæ¶0sÊj‹¿Ã~ža'"ÀèîÅVž €lò k7œ 7§ÖY2d_æ ›3/àôÖZ çtL‚îçÖ}jeu‰2éI%†iz‘J2Û†±EÒˆü­°ãŸ;|£ù² j;’-©Ôd¬uåžo˜àYc}%døz±m&%Bád™ Éè2zÀ6Ó¶Ú–50+µùtl Lƒ¹±…3·:—^Ä™”%È<…-KY¤ìZŽûõW%èSòTèVc¸õÒÈ ÊüÝôkM#›ÌŠ_ü·-}íVËÓTç½¹©…,ÿ®Ë#­ªÈêÛ„ÜÖËüÛ"›9ÀMVI‚ÆÈ!g½ .ú>>U P¶Z<`$b+Œ©ä-ï°›*‚‘¸ò&ÔNÖl1É*‰Äýa/&¥¾¶]EÀjúŽl[ @¨*«eH|3ÿ±(IÙÙëNÇÌÏ„RÊëÚÏŸ ßJ“ÌHHAÃD½3Ò$hK/l™¯0`Å €U£Â{3á¾û’Ñ8/Ò‘­l…ÿÓ&«­î€yˆOk%ùç`Åw´sœdûœž£~¿Í( ¬ E&~ÇíÇô¿ÚTÄuaÛ‘MÕ5È&ØÀ}'”R¢–8çª(»} z…òIlK¦Q6²È–o TÆS2Li˜®I&Û×Å:bh¬d•X‰‘ÀN(q™RxbØi½³|=,‹Œ¯/¬Kk…õíÿ°*çaˤr+M³5RŠ@„ñ‚@P¶rÐQPâ• SZSn››1hš¾*€a[ ¥*28½m1ñ@±FÊsPâ5·¾åvùÊy:EO¡*|çª|V@ÿ~û_ÿú7VHJV ˆž‹F™Ð#ÉÒzUgÙ@©´TJX¤·^§ÏW>[‡ÚÛŤû”e[I·jµíçE½hº%bþËÖÏÊyëÈÁ11¶ª¬¢›¤Rã-xfb]”U (².Ö&¨D•r[¤1:‚­.{¦4RE…d¢/ OnVë9¦ñlÄWγã 1‚9Ü–-y©FÂ4°Za[+=F£jÉ6‡”ÖÁøkvÜ0op°ÍPBÓ„°*§°­™pÌZ8» •73¼;§‘e¢ö O‹Þ@[Y[©­íÖüÉrfK\_¶]{]¤ÆÐ Œa˜ø· ›¯~.üãÿh8û¢¾&ÜõþV†Q5 Dyý?/4XµW•p`æo…yú²ðB«bke{,nx#kJ‰0L†CV ¡ª©´(¤Tõc CXyAiK&ªÊ?Y†˜ºÔJ鈑5†¨0Ÿzm•*‹QE³3ÂÜð;@Ì™žXäFÓmá:’9TÙæ±¥I–‰,RÿK0”%kfãaý&á‰H9׈Àït·ÏgÉmŒ­ «ÖÊ?š²Ö°µy¶RV‹‘UnÝ1Â9¿]jẗBR†yyÂÒGZzñ4Œ_¯”ßä9‘’•·¾úáÆÈAͿ򪂥zß`-ð4a[%0ßëÑ%¥#*Éœ8 [ض Ó6sø+<ˆÉLe«¤^Éú°„7ƒ×æ϶Sl dn`ßÊUe¢QS½k­½™ªð”ÉbŒ§\pËv¥Um×’‰òLl_Ðçᨠ[ùTNÖýÈêe+Òó©51L&ÈzXÍC Ð ÎB–ofkŸ>pAIÀªÂºÀ@%° n«¶­Â]N¿û‘µȆ'À¼­†À*Ø—0,UaG–Úäî[¥_ÍÝ•¬çµŽ±5úZç[}ü;NÎ4¢§¸.zǤ=}µM›g<,šVǶv„Ú1¬p@Ix…sf+¥µô…³ÅsÃPbŒŠáƒLƒï,@Óla²æi´r“*àŽc«„ ¯ ¨6Mb¶ ƒ¡·ÚöhèanHQ—™tÉ:žO÷<7`…jUµ%#Vkž"ÛÛáÈ $Ñö«ýœå«ú*ÿÄ0' —ZÛ½¶x+<½3’Ùæƒ\»4Sf;‡’€g÷fË-+‚ü+ôª;xŒµñ0>Ä| V˜xJQmŒ”m§SR#þ@¡ükvbX- %`Ï"^I©mdÛR¶©5[©®.M L¼a É3’CLÊzu–u™¡QÞâ7Ú6a0gwhÚ„dm1]1™ Y ÜT9+Yw˜§òºô=+Y̺0é¼9”ª¦Çš˜ ¥¬Qm»=@4F3óÜ0õ%âÓV—[t<ñ/ùË_|Â!ê—fÄÖßq,Ë"M÷U=ßNâš MœumjÜŠÑ>ÃîÔJþùÏ*!Uˆüµƒé;m]ü°Õ´‹6ƒB2@àOýu#b´ãæUÃð©…pl;%Þvú`ïŠ|}Û:žòœ3 šÄ ÷ÙŽd[ª{˜ÙÍÖ´¶ÎES6·ac[»1¼À9Ô ÓȤm%VS¥ÁɬBJ 2x%fË­w·­Ú@2‚™s—3Á<[²H‚JlÈ<#hÚMÚÂÓ&oBnB9@oMÜ$¶uL+×t}³µ¦XÁmÉ€iÞÉSŽÙ„ñ™”µv:šÆ¶F#Ë&ÖÙØxÙ3ë÷[2#0qÞæTRÔ7ÃwýæÏób’O‚ l½Àœ1ÓSêî“Ò ÚÕ Ù*¼ÆçIÑÐwLž}3Úµ³ Ê@žÊ1|„r«-gY)[À¶. ¹õ+—ÝF/@³µ®}VVæsÞ«*e«‘uÛ.Ç zÆZÊJ™?g@Ö$Õ’56™è{I™ ãÐ`¬¶d0«°å)Yüf“Mf6¤HÌ'½-\¡µˆI ¤aJµµÊƺt@Œmªˆ1Þ3Øz(Ö~-kTU4)2—£¤Ãbø[3Ìœ8½-@omž=ä‘Þ+²²Ê-¦ [Y¶_xžÚ)þ~üÁsë@/01F÷ôÍŸÛ·Ó‰kùù˜‡Æœ Û@åV$†³*Y+Fõª„ @ºm¸.«*qLþæ±”æÄ´í*¯]zæd‚¬4’¢T+lsC*ÄWŽD¼ZIÏÍŠÀB­°e¸Ÿ÷jÌ}»ÀwSâbýÂÓäñÚáS"Í@°¦Àº ÇX)7ÒLø~ß`< (­9kêµ÷_,GÒã•Ü7âóŸasSˆ‘%“µlùôæÐTÈÙH˜°Ldgì+%7nŸR—¢ aàËò‰Ô–âÐÃ65ó˜ëkà.éµ!"7k€¡µåŸ Ù¡d@¿aŽÅã~£aL µü¥öÄ3ÐETõu:ÿÄTXŠ™+ÓÀG}ˆ;¬/ «í[¢ÛÃà ‰ì–½Z«I(××À¹IeXUØ*è‘ç0óó«’‹Nrƒ'dÛw1Aç´ÊªÏ½3DÂS Ø–›Þ½vÀ4U¥Ô­œç[¢5FªŠ¬’éÈZÉô¢qžm¦!­õZ‰g@Ö$Êk 㸔`d™Ø  r¶­—y&‘2 ÅDw%` àáüÕ*±&Â×ì|¿œÊïŸ#­ÕZ‰•̘,@\ãó¯\ÄÃká2™$[-OŒVΤ’²yFâS2ŒQ‹¼?C z±3¶%Unµ­ à³[Zª™kWVa¶ Ùˉ,†ÀVŸl­¢mk Ù@þm­º1 ÿ[”å6=ÜðJÎEÜ€ñ Çá™p¶ʦ—…Å®ŽR¨oÅЫµ†Gú}{ßT¸Ú:&«Ñ[ÒôRø@Wd$@ a#t"@T²•¦r  oilãó$À«òp$\¬QYŒ¯szÛ×4Ÿ­x%ZÃ}§Éß¶ïÌTGüLšÓê—cHuv%­È^€މi àɬsv³¹=žÝ ”J.qž©h’¶Ä11'5ƒ vE¬hlUd Á~Ï…ÄЈ4Œ§)ÒÓ²:õ2ÉNALÓ$d°,€·Ò›¹.fÅ ©Š€2sµU¥´JDš¯é~ðÉ´e7X³5y-®ðdÍÏ­r«’ÆîïOûßK#æ#‹´:{M3ð±ÙzÛ‘0«8ÖÿùeÅ¡#XSÖ¯ ÙÖ=pÖÈÖjL2ïa±ÓïéxßP¥DȆ³­»… D Ëõ±J%ƒšÌÊ ë«JØF2·jOã«·¥ÌÙ\¶¬+‡1Ò—Âà­HUYÍMf-ˆßÙœR˜æ|AÝ­yêEÓ˜ô³•U‹oªy*HzYáDÍÌJ ŒfÀ(d+˜Â¶oƒ²VV^`d}“Õ &ˆ·"us³¥ÛÊRÎÓØa©®¢ÖHÙzaÃí ‚(&k%¶àƒTˆ§±9(ÌŸÚ?ýéO6ÊòÂf×Ç8;)qlntHëÆJÖô•c …Ú¸YæÂ¶cÇÙú¼ñ†eiú’ʃG¦dHÕ}Y}Ò*Ë!½‡š o@äÌ*l…¶†á(iK ËʨýÛê}1ÑÐËÒüa}ûa¦En ñ ‰aeUKÐ̘ºXÃZ š5ÊÁ*åZ˜4˜*Œ­5L#h’×±¦+‰‰Ì¡ãÄ(l`šdV-ðÖaš:6°³$A¡o­#Ï”7dña©ó}_E[ú{5˜º×TJ¤Œ¯KY-,%8wmkd­Ð¨²´¬@Ò ‚ެ£Tb xI©Ž€°à`%Æt †¶øôÚv:)‚²ú~þš¼Û7V:+\XÍíuÅÖL9Ža•  L`_H>Î(Wë7iC ÊÞŒ a ¡¥àwt}ÙŠàp<6À¿P+« }0l)™Ë²å#g‹NmTÊ¢9½Ù)•TÕlp7C/r@æfEž‚o£¦Ò¯ r˜9²[VÚÆD6<¥¬µ,ÌÊa­| LfÛœ4ø•x #ÆãèT%x¶ÒÔã«ÅkAiuÏȺcêB°Fv8Oí\61¼^ê…Tk›§ó6˜­,,ŒA `¶ÃÜj±.¥¶­UD^¿óÂÔ.½Uvš•Ï­l[”Ö¶€Æð-î#@,+¥Pª#tºøŽÙ ÀÆ«WìJ¹—åŒT»¶1”3‡ n6†©Èªµ²•аUU%<¿Ésºw–sQÛ‘V%}Kháíê¹§d•™&½, …¤Qkgæ°,&qÛl‰…lŒgÕA¬ôÜð4Á›ÐcM ¶Ò·]ÖÍ¯Š¸ûV‚Íã QB¦¯À¨JKYôôŽOà ¯0½a Ûø}oSŠæggKœ³-,Úæ£)þzœk)tq'øØ<¶fÈŸL¯¯üüSÖH<}¡í_ÃÆKͦ¼"»vLGÃüqܯ¿,1ÌjÊæi6 ºüÞ1Á«µ zø<’ïï@dx2Ãðï£ ´­0C%ȆqÒž¦ò²°väÆc¿¾…p·A …Ö;þgÉ$‡<1ÉÄ3÷àÀT¢Ÿ‰Ó‘¸TUÿmeµ.+«¨»-Ì 7Ö± 8,[Inée2W¤$[¤@–ò‚9‹¬B$·G`»¦pÛë‚’^•çÈʆ± |ÞéèÕ’áµöƒRÓ.¡÷ÄU§§1ÕÑW ôk•¿€UáZ[e›)˜›°Jí´h5½nÅgiÛ¨Q›`ËJ- ˰җ­Åœ#)NšFšÐí@Ï+70>ÄÈ|6?OŒX7М²’íëŽI†®hzÙu™s¶Y©¥† YÕTÊE­ïªâ <޲ü•ˆ¶VÁVH1T tWyÚÒà#½Ná&]TgT«ÐÊö—ßÿþ÷tPC\ÿS,Ì!TÖ^ ëÜ­w÷¹” 1dÚ(Ñ@­ÚCºÆŸ?$ÑÈjAлdÛÁ¬ŽDЄô‰Ñ(þ- —åÓU%Õ´ÖË2Çt€r-l…”-9‚÷?q€ì6¸ƒ+¯]CÞ¶vd¶dª² `(E ªŽ¥‘$Ni½ç_÷²V‹WU|á¹Û†:;Câ¢27€À·l‰¹E–íYì¼@Ç|™ÈÊ0|*ø;2 `¨ÝȶJ:Ë«¤Yàilù1‘LDbüªV‚q94j ™ÆZàcqĶ­&=8821| žx«Êª-lZ»§ÆÓà]cÙŒ›ÖÀ·úó-€'°"KuíÄYåVIâa)Ld&a‚KŸŽd<‚ «lK/²Âä“ Œ4l{?½Ï5ÝJàm»–ùdN0&óF’ÍÀ«Õ‡ÆØò„µž-ÞrF2Þyz$•¦ÏiŒTÓó!³¥‰o˜Zã;ZcÐ`D)”`„*¶x¤¸ò__i<™ŽVYãY;ÎñºrYùý†Æÿ•Yþuç@ŒôÖÁŠ1zÕRÊ€m OåÈM$ æ#0dH‘˜^– Òc²ÎŸ^$ ÑKI Ï6!2LŒ±b¬Èœ9°­@ÊZ…mLÛ­E†­˜Ä¥ˆ¥lut×S£áÉJª—¼Y¡ÄšÏªªµR"gRw ½ªVæ¥èA°W´Ë¡ï9d]NV•Xñz Y[J‘-æl­zÙzaL‚„ßIhŽË ¸ª4RBß–ÄV£iø ›Ydeýá<ÙÜÒàóÔ¨ZŒusÆÛjỢWÙÄL²9€,²Rë6 w2©…#Kes&kÎÄ;£\J9F0 T…ì‰ÝaM5¢ÔÈ– ßh4µÅ3ÅŽÀP#[‚Ìg¥°  l<2¼Uh*²jÕB–§Â•Õ–¾P¶Úcôe˜ÀÖJ8Ð$nYÇ•Hý%™ª3âý×lýŽjËA ¥-™*+>0ÛÎ…$o-ðFU5Od+pù¾Š‰…mÊúZ³Åà e­aë4=t €J €)«Ä c-œÿiÑÃrj«_Ùæh²40^a´é]«ÿI~Œ_ñÓÓLìm0Jo³ÂJÔn$‚¡1A[Yb+Œ4ªU—¶x¶½ÁR«¬ª4ž&±Uëeé=[ãÕÝ$ªüöïu´%Àp[‚^©¦â£jߢSÅYàéÆŠ7Œúd¬Œ,qæÖZã#ɘÕkc´•RˆwL«!Ï@ßÛä E©#Ûõ’ óiªzµÊÒk§—àV Ù ÕVNS ©&ÜÕÑö5¯–¸PR|‰ÏI7md™4ê9çýT×hæmiFªª5ï;Fíq¹>•„7ü•œSàSv?æQâ=÷¬V©—ƒ<Ÿªðw¢óŠ6 ^P&“ÈW™' ”:eWÃG!¦¿&QKƒÙ1ðÌe…©*oækv²¾åØ’©uLb8OšpCÂZw ¦”øòÌD6Íét}Èx˜§€‘Öf>ÒÊ 7€°j®£,ždMÎ&h¤’¶Q‰µm3̳÷¹F˜¥`á•¶ªb%ÅßšmdYXÓô•å[Ú´4ÕÂR¢É5Š奨Ø0þrŸÁ¦§;lâ1²ºà÷”1ÊÍPÀ²Èj­®¢1’Yë¹UIJ>΂ßí¥a 0é°@âuÓ#PBàÞĈ«ÊP‰ã0¤j¶°PÞ6þLà~lM£œÌš>±5ÐÓÑK-lU˜- ªíôù´M01Þš¦-çR½0nß/ÄÈæ¤¦Ú:êU»Èø€òšŸF#‚LógaÒ/1²JkM²ÝIïY—ãe0vúZ·â)™t@¯DaÇY•#ÓXa¤µW"M¤¬Id7kü%>42ž¸¦ á, ñ"ŒÇÀf†›67|ÓæVÏŠCVÖ@Ý­¶Ù‚2ð®·è×Obüõm0ŒÖuWèI­{†•4Fn¦ÊÁÊÄ*”7°-¥ÓY‘Ræ2„ (Çð±íZઈӓ‰‘”BŠ Ä–›­.ÌÓãþå¯ý«2cQ÷“ž>×N¥Pv:Ü7ŒL1F•ÏY‡´R¾”ø™ÚoÀ¶j‰» µMS#Yz3õ«îUϳÁj„‰´Ýœáî&PÒ„V±+† „Z#yÆ@þ@¼Zóhm¶Âlôýâli2$èøgÕTmæÄJl³ÊÁ ëEl%«DUõ"«Ð–F¼—)ËÇJ°Pãy*áOi k `:²ã7a‡²ªÍ Ÿ½PkU(ð|êŽ/l‹+?Ê<ùCªF™§ÉçZ~>!l¹¥±æ ¤g2òGŠ 2eÙiâi:uÃg[ÊZk]¬˜zám 8ˆCèÔñ™˜/Fy³ñ̶¤y¼EÝ PzܶpŒDÛf˜-GY;+ åjc2±Š;Èg˜¬êkŒþXôà”WRвSX5’å š ‰¡y«›¼òÑVÁªt´ÜOMÓXYeH­ž°u!Êó$.Ì™¡y*ɯ#ñî\-MUx€¦‹Å7 åô‚IÎ.¯ªZ…Y)Ä#Ra]øÀH&pzL¯]†ÛN†Q+«¤F@ÁŸìRŠ,ŸLlL)XdÈA‰”XÕÇýÛ.A—©Ð6\¯Äj…¬aÆꕳ^Ê+3¸ ¡C´rh•­Ö¶Ôf^ )Þªún•ª*¼î1yÚ"=k$ŒôL‰kZ#CøQh+EY­5·w€RdÙ¦÷*n$ ó|l™ oZ¤•FÊ%0±šg¸ùÕÒ˜PÀªúÔ׋^À41Çë~eQbD[ÀI9x"§ë7®üóÅ5ò–~~*©Âkÿ-ýü”²5‡Äô)‘É`Ám@ !FöÔjת[å?&AæÓš¦ÃV!“½umW’ÿíÿùÓiL/r%ëÅpþcf+Fª‘¼`jw^zÛ&°Mœ’y“Ô–mÍy¡ï• –µIiU¾*˜x¶]2}7ÌPjYJ… àhÃ]…‚•Ó¿þm·2w¨ó4».Ù7”·¥æÖAtYkÀõ’²R`Ë|Ä¥ˆcn›[$ßò>ï¶›PK&² dXªò+9³•r!j…*O‡o6@è.¥Y…w¢Ï‚ Ñs`›}ªÇ“áÐl°^0F/Û5'ìI…}múÛÆ#æFœ§r]ÈX50 6CY©{«`«`×([[$Ɇ¥šDßzaD²×À¥ñ, ¶ù‡^ª^²RdV~ &›¬•s§Æs¨;€ßÀȉ†©*‚,‡Lr€9—M<‡móo«Š^¬?C¢…Kc¸!#«rÞxàõoŒfîN60=\»J6¦7f/qšÖfNl þJˆ­Ê=Á˜~¬À4‰•«’–ŠWîhBk4/PE@‰ä\ª/¨ºoþjo·_ïÙH}•X§É-d‘ Å&0ê›omÔ){  "Öqåþ‘µ6ª¨)&ÌÊd•Œá[…lZ|ó_›ÏÿÍÑúVë‘eë[(qn²ŽÀÖv3´µ …"MO¶Ÿû•+ák#›¬¾’¬¶fN‰i°RVU"` -ˆ¥¼*HS•®uU”Æn*ÙlU Û|¬¢m ™*2>7ÿÑ¥ÌR¢£W'ÅTn%˜Ù6 Rªí^{¤™^¯Þ‚Ûùó‘1•^Ê|k€ƒ-aŒR2¼[áÆˆÜ:^¹ÈŸaxëjÏØþóŸÍŠýÁË@Æ5PÃùuD戧›ƒL–;Òð7å.Â@¬(i¼d€lÎÆ**—²•Rûy©Ð—gŒÉÉ“ÉÖô²˜LêX C$}Jéb-u¯Öü `KPmÝÞ/Е#yÂ93i¤lscžÏZ7$Â4ZØ66™¶60CÿÏHÆG–UnH ê"‹u±ÂÁ̯sU14|ÒÁÏþOßmÌä4½ËF’ÝÙÿÇðõe茭˜jÞ˜Uš'-‹ŒoÛZ­µKÖ1gÊ–/••• Mw‚!£OSª¦˜)»º•T5YQv«¬ 䨧Æõ"{dxJ «¨uµ0NOÙ[Š)eíÚ1‘¶YY+oÚ̳²¦´ )š§mU{ð˜>;¥¬5m†zxÁ¤l=n)€¡Ðß1n#¤ðj+g« OœïÃÄ¢ò.°ñý†Â^6šŽÐÚÜz«ê5è8²”XSßZ ÐûL øj%3𦪩U/z©ü1”"¤€[•LÓ–8’f…Ó¨­ÜȶÎN\ùüÕ–͇XÉÛ…Ikd;=1mÝSºäzYUqÃŒWe ØºŠ Û†Çt“™d¨—˜-¥-·V@*Ï:ÖŽ¬òÈcqÿ¨[‚X Ľ<¬0] Õu×S ³#hˆÝ=7ŒUØŠ+ù,•´æ#a†J×(’­ÐÅëš³µ·«B¸¯J²Æ“Zà…²ÖRm›‡@k}Å~"+‘ÅP–5ƒz&YÁ˜œÉܤôiš“@ÐT úÈÍ™!¾PË­Àh ¯¶ªÚUNFl[‹°U­Õðdªädd•fh•ÊAy&À­ø|¢ÛªKÁê…²‹µeU ;o¯tzµ¶^-‚CÂÂG¦;ÉV6Þœém‰Y Ïͺ1̰¬u`>Ády)»"ŒÚâ1IJ0F*À5€p#µmìÆ€#mcnéYj½­ ´K ”톯Á/“u‰oT%ãa§LdÉöøüìF¦Dz°K¶R*!NÀnk ©ê[¶”òÂh}eòLœ £]‡EžÿPlm|ž¥Í—º'ñÇ?þ1—Ü¥²è¶¯ ¯YúNÅ9·†HC³êh TNÀÊë+0Äñ€¼hkÍ :Ë«ïÁ`Ì 8À Ä<$ŸÎÒMuÞjekdå ¥PU45M¼y6j]’)É ¸ã|^}UÌŪ€Ä@˵° ü(QU!¥4V3D›¤Ú+ü|’ ÈúåÌÑh±ò°U¥^7›d8=zþFÊM­­ èD™¬]V|R ›s­á1ôȲ Y‘ 1}¶ë5Ãü•`X4aÀئõå+zë*TÕ‰*Gjgp0¥¬àoŒ^x ™•ƳЂ@ÄÓ¯<Þx‘¶R¶€*o8 ÅGSQªãhÍ.î,çCd«JßøA€±Å–'1ÐÐë(®3™î±òÆSH&¥6†@ZÕ0V2æmv:‘?^äf§R[£¶]‹5q“T®ÐVØj“}‰óˆÉØ®Q-ª5!žÆZ-ÜhD§èÞ&11ÈœfULĶ•GòŒ¯ê69¿Uçc%ö^Y™»ÀÌdôHа§4’æí²F€ã$PHÌ?«ÚU…Y(©ŠÐ`ÐÀ+ õ6†+e$,à¤qxX0ïu‚)ߦ@ÎJk%¦¢U5ešoÑÇ_ö´¹²|Þµs°JaÔÞŽÍ3Û4ôÖ<RÜ0]µFæ) A%Z>s«À¬j‰¶2Hé±j ûK1¼Ù¤ÜFJyµ”RÂVÐH‘ù~8¨õµÙÛHV +z‚9 a"L“2 +zszë8DZi ¼l{¶HÝ“UÕ–¿l P»H[šweØ H @œÆßo¡°*!Å™¬©l;¯í­>?%Ä=D©˜ TšÓé¹·Þ±EÕíy^‰.8[$eCZ Єin‡ÏBY‹ÈH2€B &ÏžŸ;©*z‚ê¢Ã£]ßz0°Ut.ÿézŸ%=ÆÚ¤ti6Î?ý ¤•^À9à‡<«;ιŠF’Rh èTbµµ2AZ ”È™3ê#ÕY¬esØéÈ™l3Ôým#›³*°*& S¸-«1ø¶e'S+¡€'X­ÔU}¾¯X›*À_pnÛIýu¯«@º /sïs)G#XíºØ*Ì­ pí?'R‚ôÑ`®Ê¶¸EçNÞ¶§àæy"1® Û²†áIPJ9&¤¥ÔÖôL š&´­*ëš$V;\TRÊ–Ìlܸ‘RÊ ¸¦V–êÈÄó,ËJ ¬‹,2Y„=2ßER.ŸRÀôByWdm0¤snXÉ•½.10þmÊÄD²ª‹•›U‰Ð7 ¶ád¶<­‰éá:ÂÄm­4˜w›CÎzí]í645¡<ñBIUÝÉÄ+ `ØÖ×j+¥ÊјÛê«EÝ•`¤€œ‰Mã•iÛî$‚¢ã©P9²U¡éâ&€mÎ0ýJÈP. È*Ì_Od‡„Ô1ú~gÚâëB“­l2†È&yKÒ—Çý^Ô„þ+ùü>a°Ænþ”MÛ5zJº=ÊΕ BÙºkkd;P"ˆ}‚daïj'Rb +!hH%97Œ«Ùb¼rFÔ’ëû( <\kÎ}fEÌÁJ/[‰rä+Às 3Þ«„Eí”4OcH)lr<\;2½T Ùx)Q ¦°E’YU |%Rà hþ™¨"Nc… /ÛBòIÜ´0Ð`¢­’à †V¼¦@Λ­m† …·¾|ª*K)Åd%ð¶²EŒÚª8ãó߲“íõƒU¥4C|ûˆž¯¿m&ÉÚbŠnCªIÜÞyýÈ0x3ô¤ †€¨Ö#ÐÔ¶Qém«zçÁŒrþNêŸè¥VÊŠÉd…=_Y% SÓãuOÜKY€ž•íúóëù­”ü«rðšú¨:POË…ÂJÌTJÀV¼ÐI±HyóŸ/M¤fÝZØ÷…Õv‰šOϹIÐ7º ÛÖ±Ià3Ê󡚌@VÔ4sr^9yÀ§ÇC#hD7 Û$rK`+Èl5jÎ¶ÜÆ÷FÙÕûH÷íƒQUž„ r–mK©\Ø"e)Meæî 1Ò¯*R‰ Á[0±â[‘<õêÔôÈxš®  yÚ‹x­ß¥€YæŒÙ`‚Ü`Y¼rØ s¢ñ)‚40ÍÍÿZÊ:š€­å8dˆZHÁÖ¬"UQÂÞ(ë},Ÿ?M%° )]S8·ÓàyþÉœ “®t¸Žd¬´Èp˜¬(Å¿€Ô%>w¸ZÝáÂ[dË¿G·UΤm%½$œ5…‘†ô”™ô?©§0þŠÆš­òMáøÈ¶ïð Òœ¡K[YÁ¿©( >%ý"Èœ¬ÍÖî_­BÉ€.”"CµÙfH&E  àЈæ0xÙ:&hÍ0‰È„³iñ Å>SÙ&;cÝÁ0Í@ÉœƒØbàZÀRÈ&G?¶È_|‰#†‘µ †yÏBƒl ©5¢AÆ´*ÇXÓ8Ù)ˆDšH“hç®*÷ sãP­ qúMUG¤r×ÐÃH6<`+å§¶ßúxºvâÎeÛ<ÍÜH êŽÿ ôý‰Ÿž'КÀYLÒqÒà31ÀŠ€Ì¶îÊ{[ÎTW“"Œ¯lJmÂC–RI]5óâbÈ`u‚ÎfJ$¬¼ŽÍW9F¶·!™l…J4–‚cÊ"qëÎ7²<5µv"Y¤Z¶+O£¶1¬"+ g%"Ìätú†^&Ä4h@S¤”½Ö½Ë!JL&rV‹œ1ÛH‚x¼ÀLÌl ,h*1ÀmrºÄ &²ÙZÆÉTåc›ÿ¶Ñ÷”10¥1œÂye;N-¬¢.€7‡CíØV˜<¦í­;…ø9,{®æ¾ýVYš¶À0Æ"0 d‡Ò–3`-å!° Rª¬Um`€LÇîd‚Lú]Ÿ 7ιù3ýUî5ýgà^n²­Jê…1 ,iM²Å¯°ª«ýõMjÔd ¹sÙ ­U!i ÀÏœL´­Áž{µN¤ÄTdÍF0)ÁÄŠ´ª"Ó”a3ÔÔÀ9 +' V‚ùà /wžˆ|;¹vX­múf®+¡5™è\ÜdÃ¥”çOS ¨Q$  piŒÊ9(aK€¶p̪"e¹]Õçñ…ÇwáÞ(óT˜§3ö:Áô”‚²dÃ1dŸŽdØA¬u7*¾»•xŒò4îm‰—rR8ÏÎ[-^àKÕEªwÆX¸vÎE©6·°^Ô)lñJj0f$ íV›˜ ýÕ~>€«•¢7Fm¶­Gëþi”Ûv¨×*\‰Öc+ÛÌ»4Ûܲr ÝÍÀÖ5êD¹5a½Z3§z!ÅšzÄza*Lûà e•O èëÈZÖ `¬Ž™¬! ¥D@_'¢W»Z÷±m…¢B2€ŒC&ƒI ©ÄxVFþð‡? ¥ÈtÄ ·ªozš®—Õ4Ñ& ‡­¶‘°Úb´N€Ï¡£Á/(ŠF’ÁHØ$æX½Š4f˳¹ÉªºÛj;Liª4u¬Ö*Ò wÞNd%¨u]Ü-9šžÈªhJDY3”}$åèÛ½­uAß}j‘ƒ”îù$+…yOŠj›ÙÄ0|aäºϰ`‹ UÙæ£W>RÊ‘¶H¸ ŒAŠÄ1Ä4­9Ã^á\¥ŽŽSSz¸Ôoÿüç?›RÊZ"Û·™2!+Uㆶõ ){‡<ßk~ð Âd]( qM3¡ÑËJÆ+ËĪŠ2[bñ£;}ÃPZù—e¥ 6Fg´…­dx¶V©/®Ó¹)A2óôøºT¢ À ðo}Y’õøpöl¬ 7kÁ“, Äé<¶¹qVîf*<7(ûö3gÕÂ)]Q2&¦²µ¸ê³HYà>AU5R…l L…TàEæ ;¾™³ÄÓo~…" E%cÂzYaÑ0%ÜÍXspiZk·‘*©K†d‰EÙ[çî*7J ¾¦¬6¹òúý:þºHe‚ISªÇ—‰F}¥¸ü©2}3àš*ô¡³N‰§1< Ö@Y+[Ì&fÎP¿oè‹QØô¹Ùž·‹Ú.ÓS09A ±7Ã[©”:ÂLò¡ÌÍŠ?#Þ'k•j•"æŒYG¸óªÑÌ £V¡•,+[Ьræ&dÅJ09Ó‹0LÓ§C;¸ZA`[S-^·)9TR÷ eæÚ±¥'[àÉnÃÏŸ¥1¶½”ªòQ²ÐSnÈ4xî +i¤pX4¤l[zØÚ¨e]²ßÓ0 EÀB jõ2€€ëE¹îø¬0ô9Pâɘ»d½Óá‚&1%[$ÆŠdÕ–°-`ä·]kµ…”€•äÜT¶ÄMrþ Gd¬È­Pä(Ås»œÛfj|8q×—ØZû·)|ê|š£Üx]C°,Ü1¼ZPÖ=eUVUú Ÿ¹-@#”“e×­u)kÙTa¬ºXû¤µº)þ3áST%ûFçeËJI#…*%Y•z )‘˜JÈ€0Rj³ÁÉM¬„8¬Ñð4«ú‘­ÄJ åÔ€'2hrV¦ê¦NQ÷Š·5ja³yÜF Ldó\áçÇ<[æi𼩑Lg¬¤ª”d®iÿšDY³ùÜ®c.K_ ˜¬ÈÄ¥ e‘|ú$KÕ h2Ja|Ý;NzJ})+©QM‰{ ¾Ú[½XÅÓ÷°tá óêÛ*…„‰aµµàÃC €0A¼¥Z3©ÑÄLà†¯5Y>¶ ›ƒÏr¢¶¦ÂDb¤ˆ­9÷-Ô©)^¿†¤wja[Sµb3ËÚvnÒV/â c s² ésÛJá§ K¯Qg®0+]hˆ­4õ²ÊŠü¥d×=gü.#• Rað¥jŠác ø1Û™O€Œ§!V.Źm2«Ð¯W%”4nÆZ–€M½(s+ wWô)ñYmÅ4mGËê%Õ(Gêe+Úb`YÀT#“! cH­ ˜¡¬hz©V“¤‘͇¦TÀa‰Éš¡ÿv`­ç–>On¬àbMÛn*ÀYjsvÀ4‘ÉÛNÿʈ›s3p˳Õ<ô«íÏxZc|âºsÇl'mfUÅ‘UÁ}ïÌ f%Ñ m•Óû Á<› œd¶€¦ 9Øßä]E¶SÐøôi´ás ¬È0‘u‰´.dÓk[Cµ€ ÐNUúȹªRU©<Òv%p§sípƒMc»’€5’XØ ¢$Œ„y&{ÏN?Эïv‘YM«°ì|¤0þ O•ðj)œØIaâÈžeU­)sƒÅœçí2×( OÏvù]Ž”Fõ=c݆*¤!1æ!zâGô}Ђ-½pâJøXùø‡™²¶gâçé4†IšSŠ~¡DêVœÏ*O[Y½tÔ6[­ûý÷ßùbP«0@^tá T˲¼jˆL–ª$Û0 7þ€!jÔsRæŸ=°%Î ©<ÏÌ¥˜'®4@XV‰5«[ªi€g¨pµ@Mk]~ æ@ +Œdm†¶0²y0”mñf€ëkKS9-^Tb•Ejg¥ðWõù² QÛ-QÂ" gí¼WnÈ µ"±ªl1”VÙx8%à&¨¯, rÃczçÓÄ3´¶†´0†ž³Ý›Yª¦²œ{¾Ä)«r®ëq®KëïC!Äw´óíÓ„Vgi ñ}&Ï’!A¶x†4ñÕªâ@,•ØZH ç²hü½ˆm†>¾ ²˜ŽcKÉÊŠlkZÝÉlCJ`l‘¢W-½ÿžÂjÙVEŸ žÜñs6•-M-ÊÚÆL¬œ`&²Nj5 ’•Ö|l3'ælf¼—aµ²pú‘ºÔ.†¡-R-† ¨e&üm#maJwÏSw·ÄŠOVpÁ3Yþ9p‹ŒÁS9\­-ÙÊmE³|¤LEƒÀºs[ n²Äs뮚G¶ß)3§é‰Ó3j¥€x%†Ô+’O)Ê<ã­‚^¶…ãß*Ûnƒ &qÝ¥0½ú"ûKÁÙ§lå&Ê*D g+ì˜V¶ ûêÙš«©Ä*0°m…‘°ŸâÓKi¤©It‘ì • Sæ!#h°4ÊÊ¥ºyU4Ö>s«  ­]B[Lƒñ´M9¼ø„iº[2)c¬¦×ì?ÿùÏŸþô§ÜîD^€ƒF@奌!ˆ¥Ê⛓Þ×lÿÆ…RJÐsv3ªhð5jB£ö‹iOßðÝ!q€ù¨'‹§é’^'@È  k1¦Û@ØV4RoÂ9Õý·IÉ6*5ÌI9·.G‰Ks¢Z§4v2k|@G[+Oÿ¦Ê2a›I3׺k„eša)[VÄ5’&6Ü—@IDATC PI½¬»Ìm…îYñußxž41²†•X[ùlPt´Ûç×çôÝVÛ™ðg^y·ÝT¬¤hüûôðR™ CP#k[­Õò±Õ¢ /«ÄEÙÊz€.yóðGö°Â®¨V6gan¶V%€˜O[kY>%cE&ASvŠ bàî§Ë±å‰™gÀG,’`…@/#kçƒ,Û`5µ°•x$Ï—›+>1ÍjAi¶~¡4-ŒqÆ&ÌðœÿûS»’ÖÍ D#ëË˪ɼmbÛ¥©æŒäð7GÊÖ`€©ºR2zÛ<Ó ‹#µñ*A*×¥S#ilo‹µ}¯²@Ê [kŸ>ï!ÿ×SйocÚüüé1Fj*+}+±ò“x>•0½BÕ @¯ƒË&xW©esf…1Éoÿûß›^qõ:­Ôé€ÚX•í}µ}SÄ®À*¤´!`â™çƒ$PÒËS5 |Æúþæh'.÷ùú0ŒB×Á*½m-¬˜ø4jdA š­ª0òöùõéšgm™ä¦»‘®ÙéHÓ«3A—з¬´U¯k ÔÚš!s¼SèůŠ`æx²¢l†2åMk…1m’1Q"êØ`px&4¢rÛ L)ú¶Vª‚`J`g™sHLæ9"E½¤Ú2¡É6r‚ t„ÆVôÜu²"CkØZйGÓÝ–Â{-1€ø †1ÌE>; Ás01²ò|`þx?udhË 3C¤Ôé÷5ôÅ!›¸vªd»`ç:5_>%g2<‡†ÌÓü¬ul~½d­¶”ÉÜPG%pèK):fxfú¾*n¦lM{è³ê³¬* 8g®Ä–U]ò´âEÛÄÓñJœv!LèsÖZT. “•êêÅéñýì8E>uì¼uTR¶Õö‡lR¹^GVn]»ø¬¬fKãa9ñNÔ•òôÍÉÆ¿·&¸XY¡Š­aðV¼l?™øs¶JQVBL°‘dájá¶Ä#MȶFHµ€ÈJšp¶R ¬ÆS»÷¿¥’0À8¦m¶Ril;æ~ŽÄWR/2Îâš#DZÓHØî6„-^0Ï©$¾É³äÏIY!%·ô˜ [WÒã¶½c~žBÙ 9¨…Ô¾[ Ï6 ‚)Ͷ•¦Ùdu·ŠÈ&½ô¶¢WÈ<^-¤Ÿïô†=zOÙºþŽƒ´âÅmòùa("•Üü©ÕbçU ó)dYåß´è3¹~ŸïÀe³j å"ü5>ÿà No}AX­Žp/*`+tç Üê) €¸dÌsæø†m‡õ!í¶múÎEXmVÖ²Èܺ@“PÊ®»I(‘|ð@×E‡j1ÃŽƒ‰¤a’-è€xA\SݳŠ'+õÒháK1©Öºª¯ÁùOâ¶«ª ýó,ybÒÐw[óç¿!·MÖLˆ1²Jª Håไd•ÈÒב )ÛÚvgT+¤ …R4 øÃ55í‚§”¢21Œíùn>ºBcmkD¸~,Ô㹟âï÷ÎŽQ{Û¶}UJl=K[˜§È„ëµ’Ùg‚á ‹dÖuQÛlñµ£DfO6%C¶VUÈ>ºÊ—†¡-š¦Ø6’Æšg€ ¹“¶rÖZÌöÔm{oøkT lû+%"’¦‘:)¸›\êòŸ¶æ¦*ž­ZiYÖj[ŒçLé‘®±_Mdñ‚ÆjKɰ‘næ,øÙ)µÀ‹˜œ; x€,qz+ñ5ø¼™i:,kN2L¤«hlžBJt| ^ãëÅ_H”lñý•|wÒ%÷cò˜ÞW¨Z«BAœUæ½ `U…OO¦Êض/ 7 œÈc$¥`…pµšJQ"lx¤^:fÕZöŒ~¯9æž@¸ÉOÙ=u½”ÈŠÌ¥ØâÓ0ªúrl`zJáD]r&ÚÑ\ïs3dV‡zýgŽŸ¦r†zñ xÊÆ«)›¤íè«¡$PUÊTFÅØ’lÙž»Já­j‘~𫲑BŠEÏÜVÖ“åÖ$f®K«lí¸¶Ùz©bÂJvA†×=ϦEŠ ûÖ‚;f7 ÓR] ^¬j5êhx2âs°û'j嶉³Å$³ªxU%+…RBæ µHúŽŒ`b<+AÉ1Aú) ”Ä7!g­­^Uέ ª"Àü˜^¹UJPêNùê9`š_yÙôVzHõI'Hã’›Ó–ÀÊÿäžI:Ž•À*´cųm%K!’²m}á}gbz+¼ç‘ôÜÜ„­.BÖ¶ááM )†4œ­·è¼!}¼vH/v§¦OlíCDÜUgÛHºt€m½:lµHÙ˜ZcDŒ*ž<#´í…lËP;w’®QÈ S릒uܦ'ÀÛªDb+“£ößvÄ ën0žMKYkÙy" ú/ü¼–ù×Ë*0Ù*g…±E6pLäQß  Y«.”ÝUÌŽœØš †é­‹kükÁÛ$v4Gög•9Œ”-M3dkxÃt' Úl§Äë¢Ü*…*ïÚ㥔·rC& GjXYyIhl³"»L Ir¶4øælJ`οýõ¯½VgÊFT©lV˜Z½R6½mk| Ö8óôÖ6¾Ofíòo²<ɤTQ*‡;¤,Æ ]šŸÐHH%ΣÐG´¦ºù(”ô•Àª¬ R’!Ó«åŒÄ ÞšRV!\@kJæÎEÞ ˜B¡¬ÄÄØZÕ <™œ’R²îŸaUV%Õâ Ý}jg}ȶ ŒèD[cÚ¦±z:˜~5Ïê´¼ŸF¼+j`Xy曡rmO¿{ ]W¿êars¬¤\uXûVб5‰^€Ph«FœSÝ÷Ö69ÍH˜¦1[M­½·|zÇú© ]ådÖÊx­Íií'VY©ÎRÓ÷ÈxÙ7ºøÊMÒ d‚ìZ: 2žIó´Ê†oÎZ'[óvG Úô¬BkAoµ% L“Ï‹ ºpåf¨Ja%8=¶’IqVËÁÖž¥l>0Ò¶j…·K9Aí¬Æh’&Ïyn4R­x¸ÇÝj[GcxpbJ¸îjFèÕV#%¢nR&Ä$ÆÓUùH9>¸fÇM¬ Ð<ª˜Ø;òË«µUE·r£¬‘U­TÂH%Vç Ð´10` dNf s0U½à•¬Åª¤vŸ)¥êÅU&óß7@êeÝ0ª„ªXÓ¬—ñ ¸µå_÷üeûwáµHkÀ´… Uð±eb J}…{ƒ‘0e+ÐÔ7gÀ*8øÞeNÜ«·];Ê1@|}­¶ÚY»`GÓÑV¹Á^=q¯ñ^xã!kGÐüÛvL¤Tc”R^G|)Ûúé‘„¬wLÖ t]üñ<;\¡UÄ(á#Ìü V) d…ñ0dV¤UPJ™ë΂¿gác ¤³LtKY«ÂÚVÄ[7Rí¤ênåsµ1|ÇùŒ—f…¹‘ÅpÀÀ3œÈÙZ¶-,*È.q–a`cïÙ¹&RaÃóÍPyí\ ¾-­uÎ@…Z¸y‚‘€PÞšœ¦·WÕÝèÍVÇÔ–ªvxbXT[^h´w@¯îä·ÿûß«ïóÙ¿œ€¤¶v/ÖÞ@ÄhP³ÒÅø€Qúâ†ÕÒ4}¡ë%ËGVJm+7o¤Ï§,ܸ€-ϯÙç× {ºs›“aΔ7ŒP©^G¤U¹£iúê2²^UÁ®Ž@–‰Fë ó¬–Øv{[z7€éî„2LcY‹fØÀLª¬?f¶E2·Î È¡ª†DrÈÄ]m‹³zwYU²uL¹B€F¶™ÛÓà>\+¦Ù`â†)«¤„œ¬{nÚHÃ(,æ&U‰´î–ðulÍٜȾ²™H |©˜ÊÇÌÍÖàd@J·DãÂÙúð·¥<»Ä}î"k—iwN Ë™^ôJ#5B cµµ~WYµ{î¶Ê‰ÊÍ3 Øâ †¶…¾ù79œø›ÿJDØšžI“¸IÂŒ*ë‘Ðã *Šš¶bd)‹z™?‡¶4uä [FÉL”ø~è–\IJÑ©Ú;F‰ôG;Ííùƪ¼ŽÍO€T…d+ÛÈž­*!“€ÂR¶°òÚÕWI4¶U!™*ëÞ[Î@ž¶JØ9(!p4Ù²r4”É¤Ò a<ÁÛ”[1ç·»ªL*ì\ôMRI[U¦7[]"1¥ÞÍì™BЦÁÔòÁ(Díl‘aJ¼Bk7ç UäS÷ž‹«@ŽGfÞœaksVÒ×Nð¥¬)U#5±,l¤|tŒäV@È’ &øZÛVÕ¶”0ŸÈÖ܎Ž–Ž´íBÒ»á†Á{=¬0”𢣱­6ŸV)$eM­uR‘Ù&›†²ËÁ8µ1^+å¶cº[[<ŸÌ‘˜7ÅÓ–¡KÎa­wuyº‡jõUÒµ˜‡ž£K+ÆEq¦²½@ÌVú5En tc|l[žL*ÁTÒ-]Éç‹wšI­d˜†aUå«ÁW[ 4 ìÒ";iJ¸SÂx½ð"}>˜šÂ¢ÙvœÍ£\JmÓ¶¥¯¼W¢TµYÅ´÷ï§²‹MÉóÝê(”4,…ïøW€ÒyHÒD~T¬FJØ*h¥Á× ¯V2 ¬ˆ÷i¶ ¬|D…¶§Ów2V¹Ñó±@”RØ2‡ Ž×÷si ¤'º`V{+>¸¬†‡AVœ™ž¦d~u³Ò˜‡†UƒÁ¼í0”¶øiºd½êB £•U%œ r>LZ_ÆWeËS F9ÓIx[Y1†²½›)k­5}Ç$S"¤bôФéV^ n}c82CXà­¶îK#”àÜ0—>80ÛñMEP»x«mÃ4žE­¥š–¬Sà9 1¥0õ")1@&@VX éÄ3…xq=Vëê73×b$)$\G†x—p*¿?kecú»+¼mJMyÂ4 ·íDæ¡‘B*„ù—ºÂÏǤI0™XixŠd:ÂÜš$O˜ŒØÁ­”xqëÎ<‘0 «ZÀHV7 Ë IoNÁ­-O˜@(Uµm6²w¶dÕ‹zU2L ¯-ÞJ†I`";‘¬^Z[³•Jl]íš";,å<&g²ªšbJÙvÚÁøVà ôhUaÛ. ÃA(1°F@óSÒ0´Åמcæ¥hr‹l©e‚‘ì&ÏF6@ó/›[ó$Ä+q„5Bš³B@l)¸ªnÏHkÑ©­&©KVJÚj7öRUé‚!³]‹­HkJoÛ kš •œØ·“¾žVE@ØfÛúãÈ9H5yå 7j]¬¹™J÷Cƒìh‡.2lUÒ×Kw¥KcÈv[ ¾¶W¨y@Öq´¦,¸ Sþ˜ßôi˜Ó¨²*±&è ¹ÁHzÛ(öchjš¸Ft„žƒWR/“à­d•à4I+Pjå ÙUÈfbk¶Ä·ù9”’·KŒ•,@`”`DŒÉÙú¡<·V¼›‡É¬„ôP„-«L”w|L3àËÚµ S•9RØÆlY²²ÖÄÆH‹>Oyå@Ç™f&N¡e-˜Kmž¶Ê šY ^- ìøó´Ez”]K  4ÝI 1Êj—Ûlñ¶Ä‚³-Y¼mÿø½»µí’VV…aU4«…ãîÄ*¬‘—ø¼*ž(«ãñùÛßþF‡Í«¹m¥UrÏn-ÛöÊfm¸NH£P ‹FG š”°CŠ™wnnŒ*†VdY«P‚!à›¶od­­ÉšÞ‰¤ªme’˜Uåµk+ÿÓòFJ½ª•ÂXɺ[å¬âHa àÔp&R#lúXÊÄE¸y `Ë0 sU_á¯1’rÑÖšÿZpà“?^`: ÜéÖHëJÒÃ4ô€Ãvíb’!•û»‡J´°õ=këõ£„19sÛ!Yõt2¤ž’X—uXüÆèà4”¯–£Q>•˧¯<Œ1Ó«Bæfë Tás[&uéŸÁZ[³ê€ª„r¤;„×HyšÌK!ÿûÓ´ytJ:~%²iÎ:™³…•Àm¥RZ«Ê®\ F—’ù#Ù*!î*Ǔќ±n8ï[ØÉ•sðDJåó:4OcXFä@)­|6†ì¤o4FMñËA­T|ò†0ÄVâx-ê’y<7[Uܼÿ=#2Ù9È|È„l#Uüú¥6ÃfhZß4BJ4On|4 “)g• ²2pÛœ­È•37dÝk¡PÆ7m«mVÖ¬ð:*2!–Ê ªèµK\aƒÉª:çüfWX/Ûëqn{™4j%ô)'Ë¡•žìÖ}jÛ¤geHä4ÓøHîG°*¤B|¶V†#+€¶( J)Ì“† y¤¯ ñúÊ[µ®»,C_Þ@–8M©”+,K§ßÛK`I L(­xkÎsÈdVA`xbå°¬­Fe­†)“§ì¤¶ªðM›“zÙŠL0x[€Þgʪ6_Êù#e[‹¾r1<ã¹UkÛYŽãuëOPÉb¶Ì/ëÑ(4p-8+Äw¢œm'ê(Ý¡°šÊ–^¶Ãbl«%ÈÍZ#ÝEíÂR…­Â¥œm;šTQþ[wž¬Àch¬¶MÛ6eš#ýþømK KÌÊ©E˜Œžfž¯LíÓÛúï\¹¥Éœ-]èHµÅ#m+±¤0¢‹RRùf#XðO¬°™U5íž>g&@%lžlb«ìoùË_¸•V¢ýúÕ49æeµµˆæk& {{ï¢6Jœ\áH+²{Û €QØ<Äü ]-Ò2Ì¡TkX•wËd¶ZVë@©Ž œ•™uT‹¬ÄŠ@¶²M¥ÀV:ÊÚ*Ÿ‰*¼Ï~M•(çŒô¿“@OÙlu'@Zi¤” å4H|t™4"€  þe• ³)·×.%Úu¢¾2É/`§ë÷/±(c˜ÕJ“ ®ðžæ|›ã)½Õ¦A:Z“ä@Ù´•TÙ)Ç멼0­”耺ãë‹dKЕâƒ^–a[ A¼Ú )Kƒ{FŽÙ_ÿËò‘m63&q… ø̪¶¾¶+¬‹T%xÉ›”­€1m}Æém­e«òò¯W©`q½?ß_|vRXª©È€Z«˜Ô(TU‹¦ŠçüÖÂM»™sÀ«ªÐxAf}ètÈü[‘‰Ž¹ª +Y_<¥Ô²·QØz渓ppcJC"oÏót+žÀê)`øßÒ3ÿÄ5 7CÀ[Ú`L²åS÷ñjaQ_ «.¤`#I)a¨ Fd¶H ó méÕ%•Û.RvÆ}YÕšXвªÙ"1ã‰aÙ|Z‘|çV•Âô¶îU"•ŸVÊPJÙÖ7™µàPhŒkp†Ä µÖYq𯶠ðÖÞ4Çâûùe.*(a+\aëHo¼>+AHøyVHl_Vô)“ô܉«ÊI¬7„XÔŽðJÜ\ÙjY©]ÕÆmŒwE*ÇeÒCáÖH&1†vVdמgUp©¦¥𤕬T[M£Q½ ¯\ kS¥±Ýq0¶­)3Éèd|Z+¡±-’Ñåu|1¶p ªîÓʧ”ÖFö-ѳ°6ž¬^Wuþ¨(Ù[Óçýý ÕÔª ¹9s‹WRÇ[w–d4E2ä¶ÙªÂÀB<‡áj‰wWHQ E ²Óeu…g‘Ý@«[«ã[ÉPy%)a×È*È„*<=åønYUJYOÁ{å½­JUËÀ#ȶ€4"sÌ0š’õ‘0}X~ûÇ?þ¡½ÏgíDg Þrj.pØÍ¨M)]ë@v`$Ûr >&4üý5°ŽªúS¬íŽDÝèVžxQÓszÑ–“I©˜‰›AJ 1 £ÜlJ1: ]t¿ÝÎo‡²Ì#›óÅô 0±2(á–^» ñç„ß÷ _­g$Õ ´i1a«h°b[‹¶?Öü‘d°•sÛ|ºw@¯‡¬T¦¢\z‘² [±,¥m>²Ê}·&ƒAþmµr˧gj¤&¡¤¬M•CÌR€H°eƒAïåce]RJ9>eYä l¥ 9sµû²¸mý`ðøœÅ‘é¥àZ´f‹P6 g@ YWg‹4eµ¶á@& À0††›¶¦uº&©¶g-k+[¯R•[ybòT <[4¡*[1Úu!˲‚[&bY@(gEc-‹„…ÆÊ9ÆZÖlRø ã‘O­ß„”ÂUÏ$>»µ°•²F­•\ƒÿwWÚ­6ójÓsFêÒ6«NTkÌf Iæª`@Ø:ŽFj•ˆ«ý,fˆo˜²ëB¤Éǵéë[—Ú½%²‚Xj‘óxó04a/P>M¶r%5•â¦Ê67U»@@a& ¦0·f°R}¦æÉ„À*›Û;@Y©8çãõýÐ¥·Ýð˜&´´@&°²­ª5 ÐJS AßöÙš6•T…™H™ãhj»Î…©D¶ª|lÉr&°M¦P宊²S Ÿj‰‘¢ª¶S£ædUÇ”R„jJÀ<TÞV*[°F¢™ä¶4”¾3‘n<ó™ ýâaËÁ* ãòñªò‡…ºÃ4R¶‹²#m4ãa|n¦å“Cže+„½óc¤‰¥2´Ju˜ÀÖ„02·4pY‚` àKØ%è(K웟+@¶W±yŒJÓðRëHYs0p ¾©TéKÈ&Àˆp)Y¡°S‡'ÀªdµÄpQ!ÏÛሠ,dáÖ™à4ŒÃzsß¶1€j—ûY#¨o«ŽE¼BU%€I6až™ôcn*2n€j­BJ°‚¹d¢m.ž,ñ4áž,@PÇ“õÿ`{sK°^SòBJ eb˜R¨·âïî<3Íœ³¾´»¨ÖªªB«íÄõÒ]aÇbhí–ªD–få¶áµµfn|CH˜­U¤ÑBd«—Fɬ ¸a”›VÓ@½¸É"Ebëôù`Œ¯ŠB$¦9yJ•Åd‚³Z̵ù¼ÓYe{›Ÿ…ÌzNxÍáJ¬1ÖÚ5-| ¾¯ˆF¥´Î0ŸJL¨µ 'su²Àt˜ ±-¬žXLמU«BA ê4¨‹ÖEd9…ížÿÜv³Å(ïÔ¶sôÝєÅLäLî6¼Üž`‘·îsöªÈŠJlKÅÔ´{ðË6IXJTH,rh[`½ÖC–Æš'Ÿj{ŸÕÎ9€‘".rËGJd(Ë_äü•ÿºŒ <»ªœ”޶¢,™È3ܶ&vÿ6†@-RdE K ©}`•(ÏЫ{+N ÆïÈ™´J-ê²H“O݉~e!дyÖÚ6¼#F%¾#Ÿ‰jÍI_ŠŒyÊ nf˜X(œ29㥽­”pÄ€]Z+1®ê¼íd1qJæi¶â˜²<¥Ï*6Y¤5=±_Éjäy5@nVÙ H y¸ß×;BWDoû!ee+´Óè-‘j µýZh „mõµ Hâ¥0zuÃMkKIðßqô0Ã^K┳Bjz¬þõ¯9€³òòÿ÷ÅA!NóÛ U9/$ìj»€€À ›Óò†íΰŠúvõªÎß·³Òð°½ç ËM­¤$ÜH°à©JŠ €¥5q³UR¯&_Id@ʶ¦·ÕùŸBâWkÕ:Ûÿ.QØ#”‚­”§ªÁXÕH£id-À*”>a%ÂV(:ŽÉlã2i†Lªj0#Uë᪒jíyöܳµÒà³ål ×®;ÁDZ 6ž^[+}ÍöÎÐ)’ß–ž^¬æÖT ,µ©Ô¾Û"i+¦û‡g^ŠŒsþÀk‹1Ö”­¶ýí”m> èsš3da»À„|U< Ù·ªIÌ/KæÕhð¶BʳàÎ$½ã#­‚¾`Þm «òóF(ÄÈ6q½˜XñÈÍhÅoì°Õß´jc ¨©ácX­K›g¼¬°å<2†"Ò™>ÞŠìDÖ|¬µèBŒ¤C [a< ’­µX‹1Ödê'wµÓO€/¥#²À Ÿn6nWþákCc+ª*2±:E]¦‘U(ð#ûz´Œ· ŒP%Âj›€FÊöª>Ýc×N×âD¦²æÓÀÖ‚¸íüSnK×÷[ôëöˆKÑ4pOdÊZÅ|€ž{­¥è­Ýó¡”â|ê¿×4$žØÖбMœÆ Ÿ žž³Pâ[˜GØ"–Ê_‰8êo è€.Ùœ²”Ì›_Ó Â àúWQÖöÕ—å–¡.¬ØNϲ£5•­ÓwÒÄÇëûR5ØÄk7LÖqê[S—à;²Z2ëγµÚÆ4ƒÂJÚJ¹*W‘yJY¯ÓçÛ¬ÙVh*Y÷QÎJ­¸£J„i:i_Œù[²JCÏÄŠÑeÃIÖxV-J)1†ìv>‹-s‚µ€“É*±mEbR‹Û–d«ªÐNàÞz«ÏKh¯*Üx_›Ï×B&?Jþ ?c+Ùíu󰩺. ?_QîB<µd^‰,†8Mgi«iÛ¦EfµlWŠt(ž"O‚º¤<ÿ ”µÿM(5'­°þ$k/Ÿ*¿ï²‚õ³•õêæ? M/ðV%Ä|è«M\­-.Å °âE¼mnÇúûçÔ²VŒµ‹pû¹aòi¼È&¡''³=¾ßï;)U­RsÈÐA03'È#`§#0‰¦Ã2g(››­£쀔g‚¯ M@c«Ð ‹èÈøÆjr$Ϯ݃ƒÅf`B d&Æ3å•}êÞüj‰+™_g)™ãúŽœOþRø5ò?cÝ'Žaµ@þ/ß:À´.Õ¶c²ÒÚÑšYгµ±‘†ÌÁð€g×)”¨|:{U4ª pJ)z$½OÌÓŽ‘‰)•ÈZ)U‰[`Qª¬”€[i`&<#1¶Wu^¤îÜV¤•&l· 13ª•U[Ô¹\ý7sþá^Y|]d;¯-Y>0@ó#Ìß³ €EUVÊ&pSíÎ#­”"~Úœ|fŽ'hS ÛÈÙÚvo˜"²©ÊfËŠÞAÜ?+%Í_«rk} lóA×½BxÊÜÊò×”XS‚:VžíšÚæIÙœ“­)Y\¯@­še Ò` [³‰xßE‚¿Ó½æá 4!ÜݬÀp³îÒRí¼Þ̹ÉÚîµ~K8' |f½7CV©¶sK¬°²›3qóÇXV°Âw^d‚WrûüzÐmiæÿPVJp²œ…21 \Õy{ï­~é§Te•ÕE4†mæÕ"¥r“g-ZiîŸInÕzÁh`«v޼yª­ïõyÙTU1Ç# ©Ñ¦mNþõÂ÷nÛ´ŽùÀxÎVµ‚¦)ÖHß:¾ÃÀR9§é…”.k„ן­ÕV6ÈâÔß:ŒZnØN9PSÙdÇëûš5¡ZÌjõíýq?‘dɬ ¹aRÚùS*i«È9Ã/¤ÇD¿ªj)›‡¡ˆ´UMÀ ¯¤,=¦ûÇh‡i’4¶@Q‰µñÖeskE®W òñó1[Q_b™€íd@†p +¸1zÿɘ#=&ÌžÔÊ‘™×Î: ,( `…ÀZhDÜA0iðìH€&™•,1 –EÊZ )M݃oŒ”Ûô• Ó”p2ë)Ôø/<ÿ)U XÖȪQ+A‚Q•¿ÁÈl‘˜U)+—Z¶Ú e)$P(¼ío¿ÿþ{¬¨¤Í¡^` ×|me‹ôÈÞ•ÉXÁ~É«G²&kš3ï÷óOé-¬/²NŽéü>­kp>¢ùÄl›’9ŒWÅlº¸r© j„§é ²‹ôfÎGV#H!‹X娠D™«j«Š¦1¬¢BJ½Dd֢!1·Ãç³Z ß´ÆëÕZ¯p§àP¡¾yÒt:©ô½Ö²6§‡(|kw@«ƒX(§Ì`„\h À ÌÇ<‘@I`$F—†GÒ¶1"›ã5¨É0JeEJ µ5"«¦,²tQVAl Yíè›Ü6Ÿy.Õ‘‰¥˜( ´ŽIiÅ”R%Ú{†²æáƒl˜.D­Tñº…+‘åÙÓ÷vImžHLS)©ÙýgÎFèÛ„óÔZS»º˜ªþ®{Y’î¶™5<ОøpŸv„áðÅÛžþùV¥¨–7H$@®UÕýé`S‹ÆÁQ²øJ…wØ7NÁ™ØbLp7=orGNC€[3D»(ÆiV„z«¢áã(!$ÂJ@U½ŸÁ¾ÓÚ(€7z² Rèí;P£h´çÈ"Ä2R|:´˜|„¶Ýtœ]ây¸LN§õÞ×#©˜b¡š*#ΜW(Y¨‘T§À<«|¿ÑpX²‚ªÈijT*v9ø·ã0ÑLÌ3d–ŽÒKnʪ—x.&tí‰G®“­*²ÀVJ˜bž#ÆAà{”·~Öö‰30)äRAg¤œTqkoâiæñÚ™'ƒDt@i¥e¥k¤¿ © ÎZ²˜'[£?›)yš÷é}þ}-w• ¼õ=x:‚w+;HÏQïm¤…Gƒ,ôq6!)AjªYCyiS 6%奟ÎûVÄäU‡'Åê,zß#ñù v!!é ÄI³4UJ|j8ª@AÿÜÕ?¦¿Ë)Hª »%]@H%´âð¼)À®BVÌy ” vd¾Æó?*) Øé»@#Å—ªêÜ6FHAêËK*`oRƒ#œ_«°)ü]{TqI!H;‰A¥wæÙG)‹¢Ú ¾ˆ„ä•f ˜ªÑ[Ò,²fI;cUªZ‚ð³ÄE!¯T´˜¶j†JSk–¡}™–6Ÿ%B¹XªÑ8­”Îrw=àRAljV¯8ûÀòI©fGúû¸ )È|W䥧¹KK¿ÞÝL .¦ÄO³´%ÿ§p[?.ñ–Ñ"½;ž „Øpsk‘FP É•Ä è!ĉ½?ã$® Ô«K옔„‰'D» F^ªšr?½ ‰kÛ™ÑgYSÐàÅ<+ÑŠ8ºpï^‚ñ iF®ËVuiQÍ'‚6PÀ Y ÞöQµ[ÕÛñ¹(1 v“!zë"U™·˜R—ªVª15„î¡öhZ Ö"ÅÔ‚¶–Òq” ª ˜[ص L|GDè\4¾Ë@4Δ,ÓÎáûÀ®·F)k¨F 2D¬WÊĆ ”€¾FŠUñÍb/¹–8Õ|S`¸ÆL•¦‰¼Rx--éD]@†)U*…Cp¤b"ª~q¬‹,°ónCH ‚Dx²µ+ùЉ|Ét^knßb|†0q¥x#x)‹aõò]¦ ÙŠ)ñÒÈ}'4«€kéÚУ{‡šËÎÈïïa!-,½õÏåk”¦&ÆŒF™Áµ„‡ ”ZF (e£!ØVUà£Yi: ¦ê8R%©v8Ñ&H<&ŽxRî‡>N`dL½tX8ϤçZï·w³ÒWÂ)†·6A±Æ˜¶BC&rÔ¿Ÿ ö© DŽ'ØV—þ»–·½Þv¨]!gíS¬Ás´­F÷Riétv†ó†P£¸A<„ 5J‘!ÉÆ‘2:8L/ÀÓjPÏE—_§ýÛ/hŠR)>„Aø@^ªÄO6$óm´‰5FÖòG›`GFHJoÁ½–³Ù×¶@—tˆËlPRõ$p!oJYËô‹õÖ¾)³‰ðâ.Ù'®ªs_Yð”@tÅ .îØ¶lcBÀ6Pbp)µ‚>fðvRbk$.†D–úÓÿ;°*¿YÈ–ÙG±’–D UB6®È ­v@6T)p%íhLŒL‡ÄŒ,mm4ˆMì~zQªjܵÔHSo¸«V…§/Ø>â”ëÒâWgÔ!‚™””µ^^‰§ÏÓ· ²˜­(U5±Äx;„CèÓ‰¯ôJŇ4H‹˜idþ§¥xgA¶ƒTœæ6APZ*>*_ÙF·ƒ”âÿè’šÒ Ú!‘Ç¡C¶×[P£m;Âh=585GðwS¤ž¾qh@Ö¬Km;èõG-JÔlOþÕÁ¤CP»X@„EÀÛŠf!tØ¥ŸûQª½^9qü¥>\Öc-ÇqE8Ö.0uRÌómr¿%Äq´ŒN?_ú.Fˆi(Y:A(ó.ªÿ~ ‰Dðö—†[²}Bxû‡$¾C! Gµ•ˆ0+ñ•T/ëì®t¦~/A H¹8>A)_ ¥sX%¸T죽&UD,ÀAÖ•…+Ik7™ÁÝd»Iº%ŽÓ…SNMŠ ŸI)t¤¿ïÓ•2½JâRñ4Úˆ©±Þ8¦×= óbHñÚ½¶RUPX‡¼G'œ'ΜSЈnà]µ´4÷6}~ )Íš‚Ã¥mÂo\±"À·Ÿ ±†¸#tó6¡/@V-€xŽ<çé‡f?AZ@’©â@˜˜o1`8ß¶´¨J™Ø fáPN¡–ÈÅF×(¥ããlUq³0 Vêmy²J넱j#x¹{(ˆ¹³õò¤€Ý³Âpæ\GôÊâKµ#(­$ÖRW¸˜-®+$¯E5[;Á&¾Õ/ëŒO˜„CĆªì¿’Sì)à÷%P£.U¸SÃqà@A µòT¥˜•í\W´>ò@-Ì<Žî!e´¬1Z6 ^© Åͽz‡yëlj×+Nj"†6}|„6AFsê)ôLc¢-@h¯dâÔêµ Ä§Ày]òº"KM¬½FÓY R4>ý”ñÙ¢”B‡Û„Çï÷O çÇ *(R»¦Õ~p»².¿m´1á€âJŽ×9‘‰ðJtš"ž¾‰ŒB´‰ÚÎÀ£á0í Âd+¡µ ΖDŸ†kZT)3A ?G÷*tSª~ÆÔRI#ƒK¼j7.n[ˆ³Ðð¾ãðáb¸€ÈL ¾ö»éq7ƒÐ³è–§^1Ax7,3Áª˜‚ÍÂ'.EãwuÕ‚àPâNd‡ö×û¶·vÊpü3û{Ép?­×AšKîP¦3qwBfC_ÙbÊÑ óÛªÑpAd¥µp½öé=ni†,pp-–Lçï{@í¬ßá´‹ó5æMäM¡ÆÈ!°T/)÷Ð¥µ¹ ^*+…$¥Eª‹álDq²@šã´¡ý¥ Œ\W…벿À·$E"Ç·U1¯-BK:\9&q:•,¦Ê÷yAè¡´*&5U^ ff AËV‡D®Ý†fyë(k'Å ÚGLOgÕp:‚RÊÒZÒ8uá(ÅT«öÚ;¦} ²’ÀJÑt!ˆ1 2Ò7²MÔ"ÅçÅðJ·ûü2M¼*Ķ€¡ñ=‚ø<œÔb‡:…RAd^‚\ÔËñZ ĘbœhUyË·¿jO­Ç‡öÇ–m¥ŠßßWl18Žú˜K©E¶mk 1(nÙV,š@)…Ú â_Êq5"ÇáY]¬¥-é ôÖžl+¡U2Žu34=J ÍÚyU)P¼Ò‚JU×BDLÓhFÁw…TP£®ö¯eã ¦Y‹·­S+Šé;Ei4LœæAh–Ý"Ô’H1Y¥6ä'«*M3¦“ ²úN¹j X#A^üøÝ_[5Ï6«» µâ>ñÀ­G" Á±-Ðam®Ôèm³…!õº%½‘ø]B½<išOgm%p3©íõHPšf÷Ù&<ÓbZˆ`n´®dí tFÞ¡ &Ž)^Š æëzGc õù(ÅL¡«Ðe¢j© *¿à‹[¾mA"g¹k¶C‹}+Ÿ…¥¤(hì~ bH] ŠMLêmQ¢Q¸pô—¿ÿýï=þü7Æoo@óè6¹#ù®QÕdoB'ÃOaWnF (“BPjJÓ;'I¤Ym%ÆkI¹)q€ïP„m Ç?Û_£Ã„¼#ÂCnvÒ†–Æ„b^ãL‰¬dkèL-e%œ¾¹\ŽÔ±>«‘4$È DtU·@]pA²)3™µÜ÷û.¨„v)Ÿw§w†”™ˆ8³¾¸.#àÀ[¢«=;f;@vAñ¦«6e¯Öb|ÓóÒë„Ê ZpΤJ‚<0&$MçR/©ÝI›§~{jŸ%§`x:1«’µq8BW×Yº™ð6)n‡mKgH¯Y#zÜ-³Æ†¶I¼¡ÍÞpíÝù”[•`›«62°€²*“6WPjIAH‰â˜m‚_Ð,%ëìÒ.Y—UKùõ¢I‡jÄ—6yƒÂêÚbÃMiPjp÷Ž ï8ùÈ•L±yd1ƒ/h“¼ËPPÕÞ—FÌd§$%ˆÌ€”¡³Hqеà@,L­};ud¾ ‰ª,Ò¥ÑàYäÅ]Âþ€ ìöìaüñµª† Z»7A\`‡Z¤‰w?©)w9ÔÕèÉ’"Â6º†óöé;i‚ÈJ|¦Tuü­*h"­ÑRd&µgíâ^©A¥ü4áb&€3ûPcµÛ\Õm°VRoúÒðÔ¼6RRÝmW„áUë=Ãî8Þ”WYü¦mÛ,½È-MíJ.ÞˆŽct½ït‚Ôò¥<#ÎpR,"`JðNšæ|ÂþgZ‰¹ ˜·Õ“¶L¾c¶);w9 ¥\c©Ò¦É¿AUà=‰a×Kù^ÕùN lÕýí6|œDÄhŒ`øÿŒUã“== A0]…>O¶ã[¦MÚb£5¢3&Ø8]üRÃ|çÖˆ #*ðÒ¶Rß @–lû à‹[IµÈ™ô5-YÌ>¿zá5v.`")üòüÃzú„ûˆ¦E\¿X'6¯T ¥EhK«6ƒo½ªñC 0CÑt‰‘7AZ‹@5Íótb&Âëê…6‡!`@h¦ßcÐÄI¡}ò@Aß\ªRÈÅë˜ÈÁ”"Ãd‚þXåGšj"vpÕªÄ1<"F`ºjÓ÷àâÓaÚ«òÅ8Œ`üR*ÕÞÚGúÞ†ÎÆOMµR/îÕ>Ž`þ |D´‹àŠ ¡NÏ÷ÇpHdãzMaÑ€L;fñ‚¥c*aRk¤ª S2%Ÿ)!»C麀Ý*° [lWM™Ôh!<>0©Òí Wì¥0Û¸¼®ƒN“ >Ï*ñ)ÀSÈG;ìÛØò”{"Z ^¿®Z Äq¤µ éÊ‹ ŽÉ"MDÐP ¨‹‡KW*€¸âLÌO¿–‰(T L mHÓõøF:&5¿«ÚGœx¯J4{O!Å„°3¹X©€¦kwÛb#Îà;z©™…ãï*ªM¹}ÇY©’ÀÚ}öíÝS¶ƒ^ÌáPnVg,Õ. ™&YˆmYȪü–ãÔ¾ýã(½¦¥ÓµÀ=ÁyÁR¨‹×›   ³FÀTB“* ÐòJø F#£½F^¬Ä$žòÌk¸|‚âÎ%ړ׈F¤å¥h3L½)HuõMcä–Œ)Ef@4>Û©£gJ êå0}„Ô ¦ D x¸”ÏêÍ'¸j`7Ð)’hÕÉJ›²­Já‰`ŠUHM•'åÒºäL|‚o–Ÿ§t˜—ïP˜b-ÒÆ5sú!=Öm’B[!0Röá‹34%žl`Ìù%<æUý|¿­+0ß’öha‹Yµq¥žB/ÛN„Öh>µ‚ðN‘ „>Ž޹gsy:•-?Ù½mˆœ¥°Àh!U›»Up $Èëmt ÒÚÓ)6=T:+mÊI 6´^íÀé$î–\»’´¹Ó«®yⲡ¸·̓Øw&œ§ TÕ%ýå×_íRHÈyŒ“ó#¤ß>+m!Ò$„oÝN(B-A>…ZŠ[—gu¡!¨*8Í·q1š*¯¥cK™5xäˆsÞâoîÈ}ß3šÉ’r~¼ÑÚ­R½FàC\¨Ø ~јNARý;‘›¢×YtÕÈk‰ßb)oJ½<‚cÂq؆Bð‰ð‘+Á#ÄI\»A•‘’ p:/DÜ,± eÕ˜|²|íIMÀj²j¥Ë:fúøŒ¬*¿ÓhDn+È ¢«´F)2VâÓyEà˜|`¿7Ðý³¶UZ{]R j ºJº&Í#˜øºpúyƒ­ËD É£„˜(Í0íßÎÈfAØ—uþЦ‘·r1áI ´L|ÊÈLéʾ¢ñìLº³Ÿ`¸®8DUùm‚&Þ¸ †cB2´4¥íO3}¥8^˜®bãàD4B˜*¯+5ÕzqXd„AjŒoIi1µø ‹-M%:q¾êd1!U•¤ÅÉJMdábƒ¾É7+BÇ×»vL4¦š¾Ýüî¡D 9N´©ÕŽ“xid¾?œ$¥TUÊœ¨xúJô lNMŒægùvŸ«h%>«ñUÖ.%Ë‹ûØ"Cº“ÈK ‚·Fšbf&ãX©'¶O~û”öa×Òmlm)&¯TKsqZ‹YJ™ª>SUrŸÅ¢Õ•N4ŽFy_Añ‘ÓŸlß<º<}Pmzãĺø,eˆ*k pàÛ«:ÁVrdA±*¾˜l:­‡S)©Èt˜ã¼LqœÀNPÚ>©?ƒ¿_ÔIÅA0”it!8!ÉJ'%’Å䛋3DÀ¯×D‡"˜fjcv·/@IDATÆy«) Ýe?¿‰g:ˆóJÓ‡ˆiRG)“I‰x ø bíV¯´Ñøzk/h"JÈGñÞ[)Ó›W… 5bkq"ëJŸO!|U`ä<<¾ AÁµ”íe(2„,P;°ãÜúoŒŒÜ7°–Fµøú²@kwF‚y¼÷ ­öb×(h:ZßÌHY/CÓ(íó+6šeÁçoüëŠÔ·³À¿¢J¢òíWÐ*m†©$6rÈøÄ#ð@ÇN!M1Ãô£Ñf;!A7UªŠÓmF¦F‡‚ÏlÞŒÑ{}M‡ÛA#¿j|Èq(Ûb+U¦«¸û ‰‘&DܽkÇâï_q†8]dx-1• øi¦ÏScUĦ0],)-LIšˆXuíðR<‚“ÒÑ(ÅLÍa!R{2i"Ýs;O-f ÚYd²˜RSToå”fÀ¤ ªRÖ{h= ÆÈU ¶$©$`ªtpH킦«¶Ìº¯ÕŽÌ Z†Ž8_ˆŒæ~ê ÁGkr¸ ´ý3P÷ùNÑ˨±bdñ¶R®´ #ãʶ*Ü–ªê‚$R` í&`µóJ^¥L—G ‹Åüü<>¸.¦Z¬±=¥#¯·~¾ímˆ¹.ù•¢çÃéàtX &)è…ô2C¼fK÷‰°ÈÆl.ejÓq¤pÁ»[اÌ7ÀûQô>#øwÖí@¤ÛtóúNÁÁÄ¥-©±Sk¬·C¡Õâ>AÜA¤D&Þƒ0n|̦´’)!dÛÂgÅÛ*ðnýùÂ…ob4¾¹˜ZܵØÙ¡(°~<µ}½KL_Ťõ €ö×B¹R-½câ?Adƒ:‚RK[CÚÝâ4B Þ)ÚG`ÖzŒ2|qL]Òf .ñ8„JbÛÁ#´¹} nIUÖ) JùV>?Ÿo+´ m´éµORyCNÍm+¥ÐÜ<š*|í©jÏÔ (‘ª]ÉAzˆëUmðÚy]¤ºb šXé½=üF(u.iÊ•ô2ûh‡gtd >ñôµd@V¬$"€”.Ø@S>BßãLM`4N£Ñ¶ƒnÛ“ 4*Q§ pEMLÿõi×ÛíõëB@Î ßðü• }š—¸T2Á|kl7A1þ4ß^âg³ûzðJµô@‹·‰T‡¯·@¼»…2Îzb>Ò©7¢SàèâX³âÔU™™TíïrX/¸ÅБ X_ïR„&öý§ÌÎ6¿ÿ9+¥`̼”ÁM9¯»ÍÔäÊT¤ R ƒ´‚3Nƒ{–#k×^I/P£.¥1Kí »æš\M|-€ËJPIÀ, G7”ŽA˜ÍMj±˜ÀÈÀî®eLTÀwéÜ5Ïž}Å[@`"¼Æ³Ü÷ì‚pÊ~V‰1âĵ@(HyúÈc¤ÌTÒÂÄÔ0¤Ý_ j‡8MÔÂÆ!G£suùNGëVÅ4A?zµCÌv%?²6©]ªQL.n´X;\ $(Uíùzâpüáv«K‰,Zo0MÌâyxÓ¤ '²MB¶I"f:ÅRUq¶*r4U`Ò¡¬a ²*S-¨½b--ÌGn·âé“ — ìÜòÖ.€`z¯`³ÜÉÞ"†Ò§³7‚N%œ&òô]5OŠß1µ°¦Û¿#`Â{ýZ˜g—þ™"&¢EPW—#ÕžTSªŠœ‘[&&‹¿¹h±µÐÁð¬ÒÁoz%`C‘qFFªõÄà›ŠÏ´KhùR>$ròì|{J_Î≇-†—ZFJ!0ßÁ#t"OVÙý áZº=`šNRJ$Ф”¬¡´´gU`]MWeÀ¬øbÇaÖ"ÕųpAâkà°­‡ã)@ÆÑëh½öp£ãÇQ…‚F/'Œ\!®k¸”Q`‚F°†vÕÅJ7B0M²8˜Dü.H‡Â•ü8HWÐâkA@§/s4A˜!“nºæ @%k8‘€dá»"ij-C‡Ñ{ÞmNç%41Îåþöã`£ÃüáWjIéÅ#&° ¼å¥´ãÄŸ)4œ‚˜8 )†'>0fšq’Šæ«êb^€ªpäÌ=(Aˆ¬š ´Ë,åGS’¾W a›(FàïuÞb ¬K‡ARk„Í!]WÊ5zU€è €ÔÎ#ðl ^÷#-hV À“Ú&h¬ë AfÀÞ=Aƒ>ÿpGê044O°=ÞbLGÊ, Æ”ô2ƒãð¬–7ëÂtMªV≿Ÿ´ôÉ"»n1°m}- *Umf‰!,Y ¬’¡Z˜”Õ%EN?Üb˜¾cªR0.ei»Åç¥<¦^1§Œ,€Ô^ZcqÕŽ êE&e¨M|-]Uäµ´g)_ ¿ƒì°.âMA/öX‰/Ø&M©Ôz8¬SÇye1ÉBpø»H‚¥¯>f]­§‹íDªÈ@1Û8b–²@õv^Ý<ƒ¿„!½ÆÏM€iR!MäUuʼnÐo?â}@šŽœQSÝt)Ãq¢Z~lµöhÒ†¶­4Yš•è:N³âhìM&šÕõâ§ß,)‚*Ï\‚H` TÌ›.¥ïÍ´U`SЯ‚˜UEc!˜¦„fMLÓ†8ÀDø>MùîAŠÃ‡8 Á­”8£ ª´4œ5—ˆªØÑežˆ¿WÇ;)\ì,ý¾R£ÞnÕ L¾¿ƒÌRnžH JÚ_S…KS O–­Wœæ­|~p(éÄÅizû«kÁ©‘)>&Pš&šôŒL ¨s‚Òöy¥ ,ri#ÞG¤“T„u!7(Nâ³­'mm4xj@Öh¡b%NS.åóË7„ÄU™*dy½®çÖ®10ñp U¥L‰ €íS5Ð[]©%¥#Ó2Ó‹Ð÷yéjÕ©^Ì}T·† oßç×¼5Øh˜&Š­: Î×—óFóÄlLA7o·Ô LÀ#¤ASBóyôY€CœKÀTÍj„$Ø>Òª@äíMµ‰šéÄIP˺6·åSŠÆ"4”8k[ˆÑ[U×hxˆv†|ÆßûT%’/eª>˜0N¯.%j‚àªéÀ¥8ÛæQ¯®*M¹ 52U½^°4M6=s5F#3 À˜­¨jaã∛¥Ô vè¢R¸Â¿=Üù¦ãP`hżöÖ௄S{š¯·2¦M´82„²R»¥S¯¡YRq›àødw11K\£A|¹›^Õm0ƒ( øh‚šÑÉzXÒî`¾¹¼”¦ÀkàóèßuoC:@¥µ ¼Ì|›4i,v„m™µŸÁ b çŸø‹Žmt'G•v)‚ òzZ‰"(5øHßw¢Þ=¡„™¯%eÌ”5ÒlD"bHB<ƒ ’ !"ndÉYiûˆik/¾MçërGÚn=$O.N'¢YŒ¦i¨Ôjï×Â[C—ýŶþMÁô5×ßQNFA Ï€îíMÐÒòµH1yf}xg‡K‹ÅÌt¶Yãlb4Õ ¡©¹Ço@Êâ¨Ö+(æ#ˆˆÃG2i"n DjÛz;B1f„&òh,Á­a[´R¥À”žl©SØŠ„¹Xœwáh-)¦¦E.`º€£Å”2-¶Â‘ò†“…+I¯Øçž!‹l74iíM—â(yÓ &«jn;(5¢׿vDˆCSÊZCÐåHïœÏwñ½­s‡«âÓ¯Jª[²U% ˜ÿaMDˆ,EØh $Ÿ¸Rd8ó)ãµ/ðù]GÚèÆíŒ-¬JMI‹ }©81fU[c¥–q)·dó-f"« ^A:‘N‰£ 7N|Ò÷otA²é#L?/ŽÏ‘J¼’ôH,mª„·mdí!>)톯7pû‘t¤-²+îk34ëåxíñ›ëöèí ‡ÄáõvnŒ`jzL‹ûéOhÄ·*št `2 B½bA[%eº‰Ô€bL-n~]í38Do¾qíÀûad=jL&BœÈ Z,Pug΄DŽh4ˆ÷TáâÍí­CSí'Έ£%5R¦ r–¾%83Z)µx×NGéÏÛ%…»: ¢”`½Òæ+ÁY «nDYÖnõŠõ¶mÕt¬'2B:˜k¬‹?ã¿ï >¤ÀÔòô3©RâÈY |pA„ºòÖÛm»¨.¸ê¼®.BªF` ¸ÒZÐvoÀðÖ0BÉ ÐÏhC·ž›~]¥îAÀ®Øgbs_¤ö.­ ßÍ!™¡¤”¤ÈlsÅíƒ °dú}¥à•z©øÑïãÛqú'B-‘3õÎm¸ñç?ÿ¹¹JÉJífÕæV}Eà ¹=yör:)óÿY©RlÞlGj!¥š_Q1k­;ñwß\!USv_ø=cƒÅ4[ô=÷tBæ+˜'‚©³,)èÕ¡ÜíZRÆÔ5Yk¢GÓ8šøé÷.^ú¡µI„uÕËÃSkºïÙ¾:©½Sš»×ÈDRzwRC;x#ð•(ð2Äy!ÆáðLËŒŽ­h)sÀÎÌ(UÅé@TIñgÀMqÌÚ¤`w´¾_»‰Ÿ߇¥W5A±.:R @ÚƒKœl/Iâ^N´¦kdèDªBߤtIq” µ|ÅN ž7MÜþ‘³ÞSë°=ÏbRšû9 ¡éÞL`¢ñ-@Sš².½ÑbŠkhAƒ¯"eU‹ùd#÷K@sñ;©´jÌ«ôù\ê¡ÐHûæÂ̺±¶¥Ô¾ÅÚ¤ÅÚG 3]|^q½RLÈKw M)nt|^{ãH±ÅJ[`Ûºœ«Í Rnd1¼€ÜÙÙ2 R%¢êÅcHDUɇ·¡wµÏnÈÖˆ–”tpˆ´.L:ãvÀ¦ó -¦âÔBDØ’¥§{ÐUpeλ¤*v"û¨JIö$ˆ‰Ó2õæ‘•\¯Þ>{— ZTwAxSŒ{cÛ·³é˜Ú{jbU¾Cõ- Ac‚L5ⶉq4“¥3‘Ä Œ¦7jÍ=þ·tæÝ‰)ÖèÒœ¨×R{ß2½4µ$W¢Ü8)~¾UK‰S˜².¥q ž‰‘/öùÃLJ™øÎ+Prºs• äl<Ñž„~1¤I“ÛÈÔK zB;@©WJɬNžì«Ñ.HV¯]™.Ç "è¦|…h „‹·m`Õ®8qø î^àV5ÞÜüîq"³g×e¨X{;k !…¼}¤p:Z"c €Ý¹à[ižxúÈ@j¤ØôßUÓoOªw÷Ï—²F JÀD:H Ÿ‰8]!…ßîßÂ)àSËð¥hÖ€tQ‘)0U AxÐÈÔTý* F¨šxkI9Ÿ¸R-FÓì\àh8tè‹\ŠÃXiÇQM\f]1ÅÆ¡Qf" Ù«siÔåÆð¥bFI‘µc–Rk"¾*¯$5bà™q¯H Î1Ô ç;)|A‚ÚÅht2g±³­êvþs;έ :H:ü&¦ùŠ}–Ô‰–Žãððfñ} ¨F†èe¶Â$IªF´¤šØh ‹¿%)ô¿Èæ6Ò‰–>DÐÛN°C < %¹L ë2D{%s 6½U#4zU¯ YÚ‹KùN±@•%X`DKâ0£CpÇa[è"hDC`ðtÚyËôžÛ]í³!+~}dípBYÌ *…KÚ/ïm#HëåIñï,V‚´9‘FDÓ®Z ÈËñUÅ.áOúïú—¿ü%Ü8̆’­ YŒÉ·[G¨ Ì(@,–HŸµ†“å‘w(q!¨Ù…à°žWäDÄiâwc¶\W-~†ú/°Ñ˜Í+ÑAèôþç?ÿ[ !ñJ)ð8ªÄí¬ ¤ºT¥LŠ“&})Pà€¤´ áÄí¦%ƒÔ’r^ Þ#€8ÞZi©€Ñ'‹'„‚`:Ò›˜š’¼…Ûj OŽØq&‚YU°‹['Zø­lz‰›Uû˜M‡{EëÚmDã0©‚ÔZ¯ÇáƒÐ8¾–í uœ)èRŠÃ'µ¡J¤ZºÿyLë·;vjJY‚>q¾«=ñ~UÀi¨’®,…”MVÊzU"ð®çA¼×~âdÅ[&6T@RÃG–Ö%¶aÊ=Jh1U™¸…-æ€zµðpüC½qOD)²*‘bçr¿¯4‚Mê­ôùßN ä1$*î´‚,Ñ<¤ E-_ÖyÒL¯‹`bßéFHÛŒo]þ Þj›èBS#r韟s@Ö8ÎÙbùÌÚ‡H—b϶jaÕ¦H½ýn_Õ‚y:J¥mÒn¼NÕb¾å«RnÛR"“*™å‘v£ƒ¬$`pïG-[IjÄŽ/f@F¡)µãô‘6.æøZš¢šQ`À­½›ISµMíVªê)+Q—:‘ AÔðw^°ŠÃ}G (›ÕƒÀÁ÷Xy;ðIE€°?ŠG¦€†@“oCAÕºÌjP 4¸§×È4Öû¶×« Ä”j, !¨+^ÊCpZÀ 8Ƥh¬‰éSFcVPZ¡ƒK÷s]°fp|C“ꔬ’Wˆ8܆šqøìݤ…ј5öª@0!.§“¢ùò!gm«„³Å M’¸”`ëõc²÷‡B²cBÄøY„~è†+Û˜AØN×ÁlhD Kuab†ÜÁy Ãvðá‚…Ÿ¦ß3ø¶µ†Ø‚§ —vê.§Íu‰MLˆŒÙ ±Àû›t¨!XŒi”2íÍMPŠ ¨¶¥6 il:Ï0Íå;&œ&(…D! ·¹”-êJP —òÍ…Ç·ŒÝLÄa@%L4'_•ÃÏ€|)¯JÄuý ¬«)Zb";‚MâS3]‰iy]ÕöO7ÈAÛ6¯—ákWͤž»Y­'eJ||±v)å<¸4q(mJœâ4•àf ,ßþ§Fü jçãëeé0gÞ˜M‚S¦¦EªÚˆ«ñ»…ÖS2Bû‚@ijº(ð¾åŒK*2pd1õb÷!"KÄž<ƒb"¨2¥Íž²vÕ63)Ÿ¸‡ 0ùŸšôHßÅÚ*Z'ªÊgc.@ ¬±»òÚØ¡. `! „Ô¸ö¤è(áôy\¾´³4ÈMÎ(°Î¯åÇ  ŒÌ»FÛuõ嬑/¦)ž 0\‹v¥Þ«N×¹”˜˜µÒÙìû#Hp»ÄLVI¯Øž4D¨1Aˆª+ XšU'‹öÚ@ËLI¿ƒPì÷­ttáÀ[€ ×^³¤”ùÍ­X‹ÛnhLR˜õŠÛ GÊ+ 7"2p©%\ÀlžÕ¥Ä¤Y%øtTÍRÂoÕÒºÐݹ¯GHùô{‰ ýOHY 3“AXSpše“~øÁy%620|‚˜Öˆý%Ћ5N€ŒÆëröh<ë­®K_jó–'"€X )bL: ª T‰ BünцáæJµ£­KÊ/NY\¯êꃠnD]œd5JÓ„´*ßUûÎ÷ï…{KûÁí³Àv‡䌹fP"4Å)« vFx†3¤¡î'°}^&…RL¦‡8¸•šØ2@#Å.ýðÑJµ8.è€i*5‹wuÑ(0HÁK‹9)#¢ÕÅ¿û;ì¤j—Æìø{èpk0ˆ˜Äï¡´•^`âU-•‹A«šT1‡_ Qà¤|OAªÑ1YR˜Èb8Ó•Õ•8B¦Ô  kÑEŠ7Ž7î=¬K OJÐòâ; ²*r²øl#J_¹õ:„,Z#RK’á˜EJª4nœT—Ï;‚ *Áø-€Æ6Σ—Ò¼ðùc[§#n±D4JÃi h–êJ6­ ¡Y;Ž.~C)Ÿ€×xmj<’k$¤N)ŸÖª!üĪ’RÍ:!)8oHã OP€ÀBxGª¥Å4n=†¯´.±k’Z@ÌÚAÐ&ÒÈUÑ\Ð/"<…1?‡ù~ÑhÇ´I Èàí…À‘¶!)©Ø±5ºªj̤4û¼íµ0ˆŽ†’ÞÍÒB3Y±ÞîªãHY»é"¢Y Ç„¤ÞAL24¾õh8bÍyvfß'8&ì]€@Ö ºà]KÌv€`BÈŠ5‘ÅLlm%ø|­vH]k`†óÒÖh(Ä[H¦v¥,å8b Mœ¤.[M¤_XË[Ec”;²gÑtšÈâ+ùù´q®à–Z'K35HN1öшb›Ž´S;Tå{:mè¨Fà×EVKü564ßb|½‘ñÛ­*¥¦$eÔká©*€àdb” X|ˆ€Üaá‡z¿©üÔà˜Ë’]Ù’Þd]JÔxñöék¯ !Ñh4Ö ¥”’UêÚ?f1&kÖÆI?>»•sLM-ƒz”Z”¤ºøÈ`L„{%FVMS Îõ™ÕÐÚÃ)HÃS«…”û%jân@ÚzzÅhRq üPÖ¥”šcvÒ†bj‡´ph¸ßÒR¥Þp1K$æþü8K‡ KLGЉ¬*ð]Í3 ø66N€£A;„A:š¡Z:A l8N¶x:ÚÃé_âq¦[“TjbÊwÇß~!ÖâBèlÂë21‘Ž/í ­Š£ au«Âk÷þú׿ªï¼ÒZ€LÏ”¯‘G°ï§)ÝCÛ&K$>#úN"íœZ½ù–éö¬])>©ÑbíÇGàã#÷r*U-Hß{&h]JU‹I±vÐ+àñh¼8\¬…IÃÅ}Þ¥1MÔU|¹¾¿ÆLŠ/pFAK¢YøÇD¥½*í3~â‚«w–´ƒkáqˆ.o#ÜÎðøJL é‰HVº•”NÃ}at±†/ÝÜî^#?~"¼Ýø8††·!ÐV-FÊŒ¤{@H-my"Ìaû •¢¹q,A‚~×Õ2âæ^îq”IéÂT Ûýò¯ýË_”ÕR³1.íó´ÒÝö·¯)²ã™4Po±Æº õÖüö»­¿ý-p‹ÖžGv§‰‹3²zÅÄ;ØæÖ.Õ®KŠVì¦ìÀ§&€³¥ˆÓ±ÒFˆ“Ý25ºFAãz¢ÆIµëí*JÅJ¼£%‚ÀŠSÛæk`L^LêÝH“q¸ê’&®Jm ˜h­Ô7Ávp'­Ç³Vª·}µ ´ð­$nÖÈ b2›¸¥]¤X Kl®À2¶ÚÐÓyß ½ŒàÄ1m¢¤·"M¿µ¥‹ã4+5½K ¶švGî]Éý7¨§\ ²Ý ˆà;8ZË[•C®Ú HÊ¥˜mÒJu GKY¼eÒï AVU".vÕbÅ2âÝ?Bã´×RŠÜ>Ò¶‚ü0³BÚdŸ¾†šH3YÞÜ ¶3ZÌÖ3ˆaÒ$(Î7B*ˆŽibx]¥8fu˜J>&³ ï{Œ¶…õzoüža·Zx¹@µAôUA^ÕÝ0BãZ»F ¸Í•ª¶L)Çd-ISРDÄæ°¼ÞÍUÒhLqFð~~ƒÔd›+ Øèíƒ,V5¥AëìpƒÎ¢÷9ò8%¥…* ïš.LY tŠ@]µTJ-Mø41½º™8‚É´H³ÒÄ!R#"x¨u:¿ò:r„|»Õ(VżÇúü›Æ…㣑r]!RÖñ{ÄF«VÒ"nÐ.GIl f_ø¦ð݉€ ï.ãhú§p–O¡YF@ˆ™¸´Kà Ñzèáb8e)Ÿ‚X dtšUU©Uu Š;£–4+ĺ %÷¯Êº(íµ4±éÀ]µX “"4ˆâRÌÎ…A†°ª¤TÓçá4oý|Q ;&&PÕnb7_{1O$‚€A42qûàK{C &â£9‚RÛÂm¨%©vC—TÏ((ÁyúV%E.Ö¸wr›ôÚ ozW‡ij@±óâóáMlh²8‚4›Û•À™.†–) ˆd/ˆæ4ж•Z ÓJÓ çS†#ô«5ð7‡ÙpR¨W 9o ¹‰ª•,FD×ZÞAZ0k„³Æéó™v†©jçÄ{»ôbžÿ#0¨=4Øà(ÝÅy)!ž ^ Á!~ju! ˜ ^B{&Òñ¢åëšdøÌµZÆÃ{oa;S°F:È5v9± Îní½vœ3ò^½ï%‚JG @°jÍ£ÁãG‡ôb9…Þ@x{Jšl"©µ¡¸µµ8?CÐ¥ªËn˜þk0ÿ3´M™TjR³˜`kŠqÈòÒ˜yˆ¡¼Y‚¢”!°ºxÊWìó1VÂFðìÜ¡U„¿Ýg%´†ò}°<Îiø’£•VåMoœ–• JíßÈZ \‹`g´-BZw+Eck,À´ƒÞª#”¶sS ðJL‰Î@4¦j6ôcò@“gµ»ü@~¿éZ>CÛÕQHD)…ÝR ¿Î,½Lq²'•eíb´v6]êµ{ôU“ê8õRcÈFtžIS¨‹ïÑ(Äâ÷f¶¾j‹á×óîÂÚÊ&Úɺä1‚4Ã4+°vsgÍí’NW¡SW zkäÅð¥o02Ž˜2Cè€V¦É+I=ÄË=H#Æ„kWªK*0ea¸@ÉC‰Ÿ&ãàªJmÕ=Ø¡[â·@LdL:JéwU_ ÅhDTzÍêÁuØ“QP-Y8A hZ;K„<¡A}QC42‡JÜí#Ŭ:‚_Dà¦k·Éb`KÒt¥VÅÅÈ@SšTÏ×8)2‚€rdx×+¨*5 ÇÏ/H[E&Û>8íPdZ€t˜@ +щéc²1á OM°YÚyñ¦ÔˆvÆÜAµ`:2)íb·$`@>òŽ[¯¡­:N"5F¦/ˆP¯}Ìj\„©òzùzuYR*ðÜð= HIdºzj„5 Xœy[i‘&hÊÞdi-hÐÚ2Y"ÈHµ9Á³ãÉòvÖë=áãtŠé8ŽvÑÎКµ¡¤Ì*¡ñ¬{Öe„{[I£jßá@1~ï縙tB‡8>\lí>YV…Ó¬ªD(@À1ù4)8Ëø4áÒf!ÃMdN,%hŠët"R©íˆ˜ZUÈ­øã¤hs·Ãùo4T(´býÔ¥-dj«¸ÖfuÕŒìat8ÝE‡4 HóhÝÝœ³1KÐ’NÎÖ¥W ¹X©F^c ²ØùklÊZxf¢–º-‰O³¡•à×¢ˆ”¶²o:ÃLÓaÅL‹Rj¥â[ùüQ¡5]˜5ºÀÖ8º×´ø«šâþÅyëuÒ^8„™.Êh¦à´³ ñ4ÃãðíVIªj1Òò‘!ÑZ;ò@%xÓ‹‰àØ–‡»7›ÁRÖžíðƵ<ÜñqzW¥âô1h‚¼¸·Îh%†“•†ðø<>Ch"o½sßÛâÑšuû>÷œægÌý ñZ*! =ÁfAÔ˜&i0~` ‹¥ª˜jîä½ÏDÒAS‚°w5J-ÉT‰kaâ–äª<¼.&FC6šAq¼À)ˆ{¥áŠ•¤þíä}Ë£©jOªÑÄã«BÄ|—&˜¡1LàSpóiv-JD ºñyÈp¥6´[L^£¹¿'©2|  )%&u|¥w+F@ð·ñ·½eZøÿçé·*¯—Ѽc».ekÚ(åá 3Uíhbj­=PDk¿}g¨@º§qÀ,¾8}„^ 7àg„F¥8Jé`~šeH7ŸNMoí8â^ k3qÞnf1qju•j/Ehm1µ›¨BS@ îc¼}ìÉ ñk·üÈ=”L¤Í›B*½ªÍ‚4+>¯ZsÓo|[ù´‰*™ÕiCçgÚdƒˆm[Ú)d˜‘ªÈ»ÃtÖ•rSZA•udAIßPß¼Fší¬¥qp4)¯J°¹ijiPR)·€Fi½‘‹R½À–L'$PŒ’fOB${BΥ߯Gg2 >‹0ÄÕ“5¨XŠ@V`1`wØö„˜(Å銌K®‹AÈ $MH4ÓuùœVwX~jZšEÓD%]éðÈô×"FÖ%ˆC¿‰CΊ÷töWBPööšÒbðN'0—”›(^J ŽG`P^‰xsà †KÅhn•ÛS5Å>Y )©F·§ër?_/Zêꇎv&€c:”^ƒÚ"¨¥Ò-)CXÌy;D8Êÿüç?;^Ò¦ÌÛhj)/ÕâºÍî>¤#˜%f¦ˆ;Nš­A”vF*r›4K‹™¯Q€œ²Þö—’CXœæòR¾R=RZ ]ziŠ[rº?Ÿô¢µg:N-k™&"ÇotñÅ>ïvûð@½£Q¶d_ÄmåJÑÐZ¦w£=k ðÏ—†O X#/fUù¶%(7¸YZXf.ͶrÒ8–¤€Ã‹SèŠt9D¤Yh– ßPŽ•z.†Ù8jZº+-ª<„B½‰k¡€‰Ðbq¤ ¹Ÿ†zUy»5W³¡p‚p¼ ì‰Ã§FÎôfp)¼^ ø—u\ 4>SÚJªÛM;›rŸA÷†“i·d#/h ^H:/ ÜYìCÓ’)ot|ûãˆÉÚ95íR»)éR¥áIAàRñëÆJÅÈy…õž?H:[Ô:k7ÆNŒ,¶>H}GtH…î‚/Õå<ÎFªX¸Š1U;$ĸ#}?rÔš…Ðnèè"ËÃ¥ù½pñ{ƒ&zQŒÃDà{HbË׈ÃÄmËKµÄ§ÉK×RÚR%Dûª‚Ó N܉Œ‰“ÁÜè®Eê,º˜ŸŒj¯Ë;.‚ªˆÖþ˜@q›ë !Ò¬¦7‘gÈ@â ÂÇì2‹á=—<ÏR@Šk‘Z£¾§s¦à¸d†©”5.€t?ÎoIû1⇂SIÀºž5, VÐÂÒŸ‚’Ñ™@ªZ¯ê‘¾Ï½…[lH½RÌb ZØD%)ÍdÑÖX Çl%›¬8eKöåØª4ªî˜ÀVª7æ}žB)š¹”[¬A©5%¯„t:Ö¹€±Ómy½b¯(Ï4jé ÔˆÜP¾+Ý&öŒoA©Lqid1°}BHÕA܉âð;f½ªo[½Ô˜ÀÂ5&‚ŸY¬‰?‹‘­Q$+ ÅSh1£Sòb½ÑF~ ¤Ü¤kÇG0‚¯— ^¶ÍcióÔötªòÛG€“&qRø@²âgïhÝr"ÚqêýŸ›´ƒU :NU{ b¥Ö˜f§Fîë’»[I1y]F¡ í Hñ7BšAˆ#ôA«`/0Ac– ØVv ¡CéeKIãÿv/[’ÝFEJ?ªçZúwrÞ8F(KÝíÈ`nnîÀ½™U¤¤6XŒÕ-Ñl 0ir}™ÇXa©€7X‹šò1RŠa#¹%Uf“íWêZ+Li›=Òâ;øyʬŠF"nT)…þšS @ä\­’2e«.HÑ ÖÛá|QÈrž¹^ž‚tÏP¯æìøœñ  ÈŸ€©/Mägå±bæFPC•ì™õN‹ÄDZ)ñ+7% PÓæ©ÊZ\³sv¡JIÝa7ï€ø†Opt÷)„›Òlæ÷Èè¥\WV ”×£©(oTa Ù^ø²z…YØy#áî0ñ¾~3¦«àI×´rX»Z7Þ/½T¶Üª’jWc%к;‘íD8*ndV°&ÂæH&”N1C|ÇÜl]”iá)Uf¶úÄÙÊÖ®Z|·¡¬ÊÚ Ä+CüR9l ¬œò·þóŸö¼¬­¬ Ô¸«=i³—¯ ¤ÌÃØÐxJ[2>Æ9‘;*±’ìEÑ´{9ÿ7²m˜C7@¬›[b䂬FVX–¿ì{› 1j‘é1€m@ÖVTN‰q.Ùf̼̀³ÔR¶VAŒáÄk'vŠ<1ÄÝÒÍŸwKÀªðô0†¬aWòùâ“¿F°”ggõ¤0Ö~;©„’Li kæ i+:~b%ñÖÊsH†é/ke讬d¢ZnZØ6dbX ³B*H ~3`4z£B%”zI9µ-ÞVÀÊ…”{³f'H9ñ²ôH«hlJÙ)9db¥±ìa™Š²ÙTq *‘ªê¸GIc[_‚4u”}Örž‰»6Ÿ…¬FY…YuÒHµ•›ÐÌJ(™ ‹É”ÌVwdBÖ?è´UhŒZã{¹mìÙv-€óîDçÆê«¦Idni*É-†˜F¡ð¦â#¥$~“ð4Lº72ØŠoŒª®ð|] ‹zu|YU°hTXêý„fγÈΰ”u ,ådcêBéh°îŒ1e·ç€Æ¨…µv@ÎVUe€#(d’ ÖdH«Ÿ¦‚¾©é»…š!7þ¶d-ÜE©’2@¡ÐH0 0†o³L¿ß‘²fj†[‘C2J79LS¡w ÏÖ‡T;Ýme›¼7#4–œO€2Ï#º!+"•Û¾&ÙÊ*² ‰ìø+Ïꇹ’µHi»`.:)7ž½oLðÕÂô~,4Í€&•?Fj8óÁlT8’¦B  µZÀkЭbvR¼°µ&Sn+8[ß¾u§ä,ÚZÛvoŽ)j¤öuÈÓÇß;W8ܶlµàP­g«B<œF,œK#«ªÆ«Y e‰Uu.X*F#±ÖÄRÝ…™äOF\Ç”Y!\¶mã)¤‰ñ1©¶_Dˆë¢èz ›A£¢¦ÙTÖšr ©…rÀК>g|…IJª0Å ®Á¹¦õŒ2d…äiž4êÞ½Ùv"$%1«¨¬ÜÃÚðz©ƒEå±UVd’i› qÛÖ¦mÎ ¼Fœgžx¶@˜Xk÷9A妑a­wj;£T¿“01 PÕœ¶0ÃŽôÎ÷¡)qVd0+[‘= ”g˜žc€°0IYzb Ä“™<±-’° ²R­ž©Ú•‹Þ€F P—¶nZ¨2I[ ­•¾ªº79^ä³,Ã÷l6—Æüò¾œ­JyºJŒmžua+"y¦lmK,h¦±Ž‘U‚±ÖZíoÿøÇ?$ ‰³¿s"5>(ð²H}å s¯ªg‚NØKãI8!’ L–›ÂµLCŒáÀªÂ0&^ A+f˜ ÌœØûêÉy<@¶øÆ£ ,{¡‹­BËjAÜœ@> ;B[â^@4CÓv4G„lÅc€Îk¡I %ê[¡m-Wòùôr5¿8ýnøÏwÍJ/çb.•ž! ›¾S»CÊfÈD¶mc«Â·áYÔò!¶pG‹¬Ö*+&}ž­uùv8'U›Òzš}O7VX¶a:šÚÓì>¦Í@Ö0‰ëˆ)£Önód4¥¬1HÀVÈ [΀”׬IZ¥T‚hÖTüØV¥P gLc ôÃ@²<1E$ÃÆ«)ÂV˜@¡UU|½ªºò£‘ò©0”€O“Õy; ìþemšÌ§)Èb:±·ŽRªŽÙZÓw@‚ú"'@*i~¸¨Ðj+•> r‡tÇtoñ†¡'FZ!Ì*1½¨‘Ta›òKœÀü¤Ô@IDAT÷¶ªÌUVÊÊ[2Û mcFÆXt$(•[z¨Fß:Z× _67¸h ˜²”rQ6¼§FßVQ-PÖ³Ö×M®»+åÜ&r%È#¨ ›˜^4FOÊû&Ûªi…ÖB;@I…V2[§ÈY–ƒˆ*äIf[:B@öеPØð•Û*71%,¦a.ò1RÃ$Þœ|lUi `à:b´CÆ#>ÈZû¥cÛèˆ1mó0ÉÖKØZK)ñó£$“ À ÏĶˆ¡GÖŽà›<Ç WbÃs“Ä´µ²â 8ˆèEºuÇ pd€@¬„a« ³–B†¥ò±ª]6«Öu!ÈǶB@à­³ºÜgÙËé>YQö ¢i+?£ƒ̰,çÈ}¬Ÿß"ÖZa-°ê ‡…lWá¹Ø:þ J &eKÜÅ2煮›¼Žœ™XÕ63@&FÖVˆdÞ 9¤D’aò©6g¼1š®KU•X+—ÊÙŠÉÖ®Zâž{[²9 õ¢&³šj}ݪ­ªd Y%°`âqgŽWî³òOWÈê˜^­-L¼¯¦ò.§ÕMn’<Ûæ`e˜’•ÏïçkÎX†0Ù¼¤aÅ"£¶,0°i;&Ž\K†4‚>ÛÆM֔ʑ ´›U‚´RŠÞÑctyb䬘 Ò`ÒÁVãY»eØ+n<š «–ƒ—ÅâÎï±¥LÆÓÖc3' ¯iØÌ>êš2©ï±¾!¥D&°Z%Õª`Yk$ÃX1jé+ùºžÿüÊÏ]¹í4»=& dž[3 2GëOöHÌq¿©f@hÑUà‘­”ùߢ3•F4.Dk$X‰l2 žÌéÖ´¬µ]¥Àà `¥|ÖÈ Àˆ )‘Ʀ¡ÇóA ÍÎ3:m¾çšPh](¯;qäµ<ä˜+ÒÍÌÇÖqº¢×'%+àåW8@3Ù¦ò¤üfœ¦›áCÖ€TUøº\Z®áÓO¼’œiè¡ÛîóÎÓWêŸuÊ6ª>˜†Ô”ƒ,ÀGªi›P—?þøƒ¸ÇÚÓi¤(ŒX-Øa¥P¨ªcr«6’F­T!n’¬dmsP•²Z[2à ծ\ lM`åÓ_:ð®‹Mó§Ä#‰¦3YGYO_öV|þ§j×5µuó4ä\ a„ÃNŠÉ¹#ƒ-MúR*ýRdú6¬…üï;o]n·3¶Ü L8Ô¨‡…1OíÈXi´@ê‚ÕÂýÖ¥JJkkâja²Óðj P_©0’€Cš°5‡VÙ^?ÛLr°ÂjݳVÇ·6^dB&vœ Íð4¦#—š¦*>9ôîœØ3w!…Bÿu>YJã¥G 8s€c`qó§µÌ€K°"yšÇR‰­­ø€‘È8K•Å7•-¾-C“œN÷¶Ô¦‘¢Ñ7eSÁoëoëôVóÙ)Òó:…îd 3Ùúy¦‡é‰E_JmwnÛ«BÃDH‰+üܧÚàÅ+ (1›Ž¢a*ÁÀdšæà»—'&Þj«Jx7zå…/‡Tq a+¥Ï@b¼VVH¬P`KYm'²*Á”"Û¿ “ƒ•@T®¤÷j$^ ׺Áliš(keŽ´ÒÃʼ1ñ–h¡PXUM¶uuVÛîY¹¦°eb5’<±™…ëEd “¬^ÝÏYÏb—Iƒ´*©Ü¶°Z5*½K>ÿ%ÝZe'¬˜Àv8ewª¥T È4N.t¥±ºJ< lŒÈß*Øb„Úp)ÌÌÊZßøá€ò½X”œÐÌn6†¸.¶aa»bÔ2´j‡ir%>0VçµâeKLàÊ7$&¾Ë÷þqÈÜéÈ0:Z…-+Û‚I HYñª>eUi¬›„ž8Ùº i8ô;Z2ÊÚow[µ½¬“Uh[Ô¥×à8ÐÜy?KÝË6¦£¹^Œî‚ÆV6_t|J¡¶òÄ­xå7d¾@ÕÍ©g+¾5AµÖÊ“¹Š1e²JºÛÜT•-U_ãUέù‰›àæ€a’-¬°‘h”ÈÚáE[«Fxã½å‘x¡6`¥Ï |Vz¼r†½BÝsƒ1§·"1²µ°*¡¯0·ðíðY0 “eÞ0øRm‰9P—À†´ Veûkh¤)ž Üä·íYÖËáF©ÊÒ“RÕÁk$EÆ$¥Õñm;š¬ò®%}­'«PGAÆÊ²À𑚠=OÙ@§PÕ×Kb)ÀZ ¸‘á‘‚¤CuÙ&'F–µÞêÏ¢* ž•­h`Ša€ç=Óç“ô óÜ ¬0_)a+es3ê†a‹—èó”Uåó2²ZY3½ÆsÎx§@ÁVb> e…­PŽñô› Ù> ÛEþ iA6B¡© ®Ådõ²¦—¥sÀ ¶ÖjY×ò€b[…‰OVHÁŽ“3} P‹™c`âz¥\_¼@ … $M[8 +øÔ|ß¶˜OY«$«= ù¼+ÒÁPNI­ã1ÜZµkÂ2[Q•¬gá÷øöçO2þdV)«‘¬BI$¦I ÄU# jW¯ÉšÍšƒl‚ñæ)Û`l»%MªÔ¦×TÊ…Ôšƒw,Y>²"±l r%ºÈnxó0!*âaþÂܬ”ÆÀÓH‰d3ÏA–­BYLU毲O½- ±Îáe´èf?ɰ%Ö›BbJµŽ—L»µÆ›I¨—›¦á|¿ônaæÌ“y[†°p5 m%áZl­¼Á(ña«ªn\­­º…@½\BOŽXéKß ‘ñHn°gæ•c8#µ¶…’ F!`+ iªe›XÓXkT-œÌjÑ(ÌÜ87›Êæì¼dÚxd¯ŠIÝm…ÿ%~>93‘Rb›¹)ºRY7£Kü²97v[3ðÑ‚!^Ô÷Ø}/ŠƒÇACéåÌ k—Œ@¡UÊ©» $¥Ú¦­ fBC,TQ¶¥gh€fh[X„oþ¿~4FU­ g%B£LRÖE6Áʵ TØ*[Ðð¹!ǯ—ìl91[`>™ YÁŬ”cš³[RˆÁ#É…k÷‚²@%jýMƒQ/†ôFê±Rz(”¶V8!Ý1AXV¨µø¸YÕö¾uÀ kÝ©uçé¡Ká[¥òÑ´úk­õ"“¢çÃ(Dvð¶]£¬À4¤¬2阔 —m0%Zð'ÈÖµ@V‚©œžæöù|¸†Uktþ²çû7/ewb}é¼°m2+Ü5R24L>ô"%~!KÓ„ML…Vƒ±Ê¹?”ª'œg‡ÅcÜžè¡p’˜låmù˜ÁÚÅÓ¨µ"«ª¤^šYQº1>e¥D[ ÐKZ(¡±RGú½)—ì­ëªÝ¬–¹It¡Ì æàm—ÂB‰«“°ê¶×QVÄógr3ç‰XÁÊ 0ŒÑl™×‹fJ†9›­™¥ºöŽYI};Å9ÿ þÄ ç9„²†©)f%?€T§¨‹ÌÜxÀžE> ~}̰á¶Í¶ ‘  Ãé[We€zU[Ç&Ìd7oHY+ÆMÊÈü›³‡ w'RÃjmUåŸ!œ…d|žWŽÞã3aCöÑ–EÂÄ.³î ×—žÏŽS¡TâVšƒÅpÞÑ0ã™§4*Ò︾j€L¶÷Ê̦Ï×zd†VAcmTJ ‡xk©øVwj<ò:}^%Rn¤”­±)uŸ¾Tâ²î®#p#ËA‰©ºº(Hk“§‘Òújêk’ªR*T…‘%ίˆ¯ c+ÈDcJA`[!ÊNDܶ²ª­ÇWN#åóiëÃ;ož“1Vcã[1+%H ?&s3Ô‘ÌJ°6¡û!ð*Jq³vcÜ´¨ªa*ô¹ýk$dªÙ¹¬?BJ!R;n)_ ’57a’xã a ZY`n@ØÊM¹z²”«ºÂsK¹ýÈæ™&C2“›Apž¾*Cbò!¨Ð–@!P9Y)>Y„7R`«B‚ùÓKiŠd«¦a\Žc"e‘0™fgôè¥xö™Uë=”òLi˜$KÏÍÏ9%ôøÚ)ß<·­QÝ¡­cß L0Êy*´õ#Š!`ÝŸÝ*q<ÍJŒÓe­:v"¶…ªÈFå¯J-ž€23Y¤mÎ_›3!RŠOºp†BVÓØ00Ãȶ•S4¨6[šÊ« çC 4Ü`VWd• `XU5D;N¬4éÃHضj›ù½´úÊöGˆ&¡W(šäô¾ leUujV¶°àfkõ¹¨Q ÁæÁh§»Ïì£ç3È­kÁˆ<ûö?ÏÅ–´–µâ­‘¬„ŽÓÒ‹;‹Bþ•+„½Æ•›/*ás½??ñÉò·brøôøNÛ‰ÉbÜÒU#ã­É2ŸFÝX£võ£ÙüÊ;Wn•ÃmëN@¯)CØK(Ki5ÆT²â™b`…¢G¬VÊ\/Ù^*z87 vMbË07€Þ61L k‘' ˆª2+Ux«­#dÒr/˜Z¤ÂH#šß$µãŒd5¦F™Û6@ ²8®ñig»áj‘Ì­ º%Õ’åcÅæô‰=©~É6^/ƒ,%™ ÎúúkM«Ëñ˜:B- Ã>Ws9±ÔV¸lwb˼Ðö·ÿûßÀŠ × )Lf ˜@޵əذm UJ@©N蜜CY%pAÖuÔËVÀ ÚjT¯øZ¿“CJ­èðZª0L“åƒa.U•m±Ž€ '¬È^޾ª ºè(èi4rRÇôž®•ÀgÀšY.[»ÙÒì ÊÖ˜LI)Ué3GvH¸‘Rª²­ gƒyíÈú‚+%+¤Ú$²Ö†·%hÚðÝÂÇèF& î» 3­¯ró(…im«5™ £•€Iáôð_þò—Ɔ®ˆÁíüùl7§u©œžFa¤ªe Xõó8²­U(oæj‰HcÃîÍ6ohªJÒ`Øæc¥ÄˆÙÂe¾”9”|‡òB%BªŽo—µS"hÒqêËÇ‹á‰X™Há÷†ãy6OO-C¤B†¦BŸµdÝ@&ÎEFLFLð–H7•B%¬Òô”òÍiÅ(;ÐØ²A²Š¡)»*¼@VÓWÂ9^*Cã…­4Õ¶‚¦‡H¦¶ùÍ Lþ” q-‚“Z#Åõ;³eîf€ÝЖ°2AžÊMRÓP†XT>ózYS¦1¡¦”ÈuŸC]:N½&SŽÏdúu4g¤µŽ•U²IÈ2ÁP¼Uȉ»C)…ÄÎ.ÕÓXñ Љò,«…B¼“^]bŒµ1¼Þ‰mª„-·@Vç‘ß¿k@bÔZs£M’§99hlUu3pq‹NV!+[óÈÂX0xJŒUål•µfLdørŸ%žÏ^Z…p“ ½žRG|G®ÐŠq«”4Ù6!…šej1zu@…R¶V‘çíy²ñ0RJª²ò¡ç)ògKmo+˜È%0ƒø49s _¡­òM7¿-\œ6÷ëB-gÁï,°,½>5— ò힘Fë”uï˜Ù8¤´*Çô Âd L¤I ¼]`—†ìÒ‰áÜ0Õ&Vè~ é‰ë.ëÕÂDv…d;-¶’ѧÉ“¿Õ`¶² PIURwOÝmñ”©¶ò \mJ+¾h0O-Lnu·êÞ½fÕ*W².YY‘¬Í^ØZk݃KŒ+ìÅæ™~&.¦4•¸ƒ•Ëœ¸ÇŠçC殬0FI‹ØŸ¹µÇ‘IC6OU²H Lie"ʶ%³E @bÇ jûÛßþö79Á.ßL•a蔩i›2Yz©dN+` pM¶þ^ƒB¶Ö¦‘%ë×ß÷ «AÍW‰c˧ÖÒ*bl ξµmÇdE X9CÄ×Y-2† Òªj-ÂÄüa² UÙ:¯d…T[YXBU>¯­¬m唺#­56Rz>Þ¼kïqØ å½š0±O>B Él)7?^´¦\S¶MÒI­Ì "ÿV"ÃÖk%Z+÷nô½ÒØrÍÌŠìâœÂV—²ôÊç ôšY•Y‘J”Vz«B©>fðíö燳¤”hTU>Ìù`” ]l…”ÕVy]‡¶Íäæ?_£J˜$à ¤-Þ)ðyfR!Í›If%«WÃÃã¥`1—$fëk>¬0ç@âcss™Þ*¼™{ î¼. fMcrwIÃ-¦wÆP2îATkÛ©g¸Ùð½4<ÍsŠo¹^¶V<°rP¢ ‡7BV‰¾RœVà[”#‹¶­7sRCÀ¹­“6dŒ¬Iª:í¿ß6Y)1scÓì6ÈøØ Yk澎°ù)¥rÇ8Ò0 •¸›ÙK’³T€š*Ÿs8e8«ºh-Jýá¼±52óþÍ+&U•°*”çP_“ÛZmaÎh-àRÖëq&×½r] ³ç‚ï‘áaæÚ<˜|hº@ª›ïÃ^az‡mTUrj˶5=`+Û·A˜yžj7 ½Ös³%Sî2}›ª.iZ+'3•Ë'P˜,L&àÖRUæGÈ–š~Ul…1”M»oÊøJøØlÖ¶Öœ™oÐtÆÓæ†í†F™ÛJlÚ2lmKŒ‘­víibÌfKÌ3f+€égÅÁs©£”€­”JŠ÷Ý›²É•Sˆ¥…]”,e¿tÁ³ºdï)J¤nÿ³à9—µ*)x½Hàz­J1[n13W…'À/¶Õ×`VŸþÚáé‘ [©Þ–°gØšÞ*Ö d¸ãÀj¯öˆßò¶ïMbLX¤,kH­3dÕHVAf•zŸ Œß0JÌÐϔʥŠëñç… ¬æI6PkÝXØÚCÿü¯)ÎËË©n8•\òUIÐJæÞ{*ir'Þ@xïG<2[¼‹à …`.…äf«Äšs¼”h>‚ |/È6qM­¬Èhj$Ö=LÀ:™cpKÖšyÎõ…_å뻦Ó÷Qq.2åxØÃö±Ü-R4$™Ðš¨ãå>$±º[€^ éEÝm)ÕÒ m=; Œ‰¬‹ WÞ#ÀØÖ"+É2©¶V‚‚aíZ‰W‘0qÓ2„¦¬üößR6Tw^%&5ÂÓØfÅÇÖœ©ãX뮪 iUU ¾i»"âRx½šÜã½®ª„ŽRem3·ÂM¨„¡a¤:/±T%”°v·,²=î÷ ²øn/CqK?ß81[Ó7¼×C_ñíðç"&“zÙrH(YÖ®›¹£}¾ÒSêÿV)ïžeÎ49”æ 4I)+2±ÕáS¡­nV”âÀ'Èy[YÝ­‚y¡ l0€ž 7Ê¥ÕŸžsàÚœñÌGŒÌSG+CäUQU¥o~[Y+%Þ+!²µVèÚ‰“š¹ªmì1‡! ÔÊÕ [´V®) ‘¯; º¼ÈJ9¾!Sæyj¾”9Wè— l•åù•>_¥4­l‚&eY«ÚFJv:Ý^™Of+lw^VnB#!ÛÅ Ã*Y3LæÆ|á«ÅWæCÜ¥‚Mïù"UEÒdå­ë,•À< IF ¿nGʤÇ'k›†C¡°jaÔ]аÊÖ¨¾ïAVH ¿ÛL Ì¿¬µ^ùäCÖM6ÀÚ1 “uÛäóU~W2ÑKt [3ó‰É'Û«: B)X 6|ì¾p­¥ ïB>µH¯P`¬·Ïçƒ/‹á#`«målMku·ŽÀV¡mz ².‘HQΊ¬ñ6ÐÐËòOo+eò˜ÎÅPÀ”x%Lt©öüwÛO w ¤b‚²¼rÑÒ¤zY%/zÔbšÛç4ª)£K— ¼m¼­Ð]( FIsRË"¥Ü‰m%µHlå&€+WØ[ëÆðB­5å™àûyÈ^¡U_'UK@¯5Œ·…eßRA¼*€­”µså9F¯ñ ëÕ$ÖPUS!ó÷ó‰I€I>«µUR#«IÌ& ë¸Lgªá­4: ½”,’E6[%£d<{aøäpŒ¾oš*‚¨¤vÕâV]˜wõ¥lf&L¹™møªÎbšÄjke+–‚i µ‰eñYIíP.Íü•Ј cÔn«9MÏӵ㠈ÓÀÊ?¾r Y#âô r0Òå#ë‚ÑE–_yž¯3e‚ë}Ö”C¤aëÙ5 ¾Ø$¶|Ò ›* óÆ+K ÒpVUdÕ²jgÞ<ªd/FµÈÅúÆ”õyá&UV*À oËÙé³mÚ3åý†ì¥u )¡J¨Ê Ç[+ñÈ–z«r¶F:p¬¯Éó¼Ö .¦¬»FzsDÒT¾•@Öõ2’ÐÅÖª)™µ*̧Ó=ŽS«]dHƒ+1p$>À_pcN`T«ˆïÔ”Z`â÷ÙÏÏÐÀR°µÚ6ç ¹©*0â½[CÃGtð®âjϫŰðïíôX)c^MJµž€Ì)þxæ)K³v°è"[…ù¤Ì°TŒµ-4²•zÙ ˜ÿåŽ!q~;Òß1Ï«+ÎdÿÈÌ­ 2©Š6A©4µ‹)›L‰­rÆÛ&«°kØ*d3w ¶ ÓÄ7@…ñ˜^Z|µîÔ0¦Zw•L¹ oóÏßzÔ:æ£V ’9,"#] ,˜ >[dŒÙãÓ̧-7â=Žõêç ¤QeñþHpúÝç²r€XÊÚ`Jd `»©bl)iÒ—mÅ)Á¡Zø-Dn쬔ߢó&nE¦´ú0\•­¨Wj¦tp«Z&”0 å}«#Ì`UYmzx!›ÆŠdÞðÕ6m‘­‘¼‘àL Ù¶€ SåÅnËJ‹H²Ru©|ÚÖCi ÔÆd~þà.R[Ý‚2¿’æf‘¬öºˆ¥Úb^½T>°ÂÎo©Ê!u‡‘Ó¬Fmá º…ŽA/rËY•@¦(c``bü{¶²ÅÊçSß² LŒÇeõlN#ÑT Tm»©V"U6ð™éûºÔÔ «âi%—E˜­“Æ…[¥ iÂÎH 4°TÝÉbl9X3ìc#«#ÅJÖZmÎ<»(ÛE2¼rkÝ‘mãâá~%‚; ^àk Äøá³al; sX#¶¥ ûu¶¢F9Ø­œÅɶaNÙ}âÄ"@¶º´æl€#ºa›gå"E‚4ȶ¬t'¬ª¿+Ò‘«Š¯6qþ²‘§ß„!€¬ÐÖ—’Õ–[Å-­·Ž¡¬yÔ¯‘T‘ùÆKF‰! Of+•,gždH1ú<+4€%=Æ`ùàU¥±æO&Òài: Õ_ ¾ãW[÷ÆhÍ ¯P•îôRy¦Á›'çôùËÚZ]™‰Z<Ì­ŽuGvÿɪíÃ讚¡¾ Â<Él+¦1º[%dx¤( K* @ žÉ¬oH(1 ‹)0þõÔ·B©æDãk— %l$_/üe«TM1p­ÏÐß¿£qÒNÔ±Ž9ð·Ým0Ä—…CÙ@kÉF¢ÖjÃÈFÒÜüYXÑcdiüM_Êãõ=WàL¿oënÍ (È4ù#Åó–Ї•'°f3Û®¢l­§´íATÂMÊI‘p-l³ÂЧÌ^4‰µÀÓˆÍï8õB®  ï¤oaO*¥¬”gx%ÈŽ6ž> *©_ƒ™¨ËÖ™¤ÙU8ȂƄÞ:&Ó«*k£0=Æ–›¨o‹e#«­o+æG¨!º³ísÄ#‹Ì÷| ¤š– {#@20é{Ä•wö “Ñ“Åp4oñnabVôÚ xµÆšF èŒp@ÖTò$¨¼!m¥VÔ««n$q‘^‰ÈG—†ÇT…‡«…žfB_!ÆVV¹Ï{Ûc5‡…¯ƒ˜|¥X`r‰ô„(½R&+i¾ÆÕ /(;ŒU!CX3L cŒæá°6[†° ¤dE+ižúZ‘dô°5±¬Öú~)ã‘Vkx‰™Ë6v+C«ê¤Ä m»ôdl$á,ð#i+› [ž_íC#8(ÑQ¶h+¥K¶ãÆ–¦¦€9•Kõ”ðaÒÍ÷àl¥0J°ñjQ;V”sÖH`hè [”[‘]gåéÕ²u‡Hâ”R”ÎŽ„ëkxŒr†iÆI`{…çõ`”0·µÂG†µ(ÛR:ŽlÚL¤h`£®[M3;HÎJÒðÔ@JÙvóŒ¯W+&²I] ÿZä K‰é;ìZz©Üæùë6Ÿ•+ÌпZ›ÁZ]ˆ#t¨æ±rÛ$Ú1©¯ç+冽+‘ZI³µ­uMÇ 1¢ïøÜ¤æ³ZLzŒ+¥*´†þÒŸ'Ž!ˆ±2ÁdkjÛ)6€ŒêÔÛbÌœ2çÄø‚³¬ÕEIM9s2o Ô%Cþ}”vŸ4yugSS¨œ¦ÉÔ1Üò‰wÈ>2€0¼7„!mæYÁUÑð˜-*„çYözPU¶vgï)WR;¸à@Üu… âKÙ %e‘Ûš ©…3F63ÜH²ô^?va·:‹USÛpVºäÓZÓªt¡QbÛ Í¼Á”TEXé#P¹ªu¡ã­pž © Rd›g†N4>ÃÆÈR`ŠH8ÞVÔè×Z²Hb½’Ý)>/^µ}úÊbÖn€¾ZmÇt´ÍóʆËf¸õHŒäÜ…¶aóïAëXjþÿÀA¤Ï™°vÝŒ-Û­J:ÆÍt9ôĘ|2ÁøH÷Å‚ôvù*T) À€­òæÉÇú#êÙ m5êȤQùdkMß‹]™-TcÄØ6@÷Éœ³+/CVÖló$®IÌ!åbžp)âÈw-…‰l¼fÃt(ã2ë˜!Fí){Â$Q–ÀÖZ |`§ÎÊvµ²ž‚{!˜l­Ù¿ýç?ÿQñÏLFæHÛŒlÉÊZUzEFÜ¥¬¶ât» R–Xù²Óø§ ²”ÓÐ V­”eÍój"^#Ê4gŽÿžD6òzÞžf`"k]»W9ìRª*êçYG“x 0Z‰©ÓJtôBÐ`ˆ{GÛæYk¤H¶h€Ø*Rêż§†i6kY|‡µ*Dvu)adÓÆ™ ÆïD¶9Ï¡ðoÐà³M€!`Ë$#!1Å&0Ä™]¬y:{VL*‰ï¬«JLã…¥X%Û–8}…®×ÙnO,Hm  ¦ÈÎÞJ\Çø†OI`h4…™VO3YxÃg’C%KÄLDÝYÁ½‘uÃ>ªüᎣ„žLÀÖºÓÇ7§­&ÀyÃÉeM+RÖTŠÃå~riêB3ÏÆvº¦*EpË6±•mÎx€Àý¤\£zV ÿ£½tÉ YªÊo6þ4¶"« Ûª<†1 jñ49h¤¶ò0 öD~ÿýwÿ¼®ã#+Q+”l­P‰À§líNðÍé2c¬»p>uméªÞõY#Çw„w«\/ŒU(‰1ª-^t(ÛŽyÔ÷V+¡W(ÕZÕΟAšÞ.&²pb«­¯ŽóÝ.—»ÊpF»ze¼f¡cJ‚ ¤$S€OgX(WeÛ™c_=ñœ)ïägɰ?¨åiEŠlÍ@o‹Õz}õr6AP6™-’€¿Fx%¶™0o‹yÏΤ¾§Ùóé"÷⮣5€§©J0€WÜïÖF²}ïGI}ñ0}Ñ6±Uà r®j…²ñ“t®4ÀDâú@)ÿÊ,eØÚmב'½“*1?°’Y; Pã ”`l ¸îº°BÚÆûyYÇ~–`fÞ ×Q/ÛîPΖò:¯Ø æÕò"MÐ`4Lêkm6VxJ)Àl€r‚lm³tGJ‰nÃGyn¥j×ÊS \—”‘Vå3·íìHSåÜT)­óŒÏÖº¾€v<•ÃJZÓ[s@¾€X€‰€{Üðº4F »²fX¡m7„­],“Êé•·Q‚!;¿Š–ꞯÓéB#l­²ÆsiùP2¡©$«”Í  Þ6½ëbU¡Ö±5¾![iDUd4̼̓Z[cTõú¼˜€Ø$È· Rp°2·öXë^kk'ê…éÞÈ7%u÷ŒøûþiȺT8ŸºsˆQ¢–¦áCOüëÀ”²G¼³ÃÆcè#Ï– †^4I'µŠ†¯ã¶Èx-V΄[ÓîUØØÄR6€oà&TìºNïï7 eÝÚÕ/øˆ0°g `‰ P-2qÛ˜zÕN–9I 0÷ПŸëŸÆÑR§ÇTÏM¬Ÿb mþ˜@âÙö°\T¶uQ(h*±âµÎ–ƒm+v9Èâ+DR:Ž­r!‹L &€Eo»‘ðÔ9 Eb a…‘qDÿñduÆÀ´­+o¼Ä²ãxá,&Ô¶ÚÖ³-ež•Ïabvï0“öÚgnUâ~h}+·ä§¼µªdFšå5íJÙ2¡A2!д1`@Hå Um)xÇT óY¥ÌAO 0}Q„×4Okå>Èú¶"sî} {ƒ§l½*•À†yKþ'&[døÊfE÷¬͆ױ’Îe;CúŽL0AU¬:r²ñ™ïžLÙº»UäùÁàîäü<Ð²ÜÆ•Õ’„‘ôºRªx¹h >˜>`ËU%¼‘¶ªÊr#&˜Ìazš>ä4’BÂ@bzµBÖÊ™À‰š*eY¸ÚÓæûd˜S|O¤OV¶u$85ßoöôïRȆØ*4ŒI’يξ1~)'%];[Îé#‰1?†Œ!(k³ÖùÈö]ðÊÖŽ_j½ÜI£ÔbJ[-:µŽj׉I]?©Ä) l=âžÕ hÇß:åkU«Ð«?Ô©ªè…é1DMU ¼:•ÄÀøÞg¸“º´fëó‚ô`^y¤-Û÷ìômßT_Éô@W-Õxª„m}Û“‰é§ ë&emÙJ ¸v«²¶Y!,”ãm­R>ï•K™ÿJ΂ìËš>A—Z÷xžÖTÝYÕKJh±76YâB‰À#­Â6¬ÖÖÊ?k {glkW£H¶V© {ؾβ4‚F$ÞZÓôH†pYbÛ[ôYl #Ûʳ+êŒp]¬9ä¦8ÿÀÎB†ïsÔ§ƒ^¡pY)L²ÈúÂx“+—íÔHΑ€^9Sª¢Y‡ ¼ƒá hZæiæ³Â”V‘g¸• ’§Õƃ½'Ê;#ÐØ²‰6¿-€÷Íl¤úzu9Ð(h¸½¤FBŠ v&®ª,JûM+ ©,X£MUÊ8ý®O'â`à< ”Ëf»m€¦,@ÃßÖº[Bbd &¶kJ gN`Ô>€@J>°×À`™&RÕ*t·V2×èkγÖÖCЀF|œ#(^hmMЉzɉ߱aq+Îë·ˆiÍÓÊmþ”²ÖüÄY¥I&UÕkîPKÊ2ÆÚ­ÒÃ9ÿê¾`(¬ÝÌÉ0HéZ"»%äÄ«y–%Pn+òim€¬t×Ú£lKÀd…Èp%²¶áæ¯l|½l…lï Ÿ£lÛjeÅü¥ &VÀ§± ›¤û¤Ÿ37Ù †sæ°Œä€ñY€w¼1ÍC¤‘Ji+2!àc²ÄéÓ¼ú9j­û–(åsW•mŒmØCôô >_ô½.rºvøÚ·ÕµÆ>á* tR"›c·câLŒ³­¼i¬;ª xÆÀô͇éØÖz)© +¤Ö ÚÖ¥ZX¨jZ…0¦imp«,2>@̼àÙ0‰ 0°,¾Ž0° ¡‘²åcfb MwBiëÛ0CJ‘¡”Ù¶Ùæ†)2„‰+¶m* ì ÂÄÎKÆ–Ft3™ùK ·GÖ¡€u!Hl%Ãç6€ÇÔî2eE$&’lVž~)zÍR*ÜÕÑ VWøùÐRæ?gn§å½|sâÚ¶Êòäp%’¬ïD$ÿ.Á Waí~ò¹ôYèñ"&Ï&ÁÔ±T«”æ4Þæ©W¤†á•d‹ ̶֭+$ó4ç#µçÙ¡lcjJÐ ß„@$7÷C³,Æ– C#ë¤p>ÍÀÀz:ݳËRÒçbcK¥Y­RJIÿÓ.žšì-:A Ëg…o ÃPbt§o’»¢f+›+½È¤D)µ$ˆR²”È™µ¢¡Ì Àˆ ðc=¾ÿÕqÿ~©æl$gñ©QÛI•ÐT%EæCÈ:Úºù=‰Rª¾•`”¬|c(D–Ê„R¡•sÚ®®P˜Ø ñVaëb @Y#€Û&If› -+b…•DZmK±­£*ó$ðM˹46*ÜJ6ž+-ÜX¶²¶ ¹5+[¯&=±=Æ¡š°-†9ÜVaJ]€V‚ü¹‘ÙâEdV)κ§±Ò49¬ï-:& ÔÎÊyJBYw…²[󬪎d õ³#s¨j]’yµTeI©å€L?@H©íÿìÙ#Ó"ózÁmß‘0¶žçZ××ÊðV| 1#”[G Í“yü|é9Hï@n)çœ[Ý‘dѹvç­cÙ· žl¶¶4%dÍ&›ŸO+AŒ5ÐG@•-²z¹:)8æÊÿ´Â'–­;Ü«J 7ÞÊœXdR¶Éã­Hˆ´¥±n*åu9Ò"íf›P•·îý,Ïy 2g%ñ[ Ð 5ZS‚:VN££5Yå¶“a(­1­ÉàüÝaØ<1éëØŠiÚZótÒJ}­‚Fë˜Ò–ýù2ím¦cámpk¥­*EÙµúü”0(°öà{<ðz+V¤vMC©¯Ú›ÿ|ØÚZ§ae$ŒÂf ýsæÖAr€i¤,€˜¬jŠoëà@¡µl©dßÌ™Jè%0OÀQ­jR#ëŽW•@J„k×–€¡s»ªó^àëû𤡳‚3Œ±5¶r¤›4O|>ý\ÑB–2PJ;…p[kL½¬Bg!Ë9¦HQÕ<Ö.°-ÂÄë_þ‘r ¦ò UІCnÖL0ELkz9ôò¨mb…ÖÎË\‰” È z‚Ä1Ý ˜xµÓ`Ì œOå˜@c¬<™­®¼Ç ³WUßd³9¾Ãb€Yuk—ü—– 2ÃfFväRVÎî äÏS`TYY“¤'µèÕÂ+ R=n×ç£K%ùtLVæéÞ–þ `K&ESw@ù°]G<¬ R‰¦ÊÄVY|Œlb)µ²Ö€I’uÀH}ó )>VÊ|xÂMXá&Ç—Rât|*OÆ„CL)LOGÖð”¢I’ÙZ1¶ô¶‘U¤oMƒLé°ÊMe‹„ &y"Ãøx#ùý C“CSáe}Z{èÕbAÇZ[}&@ØO,[|ÊÓxO€ÊßÁ0ØSV®Vt:)€èDÝ'-ÞV°µ"1õõ&cœÅ–²¾ XÕ%@i;MzL¶)eÕÆ4ªmžÍcòhð¶V‘g8+«+2LìŒÌ ” ³5œ-@Ù£ñ8t•¤$ÃRôüÙâùãm‘U)äÖµ°õßûêÆˆ5’µeг‚3©èKLV•µR ½uaÃØ2€­À Lkíêe%c{%G37‡Rkl/2!nÚøjaYC:Æ»vJkA³^UY+l’ë([G¼î+ +ïD0sM)먶gj¤Ê1Uå`?s€ ¦4¶bâx«FÕæöjÂ[¥rëʺEú.^6ü«[};F@%kÐ _ Nf˧וUÙwmª>È”óÌa>n^ŠøíòöªìîÄ)OŒÖpšLj >¢­ óW˜†¹7iûÇøïéI_ëIûl×ÞZ'k.¬û{”.¢Ù ” ³†;mcÑHkz&Ä"es¯û ä€ÇÐà”"­‚ÆÙ¬4ºtl<ЫWn­ö”}9 FI3§o›ÙWIŒMØØª0h00}·‡y=•+Ü0²‚ÈZäæ%ã䃯„~A)jiÛ…ØŽÏ#›Œ› ”B€TµðL’Iõ2áÍS¨Ä¶r[ú­sS ÎÁÑ<‚˜¡×r²fs ÍcíJÉ8˜‡†C%²¦çVGL>ôjMBŸŒ²ZÛÀô<Ǫ˜haëAô¥ H‰”ÍÏGðG×7Ó¶ÓÁ…l]æ`ÎMÞ¨0åJ¾ÕŸÿl†š’©5ƒ5s¢H€¹Ø¹¼3ÏŽƒi<%ÌÇ%Àn†&“úº;—áÛŸ>’O%”½Þ ý¦HÐÿ1™TšÄ­H€Ì£WXw[J à½?ª <½U£lU [½¤9p3ç&e1€ˆ·ÕHØ"mùÓWS6½Ž²F­ ¾*æ²Jj—u½ ,èÉja•ZPâëb+Õ¯ÚÌ«J‰§!®Äê¥Èzð5²„›üüꯄ¹É{ ªx¾V·îSËP9¯ÖUØÖ®¾p•XU[?}TuÌæ'ÈÈ\íœl¥tQâ€ñ`¤xŸiúf[ÍFf¥´½Eçº8˜Ävúfˆ‘r3ôe'ʇŒ›Ê¿alÉDYs¦·EÖŽi~¤·Úê)[kdBæ™1 ªÅت’ñÇh”¸B‚‚i†4V†§Í [å=ú^¹dô =»>ÑÅÓÔ1 ž¸!3´•Ò!AWÑœ­ejMV‰*#+ê¸u§(ÕVájrŽ19+š‰ñ™[ïœ /;FU²Õú°ä#«¤B&•o]‹4d9V·­F`¬”båᶉ9Pâ‰c†WˆÏŸfM¬¼*‚¢îpúœK½¶ø·ÐöÕÀ¿"•ä_6Ãjµ#h* à¶Ó—J¶’¤}@dEz{—2´Ê¦o5LÏ´O½Âj­‰éÝ\£Ê×Ô¶ëMPU´*·SÍJYãY)Q+›­»ËHfK\6+<£0r@‰ÈЊ!(╈•ÃdµFTkuÈ4§mØô"s¼›‘bعú:“E J)[c¸îm¥0¾ÁSHišRß`9ãµóPê  Yn”«PÒ ÂÖÚÉòH«Â¨»#Rø}3X‰ç W Ϫ÷'ñÊs Ž&h¶R0!èn ðeá†$ÈÙi¬ ãx+²!kA/Â[cÈ2o0¸ñLEÀ¼n9PÎÊT™ R áx¶de­†­¶ë%Ƥ„ëÒÝLµR"žÞ•rÃÔš’ƒ­ŸºøaO V*F^ؾޖFö4»í`×B© †ùËJ 8 6,õú0ìb*7ɱþ~#·e.(4Cæ01ÃÆ€ã1°*+ØœØãÁô¦à`+¤¬Mˆ´5L%ï¹ÚÒÓd0@vÍ>_ßÈl‘²¢,^‰ÆÊÐñ]µ•@j÷`KLà\™Ô¨-= i¡Ê–§?àÕ_£z!S6‰µÀgîõB&ë\‘sgA6¤•Ø–XI[[8‡«,™°å&[_ëæ Œ²õÆúý¬sÏG£Ú ­dj Ý)›¤Ù”—RKÜû/%`âþäRdM.•m¤µÐ7@wÒaMem»%nÌڮܦá1@VRj'Ø›©œ²,FI7Óàm‘îY–Øv%ÍÓÖZ¨U(øï¤¥pHPS[¼È¡ë‚QÕäoI¶†$jUåOÜ“Úü½0dÜ(ùH0²{Æp¨£U¤Ì–‰ZØ«JV[U?ÞØªÖ.O2åpóØ¢ÂY»Fé(Œo›¹S(¶ÖômdÎFu o/Vó/››¬­B+†ÆÑ*TU YÉDÀ™ÐÃD×"…·fì{X&ɤvdYY‰õíX€T'•꣧)(„É›˜?\#Sõám<«T¶ùзՑ'Ÿ [‰‘õUKÙ¥Å[™ +œ¡Ža« ëtVåÄHØ ÿ9JY…Öªt·ÆøþÏÖê°¹¥Œé†+Ä£`B#ÕðV8X—RVŸ¾òÚQ®o²+?o…Û°6Ælé‘ñHb¶+II@Ž[»šÊÎx%™çi­cCºlSfB³;!Ê4­9çf»çg\IÝç  EæVíDÀZ#+±!{(Ú YAŒ_Iü±¸&œ^ùy"+Lï*†Æ`.:OÁg’mX‰m¸a¬Üˆ¥¦©#eÎUM¤œ¨5ÌV­U­øü‚¥S T:û¼QëWKÙdÈþò0I¼NxÌfŠÇ(}5¸¸î.Û¬6FL[|[+Ïœa¼ ÁteùÃÈ”R†!¬°”ÖV‘C†¶xߪÆÃ”M©Šg3²%ƨu{ÄH©&\—r¿Bq¦‘•ÂÏ£¼UJ„Ué.lé»®ÎÒ ЄdÄsnÎÌñœ›¡å U‰œ‘ô¶€Å›a[Xa M&ÀúžÊ;3F/«`[­Õv­ XaƧlkuieã­jùKÁÆØ¢•^”§ߩ `Á™ÆÏOç]gz©FbBŒéÈnCá1Rp}SÊÖ—>¥5ebk€è*ÂH 2© µr˜2¬87Ik3T…¡´"ç`«‘ª–!Æ[À·ý±Ê–ÚÊnkþp ‘›’s˜û”x½T5¶Šëôùf Cò‰l’j1Ä]Rk&ÈÛi”Hek°ÜjDfb"gÒ¶^LÐ;Æ¿.}ð™w‰Œ‰ÉÖV„ Ò(4 ™T+IFƊɨ¢/ÅœÀj+êd×7Y$Üvåôëæÿs*Md‚Æ£ñ’HÁ"M“dØ1O¿çÉRV’[§ë#X¥:/p‹>sJ1Äp бòl=£ÊÛžÉî÷Œ’pþðëF—– B;&NÇüó;qM+( 2JR&ÜUaX#…BkbU°õ}–CPô™ü!³­ Íja¹Õqgnl²f°ŒaE’Á>ƾÄ}§WÞédxYU°PhÛYDS½µ‘Lˆµp4«Ÿy4¢ e±²mªëwºãEWqÛžÓÕ]¹èç·ø:V•p¦âÕ–"ž&²7•›áQ—®¨¤Õ¶.=5Øaa êÅ\°²UÂyà 1›œŒsY+ÌÊÚHd]ÙëÌA4*žL•𼦜^–²ïq$úç Я)d¶‚€Ò< ÈIŸ œR‰îþÏ5éKu|kĶŽä“3’CØj+Å <}?SL”’m­Ue•¬ImÒ'°ÖÍce"òôÔ²µu?d ó¼E¿ž/*åz©â¬°aœB  H‰étõÊí]7*€o0€gæ[˜óRÖÆàßatªªµlå 8(„½$”ðô^¨ Ϲ¤ø³2†Ìl s“ d¥¶;ééphYÊæIÖEáÅ:ô‚_kXH½“Àm;²¬¾¯sÌ— ¸Y‰ë•=çÎX +ÛfèB(mÕ¾…Üúæ´½ýú1Á6’L Œ¨/½òΑD¯Ø`2©:]B[‚7¾M`ËÊEѲ¶wÀs^Ue‘¾‚`¤µ§T¸à 0rnL¤ZÕÆÓ¬5rdÙú¯’@Ћúz‹0Ì•xÖÜ`kÃHÁY…¹r¸N纔‹¶}ôÈÒà™<ÆÊDÀ`(¦¦”° ±ÒÐwb–Âoy[åÝÒŒ/Ås&|àÆÃ÷©?mî§Ìé€Í™’®E!\À”F²­ &2FŠOVp§#xg«—,’rnp2‚µøâ[c¬SÀ [1ÎÕ$˜õ¤L…i`¨í kýn‰Ñ=”µÅÃzu7–)*lN…e›!7kÁŸyµ˜AþsØ»'ż*Û:få*3q34anéÕVB¬\Gšµ+e2©.-qóÐô:Á²ãi¤jd­ÐêÞêËP ™¨i[XŠ&¥,P9RVØÆÔt‘ÖÆ¦üüÍýirC®öyáXÐEêä0nÍ–qÙýÎ4kJUý,i Ýuζٺ»Ü²…5Unåv‡:KƒU«P`F&¨jOb“÷äˆÍìý&£Ñîœóô‘d"O«^adØJ,òlÛ0éS&Ð ©¯[¢é˜‰É À€ë}[ÄoÔ4d44ÂÖ)tö80݆.R)«ªÓ¥Ùê’I+Þ_Ðw J@4CY-`âŽi[I½¬1å²9À 5•ÂpH9g)à•”%›?p¦¹?08˜ÈæAvv[¶@+>[áä®:¸›G YR\X¹.V¡Q€ s£\ÊÚÿý0’¹-‡‚P2+Abâ­ ¡Z2|²¢ H¥oå#¤ô­ÁÇ÷û?˜ý"BŒN£*[Œñfˆ_z§nà°.¾ÎÿæÀ0 àÑãnJXu 0>þÑã,”ú*ɰ¦FF¢¶V2ŒcjÍ\m¶°ª ŒµZe1"™TL]–B2Õ*ÔŽ†#*·ݘ•Òqü~FìBbøªêr ~}TmUIÕE‹dœ›Syƒò!. „­j݉U´µN°Ö²0‡eµkZ@ /«xâ€xwò0Yþ@&€Xw ˆ„uQB,˜ŒO¹bG³%#¾EgÔªd1‹ 6azU͆ÏÇú¶ƒ· ¿Ûj1µñ¬ €éC‡¡±5! v9ô@côª›­FÝpΕñÈÁÆÇT^‹²üÜåÐç‰lÚ‚†©6[k`†yŽÌÙŠÑšìÜ0FJ_Î¥”éd"¾yðm+IÌ2Ò*j±P­”ª?‡¬Àw sÈÇv3ÀÜD¤O«”ƒˆÊ­UYS¬ rHvÎö=^àUYÍ£DÖHø>)0R¯ÜdïÏÒÙZ² ­ …Bø„ƒF ïë±v‘ýh“¨RûâFâ Õäi`Al•5 ¥h0¸Âßþõ¯‘ ‰Æ WXUV|ëNa²V$w%6®”mU>r€-%ì䔉wÑR¢Â²dª0 i+”';Ó#±Ëm$@‚4ƒZ`µðd•«‚ÉòÞ–É\¬]¼FxšÌ;£ÇL™ÐTÛÖË=ªø¨’5µ#ç“ùšW’ s[-º(e)sH?`#W’ ¾P3ÙîIF`ÍV»Æî5N ‹dU ¤-LSÑØ €ÀäBIΕÔHa-æ9ÛʽÛôM4Ø4uÄoÂÌSZŸnÌšÁ»™w*$=«ºô,ˆ_M×WJIz¸mæ‘g‚ç3똶R”ç‚nh±Ð½éfèes†ûé5)ídkgÍ¿*[‚|2«0zY‰ñLò ÈôòàlµÀg¨dMËb [“×xZE «»T3ئgÈxUk`>¶ÍÓñ±}qz ^¡´¸³|Þ ÛÆ $ƒUY«^`DL8+r+¥-[÷fåf¥ï5nÛðót0­¶›§ëòŸ¸èA4™¨ªµ“"'ÈÍŠ±êb «Á|.6ÆôQвieoÏs}–ëK&•#òÁD¾#…¬z­J­m†HX;+«ºÇ¸“à M%ʉ_Ï×jYpÛÖ•Ôô&?§ž &ŒÐј@+>¥myVˆ¬°l)XÇïäežÈk•˜¡µnøîC3óãûu>5ß#Õ b¼•C tÃYÝÒÏ÷yúæ,kåÓlpïp%|l{aÑœõµUEIàÛfc½UÐÀ?:Ú2d’!€IŸy¸‘*' Oc†&l½I|•{ñ8c8 Ums€RÍ- (—Ь¯-œ¬É}{Cßó€F±5q"ÃE¶•-4™JñÅÛMÿc&ÊŽZ•-0~¶ ño÷ÛóógVsoÚj[•žÄ›™•£"­î×JCoHÛæ´•õC}oFç˜Þåœe¹I©J S;[ÎkM&”Ç«¥'‹W(ÚtF ÇãØ)俯 R Cy½Ïôa`%¶ÄÕ”MXÇ«-C²Í +LO [ÃãòŒþý[̓¯©ì"²S3¡Ä4Æ{uÓ#aJÀÊЪD¤oxXÔΊÉèáR[‘¿- Û<YÛôW{ĵ³dÝ ’Fd"ÅçÕKÕ¥ò<› .lYU8±BY¶"‚È4pÛ4Öº×Hª.¶€Cô(mÓXÉÂz)÷‹n•CžõÂÖ|à"F-^pÆ/F7–F;2¤s¯ªònö[½ó« “e¥D½¬ ií³Éy&¸iLcتÕ×)Èr¤¬Èu÷YÈ<ÿÍÀ2‡<û'fÓ{^¼Q•70=8çÊáJÚº¢*!¨E£Ú6ddšœ¥ ŒU™–!Ü©p+Ñu™ ôsYªWh­1ÃRakµÖÛü,‘óÔn$¬Á˜Ø ³åmá É~²Ä‘ÉÞdjHŒ¡Q"bl«M 8™™EJ¼*1œckU4H2ÌjóOÙŠ‰T…qù ]ŽZGŽÌ°µK›CdÅ*˜(·] BÙÓòŽÝä<³%Ž¡© …JÅ+T!æföÎà‰Àô埭)”Àªf³²leiXÙŠjåR¶jdÍ(;Íoüñ‡œbsä‘»6beyIe¡^.ll¥T%ëÓžUçCž˜@dUª­ ’R> Ép#ms€k Í` 4ZIa„FWx†‡e]¥@ož†aB©»m ñBy€†RdÎ-g Bëø0—ÖhT@L¯P÷.&3¡UŠ óÄ•Ké+Û —Ìl‚LV yn<)žk]¹mÁVwš¬›ÆÛ¾)šM•-Ì–Þl›!Œ¤¤1 xVâEÍŸ¦nÂV²ÖªT¥GjT–°å_-e]€È)»gÙÌ«¥!h€Ö rÈDIaŒ€l…›Ö6Æš ±¬¾‰ËÚ3iZGhJUHˆÄªòda³õ½àA#yÆOY_z1Ö²mùdÜšÓpY|Zª÷ ¨*­Ù¯„¿,)×—®„y<™X-e%H}»Æ+9ÕԨ{ƒ¥TebKct˜Ž€¯€ó¾s3_(”H5¤µgä–f…˜ü­º'0 FÐ[c¶ÖÈV$èn;åB¿yªªc_Ëš@#UJ„ÞHH†iðÞ+b¡Ý¾.Èà~ÐKqPØu¬ò¬)½È¶¦¶üé‘¢øÔKÕ­8· ».€xž)Qɸr…úÒ·…¥ ò‰1Rb<ƒ)©¾òÓì^&FÀj%mû¿A“W cNïÛÅŠÝC)˜-ÒZ xwžRª;lNÛ7ŒP!hû2§åõo•R²Jš°äiM 0¨‘‘§‘u¢­akURá¶i¬Râj?2>^ OÇô#ު괹ˆU¹±Ì¥8gÛÑd…*+qï­uÀ–C¶È3Ä÷b‘pJÀV‹º#Ï«y¿´añ¶¯9¦ ±{;mn£JÂô”­†*†È'løÆl…Âd5ĈŒéöª²¾%ù0ïéa«›´ö8Œg»ªdÌû†±ÝTÍÓÌɘl ø¼š÷>eÅ<9TÛphìñ—¦[YÁDp —}•²Ä«°5Cb|%Z•3i%úöÉ%(i œö7jŽ' bζxXt"“üö÷¿ÿÝ^b=‘R¨é$¨•x˜òøÝˆä#`åNX'>ÈßY¬R˜"C2M¹õmÀ­çE“[>jõ¢iBëüñÊ›D•gÁŠÞ1eã1"[@V¹é W˜a¼Z梻š†’eA 7€¬*|% ÜZmSÑ¿&³M˜L”«"Ó¨-~‘ª¤GÐy1z°P’ç:"[8A…Y/¶p“"A…áÊa± ˜‡jñ€m‡òƒ>€”‚ ¦ªŽÏŽ)æ©c†ô°ìÍ÷£‡žÛœmÉ`…@VªÄ•|þð\‚lu'¨|ÔâÚ|^0ÌÈ~[È_ß­˜ “[µ€’·/Æã°6¤›QÂÓ $Z&¶²µs Xd[‹RÍ€§©Š¥5C)‘mN«@bv –,g²ªbÒÔ¨>s…[+-rïsz<2 &«ZPJõ`’QÒgI†çߪ.0ݘ&Äx«ÚÜjg4ÄV©70|04@øÏ²•ÔQ;š†ÁèX 2¼ç+•¡­©¬½ È¢QaÀªpÝY V݆-5½ÂN¬ÝçÏX“N™œUøWPú ¿føæÈ·ÆH ÌÈdgÖ~ß_‘¿ÿþ» ‘3½öíüï]3ì 9¯W-le;¦à)E¤¦U±ÕÈ**hˆ›Ðêà¶ô¾úL¤l×¥B2QS+LàÞTmxÀ¥aœtbŒH0díÒð·e¥¼¸çͰ݉)Ä•Ò(iERÒØ¶bdu)w^2¸³ìì¦Ïxç¡Ü¶7dGض©b”ØpLÈgów- VÓÆHwŠÜš /ðõrŸ²m벎Uå™Ç©ÐT½EHÁÓVkóXm‘ªÈÊvŠÜj„Ä(¥°¾VNД=eß/DMžÆ#&–ª;C)|¯iVµ+E¦JÇR™ÃÕâ VÕq¤l$ÙEU¶RY¹ä¦jM [ói;+äx)ÎVQߎÐ8:ÚZMní?ÒÑïöd¹Uµñ(…­µ#p³…‚¸™Õö5%5²Á¬°^Ëó”U €çxJAƒ™9AÝ‘‚  Wb++@•ÊÀ;/À+Á‡3lÕŽƒ¿/èö”·è˜Û60Œ‡3±e.k[(AÂdÚ¹¢D]ðpΉ­‰­5êõóTÏ'ÀS`´9׈^ì7ÑTÓØ"k÷6½ÚÏ'Fpkí(«jcð‡ÙŠz™³KÆWn~…H)€Œçš*ŒŒÉdŒmΕ´m˜3ÞHV‘ƒ9E­iô²d¶Eþ•`NñýkÇ'¨¯ÕÊmZ_B‡J‰<>º§'¨Ö¶.¶×UP"¥@nHÙªr† ~LURÄ>?‡Â­RB¹ÙÖñok†¢¬uÎ4Üè­ó±% /Õ-Ù6m&R¯aM#yºZðd÷ÄmgˆÏVGåùX™ô],E#dE3D6d)åJjD£¯çØ[JlK&«¤*ø˜Þ?ËY‘2µ°½¬pŒ¬Àú¶i0¶ÔÌM˜ÀH3±UÕý4píòœyóÔ¸ù{wQ óÌtðlnµ h°d‘ÄP§m†°ª éš“ ïh•ÀA†i퀶¢l£Z1•S’ÉÆÀG}³É [®al5̓À[ñ€¸ÕŸï Ê3¬5q%|l<²¶ºKíË~Ÿ#Cšzá‰+$ëÏ  ¬]÷âeR!Ü´[)«TÙJ¤¸ V‹Œi$+FSO èmi溼CŽÏ¿KC2´Úêî€~gèNl‹¸àè~l…B ,ÛA"ÙþøÁ­¬U* ¬ÐÖœ†zådgõ>J¤Tc’Õ:O+ì>iVÒEmrâ¾mtoB)ú|*|×¹QÂªÊÆç<ÜÖêJwôo•lÛªô%0ƒ­³G¤É0 Ù[b‹ÏÍñ{miDVxÌ.9OÛ.™¬T¼S ,ºU]Žã÷_øì­³%h0-²²-2¡1,ðô×Öü@LUô¶ ;r˜lLµ-Œ¤;¦¬­yl‰ ˜²—S‹>ÅJ‚5¨m]È„m·z&ûŽ ð±vºó€\|®¼å]b ‘zL³Ú6– |ÁN4wî¶].£÷‡xY®¶ù²‚ýÂÝg¬Á3I‰rÖyÂYÛÒ›LÀµå,äN$KœölÒw(çokLà a«ªdj!ˆE†.Ayc`da !U 8±*Y%g²ï¬ ȳŽô4•äcÅÄL””òœÝÖ¯˜ ¬ÂC×…²CÇ#1 )Û<9ˆ4²À;ƒr³5ñ0™BübXUkm~)¸*Œ³7ÒjeáZ(‡;ìÊõEæÓ7Up¶°P•‰µãBªÚú¶ÅÛâUís~åŸ×ã8ÞºëEïÔm«ÍHåÀV„e;]#uÉRR¶ekg%ÇNo•*;}ÛKP#Xð'¨¾k<ÃÝñ­d:Ò¨jŒ¨Ql¤Z_À¢ò&Ìœ˜ùf¶¥O™¡^·ô|ÉHQùs•à÷Èæ92Ùºd^S˜g&NA $RÉüÑôÿþïÿjÉ_¶ƒsÎG HeÈ? ¤ãØÂvíyªÅckâ0A<`-˜×ÑöJÎ}v¢˜0²îUÍ)lÉÌ,ú›¾l‰ëNc$&}>ô€òãr}ÉJ5ráU¬°•˜ÃzUk•U%Õ‰\”ÚÈ&wcH„•x Ìʪà@…Ûk`Ø"ÿl À i‹¯ÄoŤ—ÁÌÆ°Úæ32)@Ö*ÒØÆ”ÅÛJ±u"]j4 Û»JO†¯£9•¸ &+ e<ŒY÷3Ç‘)›|#©bÞUäF_6ÿRœò¡i@Šg]€—ç™ Ùô®±”߈œÈ–ma+“ù ×Ã-Ã:ZsFNéhHqµg9lùÛ²ÙéýÑy‰ó¯ç¬Ùxô¶ây6 @˜DضFZ鑪òô½Û¿ýãÿ@i&$µÂj€FggëŠaëô@zYa,Û daÁ°B†‚Û¬;ìuQBP À I&"ñ¥¬QʰI.÷ùšs÷Ŷ¿Špþh•Rk……Bž”§ÁЛienÚd­—˜C[©JðÌá¤^0Ù&Ò¨ µÐ«Áà_I£Òcx²"n$@”8×ȪŠ^¤¯) ¾BÊÖ¬½h€x3Ì–¦­Z˜F6}À*ð5j«0C%õÂ4O<½ VUtäY!ÃôbCÂÆ°Á<2æ=h2¥¼lRÐKŠ>ðö ã•ð©)‡¦Å ¶œ­4˜ÜVËy%pA,ˆóDªb•2^ª¦ë[/ÙþINílUÑ0 TþétÿG/-˜(Ü‘]Wµs ÏÐv…µc˜+qsƒL¹‹e àdù¨‚­0·L¤˜`ªõ˜”Û6@Mc¬B•ˆ'ÃÔBy$Ù«EÓ—8ç1ù[çŸg“ ¥ø˜Õ¶Èx+RIM•râpÛpþÂ&Ñ+ÀƒñH%V·ÇßÚTåúîfàÌÊÚHŒÈGUsZ‘4z¹“12¡™zÝeÉl -Œt±¥´Ö´ÁX5X«l7¼¨©róL€¬/>M­m¶Ä@²­JI²”Ó×kb2Ãð¬ÃMBÿ¦0JYížVã5î4H%uÇ»«;§¬6s$Y+àYßçbÕV˜?&R9¥0*œ¬,=`Á§©hò¤¬0Ü$ÙÊ Œ­u€ŒÀÀ²Êù'.>õÿûâÉFæÇôF™ÊËÀ I$þ1OµÄ FœÞVT’³m§¶½És¶*̲4}IJ0`$|ÃØîÓçÙ5­ßÍß…P*ô eà s~[÷h( )VœUæTµÆ+É€§vÓJXYEí‚R„­4³Ol²i*´Ž/ÕÖÚ-éOÙ{ˆ¶Rü)g K9K—à•P:—[ð0TU0Ðð²dWÁM(´bÜ`47yx%j›ÁVSÛKˆl §È6†Y† &%¤Š&‘%# Äð·âb¤h$ʲô¹QÂdR^3“CbTuÃJ$MØ" ò EæøR•˜ ¶ÒH9#óßþú׿öªe¡, Ïè`RWu–zŒ±5‡“Hhl«í¨Æ‚é‘pãbeÃRH©VÌÐ×0ŽI@¬mM›°TìñRJ+Ï­dk‡ìiå9™y£¾ñJèã­œ;Ëœã»"dm‰‹¬*i†²ÃyúUµ—F#LdM;x¶ªŠÀ^z2Ý» SS€OUª•%2O™¾F9HekNz)½˜È*´ÚÒR°Õ¶Ð¨Ð*ÅÓÇèdaôÔ´Hߨ1^èR_&5¥©¶òFꈩ„¾’”•`ˆ»<Àû6à8#g>RI¶²º0¬Vw €$+k¥¬Ò(Gö(uǤ±*l¥—å)hÔæiÅpP%jgb%jÙ|Ã¥´ÆSZ1¼?öä–?7ÓU¹†Ýû½´¦”Ê;WÊÜ&& LL`Ëáë}þsþÀ .4E«m¾Cc1¬#ô¦ª%°Ýñh²:mï}YOûûû‡Ûlh¤Õ)‘ª8H÷¢õ"°Ž½£g›mµ&ÇHé‚Ù ¡V/«aʪ*lëI0A†Óg¨8£ÜΖm–RÕvµ1¶•ƒñ1­*½¤˜¢îRÄÜJUÖ é{¬WÄ&ÛfP4‰”ZÏ¢ÿl‘*[< œ9¥`· »|[í0ñÇY [bn|rp–‚E+‡[ýù fÛ„¥¦xöÑ­Q݉9×Îl}eûý£ì|ja»i "{yŒ×¨iz@†³p49Øv"Û†ÁP UH¡ ‰Ã²¦—mòdYшz5‰¬ªx@TÌ Så6ÜL“#…BÛÄo;©¶Wu–c}Ymëh…™ >Ì×n…9ȶÚÂR»L¼«b{\¾_J˜s³?˜»„îÊdôk©„y©ÜT)A6Ææ—m`bä®è4~>>‰˜Œuþ@g™ÌV¸v_ë|j§¶ò&é&k¤d0&=†sÌ •}—©ž¬Ègb&JDµ40ª¤êbý4þfiˆ­ø4‰#{.Fâæ¡XÉŒŽ0Ê&ǸÛ¹5Yå¶ Yy2+¾Ž²9`¬.Aó”*˶ó6 ™ H+Ùa÷]G,h„¦]Å­;UIá1ž…ï(Ð6žÀ– 4IkãµÒÔˆ­¯#1*Ç›G¡vç÷6òÁ3ç#TY0ØzÎs Ñ$KY%%‚ÉÜú£œCV²°µÂ”Æ6jåÉâÓϰu  *Û 0Z8þl_ÏH ¡ãJlᮽÛ3›ç›UbO­‡E/VNI ¶ÁZ¹ÑäÏÄâ[R5%#PnÛ& ¥­Qñ‚Xغ4¼™Ã¬ˆ ²‡…'ª`%¢ylŲM%™`š¶u7' +dè!ú­Ôœ²žEb<‘›­“v-ý:Æ +F‹·ɳl²yÚÂÄ"ÒŠl¶¾KÕ.[¹#cà®NI¿yÒ@/ sbÑüÍ`ëÈÙrˆd¢©à\*“Z°RUw-à”úZ+ÇËr£'¨—•[ÛUaÈ U‰ Xñ&! Ì£% ðÛ_þòŠƒnT&çxjªÏš 2 |ì¿ghˆ¬h¼¬…ÍŠwBXʪ½€}̸UËŠžíœ14jXmOËûÈM(ØÚŽg.8”Ëjzj¥úuÞÖÊÖJm+¦Q‰É²Í¡b²UBi@6XJUµè¼n¬ª.Ê Ì)Á0rQwk_•X‰…ÓIÙZ5XU+‹ÛÄ4 (‘•7’^4{^o ÞÀ4âŽök6žãu$¶mHÃx» zq†»O¤mg‡éa&Äæéê(‘uÁ3Ï¿µ*b…ªÌLæh„ŒæÐ­žÞ7¤”€²RM˜mJ}kmÅðá¯DÔ¨î¶ÌaAɰim¥##…ì 0ž@†Œç }˜À`p>0½,Y&˜ô-Ú’‰ ó”ú|•¥Tb•ĦÓ6ƶÙJi*L"Ëʉ69%ž-ÁJ0øYen¥a((O¥ÚVUÈ|hè¯ê³ÔéP £JL)ÅÐJY$kŒ˜üÓÈÊ¥VUwL³9l…dBëNÚÛ¨Ša&º[µ–…‘‹M2†³ü›–¿l'×À˪%n]¹ldíZiHm+d…ÙI'Àˆ²ùÈx«ƒX…·‹Œ¦÷Íñ…á™{`¿‡ÁB¡*€sÄX›!^JÀü»yþõ-E/0:^ã9².V)âdÖ ñª`Y@‹ô¶4u׫g'%ÈD eQyš˜pþÖ[zº4¿ãôW‰ž©ë’U•!q—Ù–À M…áàÒX«Bæo¥·R ÙZ+/ö*VK ˆÄ¹Á;œFÓ&ÇÀÜl«zõuĈ¹q€}Tw™É¬±Â÷ÂÃ¥Œ´Ùàx)¤P•,,Kc*ÑYи΂¯ÜJßYš's2Á@6¬Šæ´ü¾üÎ%‹H[Àó2GÎóVœ»åðÁ0€Oo5€µŽ•+LF?œ±Cé˜3™’‰_=R ñ4påªlM’ b¸î”ŽPÖŠì){W1Àh›aÓ¦'n˜ÎËÞîGë(¡€ñ#iÔîs$k+d 2_ðÉÝa3¼)‚Æ@j”1`$¬œs6ÞK^ª™ùÐ[úÊmáœ;Àû’„ ­«¦Íç·ÿüç?¤ëêÕ¨'Òj¬]Ù¾”¿†ŸÏR=˜RJõ9Œ´rp®8snÄdÍA#`YbÀ°6† s®<Œ¤$;¸ØV “3ÐÖš`âw‹tjã’¿õØ}¿1 „s3Øü¥êè¾cVΰ3v¢¥ê.eµuG¶™0W҉”5?ßjÊWƒác%PârtÇ2¤UÖ%ôñÃä_IVB [I3X³’Ê0^¯E&¹ÕÈVPÎG_ÛzÁb…•˜_ÀR¬uäŸmÎN×Ý*ñ#Žl͟˱HµiJÆÖ*cí”K±¢„eÕ؉F 1¦i$M]ÂV©€R4•³R; Ì“¬, Ô ¼ÃÕb’mþd^;A/•˜I[óµ¢l«-Mï+É–R+eÛ„€­”•x^mȺKaÜíô¶‚¹¿Åá©<“ø­g‚ïO¦d>q²°BåœÃY0Ñ])Eo¼lm iÝvµÄHošr¤òÉØÂ˜¾è9ÀëkÈÆà€·¥_ÉŽ,êNƒé­30[[t×®…®ãWUCÚÂEU”/4BR&6-†HCß *žÆ1«F"@òÉ )ˆ™”÷Š&Ïcw'‘”4¤UU)kåZ(@¥Òb-`‚ªj«J¬‹,Ì ßÚC„óÁßÁÏ .¿˜Içri–—rí€Mll%¡‘­à™?Ì¡}¶k‘3’X–Õð‚ƒ¨@)ÈXÙªê{tßÏ)–•`[kg äh„±ÕzÊ@z¶4ÙÂÕzú@÷Ÿa[2³ÅŸQ¾]VŒvu€Tº±Æ3R­e“ÍáØýoPFèNìÉŒg+/+J¡¶{j*+C_ ¦0ž¬áã—¸%€}î|íÌBjËAw«¬`.:Z¸¹µš™L/+né§Üÿ4A©æÇd•à–~¾%L¥ÙÍCŸX X£ù0Á7çæéŒ4UëùW€P>‹®ž ¦ a%–mn‚ìí‡7º•’s>”Ý/ +¸5Öjõª£¬*|Œ€›,V+rnÍ0+8µ‹”+ÇóôžŸñ0Þ?ï(˜¾Ͱ]áÍœ_Ö& 9GÆ ôɱEæÏȹùÙêHЪ¤Z­EèjÂZãU!múxb¤I´ÈÀÐÛö=¦ßi-úµ¶H†ôÄa%|:{¤lóä6%³BCJÙª2§•ÆŠ/k-È"1égUS¼9Kµ6'Ò:—ûÑ•â cl9×ך€X¡­¨£.#ç_ëyâéý‡>\±¬.VÄx‘¨iŒm}Ž:iŸzÊdgØH¶fÎX‹RpW”Cåç0÷YÛRv!^0%Z÷©LÙ;ƒ!뫃@-U¢°¾¹ák­¶â…*[Àä›°•º’_/L“ Š6CÓ"e™çOŸ «m×w÷“)h Ï$¦0RI2 ûÔ±ÁdÙÒWhß6g¤ùÇôrŒ[Xß”Ù÷•¢Pª/œ.¼ÇA`°FRRU“„ewcúÏÖÛ%«ªBz¼X!˜,Ò–•Õ˜j1B!~‘Þú^QçB¾²&¬|U«Z6…N‘ÀeÕ*^Ï ³jlzšªÖÅ+/U “B Yµ­HLš|0¶HQ‰_RÃëEØ*…聾10&^#L÷\U…œ»R[‘@ `0Y]‹*¸#à ëeE¦T"[}kmµÍ¹”­^­õZ¹ªi´#³ê… §ÏÉî¤Ý$}%; ”B‰ÀÀFró)ð“Ñ/â>}©b«éõ8%˜jéó´ÂRÓÌ3M…1ô¢ ܇ FkÕn>Ì…mLÛ” óïãéÞ„”ˆ·f«\¶3"y¸ ØjN×B¿–g™LI[å׊L!V52dÙjÏú·¿ýMÎ4)ò²6ÄN¥Œº‡G)‹©¤®¥`µM,ðÊñ‰ÒkŠéýÃôÒc„B%µ°*ÄX…l|þð¶4°ñÈ”'&›'fb¥¼‚»e©°륤4sÙŽÐ}á®`"zÆR@~… £Š^¯¦¥ÇËêð9hjÛqƒ’9˜Pk)<,:V¯ƶ ¥úáDü>ÓÌùóáIœsžx¬ŠX(7@a ÐÞŠÏ—c¯\¤A*”‰Ç‘-2qV²©b(1BêµjK4§ÕüÖZà…ÂÝ 0’¦À˜„L#µ¢ª¤”Û2ßqøŠaÝÑJ)ÑHTëÑñl›Ž¢rJd|ãñ'nŒæÉ^H!­»Ï7›ƒl­0C±F4ƒ¾)¶V©Ö«:K…é8åŽö¶ÐïU¤Y‰DÓüw¨³älÕËut"2´õ•’¬‘*l0†ÄÎÒ[=7åj1 ÷°V®ªI¤æ3T%Û`•'ÈV ÏP%dÕö!¢¯µ#Ðà14ÕRÚÆÝê3ªà&kTUnƒR  ¤“zý:{Ýù«ª5 V(É #nÃsÛ|¤€4É”côRK“LðjàÝ€¬Ö"C«=ÍîŸCd7¦v@ÎUå‰ÈЖ gX÷ùà‘˜ø.NCš™ EGP zeE,ÒäÙ¡šÍØžiÃ+—‚{(~(Ø*aHc›BAlKIà¢hˆu¤Ý?¾TÙiå|êB\ Û>,Äô·ó¯»5ª”¾ª [½RVƒ´%³–µfþúÏ!q—™¸ZL'BfÀwÙ"×kžHY[¡ÆñÈÂV,TÒ1¥È´.M*q@ Pâ¹Xmݧ !®ÐšIâ¶Ä Ã1•Lï¼RÄÖž;^yöÁAê’§Ïx@ ²•mÚÂEcЈNWá”ÄpASµ&™×ãô¯c½Ún­µ}EÛþþûïž¾­—\ €›¦ðÈ0mÕá”V `†L€˜ÊÉV+墔ôþëå2 @cÅ ¨ÜJ&Ax:Ö=Ù«!N ð!k¼ÓN¶™ñ+$6[¿4ö= V–æLsß8s¼àÓÚ <ɘxm0€- TQž¨{$öYcNî·ßü ³ï&eFõhEžYž=FInidõceÛ¸VWŒÑE»²-0õ’ê‚*ÌÁŠÄp†Å;†B>Îl•"ui[z)sºY÷B&k†ò§'®c.L²•:VNÙ]+'óO¸8ô+`(Ä7F“(Q+êeÕ–¾y0&,‹W%€²ºÛòäÓ‰¼7¶²¥¤æÓqðÈ”RÆö\X•mHæ ƒp€,s+† @ Vâ€þ±Õ]I¼’|Xåã{qeÍI¯KQ-\;ØŠo˜úbÄfh þB_©6˜­r<Nƒ1 r…. YëÊëå6ðð S6Ҫخªy0 «èïPŸÏqQÇÙ¦ù±2$®\¤™I>²¹9 ÒÖJ\#Ø¡ªÅ¸Ÿ^o%B¶+ñ—þ¸9š·B–UOdµ™Û:x(7CW´•ÍÓ¶{kf¤vðÀÖ„½0Þ*d ¶Ö·915²%ÖN¤Ì¹ò¸FÉ`]ÌÙêX•O9+ÛHUôþòµ#Ø:²àÕºÓ 1•×W  O)µV¸ùcë{ÐH¶À³.Vóà)Éð »g¸mæž:’R!¨µ­lo3нøžN]”ø-ÓoÍPßðJøÆgh 4' v-˜äFPh-“Øv²°­ZA ÄÈ~áÖHŠFX ®÷9Z%•ã•wÞ™'¶ b«”‹L:c<“«úõ•2 ÞÛb¥¹ƒ|~Ð6FSYm z|0ecHí2õÝÑ: [3¿¿ýc”&5eKã6jÏ\H L%˜²Ìõê6tçã¶²æ ýo­*™mäôÁ5R ‹yn ‚”¬ÛdVÛMbÛSÖ.žÒðªæ@𮢦ª­Ë„e€g¶”§#«#“~«–`U°.ô>¼@7iÁÖV9¶ª²J©ÂËNPÊV/k#Ue«ª©ÈMï$“þkƒ™#Á&˜4Œ*+¦Ÿ©Ù2!‹‘¢µ³¥ïï#È\ˆŒ.4V[š†EüP•˜LØ*§O×Ká°£¹gA¯–•P‚·Jœ ({¬¿Ÿ)V/¶M¸Âχ%¦µîpÛâ5Ò^ëÑHôi‚Ò;¦l¼­øÔBŒ'Æ[}®­„«î»—† ¥;±bd‘Ķæô¾ß'°WV¢‘u¿?Õ—€ÿ®ˆ ­,ÐT½í4²©æÄØêH)l[ Žz´ÖèŸA¶Tâ )E…UÎîPÝ•ò9.q9ÕšðuÐ¥|˜˲‚“Y%¦ïoeżÛfˆEn²vLz"ª„çØä)²J6-Ÿ”®]Öél5²*!Þ$€¬BYwE`«¬Š> [d'šÉ¶ÄB¡”¾J¬F%€{ WN†§'¶ê­UIÁĶù·bŠ«=#ÀÎÐG€¡Öþå­éë+Û` E½fC#Ö([·âDй-<¤*[FoÐV˜^V‰,¦€‘0¾v_É9&R0¡iÔÈ ¥lKY9+/ 1’À 4ž'â§ŸR²øRH2ŶµîøZËÒ]òøFâ ðüÀÿ4Áÿ£ën¶eÁm <ô“ºý÷ôžç“vZ.¯pÀ@ Rª:çÞn;‰¬A œÎ1)—¾.UåîA[®1ÄLTñ”Ì{¹k¦L€Ô%w1†ñ”íõÂ”È åB0dÌ10Rèj%ÎŽrΔôHzN™ùdgÆ÷q»EYË܈ûÔÍʶ7´‰£eúÁ3Ž•ŒÜ­á¦7î}dËàá¾4þ% ÈÊMäÐákÝzþ0@Ò·U$¨°óF; šPÒ‹iPÎÙÊŽ\8¿nà-ÀG‡«DÐ1Çzé÷¤˜kðù;^#+?‡z1JýY7T©`µqª|d¯ä¾]™ÌEê°j ßY€Rl%X{¶áÄLüêoÞ1Ã6”u5.<(´z·I‹­Zûöo &eÀ³ÛÄ•í\ô¥šsbG1 4èT1Ž{.›(á- ˆ6/÷dý‡ôa9Šœy"¶dò©ÔE&„ªgoOÑgʉªJ¬µËZÈä”@ ( Xµë”;’™¢EÀ­l¥€,TË@a ÿrû´$†Ï~ªüe]ªÝ‹Ø‘ ¹-Y»Œ_èûw®¿ yÚ!XÀ<‘v4NûdV?G¤ ³’Mä“Iâö„UaJ³d¡Ñ'®…g7BÒ´†J6‘¤DV¬DïH‰‡EJ› e²Ÿè…éFd¨EpÄ‚æ¹{!!ï›`çþÎTªÚ}™8¶ @™Ûöý‘Éö´Ýx?&šÈîµ»óÑ%' ÌÂXR¸Â_ÿúW7]oÕlÓ˪xú5"¼–·TKÌÚµŒWrì³”‘÷)XC¦±Å$vk½Bµ–Ž4Éd¥¢ÒÀU}’#Yzƒ8û³Uþy 2o(ãí `2½ôJ|¾ñ2Æ/4†dG}õz}î) §”Œ’Ü7в?µ=…Aû>b2%-ªŽ‚s›…ª€UÛÆh¡^ò®y¾)ĦԎÉj/°MŸ¦Æ³Êý× 4GàÏÀ‹Ä]¶qM#0¬ˆÇ …®JœUïÀs}XIVíY»¬ª)^ÌKzÛ|d|íx]å"AbLJ>ã#5Æ´UzÙ&âÇ ã)(ùÈ}²öìƒÖå£1(C½ýɨ«¹ªºŽï÷·tbzü^Æ‘³pYJ>§áÿømÐùƒ¡Ñß®10e¹; Õ­‚ïõv\ПÙßÜPá¸qdƒr4·w! WMàXí—øó'“C³øØœž¾ª:bÈz¬®–`&Äé‘"Ћ¡Ë@ã¬×GBг¡ñd Ð0ä€ “%@ÂØûtÎ6wÿÜÈh0d€ö}{ˆµ¸R;Ÿ>>YY‰Üh™,Ï|T‘²)#ãSf%;R*µašùhâé…µ‰Ã ¼[ 0ìÖ®€qì¦dxn=ls9 ]ÈÞOƒÚ´ƒ¼ªgñ ³'¢ÜJ3«)52I0%¦)€­v ±ÿ¤–³ÄýרÓÇXL»éxפÜSP¶¿,h"åd ð×;«6Ä›%p³|k䉯%çdr1ÒÊæz#ëÊD&ÛÊDG|¿ã†1kÄiûþðôšÕ#›¨±QÉg„Ñ…éRpJ½®\;RµU3gâ(Z é³›UÓëÝДȾ€’l€ñ—ûü8WB Ë8æ–øþùjt‚4.¸»hÁ$¨]Í î²˜ùŽmåX‹ª‰p-®ˆÞAc%LrËp¦éíC€Q‚i~0F¬êór¬¥Üâçá†6´ e£Ñ–º)“r‚†æÏjo˜•ìæ.Û,¤à¦7ƈŸ)ª4µw¯ô”Ž&Ú°¯¨}úƒ˜l¯åyÉ;íP¸+¤ô\xJ›×„ȘiˆµàÿòÇøìÔåHÝëx¤Ü@㽯cûª‘)Ñc3A:Ò‹ªÉ ²øið9PÖõÕOŒ* »^]¨Ëzɶ?V¢w`‹Q øà¹¹‘¿ˆÐ + eï㣠À¦4}·p,š««™² ÓtnJ–¡1:’)¬$«Ö¢Æ\{"ëe “)51«¶Râ¹5")Oz™@Db`z¡—žs#Ú¡AÊ‘º•"7C_v¤‰¬—Ûd퓲¹‰Ãª9[ÕSÀ1ª;¢’Oz¹‰9󌈹ùg`%_AÙ;§¹~'çÊ1adÎYiÄÐè%S‚ùËôªd>>š‚@À‰aÊò-Ÿÿ§íû?Nó÷ãËDÆó†ŠäH¥. [Ì·¨RU/º²c =@#€¡q) r5ÓœÎ-ƒOé{ zûx|ßg/“oÃ|äô@î‚çïX0Ï2^έ}檉á>ôŽ™#»f·Ë™PTÙ Ëkqe%¤|»Õ e ¸ôùKCGíù;6½‰9ólsG¡Kn Àhר¬|`í¶¥t„@Ðï–v µ3â‰õ¸)r#íÓ8rNÆSézŸ5^O6¥*azƒj·|;·ÞHíÄbƒl›R)¥}ºj‘ÅœyÐ#ËùÔŽ¬Úbò”0ãÙû.VF*õzÎD™›Þ¯qJáX/²tÄÓó÷ªºÂxŒ#6…¬•úL-/‚F#=óñ•r“ÏÛñéâƒÌüÖ0±¨‹¿PʳŒq}ÓØËÄdŽ2æ,q—ÏDFÊö—ÉÊÉbئ©º5æ–‰wDþ-–ñ³Uj¥Ma…) Ú§—¯PÚ§dúªrÀo<|»ÅhäŒô›­F]Vrä–3Ö‚¤WMìWbŒ¼ 'ÈP#Þ—¡c% ۹匡D‹á3”ÄL¶•¯´}ðl ¿usf…\»eb´ç& W¦É$²éóÁÇèEj¡ñ2ëz¨wÄ|l%Ò·0œ ÃZ¶'~7i–,&@¶^]í” &³Cæv€‘¾Tëjbídô²%1]ùÀ^îsóÏ`ç¿Å·PÈ”.f¾Ž¹Óô:æY®y†9Ò8ÖH,û#pTÂwŸ“´ˆŽõ&“W%àP •jáyš¿?9é˦¼+u±eï"w oMF“Œ Ž4leáXIæV/²¹r@UX^K¤c%]ÞпèÓTåsov¾sJ-0 ³Š±ªc£É§çƈ»iG]&P°5ö>)³Rjnûöªôï ÐdÛb²#¥¼[ÃLºÑU#å@³2Œ‘³Ò(Ü]v##ܶìvJYož¹QFr`Û‘@ožªzcVdªÂÑD%‘¿×h7LVSn4>R¯%5:ª^›“eL$½ã>q¤Ž¢MNÏ÷1¤ÜXhéeຶ›…OóÝ¿«¹uß)µ´ÆÕž´#Ùnhã`%·Ëhó:Ê|Œó#`ºÑþK¢VuDÒ«Š àYØÍ >¢­èõvÍ&¦QEªF¶¤\/nO9RŽaòbä ñ­AÀ¨Ò8 Çs“ï/ÇÜâ)wLŒȾ– r/}}X4FˆŽJ­]¤´‹Í¢„µ Ùrhb™>Aí÷ç)a%@4nÉ"kg¾jVonÏ4`h.’¦€7Lw,ãµw£CL«jìHì÷m7í­VÚ]´t-z­1wnŽ|U UߢöÔˆ”ódÂA‰ÆÇ*÷§»v-d‚!†LÐg¾«5…2g€€•.½‘5¶É1ý~I(ù¨ýÛâ®ój&Ž,ÓÇËÝ¥}ŒSzïØˆmˆ´ŒÐîâ†Öîv˜î>3Ñ.`Wëvl«x˜,«˜±jÌÄh€¾£j@ÖX°êÓ Àª~kÌÊ »hlÕ>Ǧ Ó'ÞPGX¯ $Æí<0’‰½OXÖ•¦’#ýZûÙ¡=^h‡eQ)ÀÄt%Ë·ùº2§©š¬Uû MÕÚ1âÎ<ß´fd¨¶ù~pÌ|êªÅzVÊÓh¥žkëU•3!¨ä¨«‰Uã·'Óf&Æ“Õ>‰ ž/&p¬½ìhá>A-=LØ{º;Ù”zñ9ëê—[íidU|>07Yã_þýïû†1eáLªÖ½½š£’‘Í h×ñUÙQvìM)»’‘d2q,('VŠÌìg c%™L»}ý>ßò‰yР䢋3hð°UÉìÌ­‡îxš¿¿sÓB  ×ŽÏªM‘°ÆñHL&žNÖž “9*9¦D’ÑË=> ¦À(éª1@Ó½²EZ»?{te¢D6$¬K¬d®ó!‘<1L0ªÂ•aï)W’ñk‡ée¼v¼£.X‹À(4oØêÖ?Ë'<àß(X Höæ¬x †§í6ÂFûuÖQ‹–¡Ìö6}~{Sú,h¼¤œ¦ëÈÄx9€ì;àèMlØÀO&}7t5+æœÛ‰ö!pãj‰”w¬ê" >-0eâü‰ùV‚µ¤L OSãu=?;âÕ4Åã”d5ò$+·dÇÜzLJÿ›aoB™UË#E/S&dÖîkFÀ“¾•úa©‹R Võ÷ŸµÈÏOVr-r€@täCì˜ pDöÎUS¶dÊ]©ª7^ºUåx™Ø#(ñwìǶ)Z’žvëùcê%”úÊq®«AÞ0 ×ÞªÃùhZR©jM¯K­MO¦që5BÞ×·…L‹¬…>[>°Ø_¦)ú¸5æ_Þh¿jo.Ç™;Âb¼­taXµôÈ3¯WÕþ”íÜGÆ/®÷ç›ct‰Jrû—û¯FTâIJë‡kÜ,ÊÄ­„w¤l‡=/¾Ñ€ÈÓ³ø_4L‰™ Ãã{#^þß`e–h ¬ÊJØ' ×HæŽÆ9FÒ¤Çô‹”F#;æì.‹çãØ7¹ÏWC¤è4nܻ̕|þ^oÃWihkؤ)‘ŽÂ ð»Ûf!yžkÜïmŸlû§çÐ\‚†v$F52Yw‰Ä[ÿÀèjLß Ù1O%Gâ@#ëêérCúõHlJ>uÑ`ÌâÀΊÐ+b%‚zé}¸]0½ªP¥QÒØSµ5`¤@Ê×ûãLã¹9Ê"½#¥Ì*e9ϳÁÝ&^´†RÎŽ -ß­ñ4Vx7ÁÔUIµx:¾$™Æ¯ü˜{[™•¿£ª^ûØp$È ì˜ê–ÑEÓ]h”ú8þò÷¿ÿ=»ª~?]F@{4² è÷›÷^ îJù„Íô?Êœå<Ó¸ªÌA aѸ@Ù2"“ZÒ¬ËÎðH€l-UgÀ÷5¶5º˜¡ãºÊ»ÂyÃZ¦œƒ¡É²5KÉßQd]ª1ï±)ôB•ç{»VêRû¥ÀØÜ2²)zû’–œåÄÚý—Ñ{¤c溊¦ÀGàÊZø›¥Äª D0&²v½¦ ËO/ó‰1‚Ò1L z‰O/^XL¸ˆ–ªdŽ"Y(ahüb X6Ëô–'P ÓŸþï7Ðo.¼Y ^—#ÒèÄgÆóm¿Ýgòsùû?9Èí„¥Ö€{>@äO ±8ý7rhg뭅ƪ)_[‘%øvŸÑÉôª:vå]¡é²H£Ä &Fæyë'Íß èÃò)hÜ2JZˆ§wl‡^ C&ŽÉÚŽôét?z1õÒ8Öehè|šÛ•m…‘9 @»¨¥Œ,¦ç±ƒX©¡4=>Y‚ù«Â½ä¾¢4{"ïÖ†›î(hrÎ6¦?ÔûÓ Õ3ÖBê¡J[&s‘J{ž §ð HЛ8ÿݱ+LÑÐÙÍ•ÉT1_íyO)dHGY˜^cØÚÂV"=ž ¦ì¨´.Vx2da kùÔÛ•›¨Z{‚nŠÁ“ -V2F:2ï(0BIc#ÂôkYѬzU12²Múô…R]¾?€)Ö¨äÈn+bwI³L#:Ò´­ãZr£ÉßV²HI#ôÊgØ} Ûº”F¶¢W¢Aè„ý+íg›ï>4”‘ Ú@ ýlýéÃʱ8›ÝÝ|u7 ¨¥Û–/WMÀ„&+L—êeðk$Øsá[UÖÈ–'#n+„ÊÈnÔ툭ݛÀ¢.×äYrí¦´­|žï~»(uÁ×à¤d[©MÒpëHhÖîyáxJë9öñQrsa¤£…Sâû,k [Æ?KÆ!8Tåٱ̜IëÑdJHGbc–\ôkF @pë(k"Á@b¶ëMP^£fùþ»~½mâ÷?M/ƒ‡åö‘w  ÔØO}]®f–®>à\5ênY3†BVm-$¼PJcö99n­J=h½J‚g% <»ª ÊÖH`Û=a¥îßÎu±EúöšÞsà‘³j„“aºr&g›çSG’ÉôBiícVÅÀܲ|,€Žx7‚Uc|ðôŽ1p]Y¹‹gáĨö޽v°gAæ`çZð±­`ÿùÏ0lû{ÆQ6kk´•%µd«ÔFßÎög¢Q¦i áxVùþž”¼†.íÀ!ÛV‹À´Õ޹!,k}£\œ’‰F€  sAÎþÅ›’¹pC‰aVÄJ@½é‘ݪødpëÑ+áEí=ø~Èk¤O_>[7úߪmÒ2ºÖ°@¿O=ÅÙã~È®¿ïÒÚAÐÓ¦ @¯LtdÞhdUZø¯%L Ðw x[ndHX& „åªü]ª€Í›ÓDLÿ±ˆãû~ªùˆ[ÃV°Ì§ëô>Ml¨A‰µ7«Ṁ‰Y/ãÉ´´g‹)”ª"‡åÛýùãêuK¯ÚO„=™Ì‘ bHCì(ؾ#⻋^G¸‰ÄUéáî¾^¥¬òÏYckdn#ÞwiV~-ôeðó5+@—M-Ö,L+eóäÐJ•Òh§i1XIî+aG™²ï ‡~­™"T‹¬øH 2,§ïÅŒ«Q&k¡ŽícJÇLÞœ3V<}|Âææ+ÚcblÞÅÛ­‹¤—‘”†²Ún«¶^8JÁ“Þ¿î!¶LÏk´R¶^ì¸R> 1á&öþ Å‚C³ªj‰—3$`RNã˜!Ð3+EÊï^#á­h´¸…«‘ÍOÀÙ+Y nÐ2²ª. ŸHÞé(jÑÞ‡ž¬ 6KµM²Õ®kË8ˆÌuvp È}4½FW ¯Ü´Xµåå¾Ex>-  XžÞ”Ī¢’.%ÑD#Ü+Œ î¨ÀÐÜÎ_ÿò”¯ë™K# •í1…Ò@ÔŽM„Lÿi°ëp@êÝþÄ•à#Ëü'ã)š›,4dœ i[£ŸG%ŒHi7’{ùëqv ð·+UYIVrÜV1í©j\-&¶¼ð+ïHïhOâô޽ÿHÊ^>žMVÚ™Ã4ç?hÝ® „e 7!Ð ôÐõ·_Ž-A¨²pÔ%²ŠwäVJ»²âs޼Å@—›+ÍŸ8s½È£æ&ÓÆåsíÝŽ˜m€!v”›ÎMc##膥qíèXµ.¸pÌjŸ‰qJ2¥ÌD;à•ÌŠ¼78¤®4}/5&HÉ“Æ;Ê-oÕ0~üX‘1§lgG&0rkTºÚ'JG|ƒШM!ã`²®»ï¯2 hD€ LAϪY˜4§çvUÒ¢Tî³6Ñz#‰ÓŒw$® ÷\Xä à ´÷È™#jÔEÜÏÚ.’ AÉ0ŽÜò—yÒI,篘¸¡JÙÊH˜««é^`²×|ÎFûhTõ}–7Kc¼Ñ¾)³Ý­¡¤Q°……^-ŽvóÝÓÅJ#Eb¼p$S"p¬- ¥å;áŒ`nç€Yp/'üBOßæœw»Z˜ÈZ´49·^GË`,¦QÀZD²@ß4> ˆÍUâ#w)úªlE>ª•zšnÇAµÝ¦§,²ÅÓ›.{çÖ&Pü·œ3òûC MÑ%`;Tmáª޶ª!>=qwTE Lû[Ø>}(×þó7 n˜¦ ßLБó@¸çmDÊôM'&˜ TÆ(ñ”‘fk[wLïH,^JGY˜«E&ã gÅ¡…Uen²7ÑøZèÇhU7é˜Æ 𢪺Œû†ÀHUG2ÇLÒ‡‰ JŒeË—óWú‘a„ªÍýyílÛÙ¯q¹QjO¬äاãî[5°qŽ‚’-ÏŽÝîýèU3OSûHÇ!ŸU¹Ñ×"·9MÑÑÂWr~!`Z˜,Ä•È8çVU©Ëqž€öd}.‰1ù0©ߪõªÎ­¹ø€^ïßCaðÂ0@¦DÀ­‰˜Ì1-ÓôBIÙO77U¤¨½.˜-\)8}V0†Ì±ŒYp)óQ¢7é©]A´êφô1ïz'æÀMNÆÓ ÀmØh¹‰Ü„ûr£©—²v ðŽZzG@£?Öa#ऱh‡2Í+a ½a%½LÌYV ¸O-r@éeZ㽋ª%é¿üë_ÿò¸ztòåˆlR¦tª²$A%²ì™àëj•.#׫½qŽ ‰EÎi×NC¼'Ø4Äd)yˆãµD÷»§@&Ó8 †2±@ZÃ1=¦Ucò·  $Èan@]ÄdÌ=ôí8)R¯.˜y׉)gHÌ S@ßn}ùð”]pŸeþJ^™Ø/Ö†ª* À¶lÜ ^8¶­’8Ö÷ 0’¹F™qËô“ 3Rèz3ž¦+x©Ï|Acùþ!*7VªsÓ¢½¨}2Jx ·Ãª&Ò³2Ñû+ùpkfÉ‚,‚ºZßòÍj1J-}XHAF£ª¡Ž½€j$fzšºÆ8š^‹œ?RÔžÞh&ùd¢.úvÐÂ9R&ë²ë¥÷86ªf•O]¬YIcÇ<ɲÍ0=&ÍÏLJ¯Ï¬b¼5´[/Y 44¦è"ÐÌÖûÆðIŸ!±F¸g4¨Íå6×(vMX»h½xJ0CëÑ-}±fM¡77qÎô™È"’8Y}%UŽ¤ì¹æCÐb~-h'n2Xtš"²µÇhÈ®‰gÛááÄ€RÓYÁE½˜ët~é›EÐ1eo뾎–”ÉZRï<µ 9í‘gŸlÕñ4"2]m’¡RÓåÚ³ªý­ÒhèUa€xØ eL_Èe%]dL0޲–ºr.7Nny‚ôWûç¯G³DÎÙúô‘ù³j"5Âc€d€Hð2lݨ¿úÃ=ÐÏÿ6éR­ÑgÚ-ðްØ7hDææ:Ö2Ç®wÄPÂÜ”67¾Æs‡Ç­c;Ë󌯥v gÙpÇ42ٛͥiÉn´=×¢½ 1܈uÁÙ6·Gh%š‚¦}Ú6’UÎŽz=`/rö&ªJ9gVýp½—"È“˜I-²h$O¸w®”§¼‹PѳÈþ´5®ºŒ*Ÿø2A%ÕfqjŒéˆÑSeâvD]–4Q¼2UÇ~F˜¼o’ó58£ÉDƒd>fu#JŒÀÐ/c”Š;ùŒ¾Â3¨O8¦Mè3!€'8ãïç?YíÙ6t;˜{þÿ(÷ùùºÀt¼l¿ÈZÖ$fáh˜LÔÈŽÀ~˜ U)ãiR¶S7T"hhJ2`†JL bG%½½B÷…’FÈ^µÑ4Ú‡²Mœ)+á|t©Ö+wŒH†Ô(8ˆH¦ôƒÄ묷½4Jš®4ŽF‰CÕËóogUÀ‘`†­¹>«K/“Él»TÙô¾ U‘4Lô2AátÌŸ¦+·L$Má˜IÇ:ºBÎHÇyNÓΆÚJاxÖ(ïÖ ZoÇ?R¦_(ù ×n´ì)º¾)pÛ&žs•c`úÞ0·†"™ súìY‰÷⪮Ô}1Ž-C7ÎÄ3àŽ@2g•¿c/“ƒ£Pá¦èÕ‚!kÿU•ÒhɤA)eGbwá`·>Mbx†{LoÒ]Èt4z7—€Ò]ºN;ÀÍÊ€C]é“…U[’¦ ‚‘||èýÃ*«dHV52Il"*_?⦨*ñì+!cæã¨½U‘t)õ_ú>}¼è%÷£Jßny†åfÔ•9FÕŸÁ÷óïûOP—Lz߫܌ n¥öÝèuN¿v ArÛêJŸ-¼/[p”¬`d9ÐEjÄ´›cz ,Ñ23¡˜•SÀ|Rú¸mXCïY,‰qä (XP½¡LswùójŽåÖîˆ!æ_/·~õq¶I>˜ã~Ûõ‡sƒ‰åÖFÆÏ¶åɰûæï sþ«%èrðÍ dÑŒ¬Ã4uzùô0Rps3ÎA²/.Æ‘²R™•) Òpâ7ÔQäåGÆ ÉcC Ad àóL–ÀëÓT¢ßµÐ´s¥fѨêBø~»l(h ÙðVz—Ì™Lð¡¡çnÏíT³ð¾¦5¶v·éó#š‰L“ nyǾú@{Ê Uó§- $(cÌjœ#ÐbŽ™Bï{$è(·dã88z´Í=îÏ^ɪ’Œ÷Î6çæp»ÓÎèF´ eǪfÑV ÎÁýª8òi[y<oá€jnFc³‚Y!«==0Zài„ÆhŒÏAο#œ “níF¢A7â£3ò~Û5V5ÂÄ- T’™´Cã(^’F¯l·í.Ji”&Î!,`yëQæ9¾Þ«=‹uSÕdMq4r¤FG¼c$nJGX´$€\ÖÕu|F|º&Ab›ÀmNÐh²@š‰y¦Ä´ç@ÔHÓ÷A{æ•"U»ˆc>éý¼Øs&»l›PÄý©‡÷aùjɺ¸­×H™ }l´‹ÃL€õA#´¨ L†lâôßïe{I²- sX#^0¹ÆçL¬š9Áª½IàÇÇÜ@2Õ cü¶ì5Í*›Ó GêÅ[[fÞoZ ϲ.a\K ̳×fÛ›[F—cz}LŽÌ#[r#° ,ß±Ÿï°ªhh†4}|ƽR—Ñ-ÃJ`Û‡@;ßy–oYG]BK½°Rp„ÅøŽô}¸)•ÓÃ^,b@˜EfϦHy£È–÷˜Ú ^ÿ˜<Û$[½‚¸Ÿ—ºǧ–¦§Ì³­øDdzåp#ÊÄBµ’–cЩýíoSËݰƗ‰ðp=cBW[žF»ïß&õÂ;çƒg˪²ê4ašLªÊdV6‘m»ÍUgÛU›¥åU‘<x¥¦wÙ<‘›h¨OËe9P6‹À-´“Ý—8_”~ºZ¾=7Ðû–ˆ}uŒã ×9}{6NW+Uz¯ŒdåÚµßÊ)iÇc€fõv¬.›ôÉÆèdÝQKwlzn°ÈV¦o¨L?Ì_i£ã#“Á‚U¿•ˆóLi{ó;h®<ó6ÔÞgg[ÁV “u]®€qLLÓW¢¬A#;ŠëtÞóźÒä/÷ ’Á²È§£^L[©æ¦jÿHÙQÜî“0À[ †#{:#¸exŽ%†ç ">±L”YÕ T¥äã»»ç\1Po¼,bªº2 Ç"gØG@ Ð šž (”|䦨¦ØâËz †õ®è @ï.”À4b˜Ë™çk´-F‚wÍnA ä¯G²pŒÑ⓲eƒ*éE½šG¼@Ê Žï½™è ­“q“ š{µÇÖÑ_ïh`dÎMéAW¥µØY8öh«ÍšUɆxž½ÜÎe¼oýlë%ºò¡!–s@6! +uì HÇiZƒ§ÈÞÈD.rëƒþÄä«:kG¹ )È=Ú4«·*†¬^Ùæ¢¯gÒ,y$1j{&àY ž-#R¸”Ü#ã}O”Z€8+&ÂU_×f‘!eÁ¡ÀÄϦÏT;¥à6dVøz3I¦ÚJ@;¨b`bXëÅcòÄ×bñã`=>ĵ8 J»ëj™nš&Ð#*‹ÚM!&dx Rk;¦¹MŸïçQß« èZD Û5ÈÂLò©Åu€=»‰ª²ÐÂd÷%Ë“a@ 1g¸Ýð•í q ÛHz%¸#¬ ë•ÐÇ7HN“asiᆦÄd.c²¢üâ’}eqÆ£¤éa•íãû‰wÝà™˜‰ÑÞ ½-ИH°‰JHGÐ B5+Œ`(ÂJ¦‰ŽíàH£ÑD ?#To÷I)U úJΤ`b™Ím¥2Áç ŠŒÌ#Õvnpÿ2ábÛfŽõw²ÆL©ÊMµGi›<‘+Ù,šH-°ìùw¸A€^¸5ˆ9à)…Þ$»´[Ë!uÉLç€Ñ®·tÔ«$ˆ4üy:êjŸ.ÒÄô”9È™g2g-¾Ž&büûHz_ëþ{Éi4è¥ç“^„ì#Ä&ŽíP¶›®øU3¤oDIµô·.¸…•˜Ó¤£Œa’¹ˆ—m‚¬ú*1o NŒgÛØ>ÚwT*”,掵ÇÈ|t5K# èò«ÓßÏ4Fj)Ú§q˜ÍmO/7Ž õ0¦ÈâÃr&øþJ¡Ýø|dц”U1™¤Ì$žU%Àt-ý’êH +¹©ªWrlÃz$;ÆÜË÷|üdýuV‰Ìþ‰›eœ®í°U2GØýT"m‚ÏßcÒÔ ˆ4ª¢Í½­G@œ0\tl@f±cñüÉÔCµ6’ö³m MÀõ[2qût/¼£é¬¼6î"µ8ŠÝ(q½°h [ã*e•Mq-Ï3:&Ãô ¦PudËÐE,1¢ö¬tÅkñ»Èo$dž–5R¬|—Ä ånW»³hŒà£D€ŒÈ`÷…÷WÀ&vY8½Ä>&Gz]5êÂä´†Åj§i¥å–F I¦K4´Œ§©dnÕWï=UÉÜÎJ}^mh´^úÆUµ'}-JÚU3éR¦àËL>1ˆÍª ©Ôªr2U-UåJ¶ú¤ ”«Vêë„TíÊæ–Æ JfñéÏ-zñÝ%…iè5b¶-q l=¥B»j˜sJ½í#cdÁaÊ.« +Á¬„^™lí}"µ(áÃ{¥õbTÝ%¾xaެı×à†‘›(ÓPÆd%ªSùç ˜Â™£IzV¼6ÛÐ)mÞQ˜7#Çö¸•óR1µgEà>|°^2&ë%Ë k1MdSnÏv“³­μFù\ø~«jw¤ñƒ! %ëÙ­Ç„¹™¨jÜÏ ,ŠŽBIÖ›¡%5: |í5Rvã'[Vר…F‰ábR"3éȰ}†ršVUm‡µïø 5ºow!ó«d¹Åjœ‰®ã—Gài·5®e]€hs-¦Ëd¬*é ¦ékigzŒ¬w¥Äx¹"aþøÌe«*5°snx+aèsÈJ.ÈêUÕža>|䆦‡µ¼ M¿`sx«Fûèeƒ8Ëžð¸•d˜¾ªcûׂ'Χ• • Tõö‰ ·å¦#»rS2— ¥Ð+ú]AÌ0±lÊÚÚÂÙ¶0†ªÈlåv# wdnYxÊF0!Ö¥”y­'ÓÇxð^ Åjß F ·ÕUjr¶ÚOÉÁ={óĘA/Ÿ-å Gžî"»;FÀÚiC5ŠHYÐ`Ú‡²è¨j"¦F6¥#`–œ ª¬+“x™¿)¬G€¬ÀZø8=@Œ!èÓq$=Ù¢®üµ$£o#’Ø›¤L3ҔܴÐÇ≅ƾýT¢¯E)ܽªp&r/@°Âˆ4S«ù§‡ÞQ#gIÖ½4â™Ñ@zÕ;ä¼³PbT])Ÿøœ 9œÿgµ5XM4R'¬3p+g6½hŒvŽ}ºJÂ±ÒÆç ´/.¡êóHÖ¬vÀ"R¶€F¡ËPm4·xHƒz&ºdAÃ9eN¬ŠY;¾Uû‘shö™Óã[¾¥ØÎëêRª@k'ë.xVô=H²ZȘÈ]¤Ñ™ ¬$tuË7ºFú®cÖ…‡ñýkGÑ|Œ`눬 ßi&uMö2.¢«ÛÕö­ð”ï>ŽÆuµªynÍ>A>ÚE$€ç–¡Þ¢õ¬¤êîA£eä<é¯ßç§¥µ1øLÃ;bˆS"[C Lßhk`êê.ŽõÊ‹íÃS‹UÊœ«#ŸlÉYA–Àôß_Ç4€.& 0@»µ&^^¦Gr?,0qI6í6ÄÀ4ÝnŠ,!ÃÉ(E;˜¬š ËŽwôO.Ø,>íIà#`…÷# 7Ÿ&ÒÖ##¦Ì?¥LІJ0f1"e¸wÐ`L—;¶ŒªàS—WňzåpàV>¿dr–™ûPlb"[>d<•†98aÙQôzíScíŠ!Sm–®)[ÃtLdoRÖ•ÏëÉVàéËŽ)™Ã¢Ýø·ã¼vÛªÖbíx˜L—mU…AލQÆ7%`:&'åç 49àµèÅÈ¢ýÉ0zßÈôJv#nLŽ×em$¥®<›˜3ž>Œ¿Ò<‘¨±c›Èl[ N¯‘2€´C?P-ƒaB/Èe>ô™—‘ †"d»l™8ŠÄíIì«r»ÝçvŽ0À H`´Å0Lj$€U>~!¬äH)—g†LòTÂGЫJ¬Z#xoxz®X&#ÐÙÂZ„’ G-ƒ¾òó˜ZRâ)›8‹kÒ†µÃi>Hñ2«e³áõ¦Ç|>ÉÇ÷¹)죌i¸…õö§~Î]Á»©"9 ×ÙzHz$ÁÏLÄŽd ½ç“0>çÚ![RÕÿE蔉Û4BîË =YŸ~?þZZ‰! ÈêU¢Ä(ñlISZ Åè‘J<åŸPjÏlUçÀSܱç}D% “¦#$cÚê/ÿüç?!ýÊmDéXPç•À50TErоyaG™˜U«™´ + œÈÄ-C#b´#Éü}fŽWmÜ2éËdÝEc&øàuP¥Áä l+@¼—펹áUó—‘"À'«r¤AÚ{[ÿ<²®ŽÀü×Ý#`&ÂÄ l«¨Tuÿˆ†" ¥Ú-¯º®nÚx¶'=q³€Ž1‰ ú_Æ·—›`+ÚÀÀ}ûažZd¶ò²éÇñù@ Ý\-07‚û‡À Þ­¹í̼’¿ž¾?9x¸èÚÅYèV'æ€!Ã'ÃcÞ•l•1dÊwÂç©#UyömÔ…Äœy÷û6^i$“<[CÉ ˜?É2ñ>”]A.(yÊ2ym·!OnŽºÈÒä $0Ç+ Éßi8ÈýÁì/+¹àÏì{ñV…)áþ߇‚uÑ$n%¤£P2º?™¼OœØ5q2¥Ä”ü`šEÆg¸®æÊxJ»%ËPNÀJ/¬ »`[ÑD:Âeš:Â9DÊ­šá&"á2@F YY¯¹«n¬š9q7¢p>r£‰™Ü ¼¸ô'çÓ×ÌSû ³2È2Þ9 Y‹±2Î1Þ1‡HÏ}]Ü2ÁäLÓ>dá-Ÿ9#X¸/€vÄÈ•ê¥Ô+ðí¨oóv¦ÉV&ȇ lO¡…Æ‘À³xU˜Òðu1lŸ<‘@¯´}Z»5ø82§äÏÓè^8ÛþÑ—†2Až#ÒÐ+a.·Oϥʧ.U%XÅgïû€ÝQ.RÊ5¶g«7ÿ}X9–c˜µÃy¶°£‹¨:2Wò%D èŘÒã×F:ÂeÇfõžÇèFU#€ö¯½+hq,42ÑTKïL†„ãå}ÁZ’80+L÷ê8˜®ûô†v J]Èf5Ô‘H,§Yc© ¦Œ©%·Já|Z£.Œ€5-ÓŒéè 󯤋l³´ãfæ1åËfÁE]=×vPÂ7Ù—àßûÀ{·Hú>5¥†¶ÌÀ4h£ÞD¯ ¨·ÑpnéËJ"™ÜQ£·›A€–9¼Kéç½?÷i|¯þü;kc²®‡àØÑ¢¾I0žX&6ž‹_XªRÆ;V¥Ô¢1I Ë~ùô'#2q«ïH]r-Ü(¹Õ¤•0›^/Y?›Øë4—a½-Öc–¬t…ã»&}-yVœæ»í­ŸÄA¶Œ¨$g+ß9ç=ìïèþI”²eWPB&Sê«iÌp¶5âç- %·Žïg Óá"º(:½}ö8¦o+2Œ^<ÿþnÍDÐËMÔâhD|m[Làí“Ûª²vÁ‡a¯16±›Úª9ª*Uµddzå ÓûÒR ßþÉ´×HDnDÕU储ÂpS´(µpJžÕ¹õ&r&dm«‹¡ô0YÁD•)ûúiì»G€ÙuÍ$·zí°5è…£R˜L¯ÑSË3§ðÄd¨·ïŒjÓ½¿m ÚYÎ!}ew¤iœïYOd †lÜäŽ4ÂQ)¦;bA@Æ úº0&b aÙÚv¨åg™45v_½µó'ö¹ô{ z‘^&à¿Ó¢—` ¥£€«jq$sl=Gþ|ŒëGµ… záMÏЪ}ʰ cÕèâGÒ$“5fØçå³n¶ñ­MÙqy¶@wYÉÑ2x]Éj7«Å27Ѹ]öó×5ÍÝŠ£2ÜMÀ]Àòl] ¬d0Ù¬jé 2ÇÓˆÒ$#èéÝ®”€È?ŸŽ2Ÿ¦™3™êóUÏß¿Ö\ïcžóFÓÇÖnz]Z*ë:Ê‚À˘ž ìXcŸG_¬^ î³Ñ“R ¦[È~ηY5KnÞ¹.S|ÅkWeØ;Ç·’ÛÑ`È,ŒäP ÓãèÚWj7™iyÑCUÚz‘3¤Ë0Y Ñû4™À«ÎO)cz® j[{¶R½ÞÊ/ýF멬·(›ëwAº\§]„“§L jX‘ácœ¡i”< ¾j>õfŽ©+A¥ÿ/Û*½^s%²Í™¼Ë¼Gª€•tÙŽ™Þæ1KÓ YIèz±£ ÔÈU™ú^ `,œ¹ÏÂ[8*•UYÅkaˆ-Ö>ù4EÖÈäN;wtÁ¾­¤š¼%óé»Ñ’ â£Ô§¡¬ðkgk´Ø¥4uQ®…ŒCídBµÞ­Ú1ÿ)Udz…•Z’’#g¸#,jÇÐËףĸ#œ›#å4zÝÔ»!óé=sÎD£›x+U8Û ›ËŸ'FVeÈm%>ñ€Bð³Ù>µ4ÞQ#%~ (ionS¢ls»N%¹–ÖÓBIøÖ)Á¢¹]œÒPQ#‡øÆmí ›¢ ¶½•._9%CñyÂ+©: ³j9PûÝè|Ö.nt]€F¤Ñ‘1sk+¥ÜäÚZz[õÉÂH‚ ë S⋘n"`¢L),Ó>˜”2×èÙ *ðôH;ôƒ9žVdVuô"é…^G`%Œ ù(´§)L:Ê­J1YJ8%“È^;Ã~«ØVI;ŸzµÀ=>¤#Ðû ÅÖSå ;4H¦ïZÓ2ñ~ŽÚÊ¿Ulz#8PÊaVÃ6pã"ñ&Ê‘µsµÈ°»‹%”¦á¬9Ocó^)·6éqè+™ÞM×Þ}éɪʦéwm%J¡%ç­Ôª9Èxú>Öd4ªJ³‚M©N&«fb:‡p¤jâºäÖ8.ß )´;’ÀVhlðhpÎ8UãQöÏ[. ¥ ª `& À#Æ+d‚–@ö³=™j½­åÈöm 7HvkC¸o6sØõä¶Ú;ö÷¹<‘¦Ë»H| ü u$›£à/Ó‹K&Ò‘>ò'§‘›ûV»‹)…’…3ì+Žñ¹iaÁ§ß€H¥æ&HÉÍQôìuá ®Çùì'3…Æ2ZäŽrQ ÖÒSÓè‘ï¨ó2B©/R[™•ad<«ôŽJm8Ò¿ßÔ”²‰…FkÔ8ÆqL€[J;”mâhCG&½­qµd‹Äøí©K‹èÖûh˜øé5‚^JÙ’]AÖåw +¡”€Ò±é»1& @#án!ÚSÉ (‘“àØLäµ™~9qbWíâ¦dî®d„ªÂdJFX¯ ›+ë’-ÃßÇ­*ç£K{Î-ui îÀó˜^Þ‘rLz%æ¦t$ÀÖr?›G;8vŒw³6¦’#R/™<àØª#É„F (õþ-S¯ô-ãÅi»Xn1ÙUc΋Ü‘ÆbpÏÈÍ‘†8åñº>4•v4—,¾‡Ò‚$パ-,ïË£ô:7"[9çÈdòŸ1^öya ’»Z˜Þ8XÀ‚@ÞVŽJfYJûˆ‰o÷'9¶³¯œæ¹öŽy¶RËwȱðÌ›%וOŸ) 2¾U$ËàÉ®ßç×x<­”´xz Æ°*À)goµÀÚµ‚@:z1VBUF¦‡¹GË 1åJÝN>m·Ñ>MoPí]Á-úW”ZßÑð.Ø\šYÊB) €AFãû’ôãìËàKh"^c²ôŽ™”µÛ¡#¥#“.Õ‘ó>&kÏJ‰L(µ‰^ÎßHd’F\óÓ7+$¥ðžÙŠwÍ6'Nþã?Ò9ò„Ï@ÖIïçã?î·ªíéÝÙ[|<¨˜§×±ÏUÆçôj9È¢*“4º^f‚îÖ bLJŒ.Jæ<²G!˳YJ€ö‚Ìòádô“²å•>Íßÿ¡Z|‰ó?ÙÎÙD½ö"és³€žÀ&e|æ”@Ç3àûË¥›Ö"g»§PõYðÄ« ˜kpF`T9÷ÁÕ¨K¨âS’åœC¤ªãYýùÍ‚¤$@‚FÎ øú!…£Arz%Ç02™²cz ¾«a¼­ÍMé¦þž¡DO#“ ÊM„;ƇÏrwDdJy*á¹ÚØÌ{ÏZ*Q:.p°˜Èò̬É«j¡[&O±c«â{zbÑžøFhAnV‚Ž07Z`?ø¬½5ªŠºÚ!Ü”-ŒL©±}šÞ&æIÐBc ¡°Ÿ²£.ž€Ð¢”snuÉšB–&O#¹õzpíµÈ‹ÖöËÀôüåWÐ+e•fnf%î¦áH˜¹päÐ>¾Þž]‰ÞP¹P¥IFozÙ¸€F]ȼ% È*ð"}CMì)úDT››¬£ÌmÎÚiD|ƒú9¥\‰@`\Ù¥|¦ Y €1P ^—¼›â›•·ªYиšìjÄîu^üûGXSÈöÙ1'«Q5 s®Ëxaèæö\FPöScbžD¤ âoý|(<å+ù3ÅLÉÓ>Ž·™Àsΰ ºš[(õnÈFo@]µŒtÄw¬Ô”2>“r?ªÍm¨–4Fã †žk<%œyz)zÕ=¾c/Ì•."óÁ­]Iø·Š}X4Ý7~þíß>° ¤Áp“)k¯  J‰)ò™¬£ rÎL½¹v`æ]¹£ÜÀ]ø¸³ë™ëªTc‚z79·¦× ×5ývÃÀ‚òŘY­Ýäåí†ï#h\A{v…4ºZRn:†-\ÀéÚ•ìãÃêÊ5Â"ÏmëkIßÇ pkº§cXc £v|Ï‚É'OC•“2 ðÂh$P/¬k‘Ì/„„‘ù>\‚ybΤïO·’Yçÿ ¨ ¯o]µÆgäh-ÃÞ=[(S™,Ê‘í„Û{|-<»s&Óxñ) ÂU³ÕØ'áÈ¿¹dÂQvd½Ä j¹ª“²ÊÁ±=åbž@ã(a&Žá)ñþ-}ÍÎÿÄot@Ë5†[cL†J¯^#Þ\¤ÌÓ÷Ã× o6Q£’ÞÄ>ë~– –ùLIϧõjm{¬¿?'º¶ RL‹¥„…j?TyÆÜÊ¥×\Á7¡¯~¼%[£ï<,*± ³ôÆ4®‰\t$xƒÌ‘FK>ŽÈ1ºzaL™y‚z3Œ‘ 2@oûóFà ]ß‘cFd>^Vª¯‹­ÁàýBñ²‰Þ<‡zóaB¬Ñ±.bÑUšdÍ•EL½ŽYͺçkÐ1ÿdZz6T2©ÀÃåº,†wMG@¤‹ F86Ó/ä˜fµù«¼­'íâ™sÆà7…UGÆóŒÄ¼/ªÊŽ€à,›‚Á›Ò §ñÑc8 UÙñ6ý~ÚÝÑ «¹Ñ3÷Â@]rÜ”dÑP-@ú4ua $†ž¡ wŒ±s?ƒª¬ d¼Æ¦X›.‚lÄT"Ø0<%9·¶ÄÐȉshzV²ÐnÄøH¹Y²pìñ›ÕJpǦóï[—g;è”d¡TÖØ•¯ÇçwfnˀѷïsÇJív÷:‰`H3Òè6W2QµHרŠVLñ-°L_\ùù±Z ÓQnJ¶‘¾´ÞÇ_ûÒ3Çw—¦t&в[ã‹HC)‹la@¤I¼«wU8sâ4ÒWŸI|Ç}oèôd¢Ðz?|_Œ}?}Õ=ŽÀSÎVoëE6BµA&m+‹ªgƒï—-7ΔB/YþŽm(GÒ47«Äž(j¯J¯×]j”Úœ2;aädiôz¤På£οYH‚=HG“ÕE¬—I¿£TM׈T¢ñ…T•…’P:³¿ÏK“§Å&¶R)ÿøyÖKÈp>Èxn¦º* ØŠF81¬DXîX•çm=oh ÿJç?ð罇0O]ÏWÃL+éqa%Gv@¿ïÚFÖ+t‘ ©‹© €ðÁä_;Þ‘a>ðÕž¿„µŽ µ°cb³²Å šC²6ab«3þþ±4·”m"k40Ÿ¾>×û^ðÇœÓôJ?™`+õ lEžÝKK%ÀôŽóYé,÷ßÁä\é¶È]! 9ˆÄÀ ?û$v¬ä¬Å ™F ã[ `ræ@¬WÀÈ#úŽr%|C³š¿*Ʊ½p½Ö‹Ô;2Fîã ¬W.bÚÃ$7Y+k7Ô‘OÓ]•d¥ªSޝ*´·^zÇF§§é⎵L–ò:}Ò>r¶­-Û°‰4‘làÝ0²xß%C·Ã|0]Ü7ʈl5Ò`DG>¹áµÌÙQM2zË EÓé1µ`ÂUáªø¸%´È‚ÖVMàˆÔÓ×R^ ‡¦ÔèX ÆÑ〬ʎ}^Ž1õ2gÞ7²¥`Hœ3>ìØ@ë1½›ÇÓÔ^‰ƒ€U•DÓjq€íƒÌd½µoܺæF‰ŒGòÑâ‚|Fv$ë¿t  'ûÙ-q£aÕ°à£KÀ›è«ŽªßUd²@J‚ct¾ðý?ZJ¶^Uß+™ÕL¶ ²ºct?d&µôÓG&bä-ƒl €²÷‘áÖæéØ>)õfµq™°M`=‘aXV¬d% ®Ìk¬tt×J6b²@Êø+ü3ÔØ†i`@—*ÐÑ>¾ZuzÞþýEϘI91™£‚L2l gVª“EεgÕÚåÄ)³µƒþHÏ G-Ek„ñ™;6Ë3¶#LÀY°€Òªáçf4½ÞªúÑûº.¶9ïvYµŒR`ä•Zfÿ?ûì¹`ÍδfÇú‘ôݪϠ-ÉðõÒŸ ß?®T1}Ìmée{â ÊM †ÞÇ`Jâíà(ðÙD²0ze‚ö!ÛžôJx™LãÜ|ÌÈ®@ˆ Ó×ÂM`T10\pþrç"‰ ¶Ž2`%Ó`ĺ`³r[Õ1Ám=7™àÛJcÏRI•ŒÇ4"ЫúŠ÷[ÆõíÙ5É|jŽÈæjdH£äHYu?B û…¾^‚6‘‘Ž1LØÊ…߆Z)gšt4ˆ ^¤H 8ÊVîH)Ãø2Ð5­ç£Wȹl«2 ±Æ¾6‘zÝ]N0‘UëaGd·hsGκ’…ϰ/V¥ÝbUŒ’c€¿AÂÆW•[ ïoÿŽvXïöñì«‘ŒFèí. ŠÌy÷í(7—fVi”€·kZ¸o`ƒ2Ù7ÙцÄõæL)6BÏ ä\Ÿ«ý|ý2§LdB“‰,Èø4QV•‰ t‘Åõ«ê‚ö5Û&µÈJ‚î£Ïв5xÒ0j駠ŀ¾ 4×õü~¦‘óDæFïVŠ—Sþ|£Œkm ªöŸY™¸f¼‰Ítá~ŠaLÑÕv…íðQµdd·†»5ÁÓ&¬ªæFƒ@¡E©÷”ÚM5Ã$²Å<…R‚ãuÝ0xOŒ±gSÚ_Uf•>²#+-x9[<à Ï .'€û¥D ÄGæŒ_Pö&UÀü›K¯L®+L†¶?9@qûÎbŽ0O&Ú&VÍ UUœíÓèg-éUEædZ䪔bWnI2;ÑTÅ/r“1òpG8Æx|>ʽ!PW2šŽ«wϨo ±é0²˜'2,+ukod/€ir&4ÆÕÿ]w³$[nktÐ3‰Ï)#)šzÀWçÏèšÝ|™~À¢ÐáááÀÞ™Uçt“ì*LUa}ñަ¬éÓŹr[†²¶ÄÂvÎdªš‰»«UuÉÛV¤WˆôžF”­»UÜŠ_u[ÎeUUضÁÂu™çls£ÓÕ:cå aðVbYvNíOY¹Éº«. Ô ˆçÓ}âGÂÌx)…¶l•7 r}c…:6Õ–Æ è‰ß&¿–z(XõµVŽi +@ÂÕÂ@Ï%±T‚ esF ¶Ä™K¶Rp%V&ù4 FTeíN”DbÄ•üZ"óÉ9+µmKÙR†­Uàyiá‰×HyÑü–êÍɇP››®iO/ÕÀ“ek](<ÿ ½²ÛýóÓ£¬öb½æ™,Fƒø4UՈƵÝa`ÊÚÁ L,o¾ÀdÕâMŸU…RaÜw+|NøýI/[ }ÐkGcm;·ÈFÚüùïejÛ)تÁŠC? Ô”ÅO/š–2ðêÓ¬WgI@œ-ÒØáŽ k”\aðýò‡]>¶y¾nô‘¯‰Ir°öƒXªÖ7’À  vÄkë^ ¦SÐcláü›$ÌSJl¸.L*·å`UÂmž:¶Å9SªeI³ÉùÐÈ YJÛdúºFž˜†Q(eUpW¢’l¥>µkÈ c¬ <À¼&¶ù§Ô‚†­!M•[’íª»·ÎÒ<€Ž@\£L2—ü‘“EjAsæ»Q¯j)UÑ“ÀHH²˜4­‘4âõ‡r?×9(q|<óº`®ðs®4š îŒd5³­”h²Ž40^w%j­¢ÃÒÕö>`dóf›çZ‹œJšŸ².Ö°Öl)ÓÌ$&ÒÝO%çå»× +ºtîÐÉ“U¤,ÆÊ¤wF6f}eC’É|>ôÊ­²‹ºdeCr£± L8AŸF oŧ_az¤Jm­Äj¤Æ³*l›CšU!(K/è1N‡,‹ Û ˜@Óä¶V tœŽà¼<ûëÿu×ë= - †U¬ ™UgЫ7ŒjoH8²ì«7äÌûÓu…¯ ÜY”W›fnm­k`k2…€!1Äv.‘ 1äå>¯V RS%³ÂÀ”ñ¶5ª‹- ´W[ ¦^=r#aþÊ1éÛfØ<4¶™3=[UE2$€¡ÉÁ¶¦V!ÅJÖ)ˆ ì˜«Å3É¡Z)‘}m "é‘)[cô@ëSß4xå¶²V?6˜ AÎÑ•ŽÑ]¹*b˜@JÀ•ÇÛ n×ã<ˆ4W{ÄﶦMÛÇܳHÓs„Ù²¢ÔV…R[ ´#h¶^ kµ>×Jl­™4F„™(‘µµ°Â4h¤Ó"çL:ŽÖ”>s« +Ûœ‘1¬% ðÉ™RÖ$dž”­' 4 ð¶þb•˜,¤œÉþwVx-¼#cVÙC>Í¡¬*>¢—Ÿ&=ÀA¤È`†ÊÕÚrk$nZXOÁ³Uˆ/•F–!FŠ’-Ÿ¬®öó°`†@í¬ŠôÖRmÀHfå•#W‚¤1€mÃ4Ùð3Q–â €©È|ÜÀ„ÃL(wF)%IÉÊjÇÛæS2ÎÉ0‘ º½ú,§¹Í?/FžJÌ ;lVpÿ§³¶Ú]׳äÃC™! º€2fM—•â–!Œßû Œ?ý¾|V¶À¥Ïð²b«F¸{6ƒàYJ&¨ïôúîÈ9¤‰·ž'z?³d¶²BXðÑÅ–&€ñßéë‚@*Þ¡¤„.Ž™I g#[iTuiøÈ†Ì¶TOíŒuß%«¬¯£”V2“88,®ð³Ha¬²b «¶ÜYÇl Ò^«#¸„ —­U\›s Y[gë(Ç;ŽÕüdHUÁ¾ŽC„­ô|0µPÐ ¸m€Y†°ˆWN¼ª ‘˜ÈV¼Ú×A9“æf›e³yܽ®¬jçæÞ˜œNσ8Ã}ÇkÙ€u©@¯S¸îM‚anŒ¶V×e»—m%ÛŽÖq Ù o*äJàlÉDS©-R&ÖNvó«²µ–¥”ª pQÙ®WÊÄÖ@í¤¦Ofí>#eëÕ³€76,´«ûœó'SÛÕÁ"ýlKBkÊÎkň rÀ”Ö†„“M™†ƒp(—,VT‹‡‰cÓšJ$óæ‰žL(ÑߥÁuÁÀÙVRJáju‘RˆI£‘H`mž˜l™Ô¨c[;b†F"¸£‹Í¤9k4["qÉ&z•§!Ã7TQ—ïîóA¶UÒz|[„+±fèhç¿z7XÚZMsØ®VÒèÍjÛpÕÚÆºÛ/ÀÁ*˜™¦Ö·ÐV(§¯5±µÈøù§4gCY­­HïD0™ðozpƒñ›Ö0l;]jW…±µ¦¹ôçíDÆ×Nù®‘º#­éÛÆXM%êÞªïôJV¤z]bœ‹ž ën­ýˆZkÛÝ*RI—À–âd’¡^•Ÿ7éÛC)eª®´ d’¦. Ï`BÀ­!3Á¿ž07@ó™€aGhf[Á³áÉ6ªr[)?ª †ÿ®µCæPV “4Œé%orXkd§ƒë2>âŒõ¼!‘ñMbU+J@6“pg¯ðš}^ ¼Ž)ûP˜¤aš`+[Óòt ¶°w£í«¬E«¦•×=óĺ«ÅäÜjK_­‘Œ'´Ãp ¯–8ØôVµª8°¢Afø;l)$F!ÀgR#Pk•*ȺÙúb`²WùHÊd45Ú ¼²æÌªaÄÌá4—>Kæ­¯U‚ eÅL†é]©i°Ó]íc¬¶#yfÒªÖVÊUÕ×PØ#ó†UÝU¿OÐ`ºRúLhŒ'§øêɘ,6&ñë©„^ êB–a<ìê„óV« I&b¤<ån&ó”ÌmëR£[}ãÕ×j›¬Ö1UßT@Q#X_nBÓ<¥x&ëÚÒ”² zkjªpjú†RÜ¢£¼+R-e†¶p—`xWd…gŒZ½¶»´Y Ãá ±Â<{ ]¦vñV¡_´Uެªk‘ÅÈæ¶ÅWRÊ– q²2?ÒÕ¥'î‰óÙ£¡TR>Á¶9ßüçG$mþ óÉy3ØVˆÉKõNúÁ³" ží{|‚4V‚"fnj3iH<-l³­ __¤ŽeáÈ÷Ô§å š@ÏÞ°¬-ÀY°HÝÓ¾€Ö>/kR¢*sÁon É<¹~•$Þ/ ML¿ö³÷Xo†ù[Éfï¾…+ÄH [ѶpÓN(—êjbdß>”~“ë§H媔PâýõOå5ŠGöìOûïÍàÉÊ ¬8XmÉà…-«z)¯Lëz…/Cß´H·T9ŒÌFòÁh$8”R )XJ-líꥊ†²ò°›¤ÄúHzÛÕâU!'°­ =™­1Qy†)sÓåC–À*æ ~}/Øv9ñjõMØ ÛFÅJ+CH’‰gºbà ìÔŽßØ4¬Ôn=Ö×üÌw/G6½nò×W!£Øe+¹ÔísNQ;“˜J‰¸‡8§Ev"ŸˆJbzéEÖ*åUJ²m2zÁOÜ=Ⱥ“Ä4xÁÁ¶Ùè ܤòx2Y2w+ËjÙ²xa$µVâÊm…”ªeR»R”²ªÈôâé\½MØI3d¢V¶ZÛNÔ$V2¤BndðÌWÂçÄ 3…™4ƒ¬PK %¶ï–ÀV$ShqK=_URVN†!ëøøec2lJ·‡ÉÖz¦¹ËVTåaSYaBþ4ë¾ïÆL(»±Êûó³uÝùÀ(™hXyƒÕÔ# LܨĔpµVV;ÃyVõ–H1϶÷P°*×Ñ1eáõ¢÷†ø˜à“½Ã@`"®ác6IžüÝ?¬Fl'¦ü]—A3ÄoŇVkÛÌaëèómwùsÈŠ@ÓðÀ4å £¦0PXÇÄÉàÆvAóf9È*ù¬/±›ñ v!4¶Óóïê4E6€ª4½C¡V_€€R¶"ù -óm2üf­Öjå@á·j2zߪý@"°u³ýD]G¶ÚoÖ­«± æÌëN#lñ ÚÊV$ÿ#ºÛ΋ÔFZÉ|A'n ë®iw¢Ñuú|é$ÛÀxA‰±6-¦Žþ]Ûj”ÒåhW¡TMÕÂB!FÀÈñôRcµ-l‰aÞUØ"Ý@ OÝ‘dma3ðÙEÍHœ -¬0Þeö_¨ïø1¬/^~*©©U¯p€6L .§îR¶}}`RæY¡µŽ9Xe,™ZÀ«íNlÝUå!ÕC2Ä¿|_c[¡M—¬n†¦¹Úϳ#ÄÓ©9ɲ0d+g±íNJ!U…]Š&Ÿ¿• q©ªhgQó¯W¸Z©‚9@“ n˜FåÃPÉæétdµæ™yÛx¤PÕ ‘œ=,VëuÛžã÷m¶o%ÊñSÂSñü1’˜g$¦ÆF&¦”"¦Á4 ²,ÿH>"\mÊÖñ¶j­âU5 ¼[}Eï§TÉFZ«²ÂøŽÃS¸™c6C"s›s]fHƒµ³ˆ14½Z¶½-Ý¡G€©MzŒZžsn0O­©XI‘‰J¬ÖÚ¨”Bëâ°žì¸üëãcÞðÜ„m{—Ôö–*Áèk[ ÒªŠ²36a[)ÛºçòýV‰5 P‹FµU®KׂÈÖœ­µ–Õ…¿«îÒ´Ø*UmªfÛVU…V)b§îec›>+[¸ ¯…•ÒüøÉ*Üèàx…Ö×~÷ Õ€>¼¬r°ÂÍ– ôîÁ=#2À6[ÀàÉ¡-Úø¦õŒÌ@S¬PvÏÆ+|WÛxOd¶ui<«˜-¬<¸ZëBŠ8+ ­[‚ÍlÓ´µjÊÏ VeuÉÀ*([1ùïŒJl™äC™A…º ¶ŽVAS÷¶͉_ä‰7Y³ÕŽ^–ÒV#IVªlÛx8mLÂÙ‰L sæó†Ï$[Qw«IòTËÄØÈpš²j‘ù”…ÝZ÷¾ l² ¸Õ:qc“W›=s|©Ü2ÄÛ≗¥WˆpJ½bZûë_ÿZƒ†èAR ¾YÛ†[ùίë€,U{iŒ!l²¶xPŽé¡É( dóXSûTøèJiZ”µÞ|þ¹’ Ÿ®@/€I/•SL­1€ªšÊSV”òKüúOåx>¨Ú½µ ÛJÕL/Ã/…o‹Ž ÈÖ0“¶Ä4y®+[ž]¸›o$š¾ÌFÉJÀ›(æYaJ«m½˜ [d8M¶Öüi´ÈÐl¶²J`!¥Ö¶Àl»Ù27àøxȤ÷b\S‚HŒ^•ÂH7Öíèë60²H%¶Fð×ÌxLÁßÊ$}[%Uå@¯Þó¢/óÄ(W¡-@#lcÒÀ¥´–Er+àšZã‰mUÑ  .ME÷g3[¶žQ|MUв¾Ö3â=f¼I©ÜSî‹>R&ÛM˜xµzé¾ OP‰¬¨J_@È"7F€þGóMXz2£2Áœ߸ö¿>°d •Ë«Úk\üüa‚˜&œ±r«W+Ò¶IRJ)´ê…Û¶â7¶B3éÕHýšE@œ-¬D¼&5R%k5ЧÄd Øâ½ò».¼Ð(M…ÖBŠß)Îç4gÛSü|wm«|¸ˆu±æ¨`ŠoóÏ7skåea…dní-5•,̧Ÿb0s¤UISfKÆÌ*@ –ÆÛŽwo¤ÖFdˆD@k€CÑv Pðáo k g>2XÛ¦%ƒŠRZHe˜ìS c"mrˆi]Uíè}K{É)ý$ÒQU¯½Z «m¤Ya`µˆ½VØd™ðô.Ÿ@”­9ÉlÍ&Eüö­‘•¦ˆµ^mY[¡œ&Ù»Ö—RࡇM•ÅCÀ­¶ ¯oâeY!+¬Öš×ì¸åoO#¾r­z¹+,hêÞI)+䃙mäu:¯™­Zš}>x‚&Ä#÷á’²• ²BwŒTcÔb«T‚4L„BdãÍM‰”C`?òœšrÙ>Î.“ß »«Úítdbž™¸=$%™rkÊãÛμÊxnÃäƒ0ý€Þ÷èç[hó¬Kà·ÿú¯ÿrãkÌ(kŒ`Š +`d[c$† ì»N™Àá3éç7ÜVÖÍQG>î=O<²^SJað˜ü­H…[…¬Òô¤=Î «…+wä~³±]£|8¤ÉG‰Ð¥¦Rœ¥Ê"‹dV[+Ïøüc¬ªðïg)%ÿš6§•¸{‹·ªíPyºLL2¶YÉâ«j[¡ÜJ¯ *²ã85qµUå@#0ÝLoÕ‹À:J‚ôl=« èéШJxè‡ y¿·¨‘*&i ŽJÜ«O&ªR­HU­Hk[¼Û0[«^ »[Ú*òç Ô h¤ËGÀ“¦.¶€¨*LŸ ì›ÊCÓ½iá®æS—Ês#C6y…Ä#T’³µvçH÷P‰ÈVŸÎóì‹"78M‚œ´"n6â€^j­• «º.VgôcÕ×Y&}T˜>Ÿú’¹a<’¦l­ ™ck%#îgPнHÀõøõ”uQ(½dé[¶ ÙÖ²ôÄ9/µ, ‘,ÃÃ+©K³UR÷ÈÓj†J†¾F¼)çÈ~û¯cï›lçå¶7¶±›°IÈ5­ Ö"Æêx àfSˆ†ïD­ÖØkСǤV‰¬rQGÛüŠÁïBðJF/ Ö#Ô"Rµ8º;?1Ù¬d¦Y­ñˆ‘¢v&¿g²”ͼ-ÁÌ9T^•­sajª$ÿµN–•µ¦ù§lfLW×½ R‚ùAµþ>€@ ¤ÔðúF. ”b(*lBƒÉ6¤TVuW"Ò×Ñ¿šâàÈdî¡ÇP#†RȦÍ_Џ±a¤ìR°À+Æo¿Í˜S˜s÷£j¶Äï$f–ò¥yÜ¿ßhôb2†úª%ó"¦Y!@&e•r´œë‹7a}ñÑAhÖ‹ o @ÔŽ­’°5s Mž]j}KÏK…¡‘b(u;ŸŸ©+Š–M`+ xº[Ø$¶N­¯-€i%‚OY ß0xdzҽކñ4Yñh¬²ã“qÆÀ‚•À䧯ûM~~lWe¥¨)@/ÛÌuÏv…lù¤o¶ÄnC*|Æú*OwX 2]lw™Q-½ZÛ¦ªïõ;ÃÓàEþ¹ÁÜÌÉ6¥ò÷6“N·—-=+Û ²W®i¯öœ7AÊšbGè™SF²ÅÿóŸÿäƒl˜²pâZXm×Âui*J<,€ô@ÐÀç/hÝ2;  Q×FÙ ‡d§RJ¦U¢3wMx²uš£5s«^ýžØê0Vž”é™ê¨Jh—>Ò¨]„ª‚'0”.ð’±U­_ɯGK,k•½ÕHñ+±NœžX,¥ÆÈ2éŒ]ŵ56MzÀ„9·yJ­uâ&Ô… ެœRSãæû~¼ùs¢†¬Š çŠlë(”™Ì§B3CÊÀ~93Œ™™#xÊ&äÖÌÛb8#•7*F• a.¤f’^ @O“²ãðÁ#뢰°5˜*£©`e}ö­•w´™¯5ýîA_%ÍÓ0V·§JÓf0Y%­ÝŒyXÁJ`úÖ4e9̰“Ú ¼À4qäüÒvb3ˆ ‘R4€«ðÈø0>±­ñ F&˜I UV[†˜Þ¦Û2°Ò„­G³5Õœ9Ô"«S|ÃÖ$ÜêÍQÒm$€KÊš ž#sÃk$œ+gÀ–L9Ê[²µàÙòMku®5 dÂ\ Obkþ†F$ ÌM6€×Ê›“Y£Ö«: @À–¡*& ­¥¶b‰I_Š?,ŇCµ>bH)‹tÍC‰„^xX¨ÍÐgG­­Â>Gý‘oVº µ Íf #3´šç ÏÒG)´+Êòº±<[{ý:cz|]ˆ­ÐÚ`dÞ7YÃ0^ ™¬v¶Ãx #ИA• ([IŒµ1r  ­•ä°ò&´MÌ'ÜAózr”›ªZ2U)óÁˆ²®ŽŒÀÉÊÚ„HÛ=8eí¦ªR¸Z¤hË  ùqpþÌÉðVƒ™V o£”ðF §¬µÕö4»£* mãwKðW…OK5¡Uß°vø”}@2ä¯/`++@¡*a+ðæ·=“}?ÔU!ƨ2™UJ£[k† ¥€YÆ– Fùº'h‹§áÃ0Yw“²ñRuì€jû€ç0YVñ•ÀZ(ɹ‘Îè÷5ÃëÅD$ÀhGöÎYßšs2X”jN[àób¦";=jl«+>&#ÿñø»s¿ 4„µKìúL8Ô õ ~%v)jñ=¼ÑôxXyíà"ÛVBÀÍx|Ó5Un ø+½Æƒ)+ñºÈªEò·ŠôgÐûeåPd¢ÖÄEbx…˜c÷oG`ÿ±¸µ0+S  ÖzÁR5•RØýÔ·,qíZ‘ôÄxQ/§@šß‘÷`%hòYaå ¥^ϰ¬”/ÖF¤Ì\# œ%}>Ö†1CL}#UQš§©ø½€ý€J™AR¡Ul˜¬çeNbï›Ö°rJIÆÓVkÃ_›ÓZm扭Rjãmð&³R^;«Òš?mOÐv×]‰1„-C+œó:xÏ®9Y‰ô¹ÁÍÏM*‡Ö3å÷‡¬i+INÓÚÉòL8“Á *Ák;¦µ¯9$^9œ•-M­‘ݼÀ‰º½œ5êÒlv¢<ëîøB-7‚IaP(!`‚ì­ùh×7@LÐ)è¤ìÅ á3·Óæ>zcàMh `Ϻ»âP¤ÏÄ ‡”] À+ÎÆ$cÈ¿Úx[zó#×·”9‘ÂVêmGÎÈ!HOŒÄtXcà»®µ[°J‘r_,µˆ—ê¢ÚVÞz/ûÿõ'1½liº=LGÓ0Rµnr%€²…-òmŽ—*˜àaë 5Íö-=bkY«*åÎk6µJ€>È™Kuº|h*¯ܽѽé{'â;xcWBÃʲÖÌ­ùR­^x 5³u…9ˆþ°‘aÖ€JVÂ1f­Ã)ÉRVR*ÒZ‰ò4™¾m¥8X'®ÏG[ÓXmËæ†a8©p]b”DZ"{’5 ¾CQŽÇôv{=Þa0”žÑjŒXßmÂJ:]Êá¬;QøG }ÁëkËÓ j1‘ý„sè ¶‰Ýfz@ô1d¸—3•¿Up3ØŽ øLø‹>ì| ÏL÷íªœÏ˜<ÛšªF<~½?ß™¶3¡ìà~Gª 1žÆÖ`}wÁ¹½+Yzc§¯–¦.»YcÛJ¹g+gâÎè\R<‡m„¦y[½8ˆ‘1Ùú&!ÈP¸àSy ×ôó—7nÕÏ3eÕc•]¥­T+R§‚]îÝBcÕ)‡C»V;r2‘?À¦_—þP‘CÝ›.xdòUÍÍq¯‘jTkKìL( \/†Y5!\ëªd×4Á; ¦@u…@žH}9”"¦„­Í#%ºÙ*„Ùj °åðÞRtXþLú¬VÅ!+)ab$\Ç0g[^-[0ÒÌÖ ‹š6ÏRkQ|“0Tb˪›éÞ0”"ACfr›|~¤á»=úAw‹iš0·YÁdš²íòµƒM}ëµ,Ù€®EJ«ÂFê¡sCúm˜@J«ï« Ìnȶºç©`56¨ÜÌ9—bX•4$¬°ÿ絕c)èk½Ÿ îžz]¸9Z[)…AlÌ@žâ{«²xLÏ0˜5s§8cÀN„Ÿ³r|çŰéÂJ£?rǨ²6­òº¼Ãô›ÌV²Jb2á†qQn S Y ÆxšZÉŠ²a2`VRýBF/ðœy®#ªª…Uv! §¦‰Ãæ,ÜU&&AŠªÚ*0Jz'µ¦É§r+·ÂÊ“YO!™{¨ é\dc+%1sÜX¥”Rå~(i &8‹p²†‰'#Ƴ¢iB«l­‘Y‚¶ êÛ0é³’-”¶ÍÏ„S‹ÈµûK¦´M°Fj#WGÙjÍsnç~Fž¸™Ã ¤É‡3€üîÞí¹XÌ~®×EaJ©j[¯åY´S¨5+šBmåÄoÈv(Àð4 9\ùYðÖ1eÝ ö‚©ÊÄ/š¾¢wvb2½”p¨°ÖùXiÊVQ÷°¯]×ÒÝ6˜rV«J©©-YŸýR㼦²xÛbÍœÌËlÛAOŠ8¦ù«µ¦Ì|%†)“…UG±ªE½N0¦’p%ÈSsßYd|+ÙT0gzÄx¯ _»WFI&VÞëg;¦^Yu9+™,Æ$Ú!‰U×ÛÁñ5²l¸^x½Êò!˜²Àˆ¯W«ªœ)s£ÁÀðB6Òx ¬QÊ¥l9à«·:”UË ¨©mÓZž˜À c¸Õ+`åÜš‰ñ˜Ìpúj‰YÑôgÝ7R[n†—)%ÛHÖóc@Ht ]FNÀÖµ=¹ïÏ…Îéy¤Û©-¬V6Ó3¤ï§~ÏÃI0N•¿5™­ï”]+ža%nÄ–•mc—í¦|iªÒ±FRù[«jN+½¾”Þ´}íÒ›Ÿ’#˜Ô7·Ö.M–˜ÉÄÖÙ c[ÓR­È€Ôñ½ï.F¨Š‘ÒËJŒÉ§B¶=Ù¾B%UuóRÄoGd-N¿LM’ÅÐ׫}OÁ“Ò«KÈ8I3D¬Wyê²{ ˆT":Áù33Þ©µ#†›Y•¦pk#)ϤyT5€×²Z¼PÕ%—õªt?¶9ÞzYõâà*(ñla_–›™9ÛZ³ +é€Z©œQ®8d@!\„;¾Ù¼{†'›™~Ên¦` ”Žþb*Ï¡ZYaBÑ`(ð·uÌuo|V¶”0OkO¹¾4Nlž*W‚´jdRGX‰P><1’Þ¶vf›,g47JÁDªB[`¡¼l%†'€³UÕóÅ(i¼sž· MÊ)É0kZvžKQÂVJ Ö°S;l#m¶Êi´èau«T}kÔkâR];[b‚J”×·©ð4Í‹†ìÔ9·bRòo[&0F!ÜAL¢$ çn©4¶0A4Äi2œFŠYS`CÒÄ«´ñHµR9FÓu0ÐEq×àסµ–…óo¤R‘VÚìã“›c6L[J©ÜÀß½5žl©[÷¹ŠdZ×ݶ“ÚyÌÖ(@@ ÓÔ/îtñVÛ7;>Ðq*!›xL7F¬o‡­Ä6½‘ ƒl°x«ó(±ÚöG) É­p?îÝ9ÿa|÷Íàk¡.ùÃ;ÜóÚ dµã ÕÚ„FJÀD¡ÐK-2qæ9#ÛZ1¶(>?'«¤$´±~¨ 0šIy-h({Ã|Æ&3 Ys¸ #Õˆô‘ø~ß*›³•Òšmº” Ï­I€éŠe}¹xB¶àŸ[3#Fª‡Ê¹iÁßa$˶·Öù¨ª¶Õ6··ÛdRp³av€¿P%(‘&i¤:"iºØu!“µ%†ÙÚºLJ@0¬;†[…ÖšÞ†g‘ñ¶À`²R+˜» ×Ë\»LHu–¶¦+3¬WÀúع”[k¤ÄVHñ©©”¾ÆØ%ØN¹ùµVh+€¶µÃÍÓjŒGÌÐVÙSv?K5Æã(µñŒU 2«`¥Š` pkš3¾™3„…Þªü½7̲ôi4Rc€î„pEªg‡«¢x¤ò”VÛ¬"Åa1RB‰SH!ÕÓ73{1ŒíËŽ¾WW÷L0ul[˜€¿µß™Ó£vH”¶BJdn+U–aÎWuxc<ó‚&±rþ«gdzaÈ`J)`…ñ˜kvÜ8WˆÔˆ†³¾Ÿ²;3²@ÊÂ@k¶V†˜&´M€éñVü²Ý@$™SÀ„y€ËA¶FxÀÖ¨%ÜâdH-^hW¤Ùé ç@,h”[1¢-¦vÀbJ)a«K÷Æü-Ç«JnKc|×^‰- V¹5¡ÐÖ S8æ&OV-L³F¥&¨Ö–@0Á`> ¿©?P4Šw]j»C ·–åÜ×…Ï‘òÚáwÒj‰ïgfX˜\G[!ÅÓÖgªÂ4H)Ê&MÓXñ4Ö°•IJ†ëò1“}÷bÔH¡” óÔ]-,EvéÏ‚c–e«Ä*¸Y3!Ž´Âõµv˜¿ÿýïñ…R&´ 7ìiÎ+gèw™¡’̓)kj•Mpì¾1 \Öʶ{PÞw£1²ºÕŸ«V’ÌÚ¨ÀLÂ4ëŒò}RŸ¶ ¬£ÈÃ[‚O# +lKÖ+ZÇqïO—Ö¨ªÖW9\ÀîD¶1‘Ö¯üóqKcŇçc­Ë”™l@›áÍFš%UµÖÎIÝsßz=Âv3 †§·Š>ì²R}¾ö,dñ”&dzáòmßj×Úѧë÷ûªg”¹Zζ­o©c˜óìX ‰>Ÿ+“"@’2JÜI¶¥éšðHßÖ|¬È~#÷>)÷ÓI–s>:ÚŠZxXðŸ¦yl[>Ý)L\w½l­Vµs˶F’R«Jôlü7TºD[U&–UË0­BLÁª1¬¥êEcÛ¯}:Âü5U› ù‘fÃÛ’Y)u´& ‡ë«K˜:Œ B)!Å©üß×WøùúNÿžk¸v| ü®Qjcã ôr–¯ö\ˆ³[ñ:ÒËÂ:ÚV5ç”M7'%ì˜Ô¶ìºkJ¦‹ê¥„rddLM‘¢ûçæ«_­-™U¤Ð·Ž.î¢i~€IM¥Ò°z‘8xšR~íNÆH‰Ï§Á¸ákd嬵Ôôlx%@­ѹ00yŒs5miŽúþÖe<-º²j¥Ípµçެ»ª|xª’꼬`YÊÚÉôHa›I[8]ÀÈvEk„ÁרõúÚŸGF`àÌYÛ¾£v™1µààx.R¬:iž òáYw2¼èAX-M+° ðV8e ½B˜¬ºRbL)d=0˜, ÕkvUgaÒ%¸/§U• vºüÌ­…™Këž™ô dy à4¸cªÝ6™5ÙœoÝ9ÏÄzÉZ›Öq`af2¯iUh0¼ªu¡Ig)L‚`üñ­ à¶ø"F¡’4ßÌçý4«R4æñM¨ S•9 ÐdVO*Y[Ùj¥ LíÈ<þª>/¦Ñ%Ûç¥rUÊu!è3Õ¯!™˜ÀÍ;‚!‘  ©F 9تjÛh0R€¨¶›W‹‘Úä >½lΕ0I¨\¯²&¬{“ Éœè³ ‹ñÁ÷­E2Œ²­/C]ÞÀäŒ$®/Œw¢¶j @_ÌpZÃ+áJ“©å å1mUN™@Sëw*| ÃÄ m]d[è›ÞÊ–(ÞÏxÙ²úæO墪ÕbhÚÂdÊ+L #™ad7 `BÊJÜCŒÂ?°mŒuÊ<ë¸ùLÎÍœ~²H,’'²0*‡(`ëÔ4JhÀÛ…ÇH1q^¼@r@b„”m…° ëÛZu Ëv¨dj…¦¶ùØÛRxzílùœbCìê%2jea$ðÑ€^t¬+T"`ÎxØw™_GíVH šŒÏð¥¯6²[@ä©/kLI?Ô’ xþM‚Q˜cë*z¨ž<}WO\Ä[Õf»î:¥¾dpb[ÊóÌïo“‘L[¹e(•ÌVÉyHßï¾dVÇ”%[I FUµVÑ% lHÁ„ØTo‰¬îd²Vµ€È¤Ö×HøæM*'VŽw{×à¸å“íëûÊ2) 4Œ.|27*,èñH  ÈÓ‚[®WŒ•ÆlÈ+?T´&ÆóÌÖW! Þa{ Ȥ*ä÷h:¯I”3ér”ô.‘ùC¦.Rµ&ødÕÊXlyÊR­”4œ‰;ËÌ1¢9{^1 …œ# IcàׄL6±îÑ6ÏÎÈŸ‰Ö~˜d[y ˜4p©ÆÞXM&åóK/Ìf»ÂA3(!(»1˜kÑY€  <Ž÷Î˪jæ¥dabÀ*¸#óÌ<Þ¥Iƒ$ÞËÐaÓÃ"àŒr»Àm•«ÝqÒ'£Q«Ñj+lU%å8®(Æ‹ç±ªâÆ¡§clêÒÑâÓÄ(áC¹î¶R rk2Œî²Äv±£#«RÒÚ²’¥é€€¨WB#eEJíÁÍÓG5Ÿ4†²ÖkvºÃÍŒ©Ð%ðOЪ\È®jL CÛN>+—©‹y8„iÝÛ«Iìo aÀVÙ ‘ ‘dbcÔÅ–,ÁbL#ÁÆè~Râeû—ê…énm{è¦ÕËäu—e‚ñI¬üŒrŸ‘­àL@ pÀ$¨\ £i€¦@”Â"Ðj¡P¼ÙÌ1 Òô& yºÀîPG€Ò ØÌyvê”HI™À“âFÃßU(”]mJY LYªÙ"eŲÀßþö·Þ_þl›VÇÜ\]Ã¯Š¸'BX9 …Êή #+gDZ‰Í†ì)({ ðo!œy>µP®¤Ö§Áu¶bÒ73+̺4Òõ:Ž”hžãr}f¢<éÔ ™ôà"«Jù­×àó½½ÓMŒi"µÀÀÝÒ”ñN×AðÉ$‡ŽÓ/™ý|¯/« Øð3GvWÜz²Ž)”`òÜ<3ÚZ3·V(1•s[€UQ±°µÒÐÓÀ¿ýå/¡0n uØïS!’õÚÌ4`d·ÑyðaålËjá[ÉÊ¿)›¯±h¶ $ƒ¥Â­¶M%¥ +2g­aÑ@U²fCfn ¨í‰ö›™§R;2U²½l­ ‹<;¬UU+ÀP¤·¥„Yål­ é ×ZÐ UÉV ¤—⌬/R`l­œ§.•L¹-Ì!+úšêh†š&¶4æI ܃µ¾Ra>ý¢ÖYúºÂÍÌeóÇcJ3²UÕ1=Fª™­H‰ÌP_¿ZÈ*¶/£o&×à,4V$ ëÑ0¦5q>4›°çè6Œ·Ni +ÖnûŸÿùŸH†}ÿº@žô9—² ƒÍVÒ‘‰e­{9Tb°f“­Ä¶B‚¢¶¨D6% ªQaß`¶R&Q«ð­U…¼G#ÜŒá;¥/F‘ s!ÛjÎN„áV-=²O±Zždzu@xQÊ*‹ädË!\Ð0l¯J¶©lHÏSU@`´4ñIÜ/Ù0Ík…/FN©‰1[gi[˜2½s.Êm¨Ú›™UGË-ÆG¦BVœ _Ë‚&ž,š¡’¶°¦·Z\ùgªðÖþ±UÂD­ö437€,&sXÓaãûÀr39™ èhœiÞUЉ•LJ4®6°Ù–µ²_jŒ¾L0ÂÖºû´-nò# 'HÜÏñ‰û%ž¡§F†YÓ@«Ðaè¼Í µèU‘êáR2lBå>qºÈº[Wª$œìët~•”BÖÑjˇ¹UIJBü9ó ζx×xåñRl»L†Íó*y ÊÛá×Nø4•É{Çl])Ì„+¼@ê…çVv¶µ«jSup&sVΰ3¹19ã«bô‘TÞ—žvÙZe½VÓ Îj; ç’–m1 Tý87ç¥Ç[«UU!¦Bkh’ñ'àÐHsóŸ… ™AÛn¸Â±ÍÙ6= ÄJ&ÊÖèjϲ‘6'PTÛ½aøT•9†•,ÈÇj°:Z)«ªœ8€TÒªÄl”ù7'½ª|èm‰1‚¾%Æ{²óÏœ¬™ DÎ4E˜ìNK L@¡ˆ”À­@cä/ûÛï¿ÿ^¥äfQ«J“Y -e˜Øæe- ¨ê%Ãøºa»9ú–QžŒ PÀÜJðÍÓ™á&ì¦l™Ãz%–Õ1µÛvŠ˜²>Í€ôÁ³6b&Â_ÙÂLij¥lBXDn¥ä_#÷I °™ÓÔî“©)¼»‚…òë}þR­u©²Å&4¶Z|2…°Fò4C÷†$X* qÒXë…$Hƒ1¹# ¸+í®Œ$U!¡vs è¥Ü”¶ZÀ#ma°²1mõ]`*?“ÝÇt«=;ÊzeB£/œ092< ꕾZLÛ²‚q·e#1<ý]ÀŠ¡kñʹ.-òï`U!R‰íZÛ ‚¦õÌtz¥ÇÓT‚¡™ÐH àÔ?ÈšfH`«­/&A>&'83Ý_S*OÐ÷'CÑ…ha§&(¸E2²’aÙÖÀ€[m«–@Õ=ÊY”´íÔ1VÊܬ“sg¿ JU¥¼Ç C H 0=žØ‘;> ›É»"ãi<›„•è $#¸òÏG¯ÂzY….¶Z}®KŠl­=¿Ž\ïójy w(JHq«ÐºT}mšÄ¶â–ž%ýË4gâÉ"{ÿõ»·:Ja> OÀ8mÇ„{ßr Q˜!fVd°¬#¿$7úº0$µmÍaØV*r) ÁÊVËÓ¶ [iú,xbL ^ ‡]ˆÖ~qôŒêB†©Q`[$,h`nUé¥KþlÍ@ã»Èš'Ð@Yw¥|7F[‹ 37m![ Pþ’x,TÑàE¶[#[§IfÅ0_¼þ3*ÑËðÎÕ•Úº–^µBC–C¤¶Ö²µ–Dn@Ô²µbTßïg¯Üj„WÞE4‚» \ä¬×F°Å°Ji«ð4û†*] X#Øl@§î*ÈeÕ †V¼“nx í¬UV¼8ÄäV/]€Z[ókÄEÙl1d0‡õRB‰/r³~\îH4̓';mî³c•¿5‰¬m0üÈÖE]á¯QJd€?@¯{ó;LÐÖ:ÐcÈfR¹Ž u_Çù‰§QÊ×Çx½!þ|åŒV§3§w€CJk˜OÇy'4†lÃÔÈVP"»F<ÀÙÍÀøžBØV‹°*Ýc”ˆj›GVèŽç l‰­ÛN€O™s-¬ñÖÓqôUk+øË¥.÷™ϰ¾øË—’UeeXë4—’M&{ÎyO ;ˆ5±µË,«©Ÿ‰ =µ™bþ²‚É@-täÆÊŠáVa§Fz:V[…R0Ï€ª²HLå²xz[QSN9+“KÍ–£Ã'·4JÄ1½‘²ùV$I«­øÔÜÿÀ«µª’‚Ûbl›¤ÚLÒàßKhûÛÿøGo!#÷( *:|FR>?,¼ûÚ(H¡*/«­r‚Èx[@˜²$†U#*ÁÛV¸#aüe+KOÆ Œr!Û¿VáÇF³‘É ²4aÊŽ` Hæ$ã ¼ƒ3©¯kQrš}}Âü³ÍÁŠG²¢pŒµù‘&×®’þÜo{åçAêh¥ÑÝŠŸC¼µ™ñæ´í˜Àp<†‰xGmCÊZn…@ÑÀ fµµª[;Våcdª: 2bLíO © Þ*Õü t2‘ˆÝ’ª“’ד&«^úE2†üi”çCPß ék¨‘²â)exXtÛ,ó¬ªJ©WGȾGLÓel­"g+1¥µŽV[< (mwœñšRYÁ?^á58Çu¬ ¾{Fv4nð²ô4Üj4@—ª”¸UÛÌ¥~åÌà„˜L#«xË뾦Ùäù·­/~‘OOÁ6%7¯«9€mU¢¯51Ƅĕ¨y•u¡§¥8T£™ƒU$î€=©×DÖV/…áÚUØxé1¶®.+[U¥0ªD'µ¥¬m­üз. ›!+|†ÖÜô¬ˆEž)e·Å•”Âälkr+[¤ªÆî^ÛÊ1 ˆîÛ½N5Åo‚ZÕ*¯ª•RmX! F`¬j‘sVuUGö#¸1Qµ‘rKãûiSv²Ì{¸^N[ÖjÉX <}(Û¶V˜¬ÉµpÕÌm»=€À$+„}”2¤=2ØÌœ+DRâÉ`do›s3G9Á˳²Ý L©õNè»TÛœ­†‘B:‹mUÎÎ-å9ÕWS¯ÄnŸHo{Ôß·èBvi¥Ì£W}1jEÛæD¶ÝAâù›Íêï ÀÇ6O†ÞêH£ÄvYb‘³”H£³,²h0YÛ0zµÌ+\‹JlSš¦·šÓvë •ð)*ç¼XwLçb•­”îBÒŠÉH+¦^qà [¯öפ!­ª|óaöY°õÎËr°VÞ¶îp­)1É`%éën˜†§KgiËaþ«”I&f.0“^ ©ªBaâT‹/¤ÊÚ*QN`˜ßþüç?»}lTîr© zØx Oˆ¬¡„¬#q%ë·[[©]¥®¶ÄÖMSŠ'à„fÅ_É~Om …²xþpÿš»&¦Ì¤Öp[¶EÌjmaaŸ=ßk0Ob†zóŸwÏY•o;lk€®®Qâdl+1¤+ª^VP"§x‘ƪЖæÒ§$·ñ9¤¶åÙ¨VÇ‘ªuå3Y#€¦ùWXÏI—Œ´­Ÿi[¼HéZu¯jb-¥•›Xª8”u'lYQÉõøe"«ÄZIYÛÌ¥¼]VV=â0™-2g[XJ¸±ú*Äc’0½®+{jîMÒÖÚóåO&åZJÙ ÙMH37½d¥t•ç†$#(®Íq¶ ËÒ¤”_âCæfø,eFʇ ÚZ)•¬ïµ??–€Þ^k>j˪“Fªù{²l1+æõµí ²p>˜Ý²ÝÏÄÉ84Uξ+¼Q¹xx !a@`˜ç€­P›N0ñ¶R+T+Nå÷”öiÚú‡Z&Ä3?õ7Ö(óºÃÞ‡ÿÏÞ½µ\—IgèKOˆ7ê…OñS ŠŠ¶z=¿ªÿÞñ®ÞíÈœ‡a&aª£"##³j­½Ÿç탣Ø`ùsêË€†ÞÚ­—²ÝlÝyÃ0¬…ª|*Ùœ«Â7a©ÖÄÖjI Xl«W«µ0¹IÔœg¨c™U' K©Í$q÷À­.d ò¡Éßv€€”U!ÙÜZÛÂ1VL„îp—ÜØ4Ùš Ðèéˆ Ó4 CV•h2À¤­U•†½êY©EÖ‹ 7Jï?,øPö¸ (K寖F‰Õ§U †•XH‚¦–‚Ç0¢TµV©3Ó ˜³yÒà0¶ TÞv˜&™*%ÉÌLК FØv-V‚°B|µw–s¢\W2 ÍîDIU“`*Ì­¾0²Fê)HÊ Ká….Âï'aÏ¥ŸÊ…§\#¸Iˆ× î¹Ì£…Àˆp%‘Fe˜&sJÝ¥0€, ØÅõ{}—¦É0ñzEV7^÷ƒŽ5Uˆ¯ÜjH+Ú€.”O^ª‘²R¾0Me…k‘¿­+m¤®¢ò5²Í'Ý•#À‚ÀšÒ¡àÌ•l¤™+¬¤F­˜~$ekÍmVØ–Ú t @½ºŸ ›¼*ó®¸Zšd¶cd9×Ù¿úïÊ(3!ÍÙZ ©ã MEß„Ñ<¬úÐöé%ëUh•êñDbŠ;àyÕÈhÔâ‘dui’Ä›  “Yb*Qž>Ïç´·î<ˆ'˜¸al›¹©àx@•,^5Å{”4È0યðõ“ÞœxÙZÀm»Òœ­¶øjK­5€GêÔˆ8>[|¶ÚzáO¤^€]rÙJhT1 DZ܆ɜÚͤ¸9o“è%›¡¦Fm[vo ¥Èæg"ˆ­ø–&¥ñd[‘{èk×;f+Lbeb¸Õ ä`+Û‘aƒÑØêk›Ãz1;ZVôwÆ×™ô 2[k7ó#Û¦±nþ‚^-œ¡5 •@6S9€± Œ¶…é¶Â²¶¢ìÚ¹çŽÜr Sól»¶Ö]]²”9`2$Sèe°ÒÓ‘«‘šÊA"µ«/%ð¬‚i„.¢- ‡ÄR•Xùð4à¤ÄÂ0Žÿ”)dE/ÓûडŸ[í®Ç!Å:&Ãpð– ótÉUáÙö¤né뉆RÖ„”+@È }…dùÛVŸÞËßœNÔc*Ûév¥È®‚Œž•.x@j‡§ÙŠ4y…+ÉMÇJ¬éó±~œ3eÇÑ47βZ4Ì\Ìo[ùÓÖMJuüx2nóa•w ½¤*Ù0µ¦ÏÓ6†iZ+ÊðË“È[å ÞéìJ$ {iJÓ‚>¨Ü´‡‘€âа!h¬ÁhJï„-,EæÀÊZ­îªàFÊVG…”ª`°aȬÈ4ÕÖ®ZJYá· ÿÀ€•&ó¶ôµ³MiŒü­n¸ÿCl°~‚Ò›M¤œÏ³{ä˜3îûsœàÐØV[d¿kºXþJŒÁXMbk]¬‚†R„/wžoG³¥u±ÂÄ@€ƒ£é8[_v¦‚?PmkdZ÷ƒõ¢„§ZÑ5Ê5ÕÑ1kwógò¥®ÓùYîe©„•<}pgik¶m9ÇPê»B¤@Z•;HVô&¿Érxn i¤2‘í1Qƒ§låלV)¤¯œ,íŽÃ0R¶Ö1éùó]KÓ^ãó4)1‚ƒy’µbæ¦VØ*pǼôkIl£°Zc; ¦Jà•tjzðÄ«ÊëRtLó‘êf0xÆX1¹5Ik%|la&•cÖEªmƒÁdË®un1UY ­ö-DÖV¡hHo \#@” Of Ä'fnzàÜk“äãM3yåz[ó“uFkY@Ê hDlÎΈ©V±x“Ð4Ï<Í“‰¹ls6˜Õ…$XaÀ*2 [Ó[ i] xb¤mSU# à†aoMÐJp“gÉ0«!Eç%~*;ÿYÁnÃ퉚ª•µm WèÒCYÓúªÕQ¨ÍúzYÅÓÓ°M` È=bXùš5?1ïÐ$pG£ìtæÍlxU}=òÙ´e1‚àc*[!•O[k-g¬÷ÇjÙ…Æ#ÓÌ<¥>J2§çšêÕíÐËö'à†±Ö¥Ï -}&j ª")i:?PH [ªê`Ú®ãÈV[£léñ‚‰S4†¦Z3¨Â7LYႲ&pÆuDv-1*>¶4R¶ÏB)(;lâ +i° emE$ 0™øv@N@_£ïZÛj-ELÓ-µ…É:x?™h’Í  ÙÓ‘eXÀ§Í½+²*«ToÅ”ÈBSÙÞƒ!ý ´åйd‘ʦeb`šm *¡‘µ $ †Åîý>ñßZ*±÷D;ÃôÖ)—µ%f¹4À‚½-MΔ]¬Ù|VH}ÚVNœž•ÚRµ¦)›À_ÕV%x3”0"%2Þ6Faƒè\üãièñ¶L¸¥I0‡¶” F ¬ f>«@Jž²­RÅ™ò>qó`zÄñV-¬ª¬4ÜÈÊ `àÆP(ÂÕVÞJ_ÊkϩР‹9« çV*ÆŒA Jyç%Kc-uæ¸ÿ³³VäÝ}ù°(DZkÄ é£ÁÙ=h—›Ôî­±«"R²šÛ&¯©µâlþçW=ó4²9[›oQ¯[32 œÒjS©MY9r8Òš> uìn¤oY>ðŽ)hûM¼>VHÌÁ*0VƒiÄÊ À˜WËû—J€ÈÂÖ^Ë5 ào«ãÌÀZ · ×¥³˜ì ¼œVds"›ÇÊÇjrVþf™¬ |J¤¬5}À@Û7ýïd¯z—ïå´UؕԺ÷¶ð3:…Õ+×ä0`¥4jnVxþ¶j™ó„wÀÄ”‚NJ0>Zd›ªL ÐkW•ÛÆ0iøfk<ªJ@àÐ4[“Û&n’^›ô‰«’ͼîREå0ÌÓÊ¿ÐÚéÔV.%KUb+»U¡bòè…ò® ãéÈ*LR» LÐãæÐ$4Rܤà¶5·:‹dòÑSÓ[ôúÜÁjñ áΘ¬¶åuÄÈ&°ª-§Ç˜ m;8r­eñ­Hšæ±ÂÊGv!”¢2|ÚÂdâLyjð_ýâ¿`'׈.…;pK^ÿ­)²ÆF¶ZÒXÙzÄ01 “'Þ ¡¼K¤ÁÐØö²JÕË*·*/òºka`$B#l…­ ®’LÒxðªDV•XÉNý»/ ¤ÚpÛ|b¬|šàLßqÈ4*Uw)âùÔ71>çnÆAl šl*Û4É:8g¼u2|ÊRÄÏv°p¥•Ô…Þ´HÛls›íHY䜬DVðïgLÇZÕÖÅ Ë6m·aUn˜¶@í¬”9 Æ×cµ <&&¢¯'…IJªM2«BŒÌ<Ǧ^Él•S¦©oû»)°ÀSÝ€•­5CY&!ˆáôÇ-)¤D&ílÉx6IJX\ù—³ñŒ$ë6¬”ÆpÆÜ×ã| [s¨#Ò¶µ7 RQa@¶{Ó®©Áò¤D +>“Y‘]Ëãù1Xz‚}¾ŽÑãZè¥Do°|6€±’u±c69l 4v[éËVŽ'¨¯,CxýX¶.Hb¤ÀÀñ•Ø )«ëÜ2ì¼î–³hš'£¶` ™ùx¬UxÊʑߞD_$Ùf#¶EæˆHV¥Nƒë¦Æ?гeEfM“åMk%k¤Ì­Çè^…²Bxäí|f‹±-Ûq˜ºda]±ª”§ÍûŒÄVá¦jk£0ŸZÃ5Ê'À<ƒÒ–X Àx7¦P‰‹Z °EÖ‰'ÈM•ðJt|Y¼‡…’>ŒÜ©Ç‘'r©¶ù[];Ò·“ÚÙ )&Va»Ô˜«ú²J¬õ%í\Þ$ÍI,…ô¶ç¨JÀH‘ æfÎ7 Õ¶v d?»Ç÷eUÉFGn$·Ô=pÀÃk­£’®¶Oýܘ[&M¨²2Q([!Û@µ²¶d¶ùçc»V‹©°™mOV¹¿­n+hJá Pí°ZA RZ+įÖ$M®PTH©UÒ–LÖy·aáuê ·Éë³#@é7‡ú‘ Ü`“Ûf˜R‰¦z)ß0î³€FÄp¨Êºa€”‘é­Ä¬š&r×h+ˆ f…)eë[ÉR¶æÿLÈ:^LeU­ Ðßl²H˜ø¬þà/éä°Ô¶ T·5 ›¹À|´TÛÙT)¡ôÒÓtã<ÁJoÛ=nVÎsþH åÄ c`þ i˜FVà‘Çè~ë5I[kbJ2 zÃ×_ŸgGåà™(¯$Po¶x2ØëŽÔ¦ì¶Ï wV‚Ä0^¶ñÖµ–rXLÑvÇÔ(‡¶Í\ÄÐ}ÇA(iÈDU¶é1C6p™C†²@>ý‚›O& ‰;,>ek¡¶¦ÕZm­²"Y˜mš¶Ö^6z‘˜>Ü6 Æ hÔ/U4Æë¡p¨2s]TÁ@ï¼Â>{”¼ï#2æé#ÓÈ þzÈ-É!Må˲š¦É„“3œI„µSežz‘HÎ!1 ; ¤Þç¯U1dÚ)ÑK£Üžž m³UB g¥hþz¹«úây2t¥°¬5“@Ýém…-r€e™¨™ÌZ‰TOÇðHípÈÄVw‡0ÃÓïŽ×«¾T Ó‘¥äï˜`:‹Ÿ^dº×ÎO#®Çë‹q晘„ ÙT¤š #ºFµåÜ ÿ,t½ÕÊÒëØÖj+”«mà¥r“RUÀN‘3@-Y«`ÒK¢¤£Ô‚³ 0Úy怔R|d÷îËKeÛl@õP•ÞúRªè[×%Y-ò±>}êÅ_8šTÙ§ÿ®´Y…V̆Œ¬ 7[)AyíÏÙûûk9ׂqiºª8ìC"W¶V[‚õbH‰¬]¼­ +`ü{wþzó¯'²mäRxU:>``Žüžï4ô² šfH̤,1²-¦S'¦äïÃåÔ´Zkz>p)ë¶pÛÚ¥Á¨Â0§>G}rã^Öî%Ww̺'hÍ9CX¬#U½Nj#I=KªÚMÚÊ*´r›aØl¬l ɰªZdÉ–ŒAo­ Ó¥—ÂH¹“Jö;Àóþ•ˆj­B¡©ÂRÄ ëe+{ î5ÒH‰Ä»vÀ³ú¦¤³½¯ÙÊ#­˜¹=I¼èøÉÊ³íº–²º¦m[9œ¹mx+¦¦«ëàHÛ©|¬˜Î[Õ•|é…¤1•œÿg®þˆU†Í"mst_á”VYñœ`bz= ¤3Ó [Ì6£ DH°m_U«Ð+e…a$Á¶¦·–ò’uÌÉPÕ<úºYü9Õûv*ç°.O絫JªáóO 3q4Ø6‰^>p_ x“xªˆ«ZSbÎRøV)A*çÍŸ ùWžs)óÌ ŸSv [˜Cú>«{¸ô¢‘€L¬aVÀs½Wûú‚`+XñTX1+ÁtL´Ö 4U'mH2À_9e†ÝO-¬: hBd>Jb˜«%¤udkŒ¦²­Ælm«¢Ÿ;2½µŽ 4jr+FSæÜ„­P‚T^àúŽi+UëHV˜<­˜&a«¯,R_Xª1ò|®dÞCæM¨S Œã`Øæ@&0‚¦-`K`Û úblÓØr`+‹of¸m2w |Øö» å EÇ©öX¼û¦© ²Ï~­¬d¥é¤0[ŸY÷Ú‘a© ™L&•ÁΫæ#ˆ­4VU@ ˆ|:`Uëe+¦i[‡…Ëæc0<†LÀn{ŒîïÙÖ”²€Z +#õŠ*l*Ùs´h•r˜Þ*£ÚÓì}÷CÖñmKÕ: C3˜¤¦²a+“Ö¬l«µ*/<ÄÝ3²àŒ—e+øH5ÀŸ¬–š¸pÆ&‰L#…­€ ´6YÓR ¶¢'+%*¡ÍLÓ^JøÉÛÙ9Öd€,„É´ž!ªµ3`^# ­SÀée².gÙü5êãLLfÔdYY1ÈÁÐçCà•ˆˆ9 e{j€¦JDnÄ”¶”¾àôøX‹%̤.4€…ea@#á»Àœmó·âYÝêsW¶°Â<¥ÜžnÝ dRÈS•ŽJúE V"«VkÊd¦ÓˆÎ®°ã`šéŠØb¬6‰¡ÁXᘆ T€§­Bw¶yfwoÆJÃyW´ãhDÃ*ò‚ƒBÑó”5¤l‚ÄÍceEæ%ǶuT…#¹Í'ÞÖ$ 4RkãälLÛœuÌ™ ÀcL+Õ̹É*×ÈJU}ÏÙæŒòŽ!zØÊ9+ÎRäZñçTïßK4òª$–Ī˜¸êZm¸¾4éOÙ-ÌG¶T3{Ž|xÚ®¤‘˜a]˜pÉ€l NƒwÄG¶Ò׋„U¶ÈãuM¬µØZaO™wY¸¬*&†gØ-Ñ€²i«B:/¬ŠPKfõÝmþ²Ï5eó4ùJ0‘4šjd›-F4Y¿K5†5Ïú692$¦‡Z0aX÷Í“Æh ÇjKS¡•L°ñ¬â1ó”:Cß³XÇçÓ­O)ðHJ˜†²°Õa¥àª’‰‘@f½¦Â™ÔˆUb—‰ñåV/¤ƒ«ÊP!Ÿ‰abJ² Òø˜Öâ)xsç¯xÎÖ¢î™D`RZkêñþ§ŸL¸9ÀÍ,Œlr>E½dkÄV¤!Þ#lUYÍ£P•¦˜ó}$ܚ焚E=ú¨(óœÊÚÊ~ ‡l«ö¢OfJÛ`1ÌÁ–sï.L°’ݲè$ðzå£EÑ ‘V¤µk«J4UYlžÀôÉ ä¹Î÷`Œ¬->À Hv+΂¤™Öm½n©«îòÃJên Ë2¶õ匧è@Š ‡Üb„ò>x^9ñnɶG_¡”’fK_kÙü{|Ês–§Í=ÈV$9Z¨)Í-z l€ª§¿0Í3E`$VÊ«zÎ)¥\H¥”µ5p&ªÒØ"ÉDsúD ‰mMŽa…Ü”ãûK-P‰*2«mbJ©ªlVÖ2ÛbËŸósY<[@ªIj„øÛíõfJaÐX¡¸ô—W%«ø|0ª„yˆmo‡×óÕ%F°Ýض1ªÜm·äq»"ŒG¦ «æäŸU-ªU"(m ¤CáúÖOÖ õJœ,7 ·øÃ(Ìa‡J`CÐÖšƒFNá3‚ÍCS÷u´ežIåj1‚&¶‚F­á+±Ú’-›ÒÊ!LÜmabU‚&CÀŸcKÁ¥ôˆù«¬.d“ UÝäëMóçUYŒ•Ø*pëi*©ŠUJšÈÖJz‚º7Æ—gÏ=Á޳vøvœðzK åV¨Ä¶³7Œ¾²ñRÈæ13¾^H ¬Ñ@V¡Ê*õ<CÎxUGô¶Kõâ©’%.ÅÇA`YJ#ÓÄèˆìIÁB9=¦œ óg9,ÛÁ•ßÒó·ÌÕ–?fÑÅJat±ÖÂZ»˜Ì«ml©†ÏÖ*…!ÙJecÚênB|szEU‰éÉÚZ×ϬætR…t$SW£Ä«‚a›³Hok˜kò ðaJa+õiÔšÇu§QeN¤T€s3+¯Ë k­¼™•;Ì ¶ÀS+bè9¸½ekd µÍMT‚a›3²–0‰2×8 OÁ#{¦¶™h½»[©çSÃÓè=¤™3Ùj[Û†Y-¦T‹ô® ,Jx$‡H¼¾½*x}­6'F°U%A‡3‘*;Є5‚ bó§„ù0an…—Z! ñ«þ} OFªÙÌù´Åkñí³ñlZzµ”Me<²À'È-¾Feé 2lÔgÓ9+ ˜ìt0¾¦²ø ñóa‚¯¼kÇÄ·æÜaÍCœs@(`'Ý¡ŸL¬½ô}af¨¤© æ GªZmu¶dLø§o‹‘"ó —e%ð![\×ן‹Ô¶Èp…î§cZ)’~J‡òÓM6½ %P„›“X`îh_ÞÆ·öõ­»òzÙ*×%–jk ãqÀ³…׫.d‘e­JÆ–@9`…b”xÇ”b¢©ÓÁ@ Sw.$†@À¢î],S_UÏa¤*Ì­W… ’¾°­ãéq£*« !PnNa«£h €¶Ö¹ÁÊ^ ¼;ãëÒ ô)Iî@IDAT3Ç$ÆHµ)me`JÅ[…”©˜;‘a0;QÛþ T3S®Fä8Ë%¾ñ®PUY+lž"Ad«¬ðø¬Çч٦ƶ€Õè*MIdhë·?oà3…•dªJ‰ˆ$HC&ô”»Ÿd¾Äm»Ÿ”mU<{èô¢aè|­—ÆŠy’›–­ú3ÖV–•øx‘ªDS=/£Ð<Ú`@ª‘`@‰•[tW. \¶B<Ò`²üÞ¥‘ùXÝ¡^¢0gJš|j'E¬Jy2¸¿+°.Ž ¥—•Cw» Á#¥ØÎÙ–¿ÁΧ ¡DÒ‚üSv.|šúfØz‹^¯™¬mžpžd‚›”i²²5g𦑢A š[÷:©­Úõ’RÅBæ\/«@®ŠmX‰W‹“#`%YÆVLƒŸ \6½-½ƒÛ¦±ÏÌ#msÃԚƃóg@ªÙ¬ :§OŒÌ™ØV_×ãUI&ð¶ù·µ*<¹÷¡¶Å˜J¤o­ÜüÝLG«»•L˜ðVx>€ÈC%ÏyÎïÀƒÄû°`*Á—M»ÛCŠô>¦Ò] †RkŒÕTÍc‹·Õ%`•²>ƒ§­U£ €™U><ÃþÌ“m«¬(K@iÛ“‚©æt3W{ÄÚÉ  9»Ož¶dÖ UÍ<`%h`ë²j+T[9¤ð0eØ!rˆÛf p!æš_yÙLއg¥—Ú®RP†óGæïÆðùXy %+OzY¼€‘Ö1²Z”µš$gµ›!†C‚z‚ô5e%`z²VAПdš$=åÜh¤"ea«È6@“³ª›|=tÛRñiV"…ï–¤„m¯Å:6a† ³ƒ'î·½Žà Pb]¬o&4·ùY´°Í¡´PXÊ*‹4Í# ïÇ_攋Êñ>5‰¥8´u|å‚ÀC‘ʨÐTÐÀ"ÞªäÎòúB(kE~<ýÊ9l²¾—˜è˜-@ l÷ó—ïÞ˜Ç[)·²¶™p0InŽI™ ¬•`ѹIQÎ9½­¨ÊÚ¶Ö㫲Åë8YzáÅô©.6œ2ÁÇúU ŒŽÑ‡H­íW?ÿùÏõn”Ù‘²Ë1ã}æ± P& ±ÕÏ6A_7J+”í`Z7P7žI'ŒgRGY±Vžaú;ï¹J3×îV¼Î"U—εÅ‚aÇW"ò·v()É­­¾pëd ¹duôû¥Z}˜¿÷X-™^ÓLÚæ¯$}ëô<Ô'i‹·&Þ<¶1Ä…F<ËŠ”ê©ÑÍ ›¿•!Ò) _UŸÏnxîA6ñÛìõWdb>L°óT"ðÈ:ÆÔ—Œ8eÌHŒÈPž?¦’¾UI9¬9Éú»#˜ )E• ³²jdM Õv…RHl0 m #g’˜[>®ÅeöV|4š™k±BYLÛº(f“MÀO&U6\-M™¯¤,²8^ï0 ’§ˆÔN m×ðqhrY­+œ2çôw´sc¶V‡%™’Õ¦¬5^(Ab`ú@¿7t±;NæVA¦êvx=Y˜CSÕwØVI“4@½"YIÁ5"èÎ;‚”W³OŒXÕ6‰’ÊéEþ­›!}%œãmi2þÂÖÚ;Ï| »1ÜUåuW"|d¬¥‘áÎ…?=n—4VãqÖ‘ ¨ hCß¶3¡d;R;gìB^ŽoÐæóCÚÕ¨W£¸ ÞV ™øår_)¸”µêDlÍö8ù4‡}ûÈæIÏŠ²*ž¢&`¢6«Á²j0ÃV $ì·ÿÌ‘B‘ Ir §!aÙfCÂÖÌÛŽé F ×B#& éma«m%)á5¥·-àn¯l¿Ð䌑…¹eò\eµ Lë²åŸg/‡±kÄ & 4”L6,› lå̇¾ 3·]a½âWK¹rïa7Ãêv8ÿvÍs€d•+ìu"¨‘^ué,¬l‰>€­”B>V¸Â 5Åä »Z×Ò–˜²BÙ†g)|R/$B+}[xÎHa€Ê™ Y[# @¹¨6Œ'Ëx¦li"«µ ÌHÛ4‘|JÕ¥õ½>Mé÷t­ Éa†™XtÕ4žZG›y|å°sYEWj…µpEÖÌW; %g«°õ:YÅÆKleB‰_yØšžC“O\³óÚ¨•mk†9ÜÁÏhè¥î8ç›p“( rÈÙ­ª%kxä3˜Çë ‹æGæVßJàzÙÊúÿájx…Re½uîªÏÃL(üO¿˜ªð"¥õ™c´«‹”¾Ä&÷èa«mÇwÞÀ$˪òH¼Àã ’@Ã#{-L‡•5É­þÆo­ŠlÛÖúƳZªF¶yjQ*€¬K#M6ÀJX…&å:¶uFx ½mnÓF6€è~¬ÂµºíjóWÞ Rj누ÒÐ ²Ì­¶ô‚¸U¶9mÝ'Íslú¬d¥`ŒÚ^]ÛBªa¤àaVu™->O È3ÛH+¾îÖÚ•Í* ,k†4È®Ì^ÓúZéÃ3§©j«Sp#È3¬.­óˆ 4ÍfU‹o+û,ä ˆiJm’˜Ö†¬þ¹U%0nvuŒñJ¨±æ P† À$çÌË"KEwжõÍŸ½l¹ø9y>#É`Ô  Qñ"=ggÁûÇÄ 7àÁô—;‹!r&N€Á3´-e[Tkµµ*Ý$02n°5A«Öœ#çL6’ «Õ…o° 1²¶Îx~ê@îxßyùâ NÀןꧪ)o»×?5®q!…ÉŸ'¬Àt’L×XzYm•Sô¾M:m<­ÚžP¶¥ðœã•#Ë"þ}1õmÈ9^Õœ†¸.@AP°UÕl˜j‰E'µÊª’5 >R_¼rÝ6Ï)¯Í9]ÄáÚÙ4€P•·‘aå3˜Ïj›Ð$„‡Í– Ÿ¶^ b<%ì&ý«Ìúš¡ o°Iaw.)arÙ&ét™¤$Ȇ³BY%›ÄxZsÆ×QŠ2AÊJê…0 µLª¼Ò5JæIUÕ‹‡˜îØl½¸qHl{…¯//˜’ Ú4œÕR6€“jñ|+vUMH,63š®ˆ¹+k#={Qâ1‘pú1h„,«‘°EޝÄv%^XSó î£4›^²p\§/ßþ™ìÞ2G’5dÌC# ”ª¦[Â×ekÃt')­ýkÄËV°%æð½ï}Ïkì?†½ ³Uáßþö·?üá:VU!\¹Áôâ<†²i1…l#)ÏCŸ±î³õíÔ9Ì\!’©'Œ ÈŠ:ÀœaJ2ŒÐˆ^¯˜¬ðZ8f®:Ê¿{°åödle¹ -j×J†!È?%FÌPJÓZ›¯+G1lõPÈR†aY %«>L„îó+‹$n < › /ø´}’øZ#ï,ç€@âª` Áßu ÇÓ˜N¼K°5žm7 ]¶x« NLJ,7Ö²ÝÆ3õç:b¶ ¬ÞÊç0µ³Š¬h*ß‘m…,O¤u©Êúêõ)îDuQ•ÀÀd¶"7k>me•4M@J!,àÖd½´}mâ•O ¬tQ"XåÖ–,åÚ5¡*YæAk½à[úúhde•MOwj¸{h6¼0åJjÝé…Z+ VréciM³×ƹ*§¨ËŠZzY7Ãü+O©<µ›!KOlÛ$k½.5¥¼E¯ïp¤måñmc¬]En¶ô0ÕVXÖ)4ÏÂvUFje‘V[EðÇWÛlî³B]ð¥ê›9¦ªÆˆÌîÉîQžYïCÁ{-Ë’ÑëÎБf"Éhjª, ÑZ꘾¿£RnB@ z2…Z¬ &°Z€ >²KȤ/"a!+l­:bXiº­Z¡ª’L¬ÈV×T’¡S£ #ÙÂÝ,ÝŒ*!• ?„`Ò á¶Ö4s*<.o¥Zäis#“² †nNÏð¿¿ <å¶:’ÉZ_OWbÃ9â,´® ¤^ì=[ùó<ùËRús§ÜÜ»Õs‚k‰iVŒF­ ·í±mN¤*o¹ÂVÝÙbÈ‚:ÚζBš°JQâÉRÚ # r¶e­Hzk kx‰{*H²¬åe15­¼±‰e1b ­õô»oTóÇ$†ýDô©êB–㹘'¤Fi2‡3I—í˜é•xjL¸Á4»C7Ö§”ÝÊ$%&ÃVÛZXéÅÄ/+H€Rä–ÆZTg«0¥U;%ýlÆÛ"÷¶À‰Õ„ã0! ,kÔH%€@Ø>¿þ´ ÍLƆøŸ¥mLJŒ‡hoN«r©Baí¬™·rðeT•5%²Ö3èû·Õ^ ’a)² ;o…sÈ„5­Ý±~(2Ï9%Œ$SÛä¶ÈfPxJöYKßµp¤¸¹sÿžÏ÷¿ÿýï~÷»‰ÿ+gWç‹«s}»/O)2CŨð9ùû§Nå 0™¬7I¯Üz+Î=tW•ïh”d™š*Ñ‘ˆ·V.›¾¯$&CX ¯*™vÙ˜ ü"‡Îˆ”0¡¶¦*C¡I¦K†ûÚÉÜ=x½;†ŒOÌœ P îA÷µFó1$C_}¿ Þß€Ö ×îÝêü5Ÿµ(Á›¹{¶Å7 >ŽÎ5Âc Ÿ- h¬Ý›SxÁúïÓæ¹3’!m÷rê/™a“дµb*GênÕ)¥0ŸôdU×õËW4ÞaÍÆ(›©¼¾¥¶ML&«¤,RèëÔÁPbq&@Ûz! […ÝÁ3nBb óÒ·%ÈD!RÐXÍ`BY`«ZbÛ+gb‘¡T@Pb-ÆÔ|l)1 až€vȾH¥=h[íš¿gñì®êY…¥ÌP Ì«ëýK[Y׎´Î_ îøx[Ø$pw^ÖŸçsì ­; AÊéÙ 1Äp3dޱ•ÂÃU5[Ë<&Ï–¦*«pEJ:»”XS€ °åcË“9 TÛðR|ð¥h0üA)¤ÙVÞÇ_ŠF‹«z}ã‘!·VHÓ÷‰^¢-À­-“Ö@…ªtŸáñ_¤lû¬… íd×¢ƒ#Ï(÷kS6’°­Ð¸ãÛº&ƺ^a[¡œ'h ˜Á¸ªó¸Yñ÷CGzáïPçý×ÎVöy@Xt¨¬Øb(+0Vå̦ì-=ËåŽç d¾Š})9ô³Þ0ª*ÉD»¼!鑆ÙvŠôÖL¬ F¨¢œ9Y!¥„¿€õ’Y14J¬§÷û%¬%9±PŽ §±ŠL”»„^i?/È2lB8€o0@kåg¸{.­í¦Ê\mUVÎi`¼h›U[©N*ÕUc¬ SÂN×›¡{P"‹I ÓHa¬Êñ0R #ªrÀó÷YýÞãkÝoT5Àà‰VÖÄNËnÀ–¸NuŧI ÜtÙªÕÈûç§&O«*% Á³ ¾©Èâ­âÝáü•U[¼Á*¿{áLy«Ï1 xVh+(ÕŠ¶ÖL0=¡ ^á™À§Ô˜­^Y]€‡'«R­h+[‹øÊ­bøØ  Æ kZ–@oÍ6ÆêZ]»Ln Âxµlm‰Íü_@ðì…#¨/2†0>$sâ ›<œ,†&‡ÞUo [äÆÈ¹÷¶­²xSy1L¯5g¶pbÚ…*WB<ø4xÜ$œ¹”F”iÖšÛ4M›³Ö™ë8C)xkUiˆ™7‰vRÄõ‚AÇA …9¸=ÛZù¦ãp%‡ÄÀ¾XZY¥éWÉðÿŠÕ;Ö—¤u{Ý ì¶‡-™è†÷’ôŒ*—u·Ä¶ðǺ‹e¥ª—%†¸K戄ëõ·ö[Ký'®ºû÷©„;ùýïÿç?ÿ¹Gß«rÇ9cl­‡wbçòqCŠ ­YÝ[8þœíÞ•T¼mµ˜›<÷ÓRܶ^Ö¶—>²ÍƒiŒHüËâýnÄðÇk·7Á$ ­˜4¬lW‘]÷Öܬ"}ÁÙ*a­-A«T²˜‘Ùvª’Eڊܪ’­0}ñ ÉÜyï?A²Ý¦ “jU&HšVà9dÃXWK9r ¬`<Ã䜱KØJnL¤!pŸ0F(2Ù H¸H•Z@¸ Vª4Í .0/Ó·‰‘”àÒX 0ðUÒ ðÔ+¥F­#÷”Óg #¹%SÕ ¥XåÓ [b<€‘"´~xÚçlÍùù>ÀHnbÂJÐ Ö4ÈÜ0%ÍO<¯ÄÍ^nª„^­u©µ{óµÐlx&g¦|¶õ«Â0‰¯‘µKVÔY(7 Ìœ>·šSJ¬|/@¤˜%RœŸ?îs¾¯ïa7@æ­&æ¤þ’©áÒùîG-A䆎QU&p@c&Ód#…-ÌÊõˆX 1ÆjeÈÍʧë“bR¯ëwÙ˜[z[Q9Ynº”}–›D• ož¶3Q"¥|Öb”ŸN7¤úœ#4ÅTŽ}ò]5^-lÛLÒÃøRáÖe;š* gJW#ÇË:”5† šM‰Œ„âÞ'¼@*L¶a0•ŸùÞŸLb¸.sà÷/ʲád0 œž¿ëÍÓjHÙ4FšOZ]»—V•`¢$AµÝƲ¬tì°¶ž=1Ÿ^[¼@ €¾m)d†¶ü°²ªŠÆ`lýÎRnu§ &È*lµÕ‹87Ìóh¶‚B})“Õζϯ£q Ñ:“YEôýâÞ$m lîß Ñ”ŒþVÿ]üÀîÁ͸‡®¢K뺺Œõz|·,Œ«†=—4VŒo]2åÕ&Èù´¼qÜð€z7Èjáù/•½l~õ¯ê¿zuÌÿøÇþ‹êßýîwþi@“t„hRÛ6äs§Á#;WŸw˜‰P^– Æš[Û®äÿl¦‘j «Ïˆ0à8m®€¹‰ßår³­6O-È"áúÀV†²Ãç ù×N­”ÿÓûý-ƒG nV[n¾SˆKqTÕËú²"à [¹u(Øý A¦dxëN»ôÖŽ¹”*/} ‡Æ äSa›<ÃVLg¬c² a ›éò熹¹;’^÷¶ Ö¹¬»ºdÄh©ú29XñÃGÀdø° ÄðéqH¥œ'™lzÙ–²ÖZÊx4Z1B¶î+¯d[² á ®qÀ 7yÃ#WعmÀY¬~#¬ÖË¦Ò ßéþùWÝ€ßþÿô§?¹íâYã>m{š²)©7ʃ"è¹À=”Èž&“|”Ôhß=Jbí¤ÔbÒûß3õˆýim?¨Èþ;Cߟþô§þóèßþö·>ȽÀ½f»[a*+hB St(¸”µpRÊ®@æ e³MœgXJØÂÙÂ}ü˜3¶;´-Û$õªJІ €ZÑgžg)Ì ãÉ8Àé³âVlë­pu¶Eï†BÀœ Èçmp¦RÒV—­jwØd¾ábk€ÛjµƒûfhxëÌ«¢GV¡ìÓêøÞ #î½ü†©\ÞlLÚ2¬ 0U‚ØØÈ0µ”ôÈRÄá&„9Ãd1Ö˜ÄÜbø7!¦’—Fº>påþHÐÀÙZ9X) zš½cÄÌ‘dL€¬ÆPµa6§,\-½ÀD6pkz¸‘Àý0®I£<™T…ý;YÉâÕҜ⫩ŠßÕ ÓØÓc8¤ß¶|ܤ”àìNlYÁn©ßôªµ z‡mÎJâáZ£{9V2A #O…9Hñ‘R"ð¶1<¥Ž×u+ ã'æÜ¶’xŒ¨èCê\pg¯uâÆƒOÍý´Ò«…Éj—¾á9Dn°ZÛŠªêÒÖêõû« ½ÃYk‘ ]þù‘ilúýOÎ10B¶zõ쌥RåÞÚ¶4‰•Ç[ù0QX{̵yý¡­Ãd[Ç™Dæ#¥]×ë霌çôÜl‰“¨‹Ú4K ‚Ä0ÞAö®]²&éUUHw™<ñµ 1pQm-b”8¨­ECZ¥¬µ+L)nç×铆T•Øäæ§×ÂË—rµyÒX9Ðt®¶VÛ|*Ç…T… `×.ö]ÓĪ OFc‡»Œ0 %O÷i ½:ÝK€8«ôÍ· ã¯ñq0èyÁ>E°{j¤”V})sâ›Ó`€0Xwh$åÝ[Lµ;ñœ¶óÔÈE±š@ ÉS‡Ä5õw t¡ì_¶‘R»Ëùð¼ÏÎïµþ¿€y{³ò,â¹í‰Há[Ä{dİÇOÃÉöÄ­y ~áðÄ…,Ò³îý„…~é÷oö[1 ó?»zö³Ÿù3€#È„¢3î¢œÅØîA$°v'ŽàŒñ§òjiÄ0@CÌŸŒ­°MÈ™ËV ¸[¼«†»aúî@*è‘%pn³ÊV#ÌÈ YVI&Í“Û4ªÂ•Ð+Ša—Êêïše%»Påb½T o¤ðŽÍM!&M@ªùó4Ra+¤„Ž5ÂÈ*T%l»gLoµ,>= £V–’Fæ'–J†§$À”beKYm%ÍwRuœ&7kÁÍ„påœmÙº( ,üDÀÓà¾ÚZXÛÆ[͉ª¼Ÿ²’•µ¥."E>[Í ÄЋÈðx€yÛ3ñý»È­h~íê8â^sÂ}ç˜Ù]Y¥èe<ÃsþÇ3*K©Ëp6 1`åÜŸ dm‰Í£ 6Íóø4²Ífk¼†Qek¡ÐT•ã™0¤ÁØZ…B¤ðýÙ o$媺+šôñ ð¼Y…Õ6€•S6Û”óÄ ÛÌ­Æ8F7¤üuS9B}‘·î,J&†óïZÂBÐ…¤'+º„ÈfØ…¿>`ÊëzZ½ÏIªÒÖ¬°š¶°‡¼¥¯«ïN­šæÐ@)ËÂM“I>k„éŠ|zÓ²‚oóó¦îvJK¬5ÞA¦¬œ ³3'°m’”Ú+(õ|)›¤Z½ê`¹M–­U ëÎÖà?tWé›vp×e«,{äF&ËYŸßœRá·FWÃv-ˆa5!'¬—&åÌkÁY Î1gŸ@×èoKœmUñ‰¥Ì–¿¾ôšb„”¨Šù€¦ñ9P ”GÆ µ@Ä À§¯ ŒV‹ß%×”›®#¦±27’ù‘A}më‹„“æîn–$¹Š,ŽoæaèÃ@ Þÿ…X $¾ `ìÇæwã_y:¦Zj•¤*ÁŒ/\~?î÷FDfVvu‹·„käˆTi'PåûÝÔüvZ‡_ßÿ¾c·wÛá;ûÖ†tnßã'œýÛ“­]KúN›¥ï fýÑ¿ë‚æBð˜8ÌeϤPPÒýCteí·»"¦›_¾^®o²] œÔ ‚Ÿÿüç>÷iþÿo¿~#È}ëG&›bÞxö%nwLŽ¥}Y¶å86ޱؾ££Ö! Óqª]šéïžOï¤ÒG(vb))8ëbÕ+2©Ô(Lm‚|&…7É;{l !5eZ „O!ƒC|º^?ˆÍçÛ&<©,ÅÞcYßÛŽ#UBP–giZ2-Œ ¬Ðð@%Ô€ ›¡jm_À4ÑÇ©ÜN¶F©A8åÄ,ÜS µ'…2ÁM,Ä„<¤1êbȤÙ=Ó?f±) Öó^k)åçÊ]÷Œ¦JV;Á6µÆKS,(+îêk±lR–jg cY­.» “ŠóÌ'+‹V9or¸¦Æ ã!ê›%\€‰SªÙ"L³sèH,y%h¦‹8dò»é¢N¯áMØJîF°B%ÈZX2Yd:ÅÉZ®]j–@±s(åFB†XÚŽ¥‹KÈh²¶Ãwá ]Ê8 ¥:·Î–šTUu±Ô7>@JJ¬“fUã—mÚ TR¼ÚV®dÛ/æË¦¶¥àtη‡í­‚&æ»0RÝ=Ø=Ìn' 箞h_-Ž€ Ó¯#“m `1ÎÊcv±uQñBàŽQÕï ¿’˜ÅíSYÌ‘©%¾)UÑ*oTÞͣʋ‚á)t‘á–ÚQj-‚]4LÄJòRb†I¶›ÍÁH5‚°D*DÐE̲DðÅ”¯¢ó#>2°©Äh¼ìž"Uiç„ý…lÙ˜tð»œ×ÂÒ%`µ®Ñ<)Ö`5w–j÷ÑG9AY8ÓH¡(‹×­‚†#VÛ<õRg@µª,Å8g”ÇË\Éæl©Ê2)#@¯@F™¯VÐHÄÅLJ\Jl²-e£Á!pjÍÜÀ@Ö[ŽtbŸòUAR®ïšwÍßT6h¹ØØþq o¥ÖAñŪ:×Ô9À¶]+wøReCxKç)«ÜýéÆpJõzß#ë«». à~>Š/•蘚 ½¸+n©ð }{ ÂÔÓiÈáh—̹úŒ¬{Á·ñ–ͣʲÖbV/ À¨Ç-á/Ýúi°÷Nø¬ýìg?³GЄ;–vÜ6{XœL oï¿ØE¤ã¢Û»#rÌi¨ŠÃßk[R@«ÅÉÒt¤¯»@‰vN+…<¼ SÀ¯‘¬B`xœFűLPÌp,‰Ãgð&±ÍD {Ý+«E#a*òȺ4Ž“ÂäMB¶^‰·ÍháMá½ÛBü‘Ž»®Ô+z÷†¿;Þ0÷SíX\q3wE4E3R¶c„avÂ6ånAèèÚoçŒF Âî4^–‚*Ë^ÜUɧŸ~ê%Zðºö÷¿ÿýÿøGší·Ž&1[q¸ñ ¹u€í½}™\`ïæH][7Û ¸ÛÒ=`)¶  ¸}aváb©öÕ?í…€Ü~0҆l™ˆed¾@è|ü–‹›–‘zßLåÛ}íÜ?»oшè_j¥øú plsHLþšèÜB²ùdùvÇÒ¾xR¥ê‚©f{ç{² ‰Ô…OgΊQûå/ù“ŸüSüÂ|jt]þõ¯ÙQÛŽ ¿mBlÊr×h»Ã„{î<›Ñœ›ÓW(Èœ°@¹[B\Ií0™˜&Z|%N˜ l² fšÖ GÀcŠãl†øÅ¥¢…ˆ)PæÃõºJñj¥ÐŠ™náªÚ]š[»ÁxU–µÎ[²º—µT[Ì‹’Gï->ý»1ö÷éXwMí‹™Ð`–¬iq!E²C°ÁD\ñ ãK!x9ò²ï*·k%u$‹#ki¿)ÈÂñ-ïŸþ¾}x‹Oÿ^»|úoƒ†7ÏΡ­ñ²ü=hÙ–Íf ªXL˜ß tK)'¥\ \Ð!@R‹ fqBø{ÓÀgŒ®Ž¦U <’Þødw½¢‘b‘ PŒÌœ?ߨ›ä¢Ÿóé(ÅÂu¬)¯C¸°ó5ŠªŽBn1Y!1kZ DŠ8¯V‰rÞ’a¢µ”mÀì.¨DùUzγÙ,Åü£âL+ˆ?š¸íÓÊ+—e ¦'e±!ãD†P;w9Ô)8 K Íœo q—*!äÎBq1‚Ôæ+lŽ¥(8Gx·‚.ñáɶäw|«Õ®l]FÐĬiSñ:òáM%Þ²ò ©£‘´`>|˜ÖÉlZw°'ªv¦bb&hƒ:6¤.ô™e7Ö¡S „Ž…H…¤pHÞ„|ˆ.b¶.ð¶ [ ËDpFS¿ïeç0}RvÚ·nÉvªâSƒ÷T4I#_ÝÎä—egb0FÁg8R©=1Û™!mÐÞmÓ² ×½ a6âˆè§&ªâ;±Î¼#U"ÀÒŒ,&¾K¦0“m*ƒùÆÑÑ9CÈû†ìo—2;jZ]Ô2úÀû0¶|Á1κ_uOŸB”«5)µ˜šÆ—B¨D¼ÉÑJAÈ8üZëHS Ò;MHL¾ã;%Þ¯ú|ôÑG]I}kà4Ü®>Ähá ”×¢^–ÎÖOV6ò­R¯Bð3À_|AjÇb˼ÀN;«Íy?ت ²á]‚ðÀ.¨¬ûÇÞYR6[ÊÞ £Ïz"ßwŠf‰ E‡F RLЪ é#ˆ!õMMÌ€¬™Ráøô!Ä‚€ÁÝëX cµ˜^ÌlSUOA›R^-z#CmUÝ–âÔ&KÍIRð÷LÄð×5¿ùӵК5•‘†o€ÎÍÓ ˜|·´íXJ™Ð¾zpètžøâÊ«Eƒ(Á„·Ü8LS? 91ÊΜZU²Zû·nßâ@ü6”^”¯)žžŽ–ššÞ! oÍ#¸ÇÍf`Uâß6-CðÊ”1³éD“=Ò× Ó)æeñ•ë’¯­â3-~L3ƒ-›Ü`}d³®ox£Ú]‡i6%v+úthGf¦Ð¾Ð;ÃâYmg" (@†o×zÕ¸¬€x×T¹!)@—VVß?aé£]¾o~nñOp2åµ®i[¨/q#d¤xsBtai‘· ´¬µÀ G`É*ÁÔÞÞRõ] 2A)fØÙ"1§Ó褀4ÑîsÆOúÓFJðÞ¸kÊœ’O0éh hW“ø‘ YgÎ~„SÝi}ÛÂ9”Ûk…QÙN©sØGÞ²óïÎÚM%]/Y:¬ýJ‰Ï…8‚v‚ ¨¼+AFhÔÄ¿a,°X…–Y-šJ–,AK…~â¥Ðb1•£¦,À!RIâu;.¿åÏRÆù°Qs8n ï:j§¬Qó¤/ÖÂc_4¿ýå‹X?ø¶ûð0ÈúØ´LòŒi<äwÆ1Û³l§j¿‘+ı/æÞ†;áöÞ~áø³½; ^á†Q.^£º«Pc‘!#5cˆáU µŽÔÎå¿n•z…CÔvP“ꎒMªÂÔ@Ì6&h'™º1”àÐgb ‚ÉSã (à‹q;F_ÿŸÆ¯j”û]ªõÒ½™yqã ¼Ø:|¶ÁTYâ„ 9Ìʲ–»(²Èîy~÷2ÄË }LKÇ‚)pÅtè;¢4-‚ßÄ+~Eo6¿ 5AËz mBáRFe‚N€_ŒÃšœ›™Çßb_|"N €’bân+UÜ$u©°¾³º›*Ÿ ƒX¶54²–À 8Ž—Jƒ‰e¥Ôºd `Y nYßÈ®2¼û¼^bœZH¥/ÕRpŸKñ{¤¢™ È½Š’Í&î¦2‚†ä¥š¶Fb%p¾8ß²¸yj ) irž°çÂƳd5jžºK1qK^VaO‡)ˆÂ£,M΂i#m«¼ ð€eÅúå;Íâä -ÇÙòŒùØv˜–ªÚUâm¯‰Û^8&0Üꢄ‰kÄ(,h$qå÷ªmy3(A³}Èú2¯Žb)B}Å[âŠ4MËšG‰lÉR¦4}!L€£$>Ä ‹á¬QËÚ‚v4&«Í´¬I,†¸ª)¹sÚÀã î¯D”ÃLj–•ÈniøR–&¬Š¸î²,Aú0å¼í#èÞNÏH›‡ ômë‡ÿ D‹Œ¦ïþ¥;Dœ¨—˜¦” S+€JÏñþþ÷¿ÿì³Ïº@O ^û?®s°hïÆh’µj#ÆÀ)Ætt<ÎýÄpl“Ø—ZUm)¯µ¡Ž838®Z´ä[^>9"dé7Ÿ;IU`´‰4ª‹r)L±TKX*´ŒÏ£YÅŒ²e… Z&ˆã¾ê⇫¢Ì‰+¯V ¼åÓàêXS?ºd¥^ÑßùgMMe^ßæ1¡™Íà ŒŸ/@ˆŒÐ^d;©b—^6f%̽ Žì õí!­u"ÈÌCow µÐ®Ž†ØWó46ÄT¼ŸY _¹ªKééQÒHµ¤ßÉ[ ˆ#ÔB‰ 4KfIDÐÍ&hŒðâ)§£–fWg3L¹’4©µ_Ù:*2í´hø|øâJÚ‚Ü+›«¬ŠÏàµk0d ÁØú&[÷²…½sm©†Æ·…î±"hQSšýéHqªEµd#CŠéDƒØ7§èV¬V£,‹eÍÌ`)63ÑÈÓ´ⓦ"ªA'^¼TŠõ24žâ¶'›u±i",¶‡È8^!O¹] jÚöŒ‹€I¤îUU¾¬. AŽÓeî€bÚÉQˆ¥Üv”¾ZˆÂ‹xhƒd ʺa*¿ÏI§—&K„)Ça‚ø&ć+gåé-,² aåp£Úˆ ©l9Ž€ì¹ÑýÇB˜;¡@^}ºð;tmI ˜@jì\pâwí¥V帪HéÂT!³hÏàÝÊBŠ;©‰“eðæl‰\²-ëÞ!¨B0‚”1 )£—•ª©l-ÄÛ&>DIƒ EÛDèTqĺô,)ʉ+WK™Iñ^Ê!¤º_SkZ"*L1dœ6(†ÐAhwh§Áí焦B~¶µ Ö«2]jGP¬HLYŸ6üê0“2I‚¤•”M'H Á[Ž&€tªÄD}§„£¶F–fpüð›Ð ã1î}×ë·Ã®N)³e†ïøm$AÐTUyl_»F‚é´_| s`Ü6J|,3ؽÄ+‘åY²u6$¼!-•‹U1‡éX;µ}.Wë„}·í£"ð¤úÖ¿™»xˆ3µRÚiAÙCTÊÒlm°ZdÞRŠr‡ciû.„Bj•¤l©2}µéX.›$‹1D 0ÚÁ«â‰Ùódá{V,šDÕÌÝâ'"_Ø·)L Z('"h*Ag–›³w)döÅ_üö·¿€óêæÐ¥ãµ}3Xš*Dß!_ÊhgâÇû.Bœ² ¥’;6ÛQà08U@¯=;{wÀ–,‘«É¹Ž‚Aª›D/FY¡ì5Ý»;s|¸ª–<~j‚¤jj)+%P“>ÄmƒID£Ê”ÂĹ·2ÌF5§ÀNïDp¶ ] {§ß)Ó´¯?þxµ¯èõç?ÿùÞÑ$ÆnwÞ®©a–µó·åªìÑühøel¡ùÕ–Ô‘”BÇ®?šr¦,«c%ªJÑd~MîµÎa:Z8–ºÏ曳i›ßT3%hÓ/.¥$°MvnÅ| ¸¾J´®_€`|æLx(»*]Xš"Nì¢?}´H"›lYj€x²Y²D,Ý¥ ZvøbÊ@…hbA}¥ti 10ÒäãQuW¶ŒŒÃ¤TÑik5â5ÂŒÓÖ¼˜ ɨbF¿Fš¶lãâI ÐBø RwKV³˜§Ö ¼FS± ¥ ^¹@•  oƒR)¹`¨^l©b’XMöêÙˇÓÑ^– pL¤%ЬûccÁqà]Âø–ÊùŽ ¹íáèÈ y–>¯ȯ…%&ÌãØˆ˜•ÒQЭ¦Kc@˜ÞOŸÍֱػ^÷¦RkËfWo¤ÓìñºFYö£-¨…(±ÌL^ A¸Ž<++Кݑz¥øKM3oZ)]¤TÕ±,~›j*ž¡)Tµi•×N¶a:pÌøb~8#Þ„e5Ezì 1é$ÒÌ©A1#7N„í¢›ÐÿêüîÄ4rª¾öYßmì³i´Kû ú.½Öfëd ZÕH†Ü[J )àïpp:¢†w*gµw†]÷vHDw±*šK‚–&_@ÁÌDâ#87Kø41»"Wѹ8¦uÚ¾Ûv¡àÞH~ÖH>éR`ÈRÜîÚrG¡»aÄñydZ½J¡±jÍV åy‡c®èd¦S_š:Š #àÓo³ ãml:ŽK 0¾¾bGá6p,>÷¿ðwýˆoý;–4u׎ץy([šÜRScXòv§ï@&C(hfñþðÿË'Ó†¿®7exÌ`°^„›GÊ^t4UeÙ„J\hZj¥ŠÃyKfÙ¶`Ë]1XUK¸1.ã€ñCª ˆWˆ`ÉVèôRkà²È‚:n×p"Ž%Á ]¶AñÚ…¿Å/ÿ¸óýÉ^êÒ0‚b£6\€fl3›ÜÀµT‡ ;dd:²]Y2Ž€…ÚùÓ³jáæQ¢\,Ð.¾SÁ?Å{Á¯é àÑnT¾ bó˜ßð (;ߎâw2)Dpnæ/$2ñtª ÔK‰XpW3å vï9“ÎYÀ¤îCBšd] bœÔðGÐnß·»X^z‰P¥îÑV.ËlgM×­ ëÒKG' „뛿º ÔÝ…6[c\O¯§j+Gîi »‹Ä¯r Ù&ÇD¨V_VÄq/)±ôoeø¡«Žßê˜/þ©ékÔôy…f…È–&›‡·€uáRJBÇ1^ ”ä¾¾¼Ö-5*[_žAXO–OJ,ÈkF_ÐlîIŸþ=ƒ6%ý- fp?‰ÔýGG)"],%kžÚi#q¶)ß„jñ#ûÛûÛßÞâ_;ÑÅáëkŒ.‡Ž–®ßä iª‚ oìÈ@rœœR|†ÃFp˜NÒ­•¦¤Ìf*í”wש%[ív³I”Ǭ5f„v¡D@Vð4Ùã^š¬ ÔòiN¿ådál´ZË2{´5¯ Al`^—Þ ¯ªmò¿úÕ¯îËá?0ðŒ79óFjrôIÃÒØ¼ לnxYqÙDÔ^[|z'•b)K14×1¾¸mºô®r'CVU)~…‚@‚Ê?ûì3^üºæ—42O9¿`ƒ…´ ž)`À:Y´î7Èh–ù‚˜¶LŸOg¾,ß ’íÀéŒF²F-ùžW3¦‹Û„‰Éæ»+à.Í{“{˜qHKH·‡ûÙ0– Ѻs  Š¥ǤópdÅÌb†Öز˜ó‘ù²u‘¥¦P@GV£Jz$!-u·)¦äk»$[•Xíh@±BVÌ3²¹¸’‚˜êøôÏ¢aô¼™[â^Ü|®AõvÒepĶ'†‹‘IÁµ¹ïáMÀïh𥴮ŽT“5¸¥T›±¬WKjÕ*dâ–²¶ô &b;IaZ4vYIÄ ¥)zY2ʪ*œ×z±ò8²¼,5磣îDâl`µf†@^œ¦ÎÎ%0‚¥vчìŽNjº“’Å„ óøÝˆð<5Uø•¤S‰¬%³LœöÈ™Îî§dI65ä¬åÀš&+^V­’‚!µhi#@j@ëÏX¼¾ó†™Â}Üwz>0ÒæirÞFxHÓZŠq ¿™› ^?·×ãVO­,/ ¹ƒªà”+¤lãÊÝ]ÍÕÊ®]R|„dk¤ÐÝ.¶AAL`·V»À‡,Ågºû_>ùŒ[£oõÇ?èëmRÊ©5¶¥F<‚KÜB'ß`ªdõm’D¤ѺCHLK:nÊ^yRS†0å²@4%Z¨š­v<ÃwþÅDjJªÀG¿fù­æŸfÚ?•H‡ -ºÉ©Aøtàú::w£îp¯ámÁÒœëÛ„8mD05ÿ^§‡ÈÏã¿b`HÝu´—¶æœíØ RN»;adÈFÀ´l× ÖF’K1[³w&Í2²NI 3ŽÓÓ—ß§’î: -›ÊÄÈt¥R†6vd†ÏšgDÒ—E†hND XáZ˦o#öåÕÉ„Ýða)„Þâe'ÒiñúùÂ[tÿ$ð£¬×“&ß¹‰Ø^:Ã&l6YºFî»hË6Õí¡³ ¢ ëpêåîRŽfwþ@¹ZÙdu0) Ï’}»1|3ðÎ_;Û\_ y ¶k`BȼmËR– Y!‡ç»í•tã@Öú(^š 1gµ³Œ`ªÎŽÉR®O肊1ˆ Á·DîžAP™‡³ZðÚᛟW.®;Ïp”Ää› în‰©¼‘RF@cÀ¦Mö4¾t¤@¹^›62œ×¥*Kœg"‘©dWK\ŠA¦`¹ŽÅpFß9𖵨ª!! cÉp:„óïš[Q±/-à¨p“yxО4 â¨CT5R™*Kž!78¾JY2šL“¼.k-ì kš—j*»£sD¯—L©4!–ÅÈÞ»ºXÚµ#’½f9cÐq³ª³£x½à3ˆªf;@:fˆÖQÄWŽÆ7’=fÉbª‚XäËRS.Vdh÷¸̓Œ‰Á~mǾ:µeIÇHw}üjÉÆ7ŒrKvïk§ö»#Ež5-~xÂ¥º¸zE+h>B]dö¡ß.¦ÿÖ^¼¡ÚÛHõÚð‚Æ³5©vÑ´ðRr 8Va÷g×WKR|aO®”Úݨ:•7RwT˜•D³4šyXFöÎg b©n©Y±D †ð>ú+ñû¯>æ¶/:5Ê\VOV·S­á‚g»hl©ÆhžëdÙ”e°;4—ÒNÛ8Ê :U1Ó¢¦I:Uˆ%k°˜ÉŠeÉííoú¾ü×ý}ôïk/tÀÒ¦LÂîìÈØíëlïñÝ”Q‘ ’ÕÂF,CìB@„ÿñüüóÏÚÔ+zóœ–×<uP^+-›Á.Äð¼¬-Ä¿ÞÝÌ xÏZU…K±ëlÎÛË$äqˆ›Í ÉœCç&HÝE€‰oâªê¸Q› ¹«Ã+©êç©M -f-–8Ío™D°ñG­ØÁÖ´­!Þ Y‰1á?£Š_×Üi~Áfc Œ§— km©{{)ÛeÍß•«2¿«Ö›o)†O*£PyR@U¼?™¬PÇ8‚²ÄÓÑN—OÞàïþ:¯~u×N÷†´5¶La;ZIøûK2Kí}šÝU…SŒ)°Dί)&3[AKD!¿’)V2p¯9jƒË—ˆÖm³çÑRÐ{º¸sdÇ’,‚彋µÀ“Eƒ÷R¶ùÑ2äR4›ÒvšYŒy÷–K!Ç*‡cò4C€ oɤ øÆ@`F%’κàHYò e+É'5„¾ãên¯ªòâ:¢YŠ™,{úß9) zãÉéÍ[zÝì¤T&q•ŸË/à»6Å–|c-™ M½,zŒlµígäRá›­MŠ¿JÏ5H°*^ëJ±)åµJ°WµL#Ëv:Yâ¶Öîx8få- £‹X—‰«Bã›.ÀaðfK™g™ì†4OËö…°^Ê£%‹¿›»ç¬î̓¡Y¬J9kŒd¯yŸÄÆ H!+¿oJ¿SëÔdJ:%“ãˆïó£¾ÍW¾ZAßÊx)ÿ>ôÛˆ/ÌXßôëÞ–Ô^L(æ¥Úfb;8p±í‹!1-‹‘m¼ÚgÒ9¤PÌ'…ɤŒ! # Òyâ8vlj/«–m*µâDp,Ý–8Ô˜»%ŽZ¯ÑÔÐà.}w‹%²ñë"/ùç}âó4ý’‰¯™íW#äé Ìß=fH ¾e¯g3dø¶ÓÇ ¯éwM Œ)¨…ŸÇ,V+…qÎÀp %TøDâøÕïT \S|È)ôE)³åz tLYe38ŸÎD ÈgpMB$0ß±ÄáYÃG+¦ÍÏ!Ÿ~ú©Ôk™ví¥}YR6ª©¼¾án)ˆeÈ6(€7ÏÀ!ïÏ)Åž©Õ—²a”” t†±}3ˆ¯þçqpùXjª&¹_j¦š—-ÆoòŽwóßSµ(U…ª¬”ÁÊZÍÒ³c¤n“ëuÕ=ÝôûÍ„È5} ï‰ ïmÉKŒ^`m¹ÖviTÜçi/²8LÖ®-‚øÎïšV…©U8¯VÖ’­\PlÚF´ÑH5€@J;½tÁT„ØZ{á‘›ÓÝEIJ‡÷ê’‘Bö—¿ÓG‚ýr‹¾ÌD´c–uרñÆÐ ؾâD7a-Y–•Hiljyvìhƒý!€¾² ™GÖÝfÐÊ›,»èÇÁ;µ%ž5*òÂ_¤q§ù¡È™ ÖBÜüº L[ YKfÙŽ†w´Œ¦J@”õ°»·•ã«]¯/Ž¿–íÿà{:½†9sgÒ¼á©êµ[×ÒíÑ,Åh|¦¤Z"! ,K…«ÌgpdæL0yÒKÐå6!¦{ôÇ…f WÎw¼ ç(^7?<äÞWª, .K³ç#Ô1P tVŠB,7LR&é^ʦ¼`bÚZ·qYÛqWùn±ÔËyos~kп^ÕxM®W'¯;ÄfÛm×TÒ1¶YˆFÚm¶ßÞy±¬ªÎ‡Î[üÃÿ~Â÷°×W }MÛ¦Ú 9YãÁKYvy„û’ˆåªÄ…âwf©ñ-O³ëÖ­…TÙRÕv ¤œ,>üœøõ¶¼WA®ÁÏó%È7.`W¡|H ÏÚ²!õÂ4ŒîÝBý\¾j•6ƒ%¿¬ϲZYL±@bÙ„ ™æ}†z…¤¯ÓYVJ!A ‹1êÎS#’f´¥&~—-Æ”R+ RL?5lx›õ4AdTuþ.6äËõÉRÐÁ+®SB ¯„®§ZJLM o)K¿¥rU˜ © ßü”+GP%¦Ïâ[²)xiÃqÂz IÇT¬O9 @Í“€f41q ’…d–™*ˆ4äŽEl[H‰M¾g ²ŽU=\:–f ŒÁ ´=ÿ5›ßIõ¹_pÇ_=v•}'íC3Uؼm6¡Qõ…0ÛÛB`K"…\*Ã:C¾eÇ"/¨²#" øfCfȼ,q3[^Üÿå”À…†lk†4­Så‰D“‰Äé)—ê7ÛËÿõúMCÍW_ŽW/jm‡Û^´–bÍ`¶í:¦e²ª€÷@j4 í ÞZ³Ú™'5%„º ‰# )«Zš1¥BŒí£Ã ÿ$j>øôï¨"H*Ù”ÃÅ-6Iï.&hì^ØÅø@È6K<%–òØòÊÛµOo>D¾Ö£§¯“iŒµ6Ð’‰wÉĘÎaG!_|§•Í×È5µœHU¼F@MwÑ ™,ЉuŒ½”A˜Ùj´ivò@)F¤Ör"8b3œš‡a>£££å3fKžH£V¥—’™Ð¦ 6訑&ýjeýU×u|­Àѹ±žfãåÝTµ6¿sšª‰™ìư”b@±[´K °«E.[-ßöem\m{D¨’f)°t\Làî6ÀkÄî¯Q3,@ËÆÓ®‡(60Û ÷ˆS•[h_@²–rå²ñ[ŠÝ˜ ïúkP §mY*q…pÙÆhq˦_‰¤¾}ܲ«KMÃï©ú†Ä¡ß’ YKÛa‘£Yƒ¯¯y熃¼F‚âp©²j tÛ`ââJRfR˜½2ÎçKPý|kåmCÞXâ ²ÀÈ]xBð6pQΕ(唲$b²g3©ÕHªUvo¡H“Oa4µÌ<@œôÑzeiÙ3f8_ ÄWXPöh]Ÿ~̃€†_9¦À‹—ÖfF®9e{D`p`8¾Ú–ªšÈ" ³ ¶4I³ñŒ2}ÊJ,ù/.âdÑ‘k¡BØ­OÒÖ¦–&ÒÉ&’>N´n]ˆ³áÝTZÍ•ˆÄš²¬^>ñûÜχ¼…™Ä‡~¿â›×úšßHpÖŽÎg×m§Ë ÐàM…,° 41)…<T·Èµ…ªœå@üZXâ'ÕÕ éyAŠ xÙL̈ӤÀ,¥xÓöÁN6¤©p4%hxYW ¨âÇH_lC¾Óñ‡*ýS?ui³ºÔšT}kd O^¬P•£]@6ƒÜ­ýæ+Ái_ éh‰”rÌ8‘m¼¦øÃÑTñ•ó✪îêÍöÀC~Ûž,Ó7YjJ,Ö«5• m…Óv»ˆ¶©¤C×1ÍjyUýûúßÖ*IP¬)ÔÚ$Τóá-ÍPU[CÞ…Se¼û–‡ …Ï«’µ$h×>ÑâØ‘ÛX ÑA/±CfÁùZ n)àʼn{yùß¡t,_~ùe¯  Å.eÝÉJ1l{ß&æ÷ñúI­Ë§v1ÍLÊÆ¥ðú¥¿€>œGÓB¹”ŸR\šøxöÿ<ª][ãõÒb¯¨Ý–Z‡Ø$Ì2¤]ç!R›_Œ/%à»”ãèD†ò6ý.î]8ìtZ®J Ÿ¥ŸhÙxµP•‘m€ Þxí!‹˜ŽS’ÒÑÛ¤FýÓæÑ(‚0ƒòÄM޲ɣ ·4°î—ðÓëŒI˜*ÙI„óø6Ò¡5öâ¬o"•ÇiÈÆèw-Ô6'qƒˆŠÊžéOYÕå±z÷_µR•C-›·>D€ƒÙ¾u·£v*ËÐØÔÅ•#,É£©­{XPV iÈyû×»ƒ¨¬ Š;2l/:ˈD)…‚m ŽäÍŠa”!:f¤Xµ]ÈFÄ1(…Dxˆ”à˜|ˆÔCìÜF,}²ðbà#ƒT/1=–WÝSm¬ª<sÊ2 Ÿœ¸˜×yä˜f®WøùYãå»6¥’kM¿¾–4íT@Ÿw><“2[Ç’—%׎²9Å›DP d -'Ø ª4„Sv)+ ±kÁ5×q>÷ûkg?ðƒÅ™ø›Í¾|út >úcé~¿VgÎ{l‰™ 'efKþlìzbÅh4?D`ãNn×ȪÎt¥”(T…àJQ|å §IÉÑ)×&²4ûu¾8 &$A¸€ÁŤ˜›Íâ×±>þøãfÖååæû?ûª­]-o_ŽË²© ,ý˜Aæã*ŒI!)Ë,“mI "F€ÛW…B¨áXöÈ„HÕYP ̪šÇFnfÁKÌoù¡H¯pÈZ6˜%YfI­¸aôM¸À$–Ry¸BKÖ~Û¸e‚–8m$^mwšìÄwÅu÷ë[þ÷ÀÝ¢«zyàéë»ÏfhB²nQ‡ #ÓÚ^@€ã›+ÙÉšY•x[‹i ïHÑFˆÌOS°XmUÊS0C‘E1Ùº+ć³D,³– #¾O‹`ÉS«c:ü Á±ðÛΘIu8À.²Zc4g:æÔÈ”°šZ*‘bÈ~°ÿ®¦·Q?øÍ±ôÍÌî'Ó½g#™„Ùˆùñ]ñ^•˜sovJàÚ¡‘²<Ó_ï†D,1-I©Â!ŽLDàIK5­,\Œ¯vï•~€÷ß¿iöFRS}df£2Ãti úáS Ž\U;êy©á !,<ÙZe'hI“©BK*„O³%‚ Z¾Nd†Ó^ è'•Î¥q%âJJ‰ †Ä©DVE([k…p {@Ö®UIAàLÜ´‹C0q:)úÊÕv5O-ƒGS²àY—R•Ô=Bü.J ²RµXð,‘ÀuŒß’ß„w~Yˆ`"‚úNpˆÇ*òÙüuÈçwH«‡$a)¶7®l¯ËÈÉyz‘¦¥ka¨ò” ÅoĦG Ï”w C” 0%'~wŒ@#²öÎÑ!¨JŠBóH7ªeYÊÕ®ª 6Œ]§Ã3L%<³¼|zµµÔN\`)è•ÍœÎP€PSú¬8)UJtìåO ®Ð<¼x‡¬ÐÁêÈ‘~pZòøMØ |A»h™¬8°Ô]9MxRY©æT¨*}KˆÀT‘ûý~¾^oá às¿ß9öún æI¡É_è п{¨‘’:®ÖÒ<=•Úµ…Ý-hæacT¾Q—M“¯¼’.´¦ÔjÞ~ÕHuD"R–^«úÒ²)Ö ‚ «m Ép¢ÉBšv©‚Ia¶ ˆÑνͫr@–N4 Îp4 QHr†¸½sôÑGüšÎWÝßœÝií×ÒHyÃÛuApóóŠþÐkŽc‡Pª¤QmGÐÞwYäju³í“"«/QÈ4õ¥îÛ¨ïñçœ óï—èèëh6Þ¨ƒiUu>R~ð0¡‘xËÆk×h ×h™Hx·¸å Â)(IP`×h|ó@pøkwGÄiòNÁõF™šøN¸’Ç%^ÊÆ»Ž.÷Œ3Ùí‚8„OØüâb¶’ƒ$XU:•ó²î “À[&Õ-d°^…,ÓçcêÒvÖ±Fõ’r˜@ÖH•XÖ()΀øu!Ò T"…#KvË,Y ñySc†CWŸ‡WûDÖª 6ÞŠãåÌ­étðwuB "åìê­‡€µ Ïy"]ð5•²ÔÚ+˜áDhÄQNüêóîaÀOG¶ÚéËâßxõíÄ‘{…`Jé.¥Ü$½HI…óp´&´¬ ‡ïpÍ\‰€Eƒ`"ŒLßl (‹IÙRëÎ ‚£ÊH@…@XžÊëOÂÑ€<©¶_#1‘f¦£ Èë Ac ”KñÅð‚f+‹TkÙ–ÓÔBìCcúŠÅ÷ý¾®òꦑßðñu£/Y××ëôx{qZ#Ã-Üçé("À©1Ûd^Ê!t:‡AGWMm„8+×®«œHÅØf#ÒT  VM G,U¶ MÇN'AHW­ÂÅ–æÄPÞvx/ôÏ0ßÉh~ùå—}㛲—‹íˆT±“í¢Ôh*±BY±t˜!Rp±” ‘vaÔpA§Ì€<ÓQ+„àX¦€ÃzÖM¥ yv_*ô›Ó¾/\öÃî~+Úý©‘gA¯vÚ @™Ñ”5€/†d–ðŽ h›LÓ@ÂK±TS‘bŤ<ÁRg‚ÇK‡@m1š—#?½|úÿϺø2˜¯{RbØ{gN¿ éîYÜUÙ=#(_J\V DŒÿþ¥,Û$m"X‰˜u𲦭 Ü’­‘ ²gxËù8Ïü³¬%Y-®žB,7‰@*ZRe¤ ³B3A|Þ²¨µôTú¥5 å+Z÷yÃkÑÉÐo#X“à8O©Ù—5!ë¨eÛ‘Öåcc+‘%‹@-LµRb–>MÔåUÁSЙ¹ñ<Ñoq ~Ê$ú·}55¼å&ñéØHRbY3[´“!ìÚây‘,F`íZ€¦)ßfy µøûQ\zï^î,eqf‘Ó ÄÔâ^aÆÐ¡Ž+¯–w]lV¶9ñKÕÞ’”ÀÞí®Šée‰Ãjw×QÕ™Dvh-nZ…Rn$âb#¥¤¿K VËãŠyäfd RéÄW[9O*~"™¬y œô£Ur÷+гtÄæßx@MyÌÆ@ø/÷ŸONÞ™<‡ŸŒ‘º)$< ª!A±;¯ÇoW…\“Õß’¾m½ËvÙxˆÂj»3€íGJT"1A¶„@Ÿa2÷YïýÆØ¨&'.5Yü>y+×Ý!qËivÊ<„?mcC´#¨J­XÇA¦Š!Ûf“S€GèP-‘S¬‹ÔŒ š¥M¹­ÑÈ¢ñ@­[ ,)£QPRw>NžU’T"ØÞ-©ñmG@Áñº£|…̺©ÐÞÂ|ßïC¿ø.n £ !îrC¶;“UXÜ6½=àt4›Ù 3„kÁwtaRÀtxí€j-iÖ"fš*¡•Ò:«G6>ÄÒåFbHœ¦4@%‘Óçž¡¯÷FøòßiQ>s_}õ•'BÇfÑØ ·ÜÜÕÊv2¥xåÎÐ TÅ\ ­*›bµ`îZ D«š€!ãìãfU˜pf)ÛD&˜>ÜOGjé[}¿ EA­yœÏ5Â9‚Êׂ2ÛR §¥³µt jHµ¼,$ZK4ŠWî0»‡Ý·R™ÂÊó@A1…»Ž”Ÿ^|—ïWÆá/1ûôϧIÐ0š\kGÑäRh–ÞtÀp¾Z…! C2A…Ƴ/Ë]Èâ×åÞG6ŽG|•>½ŽYT"¨¯ÓëSÂ[#ú,>K_­Ž+‘eZD€/EJ,Å»^ý¦Ö˜Z3ZÙûîÜJ:U÷O/>‚ôñ+¬ÖŸù:òºæ·þºæiÎm§F–† t­a›/m­—VÞiðIu™ªíjŠ¥x"² Þ9ðZPn¹g H¿‰£\Öü[ü>ª›»¦ôõÒší 8†—2•hN4Håb8sq’’R…¯… °Ââ¶,V¹½Cè@Xc€øwK„/ rÏŠë^–²WÅiZ*!…®—åÆFÃi¾½4ªñ˜,VÇ-ɧÖiêˆén:FcX ^“y‚Ý“îº2²˜µX2×È»¾-5d²)DÖWyšÑîLY‚˜¡!®s›ˆ NG(®V hS|HUiò×Vþû¿¼Ðtx ¨GB1„ºÓám,B)̲»G!â+á-õg‡gw³©ê:­5>ÃÏcRӥѓsØ×%¡ (K³X•ãÀ”¥ÓåXbJñ˜ö»«X£JÖBrˆ˜ˆY9+¸sBpX8š]7‚¸›Ï$RÌr¹JO-fg.ì½}ZÂ-ӟרë_\ Ô̆ŒÆ ˆá{ bòw}´ªeùó}¿ßóy‹ÿ¹L‡À{Ãð¹ß¯ú˜ÇRwôMcg–æïjÚi` í´½C,m¤ÔÀå‹ewѪ4šxgѧÀi—J_ÇaJ"@ŠY-ŸáÈqò”é´U@–²@-ÃËÂ+·de!pŸ |Â3m©ïäýæEté6pQ:ð¾Û[GíXcàØ¤ËçT¥ ð]5:»åÚwb-Cì‚Z{ì@Ę ãf0¡%5dóجT"!‰£¥_U_ü#¼ðp|ð÷h‰ØNƒ™Š”xc'¥]Û,›G2ó·4)%ÊÃ2„‡0)4^_Kä‹ò” i_R>'y”Åñë•„÷kuþNˆäo2|L?ö˜!q <³ ârØSìê[vd)Óš§X öÊ<ÝäbžˆZq%’%«¶¦ú €-ÛZ‚<0¼ Ÿlú‘#¤S¡¸.U}“G«Å3gR•û@ÜéUâæMy»k‡”­Ehò8ÆKMªÃôõÿ7Íù½ñ~ùGÓ&ä“Ò”Ù,èÄ\kóØÜ·îÞP"‚Ææe{w›ŽNß¾( ÊÒg]µMÇ©*ޏ»îå?Ù&õïõÐ;fƒ ì—7›™™ØÖ²“1Uü–÷¢TV­8œšZqÙ"iã8iLÞ2ÂÈWÝqÍ>¾ $N´K زâ†ØÈÿÐv/K’%E†3À‚ ­áù^¹…¦X#lGd>?„Ö!‹¦+«¢lam®¦¦fîçÄ%£"³{Ôòfp‚I5•i¶Óœ8 ãÀYúÈ]qK1²@mK)1ŸH—Þ½‡Ãw+ºÍ.Õ3a –Ô:4AcËvùp6ƒ»—,œÁ 6<Ð’ >/[Àß­¾vÓjÇ¢g+LVmUÃȕ㉇D ÐÈžûçt7+¯†9i<Væ'¤žô;¦Deh@%„¨»NãñˆD7eg¡šJ@K³mŒR !õ’e©MP6©¦µ´&DÖ1>¼eóÓ2$Ä’­—ò–ü¸6›Ç²©bŠkdlHÛ)Ua§QÜ0J€Ž:¾«Ø­élÍV6…– y¸3ÔEŠf#MK>üñqâÏSc jÚcÆr%ÁÛ©_,ó‘¿Àò[˜=ú0Ò‹Mw¦u¼£Ží®Öí bòMkòöXÉÎ$òöeB G»tœoÉ\š˜ZÀ_œïÐzvPÕ¥tCV•ˆXa3ów0š=ÓL_vç nRbÛu…y Mh‰c¾Ž^¿ìƒåÞðùð¯-Ô”lÖ²,š*‚‰fx·–íDð4d笼«Â‡D+X9>¯$¾à‚ÒT]Y½ Dœsgb)h†šRöÁÿçÿúŠø÷ÂZ¡ßj `c7ýZËêκëzÄ•EcSH¶ ¥0Ó )æ(`Äí·]Û©.õM$NUÛùþûï=ƃ7©áRŒŽ3µ¥Ú`KÞ`)A·´¾¬céðͰ ÉªŠ©•E`–õ ´ŠÏ4×<-!DfòÙ¶†`åyN³á¤\Îp\êî׋Þ`@IDAT:0‘º¯$0A›$C𦄷T^Ugh©Pª— 14ˆ‹kÙi!–¿Gº¿Oøõ±×ÝkGMÇ»Ï 6p½ÚÄœÝxJ<+ÂÝtÆ7³«Öä‚NHM éLâ´TÞ$‘Å! @§—ì·8o™ˆÛF»¦j3yÃØZS‰YÞH-Û²ÍâÈfȲ@qÇ¢¤-›BJa“{Ä}ñÏù©ýGïÍ®.Ý´Æ`Mn¼&·dp嘬`K42|[«ÄÀ="pÔJYVh;@„•#ˆÛ¦€fçPIL„8F yåúÒÿÞ[‹ú6[·±y¯I¶#ËÌ^âT•‚£ÛRŒÙ™Ø£s8²Jíñ’¸’ÎY€ríÆÎâX–ÝrA̺bd¾bA— rqxˆsÀa–•‡ã CÚ©2r´-×ßcgK瀉æ|ê.¦(Æt¤ªÄ]©ºCŠŒ/;µ¼FžNéèR£ª” 8ÙÄ•tÕb¦Ù~×ZaYUÊyKA‚¥ÂyKÖ<©zQfbÌ0+´ëóŠÛIÑÍ.©Ç+ õð®gá9…ÙªÄ !õÐz”§f¦õ2²Ñ zÍ|dÅM, ¼.Ãe³ªˆTeÙ„² ; YK):SòX’J?Âü: œ¯vœ-ËF[6¸mbjÄ34 ,Ämd ˆgC) «ÃW•B8¤€wVRdRlYŠ&¾k—,ýºã MTÊ©Åöìã0ø,Ð÷"¾øí#Ùÿn&÷þÒ[_K3¼Ž>jf{dMB¤Ónª&t5Û P–&hk"–C6Ý-q\Þµ°S¸8ýÉ&\@°§fd4'l~ ]_jkTIc ,PX  &„Y†ÈÂ!¶Ü^ÚµvÉ*Á‘ªÍOûR þHœ}¾§éÝÿÌÝ jÝ$b¦Qs¶}© _ åfhÎÈj÷4ª'Å«½TÏÌ ”–tž™—‚¦QœÜ&.Àä{JÁãû­wý½·«¡Æˆ2Ùò†ix“D«i`µ|VËgðöÞ™P¨EK­8MË68\ w#ßá‹éäÍ™Pí±¼3 îÒkÚ<ùš¸‹ÛãWm—Y¬‹%¾eÖ¦Ôv–]]Ü0ªe!Ò,"(e)ÈUYV duŒ/Å€¤ø5ÀU1Y…-á,œ¿4‰#('…mM ®ïµ¡ÿó‘œ „SkÙÌtñÊšA,°¼oÜ’©òsl¼Ðû’›çg­ijÑõ²´/Þ0m§!qš“U%U€ D¸_M%pjeÍŸxÙdÓ1ƒ 8_ÓRœéû-Ä3@7yCê%¸¶ûñ­¿1ÚNœûTø BsÆÄI$Ü’!ðDâðo–JdÕ:½nì y%‚&yWÅGX0rA“¼-ñ6v}ÿ£Î§3˜3²[!„ì–‚‹u†ì•z©v×ýÐ$˜QU|Riê(ÛsQ„f¨„Ž”¸‡d%¥ö¶$PmRízÓ– Th)&‹°Fánβð&§‰Ì¾ve“º¸‹[v…ªŠu9ÇjímAZòrµñÌ»iª$-•5\9DAèе(‡t H)AKgKd`O÷ÈÔÐÓ@MyÝ^»ª´t¸bWˆ+‹ ”…Pcb©mJ Å·£)ã0˘¼eœùM[—j§£‘ØŠ–kÉËÂmÓ„k ÚvT-¹*äKìŒgþªpœ›—©ú©Úñ©S€ȦÖùA‹à¯ x÷O9Â˽wòLêw|d }ͯ]Ý›vâ âlß#RÀhvÝ!é“‚´DhÁŠ+ Dƒ“Õ¨SŠC!Kªñ ‰›ß,Xº7øª¤˜G5©vº3A€ÓÑwUÊ=c¿ü“·ß7†µnB±ŒÁ¯x±Ä”²Y1œ”Ò9䥺–øíWL_J HY`¾Išr“X2U<Ü s†¼Ð쿇\­?ƒÕË ÍYw; Áf^Œ¦$¦r»f†©‘$qª:ÉØÞëÕÒÍSId1‹P|÷d¥–]‰`4Ù&oÚÔ*4ªeÃŒ_-ƒÐÊÖèô»½8N¡.RC”ǤV¯8GâÌAy”™Mj¸€©Ò]Šát¤Ýc‘yKR²hîÏæïF…ÓÑZª ê{u8β>>Ï,+k¡—eœöR…ŽˆižBË&lˆQÛEL£™g H`jDþד‚‚r=³`¬ÑÚ ŒX'~õm˜º€W[J°±¤:8) X soVµô¥´NÊHÉVW sÛ#2}H}áâI±ÆèêæµsRÈåÑË2„“2 ÅóÃ̓в@Ìè´ß–fèXÖ:Ív ìÌ ®i"ñ €• ÈѺ¾Î|4©1óšNVVœ‚#2†¯úøÔ_@äå¦÷ý>Ur-Ú£î@º+€ÓƒGJ9C¸e`œ»œM¤òÄÕZ¦ƒdýñƒIj-([£!d!Ì ã¸¦R›Ð§‘ ¤êÅwÓÆ´”åµöCåF•`ʦ »rK4qx2L§ ÷ÿÙßæl¶ÿèý,Ýßx!E¬ŽzÀ²‘ à–R&œ5?Ry…–Žˆ—‚wâ–•«Í,R-k!Þùô}Àá(¤zɨr>‚Ž4AGä Wò9¦Ü»ÿþ¢Hš Ó¦B¦ii³<£°Óë"Ƽ«A¢ñ©íÜ–ª*ÙöI¿1,0„2c€ªxK©!ÅpȆ'ž2œU“g²öÒÃ!$޼¾ºgà8R» YgÒä²0áv‹Í£ª‘ò-ñ-eÕÚÏFÀ’¢/æ#G(V‹ÃVaøLÙ$Ê'Œ pw)7Iúpëõ\í&D_‰^¼,ýšZJyŠßßR þ-þν_uÕÝMÅk×Ù to¼Ž¨,~KU ŽÀ=ßôp°w ÈLÄGÀ´´xçЦ)†c Ð:“˜–8f°ä5ý_þñÝ?N£6¾t×´‹y6šƒ1&è;´@|x§ŽVLÊòR}Ü~p§”clïáÈáÀµ†òzÅlŒ8|Aåý¸‰ºRÍ&5~AˆóTÞí1ðþÀôyä IM;¾«·ôPâÅÛE|4â,œ];qžr¸s³îOd-¦€P_8>M9PU:@A>ñ¦ ì¨Q‹› -Pœ•5‰åæÄÑ”gÚ1AüÅ ÚNøã½BÓ{\y¥ôسTÙ%ÔCÌÇ!$®¥m´“8@Yº˜C,k&è6EcŽ»3Å©ˆ£oSеNY–…h†ÄÜ󔕔´#qúz‰‰+gŒr¸Ÿ!ФŸ2Ùq^ÀÞÐ)ÀiŽ/`¥² Âk§*ÜR€ffWt3¤©ª¦•@XÇ«„ÉZ’E à²º¸ÛT š#RˆÌ’jæfQ¥ÜKÈfLç¿›ÞúûJ‰÷—Í_Ü<[šbZ%íרhöȶ )l/!Å<£à„‰ YÖ¨$)`- £Õ%ñËÑç0æ tÕ€;Uqï"b¦…’ôÙ6ë! ÍØh-qŠ+4?B[“Âw‰Õj ôKœ>új˜Æ{—w ýå/¡Ó±Tk V÷3ñuók±ítÃ#ãÈ™±P·M%B÷°¥rL)>ZíÄ„3KfÉG \GUÀÆÆ¯é¥Ð¦ú¬”­Ï3w¬wBNX—4y:Œ2:6ƒeà’0Cct2ÍÐùhdÚ†‡Í`ãv¤¤cDƒT«P $¦e| ö%fb!fK1²B9Ü¹ÃøÝ_øÅz™ó×)|ªQ_½jÐåxã4ü}%í·’Žh»2g¨ÐG!¾,ðSñ—S‰¥s+äÖb UÉ2 qH|ÁÚ;Yœò¤ ªMPÌìÔ™WeY#±’XÎTAÐîÌ@xÏ”ó mÙ!ìÆ°,Ö´'j@ÏÀ<ƒð®>çGëÎm'Ÿ²Ž¬-`&¨JPª!KŠÏpϧ5ÄÈÍ€“E¨Ü$ui†”«’(Áì~° á—ÈÖ¢r 9Ï[k§c­ ¨M¨‡ 25kú\ïB#P0*f§9PŒ—P`À‰[¦ãǸ• 0Ë!%<¾@¶åa>kwÎ bôÆ þeÖ;]µšò.A{´ÔR÷@w`SE“ÝY â„ 8†ÃH•åʼnÈÚÄR»Î™‚xjK¾”ÂHV-‹&À‘µdbÎñ!Ÿãý›•ï@7¾éPn š‰îq ±ã·w^U  #~Ù³‡kð$Bä SӪǴ¤I§ÓÓ]”‚Ïã'ȳtøf†D€´ýü5àÇ'ÀšæTéÅ;|Yc¤Æ°úò é®ÓQˆ,n)fðRg Ogß² Ö´^eãKò³ ÷8ÂgkM°ý²”*Hµ²¦b²JxqÐz°¼I5d‚¥¦)ñiwú/ô}×…8M>{£l¶ámylMF¿¸ýŠNÇh“Åæá‘ã¨MÐRÞ%Ð]à@BT)I ¿ÚüÀkÇ£«¥Há×}3¼a@ÜFx…@oý¿Å·$ͼsêoûh”…7›š!o6‚“1m¯rÛÿÓ@a`LžDw§t5<»†Ü™âø “Úðv†ÀJë…/Ë»ŽŒ¾e“ 0ánN7*Bœúò,2¦,IA ¶l4¾@S)wøwß}§ ÿËÌÅò½ÿn'º,Û©^Lìêh'æÅNÃi_uç©À²q]ˆv¤„`cã[â0ºš¬Ö ΖÀ7SQNÞ=4*‰_‰Ÿr}韠ågš¯@ôÔl†Ù™$ÒFȶ;ÙqŠg cò¤" _I´8<$?mVU-L« !±Ã± L!205—²qç‰Ì¢1„ h‰¶ó¿òg<„n8–Ä)Ô-Aø‚²î@‹ˆÖ´–];š8DÖA̳pü”!KQ2ˆ¸òÅe7^à§~% ”84Ë”´…Žh‚5]U›’tbkª„EØx§àz³Ëù’Àw]ü?L´Ӛ¬x^Ç-›‡?ì‹S¶Â²ŽE­s`[æYÊ8»ââ;©mðêðxžÆN‡¦òÇ¿š¼ÀyØ—ÚцIݨ†¹ïËÒ=¬0Ñ ©ÞÀ–ͯŠuç´‘Åp…ª”Ì €éïñØ0È)¬¯1H%Ž®èéY9ƒ3´ú¦f÷lUŒ™OG,+¾_ KcOMª^j–‰O .Ž/˜…=Fz¹é ÁØ ) øÂ…W"…u¸Úû2Y]êÎC,•ãw8‚…e‰ôE (.Ù^jgy¿8 9¾añ•ÉLÞ.€)63ZçLAÌ\ß y´7„ÄÉð SCˆÜÂÑpdÅ@µiÖ+™¥c‰Y–æ I‰=Äø4+Ô%²î‰´Y©ö++ˆÖvd“ýýïÿ•¿ëæÝ¿º›Íü™.dYÀ—j  l¼vÔÀ¼[B &ZF6&\9oÉËv{1ÜTRqvë‹öæ¢ßÅ£áøé]¿Aä‡~ð,Ñ`ÍiðÝbƒ6˜F‚ Þµ£± ðÎK±ªdí·#BîÄ0¢·ÿH!+OÄR‰,7Æhdc&»™ï%È–+°é“µ¬œgDP;4ˆG.äáÌá3gÈã#HE3§WÓ3µâÈ÷“O޼v:FVL ‚›§)xñO‘‘ÔÆÓ4°ZmOß2_Ç$žát\Å–Z£)_­˜ ‚€é›ò½¶”’hR‚†)F(…Ã4å“%xa‡Œ¥½#4†B#!x*²Ü0Àžx± µ†²ÚmHKY8¤ñTÅBàÍ\S„ãÕ"œJd#ð8öñÐU1„ âØ,YVœ`趇S“RηDðªŽÐ,géT4•À iâDƒ¼)´Ä‘­i WV·ìUxr*yƒòÍÑïóÙ>$Ñ´xLÖXÂ6ÑÄ=pˆkŠ@d£ÃÛ6|óT{tŸ×’5aåËá8D•€ZÁb´® ²¸Ë¯Ñ]‘ž”¦ ”*ÊZHá(q;v  }q;jZ´&Ürà–Z ÙQ“ G« Ûä‰[®Kx`S‰>w" Q¿óÚž¸!ìPÀš’+D` !HŠG¶å|Aü˜Ñ¤Ñ¤6è€f™¾ø¾lRà "󬦂ÔÀ˜ö'®¯w-v} ž 41o¼d`ÜT–õí Úo³‘UΔh„Ù%„ˆ‰ðh¬¥ ^%¬Fø‚dÅdSã£U˜Nq4SQö6Ñ/>Úfäz“ì_ŠÉ¶£ÂÁ b)q‡iÙN‹[B„ Ú&³#1ß»L@ÊmÍÁ2"˜©­{UžŒpài.Hay„µF;s•j€ÍÓØ–FÚ$È XVJ•¯³ý/p{›î“­æ!Þzi]<§¸XSÁp‡ßl-•y Ó°YAä®H÷gÝO³ƒ8@;ôr"9Zs×(q±€ùdô½Ž:¿þõ¯!nRz±v$0•+t5*Ž (…9D|·$È;jU1 îm9NžÅ¼ RÕFg¼S¢ÂV#„Tt‰µ3*²Ù 8‘5•or+Ž&`ªøîå6‹ï-›*pí®Š#XAÖ@åøÐGJyÖx@žæäÉ}ÜóhìN³åhZO¡aÔv– ¦p¦iøËâZ‹¬¶“é@4•u ƒVí–éxÀ/~•÷„Ð_þIШ} Ð9Xn˜&ÞaZ¶wËãÝØ !R¬ñ@ž~¤\VU‚n³˜)ÔN÷ÎÁùÈb&"ës®—ˆ×8ÒFº.Ú0µ6’¥+(ÕÀqd™iY‡‚Ü®h©Eûºó‹‰ 9âh|AqÊO_ð©ÈR‚ì^¨#úfÛ _–¢Å±´ÞxÍ#€(Ù$jQÐ ± I­%Ù˜–&{O!ЇÓ)›oTL· ¯0PÕ¤êØ’g 6[3tàl1‡Q†Ø¬¬¸;¡TÙ˜R§Ç͈/ÕÇ»&Hf#på–‰ˆ $… †ç-»(uÀdë"çÆjó%"™û~".¤•tÍø©§ëJ à‡bˆ*qAµ!dª˜ ôc)%|›êJå YCòªB–J,µ°4³r%ÍdÅ)èRm ¼"-•ó£Ñô„µSm_e À;¢â‰X¦Ó„|{tÇ—’…ø6ä7úúúåȾ©‹^šÚfÞ䀥lçÖäæÌ"¬ÄÒÞAIÛ‡wdeLÌ£%¸Ó†ˆ¥øÙøÈ—ŸljøÚÕBÇ•ËÛE³ HYJ)é¢XJ¹^@·v¤;0rúµHJ3¤Ñx)ÌqM¿þ“??øæÏNF—º·ÙšBXóóÌ!Á4R¨‰ƒà;à¥÷ЬÜ^»ÓàjQ¹á 0ä÷™Å)ËÁï@¼û×…ÚñiÔPª8ŽØlb«ë²,Zó+ïR¸ût‹_[ñ Û’çDoÿ»TÃTž¡¶\ <„gpúìNØæJ"ófãe1»L¥ÜÉÀÇE¯³{@ìq!ë©o4…‚¦B`–” ÕÃJ ï0'}Lf‰)ÄTE¤e>)±™‰ÓìZŠyLFX¡e´Æ®P iG8)W’0ÁÈ|­W{NH®J\/7yU¯òNؿ庈†ß-ÝŽÚ‚Fµ®ãÎdKYC†;%U¾ËÑó!‚-f&ND¶.ÎA•˼ãÂl†‚ʽ û½㫎ÿÅ;_mÕâ Gëv'5s§$Þq•ŠÙÀeÃíËR,erUe-Y‡ iK©@ë(àÎî2)­%PÜRJIüÙªt ×]£n¹nÂúvKàXæ‘éäÝ™–‚ÈÀLIB&^Ð¥ D v!f•DZđê]œÓ«ïîœø)¤¦èÄ\P¦¸”%gm¸røŽ1›êˆÁRàjvņIÊ´–ÍÜüÈ àÅÈ‚5²D3a !Àɦْ¯ ….bˆåh‚óFY‚·ýȉUÝÄb)œR´ià m¸f¬ZRbLÙ‚I©òD¬P´Û}1”& ¡ØRÑH‰hd)nIm—rF|ÞŽZà#¨UÅì”Z—‡wtñÒ¯£˜©e4r)›’òÕí£¢YW¢Å¥ñxYmóD Ü‘ jz¢Y6PÌ€ ¨$&¿ úàÿ׿þu1ð…æªùf3@ EÔËyqG-FvK)©Ü-ß ÊÛµBûmﺠ‘mYk Í`1¼5Ç"Å®Váź0¸.zá#WÎ7v³Y¢%ˆl‰™Ç)†;®d‘wKÈeká¨J‹”-Å<Ã!XÊÒ¿q¿÷ƒmšoÌS§è§ÖÍŸ¾m|}!b>„µäCbª•r¶.¬Pì4x%²+ŒcÉêÈÏÈŠy…F ÇCÄÁ ÌÿÞ æÝ]6Cšd¬½àÔÅÒí'Û–æ‰ß冰Jø=8tx…RD,é”­…˜eóhu¹/“‚H©²¤À Ù@‚âº#Thm%!S3öú œüi @g⦢#–­£X`IAVì Â:@#¥Y;œ®l#;½^ÂÅ@%õ0 ^Œ›gå–)¨Ò¹C¨¼¦¥Ð.±£É*‡[*W%°4äÅ,¥v­Ñ ªJŠwï)¬©€Ž-×+ˆÀØ8øÃÒ|¡÷‰µÎV#WJGfÖ "@^Äs×Åw,R–L léöè¸6R•Ž8¤”ðŽÅR1>²˜ucÔHÊ-ù•9å7þÇ4˜ͯK34çæ10$oþ¤,›Ó2¼»NlkmD*©˜¼¦/2_!D@ÙÆï]ŠéÜ h™*)”4ì?.â“~þ‹ ÕʃÂÍ“Tšhiòƒ‡´‘f«W1ß’ÁTÕîôZòžÌi:“hø £ñp½: ·M×ë>-Y)A]R°¤Ã[²–Iõ,«Þ[Yqƒ5‚^@Y݆iZ4²hÄ‹áÔ¤nìFR"ËÎ(Ï3)®#¤Jêõœ@DÝ/:"üÇë͉®výÀbB–ó@f‰ÀÊEL§Õd Q•¥Bf)îÜAÌ7Lg×H•ð &h"b…Z—âɺT@†F‡UÇ{k±ù¦UBAºÞUQ0k~ î‚5$Z˼9ádUA·©‘ј!}tWE9~]¢Q¢¶Û” ýú÷ˆÔÞ˜Žþ\Œþá5€1¶xÖÀ!²b dâÈ-yË@±½÷F¢ò¤ê˜œaUñqT!à;RúÀµöŽB€ÉKM3æZw&hbŸý¿üï[øÝ¶ý3-ì¥áIœYníÚ2p3c®ª}9OVp%½R@:.!~ï ‚?kýSkwz!↴Dkfƒ‰¥øâ²+·/‹NDSå¶É³©ÉÆÏÃïS¹¬xÊ#K9çJŒÝä1)ßÛᤆ#®ªcO(U#̆ç]d ‚€2“Bf1DLäÂγ‰˜wOnå®ìKÞýûX‹¾Ù´vÏèb k€–Åyc˜‡Ï0; Ìl{ ‰/¥ãp˜÷+íh²žj\SÊÔ’O¿¸¥Ó£!;2eK8„Ù¤ÌðÇ?þQáøœÀ݇H!“J "àfK›‚Ÿ?tY­€ÉšP•ùÅð@ˆ¦ôþE<ã¡IA¤ìËR,àáM¾3©êî+ §ŒÌŒÄC®ÕÙµ© ±)…u/5¼¥FÖ!4›]„«b‰‡_çtnò ®þf¢£dÇÞäM…&bʵÃw•J‡ëil`|“e¥,(i|±‚ÍŒTQíˆ^`dKü% ùb=®$òðqª’u†b„ŽÔ™P@KGÐ Û#÷뿘ò¼¾þ]·.M+î0;†o>ä`$d3Ç¿ƒ…Èh8Å6«ZÇÞyL4&@ÈBÄ5%’N'¦ÊòåxÙ”oÿ7 ýf«Wcè¾,§Íæ1g²bd^•¥³²b§ÁÊÂÛ”lâJÚ,Y`·G|ˆlµâaWkyGÚŽl£¶Ëd#Ô‘x”f‹V_ž¥Cßl=H!j‰´M4¶1p®>çÞèf o™ˆG9¤×Áæ\áÊ+iÉ+Ñ­×5ÈMA O°¹Ù0‹y1‚½ÇÏC’•½ˆr†£{ÇeÙð@½,×n‚ ¶9qô-[÷ Ò”"iBäʉ3ÃXÚ {cú8)ðçñ¹kY1Ÿ F7-A'Ž/ÛÜ@ Ê9V­ Ž%Že„²M &Bþ4b|ï¿Í­ªIò¤’m©3"`ÔP˜ ÃWå…ÖÖ*‡(É#³bäÞ AŒqeÏ>mÇÞ‹Í\ëº[JÑg òâ5Nš1-Ëto Ct„ \¹.˜ÌHù¶ïwÂ^þÂ@ßž }>¤õézõÝTm­iÍ3ÄF: ¸#Rn#˜p ä<>ß %ˆ#˜¬òh÷líx†ÜÙ6!¦ .‚^8¤›|å)Ë.„Á²ñ¥p¼*)úweµ²M+Ëðy4ÈŠ•WȳnŒ4)ÄWHYÜõõµ–¯ÿu½ü+¿Ÿåzv6óܵ^µ~³»¦BS[Œ‰ãôð·w[–mr %~â¶€/.À‰A•ÄãT d"©Z$Åkê4âÄ'N¹ÿòȘŸc~•¥¯= ÓlNqSm; ¢MMJ÷¶ì:JA˜àÍ Ö̆Gf8M¾X‡'e§Ž…Á»4õµ¬ š¸›§Âæ‰0d{©Ÿf±ЊÓlr¾@mWY ÄÀ6ñ‹x6»©M‹6åžcˆgû¤.™ÇUwt÷´H<.MÊpÁô«²Ðé‡+ˆl0M6[Ùûv(0Y%Dº¸õ­¼ó !d›!5qÃðëÒÑ5/E Sܲ4%¥Ò´Î ÒÃÇýóÞ?k«ËÏš¿û©Ef[ã Ól0‘@ñf7‰Ól] Læ¦•íØ•0 „oþð. 'âÉnGÕb‚'Ct¶MX OR•Ú˜ Gª±¯LM[œ»Š(²µÁ,&‘n S[pmçô`@)%ªâ äƒÀvkéàzRÓ%-®ê#[a}“Ê+Äç‘!|cV(NÄd1ëQ$¨¯ñÄkÑÀj‰K±Èl¡FR8²A‚óá˜"°fËÃ!|¯(@f¼Æn¤¤®AÎå‡qXUÎÓ7¾þ b£Þý>ø_/í, °4OKCv>qd-¯I³½XÊfU¥ãÙP9šÓèöÀ‘ÂÀLÀBòuw2p1_\UNK¾vS‹ß0yœ¬FDL°£pÑ+á¿ûî;OÁh_cæôf·ÿWƒëbZò´Ááú283oS F ˜Ž©\5 É»™‘m¹*1D¶BOÄÞåXÂeÑØ:â°vzŸSªØ$ÌÒwÞ¾àGßþóŸû ?ÝYMófƒh”ÕÔ<61vÖ.dÍ©œ… »ƒmGm„Že{‡8åìK6µ4HVmÛ3¸Ž|KdÖ+!ÂT5RÌ{ AàÕò•“uYíx×wOâ(,`˜mŠ—mS: \t"@-d™ÂÚ5!ŸT]dïµ–íZ¯tÅ@âJ ``÷j…ŸÒdé$Î÷” ¬ušnZFÝöR ¿ÍÆÈDËÒä-q¤}fÉàÛÐü!;´6EYgnõ—?Ïû®Kù§“ÑEǦåÍÙÁ60­,9œ·…. °tïÅ…l8o§cÊJãwAý¦ª] ¾}ïÿá{Ý*ði—¾Úµ#MM2~3@›¤!Ku)ãWخێeå‚–ÊÅ‘ÖÉ ¤æïdv˜²#S§¼«Ü$µCÐA¦c‰@‡©âÃ] K £`µ™ñ6!#HвÇ)´D¤àbå)8aKÏ!R:Å•!*f²ôk'f𻯠¢Šl_¿7›víR R820)+E°M!¸ž7Xdžš%d%ÊÅønþÁ‰KÑÙ16Zü? pY&VÈÎ@ÏëhY¹B òÈô¥¸ÃmºñºÈÙ SÃÐÒZ-ÆÙ~tÂ?Ó]gtMø¸Òá%²4™e PF\2gtAx…²€DUaò1/ùs!-ëhZF¡=*¶YKµž9J” xLALÊD”TÅGv8R@PÅK±†Ô}SÅ1’€lšñC›Hú@±‡Še~K qL…¼‡ÿ¹¯p^hºx{äïÄ׋O\S&îØv­§ Ó„ª›_ÌWŽ_Îï ÐNûç}RÀ#4¡8ý1Cº‡õ*[Ód×¥Fò¬T╤®cØ,"p{·÷M^!&3̤ÐBTÕ·v8¿ýío¿þÝ?Í¿ÿýïžé»:¼ŽañÙíóQ\ªI€eùž fÝÃf»²À”i¶„3 }4ü¤Ž”rÌnwK‚|ú4>))_¦IS,%l‰\/}YšdÌ’ádBûî è ð`5)Ö ÊS–…8K»C¨ïÅ}AÈl}+ߦ¥ù^>¶€3œî.½ÄÍ_0‚eˆ½Ø¼­ /ØÉât;º.MOJCšu1›»BJ¡ÀlûÔðÑø¤Úl½0ádO-³¤ÃÞ0iÂK©‚PÈ–%‹`©‡×ÚÒžú§içÁK&PÞje-Ytg¿e©am¶ZÞ2P\yLch´]Ôh² `†¯ÿiÎû쿵èÄŒ'»£kw– Žfl6…@µ ~ç‰Ì#÷‚u$®Ç¦`ÇRk…_ÊQ8L⛊l…šú*ÔËÄ·¡ü²g«×U6[ãiÝ™¤L7° Œ oNÞÅ]y ñÞ*ˆG÷y_QRÈËBºC4ª#²Î*´h„G‰¬¥“ËvQ*‰¯ƒ4¤‘ FÄ^’- ÁgÔX²¥ð-)+A;r×ðÀJèxcÓü) m#ÑšML„GÐ¥¡ ‡0Ùb©æl¤ö+×1×b‚D”G6€”áç«Â µ `%–é7€X ëëÐh"Єg–ÀÎD`²n*%–q($b  9á„Å´ÇŠWÛ~µÓ«Ô&ÑQ\IÊÿóç?ÿIq—MŽu Ò…Ä.Uý=F£`”†°±!)À•+L„wF g KÙéO h±d›ðN†—R²jš rcL\;%ÀðüÚU{%×ôó Ù| HñFBÐÎ$Ý@q´Xa LŒP¬Êò~2RdI9^wK&èÅ>öðÙç¼ûi’Ÿò”ÿö·¿ùÀ8»«ŠyÞ$R8–1!LеG^vwˆ‚³lKH <³´ÇÅ‚ûµ¨Bà]­Ã/«dc¤Ã¯ióXF8m Z"@AV­x;J’`d „ޱ;jj‚MâQ`fÌ.(¾,4$%°T¢\üªwÿÞïúºKO@d7mÝMÂ4¿€‡3 š…Âf ·#Öð¼EÓ¢]`ËŠ)äU•ª*}`§¡´D«Wc¥Äp?ý~Áw=#ù„qÙftÕ4Úå¨/Ü™eÓ X›­ŠZ›2átª‚d™¦e3@èTRvµé[.Ph©–_¹¸r´,š8q^ YVÐH–ìžµDhûÑ0YxRp1\m²<ÍUë-…8¦ Éæ)’e`Ë{¡ÔÄ2CÚRâkäs tÁ¬—¥îyCâã°{áôá˜jX,eu}¥Î×$6Ž î¾í4RË«&{º>çl$ËFMD—¨½üwÝÑÆˆ¿½´kœ>ª(ÛÞy›êÂÙˆ ­.–5åÍ`© ¿lΚ\©$ßNÓw þ©)”Bó|EÙ$õª"à»4˜]8µÉBÄ&¬¼Tâ| ¤Ä8|q…R˜<ërT‚ÓF&ëÚV…†QhŒ,bCÓM>‚ ÎE?“X2jí&ŽK6Ð’ÅDƒ«EZjÔ*FàWr“â3åñ-©1³å» ÈãZʺ‚³³Õ‹Á2Zq¾“âteÅvÊWR!NqºÊ|Û”ò8r A/ü¤©$Ý¡óxn‰ÖÞL'ÖpÊqlF¤Þ4]G¶ì–‚`ê8…m`sO©•ꤔ˵d¤hò‘‰7ª¥@¡Û¹+”-%VȈKU>5ÖÆ¥Ê"‘º(W>‚޼vþ-Õ[ó)#`6Užˆ ýöSllóºŠ;g¸±;Ÿ}ö„KçUæFùÇ?þÁkÄ’×Ú¨MÛ<šT£Êjä¢úVÐÞ{€/1ÅûÖmJ£IÌ®—¥ÌCJYŠ6ÀÅM¿ &`1yO‡uzÝ¥0:¢^Ô.óò[—£{éäÓo:ñ73dÖä–Ô´$B$râÀz•Ã{ptó 3·–O·]S´=2lD‹d‰t­_u}uñ–Fß ÷;j76°¦<ÛfMÈZÂ;sK|R!¦mò.ǽí¨<Òé$X_ÊD ffšì^Žl 8ŽŸø£ŸÿÈ\…o¾ùFßF\}7¡vŒ`AÛ´Ä©{q[ˆS÷7üȪL‹L§K)x:]±]Ã3dˆ8¿@ 4ÖTºvRb–‚²ÂZ+ä3Á½–øª²ncžB'€Ì §ÙíX¦ƒ3¿F>²DF« ©‚Èbí\YÌέ;í(^V몦` -äô™•°n)ÛIŠuÄÑ’‰ÍCjµ¿:ÁKÁ²¦vÌ€n9T|¾.ª*€GS^ +°âSÔËÿí¯ßuñƒÁv±a» Ã`Ûľ"‹™!ä»Ëzc²Û;)qä²¶©P¼=ö9 rvûü¦O­M¥xú]GT­X—wüËŸføW~¿øjlÖ™ w×úóñа;4ˆ ”,Úø»²N§3LJU§aáoã Ø:¤Ž«(ßléÃõu—Ú”lüj#«š)‰ÖöámP )CˆLGÌÎa]O‰®uí0½‚:šÖ—g—ÒãB³‘, p´N_–”.ö…VSH,»møôU!óDð“ªS#…©ñ!ù.–ª–%+¬ë_XV®X¯Wýæ'þ·×ÿî×;1åî(c¸yxÖFêÛüâküÇ®—²Y†Ã“j›í¢„ßüRÍy&¸¾˜t’µR0SXŒ@§‘ázYò)‹úBÜ–›.MU ²€ ê"„`2)¶BÈ)¸,_`w lO'§þâ‹{½o¡íCà‘y1‚ñÓw¯¶‘N ˜¡áôÓ‰,Ï€4á~Ø0íâãÞ–ý(ŒN¯>#9.¦©i-¥t´ŠÛf8ÄHR–xší´—áµRÈL-Y-’µ;|q´â1›Á²r:˜8?W •9‡?þñZØÍmR#­™ÖFÂi˜Ge¥ÊvÈ#PÀ÷åb²ÎA¯výf#•Ó”•2KÙòŒò|¯ÙháÀ£AwC6-ßF»¥1´^Jë¶Þ7Ø™8É®iËÄ+/n§ù»lˆ×³rLƒA¨á@œƒŽÆ»OØ`÷”Ô…—µÄV*PÖ!«E½Ji/hͯé½×˜Ê¦ªn›ά×Âò?«o§}ÐV«µýÚ—ÿ¡½«¬êƒFy¿ù“2A³i¡uâ¶ÀŒŠ,Ul&ÆH xˆZ41A^Ö²óáSXáQy>}jqdG `×–Þ>XÊîCÛ³úª’¥P_Ÿ„ÞñéŸì÷×ÿüøêÿx†Ô‚r#åw2‚áMb#Jª‚3ƒñ6sËÎÄYÅo92Ý!ø†)OdÀ3´ž±S[Ó‘KÉ&¢$Á1ÄÝÌâF‡èÕ` ÑJÁgר}¹‚Yúõ½·VEgµR8ô)kd×ÔBx´|­e‡(Äd ?KØ}"@#.௢㪢Ÿ¬òÀpLшÀRC¦VÉú*Ì"ã(ShÄÛ)óñ•[v·Ùd£¥H¸*ßê~É3a“ <êBy§¤»áMel>~§4\j8°“‰Ü’,B p[€„ãd»d¥â8)¾Ô}¸ZRpÿò­‡6üUæ{%ôɦ'†×”¾€ÁY{i)d´:øb|;ºªT±K·²‹LA6ðSpOJv£yÐEn‚LG;òI·ÖRN¸w²]t ké„+¤éEL3‚¾¸* @ ß<Æ€7^›ržM!2>#È#gö´D®Eƒñ1'êbØ`Jl³ApÜÞb)…¶hkí·Éc¢!À559°yð›¹áy&‹\Ó–<¯)C !ëØ1!²Í`Y»–®c4~†á‹M¡‘Êæ pFØÖÌ®°m^Y±!à@H´äšÈpøÔbøÄí­—e)²Î ÎWÛÇ%ojá|0O§k3jSÛ䘲ñ¥²DpÌÌ3ˆr^Ü ʶGž¥SP/‚˜öÅ‹õ2R „!ó!+G¶”ê € ³8<³DãÍi9&‘éT’÷ê}ù?ójñéߊÀ$zy!½91󜉟÷4 áÅm0ÂÈv!å6ó`ôÐ Î&/C»‰8š¬”ÁÄÀ%],šb)ULÐÒH‚3åeªº"Vh4-™BªCÆ‘ ¬ojuWn‰]JÏ n§G¡?¬aI™V—Ʀæ*` ¾üòËwü«Öç ÿð_ïgÎ<Ùök©µi £uó¨)kiÔö"NK€‰À åtxd󪯄¿ªBjJA!OSÕt.ùÏ/jwc:¥Ÿþô§'2Úû~6bãøÃ: ÝDŸZ@²p±ÔÝ[Jñ™”]0åÌ^XÛ ,–ªÊ ìæ—²#x}IÙ)f%é\V ¼{&L`œtx:1Åg¦Kpqjy`ókšàÙØ¥£Zઠ£Ðej ð8“…tÑÑó„'ˆœ·TâÎब\`‰Óø]}Aâ› ÂZ:UžY*/` 5¯PG:&Beá<<‚ªöèŠà¤S ü´¼=Ð:ºS`z1ˆUñpžÕkšpLãXfñáóË Ô2“СÌS0dop1½S@u¿jÛ„˜q¦Ð9ÈFv˜¤ÜQ–8²‚– iq#ÙZ|Lú,fGg ϳŽ"OJÖ+ÝmtêØ^6€vp:ÀÈ%üxŸ“º#•«j—¸ŽÇœzæ4cØŒåæk‚ä&Úq¢)ŒV' mó:9±€w1ˆ÷È«E½Ä‰ð€•ˆ»Û Ä Ñb)–¥ÃôµI`8B8Ž_Sƒ0YÙb ÈFµÄ´”¢cÉÊ €, Ó%¦,gÑ:ê!âR ùL¬P\ªØ™¸“yù§¯~%Ú~Å~©ÚÞuÔËñÀu¹ÏØÌpÌf6° -Ycó•‹÷P  ‡(\-¤«SU:B1œí†é0u"4 ~Ê÷ g]YAó˜ “]Úqj!Êç’y¼ð€ë[÷ûH”mÇ{ÉÆ‹cÙk¹“¤‰l¸¬¿ióªÿÁçŸþô'O—Ukúi*æmpç )³—ö%„(Üźƒ1e]k1‹³Ú• én)'`¼8pUbˆsT®ÛÞðŲïûôOÜiÐ4¡I†š5€P 2±þáeÌb6!Ÿ‘²©R<Á àˆc§n{qÇ ©/r )h×8Y{§†,Æéµ)–µ„3:LUÁ²Ý•'Ù–R³NÛ’²ì¥ýø^+KApÍx¦T²¼e 8)j%Þå°ìc“ˆ˜¯ŠˆÓƒTÈ·µ-+ U5ƒå,M' Ù<ļT1å š¾aº@²Èey1$GÆl±¬—¶ªfKÊ'•K*&0~ p&æÃõ«_Yy•Ù²ßö4¶½˜¡€:vàˤ™wceMÒlÄDòªJA™¦ÃéåÐËP9„§©oK/û«ÍÄÉò쫯¾Â/~‰ßô¨ÔÔ®y]LÂ,ÍRëF-+uŸ­©m“w&j™s@èˆ(3å¥àÔ*Q.†ÜS‰+ ç™.|O˜†±tªdmͦTé2‰éG£S»£rÝùéó™’ÄÑÕb¦ÜâÌ]JL8÷w±1¤âÓdâY)K%eùʽŽÄ)űðmMJÇ/âFuÞ ÝT H°à$ÅY„h*L8Ïd©ñª…[¶Aâ@¾³š8Ä…0*°·{`·G)>“m%È]šðú¾ p %bªÄÆ>÷Ÿˆt£ØeÒuÅ[)1»’b¾¬Âæk?jäÄíÙ}i¹FµVR-/ëšñRhõê”ÝÉmI(åXã‹Iƒ‰#àP`@YK¸)ì² q8ÀÙk¡Ø ªÒoyš]ÊpRJÌOM\ê´¹ÙÀ:jGGÎÿp#ñ‘ÝÖ/ÿÍÆïý×T »6¿¥¸-ëÞvâr?̘; ËíUÌäïgˆOgÛ;åN£PùÎ^•€ÉŒþiv™ÿSLЉñ16%fhÌÆà–|±¬)S)–EÖWpÉšRLÊ·ÖÜù²@©áÌ/Šú‘ýPûUŸþýÃ>¿i`ìöÛ^ô͌Ѩ&!Å–^PøÞäR|Y²”¥ BˆF˜îR;BȤÊZ*Áoû@q"ª’åѤj:ÁIùÍŸ^˜!ÿ¦'ë'!Þš„Ït×ZÜî,uÜT‰yd1Î@…Ê]>¸Cƒ3Oß%Hß²cAëÞë‘è•B®ªvÝ®IéDÈĉËF८Õ9UAC/r)ú–lCÞñâfÛùS«„×ÂNû„aM¥J*Z pK¦‹˜Ã鯰/-è"t–ô;± B e¤#æ3ˆÈ €Sß™–g¦çc§±Q« Ù`¼Ä›‘=2KÃÕó8iÚK¤:¯e)x툻ô²u¡i`%îdˆ¦ô!Èá@KÓcÁ –/4¿ü£‘! àÅ^ õåwøv$µG¾š­aŒÇv,)(oGÎM‰%Ž *Át–p'àd:%ˆ3#°J€uß|ïÿåâï~êÕ<]w‡híl¤5^ÛD6•QíE”màyËöBmÛêÂ\ ·}1Yä”á+Üñë^ëŽT jõTÈÓA€·;#©eøÀÆ«Jª¾q¤´¤À›JQPÅÏ]q\ÄZŸ]/½Ú‰ñX… IBŽÜe4Û£¬vº^¦¾øËyV ÐU³¬Ä¾Ö¯eBu5¢N„á‚z G ËqBô¦Œo“4-á|*%ðYWºÝ–…õç®b¦nB&®‚8YžÉJ¥Ù’w| JÄ–T´¤x3ðD†—Bª2OMSà+A[ ƒÜÁã“'q—ÍÜ ¾1ïÓO›MíãÞgÄþz²vädÚ©I:4`3çcâÉÆ« d; ËÓQ¤Ð´µ }r ¶`Ë<[«Fb)žéþCÓN!³³¶ ÜTéwÂŽâÞ›D½èÀùN’‚åZëE Âj×ð‘UÉ"7Œ.Î,ÍCG`‰Lê^ ™Žótõ5­M–¥LJyV#H©tÖH Z-ÜT½+“eJ´Ã첊}ÈËG–¥& €I*¿¦é™3ŒOG0rsæ¥ÚEËê©P;©‰‡LœrÃT« ‚okŸ•eûè@A¡r; ÁÁzí»!·k`¶ÁR¶ÍW=Ú2ï/ÿt!ÚÄ0z17g“w!Lki^†<>dÆæWUJκ±kÖNqàŽ"åÆè%o¸eâȘ u †üoˆ=êÞÀkÔ.à}ûnûÌH@YÃð–) ,¾` šöU4):::L·Vâfƒ#ô¥¸‚\Vе3`¦° |(–5¡Τ›?rŠÍ:$Íy%; Þ”•0gQUKLAÃà8²úò¥€ÌßѤj¤°Z3@táÇG«õ&|`j—‚BYHê(h`…q\BˆPy]e+Oª*xG”3%¥\§b'FÄkÉHº¼üGÀÿûß}0ê0µÐ]_ï ÆðÛ»­±h<¼9 騋ùª”o_²my-z@`¦9…âLI–Z`U A0Cš%|Ý-i6m“ˆŽš”sH /’m;iòO“ ô%%æS‹‡·ô ¬…¢è( Ç/ÿ>n4}]×äZØEê+ØA53¤ÓËŸ]]woUE%í"EÊ2_¬Ðü=×Ú;ýí(¾e%-Íi Ä/(˧ w\ïþÙ—/„¼'ÕÔQ›\ÜÀ‚D#&Öt†Ãp˜o;|1ž8©üª8ÊÀÚÅL`/*A{OÒ‘ªÂáÕ¬»çÆ;2AJ,+¨%Ùv!Î*ãȺç‘eíp̦°aàøë” Qh)E-2Y&¥XÐfÅÚ¥ ªÜºnjJÂÅÙFEΪ’Â'ÅL·Ä¹V’oÙ´<üi $ÕÑñ²zÙœ>O"Ö” ÉLm…ż*ÈÉ]†€ÌSP˜ÕHŒ'Ë€¿ëÄ•Æw»MP^¾¾Î_»¾Líòñ@›EÃÆ£™°ÙR˜ ¼Ã±ÓI18…Îg –Ê{HêÓo¶WkùçµbT¿ ¥]7g—ÉÌfó ‘5€aRÀÖxË<ñ®>ìN ìn‘dšB|;e–‡‹›!&Zc¥€–â5Ê-3ôõ.¯ÄØÈ4‚q|`Ã㔿1d›¹ŽI¡õÅ­ `G)£AdÅIµ#úFRëÒ¦¾l Ó04dˆB±Fk‘&Y¦Ö²WŒ¸^!@„Ssû, A³e&`zaªâ €\ÓÎ\V*¼]T…¿ÂD”À!–&TåÜ lÉà34H}'XVÊÅR8 ‚æ¿ôþ÷Ü"¶¡N%¦Ø|ë'»°i&]Pƒõ[× ]šÁ] gÔ |c%Ò¢ªNÙrî–íSÌê'¾òFÚ²I*Tr/ŸBxK L¬„µ…Ô’’â0ye{Ä´_^¡ ;†Ž¬B–È8W“Ç7¥â´S‚Rø˜¾÷Iùª~óë§}Ft«µµíÂxYw¡]XšÄíº Te²á–¥ â†ïž³/VÀ§&9UÀ]Gœ²r´RZKYfÚj[&[|GšŠÈÍà…Ga"ÆCÐQmdKúÊCÕdI˜‡P°tzh‚õUn™f4%úzWK烞~?ÕPÖÝ 4À.ؽk›¼±yˆ—j&ÓBTÅ™ZWŽLP¯#}=—q,ï]É:„ÚÉ*l Ùb o™¸-ñîOÿ~Ï¡IS£L­§Pã=F¹öÛ<|ÃKU"@f»‚p10+@Chr ðÄöè0-áºãôÉ”úí¸Xóì†l0wio0ô!uG®{MK)4¤”d¯‘¯£”·…íËxb“L6AåìÌôld™ø¤¶ÍNÈ_wd M[p&’9c6oþF– 'çÕüñ0Ù.dÛ&Ͳýã4y{¡ßñ¶‹ÀfPh°îC4KjãáðUZ6° q¾‹Û®¯Ö ë‹;®6¢WCê(U­€Nä{¡.þÀ;þOù§Á§OŸtdFª¯ ©ìNÐ^L¨¼‘1óö4&9ò}>'i†C¿Ž9P#HM4y4jdÌÙø‹/¾xÕ/IRËþüç?o¶6Å›­ÉÅhnZ3­ÙŠ»U‰Üöy†ÃËâ;LdRÌFlo)ÛC GÏ«ª Ð0Ž*¤§3å:6ß•BˆSyâÚ•µTËïâÖW … kªw>|Kð‘øÆë†‰fB†ßkˆ ‘’RD”óÌ2K-)Kj…bY8„`j†gböÂ_îúþûï÷D}ëÒ`6eŒ@Ó6¶MáX L‚Ã[º”˜²¸Ã8ðJÊvžíŽ.® O-¯…¤–¿T…&ñcÖwú÷½_èÒ§Ó0͹.–j<üº›DÐØbdžq,™,´ ¥v×½„VVÊH²I­ª,šìÆ–eY`·¨ãXÖ]J Áb-ôUˆ©µ ©Â/ùÇç¼ú–U(…¦D€)Ž\€–íU£Üã ±†DvA!}U6MBÏ» Ò2ÊÅÊy)¹í;Ìn!8k LÙ¤jÍ_=;–ȼZ%¬Çˆ;_S)ÊÊS®od3à›¶YÌ”ôê“E–Õ‘‚8MAƒ)‘²‹–|Ã(™ùoüo¿<9)ÛE3ÃÒúRl˜@ãD… uæí(2Zc·A e›*@ÖN¶mFèĤ”óÝÕ8J,ä!³ÿÆxJØ‘Ál³ñÚŽ¦ÍìÍË—¦sV‹ù›r·‹Ëø8â&ѾÉÕ’•*®µÂ»Ž¢V6üžm†e["LÂR\ÖRk“È6žÀFÌÜýd‰£;N:–ÌkÒ!È’j#í"ä—¿ü¥&~•yØýå/¡¶—œ¦^Ì@K“§Ø´RÀönw;U-¨âÃUíLðÅÌ…T4ARy:ÀÌ2ü œ×^tÊ6­ñ4*Anæbœtjš-Dè³H[ÈG [‹ bpY\# Y`§D¡ M— ys²†ÁìÙgÞÒ Åô~²ïújôFÇ<Ó ô2sRkx{ ¡ï”V%°SÖ»èR‚ô•°º¨mŒR‰ð3L…IÑ´¼-VÈ¿ûÓ¿ßpóc} ”I™ÓMØ ±lN­„À)޳,„!³˜²D\PµÚ‰¤x ¦ w'@áhÈÊnžªMœH„º—B®»Îд" 4 ±du$.hƒÆP%–5LµËÔî©È|¬¶¤Ï€ ¬–µ5š?r×B¡l‡Ó+BêjrîU) ed >ÜRyÖ2>/Uy±r…S«’b@j½–-éXÖ¥ϨÑdL9N”¸v˜ÊÅj‚‹~F…\çÙ‚%³¬KËy¿¨jËÎßÃ?ͦõ mN»€·w§mHäk`Y%vt+ªU’SŽi)K!à ”§ÁR9"àÑpF¤Bç¿ñÛPýë_uiSº‰ßŽê®µ7 qÿßöÝ6ÍqYœô+é@øJ¤à )NÁÉD /K0ñ m“#°ÍV–/"â&DH§d!DV˜­l[‡ð8§„A,#;YÞ2°À/w¹˜7×G^²±F%ÛH!mMÜT56XïpÌßyv•{Ø%®Šøéq™X‹ÝNí+fkÔ’ÇŸ]Gun›8ã›ÁÿëZ‡Õþû£ðË?j»Cxóô˜׎l3§o0KfYöÚåcŒ¥Ðvhh8|µé@{`óŽ­wYƒÙ~š8DIÊøBš²Å8ø}Œ&œIA­x|»·ÃAh#»|R,ªâ<¾1ÌÖyza6$fO3´9^)q|»VÅ,`#1ï—˜1OD·dôù”á FM K­e Ùªâ# w«uƒ­)‚˜á3Aµôæä3)óweÅ á3å5!ßT¥Êö®—,Bï)ÔNÑd×ÝïR¿ê²½ûÁ¯Öu¹õÚ÷€Ûï²:ŸF2d7•BR¶§`Þ®SØ.,eé8(÷ /¦Ð5¢ƒÃ£Õ…§ AhBqM¯ï¾¿ü@¾ÿþ{#uót SÓvgÚ&ììKlGåí³¨m~ˆ½ðhYÖ¡u8-éthbå,P 5P\/jÈ–æa‚b|š'f›+ÇG0IÊDÐò¥,•ˆwÑeôóµÖ’Èp% Ò<ýñ¤([UÛISÇ.î{Dcu‘_I½ J,£ŠÅjž˜[FNÇ$]¾*S‡_¹¥W¦Ã € ?5>szI9CÈ6¢)z)dJ,#ð ‰×G;…4áʵØ5Zyš²øéÐó¬ló<¾³U=õ‚äð âpÍÄ‚§^üsr×4RÀ<œU.šžT ¾šÉ® ¡1½¨5} Ø­,V…p¨×5GkB`Y ¾ ¸a±`VXÀ3YåÑÄ,œ~¸#À¼];œJz5îò„ã¨%e¿Kj‰ðöëþÖî%Þ}ìS‘vÆ ß @[XËæÉ㘠I•,vEH™V`~>C(àuÄ I³r‚-X Ý*ÊeyÊ]SSÖ § ´Ì;Ø8R@Öx–I Dc¼š”™e] ÞÍY;LÙ«ô\»jpRÊÅÌù¨`Ù÷“üxÇÛü•ÿ¨sq}o¯CÖE÷fhGüÓs“WbËRíÂÌ–íºíT¢'Ù@ž%Â;¢æQn)UÇZ‹œ'“½ã ßýOýE¿á¦…áµváÄ;ÿµÖ‘Õ­X¶ßxí½ùdÛH‚æ4<Ž%;r×ÉÀ+N¹7å!˜ÆóF…yÕI¨uþÝÙÈ!)Y¡ —óÕÿ¼'±æQDS˜o‰àLRÖ!²Z‚²w~U1qðÒ0²Q—²@A©žÛ8µˆ,«…^µ¦RBÇïåßµƒ#o`µ-ómŽ_-Y`}yvßÚÎÍ.ç•0Ìd u/o)0¶ÚR<¼©èˆ©ú:KÙ–¼ÄJtãCX‡ €¿ê]:ÎwÜš›o6-7¶Òœf@Óœb)|1KY`àhyˆÑqÈ8íÝWžu*ˆ;ŸÇé–n ç žŸç´C66M¿'YÇWyßû÷W°µ0ÓB÷niq­»OÄÛ3f ¥ZKq¸½‡Ûˆ¯{™B´Ê ècŠ1#¨@XL>ƒ\“>œ¥*)A%–Ô ©ŸWXö%zévuÔ˜í4åö"nŒNƒ·Ü–õšÑZydß»›vjíâ圬 Û¾Æ„]ú¤µ°äÿ•ÕH—Z£)dUå † e© o|í0wbµ€ÄAÃQhiÞ’‰¥:XµÌvÒ/ë>G€H ’¤|iœ§«e#iɧTEÄÒ¨,žÑéÂ5ÞjU¬‹XVŠˆXˆ%Îãk l¹<õ6)•OÁõÑÍ‹¹kV‰¥6A:È ó ¦C“WÎ+ Ù¼ÀhÖT-°.@µm ×†¥ZÙª Óaò–š¦v%/õ äS&…ÏU‰Æ®W`§×¾ MÇÊùÞÚ—R>Bœ‘íBŠgÍóÚŸÿº|Ÿ>}"Þœ|GªWç`X^#<6ŽKu,×– 9DU¥PV Ìì*[2U8»(“-a7Œáét#©²ìrÐdRʵË2å⤤ºâ#£%""ÞýV-BKA`ší¸çKÓE`‚bÊ–u÷oû^õË]ÚùÒN‹öruûüº²ûø&‰&–µröym0š¸,š Z:^¶Ž²éó!6˜x¨lWVa“DŽyžà»0â>÷]=âÆ«OP_ú©n!Rë‚bÞ¿ùf†wƒ%hY¹ªª²ºˆ4€X “·¤o)uVâȶvâøü®—| mMªò®š)àF·|—’Z&‚Ù ,EÄ¥4-Ÿ,>œ¿w‡Há8aÁ^;8 ŽìZÄéýOJŸE†dMhHK©^>˜”!ļëy‚€/»›PVm4xâ<Ü2ñd˜`úõMÓîÒ—JJ[Ú—*|ƒYŠ`»6ƒ˜`¸%YK ÀÓ=ü‹_üB@êUfkþ7·]JšµÇ®WÛ‹Ö&@”˜°ÁÅ á:ÌXJI{ß!˜_´ÄËâ ˜ìôc¦ÖyÙµ¸ZýÏ×_ýòñm³Õ—¸ëè-»ÖmGëmÓðv¿!â²ÈÎs„öN ŽÃl\– 4rÚ;®²cª¥\->üœÚóýW P /Ë€'· Žh ô¥ˆñ˜2>«0>à o´gæ\ñ§W®¸9»L¥ú²*_-5žš ¸ág/p-ð$O Y¾1œhpÁ8‰¸švÚ-Dˆ÷j•jŒs×î,âõåq|ˆ„§¯\œf8µSð|¯ÁwÛ4[“/‹ FÉÔ®Žy4½ê[m/Õ†Á¹2ò‘e1»(‚!Â矚¬­ Š»„T,•©ª­ Ë¯SI ~þ ä;»æÛyI CPB¿Â†FDàMÒR c%zU¥¡YÊFÀÖôʰ©ÄR¼1¼”˜UKP¬ 3BRv!¨{‡ƒ3cð–˜Ý|Õ&X 8Y8²˜”Oÿ¾V¾d^àtñ"ÍÏ´à~£šÍ"Ð Z7‰f$¾ Úßœ-; „Kûñ¦bY¶ÂÅ –Ò±sX»–h˜JÌ 4¢WRu_,(ÆYù6•2ÁkJ¾,Dm'£„i×’gW·ãf÷¶´Óû²tŠIÕ‚ˆŸþ}ûÿÁûðüÙßì!£ÅÄjgžÀ¥ÎNžCn§ª ì_ÐÖªíØ+¹à<Óq |¨îøÀvj³–,Y´.¨lÁZãµô{ÿÞ±’ú¼^ß}÷¯»ÚG$ñ^° .…ÙbcŸ‚kÚKã\ôÍOꢜÙÃañ«íLøNÇIŽÓY¥– ÚÆ´¬oËÈæv†4ë÷èP˜MŽ”rU–’ØCز¸^æÜäë. )¥upåiªXví8ͯ¯a ™Bú Æš“¾%‚cäÉâ›yí€bR&§Œ ¬0ÍvÁ·²Ì¹Ù&Bü¦’m ̓&ÐÝ#:Á›,…†IŽŸ~jJdyq4¾ü®‹/¾$èw]š¶½kÍì¢ a ±”¥ùkŠ ¤½ €-!v”ZþÍöëÌ}èD@vV.|qœöbr‚ÅáZèK°H‰%Ôª#¼ói‰à7_õ½ašìÛo¿u!Š7¤Öbc É67|[FØÞ•ól©j[*Ï, d#Ø;Î:«ZÛ~Lú|£Vë «¢ ï9ÄçûDc$ˆìèªEŠà-»¸Fÿ¨šïþ<º¾è?~ù§oØã.D'c¹î²¶À´mk8BSjˆÙ.¦ †D°q§ÑmS¯ø”m߯‘áj{ÍÊBèC*÷É端¾zÑIŽe—›‚rˆr©h¼B©ÊëÕåè¶c´©i"¨êèòIUÞFôe1›°‹®ñ¾ #b ^‹¬©Bxåjãˆïä”}J$XUKl µ4LhÑ!Ä£1sªD£lTäuÌ&ÁQ% (æeÃC"ˆ ï@ĪøJâ'[¹s¤ÐT¼‘ iæÊUe›ÇÁÚ2šò !Nã¡5O+0Zâ)D‘™¬%õÆ@IDAT&€(ç­PUYž©’eÈR þùGu •«bY31 ç "#8ºzw91¥Ü5ãáJlã*=NÜ]påb†Ì(ˆ1ë" ÛfÒ‡¤G‰¥€ ÎÝpŒ@­%‹£D\‰Ä!bULU}Å‚fKœÔøL8#U•à’9¯¢†lYñÈ•t“©e¤^øé ïý{ µ³  —˜bòæéÒ´ ³xvÇŇ˜oã¥ÔÚ/YÛtžA²JêÅ«½ë·„L°ŽpV­“,¶Dã™â^¿dñÆZ F–ª¶qRµ0dRî ²e§$®JJ¼ÙÂ;„È}#!Y)†f™½û·Û‰¼1ïëÞ̶Y-xcF U¶ó4¹¥©¤B€×˜ç¢„8 Ù–RíÎvJ5jk*Q®j…’B`°0Y1ïš¾ûÓ?¿娛„g@¾¸ĉF§ñ•5g‡²a ðUÙ)Ï€×ÎÎéT­B1ƒ{4ù†®ZW8CAâëKJ-&YU²Ò/Vn)U!PI½š*œo*¡àøy)½Y (àM‡ ¤Vm`M!Ù Çq¡5-K‰Uñ”]LK†V‹‰h‡“‚ Å YêÍ^Ti—-ô´±T«£yIP Kß;Ôe‚‚4YUIaÚE§Ah{Ók[èâÒQޝ™oõá}_?|û_÷ˆ ¿Ýiä•Ò¾ ©À.ŒW¥‘€FŠ`NˆTK¸e“ÛH Vyç¢u„®×¤|±äêèȈ˜M‡>ÌZ ù^ØkÄfýö¿.ú¶¯ƒ›¶¾pÛdJu5• —2-ƒ (T.N Sªˆ† Ȉt]ÄY†t÷6þÅ=d1ß²øÜfˆ v°FZk9e)W>qä!i¶dx{)†7ªÉéw/%«PP;‚–j³^:¥ ”˜­.÷£–RÕl² VP6·ìf¦ƒPJ­@•‘à©“"”2ƒ,Ƭ¶[ž¬ 9Û¦ò6$ͤê2¦ fÊ8NO;gm>WUS É™8>æ3yz•…wª²?ùÍo~“„ W¶Jc)n)¦n©80ÜRŠ‘®S„‚«‚o™‚öªàž!(lÙ0Àš¬uÝ-W‹Pí6‰ÃZ • eb]l\ Í¥…01>rVÁ¦¤ÂÅ–d,þ´¿.L6…JÊ™ËCr׆Žß ñ)þó½áþè§´Ö´i ºè+(–•ó¬É+i~àÅýül‡ÚJŠÛ…Ãx¨±_K«€¼ctÈ‚ 'µZðÈ)À×(¦É\Пÿüç÷Yë+¿üª Çð”ÕbBXôeMÂg eÛ/f£^E'®6ÇR••PÓÂ.+…iû@¿ß"xôøØÜ?ß}÷]M@—Œ°I›³†4x¸ªÆq[V‚ÉzÕ´A4%b&F´w%í=Žßm_ 1šZþÝ¿ùCÊMîO5¢£E^`-ÌéÌ[⢪Áò„À&ZÞ…x ¥dY;å[VËCRnוÔ]Ê2‹)nrK&ÆÌÄë"fpçMªà©wîð†AÖ]&Ô¯‹nÙ»ÄÓî^ŠÚUqܽ—¥l‚á|ûjÙ-1 a¤²¾1a –M›¸r𦦠n<`MõMGj3H¥aÛx1¾`½Ô¶·Tž`â|š€?ºÏ÷dWbfx"ö%j²–fM©±ÎYðòïvûÈÙÀ5¡j­©37­9»¸ùzÍõ8I%íq:jû(eƒ‘Õ® ß²'¼*ËŽ¥;ª¼ÇÙ,R–õŤ°Z ÚËÿð¿_˜tãu‡ëµ{Ok±: Sµ.œaX'ÐŽ[‰mŠû*E‰¸ýk”ÐvÔLÒéQ`–˜»(SÀÔW ›‰KÁ!@å–À6?B"p3 ½TˆÀ€–‚À8U•*[G:ík|xHâ'ÛN-; dñÔ³JI-eg^ÀOßѹÃÝTZ$RSU8È‚vT/òð–ÇW O<¤rSá ”³k®Ó+e«{¾ÚŽ®.õ÷Õ`Ó"S!ñ©AùÕ…=ðšR& ÃËýäw¿ûÝ…·ãHÅÀö0QÁâ5@«$]çÞ2Íeë2eü¶1YKñÓ&‰°m¸ý,%(KPmËWé¹HÄwâJ¢ÁõÝ0tZâ ˆC ˆ †wÉÓ¼‹§S¹Á¢ ”#»º–,ñbY:¿üòË–÷s¾ý?ñæÔÅ<æ·Ìš¡Ùxü²æ·”å;Æðb¾,‘eßÌ,¥œÁy}ydÞ«Ô’B9ßT[ÞÁtš'q1ƒ/pËÝÊ.Œí{Nš x¾¸y –¦ÊÓñS,p½V‰ßx‹ R(ÆÄáµ#È,]\ßF{‰ùôï7I½6}clï»mðÞW6>ÏÌéèì”””è0…½–Ñê(P…ÏG€ ¥9ퟯë{w N%ø§÷ìmþþeÛ}Îÿ7ö¿>øÛßþ¦{ÊzLY#`ï©mÇRJ<Ž¥8°3Ðu ¥¥ÚD³£´ë–yÌÈ£µT{eo ÔLŽãá&áe¯ûå|Q4Yš5åÅáªó›*ý],Kd4N4Ë.–€QuJ²–é;Òôá8L`<§–A2Ydí¦¯;¦˜ BÈ¥ôøpfz~´JÖ$ &ŸˆÚ¤ÅRd™ åÄq"Æq,m3 —@dµ®/0N»›O¶’zAf¶Ü¨¤¤ÔÂ) ,ÅÃÐF€ø·ïqÄ/1¯ ÿK&údk×x–Ó]—&´RÛ2͵ŽÉ#£Ù—çI“Ë6ü6…CG6¯)ŽK L@AŠ)d˜@–‚l±ç*‡¼Êˆ7F½4šxW\¶‹+eK3IÖ±(76³‹^;„ÉVKÂ:s|8Kî%¯0ŽÑ¨U޼™ÕBXëÊ,… Ì €ãÆ«]‹Èñe-¥jQÌ›D x£öQ™IÁ• ¨µL?ÙÔ’“¬ˆpoÑ}'®änhŒšø¶#N¶ïè‰/À¡Vá¥tœTÞ™ÃG`–a©¶i•`žÍ_Ïð‘ 1;‘âRÈ ÃSs\¼s€#¬ÅÈÍ<Í»` •DËCÆï4¨Ÿ½ÚLsïˆuÍT ꪾQ–M|L,[›f‚¨ŠIm,euçÑb#­D£{;Ru×7Á zØQÃ4ÛZ;ö6ÛÌvœƒX s©6®.v’p¦ ™Iu <›MD,k)%P‡Wȧ#`F¿:RP–§ï³¾÷§¾s´~ô#ÿ€Ì» 1Ì`wÈMw:gúë¶Ç±4<‘¦í;Ê•À•à‹! ´ÜéHY&Îûêî…ÇÚ÷¼ýþO£6›šÁfÛT¶!D–Å4¡ MÉž#x‚½SÀœ#(V+¥°C«<…Óãy8tT]Õ§¼Ž ûa<¿ùã_EWòŸzßø÷UnÛQÛxFb–¼FZ Æ7¶”eUͳ cV[ ‚ V"Ë&˜8šl6‚eÌFêˆER4‰Óª,MKxG I²ZÃLSœßNÑÄj[VnÉRHy±ÀvÍ8J²8Mx <~Ä^kqV­—¹«¼iÕŠÓ·_­Å˜Íf©Ü.L-„à²)æ àø;·^†º+÷ÀÑQ-ÓE–É2 è\ŸŸKRÑ/2ZóDæ 6†”Ù²AUuú¶Eš•0°M¿ëB¹/oû&ѱî ÀC:ëdFhæ®Cèò!ã´k^ÌŠUÉ" ôMD Ë,CÄN’O˜Ž9ßü,7ñxÃôË?õÒ´Kvö|m„x“É$¦Å„4a­ájÛ7‘mPîZ×¢.¤å“…0-œgwˆå85â›-ÐH–b>µZ7y)+ÆlHÙ€R_£j‘2dc4̉fZÞö›9Ž²Õ &(kBÏùšê[#µ¦•²Ä±D(% Îé04^6¯älïö¤Ò(%ˆ @óRlgµFʘzÉ6¦*GH-…Íýßb#õï›—~ _¯ªšm±Ž?T‹³!8¦Bf–3¸¸;\—A¦Y ?¤àι#)àïU#ë(œ3PÀß5ÐÔUbZPÛ ¡v¦|¾®kÍ#³e»=B(\ÉãˆDÞ5JA Íd)‰ üžkäå†Sª@{#@Ú¾ ²ÖmSÖFÖ«Ùø˜U‚yüjãTÞQIm#:V‹–¾lAo²jÊ-‘ bòz1qY%ñ€'¨ªBKÙö›ˆKüŸýgþ¿àvªÓׄí·Ì/kŒ;5˜òR|8Ä%ëX<%¶£Óïijáhª|yßùÃ-Ûr´Íd†„P2à ÿNZ£yVlŒæ×KSþ\¿«µ%r1¼£0*¾”á›·„»pN#œô²KòÜb8«„¦B'y±Îf½Õ(„í|Š[ò«¢3°òô«â5í60j»@†Àe‰+ŒÏ³‰h‘¡ è¤ V´ü€d½áZkA ÍR/1K±,¾fp ZšÙz-)@XåÅÑÅm3r|>¿.q:·æ„㈲1„Hˆ‘ªå3MÑàÔφŸÏ‚™ï*Û¬ÂÖ¥yb6À£Óu&²©%(ŽcIá~ðÈ•Ÿß”ŠDº–SßžQ·Ã#2%õ"CêÔÐt2`U–u²Q¤àSK‡² >ެ%Ó®¦<))œæ7‚â²Ñø˜‚øIá@(k vUpÖ Èb>~Ûl!o*:˜q ªml§Ù­œH´dqd›ä…o¾ îZ˜¤Öí˲±ÆèH—jàÆ3R.ÃõZUÕØD੉DJ ¤’J9Ü9ÓìJÁ}tó<І°©¤ô"È‹™,«Zx³É6Xóð úoª.ã~ö³ŸõÆ£i4ÃÐdhÔ€©ñ–MkHÈŒ¸ÃÄoŸÂ ¥ØFÂ'Õc×Ç\´—˜«ßë%¥ß|[hjÂ&7 Z)\ŒÃ²lSA¤’ZŒ‰@„IÙ]…éˆYWWBð.âå€i6î7ÞýSâß~û-©gÛÇc¡c7$ÜœY£ò-Û‹øíˆÀ«•0A:D¤"SXVÈ#3L>ÐÍÓñº¯*‘Ø‚€÷ `5LÊÅ” ÉdÅëU\: ¡yãXÆ—*{ç‹YYUD·G„¤®Ÿ[X³½ È‚øðæ§‘¢ÏgRÞõ¥€˜Àé§Ã“ G³l°Ô¤Š+ÇoYÇô¦lwBûÊ#` ŵæ7pä²oF­Ñº["ä»9»èöGŠy,ð6õÚÿë Yß ðÀtÑÝØÌØNƒ7¼¾pcð¦ WÙñ ˜ªDV‹¶£Ï€4Kuý¦×¾CИ¾4K¾³Z¡o—4Éd?ø®·€vm;:š¤^û ×È}Lêû²MØl•˜Þ¡I x @¶­í`á@µ•÷…„CkAÇ‹@Gy"Z$‹Ä±B—iÁ€8S§BKj²ã„§©Ür Ç„w} Šùìùþÿ÷½Ÿô© ºëµ%D;& ÐNClNÄŽbª­ÂLâ–)ð–²â–‘áÉV¬0¾e¸¥ªgÊç3!ƒÓÙâ™yÜÞ¾GþÅ_É| Êe ¬ˆZ…!<Úúvwi‘y“+$ÎB,«š¨bCzFüú׿N þAÓÚ§ÿæo‚5­/°ãj;‹]ËŠí¿·Ÿ “j¼JxK%xåyÀ¹wÇð eQ•TG „04Þøßýé_ ôÓMnIP#äû–’¬Ö&SÐF¤²«èÜr‚f´„À6U~q–T1}ÍꥻŸ>YRpìîCY^HSUŸìN5‘ÉZ2ãaæ-ÀÛûRÍ œúK¡rHZ3ï&1­Ö+Y°£ Ö©Æ¼äÏHSÃz•í~³DN­óA¹êŽÃé>A“2Œ. ^¡ ˜7!O¿_A6‚òžF"ÞÀ¥ J |šA6<™Z §Ùeø!ÎÙÃóa©b:¬ÓçNw‚À·'ºINå+Ì]ç'À”í—ï”È›Á®e;UAsJÙßÌ*…Ö¥„»í­Âþ¾ýR<²ƒoI„²œo†i&âÑýîd’ZR±¾;I|‰芠ٯÁ Ë®]ˆ¥€u&Ó×AÊ’2Z”£“e°Dc”‘CâðjǤϟfÏG.ŒNxˆªb"Ȇhš~â8‚vÝ%®üês6ÂÔ¶µ˜–´R1ù8‚”e‘iFk³²–5¥#F®D¼ÁÌ DPNĹÉ6° ªí¸&›f |ÖT¥0›V#È}$²é ´M/Ÿ†¯ 5UÌæoY©bÊRu°ôc6ˆ0¤’@óXRk©ü(þ3SX­úF¥¬ð\ ÿ©$•š iÖõ "®S…øi­/$Ù«éãC@:RÍh‰l,"Éòæc8b¦Š!ã„«TËËFŒ\ÇúçkÌë«Ü²C÷‚¤ƒD0À½D\‰ªd!qÜ‚7Yœf®é:6;i7š,üÝ¿¡Åë[&d¥LÈ6’vR¼±ÙE|¼1ΤTÈ8²4+·‘†¿ uDŸúÎ6 NaKƒëÂÒ Äl©EA­íBPÌ£)ÄKu·Ì@î_8pæ;%hôÅ]}ÊjwP³Dè¬Ð"¨b²píÄÊC7¡X¶ÉúÞÞýç›íåÝÞ»´»f¨QRZgÀp©Ž«ÁÌð'÷ñ_ (~~K“]vówPÉâØ5Pa)ÌŽ‚Æ 8> ä_¼ø½ŸŸ6'MÊd™¸‹Û9,…Ð`›Á`8DI­ûGŒ&–Å”e@8EnËJpxVª€‚* Ḑæ– áÑ:êb^–%(P^ñÚ¡eÊG†Œ|gŠÑîHƒU«$ N¯‘®B]˜lœ‰ï4YKÞvú€Û<ô)K)ð–|j!‹Qßñá+0/ ‚1F^ܾ\\LS¥ÆK¹‹ˆHLÇRU50¾@‡áÈF@†ód3Ëô§c©*~fl²…/ÿ]ßì°)‡ï63’®¦XßköÇõKñÆ`…@Uì z]²ûŘh‚,çêü—BK4Y“PëÁå_.Ùx7ñ¤d;äª>òdHá÷¸Ðh›5j¼Ã釦5¤‘|_Ö·G|††#21Žãµ)KätRK­;ÿ²fP.[ FÈã ”0d8„ÏÂcÊÒ”Õ·l|q‹&P¢ KUe™T„Jx`4e­Å8kGˆX‹nø8Äí´©ÄII5ψ3©b‚iš ÎkÁ#Pëq\†Àˆ§&FÆ„(AKö—­KšJASžE¨œ&GÃ#$«Ü$Wݹ¤â4XÓ-…f‰Àì¨FR–« ¯°C­Èu¹à3I$ËhÚÎH½4OÔ@Œêq,ÓD°,3þN‡&³T…†O_œIá?W‡0sÍàé )´”ıwiÅ8á‘£ñ ¦,hH)dµ–WN»žJÄ#(ð©M i’î¶`-0ËV(FXw%âÔô8ˆ¿ýŒ¹. <È|¾vG¼IZtzÅMÞC,…Âæorž2¼Á:JÄø)Çá©ÑÈF&#ò1·ŒÐåX­@/|ÃáuIß2¾¥‡…ÿ§R"óþüNÿ7œ4¯^ ÈQ|~w³—œ‘¤¯TLdèÅÝ9`ÌKãñ€Xúºî…_Úù±†ë×Å&l<ñf“µtNU 1g…®f—LmCÊVÕÙN*"ñy154ñšÄ\62Í&ôBCžÁ}ãÿ#zÜáþUw3“m`2ÐÅíë.¸ ]ÓN£Q«Š 2Kc7äv!eËÙv±TÙDdÓ”íUCM`©Ü9ô~c©ÊRUv§ c6­€¬‹X6²¥F–²- ^ŒÜ’·Ô!Ž©€ôRL\¿3«å+Ä4«W4[î¹×%ð­Ö O×çKOIå1«µ© bš÷yŠ¥zµvÚ<Ò×ùЬP`9MÙZwbžtNåURǺWh/@†i¤žm?± ¦:V#^ë–Ænª—ÿòGDßÏÖΓPGcˆuì MtFb¥Ú‘»L˜Úv"óÛØ9´A¾ÍFkƒ+Aƒà/Cî7Ž}Ä—u¼š~ýõ׿YùÇ o  u7LÑZ_M½’—âk-0 $&™¿“£u\tlP-S‹¦À÷žx)GIc¨j’Jà–SHY Ø5ŠV¯fo*|„ªŠ-·ß¶ »‹Û$)4'~`Kµèâê¤i)P[9f² B],›SÀ”‰0š Íш§ïQ.Œ,MKx/Ãjf“ª×~\©–ÊkãX€‘‰ Š €JŒÜK©I"tæh•HµkÇÛ™C0Û/flMº0©5uV–ªˆw‰ ™ODP÷ÊO!)±Ix ½ö1?#9TA&þ?ÚîeG²äHÒðbzK€Ü>#™—*‚ @€|ƒþìüîR6Q½¦GëBKMTTTÍÎÅ#"#³0šU ’MWŒ@KÊÞ”4M¸e8ÐAô0k [£â á–pFAI¸XŠÁ!•X.Ç„Ü`:§ò1!oƒº4-òÎwЪÜÙ) âtÅlÙj :LA%hmP€ÐþÆÿñ{ÿÊv¶¬£àLöÜ4|ø×T|cIàp(4¼˜áC–²´-kYmdž!8«b]šíV(• 2+&¸*ú¬ŒÃSã›PI3»½ôïsB'…Ûu…pãAЈ´ A%|ä•›²§À 8ñÇôÓ£oüQ–Ê_b#›þÎÇÒ´;m$‚¬Ù€8®ÜœæŸT‚y©ÈGkd!Û)M8ƒ8‡QˆÙÛ`)oÒOþº‹¿àñü£ñ6›%ý:ò À· [Ž)6¡T8~§”Ú¤à 8¦¸«o;hªxj5ãw/%RHa·¢¸¾Ž<µ ¦€DzQãTRÌ×T°¸r>£Ÿ&µ-•Èt“5fÈ»úÿyŽVŽÃRh6žlKÇ•òD0+ÁÙ™àXJ©å› Èv›+Dè"ZÆЇ×%BÅL£²ÍVîR*‡«í‹ '”E«…¬I©—,>°^âð± M©Êi6¶W„ßÿ—ÛÓ¡£ÉˆÙxƒíĤî^ÆklAL"☫Uä+IDvj•¨jËÃÇDβR CMýZàý'·_D~`Ù(Ô±« 0†ó‘jW¤oê Ѷٮ¾+‘âñ»|qRbúž8Ùh tÄéº4\  ®„‘‚Pè Ä@µ‚ s»Ò“‚l%ìÖ‘"ˆ£0Ü b´`­ o)@КOœß0˜ðæÄ‰\#x·wß…ŠuÑmU8L•’Ûî´m­oT(À;%qx×n$ ÔøbAB€lqü¦â7X)ÙÆhk0Yc§ù§¦@"Gå™Ä.0Žðex©øõí c׬ûG–Ȇ,iÂæ9]ß_®À§Ü¡‰•õu"‘VXªg–¦)·DCØÜîÝRÈeù!ó–8+D`–@–ì@ARR•ÄAK h‹WO“M'B©emЬó5¡8\­’¡±ŽP ^Š©í8eœíZ •BøÄJ,‰ø(.û‰÷È1šZ3³Qãé™%Ü%.+Èe·t}7d#EF°©âDЀZcZŠpPI…âm¼"L–‘J!ß’§Æð1¥ ™¥.RâJÄ]Y)?t¹¿ðƒ³½‹‘5m o7ƒ*â›píw&ϼç<³–eCè|ïßcûëóºšòš Ú…ðr›­“á-í—ßF:d;uJ‰ðÛ‹ ªºˆã+Ðau_‰%°Žb… ?Dw½œm`úŸ¿½-l†ÿÏ€”_‚Ò=~ƒ-ÖZ‹|34p÷6š%Û¦p,ñMkNÁd'[–Ù®Ia&+èÎIߟ¥&P%®—Á:>Äs¤ÀÊkÔÕ1&Ž@–‘Ò ¿¡ª–‡÷<æh1‘¦xËbʦÃ[¢é[P¶µJÐ ™ÂòpUf¶qÏ#ŸH3ˆc®ð©þEÓRjjâhÊþZ(…€ï|:"ˆhSÆØÀ]K8NïK1k0œdáHYòžÁÚ³53Á8]ÓoüAíü®‹7€Fúêl_Mn Ák²÷쮓i~° 3ŒL‰³4·ß–+ìè0á@$°vñ^ÊO‡óÃïLäo4?41€Öuä5µÔË$uo0± +e€öÕðÕ.› Oªíàô¥ƒð.4P YRdRi–íu2ƒóV_ü»ˆÃn©Z¬dÁ:C Z<g¼tZš™f·´Bäâ:"7²˜u’ Z6í‹ýôMGg"›Ž‚³ʛĒáy4RZ0±rgåýï«,1fµ·©6ˆO¡¥4p¤ž>¯Û Xj¬î襰g NÍ)é’š¥ZK:5åuÍ@_ŒŸ‚¥,2< ¹s @¶Ú 1YÀã 2㉼ ùÑ<BÒŠI´sõb¸O‚œ">È ©çª‚°nkAã+‡ï¡Wç?U²ŒlWÈÔpx1¿àö¥#%0pK‰¬ Axü”«"ÀÚ¾X %ÛQ…@4µ‚ªØrúc¦é_©‡|‹ù»¿±”`ÛiÚÝÃà7¿`¡=¦Æ¯0AÈ” :1¦,Û¦zø-Óçu¤ïäcެo†<©{òb|Y"|µ#—ÒÂ/ÌÜ´â€ÈõRn€ 5•UÕã4Œ%Ãç!J£Z±€=¬—óIÖ»c‡ðIà§z}kgÂàuªoXÊ2}éÞ:~´ÂÍ,`¶ ¦€2&"¾95•h§—¸%ÓY„t¥ÄþWGüAçÚ ˆ4•lN±`ÛÁY¬ª1€8Ä'Š¥³ê â 7ª¸¥¬ëÎéoGh8<`g^VG­™‚#Kª -–qøö³ÚÅ‘+œ`|©D,,? Ü’‚¸ŽOÅÙ{ ¾“3_€†|[âA!ÜR`Ù÷b¦êË ÔkºlK©Dº@ ²CX2äb:-yˆv!õ=Ô÷o;Èúp iT"ÞM’o†²˜©u¥Ò¤ãrM(fÓ,à)0%<šùê_ùŸþöW¿ú¨E £©vL 7¼¬e¦mûj$ ”ª/j1«’b«­² î#oÙsäåæ1üö߆r ýîIlŠõ<êîºëØÞÏèÏÃÈKuƒmï=¤.Y ¶ÀdÕÆç#cîv QՇޛBxRÝ0𾨕d†a]”®B QrxïO¥ÖNÖ!óÆVìRÞ º @Úš%dà™àΤ–¦Ì×ÅëT—NûK#dÈtî%Aå1f‹ M'Y‹Óþ1KÿEà©™6B$Ü’—B0Í.k·ÁK´^¾î5²Œ€D0R;­;©{Ò–fÈßc4g“ãô˜h'–"b ¦oˆ8)âLœ¼s#¥ŠÎù¶ùäÎ8Ï@ØL•„{7Qœ)Š7¾fàR'Y,ÈS ÈÄpXH Aµñ¥I)<û{vÿ)}9HÑ [ª-ÕÞM)n€¶\ǨݲëQȳøj• I¡kGÊ$8|[+ôQC~èýV´®ÖÄÕkͲÂdë oÙñ V6‘ⶉ\# È¿þ Žæìpzz1ÛZšë•”eÕ6O[P‹ Î"óhv÷²Oð矮Ï:sS5o¿f3’a °de¤ìT!þj[ví\&Ë ù>K`…–b¾ŽÄ)HÕS_­¿õÛ7h?`no»Q#{Ó§£¯IXšÀFmK§¡*ðî 1“5-Ê•‹RíNÕd²Õòb4AÊÅ‘7˜,kž¤x…Ì,‚XJ­¥‹‚Üѵk`à X ¬1€ BÄ’à,Ù-!<«¼XÊR\_ëb™l‡~Ö`)C(IŠŽ e„¥¨I}Ëò)ë>>“b ŲÑp4‚"ˆ_yxµ ïƒ%Âðá)[ÖMÉ“?„ î%ÔZŒ.pO~ûïºø_ƒÛeúmÜ#n ­À2$ŽÞü<«„ŸÅÁ?•w‚ÎÄ&ËÅBç©;§Á´°ìbá—òÕÿ7¾3›ÜoCi§Q] zšêþl÷Ü6øðî9mHxWüüuÝ!JX²ø>^Å>‘øÊ!<°3g@%pŸŒh©”ðâfK!)ä Ö«rä6%›Q†Ôh{!‚Y¡@ÓdWkÉðBFP„“UB‡Ç·$…cé^ú—mÅ8Z#YŠ‘y1PÀ’¥#Æ?½ßßH'uïE9{ªO9™ûQpQÊ>2ç«ó5‚¤@-å²<÷-œ¯Ð¦£ ¦%P#œ¶Ðl²]Gˆeq\>%øUů -&D °” ¸¥”b_é„‹ÍYyÛáOv÷62ιç’^Ð’Š2`Šê°zHq¾¬’FLR*˜='m~Ï„JÄõUUÖ’Y²úÖqsª-µ.‰ïÁ"‰g^¹/î¯;}[ïKÉR²º'(Κ“§f*3 è@ºÃöè`ãðt’òs,²o½OÿÛ¿wIÅšfÍ–txÈú¢Ò<+%À_y›²¢Y¢Õ¥»â²JÅY­€Q <°.õâÔÈ—;ŸüI—É¿ýío&$èØéwòõ…wEd ÀêÙ D6LSIAšSm%–pú–KÖ41álwŽ%‘ºï^m<©·…ð8LÀT±hfëè qx ¬ N)…CYÖRl#; ËíÚ´~_¢."w?‹á “x­]ÖAI ¨Aã;gL1Yǘ±1âq}AÖœ*T‚ψ㴬#¦€¼Û¬©à•D;Ò×Aùi÷ýw“?4WÜŸOÓ†ÑW¬©i‰Å¥êèXZªêè¶»gä×û'›>²£Så¨1–;q—¦aŒ§¼Iôm*^\_¯åÿ_þ1ƒM¥‹^b¶;¡ ÖQðRFmiZ…ø–b†oÉwmVnã¤Ó¨f|¾Žùzy„é¸ë:ÆžhjjIñ ¿’fÀO¶‘*Y£À ¥àÞ0ƒµäÓL _ЄKµäãäUµ;4ÖÞq€†—Õˆ!ûØ…#ıœ‚Þ~é#ÓT§ßQ81YÞRm'&‹¼KßqÕÑ2M|ól b4žæÉ=fɨYM‡lRR@ž P¡[ˆg@%¼“q&øDV¬°Ú©µ¬ªrˆÂjámGŠ  UEYNüÀŽQöõ½” ’(j“_ dËò®Vªg&µzàG@.®JÌÄæS{gÅå]éòU Ù¡¨bGô±æA /Ž_Ö2²M²e3¨2}u«é€Ó ì”d¥Rh¾¦<<_£b…–÷צ•ÿ˜w{ùøÜlºÓçíÅ£Ò0Ú‡X2Ëøæ±Ä°h÷²–§æ¹Ÿ(´}“éfpPÕ&‹€Œ`É -»Ið;dqOgK B^Ì”GÛÕ49‘²|_TŧVɼ¬8r`Y qUîjG'ÆéÖ˹rxÏ‹B/åWÿ¿ëthêÛÿѹmÚP_&æÛ¸CC3³I,™%3B{¨í±Eè0áOÑ©š‚“¬{†)¨?ÙR-ïQý®³ÿÍÅ«ò?ÿ.~õßQèâÐïf£ÔsJékÚ®Z»€«õ†T× YŠG#%Vȳ¦ƒ#3ˆTYKR:`Fèf†4LœGõ¥ÀêNDª9‘‰H©…R¶dhJ’‚‡àPhZÂ8¤ e˜Ìä)@ŠÃS˜ßÌ«m­ ï(*Lp"ýtZò SJ„'kËmAVÐQDhH–>ÐÝÈ·GAYA:j‘-)› c)…Óx8b"Ô"¤ÐWc†Á÷4Å©‹¸Óau›jl±FR˜L•8BKˆ¥¿ Óv¾ËÿôÓOýÕ&⑵#±vÌH¼Ij'%Î3ÿ½\cS莀l)…#ËÔˆY­^ÌIFCP‚0Oþ— é|ñþ´° è«Wo€nó#· “»yY¡¬©Ôˆ›VùRøLm"˜–ªX[vF‹‘{c7O A°Žd]*_Ð0†£E¦¼;Â#רÁUIåµ[,È1 éÜ bH X sqJu°†„+&µ^ͯ„¦ï-‰Âʬ ká‚v5–ܓԟ‰Î=†Xá$2/Å'«ÐïHá,)^ü {¦PkÇ´¾&ÙdqŽ’YN°@U&EJ-¦”*xM+G°ÍûLj1&Ž—›Úó£Ìº1dðH¼ùKŒŸT;ª…Ázš½× ¸¬jýü¢± ‰ >›ù¯ÿ’mj“ éµÓEÏׂfäZ„SÞ1}Çî«çh÷±C´n_ y,Ö¨e¬ £ÕQŒfþZ«õÅîdÿÐû]M½|L¼óuaæ÷5/kó„ó:ÂyüpAY³‰ÍÚßN»¸*"Èn`^Œî·”‚S3Æ®l4ÑüÐ$åÏaåþÔÔŸ‡×Q£p½Lâ@Ü0`)£ Ì&àí³yz0!†TÂJµ!ª’BÈ ˜ÍòÊõâ©)G›Mʲ#²Ä¯$B“+Ëj·TH¤Ò§6R#%”XòøM‚Y \  8|6DÀ ±Íh$¸ñ€N¸MÉX•”ÂhtÚ>\`Ù J¦¯ÁÆí~«u±ˆk Gcõ²dWGK)$¡Ì´“‚?uç¬ÄʘãY› Ä7d퀕 Mˆ¦M7¼I»åĺ°:j‡ÂÓIMv8Î[êë q”¤¬£@ Y;±„ã<¥jÚëŠj¾¨õVÙåTRU=d-Å {„ÄåõÐpµ™¸#Æ QžU´—-زԫà}ý,ëX Ÿ/•`~KÇaUÕ‰ÅL*dc;% ˜YVED \kϪj¼Å.Fwƒå'¦—oŒaƒu]D1°«ŒÃt1'ß<ÆS‚ß2~Ão«ª½cªmã{"î)œ·ôH£5IOÓÍŠ‰ Ëjg)°”jfK|‡oÂ4e)MM@Y&VBœ‰u'5ýºä‰ ¬#p1¾¸9ëeIž>¯Ÿ±ÕZm;|ï?êçcÌ÷ëõ½§Éî Ó‡™ýv#9+ÃÈÂmß²C0RFí–¦¢ NûNGŒOí)}}äh‡©„+Æ\©¤ ùûßÿ>Úy‡À(Ó¯E}é×Z ÛHö D „7¶¬*† ¬$°Z…@û…ˆÓÜ1)äéðí´yNî1]HE@¦ÐHuwžXî^œÄO‡7l`x€I¸RMÛØÛ >A Èg›yíàt YêM<å+oÈá#¤°Â;¨P­*fÉz 6mwc‡ïNn’‡{®Ú>bѧ¸=†ð@ :*!Û¾(tÔȵŽ)+èèxK¦\!¾”ØÍ@‡i!Å\#>&0SÒ•I ‚™,ÿ½¿ü£»Dëæ±;sžáž»ÔvŒ¡ÃoÎûàøðj¯Z)^¶Í†$¡ ÁOa|ÛêÎãÈvªø™ŽŸü?MòÅxÿ†çr>ÖÍ W/FAÙ|c#ÂlUÄeÃÅÝçÃЀDzCŠ{´½÷è0…J0•T. ÛK4íœL´øT]xRµëŽR… abdjBŒŽ I!¾ „d˜Ì2 )&˜6’`Yx×—œákÔào_pd©Õ ¼Úô{FšYáëLLy̪v £¥, IP oåʉnj&ŽŒYÜ%†h$κ@ýy2Z‚fëZXŠÉÒÑT¹˜Á+ìd,S¦€i_‰ #ÒNœ‰Ó±Ü¦–5ÀÈ)ôÃ~ Z7d_§‰!¯›R™{Q‚ФëtoÔk/ˆl¦Æµ´7WŽg–q:/²æÃïó‘Ò%>‚%[£•‡Ïë…ˆo…J¦<&D6² ^ÀD,»ÌRæ L ^-°*ÞNWhƒ–È,Hä<þ–8–Jn#ñçæ«×bsR¦OÖØt¥jdDãÅÀ‚ø)åUm6A “½wd¿x >+Ä$Û»FL§1,7@‰¬’º,qàüîÀ¦’ÕE,Ac2¥@ëZÜžà3ã¹%šÓ!ÍO¶Ée1ëå+RèdRð[.ßuA‰û™·ìynkm$3@Ç鈌ѲR1ÑvžOÝëÖV¸í"Ú‘^ÄðNIU»îXj4Ù„bòÈþ24²?fþR£_ý¯]:ÛT]ÈBº^hqòíkø?ð!¼X• óB˜%ß~e‰P{2çl«…gU‰huÌSˆc!‘u—B(ó]¸â©¹u™fq‚‚ž¾ª¦F‚q –©ÝÃÀ¬©bÁ>ГZá8_äÚñ¬‘Bˆ¤iïg‚çkÓöÕö,+V5>q:üæ¡Vý^5Ü[b缨©»¬¥|,Fbq\5³áš\•,¤?ÁëU ©¶Tõ‡?üáËù|¸ôçcFªßÌÁÀâ&·ÔÚ06²¸DÞ™€|ã! lˆ&~4^Ÿ/-µ@c8¼¥vhø 7@åÉbú‡ÿ‹¿Ë{c4áŸq^¯wWßû¹KãË)WÙx‘w2hl…²â6‚¬¤}™(»#‚H!à‹¥*MA²®—*ø_£Dš6rèÕ1œg˜ ¢kW£†hѾک*d:Ú!‹Ñ˜ yxøL‰lÓm*B-x…Õjd‰_ M•YH§Z8>Ï›SàŠà#GŒŒAªí^Z|gÅh¬€oÂΤÁÈÆÑeÚ¯T{ÁôÀšJÀôÂÜlv –í+Áb73)µSŽéj†41ekéÌlj”Ú\Ðxæ4› Bq˜k-F« ¾.!çŠJóâÛâ)(kI”Ķ7œ‚q»• ÑNШñ r4"¥ ÇÏ6ƒ`¾ ~µtV"FcRb¾¸ª's¢]¦ljgÄ礀º(±Äg;V̬¾)W"…¼T¿‡± Lê»þ€¯“\‚æ˜äì繕l³á4ïdñ2¿’Dp˜ÉÄp%D –JÚH­uaR@â7 Ù¢ …Í”D*‘ZÓé-Ø­…SUóc☄) (#°æ,Î#+yè¯oÊkÑäø>$ µ¶l_æ1L7†e{±/H \£ÆF) ¬iSŒè‹S  ;íz½¦ãé@IDAT<\9<‚¸cáÊñÅô¥È¢‰¥Ä|›þiÿ¾|@1B}-ÅL‰˜ODÌšG°¬9¤ÅTà®FpS™VkH È-yÛLÈy„–Úmã _„2$ýöhŒôᬭ ãC0ÉbB´ƒ LvHåÈR‰ãÛxLÁ„E"ºK•µÌhNVk î“óÌ’1&åRI‰Y“¼%_w)²Z|…&if~c6•¸¨Ò®.stkƒ¤«Q bT*lÉgáí2uq£'U!òîûšÒ'›á4’7öË¥hZ§\ßÒK•åïlœ¥ZVÂ×´!+tÎA ØÅÀq|m!N"ùví4žÂ¬¬xdöÎÿ‚·ßoùÛ¢öÖs¶mážDë@ó´_¾ñ€G ´ßîÈ{fú ³.»‚“¢G95„8>ÿ:óÝ*ëxNçyƒf³94YKæÏ³,YbŠ'«}(ç®VbŒDçÓ´<½SË >æT ‡SZê+ðÔ÷{ÿë¿ÿýï¾mÖhçßšÊv¶›SÀಷµÖ¥Ü•<gwÚç!S+8‡õW“˜³^–µð{ÿ~­ó׿þµ;­‘t¤üt~uo;8Œ`ãíò©EKÇlf± ò8öBÝù24±BdUÎ-¼yKE† ð‰Ó6¤^†ƒ@\­Á0{qšÈH4g½`¥ÚKœ[ßUêbòvª6ex&Ë€ ¢¼á-ëíÉŸ3”ýRÒrg%j™ø¶Ö$Û2ŽQ™.||Y¤I<¼!-]54KñfhH^¡÷ƒS"Ò`ÊkdYß¶¹¦ÍCJVLAlZG ŒSS&£¬£÷‰ouö3…oÿ]ÿwðÚm û²_³AÚ&ÄÒ ¸¯ =­8;j§ÃwΕÛ‡tzb:@ÌÈp Ì–Qoc‚Ì:F„¤Z:–ïým(­ˆ9uäµË7­¯Y›Ͳ‚q‹¬#B‹ Ö¹ÙZ"iš_ȶ ³ìØÛ/‚¾4ËÖQÁ™*̲µøëk‰¯#Á²é ·©@FÜI!`k$%¨{Aã!„H‘]‹ùæôѬZݕدÀÍ®/)œÞRíú.ÀéT¢Á™Ÿr}-·- L¹FÕ*l©°Zã vE”Ü|"–À^&æÁ'ÂWÛ^,Gôý"£¼I ™A,Ñœ ïô<#î4 ÓHS¸e3ä-5b‚Œ”#¸(›'KÇðÉ ™rSu·¼~™Œ„\r5„jRT_™€-Ž%ZæöåP,Í¡P‚ ŽÀ'‚T©y8³,H “²ýPƒDF㋇¨E39ä0-V¡}U˜ZÝÅ3Ù|SIá¹K¨é[íSw.°“™æþúZŸñ:6vó4Þ4[6IêÞSW¡“„<'ñËaö<«-EÍFÌž% ¸Ö©Yâ”UX ‚Ù8‚bÞRŠïÙ‹©Ðœbje R…8½eôj¹îšªúµ©e”›¡1(/&‹ÓÒH¤œC“ Ýã@¾÷_ï§z~§Kß°ñ ¼½wžíלëɵ#±‘Ì_ îZ ˜šãl#m Â:÷¾½§O–H‚pU|\UƒIùIç'ÿè'5äýÅßg¢ã€÷%ëú6 ϼûLRÌã7˜*#Y‹1-iZ2RZíÚ¸Ø6# Û&dV BGVQáYÞ$‰DÆòp|)²ejÊ™žO³¢P¯,µ°SØBŸÙMH$Ãg”;ä| ‚)[2KíV¨*/+ULV1ƒ@­}øA˜¸}áÜ1rµ¤êXvÊ;jAÛÈÞÝ‹•Û»{X€àĆßdcH¡uVR–øLëÞü8 ÓäÛ)ýZ Iy5é›7¡?‹ù]Þïºt;%¨µ¦3ÃËêÛ·5ˆSÒ̉(T.n¿OG6\ë|öŽŒCŸˆlj®²%>ÍDÒùö_þñ#Êšn΂¼y£;Á†iBt¥dH¸hæ8Ó±”²tD¼BËs"ïÃàPÒ"²¸’§T%]ˆ&oÌ  œZB³u¯:^Ù›c©<¤Ø²`ËK³Q0`Ëvd©Ü Ì’5$P °« oS6²½(Aƒ3¸’tàértŸCƒÔ«³2<\•`MîÑÄÑ—lš–jÑ»BqÝwÝÓi<¸xâÔð{^dõ%§¦‚æA€X ´žÎ˜M„ûÄhR`î7d…eá>mý°À2Ù ‰L“,X`¹.ñyÖR¶Ë×˽oTz']eKÞ’!Èc–Fäm‰'ñ.ŒÚÉmZ–¿Õ@tðSÞ0_[¾Q‘©‰;G8ƒ°»6…–b©²šGŠNj‘RVØeµDC–¢YÚ»—¿¦–Ôúvׯ+¯‹Tµ•k„ˆ›Í%èv%[ žY†àëeí˜Ôæ—¢¡dh§ø}zê®S¾©Š•„c "¯Ê’5pA#Ѩ%(`Ô&ÐuP³µ8¼rU @îÞ«)DÛ ø-ëÕÆe™oæí·-£A °F–îgú] øëWµ¬å°&æ JHfU&NQ6BUÑ:ß¶ oèãCÌzº¾ßøÈRÈîîAS•?½?E" ˆ„GÛ™Ò—•ÂÖ mh@„øj] ©ZÀW9$“Íô­5#ÔA (€7Â;ü˜Ÿx×uWý‹Žv5-(+nrƒÃu„RÛ©¥‘ÅçÛ Ðuß–-‰X ìÎH˜ªì^-À3|qj–8b篶“‘eRënÙä¥Ò×—µ—Ľ}~}ÈN¬G;""˜rËW-j- ˜&¯ š¦t|± ¡ð-æ_¯ó7ØÈî½_»ÄÛòö.h¿¶Ï&Ü$ç8ž{Ï´Ž‚oT…ÔÐ&[‰¥¬ŽÌ!)YY¸%…1¥Ä¼§øóßsøóŸÿœ²Ö)·×K&Žåv$`JØ™þúáÍOÊ™´YˆÌtœ§,s‰ùzÉ¢‰ žü9"„»{+:s1ñhâf®¼»‹f¸We²M’l_‹lSM%N\P 7?AˆuL¼ Ò·¬¶Bˤµe&[ydúbY¾¬R÷âyAñÝîêÔxã9._%hê Œêºð¤ØjÛˆ%f4qcDKÈ eé”Ê'EΛ nŒÈò²[ªad™b´$Á)HÑç{6¿÷_&ë—L¢)oÙÌ<œ`ËíeA£¯Ïµ,¼ZÙ6%Õ’w™ˆH1"¼S„4•»š•“¢l©cåþ‚@Éw™Ÿ›Òºî›m `q Ó<&4ßÃë.Å´d•˜œ)µY[ƒtÀ²‰£Q … ±d V뼨!á8NÕßt昵0ag a”-š. `ÙÖHO-²!+Œd@öÌøÚ¬* ý'y²©äGŸ`K(Øl3£­‹l­yµŠ¿9¶Œ,ëe(E¡Ç®#£€P,…YÇZÀïóIHªÚ PPU ã´q},›³rÞ²ñx… lBñÄÑÔ"ð6Òœº ;¨ÎYœl½ OÄfË&¡MiŒ–í(Þ%mB/^#yÙÒ/ucU I€ gð¬K¢°S°ìpbJµìPÄ Q/4K`'b“b:ZK©•—…0]ÆWÂJ¡1x æ—*Fˆ&@à3Ý£up-ûp"¥–IÏ!X*|à³Mµh!¼Øx˜Ý4ª x%,,þõצ8ÿ©õÙ©ËNi m¡1!MÒÏY¿¿TZÕ=ªZˆÀÌ8íQé e;šá—’Èîé.zˬ°Ç^JLM–Ýjh²l›`Ây% ,¾2²Ñ0q L`išZvÜ´¶߯©±N Ž~×¥›àçæ³¡¾ºÉz™Ä X²»]sª‚Çt¼ùUX‰e&Æ nB…qF¨p ®c_ è¥ÖTYöùß…ðÿï´‘4ÑœyúMÒÒð2f»ú’µ‹Þ§ÆfFEP¨Ä¥l§@fµÅËŠkÍGSÞ–4U O™WÅ+a´‘-5ÒaØE4SŠGcéÊb«¥ âg–¡$žY*´…'óJ‰•$E_€€ÆRL'ðäÞ/Øô¯.º»¦~FE­ç«‡¨$±‡SI§Q—L¢W®CÈ6ª@ q„jŵ@  ¬Ö²*ËdÝf£©„Ç„óªbòëÛQð‘ãÔØÖ&ùß~õÓÐfûÜÿûßÿ¶;3ÔëîØ¨uorÛ±´5Ë#Aî2ƒÏ숙V/©ª®Þ«]—³ÉçòUÛÕz;ÁºäýòO_~)üë_ÿòÕ³.Á‹¥ù†ii†>Y\w³ÙK·ws¶SHdÙj÷rŽæý§Ü¶¦‹¥­¡ñ½p:7)ˆyhâXÂIAx¨Pk…^­qÛIyÝáª(àì`Û,fZíXš|Y…LUûÚ¦¶lþMB*„× š¡F|½dÍߦôªÍ­âêD£Ï€vtbü}²Øšò3ñóHâ3úõÅgb\!ZCGv•éÀ͉‰¦ªîHÓ6^ @“‰vš=HA 4Y" ?ÎR†$nŒßüæ7–L#…LìpÌæ*lGíZ6M̲‰ãHY2™?¢Ï›Ð.º=Hu·øW WˆüþøÇ?¢Êá!˜˜¢éíÁ¬z#°¦IåitÞ¹øÖ®šF ¼»A¡8~Û/À/õt8¹r«)Ž^m%Oþ«2þÄãß%bÛä5JY`xLóCÒ,ÅW+ûlñÜChÕ¦¡áy¦PÉ9Ó§©–˜ŽEì„ÝbÌOÌïÿ¸Ø Lœ¥çžôõ…Η͖­\¼ÉÛ#©g7çô {9Î’oÎjÅF³l‚{‰¦5¬£À.š_J‰ØÖàu·Ótꋃ€/išJ€ ³©dÑð>…jét–Ñ,öªQeÉdÛ>DVÌL§1x"ø8⮑ËÇV…ïKÿðšI}èMëE±C &ΦÇC¶;ˆ‘Ì ±5Vª*x;µ„Û‚}‰Û5sž¬­aÒLd› 칓õ9¥ÊëÇÿã4Û'ÞÉû7Ó(ÔŽò3ÝË¥,e-ÅÄ>Še x)fm³ÚJìÔîØ³é³ël}î4’%Ø-:&Y ® óÄá¢9%'Ü]„㔨єe"ÊU‰A Šw¶5åUiÁKñU•M ÈÚHⲬù!eëh0Kµ‘ºã i âªbGy†C­½£áyM¥à¼*â‚&©£-SÒ`oà”“U˜æÔÔ:F=íßÏ~ä&™¦ B½Äf`w—@]UŠ8žYÖZ•%2·Tèb™Ó’á4°GՎ뛦ڧâå"«•bÐyKQ‚Æ,»%†œ;Ïdžm 1|x)EKMÓo2Š5«+‚9øÈÆ×~cµI„8LL™Ú–â•‹•[Æ)Æ O™ÂðD&ŸEFƒˆ§l6UO]ŸINÆ’U[¿ãîâÑiײÎM–­D\£¦‡¨e •8áÍöÃA?¾RnŒD6CÁ–²úš‡?³>Ó a†çs©¶Ù®Ý pœhJlGª/GľȶœE¦vO˜2ÑÙW8Žˆ¯¼yRàá&QŽ£¾ÀyÞx³}ù’T| øÝÏ5âk‘¾¬r¾!1){nÝí(üþ³ÿÁ­F·ùV³Õq¸e[ƒ´wÁ8fžF2pïL‡³íÈ¢µäYúøÌF,mP#/…á@ñÓá—;„”„,`hìw¿û݇Úuñ«ÿ©™Áœº7*¿±Û2Âf3ÃöØ•-ÅK ?ï™çN©¢S‹©!·M·^`žÆC,u() ¢Q·\,•N4%ÊÓirR 6†#Å¡CÖscæn`jY #pβ–pYfžŽšk©j‹¥T­)&)hfñ¤à¤x]toÙ •ër®´ÝÊUãÕ,®½”28vw‰˜b]2œR§å1?[|¾ÎHÇGffÈOP "«8~¸¥l`1“­{ ŽeÊâX—EÐE‹¾ÂsjµÃ”bhUÁ-Õ6• ©oÃL|“8É›L'MüOÌ—)½)Π¥ö^ý²÷¶Ó•«wJÈȪÚc;êp ïd vFÁ ^,å¶¥1àɦÃCj!›/vò²Œ8 £U ˜'\` Là½Iž­õ—o¼.‰49fÊfÓg ©ñ@&f¶¬‹ñàb4¿ëòEùÕø‡þãéóOX(ôÐü  ]ªMë‚e×¢¬M¹¦âñÃW[‰¥rÛ‰©ŠˆFjë±$ŽFЉù ‰DÀIùU(ÿî§øósÍ.¥ojõ4 ] ˆl 6I-ðb)…²¼˜‰ëÂSs+Šã¸î]ôºàKuòZã°Í)FÈ€L¾îìy½¸ øµëæ?ZÏÕQÂZªÂAp˜}¹XÝRDd‘z)Ñ´Á,Å8@q:Ä+á¥àwL-)SÈhYŽ¥Bb*gbéN ^/Ì‘!ýã3iòhÍÜ9‹ oƒ.ò6Bsdjâ–uáu7¤B¸SXbaÉ 0ÙƒKÃ('$²¬@“K!4›ªR)^#' ÖÔFÌsqÿñcà'Þ üo¿´`Û ÁQÐîx“óf3m}-㊓ºÉÛäUµ¯JBè! Á9«mïôS³¬)ŽÞï!|ïø“}jg¶Óh;m )Qy©®&ÐMâJ•ê|Z®ÜüöEpµôUµ»8Ž‹™û_žÕ¨lCâh¤˜¸3À#tÕŒgé+{^Š”fœ<‹¦–møwòüyãáxÖ,25Kžx·/Üoç#ÉMæçvÑ dGÖs+—Õ†³d-Oó·áDSfº$@-˜`ûÀ+,Öh´J¨‰¥Ò¯œ·¼ù–]ÔÉ ª¢É,yjá⤚¿‘XŠ9Ê>ŸÐjT¡˜`üF²Ä§‰ üÐ\8CRÓ—>対gÐb­ÅMh~1SÂZî -Cx >f¹»¢óiwbxw$&q8[ ÁÓóàbž`·\ïDËf#sÚf1NÙ¶¯P뛆CÞ$–Y?C•²<“=fÉ0ó]P1ŽÙmÍ_ÏÕE;¿»õù×»¯ž1~úé'»ƒôÃ!ókÔ0í%²Ø¼ Æ»!á½÷ÍÜrœÞ¾Úš’–|70œ‚^¶IÙ6¼1\‚ø¬îõ Q¢V‰¥õÏÿ0ÄW6½…4mGÄ yF¿ŽKóðFb˜ÌÀ†±äCº,Õ.g›²Ô”‡ÐWbKq·œ¸a ¤:ïSgå ÄÃë‚ß µh)E Ä•¤¨„I¡énŒ ÛP­SWȤ,éÃS7dóÄä#ð”ã+3DÓ Û©l7§‡O°1,• `ú(©BfɤX½àD”$«#Äñ"-ñ1=k;X©5m¼Gõìb–>)µ²žF,wzõ­J*²áż¬@¹˜‰1»îÊ™. ¨° ŽBW³Øoÿ ¾ËÜljZܾ]4I¾Žh=`Y%U-µ[ Ç^útk/6äG†+·tpü²¼2È€”»=¾_þ™ÈççÔ_šª}—¬«0å¦2É#yî 8@ULLD`ÔðКà tž•ÔÝZÖ]W*‘§ú|/êNŽLJ‰,0~_d[âl1ª¥,Ø´h@åt ‰Thûé«UØXª’V’ßü‰##ˆ5 ¤ƒÏ*§&KPPIâ‘+畨20Ä’¦ZLÞRP-_Š`LK­©ð+ÁÒÉrJŽÑù»@­˜8‚ ±)31“ÒÎR /®—„Z¤ ÷Rlã‰çãб<=Þ]”»ôø ³' H"¶) X6šZV*©œÀ†‡ÁWüúŠ)‹ÒëGwN­›I‚õÿÐVf‡ñ€ê-[.%Û>µÁ©a2U@Á,¥”%ÙOÅ/·¦Xv¾F”Yj1¤X}·sÙø©á¤Ü2e1|Ì#ô\:FG@îfꊕHus[6Fú¼¦#L|v†ûÌ(ÓäÍ™8=ú© jº¾-yæžSç.·DèÂõDE¶#£@A¯–ñ!<Î=DÖ¥‡+éxõJ'GI‡ÙF(AVë¢)ìxÇ—Ê|mªj¦5ñhD2Y£“…PТĮë%öŒøcýi~øçüš_ šªw^ºƒßHbœ® ¦ÀäÆ3*NL_-?¤mò ™Ѽ(à K E“ïˆRS5C îŸýHý°y}û §©…^ `6âŒ8œ‰y]pàC€}ʲÈHãAª-gÊy´9åD€Lܲ‡YàzI50… “xš=xó©#%¶Üµ¸AÌ©=m_¯bqdM•×NL¤ùO§÷ËS€°×í´ Ë6ª²UÕ Í£A˜-(TåCE\¯ñø‰óŒ2OÜ Ü®o/K¤lLT5L`žËI1Ö‘¦¾8 FSVŒ@YV ¿@VŒo;G=žÏ׸4Yd>šíˆâtDæTÈ|±[÷˜Ÿ{¿ çåÓ¨”u¤É‹Y¸a<_Ó˜FjùP^ÏšB`7pß[¦É³–|‚ªûr+ïèຠbÙ;Í3÷ÚÜ ?·ŸþY#š®BoͶf˜®N°wPkHËj]âöˆŸQ.ˆƒÐ.ÐÔò)4Û„”UR ’!T"…“7€ÓSè ÐpŒÁù qŠ¥ê¥“&0åîpó´—&‰ Q•GðÊÕB0_64¯—ð7Z²]÷ŽSÊFp2H"– i#©¡I1H‚tXqåZ̤ B# p>çIÔbé`ysÖ=2O!AÌb|–ìô·,¥ŸÔÃ}½XÛ ²vmÇ<¬cKÃ(am$вK“×K .°ÌŠ"ÜħƒY;Sy)YÖ‹TGt.ªz9æ!ÅTºNj€j,##j ¬‡Æ‹Ûä×62Ma„7?³‹yU–øíÂ̈\6}qkr ¥*‡âè"†dʑѤìý¨<Ö±xð¤ðaø¼xšŽË$AGÝmQU Ÿx¯ì¶P¯â/‚&iï8f3BLcìâÂe!<-_`ªÐlâf ;A]dáÞSyÝÉ'(P[V•@&+sjéXê®Ü0†#+‘]w) šc?Šoó‡ÅB„™Â™”¦ÆI™,2A“úü¯º¾Ç9ÿõ‰î½Ú‘p·Š^…¥ø&iN8Ð6»"²ðùÊyCÛcšâêvïG)tl¹+>…D®VÊ_ƒ¦øc^/Bœƒˆíx?tÿØÝô1Bi° r.`Kï+I_¡ÒŒæ`Y4 @d±ÔÝ )—‚/›S95%pg¥‘Q™‚ Àì!bä6hIÜòní´áÓT‹µ“e]ÀÇ'%°°‚ÊT ‹6µ›S-sûñM‹Ó |Ljbc >Z^Àd"ìÒè^­,Ž#Ò¢dŸ æ¤l‰ ¶%% “—bµÈîÄp£Fã!<šŽR‚†äS ‘"hI~õÈj1Ù–ù #ÐR³ ç³ÊGÔôÆ)@J¡ý† oŒ>©ªL’”ýÚÔ˜²8‰¤§Ópt²6ŦŒÓÁ½èa°¤æ$ùÄ“205"MÛ¨ð{ÎZ„ ()n~/R.ÆLçÜqÏ=וj§J,‘Ñ2²Cšž&ÉwVìHâ»Ópî;°rÌÆC£`òJÚ~±%ü5ÐûgrÌ»éþÏÿU˜Biíj´ñ$ãÿ¿†ø_þò½:RK»3ƒvM² ©x§aª¶Üªy†° d4ñ,&v‰ûJKwü>íT Äxh w,~ʧKñ{_ýëÞœZ´5H·Yßœ¾Y*”r,h¬íãlƒ@ˆǤ/¥ª µ[³ýà T\9|‚UÆ`„-ŘvÊȺÛl„>õ>¯i4r4vO’8M:Ð$˜õå¥è¤`IÁŽ^Œße+©WL ì±­J6ÂM†4Û“<[vqyúmDˆ˜oÉ‹I)t›’òjéTÕç&M^ L`ÚZVE bÂËQ"kYkKú¬¾M(ŽðhçÙñc‚-?|jø‡nÈꥩÚ‚%°Øå¶YYËLV`6&h ÛÉâˆÑÔ:Ÿöˆ†ßùížH3(l™8¦î®³û ÈÄìóßlþ¼W“oLÒTí¥QÏn¯7d3ð˜pÌŽÈX¼WÙö•ß~+lÙC&ñÔ ;šSE‹9-aÖFðT:–¬ëÛÖ€ÍÀ£ñ^jé`¶ ÔrEÐlJÊ-ùºO¿ŽÕey‚¼ZÑ‚ZËù›¬;¢u{!K¤×¸Ÿ§qæéÀ-k¤J’fáCð³UYÖzOÁÊ©)ÔŽW¢©]LÕxȵì°Žáb&Å;LvI%îH‘wªR» 1•ôÃnM1› Y6˜˜>2+%͆(‰ÖáÀNÊ• 0ãuey#!haÚ6¢ü—ŸTɱ“ã©o'–O—ÓBÎY×¾6¢:Gî]%h>r#võ‚„w4§ò}[À[òÉBT\UxKY&ÎbòÍo™ ´Ä·4€F6if`TXwxÇê4ÜUÅR 9&Ž€‡ÀªÓ뱬KâŸøÕ½¸Žv$¨¯Ö–ïÆÓTÌ»-"óM’B÷….«”‡G¨6D*\`ƒ¶V¶Ž¥xURµ(h˜Èi*Ghâ=`j¦R›<þJ ÖýËg0ÜOŒâ¤IX;x¦©`3`Š; ×Úßý}¿á¿~糧BûjGFjƒÑ<‚”ÌãŠ7˜˜µ œÍ$Î ïð\»4Ç )Àé-ékŽ!¿óYSÿ¾ªùò‰íïðµ#Ýä²:Éá¼ÏFÏÓÄÚÈWÍ„J¼[xä‡xnï&‡¨ºoË=8ÈéóÔ(¨ò–À–ðšÞšMˆSU³µµÌH•—³¦Ác¶ëh–% £Ål ômMÜÓ¡pV ¨ (n*x:‚šFÛ IÖwÎNŽcH…½ôê>Ù”ZΔ×· átp(4†eÝm¤[™Ž{^ ¢_À¤e é´7@ã©U•Ȳ¶ÓòΊ †+IÜlJ,ùöõß´ÝK’dÇ‘¬á¦ôœp@¹à«¸;N¸g> rFX@~þ­Ã¬+-Df´ æjjjæ~<"Ÿ•€›Ó$ÛN"÷3ð%æÝÔËŽŒÁè›A»ô̧R8î@Ð^[¤ªB'€³-ˆY‚U!Á‡Ù^,ÃãKQ«5ÎNÆ{}?'T²òýòO}­‹¦Zˆ›¶ Ù¾6©…ðø"L¡lGtŸ ÁC*wVõå}Æ)Eª‘0]‰”‰_b @®Ö+K¹kÜÕ’jòN&`ªòMÒ¥…$« 뽨r㼂R&®QK4 (43¦gJ3BåíbDÆÄ/$Ò$¤.ÖÃá˜Ê‚oø–Ê;±Rb8‘²‹wŒj-3Y8¯—a Vk`ÿ^Üw¢ÙJ¦O'e^ gb^ajJjg)ÕÚÁ#`:IñfˆÖ^&‹Ï¤ x© ŒBÇx?•x^¬{A&…)`=‹(Sö< ›±ncÚ(cq)1ÓI½²¡ÈhZÂ!h3Y ,DŒÃ'b‚®5>ƒ§C!rÈð‚†‰iÈŽ¦ Þ¹Tݧyíìlíêù §ƒ9 YL)§ñfl4ˆ³NSÓÎDm])åb&õAëõLVk^‹ô›¹€3`4^Êø^DŒaã<À# 3L¾]„“Ec Þká ®Šgu‘…x§“…ð¤,ÉRàÚTµûÓ[OdŽFÓT)÷ò£#%ö¿›9Ã=Í_Ï8Ü^ÆD˜òs@Ï»‡@ÖT¥âÿö÷ãßð~Žs~ùǦÝü}ü¶4¿î:Š™s6¹¸ß{nßá0'ÎÄãŸÝ^tµÊ1wzÕJ9ðÚɺH¼»/ ¿©dß|}…óSÍud5¥¯hA_k¾©€V *qH{´l›ÀUĻŒ³ÀÔî¾ZœAš•H øL\aMÅ]Wƒ LNßF©t0«*hª6ÂcBZ¢õ,0“\b/‡,ƒrS)Äl¬@J ß<‚:ʺBÀÑJ‘UÕ×Ìn‚×”©Ä©E¨¥_œOŸOŸ™Á’DZ̫%Kœ .Í)eY-ͦXLÙ˜Z¤#Í+œ8¦K U•%0¼8Áø8–LI3‹‘ùtÐ,ë.ho;¯ý]¯‘~ti }Me›¹±ù3èó½Â»Šcì$›ª£Fë• :“¥Ú£í(³Î h¹ò$h¤ ¶7 %p¿ õÚñ½ŸÉQnA{ÑÎfuo_íQÊâL ·±Þ’‰ßÐ,Ëò÷ÚN¦sv•‹¬Z MÕV^Š`K)óã¾ÚR^€Ê=PKvt¯k/VRUƒ™_ ‹/æ{|xÏg )è‘ ¬œ7¬VÌðÉö:õÖíq+§#ïâK €R]Ú]MSËCdÅ•h6€Âá5B†„W(¦ÌgË àµ£Oœ‚yÐ¤Ò ´”‚°u‘J*¾£µG„ŽRmåí"PÕí3òªÂ[J‘UÅ÷8¨¹3–;L]šJ‰¸ö¬ˆ OœUééD*9ߊöõðiG´”«l¡BTvš‚&æáÍjÄz”°Jàh<¤ÂR6ÀàÀ”Åw‹L„E†dd-SS8}ÙÀ Ûy½âØcÑ,‹¥¤FáÅ›Á‰Ù/ZÏ»ÝYFz…ˆõjB1#b›h‚{ß²ïö¤4¢\Ào<½vòp1¦F¼ f8 ‚€'Õ0÷—Jé$;! ËZ Ú,2„uÍÔÒõkB8²v¼,áªÐxKŸˆÙx´~¦ÖÀh²OÁ'ëÕÂ3g®š -ã3kJJ*A^Ê15ýÅ/~ñ{Á¿ÿþ{*mYÓmD_M-ÛŽ½·£MØRÎÌÉSÃaÛ6eÁ–ø8îjµÚ®®îÈtpt±ÄÙÒTÈŸ>}êÄR{Ÿ÷m¼Ö:ԑ饩ֲÀZóöÎÚÈ‚–ªš™g›­8¾”€¦)‘‚¤_©Ç <\Ç·”ÍBÄ+)Æé µ {QÎZBÅÊ•xiXzQ\ðy½8g|²€š€!tSSÞ ¦8ZK1>0/ EÜ ˆ[ÞÏY–2M…kŠféz"$[kYS­ç©lH Z+‘ÕTk©–WÅÌ蔜ÆI/XG"L\¡*)R)¥ÖW,eÉL‹ÍR#1‚}]ùóa®.‚Œ¸’,ù5|Ê@F“ ðÿýü¡ú&4mØ~sjÇ A3g{1ØH–pÌvÁ‹í"5žòÙÆõÕQ^–‚¥’ø@xR=KAc«òíÿKû5ÎãðóâMØm§ìÅ{f7j“cÞ'¨0D|7ü¶ÐƒæÓAF›oã!(±w’hÀp|3t˜b4V;N‚bÞüpRÉFóE`›‚‡Ð¬_¹Z…pVÇ÷ÑÐ÷¿Ä˜^b¾%Ð…ï=9Íî°¾RM¶ ‹¯\/³]ÄHW®ÙìNS@èV×y ‚øjÅ¥Ð, #~ç׫‘pÑ*AHÙZݵŽ`jâRȉ§ð¦Z„;³e…q€ÕZš¡ÂÚùjÖÝðæ÷PÄ<š³mÈâîOâÙF†C (·‹ž2°yê¨ö|­ÙÃs±šÒ)@4CRpµx|T6.„—B(àfuUB¶ÉLö>¥T|Á¹D×3¨vd²²‰ š¸¬Zx‚vz\ïM¥ù–y" ÈS[Öò^5}17^GoÉ*¯P*A @‰À1öÙ­läUyí]熉e?h:¶}'IÊ£¡l±y˜¬XÓy“Ý ooN¡çÛ£áÓÇo;¼¦Y2ARb"|Ëd;žBßê¦|*/CHßJaqâÝà¶@ͦd¯Í=>S‚™UˆüæÏtzÑ‘µ»®}‡É”«Ê'ˆ¹½C|\ðèô±ÿø'}Ž¢Í’ÕKlªbB é¨ÈŽ…IV PÜÀÍ*,Õ4¶ œ­ëcÐÉÄÌk*èé¨í Å@?ûs¿Èï0߯ó0ɽV ÃëR »Í ˜NIhÔâinil ¥ª ñíbUV(ˆŽ&¸‚e´²îý@[èˆ<HÏ·r¦P• ßSK™! kPÜØq ‚t*ÈâS¶Ä‰L³%M'ï¬ Œ³½µ^§Éâ+L—‚« —¢_—ûTbG U(Xö°,©M¿G/Ïd<)¡9•0‡,+¨‹ÍR­ªC}>} }ÏKJ#K)ÞÖ ¼e&[‹æ”H…+¬µOòß|óM4Ù—˜OvÉÒdšj×ù=ÐeÈúF+òâ6eÙ`@Ûgp)¤/vÂ8Mœm ™Ja–JM ûC¨÷ª•¿;p uäMh¶z6U¯kãIÁ›óÞ±ÔÙØÀDp˜­½¡Å” §Ï:½´w¸ ãó^Ôt:º5mÇî4Š‚ìYóÄ=YK†–áXv2WæÄ~ãkdæå¯iÔ^”Ëç+K… Ðßv”7‰áJpZî-( ŸÎ”ÉŠÍrgH“rõB ¸ZäÊC,Ûr|`ˆ¥ râöK¶^Üœ½r1ñbVÀÈ’Õô¢œ·‘m'‚#¥¯%ò‘¸FÒ—N%}qØÞeR•;ã(t&øâ,)ˆ*"=Áõ¤ÌÌ’=ü×yµ”›Áå)ˆÃ› ¢—’AW 7Oå-!Ì)ÙTÈ M‚)%`²”!Ô˜ØOá‘SÈû„?… µSK\ …¼dÎ%L“÷½ÿ7Pè.þSc§êwßuqÿ’îùΤS2$Ü„Íf`àø ‰çÇe–eóh¡¥¼˜¯¤aÌpí¤´“ª¥”ßûÿøïAù¦Ã?þñÊYóo0‘¤XÁFÅ„ ´ÄñF!ðˆ:Ãî6ß#Fˆ–~»ã= ~‚qÆ Ÿ'roäÔ´c8Fe&ŒÞF™˜ç-MÄ<Ü2©ÔxËJ(WÔB\YvÎåùq«K„8b]"81Ó±{¥Ü¤ïÐL"Åã3A'YŠÚ†GS¢vƒÕÇã€+çÂÙj§ýeÔ,ï ¡_l¶JjM°%f{Ál’‰ðæW%(¥ÖÒ0 •´ÙfÊÖT¼ŽÑzcÚ¤Ú cô@³½Äû¡¥ñL¢k Ñš5¿yÉÁ¡Æœhjá  "%èóhL-Î.‰¸1šÄAœq§J­çî—^ûSSo›‰·ëk’ÊØ[0€µlòMÛ¾š\*³„3Ut¤H­ELÙúFËW>r")H1q X@ª¬òbxqdRÑ€˜,°+'ª…Û¦ Ç}q¹r)±¬*ÂüB‘ÀEE“"®ÏpXj–Êù`Ù¼”ªÈøÑ:)Ö$ÞRÄGúùê³*Ø –½ÿ( ‰S‹ÈjënÞö-‘!FKÕš„,D sBàʲ”J÷})±L¿¦–mMªF$ÎHÕgmÊ)I=‰ç­¬›¬;°í×=~/I}kÝ“f](§Ð¦´Ë 0#Ø©À²*AOêñ]ÔÖ*Q)¶C(°Üd*(°,HÝ·›rŸ5Ç©°F4ñ{—G–ª$ܲqë.Ö(:c@4AÃÔ‚À,™Ãó²üåý«åüø)(ô1XªÙŒÐœUAk§Ü9løÈmVŒiàÝQkA9Ù¦uJ\ÇnªŽÂ:* WžobY ¤ÄíSmåmS,¨„¯ß#ÔŽBO3Ë»HU‰$[¡’°Œ_ þ~iÑT14±WÔ›ÿÿò?þHAÖ®'UÇÄy)žÙf‚öò¿üCÓ¿`k v'0Ñ×Rß~<l§h1‘›°]4¡”ÀÙ23sß^T¡uJh‰88æ]9Í&4ƒ¬*ÿð÷ÍÙ®ËPþþúõ§†Ñ´ íhcФeKÝ!F3)ËJZb:7Ï‘I‰e³tpû²© "—ªWd^-Ï4E–ezÁï%ÀG›‹ßFŒ±]í¨\6¦òbübK%5"Õ !âh4FÛx8ý€QÝK  ÒÞ©QðNÅïÊÅÇLªý™ZM7m %Ó‚§ÓÖ0Óï#ˆÖôI1Kdq%Yˆ%ðZ¨¥žx ÷ɉL!Yž”BAÝyH·z‚U)³–hT.6(@6æ·ß~»Ž|Šà €Ö%ASݶÌÚDU4ÛqXcót¤2´ *>)›ª)È –ã/NJ;œDê÷¿ÿ} /ñˆv¡ &hHãA´†ð݈¾–²Í)Þ6!ìžê¡CÚEÌMn™…¨­—¥XªP‰ ¯£@V ®Küé7³@¶ùGЈ%K„S%FöúJ¶“)® B…{.M R &K![») J X…JÈÄïĽ-ìÂxR½ü㘰}Qƒðíb}ô“µµæºv!h¼R&ˤX  ¤Ë­ƒUèƒ,ß^€mD‰îUÉ6ÆÑ}>b´U#C¯‡rÑ¿\ â¬áKå{Õ6s"p`|¨|šF²–²=>Si­J?k6ÌfŒ@ÁúòÊÈuKP×À“Kº™à–h8JjÙ|FiŸt¤l£éïc©ˆ!>e垊‡”eÌšÆiY…ð• Š•0´˜ øp^Ì:¦Ã~"úµã§&FЗÙE±Í–MÒià;: R(…–a2w]D©w}¦…bÙ æoB§GkkÀ–×nÎ933ã'eÂ^º!–+QXm ¼1j-µs€;á¡‘ÂC^ß”Å)Y%héÛ—ˆ¦…X¡óô-ê{/L¿mB ؈7§¬åvAAXÏ Áoá ^b>¨·}j¶Ð^ĵðʧ]À×˾‘ Æk˜‚8‰@h2ð)ó!ÔB0{ –”-ÍÃ3ˆø²ÀGÊÀ²@/j?†Õ þ*óÿK!Õz‰ÍlÈíŲŽN‡†G6à'ˆÚŽä³²÷ˆ0Ì”CÄt´@ꈃ!>Ï ¼SU²áÃ#ÛÎá=‡‰_ ß!_#œ§F¡^=ý>^ÔT¹>AµÝ%;¥6X šÔúJi!%Ïךe©&¬cž~j@k©å)(ç+é;ñª€ u§ìY•·¬)Ma4"J,Ëâ#ˆkÙ;€ #ª¯¥ò.ü½®—ò¬yˆ7[}ñf¾-He=£æ!e<žAŠõ- É—ÂÔ4­²`f©Š!ô•Œ˜füÊyÛÁìíŽršh~윤® •tU½ë C±Åp"ëè½W*«EcÊÅÍM³ªšÉZŠáâ:îÂuÛfF__ r“XÖÅ$íM*P@<þSà‘…¿±J€÷Úi&Û´æÄÁl†u¬¯Yƒµ`ša8%ÓZ ¤Äd3dxÊüÇ­¦æi#ˆØOÊláÃ@,81^Y#¥ ‰Y‰¬*)àÆN"ËWÈ«íXÝYs&w…IM¹Ùò˜ºãÐç-˜²p²¥ý ¼|—z‚/7¾Â6h˜–¼’ÆÇ @IDAT&ilšuÄ÷«“/üúÆßô¨c^ ioF;Û‘ŠƒÐ¨üÝLkyß‚³5ë#ÚxLË y8„EÆ×šÈL­?ûÃßxGì7Bóð´È›aKà= ¥©¶”2á8 ÷*óEµ%r“S/Kû Ds\RZ°JàȽüæf`Ð*)u¥H剫ÔâM µªÄÈ VÛÀÀŠ%ÛŠ§Ã‰#[ÐÀŽ;±h–Rðtj-Îî7Þ Ó@¼-Åm9o€_µto§‘ÍÃ÷tÄ %fªšœ2³Ê,¯ªßlm²€g©õ±_¹}%•7¿Ølióh|šb‚[ôò_þé·5ˆ›aÝ £6m©&ägmƒNÛ¨bÓ†`’â‰ä-L4ˆÀÙR@hÀp UY Šy4'ÙÒo ¾ö—|§—öé÷üÐ56¤ ÞÜ ãuJÛR‰un æï2ˆq²ÄÅín¾“‰#F³YåL¬/Ï€8UX¯Á-ŲªÄªH1l/ "[À»œ²ÀR‚dë•OÞ®•{ÍV_x4ïÀ¤œ„A‰`JYÂ5>Ú‚8ͦEdYä©Flo;ôV›G°ý²}A¹¦£J‹zubÚµ)fÝIUe³ÖçʾºÐQ•.æµë"¥Ï+/•Ž* ßfˆòYf¹a,u¡ÃèD+H–ï)€Y*‰šŽNHØg>JàJêØ$‰ IµGH©hüù'äZ£ ì_¯’(SFE`*hï) §ŽÃTñõKAÜ)À‘•x*U!XÛÀì|1{= T;Z„,Ë r÷ÿ¶ VG3˜V/È̲#‚)0jWb0Ç—¥£*P ‘UÂÃ/…À,WB'>œ¾Tú•HÁC¨%îÍ ?B{Ï‹ãð_ÿþ~øÁùà÷ õ*6€Ú ZRÈîÊ>®•¼Äü ¶}<îôì4ýÐ¥“1“ ÉÛ…'SUœfƒTe)ØÀð¥ðÛ„`KÌtòé;œÞ €Èöƒµy|Zc }f÷MªsàewmÇ$¶0Z3ó»m§-Œ¬³Ü³¦Àl S¹Tí,q*W‚Æ¢5RÇ›‚Ô–b ©RÑ4b¤h<A/äÊ—Z6djëÒ„U@¹LP!_A>¤ }Àg{çŸ8£a篓$BR6ÂZ”Å¿4ÎÑ…L-ͶàEᇬS"XÖ²B gFíä G‰!Ÿ¯ ¦ Ö²‚š¦9¦eqTM¨©¥ÕòÈí(¦¯q௲ï¾ûŽTs®õ:n¼†´Ìâ‹Õz yKø|%R‹íËzR<°ZA±åyê×'øé7Ošh–¼lA _{ ýåŸZhmìּ1µ Û‚·šR˜¬‡éÚ`fvÚfUO"¶–r©bTóÐk¡¼K+@ò1yF-æD’â“"â’×±’šFë5« 9Yžf1ÜËʧÈÌ(4† NË4!ðÈÆÞ^VB¹ 1ÑÖ%Y4–BRÈ5*¥$ÂheÓ¦© ¼÷%3˜¤OÿÚ¦ ³Ec–mMÜØ=¬tˆ÷mþÎ*&¯ ¿; П>¼Â”•—jG²l1Îá¼r «­óG¿ Y÷Kþñélâ!Ñø™¦N Öé´q¦9,1Å;´)K¡­SBÄi7Ujðª¤àÀ5Z\KdY~Ï(M…‚tJýwúÿö·¿!iþ4‹Nž7y¾yp2}_þË?Z7¼‹ ”mžh†·µ½§Á¶ƒ3",‘©ÔÚŽ€æE?¿«†à%ÏÇ©£¦å@þ%¿ú¯‹âkÔ” ÐÒHµÓ±T­ãˆ#àCŒ×ãð΄µµ¥è$iï| }áá® g8ydÉb®©2x± ¸ÀÔ6aóTÕRì*6Ž„ TI­Í M § OYêˆTA0DL_yÊb%h–J§Àl¶Q®IAX%Í#K‡¹´)W‚Ü ‘ öá¦aª’¢gí ®œ Aå âLVp±NÀ.îySJ ‚o)ÐÅüËÆáÓÁ”k§¢Ê9ð+„¿üw]|¾k¶TÐ`â¶Ð:DÐü|{4› ¯ñº½IE“ÚšíˆÛ„NÛY/½Ð#2N£B¤*ùøÿ |­Þ7úSHm§mšs3#k“t&k$¾O­|J„ÙÅSŽ€)Ëàm(E¿w]jŽˆ¢!ãÀÅ͉Ïê ”Åtb²zá§\‹Óì2ÙgxÎ _U ©†TH¹v|â²È¬xÖ^(ˆ)ãC|¹Ûû¼…²LŠÇ¹V×0hšZ*ir íœCBëŽæÐÄL¶.@1N…)Â~ãYJaV ×TÉ&—B…Èòb`…Ñà•›ÖsÂG€X2ÁIj˪"Û`Rkräæ±ÄçµHß±ð1eáø–,‘:ÂÍÜ£´ÌV‹ÆTA ø3ßó– æµ£PÊÒøâÌ9¨eJô’ÝSCF.೪ÄeÉ ĨâÔšØS°\‰@Ä7ƒ§V lÔÄ›?ZY`"<µvššT-ˆÄI!¼¸î!v]»Fuæpßê~ó¶Sỽ¿üã|´ `NvÄmP`;æép€,‚BYˆÓ09/Ff‚8U9“NL µ£P(u5?.¤#â‘H)«¥,xÉ¿";s bõuæu8–†·£8| œšªÙzd gž¬TKâjÚ@ª3IÂÔ"@Ø–Ê™FR™%f‡fxàJÄ—ÒqÀ«ôœ¡òªz56œo^JUs&T%.h*cû¸³ ÓIá(aJÈuT¸š ¡}%R¶ #*i¶¤ qd›G»hpH>‘ÄyYâñ“ŠO!M¾A‚èմ‘*Ah KA|å_K5?Íâø<£C$à äÅ=ksþ˜&vbbÏÅVš1Ž OM@dAËÄ;.)K%L`³8Z° F–ø=Jך§ðøØ¦2»–IˆPYB1e•HQ1º¥R•fh.J4µ—Ì9wA(±üÚYœö )ÓÅÒ –Uafã7䯰ZâT’DÊ„<ÜR9Ä&‹`;@Ö@ZM\y4±ªÑ¦/€@*fÐEùÈÆv½( ²ѯ‘”Ø`¼Þ~KµŒOA¹©º©Ku RÎ-µRh¤l*P!s8 JUkÉcñô!ªz¸ÑJå«jfAd4±ÀÒAÞœ!©ÏŸ?7Xí ìQ‰½‡eR†ú)öÁjßç)ïØ5¹4º:ŸÖ,\¼gã £ âKÙ‹”m6»(çØ;“›A¬CøùÏù Ù¾ïEiÚ<ÔÜc{ nT½Êf£nþ{wd>oY!ÐÀ4w‹díK‹pqäšz! LŠGN ™¢EM‰WÈðYœÀ‰iI¡™“ª°áyå ¸ÑëÎà•cZ6˜¸Í †³Va|›My]êÅ3 L‹zµ5qïðjqêE–Âv¤‘Â4/¥3?…NG6YäSU<åÀfÀ´\‰*1ÖWL\ÌŵF((UIUÑ ¬Êä–e§P9M‡­¼aàJ¼K¼ùÕ¿/ðË^&·iÁL«yŒaiì-ŽÀj*‹&´DƒXaÑ L¬‚G–¾@‹Rj#ó”)$„ˆy B_ ½öç!þÉohm$úÌËÖl˜àÏ®žï–mÄT VМ²jÙ>BÉZòR8< â‰;¢“¸ÊÛ~‡_‰8…À+³kÀÇ¥UB6eLË÷1¼"€RÀ4µ&ç¥,kJÇá`F>#^óóR•8Cñu§Î›€˜ßEJP9°z=VGÐ+KÊ!ø¬1<—bµ‹KÁU*Ü–é,Á”ÅkaHc4 ”&nà˜-ãQÕuDZŒŸ ¾^nÉâX“aM¢°¥¬ e©pµ–Åühé<{L•K1Hdå–uçïAK>}LAP»‚”§aY§n¤ó™Y /†¾é€àT°7"šx©ºÆImšÞSÖ¸”%£Y00¤ÚÆ=Z—µLM;r;ÆÀ}ˆGƒ{›@ëÙ[QÂ*·DÄ,(Õ`j-í—ÇÒ£ZV J–&©j«KÅ,hŒ!F… Sðjœt ï0o»^œ ɶÍf0€ÁL"î4ÚHy©•Ø>2SË"t°(‹½ tï.ÅW‚F'Mƒuμ˜2#Þ¿­ÜN µ¶¼ùÏ>ŸG‡ Dw|"Ua6˜lL1°%¦ Zâ–õ¢ÆÄÝiL† äÛ¬¬Ø3ò6Ô×-Ê™¸h•“ ¯)x²áŸ>}3¾o¤ùÈ!G ¨‘˜5ž¦˜Ì/ÿ¼ðÿûƒOÉÖÈäúê(0Oo µF(uŸ\aÃËV‚\ܱX†PƯ’¤™0ZUÅ#B“ ˆ`Vk9Bƒ«©¦±; FŽÐ1•Ô^¹.²:‹—šxˆò¾™:LŸ`M ) ø,)!M›ˆªâ tÁ"7³%j=‹^Mb]àmÂױؒ&V‹SX€&«…3o ͩвrL ˜Å@j±PI­¥XRÆw˜† ǯÈ€íâ zÍȣɲÎ>~"õÚw oþÞ(ÚHS{^æ)¾&:Î ÖÀ²ìBJÜhצÏ+z:éWK­ “¹ŸœZ«Y-MÞs¤ÀªúöÛoÏp/2¿ å·ÿ»¦£ÝiÒ Wÿs{¿ýb28/ÕPRøb4‡Õ.F^*&"eû¼)Å”JÐTqøU„ðì4»žŽŽ½Ö€›í¢|¹„˜ÄS®‚%Pªýò†¡àÃPÀ£­5„AÔ dÉ6|ä‹u:ZŠ“ªW)Û¾kpçS+KSÉøðIIY&Ø8—}S~çK5¤ á˜Q †Ôh%–ø ‚Àð‰4@ ‹žŸˆ@ N4 š{–Ž˜,ÖË)Õ±·QL&NêªxTÁ½ßýîw¿øSß´ö‹öe<µŽBw˜Q3)ÁR ‰v6v™aJÑÀd{-õò³”ra0kj™UŽ–ëòü¼ AÜ„>ÛÀÔÝH=©j-F ‹M’ެàëÏþô—¿ü¥‘šA\¡àn=H{OÓ_»ï½ãN~wìóÈýáÿÆ0áóTÎEµ´)ú×Á?Þåá8]flµ†³‡"+E¤]Èâe·ýª¤ÊòJplS¡ÛˆÐ$=KÏå%õ_¯‡v8qÎÖ¤^Ü5Ð=¼-Å‘WbwJa)A|¾Ã”Õ ^kKVÖ tàNÕUV+ö˜./o_SP[ "VÂ×´¸.âÿÝÁh* ØR—&äÓ&ÅÆw8îšâ”EPÕ½³žþ˜„ö¥ŠíIQ@ËФÐ/Öyâàà Ð2š“àà‡§6ÍûñFàgh4çáÅšz Ÿ59\-3² /RØi˜TüÔZ¦S–ˆQµðêè+¥˜ô†ñæ_»æ×è¸t Ñ¢x1Ð$8…Z Á DÊ+«Q{/×4PŒOGV ƒó¤:1ÕN¶€/ÆÙx–@ÖU±„7^[^¹e ˜õB3LȽõP ýõjyW˜°s€Ü­¦zÕÅͲéEÝ5öžFÞ+‡S å ÷Q›ªÖ [¦Œ†¼ƒ¢€Vª@ÖÁ²§oËhÅRb–øÝ¸ª@:hÛšXàeJÄLª G,à}>ßbHÖ¦©8F`1-È–UAÖ¬‰ÝÝ.q%Réà3£@ú˲Bc€'U µU­¯ ©KæñÀgÃf@ ¥¼³£I R®µÓó€ã3ÙiŠÑXA)MUCV¢V—žn£FSR°ñ”@xdÞ¿[}÷4ýNªKЖm³¥gÍÀ7§ rK¾*qn bB5Ëd-á²@±ÚÚ¥‰ÏÐ:Ÿ––½»©’¥€ŸBÊ<ÚljkôÛßþöÍgÿZû¦‘K•‚%e1ë!53 HE[ʪ^e?üðCߌ!¨EÛïlßto‰#È#;…ΊWÕfòŽ+YL4`œæðÈÛlj¼)¯ÓÞX‰(áÝ¢7g;Ÿx>³!®Ê¾ôØ—QÅ.€Ò6æi;²ø-+ßüpUö’µ_±rVVçÕBhÖYÊ ¾Ø+FK¡FšÑ«V9B§TD°“M‰{ç(9¹ëAÔâÒ;™…ŠáÍ¿X ×Ô”‚ÁN›k¤7'Î+DÃÐa–dͯ&Z]ìY#×Qˆ¦„”+DÇ’NÃX2ä4›"{eÎ7F­áÀyA³U‹¬oâ£`½¶`²fŽ0M©JÖN¶Fùêéù&øÚïø¦7m-6|±ÉÍæ)hê|šª-ˆ›DIV ¯„‹ÂãêEŽÏÛ/ä~2=kHÏq÷¼eå/?ýë_¶L¼imãL`¾ÃÇ‘jfÂ6aøvÑ9Älx8&Ó…!C˜çk*(K\,%PØÇ²8|…G÷RðÑê^V‰@#ÞRP£Rí®r± c"1ËÆ‡LG`³d{EkÏVX­%Â3ùxyBhÆŒP\käõ _ùRí:Zš–¶@Äï)ùe“â6èT»{² &˜ìb)1©,2ý¾kcï˜4)È2oV¾^…t“b¾^é+šgíî““å ²È[ pÚ—¬%A-Ú ²”%“½ÇRÈ ÈT±¤ÈUñ8‘ÅÝ Ë‹&ŽŒ)Æáq€eùÿþÃþ’h·º&­ ‰©1& סù¤†$(Á<*—U• €TµhÊCÄë5\*}žYFã„WÅ#[š„¿Š¾|Ð’?ÏëŽi<³uàÕRëm¥C@8-¯.ø@ÇU-&S¡­UKG­%ŽNcçqÞýé—Uú¦ÝÑ×®¸½hj Ôeœ¦µ4€í*lk–m A-«ÖR Δ෣¶fÉpºKvòhÊ©¡‰ùfj†»¦Xͧéý®ZcðD¾ûî;¯í  )вO4+§A ŸÁýMþ ;ò‰zowí:·¢ÇÝí±Så-él/–ŒYA ²L9¼£¸XçIÕŽN)^I øNÆ-‚X/_¾êÏxûß÷ئ:j×TZ4†û`ì6G\³ÔxpÌÆæei 0µóð ßîÄRºt0 ºBRF¨ixü:Lå;IKV;¸˜fçIAaM“½¸_®4>¼*)1‚Râ¦mËlqj˜ lYœ–‚‘—JÖB¤ê[ ¿Ú‚”r7³íìØáhÈõåxV²bµëeÙë‹Þן†×Zjóˆud„8úê‚ã"¥ G§.–>Ùº¤g«*>ê×]m› M¨JÂüٟ׾K|ÿý÷:ÚŽMk<›{ùô·wà5àãH[ò dé03 ,¾òljÛ]' nk–•”Ű"bL†iÉ_ùÓËÿ'ä…2A ïíZ÷«ç9ü扷dq÷Ó1*‘µ4¡_¶¥lÈLÖöy%R]*Ì Öñ>€ªû÷”¸™ˆ0å™F㙎¾7ÁûJšÀf›2°]œ²ç+ÝÓé@š'S•é‹Üð)À] òKõÌNç ˜H­#ãvu©…/‹@Ür·H¬Ÿ—…#ôàž#?.p“W¨Ê’á(¬*…†$"EG.*A+K±8ñ-e#`²C}’ÕvUª²¼ŠG¯Ú‰ãÜ·ƒ©„l%R dÕV2YËkœ³Y†C!‘‚µëš¼.ú Î {wÝ3¸ Ç!–ÅCÐÏ”T õ7%Bd#"YûLJ­?²Þ^áL¬<L_Ìã£UKV¶K¦¹.ø“°Æ8mn?qHHšoÔì#ÁæTç;Ê-¯M<Þ7&œg@"¬l¸ÂjýôÓ'a©ÅÿϽGビï')¡o0A²=5HÇ®õ›_‰òCcøj!‚3èEÀqtð–hÄËÍGcð÷PÐà>y¦Ï+´lqoŸ>}R"žiç¯Å„ÔTœšvŒþ,N<åkÞóiÍkŠÝ/ÿha$⺘jƒYÚ&Ü0ÆÛ$@Y8Ðr›m!|%‘m‡Da/¨”!½±:„@'cÙ ¤˜%\¯WýÓF_ˆúéec·í¶—ûãÞN‘#TÒ:Š>q?ƒ^‚JS»o¤Ck;ý8 MgÅ·ä Y;"!úö¡_ œfˆ\/UV¹@2)ǨœUAÄ زì8WÑQV’—""– ¬<Gc4P– nH´–Re!RNÀ²Z_ u\˜@ž`d œ®WyÛOÙiñâ4-v©Ê]ÚRj+‡£Ùi¤ëe}®´ZÌ:B®¢ÇÀú&î5UŽ ¤ÐÁjd©j¶§®°-¾ùæ›ô_âýˆÌe#Õðšêh¤ô×ǦZS©|äæl/<33°ÊøÅ! Þ‚–•÷æéÐtïäi®Ùòµßþw ½o4É5àサÁžš¬”™Ì¡Y†õˆyÃK5¼lO³K¸¸„‘-¶}µ–ì4¸ÞmªåIñ¥(êEæ‰S‹cÙÌ!¥Ò¬ãÈ{^† §Ž] KüJø-£]™GÖH=¾Ž…3Æ8÷ZL¸l&UÖ²#2ÌbÇÛ®õ 4Àátû¨Ó „cöª1?_–ˆùÛ”§=àc2ËŒ¸@KÍs©ïgG¯:„ÏŸ?÷ÎeZƒ™¡ n/[#AY\­©Ä¾·â-^bd½Kج¦Òq£Þ'7[„µ²J”wβh÷½½#H–T½*·äqèSt^2COîíâµâÍ\ 77ƒ€éÎLh`qsÛKUJ!Úȉ{‡AÆD³Û!^yÛ‡ã·;KÖ3jž–‰ðJºÒÅÍÓsIMÜ¡®¶ Å)Ë#Ä4FâÀú ¼¦dmxà¶™Hƒ…K¡ñ]°¦µ¬‘µ&™¾ŽjhŽ‹uu2åzáÊÆ§ÏZvb)WÅ#Ü¥ÄD˜k )´wUÑ9ê×=ÄDˆI >AHçƒ>[¶¤‰Ö™¨‚'xÉŸù³M…P|'ˆÛÙĤV Kq%–!˜3) ‘˜ªÚ¸€©Å,U‰xäû„#G»Z}“¬ZÁví0Õ:¥óÿCñ‰&ÆŠQëqÕžâ¶ ‡¤ Çá;Ù µÁgñS槆/…ö¦W›”íƒ}×G-¾Ñ‹-‰#SÀ,F€# )”5Rô­; ^*kBqdóÿýï÷\|Òò“¼Rÿøãý Õl桬…3Y»Žš,<_wüvTè0Çé(,Ù] B0¼v ñ!öâŽñJ€£¹|‰WÅg FD9‚*çàÿ_9äÑûZ÷v‘Â}§ ÜHCd!fûúK‹¤Þç}óÛ–w°Úµq[s%Ò4Oòg-³%¼,„µ*úR]3Mµ‚ª,ÉÖËQK!KÑëEÓÂq~ùË_Æÿ ÷£ʺ7ªŽDVSx³u%úJUÜ2N4±Q‘mð¼U]oÔàqÒG¿ò‰ÄL„ï0;U:ö¡Ð…Àuà°uÔŽÑá᪲Î_/ÊÕZð °©ÊÞ™µøæ24V hÉàÄÀyñ0ë»ZxäT…à º IUË[Ú)B[SK9q¸ 3Ä t-áªð!õ’e޲.4]’¶¯ Q.Ë4¼”çÔT Bå÷¼ÕXR0´b}›­ÂÄŒ/HbY  Àõxí»„?åšD;:"½:RˆÈ:Ò1›Ö¦˜˜µ…Íiò–‘¯¢GÕ©¼¬2‹ÀSÐZÐk¡Tç4’ßS}ùø‘ñžrûõ,˜¾=Y 3L×IlMËg}”7¼“l`owD(XVh™$šoðZר*>2BjzEã1™‡7’lï3ÍS¹Ú˜@K¦„w+ºn]½¾Ï¨YV•N{Wr)=ÎÄMLCšÞxb¦D­ªšÊŠ©‘BãÃù”W%€o j¦QÓé*§,µX¹|å¶Ö)yµ¢‰e™˜¥V­”F@šæú„'r'hò†‡;Ït¶k˲CY:±ö‹ çé‡ § 4U|`²é‹Y² ˜fµáÀ,ÐðôõBSRœˆÖ3%˜iÕ*)ÛxÎV¶™Sn)ky®…ÿ(°îaÔ/_Yc%:„ «81š,ðî-¥š2Í#q‰$Ëד‰YÛà™ áhâñ: ÜxW‡õ$ éÇ©Äd¯ÎÇ% qެ‹eIS‡­‘¥*ˆ,ÍD¤Úš,D¶î-e‰Ü<øpÖR@²@¹¯Þýg¿—ÙÿD݉5íiséëåU¡ëåQ*ÿ?ìÝÍ’%W‘µáƘ2eDƒ`ÄÅñs¹`R•n£¿gÇ{r)”ªNJ•‡oÒøÀå{ùòå¾wDœŸ¬¬’ñ8²Å|Á°,pY`µÎß™´#“ hê/9ñ< ®¾w$)!õ“¿cêï98œ{¡eƒê+ØÙ&È Î70ý©÷›}õ÷°éS£l€z‰»+ò²Æ¨5Ï6’Tw &­½XŠei2 ·%oYP‰ÞÝëM¥B¾ws–½”þçYŸþiúþ£µÄŒ¾¦¬©L+6•e/8›Åð²í…B†ÌàømŠO¶Z±ÂÈáÅJ×pN³U¢Ü7po®ŒT&«£RKq— ÍÚÁ[ ÐÄ8ñ ĘLjµÉ ˆÙX²Î$Z-pR¨W%ü²eZÞ23“bbjR+‡Ä„0ÙøÀ˜f¼–²1y8ÐÀÎP ¯íX)ÓPåÅøÈU)Sã7'Íû7OÞ$bˆe^P¹Z §ì*…Ãd €¾@_Kâ#¡ë˜TUïô~EÐÿ­œe}B–f9'øòD(9ƒ^¦$…†¹¸Ó(UIšwr½xÖ¦&Qå¸Ì h  ÓK­¯m.„Wæçˆÿšm–ýé®yLØlÝ0Æk_p4&+î(òªUñøYH[Ž Æ÷eYa‚pÙjéui}ÓïΔòËl¡› _¡˜H|µÀÄÅ@qGÈîƒ5C 8ŽB&@`®”KÖ¡‘eqš3$­GØ–Úú1UYŠqjTk ±BMéàˆi¢©C,Ѳ¾¾÷ƒ­/}&–(dD,›DЩՋgÑNÙËG>%È-8Jt¿èr´^n§•Œ¹ãä#ñÅÓ·ÔZß3ô÷?¾âÀ7€ìâÊ©e–t–;ä8áË&Ò±#tJ²‚{ɹ3W“®N‚Hàpi)ƒt £µqüÀ¤BÄü'-2¿ ‡¤\ DßT‹õrIݨRJDŠùú&kHHÌÙ;¡ÂºGȧ£5Aä|â¼I\2RƳ̻¯º")‡©XSø†Dë<-+Ç«U¥œE£ `Í3ÍÃ¥ØÅzœ|82<!nÙ 'Û06ê4ã¤\;¦úÅÿ:súwOÓ/è³p“4RÓvµ–2¹³ê¹îF¬–GŒP¡x„6D[ÓÊùVSš;:3@"Óñ›?Ï=/éæ×Å  Q{i³¦j_Í`Y¶yðí(¤ñ,Ù¶”å‰ðøæWËH­Ȇˆ+4RL"®EÇâÕÃHJHiÁ#׫À˜Ê#«UÒ[02ŽBY̤¼*ž ¼|\“ÕÑ v¤¶.•T“BÇ%ÅRÃ×Îg—ðydðcŠ‘2¡l5&‘J0qÄYüÉÒTÒ$š¶q%¶`Z´ÊÑ”£AV"¨K“ PàkQ»µëBLˆC„AÔÒq˜!–UYà´wUm3±¤PG ˜Uâpp,©°î|ûêUªŽðÊUAŠy±ªúÆ ©¶¤pʼ”1E Z0q»vìjqÔâG†¸48¨~•A·Ä¶œ©oL¼®ó‚YU¤V^ª9ÄáZ hQ Ï,í§F–ÅmÆ"‰hÑoD#Ô½ó?r/¯6‰ÔÇ’á#òâÊ Ͳ‘€‘C*g–¬+û‚}ï¿Ýl ²Í°´Âb)4f‰£#¤”˜íAoò4…cAsiÜ{­­^€‡¤ßtO·ëéRƒ Vß@Ûm ó÷rdR‚Tå)TR\J6P }ÃLaú©I!tR6LDP£âtŒ ¬µ@a"ÓDˆFÄ[>ï¼è¸SñûàzꦌŸ5’x%k i/½ÔK–/›5'¤­ùj„/û7júå™ L³§Q ½î[ÐÂN·ýFjM‹Z^!ÏlS£bY±'“O¡Ù.–€ ¬ÿI‡þê®_ìWkü-1L4åòÖ÷!#DFX ö{/ø!ï÷šúÁžÙìˆYnâÆ`ð5²tDqÄwÜ¥éö:%¨ÖC+ÛFº¦:Þkënƒn`r]ÈÆG`²_öõrèëË*O“Á5ª—¾zI ÊŠ{àÆÛa)6ªB± ö¬u6¢–5„IÕeŽÏBêÛ´šV )¤¥ØíÚÈJv†R8é‹ËžN/¯<4|{¡#¨i>5L–,<…z%[Y°«Õ÷îäÈ|Öù ¾€–<Í;AÌâ8ðZ;aeå÷Q!ø²ÔšÊ¥„ÜÛÁN©KÜ([ö55)´éO„ ‘d^ÌઠÝ®JÐÚMÕ¦T1U–Å |ú/ÿ|øðÁ õ´öÕZ› ~f}y=Á‡0gÈ[âÌ+iNc;*GÀÅ8Ì‘âXæĤX%@YIAÀ –Èá#ka.DUp|Óǯ…¬:|Y @Ù#ýb¥p:´-(ø],"¬ò誥Y/ ø!&/ËWµÚ3Cث٠AÖ0©ñ™l}õjfO7š8q4K4KY»›¹×1ÈÍ,fÍ\<8ZÖù˜02Ÿ Ü)EŽŸNÎÄ»^ô!¾e)ËâZ'ÇáÛÐr' ±”â ÄÔBd«‚”M–ïlcâDóñɽç»HJÐÈÚ_ ÷0‰ÒñH@Ä‚bþUa„ “£‰ÌA˜XUKsh1ƒÇ¬$d1ÕRèîLé(A "N|"N8A^–š”Ãt(î<8‘ ãˆYÊhN³'-©j¤œ²€¬©˜˜5ŒB%Å€[IS  m o ÏD–Z©~Šÿe?¬õ§~vîóY;"ÎÈfâÆè%£f㙡ª®‚%2³üö[ªÂyåôóxdA/éwn^Âþ·þø~©ÆOÖ;=Rº7yÁ™æº?›3‚* D0ƒˆóhÏúk¯éÛ”ÿ…M‰ 4b:Ü®mÙ2o $xŸVj"]qÇîFR…VÕ½Љ¥yÊJ ²ÎüY¿ÈëVw™ú¡‚FúÒ×eM–&RŒfkýÁZSñ&졃?ß–÷t t÷â‹ÇLjHjmóŒÜIZº”÷ÇSyíÌ)f8Œ‚’|Y4-€.“e†o‰fÂt ˜øH!ª §Áee…õå¼í ó˜•Üý,æY…Ô–•X6ÞE9 e„¦iÎÆX!K¹²<Ј.HážÕÇ]4Md¶^«JP ¢¤ãÀY 7šÝªLÕÅj~…ìtz¹¬‰ð!ž‘»Ô;c?ÅH_÷n³Þ’Ææ±ó}6kG€Ï€2œ%HÙ1ú™T'ƒFAJ•C²ÔlPÀ§\ KJ܃y ?nR²Ï}Ùô'ºf k†°lk<°o fmµr†yÁñ—ñ"Å|A´º$ÅÓgd™ *±Y?Y ,N·q|c Ürñ‘eÝ^*—í"®Kj²̓& Ò R4ùfv‰¥,UUެŠC¢aÎ Áh&46³T«5_Iä˜Mo*äÉvPD€JšVU t88²¬`KÈ4 5Ò‚ikD˜SZ6sL‡£QY¾}©RûJ|²V‹º 3ʬ812|š–Uà’}…«]!Ú]AI…÷ ’š6°ìæ$eö aë8¾¬óqºÊâseY•^ž,“ƒÓ цSç-CðÛO¸¥¬F{ Ž Á¯ UŸŠ_ 32PJ¼î›Ó¾ˆçÇdz…4 Dª½ˆÙ­Yë|í¶#2}‡%è+H¤€ghzª-.øàJºçö)§¥^qj†lN¸Ã©ƒ¸~þí{˯ýëf¨ö3½Ûؾ·:Jt䧣ܡé·ÔQ_†Xm Шj„¼ d‘xÈFž¾Œ~Ýÿûê >~üh×ë®ð>?AÊøÌ’5É‚²Wæýë¶øNï+J“ÐY Q²v-Ö1/èC¡ÀátÝÍÌpX…!0¡Tj5J3r!-ÄrA Fê“ÿ¼Ò]êóc¿ücGÝBíEÇzµM@Ù]M ÇÊ›V ÒããeqÒ¬j‚|íªmÙ®é”ÌFH¸PÀwQBzZ›Y*KYm–¬T»kN3«"ÕÖpÚ©gªpðµÛ‹•åaÙ—çÄD”0ä¥RÛR ÍrA낦_É®Wc#Œ)6?D¶rU÷ a’µÁ½â—Ú`N²ZåFbu„ X`UdW^-dÍÓ’¯ ^,èž©×>•'¤X‰e&f&WþÜßuñ ¹ºÀ¨§ÎÖ kÝY¹üóqÍÓ]ämH­CŽß…C¤ªŠ/î~³”B‹¿‹3L(n¼4Å!t¾ø_¥SûCs^Ûu—jZAC ôåo*AS *é”ÚDÖÀÈN)‚”ÀL*\Y2)H‚ñ©Á Œ$Û$1ãpÄ—ØqM(H°,‘ž%pÞ­N¿}…ÔBá†9s¿|²4‰‡¬r¦V<;×íļkjjYV ¹É’‚ë%ÀZò Û6šrK^6)¸Ø`J Š#ˆ¯ýü­6´ óô•¿"+Ÿx – ÙRV ‡ð²:̺ØóL¹l‚J˜X*åÓàjaTxË‘cV"Ö¢ZqA„⚎&¥ÊHëxŸÔV|o±.©ñjÓá1Ýiž,q¤¹Ø«´”ªÇ€­;Mg„MˆD* ‰×R J ŸVYK"j-³ qZ*d‰@-';¾VxCÉ6ž³«¢]×É-U Þ8Õb^ Ï­L_Š__|©ªà)óŒNU-+‰)6Ló@´óøæ¡Sqçu¶¡‰ùÉ"ˆ›êÊŸš>4ˆÍü÷¿ÿÝÛÒü©´’¯¾úÊçÔÞ„š_ÇñÄÛ©© võòò·ŸÜ¬M ØRÀ–¶ Ɨ·„¿ñ ?)øj!®öHß,<)Ë>n`—¦rà0æûÿ×ï:N£ILU_ËÅcؾ”ØÙvà-ánËŽT•ÀüYÃ+qøJ<ÛRÊyLx}I1SX#“bÔΗýiRR¯¼?_ê™rÄeM¥—1šÒð–Z»»ÚÎnžk¨S(PˆŒiIÇ®ÅL¶âh’Dzûî™A#à U…ð²˜qFK„‚€oÉÒ‡°j‹ù{I1ï%È–;XîÒ· "Œ²Í¢ ´Sˤ bž9^NC¶Öc.jËdÉ«U¿š¨6¯Áä‘êË× H³»± §V¶ªÛ]µ›J D¶ûÁ²ýZ6Ï™ íûq&qºIŒ!Ë€ Ml<X¼åÀj•”J¤Z9Þo Æ|¿×èÛëï/ÕK;ךwß·fÙ$¼³uÝÿÝ?î 3ª”ZÓ²t)G ZÊRp´á8‹{—T‚)…,%6ÀQ¿Ìø7ÓdŸb$)[; ,›üìóÚŽ`<Ã;´e) ™œ¦öNÇÄ×K‹JÄp Ò!&© µÓ.`øRLÉF•eRJÝeÅ0¾ñºˆÞÓï;©˥ýx¯ÔÂ$¬ !ù8c®»]-ÍYaË{¹FÀ²ó›R¹ÔH$h ·"²–MН ³GÇâÛi÷¤%#È”h$@S55q&Np7›e%–ÊyˆÁVk±úú(¬ ŽxR¡Z&®—Öb>51ãð,D»8¶Ët.Ûö Oïë^Bˆ³`::Š©u¤KUpq"^U:iÆQb©;ß³®P•ɉõh ‡¥ ÁnÖÆíá !¼LqjMŸ¦ìUw c Bª/Åëh*A— fHYâöÃ1SÜn;8±À•[í½uíôŠÖØz!ÞR­€)Œ,¸„AtñFˆé÷BRDÀ¶S‚D’åá:*Á‰ LVÊÅýDÿ þ">öyY쟡°\|,6KïZÛ Ü Rf`€mBàøU5³Bše©J…á½³"Sø¤ù·tü[òÁw±’­Á–¼H§.KAê³%Dß/ûÕŸHßÏ¿íWÀ ¬kàn³ehÝ–]V‚%bB"¤¼ ·»°e×ÙÝ%¾¿¶ª­¯Ú ºðáMèæéÕþN#èvJ\#è[Gʋ̮ ̶Óv­JIUbf¿Ê1ùö^ ‚©¯˜&PU»C°Ä©$f…¼¥¬ÂÚ•Uâ¨y&UP 2â7^4¾F1Óoæb„lÎì ¢JÌ‹cv,!ðjkÁ›\JðIKSjœ‰§Ö±ˆ+×]Ǫ B]à&q,n•8ùª\87^Ćlkp¹¥.d™8!Þ„tj“§Á4!Å”Z^œ)Φ ª )€³‘ÈÚ‘ŸvG{Š÷a×Q·;s:%­]7†€R˜šŠeiA[phh¼Z&Æ—B«’â를ÀAèÀ©[ùzÝ©;!5H?›—Å!(ëO‚g™10Ó‹¦-U,Ð ÒlFÂ1†@¶-Gƒ#¿]¤AVÞMXÊ=ŒÆ&9Aqf)8c]f¤ô7žl°r>ÓT ñD:=K&v! v9ÄþÙ4ú¶M-Í1]>xjÀGë¢7ÞÄ JµMUp–Ÿ`Rðd/âyúªŠ#f4ÍÉû(Ÿ²“i<Ùé¤_*>¦ÚKé¸RYñLˆ%›æªJ5•atq†”myUh ØÀh@Ì DÊ´†) lùÉÖpR ‡«dqK¾ fÇ%Š5%Ó±”j)žAX…¸ØðªÒ‡,Ùª’§”¥rÝí]Ühçý•¨µƒ‡6¥Ã‚XJ Ÿ ])"ð¤-5À©¥e±å RÇ‘Å8Å8L“¸ç„g¥š'>ÄH̲¬Â\¬(&xï"®EÁQ¹~ bk)´ýÅ'ÆðÅj;U–‰˜‰utŒ1Å ß Yò#+$˜¯¯P )ÞG.Ÿã}%žÂç{?zg~¡¨Ütù¼>¶)K½´°ôØðû¢4 kà&)އï„#4³×bú}ô{`ýýà__",Y¾yR¶l G„Cp—À²ñòªâ$U•ß{y{äe l¶n0]ô]k³9C33 ,fÛ†¸^’Ľ·§ýŽ–œ& ·AˆT3µÓ¨Z ¤Á"ÀŸû þæƒÌ£©16˜˜ to§{ŠÌdzëBm'Övº ï5 ¤vôÛ/O‡‚ÂÓþ‹•´ä‹áYj|»àÅ¥H‰É2AµZ ¼oPaWP-ˆ H©J˜ 2Z›ÅA¨KZ%@v[6á•<.¾€ ¿óïèj”‚ÜÇkN¸ÛRªB+…¦ÐU“5v"y©¶£8BA{ÜYm6LV–ˆXÕ‚+y§åb4f*ˆq&À,eÝà!²‚éÄWžI­ÖJÆŒÿïµÚI¦ï¦ÕWG½˜+ÞýoTŸuÖÚäÅȲRpqÛ±;~R@):qÄíZšÖºH¡ñh^jú#å3ÁËŸ$˦ÉC6•Oÿ‰Px¿ù+m^6ÍCÓ0|‡1³ùµæÍÐÆy±¾NÞȬ²vKДm¡˜OùÕ€ReyµZS³¤¼ ·ÚšZÊj¡¤+"ˆ£V•„‹ ¨Qîu“Á5U"®°Ž.\²g²kr¾ 0úýB jFj~U±Ô:ŸÊùR8ªŠ;FÞ2}4[pÏL›&ý¤tÄLbkU«œaªRÛTui¤ê…d |•>î8„O¡Ý5X ¤à˜uZ¿c\w´¤,•3KÞÄk-àËLBö°¯£ç™T£–ÍC†“BKÇù4¿\zÇA:™m“,œ—"^-îAc é—pÂS8]°›5RźºŠT Í ‚ãðfµtpÈ5೪à17½*Öö”£…ð+Àùªv]Uu:pY3gºà¸SU¹ád1õµl!iVØÀš 8Îkš¦Ž²Í€Œ&HßHÝRøÈfƒàÐb28«£Ô6bþ@ÞE‰OÖþùÏúQ®OÕÀkþróBì×lš¶1ÄÌ`Mh`Ö®tá!¼Á Ù¹™_m1šÏý¾lø—4b¾1do Tç€|Íòx6Csâ´n¼J¬y  ᤠæñWÞãǦ ìÌuiå‚¡{à P¼aÐÚ‚¬òn‰nZ)ˆWj]}RâN£˜Ž}!´÷Mn °z…à‰¿úï&táj¡K¯Kó˜³ÓÐ] åýÞ¡ø)#"€ ·Í*Èàô™%O¢¤S…t8úÆÏ+‰<)ASÅ—·‡95ËOZUR ª²tuÄ6RJlw¦²ʺ^KÉ2:—M¹?;ˆT~|Áø¦\W§û¨DR®V•eÊÆ`6k˜ôËêžx%8mpUÍY¦%ÍÈm 3©¥,YK²r4VaC"Äçã”jþ{L*M`Ìž±}™)<¾^(xH#%µØ’¥óÜ_þÑ¢À®M¨‹14òüŠ!–ƒ š6šB ”Ox³ñb @6¦˜¸k* œq"d¯*8Þ"eéÃ1›Èdá<“zúøMTSQ6ŒoG&g:úˆÉÃÍ`GbÁb* iÂÆ»ûh|"|gÞ±x'¸Ï …¸ª¤´“RË0¥úDM*\@¿µ±Ž†@A@¹1>MÖ%èʦÃ7ƒ*1Žlµ‚&¤§زÁÄjó|ž”*A£FŠ6¾eGÉ^m„{´d²M¢ ²Á(_”ƒ°–»å.íÇñÙ¨ô-B…‰´÷¶±fN²ÈðÎVLÍcÅ‹™TAã%¨Jï"hU¥,F¨p»X¹Ô}Ú»ÚãP£@Ç"VÕ—/hžáÇt¤ñ¥ZÂk4WR!A¦£Ð0çïM;2gZýîK;¬ARQL®:b1¼sQ‚†€Æ,¥´Ø³ayÆy¹ã»œ2%žš€”ZƒÑqÿyè Õ+fCòI X÷DW Ÿ”ÄY @½ ÓT ‰\Ó ¶)K4˶cÙ‰AtT!è%¥\lT‚Æ·£z©JM-7†ñtÌcn§8‰GŽæ•Ôò}¤ë;®.?Ê|4gŽÔ_Pó‹ì^[Ö¢!-Ì<@;2CÓ6U±”rÞë¬;Šÿœ‘¨ù³?øw}Õ^—YnËpctËIlÞÒ‚•wò.½óà<ñßõbþ^5}¢½kg*½¤ÂÅÍ‘jH“DØ1 €Jàv¤Êý#`mSV¬BAcvš <3)Ù@>äç?ÿy‚‰¼ÓûdCagžÚ†1†TYݯa®aÜ!¾BàûàÛçd"†DƒìÜ,3Y‡C¨%Ï£µßFz5 BȲÖx»yȦ¾¥`W°ò¥Ú¬kÁRŠuc¨5ÍÆ¶„cnàpUhRå,™ÀR •!Ðä-#ÞŲjz‰˜bU½È4C³o‰$k¹."µOV g#(a²Z´ F1ÛæÆK0`dó-”Cv8ã/Ài;]qÖÇnƒ)ï>ú]ÿQøôèÆ;QÓ×N÷ÎÁÍï³µÐx@#DÆ49ïEÏœÛlc»Cˆ4yµ<2 ”íµÂŸ» ÈQå‰+¥²W~’¯ßª|SÕ±SJ„g Ÿû;“~aÒêÀ¾Og’ˆZ&õCÎZH¥†éx#ë… …¥ùk$€à˜Þe­á2´ð-™r]j7Y©Êá²ÊÑšê;“04g+…V/ž5&N/ž”*A3¸IBŒx|)qˆ€!l0q`ó×QV0Ž]$ÅÈFPŽ ‰oãvçHÅáÈnlLjJÐÄ‘qtOÞbW+hN‚ÉC(ˆY…–C*Ïk*KS¶ñt—ê0Cwç‡7|]Ô*$ÂL²^–p¦„¡Å„4p^ ¯×Þð@4…çß‘VÌwõ„H“k‰m¬#ȆO±G@f"z»oX´©)'’«JN-TÁÍíS eY|&ÅêR,¥ >°i ”åÅðbRÞÿH¿Ü͉^`;˜bÛA`3 >DÕ•œUÃ$'‚X¡ÏCuW+u™ÌÖ25>sßø£¸ýiÀç|æNùî=<ÌGCœ°wÉŽ0 ™·4†¥ÖÆò¶©ÜóÆÌyW~#örì«KŒ–lʵÓ ]Kq4ãuøhJ¤Ðšga)ÿ±ÏïÉ—ò•ÉY颗s¨‘¸Ë$0ܱÃxM++V%h¼Ææ!DÚ²Ôd¥ªS B™~±T-DZòéäý>÷ ð)æ›[¯¹p945¿˜m0±íè®#/F3³Q™¥[ÝJQhûjá]S¸K†/`Jº¦-©iÁ3 Ž ¼=VµxÁ‘»½‘(±¤°^1çGn¸’²‚¶iIAÌð-1- F¼[Ú-í"ÀAh±lí:OM—E¨ ~µúî£L:“ºO(U#% Cï†XšZSn c™AÜò"ží§,ˆ …ØRÀê2Q^íÝ_ÜãjÄw¹ã¯„r»‹O¡—î"©–j¬¯Z]ÍæUùß­ `>Åü`…5Œ^4ÍÓ€^®»aj-v¶=•´7°r1ß1ÆÉ;ùÎÄRÀèô¥‹÷%ž}”,AˆÀ9LS³œ=ý@ŒDÜv-p,æ4† µîJÙ¸A ;,7Uûµ,žæF(«œf/×bURS†L9Ð<ÝÏKU¸Ž‚®¦šZ²Æ®$Y:–8-1‰‹Íc³m‚“uªàL'C™!@øÔtD_ÍçY÷šÂ©)9~…æ±9ZˆRµôjÜümyR©U.fM»¾ðÚM¼œÃíîx|ÍèÁ‘Ý0Æ0ä#Õ„-Ý3ÊéHéÈc €Œ¦%«B¼ÁÔŠá‘#`2)4 ÄLªªtÄdã0£mìRJ¥£Ê±”ªæ‡ xr(D(X;)¶6s[À·J=>:£ºELÉ‹Ò u±T=.ÖÃÉ ˆò8mþô¿&@è&–2Ch,Ë vÊÙí3~Ç„\P\yoœ)of4óã'hÉÄF"îÄëŽÉà|-T!\ðk:2êØ•3a½€hȵã!UIa2“'HD 'ѳv›xK…Ôò~ŠóÍ7ßx0übê_}~´s¯~¡È,¡3èÕÑò˾i(´/ïˆþC²fô¼Í[Ú¯¥ K¯Ä’u†p‹Ì€–WòdµSÂKY>÷—Èö7•mDG- ìº>çõ…9Oû•Å1X#ñb¸wß*· KˆY%mÂ6.k©0fq`qž¾`1‘pË»Qk‰£¤X€ÌFÊ?+bfý*Q‹_I"÷rÒÖÚWŪ⬗ ‹y÷áÍSkÙ{9ÐaÇŒVSx‡¿¥¬©Ð:„È–hp×+œ¯i –ô×´îC.N<…¦;D;ÈKLÙÄ¡Aúä×ÉC CÁ¾â¨Eóóò'~C¦ì§ÝÍS#§¤©ñ¤X1B÷9ÜT&1'Âbæá¬T_žñíˆ8ÛÖ0á}ètb»Ž:ªM„šB±@…3ålËwNþ믿&ÒMy3k-룛9Më;‰‘º@<«u*s"¨šÂEß4[ªb–(®Í–b~ÁO­%Nƒ¦à%Àµ÷}Î'N?3î¦Ðtë×ËIÕ«áùu·Ç¶.²iF3@3¤ÐH[Fã ¦LªËL¹*AU<2y%†ÖQy]TuEâ'RyäpUéTžš³úöÛoý^ŠÏñÌ#ö3{Bµ&ô¹ß¯ú¸ˆÝ]d;jÛow‘m„‰;R´!Ê&b³QI97`jØ?û&ëã/e'lx»k©î÷U;rš¤—wl/æô)¿Û»9ùf¦SÐ épàÄÑXðµ¸#÷ƒ’­$þsÿŸ_þÙU3@½Ú»ÞÉŽýv2pL)Ö’ÇÁ´eÞ±”í¾«uKËö˜C:8©ø]ô΄¯…@vã5ä–²” ÂYâ–¤,egJªºˆ—Ý;§˜šQ]hµâôy„6bž{S½ªBÀW…P<‘ö"Ë6-fMó8L6šž5 D ¢»ãÅôÁN//³ðÌOš! Ÿw™ü!aú #¦#v?›™>AOœZ#9 K`ƒAîí€6ÙÎŽr-¤pˆ0ú_£”óJŠëk¼–túé;©Óòº-ùçþŠ ßϤ߾z‰0›M̱‹{óEÚÞ-jãíEV 5KxG¡6µð¶Y¡Íö *Kaò5â#»²ŽÂ$k¨ãA„ç¾l:æ4‰! vŽþº ĬMõ7‚lÅ—²k"›ŠïšÊ6v¸%[¼í¼ÂãÈ’ ò!ÊYµcÆÑ”âx]/éöÅ€N­CN®$M[S…ƒéN×ËÐTÁ&öœÂUùS\ .¼ ­ö ë÷»Ü ºxB½ÿ6^â Vù↧£…¬Mñ Û”¥¬ íð,¾}‰+tuΉ¼œI%Ñpê›·LŸ&kû:)i{[–ÕB!k*)-€–tv‡@àhÄDFnK–§îÔºÖRø0~µ˜LœO$¤“¡)Î ²žkjƦ¬R „N@Êm° ëRê zÙ:vY dˆ4?D ©óg z¸3¤¡†ÓoB@V± AÍb… A 'œO§r½››‡h©ª;¦¦Nûç›[¯®º äÑòM®#q¿1,ÅMX9>ß@g”™TY82»('E–·´w³‘ ŠóŸÕjÇ·jZ::,Á3ÊíðÓQ"«ÊRv-à~=ÃßΔò3-¿fêµi­ÿýž]¸Ž]J›2oÚkO}ÙHH{:4÷'\ìm˜¬3çÅJø©E«qãÄÝf«;e›ºë#0HS¡1æƒWëâdÄËÚoU‚ ÍO¤À#K¡Ý6–âÈ1+X²Žº;!äýÞÞ} L\£^= ã@¼Íô4Á]q,´6’"ÈÔ¶qµÞÛŠ1-‰¸m¨a*xÔ¢ñ6Ûá µq´ʼn kÉ;¢p)ÁâNFUx…-S©Ëª€Ù¥ôpªØúŠqLnG$"÷¬‘œRô\TÞ¨õšàÚ%KŠ•Åìx £iID6¤ZÜÿ^œ!³|Ìýyÿ!ØããŽU¡»oòÌm åðõr¥ÄÃkÔÍ ÀY·6Á„¯²X 340¦S"•Hå¢Åܲp¢)1X½Bð£ õ'?ñ YjC¾3ð€0²ËšA‹-oƒ¶xv€‘»¬¶Ü´vÑÀ-ã@ð™l"æÑÐk7FQ"0|7ƒ’È®#Á2r]~ùË_ BÞïýÈ»’ûÄ öÕÖ ¿#ª¤GÛx|qo^]G›RØfÛ¸r³¡! ˜€rå£t2ãWrÎñ²KãÑ32¬6pâbµ÷)|>ßçþtÖËm ÄÄ·wïí‹ß¿:½|³ù,/°.‡1LXGMut¼&Ak`§Š_ ·¢Áﺈ0Y×aR)(„0AY1²%«¥Ù­+ÀÑ” ,£å)% ¤ƒã†q?›ªòÞ€éóÈ1S˜×zY²ðɱt†.„Z–P¬Q½€¥Ì/åºÐNxC`@´LmVkèÂI¤#-¥E[P(fÈCèål!øl)148ÝÕþä¯ý+HohUÓÄ¥d©0ÁÚXŠ/øñbj©ÊФJ‘jW¦©«%šÚî’¤ÎV®Ó4¥gÈ•ËBxå&fZÐð †È•4Zä qª¢ž) áuG`õЧ†–¦Bç+®VJ0N lF§À m°ÏýbÛ§ænë-D`™µÄ;ç Þ“ ‡«eÞG{5ùâ—’æÛ›Êãçõ%³µ^Ä]ë¦jïÆ@œƒBKAÓv2R–8ÄC(hû=QƒÉT9´ÃA†Àõ«_á¼=ù²ŸþΉÏζבûuì¹ .™KƒàƳ̺š]Þ5ru¤Ðºç];w;Ï"{ÿsÝ[Öˆ,ŽFÝ»m,3WŸ8œ'b©DЇ°ÅÝ3–È1Éš$Îh+IG ßüËKûtDf–b&KU˜ÌŽ€N@920NKÊ é#tÛìGP;±À2)'ï#»ç½ÏвÏ5[ðç`þ&޲‡Ô`æÜ‰™Ç0<\w»à‹›Óî:´ûA¹+½žhJR°Œ©K°F¦B뵫 ˜N%˜Z¨%å«Oü«®4ÿñènwÄu‡¯@Ü´qÞTRm?ï’Á•‡7yû‚u…8mÓ±ë…é鈯Q7sd{p´Ëœ Ŕ᪘7‹ÿ~Þÿ àßþö7¾-ðíK;-” o;RvßvÿÛ…í¨rùpº”@ñÝpè(w‰)°RªÍÖ‚GN–Î,e4&.ÀÁ\JlBíº4ô°4ü†–õæ(Ž)öŠçÇv ˜ø¿É»7<¿}Æ0›v!3³ÁÄZ‹e™§íH9yÞUÚá(äÓ0%š*HA4‚ÓÕlï.še„Ô𛄠À²S6md^ ¢JŒÉpj*¦ fñu0ˆ!oÙh¤¶ Œ¯„ƒHi±T´¦M¹ìô!Åzµ$è>0ä¼ZcØ——wqøMNÇÕ‘¥Óሔ]z%Ÿœ 'J?õ ’oc@B¬ qi¡‰`n W –GúbÚ€À4qøŽI­Ç€”µ‹~N³s·”­' S¹B­Û‚`â [ 6¼rj|¸TÃ[„¬Ø2š%ÙLÌ0™lÛ!.[Šæ–µK$¾ÔUz.¾”­ž°£K¡’ôÅøÚ±Të9÷¥îôÜÌK=ð•@þMf0¿"â¯Ö|üøÑ~×ËÇV×´É i¤®xÛ4† ¬¸MåÝRjmG!eÃ÷.u]t…R¼’ªx'@ È(„‡ 2©NCP‹N2¾Úçþ®Ë‡ì¥]tŒ±y²&¶qƒ‚+ñfï$˺Ê1 ?¾YÊÞ™@¡ …›ÚîÄ ƒÓ‡€§ ‘7ªyžøuˆš;ÄZh*Ðhrlòpˆ¶Y´ÌR­áš-UÐ!H‰ x¦ŠNÛdÓ´Äi™·Œ# 2ú¤€¤øb×…3±¥xsºˆ»sòºˆÉ ˆ¨’:Í®¯[þ˜Úkæ¿é»ú»&t•u÷ž ŒÇ:Šm¼}ïµhø]1Ž8T^~¨‘Ž¥ò þî!m™¬ª˜¼ÓÛャ[÷ª&«u¼ÝäÈ@#uwA,]¯d›6AÊÚQc8–¼XV¬pW® \ö”]…bÙº xíj‰V‹Úñ “¾ÙÄ©õšÐäf¦ÀÐpV¥¤ÍVB')Ì&á#×ßRl°J(³ŸüùÏöŸ P1A* .ÙÇå¬AB<-aG `¥”³˜ÉJYÚFZK9²”azfà‘!1hÈÌR{&ÒÙÁ!DTéÈÊÎCtÇéL[Ênò˜“µÄç3¸™‹Ó”%;Ü S3r² Ãí"šB n¿5âΡr¨œ·_¢11&ä-Ñx"º\ôs'YÊzBRó¢Zƒð8² 7["˜š7¿ÀüæQØ…›22œá@ˆ(a4™lU–¥Îö.KACFàáöeGÏ}'«ûÿYïœÿô§?¹ ÎÖñ;pˆÓó»:]Tà@v9Xx4WS M@îý§ÛH_ÜÅ•EìBCÔŠ½p1A·ÎÈJà|7Oðh ŠvûÑi0 ÃI³q¸BAÊ‚¡çhÝ#—ÞM¡*"dÅR–<…&WØ„p2%¬XJ šÖßþ÷ãC)àÛÖýâ<åý…øþZˆOvAÙIšÐlÝÑoÇŽ³Àã´ßÞ¥zê,mͲýVK¤¥^3;71CèH]ƒ%åKK×K„¯L˜O1? ùæ›oì¥;Êíd Sµ–mÄ$®Z§ÔØhÂ…Z¼]‹™X-}1A¿b)¦Äî\¦;©ðûJD!AVw ~ê‰âO ý™amu颸j]2ßÛ!íEVwKÛ1Lf[°D¸vsŽ” €ß¡U.KV•]‹ÕÚiâ, 9Ü)"X#ñ+§Y,[UçÙîÄ6HG‰ÐìÝ̲¾?»zd&þ™AÉëå…ÑåþÌÚW4{ô/òù0Ò¾BŠùmŠ ì¢v€e•Ø lGg‰&…)‚ˆ—½”/hLŠÁcžÞ—ד ¨•Ê«KÄ’¥ ìv˜ aÙ Cdáüôá–8<ƒ‹‰ˆ b¼É&Þ'"%pÖ$Y%@píé¼nò¶¦œº/HNÏ‹¬ÔisY4!¼^·^e¬éK£ÆÆKeÙ*G“5™,¾®áÔº0–Ù¥÷x«=N %N]x¸\£‚ž`ç¢ަ)°ÇU/ÅßEÖ®i-ï}ÉâoÚ¥Bòq’¥’O“~³A0³àL¬d|K»èÎh6K4…éþnéµCU7„¥3µ4·¬‘ÂÞ6)ó@4ˆ¾éx벤×ÇÍ'6 ߨ Ы…R¿BmûBX¯‰G(†_û8'¹Ó4Í€ ¡vâv!ÛFx1B›*?÷{ûÿlàMµîØ]çÐÉ».] )Çîþìb]\>ZVâípW“ŽKÖ³¤V!MËîÆÊáÔ¥wƒÐ!X­ÂŒ‡Ó)6’r B†#–FÀtÛÇ‘ºdÎÍÖÖôÇépTM§ªJÔZÊZâ#O?µF"˜2‘Ù ß–ÛÄÓ¯¯ø·¿Rƒ|Ò| ñ€pû4léZP`Ô>Yþ/Aÿˆ°«ãŸ0•³j <Ð.Õ²Ó›š¤ìˆg–8Ll;^;.Ÿ×R`®¯¥ácjÚ§)¥øÈ<…–p{´d µöI÷‰vÍ싎‰u)¾g`Öõå]Ž6ÛÀ•@0y`Ã[F0°*{çÛ&ÁîvWÙ!,‹Ð}› fU‚N£vMU/¸¯‘O<»+ˆ7ä¶f’º» ·4ˆ C¶Ížý¶ÓMåJv?´Û‘t4JG „ D — ñNµ#0<¤¥¸ NȨ™™Ûl-\Öí΄@Y1o0ú=nž»»à¿ŒmÙSà)¶):FjÌî´`¾Õkñ/G0¿F\‰¿¨mx‚RÄ#¶ýR["¨µ#ó0ˆ«Š)ÛQ¸@bâÍœ8Ÿ)1±óìò‰iÖ.&‚X _P/Kq×ZÐ<âëR‹†O$ñÈyH)¾oHú) Sƒ[2K]œIdžU“o ¸‚e æï@bò8²‘! *)–RR6)V¬€÷áòÿøG•®<“K/Å–áøáõ«*Mp)}wÃy)²wŽX RR‚RWÅ™¸€lš ãÂ;)`ÛªêÚC, VØ<µHRÀ—ŌϷ¯ñD"¹eL#ÕEw32sÌÎj!O'œˆ}¹Zm ÈbBjgÉà ï&[PŒ#p;ÒW®*Ä< òpK£¢ ”¤èe+  Áº(QÞéðDXK©^¾2 +¨Eµ¼^<0N10\I}e+ÔÚ ÃõÂøôï¥p‚ÿ Þynž?:vFªkÝ= viÊÂ]†Ù³Ù•ru€]&ä®//ÐKY2Ÿi(Àu ©»HÊRYÂñ‰çiÂy4ˆl|²âªšÁrj‡w-ï:ÈÉJuŽˆŽeS Ú ÑTRU{¡c‰œ8NÞ«*lì£òòêïÞö±Û?\ã§þµkª»÷vëW¶|ó³=³ýðÝ™ |=ðS|Ïæ?2^ŒÝïšGÌkÚË—X#íld¶—fhãmDšû¤cqVlH¨ª,² ^hu)›2ÏpxµÖx‚¯¾úŠ¿(Op>?™‡iY›@Ú,¤¬ÃHR8½<^;~%Ý…‰Ê#…4–Êv˜ºúúóxù¥”tá^† Ú¬–”YjÀ»•‚èË»]ºoâï³~S!tÄm¯ayK(g‹ëÒj³8Æ{¡?þ‹ÌÖ"… ÅlY†)®—CG L5B:#Ûë´mÞƒo Ÿ‚.5ƒ*ˆ˜OMŒœ]s=^È¢y@èáé2ÅQ›È–âtò²–À†@lSÖ0ÊðÑø:“f³‘jÚK“oZ|…óXȤ @ÀpÈÂí…£yɳ)ï%_üÿCXÓ>|ð3]ºL†é*C-yˆIlÇ`@sùÆæÑ^``L¦ ÈQUbvÁ§Ü6³."ZKA}Ñôõ&!øío›Âû½·ŸÆhΦÊCX‡€#à÷qÓ²“±G±Ál0Ð)aš–oÂvdé"¢ÙTA–­£¬="³Êy q.…f „à³å²ÀðJø@jI‰×X/³XÌ"¤ÓÌö¯ BgRh²¡Méi_8UÕš—òÝë|î¿4>íúy¿7ò4!wZ³VIP²¯ ®Úÿ¹™ÿ%¹ý¨Þ.hÚ”Ö]±Ë]ÓN[k&ێŽÙýN¡3Q%@0{#§)…¹³’B+§†´4ž_þ¹óÓùbï[–WÞ„ô5remÙ;¯/oY†Üظ „f~‚‡—™òpY]’jÙMè:ÖÈ)á4…îU͹r‚>›ÖQÉûÍÇVÿ¦ ¦_r÷ö­¯^@[örGÓ. /‹#àáyË=e½n8.&¦ kwFüqœ€^Rʬ *É,eÙRîžf6ðRúîìÅ&DñSâ86èGþo?³Ó,°)èA&ØHî q7’@›ªß.€Kåg þÏÖÆx%þÆÒSlZ_eÓÁ\P¯ÕÖ4oÉLÈÃI vÜ!Çq]Ò,l/@jâ²ù””ñ&PØ=WÈ,]n¤’:&%®¼êKJ „‡7’€Õ"©ÄÄŪ,Èé”å!ðLJPJ ¶rWS KgåWòqWï0ã×.ý‚6%ž‚Fõ­¶ÝW"7 M¢ÕhÆë!à»Õp:P—³µ "D`)à•Ph²Qèˆh êæn*­; 8f‡BA­1µX(¦__^ ÉÒÇÙH;âSÆd²R–‰@"Xlf™N#ál¶R|ï GÆQ§_@¼^²{ý*¥ ó“v¦¼ §—¤Èmͤٹ‘ÝK‰Š.\[Má+ÄlÈ>íí*àtʉÃkì=¾×#„hú÷vp/#ö úâÄ·…í}7¾`–ˆ¦SÇiÚh<“õǬ?êg-kúF@ù믿î™Ͳ“ÑNl< £Ðx%væn]w¯¤½ËvPåm$$YàÊ_i^MÎñ–½Ó¤ÔjÊô^îÃ"ý§˜w““Ò—·^w^_ 3ƒ€‡H™§Ý‰Ë6'$P¶ZËKæ»—3|G4@A(0xÐjæ–Ö”¥‰ ËWÃ3a)%YKYËfÜikD–Ž.SÃl)ÕHÔÃ(PiY%ÞcˆôáÁ©’Âo4·ôsS¿¬âÃ…ðz­¼gûÔÕ`uTk©µ£kš8œ~¯;7Ï~Øzˆríì—Ñ·´G­¹[,‚î‚ZÀ­ÔÔ,¥X3["ÛH…ðjSkGm ^ÀW›WbùÜßuéÅlÓÖ®ùÅ5m*óo¼Í#b‚FèÞ àpàNO Õ“XUíà®2KL†Y€è]q)‚Ï=_#ýÔ€¾FZF óXÐ$^¥ ˆßáM+Æd , "~Ź/+tÈ”{Ö‰`ŠY‚–l±@ ùަÉ3Y¦Qço0O´]øºîŸRå»]#¿í éÇöÌKœsÛA©¢¿y,»¸×Ž“b87/ö]ÂH]ˆ·XÖeòê§ ²u\B¹^ÓBºQwÛQÀy a L•¥ž”¥T‚–Ô,™*cÃcY rIžOêw‹ÐT©ñø¬Že-1ME³ìJJÅ$y{²¦šrq ¬Q+1¤,S•2‚eY s€O¿C6”Z~£&Õ¨íŽ Y uá!?ýýï_KÖâÒb-«ß(IÄGcuEc÷ò ¹²7D óRb©4³¶Ýi&Õͤ©¬ñx8ÙD“Rl©6¢£˜ŽÃ­‹‡P#}W 7L]€L´ QB -d‹y*!5Pa ˜Q¨{R]ŒÔ¨J2K&µÁ ÊnNv+·M/7˜d1SÈãÈjmi…,5 bxV|ÉNó_å|½ Æ?©ðe·,«|;¥“ÕÁÀ^vó=ï?~™Õ±ÐoxM›Y_Ætnb“xñj°8Í/²ñÛŽ%r õâáL‹LL™¥„(a‘)žøë ~·ÁO¤XuïØÅ†g‚û}¾Ó;|?^£z™ ±4¹ î4à&„³†ïäÕhyä.³Dî†t>jï%ÕvhøGýª¥†É7€ZK© ^.ú"úΣ¨Ü àE#qH¶} ¾º Ú‹'rŸöÌ©¤óÁÁ·Ì0«ª¤d²à™¥ÂJ PYÀÆYŒ,6“=¤ïÓ"HÑ”²,(ÛOÐ}›òÑŽÊ›æbùÜßÝ;Šº_ƒ)YL½œ§eM1qšªó©#?ެ _ Na².–Êu ü©:~ú8«Äx>¹Z¶¯g²8Ýh@ fßÃ\M ”ª~b÷/×ß~Jçs &¤ŸA¤pX{'o¾‡]V_d K?2TØNñ1“³~¡íð”ièEÖ’YæÍ ‘î–âžsÛÂfnr^m‚{Q…Ó®áj©ARÀÁd@Lßm¾øëM:woGþþ4å.Ÿ ìبÓºCümÎvÝlãX*¬–'e`^ŒÃ¶):Èùp© Wá]¯}ÃìèVˆ/FðQõ¹¿üã³l—OGúÆÓÒ•ê|xÃ#dh‡i6Óòpž3)ÛR|ÇÅñEzÈ0F’u‚‰(·äLÒyʦi’J€S% q_ùûûݲ‚³]k}ö|½<ŠÛ}1ý¦›¡1šMÊ2rH#êý—»ôǾ9º1ú~[GSçõê&l6 À¹¹ñœÉ8]-P`¶†¬¿ÓNÓÒK¢‹…Öý,륃ÎdßiHeh2…â14H%¼Ø ¬˜¦øEàqŒR]ÖZˆU‰YËž»b ±ªLìRÅüý¦7YjL6{Q:çÜÀ=;˜ÍWÂ3d^ŠG¶k x4P|:½|I@þéþð‡Ž¾®rÚðrÊh©TiÉàL†ÆŽäËÇÇúÅá-)Ë¢©wa®º3wLK±S£ ¿T¯à.¿òö#K¢*2åZÔ+Ma#ËfucJÅß½@S/B'‚Ô]¤î³ÕÁŽ,Yä8i6ü+‘:¢Áµ‹i* µÎ#yûŠSaó)…“+i›@³)§¬Q`xû²,¾% §V|pV†ì¸ ï”´ÞØíQÇf‹É‡PPž‚˜ÁÍL‡)‘ _M92PaG‘ %°¸;Ó ¨¿ñÿh»ÛäHŽ# Ã2ék”Œº tbÉ(Åsì“õ6|jÁ/ §7~#=<<"³ª \áCèÙÿø•ÿ·/[&cÄ7U8d»3XWóÚôÙµÉW^‰e[À#³M_ªÃ¬/&0š%KA'cÉFÜm…@ã°€²€² vk-q4^*DªW™î#Ô…&Ðc G´NÆ.ök»>¥Fˆÿ«ž¦«ÇT1KÝ[†ËB¤ù6è¶qÏ0ÙŽY!š‘¼gúÕ¾ú%"_Â5Âl;ö«£FºÜç±Á6.ÕøÍ¦¶×ÅOð¾5d7õ “QîŠtÆ3d¯â†AÀl€vg‰Ì#tòFr±ø¶)5<#ÑÝb|‚*”ò´K!(aõ tÅ«2qAYK5Fj̺CpšÁ)X²{»á‚fШB[p’Î.ë³Ã‡gí7²]»|ÈR`“à xã¸3ùÆs°ŸNL`ÈöN"†À ¯1» –fæ‘yˆò†W(hf1‚¥Âhµƒëµñ€² ­:óñÛøbšâLV…Èhvç&'Õ9“m:uiZg"ÕùÔBV‹(^ÇÀŽWL<&×Î{e§ÚuQXìc²JŒ,P…#î#€j-•ÐDkû;@”bbäf°\к°È]h1D‰¥¾b ÝfSE$°€ï¬˜R–ulxž&“ d•h$ ¬[³KÜR TU"@kÔÆÍI*ñ6HŠÉž4 Ò ^ã¦X±iª‡eU– A|Ÿ&ÁFéøÄ8‘1“5SA{¨iúíÇAÂ7-ÏdÑ,©Å OY*~4Ì<¯VªŽ¼1U¡%n)Nn‰ÆCxå cÉjç>Ž 9n%ż–Èâ«è8"M¬¼íì‚9A|  `?ñfKœ‡3UåMÒ0ÞŒB´ÖÇÀ–¤ZN¡ ­ ÄWÈ×N°Ip¢Š1e1‰T[®ê—Á4§²*À¤üËÚ§WÁ@Û¬ÓX/ÃëÕ¹ÃH'V#ÌΡåvÚä¼’¤Ä -~¹o¶Ãy·`ó(¼4ŽúQþ ½ÁOéÛfÝÝ3õ2ë ²!ÅÛŽexHGÀRë»Y"–áûèN£ô§SBîäÛ»%2MPÓZÜ=<«WG-V¯Åøki 8Ȫë"HgB”X6/Zû²Ù8|:p†Üu$ëËžwcüÆø­À/Xû-‹¶ODmc$Èk ×QÄçrìŽ]­c×Y‰WýouÿCÜϸëB9MM[ÓW|&{»í &ëÐxµ¦ ’b³MP‰,¼T^¹y¤µ¸ò—M±g“/~•7˜ßÑløNbrÚ¸mê%Æa÷ì4š$…m޼;¤Â@:‚|GÁ·wÁºG‹O­?Úùvóóý—›‰Ûˆðº·Act) ÎãÌø+[ý¾T5˜6Î(3Aó 4Þè©’â ;³9sqä¶`Ëj“Šü„7!…D´`D )0§]KuVð+Ž¢;à ‡0dßk0$|±ùÊeS€h§ÐMë?xÎÙ¯1|:p†{»ëTµœo &éá¢Ç ç \›ßî •Cl¤Bo;m\Ìð-mP|¯ŠL*ò´uûS•/üåWÁ¯ 6Œ.52•axíœC—^´ßNh_qÚµl„]På‹¿Ó’—U~&x{mVkY¡S¥¬–é7‰yNÁÛÝX‰lyd²¼»ÈMºš•|Ðû—¾Žˆ5V ‚ƒÕZœZB¯(æqŒm;í¨Â²lSI"Z«òlâ…>`rÛ'Þ0 ¬…³ ‘Åd–±CfKæ†á},Ò7öxÁǵä4»F†‡H‘âSw8‚»Õ]¡.b烆à@è“×%©Z‹×"„o`ž‚B hÊ#à7dåÈ‚6(Û­‚` µÝ{õ6ZRpÊiò ‡`xM_ÀpVE  ~,•7áùúФÇE>.DPEÑÝ=õpçm©9(¦ŽÐx#¶ÕdyVwTKLWØH™¤Fhä aøkŸIÕHašµ¨6þt #ÖY@ᬶش¥0©‰¤‚X!½8á)Ϋ%å:áOSÊ2e%¥Ð –YÖ'Oë #W3dµIñ½fÆq°UU®JIU¼¥¬’w—»Ë·9qBájï{9Šow FæG³ÔÐÜ]O|“Èïx?¨½¦8w“o¿&w?ó™í2Zšj-›œGë‰&o#º26²r"õ²vÔm ÙQÃ_eõÕÅÛãôMh_phL1“ºK"L ¹eÌ–pÙŽˆ«bpþT¾=--½¸RÀ,+pAã ¼ö—þûßÿ6¼ŽÄÙÚ‰¥Ä$–†i »ƒð§ÖSÖSý¨\Uø˜vé=îð5:ç²ÊIA²éK zO¬#Î ;"ËÓìí£4)_hžûŸdûiªÏS(Ô¢@ëÓòjj`í Ã0ÁöRÊ’¹ÁDIjb|1ïÕÑý’ïGˆ‰|ÖûÀSˆB…‚â cŒb¦6… 1oéAïFà–Ý«¦3U B½¬Š—R¸XÀ4ªéDp”Õòº¸1ÐX%˜KäøÅ<œ…—"WN¶û‡`·Z÷pLˆGñ@ˆ á@Âù•ÈŠ‰·H[×:„WÈâX 2´û¸½„çzk­]žHK¬F„«×yOOÎÅo«Avs LohLž¾¬BæÚ7"œÁ[ :;µÚÕQ†Ó<¤6Bµ|±›æ‘x;;ÁDp*Ô(2Ä0•Š,e ŒV <¢o÷Çz%ŽiH±ÁíH,h#ÉâEÐ÷>å˜ ³©( Éðâ ÝUh-UÅ!ÂК?\ h…³Xêâ>Î0Є8Ä«ÆoZL6œˆXG–¾W… jA'2ßj¡D\•”`#•VU_;e5M$üµ_Ú5e>–ð1‰.æ·tëÏ’ 9 b*~`»æ…g‚vÉgøjÛ&ZÇGGA€¼³áLp]Dï&?ûg(ùUßöµKŸ7†Œçñ½«d–˜µ8âRJ|R.h 7FZ|)‡“T¯ >ÁN©ZU‚Fê¸ Ì -£af- *¾ååñ_ ›N'ÀoH½*G°œþbˆlL±‰‡ø5Á–ýCï×~üð]-ÓÝxL`Ô6×âšýÿuSñ‚^Ñ”¬oå}1NSê‰Ï'èõÒåƒ8%ÝK5yËÆ€ õ-n6àî…bªÂY°íˆeÑ =d N{_§›ä[¼_þñp°/"&\kK—CkÓÛ8Â8Íf‰ps–”BÖ`Mn©¤×‚K×Hy NÍeD0™U#-&€¼Zïb_x þ¥1Oú‚z5@ã9˺C0;«ö‡49„!TÂgújq ª ª…XŠ›$Âý d-ãø׃¢]lŒÚY†8.ÿ+î'^w¾;rᦀµÁâÚ½›¼eDàñ ¬Và fs{X&ŽßiCº¦*AߊLíS¦~÷É´PønÚæìF5ò.½¯ IÁ‹«Ð 4[æ©URÖ. b^Úgøªˆg Û²HRb&¥V ¯V¶€—ª|‚U¹š‚¤ZP«’BîéçV±”m~KG!EG*e„˜–ÖHÈ8wDÜlp‚D¨W+ ï4kaõʣɿ¾=µHZB=ƒÔ^å´´dÈW´³èÔ uÂWU›£u]6YPJžŽr`Èá½õµ7w†lƒ…W•,¼‹!Õ Æ$%ÀdRµ a²xY ÚKfÌ+ÍÌÉF–ÂIDaË8âõà³ 8I)7mµëØÀª&¬œÏšALµì,ã;R}™¾}(AÃéZ´Óø1SÌܴ'UÖR6UÊw퀆GKóªx¼Ì¤˜.í¯ú!¥ð B L!)íèýÛ¿O¼ÐÌႎ¢Së¨{»F0UãA§ñ¶Dˆif:ð†,(•·Ad8Y~6~´–wo‰ÿÚÑOóS&Þ…³¬Ý®¬¥­™­‘Ú£½T·©®]gÁÌK%(Ë<7»µsòé 0‚øÊ–œªÒw?ÈBò‚wÖÍs‰lY)¶^ë²,¤¢UNÙÒThLŒÖH@üÞ^ÃýÔûãïGþë_ÿòf±û&q'Óö;Lœp“Ô·‘ÄL–¿†z|©‹Ü+±¤gw~jŸòƽ¯£°$bòeñp›ŠÓBðY·Sͨ̚8¾A¶GH†”òÄc/üÞØ]Ú Æî`ßÚ>ž½­íØ‹Ée Œ,œo#]Ðt¶£e½Tõúj³—ÌãÝ@3$H­^t’­B¸;ð#ÿÜ|›úýÀøTX#Ò=Ó$õjZ @éXd{ºÂqlBÄÌ‚ÈÕ¦ÖÐâótȉ/e)îdàÔªBŽÓZ˜Áû°ÆæÙZ4 rîOý(÷ÊýñÇ7†I˜¥v²&yô¸þS_„ÆÞäù6{‰—šãe½ˆDlS¯ÀzÅÞßy¯ÝG[tÿ7‰î‚L ú¯ k$БÉvò)᥆T Œ,ÅîLqGÔö-™^–jño=žx)£™Pê~¼ÍC~W•`G§ß÷o«üÒ¿ÃÑ‹Ñ!k’õº´Ï+BÐü|Q"¾J¯åR[æÛ5Kf/@-°²]Œ&…l)ÀÜñ>Z~ø?î"?möɶ³©hJ™¼C®Ñº »-Ë"31~YH³]É£&å|€h,|}m'D/¶òøúBãpÄûvI­a5•*PµéW$’¸W\‚¶&«†{û<ÈÄ›ŠW’IUE°yà‚šò8ЪK±´M;:^ÜTú"·ëosv¹+‡tÑžf‡ã½»/BD€Rk€Ú‰•ðzu) Ä:¾D ^e}ÀÓœµ«5ßi·4j· ÒÓ Cóu¨,ÁtÐ(Ò—|d hð|üÎ32‡g"u´ðR–•„$aR,r,q›*›,­Ë" d=£Ì ‘â…bUÉ‘yˆRh>øÿøO«Ü_¾|IÜ“HÃ숶5úµ«¯X_ñlY bgh1ù6"î <…Fõ=¤sH¹vÊ-ÅFë"€ÚïrK b" °yK¥ðRbå-“ò—Ó¿Ä|4`kúj¡‘=êØŽ /Ö+NÓ"[²¶Ök\Jmw¾À2ZÃßwAÍýFY*&)1¼µ3…ô‘ST2ïûψ?“ЯJjÇÒ0]Ê&l61‚X`×Í`*%ޱshƒÊíQ–%«=‡x]tËzÅQÈ–ÃWR-M¦ È7-޳… êU oéÕêw¥ŒGá³æáëHšjé³»ˆÍàÅ7õƒsM73äÎOD6å WKyËDÓ×c#Øp®Üö=^žþßOݽ LÒ0 ©u›%Ñ]Pli/Èæðbƒ5’Kñ´é¤H‰¤ÔZ"x†ÀÒ)k©‘Ô)Õ³$Å®üÿáÛ4/®GñçÿÓOÔù¢®)AC®»àἜ{ìXÞoKœf¶eå•t]Ó8âRt˜éȺñ àØ_øË?.ŠÿëèýãÚáë¯{h~A»h6SYn¶À§Ó’N7Oóã3 ,µR ^£¤ðÕëÕ›WG'Vè@žû0»vï¼×‘Ñlô¤F:6¹¦ª:ówÛ²hdUq€¦õæ '„P¹€)»-§,Õlhï†,E³C’m`ge \V9}æÎyîÏ*òoÄûŒœN#ñ²™¥ôš„ét½×–)T•DÉÊ]ˆ ÎЦÚW—Í d¾F–O›¿ƒÔvøûº²K&fÑ4rþ Òüž .ôÆ#b jyåMk©M¬–Î:Þ) ”Ñàh߲Ʃ’l)þB­’t*MÐI6¹ïüö¸¬€‘ªQ—› ¥X`Œ&Ça²Yd»cbF AÐxüÄ$¨¤lVkI!(y¼\¡¦×¾'©%S)žWS,%6(OË夰C¸áªRÒ²NM/#Ø4²<³ÄD0.O„&2œ!lŽ*KM] K´M›>N©«úQŽn0÷\±Zj¥Ò©¤˜†C°»V __[P…`$ƒA⯑*râ)¨bø•”â4óðq;šôûnUl`x%q ‘¢&pÚ­ßÉÞ—L¯¾&=×eK>(à·ÇVEDÐØ¥œ»"5²v¯ý+õõ ŸF¾±»‚NÙˆc 1&P­9áâ.¨×‚ìöRÕ–é[Vî–ChƒÖ=}¾^%£•u2¯ý.hä>kæwÞfÝ<Kól°‚ŽBÖF&"è|€¶ÓU¡Á1ÅNgH"ÖzKA²¼sS¸913©@ÙÅ eIñ©á<_ÿºÜfëâVÈg• *¯J9r‚8@çciÌÛ¶Ùþ0ð,ýïõ7U4"E8kZ ÙØ@™7CË&ä!öÂ+É7Fd1>Ü2ò·üÅLoìlß&LSà<)›Áv´@Ę|41G\‰Áš\ kÚfÞ­óïXjñÚ㢘P#ÖqébÂŽÚ$vÑ`b¸¥QÅhó=F( 0‚hÅhâ&G#Å(”M?)1ƒó5ÍË:„ x)"ÍüÜ_°!û«æ÷[ôòr­µ`z9Kí̦ as”2˜l[K¼-w â@"d‰38 ®c ¸A̤¹F;Ï ŽB3”Š3Ü’!¸sžø¿eÑÔË·îÆk›–Ôh–âáöt²ök$qÃÃq¶ñÙÉÛÖ®éN-ZRñA®µP},-@+‘ ¯ý'Œˆçƒ7Dh6x[0¼CÔK¦_Š‚í›Í jÚŽ4÷U©M¨3‚%åÄ1áb>¦á#åi¦†ß|q^—¥¡ÊRšÚÐÏRÜ]í4B“ˆÕòuQØ%(k)U¯Â(382в](aÉÖÁÒ0||œÈâÇ·V½ê¬mŒÇncä”]ó<\õ8b!˜{ÙKEhÜh|íñivÁôöà;)`ìºú¢HA(¤Œ¦¤oɇ·á&„0)µ”›0Ï È”M´RpÙÆž~RùÑJ5F¤²–ô{G+P›f½š­c¡€ŒV#L)U™¸e-€–㬅ÚÊ]âm§v–øÊ”+éØÓIêô¸¬eþ’ÐäÛNS X[Æ· ¯@/‡!‰Ø¤-¨j×.¼¦®;pgU•‚x]ˆˆË~êe%¿ã}üߣ­º˜GÜг†ì¢¼aÿ¶‹ûÖ# ¿]·}¸@nw틇tÛkZ•B‡¯ÞC iN¾³°í1Ó›~}eÕ*ì>_—}ˆB⌎K)˜ø]32~²ºï¿ÿþã¿ö£ÊÇçÞhî6;ê—Ñ÷ßk¢Ç$ÄÛˆv‚ãX²R&·ÇÀ–b²Å–¯¬§Ð-Ô"%pžÆÐ…xf ïjjýŸg»ç¼ã5j‡,+æ•PÛ—  ³AžÎµ:»{iàLüƒþ]Ûµc7€.|²íŠÛª%¿Û#>ƒÛWœæwlUZèµLsÛY šÔR8“LŒLÍ _{ ~߸Q‹î†Ì :Bš|[3Ž!ó ß‘";ËtÚ…rcï4¤êIˆ˜ïˆHm×8)4L³ÕGc=j˜Ž¿öó©×,åŒà—/_ìÂRSÊ|©{€fi}Ýð^nšên›|U"[ŠÃÕm­Ø¸%#ÂpvgYƒQPe¹yü¬÷|ð}~U:jG¹óìùI3”…àˆñ}©µk;Þý­wzÕÒ—í šY¹%ЦÊÛW ܲ’˜ SŽ&WÅG_P ©È‰ÛQ›º—Ä̈½»-íB —€,M±«ìˆ6€¼zž×HûRK_ìòQ+N³S¢SIÙîg–_|aWÇá[S©¥ânÇM”7*«X)æ[Bˆ´%¬áhbœt¶[ËÎHª*Þ$×h:­Q‰tÛ¥™ $ÁY»ù,Ųœì IYºoÌ/@€T+®„`²e t”P—®‡ie+A I¹¥-#ÌÚïŽGJU%bR©‰ A ?‚˜Ev}eY½hM“H‡™f-à„HYfø‚Óã­Kø8S@@¶Ä)Ň ˜yx³Q`È÷i{©|ü_R^’r~n늠nNCVÙÀF2'3•hÔ]\L©˜ÎY€“ÚµÇýVYŒÉ[jͨѬšw-’Åœ¦¬ ?ý{œ:¾3-üÞ*ßÔN£ÙR³ñ],S lBLÓ¶ä™Ýé·_-ªíj$+à;yLqÝ‘p½˜c ÏOÖ­v:fkw¦¿/afœ8K¨…,ý¼IÚfèBö5Ò¿¶4j…ñ~¡Â_ül§ôÓQH¹rú&iNçÖÌõåÍÓ8Ì0üìäíxÔh:ßò["¾…îŽõŒ5s'£{3˜YÜ^BÍ•ãˆe ¡*c0Û âSÃ4  „K¡ëB[ÚE!y…z!¨Õ%ý&ï^E°d¼%}Ÿ)±ä-eÑ´ŸÇkQìF®GHÅßI“ë&3¢Oºû²Æ AÊ2qqˆ,…pžÄ)eÛ‚عc&ˆOÊr§“8\ÀgñïƒÉº )û˸8&i$WÂã‰Õ ŽÙ.xLKvʆ49PLs¸^†ôh #1YÖëÓR ¯»Ú6n)uoZ¬,%›(ÖKÐ0²{é®QU8|&UÓ{SYŠ)Y ÙÀðâJp0mdüÈ+3Kf±)$îÄàfóË?!kôí/ðž•5Õ¢1Î4×iЗÒTª^p³Ù‹‘œ<œ™ ¤’BÃQ¯PvAµ8mGÀdq”˶„Á!·|í/AùŠÞÝZw;‰ cŒÆnžÎ²ùËšSÕ¦ øºHDÜ™xe™€ÕKJ\• zõÕ®£Ó¢›GÖråJªj 4…†<Òo‚ZŠv¥Ju Ĭ * o¼vl­ Ü’šÍRJ¡÷Пý·>;÷î¿-ëË®ñÛr¿ñ´;ã^7'V¹ø”]…éð¼*&‹ÜIÊ66Pêéoüóq·¬Ž®¾i‰7†vôe¼ØU0óJÚ¯y ;g·×934-”Ë2)ÿâBá«ÌﺜßôÉŠ'®{„/°4O|^lTÁ’˜¯êþì ˆH±ÈZÊVKP*ЙôÕ¤ÛÒyþÏKÿÒ?þ¨Kc4¡ëné騻yøæÑÝÒœø†ïE iÚFÊÔº²Å¤$ý²Èð$Ð<Ù=FšV šê(@Ëûµ§Çù¬õî?) Z@ˆhÚbA²!5u™Œ®ª!¯ ÓDhÉË:‰¤œxd§“&}Ç!®"®ãÓÞOHƒšF®>Û[‹fÓK_ e4K÷¹UÃÍ ÖltdÞ×âûÀ²¥ðJâó‹Ûš%Rí1ýŽBGq`ðø<2ïZìr$¢Z]Ä‚ºwøjMkGŠÕrO«Ýx‚qÕÆI¨£Cæ/á¯÷³/|AR=\ÌæÙá“ïFz•7†o¸Ó6Uï6:–w—ÆÀ oB)%–íÈÀ@fYŒŒÐí*ÖÅRÇuqŸKAÄWÝ)Œ X-¥‰óÚèSvY¯0j/LeÁ›§¶ iGy…‚Îjü@Ït m¢ |”¦sµÖQ€£„xµ1‹fÉÄDÚ d»R¥šML¡ Ž&`pæ‹´8!–åÉJ•M?2B š“/0¿=üÙ_ÍòOýÊÍ Üöéw? ÒØm9·Ù3èÛÃV ªiÅÊ-•óJxˆŽb'À”øœ8Y„O™ç§ÿïµ»Öé8m-:XMb Ì&³3¼á;bU‚lL:u‡ö/¿¿Í¾1Æ¡_»ü»*};@ø‚w¸ Ü£Œ`H4²Y©§'€@±*D0LÞ!Wè0!¯=W¹á){ÁºpWçÇZ3)&hTÞÒ €iÚ­íË„‚æ`Ú¸ëNY g„ r"÷í#ÔEŠUµZ}‘„¬€Zƒ ð•ýyû§¿G²¯~øZ3ëhBíšS/{¬Q9[z{‚I¡ÁØÁ–º ¤}%ØÄíB¶  †ÇééêµI°ý¦ŒCó[ÌfmœŽF”uìxÝ@­c1N4G¤J Z/|µ†ifÞÅÊ;OHÓ&+Ë(ÈBvò8ºð@„bK( w»*”B€‹§‰€æ<¥TåŠ-1‹ Œi)¨JÜ®G«)¯Dß!Ç·db…LCæ»g¤âT.e)FF@tÇO\вòúvæÈ3"uá¿”"E%DEœ×Iªø.Ôê¦ ¦ ò] ˆSãJRæÓAnW<¤‘”¸Étš½N\uU nržaÎ_ÀWG-r¾„S¶¤é›ZïQœ ÜšÚEB#ËZ¦¦]j÷ È:RK]R§ÉkÚ´1,•h! Ÿf \­˜]Úlj›Gšoó€‚ôզܲ¸ã5!)H-x«oHL:) $^£!‚;Í<8Ó,ÐHÊ’U+ˆ,ñÏ?û º?¤èº¦ÝµèÞ0$M;bÆ«{ˆ¦È÷ÝÁ γðbâjÛ¦tqQ”8·§sÆÇät¨Uл^†MÇhÙ‘¢YRàï±%žš*HçÐiw\¶”EëE$f =!/½'ç•mêÅÛ‚€x´ÖE`¶¼€if)Õ¼˲UU(–BÆI¿Z¸­‰•D(P…Æ3ÏRq§‘m…†AH ­BL;â«En¶u3U̼Ú&‡Ô(‘¶ œBк(Õ/½s8p4÷$¦Ô@IDAT…Ú$ðÙ.*A'Û+kÌ‘!u9“›Øz^ÂÑðl¸€5"&KK¿–<>P{L8éRÍ*0ZäKõ´Îd½ýóþ• ²z·2‚ÞÙÕ¢³Ö´ÝÇyg1‰¼õ|Ü Û÷bGÓœ”«ªcq‡“‡ô44$NÒWÞI"¬£©m?Äxø,¤îcÆ‘BkršÅ‚z ”+l§ÈqÌЫ]Ö2š5 oZ/iÙ8ÙÚñÅüð»‚rËš"›¡1*S0ÁÀ–4w³*—…#ÎkÿaŸí0·™·¿ziÔåæÅ>5˜ÄHÛNòö’H¾”,ƒŒIAœx7³+âNKŸæÎpú8nHgÂè0©ÏþzÉ}È_½Ë®…iM(¯Œ°¾K4¼ÙlèEÑq˜ ÊòŬ½¤† á#ð;C„bžT-œ†.Ñ.±óLO Ί•tàÍPНg–²D”XæÍfN^¶^µ&˜¡¥Y!Ów§6^ëz÷§Ÿ~"¥—ZÏ@:fÓ¦Ü$›Ö’éß^ȵSË6[µ8ôy‡lG!ñ-ñN(Ïz¿ýìÛ˜vÑåHßvÌ©‹IÜQRâ×àÇ9äû¶l dYL)#á«Å¶/P6ÁÔ"ˆ¥^û÷vú6†Àxu4ƒ°³Ë¤,Kµýâ<Š  òÌ‘² '°Í¦<ÍZ #×‘Ž˜Çw’"˜“¿öO!u :ÒwÉjaiþv¤õb¨"7X—¸áÛ ¦ØØqâ·‹Êóõ²/K¦PÌÆ’‚#²¤fYVÐ †Þ p_Sžþ‘²[ÔgÿÍÐ…Ó´×B£^ku·£Lëkö3->Ãä)„X²v2æE?[†ØÑ^ËøÀ¾‚ÃÛ]"8÷iËÔ>øþÙ?`HÓäôçâ’ÕÅ™ˆSs\‚&4[& Q%«œw!ómaóS¦l/JHYúÙK©ÿ;L¿üÓ3ÙZc6@±¥¦íq—c„8²%š˜)ä]V{7¶kJ‚Ï v¤¤ª–8¥€˜<¤X@¼‘¤Šº¦Žôwöø©”Ÿ”:T;…µæÅ6"hú23wõí´ „)0ÃO(ÈàækÔÛYRL!Ÿ²ZA­‰*1Z%˜¥ lLðG—KþÓΖýà®Ól˜Tè{JÛ‹øæ±Œ& tù"›*++%(‹I6ç-ï³:[œ²p‰æðͱ˜AÐ!ßEžˆ©ébZ 1ånÝzÁ!RÍ\‰j'Û´#˜“ˆ¥;-0>üJÄp½è €búð@Hˉ`ÒìîMÓ¥úZlY9>Ï(·…fX÷–ó âCêH˜BÃôb·Aò”íT\ ¤¾^¶%£‰cÙT8–pB]àõ…Û”‹ÞiL9ÂÊ“:»î¨$ÇkI‹tÅí­6*!Œ–*4qsH±&ùZ^_¿~W…Ɉ˜Õ…ÁÔ¢§U‚RíDʇ”˜ Àœé”­WÙâø #VÅuI§ÖzÍÐÓ¶%Üx•DÎÄúŠ7UÑ0‰ð² R ?4&vì¼½ðÆ6j÷A½ÔV•ÇÁ”**a¸aÄ@Ag˜&x³I![âkO (¥ H¼vBUÕË2) ¤e“Äœ”ì¡ ¦ñ³†¬c:ß}÷àµæ“oÃÐÔŽ7Ó”·µbóÐÆ´ÄgNLü6òùï4)óÌf¥<†xK½X ¥ú êØ… ¯ îãÈ ­_ݦï&ìZtYMni¤Æã7­”IÌ·ì|à¥*”Bƒ\¬#È ²ý­={L‡T}ó¤sä®r%Dà©Z‹áªr UÕW­5Ä­«JSx/. ªÊ›Ââ€|ʵ.R Cù¯ýëýˆy‹³µ035Þ3YëÍ£ }8Nˆ¦| ζw)K3œïÄúºR–,ŽwŠÏÝWþõ‚û‡Ô.JôäK™ªMµ/x4‡`Sæ‘¢µ¯ž0fcÆÞ!JÔVeùÚ¿üc0²Ô­ãØ—1ø62/ËàyÙjª*4¿¬GÁNcd4Yªí Œ„ïXd»1¨YâÀSxíø2×Ï »"ÛŽ™Å†±e×qW$‚c”êߌ"´#)ã15 âDlˆ]OÛDËàWÝã0-ᘪ&ìpp4âÓ©³’E3¡”ªï¿ÿÞá ž0ûúùçŸ~åÚ1â:^Ðû+}›g©®T…mA,PŽYœ×BU&EV­|{éFR[Ó‘²ÚŽÅÁ*´}L÷†ø[ÌyÒ¡@Ÿï(ø®#¤cßTúBøv„`Nˆ§Qá×_t¢é…À,51Á m_ Ä’2ÃÏwJ -ÕºˆøíÂò>›rtNLyH:ż¥^UY ÔS Ø0Nɘ‰É#èÛ²Z—¦CSÈôõ=•ÖðîÏv—×k妒ºó…—›ïj’¥Æ¨o›é¦=£üšõñÿ™þúrÕl³u9ÌÜf7|ç“WOUIKDÌ79ŽÂÜbš½Í ì ÝÌ®jW•Ÿ²¾˜ÅIܲª@-*¤&îIjw8˜µ3ü–¼Ø Z2Ëæ„ÀÑxÓڈ߲Px´>lfðk3›Äi´l²ÞÍxÙjщˆÀÑJ4l*1œ ÎÄofI‡Å(q&ÝZbÊÏýE)üûŸãR0ªy4Ó'®)YÖ0²Å²hÀÌ´n~¾r1©~>†¦„T'ÓœÊ1ðlõíz9¥×þòÏO×µs}ëb`3ðmÁÌ$]àvdrxÛ^9)ÂöÕ¦Òç‘÷¥šf‡ÖûH©8j1ÕÖh§aLß” ^e.tw©v ¬‘€¿Nâ¼YAèMœRÊœüëznGð–f“â-y)Ù@­=ŠÌ’¬“a–ÈbSõê@¨éb$^ t_’EðÙ¿,ä 3ÛÃÆn/D·lÁfn~¸±)HA/‘JlPI ÜüªÐĬSÂaø Ö‚T"¶Ùõò…ÃS%…Sùmf¶æ×ŽYº?I .0‰ Óût1Ò¿ÿýï½|,)ózí|%°4†Tlž®QŠ&ñhÅ“î{€ ¦²™ €¦— Ø5&¹/{.4)%ò@L%¬Rðû’ $Þ~Ñ&>\LY#© ÕR­Xà`1»=ÖEÊ0 5†‘Š=”+´ä‰HU¢Ü²^ÁÕ¢­uÞv Ï[Ãkdû‡t,qB§aZY \ 7•[K¤§ ¾C  Eáìööø£`i¶ž< fgW¨Š S_± ¯OhİRÅRZá!¥ŠïK…ûÛß 0Ú¿:ìçÂj5J6)²ž'<Ü¦ìˆ šØðÈ}È6Û.àSƒlÚ‚4q’¢ƒÌ܇Ï}êOÁô !&ÜTõêL€.V³á´©ân0ÿ¿?â ÙýfR|w CP¥„šYSÏá×þ¡›þ/WÚÙ‚.륵ÁX;²)f†6"¥ aæÄdâ¼ K4f™AvbðʯnçbÉz¸«Ý!NÃK©ÚZ %Rwß—zV(y‰éÛÇzµ½ÚÄlgÜåÛKÛÒH¼SªªS…4ùU}îv£¶ ) þÚAÚ-Ó)IÕºg©,w2dþùg»K¿K ##H\PGÁRÈ]>'``K&k~%툥*¾X ÇiX*䙬Úhbû²÷m*…“8»JÏó„‹×.KÙÖ,{6¼Ýñg«×%ÆilK´n†@Àø¬eU¤0eµ'Z·œT[ëØÅh.D]ÈLB9A×T ‹#+àkáª>·ŸÔj â…)hòjS+l˜×xþ5‚¥”’6ˆÍxÀÈR,Ù¤:–ðÅ–•¬°*š¾—Ö®û RÇ¿üãÿ¨ÞZ“3S£óÌŽÆ(Šùæ†àCдڪÄ-ó«5SÅKÁéŒ#¸ò'%pÙ…l%šºäî9MíªîTQÞÅ ×¢ù“…Œ™‚å˜eõ¢<¦rÊUµæk„–!ÀÅðæ¡I˜~3 31 M’2¾ FAÖ}Ì^i©ÑQž![ÖN@Ç ½±è&MY•,ÄSÈÄF‚7^Ýqèˆ$åðq,Ío¿‹‘é Ie‰ð–Í&›a–•ª{óÈÖËòµ?Ü×Îf}ŠÓü¬i;Ïö+…ÏÌ"+€#ÃXLžmk‚®‚`·âø‚˜¤l6Ù;qçlûM%ðÁñ3Í‹Ìßž×7}ÊZ‹Á7¿¸MÁÁàF²˜à'kw-ïåbú̉#Påft!ÔA!’TúRé (´,+¦Ï0‹©EÀ4¶xKkÂʵS‹ ¼l„â«ôè#ûuyŸ¢ÝiãÿaàÌý³¨%N$³4@ån•Úé¥c'cþJ ™lD” ÒTÈêU¹;ß'{îAz;Øß%b-š¦ ÛÜ…ÓW¶+ØpãEÅ{@É6•òYµ–8Dš* 5òyî'kñ.øé§Ÿt1¤¯/šv’mï0ݽNR!Ä@´¥ÜÏð¶FÍ̲,Z%qxíš¡}áX*ÌJ¡uz–b©–i®{þþ÷¿\ù·xùÇ„5¢cøíB`˜íKÜx6âˆdy(ÜRmå4*ß„jRmÄÒ%°´ß”£ñRº ;mˉl†ÄÕʱôåÏ÷íë5©Þý÷;“ IŠÕq"–²æi„7ŒÜW¾ÿ‡˜¿ÁR˜œ`qHÀ«êj˜ZKYò¬« \¾o¶_òû´vq rN˜‰{½4ÕÈ[6˜e¸¥aX{éâZ&bB´”ÀvZ9¿×E{ljÖ2µÞ¢$¢ÜR!ÄY€%«ÎÒ·”²ll>r –Ìr)‚–®,Ç!ðŒŽ¾§ÓÛ]½ZA¯)ÞÕÑnw‚>)ÉCÎ|o½Ä²©á0íšP|5<ÇžWF…÷òüË?ÿùÏA‚†æë­X¬éä,g÷ö²®ß£ Ó4háœækbx̦ÇT›þ<\I·¥.6ÏàÝRM‚Lª¸œÄu„ 9ÇA^‹5lj3L8òéz}Ói)³Z‚ÎSß@YUÑa6mãqùájó‚ÊU5*„©B¦¦°K­ª{/1SŽ_/K´Æ `"z%Ø.,e×B¬ªBR–hL<<µ²Ê•ë¾ Á,ïó¨…óº{-Û"øêÞ«WöUæ9NÜxº4¡a´æÙÆÖÎr8f‡oBåR½¼-i<WRU|O|à‘¾ÄyL[‹£]%DÄeóp ÓÂ/9|û¿Üº Ÿéû-Hó»5êc }MbBcØΦ*A`˜‘»‡‰XÒœ,2„rÄN¯Â‚åQ¼¬‚rAc!Ë´hK”@ŠOyµ©Á™Âp‚–˜ !p"™e] àþ A>kýÁ÷ƒrS)dZ[j­)¤-¤ßÖŒ§@Í›Gܨʑݢ<œu2–b'|âÝ¿~|áΡ£Ë¥}v‘QR£y”ò.¨Iì¢á=ÆÛ¯W½™áÍ d4{?MA“w«¾öuá—¼(ˆkmú“w’pfŒn¦Ë–,|µ0BcË'Â'^¨Y$Ö(C»² fýà0[œÖʥSºµ["~¹©ÁCj²Õ˜œR8£&£é48ùü˜NófÛr5ŽÆvÉtå5ã 5 ¯±Ò!<þB8Ã_ãË-]‚V Y]MÛ›¨Ü8üBøÑBV虿פüÑtå%­ÏL9¥ùœÆ”he¶›Í Xÿü¦®RÈÀ"8|ŽŠ˜@œéÀ!­7Ѷÿö÷µ?ù”ï­]õÞÕTÔRMÕmÌN ž]úp)˜Ví±î+#à0xNš¶Í²1‚÷¡Ót$âèOÍʯ:GH¢-¼f:ÃZ‚«5\:ŸÑÄÕ>ßê€g8”áÀJ áˆF¶VWÈO¤Ÿû€åœúé':Z­ú9@f«‡¢pÖÔBœîœA™AD;±¡¬Ô:Q|:ršß`ôAûFóÏEzá০Pµ¬•rMm/_ELÕEùÖÕ¹Ç\˜úD“ˆ0¾méh)ˆî4øJøNw¥mŸ1µ~ùåµ4@|gKSÑ”9 §‘q0mE!BîçÒáõe<>ôð™¶+é¬îþQ5ÆBf:l ±­zé€~«c…?oÊù‡Rn~RMªn=D·|½ 5—­^ÈŠišˆC §3év&k¸*e‰VâžR!ü¢ÖRà‰äLßüøãš\‰ïu|aäOFËÒK¼B¶BªØº¶úásLÁ­ŽsÀ‰ l‹Ó²˜n…8˜V:LŽÉ¿Ÿç¶^JE!õ ¥Zú$øªÿ’å~‡L™¯7u•PÔŒ™s·XáÚcš±Ú;(¾Ü| h2:¢îp)¶B¶V|ˆsP·¢Mg…Sæ0Læ6¶vh§S]RŒïÁèÓÏ1ï¹þ9M§*$½Dú bR:PxÑúDàœ„ë‰j†¾6 ¶ú 7Ǫÿø”9BœÈ¶!”9ðÓÄuŸt{Dîlõ§ Em‘Oátã‰1 ƒ“Ý“évIh©ÓHp‚@)øŒsäÞ^–¶Õ ÷ÐO‡ƒ,>ȱEÎ"ó‘áë¡C©î)vY)ù=”«Vˆ¿rÔRH?ñÒ­*拎&—/d­²®«B¶!¢n}Y÷DRm»B˜N¯+Gc+«ŠÄ¥Èâ·M?¾{Ô«m8‚º§äí:65dvO×|â*ºø@éÕ‚hµN´'Ä0[á)Øb2ŽÜ.(Áz''« wÏÄéØ)t~S‰)÷…æ-M­Ê]ÍžƒR¥Š]Q[f»¶‘)4GˆIǬâë¶h„&•»‹W§6î¹!Óq9Ŷ/q|sÓUë…_'!n$]¹: Y8Ús» u. SÀalN+¦CÀ$ŀĭ˜øÔ‚s0á,r[NÇA.1fähÖJpNC×ó^ :|ÆAh4þnHjžVýk,²iú¹÷NCù«3…ô£“ŽØ8V])AЃrõߌõ¯Ÿ:é$q Gº¨­µm~Ñ@¥¿÷‡j²>ú{§OMѪÔv¾Pãè³®…XµÊÔ’Â<ø@¹Èh­D²!Ⱥ…â4E/Ì×þÿ‚ûåŒ/ój@ÅMUä] ºjpƒäˆr|‚×<°Á­‹ÊÊ:–|Çb[®÷á>y¨¢œîÌŽ4Y‚meqâ”èÃJ·VâO®¾ ð5öTÔ†•™H] Ò]Á&m„ÈV¥‘5³A4Ï ²¤ðê°,[šðÍ_¡d­Ñèà(mükÅ'%‘qü”˜TÊß»zøÉ°ŠuHÍ=ìnѹˤZR½-^H?¶@)ºÚøˆ@«g‰²FƒwªV:VQm8^—¦(\¤øŠ¢‘Ê·Ò9ç%Ö½ª}Ê=(§=[ [¡!¢ ,¦Än3ˆ­éî4—˜8~åùh¶GåM­Ò]5QoRd¯Ê÷—ôU”ÂðÚÿøGs­m´J@ºñ›T:M¸m)I¹"Ѭp"ý¢ _M‚/Š£C!:ð”ÃÓ¬n~}J”²Òôw'„ $ØëÄI’¢cýõ'6i1*³5^!kõø:ƒà@X³uÃO9k’„Ž©«.Â0­ÀJŸ.ßÇB¥¤cÅM™Žµª=Èh”‹Bâ”…‰Fœ³rñ¥ÔUM– ·Râ;\×9÷˜'¦UBŽa1!ÝmýÚ èº¢Á“ªtkj òUç[díÕ›–€VššTHÝŠZ‹RP(“HηÖ^N`ÍX…$rV:‚-ƒÊ2—ˆËê²/îY¼_ø_ö0 óEN? *T-¥áõæÚÕDWÆahz iÅáÀe!XmÎÇV"G Ü9Ó7c²Õ*QJV’¢PÈV”ÿ¹_ú-ùÓÞ:ÑªŠ ×–ÕŒ•7‹Õmi:ƒÀ=%…Hõ@鬺I¬B4“EæP 1Û.}U:7þÝpl×¾¢%¦Ù¹U§DNW¤g+¿koØ.|:,V8&ÍtÜŸ]G4Ý~úÓ?5 ŒO§~:+úµ W´Ö‰æÃu«nMBšÂ6ÇZ{Ôš §æq VáXÉâ÷ö–oû-æâþëúOž÷êÀ×¶ùÕM°×‘:@ÕM¡IÛÖzsÿØ !H©«­¶iÒ·•{? ˆSúÄ€õ·Fö7Hþqvµ”f˜Ö¦ã7x mj8DK˜zsæB©­¢í|f ŒÉçLv70X"²ãC* aÊÕÀçþ¯Ü·ú¼â»⮎VÝœ[¥mµÁô¦tý4?Îý „²˜q 9VfR‰¯¨Š©(A8ã³¥çôI4?d·õ{ÿ†š.ù4;LQÖiáS«Dj|x! 8ƒ›×#Z¶ÝBÒ\>"¢ðþûÊ~ê'gâÔsã4¾Zë¶3„°8pÌŽ´(Åj:¡Èh‰«á¤@Á¶ô Z‡À‘ë„”“ÛéÕD'öîÓ¿ôŸ¯ÿVxm$µ6¤ËÒ6£Ò%«4q…$º {0»åZ—…Ü l +sùhá7 B‡&\#Ðì”ö¶A³-Åzn¹u£6È Aåн¯ ªŒšž8UµžcxûcnQˆ”²¦¹…¤p:>‚ú®n®YŒ“RuAÈ6°óŠiøÎ­«Ò¹ë¡†† [ £Õö?GOY3ð«æc‰c#d¥YÔØ¢Bé pˆX“HÖmQÅè ZŽç°è0ë²øtT¡€–Ï AfÈ¢+WÔQ¨ìê-¦”*Ê‚TÓt–”èïº)k)¼ŠËEe¢Ö;‘N~îÅëCs[ë ßÌ®^Î!x7Ó¤¢…œ0ßð]}¡z¶bj²tëFÃç·l@+&5¹&j(L8&AN¹˜L¥1…†ó3íýáX/q<²éhCÑzàsT縉m·ŸN:­²fÕ¶Im锂i+dÍ™,§hã‹Úb*W'”  œñe!$9!ÎE?·ºN¤[eD®¨ß*ZŠh¡¡p{7Ž¿üñ{áBß»ú&ÕÇ©²P][G§~}æÃm­ºåh©Õ«•Ϻd¢F¶2äÀ!hÔv\"~ŒüÞOÌþ•HÿµMQˆÍQ¢-qmزú¹ˆçrs¬Ú38ß©rÌâw[ë}"×6œßcÐWѶé$è÷8/1=û ~ƒÐìÌ9ji©*î(_@0­“XKúbî(¤Ø"”Þ¡ñ93äô;´Òû28Žãò¹AQäôùm­5‰ÿ¹ÿ+·F{·*ê/^” çè„ß°¢¶.¢¢5ðî¸j¿&9pšBÀør†j aŽ|Ÿ:¦µ3ñ"’Þ{™ ÔmV¢Õwÿ\Kù„ã§ß~ "W{õ¬Ÿ¶JCtÑI J<™zs3 ås˜Ã¤ÐMN¡ûŠ2²Íb‹©°NÒF8ðh]odÔ„ÜH”÷Ü–‚#ý%ÿýŸ¤¯E¼«ÚêSÑú´æs„ë6¿¶;¥æÍ×ÿR8ÀÖÊÙ?ÇPÍ%” áð•CXc½‰8|QGD¹CKÜùûW"m­¢?ýôäšä#H¬Hµè;yäš!‚lõV·Šr~­Bø•¶&R Ûl=S[Hz‰RÐp Íè¥áÎÄć0>Bâçíÿ£¡ Sdñp¤YåCäã°r!ZG`|gTCü; Ç–æ*òËbwÙJ[«ÒŠP:ýIUÂ)ÚªJéVU¬½*®s8ÿ:¤¢pŽKè:ñE©I¡  ²ÔBø›b…„øcò5|§åÓOªÙ›En¥0—ÍŠ¹t²üh˜«¡\üp ‰¢ ±=c¼½6è£Õ °‰ã·–‚vå=®f²åîðáÀløð_ÿ[QP/'' s—ÃÔÚVË_¼<ùàþ¯zצOÿÜÍÒÉC4ß™7§Ùµ*´†9YÑ.„ãæ‘h„)t†&B¸Z8§ÝéB*Z=§å|î/Î+÷ÅUÞÒ4¬"}ím@Ûd%®%8ÃdùV:h® )>ò¢ …soÈÊÊЉÁmwiJì=µBãˆR@®s~R= ùùÙýãË0>3‚PÌ uíøuÓÚ@ ¶jùôÿé_Âø¤ë_’©ËHÕ³¢¶VBTdSÔze<\¶FÐ0Ð=¶&9²¬Ý6é8(…€™\þ]ßüyNzóÓ5² n[FvŽZ|MÖá©ù¢R¼Rüq-“/וâc2¸•”ê "¸®§ƒò±£Û¦ž\ýœCY]¦ÊÕÅY€Œ8ßêLDµÔ s:ù¦bÈhBrùÈ—ØQŠ6eC€cÊê4€¶.AÛ¤º-qèX3Ÿþ}‚¹d^°ì?SKÜ,ª+]‡Ž]KÝrôà ©ì|îPh(üá²skÞB8øCÓÑDmöh²D…RjR´§Dmø6÷É3ñÝ¿GecÖUÊÁ–_oîíu] >a»uEkÒ†‚»Éw]S[=“¬yk“Z)蟸ôD9B¥Ô „Ó¨ŠÞTïÜbÚÖ¼µöè¼ÊúWøþP‚J0¾Ò†Ò_{œluøÈk•T cg|QdÈ¿@ÊfÏA‹\®”n˜Ò­p¹qÚº4~SY9=ûÙO®Ó‹,Ô!ÈmL>C`†“_Ÿø&"ÒiTèR:[;Î¥ñx{µ¥–T)¢u_hgXG3¢'î.ò"í¥ ¯1ÑóŽ’îÇUhÑfÓG"×Ê‘!˜RZ+¶èœEÑ»äµ*jE†0Q'È:#Hw‘.îãvácÂe50_Êëö¢éN/8ò'5‚¥£UË a…8z»oK<Œ›-S.OR …KÒ€KM¼èÐ\á‘;Æ4­¬1‰tb@w>'$?ô«ˆ U¸-*_”Êæ\À$ΓXnÛr;s½}QjË^þÇ?”=Ê«Xõ¬jÙª®O#Ô­ä xËoü]µ¦pÿHqàuŽæ @b÷Y¡JX»Ð‰¤°3Q´4äBº ÷w½Ky‰ãa­ѰnU!Û fim˜¥q5c"4MZw€%ZPn¡ÖwóŠ.}Eq½~8øLo!È@+Ó*#ØvÍ ×$>NÈdY@ú8»ôÀÒ0}§ôéOÿޱ¯Ç6xÝ* q¤V*ä¨wÓ‰ V=³–ÅBF³öfd²¬>Žø²ü»> ù‘€Zê3Vkeå*ìJAºŽÆôD-±æ©I ׌>ù^’pÖã—¸g‚Ïœa5²s{á?‰q­ýŠF¹º­„)”®‡ú7#PÞÔÖZ‚tãw¦àÀãóYÇ¥ycÂK§P¡ªÙ²¦®+u+DA­Ër™^ø5‹âç甯^ÎLKuÞt|CG3Ž‘c:L¦g '‘²—Øù9pÇ[ŠmYø|ˆ*Œ5¹BVf‹#Q”çã—bë÷uO¾‰ø{Ñ>ת¥[fX])¤«-GoB*Ö’­ƒâk Çt_º›Ýðg’k(m Ñ1 „Ï€¤¤+Dª1áùJp¬‰˜œÒáéÞ¿€ÌHù»ž†úóx쿜K_:15S7„£™|mضBô/ÔV-ˆè¡íð 3áwȶœ6„ÙvP|²VÛôÇ©±ú~'2üù短¾¾‘UK÷&•®7`‘%šÝ¶P.\ÃR\ô.±^(Ž&—•àéãǪJ4œd­¥]“½m¿U–Òºâ õ<—¨äþö·¿5”(91¾þ¬ž„8Ľƒh54œo[‰iÎq4”J„Á4­BEeÙî†F^?|„)@ŽÄÅ·–[ÝûÖya¸<ÅyM'5&"W«Ä)Å‘´ÞÅùáõ‰?«O+“¡[R:2¿P:‚tbmÑzUئÿ±œf˜,*e>2q8‡qlEKI!2D9>‡šU¨µtëÔ0K²J s9_ Ïnwj´—¬Jû'˜­J§Ôµ^'Ú¨HmwÝw>r”\œÆ·º‹4ϧ“2²-°Ù+aùÖ)+ToW©ÿø óÚߨªâ(´D_Ÿ¶n{§­yu¿ñ=r€˜5,«m3 À &>DTÈz¿è “Aǵ«7"Þ)5¹rp‚,pN²+G$_?ý8 UÝŠi[š5ãd<~øáÑr¿wýå—_ˆÜ›\Û¤TTº~\zUŠV…ßv·_}"72d"÷KÐ{ó»ßk}þþþ÷¿ûè£ç˜â,„SVvEgƒ0CaªÞ–ˆ­V!ÝQ!o"®—¶ùhŒï³ %šèrP3‘Ð×ùÆ(}ïôõ ¥žuȺ­ÌV·SWÆV!"…øBkFº)DÓÄç[7NGW7¡~Ê%bvëªÃ‰X)¼ö@|ííEgdÊUqá\ŽÎÄ9誧މjxY&궯a‰RR¢iʇ/TQ¡æ"+ddéÈÖƒ§°”Kæq+úóÑ'ÿ‚Ô,ž“úÑ «œœŠÖ³NlõYc.™ˆ3©añSØ*·ñ”âA׫ƒ ©˜À Ÿ³“I\ºZ¥‚§YÈ¡–‰zC!û¼æ•`®xŽ¢Ý¶Ú³e|Õ3UáÖ¶|n ,1¤D+‘n+§à|l“eÑ8ç…=ž$Õ-ÝxHÆ—Âðýò“ãÓ?A×Ô ìœe!7ŽP%ª^•*ÖpÊeáïIswŽ”¤pJ±†Èe|!FÖŠ§éÍÓýBß}ÅW!N"@ÎyaPï@m¡¬’§ò5ðI½%‚m¡‹þH¹èg鼺6Ö±hH4¾Ž©¹„Úʲ²h#Õ=GdzÉxDz‘D#•šôF³EÓšÄd9oõPB E¤†98rmqøê ñ˜@°CÓö]ÃI-ÊI¤¶‰ÂÔg:V%TìjÁ£ÙêG4œ“$Rç¶YRðÆ"ðût§Ï8˜t¬8éÜÏ "ŠY­ê¿Z§KA4KÖÊt+=‚m:Wä\#Qæ ïïú[…Ò¿¾úïß*j@czP±K/w- %5§­z[">Z#™-AŽÓ`gRâ‹6òVLRÖ{cGî2à ÿç5ã;-SkOWΤ;ãž7£›M?V¥!hz+Q4ñ;É@ý62ZÓÁ­fÛZJ¡øR·!U œê–È'RJjuÈÇ¿Gm¥X UÑÈÍ[!¾t¾hu;Z.óÍÐ»ß §ó«¿¢öhB^Ú±µ2úÚëxC’ Âi.Í#àCt®Éû¼±…cz”¹|>}ûKI¢O~¾ W%µôõ±fùVVo¦`m/ø1¯œ­fD1…ÝT¶µPµ8¾BæG.K:&¹¯ºMW¡çW¿èЕш«~Ÿb+T­uÛäûGú²:"ç–Ô==¿t„FSBJÇ’ˆ*»ípd ‹ëXê62ãßu¼ð@<*ýøg4WŠ£DM*ÑA“KÍÀs¼¡À¥Ô9>k´»+¬p,C­S2/5à Ø^ô³ÀÑ(Ki ‘…fëeûü?‡ð£;Íœ¦BÊAø÷ºÚ€¨ËAF³62¿1M‘‚Ùª[GÚáHde¶q(@Dkf=( i‹‰“(Ê µh |ù§ÿ«Ôù§À~k¤O“vŒÀ”F0Ü éfn"í!èG?Äj‹,Ä UÈÚ8VštÌÅq³ I‘Ë6²ÕùX3‰¶Œ²¯ßý‚]¢oêAϲRãS–Xo|RoªÿmFün~"bR8åêv‰ ‰B<eáqçKÁ©[LHÕ!YÌC ÀŠÒ鵯§#W‡…êáŒW2”ß¶$§†Œ¤D‡Ã ò­8¶@:IµÂ9Ví"µ¥Ü…„Ä™çnÈF2ŒôN$)BàÒ‡#È ­P |8>Z„.\& Þir˜ÕåÈ…w™k(…ȽÏ/úh]Ôê’BkåPà .Aˆ¶™¨êV¸¢ìôt5#Ŷ ‘ÑøV)h¹$ÏM™`Ný× Ûª$³-ÔOå®È ÉH‡UÑê5YèU«þ?\¨©¾‘5°“\“Ú€3ÌÖƒÔa·=?£IßÕäØR“¾×ˆÜŠ»[Ð S•¤(Oí·»îmLnäW­ýýOEµÄ¼iRÃúñÛ¾¬½ˆê íjí\5ŽUcWö¹Û9¶øÍañ¶5¼sœ˜Ð&^”r|ø]Z5NUÔ­U`Lõ°BèbQæëܪù¢Ú–ëšj¾P‚__}î÷§J;´‘kI',¿5°CS¢O-AEÍ®a pte+D GQ`N ”Åç0|Æ!¥Ð ÿÖ¥'ƒ64 ==Ô’ZЪymèÜŒŽÈz/h|[Yt¬)„ðrï2 Á͇Nóât†œMݥǗ‹¯‡hR„^{ î„Æln'åÖž6ꤡ®4&Ð*š?||fXÌnÇ LÄšMÖ–Ï(,×Vºñÿqq?¿x-xýêa]Çaæ´Nôsœ‰Dñc"»áá AÆÜÏÈ…HÁYxRÖ´àÔFÁ+³u¶Òqz§£©œß#•õ̪í9œ»ˆŽÎBJ×jÍÛö€µ•¢+Q#0Ž®t+Ä8 C$v·ÃU,* Ó6}†?Bˆ(Çš(‘AÅ»ÿàq_Røµ*¨é"«r²øJpDŒN-µ"õKßj‹pg®Rœóä±"¬m4ÃöŠbÊ9%" èL„Ö_âôákLâQ¹îO/ä"÷¶ý@Czªït­¶Ô…0»* )ÄêÀ*Ý¡câsàÈEk«Ë)·³¢´ehY´ÚÓ82‚ØJ´Æ±vó©)Èõ€Öù¶¥à¶J1,“…ìRñw>^B˜Ý.ëyMB(|´ð:l ùÈ¥œÂ=·nãS“¢küô÷ö£B=¼#K”B¼ÄI•î¬At=CD!œ|[M&(Å–ï–âÔ¹\Làø´.%ò¢1e¡14Æñ¥Ó^'/q|¯™ŽzPEZ긚B3²ûAȶ,ˆ«³Ó°2œh˜l *8No%lù8V" ¦ÖaÒ©·'‹Ý,÷ÕÛ[ +êì{»µtµÿxÅY½…Ûrhr4yÂשºjp²¶«¸ ß\‹ò‘1;¥à –^•²J¬4DÖNX´>ùmW½>“­ ~)'`ÛóQb—âïæe}ïª7_ÿ_<Þ3:™Z²&ØÈsDË©I²u¹¶Fnº½<üÜøí_ü»üÅ¿Õ+‚`:ukË*”_ukNM ÉÕ P3V SèYjÛ˜îxqò||: "ð•K‡¿~ü­K¡çWšž êV]ÿœw²u¥! z÷æOa„{b`«,ïù8I5W儘c±"8™†µîÉÀrÈ™WŠ-ç…_—¨â¦5—Zôµ×Íp5ø¸cõåGèÎÑPAÈ õO ÒíÁǺëH¤bÅI¿º•¦_´­µ¬ÕuË=‡ø½G¿3—tÎT¯+ýäW]ˆ33š,÷6§¹øœ¶Ò‘­:g¤¬tÜ'Ýc†øÌVÔtB²D´~"ðÉò×§*È,üU_ÿ{\xíüå/Ùà‡ï ËÏN5£(§óákf709«ÓÙÛû‹æ¬²ö^À÷rÛ°ª@¤T—æ%pÄ ˆ0¾”üB~¯îÓÿR{ù£Ü”õ):f⊆pB†×‰µ‹7‘øp3ÒïÕ!Ý%u8=QÖ«¦¹*]n'S«"˜øÈjµ…áã0%U!£YùœóvëÚ”cÛ¥*§ f“(oËÂm7aj=ý âªK[}-RÓŸ¨2œAÜñnç²t«ïª#PhT! _.#’¦•”(ÇAðE‰ÔXjDD[1‰²Å´eÈ˪Šâ*¥ÃI-fй(¿;Ò%‡³Ú–…ä3µù8³²õ¢ILø%ùHok ß¹Z#ät8åº.ê2üRàŒ¯jÐ6ÇtP®ˆ”NR´üÚ“ÿlkRs<Ê]÷m»¬šd:ì.=ƒ½½¤kØÚP­Eñ™ÐnÚ¦HΉÀgJ¸Ü ȇpHqÖ¿†t81õé!eó%Nÿíÿz ^·*:y§ÔåvJ¦C¸•uV­ÊÕU+!¡n+ôq aªäHäì(ž’o·nÎ2ÓCÏ ~åDµ ×F³ÀÉB„ê¸m|‰*úÏÑx!åJ!#ýUh¯î˜ß»ú ¥ }j;Ÿu¬U²À¶|Nm‡4,¼æ jŒïÑ‘”n]5U€R˜{Æ{ðfÿzÛt¼[›Ÿ²•)Í¡4߉ ÌêMcõ#‹#Ú6Ü–`a“EÜñâ¿K©h/!dR¶×pÿqQÒy×Òç¶fWŽòÇw™æÒ9çjùôÜh@[åZ5I¡¡lMÊ |üBVV“9²R¶ÅÌ¡ÓMÙ*„Ÿ3‹ær÷ÿÇG:7å:Q´êŠr(k¯º¾Èlx¡ºâËrk¹Q‘ ubüÄsÐ8ºãÉŠr¬B³¥$[Ô¢þ§Íeõÿyç“íöPšCcN—;D?«…`R[éÚp_ÕŒÝ|ƒKL“>ãPˆŸ…>¦+êôi§ÒËíØ‰äÔmG˜~!ë·/€üë¯}Ü0üNóö­U¿dVª¥®»°5”mrX¸¢9.§Y­Îªm>Žm+gÕEùÔ€|‚~Aôñôì€Æp¤è„¯7¯+¤kG§‹©sÌ*ªîª¡q0\ÝJ[¥Hw5Ó$îĺÐtäV”8#BΑ‹,Zˆ2„ÏòÙ©z1s*ÑÝ‹“Ž Xã?žûj<TFФ€dr¬†ÐÚrN´DùÒ•a%©aFHÖJ9d)r=‰„ðE…Š’…ÐAã Ák›/Úëh:hœ¤RK0òhF+JáÀÍ;Ÿ/d½Z;˦*‡ÉРɲj¢ Ó¡Ù¦àé02¤r hƒÀ9¢×{†\7 ÍÍó‰ãdá!V[¸5¤(¤*óZ7/Ÿ2ƒ;ŠõÓñJD`s—µ%¨á=ã#ç,ýù?Üýë¤3§Ï"ȱí$;+<›ÐD1EõÓö2=@IDAToXéüžá¶|jœÈ8¶ ¹"¦à3>Y„ø}Ü¡À©Šûð…¿3¸/z~÷§Þà|¦s³p4æ…lÛfÔ¿PYBŒq0áhúoFHåL:N~µÒçǾ~ägþÓ´DÞ™ïtÝ*êÖÄ&ZKõ3>?°þùœ@Žs^óÚvmE!&Ù¶¨¿º¥‡X­9ñ¥£Z}°ë‰~Úüè^W:é‰ÁÑ!}øæRW W(Ü6Ž‹\Ípp¬æe½ÜHñ5oU‚H7¡ßUà` dôë$q²hµ!„¹•× ãÈ%øñƒ/ü¦U øG¯Êwš¾Yטÿ(–êJÛÚ`&Zo[Õ ‹ÉoLH!`‰œ¤P«GˆqÚrØÛçxÉøYEc¶úIÆÍï’aêÍŠÜéé$Ž,>ã0ýÌAÈ—…ÐuôUǶ׻3à‘¸¾ŒvQ|º°bzt³UM|«Ûrm]ý8ªÕàϦ 1外ÛÝ%úxº ¸¢UB-LŽTÓ8©Àó›­b8zBÈdÁ½-‘ù™(faB è,¨qÐàÒ1…lqô“ƒÀ(DÚÖ!ÇV¨r©q<Ý(VT +ÅŠVn'ŽUd)$Òª° ‚†C„u‘ҤÀ¶øuÎ!Õàj¹àYÌJ§Pu"Gý2 q€É‚¯Rg–,œ¾­ÙÞ\²"GX´+hEÃO!`ˆÕ,¶µTAóލ(M×bå"´ý%+fÑW­þ¶A'Lÿ£öTlUÅ OÂât  ßéu€ü1/É󀄂pDÓ秃À:)¢%†8½ø½{ñUô/“W‰¯Zû“tj5 7…šÂuÑ-ÒN$}zaZ1{œáHa‘OÎÛëN.Üø5ÜÁm‰2Pu8Ä–áˆÒ´-«ê)C2[ÌRªkb%Âiœn<åЄ0Ó±%MpïgÏüè¥PŸ!èWZêÖµÖ†p @ˆ¬¥uÛì8,d¦['€æ“±÷¶À¯¯Úó¯<½='®Cš|—›ÏaJ0â+gKö‚ϲšÌj_0‡!h«aÛNFÈh!Õêšê‡¾gB_û·.Þò=¥k^i/=UT¢Û,°ƒ­kWM·h|ÛâC:=¸þ}ìS"å…B8?eéE[|ÊN,'óÌ]ZÑ­Úøå—_¬µçdÖD'5s:¾L"r­"°¤š9ðÊ;÷³->‡q1£u°¶ b‹FKŠÏ©J8N \S¾Šî‹óq>áøu± ×g%l9ú¬+Ûµ¤„ҵъ#ŠÓ­.Ëì0óqÎAKv馆9| ¶˜éwPe Qëf€ ȲÆÉ'ΆH y÷I]ÖçÌDîIšÖŸþùÇ|÷{9?‰¹|èJ_Ƭ¥ºê¢óN/ùʲÍywPÍhörïâªØÂ;ÕN,š,?™¼û÷¾ôUѪW(šÜÄ¥÷¢£à´¶>;ùzk­Z]ÔÊuVÑ V?VEݱ‰«‚™øFÐ ‡ã–âwKÀY:*&‚Ö¶#%Åpä6ì»6DÏW>=ÅŠ5 ¹¤+{Q>ÑÚâcFß´À)E2Í>^ð=‚ãç8YV¸f“UQjœz«U!´ø&’ÕäˆK£ÕF Ä™ºVU˜,dÆ‘ Á·M_°CãØfe)Zn§È¢C0ŠƷªÈÏÔÅw—X!ÊÕš-°Æ …à´­mœš”ÈR@`DlÑR „èŠO9|Ñü˜¶uŽŸZ‚V·o"qª.…™ï@žùεNÞ­žæ¾ãlp«Òõ¬nÛµp GC…h,ŸfY!V•9+ ¡#—oí&ìÞ3£¨CÀ¬hkˆBÝi¿ÜŸò«_rÔ˜ÕÒƒÆÌ¼]a«ÉÝl_׉Z²¦°V ̿âç«È K3°söbW®\ ‰V¼/Hààr«2"#Mt?[é.1r‰ %ÖX=§áx<ùk¨þVKÄ3YÇQŪÏ+²-Ð݂ƀúé  á0 ‰ & ñc³[…¾Ð×͵vøÕDú+AÊÉìÓ6¨Õ[Ý’M`-Ñ©"ñ®äúÝÿ²ô¬–CŽV¡©¹ M:<¦t¿ÜXÖJ|ÚÙ@®ºŠüV²z¨ ˆ)4ßÉŸ‹t]&Là²ô) IŸƒÃçˆZD94 ˆ++ i‹9¥‡ ½ö@|QâðÉjÃ,j)­œ5°æ­@ˆž½0ù˜ Íš_çKoÆno„^•ŽŠ­é[B:ç¤Þž¥ù[W‘ã§ßç˜Nàß×*ÚD‰WËíWKú çèMÛ,šq8B8Ážÿ‘Á,„OÖÃ~[GŠ“TÈŠF&‚(ƒïZ´¥|º¹Î"+Òö¿# üuó q&ªD·~øë_ÿªÊ=Ë¿Äp˜{ÿÒkXβj²‰¦Ó±ÃÍÞ&½“òCÒ”k{ס‡¤Ÿ–ßuˆãGŸþâ›d]ÙN­DR|ƱUç^7Po‰¤\t×Ú &Ë*D¡,éÈr˜hN@4YLÎ^,e•tLQ'Ã2åøª°“>‘&ÂÑ›è¹Ã0¦RB³JZ/ýÇ=ʯ-4!rœJ†§9A¡1Í™N-òIiΜÔF0Æ‘.«¢Ut²ò¥¬I¦h Äôá:©g‚Eéªlœ µ-„FA5>ÍV¹+ã|ŽÁ‡X!ðÒ‘óË•®hjL´:i4†p7éñ‡£ÕCáh…×!ŽD¡ Ù62³N„$0r`µ0‰0šJäMÛ|¹‰@0{p@R½Î÷7œÄ_²*´Ï»j5BÊúd»»ê°þõÐm¦s¯=SÈZó›؉¡Q€‡ìZÓŒ†`Ëš™/׊P]¥“ò+ø} Ã|‰ù¾ÁÈuk(£y¹QVTu8ã@´¤ ¾žkÛ«£òšáKé|€R¬Ñ¹$w>Ÿl´f¤ÜY¯­*|Ž5Yžž¢Çõ†3êq¡¥{?¥TŽODº©× …º ¡ÿÅ_¯Ðï:þ4ÖÁ¢l:ãÔ°à:´}×€-[–SàwðÎ"½A´íæÿŽ ù£™Ú'<¿ÿ1 hŽO¿ñÓ´ÕgÇágBQ£E93¼ýTŸoØRò Òi)$¡Isp\t=ûl”¬ïMßý©±ôO›w}_ ìæWÂi+í@´Ä:#Ô¹•ß…CŽ£zÃrŒ&ÅÊmË'Èw?X“*«Ã)1²­˜DD_Å>Ëw2/üúß§4¿é~H_<Çhú©:¿>‘k¬c…›e=ó›¢r|[" SŠ-M~7|´ÊARÃáÌlYmrÃ<{(êwÉÒ7 qNuç4—giÍÛ²ŽˆM¨8&…sè™­•¾;ÎJ:}j–lmP&ßj‹/äÄ09Ö8œŽš3Ží«~ðK’ºÒaÍüóŸÿô4®|æ÷;^k8ÀuÅïÆä¤Ã™ˆžÌA™Ý‰5µ\ ?r ñ9º²Eó•¿{ÃëòÎ| à¶Çé 8)[“ÂOâ‰ä†dý@Dã§`Õ$¤þ[!nNï¬"—«çp£¹ôÖuR¨ê­Ëm¥P¹š,¢ _Ÿ”ãàÛ:)Fœí”Î+Ùxõ„ZëcK !Êr¬LVÝW m„‹û8ÑÈVø©Ý‹á:®ukót™ùøN—|µàÎݨIRRHå ÄL_"KØ•8\‰:5[ÑhëSÅÀµÍ¡SDp¤(‡/ZW¤ˆÃ -Z–hí‰êPb=À3 €Ô„&Xu ޵Á òõP“VFŽÆ¢ÀiËYJÓÕ‰¨Z%V ™•(Ä·®ô”1+!ÊA€0üð:¤#^­‹r|Q¯Ò—ÞõèQ]E‡ÙµÔ !î‡8gÎÛZÙGQ|[zit¥DµÝ…ãt›ÝĽš²\F\ „ƒvн]ˆüŽŽÏa/ÿ—Д=ˆ«Uçúј´º–t(*¤ã!fÌ—B§t++½(Ÿ¡rsøÉZÉb–^ Ä«F?økÉ+]ÑÎMçpàΖOJ.Ž\œzàCø|%8ÈLXU|úïsa 謹þßø¨.Må85© Íè0§º|†©7d:Ñü*ßÀðßíÐ}ëg—^Q䊪K¡_?¢¶J¡Õªr„¥ÀÁ‰o½²-A:ÆÑa#PëaËÁé@èðM¹”Ä奯ùÆŸsîü–¯OúîíiUmù…0 ­Àü»cêâ>–ÎN¼§‡¡ÄàJo­=>u+&_–tk4ëhZµ}á×%Jû—fãØV×áp˜ ×xµÁç°ÀÎo–B¦h­z†`&hÅ´eéXV"È©•Î 8³N’²šÖáŸs|ô[Är•&XEk>G'BêB¬Ì.küwÕgiRgÛJ‚}ô"’Næfµ%X.‚ŠÖª×Lœ«—ÂTNH¡­D¾ñ÷„ïúÿ¸Õ0S±RÚWé^§F»§ø1Õ;»T­œî„F@ãdԈȵ²¶oÁ3µ›°U¢ ÇÚ ×ÉŸ·loîªñ¯žôï‡=ÏÆzЇˆ\‰ÉîxÈzaòñuÇÖë½öŸ ×Bˆo­·Ê5‚Î],¾‡>œ¥8µJ$ˆÏDSÓ Ka"àLkv¥žÿ;U¤œJ™´0¬+OÀaÈ¥µžp®ê¿¾%”…–r)Èp>£Ãדëj«"…ª7‚¬Ä9®¨k ¥gkÍ 9 È‰XKO™,ÃÙUI“8&Ü¡-4…ärvjjáà7”hÌ‘ÈÁoË¡ã4~!¬ÔjUHŬ\m04`ms ˜Ö)/±ÿº.ÃcÖj‚V‚²8l§³-޲§ ׿­ÇU£ŒlEå ©"꬞ÿþ¦Þ¶úæk­Ž¨×¤Z¶#š&»‹J v€‹VmCb—xŸ®Û›Ân |7‘Jq˜, )¾{àå?Ð諸s…´de¶ººº8WRÃ|!¸m7LmÃ9@KÍÊÐÒù¸F°&‚DE[¹Þ€u•H|¸3ì òMá¶‘¸ƒu˜˜V-YZÓIçÀ‰ã±­YMçÌ¿øn‘Ú·¬ÞTèw\U¡¬¨B¶p"»f¢ÕaâZâ kØ€%Ú±bŠúÖßG¡R¾²z{ó°þ¶5‘ê*à]\õŽn+¤“‘ÞqáóâˆJßš¬¨5¼ožš×%Æ¡ÆJ—åЬ¶8p‰NÀ–ßÈ/üvÀç<£jÑçdŽTiXµ¡ãä#³šo8äŠ?ÎG·@šr]t[~ë¥w¦¶ÅLÜÖˆY¾«o½3¥°R|’{áøqH9âU\·ú©3”©µ§‡È¢8§­·g»mä@LY¶×/¾­ DHÎäB4“ß–f&ôæž*¶!þ`ï[^Ëý¢ãeâ‡du½)X)o¾ž] ŽºEUÔy @œŒÒ³‘­¬§D·fŸóT!^访;§8{òÍ'«%EéÐdJ—Ò%bûäÃmCùû/j=(×Ék£­ßüùÏÖÛÈuøá)Ѷ–4¬¥s.×+¨Ù…jÞšáGpDJô¬îꔂ£~Â/ ý®ã·þ¢¸_J`2)]URnÕAi÷¤-¾ž;äj Á;êZ¥VÈ ·âãt䀪(G¨r|„zº[¬B(×Á*Ú咈Ы"ÚƒP"Yþ㽤ž1¨|È@ùÀZâèŒ" ÄÄá[)X¯ìÇó®­h ßJj!Nš:s|uR !d÷–ת‘Ü Y"¦¢”X!¾¬ Õ?e4âD*A«¢ÇdbƒV“*ÞC|âºM\")4ŽÄüø½) Á!LÅwžº-d•Ë4@ MV3hpŽ(² &ŸšD4&%Ž5ÃysÏÿâÜÛàè§ô•†ØŠÊmäNÒ9s ¢[#Órê½Èˆû(F¬N¬kØÕ)d w¶Ú㵄)ÔQÛŽÆiŽ2©zßø{ Äж­V!¼cüø•fõ>KWW¡Zâ4ÔÖ^8µ´®\‡­P‡Ó,ðB …œÓ*é@*Ý*±ŠrvþJØÊ:ÌÎY9²àhtl19 ®·|:•ÇKAJKmûäO¡N¸O·ék€c­~*Çlë¸Dcæ*ÓR{ßþÑßmÿ=»ª[éQ‹Ï”у³-ª“úá Õ°íìx<¸Ê’Îl rꟇL¡¹ºp¤lñ*CÃÐóÁóµÿå?Õe¥5é( |ŽmHà:öRÕR'#Äl[¥³BÈpƒ+ÑqY Z…¬˜Æ”ŽGÈBèfN(ÝA½ö@Ü·^k^'J¯?i„ ¨®ÆgZb e;'$³5ZW–´EN'As,Ä•±ÚãúÓ¿*/ñÓ«6|{ «¬.¿5MÛ]J8ƒk#_¨›œC*š,½Á­ÌàhÂa©uÃóq¬ Q&âp(‡KGöH¬Ÿ&>‚Uõ”‘!B…Wýà)G¹ÑÔj^[óúé'¿ywQTÿÓŸþäW¾}~+W‡l>MéwpÊ@£™·×\VdY¢MŠ`Ưü5ïDüÍOýKÙ¡¹ÿ;v²ÀŽ”>ïe¨ÿ¦s˜]kEù8µ#·flBU8`U"© ¨„ƪn-WˆÃ8ŒZòéó9úYoWÙS·OÈt„ˆ× §(\:þ9ÒZiŸDºá|l+9VÍq—áÅW ‡ÀóUM¼‹;t]ÂmS°åCäB–"±=’¤‘ÕbœÓÙerï…¤ ÔŒ†…Ü”qi¦Ð¹;`E¥ôƒÈ­+„t“…â¨5_4BµàëªÎ»›k ‡£.G­nJS‘q*ÁÁam+ÁçÌЦ™Ò­IÁCŽÐ›/±m ̹ºx¼ÿ¡ÑDS¢IqŒ†S?¥Äá7od¯(²KàÙË¿íö4_cë­†ë$°SÏM-ª%u­…Ò œ1!$§©ù8¶hŒÐ ºc"B.·¢q^~ êî?ÿ¿6€†µÍš¢Þ4¹>›¨¡Âã×­¶¥@8æm+ÊQ¨ÛN/…8$ßá× ÔÇË\Ñ®ˆB1qD½?Uës«¾Z¦CPWu¤V3*öÐv,LC¤dެ¢4û3ÖzþJ{}ºõ{gÅǯqFÇvVEiˆhkÀ‘¢ð%²¢pQ¡&]Ûµºh²€‰Ôâ¥'[«d넬t|öÚ?þñ§ê*ªâ&U”Ï8{¥kÛÔlH`—†ŸŽ‘ŽÜPK¤)ŠP‰VBˆ_È’&NG ç3œY?(ÒTE‡5ÃQÈZÑ®—®X+_Ñib†to–C¿é8¤¬hÖ²: [²ÖÚè`#â{øømØJÚñÊÕÏZ­úÍ›#ªïÎç ®û§†­Ý6;»7Ó6>³ð‰”˜‚s–‡ƒf•Ø ÀÑ¡N2ÍH‡à $•/RŠS²¾ê¯ÿý^݃Tç:QHÄÝ®õ¬mæý×uùxiüTÀ(xFùW›×* Èo›ÉLÄQÚŒ|dkLÓùèO<¤Äû*ñßÿþ·_ò <ñúìˇdøÍU'VÇEwu|Péƒ"'e²Vۚɷ…[)3¡É"ØfeåÃ1KÌsT×Cø#ízE™* Ž@Á…¶ª„h»r1ùpWЦó†`>Þ8JËÚÖ*µ'<ƒH‹FS÷8[¿žø²øhC½ ÉeÈ|d¦P~ Ú‘¾ ,‘“?¾CAë6í\¦†ßYpT± Q“bËÊ­Š•š~¢çÔ¼­”¶&_ >¦—ó†#¤RVÞË^KUèÖ’ÜD.îãV¾‹Æ„pRˆf•Îrˆä½"'ÄÊ ‡æ˵EαÂ!Í\J¿ž³éü·_µú äãô\VšJ¨¾æ;UÛFà°Mí%Ôåëܬ=ñ‘ùh ßdÅ„ßÅ19¬èþi:QF¤Þ€q€]åüúR“¯:t|ó±Û^-`m(Z«Öš1fH‰š¯Ï&‚ë¿hL¡h $EÈŒs¤ðGÇ¢Á«"KºUh%J´Ê:œï4QF9GKGýíϪءrtꄎ;ä‡~xòÌ}±¤J#wÚÓ }Í4”¨­ÒÕE¨ÏhVHLkŽÿx…÷Ñ¿¸º¾¾õgQ…IdŠ2N ymÕbZêÐøµQ]>^—°,£KO B'œô±MMι: 5~„.‡7õþ­‹Ïyz£Ü àt¥™ÌQØê¡U?Ú+¤¥®©-BÌB8…Æ·‚7W>͆%Å–[‰N¬ÛbÛ{yÖd‡ã»χҟ_}Òm=Póª«æSN×NŸBªs¬¤Nê3‚µf„Ê ‰iµõü1 §óï"ï bN&_]Mâ0H‰áOþ׺êÙ‚þ‘ ñN›2RWÃUÔX¯š:âXE9r¥pôV¨t[`~kàæ2£¹ÖV].ã[mSv\|‰@Ò™m‡éTéS°¢Y¥‹2é8²øB¯úÀg÷ Q®EÕºjž{ž¯¯5¥ÿ$ùú)àüûFoÓNÞêlá¬M×¶)0mÇDÈPÈ“Áêåð»¿ÙpŸ3éøë™ ¬Ôi:múªtE8 ($)qiüp[&Ú,Öæ”ÛV $2\ÅNÑ¢i‹'ܶ5ZWA4‚m|u½ÆÁ¯¨õ¼-a°òó[IpH …¤®‰}¤ …6[œSüÍ$r­jW¢”hV!jŽ­f)m‡{¹¢;D‰œ8«ÂXÕ-7A¸û2ýüDRp±EÍ+Äß\1SÆŒ „à‡t›Ñ\l¡…€5O|j9‘ùužŽ-YYJ´*Z(~Ûwà˜uH„áÛ†XëÙZ”C6å{è΄ÛꟓˆÏI„ÓíÄѦ¨ídù]ïg®æj=ï8RßiÑ'«TQ¢U[6¯ÇÙÖ;=8¿þë ÎJO§tQâl´¶VÌš‰ 2«÷Ž+Ýg¾D^¸úhHM9Ís”ÖÉ5ë¶öš§&«ŽoRV"ñéô2¹ˆçåÀ"”Ri+ZÕCÐ8t8{… 9ÒcrҤବ8,ÐÊp>ã@8t8Ä­Þ&=d ¢V£QÀñ Û{ÒIû¬y(9aj]k2Ê1ŽBªwŒîI Ô¤U?¢8õS3 %ä[ÿßúÖµ)Ñßo(­¤¤UìæÔ¤à•Ðd/º:„çˆJMÛd2[fkU¥;ÊV(}Yž±¢Õ2ãO3e)@küFs‰kæã—ˆ›ý{Gä¬*ªé*2>Ъ1«Ã±г†mKßí‡ lí¤Cø@k)fa|˜?ÐV[ç©„êm‰ØÂe1Ûþ—ˆß ªU3n úFã¨È1QÕ$¢ã|D´Í¬JPè Hßj+*¤h´ÔàñiÊMÙ ”•Ó{$ÿÓ+Yÿš¬6Lš¾n×̽¢~„0jdÛÆ‰@“Q°¥iM_¢ô¢ÍCœ'ŽI„Ã8}ÜôÄÀ$‚¼®8h^Vr}¤s¤½ƒPk Ñ8t€¶¥?³’rÏèDE¥õFŸ¿ÞjUü$ùüÃßU~ñ9†éÇ0I¹ß BO¡Î–ßcæ…ü®õß?Ð6&MVŠód Y!V³¤o­¢•á 4l—ìŽLÁ àT¨Z¹@„® ­Ã±*“O!æ>š'XŸ•&‚9<Ù Q($QouRH]LþšÔBý §vn¯Ú\;84•¬ºß$‘áœÚÊïhJl‰LUå«Yr]×_šrï4~ü.•Dã—k6¹ª¤p<>¼2Ÿ-}„ú'ˆÙëJ^ÔÊÊV’o›?N…(Ä´b¦©„-ÅgB|Q ­ÜBp„À%ö5»õH\!d9yå8»IÄ””Û6Û¢ÅÄY•ün)~Êh|–2\ékjŸüQ`üW­þÑíAMÅ&­ÏšÑ•­+[VÆÑRO.ƒØâcÖ¿¬Úk¨RðïT)¢BRª^Ej^í)C&…Ão+×ͯ_~&ºÚßÿ(¤s+ÐZ“õ¬NS×êA>í¾Ýx‡”,FÙÉbB¢qöÒ†KÄdµ‘NÎ q€m­¤¤8"æHé¨;µÈ8?A4øëiVî ¤'ÿô_-_ÿ“RHÅÊYÛ*n:¸êÀpÝæÀ‰øë/oŠ^'ÿ·Í»…kêmE#68µ@Ž¢Óv©ÎA†TZ]4>Ä6)à¶9BES¦P"¬­ß•²v±²êâd˜™-)Ûn!7Œ¿$¶]ÿÏ8ôû–øýè¥\m«ÅÑ@å8¶}¸Aæ³Óý[ÿÍÕá ÈB"pœ„E°ÂïÍ %äŒ@Ê좜ûÁžÂ—òÿ~éÿÁô®üí¾þªZ5 ÕM­ˆPcb2[`]UEK@«­\Øa•>‡f3¶¢‰VQH.‚ÀwÀªTÂÚ·ÈÛ~ÚÙ/…TT·ŠWçÍôŸ)Ä©·,æÐ09átÐîý‹v5µè ¹w8Ìë…N¥“ÊWW¢*8‚s«°Ã$Øa¦,ëùGæ»UQ]o‚|Ó€æšNÇmæ1å'ù¯<Ó(¼ê‚ž.¯ÃWÔ/+œƒ®”•]{¡Þ¡qôߥÔü°m…èp |üÄ!ühRÂ×õE†[á‘Ç-ÄQ“³E# •+ s€Y`~µÊª>µ½V] öxèÈl_’¿¥…Gh½3k]%…ùmrR¸à3ƒ­ƒ6’a60>¦(G¡ ËšDT–-§ÃŠY"Pµš¤“I‘‡OX¹+~m¢j5`R Ã[+—Ä6;¤Ël•“Î!ÅWK][Y3\œÕrsxLˆŽ)‹¡¥_"Äv½5K"|µðm­ñ1+$K.ðÞF: EÖŸT×6Áé I± ±-·V׺ï-´ôÂo³êÖ{¼F ¢š¿z9ƒ×ØN€S·õjïŠHÑv„‘•c|Y¶N/Ù²ˆT 9‚_ŸV8;.ÁZ¥óÿñ×ÿ…**Á”S×öª|¦³U¢½ŒÏbÞÉ|VÃߊœï®@8·çMÇ¢´*ðnñï)ó9˜V²¢@Ð ³ÖÚâð7,¾ôrã ã”î&,*ô9óAÜ€³>IÑ·î@´¡.«.>ßíÚ—å&ré}UöõfˆûÛYolé¬Ö†­"W©s& ÓŠÃQW­Î¤NÒ‘rÑÏ’¡Â)”È¢e{9ô™¨J?$c¾ëGŸM* !h¬-¾_ëÿîoö«û-«Ïy*2… ËQK¢*m­a¥õ€ÀI'^ŠCŽâuémæÞ)º"Àξ(³m­š£¥_J!dRJ¿ö@ú/ÿ¯z#ó]¯þH{uµþ×›‘ޚܤŒÔ:ç4ì]ÊM‚ã â#ˆéTm™5+~Û¹/ùgÐ^D>ÑÖpUº(¬=!iF”™ßå°ZSͳä7‹7q²üÝx:í*š« ™U%Nˆ£¨ ÇV•^àÉV7‚¯z[ñäI¹Y\2=ä×'¡CôàK}ßîû^Ãw[=äÿcÕ€²/þC§aÕ‰–X¾P¦UÚp¾VáZ)®„_"Ø!”(ÄÊ‚° •·uuàh]}7‡šÕM¸”BÎVWzÛ«ÎYp€ âŠJ$Kó¨\V?:AcV‘pþ™G/ˆ /'QùrЄ/$‘‰Ö´¿(2 ‡ÄA.šù u1ª›BL~çˆÉwÛ9P†_W½\£-1G «žëVQŽ‚3[` „Ç¡Àø¢ùÄ9²Zs€8l=Ýë0ѦÌ/½¶ 5HÇR•rEš‰ ‘ Á ´%…©í8¤·un!8!ÓC¬‹£ˆà‘ÕZ œA:. ¶“‚k)2Ÿ ±RBýùækŸÞ·üñOgUEEu•)ª«pZ3â4²»"„Ùù×­ôN ²kAP4„Ÿr)•Ãl‹IÄ gÔ\çÌw¿øÛR„gÌQuåÔÕ$« šåh ×&‹ w&¶U׎5ÂNCÓö..QQ¾ÐŽw:DXj-´”…8BÈt¬ºÅç§±EáPržB»íE™\Q+MŸþŸ¼ IõáÒtÊ9Cˆ*V-1U¢1Vi šÞ¼/ºè¿Û†7Qï¾>ý›ˆÈ¥úX L xΙóºQmDŽԚ>… [³tÛeå**kü˜á »ÁY4äÊ>͸.^ªœ¶e˜d¡·!¾¿®ôó«£óPB¡ÄµÄ ºÒ§ ×V´žuÂiü^&Ñdi• Ýȶyïg‚l‹œ §è˜¶L”) ·%%Q‡¾þç¿Ä|s ÕµÒ¬·Õ]' Ãð«¯sAêXî}[ÿÃ'Ò8ùJìÜ\‚ŽEÇìŒ,Ÿå ˆ†?ÿC{=ûW¡½ª¢„©û.֘ʱs1®û„M®†u‡ìÄa %‰¢¹v«,þ%y.1£f…àãä ñ­W ¿~¬=d S«Ý½4¥×íý¸ pSŠÜÈϬ¾H2ŠDÈ2mÔaúkCózCƒ#Ä÷³…¾éùÛœfzBz¶45¤ãmd½uh¶Úr¼q %*«n…Z—Rˆ!©Öp 9¶‘I)W(µJÑÞ„¼tÂa²jAn°–ÈvŒU!8¼r)U,”H‰Bõt> aÖ9Y¡³)Tù•,d…`*¹£´eBÖšà#`ºQ¬,Ø„˜ô¶æ÷0Úž²Çš¬⼜]½iÀ&‘‚Ò ñ'Z„šñѬw§,¸>µ*ÄQ…qÌl³¶;"ÌȽràh8j © P{ÈÆä¼é=îËd·Šjɺ†Ö§&Ó8«B¯–m‰9®È˜ôÒÙÊé(8tø9J CšŽÄ–㣅 ø6ëµ_ÿkã_ÿúýzÓ ?SWEf Ïòט QŠ•NL)µÈÀ”ÍXVš¶,‹>dW ^yG‡VÛþewB%ž_ÖßV&Õt“u¹ù8zÐv¦O4m×tYú·â7”¶Ñ¤À›N–g›‚&‘Ú©ñæ'^T®~ú÷P‚^û”mÑt’­4D”iº  úñ*{þOÌýÛ2Êz0,YÆ!®“¨=«‰vÚh®µwÁßý·ÔzãìC³qô?MÛ!Õ¶ŽHEÌ‹rn~Eùhµ7þRp®ã9ú@ëFHD â áGæc^Ás'8átJásZ9Rðž>ß(ôªOxÔXÿM0uWZ‰‚˜6Ö[C´$ÞDÒmù9z–(ÊFã”%“ßv‰«+]"…ÄÇL¿nEùnÔéØ>i¾(¡¶ö´ÁטŠî7?‹ºÙÜ«8ÝuÊ!ß>š7u ¡ m[ÿš$kRkÛŠâ°9Gúí“t¾PE[»˜t|‹ü•?&©Ê·¬^¹=UįO­²NCQÎi÷ºú9›"B=;:Û^ãeuSÅ¢PÊV)fçÓ˜ÎQK´~òª ÌÊy•UHT-|Ê¢ühÏ?å:Ïn›õPcj1Ê ´ÖImKqGùW¿~åÑçc€Ç 0ýO¬žû ƒF^¹*NÓ¶ãUŽ9X‘ ˜r7KÛÔÌÕh9BYUl…”ÞVb "Þ‹‹²¢¶À²ðùÈk ZåêÎÒA(—ã†aÛÆ¹¸G§V)4 ¼ºø|„ÇOéÖtµ‘€ò­@ÖQÖ¨èj—‹P1kÅÔKÁýÊ÷æ„Sm·»ZÝ©`Ž,„:h8,"¤ør«%Äa²j£t+çI­ŸñéÔ$È?i×'qRqŠòuÞ)[»úð×~úW«?þéXêD9x©áNh[ŸBÝTœÆìF²ýxÃH4)<"*?ŸcL! ó´•µ¨¢w¤Kðª_Ô6u«ÿ&Ò*êªf¬5Ïñâ­Õu[“²p²ü!ø8¶šçxJÇ*jÅgIÙÁJd²¢%… ×L§aÝ?“J ëSî¤ûj€#šhÝBÐÈŸžûï~Ñ­¯ÿמr]P¸W®ŠÑ¼íùëï|ú§ð[FÁ—ý¾0ón!1KÇj"ˆÜ‰ØŽÙÑÕ\E+ˆÉ:·N:p´Î é"òS"˜ñÃ%º¤PŽ`Áñm]+AH²p#)øg0/ü‚°ŸÐÈ&Þ¨ËôÜQtžhÀÞ¡tU«˜ðšçspt”ËÊ…³|`EãWÝj{eœ™Î•ô¸€k™Ùº[^õŸp!èà¦RW-[ÕO+o~Û^5t5Z'€Æ1ãÌGáh8YÑ…8L¨‘ÝB”ᵡ$Zã§6°Ò˜/ù/ÿôt'¯UˆI Î4Sz®kH[mH9§öö1†”‰løÖ4/Ê……B¬**-ª.‚oè× &„qX§DŸ/ÑéQò!üÈÖÔ„B§×"§ çNø]¢,†œCÁ6µ8¥ÃbÈ„¥—4?\u~4§Y¬Öz¸#| “eë”Hµµj€¬sóA“SK|ÎãA†Ñðø¬LŠåTÑ´(»ˆr†TÀu†#+LÊ' Ƕ”! ™çñÑ4ð®n••øÊ­=„{ó¶5‰g+‡;7™ˆ\ð„BÞ¸'dL[":YÔÖå†w8.•mÓ9Sôâ¯úŠv •°ŠÖ ý¬(¿DÑ)t2ñ{¦SÀW7}§Z ¥áE!ÔÚr€ŒdÊf_ñ³$kç`[ÈjF…¼»åENü{­GIYú¬œëÙÊD᫹tØ!C´¤I8?2^VŽ•u2gÔÛc/„¬4“î8ÈpQjÝÿGâ‰ÀEóNE^¹økȳfµQQýÔ§Nê<Ž(Ķ5g™«Ã‰O$RŒãNóQŽÓ¶×…hçÀ!‚ ZW˜ ô{u¬n¡ÿ£íÞ’lI’b D ¹=0ÿ)!PÝ`çsÿ3µ£³€{EÛƒ—¹™šššG¬X+/;«ó¤ŒoUÆv—R­ H+BH>Gkæ˜îÏ9KýšíÓ¿FFIZXGëœ_õaÁÿá(÷¹¿?G- À‰óÆÎ\Ž®Ó ­¬ÁÅ+d|°VÂDvg¢’jªÃž£u<`,~‘ÅEØ®Z~׈m2¬¬j­RVT—øë“KSÉç«® õJ3Ú" å@8ÎÍÊ—¥m7LD&Õ±hŸçS¤$’|åœF¶J1àÂz©zñ·¡¼ˆF‰i[C‰X½(|ÔëöèÕ’’ †£Äʧ<ç©YV¼&þuDÎg4زц·UÒɸ:¶oÝþ7‘º³¾iëêëÕGy SrÕ‹NLJÄ÷¨áKaptÞSšK d´üåY„„Q¢\G÷*ßù£2/°-ƒìŠT&ůõ9Äûɬ`òÀT½õ½6_7bKÏd<¯‘v¶ ˜ÂeéY„Ÿx«ñ“êÐ<÷”¸E¥~̹ Ä ë|`€•g„ÕBvòD2Hq[ VüºG2¶]tŸ’#)UaëwÃó’·ÆÃ©‹µ¸ U`Èmù´@B›à˜ù)±2àH¬ü‚|Æ×Ky¾,¿öþ›A`ãkB« ;ð¼›fBQe娬Mð‡±íÚÔi#qX á#·6'Ç­¿Cìt:Q0$øELE[Ö‘£ ä”óYŽ•ÑPЊ-Iüiã`°²!󷜩¾Ûè=´­Oò›<œº›®^)w‘ÜÊÆ—é‹3~[üÆ Ïç´ÅãšñYàZœñ® &`×B# â"ªdÀKY¸8 …±‰‹À–j:Û¬Ó ƒm Åm‹t±Âkæ­GR: öw´¨o½¨2T‚ƒ=W)àîº`ái¶í@8‚ØhP‹Ê#ìXŒ ¶`¾kªF¹ŒZÆÑHìÿûé0òÿÓêaê|¯JS>IkÍç°†¥Šß6€¬£ð%Ðî@Ž ƒ„Á2m^¶ ù!ÍXÄu)†Ì·Ä>ÿ>"µ~ôLL‡©‘.#ØÖ׺.«/w‹ëýù_ªúÐïÓRË۶Š0¾bü9\JÇš ªêîK^µ|Ÿ0l­Ýñ\‚¯7 †G/«BV°v‚œ‚º¨…,âd"·Š-Ù«ÝR¢Öêá0IµûdýÓŸþTÇôAD¼gTzºëšÆV >ýÅEšñ2#Š FªÓÈ·ÚfÕ*é4懴‚Á¬©_à¦Jüó[ïN@‹^e5¢G$=ú&O*UFãw­)TÕü§P Îq&0†.3¼Ç<’Éæd—û‹ C%Õ.;𨤠†·]*GI üë"k–`Ýq‡lRÁxT™Ñ–ìEÂÄÃø?¶ÀÚ *LRW$|·à¡¾w[¤l«®Öª]lüjƒ‰¸U\ ƒˆB¿w‘Z©Wì·ß~óÀí(4âhÄž]A0§u§ö |_íð}Y#e¨ä]²¯CCn©:ò!ÕªêˆêÛê"r¬ZÔ˜_¹Hï|°W~P›æ­~ÿùºëBöó£³l’ùrÀ€M§¶ؤ"Re¼r…ÍÛùì¡ÃTYãWÛ}bÅI@J`<—eoÅ)a¶´µn:-2κ—…a‘$Lä•ÿ÷œß:CH¼.Ýêµö w)}ô7Ťþ—Ž*¿äã°RÕtØHµ>G–É:FœaøÏc/#›‰#¬AÉšZO(gQ…y¶[¼BHÁ,UÑ>ke/ëùâ­á•?w¿;ÖǸúÖ½jÀT™«”µ¡È–rbÝÉe) ¬¶ÑbÈ—­ýÅ•8ÌÀÍŽª.cˆ¹ˆÕ6x|#CÇ·þ>²oÿ'2~½2-8´yéÞUæïˆJÁ$ÞÉ`è4¤º—©Ë FÛŒk÷ttÁÆtÑuÑZ‰¶iFÈaâxÄ;["ÛÈ›å•Oÿ:úu)+Ó·{¦W‡­vfçXS›ž¶Öô«…L¶ ‹mkYÛž¨¹ ‰ø ‘K5—YxüŒó´„‰€u&0‚"­[½`\…É‹ Œ¥3[NMŸNbD¨M¹B¾ˆÓ¨µŽø`â1N¾•%Cj–Uø kqJaÈ `ÅuùþüÇ ìæLmHMÏ—®+ºß7Hqì`al9‰«„ßµ!N6¶ÞÔ“È_PS…ñÄ ‡å¡Ó àÙ«À‚`UáéˆÑ"a¤ 2¾xVG¾B–ò¶Áà—½Õg ¼¸m¾5†hG^Üú{ƒ!,å|TÓIyø²RA¤{4¤-GaGÊ©/#-@®YDB"‰Gk)€Z~Yûó_µÂéû+È ˆÜÍþ7?Æ1µÏa~¤Î!ÉDV$,ßÚù$تQ©"m‡’0[‡‰8‡`A§&È·²ÛÿëAª$_-*à]YåR,þºÇöÖÿŽ$I>ù¥ñ‹sDjº”81ÃIs€é´íÌeqV%`­0ߘ}Ù3Úð`jY0[M;¥pÊZ»=ô?ÿHŠù‡ýø“‘ÚQÒ›Y’DHíæqí”SkA[k[àðE¤¢*Û8k­\–G%eC§dËép¬ýžLJà‰ÔEÜùÄÆÖå4ø~ „Ä/ ,ˆxša¨•òNüʇ*EÑ%Ó›½'[§7yÿ¥ãY¯Ê»i’`¨"•c4R­r¬‚È›rÛÖ`¶Œo}–ð•0Tðlp)´‚•Ã30[k˜‚­À¬T0q ØŠóÏo Ò%àØ"ŸÁÄÐà:ºÖ}Xq˜C~èø]Ý'IS~÷UqüœÎªÏ4¦é-Ù}bÌf„욅澈B(.[+r% (%^ª ã@–%Æ·o_<þ„Kj»ñ¬ÄjЦH[©¦³í”di“R"Ò…ƒ±-…<~[ÆnUfíH½ØÆà¨7xx‘¶ÝH¾9òÊ?ƒ¦Ç[F¯VJRkM@kóæ»1€Im›6$il¢îÙü 0å"¶?üØlùméáh—0%19 ®ZÖå+N“<¾³VòÉêÄ”ãÔ‘¤T¹3»¸Z$ØÊšÅZk Õ^±gRµ|)7CÇøœ®ˆ•i—³`•ç× [·ß,[G+åÀR˜7‹-k+Þ^UqŽZι‚ýaxÎqÜÏ·RøCŠÄ&¨¼^Và~ï„{½D›<°,yZ ̇‘MR~-â‘JC’ôª Œø×# )è¤û4Ò1*xŠˆÞ«DÖ-h5‰Tãt“è«{â©pñ‚éç7£5ýVà²GV#äSÕa¦Ïž"!À"þuWhÝY¡Âl¢æµíxkà;"©$‰ÀˆÔ«{ÛÆ'ÂR üêÈô¼åø À¨´Ð´[«×ÔRâ”4Ëü¶¦à0Œ,µ7/NT « k.ǥʃEŠ&ʼnD‰”5f©âz)DÞ燀A S•†z÷¢ã7c½¬L ¼*¿¢óÊ÷QýÏF¼_òñÑß+¢óé3®Y ¸Ò†êñ·5¬Tà0æZG³d* Ú‚ñ­!¥:v$¥`œ'ßyÚòÛFR|ÛCÿ>vÙ˜ò.ô‚Ïp>iñ<Éû8ègƒµÏ/;ß/»kJÓÎ:URm­ƒÍ2¼ZFy« †u\"²Î\|-LW«ñY)Uœ>Rôd`°aPFð¯ñÛÿ>ý난 ³e‰©»í4ž#þÜÂv§…´Å,ÇÉÔCç bX<¬¾ °EÈžH€"‘À»Ý<⨊W%˱ FÞŒ/H@A—¬ŽïÞ„hŸ¦‘ýŽ£»Ž„4m|AØ¡Y+Ï1Ç ÃAC0ÇžÓÚ9,bû$´U^‰Óp€EzAŒ‰ð!‘0«©"|Ûámú>]Én F¶ËÖ.žn)$:–r‰}m6؇Ž,º“á »¦&CÐVPwY2Û뛼3Òýª GœÓ8i[Üm+ÜVbÕB%IüÓáÏjäÓÛ‹òÛo¿%Àø]&ã3Jl9Æw ŒpÃ'Î(±Tk›þ&5T:0œñ¾ß) Rm \”ŽÅñ×"¤T‘N-ü[ÿö×»Fª¶6….‡HÐìÄP’Tqzˆ‡‘Zܾ-¶øm‹ØÄ |oÍJ¤¢…¬¯5'0, ðMž×ŽŸ’‚Vz ;7]^yOñ- -bžT-‡#ëÎ!æŒzßýÁtUȯ0åÖÍ"[¸Óãt8Á¶Š×l`†?äVN&¿-ä!ïQ^ƒ3pì`0x“Ò0|=|çÒ™†O\¾-0ÇÆé‘Äïži´,ZåJt‘š#ˆÍ YÜŠ gøU 6†ØÂwL‚"oFµÁHÆ_ÜšCl‘Öª*IŸÉv\üšÚòkä´c-@ÚŒ`Š^fU5—ycPë@‡i×ÚhV)ÈÅ9ñt&¥j­P_> ¯ †ExIÁCÊ2þ[ÿ~K#æŽêWÿÛþkóþ`Ì̲|+ßî:o“Š˜¢1Œm)ëLœ¯–c^Ž-d7ò"‚ó9 F‰ì_ãÛÒûÃ2z1ÝÝ-¦Ð×D)䔲R’/eІJ³uÛž†8ŽP9ÇP±‰ë`+(ÅÜ¢æµe¥9âZÊ&C È×ÑE±ÂàìÆV˜*ŽB)²Áüz±ª²ñÀùÝŸA¡u«¸}î×ZÇ´Ó« qÌB‡$ñVŽÙa¬ B¦æ^R¶r„L!,>6[>LYl!Ÿ«,Á‡âû¸4g©ªøÍ-5 ƒV¤IQ1©U œâ9 ²Ißúœ>ä¹(i³uEvk êèx N³î¾Œ¤ô4‹8k–«÷dÛ¶"‡A‹Íй;`רxœJl«‚±Í ZÁd ~ñ@ü6ahñ§œÏÑkå­†˜Qzøƒªo½ç¥'›‘íâ6…xÌÃ'þZ rº:Rã â0ü»pÛÍëÔ#ñKô½ ÑjaÀ¤j€C0"—¸‹¦ø$)ç[UIUë!À:@$»ë`Ä­õµ> má­ñ« Ö¶¸U—g$~´tú…ÒÏŸuøû’)1:rèlŠZ[Á¤\z—ÒIênË”e mÅ)p2¶ØDºm¢ŠF•¬TMe0K‰­Ô ÿ\„¬9Á"WŽ– Êæ•×ø`M/ù 9­HجÈiü}ùæ(‘ÒQ„ [ʶÊF»’9«­\üÄ=äN²m#à‰j´+ÇZÊ9‡<=D;t¦²J»® ÄŠ`\Áø‚üM™¬Êm›S'AŽ•I©eJ¬¶õÍG^»TR".¨PÓ¶ð §IÚZYxŽlxN‚1£0 øŸ-ÔR+nÇš‘‘†ïÀ×+·¹LGm"£FLd}mƒ‰€=9Å5M#2§óL•^j1p.ð,RE ÑÞÎ_'&…|N~Žª‚i+˜ìxzj;I}¥Âפ¶9¥ÞýåüÕÌDêø£µø‚ROÌ©À K0f&Èl½®:Š¥b«K&R¿›¡¦‘8Ç«uçVùÖ ¥âQ.Âübä[ÈÒ¿¿G­F³$ý^ €Ñ(QE<Œ ¾•ŸÎ4‹D"ΑêŽržƒ!L€ˆ×¦S…ìäUá©ÖÊjÐi·­‹¬ø a˜H$¯|éÓ¿¦ähº¦K/XNwKOI‘fwD̘,_œ6ÛD&X‰xlù8“ÖÊlÙR9ÁJ=×'¾v=c D’tçtz©åïUÀÇðdVUÓ Ÿ’ » µO‘¶ZXÂÄ#’*Nþ³Ý“ŸrN/([VUkœº¦Oò‰?©M‹N¥"8[NצïuáRv[ý›Â¶V²dÁâé ‰»D§¬/Çs¬L/äÍìžëïØrüH½^`½`€ñLXóð0暪Éo’àS¼Y"ç€c•­øh×îéðYÓ˜Fæ+éN³]Ä#B0Zg_Àúâ·u˜Rë"8$†ò6¼­xöÖ§ÌÿüÏÿô-Uœš:w©VÄ8 3ËæéM”% ’6Née9Vx) `|ñß›¬à¡û~Ëi[ܶW.mÎ OOœºtÎá!m#LXíŠð# ¾N;f-øEš¢-$†Öñkau‡¼ø|ð«ÿz±Z[õÒ”$¾Õ6m0⎂#âÚu `š±”lj­"V&ÈÀXlªvÉDd;m%™¬BÁN©»Tä©“Ð÷^üE5ð¾^5",ýT¹1º{“ÀéÖ•5‘Âd7š y1Tb›Ú,dAk¦¤“w“€Ù~ÃÏm£åÃç 2ßú«q¾\g..ZÐÙ…ÖE¤‹"X–ŒÄ´•U¨ªcÌl9Wéy`¶hÇÌAej/ð} ìfJL‘Øvh1×K0©mó­‹£²M¤_ûü;JNó.I ÂÏ¡¶›¡7”ž3u—‚q\^SJ8ÃK¡¡vÊ{]p¤PÖ¡GÏŠ[çs෠É Ä‘A’µq>=0Ý"Ru¬‘-L |­£œ V*ØÄ¤†Á[E€s‡:e·æÜqÑ,rUü|ŒG£®ÅioÚ‰«5¸­•^]›x³úÀi_qŒ"Q´5<ÆÎåVŸ÷0’#¬ ŒU‰-Î>B]À€Ir“ņŒ‰WÉøj§$XÔ†áߊ¯×]#x„RH8¶uçdJRÒIÙŠo° [–ßDµÀÐÈúÉIg<•H)#ÈDr¬"30R­Ú²"¶3ÛLpM»ÍÂ/•$<ÀJ¤´0¸`$RLÜúÊŸ\¼|gñïKǦ¶Õ1aÖ¶ xÊ8eWjšóoì|ðjLÛ²Í;$Ú¨“oR÷dq[ø•¨bRk!›6«‘ÒTÊ-/øÊ/kÖnkÿü—ž+ðÜØÝÒúŠPÞWòÁ(äWNëÆ(ŸÙÎÁ ¤O·îj¾TV°V<âñ‹ÐPß²½DŠ€Wåp4šÔ®”^½+ÈJ%X KXN)Ì8‹¼ò¡ ¡¿"BFÚÈЈú=jj×m)l|[Jž‚E¤‚ ?N>BäR %f#Ç3æ¶ÀµSëZ“JO<8ÃÃp€UñYNê(XÓÁlYYNbøZ ÄÏg‰±ÂÛJìZ¨: ïgÅ[?–Ñηº]íXé2§#uª¾%ÑŠTfKjs9ïË6þ†ÅÜRü'Ó °F­ÕÔœô”zj[#ÁÄwpû¢-ì9)ß«IŠc.¢ÇøÀ7Žmƒ¤Sœ æH5‘Hç`«§W. %;œjußqu˜¶½ÌÕú ëbEþáêWF1›T_T­DЖBòÒ<Œl²Å• ¦„ˆ3ñDvt¶Rª`DòCw_Y¶Ž‚«ÁÓfglü8[+ç‹×”RŠ_ðoþæo²îOâG?yµHIOÂ;Ü×§ä`J8È&ÃQ˜‘/Î `v#R•­ƒª ’oÕWaäÑÆ3¿ÖN£Â‚¨z8ÀP¹ˆvhñw×)¨i‡/Ëà­)¬iYkÁh¥ÀžW§B~ɘ“ºµl"[‹à¡9žZ‹ÄfËb˜¤Î\¼ó¬§]Pœcöó²$NÎÊH°"Ψ¬2‘ØUBZׯ¶K[Š„ÖI oMhq+<ÃSIi[m‰I=Ì<â Ÿ‘xˆtÕ•¦Jœ©DV3_ÜÚ¼¬­â,$«]}­90¥æÊV…Ä6€î| ó9#žÁ¨•zÒªáha(¨$Áø9ÃCFÈ¡Ä3:†ÊÁ[v\?xRS†¡ì´ VÈñ½=ßá“zÅ|C¢¿eáÂMó“YG"uOÃspÈÖJdÙ³Ü!ˆTn(~×®¸©;á 9•srHÆÒ–’í¢` †óÅ#Z_o·ÅŸìÚZme9T°M•ãM³uHÙ‚Á–RRUTV)§Wa½¼~Ãw«ÔN—0Rž=C4bRŽË Xai²™l+€U°v0²8Uùô_àó[~Ý¿y5rK˜‚f¾U£Èùº3©Æ¬J„*+ŒrÆgÉã7,‰q6Z$Á–Ù*)h‹ž0þåþ:4/™ƒ¾Á•Øæ' í0R4㆒m^×B•´K©:Â'æÙ¥Ñ Yªd}éûù·*륵ïðÉcÛ¶jJª7…Ý”¤O¨V°.‡òÔr:È„<3\ãcs2ÕvÅEăRL¶.âŽNIœœ™íúÖháCcÖ=~b è(S`œDv)SÛýC›C¨r)<"iÎÉߌM-Õía «ElN†¾²RŒƒŸqc¾É‚ä•/Úà#©ñ7š^úЧ?1mEÀ‡™…OIç`kf+>~ìÇ*ejf(½ÐN†”‘ïô–[Ȩ®–³H•U¨{‡–~Y[¾;üó[ȉyÖ!Ü‚YSz’Ágd$5m¶ ,; `WöÖ§ŸZÙ^4;½êé5’å×ÑÊ/2ò9ReE8­ª4uΑµH¼1]/ȱ=-oUããWÈâ—å[° ?«ˆÚ mÝ÷{˜F?¬ì3x+¾ïuqVÎ'ƒ¸Š¾>ÌÖ·@¤^Q)?•÷ÆV(uîi9!{rm]*§ßËÆgqYD*‘Ö2vÅJꡜ~*!•ŠA+3xj¡„/2NHµQÕ®«èC§,0 ‹Ê[ &Œ¼ÁE§!Ÿ‰7”5?ª¶Ïª"T9 q·W ð‚„q4b¥Û²qÀl­ a%io+ÅÁÏa"µãßê/ž›Í¶âjšåÏb^YN'æå`c•Hq"©{x7!¤¨Ç=NT’µZ%Ê6Ì0¨^4­Ù™äû͵KÓ¼‚ÉNU"ºË’D?=á Špº‡ÉœZ% X U/±FÆS/©:ÚÂØáwqƼóÌ×¾x8˜['©»B˜V­U 6Wƒ¼ò-1´þYmzíòCF­›L&˜-€µlƒ—âCªåpØ­; ¹Q%7y" XI޵ªH:‡°l€Cýý(Þê¬èua|+ýL–¯V ¿ gq—>yIçvûZ”˜eÝ9/>ü» ÚèÞE¯Qk"Iâ ÆáÁêv²·md‘À¼BŽ‹ÄÖiX•;<0=1ø ÀÏø0üœR±!´}ñç¥ýªdƒcÖ…­ s¥ø4Pk|«°•xξ‰ÀW.Ë’š¡eDÐÖŠ!+G9þQqKs<¸DHò«ÿŸÅÉú—¬Âê¥!ÀÚRœ Èyb$ ýR]`A©¦¶8NçÉV Vm:‘YȶJjÆøLU7LÚ¸à?ÿó?ÿPò Û?ýéOiÖ‚—‰U/-XM“Á¿Š¾ÂE¬ &£*§,¢—ßâ+œfÁ¬ˆFªàd²R«œ¹FPÞu™ù¼:ùWO´icR"¥æO@Yà•/¹¸ägá#ÇÓmL[UÊwž#\¯8·UãVññ ƒ¬Uù×k»WסÕy9}—NX—'ŠtðYR8ð`mUuSr(à´rÀ†œXaw0­ô$L|·¾,|%VúÁ8ͬ‹ Ü ¶u/̪Ê*kí#Ô¿”f F,k•²þ°éQ•x%̘ å+Òâä$€Ã8·èô²ý¡s]ÄÁ0„9ú®Âðj€¦V¾Â̶.xœyU¥ª‘²’-.ϯ•!¬ï?üÃ?œNo˜ŽÞà5œÇØ#ISqÆ©!˜Ë ³þÜÍÜ7àô{ø`\ަüÓCÒU‘nÏl‘ÄàmÅÁ]/(l” þ5þþïR×qz4ÒNßF§ÐÖú¼ º±7NƒÀpÒŒ'æ0Ñò˜^5ž!"ÍX¡”ñ•‹Ÿ‚ë[–‚lË,Îo Ú¶šÂÁò+iM[òøLƧ̎ºà/¯~åë:}{’—6NM“¡cGm–¦´ÕRÖ œVåI ÌÙ à<ÝHjá;¥ü:6ˬ$6qj‘äË2…¶þ~Ö:S‚!Ù“gí!0'ò0Eò¥b#­8 ~<8@<¿¼úÁ`…¡SâÔ”sÆþ¾§!%®ŽCç §ÄÈa¤BW6_< '˜*)«-¶fTe›•Ò‚ó¼FåËÔ·Ä·o;$ÕNkš=‚tñ rÅa8dð{`r¤¸,S@¹8’¦–Út²`Ö¦n®g ÂT9ŸNÏ Àº<Š}·§.oýbä¾£ ZªšelÅŸš—˜$€¶U‚AÆÁ?'N‘`âNÒAUhÛ¹°2©Î6N…qZç`(.²^jñs^ùíßhÛÍÓ“œ0-üh½Fƒ ɦ­¸ÈÓ_ÐÈÌV¶û ƒÚN£ó/[‰?p¬L0Ǫå¬0UEòc[¶Ž¶R"úz.ÐÖm)Óy ¦A#ñÚJ¤ls5ßOu˜”ÃðKUØ6ÅȳùRE¶J±ÑòK‰Ô—Œ"ѶŠ@–:õ÷áÓç3ÊòO0eÐÍ_1_ÄéxçƒIœmý:eG)€FʶÓ *œÄ¶ÏµR‚s+rJ° 3Œx0̶™žÄóU={Ûª•bU)Ožõö9Cé)å4°¿ì˜¥˜H„`‚M#>ÙŠ0_ÐÙ½¬0¿•óŒ¨a²r4U…‡kí8aΜ׊OÒ¸sÈGn«£R+ŸÅVP<%>u5B„®¾!á%êXê’ïaÚ  ’¶ºS™Á˜Ž˜çŒNf¯ù®N/g‚Ö•bÊ#ç÷²A®Ë5Z[«Z}9ÞÌÔâL ŸCs[U`$u'GòÖÚ?Àf(Jh`¶CI—†#Û±pc‚yq«x°¦C%ŽœIÙÂÀó£—ŸzçÐ¥ x·$«6ò"­â,¹µ+NBqƒx9aÌ¥°EÂa©²*y믈ø “îÀ¾bìH;¥dPbËrF•,'Œò­»W¤17uS´ª æ$Ík;ÎðO0 8Ú+ä\‘.\ÝŸ€µ¶0. I¶¤Špl]ÖgëØ¨ i Ù}U”T•+Lw‚“|ë»ëîWÿ}ÎÓ½W“KS_í£i}Å#FÄÖðMdµ•m+ËÁÀ:.Çh+—½ô__ß^øy *tDu”aƼõ/}€Y;Ý_;qf@æöd„IÙzÍò cëL¬|$ƒ¬Bà»âd‹À84N0«Ââέírþ¹¼TH\¡-ZŸ\ùL•­§«äÃÕ?Ù×. FÀF¹m>§Žadm­âùÄ„´eùtV¸U¶©m6²”ƒuZs*ß© fð+ƒÉi]¼­,Ó®ËñOÿôOOð/øx<èpº ]÷5"›Q›~­ˆo+·„„çËv"|ŽsòáÅ™­,“ª—`ϱފÖµ¸m™F¶âëÈqE”»:|¾×Bÿ_ÎjE”T^£Ãõ¸{Õ¦(µBø§'ÓAò[/ûûõ¬-˜BæªÀA'Y·³íù\\äTÞ£°áü½ꪈ€vR*5°îŒní×}Ì'È Ï10ØmzžN6ž‚g…+OZÚJB¢2Ž»"Ú²‰´æTîV¬ªí/¯¾¦ê²ZÍeu+Ƭ] #ç‹l´)çt»r08L%glù`]G‡Æ¯)§^ÕÖñ9¯LÆ®<¤µ.ErÂWÂi(NæÀa3~<¡Ë­$ÁNià9²R¶•üÝßý]>_}Ã’*ß96)ëY×Q';µú BRÂ!5µðªŠ“HÛ¤Š(,håW(+Å/É.M}Ku8•@²dˆ¼{ ~Xj"7ŒU#-\&µ¤ò“‘NA|ùäAä(ÈT9ñÄÓSQ!¼Ós! C3v‡¤A¼“ä çÃk£5~È·¾ýOªWîDÖ”0½¶êØ}„aL\°ënµUE-ƒ [‘ü‚Ê/ӟߣÛFŽ3À U‰°°¶[E¤²‚GÇ}ê:4ç9ä¯9nž®N ÷’YGNÌsž[ÁŽ‹$q~Ä€ú–€pÅH;‚"æ·ÏéZJ!AÞÙ*¬ÅVS;%m©Ç£¯ïPOLüV¾¬‡¤*«^6*Ž­±i‹JU].ðëdSÕ1ñQ)¬66¾¬Ú‚Øí€n k´Ïµ5 S¬ÂšZk*‹ÜjËÄÁž¶L¾•P—j‹(whŽè2}i ì¬àCŠhQ*†ä 6iAøâœ ’ñe_|w÷{ý=ûzÕº—"ÍMdíž$¬ ¬ 5U=È’Ú°Vl&²v¾›¬ Ç}Û7É8ZZÁ¤Xx„RÈùšºÙà ÖÍ/k Ù}[í[«ßÿi@„‰¬uSNm2 ÙtHÊrfél‡ãUURylð‚)á8T¶ð“7ZŽÂ]2[ø'2<ÀP.œégõå¼õ…¨ï1?àŸ`›‚Óqɲð֬ç?ÍU‰Ge}"Å÷X+eLµáõB>ž§_/‘îÞʃQ(ÐZк’ø­}2k"íX%C´5ß%î=¾{^P-C.K ¿Ë÷/ÿò/oÝùþÜ­ça¬w5G¤õ^t:ÚÊÒi¥¡ANÁýÞŠm RDŠlk:‹ÀÄìÔ¿Äâ¬EA«-æî|Ž*·+‘†¬H…øÃ^<~Ð9èåÉS‹A:2­»(RŒ/f…Ôîª!a=÷ŒÓ\ù††ÆAIä`Lm7-€í‘r«€{0÷µ»¬Ÿ.¾™­2rôÒT¤­Uª¬uƒ$É¥g´I̲ròm˜WÇà|©ñwZtìR˜oÑY¦YÕ‚9R¬Š(ÄáóŸ ùÁ‘÷8ü1ë^/-t|Š,neâðùœªŠ4¦Û^¹a£ £¤K§½ŽR†RʼnÊÊ’Á×·;#¾×¦-žÝ~µ€×g/[J” B*·L€{²vûþ ˜ dœüºT›*2”äSÂø™xx[q$¬ZÌL¦’9Ûªªœ6ŽBUÅ­,Zk'FBAÖ+ºãRâ@dÏ{ FtVeÐ":‘x¤ÝŸªIn:`˜f ˜I~…e•«,‰8X[UœHbÐKDaHÒé¡ÕÖmÚ÷ 0›A°Z„Å¥l™¬B%|0YäeùE8²:r0&,Z`ÛŒŒ•`TÀÄÙ¶Ÿ+pgÈѨmbøØm­ùJ1´¬ ³­/€­U­ˆï|غØ'Ø÷xÔ>ñVmë%þ3s"·:4Ǭ…¨ÄÛ‚e~õ?Øwà×ÿëÁáïXÓ¶” ÓZ_A>…üŽ @ÄD¶©*eK°KMx ¶˜ý=~‘R=—ùâ„ÔÑ–ÅVa„EæsBÂÐßY&ˆ“H½õ>WßV/3ç÷m ‹xò¬¶ÖpJ…QBç-ýzF Õb<˜QÊùpùª¢â°N£SÕE Úa$L€ß66k":OUü8m‘‹ˆ¿õÿŸvoxù`Öm7¤îœ3Ûm7‘M4mÅ9ŒƒÄêŸÇÑfäà‘â0]€½rY÷¼^8)Émþu’·îœ§Ç f]<'%eA¬‘,ßZG0J‚á\ëäm ÐñØJYÁDÜxþõ_ÿõ­»È}òakD9ÓQ»tNísR" U7¦×>_íVYqÊÝ™¶JÔŠÔ”#ÈÚJU;€­×N¤”¾lAJÓ¿ÿû¿ëÇ€”x`6šUÊÝ?äÑf«£î¶²Vf«ª”,p«Kfö4#Œ¶‘¥T4uÇR/YÛŒØÐF‚˜ Ö½8¼ç¡Èçdµ`ö—ìÛ¶6Ñs}f©R%Km TqleIµÍ^°û„ Šc|—Þ¹E([¡‹nvÛºÀóñTk«„qDv‚Y– Ü/:¦áæe¡Ù¿¥yVv©BNmãhF! ²,ý‚EžµÖîÆ^J¨îˆ~tëÞmy­Ï×:h­ °î¶œaž[Õ¶N²³šr÷›‰¤èÁÀͪp[)[Áuì¨kÊÇ^Ø 9X„áÃHñ™Z’’QÄ `œ›HÁº¤ÍZP#ÆO•5‹ß!Ûò·z"Þö¼µ(ëÆ—„ŸnÙ*C¦žt€Zæs ™°Hà­}L1§ÂÚY›VPßùî!F1œ²L6¿k +ƒl:‘ð[ Àa‹   ž6‘!E˜­µ¸µîIÁÁ8ùÏuqäâV†Á–xäº÷n„B‘tðYTî €/ˆ„ws;d“bCëp8²œH´pŒª²ª¤œ°xÚÛò£…a4£T_°Õ³ûÅ7³ÿøÿ Ízq ¢;Iâœ"fL$ "L¾›ÌÈÅ©6Çün÷jw…Õ·m¤8fd0V%8ù 'ÃYÜ!̉Ù*B-pÙÎÊVJ¤ø_ã_»èz±äéÅ'†“ßµKpq«qÊf›¼HÌÏ@Þ,‚”­;ÊVªá[wVuV.€°³ÒÀª‹x&Ë™%/‚²|Žx„"~ Îbøpíˆ×šrœjEÌ›rÛ44¬ì”s¤ÀÜœ¶îÄø¬YÀ*„äØã,²­•)ÏÙªãξøb«c)>ͲñÈò3…Íl¯»ªlYY…L¡” +ëÆ(ëîÚ„}èø¼B˜.Œ£#눴sÂä‰P%ke„5‹À,Y[RWBLñK|x1L6¿ÖVÁ£ã¾ÜB¶­€*%V„˜)ôWÿߺKñû¼‹ÜD^’fÑ˼.Î?I b¥ª)Ä»"J€½kªÉð¨œOÓArT‰ð¥ ÜÔðº[E˜Ç)|ÁѦMœàjµÖÑiø9­?\ýÔ9]Xl9:ÎÄù„ Ls£™NÖ,I6°-Ìe=´ó9&Užé0ñà/ÂçxJ7oª¢åãä[1¨m[ÄØšø¶|×âóÿ›ž?E6´޼¾â&Å7c€"E)[Yú³|k7µœÀØvD‚¶­jùð’²9|N¾ìĈäGÆ´8,·ŒC¶Ú‚q(+b/ÞÔÖ²cP¨*f.ÛzU¥dU!(,ޝÄá+I þ5‚çGËÑÈfŽÛLyAø0²|qµ‘ò0»·m9_ßÚwmB{d¸A%XZ®D¤2Yu•o›/Îa8ÅkY¿ÖRªr¬83¾x…|xå"½–ø`²âl8”ë%+oB~¯:<¦`kWmòò«Qž/Îà3¾xÝE8Ö+äœlȶOm0‡åÖ*_ß8„ «0ð-:—­ ß:* RŒÃ¤¬Ä»š8I±e0fo‹DNƒØ ùÑK¶F8Ç,¢Üƒþ­ÿ‹ òû·sÕ®ê¯=TéåÎÔ:åÞGʼn´J„iŠ0"IÝ>Ë «‹Ž ƒÕ-¤œ)9åEàmùm­ eÑ&£¸`Ì‘(ÑK°l-¤^4-˜æzéë0m;OÙNL„ÃÏ‘‚w ;çr¯µ8Íá{ˆ»è8«€Œ ¬rA¾8aRÀ¶L6Zk>$Ç: |©0|VB„†âÀ ³-U/þEE?LCkF€— “ít$›0Û¤Ú*é§AYlx|©¤a:4%`  #çïpdÕVÈ/ÞZ/~Ûz…‘*¿ “´â‘êxɵ²ªêb«6yu¬†o­ŒfïOï~ú÷3¿± zÑ£K³è•k·=ñ,…MMUŸõ9ʇtù ‹p€qÆ(þÒT‹ö™©/ #×Ýï§½õÝn]ÜK¾pZ˜¿¾‰¡lY7§`)UÄ0UîFÁ0i¯<¤ÕõŠÁƒýÅñëaºhA1Ìåáœö÷vÍH'§¤ŠÉ:ÈjŸ<+é4ޏ3é*˜ÔȦ“eRÀRyTϔֶÚå¨äÝ™ëX-ðçN×÷8öÓ½òã·ås:¶¦ ¯c$)'ßšTq˜`¼·:_róÏßßÑíĺaÔŠT-ð὜"kN‡Ðú b¦e;@Åvµ¨ž½Äm j2pMe׋CsüF«¯ˆ{éŒ÷ýüTØŒÝcÅ)dx¬µ[G "Öµ›/ž£]‚óÞ!ëNKFø£zÎ""E½õPÅ€ÏS#V!e.(R)¦XPýdÙVâd!E 0ˆ(çØ®1‡9,¦?«ŠpžŽø‰c¨m ”­…^²,’¶SURal1( ƒ`¦ R;Žã0œ,ޏîâ5½Ø3¾ãtº„IC·&_ÓÎ&¶†3F‹u±\|²EÒP ñjªµ ]úPRjÌ)Á ÆIRüñ‹7»Õu„xñWÿûAvMõê4g%h5‘»Î16ÁÄT¥„‰—¢³¹º(‚‘lLA[oBœÍ›Õ3ˆ˜5;§ìs­ÖÊjU‹ð¯ôíÿ+êˆáh§µ#²Õ”ÿl+nÍ‘âXgØîXYÊE°õ:©.Dµz9A0`Hñî[ñzáç@:ùz­ïéw R”ƒg¶@lk]Gþñÿq#|èøôßDzê…sçiü{M™ˆ­#ðDr¦P­ªÎJÐ\Ö’rµ‚1G(hke;©‚ðL*ðdˆ”zfk¡pÌ•<ÁR"ª8‘°&;Íü`.GW­3‰ òw?ý“Ô/ÿh]GiíCFâ;ÿ͵yÓ&.Òg"‘t‹r”«5?~%ñ´ÎlsRÂÇž¿YÌ^>/>0‘ûnS«µYDôbdغ^â†ÊÙ,$9ÉîÉeÕîÊ6)æqŠð*w²3få#׋“A[Gm鈬¤|ñ<|ñeëÛÿzѠצàw:2X™”—¹A¶ x§$’³ZÈÊ­†² i(«‚`·Pµ”8®íØrð¨M-‡¡Mõ‰Ó–_^-þk+…^MÚ)s<]>8ReC:ÉTQ/Ʊ Ù&³ëÕËÍQ3ÃâQ"Ÿ£*¶|´?fOá`ˆT5©.k-¤°vìº7—>BU|FXJ$ÀÖ¶8ê©‘ˆ­rÌŒcLÖÖ]Á‡aJ ‘K5xíªV+Ùΰ^.ý`"â4à·¥­Bü)‰Á*BƒÈs €âí• Ÿ 4.q+jH>Ç–£>ßrÒmÓ]'Û&ïbˆdâØ˜-¿mkµR±q,žã9÷èÕÒÉ7ë6Eœj™,0ǰV%¶É°MC[UxDð¨êp8JBÆ3† :n+ÃS–¤k&° bƒ‰­‹Ä/˜†Ãò—&žæ+iÀŠfä‰×È Ø²5U¨Ê‹FЛS„ÏÑÄ™¸rÖ9 á‹¿ø?ýõgú‡}¾N5ˆoõuÕøÞftïÜD’‘þçzÆûþõòÌE¹‡Iî'c#svÃÇp“_÷¡*]ªåHñ8|ÛEŠoŸà`=†yËñïÿk‡°^®N¾ŽÆÏ·Ò¬`‘J m3lN؃Ɩߤ8Õî«÷nYoäòñ¸p!ùnfÁ.\)…¶ZÇÀƒÖk*û€•€f혅ò¡Â_^}P_cê¥ë¯;%‚Éî )/"èîà@'ß= ËT‚–¯ó`Š0þ! )(¥ÐÔià‡ `+.¹4‡§ˆ.|}Ÿ…aâ¬Äš…o:UN[Ü µS©PëºØ¾þéß7,5­14˜½ÓkëætÚÝ`Én&Ì3ÄÈ]‚^Œ—¡¤øÖZt°"wV²!2Û¬³âë˜P¹Õ êÅ»Zø×®F¦¹¾õ²ö¨4  RÖÉ@ÒfüC¦³sw˜R·Úª‘EÕm¬‘lBâ„dR±YUÕX ‰¬|q[×ÌoþxÙ®êsg:‚¦§Á]ÎâümÉWØ¡=1¦ÃPœÃT52GœÏøÎÊù;.ŽH)q%ï@0¡ÇYé¬×TÙĤxbr>ÿQ§/QÑs§9Oƒº4E§GƒAh“b⪌–ògŠ {â{p0qUV¾«íq³' Ñ4gqÝ[‡ä§Š£ã0œ| :ö“‡”‹T…¯*Bx}ië €¹d_ço©G<˜µ+b(UØÄÓiËW(ŽdDL<Øh¥X «‚ô:ŠŠÏ¤ êb+ËÑB\G¾ÃÌ´óÈ]úuç)kͳµ‚ª4 –Øù @*éùjX]­j!e5Æ2´ñ¯]å± *d Ê ÎH v0»e¥Ì¯¿H˜4Ûrà­²`§Ç=Z¨å¬©TxA…¶O¼¸ªh9 +¥`ÅÐûŒ8ƒ!O•íRekÍo›ÓZʪpÝÝÊê"•þekÚø²ÀV–Â|+~HµVÛFóÃ[nÅ"}$×¹s ^;ú» ¶i³B–%Ì ‘R¶‘XÀÄãät2¥7£HÃZyu„ÌRÀ|+Zq+&ø­,QÇV¯-´c"95µ-=¤Ê6$'ƒÙá8:YVƒ¹w5O`%"¥vó¸±E0HimV…pÁ±Éf²´ñ¥ø ™îE†—Ê´׎/軪ï~eåkªdJt!24ròÃïù#•…T%…ªrNw¦3TÀ4u+ªE8¶‚R_Ðj ÀÐZËÒÆøì&Ï=IÛ²ÖR² ®‘H~)+ZH$¥4u¡m])Ó¹"†ù玛Üñ$F;}ua"=7¬gæ{Ï‹SµÖð^}xˆƒ ²¦¶vósªÂÜ•i|½2å;„u‘S†Ïdûô¯dȃxf¦Ü¶5¸-Ÿ€n¶5µ=ÓÞ©î«,°1]5ë‹„rw»“äwÛG £W©m•×.U¶‚²ºè ìë·þ½>Z¦Ó(U":2ò(g”°‹=S3Ûdw¶À¶V.… L•TŽF‚îyÛµãkUV÷ÞUqÞª4ž“¥’ñ­âz•µå·~þÿÛñRrø½‘㌶vºPN¤Á‹”ÏTqºÂDÒ!4uúÙ ƒˆBŽCƒ×½Úî:Y…EªM›FÀ¬ÖOÀŸ€'  ¾ÈÑÊ6Z°Öx ëÉ®ÝÄi‹-,ñR|$^8œ¤ëÌ™Huç$/ m³­"RŽÑ›¤ÚâµëxS )«cHk²Þ?LzÎ @ D{i•)—Ƶš5à@Š+$¢¸ˆ­rq ât$ÅV¶Û¥ÏÚU‰kŽ̨ø¥ðç(aBÖÚ*®E<Öµ«8 ‡f~åáùƒá!#Z§Z˜²õ¬|%œÆ)’N«ŽÎUŽvgMç«SÂlÿ; 0LŽÚð8›‘'§#ªK÷Öóû¸#„7Z×OâùŸÿb"Ýi~ù'ߪ~ævb£H˜]Ü"»`tb€Ï`lKaã˜b×K æÙ: À‘/e[DJ0fþ,…aZEhHÉ»ŸS‘ʽ¹ŽŽ‹JGYkR™L'#nËW ÀªÄùtV1(éBxŽˆ+ñŠæØJE˜ÜMÒ—úØÈ35˜“—K$%âEpòN+0»ã/ÞP¶ü”~›üyé'*È; ÎS…ŒÚ>Êt¿¹“î@`”ó!•ËÒ,RÜ–#+å|¬`5â3þs[¦³å°0VÌÖŽeYN#~n0å“•BUÓÆ±Í¤`ºLá‹pËþð‡'ò»â£ÿún7N]HmœT58Ý´€Ó‡3ÁN¾Zÿ›WͤբŽÄÝh‚L S^Ü Åa8!wÈÁJòEôòk²ýèþ²xß1i:«^L¯‘üf·Ny‘AòÅe¼1E¼#Øs¢rYû¦€×µ­”Õ™+á3x²m‘·ŠCF(ØMò·û·â9ÓG;ÿ:\ ˆI!:ŽŽº[{¡Éò‹˜+‘g†ï§&5Q5š¸­u1;Œ“åK5Q°ú†ov+|µÝrÖYY­['É63ˇÿdÂtVd¬¯.™i •ÙZÁº|7v‚ eu¤xDo ¶a‹ ‹ŠSkŒ¬ÖðЩ³²Á¶í¬„i­{)HŽ9ÃcU§€ã¯¼`œÖªÊÖÑ8‚N¦ U\°µ)Ô€¹ItŒÍs)G¼O_ªÊg"©â ¢ò›t*·•UR;~°Þjem­ ™‹BX’èìªáùú\î@!šO«­~DâXøV>«½$_=íãKÿñË*dt8º é¶Fë’¥`à$‰S¤Ó¶¹`˜ˆ-Fa&È ¦©T«8s]Dt·º Æ÷#£.&ް¾iƉøR" §Uaq«ˆß!~ëúKOæ €nxí(´ê5©ðµîõb.@|"9xøNÀíÍzЉˆC6‚U¡yá²¾t|¿ZmeÕZ³ù‘TÐZpN%Hž9Œ Uc–G"UNx$ ¡wPŸt;Ê_YýÃ_¥.éIFš“¡içI†31ÇÚ}î’)±Ò»ï"± *ü/‡-ÕD‰QÂø‚²Ö 9¥:¿ùóîkß?u5…y]Žvøu¤a}MaK›H~N‘f镳|f§*õ¤  “áˆl«Ä¨=]ß3¿ÿC*Í^nuŒ›ÏÌ+›¿8 )$IJ|NS+ß§4[MÜgžÏAòÁX•gÕòGU-æÖ%PY÷­ÿiq.…¯ã,;ªø^rOªWüÄújZ_«éLšQèâê5åR½e Sní48!9M„ÏâÉ·Š{(¬£¬×få 9NF–Ó¶.OJ¤bc¨;g&ÂÓ7þßýâzù$\ âµKI‘V)²‹ó è*›Ý9Àd^&žÚLЦ…ìÊáµhœº7f°g\Ub‚=×Ú‰Ào ‰•!¯?‚õMO„R1MÜ…V-|×:˜µË1ýÕ~¾ìÿû‹¶‰8N_ßI$²K6…‡ï+Oâ†Qe ¬ FÄêaóºâxî5 m%À ¥ÊÖµU!Ÿ<ÆaZøyÈ+OËšÖȯphªE¯Ù^àtj­#Œl¯»´¿a¥6µT†Gܵj™*äF‹ÀgÎïOÿ8!ÅÌÄ­ØŠ£ÚIb{ý@ôõ‘kAC sÄŸ˜îÞ¶7|æu&`"dÏéègÞß;"+°ªãás´S[Ê-äÞë$C–êpøx:Û²V&ˆD€-ÿ†¹^}øÓÎ?þñªÖVäÚáϯˆ^F‰­‰`¦NGduh"R>áÁ¤Am¬‚8ñç§•”•5fµe•Ä`›Ù6ãØëÞâ£ÖÝ•åHÅSŸcÍY…â™”Z‘²‘&òDûüÏ#Çìß!á\‹+HÞÓ©j‘&%XdÁ|kqT]AŽHÌ"úvòÚ2„qޤì¶q¶vD‰Dë.²:sþ0¶µFâÕ[ŽïŒºÄµÃ©R%øŒËnK'Uj™;Äýï@¼ÒÝÌ‘Àü?ÚîfÉ‘ëfÂðExãp8Âòý_“-k$ï¼óþ{ª^2U{$«IG8‰D8Uüi6§Å®¹C€¬h«íJ4¸S:p²Æ-ýÐ=oo4¹pˆºÈ¶¬)¬9gÆñ”Gï>üïþ=(á@¬«GWÀJ«©+«Pƒ6!ÄÖÔ48šé„ŒG†p0«ÂaǴ磯Y Ÿ³è•&ý¿eäÎPŒ#%œÏÔ½–b1­EÕeñó…8]Ó8e™Ë[“?›$þMóu=è_E…š]Ýz+A@sÚ¸[ºG¥­\¸-N’ˆP_[FÊ¡Dd:.š?³º¶œmë3ÿB5ù®Õ&ÝQúq!˜rV=¸?zVˆSoÚ0rͬOÑŽÎo‚ÆgC]ï¡ M!G­t”È¡¦V Èò…½ïñ4è¡Í«hNm5Ð\ÆäC24ç¦OxHN‰ÄD˜¶ÈhqlI1!&¥¬€¢&…{jí4H¹p‰| Ër9~A·SþsëþóŸëAuóÔŒõâ¸ùu»®€êvƒÅ4;(TÛ5c ï<‡‹ „H·¦cu/‘eÝÜÄÑ®‚YN`‚­tŽšO§+ˆÉg@ˆ”.¨ŠÊu h)T%}%8OdÇK@IDATÝR( ¿œ™Vi\?åÚz½£À„4Bj‰È=û=NUÅëÉPjå!3ššL6M²@‚D 8ùõpÜú’Ix´ËäHh‹AH2ľVÛ¢Õî”w|Ô&Y8qˆß'Ò¯¶DÑ| "¿-} Ègá@‚ÌXogêM³E3  UÎz¯ YNÖÌŒ{V¥© ý8²Áʯ‚mu´­:§ºh%6 >AŒ8…h8i&˯ºÄ ÑØÀdœ|å ÂWˆ2?…Ò!h¢ Ç6#-¾5gRŸß„¿¸z÷ß/š•&Ûª=¦ædz^¸êHë ‡[>ZQëCJ³tþ|„£äyþõ2Á9 Ú"§/}…ò¬(¿óÄOÓDS{—ã }Eiò™NX­ZU×É*jõzÚBnuˆX«Òk˜ÂœI!L9°*¶Ä΃%HVÈ*¤Êøéth|Ìn]U€ÑÊ"Õ#«~¨iù{|Õ„x穦´¢V-5ÅŽ±ášê°öÚnd¸¨÷f÷¨Ì¡Œlj4Ýê‰U:k‹¼-d[`>UÒvÑ9KäìYh£¥`Õ3£Y›Koúìîí4ŒÙŸJ¾ë¢“«yZöá®ÒPEµZõ¶ñs„$Ö¨mˆ3ïy†_ÜOfÇ)‹#‘5°ÙádRl;dÑÆ/Sné~"zû/ý:Uìb)­+¥ÖŽ×,çVçn|8'ñq—A‚hk Ž£zkË©4‚®Ü9;Ýz¨b !üå/yûe¶JsÔb5`[ÃãÞ^¾µ¦ø‰PÔêxE=NùÍeÛ,ümù5@‡9´ßUÊøs"ÖÑmkÖñÛâÝ …?±šÂ¿QH{UÉß@²Uç‹¶VK„ÙÂYxà²Lw áD(ËJÇê`Ñ:½Cë|(Á~'æfFîfÃwþ1VŽ/¥‰ø)ª¡Öåè…¦« G"©VRÀVN?È9@4`w‡ŸÒŠÌàãˆzÏá¿b?ÿüs_êUK“¤ÈjàZÔ,L”Õ§öðùßlÓUˆ–Z4RUQ!¿ê“•Ûiˆò³ÒC’Õ'µÄSàCàŽ“C“?ÈÛ_ü¼³1Žª[“+׉­6lk£Uˆ¹o»«ù5ÌAà'r?ƒã¿p3v¯rpŠÂ‹ÊÍQ”ƒSo˜L‡ÚÖ‚-¾6\”¶r;Û8ÀO$ÐO¡Èùï]Ý–µD_'­JÔÛÃŒ¶µ³Nø++sÔ}Äà v{`<Û8óžÇ%˜Ÿ2~ÊmѪˆl+˶µmHÍCT‡ª¢P[ ÅQŽB¹¢‰®£n¼Ð÷{÷Oߟ*7×YogÙÛÓ”­kR{ŒÌšHÛ½IÕ¹/µz¼PºßpÌžB²†¢'‚fR«rÍ…DæÃ1­&ÝŠ/Äñaíÿw¿Mmõñ?}Ö‹ &kC'½ZÕ?¤¬|ëÐ ï:^£óé3·Ù0B¼y)Pò¥Û 9X[/²Wo¶ yÿú=þ/(J{÷ïÀë­©­¬¶ó[sÃ.SÿD˜í˜ÙisÔâØv˜RÐÊb8SÈÕ‰ãL‹O¤Zhœ­EË…{”ýéOŠùĪ¥ô+Á¯mNµ8šY´­>=5Ã[…ʲmÍá3QÓvÎuRé¶dkL«PwroÕ:4Ǩ[R¢«U:…@Žt† ÔÚ{wtwf™ˆ>µnàhÍ(«y‰L_i|…ˆØŠJd¶GÉûÔL·u5<¾ºú)]McqÆä0¡‰Z’’UÖ†DUÈ?û:®KE%ŠÂ½õ„/ÄŽ7+þCB=iü 8ˆÒ8ÆFå³RbÖ?B…©W˜‡È5¼”¢¶£'‹\ÅpÔ•ç×0Gu¶#V4>Ι}{F®EKçÔ Ž|âr‰èÁ-¸ê.¿6–( ­êVâÆ²ÅI‡“us«Ë(§ÐŽ™”*ú©4P Q §ž½È)ÄOв\œ˜¶ùB@L~…â$.¡ºúokÅ÷ÍŸœzeõ^Ÿê5ˆ¶)DŒ¬-«.§C(ÍŠbú_“‡ÄýgEcJqàV‚­ÑÊŤÀ–"‹oÍAãq*—#*+~ÎÒéCzDpàjU.0YéȃpÒOAй?þ#lÍHA{Ñ|c”éTggÇós²¤£‚èg+¸ÛLÈy]Õ¼×#Lx| ² ©’?gü{üv}{t¯¥ïôîßWÿu¨×¢qªË‡èMu«½¤Óë „F–r5!+AN#szs-hVȪŠ׌\=àw‡0÷ÉûÿÒæ¹vò)ߪ¦ƒhO3Ú+j«Ï)ëªPL[„¡uWX;Ê@÷O8¹h:ÝZðÎG”S?p~ÏBº²LA®‚Àäúèíý¬ÿ¯ýËû?£‘µJ'[ +Ò¶[È6²)¤Á‹=ÝÓK ‰3ý8dSŽ#ʑճDgHG‡ŽÑ±ØZý¸î ñÞ]J‡¹ö$ÖaU¬!hÄ¥W.]hBÄ-j®ÊY!8z˜‡NRp„ŠÆ)±Ü­B|¡æMJKtâ¨Ë™l >3…­Ò,štNt,|lœ:áK¤PºÁíW.5ˆ~Ž2êÏê -ÿ(~S$­Ì*Éç¨Ìd!C83ˆÜ8‘…¼þõo‹õÓš+ªÙ%T‚s*"Ä$ÚŠ qÚAE å&5rR’+*ĤÐéžàØ^ñiJ‰Œ‰ÆW‘š“mØk·|–T­†XmáRꄟïœ|[Vó1Û"ûˆË,¬ºǰj¡Ðù ñEõŸ?¼Òüºò Ä[þî§·þž¯ eýÔ¼¢Z²Õ<Çj tDîTHq"‹2),_"MÆaEÍ¥¹DFî(p©1>ruù!R8ùUHÄäX™(qÑ#,‘S¢rÞ¸zŠt ¨eŽqtÅQQaŽhL+Có®×Ú±t]t"I5f|k ­Ä9Švæ*ÊÂùŒ_.Ÿ2NU"H?Y·W&L„‘É–’¦‡_¤`ÖI%^Y=¥:‡ºâ+½mBD¢–uÓÕ¡mý”bMPnáxЙ«Š¾Ä8ŠV×Ó‹[«ÓÄÁᇭ¥:‰_9~Ç"—²ÃW()Î!q·&RS̓T¼,âzŽæß`||çk¯|TYŸV÷€ÿ±«ºu¢™É5P´©[ãwÆÁ¤†Y Ðû ÛÎSˆ#ËJŠédÌnËÂmç‡à¯±¾ õ=>ûwQü5¤ÆÔÓ5šD{×­Y˜P~ ÛºŽ8æ4HÑI0PÿˆôV‡éŠoÌ8*âw‡@DÝ®iªk«„ržêýˆøpŸÄÿûå$òœõq’\uµ:œ¤š‚¯1­ m^ÍkUÈt žBœÐjdEL™©"WTHn‡ Ç¡,]ÈÓɨ®­•/”¸”Ùz{@< ¤ ü¬ãOèºç Âj‰‚Z+§#¬g4L+Ð8UÄ‚pêŽô8×3+«‚n ÇäC„¬©IÉ2RîX÷sò¥K!‹,š>d¹,A«¨??P( á SSïzÙÊŠ,‹%ÎAh­?ëƒEÀ/eQ)\¡ã¾9ïÎjYøhê¢ñ­Z²6/§¨•H‚r;±…R“®§£©DúåÚo¶=¶»“ÄrªdË©û: Äò…Brà©Iqë!|kÃ'§D«Jwåh"/d+X{rW±d1¸q¬9 œ#Þ^çd©’ñ…òk/_iN!œ¶€ qG kÕ­¶¦Cf|‰hR¬¶­BMaË/ýH8ñ¤ªá°Z"Ò³§P‚´uOÛJo ¡¬4„c —n{m²­\>åºJêZÝé-ÿàÒ“¾_DVW-éGoÞÒuctP:W½ÃAn[opÝò·åtJ˜9D8Œc¨.JQš•pW𣥠Šà )ºU]~Õç`²š´2 ¤mËÂßKï_wŒvÖ¿=ú¡;´žLµ±†µ‡Àœ ÜÕwMí@¨a¶â”ÒVÅÎ-Í«2GźzÈ­n¡8:ÌÆœS'Úà08Cö9âÇ·V^þ?‚¥|võ£©µêLŒÓëDˆ­~¬ 7/ ×'f"­ÚvŒÑda:m‰p÷<¤ ±ÅDë!lË<.ô9 nš Ž”ë˜pBàX#@8¢k`éBÄ!Vf‹`–>“Ó¶,!|Æ÷“˜OsÙêÑmðUþ„ã».×{H‡è¡>­9ßµpt!¢%¡ÈkgʬÁô»î|¸ÜÒãCá`Ò„—ëC¿ëX­­ÞÆmRÕ ¥t]ݧ´uƒºˆÞ ¹±!Ò›=ší±­{Ó–H#“ ©|¢Ã‹lõKã‡ñqÃO?ýôâGÚJg³Šj‰í|ê ¡1YŸ·´ó²Fp‡È-T¢­ÄÖêåbKÐI»¯€NÕ–™K¨ÜÜ{*[‰ãˆ)“žå[ñïØñ_ˆ|å'j¯¹~q¤Îg'Óhð=f¸¿C«ÿºªùæ‚0´ùfYÃqlj¡¨©—q¥¬øl-Aœª#* .Å¡¹Uª4Gb:GÓg9ä!®8“’ˆ¾¬ºjÈQγO¶j%¯J4>$§&Ûò³B@V?%ª.„) éi§þ˜Òå9ˆÃD0KCÅAà$A #[q8ŽÐqåšÐž#up|$kŠVLÅ ˜üz•MhLé5ÍAcB*nË$2Q­[B8ón ¼Z1ùgêíL” B§ËY ! h|“ÎO'°ðŽŸ&ŽPkçÈg˜•FæOÊ!àc.ZQ«ÈÌ–ÉÂÄoËaëSQäÀrûMH XEY˜p`Õá®lÊN† IˆNÐj#q)¨Y™wÿ5&ú´ù¯ujŠZõÖµöð®O ¨Ø [µô ÄÒ!¸F0ÁÊ)7£\ ß¼8 µ¢£5ZQ"Rš1©‡yÑð)8UÊLVUt%E!ŽPÛ©×·®>Õ몊ÇAܯ»g7œ&jÞ\Òm@ Ø çÐ)—ßMZÅBŠŠ²rєȱÅßÚ³­m…„p¢Å!$Œãó‡w8î(åŽòï0/ኺ¦Î­»Ô6³uP|uÎNÅV·LH“ Âw'xÓÀÁÁ#dË7TRmK·*ÁМ^‚È=@HuE:ˆms+#Z­kÅô‘NÌ]¡IåàªYV ­D»ÉcB¤û7Ž¨Ò­d}µÏ»±¿ÿýïWü9ŸŽ‰k‚–¬µ·mÊõ©z[NÖµˆ,èHm‰‚”’¸U( q¶&°Äj‰2 (_«Þý?üG÷–ûÓïúœI «X룷¢Ö¢œ@QfëAGÄà:Çá„ï(pòán`…ôçavéD ¡Ÿõbï¨Ý!ým(²3œ¯_¿Ró+å¯8NFi‚ë\AopT«¶­9B Ç#T!‡ÄcÐP¶‰k „ıE3¯¢¤ðm£©"‹ÕÜj›:2OPTŠo<ÞãŸþ¯WIÏd7©~jI‰£•óÅ‘.²> b:L lÝ hˆ• X¿mµàÒù”ã 9(wÔpšV?+YEEáz:rl™ê²­,"Ö®` Üø. d «Ã”ù:)WÈ)%ÂÉ=æ²íªñY h“âÔÀ ‘+E‰ž*ªÿ8á)Àe9fÍ—Âçtìüš¬䤌VËr"GnËT¹=lV¦¬¨xkˆ_G«žD¾z¢LT"ƒB;kÝ^øÕÚ %J‰iK°r˜œ|ë)|[l£µo ‘†wá…øŒCVÅŠÚ¦‰ÌQ¥Î 2Ñšt·…¤àæèNÊbES«„DšÔ8V ­·¶{ú€§ÃIŸÙžò¿.áöB®nü@iÏíE§q8:/AJcâóq¬³¥oËèˆ!éøæOwð¯=}Þs€ý1ïd+äáj«–—%¯7Jw8@¦œÈÕ0Òœî“V|‚|ÎÒ³@à y!Äq>Zn[šLV–fk]Áçð+ÇYÛ)\e•þøqiúO¯úgÒ»â')µ”Ö!œ™Ýáwt¦¨7LQ8΀֎݊@ ˆÐ¼!B¬k‘85'À—H‡PKOúí =_ô(y¾õ´VšlüVšã3þg¦¯“½ø§ñª¸º¦¨Ž6ôé­;¥£é³a)œÎ¤µÓî´á‘9Z)©„•B¡Zp§´(g_u ŸT?ä H)@Hx%„ÚF°Å‡vM1õØñ÷—àX«¬¾düâ*™æ/¿ü¢²æ½v×ÏW~Ó5²ëhk"«AtîQ3…Ä·MÍʪè<å†ä\gOV!? >|ªíqç}ËMî§µam"mWÚ¶¬ÚëÜ„l…Ä*äfîÛ Ýç¢Ñ0XRÉÚJ™Â±EsV§´#êÄñÿÏþózæ8÷ YÕ=á_COûýÿ¿ŽÖïÏ6¤vÉâÒ›‘ñçðËBC°vÀ7cç ‘#JR:øUé4D£3ˆ“qï! IÄ–Sé…jÆŽ_è¯jùMKÕO…´¡7² ´mŠÚ’ º^@¯ÅÝððea2Û­9Iñ»CÅá¼b{Þ'¢zRzèB8(@¸¢¦ÐFI½ñÝKÝNF`|Lxƒ'Õõ¿é„ VjVœŽÈNaI)!K'W°Ä¥ á±2dâõc–:œ Y´Ò«ò–U!:J3˜~ÍÀ5oRC¹ÀÚÀäH÷,ìÁ‚P‡shò7òœŒ¦ƒí(0)B‰[¥éÂ!ìU?¼6æïÐÊ¥â±üñÝ¿_mûRŽ—–Zzqí©yÝBŒ`ËêD˜ž&Õ­­t+~+'«Ðtl6ÇýSERq’‘E<ª E"XC0¯„ô!Ä­] åªYé@è˜=M[¸•õ ·Û¶¢yWWçoù.–?ü¯7Uôcu³Y=ÊL§¢ÒV}Ö§m½¹†F‡yŒX1;ÿ3Bj9­¢høt’jê!«Äøx³ë‘õã?þðÃÒ+«ÑI…è4ìn†NC´~¬ììúöä"Ó\¡Av†ÖN 9ùøõ`Íi(8‚mIq¤ø±çá@<õ~T mŽ6j²†k2ßz4}Zm·Õ§gQ:XtÌÂ;– ¢.AEËÊG(­S%ÈaÝ?h•®–5åá?R>ýâ«OÜR³NÎו~å@¶ÝP@äúÔ¶­ïVL!Ùcªûóφ¢V L—Ëï ñwž:zlvD;Ìú´Â!rõ ‘T]Õ'œé NÏr˜= )]V}–äÔ›\– Ü4Y"q¡²¬¥|ÅóáÈ"ó>åýµ!4]Õªt[¸tµD™eÇZVŸz;4Y©ñ+Š&ÈJ”uû®¶´fŽZá£Úi¶þ›tù„€Trø´¦+†,ÊhÂ0Ý]rM¼-™ˆ­ô|Lvˆžþú‘âb[»üž_Ðl‰°3éØÊ’’¬-<„aºu¸œÊ•8˜pYgÆQ¥&9Y%dyǃ©+8x£ÙV¢*®w) nò‘µÍº#‹J¤Ïê$A⶘•Ã, w}“ròœšÑž–"Ëê Ú†øç㯪ÿñU]ïT©úu®¢m®OÖ£±¡ŽÙΫÐÝbkÝfrËÒí.Y')¥óŒÐ±@ö°á3‰D8”+}L~·ZÍyX±ô/J|R8p[Æ·Úv>ˆ¼²õ»ïJwášÑ¼ŠZ)w¼æ2u~cŠÚÂs€kÍܧ?5²ÇT÷’ã¢tc£‘ãÑMÖ–¿Ùåæà­«UÅ*Ê_Šs{ø`U–›Ê˲öÔÒ|b5‹ö$¶Öv³«ÒZ{uX¡Fhv‰ÑÊå‹¢õˆ_n¡Ñl•f¥?LG„!™ˆhRÈÀ¤ Ò âŠÇ͉¡é³õSÖ˜&Úšäg8þ)çÃ÷[ÐztsäúWÃÒŸ[=ºýÛ_õ0'«gÕ©é„cÕ?§ÑÖ$îÎä{Etó8‚¥×êO¶VOÛÃb+%þõ‰±ëXõÒ}JòñÍî?ÿùOßÞ~×DEýT]ÿNF‡¨?kú˜Úi8«‰H‘ß9# «Åê¬*/¥rhÈñ1ó)óÇ¡þ}ý¼å¯Éi£ïÿÔ¶qšhMjÉ¢™í·c^ [MÁ‹->ŸÑhå9®¦©•b ´ Qe¾P‚)W4?q ôK iõÒìŸ<%ûÄê5W•cŒû[—åšEñzØ‚Üh5ÖÁ– 1WjE°Áåæ äè®°²R8µÑMßù¥0]åÈ•HJhã@äºR$F& ÄGn(>P">§~** ¯7[¸Š È%b…¬t-9V´q6ìF  gÈ­ÿDЪºÔBFæ—Z–¬þùtEÃ"ǧæU`Uä*QÅúŸ§òœ#¶=9+ž¢ŠrÖŠ¨-ÂꀃÉÒå´Õœ¨”jÁ{Oœfj…Ø2[&Ë:0'$ýƒt?\YøÝômñK©ÿ|-MöŒƒ¤!A4¸Ñ˜s Ö,N ‚Zä@+‚,U$–ž¦ñ9¹œŒß]ˆÏ¯NV-L[«\‡™‚lY/íS ˆßv:ÀéÕ¤ÎSÓ[‚V ¦Õ1ú] O¯Nì矮¥5“¾­rV#Xu¥™š´5¤DÏá@¡:B$ÁnÚ²„ Âäò­U±†È-=Gà ÿ¡mjDòãó‘w’Ý-BÈ@Q¾•µÍ˺kšr‡£½:œ£–2GV½iÕ¤km‰@¾•É¢ÏøV´Èºv¤èNµZÈWÇu” ñ„ƒ©éNï¬óÿN ‡I—â&¬®mÖ›ÎÚx×G‰”½™Ð•fœL§Çáèg}­C½1ˆÕ,œ„,¤3eáB4!¤ø¢Ý?JKâ–o»ê™­Kü¤è $"%)|` À¶Ñõ3ØÇ?÷Ù…0¯¶¥¿åºø´›”6\_«´Íç°ÎVoµ·•SÛùüé¸Ó ¦*›ô¾¿ ¯`[L {¼ÀIUè›_tñQ·¨ ¬/ZR?0…Ófsi£»‹Ïô³öj^·zºdéV‡Ãʉ€IаQkW’TUÎFŽ×G¹V¦ïþ~bWÔ/CD=ð{ì[Oú«‹/Е“QZ̹Ze²8VbÒc0_®dÛt0ù8å¬Bǧ)‹š“ò[M.½ƒ¥ŒÕªƒõÍF„¶Ÿ]ýj´ ]i:z®UÚj£Ò¶œfç#`2=Ôm!±6?)ëNc‡&££y+Ÿ œU’ãIÞ×uøŸ¦Óƒ I±%ÒÉC˜­nëЖ¿BÉî*À›Q þr]޳cQHVÕ­rUWî¨tÞ éG ÃâW‡HÑ3ãXJA‹Q“Ïç—_Q𢶸¶¥ sÝsönx4éªäı 4WœDƒÜ®*Ôeh*[Ž2H3êª ä@¬À ‰o€4m{ tL˜5Tsø¥ØVŽ#¥U¹3"D³E;MšWf…ÊZ®ô q\uxŽ—4os?~9[ÏÎ×— YͨéÌ©‡†JÖ*ʈXë¡PRtd±F(Äç˜Ec™Ü9|%¤£I¿ö Ä$vÓˆîK·Ê58¦®âX!ÆÔ æ¡r¿¦ô•{å ¨Òžƒ¼ûoê ÑW ^iN6—Uo@k~4n–5Œ†ƒ œ G‰Vté¥XFQ«ʲ A…œúá×y`'†_Vç&ÔU Rðøï]/AUè7¬bÍá éÅ´æÔ_ó'v{Ž.±AÊâÇ9UGAGÞ]Ç"¸£8V-)"8iâ!Úpb ¡B¢Bþœh®Oÿ¬m½½ë£Dâ4+ÍçhÒt@ h¦q¬lƒÔòz+3B·Yg• Z¡ásX Ð7»Ã”È"ì‘K9Zkuh[c)w!à)wÎÈDóð‡0š˜¥ØN¿Z_¾|ùø$Ù_ôB¦íõkág0ÿH«:¡¬%>ñz¶ípMbšˆ€i+…‚¬1LQ«-fk r†_¨`)‡¤ Š}ü¨Û‘öá«M_?oŒú}HOÔM§ ç`íáÖYÕ‚­—rMr€³ä‹Ú!MgÔl‹zAäì(:„¶²\~ç@§«S3˜DLýñÝ¿‘•éM£öº¹a´‘²êK³¶m9!Mme Øj|ýp蔸Æ&¸,¡Æ—”¢®‡6ó„ dÔè¥l Lªx%uôtçS~ñî ÖƧïþ½o©êª¢¥×|QEáV4k4ëqOœ§!*…/ÊÐl­ÒÄŒÖùr¯­ Ùâ0¡VÇ¥÷3q>ÐmÌGh{Õç Õ#¨&‡>ÄÉ[×0_”¡…[#CR««)ɨÅk[Ô“!ä²2`Æ/ÚJå›Nc|Á˜E‰{bˆ?òõ|ÐÒQÇh‰ŸSþ² ÈÚÆ,Z‰c°Ó€‰ÈÒØñÃs=ÌD ©­õ2Q9Æ¡"šoex!œ`Ló7Æø:@V.å­hLzmð…Š– ©VN%¨ñŒxd:ðSà¸K”ëω$.úÑ„˜§oCBËg0Iu|ø¶!diZñ÷ØFÓ€¢Ž·NvÔF ˜ð|RŒ£D [E«Û Ñ„ùåÖR)”Dmá²§Ìð‡ —…Ïhþío{ú (φ>Ó‰è׳º EؘB ÞDœÚCk gÂÑ‚OÄVÈ–'?eH3ŠJäÓÑL>&úIî ò1Em“¥mü”1S®[«h±&­¬ßJ‰¾Ñê µ­™E95ÙP•F.a‡€p%ÃKߤåš+ÄÊÓI¶ôXÀ„*‡ ì˜xŽhRÖƒ3=¸ ë°BVœ_~ù%q=3ÌE_tzED{Li✠Y¯­êdÑR¬ R®ôø=”Ò±ÆA®s³eùm­=9ì$m£­ÊR„ð1!˜ á³säÚ²žLê¡A¬¢ÑÆtÕüÆZé­þDOÿ“É}Ë?uõ£ÝÑñùÁš²¹rji=pšÅªÆ¢9ùÒ%Ú–ŽàX¨ aJd¾íU‡)꽸C ¡IÇߤúøÍŸ¯_¿v¿åãÿ²Š>ª×¼•Õª«Ó h•õ|kRQ eBÀ½$Ù"ȵjø:Zw]wo´NšÒ'ÀlqlE½b~<°ú—eí_|qQ‘G“Ê5C_‡š©ŸœÆçc¶æh8"—“o»¹ uM/*·‰ u&×tþø¥(Q•4)¬JµõSåÓ¿Lóã"£¯zúׯº+T²8]DÛªË-YÿðÚ^ÔH¼Ã/B‚¥£qÐØr uÇz¾å(ÙmI°,|¾qš L-A+¾þªàçÐ)dB“ùIUâ:„ˆ¦œ † E9¿mœÐVTˆ,ÿ¬üëë”P¥£µj’#E9QN+rm‹²fÚ¼@vÆo÷-?NíY#T%áør°Ëàô%tâPõ¬lŠÚZ“@fµ‚l+×Ìœ^󀃰årªD°åD±"X™¢|´¥`ÖO¸¢fÁáh,B¥1sÐüºÖ×X»¢8ÿÓ¤ø»~Qà“lÏ¿ø+MU¬ R]¾~øœÝÓUÂìÖSŸ@ÓŸ]E’²®g[Öarš"}QÛn;o:ES+Ýö(p~ògµÕI–H¾'ñß°úömïþ•`¦öl¢„¢ú(TÅ@['ެÿ¦Ë‘…Æo–r›·;G"ÇŒ8rR—_njÊUÚšCÁcA¢”ú‘œæš¤À‡ç Ù&RzµøÓ9‹¼yéÄÔêNS«†P1 ¬¤(¼ö$Ö°éF?ÐQ„4 _Ö|RS£Y]çïè$F«+Q‚‘­«ÂA³J±²úçHÁô8}hßMåÖJGÊ‹7êYù¶ìXÈêÁ8ÝÂՊм–Ðy6‘-˜A¬øVRÝfË–ˆXJÏùp"KRðÞq …¤ð!Ú`Õ½ŠóEBRú‘Î×[Ñ>ÞNSÊÌÛtÿ—D¶>ý¯'ë‹‹Û¯ô m&šßÝÕ8Õ@#D³5SŠÛ¯)ŠZm­ÆÉ©nœV ÖãÔΧ)œÒ«ˆ–¸­?ÍþñÍ®—‰NÈëÿû×D*Öž–4O_u—xƒì¦(ÐZhn`Ûf')=°¥(!ä%[T ¤´²8L”GsvbõšX'¼£úx °”k¿Ã$²S}ÚzEÖa [5ïá°ûŸrG§ùªäXázà´ÚÒ$fë³­Š|LV"Òc00©|ÑóØŽÇ”t%!Îa9æ*<ý?ÜôÎöË M™>Ymh¦[¥àµW?ÚÑÄy8î=çé M{hµÚÝ"*E( ¤)ªND ‡ªÇ™_ú.Ö:­„U.ÆQˆåZÖ˜TõÐr¯\»Ü02ámù©×Jé³2õVØáªB¶™¥SC†ä_ Ü6)¹“E®®U¡¢UÅŒÀ±õ”ýܧ2îÑ/_¾xÙó7ÝHeõÉ×Xƒ 1”gC[·£(C«½!ëS?­)ð€I­íÕBbdKá å[#¨…³SBÐêΑ¨P:MW¹@§ôôÇÔ˜›§o|ò)+ª«á:9‰·Ç_éú¬ášÄ—kµun©a>ŒSz¸[¨h)ÒYx"¶,Zâ|4 ¬§€µ©1)8˜'븵ߺ\~3®>ƒá¿Åô©.Yíñ/’8\ÝuÎa¢æÒaœF˯Iœ@W­é Ùv&ø!¢ Õƒ§n"mÑN)ùÖRÜ¥˜U +GŠoþP[4ǰ¯ŠÖ'>µ«Èÿ³[_'HÙJ¹)ôY§®îÀÑʪ2§ô©ádüh˜¶ñ·BfdÕƒDHÛî(]ÚÂÛV…2„5…íLÍÖÚý“`[}ðã³%)èöÆkÍñf7µéÖ¡æ‰ÊÒ¿žµ­·Z²Î ÂlÕ6ǶÎ9uR” ‚q„œ¼¬høt ¢\ M+¸(P´VIAøE¨°®8ÒÓäsl7BéJ'í5BïB„ÔC²)7…¦¸¶¿reY¥XáLŽŽuœ¢­ æ#×§µƒªr͂Љ%+Z•«`„ˆê5x ¥ß^Û”SÌ)¶ªm&)d{%ðÙÚR ¿Y–t˜’r]{#ß6';{>®·-[Î)s,Ýs¹•æäwpÈRŽÎî ¾˜èãÿÄŸ[}¼áÉÅóoÊ•Øà¶j5 §äìâøœS‡šDØ\ éœS:ZÝr²&J ŸZÕ¥cr:Zbh•öDéB”E„©hëuëÅ_å;¢¯_¿V«†»4ê2¾•U]Ÿu+z´x¾AäãœÜ# ØaJ”q;‰ò™àL¢ó iFw XÎÜV¨([ hV~-‰º§rñK´®ÉÄÛž’·»÷êŸ2ïY\Ük ˆò­uÖ’YR°6r¸CÃÌb ‹C°ÐÎÓàËêÓ—Fbus$–Žïü§¾ÇùòÅý ¿šwÿýƒéÖø~Ò¾Ò^ñu(=qNÛút™cWº;J@ã@˜ÛÖ[œM*b‹S'‘éZ4A KŸŽ5N‚ýÔ9‚¨N&'bXÊøBœB|_ûùø¥×Ô'Ü~LÚ™,åŧV:>¼t éGuÏ!µ¤3usm#àØ²ÆáPhœ eLj¶8VR²J*7) ‡á3¡Ö*mø€öáG# û›?£I|ýãïþÕbz8û½½ê¢ÖCŸ¶ê°DˆÇ‘\+«-äë¼¶®ïU\ú¬ëb[zUß+ãë†q«TT]&™£±×YtJÿj¿–4Ï({Vï¥oœ]îøV´5ßt&ˆ`|ø‡ ð Y›1©­ËB8²”@C¶u8V|||ê›Úï8~#ç‹Ê.#e(c,E•Æt,@[>‚fø1·®+š-‡líj Z+áÉß±÷KÚ iC9~…¨á ‡{öî…ƒ?q‚»ë|EkƒAÊVÖÖ’"¤0>§fl9L!ÆñZ‰04é@Ž•ìQøò°>9‡ô95ÍÉJ”Â!8Ƕ‰T´­JY¥$®Y4?‚m}r7rœÅ?ÔUò°Q£GU>¡¤{ á(MÈyU ™‚,Q{·oR¢œ+Î.<œ2>[Ñžýë?ý:ɇ3HóIðqš—ƒ@ U®¨×³×_¢èû)Â=ýz€¨Òª¢NøŒãÐpBp²¢Ò‹µ­fg´%Õ©Új q"ÏR 91éÀuÂÉ·J齯mGWŠwÿ¾wQWÏ­>„èc¼”'ÒµÖZ#¨«ŸÆ)ÑÐ 0>D:GÛ˜ù)8ÆõßD”•@ëÙD[ e„¶rK¡ÆlrmKò·æý­• ‹Y'*²?’û[šßÄiÒ·jÒŒmõ¯zåà9Kª¥Vd¡º…pl²8!Àpˆ*‹§Zª tQ8p÷²»-mÇá;áNC¨Š9*Šz¨Ê…_mß9ÁA®C:¯´W|²Ä5¦ãTˆ_ÏkÕÖ]gÅA^׉´/´n4­d¥”U]¡¶×ô“r,© 1 ¸ö€Î„u&ø9ôÛ¦ÃgWN#‹bzIöO/\ë³Ô¯‹çvŸý«+÷Wôô />»jÆû]b=¢ÕÒ‰Y²Þø†ÆGãDVÎ×Z~sQ@»æŠž©Ç3†1mwü&Âwªr Ñç„™ñû%r¼ÿûúõ+'‚5åªÛvÉ®)Ïùtñô; {t F¿IN/ BDt<•n7PVâuÉR{h3‘8¢œ­o¥ äˆZó­~ˆzî¶é±IJ.ø†jL BV`C©UÂDwA…0­uîˆètbù¢¶Ñ¦ÖDBŒ&N ÕâWȶçàÓ<Û9D(%Ùâ¢ZbÈp eqhò–‚U.¤êê6¦\¡SîHA Ž( 'Ù:À#ἚU¤Œ™ t憙H³ Õyâ5 ODˆOV4ÁÑÞÞTÂಚ·t«Š_t‡–¸Ûæø°¤+!FÂV b[ë$”L%¹ÚµêL©ã¤k­6‡`>Nµ0á*ÚÖšf"ÈÖ0jA¬5låŠ&ZÑñÛ¢ù]ö‹¯O•°êß»dÿ0‹8Ós}Öžþ!õl4÷î¶…Ð š_·püN´²øìaÒê®tWЬC–ÎQW:‚DœZ%DÑà˜œ¶È8~rsPÀ§Í‡½hQ ©DUä+¢\ÙjŒi hE®½®t˜þ™C«á²(@d!,‘“`…dyl'ˆd»d˜Ò©ÙòÑ€Ú¨Ÿ®Pi:'?f¶†¤Œøú'‚×*|^kÍh›ßh*òU´­Im@²¢Ú ¼†®éë<åàÃã'B§Ó†#£q„r’U_”o‰.(_ÿûæŸ÷í|ßoI„ ” Èñƒfñ‡t¢%úø¾V\ˆñ;|ŽY Õ†lk¬3á“•ÒQ ì@Êm ¾èu­:ÕÀ7ßýÿôÓO}X@§¯ˆOs»^F¨[ ïXtÕ¼&µm̤CÐv£Ù"ØZ›ëJ¦-Yþ•–”‹Ö©â@|öÿ0¬Ç‘‡j5©˜“åäÃ_4_T¨Z¤´jÆ>G¤O Ÿ)c„ƱX?)Œä·Ž–“šµ[‡Â˜†¹hYÖΡÕ1zk±Ðw<^8úVµŒ©~ë¤ šZMlõØ—â¬h9¢Ò{¶OÎÁi›h­¢×…îL…æ…–ÅW×¶Ò¢ó½p»—à¤[ù¬*¶˜ÖR ":diÓ-Q'ȬÌÈbŠ2Ê8UÁÔ-“N¶Æ —…V:ŸáXœ[9áBŒ8R¶BÔEàÃÓ‚ki|2°Dü¢ðmeÙ"”«ç4­·GªX$<[Ã$d+¡¾œ:«WkLxg-—/WÊtJÔKR9 hüL´a¤ç`²²™m5YMxjß^0Í/¯j!oYýò×Ë•©µQu²ZU‹Ó¶ˆµÙáÝÙ(Ê752‚3Éj+ÄðK‘ × ý1ñ „H¹ó䬮Pjøl>y…ºO™·>õ!®Ò¯[%ôÉhó5lØ8NQk-u&ñhòeE¦/Ý–ñKbÓgÊÁùV>2ŽmÌR¨ÙÖ¤fêÇZ.ãC$VÈ·æ[oKSHç²J±}¯U±¢•ã×'§¡TÂÚB˜,k­Z#@8B¦rl¶Ä»»€ Ø5*1¸E9Þ$Áe¥ÀO¿D¾/¿öI òÌû¯º\äø”u2æëŽ*ësMšH]âfkvf![‰«~²ŽÒ%@+£gdv ÁñÃËR±{Û°B)¬ù¨q BГµcÁ‘nHMVÈ I™”­¨­w·oæªèͨì‰ÛzÅÏl5ÀîK ‰[ ÛÇÿýöØscs­gD‡M­y&Ѫzç'$²†9p†³,xR‹Â¯†¬+ju†¢îχºµêÝ?j­ž¸ø¿=uÿŸ¾‹èÛnªÓ´vò²êy3šX«V82?r÷-ÜÖ ñÆÒO¤Ärǧ`F eà "×ïÃnd¯uX?é—XÖ™àŽïÿÈ¢¦I+ñ|Ža­ð|[Íôƒ¥IYáá4±¦¼VñCº|CˆïVV7fÑ“{\[âêZ¯Ï{ßüÁ[¡ß·œZFÓ¨Y… +T@NÍÔ<G.«·•[–µ¹ˆ°1Ûb¦™NRV \%¬8Døð¶V:ÌéÑY«e=ôަVã/—NYjÕŒN†lu'‡à Ͷ'I>²»‚#JV|éLÈnŠÄ§ÉªÎ©”œBü¬­ºL  ¢&!["ª`rjIH]è"µ‡ÉGh›Z%øDTe³ïÑ.Î'Z+;žUþŒn¶(fü8pkGCÍáò_¨´UËV.„Si"rùÖU‚oE“ØÀE!³@[ÏÚßâèÍïé¼(Rãk žÏ^Ž#®%Ñæm cBêj³¸„.ÃN_.…]]üô+ÑÚÉŠv°t r?! Y—ÜVÅŽ™š—+§”ŸøgWÿö¨Ïþ Wõà×såê¤BcÖy[~¡9‡Öi©E&B-œ³Bm­úa¦ÎÇì„ùÀå¶•›‚m…p‘m—¸BFª®¬É)óåMê]+ý¨híYág;ÇÄøÑªÛÖÚ™¡áD³Ú¦¹{’/dí‚*ÅMU(„étÚnKG±6®>ò7?û÷;%_þ)Ç=¬b·ºZœ‡÷1Ÿ^•èbQèlMaË1…Ñà­‘ '§5äB‹æPØh"¦Š5¾¨¬‰·-MÈ!"±&ži­NÉʤå;+)Y@)¯‘À^b¿yþ8>ø÷9«*t0«E$…úyñ·[>Oi%zW§+£©Å„Tg“cm®¢õ3‚hçcj¡::‚h+ÑøUIP“õb ì~ûᇠ¢3ïÑŽ\dR q^</.µMŠ~WY«¶lÃ*WÏ!ìéýÒáz£#”œ_:§qB„€ n['I}ùòåá@`÷'h\ '`­ùkV¹ô7äió‰>qRgü®#Ç!XYj˜#Š6DT'lG!T39 »öl¥Ør-ÄJ–puÇ\–ÄúQqš[ÿ¯¡ðJø-¿oåI\3DQf ÑuruFàH—È4ÏW®¨UJ&Ú=ÐÉ9[…‚”˜‚3!” áã¸1d©‡Œiˤ‚7AéRö2ŠlM ™ñ[‹"H´zIJº&q”°å0ä*¥OMèÐ=Aä;¹Ì–Å4Î4—;')[Yù9GçtV%Nà˜%³åÀõ–ßZ´¡ô@m¹œR8» õq øÎqÌ~“$mUIHNµm9‘ㄨÑV¨5>œÍ*¥³sd¢:L)¥Œg‰spÒolÛ@ކYœç¾T'÷÷­×<}ª«V slY³Pà ±º2iÛô9A°åK”ÂBgº &Ôó©P V–ˆ•²[¡tO‹B~d”.Ôo%zN‡×¤õ¹gŸJ+á-‚×ì³ÛcµÐÚ«ô@} ™¨¡j'¾5¿­(šÜÖ>N’`·Ä5¥¬ŽE9}'l;rHÊ«+‘³ð‰A¬ù.ã[ëížýžÿª^VÖ8êrºjXSÉõ_Ÿ@÷F¾è©ñëc'òR¤‘Ë’Ò\¶Ìªt mCž‘ci»NÐݺ>ýzø(Ù”~­än)ß­kõ#½Du­Ô ^_+A–ñM¾*'v\\æ„«.j[ÈzÛ‰]›œÉiÝéÁÉN¤+ˆæp¬BÖé— aG”cͧìâò‘á|š ¢·I9vÿîð›ÿ>ª·uHŽD •©Ö‹Ÿv÷ñMö2_ µjµCP+§¨-ëœå2Ûîg Ǻ#Õ¼_rÆ!Ëé@àm;¥§ð¯Ï >>üxöî¿cá8(f+½OÓybõ«T:¬ëÞ v³ÕbÚ¦ÌTÂ×CQ¾{²y¤Ýo•¦¶ÝÕ,”~LJŒÖÁšÎ7°î–þöƒ,=èÖÅ¢Y:¦ kE½dÔö++)¦âŠšW]U4¬4ñ$„_Ó Ñmd>A+«Õü­¢pÛh²ˆ¨huÚôEõÀ±- 'rëÒ¥d>}{8Ì•û§§Gâݤ(Û:Š+St'°¶'+KTÿºµÂ9@Yr×9?ýCñį h²ª{B³3‘ŽæÑíæÙá¤VW Ò¹!oë<ÉžñcA°eÈõ\‰ ¡)«UŠPíY»Ö•`ùõCõ ã PBñ2Ê@!:x² h•h-¥-<Á@ÂÇ‘Ò62Níåïãñ5Y „4OÊq>²p´Ä¶màñ“+³ïÉ·^ ¤38u«mrü:ȉV/…VQ[ ¹<øÈö¸í€ÈÕrX"M%qçãIyøÊ&æ[¬†IÕ†«G[w@IDATZz¶:INkÙrZ‹‹o:Æ¡ ‹ï< h8³•eµÅ‘ØÃB(Wb–>¿ŠÈRO_ÔõíQ!4æÇ×6)Ð\š¯_¿ö7u%ëÖнˆBÙ¢¶5`•¥¥fì@D1k˜BIAí:·ÎjCu­‰ÎDdåŠZª‚F9©V}RG§Aâà4©óDÂù:,tË|ÓTÔ€ŠVµ Q‹Ïj¯>« á@¬²ôÖ%ËÊ'GV"ÈÆ‘Þ6ǺӣãÞ°¥Ï:p"9Òm{31üÔ>/o}óG³Æ<@TtCRP”¿¬Ž‹fµ­¶@9=G)ZݘšDÀ·µÆÌ_KÛš¿þEm­Ò™éüô.Úç 8LTn' Ä0«´êͺ—.¾DäJÛò÷$OÖwïääòìçŸö¥||Qz •Ãç@8L¢‹øþÇ·zv­épÒÔ§Òö”?Þ]U½ÈÁQ‚Ã4³>áª>;ؘÖLˆ ñ¢ÖŒAQk%ò]ˆ/_¾@®ù…g?´”¥Q¾²_ù‰È=à@èt¶d+A¹Ê…T®Þ fà`æÄäç4ˆ-2Z̤"ðÙfAЀ¬ Çéù Q¶ü™ñ€êÑè;aQý»Ÿ94#Ÿ5kÇ yeU…Ž–ˆ(‘f¥Ãõc#0ˆ-BÏx¶Ze@>‡Qk‚~¡“r{>DHŠ&š,[„ŽBB¹ÖœLñéÛïþûùSz:*rLª.¿¢š¯äj˜mãÇäo^ÑB­‰§_.¼Ž·sÀ‘%ÊŠr¦ äùGJuᲄ8Ѥ3H —u•ÑŠrlé´Újc’døp¹Ý*ø®¼N®þholJrk^W­‰‹ÂצB5†9Y¿m!Û ¹^¸0\.f: ¢b!>ÍÂñ;½C•oÀãG4a VT ô˜A:eoK„$4‡,`…0ˆkœc•;AÅÔòŒ€#$+$LNÓ–’&3ÑæLYÃ!ãÀ á³ïô¨D­z€\;шh‡,êpLÍ4ïÎkœ1šHb§Š .%šPu%ò+ñ¢ìSy D"®&³D+æsŸ=Oß»²|úÔYÛªp4 4Q¥{–„Û e|¦ Õrë6éÝŸM¤i¥–`E©œ¡[‹.Ë–¡¥F|ÝVÈy Y|HVÏü)üÈòu¥!oÅ*„lk̛ʛþS¹Zås”vV9šé$9Úæ—Ò ‡éЙ”Km=F°Šb’†€—Â*aËàêæ£º:BI}ó ¨7@¾ØŠÀHe¥ð+×ÉóûÊøº}ÅQÂtÈZ½0×¼‘+­‡š)jÕÌür#XúAK_(f…ó…ûÞªN²>ã À¥§y?ǹŠðSã¸?~”ßW«1å¡SøX ª+W3Bo´Ä ñdæXvDx½…óq€Bµ)wä¶qUb)|¹Ç‘VÔ–oÒd…Ð…%rØàäÇ¢pRŽëEÐhNþ›ÏÿýïýâÅP¥à“*Wi=\ ‘‚¸ŽÈ¢O˜BžI$ºQuÅ¡oX«æ“ÕÃ&²ª«1Ž)$òI5µD¡N‰&Ÿé³Î4ÏA  bÌJóýãrà’3CöQwßÎÖ^—&5U8LËú”C­ÒuK͈U{jÑäÓj« åúß š ¯d ãÔ‰Pˆ-°Ü²*WG Qk¹Äë‰LÊÝâžA–âç@|–D®æ¥×g­5`ºW~R¢£}âJЄ45„U·æh©ê¥¸Ü{޽ €áÈÄÛ†Pc|k ÓÈø5€`k ¡¬"³-ת«wÿO|@ÙÏŸ/ñš¬ôF¶UNgË·EEx=ÌÔHTk õY«!²Jl´…$v€V!¸˜Ý®+øå¦/êrX¯MVѪkEU‘bÛZ«Bmát: `¹BɆÛ²Ö[kQ~Í™Œ\Ý)三œ³>¸DÕY‰d¥ 3Y”…øVL ¢  )›¨ƒ*T B ´F„CøëÙ}Þ± ÕxÜšM‘#¡>ÊœJ…cR¯Q¨X¦ÜzJVºËÑ=„Õ™,¿nÈ2ˆí.ž(AéD"ÔŒrLÔZõms ñó=¬fj²öøÍhËgÚ³6uׯƒj¨^öÌ ¤†¦O¹ Õ%ß‘q$ºuH¡%ÛhB¬8p t äslåúdË?ázúpü… ¯RÔô@™£+NÕm9]J>kð:±2‰RXÑ£aGap |š§aáÒ+T•‡MâgÙce†éUᲦɯ瘲…f‡Ü‰œ’Çb;MbHÊúß‹“)]ÊëN÷’¢M¡㓵ºµœA:ÌUÜŒMÝ+·¬È#×¹µ“'k®® Pp&×–Õ†­ó´î”àhûñÍD½y?áamX¥´%ΰ&Ò³о¾öópçI£ 3ˆM É€zÓN •ÆáõdíL„j»D8“Dà/o.ÛJ7f"V ¸]2¾*˜µ‘ˆ5òqXg“=Ê|ðÿ[ÙÇŠÚÔ4PÛ4Yéi9•Ó[ΫödÑwòÞZ½ëÁ¢„N„´S]¼BBÛN»6ºXEJ±)JÞ)5_iëÙ3þº”è?þØGÎD:|šÖªÔ!¿Óãøx·ŠæˆéÄ: [Lé¶|Õk 0A¸(ŸrEÃ_Y»¾ ¾q”îLDk #µõ“š_pqôéÒs$0ßøižÁã½l­rÎùŽ«Ãl™ärš1Gu ,´¦†pü(õpžÿóèøùÓ/ˆt¥ÄQòþ¶8e +­½JC$²BmñK—’‰“”Ëz&Y¯Ã1%Blq´„¿‡¼­¨N*él¥”îÁˆÃ’ª„è¶B®Ä@Á3ãvÚ¶ÈÖdC8eÁ9ªG ·²¤jbu?ÔÏI¹=¦jƒ)¾Ÿ2¾£†CX!N´›Ý,B¶ óx‘>ÿÈéðznEˆ¶ŠéÛ†Ûf:© ¡†âäÃ9­.Ǽ²”ÈŽ÷ Êw|gÖíõ ¢ 9liÌ–ŸÜ•_õ„fË/=Á.!Ж ­gR}ØzjXJŸ| xˆº•ên¾––¢–pŽæîsrêç{¯UÔRs)§%SCt»6r¬æÕm[Nèºál…HE œMjÄmESà&Td)œV¹]oœÚóîß7ªþÙ#"âƒù”˜HY{1jNWGˆ©ÎôÆj¸¨-|“Ê…'ÕÍŸš­q§iØ”€ð9Ÿ³£‰“SÛDó+мFã·"‹²eÝ…ÿMÉak@Hϵ-÷šòº¯M [ùNƒ£*Òo!ÆGàˆFƒèÓÊxMv·¡ö09Vˆô8øRMZ!u9­p†PÈšŸã•ïá£D8sky÷¿Üôm‹¶MÇÊ*aU´ê1Ÿ^ÍE­‘9΄od¯RfU4qQ¦(Pu´rEqø~‚¹‡!rüÚ¦9¾í|Ž­\¶k¬⢫5NЖ!Ë…˜ÅóÌÇ?eƒÀ¼ùö£5†XW¶,ŸŸ ­Õ˜¯|ÿÇ¿v¥ Ojë–ãÁqYù*⨘ÕÐEq€Æ²BºdÖÈ…–ˆÀï'.5dµ68åÿg+Qïþ%ŠÒìà©Û–`÷N¦—­úüìêíMYÚ£\ÿ|fX[%lqbrêa¶û0^ dd¡ rùÒ?#Çq2ø­ßTq ¾'¦%GÊÜ9´•åéÚÿ¾CÇŠ|vw»— ðAøYKsÊ·ñî(-4H§—ƒcÒ®W]Ùš”iž!ȧ jÕ­mW‚ƒÀ8ÀÚ¾n;‰hýçÞýÿãÿp1¬•2Ó qVpŽÜP&-І/c6H ,ˆäÖjjÖŽ7ë¶À§&ÈסŠR¨AÒ_ \J²©MÊž"¥š…ro j a'`»ÒøpßUEJS·V(…ú´VÑšÏÉGžŸ³ ÍAŽ?ZYºr,Êi^ÈQðU”Âp´ç¹‚`í} '½¢4'±mÌ£Øý)‚PЇ‡ˆ*À!@|+ÄŠ‚ŒpÜß:+M d¢¤«E´ò#—ÅGã·µjE»Z´.ÓGf)ä×72°÷ý© ÉJ--A:ºÍ œJX™-Bþ÷X=h’²ƒúØ’‰œlukڛŶDgËÙöÆ»7/êXŒcö!Ìö¸xg¨ChkU}-©U3® ÐÃÀ³Ï¤üƒ«‘½E³*Q A¥[i­ŽEQVˆѪ(&hËÞéÿsw³$IVdy\F‘Ù²`õzlxV6UPU ‹yˆžŸÙß㔵{d”GdNwëâ¢WõèÑ»fþž/$‘†×aБý‚Áðî´¨ËÊ•(–ž½:yñSXÊȋܖˆ%Õ€ ž±¨×íì\ìHXÄRðÌÈ•®/ÊW”5UvÛ+ù¶Õ\³Ê³m2ªMŒ´–’ΉPU9°ù ëYC‡“EˆUøì¶`Õ@Ç`åzü*‘‘øÓv¿¡W0¥Ã}^k[®’ÖB´û…¿%(…U 5ײDÚ$0õ˜eWŒ‘¨‡PêšË……QH„túOýܽ©]UÞXøÖ¹ôÆ(…Ul<­hóìóá^~Fˆ§Ã飾¿³Åÿô´Fj–WU¢GKy¶­–ÍDËÚiÛŠÄ`EI€NñØñfw͖ȧŸŽ®Tñ„HºÝøÖb߻ʥ’Žò8‘”îÊÆlF`e06¢†Vk¯[ü\¹ P²ŒÓ™ñ'£ÚœQ‘¾’ká*€”B ”êɃG–¥ðú5Ú)8å:Ë?NcMÉ›>NÛå¢$H!á)MB ¤HQ®±È´…L€Y¸¬& œÂåoïïýå£/GbhŒåjÅYÛ–RFÙ‹íš*Ö–·£ãÜbÂ-cœc.K˜¶±µ>d20E^ÌV°¥´² ¡o Ó‰b§»y58 ½^4+:)—ðå-5—Àž¼`Õσ•½ÔŒaÀ&À¼\„q+¥Ñ™íYÅí.Ìð0 XY<=Né8|`KÊ-/#9ÇK¶.eéò.µÀJMr4Ô ZM¶ïùäc´%r;1qqI×êÞ\À„Gè©*Ķ¢±eHÅRZmц"é‰úé>´e¬%!,åº2BVçÕþu·¥,½¬JDWU{k.QF«‚y]•kvmÚÖ ~Å’ª[CkæÀÙÁ€½^z§BØI“©k«ŒÁ¸©×x?l]Šw)þÏý迨²(Fa*T ]®t°®l– “CT,¢XèV[ }„á*„€Â^öY2BbM§À¤GnÛX„È@¸`‚ÙRx'¼Œ¶Ÿs¹^W]HJ¡§¥7:ãüBek§·õ‚–+rJóqT”´{“×ê±–C*&WvH ±YñØv)¥ƒ)BX¸XðxIYôŠòÇôV@ IQyg9éWK´¤Â”ÄþUDž{¨Ô¬Z£ WE ’ÚZm5¸ÉPØÕ†A`%i ¸Aaƒe…Ç6ªÂÁÖTýÚ’Ŧ0œ OX\²Àá<{ý¿ |îÿE›ÿú׿°õî?ž°UO[Ù+¦šy —mZ³¼kè>f…“®Z•hÁ–ÒØT§Ñ ¦Œ†`Î¼é  p1ªŠ‚D1VÛöUÈy Ö_þò—þQæ)~¡Ô»ÿšE¨B.÷2‹¨$»ìޱ,%½£úÙ­®û |Ç›úG›2Q˜b¸šŒtªb³.Ä–ðf±Ú ”=K.Fyüÿ†óYÑ»Þ.+bŒµÆHl ª]Íh¥`YRU±XÕ™ý«fE) Z„±¡e§+)Ú³ºÛÍ«[^0RX˜ÆiENºµ7áðJa°Š-Ü(¥ <þ´lŸS¼ò‰®•Ø®…ôaöÈ.»ùèÂV EýõX‰š‰-O–¶ë±mÖ•A¯M BÈ«ÄÀRTñL§$ìt«2v èY2ZC®GFRH ®€±TÅýke4Æ,À±±P:Àt‚…èkáµÉÎXå‘Àó¢]ÚF•½@.F`G‹xÿÜW*¼Áô¢ZWÍJ²[‰ÀÂé †§4‡ºæmìJ²°,h7볦[QiL¼1±dÄØJ'V`)mÅÂBè„ËóÑ£mÕ Œ™‘îE«Ááak¸)‰b©<øW%°ð¨^Å|‰Q^>Õ ÛÕ”‹dËEš;’¥ ™4[ K}b­N)ô޹±p\ØÉðSô²ã|ü7mÑþìª0ïÏÜ0²¨p!òVþ Pá Œå¬ñ( 9°ˆ".z×4~+Ke× #’4NS5fB_ ,H(BÅ10‚G%„1«-ÑK„¥`ÄÃîââ|¯x³Û=X﵃¹ªf"±e'`òRĪ9< 0— X³3Ò…ØÂPXˆ-ÒMáñ诣ٷútÔÿ!—•Â@„XûÜÒ¶‹"Q@šüHžWü\ NBI„S>G2¤ÔFÔ¶¾j¶ÀZVª&Io+„×JÃÐÝ­_T{ëï빤ØQÄÓL*•K8K·,éBäâZ"`o >ü¤xº¾¨j³bÔ°Û!{}Ñ)„c…·Êö˜Ë˛඼0ŒFÆØíV#¶xØÇi›…ñ$;þz/ÖêñŸå}uëîW‘ÃD^‘ñ¯÷a(Êc¯òÕ£HzÀÐIQ\ج$—ÖH–/$d˜éWÌôIÁ>]‘\f‰UZF!ÀŒ¢è¢¸ˆ£µ $± `ËNï Ú"ð£ìH³77Hwº@Ö£¯6ó 'Âc(5Z[º¾fÃ× r¯ƒªuSPBrÐKZ  °m^°8/‹t„ý„G!ìȳkð °(>]MŒ KìˆlÃ[S¶Ê¤_2ñÊmË‹¼~JÁ¥‡tÌÁ`"„¬0Å"Oð®ømaz‘ÈøW·¥"›»\ÄV1Ueëžw9W¤)¨Û­UÁ³ðzÂ÷ÌBUåAEe¢l½H]vøM€%ÀÇþcÃx¼¯òþ ‰ì±•š…—Ѫ€Š\ê °€TsH+#alz×Fá0­‚ÝÖ]ŠŠ ÏÑíÙÝumÀ] Äw¨*ƒ=å¨à¬A,KwB.–kñÂy¹–Z mŠíB(+ m— ¬+è#,ü«¬j¿Dt‚V§e¤k_ñ¼jsœÂ7ÒìŒ0,ÕOÉ8¼â )V 0!a‚Ù’hÙ+Ã?:÷Ý?ý®e„ß}÷|!bmÑf¡£¥³`.º «„ æj»ãÿØÖ“ªQy%-/6©e$YV˜Ì€½¤ªÝÓLTFÞs<·ç8#*^á¹RlÙ¯lt0Þt°RxΌģ¿cÏè»ÆÏýóJß0ùE¨ÆXF!ÕÓ%`P‰\¤¸Ò•qšÊ)¶ïïw…%bdT<£«‰Óéu*‹ìá{'ÕÃnaH+£ÀUVںи_etùÖ‚(ÿµÀ*ü¢ªÊŠÀ',}6ÕóJ?ˆÂ&¤'BR©j`·íB0Öæ`)ÆÂ¥lÆÊCgÆ 3/˜èâZ9˜3㯗¼®‹ËÄ[…·ÂX) ÕYñVR ÙK„ÊçÀ/ù NÅ`ÖKœkD ŒÚ”‘«ìÊ£ºY)Ò–ÎR/J¥·µžµKc§ lÈ#Xl ŒÀFìx7ÒŸ[ÝÞý{ã 2F^^õÊ€LX2ò²´­…;òBlcާ@º1 †ÂÈb%Û¦d|\y ‰Êj,VÂ%—Ô¢ÔVlv:…+Ì~É+$¯òº|ÕÀ¦ÔÖ}aá0w#Ô2£ÓHw`fqYb íHÿr?R ­¥°Û†PLMÑÕ9%°5Ý*‘+®µáQ^OB.±Ñv:) ›\b pY¹€³kÎØ–~{ç*’/+7Q®•±®JÉ2…X0{&¨C[0:E:rL ïšÑ%%áBRºWcl,lÞÂfùŠ«¤¾ QLµunU»ì¶.dHé4(ŒË:Å%Д0zyvÕ]{!êïå¼yÚ[kÀUÂE9xO{•Húø4Ïõ³«¿<ú¾§¼ HYñ²0ZÀh]û˜Ù¯[ ƒ¹âµ¦_’ž€…” ¦Á 4^u¢«Y+€m…ÙRŒ›¨UxÒÿtr¸À¬‘§Àd œaQeAÆ®<+pÅL£[Á¸ê1 °wß5X¤(¶^¤KÍu¡†¦aÛYâª~Œb«\azD¢`F^Òl»`YD!)ÝRçµ.5£ïV_ýn^:YNHÏ*Á‰+¯DÒqÙÒ Ÿ®£:Õ£»¦Ê+éÃ+†:jJV«¡:gon¶N©õ¨ûå–é´GUNÕÒ[!„г´–â®e€Õ8]8<xŸö œñ.ªü ¥›ÚVm¢°Ñ I ¶¹x‰±””—‹À³?&úY‹ T-’3Û1„ʰ•sÛ.t[Q¼!,/Å1ÀÃn­Ñb¨H¹*þ®e_rûª;òÕì õÞ«f1‘( $#ÝjKi\N D£z^ÁïU¿Ö⌶~›3{®¶Àá»ú†@‘]%b›!qQ¶‰rP)pvïÅ?«{…òOtz÷_ËõØ1¦KMGX®0%©Zü¶ë2°Óøá¦Ö&6ÌÖ.URÅHÊ^HF’²~Ï*Ž{çêÞ*¬6mëåp¿@ÖÀe1R·ä»Mfâ>ÕHÜ)ñ[S .*Œ°_HÆêᢈ¢dßA]Æú²ÒÁ̇wÂ~MT%%Ý P.Q+ÌšWüV¹Ã>Låb¿Ö¿ÂÁ l›%Âk fEJ PêªrȹÜŠÈåIJPokÌVxÛ¢ZK!*Å: ‰¸^â«Hlêç³jG²;3B޼ìUÂ(ä*ã¬kÃEà+†Â%PwGÛÝŸö®ý°žï!T“Mj†RâH[Oÿ±p%tx^«Þc¶­tŠtÅÂÛ‚¹Ë‹äjG/ÄV ÂPádפ5Ô–}¿©zñÑÿÊûý÷ßË‹¿‚)D¢ziÜ,¶Ú¡˜¡·;Ú_bå©_ñ¾¨3mÏVl]4|¯I¼’b`·b ÌBÉÆU"Tÿ¦m5¼¡(ÆßcguFN¯6 ]ÞFm]1\Õ`¢0vÒ¡ÊX.ýFÎ^/¹”ÄÒ …3B²t¢„WϵmõlÛð¤ä-#6öЉ\Þk`Ì0WàAbÛÓßEdñ:Z®¯²úær/Ì2®‰ªª"Ù{ÜkÄÄ +[yÕÉî¬GBkžÅê­­5e:W!”=Êé>|úBìNü²b¿$(DÞÆ‹Ù•…·%<l$å²¥¬~·ù»^eÇö¨¨Ù“г×Û¢ž«Q KåW•W¼Ñ9±êQ]¼M†‚„ˆ¶­ H {ͲXÙ%¢•J//‹Ôr!÷ƒ_ýêW0äùk^ÅÈÒÜxOâƒ-¥lñÔoy­,¼reÇæØ,ÅóŠC»±à$¨4‚ÍÐÌ]:ÞìŒU.$˜z(Mr.^Hö-„ôÈ1÷I)}«Â¼÷’ø(ë,Lïéjæ ÌÒd(1ªPTÆ>©8½w¶Ú‘qY´Ð%ÀÉXÞE |“ Ã%áeéíÎÆ¥~±>7’»‚‡˜DãAØ4LÕ“Ù¶³Ñ‘àªé²tâÆcÚ¨Óƒý.õ3[)À†îÛˆð»êQpÞͧâëZ¸-¡(Æ*Öš\-t"Š‹b-ê=ÿ?±ªÄ-éßQ<®!W] ïÝü¾€¢ Y®ÅЄ¥°­¤’²Â3ò,†ÀH§pQà)·R†É Œí >óš* ]8ÅZ¢ÈÓ…䵦°d„‰Ê!1%^–¼Ö­0JסR€\ÄÅÍB_ ë¨À+O^´=OJ×ô°•º¿r¡íUÛ}]Á²0¦ÃHQ+ ‰­¾re¯Œ}9cتD"eˆeÔ‘ްÓÁj30;˜t¶¤áZ“"Îì¢Øá)xÎŽ‘ÚZoÿI~Dbø²Úò±¨æä¿%p»"bƒAgUŸ›œNØãa'tx+{e™©;ß”y¥ ظÄv ŠbEÊžÞšK ¨¼1óf©.Åû#À—ü‘áí?Îÿë–RèEw]ìêáR†^<Ôš@H=y‹Íè4S…nbÀ=Ñxk­@vRãì)Öé¼Þ ø¾Å/ƒ‰D» .‡ôȘÈeËNt­Z9ª«|m³ÓIb芅4=^.0g@{Y̤!›g€†À®€¢ó¸ZK„ŠWü½ÍNY‘tRyáš­# QCF^1e·­²ÙI±R+€ é±R;Ý¢‹ú°¢Ô²[eQ*Š-ý¬ý¸õlÍ ˜Ë(”gÈu @(ð =Î*<Çs™R²7·\t>_mÓgKŸ‡ …cöHQX)²ðªS=Œ,Í¿òX(U¨Þ²û¼ú¹íóókJd_Æ’V¡µšÀ PÍg£w6`ê´ru×T < ªÇÏÒKLxá¥.†½¦‚ýç•^ý¬ƒÁ[o1"O´xXâ”TŠe©¶R¸"ð.ĺÎÛ6ªçWo+U%©ìUU^k·ǃ«ÉÈÛ@x›çÚÒÝ €“²JêΕ@5³_ü?¾(xîõ“k„Õ§¤‰AÕ56¹x ½ÔŒ™¾ìÏ+®N`lâ‘g)0ŸÙަ˜ 8š9O‚ð®EÞ‘°ÓÅFc‹„?¯CÙÿá#$˜ÕC¸X[4OŠp"”Bv †Øªß C`ˆ\ô`é~ûäk'äÝ‹{§¨”á‹­ëeµed!õ+$)™:«ê(îåý/½ò‚…ϸ•±Þ!‹mÂõê¿¢ŽíÕÕ0üñG•#©€¥f‘ÈV#VÓ«‹ÏØñ£‡·ÚVyv+AÅØõªòÖha¤(к‹-)€­z„PÀÈ•Á–}Ìô¡À3âÀÔšz€«­5æ+C©y#Ùg Æ‹6®jã"\E ]‡‡]/¢¸R»Hl½T0ïj¦ä¢°#!ÆZ¸Ž†à pFÜ.7€½d×cyCŽsÈÀ•±•2f' !ÝMa{Öräb¹}“ÚŒ®ùX AщQ 4FØ+¢1E cpQÁD[>¦ûÚ»q[³„ô’YF[)pF²Š)ŠÁIÄΟ’o Þxu|1ü}ðµ¥.z¬ íSTØVºÕ¬ ƒ )¥jax §Â€7%H!EIá9ÛË¿@ü`Ql뎒ÎÆ(äÕ—·o¬æé—¯^ŠP%$]Pä=ýÁÊÒ €­ŒÑ² ¬°&ÃÞºÊÛbÞôÀ*^,»-EHÅ £-#i’V)c ’”8¥“”Ëv0!${[ÂB†dq™¬«VÔ{¹ÀÂch22*Õ5µÒ 07¤¦\Ü“ãK—‰ù(Ca•Ýå`‘‘¨¼NÙméDUJZÕo»»[0‹(´Øè[YHl„¼Œ¨üèßû‰Êàšðú%±ã'þ•”2µQPYk€N`XKó<:¾GìŽ[º+ÞIcVmÌy·=«8'˺†dW•¤ 3=mÚª*=/Z+¤($åBØJßµèBÌ I؉[Ò/Ê¼Õø\³þØâ}måÁ ½CÆ Ð„)Ê£$ –Td­QX¢‚¹#|fëžêIh€P%heOtÇh•Ž¥lé`${UÙ£²]It¢~“ŒßöÕ‘ÂÞ¯\‚É*¢kÂbÍB¯Ûì¶ÕóÌî0¦±¤Š1–2¢U¼–Ûš›,¶’T¡2DÙ¢ªe:#iV¶x"t~ª¹ÓînvUw«Æ ‹¬ ÇÞTqR#;Z0Ù!% #¤ãš·âÁDÑy½°ÚÞ°JÞV¼Éƒ\ H*تN´Œ*±* ÌZ^zx¤,¼±Q¦çj|à`WÎ^ýgåWäî&õÿí`öôR mÍ9oƶ\Š_©¶„«Â²[³¨ÒˆP^ºBl“ŠŒ¡ìŒ’=dœÖ¶+°pepèê¸RVÂÎèEîɾJl©»äb´Â0¦;Šøm+€±m`áÝò.ŠÀdW†Ù6:‚Ö€Ô¥V¹¬n.YζnŸÖꎗ«zŠªH:厭¦Ø£-ж¼…×$E8oTRÍÖÄR€uç}ž£B‰ä.ŸÛRÖ3ƶ¸J,xF–®Í»xfÙº:0@§pÕŒ•±/±bÀnÅFÒ¹èŒdŠÊ’ ²ò¬¾pòÜÏûÞU¸/,}аböŠëº"WƒŒDmy ‹BŸ]Hg¢yš¯[04Je oJ¼®Ž­G$W©Q‰\’–í»þæ¸ièÎË‚ ³áS e:ñÉÄ`¥B•ت“Kvv•`àåŒ×¶Æyal c˜æÃ~¤¹¼1e©/€xµY£Ú}Ûô Ð­@$d°¨ÎZŽ%—\ôêW- I‰6d!²ÐÕ“ÝJJášvY±EˆÊ¨¿ÖwÕ]Ù‰ŒRT*½”§ý£ÿøÏ5Ch¶Ê>ÍÇ0Ù!ãÑWÞñÄf+ p$\À\Â)>l¿ú~Ô9ñãŠf‹Á¶@5c+i] aA¨à}æT!;E*lÛݤû«¶;ñëp_2êQ:kEZIgÉéU€Ô¼!Sè]k÷K±Õɫ͢è$/'*ä¶C‡'¼vTì¶D³o$ o) ¼áó«+~®ŠW†XÛÒ! ÀËEwày_e{Û¨6s'BzmF.µ¢YâsÉÈUy¼àñ.P¸ió—šKá¢᯾-s‡z÷)pHQð„ÝÊ­~m—¢mC`—ýcQƒ•ŠœÒmK©*Š! ÓU¨kÓà¥XÉŠ¤Ø*ŒëÇy»²&ìÿGH1~öSj± ‹PÒ d1yµa¦Tƒm§B)`pm,õÈŽ˜à„ñýø ðöŠÊ#ƒ‚¢6lŠ‘]¢•DWÀº8Fðò2„lëU¡ !)¹€Y¤¨µ\ŒZÀ×o~ó›Ç?§¿*ÊöÅb/ñ›92|vÛꑨ\[BÏóSÔé?J½n…³3Rr¥gœ‹÷ê‚T¡•ÀX»éµ¼•ז΋)XJÁNO\/×Î<–Àté:`ÎÒ™ööT.ªÚ\вu­'¯Ø[š—w‰¢fX%ìRX.. @‘¶h¥Ë–ð¦ðV’mêa±…¡¤gY…óRà:…Œ¼Œñs!‡ä%Œ Ý‹-;;X÷o5tA;Ææû‚P@µÆ»8ÏV[Øb0‹ÒЃ9"énN×^ÅðëA0wϸº’ÒªBo%€p¥Ÿ7¼¤¼VÈQ°¶^ßõÀg#ïÒt­NOCI%R­¦j§Âš µs³ÔÊhV®`Œ ¤â §šÕYÊf§7j0éš 0‘ºÙÖ/A¥Bo¼^}ï…ç îË j@{RÞÆ®~-¸^€Š¢B«J¸t& ’=—:!c+;©G: Œ{ü쥠(‰ØZ›yTÓå>ž,ÈÙ+cœ0ZË…­\•!Ä0iKðEQr‰R<|íC²áìÕßÉ¡àqMý‰æŽðJþ¼Ž¿›HÒ:•ºYT%‹JªÓ:# {È0\åeg!È(1tH^¹¬,D.¯yÞO8'ñ\W¿¬èŸµEÒ!*»2†ož˜YÌMËÊ8*;ÿhkå IP}Å}¨e¹ðË"â­ÆÞ–^ÕVI \ýìô©—ŽGá¼1ØÆ\.H®kвDî[Â[Ò»U Š÷Ðæª$IƒÅÜÊLÞ¶J}kå° ¦g‚;åÕ‹^ºÇÞô~±‘4ö. û²`Ën™7¶»Dol D" E¿u*ª2XTèh¶i(&,ÖZa à*‚–½:¹pê”øªèñÂ5)¸ÄRÐJݧcàB¾kAÇ l­6ä!K*{yaHàΤp§úØ$j‹PÆZF+¤*䢰3*&Ha'Yx³Ó“¶Ve³ãAˆyvá][ÏÀwý»;?r«v€ñ”µ!d¹–WÙ«GI•ÁE_a¼,ä:œŒU>rŠ[³Cf‰?ã£Uœ|§‡…( X`WFŠ.VƒõdàrÆÀ€Àóv§t r­rÌxl óÌsœy±tkJÕÂ8ŸÃY–`•W=WKs° ”1;$RêÒ!a‘ˆQÍ„N0(€±ʲõ¤9.Ǩ²§hÁÊk PG`£Œ‡™…"¯ËÞÛZQм}`â6_'˜Oác©JÛ®øž•]ú5# /âúa‡®2 \,méõ`‹GÝÖÀò,/o¡né¹J'¼AðlM9iŽwÕžkÏ?btäëð%UfF‰ÔOW§µ²`K'tM ¬¤&ÓV‰ây7ð]Ƽb«™"œ^¢˜mE5ÂËå'U^ÞJýÉÕX|ý€‰Ì’ºpRvФtMñ‚騦l¹X„“JÕ 0a´­Ó.wFH´,„—1f¶¼„>Å|TÅ" 8¥ Ó%¢(’PÚPXÚ²GK™„ÈU1B(0¼!SZyÇÆØ–B–«J„ó°°|ø¯Š¹®Þªúó±á 7k(¬.jÄœ¥æ%†¹Ž*ï0`ÍÄO!¶µ`eï¨ ñ=¢fœ)n%/ðm­I´ºôsñÒ,ÂÀjf$Ï^yj¨µð>i¼ë?¶}Wê¶JÂÓg¹dÉÕTy%­žìŠY,… R •ίò)¶Á¬‘c`4OŠ–­eHo½õ¿K‡dâ0tXÀÊî…”+=’½K) ¸Nx•pAZ=ÞÝ×U ¹ìÏ(á½#W@„ ’Jª;zCˆ“·vä¥ôí ½Ê]l¢ÀðÂNrWrJ½‹DUÂ#×l¹¢Z¶ôÕIyäˆùÎþöVê£è—;˜®’f^l^+rk3¬M0p™(Ä“Ya}xƒŒBàM òø÷aÿB¬xE@ާ¼B(Bb€a!¶`Øäâ…al2¹ “Wa\5È€ÑjKÁùÞhQ@ßÖ!gQ‰Œ¥¦Ç_;Õк¼U"0Kë˜yÈn,0˜I®xý’êù«Ó+oÿÞ×è6ðe§é_¦D©GÐóÒÛ6[ƬÎã:½<¦Ä_Tä±e¿ê,`Ù…™^ ²È( ¼Qt*è¤D”­§ù¸Ö\ºÎ%œâº;¨ì¶Ýz}¶Ä ‰Ÿä*¼%²T’-Â…–"ªÔtöê¡°Ð%’¿ØŒ`¹bæ Pl$ Í:K}±PáUÀ–ÐYjPR0¹ kR¶[ xF±VÆŒ,Ùë.rÆÈ­€ñ4Õø1ßþßÎ%ééSÁ@å6‘(ê§d®–Xv¼Bè¼xx)¼ìØ…gÎ[e`^¢zI 3¢J!–R}Í@ a$S€³³dô¿,!ß^]'ÏG¯£ãl Äꦤ/EÆ SaR+ÀV¿V0„5Ra*;#XQÖôR‹Å)#¤DÖQsSêãËÛÛ òÊîï¼ýȾŒ²t¥Ô†YÞJ®l€Ê f[ƒì ½Ë$Ü)blBâ±’0¼& cé¬åâR={Qt`±¶\ÌʘΞÅJBRœ¶Ûƒ‰X`±tÕš‰ðŪÁ¶ª–¶ÚX2Ò6Ú­”òZEÙo;žÿ8ZÈçÖ^é¥^³K'DwÖ ÓݶaØ£]åµÀ~•‡×þ€p!¾J|õ/l2þðÃÖj(×ÊkªÎsYx¹¬¦Ô 0suêèðUÅ[Á'ðXº"Voé|a?¶z9÷fHöÂeIQ i+ c=V^FQtFå™I«™1|˜t.Âoõ_hñîÿÖÜJîhïÿzDT$†U[%[)é0÷äw?vÃj¿Æq§‡qð޼ÏÿࡌrõèXã”CQ¡(^kHŠÂ¸”𗾨FgK)Ü˭é+9]vöôÆ ¡F-B$ªY @„Ëe;#€Ž²Ð{u¸Ëøö¶,åV׌]nëòRÔ¶tÝ\ÍD/@,Y¹Õ•ò&õÕøKˆ±Ô5~!°, $B[^v[ø Û#ëY6;“wGÝ–±Q„L‡ñ5gÀÛƒzôê» ñTR<¥caO—Ý6’*Én­ž»òp’ÁPi?’Q9f¾øwG<–÷ªÅ»bÚ’Ž`u!¡#ÏÂU^vzÓ®SöN/0áµ*p‹²F¸À‰m–x¬†„YUé˜);xŽŠ-vË„‹âÓÍ­³ÄÒaãõ;p¯¶õƒ@!¥à„†«š!K½ìS _ uçzÉ.Jc€!5.J¢€ì%M¶Ø1PPåV ¶=9)×"Û– é<”·oZ‘įžø!ëR v:òØKÔ„{D׎ò®}ïÚq)Îp+]î!:pHYÖU™rÉdË[ŒRÂKo²ÕÇË" †‘¬PéÌ(…™c¶EÒ ªðº>ÚYz ‰…¤U½°“n[7»¼ÿùHà7¤Ôš­Bé®`^)XÎTǃ]…0¦s™[ ŒÚ´ ÏÃñ_µ|øïZ{ô´¾R?BF÷£1â!\¨P¬˜²PHÅ”ŽN Ù³x˜œ¨÷-Ê–Õš2¶E›‹RöKZTÙY²lKok¯~Uä«.ç§f­ ¤ê‹•Ž¢ÃIa™q^¬i``±B*‰+¬ŒË]`øN‘{ͧîò>¿bpwø›*Zz©[%eaoK­è,­•Já‚W*€Úl­1ëg­j~¾lgÌÿšnÎDÆs0·ÓËžTÉËî§ÿUO¦’ lÕ©ŠÂÀÜC¦9°³6ö,À¼„Â…ÄÚ2R&¼À…;¥n¥8#9¸NɈT[OzwßF î$¸+ €Qx«ÇЮ—‚Õc«¶VJ©)5ÎNÙ:*)°)ƒ.Ö] ;I)‘-|Ž')céÚjíj‡$–¢mlt•ð¢Ma‘…¾³Ç«}Âã©[IwÔÃ9ªu; ¿øãÿ˜O _¤‚Óñ*eÁìtŠõLtÜ*ÁX*”—¥«(œ"ŠQ5` ËÂÙqâq=èVÞ€‘ÇÀN(QQ»- ˜¼Â/‹õ3 §°?ȈA@s¨ŒÊëÐÈ.EgL %¥SHe¯} ÉØ¬5θâ”VGÖ^F¿#ãwÀc¸SüÖÿÓ§O¾ÚŒ$rIE^ñÙ­)»âì,÷‚çúÖïk¹!L‰Tÿuß…co°ë@5ÀPÂĽÒщ(€¼V` ŶBº: s*`äã:in”!“1ÀFËUy,mY(hMFœ\U•‹åÉ£XÞÏ­h«@ºÊhmzʰå"¦ &ÄzEÞ‘ ž½N ,VñŒ^ö|½Šç.ÜÖ'L‚‡Ü2^íXZ¥°𵂥ãªàŒ¼ì¶S’~æ±°wY¼ùvá8Kþ&¹À‰‡†[g–¥£³¯)0³pøÖÒYC2ºý­ÂEAêKý>HÓÙ d)ÊJx­ðRø ¦ªžYÑz·DЖ…`Fû9Bv"ª‡3]H«z(bYÔ` Æ’Îî˜ù¹óóv^vøá‡xå1·1—‘BÙD1*FꊩlIÞzé,ÁsÕskM©né®È,_&^2;?h⯌ôêo’R«SÍ!¹l§«öèä刢¢k«æÏýC[ÇŒ”¢¤x\D´W£teä¥ÈæÈzV¬ IGQx…)€Þ–ΜR–½³ñòÌò…¢†o¾ùæ»ï¾“‘Þ¬ VÛYÈqð$­Ô’R¬³CÚZY\,áB<¾l5Hñôpw»š0o” éDTØÓ Uå•ÑXb(ËlwÛ:Å&Q ÇŸËjË˲.±,êIE›¾RQ€’$B+0Úk l0•Z/¶BtAº¶`h)Ä«° yÙ-:ò·ÐëÆxØÕæöüæ›o\YF®·ÅÃÇNÔ÷’! ÏuUÛH$͵ڎN^J¢tJÃÛŠ-\a ¹aHQ0,)­EÑa…\a³çEže`øµÃˆ_Iaª¤tâŠ[…‘Òª©ªePÅêˆÆÌʲ'¥QÞZ®Z(—¨nsx^ë9³cqŒÉ¨Àx­’RŒ–¥mÓ€v-Ø¢] ¶aj–ÂKÚ~%a'á­1À£ŒC[3EÆ‘d &Ä(¸6aÂ"ä¿ÿýïKŒ‚ck[PDµ—^&:;/‹­ÆÚ¸m¹7èEUm$¢l­\Ú’é!tÌ+#Å I(Â)áOÏñ3 O™.vÆÏ­ô$õæÃǽ€UCüU‹'rå²UØ™ööJ,ªZ!Á„'Ô³pÀŽÇã¦×¶zù\‘wv©=z>}úäõ«ª¤ÑZy•Á%»Ö¼ÜžÉo/$Õl…$ê±Â ¿•~5 ¡ÙJ9£oÏÖ¹(I^Ùë×¶¹ ,ìj´-Ë™í– ü8yñÄ¡²ë4Œ•·5Âõ^I­‘ˆU¡Ë$Ä—M Ø`QU WlWþ•ŒË ÿWù±ŠW&_½W Z¢žI[\;²­ 0öÖ*_8%‹÷~ClÂx'~€ë¥ngU€/)¥P–+0 {:Y¬ŒDl3§gŒ†~l¶Ä+{ÐdÚ~ɪ¾Ç&G› Ià\¶•{·B"'!ÑR;=Q§pÊ‹í˜2¼@:¹*²ä²æ­Û'¿lð<ò h/ÝØe¯’½B”‚Qûé²W°FèìY„S¾U^‘À,^<|#衳?—îgWœÞúÿøã>®Ðá±iSöÆ¢åõúÇbk-u%õxR…K8;À0, ~BŽüZ^QR_'6¶“ò¶4œz¡¿=CˆBH`jÌ–w.:/©0 Ì*Ê6a)¼\/æÛÿ޳Ô)}é´8¶:²V6¡àòZÙm‘g,×ýl$ÆWL?ð3ŠìÎgç~õ,/€\Þ¹ÀèMi!Mf>ŸøÖÿs_g:öþ¾äÀÂb0Yš #ׯÅÈBJLŠU:;–WÆ kÛ„),«9¸N6ÁóÞw‘<®.“»Rv'!~ÙU¸Œéê)¼úWžF¼?ó}¿÷¬ëï?,‰fA¥…>Æ÷5pyÑ6HsÀŸT€•¸Üסe„§Ä?Å6ZœŒ¢¢½Â®°ò+DyÏÿ9ËqfDÉX–tÛ‚_GæÌN—ÚJláë½1º"ãÙêèÝÏ@TbEá)Q!ˆ.‘#p&9æ>6áÞìmÓ­¶ž^! Ä'¢ë3àsâUÀ….[TVs&ŠŒ* pO £¹y½p® D=‰¼õ®TUÀä …°HÔ PSˆ·ìrI¤÷>o/ëŒB7 ‹»¾k½î„L¹®ì¢ˆW7Ñc~UÑŽŠ’âŒ¾)—”=r“Q6—ªœ.GËè0 yMá‡y?üðƒ±ˆbïq¤;‚OÀÃ`5dk„Y–…K\®W% »›%6Cæ]8—X%1†·=Ÿ²ÿÇËB±¥~ru® M^,Zœ‹­S[Ť×WÛª¢ ¡{Kà…ØWþnáüF ³ç¡Ïœ’"Rwé¶9£µ’rY­:m˜Áäb ÀH2v×Pb ” XñŒ.ª@§†^¥BËNgÏeÒ5ÊŽ?{)c¬’;»-áE^¬­ÃÀÒÃ-6^ `½ÎVLíÈ90 Q6%‹-¤.ðÐI.å* žÑÜGõéQUde€QŠj…¤°ˆƒìgWq[I­Œr™‰Ô¨ÔàH¨œÞ@¼ï'oÿÕÅë‚ÿöZ’ê¥tR —± ÄBgpQܶ.)ä«ÌF¯¼rõÔU.Å×¼\%ªw.¯øòv•ÃKMVL…5„VH Rì(²×‘@UBêIOHçÁZ"+$»Åc«$+—@FBGKÁc­€0å ²Ã™ÎËEOq!0t6$õnÇÏÞ(8cP0¤tVW’«®µL'Kgàê,V:VÙ[‚†… ÆÄºëY\÷ð•7*Q’B²ÈbKoY„)_^Œ(Brá “Š´b0¥Ò]]y Wø¶J¢ð¢ÊU.:e æ<ÄÏ•T³Õxå%]ˆRQùË_䀆‰ƒ^J9€½ `K`³Ð‘ZcdÂbÛé<9ŽApY»!bpð¼…” ÌeCžÝÊ5½¤¶%¢ÀĆ€+ /‹mQñD?¯çµÏý]?e¼KÜ!òzˆò"„MŠrYeì {v+Æ4Þ•å –Ë3®¼ìe”‚°XYt'5 £Š­Ç` ’‹(’—½“ÃBÀ¬b)‘k¹“ÓT1ÄfuW Â£Y^âÒ°‡©’¨°‘˜«ÁžL 6ƒjVHN/"õLu4e+’ˆ¡,Œª"\b! …—…Þš«¸„#©:áBbnRØ‚…f[8Ð`+ /”_ÚØž¨/ ðmŸƒQ#URFÅ0ªÙšÎ®ŒDwÞ]9ÿo è‹®ya'Êàj5^˜ôB·¢’‡íÐKÚ’ã,‹:QmÒóÚR€ñH‡…ÎXt cYj¤ÂèðÒ fk†ðÝMá1°»(ÈV\Á,½ôP2V€•HTxÛV-#¯ø:Â?]ÒØ¬òV¤ð¶_yÙ#,/] /T„n¶¶¼j <²È˘k-] «g䌤pàDy˜¥{¡<ʦƒ.„ÂBQ <×Kô1áïKEÁ(õ¸—ÿüç? I³Q@H[ìÚpGF,¹"­”,tÆ,֌‰@OïâRzHePÔÀØ­’EH€ÊÛPV9/9¹o!ª–¥¶ÊNf¥×u^¯a¾Å™åÚj\^!¼]0.µuuëëÚZ#b!¼:Õ&£ŠË§ÁæÉ` ã> 0±…'Ù§«Ä@ íšº¥1ÛJ‡*€˜@¶RÒQÅf &ÐV,6·–Ë _Š€Yè„WFH¶’Z1Øh‹¼X…_eä`›W†H°.YR^ó„§h¡ÀôÊ@›b-Š^=ŠÌ8org—mÌ\£]›EÕEEºô¼rÁ¯A0ƶVÛÆB?~f- KD"¹­p¡)údѼ•°l‹bWkiä+%äIüÓ‹}´À8÷m"ŒX„Ç!×H(h•בª F!„B0°ƒ±Tá+¾jaȵ°ÂEy=öuóøpâÃØAýß*ª2(ßj­è´•¦MrvŒ"{£ÐxmÚv!ch&Í¡‰¹3S2Bv’º:§\KšžÝ…s<ðcçª ¹âm¥Ã“]FúµMö’ ¡„§ÔÈbY®e0f¯#ÌøéH SƸJò²ðfÉÛ*°ØÒÑÙÁ¬ªÒx£Ö…ÑŠgóŒs!¯ÿøÇ?¾Ê/U¼RŸå©ÊÉw9©°®‹É<ÿ>•ߣ»ŽÊFˆ †È)ºSít—±ðÂ3Z‚ö Q…±ù4·Và†I!0Ö(¶#i[Þél¥«ÙUn ?þø£›ÚŸ|òü¯Å{ w#{Èt\”:RL½PXÝV}3¨)Ú4ÃŒì0‘X¹¤oEHxEYé…P*ƒ=]ŠÁJÊž„ä V\,†ü·¿ýÍ_´ž?`H¼'³>)²;“~ßÒ‰’—¥£ƒ2vä:2–õØðm;·”p®TtüFMx–æLe¼†çõÜöw9ÿ¹§w¹÷ÄËV‘T¯Gµ­Úº«Œ•]wõ¸ 4ºÚiÂh#ÂH(D81Rxǀݶ³Ê+Ê:0%˲Ç,„K^8¥¯Û}”"¶×ªžÑ]2ò òUŒ:{ßo¨/ëD‘Š·U0€Õ–±~ã¬Ùí1¯sæV!ZO¶¤Æm)ðñ/ ½¤0 ’ÂB‡´Žß–]`[«Ó¹Â3¡‚KÁ^;…±5ªÀt<º«à^D¸b põ$ìnÍÕ8Ã[áäª``Y–†ÅZn«•‹]=,õb›%NºXŠð:ï8JרaèÞ¶` ‘påå’Ò–’Èr;ãþÓ£)KU!Xöt„xØ[;f¶Bxo_-UzDÖ:tÛ,e˜óVúß}Ò­ÜukŽE•rcó‘Î[LxO¯ÍÂ%u%p¨¬Åb[Ñ`<0ðÆÏÈEÚn],K)dÔ¼X Àb£eW†’(^`{¼i¨–ÿQ‰WïK鲈 CI· '`YJš®¼òŠbQIÓ†§DÎ~E~ûí·ï}çte¸êÎ-¹Z> »|ëvy ÊÓQu;f\îë.wÝYaº:t€.J³²í¹ ƒ°;‹‘>{Õ“&Oà¢À†¡Cr±HGñ¸§°glìÞ|{·ä&7µ¯´P®ÿ¯«GŸ‡^·ó®>¥ƒÑÐl³4ç&¶ªÚj$‹mO33¹zµÓ%È…¶1²7.Š+Ì‘ø^çV,Á¿²”(XÖFJ)¬¢þþ÷¿û'°þå»ÞÈž|o-‰Î¤+(£²åRU© cY<×J‚×QSR;€ÝI¦äë<4«mü`.ŠÀr.Æ¥£¤‹Âø7!ïú4Uåï]ݰÄë¯w;µ¯R‘ØÒ]\Ò¶aoÔ0阦g…!¨xͤǩɀ%À\éÁ¬ea¤$H(¦ÅÒöxü¯À¼t B˜”,ô`KQÁ¶SDõì­*.2Ú­¼³ë®é(ú5±,˜G ÊR%¼u€Nl¹`Fý²k§£t „UxH[HáÀV’‘½íÖe——`¹"±¥”À26:¹r¦PÒ—ˆ’ÝZ©t ØXè¤Zm뎷DBªDaÓ¹Àz,CŸ¢øºeâf!x‹¤cïÖe¤T¤-±µÂ@V„í.9{Ìrá,“ÙË"#ײÓÇL¯1`Æ’R|!ŒÕ¡m‰A=+£Ž„°_; o Ýë· zñàöÐ!NITg毶‹"½ÂYéDöZSÕF­v}5(OU€YBa'ô‘Ôš@ϵy»Xe´¥tÉ0ìÚ嵦ˆ…œ\íô €Åz\¤SŠRX—£Ø1PF;eÆŽãpWC+;p$Ú‘Î$ ׬z¤£PF2=žt®éWe¹(!…à§wi€YZ³(I¨â¹f¤7±o¿ýÖ¼sBûß(ÞRøq…â6ÌúRyG¥yžçôø¦‚CÖ;ŪðÕ®U•”j¤†Ï »12Y·á§‰üÑè¿ó'Ï.¤ޤg½ºsÛë < o .…o`Ua†;;Fä DØZ j·¦¥d1¡Â.$‡n@9žÀ‰T‹G [A¯ïÑXý8öÇØOaŒ4g¦ÿv£¾ü}xùÕwÇÄÀHë»m¸mÇOÜÚ¡h:”“º^½øHm8()êbíTUI>4µã ÓXs°òiÅppFå›°îù$k€•ÿØßï+§/¼§sÈîB|êÓÛ–­»iñÄéÉ<å z÷´®{ L£Vs›ÿ†ÉàÄ5íu*‹¡q'Y½ l $XSå=ÊJð@˜²@š Žïº¦a++Æáñ7ŒW.®ä,Êù øÛðs3ïÀéÉ21öfëãœ_km«­«‰Äs¬M¤9Þ®¦Tµ é&†iýÁÒõ²å¦/²ƒè4€ÕRïæ­0—¹ñÞSw@kå& ¨2ªÖJ˜Ô躞§€$¬R1²Ê¥|"zâ˜81=¬Ä*V¤B­a&ÖZd^#ë Ï‹L#U:%µ o l‹¤t«Ö<“ñdž }“4­FÍSI†p@UÑlH[˜ cÛ´Mn[­UØRÖ0ÆH@]hÛħæy"mNƒYm†­x]ȺödSæóÇ• “]E×åÍy'ÌpŒS$&Ì!™²‘ðÞùócʱ²LM\ªDæhJ×ÛìcÀD ±ÛêG£@™ÀZGJ£ÔXv-"‰ƒ>€‡óÁhÄL:mß2½Ðe¥Ü)¬B-%ÂV’è[IÞA0¾‹3Q()+û&R«ª‘T9E†”«%ˆ‘m$Ûî0ŒZ@Š3±p^!“ÂT  u¡4 Û„ªh8K!¥¯Åczn”RsûO€rYU+T.ðz‰RÀ”œ‘ùS6,F`¬‘dæ‡#a÷`+h2öÔð5œ޷;ÎaxJnd‚9Ud  ãá›<äBŠ›òî­’&§Ä|(kZJí4€lJ#ùËi?ØþÇþmu¿¹úAØOA“œß0RSµöú9B[§¦r@ÛR.Á;Œ´…Yuc˜ð½óXe{¦0Ò*’uc<ñùÀx²®±ëÚŠ¦êó^/Y¤*²€! ¦¶+E¦8üèNÖ÷ñ$È ¾È¸IÍ Þ³{ 4Â0¬ÊßP¥ÃPkJÑ ôÊa« ÃXî¿-=a+®ÁYÈj÷2pn&ÓýºžãpP´ŽºÀøáÌe  *†|º¢dmÅñûP:o‚JúävdVÈæTÞ¨/+€ÃYJ °ƒh ¿±Q¥ŠIY…¶ÓxF"@ØøRaä¶”¶ªè‘¶V2VJd)­ø–5j>‘4¢a2!ˆ¹™Ï0bËÐ*1©{V‚Ç4²;×7^à1}âÜŒÀËúQÒ_GÚ*™8+[âRÇô^ Û”ùS®¶ò²Ý†rU˜H˜&LÏ—íÁ^ù¯-^øÕ\mMs{W"h~+ÜMê񬃿èŽáÌÖªVJÐÃRVU§÷½p2 œ2 RTTÒ‰ò×ÏM¼à-K)ðâÈxbOœg?šõÒ(q>Ö†¤y1­OÀ ¨ð]39W£A'™š?]v” š²”MßLx«÷ÏôRÉd»ýúªb"Þ^ÕfH¬„ FŠòVœEJxÙ"œÒjòºËÚV[¶ a)>Óô q%ºIlažâö?…E·dZ¿`å?M­­ñÊÑ„¶=õ¯Ù™j˜ç0%Ù"¾ù¥ÚJmK1·5+0¡IYUóÇ—"{»$c8bU¯OMgNì%FƯ U˜‡C%.db€¬+’l±Â·…mþV˜Àì{s%H6í|j×Öª<\wU‹ekMYØ·Ò%½„-Œh:E‚œ™ ­m•YýµtðoPø^ûçÝiþßÖû×OÿË_ö÷ï³™gM›°SèΩÍßÛŽúýG¯Ë'|ð)ᮥ²K#ð»{²Ld‰E@mnÚÑÄ+z¸RmkDIY¹-£Õ…ÐGfÒŸx¶ðŽÓÀR׊•Ô+æÇ*¥ÐjN…¢ïÆÎ»ÂŽV ƒõÆÊÒ§ArVkuÉôĺ‹·cz+òåYÉŠ ™°z[!«‹ln•Xá®®V┲R9[E+ožÊÉ”ìƒ ãE>@žH€Uß]ÀžuwÒ—½˜¸#(¼§9¯Y)[ú 錕׋ƒÌ52†¨»mn|Ö&©©-Oaë{¯Ô­>åiÚZm‘]/l€˜™ÐD®0g¤m¼ec¬M% ØÆè%j°’Íg3üл%2>€B>N$Ú|àü­Ä Ó'Àô—P¶ü 2ØÊßší¬¾Â33wœMÂVJLI&ømÒãkÎxåÄÍ@cË¡ŸM¾¬’Lh8ãk„Ï9††³‘¿lACÀAÖ<¶®Ö׺‘/eë¹$¨¶.­²RB/PÖ¢SÈÚNP‹ u¯V!\a>¶Ë–XP&k!ËYV ËJ bü†'˜,Ÿ˜”VJ«É»íWÏ3·Ìëõ ঳FVÇðd.›9ÒÇ_Çî¹yèi WØl˜v€F!^V/‘OÝÓç“UþÿîªD$ö½$j›V—ùlÂ[wÞÃÂTÝ<+&dR€Èßھ׸÷^&¢~OB-q/e +$vNv®µ È*éüȶ[óW^»5ÅФ¯—U47 K“Àz“Ÿ%MäLÒç@(7ÿZ”šÞÀR)ÈVô$ð=ƒžAYÀ™0Ôb4’uQDåù3‰'ëIPÂÚq°’‰ –-â°•žˆ3>ÆP» ç<¾²I¬²Jþg²oÈ’ýGJ¼³4€ŠF¶ñ‚ÌTa2XÕ[n+è+Ù–vHâRmMÛ–³27¤°m°|ÞU–²{0°ëR•’°fÕæIo ÔIiËÄßµ§©p˜vu XëŽk¤ÊÝZ™G Gj×5æÖ&hÅ “ئtE¾„­x‘Uñ¤AÚÂÅhðAZUµ ç ¶,NPSÁÿ¤^J•Ig4¡©ð­Ü‚40†øVŸ3V<€´†é¹­\ÊU ñ<…@åd•g»5ç†Aa¼xiËß|cØîPjoÅç›0sr{yµ˜ÆV.…Ñe³¥ßxÔÃ%ž-yL©Ü0Sœmõ‚ oõ,¬o¬Ð`h†]8%&ŸaUÍÐüRç'Ÿ{W aEå$bTcÅ"P›€Î̪¶yö*3qž^5‡©œ€om¤Z   )Rv¤D_Ñã$ SUVëÊ79e¶Vc˜³mæUÁÓcjÉ­hZþj!œ¬õ«:Ãd¥Q)[UVU²Ý¹©”¤èD¶xb eç’ ˜M*AsÚF*V[6s8…€¯!ÿLÐ0=ÙBVQw× ÉfϼlßhrbÙ¢l3`l;&ÍRsN {Œ9c6[}ec(iÚR:‹QÙ–µ"’³éøþf]-R f´]S ÆúFÊ1dÊÜ æu¦of«°­©ÕCq@щšßj‹¤„g¡„ý‘ ‡4z1!®cƒ­P¶ˆ‡ßÚ棪ù Æ°¸aŒ-lþ¥6ùÎ…¡´%På;a÷6À“ŒMbÛ K!cë%•­g)ÈCŠÊÉšS #Ú4C}oÅ™V`¶8 µ[iÚ¦lý#©–L¹^ž&|ÞÛ:¨ÅÜ܆FЦo•H‚m¯ ³-\;åL·DÃ<\IbDäÉ-+<(T%°õœQ/ïh@žRÕF’J/Å<žÀÖ:Ÿ4ɶ­;^À‚aÀ0FÂ×ÑÕÙºF`nôSÚJz^Jèa%úZm­Rªò ÓðLߨªÚ1lÛÍ|þ£#ÃͰ^4ð8 €yMµã°-ý&Ÿs܈3Ó¶«àL#¸Á¬Šð›æ+}<˜yŒU¶'µÖ”œñ",% ÓÛThåï®§TM‡'ØÁjúý°GŠœ­ô)WÈŒ:E%’%xõ˜ü5¥1žmãíÚñdOPô&cÈö¼ÔÖ7ýF‘4@©pάëãmië;¯‘U¼12‡Ì¶µ“Ê­ôÖ«¦R@¯‹­¬ë0@µ™x|n†M-’Ù"1ÄÂÖºvxå É&xñ£Â~×€’¦ò[q¾|hj„±% Kƒ·µÚv„<¹5’UJ!HÜÇ|íµ‚€¸’ 1ñHQÈð–~®½SäóÇÚô•Xm»ó@YU"lù ß<¶ ƒ,ŽôØ7*º‹­–^‹Ö*vœÛü¤(¥Œ¨eè§j§› A£fÒ¯Ú”Ýa…‰³¯—ÇÔÙ úŠÐ£u窱m£|È”`…€îdV¼H‡ ³¦Ž9'hµ¶ÌßuV ¶dV¡ CúÝצZåB¶ÿ†ÀÌÔ%})¤PHÀŸÙ¶”íHÀü…"•$+Õx.GPÊ6ž`“¯oæ(e‰gØ6ó7µyRÚ®„ØV䣣”Ið†Áó€y©SX«¥?õ_’Þ*x @¸ª_ËWõKf˳8«zåc5ž9#h¬ëÄÍvçªð8ø€ÿÐIºb¢Š­?‚F¸|A\oµ@$@ÖÉÖêÍ® ŸMs› Pðô©k†L0B•U•µ^ÖpYU…-ÆZh‘@YóT^v¶kIŸ […0^|]Ï1Ã&°ÒOØv9j› +·V…ÉÄ‹XùÄd˜îÇä5ÅTh‹TîÂ+™¹’l¥ú©Ó=Ô”’ ‡ ½ѶÖ¤˜-\êVœùoþ3XÝqèE…Ö‰¦‘b„¬9uÏ+m÷é7¡˜ÖwHØév'ôboÛ¶·Ãy¢¬‘V¶d oK³v“¬T…°€YÑ$pÉáR)­H-"÷dñ0¾‘êeµX‰m…VÑ–,¥5òG/KÕNU[b@PÒZ-^PŠdÖ¶ô@ú˜Rô­˜Äde«Š‡_+U"Y^£›<Ë:ʘÎUÕ”™KíKÖMj:‡p&U…ñµy*ÁlZ[˜[}_©¬l‰ûh æÉ¤hJy]yö“Iª½ó¡†[úœ,27VÈ4/–E b|[À–>f'BÖ EÛÄVn|º(zLä@‚¶V7F PÛ‡”|dsnžRjè°d”U°R¨—(‹¬MÛ6ƒ oŒfóprUrì¾_Ÿ®÷÷$ÁF2†,&¿"07&€m %FHij 0y5p¶ë ©H¸`‚NÄ àï½Jo­\*œ±ÚZÑV²ÆëŒ¶5Zm³ÉJ &B6ÚL0mZTr¤w*Vjk¡7y.§¾|ºLÀ§#™•¾’ý4VgÒ© _S[ékJ¹W#b¤*«*3X¥º^8}‚Làü+ä ðŒhêh5R%­é³² %….VBi« ³Êb`‚Jfn› ÒŸÊ{"Yµm­esxùL&p7À°©¬ ­x}ñ¶ˆªZ¥à²@ž”‚ÀÚÍ8H)SÄp°µÒ3ái{šÝÀs#³ÂÄé»FŒX9çoÝyáÕ¶@ æ?ÍdÕ¾[¸a€}2¤I¤ª‚Q5gµ4xŒØ‹SÕoÿøÿ¨ÆÆˆtU~ü¾G¥ÁWi…)U¹²æÈÎZÐãyÚ¶ª`Uýµ7̤ÇÓµ hKïqÖ1ϨÝHL@YÔ“!X(Z›GêU&KX Y€kà“{|Èæ iÈî°#÷I˜¨ÐlÄ4VLÇ16ÆÖçê½Æ^YUJðJs[b«(‹o’&Ï_ɘmM;Zƒ•:^ßçµ"ÿÌasúi äÄr±F¥duISŠÒ´ë"‹[YÇ4g8Õ ]µƸ±Í`ë_íÞ`¢vV3ì3‚'ÀåáFÚå(ÁW©æDÖY9€”e¨K¶i\mJ k­RÙ¶¦™Ã eémECRÂÖ÷vá¥ÚŽiH[UÙÆ/hµnxL,ˆ›Y¬6ð¥Ï^ïc^(j÷6EJÑwv3,2±¥±’™m¶¶HÛÓìûެDŠç+€¥ ÊÝ6FJ̧™1<ÕK…i  — /¶¾ßþ¡œáûZbD©@×Û$˜ @ÓÑJÙ–jÛšƒ9™€¬ZÄ(¡¶4Ö ßò)éi¤È|6» ¥ðœ™¸â¶ÍCß§K k€Öî­9(ÏdæùÈâû}Pˆd°ª¾N jg*%¹ÙuY0˜•²°ÍÒyý-,^yM›Š@ØúVXŠU¡¼Àç0Y̲ùT•†- …aúKSà†(•#›¼ÙÚZ•à¼Û:"u)uUŸß§UƒÙ1Ý@2@VØ  îpþîc Û+ü\ ^/nñÕ’iÏÐy14b-¬¾ûôÁJ»@IDATݦLóùÛ²Ê_- dÃ0F·ù)‰ç#4­4•We%°â;5Ïo\HÛî¤wƶUsˆa®Qót^ ‡šÖý¸ß 97ydˆ$så§#“ð c¤\¾µûWèý—2m í{˜ç)‡­u‡«²–bËÄØZù”€¾dBUaZ@ÊgÜj€5„l‡¥l{éÏ0™Ä”Å 'н9l JäëVíH²pOðÕ›?#t4šï’M.ûù€ #¡LÔ¦ùj险a'o•jk|><õ‹‘:¾÷±5)‚°l¸/£óXndž›µr@”R ka•uB «ÕbÈ®¶À(3lž¶­ü‰‹:Z‘ÖEÛ‘œ¥¬Þ`B#Ô׿•ÞƒA&ÈRÆdKu þóAІ ·VÖHðaÎÇ…×%+ ¥?­Õè-Ï¡1Æ~¤:¸7éÒ:©g EÛp[U¹ud>Ê9Óô¬1$Oük®DtØNÔ4ÒkaÝ6=±¨]%dª6€­ ¡wÌ+?˜ØHÉHW 40­m‘!Ò¹ˆ‹ôL™š*FÖV¡&C$ÆZ¼žHJ+ìk·›mÝ·ªês®DOüÇF :ˆlUõ‚U!mak‘X¡Iàf¶…‰Å[%¶0™*[mÈm3?C|¯IàŠ8L!&eUÒµ–µ}Á"1Ür… C#cÒ—­/½-™u8«P%•g4¥ÏÇš¬Ö0± £­V‰¨KždV±,!2@V«]X;ÛÎØ ¥¢™}.j”,Ÿ×?ý;¼¦¶³bî—]dVÄR°€ñk‡sSûtèîõHܯþ‘V"»@.Õ `^PÕ…á`  ‹ÍS_Lw˜€˜6!M÷@“/ºÞ5µíCá\ 8pNæ¡¿ýÓ?ý“î™Ò5kàÅ5#ó´ðL+¬„µ-Ó¢¬|ßz×ì<0]³‚ɬsȤ¬ÕôÄÈÆ(K_*ÃV­«j$Ê®‰3^BÖùÍ“^mÝ ”¼)K)Ö«™»Ð·µÚJ&ê8f&ý™ÌÖ0²n“sÓBè÷f[Ý1 7€í=Ùyjk¼JÓkMlÛ«°F›Ç–9A†;Žídïv8}žH' bš¿ª‰‘p“KÙšÊ$J¼`R¶ù÷ i0™‚¦mþÎgYc°µV•§?öôhjD cKPjSxY&€ ÅZãpˆ70e“”ªÜU®Íù!¡oëÙå_U2Œ0%2†¦³ÌÍVØv ‘ª]á²c*äß Òàëe%~£²‘á2=¦€iŒ4R­T- Èæ“Cç­WU²RVÎ N P¨²ºXþ0™cÒ+¬iJUB $Æ*^0Ýûâ0²Ü …‘}Æ«ÅÈ.ªŠ7¿l-ðÝF á…Âf³®c%”»ÀÊbàJª­ ²àÜ'‘22©0Ш‰iD#$‹LÏM(±úÊ•ÂÓÛZñºçŸ­¬Y2qUÉ`‚qPN‰Œ¡©ïr`Ѩ¥&³e^6œ­§ƒ”J‰ FSQa«^Äd:®×ÕÅÚIÉòáÙ™Y¡ŠùVÊô@¤* eï˜÷ L®–’†ØŠ¬0ÆOlRBJ1²1â‡OÁU^ƒÏ+á°©¤ÚºÄV³%“Z-†sä`m»ÂŒl­y&^á[ËﺬÞjëºÃRÒK©µR[ñp&ñ¶HAoÍn‹I°+%ðAp!½0k½çT.%8P²J`[˜S|wg ×¶r@y~ËÔÕo™\P?\v˜:™L²ê¾=NšNˆ„K‘ebkî&˜ífjP>s£|Dú4­5²Ê ¨‘5·/îy]Ï‘+§ÏÄVHPªeNYI®EUÉ”ô¼dñPkíȰ螕‹R”³¥Ä§ÜŠQu-ÏI'P6öfà@,(‘okŒ!U U‘q ƒ1ÄRNA ÔQ &‹‘Ú$pa•€ž†­¬BxsÒà­âA]"—­œ C- ÙÌJȪ%#€>"¤ T"ÒKÁÄm‰m‘•ég.ËD¶W–ò¤Ì¼8@Yðk*‹ç†ªu<ÍÖ²ÖômݘB¡ÊÀ‘ª0¬(E$9g ™*¤m8T…¡/›mkk ^ÜjT2µpÿ/Ô^›¶J¤¨ ‰ g"5Y-0.9“4Öb>UY70Açš¶’je‘V93ÙAb0ù—­coÂL€º+y¯Êª ÏǾö•3ÄÓ&BÊ·±–ê;°’¾¥¿‡x[þNà3Õ]ñìó%¥ªIú íkcml%oÜIÏÂp£’)3)eѹ´Ø³ò£–¸IÌÖ÷ê[wÀ4L0‘M^£XJaú|0x$ÐqºÃáɬ¹¥´Â=ŽšžƒŽb}›'·xæË*‘âF–²µ+JÖ`@mo¾‘ºŸ<9ðA*W%ðYÁ²V‚B!_!æüûÿðÿ ¬´6¹Î¹”íë“€‰Qš )ÌM£YÓ“uÌÄHxQ£ŽÔ¸™s³å#ˆm3Ùœ@üiüý  ëñðæAR¬5&²êkU^øXßoLJÎÂvʱ`kKжTµÈ†)EiKpûŸO—Ž”‘4¾;h< ä‚x-ÖSk+eÎÚxkÂH«Há ¢’øHkVQa—`+( šdz|‚V©î3çpµf°Î'†’œC“#E @ Ê¶Ö™¬#AV²{ã1f}ù We]ÐïDȽÚZûT@ÉÆ˜{W=Ö|¬µÎßH=‹²ô¹"93Ñî¾þŸßDGzÑ3”¶ÄÍóº5LÓõ­·•¬6`å#•?q[²ÍiÍ6&ŒŒ¯Ê1Uô&Û²4ÍP 28Óª²uV¡¤Â@2j‰­0RØæ\VªHPë™x p?“Èvá|VÔ‚8½¬ñ¬ùÀk  XEÊ­N„T•sÖÈ{âsuÒt?Ê™¨#AÛ˜la²a£v']¦”ªîÀ²L€@a3аÅÛøduÏÁdVÁGH5L8å ÉÆÀµ«Ä}*éœ,ÕØsN›çãYanªèß,\I«,¥ ñÄÖÙ w+Ä;cJ%0†¾ûIß%,K ¤ôJx aw4b&øk­K<,–¥ÏSÓ•0‘>OÙ “•B[«¬õ}ĶÆ+%K&²E.Ö çx fUiô>—J¤è­ÉÎ|7ÆhAi맘æÓHR´ [¥|á S÷í‡ÏÈ« LŠL0G*e'¦ïºÀVTU¡Š©ÖÊ3‡ó©$#ˆ¬–•¨EY-V‹if4ñ¦Å»dÊ+ËD6ÏܬÉhz"4Ý¥˜y€^yÏCÐ4@žx Ô±ø~OҨ寑Î+U"Ÿ²L $“RVYfnU¹”Z¡$M³µÅSjA,¼œ4ZÐ4 ýµ9za«5 [;˜8 ¤ØRz Úê•óoúÓŸì Ô9ÊýˆªD¶º2ÍZïSö=sc1ÑI ‡?«x%N¨K†¶ ó+i»Ö§ÇíªÙ<€ÎI“l[€­»£)ež²œg…ì°ið®¦Éã÷!m~²Í–@I¶²Rµ˜¨– Û#8N‚Èæï˜›–LiÝ'·ÊÕÖB*gJÀÖ ÀÂÅZ+iÎùãû hÛ|ê¢ïƒÑ —¦,€oc[äÖ‘óTÛw.@S2Y+/GÒd›€ÆV X Mbµ›¼©vJˆsNã¹Í@CœIYÛüë¥VdÓ [¸±S"S"Ý@JÏÂóáO`×Þä­d)[ó·5j¤iÙ6F“Çg^Dzœghm 2UÜ(aäAªjx«È$’Fzk)ǹªsXYAhž”V‡Õ·Öªú ¿{¸“Tµ^ôøšÂôbÃÈÄzI­c€ÀA’Q&îháÖ5µUh[•¶î§1<¦Zоðí<Óª3 \x(2ë«âÇž F(ïì µ²œ¯ÍyñвÄmkGf›U#9Kæ¦Í£œaµéóWÙ4Ö^$ÊÎŽáÏ)¸udØ0»ïGþJ>g_ªIb¶ªÅ—ªª.VMM;ЯÂ^E}­~©%h6kÌĽ副­”íiöœNU%RݪlOAÊÙ„ø”Öæçœy¼Áˆaß»6¤1ç:ÂÍlU²m³EÂjY)Á‡ùçþgPýšÀŠy…W©w ß4²@ÓÐu#òO$&èFˆ…*¼Ö| Xà[<A·ÊHåÌeCBö]™OT¿‚$SÕ÷À}cX³Ås«Ýõ;‚2瘔¬  %’¦ÖÈl“mÈx[)«Ö#˜ä¨{&“¥Ç$;êo°å&d @Ÿ[[ÛF2s¿¨!gKÆAÔÝ w [iè닽0>¥B[¶H`¶E¾Aik¥ì˜N x¬J¢™Ù®V †XdŽQ¯Êkƒ´ehUb+¤l­ kdµe­RÌ­ª»[)[€X•­‹¥\/,ûÓ’þ ž4›§ ™ÄÕ`ø×Fš¤F°Zî&çdÖ‚ìÇ d˜H€Ææ ÜÌgi›C¬;¨rötð"=ÙR²FÅH½Œ’"Ÿ3ßÓÉx$L¯5^_3 T˜†cšz™ÇÉÖ—#ÕTÍox@ 2µ²j1¶Èüw"‚4­Ìe‰»„Ƹ’sÃøáê"¥»” g%È„­­ Æ$ýû~ønFŠObŒÚn©†ÇÃR‰ÝŒôæ` Üžg¡´"cnþ|å*ŒÏ-C«H ˜ÇZS˜R¹­0˜îGý[Þ–¹lFf%ËNÔ¡(›ÇêQZE2++«PÒÀº.p3²MB™ hëé÷¼Æúv)b)+}™4•r8‡:Ò þÎøRv%UPâ+_k¤”FÖ~¦H‘ÙN|z<_Ñ^-Ù|Þ±«Â[¥g˜§ñåVŒ­h¼jÃÂjcÈ<\7lH¤r>€^Õi})ÕÒtŠÚÙ¤a8œ Ó¡ðΘ&±rÀ[+´¾ƒ)ª–çJ”ÓôekKïZßȪò„;/YYk¡‹*nÎ+(ix¶J‰J`ÛØ7óùªL(ýŒ“²…÷I5s…º§é¢lés%”x3ä)«ª[)ó¹Eg¡·ÒÀÌ7gÙ0¿ýþûï[岨¼=Ô”j¦ 1÷Ê+„wŪàÒ6ÜJÙ 3$`‚¾íV \­µˆìµ0Uµƒýìxf5"tQeJDí6,RSvÏ Ó=¬ ÌÓäÜYò¯Qæk¡$ =€QhíBàüm‰­¢r<Æå4óåócC• +^çøf½Âóì`d->eßÿX @©#P;k¤µƒø–þ:TþdB—õd3ÉðžïœÔC„{c5…΄ ™cjG@ÆGP•G(Á{‚yúSA­eÍ6R&Uuβ¬ÒHÅs˜ ˆ±ÂÄé­Z ­ñÍT˜¬ËA5FÕJÂfP’rÎ4i8$ Ç“a„BçÕůªÄLV«ª¸-œVH +†m•·â,éø0@…VLÝ«*õƒÏGŠ›”5±õGp‘Éèùïã\*àY#aþ€s9f#©Ý›à°L¬¿ŠRKFÐ=(ÇÀ€`XÖO±ü«'SHFÓ„xÑ/Ù)ekÑ0Lð9÷ìèkW ‰1¿ñæÐY:¦”rb†Bmƒí¼ÊËL¨¤*HU>­ ‹ÆÈÓlóìºló_¶^jÅ08}W‚‡Eó¯ŠXØJnÏÌaMûbÉ¿J8qnô 8Wëö¤ÈðÃmiÄÌ1ïÑب®Ez+7Ûªˆ1€móX D[)À¡²ª£×  Ñ.skÀlJ`½xê›Æ–QKáOÁÌ*[àÉP„§©¤,Z¿ò󟶪Fv]øÎrÜoVaÇlªøÈßµpÀw.|U@½Öˆ8+ qW¡ ìq VøclYôZpë9ÂÜò—¢I7Fƒaq=>ß~Ëâב/²ê1Eªítô[3h (—ê Õž?  :"©+¾ÎÂŽ²,àB B³d r<\× ;FHU5“ëô7ïÂV! lÍo~Yb…«­¤#1 µ|œh`Ê€UÈ:rØšl­ã‘õŸ¿bh|Þ:¬UÐóô ì…ÀäÃDØ*Z‰s£Ù0eñÄ\¦„{޲ñN§Y_mH>5’b‹!Μ#kE¶ÐèbÅ[DâF’2†•¾Í„9RÈJ…ÍcM)Õ¨ "•è"öÒï8݉­¾kª„ØI¥âÜ®%²îmJš¬Ôn¶²”…mM»=å•XUѬæ© «Ê ×Ñ W2\¯&O‹ª*´¥·š¤cj¡ÊŠiȶ³Ía…À0m…› Xp5ýQhët»í:*¤Gò„‘»%@\¿a¶dÍ`åY9a™-}%V2n°^pk€  cà@U¶‚¦9áœéûèùXI‰ZMh5› Ïð4™geµ}CV6qÙ˜LªJfõ|}¥¸˜X/“˜¢†¢oÊ<  ÜÝ’hg+«DVq=Î÷˜ ñ1‘ d½ZKi!«°ùa2žÇâû’d•t±ª(ÉúXµeÐü˜†¸¹•µ"}}·²Å§‡)­É€¾%ÀYÕ²ô°õôøòd&4UV 5Àwcd¡ŠCVªh\B>²ÄHš¶4ƒ†ñÕòçÖSÊZ0<ã~?kÀ«ñD<_Œ˜FI]&øsž{´4é7 ¬dz'JšŠ@Ióç ß¿¡”ú1ªÚ¦­•`«ÂôºíOMðæ Ûà …Q÷ÛÊrp 0ÙÛ«”ÂzIHGø(„©ZÏ‘@̈Éß̪l9XýùÁðþÕ )Á)´*´Ý TެK/”4-gµ}âÈØÊ¾¯Ö†¤U!kU«X;n¶ÂÓõ dúdÙ¶r(*Wdkíª`)ØÆ[Ó3w( 2·]‘mÄÄÉÜ'IÃMôàê‚ìYà)m‰ÀÀ”xÀÚÁ¢#Kù» +C * h+Ë®h‹ïËOߨõšy`Ùª&®ob“R ï*ˆûë_ÿê?R ä¸$ý1.2¥UJ¬P ßÚ# v†/Ÿ¸òéßФ,l S}áç? úá¡öD» øš}–Ô6]èRãUTßøÉ¤È¿­kÔ·Õ„½F¦ X{ÄÝ

]r“¤¯ž­r>(¸™Žl…m­½lºäf݉çóÿš“®h¶¥š¶.ìJÞ ÞEÉËZµH‹ü;oŒl[J€‰us:ÛP8=@ƒ”U%jmÅà•4¥¯zb|ÎÍ ÕβV·¤Ÿ[ÛB¶òÛí´ë¡ÛºðÆÓ‰i<«Úõ²±r»»Ïb¤l‘`šL–J€$€«›ñ‡.D ›ó·¿üå/î´g/«Îê©1,[¦¶0AF•ØÖ¦B˜¸*«°Uh-’u†˜d[¿ÂÏèãº$ËÄ*Û9Ê<gÁ$(U [$¬µ6•èdYµÊN TNÈ9«Lê^-†až&á):l…L0ÖÛü×÷`¼Y‚ZsV¯Dñ>ÕÔVà‘MX;ï\Ɉ]…ò”ùÒ7líø{Y•û"ø»¿û»|J‘å¬6¾aÂV²éb‘Æ WØ0°ˆ”]¡!ûÈiGÙG¨ ¤©¤yÖŸØÑ`†‚ycTHï*bh|új+§Ï¶­ÕV…»ø9Ácx~¤÷ÉÖ+’ùLx nõujXHÁR”Öy¶%ÈÓ6& ÞVmžÍF‰„eç“3“>ŸpnA`U[ØÊ¾²+A˜ Ídme·†Až·E‚=tVxëŽ@P¹ç‹ÏÙš¡•@Ð÷xg\¤©Ê–&¸Í?7’³§@\Êvþ̽-ëKƧ”ªÆUX/Œ*²n…H ©¶m#­V€F­@ž^Øv:ŒÚ¶Œ­È)ºÃÀÌëEs+>%²lóËb6-7|”j•¥Ym“´ÕQ¶*+Œ‰T X#»äúb”‹4ɤÊÖn0âôx;ˆ¸a^¦ ®Ëñý~}QfRÊZÊêÆÂ^ XÙú:5WZI&Vüæ‡1"è_²òšñiÈ•ûÈt'½`ù$3±•C“bVÉlóÌÁœý°Å‹†I¶Z> 9¾hÔ×u¤Z> ™lûÝSævÚß¿–êûAmV?ðô•œ7bÛ¨œ­™óôÓM ãÑHõ¤0JݶÕÍs ¨{Î0s «{¾ó ÀM!ÒJV0´¶•¶VLXmŒ-†@ß-€ñRJåÓZÊl~”Hí€Ä ­d9gΖ¦*x„ñdýÙ€'`ňJ€wà°Uù‹‰sÆ'àö^2¾3rX”¢Ç4*M7/åìÎâ®eÉ´sRáHµÂ–Æã&€kG‰ [aLÁVÀj™H©R‹¼~ç¹ËbJ•­]GK ‹€_´ŒÚ+êvùÐùRlµ&†;¦CÁÓÔEÇPÕ‰”"UZÄ[•¸À󯩧CY±ÍÑZqk©zk JI'!Ž·‹†&h‹Ï?ÁV…&³Ê"Ç«¾ôÇ6ýcK©Öíxkkg5ª*Ù‚i5UóàmcÒçcý}>¨éãÃÕvÀÄDó _ûÏ'„©ÜêÞÆÀ”ÕÂë#i<%B )jžž ÆÊ9 U ŒèB¸ÍÇ!ýCFúÉ2~ã±"‰Ýmgiž|¬< åˆÉrà9^ª9Ó[ÇT•˜3s8Á ;RS•:¦lrÙ@¸ÌxšøNjÊãaÀ¶oCXÓRú¥P9«H«Ÿ¶þÛ&îæ@PS>"‡‚);…­KÎ)«öï U¾Ž”ù«¥\/2)U”5"€›'gbŒ˜!2ÞZ*mþ'}ïÖÓØ­Jñ­É`‚4Ö¶ *Ùs—5Œ8mî Ö¾õÎgàû·õªŽÝß~{TØJðãr´CrcRk÷°²j†<ûHÙ$Vµa¶é)ψ÷ùvKæ´•Mi«JÔ_mƒ¥™Éu: =e>pó´ÅÇô1ïT2ô†Gæ!CÚŠ·µ!½{ư•ÒZq@!NKÁîM*MM‘±Èt¯¯µ ¯‹µá7!=mž²¦JO,`})m 0p ÃLÖn~š%†ÛÊÄm™4v 嚺T5>৬(EVw)XkÀé8ž…  @P(‘ÕÔ¡Ó0ªøpÀclutEizFÞê[;>Ê1ÆSiË®W|ØX¹Ä|0ZT«ê=š¦^¶e³jýáfåôÄ 0'dEØ ,ø`ÂñV­Ó÷m\w¤¯h?øjml…)g‚é>"3ìŒ ewp©>éx§Noe(€.#B¹5g€Œ'ÐêD¶²‚8&³Õ—ùÆ»ªÏ—Òœ™¨’2LT¶¯a½0~®¹+ãõà*á UÄXi²«ÈÁ`A3P¡lgOfÅ/6=¦”ÓµÔÈêBw§PÒ%Iu]²ž…#ðQ‹§!Fz¬<É`LžÕv«]-YJo#r%° )ø(¤'È&ÙH 0 ‹o¶|ꢰm3èÅ„ 3Iœ– ¯–¹ñwœóX9ôRRHÿ'à¤(îDåX¨7mçÑ£@¶€;íÏ7ø† œ¬*)>0b(‹xd|ëHDäºÌŠƒ™¦¤I¯ßÝ!e­«T3[EJÉ0ÓÃx¡ÜÚ³‘_£Óû¾SºîÈž:ñ¿þë¿z5;‚lŽ¿ÆŸlJbšG»†¤Á ½¸¯OÁvn(1‚¦¾€ÄOÓj°>0V‡ò-€7 † Ö1¶Ü2¬]<ÙºdÍŸC†!S ¤±Úò·z¤‘`äÂ/8¤1¤È¿,Ìn«Ö¶ó–‚9‡óá€ÙÍ+‘ÍÖÅjgkmrå¶ÄJÄz5$’@¶M²#je¥˜Øºöd·ú# NO\Ïl‰s–J‰ÉÇ6æHµ¶€hf…pÏBŠ­ð†0š ¤QX-qnVÙª„¸ÙZÛ–¶ÍD#Ø´¥”7¹,¾Â§Ÿ¬ÖÈwN¸Yʶ™cf¢ÊÓ±êN¦„ÆŠfÒYð1ÐVWR¹- öfÎâ†e«¤Ú& ž2 ›`%•Û YÌ+†ËZoõç*¶]cn€f°° 2Œo«àãZ6¯9,ð¢Áèw“ñiZiDX¶“¾Ç,ÕðÝ0Æv«*|íXIi'`Ç©ðX™§  €´ÒÛNfKFÃ?«~‰¢Œ iÕȯCH%u„…Ú¦b("[É: ^ I Sö§¬æÏA•’ksž­¬Öô¢#0!@ÚÒˆ+!'˳ZõB–ÌzJüÿ :9)¬_F& @Z©mÃÖê‘>} ½.4"‡ Óðû‘î–K©-:?eѬ5¥øVœ“*!UÀuQ([H5'€éB™d޹ŸÏsÇû/™gåV±¦´ðÈü­.DS/£è~¬RJx&®) ¶æ©d—o«dwÕTôV¶G§ (³²¤7L¼­ªˆÉòá™IY_—}fÌPàé™XaþLÚŽg–U%kBÉMvz¤hþúÒ“ñ´JQZ¥Ì/ðp±MÀÛÆX:  S°µ²JÀçØ}] ÎC¯ðz[}n‰‘>/½ðŽÐÍ7Ã|˜‹œ¥!+˜ `¶ŽÐÍàɬjUméÛ‹{x ¬öv;7ÉhšŠi«‹*ax«’Ue à4µªêX¶1¬Hb€,e©+9 “H‘ þ¶x«ÊÅZ“Í$%r†Êes¨ÐY(«ÅËbÈî6«z±šŒ2qž¬³ÃªZ°h†Î!Yq€ñȶXÖªJVëd˜Å1ýj†ùÐ ²È÷IÁ"AkLk-6ÝT)Ífë¶ÂùÛÒ;¸cÚÖÞpcc2)Ef*L³-«*ÛĹíP²(sU lÅK†ët>bÄn•˜•0+Æ<Í_ÖÊD–¨]ÊZH‰ µéMÞ£ï v¯MM™œÊ•X•ô”­F9¡.VbšNÐ`4€È6ÌJÜn¿^’NG€g(´mUZÀËð‡™Ðd5ŸÎRk+YJ)ouo»”BW”^6·Ú±í°•äÓà™À ¤h@­”¦y&ÃÇlYAlMï&e… épx­¯ðóл0,‹4eÄ­9§´ÀÏ?Rëž)¥›Å|Ò¨”x+At3cdé÷ûdâ «••—¿öç2‰Ù>Pɬ˜Õ—Æ–¬èJkd-è•'Vhl<[«kqí ;‹,ÒÖ&Uýã£=ýFµÖ=qVHU€3Œo«Ež¶=…NÊŸvóÑ A&ʵàYO‰©K䓾¦µ³aˆüíÏþ³šŠ­Ýk.1tŸ†Ë>ù}Ñôc’¦PËP4º*¼*LµGÆ ‹†>•÷qš$[k%ëBÀªè.&Hl+› S ;WMsËŸ˜FÖ‘â€4 à "gÙdôR«RâŠèý–IìÑÒØ )[&¢¦H`0ÄHxâzy"l+±2±í·[Î4 çài)â¬Èð^¬UÛH¶6²±‰µÎy#TËV à&…QãaÃÀ"g€iÎñd‚@𱪱°¥¤•#ÉÕØ«×›F;€Hÿ®Ê™wÃj9åôœm}eôˆk䀪šsƒ²Ž1 ½m-8÷0¦¢ÿøœ”Ä4vzL—$ÀwW­x [óLÓV¡H5&s)ÛL0oS)úeiòi¥ÄXELOÁÖ}šÇ@_©JlÙ ¬‘lÐt²Ê×B‰m…@UôzuœczC­¬G³©è÷XñM¢ŠrSÁzÕN9ÞY¬Â–1%¶Ÿ6÷êT!¥®ðsKi2·ÒsÈŸR‹ÄïJ“€› µÄSb<n¢y¼ÞRx> mñÞÆ²øFI&M•¬o¯qÒß΋³Í`êc%c"`+[2/àÜ€¶d2+7#½X¤d" ›°É÷¬ik%hŒ¦µ­ckÛ4d)¥ÂzéRáíüù˜™Ù”æç ½oЕæÓéÒÔ îµ& Ìp<¥'¨+d(µ ´•9dŽ7a) 1&µ7 н”P ¼Fj5¡±dñœ×V+EXÊâžµH3Ab±rd-¬Èœ Þ4¢c2wyÂdAy s'¢MbU®  Á[“þÁ‚É™'‹Ï¿‘ÔÚEŪvcëKo僤T+=¼|%e[i\¼åV*Mæ€ù ðpç)•¿5þÉ”‹x©ž¯ã` s ‘ ß5±-kÛÄs«Åæl%>Εãi´Ë ° 7O«ª¤SB­­×^‰ßŽl>+VúñHiZU|„G©‘­ÄïùW…”¢Qô|mem)­Ôñúþ¡ë úm¤]x ¼a`Á ÿºÁçŸ8dG¡S"p5=Θ.Zª­Ú›UH•í²ø ɺ¯n©D9²[ñ‚@‰Éþoч§/›^w ±ëke8 >Î2\k2Œ”€ù[ý¨«<A픜´/ÍæéG)±­èJ‰3¤˜t3V—ÖÌ­é P£¶ü10’Ü0^5o£œ ÕœC‰¬ðè{X®1þ]w”$Ûm$[ôƒƒM2ÑL»ð°3½ Òëø€œ“Yu/Én&HL2½2Á»ûÃCmÇ´êU;æJ„mÙĶ€,RèÂÊÖH.¤*†€U9Aq|ïÍ7LëíðyÈËŠ´Ã3Ä”Åä¼K¨Ö<°Q‘ù«å@lBs²%èÓK/ÈÎ㼯eU€ÈªÖó!h††´ú±QÊ*·@žãmKµÚ&Þñm…Q­ëU†,[«±ã‘Nçò4†ØSYy²4kjK¶Ù(ïf2™RÂnµ™1]쀃pHlÅÝ;`Ã4ì8xL[«-=†Cb«÷<Œ—2·]Ö¨Hå¼°¨ož4 k‡q3 TϤQ1B6çÄ‘eù«sÈ„@¨µ4aÊwíÈòÉVåò;£#{(«ÊÊgA-RmU‰½?H‡U8s|_N ãÔîfþkÁwi½“¶ŽS¸Z«ÖÊ(…ìkAÖë4>P­”0|κÀLzÓÁ–’a>µî–êÎs|X“­É¬H†M. `ðá<Í`Z33$;‹7|¸.<{ *´­¯Õ—|ǧ·%Aé 2U…“åÙ´Ó=n&Ä£Y¹,@À!¬P—Õ°¨in­ºH%c+rK\йˆq‡f kEÒ÷–H%4^!1YGÓ ¾l[ŒZ“#Édë~åçâù[1²ñáÆ˜¾ŽJdÍfU¶f°æŒñ»,,<;)åpGÚæo[! ,»•¦ãäÏ!·Ö¦‚R_˜*X¶m2dξG¹ñÍÀ ŸgUøRD©†$@°^ú¿>éi8KéÞØH>} ­Py²ÙfÞ®TÖWœµ*l0$ç¾Ã ºàÃÍÌ– ÒœVO9Œô÷†Z,F;Q»^% 8Ó°ÂГ5?RÈrë¦$€A ¤y"™[}HÁÙþñ×_Ù3"jmb:[:oŒ²Ô@ƒÚªâ®‡Ødmñ˜&ƒ‰­ôÊëE†)êÛ uäo‰­‹oÅç_Þº¨z H­RÖ°Š\d•¤Œ´åðÁÈ”À·è,Eæ{Qh¼…Ê‘B¡ $–ê6à|fȤÃbdM"`¤ò%ÆD¦„› 7ªbø ‰Åû$ë;ÅTÈR°ñlui%V++¥ª³Dö€0+ äž5F£Îȇóæ,•,›?ƶ'ˆ¬/€|#·˜°U`taRSkšw†dxd˜ÞçÐlNŠqFWaid¥Ì´ÕH•+ªŠ!A·M l²ÜÔ27ìó5%7&¢Ž)÷P"›Ê*[ä–²T>°*X ØJÓÚ¶©`ƒIÀ"$l-tik­#‡<­ùX¥\É+î¼È¨Üš3e¼5à6libšãþ#gB)lÓ¯¤az‘j””۪࠳T›²5s‚4Öý¦ ï Q д· 1š `%)µáÊsK¯dÙë÷ñ\¡,j¼-åM’säd=8)2)«3zv¾.{iu÷Õaë=QKÖêªU÷þ~úð˜üõ n! ·²¥ªåó¾ÝÁÄ_'š­lâ1œÕØ<ñüÉò÷‚mì²:"™Pb(ß2o-ׂ^ÀÅ0L&Žââ€Áw‡:Zã+$ˆ—2ª-1¦StQ¶øœÊÓô°|­ùÛ=Rl­°ð çÖ1¥| ™,0œmó'ƒ­‚-“ô#OGæ¶1L© ,øÄ+„¥b’ÙR.ŸXPˆÎ¶j]¯Äô•ÂT|¬õꨊ!ŒaBc¥a.6 ’ÌVÐT«Q· (i6)‘ÒºËLc@0\aòGšö%Þ>e>z¬`b-L.hˆ•Ìд&&¨Ä¶¨ ÎP!«ŽIF¡Tþùôu—ÀJo%2't1ðÎcR&cÂ<«ºÀÛæÃhÅGrbÎ÷…ŒLì‘é(˜ ¤ÒZ4 ü¦ú¥¼'"U—Êù§¬…µyYaÄÇýûÓ³ÌIYGUƳeÛm{ÜxníŸ&õ¯ÕšU%²ÍfUUGYn÷¸Ÿ§câ01žÏ¹µï2<ÿg@‰úþŒ±¥Sã…X¿fÝèB)ø–M\3n¶¦ôH#%`¢f"Ò¬™¬y0Ä4ç ³ªªƒÙN¼ÚÈÊáYˆ¬)Aîƒg`¤ÇCæ8ºÔËi I#ÕŸšˆñîôù`DMV­=Q[](T•=Œa J)L%{w `$ D„“q6°IlëÒ¹0¾}ˆuÏ“¬F¶MXÓ|º1Xà•[“anÛóGJŒp3²¦5[¼ ±0R¶¾û0ô©k.d!‹· è+`‘†¬°±µn+c‘³¾__¡–@¬‹Â†$¶%ö5¡‰¡­¶ádpYkŒÈY l$ô%h[9™­•#vXyæÈøJÄRuI|,nØ.;rU]H‚Z7XàRº8] ’>’0M—œU…º“ÑÈzîž¾ÀËâÛêHã­ÍfíËRÖ ùVÒ00å2µy6•låÜd…Y¶­NA#š‚e‰a“4 L†¯KkAX‹‘¶J„y¾ÉÓEhŠÿÔ? ÉG–F ~šð@—ïcè\RÚ·o3/ÃNd†® ô(é»+À<Ùêh˼ 뾎͹T·Äªyªµò‘B; ò/E£D” aÞI½0ñɬ·è\E¸{€1ë˜[ú’¹%æé¥ŠR™—í8¯³Ân©Ù8ÌœIsÒ U9‚¨çTÛØeÈ ž Ó{p˜ºã #%zÐNM#+šÜ¶a g)zƒÅøWtqŸµN¯¤¾µè­\UåeáÙ¾Oĵà¬$g%^ÈÃ4•­ n0zG²eX¹B¹1\fN|óç)Ó(ÁSöÎÀTk}‘ÎBc¥7mGãSw‚×õP[¸hŒŽó”p×F Q;c#ÓÀJlǸ-º"©j1ôò·Äæ7R¶<·J®êl³íZ`V M&(1­di‹·V›a…Ö_À0dÈn¦^½{s8ÀMhÍÒ<5²fB)Ûƒs@$=ЩÛÖ1b‘ÕÜtKçÌßSSÂu„÷°àJ¤„^ÉœÂÿQZôÅ; YóÓûzäIÃÁZ ¬°Z嫪›¤°•Xª¨0†3Ð{&ëñðq@À;äWb#ˆwÀº¬£”©œ®;I ÝöÜÁR¶ЗØ*â)»@[^&É_Ê x£†Ó¯V Ä#µ8èÒJ&+Åü Ï$püH@p AdUV)÷ÃÊ `uLä>¥uG*,”4Ü®ñÏ7`ž²¿ZTHÌmØ¥),•!,ÕÚkbÀ<­L ÓI­F²å©<]l­iÖ À¿ô,8 g«ícK +:Py½NËç…!–½òÏWâl•ËšÄý:+ÔQØAØ×†F`RÊöªKudü²90më6ƒ0åoÚ² p‚­cøà1æoEb˜;Ì_äS¡T%Çýûû¢ÜÃÚØ‘WõùÈ(tR4‰i2¬\v)âÖÚ)ˆ1½­!Ý?ÀHîyWÝj¥º7_V‚LSµ ° ƒ/Õ„Re9ï̓Ák-r«Š|ƒ5FM)#­™ð×ÑjlÀ¡˜(•›;¾Æ™ÖÃÊj‹_ ðaÒLpTòŠs¶"`H†’­unUý’Ùö â+éÙ£í½ÆöKža2¡…È“Æ$V†ÜÈâ“å&UÉæã»ÊJåiÞvM…ÙÁÈnR‹Á¤Ž¹Á;) 0ü3¬QÊ­Èá>ËÄsSn†Í–U­d­z5UÙ¥”Ykèêè·…Å™õÆZŸ²[ÈV!L¶v™ìUw·RÊ]u…–“Õø:¯$Ð`pÎ uÔ P…·V3> JÀuz˜(læ”™ )÷e(¥E@ªB8=Àd>)™¶…B (1’U0¥*!…Û$n^Ó ñª¬ª\2RëÜÈ ]r&# ì“…Ï Ëþ ¤˜¶Ä‚É›¥YH Óä™OUš <+¶xcc:Æ»”O© 3©V¡¼*¸.õ Ç7Ïé“I)”PÆ"«[> »Ø}j:7³×HŒ‡ó—ò…Æç}4R”õJÖIã•Û4K1HþB÷Zj­4†´Š†h¬éëk¥÷V‚-h$>¢Á…VJd/$Cú}+1ÆÁ>8³RųF3o«@òTË’ d¶½'m•*±XuL¤±í8²˜°ZÛº¶fõ¤Æ3‰t4©lë’óªÏññ ‰¶ÜŸæÁà1jésê2»^Y&cÛ˜º_ïÏ÷Òqÿ$>Žb)d­ €I\§ÏU }y 6+X¯ó» fÒÚ÷Ë„ÀXÕ¨WcKVïe‘¥&™mš )»e‡ÄÛŠ¸á2p¨VŠÿZ e]J]Ô£¶rŒµÆ×”Yëmuϯ)><ÿ>®0 %z¨€ÁNïo_2!u&»W*ÕüªàR.6[ß9ÃúšIÃ`àZ3´Õ²ò(m¢£GÂE>:*—ÒÑ£‘6 IÉÇzzܾd˜s’ïƒk+;ó!PØYaô²5!¸yúƒo}þñµFÞV?KÎVš|X1tMŽ!¨,güK¯—{[‹ôÜ0#›“`$]zvñ #«#Q9 ‘¬­ZÛ0^`šo —ò ̹̆'ÕGJÁÛKÏV4 {2Ùâæ?Ëäg úÆS+f…¯ ÙÀ¿ WTHÙüV¼QYe+;Ûªl=WQ!@)ºùZWޤÔÂùâ‚E“gKL SfÛé"ówÕÊ)½‡§ÍÆn«m²²ZJr~¯_ë È:‚•Òê ‚î ø€50­9¼UI) ^¶%&¥íÄ ŽËó¢Ä“ À è8¶Ü0Önþù•ÏQb+1A>õƒô,ˆàóW%¿JG7 7%ÈY¥Ìgkn]o/=%&®3p#ÉÂd^¡ÆÖ…8}í~ o«c @aJi”Rªùð$@Ú6@Œ·r@Êz-Éú/ŽMÕ IežÓkl¿7(çVd´['@IDATÈbÛ*ïXS<)Õ€òºÇÔÚJŸ¡,ÐTÆàУïx&Jú÷Ýëb<ŒP«£BÖÂ7°òjc´Ã3Gªzd9Äð!î V)|_þa[‘ÃæÇ$æÙlÄ|² ¬K)c$îsèên‡³($²EÛláHoßWMc¸²”ÍLêU*Ù|êUIb[‚Ú½Ê[7™­-¥kô š<­‚UCæC¸¼rb[SÙ¦Y!²,æÍ&V[!ÐüÄ“ÕîýɈ¹Y»€¡{³z¾µTÕ:MØêÍï—{>¶Í°Ù& ûÑP ±Á«*2)a<FX›p2UW~.ïöºüþ¥ÿ¶ýöŸCãeã ¿Ì )j—?+[«r) 57šóæÖØp¥á€—àøÝ2R=\e^V«,Yx£”eK _·Óy Éxg£g"l_L&kï ïøª:‹ZŒP¢‘Àp¨OfEвÙÚÒlKfëݲêŹï,@ ‹NMü’Üš!àæea#Ñ—j<í+¤š0¦*å4Ê¥Lr+·FŠ&i[€FÖC43[@;ŸJ‚ÆXý®E•Àˆf°¶½~މiZ«Z[óœQ¾ŠðiDzÁ"™è.0pãÊ1‘yfhHÛ†)‹§GòÄÈÚÜ*1I/vþMr|#Þxêy~+~þoc-ÒЋ—é+µSð¯Dlmf¸SÈbˆÀª‘~Z~ß ‚RÖHáI«š-ÒÖVa¤ |_0Ÿzarãå–aMá€*Ø)ú­Q‰î¥:µr¬×@Um+IÐ02q„xåHʶ» cÄK ƒì)”RV½Ôbh¬&ÄHY­°.lßP»ˆ§ì®€14°vù´ GÖ·yRÒøõÅH~•é7 L2OÁAˆc¬B•µ¦R ;ìMžRUY&ïÙ‘¶B qó¨uŠj‡ý! T»ÖØ7^ÀbïLµL6ÍLªMCoË¡”Ál[‘ù'ëZ`ÙVÔ¶”í[¨Öa1 Û4R…BÀµXy‰Ë6@)«Á&èýšÛ“".ªµfŽZÿU• c+e W²-&ÏͶñ‘µ¦ºøÕ¨^”®HÖÀ”Èu¶ô}rñÄÝ}¼wR¡­Ú·ió´Ê²UµÕÔu -dÏXß¿e¸IÄB­|k©kpdÍÙÌÜ|ù ã×;¼a8(ì,€måÖÌ)èBL[LUH×¢Á€óOôÓØƒ÷õ'mè:±°UfÍ#ŒŽì¢U &ª¬ë KÍ„2k€‘Çè JU7ŒLÏ¿œÁ–LóH­*ñ÷žB‰ 'ÃTX£œ­5"€ùˆ”¶;/RíÌ¥lEà-ɤ»ªÖ¶¯í²Å0ô8zk‘¶‚~+’á¥?ß¡a&B*%ÂIe_’¦ONÃH 3 J+>R-‡Êoþ,¯8YüÉS9²B“3ï[mã–¦/h¤ªõ»`z‚CbÊÌùHEÎI@Ü$«9ãQjJŒTã!¶ÆXÙ¶òìùÖZ#‘§ƒ0)d‘‚I`奸ø†’¢7FÊuè+‘bT…™( ÿª¢©D6Á@¼uM=ÅÖ¡Ìï+fîPùt{9䦇"†صô ²sUKØV#V4°Mc ìÍ3ÒÖlL«ÂV‚îÄjó¬W8‡ôo9>CX(ǘ¸IÌãu¿ªÏ›CƒwV[ØMÚ’Ùf»£!Ç ak†Íoµu‡ÒMb+µ*ä‚0¦ãT;€Àj0 ¦em5õ6ÖÑ6ÀªCù£RuT´m¤­Ug~ë>ŸMz¤^½iTÛV9*+F40 u‰sA )ú¥Á¥µl<\!Câ>¡€¸—ÜaÉz©{]ª•Ò‹!™µlçjåü–„« «Ê™X¤s!çÉDÔ…  DÄ7‰Õ¦ŸCƒY½~ª(aÙJjêø¶°•¸50F!=ÒjHâ&RèEß÷˜©Ø"À•§·•íÏ=0”Bª•U¢Q¦HOc«Ö– Za )`°X9Žo R(é§3± `Hˆîßœñ9HQ&s LÒàW^  «*kÎóW“ɚ͹*Ä—ª—¬ê¶ÚJ-0E2µ½r½¦Å4­gÁŸ,=~&Àl‰ÕšI&ú !)û "›íLæPU¼^¶Å˜0L½e_^ê=”m­iê‹sè®èŒçoÍYI“ÔT¡a¬# ¤"Ãe‘‚g.:œ¾•€^•ŽdI .²JF°šÓÖš?,ðP«K[+\À:ï­8KG®pÇA†&€#¥r¶p¶‘æIIœ'e ¦“*ÌAJHÅÔ³ªdV#‰ø[ô©zðy™Ê5õ}ç+©ëêcœ²¾Vóߟ.˜ f*¬•s_4¶@àÆ«W³½å dëEÓeÚ– ðÌ­-%Ælõʶ;ì,x$+¡$ ø6€-­àé[Å–OUײ7³ÚÍV-¥¬U_Q‹iQa2†dôxD—¦”5 fµ9X1F}ù¹ÌÜ6`­2 “T’RSAÐÆ {ÖYÃ`Èx&øVcûìã7€rQ¡*¸WOܣɤû×®.€hBʪ¦±åFÐEåœþt½}i0ÖŽlí—6Œ‡NÓ)€5š^ _»|#¤Xuj€&µÀ²Â„ú¥` ­U+ówRï0sËœ²Z…Bk|a0Lz²”&ß KÁVOj§È­ªÜJaØ2ÉÜuÉr³Ö%>†­­s©½ÏEåÙ‰1•Û2™9Ì![…€ ¤ïgbÅ÷,8Øö|r†9d &¶ ­Õ‰úîã¦C¯ð¸|¯´mS@`l½ðá¬0ùËb¤¬™¹lUVŒ*`&n«PÀ¹ÁY ÿÊÍãÏ1²€õ|÷qrgÿHg;k·0Ye;CÐ4Ê¥lŒ¬°Ý‚FÔÀèØ¥—u€â¨Ÿܽ¨ !·ž“Ü—ƒ òÔ_#5Œ­”¾}%5€UVª©ª}RU…Ä" ¥¶#+Çt^“t!HVôØšðÁ°Jø Äö¶YEÊZ°Â7^ñiâ'% æ=yDµx¶\¸IgdΊ Ïkµ]4RœáîÍç9T÷À–¿¦Rp­ô»g˜ ™i»¿C÷â6!iT‰ñõå¯#eóà/pÑ­²"‹iZ•#›¼B|ì,æ©pΪœ¢­•RUdnø•¼©&ñàg‘"ëP¹Y›¡Ô<é¥""ew^ÊÚ0@ULÒç6ÙÎ’À‘+±bæC¦¤gŠ[Aã/€-LÔÎÖÀéó™3Yóï2p¨…õMH ˆµ°ÒÔ7œ fµU‹‘uü˜UùÜ’'†2ŸU/F¹l/<ÜüR@½8Ôˆ!RŠ¡v²Nj«6œ>[kïdó,eËD°í&a>Ä¥€†áв4x+ÃXÛ*)Eg¤I&%JY» ýNäK@/z¼òÞ‚¶•Ø ˜ŒOæ«/èÍÓî\ŠR>p=ΜAlm«\‰-O«m⚆9ãk]#ÊRu׋˜–²vºp2+A…S"óð·UέÀçoõ Ù¨°˜a%ͦŠyÝg¾ºl¶d‘­•ª¢™­‚ iݨþ®ö¶(ñú„R"1ÙVBƒ§Aö1!›<™î˜ž Œt"%”¶+ û¤,ÕTVY‘m“ln~ú UÑ #al×kµ²øf4¢DêÞ´)c²i’Y›“ÀÍhš¦ucó‘"@bt¡)…TÒÅÔ%gUëÕØªÊšJäÆICÐd²é+¡Ä„‰›!¦B+0¤yL)`Ÿhµ4î6`²5ÊäÊÏb+2iÛl5å ¸vCÒSÚãݽmŒ•Ú´4”Rmcfx·jÁ&ã ØVb‰©]—f[9nZi5@þ ±­‹ ^YïUƒaÖ u¯‘­ˆI‰lòÆàxxµVÛ˜ŸMÕ›@“Ô*© LÖÄMïÙcd»e2ÉcÊÆEôu´¦ß¶îÛ¦¬5[€@ Òj©•óob¡‘Â.ÂúŸÿü™ÀÊDaþ¶@k]–âTu½Ï0bþ€½ýÈ?qJVRBG«‡DÜíahl‰¥®å9’d_úþÌÐ{ßwD]¬”ʵ¨iŸR<ŸÜ¬½Ê]ˆT…ª¤nšÆX*½-Í¢ì|hDV¥ø˜'Æ$Îî8΢Ŀ?ºûI°w¦‹bE¦WÙùÈv9øZÉ€ðägÊW k+&ã£0qÆ0È4Hà¸Cö5OLÖÌei7a÷éø’X6•8}L­HLnV¸­‡‰ËZjáÑGZ« ã1÷%Ë3ÕÙïÄRx€yëÆÃ¨5€U_¼µIÓœx'…{"µh`©¦ äŸY£&è83lžN1,›ÀÚH—øùì0Ä‹œ›°¤¾Vn£»/ ÁZ8‚ªxkµ˜@ßó…çÓuÛm÷›‡¬vߺŸòÌé=šÖ/è<>5Òɧ^pó4m¦²¢Áfó¡Q+”9`Èr€¯Ç™V6U;Ça’ò¸<7Ö˜&4öÍÿ,xÁÅ™áÚÅH˜³á—ÝyÙæÓ6°l iÛ}*irUôg‚ïRŠÝIítO£¶ª@n¥d•#óœ¦ÛȪ§™Òj0«r…"+±FVJú´:Nï@d³Ž”@iÎÆ&¶MŒÖQJ¨ÚÁ²"Lªª×¤Ùnݧ¶òÖ<­¶‚aþfkkì›9¿o”²Õ¥¾cŽõ÷©Qò!Ëæ6Ã:ÖÈ-µ¬*¸¬…Ï ­k„™+¤¼}~^EÛÊe }›ä›Ock-x6!±ÂÊÓD†3 4^× ×(«Jú¬™¼£YÉÔÊÂÞ"äÖ1™ð¯ LOÜ œ¥Œ$­5ŧd׳!ý^ä'²ÓVb¥L +bY+œŒí÷,ðMØ´[]lÉl+I™ÒŠŒO 7Æj_ OAÓØiÚ&³þ²› µ›R¶ò ´Àà=ÍôJŒDcP -ÍÌ+?çìq0\\×cËÁ=ã‰=¶ÂŸ¡îéä ¯T&Jzú’©æÖ‡WUV”ù¨¶MÛfÎdz©1Ã)7O-dñZ[÷]ÊGTP^â,Ê7ž™…K#À§Y»ØV‹jɤü¥u‡uR|(1²@š×áÿ2çY +Ì9„ùÌ–¦I&pp¼Ç ôhd«o¡Þ ¼P+%šM€l[ß²R9·=5ߪJšN¹,“¶ÍŸÿduiÕo°=¾J¬xOJ¶u9”B» aåÝ? >qµ²µÎŸÒöõQBóêm»4@dR;«y*…"³ % †¿g!ÎnT# sßáFT•…7yí’yå²úÐg‹Hš<1°Â€Õüa…Î%+8ÐUe8¾V…DšÖ+o$V²ZÏ's+R¨’0nÏ`@þÙÚê˜?Ì_}Î^{ 7 Å&$cŽaeåÙÓ UY§OfKЪª±ðÊ'+þ”‰eÍFfËÙ¶¦ €ñiµÒôAÞ—9[¤ %8ϹRHZñ…ZŒlÆÃu7öReÏðDþ§Þе§k%ªqFø¢{Gî ôi€•(·uì¾°GòZ+1 òI6϶Ö&$ö$ò!V¦,:Œ¿öŸY8}Ç!àÀÓÀVÏÉÀÍL › 9á×™Œ••ƒÁª [‰‘çdÊE§\_ AÊf +üqz8sƒåÏA¹Ù«ñ˜&Ùµ°2”z©Jm@¶57[!› Ìd%¥VìJaL«*²¶æ÷Q8ÿ4øybêE³(ÛvÆ]ÔR …­StdúH¿,ò.Ùe6lZb§È„L9<š˜üó‰a’›fî¼ÈvO›ÐkY zV&Èf¶ZÈÖÎÆ» ”íàg ïY^“JˆOŠžÌÈ| g†¾ñÀUø‘_•†‘9“1Ä·Î_6†@!^™`+eÛ„nÙ:>LOf;~[)>™Ãiš?>ß$ "c¬È 3˜Ö—€^#ó·•Å‹µ0· amc†SÊ µpJ‚EY¼[ÚÕÉb|(t1 àzÍI€—·µ²ªpx—SªGÙ“Â(  ¤À¨Ò¨Èjݰ[ÂóÙ-eb­œƒ¬mU»7z…È@üúµŽ±vLVæá†áoíÑ0±µ’aÔÂd€iM¯ÜíýjÚ¨ÜÈÜpJ«­`Ø55o[£†¯uµY½}ó¡ÏjÀ$¢CÑôíךJ»€µ›äÔî=,œ’GFP¼Ç8¾Ï{[úHbøªÎÅÚöÂ"7…f69P£071Y[ù§iÎRÖÛá´¬9ÈŽ€T(°àUb„‘=ÐÄHzáõNaëB:ý®ñ O¬4ĆÉítú~iñdµÀ0W‚·òq±²)ct¬øÎh 7žØ_•gþÉðþ^Ò¯a‚餀r«¨‘ik×)J­]2J¯)À°SHqÀxúÏD_–!2}ç:ŽßS•)ma“óìhªÎ‘v$½ý«šU†$ÊÓ ô¶·%]M[¾½ 4¢Þ@åÙ"a%€¾²¬ X° ¤Ì„>²¦ô¶¥bÞ•¿È'%qÀŠWX¹S›áÜËýõpÅM•Æp«è©ÄÈâyÚÒ‹™#¹ÙÒ0˜jÉ`…=lå‚R¨4ÚÒ{]2mUM†‘ñïʹÁ’Y•À¿íÍœåŽóSŸç›Âhš¿Õ‹a˜†·uØYiÔ'¯ª¾e{d;H÷\Çœ1U!µ«ª;é~Ú²MœŒR/¡Ûf°fEãºDâLÂïÊ#U ÐóZíJø#U1tE¶îÊÚe‰i´®©-MÛô~ö·R˜ž‘ãˆnúS(±Z<†­!J…nM_²’­6AÃcв³UÅÙ´󯜞ƒlζ²¹åüŽ‹Jhàj·ªB²‰»|)¼pü~÷‚ݽ›o’&œ¸?/9ñ¢ìœ &e ðÕ–uÆxWß–&<…Í–¦ªœs#=ĂPè,Rdµ+ÅJdұ僱ÂÈÁu_!Á曇@¹­ ¤Dd&9(Œ”ÀV¡ˆ$¦„­á‘d@…@AP   1ÿµçzU‹±ÇåÐ)¦ÑBùŽI_ Ƈ…LtjnLè…¬m¸• @ ¼¾Vá8fÞ¾±;ïÝ9mõâ „ CÛÜð aݳª5†VhT%uÔhÊ|hš¾.X´xf{“?Kz)2XhñÇ?ÿùÏ|£ÊiŸcd÷nEbrš£‰W¾!Øv³ »)âæÊª5¦[hŒe¼ïw¿ë¥V;‘&XHµÖÚ§q/}÷ž€Ò`n;æf0Y½8lþª¬›hžR Pf%`>‚̶Ж ^™”5ÞZ*†@Ì!OŒ’”É¬Ä ¬ÂA¤jq¦ùþH¤Ì#›Òj070/ÈÈ”Ûv–ÎÅ g5 C ¥gÇ™›mö<[mW‹µÛ ºä@)Ëg_Úô¶], ’IÁÞC‚Z˜S_$FÈÚöZÌ¡yhVUáÊ ˆ9sÜIlÕÆóÇdˆÏ$Á.Ù<Ä3·µ²ÝŒ­˜>ÿ~”À9ëWÐ;c`>)×7gkc+ `(E&/Ÿ~kƒYµŽÌ'¦ýë…ɶ1 é"{ŸZíÞrî€5 tLk3WÈ„@Ø&lš ®)YofY!«¶yæR& Áj§·KVHÑ<…-cmû®K‘ñéN`xšõ*ÁwºÛo«È|º>"=¾-À¶ZÌø|üÊ!å°& |h¶²ÄÖø¦Í¹ñÊVN“,‡FUëD‚¦^e›°®EªvÖ@âª`¡¤5'¦Áhm ÎhBŠ&Ì  ¨„R„­pšzÁ‚OÙ"kAolV¢ªÊ$™U4ÀÜš 8&’a3 u‘Ý$‘±È‡x#sbš[tŽö àœ­¢S#;iÙÊ1²·ÛyLHz«S,°õ˜®Ù;«pnÖ2Ló6]ª^u!0‰T`8Må&´…•4­a”Ä—2g†m‰‹¶Ä:;“ÎòÕ~þ·9+!^#@‰¦~Sï¤ X¥yg/%Ò¨]ä©cžÞ4JÛ¨$,[UV«EÃw¢ºl†Óõ~dd‘p3¨j[ÆWU—üÉ+’2L¶¬!Ë*Ï“Ò<d±V’C$^¹Uà›¿³(Ïa…m‰»“xJOÜ¢sLzd+¬t²"7U…1hàÓæû(GοiÛó±æÙÍ´åÀÍZÓ”ÛºR²× Y¹!»yóUÕ JÜéÎ=‚²d1­4 ­iÈÄRñÖñsVB#[†˜&Eås ™-MÛ<)õê›ßd¢«P‹”LÔò—mŒÛ É“IÙJl Z+„ÕÂÊ)bˆõjž ’ ´­;ÆVj†¿”¢,¥ˆ©oƒ!Ȭ2Ç+,2;])+%ÆüÙ~åçZ†«]G<¦­rµšÒ×=+)á\i%ùØxµ ¥ˆ­¶ÉYQ&³ Y z“/«P(Á#¥l«ÂdŸFäÀ>åÊY1Dv4¼°}[TÕ:·ü‰SÊ&¸gaÉùüGÀ5®Y5Y`Fd¡‡T$†&¯­·èó“éß,*…w~UeR—¶° l­æ/hv}Ro [L<Ü#'n©Ül™ðô º7Ÿ?}¼­ÈD šÜñ]^ -ÞÖÊ㯠ý}jÏUJë|ˆ€ì³j› CÙ/yZÐ ë•&±9|V¥Í£62+ÁR•Ь ‰‘@[+±˜OÛ ß’4d)çl~}e»L@ª¿YœÔÊGÖÁeáj…­˜œcÈ:¸5qM[iØŠd¶ñÏ9Þ–RtÕÈ…T­5s>M•^k'›½B¸W¯—-Þšs«mÇ!™t“H2]:nò[q²ùŸQ¾Ûµ-«P˜ÁK»sa(¹‰aT…4 o'h+Ë-Ÿd¥0ΘÀ$›y%óW(Û…¶œµ#0Fù¢ª²”¶ V_bÌî–VK³ \hTG𯰠[êóáÂ¥´²ê¨ª.ÖÉh"˜Äá|ÂR¶Êï˜?o ¾kl’"1j•جHŒ‡ËÍ–[â ½“xчY¹=GŒl¤•Ã"2¤­0ÞŸxí0·Ãý—î£'óÍœXÖ„Ä…µ;^Ïç&íì¶Æ£ü¨oèèe…wŒ[“¤é\ÈîÁª;%« Ós°´ælm6cȲ²î‰”ízU.+¤¬Êeç„+ù_ŒYdžÏ3l½Þ?æ¶È|¬ áë­*CL“gR ÿ![1sk‚œÝXLæýÂYùëù™óa›³QÉê+%ðVn@w•²/0ÆÍ[…ZÑVÊ<È.ßVmw‚){*¯Œa—`[vbžch’ñé¡+MØýX…R^ﶪ4ü›œ@¶îüûßÿ¦°7¨Uލ ÔRÈE§-E&J…k Dt~z‚~¯5\[ hîj­ª¬LdK1jÜk‡„ñË*Ÿž¡­cZùœ±¾¿BHk3œ çL0¶YqÓQØ&†»åɲ4É”Fd»‘úôº¥lÃàf¢–-d¶¼ìfr{jÝ9½T툛C&d1Û²HLšÚY‘VÁS´­¼Uk¡Êן̆¬½ R¶õª.H«˜Þ)l‘Í“Þ6ðkÈ—'¨è¹GnK_Ä(¹ç;·­»,¦.3DÂÈ|‘°rODJ¨ àkô®²ÕvŸ +·Š”Ön)CÙÌUå³FÓ7¤ƒI‰ãJ1€ˆT²a°Ö« ‘MoMÌPÔÉSÐ2l«ðȶÒs QRíLlãs³T½…Ä1”‚Æ– ¼¢˜™áZëûTÉð‘€r+“ô] ^t·²Ýóýœ%¬$l £5œg#%ãvUçÈ’Y}|0R—¨Jªâ‰”EΓ°eëke‹ Dbè­¶E œr¤Ö”"FÖ®”4@b[ba‹¬ª“º@‘²¬uçcàÐñ1ó¼ÆÇ™’37 sÓ? ¨ã¬æŸ¹ìÆH™,²áWÐ ­z&+|JÌkÈ$qR…Çã­dgb…Ešdª– 4'>qþRñ§V wp˜ÞŸr½€ºô¤l‰×7…/€>”J¸%¤`kž€(‹Ê­1V%⺞%3 l`|+7gIƒ¯Ê[±Ž”¶j]>C‚°FÊ1Î" gžÛFj*d¼U ½`¸ÉÃWÅŠgd  ÑÆôq௰lHâz±f šE[+ÍÈô1­üËN¦„¹-°h0]Ëô™ç@Ù¶unÄ r³ÚÊFZEÎ@΀F¢uߊ4»+‚02Í;’jÝy]¬eã7RªìZÛ&ˆùè5’³T$p¦¼ûcmkž]Fð숷jMoåàoKÜT€”ˆÌd˜XÕýFµ­ºKýñ×_MÍEËŒ¼ýï ëŒ`QWåakY8Ðáaã’[¼¶0“˜L8d[3YšxC™¬-,Fø˜sÎ;`$-üP”jæÊ¥”$Ãtõ4e­&±M–¹õÎ{Ƙ”ùÏa%Ú bUzõ“»ZåYÊüÃY²ïOYd ¬ªyð7d%¶€r+Pt-O$÷†”’Å—R"ãå›$MkÃPVâ¼NM†iT)&Ùdm ˜ÐÓˆHkÀó-ÕÄ0ЀmsV^­. Pa$ŒLœO2Ù’ÌJ)åÏ9ù¿&²ê•O[kž‘VJ|€Û[RªFµÖbÛpž­y» š _ ºCµEY©Æ6X岕ÇÛæIØVH“ln)“©¸ ±Ò§ ÆGZaŒQÕš[áܶN @½cÖåí›9&Ò–þœîU±*¸ÚsîÝ*0pUõ¯f»V>&БMh»^pOÂo0ž‰3—â×±aTa6<,T ²¶9c¶­jÓŽÙ$€Ø¯ëù^õíÑ0 žLªL˜3OÑ5Øâ›ŸÒÙ sÃcZ9ãm“¥ßéhÌã >YÊ&©DVŠ ÃzÁ>ñ+ DZw"J)†¯r²Í`.ÕÌôjñ#Ö”†’@—%›mMm×:œ'Lo%c‹k] @†·^ɹvdüÈ@f‹_ SV>4k„ßçl÷)W¸-}¼ªµ h*U0%~zx7CgŽ÷dèA—Rø»ä|àĵ°Úö¹KiÍ0AgW%:£U¤!¶/¨ÃÖZ»ÊmMHL0mo‡ó àt+,Õœ™„¥ú‘õeȬÖ7j‘ }[µ4 Ýd…€m¤lžô–F~硌‘BZ‰[•g˜ Ã9dÎÁ °ZÿXµ«kªÍ¦„@È"›­œ3¯°04œuÄÀ‚¾ˆLÖTÖcô½Ã4dxQm_2M«Rª!=;ãÁÈþ…ù;ï¹R %Ìß*šÓ<ðmûi¹íJÝŠ#ãS(l¶Ï?þñ¨öt «ÍÊÔT#¯lÅ'“r¤¬”¥ÉúWQi0™4=ÐÜx[­•—-…gR‹ÕÖ¶ªâCù:0¬„l)dÏØ„e­µÈ ¹Bžj) #ð²¦ÔVhI³í¯ÀË2Ç3WÒØûg…¶•P’mUø²ªò©‹‘©³&Øq|A4ö†Yy¶ø1°rx·iX]»UäCËZáLzôMU#YÓ¦ÁÐË %¶x…¶€T>îA ,‚ÖªZ#k1Ù­8 7²ª¦1Þ¶Qç.¥ ™˜öòÓ›Ù´¯'sAYÕ;¦F¬¬P]˘jmYYmÉXYáÕJuWÇåû)@ŠJ|8HÙ*OÜH“¬›@Ô%+˜I|zÛœ¥)-€úÒ4l‚ü­f¨0 YJ…”+´…‹°nµ‹½®g!-ÕÖŠÑè²”i¯cæ‘2+,ÒVÀ{9meÕÖ®µ¾ÝÎY:i¤õ:}b¨ÚAãkÝ+Á$ßÙm¥l™ˆÊ5¥u—øð¤©;†8þ=±¨Kn­‘UUŽÇðÇœâ¶z‰ŽP6·°µwÀ›M ±Ï”á1œ²-k `qÛd·ç¹„RtE¬ØòÄø²õ•HÓTñúܺßÿÖJMeWHÿb2z‘a½0azxÛÈ­JÖ%å[åt)Ø: u|ÎÔÃ6·­eÕ.•aÝá Ó¨ªäí·•" NÃÁm3”µÚâêq$h«”ƒX)k‘•)R6 ¦.xàJ>šJ¤`+Ȫmo †ÒBÓ¨‰Me›¬Á8¼­’Hæ@¡ÀðÊa«°Mi%˜nfûõ8åx%WuYäéýý›µx3¤ÉY–‰”æÀg %œ¨$ D`¯r)ä™àù3€ÒB;åÀdëØYˆ1 ò·Ö1“¥t‘²v„Ìmû›Iz²ÆPØlºTNÖ R¦” +Vi[PNÞ¨J Œªa}½$«T>u‡1”ýÿ>ê£L–O˜&ÞVÀ/mR Ó1“ÕÎ éùà ¬çGV1%úMÝVðí~ÛÊv’ÀF7txýlSJåÉ!YµM )[Q—0‡j JuXªªS|ËAm[«Â}­{]b2)kïÓ©Ú¿’ ' i’<‘u 4Ò†I`mHö<¬K³Šì–`>š ƒqÀˆ&ïûÈVm2@íŠÌ |C^ƒÏ0lmñî¤B[V­øj¥Êâ34 sY¼¾¢Ó,e[a>ÊÇó9¦ßùØ$Lú¦Ë¦%“­¶ ‰”íŒý ™ }­ÉTycEÌiùýzÕn.öœäþnÚû¯ö új‘@æô^8+)²æ·Â"½•iZ$}%Ntfºo»•&¾ª›ùüpRûZÁ™ÓX¨ÈÜ`%f²]p¿jZ»%Ã9óR‰Ç”V%u¬ªÕ¢ãgØ6Ÿ4e C Ë­^áôÊ_IŸ²y¶2¬€¤ÏÙjËÊ*80J Â²ö†Ë®W2‚)†˜,R¹;×nþ0M§@ÞgrͰFiL€fÎßZ/ë‚€-‡µª* j& ‰ñVŸ—½‘”Nçáú,PÚ¦gNÐvæ<µ°.¤`+}%cxêÒÀHÛd§VhUõ¤ð>8é•cz]‰Íæ û÷ø1Jºá¾âªêVi†Z0·Evçü7 ñh8óïÛFS…é‘”™À# [)8’Ì~†I —Ú$ [©Ò`Dbæbø°u†)1‚€¾”­ÔÖ“þ>Ád¶î‡XÜä绎´æ€Q" 6|UiÜ<7Lo‚1l¥²°`h[j$ ¤ ‰·¾aNÛúR’i{ÜŸÃV«‘€¥Ô â¶ÀIc¸Q aCæO$6¿]Ñx8Èz"ïO…MÕ“¿‘g‚Æàé7Udbm›À¬*[#eU ¾<¼X#b¯¾Ó5aCÖªí)g¢‹r؃z4Èõe‚o = ¤Z‘n.  ÕÂ9Pþo# èûèÒ7€òw€ñ”Jl­ 0dY[&­Zð· %;-}+~1gÈÒWHÀÇ]Y9×Kʶ^a)Œ €»SÙ"³<Yžø0Òv†@VïÀirK™Œ PG&”‘ɺLŒKÎFªlG«äµ’•€*¡Ê–²òÖ¾^MÛ‹t+ŽFTh˜^£™ÀÈZ×´¦Zk3X5—"0y’üý¿›ñÍ#¥¤*÷LÜx¿ÖuÇsÈÍÍ×ÉçÛáÜ€À¨ê§Ë•Ÿ-YU•;_»94Rˆ'¨VhÕ%²Ö‘黊˜Lέk‰1žÙü5X3§Q˜g·ÔðHA&U­-,ÛªµlŸŽ¹9,1¥•[†}#5ªÔüU!³úà{yèÙÚfKÏ p}¸-œy+}2+L6vSêÒq6FÎÖ)8 =ìŒd‹f˜ç%=Mâ m?@)V»Tz-DØýÈ6ÌdÒȺ:¶Ý@¼Bd M$‡Êe{LÚÍ3AÙøæV/ëæ‡ …ÄÖdÆ ¥üÇ!À¦Åïã9­Ódhûö’ÊIÕL0½¢“õø˜oš¶_b½x%Ö²Óì®ødCLÃÁ&Y-FÌ¿­µyš9¬¢¤`-ÚÒ8޾2@ƒ49eú•ó§±ú“ÍÖÌoDz;E/L[+½0CÁDèXUí¬ªÖwŒm!ÅÐJŒ@£EFšÜ6}!U$öÂãó¡ôÕá+“'>ì¤vVÖz•¢¯‘Tne“9¬aôÊÐÒ YÁ†á@X“áaëùÿÂFŽ‘­b¦X¤nJ²,Å ô²ÂÂ5«7Œ! mÉ„ìøÙ¯¯ÿÞ!A@Ö•)l+ŒWBÔ%‡J‹º8A&€aXY•kAæ[ ò 97%EUñ˜Ž¶m¤`‚5TNÓ‰¤™¤1UÖfH;)²­³p@ÚZEó+çé85ÅW`ˆEMÛn†7­Um 2Ÿ²Ö€,Û)d»X³åpû”Ío­ÖÚQ;¬mŒFàuo€| Yä_îU¥Á(¡$ÀØVXHÙZá4ùˆ”˜s s§Ÿ ¾? {4gâû€¬j§nÏÓHåë^ÓWyÚߊϭrˆO@Û’a`YäÎcÚvØL&°5¿Ú¬ªMcm›^H!Û6¡Õxl~8e)k©<áÀV ”Ú·¼F_Ù7”ÈJ!½HN¦Ì ôÕ‘O&ÈBá{Õ²=wYÀVU%5â/Ëúî²oëAûª\_Û4d¬¶ºã­xA,8 ¼Á€:VE)ðNT/X;µýhÒ”=¦ßŽ ‘ô¬ Ê_À¶òÆ4db)ÛV ϶)[ àаm’p)à …Lœcž˜€Y;ÀÏZç‰{)kUâ§2’s`À*ª­£•s%z±"«u²éÄ«m¶ü‘Å$œÞ8{Ê4 ­eHÕ=‡J¬¶bY¤°¥²Š §é‰O£E÷IIP#ÙªLØÓ!®¸ÒvEÈ4mUùÙZ-eçé׳&iX®Pvƒá›M¶‹ÂDZ=;Y)˜PûÿغƒeÙnb Ã3ãIq„ ˆàÕñý¤¿;-oßÈ©¬¬¬’ÖêÞÛÇÆ4•?pÛ•~/-ÃúŠëý9C[|µgŽ;vU) ¤ìÀUSÕ%Ƶ4a¼”È@ÂuÌ©N¶*2LQ¹” Ž„¿ùÏ£qü³Eö ºtŠôÍãöláduA²êëHUúTVIµ­ óÁ¯YÖ<Äf áæqS"­ ˆñ·è€øúFZw(&ùõ‡£¶SgØJ¿v²4øV[U,ˆ@ÉNW#Y“ÈúóÊÙ: ýûå£C–•-=F0±v"$ÁÆ+Õzþ3 rfJÑE+¨Y)[F5SFcíñR2+,e-¶ˆÉãÀ H³-R_%ÜD-¬n¡íèœl[…ò+½ë› [½l‹Ê•DRÂRdÞËîÝß–Ùv-Y5[-ôCJy&‘ÖüpS!sˆßTø‚­¦e§$Ó"€ÍFŸ ¨6=Ü`J0ü›9ŸoÃóù¬Ñ˜¨˜ª` •Û ‘÷Á~¾ý;,YÎÛæŒWãU~­ªz;Ö”¦Ã>¢r †à&Ïןªñ;È{!j¦l[¨o l•bî•ö¶Xe¹-l‹Æ€éeö:ÁÀ=¦ŽF©ÊZ °¥Ì°”*[U"žRŠ3&œn†]TŒÉkm[ÐÓhÄA lå¹R>Í` § À‚A+g@6-МxbØ:Zm5‡‰[3±Ö—8ÿ ȼH ÓäÙYr¨»#w4$ P¨ @ÊÎ(r° UÓhðüLŒØ0·Ê)aë¼ÖczoLs8Ãp) %¦+â × ÑVS$‡zá3Y‹)UEæ6¦ ·f¾ÿôm\;34‰Ö˜ÄyÂb­ œ‹>e<1Ò¶k¬$sdúÞO[Y)·$\²È§Ö~Žüã)Uô“µ  3ìÈÈÌkÊ'xXµ¬µ*|+ÒZÔñÖ}|0¥Èð™ç§_¾¨¯Â¶(‘r“Ù’µ:8 PÕ%'nŒéÈIJm­·&)Õ¶Og¤©8¦gKõÂd¨6Æ–þÛá|²ð1RBª­TΘÎÅVÀº{îo#$=ZJY—V÷š;A[+¥mnmKy‡:X±-2‡Ö9¤Ñ(e€¦Y! ê¨ZÃÕ æðnËZ)Õ¦·¶ºŒÂÊeaÙÚÝÌÙ Ywc'Ò)Ú’I1Ù„0R茫mà²Ì™¨ªÑÆÀ«Åc`Y#ãžW8}²æ!«EÏ4 4M2$†8óôÈÌ뎤q@kU²¶½f™K ˜€ž›Hlët¶lKi—ÞJ3œC¶x÷£‹h+<[úuÑÚÖ&Î3²«H#Û Ÿqïå’Év„ ÙE)—2^%¶F(˜g îW¡uÎÝùÿ;žÛSnMÌ¿I2q9˜^*²w÷F) –ƒõí®6Þ„QÖT³•€'“|ÖúTÑtV°¾²^~OŠÕ²H¸Áˆ7ÿÚÀ9 gkåÝ€ÐÛÑbm@IDAT 4ª„­¨¼"kÿúý÷ß)¸0ul+Œáu î¯ÚøÜw0õÌšo-ó%æ`8k¼µ)/ò'4ÕÅ.E“?Û®~³IÁñÉ( ïöæÙ`² š'gb$@4•g£¤èßÇ2’¬B$PG0°ÊæiåY÷œeOïáø”9ÀÜb¾ÚÏ/duéD{ª˜l¤…éÈuç&”gøþF• T“Ó$–ÂçƒÁè¾°xLÇ9mî³ËßM21’À [U•EÇ_ŠÆÖêg³F [Ká1§ß0«×'=Æ$Y‘ÕNQ%ñ”‡Ï$ŸôH[©ª¬|*iud/^O6çJÈXé[k$})/˜,O hl… $ 3·6 /Ì&³‡®„20MµµèQb"sæ¯D46ÿÎEóΓF9RŠ­u .4e'€“©…}ú49y*,ð•Û²4ÀÛÆ[wZt Öª0„2œC2¤ìlma¼éŠ`ÉJ¹ HŒ:Qz{gQKií8ÉlU]3C‘až|t!ë~`~Ù@š·…ÚÌÒHÙÆØŠ™KŘ֨¶Jvu+¤“õS åLr·ä "kj­cÛÆÓ…X0Ѻ'Þí‘©mÎaÊ|bÖ"Òš Ù^ûÏ[ºÖ‰)¥ª†×EÀñ¯ÁÈþ4ÆPU;µ‹Yõªr[UY™c;²òj“Ñ(7@/'LSSÀ–¥’<1ÙÊÆX‘4UÕ®Õ½ò¾âT­{Êæ®#7ÀÙµÃk·’ù7“R»´Æþ‘Ý x¶FͧjKÈ&Ã;‚¯)üú’É }‹mëBœ­áM“) èæœ÷|{×W¶STeåÐ ²x®gW*+ÛŽ¶²š&üzVˆyS¸1怇O‰im°.úÂYa’eÕ¹Ö )+Êj;l…ÖlÓ40MÝ‘1Jà«Z/ú&f(ªjUå ú¡)»³ð©<¾ZbQ»ʰ5@ìt›³a¬RVš€f˜gü³å™.V…‡ÛVBШʶ:©”v°í–ºœj1ÝY ÍYU ½ˆ§tÕÖ¶ñ¶‚ØlÝ3žm1¾Á(W{|oÐø«Uöøû%EÖ”Àc"Ìçèó‡ÒV(iÅÔÈš9F¤§Aêbu¥¶xØúV…+$+KV Y©óHî÷ì”kD,¤„ƒP–ò€0|Ü•@Z3¤¬4aJdQw¤-åÌ@$Íî¾ð.YçΞUz)[`Rak¤v >sÜ¿$n’ÌáÀúV3¶e¨—£Ù`÷@ÓÙ D) Z%°ߥÙòŒ¦ÇR”pñ=€Ù›GFäYy#al­µ†‰cº[WjËÇðRݰí 7^üs9ÿ°±yòÏ¡’N”>[¼B¸ñyÒ¼ö£)4ªvO\‰Øó¥É ¶ m)e¿^Özj9W÷ø"ñb¶0ÏþT~dn eûZ`Uk€ìÑJê 7‰T ‡BP ¬E[`ž šÌsÛÉ0ð£;«ºXÓtb?,¦©£4«ÅÇܺ?– Û¿%×ã˜ìháUæ™yJMƒ·¥é“`š &k«{ŸA$«÷ )hY)é¿·P¦‘²­5€ÔÅV¤Aò™æ-œ 8-Ÿ÷³±òæ('Àx§w†Oí¬Rù“ôÝv˜ÒÖ*Ë!«HJÀªuµJDâÍC PÄ#‹Äf¨i½(¯ÓYÖIŒ`»“Ú2ì,ž‚cb¸‰Èµ«P-†¹l;2F/µnåPØ zíÈ`%E¼u_æ ˆ]†z!‹ km œ²‹ûÊ…?ÍîAV2ÍQ?†‰øXë"«»5¦‘l‡ÄZHʘ L“3¦Bžpw2=%YU×ø,"rh$«oB;ïJ€î p- Ó$€Õâë‹$°¾`˜Xö׿þõ/ŽÕ4t㈂:@Úˆõƒ3Rè‡ ¬*†Òd†lÙ`šdV&"²Ã„ë«$å+X­¬X9œ!ÀJ0IÐó°åC/Ei6[@8E'[•’Ý&¬VInuDbà|¬°@ÄcÅù¤Ls ¾ßwù“¥±®p&Á¨sëÂ4•B@9Ùž²TW1}2ÊFÂgާ<.ßã4@ÓE™ŸÌ çpõ¹åª X­B%ul˜Z«Ê„¸læªÈhl;œmíèK)dÓ'› VÂÁÖjžÆ»ù?>;ßB™ä¿3n›§ZŒ!ù°ø¤!(Õ–g¡Vt±1† I/¶x¶~,îÓL,%`)>YåPwÙÕb"›6¬0ëî¿÷ÏôdÛØ:¦1½W‰[ãJaˆ½©Z%­ÉÞªøRá7› ê:5’’ÌéžøœKÛÂ`ÌV(0•GÊjÔ11 £üuX—ºK%£—rX|ž"ž3ò:¥ÛØüR{-9tF²†$Ìrk¤•RV‹"Ì–C>0>qgï Úú"+¤ÈJaTa¬dgŽo»RøUùs«µB¿íDxå‰ëî%i†Äµ³Â˜4ýab}›?VÛº7Õ&qšÚ66™ 1F§ãìÂ;—IèEó4@X¹¨Q-l¥:éMžãçY¹T›Á*8dÒ֚û*·%SN WíÞø:ýé{3pª0U!¦yÀ=÷ŒlÝIwE£uWTSÛlÍÆPˆ” C k‹Ìêæ?Ÿ¾f¶6‰î}í4€95â d-*Ÿ%’ÒjNkô(É„”³de›mSÙ*‘²UhNlkžºçI_/ÊR MÙ|à IÙl°TÙ–þŸ€¥ÅžBïÎÈ¥àR,Ný}ùÜ­£2éHeaU ñ=`½8ˆæ(e©D-ýÛÎ… •€LkLma)«FdË*ÏVóY7p)V™È S]¿?>±Èô9k̉’"}ÎóÇ4p…Ä"$7+c C8[ï8jéÕf"E&„Éñù¬ ¶úñC¤¡Ïç{j¤Áh*T¢Ò6½5²õŽpfàSÊ*x2¤æfKV L š$ÜZG †I/«¦ÅˆµNlÕ ¹uÀÕqëfŤñ^ M>MadJZ €îpÇl¤Êabåácd´2ÑQPb€™Ø¾½j—I+ÿÎ’U÷)…œ¹­è‘JlY‰Ûöó&½Þ*lM%‘ª6F•¦HÙùÉ"»=XÐ׫.d¶Ê[ëbÚüË:Ž-\–ƒ¨ÜŠì¼ýi+½v9XÅLÚÊ*×wþø&TîŸÞø¡¶Ì+S¸Úœ X ‹1)‹Ç×S0Ìʶæiå â­‘F‚߇ÛåLÀÁ)j•Øú¯ÓróDðï´52!7k½øàE[åi¥Q¶iÔR€ÐEŠ 0qdšÈãþ}µê[¯ü;`MS6ÒZÛòé Ì}EÃÖdå3X–‡›¬ °*Ò[Í,%2)k«D˜Mk@-±î5%ðb[2cë†{ÇêØq˧¾Ö>0eæ55ƒ¨°¾¶NZ1òªd‘Ëæ)•øm+°¸ªÏO'Â8ެñ«VLå4æì­s9üQÒ;+å4?m]#% ¨Ê6À o…ñ3h¬½!5¢4XzM3±6@@ AVgQ ã5|"áÌ•˜.Äî}è{O*´*ÌGÓCRp>@S°4ÖFBžŸ¾¥¾UÁøü-?ŽZº¦¯\ÊVŠ>ež‰ë*eëlÉ€˜mÌxzbn½ Í@ÐàEnÝÅ ¯ëYêHOP¡’ø@V ülð'‘²RÂ#¬Š@ÀZˆjlY“X1)óY¹Ë!ۦׅ@1­FÍÐÀ Fw-]Q#)!Ã[ñ†)k+2´úðsp^Ÿ4…fãæbè)kw‹®P‰ˆ4†°•R‚XÐ`¬·âóði’I¥´6*Æ ýL5y?b|½[)%irkw¾Ë¡a8%Û&VÛ„º“xÛµÓ1MWšÃ®h¯e2å+™.Lª-;\;[@Š›ÝÅý#;8ÓÂsÃð·ÒˆDæáÍÜqlÇÃÏ©‘µî€xþ4BkM¥ŒUÖªÄ*:i8‡ÄáfƒÉ²m¸·NaVùhALã°7еà×qÎ>ÄMhC¬– ©…ípoEkzViTiš¦|]XÅó‡ë’?­Z«?eTèÎo S [žž>™i’|`Œ’²ÈÊ' &¨©Äˆw¶*Á4p}­‘ë"«v³­TÑ0¥Ü[WG_SJ&7ƒ1œ” qMÉú]Ä6Æ¥!EµªX!É<|7Ó¬0 £qÂÖF¤h’a€Ubþ²}âcL+b¬4†”ЇO³{{²ZÀ²Æh€š^ÉIyæÓeÂ+ÜñM‚!`EpÃä–¢GЬ0°K3-ØÑøfb[/å±'Õœ²”uô8ðþ‡søÍ“2M§–¥Ç°’ÚÍÍKÂÍUøÎÕ¡"×½¦‚ %Þ%4•¿±‘ÝÌÉ0pcÀi ÀßÌÄ0Ÿ÷/®%%0£ª€×E/A–[% ´¶uêÎY“Æú¶Ø6P»jUaš0C×h¥é{Uª‘j-E Úfhè,éÿ_Í©üúëõ¾Ìk¤¼CÆ ï5Skk˜z!½'˜½ZȦÅk$ÎxU¶&Á4OJ<¦¾Ï0eB-Fd¨ªÃÊÕ1!FÎ9sbLž0²³ìûjí³ïšFU(xÒ¼)>Éòl˜° Üú¶~K`Ù|ƽ®Öްê! ôÅíÃÐ±ë§ }šdLJud€Ck3rX-·n¼)Ã#”ó´¦\ÇRYµºtd]jšÆˆäcK–­“zN ¤ö†‹Sùý$„€R»ÖѧòûeİBG«£TÝ­ôÖÄáÖR^—j{Ÿ`n}Cy.¶žed@ @/ç’­„?à;×~D!Ûæ$à,dEƒ²ÂdK0ÍÈY©­ÊÕ ebk— {/@Icª.ÇHR)•™Ð¨µ*±"Û:{2¼`¢X- …\]ÓÒèÒ£á–!B)Û¬0 k” ÞvJ&˜ž²is¸®gNÛn²çÅ ©–Æ»‡o<¤‘`†V2“yœEŒì‹»É›ÿh*g•Þ àhrß³“àÇxc çà#Ũûø€’¥V©~KT $ŸüóxÌæZŒ7ÙŒ¤¸+¢p€mÝÞ*²h`QIX‰vÂJÌMª w[¼µXÃ(Ì™ kì<ÿö·¿¥ì:r}eÉèk×j€” Ù ª²°€UY†¡rzµ†D¸s}uà»êÎbÍ'åH€m>€y~4m6©º$nbžº(á“h¶]±ˆT^Ç®b§HcÕ¥F0çú&ÓÎV¨Ú±²¶i€¬ÚNCV¡l©¶<+' ö¤td)­+D‹®—LVôD|Ä\‚¬*ʲ9´Õ…¸Öºl þu$CÆ“…e…iº;), ÈæoF’Áÿýï­^ÂÄdjaA`UÒ=ëÕx‚C'íjd€¶Ê—r °’üuô=à[H•|úºÃ+tWž!¾ßó”Ì[˜ÌJ$Ë*¼¾ÝVPzÌ)ñ”ñ<[Î4RV ™±cº)bCò‰ïV‰‘ªm†ÆƒKÑdñü]‚¿EÉGyæ¨d&Ÿ.–&@V_c¸I[㙳Zš¾câÛJMoaA/•!†>Ü¡Èf|Y=wÙ™¤$À˜ÓÖð¶†äæž;‹.nF9žÒ)êÛ)`æuÄaD}É€ó;›Úu'“⟛­,¦óÜHÓ¬eh€HŒ­*@à½ö˜™ëåÈ”HµÒ$5¢Då®"lU"kÍŠàènTÕZa­»„Æûã÷ø&V˜ã'}?ºR*ñÀúÙÖPî$jHí1¶Èx¸™€¿FUxà=@æHˆÊÛ&¨v}Ú¥1m aâ­¯[8‡÷kWÖûÊŸ^4êNœ,².VÑT½¦²Å¦²UX|“ŸŽjÉœHǮі6ª,¾ÂÜðÐT ¦ôÔ†³"Ãt-ÄHzÎéT”m%¦i#k‘§9ÉT£¦xüyC)‚þ¥ëÒŽ˜²òÍ£Q‚Lj‘y·š•µÔVUHÝrëÞj!…T.öö¾}‰i¬ˆç˜¤.Õj”'€Gxv9²aV'[JÏVåÔÄÍlK¦DÊT³M +êB (+lkݶZëÈ ãºyŒÁ˜ÓÔwš×Iß½À=ÈZ1õmàJšÐðÎ…™F£ïŠ"X- ð„irkàÈŽÏÙØ•ã)³¥ïƤD² mgô[½¬ÁTø(o 4 pÿø¹Þ•ËÚšÐýs³ÍY­ªz!ó¬°7­ûÌY6½-qUüa÷ì™6¡p %CJ¼- 2ÔŽa­hDd2«dÝ­•’ŒT AúY95i­iJ%ãtdÛ. )Û´²ÅZØêkKéßöýñ÷9²jÅn 6Cœ».ÛNÊ2*/†-Á”ºÔÑš-z·je¼³ÃgˆïÎ%Øðª²Â÷?dÊ6R_…REþ0¾v˜ýFøU_t¦Œ¤XUµZ ¯úB-Rw%°*[×#æ!.e…3¤¶”) [k¨¯#² ­­½Ð¢h;[J)U im3LO?r<Y§¶"¹‘•Í'Ã3Ó÷—›”]B˜ÞÖóM¬°Qk·hZzG&îmE}pV/È3Þ0€Ûãöúg ¯ÙgžŽCC?È Aã£^}ÝóWH†÷à[ç­°»m…UÙ6°µªµî8 ò¬*‡1’aàMÕéÜC³¥¶µ¶ C¦w©™PÊ2¿ª³tøÆ¶i;[€ç[«"n˜¬šÄ÷`ÔkvHle›¦h21­!Söpñ4x+fµøS|‰?ñY`9ÃpK´3¶%ÃTâ˜]—¦éme­Ä4¬¤´­|â:"‰E…u¬’€µHÙËFNY£ ¹‰N— .iò‘øKù¡ «%Àl#úE²µà@&Ô:µ,†³èû —¢)æ&E`aÛ‚ ”²ºÃVäWòùbÏàüÿÈ¥ªÑ2\eYx$\¶ùoÁBCßa81jß@ MþÊö>ÕÂ4µƒ ÃRá MKàZåÌS¸ešVYsÊ&ëDm•#­Ä©Æ<Rw$`ë[5%Í«$4†çgU‚ªŸ¶Ä1 @f+¥DJ„­Jz+o¼•žƒá)u³å_% V–Þ¶¾­jŒ˜¾r½€œâ4dHa‹´¥Çîn‰^дm 2…ø¶eÉà®Îo-|0µ°]#LÓª lx)g‰ tKµ³6²Ò£¯mÓ& ÆhBÙ~Ô59ÛYb[‘án -AY+ÃÚ%®£ñv%ÀÊmaµù”µ¬”x&ÂHº».£N†÷fê‹$ÆÓ U5j¶¬„¬hŒÖÈ›üd J¥Ñf-GIžšùÈQŠŽ¶Ò$ƒ›Sʶʥ⻋w[a©ÆS¢ª9ÃR)§G:ÃR°à\w&BVTbëúº+b…ôH`àUÝ™ò~ãGö‹…RyšG )Ñ<4 ¬ŽõŠ17ç%Î_9Ð ð9Ž×S Paš1uAb¬‚²áµ¸ãŒÈ3¥-±sMf+ÅpXy%1§Óí%fÞ=(G’aù4¾¿5b:/®Êj;+Jµ ikBƒ¥„¥›Àð=M)ŒA¡Jà;éÌ÷O3gÌü`}yJÙ %™(D® ®MdÊÉêUm©—ÖlºÄ7†Uð$¸Ï ³.–Ø}ò÷*r°Lè¾çÝÀw«\`ÊËràd¥P—Öî°k¡œ ÜØªÊv‚¤x%‚xë%>žpµV;¦Äî\oek5äô°¦b“ÔŸC§°òït”¶9'èb3'Ãó´5Ýy1²‚L¬WU‰OÌß¶ i0V1¥”òá.Y9Mkâ « ã;‹méªñ¹Flæ=Hµ‰­Ó¤ŒY; ;Á3éÆŠ ô}èD»Òu¡0­d«ÐÛã».L‘~þ o«Kâš­’Ìùcà94@URï=Ð蛉‡új›Ó–Ï hl['‘uéžs¨˜ÞEýç?ÿéº0 Î?>ÊŸ@À0@…ïy#gÞÀ ¦*¼p¾aJà=…†Ô ïô `¶=káe›¶,½5 EÏŠ'ङ׋† l…R˜Ü¬Ž–½Ú?Fj°ª~dßBÎZ×î­¼{kH«Ëq'Hi³%f‚FI)¶^Vª-& Ð`.ÁÆ‹d‘–¥//’ùGú}Ûs¶â)˜\0±eÒÃV[6^S©Ö¥j"e)³Í“§0°l#¥\G|?±wÒU—2Œ©vó~ i¼ÚU•-˜äc+¤ÆÀ†±-Uv8™óv¢É]D]’ Ciž.§lOJŠ­,°ËÁd5’lñĶçÐÏ~{‘´Û´Õ•HdÄQ*¿6® £±Â¬`[¯ï³áÓ6¦B¤è }Tõ¤’!ùã)on+¥U 1ܰØÌ@˜A%•Ûֶʳå\/¾Å¬ Ìì!ù+¹‰Ú1ñ™´Û»U­ld×NÇ„çVådëe Ó$(kå‰9ýnGk÷ßk͊Ƙù•Ÿ7&1žÌMŸçx!…IF:7Q-à6ÂÄ&׈XìDm­×õØÒ(ñDD[µ=þdM+E&²²mB@ ­e/q&Ê76lBžÑÛú,dbŤWw“çl÷·«<µSÓØæ_ š¶Ö&É“ƒmÙ|¶MlKÌp‚¶ÜÔ¦Xi³ÂcqcO‡a¥çˆJ­;¾Z q8Ò60Í”Oã²íf`íºO gkÃX‹!¥p‚söðì¶áÂãàƒç ä,ÅpþÚjA/ëc5Ò¶ù‚n¸7¤+EªMßÌ…^Jð^[)[Ñø:b`☬`%õʇ, ^ö}b½ÖN#ÁG(Ý€•RœÊïgGU‚)«êæ?®¾úÜ€;Ùy š!qæÍŸ[â|¦Ü0x…é­%UI1TN©EzL½"çÓ¡ø`ªêêðôÕ6Ì•L ÕRÞ>OÍ#.ð²lwu0O7CÐ<&5"óÄñs?ª¬½Q³Úü.¶2×H4$q_˜«WZ«Â Ø€Ô&\#Ù.S; Ù„·Û§Ýª”0áP ^T›[‡Å(Ç4Pàé9d»%n.Á*‹èɬ1Hçc»Ž°Ä*l“úïÇŠX‹¶êe’>Ëx…µîÑÄX^9=ç= üPkkÅ ƒa……m€žFÐ×BÊ £Ú6O…ü²5Å e;£m€ΧªÞabU^'æÝMß™²Ùhš*±—DŠhªZ+)l Y ÖR; À9Þ pÛ‚¡Áð…Z2«ÚÖø¬àȲõ²ŠÙià’ ‹‚éK!ï™Îˆ,e5^“#UÁ€ë° ”‚C€Æ€N­8MåÖÏßë8­cwV:¿ %åb,X¸6`÷®\ 7²Ý +2@ûJhAf¥WKf=Ó|ÿcUª`$Yc¤×%OgÆTӘ͖ßÌV©Lò¹OÓ‚@™Þø$²ó¾¸.1«U¨Eó{/{$5eèUî´sÏåÍàžé» +Ú ô²e (ÉD˜HÉCn¶º«EÒ(§é%€‘¶‹Ê‰ÊÆ iø#­HëÂv|æ{|øž>1’Iµ@SÙæ¬P´¥ºkÄóáæP¬(­ €<+·aKOÃÁênmýtño¾¦'@fÅv&ô"«µ ,l‘më‹[§°nr¤T²ð•ž€'`f)kWÑUY7°Sp³5¼ª¦Í©D4íJl)›§ÁîÑíÿHk¼ùÕnΫ-dñp2ë_ù2¡‘1vº ;8,ëPdž aæ§þ;Ï<¥VŽ„+ÑE$ÉÊÊŠ££¾4éKɺ„X–foK>ø†¤¶v{Þ:_aåµS«ÊV°mZiåÓ° öÑÆìoS1|š¤Z%)5ò=#kËM`Òè©ÉsH–FV` À¢ÉŒl‚é)kJPªZ¤¾¥j‘Æ»NgA’ž¬*7IÐØõ͇8+§î°Æ É'·¥G ií&9»Ì¶=z˜ƒ’"7ݵX*§‰4U'eö8ÔÒ$%³fÈhUBLÙÑöŒ7¼,Ъ0+Á$8O2ÀŠw@†0ó @™•Ã"?øïÇSåõ•Ô b…¶ÖJtÁ§T%DSnɬñmÃgÜ{|[ARJ´½ kj}ƒÀ$/£¶rk)‚FjW÷Ö•Âðœkº«_ʪ¼ILõ6%¶õóì8ݬ*1@cš6˜.sQ¹i>Z;, lµ 3T.”DÆÈzˆVãU^£ÊáRV¸ŽV>RUÇêhªú•† bãQZ•Ô"Xœ™¾A ì¬e[yrpEFµf;«ÄRI£.§ÃòÌ*©dúÊ[ÓXÅxMk”R+‹ì&m¥êÒµTnN)Œuw®J“¦Ë‡ñ0ŸS øÔúç‹rl¾š5sf§^„¥Ê*Α‘í ²è%ÚJÑÃZ\³³Ø bYJ€иa‚ôÆ[IL…ºã™Û»¬Ûr"†Z5í°Ö”ªÒ³Ú0²Eàma ƒð±5*7…€^Ý@šVY¡V–ÞjòmKY9X•k”,…°²ô{|øüóÆå¬JIp[2÷#Ë$µÀÈRÚ¦oŒwæ4VQSâ<ùI¨j¥é"bª­•Iç=¾_gÏ*Ó)ˆƒ­Š¬Óá™ãmµƒEV¹åO–¡­PŽ¡Û^úOgÌ™-/CšfÈJ²£{ŒUà_¦»eå[Œ³m +bkMáª:½k4­cÂ…F­m-6 ¾™rS‹Í‰„­+Êj Øä€4Ü NѦ·jº‘à>¹YR„;æü‘02>qJCÜ9ËÒTÕ‹º’<·Ä|h¬x+…Í@“R­³÷Û]Öye{ ã*—eUëæ¬+2+A8Ÿ¾"¼·ªè@™,è…ÞÖZ£œçŸL!Ʊ-²Z¸Ž¶bµÊm­°Pn«c:¯*ÔÂ*Kcl)Ø i%°•MÙÊ„¬Yd­Ù¦êËAʪ©'‚ï°©g·fÒÊGоZn~'Sîh˜7X(AZ 8ô½‘l}WE£ÙJ*×tƒ šjµg ˆxš ^ ^Öú„ &l{ÖQ•y¬ô &Ef›¹rŒmJŒ¨dUÿVÙL$¥KëaÕ¢ŽxQ¯ãxg–rŸ}Mqø3ú [ŨRÛ³®ð ¬\kk@SïCz+%~çÒCSŠ@`…³åfLeñ¶Æ:f©ÙâÅÈj­ñ­‰•{ÃyrÃ8ÅN#‹'y¶Í­QánÉVy>ÄË6Àú¾À È2ç®Kž™0˜Žœ[÷ãn¥vWL®öˆ7LϽ«–¥²‚Lœ¿Ð)wo§3ûà 5@m½úÏ÷xFª*ìä|ÒÈÒß{û¤ ¬¶ ;5@zvýàɧv;#ÀS Ù|ˆ…¦HLSY ^6rçÅ„ š@¶ÄÁªmšÓæþ$è”"ÐIPÇá#ýv‘*0JDݯäçÒ$)ÍCœ¢Ï&+ü¹‹ïß =Ü5Z OQ [Ï7`-8{Ù¬07€¡|غ»Eæ@ɳr€Æ*‹¯ J…n Ó]ÉzÊéáZ…ÉŠZX…IÔâÒ bRV!…‰\X§ˆ1¢ªð±þþÁë+4•=mn#Çl+µZXÖ¶,“ÄÆöà"Ú=ä_»|º)'Bv?áŸIµsX;Q#@¡Õ´-ÅÜê·|“d™ï)š§ZX4…#kEÆSÊ&°&({>˜¸§™­v.4’å`ÚÄïdž ÿz3q(½¼ÆÖ²‰m¥¾ÎÌ~}w'=[Ãw9Ü1FÀLrPÅÜD%ü…TÙ€l'R[ µc äϤ£YÉl ĶKÀ°µ6’¬P.› òdaYÛ˜0¾°j]9óoò|$ „T€Öº-lÈW¸Fi¬y¶…÷òÇ[™ÈfëqØÂxÎVÎV¶4­ëH,å0;€/lk½òlE†@Y[Y… a|åu´Já;µ-ãT^ÖêyõtàÜV+eåÓ–­K3Äó¤ÁXê2Y3°êé›§¦d ëK_ CüÚ&ªzuY½Ùúb棪+œàxÝŽ‰µ%Z‡âeFÀÊ &\Œâ£ö| ûK7"á%zccÞ®ŠyuSýWçh(Bè«Ö‡Ù(¶2ÎVÑ ¨†³¶þ ß&Jh+kUH%^‰Úæ÷úšDVŠ0vóó´…§Dp‹TÞu¨X¾Ço«ŠUAXdE qzk2kÌ»í&5ñÚqÈJ¶ªZ„­²¬Ìl- s:”ë‚JqÈ*¥UÈÖëý„¿7#+‡]Q P¯žŽ.¶ui°”Öª€â5„›|d[›\UÛ1‡­“V¨ª.•+±®oS!+é}è$è5è,¶dR€*‘•5\¯|¬È—©ÜZ|áŸ>‡È=Îå-Év#ÕˆR$ÓÔ/ÏÝØ¨mz©yj‡$ãŒçCÖEáû¤ØJÑ4^½¬É:þ ñ mÜ´€ÉÒLÐ0¶1ܪC%V>d7ŸñÜ0&$väu±Ýü3¬Enù„×)øÄÈÆ4•­/«1¬zujšéV¤*nŸ^U 0®”¸Ž¶”ª¬x O“×—¾^œ ²ª5(^W¤V£öÕAg9'…9«M “ÙC#Y†fh*U¶”•¯¯-,(a‚MË*q«r)2b©d¥T5†¾aü0%Œ1 lH[ 9é9ÃwŠs‡RO)…WÛ0H)×"¤|7Ò‰a'ÅÓt¤?lÞ7ÃFh:P 9Ô´Iz…|Ž0:4žq%º¤iB$À³#Ø ÛÖÀðTä&[ªòi cëB¤DwÒÀxçENw!˜]>BŠ@‰Û“øô¾ÑÈŠ.Ðy9 ?µ7g>Rp3ÈÚ"c¬¶FÅkTm$^‰°]ØjM¯{k_ mÒ„j»ú:Êv€ƒ'Þami¸ U >R(Ë'¦!)7ж•¡îºL€Q‹#“­«ëZÔÖ‘FôM »L]l«…•×wU&$Ј•,Þ$˜¢ùã1¶dœwb§ì£u¢4ÕÂÀºÔ©;Ã×]áH—/E€Áך̉`!Å“F¤áO‰Œo+¨¢—#F9ŒÔ‘X ûœÎ§Zb­!ÅJI†VUx…Žé­ÃdËA¡*€OVVŒPkÝ$øM"Õ»ÚÊÈ¿*J…"7¤Žo ^iT ÒxÖÈÆ2'«øç¼)µ÷ü¬˜@o†­È”‹ùÚ <ÀîH‰/»n)ªÕX¡¬Ä1½å¥”›)R–Ì$œñnv¿ãöÀò'èÒsëlLdM¢µûbˆ‘º³|îèŒþü´†uáæ‡ÁÍœÞÊ™g¤•›Ùämw)]dë^ÇÄën;<ÙäV>yfhŒYM¦1l›S o] d)ÈëëŒÂ¥Õêþ¦Dm}T…Ñ‘i V•­µ¦Ý<½mA (äc5I3ØÇ CŽo8¡µm%¶xâl”L FZ‡Ù"¥v"™DN FùP )&JˆŒuA=µ™(4ùÆæ‰÷c}÷Îu¯EÛÓøÛZ!ÿV}‰—j‹‘e•ÌV#1fJd)Œ*íLNPù”4°¬8^wÛ´„^V&wwn‰rÀpå×ìó&l ž¸*Œ°U4dVñ'ýýµOv…ÆsÛÞ…5u4XÐ(!¶jGÖ]¯{ 2 Í-:U&f{…çƒ,ø |n~+PØ×Ž)âjÃÕ¶*¡ì÷zô8ïqø±Ò04È0·üû÷»èyJ!’ùÔ M»ñ¤¦ÂJÌ€¤ñ¶#_ÜH×k%Æèe*@ëÒšÌׂÈ&V«QšªôÂTγm嘠‘l²ÜXI [G¶ÜT¹Ýñðª[|¶på¶Rpå€íH…ñ10&s¨Wîüÿ°“˜£™Ìaëº85¶‚»`¤D gJàúT²V˜FxG—Ò±±jMf gn {b¤ŒÄ³óTóÁ󯶦YI5ÀZÐÛò±V+E¦#¼w&l!µ.4É(G’ÙâÇäoíBâÍ–Ì*¥J/[sþ•@SzÃ4“µ>ãÞµ#ȹR¡‘ ð§_᮲Ež7”û+±Zn¦ÂcZµÇîûi"†{%.ýYV^6gᣄÃįs."e %€Ù“ ÃÙ ÐÑ:HâY¤ðj^kŒ!e1ø¦šX¶™{ÐÞÛÌ›‡Cn¶‡eùd[ ¡áŒ±çð8&’¬’ºÃA™€°íž­Z‡ÓK-¤:)A$«õ…ñ"†m ¥BdQ¡›[kè8^ªi #«»'†)­Z²lûFm¶šâk!åqÛâûW#J•å#jÍÿÎøù›[<¥ïq,U|¶1Lò±²M¦u©fC †”@YnÀ¬RÚ’Áö4¸·—,5>òz<ñùÓh^2‡<3™§S‹×Ó–ÆÚ3læniå]‹•’ï !1f“í Lඪü‘ǧªî•˦d"<¬]µîM_£VŽ,²¢o$«|¤ºgµ½Qj (­Ròlb%Ù2›ê]iÇg¶ŠZj+þ7s^°Sh$dék'µ¾ùØÒÀ+忤7j‚ÎÛ³£áМİՄë ÊæÉ'¥Bþ²RšÚÂR>_]¸l檚§2ÄTb H©M†‰´®üëßÿþ7‘hŽc›(`Õ>;ØdVÁÚùSöÌŽÆ/L j…˜ Éࢉ7Œ§ S2ÇØF†ìNaQ/Ê·…’uÁ›Š 7ÀÆØ‘¥LkÍÓêZ«¥Af «…m‚1 @ÔWŠ7ïÜÊ¥„. àIsS«¤óÂdªA@*qŒMÓt4“ÀRÃðý¨ÄûËúö|ôÕ¥IˆËb:á‘ ŒàÐÑð@ å&Ù)¦• *šnVlFø†·­P RÉbh¾_ÔÂd²)™#[‘ôx‘[Ç×Q`’8%þR\jY@Êã(K ¤IÜLg¼ò³HÄ4ºÐ×Q#v¬¦'X‹JÚ(é)(ñÊyˆá¹÷O~hê^a[b¤ 7|ÝwdôVJdü|ð"R­m2­ãTˆ)ÚÒWEœçV@|å篧ӽU|-lñÉnòlóŒOÖTîÁýàû#V¸pWëäÀБašåÖ䵫ê&CÇ÷&}?)±UŠÀ¡0ò[úùëR™/;“˜ºt]RÄ¢Úé‘¶ bhz¶4xÛn¾S爐ʧù{"¥¬²ôYͰÛâ<þû“ÑØ›¼yðUªWËK…¯–yöw¬Ú ­ÇýþÔŽo~2ŸqYåe™O&;Yü•çgÞ ­/%R|Nû;02¿m˜À<ަDwÛaLß™¹ÁþÀÔ´d¹ék‹WçÙ0D/iªóüf‡@IDATƨo gU"  l熄ýŽíÞ¼Ìú–R›òÚœ«lUèPÆÀlòµë~TIÿ @ˆTðΡÌeQšÀkXw#nÁpÝ…T'iJV¢3”—ڠcdÛ­ÜÂããÒ­ÈîwÃÐÔ¥ùmµ³ÚÒóI–¾ÙxÒPÖ}Î4ÎU¡•!rAcU…I_í=îùÙåä/åwnnøjÝÕôæ¶Ä¬x¦éIÇt¼àC,Y¡\U…#K­OÖxÎËÀ3åƒÇz[kÛÍÏ\‰Tþ¶ 0‘xQaMñʽ0lKá…"°ÚnæxÝ«H9C«B&Ž¡ìÞlÕ†;Lœ!&7 ¥­àœŒ·2Dºü3ÊÆÖ󲦊|¬JÄëð2Ù&“l9¼%#™ˆ¶ «µÆXeÕr[yÃܺs©î¼’>¤µîìù{‚Hè¢ÔòTÕZkÙܺ@J8[)]8¨…ñl{ÊéñdM"맬ÁúVDÒ Æ¶Í Ù¨i8HñÏèµIŸ¹*Ï¡îÖ”4lg•! Ùöp9`xZ‘ñRÄdH}‘9·Úæ¹î„ &@*Wë~:QU²Ry®0« ëØ$Jœ¾v|•XÓ´ÚŠ‰©P/}1Wud˜&HS£ñHØUtmù®;С2Yá|*Y¶‘Ê6ÏŽ†›²U[¯LTáÄÉrsù¶jmßZ8“À²mK‰7–Ny&¸‘˜rC&TVWø“³9è~dkA_*+€>dç„÷Ú‘¶œ9˜a%ï=`íë"µ°UíÌŠmó·rƯiöÝâ…ÌM6@ŸCåñzqÀÖ%†ÞØáÝRøŒ÷q“í®xrh~|[L¨ª°¾dȆI™&2+gq(ÑwòLðý ·ª†H³1ðd­»•³í¯ß~û¨Q8˜ÿÏ0«CVi¥]1/ÌŒj€©YJÙ‚¸ã¸Q†Ê<âÎÀww<ë²ôRÒ!¥„­,àÔ­ÎVoË!=P ÛüYaàdª²r?MU¡•^BJwpP[vnRÝ-°À[{é(Y!Û¬¬¶R½L9{ЪòI\£‰+·nT˜‰mL@-«mµ½MÒZk­3©*µ®NŸ¦ÖUqKÓ#C®°ÊS/@¡Ãº¨ni©ŽR®E-=ÜÍ3[ \¶•¾m» +JnH&€lWm[TÛÕ‘-âmÉZ™ç“R¡.…gì ȳC!”£u„aLÖR]8Œy»Ø&®j+®WšÄ¥Z³‚¥ 3ÛvŠVÛL’Yxú:Bocz| X!Œ¯ª#oëŒYY)éßmŒ5=å°ïäjñÝU20¢IšAá¶pkÙZ$è­ëãC£W\aNö|É´@ÎV6XʶͤToi X–ÌœÖd¹Á½ÉÚIÑw é‘o ŒéSì#¬VP:ˆÈˆ/eaN` >ÎØ%WØ*¬„À6±Ù:TÎ/NS-\S&J²BŠ)ØRZaµîÜ€?ØèmDá¨Òn«€‹¨¾¬ d­kæO*RzÄ+/\ùq.õc›@ª˜`˜‰”*Mk‹× #l‰m‘}¡»5¸¢ UHй¼ªC Òw ânC–’¹µkŒ¤ˆ8ˆ@þ¶”Ì{ŠV[¡¤U-ðôE„ ¾Üù'ÛÖSÿýXN «­@ÐýŸ_‘ @ÓV‚‘Ýyëb•¥Äó,ø`rÆpkža)V" qA‰!Û$+dÉ*ÙŠÁ+º=“ÈÚ­zY…”•›™“Ɇ¥ðÜ0j#½Þ€Tgä`û¾óuDzŽdõb"lù@Ðô()ù$ÈιÖĶâÖ¦´Îp¶²/Ùq"•8‘¦HµA/ú¶& Súò¾…•+ÙêÛpó³…i’ÁkªVh=A¶JU;=Ðéb¬FuÉ9_³ÏW6‡È¬(‹ÿ¹Efk ØÊ ྙ9”Š·ª"hÀA^Øgk˰r¤H +ð§àûÈ"+¿Ú¸rçí_ºxPóÇ7 ÞQÏî«ú¼c=j‘•‰rÑHMeUÞTùPÚöžd¢Ð=$Sn+;1†,¥ÕÖ„Lh(oæ¼óH%xQIp/§± S­L)ÅAŠŒÛ­>×"+rHÐ¥!Ɉ)ðJˆÃœç@ ¯.²°rÿÉþ>ÉÒÔF&¶jÔØ€àÏA¬WSIa"9%ÎÙzŠoÀ‚@8 àpóŸ…yO\JÓî¹™ë…ÍnÌà Ûê°ùè„ ¯¼’ ¹@dãÖù! ¦*úEL«Ú ô¥©Ð}˜¦rL%5Eîí®¼ôsS"bò±.Ê&à†¯QÀOƒ©)².]”펓ëâþ&`LþöªŠˆç¦ªB+RÌêUâ ú\èËA—;ÂùyÚ]!é)ñ:†›²èÒš^¤Á4HW$jÔµÉΔ_bCºj?Š6O%ʧ$«¨Q©È˜œ¹Ñ°ÊÙ_Š!Òãok•ÚYÛZÕf[‹+ù|a)g’`…5Jœ —3r€&p·5õ"ºáÈ i„,kµôÝiÉšÞaãé¯ÁÇÆ …R »‡dV)3ðo`Ê9„= <’&FaµÈRlÅÊMÏ<%“®NÉÿ¬5‰!Ks†~³ HðL &ë&ñaÃ`‰ )ÕT0ã7 §!Jäïj»ÀÖÊeE8íÔÖH·•5mbŒø1ƒmA)ÂsŽé¤8‡ãmÅ)»G Ð(†,“ôfu(­¢›ì¼n€€Ã[ bÃgn[G$+xk 7€?Câ”ZÓÃç 70æ¯åñ„™é-ÄsƒëÕ‘3Ì¡• µý0°­JySIçÊ¡¦8‡ªš ©uÔ*6ZÑ÷EDY­(mù`”$èÛ¾B‰­”@²¢³dk›àÜÖê‹w)V}Z1Ý 8K)èb+jIÖ¶±ëµ‘Ò[ÁT4R­•'ȹª•†™yÎLz‘d»@aµ†iÚ†©C© è½ ÔJ)ÁŸc߃ÏpVø&ß´iÖ%[äX;à÷TžÓÔÝ<"çPHs†û~XÊþ ó_ù«¯E>¡5¦Â7Þ`½À¬e·Ýý ò o[l ³)¤ìD”sƒ#¿Eçì0=Ø6©žJéc`á½Ê§­—*AšU{mÎRÓÊ#Õ L%V˜ÒÚ'±*MûØö)ûṎ@©<™›Óª\(÷>ç`‹‡Eç’êP5åô;-À°Q)ë>Me1>#˜IþøHUR7çÆcŠHÀ7^>¶EÊ‘5œ@¹˜g[S‡kau ïéó7ƒÌñÚånãÜ›?¨—Ó©o‰0—µïG…Ô¦”UUWRË®¦Y9È6åpU¶x%˜zñL¬ A[]à|–êxÍÃs¤!áΕF• Ñ‘›sÉr°Âø°m]l)9wv‚f˜ œ›T7P¯eeż£±²‹­?äfUÞüÄÜÔ–Ò¥°pG KÁñ˜›9©ô::”¬m“£”zde†Ò AO¡r ÎZÛ*Ùß´m~ÀT¾<­JzÙòl[Gâ®Î¶Ö'1F`d¹±²*)h  W†‰›–^µJ·b+[µ€¨]ú·õn€-,µÖ“ÅŒ¯ ½à/Üp…+q¸ÿõm…•ÈæqÃU5›€lK/6Ò–FGÀ°î@ÊÍ€¶­ô¢ì­û¹H?Uµ²ÚÌ¥Æ*Ô*̇f_8R°µy2¬»)TÕ+Y—Li˜jñÙ¢Ž;T­e¡Ü*› F²JÐ×]í0&ÉnégIlZªä¹S׎ÀÙ­ÓÔ¶ç Ñ{ÿÞ¿· ^½Jsähõ˜Æüªüþ—¢!jiUµÑaŒÚ ªWþøAAÏÓ0«PK‰O3ÉI@/0xYÀs"–²ÚÊ6ªµ­—2%A¿ôàÃ.–­Š'7«ì;Cƒåo=Üg ¶¾ÄåƒhbAÖ£Rå7Q%E¬_âü“ÞªÜJ¯ðz|ž+ž¹’xÉ:1eâ‰#s°ÖË<€¥$“²ðHŒµ€WÒl”õm˜kvÞoúÄeù²^Ê~©Ke…ª]¯g¤Ö¹DÏzz&ºX…ªNmUÒW’w[­BY¡ oÕh½«JY}¹u´J:Ò<¥bdUÕÚ:Ûæì,éëe°¦-•~²€’Þ0Î2}w"…‘7FóXá~݆ØJìt•8oæŽÃŒ­ØÿÀH>ú’mrÊ0àPôùíY# v NûÄ;@C97ÙôÖ@JÔÔ$áiðm§Ópþxbg$;Ö÷«Ù%têÉlUY1•pÆÐ#óŒ©YÃЯª.¶§ÓM© 6' *h`Q••Un …K3‰0¼¬‘d‘Àu: ž˜•-}¡ÇÓ“!gnû†ò¥èOïë™?å\÷ÊUôæL ùèèm±ÊV¨6Ì0½9½–dx¶xç³ÔÑ èçIó´ MñH>>Ý€mÜ6ßÛË*g)JX_‚Zt'·â|ÛÈ&ˆ¯~ú3Á_}l« ˜M•°ÍcøFbë§Fz$†Ì Ä0An lL¤mšƒ—"•×·gN*ÿ«ú<‚éëb3Ü6²m+ÏZsØY¤`ëR)šk­ñny¾]i0úJ¶ý!›H ¼š°TÝÛv«˜ÄÈøLÊÂE—ï˜@Œ«¦çé%'Ægõ­øË­Ñ·’Õ#àÍ6Ü­ZkD òWÒ$R‚?>ŸôÊñš•ÓÜmGÀ©Ýx¶13TsZ^“¥ûøfž‰Z]ˆ›vV€ÀZO¿û³¦#7,kNksâë^ÊGÌ/ EJèNÜj›¹•9òmбå$k»i•KZtÞúFªz[ØrÄpz8ë‡ñùتíkÓ¨Ÿÿ@9¬[ Ð¾³™Y–o^R.d?ãŸn¿?õFfE9 ^p0´0Í&Kf%—¢±iåV!¥ÁÈ&–ºÚϧN V|]ñˆ ^á²µN‹(UåƒÑš‰Áf÷óc|&”a[z&m;{Î0’³­È îø@µL¸”õVüåE¥AÒw+Œi« I6 ÔÄß¶9ljgÚü³ñÜÕÕ$„dØ´¯~Óöê®W&JŠ–ÒHÈŠ†I/ê‚ǼåM’Uc[ñkÄ_#[ëkÞåÆœF d˜·P­l)Œuƒ!«"­Åš.5&~ñ-úPR|le YdLw`¬YµÆ(Â?V©è{%"ëXkÙL|®cT‰þ~S‰Zš™ašpæÓäV ©W)«”*ÀšLvn3,ÕÚg¿0]HVýµ‡~pð! ÷ÛÿÛY;&°XkúJ6ö&ÔQŠIÑV¡—µB8Á1úkp óÄ v[íhgÙv©—€óÇ¿ÿýï]@ʽc´¥v0¼¨Y|C&¨õÔá¾›(µiб˭†ÒªEβL¡õÛÎÄj1V…^)ëB¹*%˜]eãõ.ÖZ-dæ°rµ²á&OÓª…ˆ@y¼ØTa) 9aÙÄËCdÓö¼•ØŠLzaÎÊ*Jq+F2„ ãc€›[«B“T1ÓüðOV»­ÄV¶Q;l «ô²ÙŽ!nÔªl“¥Ì§ÃÏo[(ñ³ÍŠ›§+²ªÂK±¥ì–¤V÷4•íµ9/¿!ˆei0.ÊjÛ‰Âl3$Æóá 7y#Õ¢øÝ*±}S•[¬´ ³Õ%=Ѓ³Û#3C²Ûê ì6‰Ôø<•#aÀ1;‚U0±rà,+l•w@n*ÇËRvMn™Sf¥|Ud²V/„UmKFŠ)ÃjÅÍ|¾Œ‘LaµîÁ¨xb)«Ó …}ÆÁä˜ sMß ¹YËËÚZ€Iæ5E®….i¬4îhebµ)ÉDíbò‡é;þQ¢ oN|C2w@$ÏRáÛäóng²Uj'%æé«…›-ñ¶È:R6C&ªŒa5†µ*€FTB‰ÉYa«íR{ÙÜbØz! j vœd°”ØüRd¶&d%VJ%Ua~«ýu]ôUY7y¤Zþ9TÕÖÍ@æËM• £qÑTfU Tb@JÜês"…‘m׺µN¦Êaid­™lÛ sHP sÓ˜¹ ë‹¡ìSFc›-œó@þ„ŒOl<ñ÷™üú5+¾òÆk~LÛ¥ðù§™2ÒHWȶñ€˜+ü\~xVk¤o*ÃÓ„KÁÕZ1Âa­ø½[½™_KV8OUªðBeÀ«n[À*^?+Œìã¯*ìøu¤1C-˜ûÏÀHšx ‰‘E œ@LóöJ³Ú:ËKVØŠHÏÐ)ú•RJÄȲ¢oEËQd€U™^Süm¥|çËŠî*™”HF™Ày&»q%gá ¶l‚ ë«–ü]m jDã³f5ü™áÏ?ÿôœ>›ûð*^½,¼f€PÏNÀÖ;ÞéÑ(é›B€ÀÕÀ]ZzsŸú{G w ¸-1Rðìxµ™ôn]í©-È6ØZ”ª©ÕBa‚°­9yö¯F\Éç•·fÁ6<>1€lNÚ’Ù¬¶@…j;H7pzÜ.ÕæoÍ_a&ù·J å@¶L`%ø~ºc¼èYƒY3of­é‰ €w¨“*‹¬Ê/wJŽîû(‘³*…™¡¥în (òÄ4dóÛŠTØÛß6†­l-D€ÆÚ‘òm +7Õ8×ñý%LCög ãI!wÛ˜ "™Ô·-FÐd~}ùfÕ´LhrƒÛZËæ)kZUÌ…3Ç$ªVh+«j ¥*ÀÊÖC å²Í‰¤‘ÕÑ*‹ñ:Ñ(‡ë•mY ^4ª*Q#¦¤‘…ɬÆS ´æ)52Ok!XÙæ¬ÖÀ9äy.ú~î4â#ð»[bGàgkÎ0Y/[åÈ ‘ÙVhm Svöe%VYž}ùW›ÀzŽt&&Û`°È'œ22q¼Óµe6¦PEfÚ³ÅÃ@? ›¿ãdXS«à)ðœÛ:1’CÌÑ}?GaY µ_#ÚV¥\­†1Okg×H¤iTÝ+“þÜK[•ì8iÈ6ÀYÓÖÊ‚l©»X1YŒÙ™­Â²ô"ý‚RĹ)߉*i%ëq8 R 7$ tX¸I% ìÔ¥lnôE6OßÌç áõÙüª ¦Ê"ücÝHV—ñ‘Öšâk§ušœÇ+ßÍLc0Su$ ·œ›Óý€Raz2[¡Šg O‚M"‹çcÅç¶!~#^!±ÂºÀœÉdkÈêÛ)àש“¸l}ý•0kÏxÿ1M=­8S[ý`¾¯Àv'ï{–̯Ôôd-„öb&ðl‘ãÕNì9‘ñgR-C¡°rbÛô›•¬»ë‡­BJ­µØ¥¶º sË#…ᬶ3^›Ï/ˆ²¢læðH&¶ÊE2Œ°µÒËê(ÅùfÎb{+NÓ¢Úô°¨±B8}¶Hc#å¥` ZÙl+LceeJ²ÖJ€xÛ¸18+\m%“ùðךضa”—ª¼™il“Év–”Èø®K6¥l‚ô4^›”ù7ŒU!žØ»Ñs·d8ÜÚ]91™ße½‡½Š>/~ñß‘寓X̧{à#j )i.}¾G&£Á·š“Lª¶x[ 8¦ÅÀg‚+Î9Y…xÎæ7|²·…Žºt¥dয¤/ Ÿî.“¦!õÊÁ6=ðÿ•»¢Í€ç¦;ÐxM²€ÍÆ^¬„CMའ4²òIf È:>YYãá:T…Rb·šg&x"Âþ T8 P^_[L“S:~ºM>‡"˜dô¢—ÓH[…O qCbL‚& 0}þ†!cE)’aôªª¾˜ªli„,&-Tn³ºÂ£ÄÈÂYUÎ!Þ@…VJ—™¦OYÙ=&[A°Öº§WN†ÏÜÚã@ö¸¥j„ià>ÂÊ«µÂü; ¹B k/…IÈÁJ†Q˜?Æ ù”jLž­Rl…m‘y+§÷³{ããMÃ÷i0sì¾+M‘¶7ù4®¥Cñ¯¯Ij:=^y­›3±Up·m˜ ßõ tϘ›Túzq˜`|å§Ó¶g¶i”+\à1ŸÊ{À0“€”ƒmÇokMÐd¾k_k€Àš¸í &Ë<¾vð²ïqºvšH—#[Qk$ÙIÉ“3€”ªœ¢SÃdH²Æ AÚönô(m[J…pÎ4°B©ÖdMB,Jñ‘~R ^9†f¡U!Ež})qèÄßüY˜Ê­dÏø6€ª²YÙæ¦K 1=1¬œþ¬þÈu¢¯H5=c 5¦i 𦔠psÀlKY«¸é"[­•³3ž˜c¿Zeƒ”­ÄÊ­.jkÑ*%¤²’Õ‚SkµžP}™§§¬Q% Æ'Þ<ôH P•mž‘yŒ*ÀÚHß$ `¤[80·e®6 ®ýçK¼.µ+ÕH%‚ ¾·ôヴí8²´­ã5Oæ”Ã@äRµ~ÉÛöô}£î˜Ltì¿ixÎõ•¥l  ع0 9Ë"Ãn˜‰ÈßjZ-¬"€^ñ•ó'à` 7›v€×Àêy[Û `åYaæükaÍMöM)¥¬É0@Vóª>¿ ”ms‚mÉMmSá7á§—ê·ŒŽo/YÌH…ÎÈ–œ­ s¦à‰më )« ñúò‘mÈ ˆ¡™'–j`%Â6†¦ò:"1ɬ&7›ïzÙ®Åü9HQö)gÒ—O…xÃÓwþ}ØŠÝLÿ¨-ó3Ù}“;¬‘*`ÝýhŒÑo5^ÀZGÀØVå¬RÚ X˜Š Ð:žØRÓ³½u§@‰l—ã,H[ëið„TU¸¶úH%ÍO#âi|÷ÌJªîRæ”*̃7Rí®Ççíå@\-@–•§/ÕÛ^_<Á.ǶkWT!qJb  aÛ²S"¥Nï;U§ˆôX«²6€•›x·µÆŒ|Á¥OYÑÙÓ8K¿»H Àeõ­WWá{¥4fNÜq`%…,’ÉŬ%RHѧ˜fgÙ7È2lìæa’³q+%L¦W$LOé…É“r£ž îi*âiê˜8+ʺÃ%sÛýžÞœ‚¬æ`U¿¨u<üZÑo[ëÄÈ ‘s®VÓî‹¢¾Sn%‘Jb€3ýýP¤‘RÍcxÛ4¶°ÛvÿdȆÙð¶é°’¢ªüù²{”^N¤È6«òâeÔ–âÐ$ú’)¯c[ä ·ÕBßô•ÐTXGSqæ‰÷}HC¿—Ù6ÿâfvQR UùzÙHµÀ³í+®;I9+-#ÿxŒˆÉ´º[¹Åk‘•.È.S¹ª²V'‰'.›øÿü»Y)Ò¬¼Y¦¤,¥­‚»”F¯¶± ZÖõw„Ê¥¸u˜ƒÉÈ0bç²L%ÕOGµ3i†NN&ÈXñ„e¥lÇ ¥h¤çF€¤‡}óé€Äéms°¥Œñªk)¶s€¥ºº£¾A†dº÷ñ‹/ÕJ/V Ø®]üÖ Ó[Û¾Y¤0RGà£oµd€Tåmßœÿf.Û}®ªì.Á6+kåfHÓVÇšzC2)û¶Ã¬ßmÔÂqFÉþh7’¾ ÄkS;[À o_Œsa"kaB²¾úä'¨Ü™ 72\/«í”mésP.kM¶6ÐC4°@ò©/œ¨;„ñ# \ô™Uî£ “![…-[ÑYbèyž‹þþ– Q²3ͽCLzÎ}„É|Ûöç@Îͼ6˜Z@hAck¬ÖW–]¯^92ž o )Wäñ)7¡TcSžö÷©!mÓ7e‡và gþ4Ê1auc®‚9`«» µ@Z‘<+Œ'¥d#m3å}îÖ‰´hxUJ€¤†ÔIiÈHÛªlá‘9XÃ40 ‰‡•À]¦;YŠ€ÞJÐýÓcDVÞÆ1jaJ‰†/Û¹(2l6÷ÌÀjóZ`¬ôµ³eà ðò™`ØZ ÒH:b kšÿø $S5O2w’-²#ðé5#V%jЈÌÙlÝCÏcŒSyƒž! àCz=N­F.S°±JLkzµÂVÃЊQ>}×úÊ?/¿ª¶ÆëcPrÈ­l+ž^˜¡h6â ÙYÆØ YLå ¹5L¶ædKfÓu©²µR"kZ•5þwol ¶È×Ãy&¶f«6˜©&°Q³B&#èPüÍé{i&x-ÄèvWå€VʘܔÙ"Ì­;g¶Ýa@j—©E ŸV|&ãm™‹ FS!CYJYçJáù-_IþR€9)á™G6ŒÕëÚqh(aWç¡+LTVY€@تµíÃîkÇ›ƒßx±‡•8C«mÃÁ9×ÂÙǾÝÎgP•ãÁQ 23WžOGx³ñj}™æó·,íëD!úpr@“µöd5CÂbã†eÉT©U¦R$Oz& r³¨u²•§Ù½eåájÛòÏö5“~)“ÐÛæài rV¶h[M…pž°’V `Í!Y©¦Œ´<=EUðá3FÌ<É2 Ä+aµ8vOä€ På‰sèÈt? e” ´–²žŸÏCà«­£ZúR°XN“ÀÖT°1èôŠ‘É2±r +j¦°‡EYíGzïv&ÈîPUw⫝̸'  • €Ì¶îªš*ÏNøD1!«<Ÿám1Â$ֲ̛Ð6Æȳ›ÁèW«zç UB–CµYÕe/<²ŸôŽ -:Nµù#ÛêË-âr¸™_y Èþç?ÿñ× š6^áyÆý>îº4L¸ a¹©8GÒD&°ÚZk­öµæïé­šzúžšóv(‚¦õ=Ž”êç=sΙ|渷ªÜ'ˆLÔš¦›ªrR˜3 †a|%ª´6äëÏ“F•ǘYvþ=˜ä¿#ëh#»=šŽ\ÖVÐÛÒ<¬Ü (“iŠÏ¤I¸ô)X»(EÏÖ–8 ÜVg‰·*ô‘§×Å+Í_ÉÙ® ehUÞU¬WÎkšOšN1«üÛÒgžÞ¶.݆T±© ÙûÓ1™Ð7L¶: …V ©`Q* –[2…‘ØÖ=¾“f«—ZdKÙZ§mã9]'Ý”B:Þ7°ª°•Ò‚OV°X_˜l[¸Ö¥¬…rMáÄZۦĬ)A2+R4RåÕJæ— Û6^2%&„{Ç€¦Læ%ôyÉ„’nB@Thm*_Èœa)â»ÂÏ"%¤ÌSØ–»™³pÃ46ÜO)ûNKÐ)dÙJèk„w™̳‘h0R½½”U UÜøœ6tDÕÛÂŒÔý@’Fá4ºrتË6_‰<ª”•pÃ0™¨C…|²­J¶Ö€P˜Ò*®Óç*aþ1‰›ÓP²÷Ë{qk²¥ô(ñßc`BÆSdÕ<ð ÎX÷PÙâÇ©‹®µl¶‰@_À¡š¿.Æg+E©¶ì¹è½ e«¢'ËäÕ#e­xšœ[ßÈä\Ľ ©1Êm³BÄDÂbäZ©¯¬7¤kÏ6çÊ;cÌuúüœpŠÖ4ÜDÛ”pþMeÅû­Ô#zJâ‰1ôܬ®ÑH²³Â‹Óãé¦Q.6g8þ%ñŸ‚ Zcœ®Ém@ëR+oTU*¡i0J[Y¼³xµlñ”R€È´zuI€´Å[?ž0§éƒ+é› ÐµÉúˆÁfÐ"ÒJCŒÑH$¿-€C%VQ‰1ú ˜J6@wLOœ›Hü}MÛäñÚað¦õÚ(á“sogÙôÄ4ïü]E$,è šGÕï—,[¨¢§±U¥/¦’@ë˜<‰—íÈïvÎÀ{R¸B+žªVn%(k$U&¬P耑]7×⺌ª|6v†V—)•¹5€÷R)ïø¬OVwQ9RÓ¾r'bh[4¤ªxëõ8&=èl·âÕîí¯° ßݹšmÃÖÀÕþz:Ù+ÑYÔ¦oÕO°#R¨6gkWÝýSvÛIEòïÈH×EÀ¤ò:ÊâÕÒ $L pnž¬Ç‘RaÃËÂBm 9;Kz2$À¯ R=å¥TáaŒÖs@z‹Œ×䔕°RbëÔ9Çg’ #`nñk1@kš?[ú"Íw÷RO}uoàɪJç/ë¹Sb4²Un Ó8‹à–®–€R൛¬Üµ`ئÙ*%𥪒åi'°mÅÀà œúïcªÅ4 h>å¸oV+/·C-tòÙ@Š#½¾F™)’F–Øv  Ôø4ĸZ«ilÏ870¢1ð²=¼3ÓJ6L°VK/`3´­ÊÚ$UY9;§E,zl;©MU­l¬òi‹/…T—m°ôÖ…*2[J ªæ1†-~b7)ÒK( FLÏÄ6±{˃;iÝ;¯ÕV#žªº¸. [kÃXhÚ²’JÙZmÙax2M;&’ž pŒT@]l3«Âk>)[{ÛÙÒ0ÑÂ-qîǤgØ V©h`@‰FÍÖ ðª6gŒ-Ÿd€ ø5qç‚Ká1ËâEøúÊ2/`Á<ÿô­xàæ-ª(W ÐÌ–S!Þ0¶çÀßoO3ÒðmWÛ¶õNw®}úWoK£igÑš¾ΡrkUÍs ~=ÙhÆ¿}eU §Ö‚¬›O‹°¿$ðÝT—Júº?Ÿ–ï êB/8 LbLè‚G挼ò“Å$þ=KÓx‰uLÉ_äɳ5’[攪|Êê‹T®¤¬_y `Lžab%i¬R|`)×Õ©¼©Ná3Bf’®µ-Ÿø ³j6J[·êWa²†Ô¨‹Ú¡VNÀ$VÒ3²¾[kgKfµ¬àM¥‘o!+ÆÚ¡¸9wjäf®7¤Õ–®Ü6‡d°!ÓXuQB¹³ÄtÆ …Â`R†ø˜Aª+Âw¢dW~†yRîD@dK-Þ6Ÿ.ÆH)ÔzUñ[ ò¡xJsêõ¦ÒH‰lbæ€BM¯Áç7˜‰o`«pjâÖuQ¨K[ Ö™ÔŽž¿¨cg©i)<¡¬–Ø–ÒZU«Âz¦±RÒôtæI#+eÄš¹T¼1Þƒ ûpãÑPz%˜Ì§v´ ™*gâ|ˆéáÊ}§©*ž'À3s)²Î3™ƒ-MÙêÂÞäV²ç{Äc"ÂÈd½Ý¤-¾!Í“ÞJÏК?fŸ!rÄ8·}šdÛJé8Ü…B¶àœl®)rÙ”Y‘UNà O +ôHƒ¹4Û4˜•cYGÀX+9ŠïG˜L9’¡”ê71¼è6¤ðÜÌÜðRÜÒc Ùmr&)eÅàKFæ Ð¾Fl%Ð ³ÚÚu®u„Úµªª/`Nž”Î’Ô}éÎÂM¢0ÎHÑ1izy[Jk·Á™L9(·•í|TåY»ÊÍi+È:\Çþ¤¿?GÙºZtGú×:fMá¥òo›OÛVŒ8Y#•Vs<í‘tV˜N  qJhš¯51’ÀíÏÊïRX-úpsä¬\IUôyÆÀ²™´&SnÛÊ$ÎôxšUI!E…VsÒ4mc85Þ;dø +i0<š®°¾Ä '0†A¶.`)Á ÎP* ½Á˜ãá"% `­u[ µ¬U˜œ!++}¹šæà“ã{?“4L(Ãø‚ ¼múm?5ßà *gÛTÍ€?S~Íe+ÂÿHÙž~7¦'†qÜzšÎ çÓ©ç9e-úÞAîqg+ë5`pnŒ^ÌüÝ}S!•X+©öí;+¤*+çµ»g:ËÒ[wê*†Ã"¦’Ȭà¥dðÑE*Æ–¸‘ðÓ)ÓEᑉÕnNþ¢r†nrÄ"±ZY©ߣáÜ0˜|6ŒBnV¼,¾ñÂÜNãyÖ¢Ýé’Y㹉mµ&ñUF[Õjwj%Ãôå0% 2i†Ö×í²Ý;ƒßÅ KðCÆS»ú¶"wáR»<“ô0O«a[Á¤Xö/L,øÔÈ c:¦_DÆ›*ðÎÖËô²R­<3/åÔºÃÈLÓý;‹ûé=I@aµPE|O!Û5æL0ÙNǪBΑÖdxÁ¤!Y5sY«ÀÈ*Iy+Îåã ˆÎ"•/ØÒÈægI ÐËzÙ"m‘†•›‘eUIJY)«À#Ö 9à5Í )ëŒiˆcêØÃÕ¢¬-Ú@†RÀ™ì~^f[÷,L;Y#)$ƒ¹¥o%ËDJtWM"åÃHÖ È‚Í<«ÊmÙÖœUÙº(Y«-Ax>ÆZ8,%€f¸ñ©œ^; lUýùÊ×HCR:W%HnJ [çìÞ@?‘ÔÒÀñVL‡ŠG’5€ÚÚ!cˆ‘V“¬ÊV(ïÚ)i ¿à'¶Ú’MSI‚H+MCú¿PHé>ó”î\9NfÍ Ù1V¶ôÖ® Ó¸ÍN·Z_MÍÀÁCa.Ûs9ׂ^Ô¯/Ì¥DìÉ*ÁÐdµg$…·*AV•?¦lO i«Ü*f[-PHU>ý|néYø¤—m$ <¦GðÇ?þñj7ØMILd5Ô­R”3½ñ|;dWK>=·Êɺ8d €!” @TÔ1IŒ´M œ²ïMM`òZHåÓY¬"¦r´žÞEÛ¦íšA–϶¶á|òTûC€Ñ)”Œ°Å³µ"µã€ÏY£Â Wþ±½ŸT¡æzåbLΔÜð€·V/¼-2AYU¥Ö‘^ì©‹²Ê'Ö±î­‘ÉøäÏ à3“ ­¢Bg¿ ÏÉàRµS>%ìxæEbÌÛÅVPNÓµk„Éá´^¼Zcx*_‰#‹„1(·Zx©¤X3'f˜IÓv¢J66ÉÄ–>óz9á9¤±Ò¿V]i&¥d˜¿#¬/h}5R%Ó‰&ð²îøî„³S¹µ^ŠOŸÀW«;7Ujo°ª*lÂX¹µaZ›IS «É1nælà §$nªN„Ô ˆfH+ŒiU"•m÷†ðLà’á‘Å*kKPáºs«œF´­Õv¡6çÖÍ@¦(‹iÚlñ"¤‘ð d‘&Y«i;5€÷ãÙ‹Ý{Žd+kõtÚö˜x޼G¦¯­P‰Quô¶õB–êÒ#e;=2^¡ Dªâ‡¬+^­ÔĶ·ô|F”çLà€x¢‚7$[AL&â()t@€`æ fýVd€f 3˜hËãV9—]ÙŽŸL¶FV±i¡‘`Â9½ê@Ìïë©¿Y«Z&°‘`Ÿ›-ÜÁg¥P—ÊS6y¶J€‚UoT>Ä—ÞÍä³r²ºb]ø0,UÇÉð²Ä&ô* ”YTØ ¡©5¥{ÆtÏx&Ë*$ÊsÛÚg„Iµ¶»‡*dE0Oz|snŒ)ë^ÖJ¦AãVø 1«m枉mV“; `Û‰Èlc ÝLÛºÜäÑSv°jWǘfޱ¶Õ…»Éø„¥7mzíSÂ?‚ ™ÇÛ [¬s@æ 0LS•­›„µ¦y³x[Ò×Ë6Íi-¡Y%l+]cÅ"œ©Û”EÎK–;†@û¶×õ|–Ès…iÈ0›ÒV¨²ª„lm[›ŠI]èÙ†‰3ª¥×¨á'#X [)è¦`æôÊá ­Í@¼v›P¶.ià˜€’Fmå)4nàºÀBm¦ÁàsF†ÕâFÈæŒIY;âñ°H‰tØ^bÍ>¿0lK|í?-F*éˆÊv‡pï@†N&›Ìš݉î*Æ–F¤ñys.­mHb2¶‚RÕœóIæKÓ‘i„’L0dÕb¤˜äÙ¶¦+UhçÂ0l %d)€ükÉ6Yk²ZÀHV@똾blΤ¬ZLBSªv=š ñ4V¶ÉÔÆk*£ÊqD”šR­­È_¹Tžô¥T!)iàÄ4¶µkþ²JPJÅÐä\#ÛümD-d¹IñÇLRÚÎ<™-ÒûàÛÏí¥oNk€2œ-+ŒBúƫʺF²°*%@…ªÔÂÎ¥czʶ=#šL:2 ’d¶<»–ôp½Thè­ž¦K€¾ÛH÷Í?}²J>.÷üßP.öÐó$pr)L€aYÃwuVS©%%î8®…RVŠXÖJ@œ¡­=)+Œ'd 8à#1µ¶Râë K5˜/2É¡r2Y‘rCÒ`h0 cà>Sø¾âö@‰ç̪r 9›ÿôø>š°ìfã³Ò c«Wc·r6 ²#Ð$³%–UèOøÕÆxú³ÓI©šƒÙVÈŠ ß&ŸoïxÄ “`²FåFÜŠ‘Í|$М4u4ä”™tu‘o8g“Ï9††yž¬ÿäj|o`zUæi<¤¦¦ÇaK#óT(ȤôZI©”[‘ü§gkûf0º÷LOÙ$RîÆø˜Ž„­3'+˜8‹UÐ[iülª²%ÈRj¼ˆ!FšdÊd=PÏÎE“Ù ´…•¼ ^ô=ÂVª^[† 4 I¦¼.'ÛÀxL½zŸûÙFÜ&0­’·ožV]XÉòô•p°í ³*…¯#Í•Ÿß6øãr£ø’I/¿T÷€øL¶­<f ˆøY3+‡‘(lûÞ@·§£lÒ×eµïG½‡ÍPJdbø±Z< ¾²i‘R S£:JÃÜ^›Á–xdµª€:ÊšŠÀªW†oIb©JTU˜3¥P‹ìÒð¾B‘ôB!œJ2ÃKù,¤¤ÁØæiÈ6+þJ¬æ‘…e­²RÀñ ¹çX9`UX{åü#;f-(ÛJ [¡ÊªDaÃÛÖ¥”YYal­¶JjdËSpÃøÞÆd?|ŒGrÎÛÛˆœð«'Ÿ”4ô<Ý©Sy/‡YÓ< ÒV¨Ý’ad‘‚òJΕ¶%è!Î!>ñ†_a“Ì“ž @d…ﻓ¦*k2VpÙR0Ò hŒ^dc›I£J¹Rµ¥Öš8ÿf0˜ïœ·¶G c¨¼¨3,ó<Ïwæô°¬µ!µ€­ÈÂv¡¤i‰ûÛ)-¼ ÆÀl<¤PŽ€Bšðø+…_ Yøeš³ƒèbë*"Szyð‚Faëð<³5ƒÂzEÆ·šYêuV[ ‚{¦óc ÷ÿ:«ÒWº4¶jmUpg±-[![Y/’^ÄFåîµÄt´hd4›òz5vþ • ¨61𛾮ç¼RHM‘cÄ ¸÷îZš¿rÀ¡*´:…¬ ”²$ÀŠlc“)oþ»Õ¿^Qú®ÑJÉMyǡϰB|7©ß¹`YØÚT|¿ý3¡o¤ÿ4 Ù&øX&OJV»O)æV÷C扡Dªê¡c` Û&·V"5&L“Œ›HF#+z!ñZ»íUÑcè{Ùê^¹Õ– ËU­Ö"@@i ¨]aض¦4=£ÌÙ¶gî~wçà9׺­5M†d¶Ú‰pÇoÛ„ð4:j]–R¨jŒœ¥Þ„Þ.«ïŸœë8O|±‘";fMK‘5Òh6n=5¤x{ÙÃTZ‰)ßIêw½™•žìYx ß)á¿ñh`7É ñMU¶íå@ìÞú8ÀÆÐß{(EéœÕöRGÛÂV|wç5ƒÆ+· §‘J@æYeOÓ”"žI§°v{üóŸÿ”–0}É6‹&°&ÐŒ,¯^w[O÷i4+,˶òª:'R6ÜyŽéœ ìšjʳ%ËŸlªM\ Y7BÐ7 çŸ²ÕÌÝU 9`î8¿Ìרª²‘¶Î[ÓHÝ‘”<ûöÄlÈ[qÎX³…;£-ØÊÖü¿²tÉôøÖzå“ÑTØšCŸ–ÄB‰C¦ªI¶¢aêB¨ÜÕ‘Å×Ι¬^ «MIp¬¿?!ÞëªDªªÂJ0ž+Q;)O¦‘UTØZ¶Ó5Éܤ Ÿ¡ª¶u¡¤2QRà•”M‰WkU~ztÕO&p‹± >ÖÈ¥ˆóoų**븺Õ*¹#|þcVR…0 Ö Ц¯NÜëÑ R…­š¨o[·!Ûã È K))‹½ÿn•¦ÖR}0óTÔ+Feg|‡›ŸLÕ1ªÖÛ&‰T^àu¬/М¥âo¡¤Ò¿ãUn­oM9Ø:x¤ªšN¬,ð4n[—¶ëX‰UwÎb§Ë'}ëª ´ªÕËÖ·ŠJ¬QmñÕœWÕ8ÄÛ’ÁÜ,€ôù›­a”x¶VŒÛR½0Ù~Ü®©r¼ÈÁšs}m Îz!;à—>AÚªò†[EšÄ­`a<¡J_^]…û‡ èñláã{¯t«ZçÊÇÊSIÎy‘˜:"óGÂ<¥Èdd]0R¸:‚ ë¥VÛjNWT—î*|%Ÿo µ|˜gbþZÓäoU›¹TÒ ˜¤ñðMHüðó’¤iÝ„ud%Þ‘šÙ$½œô9÷¶4’5H`Ëж. ön »¥Ž&+¦TXm<Ì Î9’8=R¼J¼ùËÂð4ùèOý÷[‚˜ :Â&Ùñ rH`»‘˜Û ;YÊ Ù djÑŠœÉô«TYâ ë%UùÞ¨¦­EÝ Ò$v„‰=‹=_€ìŽ|Þí0bòdd FRæ/¥Î*R™™áôy–ÍäóÓs³}õª0Ù¶rx°òªâ[‘ÜàÍæræ³.µn-[;ŒPÂäû‡ Пԟþ©`Ÿ4¬-G€• %Ë‹Åz¶ÍM¦œOµ¥Ka+Y±º|¹Ïk3¾ @Y—JâSjŸfß]Š7LU¸B2L«Ij­õ’*»”­.5Ê¡µªaV¼ZƶRâÂe¯ðóÒÃi¤¬p:+óGÌáènÇ”ÈÌmÉ&®i„•²Mo¥§aÒs*l’ʳí’ëkÍ“ƒÈÐZ”U+vئlJÏ%M&_ƒsuÉ€HÇñ³²… ²UR7©— UùúëÌ“¥‰ÌÇZГñ\»d¶Üšj+Ù®{z-Úâ=T†” [>d¶²Íßlª0R¶VMe1‹d¥Â4¶ ê‚G nÎ.…·¤º;‹HÓ²R9[eól•*›‰•†[zb-FÔ(Ò(”¤4O¶e­Ä˜B_Ê«-žÆ¡à˜WÏ3ÖÀ®š&Ù²)#ë… Dž‚;Ií\¦ éÁÕݶ­zU"ÕÌH†•Äô,0¶dYÕÔ–ÞØLXÁ¢.@OÄVÐßäyôÄ•0D¶Ö4[+Á²ôR6F‚Ä‘¾³X때¡¡ÇŽà•®ÄZªù­3'®YæÑJÉJ¹ñj ‹w°Ld9×¥¦”ÍÃMÐÈîDb̬€ZèU!FU­“)¯¯Ù0ºå ¼ÓÑTe*¤ZY¯ R”MŒ×‚, Œ4Q‰ÖÚÙvLXp”ÂÖªxË×÷Ï~Êi´à–³mw¢KÊįsæ ûnÙÀÈÆ¨)Ï"+âfJ¤S`”³Â«B6 Œ4@#u3 hTåYy ±-M—“gåî\Ê¿võs‡,%²0†^x‡­ÍСLE#l¥¬¢©µf°ÕTÖ™íŽÆ3+•REyY<’É.ð1ð•`TqÀˆÜlûI伬™IÃØöÿ PX‹V/•!€{(pcà…B|J+FöfNŠ›I´^­òÛäünT2@ÐTÎG•­#`àÄemE}­‰•Éemñ‘‰[1e‚L4RÓZ¥¸­0P/#4ªð¥¬JMÊØ –²•Ͷ›Të)[Kñ”M@9ž•e%[%@8q+Fj/m¾Bº†A¦¯¯)Luƒœ@Zã[ž^—Æ áÖ”ue:Å|0²£D`ÂéÛNHÙCÖ„9Xñlñ&´í iºm|@–˜ÌÚk†QkkZk&ôYÕΖÌ*&ª;æÐ´6\kƒVµ‰kš³çe+r¶Å‹†£w¹¨¤^µ`ŽŒ¹g*À€»&/i+Ť*&UŇsÀäF hf}¥\HãZ•`Î%]õئ´Í—´ºŽ,bh_©W¼§"ÛˆÍÑ Ed½`A9[)Ôî(¾—Oo°NUêJΖIz™ƒCß„‰Ï±ïã¤Ç´¥QB¦cæ°Ú¼ ÃP6-&|“碗F¢{'ÖHÔŰͼõˆn4°”-ÛAþN¢c-ÂÍ“S0l0VµÀ#Ye >¶‘m­Í` Ý÷Ë«IXm¤ÚÍAI#)‘Ú«r=>߀øÎ“X¥ÓU {:¬Õ¶ãœÉ¾_RA¡§#êøž±Ö•lŒÚ‘iÔ¨v|¤­H Dfž~m&¶Ò7Rµã)±Å79œ!F¹³!mû·)üäÞý°’¥¹òÏw+þÝX¼ùÛ*é J ùY•bˆ!®/¾rÊ£I@ÙµKá;…Ì¿5%fof%²U3ïNâÕJ Î~Ó¥€•8¯1bdUeÎJØêHPa©N—2[]èLC® Î(ßOÐ]á¹uʯðüŽe྾d±èÿ-]à 5ª#fƒÕ(Ÿ†O„ïbëU £ÜüV‚†ÚU 9­•OO-ÁŽ`xåŠ åfÅài`ÁM9Y/”ôöJÕ…3@Qžè Abd…Ó ØZíŽÄ«€Ôßþö·¹yJØJ!Æ“¡B>˜ÜòÓј ¼oÓß´ÈZTμ­F˜ ‘{ð ñÈky~ ôæ4CçCc$znÍ–ÿd5êÚi˜¨•Uȶ©f²Öª¶‚~%@½ðÍoK)IMÃg7–¬ÁÔfµòfK³•f®]ç­Kã¥ë®¼,s„ë‹èëΠȤ^ῃt{ÈýI©BYUÚ1Tè5Èð¿Q›¡VšÄøÊ+)óRñp†‰óA:Kã|Ên¡-YUuÏöõ¡±-ÂVÁ¡Á¤`+ò£»ÿ"__4oý/_w³$[N4kxÐ3àB1ãïÞé÷Ho¦·¨}ìÄ@¸<<ÿ&$[o}JYnpÛ­ C/$«]Ž<›0ó×°!eéõi˜œØ–&ÆÇÔÈȼ”Cq¦A–] @ ÉYØŠ¶ÄX£zaXÄX·æl]£MkD™8 ÿ4§·/°×FZ z•eá 7‹II^ OÖIÚî$ñ]GWƒé³Á¡vÉð@ÁG`ÈÖNXÎ92ñ g<1 l`VÎÕ Üüéô×RÙûm¤PвݘcælͤmåÇ÷:7CÃ7Y+ù¦~J â>pÎ{.>!J4r“} #%¼IÕ ”}ùR=ÐZ«%XI@9Þ*ΈwH_ÈxÌŽ¯…¿õlÔ•‚ŒùÄ1‘M•?OG6•m?¥hÄõ8Ë™ã¾Qšº+µÄªº [8=PÓ ¥_ó\âÒËv-;W“eÎÊxH-š)êÈa®„C©²˜‘¥l¥à ;][>.¼2AŠ|@¯>UYe7IcÛ·íï_mVM²,P¯Ä5rXcËŠ3ÁÅȽ¢xbÃÊ1Al›­,V $K`ë·)턞g7°Ü6̧ŸXpÊ.‡‰Pøæ‰²-MµNÁ–g&ÕªÒ]е“¢´• ÛšæC܇TV<@#®å§*ÒÊJU½TuØüÙ&#€¥l•ØRr(ÕZ¥ðm)eO›kî˜Eþ‰éE¼[²–D‚÷%‘¥š0‡È[ôqøÁ”Bæoí’[ñ¥È¤œÂ–} «íD9Ñ$ƒ»)A†‰´bÜ@Îô¶æ¥æä,šÄÙÆCaÅÁ¶ §¬Cd9[«²*±UÓóÿ šøMSU«¾3×´­1 `ñÚö†à=}Œs9BæøSsß빬{:)Z¨Í¡­‘ê²g!+%â3̼W®_*ÒËî£é®*Ì$7k!Õ%(êbmTš1”4É(æ…Év¢lëUIت„R 0·°vy¼ Y1CàË}~.èÃAlÛð›‡f~þW€BQV7hzqÑ÷ùá5£¬¦Ÿ©ímz~~d4¢94+"ùÓwYUu˜u!£ߪÚ%–mK?Ÿ9”ª]+¼©VØÁã;š&JÈ*±5~ǧ™Ï ¡¶ÕœœÉlû<¨‚YÑX êUI)LG6d>”¥ÒÃ^4‰Y[«ŽV‘-~nHaâh²scÆgEÙü¶B¶«øÇÜÌgŒR@|å|4ª & ±ðóÞ-a¤†Œ•y%gyKX 5¹Úšv9¼å”4ùÀ ´„_¥€Äºp àì–£îm­4‚¿€ž¶MÕÊ ¸ûo¶HpêD@¡ ÌÎ<2žC†LÈÂFÂs5•¬úH¬x@‰lU¶Rn•U¢F–¾;쫹Úüé ˆmåMT²{¥WØSƒl0@–-ªD¤6ž×OŠÙd52 Rв°¦½#r{õl™‚À1ùDf—ò‘«)+cÀÖ÷sh«¤FL`1ÿô]ãívÚ-È”àMΡÖ0¾*«˜jaÌZ×é)¼2¼$2ïÏðª&+GÐË1   )uOv~›oª•Ä÷ïƒéÕo‘UYwøZ …ãh´ÀØjA_ “AÛ®bW—•ršÎòΠ6ÏÈ:¬`µ²ëËS*<·:¦‘êÜÃ&CæIé ¦ë+%Œg•BÑÀÄ›°O@á¦í˜•¨’¦ñ&$¨ÊÖ0ÈÜÚ»aÚºÈΰÕÑJÐV#á~j'eÛa{÷j‡lT)í`|±;™!^­’Ül›Ç œ˜ Nà °E‰É¦2lø†»|bµ•#;Ž^¬à¢Ö²HJÛ<“¹7)Ý|È …l)Y%é¥7穼¡£„R´ Ï@HÅ‚­Ï ²-? s(aË­3âi`¤sYû¹K¶^èËfeuªð9ÐÃîíli„ÏH<½^ÙrÄMˆuIÜ¥Ôºçn^aÃÔÝö¶<­ 'kªzÉV‰ ±¡{lfÙ–‚ÇlHú™ó!Ȫ*Áá¥ú 6UYkÛf€1æ/`£÷ÐC—bÞØÉhš¿rY h° ÐT3g€+èÛR†ÄlÉl x+Ì@Ù['¿vgKcmøpíRⲚ•Úš:{·-‹TNÜœ0ÕhÔm—š>M+Ù”áÖUåöù)_“ü›@Jä¶r Œ$n¥Çt‡}ÉÀJñ±%v!¢NK_j'¢Q[kµ™7d­5=¯².‘Íf¶ &+bê‚·íÔRž”a"g‚‡·u²@å001ÞJà ®-rØ–¡¬hkiu4L ç²ms‹ŸRƶ5‚)û׿þÕÙPöÒ Qeïh)YB3¯¯­ï;zL¦zHw xäÀ³Ò{ߪ`̺*¯Äj+€ZÐØ¶mKà»Û¶C¥gŽü1ºßzN‡ghí‚È̃ 󔲿P +Êâ4d€.*YY«ìéý­ÝHôRVÃD§Ì§Æ6¦ÆëÇloKl|ÓjR)~t)ÑH–¹ª¶É0ñͰÃÚ >Vúœ»Ž£u]¬ø”Yqîïüjä3/vù kýÚæ0C-àšÂ²ªšÜõ•ªccì"» JÇo~½”clÓ˜O+²ú5¤V&ÖfS«iÉ„f‚ŽV–ÒÖ*0E]âà v@°êhøp)&€PKÀ´fh[è¹l`…] uVH>ÖLºX[å9dÛÝRÚ¢?k±2d¶R¬ˆ{vÜè½ÕÌ{+0”u)Ûc"ÐS£0Û ñ¢É•ó”¢Qc¦{kKß`)¯ê|íT‹ìõÔ–­Ð–&YÀŠÉ ÿZÜÌçÁ0ŒœÝH¶æ<êûÔú˜Ã «2hž=޵N¿#÷¹¥×Âê†rà6^UV¼*k]Ò(ÁˆNÑHÜTYY—ˆÉ[-ʬ0x8À-Ý l…i8l*â¦ÍÖÊ¡Ç$µP›yþd¯¶Ý†«nk-˜TÞÚHÙ ð$ð}§1ôª1†ÈæC©3ᣰ_9ÆÌ™ÀÄBJDæ#%Ü@<Ü0ùP&VËߪÊõY6­©²ZM&ÌSæ4¾­+Ô ëb¡E2p9š!@²©2lMsƺ7@ E7ƒQû–$Àƪª…m¯=ÙȺÛÕê"\E&0°Lˆ‘UÈnlK¶õrÉÕ*¬iYU¶V…ãa2‚@¸mk]𬬘ÿ¦ÂR/™ÕK`'Ji%˜¿#Õá·Š!På}è¶ñ~Ýo KÅ÷€ˆ‘ùŲ׃ ÊMbû£i×¢J˜Äš€6€Àˆ_OÔä¥ræ– Æ ÝEVX¶ÖÊoòs{p&U%^á™ã^ÎøFfR_ÛÛöüxž)2QRpHÓJ,à7ªrÛÄÝ @öÛ?ÿùÏ&èÙB¥9¬”µ†ÁV«àSW2…xd…§D6l5w¢ïÊL¬¿‚>~Í]¡Õ¨œî<ܶû„hÊP îÝ’Õ”ÌW^ÿ¨·ÃòÌÈÊ p2åÂ*ªd…FlÅ9Ã÷ K6™ÌjëÜhbæ@/ðºÌ¡òkÿ?O$ þÌtéWÂ\(ÌñÞÌV·¡p+N*MM=—Y¶³I‘Õ]ªÈÓzÆý^E½æÐøx׺Ø L ie[¹UÊŸ ºâªêk+jÝäõ¢ÝørRŠßê¥ÂXÔ`šâ»óì iÇ^÷fØŠ§@Ýö–v|$qk²g+e•% dÓRf‹ÂÄd1d]c)¤,ìt44f-²Å:â7Me9ó‘íš'†Œ Ç”ÏLF }Ý•ˆ‰)•cM9Ò!V+Èê|@GUáÄVJ­‘²­M‚/e•ʦI_­U Ky|ZˆÜnÛJ,Â#ÏèÏ÷g²üñd½µ³MˆO ¯«3MŸÛRÜw´s5â°Qá¦:¾÷¼|Ü3s…˜ cÆ0‰ñ"ñô¤ÂÄ:ާof2$€Ç÷ëÜéz ㌅€C_û^0'fH¶¾pLµAö4þ^‚϶›Mwæf–¬Ym  ]—Vb !{çúüQ­ Yéζo•î³ g…Q˰Ÿ>x¤Ã&`Ò£©°cžẩiœBÀƒÙÖ΢)ÚR–j-‹$Àt]¥24*@@ Ke޹ƒœ¥ã”Ez%HXÐtQúÊÕ Ùe›ÕNÊŠ€Ižpç­‘ms2r‹¡GN–ÏH¼ ¯ èb]TVˆäÖï %Act¨ú6ƒu¡¥­9a«`H¬û+¦9óÝËT‚‡&‰§Á·bàã~ýmcd ÛÒ$ŽŒ¿¥¿¥²je‚±*4v[Xà­¥Úb ¤àïÆ7Öû#[S7ÌÍ®°Go+`U%.“ÞHÀ²iÈD!ƒ¥<2µÇî;¤ÂpG»™3¿˜³W”Æ´0 Ò–‰-™còÛí÷Ÿ‰‘‰³U^÷|ࣩ{]ˆmcVØ&a‹Ü0™X5UÛçœ÷s¾ÀËjdU+ÒÇ4pkd¶Ý9ЄºTÞ ­ôÜŒg+KC¬¤ŽcöA¦qºRZµyðÉæA š˜s†oß6·Z[ ˜h”ˆ[úû; —ŸÖ•T¥}¥ÌOÖƒ`’ ! —êP¶š YÌ0•¼Ÿæœ†­*zŸ3~>ªÂ <}Ùôã¥6¹Ž¢³ã•ÛrŽ9-¿ï?F ŸF ›A¨¢Lp‹Îwe+[%4Õ¦”ê¸me9©¦¬rÀŠi’dùgNÐH„€¿ Ñ)h8ˆ 1Lå¿F‘Gý}±Y5†U\ËÏ› ëé¼¶ÝIåAžÆ)l«"ðf"é™4UÃ`lÏÓõR!ßõú)ŸR^JHÁ[J’Y+ÇY!F(oM g’y[kÀN±S;ÚR«LÔ¶Ýl/"ˆYSàG•m·—F/á—.[@V˜žŒ³¬ #µ é Á“ÕÚ 2o‘G UžTRaÛâ¸|ÙkÝ3‘íÁéV¨ï)»_¶ù'°ÕE4* ÆÌW~Þ |k-¸ %˜E÷@Pmü5>GXà3$ƒñé[Ýr*kµÕÂy)ûÛßþfŽ:a[O«k³ÞŠa2gU"È€µq=$l½’“Ò;œR#Y훡ì«ì!Ñp S"ËœF0o¡-¾ {?¬J² X ([¥š„¼ªœa$,L²R#«a¤š  €,g%VLb˜^Øvv@¤¿¥Ÿ»/%+rÓ(ëœËV^G")L¸Z²l•;Ž0O2)OЩb¤(ï ™ÐkíEòó²â1ZÍ€·âVU¢-M˜{.ëÕ<;~ôé@ ˜UžÖ> m{¬Ý¡QÉ Ã_HYÉîîóN ͬi )‚hN#IÁ=Sþ²4Ê‘éýþ” ¯)½y(3¯#²[RR¾YݪðÀpÙNŠ”…E@•î €4çMž,¬VJU¤­îÖ5í ”ýpQ••cºv2‚ª0LXõh2‘e˜LVyccAFÃ3Æ– ^Uæ”ÕêBÜ•ú~6Øæ©Y× 4ªf˜¹-O£nÂÞ"%€õ9gÖ;-+€I·§4<[milclÚb¦aÒ©¥Dœ‹Æ¶Vx·“±Â[•gk¶Í“¿+Böì¤8(Q›yU[¢Z}…c*Y ‚F•‚)›Á–fdãaúè50rúj1”eb[I†:êRÀ¢G£¤q”Rdؾ†QÓas’U $½mL“ {©zèºxCˆiô¥©¾u‡tç|ð˜l…Ä¢Ú¥b¬Jo3´m=•ßë"h€­#ð”Õºv)K²|\°†±,7#ൖm;5Ü–Ì+(!ø´]vU@šÈ1@ú2€g÷©—Ù<‚Ïoº4b¤2`^Ú”ÊÎÚgÞ=ï•Øj“ݬ+#N`ÕÅ*4)šX‰‚ƒZ}*@ ±DÖ:AæÊ;|¤öÿû_2[Á žUÛR=*Yå˜3Ç Ø0èa2šÆ6¿4ä€CPžç0ßÇL&Es+ÎÒöõAÚâ µó ŒÈ f^íþøÇ?úÞoB…ÄYaDUV¡ # ÏãA4RSU>¦-Mæ.‡LëUÒ©Æm³µõ7ñzÁj)ûµ%ëb¹lkQ/¼0F$Cµ}›Pš 6*\Çü‘RJv¶@ÇI\ Þª žy7` w„º#p@U@-жÂWÐl9›gƒuð P ™è¤ s+±*)[á~hL­óÙ‹-¥ŠF6}Êu¡i8§g ¨ªogÁˆ ñ|D¯_þ¥jDÙZž= }žÆã@ÙÙüÌói¤‘!á4¶ÍÍZŠÃü)AÕžB>­H%¬ÚªbØ#l‘@S…oæ³`D3 V[¡T7i/aí\’¡³WK¬¶á·‚2@£œ§åU€$sLÎù(¡§Ì)ú:ê6t—"0•×K¢Y—nŒ­B¯œ'Àà‹Óà{|>ùWÞ¨H‚ø0+­37†­ a¨¤* q‘Â0y™ÓøÞC©[z–x3à…U©íº²Š§YS2…dî6!,ÔNF쪵ðSæz~ôrv½‰™HM©œ[i« ¡—‚…LÙ)lÏ‘¾‡B&ˆ™XבƒIªmì:’™ÁØRj¥ ½F•5+¤* [ .^vG0',È ™P6*Pà7•¾¶ ;©vÊ+¼~ç…±RÝŒ!iê˜Xðþø;K— ’‰ámUÁRÄ<¥šÁ=°²!¨#1¥-~“T^;2[‘-œy©Ê—ÝÑ´3ª³©’ÀñºOü-ÄØŠweþ[KÝHc´ëÕY-+W/tl ÿZSbîhç/6`Ç&&ÌÙ=­ à±aIIŒ•ò¾MlUˆ˜E¤0Rµ³fR [2k ˆmÅj“aš°”ìË·m|ctv'²åIcAÖ»+» $MVALƒ”‚Ýó‰!nžôVŒh’À¥*+YgadôŽMOl)ÊÛçóã‡>g­eξڪ݄Š  4'Ü-uF²¢FßÝçcl«ÜZ MåÖŽÓam…aŠÄáš’!•LÀׂŒ>S-o[m“°šÏ dÑa{çÝ$2ÃÆèb‘3‡9 @£¥„Ù§À¶Yµbˆó®+™ÂÊâeme Ìéw_<ë; A¶x Z|²½«ÉºíÆ8Ž×2q?o(ñYMÙxÉJYÅ-ý܃*þoíë_mߊì®…imÙzÆðÅ’?¼ržiÈòi«¼yˆÃM’ƒ”ÈG•v> ÉlÅÄd²”l×4“.ÓÅõ;À”é™\³óC¥vx¤r<Œ´M_­#(5åªa0‚ Szd<Íig¾;•”*Êæ—ÖȰU*Ã&™)˜hTªËI?7[&R‚²ÆPåžøt4­”²‘•X¥ð= ›²’uzÜ/‡º¨ÂÔh)& 6O#mfJ­m«…¦¦^¿·UR_Já6¬xQ/YበÃ\Õ¸1Œîdx)$-l­˜ÖN1熷ŇڽŒÚNGèaYw4“ØæßÌZ³‚‘rˆ·2'x[äÓ¨Dl».ð¶Íï*â­™ãù‹:ºp3ÀJˆ½3Ö<)~ÃàE†Jd­m¶½ÞçÒ1óz1I\aU½¢ØšÇV-™PEyæøþf³,@Ÿ Gºs¯47çb©çPw¯J3pˇպïD<š²R¦Ï‚ì 2%ÐÑ„ÂÖ0ÕªÚ¯v4ŸRÔ é©q&°å Ô+MYóÄÓ4Û;¡ò™R‚2²,,F¶M¹U ÓJaªj$«Ftv€ìlûÀ òÝ™åXªõ8}¿Ù˜ÈjÖë›rÇÜ2q3iqG˜nX°"ËéZé½yâmý¤Ì<Ù;¾. J)¡ä6[@¤éª5òþˆ=c¯‚•²Ç¿Y3H9/l¼ÌÕê®sÉò¶²˜¶»Jqæx~xL™ŒÃ¡mÊ[ñYêÛnÐÎ<°ñn«³˜*͆±eΡ“º€rM÷NÙWó±jD`NÛR•óÁ0̤ûɼk!«„`çʧ7I³ò‘I#!eÍ_SY…<«~°m* ™‡t©Üš§!‘QŠ¡”'ÎPÈ\¶iéõ³¦Ä+”ªª”‹Ê­d|`+,=Òj[­Že+ÌŠsæ¶™4'*)¤”BåRW¶—Öù¯¼7cm`$† êÕ´x#¶ª*ª2ÌôM. X¯åy¯Ty ÖþC–žØ FÓ‘)sf[Ùa#›GáÆƒµ DØR2ÄlH- )|Y¶°¶² «…6Ìv>ô9´–ÍÐãèŸŒÙæ¡r-¬¯P5ÿeÛ2y}déýûEÖÊ•¸:Ç' ;Î5û¼öæÉ!ÒZ¡µã5µ²Jlf>µïæ{Ólµ“êÆ¼fø_3[•7O@  ŽýŠÌDwQkÙBO,ÂzíÈmáºXWÞ ×û,/OV Ûž…­I6}pŸGbµx ²9#´ï8ÉbœCflŒ:Žª3è½1Øzè ^­Àì°R¬²ïTRlU)ÛJZ‘•÷ûƒÛ`::>ÃH€™g}KYñ<z)(W‚CÐ'}£‘ÆÛÓ”²ŽwR[AƒÔÅ k-lMeC‚GsPøÛ_þòÒÏæûûoƒÕÜüçÉ1µå‹wrîâ<ç;¨,^Ô%[o›ÁPx?”çi%vß ÌĉÉ!¾9¥o!Я/{uéqúùgJµðoŒLÂÍÐmÖBG‰tÀ™YL¤«"ÌH KÙªJsïìxÕÚxIJRiªmUp1Jºö&Á§É¦-Œl-`7æPÇèþ£€¾Ó ÍCCÙ`WøiÚlÄ…­’ªš #Úâ{µÃàU]ùé"Ús CR"9XÕ¾“PÖ¨¬Ôé÷ýЬi§s.Ýk—&OB¶¢±Ý0P":7íl×Z¡W ßÖœÉÜYšX‘ñlçYO£p[í2Ï-¾á›<••5ÿHŒî!½ƒ›Vª1à®H ’‹7Õd˜Æ0À‘Þ( *FÀ;,ÿ®Èj0ƒ™*Ÿ[÷ùšƒñÕö¼:]¶)™çÃV6q'…¥:¬¬*„­ ©yv9e;ì;R%²âéù£ S¤T%ZUŰÔZ7¤±}7rH)umÎ;°*©6YL˜>ЪeSé‚$®]k-4º+¯]?ÑU‘±BжÖRJ¡”Ú‚Eþ€¨‹'(Eé}ëë:·Âp1°PÛ_˹Ÿjó´ê+KÃP(/0M+‹±Ê¦¬Ì §Ç_óhªšçVH#k«Àf©fH0“~åà\d½Õîçœáþ(ÙT=>¶4Ü<&ŒQ¦á TH³̃vÏn[îPÄ]&À¯oÛ"1­@¶•€§Zú0YJk—@\ú|—Âôý‰d¥|-¶Ö˜jiÔZ^¤±¥lE–5scÓTÅDʰ6êÈëw^é¬rVè&iŒJ ¤±% d›g™[|Ûª¸¹2µÖ¦Ef剸ù­¢Fdü…1Tô•HålÅg…tºfJÕkM•Çèr¬ï¹dUù]\‰aŒÊpg§_I³Õú úý@¯C¯Æ:Z2Ñe/@¼öjñÄ4 RZßFÃ+¨uÝ•k-…/˜ž²;4‰r‡uÒÝj>}F¸Ýç}ÃwK”0s©¬0ÉZÙ:oâf Nwfºa´"ÒÏä&?°U6¬]a«ªBø6ùüvñ’R’@! 4¥'3Õù?k”ضZ*°·n¸èÆ÷tƸÖR¬ÊvNY7eÅX½]=\w«,†•*%ôÆ ï­þþ±™Fªvֆʧ.{NÙ~^ÊȬFšÎMªiv´<­d^)|)%ü­Óã`V‚ߥ%S ë^U[ë Ú2:”’ÆFvÕŽ&ë°MeeNÐ8iX;z)²>*R°¨µù»OS¶îŸ «R}³À˜FÍg%ui&R¬þɩ֜¢ªuTÕØVdÀ‹ÄîCA`+ex@ä‰1†5 šÓ*åúTYÄŸŒÛ ‰ÎžsÛøæ±vœª¤Òg˜r+@–&Ã6M}ó$0ŒÔ!€1ysšPXmçJo-øÀ¹)!n[SUód×ì÷¿CB¦WBf­W¶VŒÏ~Ÿ>O!+¤P+º·ª"kÑäôO&–’x†‰µZÓî)ãéUæ«8§ gŽ0Ú*¼Í?¿G6Oš­ÕþX9Äh(Ü‹$5þõj*©F’‚Õ6gng"U¡­³+Ù骺y+ìW·“M™§^‘ξvHUÆ †ïTp)>Ä^ELg™Œ¡lO“U[ +ó[ßTå4ZT…ÔEUÏ=Y#uc tW±gjM™­UsŒgM3>+‚|l Љhj  ÓU4*ž):>[ C2$FwúRÎŽ¬5’,¥Fn›a©È!,K ÈH…Úªò±5³’=n%‰cÂÖ¬”ô›_n¶x‘­-P£r`ŽÄX•P·â”äl•9TbBL(«À€+™vmufEV—µ8mî;ŒôNÚv‡µ ©ГÊ_ÖU`8Ãù[1#ŒK6ŒÁ0L ¯ËÍŸ#äO #­ª ³F@ƒá UÄö°{ Ý!&ÿ¬à‚“¶1ÍÐU4?’Ø` ‘Vótçðþ6–† szAÓYjZööù<}!¿C+¬Öj˜V…&éCÑTzIái00[&Él;††¯)>¦¬Ê¥¬°¥˜/**·þÿƒþÖÅTü‹ª6€æíe¹^MeÛ[zþ "…´ãåB„,km‹ c—b «ª±U¯±Í0+%1¶²]WÁ‡!œ€¦I’ñxJUþô€-ÞûdK >¢rg†e=àYåFPSkóUÞ«ÐétTޤ•YÙò¯ cÛ`@Th&ëýƒÉRò¤ë~šÝ.†íuú< ðVš&1sÊ®—v¶yê‰ñ86s½Ô®Py†iê¦άßËa¥¶cê(`1¦«Øx[¼,>A¤Ú¶¬U_Cfæ¾³œË ÐHq°µV…äã~¡)a++à FRö%žÓ‡ª™ÉЩïŸ5537¡Ä$  CM›¿”ìâ}ªh6¥µ*·*Ñ:[8OÝiÝã­dý"ÎA9A-j ÷•²9›!¥”í>eµ*¤€¹åc/^Ê ­)‰[Y˜L‰Gf¶ Ù0±èÔ¶Ä֜ÜžÌšÉæ H¹¢|è3Ÿ2CÊÛ|(ÃøÄ[³µbÂÕZ‹zI±CÌpµ€TLb[µn»¯Áü[7vUȘ^x[Ž,`—Ì ‰šôâ‡ÆÜ¼.AÌ6Yæ1H-¬” ÚÒþÊâzq`Ni€˜†¯1æGH¥tɼÙ(ùx ¦­²@¡¯FÖ̇«¥i°`L†V1ç…“ëªi|Üü¥†5Oh<…Ý!‡zá…Id•»ùnIyº>ÏËØÈND ¿“àçÙ±enÊRÍœ²ÓÁB—d •4CgŒw@A†ÌJlUbxUx±‡‚_ µ‡»Sœã]ÏV²4R ñ¹a¤´CZ'𦜠©ˆ&ƒE'bî%æ„ñdF¥LïNlõe+ðÃc&æ)â‡s£·óyð‘m­•’åcí¼Fv Ø„]Ü6ÛÓïvDæ ¸«œ¥4MPw¸§ã÷Ì{‰•ü(ôøÓs¶æ†1Õz²*&°Ûfh[k2‚&×ÈéeRud’TÃhm±’4JôŘ¡/©&ñ4Ožé­:æ¼+Jex&øÞvUVÌf¦d.š¤S›¥Z åÌ‘µN†ì…ç±ÒÐ;²CÁÄJȘÛv“Qæ“gþ²x«ªµ¶¥!H·åi%scVz²¹QV®vAÓU§¤i6kÝWKY6“­5bˆi*q4[XȺžV[d .Ìƪ ¦t.[¼h«¸ªS’øX|ßÒª¶=ŠøÀ¾ \ZƒÉð¶Zû¸!)7¾R áÍ–@оw¼*üz5¿*€ŒXyYk“äP¥ ”Å#…­Õ€5 Ô‘IÎJ¤0{m}¦€šV›!†‰h«P+æ´P‚§)T‰4½uÄdÈÚà×§Ù÷¥å91‡|bdk¼Ú˜ž·f¶mT)2¼nò~èЯµù)‰Œ$•›UÈ*ÑÅ*Õµw0ÀŸ,²FÂtÌŽÞÑrSr|efþÊyԈƖ¦Z|ã‘ͳùi(é{:”‚‰•RjúÓò;pcgÀ49ç •sV>/€aŒs%vÿÊr( ³-볓§¬F àŒøýj²Þgíj Ð×7O³¹d…U"1ÍÓJŒ”µÉs¶ugŽÉ¤F1Jªµ½çíš !9,UÖFª])È$ÍiäFR"˜ÄKÁ‚À*ãen<>yb ÀY!gâf¶mÚôÇë‰jßõöÿÌ0^¡U#oCí¤üéÚ¶¥”adá~âø0VÛj·Á–2†‰iy"­ÊÞ6A`+µ¶B-€Õž¡ïw掌œÆH”µ3!œUdnùÄ«±®~å¿ýë_ÿbÊÑÜD;éxÀdÇéžfa ¼_elU)éâhÒ×µ!Kí~a%j‰)»Ä[¤OC2©¼¹¹¥šœmÖÏŠI ndjñÈ4ÿûßÈ^ ˆûu­¬Âº[ÔRK)‘Õ=º"d3h-f¥–"(e}•x‘>¼ò ‰E$†¦ ö=Y“¤tØ#¨cŽt?ôHXVäÜø&²ý:‹„™à)™XLŸÆúƒoZ¤Ï›l“#ù4«ø†±æ`%+Õ3U[ÐüU5^7@£¼^ká–‰PšyßÚ¶}3r€ñ”ò¶ÖRx2åý:«µ?mJÑ´*¿Eçi«ow(‹/" ˜°µ²)¤ŒQ¸Úæ‘ŘœF-ìÏîM®rµÍ–s} V•-^‰­©`«rYØ*YY/¤ZUé­R®K9>€XpdøR¶ÕÒ©x[µe™ÃÎ+8Øf(Û™ƒdE…øÜ0@[ø ôÓï;@U1#Öãû¿´)ñjYú+ð4&‘ÅT^·1@%F’ònlT©eû„Úv:+eÛÊûÔËýp èbeÉ87U?7R|×[ß¹%æol27Ð'´’®Å©·JÖÖªg˜'P‹ïÆãÜUpS¸*âL8[n%0©fž’gz+k̪â‘em»+çòU€/|yÒà1ÊaÀœôk÷x]ª¥,Ô*VÓ ea|Œr-,A†€Ìêƒc¶~ØX¡,q&ùØò)[ªrw®#f¶õ"Æ#•ÃV1C¼L‚V[dnecdEnºF)ï&‘Ó§$&ˆ‡RME,¶ÇúH⢙aí&k2­}wMÀ;» QB)”·b¤„¦¹^ÈoÿóŸø‘ „“…­ºð$ Ö§ÀºïCz©îJ»ýV©°›Ä;ÈÛ²ü‰á3â }‘ ž's,ðÏbC¦‘Å[Ûò•™()´LBЭ¶xÝ+D*üôó¿t=Ï¿}ED!—ELv­ÆšõŽÝX=T)ÍÔ <ŸZÚÂRd )d'}x`‚`‘CVï„YÌëÀD H¶vM‚ôü˜ÛêÞ<ž‡¯]d&•KywûW·)¥Ô @Ц·aæRH툯ð,¨Â{Õª…». B@”²²ÂÓÃ"OL(âd«Ò”†ž-àbó™R¹»öÖ|d)mëòc¼p‡Úùc47€ÒÍà9ÜüYàMïÒlƒ&²WKV mMŸŸÎU‰¦‘ù# [ ²UÕS…Ü¿`Ð=tÒR”‚ƒ¾çwÔR˜¦rcJ™#0$³µÂ€ÁzVæÙ[W_ 1e>ðšÂjÉ« ¡äÖöLvÖoÄ xN#Ei•²JÙÆ¤Á4Ï»:NwR‰õ>ŸóÚ§W›!+ La½LÊßA/ÖÅ–ƒ À¦éš'x-òoE&„rch*\{æz:ðIIoÕ±B€¹¨µõ0Áiv#e«.qŒm>‘逸®Çùr0@ßÌ)û±äf³*¬µPÕÀemKÉa©ÄÌóô†“ÆA«x©Þs@IüºÓ¸Æ4陥·bj§ˆOl 4I_þ¶Zd‚o$©L<>dæY­¼£ÕH‹ºX ¾“*7|2<Û–rð•Ø¾q¿¡\ß{uÑÄHn‡”…­‰¥2“Àî­kDbœÚ³–vp)+’ ·ñ·m`€ †­lÛÚá#9ôšÂd.FJacÛñVXT‰SvÁª­JGYëBG¸ç5&±Z 2±­‹S×± «­#Aa‹Ï æcåŽÏ?+<·Ye¢ c`J%4x+ Ðý.AàsX!Fp¨°#ÈÚ"]rVV[«H©‹Pk»©#d­1ªDä[EŒ§ß05ÂôE7+ <Ÿ€ñ¶ªe˜â:Êz4]TuºÞO¯œFÊ*´æX}}ùJWHÆ_ôûô™æÆò!¬áÆø±Œ [ ¼ZakÍÖc63pn¼.’ õT~¿©hˆýŸ¨ö^uvþxæ¹1Ú6@°Z¶ÄVA©E‡šOùf ªµ’ÙªlE&˜f›O#ÉŽ [«ÂÓX&>ÿ3 rö¡Vp&½³žnß[¦ºfW{.m™‚¦*©ÂYoLßzÊ‹üa‚.7+gÙ¶ÙšŠÒ*«×[Ep†þ¦Êrp. rV«IðÞ?Ê‚cï¨*”F ±áéñ&Q%|¬xƒá7žBJ…f è\HJßšsX9±¥x X¹ØF¦×ˆ!(ÅYy¼nPN_ª¯‰9T¨„‰øÖ}Þ¿¬œZ­Påê”àM“Ã[ˆGnb·-øôËMïŸ É*´"ß›Ç8š d"êžRÔ. +¼¶Õú3€òn£c Œk!îtJ: A@ ÖâÜѽm[2`°¾YYu„|”OÐHwŠÖ¬déðš£îÖ²› È$Yçêh¥Œ$jM€4C&ñ°0|ƒ¥¡ç [à eä¶›¶Â¦®ÄÊ\ <‡×Üëa Ù3Ä=Zþ4ªŒj+‘›‘<РʑĶQ-¦F:ö ™”¾LêKf"2?3ÝXª1ÊZSþª?ßo9 }-#CÞ²ñéó÷¥œ¥î@ÈVyg¬{Œ³ø¸a:8°¥tFÛÛªWÌ®ÅO\pKÏ“UwØœÖ^ìD 9P" ”_áç'%^–›D¦„ØHV²Ì­¢) dN°U¡.Äp<±Ëi`kH‰¬0‘méc€7Ê1 ÇOiZd>9oN@ •{p~«€k3=5có!¶:H]•çÏD(AöA†1¶u·ªµ"­¬tqe‘|ˆEÏAŒ_V )Õå³][äú¦´5R-4 ì€V¡ÐŠgK)òl Ù&¡ÙÁ7ϯ€F!7…Ph†ÎË£Ê ÔÑHšBʶףyl‡yö’÷¼jô­>›Ò =¾Ì#›„?Fk,;Ÿ4øMµP &Á×òóãiàJ¤”ˆs/—¬d…M†«ªá_;fØ Âd°ª^6L2¤ût{²"™lµV¡£už—;³Ñ¯ðVŸ¥v¿ò ²‚WÐÑ$à™þª×J§7dÏWw[PÛT@O-[¿NXÓÐW…m)‹¥ðÜD2|/Y>f£ –U&Èj[»@)ÛpÓ8”ìN¡|MÏà4¹¡¬ö*p½a©ÜK¹ zÈ6+=ÀZ o­1ìUP¸ßÅg(…§Ä‚>?ãgOæ˜  V(á`²”Hb+Òð>“ i:©”HÃk°*ñ³_mÑ„ ¿Äy®JŠj~Òt"$1’[ÎLœ ¬µ­3Õ0A¬Ð*”Àªâ‘™ž˜ ß«œ¡R•ÖŽQe‘Oþ¶Lj”8\ŠI…]5##×77[)] x¤šÄ³~çϳ^ÙNpˆhšsæïTÄëbŒM‚§7§Ë×vù²pnÅZôé Ûf@*±r·ÛçÎ)1¬nòó@[™[ 1ÀÖJ ˆªòŒÜY"Wòj¶éaaþ ¦³×#êåò;‹P‰!E“”bbæß ¶½€à‰Ï?¦m>˜UÕ´•³!¥zLjáf˜Þ„dz1)e Ø2Tuó>VžRÖ¶˜!ýº»1©†´ÂúfÈ o’w°HëÀ«ÑÎV9 ˜”M<)ø\ú÷¶'êÞl°8½÷u'RÍA²4jrYÛ.AÖÑ™ø~Þñ|xvQñ̹±Uާá`‹D7!½ n6€C)Ócµåi*+.ȘÊù2Ñ`­g‚{^¼0§ÚžxsZñ´Ë~ÊZL–ÏY•íb¤¦ÄUòÃÁ¶T§àFfe›3Êݳ )µ¾²¢­&à\÷ž gÇ!p-dµ ç`+º<²sM I/K<¼Ù6öëã­Ê f$ú›Éli0ž—vy:x…ÖÛ$"•óO/«DÙ^'LïgÊÊ †ƒŠo0)Câ‘Mΰ¥˜ bJ+FS[iüþP9FU%ð-=““…‘ãl¥Z)ù7¡± ­§òë©D#UJÂÖÑ‘1+YjLYó4¢L,Uhİ[ê ÿ6¥'hb_/kþ³Z—<5 lž”› xcå#W˜5MÎÜ(1Ý’[%ò¾9xÊÞ¹C£œÞÚ¹”Ì?Ïü÷dÃ5•%³êÈ`kM–† `m¼¶|„BA£PûŠa Y]²B§Tbë\N—ùù_’“ 긵Qì"œ“.©J))ëß÷°bâË– Fä@?C-¼(Ú $+…6œ”­ù"ÉTqë1À5ê“V¯<+׎ƒU(AöiÌGGÁ¤£y7€4>´ªdmùÔP…yI¸ZÙÎBÀ¤,Űã49+ŒgÐHÇô &”5u É6|òfƒS aP…ì›Mß&DÖÝyŽL/²µ íCzVm­0¥µp]4.³¾°±á­dZxXV…xæ­·ÏYh"ùKY]šµ7Xd•Oúf€¬»ÐÅÊÇäñù·b¦4"ˆ kÔ9¤D|cœ~·c>œñBùzl­&®©-°J8Xa“èXã%YmU”‚€¥ÀS L|S¥·üa%‰=/NG¤,œQ¹iñ&¶µ þº#™«ŠA2!Xë@…é“)ÄœcÜÀ$&DtOФ­o£ÄdHåYѶEÎF5Éù(”r½”ȵ®é¾£È˜+QKYUž¶‘Ûb`ë ÂiʆYå¦5 «7k+ëYÈÖÅé+GÆDÂÉ2‰do ³bˆ×ÁéΩÃd‚Œ›[BÚÒsPb+à½'e ˜[†¶=ÜjËÐ6†CžÈœç£µÖÒÔO/e6¶ « à ôš6Ãêªò\6Ÿf怷"E$æŒûý/Û6žÌ9£¯m-€†¤¬Ešºh”g[X6ù•»gUOÆ\Š2OkUãU)iHÊ΂¬Ä*[•79·ZTnÅ àGm³ÉVØHðΕCíz¬;KŸAµBC6°­ÀsðàªB6I¶0fê+b€*_æÕ…?’¦¬!µ`®)`¥ÈˆsCR"MïJþ²€Uh0@C“ÆHÀÓæ0«ªYëd)aÎVšÀ4H¸µîJ»kÙ`.<Ó4‰ÚƯT?Ý( JVu!Óe|)úx+½^•˜!½m)²¶Çå¤ñ`3w½¶Æ€U¹„}@eνç¿¿‘'nø0^4aðÀ²gúïŸ<[e¬:ªrÄ‘‰'jЧ´v€à LÕ眎j•ëù5¥•Q(j`íåædªVtAzl>bÓóç[›ø5ìèÏÍ)­ šÌ–F¹¿$ÆÃ Võ’2F¤ãÀ~–WBÃÄ-0!­\I¤ï‹RÖªˆ;2ÿ˜F²N#¾y”»jÊ>+±l«Ù`‘ad+>óp𲔑€#[õíi–²$câ ñÝ€³uÞóšÜä ¬w¢ß¿gëÛVVyR ¸Å¤ÔÓmôûV2+Á©¹…UØâaUH+fKõ2gíºXvX Ü%ÀÄ<Å4|]z8cv˜8í¼Rªº«3÷/ž,ÖÂ6Y§PÛÖ*Å<ÒcmŒB³™¤áÓ$ :ŸI¨Ýpþ²&qX»å² è 2sæÖmà›ÙÊAJÐHó¤d…¤çl}I%”» 2[¯ sF¹Ñ£©/bíèmµËˆ™ ž îÇýû{mæþ¾Gª?ì™ –³òÐG°pW½xls¦áÙÖª¶s‚Ûíy†Žo{éÏO‚[ñùXUÎ`Œé¿˜g…Q%0'CŒµk—¬HTˆ!èàü+W+eK¹¦Jˆ»:€’€l% 1ÕÂE%ÄmkTG©HU¦‚1ÂÖsç㌥èeil̓·%°Ú*akÛ1i0J¤àÕ6ØipûÚ6•íæñGq.¶0mßµy¤j×+å¶RgÃŒ‘¥±U˜e¿†aü¦ þ iõV59cí^"qcQòZªìñ¶4Ý—*Vd™ã9ÀΉ¡±ÖZ-A†˜ü1F¢ÉßvÐ(÷äd{¢R ˜(·5LV ­‘Ý8 ¥ÐVU37˜T ²"ÃóQEŸ³ª¶4ºÀš&Ð=ÌMyóì\ùƒ’ô•ðÁB¡íÛ±Û /eÛ¹hŒ—Å·2y ›sžmÓÐÛ*¬vU /%`-(ݧ£^³ÝuqNãf(m¥Ì‰$Æà$7¼R“™) ¤· l…+Éšž!’¸Il›\¯ìïû­DÉŠ &C@ag—àP l$8U¬l+d÷ŒWh˜ W$“2¼«h`«’|ܧ³“a¬5’r!¥Ð6}ãu®9”u4¼`ÈGÕ“­Ö9÷ ñ¬¶Lên»Ð"ü£;¥¨¯ŽZÌ­xA`|/anÄd0 ½9a °óJaŽ× ˜þeª"+ø¨õ'«.¹¬v®Ñ õBrhNUŒcȬ+’ 7ÀZ@²ò¢Æ[U‰ cÞeJ±‚e‘¢^¶É04­9òHã @/â&)k‹„87¥°E²*Ò¤'ÓËšI#I•µUÇ[±ï½be[ +©SŠr[˜†gú5b_;zŒ°+¾ñô¬Ò$k›ÒÀ²U‘ ©c}¿`]#F)l›Óµ8TÙNGÃß³‚¯ÙYÖ(M)dÏŽI|Qaæ=â0b)@Š,fY Ÿ‰myn­F4˜T-0r:ú¾‚SF+³ÚV¯@oX¿”y9^ÖV¸µ¢DšùtÝÁ–$H­¤áE½,§†Ã»sØÎçþGXùM-„¹Éd’{DfU7Ì™±Ÿ=˜ ¥’c³Jÿ[bímÂ,èÅ[m7¥Ü¦ä™^‰ƒ¬ñ ÎuQŠ3àú؇^¶-^  Än9ߎ3šÓ‘ÞZ8Ô‚Ñ(;¶‰?t­Åˆ°j$ÆC–lÌD)ðB r¼F†ÆôdŽÈ”ŽÙöòÈHb…‰ñ@½™Ð`RT)1’g&]ùp¤{ ³d€Ü¶¬´ ì­)Ý‹†^‹‰ Žîû—¡wÃa]íƒÔ<å¢m›²uÔÐÍRò0q¶5fçÀ³ß÷×(+|GYc¿J²Uå07í°âZ~zÃ-ÜŸMzü˜îNÜe¹m:&O¹=D@VÕ;×›'Öe[᣼óÏS´dþéÓô)÷9·O&|ŠLÚ£½Yx ,hd{–¸kÜâ畈5¶A5¶F5CšÝ× „Ó÷ÝK@Œfaø``V޹Eë•1ºÚ p„õËc^1gñn…4Ôt¤Ç™‡¦ÐML€!–íÉ¡q)g+ÓóGÂÄ01,¦ÏSFô&Æ vúmÕÄx Û”|\G¶6C˜†¿¾Ã@V²ªß”‚‰#V™;Ò`û…ã¾Æ~¾È´h”J}”Gí¢j Û@Ë·ùpzÙÄÛ‡(æ†$ÛñüñH›Ð÷…÷Åû) [UAËíC<ñáŽLÓeŽr«®´.·PÕÈ-òÞl[>l=€^SÆÜD¥dÍ…qËÐ;†oå$킆CÏÞßZz(<ÛÞpħ‡œ²G€…J™oÐÀ™w#M<ˆÉvŒ#OǪ»fiC &ekËzË™ìšyÊJBc]² qû(Á¾‘ý†qÜu¶n•ú8 ªZ‹Ãí `Ú¼R›è¡œ,+LëÉùìpKÌU¶.ÛbŽÄ{Æœ³Ò „•Âl‹ŽòŽ€#¥U…ö"e³^ßQÉÐ^,<ÆG€„A;sÎJ; R³Rm…d[Ñhi±¾«ÓlŸzé+™`ä¬`@´9CÙD»ÔƒÔ¨$¸á3W5Úí|ß4 ª?&Øv$kbH%Œ€žÆñÂVÈñQE6 6ÎQo¶¾Ø4ô˜=užÄ½¹ë´d|sÛŸ•AxC‰û¤8·R@µ5"µ×Ò‘mÈ3RKÕ“¦’’^t‘˘Èe@K&|ÂòÑÝ/ U$È_µYËuÉÄîK&ñõ8&=šgDÎrßC-gð5Wíõf%ÏvL Fâ¤c†¬æ #V*#kt„ñ9È}ŸíÓW“òÇÎxã”úÄé[L;²o sa A>þˆqDîv¹ÉLTy¶’/É*MíáæÂ"¥lVâFÄï}´ÀH>5v<¿¶Œ¬³2œhcðá7ktTZÖÅ—¡ì5í”ÆÏ½‡pdž£WøHwF¦©×ËöÈdl÷£ÕèFµw—V²dÀ Gײ?çônípÒ„GYµ}VÕdk ªÜ\ ®Þ§¿ŽtÁµ7"™µñ¬4º…R ´jËÕÚáPÅ8šÈÁJ@‹á2±‰Ä9Àí£ÀàÜ‘ºx6‚m{:" òÔ­‰n TÝtÇx L t‰1¬<¸£ÛרDÎxÑ8%OÚ&¬šË‡a #;Þ!g žL†›øW’ ’^°íYt™k%2\‰2“îû¦Ô i:Ï ²ƒ)xxÏÌ˺0rKê"cN‰lJír€’Óõ:êRjµtäÖVy¶ƒdk·Ÿ¬4B;Ïz3'8W½—Å Lc X/Íõ8 ÝöþZL—_s»e;2ÏÖ0—@8Ê E£ÙÂzÛð¬rÿ¿´kº¬“C6Ýç(|490|£MÆ0›t,›ÒòÓô‰8²…uÉdå–aè^nXæÇ<½øÓÎ~(´ÚŸsë¥!Ve¨w†­l´éJµð¯*7 ÀWªš£«•Êx³Ò(ñ—;‚@1 ü„¤o®Ëöߪi§wœ •€w·ªZ¤úê;b‰8&CØž°»À«†µ|ú΂Xèò†ôi¡*+…S²cU¶¢»JÉú²=™§y`z¯dœÞ†»ï[Åt_›g™®ÊÖ’˜Þ1†ù€Y³­½j;èrìšÜ2}EáÉ`ÁpYÉPû7ÍDéqä†HCÉ0dþm”ï ^e>5"Ɉ=K6”  È„Ûô “Ém’‰ïC>zñ-†I`”v/†Ì9ºZÓz4«ä‰á® £12Ýdä™ô;s¼*>Yd«ä•úqƒ1â¸\½l-Óõ:’"ÍxÌYñÙ1úþ­ƒ?Úã{ï/˜´ M†½?¾{e(cð-Cï(zÎÉ‘¾$d>&GaÜYâûßÞSÂé‰)m¶›ް7¹MŸ¿³a-“€Þ‘‰ýa-12}ùèÖ”x³rƒã›žRÃnôËÐk¢©Y(QÏ”#² ð ò• |{°†Eª~´ô‚#›HÜÜÝy«gÛ,Ùª”=®ã¦ÀZ”Äg•ûŽ·Ä <ÚÏÈïSZú#Ð8Ϭöòn‘mY/óÅŽÞJU(Ékœ¬Ä6eŸã¶¥Tjz¿jºQ|X£. FnôŽÛ!€Qã‡*9rˆ4âmìúÆ©º;Y_x- 4Z&®·Wê¾Gí¢ïOzx¹‡2·[¸`"FK¯Dv Î]ðÕ‹l·dœßyY·$™. ýÛãH :ÿÛw~oc`À, }¼à0ìØêrU]"çÛq’–1aG½µ8¶U$M²9lá‘1”&Âs[xZŒ#úòÜ g+±vWp_ó0Ô® ààywÌV/ €¦³êRĬL©ŠT‚»} œæûaõiÂJ9Àuu”•,ƒÏªV²C2 |wéŽ[ILíôÙÆ#cjw°LÐŽ1Ž¢’ª‹›8Ø&Ž"Ü;ðÙ*±’•D¶Jl+ÄpSPv5¼¡Â ”p+õð<{g¼y·ølÒ·w+ýÝ4ziLÏœL`FÆT}ùpÙJu¹‚¿1?7¿_nÃp-áOÞþ¶Š‘”i`Cy €_µcír/V‹ìH°³³ vh:œ Û[ù|{)ÍmÖ;æ,û¼øyÓU‹ ΜìýyÁÛ¦¹ª“µ›|ŸöwjÖVu„ÅLÂmÞtÀ,7ò»ôm1±Æ}»LJ,_ãsïöë_ÿú—þîÖ±0iFmÍp,0úÛ¬'ÐeÒ¾^ {\k‘µ\í2¥_…²u\©vCÛ¯-M2|˜FUxb¹=Ó¬TU‹›ÊÓ4e]­½.&ªøJrÕKœŒºZÇüe³8$pT^êøZ¼¾®ÆÕ«½=cXVõû Äl•˜ßQ'µª¬EŒ'}/{]5â)µ´‹™¢ª„—ùàÃŽi:ÂþŹ{Ñçà¦Úe‚œkq,´`[)ë0|½xÓ_&bT»B[U…E³¨ŠS»Á0†I»Q&Þtæ|úÔ”|‚u­Ùí)+U•U1 uôŽÜ´Xaˤ”U…R˜ŒÓž2s¤÷úô½0q ê÷š<çÚÓðaȉi¸V°˜ H†Ô•ÉÙàþ᪠£”F¶’WÕeΓ>™ 3wôLõö8º0xU>€–;ó, Â9×B¦cæ|ˆ1ŽÄ|àzá|€f¤Ú8z285˜oœªc¥21 šë˜C³FÆ;Êóåëí °Ñ–§OV£® ï?oÇkluõ?¯ÇóäFÜ¿ßjá¾#ÈÄA˜~_µs;*™U‹®ëqx¶rûäFcJâzã=;e ã‘”w¯ƒÑ"ÏZr&,#ÃÛÇÔ¬d]Mcáø…ç?½I2í»M t C¶# ×Y‰ILûW‚Ûª^ím˜–˜¹Ñ6Aj$ëó…1z‹ð ‘Z™Ý> íù,7"¯‡‡#æ)sC2Éò4ý O‚{C‚ŽÉØväCçÈdâû¼ðé•ôvlzã&Yجª‘²hIÙSðIcôû-Z»*MCmhŠ`‚GÊ|l(ûÁ‘‰e%‘̱äÀYâûç¾^$ŸlpÔÒs¥T=Ïç{·8‰RMßJÖ()àkðI MéSÂÍZˆ71+y»%˧ÏHµ=髼@Ó§lôFleÓeÕ¢[+Ž`Oª‘?™£Ÿ›œ ¡ŽbÓû²Y8ó²j-Ý«¬mùk_Õ,UÇ÷.È;äóCT‹[ãDãôšØ÷'ÁöìHÆp½Žóî%»~‚J=í#÷2˜®öëÏ?ÿ\¿yMRî)a=¹ 3Òié’2kšæMŒdNŸOû!3w¤ÔKcã™ÐWÒÕ’d2> ø4ÙˆÌ+!}Þã~šë‰U…–&ÂF8f•³œg .ú)á™È”ÖÎÖ¯]Øÿ]¤7å`³€f-GÛªf™¸ê0¶dôœ5b|904“µ¹##c”ŠøM¡Ï3lJÎûôéqAÖ&Žnª1½’‰ÚWœ™²Ḻ¡zSºB·N™¦»ão"zmŒ®4Ëf÷º›˜s;À”°,Åy»°>™@¯Œ•MâeXu_+!1*½VJâmqlPSný³“ª€jW°` ÈUßöLZ¯¹z½Ø»¤v¹M€æ–3TjDJ¤ðU¤ÉÙÑŸ»0†æÖÏïP¸GD#²4µcúБˆlöÁ#µZPÊÈÓut‘áÃxU›ÐÃ÷+s¾3dxš&ÂX¬$X Õ"1 õò‰—È4zn²µË¬rN_‹R#qž™è X䆩Qv©ºTñü¹Uµ@³2ì.9”5ð!hg@ú2Fúµ8Ò8š^Õ#´ÔµëÄÔ#t_Y ý"ÕØgÊ0o„F%¤|埗l4)›B†‘ª%†}ù•WržÏ\ÆP*!kGÂ9¤/sö\-×(‹w/!¾)< jŸÛñùã˜^l Õ]®ê¡ØöÚªÜdÁ¿74‘2ŽTm±Ä2CÕ>>×éjU)åø)1‚¦ªöŽÆµª!a¶rwA¦×h‚¾l4S­=½FUJ ¸“?£÷nÈzeä¦t½UþBU¨rPmIúZk±$qÄxæõTµ”Ý…æzœÿ%‚`¢$*57¼ö›•>¥ÒÛ¢ÓSÐ/jÙ1@hQµ0·7GQKXÕ±öîëØ\àý"Qö\mÞÁº2¡hÈÂ1¦ÑÍòÏ]ûU‘‰3IS¯. Ü¬|"õjÙ?* ²M܆ù—i%2wÌJ®±hrSBªöW ß%þ/üê𪠅. ëu€Tò€ë+÷¤4° 3È­W )rîjŽç¯Ñ´-´?˜Ù­ iãeAÐ ñïfa¼x5«b{mÌÐt %¹EçCÖVeGá’V"nt³”€¢?ÈÙšÅߟ"þ.îÈÐHï!õ¶€£jxÀ‘€žƒÚ§^GËZ<»{GƒòLSúfàÉ*YI„µ÷;ZFÒè—>ÿ%{+u¬ ÃÁˆ"’@&ýõ8)FN†yõ "ß»Àd¦°µ’5ÒtïãåÇ0§tßœ7/:ÓÂÓ¶XµRzVÀ°]KŸ‘/¹*,ìƒ.‘\¼¥°l‡rËÌ\ ‡nMË‚,g‚˜Z䪀 ñ2ÚGk[OÖÞEsˆU[¸qå–§o¢j«òáÙQcËÈðÖv„s˜³v}]½^£Û™X´°é”øæòÁ82dšvk4²‰ñº|@ý:ÖU»RÕÌ{nQʤ‰ºDæ±°6™£ì(Ûıëh¯¤ËDØJxL¿4áhŠìÈÁªÜ< hôJmÒ .K/à‘]­jYWadö\‹vÕº²rÜ­dk×2qV"’?Òžý²¥ÇU?Ì宯„¬T)½–$#hz9ñ2} í kl‘ùÐÛ,äëC¬ºRse2ämýýD}c=ˆmû˜h`2-¢Ñükœ³±° Ù»=A]r+u¬%7ŒˆÈf5A 8”{Xã*•«ÖµgUqnòý#µ/$¥ªìU z[&âvœ–4˜|º¯jªW~ô˜;áó°C×%R¦ç`2zí¤+½Üið]M¬‘£êÈ6}›k#Ï6WLðÑK£…ƒìHv:¿ýÀ ß“º€6™3¥R&ªºÐ&2AÓáÚ1Mϼß™³µoz>wµ3§q¬JŽJpDÖˆ©1Yƒ·MbüJ/Î$-é#ôNÔ¨ÔD-ÛÐÅûÔúýy>˜û%ôbZ¶ð6a²Â+áuµÏKâ[ÏãÚp‚5TEÎr s@fÒt™Þo ÛÂ}¾ð½Áù¶kŸ'Þ1™K‰º†Â”1²*“¦ÃþŸÄÜWBö¿¶¢á¯Åo]ž”˜æ6ÂQÐZ¬Œô}9‰ÛŸ•ª’eLEíù”cä_ýë_×_O[fAa-=JÆQµ»m¤10Mt¥¿ œoU#QoJY ­at†WuæVBúƒ¶c÷ahAö Žl«"ðñÏ6²éïn޵kÙÚdÈ>žô5¶eÌÍ¥ÈèãezY {@Jí9ËH-Y´0+%Ñu„$sk¤R³ÊdÆa<’¼Rn”¾7adV­ñÂóYÞô6qc:̰Wª¥Þ0>gsTÕ¹É}¶_â³²;önŽ"±¹Ìµ0Ìs+á U»rLÍHUs&è r –r÷’E-x±g4W´ªv H€ÑeáéÛŠ¦Æ 1Þ­£ÌlϼïW®¯%O]@G€â»Â¾œŽÓ³bÂܪ¦g+§Qb…§­‡ÁÿX€CÊ)i\Íà“g;›èFô‰ %©¤‘Ʊ.ÀwÓVŽ‚¦è:‘ô…R¼#½&s_íùO éþtn ¦ ë•É”|=ðöÉa‚LÒÈÛ§¹2ÃÈü1dLð>¹^šÀÖhtƒ”ÄÜ”ðŽ-ó€ *sÆûÛ¿F˜ø½{¶Ú]ŠLŒAŠLôæðjeW IVãõ8&¯yšdeáFç¬9fìG£.CÜ8²§Þ€@½?AÇ7×{tßÀ]Ù¶2!ÁöÄÌï)’ÉýÒ#p zŒ*ŒO£ ™ Þ±OY5ÃÄMD2Ä÷eÐ(U™À˜öP½Í•Ÿà-¿®Üj,·y_¤F0J¬”rëv0FodíJÀi°Ý¢þÔŽ@ €ˆi'Ê^ß^Ð0ŒÙj¤ïY9´wU M28¦›èÒ'¸ÂóÑšKœ­+TmO-Ý%C¿Mhè{©¶ò;È‘¦åg‚¡LŒdE tqöî2ܯ§¬Lω±p8ÂÌå©®‰ÖÕgê“"ŽlUØb.¥½g¡ìý»BSXÕè(tu”cz´9#»æ&:òid8«ÿΪÙFôñ5kÌ ñ}(>Ž;áüt+µ•¿°:2$Ð^(wSL€• ô2’ @ÒŒtì"l}jü) ‹ûK_µY9 1²£HhÏ<1d0@œƒ#=/ûÂ8ÒÈY‹õòÁôÚ­FY©‰dY›Kì¨ä¹j£—æ}Æ^¾«58pkàÈ«úùnÚsH_ÆëÅ÷0~b| ØÆ«b¡¥¹Èªdþ"¢”g|2Xi2J÷È=%ïëm ,Üå3õûÍÄwzC À§×èüñlý#’ZöÎé=~<£½.-˜JÝZ•3RîƒÆ#iJÉ ˆöð•¶µ4ÎbípÕ°£®“Õ%ÓȲpl7`ƒÆt¯ZX%^î x #Eëiïô˜Þ°ÏÈ5‘»];hd‚éAš• ÁމÉ0½mß(S´3Y ðùy€h7žFí9ht̹LSIÞÕö3ȹŲÒB&·ì‚MÔb(¾l ¬Jã7XÐ,%üdÚÝËQ´y#tuM—ÒèÖº²µŒì mK¯$˜X@°uì"­lzqUŸÄ3¯@^Ë3­ˆ¤l€>w¸@9«Éò”‹5¦‘¦$aOáqº~ 4H•/Óä&«6¥ÛôwÂçM0”º€¬¥¡pÎ}ÓŒ¦^’ ¾AHÕæ*™›3‡L2'ÓÑÈdŒIO6bJŒ,0^@¦Áe> äæ*½Ñˆ˜&Ú‰Ì&0¥a¼`XWGà Ð"'rPbè¨Tµ.ÌÚa>?ŠÕX` @*º†Àðî¶´„^ÏI¿]ëzwRÒ•'Ü,yÓ‘adûÈ|´fÁ14ô¢*^/RÔ‹w<€§± à¹^]dðu=¿Mög¼ªÜP½O¿úH`A x]°F&Þ͉ᜃ’cëMI_)Cx‘!%O¸ÍU)Ç<±»ÄðǘHOÔny[uÄ×ÅpCG*á'€M¬ð2Œ€A‚sƒ0ªH‘ /àùÃ>çJZ´ÏÍÈJé¦óL†l’ƽ¼M ÊJáè^toy®)h˜´%0Ÿ@²2I/ã™ ‹®Š¯ `*ÉŽBÉuù¼Ú­=1i6—¸ÅÚ!O Y-Mïs÷UW}i ÒU£L¬Dpöø>©G@Úkd¸‹a<{p ì Üíü9d‹¬ oâ¦7‚ƒ‰sÖž›.žŽ€F2>zaúµÙÊLT‘‰5b-`]‰óWê(˜Â±Ž?JŸ î$?m_CG;Œ0d•n«½ªÓ’`ö„E|žz»ö‡  †€?ÏÓóýeh%š‚R(õ¡´•Rk4¢O­’¬Š!ЕŒC (¹Žð!FúàhT› íUñ€®lsN©$ŠÑÂÖ’4õ6+%[ %Y cð@5SžUΘVjúd²‚Œ¿lœRÖn´*^Õ^Ã-àÚ•r.7´ýÉhúŠª U¡×PY/™sÌöiZ£¢l¹õ·Õ0ÿV5@ªöȵ°rô‰ë=[~¿¥È ]G ,ßQŸ7IÜDxëѬ×ÙÖ.÷ 4Z¶aƒf¥‡Úw†Œž­ ÷À)Û¡¡1µ;Z¬Íaþdv Ð…_5È\nUCE³8ˆ>ed ë"ƶÿ±{¾Hïqû‹Ž š Ãåø¯·C/Ö]Ò»¦cž4°ûÊøÌ“aªº €fÁª‰ù­‡gB&ˆ›•2üîPêJé¨Ú»y¼¬ôú[5†›¦Ï‘ Rf’^&Ø8¼Ñ”Ñ´*€Ñ.‡)•ü»kôĤÇs&ö'rÿä‰Ï?“Ž/€FëUuGGËo:òÊÿc®F|›üúÇ?þáÜ£Ëû÷cýÚˆDý6ªJ=–~‘àö”¬^Ù±§„-ñJ×þóÄJuEʳdQALUGkçãæHUS0øZôÚV®ÔXÀí?q-|8èr$s$ëU­$‹ô@%Ç|ÒÇóòÉ ÓQÜgF£W4Ðòßñ*7 ¶÷ò2l %³51@T’‘‰iŠd ¬l8·”ay7jŸ<ý®×c·ëŽÙnDþ|âkï(;ŠF8²’EËJ²^ÙbÄJÔ÷“èƒ À˘nã…#ÒÏg?cõ"•zIL>ôVm=|sAnaʢͳªF¶Þp2díé™Èxþ™ÃÖ˼L_‹ª{u-‹¾&â3¤'PÂhÄp“‘˜ðª|¤$èUÄĦtÌ– U™ kqìj¹µ Ò1@`Ä 1º¸¸£‰zýý†m¿âU`„*¦CŸ¹|GYFˆze¸*}Fò\#O1Áª‘k¬~õ®€é:™À¢érúÈì6“n稔­ªè"¦ãoŸÄkÄÓO©*ãko -ÈnÖH …%›‚ÏG ¸’Ït¤ÏJÓÃJípLï-CÑ#ôuºMç·G)åŽrSäÌe8Û@Xfë+$Z^Æä¯Úò|jlôYë¾^ú4ûŠ*×bíOƒ)ðÄ4¢ŸM@É2Éä;á|É[ïjOÒësÙ¶Žüñ %¤h+GVZ|å}¦È6É0LFжm…OÏJI—È?X¨Êºä܆»#2Ù;Ïg-Áº²•‘Jô¯?,ì‰o½Ž”[íÅZX&¦ ¨Öë ÷Ç÷ûµÔK)0rV2±)r¥ô²ej‘E]ÓŒÄÿÏx¯ñ7Ti‘­£•(k,#­äš2¬J#jÉ–abG¯Ñƒ#+y®HL¡Ê6ÆŸŽûÒ6B ©±¹3ÔVåLÖzýÛ.Ù7V /›kYƬOÓn[;2s$àÃ8\Ëã)ö˜R¯åíÓÏÔžq홲×ËJiÍÙ¦7ü°å_©Ae;h<›PCX¹û§à…f/mF)ߥ)[ ïz2 ¦ÇrüŸ¡«éUõl´e¶O€­ ¦é ø¬a|÷´†Rß$]@<åkí3TïïMwo1b@B‰3F‹‹”¹Ñ †R¶•/"ž =­„t|ã}œUVJLV¯£¡H†oºÝº»^±Í‰aâWæ92CŒ;–1@]iä^ AŽ42¨+A& +¹¿}­vb² º@`%x;ôž5.Ï(èÙrÐŽéëƒ t„@IDAT4 ßÕ`8Ä _ ¼X㘉W“!¥Ýh Õ>;za±U½¥<¥#9OJ%ïÜ÷°+ç‰ïè#£wdN©e†Èy*…‘E³˜h¹«ÏB4 P2Ž¡vš[?©ÑÛS‰²ÚU§2tA·€=[¹ükÁL@œÆTU%S´Ô­';ê}‡:¾k8önÚñ{–ш/ÆÁºðçòEKÀ¦Â…c³ág‡g3±Þx—Ï-RFŠÚ•Šzu96¥‰²£L/ÛÌÜø”U{Œ½àØ õQiÇkÁ¨ú0U‘݈¦ß¶õ’Õ¥hœXÉQX “@+©æc+þpãà9`šB8ö)À¬(Áª^Xoí/Ž”3TÒ Ÿo$–­a„q@ÏR©Íe&ýuÙ?¥(ÅÏïq~ ;ªš+¶’@ YÑË‚@IÌùmiЬJSo-[ Ïº2l ýxþ­sþŽ€ÐÛ”³âýD0uáa"/´ÔkÖv6QošºZRv$«‹ ßq@CùÔ˜^^˘ºè-ÐÄZ(§WMßÐZö™ö»I)@,:2¬%+lå70Ý‹a¿‘µÐ +Á}…Ú¹ÞmK €›\ƒógàØpäÆ6«Híø²*Rod¿I󴾵녋ª€ÜJ°}24¢Þý´Jp†4¢¦#A$@ÙצU3™L{ž)—ÉÄŽdá@¥^ï£Ì0`™<]Äz ?Âø–AÂ|¼°Å4bÎÈ;”ƒA)ûž$ÆJÑ&r ÑÉd¤L,÷8yòÇä€ñ‘9êÅÛÄ@¶³ÍÓ7ˆ +¹ Éȳ"‰‘âÇz‘Éʳª:ÍL,&ËÂQ„ÇG²= ÷:vƒ­'Tß—$°Ò•Ÿ·²Œ ¤˜J­êØL?/çžß›b*QÖR••#+í€SÕ†ý f¾œIðûYø€˜DÊ"çÄmNo\LÎ1í‰QbÕãÐ÷{Éÿ¶„ŒFÔÕ¸pyæŽæÊM•DL—i’eÕ,Œ)ýøçÙªL‰ $0"ŒéS@º”G ë§ÿÞáõ$øÿ…–íjlÛ¼»¨*‰v` ä»õ;E©ã[…ãAC×¾ª¹}y€¾´”±Gð=ÑÕnº¶Ææa>~/iôþZ˜D}%’½+4”m_HïÜiÐPJæÏŠ× ­Ô8þ4ýæéx 0Äcèi„^%G<óN¹ªsw¸L^£U…dJLUG—’ý„íàI÷™7·Ñùc]HÛÊl;2˜”zdŒüóž*߯“(Š˜0£l¶û(!EŸ‡lÊĪï»p£DfKp·ã“¡J®ç94âM|•¬s“)ë%ÛJ½%·ª@ŸRU|"UeŒ,5î}»‘¯ÎnC“²)µ·v½ª}ºkLéó( ”pÕs9|ƒ(‹J²­(Uëj|]MŸ˜Oó=ÿÄ&¢^$ìR²7qÄÃÍÅ'Ú<žCI3Î0ÜÚæöMc+î"¿—ùïc½»š¹07¥ôJ<ÛχF)¹£ÜuΦ+ëïŸx>BU)q¸[#UÉ,“[2XÀ…çÒ¥%>-×û˜sN7¥t5ïrz¤£ö™;¶@ÎŽ‚ £Lj4ˆÆ'ÂÖhù|é½ÖÁlޝEmÈ^\¦Ü¼nØ*ø€l@%ó¶.«¹½G½H ä¬Ý x³àôd<[&ç6´9@V/M ¶-“‰.$1 ޱϠY¥·ÚU)«’ñ—m¿M€ÃSÊø.% &==ÜPþ±#™cCU“É|¸\#Œ‡õjÉ!=OÌHI€ñÑ»ˆLЃTeÕš>2+SÚ“Á¢vÔE)X!z{œ”óL°Û³Ò¨šr]üádª5Ê¢~?uðS»cw‘àâ]Äb|Ê=£Òv¼í›¾’*‡µ4¥–³Ö½‘ccZÞ2øµ«R&~sšd9ȶÕî°Ò¹Ø}g)taòIûè}!•`J¡äX ;´óÉd¼¹°WÂò·û|.Ù"E-Fô³©êcòo;bLIð¾?lt€qp£Vò©! ÒËÇ‘•™cšüs&1”¾*ÿþ÷¿1Ý#¸å¿öÛtž¨ß3½X—bÅYÐh¼çg*9Y|>[©]T]&‹§D:|RÖŽÏÙPÓ]_´ÀÚésÀgXi{rÀˆlûn¼k·Xr-3tYb/7ÑQ5%=UMIÃÖzÆø“¸®–Ù$LF“Þž-«˜¦ÐÔÛÎËÉÌREvL,›¹ÅÈ·z©*‰Ö“ jD+É®fC½®fMþ­”' Ȫ4”®OžJ¦`ùÎ<_Gíbâ·WÕJ}ÿ™ç†ÌGVÕŽðFTJIàX©»ÇhD½åzó”W…l}ʲ%¯Ùù3«YuQþ]I&úøêŠ‘k!ãÉ's+‘… `‘•ÇÁ¤—98À¦á#Tsú¾{1J0¾[äà8¦êõ8ÊŽËñåºä¶Íy™?¾h8¬72O²@”y]°WsäÙΘªrw(ß)bd†¦.&¢v¿ç}â¦4®Åã=cþx-4J>†øÙn"Yy—šÒzp×!{[^ÏJýèµ³®6÷Õê籟M©êhCí"܈Èw\<™PbhJÝ),Öþ°ÑµÈ]<çºh8¬üjÎwÚïÔÚºPY‘x¡ñ×üá?:˽5¼]5d¹IªHÇ×n¤yJ`2‘‹üË}6xSîéü=»ÿ%˜,âª8²JÝÙ#vì×ñ¶„Æ®,à ›µ£Ržø‚ê9tTµ¤¹¦ûÔ)1™#a@|ì¾§é­Ú\UãÆšu[Ï94欥*=7ù5éAj4EUKJ@£^£c?$ÝEÉGÐz°–¦t‘za³2O“3Œ%°ö6ÇèEÆ;’僷FÎÉð a]Ã5ºƶzi|i rí}»üVB2I\ïûŒºTk„MiºÜ£x1Íú"#×è˜ ^©!ý•§Ç;ÚðD°ƒˆd({ V9gˆd•&¡Šl YìX£cJY5Ï|Äm:|Jo–•Úm`½0 A-6Ì°ÆÆ!-Ä®Ö&ù;"k‡=HÕôi2oPs}1(Ù›KLY#YXÖ( ‘C¤jX‰§#‡É $@©4ìø­ŸGhtŒU­¥¬D#TEÇJ}âHÀ\ O9ÿ’ƬÆ%èÑÜ¥ROš¦®3òZ)•º»A4øHViÚJZˆåü{p]&M™ >½–<[ƒfú@|ú ŠÔ;gV¶²²F-‘ ´¤­€‚¬¡E+!º˜©bšmS<‘€ýžQíK’Ø”F4¥v й1§É?M£Û' †ãë=½R«Æ0lÐÄ1uY²‰²åµœÇú~ÊëU­=ÏHïe¼#7kÌS`¬dC²¡¥«m [„Ì–>LXÖÕ7 0 £…½ŽBÍípQ A¤õÒ˺j<.ß{+µm+ÆP$\¾ŸD_W&pW¨\£±^–-Yuš5ê-,PD_dX—O–ϹOùªDŒïå[ƒ8ó~sÒg%Ã"o…éMò©„l(²?vi\ÊQ‰9œ ÅhQ—LæØÂéi(aüœSv£ U­ÔgŠiœlV9ga%½æY}šÌõâ‘d)åð¯2¥+üˆGâ:îvõ&†ÄÀvŽY¨B—HìX£KýúÛßþV¡Ÿ¤§ã{€šF¶ ‹Ýî½F ˆ5öjŽp2Ù1eKÀ¹ù¯ÌJ¤ÌüX‰P;Íi¸¯¦'ް™âÓiO<%f2‚Ü"ý±H³çº£NBR½[{ž4e€>Ã}1üžé¯ ¹ÕH–žs&ËÚ#e_ÅZä–±À¦Ë™ä µSŠ-é.ŽFðüØ™XWïÐÛjAÆ‹ûÚòö4¦ ·Rþ<+!áþ¡¨ Ò+57«®ßò˜;ó¤áôµÃíIoÿºdz%Î@ß„H2A¶dvµ uYÞqeJ¼vzˆÄcco&^—%•b€µÇ'”L\ÔòÔÏt½Ür~õ&Î9=[ ™‹çC Œj²œ½†7QõzŽ@íïˆ>М»c˜òJæaýÜaׇ ™ŒRà1‚s”þ´ÝˆÔ^ðd»‚.Ù±?î)u yFÔKÓ?š:67ÖŸµî#Dbî.Ç3Mƒðõâa%³4ªâ­Ú—6qxdßCX$n1h‘Žüe€¬ôëŸÿü'iÛ¢a5 °Ÿÿ¾“8Ãk½]>T…úVûOOìÂL0žÛ%bÑ /Dæ-XWÇÚa&íI\F(Ñ”ls–c4øfÈpãäRd5çdO °‚µpˆ¯Eng@È}ðMìMhðLÊü›Ž_4ÔÚJuñAvBIxIyÊW¿¡Å¨}nµ«Ö²RÇ3ïû'“qHGW°ì¨W—ãzWß¾ÿó寤9Wºþy²Gþ}d Åó,Z†Œ&˜ ïa“c·Óˆ†Êµ³Ò%a˜!2èåù¬Ú!¾}WȈiºšk+Óæ)1 ÖÛ< U ëj"fëÁbûô£º%陟ôZZª”c [Í Ó½äzµp˜¹FG•ïµU17bVðÄ4Ä]H‘Z6ºF¼²³Ê íÄ“±J¬]d… Èý›(5Òh”9¨Ö€ûå¼.ý*éŠ'ÆcšX‰[zSÒð´yJú[ ¾»k4(‡¬ðÚíÉ  ÏV H‰\£)††@P~é³g<°ÿ•|žF®ñJ>?ÂH&YÕXÆWÒËM86˜Ð $MˇíßdSzUá˜'à˜!P×Þ!ñôŽÉöy¥Ç{j²Ž|0}F€ãv›¾Íu©ö¡´€c]40r/Б¸.#ú{?-5êª= ²/6}7”„#% $j7«ØJl[>Œ¡ìaád¹éÅÃds£àÉ^@Á[îxšïÕÈÜÂò”–QÎï_,k”Z?i õ2ÍMÒå¨EŽÍîžGXWnl·A÷¤áïŸMOVPªj¹öÇ­¹eÊM$`ò¾ÍnzåÞÇŒO©šÀ± ÉŒHÜ>bæ€ibVZª"EúÌ÷\k'€;šèYèýT`”Œð¢qÇñò-†_/¬—ƒ q4tw¬«òt;ïCëÕÃJ˜Â#Óh”…cs“ÁÜ𔘪ÉäÆák™[úüUñ…5šÛíL#èMI“ó.E 0‡Ò1íuÉÂ\ãêÒ#cdúfx8 çêâa†ŽJfé¥wÎçw½5 ÊwDo AÁS˜…,ðŽôæ¾¼ïAÿ¤ÝShì¿ð!ë5ü°Ã6T"F:  wÞMɇr2¼^2&iÚJvìs£ê¦ÍJŒæös áßQÞ12CdÏŽÄôýGÒoC1ª¦šÛJ€ó,J²/C÷ª¥7Ñ"¸©*ÅÈÚ+Eæ wü!Cr¨nÇÞ1CÇfeEVo2ƒ¶û3YI æÄ᎘c÷íV5z{xC}¯Œãܱ¡€ÿô­ÇdSxbÏbCÕ6d%Z ßû7T hb2GbØ”ºä-¾¹d)õR"ÉZŒæ5Ì–ƒ_o»Ñ%y·r>‹ywàçç·‹ 3§ôtîå(T1"CHo1À¬~„ÝH—¼Þí>o•̱}-ëÍ¿ÅM© äsùü¦MÐÚ™Ï0TÆXn"’£×ÿEEéÏ MÄŽM“³Ê½™5:N`Þ&Ä‚s8Œ”527Ë1 ýånWu- Eˆ|–ÍmtÎa½–é´É•|þBÈAU ™ÐìRŽ"±vØÐ”džT©s4NIï¯?ÿü“Zøã­G!Ò™Qî¤ìh¯ŠÇ”[&Ð+btæaÞÕû’õ2éÚ74ó<“U§oC‚b “ 2£m"s’Um=ÇnÝzògãûŽ­Mœž È0Fnм^¤Ýèùˆ4rÑD˜O¸ÆZðÀLêjº,(k‡«î)ôæs…'Í܆é­˜3è'Ìb•–ch” "N3àxÍÎ}¤–ÆÉÐø@‰ûR¾nJŽdö1B8Öbsn3L)‹”çÅ樂UUX¯Ðk´,UÍRÕqÔž&*Y8}VÙ+Ñ»NVØ6QÆËiäæ dC ê[íHÐ\¸£‰ïÈ6ì &v«¸ vGWHƒŽª~ïwµ®£×‘~V‘1@1·/qþ³%€ €ùl4ÆG,šKY)`+À&¦¿s[IÉOñ®Ù âfÅÓ8öº&e7R}÷„cø{IÌí;Ží™'ž%j2¶ù7î8Þ±}zs²JLâ×ø«6hãX†§52ôwAÇHV¹è…jnɺ)=€a’LKD d·ö=ÔW 4…F»W€@F/;NÖ  ÊŸ ‰€¸3?_`˜›*¥%ñC)ód__-ßÄåF´$’-}&HŸr• rt€CFß#µ‰Ü5“Á”ª5KFz½qÀdH)jé m¢ŠtYÐOÙ;lŸJF·›¹Óc,Ïh‡€\ 黑.žV­'k4Œ“iéÊJ4À0Ùe 0¹ú.e˜IÛ" Rµ^< Ó‘­#R/¦cqÚ­7ÌÐQ»Ð(hÇt)+µpNïH cTמlþ×ò$†áJôzMpnËJUÐŽß&ø0¥ŽM!ëúõ®ˆ­1ÉYé-(ù ïýßúçƒ#hnJY éñÃkG&Hùb›Ð×Hf¨#Ò+ͯ*`Ù\ Ld²ïÆÕžd¢X Ìœ^±.% †mšÓ|Ç)EÊÍ’a¡D£Ý¶Ž€®7Ã.Ÿ˜¬+ÔÞˆ1ÜZI5ÃFäŒlP 8ÊJÚ)…‹d¥ÏHëúü_Ê«w¡î‘`A'`‚ëyRýñ2÷>¶L0dœ'Žq¤éÓ’û+¸‰x]IÙè2Á‹d])åx#ð=™;÷󜒸Fâ¶e»q]Ä‘˜ W• È` ð’üÛ'~z¼.y a¤Œ§Ç¼-M9Û|oÝȈ‘†Âî«Ë1ž[ =ñmÒˆm¥¥.ž}](ÛPûz·mzíùÈ ¢ý^•›À/æŒ×R·¦¿Û!ÉÚ Ù\š0Ð,Ç í£Ïp‚l;NÉm‚Œpfx]™´S® |n†.]*sYÄd^—M6Â¥¾Ï•Ò7W‰ìzœo5L@¦ßhÇÈ2ñz¹!Eß™-ßQ/¦)Ë-àȧà/àiÂLÖžÒéF˜v®KÉV-FC÷žŽ4Mé7Z;p@Rò!a]J¾K¯?®ZîœóÑÌ ”àr¿¬öÉVUpCVÂeãº7C‰E%íU ¯US( D`½kqS]õvö\F÷>@Óù¨’ùÕð©åù˜G÷•’_¯jµ÷\ÆmÕ®\K>é‰u¥—Å6'Ð.Ó´ªj«òI¦Zt¤,YèÕåšÚ‘Æi¡Ç§iY(á»`GŸ8RdÈ-+ÇVê²ôª”°pds1œ'0K£ÌDIŽ…–HG-”2Ã<3OFÓˆ"{ÿLðíOY{úª×òó“CÊ™;ê%3¡dæH-¤öZ`¤0š&=*ŸLðl+%†é-ïåiq&]Y¦áC‹9= ·Ñ2†²5U''s¤R ƒj!kÉñŽ¢éHXÞuÒ_ÉG¦”XÉ”•5Ú!@©ö”ÄHáÈAî ‘˜Ž­Šì3j¢ÇF'ƒ>,ì©ó”…Ë´OdG9Ï—„» QÄ´êÈ–Ï37÷¿d+|Éíc¼¼–VÊ9C9R×&þµÆšKô=Ôb¦+‘'óøU‰‘y¶d ô˜pnÚEãš›§ì7€C¹RÇ<7ñ}"%úb_Α©Š²~4̪ÔÂŽJºvð¡ÿúûßÿn64S.˜Hm-á¨iG. x%óÉñ©”‰y½ ®‹&R—YEÙVmI©EðWr¤Ôˆ¡I–?j‘žóH÷ª P%KC00Ò ân÷ù[f¶@XK‹5H´ ÆÓ;âsnÊñú> ¥ ºW™¬¹òÖË­.O¼Ÿ =%‚…›¥šá^¦–&*ÙSVe’3AU½M'xY‰¸ÝoNVïiû~#û€ð”–}M÷nU ed[9ÆØG°Í™á­ü2޽ Þ± ·R‚Fì…#µ¶õLI¿…ã){Õ–§\/æ\ïûwˆÌ›¸ßÔªÝBµ¿R°å0q†ÍBú)ƒML°Y|¼ó¢+#Ïo‡;ßžYu#9Ùuõ2°àŸ2Àªßzí€$Ì Ê¹.†y–'ËþÖ?¿Åü°à9ËF¤!àŸ¬vÎ@£i^gJÕHædVHô·¢éÝ'S ;n^GA ”øç,pN61ýp­d Ÿ2†’;êÊðìtÿ¬ê^Jµ{.ÿã%²”LtPÂïï1s«²rSUàyÆpÌ»BSªf’@nnSÎ6ßÿQýZð4=~hùªS:-vt÷›æ/ µ¤A’¥É9Fusý/©{7Y(#…^Ù‘§œÀ0ô½GØQʵp sÔU&†E]iúv‘Ä0«> iJíø •ú賕•ò¤ s˜Û%6±‡p¼FaЍ$ ¯$[/÷ûšõÊxí낻鉎‰¹eˆéSÐ#»{³ÚPš‚ïØ¸˜Äp¥²q”ÚSʽ0 ”z®°M00ŸS¾ã0|„ãFW’9׆`A/×.ÇlÛ)ª)3©w%³—À+ùV`›.kp?&µ4…¸#&g5Á±¸d߯dr#¸õ qDîoÿð¹OÉM®½—W¢Ïn¦xÇ𜠫fÕFÒømÓbJB‰é(°Mdþ½U¼c»˜¶e×Žïˆ ç¯š@KbǬdÑ&Zð™‡ñ;Âïñ8Þ@rðqüúË_þ’»¡ªÖßA[sÇýþFâ1YNh죅µ—½B³‰½Wæ@G%Ñh&È9PÆ÷ƒÝŠßb-3¥ª™‡­°ZWz$`a%¸ÝÚÖOq&x²Ä5–o1b·«N ´@®¥Y1ý© ÷'ŸZ¸ÙPt$Ð%˜ˆfUjî¨DƒïÖd0þÚœO¤ÆŽþ²sÈ ¨ŠïFg¥vèÖ•f¨$¶ª.úzSÂ?‚ ­‘’ 2ïj°È3Üíà;ùó%©Ñ à稷ÆZÚ¸ÜÖEC°#P×ÏlGjáÆÊ—PVí­ô:’G‚BWþeG?˜@×ï“…·§FViàd¹ßt&ÂJô@seÁMJÄLÈ› UØ14˜|¦Áppʹë­„QÍ­¡ù7O&“mœR"•`€ hPž&Fâ–a2LÑ’'F£HY5Röso4®7%n9ÐtY`&ÃPvY\Õ'ÏY¯‰•rs#Á§?«h²• „’}‚d~·Úñ€ßrÀÿ£ë–$;n$ŠÚ·úM-d”L_O®çDÜLïPQÂ"Þˬê&G“lk;}-M!²é@U¦Å,W B¹qD4J›«WMÐC1Åí Æç×%ÅÑ…cDUšbÁ”2d"¬´(ÕË×{)Ÿ/„d›‚°ýáLj"~&FH3A4„)DækÍ(Ä'«=¯2ϘH$A"JÔxKêrÄä¾[ÕˆI9±#ø»Õ˜@Ch+ˆÞ@8NsWJV»qbâJ˜ÙViq÷€ Ñ«‹5KUWUw¢vàÑà«ÆDË(ìÔ•¤FtK‚\5„‡àðd]¯),/n7Õ‘ëíU)›%÷3ZHA:õvöFCG®Š«vŸÜ¦4±•Ðbòm^—ôjŸ3Š1‰×¥JPÌ/ ›ŽÌzR÷VεÀÛaâà/ý—ƒ4+(Í^]1‹ð>P|â;¸Æ3_Ú¬¾S#>…8ÒJ“…³#k:ï¹CJ©MSšïàÝ•¸¡ÛjÕ&JϘ{]˜‘{»L,%ÕÙ[Fz‰g\"<ë¶ÍjtL¹ørÏ«ÂÎàkÈL#ƒ“cÎ <ï·/¿ðùbõ†)+ÔÖíˆñHl†æ$ JáwâÙÓ §àçïxݲ*&Z&­Š C´hï®[úm7‚·0ßÝ¥ð.fD»u4A-ÅNŠP r ®Ô’Ö\~³jiØ/ÿ6LJcÛJu¹çg˜|p|f›‹SÀŠ[‰HLi ù¥ødu™7:©þV¸õZŽÖo 5â3šL-5H$ë¡Û$˜¦4¾`ÇTepjÆ1ä|)Ž=´RRºà­!Ð G†¹ïOߦTmZ ìe&Î÷Žf®¸ã§)MAÊMŠÙÝÞÞv¸ÆzyS²@kLÿð¾§\†/%^æ|–iÔ•ïsWªh%ŸqAómâÈbƒòÅhp-†Bè4 ‡,ÿ.³-&ŽwŒB;xIĤˆ›ÂõëJ¼AÝ-O)íZjA£™¬…¿x]tðMlm„† Úg¥Jh!nhGJY¯…•⿲Å|"G»^㤬=§)ÀÜD©§é84“RÒBPê†)@Ðpú?múÕþõ¿ý@ S—M²È¹ª&jàbFèæ‰¸{ Z©Y ÌnzG@ÐÈ›‹#pŠB_ÉΟ\UÇG£¡5ÄFL¨1ñ?ÿüS*î†Ú`-Ú\DN­Y@ãÄU£ñhtðá5U[ÁõRKÈÄp -à©T¾+žË¬K©K¾CÅzíCÖ\ˆ¿Ü‘!Ó‰àu„´<¾‡§E o1±Å˜g#vø8&ja‚,ñÚá¶…è‚0 T»)4Ó™B Z§ËWåY ÙÞl|„–‡MG³ÿ֖«bÖ¨KÕis)rËóR K²«¦ßÂÈÕ,r%±*¼'û¥œ/€czW!ÈêYé®M ¤ÐŽ“ìÈÿ»I±R°|L4±Ñ®N•T"Ž'K ¶˜‰‘ñáÈZ¶1²`- ›RÜejo+`·±˜ÑÓ7K‰ÕèhS«"Ã,&2½˜šm•Ú\ÚR´m‹ŒÓ'Úb^B¥ÉÒAÓåÁ ZO•Ô{.©*2f·'´•®Ô­”IY¥Ž¢q-˜#¨*Ù¾ñWò ín#×n½ô¥µ ê‚D+o.ZA±ÈÌbãwØð›Žïh·û3]„µBwG£Ô£‰Æ#TjýZÂ¥Žïiª2L ]ˆdûרÙÅÌ|„—v‹Gæ‰Dg+Á‹•˜}]·FH¯J‡m¢õÒL!i-ŽkaçâîÚ@Ÿ ¾ÊtéÝž¥¶òÛ?ü?þ 啲Ȫ¬h"°R¾Mºªæ]5Ð|”,иԊ1 5h"”-AÃ{EÓ$¨¤¥Fd>…­-eµÿöûï¿c·GcÔvš‰¦ÒNüm?¿=ê-Ð¥šµŠFio¡€Ÿ~4ínδ0"mÁ Q]ûiø^qã`6]U‰uSÅgÒ5©"ç bâ¸)·ãlˆÏ+9ZÇI'ÕL-..¨¥w”¾=›¢ŠÓ ܳ+Rbf…§WBNsS€bž¡©–FhÊ=p¸;#ïЌ˪ŠUCˆG‹‚¡.3eäÞ‘ÛYoÏq½Ò™ãkäñ•hj1—Å5FkëEÆ Eh ˆ´—¤Sð›.ˆÀ7túkWÒNÄ V*ÆL°YÀ)‹-ŒàÍétbí‰/@k:\À{ ˆW5qSTJD@\À#÷e*ui¸R8s×a¥m%Îð-ÀÃãÀÅ6áÉörvÛ­ dÈÒ‚\ÈŽC‡,Ã[©=ÔXUüZÜ!¦/ÖRIJ<ƒHijgRñ…Ó¸&&M„Äù8(ÖÛ»g´.ä3ãþÔD(žo´lôZâó5«€'Þ> Õ L$>‘î .®QIü éų Sâé  Ö%PB¦i–ØójaÞkƒ¬zŽq{ÓiÃh= "mÕD锥Dô6Ô B(´Ò=Ã+á+•Ö[ÌKC6X ïNxFÁžûO°C­W …gk·yõ6TÚ¶ …K·)qé“lâ•¢iϳGÐ)º´øæ²‰/Åô†S¶Ijk”ãp"Ññ,zИ¬xíRfC†PÀOÇ—X:8NË4«­BvØC‡ï´'Ü·»JŸ‚;Ä÷_€ÀUÅ6(u„M¤A¶WŠ_L!²ÔþJÉÂ]Щ{ŽÉ~f\5¢¥G“åº×>š¯kÓl™ÃÁdz)dÒZÜòd/ñœ%CV"ˆ,`p^‰ïPCÒtœ®Â2¬_Uê6tÕÂòÆM¼ 0åºàRzi¢Á™ôLýþ¹Hª„_ ¿T»M<ú[ÿ<Änµm‘Y²¼X sC€M„ÐQ A“{׎à‘Uö´L0ˆÄ4·š væ'n÷¼vj0<Í]T‹) {íÑÄÑĉàÛÙöKjOkûBv]ðôÃű¤)4;`—©ä)3ü~Æ¥•œ‡SpÆ:e|Ö1«ê‚w?âJ8µ@Bjí­Ê›¢J*q4éøZ¤É:E[M¹îÔ¤\NƒÄŒš^ãܤRwbC%½DÄz]-|&ÆOǧو•¶'„©ÖhÒÈJÓ߯8Mµõj‡— ©*´e‡‚ü°—ö–àí˜lËç×"Õ’/P*Õ%î˜â]KlŠª.Òë€RÕÎ/õhÒ)Ý«‹Ð­'e ¢ V•êêè4tÛÖÎCŠëÚþí£ ¤qBЬívó¶x‘¤Àþ½e1©d7%Fk+KÆWmDqRz‘áR¸^±sÅÉÇ1ÇDšC “Odx„s¨ô{·½“R«Ò§ƒlLH+5"g.Ù–ÿ1‚NLFƒì ‘&.(6]ﯿØ&vä£ ̺»"CÒm›æ%BS©8¿);*Bš1µ¸)qãÝŽqÍ7ÅD¦…NG" AëðÚõ^ÖçmÓÛí–GÀÔ¥*°€X@Ó |4’~Ó;~̪3AäÒðÄ!%¾w¢Ø‚˜Ñ:EL£Ÿg~hÅ11œGŽ ÐŽ)­—g@üJ‚¦×ØD#yq]S“n?f7œÈö=‚ ­ åÅõ"tÒÆ Ld8.¤ƒðõò=² š.Õ¬*OÄ ðžóx&]Û¶2퇼‹R OYš¯¥mÅ1Í8J஫M”ÒD³œBK\#“Fn%¥oœ®«×_JSUÜ"çß«ëìÆÕˆ`О¸˜5 ­aø!ÀLÊà]ÝÈ4K[µ' ×H9ñ.'f—“Z4íhª4ªNØ^ä÷€g­ûXT#‚jC§ ¥‡>¦mûúRm.N{¶Œôj‡ …¤¢}„CýfÛRäaF°ÄÓ­ÊKxÛú—×b’ø àöKƒ;g˜À„t¿öÙ!°Ã6EŒÃSÄÁ”v)f4„®b™À“vù˜vg'R—fј€SórF0ŽyšÒÑbnaxdâ)ØÄÚ¡‰‰¸ WIªëÂl¥»Â¹=Aua"t΂ç3d%)/fm8‚‰§ù¾c¶êJUé[ 2f½‰ 8Q!^W¶àcÎ:8Ž ¯·vÌdU>$Á¾lÕ ªbH„b¾Ý&åŠ:‹eX§(Æ)mÚ·°@Úæ‚‚Í­—ŽË‡ È2¸TûN'¦“Ÿ>ÍÅ8z­'/–ÎY©`‚½ðJ ÿGWä1¥^rw’rG¶°aòÈ]&¯A „æ‰J^c|¶õãO¹:NßžüL#{×3šíÐIYY¯u ¶ D—^ðÊ|bã†ôYK3³WJGK—)îq7ÈšÞy½ZJâ¾XúJÜûÖ¼.²ãìÓA½¹ÐâK-€Ð/±ï“BÖÕzbƒ×ѤææÛyÌ®.B"õžÅü?SÈä®ÏÁÕk!Ð L—\±f‹òÈ&îHÛ€ X‹ýbJøÇó«‰4):æb2½ÁÑà¼@¹­¤âIˆcÝ\ìå&•þU=9&ÎF7ˆ,\ W• X"VRÕ‹B%i+ X Æ˜ZéRŽ5G¶*ñ¾­¦ƒPŒãDº¤b^IP{—Èo´ ³h¤¯Ô\‚Úé 1©˜ðdùZ⨖*Ù‡ +J*ñ€mò¶²µ@Ä–¤Ã¤b¾w ¿6k1Ï”,£‹NËÅZÞ•Òéb‘kG+ftTiòÚÓoo"&A&mÿÚí#h ½h<~:Kùª%þÕQ Çô©yçÀd¦w|UiËã ¬„,H$å‚ÔÂ##À:ÐÁyH1‚>³5”6½¤¬qÈ‹!RjVÒ›DlÏ1‰HÉ2d]hŒZ-駆 =S¯!o\½ˆ,>ŠK\P—­ŒîbRqê³hùSmÊõB2{§‹_ÃÔe}Â!Ó×¾} 0ktEµ{íž¡õAH-Y‚],Ž*ß\¤”ú<Â¥Jø!zkÁD“ò¼xí)Hs¯SSWeJm+îõ †ä”+Á²@âãHÇïoLl‡ +¦o´M´y‹Ð† êìJ5½ŽÙæÀ†&2} 2»ÂŸ{ƒx¶œ¢öZĆòz•0“¥ã6”¢I¯ÌqÝ?“â8u;ó~ž¶íøw¯ÏÏ…WGc>fjpÁ{iËhŸ¡‰[Cйt…hñþHÑ\`Ï%ežiéh½EZ€yªbL¾¸)¾@à{]M×ïŠx1°Ý…Òv³F)ßµÐÔmt²Dh¢i ˜àG\ŠaA½À´±O|gŠcOO­U­a-Öéz7òÍÕ"%…€¿wlspúø<Ká}‘И€™›ÕiŠbŠ%Äy©)}9o\‚J&ãK‰lOíR¦Ä§Ö˜Ò^ŒKü|pÆW¥ßÙ-)Јß>¹)î¿5šÈã4“!T ´U|%²é¤Ïãx9)¸O}icÂ5*ᤲ3"ÃÙÖPj¢RÕÈü|©–FŸ?¤ÛZ|¦¡6 =°.´£öì!RB.Ew*œ‚‡ª)áD8[ß¿[’RG¦Àˆ«:¹»ÐH‡MY€ÓÐnÇç§—¿ÛÀß”íbVW°‰DÎ~_“fª8ÖšQSíÒI3D¬z&}ßEAjûÄqÂ5:/o¤—À,wk£8¼¹8É ºð8Ý@k4NcAC”ãç=bRJ·›ÑÒqŒkfq:#‹\©–­Ý\â†Óž‚d¥ŒB"­D\¢1§Þ^-vë˜âDj” øª=Ž6!¢’~n\X"cJ[@cœ6£5…òZZ5)~Öž8‚˜F'h )ŸBSR®¥7Ö‰šÕý ‡èíA«6To¦%XŒ¬Ôþpñ–¡90ôt˜ª^;kò@4CÓ„0)‚f7AœV’b :²¤Ñ”ŒˆÀ4Z¼ÀÖÒbp³,#`•F0ø¦·X ´wÀ˜Ý'‚^¥æ }jpÄyKö‹‘UuÙaÅiÞYâ÷-Œ@i¯z•ÎU×Òé€È,œ'’lsκgûëªL?/M°ÿ+öùg|'Ú7¤Ÿ7ã¨Fè€pjÎbV ûµI o½ÆAÐÒ©š!2BL‚ðŽ#€‡t HkðíÀ§ÿCßm¨vÒ¤Zsd8ktë×ß|ï2IÅÑEá0¯åp%³DcúY:4Å]N ½iZ˜ªöf „ €¥]‹4¦ƒ7è%‡Ü½Ä#wSè,©iddÇzÝ­5pÚPpÖ½É)¨àPà ,TEcÑø˜‡ ¤–TÚÖ¨Èh£!4ÂÅö»)8Bí&M¿Úí¬x-Nßi­D3&GÐh)B·j®¸µ”âóR¾Æ7€Û°w®¥óŽ¿¡J >s 1BœâÄ!Òø|Æõƒ@IDATšb ALÚ] Ð ög8Èì²þã¯9ÐBR½ó˜áS–Š-†&à4á ø6 âó¬ö8ø—xlÌz ¢u£­Ñþuñž²ÑÈôm,F`»"]^€^|¦·OAW$†¸gA†¯Ñ‹GŠl à#o"&DšxgÁ 4by- Âog1o™V• ´Pcƒ°ÒÖN( b¢üy¾ÿVÓô 0›<ÿ€D mÊmïRºó¨(m€’ ÎĺкÍNØB1 ΀ïºõBHÑ—vTr:ví~’!0ã˜(^ªns] BôfÔìt%ý¦ÒíPL¡”¬^1¾é‚SBPJ_µ8~£ë G°ª…éSpcp)s•èà@¬^j£7Wcj8Uã×Âcòh|%S´t´¾j5"˜-&r›LÎi6W-¼Ýx#â 1U`SŽÄMBÆ!U/$~+‰Í^­N„ ™š–Ôà¬U•¦³Y(M_ŒÏkç×¢ á½xF—ƺ}tAª½j¯«ÍkÁɪŠã7š§†) ü¿ŸùÎRj#šBJ€ìBøôC"xâh>û•ªijo«àxL"Y„UH½S®Ä[Ø Ìnßÿõ_ ¶O]›+HJKƒ¬ÚÃ@‡¦eòVE`ÀÔ4†üM¤|»?ïFƒt1‚ÄkLJZ MÀ3sY'â+i×eCi%ÌÉJñW5…I;¾ qsü]#æ¹ÍïOA̺šÞ†ékl7½ª+µžUI‰ªÍòJHû_¾SêêðþKK²âD´ œí¯T˧ÊS–nãØ9ÛÞ~®[ªªQÚD1 À,Ï*‰ú‰.0g|úi¢‰‚FŸJR[5N5äöá{3Ñt1%~úÒVºÅŸN;¨ŠÝ6D‹éÆig̈â-&ÅßPw¥™šj[áKán›;¦®”鈑ŒÈ‚vãh¦ì£‡€Ìgé7Èb4»d8²^4œm ý@H½•t ˜Þ¨ ¢d7q› B~ûÇ?þ¡ì3Ù0(u«¹S38ß~ºlÀð‰2U%" Þà–à™vUAí‚ÈøFï×£vEvÊ5ò .hœFdjÚy1‚­ÚGŠ,F«K,híDðÙ‘¾¦ÅæVfÒÄÓB˜Ñº·D|+ÇU‚üáªÆ ÈRëáóø-“ïÔȦ#×…Ó‚n@à¼S–Šù‚¤(àPðôÐÅÚ Ä'›2D¯Ýøªkß#ƒ(ÕÒ )ånž ‹cJ¦šþ+M¤­´ ¯÷ʲh݆b‹JÙ6ѾYI½´È·†.-}LÌ«ö˜¦ÖÃB¦¢KU‹»ê,ëÚDÈÄ)ˆM©±5ÒRp3 ’Š!ô€-÷ŧ½é  xL%¿ˆãÔ×ÂèðÝ|š¦CZ© `xÈŠrïZúm«ÚAZ r‡â•à˜píD€½ZRόÄ4hP ‹U[/…Ž“ïpv%Ï„ƒä!,|é…?®Uñ»qL8ÐDi„Ú¨-hA ¯«¿vrëM\#Oy7¯*eSæM/*\œf¯#’-– ºæýGDðt»I3š bì ~~á°dío–F´4oÇÇMSŽÜòÈpˆA@qx=Ò^*4ˆ”âCpZRG° Û<oUÒ×Hs ÖËÓL–Â9ó÷7K^£•Ω·›O-)SÒ°ícÃz-h—òyF@Hgl¨‰6’ 5DèÇ©b UKŠ›eg‹[ P¬«sé-³Mp€)k”*ù€ð~«Ž€“á4%Áô•ð5J;¤Æ—n±ø|•Ä.ïCL# ^Œo"~ÌPi+Y£ÑÑ€Ì À'«”vF³­TŪR¸TÀ(ä“ #/Ž e•TÙn&Ù@>f¸ÔY¤NçPƒ(ñ6©¤ ÎêŠUÚk˜8—ûë…°h ^øƒké•S"k„¸"CìÄqÀñ̓ÐbõJd¥âªRm}ǺAÛ¦Žãé÷éšb´‡¾‹§Ì3j­QŠ døÉ®Ëb•öQÕ☑uDkó8ɶC|"qRVªÊ×BöüT‘½-Ñ mÒ3ùžŸ7[µyV ~„‹c ˜Ù†AÄuAÑúUî0p˘ëÔ˜o¦.R=¼žÓÖI­E†Ï ‰X‰µƒô¥V€6&)ß&8;u|[©jïÔZ,£Ä§© <îñ#ÿPv¢žœÆÝ˜ÃšåD)+é%˧O$Іĥzºp:E-í,FH9ÂYë~Àp¨…Ç·D5¯Ä.ý8q7C6ЪÛ>p_:À n:ƒ#ûÔŸ¼¥¯T'º-vÞGÀÑkU¯M—†_Ð>ÈŒTSàÀ|Á‹£31ë€d‰¸ ˆÞðJ¼TU—€§€·^&f8˜ñ?“žÀ3Ì”;NâzY¸À[a%³ŸwϺS5T ÇóŒ/uù8Úq€ mJ]=zø&’êù&’rä5"g‡Ah.¼k¬q K#ví,ü+|î¢3ýps;¾®8¥ñq)чêo€ÄZxL&^€£±^¾f††yÕSLG ä+aí¶o¤Ú-AÞ¶˜@&Mo+ˆªÔòtÃGú~‚ìcÏk$EÖ_vò-€ PÝÜbž¾vâF€¯id¤ôz!„Y—=CòÑðÉÖBv#pv"12o7R5j‘¶$e›óJv'‘É6_rü”y§™¬ÅÖ§·¡˜!·€qhLjC©j«ZI—·KcâṗqMË^Âhgû{]R‘˜ohOÞ&])Y6²ÝúåÁ÷’Æþ- ‘S£,À_°^ZÒWN»#wüÚysÓÔ(6NoÏK@ª«h‡4”/hƒ”ôúuh+¥ O_; ÔK–ׂÃOPŒ6¦ œ¡ÝâÇ%Î×Z a#‹á¥â2Dú²t7ööÆß>”GÓž”˜5šoJ`q‰8R©^)|ÇÇŒÓMz(R 2&ñ{Çç·‘hi™õxL¿Óóº ˜øÞúhíhZÐz©Z@ÚD &hm¬–mbJÕ˜âv Õ¯Ó@1qüöéDâféMÖä>,Zðûþ‰€Ã4½5àíðvàÏü£‘jN‹DÒÅiKˆW¢±$0›g‚ØNdSZ|F~¿\Z®F4Ê£ àÈU=§éÅMçëÂ7—AÄL Õ¾• ¶…Tu@1Nû§cm È0èóBtp¸x×%ˆS‹)5 ”ºX°eÂ!Èñ^k Múm%Fæã7}½FD˜ríhª”vh\ˈ]ˆ!øÝ±GéuÄÔe |³€ükt’Âgbšµ„#K•úa#E¸ÜãĬ3¢uí8JÎÂÄ=zjö$‚£®šN åM“ˆ§àH_fÛAJä ÿúçÀdÓ±Iš¼ã³]‚G1*„œxR‚bœ&½È¶U G{ÁðR#0{gœKo;ˆí³w)¦4A¯Ÿ!3AOªUSÃ)Ågb†–‚‡kO1«DD ÷|ô}Cš —v?Ó¢!`VÒ¥DžZ)Å) ›ŽõüA×ß„ª¶ØFè§³ã@èkW ¤&Â}Fð§&ÀWà,¶Ò”þöûï¿+Èyì>iúñúî Ú ´ÄÚÄȳMQcj½ÔÞ~D™˜áKÉfF4¨Ñê|³à@ü\Ç F§Éw¹‰•ÚgJ%£U]‚YR8DÚz8¦¼^š¬€ßž@i"µ×… ^ZœGÓЕ¡E ’ÂÛë¼õjDXj®.fs›¨RKœ‡“Òˆ¯ÚßK•X_»-àSs•ŽÃ¡Ü&)¬«Þ<¦@IÐμ®sÑ÷éÄ1®TË™q_ÇÚf˜âÚU»^â,SzT¾¦]/&D|ë‡Ï†¼4œzWàónŸðÚ[€oJ‚®K#Ù„!;…F†ÃÎø»€ªÞ¬•ªò5žþkÑà{Ö`év–zŸžï%Ã&¯Ô £µ0DHN9°–ÀzU‘ÿcZ³’”Hoi£§€Ö‡ÈËÏöék4¦FœDj1T )Uq%)šÔk,víÍZ‹4„2ƒ[/D×-~n{'™Ղ™ádWì× &MJµ#Sˆ)ˆ`[i¯M`Ï4}]ýõœ¦s1|§æ!‹áº|´ù!º·Ž€,¥Ö•j˜Øè~gÝÈéhëJDP¬]c§ 6TI0f³x'Èļ–ø‡ñÚ™zÍsïîÍé+Gô ÒÔˆÖ>¼ØÑ"XÀÑ R’<²ˆYªšIªÖà‰ˆu©ÎR n1[%%í4‘Iá+!w|± Ž5u!ïb›Ë«&˳u)áG{G@ÐÂ-à#f"B œ‰;>5œ4á‹ñ½Q—ûy‚uM„¦Ë!¢.îtJʺŠáéjŒÙpT!R& DTâ-ìçZ¯º 7.¤Æw „ž¬5p˜*(͇x"­dJ—±€j»åOÿ}C¤ ’²ÞÔÚJUS)rœ|“g®‘¦÷ßþáîˆÙ’6DsEp±.%4ƒ^Krf|ë2‘Uy†|«jÄl14ƒX€ €3Zy’Oʧ î€Ú[þ,qMJÊ/24c³Z ¡ƒ”æ£Ôë;VJ_#} .å[ƒ¸”--Е8&pû—Î ”ЈÛÖoÿRÏâ¡„fŠ’€§ A³›*-– ”,ÌÂ5j¡CÙLJˆ*™ëÂ9ÿ­?Õ\Á] Ú’À ª’ÖI„Ó“€7;DŠœafÒ Bvx%^cC­×#Š- WÌjt1PK;ˆ ¶*CFã kÁ§£]oí¯‚eànLo± µÛ3}"ÒtÐ*5”ŸaŠÑ¶¡ •øÌ‘S&%Õ"°­BÊÜ9>µiJá>@´¶j¥”!Ä÷– û·] YJÈ[µ=Kà@½¯DÍ'BŠÓªNº®hÓAîÅ Ã3)¯*Þ>Ò÷³@|—ÐÚ| z­,†÷ƒÕþJ¦(µmjÈRæBÚC]Ž.©'Mþ5#¤qŠ j£µ×ˆÐTdH²-/n4œ)0¸8e1M¦]œ‰!-éhÀKùpô"$%`<ŽáV>UH#*%n%;Ô…§4K‡ïõ 9‹gÊÄU ’Mm4+ÑYº.¾5ºXR~©ÞP`¸ K-ßní£D¶?½ô[Š´öJfaÒa­‡ Ô‘{:Ò4»+ËtºþkX%¦Ë3‚'+ ä‹Ã/nUÕJ¥||"•B¬áÈùçŸBútKqXëÙʸF„ó¡}ºF È«n®Ô)âêÞ¼Õ@F­ßfýi»¼oLZDÝo?3˜6*p±1¬%ðKᬄiŒ®ø|ûµ+Y‚õ.@cÀ-wþq8•ª*Õ42¿^Aß)Èo¯R–BGЋÒ²üª®EÌ6e' §Ï´85åtÜO?ŒSæ¿cþSoGh:¦]Êc›aª6GPò¤:¾xH‚8ö±ÄdpRŽcU4ûØVœB)©)ÿ¯€šF|8µ´gïúy‡âŒÖ”¾v)À×Û ˆ.Ê ¹³+ÅŒ¬$Õnܼ ^ÌRh1éªoð®Ý¥¥9~³´¤f.³d\£=qÏìïn@gab¥ Ð ©«8qqà•9ßø-_—¼}œÑ¤±ªo[µž®Z’…·‰ª¿A‰ò8­ÝΪRÌð¾1Þ’ÇmØl7#ðÛI²LÞ2뢩¤+kOñ‚ªRâÈJ-ï¼ý ’¬bl\âÍêc›( ´ô)ëÍÓ„‹5¾YÎȪöæÓQbí‰ 9m©¶Nj€(~`ë2‘/#ûÝÝ#«]£‰uáè£ÙG i+iœ\Bsú÷û¶vS˜*~š©AR†3)Sòqöú)ÕÕ¬ô)§DÞóÔTµÙYâ¾<ñ&ŠÏ*×€º„ŽoãqY:ªµwj]DÆÜAÄ4µ×¯Ò{×ÅÒ?“î"е‹ù1¥í|š¯MùH|ߊÚ(¨ËÎJ¤˜}*ñ¶RTBkOitµ (óª.!Ÿ8šTŒš˜)NDµ`š‚”ûƒÇ–¤à­v4LòŒ”qÞÖI'®‘Y+•ÚDï-ž…+u.>SM³çh_ tº®º0ÿö·¿ýñÇ ![ w] íhÞp±ª¡Ô(àK56N®Ô’˜ékJY´1Ì ë  GµAz)¼Õ7n̤ڪ{㬴8qMH‹5‚‡Œ x{ãCZÆ\&vÕ}£vˆKÓëø|šÆe¥ÉBÙð¦l^¡6ÁDc]K;˜+özdw©³~ä~gk¦*¤_Eð»1âMhoŠ´v>‹£š#KÅ|£'øáÝoæb ži± ommD£3rüZz9Cpð£‰]Îoÿûßýêœ,QóÃ[ºËª8¼˜o¢Í#­QÌÓ¹ÂçË…%ˆÏà!‚á—uhš•œ—„•‹4âðî%Pû+e7RÀÇÿ¯‚Ùë[W¾Ci¤ŸŽøסÜ@LW×ëÕ‘uýW›HïÎ1íÀûöA "&²•Ä1x#´›.Mȴ󞦀x‚‰#3RkÛ.¤‡(Vj´ÆJyül `±RWd–¡RâÆ!À!½`ªwøg+ðùØÊBðíCD ¾®8‚”Wm–ø5U%ˆ .–:øŒü~¯÷vRº ‚ëí¤@× ·RW o.jÒ;çóZ)d´kâ€b6A³gD˜Ž•êªäìd¤bU cJÛÍw/AXR”˜lÛ–òqvd+¥€Ï óðÒE+V]Ðè˜8·6šµ•Lwƺ,¯Z×=ÊçǺxCt1´æªvu])Á½cÝL¾®56½^ ýGkP‹E¶6ŽX ÎZUðvI-¦”Þ½Ci´|R/®—5.èõÎïøÚÓw ©H*Gº5~ÌÚÐ4Ûø.–l:J˜Ô€â6ôì ¼*0‹Â#ì5‹PKÊøµ¨ òª•úS™Ó5!5_n˜é#3Ü’{= ˜J]OGK© j£•2U%"<„§cºƒ X]‘2 ”ï…¤À’-°0D;²àž¾€á¼iíq1O™B|Êi*B*éB볕"Û³…Ç'‚#åÝ•1N½éó B-Ù3àòSãKqrH©[ê ú¦–hÔz“x% ¤Ž& Ü 1*…8N ÒläöI\©–"oJÞn©éSiãTí t:1&CèÑ@HåѲ퉼.ÌÙ»N¸ SÕõ¿8©ò]l4!bRix>YèíV1¥bÇ)Ž–OŠN†éA§Ó «Ý£O¹Mà¥"¦xâ[²ÑR‚ÀbbRuk$«wšÍÂé”<&d)#Åtù¨§WÕÂÀÉ&.®T#B[QBx†f.kx'eˆ”B š8Y%)¼éb-N1¤ÆtTBÜ-¸+œ_ŽýAYU,`ø¬4‘[5‰§€³}ÄÖë*PÝt)ÁàL¯.éKÆLÈpx4Þܤ:u½<Sm¢ ¹Èñ».´Äw„uÕX—m œaïe+a"À)˜%õ ÌóÒˆß,)æž 5Õ&jÁ¡É Å¥ÔŒK§¥,>dÚtç7YÌ,Axi¯¿jÇiÃh6$2¾*oUC6‚ “¾~g™fÕhâŽ\*Ž6o)‰ì‚D†kìfÚ§ÛpEt¦¹.œŽÃ<5)1Ç(`»ÜÏ)x|4s¥‚תêm.AH¾)¥{J˜I9‚ 54-FpŠ«n½¦DÐÞ ½¤ú&Ѩ+a²˜ªõ*‰Û°|4ž<)4±Ñ8Lµ5¼<hJ—ŒÜ÷[½Éºü·¿˜ð­Dȿ糮hA³â'Âà#ô­(È®Ìçï5t1šøÎÞ¶ Ž©×zÌòÚÑx1Žˆ,à‰8¾®’ß'+Þ%ðÈ84ùhKUMá5Úß¶!˜»hºX›ðÖà•x½.¹T{V’Òaª]‚XPŽ”ïÞj1EW³T•àÌ’¦œ%¾¶T ‚‘ 4²ÛwÞÌF Æ\ŒærjÔÛE¡¥3µJùfÍ¿]Ùª;Ô>2f™n7h:¯›WíöT˜n@¬´w>q%¦´RÓu¥Ðc…à7K„HYÇÔ• d¥#ýý‰dM¹}ÇÙ“ à½HÐÃòT/•ª’ 6®eÄL̬ÄzSãYsó pòfy Ä-YÌF <®u®Ý¹ì¦ÝPéé+%›ŽV{¶ž'µ3éûú É*¬%°Ò¥}¬''ƒÄ$,H³#DˆÌÓAàáNšÚ¹âû&G®:µë5+fA]qR¦#uK˜6o„*SŠÙMv@œJ|âqZ[¼ œ8ó>øO bƒ˜ѧ`Ic„q¼{g{ZZ@Á,àSaDâð¦•{ JáÔ .4ÝV·ûŒpR`é³”&®]K à둸cÖÞ %i:ùÈ[ìüN‹´ÓhÐŒJ´©Ætªz]h¹5 &"†,Jµdð Ø{ Ð;mqhã ZL*°†ªÀþ‚ΤɨÑ"VM\ ©ÄgÑà¬Æ‚ œÇ#hUü[°R"||g ±ƒ ‰¦°p^)"ˆcò!Ôà6aií)¸ZT•¤ñyf ¿ñ»±Ë)ÀGÃß ƒS†k‘7QéêMXU%±R®„ :ìË öFéE€ÀÛ9~C5FˆÓ+ª—lCáSRˆÉ´í8ÕØbAä<ÂR1ë]Я+¿Cá›»ÝRžø­è´ ¦‚ìP‹Ö’á;ˆ‚Ó8hâuMó]Z'ÒÕïyg­çÓ#yº‡º”_`•Ìr'R†Ób%øi¾oy™ÛxÕ,ÓÂJhõš.+ —¦Ï³^ » ŒSW"Jþ~¹¿lVLd†Ó&Èvé$eR%x4Èíø¼]'¼|>é}p9-O!5x‚‚¦×.õ›ŠR)>5Ü'N¡¹büîJà…ß>ÑüH#ÞnÀð&F+‰™)q"oP¾ªÛ¨¤eÈ@ëR À™sñDJЩa 0™€šÁJJ5jk4³ f1?ޏ®@¾ ‰‰#ðS–â\øW)Nþ*WÚDq§+uÞÖ†ð˜zÑÙPLÏ(­šl¾MìþÃ;`ƒxœ¼€UåuÁ™ømwáýF>æd‹™k¥Ôø¦{X@‰G`½‡”š 3dÌžþçÛ¬d1K›ÛÐîІJJ½0µÀû(UÝP±–³Ù×´·XdUG©Ê;‚Ô%ž%PoÛ§F]éà@l>µu›Øôñ]K²kl¢RPoÈÙûùDDà[ ³Y‰§ÎèïÇ¥ªÒÆ-vuI5Z&Á1í“Bøë5ªò5 ÙûƒF0©ÔðõbFÆiÌm̪ùp„‰ü Qk+¶£‰ëݬJ½!«ât“ 9Š×Ð òþé€`ñ» Dªªñ¯%ÕóérS¾)ì!†(ø“·”y<©§«dêa¯Ž ‰ámÏÒLAUÉ'M*67d+F–jìlb#øLŒÓwzw-Ål\ÌĪ1 ±[ ÇWÿ9ÓÅ·xœ´ö7H­R7ƒ,ØM67÷¦%ƒè o(¼m£)•†7¥•x¥ªDð‡”¦l4NH? ШÁ]Nˆ9Žéíí)­Ê; !è>øÌõŠãÏ¿A4äÛ'È2U˰֓RÆ1Ë;†ö¾cGëû©ÆIpÇ™&Y¥RÁºB¤Í Y¼&“æ ,)0Žï¹‹GKGÚtœF/­””åJl ôk i'ˆã6}CAtiiAqœÆAXÎ;«­€@+ކé8LÊ å=Cð-¦QL Gì €JÈ@±m¥ýÙ5š´•p´óµh¿ç;¿<ô£5ˆ¸.&eµ¨ôç|HS6®e¼•ø5±FjÒb^º)ÒÈâ0 ¬€Ghb²È?î¡UíƒYo>Y¾`¥m¥ð]NR1ÝOiü‘ò–l„`:JŽÀ³ÚãH;ZA‡«¢½ã€©=gð=_ÂF+‘¢`j?æ.ÕÈ6Z¬½jƒÈ6%ÙKÿ¼N”ãØ ­¡zቴ³H $‚4©`)_ Áª4‹™¬q„ã°…)FˆCníK98a²âÎ2ͤ§W¼ô|íú !éïƒ$¦k óxê×LŽLÎph¡Åð ¾S>/ f-ht|MT\™_¿tÂøÖ-–jk‡M„X›ˆÝšžxûø®2d†ìý›>Ù6ÁHY-Í©]ÀÐ&(ÇGPºÝŸ¯Õn)0r|x:öaª<‰;×@][҃Ǣi‰ÐˆÚ;¾XMÚ,ˆØR±¡Ý5Liòéć³˜5’‚R‚5†‹3½Mñotg ‰qT) ½¦tK¼ïh”9{;¤P¬‹>„ß\qi²â6YK À‰´F²Öˆ£Dƒ Y¡Õ–²m†V¤ÂÒ0If°>•e­ÓWŽ)EÖo x CVièÉj:Mb½Â¶”“’ ì&SFZ;«€ 0I Ë®°”Õ= }½ëNfxAÀʧ©^ ‘¶Êb*„Éjý–˜æ²Q­ô|Úæ\wL¤!º×ÂímŒ«ú,²9¤ßl+«àÕ†;;RjŒ”­Ö:FÙ«Žtc¶ô) ·ew4±p†X­Ø`˜Sðý¤$NFÓI›P‹”V±-ˆTÁo—˜  HyŽæ8ñ­ó”ç°k£¤ªÌ{ú9PÚêRŠ ÎÖzs";#eþ3„£TU)1²û(å‰i¶Ö40ž@!Ìȯ;™jH FÓ%X‘óÏ¡Z˜L*AV H ˜˜³¨6}šV©[c[sãCc’©fó«%`žÆZ ¤Ö”RîV˜g%ºÛžŸë¬½6>¤™Ú*˜ºöÝ,¾ë@ÂJ€¬«…ñÙúêû(ežR¯IåÖ¬¬(ã•c„ŽÙmf<±sÒÔ#«‹ ïÿ®rª:½  ŒÔ×—ì&‘â/Ê*ÆÀcTÙf¥D ã €—Øâ­4²ž‚•Ud¶“™ž¹¬Àt|˜IcÔ¨,¨Û3ͽ%Y2É6M&•û‰hâ†!`>Û •D–…K)X] z@\îüÞ¹Sl†Ê™(·CjM1z «l¸B%˜&ìø®HÕ<똠ÁZY!Ó#ßÀD8¥5ÿ¥*G*äf%n¼è‘pÎVdã©…s(ëhÊc„Z«¦J¬—û, Ð VA£/ˆ<3QFPøXÍà­ ¡´Ó+ÉÙZ×<#1)‘˜ÖdÖmëØ¶BLz½¼'µVb’ºÛ’âaYʺ`Lΰr¼­”p̲ŽÄ¶€,°K³-ßÕa„B‘a ŽH@ðÑEÀ &Ã8£­5}‡–R(‹ï£ @cÉò‘5Œ¯>[‘ªeØJoեޥ¬ª„TÔ‘V>€aš'f«T«!­­eaz«0ÒÖºC™­ñzO*'N–rzšz a²”ádoí™þ>¾¥´óÚÐ×ï,ª0µPž‰Â¥­Y)¯Š î>áʹÁ¾4ðµËœƒH,Û¯U˜erpW‘sÛx+*V4ÇôYíJ)wÒ¾*âirSR°¯*L_¶'X»ÊÂ+ÈT53,Õ]IÕ´\#…ñÄ*‡U) k Äl~Yz¼€eÝC&u”í~ŒÐ(g×¶–ýíŸÿüg^Æê¯€Òµ§4Œ¤D_¬º–"n&=A@¹€ ÔV%aåñÖ4ÖÎÓ–e_sæv~Ûzå@f*†º”RÂÁ–Œ¿xKšV²1ˆßm‚JšÁ…äi+XõÙ<;EåZÓl°ejK5‰BʺªR| ‰¯ÖdBv¼mƒÅWˆ0”Û: U¢ùšÌ«­‹ÙèiI ­pÛ“{¶² ­²J€Î˜X iQÓ€.¢™3lÅÐÇçÉÇ6ŸJ¦O`•x‚V%¢‘¦æ¶í˜x¡œ'ÃüYÙö½¦ÖÖAªê燬z)Û˜4î¤Ù€Ê[‰1lk·*YŒµ`’϶²‘@ØG a+ÊÒÿ¦ÝÚaÉøØæðY¡©"i&Kl%S„3™¾7ƬEzå[]zWï!Î-¥Ö1¶]”“ÂJª%HÙÀï<ø&·ªUh<ζÊe1añÚÁ²Y¥Ì¼F@0\Gw+Õ ™Z¯ï:fXíÜÚº dz)4¥-lucœ‘gúïüJjG™U£’©"S˜- Eæ·|Œ­¨ÄY€.¼’Óà[«jV™+„.׿,¶J5 +ò±:TíZ• ÀSš˜òŶxÔK°š<&Rü7¹Â¶ k}k¤VP"+ÏVm©ªˆs¬V¶5›ðì`!ÅÖû‘ù•†_OÖ`{’m$Û 1+kaM©… n¦w‰•k$¤ÊZé 0`é­þW“mÎÿ;sL/­.¤Çƒ³-«ëa‘5Æ M )i‰ì ¹|…¬ÞvJd•¬^PÂúZÉ€n£a ¬]ú:VeªêÕ:¦- €ôè Cœ§ ±Evç:Vz¼6Ø; ²`(ȸ!ÉÁ/‹´¾'’}Ë;uʦÂ$ Œ·mξgrÎÓêÎRT‚¬©U ó¤ )x&¶ÂÉðm;Q¤*AÓ`›@VUIVÄùIVx=5u#ÛnlV]¾T嵃·Í¤Â²Í 0r­›6«4²õ­Ö–ŒyÙ7ª­èU¹Í?Œ€^êüiØÆè£:g-s¬AŒöù:¶ÿl B%x^™¦$üHƒtr2 cü¨}J YcÈ ½6 [˜¦Ø7)'ÔkÄgš¬8øœ#)1 ”çùÎC™ùV€ òù3q!x€­¦©ºÞZð¬Eæ5•R…·í&µè%ÀËr —ôE6‰’ ) × XJI“˜ ýÇô€ÂÄ Æ™ÞÚ_ÿ#; &YåHL¸Fµ°ÚrèÔÌ1µH¬O$OÊ6+²õÒw…3„)Ÿ )Å;OÙ¡3O̪ñlcLNƒd•›•C+ A8]²üËúR³Rzí¥Oh ©@3ØŠÆà¶ݤÚ~,aN ]Ýñ¬;ì©ü2jáÉ` ñ|ض¯?ŒoNµ:êBÓ×…,J­ ™@ µø^é˜ô­Y˜æ¯i-¤d€ÐÑÄVÖƒv-nfYb2‚ãk”Ò* FC °…ƒXØþxs[ËZÕVnÅkÔý˜çfÎÓ•0¦ ãL|Z~¿-;È»eÒ÷[÷Ã$åL”\³ó›@O©¤ÓqÀ÷~*$¨„ÌVÔîn»„¬hv“x…ÑYZém”çKÆ7ž[é6ð ZeÒ:ÏÈx&hµu †W cÌIl+lEØÊA–gÒ#m …£Ù–Š·f2rÛÕ¦!à€t°XwXª9'ðÖÏ1ÁVYa+ò·µ6†^H@옜m{Ķaš¦ÚäøpµËRâ[µ­)&2fnUX-YØšÃ)øþñÕxùÈ6$0†lå0h<…ƸFØ @ì°”5z}¶íÝvï+dr|ï*˜RÀ´¾S!Ûît5²u½âk‡ ¶b˜ŒÏPV¡UÇWikl¡„-™/Æa<=M†ô½~qVRÉæ|ìUØ%x¦ôíÒú– Ç[1V†M‚QâaY1d=Jk[knª @ ©•!~n²é'k6d€X¨4ȶÖpOD8Òæ TÒ‰zaU¶;ô"L: ñ˜×ß̶¢ ©µZ`1™ò”:ô²¦×.FÈÂ|8X+±Î¯\43‡ ­Ÿ¯E§^ Àr!Â(¨F–Wýhè¯ùçœô”|" (¥#­Q;k .Ö€3è(€Wx&t*½ð9w}u¯<†É¡óë^U>jïÿõºI¤̬œ§mÈX±-% 7§¬°Í¼Õ<€UJIT[jW¤cçԥ- rS.«Dhd˪h0X•y6ƒ-¥R¥ %`Iã·ÿM¨V)æ£|3Tø2Ry*¬;€œ§#pÓ¬!›¤©¬é•B µëˆ™oUH 0‡S|¿|éߨ fK_G+>&7ëB–>çpæJÒ¬¼³ôþ—Z•­¾•hÄ#›€7S••§ T"ÛÖ*e[¹ YV•cT‰ó*”ªÊVa†M…ÇPf’¬Âj[‰V6sÛ°ZæVÛƒUmòúVEf›˜ÛÆàÓÁçF†ÑWø—œ‘ÿNÄ'ÛN±ÉÕÒØ« ×£D(i°æ´AŠNÚ„ÖFyÓök¨l½dµKLçF²RJÃ8°Hf›FI¿ÜðáfÛ̲‚˜Oõ%àÙ1kÍŠ Æ7§ÂÚ½Wá4Ê­^ãÞ䶪(1lëHc XÀ­5ºÜY:Âó¼#}cóì!Úêå±’XðÃ檒Áî§«ÀôˆÉðÖ#4è†DîBàHÌ ‘‚Ûô¶°¨ÈÏö¨¿zUi0d¶bâcñ}» oå ’© »ó m+‡«Y‚Ù|(Ó3ÞAÄ@IDAT KÑ É“ºÃ9\§_¿»”róUÉR <ÌAŒŒ¿ù#h ÆÈÏÍk2Y)ÊH¶fSbæ~Ù­Š€2¾÷¡3î )i(;oC)"i({á1é­ñü™+kå­ XI•Å0ið­þGá˜Ü扗µ}Ù"–…‰µÌ Úb¦áÓH|þV<¦ìøpªÒÇÀÈV-A3·òQ庬°èê6€/<µ–ʧlV´*²HJXGëlcJQÆëQ6§•/ëË9¾7àº~^Jå‚R²Öcw#ÞºÚ£¾2­¹½Q %€·Ò„• dų¬ËÜ4‚@ì ó!Þ·ô¦"빨ªä8šÀÞ'*ʥǴH}ý7Ÿm #:RûV/€¦ô£¥v”Í„—dp]¤Vå 0†F­^úZó©J*¦L¤0µºJ‘[‚è «J @ÌÖ®”µT|Šô ×”¬y"™¬è®”´C¦0q·G`¤*Œ´ÆóÔŽ@ ãëÛEEÒ[‰Æ– ØR˜^½0‘•·®¼a*$Ô Àó|žiYUf hàÆó(¥úýf*É0îd¢v¶‰ßTáE€¹^¶9ÐH`€9à#ja-e¥/p÷†Ì¶0ž _Dbòá,Å–Fä`è¥qz)d4RÕ" l«µö3Iàñ¥énßIðô=£°ÚFÊd2½8‹3Ü÷§ ¥ðÉê"Õ¹Ùʪ•¥QÞ§¦Ö²É¶RJá­MRÊV c ,šÇIýIÕ|$˶*¬¨…ÉùØš°ËiëÁ4[YÑWHÃGØÂR€ÀÐ d§Æ4pµxY ¾ÂFj #ËÂbøºžŸdºôúHŒ®ÝzÍ? ;…µeaÎ=ð,™Jw%%² +d‰çÖä!…ȫˆd@³åßJ¿3É/”9¸™má¶S!åJ¼$°,Ò)°r[Y˜y Ÿ˜Ru§œɉc y®Àöœ…RÔ]*ƪßÚND©XÉË_˳(QK¦c§¨ªB dɈU l›9Áß¶Âú¶.K0Mc¨ lÎ|*iÅDC9’X¬0€—5|ó{”žfẺ:¾*ë²Þg‚š"5‚%} l ”Ôˆ@#$A§«–°Èd9̇Ô&àL ÅDà1¶¢ÂL’åü®øR§Í²|ìª çÑ—9à¢FL[YÊLrÎ$7øô»¿£§aTëÚbjŠëéÒnÝžBJ†HÑ0R‘â œÏꛃÈÂd&³¶e§(áZ‘B/©€•›`~rßï.¸a2§A€FB6}«TÙj‘ñ¶§Á¥t”2‰ªæ‰)‹ÜA0aïœùÏ8“¶ÍÀ„F‰iýïáÈž‡ê/ü(•C îHïJe~<Ða+’@ÐÛzxÍ]{˜{újY!F¯whå¶yÊ µ¶V-ªò¡â©^;Ø´›S‰­¬¨…r†j­0`•bCÙµSH‰a¤ÈV»ãà oK¬¤¦@J«°­Vw3sÈ_65МÌÉjQÊJ¯] Tí`½’a:2 #ÞV_'ň”ýG>Rª0¿€cdmU%KÙ¶v­x1Y³¡Á¬µû—rº×ËŠ1!²FðªrsŸU¼í¢Qñ¥ò$ÆÓð4õ³[dµ4Jè­xYѶ5Z[%ÖlÛblájÍ)0™ë[*± tÉ (G¶)‘€H ¤L@ßÁm;ŽÚ1qŒ¾°Phà\¶1à•ÈÂîÍ—€,,V^ïX³%îOûÈ<¥t [ÃHâåfåŒá™ŒN†!ÿ›#×´Ot½¤¥`¥‘¨ÊÚØf[êÙeººé¹u„•ÔHy}sèÛ’˜ÿ™à +ï6ÛF‚ejÍp†­ÜÂÍIÌÙ•VUå|ØZµ€È™¸mVž³ÉkÑ tX§`‹±åC`Moµ …m-Z•Œ—jK\Û˜fkÔ UÑ`œÂ$ÝÍ6 ÂºØîNðHU|ððîó"‘ᵕØÒÀ"OUJYYµ" F#2gõÂDÖ¶b÷SUž œP\ïs“€Zí`1ȶ@þo’F¡uÏôÍ€'`e+ÊbŠÙö¸ó‘¢¬{Ø"« Óë%ËknVAfe"`VŪù«½ò³à]£.Ķe{Fé+$X @ ÒWBVز€î4­È)çCÓ1¯ë±mìeÍàI\ÀªøøˆÕ½*ÊIJ›¡Ã~KÏ©Å܉ãé#':EVÌÞ'OŒ_ŠX¯ Û&l€²‰ëÒš'HS¯3Ÿ3¼Þ±¦êLJB¤·šFÊ*‹ñ&ä&ES°B6,`Êü71^6gEP‰–Ö¨ìnrb²FʰªfÇcÞ-Ü ­4@M¥‘1e•ll¼ËÁ´©S#le"ˆÅ¥Ï„Ø6· 9°BPío¿ÿþ»`sIGÔ »2ÛJš·,e}g"óÑ@Pâ[mIÀV”Jc+ËðZ my–5ÞïL¿NõýÅG‚!™……rQknR‘¦ìU}–¥ˆQô6¼mþVÊî!e‚\”ÈzβBµ¢íHÇ \/+·”P²¥±¦!~ÉšJáÍPk%²¶ÊêH0^ ¦Ö•ÈÖz>”²¶•‚8²*«_×z¦]H#QFjäøJ±Àô¥™§ÕÖºh~[zU=š¶„Fô1¨P¶ kšùí)sö:Ùª%`h„ó±åŸy&ÖR@˜à©ðr¿~h•b¢Dj£ë+§‘*K,²ÝñÛÐ_áB£¶)DZ9ã‘ÁΪ ŸRÐâ Jd)%Ê­¶.bÈRJqh[Lå@žU™AW’aÇÛJ5mV¶ «ÅÔT-±÷ªÏhJ[kß9ÈæÏ!e)Y@ÖÊÖ– ±¶ÍYJ—¶«šñ›jÎ|ò4•Žf…‰¥Ú•K‰•$°z-)¥à‚¦Ïš-ÌÙ ³…{1u±×%ñë7•rµS—VŒÚº7> Ûô@&¶²ï¨¶Êé…îd•Û†‰; F îK£ái€'ëŒÚ‰ÚeN/øl …|ðjitÁ¿2X kqÊn\Ë_¯¢ã±"[ SßÖmijOfr+F“—ok•-jD#ð »"˜yO”ç²îk@F +!+x¶UÑ0I‰)kK`]Ôh&”]¦êBi‚Þ>k $c²Bžù[ñÂé•wxä¯OœO”Jó6•ª¸?cû1¡<‡5ªé¶™XÆ*83ɲ¥ÆHã5 \k3 ¤Z[‰W^»¶™¯ «PV ¼§“sÒÔw픈Ì#}^º¤H`e’O×(ê›L*ŸV[3ø‚,†9=²ª&¬#&ÿ²)O³û†Ëb"SZ;¬Ö°PnÝ´—ûEvç ¦i-2± ]¶¦_U/XΪx€ID¼u|>ñwüóÒc€p—Ó6¥©&ÆxWYýö׿þUq&©U"#5²¶Àj><€¼Ó~~`cÍ&0}%æØ©da©™œ6ßà@Ю黂·œ@ëÖZtûªÈ¤*wÅC€XÄ sö>u®Æ¶J¥ [‹<[1dabxׂì\üñ”pCöÈw|¬ªDG ‡³ÍÁÿ?Rµ3L¼vzÕ®BcxVU¶U•ª%¹Y‘ghUn50Y<Ð…œÊKî8)ëR Fö€ÂLº®Ü¬”4[1²°ª5"HÓÑd}õèiJU7¹ml݃è\ñ¶¯3¥¨‡ €ÇjU-"Ûv@˜FH5†ƒÖc(‡‚ÖžQ¾?&Y“XáœÓ×W—âG‹æQX‰lå¶RbnóÌ–@དྷj~kX Ø<™0O,«Ù¡ðÄ¢-ÏÜ8d‚Qbí5öXá¦-¥Ü6gëR¬Ø²"–Âp³ ©¸*šd›p%xd}éëXVª 󜛦1u$+ÅGÊ*6€¬×Õ–s˜¸@Æðqd²5M`!<’3ñéw[û@`†þ|žyÙ:ÂHÃb!ÅD`:@†±Õ Sö Z™è.«Pd.Ÿßàæ¤[6e[ÙF²¦”Í s![h x‹Ö.ž8½Z ó‚Ó…+‘²Í°mU3ðªºmX(¹ög9™Œ¾=?ŸtÄé¥j]aµÓÉ®ü,Í™Ì2±©'Õ#°Eæù–dRÕ1}¾[”È*1Oƒ%H£¤{‰ +¬#‘u?™LÖVÉê5 Pž¦”^4ú nÝ­liÌ (­RLJ]úóÐgÅ'A>°OP&gŽ›µ*aEtdº´…e§GÚ*1d€@SÑÖZ ‡s°¯LI¶”ܬRë¸^MUVâ/7Îñ )sØb"oég’<ãɘp@n r²uìøHÁBæû®ð×¾ m ÓǬ„’ªð@ƒ_ú,4 àënµÍm…•H‘ !+l[oæ`AßÊ'[ “[oÆqê››Ÿh¶óœÏÌÇ)§¬¤vá9|Ñé»O8gèߨ«—¢û%ÀïÛ™)&™UcÓ¤!cb«PØ6(þ7ŸÚ"Cú¶38àW›'’ƒ •Ö<ÃxUH%ù ˆc”Ó(éב0²ìª²€ §)ÂHYÁŸùü}“56™ZŒª¯Íéˆwùéñ˜"q+«+w»ãä&+˜°ª6¾mÃ`8Í’!\Õx ¥mÝ•oÛ Te8`Șw àpóUn%È÷ýß{…W+LÒu´·*—*ÿbY_ ª¤´£‹ .Ë €ÖJ€5Ú[­JJa%™ØVˆ„õµÍ 7ž­,&¸!)ÓÔ¢-†l)sµðRb*´ )‘yâxµNG/0U±2¡Á00R6’ `Ë*=œ Ú^C§8cdˆÁ÷_mÕ‹@_…#­²ù›n€ÌÀ@ü­û"Õê¢c3ÐÖn£­Ÿ|s£GÖ:gµ"2s«-å»Å¼¿„5Ø”ÙZÒª£±ûOˆµ¸ÉsÛ”lLcò¡dU#©ô­õµŠ ;uUVž›p2«l«r2ýÎRäJ– FÍ_ëܪrüÈÜ)²ž©1`‚4MU¡î#ÕMªµeHm[Ñ6A+Fm©kö¹Ã¬HÝ fž[€I PÛØ¬—m¸¬rŒµ.4ÂÖqð<ËÚâ?Ö÷M°­£T&^ m)žÙVˆÏÄZ$€ ` M.oÍS _ªu4d%f`•2`<€Œ¨QËvRL2õJ#Uè‚WÒ¨H[«­™‰EוÒ6M²›?wØq|B…¦xQ‰u^œ[ÆûâBªR‹ôjÍ ‰ l¤ÄY™!玠1VÕväñ½Qaà vÀ1¾~eµk”^¼1¤ZLÙ$‘§mG˜^”þ Ö©zó9¤­X¨ìêÃùvY ”¸4|âSnÛ›¬Ž)#­ÄÉÔ¶e ì^¤ªâпΨE/V'JÜáé7?FÊðVå‚¿ ð“C­è«Ú0HfE‚À˜Û@¦‘bÂ9™’z8+šb-lÓl5*“µ©Ò ·Õ‚R»šò_¯[›_yÓ6 rÛñÄÊEµ]&1cHŒmݛǶã[ÉzL0T¶y¶Íí«:ÿÜ0mƒu!€pVµw÷ù™mKóÞrš‡^*%M+›C…ekÚãVë¼VŸaú¢¦Vž²Ê'”hd4¥0Mb)[ÓøîIc¿Ò)ì4­„h<<,0< ØXñoìô%¥X¶F¥d¢6+@¬©,Y݉&³")ea1P»U«Ž®½G,k»!×H‰­T…¶ÊÙÚñkd á“)ø:"u‘Eæp‹þëƒL)[SX俤€m%@Î5……*ÝX‘¨ò}ÕR31R‹1nF¹íë`Ë ó>/…½0²|2¡¡,ðÂÚváéù«5UÏT FãoÑ©:»“[™'À³RPi€©‹ŽôªjD3¬Fþ‚PÊðH…0 6çšÎ)تͿTHoÈÚçì–ð„\­µS+„‹ZP¬VeÛ1Âdx ¬|k@!2MâO›ï'¨*úMØÆDÒ46’ç"¥UÔhÌ„ž‹BUî@J(ÇÔ—¾ƒŒæFcf& C™¸1vv²4jáFÕˆLä†/ðÛeëŽ/hú…’Æä‘ ¦ä-Ü6[ 50[VµnHåEP*/…I¯„¦BYášêô¸¡yŸ¯,Ͳ¶ 2|åMÛÊ )»Úº§¯K>¶¾ÜlWËaÏÙYfµui˜lgNŸUÝ)—ª AãyÁàm)ûÙÔ‹W J l;Ãüõ4x…”¶VL§s?(Wèÿ<2‡ÖÄôµ W(+d+¬—5ý»ª-ÊÎp@Ö0žx€­cZÓÏYwA3&Û|èe­f4qåOíR¹”ƽ!ÍÙ¨ñâëb[móìæ•p“M)ÛlÖw¼ë}®«¨‘ž/³Ú<¥(ùÌ<ÏuÁ;¬m~HN€ìMãC¹U‰”íjËbÂÑ̶FŠLÈ )$ì>uDÙªt©¹·7ód»2¼ò®×–?Md ¬$O[Ø+-›¯Ü›f—JoÛl”B­ÙJѤm)寫b[ VxåçY&“…ëB„ɸuái¤0Fµ%°Úöfº¨•¯5’S|[¸µ°Ùlb…á¶jÍ` ­4 mzYdÇ<=îþ¾‡H_!“n|›„X¯·iËv®Üª —m6¼J[7f-¼rVd!%:ˆ5€á&l9ðqŠ›üÜ$Á×à\/• ÷èRÉx† Ý Î0·®?sÙ°rXŠÆÊ3ŸZ'£”@b¸¾ô1[d|æUeÂ<ÿÄóái“I Ç÷ç϶©Üý[Ù UVUY däñýn)ãùœâûP0‚æzœ%¬»`CL‰/Òœqïï rà¯ß{ŽLÜæ' ()Xìq×.MúdÊ|)«mž½ØL²•·b€ùÃæG¾n°Zðôû«Âéem°’€áÉÓ‰Q%ËV´Å”Â0´Ò+´¦j”@‹œ+·âY#eRëxk$žfE†1’è˰‡ÕHÈJê¥E¼­i¼“<6­v@Û Œ©ÊæÆa[Ê y²¹Y‰¥„ªÖe1âÌô½[Û¬º[÷©uL«¥Éè6ð0] sI‘ż% ‰ß0az-~ûóŸÿÜ!‹Eõ2ÊÑ6w€‘ÛT%Õ6Y2Q3ŒT«sŠså@/d­• Ø Û°ôÊÙb‰‘¶’UníùJ`«1Ô&0ÂéÒÜ&¿>BYåö³ó&>¿o CbY‰õåßñw9¾<7 %àÄsK'›Ø[K©°aˆ+¬ÊªÐÙeÄK1눜,e·úŠ ÀS¶¨d‚u¤•ûëR‹N‘ÃLÔÂ9¼nc"µÞîï6Uä hÝÖ$ý`³õ!±õ·¬ æÝÈÙ:s`÷c"%¼¢ñ°å®é¶d²¢Á¬”Ö”#1‚I1>€d¥ÄïC}šaŸ_瀰{îß–ûn4yJ³)q®Ìa![à1SÂŽ¶,ÀAl6J¤mäôûãOª ¬E¶ ZeÕvᘘ eï^Û£¡¤Ó†”ÆR[ù~ÞØ iš–ÒË_÷WD“IM [¼FÞdþ0¥¬€™Ð4a¶ilÇ7¶Ô c(‘lùH)ûJ‘¢Ág›¾ÕHdé1‚$înfJ±¦Ó‰ åN§ñÍœ†iàæ$àÓÈZtÞ}¿!éUÕ·Ž•ä /åA'&²‚}oëb+†™Äðl¼ZÀ¢FÄÈøÖø+GþPvçšR†éÅ”™(X¥¶½ ? ²¾¬º7åHúøtmñ4Üù7(W5VNTÜ@0 _ÊR D ¨ªÖ†$n‹±eØQec” iæYÏù­*+eغðbe¥ö¸|}lVt ÖRVSÕÅ^‚&¤Ȥ`1ÐVǬæDÆÀ” ém…Uk%“*kÛ1Ûv ¶x%‘,çSÅ8#±ˆÔŽ^Pf+³ª¶seˆÂd> «…sËœC!ß„§ýSžC%øköëbÝ3s¸ë ‘w¢ÏÏÔj­¹Y¿#œr[yZEµ¯2^_W×EùÁFfë8ýËÁŽÓš~}l•Õ– e7l1CU누k É 3§™RÄ“i9>1 AOÄzÞ¼û-ÃßV´H cëøÃYuºzј¶r2zÑ´xX4Òg3xöY£©Öš^ªh;ÃΫC [‹Ê;ÞäxbÑ„ô ,‹Qh•µÅÃô@ÙJnõ篈ðõ"ƒ+$Ó×*Ê–Ò+mãYÉ~ /E/eÍ nK Ô]/çê FU…·ÿ€@´­…l7l[ ^Ù^ƒ3$ …c7¦/²ûñq ™¬iÙ9yF6s¤h€–eKƯÅ-ú¸aU_¶@…>³ÞCÛF’…{kº±K¯ëÓZöµ5ƒÁ\ ²[ÅÀ¢Öj ä Ð3´½§9©Zw¨\Ì“F˜³YLÛVæ‘)ù§¯5 7‚¶R © ­ðéô U‘ç0÷8¶x>+^­ßYÁ¶BŸe¤_ý{' ÊÊkj›Id¸©2!ð€ªŠ‡hD¶­ <¥«vÇBvY›­¯–•LVä`[kÀï…½9Z0GLÚJâzT†Í\6³©b*ɰÚ&±J囼ßab(m9HYo3×CÐm”mÅl› [ž=5)å.£<‡ôøÚY3qEd•SVRÊŠÏMJ­Ð"0%+ eü^'ÌZ7dJä~d8)’Ò:¬/ó%ÚÕFNÉdžLDÛÌa>áeÕr(•kþÓçlm’•cÂõÊ<1&ÀÀ;©^•L<“‚@$¶Ìj€øÄµpŸ²aY½„ÛKS-Z!KÁ¥`ÁÄŸ! ´V˜ìF–yY©4µË“à ñ}Hsjš¬è 4k1‡€`Aÿc» i$Ù<•L ȦÔzOйoa)LGÈÄZ(;…*(­}{†#7mþ}Ù•å3™*š¶Ö ‘š’õW§€ÁªÂÓÀ4¢kTè?ŒÆcúÂ)1²E38…,2+n3¤¯V™gV mã¿”0}èM™szL·ŠÌÜ: àÆ³Ž¶‰“­W2$O`/?}G&³ âJ´ ¡ìyÅ#ºú²ÜøàÊm1øRUÅòÑ”†•­h[•­ßcœÈ·q\Éyš„”É5U%…·f¥ Lc+(…më9Õ÷·‚<˪Å(×”_×ÚfË C_-u”bnMÖ6Õo)ãiv 1% {?¯Ÿ‘¼®Ö”² 2z‘CÊŽIÖHbÖLªÍǹO™¸û!èV»„ðn¬òÆØ0 E4 m7'à ػFµ®ªÂVñŠesÞ Õò\J‰-s![ ¤‘<_5LÚRöBâû£×iüý¤ ).A‰[+,ÂV˜²IdÃ@!HSÂV¸G_­Ḇþ^k˜Ö0ßÌç]m«†•òL-Âx…¶î¡¶¼‘›Z1^kØ$Ê1n PÂo›¿v¢5? kHzYåJÎÁ.Ó¦w*Ùbþ•dŠŒgž²±ÕÚæ@ X¥Ü¬ic«¶‘hFšzYÉ6Œ± VØÖ<ò‘ê*¬ÈœX ¤å0 „@ØZeèÛ´cæ,KŒ©Î*† Ô–Ê*gÙHÙ” p:Ý^d…­BØ*–”`¤àw0ó`Dú¶1†LÜä9k1d-lEŒè‘…’íÛ‚ø·¿üå/LcxXj 9ÖÉ–Wmà:Ù"·#©­åeÕ…[bšúÒã‘ô4e‘€ÈjžJ6¡T|UÄ|˜x¿QŠR4ŽÙ¡4¶¥|Çeb[÷”¶ LÙHyn›`©`sâÃúæP—|àâuÃØžÃÜ/ ã)¤¤ $™Xñ¥Á–Þ›D¯¶r˜Þ:Ïô‰¥Èà­|#© Ó4†âô¾ŸÌ­d}ó³òàˆiüh±í§»-8v7ûöú8>o BA#Â5ªÖÊJUd«i)[Y¯AV¿7#ý¦Bà&`T@ΓƖ9O°U Àxå:ÅÎÒymidY‰d%R"&R9ù÷ç=ä²B!DšG ¤»…Uµ¬œélUÑÓT.t@zζÖÀív.Ä–ÒV!leÛ$xQSµ@]–Í$™µmþĶ•×kWB©iÃÔ(OXÊ*Ó09ô˜ê‚0õ‚1Bm3ÄÀŽ`! ì–º¨¶§òÆšò³•¬$–"¶€¡·îº*Ìj²R›¶‘Øö¬•clÉJU¬óQ+0dñm•fÍ ¤rJd'"kƪ¤( #ò4•*ÛÞv¸ßêÛ ²E&ßÝ/¯b>ªš¼Üâ­RoÔ.*7z1ÿ¶”€îÄÍa²ñ‰‘ÉlÉdkÔ¹´–õ¬u œiî+Ϫ ü6m›?%=€[µÍ¹ªz9iæñµV©0Ã($½lQ¶’°¬séî©u´†Ç éuÇSÒ(l<²A hâ1@‘a%Gˆ±Ò[k]-¼ÐW–ÞZÃÊ[27ïO½Ô¾M+Oc¼²È®µË0$©VàÇÀ³zIx&ñ 1°èzÕÖq|Llûó3%ÒÖºùÕžùî„‘jEš©°-ÐuIá›ÄZ¶Â µ ¦áP¹‘A&}­s¨Ý˜}äá^ŒV$«ÍÀœ€mGËŸOA)˯üG–FVa¼ÒT´ÍÜV_Mm ”æpÃË ¼vU%€ Y ¦uÁZË&Ïpƒa²%L~g9WªÀ‹&éìd˜ª¬”­øŽ¡R õÛ?þñ6%P¦¹²£s/Ö>!PzóRÎ…õ˜Ä({¥`åÀÀªG‹Áÿx6ÈzYHÇî0ÌÛZuì:F¨‚{™0­7y|)ÞŠßeI%3^µüÙÛÂVA°N#[ÈözÙÂY5² ¤ªºë(`Q6ö3ÏÇJL†‡™µ­1´Àøòݧˆ¾›é\ÊÄ5•²e¨*çÜÒ´6UkítomYfV”+—òè9wÉ€ Ƹ´p>H‘†C 2¾æ¿1òŒ‡‰KebxŒ¶9ìÓn@Œq]46p2k¶@CƧ´v-Ü’uvsöhœˆF6Zæ¦Rõ‡?üaVÈôHåÜ`AÙ<œ‘d i6ƶ‰Æåh=1‡|¤TImæf³jÑ0Vz¬fp®$Vú®°Zk…Lb®ßçÓ“I]XÙrvj†3õ²i~æxb2‘UµÄ:²;Llu V%14¥µ—H}³å©cO„¦NË;*·Ö”ÀY²EVÎ ÇØØÆÀem›#Wøëõ»É“Mc†Â{…ÙÔSkH$FÇ•g÷.ɲ šê^À¹Ã^*)Cæc…ÇÙ*™-RPv“@:†@R&‹„‘0C [‘Kñ±•²¦¬ÖV#«ÍV‰BLÊU•í+ÕËc[SzbÛcw g%Â$¶x˜^\úÜ\’OÙÚJqÀÛ ì™Â²‰VR@&¦UB©5²©nF,ö¸³²æo­c…mµ•²Ù–²Ej|/àm«­iY¸-ÍÀA¤•X­HSßNd=7æ©ÄMòÃ$«oÅùgÎñké8]ìªâ«z3Ò¦"–ªÐYL¸ÔŽàž›“X/…‹SUƒ({çY{)Y™­ì“µÂõ ›ƒRI>V<’O%ÆÍÐVŠØ1ઠ­Kúɤà•dŽQȶ/SšZà+¡Dbˆ›òð10¥ÖVµÈ]…”-ªj…RºÌ_¶H)+¥¶‡³ÍY*e$L&âi ‰t!j{ÒéµcÞ5â}ÞzÒ²ReëÎÄ_À&É Ã ¬#Ãm¥6v÷sÛžg§¤lsV²G9ç†Á™o6í" :”lÀÚ„ù3Ä€gJ—9çu! ¬¯U˜'+«”ÖYÙjÔû¦ª)á|š¤¾È â¢aˆs•÷…!°ýJÎ?m›“HOK¥qOI&€dùïÔÚ¦W’’¸S;©¨äøÞp'륰>ÈV$@F4°UH ¶áZÃÊ­ÕZßP«ä6ÿõ5N€©‹·À4¹Uä@ßš Ψuþ®ˆ¬ÜÆþóŸ>ƒJÜžÕ¶lgQÛVªà t(VmiÌó¼N;²žHØšÛÇèþ£'âg×§’Lpã‰$°?Žét׿ׇ®‘”R”MÕ9T&ñÖš®ÀGè]òÙgÒevKõªËô9HíeH¦D¹v‚­Á0×érVÞl¶äYª•§Pn¥·ò”ˆô1°p ¼•²ƒC š=hÌ4™s®Ü6=±h‹I`à¶­AÌ“€OŒl'ÅŸ‚û©t3A¤©œ YùÑ]Aµ0>OŒrz] ©®š`²ÈfèP­”Ó˜Öéž8^ù08V…¶ºïBµóÐ(§oB)[Y ÓV˜²'RÓn ¦© —¹-,¤Æüï–‰ Gš*lËJàK! `ÓR*iK [m+lm’Ê¥ÚVKP°ýÂ3¿¬-qQ ¤m)Yctÿ°kÛ)á‰)eëêܧ{ö ú"­©•'A-²²=¿bj#ÍH"iض~4É„[‰óªMdÓ¼‚nÃ͈€ùúú³5¨ô?ÞLÃM Å&QU-RÓ0 LP0—õã\_bÛ†im†loŸÏ·¶B3Г1„ó´%³ÚZñÌaJ²ôx†S6|úÈšÖŽƒÁV‹”õ;_3T(lÍOï–l;)à1#Õ ”Ûväb$‡ÈI^‘R¬¶VzÊw0Ybë@‡BVnó‰I`}ƒ,$`ÍVm `ÔÆKÓ«¼.fÃ[«Ê¶j3LjÀF­ãª*Döfн ·b ÀGG×E_¶Ts*qù<ɼRp¥”‹?þñ éW¾yTyÄ C‰g¢œ­òª0]”íõû¼pßI(M®<·fè•Ë ¤«òZTÒqú¿€9Tž•@¹Ô² rKÐÇĤ2 ‚ ;Ýü+´-l…Ùˆ­j›Ü æ+üü“€Ò`ª`ìnO¡­UUåû·çÄn¾’æô˜*ÌPŠm­½ ĶÝdƒþô/0 qóg$ ÁµRžxÌç ÷˜¢Ž+™l#¹L—Ì )ÅÜ¿ 0p[§¶&žP@v¼*zåÇ’ÓµÓšâKaø$Îðµm0ëÕ oÈúÐ9»ø#óo†|¬ZTÈ!’4MÕH[¹eE ¨JÖ¹í;¡.]¬%= Ö´[eË0U¶4}~UqHlN-daŸ²ºXɧÁ÷3–ƒ-óü‡yÊf˜C³IÚÒËžâçAÓu”ÊÇÀ˜°ƒdK©ÄÚaaü¦O  j×v…j—Z Ÿ%ef3${Mà|€Yd·—?Rx…öE‘©¥ Ád¢¤wFÓ$¥0Í“-ü@ÙÍlYÌHÛÜg¶ilEW p¨»Á¶É¬pkÏѡʚ c[‰¾ ªb˜ PN¯0ÏÌ+o€øJdy*TeíUÏÁêõpoîD‰÷9OL¶x[«`ˆÏ6†F9[¡K)+ÞŠT« q÷ ä†LFY˜²/wþÙ¹¤jãûôÕ(C©^hG,{g<—€lT€XVT¥WY[ÊZ'°JcÈØfÒš?  ²›ìø+ÿ:ûLLϪ`$¼9+GÒÀ^a¯ôù4êd­}Û˜:©´m¦‚,¤¾ðók£RtB²VÛ0ÏʽÆò#Ù'–F4@}méyÖȶÁâÛÖnG T[ÊZ—HJ¸kUÜ`µnmb GXß­ ¥XÉŠ¬kÑl­dÄE‚ôÕÆL¹_h”hDÖ”ÆË ã+”j$U˜F²3êb«ŠÒ;íGLŒ¬ŠFxx_dˆIü¥?Ÿ"¤9eUImà,e ÒÌ$`$zÑWpÝ ©ª—á|ަƒ›P"ÅĪJ`ò 㧉·½Âóç7c»k„…£v‡þšÐ¶ÚIéȤó2ÉÚ‚RPZSFÒ$sœKc%ë@Unðàåî„LR¬ˆÅøŽ°‘ÂfÖŽF(±åC © i˜d‹ñzüë_ÿÒ£–À'hV{ç:?àܬ‚@ÇlkÁJ$ËÞYnªðùó©¦Z[˜Ææ_ }J|3´¥±í¥Rå0ZÈÖÂ_ô{XPvK4®Î›À°Ö îÊɬ›6КF!·é_1,Õ ×ìuH¼i*69Þ=`´`²lÕšY ²µF‚à8Þ Ä'àhÔxRmÉÔÁ@š"1@Vpâ=5Uâ½:[YæÂÂ)4õ_îœWäÉ¶èø m½ä=}2 Ù¨FYuKô ‘õ6ù¼ððjÍ 6¬©ræ ­ 8 ©zo­ñ 0žÛ¬”¶Ö°ŽÃ³êP{»šJ¶IrhŒíkb+˜µ†ML)XY“Á@7 ‹oéù§Ô¦µU•aµVc˜Ó‘+ÔCÙx“U…ļ1þ4»!ëŸ[sÑ÷g¢ÙZM‚Ę\èÛœbzú•3Ä‹lÕvox eM7a'Ýøøá޼WáÛF#žýÔk>Y)qµ †ÏÙ¹¼3¶ÜxÚÚš¸B©x+Ò=…ó§°Õw”9kÄÜä~Ná ëmTU@¢1˜P–5I¶î‡¬FÝ9ew‚ÇXo[¡D IÓ –F–‰5† Û–ÅX¥Ì dAãtR¢¦TV2«é¥8¨’âfÛ[O“ƒ <þùï—@VnISjbÛfèhp‚œ{@j›GUâ:®þüqœE7^?XHã1¼ˆ²®¥d)+±J¥ëÈ)ˆ_gãuÌн«BV"¥i¸™À€Acà=Rk>žßƫʊ¡I_ ½-R•¬¬Ê½µ ¬‚F9\Ǫ0J˜¨â`+xÛÂVUB '³Î9²UGxÝ(ù¨uK0`B%H[ÊlV­ d˜Ê­Æ.ÇT¶R‚‰­¾4 ß@’Å”UNKá·jM)j Ì'œUÃH5çÊMb6JdŸsbdâ܈m…í9À÷w J̺ Ih¥÷{ž q%²;;¬ŠIæ £ªºÝ>7†$dž‚ì‡þŸ»®œUaÄÊ2‡L¥…,[Û:v|šBꜟyôŽ0½’n軯ÁºÉV&KéE)xâm;r£ZëÅS—ÄdÚaš ÈêZþ²W^í)¸ß›|ˆ¬x`YLÏE—ÈæYåôØ:‘“øýã~Š³Ì¼ámû¯ç›ŸC¡¼FLÔZ)‘V¡Vôd•µhŒíg' Û”e3÷zôí×´¥&c…Gví i[_ÎB‹õ•UÛZëÄpSQІ‘‚­¶"lHŒ ÏG‹š F»ç£½3F¶f.å°Žðq„la2[| à¼.ÍØ]~}»„4Ö™óÄVþ–jx…ÂVTÒÕQÚÖ‘rÃl…ɺm…RJbDåjñÖni˜~¢#a>Â)l¹‘9c¸aVÁÊuY»æ–~L>ísà©—¿¥õmÉ™§-ŸÞpW¤ÊbXHÁ6¦-e!4ŒTsH«.5‚ úL¾Ä¹½%šÒo›ÉÍŸIâ=>|¶1¥[Hi¤Ä6á!óÏ°î½ ô•ð¡­j­µ`˜+ñS`‡rž&ÍZ/»ò&©i]òW¥]xU$½G™?æ·ßÿ•i«GŠ^5Åj2UIœ#:I ,´ÑX9ÒžPÒXd]´7Ik#KS—¶ÓgÒšg-"M‘¶‡Ì¡*ÛJ;¦7 HL&ð¦5$ò_e|[x€¦KPë ¬D>€cÊp«-=%«Rx ¥©`¤`b»÷²Jbèû P²*$LfUˆQ¢)O¤°%Á‚C&­Jz1Ò¼ú4˜d3"ñ…F@‚f€#Cçåæòõ¢’ÁxѨ€ªjYå7nÓ w´j­HA–¾Z²¹I &2)²^]Û²L:N×bT2ó+Ä÷þ(Éöö<‹”øPÊÚ’Á‚3¦, Í à›Þ.í$‚•`Tõ‰CÂiøç€¬—Ö²LZøHÎV!¥…rA“ Æ‹¶@3ÞÂ#º£*‰Wi[;½[WjµíMè­zõ)“mÈ^›Yñ]Kk À¶Ï& Ì:RòHúJ*ÏMjšx‚“ZÛ’]ú×Ó”Jz+8O¦WŸhSù)‹× ðÄXkŠÁ›ß)zÓrãß”¢i›3Œlþ¬ åýX’âÙ©;\yn{åd…Tb>j’àWÞÈ;ÈgI`UhlbUkŠÁÓÉжVô¡û4¸˜¦ÈC¹Žï•ŒÛZ×N0[S%îNšÄH ¬žlzd]¥'›’'“º™¨Pkz` làÌÙ •{Cx24¹5-^tЬ&ÏÖô²MB_­µÚò!¶eئ ãË&°*¯µë¥‡­FM "++Û 9ÀVd”O¤’7›mk%».ÊNGÀ¼ÙØØ ¬­b‘[%”07AC\PÚÆäéIÑ÷€T1‡{p”{^dJèyÒãeéã~ÿ!‰7d]Þ.š&aÅ97bY[&fÈDJ9YÇA Ê70¹Qr怡·ö·€Ê6AM»–²V¶dÖSp£mþc˜|ð©–f³Á¯Ûl‰“y[ŒDãrd»ù&gîÔøæ”UÕÕ…sSˤs{4‘ÿ†a ¶*I†ÉÊ*¦„ P‰1`þbæpg!³= nàÈ M‚Nc»ŽM21‡ó¿¤e:(s5;I¾È®’& Ö¥š–²4œÝ]bnÆ¢!æàÆñ¾uD* áil€YPµ“ ·Õ¨-`f&ÍSÇw›¬ûJ#ËÍŠÌ oKiíZa«^"C+A·ŠL£v×%ÕÇÆ}:>±’ÆÐEäÐjÛÙY¥ŒÙØÀ©¹ÇLCVI ÔÆè·âüÒPÖýÓhŠ©T»©liøTbM‰ŠÈVLžÜf/¾E¿ž8ÆY[±¦VVmÝ«•-U)7¡ ìcOP @ÂÀºð!¶%ž?¦àùs°õzûè’yŽkÛÒ0´vu'V_/‰­°¬ÀoÅí܄­o†"Ûd1&!ˆ!³…V°-<÷ët¬~ûûßÿ.×į¤ÒH¡¬€‘‹^#Ÿc+¶‰·÷m4ëL”1­ûXæI¦u†VÌbòTXªl49T[_d[|O÷ÿ躃%Érb ËÙÂ{b3O,±ûI¦·¨áÆB¸<<eó¯Ðª½U¾¬Ô£¾¬(a|¶|œÑ?GÓWèë‘Ð47J2«vøÊë’¡¬-½Ân ˆ\ å;ƒìf ©Ö °ÂX{õÉ`†õd­ñHÁM„¥Ä°Úù…Ÿ·ŸƒÀ[—˜žsó`nŸ³4ƒ.#Ã}üœ¢¬•Ðë"‹±"vê=Ž:PX±ZÆ*dM(«ªH©VлC€LÐ÷ªãe™Çž²òky.³h*¤9äøÜ ¬Êö½¥ãó•kÍÖüe`µVV9àû¾ž¦F4fH¯£lÝ‘ž,ÏF…Éàla2$¥I@Mc>Œo@*œ€çIÕ7@ã8®š@m… lE Û6ížB·Á‡Æúú8+ú€P…¡TEܽT›ŒƒHfA)R°lb ”,“£¾ÁÓ[i´«oµ|[…i"•¦åLi [Es†­Rõ‚e‹R<‹Æ ÈâÑ—L-¤ÚæFÌТ“æiK©©µÀp“U(T Û&¡‘í__^–!^!•>+ ò+õ”€ò®¢‘¬ž²IÔb:ÒV 7Œ.Rp…AQ;˜¾C¹µ‚•uéŠ`Y¼ °5‰*±H†¢FÍ`PH¬)³lä#šÁãØ„w¢³$È"•#‹ð»N‰L_¡mqúݨW˜›,}šL¤ ÙéÈŒŠÿ´ª¸á‰Ë40}â¥â¥t;µ‹ucLÈc ’^”u“bÎ]µ*Va%¶]5 ¬¼Áô]#@4 ÀáŸ_ÂšŠ¥îd}|ðQ#@/kúUÉ <Ã9ô.)¡+¬*Øý¨Šé7 côW6Jl º%Zá¶[‰³RBà,͆ɺ²@£ë<ÒÖ`•Ä[ëË_v$ çãõ½¢ ­‘À¬F >·áçµíüñ°U ÊÙŠle[Y¸[‘Z¸7¼'ãE låYYç!¥a¬x«îVáé`œ—y¶²ª\ØJÑÛÒ'F¾Ù4 ™òèý{9¡˜«)ÆŠi Ô¾±à¢fVJ«rÓdU¹w€i%«°“¤¯i)3˜'Yžá1þµÍÜ à9A|]¤4ëàV‚n ±Í@P; '¤œ¬5“­ëK¯ï:œÞ×ÜßáI½‚® I“%°Õ«FÈÂ?2lkà™C)çƒT®‘BX¼MfX—¾•ª¥¬„˜o›'+ ·%òHoötú&¸ÚŽ·=eß(Ûœ¥¬Û$Î%È7•1:@\#Œª az©’^Ðàó”r¢qr£ÃK)DrÈßš[½¼E@µÌ)1£#Ý+±ÍÜšÀšÉÕþZÎH¯;^hÑ$k•”}utF©²•l0€!±*?3€&4|Ã$° 6%¶ ùÛÒ‹_s?¯¼làH¯¸ŽÖxëêà}TkdxÙp›‡U¤±F­@bª²%ƒ­aõ"Ó¨U¶W£9W‚ª’ ¼«K¶åfe(èEÓ*!°btqŸèÑT’-½èaeF¦o`þ²•`øÈÚ ÷p;ŸÖjEþ:ªªcbÛ4ÄH ÀnBŒªxbX6Fý‰·Z]T5U6¡­ñš0Y_A Õ ¤1ªê8Ë ˜$ݕȖê€Öæl•U‚LF MÛ<[‰a¶²Öm+± ñ¬ôB*¬p¼SÛ6§ßÆòLcuÌf£IÌÏJÌÓI‘§ÍmÄ$l5CÅÓA¼U¨á­ÄüYi* ÷u¥?¬®ÁqØ1«µvùR°õG!ó—16û©¼©Ì€,ð4R~¥[ Àpd»¨ÜJ)DZûEÐYèmÙ¬;Z…ôH²wH[á¤d4MÌ’|õ@IDAT‹“a<…Zã­ÂcU‚¤¡Tk+‹—Å$Xw[å¶z[za`|“'È­›yÖ&À;]$i5 øGàY™ÐWTŽ©€ÔÈxkU”Æó"¥D¶å´¿%Ä]KV°ØÿœAÖýã !a¶ÊfÞS¾Þgž¿þõ¯ÞØñï‡(~z)åÝa³%¶Òð;3Ll 冤ÔÚjH©3Óý`šªjQI£Öît¶jmÿùÏòñE”¸k×Bð´•%ƒ º“Qk>VAfµ%3³BÛZH˜†!HŒÇX¾!«ã§ìjÊVžþ½¥UÝ•Zz$`X!ýÊ)+)•îV;Bµ™XÕÎvó7Czž" †>7¶M…qÏ]©ÂªdUY› È&ƒ1<Ýy3Ü&gQ"U¶¦ükÔxV%UIQb(}åMèAssK”•4R-êÒGXíÞºò¬“‰-¥ùù×¥²š­lccd?¶‘Þ锤§1L]ôõeÒÕÑç£ÄœØ?èøI O˜az«-R–¼.΋«’a²:¦ŒGÚµÓWyGèÚ™äƒ+„1yÚÝ’Ò¶€'N©ÊI!1’’ r3x§ÆtKÄRž¯¬³›–¾#Ä®ÎK˰y0]u…º×¨yh¸a¶ “ÀVáoüñGRsì¡RHwSMl+`‘c.ÛZ¥ÑØ6\|$ ¸z«9ºóÁü;˜Žp}k: l€4µ†Ö¢$ ¥¤53ã*hZ›Oó:Çç¶ OßÙ[߬.‚ƒœÎVÛ¡0ÍÌ™Ì6¾¾Í“sXašÜz È¢ñøxá¶øÆ`lVE‚ZÃJ2|J¤• øÿé?¾ùóŸK² ¯`è6ð:Ö+,eT)À´‡€>YUÞ%Û”+Ÿ¬F²"ŒB¸mÎ<¡5%•‰-}$€IãÎa¿™J­”—œ!¥­P¶â«Í°5q©W—M‰Ñ”ç¶Î^ …BJSaÜL©¶²_>h8ÍÜ¡ö-)E¯œ'¥&Þ²¶V)@áw%ØØ4mMãóa«jwÇS6¤-U`à9HŒ9#$Y+=g©þ›'ÌÅk›Y;Û+93ä€ç·…‹4YµêÒ­î醑Õ]÷4sŒl$±¸=?=YGLþÊöÂV›‡-‡kÓ2!“2§*³I%³ì¡© ¨Å˜Ó¶ )9¤Ï„fìRe[1ªü²nekÛØº`h˜hlžªØÏÎnI!²Ù`¤·×0B!±,Œ—%ÊÛâÙhTÙ ÓÙ›3Ï1i¼ÜöN6g&EΙǸÃ~½ÓKiåf!Fr0¢Ë¯YЋïîó¡ Î_vë@3Ûvùéá¶øRx&55^Ù¶N!úMÅ£lŒ²µ[‰1ÊöÖÓõ^5wŠªb¬fÀ¸^…:òq] Ô¨ÇäŒJ(l»R&”¶Jª"+r°ŠÄÀZ÷r*ÁÀ²Ú žx&RȆL)ëkÇÀ~Û«êU2AzÄ<ùôv±â,9=ÌAª‡‚ÑNªîVúd 3½…R `+dÅ@¸-[æJÛSðý¤Hñw:@Ч-ÐÙ‘Þ b&1 I¦DŠXŠÞJ†‡uiæ ™5 K‰ [s˜`ø¤÷’h-‹)U6Á¬ÚJ-JáE… ¹ƒðo@,zÊÎU­ÕÖó°N = ¤§ßÀVä°¬è-…°.x³…­xãY{.RBëÏ¿€mD+6œKëÛ8|Z=ŸØz´&È Þ4ôÌÓho )­ ?ñ`dÓjWn›O³eò®øJ¡P»V½6*“·ªí¹ŒïÛ¯Dy³UE/(mcZ‘Ä7ùxµÖúJÙæ¬¨„À«µ–Ò±gxªM¦°ŽÜŠ.ŠLÔZeÃôxåÌ‘)ùÈJõgk¤(‹§—¢GâæÏ®¶&¤¬D)¤€ëgò:À‚†áÌ#'¶ιKбmYZXxJ2öVûɺ üëIƒÉ ‘`…M.› ¾•@áùÈÞ_J ç|8÷8úF³”"%¾f{ý›¤Ð]*œ9,¹Ñt´€T%d )•þ|¾;( i6sº1“ÀVzUÝ6B¡‹T¶^!|þ˜ñX šdJ`k§Èß¶Úœad>d€UF*L™9d¸Ĩ"CNŒt[U^•λk7 [G¶°ª©UʉSQvgAÒèÕÊc"uŒñ8 µæ™æÎr-ÄxY!{¬¬rsR€¸#À™`Ö4OnL¬ ‰¤iž+…™† ±U¬„FtñVb_t 󸢽t·å[ (cö]`%ø4. $™Õ6¥uA,Rf2Œo µ)­ñ•à °W˜0+2«@9mÃÓ,…éÈômSs%d„„ ܘÂHk|Í)0™€_Ðö£ø~NskN)[†¬œÅÊ HÓAšÍ;f$bUD–r­ñcÞîøR”lë9À?+ {îÍ1ž’R~Ïîý1mV©ü¥K˜Ó¼³áu©{%jkqNõ}Ÿ¥tô+&%’ PwC" iíáÒX׎FtÉ­;fí¬ ð|:i>#0ðJ(ƒ—¥É x•“Z+aÒeÞÏ÷† @àÚn²HJc+ wüx§«vE¦j°F"žœmí®oØVtLïÀd†ÑBôZê²”*¸¸Vš ©æ· i$PJ6‡V[3‹‘@ ½¾&ÆkÛ\ F#‹t0†!,dëÎP`¬g ïH Ôbºóú’±B꫊¡¦¿ýío³AU€¥`1k@à‹Û/}þS*_Ljo¦ÎÓc#µÀŸ;¸?ð}6Œ¡i­µªzã]ÞªµÔÖ@MÅJÐ ˜”ÚÂy3º5[€¸.µ¾ªÏmÌm@v“;È:òéê‘@¯8ñ;‰¾÷€IžZÓ“u-• m7Uß5Hñ|”tŸÍ 0‡Ì³îo•¬ ~ƒ˜SŠ¿ãCâ[Y‘I‰pÈִƼëªVÊEúë}ÌWo[@j†°£!½„ÖÆë7¼jUáÓoŰçüßïwVX_€­_"Ýj·Qkâ kDÌ C#Ò°Å\ãÏR %}g7ÞV”Ý–LpÁ-¬;E€ BÛ1Høõ믢ùPn<EPI¯ÇivŸþíöi‡Qå¼ýJÍ$¦Âº ›0F´Øn éŠlA…m•Û"{¾e 3ÛU£&ì· [}Ê”÷¸1>;|ÈÔ«Z+f‘§ñµï<ÍI¿ d‚¬©•ÛØ‹„¬[càe)Î-fâõÂ÷"Q [!+l3á`Û`ÈÞÞl“ÊÛ(eß«Áè5² dÌœ-A}eÉĬïÈ0¶¢¦ë¢$ÞæVE¬ÐS[£ 3\;%xà+o$+M<X4¼mÑÙ€YÁ‚¬TΘL¦qo>5x‚Spr¥V¶§¼r…BªSÐ3„³½gI€°På,Ócܼ·:7äúÊv‡²ÿ_TRÇ3Ù70J—Œ›yv¥ºèŽ‘” ‘Ý6«5²ÅX×B6R„g2P¶•Ï-úüfcÓn`UHsH#Œ’Ý•,Þ¨J:F±¥·†­ÂéöõÈG&Cå@å@S)¡‰‡‘d Ï@wR˜Ï”ü b2±Æt[µNÀ¡;lâÎBÆ–¦Fp‚¶FUÿ4¼UU Ï #”m³Â(;…_ò4 Ö´Uu–•»{ü^àÆ£!.( ZÌ¥0ïªuÝñ€Þã3†ÕHûå­:J˜Ð ˜žª”7R†˜Î˜!=±¨ e™»ïW…ºþ $×{£™täÎNä 4ÍËÀ&¨3Q‚¿}ÏÝùwf$eF*ÏÁ€ld&ÒÚc#4Ólp[3 …Ö¥€˜­ i« PE pÆ4¡-O|)Û°uV1ªŠ¶ŒC>–OX¡^"1†Òª EÔºÁÖ±¤#Ä´vö&´zš”ù0”Efâ=óÚI)4˜FR]¥¨‹UÊ–ˆ tX9ÞZ¯^¾.9Tnmàü9UIæz ÉP ÛLâ+WÒT4”¶.¡_ì`Œ©TWn]”êøi”PÆH¶É¤Fù<1ºÛM(Kã¹'“*Ä‹ÝaÛ •„Õv|žš²T#2ÀÊ­ ˆLÓqöIoÚ¾€(e" ûj¤]c²V'2 C%¡½h$šÚ5I$Ȭ0RY!•[³Õ× _ª’1džìíyšv"Á°ùj $k‹TQ:[ @á/çð IO,2¤ ²Æ®ÑÄdb[#M¶1A/Yb“X»x©é“`¬i`Á\ÏЉ¬B ss£Ç'þTÞ$Íܪ#`Ì#òù*Ó$Î0œ­¬ªá&@fòv×ÈV0’PRFÉ p.aëfÒ“yd†©-& ¯\¶­Ê Ê7µ€&‡Z#m‘J£FÓa çà‰¼NÞg|SY•XFž3ßP.6@ŸÐž,eXmk­D÷ên P®]³TŸa[M ÀÀœiîGäóß²ã )Þj2à´ü¾T¶¯0¾­Õ6œ9è,@Ùd0F_ÛfpLĶ>×fàÀéºdÖ¦á€RT¸§I\G%È=,n˜b‚ÿ ^!µðë»W#!kEª…k7€,0:Š3â÷e1œ ÐÑòŒyɬ˜ˆ]HX‰ÀˆØåUãõe+0Êm—(¥øŒ§‰¯—kÔ—Æý—ûbÀî¶÷JíJd¥ÞŽù×1C[…=¸µÞØÄ^ $Pj30É-g‚«°Úµ«#¬Ë‰Ë€Œ¦7S;Ók*Œ (Ä'n‹á@ hô6m*bYVÊ›„!€ͳ*Œ”›§ùíïÿ»tjk—BŠ$âk½~­Ág„O“Œ)žƒ¨<¦ö4¢aU^}Jd$`{ Î/ÇÉ´F2¤ÏÖH"ñ˜.(fÃÉAÄ+”òªy°”p‰ªÂÆP%dE|c3iB€8€l¶¶L*/«à**lÝ%Ð;)½1ò,K5ƒ[cdˆ_/ œ _Ê– =`X¹.€m¼µƒ+ÕVN¬ ”Ò¥©jgU.[ (ÁÖcý½·ÌcZc*±Š:vù0'ÖÝ6+`ƒiª ã’‘d¶ÚâeáÚåáw=ío$°2?v÷ãÄ­0*¤!Écˆa|2k ‡Llcô@œÜ÷£7†À'V(ñÆÚîÎilP åÆÏ_ A¤=qVb“¢±^ úîRsÞ ƒ”jJª5ž§µ|ö}»ø¨Ò#¥#Ôf¢P¤'RiŽË=ccëXÓKqÞÌ–RnKP6-9+t-H+OúÖZ'“Ú$Z+L,˜ÃV%~¤Áªl2´ÕB•à`žôp±4 ÔKYi¢y”Çd|¤rÈ #ÕVµhk¥O|Ï'N Y¤µib£=}¤©è„™Ð7U¡—Í„ ².p[Äìì˜H&ÛJðÄ¢r#ÁHY U*A}muq9VXIúx¤ù;½`b•„”5Y­ÁrÓHô¼dÉð²d¶B¹µ*+1·eØJcBYoŽmóT%…á,KüŽÐZ¤Á U¶È&„1‚CK5†¹H–•€°I(¯Íyô@Y€ ó2‘²RÊi¬MB\—™K‰5­„,¼€­ÙnfM‘Ž™ÀÍ‚^wŒ:šOÛ’eÂ'ž@dXyíšGIÂ(Ya A>x¸oØÿP„B3`úÝÆH‰Âugl [båë« i…1¦m«$Fª¬­”ê5Ã̯#¥i;2l‚Ê3ϳI^Ûn²¦¬JÕ+Ûü;îîæ–R#ž4˜#dw¨1ÀVè.*©Ý׿ó%Ð$²aNÇ´õP(9à‹på`«¦ ½ul[9F K…ÕšÇV•5+ì¢”Èø•·•u(C*„ÛÞ«ü9 ¤SX• µ›D–¿ÀHÿ P^Œ°¥%Ä©¾Qb™|1€r‘©²&ã&E&z݉¥œ“ÞK€¼G8S"E穯íás•ÃÜšÿ™ûûÊß}J1‚èž𘲠C†©ï-=‹ñ-•ÞŠÑk'j<‡’²¥1¤=ÀWhmJ£¥jd5F˜¡­UKñ¶]ÈKºèþïÿÛc*Ñ”aµÈ°mÑv£6«]``Lµu´*¬ŠÏ[/ûmò«WíÈ8¸G@aZY)ˆ¬¬dV3[k³å¹’>¿Ÿê×Jí4¹#]`]€m!µÖRd%²gâ{"¸‡‹¯×xAΨ183TîµaåC„(s…­pX ­­H7¹¡¿çÆ+ÔB‰?š¶¥D2÷Ù¡±êˆdˆ$KßË£PìJŒä«êrš'qV §aXkV‘¶ ÚªRÞÚ æ¤É?gzL2Jë4oª[¥WŽ§ì¼Æ0²ûTž 1RÀ] qk­¥D[ïÙñœÒx ÖäÕ’ÑW XwEð¢Z[€•yÈ"•ÃÈÏš ¬0€Eúª^‡H@Êp#ÍÐYx:K°”˜ >î´4Z[e[SV;-sJYwhëÝö:*‡­™¾psÒÛ0DÚælHA#ëMî•«WÎpóÐ/8Àù“ PÒ žu‘‚F”êÁ4"ž!·]l‡Ef‚JšíZž3¦Ñû5¢CÅ ëbå hà:2ÙYÊZ•,l“…msLµr³©ªi³e¿m¥ula¶…mçí õ} kЧ„=8ÊH€I%œ [†øþ!§-ÃVïYL­ñ‚¡À3é­ËFVS…˜nÂM%åkA*“|¬Þ4<’ÀÚûÞe2¬F_­›¦Ya`O¡v 1‚¦à)âko L©‘Àäf•Rˆéõ3,È`²4úº“ùc`LΰHÖVæÕf˜©Ê© øw2 Â„,È8çf˜ßV¶§†ç¶Ù˜÷!½ZIƲŸ•4fNY6[ø[»±Mk¤-p-Ï—›-2Þš•rµµÃT’§ŽñVŒ0’B[k7–9%F¶-ÌGGÛß~ÿýw ÅD˜BØGwÝ3²• ž]+t×Ú(œÞ¶Y•xÒ™W%¥ðý\(Œá¿÷)·ª8¨’uGV)|À³‘ÊP¾Y-=Z)V°@Ú @pë@í›'Ÿ¬ÈhjÇgÈãȬ\TGÓ+¥•†¡’†ÁÔ ÙqlcŒ&ÂÉÌÃÊ×M¹¬CÙâý>êØ‰ºaVJ%^ðÙYNËï‹^¹-Oz…üËò*M`ÑœZ¤G¶m [wµ‘4º3~Þ¨.¡ZØ}n dXmyýá?wŒÄ7^Ý&}­"Ãô·g&0ù’ÉB–sµ³úŸSåê#+_XÄý³cžÌ ¸¹2 æCƒ”òÐ¥êè“2+z÷Ü0Cþë_ÿR«JÐûc±r]Èv[båd°VÄx1Äú½ žH²²ªjgå²Ká Ê–@;«V‘†§r2@;€Ìle¥ðγØ"»Õ”ZÊgKæ8T䀔Öfc tç ¥šXk@Ê©¹­ :1…˜V<¬ÊÖ Ó¤—Â)ÎýoRÕ. uðÄŽL¹r[Ø*d3?¾ßo‰|fBæBjz‹Î<4› V›¦K&£·Ò8ß… ….G­€óϼ{VhK# ˆ†WnB+Fm-`Ô‹^„· » ¯P¹^ÂV£ O)»»J¬JÐÔ” ‡Ûä4Ó÷dÛ 2l­WÃÐÔÓm¸"¤Žp}É”#E ·˜²YÅX@y]Œ¤EÝe‰1L0dSUb•m¤½Qªhð™5E"Ï£vå5ªÞºW‡ñ‘4R%>hÂ$l=wÙæWKFȎ䜘гPXGŒ³Z áxc_íyâ1‘•Àˆ7@WákÜ¿vÕgGSU‚ŒIg±ÙÖ‘ƒàm%MB`OP0ðq¿Úɬ°¬FV)ã*¬"ç‰2(•XSŒ(e¶¦¥É #©D¤˜”%ÐÓѬ €•L_/<@)&ÜÖ*¥oV²°ÏHLµ4îß ˜™LlÂzJYw´³¨ñÀÇW¨;[¤­ržÞÃ<…M…©\÷”¶ ÓkÜI­bž n ;iãeU cÛ97“Ï¿ÐÉÓåž µÈÈåµÉ ß莪¤ï£Êù÷“µÚÌ7œ*x)À®†+APÕ±m%éñHÌ”+…]ÐÞ†ŽY­«7az³ÃRµ{OYx$ån0ÌZÛ å~ùÆÃVÃä-Œt¾}º:) YxëäóF¶%zÀ }³ôªá;{¯{‡ê©5¦ZU@ÖúLp_£¶”z…éÅFjz¶d4Õ¶2Éç”mÓ+1*= eTY çdø0©Ý6½­µ©âBmUmábü~…‘@|Íκ‹z–õ­¶.£¤.­¦’…­ðZ~žl¸• ¦éh˜Þžé|Ä++¥…BÝ{ÍXÙ ÀÏzÁY!PÒ¢HJåµ–ÒZy÷¬D­Fø mÓ7 ^VŠCU˜‰8Íîoágî;y€F;ÏZ–X°Eùc Ûñ¶J"5EZê_¿cHéÓGÀqlÒ7Ÿ˜.ÖÚäJ†a®pâ ¬°XŠ’ÞVè"Ëæ 7[;Hå Ó/%ªj]JÉN*ÅŠ?`õe[6¦Ë¬)^9±Uë×!Û²J„çÈÇ6ÒÊ$gd†d<à[}øBö­íÂëb¥± ²ôfƒ­ª¬RV×hÛS#KC&2Ñ7qn= ¤{PŽ4|µ­=J$·‚FȪU‚ìÑ3I UGU€-½ÁÞÖ ¥Ò7C%;½ÚNtZ~(¼ÄÓ¯o…muáY» £©à‘Þy3ßä¶dø0CÇä´ ÀÅ+æØ0=_Û®W•¨£Bs6Á{ضΛƒVˆ7b¸Ãr¯¨vl=¦žÞVmzÊ­MÕ}z‹:‚r8Îj­¢a8,8À¬tɰ‘&`Ò¨”¥*± L$ æcä ÛyߢO¾ WKÍ>†•ÓU‘…)ÆÿÀ É 6O§¶ÚZ;©vd)ñÁS 2瀉?߬õªÎÜ÷Ó‘>7r¿â¬¶^úÃ̼Ù ‚wÛ΂4Œ©˜ÈºaŒ. ‹¦­î;Ö¯ôÖ3ßýdY)îYmüÝ×핞',º.À<&é’m ÆÐ“y"óÄè…©;sƒÙ®Á”RñZ2-ª ܬdÝ|þPÚÊΪXBeÖ¶(•ÆÚI€¢*>MC¬«U8Ò™ëb+ܸ”? K±bâQáóQ Ð  ôz!…é.Ñóë8L*Cbµf°•ʇ²«Q[;[ÊyfÒ_!åíöùnBÖØHÍ_¹¦§S(•¡uϵÂVÑ7R¬n€R1Bw `%« +«H WhuóJ0ÕÒØZ¥jƒ$ˆÏÊØÈ^58C ”rG°ŠÎh’È bÁ§¹Äóá ébÊSùý0çFcžzÕÃ|AWÎÄšÃÖŒF«mZ|Y­eÍÐX$¶’ @– –Í )Ö"™-Ãø)å¶B-Œ1Fµ^ [¤ÛØÇÊ÷¦GÙE‘ù´ÚZ5ÄëÆØKÕ‰“±²å)+ÌÓ`ÈЖC2«mǧ¤7ž^ ¤”p3v¶[RH¡¤`dn5§,`•ÒÅ„öWq®ÙYÏ ˜‡æøÞo˜n•<ªfƒÛÞŠsR5e™&+¤,L&V¥/Ò¶Z%¥¬ps–­…›W¾{ƒ )ð –’l3銬x‡¦ïÎkÁÏ™OdU9ÃT¹’lkMÆÍš[!›CbX”Åè%8Û&PKù#®ë±=ïñ÷™¾r…‚‘Ïíîœrë·èóµŸl'µ5}2¨J9ÜÒ‹”Z¢ I_ßLð½µvü雊9qŒË$°¥¼–Gc‹ÄPäc¤,^àK”’%h ËŠÈLøcà›ùœn`JGàÏ!“W©*2Yw +y [n¶™½ÛL`“W^ël­§ëýŠ›¡ÚH„ ë¢Ü)˜ËbÆZë „…ø4mU]¿óÀ‘Cªa¬RVçÐãè 9l¥lÔ­ÔîLù}1jAPy«yªJœ„ÓkdÊ~‹¤qõJO ¦_”2?‡f°*|ýk¤)±QßC¼ïUí€j‰ã1ZÙ+1ÆFê}&À#¾¾j#eñ#Õÿ&œ¾ZY [X‹"Ò˜³rŒw  ,ëŒGwÿ¼Ñàº8i½\¾î;©ñ`áj÷ƒFUÑ »Œ3ûo Ä[ŸºäϧŽÁ6†@™[](1o˜¬Ûf‚„S–êI49†L–L [`+¾Rjç¼<­²%R¢.ü³ª„¬Ž”š J%U­WÛÚÁ¬„mü] rO!ÏÄd<½‹×û˜ËnÝxÄõ• +äI €´ < 7«Ž‰ºSH!«²…³¢·Ýš ðº²·E*ÿ¢3öØ:≙䋪ˆõ*ø‹Ž€¦@ª…é[Ð[•ËZɬ1Éø”53FÜ&gÁo 8f‚|—Õšÿ>ü«ÉyYtÀY݆gQH`íY`Ò{%ú¢WØðHÎ0M%º»Iÿ®Hµ¶®½óÒØ*)z¤z¸Q#©þ¹Ÿb)-ž;cOS÷Èòg¨ŠŒ‰‘’5í|2QH $}dCÒÛ‚?7 KPÛg$‡î„ÆÙilE&ˆ=©ª¬ÃªÒ#¬»ŽÝ€,“›óÚÊ’…m¥L5,Õ0™[ óÓçÀ†ê×1är„~Ö×÷Òga$[¨Í$¥®la¤ÕTŸŒÿjpP• ã‘7¢“à9تµRæ£ÆŠÈ€®ÃÚ¶¤mb2‘pé^ « ÌJ¡0ƒ^;EM­B–^ŠæuÆód X`š_;gT•=7…ã‘pƒia»³g¸Ú5b"˜ˆFâ°Úœ½^b7Ïj«"¶­µ-À°‹J†<‡ÿ>ýÛð,+MCêe«PðTÕ¶ú€9šæ‡'b­oŸO/d-J©²UX£”ùÔH¹.†i[1*1ÁÊÕ¾¡)MY«”*kƧÇ3/àluWΟ6Á Kñ‰Ä´Í³5r q“§”Å0·­¦!mÍiÛa`³ÑÉu÷7 Þ [2†Î(¼6dùÐ46Ÿzµí5¶òq )ƇK˜6ž>[}“¸uWzÑ«íD ëN&×ø ¼À#­9o%HŒáoÕ³z@}ÏÕ„‡n[Ç™lÉÔ*Ùk´©Þ16ÉÆÀ° c˰³÷E¯;O-Û¬™çƮٯŸ²¥¬RÄÌ­º›¹¦Rl la#éNO#VAƒ± ²…-^¹yt„lU¦9•ß÷³£™Ð#P®µ*YzÛfˆ”Âð´íòã»Äi+ܶûQU9±,LÙÁëˆÉ_à-“Š|AOP£V_qRHkðµVÎfÕƒ AöÍLæD•˪mBSÁ4µ¨KoB2£NOöbÛ?‡.(%LÓ]¨ÑÄ¥¾èmõ5’ Ï°^¶€µ»’±rÊjËJ­WŸ/2QI·ebÝ 5µ"i3$K‰7ž¨IÓT ï€>€¸Ÿ¼€ÈÖCÑæOÜ3òçU‚½x¶Z0Ô‚‰ å¢#H˜@²ø~ûB ¤¯¤çûÛü"b÷ÀL¶È[rúu¶d¹4´Ú4‘ªŠÙ¸MæÃæ|¦ÃX&ú†é—íd÷)Mÿ^V‚ƨ…m}¥ð ñHþM°æ tËJô"ëÉ|+¥2€§„ÛÂjyRo6òÜõ½¨†é˜ÞòªÊJÅ›c«#°•Ê/êû2ak…LX)Ÿ?@PH1áŒlìº(o +&7%@[¸ ÐxRá®HЬáVxRôx¡ªÂ¶ø ‘uÄ#•[•Re­5?eå²ôøui‘oK ,”ÃÖ\[Ê ³’â/Ûvd²~®ãmW›¿všÞê²µc^ÇõÅsNÏÜ1{š9§oxÙ€  °²ªX½_è¶&Y­mÃk¡°. 9˜³r^ @Üvå¡X؆­4­òD澡ªµ¥]AŸâôsÎ?%ÍøÊep¶§Ó÷E{(Ê™c×Ú ôRï,ÈxU¥¬Jl·…©zviÂÈ"ÒËÉЊlµ›iK Í È^¾ÖËçÖOʘÚÂõÖÅI‘l‘z0"†Œ!Ü Ö.0¥-`]-¼Úå5òÒwdÿ4¦éÈ€F9^¡rµ4úâùÛZÁ6,E@,¤­r2[€LÈSk[ôyKm›Ök™†•Tż+†mU¶Rp£¶…uÇ|4ݹd•#› ¯œCß–OÛzÍÇv-`<™@Ú6nYÁBÖ 8²î]È Ýmn;>±BÀ4$Ãz™ Èî,çU"çùØÂ‘²°ª@d‚øRñMŽ7Àñ½oˆÖEÙd²°˜(!3ß´/mŒ¬@I‡jkµ¥ÁÓ7Ožx$pŸ4"EʰëÕ®KîMSÂDÔlL|…áÓà^O .Km[ªC! èóo¤Uô2$pví0‰mÊ×Ѷ‘Z3\ëÙÆÓh’ܬmñµ0-\–ÍO&¦fkΕ³ÅS"ývÇ¡Ù:,¬ÐJÐg\)[$r°T@9ÞY0ë›>Í;˜ûììÈô”nÉúçªÖF¶%df³eÕV¼H¶)É€<­" ÃÊd+«YM¥PÐ[mÅ[‚§ hªmKÙÖ/XþÊÁ¸kU0ÞÀµk6]|˜ÀgèoÐû>’¬Ð3låÈL¬Â6=Ad%|æ¶zQ6p£"÷¼\¦ID‚šH>ál»||%ô0ÿ&|Œ'Ö™8¥7­¦¶97- ÌŸa‚FjMŸRv©P#sꨦ”Â$†‘)´iÒׂ^¸:-¸„ið4H)[©FͼŽ0@pde…ÏŠÒHA&VHÓ„R.5@c’ÜÔúÓȉ´pϹõ§e%d"ÀPÖ¶1`>RÊ…í†4ƒ-ÙšÊWkÛ •èÞåÀä²[Ü´ Î6«¯Tí:8žc ÙùÀøÜÂÄ€PKYy§kxGÓ×¥Û*ÒWKLùFšP.ÕaNJ —mÃÐÿˆž ÚÐ0x‘àÓl@Võeh Œ œ¾¦xdkãmu !«ãivß±‰Ê· Ažª`³)ìB¬…*Qiñ|ªÝù*óâ¹[IJ>nøZHé’! +Ù³Õ±‘Ö7=7íøÛJEZ…*k© ó·ÞügI–^ê˜æ4˜ _£ŽßûC¼Z<™-¥)Œµá¥ÜU¿ÖO\}þ«š- ÛKÉJ4F-ð˜²MkÛü ñ¦ ä_ÕXm«TYÊFr™˜NÑÅJ•å,ÅܹNÙþãµ7Ðýha«Š¹• eüÙëÍ s-?ï'瘎ƒaè¹OìÛÆOÀ¶Ú C©©^eûRš MQG¸a”¯éRM^JvCÖT-Ð]G+Íùlø,µ_[¡ÆL¶µob5‰˜ U97Ù>E4¶ù4Sfh½¥Ÿh“phÜV÷Î$Y‡±”‹ƸôÚ•Õèp`˜¹ñdmÑ÷ŸÆ6y²Þà0Y‘ù:j‘eáR¶-d_[ž­Z||ï—²³›ß{¦ÖxÖ‚ƒ&VWÑ›ª°ƒÐÈ9—BŠZ¨2 Oš^} Â@%ü…*$†  |¼¬‘¬Ì¥0‘VåÕ–êøÖw W›> ÌjáÍ1-Ò ®…Þ`Çl«Q3ÐpPˆ?ÓßùKað™p‚;‚y`Ù&ר0Òö ‚Ž£ ¶æIŒ7矫P V£D*'¶.jd+fHÜCï…ïJs&ã#àl)iúë$CÙ*1F—ƒQU/XJ;)+Rß ­^›fH/E\Ç5Er泪@CZ¥ºæÕ¶â…¾ïðô:6JAV­i[‹ ‡°•Fa×H¦‹ ßT“¹7˜¦FùÏÊ0”4*,d‹aU¢­®ÑWxΉé=o¶¥Ný÷dÉ|wK¤qŠZtç‘”4ÂÖ÷y·G†'³nTþÍf $P¸#œÅ‹dU ('f.°‹õ˜òoëUiZbšuTÞ ¬ÐE¯~¾*GRb*±ÆÌ¤Žœu‰$ñoV-÷µ^¹Y¥8(dRß Þ4p<§ÃDòp° ghUKжlz|cðviiÒóIL@¦—y1ë@“8B åa&! 7@6ÆDŠM[¿‘U»SÌMʃ“Ý‘~¯ErfkN`qf½Ï”¹ª¶­¶º—Óã°Õ1“U…,ÐH4JRêþö…;fJ«Òçã笤1Í…û¬ÑPêâh”}n~ÙM+k;>uL€—Eªíá‘á|æ&õº…ó±’ÃÍŒdX‹J#¥‘€idK@ [á.A‰#¿×Â<2Ûôu´&Öæ u±%³ò·æ°i¸¼ERj«Â»CŒÔµ<‹‘'7Y¯ 6žîñÙ &UIyÜ^G£Q¥¼F)ñô)ÉF •ÐÃ4½H¶LT9=\–ØëdË¡^jÃÓÆU÷QRÕ$5­Óð•Ð̯uíJa„”À˜P|¾¶Tj¬MOºö0dE^YÀm:1`-Tqd=æßä±-e38á.¢vÄ {TZ3QÎm&k‡ä^9(ùô•Ê)¦¯<)AxoKU¶sØ–©VaÝ­ÚqÆËºs³9¬Ù$Y¥Ä´å©¤ƒä†Ä«Õ¥(»s„,ϪGÆ 7©ÖuÄu.˜ÏZÃéÞ1@9ÁR •¿U%¯%ÜäJ(Ù/¿ƒÑVRº.¥}LEÐ0¶0k§h« îÂãm“MPwsbܘ- ¼#vXÊÖÊ?óx…lul˜ÄÍL`«£7‡'MbžHYï'î`‚øpÔâÀI¦VÄH)iNÎ^{X”%–Mld£¦±N`Únx@U9åˆm—UEÃ)Ë X¤ïŠòw.µdªð@¯^¶yXÉ­ZÛîÆÈˆ10ºüº³Íp[&G Ó40q«m¼-ó”ýp© œ­•€¬]Ú˜š¶¦Ñ" nôB cÓÈÖhž˜ U¼° ` IY‰,fcW‚‰õuÀ ý Aj…ܲ’pŒkôìB Î9¦Ùšy}ÊÚÆl˜ö‚0sÀœªj!Û$cÌŒ•t:×ïãVX˜–ÀœnÀK¨‹*¤ÓÁ e×t>@åµS6@#Ï@÷¡[Û*̰}Ý›/žUdßvd"› .È.™ #Våd"ÒéàfS²3=FL+´h”›Q‘Vµi 2Œp±x[%²™»Þ¿üå/ZJ¼|Ó²…™ÔÂV°ŠªµÅ“aÔ†ô†‘ü§”7ü·üãi‡YŠ·¾cwTÊ:Ùæ(ÜÕ$3¦¯3%ÏSô7žR¹×®¹e=Y[ÁA—õ¢ä`©Áµš§+è,Rx%@&:&ÃÓôHå,œY¿ß‰9”%¶µ n)iD˜ –rËZä3R­!eïϽ¥gA&£éƒ‡Ñ…†™ 'îDY©äÏ­*¤·í€d‚ *$C“Fhm•ªµ5ñMþš6R­àYÖ ¶°‡›§r[âæ‰´šPþ ÷}wéÃyªµ%ΩJ ZtÞÝÀ™éŽ1m%•ÛæÙv+Þñ تª_¯ýžÌêŒ:rô‚XÔ®FdÊ“µbè™4mâZ·Í æ°»u|[$úÛðtìcT>ŒˆŸ¡†øª`OÍ„5”Ȧ Hu «hÛ3²¥Œ±òH>VÉÄœ¶€*)¼ ²Êm¥ð²¢ªøÆJ &g‚.a>õ­]@ò²UèÉ*Ôš@ÔpxÁÇJéð¯­m>Ö€r“Lf’˜²º49>7 Cd}u©][«­Z¯YVB•r$Ð6p“' X2“‘¬D}Éô}}ª-BÙF5Fª5ój=P[aÛ¨0 ~‘¡5 ¾!1¢ZwöúVîç/ ^l‚ Éù‡¹Ôí,ªd&ªZmÓ0$°z²0µ*@Ô XßK–ôg¾{±ÄjÛ¦è ȵkJ̹§@LÙx>¶dGèMá 낹~?ÿ–A¡h½¼ž­ªMžÃÌœsð,’Y».V‡9dÕ„ª4%èS ('ce5Þfˆ»‡zQ¶µ†ûÞ±eNc…µ³*[Håçmó¾ ×ã,•p`‰é¯)CV¢,pÛ~dŒµÉë•8O¼­îûTw²ªzp«Ýƒ“r‡ùó$6$€ÙͶá dK©­„/XaºLúl›ù½[岿´*Q˜ÃZô2t¢ÚÑ¢™«Z‰.×3¥q@)>°T³Tñ©éRcž—F˜~ÁY–R°ít‰©KÀ‰d ¹¤é8°¯‡µÍ^¯V 1I+2«WK†@ AdØÍ”ÅôJlÎlûˆ¹½¬¬xÃkM©6+|Lð]×i¬jY©2 êòÉøph€f#°µz²‰)yZãáî„^à9 ¬¤ùf[ ÀDr n$¶°§­ ¨h[@/k…ôÆ#vÆfÀˆ”{‘¤0øù\Õg©KU¬h0yr€»F€!›œL¨¢²Ä1»O·L¤Ôâ3T¢ÖØ>>p ±*&¢cªU%l;¦5PE)®µ-[¼h›¬a¸iWÊÊ„FЀÀã >õ7¸!ÄJß)dhné§Ö–C…JÈh:Q)+²Kë!v|¢P¤wEªDLµ0PÀ²|L¥Ði›Ìªq&U5­Ð)âilñ|0ÀZWb+ªªŒ©‹UUo# e$óTÒ%ð/¨$^•j’ú¶&¶M©…ø¡·¥¤yj¤‡iÖÚØ~'éß’²öPœÑßÅúª”Ub6úœ½"CY]¤z ª™÷§.Í@ßévY2äÌÌünáeÍ £¯ZMKiÍÙÀ¶‚9 ±Æ4ñ\í¯…FðaÛÁaŒCõˆu3eÙ²h€1õbB¼ÊǤZk¡C+&Ÿ1’'7Ñ61R¤*œF¡lµiÚšŠ#\£ÿ¡y÷#ŒGéÈù$>72Ü<]ñuWõjZžÈµc{ͬz5¥Ì¾ó÷}¨PÊÖʇ8̤¹S‡)ã»Iàdmi00ò¼;p5¶,¬+®e2mȲ˜ÞVvd¯‹¹7_3Õ²ò>9xç§WNO`…c2z[©J€ÚÉ*#õ²"ÝѲùÛ&cìÍÎÙ½ëe«l3xÒ-‡L¬fÖ(·ÄV[«l-l»7J“[k‚0˜9~MÔ"1ưšSð‘*rÀóoÅ8ˆ¬*- œsc ÛZE#…•·¥$ƒ†l‘lMâ~¦ÉpµUe˜ÀHÝ<ŒQî\ ÀAp°â)ka› ÊZe­B‰ '³b”æôì´ÐN`hZcºŸNÁ¤4á¬(ÉÞÂMkA#eÅëÒ¶CÕ”fc¢—)‹_Ég6[âæ„+±-T5‰B XáÞŽa"8xô€*+™0-Yz[šÌ‘4€Q8·Ú5UAžJÊ6¾ñ`1²­ª M®ñ”­ÖfÛJ£J¨JPUÇiUÕ‡ÔÌFEÒX…¦ŜÏï+f@ò$«ÊÚüd·ú×OÜ[úùiTª5¾U£n¬^Øv.…‘¬zùþÉà:RYIÙZmOÍ„ô5’ªÐOÃ0eÎ hÅp T]jcxÚÎ!2^­ã8ÐeC•¬'bë¿` «2ž o wêNÔ¡Òdkj¥:”Z…Y¤‘­|¯zzJ]nÅYªæ¦Ö¯&&—2‰èo:mÉô¢§²EJa¬o4CJâÎØ¨—µúq|½˜'6€)áºDÝm×…ÀØyFÚLŠŽ_J!%RÉ´ÀpÆ…CÉÖZªajj-(yÂÊc+›0·½¢ŽÓ`­ª [€§röù]/ FµžÃFRÛüR¯¦Âj_ì֞‚¾þ·È»¼îV>x¯ñž‹’¦šs÷@ìtªÊÚŠN¤{³uÿ”²Æ*(u×èÇü׿óyѨ ¤ïDôa²R Wr|o/æe9`œE92e#Ȟ̖ž¡€»b˜ ÿåè²UuFjËLU|ž²Y1·4¶ñ4 í %°Çd«…mŸ@vÊ&Yù×éü'ÙÖôέ’>#0ÒJÙÚTm7|34?MÎÝ[bÙîP䮢ǡ¼Ï¬`bMÖ•r£äc‹—m$˜sb¹¾ø¶€ÏN ©¶x˜çß~ÿý÷z $x%²ŽÁ¥-ë| Òà .qªXÃ)ûhUÆ'О fè.hê¾,ÖZ qXIn±À¨57£Pk…0’¡Ê³y’ù‘ `¬A­Û%•#Åzɪ2=M“à1¬DnK£V eá÷‹X-’¸a€Ä§æg]„%@™­Òvbh~¬¶E)X•••vmÍP—Óòû S‰Fnn는«"àÐ=`ÞÃ&`E³Éb¤”ì«„C²Ž#+”èÕwmšøæ$(JÁô_îó›ý™ø¾9µ€ë¤± }_Ï3ê¤l;f[˜R¹Up¶Ú\À £—T#…§'ë ãP¡­ÖlµSU6À¯DÊYl­ª86‰”ÀŸÞ÷ÜVæH2˜“ ¸m+ ÒÈYj-”±+ @IDAT7O¶×ã×—‰­^joŸsÙÚzʲâ8sn>¶Ì•JðÖº2ì8[±Ó±R¾lH­ý5¡éñ4jÄe3Œ/æï7oQ7ß?®„C£6üµüe›¿”CÑw‡Æ0]/ PyV€ ²µƒ4†UÃÀ"7Œ Œ9sÜSÛ®)‘y|³©j×vÓ7À ¥®Ó±‚ÅŽ£Ìš³‘j×¶*]‹² áõ’]•”«^4µ¼]°.ÖË6=ç­Ú:²Màƒ¯–Â3‰ïJ1cK èaÐâ ‚RH…¥èEô-¤ÒÔT > ÈZI9Êj½ó€¦µ½´™H Ô¨w–ó]™[X)dkR…”yð ñVÌ0MâÖRHí>õÿë?ÈR¶2§âi5†Çן½yöµY_Ê®BS•ͤrïY°m$[‚Úala ùa€ß× ;OÙ|Œa€”4@µ9[+­ÚÊ2GÚ–µw@Œ1@_têxV4ÍØ&N¿ûÎcÖTaA àÖUÙªŠ/ïYðìȺ%ç2VÖÓþ¾3V…‰áZ¬öõOÉ\4v3X9ë‚„»ðµèqtù'ƒ‘µ†EM#itA:ÈК¿T}­¥’Ùª”'ÅÌÜV4@S„wos“­ðú|þàw5‰Rhf«‡_dY¶">ÍnWrÎ/åó:xÉö,i¤vØz ^t?u´? ƤEzÛ Oãïç(Û$hlJ)%8Y<ÏYÑÓØ"[x½r³bÖëÌôý^ê5–M@™L;šº¿Ç™€ž gb •Þ;–íéwCÊRê‹ôHG Yð„Ç+ÁxÄ^¿bRÖÕiÚð³µ]_d<1R AÐíy¾Üj*UÇm1”ýøN¶5J€3¾S¶ÔOi[– £ùùK¢ÞÖ×ȶr¡¸z^¹¸ ã"iòiJ[¤O—ëóyóøã»b[<ÆÖôÇñî㊵NÉæÖõÙÖ¥‘² ˆô9Ãd°U`‘*k ÃpÐŽ@äƒl•èB@µn‹”Ê¥ÊJÍÖ jK¶Bæec”µ³]«ÜøpXŒWe…‰7ÙÀÚ}mÎJÇÚ6«æ‰´^2ÌÐ$²Ù¬êÞØ²¹ñµgšïwŠmÙÈŽ °“º"‚þ¤”ÒJÃJ諦QÒs¬ !KÃß0R@L2&9#kê!b6 —S¹v Ák{s`åsž¡BaKS![a»1’1ɇ'VH3 >sÙc}«6q$¡µ³_VŠ®…­T¤5ž^ÞœdnÆ*âÉÂÄ9“º[µ.Ei0§æS£ãõ½4Œ i UR«^§Á=‡Ss«Œ‡”UU#¸TÈrhU(ðzUôæ©Ö6…æ¬$‡dÂ}"ë‡Xp³ÊJ1Q{éŸ/ì߬r[VBªñÈL˜ßHRxkå õr ž²iÍp>ÿuzŒ¨¯”’ô•3R*s+œ9M•û|mTž«Ý` ±”­ Ãv]HU¶ŽY*çe¯¬œ˜˜~š@L¶dMU#ó;#ÜAè5≄]ó&Q•¬r2V4ÙªÂx‡UC c3éið o+o˜Æ#¨„@¨mͼylãõêa;)™íÄ FÙ‡œ¥-“|8èØ²†‰oNkd† mcLXKU¥üæÏ1‰ÓKU²5[ÛºTÒÖÊ­¨cB&Î…”¶› v bg40ÿœm‘ÞéüÂÍJ°­éJ5R–¦Fù“Ia¦7 óª`ã½YíjݵcECiËޝ—­*zŸS6LjdÛ 4Y)D`:ZÓÚ:x7V¹‘Db+\¶v4©²ª´°–ª‘™1M›-1p‹~æªÈ¦´ÍJ;¡5lJÉò”]ëcôý¦&†­LÌ“U—¶ E2΋f¶­ªÉm{(™(Ä«ÅÃV[ˆiK“†^ô²ÉÂk«j•‚ÕÆ8…áN~9‰Ãd˜àmϙ̛ã+ö‹CO\Gk_1Ìû²6€Ö²x8“ V]rV°H‰›ÇJÙTUÕW‹ÄHÌRkË¡ Ä“qÃV…µ® ü’”²ª”ÔÔ¶ZÛÜ6&±rµñp3`DVÈB ( Ûê⮬"MYÛúZÉœKt [sâ+à™eg·r#3ÛpŒ*)Ö:çf¶J5'ASq¦é)BÇ|Âéa@ÕHÛEYUÕš¤±›Þü3,«D ÉJUy†R¶ÞÙ¹)Ágee­M‚™`£J!«ˆù—…¯ÍÏWñ ¥(=/“Ì$ý49Ïž§”*@#úI´^uÁx½‚à¡,±°%S"e Xk¤$†okH7ðq¼·eàÍŒoB&ºàmµ¨u€¦8s³aYb«­ Ô”²ßêŽï—œ>õ¶•¸"J%<)­ø¶u±27\»4|²Âw¨lãUeBœÏ©ÿkTCÄZVYê”°à¸Â½+¥ÆÛrPn5q1Ä­NŽ´uNïºQ; ìöiô"nzâZçlH¶4™p³¥´%ðÇ}뮦ûâ3ÀPI¶4jwc6€F‰€9àN'+˜,• ’LÊGË–¡0³Ó%ÖCcþ4{ 3iËA/LwH/Ö%CJ]x’ñ¯E²éÛZ:>±Zq½? 2¿¬š®D;)óGV•¿r[AÐz;^å™—µíJ<;ˆ’®tÀWízÍÌ0»[β”9‡Õа'é¢×ÀÈz¯ð4bMñN—^(éí $kµ5agá ja-ÈÌ-Üä0_ ÌJÙSp?¶øjK©²Íç–Rë…7³GiæNÚ¯žªh”ØNcÛxe9t'b&pMéö½rä)d¥D²|ðÉñmÓÃH+ÃwB¤­SãsH¿* FUÁž‘kYÓX­ìšÖ_*>qM=Û•äŸ~æ.³ñ²JÃÐe¦5QI÷/ÛñUaêE —ÂØÂ îìÙ6 óx‚†ìÙe•mšÞ™l•oÚNQ–úà=¤Âò‘¶0Æ6l-¥oí˜4 ð4™ÐÛ L0 ªQ¹‰æ$Γ Áµ<ßü°‡.‹é&ù4ŒUØ6m3ÔT!Pyú>Jù`&Æ0±v3ÚõìZ_½.5Bù°0@8C$=@8E|&½Tt t¶|ð¥zd}¬¹µ…ÊaJÑlÍ6ñÍœf"ÊVžF*Í«Çp#6­ÕÀ%+Åj[€Lp°öP<ØÇG¡¨#@|9K×ÒÄ]Kʲ 7[¤*Ûº.†,Ûj«µ^d°¾xUÍ,ë«VÊ–'@ZmGr ÃïJ>[yjÁPI[˜­*_/µVÞHHY2?Ú¯J£†ilh0€2žX¨RN&”ÛN1M€€8+Y[Cö¿!Ö–}žŽ¬^dÕÚVž²#U˜îóèf:x…ô| IP­B½0¯CI‚-ó I“,2,k[ ¬5óÀ:æÀÐl×ø|Fj£^ïŸï: Ÿž2LÏ-UI3ÔÈjTà £ wkC¨Ù4Kå¢@DÒÀÝ&,=A&psTn¥o)­ ݸp?óð"7À¿ Ρ*€‰¬*|ï2)$OŒZ†Él}ýaDþրǠdãÉ´ã–F6žawÍ“o›L €|úº!ÃÃVíl‰YYaÒØûó%Ñ•æ™-bòÁL›'[åd4æ!¶¢»ÂÔH±ùáx 0ÊJ9çFEý¹–ŸƒU ½¬(%›gÙl‘1±µ„*ó÷¡ÕZô”<“låô1’yëµ9_²¶5};Â"«Ú)læÜÎîÅ*ïÑ×K•9 )”½çÔ@glÚ&AJq h0[Ù b¤HÏ|Ãj鵦¤ÁÐ{‹ú'ÝRBŠl¯«Jd¯÷Ï„mñ¬`µxVáKI–’Ø„H äSÒ<¶…anõcòÞ­^i¬iÃ5jÔ³"{’iŠtðU5mV=‚†i<åôošGFo-꘲¾1ÌduŒ1 «>à˜¬di¼R¶ºëÛhØ"Ð)”¢^ïdH+“žÈ˜¶º4|¶dõ]—u”zk'+òÓphU‚tÞl‚Ò¶békMo¼½´ff"(¯ Y%3Ô¢CÕˆm2‘Ì*lkð\aÀ*¤¬ë˜›Z@—˜×òó¬°l6†mG›ÞÓ5¹òd9üš?«è1ÒÌßðiØ•˦¹ïÎù8üº [AÓÍÀ9SŒ  è¬4a)|潕g5çסB…nZ»sš_o M}³¢$˜¬Ðñü» kcgÛl¦ÊÜCñQmU‚>e‡Ò+¾”m£’Á4ïä4éKÙ–µb %~€bô%ð/h×½!{ŽëE,R6póS X¶¦Ìm­¶þ;|ºÜl ž _™n‡s cha+1«Êµ(êËÙ¶^&Òª*½•MŸ‚Fêæ1xQS@q&™¿©jÅ´îX RÔ1Æð²"ÃVU²Üšª’ÖjÉ€®‘ò˜~b—i0LO0ýÈj›MÖ­²~²äÙAL^ŠUÃ7˜mcÄÃô°,VÄ1Ⱥï­0ž ¤qêþfœìó±¯}˽ˆ\ËF‘b‡ZɆ Ñ@RÍÑ1¬4Vµ5µ"ëKÁ™Ø.ÅM5IY'™ÒQiÔ.(uaޝEÝÃd€ò懡„yÙi¼… Ü…ª’bKŸ&`x‚Fb¨¤­5[ógn[‰•rUÚ¶T+=sÎÄEX–!Fa g8=àÞˆ)Ù’ Xä³£av– ­WøÃ×"¥U ó_¹F²ñuQˆÉ–¬°WŽ)‹ñX‰ †dEÀÊ–f€vjÕÎJJ¤wp‡™à•l ÙÑbˆõ¥o ‚^bJL#!M˜OžÇúFcˆ÷,x±ªî°ö²)ÑÂ[³Iõ¾!ó¬ðŽyþ¤”­µK›gcàµzX­sY‘ºt ÙŽŒl<…á&L)µßÉdÉg%“Æ÷Ú»ÃÚ‘i$€õ±¥ªúÝÑË&¥¼câ+¡éN˜À²¶¥0"Ãmk-ðé‘Úå/…W’'œIcÛºCU hr­Ê`"dM’J) L ²#T¨ÄÖð ŽÑ÷÷IåÏÙ”Ù¶FØÂ§Ù÷ãp>ÉÄ Ä}7Ö”4RŸ?ð2¥õØ?ækcU&€Xy¥áɇéI$>m¿<ßÕ‡JôU"Œ$å—¤R×༚¢^4ºd §ì>°žA“X}tµš_y€¿¥¶Ý;R ³Â‹L²•m*¤9ÉÖ ©O`mZUø}}œïäV++åVA‰¬Æol|ÎJ’YRd[̤F”ʦûwØZÈîåk2Áv-b¬˜<;5«l­R<¨Ö*6\¹U ©°’üGi…Íc¥/àw[& c…ów.%9³ªQµs e×±ä<áe³jëuêïN\fg¡AixCº:2µÚ‘ɦ±–mÅ(ÉS!7˜¡ÓizÊîѤzÄy"‘˜}kÎesS˯WÎ ³Q•4yÙ¶øW#[÷­M˜¾1:Ôn)A«r†Vzú×' ¶RZ‰‡ ÞÛH`­pÿ×¼K6X·Áj6”`"0¬l5­o[Ìx8 ‡nÆD+Ï@6†á¥`ŒwŒ®°_‚»Ÿ3Ê=TnmÉ7bg¤ù%³Uâ˜Äéf¨°#e¯ëY04@nüM±%°PK `h†ñž‚ÏŽî³,™¾ ñ«@*Ä3·}Ýhš©ª[j¼x)ÔÔv –†d‰'‹”GæÇè«ÁÛ2ô­GwÏbyètµ 0 Øð0ÒVx¬c€94f ¬­›Q• ½_C{‚¨oY[XäðbŒl+ÀYI²V$ç·6ýJ2µRë˜,råª\EÔˆÀ–8e§žydO0’R`šYíJ¹ã÷»+84’lU ß@r&CR6ꎬOo8¾a0‰é'fîßz࣠Ïþ)nÎJšüiliø&ùÌP–2«4°³ð¡´¦¤é ÙÁÉÒLFÉ É'C[ ¹Y ú‚C ˆ¿ôŸþ³T×n•S¼Z#‰}E—­K…d‘™Ji$ŒênR5rïCIFÐ9ÃNŠWhª9Ha¤z+ðZ+Ç#¥Þ[Bjç8ºK bëÚÕˆI¡{þ4@8’ ã·må#ˆ+'X ”‘¬Ní.ù²=w]Ô  #â7¾È%±m€ÌŠgbmšJ&&“5 àF¬n¤ÉØ.eΉëõZÁ¢¦j÷êÞVG…¸'Wbå¦Ð7Ýþ¿ û`Ш•ª¼*¯„ U–>莇9¦r¢N×y¥jÑ0²dµ€û—ðl] AJ¶¢;$Ä.‹‰ä£+γP¤ˆãw™÷WÄ ²Ü”Wh6ØJ#e¥¦)NƒÒ,×ÑÊÊêy¡-`ª]©Zd™Ô΢CÑت‚žð[¨Å¬d…y¬ó´…ix6j$Ðé1Z0'3so‘-, 0½ªuäÚ‘C€^4 1d0¶V³ ]*t($\S¼*[¤Âj ‰lOYÌétO ÇrÀ©ÚãÀÓ7ÐöX|ß1åJ²y¤ŒgMl­/[ÊH8ÞªJ9ÙT¶EU9œ®ß7ÓX+ÐET˜¾si$”ȶÊög9Œ’U©)6Ûüs®¶^Lô4Îe…‘²dV¸mn²ÉòôÂaÜa 0ª¤èħȊRÐÈÒÛÓæ{¢¯ü¼H­» zkA#e•=f²R¶VÛÜ`€}æ)óá El&s Kõù2ÚªÁÙʪÈèÕ½·«¥‘ݧ†€’‰.j^¤B[…™cºŠdõµâE+Ùž¦HëUvgQ’í·úóÁ´õô¥X‰|Ö.dµÜ8[1ªÌŸŒ>VÈxWÄÔ…¦ÿ’ºKà~-ÕÎM¡°-ÚZÉ”ógÈÖjÚZÿ*ì‰sÞSP啦o°lÓÀ5•F£ž,µ@2”V?|ûG=•ðÊvUõÔÔ–­”íH¸¨)^è²µ,óÊ¥Öc«{7F£ ɪaƒçClm›x|V²JÈ6äJbüÊ] ,:~ÎV2Œ¬‚@må² ¬R”øË…¹m`…²>†VA†·šV˜ÊÐ €“1Ñe¶HL§¦We+ÛÁá²/“üÇ۲݅¶MôÎÀ€©ZÃ@—5é³ÓœøÈͳ*­«eTãiD³µÒXE­Ã]*7)>j1úZó‰9g ¨2]¸[€éÄFQ_³‰kcË]¤§qe•gXcYšwŒ‰;¡Y+‡¶pï)‘¡Â4u±ˆ›§¯l˜ >Ý|àÜÈ&¸–Ç“¿UŠÞ鬊WUßHVåx ñ(û}ç­ùo*bX[9=| nI)L…M"ÕêiÒ4@V(¡!°5 [[¸!9=ý>)7-%7[ÖÔ–Ì™!¬`Õ‘d+ dUuœV[í  (IV‰S£ü˜þ´ü>& v/¨Ü*š\#X­U#¡J`D‡r¢˜Sv'7$Ûš’ÁÅ-=ã)ÄÛVR¹•¿,`]>Í”p$†'M­¼¸“žQ1ð&1X& ©¼Ãn+;[¤Àt¼-ç“É"­À7§“&cP(ë¶1yÆ7R­ñÊ7<±Ÿµ~Ç¢4¿¬•’c;Ï" (§yÿ-|ʪJWêùKn&ƫŠ; *ÁVVmgÄYõâlH€À¿Œa}Ý2±Ól[ùÌ5"‹5µÕKmå­üÌ#ëXJ ζpnsÛMviø˜R|LBÐt(À`™[m=ãaÁªèµã,ðß „mÍSÅÕØ²rÕ¬€.¨WâζJ&™µ¬B {¨³|[CÊâ9ЋY/RdÂ\ô›@«i ˆUIuä94Ûšº½vQM¥\£ÊÓ7s+†€’ —а%Б@wÎædˆ§©#žƒ#$ê°@3L¦¶>çµ{ú ÓÀ°ÝÕ)1ÕlöLæ6ó?ÃåsP+LÛÁõèל¶@³uú¹I50–ÊÆðQh+ɸe^6)VRǬZ•lÉÄ4<3´zšúß°q4±ƳU>O hT¸îóç,Õ$ÖÍ–çªÒwJ\`Q‰­ð¿F‹Ü~~Ï·#Q0RSæ«1 âNH‘µ{é“›*ltå™ç fRÒ3ãÀ¼—òÌ{? ;°ÙšÇš cÑ ‰ÝrçW%Eƒ”X™Ë:¥ ë•LâH«h¼€…ò”²‘Ê1Rü1ZHaNýRš6••²Á¬ $Ph+›ƒJ²ÂÈ„”-kç ¸a·ÚÍT¢»ÁèçnFЉB䜹·ÃÉ %µ“Ò‚¸§\Uz2©²V¤ìmx£JÊ`ÝÜMÛfK‰´}­è £¾©d3i$%¤¦šRÓ&4‚ÉYU÷fåS­,M²”RE)b1™\¬Š¦«H¼<™îÖŽYߎ0µyëN SVÈ [þjaUdR‚ØïaÎã;221rz“TÈD4Ø”§Ç ÙÂAÿ•œ'î=ôSV_X(iæ¶VzsšÄZ;²ÝRYLúÌm\9`«\À¦ÅÃÞ;ÐTZ×EêÔߨ4¶V‚”v¢Üd™j+Y%õM/ÅáÕ8rCZÓS¶zª ùÃ. &¸ ?_P¶l2¸¨)<ŸoæOÿ¹òôfÐ.ÒyÕê‚ÔØ*eÔ²H@ €;ܨâªÒ É:Nd×[vÛÒ [) ÂáN!ˤÚR”€¬©ÍÌÆÀäÌGøáK™Ìéê¢DäP–’2Ïš®Ñ•ŸÐåÔÃ0qµù›§Z$ÿH+,ò©–Ò# kræ"sz‘¬*«‡n¥§É§-†X–!ÌîO¡xb´µÊº]ð·Ûç³Ì•ÀÿRËÖšpáÚñ\ ÃR%f A6†X8l€=”FÂ+±’|œ%å¶x­EÝ•-@¶kÑQðLiU+›ÒÀˆ®œE¸”Z¬Ðºl¼°òpµRîA‰aühðg³d4Žæ¡tpc4R«cö["YíšsžñHþïøŽ w]LJÍüHïÇÁšCí"ÉÄQ|ÃVP $L_‰^að5¥lžÜJUÅÉëv;œ%C`U€_!èÈf~ߊÝ'@ö·ÿüç?ÒêérÉ..–õ´²›Q—¢ß˜p[âô dÕå ‡á@œ€¸ãÑ …¬èð®ÿêü§Tn›“rßt®q³Y5[n­]Y<0DrFÂda † €çx÷[C …T…´50¦ ³ªVÖû­ÄW0†Rä \÷Äd@|¸­õm9Ð4€À™+^ u XÉÌiíìÒŽîˆC€@¡§1lß•¾9zš"\¶ïÕ}ÚçqÜOâj'*ÁÖ·—B¤@ [á,ÜY­DjÊÜ(W ˜‰íL®÷YŒ$ÕkIö:Üy^fåBS|{7TEÊöJØ"Å­øT5ùñ¾™šµ TBP V“¾9kG¬#,Í[ÎÍäC¹“ž ¾O³C*F9†OnÈZ`Ô¢m«˜ÍfµZm a›ù_¾˜Ì‡¸m«m&¶j“Ys ”´UÒ‘m÷Àñ‚².@¡E ¬­ZUm†dH²4éÕÒˆªl]ÜÖÊDU-ç€äc5FÜ¢ŸB¨FÖ_!U^k¶|¯ÄåûQ"“ʧvaµÓ¥âÆÀŒÇDnŽÓ{B@o« °rƨ²Ub«Døññ¡€UÕgUy]¬"žs`ïÞN] +7¶ú»ú4V]%Æ–³10“' §¯ÖJ)dñ­£”êàœ¥le)+ïBñÓl²‚ Ëq"Œ-[zÁ0Odζ²m¾sx^áç{Ãx¶¬ZX7R@(:™Ð·^‡*ÏŠÀÍÐÀ5Âs‹l{ôªZø„îeP²`RßzÙJY•¨…[«eÅé‡/@f]S[­e#V‹‡ÉRÆ#ma΀{#iêk›¡aè )¿Ü@V9`Ò`9`ˆ3±¤¾½á ‰´duʾ_Ô ÉܡކLdñÄóÄÄ PÕv+ v¼ª"‡d‹ô²&&ñDƒ˜§†Y ®‹-àDK!3Qˆ¯’Ì*hD½¬ ™OíºL+¥’Z×eR1ju„émSJå¹I&#—ªËÎ+U–¬H¦ÅÿŒÊ)%C[Ç´ú°»g¶ÆóæœÙ’Ò¹"FRÀ–©k7ë^„-& `{¦¾bÙ¦ÉAv)|d&VA Ä|¦´%X´=¢ï«°Ùh(«K˜6’CekÈf¨—?nºY…¥šß•©­{ çzY+!†{q1œ³M`Ë<Ï!+LŸ@5"ÆÃ‘¶HÎô"A@#ÊZ׎¸àÉAÜ¢ó°(†€³IJÙÖ.­é1U͈§¯i%lñ²§Ó÷ºø$` bŒç&¾æ&é*l #â[m‰ÉFr@ªŠÔÑ©ià»Àfnƪ )Zé»ö÷’1d†iž+?7¿a𪓠¥´àl±ÊâKÁý V%•§«Ðèuè\uï€ÍÉÄV­•†À*dNßȘüµRîJŠÞ¡hð˜d‘9˜¶SËŠÜÒ_³Ï5†×Ë Ê› X‡Uш˜R¶ZÃV˜Òœj#½bYΙX•ã1øm•`²Ê™,ÒV(!Þ1a¤U¼æ°³'æ à&V•ž•€…§ W²˜küûcBC™'¼ÖJÔZ›ÓRÌpn¿)ÝRkµÀ{-Zìùª…Í–ÃéqÝê²-gA‰”º.$¦yt‘êŸr÷Ý2‡}êÓ[‰Ý? 6k[Ì#¤´CÂ]ÑîYy©£þŽètÕnÄú…±ù+äéauØJòLƒ±'FªŠikõ|Ô&Kƒ ªz·¥‡ñ¨|+’‰µ¯GCbªz ë®G`íí%›Áغ«ÅàOË{Ï[™ãɺL<ŸÞ" üž¨T½Tù¡@?sLnM[ÿϰG€l `gÌoˆ4¡a4ÚØÑc’Ê9OX(o˜¬m_*’-ž ¸õ¸‘VInz2á•k$z)%@cj«’Â䙨ºF|”DVÕÙ‘É‚øÚYïáÎWP‚N WXþ¢Öº0ñ:yó›'s[Oößÿþw.¢94€ñ—û<†Èø¦‡;•”;¢×Cùè½ÔJ¤fGBÂøJ&h6$Û ›ÊÊÐJ)š*À§Áò¬…”m<¬Ö¥ø"~Uòø¥š¿aj¡*gcˆPØ‘1J^ LÃAp¨vdS!µSXS¿–áKy6ª„,sdk¡°@Æ[›Ê}ÀU}“ræd•Àm­‡ ‡œ‘™"ÍSUdµªrÐÐBTƒ¤T+ðôÍfÕ“o68C)˜F(@J†‚ ­G÷Gñ|[nk†NêÒ¾j8s@˜¹L`¸y &:E)ÛÆhËhŒ|”çok¼v‚˜ k•­°S­0Yƒáe1€UT/g)`¶¥loÑçß73ÛNÄAôjÃxb%|È0Í`ÅÛJu«ŽVª¦°(E†Œ±r.àl»g_}o MÃ#»7@Ô´î4˜Ìa)«‘"á ë‚Ä·”ޝj&¶xQ+\6rʹÅó]€n/ƬD'í•ðç"‚ÞÙ•pà/dÖ‘áº(„S ·jëSv_Õ©SæŒé…¬Ü´$c’ õíRj“€ã@/µûã? :l¿‚˜€Zkþyš&ƺ ¦ŽÝ÷犭°m•ÚÅ5Íx)Ø!Û1¬øÆ°Ê'­Ä6&Áî‹snøš’åc  uv© æ8>A&‹ 3ñÆä …„ßc€X ºXóïO¶n›‰Tóè‚ÁÜÊ™HÙ¶6’mL$œ›¤¬¶^>扣æ/Ûð&!SnHµ‚¸Ô9ö½Æ ɤ¬ÈÌoþOïLY<·²7Á4`èWw[b£Þq>‹í uoU"Yœ¢lV²Ž)èS²&ÓK”¥‡‘d‘x‘Oø×–ŸR}›(·µ]¸˜PZ¿™ÌÁ"»v€ç™é~†YæQèÓ ï¼”¶éÉâ=qJú˜œ¥:8 Û? Б>Òl€UHÌ….BƸSPb˜0&HfEªRK`›? Èl×%IØJ†Y*7­›äÚœ…)¼FJ"ÌÄÏ¢yúöü“ÐØŠ€¬¨0ÒöæÏ¹X1ÑÝ%èÛSƧ§ÄøÙx[)«î<kUxÏ"¨‹õuƒe­ ´V §éYøªñŒZ°Í²ÚÚJ%@ ί¹”m剭ÉÚJ±%+G “Ô1îÔ@- iò ßVÊ# jÁ§÷_ Ù©‘‰¥šYêÎuÙÆèû0i%ÐBŠ3Œ)àFšgz¼°å,+”4'ü’á áZX;{ï¡n²‚2[øø^gÌmøùvŠ×Ž˜¬©ðHäïPp¶‘5¢AÆgR­Uà[µ¶Ê;Kíài†3u̳Ùké]Mìµ%À»œjK­ÄVÖª5Rt«HzUÀN†,{‹ø+¡ä@ ¼ªÞã$Ã#áÚs³âëµÂ”Lúã{­ÎÕ?›ºÜY: À°2ƒÙn ϱl%=Vš|ê²ãÛv[ú ­ ªÕèh;8’”FUíÍFSU ±•›ŽÈÕÄgÔ¨¦¥PØxð;×@•‡•ÛÕž§Ö?¾f[a|3äÖm°ê€¾²êf€þAY‡m6¤×€€Óä ñ•[R½`õU‚WÒHe­ÌñÈ!sI²Ö:j·!óÇnB*Ðú¦Æl~YzæUqÓÚ¨Ö ­çz™ƒÅŽ7ë\ro w,zµk¹ÑéÉ„r€RV/`n¶²º7¥ëÂ3ÈÚÖQ‰íîÚxš7˜$sf ·¥QÛy1·ÛùqbN&+’ ¶2u¯¶^ÈdRÕòDæSÊŽ„‘Ä@gï¼<†[‚Fª–ž!¾€ËZ¯‘Ò(až]]”ÇSŠÞ¼&´%è/8Ø*étJàdHÖ6óĶ1Z.ñyeéÅ KmíP¶ f«×Þ ©ëñYˆ§l<â|ZWÛxÊ”¸aâ-ìÈÖZ[×BU¶ÀÊ–`zþÀ5ÒwÉ@Îu¬WVAU[8óÈx%ugÔ—°Í¶yŒ”émn•)mÉÆÓèE,Œ!|Fò§´UÐX LÁ ¨;@_SÀ-Éf+¥°+lÅÔ=âʉs2‰ÉǪPÐËUYŲ«a¬R·*‚lÑyméP¨%€Q$°*ÇHÑn¯ß$ècòaK‰4p3ÛÊÚJ˜Ö¥gB0“.v²j Êx…=k>Z8TÃÈö4ý=7FÖ6˜ ( ˜×Ù¶.‰FÒSÖš¦Ù*Çñ°áüJ•‘šGVUþ°Q  *æ0 `åÀa{Ê )=޲ yì¾Q#JUu4 H¼Bª.‘Jø Ï¡Q•çf…ÕrÊŸç±¾æaY&"Æ=)冕È*‡MUIóØ*Ág˜y%‰eià‚†C¿ôäœÕZ4=PU¶ª Ûµ£ÛæFS-™^‰‘€ ™mS!ë>”¥&À«R;ÿ4VQ‹æ$ K ™4'1†é/Œ€û2”ª¤Z)µZEÛ0M“ت² Àñ@Ûþý+µºó”­ Æ‘µkKÀ'†Là•x»àºôò“á1LhšR¶ÝHœž€¶0 h$x²p-˜äS–ƒx™ò‘²µÂ™[…ZŒªµ@ú8Pú‚E:ì²”˜>ìëR”Âx} àÛä,4¹õè™÷28Q²¯Í™S7ê‹»U«”4B¹ZL^ªl¼•o0µm®êàZžåNñY·¢.Ô6OÙѸ·zéë=ôþ”:€Ì'ÝJ-­ž”R€Zç´ÂmsÓoõxð~¹ä/åÌxžº0éŽle1@¬¾jÉ€X@ɪš!%2™-¾TåpdŽŒ_/Up·4Y‚lÓÀmùÈòÁïÞ0º`˜§RÖnYkã­ÛÈA*YÃT(µmUÖæ_»NÑ'iT%4œEU4xìÔ@IDATHn \I©|0FYé; ,%Ò4­³µ’Sü<µ”> ` w?Í€¨Ý‹ÕÊ:Z‚4œÉO€!Ð͸ÌH%g¬oØú„>BâÊùH1—…Ze1ã9T…ìÅØ„ª¤"UuEȶÂÄ•·M ·å©éLèùÐ$аšJ ßA2L,+˜´UîP"á~øÙ`:W­ÄdnÍÀ+ïB”cª†‰¥úNh`%æé1]i…[FÌÛ´òw]I@I“»aûןñ)»4æ4‚'\I‚úrD#Àô&ÇP*Dýt‘uêå~`LX!¥U­ŸCemiâ³å‰Œ—p½6jzo¯W££.²éO)dñœÙƨ‹’‚²^5Ê? ˆo«ÓÝÏðZ@P2´liàÖfPȪÈÁú%Îå\›sá¹IÁñpâÌ­<Ý€C±]w|J€¾r€¥ð¨¤-–-šÖ‹@#˜• õkBüj•À=k…¥|ØÚa 'Æ#k$d…yÚî8˜Æ³Ò¨òBU`t÷>ЋÕfÛ¶.²‘[1ú¾­¥^‡v)#WeûΩœ Òj<Àx Jºda+6Ú˜C©5E°Â#¦ÖÜ^•,XÉ*¶R™Ã/ K¥±Òpv½dʵÀ”%Ãë"å!<Üݦ!S‹!<Œ ãÓ·¥mi~¸–XÉž”^n8¾*b[SEÒÄdHÓAâ­â-´åo]ëʹ¥ÌŽ!SnmK,d‹¶VY–˜- ”ç`uKîD¶¯Ó†Q…§´eX•·ô°rÊðyŸîߌô8``›;¯`7ØXeÂÖêâ€Úë¡P—Ë—@C‰ÌÓ‰9½ï ZwB¸3h¤àº¬EÔWÓñdYxAó×UV”ªÖV/›¹¨Jv]­U…Õ+·*4Àêô¸mu„>óJ(­˜d€¦ªºÎ¶"E¶dñ¶›áHï„È…,œÞšÕ&aØé0°¬îÉð¶V)°™¥È¬lmµ“‚eñu¯£UtX+|†»q3ŸesÖEž¨Ü„µ¨K2«,YC®@Ö:Ð$Ö^!)>j1½LlªGOÀxYïj¯±¾MÛ`ªD°°`®6ÆJ©–3+![á”0AéáŽÆœ ™lâüóÉÖÚHÔz‡åƺo£µ*?O1 ÀÄØÎŠIV‰ë¨»*ž¶xâJ°ª”ñ44²Ý0™”‚­HŒ¹ôŸ>éµ3 –-àDåô¥`àÚŸ?ÁMe…E½¬ñÙæ‰¬Ü8[ù0¡ÌRÏ g ¨‘¶Àžl²²Y1_!0¬íÛcÛ‡š§ß¼í4Ì‘<3´òìÑ#3Q Ù€Fõ²b”Ô¶IŽâ{œ‘Z¯QbáìÊ CÐ c<¿õA›3U «Äð¨R¹ñ‡3Lj4º²;fÊæ!c›áÛ®ìÌÍÉ„,5AVÝÛšZ;xóXmKÁÜ*Dª…7ìêÒl¥`ä‚•ÂuÄcÞl[½Š”¶@ß*ødȶ9D ´VØ6C8Ùà²@Û×êô¾o»_*œ!†ÿ}‡ ï¼<]—1²ð|\‚, x3q4LG Phå‰A¼T<ÆÛ˜¢Üé¸Õ±TY¸rJØ*¤Ûu¡áoõGqY)¯h%¶¹é±v½ÌJ˜à³XÑä£C€eù;$Í™ò~qIM“¬”•ƒ”U0”ðÉ0uÔ¹­©r£Qˆ™Õ ðbJ˜˜•ò¸Ñã­[-ú©í»bV¡øHUwðŸ/[dŒã ˜­/8œ±näV#@¨d3”z·0ó¾lçÓ‰¬5¢Ñ—!1 e]6u)JÙ…­ÆZÌ ·'õ*ßvçþûßÿÖ¸&ËC÷˜Ž»5)OÅ(õ° JÖ³t_‚‰o¢î¯DJ>”·âw%`7€ª»¯&ʾ” æÚ/‡EÆAJɯÏTnU€PiUkÛR°v1ÚÆX¹•Êd¶uñè9“峋Jf5mcÃJÄôm«m<øÔT6O`µ•Û&ËÙš2mk†0Ox]v¢•Ï„ÿ+€s#ÈÀ4¼-r†ut!Ýy)xæÏqÃãmé…”ÀÈÚªI-h'"Í3“‰•@ Ä?ú۞3ÜÀ“arÃy‚m1g¬g°¾„½½4>˜9[i2W(Õ*7•UÈÂï/ª: 5L–-+Cë™àú‡YõñÔÖ—`n‘VåÖÜ FÓ$xþdõUã“HY ±­cJY…-«µiÕÊÚZµËÐÑo/H‚®e2 ù‘g$,€ð :ª*Õ„­˜Ržš3šÁ¨ªºk`âYUu'ê’ù[â8NAŒ\#[ÁP¶{¨IV£¶µ°U¿µl+ÿðù'ÜÓéᣢqCPÀ€€)Þ“Fb: ìv8: A¼•RJdÉ8ˆ†ë'“;r¡}‰+yÒÀõª*ž¡è#4%¬P¥#ŒÙR¶YÉ:‘ ‘RéÛZiD[@á»Q’­r¿M1¶”¥ŒÀÎæt'H˜²^MX;7³/ˆÑ”*l­ÖÊce(ÚÆ($àiXkÀ%X#¼Õl½è¶n;)2Ï­Ž@—Z•¥’Y•[…”¨€ySZë›@ŠìÔz²™(Ä[{:d|0™[µ[Ø*´¥‡‰á†W%dÕiüëvm­µP+«\ä#7†”›TXŠ!`K¶s¨‘µ8¦w°Ú)|NƒIf ¬ð͆·rÓT¡#(ÉÁzgù C<çéX–Í“@Ï©EŸ\)äU1ȪjÝåÈî­ètïÏÕkF™-^Øj±+5UƒIÕÈŠiÕîÔ Å5Aö'Õw6)zL@Q9¾cFZû`®$0¤µÔ‚,[Ø4›Ö–³-M²”x¡QJÀv³×øóøVKæÞÊbšÊj}|X¶ Y•’”R1­Ä=£•š"gU#OØÙe1ÂÝb„^™ä)X)eªíÒlSšGÖHEbd«°µ#ÃX¹WÕïcxšjúÄô}«Hu¨Í†Ê ‰‡­‡„ ‰IPÊxH-Š™¦¬µù „B[†0 +jÔ+D ΧWšH®ëVcnkõeIuE”›@yµd¥hŽõ÷wˆÓùÛ› î’Á”€E:[²fÈ-ÛJˆE<°Âªlyf‹yçQ"b¬Ž©ÜYÌCi›Àºû3 %l›!~óè>%g¶¶ô I[u¯©,Õ†çIV-FØŠ¶À_ã s7@Ïs$¾BfÀÇ©­1®÷ùFN̹ڞ2Þ‹ÁjµnŒ’s%­¹Yi¦Ö¶Lª“Z«­\Ö¶C%k+«ûnµ|”¶J¬¶õêÂÒGŸÆ*[‰¬Ó…kW*L)´Î¹¤lJo0d|7I£/Aßžî –âàtüïÿ{ï}ú½_é«Á1b¯c¿n*Y­9o*Y¤Z>UÊQGíl âu©Q%”ªüÈa«Ð.&  Š0Œe[yº"MÛNoUÝäæq´pÙÙ"ÙÚ2Ù©m; FØŠÛÿ,9ÔTÖ¶Z%² oÑç[µÚ·i ™*z[Yg©£kqÏQv@ ¾#mñªò)Ëܶy惡džØ*%´²ÜÜR'²u·Vo7U{kG† #=enl¹)÷¬÷RÅHáßÀ«Åpn87)zD¯½ù`4Rb+:R-¬i{“Ÿo*V‡… w8=MÝ9t.¼`Bï7lY½\Ríµù|”\ FÊEñiH%Œ§Q‹YÊäbV¥š„2ÞJ#e*ÁD—þ0–î€?õ€*¤ç“ [顯cÎi8+ì°éËÂÛ4 S¶*<€/u îs̹ã`zÖ”² ¬l >">7³*>”ÖN‡S"E8C¤S“ ¤÷(Ùú.u™²°* r .ÄB­HÐxÄN³ûÚX7vzbÙ*AÚ6ØH[…(°1R‹¬EYIQm“ëH`ų¢éŒ‚¹×ÆÖGÀJ€¬Ÿ¹U9žk³Õ³[R"\H¤š'CÛ e…myÝ éíÍ“ÆV°M¦×­>‡ÍÁ–­¦”°rkÄ;é^–èÈÊ=}£ >»O‚‚¸#07+½0¢*²H@ùªê¾{«i…H‡âç-1[€f>Ü*‘Mæç;†[@½kÛW xÛæì c•í¤1úÖÓæûmfkl[©Ž™¸§ u™ÿpgÓ2²€ö*sÉ—ˆ‘Í‘‘ÐÄ0åÂ6O¤­òœñM‰Ág.E&à &àE-€HÙ®¦< ðÖ&ê¨ `kʦÂÔZIþß6ð¦Êré p§H=>Ÿ¹éhl±vÉô•X«ºÄé¾á"åw÷󟯃ãð‘«\ wW¶}ŠÊÆ+ù?ºîeK¶¤V¢h£¾Á¿CÿN÷aédqÕ’Éd’ûÞ™çPöÉ|Þ 6T…[›×ÈÀøÅhp}± xV)΋¬D0ÂÈâÛÄ“U 䉧ojHšh¬%õ ˜@Y\ï~ä+içkä#䥉hoz|¸•pÂ¥ÅË›ØOœ¾øœ®֯颀ƒø<ó]‚b¦Ú’y; T‚º8£O– fg'e„xûÔ…O¾‚@?tÓç©á+½ÖPK&U'²Ó ±©VZ@“>ëhá-AeM@–ïNÍàÝ^ë%ÎKшä-ÖŸ!ªºÂϘïyÄ«âÀ›³.%;„ˆqš+.ES§“·*&›¦9šÝpÄÄ1Ã!ønÀ”¼S °J] 2sçR-ª-_é®ö¹%½¤pZy| Àg5J[UWçA#ASÂŽp-õ =<)A#Ú”vßBöö*FcJ5¾´£©jÉk¤†œXÆ8¸ËÁ× d µRÐÅæ¾‚1OÿUP‚0Lú= !D"êt¶^ü·×’p½Gë8qZ¦Fà,žU"âåwR½µ¯%<°.©€‡ë‚Ø„ ©p¥žBL&6gk0Õ»Úç³!ËÉâS#”•:»Ï‚jâG÷Žˆ FËnåLoɳÍ}åÞ*¤T€Ét‰ÓI¡T©SÇ«U;õ–@úæ™ÎDÎŒû¡àÓß”¾ÙAçE  o ¯“*C·M´vkO¾ALŒOGI{Õ‚÷…ÇÁÇ1š½½½Bž‚jÇL-šÆío%L¦„¿YRÕN­‰<)U-Äéøµ­T—j)~RñU-Ð>;ÆÁ.æ; Yí|(@cÍåÙ6·a‘•¨ÕS¯*|#¤âéL¡)ðìL½s¥4íÜéܰSMI n[©€² «Z#~RpÖy¡KäÅÌjüío‘“tw¥äH¤B](€ºSdVNDÚ Ïè« ”èð┓mtÌ+ùùÕ3L ºÌUíð‚¤¥<>Ðæ˜‚í9°K„t4¬ð×àu¡e—ûÇìD˜GnÏ¥@½¦C'åy C# lVsA#Z8æD¤ðùº,)mРɤÀMoVRï,d4· ¬¥*fg¯1}ñ2©)kŒ¦1æRȆ( ˆÄ Ô5YˆÝ¯ªT °G —U-.múîÐô^LÛV¥ªïŽÑÝL¿dè·0eÌžEâTuI}ÙQ Ö¯pU䮺 yC3(¦‡õu Zé?Ÿ…–Ç$ËìC\ f%dx XHØùh]©˜ ¼²F‚Lðr(ãt ZjÌKY½¼•¤˜,ü”ï Ódb4^» ØDúç ¾¿nÂGÆ/^ 9$M„F™öFð1SàSuWb¦‹'ë˜)ÔÒ\RžK›ë‚óJ™Ao^0)%~Sl:·éœYˆÆ¬¤*è[EÕïÙÀÆ¥@œ½:Z¤ŒN×hU:ÀÆ JiÆ?³ïe*%¨%>&õ“,Áw9Þ(RDî"ç!f@†À0}p´ 'Å£µ†@•LJ‘‚x¿#Š{4;lÛõjl1|we"~"øªíV ¯JA‰IÅák¬}„W¡WEIW1Á2Xc>eÕ¶Õ‚&fU#7§ÑðøÀZ¤¡9fU%&>r÷àùÑÌÃñÅIYo÷¬Ô‰§‰É¦&~õí9ðrÏÅn ¼›I¤'‘ŠÛÁ,4–¸@{RâFäZð¥ïÅn½DÐBø,Mq¥œßÿZF#³djªÈR›ÔK„E SìOào©¡‡Ð´€TKŸqRF4âÒÐúÎÇ´íKDºw©v8K2ÒWÎ& Š‘o÷qÅ|OÁ nF­#Çì„Üæ‚ø˜ûw|UˆYiÚüh}¦¦Ácæ¥ML*}„Ö#‹óÇ¿þõ/›iKZŠíîtê¯M'Ch9*¡¬ßì<6|A´^ ”)¨¦`4„Ý ?dž´%_ãd+Áô#¡,îÆÅ‰#ðø”|:Gë¿­“ÂYÅb],Ð )Ê⎟rï¥ÞGŒÃTû>PÓ®´% ¬Ž“½k|±Ï;G3>ü.øÙ°UwKuE¨DØ…ôrôŒv?v@h=Aiw›líz™¸”·2P/5.f®¸é<”–¦@ðA‡éïuµd¿ t„-™rjhºØcŠÀ#0`v–{~Å,æ7×8|£·‘V%¡YâÚJÊÐòpAoHÕVÒÞ·ÞVÕb ²3‘-Œ–Ž®§Y­ܯb8ôuUmÉ@:Ýeãx%8¾¸.¨ ­X—A .fñU)ki¢XÀBÐܧÝâ»ü×ÖhKªÑ|ßøp‚ÒdIu@½gÞ×(0{êBó&ª‡7‘ Aµ0¦प&Ïpì D£TŒé'ã#°d âw'Z(­ï—ƒwÍ¥yÖJIiÇw!‚mŽI ¶¼Øh©“Bgá¥ÀZÄ&JÙþãBF®Ý2ÿùÏZÀzþq|o£€¥\°S1¨5€ÖÐëBèìzw™˜Æ1Lq«àëÚzôOY* ¥‹Nµq˜¶ª:ÌÕÚ-#ÖË+µþYå¾6Mĉ&eJ@që‰!K'Rº§¦¥¡Z*ñIAv©ãà‹µdqĵ7…ßÐ¥ÚÄ Ö‚ù’cª‡×.] ~ùÒÎR£ûÔ‰Æ÷ ©FÐ É«‘„nœàtÞýÅ—~Þ‡ž{Ï1…¯KÀtÐùs€¯7¦GÊ”RNa²p/áŽÙñkLM)-˜Jýˆ‰ t„ÀDLAТD©òKC2ävÃÇüÒ©îÈo.ĉ@„AÒQµ3f»ñJÑêB6ôׯ=JWæè¨²Ž\êÁAè·@ã.듵.AÓõ‘yß ˜5¶Œ IQV𬃷[#B|úÚÓAÆ/Õ‚f–*ñD¤í\ AWhç•x|V 1®”¬Ô_Ju±NªWÜt1ŽÔ¸~úë2«žATSÌtIÿøç?ÿiª[áis O=×,À1ŸéÅä! 'PS*îj´#HñiR“~öø~xÒÁÑÒJ‰ó–d•6W»'-µŒ‰ªb"FŠq´S(1´–ÑŸ)#\âçÏ<µ‡ŒƒIŸOÍt%LÓ@f.s(ÞÂõòñùwG¦/…7‚Z]Ò—OYõ,t ^{Êõ*"Û‰lÞ]Õ¨«ß”‚>>„ó¼V œá‹©½"ïJz¥˜zq¤V‚¤É+ÕγÄÉÞiÇmOUéeWŒ‰À“õèÛGɬzUYæ¶y³ÚS@'ŽÒG×ÁÝaúp½¿¾ï:]„n¦£Q ÖË\µ} N¡‹,k™Zàíàck£Q`@¾Fߪ(ó$Mq³R¸ã4Ë‚Æñªà}鳘ºØ-ð›^Už¥Ðn–1šU’ ¤£ms"‡ýý ÓÄ´ÏYâÞÁ<‚3ÜnÄ Þ}çœßÏT]-Æ“bþ]UÛšqKUµ4±²^<4)2Ð;d@%§Óe®!"vÕ}"Š”ÏCè§)-zÍ‹ßbh©ÁõvØZÆi4ÿš*‹FÜO)í6ék˜²’‰nFl„”%R5±vvîý^\€\‚õ"¥!Z´ ͳÊ5C]fG&ˆ–i ðZ Jé¨ò™.Õùf·0N´µH“Âë¨Fë ¤Y»I=ߎ/Þ>¤4&®¤—†hÇÙdj ­1©iJßã`fðŒ,¿[à í tãÓŒ3o£éà¼ß ó[h±½R‚†"ˆ!ðD¦Ð¥ùIhb%nÆæø¤öž•¬*h Bw+í¹ØG#Z‚&}HédÛ×B¤ÑÝò~pq â–w| ¨ŠÎDè°– œ‚ •ÚA5K_µãwX%Ê-J7W»j-¥bÜbð{¬þgy”>“f)2#˜Å¥¬ƒ@ǬK5‹ TŠÙÆ©ÒÔÕVk-Mt8ß_ë¨ÂÍ…h¿ëœ¯¸b'bZÒÄCôŠóì<{†j‰xÊpžœJ02œ_ ª‘Çl0&“ò“jg ÙQü¾ÐdÖs÷û#l-¼’GŒ/n\úí¯«)h ÍbM„„¦‘xÊ_M6½C‰#·и&BU ê XâUueª! ëZ”=>]N„ dÄ6Is>þR_¸ÈÒFtÏo¯82e&v ¿= vð¿•&°)%ÖË÷*vÉ<Ñ0™F í©î]¥o+UR­—?P4¬ä{ÖÅWøç-¬U·!„h1®´í ¥³ÝZ@jrO‡`çAŠ ‚¸TU@ !æ­|þ–ѵ û3gûÐ7Èéàhkt3h&6+5d)£•,ÆÓÁœ!+ x|&`NDJ`4?Sc½@ûت)m…ææ5¥µ¯—²ÊL@į콊˜3àûOAoûHÓ‘"wÀR]Û}N'Pbbdžê*¬­*U]N 5SE†³Û}\8_;ržI_;ÍßÏŽÞ⼓zÅVEoÇ„) *mœ4Kä›ÿ´וi·@© ™Þž¹mÞxzÅãt“¶%®Ä·pÊM´³Õö×Õ´f¸YªÖÄWbâ˜éW ·LkS¸Üóo\-ÜÐvNmšÀÖÐd©õ •R0³Äª– YˆC¨·_~ÄxÖS‹œ²}"85¯\Ð…ðbH„ÎcvQ®‚&S3úWì\Z§NP‰Ž8¾ª˜´ íÍ‚wQ8y„ø„‰ Uj+%üz1áPjúbS2v‹io\]ð˜8]‰¤=ÍtjW@Ø™q/“)Ñì{u‡úóP-˜|-‚¤0[©óWÂw‡Å¼mUyq˸^:i 8m… ÀTêZ¤m"`píÑœåüKÀÉI\‡oa©ÀH¤„ò;UÍ¥‰¦KšÁñ!h¥öŠÓ¬Å ²z½8R´†Jñ;j:b†\À#ÏÞRãbPNm½ ­],ˆÏ³ºj‘¶À­œéºØÂ šR»czBèÙ×Þû$ž²Aïñ]f÷©‹)U5‹ZÖÕQ¤£EÐAH;KüªF›§^žb2ivÇióöÜ OŠ¡ñªÖËÚÈRU #ÇD€¤ † °l+d8)&À‡°ÚÖÃc^Öù}%Â…O¡jg¤V;/n^/Ѓ0U&˜š€PàB ò•T™&оc ¬/ˆÏ¿"Z†`JUÓ|ù@Ï¢)h¬ƒ“m(Ï4*%˜ÿêK·ÞVŠÓ8ƒ˜R—£”l XÉ¢b+dT)~íF„D¸ðç·çÅÑ´Ÿ Åû\ã;®‘¬se« 2²âÈÒâVªRxωX^  DçûNHS‚ŒÞYvöJùé×N_»9}½=ß”[  IœT#.Ç?¸ßïÓÀÙï+41ãç!LlÌRÓ™p‚#è^Õ Uv'·ïóEo«VMYÜž8ïDÀp|:8Íæ!”yUÌW¹•øÈž…X;ß_}ÃDàY´â»ÅÏzKµ¼Ck$%e¦H”™ØÂÀô;E²@8"Ào[Uçm=q–f² ñÈéÔÕæ.SJ“WM¼÷ AàÅóÛB—l‡“öY‹“TÕ-€§i´RO­*pGPmωT…ÍkÔžÕÎKÛ¤ Íy¦…§6~dQÐ1oÓùÍŒ –ÚŠïí­=å_ÉÏ%í´tº ‚nÒ1kk 0A (1EÊ“b‘ÃK›(Ž¡. q~HGVÊ”˜éá&ò žm®•’ø¾.ZO;„ ’xßHÒzûá<§zþÞ§qLÕJÔìi%é-žéáJ=)i;SŸgJÅÛ‚mï5‡Ð= `g5b à¦HÛ­F)!þ‚&ò”ñáG6K#ßG†¬©•yg)Ef­Š/ÝÎb8œo±)KÍ”ªçõƒŒaR¼NH.0œ„ò<¼ºÛ°5ÒÔÔX€Lj¬·ØÎÞýŠÐ2ªµ·¼’ ¡”‡Ä¯]Ê:ˆG&¶yCÞ=ž,Sª]@¡SCÄ•œâÕ ŒÙô J ¦V —u.k8¦F¦Å2Œr;˜+`p¤ÆˆkY¼NjUÍ¢ÔC 5úÊœC úº¨‘o¨gä÷g¥ž,OÇb<Üèö)U’峦ˆwÓó·påÄq@"ç:¾?µÛ-\I1™Ž®õ¦<r8A©F± Ôò¾réŃkÇÑÈ’jW×a¥pVcâÈdYUƒJù˜ùî™ÔçßP@ÚêRµD R–D^Ú0ó²hb³5¶=š °)³YríK‘ᮣŠȢÅ7wk¤ k8¦Æ!ðÈ|¦%ò|Èü—øy_¥˜3»aaÐZŠÙ1U{‚À.–ÔëâÝISø>¨º|nca‰ÛAP#©4¥,œß-!”ê¢ e˜öÁˆCª"KÅ™.4»ñ˜o¦ÎÖ¶p;ôÿŠçkNÉA0S t¼x:5&Åã#gRfÄl]_Êçg4L1ëN]ÊCZÀ¹2«Ö‹™¹=ˆ˜‹¬·%IáŠÖZ\DWâ-†Æ zé‡`J5RÖ;šTïÖ®W \Ì‹«Š²ÞÔJ¾yÉ ¤ªq €,$MéÏ tÄ5 Y ÷ÿõÒØUã°Öð’¤c q%² ’ŠYÊÅÆðªJ‚³ß=×ËQm÷šÕ>R–xw¥]5¼ !ÄÏ]\SÂÌÍSܤ ŽÜ§8>Ïj¯‘7—BoW Kƒ#C^K4ˆ*C·L]R;DàýÖÕO\í¶*­E{ÿ4¼ýµðuY¥¯xéKó-ÓD J[LÜDÓ«¢Ù³/‡y%8òØMÕbZhº.L%8¤Æf54>CÀl+ >Œ˜ Rµ•vHsTy8Ï´Ï à•œEI¬‹‰³8Fî:çKÀzÝCL£Ôq^i‡­¤Eɨdž‘Ūy]o 2|„8¥ÄC!h¸­çñÙYlè–l´[…×Ë«– œN#šmFÔËCRK¹gW;äÝdÊyN9M‚LÌ´3)ýR±û ”ôJu‘õ¡èmi7U—$².L:p&æQbhqi´øÕöìmÔn®•ümšªÃqí–1]cx'U"˜N£§¿ÒDš_`3¿–)Ç”zëLé[ˆéf('1WÚÛ{Ú¾¿´O;„ß”!ô5¢ ŠÑTäñ×Õ8 Ãazñy1‚ÑZ†+éekLvˆÓþ#§ /À¯åîço2 &GÓ%†óª<ƒ ˜è•¤¼…÷¤=Ù-d R«2AÊyH÷ ¢jbMlCümrþ’ksÏ¥ôý˜ŠþöNBÊ6U!³bL:h1#nDPÐ*pUoÛ@³ µS“Z"Ö%eÅUÉ ´³®@o©óo×…œö,2þÒ‘,ÐJÅ||[9…ÑR¾@ìÅr“Ò!z!ö0:ŪtøœBO³s‰µÃÝjAwEÜD>ƒ#tAñªã(ANÿ51… €Ã×%èì–i=4ßn<¼M”¤Ø tàg¿{ùühZ´ó´(9/²í öžð8˜H?Á¦Cèðº¼*kC½ «WP•{v!®•|R€ýÕ¦ FãH)õ}Ú竵“âK¼U‚¬"‹YG[¯˜2މIémn4)Ï”Ž•”€Õ©Åd8í]j–Ôt1óvð+TwØôy"ðí †HuY»ÑÀ¤ñ!í“—f¥8æB¤â·÷Å©Iº„J|»^U3âDÞJhýJIá#[^€PÉ­ ¤Tõ»õÙ³µ<ç)óÞJú@jq¤Iéb­§”)Q†k!R,UµžoZx£Kq2©^U)æ5FH³é(ÁíÀ7tq|jZ”è#×È38Ÿw½oµ’#£ÑÉÄMô¤Z’&ÐÛ”@o7(î÷{Õ¦è¥C„gææ5^àó‰kzÇ©´ ÛØR³X-h,_*Ö¤l\ÒJAûv6Ç3ǯ±åSÓËŒøe@ü×#ÐçOÃýÇÒ¤æÒø/…Lt½î–>!bq ô‘3]hY‚LÐ8F‚ì SHVŽœ%¹}Ÿm+5+<ýÆ©6A;0Ž5¤¦ 49æªí³!ò¤:B)k+ÈÒ@½‚Ú§—õ+V].Ózm%f–©T»˜HœJR¥U#oÊ&¶¡F¦‘ò^ûž,&ó ïØÏÏP¥>­ö¤Ì«ºU8AP`:µF1BÊ‹[¸F?ùn¸*‘RüPb˜ªáJP`"M%òËôF¾2A3+¯Ú¯f9å6GЂÓÝêJ³Ñæ*áÄçõÖi"ß’SëPh4£%Uã+RKoHÛ’Ò‚ÃÄVíy…ã×¢ŠO߃€hÉz|þ´ ÄäÏÿ (T¢A'ˆ÷ìI˜!Õi?9¥š#óá |.,­…rx‚@C{¥:¼’»‹l“8Û*©||±Ýøn ŽX êVªw›HÑxH†¿UÅ žTÇQep»eqÐMDØ Ç©‘o½&&¢«ÞW“¬ª’A ÔΜ”# )¥ÃÃ3qkÍ“òE,Ài;3¶¹¥a~4ˆÑ<>‚â~û÷C´ÛЉ˜}öÒäk‡3d)e+ñÛIÃáÓÔÒ·Uµªp†ÖÂ+YOÀñÚzk§ ˜I‘©éu8¤“š"6H:hNаF_‰TÒ¢ÊЀ½-)eÒ®K¹JtÚg]Íí°DTYã®ØÑgmâ §½‹´C¥Ï3]–çqâ¡kª6t%AC¥g‰kèY½=²˜ÖÔŽ££ãÇüHÜÿ@›¤Zö‰B¬ÚÎJãÐì‰ ˆáȆ6Q *¥™¾4M!/Ð¥×\×(è!N™NÖ 4Ñ\WSxä84“EÀ¤¬i1->,˜á5ÞŽ³P‹ÃêGƒH[F€ ±ª{fg" Î’… ¤­!@(æà„ó­ÚqJM¤£×\-Rl4Zãø4!ª|©‹ÕÒí½$µÀ[ÏÁiÑ=lp <ÓBŸT#jÄ”"ð‰ pàbD*ÙRÕ&“…ÜiçY$ò6ªÂ‘»®5¢ÕKÐIö߯œaßOz'}5[ohßzÔô6NðŠ÷*Cðt]u1ríp âî§–@Èôë‚3àøvî©í ÚÁ¥-™¸’à]áŠ}^°âé8µ* ÕôÄÝ’”ÅL0²F/›m“âYí5&åÔpÕÀ8ân Óud÷Ù ^L¤–ôq¢Mp-R£‰µCФl:ÔT$P— DUªë?o5„QkgŸ1ƒ×’‚ßÚ] & ,“B·× ^Õ ºÛ™48Z‚JöIäÝÎù”;à<…JF¡ NómÌë2šj—™r ´|"ÕV­½ø‚öWÒX0Ÿ BC¥l|4F¤Þ4!@£™«p‡—x¾ÉÅUy)œ FépJÔ)üa=»¦ógŸ¿üå/"Ö³tiÏÒ`*—nãªkl)³ƒ§I¡Ã´td:ÈZp1_)M UÛ¤…{Bº €¥¼®yU~ÌñÓ9‘@™¸Mj‰@Ê dC"㲞j'CÒñ`"·¹{`é×%nSÕ®W•2A7 Íé“õ¼”jÁ×(mC´ŒB¸ R:º¼ºA0‚È·€€Í¾†ÌTíÀÛ­;is`©RL{jí—NžYo§Æ„èJ02€ÖØ€ˆñ *‰µ L3ÔÎðÒ6¡³¢†óïyu”¦@5M1¢³„Ä"÷OWOv©XâSV¥c¾[ª‘gªoPûð”z£uºîÊOªû¬ZêÎÓáñ[@,èq §ÃÃYASÄ g¸ } nCµ5-Ö°óú¡áDF³XPc4žˆ^ÁpR ¿qÎ(Ý›&† ±F uë1‰UÚékm~e!NRÔªk¿õã¤fb2hb 8¤Àh%«Ú'5Ì»ÔÙÊ”VíºtAò˜îÇOâZÒ×KpúÊÀºÈéhŒ Ünhp4²ðRƒg­D„uR²~OEö+ŽßAš ™,\l:`öZFîZRhUú,„×®1qžu'ÈpûØ È7®¿Ë~~·ÏZ”Bê-æ3 £ÆCl8~GPšÝÎôv@Ð"Õ¢1ГØJWüµM$t ‚µwð‘õ¦¯+~íhÒëNlHʵëó®Q¯ªB—‰/eª¼|–üõ¯%ÚKÐBÒË<ïÍaÜÇ !°mR1ž©Qª i°-)´7¹ŸQUÒå €ÇI8f:qì† N-¾ÞÎ’ˆ á–‘Šë…HóÑ,³U#PÎ@9šÞpiH Ä>8Œx"öCrˆUA¾Ë‘’í\u‰I½ÇiU-È)©ß32]ÈL Š#Ž)uÌ@KgÒvp:L^»´jšÒ6T…t¨˜®Î 3¾.qw+n~×%~,[»R+ v³nýçÒb=‹M¬JŠHkØÐz|jùJÅöDè~4j‡Xȳ ÚŸŽªö ŠSC BÍÛ¹%õÒah‘ßH§ý-ߺZ¬Ñp4 A—–”TLÄÎ E¾3Ïw#k[àkô_S"¡õ|xékBˆXCÚÎ]fÙ^;¬‘W*¥'¤­&E¤o•)÷¦Iµ³¦tR‘¥)äÓÄ´ÀÔÚÿWà:QË7 'R+Æ´¹X@\q©Mx4d8t·p4Ùªp´^qÒ-peŽKG@*›²ûk¤ °["t ðßãà@šR\ ‘fÎ’l`M/%Ë0á>&bú¥Ÿþï’ñµ§À+µªµ‰ð®“”ªYZ ÚdúݵÐé ™2¦˜à¦·¹Tï ‡/æu1Ðzí³AÀÄÅý×B Hÿ—?Ô;b½é‘MÑ+P¥Ðz-,n%%4÷Ó ð¯öy¾˜éW ðM—¾kàwoqê2qgQH™ö³úÝ£eðÉŠ­§d«ø %’¥ÀŸ1×ôâ¿ø/M5o„qºjLSlz›˜¥Ý>˜ª¥JLœÎí>'ÂÄi4d)vdƒèð­#o1dÓ¡Ä”êB6¥Úi8 „Àź <8àù€*uÒT㳪։ôaLëKÿ¼ñRþJœ$µù4©õ)M–‡w‚4ä5ÒÙÜÍZ¯êËitUíÉÖ•¤–æòµ«Â³¶¬R‚1ÛSöô:}q4q·ß1§“2j|&ÞD‚$#› œ ëeéÃSô/˜{ÄU‘SíDÀÔ€_áϯÈéµEØ>‚-SI3Ž,î'½)ÓÇüïÞ°o¾¸­J­*Z§p-Ô¤uE Bë‘U’ ²ø!Ȧ3`x#ÄySx´ŠÈ/†S®Å¬­ü–cI4‡êìR%SZÞVŽŒ`¨¸é©¡±bUš6îàb C ²[t %x„Ò@²w\ÊÑŒc‰[cdeÌÞ[diÈ8R]ȶÅlˆ*ëàºÄÎØ÷‰®[üü$SÅoaxÓÛŸµ@bíR‚mUÉDjRÕ­× øL© ©½/Ø&ª ¹ g-ÞJR‰”õÌrL½bU`ÓÅÄ¥J1D#„&U‰‚õ”Dœfk½fÀRíJ»vÞòºüßZz¬ÒŽ)Å”jQ0‚b|ñ8u‰{jþŸ€1;;š? ПB"ÒL—•õš%ÅwLiˆ/´R|Õf)un† ¸’Ø=Hiîf”Ö ¼ÂçÍ”¤‚üÅ>j⺄Éá©ej)ØVZUÌU!Ìiú–Ö‰ H!ðÌ»›»½º®Òç¹àHùNÔ¢AØv.M§)4|Þí)-E ¶vAó˜d« šÕ“ã8Ÿ>2“F+m+Þˆ, eº ü˜@)0»›_™ŸÌpF ­­#`v¥é¬¥›1z³ $˿խ i¢q¦H‰[€lH‰0ç!hÀŽ?Íh½-^ )& §À b¾FgÕø¦ÐQbÈ%i ‚Ô´Oó6}4»1%²{åš…Ö‡·F¾ e›Îã›Åœz*IZ˜‰âÞ µ  ^KÓƦ¬Å”=šduáÁKµÃcæ¥@¥p:ö9Kð¿ä@S´°K<ÏEÌ3üFw®NªÚ 4Ž·¤ûklʽ$ÒZèDN0&N'‡#³VEè]’RPµ$¤&M£µs½ …K)ëÅÔØ #wvAÌR“jD³Në%‰3&2e¾ÝúÑÓ&qàR8ÎN–ECç„iT…óºÐÄÖèìRÅJGåûí S{"é#‘á!1S_ãÄ@½øÃ[¦Ni½¼ ‰™ïÞ((1d^Ê:#dË ' ©ê\FhI­ÞÒ˜â$©†JMQm„´Ÿ#zy–þDÚÐ)ˆ0¿ÕµIL>A´î‡7¥ªÀcmy›G®š~O“§ÌK{‘¡]lÊ¥ l„JR%8H^s t@é‹r¸•ļ˜A•‰C¿‡Õ¨ a˜·ãóFmÉ5b²8‘Óèݦ“¦œ¸*C“ªŠùÖÃw·¼ãÀ¡ÊÄ)ˆuUå[c¸ ç“íµ§Ðs´v›Ÿ1_SÅoa‹¶¸RtS T kÉ› GƒSNª1§ƒO³€gªÑR§­R4H%)œ”)Þs'í)¸U8\•M$Z ½·ÍåÑ’ô©¡ï ¤Pm`³¤yÓOìßõÍ®¹~b-A«Ób]“þ=¶pFNª¥¥bÌD¤¬íÑžD%½^š‚!ÄЪґÛ'|iA¨š‚éNª÷.r‰R;ðªÌµ: €ùÒøâK?› *¥SIœN½81­ÑévsEð_ú•TµÅ1ùp:Iפ­g´Øsä_‘6äJU·8?k±º¬!h±FAí& šn“ôùZÎîùÙ ê’ý„ ~ ×µÑv#È6”°”²”ÏÖ«ÚJp±ëÄ<§½¯¤éé7´^~`H‚Z¢ à•xG&+p4ÏÆ×ÌõŸ|C¤£$àû㈉´í4S ËÞéÁgµÅZ¤ø©ñR~g¬·*ÐE€Ü9?_÷˜@‚µ8`úáJíDÂð™Øû€ÆTÔE)¡##hDÓg‰×>È€F°ªùUtšU h¨¸%©á§Ð8 C1íÈY%~)©8t˜8+½Ûý|¿ëUU‚ ¤f±î*eï0Ìd-#À„w %§Û»´þ„†É0»Ì¤(k„cBü•[R-ib¥n[©.ÿB]Rš†ê344œhõÂl#ôú°wR tâc¶ª+UíÔ•Ð!ÀÙ\²†VÅÄñ5 ˜“J•Äç‚î{kÐ׎FøQ2¥e”Ähq’¥×ÅÄv‹ *à·@|dAž~´ZlÎè•pL³Øð˜KMEܬ_¤–¯Hœœá7 ˜B%žÔá}_תu5T¬*¦ÎÞ^#¬_`·öTÒr–ø^£@I{;ó½œz/÷óÎwdži13K‚ß/@ĉà‹-S£ÄÈK‘ÑÚ`:8º” Uyq§ÞÜ‚ðñuy0µPë•xFÌ\%Hšb½ðt¤b  áðª .ÎÄÈqÄJq;Nãøf ’Rh°^x CLÇÁWbR㤠Š=¯4«*±ºø‚FˆÇ4¹Ø&Š©]ã¤|pãt­Ž3ÛÁhDª7f¥µñªë•bîêZúJñ  $ÅÙA )ðD2 €M‹wµ¯88ÂŽÖ]…¸À›CsïUœvÐ«Š–>š­€F@JùMo™l‡ó¿DÝǵWDFBKjj ‰T òfâÚU»^ió"é´_+òJLЬ¹í=þZÒW5¢).ˆ 8)ˆ4W´›8ÃÑh=C§Ð¸­Ú,œ®q"@Áv躾ÎPíÄyoh©*YÞª8¥Ý­T‰ tÁK_P¬·ª3ÚÈõÚ¤} ÞãêrjVåÃq€ui±j?}źpðY¾ œÏZLÕÒËýÙ*ŽB"F JVê‹X#¼­*©ÀÅ<ƒ$RUª%|©¸#8oœÖSJ'œ`Ë[FÀ=Ç MŒ–dÖÐJéoIˆ‹•ö½|µ?ÿ%ƒžo„TÀÑËRP…3R@!‚­!Õa‚ªâð.JìÔ,4:Œe©qñzM]ÅéLÁáö¬—‡ Cj¹sÎõ g˜YäŽo ÕÞÀ޳­(´F:6Ä\lœ4Aq¸”x v-©EŽÿzÕsòç»´XoÇÙ˜Öc½TDXçÕ‚W ô‘Tê‚8)NUAœ”y´tZFõ%¨â@âã@ìVþz8æßöº^Öª|¸®‚d»:UÇQê8¼t³íVãÑÒ¬KÕUìÔhFp^gô]¬`ë%Ût2ßȪñ)°bR¾QÅ¥h-–Á’-ÜGÙÿp F=¤MíÑBXq¨ŽÓˆ¦‹é‡èm¶– ‚#—ŠCødz ­=0ÎÛ˜Tï.µôÑÄÛÊk —ŽÐž|4íôI±žŽÀzáÛ>Sj®ªx{1ò8‚®.B;  )ÅÜ]¥i 4A”T50_{Rv0ņLÌâ7nII™ÒzDªK»|ƒ.÷¬ºMÚ¹TUË ðû…Ð| ø¢?·8¸^|8/E#2rƒ6žé²dWÑ› 7ô=EÊU#ãã¬ý2 k+s_5©ÔT;l]ª  «FïÅÀifU)‚˜Bo)D5lù RÊöÚ'…Ùo¦ˆY]ªìfD±[57)C¦Y šð]C»*q¾F)hR²<~÷TPW-‘ñ:õ˜Ú¯Êk©‹×ÈÇÑb¥Žl1qLi«âˆ“Ò•þgÑgœ`»ÑÁL¼qªV…o1S¤á@—I6š´YÒYßãh­g„’Y<°¸®FòÈT•ÚG•)…ˆ na±*KÓòýÆæg<2&Ãdhë- GÀìM“&eâ‚@}².@Sµ´û§ QÝ÷C85fVä)`â3Õ¼Mˆø—¤b¾®sÎ{Òhø!mÂg”g›Ž)&+eRgÁ'…LJ,èéJ«ŠÀ®®*)߃«ŠÉˆ°^©vk„!ŪYâÀÈ8V:ßA}O¦FGµhÒm3¯ªDS‹çb\Ì››BŸ¥ð"ó@ÞL-ág®?@±–\Ôf÷Å­ß«gáZ–@y:Œ¯%„gRUþvœ{/®ØVpLx:•Ä1Ã¥# ºšñU_Ábš;r%ín“š´‡úNÔ"m1½b_£€onAïý±oø)L“_;Ú«fC0>k¨eL©D!‘åÑÂ!¤ƒ *åÙºTц`ÖÕ”®îUÌӠ5„SÛW°ÔëÈ3WÄÓ¹ÙçóÜÜ!ò;©5Ú³µÛA,¨ÓO¦½£y#’ „€‚×Ú„”ApqG£ü^‚RÓµX©ÅZbh U" ÒÐÍ¥ ÷ÑW‹M32DÚD-džIcЉ,fp€<ñ N¹A¤" g}}ôÑÀa¤j£]ìsmXËy~_ôôÅ"ß2Ä æµ#Ø¡@,Èî:çŒÅªDÚÇq¤ºbò˜µ41Áb¾”HŸÙZêÕïz‰·í¦K3NO ¿w»*‰ÓTbÔÜŒF¦Eµv)©ó¥mK¹Y!=Á˜!ÄI±˜–Á¹+œ{£aÈž‹ŸgD€Èü†hÔ(¶yR¼)z×B„‚éx£½Õ1D@§vÓµØØJS+Ö(`Ml¦øŒã'W–DaÍ 1Ž‚R|‹±¼kÙÚÚ›+0 N'K„g´L*h.M±ª«ÄU˜À«òµ˜‹£”õã¨2%²<&pOJ\o]ºfËJ×N â¢ô6q¾UUq4 j"r u§*FFèÈ@i›ô2à4N§ö¤û‰L‡‰U‰ô´dbjâëRKÂ¥!-ðé¹ä>d+iIœZ-›k@±«˜¦µUY ãì÷+› ðñµP¸Mç…SÞÑø‚8ZX‹ñ^µ˜ DZ#æyÞß ‚¾•ÌŒï*€øzù^xU†ywކI¹YÂÄ‘5&Õ”JUµgæU * IV*ø6ýþϳÆzÅž¾’5ê…gަ lCA4`¯S —Š3¥ bÎ!¹¸ĉ E M(ج B<¸R¿ý7º#%@žM|øù<ë¡âF”A¬þv/ЦÚQÅ*=l M‚k Ÿ`ãë ¶h¥|'¡O™áÀ_¦tkŒ ØW*ŽMœ (æÀýœàý&N½h©9¯qZêj:_ûP5±vKÔØ¯¡)÷à Mº=…ªiöš’Ü\¾«æÅ6çõÝuEÐB!Ä A½ªJL¢×žb N ¯4µR“a®]J\Wר‰V=Bß Ðð»j§îV­¥eâð¦#èR’V é’6Næùµ¶•il+q¾SàÓÏ×=~ÁÒȘl%úÝp 4N‡¾3ÚÙW'„‰ó]jé˜â¾a¥tM$%†°Èg‰ûJì¤Äñ8¤ÌïVMLÂjIYŠ|áϯøDt¥¦Ë ª­Ç3Hżu‰‡hl\¦"¬E`bO§ þA)NU¾ejÙ8)Útà˜Ž1W;‹£Ana ý¥øÑxœbU"l"ð1UÅí VJÊaán€×ËÇ„#¤l¢KÓ+ˆ§“¬4òÒ‚Ž $m1²‚¦œuﳓ618›G—&Þ_XÚv% eiûÐt'⦠¼fþÅ€Öv´6X/°7D/ÄDÿ°¾@JYU¯T—/ ‹Aà ¯$ÆW’6  |üªhDúˆ ßUÇרN“œ‡¤É[žH%"¾¡S‹¬wÛ*bâ3Õb¸}Z hÛ½h™ªÓgMäY´8ȪD€—øy¥¥•T=/i%ÇYuS•GÃ'+@Ó$…ix ðbR1õBЪ–v½æÒ¡ ÖB™ Z ¤¹)#³t â¼®Ñ Lo¾)â«}žT è!ªJáRVš~DènU1©)AxÈ;Nì–º¨WYËÛ[#)›óJÌtí‡x1&‚ dÈ@¦:¸*¦ÿî«/ý<?ñ} œ¨CéeQÐ’š´€×å tÒŒéËÁ S¯¹ó­Á3HÜ’ü¬éR½‘ BŠqêÍ“²C²•§ÙMD+]Õ àwXñ0qJÅSxF!õÓW´í8ª˜|³ªò»:12NÊpHdjÀF ÌRÂÄo®’ŽP Äô ·‚¨=ódUÅp†Püóƒ-6]VZÚz-´™” rSém©@‰#áÛ&NúðV Èòu­T/Âpqí| o\½–êb ” ˆ õZ'—&•²ð r´R—@6°‰Öfð~€Uâµä[©§Ñ¥DŠ7ìWjÕr›˜ýN Ì€[ƒ ¼å{Fð&n -p〪L/$PÂ×(ÆéD#à´³@•2³%üîM Ê¤¶ĬQo]Òðd‘C¢_/üª~^ni£ÃaR¯7r]á‹¥UçC"Ì™´ƒ”2¤ð:rPÐÞŠµïŠÓB “ÄæùR ™…`f©á{‹\¬*&ïåìÝyâ hªâ3ñu~s“U¢ fJRâpŸ# >2Ò@)‚„ ̹(hÂét+Ç5zi—â#¹kp#¨m"Deüž»ACš…y½®m¹-æâD¢‰õZÃ,g ì'¨GÀgÉöpCºL½!tLìì oÊÖÀ,N-f7)^Š–,Ä-””´U¤ü€os"ªögÈI5Y°%u! Qî+ 9r+C¶¿¡n ß)DnŸt(7±YÔtáøøl r„Ò×àøÞ Ï¦즚© ¨b2LHU;ß,>ë®jììá˜,Üò@:v¢ ŒcÒJuYF4=5ˆ4œš*œ·yâ¥J¬Í= g44ƒc¶d‹Á¥|š‚½Ö«*ÐÛãëÒNÖP„6Šãˆ³&ŠáN$eh;œ!À &"íNL¯º#Hµt®b)2kAh¤ôº™N$mJ-‘½øU-â¤è#0¥­AMUŠ©„Üý!¬Mæ!dñݳY¬ªw"z3LFSUÐ%,Ö%h1çŠÀ&…VŒ©ÔÐ>‰/¶˜ÏµØ—ƒ‰©Å©ÂĬ®Mk”v.ƒÌ"hÔ«$¡TW†#»„®.™}»òS°[<#Ó©tEžZœÉJß}ð7hs[f‚íÌû¾ld‘ìÔ6«öɶ€e˜.jb-@²é^€¥\{ÿ,ñý¢j”¶*é¤{Z>j’4xð;’ýpU±%Ī|¯ŽŠ®öÞ<Ò Ö«…é­Q@ª…Ä,§@5ˆ¹È£M¤{©´µ[ÃJu©&².ÁÎÒu`6e%"ºœÎ&"Ƙ"È”tiiD%-h ¾}‚º Á!Ò’ÀªµtííÆ³hSXF£M’-~Ï"ÐŽÖ'Ø2|%5é ^Y;ÇÒ‘6NÚ¨BZ ¨«sµ5·ä§¸F–8¯*E³Ö¨® l i²kGƒ„ÔÒ!ö©JD€_‹Rsëú5b©jBA¤Ž¶«äMPuFA÷S—‰@o¦›àð-&°*rÌ<}L¸Toüzyk·R¸tœVêàúCé p)Ÿ¸^ ,¼ÍÚ’ª8Ž©—Á ìÍGî6 t —{È;‹ ]Žj†Ð\j§ÀÒTÁ4;¤*²@©.Õ|"Gúª%«B¤XÐJpR|xF®·˜¯·Gï\û2„´ ¶ÚÕ%ëÒ(» fa6Ù½Ml7¦TUÒ†)eÂ\#´ØÊhSÄJ¼gQW8ßw&eúM¤#nçMo.`/¹ö] R ×Ë+ily½Å<æÒZ À0KÚ¼¹|ƒ´ 8f &5Õ|)Sª…t¿|+¥†ï¿ÜÀÜ¥áH/÷81Óδ°¥bƒ q.÷üÉß}ö)˜Õ¸4·¡4©ŽS’2qL1ÏRà¬jB¾é­Q{HÞJ5â ¨½;§¯š¬®öi%šºB£Æ£Ýì8Ujñ“Ú¶Rq-†¯+ÈF4Λ¨ÊÄL Ú¡(H©éRê)t-aj]NOª]éé#gpZ³tŽ|-Öh–’çÛ%GÞÂK!zñ‰mB U; Üû db†Ü«‹¦7Þz¼®~¿Ç¯š¬–΋ÓUjâhürºiÊháX³Y›(À_#f¥£{ áÅñ¥¯l4^‰iùãëõ☀æ6|*;r7±@KÏNàø˜ð£~A˜¡ÞÖ6î&uu­ÔtüF«Š –ªJœ`ƒ¤xK*QCcUz‘Zí”Aï4ŶâYàÙ–z°''"‚GU¬“5urUéâ0½|à>EpíâRʲ|Íô¥8gØ÷#æOÏN$òé¹KòÍ*¾çÃÌYW©Ê; ÍîD@Áq(@Ð ¡g $”Âû¡Žá3‚‚ –5 SJ‡?ÓÕDÕhJ>ºí,*,Öñß°“eÚUóH:ʼn¨:ZçÕËT©EV LMÚ¬º”0SC0½^ž©"ïÝÀ”¶¡ªéZpR¾gU|`]@U»5eœ”«òI£Qƒ“•*M_¬XKÕÑ0_¾’FË#$^É–¬åýÅÉ« önðÈÿÇÇÝ,Ë–ËmT‚×Ä Œ¿WÇ hŸ!}™~Īso4T.æÌ\kï*è80Y?6\KæÊ3‘¶4²ï$°è=‘¢ï Óà•[u `mÚëñYêØ ²4€¤¬†ôÓ¥FR|l3¬ µÖ]\ÔÚl ¿ÇZ#†µ³íDul¤À@­²U˜_ Û †y»K^-1\‰U|Ç<ÿlË„¦‹½’S"kZ3ÈdzbLM §¬Ö–¬ÁRf…0«¢ÿAš\G|žem]¾U¸ ©F¢lkís'åivujÉZkª/%LÐ Ó >"`՗ƪKæ°FŽ P&X;<½XßUQž÷*à…€si”­•‰Ð®BGØ)‡ñc`¤*>q[bê‚E%VÓü°j›†€Ü6gnmÏï‘ý8—RÈÍÛØ0if¬Š@()Ò°º·æ´bR–r'HU¶¹Y  )»I$ÆJfB«HIÔEGb…ªÒd¢Ö¶£Í6™µh*Vmóo¶ÈV²iRÚþ`hô²š*LLÏ|[dƒ!;¯Õ‡E-¾Ë'.h„'õC–-Mz‚ü1ÆH9;+÷¼-s&9Ëâ»[bÁ9‡Ûí|{ˆ<14RçÌ7”祑± ÷Á+´6O˜mŸ U[…€-P»™¡ ”­Û¢¾øÿ3òÉ™ž&}LïºVn‹ßTãv3óœs`ëªV²¤ÜŒ-`‚RHO_®lÓô>°JdáT%@vc/lzO¤v4&&-à|l›_ rO!ÍÜꕞ­sÈ¿O®—Þ–8Ó •6NE-“#†]¸êGCïlnaCg•R¡¨0[zÙ­ôõuÈ™,¾Z@pPµBLÛñÄæjanpãc ‰i$µéÉÜEnɤÈð=õ}¶éKq0'A î³—2Æ*:Ž*-DÇÜü¸±›ß@JåP_LéÇ$´& vÚ|¯èæ Ö¯¦^¶e[ÛJSIƒyXãË š”v²F²?€qíH«ÃN ¶-F­QK©RÔ¨ò­€òwÝ$€àl%àüÿŠ:ÊVr›ŸS4’ w ß<=ÐÈü×B-½UÖEÉÚ`d™7€™ ÿ©4™'N‰×®SÌŠ²ZY‘%Sˆ@˜AŒÂÜNÙ÷á"•OcZõB:²Õ„l‘‚CS7C­[¥TÑä¥Ò4M 1¸a:£³à ¬¹õ#Ø’9ÿ`¤øÙº´%³­ÃÙj›Œgn¥šJ‰h  (`òiû’cèÉV2à úl’IµJ圦Ø´æbF*¬ª^%ÜÞy[âÈL¤(1¶Æ`SVnÛG^Š™ÜŸ<&¤mAÖ‘pÛ²0¾' ˆúâŽf¼x})ñXø¢öRõ{- Ï€ï÷:¸”*ú4™à‘Í ×C’ @7@d+~¶"SMð¼åp΀ÚÓæÛ4[çÏ|œ#Ö‹‚µõrÜ^gai WC/…{Ãb”ÔO “OO=+ Y@¤µ±d½Ä¶lóIlå–¡¬rJ+^ä™U¶ù¯‹1ä,ËVÔnåŽ@ÀǨÞ[µÉ€üZ 94­¨ï Ä4 lùD&³æ¼í€*ó gUV³ )Û•ÂÌe *%g$ÐJ©D`DÔª…5çÜleÀJ ,Å0,ðp§hNz¤µx1F ±aÔæ€äl­$²vÉðb}óomΗifŒY+gÛWIc;æ¸_1™.sC†)³}Ž$ˆ±î6ŽïýtäÙÖqXÕ×kF¿© ‹®‚aþî @ŠÜ¬dô^lßÝpʺÐK 2Yk§ ‰<`¥±í02&A[«˜û3@æ¬DMÓ¬žƒà92 2Ûñ’9A¤rXæáJÈlÓ§”R(êRÖ .ª,FŠÈ”Ý-Ci]Tb; Üx]£Ë9ËÚŠLÛÂbµï“ÅÛƒøªN+¶½ Rée¥˜ðGÚ”²+T"ðGfÛ7m¿ 43A³ÕÔÊ„2’'¬–¬àÖ¶îMB,ÛœÍ`Û$€¬”Ò_3@÷¬8àeâ×Ù&ÈŠóÖxVH²alã—ÊJ9™T“[T¨1á­‘V-ꤻÒBm‘3™Ï»ó6ÒméÙÂdø]ø×ãŒ[5"SÞvׂ.“ƒ,ŧBU¶â ú½Ý}§Po Û:¦¤)’åC€œ2ÀDH‰°µ±s°MIsµÿõ­#;«:bÎîKh0‘U|úüÇhÝ$1ݨ‹•¡ëâ&;P‚ìNÒߺ³ÌßoÒ¶.ß$‰mžúŒ{ÿƒœJÈlû 4O§°ª­¯5%æœ7YpNƒ4s¸_Þ¼c9gÞ0¯'1’Ì$j¥ÆF”7$¬}ÛÛù,µðV².®u<[ŒX¹B‚i& Î<‡ñ¶xÊrˆ±Dž~|G 8sÜ.p&¶§ò¦ñaó”B6Û&¬Ð:½<«Æ#¬Y•µ-ª…ñ³€­‘%1¡äÇ{K§©{>Hã¹)±µö5ëI¥'€Ï¿¥ÕÉÛÀB,׫L!|M³¨ÓñþºcÚ:ñaÊÄV4ÆÂÌ;€ª5ˆoósÑ0 `…S’!«B’…›9Æ 1j[_¸xnJ`ŒÆÖÙñ° fb] ijª¤ÓŸ h¤Ä-=ƒ±ÍddŒ•X*Ÿô˜ÞØã3!®…¦ ™PšAH•Å2[k½¶bMñ|(…,“²Ý³¬-ÞÖWŒáÖHÖJdYYþÀZÐO™? ½ #–ÍÜBÊÚ¾UYcJÕ.CúSùd­¸üßõô¾%Ó äÁ¶B2)µVlÅÓ[kY¸Õ´Þ1Ù>>ùÔt)U²4B¡+µ:lGÎ6·R)1Ý*€á™mÄL¬¹É¦OF 0 ,Ò¨ZXH5À&Ĉ+@/ }þSÿ Y©õE§äoŒ@)žéùc*ɤ$Î$ÙÌKmB¼¨cžé»(ëÆ Se%þÔßJd3D_íç% 'NfíKf?Ê×½Óɽ Ü´ëþgB“yÓÁ´Àx_Vá¦%cÕÀt©pÄpM€Àö}Ī|K 3LcUÛÔ*É–¬r[Qw0† ŽRUÙ †RSn<ÜOCœ? ž†m ‡†Á˜ÁíÕ=++Íé}ߺÍÓ̲ÿÿPU 2@è%~ýõWknR¯­1ÚºFåîÍHpz)ãaª²]`Δߎd¥vºËn’ô®‘Œ¿³kM` ¬®#Ü–ØEÙ6Oë:òYk©²Vµw÷ÇôF>¥6í«¯c2¥“ÉêÛKèö”Y| þãm¥TÑUç€0 àD²d]E…Çåpƒ[™`ÜXÇÇÓׄùˆÚUãapåf8mnÀaâÊÛ79à™Ö‘8}@GUô”€•Cóxúõ5¶”¢'Æ­“ÿjËÚÖ‹²kÁ§ $¨)Ùt4«¬C fot Œ­ Ž1­­5‡«KÙ”dåk—§ÂR²ÉS¡ããKÙâ™;HïÞ¶ÖE9>ÛJl¼u©Ö´ehž=… 5ªVk°ÂUUBLˆRa©¶Ö0¾«ÓËIO­}ã²à.Ñ¿‡í‡‡¬ØóËH™˜5 5™QYž¢?Lªl+‡z)dWŒÜ‘àk÷2R9Ocz†²ÁÍVxû›¤™¥r¦¤i$ÃÈÆ×n3+gÒÖ*zcˆk¨Vd¯]æ[e×Î fæ+d’²C1?=nk2€™³¾ÄnÆ6}V°9»H¬ ³B M½Øb2ç)« “-U)“Ù6U>q)«²RJLB™ØŠ—8 M+ÌÜÊÁº¨»Â—‰Œ¹®'›FªÐ(k’•xY©”§nëÝ8óÝòlÓc܉5O—í¤}mH–•,1Œ¡¶ †Jòyo@¡ô €!ã\4ÉwwžQΉÇªdÜjKfµ5›õõÄt¨•ë·V•ɘÊm×~K #Øêømµ hÎ^íŸ ¦„­â'Ұ͇¡HŸLjz©JêB&"ñ§ò{óíòg.Å*Ád93É–€^ÖÚk€—ÍÍkÆUn¶™ÓWBÜA”ô÷|{EñùpØ7<¬°F¬¼HâI6C—†lH$¦ÏA–F;Û|`Î5Mc« _г­• Ùl•³ÊÙIѨ€bÁDm½Èdµ8êïÒ°µ¥WؽH)@0±B¸lëíRôÕ7IÔ…iܹçÕqîøç/¡ü”ÜÀÄÆðÔˆaÊœgiUÞÀœ…m¶RÍYI>ÄUÀ©“eÒ´”4³²=¾÷>³ªÜC¡×¢Z“ÃMòŽ“s><¦9­EIÖ–²!9À˜µÐ×–lÃKy*”ªd½—,+`á/4ûo!ˆ™`¬«"«µ£uÿkù¶ UEÃôŽFjBe}=ÙÜ6 å ÈjKϹ*d& ‘m7¡íø=,k ·ÚÖך²e6s‚4­‘Ô‹áÞ66¦´€UÕ¦‡ó™Ì–ƒÕ<x3lq¼-`}=u‰ŸC[&;£ñ6aµVA¹*wEã°:*L`mJ¼îV¤*A¦Da>(i` Ü“dVxQ_ŒÖ¶ aA`ŒÕâ1øœ“a6^welU݆F†‰¨Ü*ð9ä–R!·H‘s°r°µÖ¸c~æ±Í IP¶kÄÛÆTò6‚‘š&;Ã}?ùø<1ÀÍ€ÇÇhšy[Xdzl½6åëHÍ“OSa¼EëiÛ)téçAm¥„Kã̳F‘Wr–®”•OhOŠ@ M¥¬°¬dÕF‘¸îÖz¥TðáLVÖŠe4²Ü©²iè›$O$½ÿ’áǼ6g¡¯u²­R æ€4Bªª¬"7v)+Yä:øUå³F|f;BVó±­ûJ&èªMبdaJ—Àj%@3X_¾§ `¢¼Â¬à^_¡ùè˧Z Ãwâ>¡€O…VUïo*e›n¼¬ê‚aÛíah`Î4°”:¯­O„Ÿ,z5 L °µ¶„oc¸ñ¤lûé…ÑרªD½èsV"Ö”R­”µØ$  \a}ù³êøµ¾~Ÿ÷*,õ&uA¶ÌõÒ¨1€ôO8¯Ù<°ßMáZde4Æî1Ùª­Ò¶Ö}1²"n²°¬èPM¸KÃ7F bk7C_÷MÅ Y-,¤’µm­;|ÛÿxJ³!­ÄêÔýð…¥Ü›¬³À|²ÒQö£Ô˜dµS®^HU˜˜ÀÖ/-Ȉu4Cbsƒß” .yâ.m÷а®4µrLç5Ïl¥„ªl–ê,R™4’.¢”•›ÂôV·¬¬&qFá-"cËOY-д¶²d Ïè÷‚ [ÙJêžU¶4™äÌSIþ²ù¬À!ÌS-L3$ÈöLóý9‚o+æƒÙ=e—, XU@ÝÓ ©²H‘t¥V[Jµ¶Él‘ºD¶…EåÖÀ«dÛØHY+F‰õRÖRdEòžW𦂙ð'È0âÌô “OU]FHÙö]À^ß|0 ùc¼~ýÁ;ŒÇ'KS-C˜8²WÙVJ!¬×¢#4CJŒ  Ç4o+à·©ÁئÁFZ9=#»ÔÆÖNʉd×%}%[båw¨ó&åxg§¿ÚóO¼ h¤—aeÔ“eb; ÞUðÉŠ&Çy£GþzL·×S࣪Fp‚@O¼T>n>1°% §·Ö¹§ «Õǫ̀/ Å~åÍgãÑ%Ó‡{ñÈd¥„DÛZ#HO?Òx{oÅY(ëËf+*©»LŸŽ4‹[þ²[ &-CaÛäRa8ûýÀèU;[2U:F^cŸ•µHc-KÌ6SàÆ–²Õ+¥•ðlÿÆãk|þƒì² )Uµâ†›†ïC—>Y³Áç¾ÿM€‰ßÂ4¹#˜œK ÙlmeoÅçÎm)….xÊÊ7¹-²,nR¶¯0}d«"˜>¥5p |ºÿfÀØfË*ÒÍ÷Ä3©‹µ-“½À—‚ñ²m·Ijl™ŸšûG—¬ÊéðBùðÉZ™$hš¡Zµpg´M`í1å\I§Æ&áéí’ê>ÕúÑÓåÇ}3(ÑÝÖʰ*× S–¶¾s&k8 ÀgeÕ=sšøYÉblU1·5’ m3¬Vù “ù…0çFʇ¬- òTˆÌi‹ÏÍŠz-ds“­»T¤r ^Àd1&“š?&¥`zÁ[AÓã­áÄ.$Ûµ ©K<ì°¨©‡îeøü¦‹’æâÖ(¨ëî{¡²õÖ~XmSb sØ(µ¤¹§8ÇÚ‰¹*ŒU–U$L?Ò0J´ Œ‡i„d…Z<†Þ«Ü{¯P•ÍV…õâFï^l ²mTÛÞ'€¾Ú®…3&^ac¨Å¨i©BJl’ºÓÈÂf°0á`f¼l“Ì ((×…’¬.ž ;Ñ‹†!&ClE ]ü—©Î"kÅð!¦*é;8¼i‰ß¦ ƒé)Gj¡jSÑÀRª,0RfkÈZ§¬*ÍÌ1‰[ÙVÕ‘ ƒÌp9]ÂÜXå&+X•Šô>0QUÊ §Ñ¥¿ð¹ziZ/Yìzÿ×'ÙºŒ°•M`U«]w{éÏ¥!mé›P£Jæ`†j1¥”Te˰vBÐm¬Ë›T•X¡ ¯ª•ûp¥©]Vó‰´.6[ó«ôã×kÝÕÖ=“s˜HU†±3F `MmñMÕ¤ôÅgÎär~-[Õ@2뜹yîãÓw+†²¬'eÛ YiêÓQàA§„‰™äCƒŒ70 –½›§d¨‘€4j;l&•KÙ–í©5@ÓÀëhªª’Óæd¬lKa`dšÈŽ ãe‹&¶ P:µÕVm§È¤Éa&V¿dÒS"ĶٸÈÎûŽª°^•µ-¤0‘Üœ4Ì¿'¥Ä'ºçË|sµn z…Äcå®jL}‘ôV¡VÖV‚¦Á´“Õ¨³›0¤¦Tn6…J€ô×㪥dLÒTe%  C‚ ‘° «Ñ¶R4<î|…õ•„i†RJÙÒXïtçãC†iÛ…ç¯PBSykµ°s)”˜P2©{CZeéûÆ60LlÌ­|š§BJUÓ &¥uÃ+$Ÿ¦ƒ Ê)…”!›‡G“Å[Û€U(™IØÊ¡w^k[by:3@IDAT@I‚[÷ùa—©2gE³¨/=™”m† î•ÀÄ)‰#µæïÌÇ¡òIŒ”u^ž»œ 1@þ?RÕ"ãÓ'îA‡™ÛZª ÓÖªV‹ZK™ S¡µ!11†˜ÌüJzUlE3¿üéOªÞíTÖ5)ÈÙUõ&¬:Ñè!ä1‚¸ ¤ÂVg+ž ¨D6¦*kz+Y]hàNùòâUf¿à¦ÏGª8SÞ¼¬Ò¶÷¾î˜z®Qæô÷¸ŸÏRí&2^ à`x¼UÔNë^5[†^8JY«&\ù<#­Â$E†FUHɶsÉ"­HÄ«e[‹fëõ¥´¥‘‚·¦‰IO“ñ· š•ËÂô½Ê@'š¨ÐjZbåpÉ”¬ ¬z:°1±”°e¢¯U¥3vQ°'n{K? ™‰÷`â‹ÉzÚ߃Ô“gB¡û´ )b…‰aeÛn$1ž ^R4¦’Ò¢mnuA6R†ÕÒ°RÕð œ9†>±UØ"eûRxý›¹÷§o@þ”V}ñÕ0ní2 3u·60=2ýÂÌ…Ö_xþI©PPZµÖ"V•“å_ª,,h¬•§·5-2åGô}½‡¥D[µ™†A²axâR²â¸\e •’aú4L:ÒH·ôóªÔÚ# ð¯š!Ò:Û˜ 9à»@IÇø¯$™-r79O 7·ä®*Q.k+¤0•ã)E+ ’3åšÔ¨ÂSÙú«ßßýîw~`!¥nÝ9K¡/Àc¬˜FjN-ðð‚ØëÚd+¤ÁÐ(Ÿ^ à ƒ/¥ÉÙð¶ kMiÛ=Ћe†dÙ¾æRüÓ¨ítn`ÎÿùÏ|ÍþòÇ?þ1ß&†,”©/FTÜÃk›Òú#ÔLl»Í01OY—…OÖKƒÇ47žÞù‘ùÛŠ3Ù½J‚x[ µlm‘‰1<=Û²mÃÎEwج8Te†˜²ÖÌ•À{äÊ7ÞF™kšì¦”Ü`Ãð¬rÙ|Î|?¢Á%(r.¥¤- kf’¬”µ£LIÐ+h$·±óâŦïh€k‘âÆÇ sÀݘÖ¢Ži¬Jß\Ö¶MÛm4Y dmõ¢éã ã5N§ï70@#.w°y(Û~CV[2Có*ÍÀ¤¾ñªl= «³;‚ªZH È00Îý9|O•)]ºÆPŽ!#€E_¶uçI_Sʪ¤0Ræ,¬²ñÐV62ÆVP JØJÀ\ À€ƒÓÓ[\ùÑ´„r²)Û&K@ÌY¹¯Y«ÃÊ 8±•cEZÙ=À&)%»¦H©cqKZ1f€e­9«Ugk Œ(k’ÆÆU+J\Y‘ÿÜòI‰øó!Ë„ƒèF’шHª%VÁ0ÐZ£x˜&Özd%)K‘ÙŠÄ»í¤s@ɪk÷‡À;àYðV3w¶¶Ü[[ÑÏs§++…ì~Î÷›FÞ0°{ÖWyg‘J–mbZë‚7±*×+U¶-ÛšN#‹é8ª´Ã4[G«]cd’¾Z52ª±ë„›-²ƒÐd¨œ[…³ÕQ¶Öô@£2á Düò÷¿ÿ=_9¡¸¾?tŒDYÛfz•™X¥4¶–i­p„“™O6fæRFJ/¥»(Sõ’¢ßN)ë´0«ª`žŽ#¥ÊK ¸ÊåFc$&½.Y—%¢ššÚXEŒÖÝÃÌ‘bsJ!µë*ˆ‹¬¬¢1Ø£ùo“Ï÷HX@̦´:#ÿ&¬ ŽVg7Iž¶Êg¥ÇÓdÄÐkÔÌ ¤Dc`œ¨ï‚ÛHþǦdÕl¶»ž‘™÷€ŠÓà¶P`Ø{Ð+lrdŸ&æ©JIÀOPÃ4*>0[Y‘§ÂNd­E+=@¬DJÄ”µÍ¤l)¥ôaJ@£f0€Ì$±DڹѫÕËÙ;>FÊê,ZDæcK)¼“ð!F&VŽÙJ©ÂpͤœZ|g•Ëö˜À–Õµ¤ ˜¼û~duïJKó×±FÖnF%žÀl5µŠ ÍáÓ5¼T@kŸG`›¸ûçÜTø.¡ãäCÉCƒ8T˪"èb ²ÂWRyã¥o«(«i¸­u­{ë<”^”ZX¥ðŽŒaE#:¦?3À¤DìŒôÚµ‚X÷Ä×éó]AãMVž9ACj„±U l›†€§QñÝU3 "…”J€|ðé9ïbÞ„)“)𦂺+ŸH5! Wá“Òlâ vœ:…^Õ2=æ8Þ If¿óhG‹!ýùVXJÆÀÅ•|>kirÎS–L ! pØÝò'&K# c [%ÄžÆ%Àò·'ª„”a€/Ã*Ù¬€ g"NËûÿo@¹×Ý—^/åV%Çúâ|Ìc†YÙæIƒ”j`Xyã%†idmYeGâ{ø Œ]Y|x†+Á¤_ßù+'c8'hkíòëWÒJ)ø[+lk’]%R—ñ « ;ãÞ@V¹”{ +ÇðWÔ"²Âf³"Y…Z#mpÏ"†²ž¬mÎÞicsØYröé%ʉ­†”°µYëUSÛ†±Ò×T9ÒðÃS_ŒH‰ä,+%"YnùÇ#é‘ï¤ð†OoU^Uk<}Ý­˜à#꬜LVk)kGÔÝéø`jáK?1Aþþœ#ëZœ"³a)ú> º$µ5Œ”r†ÚEfŽ7L#Ta„*Ø ÄÖ²Ö «­)'M¸o[J#ƒ)·=¯¹vÙ”4ª€õ²U%¤D¸­”*n #Ûýk„WkÍ<…½mÊ6j>V!›ƒg¡ož”‘µ³’e^•YÀRe¿ÜyO„íËW•^#‚&4•?lÄ;ˆ*ÌV2[Y3 gK {a>ÔEåbUN¤¬ž3æICÐ+§dÇ—­c·*%"ñH…&ï_g{Ÿeïœw¯sÙR ­ÙZ•ÈŠH ϾÚs䔹Ùâ)mɬ0î€Ù:@#eÙ5u-‘j¥¬Ào*7cë·áLd}M “'I,ÂR”n8ewàÍ `–„Z% EÙëwn '˜ÎMdž·¶ û±Í<2Ïn¯iaóôµƒñsß‹ÇY•Ix™Wb dÁV-Ü…sÕݑÝ9¦ ¡iò¤±U…¯]2¶Æ°ˆ²dÄd)aOSêʺØ8 Ðüé­<#ˆƒ¨ª¨&ª¦¡ßVŠ }3WåNï–žZ‘LІU÷ƪQ1A9Ry¤UtuÖ¦¢\•ê…‰œMòÞ ÎX÷¶EÂ@A&àð²7s̯y&è*çÐkC–³­yÜ@)Û²ÈJRæ¯Q“Ó“U€«µÆ3;)“œ»œ4sfØæÃd±I0Ü|Å 7˜òü2¯.ˆäl’¶RVmQe5ÞçOÉê}JS ÅÍ gQ` l޼jЈ|h”Óצ‹ ÑHJ‰#eË_kXW…¬–¡h«° J¸-Aµ§û&§¤±m¤ôdJÌà›"Á1º!Å ¹ï‚9$nT2ÁSón %~V02Ô¶¾åñJRj$“y:HÐ*5b;f ¬‚€AXIï\Çw¢J%M«iÛÆÈ £Ñ‚F´(aÊKŸrMWŽôûO5"KlŒ ‰šÖ¶ÎªÖ¶Z n&×B +†yµHY¼P¹¾¶=Í^[ó¤dž¸ÉùWài<>7©A“d+›À*%´Ú#ÀOHõ%«ÊH°-Õ p¼Z8ñ2·­Eoi3KåiìúZ#­J¬opÞH mõ­{M],F ÿ^&õ²uj²·Q#ÕÈZ(ÿÂÏ×KÛfÓNÔHl »Jg銶º Ó–Ú¥¬Ä‘Y/kØ*2Œd8T©Hø^«að§ ðNJ¹&yÏHi†rkÍ„^UCd•çÐ'4fµËò\LêÚZjX*ŒÜÕ²”oëbów?lï­þÀаUH_ Æ[°F0àñ™LVJU7fÕEH5$qYk%V2‚®«v5ªJ €€­axÒûöÃh ×Ÿèæ‰µ°ÕQ öʘÈùkAiUE,Ûl1W~þr‡FpPôÕdÀÔ­”J¼?z¥$<ñªu[€™&lÛÍgØTÕT›6²{X #j¤œÆu¹] FŒLl]¤ç¬i{m>xâr  Â]TÙÚÅdEÓ¶ï1X##5Î4.ÐJcÔ²ô®ªè«¢üõ×_ûbÁSJ!­M¾ÚR” ,Ò(©¿Ž¹aÒ¼+’UkG~ܼͥû¯¯#×±.ô•ØÈÚX G÷Rå†Ñ‚Ì6}¸¾ÖsÐZ_…pJbÛ4ÙZ=^PÞm$e¤Ùnþ£ñ©j­Jwu˜ZÁ½®îâë(›¦Q³Ò«÷-¦ª01%R°êìHY<€`«i“Db< ­gBæyY{ÈÚVN¯²ñò—ŠäŒ§÷5åŒ~O³æ¬E­pn°B[…"€d«j%4_S˜ØØ•üò·¿ý-Ši@¨÷̲³b’)#ËŽãÕ~–«¢DÙ2)ÀH9¡|ÜO@dá4Ê靨U^І'1¸ug)+erz+[ å™ã” +/ ÙÄ meçV;¤T‡‚‘l[Ï÷_aMó¤ñÉäæz¹"ÀªyæþúhÊ¡¶2É\ö‡²-¾³é›8g)Û¦5YZ×}YnE2Û”j,rޱVâe0g§V®¯aˆšî!ÜHÈFå–§•cµf€;‚B‚ʬ›Ñ.M'Úª¼{VÒ>+ådVA†/6­ª9“ÁmáÄ&Cv-€ læ¶­ª6Û¾M’1 ”¹Éøšz‘üuZXŠ3¥±…mWÚûl+eX Ðj;†s<‡€ª®®M…„‘L”WhAv!µ üÓç& ·2\9PÈ2'p.ñ41NçÕø€X`ˆg&Öî*&L¬c%€|h84 ²­”*ïAÃHÊ4dñ¶E&x ï«ß*‹"e++>eߎmµkª²¦é­ñ+ŠxkþUY_&g‚îªgšÒÅúøtáJ­h*k>½Õq"] ,ët=G[ÇÔÚ¨ø”šÚ!ëb›ÀP¿mO!™ÏYÃ(7¿.4ýòG‰´™ŒÙôUn[Š'1#};£r©{ŸkYS™ ðýýï/¥ªŽJ4R"+ê•§mÙ¶:r':Ï{ÂÐxl«_,²êíÂXù¹©J­¯,Œ«¦dV¸=£|Ÿø¹šû½‡§„óqç}ýV~L¯@aŸYÈÓ0€Uí®”Xê *¡éz»ùƨï‹1;¸m ÊÒÖ¢ËI`5^_€,e[LÎg¬ûnËvj BµLž²“fîJC &pQÊZdkøæg‹‘²6vCÊê¹¾ Ëx¡nK\•m%U½%†© Í›Å+± É¤ÑÈ6Fùà;È&Á“Ô´²­ªT<1îà0±à°ˆ|õëkl#Y‘Üò±­|Œr>Þ4ßÕô_M‘i”÷ºÆX D> ½öÌÉêo›†CPèâ¼0²a¼Þ0=åªn‡s?F¢/KðÛ¨^ å绨“zÅBKçѲ±` ’ÌÀ+É\ Þ·Œµ$“Ê­½èJAã¯@jšÓ5Újûä4’Úxß§R9¨¬Â5UR­-¥,±ç!•2ÆÖT01lå¯Qζ¥b Ÿ•C`[ ™¾”"z¸Ic¤00½ËY- {gÿüy¦¡ŒdhžÓæÇV¨µÆôŸá*Ô¨'¨Åtuõ²¶Õ_¿s–.ܶ¾VåÃ=†€³p±VVHÎn¦Wi ‡EvÚÚë‘’Œg§°6Œ7©<9¨J¹y*‘JÖ„œ•ôz¤Ç”jUeþ•w«À«í ²Ê@ŒT®™-P¹C¦ i­˜ F#•ÒêHàƒC`Î&Ñš™F¢{#¦$È-olo }âæéžéɤà‚ma+Û´™ã³E*áI3± ç0½,q§&P…1‚Z¼UÄÙÆ‡‘JªJ0Ì“!R­½-e›0ŒìsíÆèß›°¯©"«mcÀ ïãsPh%Ð= n ¨êÆhVÑÀ&²¾<ë¨ÊCofÿ~Ü®ÇYV äкm  «2’yVHÏ<™õô ƒTb›2«“€•™e•È )aÛ]½þx¤hžþò[ížÜk_;æ {U)Wˆe €4€eˆg²Õ›t±²o4vŽ×ÅKÕÑlesžUÇÑ VtšJdaY«èƒé=ÄÓãÓûí¿áuðzQaÎûÌv4d§ ¦T%–ªÜj’H -OÛþ7ÙÕNš3ë( äÖ<4:j-ðÆZémOýuÀˆ+9$¬»*'õ’c´àT•U}ñÿüç?a+¯µ¦°ïF8}oK%­Ì¾3µ°%úæi%PÞäM‚ü= ŸqúFÚTç 7bÂ|”+ÌЪÐ*K&’Y‘d}¤-LS-` ‹<;Æq<ú µèL˜¦gá¤m×B!† #DµLš‡æÅu'SÆ£‡ùÐLд[‚M¢ÐäÙH¶< f«ÐV8iM­‘4‘ÒÌA¡m²ªælH€¬± ½3‘‰µ;ÁdE,Ò°Ú+A`«‘B2Ÿ¶¾ýl‘Yˆe‰¥àädÜ„Fõª5&1òíØÏ…Þ-ÈøLŒiκ_ËSΓŒ¡¾HzLízC¤>/Š“ø¼ùTCª¥²*#­ó‚5³zZyÁ"ª®@ʧ«“Èêm ½ø‹²Þ§ReᲑümi8äÏAVpCtr†6€¬¾p†°¬ÚJ²JpÍÎÒ­µ}Ë• » kÞ OßïVþ¶‚XÓÆ q 3Ì­ÂR€òZ[m+o­W%˜Nd­¼Ùh¤0ë˜[ãI•õÿ·í>œLlNLúÌm&q¥”dÏ-,k;^•Kh¶Ö]kÊÌ­p3m«=†@)²ÆËP¡­’N-›_J6Œwÿ.’¡à8C²ºàSb8ƒ¸‡R— ¯Çù ÒÔ‘¦©láZ¶í¤ðÑ«×Æœ½í&iHUÍC_Ç ñ" q‡Å°‚ñºX¹!MˆTžI§ÃHaV¡ÄJO X×Ú¶'hÚÜ(ë˜X¹­UÖÚ¨R¢F/€Ö(ž&ÙÆh[@Êä½Zžˆp]xÇ·öˆû}”§9­x¡ð Ú|¿¾ÄXMÂÙ)z aLn=;%„¤ áÆ¶váó¬6Yd8=7‚Ž£ïÒJ /PÕë³,’‰à™2Yÿ(!›¶µ«¬-Yy+ ¾Óû°-æYmbdŒÇt·°§é¤ب=DÌÎ`Ò#°eKÐ[§¨>ó;ÂçïST)Á 4L… h8ŒÆ-¸ì{êဵ©¸ÛÖmÔȺ÷ˆkDóÄÕij%ÖQ¡€Ç(´å`‹¬ßѪ²î‹b…äF¹v EÛ<Ûbzj›Sm) ’¾°EÂVSa¬‘îÁ{f»¯½ðŠÒ/ýxÏ·¬•_ÇÈu¤œNôbd‹¯KóÐ(¤±Ž£—Fn£g‘?¬<‡5XåÐZS2@¶^4œ áRi†mvfÞÁ0ñàšŽc«QæÃ²H2·„äàö´`{Ü¿Ÿ¸ 7ŒÁŠÀŠ9ã‘æÉ ¯öÊŸ ;žs,.ÀËÂÆ¶V ÄÌå7FØÒ_뀵ydµhÔZÛ:l3g§IÆ™RyÃè"ëq×NÖx¡K#kåƒGzÅÚùrÀ÷Y@bD¯PM‘@7 £,¬ Ò¦e"êk-d‘Ö·Z…™!úÄRùÈ $\ßyr#›ÿ/þóŸí…ó4kÛÜéÎá.oE¶”5èœ ”Ú nxA@ø 0œrnBJ‰õÁ ë?¦÷óЦWE#«¤#`l­ÈΘ †ø4¾­‘Eæ‘[õ’5-ȳã`Xõ˜ ´ðœ˜À VåİÈ@-R¹ªFº#†O#ÛM"EÓJ1a¨#&n o«ÏW’¯¤Ë$è· …]õ&ï8œñ¥à:6p#YGêEcB€†³«¨ÊZ•U¶S(|Oa‹Ç4¤­¾M +´­E¤Ög²«Á4y6•¦i²}k‰¥øÐLæNm›ó¸_[µ‚¹HC†¿mn ¤ZmSŽ!¶E˜ƒÐ¢­°íõ÷ýh¤ é‹þf>¯†Új€¦lUµõ”k÷âþC–RÐ ºdó3”ª ¼CèhåO ÀÀRnL¤¬Àë…Ù×Jebn·ô˜;ÒA¬:š­©”xå4¦!S[;Œ¬-P­r`ÑHî¼Õ6C³%çÌ6R;Y/kÙ¶RÜ40©‚1ø®¼¦áÖµžá«Öl¶Êi¬gÅ[Y˜`&ÀëLÓ֛䇉ßdd÷lÛKÈ­¯ )§¾Ÿg¯Å޼dO9¦. mû¦Í£J_M­.9¦^«’¥—¢É.k à XQZaO¹÷0±T2˜@d‹‡­ älÛ[a›C8§KÕ¢*˜szŒ±¥pçpG00L&êBÐÖzÆý~iב£Ä–Òxâ˜Þ*ëLbÈøT+%`%‘|zFÉ”4³=S²ª”ÐTÞ%ÛÒ d£bÌÆ¡ïðºXPÊÖˆiíø~“óÛ¿¦ùSâç<ó†iÂ|0d €p$@–Uóc^ÐX¥0Íãûœiër<Üd”D9œ *ï5€UYUÝV1=SŠ9FmækìŠêB`Îôx‘çj¹‰RÄëNx"¬¬HU-h`)AVIÛÞ12¼ KµÆHÙJq°v(¸î+!“JVJy'Ò/hVšd+´ÕHdnÛ¨>G˜½l “mÛæì¹à»ŠÍ@ÐÙa ääÓ¨ùÃÜÈÎÄ÷K5Ø`RÚ¶ÒÃÆ¶jje+E|þ_€jö¾v›€´ˆ 7ÐK‰d%z„€¬×T•@iíîLCfëÓˆ7¥-ÐÁ`­m@ TGªvb qàk¿ª>odâõ$³}ï.dÂÅzÕb>d‚?††Ø‰0ÛHUH)šÚ!ý Ô}V4¡„{]º[……Ù )…î7£„Fª@–µÅ·ÍM‰FH%ç÷ö¬¶dîªîVQ6=CLnÕ«©O)-[²Úq¨Ü ‹ôV‚#îË6X]¬Eæü™à:}ž; Ò3oTäÀH@l<¸bóØbíôJ€á&ÈVr¼¾?Ú|GWbµuFkâÌué_ÊwoÊmaMZ‘ª©KØTL0V ±5€¬ˆá€±‹U«,ë5“2L$¤ZÙù¿Ud¦'&¶|RZámh€Êoò, ›Ó“ÀüM˘ÿéôýˆIõ\­öPXålå@Ã9Y˜f‡ÊßVlžN'…¬pcÄðôíDonZ…må0±ÂTþC°íWûù‚Hµ:2L8«žfr^ %ˆ¬l/‰¹Â³”eto.sí6ë%`"àÍ´¥Q%úB #Ê–,@V ÓW½Žp¶4ÊûµÏwš¬`«—¬r§‡‰u€ÀsPÒØÉJ5X&ø@%¶"Y+‚l¥úÚ×i{†øÞ Œá¬ÚòA €ÌAd·=._)øjÏ¥™4‰©ÂGi˪*ø]«Ö|Z•P Û®åjÿë%÷,4j<ç¥ï?ï!îç”r<†Æ³õ ÏjÛï„pUMkõX‰â©¥ˆá&”Lå­óŸ<4AW¹¬m¶kµ‘β©jAÀ™¾Žm o˜Ll iUHP6ºäf$  ch~²„4¤Ÿ’,“ü©µì»RÚr HÆ·íñU®õùb©j ãYfM¹9Ë<É”ØÀ}Ç&Ffbeh+JYá“”­5[_MÃ`t±Úæ ë©ÖüU±­ÄŠ´ÍP– ™I“HÕê.eÛ<ºt'­ÈøÊ›ÜÍôæ×¢Á8Ô:Ûúf›'ŸLüÁ• òx†dî\•–ª¶î•·vùçç ‘be0]R+aš,È02w%F©%̤_'«dy÷’¹Õš†-OŒ­*-0oy4Òa&¶†©2æ±ò”í^l}ìeY‰ôGðïùHQŠ«:KǤDòô°Bnø”©øl»œ&—bÕ¨Xa¶@Y¶nöFd)0x¶ 0Y…¶°•2±U-sØR*¡é½1!,•›¬ &[ÙJ¬LlcèmS2´íð?qƒ‰­‚ýüaUx‚3âw<ÃÀøË}>ó¶ÄBUV«Jf•ú?CЏîoG<Æéhøëþ‡?ü!Ÿ²Ã¶jEGv9o÷²*d®%­Â®31Æ*‹×ÝÞ$H…0ž¦³+$ ÃÏJÊè5² Œrb—[2…¶ô9[g|βÿC×,K–I^ð´†f<:K6óI¦—&{&ÂåááÒ9™÷VÑÐYáÕŠR¶5WÒ›æçî¦%J¢l¶Çîþ## |)²V> •#­±Âïî8Û:š¨°£Áª:mU˜ú&PÅ*f|)++µÎØêæ…9UÕW ‘ƒUj&€¸—q^ïua[HÝês^Ø`Ú)Ñ®B-zÇë~"ø[E>KmË–›!MË„²1(»ä:Âݼ,¼*Ù&©QµV©”p|Ý­Rw¨3•l®6¥©„~~zõÑRØ*7m¶æ‡)‘†DÚ"=æx«ñjdKÜË:¦ß>µ{gf^•râ4›Hܨ¶ƒ#éu9§ºk‹$È'=ù›¡ƒXÉ c¤²JF&&²³šž¾Ÿk&ÏA÷Ì«Š´L¢D PR/ÎNÚ?ô++JUõc+š9`U¤Âr‰…m‡Ó'ní3%Û‰Œä,ç“v»õq¨‘ÕxÖNÁG4êisßO…†i†­RÍÈÄ ÀßÙ•ƒ¸a<&J¬•Ô¥•ž¸HWM°¦’Ù6Æ”™ä`~¼èÐZø¹i˜£o6â5B¢ €Æ;žƒÀ³Í„¬Ê{'øŸ Á4Øn2M)ˆ²º»O¶˜™÷쌬I€uaEÖ#•,«·FÈ*4¢‡G®*¯öóîe#U_¤Â”jE¶Va;«Ê­=S)V £5½³s˰­òŽÝ÷Ó§V qVý5Ì-YcdžCY¸+²Õ¥‘Èèá@ŸþêÐT†ôdk%ãO‡=_gæÿûß|Ø[IUZ…ÊfÊ®ú˜xç]»¤&xmd¶üFò„;˜-ì (K‰4D “Ü0cU•æ´ü> ŽR€ógŽÚº53Ÿ[¸Ÿ†laãyN+W"NãõD&€4VµPÎsÒäO߈éçM²Æà¬œF£VV¢ªp“´ªâéDü]¦*ÎH‘C³ÅK©ÊÊ +ÔVnE§/«i àt›3±FªÄü ÓññQ­V<ÒÚQÚÖtU°³ðä_;Un©UBŠRÈZŒ·MÙ<­e­² †‰Ï$^ “h—'sJ§Så¤H¡ Ρ1Ôfk~Œ(©;æçG&¬¶ydan½ §ìÿ3¬ª^Íc Ö¢^”M˜ÉØ<4Re¥ ¤iš¼¯z>xÙÊõ¶=AYX¼#Ñë¨ è W…$ñLl•câ‘Gq5øMŽéàsóŸÇQk3#Õ6dÝ=ÓÞa…Hb¦¢·-:E½¬Úo$duœCÝîì†Ƕ•%«—BÛ0±UÐ01¤rJ[«Âü ¤(ÛÊVuŠ¿ÌæÙºc*Å;¦Zn¢^¼’¤r[!Û$áR‘õ…· p&“MìøÕVG>Úµ®ÐÖ¨¶M’La/IäÚÍP•M¼-OÐk,‹ô•bžnÛj<¤Héw/ûƒ§éN²JÃJ$&€½ZVJ+F*A¤Z@H  ³õ7ž²Ésh€Sù<Ün²1 jA‰9Ôîœwòöÿ @ ŠRßvJÛj—"–íöÂ4<ÍÓH¶Ý<\dnõ©èëYXù[÷™²u™ü9÷5ÈæÄÛf‹–²e•’'ËVÕÛW¶! ¼4V2¤ZÁG¬dÛ1ud« ®J–’'¦€cÞ©à‚^Pæ¯;àÅîŒ{9›ª,Cµ[±­#°Èh®ñçM#³¾×Ø0¾’wYU%0P£·|7 WºShM$Æ“‰u—‹¥ºU…Af0[À*š³10ÌHc{t_¾;”—R+«‘¾C P»Sÿí©ÊÑd=¦fÀ3OßS`’‰á€éFEʤÂáUâõ*«¶-YA Xµ@š™Ûâ›À8™BΘ4Vaë«ØÑÎÿ heZ Å ÂVºÆ¨KÁRpÛLlSk£ŸN÷*­Å„¸ÚÖ5]_†ù`h”, É‘ªÈ¬bcÀ²¿”‡d»W¡™1Lè«’ÕQjñ0!%èadg#“4Cí²-e•Õ¢gÐTÊ)Y©2à«O ° ¹ÕÎÚ¾>¤šÊúž‘¦©x¦ÙH ÷Ën>NoÕEÇ0ñ9BJ¹À¨-L+ö“ž€ØH²UÑÃ~ÖZ…ÉUIi$0ºMy*”më‡Y§ ã#2è^ =Fk˜@”m‘âO¦p6`þî?<[µ4Í kÛÁe3¯Dkš­˜2qWGÖÌVŒÖ¢ÖÊ¥Dc6 Æ6™a`žVzxa«©í1ºŸSk§ “µµRfÛO£;É<%·®ÿ–sc;O ÚŽ k¡ÏÁV()3î÷ó®J M®;¼;NÙ÷\¶3„)c<Î{¯€q3†m¡DHYyª2̇ gë7ü»r0|ë=ÇyvU±M‰×ÝxõÂÃÖª8ã Èè›×”²T *¸mM­+T%ÅÀO6ÞxÄž²Ôº¤ÄT¥ $AXJØÆ”ÂÄV*Ÿ²…™!1Æ–Ò%§1IÏ¥ZSù‚òeBÓí ºÔÎZG@PÚrŽdËÐ_÷jÁ­î¬d' ÑÅ׋*a†dÊ ¶¶L¬VŸk/3PP²5¤5†áét£‘U•5O½jÚÊAJ 7¨ÃÀfÎñ¡Á¬xnª>MX¯«=VÆÐÈ6ÍÖùtœ¥C+r}‘¶e³:ÒÌe©‹bEÓšÆV¹ËôtˆÓ=HÁ} Ùv4²ù;s)¶Í£Ä–@•¬òÄVå¶ô”0`òu–Rp[ëz)iTd'â&ÚZei蛤ژñ¬(1B–Œ‰[o8,‹t" ¾ãäi%hæª8”Ìó·݉µ0${ײúŽT%ŽÑ·°rƒ5jóØ šNäZ>±©lsÛ*”í e ö¤ÊŠÕ™`ÄfÃg›¡”›±"ÞJc* @†!ÀÔ¥KÆ#­ºˆ° C¯âÎÈÆ{yÌLì+%gU˜¬2oͰ5gšJ^ L-:™­5 Ù)Ò3ømA_yØjÚŽWrD7 Üú·üã%´Ä†ÕÁH€¯ zÆ1Èߺ8O3Õ’¾TφyC(]™4Åì,m‰9د~ ¾{ÄTx¬¿Ó$@GkåO#U¬<7EÎâgà¦RhfÊV ¥,ÀêT~ƒ¬;Ð;G©ªãKu«€[¢·•]‰­!5UÞØy7L+¦1TóÁç£Pà1Ö”u4€Ð±*¢'ÕOšx…¥åÕÂm&çôV•pnrnŽT²Ô¾ãê¥/¦/îw #;Q(¬¬ ÞÌ9Àñ_³óqîŠ(óQU‹™†7O>VLãÛzR]~3°ÂkQ;â&éÈôù¿³±Í¹¦FªÖ¶ñd•{Ê™¿V)/s« ±VnÔË}xCªŠÙø+,bÌI¼¾6<™†fg22àÆjm4JVۭͧÂÝUÙ|”ÛÂïü™#e»X4aÀªEÓ€±ßw³‚kÑ0% Ô±sÍ*PIžù“!Ë6?œL‹”4]…-`¥qÕ}/µU5ý56Á iLX_2ÀkP¯Ül½áôZÈ"{¶Ü ie"ÅVt{Ö²d›_!ò½[Qmoo¶ €××Ê£°e®W)äúÂ;8ÙèûÝÛéb4ÝäÊu©E3ÓtQ i5žI*IiU›m+¦ù3‘-–­¼mÓÒ3÷:éøú#¹ÑOÉ ¹TÇÄTkàÜè)J5@Vùà‘jH aµl=nJáÑ“¥±¥Ñ" ÖV4˜uOЄÌ9Àm•o˜JðMbíìãµ~<᫲®©al;/A?ŤU¯¬²%ÆD²µÅÇ´ÞÏçxWº“Z+°jñ®7–zYÇ(É©…(Û– ¥Kã£êޤ©cÎ>‰ÙþŒÉ!·Ôb„,Ã>ã=wd3Üüù»*€§BQ‰•Ø=XÍÙÌ ÆS A@—J$,jMP_å¹^ÚU£Ð)EÙu^ØFʆé"g›9“j•»RÝÝ'q…RgŽû¶[iè¥àRVžéÿö¯ýKoý÷¤Y[EºÕ;y½¥àÚ[;˜QôðÛm×QYÎ0«‚f Œ´`ÎZ­Í?€^ŠO²ôðu:ž² Û†IÿöêsE‰„Éœ«ñ>”ó}!å~;fΘf@ªÝ¨pk`3TÞV­è®4µeÛu™sWMc+ËØŠi›± Ô A€†ÞÊÊY6Àn¬¦¶‚€ =ÒZ >ܘ€rô•½Ÿ7²r¸Z i)aàà'Dÿ³'>Z;Níh\{a#U‰ª÷Œ³RÒ£4qæ²Ê­ó„¥¶Ä•TUk«0^za&B­­’ÆPE‰¼geÊ9$ÆÃɪ‚Ч!­°1Í;’vãn…B%_C"ù(k'…ÇXÕÒw.€ãÚoŹä¦ÅôÏhùèRSŒ-ÛõzvÈY‘¶‰›¹FþðMÞ›Sªíµì׈¬Ì¼±9¼óhg«oµm‰1”ÊÝUcXRÿgT%ÅÓð˜àyâùã‘•3L<ƶîâiö¼ð=zk…dª¬zñ§‡Ûâ{ÜÙvÒRµ°µ.E´j|UŸ—ÁV/ìDý¼TRÈ®6[kA¤„S¥b¬ü™××ð= šÌ1eÉd šÖ*hX‰¶ô1+$ ke8°mU~Æû¡ñøËZ‰‘nnÛ¬xd|¯쫉¦FV¸î€P"€é9÷ì’énˇF‹Ý@CZ1E¯J²F•ÝlÜ,&¬NOS0)ˆÍï³FcŒYbâl 6«R¶²:¶m¶ ñͰrgñd)“ L/zñÌV2ÎRd0¡J`öž]T‡ª¼B˜®\U7xFRZ”h{Ú|/fbMÔ%Í[bZÛd•Ø6FÝ+Ô½sí“qËPJ­s 2Ï™O&9ФÏAÊV ÇX]ÔLnÏÏ•6ö­þ”‹nŸØšRGw»Ûú™rúÚ!)uw(U÷|Ÿ¿ðR^—Ä•#L&g¦û;›]Cb«”Uжµ4@†VÙ½“dR `•eRݳì^¡Î[Gþ·è,p[%ဲI\Eo;L}ÓÏ P«JTnTï!2!h¤ L€hþ”Z [nçÿÔX›ÔÚÔSqL.0±â"²fRB‰Q2¤æ'¶’¥Dò€¦¥^Ðs°Å¶½owÛ ‰ù™a²øx#5=àûˆy—K)²MÜ$žÛÖxk}‘1¶4°#[;ŽlÿmDFܹ*ÇcµõÊ6†a PîZÔFâ‹÷68 u¬< ‹iÈDc`AÓªü牋¦¢$Š´æé*ü<®‹ÕœnãçÛ/˜›ÚñlìVÛ‚sU©B©"žg}ÛJ ¼-M$P+¡D;¤”|ÚßÿX;b™X1|.ñù™Ô´1fU» iDY«¦ø€I©ªÔp3Ø6O|…¬ˆ œ³ÝZ?Œ= < O Æ÷÷˜¤lպ̦ÂÐóaÛ`˜Fª– ¯ ²Ka|šl --@“Y¶:"ãi²Jœ†²Ö‡¯6}8q)L¤µFü9È:ÐÒ¬ðªDôV¨ÏÍšyVV'u±V|Á01£ª)àsìïÿ?麿µH2bbMÌÄ–ƒ-ÛfUÇByíN×ï_0³µf’súÜ0E" •[m5Å¢Ù¼Ä&‰ì˜ÄH 1YnCß–Hœƒ­àã/ìýa’ØU“¹y2¼lžV¼U! €&¤ÌF¯¾šìÊÏw7ðLÉ:ˆÚ™w" R@‹3è&À‡F˜™´U²À S¶µ [þ‘š:{/ÞH Û{ôê,H‚ð ‘áRmW> iuç¬JppdØséÆ$­D&Pkµ½Nl9Ä'³uF>Žé꘎Cɤ#w® ‡ÛZé1lmZ òmlN©ÍÓ”²ŠN¡µHɹ¨ÜœdkþJÌl«¤¿ÏÊŸ2Û½!d¿|× uÙµ4ƒ*2}ZmëÕ*0’¬Pe5CŸ‚úÚ¦MÓSÐ H,Äsj]ù;*‡HkCš¡10ùsD…d i0)¤FBÕHÀ¨Þ–R•#3ÌǺ€FíÞè;ÅüYIá7 ÌPd4Þ »7%UÉâÅÛŽ4 Ðjà.YG¤í4 Úªå_w£Új”¡¿n˜Yyy$b-WÐd¶ÜPK°UhÙL²m“HYw)j3i22‚Èlmë8rÛÜœ*¦Zk³µ)CV² a+â÷O€Ì¹¬•ÕFâymγ„E²<¥ðn)T%n`)aH|· S¡UŠ=ÌÜJc¼ŽC €e]J<2KÁRù×+~8½#U#¸Fù㫚Êâ•TgBé,@bXHÙ²rü^JX•“âŹÐ{¥Ä¹Y+de<ÛÌ—µe"”›Ðª‹˜ÕR+ŒÙ–žCGkr)¤x•ȇML¯QóX¨‚ñ¥lY•—mËDø±çsç6:Ö·ù‰RŠYIaˆ5ªE…ÁJ0±›ÏªñèscÞ—uÓö0’ÂÜü·4Jˆ1ÄVQ_À÷gJ%›É_È9\ß&iŒ­,7%ZغjY)[€ƒß¨ªêƈz}‰)²PeÛØ°€‹d<)OÍ÷ÛCf%“jfY ñµ9¶d1þx}õRd¶”ƃEó».Y)[$°mÙñmEþMÛ4=5YXLÉP¸OâúG2V=_PÒtV{ˆý®l›3´*´SÅð4û¾K11Þ–Æ I ¯Ùð¥ÊªBhêYKÕB=ís…ÖIJ€5%¾’C¯Í^3 YôµÚªJ\²™[òAè¶õ¢é&µPE£){zßgU ð4fè%¨cn4”â–þ¹ÛÕv?²˜î¦Wn]¹r@vçY¡»ÖH¸ªZs^È–ÒÀ7¼£…k$[ ›ÇÖB/ }»p¼ ˆ\`YW‡ÔÎÊ9`5UþVºðǨB2i¤¨E†°ò¾¦Jó/d” ’3œž`L8qóÀµ°Òϼ’|Ò8ˆ­ s3þ‡x†ï𮂠‘€+ó#ûŸ #§‘ÊÛ4Ý›­Z[Acm˧÷ÐH«.aU3<Öß;ái~ ÃÚE’±­#ìk„a‡µ³RNJ¶a2‰‘a¶À˜ :š¬`‚×¥©Z•àf⿞K•y”J0<)ñ鑹ÞÙ0¢ÚÞöwT>m“q³5Œ©`_#ðZÐÀ‚&=[ØZ‹¬Òp0^GÆGRêØ0@§¦.¼’¶ç\Âè}¨«ä¸é 4Ç0)…g[ÍW*[žF!ïÚLø¢B< Ðy€N«|7^‰.µ QrÚ|¯#Xèaz[Cº …z+Œ§±vwÈ&GÖ]mÊJªíG²”î”Jˆmµ`åyÃx[#J‡Þ‡<ÒOŸù€mzþȬÚJaÄ9ù÷ƒ!…·ª²0 ­zQ°ínÀVT à ½¬Dæ)m)aX#a{G;¯©k÷ƒLÐZɬ2¯D ÿöU"…‘‚n&¬®¤Ù0ñÖEÎÊP¹ÁÞl}&VY¡°PU/[í(1VÛ”V[«¬TDF@IDAT)ïÉÖ<­‚²™¦BJŸIΕdKéà>2™¼2C–B6†r%œëå-uR¸/¯,BkVÖô²¢¨oŸ‚<§¯Ñ;üž‚ É*7LÖ_r[ iK&”dÕ…7ÀÄkmx+R!™V+ÌÈÙj‘¸­òªxâ—ªDjÁyä\ª „e­;+½\8f¸µóZB–§§£*·ø L€OÙƒËÙªÐÖNÀw gĬ…m“ iD¶VÑ– µµnxš²R…­ °òì¤Úկʶ¬­k©—*AcMn¶›üÃK±M`]£Þjå@9 `…뢪”ßWð”]¼¨K­­½E²>2R¶ªÜ ,ËMSY>µ–Âȶڊ 1‘?[&‚¬±§'ƒÙZEåJǬð)­X½ÇGˆëñy+bªâSÊ–š3PH±MÿÊ4êNzÕ;·4j}cXm»48ë[ «rÑvª-غä^`¶:â» æ^×jÙV ìÈ=)‚¬0²i Tò®ÍÉÿ}úMKèžmß®ãoÔæÉ“,1ræ›G‹.P—Þ%)¡ªPòúððVɹBØ›mçµí8•§TË$ °xÜ<«›iUî 87ë u„€ÏD-À„›Õ5¸@|‡"Ö®{+M3[ âX_>†CÜ–>7àÊÏELJ­0-PªznQm—fk†4™X¥”{¬ &+î°Ÿ‡#KÌ¡vmÕÚ¾Q!†@Ö]Áõ5‰¬£I}~ê'J­Í¤°Tke®[%ÌKPr74’)q¾HÀªïvˆó¹ugɹ¦ë˜,’ Mâü#Oý÷øÁ´5 ¬Ò:6ƒ-O! “á;,ð²MkKSàùHõhmÓ(kQÇ^b<¡ßû¡Šmµ>€½_w O³?ß“qØûd«%·k “f Õ9TVÍœFm‡UH ”7ž*³É®…É:µ÷iYUÓÀµÎß–›àS¤Ô…›óæC~>NŸU+«.ÙôÈú*3dëKiȺWRªìlóiÕB Ü„ô]¸˜5%(2±vodJ„16X2<2,X~¤-LÖñ+aŽ1˜¶¯Œ#k%°šYy/Øið )üL’ÕÂÁ9K ÿ¤„Õ#Pç) døÆèºˆs69OYzdÎÖkp–j¾Tup }Gú~ßV‰.<µfnµUN€)vuªD[Us¦¡´µ&Кg‚Ra3â½ÆnÃï…|v™4¹14ŒTÑy‘.óRÜ*ßÑ:Ãfk0MÍ€” ]±I¬jµ‘Êë’Ò¶ÐH 3AV…œ¡TM‘sSBÜúñúþÙ~>b–4R.ö,Ö˜¾ƒPÕ)¡Öû#Æ¿mÒw >¡Êqü£ÿO¶›Ï V²^0”” fÅ0«n»|æH2…{LA¶ÂÄHŒ^VµÖ ØéÖ†·R6¤×  u,»*ÛnH‚¼yŒQ­U–!>%¦m<“²Ý–fø‰¬hú¹V¤/>YÉnÃO½ÿüç?°vÖEyÛf H³‘¦‘Âwóõ*ÅjznmÝFÎ×àÓ%†RI3 kº§ Uv­i0m|vØ Àgwâó4û ¥4y>ñjÚ0­M¥Laú†L¼Ö¶°àL–¦ñªÚñ¥¥¦m›¿a¤¸‰ÈÓÛV’9-RU寉·mÌœ3±JuÉ Ù”µÖ¢.1ô.‰kѻ㮔PZ‘.Í@½ØbŒ‡Ì¹‘Xy…@L…0éQj'T5*¾ÖV‚ܵ¨—*<’F”BrÈJ.Êâ]£[r@J Ã<Éxª]!6•BJÙ??ù²èxr=†yyá#mÉÒ÷ò~ñØêT™[vYëÙd|D¶¯y¼•‰¨°U.`¶iÖËJ_ \‰*À ˜RÉÏÅÕ‹†ÿ” •ˆ<­A™ƺ<`.Å­”­¬Ùz`•Ûêîdýö¯¶ZÛVLnx¤hËYðáVо”µF¡Äv©²­Ì}–øœCÞ±cèbø÷ø¬|ô„òFµÖÉ/0l­BaçeèGf½dy’ªÔ–ÊIlB|CRJµæoª*á™­Oyú^@&8+¡Á”Gt¿§Í¤5U0Ï€BOö–ž…3Ak…maJ¼Œm 7kÇG‘{a(kmuuLd«ÝHî俦ë‚ä‘Ùª…ÓX9°­\ëÆÐNŠó58@ﬤƒ7†TJd-ªâ@\`rX@I¿KÉšŠ8ÏÎKfk¼ÞYš.Á¨ÍÓñ¹q ¶’ÙŠ}˜òÒ~ÆÇWÒ¿œgB:&‡~Tp6ª-7`ŒçÙ¹2L@#j 4^7_Gþme»4}FL‚gȉ°5[[ÐtE À»Rz>=©.J¹È‡¦»¾ùeóAv|ÙS|e°ì+hkml&Ø6Û9dnKcÈúîñ)ÙT4»j¸“¾>¬úyä¹–Äd<­‚U¤µ÷§îºÐ4C))%]>¨Ä**q½ oÕZ­(Õq(1œEU”1#¥à ÃVÄú♢’­À°‘¿¯0‡ÁÖUûÖ›o…éãÛÂÈpšw›ÀÚÙÝaWG£¼{èr#蟄î€yfHàŒÄ@ÝÁÜš!,E¨°µOS†µn˜kóùÔ7Ì{™JŠõ²íDøGÜ<Ÿš{Kðjk]U½v|#rÆš) 0oòuAvöw’Û ÄÍ€ÕH¸­ÕlHn°I`#©x¤€S® &C 7Û0c¿bþ>V¾Bû£`þ ;—¬`b]–#0dÄ>×g¬çD+—Õº ت¢ÄAŒtñ¾1L…¬ïzՂƉ¤¸•‚Ûõ0ô}Ͷ5gz-D×BÓ÷¶í:ºŸ 7°bBI¡…C%[w©dutÆl­°ì^­æüÛßÿþ÷.¢+cGš °²‹QR•lgz“ï3ò}pæ5Ú#|{5"åz1̤™ÀªÛÊPh‡÷{ PvGÈDYcdåâˆÃ‰mwx£ÐIu±Mœ¿”ªÞì´¦ÄJlÉhÔæf…1B*ÜI‰ú¦·.¤`Uls† ã Î&¸ZT²™só¤8èÞ#«{ÏEùZÜ>çw g³ÙÂ@$qž‰§lK¬ ±FæìH«ÂzeÞ¶U%!µ+⼫èÔÖ2a+È”‡ã·vF†²Ì)­F²50ÞÚ•´…+¤”Ðϳó6›”Ö9TB Vi¬HV“ô¶‚Cbúº¼½ŽÑ÷1uEdƆÒʤÙÎDU$ê †}/ô.™m•ž¬Ö^ošÞ8’Æ Èº#…¬cÖ×¶“ò)ð £Ä0zÕˆLÐ(!°âs³]Àµ#²~@ö |-œBRñ17æ}±ôoŠG61@É ®{]h0Ö·i[<ÒÚ›VÓVd†VY¤©f+«‘­ÔÏ%ç¬*qæÄdLZ¥ê+ 䣄¬B€¬ÄÚäd¢’)[Qa­aL‚›ü<è•ÔÂö5·ÍÍÊǹÔÀÖ·Ö=ÐT¢`0d©>•HoÑV‚J¸áÙŠ:v( 'Ë-[ž½´û€(dbD=ˆ¹ù÷<Àdói«ÄÖý/ D&Û©)±š ³T8ÃdRÀêsðªÊÄpP®JD¦A–²í°fFnTb%4÷­ðj¹J¿}*ì¹4­-ž­íz%ޱj$EˆÛM‹x‚påð-úónèέ´,MÝUÍ ÓÓ‰È4u" ˜H& ¤á_6çx†¶OÛ†‰¡jJ¤E)d¶RB¹”d»I[šdV<}8³>ÔR"™5¾ZbU°.c[ÔE­¦n¹;©Ê`B‰râÚøRÖà µ,½@2éKÉlm­…Zúî¹ £»ð…ë|~G_ƒDÀý:qs¥¬Ê*:v§•Uë.ÌêkQV-`,Œm‡9eßKL¬ªƒá• Ö×ÊÖJ ¤Æ7°’zá¾ÿ›'€Cc“Ùjä†ižHú3Ö b‚ÆÐ´­ ø8Ž*¸* ­ÛX;zdr¶Ý0ü+ÄP&ˆ¡ÇšþΦ*LV•d~…g˜:Zñ¶BÊÚÁÛúì&&8‡ëEƪÃÊò$è›h©†© ½ÉilÀðghM9ÔTJUþ²Èw$[Ù¥OLŸ!Ðx@}ÉʦÌ0Ü$•`š$Ûܬ"µ#ɬx'ÂÔÈVÔ‹³ I„‘Äma½ªåƒììë…ÁÓälKœÞ /åcUJ!Y­øõj*kV²7 L¦p—ÜÇ3ÚZu$¦¬Š€¸Fà àfh[6^ª¬m†ù4!¥¢¤`V ²B9R_oKÖ¨™Ä ã· äÐed²r>t.™¸Ž×æ\`…xÀVÀ mÓÆ`˜4­˜•Sš¼O"¬••ª.yåô˜¶4YV¶"C|$«n‰?¥ß3êcüE”UwzJ@U…ïðk‘ ”u÷óÊbX5R[zàŽO'€¥ cKf+*Çwç@˜ø1·Uy…8Ûzdð5;‹o-êkí2)”'Û.Jª ‰ ZþÁ²]`-Â<•¡g%0Òªja+âÊKü!9´j o;¬—›óŒ*|m™ÔÈ*ëZÒw9˜ª€ºÛÖwüÜbÞm¸GÀvÝ»·³Ä»a2M ØÒÔ=A˜¡mÁ!Œt^%fƒ¥â­x$ ³TLgÁ¿%ЈLÒ¤ï®rëɾÊJb(•Ì|bµl´;qêœÝ€¯î¾½» ß690lËLz—ÞÙô¥Ì¿µãÀ ÇðÂÈÆèȆÿ±"›L0@j£ŽÏ¤¿ç–{ÊN]Õk‹¡±jítp]l‘bÙ°Úâ&?Ù†¬d§ è8)Ꭹð (³ê%Lf•Étï!3Ic-K¬°ÉóÁ{«1¯•r†Ä@¸mM­5ʪ™A/¿w CFÀ$Ml§“%óeˆGöòÿü Q\ˆ˜jST{JŸ#«J jMSV•ôÇ9Æ•¿†3áÐVOÏ¿‡øÜÂÊaAÕÆÈ­ÚRd²ÎY‹ô ˜ /Fmåð&—m€ß0®Å„}ÿ†+ï±®ÉÂjY…e3¯¶RH>¶ÕÚz¸4:Ê"ù# jTÓzaòÉY_¼«°íJ•#°y ·ÈÖxk}5ºØRzqfe 4+”ÝHø0Y8¥-OaªùÖŸ17[«¨ÀiÛü=þžò*™lÛ•7|×’m«àë˜'RvŒr_X¬È„”@tÒfPÕ…÷ÂØ6³Â4F4¹•É»mf«”B)½¬dHßSLŒ:Y€&CÃè¾/VÊ|¦çƒäœ¹u) qóKÙæ˜`ÇÙw¿ßÝ*© ß„vWЧ¤)ò‡ñ¾!µ ¯0œ¿h -d‘ ‰´e¾l3 1%£ÈÑ,4x œŒÁ÷†mW«…°µÆÓ_îð»MɼT—fÕ´Ž•Ër¨µU˜3&‡šª2°µùãKuÝLP$èµÜIù+o$ÊÆÈJ¶”–U0y-¤ˆñÆK«©l²|b^çÍÜ=$K`e%ò·6az«ˆIf`Žó4,OŠƒ™»L«úÔ ©V$¶ÍÀp~·˜øÙºÇýæ ðw´Í©ŠoEæ)+%Œ‘ ˆ vógUgÜ«œ³­Áô² ¼P^Unø¶ñ­%ñ%·Áµ`ËÄJC)^óÜ"ÇSžiî/Ä~?fåSï‚ê”ôúrëNôò€Dš^?Ä·çç=i| ìVÀ Ö@¸©^«e¥â¹%³ÎYJ붦 9°#'0yn¹ÍÏsq]fâõ­©­ZXè[¼wžþت2’¸*þ™WÒØ’™Ä<ÈJŒÚKȇf³Õš™È É¶W‚ `Òðé­ùlž©¤^Y%«ŠˆIà Ó< Ö¶i“ Œ¡ ¨DJôsçcòžeÛôÇÖfÍ£w[%¯Y‘V‚FqŶ(•¬u6‡T³v %xØóè‡ÓˆYéb«Ö*œ IVùôR°àÙ$¶‰oéŸÏF©È ù+üeUa`3A†Õô{¿ë&«;ÁdZ vœ¬jD¬Ðj€Êûü¸UE†ªlᅪŬu2ÊA Ùýw–µô•Å >­+Á°Ê“aóäÜ9¤!C2ì°ÂõÍy€Ol[‰Ë!†¥œ•”èsÕ] 3%„‘4²= ›DyC¶Vb¥ï ‚²«À×cÈ:2D2IIéM¨…iY¯Lš¥”ˆÎ•§UÄWR ¤ÂV@ÉZ×Èv¯YÊÖÄjažô]iw‹Çø¡åº`©&œ!RÊ]—CÎP‰mæp#ÙŠž¯^ý”BÒt¥yV[¡_YØÂþB,4%°VØög2ŒÂÀ;籸Aà?¥’Evi=V¼FdMÒŠÔ×ë!EŒ´ä>ç ó'@ö*w4ƒ{®ÜJ)²¥é˜”B‹º$èÞà†‘bemB>xÇáÔEë3Á'@__[pâ/q®‹gšWI`†3÷ Ui½­Îðé­$Èð”†TeNo€½Ö”¯ž3PÉÖæO¦ 0´M`ò Ç/eæ¶ŽI‹·°±µ+¥D´m†÷\a«È HÜ„jù`ÞÐyÿ|ÍÀá:ßZ{Ã+ «¥L¼Ž5µÕ~[÷èÓ7É­>O¿_!ªŠ:õ¦%‹¬Åd†Ì–C–]m€ÃjN¡ðš™Ùãο Û4«ôÀ;\ƒ²m³Î®Ñ˜¸Þ˜î‚ nP)S¯4Èn3`Í ØÐoЏÁd»wóhm³ÏŠFÀæÔæ,u+>Ûx$± éÓX1}ñ0¥5d+œ?27LWD‰\ÔÈlÌ­ùð$hŒæoëm,27ÛÙ¶49MOF#+e*‘¹¼8 î;mUB€PÃ4HV¶ijg6<ÜVêÕ‡]Z®rd#•]y3ðÙHdFš ïEÏ0’À¶ûÄ4Ãå^WGhK©¼ ìJÕ"ðŠ1é;}oEí˜ØZoéYjͤ^¬¶40Q»Ö¬`¡ª•^ØVŽ X1ËJ‰4ë•M@Vè•x+’ m¶& ÛŽ†qcFµ­T3°•ͧc´ÍŽ·Öe˜4€Às›a)«Û@jWk 0¥8ˆ¬M€±*™¦ª&‡ß¶ÖBJ!ÜyÄ5B¾žµˆqc‰ ¡ ³•}¯.Y!¥w8˜þFÂä¹m}é ¤Šx$s¸¯ˆoòü8#Öh%d#ÎL÷ÇŠZÁ§ÚæÇÐ(§¯ö©>_+:Kï<&¥*ÊHÏd`ÇM‰©ÃÈÈ¿µÁrž9«Ä¦üÈ+Gã›SU_&¶Ü¦KÀsèbUH‰wB¤àoÅ¿©Üð¹m Th¥I0ÉLYÝS¦)›CksÒ?£:=Rw⬶"q$œ³µ¾+$Hc­£Z8ó®×¹uóae6oþ4¾­½ÍVk˜L"eÎ0î[´ÖÊ1‚¸± ÐóEÒä/‹×==üWsþJ¬²€^pŸ ælB+^$^ß4¥hÊ|*Áœ_"9 ¬‚é*k&¤ ¥é)á/›ÌIòµÍÍÜô¶1þàËF6\GdÎDΪòΟFÊV¶‹ V«*•y˜mkd‹T»*¹'Ôédõ¥L,[wâæé–ÃJÈ”Ð8©í×S‚:Òx]ºj&”5B6 ‡fn«-=·R¶½j¥:R¹UÄ$F’aÄôRÜâað/kÎB­¬9ìúCdت*,E?%€·°,+@|é£9óÝ0XŽIƒ6ž‹ê&‰áøLžYÝñ˜îJ`µRe1…Ú Ô0FúšxÌu:qŒ•­WÈ֛óšTµ[ëÎ 3²Ž1Ö5âI¯°HœÃ”ï#F*ѰVØëmÛxë‚éFI÷ J*R ÿ¬d]ÁNTßVå@åðÌÇÈ6ØÏÏœÚòœ õœm{( ðcxÙÀ¾7þ—Ð=2Îx«ûIé¤9è[ªð u\S¶ÍF¦D4güÙèޔϮ S¶íjôÞd3 H ƒatiË*ìDR”àaUm[|SY×FVH)x˜™ü`[J­ë˜¬Z©ò´â‘\[Ø¡œ¥ãP2RVåRô¶VgäLPªç#;~â²ô|ð‘¶BG‘`óØòLÐT4€BÎ"e2k½*)›³”Àìü†šKçYWŠ ùvuH:Uµ­4ª`‘ž\ ¯;܈ 퇓ùJËÊÙM’¥ªa)sÛvÅF£pµM“áEç¯{↱JY…¼Öe: Uɹ¦û+xš€)ñu±ªEêÕ 4[˜¸B˜˜¦WŸYJU錵 ‡ç ä6²^œÕFÆØôBV;‡‚CʬbJ ©*Il¥Á3Qb»{KO“þ8Þ óŸ<ÓW[¯°È¿ó2l*<Í´°¥ìÄR·úóÁi–"ÉØNSZw-ZÀVt(¡üç´²] kɼ’ŽPG˜&Š07 ˜3ÙrFb"‘I“ƒ›Zo ¾xÁAªaLÈÒäЊ§WÛÑA)”ÓchkU|ò÷ã;€ P!€Çà5¢¼’ópóq™þ n[½4%PØ7FUøü›3sÌŽƒªZó·nfæE×ËvØæ¬Dw@—¶d [d†döðf { ‘÷JζÕëÇY!²u]0¬(c*©iݳ­*Y§˜Ãk«°¾æ$†]ZήDt@ ÛË}øÌÓXóI/Rj…˜HÊZ[‹4xAã5À¸+#À¥ÊbÆK™¯c2ëí¶Åjm“)oÂ÷¼5J@Ù‡h«MÀS-ÜümcWBS¸j%Þ%ÎÀ²ùX•GZóÇgnåP*Û•”Ú<²Ž™àïA÷iÂ|X._¶ñ`&ük±v”0Ù›µíáÏ£5æÚŸ*a+±¬ÁÌ“2ÆȰ’|’qî8¶‚`Y…k$ekåt4‚FZa@¶I#òð­3‘bÛ„]ݬ¤„ÙR¢G“O­½óN$˜Ð˜Œ¦m♰醙`ÂÓ0‰omk9×®„l?}àZWKÓ*Å$2îÜÜ­2ŒiN²%˜&b¬ôXÄTΧH“ÁÕÒ¼ü”Ÿšû”«ªP•@VÛ`l1Ù޺ϋDifÇœLÃZ¥š§§FlKI#d«"„•'†eaqë>o]Ö)Ãu!Æ—ÚqlÃVž›ä ?o2üù#T×¶°J<Ð;šEͬ‚àÔׯNBà.2ácˆ^qú4RH[âJd}óÇØª%«×Ê TIшùÐ×Z6gØÂ³ZJ 7$^R†Á«¥Ÿ’¬vëh‹T•˜º°r‡ÖQªAS±ò"ÃÜL"àÜ: ±V€ Í6ƒ”Íf `z Lš¶ÂVž‰×Óï43+WHƒïr0je1°igÕ`²ÆP Óà#W•­Sȯû|7Æñ½o$`óȤ:Håõ‚«MS*\SXÀÕšÁ«žÀ¨â–Øv:µ ¶%&°¥”¥Lƒ1¥Ú†›só#1‘p1† ¦‘°l|€y@êÍÒx|1æp…JÂnÀ¿Ÿ®v»™‰}ã«Rˆ,`!+ô¬è[õª1²m…ÜܧrÌæY!ýOhAF ‰5ímI½Ú6€Õki­¤¦¶ 6%¦ÀHYͰU•-Áô˜w¤Î!¥¬Ž˜:òfHQFÚv¶È¨ÐV*ç²ÄNdu‡x]h0€Â:fßœ»¨ €UÈ^à€Ñ.®“fÙ[zj;u ² 3´æs¾ËlZc;^Ž8žJ –i¶Â ‡!Éö˜kàývfJ±€e[«EÜüp˜\áŸ÷8”ª°vÃ`xº#ÍÏlUÙæiµÅ_¿ókî4ÜræÓI¥à­²iM¡ÈÙ*Ȭfód7éh¬è¥šÞœµní,•shâðωlcdOïï[Ä_îü+rš$YnNØ0]Lfå`l…uß`d•ÆÃS* ”ÚTua.+æ O ¤ÏùíKVÊÚü ưW.C$Æ0V2†Í£<}/b(EH­HÐÍߊÏO ˜’Und…¦ Oæ R­^¡—¼WÅV ¦rµzå€5µF&›[ODʨ4Ü”Õ"þ•gHC9OåRÈĺFd²"Ðjx€­ªšZéÃRº‡ô~-–%¶²„¦dNá¯ÿ/·î!¬#eµÄHðDvœ²­×øè'æl[U Ÿsg!0¹*Ù™NÔ<°â4ÖiH«mµ9{ÊŽF¯œI"]RâEÛU¥!HƒÇÀ}ôÖ±IdëÈ'½ù{‚lid1“zuFL¡ kmûÉÝgVE#+Þem±X-m‚ “Õlm Üü4ñ VŽÉœ²¬N „m™ b¸•’sU¯IU]ˆ¬T“¶dËÖ¥9{rÖ à Ê%gE ôæ×K óšœ;@ŸŸC«­+JœóâMa´Í\ ¤©”Ûæ@ —׉Uþô&°Â™˜l{Fj DGX™ €X‰Ø! ¶MÈ!’Ò04”0%J[M½ðUYÉ›¡Ž vÚß+mfë •˜ÇŠŒ”pËåÉZ‰É¬4 ´›€ ^V )…¾”1ŽÓaeg27¨Ñ4xÏáö?¯‡Z&÷”çþÓ\íç;« ¹)¡”ò±B~g*+eÛ­¦´eÞ $ÖÄø&IãÃî¹õ†0Éá5©CãP416’‰­ÁØvj¼#\Õù}ÅVx°³40}SÍÖÚöOC¥¡§ä µr-ð¥±a± ´ÚŠªhÄÈ4j«"ƒ;Üä§øåi”4V•êµ’ú–žÿ¼Í?Ÿ/&“ç²F¯0ó<ñd¥¬•߯37X à4À©“ÌŠ/•s+¥¸®Ÿ^ÃJgk¤Áa+¤ZL¼í­8?ø}¦zI0¶z‘H%¶§ë÷óUáÊp­]»­òªJÙFZ{.>GšÚ’i:Ùšj+ÖÖ"gU_âôê¹`”7¶rX/ÙŸNG™§­¬r[%¶Ö²ÈµIÙæ´’I!õ²é¥¶;iM1²œ]2ÿ®2ÑÌ@‚4dªãªþ×BÙäji†PÎ\Ô4s¤9­s!PR!Œ·¥Œw¾þû_ÿnÁ·$=F8Zþù`d‘7yºØÖ ÓvŒmdknFF²}m“­`µík‚WŽÉ˜ ÷°ð½ ¼Ž‚ÞÊ ë9PSâ®2“&±ÊÛRÝ¡atÄØîŸ5ee技O÷ƒ÷e‹:š\I à­"zŒ• ¥µlåR"\—Y•c¤T U°žÉ[µ˜³²uÒ›ùsúR­µ Îj÷"ѯ¶bë†`DضR5ÀÛ Ú77M@•è•Àx&”mUe•³,+²øk|ÎSSkA,•U >žN0qžBê•ÀÚxVåÖ ›Ð1Õл Á¸A¼À«²ö?Åà¬Äý+ߦW"Ròç¶õLvo2Akndªl­R€u DVÈ|tœ?_-7ÑœÙZ*è8}VÖByQvæ ñî‡LªÙ¶JÁïº+êJó„Ñï‹é›SvÃ`üx&s^¤­Ž l \y“7É\«­2q U;E>FíZÒX9T¥PªIÌàããùPæÜZa.Ë'™r@‚À*kE¶¦ç)åC5›T§Hf•2•/G)¡J<þ0¶J¤®ðÜ6C7ï6šÇVäÐ`J4ú}¥ß˜wc93¤ás>¶ýqcæôV‘¨Ñå>K iUUˆYíª” …iõ5a:Úî³¶‘liè3's†—€vHÙW¬*[€ g%ôî‡C%Ó aÝ)yªRžC¶u‡ `)%¬Ù4­¶E2¸Ž¶Ãj·•­0«ª†meM«v]‚ÖzÕ)R`Úc§¨°¬Ø–I+gQUX‰¬UÐ(¤Z1Éf‚ç,T Y©ODv$°Tå}º"X­ã2$KØ*Kœ¦Ž­Z4§mŒ­ªžuT!ãileS–â#ÚÖ ž&Þ*ÈðÆø4R¼UŠ¡”Ö498`L3´zÿ•ÇûÚZó¬AÙ{RI3kA#TaRÚ‘©WwáiXÛ2¯\’‚üKY{ÊÈ¢Z+ñ«oTúx ÃÝ? ˜”2˜oÚ~ŒrÛIl]#)U•X—¥‘ aš—iÔÄ¥0Ä}:à<¯Áÿzù량µyuÜ$ {Ü4Ú±-ž87@aUˆ§t·î³á×@nàLʶšÃx@`Tu]¶z-VY9q!k¸ùeá^ïã†iÅXЪ+Ò+yWÙw[¹•¡ÚÝ`›Ïư¥ÌÉçu“ReuÙºÀýô7¡l<ÒmXyž¾rý)RDv‰m1Œè‹Uå`KöÓÈvÍà†Ð±»&ÝãÉl)ŒÀœi¾—«Dà1R°Ùb"ùd®i>Yå²MoåLƒoµ…ËRÚv|Y]…Tn•X…ÛëǪ2¥5E–UÝabQ;+†ž ™¨5+Qy‡¯|]LSS&E>V<½ötÎ¾ØøÙLk°fžg[ÌHý$ˆÌªZ­ea_‹½Í²H¸”mUÆ©¹m˜F˜_9ÆoH }U²Y)ÏÙš FßdÞ²µ à#®ýçõ£Ì*‡æ§Q%ºCš¶9Ð Lr“”ˆ¤iæ›ü, oSǶ”&’ à+@£ÞÀ›ùüü£4áyÀ÷W“¬(½R FÜq>ÿMWþÿàûÞRÂÊVå7cz±É“YÝ*ñx— „²Ú®Î–Iå3( °ÈŠó”3ÿÿ±T¬Ð¨/\-ÏŽÖZ÷VÈš\¶€1ŽP•Ldˆ!® ·ar¬©íL’ j(ì š*ýÜÎaî…ì¸ V"›ìÊÿ™O¼*€LkUpb8dŽG–MðÖÂE…nllºÿ5;F61% Ì kaË$2«Á(»ÚlÆÛÆt.>–Ý`xAiMPjwB¯…«&ð°ø_ãÏWq3—ïDI$@×”€U™ÄulNk¬NºF¶Ä6[÷ÐÛÂY¡¬ÈÓÚ¥~&d›¡ªô«•m{µ4¢ ãËÚ Y¯ÍhšLJ`€oìKžH©w¤ÎˆÁ»+?ÅRìò¿®g©PÉ&ç‰W²5ÿVJ)â²ÕV8šìNª„¾Â”ɬú’û,ÓôL—•R…l+™lnRSF6­¬-Üv[)k¶Vx&]K÷€™(©{-"[§aâÈVâ"[…¢[rÿµÅmrF¢Áô>”ÂpJê‚¡”EîaÅX‘dV²émé³RR#ÛÞF2‘²°¥Teº‹F²V×±,,j¡„¸m+TʶFjm˜Ø¡:W²ÊKåÜAð.œ²—ÇØF"èa²p!Õ»'~Ë¡¶§«²æPSKm¼p^¶€­òÞÔ¦I@OÌ0qÊÞx‚—çczωîwµu¯)«|z±cºz½à:²ñ°^J¤ [†p©ðÌ‘B¹ñ:igIfe› ƒßim3´ö‹FÇdª:»7¢Ö‘ß_|‰;`sZ)ó„ßà)bØ’Áä ¥L“ëž#¤tGøš^˳È²Ý MŒŒgK­m ”­È¿ÁÖ}2@¹l¶@SU˜Í>íÒcåd Ém†nÉ6CšeS–LpÈƯÂ0@†?¢{R¬Ö‰Ó¯ ÐHªd%‘¦Eb\f‚a@¯×¬jjZ!›mM;¦*z+ƺ’:ZMÛ‹A9%R­YíŒf8ýnGµ4 –¬îjžóú&øÐ¤çXs[ßýxc…Üx)›œákÅG•T}Ua íjÄÓˆð«üVœW¯ hZ`&˜H¼IÌÙ…ï2 èñd¶n™³^])Í¿ÖÊ×YI¤Õ¶•9æK©‚úê€ 4ÚåÃL~FªµTA ˆÓ#æÛÖŽl<ÏžKURN—¬*+r5V2œ9†EsÂkšØz®òÖ¦©>¥-Þx‚Ì6f%²Â–~`R~ûŸÛsÃÈ4•—ÌV!ÒÊ-Lé”Â+÷€zR jg¥ÁD +ÏSJa†ð;v…V‘[ήV•‘øt-Rp­4À.áÅuç)«# …Û¸­>íl•Ô H,çG›Öªàº÷3Ýv€@íÛ˜§©¬0=[[˜!1F PX1‚ÆJl-U! Ç ±UGÁST¨*RVØJ­TæÿC×Ý,É–Íô°¿ëš3®Æç‘ÞLoQpb \!­•Yµw7¿µ¨$q‚˜Æs:².'¬g⳺+³)‘" Û>ïpc¢sÆ77©ZÇXm_œ¦¦°Ð«ÙÚ^ûÏ_¹’õÅÀÕÂR&4¿©lñoÖ|ê’f·JlëLºkí›§^1”ÓÕ!c”$¶6À@WÔ`柭òn•LTå=¡—Ê3^/%"2¥móȲµMÖ: ¾ ‰¹Í ÿ ÔˆX )|ª²­…_Ê5›_¶× OÈp_AÀyýU}_1t½XõV͸gŠd]ãHJåñR3¦YÍ×k SZ²î(_¨°•›ÁÄl‘̵ÆÐ¨e’¾ë†‘B¶‘ÊÆtpÇLC øÔhš½ ²™+„ €ÆÈÁçÁ+I€l~[†JX¥iªV†>·æ‰T¥DaÙNakMc«‘µFÜ™…,¦y˜¿?[Y¥™€Œ€[¶øÎ ÔBI@!rÃÔÅ*¤ð¢‡‚¡ìtV[æ¥ðE%Væµd×ã,Ód²-=&Y)ζ0@ÖY€šºR%¶­•H ä/ýë_¡_=ìü>? ²Æ[Qc•E$<£Ï1²ÈL“çd¶»n…ª@IMY/)€Y‚¬l~2|ƒY+±Æ¼S…§–…y¾Û²‰k7 àôÍ, H‰&‰ç&EFd¾Ï‡ òŸfÛ –†IÛòïBfh’ðiÈb¬‚I³ÝÙÏ=cÿy’Á"CcgniÅ´vئß`Â"g†“ï‹W ÊbTµ5•m7_÷”ÄšLÊ0°ÈÇöUÂf(ËM–Lä,õƒ¡¬\ æ¡7  ³Ž‰gâ:Ý % ¾ŽÈ:"•׺Z©¶«* xÓÊn}Gòñµ†‘N7%¼B©õlE”F#_g$Ùn X–¿ÖE3³²íß°‡•¨%;î_ž;×½m‚M>AUºcàÆP•À¨Ðʧ7°5Ïú:‘”­uÎáÍï·RŸ¿*ù–ë«YJdÂÜ ÓxÁ¤ƒÔ¦iíZl™ªN!ë®Ôâ‘@†¶xˆœf­Óp6R(³Ê‡¿ÀhÚ·:LÙZG)æ_UŒÂx+¦h$J}™ˆ•$P…‰ g›?=2eµýM“¬’MÐ6žXÕñý†mU¹ÍS¹Hìæ)1ç>?t¶Ä, iø£Q&Þ+ÙV@(T¾'¥]Û&'èìdï¶R”d"F#[qÜ¿ÅD2IÖj$åM¸”ŽLð1 `‹ÌÐ?ÄÔ*”Í„¿S(ñ’`ø×BÕ@Ô zb¶š¶vz¤ ‡‰­ÍóbzA¦\VÓyÒÃÖ~I’µ™à³e -x=J[>óå³Il‘mßUan.$C«/¯ºZ1MF6[ey ÛÊ1FÔÂJ`YÀg ©Q>9T¨D8AbÛZ×±2$ÈSŠ•ÀkdU™Üäáma«[ú†É¡,Ò ²Y!}¹×̆Te­ & wŸ²bwHãÈR”|l›¤ðH«ˆ·±V2å ‰;¦¾H2ÓÒ3?Å×ພ%Æš@Iå€Â&—ík®IU43e©øTŽ,+µ÷2Rj¼k¡W%`¼Ú”Ö5UE`[—Z7F3ÈÖNÿ†,•æô¸ãak‚ºÀ ñ§¦ñÒW[SXT(Kœ[Uø²Nc•Åpv3ªj‘ñŽF)2N¿ç3Õ´²‘€ðô­¬"Y‰m¯äŒª£3ÒÐóÁ#¤Á@…Þ^b)Û5¢¡Ïnr€_»ÊÃõ…eã+Ÿ'¡\;>^?/0Ã)ólr…×à<>l»Ô71e¼UÌú¶è˜@>Ɇ;—-`­;ìŠz"z9‡> ÀÔÅš›¾H%™ð¶ª¤øà‰1¶Eæ‡X–8%Á ¥l­1µH™OÎÊEâôÛ®KéëÝ ¬cæ¶ÍŸq'=Ö÷ªÉ0u¤1Ö ÉT]ùç \*X @/€n ŸåNg«.^§~7íb›Üš PÈæl[ÊÚ-µ%hª&±ê‹Ñ×J«²@Éî÷I|¤hÂÊ¿ƒœîHµ9ÃâíÕ6g2…”¢9·ê%Èèi¬]¬ÊVÔH°Znjm­²¤,%€9î÷ø@²V‚ › ^~çV« cÂ׿.Çú¾Ý'gn”Bjí®÷Y}6€Ú}¯ÒÓ49œ#m­ð"k@S ¾l“aúbÄÀÖ™0‰m‚ÊmÉ„,ÌÄêåtÀ0žÞk°þ9Ùª<>tùвÊáÀ0Ù°U.¦×ÎÖ*K©PÔ 0,+E€©À‹ æܬ…Tç²­ÐÚÕBS!¦ƒsË¿F ¸Ù*©…->Ÿ­õÍS¶£ÉúCT Ù¨Rdî¶#Øê¾±‘RZ4Éüÿ4žrYØœ:<ùˆ&Oß餔À•›@Ò¸wiÄ<ñõ…; žà|Žz_%±^ù«¢qä_~ûí·ÜíYÀuµ6ñŠÛÖ’‘à¢ßÉz¡¾­Ï÷áÏͪWgzðÖªæU1‡‰Òv 1œù4 œ€)l‹0žfÙlÕ"ã_\!>ÐðÊ1/·.½r)€†ƒ¬Xñ"Æ–§#´5a𬘦"‚ÿ{)›€NœµTd3´wRÊÚ³6€*Yˆ3ý÷[F!¦‹E*·j© ÊúeN–sÙ”>f½ÈÊÕ Ê[óI@#fN,D)²Èé}‹y£ôUUêU"S/FÚRr¾™ÏC¼­>767 Z@#×Uyb+Ò HAÓwzæ²HרŠL°Ê!1ý)û^©*UVŸL3’)²»5>1 fcðµH#K©<ý¶‚4J¦É­ìZئÑÐTÊZ/%@/~ÀÂ%4”ªÄí|ŽÐ<4Z(¤ '°â…ë¶pÛzL4n¦Á(MeYL‘9ȶm½Ú6[Ób¤L¨c&Z;”5MÙ&lÍMaV”õÅÇXaQ­¦)ëÕr®“âÓÖ0¬rËáµ­uÙxA£œ®³âÖV6A×ßTÊO§{cëÞ´u䀯K“[Ûfg¨Ì h†V¤^°{–…kçYIU%U‹üá¶gúëI ÒXu‘Ö«=¶RV±ª[z.-@ Jš S»x8«hl£ÂÄÞ–°TSå™2Ã>8Év„~ #1Vb£ú[° ­UqNßÀ¶–¤:Tâ¶ÖwXøÙa‰­=åÝ¿¬r)Ì՞ǴàWR—f£ôÅð °£«¿WÈóKœ¦ad)@ ¹z¹….™ƒ¦øbS²J–ÅLȶ z²fP(b¬Ü1‰%XŠ-0Ÿ¶Ö‚@6Ak%ÖÀM~Þ:&ª¬ÆÐè^/JÛžT7€iTbãUE o‹¬KÃX›AŠFгu±˜jiòŸÂÇX‰ŒIw…Y ­ekÓí`­a@$&Ä^9àE­É4MŒLãD¦%¦ñ¶DæïBzñ4ÕZeEÖl9ÐãùË_þµ¶Â– @Ç%ìÕïÞU"EU²1u¯ F6 ¸öçfÉÚ2¶Rý³°®€¾0T*)â5’µ}~òlÅ)YõŠÐ»28+çM÷Þs€MÅ–U|í9·"›–&¿y*ŸX#²mQNÀ‰Na› ÍQB4jd³½ YU™ìÆlÉŒ§W¿oQÚ:—@º¨î ¦Dja˜=ú97s­ÙÒ`|ÂÖ‚^÷sžûoà±T%–"›'Œ¯uþR‚^J!2Æ g•B¼ãà‘†GV…”òb'SÛy­RÙZAAÏ„§UðÉ*~J¤¬ûéÞðõŠOÌpn}_ØNjYáW«ik‚„˜—„)K¶uWÅyVH8Ok@G¨PUÀJæt]•hr|½jWI†RdÕVŽW…œ³mØJSa%ɬ¢¾e•ô˜î vW ‰­Ü ¥ ýí@IDATìÃeõH9^¶çˆÄX19xb+ƺ.¶}³)1*«R*±]­îø|ð:— iKàÔ4$[Û;ÝY²²ˆøzÙRŠÛxLæÍÙ#ŽúûʱRbëàÇúŽ]ÇYéÛ–e«Â‹ëúY •ì½’˜ ÏܶòZ'¨^yÑ–°Ò ˜ÃyZ÷ãχiÅ[i*Y¯Îòn ”c¦W‹yÛ•RëGS]ª WŽÁwj ¿ù°ùÛ®—B↿lU² 4m¤ ­1²S®VÖ$:6Áµ9·”j$Û^?“¿úÚu¢ 1¥`AÓj @aonÔ GÒǧÔÀ©v4øuÞ¼Ä@3Ê#­¦ܸvÝïøÖÕÄ×B‰­ÐªV ëk›s¼Ö akšÆPhk_v2}E;¾-Л=%OÊ»ÅM(éûboRÌPI½ºœÎN/80Ä4ÚùúCJq ´Êb:ãô·è÷¥ÄùÇV_)µZTÓlka»»‚)•xñøàE‡R›ƒ5žRDªLn½ô9š#Ⱥ.—æí……3v´j똹Žîo˪ÖJláœGã‰wðL¬RÄVÑ0VXª¨gàÌôý Ó”Ào0[£Â" [`&áõrR)…™X«Õ:Ò¶1l7€g"´ën­4VoAbØÆ¨ÂHUÁiLN‡ÝREó¶¹i3¬œ’¹TÉM`Œ*´¨»µî4¢dHÑpEm¥ÔêÞŸ±aÇ?Òû[E…<¥f83ÙJt‡9F•ŠIiµ59C)1‰; †@ßIH«h’‹±*YYilk½s5$1Aå)cà¹óçc[Ó¦²fUǹ9…È„&£é'K&îÂW^£FEÖ9ŸîAA€IOcûžŽ`…žH%¢rÝ¥\µZYópcR¨ÄVØÊ½*€l¡œO“ÌÍhZ  +2)2«à°NSyk¶²@Q­Â†,µ@JÄ'¶zù; U_wdnÆtÕÄfþ4»W“åLI Ri¬/ˆ÷­Ë0­ÕâL>«ŠL™O }#µu “eˆ1OÊÚÙÎ_VÊV•U‹ºdb%ÆøÆS› 5=L ·äÍÁ<ß«–ÅÀ`4e1¸?ï^ɰǑqJ+mL+ “1á­J6MóG¦AÆÛM13ƇÅ*ª †€²Û€em­ºœ¬ PI±Jv{ 1½–7y%Öëú¹á.JanRFJlŒ-PbÛ£'‘{j]6ÙÃñJªÊ‚­”×håÈ®@.˜(!þ¼[Þ¹¬» é}OI©wSÈæ¶x€Â~kï®iHJ«­rbŸI«gÜ9»\¯`M;?}>Èj­†AªŠì$xnáZt>"¾ mÕb”ÛZ#•М‚ï§…U‘8+2Mëüm®±‚1Mϧ9­ú:@À°“†U%º[µYig+d‘›Ê¶Á¬ª’••ZÐv «‘ÙrÀ07Õ²0¾­Õƒ°j$(m›ÇB9ýFˆÉˆ»–¶VJd¿só§YYEJ2G6adƒiÚ R ›¡U"Æ[C¹ÚYu—í³®QSI5ŸZTK€„10gå]‚ÿ—Dz&”õçuu°B©¾ýáyrP(dY¹ºÎˆ‡ÉÌ#k’LÔV.H“¥éGwÃv ©º$[>dNaÛ‰:;})@Ì*ÃHkƒ2g«aXY)UIé‚_¡lÑ¥9x¦´uáV½Ä<‘ÌÓTU ÏŸ².R]czÛ|Le¶”ÞRóÈ’Y˜Rp`e¥Äë %°W)TaºR[³¥g(²º†—>£Ö´­U-qŸ1i¤ð²xtÏ– Æ*ÒëÄu&uçãekBÎù9ÐÔ" PEƒ$àc °Âj­x‘#8ˆÈL"c–åÖé€ô9´bttÜ¿Ÿ8>w€Ë!k`„·ˆ À§C±Æ–O`«]%®:­*åÄx·Š¶sƇkaYÓâ²² šº'Æ“åŸg¼1ÔJ‰ít¶ÝIÙôœñœY/óü;T>c*aÂA ŸC§ËÜÚq8 Ÿï¶Ê;Ða‘¬W;Ÿ€†¡QB&ÈJ"²Qm)y4€¬§¬Óxé[S&ØJ)òÉÓ)d³b«¶›Y  d«FföoówQ¬0*ä€tºn£k”eNйr#h+Xð̶16UFž“ÜÁTõ’ûš-[!Ì­/ÿWʵèæsÀ,¬°"ë §Œ³ZW5Тëí, 2‘RR æZÔx‡»:ÿýiz>•8/PÔCàt:bRfK¦]ÿÓUõÕqäш )à‘¶aksb({^zi* „­M^kYó`„œlm…-±l‘‰+ß6Y%VÑG›ìüw¤sF®Æ Õ4®¬­²VJ¼Pï`VGí´4¡‹³•õý+‹±U Ó(ôòÉÆWÎ?[J3øÅCì]¤lBz ÔŽ&O€ŒƒA6Cí*ÏG¡(k…é+' §o=vWÀ<ýdæÁØ2±Ö¨!õ2'f[|¯OØ…[›§B|#98ìt¢I(k‘ÒTB R¯HÛbn€ÈG øJþãøÈ™˜_°4¶ AèØwÏÜ ™² ñôuÄ˲ÄHäf¥·íNl…mJâÎŽ„ïA??€kj-•ab¤Àpn†<Ó E¸U–ÌÊ#¸#>íh¼ç¦HØ‘‘ümk%L¤¬mݰ”©†Þª{údë àE2JØ:~©÷Œ²‘¤Èà ñîË&‹·zŒW¶aôí¤²·çqÎ_ª ­ÍC?gWò2a‚NQVm-Zi< FÐ5¦´rh<øŒuC¾ÓÁèz!=²¶RÜz+àÜ´–õଵb[zY>)ʵVM²ÃHåf’†!š³î4@¸ò Ó—âÌGÕq¹¿H…ËbÖÓÍ÷¹î¢›¬at)0€ZØv d°æœÌ ÓOLÓ„W~–üß•C-¬Çýú[Ƥ¯¼£­…-œ`àz|¾¸æPy½`æÂ–ƒ­091.Æ)üÀêãpµç\5íV÷Anø¬:;Y%RžNnüS–ª«†¡ÁL…é#­=h€ƒŸ2u¡ÁÀ+¬Š‰sI‰:Ò¬M² i¤¬‘ åÆÃTU6%CÀJÆÁ©}7ÚÄ™T së1¶²ôH/§³dH ©Vâ94 ¾a+AM‘VðBR$ˤçÛSÃHéK·Õˆ¼áoæ,øf¨<[d_)R}em6€3Cµ‘gØêNÂ4¹ ¨]šºÓhg++|MÙ >¦·T­©ª²ÊÖh“TȰrÐZØÒ4gO£¶tiHX‡×ãsMÛšS$¦¯„C˜ ¶6Œ] P( dVT¢E­­¶<¥Ìo…{44¶ó·Í¡Fn¬ª|¤ÌCo¯Ò«i%(ÒÀ45Â䈞#€´rSÞ @W]꨿µ d³jxY0¶R>ƒŸAmêÝ×DêVjmÎ@\}ÍîÂ˦×l-UÙZ¥Ü…5™’~ÞÄx«½g¨Ša&õš!Ðüy£íÄõŽ6+âÐ=Y†dZX‰›?œ¬óF³©eB`-ëO¢ûû'šÞ'oÌL:¬F%†y¿0)Éà&l*Ûªsݤè2 ¥Ëá 8`wH€¡Œ±•å†ôó¬‘Â`l1€Pż€EVÄ ƒ9&rúf¦1¹¿fnHYåH]àV…/ikúÖRF’BV•?̸¾i”`ðôÖn^­ö€&PR-™’MÕ Ô¿  ¬|^xJYÃUÉòø_ý0ÆúæpóçÞ¤TY²j…ZÃ"’~3ÍÇLaÈD¸¨:&fÛŸ½«2@l¾Å\Wb&^mKµ5³¦L”¯†2C`å¥PkªîާÙôLò‘uðnOmU•h];Uñù—•²5³,ŸnÆØÎk¥I€'+4âÙ´îRx¯$†gåœßîe­ÿú׿öÓŽ²Q1óÄälͬ©¬Æö.…”µ-Õ–?Rv‚®ˆc-t§—ºÂÏ"õn×´d,lÅnŒ^ŠXÈÒ—JoKPÄ ÛÂÖ@˜¾Hà‡` Ù.¿y0×é6°uç]•Q9sÉÞ7gÇ‚ž‰òªê…_/íºäOŸ¯^à®0O©úbÇTËÓj›§ŽéµSÒ`˜&±Ö—8«ºxÏ_‡¬(E…ºd»”­B!`­ƨ¶¥Ð¹l­j}äô¾õm³ÙTÁE})u±U}ޏIÕ îkÖÔšƒHc…õúe©˜Ä1´Êš„•ªN1=€¤!€Å;37UVädžã¡XU!ÿïÿþÏï 4ôý$B 3$8îß ‘²6¡*ž°O•Oò˜VL…j7*Flkæ.Óüm]5Y…¯3† ×¦ç+ÛE)g☙›ê¶:‡REÖª|†°¬À[W«<™. ;£,`í&•À‚1 •dh6|¿•õ§P©ôµK\‹J¬ù+”m𙇕TIFÀ¹{Ð7·4ÖbƒÙ:xž‘jmá‚Øåð‘dÖšPkfbšRþåÏþ3—ŠÒ¥P«9éï?Àå’/¾P3+Y¾ÊeHŒ•^I­gµÖþ·®4uMir³¦1hUÊw°¦§ÁÔEmMæÓßü†/••UažñLT…ùØ6Ã@¤í,T¥ I£o-xú¶ÂX™líˆÉ¼ŽoE d· Ó[ÇÖÌda²ÏÖ‹[æQaššÂ¬xJˆj D·g $™rŒµ,=%ž“áV©š<C@d«œ‰Ca²ºÉÏ3UèQ”@mÓ6pns0ª,ñΕg²J8ˆ¦WåašÂ•K”²æi$šãò­]Óê…Tèc…¬°«Ss“¥‘"@vÏÈZ˜Þ<°ä&Q µ @#ÚZ×;dbÛ÷ æÌ ß‘øîÄz{Q10¦#0ol>Êš„Æ)ØØ" ¼ª ­;NµJD³ê,ßêÓ(ÜW 1†511dH6!Û6ƪ «7^[¸±ÉDžª„+ ¦A Lo}#†§À·´5'[¸m @P nÆa[{:J”»ÖdÞyLw®$ÏF­)ÌeUÁLxzŽ]l© hÝÀ;Z#ÍDÓœ7íZThò ;šUmCf‚QÒºÖ¹5¤µ,™ Ä‘¶]ËdR$X—HY3X*h¦lNYžzáU…'*2A µ˜Jl‰ç@æE•r·Ü`Ÿ¦®Â³ÈP6&[-â­×þ÷ãôJªâ¯V ¥I³ŸSYe~+N#ãá^$ʬ¼x¸s©âFo~J«rÑ1Éj]w<=F„Û–ýA6U61н‚ÞVª.p$FJ!^˜ÊÀmñáÌé—2yÃ+éµIÃM ‰ 8@*‡)“uWplMÓ)Ô 3ç#w:d&VMÙvRƒ±²­Ö«" wFâmr© S£­øR;µ­B&)EŒÑZÀܺ™”ç7:~+‚8}Ûdª¤øw †¶º¯)@™}Ó’å`».ÕœÄøÏ‘ºèþÝ)î'kFdëÑó  zsPvT«°Õ•@ØrëW  ¶…:ú%ØXÕn)µ4õêHRjEVj½¾jJ:³îui¤¬B[ 1l×hM‘‚ÞÚhVÿº)æT¢©ºB¯]¼‘l…­%Îjµ a·MÓdÈ0ƒƒ'V(øY¤ Ø bQ9r¼ÜÉd ˜°*+7<½F”RUÙ"ëž§±3é ø=­UÜh`A°"ÉD½t{Äeç,%Ò¨"ãï}xð°¨@¦\Š %^*k+Û#»–ÇS—Ljææ˜= 0ž˜Uz˜i èëSF)Û$ÚIu'À«”ó4  9Ï¡¾ÖœËF^¿c¨/L *«M°T}+Ad‚wcsÀX¶H@VX/Û÷knµ4† Íc^!o²F€X-åH[‚Z4U$‡”€I˜ã͆„­xU;ƶÁN‘5qG㙳Z‘sŸk[šKÿþþ`„rgÙwgG•×ZÖl]—”FY5¥À¼sÞ Œ‘¢gè{üH>Ü K³lâcý˜§±’UnÆk×N“¬-ÆÖÚÖW¸ c-¸}áéÕ–lx†@|o¼òÚi{Ê5b”t-€`Û…˜Ÿ’èPUá›f.0Í´~ÁRº³%Ȩ Mó`ˆm…Ôî~#•ÀeM¨jkíòsHY_)[¸ËLÖÊDm|2Œ’ÞOšÃAØÂlã•ÀĪ0ý­ÁÜjm•­\/ÿ¤—¾Ï2¾FL0î?qæ]BáÆ£ÂV·ŠaÞ爡mÁJ-M+‡†Ä(±6!0Ãj­uÇ«êza±*ÊÉ’¬Ž I€øÎAb¸ã÷…ÃÏ­.Ö¬¬œ‘ ßv¶ñ¯†Ø_Ç9LS‰ÓäZ³µñ®×Ùñ€TÓ󤤤ÏÁZ–^x¬Âé“)¼Õ§ÓõI7-°ùwj¤1ÒÛ‚ Il Y¶Ã[A{3ó±Mlk*«@3t„øH2Mú;Âç÷ƒnF6Q¡ik¨<\—µhÈ>EJȬ|(a«£)ôªXÕÒ×%[$Xw©¶…̧±•^r7CC™¡Õ ù[s°ª%3½maÛ“Š$P‚i V!P9æ JVV‡­õÝk†lB3Èæ …mKaÌPÖªªB‚YñªR(I/k …øÈ¹ɸiu$H–ª„’ÆÅ4 œI-LBŒ,Öº.])=qJø µqŸµÓ%ª¼<¶j¥¬”C<¬5q + ek|ã5ƒ!•[É>¬£HlEn L&Ô²n£JØšªÁ o+ð™_Éï™’CnJXÍm…•ã¹õ¦•ºö§cVV Yú¶ièµx|d3¬©m&µSx^Äî°*>øúâ§  p“gY¡G …i˜úR2t|÷˜0Åæi d¶}>³Í)d㹵͜ #L­ ¶(ee2¥-™g—±äq¼[º`D­é1]ú1ºO‘XœC~IS_<|óçø°HÆPHYc’¥!6˜a"»J¶VY3˜°!móÙcÃÌ6}2þåáÎ~F¿a+ºCJ¯QÎ0ž¤Ö™cn&k†Ì«Åwn°PØ Šç©Dphl‡¢©VpµŽ·î ¬ÈfË\0Lœ,¤H‘?FS-l¤0MMõ•í5S@ÂlUÁÄÕJa¬x“°…C¼’;Ôg°P‹eÐ;£Úlñ:hlŒ i¥:@3g¶¥*O€|ƒL¨âf©ÆÀh—’ Ž|ÝŠ¤/ÕHk¡6žR*kúdu4±¦€H EÃAj2ŸÏÂHùHqnZÊuñ¥Ù{ȪF”+Ê97a7 %hºåR@<)ˆO‰•­ù ”úRÂÉ`¡\ðÍoÚ”º#Ð…lT$1Û OÛúÚëçÞâ­i–McU"• ÜMj„9CÜ×CG‰¤,`E†ãgTUaâ<ÃL²Ê/0B¹°•7óùf— O¨}·›œRªëòqs̶=Y²"[=¾¹uáx4z©·—T3'îÙ‘µí’Õ&ó¬u4‰­ MÅ„¸IâÑZÓ«<×tßFJ)Q£ëzæ‰__@[È’úûÂe™8¾ ­Ùa[k ÒšÀ*æ€ÏM£F’­i¼µ¯ôŽÓä”0®tjnÕZš ¾)aÙL8Ãm3áücÈܤ€‚€Q;>«Ý’­”(}Û4ªÂÎ.ÛTÎè}€ç œ,2ÿZg®{3wQïq:™€•‹HƒqÓeA0 T©Ä¶,ÜñclÅ[XÖYø›ÍÊ$’@|'"Î!e­ÈÝ!€/N³o;€ÿ%>ß4j]f³…µtR4€v€ÚR4˜¬4 âßÙª¥¬¼”u|˜-rVŽ€¤¯dÝi |‡M–ùd·î³$°º1b&ÄVŒ”;镃 ¤*Îþ:WÛJ@ÖØl™h‡~ùÛßþ†ê¹Ú…Ýl:'ѸßVÕpLo& A< „ mÇÞª:'€L èÈÊV–ƒlëÊÍÃ/Ü>,ü]Bnd½y"éyÚÒsææ´dBÖšOJ˜à&ßTô°.¶+˜L9(RV2ü%~ÿ™dKIP÷ *Ï6au¼SÂZ˜Ø ÛfnÊé¥TÉæ¸ѿ啌^¡”;„²vù·b˜Ð0¬uŒÂî„Iãa¤ÊbzÈÝéš!7âªJ1ôì “sz†æ©#PaVÖ½©¬ªh€«:7<ŸŽV;%”LC V¡m' À€¨{g!›UM•ó´:5Mó«ÊpÙZØ ©Ä{âÙ)$@*\£Z¯K ³©Xa:rM×ßH•°Õ6¥p[«­va;«Jb4+iòët¬|ŸÔ×¶cvdU÷þ7Œ@- 2C«”rì¡o6 %qgX*°'åàù(ÑEp®#:`í Ÿ [µÿÀ‡¸,qƒüÉüþ|œ1²Æ¥O‰ ã»@Ð4¼Z]hâ›Êš‰Õ¥àBazƒÁÇ_ÕùÈ4RbžÙ¦±â=¬½Fâ7’T²V½¤:F¨Jœ9¾÷ͬP- Ö|Q-Fm Y-lÍO`*Yd&í89Sb"Oûï/Êw¨³ü }õ8ªâ/¸Y)éánFæÐ?nÚ™Ä|RºÉ^ +âÜh†¾ÄX#ó¤GýÙ†L·MUI2L)%x¤©®üœR›˜qšÚÁÆ“Y™ÛZK­{©² 0‚³•XJß¶@Jk÷ÌpóôÐã™ÐˆäÌ? »B«ˆÑtæJJa*R’ ¤PX÷pš°Ô\ ØÚé2ØJVRy:ÊSaY‚ÆÈ_¶¼ÿ‰³•ÅÔÃêüòB[½ÙŒ|æýæEÜ@tjf‘µõa@ڞ鮸#Ñdµ¹)òÊû ’fÕ—Ò0Ïj+jQ!C ŒÆ–-@6[3ß)>/¢$Mz2[úÆvöšÚæ#{Žt¿Jú­%7ëªæ¯–!1Т.¿y#K£séBo­6A˜UÞÀ@½Bvã‰ç`K\kå9˜Ù ë>« }=1”åÓä¶žÈHnøRJ¸aøôkYnVúV€¸Òè›L)†I×ã5åo &¢^ï;Bc줅@’YC/>x+2 Ü–y ãm´&¶¦Ì™&Ÿ&^ ©&ìtL0Ìw·¬d³‚E%˜Ž`íø&—m$š^¼ÜhxÌV!-À9}å5Êù4»C ¤*YsÞäçaá;¾r¼FùX‰mkYÖ*¯$%ŸlÛ¶šP$&ðÜç¿Bgw Þ‚~-£—µÅëâ F6•µŽxAf%¤.w–4X)nfÀŒ^a€N”UÍ ÜV- ¥À Ja[“%ž¿”9Þˆ—ê6zr«i7Öœ˜Ûä,óOÖ1ñ<‰e4 ’içÄÕ–²*ìªML@æßÖÊ'¬ö )dë pÞ¬àJ¬ÆÀÿ|óXx’mû:hT/äÙ0zÎÍ£Ö–@­Ç±îûq²˜”µC&Êt¥˜ ƒôÄmwáyòéA\óöÜ¥`L1¾k_*Þª„ÒZTÕ„f¨µ!½iH&ùXw"%Rn[äUâ,¼!¥D­°ù4@«ÐËÏÓ…c =üŽÝ¡”DÒèˆ $î{²yôE:šIà&UÅ )ñɶÁjd­W‚>Œ¶Â²0²I¬E§¨0¬£àikHUÎ ô“"†™7 ̳rë"ó‘è eó)_2ž0Á4ådY<º+0Iƒx|ùÔ¢Óq ¨Ú)`Y—™~²ú–µŠŽ¶ê…lå0Þ­"•—Ê“¾l3õËVh0â)em™ðŸ‰¬°-æ 4½`H–L §!«*•~nßûxJ…i¬Rªk$´d˜Ä1Vú¦‚ë‚¡):F6¾«8Ÿÿ ¹þ«9܉¼©~e©kOÎmâ%>;¸NÍTªlµÚˆJ@0yqUæÖÈsª…h|oÒ›².²¢Zz¡ÖJ J#+ì.‹é8²U˜™# ÿj&+þI åì‚`'mŒ:ò0”VQë°I€V2’©rž¶lñdù[+¡o[˜‰È|±5'°*€lÊÒ`XÕÈ6Ü”¶ªè1” Òà)[ f[tQdj{|Rð¢‘"™sêB~´¶ÅÓðib¡Ö î­ò!æ_ )2˜¾F@[µÄÇîzùctÄÉ9×zæ˜ 1Õª d_ãad‘º+ñžaúø˜^ûNÑÌVxfkË Ï§Zþ›f% „ÛZïtçŠ:‘’H«!#aÀ–à(Á¶º»$«×€;£B[%•'È¡QГ1ÔÑ' ¯`ÎA;«­ SÕQVBV0gE€ ¶6†U ”‹ ”ª<¬vùÔ ÖHtØ ‘"A)þWuþ‡t]rU‘J”«²Ò;{n]¬°”gíÝ ÇðiÂÊá¶R@zk'Ê<+zÑ0‰wÛ…ª(­Çú~ê­ r€1”"C }‘y‚°ª4…E©Ê­nF¬ÒOs埥1l6az[w(šD³1¤ÔÔŠ© 1²o`Ø­gUªˆùp¨ÄÚFe²Pˆ,YÇ•4 ­ÂHMHF?s)ƒaè­²…¶1ýµù|4ê’¾›ÌPù:Ê’Ùz£z”aË­rXmUrsÚ -,øcÐ}ÖÃV>g˜¹vÌcˇ&[Ì5>K…9T… pØãÃÔËŠ·í@SqÕ6™KØ bjwŽttž9nS+™x¸ŽM{µ¿MIM†­IȬ²ZÏ„ [b…´¾£vX‚‚˜¦;¬EÓZkì6š¡l-â1#ñ0çRõݹ& ìfv:¼P%…4U)xÎ0sÑÃÒQ¼°ètÀ9ßÿ±è’KÏÙšbµZ‹m»1[s.*¯£Ùÿ1 ~šüwœœ‘Jþ˜MUwÛÊ[óÜÀ‰Ò™ÀVH†óŸ³·QUb)za[+¤÷ ™X•”_«Úþò§?ýÉÆ§ÖDÍAQeÌ.]¶²RdVáÌø ×ÞúÿÃÍa²L|c7 Ö–âŒ×T0Ôδ5% ìÒ÷›DUˆL¹*[å|6§BŒªÜ€°rž­•C>V²|8Ûò¬Y™™@‰/Úò¬ÜýПLTQvdCx˜¶6Õ®±£Ù6[Ï…¦KSX”-àAóñaÌÙ Ÿ¹ã™3%ž@¼c4'²¬­*“Õ¶ ClBóìÚ+?=nHùOd%Få`r[QªƒkP­”ɘ4†Sø³ ìDVÁÁj+:~—c«VŠ ·R‰·–²4V%ŽTHpr÷³ ÅÙ£i¤F%jUÅ+쪉KÉ YÏÅÚaeâÌSÂø·µ»RÛ_._§ÏMêÈ¡¦ªˆ»Õô aåY—Ê­›*\SU –Þ–Œ¹íô°m­)nÌ–¾lm¶ :2ÐØ 0¢£5†-7aÛ”¶É¬<­u‰·Ú6v¸ÂVâôu$0óÁ¸.ïLž¶L– Œ™`œÈ–Iu„ŽI³c"b¬)g¥ÞK¥ûÊÙ&4úÑ¥ˆÏ@÷›ÓŠÄôV€v•s[«0›P(%ˆ›\Љ8Ö70þÓßwx!)¸WT‰HV»ÄÊ)À$@S!=Pb60ÄÃüe5êR¾¾ˆ)«y&Sˆi J¸¨ û`fˆ]¶BwR#[½ræV_[X6s[µ~2›-ÜÖJÆÊ*òyoCk¤5óÉš§îÓ7›Ë1¿ŽJ:8Ðõ¤*¯o«ªÈš¶R ‚² xfkk<«- Ö ƒo«Ö`ð)ûq})5ÂÈôyr°•riðêóSÀ­JñoÈÙ®¼ÉgˆÇcê¨BZ_Y1°h`UMe;Lf¼1¥§@ƒ¡qí˜ü3Éd=—Ü0¬„­@‹Kœ%Ã4VŒÌ“žC÷£…«Ã4L…1ü“Q˜\4[VBª“RVkëÎË6!¬Èð—¿ÿýïê ä'ßÜm7G£³@XwŒ¶˜oUk]ÁVÂŒRÙRæ#˜˜Ài‰eé¥lYI cÃiñ^MnñÄi|Ö…azV‰1ô$ `÷XkLW¯PÐX›V9Ü0)L}säd¸s?0ºsþZÃÖšª2ÇW®P`dw!jµë3¦FvãÑ 2 ×‚n`—†Åmu¾Ó;2·¢µ­B¸F1û ùÞ€,†˜GkÛ²YYu´U 1±rÑ–[3‰^†¸*)a+K/«Ðê+þ8~ÿ­ÜL„›±²Ú+7S)—R˜¡B±ÞIÿ¥áÚfîAcXM ÈksÞj¡¯ñ:`ÇáÜÀÞ%¶&T5À™qMKµÆ4ÞU.¥]µ¬êõÚª’ÅJUdÊ.Ç…Hu |¶²}b‚|lÅ­Zo Þ^%²ÕOÀæ/àÝ@nV¼§fuK™è¸ÙVKÙ„%€’Vš.è, ;B³µÅ™¯€4IJæžZ‚FÊJ‹”ù¤×ÎAÈlûÄɪí­CÚ6³°2‡ `.¤ ¼mŸzY[žÕ~%ç;³B ±lJ@ðO;ÆÚ…+á)¥$±¬€™¬­¬¦‡=zå™C¶U½+^ÐL¶,®—UÔ¥+gÇkYm@V••ÓxyFb2‰$æ¿òž©­,=#V.Ì ¦Ú¬2oxXÈ* WËD\¿s!«Äéô²Õ‹ ™à@VdËÇÀe•{߬JðjéU Ã5BVŽˆuØöéÃÃñV°€Ó[›°î iåL&+6pÛ4µÆø@aþýïkÄßê#£6)ÛZWIЖ ŽLcU+‰Ⱥœßl1=z$[†‘Í“Cž¸mJ²ÚÕš~“w9šFZ½•Æ‹°Z˜¿mcDµ°•¥¡¬WŒl'µÉ„0ÀJVÔ.Ok_wÛi2ÉPÖwoae©³(,Û0Ö5íU!Ö Æ#¢1²…‹d %i`Uý”qF<¦v ¬H³Ry«°Ýµ$K`íÌk×løŽ€L$c%È8K™AØzÖJxöëÐGŸ'=>R”²ÊKeNX{mˆ+™À+$(ï—þóŸö¹Ô VC-’âU £*áÈø”0Pù›Móc%jZÐðG:^Ðð„¯ü\´'äÊh )dí’­P ±rJ˜f`JîÏ?ÞV^‚ܬRž‡UaƒyvR¶J˜|.ô>×ô­õ¡rzµ™÷ì­¤¬BaÇW SÖÚ$²j“Ól”0’Cƒ½ ZpC²ê "iT©u.+~µFÒÄs`^ Ãp€[ž²…ÂRüëÕ ™`\5¤PBtöîœL˜AÖ*²CÅÐ0ÁÈÂÍyåçñ‰ãò¼–HSud[Zw{ÓùX l 4J¬ÊVSYµcTþ¢9‹, €¼c0@Ö ÍÏ AY‚ªÜ’¦Ì À™¸yà&ÌÙÚ¶•F‰µ€j!rÀk§ í\je…Þòz! ðªhrË¿IPm¯/*$pêþ[o*b   Oc{üüîØÙÒTb€ü›îêXqÈŠN€gØ•ÊãMEH­;F4§õ®)}lcnÑç, k¡ÜÙS6 ±ì˜ük”‚¯åYl €j“%¨ÐmÕ:Q²~µ³õOÀ8ÐdE#`×ÛE Ø 2éÔ"m‹w$ å¸ðȶ™\ã³xmÜs.EߨpUýÜŸs£Ö+FVÊëe¥qØÈ¤­Ö¶1ÖóO[Â)ØÁ­×ÿs Ö쇑­P%hjÐnÛù¦ð•[ÕšÄñ:aÝ=‡lEÊ’YÁCéP€ZbX9Íñý^1¬OãÆ¶u'R1l1uóÉIYßÚÁªºO˜IkCZkÍD9FVÞHHYµ^ Ü%ËêBfµí;ÉÃD Ver[ IªJ™ ŽÖzUØ0á•0™7&Ør üƃ”Â'à¶îH#QÒä`}mssê™Ð3qjE?ÆT56†¸ãP’Õº©¤&Øœ5U ûv+÷wKH[>ªiUhK -D̶Jû‰‹Ç0TëƒÍN#¥©û=€sŸÿÚuº0œ•¶]¾í™ãÉì2%ÞÍtp0U(‡Ûš'¬Þ0‰‘2Þ¶‘Œ ØV¨@£ E 4ÂÔ8v÷õ"ÃWèX‹x#m˜JÜ$AÊVb+[k7ÌŠ‰*¨ ^`T5^lζÜl¥ª¬||—™³Ú@Y2“ä37$™Z©~a²•mÂõ2yOÍA”àkGÖ„=&[µM•’¸*³a"VΪmæVÎÂRL'ë,½´]/>¥V t:VŽÐ/µÀ3TÕÌLhl;K¯MÊ镬Å[XmMÀÌñ“REÃX×´KEš'`UµB@ª,ó4 ãW«µk±MSV£Ü긭l¸,sL÷ðSÜþçõ ÷º@%B_Ynp˜¦kq«¦Â+ÊÅ­;ËÛ ßH ú¦¼EŸBY¨{ÓדžZA¯ M½˜ô›V>­ªº=ÛðëQe5C]dab¶ºpî%ÌÍ–8«|ÂÈ"7V”nã=,}þ@G#Öª£’ZØÌÍ·=¾!GCržÃÇ-‘R˜UŒ’ ,¾/m*”ծ޶ôY‰uT‚ÅŽ“9*¸ Î'¥¾4È8sÜËé~r¦Œ¯Ù¶*J‘É€cb²Jf+ªµƒ¦©’Íœ_H• ŒÔËé0B9¾F™Ç襑”-ÏÕ¨PI½Y˜râ²¶”¬la† ˆWž•U¶g]É廡 `•â@ÏDØü•¾âdy®Ù;a‡ÂJçúåü£úŒ° ˆ¶½ÊÏô®]Gog‚ªŠ·+<²òk ¤´¶šÇZ¡U;]ÈàÝŒä\‰ma›Þɬ0[%¹ÙÂý»GwïZÊÙ9$£×׊Gv-=³J2ÄÛ~G8çµU˜²* ¾Ç +´ú ¬¯ª4xѨÈj1²&ÊuŒêÒ ¥Êrúy_»  ¹4Þ9þJ|Z*Ä+O¦Wž@GhÔ^8)Q9=äô½!ƒ™˜Ç_äìË´±»4‚”×õSÄpC Ëñ}‹1ICf$¤cÒ@v¥dé‘õõ«Œ«àÐC˜T¨v³©™ DX–R c$·Š‘L0nfëL8+1¡ILŸLI ÁY uüî~þ'ñKÙ [¸sÀÂyÃ5ª°FÕŽ0`a*8=ÐŰ’€Óqƒ›¹ŽÊ1²Í `**Lpïéüµ± ÄzaŒÊ–I­­ÚÙfBÙÛȰSK5æ¢ôBy+@–•qógBb¼€‘e™HU"@lÍ–¸Z#e(¥DÖÖªªãàc(›­,\Èîå™ù&o ¼ò 9B¹ìjñ=&µZg®» Cú˜¨‚Y9£=œ€ƒ Q(±ÒØÆ(a¢$ÛmOåýqœô²lJ0Ђ–µr°bð²mùÀH[¼ iÅ4r˜ê­8Ò{9“ÕY À¡VKÆ9ÍNW÷:Vèì”97mÙÊñc°XŒç/4åœ9™Ø©‰·…)Å•|~Á*KÏÇzÜ¿‘ )ºüz9ؽ?øŠCªn<+™ÛóÝàÉXÁFõ—€þþùÄ­˜rn€èÀFý]5MíxÂæ¨¼²ñ­Ðë¾§æ=)2%QŠÓûbëÒp¸ÉÏÕ%°šÊÁ­á|lc𳩼¬šDyš “ ó±mí•ÀóÙ)¤ô•Â;×þ\¡V¨åLÜTzb§†kjEæi68¾va¤P¢Kód…dŽ$lé“U(¨Jd1±r)… =†€òÝä”J‰'Ã0a^ÖVл±Þƶ$`UÊÌÖZ`Ä;!Þ pøèîéX6= ¦9#sº~?×HåÖ [‰ ¥D§è=„E&›gÓ*üü½ˆ„Õ#´Ê ¼Po•M`Û󮇖 h*1†Ø>ÿ+¤4’IÃ'`UÞ Õ…²ãIg¾ïÉóAæfK\>s߀7ž¹ K ¤?Á>“MoÑ!{§U!ûâÃÈæ`Õ‚LfáÓEyÊ}u g‚ïµôŒm™Àý…1™á;Këæ9g¾?fc5R÷k–æDšª¯Î®ˆX/iè›ÁŠ·åd5=³.pÛ.­ñ0ô»pbSÕ¦Jƒä »R³ñ!® Ò ¶æ¤i`ˆ­ÊOJ+B3dÙš¡”.d kç!u!û׿þeen͵(Ä”Õß ?d:ÞºóL«¥ÀœU)ë˜XǤDjZ£<­²V&4“ÅSv4Õ¯oä`È0“N4þ[ñùOYA_»dù”J·a(ñ Z1´;¡ÄgèA0,ëZ¤zÜ‘yZ‰ë’!ÆÓô%N —R®oÛc"Ô¾åž}ïU¯™BÀ 9{Ôú*um>Vj¥hèõR‚± )«ÓÙÊ6•5+ +åd!k«»¬ß¢~ýõ×^Ô¬Lâ¼R½Ìœ›)‹H Ã< ð ­Í@`æÄ1Ó#E·AæÆ¤lû…îzû£2’˜†¹ ïƺ@bÁ“’FI÷3ÁË.’Õ¢ÔFb&v¨ÀzÉiNïÿõȆg„™äœ†³¬ñLΡieUÕ+M L¬D¶G¹g‘a+,%ÏdlSrhJíêã­¶ñ1‘0+X4¼ƒlùÄô»Ž¦¶ iÕº£U[ k ˜“Lpư²nÐi­/™­T_zxÊVíÌC`5ðRôïvgÁóÔ¢Kó/oØrërºØn0…YÉ6 ¦ñTéX/Xa)d‰¶åTE 70^`ò÷K©ê¼ôL(iº%Yb¤”p™”]) ¶k¼Æg© ÐÛæ™&ÌÍ °Èά`í(9ó¬›È–¿ªæìàôÜàfÞëUHÿÆ5;‰¿ynLàÄø4VnúJqàO©W‚‚²maAÀ–¾’L¸á1€NiU[Ç1^«Ž+÷@Å™ã~:ä€Q[tWV¤8PVÐ`„î²ýñ ö–"óTk<˜9}Uò$Sˆ¯‘áÉ6Rz[§aB»ñ ù0ïg’—³ÚÜðf"a§ Ix²zÑh'ðg‚{-RÄ0RG#ˆ­üôVသ—T—æQšÐä¶}vh˜¬‹-QË>F—ÏJ_]ðjib:{dŒl&ù(ÁÛ€Á^@ êÈZ ´³Ú6UÝã'X!^w‘O…Ös†ï¯’áH«y0@Që p“2Yw¦ÈDJÐ×ß@RÚÞŠó)ðæ8ŽpQ]¯*íˆwudÇñ~~eã­†ó·…Ûþ?ºîhWã6ÂðÅ>¬a ‚í÷‚|ÝÿLmë(áS],Ù=sήd'!kYËïãŽ'0ZÆ›nD<Ì/×xï=‚,rk(²@¶ªìÈ0çôïÎpã´¤ÁÇùZž»4(ÁYèûµÄ3é'ÙdN¯=«lÉÙ TaÑ,9PŠ¬Ñ  åôxß2 ,ϘFÉ1“ÆùÄô}®&°’ÏBcƒ”è]J®Ý¿e¨DƒL¯·wŽ!PÅhi>LK¦Ió0¥ Àˆöá,ð[)L´ÀªõÚ;`5ªªÝ¨Ìì[üX)í3õ‹E Ll¢ óçì¨t–»¿ý¹µÛœŒÆ@>zótŒa‹ÉÓ yK"­‡!=‘¿^úµ{ ülÉŠ­Ñ‘R¥W5WÉ\  Št„ë=ÿÐf·÷|We$E9+i6@DRJÈô9È‚¬L¾ô1¦…òty‰¤¡¿ÚÏJx‚×$Þ%`·üa‘Ûùê¤Mˆ•|'ìOÙΓ¾{ÕB™g o72z/÷Ëhn¥d4mØn>o ç]?€l.Aëo nùÔÓ†Fw—ÌÉ:º/+ÇþŽ”(7´7䣗ƒO‡À#iòiÛH¹•ˆuå€1(™®Ë©#ü‘‚r€ U›+ Œ«É ÀP9Ù‘Œ+|ä6dîèÏo€ªµÈ–wª4œáªY\Éq^Œi%@fb ²L‘Ž™ËýÒÞAHá_šíª¢é³d?¤ZrÆ{wÆ×•’IåÈ&îѶU‚Lèkd.Î_æå•ºì£…À&y¤„lz-1nj+ØíðôÚ\Õª‚²Ç‰tu…u541Òtë¨ô†’Y¼R>ôJ®€ÇX¯Ï”y¡ÊySêRÚ OL–#ÒQ$h7]Ú+õbº¼XÎþ£*UQêç¦9ÄÈùÔ¨äØ-è9$ˆ‘12O<+m g®‘FæÉ0“ùgeŠ áll~ 8׸ëï3Õ‚õ–‰Þ–®'ÌM6š  ÝÕö±³.ŒjkÈÈÊùÈ1d)U9À´Ã­j–ЂÛ§c2˜ ¯7“JLˆ…#Ò‘ÆQ‹cÑ&1dáâ®_‹Ðôõ Ñ‹¡Ÿá4¸cO—²µ´pHAª}@IDATš7çÙ&µÃz­§«ÏÔCõ“n¥W¬% ²o Œ—ÿΤ*Œ´Fyû l¾.³øOïX{)[ äS£ÜæóÔU#f†îëH\uË7Žó¯?ÿüSí ¯Tα Ú¯a#i’2kcDX®DO62¼ àØ]Ãa%YïôáÄUazaɾpÇå;±Æµ`dA/ûr°§?¿å¾‘JmN– f—‚ëâ/·F³Ê^O CSd$ hn².ÕSû(É”š[ÆX¦¯BÇÚ“É"-€#Ъ™Ð»£ßk-ãHÖ’™ûCÝ? »²­ÒôH/ƒ!ãc f5ºÁĪ-& JUG&@[‰©KntI XUÀávæÃP8§ðÔ°J²’[´]5¶†Œ¾@‘ZK|¤ŒlÛÜd/OÓPY¥é°&ÂJøä‚¸é ²v/€Ìj€ræÄ²ï•GPE:Š}Xܶ!,´|»Ï £ŒoЕü^’’­RÓÓ ·|z¼èÒ-úc@Õb…®J¾ê>,ªbð€¸å½Øh½0g‚®¿_h#Û‡2 ³²€lJn¬Ì•UeÁ3[bA,c–ûOéyª¶O ¯=±eLIF¡ä¿‡Ö·Ñ± ªâÙÞNjI½xÕl Òäéú¦ ¼,Ù†Vr]•´ÇÀüýÆà†ôËÁÚû‹Rz½økU%¤j£w¤A*ÝÕ>ÿ‚¼vš=KL ëòd}Äl3o ¨¥[ÃJb%©«€Eb ™Ì@*j¢!æ²’0BËñ½ƒ0Ä¢ã;CÜÜ£þþ®&NôùžþïïóµÐh!Pʤ÷qlÛ6‘1×þ“2Ç7±ïX82·^ŽL³’¹˜”@C}o}C„oHßáÖ+cèay¡·Àt‘ÆyCSŒ]ö¤ÜÇÑĪ”¢vš€ol¼Œäß 2R/’y²­Ô‡hÆ82†4”]¡ÑªÝ¥öliD¶r;Ó«â—<ëâ0Î91,ªªöIvGO‘¦wë °X MŸBk¤Çàó·Û%£A0± –W´,ˆMA’¹5¥÷7Ú cƒÈ2aœ¼j§´vk(!Es‰ëÅði€¿@V×àüÞ°Œ‰þe}¤ ÛªŒÌ'²`U©AŽ î ÐàÛ|¶íì¸åa>)"‡œ1þ(‘ººf%F#²0P"Rn=>­a±¨ÄA¨jÁ#ýñÇž&ª«6 +áYëéØ$Ç4ÍàÒ ùGÔY×R˜2Àæ)•4¶d‚Ž€2[%€¾jÇJ”–ñjª€’ŒÔÛo@nSÅžàã)4ŠL0}’iª½@ äÇöÈ™ø€ÛPÆGŽ©…O»å\®E.ˆ9ˆŽ€.áÈAÖbyŒö o_¿©aÛ†å²Õ[™kfëU)»¬R¯Š©ªK´’¿––ìàA˜ÃOã(taåŽ ‚1MÈbΘÈÆáí#ºšö>‹xZÓÝ fõ>€csá^O»¡Äñ äwº’ˆL£+Ò¤M0xþÂ#`{4Œ¡ n:Ñ]rû@ñ”²#ÿ£»XoíÓDãR "óJª™9]^§yËÈî2CGX6·¨EŽ”)•Œ“ÓÃ}%Þ6ô°q°…aUq‹gÕn§$Fâ5Fë2È÷á¶ž­”º`ãâ1}ÉUã1)¹ d W•¦vþ>M‘UÛ9O&ôª‘°«…‰í/kDÒãe$ÙJª°Œ$^`DG@õ'e•¾YÈFdÛ5•h`Kjé¾ÈvÖ¢Ô2zï ÞÜœ›ë)8Ä«:Ê:"yfëˆlmJþIƒ¸;bøsnn&p&õ®ý®s¬8'h¢# —àL½Çr½0½ÍE›àÛÁ,o12ûäL`1L u Åõç–&ÿåd]„ynƵmÿ<‰<›}w˧­4ÖkVùÀÖ«‘¾ÒYî»ÞH€¬GnÄÆwëµ7‹ vŒlŸÑYå~švЂ~(tûèe‘[ùeà ì5_Üw ©—ÀÑôVÅ8¸Û}þÛž(Ï&–× ´^ËÃÞIæyÂÙ:Âõæ##ÒP&«:â'ëh ÌP6K®£$”f’ž¬^ÇHG Ó`–14"7%ØzŽºÌMÙeϤïßÓ“ ¶µøô\JiäF+útZc½J~ßÊé[©FG@&ØYµLŒÜ±d+Ò‡U•ÈXùÀù«Ek0&:®ËÑÂܪʛÂA¯Ò5;Ë/8œg½7Õâ(;‚lù÷G3c£o÷ç—3^‹FƒÒaú ÐP¥ü9·°˜òü'Ê—ÑpGr—ëWÚÆZª)Ï%îGNƒÑ’‰ ֎ɳ@jtLÀÌ6 •¶dþŽ Öø•>ƒôÞÈÂ4~µ ì=,øÐÌÐQtkž½@£Wií ˜4ÎÑnÝÑö{3 h±[G œƒ|¤ß>B•>¬¤ ^oŒ£H#Û°»«Zž­?`Ò`ºËþCÏ 'ÐKƤ·ê¨Ë‘Æ7U†1sÃf¥á/ïÏ­õêêR°'êµÃm"ãµ4¨;ÊñÈÇ>YÿQÌÇkëb“ÙG8 -[ÉQUÖ%h”šíCÖT×2+ ,T¹é…k”»#ÀËôe x-Þ ßÊç‡>Öß_R€qîŧ€óibã’É–i héš&öðº€]³k2g"jÁ‹¶"+‡µÈ4ü“émÒt ûMh×¥ PrŒƒµ»š–ôZêÍ0=%PP²"4°Æ¦ˆ‡»ˆ£v·3š?rxVަàµ`’Á®ãh(Œt_ÌÆ)5Ì)3áÆvï ê¨u™H)´T%ðm(·az¥H©TµÌ0 hCUØnòøô²Ñm%'³«u©uÍØ€¨dÖ6A¶Ûºø çÆ¼·Ú›+ã‹za]9Á¤ýã- —u‹ÆÉ>ËøG@Nư‹óÄtÜD&í0ÏJZ€ª¬|ÁlX¯2C‹éj¢*yÂx&Úí %þ´ þ¾€‰°¬Ë zsÎüÊOÚáʺxòwlbb%kº ½£à/´ÿØß‘8g¸e0ãÙÌÁОOɇ #àÈÄ a-ûÑ«QU£œ˜až÷‰P²šL “Uu} }ªæ‰¬‘¯}²¾]ønA¯*L¬Nœ@ûk¥$R–[µ[륇3i%í^èâ€Ú îÊõâ]pâ–&¦UûɢĴIæpÇöTÅ[Rð×(Ã`ŸYW;´!¾ª#LÌMãK2DŠ4Lš´ykhÏsÇ1–ñòéçÿ€©?½ÔX“ ¾šI{ ÁÈJ]Ã`‚JòëÐõñzEÎ19Èu¥çOV¾\ã°ÑB©êºÎìçkçw‡7ø® `\ÄÜØOóýi (i¬ 0‚M›Ý¨ÝΊß/2‡¾R›ÈAIèU2‚²¹Ú«ÒŽgä_ Ùô”UéÅÕžÏÔÎöìoíðÌ3¤¬w> Ò—D#¿s5fž¬/†¯2ÏrOºUkqœæn÷?þÊ®oqJÌw£…A|ÕëØE`2V=  xZF‰Ì1“ZäåIãh«Ö€ª¼}€Ú·H }¶€}Ø*á“e‹ŒÉd]ªZ^q+á9t7j=+?Õxo¨£D¼5teØh¥<å4ziT·„Ì 0"\W¥u¬Ž…¹ï(ó7`‚É* ¬š –¶…â>DŸ Læ» €ó}WõzœJH?þªæIß±®Úµ8 dHÀD¹@ [€ØL„£Üž4—ûüžÏ4•à b`zÑÄ>5X»,´‚Ü`À-ø šuì®Þ}ñÝ´RšMwä&2¡é(ówÌ'™Œ,ZŒÌÂdn2Ç7w̤e(í†)ØÂåv JÛŽ$k ;Î OзÈozû7RAÆqkÄç‹}Èj¹ßÓÏ¿#ËܧC©Ú÷-%ÓñÛãØ8¶-CƒQbŸ¿?š½¶#¥O2š0½#‹6Ä1dÂÇôiäJeG»µ0¥#qáRŽJ"ÆqãºÑô@†^fxšÈ™ól>HY»gá&0rU>ÞGµÞ¦À #Lq Îzý ðQj [|z@°Ò4W~•>‘vXËvÖóä`b‹åc"½÷t/ Оš¬q1ŽA$ÐÎx¡W£ê(w…H¸ +h0pn%,ð°è;ìϺ]/'¶¶ì.õk òJ>éÏ?x¾´Í”3ÍÎßµñ½2¦1eäx]¢c½Ä˜>ã{Á“”hòÉ<Üw4Ez8ry;HSñgûÜJ ¯i°R<Üs+yq¹¹–ÍE¦çÙíl¥qÎdÇôøLÚÁŸ¾º´ÈS²5šxƒT‘E²cÐkšîk”ø4¿Óӓш6‰‡E ¼J8±RÓ-éØÅ½d%Y©õTaž®ì´R²FÐøFt©Ö¨¤*Þ–†Ò0ï3J WK½˜€O*¾‚¾~@W(³òåosþlMt/U$Ü8Ç~Å ­¥õd½éUE/LtDÂe ’%MQzd×Ù>Z¼ªvÀA[µC#Â4Jr>€0NUÙ"˜Ë¹ÒÕ±Puìåxßò5êM,×(GšÐ{^ïì=iZ¯+4‚Æ¥t‘ñ ÷JB—?˜ø¢^¬1n1|ØŠH°l1ß¶4»ûyaôöÑXîG¸.b%ØÚµóŸ@oA@)Te£Ë •úßQCº ÿÛšZL)˜ ûPæ×"܈à úö¯¢FG}±;v5¼#ÈAn¼MÈb0boÓçg$7%†aÕ=¬Çר„Ì0àî}ÊJÞʽÚÇD¼Laú°¬TXµm)HÖrʺ²‚·$½º”€dH£õÚ'¬ÚÎü!óÑÕ‘€L82œ³ßÐJÄdEX.µ8Ë_áùŸJ[¨…¿±lG¼Ü¶na:FIDÆd¨évŠ‘Ž9+Ÿõ"9Û§kè‚•úþ`Tið-†±pƒ(ñ§/+ÑÐÃ@áûÓwÉQ—\µ%G|C{ L‘?CâvÀ›"*ªrîG¯£ŒÆéÚß7D»®<ÃJ]JÞ”&ÄÈ”°W‚kIm¾»œe4Êu9Ò‹L®ý—¸R™'±/F¶­¡Ô¬Wé¾ÂÝ·³^¼XËJ‘¦Ð«Æ'3®£qÙj©´‹8ÆDL^¾ÏTU0‘U2¸‰á·;{ÿž]©öº˜èê²F8‘íîÈ~Çð˜4kšhš2²å‰Ãަ˜+àÌ+éâ |:ª•Ú<7J›#SϳÆ~Á"ÏÿPFµ½Ç,`¡µèV§ÿ^¾.î4+”•ìÚ1‡°,0ºR;6N(wáª[,O¤  ¼ ΰû²'™Ì’¼§ðp~ã`¥ tÁÂt¼è¡êhÏ6—…^GíÞ$n%ù0ZΤvš5bÈè1‚'%m÷RÅËÈ" €9cì +.³” U@ /`o"k àë-ã9ŒÌ)äªíP6¾•`š³ßïúç²"TfÕË”•ÚÒo7>¶y" "l:½Ðž +éêÏNYà‘€vØÓŽi«v>¾LÓëM,Svä¹­âÓØ0 —l˜X hùÚYáE|²¹çB¶Æ3 <ÆÅæ27   4¢­|!5’9³ªÅñZ~<›…\Ô54‰ðfá ³¶¤vÇ[]yÆÈ/WÊ?Ÿôl&®¼*²Aeí ¥µË‹u·ÃpCû¥¡¤1ŸÝ Ç3Ô%;rPôýoç-|ÊUÉhÛ¶òQ4B£ìHV´ÐÈo¢ö+íK¨êŸ‘Ú¯§¬±wÓ˜'¥R†1p¶éa-L #`—ò-’M©dçl²Åkdâ= T#܆MÿHï¬Ä/Ï<Á«fiÀ¹‰6ð9ghš6l+w1",‡SFº;L›4×ѬƑ‰ZÞAœ˔݂^ÄhlbU™cšÜºr>•Ëwþç…›ˆ­ ÓÈH«ž ¾ÿbØ÷‡¦Å¶gzG|>2RWæ©17Õ¾0«æÖ2º€^,}ü[ÅsοµøÁTÊ¡5#Ò+õ[´j?½X;P6´tat9n¨^øÿ‹öÜô­Ý7J+¸væð~|ñ½gû×›s‚Éê’÷nùï☽3^¤ÑU£oC¤# ô’9/¿Ÿ—ZØ&Ðc€¦¬=^ (6«®Ž} ýÈg"›ÕÓMɶÃîcUrÔÒn¾ls®Ôn²#q¹aÚÐu8¼ÏÒ J ¼qÝë%aa4 @ ·ï<¯)6Dú‚·ŒéÜÚ-¥ªhÄq¼R“qÞ’UuTè^¿þõ¯Ayin6Œìi0Æ1£h0¦ «Ñ`ÛŽp«7˜††M~ýj ð†ž›ÐòCà(ðkICŒo.¦õ¼e6iG‘8·|fNÀD$P¥qÓMqTí(;Ê&¦q,|Àýœsà‰Ì ÷€ÍêD]]‡•cæ5šH,EzJ¶Û§. Œ—»{úv€í–[28Ð -õ"Y™B€l–c¡ PâcÜ«o6€ì/9”Éøp 4´måüe|žùÄ”yÊÂd<ý3(èUaá©ûP`Êlki(qs[@¦ÄDR—û}ãÙöPJk$ àÌŠ¹L/`ËmN€‘û"ÁuÝÉçÇGÀ9$¾ÆÇ`BC«âEzS"e$=±Æ2þê#•hDÛ²ÅÀ2>²#H–&Mâz"Yt)]5î)ȸɯCþº¼^_†6tôn]SA/¡>{Ü‘«r>k}=V•ñlNÉ9“|ZI£502²ðA·‡k®P;s·h"2¯q¶ø@âáñZº†£ÑÂ?xø~²âŸ³Rs­G\ FØP&PÂÃM:6…-~Õ˜éÛeàâÓ·^£óW´ xÂkô |f4´R]0}/ІÍRm;º€€¦–vÀ°‚üô0ÒQ´Cæ.ÈVðרÜ@¶¦h9°m“F« %>éùH™UL&²¹²j¿îÂrCñm˜’Õ߃¦PêŽ@îb®vß1žÉœ I#€¢=ŠáLÄtµMŒç£T×Ä”b†m’›LOih¯í(¸)ù¶·˜£Dì©1²ã d÷Ÿ?#r Ãëu„É`—#åÙGtemˆ4nqVødóÇb Þ…cŸ«˜x&H Ð‹GÖŒÁ# -5öÎ~94)`2%²‚9žƒeŒVÅï"ßáŸeÈ8½ß¶é Þ¨%åôz°’‰»2fJU½¾•Èô’‰4l1J2¥\;½R¯Ñh¼.ø}G$†’¡vŒ`…0&4^‹ÏÅ ip†Çrž@Qµ­š‚§1eíð÷îB ^#¾5”†€*« 2$™`WåC™ ¾¿–Uâ£]U{oVb"·pCóÑ.låñc 11ж2ö%A³0¹e®…‰ÜP—€aËÈŽa&z…£ÐDÐP$†CA¯”~]€X)à^MÔ¨Ú>Þ°)íÓg× ¶ƒ^]Ž–éEËÐc ")º5²ñÜ΀,1LSoùÜá†ãËÔ…±lOØ,Á‡¹¬!œÃÝ­ÏË+Í!}šeUL[÷Åsìhðý–dkº¼övãœ97ád™cŽú.χ |¡4W–¹ç‹$öÈÃ|Ȉyf¢„Ää,€­`&ªa%¨ Dº;&O >óù‘ LLˆæŽ÷’•Ò4PªÖâ ý{b]ÂbÏ.ãÉèa¡K‹ Ë*~™²äô2R óJ)ÛDÕÑЪùk Í'žžÒ1gCC,ã¸Ý”-Ü8YIo&p|·FŠÜVjèÚ×ëR4ÄzUÂï‘b†€•„ª¨š›FÕîøê}(cê¥ÔH™¸ÆæîKÂS£®6L<¥öñH¶í@ß¶&f¥±ÿÓm•zJ¥®³ÝðªÂõÃFèôÈœÓX覉OÏýSXWËçŒlC &73ÇãþýåÙùȽ¨1,[€aWŽ$HÏ @Ê Ú™ÀkT²°£+±ËAny Ï˜ÎŽ¥jž@Ë,ob2-@›×®EÜ7øý»¢RÏs‹‘3ÔÒƒ÷#IЭñ4r ì4Âh¡ŠÑæ©Ëqïù:´F-²ßðû0ž2™†É‚ ¨Å±èÈÄ‘uqØeÉú VTÛÍ8-_Ëó?1¶êÊSvߦ4·…‰Sö‹ÝQKnÄ”À‹ZýëŸÿü§sj /%i"|’¶”`Á¿1Ä[]ɱÌ\ ÐÕ£lPíx¯Ó\¹0H5àÀ™Ò\@`^œ¦Òº’9š+÷Žù+eÕ­=e?`<¹ ߟ“kz Ã̳Âl4Ìܱq¬ª”v©##@*sËÓQ˜®Ú’5¶\$ƒè- Œ,ïj²AÐ^Àn4ȃ Uô {ÌG#™Ø2ú^É_d•0ýº÷ïctղϴÆdþ4€`Ò”6œ’ælóý¥ä‰Oã÷£Æ®$è^â4ß×nàŽ@¥¦ëE6(¦j¯šOC†ÔÈÊò˜{‰p´€œq-¦cRn CРéËÙ2ùèÝ‘ ‡¬â1”˜¶­ °ðQ­Ñ§Ï )2|M&x­òŒyqíZn®&ó+©Š÷éh²²ܧiD®]>ókóùÃÒ pH)sp;À÷PÞ’zkÄÀ›Pr4®)ÈVj=<€Ôˆñ9¨j¯Ú™`;Ã}-é•r“­Šp+QúiâosÊ~|úb(aÈ*ÑàŠÔ¥Ú‘o”v€ ¨ZoÏ„Øx&dŽL0Æ”­À€R²HG>æ@Ów™Rcà½H½2+A ( $Pj™¦§IO°Þq ä((­¤w—«¶“|²•éiT[c©ªÑ ×[#™+ûG>/¿ÒfÅÈ)èµÇ´j|Lk´ƒì3jn²þv˜LU©1OYÉ<}SJáØ§Èy"û¹ &2¦YŽÂ‘¹¨QIгbÂkØsUb¥”2¬%+¹v$Ø&ü·Ûûyó4L1®FÇü›î¨ ÏãØ7“§£à#ð‚L¤WŠ©Zéª~&¥WãØæF°’ë•óT=#¿C9*õ[Ëž€.?ήOæ÷†¬Ånëù~˜Ž¹qál7}$&+Ÿ€éYXÁË•ôÒ´ÐDJ%¸)¶¿jJ@‘C&˜ue…Çøñ1ã“åi–gQb‹l[Ì×ò˜ 1e2¸Íkl 7€CS¶-X  '€i`L7ðdVÝ>&Lí4a€FÔ"³’S6‚>MÇZZÐ 2X,³jOü6ÄŸÿj¦ª±SMÂcð4×ù3ÉÙ0ЀËï‹ø€9$•˜ÓÈÙ`¥6kq #z­Úgܳj+ÑDV"˜’à Ðè(®ü$ ‡ åÖà“#2Ñ¥ŠoŠ k\;¦/¨˜RI ë8hgè¹|­U)ûŠ»¬Þ¦+ýÌ·9Ã6o‚í·°R¸‰Üj‰±†A†Âºd>¶L2F£*l²Û9Ö¸¹Lº2žÒ/)  ``ŒÐõFcZ¦¹²RûŸ îÇW;¬ªEUÖ(Éî…ôG¯Í«–éñ>€ÌH2ÏÜ çP ÒQÍ´›Tr w”3´“¶…i¶¡A°¬·zÑ%¼UÎøªñ‰9ˆ> ÿÀšÑp=Iõx=ð–³w¥mSU{VéU1b혂'·6Ãh‡»cÕ<«Â7  Ù:V’×…„eúF8ê•ÃûxŠM!Èä6}~^Û¶í46…˜CæÄ)Éø†ÒÃJµ4®ä<ë"ÃPf˜?ŒÙº¾Ðå˜mSZžxúá–!˜R£#@æ6œmGQ°’ìÐm›@{‘‰’õè™×¢‹Ùt2&pú×dŒ^]LÚVÚ•‘ñLDþi8+™+ í‰ôöãš)¸­× Ä@$†žL; €Hp,LÔ÷ ˜¬®V‚ýà À)òAÈö‡®ÐJ<oX hIYµzéÝÈVj!+ˆ[@VuŒï(rX F2éø£ô’J¦Û<kãFIÀ]Ÿ!‚³Ü V5¶ qÇ”}y‰{JŸþû˜L´ ¤ì0·Þ|4âá.¨Ú›Ïßh‚í“¡£àÙ:æoÑ8&áL`AÀGA `(iЦPîH&hêÅ·âô˜ðŽM¿3Ï“rÐØ]° »~]iÈ[ †Uß@4(+ÉHLëUŠ‘‘" `ºŒïúÄÝ‘@(­OL†¯ËÇä—ÕÞÍní©Kµ—jÛá֣ѳÊöÏáÚ­$ü~ãÜ\ýSJ]ªÈò|ÿ“3‡wb2%@ð´³£GÀá²v?`JƒÒ—çÔœi´ˆ· ßîÏOÁéü~¾M‘ d‘ÕÏ^‹L@öÃÁQK%YtÄ‹ÖÛ2}”𕜤¥ÄðbU%œ£¬E†¹Íîëê»Ý‡˜O/ Ä™·Ø»3\=L&`›\¿³é[äÓ­„ÙDzS0Ä]/=Ÿü1gÆâ«XI»ë¬¤Jüc[æBÉÐÚ3l·ze>læ°¡­Ú8>ŽJ€–ã{ß¹¯n-|ji"’2†¸Þ hD<Ð2ù”Ïç*:ëœÖéXI¦ì9^þ|~yeµyÝ™ƒ€]’@ ÏÔï¿ Ï“,Ьvxm»[U=¨Ï8#pæÝÏFd¼Üw úFX‰LuâdQ{‚ÖÓeU%>˜g&‰ëÚM‘µä/û·]ÚyZú¤‚mCe__²f5´Aõªº žÜ_ù¿›o1<Ãí¯E‰fz`ík¤íÖ½è2>} Ã#éa-þQöøÈh™2ž4×àóUìØ­»EHÜ”Ö 3zb ¿ó'‹oD]²…ñ9Ã]Ó1AW«QÔÒæ>¤®¶ÚËp USV’2Á‹Ù2q/úÝ ™xŸö©)TeVÚi´W"v‹Ó,€ÙV@âñÈä•ÕÅ¤Æ hr ¡1)+…›’¦¹x‚0m—"ë^õ–1dJB—+w”ýŸÕ§Á÷>{¥~ „–ynmd]JMÉ–¾#Ð8ÇH-}])ë"¯&3E^M?³€’^{ªÂöÜ -œEßóVÕ’ÒQd‹´‰0nds#á6)w4Ë\?/xSøügkúÆ%vD’Û\‹®àe‚Â>ô½?F•ò4|WŠiíoÓ¹¾@: -í[›é¹m@£?7ÌpL&•d×o„ìXð7ã ÙÂ98ö8Í’ñ6ÚŠƒ#ý–ìÝðHí@]xJ2;Ç‚f•‰Uk'p„ †=eGضß_›Ý¥eàEìH©±àœÕ­esÉð2è Ú5[CÕÚF$®±gÌÙ ¿«õdÚŽÌ{z|ú&†eÇUá¦$®ÔíxözÄõÒdÕJH/FâÝN¨ÒUaUb`ŒÍw;¥Æ$£¡<Å;¹# ôjÙ,âv¾H4>5Àea;À“ÝŽOÒøºuTËß2RæÀGÐϪƒOãYjœCb½~×%¾W<)^‘¿ ãÛ–F;,”û…iŠoˆìŽxw4]#£)­o‡ªžÔÜI÷¯&›ÑSªêÉŽLt¬Ë‘Þh'&#á^³U0”>3$ÌDZ®nèH,«6H“áÉóì-G†J/†ºÙÆì8±)S"ã‘â51]x¥v€Ù¶CeL‹Å—é•è=8sš`€¾AU_«µ·ÿÿýssЛa#²ÂWBbŠzñù)òp—ÈæÒ0v㬷ýé•ÚPJcI¥ªm¿ê64¨ŸUnºVudÅ¡¹€`Õ‘Ò^8ZÀïLZµõhúÑ÷ÁD J]Mì(+ái¶ ¾PÍÜ‘,q£Í˜+0‚ÆÚ1”µ8rpôÚýï}6îtÞ’ê^²[kDºHß"âÅûJuµCk[ C¤ÇoL]@ûÔ²<àÝ.ÈRï9hyØ5-hIVo8· f²*†Uo…l™HGù^nO@l½Z:¶OËtS9Òæ¦džg%Y/g¥¾ím«„o1Ù±¡ïhËwd>Z^Y&톯Ioh]x#’Í¡ýß^‹uiVZ•¹¸£N¢ªHí=à•œ/C¼#,çÔØ­u‰J(ÑÔàϘûÕj ->qÙÅÓ8úè]Y£M4ã_7ÇleòªÚa¤Þd•Z³Aº=/¦’TÅD¶Üæ5Êd¬ðæÂ† Œ/0¾ÓÎÜH&H]ŽJÖHkÉ­œ¹Ü¶MIÉ¤ð€™¤Aåøº0Ʊ­k†€ha%‚ij·g›·ž#Ì–&."úÉõÃR#Aæ@r¤ÜDôa@»äçÕÚƒZ nƒfðBR˰U„câ&)9‰ázÛ ¦¥ëˆ4º`s 8 Ô";’%ÈS¯ßþRJöN‡Û“axºÆÄ£¶Ò(¥WÝecZ#RUà;êꈷ®ÑhÕ·kíu) âÆ‹K~ Ò±’»'8Ò牌K_¦oÉRO=ó]¿‡"hÙ‹õY4(Ÿ}Rô3!P•7´sÁ¤•üù÷Aô·ä>ÁüŠ­Ç_»Ò÷M¯)­AÓT =¦qéy¶AU%ùZ0@Ëœ1ýàøïM½R¼#ØžF„•4ö†¬Ä i+b¥¶ªc«ÀHf¶ã)óшVj]˜ÄË=>OãØP2À”˜åwboŽÑ»AýÄÍÊ¢hǽa¶ /ŒSÕ ˆfõ1Q&ðªÜ¼@b%-œŒ@ .´ÔoO%|À9s‚¬dÐ-~þâ’•,TEV@å[ù|—Ú-®‘Ìt›ïP‚æâ)aš3ìù{[ïƒé¦Zü4ÁV¬q-Ó†² Vb tŒ¡µ›øþ`f%_ƒOÒÕ“âázÙVæP—# ÚQÆ8Ê}ôLbZIIL\/AÛd3IF‡-l+<±@Â"}írn²j†uÉ ¥ÖÆlóÄŽÛǼøJ úÄ+‘½CµÐ´\I/LY©¶H¥Vm%¸Aª™p¨0Ö%Z™l+&JH½~Q7(ñé¹KVíÇ¡*ådªWxRkódñÄñr;à Ò“õ,2R6 éÔû=Ì)ZR©‰l‘97_L¨*;Ö®K{¼_MçÏ!Ï] Ö€g:ìÉ”Rµ4@8“VáSIKÿ$ª%sy877·™öB# ÏÉòÇÀ<á.öd½ˆLPû|€EUG³b›Ð 7(’, ¯½ÞÄf¸gQ'^¸)±¨Qó„ |id-½²~CÑô&{™¾4õj¤¼ÓN¯Rx—ʶLièYèþÉ ãÙjé­^ÀŸLÓð·p÷J¦Ú,VSèEjÉÊoðþKPȲZ0Üú`ÎP )7+A¤^ËèÕ%Ü‹LU  á^† èjïhG|â>ˆ2&~>Ü`Î^Ðów¤/·6 ˆx]×>/pÍ>=œO.MVCUÓÑ® à·özŽðz}T²Ú†ªùÈ[γ­hDL2|‘Ò¥€d²ÒŽpWŽÏ'}2ÊÅzÇ L Å‚[ãÛé²>ŽôµbwÙ3z1$}&ù0ñ€ôø e]׿$̆ȶÇO©Ä¤gƒDV4-¯ª«Æ2[U;²–l·¦­+ç|0ˆÔզƋY T2hãêmzÇv³ùF7«q àÞ¹È4;§ÏMF:š"[ xoZËz `ûÇP½=>+¹TJœFVÂ- í2O%ᨤw¯„$ȰYJøL5G&-OÖcû9%¦ÁˆíÂõ=8žÆ%â$&Žl;õF½gþŽ‘ ¾1a®öø42¾¿LvµŸ_üf›7‚ Å\Ùo°UdÝBîµÉ²ëu)&Èž¥Å|ud%Yd%³¥Ô˜óJ@?‡ï’§óûœa]dÍrl$Ûª²hd-ÜðV‚ ]Ù‘8Óu, x?ŸÝ´)ez¯ÝP‹éEòq4H‚ž,\ɑҬ"O‚¹i¹=µ 7N)®€¶•+¨êªtö¾ßVÝ‘Užñ³ÊgÓ´‰ é²?ªŽl ’5ÚCßý@9æICÀJn™ Ûœ&Ã3õš,+1)dÂQ^×åΫ YIÀEY#‡oñó³à˜L®”7âöÇœ÷¿„CÖ˨¦ì^pú.ë}Ã>,˜@4޲qËJë4Ù{-†ÙJ02C …A4ý ÔŸUŽ”²È97ÙníUåî ¤qô}sì·1’Þ’•0c%q/ñùR5·Éç3e˸밪ØÕÞg¤tóχ>óªŽÛ&¯,œ q|†ƒp/™L$³-2qžñºnáh=ÇZ´‡ FRž÷‘v}‚^2ïŸ ©±ŒÉ2ÙÎJ>;Õx‚4÷™?Û¶Þõ8Q#Ë6âzÉãgØtµª «òOÉsë5OÃ`Jôµ¨"[»ÿtOÀVt‘°L,_³ã?Yf)!ù¸Ʊëy&Hƒ±61RvHÓ‘?f¤£ÞÍ0LV{¹v#h쓉RVdûŽ£‰³D¥Þ8 ÀªÇy6.A¼F-gü3w˜‰)28ã¿¿aAÏG˜y+ɾMé)à"%ßY•9RppžM7·ãU}þêBìØ&9“µ§#¬W#>M›E K°ÿ4{] lP|¤.Á Èd}·]aŒ5h$ú‰yy¸Y”"#ÂŽíI#`¹Ñ=ڻɕüþÂpV퇔›êðF¬M¼ˆï¨”ØPze~¸ MüõïÿÛ–£’â-é®äª”x¾xƒ„‘¢ûã÷-¡Ï0sÇS*á‘Y¹?†¡Yµ ùæa&>0Œcñ­4ÛJÈøiË sÀ;¦ÜñVÎ#ÌÁˆ®0*R.ð@z¹è”\v x]ÀÞ^{¯)0útð¦iU²°¼}séåxLnÚÅÈŽLj1È“yÊ4åÖH&ç¨öyéõ“Œ/rC š¦pVí¯P1vc"êJ©”R¯»DÊ4+Á­ªˆd™ØílpߪwN#È ‚ )‘§øÓ¨Ò)† s®šXLöª«ße­AßÛª«5ö’umtS&ØD<’H¼ *‰V¢‡ek#;´yíÖ5wßdŽ@&göWS‰Ÿ9Þ•}gjÄo>Äñûn׫‘[ËÛDZwÀJ6¬ kÄwì Ì®Lœ AkgÒq56”Æ¿þøãj+#ë/Çë4FÉQ¿PM d]¦ÁÐô=@ÂÚ#UaŒKÂ4ps$>k}0”ÂJ¢«®¸ˆOSƈU¶-W¾õvȬ§K©Oã¸Fxz$Ù& {ó–róE¤Ñ€v@:Ê}¬D,em²AÄ0±€?‡fµÀô}?=uw—gÕ•’ù1Sbkjž­—øÝ“†2?]€ºZ,ÏLzyŒÅT)…½#`n£a äPo¼RUe>Ä4ÄažÇëFkË‚>†OA¥ éë*7ˆ—15Ò×;²FL-•æ ˜’L0´-¾’ª€µ+5@æ %\õö}þsóºTõ&–á^#e˜‰£O Á_‹L sKÓQ;Räùsf¨$_ío=·‹Æ^Þ8圞l_{ÀÑVdr¿[¶dsµˆ°o2eGæHííì¨Ú¥¼gX•F´<жUY‰Zx*U%ãP ¥¦P¯k21°õºWí¯s›¬kû¬×­á÷î|0ZêUÊom¿1ð¨KÓö¯])[ë•ÛGv”s«¾`šZÞö°¹5‚ÆŸC½­ŠtÜÂMĬWisñ‹§ï9̇¡0¨пªp,ªR2—{ 8O@P÷NAb¸ù¯™xpG&ùèj®ÆÈº` œLoærï_©–ª07Ù ”Û-F6”҈𾥔ۄ@¯ IÜèÜ0€Ñô@bÊÈ1Úû }"™hÔ¢„ÏÊJ°ðÓ'è'ÉYfÛ8@´X™‰PÝû„‘-é(üfh^c$°ÈDK2%£ªaG¸YõâëuØža]ýjÂäÔÈ ®W)rícÒðh ¥ªÄ=Îy£ï+­ª‘~ÇZ0”°ªèoH˜›/mb†nîÚÉTÖ[Õ•™k gÒ70`üµ?Ñ÷ßÎÇ|ð”}¦ÝNWâ¦ä£%M€çz uŽ”ÉÊ”Z)AÇÖëË©E`j “ íÆáŬ¤—‰åyaš˜z…[Ï-ñ49´•ŒÏ¿¬š`únúëÿøÇ¾…¬÷ñ¤Ölª,ê´–’#>ÜSFzqå¿ÿ‘«ÞÈÖÒKæ’2Æÿ¶™Ñ‚Uã¸íªHAÖ×®m‰Û![9YÓ·|ãä@-»‘#¥ÈŽe2³öI˜ˆ/ÒÔcz>2Ü]”æÌ$+¶\*¬ºO½ÆzYQÚ ×k ²AUêd²hájwÔˆw4E¯m‘y¦oÒ‘À&KÙnJ UÁ¡MÈ´%ØÜ4H`¹e½̾j²Žx/ û Ȉ«¦tÁ¦Èñôž]¶ P²’ê«l"²ÏHI8¶Õĵ#“9*Ùçø~‚0‘ƒ¹·rp ÃÌc–•„Þ^¬×ø¦Œ,&è­ð½ƒ­¼@&|ðmÂ!ÌÄn)½$Ì9ýÞ&óÄ4€*R ,ƒ4« e ´*Û0}?GÀ.À‰²¹}v•U†¬»8&3Zt,´×›e,_WGšøù àaÁÁÿ$ {Ázý«¸9ʬúe¨«dµk‹F§á@†œ)ûŒTn'÷¯`ðôJ>\ã±¹”p ,J£«‰‰‘ކv0—¶'²^Ç‚R¼ ©nÀXoþ-IVÜ5?¿ÇˆSª€ŒWÙ:jWrlI Ãd²ãÈJÖë:Uå×¼=Í"æßš½@¼£HÆŸC)Öˆtœ nÛL4*érÌÓÄvÎg;äL hñ†daäÛˆŒÏØw#ÏJ‰ñ¦{JŽ€@ÊŽµkj\{—w ß@¿os“ùçÓ—§+÷cÒË45î)úNêª1¾¹ü‘ÈVÕ[{G†4GAÖ¥Ò+5)&£ÌdVc´´d¶¬`_nçÛzĦÌ<¾.åXËk‹|ýg¸‘G0ˆ@ œU£åþÉÈøõÁ †6ììÌsÆ´˜ªhãÒ·g )WûùõÇD·ƒ*OÇ bBÀ_Vò8ýo¡ÁÆÅ¯«oBG˜ YÿŽX0QÝ¢¹í ©Ž„_ 1ÆðïnaU@‰’I>ŽEΑ0 ~CêÉ:¶¶lb ¦yܱe\?1°‡Â´›÷Iï(Œ3… Y‰R¤)w¤]-¯Çç% `ÚÙ1}7}ï{ŽU>ZX!sÀ¨ŠMÇÓ¿ÌÄ”Gܱmñ uY la2˜ƒoZÿú&À—…£`¢…ÒwlžÀ±÷zÏî"[ F†”Ž€( úh`<Í­Ÿ?S­äØòª•šxúþF˜ô—E½ùV|q¬Ö•rþ6o>Ÿé1œ§ª‹LÓ-0zO¥œÌ%Û;¨b˜gÒ\xù¦àE›wS(a>B5+ Á R¶ž»dUË;+¼€+ÉZ‡gîÓñ¼˜Ž>þ^†òtÞ=Û/0ÛÐQ£ªe4Bc·gþô¼eð¦ÀÉÎ¤ï›ØGuWÛn@ålkq|Mœ‰ %$`\½Fô;ÉJß½à7ð™{ш½Ý£…'ÞÐv[& iq¤‘»¦#·ý{^&1ìmõ˜ƒ’È!Й’€r óìÙô2 ðnu]?¿$ÍÍY{üºaŸÌJÐËŽ[/™cUIW-U¹éšg¤<¦«aæµá 1EÕuµùµ æéÛ¹‹Ä( ¼lŠ’h"ÖîÐcûl:0óÞß狌W*8˜²— ¸aFÖÂĈVÒ[¨¥¿/µ¦  ™”×’˜>[ÌZ8˜¨KÀ"Ÿº`™8¬úéÓ–…j0±ÐnÖ¾êé9´€L£«õnÇù¤Äõû\y«Wò‘UŠ1]£|þ—€5´%ʤ) Ë‘NÄcv7Lã«Âi"ÝA´M>és Ñ%ÍÐ\ßãr>mBÓЬ’5—!^Æ·’ÆJ2²¯…’,ý["6‹?2M-?²Þ4ø–)k6ÑbŸñ÷82×¢–}›{.$ w—²¦x¶°ŒÁ@(åœ/(= Œªbƒð wd(hDƒ€Hz2¤cƒím „w2]0Æ`âˬ0»µãÖÞ‡®”§F%Ú[é\òûum=ÕÚ È íxÌlñdÂÆlç†q¬K ŒyAJL À7‚ „‰bU%ßùÜ•´•´ÈÚñ=/0ü‘aVgêóG#œ¦Ø Œ£HÙ?ÒÑ %sSâ|ZÆQPþÐwL¯*îÏÓÅ/i²r,Fº¯’§ØÇ4ÖÀSŽÁ÷>éa¨jß"_IN¬päfÏÜ´ˆî^¯£CQ‹ìçÈ£i¯ÑÑ’ºhkažL5“1¦—G7‚ƒªoi;l.¾‰øºÊÄ7ƒº`WpZ Í“L¤§Q[ /´L×{û΃Wí™1]Ó±jí¬þ4âz0NèªeÇ0½'ÜV²j-ªŽ¹!Sb<’ùÜb-ãâÝR(åÀ¤‹á7¢¡ƒÓ;Âa½0z½ù4ÂD@¤Ì\{$OOêcDß^À>”za‚îÕ Žâ1Ùø~ËùrãVô Ì‘m¯·Çq7Øv¬ fµ5º—lçöáï(w‹ÚnÄ £4†ƒRk÷Ï'°@Òh¦‡åJr&ªðU}¾¢9›"”Û„îˆåü;Ú§ËN9Y]ͪ*7©*; ‰¥lñ9MïV•[YÍÙ¸x{On3¡ù—5 ¸ÐXhÁÀªë Ÿ†ûç»o©YZƇKïôÕ%¸ò“”ä–¡çï#ðï}Ù†¸¡ù`ˆ×P¢I<··Ž©ÅÀ‚ªe˜È‚F “@½•ðdºrh%G¼%]@>ŽùÄÈdý¹C`þ·­;X’¬F–0¼¨ðš˜ Ͻù¤?ÓëL1±Ð y¸{„tNfU÷·/s8+Z‰µ„\XI¢c½¬ŽC²Ó}i—5¾j¡¶ Ìsxcif­M¾H¶òúíf[w#¶"_Im$ä„ðç?éØÍÒrÎ?UäMÙ$ÀîÅV©ÕÙrˆ“P4yó<­0UÇG{æøÅÀkvø>„áZdNómpN-lDÛV „UnŽÖÖ=¬Ý Á÷ÏGádÎM’¼$ÛÓÊ$°×¨F$.­ÖrM­J=ýF¥J“d:L*Ñ ³%9Oô~q«"{©"³’³RUbHÕœ}6àäýW·ââ Br’æD“ÀÑŸËz}›ÐJÂAh ‚IÞ`r¥^{ œ•D#AJ"Jj'癡ŸÊ*‰íU¼Îzå3mIMm#LÈY¨úΪ„c6¸ÆVe.$\U¥’•ŽÝû µŽl«"+i¡T5f+° ­Í¿ÃÚ~ño‹@NØÖº¤gú{“ÿî5d}’tö~¹q|ˆRU‰ïœ®ˆJ4[UžÍìoÙ%ö>äf½¿»H¬|z åTZp¦‚—çßxÙÒÊÏw|3˳Mb+ÀFj~[óÀ5‚'ì©AàܸíoƮݜͯ„Ù‰lçƒ#×BUÔ«C‘´•¸jLÂ&”ØÂy†f–<[«Î™y’`h ½ø´•¬ Oëo÷U%;‚­°¥ar®‘ØÖø›œ9Ð L’¿<ç΂³CÁͦ P¢‹ßžZ¤²MÕå„‡È —óäæìTB §vª|¥šÚòÇQ’ˆ€”s«$yÒ.÷%Œ°I” õÕE¢£È3¼Ù4JåÔN‡s›Ÿ 94þÀò´º8£©!ÏRüäåÜ f3XBg±Nˆ/"X©¤^…¼jù½òϧ‰éD‚Ӝޫä˜$Ü´‹&éLˆªUÞ ¶1+Ùò”[{WëÿᇀüMØÍ V‚J„ @¯ÕV‰Vb˜Ð<Æ*•èn[>!²B:ŽFFЦ;$>‚¤*‚È“-ЊŸ‰¼:áÑäq¢åÖ¹*¾îr¥fØqZEGè®0!VB>!‡äµð"¤M®‚)äÂUU?qB2ÏßZä©‘ŽâªÏ;P‚£»‘àÌg9¦cjz4ï_/àÆkNü®?-\´2DŽ©‘§G¨Ê¼mÕ’?'g›3·ÎHˆÀÄšB +ˆ•JÈBRnÅAΧ±RI*ÙVÚYžD Y"’×xó;ì´­/-²\Rk Ÿ!rˆ€Z‹¦’³-0%p \PA¬ò8ªÇëF„rcð!ø5Ê¡ÜÚ¶*æ8‚gÿ½Hµcæ‰0¾1r¨$‡ “ï6U;Ž.mq$¢Ç¯¸I´&L‚¹‘k¤*YD®/«^ ØT¶·íYø”KÊ )€¦ñL#4%&¢$rCªâ@"<ùù •è’$9~Î$òÚAЬ$Êã[‹3îû‹’\¼I$ &ËYÙvWç?jCÖ§1R[Œu­Sm€ÏVd ¤… g •@$µèI°VjŸv„]7~í@Î\µ¾„üüåB¾›:3=ž¢\•¶¨9¤Kk~¶B¾->B]€—~ƾ”óEâÒDf´$¦BVµÒ®TÓœ­Îs†nOè®$mùȹ%׈vΕ;Bˆ Þ`ñÅÿ7YUÒ0¬*e~F¼G€s@C– ?n=”ªrs’Äá Gvj NÕ´8ÊÁ•¹5 ²’,š‡ ¢ÔvU¸r+ƒÐ=+É+AÉÖx•z4rã™GØ"äÜu„t3CÐ’‡·Í*œ˜B)&p£¢i$”F€ ÌdW`‹i½fçC!¹ê×›#‡D#or?ÎkQÍ–[‘DžVž0süª˜ió±…ã»·8ѨÄò$h"¾uYIǘ®E”ç,WõŽEvár`k†|ÜgÃCúÛüFåm½˜I2lBnøøÈõ…çïÚ ![€lfÈ ^÷$Jä$ð„$!óÇ¡ÍDuÏM ¡ ÇÉ BkÛØø˜ÚÉq [L $79œƒµˆÜä·úó‡$[UÂ=#8Uº«Ú¢iGR ÍVŒ‰†o›C¶9 I"‡ð‡íóè÷ËÉ{ÊÚÀ‘•^bOˆSßÖ >O¹ß¨ÞÅׇEUo¤¬ j<þ›_>‡’’&‰\ŽÓ9\4UU¹¦Jä9@_.Á@Ÿ2¡Qß-À¦­jÎ*“JZ¸:`nr&J­L #oBÕh!M•Cþò‚ƒˆ°\)°‡eÛ©Í#á,OUªùËq  Ô…@äÀ’%À$Çý¾ç™—TmŸ69B¹MuxÈJ] $ÚJ^$Z­i%B©¸¸ü]|}ÜàZ>=‚½!@¥ ­‘ÌP.Á鮯¬EM# ãdßq´“K„¤ùwˆˆy–XÉ=8Z‰v_I/à$•Lr[‡ Qe+iKÈØÀùL¹1:ˆ<·†ß„áfã,ßÊJ É0«êˆï³GƱµiáyŸbò„ªOm[$ùøõ×_ÝNÄ´Y1ÌQ$ÛÆ•¸•£€cJám Mȶ± „`+Až¤ù ¬8ª_ÐLÊÙöPUEªÃY÷†´Å—#¨öfH lÓ6¿¼IHsH`Ç'©Ž òVL&ûüä !(YiÙ"Œvm^ sU4Ñ`Tn+G±ms±e;„ÄV;Iž®á‘%ábqnò†\¯á%é2‡4¤µDIà[qÜ$\SLÛ[< "$ëb‹#ŒçA[1­|˜HTÓV­Q&Ö"ùªC¨¥ªJän¦¾. íé`› œNOJé8Ï7xú½‚ —U/¹¤+bަT4RꬑjcDØð´9cn0UüLmÏ4÷g0¾ñ a¿š1×¢$Zæ´ÚJpZ±IT‹gði•!„P.˜Û)g%QÊ¿Iœ®™UÓö!ït¯ îÍ“GÛßl1뻎hž‹µÛ“˜Ùä<­M(/È» V"¨ oÛÁ’&©ªE½€}ÝAœ¢ƒ™C; •\H Ðrˆ°Õ±Zmáªá¶å­™Üa_§þ¿äÎ’Uæ£1Tu|ˆ9­Fjø8MÕxÖø@äfhN¹Ø'pæUy2[!¶Vb-¨êÕý¬×´hò&ÌAÇhþ´ Ñýþ ýú jA…ãI5›-Û”ôåÓü…RI½6X†ÈMRÒË€Œ ‹?ó“¬EÎ*Iy&„B%9[a6Õøˆ*7!‡cZåªD•0B|US©BÚj‡Ó<$õU’#·šPåõÒ­€—ÄAH[¢„!±jšíµ|}{‡`6>­§v’¬€ˆ¤ëŠ lKø%UE¸­˜óššPŽöeTdÂ@UOêßV@ó|ék{[^æL€’™4³mo~Õå<.ßÌV‚3ìùò§Í|x³yWÑ{K¿Œ×¨u,·:©h›\.a"1F„V†È¡GbBÕ„ª(B&”ÔbíjÔºƒ“;©mIæUsÆ—øþïBlõâ)±*IŒMRØJ¬޼žg ªBšˆ¦ªéÇï¿ÿQh™{™±¬‚c ò‚w s—wl[a‹ÃÓÓ%¯}In U›>2$­D ™ÍWgœ¬Ü&r´Ö‚o…8!>¡°õ>ñIb+T»>¶½ 8Ž 9—·MhÅÑÅ%$Â=h‘yVwœsÏÚEÎJëÁCÚ2i+i€|ê‚\¯•FÖÇš!7ˆÀ’ä9@jQßÀK?üÆPJ•gVZlT‰mpœ½1 §p3ŽÌÁcí—‡`êH i~º\›ó6ÇAÀ,Ê3±F°24•„[å ÁZ»¬äñS…ì;—S 5ö˜hÀži[qæ¸/žucë.Ò"Ãm³jaEKhUÒ"rÛl­È[I´6pó(Aæ¶mÎÜ¢Ö’:"¨cóñ(õ’ŸÞSËCº¥ç”ÜÄÓ<ÏÖ'Í 1÷ðjVÉVn­Uý J¹-Ð6¹?$²‚Ö¦’ÌíÔÞ_z‰œc6Fæ̪ð’uWBè~úå ÒE}M%'´¡Õ޹¦9ËUÀ#rÇÉS Òº$Θ|ª&‘ Ž„`Þ g²;I«<ÉV *·¹DU¸d}+–+yj¬Í¡W«\¯Úå¹<“¶Ž@’!ÜA¬øªláå¸(¡ÒÂM„Kà‚äPo•9æ°ceYUî,+¶©hm3éÚå±IÌœP؆Öxn;%LI*+ÏúâûKL%É3fZàâHäþtˆÖÉ­ÈBIHÂM%h;2œ›Õðƒ–óø­1m UÛò¼¬ó•ÄîÞ¡»­£UàÃÊI$¶á‡ñÞfÔŽÐ6­•Ö¨ª—0ܺiÇÏÇJHÒLJgcC&¼sµÚ.c¡‘k¤ŠG ²2*Ÿ¶%„5jxV$qò”âDsöªk-Q2Ü0!Ym•+ùM ?œJ#g‘À½!ž ¾-f'êW8|ÁG,iªm% ³‘z4¶TVþBB˜vkI}µfiZëð !AäÖÖÚÖ*g߉zúbW2ÆÓÊxµp'•hE>Vò>AkZGÂhJI åÖhzí8áÀs›þùg£TàÕ”Ï jƒ­ä¶¹‡×‰¶¼É¬k)±MîT éxYÅ쥙ƒF ©y´Ì<{ŸrÈÓ)$8ó·/¬Z—Ï¿;9ôøµf 2%ò’<)„Zœ™ÛšÄªc§°Úf˜¿ÕÀY¡­ÊVx:%r(áÙ$mUrV‚§.ø]E3À1#wö&¹­Î“´E³ÕH‰_¡F˜üÑ’KP Ñ:©ÜçÜÑ”jÚ`Fí“ÓU9dŽÏD÷¨Ekþµ('g ¹­UŽÀ\2gˆUÉêDyÉVÊ»ÒüñãäÓ——W×q²…"×zí¶UòhòJV‘XIk§â_—íȧQU{¬@ªFUÐÞ¶Ó¡¼µŽÀ|<æÑB¨Úê"±’×QrY/$óçqN×ûzX9ˆ üÏ‹·yTåÀ)©Wæ^ªä¹u©:­D•Ê$þ,J.i¶„g‹^xTÅlå–§+jªœÙ’TBk y O!r¡jeÒ­Â+Y9 ‰· '·;ú;üѼù½ÐÒbm­Þ.>ý?jô'%­ñÉ ­„QS8m%B%YálªÎU£š¢ñif4 ƒxskÖž¿uª> k-nÿ3°*‡šBœ(¼9åÕºÈ!EGHkBãÁŸ_A ßÍ'ïràÑ´v|ž¦òmrzI †fL*Ãs°ÂU•º“­$ï&3ÙHðnŒV£æÑTl ¦ґ•¼-¾¾‚§OM7ÌA²^år‰’ÕLB†C8Øvi8Z„HÌYG8ŽŽkr’Ür¶"7XüÕÔjË_I^;nT9mU™Ë‹< ÛJÊëÛ´u´òQm0|[I]$ÜÜšO¶V*¸§PN"Á¹ŠC~Jê2‡’8óg(€l³’³-ÂJð"<-¾p'Jœǃfh›ÐŠ0­®*ÙHmÉvU ÜZÒ -‚U HOÍ­IàgÄû.á{g|:0áÙV.$…œCæú²µ¤—9Ï«;Ï‘¹\RäÀp“ÛÊZåÈáÈ"„C`î\æqŒÔ·ŽHÛ ÈýJɶWA_¸¦8pˆU‘çܹY s`¢é~I@;ÿ°i"I2%0_·O¹èðkc+ªš !´'_¹9œ¤Þemh¥ÞäU%&LE(ÆË"4e…“‰Ü*”€8øk'iT++UÌÖI\B÷Gc¨¯*‘¿„¿ÈÄð4üBNÞlJrÁD•ªÄ*à<­È9Ü3;š;·83Oh‹ Tb5aSqóÔi³RéT¢Ê–ªŽ·ÛkHàsò¶´|¬Íœ¼-Z ¼5rSmf¥½÷JÝ•UN¨/±@)|M›8“Pª$aë<·%wWhTY%1Œ9] Iio‚_/¢Á3Á‰a]ð9äCÒT&¤‚ë"Úâ HÕü‘%måfΨs ĺñäá—Qs³ä¾0ƒ’$ÄÚ[Ä!çLÚ†œ“¼'"8‚?7+NÎÛÖº¦rZa‹&I+¿6ç+«ã`šS¢ÔJ~Š4!‰7ÍÁ%Àn O®ÖVU0÷p9HBä¢ñ"ãCÊqÌf‹/n¦ •ûÙæ¿¿nõÔjd˜Jä{ý‚ˆ\£õåÓ©âdNuZÞ€7Zªkv´=Ut`«ä5èý?¶ÓrÃg˜$2|4H}u ´ ¡ZÞ¡êO¢úïj” ¹ÞyÂ3R‚°@³µð˜ˆ£¼c$©÷¿ªr»+9¹G@+A†D[—ðÝ­<ó$ä’$j«/+L¹·QŽÉÄ$½zôø¶H€*B9\Ì(7XVJ ÐÀ .š$&$[ˆd£Ê+¥µÍßÃ5Œ’#ó ©TÝ“I'"Ï¿™UáÂÖJhEJ­ø#»yøÇ_ýõýûwì®#ëØò¶À4%Çøý»u9\B%6+„¡PåcmPˆ’m³ÚzB¶p{ž÷cò øIÍ ‘àcÆ—#ÇW2°y$œ´˜þÆ¢©Õ¶ãËkÝ# ò~`ÈÉ='4 7«ZUù$GPÕTtÞúÂ% ÕLš>•¼ÖÀQµers¹D¬T÷¶pZ˜V8ÄÀû;°8Äpà„"¾ƒ«vjx[%‰ ’$Ù6<$gÛ^qL9ÜÁ!’˜Ì¯ÙËDŽœa’YÁë"a˜ B¥†±Uõô»ùçÝ*ÕÝʪۓ7ƒ¤¼Ö&i˜¾š7óÑÒ6 °mCZmI“ÈrH9!°Ù¦í8°vT½tÁ©idVùHHjÚ0ÅÇ„«øJÖ.GUÞ*!A“ˆ§§-NHMÉ›Ä6äŠÎ£‘(ድƱÍçV^KÚ®‚jV¶A†Ý@bˆð¶S |¿E)wirZ!yÎdWGG|«­*I“ÛRe"1XÏ:¹15j’© Üm`4[U[!áY#ˆ-“Ý„Ü Ý†5>§`+aheÕßÔJ’p@À'”¶ÃµËÍJ%øDhK(ðóÇïÏMuA‹IâW®]ó×"~¥ÎÎHÕÅv5Eh‹Ï-¾.1äþ™\ hÓO¢îΊIÑé¸-áçX<ÞÛL90·F3ƒFpn“N¹©š(T!®#«9w4«’@kBªL€øVÿ±ÚÈ•˜#À!®‘–3„nÛØøB^D3scr+:l}ÝB'ÕHÈ'¹$òæq\‘‚mM§²Õ¥ÙÊqÞÏashMkq$JO‘•ÕœµÎ¤ê•¾~8¦@@fÈ'B¶IVà7XG–pp9pœä’´Á›P.±5ç<'‡ä_ §êBÁ*/à‚CþJ¶J¶º Ú˜yæE‡fH#Yù(QÉñuO»'¨ºã¸4r4 ÕÖJNU#+¼‡$ù>MØ0æi’z•HD¶u§ÅÙªŠÖ´ÞØr ‚wrwnÛ` [B« ý–Åßêµf˜œÊG»I ˜ ”Ü[kg‰ B8ŽmLs"¨6Ò8 Ï¿Œ=—¼ú–1MOØ·d.|Eªù~)‘ˆ¦QÒÕÚmVjŽùÞÓ­¯Ÿñ­Ék1°¬ª„”¬]1g|¡ ·•(I4²]+BwÔÖ£eÈÍ àc"4pª¹÷[%¶’¤©¬—øùõ‘mÚVÚ=¤V•@Œjc`IŸ‰¨ŸVˆùý!§óêØK¬º ıeeÕ(¤ó*Õ1C„x#­ÚqL¥Ô%îÊ.Á1’Ü*:]%M=kHcØRi§*i$ ¤¦üki°Ì;E9· ¿ÿ°yª^ËÏ£Á›ªƒ×NÞÖŠ@••¤ÖÍÇHÂaq O2g¥&”Øæ€& T%ðŽÓ ?ÖoIxü¾/ Z|ù |h›G äce»v̓V‹:ªŠrOJUNŽ,±m%ÖEŽ)’Ô´|7ÖGSk ²m>r‰µÇähT`ü«;/¼HÛã~Îï“®YëÎXîÛ +úò[H¶TølÓJº^½”ø`¹µ\Þ œCÐLhU„[åΕùu=7ðì•«pU`¯¨¢qWÝ€-s¥p¥I"äi*¶šÚb ³‰Ý€-Ç6¦’§îr ç5†îœ!yÎNÂÊ@‘0VÍVοooóo4ÁßÊá>ß([æÞ_•õ‚˜ƒˆlÕ…9>‰£¯*¼­UG`[Z[’pnrä<ª²j6¸-s[„¶ùt¥Öt” w.’¡\§Øc­/§Í´V&ÜÒZå8%‘U*[aZ‘*!P­I²"1¿ø%ž-:‘;é·Ž¬j×J+Ak‹ 8ë;šds>'‘#sX’›#”äÀ\Äi¥ZIÞƒ#‘cÎb ˆ+%$©:«ÀzYmC\ r|B[yäh­µ(¯5Nl“X ˆËìQâÌ­ªƒåÙÖ·ŠL.F“+Ù’¬ lÔ@+¤gmE#Ù§LUØj<4IOpæî¿Ù¼}X”€T…ªxÎ`VÈUq¨J¬´V¸¾æ|+Îå ¸Ž}Ã(áàg’Ä„JÖšF;&¶¾=hÒÕIH¬Æè…»(4'MÈ ÇÊ¡Ö8"ÎyBj·Ö™#tÆf`eSrþ%`cýøãdLRÞÙ ˜àÔ"ç%Jv•‘!ujk‚*ÎåV¸3Ð]WÒBR…ó7\â¾0;L6’sˆÀvðª|€Èhº@Tm5Åðãr} Ú*I¬T&‚g[H3[ Óoá@ò ›Ê¢.i™ ©> r¸©:ikMki½à<½¬TZâ¢Èqøë(ïnÉå‚¶Ræ|€›D¯&#[ IÈõxýFØ´8À„ºo†iæé·—CUSLAnBkó#Y5@¥™‡ÊZ^‚ ZIÕ+§ ­9HB>.M¾¦8„9À×]"¢I¨.ðú(ê®Eÿ[“\pÈ-Ÿfã°-DnÓVN¸yŒ /”8“ä¯$úŽ»¥rXˆðÒ•Ú*3¿ù„uQÅQí&+]ÊY8x^ 4 ­ÕVR yný,'ÔWbkHIŸ¸ã{ˆ&WêŒÖòœó„Ô·I€5íåIÈD¢DØÄVÇz1ñÔp¨j‘›rˆ¼D @¼uHU²aüÓhë‚&E£ÒJ¨øÔ]õ9yƒrF&):Ôµ|M(Ï Ó„Ln«ó‰`²‘ÐÚöà0my"+5F¹m ŽÖø´êŠp”ôRMÞœÞV!’"CB¶$„fPêŒ[UÉk*ÇÇD“Ä·6¶äãçŸVPö“8^îž–-S§·Cv)µ<âw4™*ßrZÁÊVäÃAB.JX5¨_•˜píB=~ˆ’-š«±6^|d%Á³Ž»b[œºD»m_]§„œ›™ÛG÷´„ÂãÁáS#`r­{TJTðÜ$‚P©I€ø™C²ªõä@4 ÀYm‡f+âÜú!hJÈ\´­‘œÊoºÆ¨©X‘gb…(;oÕ:¢i#£eËs]Ðâ‹Ì!b|`Æ1$ÄóBȹ^ª9Çïz5Åìpäùh‘°Khòš"Ø"°:£¼ÿ²69Už~À°µrÈsÃà˜Ç.ÓY•§œUI¹-&¹“fB"€©Ð$N3äf¥3„|¶øÕË&Á Dè°„r´JSI u'‘Ü&ç=äV529BA"Ì©—ØÊùs(äB5“°J¬¨ä©B\/²máò>òü•¬(Žõã«-¤ÙÂ9óÑ+‰\"RÙö ˜^ÂA˜ŠDÂ_"$͆#WEs‰¾1Ë;,~ª¦í6¬þé &¶dI†$¹„³P|bB´8.$MX¾µ^Ú LA·¢¹×ry¯K;]Ñ$cʰvV‘“J  ™3h Q=“ÝÙ ¶^Õf‹Cß6Vª¬l•p /—ˆõíƒÙÖ™¤ÃfÛ‹á*z%¨ê¢š'mræº ¥â6< í­œoæ5r–m9àlNŸÓœæÌÜnuFü° x÷!sMmU‘UAB q®öªK\2 ¦I|-Kø ùê€C©sͶŽÈ!1³.È­| Z­œ–ê‚ ì´„ònM)[½l•ÃW•„lq|Ĭ¶ Ÿ3”ãtLIóD³jWGò(i$k‰I"wƶVc ç ÷.iq-ÿóñÇ80ïÞÞ9R_”@vKbj–Wâ |i› Þˆ–O-€æëñóTÕ·TBÆtYþå„N‚&ÁA0ºª\4pÎ=<[/´@îƒTG[†ªÁáZg Á/Ça qÆ:Z•º@íÒ6üähò|æ&Ù©ÍШ<1óÖ¢ùåz•çVˆîÜrPòl÷³MÒŸ¡áu¬ ¡k”“ÓÖ·ñFˆšÒJÐ 8„–­kn`ƒARù*6„!¼ëUª œÛV„’´ùC²• †ÜšJ.ð{¹Ûâð”÷ÚÈ{jýÎW;ó½l®K¡ÖTªÉuÑ= B ò&´5ÂË:×Ûá «2ÉRâÃ!¶|$Väø¶N‘sç²ÚâXI’·: ¼ñ9 ;š¯ ?íã§²•ÄÙÙ‘PU4 ¹G™³ªb,mä;òëWäÑ)êeHwb Uˆðž49œ‰œy}9ßVgÑ« <ÏÚÁUÉ )ÏÜ“°¶å©äÈÏèn‘Éû±E†›G®ª ²¶ªÈÀÆ“@”’(9 +æ8·Ö™³m+1ð±b[£õíÓGˆY#9¡^ÖÆP¢%qp sU‰•§È³ÁZ›3«.‡IÌäC4@†L$B’°€Pu±ÍlL4!ÑÞ$d h§1¶2Ÿª¦@Sá7 åp&Eùé§Ÿü Á@&¾$œë.Ça(T=¾ªTùV´$Jžu$œ¾plU¹KnSUIhTר«`Òé$Bf A&Œì¼J^l—ÇŠÖq4ê ™Dtj9ZCÞÊ™ß5ªvÆMVT&ç©DØVˆÕÃÈ? HÃH:…Uh¡h›ÐVS[ ™oý Š•²¨´œ¤mç%·ÅorMg[¯ª¡ROSY tcV%V’­ªTV¼\_Ïe¿«‘˜Ö:2‘ÏÊG_9‚ߊPÂó9FþøªpZªå¶ I<â>@«À„ª Œ‡OCÂKðåmK 9ˆ|BU¡‹Ï\ôˆM·p†r ²µ^m¹©âå„J9ãKضM"—8ÂæìZ2²bâS€&ð;/ж^‰räTúÖÂ6„0+¸„Ð+-0Ý9y4›êTäv>‹9xž&@ctc>eÀªõŠ£…$!ÉÜôbXŽ“•¨dÂ!¶¾s”Ìß›gâÚ ¹0 S/@æBáÈ Dki$[qd÷2o«³43«„‰àÜ}vdaøõx-ºØ”Xq —ë›ØóâÙ§_uMñ.§²„!˜B>ówp’T@«€tÆ[<7‰ÙµŒ³GŸ­ñ$ÀÆÆ·eeËĶ$CÛÛçµ`Š1UÑ y“ ù ¼cJ ^8$Yq IH+ {y\) šà©dÛ½Õ¢ä)û~ð`~Àì"—#(A²"3Ñ"²‚x-m»½Óò^ ¾a ÆÁHñw@&pœq˜PΪJY Uäºwj4ˆ¨$ј-&m“ćHòŒ© ÉÙßEúgòëÕkaÚp|ySÕ—•ÈÊ èî,]Q´æ!Tm*ùùw4 †žs¼}†(±È=Ú&¶ÅW…VLëd«ˆä¦ Dƒ.¾ãœ\ÒÊAµ+ml†äsH…¿^¦•›P°’T3q´ Ù Uá–äÉ×ôØ}|ø©ã5ðɇÓFc[µ©ù¯ßë™ÊI%VsJEHãÙšÐV»Æ3³P"‡°ƒ›Ä…4X÷ g½äN×ûhüVÁ§Á˜(õ“? *7 s!a«BÕº@0!œÑTá Y %«îýr Á‡pÎ-­-9“üm% œI]ÄV/+¤“jÍø%öÁQ¥­Q½4B¶2»V§Ç=s× Q²ª6XU3ÀåÍÀ™gþGçl$Z‰’¤¨Zk«-7rí¬!½u%»ê&Aæ#GˆoÍYIØ å3Ç·5I`Û¶: 2ÜHM;\¢TÓJZÛv!„T¶•Xq€;Dî«Å—9ÍÓéêÎÐ%toÝLTDR¯%;£„J‰ š·N•s–ùlU Ð 9û»vL¹<+Úp‰-Pî8™spl…î ÀŽi…Ö\ÐV’>iÑ„R>Çñ~N'7&òm™àÄG#¯‹¦½Þuǧí h†DË.©$Çìöp’`²åÓÏ£Ž©#ULwNÞ+Ñ·7²j-”Ä™ø¾-JuÁ¯/Ä)];¦ªè5CÐÈ+GÐÒSŽÉV4 +Ìl›y¸@Æ´rS’„ËxÃØªjÄGŽ@RäY+ Næ=y“p@H%pëêk '¼¬×Õ±õ¬RYql'L Þƒkl B˜ÍÖHnØlqÄo&y½Â%kƒ1É™§¤\IÒÈñ;>9œ?2d†ÍßJ FnTæ”{¬˜å4ƒ\t?µËÊ gHÒ¡žGóÖ5¡ªÈÊËÖœ¶„=ôN„Ì\~»½®Á™ó:JháÈëÛO N>8çÆïûä_ÂÐH}Ž˜ÌÜûŸªc2„ZïW&[¸*&7Î1­Jâv~=ú¦Å×ÊÚ ÈU1]Qnr‰‡bò†G«‹D•C&@L`B—&çcB´n‡X©¬œ#ü¼|ˆ±¶¡„âIEND®B`‚ic13Ða‰PNG  IHDRÓ?1 AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs%%IR$ð@IDATxlÝÛ¶m[Q¬a@DQÄ…÷$ä– @»¢<°¿ÚþÞcÖ5¦YÊN¢FFFfm½>æš,Ü_þ×ý×?ýéO_úÒ—¾üå/ÿÙŸýÙÿþïÿ:~å+_ •D¤#PDbÄÿ÷k‘>kGb-;&ˆ—E<Á¬±Ål›ŒLùÕ¯~ó?ÿó?²Þ‰»Á=ñ>â+Õ˜m]Ü”š…l…öJ?ÿó?ïHlC9^n7$PÉ#²Êß±®MIŸF5ÛdZf›S`ä@Õ˜Fâ'¦¥U‰á¦¨>ÝçiÃÿõ_ÿÕ2r|z`]i0‚lj]H¥í°ã|²2´Þ#åxdþYÉJ¬äaÇz1ÂÄîÈ–ì8üà?P¨3 k#Ñ@‹ÖY Yd“"åÝ!Ï–V,ÑqOßImÂ+ŽB¯¬ã(ý<į´^<Œ]°]KÆ áÚa?Q²#gYÔ¤?FÏz*ÍI 2l Ðó¹mo²¹ÚS #/2™ >»¾°®¶]»RëÉ‘€È¶ªc%&{••hº©jÌi~¾/ú|/ ‰iäÚ,òéxý˜¥¬$;–›Õu <³ÅhÙãJ€Ü2L#‹Ó¶2•®Í¤À£?î]ö‰âo‡ÄrzÙSö¼*µÊd÷Ù9À³ ³*(]~Ó}?Yl]‰ÓDêðºð¢Û!g¢ŠÇÈáÖ^ËJª­Ñožx e›l%&â6Ñ.b4ž…žèóU #¦.Y‹À¬±cz¼#ÙGýÄíÅTøÈÚ‘yâóÁJøJr&•ä@ž.âQLà!gBƒ„3 |£[&™RžôÄ—#ù;ªš0: ¸€µÐŸO‹¨Íìú´¼>þLI‘5`:‘ŽÞoŸÍÄÓ[Â0ÎÙÆc1Pä)k‘‘”#jíwßù ëA‹z»Q4€¡²è´ÆÃ‹ËHÜùÀAyûÀóe-=<Ù£K#{†Ú)‹&Â@'v¤,ÃiÚª®ôø4F×È$ã;ŽÉ“2 »H¸)ô@žø5jùãÿ(÷Vô(ÄHâÆ!¼ÄõûRJéñ»i²¦Ëø4·!Æ1¦a¤ ÏgP9Çšs!ʱžd¶tt+Ù©„T…§É§+µ}™g-;fèØ8ÙZ½(µgN ôx׋Jò‡.¢q)Ó?•O%½x$†ÿÜWÂw”{@#*•‰Ü8Êž3¥‡&’9а¯ 2nŽ¢F“¾[çœ2>Í2@³Ý‹‰€…‰0 üÐ÷Op+c íRŽ¢MŒYÉ6ÝÏÍJ=“Ƨ¯„ L™çª5ÚR©'ðÂD¡K®å!Ž$ð¹Än :Ç©áŽc“ã3>Ʊg¤Ý~X )×xj8òÀcͰ{>Å×ëÈŒ@{âùªµGnP¨Vò’aˬØÂªÓðB·¡Ue-M”ÃHÑ-²Ú Ø”ºš ›•ŒÏ<){ždx‚rGRFb"µ ÀªòžjKbXKƒÒ;™§l¥p;4}³"u äôøJõªô¨NŠ”ã•j”EŸõÚiŽôOý| "F^tG2‚ó‡fúôžÄ— >RgÃtù´º#Y9=MoUü®‘FŸÀ3~{ˆ›•Rnçz7:sEL(UÀœ¦{5înɳì²Aµ Xh7‚Ìíž²7U5fV@!«Ë&ùÙëõåJISc#00¢Ñ+uG ÀJÖNvzÞ#”0a¹jzÇÜÚ[’`Ëk™>²¾ÒÔ^‰’¬Kä¿)ñ)ïÌg-@7ªËãÅX/¼@öj²láÈ!|÷jÐWþð‡?(¼ÏßNÖŒ©¡æÛN©IÇòùxÌ ÈDvì¡è­]&˜&ò¬öDǪÂ*7ß1Þ-Y˜ h€fHi+Qo#d‘ÉZ0ð¬<)Çl$Óä¬WUŽiCLwÇ“‰d‘å1MAb„£mex$ŒŒ™(«&㵎6´Ì>šSmÖi{ÏêÑE/;¶I¶å·KV©Fæºz†µÇÓ¬V’‰}F{’í¦ øS¢ì b>YËvh´#™^GÀy~F?žÏÒ1²a3Ò`¹šiÚfÃTuÙø6¬…˜‰,v½j ˜¬x´çí Û¤5šÞДñòvÎD.È2§É6°j#ä"Ô˜œ»ÚZVÅÀeÊnãØ\G˜F~9ÿéCp+ÓT‚UÅ£=†ý’dë˜&°j]ÍBô^…µ^ < $(e sßÐfaD¯° µèÂÀ²§Çhþô?ôknÇde½í“3Ãð”ùŽwÄÈz-CV»Þפ¦ ‹|g×Ñ}|ÍóTëÂôS˜¾1Zƒ'[U ·l¢¶"È¿FX‹èHŸ8ÞQɺ*É·y2™€RÕnu1Ôˆ¬×±FYlbsã7¯ÑQ.RzDF›"L½d|TUë*#²–fŬ% %2®kx `¨ ¬E¬%G‘ÌhѪ< &ÈZ -p] îAÞ-øô·§Þ¬ò̇,pV|Þ½m¥ÇÃ@¶ÓwÄOiXqÜjî¶jmæ¸jŒèò. ÚJ€R³e¥LrPrìuìÛ¢‰ª‘€?Pù}°êÍ`KÖÜ@ãháJ@UVJ{« xbjI&Û'F¦.5Ã]2Á‰›˜+ŒÛeŽì90lÕ|â³Ê¤'ÉM`ôŸ3ªø6nhâ0AÆ€‡ÉêJ/·CdʧfSú $5XÔÙBkö…=/d<±‘OÓydñaÀ7©J†‘Š4·¯LC ãad&˜/òqT*OýÓŸší[õzÛãijL +É"܆€À´ ”Cß^Jò.Õñv£Çëq 9TÕŠdå¹ |‘R& ã›%´mL0}Lƒï» ÛÈ'=’C-ô}uÎ9qdžk×;“Z6ëö_o†L€²®$×wN&ŸwqÒØ^DX©þmOéÏŽ‚ *ÐÍËJxd Á…kãÅÈ4>E@î¡'H³Œä`FØX×#]5–•2|èOïžSU%0‰ì.‘rß­DÚÓ×%= «z-Xãð‡#žX—)õbš‚gUc²0åùGÉj= M• ÎN¿è3Í~èó¶¹I—ñÈTE³“9rë)Äg…¼J¬Ô~ª hDÌ]M¿Í7Ñ?±ô@[ Ý´7‚ ÏÒïŸÀ™71g홫x-áJÝ(=>C—Ši¼GAÓ [2™.³G‘aæ˜567CUÇ Í°Ñ° Û2âHUL½öõCŽÉó^^#±ØtXWn³ª×ш­¡7¥Œ¼§ÇgâÃuÜ@ãÆÕÛÐÈVª…gVÍê=‰œ ÝF“þð‡9) rÙ5ªÊ˜Œ€ûE×UI5±0~íJd‘Rî&eUz½zz8%CŽjÃ܈{dªÄÞ¡ûAÓz&”&ú€Í¥l(MǶ}<ÎæÀµ/ß2;ä@0«zÝÇVuž¦c¶eGì'$’ŒóVD]M¬š§×$˜ù6líår%Cíý|æÀ™  q9l½zå6Qª1óô0Ix<½´ô¬T9w”'CÂŽ× ,·FÇ9gr÷ªžN¡0 ÐßÑâˆÞ_Õ0†E2S'î]Ìdzú´7^¾I¼¡{ÿ€<ËëÚ•ŒhI°à&€Z$[É{ÓQo&«”˜üñŽ ¼F;–‘™Oå•ê­„ Ô~ŒñÏî¯o¸².¹õ²Û5#ðÌGx9R 8ölÓq g’Ì*âR:R’ ‚b³T+Gbz7}ÿ*ͦÐÓ8Æ8úÔ`ʇ{ñ«æ¯…À3z’øZb³dŒcþð)áÏ?yäË"©¶÷ÔijðÓFIÃOS{@#ðûßÿ¾¿Ñtù^¾º4Šu!ÉdnBInVz½HØŸû[òô?A‰ÍMö*<&0gh碣ªcƒ`ng‰ç‡¡Ï8A¶YÑ;¦Œ—óÔ¦tkxí€hPkI¯±#Y )Ï ¾?Ú“Á;æÐ>™g›æÞ$ >YþáJri2¡¹Ž¾Í^ÜkhÉó±o%¥x½Ù: OÏ›Ö8Ùr%þu-¯ñ.ÁZDû”9Äh©ëüA?öÙÿüsOdž¥“{ ­Õºû„¸/8ˆÆi$Ëœ°Ï¯Ñiâa ¡µä#gRéÞm†r^{;ë²p¸^y‰³j Ì¡PÒ(2ìvµ;’Õ+kÇËIJpŒ—s9+|%âB‰l-^®Ež,œ›B +Å”#,O€„SÊðýb´õŽ”ϰ÷£xèóßK›ÎCCÿh_(«zkÄœ§ðþÐçàÉà÷´›ž§jǧû$J™r‚Fà1‚ùü)U•ΖýøÖOÌÆ8z4®3\5™l€l‰@ÇäFÀ uUµI7Ÿ‰Þ}[hÉYho¾Ïÿ¸ž”XûH¶¯ È•Föø¬aüa²Y«ÖÞÂ1=€ÜPÇFáHXI/ýS<)Cþ™L`ÕĬ­TTÊ¡çF Sõ6\ P•ý'H#'¨jbGÁÓ1Ž‘w 8AÓ‹|º”õVMOÖs¸Í‘oDÈQµ)i`½ËÍ-GžûÏ™¨†{Ò½^¹×6­cÏÈJW&]!^©.d‹Éê’+µäVl Müä8êUÚОƒý[,7šd­4¬ZØ¿«=Â×—¨’c‚Å0q”Ûœ¦j¯E¤ên—ìfتz{˜ø]$ ¯w –Ï?Ù­¤‘sè±9ûh'`¨$ÂHÙCk(¦Qæ€Ñ§)µËh§Âéåöì c>L¯Ï![¸8ë.jN¡W­¹*Œo¡p;ÁµlLLʬzRd÷ýéMGÊn’y äŸ!A‘`ùç HÙµ7š@‰¦ŒQš3Ûp%Uí‚Æ«lÃe]JpY—0"gÀq 4ÓðGýŽHV¸U™·ölU‘™ëª±zJ"M`XïS|}”fÕŽ×ë(’àï ¾’œ3ü<Ÿú§dnú“õ¸Êí  #zsD$A&1X‰,ž¾Woí²ó§oÇΤ\v“:«Â5“Åp%’IÇ||U‰HkµYæx]rèèAÐÔN†,À™8Æ$¨1¼v†°Y2q|£ËUu9úÚvŒÑ8Ùœ9 E×ÑØ`‘IGz±àÊ|z>”˜œéË5†É´¤Áúà`šF`æ–¿ê6dáæº4â—ã1íÓQ·-ºð=¢ª¨÷¶¥\XžÀÏa2|é3Ì-¬ªÔ‡‚É'ññ…* ýõ?€p uNºa^‚«R¹IxæϱñJŽá9!Ròðr| ½€}×ÊE]SÔ‹'Ç:[¥ü1yæ37bTj=2-µ÷FÚAi–úThjlnKnI):Êl“±ê— ÃLÈ”tõôÇvƒãsM8ò1> ÆO ]PUäœ,M*OØÐZns‘µlVWèH“­œl]ÓÇL ˆ™4˜m̪Ž3lVG Å–ïÑEö`wÌs-ŽçU;ÿñ¼s¤¢‘²ð9eêÓb‘24£öŽr2 °×EÆóŸ¸…w EÿÂ)>>”¬0°Ì§ª®1k<÷yªs „‰c(¹ÝSyöÒãýÝ+MæëÂÓÜV™´€,òi“•ªÊÂ>§íŸ·÷Üš+t íý¬ÖU愇 r Ë6Avlt»¹`-•Ò„9ª”F+‰z×…¡‰ºÑãu‰ëòX?V^›­ªª« «>ò“s³áöÄèê¬ ›Þ|ýfÏñJê8/ïD¯E^ £äEfp¶x~ljŸX 9ÖÒô|Õëç#¦ì˜Ö%|ð¢éÌñr-ùË ‰$ã0Cà±H²H&°\ G¼–B ¾Æ<ß•Oˆ R¯«õ{²7“Cüåz[㩜R ”ïcŸ)RËÊ"ÏÄÂȪvëxËôRö´É¬­Š|™øPŠ=Öåzjk­Z"¹‹d6вu3QJ騽-{Žø42Ùž©£Rʪ™›UÐÎŽ‘-O†Ÿ¬éJ5”Ébd³ä‰Ûa;·UÓÛÊ ýY<žíVÝ€ê Y;Ä/#[u ¥­æ WŠ/cDš²c#wîI¦—‹ùô:ö$æ)«&ˆ!¨=O]ŽÉ€p˜ e¹’Œ§9„e2{ûcŒöHLß&üZ`¶µ4+ ,à¶:íH$;w[å˜tJ€ ìäØl.ÕÒ0UXŽz øcôþÁudRdAÐPØnŽJržpS<‹•Zæn¬…C#”r–•ÀG5· ªÊJțӧّ27Œ’iúŽÄ´@]ý“\KZj—»T¼,ª–ûäÈð²ÈJUðlJ]0AÓU§T] O÷§¤%²öGòZc˜C@ì:‹l%™2¼1[Lµ‹TН%¦·ÈÝ7…¾Ø¸Ž[Éqƒò™òõ]²ÎyÝ.ªø,º•c/¥?~à[«Ü¨/¹.œØ*gÞ~òžÿâ6“ˆZÔ±ÐÛñ{"ÜbäB ©Ë±^ ò¥xŽJ™´¤5îjÓ(a`Éa½ít¤ï˜ ‡€Ô¸R„x&JÂñ™ðú³VÕáæf.ÇÔ Z#óm¿ÀŽ”¢v`V‘’•*XTÚwSkËû—_àlk)kœ çãw Åd)#·ªã°^¸Ÿ‡^?Ǭ ÓÀ;jG–çÿjé?båýj†5°¨di1™’h°a¢'â^“ÙLïH¹^@(=/ÿ¬dþM$‡ô>uçܺlY¤œ2FY)-,ÀJÆÅYëýsŽï˜C&Uù3l(IŒ„×É6q²™hŸµw_ÇÚ-JŽöc#“-o·d5Ê0 ë½/Ÿyï7ÞMYÍV®*ÏÆdBÓe%ŒÒŽÖH_îžIVÍÒèØ2p†} yÎ)Ò ±È°‰x¸C¾þT!þ>¼D©?x9š! óò@¬·×àP#e¸=äÙâU16]µÈ12®xÇ»‹^µY9« ?‡Ç÷‰{Õ”²J˜ƒ…_Ò÷¿ÂA•!¾¼¹Ž.Hyö~Â'Úoâun1%ÛFĨ¦ÇMTêßJ a bdkÇ'ƈ)a|Ù·a8Ü·$ ^c?TŽ¢ëlÏr½ù9ÆÈzª€ÒÄLð¶Ì™Þ1ŽtÌm|sWÊ6ÜQþôæUã( δåXLѱR™‘’Æþtëè¡8î'[•2Y‰FÔ%ϳ_A)ñ+¥¯Eæ Ô'T¯c¶Á>ã“ɵËÜüÀ4¢ÕöaBà —rÍlÛ$1,Š^”ÆáõŠf1r‚øJÆ ¹<Ï‘µSÖU ž@Ö¾å“MбõÚáé>IKÎ.+bš{wmÐfÕ/t 2ŒY€#Y»=Ås¿R 5Èl‚ „Ì®‰)ð‹Fœ×HÄÚ¸¼Ï>ÁÛäh,-ãÉðZàî´\äªè!V]£c?94•ùIëjÛ­×Î|dG2ÓáÚÃxÛÖ{?V ™Üˆ5n.ç¬4¨–ö—MÏVuþiZVr ™žóçÊJôd ŠŒaB ó$kVÙÑ•‰i*}È-,ÓËL;ÂU÷u†\»ܱv8½FCÅS?ûTê:4m[ÙºrÓ^hìš›K©”ì&7‚@Ko²X‹êzÏÇé,7޳ꀪf^6îû’l-JazYDŽÇÔ4ƒ8º·’>>F®·¹›ô(' 赘ËÛ‹&Î6O<Ã}¯oÛ¶Ò¢T¤”ÛDôÇcšÛ,ëP"“Çå ‚ôxXÖ˜aw—E-ô4é)Ÿâù@ï¸I¸’^&pkl(f†dý”–IÖÐY)aÄ=4ŸZ(UeÑÎ97ýi}ÝŸLI¯ w¯¶]Wy•n¬¤7®H¶UÏÆj•ÕŒ ÍH¸Ïƒ»?ô·z“hˆE½›¡«Æ1ÉtÜÒTÕRµ}"åÇì$_H•b&8çIS´§ÜÎõâ9×…Ñ+“8´IÇœk[éÐ+˜¨Öµ»#õæ/*2 FbÇZQ—Mf;çªzáë%X¯ÆÂÐzÉê ¨âéåwqÄs–‰k÷m‚ ÷ÛèÏýñ·sr+©ºQ½1Jô02YÃö1w‚Zî®.B¦Ÿ^ž”ÊÄ1¯ʨ[…ºU2j!Ù½U°FÙ³d=dÏb-|¾0õy ZîGÖBÌ‘ù4h‡öIÀ\P6V]tÔËÎ$ãÈPÐËU?üûÄä|£§Ilz¿Rš¥”mSº«ž;Ò³Ú†Äu1© hJæÄíÖJ•(|,OY¯¬Ý/hRve8qΪ÷‘¿£,2Ÿ,ÿ™tl"eÕÑQ¯ªÀÚ&H£Ü¸ë7:qírÊ[Ÿ8A×ló5&6¥ žÁÏËP6Ågo·cÎå³.ߣþ¹‚ GÓQ£°lž7 ãªÓ+ñ©7CùOì…è¨Åå“þÐ"º6A ´¡ZZ£×nJ-{ò‘U•,­AŽ­!wlP™i‡lsƒ‘íÖ2» A±ýßÄëñ&“­¤4çø|dË´çÜp™y€R(ebCÊžg#fî$Ã0ïsáÓ=‡Jµ0¤Ç‹Ú‰aß#ELJù”•€¬”ª§«O3O™F%Y`˜ø¼Æ¬ x½…t¤·ÇzðéI…•ªêí p4É­bžúIÚóϰö˜2˜è3¦´·Ì_0§ïߥñ3¶oâ|r€luÅsÈÖ‘@éq}½.dípor·kéú”@ž›¸^2çz{¤ù;ji.<ÍÜ8Ö¨«‡–?Ò‘a2¿Y¹¤ª€ñcxŸ/2戞0´Ÿê-CÎy<9ÿœaK CClJÕâ•Òì8óÀ]…‘)ç ž=¸F2Øò¶Â$[¶žWEéÞÓ±û~á'LOÑêÙ5 O_‰RîY§1Æ ŒP|v<[B vL&±ª—),‹>¿6‘ko 8´pL ß8’¬Ú'Ëʱª ÝtÕÌ‘®) dæÕÑn‘rQ—¬TÆëÛðxž‰sÈs½€–¶ºIb»—.2 M¥ÄµW’•<Òn‘2r²¦G’µ’ªØ8UG¥‡> Ö(<ù®ö’dU^U+̺¤%óTj\€ƒ£§áâ1d)Óß]¯Y hÌ:‰ÇÈÆ›Ž¢£ñ@˪M­ëvƒUmiP³˜$`#ÓÄ÷MÿÈÏÿmˆFÓЛÕ'½®ª–¹­ˆ Ti¶@³æÐo‘õ&ƒ›B g•Ò±èH@);òT‚ V½v+©¶›,^Fï«^™¾%a@Ÿ­q{Q0Mo[½ùlÀÏm÷R¥l¾rÞh‚¬šžàö¯q2¥U•zÁSV%–ó´LäŽMÌSK×o¥”Jâ˜>†þ°&^Îá8'ꬹH¡`d¯ ÿc'=Y‰£ÜOMŒûˆV× «ôU¹äÖa-€,sKïh›ˆµ3O¯‘L‹è޹%@V•+ñ©KU|‚”ké(/Ⱥ ÍzUk ÜímN9ÆclgX¨ æóp/¾éh*¥ôx="dæHWðiö!æƒxYÌ  ¼ ¥ù0ù^¥œ5b dŸu†ùÔ%Û¡AuÍ„’ƒLv¤™CÇ‘ÉTsãÃ<Ï4ñåó²fZöÜwaм2¹×=k¹cp,ÈŒé2eüo˺Æ×»*Q#“‰c’­dåƒ×Úpû˾çÈ€².Á–(ÉÈŽäÓܲ¦xoÒ´Þí†÷<1‘wæ#2)chžÊ Ô…l32‡ÖVêès„wM8†É”HŸ ýžIž]Yµe¦TÀø2FȘÜÚ'&eUÊièÅJøÞÚ@C[#šòÁ°)Y5·-µÓ,ÙO§Ôw@jº:}„š Àw? ªŽÈ^S]ÚÉ6&, ¥ªit‰ÌY%Ã86+2F;žF[d•2§?î蓶ðÝ«~wÁ ÂYñð6z¿‘Ä)p¤—'ƒEâãþ$˜­¢£^ ¾' œæ÷‡*¾.27ªSÆÄ˜}æ6!p,FRb”ºìd¬s¦d;ç£1ÆëѸ<7:AG]>zwá3¯C¶v;ˆô2üyûëÍð&1¯¶6P»g(;úó“`aFÕŒn;ýü {!èHÑ`9 ê‘ Ǫ̑ݳY÷= ƒ×¸j'KéØh‘uÉÙê+‚ø4Ès‹w)Çþßý5Á¤O1«®{ r†&†Jöȡ.SeG¡¥®ûšêDÊĽ…tÍV)Y¶¬ô"›î+ÑÄÈ­1ÐÙ"é‹lcjQEæ ˆô›eŸG#TeÊpûgX °LÆŸ¦vÇJ«bºT¥–_;Y¡ú…wÛÞõga¡>ø£~®az w Ó®F65¥R ±Õùã1ŽeQãcð…_‘ùgظºð5öCجdV6¹™êdåºu½Ñí<[2½n‡½ëŽd C•&Ë37í¥XKØ‘FL#&îX;LÐÁˆFäPµÆeb|2z¼˜'Æl«•n?1™P’ë•Ež¯ß¶Ê(ßô=&5ýËUeŸw¾5k™õí“©öYÖ‚í!‹4ÈÜa]é'H&÷\2y Nòɵ³F Ðgûy•ƒ “iÂêrìÂÌÆ‹66ÏgÌv¨«}hÒøöþ½OçKËñƒ .æªÛ6 ²Þªp†”=–‰gËpLHãþû]½ª 2lx?$÷3Ç·UVJý>Ä ½ÛÙ2"dGƒ0­´¡Jz³“hL¶m–j©*7ѸÌãÏç¯rï7æƒcrÚ8׫…æKƉIß¼Èá} 57[™ Mã:NãØæ£/ðÖ«J–2ª¨‹s¥™;’Õ ´Œ}ï+ÆQU$Îg-ù+Í0ÁUZ׎[)+þY5h¶ù éëõÙmO8A{nôýSŸ·¶AMYWË;zbp“:öU1Ë™ÈvkP-­¤ Š4"1]ÀTâëUjùõ&#Ð(‰õbfUéÓ©î)Dézä,ô(ÉŽy)å‹ìJÚ‘»s-}*µÈ_©YåÖ§ih1 B¶Uík‰¼5[ã~¢<5&¾ó>l»Y”í@Fü#A-H/D†² ‘ñº,GzDŸ—0‚¦xÖÏßã~€³R[!û,»it”»OÁ³ÞîÈg…ì( G¶ÄÂQÆÈ™ÇÀ"@Êd‡}ø0^ØÓ±p$¸qþOßIJ2rüÄJ6tä–ÌÓ±)ç ìª w¤n^¾™ndzÙûä“èKÂQäLÓ§Ò‡Ôì>xæ@xHÌ•’!>à1¦“탡W’Ÿî×׆m¦F™ œmz¸‰îe#RûéeL6+L|>pË4±RyækÉJµˆ'ëÊŽb‘m·&nz#â‘=I¹M䬺K½˜‰f™¢]VòZ¦)‰Çð$km¸®ª”%ÇÏKH½ر.G¼¼hçŽ0Y'jt‘À|¦Çœï‰ÛÚQ¹kàyÉt“5à>f'ç“CÈ»Æ÷7­^V›eŽOà@–-†ÎV‹ÆJès¢I k #}fŽ[&[Œ_4ûÀ¢5âåôûMÒ/(Ëw™²•bö`;ÒØ°¡güûm«kW#ÞãjmŒ ×Kœm]ø=XLšGþzùvG€’FUvÜÓÈo\™OúcT;—•€òĘÈñ³wÌ!g¤­v#¸Md‚Ö¶ùq Ÿ=½Üøà#¿Þï Î4¨:MLÇEÖ…¹”·1€ÙBÉzMaí¦ â¬dX¸L]»ƒRnueeVúªp¼£’ì!ÂîXî)Gæ&/4žžâ³³²¼^ÇÉ'ˆ„E¼^ÏA`jß >Æzæûú¶vìÉÔ~h7¢¡YÁ ý•®®ø˜°®=¢¦ð4ÞtÊöÙ”˜ã¡ºSf~/IÊî>[佯Öž²#É`¥Þ–œÛ0%¾+Ð`ÎAƒ‹y2Œ©¦YÀÈpJ‰É—#f¤’PâŒÏAÆ´J²£~Ëjqh([f³”r“²åµJâ˜>O!,«Šx9,O|¯:ÙªµäÓÐiŽïÛ9ÁY&ü5†é;öbµլȚR&ÆC‰Ó”»2Ç1écdÇÏŸ$g¤_È@ÓÝ»é€vA&m2fSúÝ®JÖP€§)Ž….‚zø óI¶¼‰5ÒäIm÷šO@unÌ{D+9äsîãÌÍ´mïÌ1Gd?¸ÈÅfo¤’S0á Ì=V¥†1‚ÒçíKNªµ+¥|T'µ€|/Ùè”]|S”º&¦v <Ï4™Èªa†Ê€Òìqy”eš˜à‘Y}Ј qŸ_ô[oŸ>åvÃǨÖëxw9“õ$«–Uźö¨zªº0ª€Ü¶äJ˜LæßM7H¯Bèx¥â™л)0¦Ræ0}_(@ÊHÙ17+ÑÀ•^? ÷ÔIL4âÕö`dó€{!îJQc A2· ›p2$ Úµ.ÿíD|GÙ¬¬àû÷f¤•èkámøT^Z w”UÃF‡µä&‡å#èÖ ë…3$}üu9Vj;òt”»ZKÂuÉ‚Lf"(ËOå4:&ÀäS»£má<É0°L¨=‡Lâ³Ú ‰{þ~ž)ÙÎa•ÞÃÙt@°º?k²²}úÎ"ÜÐp™Ø;9Y|WCP¾þ•),‘ànj Yô쀶! sNùùTê¢t«˜Çì IUÉ b¡»sã>ïŠQm㎲õ¶O“§#ÏÄ{{5kOÖ 6üœaëû‰Õ<bL¹ó4¬éiœ¦ö¹) %Ùç‚71-há(öp:n:«<aC¶€ï]X•Ó“1Iܶen@qË0Ùæyïß•_/MW*ò‡õê"Ûæü.ÞM1íCY— WmîKŒD³Ç õÖ~ty…‘Çéx¢ðø=KO ¬ )¯1Y/}a<¦{z±2—=ˆ6“‰= ˜²)h"“9#q> ß4“•5ª–i`¼£Ñö´dL$Ûܸõ0b&>’g @¤7zÊúœËµìvHá(zVrVü‘MÙÜ % Y<+|ŸŽ’#>9€¡i\&2r 9æl“|l3LŸ ºœ2r#€b2ÀP$e¤ìØ-"iªâ#åO3ÅšI{)),aõU1ù6ƒ#ê L{·éX¤4Y´÷ãq~“µÓBŽœRÖÞoG¸>Àü³íÎa&Är 󋜫#óª™o:F¨â|#Ú$Y9hn7z ^ÍÒÜ”2ñ¦×ˆÜáÄkD›ÔRÞ’Žp2¹v›øßÊÁ¦l¨WH–&±öÝÂ1¥ks‘ô{p2¶~ºè;¶ÕpíKÓÓÎ?¼å#ëÝn¤J¹ö6‰¤QrG½‹JH‹dr€r]«¾þ ‚³Ó`^‹ðÏIÄJ=_XI.ªÎ¤c%-™T½Iiﻤ×èd5b˜ }lÂ'½%8ÚjCk÷i5z?f<ÍJ™XûÁô}ÇÔ[i™­öÌ[rW£Ñ®„É¿cþgÿí©‹¾Þa] úÐN#´ãWâÐ2rn²v>€•(§Ñ^#æX¼]-17/w¬´Œ.‘8ãøµ0i%]FUpˆ·<&“žCŒê£=Ë„ÛJ&Æ ˜låÄ1³:‡¨ 7#5‹f( ŸåU½ÍÃçX£j@NpúŸ¸?òª²¨šX¶FHÉQæoJ8XlnXf%×ÊðíÖ³Å`¡KfÕÐ<Ë•Ü=^ûi{âŒ|ÂɪŽ-¦£}\á-9Ï ÓVûá$˜ÏlõZÉ’˜ü{P)•ðMÉ_‰LµK)‰ý4Hø)ž·V ΰYŽ™;k\WŒ¬K¤ot%̪”0C¶|ÇJÈÆ!¹Õ(·LþŽ·'²™á§Y"Tjý0޳Р{¾z¸IÄ"\ußràvÀˆ »äªR¯hJ{ÂIÐzad-Oý•0! h?^×–j‚H™øþqÔïGÌAÐ÷ªeÛ#²†cëÑÃñÇD&bÓÃ7Ȉ˜Ž·~æ°¨§÷Þt›¤qT…Ƥ?åçFr ãÏÅÞ_™MT=žÒixŽé'@êJVN&ûàÆ´d½J"†°óýL"×r—8ogšY”"fþ¹ÉöD ‚Þ´×/ŽXåÝMYÐa*Á;ªJwø‘¼.ß#[‚ƇdE-E²ª²# žÎO_„•)s[/¾Û’²÷UÔ(§ È‚‰G'Ûôø=;UÇž€#™Ìñ8¾§?õ×'­…lJÇ;(»Iíp%ÕJ²¨jº¿ÓìH è‘2ÜGœC£4F²eÕgÇóƤqlP#À…#™pÜë”æ¬ò|‡â ¬D£ôê|_6d&õFjøŽ@8M-À’>åÉ*9Ÿ‡–Oßô•±«¿%ôŽ>k¿žÈ,Èq,ž]ñ@Çe ™œ,%¾à„Ï“y&½ï`ÒÃö<µw(5÷ÔÚ¤®&<Ùݸ.@dP†˜œ¨&·V¯øÝV¦§XYïÚæI)ð1ðZ"g¤Ò¦œž'0žiA/#ŸÖ—§cŸbíUÉö=DÌ¡–­3·>ckôLñ•¸‰p½|0ðç¯ÎJ«W»£ÜÝן¦­tù+þ^äï ¶­,Æô 憫n´’È3ÜóO£D°¯9#DÏgÙDšynC qþ~†³z ^ÿ÷Â0zeCÉ”àZZfwI˜¯±ñZê (ÝzäLÖ¥óËBìlé¶qU.¹÷ªuÕ&qð©E;¼ê|R:ª†iì™Ã `aº¼)Ã@›—gˆgè.Í•o‡fÕ›•ª…­ÑsËßž0eÑ ½è.2ž&qíµð÷ܲ5]>=ÙÓzR›ÒÚ‰s£qäp+­9+ Rc¤LÙ1Û ½A%±¬šXÎPFdK l˜[¤jkh:’™â1Î' וÃ#Óåcô|*r%¹7xНo¦œ1›>ŸÄw)½ªP5ÝóMà¸o 8žáÄ@þª"YW2Ù¥¸±ÝÐÖÆÔ+‹ª9ï è5TdN6§Aý 5&HÏ$2çã@¦PíØ(~¿¾`]vÈg£Ì×›•`˜hº•O–f~îf¥ßÂuÑçš«±®Ó±€ÐPO9Lƒ!ÈdíJv}ZÏ3Âô#žÃ@V¦{òõÒÔN ”ðYÕ¾·g$Á4ZÈû "x‘žÀªÇú7Ô.ºTäϜׯ$M¯ ¬ê('ö̉aÙ“¥™¾®†zVE†UéóÜ29Ⱥ6&vÄz©h-¬œo:y‘xÇfÌeü.†É Ëy—Ar(Â4ÞQ æÖ¼;Ϊö‘7¢Òãñ…ÔÜ5ùOßCáfsâø~o(¥oã½dÓ‘™È½‹4@V2YÊlëfîÕ5“îˆ `Zòž”yÇéäÏ$ºv—)‘mŽ2åíyo¥ôaPË´¥È6Yɹ’ëç?Ÿ{¤£ cmЙqý²ÊÓóН(¼M87(|¾Ú;4n ´m•0±,²ËDi-É€"Ü*e|ÃHÇáÙ’Éðå>鎖ñ"z”3¹ßK#* G1°•0ps½âyjšb4,kÙ']{¶ ˜4(œ(Î6¹c¥2SžÒ8—ÝJýå_þeÇ­„$î˜# ÁÄQ„» >M¥zæ áíð˜½Þ$‡˜ “É"CUíp+e¥êX#¦’\4&£ÑK#‘)c¶9Põðþ_Ñl˜Em‰rL/oXâÙ‘Á‚¦ROgÇ›B#öaÄG¶¼¡7ÙÆUš¨Ýs/ZÀ×áJÀÞÈÄM¿+^»^`»d|7UåÆƒï¨&nº¼§q3Yqée±{Á{Dm‚ дp½íó8½^èð69¾×«æ+Àÿ,¸Í)Ûjž›ÕæŽöÏPv›NãˆçùŒ:¯S¤L™²q1²cÌÓq|:N<ÛGxÆY5ñUã ,ÜÎ1<‘›Eù釦šrî2S¤ðJÉ7±£ q$X aäÚ·¼šü‘°Ðg¥$´àeá‰`´Ã40ñÓºíI);Îv¿â™oJnòJ@VüaÑý¨´IJÕzå|˜·áøÇã¤Z²…Ìbî8“» o4²”Ý¢+`”ZàLº¶ÊŠØ™½LÖ5-¼^¡« PÍ¿¹ºt‰¤#a>rÏÿöäL–RnP½faÖ2MË'nb†°8%«Fç)¿^÷3ªYã:iº*‹é§$»•6)•êu„[(½|‹kiï5jašLú´´+mмüÅœ®îßò—ý}à¿üNéʬ ÚVpâ42F(Íí¬øþ\µÞ4y&#@Š$N «Î¿có‘û€Èjì6M½ãå.˜3ìúçãvèÅÂp«—V®¼[;È)É:b6ø¢UᛇÛ\n%‚Üê‚3Ú¤Ë:¶L2¤cæöÏÄÄ­7°vàxr÷¹„+ Å|õ M²á†åpkŸ‰ª.+„§ÇÃd•âÏŒ÷£ Èý¦fÒ†²Àë¹Àd›aX© Uõú¼ûƒòþ;ŒÒÝ¥eLU#WA#vL¼·*A›lŠM`¥97¨õà>lGøÎô÷8¸êÚ«&˼%\t&žyz¥¬¶^L9C‚;²•‘2“pxG@u‚–¹e½Ü§ç½-¥£Mì0ë ȧíýíF‰yýËa [-£ÚÒqWµRÞµaïzš6˜&FµÞdy–9abÙOx]L¼©Öà âÕ™•&xǵ×x†½¿ÀŒqô6ða»R]1#itqà›n(àXLFÌÁQnzúHŸkdǘ;šÞE"³%ÆOìhmÇLdâ0} =,ÂJd™4«å Ö…éXK]€¡Ê¨%CXÀ²ªœIä°cŒöd@]•æ†ë ۄ¹4ªf‹Ù øëQvÈ4¦¶æ-G¶nFº|xÚ…ª÷— fâûÕBüôDÖWšLÓƒL§LæX(²&&`+·6ê«"iðŽ"Mí9Ü|J™ ¿¡Ùn¨Ò>dWÒ×^žÃ]]o¶rs;¶ð˜ÖÛCsTºò­±L/€voœMh˜w²iÚŠXDÎMW?ØU3‡Ï˜çQ‡e-| Ç7<_ê¹Å8îæð8O-eb8OU;«æé¨$õ~úï>Cmu™¢Œ7x[®Ô`™RÆËÂÔÄ9DÎín‡Í-kézôµËm•3¿‘‘K‹Û$\ M@&s@Gƒ`ÙqLÓïc¿ÝjLo «Ö h¡T-çì úLμg¥s^cÇJua8d…é.s¼p-¶)@˜˜ [ŒLl *bÊ>Çû‡'˜mnO÷iŸ§£ÒnFæ´X@N™,ÏH¨«? SFÊL ØSr|¥.Žä Ëçwô ¸8x¢f(±Ø§˜&k%š¬'ÈÇQ¤l„¡˜Ö­4%¾p|½›;2`z&kß8-ÍŠÏg2 ÍÝN ·Y9ȶÞl”þrX× [Ãè 4÷¬[ܸIJ¨Öµ+d^v)/͘&îÉàÃLºA¤Fd§å8½k:öÄ@J°˜Hãš‘¸öðrâ|Âr‘Lp‡[ôÖˆ.h)Ý©<¿†Æ~YgJÙx÷wL|,ž Û&’cVã§!PZÆ'ö‰3wÄ-”˜EfÞD<®‹¸õÖUîeu©ôµë™”sˆ¤IéÈD¬7P#çôŽ€ÀrØ>;EæpCe˜C>yb]éáªrãÊ|dd&åziFdè:Öy€F;Ÿ¶÷çBÓq½•+eŽZ¨%¹[¬ñÿH äIϤ. ,øG:˪Ýèl¿†zR”“â‹úç󉦲k?U4e·J¬´ÈËäv† „Æ@UÇÚïí Éd¶i"ûtvÔøÚó^ΡvÕ¸™M$ÐRP÷1½J²0ºý•V «’…Ë”ôHžrs;ÞÛ®¥ö|f èUUŠŽšmÇž®¦#="YdÅ^8î=mKO£Úæ)µ'Te2EU-…ýsèÈ'½–ÄILи€F¥”ÃJŸr`ü|*i4E¨qd₎!ñ@S>•³ðÚ«§Üô×?ŠD°LýЯ”iŽJ›PŒ!°ecrȰýn›?%AWòáºZö6ô;ù÷éN–!™ h ½Ž~ü ˜Óg®”Ax›ÓïÈJ­DFP´0+@¼éó©Ð;Sbn>A+…[Ø@hÌ6,ï8ê’y&4)0]“›cžå-ÓÉ#?€³®¹GJ/2´$R nŸõvÇF뢤Á»2,òð4ÛÓ‰ÉüÃzJ]<Ù2 x¶y¶‘a¥'› eº ü…?Í è¶ÝKƒ7¾m{_±ªËˆ[l˜£R«È”2䔹µåĪܞԖ1‹¸^™#’Œ¸5ZŸ¤#Y4ˆFnFw¤qFnóøÇæõ;AU`dUÑ1Ÿ^ná63&ük‘Í=Íï—IŸ&2MׄUáéÙæ/˜ÙÖÃSTªK&x÷ÿL“L&h dQ)P®½ÑshÖixÿñ†•Þv3ð úƒ¸R&ñdÚ æœÓèL@IDATq+9Þ>Ä妫z,Äð¬š. ¤’´;âz3,[C)ßæñ-°;2é.3ÁÜíñ2^d è‚…ܺ²#e®ÅbýŸu\ÞÉG¦”³•…#™q@Y£ì£A®«{ah]ù´½MjTíÉÌŠX©ˆŒO'òÎùÓLÄè™r7££ ¬.š™)%£.@7U¾=;êy¶óTïX™¬Ä¹–pb%¡äXè²O<ÆQ<7xý¹S5¾eà~<˜>F;€—E½™ µ¤L@ìØÓ A¦/w”õf‹lÖ6Ä<3ÏP$œ?>s@Éþ&ªæ`%/ë”ñJ=@<,4ÊyÎÌPË#?kQÊ>«Àé¿k¤I–›Æ”ÞQ®à¨‹pG]˜Ö^WÇɲªÄ0Æñx=Ÿ‚ìe%çãjމl§Çáõ æØO»Ä}Øk¤Ñ(³Ý~Ž1‘ÝY5“à`ÖZ2Œ©½’¿®ŽSBKª÷£1B;A¹/¿ŽzUÛvÓ³Ò’@µbb «ÕÈ*Oú¢^h n‡áYå£ÔQ бòؼ~ø»/A0A GÖÞ>,üÖFæœaú» ®äîÛ¨±;fE©Z´O‚Ä4=F¶4@@)¼5Ö®ZWUÊZ( Gb¼(tçyFÊs Dn?ÿº¼¤d9%`‘R™ÊŽ:½^ƒädð°à k$Nƒõ«:ůJ<.O8®àš›¦öƽzž‡ÐtLšÀŽZ ¿þõ¯ÿÕ_ý•ŸÞE~ýë_ÿîw¿£$h °¿]—u+ÁŒŒ±¶h$AG-yŽéH ÐôSm\Ô1󜑎‰ ºä>Sü™ú¼3Lи۪q1ÄL`Žäãƒl´Ò®Ð†|ÒW¢lÕæ:¶#>ÏZnOS´Çg«*žù¯×&ìáP ÊH½¯Ç”KpG9¾ Z1œ˜]²ÇùFvª|2IV)¬40q¤,"{ pÏ‘ÛÝÅÐ1[¥ZÒp¨J0ÿÀZöèñÙÆdùìrn!¼ñþ€ñ×ý×¾TTÿñÿ¡‘qY©ÆŽ3ÑÈDö UKú_'þû¿ÿ»Ê×…Ù‹ÒþæáMd#{,›‚¡w̪^8ýÖ”ü¸Kõ¦dÛ“w$K¯È\£h.PW¥Zmâ(”¶ ÜÚkLÓ±)–©+L#E½å Ü& "F —rÕóèó•³H4_)÷ ëмMðŽôyîˆÔëÈh£*TE $P²+2 €ßëÊè¢L&7ˆeá<>¤èå´ãµˆ6);fŸò;ÌUj[¿!ó›ßpÈ'>!†Æ&ÚýÆøÆ7¾á—†5æÿö;ÿùíoûÿ=Q—F»5ˆC³LfNÉ­¯7$,O³Mæ³[0Ú‰‹aD³XMsW›Ž™˜CäUŒ£„-¦%±ÜžÉcÖ«´FØVMtã+idâLà¢*iúù1êŒjpjd?"Û ª6rËÕ¥$§×C)7, oKÛ3ÄèUÂ8Âû´ŽxLXnõi2œ&WÍñ6á»–X(‰ u¹ Ð.”:*ÑÃ2_öþÅ /™¯çÿüÏÿˆ³r»cqý¥ç†ÏLïßüÍß|ó›ß´‰#AÎŽw÷ÿðÖþ·û7Ž.KÌ*ÞGÛH-ƒUï}b(ÂÌk¾÷½ïµ &g&?ùÉO\VÆË9|.øï|G©czЉe˜¶bRŒltwŒ Ï-O›à= —å–¡|ïS#RË.è8~žUÏÀ¨ÚtÆTÒ Ø¸jÃZès<« ´Ã2ÕÀ¬ª*¥oŠ|w5ݳz 0Ƌ޻ð4ñj!ó á'þ€ª½ÄVíc¨^¸é~„¼²¾°Ðþ‹_ü‚ƒåŽ&Î'€^ýo}ë[|üðüìg?ce´[æ^ m—µø}âå#k¥F0ŽãÃ@wä92[ï ’/ #û‘sÙMXÀÉxÚ£½.8&ÿ0éÇûöñÐ42©=q Ë·R©ª¬ÄP¶[šŽ•úŒðH;´FÙ†4°ÜMÁÀª½!½ ¯w%‘€:6 ¯n/˜ ®”H@TJ™ àƒÀQcU@`ûA¿aΟ"|f^¯þ$]—LàcóÆ{ÛÜP¶"¹K©ÂxÏ¥·Ä{é4BéW¿ú•?’0¤É ™Éœ10²ìh Ëÿýßÿ=^e&^ýî’•ç韛Mü—ù—´/\í·¿ý­ ÙŠZªö`]bU`í‘F$ó#71Àmï¥Ëþíßþíô?ÿùÏ™‡ì³îé|ˆ¿ûÝï~þö»Ÿ¢d¡§­cð}<I Úò‚¬š'±–3à=‚•*M<ÁªiúS|þÀ$ºìÒ…Ûö°X°«9_L$%2F¦Çxd –d"×Ò¬J1ŸgUÂï÷lëâ†µÈÆyѽd½ô}¿òï3ökak7”ŸÞ•"½ þîåSbè%á>†ékÛA{OI;€ÄL¼ý€e~úÓŸúGÛóá€Ñ®ôË_þÒ×'æn™'cë(¹ÉZda™@̽UV d®ÏŠÒgäë?|O÷04q¼.>F8öÂŽxŠŸó»öð}ý·’Ü>Å0wô|¼‹HÇ^Jžš&:R–‘pGL&)‘ÛSðÁ“Ùú0ª•^ÿ¦C+*dä’aYOãÉDýx$™Ü׃1Éú2Hœ ¼Ë0Ýdé[#†+Ï·?‚[ƒ¬ ö õOnt;x¬ÄýÚ_{›e†€^?]ŽJ><ï%`“Zd¶ª˜îR©£)‚¦? ÷' ß~„ú9Ô"šE&`-²Yæ6Ú±èoT»Ô›{ý¸òÑ.«*uì.‘+m7 ¥Ü«fº<_óøæö`=1Êá˜y<OÕ׿ã?B¾. rh >«a>˜žO×ì3ýào ûë„*Y]@ŸEækl%-ª˜Oÿ Py=-ª9Ó²#~ŽH÷—ÙiÇÈ/;Äc´ÈéUç³÷Þk±Þ4Þ 6b-Vr¥Ö&Μ™ÒD€²M\áÿñ}‡!u±íþcd⺄F %[GŒq}ñ;{õ½IHÑ,9±Œ”côú-ñý￟X|j±µ4B6qoO$=‡J€# P¯M0 +¨z¶÷w§zs?1¹É¢Ëš¢Ô¼_tý¼Mü¹ÑŒÑÚ˜v“kwGÀ24é-É_0G*&˜¾çÓ5U5Láw¤a¥2 zþ CÊÑO°$YƒsÄ0MŒ'†e;xXf`"ñÄÝ<7üºÒ8>ï¢ïãÍ›þ’oq¯…ðe?£#k1³Âl í»?Ü ÖN÷ÏÿüÏûô‡(o¿Ä|–ékÁt@DzP¾ò}rÓ¥ « Ëí?7µç~ô#g®ÑÛƒ§ïRîÛ¥üvK€QòØ“ñ×Þ”Äø ¨ ¿ñöôÞõ/ùÇôÆ%[»N£µ ]5ºõç?Bž†~ízM)Û-ðL>dÁ' s¸+Ää`\›Ô˜¾é˜Ž ôŽ ¨º‹AŽ4°5þÂ**«:õ'r¥@ó’Á-§´-û™i^&ª@Œ<\»c퀗ÞÓôÁm)kñ§pß(~)÷齯{R4s³µ9Fci¨ªU`;øÀý'`#~üã÷ÈêÒ1Ÿ{·Üðþ’ÇïC™gÒªJ˜Bc½üc¯>MŒÜW/fÎïîO¿ßÉTi Ç‘vJí¯d¨ªŒ¬x\~Yõ㺀<¿µÎ¢×»»F‚žs-4žÏÛv -ªípß/h”ä.•tTËö7%qšpþê¢ÑÞ“ÏGcÕ2Rèrä>ÿ@à,³ÃÙÕ‰OPud[&ƒû$Úo²ª2>+K´\wðêûM*Ÿ ÞAïûÞGâ`¶€Åºƒ£ß”H¥Z›¢ ôÛ™@¨–•|ŸýÓ?ýÓý·fùÚn²]pM¼ù¯Ç­M¼^¦JÞ˜Q­=7X–Y €F»X øÿ|ÝQ®4MR¤áafXÛÁºûšŒæ‰|ëØ‰Îú—ˆö077÷ˆŒÌʪóuƒY Ÿåã£[`Êi.Å”¬Õ­½!Ö›OVÔÑ×öSäwpt<þÑÆãÛv£i¥nû×%º^Œ£J¹úY°J„ÁiBžø\Vàö ¿-±8>Χ Ñ”“¶'¤¦VôN¬îy‰sn9ÉÝÄMzzèg…m …!¬bF>æƒC®ï|WÂSÿ>ˆåzÅ÷ ñº_­„t¢ošðN?ÇW‹8«ÛãZå3;ø·û·÷óÏé÷ìÚÒ0[ðÉ;:ýó}Qqô}ëà‡N(އµüFàr£Ù˜p/Bš—U´t8ÓLx"M† 4..Zó¢S††ã£¯DÓÙ_þòns 8åæ·çùF:hß¿\¹ÛE×_Ãý4B¡Y‰®#„râô[ˆ±-‚ ˜"pXk‰‚h¬Äh¦­HÑ»ÿ÷ç’å@³tá išJŠJV ‡ U&‘%ò[ B²8^y ΧÞó£ï)‚–8˜ø8ñ-Íc¾î‰»œ¥‹êÜk«¿zMÓK‹Çvƒ&qS¹ÕMdâ²D]NŸ!ûò g7@‚%–ÕXüDRˆÜ¾©È1ÞüZZJÍòcZQ¾)§+²6€µ ¡Ã‡xÜøí?ÎFn&‹Ì_ÊýL¡Àœþî8N¿Ë×ÞJg‘ãèkÃb[d"ø¢pÈÛþ ZÓt6Šo!BE…*Íù|(0ÝZaMÒÇ {èòI°"­ÍTÇ%JÌ¥ì+ãëÁÖ_ˆó‘µAd¹MBë AœHŽQ®1gEE=õ÷7m0wΞý5o¬„h¹Æ‡{Ú&‚àÜÓé‘&ä;Ÿ ~äF u>5NvZ|¬¢Õµ„{XK¦t”ŽlÊø@Fª1ΑhDŠn ß/?=¹;‘åªU"ÂLùù>ô^×N´÷U"úOJÅïþëœH]݉ªcr¶35 ÊÉRà·´M%²¦FFÇ(— Ñl-Æß_m×rŒÒàÉ5uúMíã¢u³qäê­pú¦Øþö¹gg‰ZéF¦GæÛµ¢mƒüÒGHEÖ=ɰ-ujß§ßãÊé_‡ÄµQ! 5MŒ²(óâëô#Çtú=ùDRWVŽÚ“ýÑY3˜R(@Ê•¨>«hOwSEás’ªU–…ÀWÔ”ƒÆ€!ž;÷§_éúß ²ü.4¤ÛâòùÆ_âFé~ø/ÑX]óíÈ=…#ËÒÛº…0Kƒ%‚ÙT:2B‚œš99׉O’ƒœ~Sþï¯@j´ÑPVN¾PSi–ÚEåŠ?Ž©”8MœB§ÿu z )#3 zÕÇ”?ñ6nI!†ãô]°ÒëJÝšéͧ(£ã[¯¬”§SEc+å´-¤˜‡Ÿþ×§¿¿—¥fL$&?©Sì¯OĈPuµX`‰áFíV 'Rè(D*A|Îÿôòãý9k{‰Ü&·(Çwß×åÃt y$y¨!˜"+=) i8¿æ![E¾,ȲL;⥴?qlW¹¦õI¡Òð!ù8§NœQþij¬0¿üNyµ‡p ‘ Õ¦Î™¿¨ÑÃãõþ-êGž?ÿù϶¯ŠÓ7%’¡1¾hÆGh#ô .ò¢¥Ù Â#s"žXÞzëí®"Ô´µlªŠt?û½ô{ü£©’IlC\9~­W—GÖ ÇTŒ¬ÆÊrûA)=~)i–R–¡žùSÖar¼¸CDgª8»Mij^o‰7.$‘ˆûß7·¥çôòC_:-K Ü8 )&Nͤ^ÊVA 30eø8·)&…áðË2å´±‹ž7Z¬KR¾é$8M·;•Älm¥ˆæFâ°h¢Þ˜=;U oô³ƒ—»Ó¾#—BÕÃøÍÄá“5å-‘pé¦ßŸ9žÜ.[‰•–B-uY…B„<ùèH0¿x:ýåF6ŠE{™1M3©OöšÖjãÄ9©!ß~j@ÕK1¶4Û¥ø¦mÇï ¯×N –à@ ³ª¯1‰¦kïû_=ìB£ º®äšÖ‘]‹šAc4Ë ¿Ç% D3R3]o¦ùqÖ0æ8Bð§ÎçÑ–lš'öJF]ÇHÌ4‡Ad15VÆGîœ'õômŒ^_À)ñÓ…˜Ò™tdÈëN TÃÐpz®Ô0ZŠ@Ðz}òjô‰ß{‹éYÏ£Y“²¤C$rÒ4õ³ 4eõÃÑéãçÓ/SQ´=Mø¤*$jzrÇùˆ\Tˆ ¡€€ 1Ògqš‚ŒÃa•+K´Nôÿý'[÷°­À_Š,ûÐ\W>@^;‰ß?›K!&©a׈A˜Ƙ- ®D|Ñ*š¶Š'ã³{ A0Ö•!fše¥–²åä4ê ³—+ÎçÚˆ6ÞB+£×8D™e wR9Õ.';×íÿþ_»ÿúé èÙïà´‰üÒ©µàB[¨Ñ7ÑüÇô©"å.ma­MŠ<±|jÿôrþÓ7 ß¶Cä²ü”ùÕ­ £eúÞâô«ÓÛZ?›V×È„YY5°(§«®"ÿµ.Y†ÃÇ9ûû³Ã¦”#Ä1B¢ñ¥,1Ú:Áøå'Zí]5ƒ@L…ÊâàÛÈ·ˆ/Qß?ü»üÅ&šø–F9ž`EM×0'°QbÖ´ýI>Nk4ÝN‡ƒ‰ +>gþÄõ#שÛ=iz.F9…MWN:Â=ªäœÕБxnwé“’8¾¿?ôVbãÿ÷{û—X‰ðê+J¡…‰n ¸g0Çûè]¹‡J ¢l+Ô—º™[È(ÔÞIä‡4öí¹• Ñ÷©åÀÌ€ Á¹ID"GnÜ!àëð¡ÿî*°,¸(ƒÔ^̦&šf¡ùJô„"…ƒ)TÿBøïÕœþž>»jåìR.×XÃFÓÿÿ-„³–(Ô˜NtE§M6eB¥ ©VmÞcõÓÁÀ»É¢«˜¬‘µ] ðVÍÿ| Tu•LÙB z£dN&‹Sˆ#T[ø¦žÁ¶ f£­÷’xY•+÷«X™Oߥrÿ8¥ÛèžÜ¢•úþÁÛçu]ÆÁ´­ÂX¢!ˆ¶}륜¦PÿÊMÑhðR9 Ò.…ƒ_h›%¶„I'žlRùƳðq—®4…lþþ¥F:ƽüô´–˜Èr5Àòì÷1¸ôœ~ùÑrü.Ò.)ÜkD`ð“ùó¤·"ÎøEuB3©µ‘~âh²ø¢œˆY‡BÝ@H¥O¡ØæVá¶R]><­Ê˜j% ǑȄê¸>åï?šxü·N„,…²èh‘Ï 7fÊáWÔÅó)TQQ…â Àý™Ö4fcW=åÖÛ(ÚqW:µ×·g—Ü'ÏjÝkä·"|¦±ê6]4ÐTÿ•S‹cd-'‘Àü²–‹Y4qÓ{±@QÆùÃ'wO‚cú öÔh+ÊåxÛü~ùñ‚—ŸåjûÔ»º|'ž¥–Ÿ,eN­5Í&h,QoeŽRø-?Ó¥êâ“âqèœÛ—W>¹xÕ3Š"1ÎýAV~µG[yj|Ř¯M¯oNÀ^ë>)%8²ªUW¦Æj!°¢¦…€¬Ò.Ø÷n¿x HÁgäê†ç ™*íôß÷Wꪋ24)¦Û½©2eOͳã@£kbÊŒ@-ÄFu]ÊÂL!‘²âDŽ â+ÐÿôäNAnå8úOÐØm€ãQâŠS‡FÊ632+DDé:é°š²¢Ñºè'ï3D h^iˆ©ºlM ,Ë´êÃ9•Fàl¥² ¢ÎU¬ eÖë¡ s¬­d>›Š\ÌšVÒTU·1f£‡¨‡ÐRo£·ÎuB§ÞpªXÑ ! 3„@ˆoÛ~²¬V£,oÍ,"wjhUDstî긯ε¡í‘Cêa >:\¦ŠZ~ÍhCÈh´Á†4M¡4-ÄÑÂ@¹ýï—ŸÝÆ©U‘ –V ˜²EÙÉï[È›¤—XEK_4“•Øâ$^‡8-‡CĨ„89F8KÜØ¾-T4AÑôãð¿ü:QKJœOs ™hK p=åKæ@’¨û#ÿˆšª!!Î|S'»b½…?ÄsvSûnc‡µŽ,˜¦À‡hÆñ¿_ý]õ~õES½fê¿KU'GÁ·ÆûÛ3~?ûTÒvç§–8ŸHH…Z`ˆ­íBKd|N%8ëJ 0)¹¦ñçAP’Ìö_QXišýò#*¥6€k M!ó)ú} ÙI0šD”ãÈb¦RäºâšSä?zŸ#Ø34F„ï»x«™ñ3!´dù•F(%f;fÚ7~¹˜í-þûõÎ\IðKNZQ83å#p2Y¦ÈE1ù·iEºÄÊ IÌš–©`+A@vñ¼°z­Oyµ<¹»®áFïþbÇXçD\*â}Å÷òzåõéá w¢m0üJÐY.Çæb µ!qd Í…7Jg-œç³Ê5m”^J¡|!Íð“’îàÞŸ`h¬'÷” ®§)3ߣùIý öÊn´|Ñm…D~ïÉBµTši–80gxk7­=>æödN𦷵À[?²Y{R.÷Ü÷üžbDZZ¯ r8¾tßY|í \B‘9L.¯. ;3õÒŒ3*|+O”ßö!D+™Tpé98Œ?~ˆ±§rOñ·#'íI4ºÀN¿/Ó˜¦˜¿_~üÜÔï6zÖU‚F×ÞTlÍCœþJ×j¼˜ókøtó³ÔÐ1Ŭ(ç{.²P4cŸÈ@œÆœ©á°tøé<ðð³B6Gõìü§…¸‰X¾¢]ÇÒák‰ïòYz+ð= X%L+¡-Ù´”ÉrÚCL!SÆß(En¡Ô„L“¢Ü”ásòMYÓÆ4Ã[]È­O…ª•Aѳ鬘î_’F Ëf*‘o„í]…êmgM»º§Æc¶ž`U4î’,Eˆ ¿,~ß̼ÎkÌèô»Jiì¯ eA꟣16$ÐK³ _nüþ© ë o¬4ŸÕm ' 1ÊbOüwP]¨(_ Z>ûÇÈ*$…o9@)Oð“͈óýGwY½üœª?V @úü¡ï7I·ÝÒf]Y¯©Ñ{f¹p§¿ö( Aâ—Ò5*Î()gñkB–ùÈ»ÄàU阉âàÓÉÁ1UThʉ>ò„™VŒ±«gÊ1ZU•†p2xe6ý‰œÿôœnÔt©ŽÄÄ·Mt€3)5_È73'Õ/Ùíñ¥ÿò#×ÒaâK¤ÈEëMôüÑø¯ÿlì«ó¾c”^?]`HFs» !¹+òY¥9âJçÔÕúÁ¤¶•¾ºE­ÂTZoß/?Ò×Ö ÖƒÏN^ÛtTñ|ù~ùqúêüÕêÓÑç$ì:Ö¤(„U4²BÌ=€ª¾+U:‚¡Î40\ú¤8;±Ï•+AÖVÍ)—ÄL?¿HŒ·ZõÁ6Õ Z m»‡ˆ{à'ïü§L!˜Rh Œi¦S:‡Å·þ4ëw$_Ågß/?ýÙ A¢±tªbìbC4ìÁÿRpyzàÉ=M?Ư“]žÉŠ ¹ ê3­„¨n¥ùž¦ü³OoÊ™t!£iR¦SS̲8zàsU(ñï_~| ZHR’K!ƒWÔ”Úk+D½>õ,¨a êJ1Z D¢ôµÍiù_ ŸÕ¼Íaùµ$-Mº»Ë˜ø“úÙ.úhBÉršÖíP3œ|)M?OÜ&Ôc4¦›¨òxà—‚hÌ/w Ǩ•”åim³ÖŸÐD¢ mµRjÂñ_f‡üå/Á1åÛ>Ÿ×íQú®:5ÕM§V ^|Í|ÿÙ¸ß:ð×ê²JIJ –Dø#‹cÄÉF(¤CÌ…šn䌃¦D†C8ß/?-!“¥£Ó#ÊL¦þðå§ŸNÉ¿~ Hé3áQúÜÿ÷wH\Õª®D¸æ=k,šmLSÈ=f\:)K†dð*žæžöb¶-üé 55b)üoº'ñ ¨FhH •‘mUøÎ_ ŸS±¤ø¾ªÚÁ@£SâR‰¶œ;—o[‘E5ñ¡üÿðVõ_ÿõ_ŠÚ !„ïW Óo×Z …•€ Ôg¥=ðîWѾ:—µã•Bu+]ˆßi’8$š>…ø4YE9ñç¤<N"UXQ%ä†ß…ÔUåû7ûý„Îzã/—Z¾Áf¾~FCv u•ðYR@—©ÕIÇJ¼©Qç«ËaËzÄÎܪM%¶^£ÓYkÇ)T¹dqL‡T1M,ðsmš?äÏŃ@bIä»á…4”Â@S¡åx·ìm®¿4¹ñúã”­ë —è“Ý à\zõW½ã%‹¾ã[.~ækïîÛ)¶=¢ Cæ}÷õêïÎéaü'õ¬eéù¬fš:È#˜:µpˆöFˆÉ3 M¦ùê–x§‹†/ôýäöòÓï8,Mmäè\cüBF{ò‡ßl»KSz Gñ9OÆB[‡¡QŸ‡÷³pS&¤ydB>¤¬ž %.K”>“"ÄZ8$N#üa¡ˉÙþ1mŠ€v>k oLq9œh˜B¦’!|  ³Ë@ðý;dSÏ~>šfŸ @HåRKJ!‹øÎ¨kéµÇop]‰–!Ñ3ïõòCÁ‹‚Ñ ™)P-NjÎ ä¶¾:w1AFh-¶‹OÐ(º)BG‰òM³DòÓ`BL‰s2!S7?q'Ùub‹öp†ûå'ñºJä³… ôhCžìÏÐ-d5ŸO!ÿû=âIÕ|å´]9mCL–ƒé UÉHªåR4"ÀeUÔ˜SÝü;Û¥DL‰@cýp¦@vôÕk—w-¡HUB…0ÓùåYÛ‘ÓR‘MK7ÖŠKâñìÔzå@ð¼ñ\÷1mý>â¸:ArÀýñÅK‘{/l¢¿tþáÍ _‡,’ K(‹cºfZ¿ àÓ£UŸ5<&×§G >¬Dݶ¿‘ÑLSã¨ÎéYnº, 1Û™dãË 4Í7íº„ o!r9˜p4 ù¾­böÂ'˜•µ±–ŒîŸ×'!Îþì¥P¯”%’²v#<þ4ÃBí‰>CíÖŽY™¸§³´Åb"Ф&³ så—¿B)×’Z¿ŸUBÅ`iqNÏ=ž"4¼ë]täNÄqwš]_…ý[G܃¡¢UA¶ÝÎb7Œ)Y%Œì>ñ^¤é gR´º9J`¶S¥ÝcËå ôòS!×Ùþ˜ÒÑÀÊñYå&~WÁiÊ)‹¬‹mùFmÔƒr~Ýrj­=Ž,)8™N8¢ÈBL{ß·±ÛÞB0åªUiYøùœÖâqÓU¨“Æ®TÇCîÎÉV”B­I±Éæ×€•*a¥Öû°Î¢4é3)]”U‡h¾VSFH¹åÛ‡8z`”Mç2æˆ  ±عË)\=x¢|¡¦÷(äâÓrÍtÆøÈ¥,·ô r™Y)Drj€‚.ɦ)K´gƒ-ã§ãÕÈžÞýð)øL@È7æ¿hM·ÆE½ìú€ªPcu¡-ãÉ2ˆ¨“a¤)„Ã6mÉ]?‡À³ÖÍã¸û|#âŽ%ë¿O¼²(Ô''Ùœ@ˆ{Øûç¶~ù¹{(Z.Ÿ#Ê8útúk`"ó*h+ZZ|¾”Ãä7ŠL¼ÑcN{¬Ë×qG6µRÿÈÔÂ]eÛîf“B_Å4ë-eˆÝã7½G)¦•3fË i-]¯Ý uñZ¡´ÂÒØìùÏ8ŒVN­;4r…ˆë[bU×Pšh޵©©ö‘C-_¢¨S’P–'Ê÷ËΟþô'Z"‡Q#žÍwÿxpÖF£ô~쓈”k\bS!޶PØrð8nW=;ýrPƒÈp {]ùû¿ÿû6ÐzÇÿ÷_éÓŒoš¯(ò÷ËUì/h9ùÆÛ ZzÝB@Ú‰LcšR3…k€c!.7Gc)Cˆ›´Øþµ\·´ÓŸH›ãëŸÿš5K0ºß¤ÓIœ‹ÌQ% T¥ŠÀÛ²4­%N׈“,ä¯Uâ³$„£VÞXHNëµ$­3ѺÙf)c:é4!8øFœUŒ‡/„³í®«Fg·D´™ô]B:N´rùãphêm¯I ygp+ …Й“ßÒ€9tÖC;;©²ßþ8 *šzÔõx–ûÄÏ)Ù6:b zðìô?NýO³©\Î÷ËpÚ„7nS:9)¨îM2ÎFMêA¤¶r·d¸U— bêÙÔW;>ÄÓÝ ic[ °–hz¿ý»¿û»D< {IDc)s$®zK§ÈÖ*?Á>S4uéœÃ€ç?­KlÆ‘cV ÇH‡‰òEÌ%§ÙÆ-ÔñjyMŒ#‹£Iίï@¸Ír>7º`.[:O Õª\`E9.¹—Ëñ‰ï•L:}äêÖÃÝ\‡Ú®óµD3ÚÆz ìYè˜*qÉˆÚ N Ø”,gV{q€Ñ8µT¢·ˆÝ3KìÉíXCÖŒ¬ SŽÐaýÞŠý \9|L=p:=œ¤€]2Aë>OÙåîÁRnLéîUŸT½ Ò÷ÓˆOEBÈ#Õ€(…¶¨Ò¦E1»ME‘e•r$ž6Ek*wšçC ”®QíH«ªLiFœI U “4fÇ/„–¦('Ø'F¹UœoŠŒ¢Å-l )—öû·j‰.¼D&±>ù;Q~j¨ïsãYÿ8jÍHñw1äš¶.~ScûðŸ'Q«½]÷+° ¼Ý@¨PÝ"ß øí@R+ÁÉÇÿ~ù± %’ª‘6ÍÁ’x_Êz«½•ºK»j•–ÎI‡‚iÛ"e ¾—onö6)Ï#ÿë ´ÈÆÔ8iú´@Èuq9‰(‡ÖÈóSCà+Ñ‚£VŪá…Ò±E…€ŸYË)- ãÊàñÕF™å§;f`:h)Ѳ[ …øéç‹r˜DScï‹ nôÑéq’Ž-_bš òýú$·å«·eqزª55w2)øhÈ@Çð8ìdÄP¥¨1'¾Ýp=z]® ¾s¼]š~QSm|?¹éÛ²‚ƒ_!ÓUliBômEšû9)†I§Ñ”nä{ê;ýá¦6Ó³?…{ªùõ <óuÙ{,áû¤THcYÑv†/ÊGàò×­]Æ1Nç|Ou*Y¦˜i ºc%›._n)nD•Á_O8°*OÐXÌŠ\é4=-^O,LO/?Œ‰­ízq©¾_Ÿ<8éø¸°ŠÈ:©O£¶[fͬPM®ù¢štú‰˜ÒüóŸÿ¬I„diÂYRÄ}úGïKB>òÌñ Ò·£Éê¶\‡æUÄØeBæè™9²¯—Ì^~*¤Ö#ðy_’Rÿ@:Æs+ê?îZôÒÇ/œš‘á—˜o\Wp&…õa%ª¢±ëX3´¥óãmŒ Ÿ*bú9ÔŸ_BCÛ ¶)•Ê¢ÅI¢Júþn®JáùvBÝâ|ˆ§ÒjU®Ñ^—Ré4m·¬[ ¹ÃEùšt©–›ãÁéóz‘9Ô9BÀj 7å³¢ý¾ÇZœ~%î£ßYÇ×’Ñcï>Í}ý­¨1A†ïSåûådzß*ÚÞÚ–X Yp`SÁïG‰¨[hµîêº(¢|·r«pŸ[/r¦sozB '“%ʯŽi>Ú'óù½9îÛϯy‰5OPb²tX|#Í3"Ј&ëÅ Œÿy·©-Ð΄¡ÓåÐÂÑ"‡ÕB¡(¿@“k¬°éVd¥s²)HtJöЉ–í#›Žê–/«êuÕ£Bï$?Ùç?)”¥çD€µ´)~8'ß4_”ßÔp:CD½{ö§ÖX-~o>û]r3÷ ž`µÊmWûJ¡Ñ#Ómciîp²) q¤W‹¸)ŸˆÍñø-?ÅzïXŸÆtl g`—Oç÷é—îô×jm—^VUè³8¾¬jìr㘢±S`;SH ÑOÌhùES¨t~d>+øy["-@…A·T`Šð„:ÁœœUªc÷1§\ã “)מ Õ™1«÷:@Ž«ëñ_'q_ÑÚ KÍXi‰‰CHÝÚD(øñ§öâ'•O‡ÓÎŒbŒÙ(Êññr½v”‰·øµ‘¦º–ì_w#Èuˆ/cw!xYœpOnf:£ì †)‚gs»Á‡3› ±~)BNÿëäu át¡óÓá§fª+÷ùý:JÁݾ*]ßD€/§Nh~?ú.$ÝZjÛ¸­“HM¢^'>Bý¿XöpT¥B1!|fÊâX x´ ­ðÌì!žÜ°hF™ÆSêÙ/£þŠJ)”“l:Æ'ãl1Žg•k0úDÓñKQ޾ÓϹC|½²*ZµºZœp§MÑ—‚Ç^ÍÛMÌßMy6Yn‚q€iVB4š_úïï”^º9eaœªóåº[‘÷ñ2BŸ4ÝTñ1—È1­É:±÷ÁEëåÇ{ZAX)­‘BŸ-pˆ64o½ñ ”~ã:wì2:øk)GŠZ‰äèÍ]!K'~Í ´F¡LþU¥þídjE%rð3j¦]ˆá¿÷ɯäÂFZ ­ §å–X¤M·ù[ ÜÉj×ð›BT1¶~¹6å~²’bNXo|:Ä)¶~0Eáß)Db¢áårZ©P‚pþ–ÏgU9Åž?¦Þ§ßY웉ҢõÀ§`ê!‡Ü£ÎeóAáçð ‘Åyä~‹Ê1~¿ü8µž”—X«F&ÅH$‚)Ú÷÷¨¾?´áÈh®…QKÉò)SWÄ™ó¦w ü˜ó×›^L‰"ùR8‰4µL;ÿÑ8ÿé%ÊcÑsÁgÂtnN>‹Ò†ÏC÷ž“€Ìô_-þ˜œå#°ö~n€ “¨!F*À,霙tÝôJƒlÚˆÐ2„HU5°\Qf»¢À¥shvñ¾_~ºð²âO_¡á¢²Mߟ¶N¿“ÚNI‰YÝ»¸Þ2Ñí ¼Z^@_¯ÔÎtÔÞÔ\]/ͽ7»Ø^xœ:ÝüœuÎgôÕåÐñxÝÃ@'o…"ãsl ¡çüûåG~²Ô€(÷™Úàäk  $JÓoh¯¯à>EýòS§– -|ˇ´9^]8·ÑQÝûŒ{ÀDÛ-ßB^;ã™èq ONo_h¤T×vmðKçÔƒi‡ªP)ç^/ß\¸ä„²ÀÆ–¡’8¦ ùgç~¢µn:"ÈLÂøp‚cŽç‡ç6¾Ý‘'nÔ~j…øBß @7€q¥K„pT§Æ©C 'q!NQ‡£7œŒ¬ÃÍOÙÈ:ú½{tb<õ‰LS•–Ò´ºÒ_ÇŽ¾'wÈÚ Vœ;ÀÊqàj šQ Ï‘MeñívE™ëñÜÆ–å*¸Û…€ø@ŽŽ¾5êÊó¨ÏÀtŒŽ¾»‘ ÐeKÝÞîl¦ôî@Yz³ 3ˆÇ‡¨´rH×C ¡ÆÃ9âM$oaÅ„Ššr°é²¦ñùr‹ZáIxLôÖ„A’¥cŠl𠱬F8Có¼éyyGí kS뤳BªSàÛ²ïŸì5+E-Yõã2ÔR¹é‹âÔäZ ñºÿQªtB.KÓ; ¸´®™Óß«&q0Ié–²†»ØRêÐSÀáCžQHJÍ×v>Μ4!òú˜ÚFï`BÓ)QѺÒO Aú(~µ¡¥ë92&e ©”MgÙ–`æ¬[/ïuÿùŸÿÙ× 5æ£q> 0}V ‡Ó¬4„q€¬)§UTHÔ4DâçøÎ‘V*^i!Ô8Æ8!GFà§ *åÔ.¼"T-Ž)Ð:/y·N¯×‘é-e"¦¢Ý™n€—ˆ¨ƒ(ªDd~×òtö_´9h‰@âK÷ {=SqGÓ…ß¹ÇtÈ5Oë´hÇ=Áv£6Z—ÑT!µÜ`¯*¢Þˆ´dNR5™ 0 ßIz½v Å‘‚Æ5@3YHÞuÈñæÍb¾R–˜ˆiZú¯iÃic1qÜZN¹ûMÛ!VáylqÒ©m»jKqˆT®EáD[ét€‘Ï PÂÂÛ…ä¶;Mã·õùpÑŸ‘’%šŸÓ˜¸9ßœ?—D–iyìÝ×ÒýV¨rMÝüU‘G¨ M‚®ð6|‡²uÕ‘N'‘tŒ)ç-ˆ¦Äëþ„«è_8ºlÈ.•cÚ›`ÎtZlÝv]%Öª)߇LYáÆn§6ÁtÑd! r´DÇçÏëƒîÕßy’"Ý”qªž#HŠÚ뛘7Õ2ÅﱘlþeÊ÷Fúº²êü¢µÁa=5\)¾,!޶p!ú¦[é:²tŒYdü¤BŒŸL''‰%çÈ—Ã*)!|L •75š²üøý#kÊðCªeôä~ _ýö*õ´vúY 5¾¢ÀŠêóõuÓ-䈃Ì"[]--ä!òúÊZ\ |>¾ÜîK€µÇ™Çyõ³çfäœÆµDŸE¦i:½­e:…ÊhÊ>¦KôoJ®%…[ä¢9£IaøFe8F›¾5„ãCäÖ¢ÑIú~¸z¦zè€Æ$È©Ÿª„P«MÎk¯qàÔ„œ¾[ˆŽ,cNͤŒv–ñœ08'qç²…D3îÛ-ši´ù혱,ûÁˆ“ñ+ˆãåçUÅk±/FШŽ—:!ep ÑÙ}½º y½^.>¤ërW—Ûnpþp±öŸÅ$Ò*BjÆHĬ²Ï´E9tÜKp~ ¦rùéëУÇA«b!«^ÊÈÓ©>‡!°ß× Pù‹ WIN×ïä=Ƭ6?‹á!žærÚˆ`²£—¨Š'Ä÷õ?³«"‘fj‰Ð‘.d¬Ÿ8|‡›ÕÀFOf*…Žê¦R¤3åßS )²›êõDTËѤ9|8Î1ÅÙØ®B„XéÕýè=ð?ƒ¿Zj£û'ñ% Aý]C¼ºx«–K ‡#«|&Ý”óhœöëGd¸»AbÛŽÏI$M~:¦õSԾݿȉúRg$Åh.1¿6íÕ¶k¸t¥r…Œ«Ë×@UDK<¥ýŸ ˆñÅJ€´ÈBòÉÅéÁY)᩹_·¤¤¦<…r×(‚'Öë×:Q{ä9ŒP­Ös UÈ®ˆ·ç85ÐHÊ~í™XKÈH-™²9Vd]^Ï8á4{ùAk[£uÙv pø5Ì(+šÿýÓï—7Onã´ Yó˵.š‘×÷›ÓßÎp0YÕ‰°Ô ¬Öïź,¶¿,¹4'¿¡Í4Jy=þ=ûm¦¨Á¸'=5ø4…ÁSæÿ…Ù˜@Ž\äøF4«ˆi¬[Ì©}~-ºpɦ+9Ÿ“œ”]ÔEñ³…¨Ùh#“8fS4ŽjFÛ\3Fdo>^Ù%bŽ&eËã µRRƒH±G“šãú‘e ¦#«ÄJˆrò»£¢ÑtªÔšZNšñíÏîócâ¬VÌôÛ%âJ|¿¹Ù¿9¢I¯‰§ÅŸ‹Ê)Ôèäûç/ ^üZ_ncW§>‰8ý:¹/G!Ÿ!@äÞ!ùÈvé´òs?¯·]5ú^Æî­³"w£µ1eñ7&²)ñ¢ÈLEuºZH""‘«4 ù|³ˆ§ROšu&g ž¢È˜ÑõÚ¥#à3Ózå´›B6èuÍ\°~^ßøŒ”Œ”ăçëöÞî'ï ž^#S ®™Àh@âüB½G!x£à×ÌÆ½—’ÅtUcÄubL0ŽA–¾ŠîØþ{âÝu+!äAДüE‰4]9}~€¸K}ÝÔ rf+Øúi?… :ñ/U÷£ûjáxfÝ3gyÏ YTbSNHÊ­Q?÷{£º~‡&+ŽDNþ*¶ä¢{SÈÎÜ @ÆÄ¿§iV÷ÁûÍÖŽí·¬8‰`š¬`f*:ŸƒcŒÜ4D?ÄÓÏÁŒœžŽêÍÎGºASçìUØ‘õ…NËÓÂá0Þ‰øZ7Ú/¸ZU¥<_Ô§í½A8N¿ ÖÎ"¤¹~î=’-[Vå/×õ.QQ#ZÌ”‡#ólñ´­½Qø¡ÓbU_"§CÀ©«t"„$2YÓ‘âØF;à%Ǔދ0£3ç ªûtw.*DZ–š DÖ§Íôp%2Nß}ëÁ˜ÇîEƒpôÖéw}õzý‹7*g9Ö¾ÒuU?¢¬•ý!ÂEÁg¦”é ÔÆJ‹R+k~=Ã9«•S"f:Ë¥ Ìî”àñ#œ'R¼ÛǶŕ™¢}‡û‘Î+»ýÂd~²°é­*5|ŽQ´sӦȅLÖ§m‰é~ϼÓÓÏÅîJK©Ÿ¦DLÝZÆÈôSn…ÀiæLÇ4Ÿ“2§Š‘ù-ÇÑô§{—Í[ÄNLœt4Ca¸Ö'sbZ¸1²*·ƒëýÄsÑAy}°îg [fjM‰­yÛèôû‡4š®môS£¾±êu2\zÏ~¤¹hNßY]MSRª´Š-ŠÈ6Óêö>†FÙÛ?œ‚‘Å—Ø´[…¸idz¨qW''ü-^HzÑÈ鹟çJ‹AÆã@Œù9X*¶øõèÃ×ÍS++¥©VnÐj½kîTIô1Ò{¿¬t8mŠ©ôû‰k T:gâYð—!«nÅ É7¶jxÕ9nr/¯N¿‡(½4 †$…`¥ùÛ‡XÈBø ±]ô=üW‡=þéðïÜêîØÉuÛÇo9ü">£È¾¾JÙO#ÉÊms$¶êú‘Õ#L¹^óð…^‹E+^­´Nn°r>CvN0ýCË”¸5Î!«}‡ÁJ9¦R¦\3ø]£ø¢ Èò›"‡ ·Ì¢ËJÙô¼¡êi9bã6®0¾GÎJÎÑz䮦iÑœ¢j._+#X³€6h+¯ÊDÂÉ2>ë2P $µ×­e¥_QL)åB8í_ƦhfO/§¿{’`´Yu…’…'.g8á@d÷•OQGó?þã?Œ¸2Çã?2j[cššÄi­Ú³Ç=æ.šŽæ%ÖOk2ÜÍé#Îr¾waÂ%²ép½§“ên¬¥q8-°/f>Be•˜ “Yæê>”ÏÉ‚ñ#—ÞÞÆjsÆi±À4«ej“'•Î9¯0/dÒ2•ß (ô‡fõ”º,›ˆ_ÊzÞ8ý=ÚIùÊåô{àá˜"i·tcåÈvkÕ^µø+’²Ê5.¢Dc 4jU¢çÓß³ÙGvýËú֬њ'Ø’l嚊:厾pàË¡f[L…Œ¦'vY´¶·¨1PŠ6ÛˆiˆÐ%s^ѵ±hœOá¨Õ -–î„8pêÊpœ'cïši£!Õ+=…²à@Æqô÷“°‡“£ï9'DY þšŽÒž~„t!2ܪtUç¹D˜~^ÿîYb{çHÿ¼½p€*GÓG¶Ë¯°–øvйÜÂ+熱>B"ú‘U«ùVíAËé[~ueIç³jõ QÊÆ!eŠãP:a^~\×¢E‰2kDà$èójiú@é>=¬ñOú“¿¬J(­®×'÷ØZR·«\Eœ®ˆ©\|Nßš¤hÌÅí;Œþ!øÆõRˆŽ»q„œúá»CZ°ÝhED ñ7e«Â‰3¿,ÓsÜVf£0§d $Äü°`»w-û> âO™ŽƒâôDѽO †³CŒV }ŽÒ9|!û«„_Wp»lºZí£h·¨Ñ¶¦iä«å¦ÁÜ>Š:šô‰ä¡•¬¶«ˆ¬ ²‹ê‘/q²n3÷¿@–ÎAæ[¯Æéuì›®¤O¡5âsœ×ûW ­«ê‰»E¦Ï7އ¹mè·Éeiã¾|@+uÿøöä²YÀŒøz³Û|«›š— ^Tb×BÁ2þî@‰VŠvzú9Žd‰ÛdÆ/”Ó"XÈ(Ë΄7Bº.ùpS~ |L͘ß8µÿóOÿôOu EÍjtx4K%Íñ,´5vÓè²AØZG+…޳5.›+až+ž¯NÃ4á4¥ˆjΆäˆÚÜd£Õ[QYDÔª„)C¾ŸÖ¦ÈêE+A îÎô„ ßé´áS3br¾©O-Y>£fJÇ¡4å kÕ½äe€yÇP´ß@žŒ“’ZSüëá]®@IDATèÀ¥L§ÇŠ)²uùs¡ÏO²N-C #±•&ҳ܆Ã%šê !M"®S7¹û6ñšiŒI™ñÝQVÇ'èZ“J0²¢ ¡•òõì⺦ÙÒH%ظhåŒ3%*‡sûM£ñ“åäÃ9Æô7 D>¼Ÿ,Ñ¿ùçþgM/ðA´L£æØñtM™D£ ÆzH8vǨ׊O V !»Ã8B¬K˜¬kCMîÓçùÄà(Ç0Œµ*E ˆh|¹ñ9@ŽDuíñg]xéøÚvV,)žmžýÉ•olE|‰²¼XÚd9š¯.…Dœž^û&jQ5œ¦‘”±År¤û†@Y禎‘í"¥s/×Í©Ojq(Ô§¢Úðs~ï™B…ï†$âVT‚‚rkTˆTÕ¿©³KZÚGSwpY™ÃÒªö\\!âÝ-ÓDÎ7¶Þ¦ÈjáoB€4«ÒˆSȘ¥¼ñ4ýœ–¢öAQ²¦8¥ço½ó¯ÿú¯ƒjÈH% £´±í-¦Ø1å—‚o\!#ÃOS³»ÂÈŸ~ÓøêBš·mPx¾…jñã$M”¹x>ñ«’¾(œ²: ½™ˆ¢=IŸLjë0¾)C³äVMJnQmX©sÀ8i'Å©DN‰5ƒfjÝ“œ3„©CronN‚Ò8pcÖn,Ä‘èõ`&µ¨f¬TW.J大C³ÓR¦èJ¤`¥ ºî85FJoîs¯R‹¦“È4‹*QÑøYóóù¥0¿qäjáUo]@›À8Èj¡1 $çoþå_þ¥‰±uËhZ2Pšõ«Ç©@·ÄÈ«95nz:I…çñ ù–fŸæ@¶ÍBËÊ LÁ£hñŠæxDõåôU¢+ÇQ"Y£ÄôóM·d>«½üŠòoàh|V‡%b–¨ Ä4‘]9Ó–³*¥—ed F4†&Ë(¤"'ŠlZ'hK¤Ÿ#+}øQŒß¢Œ6ÇÈj \Vz~S4üp>PÖMã™ÃÇl¬VÑeÅL_hÑ[¿BõIxŽrãÃ;v«©çÔøi †‡àH,«ÅgðI• !UÑÄùB¢|Íh;þê–ˆ\n`‹â‡Ë-kÊÑŒcŽl¯hfeád@£ƒoª±À_’6’³ì ׇ|9EáSZ¡ÆEM#7Â1{Ï–hzw@Ÿ©…ߎ†,”P÷5ödœ!)¹]<ˆ”m_®éº… rLÑNìy=HŸcÊÉG¨z|~ûÐÎnOLk_b‚ÆRà‰#]¹hB-¤ŠõƒIy¥…˜išRrŒCL‰cÒ‰/´0ù-y'BX ¥ „WÝXów4>¦¢ðV±D‡¥od¦B®)~;nl‡›¦ÆÇ¡9'ÁhJ˪PÈÆÏ× &¿…åC¤qŒIçiÅás”¯­ú4Ö‡lü5‘#ÄAS+ZRáU‘Û”ÂÚãgBÒwú—ÈÏn!HúS¾Œí”§@=‡+‘šq¸+=µJ ŽVâ“qRæHAnZ–ÒÈ‘YSx¾1?ÙÃx4»R…hš†Ô9ͬ®±«_•ÚˆçäÿìØ–Ÿx´ü*brÆŸÎdCîK¥Ü%˜‚i~ES€°DîfBVy~k„Üþç­€b'X[þg£cëCÔ› GI ¡¬燗‹`šT!x+Ì1ÂO ŸTgjsðe­_¨¨‘xM"ÄDЀi›XõÕ…`ÊZ•²„2œå—kd@#²©U7­+ÎE‘ I±Ÿ|N«ª™øF–HY¦9F>2gÓ:‰vòŸ”c…e¥çGƒÜü{Z!dú| é9…²Šë'ÄȪˡP kïY ­·‡ûWç„8­Ïõ?)¡E'^Å©iRb†¼«ÀŠ~>p9r0*YTô Ç®ØÆrã;m¦8%*…¯9õŒá­g%ÐDm "(TÅbò‚)#•AàËŠfÄ1Ös#$/ÄnÐTtä'þ9p…žF>+ÕymÁ¦Ñ&^ÛÖÅjµ®ž.>ÖÏôÉJLJpÊâgk>üÙøñU„÷PUÏ+ÚÓ !~ üV4¼Ä½swסE02)Õ ¯¿ZºjÒ’΀ÀZ©)Ž){"Ÿ'œ­±jÀ™`¹˜˜JóÃ9íñªWÀ^LE2ë·ón¡6údþ<óp(˜V›ÎüLm™\&T!cüѳ¸Ÿ•?ô³Ž£AÖênÑð•0•¥íÚƒC&¿&#Üx @Ú¬åÖUEn›fÍÔ€ÄRÒ4â°é óþÊA“S´ÕÕ-påàjA’’ a²B œ¦èÝ šëH ž>æ6çfF0²6“>§æU¯.$ß”ÕÐFIá|Ó…›¸¬m¬ÐRÔb)ë$ИΖ0…%ä×ÒKóóO H0Òx, S ©;Ua>«Å|8i>&~û+„ áËJßhZ¡U1Ŭâhpü»ládM…êßhg¥Ä¬–~jÀˆ`ZKi¥@ª ”˯ŠP"¥Ì/%0¿»a9•6åÜkR-c$°ëZ.ÁÖɤ¤#Ä1…76”Þp —+‹’rÓüEk¦¢,Aná„s:!j^]¸ø¦éá8ésZ Š#ó¬r‰ï0¬ |d4#Ã1ž‡½€ÑDaá$Lå˜Ö:‡gÍ™RXíŠ!3:¬bpfJŠSÑrÚ'øûËq¹åsJ¬áÈ©Q /dš¾,!£ÐH¤Ü|SCfù|‰6$e4Vbj‘ùé+j£"ˢ×­U˜Âo9Gô§deµ!9pŽ'¾\úªCLceIÙŠòE38Žr)¤(Qh‰œhdV'œ89‰C(äÃós$ŠÖ°VM'u+cÂÓ.+?§*ü9¢í[[*”Ý]A>Onì2æ‹©:‰š‚Çá¬cæ«KÑø¥SFæ³zÕß*N9Φ#‹Ÿµk1¦p+Q?ø¦§ØÏ]W“ÃË2âäãp¤*|­:Ü/°*ñ· ¦1Ã¥°¥C-}#…¦ò“ͳ1µ¦¤LÑ”órÊ…›Òœ>~ӻʘ¦8r9LKÆWˆå'~†¢õ ʈÜ6¯J4# '0f´F!`µNÉŸ‹Å i™r5cd‰5í•û<´P[d¤©t9m«L*egp)ÒCøú0¶;ðѧÃÓ=¤©±¢ÈÀ]¶”k,qS Ʀqöªc*%ªRÊÆÚ0®‡ÓJJŸd¦mVâ­K9#„‰‘?+ÚJGîYK…p"ß["d¬D D"ãT‘BÑœ®§\8Ú6vuá0Yš¢ü”ø×G`RTìs&©øS…·¾lä×dcâ7NVž ‡­:ÿ©|†ds€#ó»ú'ÿçÉ2çä?V«F«0–ò¹óƶJP’s„BÈ7ROÖl%6áÛµeE(‘Ïè$Þñ2ž2¥P­ÆÈF–2"AScWˆOÄÚXY¦5&¿*gd!ÕdE]Q‚±&©±8ÑLEéh f ˜€¦ÚN³>#ð“:Ëøù¸ƒÆâ´ðjJIa!Ì™NÐŒ:)K“MS(ÎÚ.d*e~´¦F—lHU(çˆ&¥JWv"þÕãÈK™2Ç!1ª®D \ 8KŸs¯9YNV”_ú9p¯Â¿1Õž©ãÒVcYÈB«Šz¹,µJLY<?eŽ'º…õܪ9! kZÖr©Ù;œš\Š©Í‰ÀÉp"W´c!ÕÛÜñ+ÃÑpè3 Ñ´èdÃñCJä6„ØXÊ£ý¹ÌHMºÒ¦Ê±[/%‡³”MBj¦Vn~úø¤¦Ö ²ê|)BíRS¾Ã8B¬åĬÖdK $¾U(H„Õ^jRrKÙBª2©Deq*Í)å³Y/* T}t"—OH 'hê¤n!@´Ö_"¦)ýRŒ Ó$e4m²²bâ×dxã³{¿×¡Æ6rò“ª 19)¬BzcRJå1`m䊎̑ )«BÕ­JRÆ»::±Vº'ÂêÆ¬Ä¶º©Zh1ÓŒ\~4#S%&M⨻¥!ô|Qèè>WMKgÈó¥³¶+Ü´,UЊrž&®S"úÊ…„K"aÑHÁÖsBà¦ÆMó‘ÂHI˜Ÿ„ñ.mP•eµMÈÌ4‡TVbY!²nàÄ„ eA’ÅéÓ0~)|'#¤%”[!¥@¦ÏǓӊ0Y·´hÓ9MÂÓ¯´i"ÈÈùUÒâ¯íZ­+‹¦åO™œg¾P7Œ”À©Iis88OÒéÝ ùzרhd».8•Hsåà²Új>Ç~Šž—•àdùøœJ+ºZq 7¹”euÐo>å@ãùHÕ“ph>„\K=‚GòiÎÁd¢$Ñd¢ò6 A—«µ…mPé™”Fäú6-±røÀ²ò19ɦì:ŸÃgs˜~ˆÈ꯶Õ%^´*!F"²±ÏÁj¥F̵Tóh¥¤ÌG{Úùôƒ KtcVn*Ô4² bÉpj)‘Ô*]o1£ ݲé'N6rŽPÌRT„WN­Š7“A²hR€ÈF=¼‡¹)Â8þÑ8ÿù$}6'…éÜx²Ÿÿ¾ÂÍXÆ)ø,²zÈBÑŠ*Ö†P ‚ññ]"0¤ÒÆ›èñ“¿D‚|¹Dà}P_'ÿg‰ —ÕÃL¢,†ó4õ;E7/ËNĨgYÑšº%&ˆ­”tÐrR3â„ÔX„ÓñÓs/u| [cKˆf„´>{ò>÷?P.¿ýÉW·¥Áç#cÖyQc½)]‰Dâ´Þ‰´ÿRpB¦¬fL™\{¥%ø8ñ… ¢h!8üù*‰Y"­%ÂFN½qd±RhÖy8“/dZÖçl€˜äHÆT8ñ„L_Î8p¶&šJA°­Ö 'QÆgÍÁ©­¶L®i¹¥$lï„"ŒÓ´¢µÑO“™V ˆ°m-¼D¸©”rËJ„_Ôˆ€–™*h]œ4‘#Ü:[±¢wnK–…@DˆÕRS¹ h¤P´ºeAšNʳômB馉EËMÜÈtbŒÓ3"}QN·1¿f  /H0ãäW?&ñ›Ð*D¥§É7Öqû/Ë´ºqÎÝYf•$ÜÒ@QÔ¡¦hµkª§r‹ò'²bm\”a6Bêc )åÕâ3¸[hå&ØÖ P Æø[pé@é­—>ƒ$rà|`: Á!÷£±Äiògøª§I^i–Rt4 –ÎW(…pé‘Ó,½f\´\ÎÀ¦‰$+W]Hú@=˜õ€¿h‚F„…v!Ò¬Ѳ’5ͺ|QÆAbÌ 1¦SȈŒPJR3Ѧ¸t×+Â#ÿÙ7>ZˆèùhÂa]cŽ!†½2¦BøEÛ)`H`äŽ „C§tYišF¦ÉWº«Îç´fä– ¤)12¼\#<°¢p‰øiq 1¥W%¿®(«Åçsdi¡Ž©Äh¦K7J‰&dúª˜TãºJ¹n“ÂÙò!¦hÒLD¨B…¤ÀÛO8kR’5bFM¹©ÿr‚Ž©§¯ñå ¬jéà@šBª„ˆÄl<5ž*éð•ÞÛ—” =¬Ïð(}ðÐRFJ b€çT »M1]—‡ñcÉápdmåM±€ü—‘ 'Ëò7BèHy‚¿»Y«eÈ%;Í:¬V¥EM‡Ûâ¢ðžUµ`u©á0œðµWi´é1WH(ƒ'H„ñ­MÏåcÊyˆ2>…¤ð·Ò[¡8Û(ƒ ³B9åÖ( ä×[!´E+ÙIÇ” ÷“2Áì¡|ŽS䙸¢:AKyÑ”ÛÉD ‘«bl&^b Ä‰Eÿæßþíß,‰®ù­Ë+3BrFŨ¬é¤ÓµG]BÈüÔDÕŠ a/)µ¤qDk '¿imœäŸ›'ÎDjO¨@]õ`KgãI{6´¥áÀùÓ—²æùÑpê¤ñhý2H>òŸa‚ñïD´å[‚d»‘T#¼MNd#çÔøë›-Ä-g`ULk¬.:\?|ähL™Êú\õ 5¶éâoš³étˆÏe«ÅO GKá|xæ§Ð8)þùZ€ÚþbD€äO‹“…W2gå«þ"Ç7ž²ß(ÞTúhü@Q–r‡Ã-f~„¥$Ž6~:'ù§z×OJK€§6‘RFÛ¾‘ee!;—¦ðùÔNÎL‰¤"*qg]ˆ/“Z'Ï´DQ`m$Ž0Íeqt’2¿–&[¢‚35H{U(Z5Å42ÓÔŠòsŠ6â KÉ1ÆJvYi&~—¨«KÁääÃ9–g)!Û%d«Àÿ´e^srøõT~«ýî?r¿+©Œ±¢ýK²huÀgµ[ß|V•Ò8E#MYuñÃ9)‡ Q3 Ùðý7"ˆŽ€“_‰M—˜ÈÓÂçpW"Ĥ·]¶‚¥#]¡ÕâÄ|2>]a® '+e뇡Ÿ½Ub”ìÓà%Þ"°)HydÎò×0MÎðJIYã¯JÌtà¦FRñof$…F9ƒ›¦C!‘jÝé “qª…Ï7íZWáa}î˜ÑŒ‡´4‹­^Scõ´(4‚dS´pŽƒ^а¡VUTV!Žþš6Â1k©¹Àq(À&]4BMò뇃–)+Úz¨+`OkÓZ…ÔC½E+]ˆQÛ8ütóóøiíMR–Bÿa'7²PQ#BX«ue¢ÜæDF3%e\J»QõÕ’ŽÐ4…5LŠƒcíâ¯V¡»"¿i„І§#zxÑâ8›Ö¹*ëÏj.…•ÛUæ¯4¾¯|ÃK/š2Âù|¬›ØÂŰsŒÌ´zMIì‡àT@ˆ™)K7Å `J|8ßTõã—.+fÑDR+4$p#‡)Qé˜4MKiÜÖG~’þ`@¾Õ6åÐâd µ«Õ–˜Ão9¦åÖRÄd…8øøŒ~!Q7-dš²‘Õ ‚eÞÌøÆÙÝ3)äF"üh!˜mÚøt–ÏçtlLWt ¢ìÎÂmO8w–PK‡Szü€å%R«ç‡^v‡k%ܸV¢Ýx>BMHŒCS"p-Bú «D4V[hS‚<”ã$¾û­{¡qEM+aŒSÈhÙzˆŸ&0¾Qt);(‹ÆßuÅd®çhMù dÍ'%¿–ÒÁLvâO/)ø²¢Ub#'Md;ƒVVUª '‚&´Š)”;‘MñmQ?š%"1ÍFÌ0–8šh| GF~ýðY´‘9¢…V¥éðU\]kÐØ8‹ …˜6ž_Ç Ô½.ï&Æ»…j"ñÞñp MQ1 W¯ZŠcôâßÛD6M3B ùU䬖‘Q2ä­°ÕÚx Hïx¥i”+´D)8v"±,`‡­ŽtZ:SÛ~öE?ýŠ&ËJäP˜,P®i¯”ÀB)›fëY.~=´«D˜Bá|`µR³]uþÐ9@‰Õ• )7rȈP!‰˜üø˜ Ñ!gÓRæOÂÏ–â³IñjÇôáž!#°N8Jó£Uóó Z7|á©ìHn5m!?YEsfwU)Mãð™,&ÔG„¬z]ÈØÃ{½ÍÑI)F:)ÙÊÕ*A8AL~%á@¡“ù<´j£©S.Ë…d8Z²uÀœ cÄI–Ï)úè}.U ‘ÝBÚötʲùõX?q~›Æ‰““ÚöD]ÑÒ: –©èÝ3ä.WÏÀÌ4§\>r=/”`SÊ©µ|8Û´ÒÑŠ­‡×*…'郘"”øòÑ RÊú}ZIi·iÝT¥„*3½0!´–ZýoG¨æ’MP7í{äÀ.•º•KÓÎL·T>DÔ3ž9¢õ“BQãÓ¤ +ß4YcÓRâÂg8­Bi¸á-*ø &Q”Ãà*5oŒžBäú7zm]‚ÆÔÐê­ºFÈ©÷sŒîÆÒl 7šæ—ÈÏFS ²1GT]åì‰Z[&g²M!h|Yþ_:|jü*xÕO„fð‰‹®"¤fº²çß«Tæîbª c¶ü¶Œ „´¨Uñ+IÔ›Lx„r]NWåv¤w^Ò,…FS²Ò' Y '¿hmX­)kÁ˜ó$? 1‹®¦Ëâ¼rÕ¢)„ÀŽîÏUŒOÒJ98|æ矄'?¿~Dm#Z›Ð5Be"8Y‰Æ¦mÅȘRè@Œ8cÆ$?ÿcÉBE[_º¬­q)B“m±u»1…’…#@j¦­(jÌIª•B**1ÿ~v€Sÿ8ü˜%X)ÔÎŽC›—;°´ª‚˜Ê 4ÍšRch,%ùŽ8¼‡HÁ/¥.qÑ8‘Öcø«y8& ¤èü¥À#@øÆŒŸHÍläÀ MñYޱܭ¨h:-6ßvÅAà”È/jÊÙG¿Š ùjaúÿždOÖ$›ZšÈ¬º…Ô­%|¹ÞŽL…ê‡ÃªX­t€õóSç³-§Bœ|4NÑR¨UˆäéësЛëSîkšl%R€°4‘ë™S”ÃÌT ),¾ñcÂ|ìjä«%ИÏQÅØBJ‰áóß°–cžé;Ò¨B a5íüäÿJ·Ô“5šÊbmAø¶#¾h ¢YY@!þ¢9Cì~«-D°Þ8ËÂY à‹ñ8D@ã³ÈÆõnzëÔ¤lQŽÐÔD¥›вZÊÝŠ¦ümÜÑv-Ç­CÑÿÿã-úª‘¦è +å0¨$Ì3g™’‰A¾`èw‹ïÏϦoUíF7Ž,³í3rTÞqn˜¶J¬ÈB£¥/›÷ëÙÂx4¯8F Y&è饬±*1ùHã´kYn“<¯üÈ EþJF gîˆTŠo–oFì5ù\R¸¶RüŒ«Ê6`Ú±ýè‹ø·«Çù3¨ö.Ü›­—¾Ò¾Ç×Í êVVe"ó7K¨æC‰”3L@Lƒq”7pÔh™pú|RΙÉüôcšÛ±q]ÃA4¢åõ #ðÌ»­Râ6±'%‡ãu¿yùqάªr%&í|†]±MZ¦£Ühæ”}y¾2šdr-²ÐE–a&1)[2Y5^Æ4]œÀhwÁÈ09Õ™ÀmØKÖ訴öd¿âÀÐÈíìCêØ’ùÔÕç§Ñò ÅøžG#"û -Ímù~ùK#tiÏA“¿ÜˆJWrrniòÔ„æ&ø¿]í@ЬZÒgEÀÁ]oô×L+iòîX)ç®‰ÔØhâÀF;6N R»_pÉ‘>xû U[¸ŒêËÔÞÂo/þߥFÛ­’¬QWÇlÏ—,*n¤c3äDËÉbâÓv•‘‰#Í=U8U$†™xSjéBÒˆiT¦/’°#Àž2=L#Ÿ†û‰â…ÑŽíÓ&²õdÕ¾¢ÚÜ rÓÕ¬ÆÉ»ò¬+‡»\»£ê|fE @@™?ì}Êp·H–R)[/·y&&}ñâ½.2 ·F¥e†ª¢ÝÈ`ÛÈÊ1rGŒvy‹)Mtä<%àX ‘¦`Ž—&@ßËÓVøz¨Š”cÎ ¬£d¢È—‘¼âéYkq¬:€·Pp@UÐ×RŽl rb HIãª}º²%€—óIßn1}Ú½ õÊÍÒ«ê(k„e9×õý”B¡íàÈE$­Ú$•;zF|r¨*·R˜M¯K4ÑåOÖÿnO“’£ªÙñ­æVnÜ ýAQ{½eŒ–2€,Rš)(OV;Ò¸•øhÙ³½NßWHU-âüûºí˜¡ýç¬X6”ÆóÜ4}ß­Z‹’£¼µ}4ÜÒèíóÍPW²ÆíØg¤Ô—Y-=‡¦Ó« ŸÌá"2+¥Kœ­(a >ÏËÙôÄkÔnºŸ9g2Y潊.Å™þ•Á5gãþÒ k¨Ü•ÃEÀ]c+Þú'X©^úYa(ù§DüGU{¢qLàiÒ;fŸ˜rb<Ò”‘€£ç3{{‘”>²—HœÀñá(”äxbѳÚgo—’iL¿MßÐöÇL\•R É-Ì#i*cÈzh¯3¬—€~’á]-7X»L“y•ÎeîÓÀ "5vdX‰FtU±A”¢*ñžçÓtœíªF¯7 Vª÷LºËí ×^®¥Ló:Ãß7޼z@y)ª¶rŽô[Ù‹åYÀdu…×¹1϶7äÏÇ‘IO³ˆ’ „Û0+@>ª-I üQƒY/,Të-×Û\ÕÈ+ü_ ÿ›ÕQî:Èuå6Á<1Ÿ€Ç¢±¯U˜ÀJÛÄ£ˆi%Í*¨úžº. ­VÒÂÊ%ÊZ .ÊÞ >Msçœa_} éì!t´­ªpì90Öëâ)Ó˜¸qô4}Qm¥L¶^üJ™ë"CæüæÃ mÂm{”é”Ê,jÃXhSÄÇå¾Ö]8M½‚ù½UÇdª>û$SÒ SNžs;“UãÈÄîø¨”Þjz²øå˜¦GšÎ_‹¼#¬J†Y•²[øÂ371R¤Ù‡]üÕ×µÝvSbÏʱç“ L Ä0¤WzõýìQ£lP[½íH½y¶‰L°.†®ïH¶MrË&‡ŽbhúQø®š-™3wYÌE+…‘¬"É-÷1a|"çU@U~ñõpi€Nšk¬JO“U½² ÐÕ*2&¹,Ú©Cæ½°jS`]¦„ûð„§d²ŒOÌŸ8¾Ñd9A@IÀ†ÊLG MäÈÄËY%–Å«dˆ©ýå_X[»1ôáL:ºMž4rkàý›Ä{ιÕ8¥ž­÷Òwb3gN™&CGñê»OÓÛüªþùWQ¶Æ†6â•…)i&,Fl"íéˆHšü‘ç^j«AYÄÔ“Fß ÀmÀ4AcÚŒ `Ò*@ÊÚ#«Ú j4…­£È$Xoû¤t¤é›&q¤,b´ÀlÅu=ˆ^&À„iÌ…%Lwj¿œœ­Æª›¢Z°*ˆÉ€í£” 0+LïGïV³"öxs#®W£‹èŠñމfØ8ž>sGÊ=Ûº´«¶ÕdµW"sœ¬ž ò,§É]°v>âýsI— ñßtêc¢LÖ]à4‘ybâeúwFïùààV€Ÿ®H±Öu„•ä’…ˆ ™´Üx2|‘ŒL2_K]vÄ-™¯°•«:âû#•\I/œçvÆÀHµ[ËŽá^©~P®¤q)ˆ·€Gjî.’CË=ó°£’Þ}º¶uÜWTHƒˆ³ÕÛ‰§TYåZ”à4²è˜~†ÈÚmÒ†Ú]özå¬Ýz™ÏYc äv‡œ•DL³ì©öÄÚ‡`] *㉛˜&+b>²c Ÿå-ÙÐzaa%-çy%ÒÓ×\d¦ó­i!¤#™ÆÄkI0£1Yi‰'Æd˜?œFžg‚eJQ# ¡H¹Æ¬”ÌÝß–zi4&id %ÐÏè@†È€A¦ïÓ‹JeGS˜pˆ©Ý1&PV¢yùŽœœà?ÿù‰aY¨ÞÉgÖ«ör(°í 7 ¨Q®¤]8š‹ ô0=@z˜“C«ºjÉ?^ÎMKÌgJ>˜ZšFa½F³ªZ/2@‰Ï?Ì9=¦ ÎgJ|3üžÎ¯å{“zLµÁªamGØYüãø[Ù¼Ö…wCâ‘o/ìr—¬Ð»•Tõö õ«*(‘éiDšÈ½1xúF8*]ƒsG%9°ü¿çíá2LжX½=®h±kyÌ{i`LxWhzÇ j®L_ Gí—>@(¥l®@ ¸Üõ;bì3g·æƒ”‘VjÿãþûR5gdGsD¿5ôvÓîÒíÚ¸MÑ¢ºö&¾Õ<¹M¶€mø§ÅQ4ñ¬õ‹ï/Á)\¬#,*ÉU»€£7°‘€°´Y¹vVª‘sp™RmÈŠ-ŸÄ@nÉv´ÈZ(UáZð/Ø|h„–¾„(#U…Æu-Uc’Õ¯ô~ùqN $h½ ÚA{ñåÅÓh̤GíH¦êÈg†Y9ç&¦!vÌÍ«–I%VMÔ+RÈñ@b< EŽ<¢ûdävªžÂï f®—Ï@†mK£$á|R&“[ž&* 0Uÿç”PÞ¼c¥•ð1òë¢Ú$dŸ€µÔ¥4 ¦)5Òs&§í÷u¸òT¥ï›ŠwH4I@é9ÒôÇ.œ3ÍÜøhU•ª6—lJšªr¸‰ e"å¶ðªʦìS@ôüñžR]°.¶dÈz᎘°Ühí•4ªÖˆá‹6™fLsu‰ÈÌ3ùƒ_zŒFY´Ì»*AÕºhj‘Û$^_©Í嶺öŸ?Üs›Ã€Þc´sý²Í®zt77ïx<[8Á”½7È èõL…’54ŠºšŽ€U‰¯êÈ´ ‹0ÛöDÎô4u%ÎsüH`㪲í=SâüG`D¶º9«H½µÜ]Î2ž˜Ü†;R LXν6¨µ÷ðGÖ… Н„|¹9ÊñÇ$YW« i8׋ñŸ.†1Â’®²‰Ju5ˆ3M̹Òï—T˜å; î±| ®³ž ²ãfOÖo3ŒÀп™ « @d®´#iÒ—i„jÙsuÚÜQÕJÉz½0ølY‰MW®EàÆVUÔȳ}zjñJ“aêݬ9—[Å”1ýŠÝYðâ—Av´€Ð.7V¥÷ly-¹Éµô;Ç6÷‚~ÑN ”IØQ„Ó;f.ð>f’Ò±vù]¯ët5 åû{9÷ʶF‚Ÿ'€ó‰ÄØd³ö³õdq^Gêfˆ¬1MM 3B¦0VìøvÁªÄ¢j½²À4.LéS ÆÜz@øM¡¯½–¾šK¦$+½-°¸Æç‘ÑèJ·@dSd¡…F•X¤t¬ÚÆx·ì™x¶ÚÇ÷ÙÀ^2½ [‘ Œj÷í8¦Osnò8o™¦Ùe¬ hçô Â8ʙҠí Eµ#ü~"Y)Õâ(®Á?Ž96tÙ”wnιÞL0³m½ºä¬4ô° Sr÷ô°È è(kÁŸ=¨«5 +0Öè¬õ‘myt¿/Y Øp‚˜¶Œ™,#z T‰ÑïsjÃÖ­½.¼ðæ!‰óŸ xæp²²«¿ ¯öûMË6¡ÄgËóÔ8Ø>¹l§áPLÌA/YàW?ƒà2«”14Z¬£¿5M™¿,òW"ËŽJvY#ú{Wo¿#žÐHܰÐXd3¡$ ¶U È€°Aª5F:¶[‚æò¤iªÞĺÖÒÊdáªùôTÖÿù5h­^g ]ÚÁÇXW•²·²*A%]¢ç8q ñ‘2Œ÷Á¸@‚ ¦ª®å¸ü>*¥ #-³ç»®5ö…§é؈|:VåÉv#|Gs ©4>PöQsiÒta¹…ä–ˆÉA&nœR?eβH Tˆ#m²§#óqÁ‹vã@  ¬Ë1ÏØ¥ÚÖ‘‡ª „˽LðÈÜÀ®So¥L*Á@sÓ¬Z{GXœQ×P§…˜€¬ä¼ÂïG4/Ök$ÈGÝ'p†ýB—»­P•oÓ÷>1o™óxîÊ­^ÕÄ=Jšö);Ö.k‰Ô²)VEŠã~´*7ߢún‘3ÁÚ‡w/ʦ´ŒÌªÝh½àuÁ‚¡¯½Ân€€æ@ú”¼F$ÐMÓ´~û×KY8æ ì²y:úù¶ÞŸüŸ¯=ëe%Ó×%ïÖ°ÈÁ”ŽH™>¥A ×E°Ñ ¸ãøÄ•Â]‡ƒF9ð àMI|¾³Z‚iò/«Â€à›¦'ž©ÔÆYÉ}Gˆ» ]‰×3Û í4¹y_1U1º­”ÌGÕ Ä‘°eઽî bÛª2Ì„ëm.ܱg¢±w"Ù[ÍS©ã–ßÚýxÐÂ4"\îi¿!°@wÁߎóÓ÷]Hß`U2¹°O+Q¾`Ï I™s)'Î3Y¾Gš¦ÅZC à0ÏebGÕ Úa ¨N–á^µq”@ŸÎºˆ óÏAþ¾»äÕ¸ò à½X¹`·WînŸE¬j8«3û÷S5¦¨®Ý1‡‹qªËH‹U­«œ ÎÙ’õ:¶Ïô˜½Í«º 0B Ï7ÂHo›À‘YßJ¯Xµrãö¸™`Ü4e-án6…žRÐX Ã2¦jí5Îs>³eR£.‘ÀChJ¥H™§¬…²A¯s¼/cþhÉåÙnVæŽ4È…£YJ˜mW>ºçÏÒÛ}Y£ÃuQ^+ä÷mc=…‚lW¿¯ð'ìŒøº°£8Í¿ŸÛš§WØCµu[ôÊÏçT‹,r(µ À1™)¬Žî÷,,óg¨R#åkn²È¡éÄ<Ý}Åu…·†£ÑÞÂЫ$gEïØooâ•„®š )Ž›U FxÉšÅÁþiâ[?ÓŽ)»²ÞÜ€>”Žª‚>²ýk”3lŸd0¾ÞxË\›ÿIiäœSZòa•­Û b‘ ’c;Ýâ÷ÂäPo|ºŠ™¤ì»¾®ÖÐ’~?RŽá£«# ÈÎPµ@Ì£h‰ÆqAfdä(WÂJ5ÆÔB#0JÉ<{G“ÍßsL/#EwÐLÓ ÈF§Çion-{çðZvGš3ì÷yžõÛÙÇ,c¶?æÅ±¸{Ò¼æ£ÑÕKL¦Ñ¡*ÏΤŽâF jÌF¬·†Ó¬Ô†›ëï"1@»bVÕ›3Æt퀄R`]J°ÐX/c<ýi¾ËAã"¾Ý'p7BÕÑ£Võ`ñVª_K&_c tÎÇò®Õ5ú`*U•{¾5ë­½\/Ü6­u¿+ ;·À4œµ·+€·nãÚ[©PZ¤Ä¯7#ÿFTÂ;2ÔÛ¬P¼½ÄM¤ÄSâ{Ñá˜Lä}ý´ &M†‰·óþÇ<’’~h=˜&q>Û QÉÖC¦vÕUÀ¥%¡TtqX YaêíÝZתÀÌWÕ5“¦¤‘g8¾‰ÇXr‚¬lîkظJõ}C{)ÙbÎÍý£—À0=«1ZP« bd^Y¤Ï§] 6;½ª_/ÓYOÓ;±é5zôÄ"$1MWúl€ø<éV…sèÖ˜¢ª’ckÔ+#1nç4ÞfáY Ì6II,â õÈš.ã‹dF«†‹¶‚µä€{VJM¯±<¥â[9C@ ?FoY¯,r+ Ld@£jí@Šf‚@þyb¹õK-¸#ÞÇ׎Ä4ôJN FU´ÞsF¸ÜDøŸÿš…¿¾hS{d¹ÔN`*Áú½mñëÊŽåz»€yŽãÿ ê"S¢LŸs>žæ._;Í&zÃÖ¨K¼#ÂñZÂÚå<+…eo¶* ±ÞÞO) Œ.Õ øû’ ©·ý òl–L‰<þß×mæÆéâ §Ôkh”<™f%“12ÿU 2ºÃÜÈR(Áã· U|+M†)ðÛÓñWüþyÆü¾ÿ¦¡÷„û(]Jx’ÈÚ·¡q˜×­=O¶[Î\¶üÑø?=5›$0²0žÚ*úÛ ¹È ž yøôe†òŸ0CœÃoþ?ÿÄ;Ì?Ǿ[äfI³˜8&ža™TåûôŽ•âçÙÅ3¡©ÐÛ³V² YÊW Rl¥–©En\aEÙ\”ªbÊ0=8“®C2&>GŒ’˜aŒãJªþå³¶ÛdJÝ1™!`†¦Þ÷viTÓïYeB\ä ka%úa#j§ä häJ”pßµ14 •;Ê0¨ëÍUÏŸµ³¤Vvô‰‡zõØÏeG ¦1bSðª)Ó(UM)ã#Ûª¶ddË·pþ˜HGJOÿÞ«jþôžlþ¯¾}æÆ¡*Pc&›BÐWÓØSêÉ8f¸vGzÇz ²H 7ZÎ6 ‡ÙVª1¼%„ lP¶} ­J³R<v)G¸¨±/F—PÚ>5æ¬D zSjQ97¶˜Ó ½|Ú1ZèÇ)WÚ»N§øÕS¶v½íL0·Zz¾Y ™OÇf!s¶À*%Læ(ÓäLädcÉôrÓØ·ªjLÓ8XÔÎSôÌÓ;U³íêéåö'+a@̼FG€›|BÁa³ã(âå»Ïyâô[‹ ß«ý?O¯q>µ;2¾?eÞ¬ÄVô ‰Fl‡ ]ÚÉj)§OÞ†)À4rU¦G·¦_æ0™3Ù¾­6¨?|6”žÃ<ë­½Yù‡É€>ªZÚ$7Jíù››‰<ŒƒêÚmÈ©=^æÓh™Æ¿ÖQ—£¥£Ô˜[x펔åÛô¥1@8°LǤRÁ!²c·»Ü!…•Ö•ž† WCóú¨æ£Ö›?,ßûMÿûK0‘žr5#€:s)ã‘ô}<0>&ýÚë-Ó\Ë“0i¦Ú591¾’cw®‰¬!ãE&fUŠ”së= n2zGí"LC 2‘˜Ú÷öLÚû$ê2·’#ÐæÈÝßSÅà±ÞºÊÚ9Ë4” r\ÈŸÀWE†ͪENC Ë…o.[[/ÜU²dnu©¾£ã“)Õ%'Ë!OdbY8âÝe¶@ô])+b¼Œ—7 Î!AaàÏDçGçSÈîR éU$;Ïí´ *o³l{ž>™’'ރȆ¶: g²œ«ÂÀÄp¦ÜtUw—™ïÚ0Ù«ÁäÀ­ªãÛ¾YwÂÙªA@æõ¦tÄ3® 'ð2ƃ­·ÏÛ11’I½0}LiàŽ”"Ÿ%¸­”<=³Âs0«/?dük{½OªªÔ2z‘ܫʪ9$ŽAö‘9öç<Zë’û_{0m˜ìØÜñ@¹Ý4v£· †gïMêX-Ǽ0i;þŽÈ-AœÀUù„ŸÙ÷‰÷èÝsIŒõdØ>s¦'ÎM©jnHÕr¶²Y~ñM 3ÄÈŽü'´ ärãûœõž%~ŸëÄÌžøÖÏcÜ"1(Á<÷c^Œ^|–žŒÜ89}nã[és<ûöO¯ŠÙ§ÿjˆ³]V%kçU‘”DVÃV2KhßÓ¶|;ãé ß|#E>®¬T¼Û—?¶‚LÆræôŽ”WrEÎ…Z¬ æ˜i.“J_ÛÓ$«¤±ã¬rC¶„ö¶Ç›xš[bDSh¬ž2+g%¸Èví›bOÎŽ¢ÅÚ¤™¸>e%YµôVÂÀMQa°5¦O,cz†yÒÔÒQ•æÚ|>úމכ cú2ðúÀ¢*çŽ1án±­2ï( ‘XUðÁH ;¾ná¿ Ü]d dÕzÄŽkgŸ¬R_p&ÄÀ¦Ô’ƧyÜÕôÊo3ý¯šé¬;Âzï¾/GX¹ÄŽ)ë­šyŒu)ëM&¿ cþõÒ›.€”€G¿‚°ù«ú&½®x¥ÂQÌ­‡x‡|ÏWµçC?Yß¡É0祸_*¬ñÜ8ŒjÏ&™Ü ³7%ì(ªf‹/"UÍ’‘4} #1‚21>e]“9öÁ2ߣÓÀ\ºDW¾sN„}­*­=~ÇWt}#ÄëxJÀóïSÖøÏwPmŠSë)úTò¾¾ƒ72Jí[ѰÜðí$#E©‡Ø}wDÊ—É3%@&k‡wáHyËØðÊÞ½à9G†)O™ÞÑGNײ)˜¶"@ wLƒÑî§[>kßh#arëÉÄ«¹ÞG“RÖΙ!}-mB#2'SÚ½xÒ œÕ™tyY—ª,˜¸‹ ñ2™¦{QbÈzVU7"Í58©ÅÞ‘ÙÞ±ßè‰shâHzŒ07ÓÚ˜ Î7ž²å0¢½‘ðÔ» àÁÑTµÄé¹Vóž^{¸U(™ x›tl |K6¨R$F ‡”Ëkñô›’ƒ^{ji[2A€'€Ëñ瘃üŽcE)㙄ßÞÍJI¶j`S´ç“f†[5+Ï¿Aëý÷Üž*esÛei0±¾Ë5V¢O‰ÿÉ¿÷>Û sÓÄ=mL«b2Ç„eʶMï(ÈôÖ£*Z¬g²c²2ç}mc¶s&˜FÿE$g.ïCéýžúÌü½¦HÍýX ³vÔKÐ17£*àŽ²ªøévešIDATäÙæ3< ÀAn½ÉÙêöøÎ°ß·Æ j½ Ò\íYh¹R$¦až"L€w”_ñ•RP­]ÉžL¬}&Zʪ½v˜¾ŒÉ`æ™ÈÒ#aÜ5ôlp™¦³ªå0ÍÖÓûs Yi-É­A“³ÜÜdilXxIXÁ^§­ÇVÐ×[£Œ´|¥Ä¢RL™&Þ1æ 2æmÉÐÂÖHF&;¿ÃÂòú7`Ö—S®ÅñU:¶M¤#e]}œ h&”Ç;¦·r½À«oú¦(mz éa·¨½or®ÓCÐÅέÑ=8íõÖˆLƒÜ¬Ë=OÇ [€¸Ð®T–W0 o.™3 [%Œ[8‘ù;jÙ¬p&rwQ½ zá-“9æŒÉ„¦/Ë”»&àñ"íz䑪4ñ}á¥\×ÄëÝ>9üá[#‡Ä3‰ÔH#ÿóÛ5WXmßB²Àˆ|‘yazúªW{RóZ(²ÆjÄ;Îà3r?½ôÕ8} 4¨)dïÙ™ËÚ'°“mø ’)¥Tʪ¯ŸªæöU1ɺf¶1Ë5&^K;4‹’gWƒ¶J€ÀªqOIVÊ@Î-¢j#’y_ÉÚ_UUº§èdÓtBµ£®d5*Õ+G’ Xc e-Ħ +Ñ#1"󑎹ÍgVÄÉÖ‚Éçûëvg¢WGݺñ4€É4@ ôD]Snd`ƒáµtÁB©À{4¹Å—[ÌD`z þ5‡wœ'†R»wEvœÉ4£«ö¹Ö%#U±OþskŒ)]Ší€^Ñ à¸iäé‰ñÍÂo( ôn…IÙhøOµv2æç—çÞöõ¬J“l A-˜ÄL¦Ë1Y ͆«†ÝŸ Ã#€ŽµÃv{¼%HQã2MJ@{†i "p4¢‡žçJ 1Ž2 –+ñlÛ5ÚN¶| >·¾=÷çF†åzmÕ 1o‡ªóÙ1 ×8ÃË„-LfúV­Ô±ö=s-Ã@J]¼¡=|J¼ kÛ×N ‘O‚üåÖ«Öâ¸F¤£ÿ}Ø2ª·åSÖˆ´U³0"\æùý~=¶~mîÆÝߥºXRU+u™6Àl>Ž2e»†ãkOœ oL¼û$C ˜F„½þ¤FfhÉ4W{¦·a÷Œäl\GÁ6"C™^5åŸõȲ•[&qssÃrÐà¼ö›Å÷xóAáueÉD¸‹¬7ò4ü>¤’cKfظFçF†”x-øžÆKÆ÷ûŸü Q?}b<Ò%cv  ßM+E¤Ùòc2ƒòt„÷[{ãOL ýYô†#>üýrÐ9V.ºðÖ¥f§4 —²R ÕN¬w‚ùŒÑž›Û"õÒ``þã¯ä©õ,8´d]¾x²2…ç;¥*[A ëåüjÚ­öùר 9>“9BiU Íå>Üc11±#M¤¡HGzït¤#2Y¥i±Uko(Ð%ð0F{šª‘ᦄÓ÷L´¨*µ¾–¦ÀÉAI¿,1ï;¯30ðÖ’ŒO·ÈV1ôÄ«nPšåïçç&Yö’½ßß%ànÎ1` ¡Ë¼|ðù°ÕXÑk/(½y?âü“RVd½ÜŒh þŒÿ}±æ_#²®ªxíLÖ¤QMïØE0¯é•f;‡@Kªç™O-¦Jþ(S¸^¹x}°ésØE´4 iP Ôò^I¶X#æ?±eÚ'Ï6ÜЙ¬Jì÷9Â\ÁÁþ‚€9¦)ŽYmbüÈmKã(hbd±ã¶B’UBj\‰8&Rþ/…!‰f‡Þ>IEND®B`‚ic096/‰PNG  IHDR{C­ AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs  šœ@IDATxlÝi–$H‘¬Q Š2Ö~Y ÅÐÐ×ìó²“ÝúCU3÷ˆL’~çýòoûÛ/~ñ‹ÿûß¿üå/õ«_ý÷¿ÿ Èân ûÛßþç?ÿ¡Dþë_ÿ¢üöí #W¥™ P ãùýú׿†€ÞŽ•è3O°öÕB/`› í€ñcÒ;þóŸÿT5ÔþFàa ë‡‘-Ù¥à6”[&¡¼=³ª½ªA–³ ×î¨*e¼•œ½3CG vǦ[Ï]ê(•8÷Ñ$+× zí€,j\©ªcL ÇQr‘cëØó†ó›ßðD:®ãhÛ®ßÝ15"U¶HG&í|ŠöDÚ¤v-HíKn¦®íƒG: CU3LÆ àœLßµ$+³êeâ¶­—Ø Ù¬ø4Z ɇ@»Ø2¥]‡F‹ªè„5ÎM2ÛÚe-¢M05–ñ|ǘƸŽFk\¯£ð†Ì‰ öņɸ\ùÝËLUŒh±)·e_•>q³’åv‡Ÿ_3•ââMé÷@G‚–y•ðLº7 _;€ª®6!n1 Àé½@@æÇª ‚1¬jg…Ùw¯‘O 2zÑbÓ«Râ™´•eÆ´ ¾é³Â|ûãÿè¬mÏ Ó!sÇÓ±® ØfÉ0gÕžIà˜Y©*ÏüÉ”Î*÷¥ZS¨æ@ šH9PÕ›b² Ì–ŒÔ×Û,¤vᨔƑ>C¤cád=.þ¢$&Î37< ³]—# ÆO*YF Ó/ܾ¯™È‚€L£4x¸Üí"Ç;RVŒh"’X{2Œ³L‚àX #¬±}´÷Åv$›IÓ3™’¿¡Ú1ùD7jÏõZž`z-YE:Ò ÇJ['¾ zžª‘øÆ då˜[UbVJ$·rƒâ3!x9U⪠Av›ŽÀ' Ìgšv#&CîhDÎÈ>Š×TÛ'òé>ˆÆél ¥Z…jA“›jËÛ9Þ8ʺ(ë%&€e‚ßýîwÝ“ÏÌ1JÞb5¦Oœ±£’‹`±Fd{šØ7¢6b-@KR¾u4ð·üÑ9Ó¹ÔÖ5<„**Ðô›—¬ûàÍ»h#ÏŒ{gYvünKíª"=@ÙÜœ [©ö>§w®v½ÄVm«~_ÔÞ\]›Ò jɰc¯S»Ò¶m+ÇÏ–tÈGªx«dYà›Sn«J–ÙurÀ×ë˜mÀ”ˆóÙÂÀ]á¼äJ˜r#U/vUŸ¢Ýj—› àE‹½ë!÷Ñ)%–gûî€í<Ã>ÐŽªíßz² ­!Â2LÌ6Òuúr:j¯JÎÙ Z€7JÌ [[ƈM‡­˜mkØÙ‘¡K9FÆwĈvÀltUG‘?+$æp1Ù®há ´- qŒÜ±Ì¹ÅrÓˆï^µÈk§$ÀÈ‚UU‚ Ūm¨”U;ãµÇßëL–9 ‹`€Žp›'öQjǤAê…¼^áÑ´#³-ïØ•™®À|$g’[ÕYiž³Æ[<ï©Z‰Rä‰ ”×H@/ÆPŽ$ŽÂ}÷²ÝÄÞ_{b7ýüûéA_ÿêm˜2]áØGåè³ôÓTÍ%=œÌBª•èôȺ²R4&*!}„þTG¶¨Òw¸çᘠ2˜FÀÝY—’c\]2™¬¥œC<}ë9Âß‘O&ùcà€µ”c'«# ¸ÉLz$L#¼™¿õoÿFh¡T%s„;7Ú1Ƴ\ËÏÏ¡Fžà©äÙým%ãÈï¨Ò±qDáËiùvkÊFäs¶ª ˆ›‚¬òG*A†tÜ"e&ñtÁª‘°H Ë&ƯÄОH&²£L k\¶†M%@¨ŠJUsЋ§iº«á1"[>@+‘Õå˜Æ± ©7çeJ{ŠL¯T;M¼«!ùà ›eD‹u¬ËJÓz½éôlU•oV:{ÜßZx2¤µy¢ƒ:Ö/Ïmձʭö™;ŠÚÍÅ Œ¬“gw‡û^©*å Ð3obÙz4{FOÓût”90lJCåz«ÖEP#€?ßìÔeŸ(/¡B´à×ô4u‘‚©ÈM#FÉQ ´#¦j2Ù醹ebP<½T+  KôqVÕ¢kÏGc>Lˆå€ªc;×âH)r2¤€s”0eÇ1À”6ý®IÌÓVW~ ¥Öë^Fø‚Ìíôjl+Êz]pW#î¹€ÖèúéõÚG¯0‚§Ýhü&¥GÒȰêzÛ _ ‰Ñ”Û æ +eUSŒîÕ–iî&ê-ÑÕ`-¹©"¹9ÂñßÉ+9â1½<óYP’õ˜ÉV¥ï.-ði{¾6š t¯+Á­¤Š Û\©¨Å&@ãòTÅÐ;Î9q‚ªí†ÙP¼^L¤ ‘x†pÇrŒ•FÒ¿»£ËX² ÛŠfLûcŽõ XhÃFÐ ½³#lbŸ™#²vo^Ë=×.R{0Y³Ê]¤…×¢ÄG$îÈaƒ`¥º‘8ž~ƒ%<@/ˆßì8ÿi,ÓSLÌ$L¦ÆDN©”!°†*Û45*‰¬ðÈ#e é¡È2ìFßþô§?Q8(Pˆ¾tññ\T ¦øBµÆXѱ-ëUÒÂP´Ÿ-¢#Ð52¼MŸ¿—ñwTÕ%'¨±eÚ#ªnÈöÿ1R5pd"š¸Ñ<1€ v ÀîâK¯7˜”¢oIJY YÉ;†»Úð Ú¤•rPu„YÕhy$,”jïmkÁ22p¤ÏƒÇ7%«öÌmŒ– ʹ£/‡¶ê—B/V;ì)(󼓇.T'SåàÈ¿eˆ}-S)OÊÄHšÌsp¬Ú‡• ™`#²ŠÏ­ÝšÛnx½ýy+åð*ù Ç×Þ2²£èHóò³µLwHi¢¨Å^ž@&Ã^)¬,ý™w÷TáFà˜­–x$¥F™!2ed¦_[U•êr„wlú¬ðÀô 0W4ˆ‰¨ +]î³Rþe›Tê˜î:€ª‰Ü$œV-” ŠßÚíYÖŸ¾O£+güô“ÁýÒ hOS( ØƨΤ)=/¥cžÍ˜+k)'è³ 9¿§ÌÎ1]Í{йo™@ÖÓàëåÞ*­Õº}r –k禯’=^´+£“åß8Ìû%&vS­D\/Cân.;â@iP¶4H&ú~7W)Ô’[†”9´°^&0~ƒôŠôJíIk¨:Š+ü`2U†øž³ äŸÛmý|Ÿðïõ•´ )áVª7ÏøZ(iTLß ÔNY‹j%GXìêÍßò€Hæ0!ւ瓃L#”ì¹ãn7+]ýk!&Y%ÎJB ŸÍ¢ÁÈéßQŸ¿¾`½¹”@Ÿ#M ÏLLÁJ”ôJŽHÏø74úùh¡i‡®¯êHÏ$Ã|ÒÈœÏMî ÷{s¥Õ¶Âóq¬Q&˜>)U ^Ë»¾AJâ¶~þlXÕPX•X»ã½â¶žŸ¸4d†f•'}ƒº;’@8&›˜Ò¿ãÕÕׯҔî’[&]m;˜â}8ÓD6WÆû×¢½R ÅÌ¢Ág.‹m¸)-€Xï@]¬úŸ£ðÙÎʈ0Ð;øæDRjgkUÙ·ý,q_Œ›å5ž©_QÂä#kטUY5M²ãõõ¥5šø¼ˆ6¡f]ë7¦‘­¥Š‡+ù„êÅpWº‹}þü¤É O&›… u1™9Q—vÁð=2i=V)iL dˆ$6.Ÿôu%F J- kiC2]<#O ¹²­db¡*Tiñ­ÁDɱ×@I™!,6"&O¯„^6ÂDǪݷ¹Züxà훡„¬H&2Œç“§c?¢È÷^ êF§ÿë»#ƒÏŒLÌñ‚C·Y#šÛDOéH¬xG%—UͰ7qäF@¶û`R&.cð0«‚mÎÞ³öª°Yà c”ÑÈPuÿ0¥š-RUÆ´†v]ªýÀYA†ï;S‹#L-¦–¦`z YÕŽiÌÊÖQ(q–íæ–µç3­ñmB º”–m žªùw„×H›>? 5EI‘9\#^³ضU«j‡ék1«ÑHACÓªñ0}b)“ŹÒYô®×Ú‘ýkdzSÞß1+@ Èyï‰Wm ‰Y#CX´ €¡LS ¦)4×'èx.S3ë@"Žš©r;9ôj~øãKh¬—R4C&U‡Y1ñ€ —„ÛÇ58*éd 1íÀǪ~¨v]"Y ,O U 7¶Ú1²Ç»æz“ÉÅ+Öâh1&z[,^æ_4…À1Õ”2^t4ºF@Ð;n laá½aGY£Ç±XãâiŒPr ¨&pC& ZÉnðHíªŽ Ò˜!@É_õØÝc>6‰äS»’~“:Šxù;P»ì:9Ëû£¨ýuI£) ž?g½}4‘ [@Iý^æÐqš~øCŸU¼ÜÑ&ní€ {|]‚سªÂ©‹²€¤´+´ = ž‰RžÓ'Ž_©·uzûv™ž‰¡ñ!6s·;? ±q€ë`ò‡7H©õ˜ûz4BF֏ɸhW­dCw¬%Aû¿£¹-²Ý&%+ÁÊE˜s»TG½ÄdÜzxUx ^ÎPµ}0-PÆk©KÎÁtþ.å(¿ƒè‹ÈáŬ€°¹ª›Ûe=à ÏhCm¯¿#²ÀççD9‘\'uX‰©—‚¹gŠÇ U8´ÙÞ%+9@\/ñRíS'˜ƒjbdÓ•<%,×kÙ±­4Ö…Ž2F„m(Ìb’ùðúÌ"«6Q»Ðå°`º|†ÝW†u)qP’µ¤d8RâÉШšX¯AÝCÙCþšOý¤I6*̇¾¹Àöo4A&ãjâ »5^˜¥EôEoç¬û+GÊä<2ŸÖ««*OG<ãÏfÀtdÞ—f~®}¿2OÎ0ܽ<žÕo8&s¢äŒ!CÎ?ÿ|ˆU+-ŽyÔ,&oUÁ“Æ‘FcŸZãð¹Í„LÉ‘[×☠´0P•Ý϶‰òÌñû œG¡ª(kÌ háãûõßKÈú3¨JÜ,†ñ§c£µäÜJ<@¬šxJV­ ˆFḩR{FŽ»zL¡ËV2[¼lk¡.8ÍÞPIœUî;¶?O dåÈÖ±Ä(µC½r»9t”{¥œëí¹`dVæblÞJ²¨7ó ϯÑ9ùʬmÙÑ€6 ßf8ö:J˜‚§cN‰ïH¯ÔPžU½,€ÇÀªÍµ½ÆºäJõĦÓÔYÕ³ÜÎŽ431#¶‘‰ rp×É?YU¨ `þ@ú Mq}Ùï‚€Rš|ÁF8¶¿¼ç"Ægˆ7TK¹^$[¿Îö+Cs7¢jVÍÒKlÃ&úBûž¸šÞ†òT*4Z4dÄH€8ÆÄ)á U™'†‘J|€L<ûóÀ¯0$dæÄ°l `˜¨jIœ9 ¨*s“Û3>3h0BcW ÕÃç‰ÙÎÛ„Fx^Ù‡Ò&)[»lŸ€Fbaœ£ÆöéÅ]ŠyËÈ”ý&RЬ¥åÙ‡G‘³¡¬é7î ¾±vbœý|> šÕ½ð4}©àö$ãàȶª#}sÛy•’ÕE#æ KuûàU½˜lDÙÜ45–{CXµ×fÕÅ•êÍOŒ‡¹)5 Ù?*8šë¾Õœeúvާq$Ȫ’ÌSД‚2£ ØP¶¶c·±Ìíü¶õõÄÚ,iדÙ)§õÎîÚx½JÛ@µÛ`cðZR¬L‘1Ë\—j÷·•*Mžx¸8{|]£5ˆ…ªcG-É`À½ªžæ¯ÿ1@êíA´á­‘ƒR^§ÏçѸº¸ ÷"Èí©Zo›¨ö»8…ñ¹Oñ˜ÞÐå?íhLàM4#?i5ö)`ÞO¼’^$OGíõÂùàúé'¼­àp”9d[{WkŸ÷:p?ö½°n2åp2QÉq;8¶­*íHo%œUueµ‰]­ÍU;$îFŽm·yJ%J È{.þ4­!ãÛan«ÖŽï/àü3¯Ö“F¼Ca$10= ¸u½²#ÃZdLÕ”Ýh{¶a¯M)ÈÒ(y ¿ŽUE_€Ö hJímÒãÄÇèj¨\t;]C`"ÌÖ,G ˆ? }}ÍêUÍ Ô 86Ž óÓùÕ“˜Àz3eí¦"O©% ¥=ã|h’Uê5ø´› +¬…•oBú®?Mn²®;ö|7ðy¦ì˜à,}jûëÊsþÏ@•ûלÂÑÓÀåj*˜©ª Ó¤ºâ])CU½HÓUƒ¬”ìì~K‹ а½ò“kÏ £E;€WÍ_ËøÐÔ˜,[âcz¿:òœ]ßUw;U%4ȺëâÓhGw´@©WnÄžÀ´ŒªÏ/«dzEŸ‹j% óŽ}0Že†Hs}â}ˆa>uñiÉÖ¸+>$+ hô[ ‹ä$ÎDÄ$ãÌÎ$gËPòlÐx µSÊí¢Jª¦wT’É0ÉêMÆHSo-M”U5Z©›¾»QŠmÂD4¥’Ü”ŽˆE»Ã9ôp@isë•[ ed$¥ÜQ/œÿ̳jô>¦æ&~õm[U [íòl•𨇵%;&Þ÷°ö¶Ê¤eÑÕ10Ö”Ùª¦·P ¦Mµ`Z[.èø/îóñ92l<%Ÿ!,¶¼¹@¡ªW8^ùçgÐcîï7ÞÊ·1M²y"›ÔîHÓ‘L`ÄÞa-ñ²Æ>n¥Z€í3=†Œ#¾ýáÐ eÁ Úcu=qz¾þû`.ñZÖ•Y¥ô}1kdÏ6¾kpkÑlËó¬¥Aº^ŸVµswi¢Ü‘CÖ^Ö¥ÔJ±[DÔ’Çöiíñ)UÅv«ŠálGèÇæH¯Ø1Ï~×ÛÒu6…?L¿ ûçõx¥ª=¸ÆÂ¬ø[ÿüµT‰‰‰ ¢™Œ›U›²×@6TÖK¬$Läyý>ß®.ØD;ÔÛJÄ€ ·ºfž-A¶ød …1´ë¥Á÷ǬTV¢„Ó´ÀªdU9¦ÅdGŸH³ÖEoVâJ-9Ð24JùØ!1^ªdô.³ÍdØJÛ0F~ƒ¸‰@nA<ÀÎÐ2Âܪý’j<9¬r½HGß4QIÎg™!·Ä2}]&få˜@¶6 >#°üÉ I ³Ê0ì0‰ÏîX~«ÃmÒt]ù; þªÃŽ2 ÐW®Õühql™î˜ÉJÙ®J 6ˆ`þ­Á)‹^ûµª[ä@½2Ãx˜ÉY¿‚„ÆrwŒ¡ P:Òû½´·£*SŽ ¦‰Y%FUTÒ.bÈ‚•h0ÿZé;VÒä äCcó°U˜Ä‘¾‰ `n¾[]ÏʇŠ×Òk¡$ ö{·Ë?™*R;=™q[‰ ÿJíßh|¶õjäÉÄ8Ga1Î÷6Ÿ_ ée>d޲Ÿœ°ŒìÈŸŒ¸K±j¥ªJ¯UžUµ‹4˜n§}•X&#è.µ¼>ôí³LIŸ³ér·€U[²Þ-L ´8ÆsËŸ³R¤j¶>RîÖ“À§½Tç©¥À àÕ; †ƒµ4ˆþuC 2áv+BcS´g¢=g AG™I#z7XèÍÆ“í»‡©%[ÊIJ/že4Ælœ–—äÖçůŠ);fŽa"'Ëü圕`@éûYsäIÜt%WÔž‹%òìq#±I)Tú¼2©QvìMˆ]#è9 |Ï8úÃ;gG2™²‰1×hÊÌ;šb™3æòé5ªÆhG} ôÐbް¨KNlzÃ$’¬=Õ4°Ñsë¡”2b>Â_Τ¬Ô¸ ÂtßœU‹lU·C#jìbÈ]Žbþpâªd˜Ä…åB»8ÿ#°Ú±|þ ‰Ù¯¶]˜uëêã/9C¹^Õ>3¿J0rJ8Cn‘I]€ä~жq€X)LÏ_¯}µÌ™†À8šôÚ›…w„ªê9LŸ‰£˜ 7TÎ$ËÙˆŽr¶v¦§lɲp ÕLµ¸uÊÁ™Ä‡Ë-Дr-°®6”{.æuaT{ð^@n“­‘¥€é¤·’È0^N™‰\µŽ™Ø°’Ü-4¦"e¸c9g_G>5’‰V’ë)à€ªÆZ" ®W51OâÖSª ÈV ¦–î•Fî›o7¸q”‰¹±õPÍE XÖ%h´tÍù]Fu½øöÑ~&ÝÅä¦tMâÚ7%Ya¼,^-x V"(æÜt )°…k!NDòì«î7C¯‘@Þ5×µµ¹e(¿úuÝúIüÅ–4â;½#Ò,A¦¥œUY)ÃCün7%Po&ŽÇ÷¶;LäÓçë˜2ÐÎï}ñïnª˜ø”C6‹a#S|…Úd#Î?€8==Í.@ZUI8¾2˜u¼a‚@\íGÜÅü÷_¤_7>æ>ã3ï¹?o´Ã¬Sâýåë£þ?Ÿ“^-Öh󔌻}þË,†C²­G€?ß§!¨„4cg|¨6‹Æ¸ÁZHGØ‹wÁ óÔ(RÝ"qf)!e¤ŒX‰lùädMoO¤c]@GbQ£ÌjÙ§¤A¶U²¦+å\c¶½ Ù¶%£mè7†m&gƒ'xj1:޲vb¡·pÌ-¦j;w%£Éj©D tAX˜‚ÑN6³.`£3!˜ç`Dtl\½åœ•t™`€uåŸX•U9†Œ¾}0Ž!ƒ{RX4Ë ]J…–ø)4ð”µÏ ´ F0ô…òüÔ¾Èkðù\–Ñ%ZXKFžôÝM‹#^æÐëÁF«ò¡ìFŽgƒû%‰ï8[²4².&™×‚ÌÖ’ýqÔÒ&•(ÉìPcÙ,Ë7+–ŽºÜŽ^W·sz¹GØ»M¼£5ÖÒ«j ï8ÇlíF¦dÛÚVÒ5gø³"ŠH³œ?çýÊîªu–™Òô“Ð$²|Ù‰µ´JÐg[µ…Šõâ… /ØPLä•|>r˜€£ç†²–Ü-#meFÆcD÷ÂG<@/'6“Ff‚Zp7=û‡_@ß-´dµF|÷U"s#%L-ªÝ¯1“Š#hg¯éH˜g-dù÷×Gz™&·L0E|žMLò,SB•F4—OG%L¶p‚e|_Α6!kFáç“yŸªÂÝ” © ¨4`DU<zYŒŒqÜÎ02Êø êõµ^„)«b´×h+U‘ é.ªÓ˜Ä].Ú¡œ>+¹‹7®% z^OWbV™èÚ>Uk™mSè1{½0f½]3e‚öÇ×"ä9†IßðÜð™oA]xÎ"ã™'ÀJhWíŽJðœß4Ë)‰Ú$L¬DVÎIÐ7ì´}½j³ÓSf¸¡’e.g~=Îô˜ôJ9s‹ß&•ÖX†³RUG •¶ ÙÄpƒ0~™|þ4ˆ•×í|>EŽ™6`[–>!Çõò­Ý±¤GïoÜ0zUËÉ–mO`ôpwÈ æ£t7:ŸF—ßeµ(Y¦^<™£¡0Rh©‹ž§à@6 ¤I– Œáã=nƒò,·ÌÚí÷Är ÀiddX hsÑ8‚5w-u!û#æ`™™8æP»ÛåÀX8*ˬð­äÈJø@%¶<)åæÚ6[>¢FLx3p´¡‘> ÃÍQpƈîxãçÿ m¢zmNÙB;¬ P­Ú½´ÔHƒ@™A¾½ñ)™É`íZàH9Ü2JÂ\¤h “œe¼wà–!½.šÛtœc¶*i˜|*Å»ˆÈSVr”¹s€‹LìÛ‹lg>py»9úÙñ2&ÍÕˆwLüñ½>}ÕúKêD½-Ó†ñÚ­ÊÊJ†º»A2AkΡ…5rCZFÊ˵l[ }-­—y-ªZddî¨+2ÃÞ¹%e2üŽ@-¯lûÌ-ý3¹óÏÜd4n+˜~×Ç Làíš­?•¯ÉϺգl@9Ç>¤>•Þ‚8#•Rß¹&ÁªøÀ~ïsÓB#àZr‹ »RÎ4|Þqã‘™”sÞg¯‹‰o¤h”ì£+OYpÃ4»Ò7ØÎÄ¢‰dýL¦ÇˆLÚÒL‰ç®¤ zÙ‘†9œ¡#²o[Q&îW*™c>Ä–ÇÇëVI57dÕô šFÕVŽ4¬ C ?V#5†e˜ÛJ0†ƒFÎAh!P€ÈD nDšœã—•öyI¬EId¨ ã ÍŸçø–ÄŸ¶ ª7¹ÍÕµ'[ –³ÒØ[%“1{[ q+©k¤Á Œì(êâg2 fWf"”äcôõß&À Ó°íxµ'ÕÞPÙbýè5Nny@kוßÂ=K2ßz¤oìî^ 2çÞ TbÛ1-¼¡€ £é§€r]ÄÝq‹)!e]” •0"fǵ(e wå—Ìv-™ì:kï"ô‰—U»]þŽAëíëRr,˜²à`aé1Ú12²R]ñôŽxJy×qħÁ‡kT*Ã@˜¦kbDÕx áZòׂ„¼só½½ôI4ªôÌ{  «ªÐtL–!YïÙ>a™^ì¸/¤)ø&îv½ÿ·¿þõ¯sÑiŒ ÊÐ&‹~•÷˜FNFc->Ž21 î>石)«*µJÛ Ó+mÐg€,(†s˜9AäþIÖöÛŸæ}kÇÊMö(½ ”­Už¸*“Ìødu¥ÇôÉe’@ ËnÄY¿qÉXÁë"Ð(jÄ÷ hh@µ® aÕÞÊ©TW{héeJã”Ö…¬—2çô²ØDX#A$q³(U7šLI ESrX#M· C’H‘†'¬1’À§7N‹zª¹Ñ)×ÂÙ>ªÊ|ÂúZ(…’®¶’,Z²+¤ŒÑKœƒ™¾Pµ3ÆQUo`sUálS:æ3LÐ~z%þ9OŒŒÇäÙ,sñíз·f™¼+÷¯%s³FKV jI|nùœÎ«¤ÁDj쑬4²Æ>tG%‘•¼Ã%>7Â8ò©‘É 9àÓäLt‰ö)ûí—²··2À±YŽ»;«vHI£„¡‘µÓÏd½ÑV2+úZàÏï¸ÎIÍðjÔ¢R¿ý{™ÒøcsƒÌqc`Lnþ6ÍÊê„‘U‘µJ<=+Y¤'ëEðºŠwVŸÁ˜¶Í“Ö˜¹Œ—m¥Ô>Ì÷ ¥!htÿ=€a•ƒcA‰ÑÛMSF(Á€§»ëœkúgý%<›neÇÓ·< 0æ»/}4èË]‹ŒÑ˜g2Ln2ÒÂHGJYÕªvsƒU[8s¹^YÔ›ùÓPúMGHÎþ¨î k¤ÌŽZð˜ýuéeô*uï’]Ÿ¸Œ´aá£|òDÎyŒ*ÞLÃÄ0Ʀqì+áXcVUµ×Å!,ç6Œ O4W.ÜÑõï]Ï'Ò”w%¤cŒv‚MW k·pÕ Ð{Ïf%fÕn×õãœÀA£ lP<ŒœÆ÷+5ƒOÙ 9«r†½3&7¤Ð› ÏJ2IÖû¹¹É4šÒ3äŸ ¾h±eÇôª•dƒZ#¦c‘Ä1}+LÇô]mÇFë ñ€ÞAJ>ëަs&˜IúvVjÃ7âü¡§a“ôXîuWŠÉ=SXÞ1ÎDð=h†Í²ÅôpW{ÄÞoœ–ñÉѪÈr2¸gŠ$Û¬”d]8ež{Yb?3•¸ <+² ËH‹u™€Åû…ÔK/ãÉ2„r›7‚‰Ø'…´Y‘•Æ‚2Þq%LË´¼&X©*FTµ@]ýì„#iLñùöç“RÕ&ªZ5¦e í:H˜á0—ïLJÓ#µSfBÙò€¹‘l…#’î+DÌMÜúçÃ"Ãs~/’òåa±ë kŒD;`FšebÇ®ýª>_ %Æ}+à]œËHÊvîÓw¬äŽ“åߘôª}p™ô•FIKŸÂ†’ü“aLǘÞhY‹’ˆqɾ<ÎÆ kñ«¦é “™¢”ËÄ;’¹‚¬÷ü¥©cœÃVÇ÷"  ÞÈÜñ2zŽZÎÖÏ¢4"’¸ @Z±R£×ncWê‰M§¿fŸ8¥œAÓVÈMð]8 q&p·ÃÄódÓó¡41A¶éU+½Ñ[{â4{ÌÉ”†Ç<×…dÞ·¤µíæ}Þ‰[ Aó4N0ܧÞ,zd³d¶áôœd£azûÄDÊ-£OV ÈXUêî9ó0J²›Êï°önwqÎü™8Â@Ëh±›ÜÎ@#G3OÓUß^UѶªMü¢Ù’Y饇¹ ¸}0®6±4Ž"‡Lb`úJí@S°d¥ºdb—»o¥zGf»v OÜVóÔ¢·v²ð›»,Yn•ìÖC© GÙPæ%}®o;§Á>ôb@oíñ•(þ²ö×àŒy–[£*¥#óÍ}}苪Y­$³"ÈP)L€qÔu¾>Áôªñ@湑٧GSrT•YVrL£ÔV²jJYøZb˜Èm3ïç¨.2nç äÜUQŽa¤GÚ6£jûÑ«öç¼]a‘!€iRâ¬òa¢—`â~ß!r`ã˜Ð;r~§geU-JMÉ$Ð÷Œ¦vJ|ƒ´xÍMl%2LW°Xže£3!`èX¯'JàðÌ•,@™Xnt ›Ò¬€ÞÚm‚Ú)Y1Ü,Gä¾pz‚¦0©#´w»”­'ƒ;VBúLåÐŽg¸?X9âÀ½h–,ð˜2m[[ûÕž•ð-–'±MÚ³RíU=#[½5RÒ4 Ä71 ”FÕh7Å3—›B¼ë7(>r&J-C¯]pù¨êrl´*€ÂQ¤X U €Ù‡ëˆäÀ³˜ÆJ”¹!‹ÜdÇzaÊÞ¹éÒw¶ êͳéÖË\‰†! n¥h:  w$ƒïë¤QW p+ù^¥Ç·øùš¥Ìéû&(Åä HÁvú4Èd]-qέŠ1-€ÇÔ¸vOÏîW±‰¢äÜ sËÓ/%<’!ÜdDÏ¿jC»Ûx$ÍZ ãŒ×¸µ¼AŸÏ•Ž(µL­_†IS;(›MÓàf\á¹Ð0àõ!fB¼AÈ4~Y(%î& +!ÃùÇ–^ÓÇ芩=·`µ§ìF¾¦YU"Úynóv„*±€‰ùŒ±'²/·ÿ)ÕD>=^ -õb„#M½åJ°x×vÔ‹™ C½­!ûˆ‰Yi‰Uû“IµeôÎÒQ—Äs@È3ãëO;z8sÀ±ÄŽðæ:š"6b]ŠX 0N@ïI X©éûÚÄ«êÊmGdØ'Þ“6…‰wP¢ïa}|]Ä #UÔ^CzY °«Í§H£%=ϰ͵leïƒL@oíŽ}"4JJ¶Ž@ ¤£F‘˜~²p%†.ë"d%G¾Îë>ŸUῼržßž À¨^íí"½CÏR©+ôªÚ3Ï“ è{ÕHÉÙ‘C&2R®KžØõSÊuÉÄ)µàûÜ‘ÖhçöWá-@ +2L»Å무F7mϦ½U×l²Àè%¶˜R#0ª|äÈ®IŒL~µÑõ¿¾ÂÔý,Lµå«§adJU’+ÁdLÆA^KJnxzâÚ%W2]5Y]3Te¥Z %“^²ßh£‘3Ñîh–Ù&‰ß)”ŽÂSì ¬êÂŽÖhD¼}øÇÃÀ˜~ÑÔȶͻxþ²czû‚mbxUJ·ÎM¢¡Ý5rèý9“Õ‚Êôµ8&«ä(”œ.NÀSx.Œ}&Sê:H¥ÞÀŸÞ{ññ>ZrCbÊd‚³q¦«:ú3À8÷üúíœ,+ž#Âx-e$ç[üùgžŒ¹Wjû7´È0€Ñ2ÞQtGU7ˈªåJ0@Ö1óô0s¼ìˆô\ôüåÈnT L&ø×Hæç"Û†¦Læ²J³"€E»•;6ÎD»j¶0ÏõæO?s²4€`âî‡H }ª¯‰QÕâƒp4(}&ŽéSWom‚Žrƒ,OÖ2+!«}ôHÁÙ¶ù¯±£^Œj_žÚ#e|þûa©×d½2bYV¶Úd;×â(2—™8–oå”DO‡é ü‘ðÁ(/™ŽHÐÉ]xâ&ÙLËòõK?“rnº¬=^æ`%Ý¢k‡ªkjæ–{&ükÛ1禘ۈZˆ7— 7‚-¯:gUú2q›7B.Tñdspt‘î²öz“Á½†^±Æ/ËóŸ”dª–é­‘>Õ÷¯¢¹1!¶¼*¦˜‰ÞJ™^L7TI/%«ôCáF¶ŠÉ°¡)Y)•1F¨ŠvÀ§\ÐO1çZ€”¢•d¤”mt,kÄ4™#,3 ;ê¥ñ’º„Û!ïœ_ùÃFtdžh´$Ö¨ªE8jl+@¨MÄu# ªd¥˜ñª»;ÿ9SÖHYW#à!~$ 7’! 8ÈZœ56ް³ Ôž™£*qvÔWÅ_×Ïß Ö…Tò’ ʶª,ðbKb´8ΰqó€­‡Q•[/“Ä3 $nO³hô¦l.Y_“ÑË}÷Ìê"mNܶxÊ6ñÍIéZcÀPÁÁhpÓËZRõ ?©å7… ÃD¹%k×åøóQªÛ*ݧ›Ô€Á‹ûõ>?˜ý]›cÆ0IJÙ^•­ë%PâÓÓTJŸ lcÁŸØ‘F4`™Û¾+œ¯‡4d¢v†Ú¯ýù˜Ï@›¨æÖ&ló¤„e¿8Ü®K%–÷Œn1Ù±Fèõ,œ­”¡£Ý0)kQêosº`±Æp#`¥d ¤à‰ôÊa€ãض­Ñ\›#³›–B £‹L6½x‘¥‹÷à@ŸZãx’Í&–Û'[z>k=Aï†É°ÆÛVŽ1·)ŽY™²Pªj ‹§ª£ëTÒ·‰O­¡ùSª‘!‹ªpΔ"eÙ‘m¶*«+<Ûš[ÐÔd²Æ•Ú|ÇÀÚc2/Ï$ó>#%úÜšN&Þfµ¡ZhÆê’»ZwLFP/Û–¬Å‘øÎm³ðÅî¢ÔÚ2ÿrÈÇ1C˜²@2qÁ#·Àö ´¤*%¦.Çk%U ²Ñ]„žXôíuÈDìñ5joí°¬/2$Ы¤1ÁF$0EK éؽ΅…²Ì4  7JŠgæ}d«#6™.>ª·ã|;UýY×_¬0Ý`Õ Yí¶¶X<}¿;Z ICPd£$0íÜ2H@»œ@öjö!F²ÒBßSÂŽ€"£±@VLU]µË9ÐÔë^  °A4MÙŽp#h`ŒÈsí@ŒnV2-½øc”ŽÅ—‰*ÇJŽ·x­Rz™lŸM¼®^ÕhÕ–ÌDn(P;ÐßR6±Ü†m’>gŒ¨ú.Fc[ÐÐ#_Ït%n7ä–Ï¡#ÈÃн|Ê®Ð玤—É|)›ã)1ĪzÉz–ôÈ@ä¦ ™hÇ×å¦^¦©¥7Ä#ù´CÓ1Ú•(ÓcÑÄŽÃ7Ž¡OaOŠïk£%%Ï j½ñ½ñµ°åi1ãÞÞd2¾mUéá.ÎÖ&|朒ð¼€Èÿ½²ªÆFÀ‚†ù|xÆhW•MZ %Aü”{. ±‰”ɪ®ö€í¶¡~Kàë¥ln ;ÒËÂJ} ÄÅd ÅOC¯‘ Pʧg›+WÊø½¸cβÐõíÇd­G®\VŽâ>»6¸Ÿ‡Ãt¤$c"êªT{Ë寚Un²@jÄ{e>ô1U•0HLcnUY©Üªs a¸‰€è›aÖëP»ª×Ä ÅvDíxVÈ‚O%$‡‘µ# }=>¿5ÄãýrÉDVšI2$·¦ïÏÔ÷ÊdÂE&ÛXåÜ—¦ 1B‰LÔÆk8P»—ÔÕ{êj\-xÌß·¼& J‚Ù¦ea\%¸RëåϤß ¶¶UY‹(óÑN¦ß±& ÃàÄŽ¢vf« §çVï|ò| uÕòj²õÔÞVæC“¬Þ} ñôø2†>‡öQê¾[Œf/Ù]"O|Xî"+Ø#k¯!\$ƒ[ƒF``ÂQn(€WíR)zËÄÈÄa ÔX¦Çø(ëÍ<7¼Fþ”@‘ “Foh`™~%‚^;ó"ŒïH¼5®ü ð”a‰ÀÓÌdC-‰Ì?<†m£1BË4Ý¢qJø9Ì矸lº ~í¨ibúÓ¯Whª^¾ýjذIJ ¦‘é)ûsž@»RÀ•ÞqæRjÉ&&@ÇÚaAV‰¡•W’óyy }SòÙ?pqÐBœ'LIO,"(Å“ásÙJô”`¤qªn9=÷{“ ,>³˜èjÕí€éˆùnC½VjÏ Ð”µ‚˜,0íÜß\”ºE‚2+üíþ|âõj×’†U4²AÉÊ|ðŽ¢é@þÚJƒ” þã›N@‰|Í‘ 7 H~³’/­ª)­¡ÊÁ±}:’!åz ¢Ôn¤¯VJŒ*z%|¬ªÔzJý:Fæ¼¥/’ÉÈ4ºèŒ*,wüŽ$¸Ú#º,2Yû´³œÿ ªk‚¦DºxÓU)ó„…RKZž#Oï)ü+æÊÏ›h—=e¸×³pÊ= .$Jm-†Çä 7çZ’¸ÝLAR¶Œ£è‚zç™^#¾A‰Û™ °€ˆôàdmÒzY‘E6…Þe>üi`@6T#œhOšÄ4ÜÎåÚ…B¿£mÌ࢓&Ád@›ôÎ ãèK™ ß…ñi§ÄkÁ$&hãÖð^RÌ#­*›ˆahg žgXVBÒ‡›²¡9ôR4m›Ü}(T=—Ƶh¦0=`g£1ôd½+UL-J45*a:ÆÌo7&‘­· "1z‘if[µôâá ‚mNc:,ÛßkÔÕ¥t‰6|j‰/}~¤úé'¸¹€ b²¯“žÒ&诗@( ¼#@¶Mð|nÇgÐE_»ÌM¸`&òµ«’åS©ŒÊ^xƒú}„á©·Yª}XZZC¦t}—Œ3¨Yªô&4|x¬(ñ=† žL#C½ð2L#ŒNÙªøÌ½2Ì„@I61ÍJ×é,–-@¯J†qµ§” Œ®$;–ɬW#‡øÖ Êdª¹mÕý¹¨‹ e+mÕ6o+²¾Àdº`|&ô@³dØÐªmUUKŸNÊ.ÛÄíY#ÿs]ŽM$àæØŽø&b|`nºðidSÚn„,øPÊŸ¿nLÝ~D]©oÛÙªJ î&k¡Q²–ªŽjˆáÄm³ê Uws ø•Á 雡½‡ÈÎÕÜôÂ2 ÐdN/º‘ªMxv¤TêÓŠ\#"–…#þp X¸ÝÆlç6%òls£÷™hÌù£$Ú 뚀`ëøûßÿ^®Œ‘•æ°Uðíœþ¸ß«w Y¨² Úw£J_‰s±2zÕ=/R¦‘íC *ÇËHYWb¸c¹q—û¼?qW8s#£É¡9Òd ˆUkÇPÖÞÚ}Cjlʬ›‚TÕÞÅ•$Û ºvÙ4­Q»’^ß±–©d O ¼OŠ• LúÐ'#µÃ)+á‘ô2¬ÄM&γ$€o=½E]aÕ™`(Ó 1rVa·kâŽß^Ê^;M?t–tTêÖÌÛ-’>ÿxžnAFîŽiÃÄé÷sM¦ÊSèJÐíÞãzö²Õ¬QU»^ï(ÕÒ•chˆ•áJŽâô]IäIƒq‘ÄûÕqøóÿ)<‹–ð^°H§¿=d=•pÖd+ÉŽ­ëêYU^¦É!k)`-¶êhošg÷$`‚$ð W©­‘ª~BêTÃx ÜÅ=D+)ÛSÃd0ÆQÌ$F¤F¼p¤ohǪ2^Kƒ`-p³UÅ„ëͼŒYÿûß;Ê.â‰âÓƒg…wY¤ K)[o8s çx%í²@.(14`bãjÄ7ˆ,׈œÞQ‹hœ§CöÉF6™§[äÏäö}úªd›OÎ2 ©kß(&õ~'KŒlõö5ð¼}ÙâeJÑDÇîâŸlžé[£Ï‚È¡^šéÛ0Ûz×¥%¨QÞÜWÀÌmþ€HÌ„'% \sÎŽpÇw }Ÿ8ÆåÌë…ªp&ʘÒw)¦Íãk4¨O¡GЕùîè(ˆe@#5ÊÛ9É;Êœ5 %½&®äh ì›'L,˜ûê"ÉÚ0}U¬rVUZ#A¶Há˜Oz†¾MT׈騚?FU$¶RG2Ìd­—æüAgžƒ+ÉŒôÈšeí´ÁªõcúøëÚ`%ÑÈ|všJòôhÚ{,Ø’ZZ )´{ tϪ2¥»øG:@Ésv¤obÎŽ½2«øî¥DР÷šª…j¶[ &О2™¼ŒÑeD†-f-ª™OÙ”ÈÆér¬‹·þMfíUûÊ6±5´ Už%Ž©‹y»%– Žýö'ÎAÉeg8[dKRNcÛ™ÔÞ>9¨x“9C¸ª)Ϫõ¦Ñëh¢™Œwìû¦Ë/Â8M`dk;2ô¹«Âºšˆ­"ñ¦T@IDAT:ŸôU'¦|ù¬$à2+Ö®·œs¸µgNŸó²®÷jñéeúÖÀ·›cšxY;¥5`ßGGOíA0^{ òd‚G6 ŽlmíŽëÊ#”Ìò{LÕQh‡«úüï{Å™‰qu•#»×ç+¸›¨µœ‘€1ŒòZ3£šx€ªÞÛôù~LÌ\8Òÿ_ÿm™¦qëͳ¥çÀ§ ®K†};ýàS²ê³Ç `Ž4vÙ/SžÙj$óK YÎ?Ú°WÕå#Iƒo–#\;½c ÿðõc„^švÃ;zûQçF¶5 m eŽpsá×G£R|ä3ûëKïXKbþ"muY(r“iwÍNJÙ1¸õ·|¥ ¥Qb®]ΙJ4h´È?=†ƒFW ®„€Sª’‰ŽøÂ—J V’U;r†1¨+}SŽÑ—Þ¬ÈvŽ¿õóÛ>x¸‹(‰F7®.dšwVÊr+Ñô#àîÚûNj©«-³‰Ž ê.°@öç´§h9¾}:Ê|D›Ð86¢• ÷ñ%Cö%ïö$`b‚HǵӇ«¦G6Wî¦<˜Õ× æÄ‚IÓë L ÓJªLà󇉕(1Çú~j©¶ÃºÚÄÃjéªå¶žo7-ªÍ’•`E†GN_{å¹}þŸeq +d”iÃ` àî8MXîžýO.”d 9øOŸ¬Œazn¢eñÞÅ“ÉLTóWÊÓ±A¾£¬iRn.†&=@Ã0qÇÜ`Ê3õkÿ>*ûè¥W•ûœˆ L-Ä5P:v‘3!0}äaGVJß±ËÆozSd¡„§0F‹à÷&6WûIxŒ‰é±˜1½6 ð=Tþµä¦ªÅ@µR/@`L¤\KÏBá • [†²8WÌ¡ßeŽ4Ä·òIÖ`^KÛàf1<5¬7gŒ£j§Ì.-Õ–©Frx±c¤LÉ(ó±1Þè!=hú-ðºÁ]¶µó!vìµÙòäƒíÙzý%ÃwÀqŸ”)dJf¥½¿ômOXI&nG]¡—²Jp¤jJ<2d½Ž¢Ñ‘ŽFpC²ºÂŸ'îH–ƒö.ÂÙQVõUQ:6ãîMÁG< KÕtËèíãhœ^‘[-ñdñH ,:6Ô8ú€¿§ÎÓÂF{jš¢7áÖ3")‘‚•T‘¢)ÛVéËæ«Ž™Ð#…ñè4L0É\Ä÷ÓÕM²[À€PÍ&ŽArètÌ ÉM騔”a‘9ã1Ú“šLF’µdÙ½0B£L“LÔÂø0+-Ý Ví8Y—%è³?+%­‘­eš®$`á2o½ùDPÂYÉLuY€9Æ"1U•ÈôVêúX‘U9ûhzœÜ`¤^¼^ž¡ªQøe!ë•)åÌ· FØPfR•’€mïy…Ÿw0 I¶»À­Ô½êÕâ(EâÖ#f^)>ÕÛq.¢EÆH2Gså«ÝÚÜTÓlP†²’Ƕa†|rhØ-”ª:`äžC#6QI/[w$ÛzpÁ§YÌc4Zˆk!JZäðåÎ PÂL` ¼êœÙÒ´à¨1g½ Â#kœ3#0Þ vYW†ªø¬È”ĬðUÉÒÛŠ€ÒqÏâ(,I ø”»Ü!)uq€¯ýùJ¤¤ùª^úÚ[#F~ûË_þâ?4ÄŽB›@6X$Æ'ޝ îÜ %J¡êˆßþŽQš8.wÑåz+5îJ>?*ø÷'¶È")­×ÿ2Ü¥-8Ò{VØn­×Qoš-V»ãJïç±ÅšÕ 9ýªF Á•hàB•ÆïI+‘ñP:n\&ÈßÜ\ÌÖÎ!O¹ãü·*>Ÿ1Žô"ž [Dú­aóªx@cCÛ£%²ßÈ|0^ÃôJ²˜ǘ¦·'†[8Û¬0“ ´•‡ -–yúrä ¹p£ô3'S”aWãûcI67L¬Š¬ø-„å¬ÒDj ÞÓ,Xn“øu1qÍ—¤D.zz|ÊÜ`a„cŒ2SRv‘=HdGJǖ̹ÞÚ«´?RaœÒK:âcrH€ìX#+±›ë Û¹^Ù±o#@€¡éHßá>»¦Èu©jÔÞ#8.®K©éÙv;8%ÖHÖS;&n\¹‰óÔ |zŸ6]U¾•ûƒr¬œÂø#Hp±D‘ckm‰H£·p,ü\ém¤üÝ ¹Qê ÿ/[w°%‰m#kx¡•ßTDz^_ÚùÌGþ™Ñti°€ƒ@dfU·dϽ=¬+FÈ”ñidžø>ª&n\ ÌßQI{—Ï$¥Œ$ÀسM¶°*^œmnT´@‹©ä¬Z©[7}í4m›-G $†Ï)tÁói2¡Z/Áv»M‡'@ Ìc6WÕÅ}ÑgµYc¸ÙÐ2òþú¼%™p¦Ñ"v…6WuYY/MËô#çˆÐ 8¶6=œrW¸>ú†e²f%ÃØ¡¡ñyƳí§ÚuüÍ ™Rã4jI±IžY%n[U@¼×G:"w í?|Ò0$ƒ ²V² ÷¿ë‘iTs¸ö²£.AÓÃ6ýt~‘&ÜQÖ^L¹ç‹$c%%œ¯ê“Îà.’¿BCÙ€¤ ”³ê;Ã!%ÁÇgj:¯´FÕqƋϷ¤J¯+™/6“F5:ê"`ˆqÓ±.G%Î@ճ͵ª®J`ܱ¸‘^¶7@&é#×[×9ÂÌ·=F°:<ß(¸ö3^™ˆuà6ž”o2ÊîÖ*Žø^SI¯¨kÀqU]» ÿ¶Ìjz<|Æ?Â$±¬*zw%G/e?@S(ÁÚÛD©¥¹r‘¼GÄ8Žïh Ÿ"ÿ&bRÊ&Ê6¬Ý,GbGíŽÞySúlA™[Xv +QÖÛ½EûÐ$cÂŽ"Cz«öYT…ÈT-ã ýø<¯Á'±u)|Ä’‰®vö¸‚¬Z²Î¬db¤AØ<127üFÀºRrPíùøYÕç¬ Ë"çÖsäðY_!ƒ*Q¶g-›åhD$1ž¸Ua¼A6Âq_’÷vÄÚ[O—£jnŽøÖC²¢ªpáHÐÿúÖt&Ÿ¦7+ÃéõfޱŒF뀣–‰1â׃ŸÎ‰)›ÕÚY‘­}bÓ·hÀ„Ãv¸Åóà¶üþSZ&‘Uk‡”€Ï“¿Z“OãRGöÊi„ÈÇwÏ'‡¾™ë¥aèã ×HC ;"cã)Å”ª4IJ)d)1‚L6ÂhX#=ãl `šÛz>¸ö$ÞÂz3!>Ê,dQ?^p sá ÓØ^†-JÊJ­%Ç4’ÀëÔ˜Æyb2”]Rö|zÇ5b`? Óc(ɶ3sC;·'CdïKßÄô¾ß­-×.ŒH¦%€Áç@¶¡€Pø圑JklÄ2ÞsQNíF;h†7"‡ íñ)íÙ¬–lŸE—âÉmC7WWn»é½Ùç+•3ÏÌ=¬*eSxƯ÷ìíÆ<ÆJÇÜ"›T™kw,ÇËÚ“…ÉbÈðŒ¨ Çc…£ †C ¾®²|nÓ¯OydÿO‘‰¨±ÉDUŸB÷åŸP¥w¼Â8F¦÷-Å sÖøø¬ÝOªõÈJæµÅ5¥kÊô1)gÒ±5cÇË edsã[fØ\½ÍÊóÞE»‹( <1àãvÈ 1yà)R; ’‰L³Žé÷Ó§¬QÖ¨ªÅ×nh½Žý®ãƒ×%˜L†‡1>@ 9ô ‡mÕá3Ôγœ³¬*ÇsS×ø\*F•aJâ.èØèügÔüú/™Ö¯ÆNn˰cýÆ``zïÆa%>°»µ(œ mrÛ8²Ó|­”ÈÒ$Pu´ ’°F`M„‰U›K© î@v5-˜­¨v¯púrŒ{ì·$À§½Í²ƒÑö‰A6Α žaUGÑ&U;v_9†þ©_ɱ nÿ—­Ê|G˜?¾)Íu$h"~„wMƒü.‹‘ùxŠôeHA£‹pôÕo²¡x9 @ *]ϳ%-Ó‘ °xJXu?l˜‚ Cfœèõr˜-¾[̳}¼<†˜UƒrsÔ«¥õ2§õÊ•€ ¥¤ah4Ò½*ýØgæd[£•8®¬eß$s³` μ/Žoù¾í9§É*,Û*}ÎŽ5:î:-€iù.¢Z{WhD·  ´y Cyd%æt ]÷¦ogžÀd<áœ]P½öÿÌ— Te³Z€¶¹¼Æ42>R¦o›ønEÉM‰l@G%·hzUŒ£jþ Z•2¬J–Ïç+bEýýá‹. êó¸ª#ëŸÀ'{MÇnuëŸßþ‘Ìw眧ÊZ"pw@¶7½irþa…d… ÀµxÁSiïâ8ÜËf.'ÖåW¡¬Ša(ÚÇûx19Ÿ¬:áJÚ]Ó«V²Ìõ;JÿpÓ,Y/1  *“ÑÔå˜JŽÜò‡1E+)ù\(¹¤iOJ¶{l ¾FŒË&è)”0wøù@‘ÙâÃÛ“™*F…£èXn7X ¡‘¦Uµ`RàU|ÇôJ˜nÑ_ÍàvÓËabÕ|Æ8ºÃñJEkÀ@ØÄ”­4™*œƒ&n:±Û©Šöˆ ®öƒ)冷ï85ÂxâÈ4Jüåº\Ù±(ñ9kÞŠÙ+Á9³ô}gúø²mœ*%¾¿&f¿eh0ˆ6Ù?+±5W/·ÄŽ}É·ù6Œ|[*™’s¹¿imC²4 ÂüÛ°¥ÖÐÕ4½€–ºò[£# ¦7Ç´3²ºxJ† ŒˆçƒJÍå#`ž­—?­™wX#üù'ÜØÔ>?'ý¨´zYՅڳ؊¥VÄtlžå¬¸R€X 2 €LfP¥Áˆ)•ˆg®Ô£l%ULŸÙmý´sÈ™€ ŒqÙF;òt”{GXT•·»zªJ¶-Ò)ÚÓ’]2$½‡Mo¨ÏÎÖþ™hl %a%@i+!õ Ûp‚Lh€r>µ`ø4Ì#¸™›ƒªèa%˜‰»¸—\IK‘Ü#$v0¢@)'ÄŸù{5ǘz³’é+Ù Ö¸Ræ<•à}Ä)T×›²§ø ?_W㈑N™ œIÝC¶+䀪ÐÛ¶¡L¦é"·ï<¬—¯ÑGZˆ) z¥å˜ aJXèÚ‰2¼ïžÒ+f5[íÝIëíŒ Ó„«¾#`Lä°ìÈJh—1€ “5®jpS¼Œ_¸É”jqÔbF2<\{iš˜ƒêíøõSß1Ù}ù$Ónt—)ýÔ Œ®îÂAÔh÷«›Äs;˜L©µe‚z¹¿º:t·÷|u:²PÚmCcƒJUYëM9MÛÈx¯+†[ã”0ñ4Œ}d7ÁDRv‡d‘dVÁ:]‡¬‹? ÏЈ®Ùn•ì ==@#MÓ&œÓÈ5²ª[¯êˆïMT ÎÉðŽïÏfU¯åù˜Ó…#¬EîÑì™X‰ ‰íFÖ±¬h1¸Fßp½Ï•™$nPç¶¡ªm^&ÐUUŽ"‰E¥íP•LÕª2FÆ´‰é]!MǪSý!Šñ™ÐcÌuGsy:F’ÁdŽ}ÈZY൴0¦MÖHt$`õVÛa©j$CX4«)1p‹ýxÕɲmh»aXù´CJdÁJ;¼{ÅÔò–ÛG&è"M™Ì±wHSFæŸ8‹µŒÜëaØnÞr]»ïº0ªí÷nŽ¢®rkp¦‘«]HàëÑûëBÊx-ôŽÛ¤*^»ÍUÍÄ$k·xíïJÈø~0a]]--»¦Œk.¦íæ(†•òL«2ŸÕµ|~÷)»°I ÅDÜ™ 'ki™Lp¯7 EÔâΫjÁkqU¹_mH€¦ueØMä~€)+QòÄ3‘™`ZÒ&“a`]‰‘¢é@»™Ò¸x¸¹<3Ï_&=´£vGzùÌý‡ªÞ~³Ô(ã9wÔÒ×®Þ²–Üd¯á¨EÉ- ÕØ51í<«ñîFÆGI{ªv†ñhD¸ sÐëØ;Ó0±­#%þØÝ6¹)€,ì¶ß’™çPWWã ïˆñ@%æ@ïÖæ²Y»¹œbäæ&‹Ñ¾))™«vÔu.ð|¦>…îE™˜!±.Y©q[µvš–˜Ãø¤Fí ÂÛ0gGo¨”¬Ñd"}k8¶^ ”[OÉnïb÷Å€¥œ§‰¬èå[üõD€÷cè"@Ǧ4S“p£ibZÙ8k4«¡“éñ•´tG£Ä™&«v˜a½4c`$ÿ6)#Eþr]¬ r5âü3ÁÔÕ,úø¾Ä"·^ƽˆ1‘° Ï¡KÕhUÊŽò~äñ¬ä×ÒñÞà|ý`-Žp{Χ.Y H ³²ð痋ˤ+×@וگ6Ç.϶¢·kÀÚñ°e2 M²ºLIÓWA‰ž8~»:Ò ËT¢Œ|^|ã8«Âºð޲£À‹Äx-ŽþÁûºW%{é(÷ŽºØ: |Gþ€£ÿu9žÀà¡ðºe»µx„Ú;ÊVB’åTr¤TupŒ¼'j:¦ 3¨éJFÉJÚÛŸ›,rÈÜÄþ1™ ^Æ÷—&Ÿoʵ¨Z£mÓ+½ŸN7â ð–!­GÜz» J%kh·O Æ,AŒ'Ã01,÷uÍŒ¡¨Ê6¼_mZbØÂôö!n9'èhbA#ŒÃg%óÁtÔU íFF»WïÉ'%VÚ|½x†)Ç4‘ælðý5GÓˆZ>³ïËäÖ,U¥²Þa ×@Vݸ4¥À8`ÿ 5ø}Ö˜v@Nf–ÆJéá>Žø$sà>ß¾ÂVÄÈÞM6#¾(eCñ0¦·j³Z`2ž½¡–vhw$£÷§#òý ›ž ÉjÔÂP¦'0š ç–×ë¹)™4‚x‡¦´-gôÒ,9Ï _¯öÄLº³ª+7>ªÝÈ ‰áƒÉy9¦{1œ Á4H8Ÿ@WÓÕ˜øMÙ2à •ÛAæÐ¸Èx¤ÞžFÂg8%`í½pÇ<{zåâèÓÇ#¿VFˆî+ kˆ†µÈd B†[›yÛñ†Ò¨:"aY0÷×Ç;ç$/)·¶‰ôªÂ |ãjìµ3LÖö™àYðlg ÃV­ÊPIX&ÆG¶‰0^É,q|ÿû_¿QÏÿå#ÇùÖ@Ç–…#A wÍY‹Ÿ®Ž§á’Ž]ÉO)±Æ>‰îÓˆl9 G¸p¤é ;ZΡ)˜¬dËðx݇£Á7ÃÙQ†û•Âñ˜ö1¨…/Fç‰l.F¤¼‰•|6dyfe´ª–BàY¯öl1[2F;¦¬ª /FêU­”›*F“åI¦*ð}a¼…“Qê•“)á3‰Ç¤ ÈBIfò£„מ @4]•sÌ›­§ÅÓ١阎d¹õ?”‚sY›áa±­rK)7èv[Óª²–&&ƒóL€dÃäÇtbíÖ®”OYK÷’=Eªiw\lž€¡#“‚sÑž_ú<†³.|J#k™çÜ Yi¤L ¯Ý½òI [¯.æyØ+õ‹ó6¦ÇXÕ”ñ”< ²»ÂI˜Jøqñ™1ñÛØ q2Ræ#:ròœžC =AG2¯w†J&î˜ ~Êdí ×Qg‹Ñ2¾cû)‰¦haÒâwÈYv#™XVŸ?¢ØÝ>×;6߯ZFzr‰‡1ºlVi2L<àèãl‰žØ8Gѵ›žÉ˜|ÒäÖ\LJ¶€5¶•£j/ÎǬ½~¶¯mX‰•\4VM€4þ`{ß 4 ˜ç¿£’Íëe¸7!ÛfÒ¸ðŽ–7Qö†µØ[bY8šröø~'za?µÈ­ñjìk‰Ý2úõѽîÏ#œáª^×”-ÓÄÞzdÛ ¦Ù,ಠ-–mzSfB/j”SÆ8Ê|VbÛË+ Vüé;Âe-]„€ƒ¼7!†k'£'¨ ™@Yqß)yæPU‹Èvر ko´.ÑÄzUw‘Z8ôC—§L©  þxm~ý *‰öo ‚‘‚F»ã~­—¾LP®Ä‡RªžN FZ•¸ k‡sp$ˆl®,4Ê4UáÌ1ã}v|ús¨«äH2˜Rf"úX“1ì íƒäßLä2%¬Ê™¡`ÎPæ‰ßˆÓù|aU2O¼æ(®ühràÆ–ÌˆÈ]$€é•2s‚:¤æ¥¬MÔ£¡%Ê&ݦóRuÊôÖ>ÐG`K»m-29™/V¿›Ö¥&}WVªIÿ§í#ðm«=ÜÝ[¯­Ü%0’X/½•tå†Louám¢—¸*ÆQTjtíHVéŽu9¦ô‹Ó Ô%«"-U‘ Hã˜,«ª ©ºQ@K7âû€šB#š °JÖú[ÿüÌÃUã{|¸`b(^™¸é-6 é‘56®ö–¡OÌG5¸%û5—>Awµ¦sÓ[ðñâ 0W%k@ƒJùÀl/w”²à ;êUC =ÌDæ6Öe:†³Üˆ×ªvJ#º8æL½AiúF¼ÐÕÂF7l\Ë`”„.x#ˆ‘{">)(ù)†ãû›8Ϧ4Ž&«Zh,'¦lu+‡T-cTµ3µ8úì¶­rKF»€oßIŽefi}|ù(•åLð=ÚH&ªÖå¸Mˆ•ÒpÈD/@Ö§¶Y‘izmÚ¹½S¶L›8ªê¢ä,æ WýíÏ?ÿì@§|T7r¯¹Ìô[\i™s-Ì äv“i§­!Ës€³âF cäz÷ȦÄkï›às3Âôþ…™pä Ê`Ò)k¡Ù>xšJrû(߯Öq¿Wn«ÖÛ&J&jdgxîJòª Ub’›Þ’ÁEU9Ÿv†ÅHz±¹k¤‰Ïœ¾Äõø|UðñZr˜a÷"ØO}ÌÄó?{ÜM8xj9[$Pnt½H §ë³sœù4˜d|ëèû>ðoIü‹›Ón-ÉäîËŸLnn†ŽíFŽGêrsU…’lP¶õÒ8¶F ã8iPbz¡šG¸öJ}“Ûíü?£×YÏ>[Ú‡£\j¹W8?êÄ2R6@$ŽQµ«pÄOP»œ' êW¿é9Ðç¬WIdñ™#°®ª[`ŒÅúÆ!²h[¼À°Rm ¥ϼÑ1ޑމ1®Ð-¦q‹aíª™Ï™@FvS$·Þ¿U]9 ðã‚ô˜|2l &‘rXîõøüᨚU&µp®$óQbñd4¢.nùxOÀP……Kõΰ¿›;lëjÛ| &2ekÀz‰åJ%&´dk¡¯=}ùÊÒds£,ö&Žbs‰…)r·SJ,Sâç¨bâá¾*¶*“ÀÚÓ¯7Ã2âÚ‡3o¥ÆÉÚk‰wlÊÜRn¨c»yJS± @seØ-poBßi`@íë ËŽR/ÐDzß+YÐô[[©F MTk¬Dé.‘rU%ÇÆ½]ÈF´LÇr½ªŽðÂèĘo~ï`®)xÕ@£;²*tµd£Dœ­*€ ȹ‘€hJq.Œ’9ÞêéÔü×IJ=±—}ÿum{ãÛ@{}nÑ5Òà1’˜¦¡ Ê– Ÿ¬ûƒQ/xs ‰×’?M2ǾŽíp+Ÿo|í)ånÁÊk$k½îÒÛŠm³ª–³ÂoϬØî"ÙràY£j]]D =°›@•¾= ’1ÁÈ"f%€ß-œ8M|CûÀHJV°ÞJŽ?bãÆë¥÷·lÙ[‘!1îÇ?’fU‚¦#a< QÀýœ3⎀cãê­1½9“Á)󴣫á1{ó6Ÿƒ*™Ì™F5Ï…#ÐnpJÀˆHÉ*óæ& 1E»ßîÛŸ‘d4œkq4Žy˜<³úw/­O\/27]³ðÜdâZäÞ‡–ݨédm…Á¯+™®™Ï-cÑqÎÈ®‰l·.HŒ4«=¯ä3TÃ!o–¿mŒ¬ç”÷‰³u—6ÇgÐÂ_©ÞÈÚ›²A@¿-Y‘9   6E xâùô†ªyª*‘¹ukà1 Fv#bUÑ’Û“&6–ßý?ôQ° ¨Æ¨ýRg*7†LÜqŸo[²vŠ—›Úø™§”÷”ÊZ| ¾ñþìi„ì(›n¥.À ðSZ<ç [Ù±õ¨ï§˜¡œè« š@æo72˜¡)@wÑ¥$ã (áZÊmÒ¾®ÓË4”ÈÓtž¢ë(áa¹_°Ý9ÅG2imG%G.Û ÃSzåÖc¼v|ƒzn¤$tµ¿®yf¨š¡‰½IGÿ×<éñØ;88âµÏI/*MÃ<œ¾òÏïôÖÐÕŽ^/2=,ªê„5äÞ¤máž=Í]äóÉòQÅïãÐË3åÌ۪ƪ²¨·Y™ÀøôŒcbû3D;à+9ÆË˜ »”2q hÆÃ”}úÅ~su¯Ä•tí}0Û-28Јœ™X@ÂÚ“×1N ä€'–›RÕ @›˜¥…­ H£™Fi]s@ú üx)s£Ì'dG Ð•[k” RÕþþZ×Èœ@n“˜­Z)ÿÖ€³R d›¦Œ!†=—c zEÕdpüùÿ˜¯r€B³ñ€p ¸ß¡ X‹ºÞ–Hî“Áz›šŽiƒ”ž *ñéØP¸_÷x] Úá>QŸÆÂõæìH”Eäuú¼Nƒª2QÒ^Wæ0~™²ÑíЯ˜µä\;Lì È‘À}“”(µt‘÷:ÄJûÎÙ­ÍÉ´Ô˜ML]•ä½ 0ZDËÄWbÛkÐ0TêwbO¡ezéL¯ËošþkX%Œ F¶ØëkL£n%Œ’v—eÔ^u²Ž×EYU~[xöÙ… ËJå)Û“ln‰c—8Ì_‹ly<çö¹C>ïFÙ;sƒ[,qþñm»‰}(d…®d¾Ÿ2=Æb€–l%4¾iò‘µË+!ᘔY5%ž #ÍJïØíÒ#­— Þ‘&[LúG¯~Sz„=r> …)ã{ z£D&óð°€°M«6Ƹš0"±Ü8@£LF á4MÁŸy÷§,À?A-HVÉÆ7(²Ì¹qŽdçg¬a[‚‹‚cWrÖþ¦æg¸+©¾¡ÊAnÀJ&r¡šgß–‘ñïbÊÜLÇûD«ÊJŽ}N™3©iá¶ô­Á Þ Jw tÁ ›žžÉÁC»HÇ&jDÂUõµ(µF&í¹}ÇÐër¯ybVõ#ÇJ´MŸ¦åeÌn€IzÆ ²…¹JY0™/"É´ôA`μïïÊY²êÿÒØÅ‰ñ«Þ>¿Çñ¸£>FêJ è²~‘§,ZXV çé¸'…‘Ä•ÈÚÍ}»2¥*™…[&%²#‰1b³€Ò8ªe¥§çvL±GÑ‘#w£øµc›UK¸O32ÛN¬kJ˜Õž+ÃbÓ)¹ùæ“'eb‚ôÝè½BzÕ•à¦È€ÑždÌaäWøë»ª”X‰’Œƒìú—Ž ê)è>[ è÷Lx¡ä&ú¦ÈðŽ›¤ÔËéóT¯„‘Ä 0Æe‚OÖÑ× îªÓ#…ã6QHŒÞ¾Ÿ˜®óù¯­Ô®ìó}m0ÆÏCF:ýkG¥ÖÕ/féÑ›72Ïdw ,ˆsèX×x°{ëbB“ Þ¦4Ÿ3²Ÿy½ßÑzŽ=AnræýK§yj1ˆž =YÕrk1L WµªÑVx #™aŽÄh·dd½áÑ ™$~­0”² x×À4YµAÈöÔØb9ã+Ñ‹H-z[ÆH]e8%^hOìO,½µ«ö!zÕd)á>V2XÜŽs)-r`¤£FA©±Ï¨^o´ÒÙæûC«Å2ª½¡*–a-€jzÇöáÀlJŽÍRÓà ¿MÞúù{e¥EÊFä#·R%G-ªdÅ™@µ£hº,ƒlÃdZ4+ P dV$qG@hçFßÎ÷\£c²Ý®öYé¢ÑH/Â2“J…ÆG<̄۶u„ ¦c¶¼jJ½#°ÇlŠœ!ð:lVÓÙ´ö#ß;n“dÓðÛ”42¾U'Æ›%c'ð‘r›ˆLøÃJ™—oýÙh>ç·jçðý‹0Ì¥c¦ýnrÛdªº²†w|JSÉD¿»v‹f«DÖ6Lj¯+AbíFÇÈŽ™Û°ý×ëŽ×¾‡ÈÊ?pÐÞh¸¿&Ðà{Y¼ á#ײWRÊS©}´xJ¸M¶ùVÒkl b¼ÿÓVßW$pÌ#’F4½YG¶ªÄn¢˜AV¹ÉÃUy"åZà^ƒ€ÿ«Y/AðbmgU‹v†pƒºéad³6½^£äyÉÒw}G|½ëŠvn"FKkd² &ˆ¤1ã"ñåÄpÁÍVÅœ-CV ¦tø0?öÑ‹Ù]`$°¡À–ÏJU$ËÁD#‰áޝžFøÊébÞ‰0¾v½9`ÒÀø€‰Ä‰öœ¦£Ü2dý˜È Ç®ÖH-”;ª¶¿ÌYÐÔT%î“Õ«DãÏŒ™Ôˆ袧نUšy:âyâaWÌ¡ÆôvP™ðÇÝ2H›Pv”•܈É·sŒU1°Ðu¾Ð¹8Ã]¯UÌ0•£ª6Ç,0”ÉdªÙõ²Â ÀÉèãkD6Z§|1«¾ z ¢dñzZ£â½£\£?Ej‘»#@l‡®& ¤¬ _Iv¬/“u¯ÓóýŠtACUi¬j &L#6™€öç½È¦ÄXØ×EÃG#ÀMWž•jŸIÝ(7½@+É‘~†Ä6o gU¥Ì‰Ã޶"“xÊE tÔ•>cû86Œ Ua¤À1qD†e½+µjí­Ô -ui¤}"‘Ž|à<=#ÆQ¯[·€@nr$lœF‚>¾È2²9™y+­¤Wô°¾¢x2´‰jŒq˜ÈÚ1ÌU¡cV½ò“6LfdµðÇh)#UkD $“ÙÖªø4HGUŽŽ.få˜ùFìh4Y[5è]&çržé[ߤ0ZFʬ|(G‹é…½¾qH2>‰3¬TW-&½Üe«rPª&†kÿ¶þÏoíñ5fÛ¿…Ž©Ú—¹=1}”@ÎëU¥&£éÓ9Îô:€XO.=¬¤? [T&FÊÄÜr•hÆ_û3¸–yöv¢!È9}™Œm_2¿ý#9ˆZ²^ÑÝ”òœFoÊÖÀÝ>ü•Þé¹Éd‚UÕŽ°RûËHsåL*Éù'#0ÅÇÆêlùýg‹ åþL" {7gâØ¿‚Óe41ÏvP2èúÀ5UGnmÊ—wÌAËL²• 5Å2+JÙG|É2‘žÃL6ˆ¡.|ûS˜Ue¼,”ú¸M‰éR™ÀæÂ€hÂrkd¢ÔæU•&~j§´OKæC߆ÖÀÔIì(ð›®$cêšÆPV·ïóô&ÖÕ¿;òKJ;e&¹ÉÇúûMSvÓ†‘Æ9f‹q,~¼¹«]˳°Rš<ᵫöȦAJ>&GÁŠ#;j—É´„ñ¶z÷Ñ¢„á/×ÛJxúï(‹d²à¯Qîi˜>ÏLÉd2“|ݨ ßZ8Ÿ@í)µkü±!·øFÜ5χåÓÄh̯Wd娋 ÏІÒqb2-•üÆÀ¤G† ²"V}ùŽÍ…?ßB ”,\ÞÒ왑”]SõlŒT kÇÔà†¤%Ј3«¾ ëÅ·ã´ð‘ 2Ìf3Dûk¡WòÑã™§äOÙÏ^¤.%O&Ž­älhGÀ­Ý>e 7-ù¯%O%@µ#`±4SQÐ|þŸ‚à‹’©õÔ†Þ%0îм¸ÚóvÅfä@‰çI ”—!èè…2gÓkÖÒŒ# ­\äàæÙ¦<ËÝõh8ˆ ËŽÚY—¯ÇyqGæŽÉG$“4ß.| íÆEjÌœ ‡HÙ2dé×…‡•2$‘óq}Œ³ªM±9fo¢ÎydÛ*mmÎÂQoþ ª¥A¯FïÛ®Eu³§ä“€Un1”ªdÝ" ¿AÓn‘”x9ì”üհϨ®œñ);*ñ„?Ÿ(ʹ\ͱñ}xJÔï†À½”®Ú·M†/?O-Ä jcÇȆ²5K 3ZÀ]£Ñµ‡9ûÕ>xÀq#ôN¦Ô Œ®ÄøEbGJkÈÛÜøþaé/2zÛP¦TM,ëÍpgD¤‡‹záYÍ Éª¿ûO@Ƴ‹7H©”¬úîÓ= %s]½ª# îa"r&†ó'ëÈY Ruwh |²¦ U…––Ç´ €d«j ÿÄ£Ñ1ë­º)ZȘ6iÕ¬’©rÀ8Ê}+|¥‘MáN^6QÞßÊõ dκz‡|ð‚›ªR‹×?QÁi¦è󰹓áù4w$Ïžšh &“5¶[¶”øa¥ŽcÎw–^‘Þ½yâif÷˜‘u©:¶¦Í}ñM hDbèMÙHÇøÚÔH˜a+UbåÃʪ)r[b䦴@úf)™‚/ÚGãª.˜'M¸ˆaïØ L]4UÇWjã²oÌu=i³Ìµ’ã”k¸ %2]iˆádÇëû½‰©KîÓTáéíKL ^$îƒQ¢i‡n‡qÜ&@¸Mh¬Çª%Œœ%Gì"u92W2šÞÑhÇ>Ę(Õ"7—, W:7¹#¸U妷1ݦ¬Ó4%}VuÕH&´À&—øü ‘Þ8wø¹ ÙÌùÄ#3hž¿àPZ’3^vèu9¬*a´`j —L”ò2ŒÉ–JUìÁñÌÙòW%† 0¥TûVã3Ù&˜dµ—9äÓÚHGJã«'™e02½`˜ *w¬—¾é2$Ü,€?²\uŒ™äPo›û”[U s¤ÀtÔ蘧jËÛ ÙþøWOSï p2›LâÛ‰#[ÀJ4Žd@ûlüz»Z½xš²šµ)»~2ʾá‰L‰„_“9ãECëRªºüòÝâJÎ ʼcVÄÑñÍç7©@Uo¶#£” £Ü‚ G½sóQÙ& ²·~46¨]‰ãõ̶.ãt %ãDn :æF¤§ÑÒ>q‹Áiv¤ñ‘õšnDbX\íçûÝ8#>&LÐ5y¦„ÙôH¡ÚÇAà¨Wö8œáH àSFjײ•0ÿú׿(|SüŠ$ë:xÁA ɾݴ«b  ³=ÓkQ•ñ•ÖKð#RŽtd®# 2ÞVJ‚[†È·Þty1ÌZ`zagíadþáb%2&ý¶åÓGm]ôk'nmÇ~“’aŒµ7+ç°‰ÄÛLKw„·OnxdúpŸ’CKjk̯E82W À…ýé3ĨƄ÷ Î,ß>uµ31F¯áט¡ªÆV‚Å“•ñ€–”°•ÚS†k$HI0aÊnQ¯}€–­—­,ðÄ׿×~7bb.Æ"|"˜0YÿGøÇëjzó³â}p‚ðù^&2 ˆ•yù—@ß9%mŸ²–^¶ûhJÄduåY©í{;]dï]R#%7Ô¨…¾oáÞ´ßãz³BºÊÜD k*…ª–²’ÙÐ8 ÞÞÎ3U€ pT•1É|ú~ç¶Yº”ÖÞ8fUjJŸJŒRƒ(EdÎ[†¦Ñiä¬Z2î[&üZ5®ÎJEúh¨ÒÌíà.>Ù4•» `–L¯—’^´$fÛæìX Ÿ eµ‡sËäš}þLÊMUoÕFãExÕ0>=gà-ïâ0e?Y”HG_Àd¦Dfóe¥”5*õV-`t펽3p–øþ>ÑKÌ„gI/”xâYõJ˜H&øk$pÖ+ˆÙ6º›"!WÕ{¦~ÿèª]‹ÆvÈÓ\¼×ó[¨'jh›0ia­ÊœI†!ûí÷ßÏH­æYkCÊtr;E¦iw +h"s‡í' ¡Y)åºZË1YËt+#2Dv«µ åVÒ;ÿpGXdŽe-rÀ{˜í­½^ËôMUmm-ýKk«}¢JÄzá–ϰ›–•^ØD WÒγѪH¸jÁÐ`T7 ðmè AV;È_Þn\ÁQô9ö§>1¾ÞÌË|€Yi×èø2°éJ®Ù«Òteexž°®‘4²¹Óì˜,·¾4FxgdÕžËÑb@Tz—1)#åvÐkVž1zù$¸N¿ØHÊ¢^i%]-I9œÛl;Ö ·j†p?ƒ-阹£èÖüÖæ°YºÌ¥l–,ðr†”ŽÂQl˜FµöRæxÓ „ÅÀJÃĘ¦à›Žì+„=i/Öh-4J²[zVÒëc*Ñ4ºÞ2åùŸRÐ ¬ØpŸY“šÍ7¯”õ6‰CšH?í­îÓ¢ÄòÌø^`K×(3Ù®‰ýÅmS4"÷:ŽöQEÖXÆœß_OŽ19§ÑhœPʰõZµœ ½€d°vٿ͸Þg“ S:2þY,fK¶³^ûUL˰à&Ïp¬Ë&ªmÕt±ÅôË— ®%«¦ÄcA+åÓƒäŸ`ÎŽá@½=W×4(í0[ÑÄÄ2FFöÚU‘×Û±Þ.h+J/ÚÀg ÈPµXÏÜ‹®€Ñä9²RËðÙGYLÜEú€ˆuÉ¢^€@4eÊøzá]„àôÜß ›¥‘@—Mࢪ\ >¿³rA¥Ârß31”qn@½21r»)Q†&[s‘-L“£Dé·?óYbJ±ÆöÑBI#«îȇRVjºLS^I g÷ª@žÈÜj$ÆÀñ•d³„+àù¤¬ŽIFï(ª3lŠ?RÖØÂdU×h”-“›ë8â-6p¦Þˆ‘û“¯kªËœ“u©n4Þ‡ÎDoG@´`ôp+‘!{çi0}1ÈL4]¯ïW‘¬^9+-HL-;$¾g>b<çLòQòá铬#,h˜¸o]La€^´ª–~éªôzi`ã‰íiT…v<Ír†Ž™héµkoaX¯,’”|⛂ì+—Îd§íà…ÝÈFôëbžfu‘x-W~~âfKf<2ŸJwÂI•2©D騔/gi`%yÎ)ß*ÌÊ\·°¹à6O@lœ#Ïz·Cʆt œw©-¯ÖUËbÏM&ꔓ¡÷޶TBê:êï%Ó·¼§„w$&°:ÀÍJJ~û;z;Ë(ahäœùÀM¯—@¬ÈRZ‰Ñ"wAÈ$1ÌŠIG-ŽHgBËzC<ÆÿæO6T¶˜.Ø$˜X8ö¼º2gE¼¹HÌ®¦$0]‡LÄ ËH³„eq»ÿ'Õ^µ=•÷9;ºEÊšÍÂà‘@Ñ£J†ôÚ•™ã G1Ä."·€<X‰>à"¾þU[Ê®¯ÊÊ]=¦jnùÔÓ+c6 §ÉJ/MáÜ’øº–Ôa]Žtñu5 °'eC YY ÿdÇÄpæª{XXu™3M2<`yÕ‚•F¶•äS]J…c¯ªQðQÅô£­i·Ökçú¬Z©5`]ô&¶0ü–èïÀó€¢e¡—müÚ‘Œ@d’2FÖŤª^S^çt$HT•ÙʬÞ‘[Sà‚ <ÙºØ:VJCÏÙ ðå>?³­áÑú}¨”-ðÏ-³òɹÃd6'ûõ/1Rä['EÑ$äŽô®ä6ûTò•ˆsh˜ä WÅôK°§Ñ¥D™'ì™¬ÚÆJ07SÝQµÅðôŽª˜¢(ñd€¨—a²ü‰ë5”xU ‰zaVyÊŽrâÚÙvG> Å‹;ùü¡í ]dy6—²}(1ÊøU…ön§—·CKbÞ¨åvŸÏ½é™© ÕG»EÊYµ‰c³fÒÇ©:ž!œgV|Èøtl¢#ÐrеêšÏ¬tÁªù8¶ŒÅnñš6¤Ï³j¿ìÈ4"C-ôÇýû5P¢éjz]a·à·€R½é9ìÿX¤)uå°ÑZðŽx_˜ ûR) å~@IDATµCæó¥¬ËÎ4|2ÉáÇ‘¬–)㋪p¶Ë-ïÜícDü2 ªà°è£©ŠL¿wø¸£Ð+ïM”vÓ£ø6 T…ûd<6N•½cS"Û$·ùP*1AxG‘R—Ü<9±Rsí€w̰̙’Õ;7,‹™ßG¦‘!7I çܱ.²È>îÛE0…^n21Æ2úŒðôJøOÃý¼ÿ<¾ßO +u%hÛª°«<éÓ\ËÏ_‚Õˆë†FĹ9*½U¥Ú•Œþü—Àݶžš•ÝÖß8dU¥r3RÊÍ«dŒgެý=¥I>Ê3ìþ¯ÊDÔ%“…[Tnº gBÏÓ&Ž}º@]ÙÒ`ÚJ† m:¼)JöI0IL); -üÅ–Çûöp¸õÓߪï&JŽ€†æ,§d¢QîXÎP{2¯QWUG%]H@à·Œ¯å}Óßß™¬èÑÒpÈPæß1ç­ª£ 4 à¼ÝÞF%Vº^C׋·d2˜O#º +ÕšdHÑ U“5eãTµÈ­§Ú7³ö-–Õµ?R5–yÊ"™ÌSæ)T™héªZ)£Æd€Ÿ5úZ•Ò´‰Ö.Ãs€ ŒP5±Uez†Û2‡leÁœÐÞË“µ†’^_Vý{í ¤Ïìîªz[WûìæØuhðŽ}R Å¨ÂøvE< ¤qŒ_Jée¡”ƒÍÇ–QJ 0oúi¸¼ÆÆ»“n à³Z ÂlÕ°,´&Ü¡¥4íŽdkÛA`zX M;L™ÆQ)ÁuLÚY )7E5þóç*…@¬-ÆfPc4À)e%$ ¬¥·åh'е-íÚßIh܆æé(T¹±•g’@Ì â™ÃÈþ„0Åz˜ô û÷Q‘Ì•ð˜nÇÓW©¼›.2ü^,ÍÕØ&†œR†1”VíÓB¶m| 4Q AJxgµRœõrh¢ÞŽ}ÐŽÉŽé÷W ¥*¾Ñ@Ó™ÐȆÊÍêsÜ[ÓV½!ÜtÏ›y;èªo rþ1HŒLö¶˜’OíílÛH¹v`wÌgǶ"Ë6žÆq&Hw”•y½Ž®ÙP9À_‹ÅÚ¼¬ Oï¨Zv4—›F¸?(;d²¿Wëço0}Ÿ1ºrÞC™ ÷ûQ‰À‘2«Z6=’¦P­ÅÑbªng:ÀDɪ–ï=óĨқ«D†I);*aäª+iÏAIÀ‰ &¯``d}Ë`rëÙPV5:>FÆÈ¢F z$@“g™ /ÓoOoDë9 8±’€ÝH†)íï8=^ôæ^•²»w žf)9ÊpÊ;íöWñøLƒÿíßÿþ·ÿPÀn»†ÖïsàFUÌc¼v®TÆò€ã®§17yU:j§qLéáà:¾Ÿ¸¯‹v‚†Ö•¬ç)(‘”‰1@·À˜³÷ &-HU\ÌÌ“ÕBÙnôµ$Ƨ'+tMi:gA£*7En蚀1ÐXv줤O™†FdbCæ …q0MÁ8²ê·8 ÷W€Ü\2ô1€èÃâ ˆ~Oa—m†åú ¶6{%ØM‰•d£Ñõ'$ ,(1ÉZš¨*•k±%1+%á(ëÕNY 9^/’mƒÚ!Y¥Úa%¸Þę̪¶"Fú憩7 ½g'È9ånh$+|X—£p”óLÜÎ2Ãüᑦ–pa ³²-q²”ßîóŸxÐEË‘í¯8œXUc³€¾BH ‹JZ0²ÈЕD€[#“FP&‰ÀsÈPKGƒOXF†õö8J4ø© U9f8™^<Ò1À±¡•ΣwÄæ1…Ï„»Y_£óB߆x-×Õ›*å~š¿w tU?íiZz=A½E둥ܒ†ö.ÆŽ¬Ú,Yc]<É_®ŠÜ -F'Îjƒr“ée¼öÀ4#”ó§,ðMÑ‚qÌI,ŸÎïwTi;Àb&›KŒ¬¤}‚~½ú‹‰à|]²£é@›(ï>„Tõ˜vÛ¥d²ÈÍ nÑå#&s#†¶Ééü:·¡v̶íjºõÑ>JYå²Þp÷’[ȤöWɧ‘ôz>uÙ Ö8·49ïF;Ö›Û©21ˆì((Õh`žM?¢+“#ñÂ1ƒ’—iÇÓöý]ƒ‡k7]#¦\Ëëá¬KNÜ#˜Âö£rî¨WU˦ÔΡÄ]Ÿ²oK%U¼ ß;4—r;À4rÿ BP`ZC†‘í ï¨Ô#RòÙbºðmìt©FhQµ¼Ü2ï\bLAó#¼˜.ÕæVm·®©])f¶½Lû—h´ȶ?€Ç´L)2—ÛÐ>çGNEÏáhÆ%éðŽ¢ÇH \üõ×_Úý"ðUˆ×BÜNµÏ  l(cCÛ•Ð3Ï'Mãp<+b½»¶j/¾e”22†CV98¾‹õœk9Sïzež¹¥\/ÕöÑhgs^üþÙÀ ¸~Ÿ/èµü$]Je±Üˆ6‰Ä;ŠžÅ2†n}²=&@€×TÕˆ|21™KÁ{·È͸™Ø™2 èåÙE˜ Õ [OU»e¼€ÉôÊŽ|”ÄzÃJÌ xw¯‹¦5EWÞû¡šF/Á×éó‹£%• ˆ”ÁyÖË'f|ØÜÞ™Rh#¥½!+Ѹ”Z0½ÙiLЪ²c½]³Ú?å Õ~Üà»×g7ÿazÊ–äéªý?íp¼lJŒ¬]ñJ9ôE’÷€i2Á÷9žUnÀ"YwgÕQnþ´Ž‚ØQnbGË‚¬™EìˆÄÜ}fkWÍ„ gÕ×–Þq[5·)w÷Ï—ªÝ(}(¸ù Ьýц<»#`l2Vé(ˆ‘ª¦pvx ¾Ç'®Q>?±þƒÈ÷@Ö¦\À:êf¤.d“"}¢Øæ,rGbxÚƒ p¤ä“¦½‰Ã]Œ }»É¢5jï“kmæ-–€^vlt>2¦)@V{ý®o|2ÏÇtG¡IÖ’1‘1ÍeÕ8%2ž‰F9&si&«Éû¿.ÖÒ§ÛG<̦O!&’ žƒ#~žbr ¨$·°R¤Fd1¥ŸƒÈHûô0hO +1yC5¾l{OŒãlá¦Jpn0ÒP™CœÆ§lw1Ž¡R-ôpÎÙ’iñ’- ¥EúøJÆuëw½¦,S’eΪ¹ûÂ÷xúJ-ÿ.‰ÙÐ}µÀ”m…lâ1Â1Yß Lsñ»u «8ÒôWs•únÄcš’ú°,ì¶LÜ·¢ýaúmuå'µƒ §ŒësÄólçöïx:otì¦pš–lŒ46 XžL•¥£ –U1|ˆ½C› õ&h%ÀAãnÉ'M¹C¯#“üe䀯“þÖ`²¶u¬¥AŽ]°Y¿ýç?ÿÙ¢¯m6;÷ Vg” ž^ø/¬Òà zü&µF¤ÑÂîOßQ]ÞãÈÂQUŒïÈ!OÇÜÊŽuÕx=Î[7]ÕE”½*Þ 0B‰&Û-€Ìj M>²`•æ] ãüOþ z64QI‹‰@néØ>Zêr È’Ú}Ùϧ)LRÒˆ¦°U¢QB–@:j¾vX‹\—ƺ0™‚¾‰°F%#‹ #a¥öùó¬Ô›è((}:¾°ÆÄ}IÖ¥æ“9| Λ·@ëÁb¨]W#¤v²‰sÈSûÌóé«{sdkðLŒ$plºcúÃÐÑP×4Ýz4ÛªéYá=Î µ4znÉ UeÑñ™Ëø1)+-êÂ÷ ˜> Œ¹µ÷g‰y§ÃgðÝÁÎ@-”Bõ9SaÕø˜Ú‘@‚1”¢ÅdÕ"±R@n–j²Ù‘f¥ãvÿ:‚4f¨Ë1ýHÇù×»®4™ëíc¢”ð°8Ãî¸ÀÜdÒSW"‹”[ÉE¬´ˆùàÄÀ4çÿ5ÐDY8ú¶õátc ö4À§ÿ«Š©WµßæûÖ4› ý0&ú´¨/ gƒÈšg[a5V5ÏPŽŸ ¦Æ< ´'ÍX´&—þõSŠá™­’ ÂÖõÖÈÜQX½*Œ—ÑòMo¨c³ä‚p¼î#Df‚Iß¶Wrö¡ÁWjl–hÛ> Žº€l嬖3YÕ1Ødá”2’'™È°ã<”–ɰìXïº%±VްÂ);½†Mh2¿{ŸCŒg‰g…ÏPo#Ê{%ÊdÀ kÙ”ææ ·ŒL/Ñå;Ï(·[íÉü(! jŒL~QÚZ.sÈÓ­c….½ko [½¾$”Jº²ªÜn@Î4ªéë}Ű`˜ ¬Kï?C ÉøôÜc#b`@”‘n‘Ø6e¥ñ€j_{¿|Z¸`]YÉŽk¸µObJÿìe8ï§©qrÝ7çÚóq…^Ìq @©Ä¤¿Tr44ÿîëHËp]‰›Eœ[¹^Xè:­H1#Gdc˜¾¾°ßÔéa .`çAsãÛ쎽 ¥‡¨+Þï#Œ.‚»ØÙ¬R¶²‰²¨åÕ3ì8·”媭aðö'j³8LZô@‹µÛö¡Ñ® ӷʽ`-Jø-9“ª•¸1ß_ĹUÅcä?󖡉Ý"Ç;ªjdU{Îñ#Óˆ&³ÆÜjÓ(…Ót¤éWjËpv_nŽBW1µÌP)£tµç? J‘|xʘõÞßèpG%þô­ÑÚJ4íP&‹T‘í°)@L#^7æ­š9‡4‘y6Ž›jûÃ-¬Äʵ¼%»,Ý…-M;ãE>z™LˆÜibLAÒhŒñÂÈlÀ£ï&™ƒµ£aúÂà™­# ¦‰Z`L³vͪõ*¢F 7#¬ÄÄPÅøy‡gH UfR¯HÃ-CI/îÌÏß<®ê¬Á¿¹cÖeP[TeÂÀtµp‚$ÈS—ñoüñ‡C¾I{ ¹ýfŠñu®T//AÀ¨Ê 0•F´eƒÚR.Ò´q-LzÊ s&æ‰ð•8Çõªþ°j“í`œ‹l7æ]2>+X´vÎß‘§ª='†1ñ•êLIl·ÜV8“‰@¥dñ°ûÊ;†é ¥ƒ` ûhTûa`±vè³oÊÈd)1‹ÔKl €À·[þr@)7Õdø”Žk±aU>ñº˜gR/Œ6¡™`›(‰|jy¬˜¬GA?¶M½[ vÊx€¬w¨ÔSçÿÚÒÔeyš•t5NžF;  èƒóýqìM²ê p☭Æ"™,0<9„åFlíñ”d"2C6H—L «#}˜²F[ÁmU5}ƒâiòIÀ¶A)eÙËȦë¥ô%§ôÊJ¢ÿsJHA©·GƒñLðLd¥ÚÛÓ‘²«axn"^;LåF$«]U;Þf³Bf…©¤kÕ¹Æi00eËØ™I«*Í“@8"LYÕ‘'F£Ì-^Þ— Vê·SŽMÜ&ñ]„¾)íÖ1ªpGÃJ=M™@4É_´R¼ÊI©—Œ[G ÆgAÙ½ò?Ž7²E&n¹ koÊTµÂ1õÖn+»e¢Ú,ùûk,#QƒþÆðÒC]©£ª;ì»81p7??x°^ŸÆ‘‰c>°hcUäþ¥ÁJÈÜÈúö+™(sÓ¥ „ijÌ­ªŒL& ŒÐ+µL|{&H£JÖ’?1ÞõM Ìdþ®©*çvV¼ÿ(—•¬*3Ä10&ÿøJ#ÍD Ð1W{žàFïSw,È0Jް[¿njoäôsFÂkì¹Z£­ê¢i®£ª’H†Qê£ô8ë%¨«!'@ª”L\¹4á4ªlÃ&Öˆ$v„ÉŽd‚{®6ÇX•8G-4m‚Tr”ñ”ýœçC£”¿LL#šÔ…§¯ Äèµ=‘ù8"“ù)0ˆiºQΘý`êJ kh‘ë댗•¤ÚlõÖ[Éy”rëQ سØäÊOb[I1Œ$Ó»%; €6tÜzmȶ¡Úfï“X©q²+-¡-ЙÐ(Ñ´U³’ d¼.YW¸/Œ^žªpž€œNÐ\Gûh§;ÒdØÖ¨E$VÄLZ©ÑHãvÓZ0ªíß¿¥Á ¢jaj*,êôw$l]ÙŒ‘z;6I®‘ÃxæôŽJµhð°ìÓmý‡ fÅk°`"(U›%ÿUe˜FIKÓᑵ ¸ÈCÆÀ(ɬ7®w s„k4 î1Ý®¯x&ø”áÄŽ°ÈŠ?&²7Ô踙ÒmB \ù÷ ÞÊaÈäãSW»õì56ßѺ²íFŽ+ùhZ £J&Ü"¼ï”JýR Æh?÷¦JÛ–c;Ózl™ªd˜vók‘<éåô}%šñ4ý6Éǽ0dóŒ—ë­ä¸O„ÃÌuùt”Èh"›å¸åÓ„l¥ÀˆÖSj"ài¶JýÜ)aY˜ÈæËmU‹Ò497š­1űdZè›r¬o H¹× ©Š­„±@b‚Û÷ý4%#àÐW¥ì¿[à3Ïjn-ÖQ6ÓG°ñùä ÄaVkO“°•cJ¶0ÒãÈ“{·Wc =¦ü)ex¡JÖhû8vwÊJ ­‹g&Úñ¨Nl™Æá…^Gz¶î(§×øý'f‰2êƒ×èÉØµwÌ¥#_ÊÚeÑZxX—# ¥ïnnÆ ª)ñ鵘Ûßq0ª&}-]/OzU¼lcæ U?—û?FNŒ›Â Ó-zMkg…ŒgFcÿ1ý‘«vÍliômBƒ¯±Pª1êZ(ßÇ¡œÕ G¤·…›ë%ý6ñhÄ|(|ˆ1“@±‚Ú×[»£v4."Lt¤¨ÊB‰çJ šŽ¬´*}8Ãde+Áù$‹‡;2 ËÆÂýy€ç 3™2#ªVrô¾±~ßî.‘ô=»vbý¡øh0-ãhÌ‘™¿·ÅÀœ+ñœ?&£k· ùW}sÛðÁ‹FÙö0[uÇZ0Àí;_~a[Ç· ëµ'–ó­—¦#l:A>¾€LÐVŽ«Âb†4•d>þŒž,РZŽv(àómþýGíC£Z—RLülw¬dÖºøôÔÞ.¬· ½£€e½ L|Kø”«Z Ö…šÈ ŸáÙ<„ÍEíxÌî%ûë™/FB)£«ú~NVUÊVn<Я†Æ¥É*7wKY©5(éùX ÷ÒâãÇ;â‰aŒp&4gÑß—À¨ò¼ôw…¹ IæÈ¹¯Æ ?¢ŽÌ¯ä{"nÓv£íÙe³r¤a¨Ïÿ÷â‘&^¿?¿zÚªåùd²KåÌß±%Yæl^`Þj&rÓA&»`gÙòÌõÂôøÄŽx÷¿¨ÜoCô½Xq°eèpÔÆçÌ„'M%˜ 騅¬ÆH½”&9§Wm±F(9r(` OUíbºržJ˜r@Wb@°rhšÎgVa9ÍtÑ |ÓÜ÷ï:}Ù”8{I@0)œeÓ{.ÜÚJ”@ œ¾£Œ¡çPôôù›ŸT» Ü,bHÑ ôq«¶UÊöA¬ÊZh88ê¥,šK¬„!Ã8ŠmØJ²ã>0e-ôxeª·ã›{|/S‹¬ #×Õòî§€gG²-·j]ëm·éià&Ö"cè7(Æ1^†Ûy²@n)»)†rzÜZ£}Ù8ÿÝÍ>†* %¼A"OúÉ4Hz¶98jé ƒôdڹɪûñ$NP~Éš( -iúL 4 žŽ]¶£ìGO‹Przcà­GÊ×þ|ÓŒæ&€ÚUëjP-ªµx †®ìØKæ/3Á4EïëCG’í¬‘ ”Æqë%PÒ[`L!è·ÊVj4šVÕhíZ²Í #ôv ΰ¨ À¤O_Ƭ‰SÚ ÉVµ=UEƒâùg’á÷¿à ¡£ò,a;…d]©Û²Î¥mZ]vÜŒŽ€xæ0&s€•äf>§^9>Mã`ûÈ"½o*@™‹9¶g¿§ˆµ³º)@™‰¬·`J†"¾Œd›¾­ht UJ FV¥ Ä8F6®‹°mVB©×ÖžXŽª”;6É$RuG¤p­MÓqS sA_4«Í§TÊGî7T²^ÎÇèþs’ ËÙÆ+õªi”Új/94½»×ÛÇg"ö,-“mJ˜@&öÈ •0µoaBuJšx9C¹Å(·gŒ&>ñŽÚÃøÞ¹¬±wð 7W´ÞLr– &MÉm2G¥“LC·ëpðª”ÙQËô¹åÓãkWM¼êf)u¯JL€ ótÁÖÈάŸÜvȰÆ0[U@‹P˜ÈæbÈ„®[??Mq”€2ƒg•F è¸Yû飯ų¤ÄcÎìûY—•¦Ç´t—Aðp7¡÷>2ÒD¡+ý¬²ÅWrçŠÞ=JÆ„“úPý„ÓÆzŽ€èž×ö<™¥=:7‚¾áùÓør·1.¿¯]™’²LÖ”Ý?½cþ'häZ,©$‹Ä™ÑV› 5 ¸x#ªâ‘°à,ÒÏAÉ&–?^¿Ï‰™8w lµg…Ô.0µwÄëÂm@ô”yöG8“-,hÞÐ¥ªE©¹Wõ)È-ׂá“ßMo´jsbJÇôkt„µW „óϤ¹°)pGn]­•rÖåX&Ë*F{ëµL_ÂkvdHQ‹)Í•4BÞ1¬‘¦Z)2‡ÖKC&Âríz‡9ÐÈxëyF˜X[#lk ¸Þ> U ÛÜd_{&Ȫ‘a<0L,˜çÉëÖ&ô¹‡Ï–w„td-ËsY#˜RÔ"Wõd1Ž41J+G‚LšBÌê51˱hneGwoV‚Ž^ÒqâJ •M\ P¥×ˆ÷˜‰e_TÿaU ;ú,ÙQîñsÈŠ [¡D°‰=Qšª•²‚•ì„ñ=^¯à“-Y€ ÙOeGØÏ¬.³,3qL ?ëþ~ 6=}$ÜbrŒ"M¸ÅºòJ¯¶I2ÆìR•ðÂ6$Xt‹Ý—&è“ÁdòµùóÅ«K®‹¸Ž1YY¦ÛÄóIC€ïSP²¡œm¯ªˆ„ jÑe1ÃçmÁ‹ÌÜ ¤€éäøF:GqäŽÑé“V­Sß‘EŸ41Þ±1YÓˆp“ä^O9ŸVßwK‰[ž e"èûöÓ«bȈïœó4öt¬Tb’§<ÜzÇx-4J@ß&k¨–MgµFǪ‰«Žá9 ¨rh"½kÔØtWîh1ÜþMç€ 'ÃÊ<3qÌ6’ÈgíÈmB/Òà땽³}4æ úĆd}¦9T%؆x¸¨ÿïìðiv_+ÁªJÂQ&ÀÄZ ÏPú¬wÄc(EUàÝ™3pæý~ç:"­*tÁÜ À«w¯!ò)û3`ßy¶ª¬ggžá&Ê–é.™Ë4ã“5ÔF`ÄL¶Õ;‚[V”šB#0‘ ð=ˆÌŸXÉ â'C GæW{Rw4n4” îüsS<ÜË_n:Üh>˜ô97"±[S:*Õ.׋ÙE­”Ìõ¨jDʘÓüûaîØªø0q>e¤ˆÌD#æ:ó5Z˜LþkAï£ZÍVeÅDIhìÖy†ñ4ÙæÓqV•^²_FýÙ{UÌ÷“Ü6ŽCi[zbdëež-ÞÎ}X•f¨ ‹½ì •™Ô%ãs»MçúVjÞe¤PeÂJ {Ÿü×¢”@ ßï¥À—ßÏ †ìÊÏ›tUß YËoÕöÔ"Tk‘uÙê)2qdLõʘ¢}rk‡ªAãˆO8ÆŒtT•éûôÛä|¿ñk”EV½á€ƒq/èØÀÐN/ºæÖSBž_(ij=x¤›dK €ÙZšeŸG-4‰ñ™gßÑÜ&fNßÛ5g??FÐ ½âN8›ô²i¶X]“žmU¹Ú¹ÁrãvLàH¼R²ýµN{žy¶L†ª†bš«Ú0sÙ’ÚE-Õdb‘þc’†Êé•z J 7o.öéÔå¸×;SïÜlaU³ÚÖM{IúãrÿI)ú8(7½‰0î‘ær†å®iP¤+ esËþϪeZX5ÒÙòÆq›'P¬TNI]Jý%ÝŸIwqô†B £×#tl.Rh¡ÓÿžežË¹Õˆt¤qÜÝ1¦Ô8*Mb³ÂU‘°èƒ(ù8zF¢#’˜ÿÜ}…šB€ì%Jz¤ YU`ŒHÖnHLo՗DZeê%v„ß)×ì$%qGYV1µgŽìkC¨&À!oÛ@LÎ0ŸM 4%™ì¸–V%ãlJ<ѰŸD_x7J)«"ç¿mñ=^pîvZº‰•àVj.K©Þ¶a-5ú9úŸþùç]‚tÔ¹õ‹.†¬Qæ˜FUËU}ÑSªŠx¶B—ˆy[Ò·b]ÝP˜2½ãs{Å)›¥ÅþÚ Šªñiª¶IUJ‚øe‚Í}°«)i©Ë7R+-þÝšl‡"7%C¾­_ÂD6ËŸ¾›æ $âòqGüåøi´U$YžHíý¸Fbr#ã94NÞ¸šßVñ])¶@¥irh™d[  ‘ÅFЋŽ}”[cŸ >F ^‹ãáá2ÀDØ-Ü&cÞA4 5”µÌ¼‰•æ o²ïÌ”`ÎéóDHiœ€ùï³PÚÄ~Ð0‘xÎZˆõÆË½^ÕP5ÈQi– Š9ÐÔ (Å‘²‰ÚíƒÜÍÂÔE&Ön‡ÕWiÇöWjÕ¼ƒãnWc&l5&¶†ü…FÆP&û}®z 5#5èmS›#q;Ï‹†;&«†$ÓHü’ð– $ º8³jpÃuñIè"pìð¦èr Œ?¢óWÂ8ÝQ#¬*ê0ùÇ8šûVa²zUÆÙ»YÆ1F5OÙhJa:>AVWþý¬„4º£Üõ[&}ñ1}:Ä6k·¡HAæ¯f2FÆT"î Ó”í&<òŽ@¸Ï+Y˜%ãë‚ÿRâ[ï;] ²}m"h~W€Ów#¥4°v†‰™·ñ±»†iTEG@L)·°GàÌA)ìXé¶ž^ ÛµàÈñªÂ‘ ·þU/12«™àEs-c´c·`È5*‘Ádû½p»Ï¦P¢i^cÕ@<Ühbn€¼µ@Ó4íÖQ® §´ÌÍ %<%&ÛŽÃx-"ÿ>ÐÜ®I è¢TµÒÆe©6>vw Y»–ªŽ­DÎÖ‘,Ü>rwŠ µã…ÒÝ¥é0€¤4·q”xÍD]éM‘k‘[©)ø5‚X)œOL€À_¤Îä½86)†È? (ÕT%ƒÛ~%¹×¡Ü $C9wáK/£Ô®•|x¬ •+¥Ï ã™<7G¡‘ƒÑ ,ßþ•´6ôûWcÿé7%F£ªF`+)‰–ÑÈJ£ ¥r¶º„éŽZz †yRjŒœç´û€Èš‚ܺԙzçf[&®ð\$¶ T²^ž2¬P5H X©?&4¬Ê4Ù’Y`GØ|Ü‘k\J}ÖanãSbŠªþ] ÜãИEÐz€R& 7"ˆÜh ·€LÓeñÛä`C<ì.F¤g^‹cŒ#Y;0Ž2>ònôçOMd< @¶myÊZ€¶J–ÓP+‰Ž« S5U>íc„’èKeh¥le2U-¢Í¯ü,ãi"L©÷ ÿ|yÖxÉ í Æµ”r‹oŠ<ÒÚB;r@×î¥äFzåVð¾½zã1v;dWüö#{}2ìô 8 È¢ro‚±CLâ £Åxx2¸}Zɽ&ã|GÂÛâ󌜲Uñ[ž²Yþ‚c€²‚fòc¾ÝVÞÅTÃ-M–F w¡Š!ƒU·f-‘ s¬«82gU`½#ëbÒÂhÑ’˜æÖÎV©ª>*ïwÕxÚ5¶gØQÃ2ÛFd¢Š¬Q)@ÀÓ,À”®I©Z®WÞˆ-Ÿù9.¢.+±RŠÔ.fŽ'«‘Àb“Ťyq½"·z]c¨g(‹ÄÚÍjº*Ãð2%Ì爉¯…Uƒ2—ù(‘…‰û‘Þ/‚¨+-Èe€s2Ù´Ç(™¢KÀýXÀ¿!ßïMzL½í#™l4SÕ‚{dâx†®ã>¹’®VBjìŽ[[©É€üið1ùt#SD 3qT’É0aã‘­]&ö·¨È†¦¼Zµehø`Ta™8ÜQV-ç@àȶA‰Ó´*¦{ôËógE©Ëe}¶[˜21^; l Üú·sJ½ }Xþèk!®Ñ±‰íã¨níÓð|ŸÙÆç D,vTm´ìɺY7Wà1çdȹY°–ñªX点ÓÈÙ½úmFŸ Ïñ€o³ŒoD eëáª&hŠÐxÁy9=†@P&Æ»½ª|ëçš :N|=N¼bL¶›» ,ãk§wìRÙÚí­Ök%Ÿ“›f(g¢]¤÷q2ÜP† •UéíÐKrø¶JFp;Î (½'Ð5šð5;ɱ ha.€FO0Òqƒú% ëJ¬ÊÐjzGU%‚"&Y£)ûã6e¸°³®dZø¤‘Éd%ã„*+G¤.˜‰µ G‚öÑ(á«:4·ã\gnk!®K  >zijo‡4°g´'[ÊŽ|TëÒ(ø”JX†iäîˆq}ŽÉÊÜ”èŒÈÄtš|6´—ì{K)jÌS#F6îÞžðY˜®7ŸzÛ'LÈ‘íL/XÅ+JXøsË?V÷)U,'†ú¦à3œ¹#·®š@N3%Ò£¥anz#d—¹±*÷ØÏ ¥”a½‚ lM2ùü×@=útý¤uÙstt%U‘R‰ Læ&ºÚ¾j2¹ñp³Éh:àŽÂ<5þ;¿½Ä Ò{Uƒš¢ß2˜ÈrC¤‘½7A£Dî‰^+%¤OÂÄxú.¨åí 7ŽR` X‹…›²õr¸Úó\ŽþÑWÄ1ý 2½@š²œ[™FiþµËx¤Xîˆ Û¹ÆÅÓT²R; «+¼OÄ‘’¦·‚ßY]azÇ~#4š¹öü÷8Ü€EË4H£ (w…)ãw…ÖplO-”k÷ +%¸)íéØ ’I¦×%ûMB Ë&­7k/¬q °# Kû~N1<5âé]mÎôJaúK?\ŽªåZRÖÒôüñ˜ôáí–åû ¶vzsØô+Œh7@Õ]úG„|ˆU‹-܆Ll¢”CúŽª1ò.Ø%2¤#OÑ(1z "_ ,rÎ3¦qÛ„!,‚lËzrW˜ I¯Š9ñw>P¿ZÇ#º¿dñĹñMÜÂM6¸U9Ä»$¾RΛHÓ  FU¬Æ·*çct¿ &6(Æ2¢m•ª6Ž€¿ìˆ—5î.W{’A•à•‰•€¸§4Û<ø•8#톯TÆ3Ä"½­mû/&½³r3´5¬ýøÞÐÛÏçÌéÉ„ºL£:‡ª9'“{Oš0ýö4Â’’qd}æOÙÇÊÆq%G&äXœýîWQ‰8JÕŽrž|&SÊÉ€°•¸Áª ¯÷wl7U<Ð’MïOÙæ­Aä@“ƒöÖêͧѭ©J ”2ŸanJ«¦ËŽ‚ÌG¥j¶p›¸,½<«°£FØ\€@j—FôDiÒcVòÉÖ«ôú0ql=Vk‰ÄwÁÌ Û„žÜÏ&¥AxbÙî m+ @/™# 8ù"¥Çé:i„jkÈ-ܬªôȺš’øU6tJ “FïY\Rõ¬uCÉÿœ­Ç›•€Scâ>ˆ½RËä ‘F©Þ­Ñª-){j?¶ç»’Wד÷ ÷^u2ê×"ÌUñ&Á"R ;Ý¡ý5Šž Ÿ°’°=`bÊŽiʆ¨Ò`Ý‚Uƒ&9¸¶#™ ht¤#@©¤… ÓçQ»#~õ’™[oí-@´3 d“ÕÛÂ=Qš©¦á`g²Ž”É0"F—Z^Lc7LÐÜ7b£³’™ä¨·»g¨·vÿzÞƒãûnº#@Ó1qÎðž‘¿#^¤ôŠžK•9eUÝ«ªÞî® 4Ž ÛZúŒ0d²ªùËù(M–‰,臣‘B‹^ Áî’2¦}hz(ú‰çÙò½*O-²jA¸)FÔxÿ¾E< €kJÿ·eäÈ鳚aƼ·°É¾dòkèilÒžµÃd¢¹}‡ûÎ4±LHl"‡Ó$M2zÕcb±v „ËuÙS#™œI/ָ׳ýëâàXon»{n 9ÐÐÃ2Þ1C¹®ŽÅ«Ñ"Z©¬ DrÓ™¨r¶X£·[zžÌ›¨Â§ÝÿwÐ-Á"#€o<Ür€ÐÙ‘pxbíÁŠÀŒ«;äŸC‹Æk˜|²"îH#;Ú†‘d9†*96e›ø‘k„œ­LCinWâá#0ñ˜°Yá&y&“³”E$7xC‘‚'’ùÑÝ @š²_öi´úìvý Â[f›2+scòሺÈ:¶cšYaàŽ½ÜûØÓK·š«%+ÓÙuú–T-LÄ»”£ÆfÍP»ÆJrU2‚"&+9$sÎ6WTSÊd USº ÒÐ̵gØQ‰R9ÈŽrKB•>ÞQ¨ʪ‰åÆ™Kï(låØ3fžÜеçÖ‹Õ+×BÙPâ½æÝê5„sÈ„£^Gí& 5d£ÓÀ¾þ²©ŠiÜ%½,zgÕÆÑ¸©£R›×Õiä@]0yJ°è³ë5î´³ ž )H/7 KÙze< QôgXV5Z@Ky€`‹!ùÇ _\ )êUˆøá“­%gË$nO?¡vîóÂ(u…ó“Ö>]¯Î¬ix;Ó«Ša½GÒûÛA§ÉIku¤×EࣚCV™#ž¹cã"oý|ÒM”1rk.Ÿ¦Þôó²ªA¾¯ÄïVƒv÷™´I«Ò×õÞe ª2“6lŒÔ2ÞzܺZ«ö!¨ ÀÀMìÿ(c½H-0&6BÄ8ŽH>•´T-·pO‡ìÊ•ÚÇûàµ+’aDǦ$ÃhñÓÚ•ôŠÄdHXûH³àœá@yËpÖ…@Ê,`ôµ4ÝÕR&î"xGÓ‰a{â#ñ×ãLßÚJpÎùѪÉ䂲ëkÉsÀOø=²Ñ˜Z€ÚÉz%SuíÖl²ïª^2LI· ” U¤Fƒ²×…±Už[@;ÞqJLkøæ,r–‘Ýhda@ T}ýŒØ”Ÿð{±…’Q‹5tÅ-@ƒyùº0é[‰‘ßà¼Åì÷øgöïÏìL(®Àa¯ 7:s²q&€U[Cµðâ|d#Ú$Ü’²*¿¾mW O°‡À;0q ÕÕ1†à`1Ñhä)Sú–PƤ”›ÒS*µá_ pÖˆÒ/ãçþ÷Y¶qƒ(»‚l%Y É€ô”‘»T&õ*á)Ó4ú%íLÀD)Y{ú~¬èÛÇž)ñªã½éÁ“ˆ$p\n¥æ",h<ˆã¦¯½kmÕ–Ù¥ˆUµ3¡t Ô%[©’{á³Å#‰1ºh|S`2VÊîØLVùSú1ȇ,™¦^˜'LPÖ.7:e¾ZšË!%M—ÅYµF‚pV47Ú;c²Õk™ºZ Ü' Ä1Þkh94å ¿ß×Ì«úÔNãlE»mŠ’ ‰ Ëõ¶öîîÈAõ:}_€ÄÐRXÙïîöïç_{Òžº6ˆÀ2Ž=T%2 p®ôûžWrÄWšÕ^,«v¦i‡H6̤M²Š?R×óg·<LÜN£È½‘ôŽp-Œ±0M2UG½mÕ]öÉnh¼V.òýÉœï™ùü Óܤ|©ý¢!ÈBÎ¥^™¸áJmo¶Põ÷/í~ ”0øÚÓ«VjoU²Y!UÍ•…#­t ˜²U_ ½ÄÉðȬÚ£ëÝÇmù2™ïbÿŠóõÜ`Ëw‘Ž0·ü[ Tm™Ì‘ãµÔH&ÈÚ)0®`ä£äÈ$Íõû~sÅŸ‹Ý«É‰k§Z&l%SÈð€ŒÑ‚qÈèa)½Ì¶Õ• (Ó‹J1.¢1‡†¦É¼q<‘d>\9A> \?ž˜é‘ô­Ô8+õ}sÌJ™2MnÁ iIã`ß_$LûDÎ (â³Å0´y‹™ŽG2'@>¦+êHc4“mÛn4w)g(ã»{Y•Ç1dE½»/ ¶dkÐB‰C&-ÌIP‰&Üeû®nàFMœO¶ùÌĶxk zÕŽ iš"ãùÈôÉRÂ"¥Œt÷@Îõâ‘ñÓ3l( ÜNÙ_£®•òá©n½Ì •ªÇÈ-I DæF‰‘!«šÒ v¨×‡‚¤lt&õ¶’ƒpMâHíßÿ9-ç¼jÎNIu†eJ w8_X¤9Cn(bS-ÇjGúÍ"o Àk¡üŒîÿØ£¸­h0lÃr¯€÷-ô“Ã!A†ÜhøãiXÊ·[¤Ü3ñý—p´0Tb"ÂÙêibæ£ß,ž”4Ä‘U™ÔN´I9ìF6¡Ži˜à{·mEÆÐ±.€øuvDÆÓä°^CÏ€ßÆ e&•RÊŽó9 ÷…ûtÚ\#Y¥®°–‘{Ot¬T#Œ¬= êØ]94‹¬miTklm-«n+@hy #Ç8zds9ÿÖèR˜v3 £U²ÞL”^`FæTµ«@IDAT#è}úŽºZ^¯pY2@À|àüa½ òÁø˜Ö«‹R$0Ž?DHJ6q õài½JÙâ¹±}Ë|2Ô¯½õ™¼²­žÒ,¹^z@cir&(’ÁÝzǹáUí#»¾dîhY¶°Ø§Ó'Ò#dE¿¡êj½6¡éÕ¬¿‘BcÊ@ûWzù³2ïÝÒ÷&ø}L6?‰Öfõí‡õx ‘9²°%~îhð"ìÐc4R ]É”º?²¹çìEðzå@úÖ ^‰C[å,S"i\/RÀH€¡²KŸ«a`Õ‚ƒMúÐw‘ö™[†‰ó‘µËœóÉ„rsi²Â‚lO í@ßíúÆ$NÐuŒ£œ˜>òçôýJªdmž•¸ÁÄÙjlÕnÁV—j‚ªJ9 ¯Eû0 RU(ú1xd]Ý]o €µ´Ü}½œ²YJkÏ¡wƒÝÅ_^A&Q/™vüJ‘¬;æL©«¼#:cdËw÷|0õ·v„ÿo ä®ÜJMÉ_É1[Ù1œ§Rކªöž™o\¥zµ zGY;ÐÑH¶p‘ž¦AJ°ÝTa#í¯8yJ8e/ƒ/8ÎÚÛŸù>ôæv&³Ê°F&-€ìÝš. %¶JdŽ "ƒ‘óÞîô\Y€@£/R>pÑžœñ4¾ }šÅ3*-€ Á;’ %㟟6®ãÖ¿_¹Ã4L2—Ïöw=¤+0ß»ñTÒxJæís¡ÖŸÜ€Ô-GgÇh<Œ,2„›¤Ëx¤0Rè ÓÌ!ÀÖ%{ôËha%ÃÈœ;¶R˜"cÈÒ—)SU¤ñC¼ #UaaÇZôª*¥A*5‹ )÷ÿEeßûÄH>0ý`7Å·¡ÝX½¶u ÕÄ=FK]ðÈ4Ýî´]YÓ‰;6·çÒ˜3Rt;2¤ÀÔEÖSˆH2YµMäãòûzqÀX)òZžt쉚žLvªû(õnVP (UÕ h‘³ŠqôàN J6ÆtÇbæ­lC€›* s`UL“ » U-é(o¨Qàkî.Žxséù÷ËÆTRp&¶ +x%ŒÝRÊ4µ Š7®Aï5×β¯Á|òÄ“ L$ €‰—1-f:,Þ5Ràe‘¯ðüpq3èVÎ]"e;'Fîîɪ2Ñ[×üsF ú6ô=ñ²*^;>7 \c>²=·Ø¨ªÄ™!Œ”³ÊÙ‘þÚŸ7 G†åZÒ8’éE6:¾‹”Uý”Ù_Ô_£*ò<ŸÿÁ(+P´¨U‘ «ßËæ^)RÕQhç£ÈH»*¥ 7‚ÆKõ¹FÖµvǽ‹^ÎA¤+F•¾sNrž#’RÞ²¨tåÇÕĹ™5qL6§ZYþóTÂp–‘ r(à™; V°PÒ‹t‹umO¸ß­þâ°));æÌ™[ü4ã˜8½ã-ïØ×‹¬éÜ€Z"aJ2% ˜.”d$Ûº´×¨TÕrÔ?¥#1eN–²ÝÈrsoëy: ¥F@Ž«‘ŽüÄÉdñ¶{j-Äx™§cϲF¥^À©*Èð«Qï”ýdkAÒsp¤º„.Œh:Œ¿Ü÷åÙ U)sèHÔ¨ê;³cÎ'›€§@öU„¹yC«ŠÖS"ªñµôÛ8çö$#Ø+ݾs;@JM§çƒ¡wåÌåž‹†@×y¦û ·ûûÄ›ˆ¡yZLÖÒÏŽjβjJ>pÃmÎŽkéRJ€Ü ¨îkÙJu)Á¢Æªy+¸‰ªdŽÝñm„o÷Ùͬd=ib<¦<€©¨0 ùú&3`ZÕ\•µAÆD©ï1ŒÁ“Éõ V2>ç4z1ª‚>C>J-%«Æ¬È|`2Gíý¸6˱k&&^ª‡¶€vq¶üýñNp¬o0}#Y GJ³Ô›˜ÕJñÈò™ñû3‰?¼ªŒPXýueúµÐ×bËÆë6š€Uy$Ûüå‘€£§†ž=îJÜ\VÏ'ŸFWÑ< „äS©öZr pÃP—cÖ‹ÉV×€ÞLªîH0Ûô²5ÈÀ¦êv4ø5ªŠÞJ)Œö=¬Cv›Î‘Ú.•eƒäxÙCíў¡L†¬½¬ê;‰ÝÎ6´ï­£È\Vz­†yÂxÚJ{J vY)œØ1C$±ß§¾Joïü Šh,ã>‹ ­ÑWH #0ÇÔ‚ttÇd¯ìêjŸZd¥˜Ö é@/§ì)”¶ ̧}`nJ-\ ’'œU”rËJYmIÇ >wÇÆéâ_»\ õÒˆl‘ñß/zRµ2ànØ9ö«Ä± Lü¶D]ªz…¯¯a”JM DîuíŠÔè˜ C-aïè2<³…µ¤,Çðä@ j—Þ”ù`èi\Ó—¦‰˜FÈ·éK]ÉAÖ’›ÌPUÊ)16‘ÿrsµ$€·-‡Ž€*%C&ŽBI 1¢YŽV¿tœ ±j@Î ËàG×>ÆuZã½NŒö˜“éß¶ ½Æß¯Núœoë÷SÑôöi‘/åªõò}"JF(5ÊmªMŸ1f]€ Æ!;ʾ!½­#=F¤”…—ɦT•aV¶ª­ªäXÉz¦ÀÇî÷óOé‡(í€P•›™^ž-A›cöùšÉv_«æÙÔé T+uäã)úþw)JÁ9s8‡¶ÕK¦(ð=,±£h“dªZD÷J¶ÞZkl\{Ò ¼MXqéezL9gǺTs Ð@ CãúëuŒ$€‘.â¡`nÚ….G¼‰a@291@02AkûÙ¬”g¶LòÜæõNC#Y‰ F}ç»A›)à¿ãø¿ÿû¿þí6ÀW¦ÏH¼<÷¾VÜ Ñ—ƒC«o2¤H©„”óO°¹i:&(g8¾—ÊÖ™¥„UgOS ]ršgâŽnÑEü”ºW|ê0Ž"™T…­‘¦}©ªÑ›^UÖn¢hâá)‚Àã„G.κ7,æ[C“CŸl-˜ª Í6%Þ±¹i6«£ª˜Ã|b”^†g¯„ä£êq|Ӛ嘹mµ·Rì¨*Q2á¦ê8 Î_ŽÞ!Á°ö<ËÉTçÜ&ª ºNŸµ‰«:"ºDUï/²­EV͉ pèÃ:¿Ë²¢ Ó /àØ«v\#p%߫ƳJì ðî‹vÎÓÑ»Ù'R;À0[ÀhdٙؕSn·ÚUÖèšFÑŽôöy‹l•hTéáxVM¹Âï…ÁÓ0¡Ï9A³šŽÙ׬ªLÐàÆñIßÿ™í™™ooÛVÂÏ-Cí¹É0} ç¬Ìí¨ÅtAPé§9?ØD½©H‡.éUć)cä|“aÖ¸U,Jæ†ÌiŽõ]¥/ôq¿W¢±Ÿ¨Ú 2TÅ=P¢£ßYbY‰Œ!¼8c~¶õ4º{éÕ 6ÎyUz‹µÛëiz÷ÕrÍþ¬×Dâ€ÜuÈ`Ë—97ÝQ)\5C#Z¬ê>;ú6ŠŽ2åZ´[»®xLκZ©¡x }²ò¾ Ú‘€‘µŸH6FU‹#Ÿf±ÚP5·7¿ûà M_#+‚4«ú‚EîR-Ÿ¿ìȇ&棽 0ŽJ^žÒE1‰74ñÜò”‰ÅféÊ*ÆäŸ¬œ¹÷ÑhhG¥³Ó½¾Ûí‚ eELéHп¼­ßOè_†FÔÞ]Äܺ#¾ ˆïo„}&¶ðdmB#`;sã@fb+áL¸Äù3fÕÖ¨¥Å"kTÕž94Ùâ3(kÌFÆSŠH; b.UÊ4á†Â¢÷¡„ñpÒ•×ï{x'†0Aþ€dæ+š^îè"”x‘† ìXP8ÿù]ƒº&çc\ò’YT…$Þ-ž²»ÕN¶#¦‘4aw¶.sU|ss–i|{êRÂO7á0"OÕÆá19“%Àà+Á•0̉#ed]ø“a*YCÙbµËk(‘)%€sÛ'÷Ž#4È)8²å°Ÿ¥&&NC#`ñºiÇØJUÜÄLµ/ÖÙà^#àÄ ª‹ƒ®¦à5Â"ÞQoŸTßB½Wõç_e.Û_‰(Û î 3a›r]ñ R˜ÖfâØþ*QÊÂ?´MÐ{f2çŽØç«KÕÿÇÎ Li«¦8ÚãaU&À“C=Ëþ‚•Xã†ÂÄ2=ÑbrŒÕ-ãÈSÔÕ Õ¿ºÖ›LƒÔîeÔ^#>&7²J)ûAV–¤¿Ëž„éØ-ÚvU&ªL0 2„cdšdÓxy]ÈÆYi¥›K¦* z棸Ä÷Ç‹Pj—Ñnxš> ÊGWG¸W ã·!‡B xsH#f•`³ò×b=$ 굞.&޾ r—żnýüž?œ±YTnW=B³R Áfм—©ñ5!NÐï ™åúÁVåßh¹0¢‹Q6:àFÃ]¨UKH½JBûögŽq”äFƒQZ ãªH ·<¾AººK½Éhª6.ç6—)e$M¸cù·j>”æ¦ežß®Üvõ˜ö¤oÏŽdÝTfîoy·«·ŒÑî³Ð;+ïÍâÖ& º’#™œ ›Eß ‚ŽUuµ`UàiäFËl1ÓçR^à ª—gß®L”Èr`BæHÓ³„û²…iÞÑ”˜J2,ü~g› ÉJÄÐÂÄôò É`Uš0C ™,ú8ü”a")Lˆ·ˆ¼’óè‚€¼Y}™+Õ’ÉsR&r-Ì›¸å™$Æ÷t@ ËÞa†ø.•þkO>H+É 4TîqtÁ+‘8ö8dÖ&ÃËzå–ñ€Vuœ¿#üo+†U÷doàó¡ Èi.#]4‚ØÝûï”ÃûŠ®‘¾Æl½¢A s h9Šçoçÿ"XK(gÔ ™ZpÁ @hN86,þßÀq¤Ñ"{kÇ‚[Û$Ó۔̕•ˆ9,+åÐw¨cÕ¦ÀÜÚ6eVù,÷÷>J]ëŸ>™U½-° :šKО@ŽZD_Ö÷Rñ¯,´ Ïô˜œçî³ð'hí‰åkvÛï5ªòTeVuµ*вïM¿MÚG×v´Œ¬„̳ÌD´Iw+ÕEÆQµï†{Õ¥„Ï“ƒÀϹ*&‡7GöC‚ïF@/`í­ÛÌ;Öl:  $˜DÖ2^Ë‹Sf(ìÖ’zÝš¾–¡qS½‰Rk_í÷e#õÖåèó"®Ýñ.û½$’,Ò&@yŒ ×ñÀ¤'a™F¦!(«Âõö\rßÛ”d¢FùmÔÛ-æh/SªÂ½mðL!ÀÓ;ŠzU<[€>ÿxLžiÈr€@(c€ákÀŒ†[xÓ3áÐ7§êë#åv dgÞ’¯ ‡4õ¦<¿S„Ë÷~½5‹fïV¹¨zô4¼ KtHJ|xY#ÞùÐ8öX€h2]v«— #0ë§h%]Jx½›EÉV ЮC€ï +|2%áXt…L+½÷ZK‚hO%díºñzEþ˜Ž)áûÍèhg¥r{òOÓÂJ~þ¹! ÌÊDUc«Î6MCÛ§Ýò¬·qZÚ<R/YGÕÙÓD2X®K Hƒo.O,únuLO`Š,Òïqø ã»rb “M¬Ýñݤölu‰æêm€¾Ç÷Èú´4BcŒFJúiBjO êØ+aXÉ-Œt ÇܪrHƒÔH€I@8"Ù2¡G¥èÿÿ’|’5b]H]í ;6ˆC¤ª–lëMFÉäíUMP AVŠª”ŽJµÀ§ù~è½OU™ÞJŒ'[£-Œï(Éx‘Cnõö,Æy+-J°Y¢ÆVÝD ¨]UWnrd‚ær‹×«úó8lPo “e('Smb˜q81™o#¦–ÚU'p$Óxwظó@¹) –KÇöÃücj‘ÌMc¥–Ë<¦‹T"z‹Ö€›µ^íJ­Ô¬3ø÷½Räp‹ß·ª®4dË?²hnƒ¬ç¹ñk¯ÅôX ©š8‡<¨äÈ¿.dšköý B©T×/É/§‡;ŠMŒIÖ³7KIcn˜ÈÛx1q²õªnÉfeX×~žÓG¶üøýôb0iäŽÜbhÜH´ÀªFž¶ß?¸m$¾}ç'Aä3¬sš6hÁ4·qp®žOÓµ¼kh§”Éèå£0¥Þœ1YJÕ˜–éˆá3+ µ½9§,§”5¶çÚsJÛ¶0Ï€½v@ä4ÔDàå1µ k”70“?¥£ÈضÀ­ÆCÅgØhŒ.ãÈ0J™Èâ U#jXÁéë…y'uLk©?ÓÜùttUX´ã6h S—¦ÞÄ”FÄËŽÚa™RDz[ÚÔÞ búõn æÅކ^ïs#¥½Æ »OzAŸ¬)Ž€Ý"5ÒÀ¢¦L쟃ìo%= * èª#¬Ä<«Lù7])ÍzU5:ò ü…µˆÜ€Æe[¯Ï+’Ÿ,jÖn²Æøp¼ûZ•! Të]Ö.v¤Ñ‚ñ>a\µíúÜúÔðÎßÚ´¹HJGJÑÅe¤RâºjY®%g;تÑ/úmÈObžxLæõÖˆ¤¤¯„´’Ü’íÓ»é2+A?P½…. ¹ÆiÉ# J€TZ‹RxVWþç3²F—HY‹C›I#8‘Ø8|Y# ºÇ!H|¬æÈ°¬]$뛀Ԓ^O »£A¯@c¡Ýëiðbb²¬”˜¸¥ ⑎HŒŒc€ÐÛç`è}v¯2=†Flóz‘Í¢fqÃÔë(në÷\pdׯKËñé ³¥»€BŒÿ¨wéXn†L)F®Á'L&ÌÃ4£ÄFÐ(5Ë­`%@¨:®±k8"‰ÙÂ2YH¹ö·ÊV‰IÕ€œžrÏ–›p«×³ÂmÒ,x²ÜÒwA¸P¢OÀ³’·¬$3LCוҒv¨%¦Œð©6Ë‘¸5ú6Àę뭘²A#{+Gâº8¤¯¤¥Åõ²•‘4 eŒ£üê«jTªQÞ`R{þªZ VvÀ˜fZŠø·J£TKo¢ŠÑåhœ’_ÊVÒB£š'‰#Lf‡FÏ w @PÊøÂQ„›rUߟ:]Š' ž`bÇöIßz2 &CÓѺÒû¸æJø³Ð½c&cZ¦»è{sí[R/Ì™RtdÅgVô⌹÷¢§Œ¡„µ_Õ—h„ª–s¬½£¬Eo²Ž°_8ölUz%¦Ë@‘æÆ÷« ÖÒnªõºx»ÉüUo·”ÚEZpÞ¶ ÒK–%Ç.Î3¾»Èøôs®ÄŸÛ‚Ll ,‹»Ë¹© O†{ÃZL! ¸/s~ÈQ 5;¶Ì¿ :ÙäS©^VÆàEÇ}€*r³0Ü0¢C‹Õ>“þ›ÈJÄváb|x9Óàly®”!¦ÆÄ”o+Y£P9 b ÒEP¯* ÑzJ¹ù²c 8f²GèóÜÜü›Û&eíùÏJ gU‘¹F´-2>F{¼,t5«öVm®ë$NÐgZW˜€§q™ã(š«—Ì‘ÕUÅÐéï©)uqh³Ÿ>Aå˜XÖË0½#™F2š&"»8+CŸET`ò!áô)ó‘# ÚL|Ð 4â9Tí.ZDLUŒ¡z[Æ›ó<³ooÛ¦ihdJgï篺ùh¤isY˜…©Ý&‘ŽMôS¦Ú‡h4CXlœªhŸøLΊ÷‰TyÒkÜŽ“º¦’HÜõ;bR2l™˜Æ$Ž\K ¬x§ØiOží£ÝqÿaÉ^¬—¡Ù»at1˜Ô(kAbÚ§FY Su?,ŽþºÆSµ%s ·,Xµ[&ŽÝ"@ÀVÉQ¤tÌSž0Ôæv ä¢ÝÎ’ÿüóžkø~Ÿ¦£hRGŽE-‘}9`´ÄËïHŽ“©2‰‡ÉrÀø[Œç¨ô®ÁÇ(s#87¹hw1ÿ{Ëï F(!‰;Öø¹ÁÈÚ· F#2¦js#czè”™´g]¡êÅŒƒUe½ñdñW%Ào<>JŽ+Í xq)žžƒ¯ ÆpÃ÷/.Tuu#4µt%‚‘-VYGL&ùàMßgM¦nÐ"0‘rŒ.ÕZ¶'CLãÂôªÂÑ}õî˜ Æ^/Ð\ œ³ö P²ò}6è¬{ŸZv2]¢MnñÌ]© ލ7ÐÚ#VÒhO†¤憕*±པЮd¢®êûU•›^J˜•œCsaz]ŽLò„‘²Àˆzc”0›´ašxʳ÷½ÌžÍÖÖØ„¸}LibãL`@—ÈS×FÄT’kö9bÒS6×ëy2ÎÈÄ}}{Yµöœ—÷ 4”Ž›ÞDüKšÎS©ÆÖn¥ÖÀô«,rz%bšJVr‹0¥’qkéš@’UµgµàüZQj¬«ÜÂ=eÕ® %ëÉ»r|í°)»5Y 0íÍE zPÿâîsÏý”Q:2Ñ{ûNÚ ¯Ú†”ªÝ”OÊJd­*cD&ŽJwì—ðô¦±vÌ‹««âš"ÓÚ€A/zʪcÄ‚LV¢³½•ï^°AàôÚöy= ²â£Déå[ƒ #ܺA0¤#,ð1.¦Ü<ÀV•2@à¸5àŽ)9;N™›c@µ °Ü>p>64WKüù¯j¦Ë~íàñ€\3^èJ¯W +y”® ט€¦8ý7 ¬5ô±»¯t„){5£+M Dæèb€®&tç5‚ß½hˆ3¯ÔQ5UƒjìðzáJz§Ä„Ëí‰lŸ-Ùh3L“³Œo oE×¢ÔP ú9ä\Ùöa¿ŸNV …µ×#ë½®çmktä_Ô˜IšÖÓôµüÃ;ÒA$€ï7—+ÌîÖŽ-f:fKêÅ$Þ@Kî x¡EÆÇ4h²”|ìÖ›“5hã2‘ ãr#°ÌAcø­Vªú—óÞm>]Äó–és‹gÅßÈVÍÖq|JÇÄk¬RÀ7kéµUØIÃjÊQÒ„-¶_£=H|&,ç&»/Ÿ`žøJÙuJ޽^áØ0žŒF.ê%^>囯Ù÷U¤tä@°®9¦‹Ë˜Ì‰ÃnCXµA«¦ÌG®ýüguÖ#{‚D€IGÑZ3]%GŽ}Š­‹ÇGÑä@ŸVäü'&h ÁµùÛêÿÑvo½²&ņ/¸šá,ÄO~53oýT½Ý±?Ö dä¼HGEFFfU÷Z{Ï€m†ñž¼RÇÜàŽyf&ØôÉžsázb½óÜEr(÷˜c˜´Ð\ø|d|/Ð&'¨ÄÃ$ççø^H–CãjñÉõÒ$“í#”2¹•OÏ­ ío£‘¾‹LôMI‰Ñ…ä#à€ªïV˜þYÀËóÎrw=<7Y$kÕ~ 8wjwû]éhbe#(³ê§½÷Ä›•ƒv8¥ÌD‹È  ˆ™ˆzYÄÉ€éãµÂW”V–<î×?k²M†I¶.æÄÓ4‹ );Â)ºT{C¶‘”ÖÃçØgUÇáŸÛ™qÿ`a \•`s×Y/%pšßáh‡lµä¦Ù’HGd&‘°@:®1@ŒÌ“²È¿€ô”öOY—7Ù׉æCKL†-3fǾûð° 4( ˆÝÑòŽ[€².&ßøÅ/~QÖ¤M­A®`Ô7î=V»*·3ÿýó™¡ä¨©}U F qÙg¤®˜azHËD×Þ ˜`?¢jIœ-\(çxü×eÕè6ï¦ãûË,ªq½Œ#ŒÁ;Ò¤d…Äi,“s[õ5ÊŠl>ª·ïÅ$háÖ’›F ·VêÈıŒ!ËÙ ¯¥Ä ­ gU Ÿ†vY½uáó™,@†ï15úÔ„ï›j™ Û gîHÓÐ0^ÀÌ…’pÔîØè²xÕç,ÇÚûÄJ?sŒ¦Ýéå3æýèHpöxÄJMÁ<%g—ç™U¤Ü”5ææ(à¾Qž³j¶Ú»Žª–˜ÆÉ]¢A‘Ú÷UlP½dµp 5·vJ톆•0BKº`|¶J@-pæ†u ˜L¦!ŽE#x"sXã-<ŸÐ(ìs'¼~*S&…* eG#à@ªúÌÚÕd•°–bV@%UÄpS-Ö±KùÏó˜‹zkq$ƒ„ùøù:ÿ·€šRKŠ #ÈÛãùÖ)eÊzÍË )š§töº7×Î _$«=>X¬ª—~ ìæl<ŒI@Ì@?“‰JF«jÉ'ç–l(^0ï^µ#w8 ·J,઺2iôU½’åó ùL™ c8g-w…×/¤£¿A·[Ùqob$$è ­‚QŠÇXÃqü×ÅmÊž·åÇÓÔ 4(ç¦-_ÉÚ–ÔÅ #z„4J@·PÒ®Z‰§cS'3!¸6'èÅ J7 d›F‹<ÿþ2%¦AYuTÒÕ#¤TE†iea¹•ZÒ‘­ØE(áÛñ/ŸÈÚkÉ'%ÜbF³…çàˆäŸž­ß¼7ohÓÛn¥˜4²’ÂrÊd†öŒLih+95î|$AÁ aâI3©ô¤ª‹¸·¥§œ8CÕB;F;@#ã$ŸŽ2ž>™ŒqLŸ’Œ&>™£5ä6$³9ÌœÌQø÷Ÿ¹e¥*ðȰ<‡l1€Øòzi0sÀ‘ AoåëÚ&Jù+­Ú¬¬*}ã—¿ü%B“t*slEG|¥š»‘ “3 ¯ttw{©JÖÞ˜ZLT‚‹x$ 6ÝjLÖ5iýö½>¶9ìÕRöïjt³˜p0hÇÚÛá)h(O>²{‰œçF¯* >dJr½˜³#¡…R4=|mÎ5W}b¶‰É`>½d°j@u&U1‘;ºQ>˜b‚vkÈn‡!Eäòµùô ŸgwéÙ{ÆFhl€8@/‰«Öb(F½ ¥’?ºÈàJµãÓ$N9$&Ãz•VUz†eý3hî:gÉ~±:ÂËOA$d³06”› 4´}”„qÍ­*wŒ§wì¡2‘•4R XFRFög-üôyýg¤tYëya¡G~–ºÏ-ž¤½Üê“ s™½f o‡)bè ð®œÑª>l|2 OÇ@ž°è×®’I-aUn0‡V…Û¶)‰É€õzh²ñýIC´L-Uñ3Ù‘I÷êçߪÏÐ+÷ÑFʦã”S¶9l -4ÄéU“Õ»Xi[Y I&jé ÍÅWÊ¿lV€²½€”ùhÜ 0Î)xv$Žá™3`nþ‘‘m.àj¬«F| à1°\4%[2‘Û-@é¢Z –M)tmsL›oDžÍݪµË"R£¹Žü¹jWîRL½L¿ÆHšø|¸É~^(Uss|þÆ´jb‚Lä@ªŽz]3ÜDXÀUóÁ$›žOï à1Z(ávVM07ïЫb"ë²PÔ®ªÃP~:+¥‘Oa´¤Ú"ÇgëØß³ª½¹ñ„ÉæÂõÒÏ+ЊwÇå†qŽ<í£±+7È?Àéív@·SJcœF»#,Z©¹gœ¤­ 4À­˜Ü‘ô yÅtxŒ.Acؘîžz)Ï^ïÏ£#>½ÆJŽ¢‹Ñà›ŽL€„åxC`èe—ÅWB˜îŽHÑ8Y/¦Ò°ÆJ›NS5q+µ0% ”Ð'Ô\Ç™Ã-pé 0ùÛªjL¥”ª²ÒõZÛÀ4ªý±ªä÷]ST EªòÇLfÿÖàˆÖ KÙ]ð4œÇsSUÒXv\ØÓÑçƒÌjWÎA~zA#-~„dx[¥Ç¸Ëž=MSBcòòéʹiÁÃu9nh¥§§Ï-E&ªž7Ab¼*~Sò÷8#|³âá®F9+&ª>t¤–4=Nƒ|1”ºr†4ZäŽ<í#;²ª¥ïvǪS2Ž‚Fvl ²My¶ÃÂÐ^X™h‰·0¦ÅTéå òù/Ÿ&ñpZÒtÌÓJm…ܪdñÀ³7·vË\®kǵÌí¹7¡*”úhšß&ª6ü°›+k¹­ŸÙ³`r–œ×ìcfq'~º LÖ€ý‡ ›­½®ž©U4 šr€ßlYlbÛ¤ ;Âd5ö¹Âëšçßi°¸sÎìÍåfÛ~Æ`dãkVCÓÏhtÀǾèr«ö\L„ÿ…dÿk™ô=o#‚} 8#ó'»’Oßd|C3ܱ9j!PŬ Æ”l‡É è“ÉY=MêÅäßH ·z«î˜ s€^¸, —1ªr¿p4ôZÚ“ HŒw\¯ªhg"þ xÿ*P‚¯äõŒ“›ª#CG@¶€jäÚÏKåeÑÚÖlüÚ¦$úV¹oïçT2>mölÙr+YÆË¾vrúHž”ýyH "]0 £½¯àZTu ¿N "N·+Ǻ²ív˜BK¡Š‘;æÓ-0C$˜mJ/ŒQÝ«ÎÖiD? 2‹XK²–áïØJZzÀÄžB¯.Yµ¬¤ËQ¬VÜÊ1²v‘¡ ªâ[ÆYoY4Î&¹å<+¯ ïº*y%X¯R¿Î1R&ž•AI)Ã4x£«zpÑ&ô˜zkTm1#0F§ñÚÛ$«¶¢FȵÀ0&bZ¾Ý(•ÆäO)à6?¦÷#À4(ž¦q P’YÝîóªaØtyLâV"ëqÒß[¾~¸4jiUXôtþÞ€iÑòÀ4¬:ª"óާçŠ[@Wn2AæðÂÜô@˜áYè>òd5æPNV/}xÓÏf÷KB¯*÷8Ä4fyÒ5ò'ng™ # ´Sb˜8¶g>-C¹R_ÕvÆÀ1)uE–ñ¡š&,GàÛ$#çd€ {ýöÚ²6 {ˆtåC3°ª+íQˆi”œÿÈEŠö“«Òó;âW"®Z×x$¬ È90ÝŽ-0ó@lW ž®‰œM2-É»;±/ŠÐˆ§ò+ùåÞbß½˜J0ÿ9“9®¶€ÀŸF žÀ¤£[ÔBóìÂôÇŒFJ¹Y²P•›ÕVL{æÏ*O²=WŒd˜p¼R«íÙó>'ÂmÕhJ¡/t©öàÈþpÅ' Ü·ïõ:Aí=~+mgGκ&Ƥ—ËE2¼qôrã0‘Ž€¬Ôu`@û•œÿWƘzíÓû;ÖBC™@~&-ÐÃzÜðs<1C`+eˆ×û[É6r¥”ÄEãˆÛÍñ,ñ¾2±F³ø(‰Ú·-%Y©›ô8•´'ÞÜ6¡ùô¿ L*²°J˜Âkno.M’#Ï:ïÂlrëÂxY—ýÈæ)îðómV¥t ¤o¼H£ ©*Âôp2²A>7í•äkvÜcÁ%Æ”œ[•‰ªÒÓÎ ¿Fcì׊^/@/RÀ‘Z"[¦wSÅ +Áícˆ‘Ns¤7úø÷P‘ô¢q€êL0¬¬š&<haÇ&"瀌ï;Â2Ÿðö¬«_pÈíÓ †-6óF3ÁË}(=B%+Á‚§ 4ªrÇåm ïsϹwË–! ÁÓ‡ìŽzýÈm“ø3þýY+ G£»Ÿ¾Q€z›À”>< ÑøÝÙ±F˜Ö–Ì,d¼£*ü§ÑR©êf5Hž? Z,Az» ÌM¶ Òð” RÎ 0B=™Ø†ôµÄWº{ÔÏËféê)2”+LÊõÎó¸¿P•›vÔh®£œæì¨4ÞQÔ¯äA¶† Ãi:2TôdH³XT [ ó Óµ˜[âÞyþÁHë—•õôv·ï"S¡D3=q¡¨ª Yè’«¦”ùËõÖ#áñuáÝ“I>‘Õ¾45j™€†!F;p›Î-DíˆsN9~28ªquÁ+51 q<¹=`«öiÁ]‡`7B.ð› ãùA@&XÉUzLûÈ>Ápƒr€Ý"“ ð|>•dJY´#tñýös®WÖ(®ê$ºD-J𕼾T"« lZ*$ÓBPV…EC{"d¼.ϲˈñ»ã•Ÿc]œ«6"½Á¬Y4-ƒôÃøÞÔ¥…•ãYôþøÐ`„>+¥¬Ò;jàlp7—ýá*4;Ö"“±uk¸j³d²LÂYaDb­Ð,ºˆ#Y&SêUÍŠhÛÄ1Ϭ*´ KjW-šÒ—ª)-F©DƒTÝ ’Œg|†Ž­:M€þN~}¾µ u5BcCIˆøJôÓÔk–€E—Ò’† ²õá aþ¢jX xv9¦$+ÒÀ½†ê‚Øo!Ǻ²V:ÿ°‚²#¡œ"²UÝÊ*nÒBÚé3ÁÐÀÞ‘^N?[Œ°ty[ÖâHl\VH#»X{ÖhVzY ·‰FSüx4+>eû s0.r‚@½«¶Uÿg5éùl@ÄÈÏ‹3ÌóÙhJ¡„wL##µ#EGŒ»·³¬* Ce7É ÙQ‡aÇÛôéËq'¼þöÀ] à O 3ikô°HÑDJXn" h‘ÛpÏ8MUÊ9÷àcð¡Å”FT•E£É”È2„EÓ1d®±Œ­0MÏ¥…À±YaYÏ“^8ƨ¦éŽJ™hÁ(ahˆ”1¦Ï0Ob ÜÂÛ­‹+U•»e#š‹§„å”ÙF‘ŽmÅ$&¢#&27bÇžŽnɪjÜæ€#¾ð#œ¾ûn²°Ì¹qÍÒ `Ìm£hÊsÏ.‹¯EÎ3¥c€Lp¨—&Y;Ð\û×^n€PÚz1Üônh|nªUE>Íí·Ù•Ä•zgÌJYLÐË\Œ§ñnޝÕãlp¦©mï¸ëê?Þ×&ŽJÄrí˜x†HÑC¨vÌS&‹±Š_Ya”àÛ„˜™huJŒMfU;‡6¤´F©+pÐØC#ã+Á”¢q@ksVÒEIF Šú··Hb²F§!ÀèRjmÓsh–jS(J21ˆo\×Ißtí|dZŒðÏp~®2Wt=³£’¢Ñ½ ÿF,Ò$îÈù6ëרíòWÒwL YW‹ud(02·º‘L ðaœãí;¿å/ŒÑb‡ª0 ã›uLßj&sdž eÔ(”„£öFt#zJ%L&Öè(ÃñYeR‹Ï¥ïO²&j© C WUn|AO);ªNˆÜèí¬Tûs>”]D ˆÌ\c]¬„£ÿ°W΄8LJ ú~"æ€Ì¼ëh!&“•<¬“3q$‡þx¨Å»qhgíH™’^»À°Ê­–4|"µ7—x2U$Yà šU›w¤†)×›[¶)¥ÂQÀr +ç“ î;àx†ÝçrM»)Õ›Aþ½RÎ˵×%»H_<¸ö3»³‚ƒ`ıgª¡NŒc¾Ík6²I²˜F5sŒÞªÀpžãÝò\÷ý)à[’§Ñpß¼ö^°Ñe¼ß€4íÐ¥¤àŒ´¥8#ïÐØ’rÕÆu|N•A©EF¶[&]–­€ µ-£ÞŽ™  ¥”»~]d‹ª|Râû’8"«"7=ÛæÂ¶rû+ÿ HV^n³ø–£vd;ªb|0˜f禷e¶˜H‚<[ê"fNOè?`4/·L°^ïEàüµu!›ÞWih»Éµû¢sËòFÓ¨:&n‡FÈ3×n.ro]б•Ú°!ŒH©î"‘r Æu”7 nbßJ‘2[]² “5Š ›+ùß`È¡)]­ÑªŽÏ®½O¦”97d%½bJ¤£l™déû ö&OMx 8†µ·[>yÆÈ]–8\µ¡HW{®©”x¸Ï.ÿæµ¼Og\#zœZ¦dB©e™ œrƒ")sK&4"ü| |ÎH`ÊñYqÎ-±ODhiIÀã‹þrJ A­Z£ªh@°ÈöÖÀ³ÔHÀ0¾k¹‘UoO¤H# wd›!Œ.úUdÀ~*á†6ÅQ´\Üñõ/1õ·(GÑ*²¾fG0Ž¢.Ù6•rPªOš6èSQe²YaÊV–šÞ?Qî&í¦Ômõ6EÆ,È8gXoxã\²»Œ¤ñHa̳¥'À#•º¬,z„Ût. ôÏєϸŽCúzgŽÜWVÍ àÓh½ºðΰv‚@ûd˧Wr…–TòìJyæOÖžþ¼¶ Œ7Hf¥½#ÖË–ñ"ó¦ÇÈ)skœì¨1@3Œw”+ÉÎHV)i*•ûálvv#?uû÷ÁŽ¢§cØ"[¯†Ðí…ÍwÍ<‘|VjG9—·€vΪ”a%s 1sp$–ù¸T˜ÞÝóOÖÚôx™ Mb1ñöÁàé1gàž¬ŒTuqèÚ0ªíP#LðÜMKÊÇuÑ×ø´%Øþª>yžZêÚz«ê²C“`ßU|ιÁdá†æÌäÉwëµp5ð©«R÷ÅÚëqpU KòŽ51ÝD6‰‰5ÊédŒ‹‘5ÙÎB Ó7Ì1YyCiüGª3ÌŠL ßD9­ÂdµltÊmÂÄÕ-Sbò!Vj™0~ÎÓkWrÀ¹á×4º4ް ƒ{²µ#Ù¶* Ôkh‘[l¿OÇgËP„)9ØœF 12’U#rCêÚŽJ2Ü,GÿÌéçd÷ ô{XР˺ØÂÂk(ÝuNj„M<ŒLVϳ\Ëî´óÙq¶ÕªÝ…ƒ˜ùLò÷ªm…á& ;”ðdÇÖótù7H&«‘'@™›¬$èåÚé8ÒÓôYä?²6 d܈Ã4)cZcÿ?)‘æVU2Hî8ðÁ ó—E «fHéySÎP ’žR`| ÚJv‘Ú•(¥v(M¬Ñ¤ƒ…ƹÕBy Î¥2¯ „™lV÷ÅcÚ˜+y‡f±™Ì?ú.Òãªý|ñ$pº‹l.%¸ÅWrlHôÃ¥&82GunK¹ ØMdÑfHvŽÛ ŽjìØ£%æ3`4¥Ú>gŒÈ\)O¥4JQÕVª<ÇÓ(õpí¦”X¦éȹ Ÿ>­Z#eb²^È–„ÆL‡±¿ÜQ‰àèîòfä?qú™¨ ]˜ö-›Tñ2ŒŠ•ª"õj ¤¡ï: ûEœƒã¾ pkgÒ2Y¥Á´ñîÅœ@/·'P¯n´Rz€‰7]y:âE-Ú•0üa ²mY±MpÚî’ÙvëZe²&š’ £‹'Cz% KµŒ£0Nö ¤Ì$7íH¥z‘)#}:µ°Ê3²Íù´‰þ¶¾îÛ]Z@®D£~êU¹á‘°Æç&Z:6×wC{Ó1….ˆéYñìS#À¿î?ñ-£ ݽ÷Ä\ËS­}WT®×¸Ú# üÌsÃàÓh„yF: GUb@-#ãË€*±…sH¬Ú²R]€Fzd;¤ARÚÁ;×Þ¶.2ŒÆ>‚ÚÓÀÍÍÙŒj¤èˆOàØÄJçÿ@5 0Þ1¬SRXVr¤éŽ@ú6+c¥#±ØG2äÿléEð"%ÐD-°ìÈ¡gêÅ'ÆÀ9äÚeíJFo±%AC>yMI܇—¡–Ž3§Ñ˜žF8’ÙGä‰!n‡ze¼–Äd}ðdµÈT˵#…ÆòzxÁÇžþ¶‚ì=û³3$7G˜F~º%ÃTÚ†€ÀËi™à Õ’ÙoF¼ _K¶edúÂQ©Àµ³í¨¥}ª~ÏöWTG9[`ÑnnÝS°e²GÈ ©QôÔŽÚ½U1ÂÃêÊJv$Hon[9"á@ƒ²Â“‰ŽYb ½£q-c ªœHÖ¬”Ž5NìˆTS¯Œo4  Vr);àÉjL#«bÆW•±#¥ÑþÈL¿#rn±&&ƳZ`-²M‘ó‡ée8çF`süJŽøöi%úù;†e¼O¼%ñMwLS×feû$É|!MôªÆÁh ¬ÔV0²²)=BÌi¾ÓPY ²%_ÿ- `î•éå¥:ˆìYÅ»·Ÿ˜¶ê]é5¾=d—qn.ÇrãªÚ‹QrôÁž@˜fÁ@ÎÀ³¤wú‚`á.¸R oœù@;ØŠmÎJmkVã2œ`‹% ¾UþZ¥•HÊÌ«ÎÄQ©ªƒ`àrǼ×Ö‹q$в}瘠.íB#¥hzÛš+”+ÕE ‹Õ<}Û9‡ô9#a1‚Öˆß2 äÜÈÚÌD² U1ªr?Až´•äÌËÚ¹©úáîRãS‰éÈ^8Ê»TkqP"–Ÿ8#°ëئËÝ=%ŸºRʆŠ c¥ê8¬ªK¾sNUI>m·q—µƒØŸÁdÙnßIÇøÍjâÈ€ö”Ó7NÕ½ø Ý€‚€'’ sŒ=UûÜ·3·nJ Ë[{GŒÐ«‹ÜrÞ,Ç”z1ùD&kù¶Â /–³.¼˜§ýE1\µÜ kó©”©Z/íÆxS0ŸLž]Jxš&ª"b%ÕÚ«ÊJY¯¡­š ÜÑP¡%ÎmzG&9ÚÓã…£F ‡@$±#62@IDAT±£xšyí ¢ñ2€ÛD ÆQ# ¼)H¡‰Ì<\&8ÿ·€²(·Í\€­7ƒ²ñ@‚³û½dëÆW’ w Užô€hËù´eCŸÕ0q£éÈZž+á«V".,lÕFSb|½tyb‘,óœÛ#T妫/#¾’£Põ)Ê6ql ‘”µX +²€ÜÑpèï­™Žïç0‡LèEL³f¸jæÉà­'PbnOSt ¼?;Î퓹#± ¤é¨¥j£áÀµyyj!^KG™X̶RˤQªª—mÇüaz¼ÜæZD2|8ЕPÒE©š§ c„j¯Ýǵä™,R—ép¶pΔE†­ñl¤Lœ>s-}Ü”µ´¾q¹MŒL™s;h0µ‹AÐ#G6&3¨RJÿ‚Â>Ï‹ÀÖî?íH\• ž‰v½HŒÌ³#ÜhLÿ Û 2|ÓË9 V¢)Dæ•bR6‚?¼–”pkh)ðH8öt]Ȭ«Ê"Ã@—¡˜[c ¤l+¥}-|ˆaÐez&åJ°Xìç—¾Yù XÍPrÙO?p—a!R”cLÒƒñ©?oÛ`-¹‹w?+¼ïãh„Ü­²uâÃôd%‹a”z –„«&#ÀÈ}M2%]"%Àmå8¬×±ôjÜn#äISpÆ7º•0J›hGn‘eJ>°œ`_ôm¨ä¿¡´’jÄæ ˜¬ËV¥¬Ä¤®,”Hkø(õý¡ÂÊÂ=‹ggHÖ%2ÑÏ<2+í4ðrS0}£ð gR—#ÏÄ9ï¨ÅSä ²ö„’´„·gÁC`4LC‰TÏ\éXßHF©‹e]U‘á8s2G$ ïè6qÓŸ&d}èm»5øøD:¶jæ2²eôn«Þa‹ÑÝòZ8ÔÞ¶Ì 0…£hÏ”eß-}%hÞ×@ny¥§ÿ–ÁçÖ³(1ŒÄ[R`8ôÎùÔãÓ7Ú± LdëÉ“ŽÝš!eæH Ô»žÙˆªÎÓÚŽ«Æ1¬½|kÆÁ…FÑVùhtl: 1®˜Üä‰{4 ™¬]  7èÈ$fU&矰‰Ö ÏHÛÖê>޿ɖHæH&–- ã)?KÏ)ºT@ßM< Ý=åŽÍJ/wí6©Ë |Ó[X>ËÝgЇ‘BKL†ðœ›‹!†_z?œÇèñ¤¯™›# e?$µgu»_œØg_Uc¹/v«bÒÀ‘ø‘Ž~8§¯‹I²2=@C ÷ÛßоO•uÊæ:ѳjè<‰ÉäÚñŽUk)¬1½ì­šN_K&{ä¶Ú@#¶jÓÛ©‹@øžô_alŠh–¬‘¬)O2¥RkW‚‹éÍ‘gÞý8½b&°çUʫڹµ1¶eåî°€+¬4æl"¥RŸr2xÎ h>ºb2™¾HŒÞ~Ň•j‘ ê­—tlÊ¢­ŽzûRmP+‘û§‚J2Q©»È}?uUÕ%æÖ¸ž¨R½ŒªF&é 2qŒé©½–4ª)eiO>4pÕ”ÓÔbáMìPWJ>&ÍÚcš¢¥jŽüg ;#9'(cTE%ß Ê×_ÿ±\üÛ`’h¹ÙaÈZEvÌÅC¤éEhj|V÷úm Ógh!‚­›ñ4­Þ )«*]‰ ¡4vÀ;v£Ì9×… ;dõÂmU/Þ¾—xoÝûèM£*8Ë~ZÚ92[¸Öå¶d›·1î ††:öÑ0äOàØž â •ìC˜ÿwhºÚnJF숷؜¢—1¨1lL€Äȶ`múöÈš dßÜm¥ ›$è©×Þzö²Yô[¦‰Ž{±pwï÷Fð‘éµ›%›…ôÆŒ'K\£^ŒÑ­×&10 XlÛÚóAHÐØJæŠvμ=•rX—¾3Û9YØ €L o±üsõöe˼/3F#±ªF¥<¼j;;vG %±’£¨Åцp;$`‚‡ëª¥gW"–­‰cb ¼ÑwÚë/ÆÈÄ2+³º&€l ÎëE6EfÒd‚Fž•’ÑŽÆ·ÐzÊd=¸™X¨v»l1U;jIã˜OzÏxšß?}Æu/ƒ„.?Å2ÜËÄzó‘GMßr{e ]Óµ«æúsìqW;“žÛ +•ód²7¢7®…²ÅÃbž5Î?Þ‘’Þ—“Þî«vü2`)sk·à/l˜ÌQIõðU¯éÀ°Š'ÓÛQîîþÞäCê¡rVbg®ŠëÅ»¦_âHƒšÎ AÈþ?úº»ª ·OžÝH{÷mI¤ebr“}ÃTÛ'=\¨f ´^GU]ý;+˜aÖ(óTõ ž¥ªFÀá˜yÇp$,ð€Fí07™2OXì"H8M³T½áGüé¹Ï¼¹&æãØV}«f.Ϥ®Žõ² X0$ÀÀñŽF;Æ3Á÷qoÃÖ˜&ß(-pÇ^I/¡F ˜¦AÈ~]âk¿’ƒ…jJ-L,€4òÍОù×V=;€ì›CÃ!ÏmH€w¬W•†ÞíLœ@™&™܈’^µL@6 .á܆M7å)Prä¼  LÜÚÖHxû|ôdíÖǬäVʧUa@Ô"ÛI‰ä!fsÏÿ@Ö·ñÕ‰Ñ#rï) :–çõä5v”kŸÌ>¦÷õe¶2·4Z¼Ë)¿£cÓ[’2ç$z ºg>ŽÄ°hŸ9`4jÙÒ óÏ– c2æZ£Oœ¡#àK£ø:æƒ×(×è“c˜ç¦„‰sãS£P™gnöëÝF¡ë}júê iðØ>u©*¹õÖÈꌼ-í3,ð²¹r†s>å+Àhá€+É0¨ ³’2­#ßrr{bŒhÔ¦`\éjÜà«:³æ†áShJ¶^o‚$à³ÑÍÂàÓÏS)YÕ&Ö»ÜÐJéùtltúª°Æ®Ÿ ÝT;*=v‹Ì™T’[RÉ?ç&›žÆÅ»;Sï–¬½L6+³>ø·Þž([Ñeuùn;c(›X¾[;ŠJmÒñéó4®jƒºQ ´ŸZÎmß?V’LhÄ‹Æ×NÌŸ¸ò×OÇZMÁ¤iG³äFpƒ—)ûìÒ86‰ýLö7’Ì4«|v22;À)0¤²ˆäÛl€8k¹ ŨöÖ寧 ñ4Àd=eä™t aƒ1+‚¬èž™dâØ‚#³Ò…/bà6qŒOF‰/`ûz!ë}×__P¤ [F©¿SwqÎøœûÜ+ô|³Å[©eªÂü= lÄ®¦¯Jù!Æ71ÛÈÆÑçÖÃ")aþ¦4‰1{Ø>ÇvPÅg.#u1aå¨*æ7«AiTÍÊ ²»„ŸU|ã2w¤yŠÃãɶÒ›wAC·^¦ly q«v#¼A½@U¹À«öifÛÚ[Œs%ídºmDØ1s ¾H6F•LdEC chê•kϪ˜ü)ÓxOzásÔ‹ßbæ‰'Cjéß98Âø¬é S\ èHŸ[VªŽÞ!ó4ÄÛ„ILP££x3Qš^{J½¡دî[ÅÚ6‡Ö‹ï[²ðÚó§òiÛ¦—)3¤Ö»q˜¬>‰a>•z¢QºQš# ì"Uc(E¶7â)cdL¯zþ ”8ï="¤©@Ïšæ©„‹Ûú)µkJÐ{µGG‚âŒÑÙÒ‘Ý_‹êL½¢–²^Œ»zuµ0ÆWÁQ—Hè™ËdÓ¨êåÖ“ Ýn{º|øï:|‚@oÎᑵŎ€Þ¦t‚ŽUÅÐtl=G MˆALß”œe×Iƒ0®Eµ×pJiàÜ002Po&rÏ…'«€•˜ÈöÌds;–7ñ9ržY-¦*`Õ–|¶Pª–Ó¨:Ê–ñ÷&[ùɧ©½*âd@+¹;œžXã†v¬úeê3tås&Ì{^GAÏß»Æ1HËw”[©£¹­Äg%‚¬j4W ^c‚nʹŒL™8}%LþvókIIЭÛÖqkÓT—‘FTj4†dÈr»É1<Ôî”Û ¦„#뚉^³„ªPÅÈpn¾µ#Å‘ÞHf $(Ïá)3«£¬«œg8«v»œkLŒ­ ¬´Ñ ²yúø&žß¼n%û´fÃhšoûÚmd<}Ñ<½Ï.˜¬$k à{c2‹r 诘¾LûâjÙeÚPæ@I#BµáÙ:¶!Û¦·ŒFkÙÇÜ 0}-azV·ï¤;íÕ›YýKá|ˆµ¯Tˇö ¸Á â#´»—µ•˜´ >å3wA%²”-`²¹ÚEšvÈVŽTÅko¢#Œa…¡9ýoßÇpgðã·‰•er¾’óà;]¨%[ƒ4R¶[1”"~sG‘lB{9«VŠŒ‘]côÒ‘Iº,‰É|%û䆄…ÞþyÜ?#"Ý‹ ”y.7º^ ¤tÈDïÓ”Žý×êûI¡¬ÄÊzèýËÍEÄèëšy]xŒÈ°¹µ œÄßgb$€×Øò2Po]œ·XSÛDoX/nÏŽaЈÖKƧJ¥yÆsh+UŒ¼pô)hä¬1sU-"Ð-à9+5‹mšªÜbòu: TÕì¹ÉämÞЉµTÒ‚T°Ð èëwÞ¨e5ÒfSP×9¦ß¤Ñ›±ÃÀÈºš´¥ R*ó)cz\ >†HA0ñi»¯Ãß•|*díÐ22J@fKÙ˜Žñå6©EÎ6°#Ò”<™„S ´°­´ÄdJ­AfRËS·RPªæISn¬«&[-í¯mðëÆ,]zé᎙¬%žã{Õd2«V5³@:晜Oõ²BvYhÄÓkoÃ4²?øiº äFÀZš(/2©‹LËÄJa¶6é(´Ãd¹©Ú6±l¢\ SÂe¥€AÈ~^Â<“uµ2±6lI‘~€§ªGØb_ Ù8¹Vgž†aoÒn2ý^ÕQPæ }ôñ©Ò°"Œdñå>âzŸ×a؆dñz™;ÆkiLßd]ÄxOŸ¬ÔzUÁÇÀó1"%Œ‰Ì¾ö'‘k‡6ˆ²ÇdËÇñúŒšž•#Ç?cÞoþ_ƒ—‰ÿшèe| äæh7ŒXK%b½²Ø”É”Î7»:åÞÓ¯- qO/[¯’ß¼ø¶àXµu>í§Ê‡@4·wL4B/½ÜÞ4¦``¼¬„±‰–~ƒ‹ªþ§v—‚Û Cé˜mJ™yÏ~åÑ´^«C/hÄ6„#ÉÒ÷—>GV¹%>Ûßýé1ðZ2^lí¬ÝñÚ¼~{â÷]çCC,>ûì3G€@´­ãõ;iJs[¸7¡L&+9îŸÆrÓ‹T²&Ò€ƒêxAT%.4êzJ,ãi´œåÞ¿qµ£Ë‡ÏÈŽU€ Pf5g ç¾'ŽÄ형²0lUﯲ*²^ƒöMË*Õ>¤k¶X†åÕô ɘOj³¼o¯F€Ó’@Çvã‰×…Ïß±O$2ý‡•hÒ[›ªLïÁ8GVm§ÔR8 X‹¬Åqþºº‡Èüã³mÃ|˜<‡Rºx›èÍœÀÏÇ1lŠ`ë( Ǫµ‡Uܱ­`o\²}äø+Ý.^žCâ4×þøÀ²åv“c\H6q ?[`‘OSÂcö7{RÚ_‰Rœ›è÷z¥ó@Öçp‡m $`mÛÞ€>ãuѨҸÌ0dSŸ†dd‘yÕü{eÎB5A¥ŽrúfñoŠ#P{·˜=œL{üªÖ Ð.7B‰­ã‚¡Rwɪ.žçñÉy :ÊŽ¢…ÛÊѬvKc¢/7¾ödÛçôß²6úxüþ[Úãí u„#e ¨Rú”Y¥ìúdŽpzbÓ‡…A™˜¡P¢”ÒA€q¬K®OÔeÐ¥ÏQÀ¬€3ò:ÈwàëkCП̑ÉsŠ5Z ù\»Až´ ·Fì.HÌ^ ®²F€0]ĵt,§ïFÖÀÛÏÏ¢š•ÅšÞJ¬È”º#ÒQæS{æM$3( (u_8ó–'”d|þ5ÊÏ 4Óô¹^%G@ʰ#¥®ÖkJbz§/׈L?1½è l÷å™ 0ˆ̬ 9gHn L“²v؈å3ò~¾µcjG6WHLïFjA:ÂMqü4-,‹ÌÛíøÞUǬôò1¥ßŽJÝWûÌÉ„ªŒý#ilSå6FÔsÖ¹O‰œ¯Á™Ž¤¡' HïWRÎÑ­ú!'˜ƒÑ02«+?z@I ІݼúKaòÜÓï8ë5‘ A4VùÈŽLRö)"cÙ*a´0y+I̪×yÖ¹p3+Œ^™§Üb=]w·@`¤œmÛjw̶Fnr÷‚‰[¾µé‹Z¦ÑØjÎÈyÂ9$sDÂÝ‚[GCɲ͓C-Ä>šÆu¤lÿXV¯®]€™I‡ƒ˜µ´@]J‘2LÃh[@´Xíø¦g[Unzž+9º…’‹´¥*¾qJ1rªR:š’'¦ˆ'ó5ÆÈ sÀÃ4Ú#ñÖòZ öôí£T¤T¢y~èãU1O@¯´Ø°WÅ=x¹cüfñQuä¬rÆäÙ†MÌ¼Òøua”¬°?rß™ÖhY·3BÔE©Q»oÚ¬¶<^b%O™[bXÀ4{‡4µpÖè(jI¦ä ÷ï!®êü¨²íFJù$v}Õ|dÇùÀÚûôJ•ÂßøÕ¯~¥A4+²n ¨g¦‘ºb¬^»1 «&fÛÃÉgÞH ‡3ø~üôÅ[õúÑÀU·Ò‡JSZÀ‘Oþ-€$‰±%|›«&N¦J¹J˜xØb;†éE+µFû÷h+õ;NɬÄ<HàŒé©™‹µhܰ.æiðg‰ûÍV8ÈíÏ™Ø>€ñµÇwúßß] ÅS:êÚè'¶$®ôJŽ0Þ¬z{J%L]4-ÙEKÊ‚^Ì?Üx€ ¡‘ËÕgWO¡Qàë­½cæFišUÞ/Ðõ’ †}‚aþ¢ »2†¸‰L„cŸBKÚ;äIà­ôª GbÇž…[z9db º‹‹×›¾ö´Óä ÷ÙuTʧlænÔ±ÆòYñ.Y AŒAÏ…’ÜÐpzY»Ñõ:¶Æ—Ý´S–›X—ÏÅ’]Pbå8ÿÆáMlŸ­Eiëiq$5ª@ß^üöIì¸Pmh°FUÂnkËŽñÈœc”Díý½Ó±Uéñm›…ίqO§€Óù’)ÁÈ èníšÅmz%úòìÄ•­«…?·&ÊJý™†¤'µË0RÕ)Gæç ( |€CoÄCT-w¬j“­AŒÔÞ59Ó7¥[L—ʤg{Nðéž’•#“œŒ¬Ô>nÉŒoeÛ’µFÐÓ$ƒ•âÉ#„µ•b(1ùÃÏϽ;¶yÎ9à90gÒ½Ã9W:“ÞÿÛ*F»q‚Œ„kLjvCÚÀ¾ÐmKÌâ45¶a˜€ÌD]ÝBVÚ”HG²0¥®>ÍvÀï‹Ô­³ÍF 2>B—,IyþÿøÔB­ß¶QŠœ€”Z¹öãrC• ¨vmÛ#û-ÙKq£‘ûÚå“s¶p¥¶gU‹¼Ñdpãâ+eˆ1:Á˜.b.C[y@u>@šz•L!Ëfå– ¶<CJ<‡ªíVoW£TkTŽr³.÷º,^DfbJKf¥Ô8¶[¤%1®œ¦Ñ‘L|.xQ×nÚrÖâØ­JÆ¡5ÖK\àïʯ*·ƒP¢ÄûXa ä©%ŸÖƒ-FF «^Ó¢$È*áa·s$K\Æç@4õÒ»f¶Æðj±pJ%ÁD’Þ±€F(‰Ú‘áËM:fBÃDN–&9Ûýj6+= cXZCyÁßú[Óò âa½&‰¬ä¨^Âíܸv½[@¾=ߦ“Ú¸ræ>`Q©®Zrëv˜žˆFZf8¥#Ðþ›[WbÛ¶0’Ød™tln;¬Ñq?J¾¢”cêÕ-T{„7—ÀDL‚§l^ w¼ô«dh³‘Ræß&vNp~1iR&"O÷í¯nL^.ÌèJÎ 8YÖ”]ÌÈ4ª@G%G˜ÚåF¤÷«•*±Òª@ëU‚Ü­𠀿†Ø3!ázàkgÛGkz ÜÛaŠL¬T5Šle˜†­•ÎÔô­ÊÀq9q‚z3o&RŽšâ‚{ZÃ뉷ÀÓêiH&Ú¿@òt´µjÇpï „d[®‘“[]µ$†3Ô¢úÍo~Ó[Égéÿüç?a¥˜|zØlc<]¯—2·9›"ñ·g$O·CnÆD:"는…ú–8&ÛiŽbûû8b(͵s¿(»™#C²ÞœO]íßMg§®özÚ›¸qô}Xkoº.‘¸MäÞĸ¦äï˜ YWÙ‘•’µ[•ƒRûãašŽ4b†•bksŠõVm%Ǧ$sä zÿžÑ‘`/ÌMµëׂ!H¦‰˜F ;Ú n(C]x + Í“=K°à™ ,ž›hïî4ÄŽd·ï¤>M%]ã7:Ãö!¦©/’e«D–Û±­l3äFŠî¬ QIé8²Uvìݱ¨Wö^º|U9+ WàJdÁ ð;iu¹ ‡ešºd8ì¸Ûâ¦Ñö²Ýè¯äŒã©_; ‹ÀªºklÊu:¤£ÞÌ)Ÿ¡% =™¦²MLÃáYM†iôrwïñU·[ ðií@Ó½XϘ†Uw¬×Ñ·¿c£7ÑãÓ›óvTÛ_ÎÖž`Œ–oûÛßúÖ·üö‡{]Å?þñßüæ7Ÿþ3e¦¤¢ûiK}=©PÝ SÎN/q&a9s£É2 g+ËFÇËõ.÷«§0Tí†U™ÔÅ^õú@Û¦d•,VU"1ŽÈ”õ&“uÕ8Ïô³Åó‘Û§¬Š¡ü¾a.h¨–l (…¤ã¹ÌÝ Içïè§”ÕëªÓ\”¢A^8r½J9P”´; z¤h¥§XÕ¸œ ÜÈVþ¾ÿï|ǯ§ÛôoÒçŸNéÿ¶¨v½°Y}‹ú—M¯3Mׇq½x²nª–g›9Ûª²’Y~ƒô¹e‹×›&‡ s¤Tb˜J%;  baÆZð@n@[Yƒ€?ƽ€ÆÄÏ.bD hAÊ—‰LOÃ6“üYÑ+>¦¬,£ŠGjñÑiiœj³Ã4·éÌÆÀ6þ\ÑK,('Þu2©‹¯gÚÉz.̦Ž1 sn7U9öAN hŸ†¬ã˜¶’…ö¢Ãø3#_í+Y¦Y‰ÙjÈ€‰Z„R¹ÑF©Š˜Zhð˜x9™µ?ˆ!>ßK‡vê¹¼ŒivbÇF:£û³íÃÛ0<Íôµ'@{#2ш¶l.¦HÌÏç9…Þ÷ F©ªç6Bo|ænn"f7Å; ]-3¦¹x€¿2˜Ì>î ëôÃYµ[øhS²Í¹­tuÕëñú35OÊ>$í­ZÆp½OS"Ç%•, 4ݸ€Pv0+ú€ëBµA2Œ©K‹71·—Qây;^¿a­J)·p²›ïj/ŸÆåà3õAðAZ 5”„£®ÈÖèv)÷2þÔq)¹ÿ2•Æü¿¼†v³þö·¿ýå/éÿÌuþ==OŸQŒ¹T Ü]^û´^kÈŽ ™4T‹Æ¾m³M{ê˜Ú³JÐËÓ8Æœ î›!4Æ·Ìœß× SIV’·Õuzý_°¨‘¡‰û’ô™æPÌYð!æÐ8]ŽÝK)A%¼ª£ÏW æŒç >‰á£ÉÚ3Yí]¤eêí²Z|²4Èç5gž¿Lÿ\µA‘­é°AÓïï.<#ù2ÌnÚ-øçi" 7¥diäñ‰³Íp›OÌ æ¬KÓ´$[” ^ÿ¶±N À€ð£’®c|^ÓOÜÇ6ÏÐìEŽΰÞõnÖ|8ˆŽ­DƒézµÌ0™c@æ| ^ÿç•:–«2œ,¬—zšÔetþŽÍªkêhÄ´§/´/™£FßÂZh˜¨2‰wª‘žEc$ ³UU‰‘YUÅw¾Ü^LK‹Ñë5Ë$P£#Œií@K6¢#ÿ‡ß¹–ߥ×n®¦´­z‚¸wö5úáß5ù¥Ï$òk³G ßýîwÿçF¶F›¥#xnÛ˜­Gc yŒ^A†ï‚>G¤€Ì'%÷±çÚƒ¾é³åF +e «Êº€v IÀ9|O1C"žl‚Ví²øÙÂÏ/X«Ê‚†•,šÞbÉhª2'hz¥U|w ¨Öezúª”Ýݱè1x²<1®ìÉÔhÙ1Yž{“ªÈ”ŽœÛÆr]@½JaÕýTb"úlª¬Ú-U‘ÚGoØ kyþëdû-tþn¨3u¢ì¼ÂÈxYÐ7>ÀÚדµLã¨7‹g#,òoï@&V‚»C½•Ìj·nµYª òyޣɇ'L ÑËëõm-Óù$Òd"Ãz‰5ÊSjÔÕôôM1‘Lªå¦Äëòy´XÙÜdgÑþg_Žª Õ‹Ï ø;©éÖsdÁM´¿LÖèÿ[6qð^ ¹’¡›rÕ¾Žv˜˜C>žôï7÷žùÀ"\ã3Ó»` àß#ù½ï?iðKü¿¹¯—üñìÏßýîw6g%¬á‚w£ó‰ÓÀíl4œ&êé¹ož ÖÞ­YÝâë‹ÁÄ¥H2Œp»Üºf>•Lé1ÙÒ 1{´˜ÄF8¶%kIܸ”ªŽ~kvƒuqæ Rf¥W „[F£ˆ)kW‚[&¨‘![G$œ²vÇe¤°¥–)óAJ€ªµMt…nÑtUß:% à‡ÓÈ<e‘Œ~‚üka¤†‘x÷€Ú5ÙÖ• c·^€I9~2u©=Þ#r؈smc°jÔ Ý_ö.‚˜Í¦Ü€Œ`¾®—¾Ë”3ÈÚÎpOÓJHÁA6t€^´0€oO²6Ùs';.·”L#n7%ß~x{*1ÁȪûØüÅ\_Ë3#í +Χ›ò­A߬é*’½OçúEæªý¢wö÷÷3œynÌ¿:øäl·÷óùÂ1ÝÌ9GV21#LÙ‹m ¿yýÎõV9û£Ë?÷bd‚¬õú˜(¤A½*¦MRÂñºÌÝCJ¦J‘̶ü½ï}Ϙªÿ}öÀÏþsÿÑ´ýs»_ié®às±¤û¶[%«ªÖ¢ ¨"{½.¥¥R•Œ'««¡L®C¼×î1e]‰éŸ€œØg¤ÑÑP† úáèé>ø?ô½¿wøõ¯Í¡Fžø'öjnŽx»Á¬`@ŒìöÓŸþ” ¯JùÜ!¼MþøÇ?~ñÅ‘-£˜-°;ÚÓäøôl¥ö©š‰’#>ÿ§gØ’4fAßоŽ=’ÆQKW–{7|ïÓW¨£L©WîvÃäÃ5+Éb‹š(ë•‘"Ÿó/%¬%rì!”¹4/¹¯ ÙA¦º¼¿JPÆ+!çŸs%è}ÍrôÄl-zŽ4le]U”Ù²¢ï¥dÕ¢^ÕJ€_UÝ.†ÀpkŠFži`[É…õüR“U5j©ÄIàhÝ®U[II£#%@ÜzøÝ. °_áØnª_LÌålœ\ÄÀí ··ôü…#^˜î{â¦Ý1ªM„ß¶~Eö«ß¸ýõ¯õ†_jýö÷,L”„¡&‚˜ÏÈJ<•`Ù4-™ Cd8Ù÷¿ÿ}¿¿lÈð”6k§é}ʾ{öýèG¿ýíoÉøð”íév´§WÊÜÝÝÚ†x£“Jã²Zôv¯ÜºHz¥<» AA“O@ÆcÈ2tä)Û!’Fi˜s]r_`íôVrÁüàxÌׯþð-­·mã Ï òvÛbþúò‡øoWò_óMãY5C±é-†±³[ %…±’¨%>«z3iùñµ8²õÉv;™Ø&"@à<}š•OÕ&böŒÛ!ß2ãð€XoG¤j<òªN‹^ǀƒ¢ûZI¼~ÏnFŽDzž‘@¶_ßf€€¯ì²^7ƒ ©v2)˜ Ðö™'†{Ãjšf=n•ˆùÜ»œ“¾.#ÒËY™ô˜ŒFckÈÉjìvü3¡og¹•ÖÕŽZ¸ùù§1DíÛgSÆt5$=ìß`ø«Ðni¾:›åš}á,c7áØk×ëh„j[1/Úsâè7B%›ãuYFF²òå¶žÇâWÏ…ôKߤgNßõõRÊ êí)0€AÈla‹­}%½‰)EËëuAåßÔ‹­A,ÜÔ/+ù·J”}4òáàüá ‰ÿ“ì²þ²É­[h±gíÙüñ}šÍ2ެ0°5­¤7Rî5´wÁFÀ4½‰.W&êÚ;·U&}Ê¡]oíĆr”ˆ ÇŸüä'˜®óÕÙG,v)Ma+3ß’F‰a#`&]ã(|޾Q_½@U¿ÿýïe]-ƒwqV®ŒwÌè¹Ó"Ÿ²Í÷Î[ønt>/âVuµí¬e˜ f¢ fUä&ýPÐÄïŽ> ~ê[;-|ºTûP:ÆÀM!³®3ø~I†•0ü14âüדÀŽBƈ^ˆÑFsÏ·ùØ¿wê]ˆ½K¶ªôJÄJx &çö@n 7OL&¨²m“Jòº¡±›B°Í1½K>+$&CdSÚ<$™WKF?™¹p›DòÌP‹ö|ÜÀcdAœžƒßA~Õºx€R$øŠÌ„›¯»Ìß<ÂQ¶ƒÆ¶Œ ¶O{2ä­çð© &ÐÕû;¶ +تý·øxJ¿þüç?ûm[£¬¯Å>ü#1Žk4‘,¥\#YCUÃÉXÅh¼›_âþK¥º2”™ûoïØG†Óš†`PšŸýìgþ$Xï××HÆ6óð¹Àã×Ë:ÚÜ,JØuº8²^í%ÇvAúü5: ›Ã”‚ 㘘¶I$%\U>ÍïÒ®ª‘Fì’Vó×å(jr¨Ú‘Ûø]©Äy-1̼­ºÚÝâ\P©}äÍmç"D׋w”¹‰nj"¦Ä;¶°ü¿”ÝMv+Ë­„Ñ9¸ã†ÿæ?,7®^ƒ×ÛY§Ì#Q|hÀÈ@ €Ì*)Jç:áÃã@<¶ˆóÿß'¾ Á\BRµ®Ÿa6˜Œ>ñpK#Ý­Ùàæ„7¹%‘éÀeéÈÒ# ìYÙŸðãT"åØKq: CBZ¢YÒ,/¤¦ÄrÊå˜áÍܣߧÅj—òÜ÷GDGáô“­5<²¥‘|­ÿüãóŸôµ‹MµØÀ†Ñn]ÚÂËIª‚·/%ÈMØ`eÍ&5\PIʵè(:±Uhv«‚xýbºgxYµ  Ð¦>ìþç?ÿ!BPy“SÓe×— qžÕ³MÀ•´‘N Í-öåOÏÈ{󳻎âÅͦ(šg`ˆváÍo6ç›J!³Œ€¯–/Õ^è”UŽÃÊV+v8 Ã뛎B_àÅ+JG\IK±Ú‰[f•ðÌ´ Pê®Ó$ÑxG}^Û )TMê–bx{#ŠÆ7ÙUtŽÉ’â•à§ UŒÙ™ª•ªK^ $â¥+F“JS¬—eüÆÆA– ä1ù&—µäeåÝ•Ѯ䯇 Ðs-&O­mÖ­×[KÞ„jWâºztzÐø¢¡ÉqÞ}/¶¾F7vK%º4¶íhAm‚MÂ+aF+)k)ØÆ©…óhöØ hbxZókwØ`ûD,U9ÁTÓ*L6A  ƒ ±®»¾LŠE6-©h¾èÿÓŸþtF¡Gÿý}˜&©–DTñpjpÞ{ÀßÿþwEü£F¹©±”dᬾ»]Ûf©h6h©êÒxÜB †GÊüìÎQÒᔵԨ­y ]wÊ‚¼ ‚9ÅYú~·AœÂÖM›œÈJ\JÊO”mËíÑRS)¡ÀíQŒã›÷ØßȾüQK°CÐ1©6bYyjj6©…X ®œEn6/RHL¸ÙÔBð+©‘XvXž-=˜ ZÒIJœˆ«Ð$p æÄ5ªp„ƒ¥o)`Ñ—üãkà‚‹{Èh|:ÚµÁ¹š¬)y¹æˆ$‹S¥öIHÁ‘yZ<Ü HsäeëRÓ6£ ŸOV6šòbK –MÀʦ#®àlìù:§Ìzš ´«*O¹ZžY´‹RJ’Hµ,@R2ð8ÿjFÊ^‡=ñ}Im9©¿ô •3Ï}ï…‡Ù… ^;{È –ødMk)æñÃóÈ…ó(OAm @ÙbxŲφ^–/ÃëÒ_Çã0%̹),„…ðõj/á!—Ìqk4¤rÞ~ñYÕTuÉ;(_JøjÞR9šZâ‚bK'ö"®/ŽÃ‘ú÷¿ÿí» ä»ì—1N±…uifjJà5­¼Ë¡‹lðÕJ)d`ÊÕZ2)"jÅ’,K¹Â:¦OÈ3üRø@K§$Hm‡£µ/>ü ÙA‘¢™ŽH­¦:ÊšvYeyL¬{ÕcÆàKYús[4ÈæÞóá#ñŠB})xY»Ó,‰Cø˜‚æYÓ«è|r2fd“ xx›õÚDPUkU)²ã@šA 5K§¦µj)P$R¹FZO-¯°MñøAAÀpÄp »Rð ùó®hܨbl¦YZb$K-@„Lf©S¸YeÙäúC ©4 †¨R›ŽF ­€o˜Jp,I¥#`RÍÖ5ƒÂZ§Z± ©¥L­%ZãM'‘¼í÷óÚ@‚Ôú½¨•{ý¾‹Ñ^â¤ú¤ï)&@0 ¼1xï”ÂÅ›¿K[•Jd5#yb¶5L ²é#Ðl§–Ê-mÍ£áå;)æc Ï_^]"på ™8¼•ÀcvÑÝ‹?…汄«õVêÑÿò¨¢ãS?CÀ¬]-ò—ê)ŸÐ9 êâ§Ï?UÄãÛÝ A &hGš¦Ó±ˆCôdjeÕº¸œÈD" uMê(h#øl˶)U¶Ï1À4V£˜NÕ·.á?zOï"nBU0'£\ß@|ཀྵýZöU[‰1^Þ׿›Ç ®¸BÊ5˜§^5R[ÀK!01ë¸móž‚{ÉD3ØRüvZ|ØFâÜ·¼QM˜¾òð—.ÉbÊŠËn©p&ëÞ@c@°dÇãLD¬0òyca.‰µfL [ü ^·øîT “%'Àç5k¦R–|jÅ–MY;LËt¶%ü@YÖ²– ù f”áîuq½²p ÄlD6j#U¾Öøâ–éÜ[+—âK¹w}Ì÷õ¿©7¦»[9k°>ïW®—yŠ›¼! šÞ±7Âfó€Àd8¼«Ù q:®&W(Àᯢó¦ïQèk–ºß·€ï³¶_öÖQ >YP µÝ$@ž&ZËÞÂùmD–MJܨ ãÝèeßûªþÍÀ³Kæ×§-"Í#èM«Öh÷€”kÇ*ÿÎûà©ÊÙïr òxðóÍ¿T»ÃWØe2XÛOjû dÝ*…w…+yÀeµëú¶k ·|ù&­á¿ôÎÙ/WÔʶÛgC€–í®ñòv±™Û‘kÑJ¼p\â/û¾€J¼Q&¢Ýøý6®J—& ¸ ôX6íÄ-W‚ÐÒØ4‘uÉ B».–²TÒ²CHm²•ðpdÊRæéº+´d‚ q¢-%«¼í 1 y&…€,Èò:öܨu æãY¿*›5 ÛÀÓ(f¦u¤™T»Ò¾Ú ¥bR¨Y¹¾J¤,™@¶.8Í®Ãâ 6À™æÚ$…::Y»½¸ÇÉÖ=åðâBj­#PI}¥,)[ž6ÏCà>@õyßcw)øsß{ry9yô·»)Ñ«mŠ©Ádw‰Ôö« ›ÍH=g¥ Ê!“ª¤¥*AY´=škê#öwŸÅ ì¯à=1ëNd»3©L—–º7Ûbûj;Û”1dÑRPk)ö½°þÎù)|þ­÷!Rí·ŽÏ·›''úÌâÙäÁ|cD<7=÷™0ª3Íó–B÷T*æ[šÙÁš¡{³cL§Á¡V ¼ÝIi*nøfDóÁÜ£Öw>ßÍß¿ûä¥ãºàhÁÓIJ_„@4 „xÛ4¼¥GŒÐœ<‘hJ”ã4€y|D¶Ì»Mâ$Ãy‚‰¤Ï7CR²Ñà5å×EŠI9ašþ}“?‡¿·»Ç¾)òÎí<•˜ˆBÒë¨ÖZÔ"F7¹AüðD,ÅLÌÐ0_;KO!—…0)ñd”uà;YK¿û½—Tø¥÷Ø¥¦0e½8XK:ô²ˆÜ{v½:œâz¹å¼šŠß{Aúò‡TLû¢Æ,íE#²ˆ‘rÀhZå§ò:·JÆT \/Ëé¤ìâ(ÔQVáøÍð»¿QuW•š YHK1뎅4CˆeAB ©{²Ô€á5ÝrLc<¾"èNUäk©ÀRüRo 磭PÌÚP×Rýh‚µäc¦¼ÖÀJ0)•Ó´¬K§C‰Ã׿ûµ.ª˜˜Å„ðÈáu»§=ô}ä÷¬ŒoúeÜsß—æ}u¬0‚)«å Ûý-¶G)K,hw–}üÁO¶±éجBâíZ Ťøº×Ѧü n7Ã}/˜‹^xªlÜR¶¾‚¤øâ7Œ€¾’|K›ê6ÐNŠ5ÉD,=Ìóû2Á†éѦÐ~iòú¶TÛlÔ˜%/…Æ‹ ^­®ÄÒûœ©¾üZÜÛƒ7üö¢JP‹ƒ“JÖ6;yAæJÝg@c Yà­ÚqLÅàô âÔZ•eÔ”°eµF³_^\;OWçGóžçV®0e‘ÌéR¸ý¦AV ]c^9³TGÐÇŽg@дÿS ¤(0MñéCRkH3Xʲk_7Ìø1ï“T¢E…D2cظ­¡­‹>&D‰,}ËD6Ccç•„ãLª–@R‚,AµõšrLM†Gà™ZüjÓVx~Í ²6+oÉ7ÓH¨;â@Ë8jM“ÂbünAƒÞG‰ )K05A† U–§ß)‡ãÔºS¹‰«Z€o-òÕ!†Lü4»J bмËì6í«žn¾ho¼†—§•Ï,íÔ<R: to³üËÈâÄ7€ Û¨-@zWç›VÐ<&·ÔH-<Aí"ää3¯ÝUþâ5õÔóXLÁ«]€£vR; lûÅÙÀñÅøh²âvÚ$]e²¾î÷xªÑæÁñ9ÔÓ¾C#2)Áª KjÚûeãE躈~à9î'´JìÚÕt&¬u}Û„&\ëåJ€˜CÒĘ­eC¢ií³‚l„|Ì {àz‰ð ´à ^fM¥Ð˜”XÊ}~ùƒìØé»ëR¸”NS휛ÙÚ£@;WªF˜b†PA—ÂÿüË—Þ Š~÷¿ÖÊYRuO_w¶” ¬¾‚R!nK¦üT^`øÄY"Ħv'™F@å}H3YYåÝ !È@ähb‚ÈWøèý|ÑM§lUJUÎCdÅ.–eMyÊ1Ï,HÌf$¶œ Ü2ÐR Ò&ùÔ˜ë?DV@SyF’”—VUu‰ ‡ÏàÀd뮊ƒ‹•㴌ѴZ1NxRk¤áh]›CÈŽYìÉè×S¿EþÝ”xâ»M}brÔΘü‚::FM{ô˜S-Z/Àì´S°5w?²§’V-„~q%jÚQÝ1µØ×Ÿÿüç=éd聯¿‘÷ìë‰I2Ai‰Ó1j-¸g£µGx)`¸÷ÔÆ«c|ðÿýÝÓsÙ#X-~[¨ÄR K‚¬Á Fê("ðõ2³3ZAœô}Ñï"ÊZ²í±.<‚@/AÇÒ3Q횢¹pJp´»5•TØëHœ²¬ÂbÁ† ,[G÷YHÃèHÓ¹µ )„@µŸ?v=ýýèC„¡©œm³1KÙRˆØ$(VÏ{úýZ?Yÿó¿îvW¤o\•·Íƒ5Àd5í!b§½+lxA;jrÍÂÛ¿öáZ°µM™N¯£ÚYÞS@K38&f÷¦øk*ƹ÷µD6p 4<$µb©©Aè\Ýo]‘Mù¹/±ñ:Ž–µ¯GžDZ<~õüÊï·2^6¾x3‰»*âõM P9Ž˜¡ÅLGÀÇiK4ˆ‹/§ãXº™¼¤=€àȵÈÔ1Ý@žûnÐ^]²ïÍ´úýTñ}0…dݼTëeíXK#u§ÖNª@ŽQ/úãALœO¤¥Ý»lü ¨—OÙ¾d—úÒ|õ+_gÕ< ÑTñÆ(¦#î¨ùpL´úŠwDa‡àü‡•ûXêg¸åÝÌð¯ýË;k§Ú ÊuÚ¯!-¾‘ij”Øb%uQløb¢mï}§^‘Óç‘+„w1X‰ÀËdYKÊ †ž¸ÛfœÖZÐ<âgµKh6"NÞÓÿÃïܽ÷{PÈê• Žlâ²Íl/zñ¹áö+…‰/¸êO:wàsêwÿKÇ¡j;«<µÄùšbÊÖŽ"PSŠB§cÙk$°ö˜)…ʼn„ð ëÅ[VÅ'¢J #[IœhjÇ–‚rA]ÜKÝNNòÎQØ`]J©æ³z †G†´e-R†ãÀ_µ¨}›o3p&æÕ$$°Ÿ–µ¬ÄL½¢AtR… fÕö" 0Å4«­ËÊ¥†§À3-ª*ÕÌ©Ñw/:^ìeÄÑæLè+þFªü'峉§žS‰ÔeOa ©é7C‚Û;‚“¬×}§Í©VVUœö懓Bhwb…”§©…X¡×Þ›_>ôùì_»JiÎâûõmø5tíÚ š €b¶ä‘}åòåÇRÏ œƒl˜üý-; ‚pKÓ¢¸^Û>Ž^[âÔ.hZ{„㸲@DJ@9&Bg«»˜&_S§«R˜&¤ñxµíhú…8‰‡7>«¼Q5µlûM›ÄYiœpFÁ‡hçÜxï½Bߺ츶)Ý鸅´€oHƒ¨RåYK|Ãøðá•ø~†²þ‰F¿„P•¬@Šg©ñZ 4â5í…N`÷ÒË„ÈÔ‚Q®*oI -&šÀe’b–W8ÄQ ©Ç§°«Ö?qŸºN³ë¬ ‘SC®u OÇT¹-@R¬‘{;sIËÕÉRhA©!vØf¶74 Ú¤Ó’Ie@U¤Úyq * oÉðźÐd–½QS“•аxÂÉâ¨0S"Ž&+€(‰†Âkäûüe14Ÿ‘}äïÛd](¯‘ µðz«;‡²÷‰Zk×O!˜b´{GR™£¸öq6BD­%fOÿ@²RÑ@ȪÀô~íƒvå÷Ž‹=s}ö×hUR4›¤×Oš•^Ö.ð™Öu/ÛfÅRh–²• ¥¯¡¾üë#o«žþ  ¯*e¸¦¦b‰Óo×ÉZbê(H /Õ´RÉF–"‹ Ì7³ZPkÌâ)Ö´ù²È–b†€|#RÇÎCô­uËy:¹kYª£¨¯%œ+€0UŽzø÷ô÷9@ycW55vøˆ†¯oâªà‰àþK?ùù)ÄíªêÚЯ2½´àw'ˆY}šØk-©OCKdãÉò¶† DÈ+¸sɆ B)K­ÅíšßkßRÇf³;²L 0œ·LydjðÈRcB´æ!8ÝÕF^JPÓ¦:¯(6FiK* ÂGk²æn©„Ã䓇cÚ§)'‚P#—mÓã¯Y%‚®®¬eÖ -ì_@AÉËeÆI­Á”«e…È>úà¿‹÷hðÍÿxôû«þDòšj-®—˜rߟFHL ç` K¸÷j¶oòRâm\`ïÈ Ï#·Ô……+ÑÚRN:p¥·7€8ßÍ3×÷-øÈhúêNÍÒ^:UU) pÚoRp{é†nþõÈ6| æ_þòo“¿Oâeïk];˜½óéÒ ¦ÓTbH}‡Çi#ª˜1â‹ÑÌ¿r¬]„&ŠS«‚O$ZÌ w{ëOßñªðª21Cc!ÍÜEo<%Aâ _¥Ç•­0ˆ›Ü“wœ7ýä>Àøº†ÕÅ.zõÁñáëÛ} 1a啸)ÄTü. Ó—?ínœ`G'›Úúµ֔µ…&‰o›³ŸóÄà&,x@IDATRá1«B£ ©E]&‚Â÷ps:º» hã7yãñLX KíðY3 LÅÓDfí^œˆrA ¼T>qLàj籂¡e<éHMÖ% ä'‡Ì,öϧ¬"Vž_y"-:‚X 딊æ4¶O¾KBg²d)Ÿ¤$q4øzÁõ’zúøiô÷¯žSxñ>¿ûÔkÃNS …c¤¼F üе¢¬Ù”ˆ•0ÝÍ1Zˆ,œDV GÐmaɶ)qí Ò‡\ÝÎ-âÑÿþ[W?ÐøK;Ýé'¸F¤Ì™`óXÇì`Ë*qJÈL8ŽÙŠ£Aú[O[ ¹{/{oJˆLœš*¦OÈC/ /•~…bÊá)⫲;àﻲ£MaUõ‚ãðeõbâ®)B8_\•¥€gáËR+o éCšß0^†"Ëf÷¹8G÷'£ã @Oƶ?z‡l‰Ð ˆ;aKƒtâf0§Ø–‡ñßÿº?|¹ùàãF™ˆˆµ»£y€ëÛiï‚6‚€I!aÈvh´kÀ3¹ªm3~ ÖRhÖS˜l RzcJAX¼=v,¥zÑUòÞûç G9ñôÛxˆ.)7˜Í2|xòZÃe[¦)쬌gY bÖF0 Š‘ò{*9S4²¼Fõ¢ÀZÂÍÉ,[n 1Fè½ÄK³ÑgM ¼ôÎ!€RÀưdZè *·›™¸ÿ‡Õ÷ïs¾Þñ²OD¡ÅÑ^ô‰ÌÀZ˜’!còâ4ádÚˆe_¸=«ý/M_ú{+J¿òu/X_£©¾êÛ’ˆ ,Æ ¤ Ph0^‰%#ÛŽê«$Až>‚Ç'A¸`žŽZÙúò/¥œ!Œ¯¶ó‘6Rä)DN³ÖbœtdÅd£‰¬Àˆÿ£9|O/“‰¤ KçPkʤÌiHÁ}|8«D€Ðx/ÕÿûT˜nÈ·B×¥÷NK-ê΋‘™+,െðøh=…IË&+Ë -yq" ª…ŒƒŸ/°Èñ›AÇ®K}K‰Ì0y 4‰íÐd8:‰!Åjí\ìBž”%Ÿ‡äÛ¹eG&«œÉ2T^ÐóT°s‰i_Ê ^´> ½ bf¾Íðè÷ª¨u`»hkûêÈ€½[`Ú—¦˜D•,$5±œ¾[SpTžÛl§+Oj:wf‚Ê‘{µô:î9UöwùënÔ»r½´ØH{åtª÷³¥l™~%-‹É¶¿Šø} -|óã½VJÌ^IFÂ[ ¸.|YAÓ¢µ§!fq’ I MI41‚Ö¼8ñÚá@¤4u‚æL™W‘%U…JRÆ¿T éWÎWt©Aš\!¾¥”˜Çor`3·Œàç?ÁUñÎ)ñ»_j¼š šM™¬îRðHS,µ mjåµzãÿðuçGm/:Ÿ]Ú…ÊY[»ï¡”^õµÄQ%(V% ©ª9»!. ZµíBʲcçãâ÷ì ´^}Îå3A±¦ªZòJš_@¹\aâ–¥ô²ì2ýbKU‘‹Ûx)Ó|±ŒOøë–¤kŸhT~· )G†Ü1íX¾çUÓÁ‡[º«:q1åÊÓ=è@| Jp0» â–ø::ʲ¶¤*ƒ¤ oGá–þöÑßÀЩä§à;?„6ÏIÑ´(7$Ñ’rípd;¨È#(il…ôc+WW ‡ðL–¯uW$Íð{vÃøÚ×gÿ÷ß·º"~ëkxµL@0Ó«©Ú ¦ÆèüÏXÏ'òöt×6? dí1Á”ú¶Ä1$P)h0Kd¯Ê-á @ü£ùÔå7@ 3µ{-@,gZˆ;À^5ÄhÞT6‚cHqGxg"Èò‰TÂ×HZ¸XÀO<¤ÃQBjq³)3:Ë ’g²{W’¸À²¸ãEkŒöRŒÆ"\M·qúe#œ0Ms/–n, XKû$ç¬ËÞ{È:”¥Ô6+¹ Zœu7 Zí^Rvk¡°1H xµ § ®uÙþÊSü£ù¢Ãóˆ'ÅL¨@G1_wý®MK1s¯×W¼^b`8q9™XmÖ.øåvq!DV’¾eM:&ô©ßØt¥JýîÑú×^ô)0µhv×ù‹b:í…—*QÎÇy?ZÏ‘”ËR0Ï—?‹ £¿ªjþæÛ©‘H…`‘ÅFÒBÖaò=ïTµ©øÒÄäÕBHAêHÙ=†ì:*†·GUÍÐ’·l$‹¼BAU|š8b],~»À,¥‘ÁàM`‘Ñ,‰XV"HSàÀ•;ð7ÿÜmæü}în­‰¡lB Ô]y­‚¬X¡X-|iƒëøe Öûó7­kÁ·Ô‡ì²Ãl‰à xc+‘R%åÀÛ\‹^ ©†¯PŒ– Í,“j’8øu ä#²eW3o™¦a "çK¥Ãk ‘Òˆo pˆOs´‚uo‰3qåãÖ¯qbÉjÖ|âÚè'Óù"Ï€ÅJÌÇK(¼A› ¡Q"O?)&eÉ‹+ÔÑ`²¼*œÈ–|L±^> ûÛß„ZþhþÒ÷jj¿tš³Žñ™¦îìÌt{–¥OS9'5"ºðJøKà\Ìhæùîgd§í³µn˜”ë(kM \ ¹| © ÂdŦRJLÊì´¾ÁpV( Š Œaâv§¤rRqàe›6¾\l†Ž«ñ µ+«°e¸%k›!ân`8DSÒ䑎.1¥XËÏ¿üñý›r-š–¦X k#À,q/+ÃTÒl+q«íÚù}Û‡êÕçfPŦi;–!½ `±×T B»nþÈÀîÐZÚŽ’â]¸! L!¦-§§Ï€îÈ •X•yˆð–p½œf¯`„Ä+‡àó)ð–“¢ Τ¢%¢<&Ùõ]ŒÆ€ qع×õn¬åÒ•Žjܺ†´[HK¦¶*±ÔŸ_’¦lŽ˜[TKvú,áuoâ Ýdp²óU5öíé㛇O~ ¦ÓŸŸëbx]´fµ#(ÈcŠ÷ö¦#œgø²ÚT3KùÙ¶©&5ñ”½£ ‹Ã‹Vd–‘]ïšê¨)Ä׬öûþéßW.i¤Æ§“¾î)7-qËŽåÞW‰¥¬€Zäneï»ïŸþþü´z17OjÚQãÛ5–~J ”( ÉV­¥y´8õ×HJl„TF?!ÈðD”ˆ/³©q€-Ë¢I+ŒÂ+Ï£%“‡l›U…”"¥ šÜ~Û²¬Tw‚À2¤.¾rñŒÿh~ÑÕïšéBG•€¬Q5åÝŸ–!hæóbr@±!ÅnÈ¿üñqÄûP[Ð.ʤº?ÝÕ@)ÏèKu·WÈ7›”Ç’çžHâ²DД@,Óçm¹ejh›Ê9eÙZ$ QkªRiâxb4¿3ZóÔ]ƒDHM# Ö|% 꾪‚1 ”ãÅÛ+èº>¶ b¤S7¢ú–:YÖÉ–MV©  h¹Q ⤚ ”-Ñç~” ׆ÅɶD#Ë[òtXµ‚f¨Ë•9ÿÒêÇoBjçP|Ñß'Ø`›³F²k½Ì ab†ßT-Jˆm*þÈ9Zg•8Ð’ïVÁ~|ú«òS¶Zª¦™,D€ÀLUa®Âµ›Ç ÖÅmd„ ¬„š§ÿw?‹¨òj÷ôox^Çæ!a‰ëf(ÐBªQÅM«0 QŽœÇ2ý&¼"[öò°L–ZB"é…°Dx4'¤FÀƭ˜²Ñz\R«á4¼˜oi64±Ç“^g‚k™”KŸ{>|ìîËÊ4»‚ zݵ£æG«°—a%ºÃ»%®‰ÎF¼¯øá»Éi¾1ä~ò®‹§'„‘r2@OOå–ÈYoªÎÙ² k'5\¹ÔÍõª ެ˜ ’˜"µ(U,kï+/UßÅ‚ YŠW«KšjY·™,æ†×AÀôâS@f|0þE|è+” 9ìç©öÎ?žæØÂà›[&ÖÌ h²C”ìÓ­MånÍÆÂ‡#ðu‹Ñêk)ˆ l«‚:¦VmÄlÛ)~ç(Vd}ó Õò÷ÑÃïByäö™šùù&&·He¼-›“0æøð![ ;R‚ŒBå&1©;P¹WÈ'ïv~Êñmoå¤xCR¨Kj–Z‹ó-ñ!5퉥x“cR³lT?¿{7Âï{Q¥„Ŭ¦‚µè¬"_”é*~µ‚&”ݲrHÊ8£UÇA0¿¸Ã‘Š» bÂÀºä1Ã-'(Îð=ßcZ6@±× Zµr{¯W;­ ™uÂÎ\J•|-à_ý×·ßy…>þËÖzÔ2‚ᎅ>ñ)-Òl€a$œ©ù×'~ùãžônÑðîd-ˆðuÔh±.æa&± ASIY+)¶TØI³‘/ÅŠiÆ· HLYšÕjS;  ZŠ)X6vYµ mŠ”¬8MY4U–:Wi)‹/K9}xÑ, xúðhªø•Èvn˜²ç[Ž¢êKW0/H׸¦“Çlµ#CJa6%¹xYˆ­N9…ÊU,HG•F–Àð@Ÿ…ýÁ³‹üÆûä£G‰Ú.Rë¥Å4¦ÝöhyMqnÄ{Õâ²WÝã±¢VS×G• t‘ºŸ Â38‹€BÜ~¿û¦¥-ämÖ€¸ù)PKx_-5‚×ÑÉ„ðLÓqº}cv‡ùÁß<Ã¥îæGa傳}âí-вÇ"DœTMŒo’JÄhm¡Ô kœÅɧfr|#)‰ Dàá8‘yKV f±eȼTRÖY‹é㨂["ó §€o 8ÈÝ3ð!@æ±ûáo¼Ü ~êmŒæÏÓo§)u¡ Œl¹-Íìfæq6°ñ>ü%„ú‹»]åNƒà¦7ÛCÛ0âîN)SñRJðy1‚Û® Z>$®÷öø˜†Ì´ŠÈªˆXÈRóņ‰SkKAžˆWš]Ò÷æöÕ¿|³€8Aˆ^‚ÆÎO9~Ó–j žÛ! ÷½?p"÷ÀK‘j ¾êË0k—>¤(˜Î†DÈ7†*~KY ,AeÄo°(hé¨ðGâªí(©!ÕºÒO¶ci7ORÊë§ÁB¤ä ¨™³îÝ~éÐTR•™Cöƒï‡ùã×­¾ ¼Z=."A"Ʀc˜zY:zµwx4ŽÀ IªaÒñnv Ë—^•ŸBîoöÔz€´q]phV®…À ›Á’BWMŒÐ¹XÖ2WÍG¥†lZ½p^ήDÓ6 ±ú<2qR8D€‰àdÀî"4ä{‰”ve²rdK |Lˆ°Èøb„R@K`OMJÓR¼ Ò„°@Qk*.›?OO 9k¾ã°$ºÛyÅRuÒ ß^P¹ù¦Ö)l?t Èh6É#ÌZ&‹)ÚÜ÷v˜—}LOÿ? «õß?ð@ØŽFÛ$#¸Qõm׎Ž©¤¥XP6¼[ Yj?h—mG|´GËë²!W¥»óé  ¹óǤæoì~|¥aú«Ç4AñLù6kúM gVpiž{•ydM(ûþ³¿/ |ùƒ™7I‡|a;x‚ÑèCˆ[Šu4- lR²€.âÔjê(¤,™,Í&‰¼*K)ÞÝE¹F®šÃ,¥Šr÷6‚ÂÑuQ.¼Ëª‚ÏÓaDY ÖÞx¥ð¥xÙ4•÷ÙŽéNøñ£€BæØ=Ù®-Ì’)²b3ç6ÌêÅg²•ËvpJ,¯Vïœ_¼¹%0UѱS± ÛUÀ€ŽÂ±#tªJÄ&Ü´·£˜DLÈt„d§Áó&Y ¥)ZH%hTâVSKä.ñ=% 'Lgó¸¸UA6FÙø|š!§ßuK'È[òÛ¾^æ´tɺšZ0äe-Åçák,žÚæ•1K<El•§ìúÜ­DP')qRb%© jŒ¼ q‘I;Lˆ,eA‹{y]ÊÆÓÄqÇøá×'Pñ{Ãô½?eçUßùPBÍ—?>Ú¾òö²'£eš÷&×óËbíXÃÀ»‚šJ”‹)$¢“w7";Û 1+ÙŽÔºc=¯T!Ä/'.0?‡Õ®T(f»¾ø8”•ããÔº1Rè0¥Ô ŠkÍ«…Ðé%e‰,Á" épªâ5:/oéw–Òj V\J6\“åñy[²ÔÉ’‡ «·%…ÆÖ×çGÙ6 °ª¤Ò©o)ÌÊ©eð@K{ÓË/B+|R¾ø_SùÐá¶«MˆaPS«e©5…kÁ‡+ï·Iª-ך ¤í·ËîNŸŒÄÞ þùÏÚxjý\Y£t¤ô#3)>ÁĪòeÚEùÖ¹(ö‹ŸÚf3¶˜/%«©F–´xKÇ‚#^4–šr)U¾ùyóôGó„–Ž e:•“rul¾FóÀÆÃ'ÂoR‘)ÄÁÓ.T15C«¯I£a"dJàÅpL3ëËÄj¥V´äw†Êèè!ýŽŒ#¨ ,5M"òibº~ùãÇAUjY½,ë1Ì•9ʲÌvïh#²æéÖm0ˆ10Ý–ü¶ð]à (“tõª;5/Êaén†hFe›BËpøR|¦û4±ZLûJ?KL1¿X€®K·„N̆§Ùit2øp>©‘“ad› b™Ž€¾.ÌDê%[‰¥˜`§¡v"MÁ!ÒüéX*×(µÓª†œ¥€E’bQyx BpZâÄo&{!M4‡NA`éŠ2UJR>]/ƒ0… «D²v@|M½>ùêß⥓>ñ&´$¨£Ãê Iiç|´€„!Ë2l rf<#^†ãs‡½­|Xf²Ñ.™_ïCZÐìlõR…ŒÙ1Â}Èêå—þ—ßo¹µ€  B-eÞl!mDlË׽Ѳr8k(ûæ/>Ìà§AûU¥¯?5Áé·qåš½ÄL ‚#æÅh•8I;uìüR‘[Æ×ËØÚ Ðpœ°l´J¤åð¥&Ra3Ьê’?Gª² gY­,Á’·$®Q- ÙpänT§AÿÃïÜÝ>w'K°]v¿‰ëØÄ lͯ¯™U¡5¶¬¥¿@ýðË¿”Jª1Ú5â=Ê;£ê•8ÏTÕ—·4ïÓd±ùZ"ËB ÂJiQ¢5G, gá@Y1f4jÞÃøfF®¯_Œ†ˆ.–²Éò⬑ÐîCY‚ 3| Ú+y¾ ‹jÈW…ì ¾1àÈ繆ã¾1±C—ÅÆCHZÐ~ªb¢5zÒ–pq`R‰ïNªˆƒO– ˜òC¤ ÙÆh0µp1åOþÝ£3r÷kD‡rÅ6EŠF¨/°ÖR (›)lŒ¥B,U%ë¶0"{ïñèGð‹Š]0úMÐEÂG #€«•ªîžþtì÷“¾Ÿuj¦HWÈ(ÃuäõbZä¥ð-+l6~7LYô¯Ïzùaþn^çžþÈj¾KÌÄõj_ OwBR²®$J¢Á‘I#$eS òLª¦ÉB”„×¢¥,<‘–1ùu!(v˜ÅÄT¥|i O nøDÄã×^-/f8R”;ŠÚ©‚»ùü4€©Ö-±ÂI ”gv„о€ú6/ké î¸g‰øNòÃ/¼<=Û5YçÜQL\ÊÌ]ZëÆ€ d wû‘BxfΑ tn8FÕ…²˜!´øº‘²äÅñ-é$Ÿ”ZF§îâô70…ð 7þ†”ª/Z}щ¤l‰–/¥\kxãMŸT- RãÙyýûŸu0•GÙâái•â‘)´Äi{;ÙªdÍ$fâU”ñK…;\¼Û‘x%m©TóðJ"ð~øýñ€ïï޴КÔ6Þ´©Ýe#G6†@Ö$dq¾* Zq%Rðnqx*ðòR¡S­`‚|/°ZàXy&ké¿ì‰}û¿þÄÛ/ú¤ëÂw›n9ÍögÀÞ~m Þx–AŸýß|â3@ï¸D”·M-:õ*è*§,&n³5mŒhŽn)ÆáÒxb¸ÉÅ Æ D‹­ªÅ8!+©E:RL;ƒA˜˜Zd)äøñ,wõrYrY­™ÀŽœ †QÐÂãR`Ù™Adži×Ãk×RìVO¡Ù(œ7ꔫâwÉÎp%ƱM¾ â Œ!HJ ­vb½ ˜ò¶P–ψlGÔbUɦ\_ž©åqªšÇ¹’¤ìESÖ´Wé£gˆå£’ TNY±²bmà–zÔ¾ë$ņK¹ë€ˆ¸ºy…®.fåWÝã¶£,«E)fé´+|8‘ðúÖ15ÿ÷3 üK#Òï¾Rk;˜4‰ j·¥Ù,5øî’&Ù¦¤ÑèˆMâ©-`Æ O¦÷!KåÍŒfÉÜ:¼sãeµã›¡mòÈŸüâWU_ýwn LÜN ÌšÎ4…”ÔÂ,CíËsçÍ×Pî“þ‘B²‰‹Ù%yŽ"e)R†d÷.‘q4]aä¤Â!@qÊö«°¸Ú {s­¤½LÙRÖáII°;Ÿòö‚À,«âY­1UT8Š•,ˆì–`R÷]‚tí†WKÖÇ%§ý[£ï÷ðbÔ½ 4¢ïÆ#ènô8C†S`8–¬8¾%²?Áx;Â#é§_K*dMR¢†§/èÖm0Hüfà[º^©ñDÐÌ“Ð2PïЧ,°…hªÂŒ~­‰Ãyµ,°­:A^` qL^9Š™”ZžYÂ3…pþb×ð)K™ç^hÚ8ñ‰l`4çI_-Óýñ|‘À‘6=’\ÒMÃ[2¸¸ÉÜ N^§tòš–;qH“ ’­ZÊüt‰H|Yjb )ò‡ÿ>ú¤Ð0¼¦G§yxÊ2D ;œŽ òRö% p÷.-(Ü2-ìÔÅSIËRa£@”ð+§É”óe‹)‡ –Єwë dYh2í\Ÿ‰jýé=~"æ7¤˜²XS8o gÝCI¸ØHhÓéLçÙDL›”Ó§—¥Ãˆ@dY¸‚À38¢——ú'ßtùIßÏ:ª”׫a yº^?^˜ª­í`v×êëHËLP ‡xÇ}ÿ»¾þÐv/•öÂw{t#¶Y‚`RÝýbLYŒ„`)nT4ÖüIŠ&Dþ}B)[vé[Š!øµCN­!ã#Ü·X#ßfǬ’™lŸªât2bµ1Ÿü™“!ûê_­ÉuTn¤u÷|g¶#ˆ#PÒ…6•”Ö¯”÷Üø{àíÇçÍ~{¡¼ÓK§£Û0Ú‰yç 06¹”%k#z‰*€°G† T~ ‚@œ÷².–—ÌCÍ2©š¦Ï¯WÜi6å¨ãT+fÔõrMmб[†óÅ-qš¹§¹+Òð”ã$«Ðaþ”@ðÞèôôב>eAR4;ŠZèÛ;Y7@pÚ€%Òö“²µÿÛsî _þP`f.àÉ&Ø9ˆe)Ž-Ö_¶óYÐrç¶áíE-Á»¬F 0\ÀÎoç,Vµ½p,ïdñôSoû2B­Å‚²|cGÀ ·d÷FðûÌRÍ–fÌ.G³MJ)å]ÓbµÑ7™Åiø|Xe‘ªìùA\ñN§e"ø/áÂKñ‰ àÆ2"D|º>†hKÀ‚¶!n¹Žføä5àC±B¤pc4€Žm¤Ç%NSaŠ;C¾l¶ÁxƒQ&Åã2xµMˆ_Ðü–q“4$Ž¥B&ÐÝ$Ÿü¿j(ìo«Uµ[—ºj*€èѱl„ MÕ„@ô<ý·„¼Xÿ}=špR´ `ÙÓo<)MÑ,2¿Ö Å:Ži¾±·”b)”µT®î”!ø‚-ð!yK%$¶…®N…Ù»VbÉ'Þ[ÖBÕ=°4žB|R|ˆ#¥P*‘öËûòç“ÆðÕ LŠŽ£Xk]î†ÏK)¡ÙZnƒ–ÆhZñóñÙÀíT!eú–RÆKÊRg6ËšD_ˆì•9_,Ç·¤CaL|4, ‡$'˜É^ô³åÞÓTÒÞ0é'ÒR­X‰bÜ5%%–ªoUZЄ¦S²Žp[«ªîp­k‡ ¾ËâGБÃìŽHApøDÒÑúñYk[B¼e•Reá;ÜÍ„,àøNªÍœÊk¦#zu±¬K4Ë6`·+‰ÌK±Ž¬ªŽ ©ßÔöÇ?ø•¸!ÏXÏ·Vú½ÃÛ”©´À‰Æ‡Ü¢ñ”·ýÄ[òš†‹•ËÖô(>íìêùˆAÓ±ByyÊZzý¸M4[m§÷mŠ;aA1O¶vêÓÊ•9~¾LVÌwJ‰;Oÿ ðÅúꟂrü¤ ÜŽÀîœðäÁusëG†·÷ÄeÓÁ3ÃAุrqÌ.¨%Õ"VK³¸eµ!õªyWJ nS|âRÚYÖÙ˜ œ-éwžbG¤ Î3}âG(FÀt! â÷æË?UèöN“,¤+b’t LŠÝ5˜h];©Æ†0¿òáÿeŒéSRzµ_],/sÌÖdyú<Bô…`vuWžä }=cV¨¤¬^êÎW„˜¤ÊòJd pdãˆ;®>œ­ÄljïV–§ƒF¤íã4A&ÖZ0~„Iµ¯Ã~~ÖéÜ2üN¦ãâѽ9¹”¤Úüñ‰X ƒ²Ø–xâ Ä- d¥Ä_SË´4%‚¸xËKØay(¯œ¾ÂZ ÝÅ©i»}¿/}ùÓ)¬°@¼@<d³1Y:–½TîÈ•DÃÁ4'Ïj-ËÄ É#¨BPÇ–YËI©c6ïoœÞüº5)Þ÷ >a]#<¶©)œ`MyÐóRíº€²ýž°ÍZ–²ÄôÐyóëå^äd1k*PáÅDR³kÊf8¤c`6%# àª:ŠyF¢|ò».ûC,“k±-S†èE°#² ÜüíQ‰î¥p˜¥ñˆ;‡÷¿ R•ùů—áý¸Ú¦^i¢idk†ì2AdÃqRj9~Cv¤¼—AU Y¶’Ú!À+\ ý&løŽ Δ(ïÚY´Dƒ$Õ„º tMS®ÓR N#Á›!Á4Åéä×N_ùèyCâˆ)'Û’DÌ«jS<9üñÁ¤fÍ-ÀSSÉÀ‡· T%`õXªK;jbÖNŠ™‰ÉâóâÑÛ¤.²Ï£;'ÍïgOwÌî†Óã:…l[3€˜¦`‡€Ð#¯¬BW´~Á² )ð!ˆ\=Ï=±lB`?s4OÙ½ð¾ê¥ö²©—¥Ú¾ðZ×¥³ÒTÐbäðÎYI÷\- T1Æû‡Ž/š}ÞìÚ8ejm9ñdy©p{M “bJBxÃTerA)¸ÁBT váp(´M—Ly3\ò}¸*34&P•Ï€™X_UtÄ |•©‚:ž²ç8µ­Â‰Ûšî¬©®ŠÓËHMÉèùXñË•»>û{RhNÝkªEC <—ïKœfC¨»¾í.â‹üMš³Mê÷ÁÓϦªׂÚ&¦@^£âðnEHèíð½:ÔÆ§†Æ«E(¥QâpÏUe‰@âAÓ…”Ç÷ÐØ‘{~j±Œ@D-œWk©Öa·qšùÅt†¡Ðò4»d»¥ã7³9ë"P” óhqÂÅðF=[²À`I—+WÖ–äRI7¯%¾˜EƤ\y©úÅHmŽdm‰Nƒ:& )|䤪E`á¼=£á¼1·N‚ž?I!¥êÎ+L$„ă~"pœÈãb¦)x<É­R=SÃH•Å)Æó"­äíª*[Ö²¹•+ä+Q‹ã"%‹É–íXn HwC÷ÙוּŒfó#×·*xAi)ú1ŦB”›Ÿ`"ã«Z/)qâ&øø_Õ^Ÿ‰ÇA&®Žo]¼àÃßx/u?ìX¡òmP âLkf#²hp^¢J RP–‚ÀÄß à÷{}ÃK6©NOL3)± ë+k©W €Ño:µSÂIJµ^ÞLLœ òÝÐ,UµëtøðZ‹[’Õ.2ŽBÈC(•È“­E5އcH÷ …Ê‚û¶«L9&¡œ2°Á¾ü©o©ï¼¿ó•`3¤Æ×Z‰ &±¬©¨ƒCjaI!Ðáû׈ŸüU‚ÿ ŽÌÒ®‰Ø8eA½´óÝbäm3¦ò¦m`ËDx1šAíûÎãDƱÄ'e˜zÉ2 ]„î.%h¥Ä ¿%Nf)Pkrq4ˆ B3‹ËÞïÛqÊnwN;òˆÆS`õ²Ü©b‰4¶^8fžBG£s^Š%,ºÒ]-8¯ [R¤¿‰Ydq8š%ß4Kƒ¦¡A;7‡{‹‚BL—Aö¨__£ã5"(àáõµ|cÉҤХ–7BíÐî›í@*—jÚö¢Ñé¨;ÛHh|)|– ¦”Ú¾I÷C±Ÿpe‘Yó#(,ö>ñþ;÷h~ŒèÖ[¦FD/š–æÏCŒ!Îp8ð{-Ùv„à‰ã;«z}émÄ;‘íBà0‘¬í·µ^Z`¤)__¡1VÞ¨ĉp—j§ø•Wˆ‰ƒÜ@1#Õf·_´Mjd#ãÔˆdã%N³y’EN¼¾ËZ2Lå|“`â+ 6C‚=v?üòLJîô;꺻 @w}éØŽx`S™5¶&Ëù†4Ÿ Ê"¼1cø½T7R-ÚAËóû¸ÓÆ#ÏcA;¦°Óh¤@´ôÅ6¨i8&K0¾F41lJÊRÊRʉ¥fyÇ-׎ƒ¬6–з\^qøFiy?D4X=’rÖ–‘¥ Ž\ ÇL@×ïp#ó‹ÃÒï2 Ÿ~?™r“8ÊßSæ™¬ŽøÍ Ú̲ì➪ X-¯6jŠRùJ(xú¿ÿ GÓ¿;s!ÚiW„Z“'˜¸”é"†ðª(Ôî¿r±”X¹˜áÛÔ…ŸÊ¤s¿Žªx­«RîèÒD¾Ëv½TɆ#ˆ™*…mAÓgX †×]š@/œ”Ñ0±oÿq~´þêß-a›ª/olæÇïD6ÿî S(©—€Ô6â«ÿ=©ß 㣉ŸBt¤I!ÿ²ñ•#°²`KÔ45R S0Ž¥x?÷PPëT ”ÈÖb§z_LY]6°xU”¥ Ί`Ýe•Ô4² ÷–Ž,¼Td1¥`©\*rRR Çl]AAà8`F!SÕÕ„˜µw8Â%|.1<¾çM ’²º1, ‡‰>Åîém¡–|؆ZËt·dbVUA^–0Úæ±j–‰ Þ)üÄMkDW.ÈŒZ_œô-kÁg²D€Ê+á :F¸¢*²>J÷]3øó Yåø)PX’ýð¿øæ³ÿìË< ÓÀz5R;m¤Çö®ÿ‘m#=qÄ!¼?¼ÿůÏ_dUni~“Ô.ß<|í0Ùš:„õ”BüðÈ B,CâÀ–ÅhUÉfÀŽ.˜B1~÷ƒ¾Äýè“ZåÀk µ1á¬Ý¥ãCã(rî)˵XÖHI/(œº¤f‚!µ¨ÿVJ"ÚÒ€ÈLk)5lŒYTY™8Ƨ§Ë—‹Œ)¡(‚‰`ÌŒ¦=¹ËÒž¬S3^ÜE ™Š¦+™¥'GE”™n¦¤ÒáW‰#ÑÈ„æËB&L­*£Å42d8BQY6Ô»ð‹M†&…Qˆ#—Kí’ÿ¸›ä×2æ•zêšêÖ”O¶Î›F+‹Ï1Æ÷]ßê$å£q¸©D z(Ä÷µ»{z ¼}óã”±*µa4UÝñ6šÆAãGæìlèÎ /¤­¾þ¿˜î5ûSUŒpÊsL-MuÈöjd8P5P¢1Kj~{%— 5å0š¶ù4ï„ÐIdcŽD ²ñè^ÊB¤RÈ~åý^-°Žy/”Ž(G´®òK2H êá3)ûàXʳ±_þàÄ¡ÉL‰äÃM™¨†¸EBà­—ÏA`…4q¿óOR”s†S®yŽBÒÉB*D°ÓƒPE ¸5CÃk ‰PèÞëøÔÂÓ!%¥¨‘š)ZU® —´…™ZÌR83«âÕóLÈéø"ò̈8œªg²8Iñe™ù¥d@}V1&_žÉå<N3¦Ñ-µSªû&¤¢‚J0 óÿÜÆø‰B:k¯–֧͘2N´ŽŽDHc¡úц)?þ±Ñ†{Å«zmäKçT±q%TÑP¬êœ‰‘‚sÊÂçX,Yx¡hö ™%Âoár«y…ž7ø”E—È1­7 Éš¶:SQ)œÆ˜ö–aª˜¬‘Ï€hÒY>œˆ,# 4E0õ}`…^˜;¦/dÕ€\ý$Â:ý –@¢™JDƒCL9¢1!,_ b¾è¡3Ó«‰ôE*Íô_um;¾¤G @IDATÆÊ¥àH¡c D†$eWKLߨO!Ž”üånš²WF4Æ/…`ÊFÊÞzÕÅä£áÈ…˜O_ÔIÕ˜`‰–†G.KŸr7q#gj¦ S–*œV­ÿtL”EDi8¦ÓÅ!I¹Š_GRp鲌*š6r蔕¾)e­‘S:‚Z‰¤Ùļ2ÎàÐ&Åß µ›¦¯MVHH•®ÌîõŸH„£kÌ *½Mh—H©˜•‹Àôìi*eVŠÝCÅ´Qz༨®Uß>ÉÅIcCÈšÒÑ«¸¨©†Y[çR‰Pº†f”EG”_Ÿ~Ç7߈L$+ЦP‡ðñ9h&§ö0³”[Ú˜µalu¥§Üi  !NQN‚U7â#6°t#D´Üt(04QoÄNÓº}1zén‹$V_z…ŽîçÙÛnÀ;(œÈ:Ñši½q¼ûkæE…üýY'm”óJîöÏ¢qpTáè3ܨŽËÞEM¢¨Ñ”&ó‰ÄJïKKC³ýä0ë5†Ó‘N?) íFÕÏiz=j,š\Ñ6¶ê3A¾†]eÛy‚Äk@-4FÈæsäžØuk2q£êùðtŒÓtLY~¹›Êe—öïݨNµ$þþÄaBº@RL½Ý¡¸däŠ!pL[6fUsDé°t8)Ê?±ëZ­]4– "üe8™ïG5/Þ[½YWb‰rk€Ç¡ªçe¦ÏâÒ©%‰…äŽÌAÆá ðÝOkÌ[¯ÿí BQ ,Í9]/Fטð6DW˜õbJ>£¬7cÍ(]¨qb®œ¯þ{+òÕ±ŠžêÊM¸BÖŠ8õpa w”E¿*ñ B¹ÜJ„´ÃÓr‘étPÇo¦6ÇÝ$>D 2k[D»é,—øéãó9Ä©„{(¾èÝáSÆ/E‰#t™°[ ÂN+×’ù@%LÝý<h¾üqþ¯«¤Ô² [{ý4†Ç©¨Ñ”‚ÆLýùêÅÅ…œô/Ò:‘e”nê$´ ¾Æ0«UKU¬ùF nÄrEM;“ñǬ7´Yü>¿t'm¹9ð6J‡¬&…8dá÷',=À—Û{•D¡˜RªXK‘EÙ|L%æUöã¡OW…c*Qz œsé}Ü4 ÓIH&Ë·"4ÓÈ9üSƒ¢J&ü“ôùHá@t`lm•'*%|MˆZ¼i´FÓŒãK4Ö+}æéæ²h\<°”8©i@bˆ @'%~½¼8‰Sh9qèpàNµºâ«H MÝ qœ=Ž\gŒiœr—¸8 îÛÛ®é¿~ý¢l¥ 1 d·þwþÐ‡é «³­ô5i*š`¡VÚ±/¹æ!J3´øþÄ÷ãWÿöÙ㇎BävùD,ªJViL¬™Èu­½¥ !ë¨1‰p ªŠ\H Bèô¬·j%¤³,¸5âÃó%Z‹ë¤ÐXâB!%êa«¦P:r¥‘¼ÜΫKì àF¿üaœ×&Ý)#‹Õ°‘¥¶7SÓ(´Zv€É…¤¯íú|çW ð¹ÐÂ{Àoù¤M**DS9c;‰4šáíž#âóhM®±:/q{˜l! ³hpšF|]q 4'»)¡Í.âÇiAHŠu%E–)—ޱ6 Ç”‹”>MÎs®‰`lŠ N%XåÙ½D%.t5xJÇá¥yþ*M‹4´_ØaˆT7ªÖívlpÒ2vYr²DøœåéY_‰6¥¥šÆ‘ˆS¦uÁ4#3Åyý—w74F¶,…*Áç˜òiÖš%ÇÑFY¦¢¬¬Rø|ËñîßïèÝýÿýï§6©ø)}ÁÚ)¼0ט?a9÷ê)P–˜¯Ç¢à,gÊB­¿…¿ó–GÖWXøŒ‚5Ö3§*µáÌAH™ì’®ºÄ²8ÛáB‘MÓHÈ‘ÈøøE9¢U‘È*Z¢¨Å2åVQM¿„r%øœ. ‚iäBÆ[´D4ú ²)ðÞj%¼ô4ËÒm'ð…!»û÷n‹FcË©Ûz@¨#„áSHß´Ò8zà¿ùå_ôfÐ’)¯e`Oå@£}ÒoO8 dªÇœÂG¶Àþ¢9˜GîS³Õéï¼–Hç0M …ùÛ"³·ðÌ4'ñÖ[Ê5À§Ìø‰ãK„sb¦,©B¢R;Í09¼8ðµQQSEJ7å arªøñee%SÜju£^ê•ç'”–iËS‰_„IñK‡XALš²àm ˆÉ8m-RÇDøFv¨è@|5á•áÙ;¬Wl!/°¤X/×H¸P«R¹BN º-m;À—hÚ±ñÞê†^'.Î?ÿü³—j)|YFå{Ö6Í™[¿ßª.¥£S]íqàŒo4Íä¶R '¦\{+„Ù6þøÕ?¾{M¯ ‰kƒ ܪSK0D‰hš‰rÛIH‡ƒ/Ôþ‡§ÜŠŒZågøU*JÍŠÄ©œZ¢ÈõÙ’ ñ9í ©ug²ˆäHgÈ Î¦_ÈÞ^ÄÃA°V‰—nÔ†D!Ž“ÊIËOVŠ€Ý +Ùg£óÙ–HÉ%Òô@AóµG9_ŸŒ`½™Þû7­O)8oþ¿N*çêK_:'ýF…:]# ;‹´ªÖ>áÅÜ™‰# dü–¯·©Á!hF†Ìš"3Ó8ʹù2_3|]™âCŒö“7ZBšS† ‹¯DUÊŠPð %ˆ&kåp˜,‹â`6Å"* ÞÓ­3D&Ê8+Ê ¯O:•£ÉýïþóŸD¡ª=E¢u€s%ž95•b¤˜¨)“•C Yºh-Âñá)‹®§,d|N„B1bf6ů&àë?j®4 ”_6Ÿ”®ªhZ3œ**ßx#¤ÿ¡D§ÐÏ!¼û;­ãYåò•ëiñmÏkŒ£œŸyxpL¥sòM;ÆD4_‰n”BÀö'>dËð=®\êÈ/ÌZ\ä‰K‘عÞê ­¨Ý3íà¶®§Dµj “YóŒ/„&T¢1ån(M€Æ¦eñ!Ì”™²vÉnºžMùlåJ+Ío4eCSÓ³ÜJÀY‚)­‡Ïy¢ü"Í Á;Ïc›ð¯Ïÿ÷Íé¨[ #µ|Ñ–¦ Žfd¦ ίç|Êýë_ÿúÎsȉѿH¯\kÙX‰kÏ•³-ømKdL8?Z>N ¦È¢¦@SN 1µÀ%FH¹¬Î´Fñ5 ʤËÖ’tS q ’Zu‰e 1S= S.ͨ¢¨Œ_Ï5œ`E«ÅÁ†G‰Éæ·œSûóPŠ\ü锲Qt¾ìã,L¢žFªƒÆØFù‘M ¡Õ Å%Ø‹# ^"ÜŽGÛb8Ò‰ô]GLH]Y¥«!ÄãÝ]ò/ùË8M|šàºÚ¶^ )éÈueºBpÝJíà Õ!œ/1ß”}ßã÷½-Ü·%~®óYüã-‹U®Ñ'ý ù­ãóµOÙzèôÕg­v}&%1qãn‘BšÛH ‘ˆ†ü¡!¦ÿà3Mü5¾Š¦©™&Q®U@­ºS~4kMG”µN§"f:8@SÏøÄM'Ë™NË”G¨”Ä#'ˆ0ZQc¥#¬M!âiŽŒÀ*‘šƒ“B‚áwÔvÚ‹gß¹K¹d^ ýK@‰4%®C¹¦â\?Àö|H}ÂC$VZ“þýίœ–NuU$Ê22ç@ T1q*§¦hø*" ñ[‹Íá»üѼ!0dR¥ã •{Š]{%”ÏY•¶…KìãdÊÓG£,=S!>)–'DVE9Ûdþøœá|—Ñꀔ[ldcKSŽ”i4>«C¥0ubdk¾¢-Q­S"Ñò¿û Hhñé*\¦ÇX+8’•?­}^´qTzˆjHn8G”/é9Æîûv*¦vÉ  •®%ŸˆùÞ\ø'í?ÍÍNÔ ‹Ñbk ¥ôÚ^ÿ¥®[«f“•¢DŒ^ü}lçÈr“ò˜ñNÔuÁL¶BõOÙ¬ï|ù£OW»ê÷…ëÄ´ƒM–šiíÕ[ýóï`~+uºûTôΟ÷·‡JÔI‘”ŒA°|Uš2ýÄDã 1LmXA¨»|)K„Kt6Ûä­"…²¶?À¯:ŸŽqèÇœfœÑ„€ŒÃDYSœÙ%y–, ¼X׋¬6 ކÃòáÞQvÚ=3/LJÓQÅ&T.ñª×')4†S9;É1-ÄçèÁ‹”ÓòC®W.‰™¶;ÿ•v@ùŽ,%ˆó™„êb:£F¹ö„’Ŕ˗+n„´F¹Óª†¤†É,Ήo4âD¦E«šºF!xN4¹ã§LE6Âé XZ½5çäËJÇG-#X?ôMÛ“D„€j ©1‘]8ÈœWâãïx+ °d>“‘ãØk0ÞË×e Qb=å›êoÍYKÕG:;µGÓvÜHjúD´q:ûl•©j¾ç1õ9€_¡ûØmÚ×ÙŠN–fµ€êä·êjUˆ_E‰nâ41á²<Ü.ýèŸaÂ95S¡wþЇOÐ5I¡ŠUOǸá(Á*-$Ec´ªè|oyðI}ëx$÷·“¶¥6ì-)¹Æ•žlmà'-ñµ±VÈmQbR@Vi…‚{ „¥‰?ñ@â«ò@ÃBæ sò ñÓÌ1†«+e„±é²òW¢}(ÚýÏ!B픿ZrÛ}ç—?./ÝdµäÒ!¢™£1GŠ/Ä瘊š²R“5\µ7ù£ gf5RÌFQ05’5’jÀ¨.„…t"Eâ§#…ÝÉp)J`Š–E22§µàÀùLbéíF)p&ÁBà©ñøÏf]ß8M¹¦é'XÈØÒ„"p€ ¦0Í@|H4çy¾yüV—ŽÑm½’*%Dÿår²¹ù²Áüs‹Ì3êC@œp‹ç3ÑVÂ/´š›"&_gÖ€ÉÚmMØ:ï¹ÕBÖºô8RZs=T…/Ýe„qêÊË5'ñ·ŸaýâÅv¸«º¯á+¡èr•&d¢Ýq¶:]Q6%â›/þ[¦ÏÂ4û/4ÄÌZ#µé—öù‘èöIü_²}¬iêäZîy‘ —ƯsmY`Q¸t¸Q?ßîϽš.ò¶šŽ\c›FsSšé·:#¤º¶Ô4ÙrùÖÎp„Ú“l)Ä´ÎR9‰z¨SHQ|k¬ dS†&ŠÃÖ6²U!Ö¡¢ïü³/‰ýÿ¯•’ÎNT”ƒÓBL5À€¬ºÆ8LŠ…81œÞ!/Fÿ$ÅÔÁ¢¯›$£O¶cm·ü˜||cLò!:4e¦@¦ñêýèDèG¹‘W¥ÅJA …ÀøªðŽ­ˆ‚(µ²L)¹øö‡ƒ¹”>î™B)HÁ¯ç’ä«¢·Bë¼i©±J$5‘ÓëÕ<! ˜M-}:d#ã„Y|Î9bëŒÃ.ÎÇ=ºÂ Á‹ù¥J§e¬˜&œSnÌJ$" ¤™Ú®Fë¯7¹Õ·lÓŠ¶ !S#œÅq ýúågøÞÐ#¯"G ܾý®Æy¼åt‚ÖA¸žS–WÝkš[¿¿šÂÓìíÖ_ÿðÖØŠœO)´F)šTš•þbÄtÿ•¨ £©?A÷eÓœ£¢±}ŽÖ‰Ëwâ;iè¸Âí 䵹­ÎÂi¶r;åÚ+#ŸT= ³ZEƒ›v438œÁlÈÔ_t{ÈG&›N r%Æç#Ä‘Èaö!Yúd ¶‘ïC§(©6“OÍ8Óº5ÂÑd-JXˆÃÖI8¤­+$·¨)q_þôÛÒŸ¾Zt¦IYi=×5Î:áã˜Ö'Ÿ¤,¥ÞŒpV'BNl<«>œ”ï9ûÂV3¦Õ¥Ü§2–dÄë­('K/Z'|„tøMÕÕ'_”Ý[×2LÇ¥\ü%žZ’úF† º4Ïtl,DžV!øj—H¨ûhÍõT®ÐÈèE…˜\S#¼š*¦Æ”ñ›ŠÖ¹“;GˆOÊ»’ ÆcÀý.0N£[9sÓ÷ è?A…“)!ï¨3¥Õrmð«NA'½žË5…ão]¥ Y÷¥™¾ù‡¾î¿ÄëŠf˯P«0Âé9¶×èxcj»©6X:¢˜>§ð­CÄã‡NÊÔø®d²,„2Í«ÂúTÑ)¨«ƒãóWˆOAè#ásJsýë‡!—[b") Ùç»&œ•n$+×ÐtË!BS´–ßXTV&¥ºBë³à5|¸Z|;€ÏLÛ c!ç¡/ïRßú6ß)‚‘&ZR qšZ‚(›ù©ÕO@(‘­Ž¥æÌL§”g££D-á³ÒÕâSf|c -ó‚?žø¥D VbÌÕÅi!!É^©gÐv¸ZGãv^¢ö®ÅÏš8Rð#çÃ9˜g Ÿ«èøÂÙêrî"9˜•èˆßiBj%ˆÐº€l`¢8p¹,‚1²NBzFíPR`!¤rV(µC®/Å@ˆüÕã\‚G‘ÓÓUÌÈðKq r¿‚g‘)Á©¹Bé—¨JR¦­N~ý‹rŒIqX+ò’â·˜nß}cã¤ÜBÌ´,µò•N¡ã+á¥ØsÅݹÆFpòE«‚ö¸†tóýÚÆôçHì‡ÿªL²Æšj;²r¦¢ù-D@S›™²©¯ÞiÀ¯˜ìžDR™DIÑ0"úá(ÚØÔÈ´‘S]N;À©C8?~ÌV¡sÓšç”n¤ –‘¯„Æj)åñ9e‰2Ó¤øE½âyVYQç°ôz@£é·"dÈ|œJ+Àø”µÄ©s½áÔ•Q”HÓ‹Êzÿ˲©‘R‹©X|¡¢UÁYÿ§×ϧ,¿cŠcú毜ü éÄ=­\愱pÑÓÄíiC€vx«€—xÑ?ÔSÀl?EÛ.=«h4åT‹Â@ˆ#ëäŒßHM 5Qï|FS#ÙàsºçT‚&'ñ¦%òá¥sD¡q*Z¨-¢@V9ÓJàÛâe‘*ŠÎa¢‚Ô˜(ÜŽq*Ñù$hùÆ8µzþ3æŒÒ„8™ÐZáã·×ã”+¤ªò¦•/eÑ#œQfw¡À0 u†4JY¢~j)Mc…ôÍ!ï‹ëõ"ßÅ/­øl²t¼JxÓ'BÊžV®åÐø:azf6Ô*>šÏ"ï|ùƒIÖg"ª7­dsDgªÄ‡ðÈæ}sügŽ[¿€åPÛZl‚³Ù(Ki‹Âá(dŒ/$‹¯Všæ嚆äd)Sb"¨œ\–8œ¯4“Ò´®J¬Š£€ ×åíè»;8Rõ­‘ÝcžT ˜üjñ×X>œ&¹ºÆªK¯±t¢y!°«¢¯Í_¶œõf!­T Ä´À§S-!H[çÌ,ª%†/Ê!åÒè¿\²ôoL¿£³.ÑŒ-¼BƦ5V“Èj…¬I´¢©ID ÆÉ¯=ç›õV®–VN¨ê¨³ÍÁµR:,òב¸Ý³™}ÂVÅÚK)TuÊ,Ÿˆ­3E«ŽBp„‹x¡Ì]aëBCå/k¹‹jLV|d8ü»xÈÀr,ŸoK;Ù8Î Røp4F!‘3¦2H8@ÆiÃ/…ßëQã¡QL‰GHt,'Aœ•˜‚ÜüSû"¬œî…ÖdL¹Ö‰¹>qè‹Â‘…øñ¥M_¡j9ð9h|éi*'×h ¬&i"”’ŸŽ¢+‡,ÑÎ[Eé]í ™þhÒÙ´ÿ‚Eù†WçN_Ïš0‹u1@¬qkál±Òù‘G#~)}<zEj'Ñ8²09ßö¶çísü4ã@„X!`瀞»n:§Ãˆk^TºŠ˜á‰HažÖ¾uÁ´|£Dâé#K\ÀÕJ›J‡&¿uUÈ6úÙÏ;ŒqºíJg-ÐHJõJœrœº…ë¹[?gH=ˆbÂ}ùS4üÙ¨Ž~:|=\}}\>Dt«;f+Lùªà§oÊ‘žïp ÂlK9hu’‡¬ÑãÜêÖ?f|ëbp‚l L®ßâº-È’Â8ª0Y!r¦‡%n¬–h‰å…Ú"¹ÐpÊ2²WÉñÉršÖ¨µc¦Y!à,5#¤(¿\#°tNÊUù¸ßB£…cð•äsZ'B Ñß"áê³ø@š#/³Ü­ížDˆÏðµÊÁi7…JÜç³kY·ƒÑ€|š¶Þ[^4jÀÆ+õ9)µV( ØLu!ß42Z!|ˆ«Ýi§ÐVFLéÆü%6]èŽyç ´ü‡èÃÔg|fmˆrL­ÂÚ;‚¦vw臔bÄ7v÷䨫…Dʱ¨éhq€L¦uR®L)• qiy®xܺ‰{+Œ/jiÞwá3½ùÝ˳»°›Ëßÿþ÷?¯ÿžʬnM¥óm ‡ ~¨©¢:ŽlÊê(+Ÿƒ ´)ÿ…Éê1˜¬ZÊÕ‰¢ù¦DZ—“ ?åó…ˆèª‘óο—k÷üÔÍ9LM!kOŠÄk¯©EÙy!çWE:ÐXoš D`“jZh`; d¸žÎÿãÅ?d£_7t‡X¡eazpÁ¹Á¬ËcÞ>à³öP¨ž-ŠßŽE0¥ƒ“°if8'…Ä9©••/4ŽÆê¡¬¶‚¯=!d¦Þb¦VÍT:ã³.+D”ÿû#ÌD×4gSa*-éÉ©jjTÆ “SCE)´Œø¢ë†/Ä0ùƦ:†Ùuõà#ÈB–™³¢üøÒE™/Ê© £)CsHR;œµWÔºîjúqÞ¥ÔÇëÆ³»ŒèÝôùë×/—‡~ê-q'wëBv Ð7ml𙨮¤Ø®z( è»æiNÊí†N¥9©qÞ}Kgµ!…ƒÃ µ|S]¡M­S)|C3¶>Gˆ§ÑtZ‘²ŒÈ¢Ž‘« ç™Îû‘. ž²›…§ÜÓ"òÃh«½ÿñÇÄÕbúéZ¨ˆš5l äsÚ…øFvTþ÷ßüåWT·3mXvØ”Ž)ÐZ¨U‚c*T'…Öù©}…àÀ˜Þ£Ÿ­=~£%ûg_ª+ÄÊMØb ­š´ÒùgÁ×ãÖnç´zÃá4&‚“8GéÈžÇN`wÓºjÄqgÄ¥«k¬hšÚð¯Ñì9‘{.ß³Ááó pÑÕAvßCS!Ö†§`ÊRî®ÙöŠÂEu i¦E9¬&cvRéDKÜXD8R«kl±@F¡NŽúEV‚Z¾ ÿ“ÍA“Ÿ(²)ÓPºqøép‰- &<ÄÈpà¨ê²¶ Š …ÑÁa˜.L‡DzµÐ’J¶Ò©ñ%ªkÄ)ddã×Xx…è+T®(&¤rÑøe©žr!S}"¸% ,ôlô·ß>š Xìú¹–~ÖN­Ý .ÚÚU‰iŒ#ÚK§/4žîvÓ%Z£…”YÕÒR«åñYûÄ„”( OŸ#Ä/=Ä(%Ð*¤à¬Ä.W!&WÔarƒð‹š@+òHs Únš¾öüÁÃ}ÁË ÐW³uînRjï®?°öZ»*¦[¾qçLEÝv|ëÄmË¿[”’U/¤.Yͬ!NœBM‘[Ú‡Öç×^ÿŠðíè êX+Ú¢ˆ¸UQfø•3êÇ5•%Å&˜Fv,øŠâàóY²@–”SGÇä@ˆ>´ç¾¯7¥Äéæê‡òŠâ'è„ñݦÿR€ÍñÁOÃý`D·B•®%R4E¯ gÉ–otX!kméÝÝ£u¶²LMÇ'M~KŽiTB:§»Ÿr–ް\ŽžãWh¥…~ïW[|e08ŒÃèòÕC»ûõ"X3Zý•e+)ÈâÔi­éëÌèn•/´ F Ù–ÝÚ¬Ä2ÂMùBáu¨Ÿ¤Œ|!8>5p£‹OÂi9@N‚LuÛV¦3Á 4S‰Þý¿žs8_ÍyìPi¹lmPË·¥åBVÅtâp˜=PûZñŽX”{e[—«¢,…LáF`ÊkU9U\Hd)@G‡çÒÙtøå ÒÉô9dDÛ‰ÓµwƒØ¿ÊF`ždý\m;VÈH– 1Ž? >{ »õx”U*j©UKO6Ç… uhùhªX>Îç—?Jx-µ ü•¦  ýn£B ÎÚÑÚÛá"Z{…4ÃñîÿΙi힣 mÛëÇÈZ—5*b¬Êé麹‹Bà})T?q€8”;=4Ïjâ 8¬–À‰çØOn€Xú6dUèK7B<-öý.è~å£Þ¿þõ¯¢ƒÏºØ9ZÈJ «kj¤–?YüüöÍzÓD“HƒMØ!j»ÖLÕc—žæ‘ø|¢ÇT7%hZd Kö㙌Q—*|Ñ>Nù˜¢øvAd~SHW8B«•¤Æ-Y–i‚Æ‘ž¯D~:@ÌÄ)X[ÍHá 3LmsŠBØ‘McM1ÉÊÊ‘UÏÆÐ*Œ ”ÂXdS4Sí½óS?þÈæl³Ó©¦k£Í)d”Xuþéã*Ýb1åºÝ¼s»œ\TöD [ ’­®)¼Ò·98³#Ò™Ó5‡á§Æ™ÙAé¸!Ãí°Í¤ÌÁmo4àÛ¿`yøFØs´¿ßb¶tòMK¯“ªXø½±ÚÛh ŠÆDÓF›sWÖX Ffºþ«Tמ8Nü™ÓÝ­5vP.á£,ÂÉjCW b* '‡Ïà¢ážjÖI¥Û7R5>qqHÊ qœðBȶ^VW5 ÂêÓCµvÈÝ_·òui<Ûpü4ë§t 3²wµ|'R‹-×è¬+ZÏIõl mˆ*êV ÿ¾xk4ò¥¤ƒL³,8«–æw²Uº1Ž‘‚,¹kr×7•ŸãôvØdâ¦5ùñG*ÔzBåW†n*뀣ª|#‚‘\Ì¥è¾5Ë­^šIuâ–"“&‚ÀÖ„)Áè`6u/ãt¦ÜTWh|cT{mSÍ ¥o\ŸKäZW˜Jëßb;k+1BN:|§”~äþh}ù£(¦Ä.mð×X T=S!v/¤h"¼Àð­ïMÓ[p7k‰íÌôëA´MW¨}¨Ÿz«™z€p¦)duM‚DZ')c`ú9JØm]u†˜Ê5úäþð] ÜsÔZÊÂQw…TW…q„_3øÏ MHJW_'‘‰3ÓKìC­ÕÁ{yT‚_ßf¼óϾ\±npRÈÖê)s-Ä>¤o+´]çãè “¬N}rÜý[ÿ…ÙLßIÖFuI¥ViúZê›Cmàˆ&_.'+QŠ©I8œZ¾Ñ5î¤}x¨§éx´÷dxRtˆºâè ^V ö˜g€«r¡?#û nJYW¬,ߨr8;ø¬U´ç˜ô!p¥9ðš4R.šŸl²r)Ã%Æ‘2?&åÖ^­é£‰c¬1Lš8‰pdKÑ6!±´EŠQëõ¬‰¦…Z^¸ AÔî‹f@Žª¥.“S9g<§P]ÕR)Ô„*-Ê:ºD(ã »c: ã$Ëo§–0Y)¢Ú6Uš¦‘!ó[#òýÈ‚´{)¤o¬ÉŠqoòžÿÑlWª+MGE:ãV×Tc4Ãq8M¦­ˆ¬‡È¯{è}ª\úâ·Ò%Û;«®n‰éÄÌ_8ÑŒ-A4}`ë2åÛLGJ4åЬË{œƒ>AŽMóµOD¡)XÛ9å&ÂÇ¡ ë.ò­_3RØK_WÒµGŠ_S|£)|‡ÒÔß!öák9íùêßHDÔÈÔ¥£AÊí)µ ˆÌ©´‘ŽDœ¢Rîtï|(tŸõ(U±ôš1%E„CÈ÷˜2S]Á™¬€ó!9_¢nüBíÐW1Ͼ±twö@êk1‰²l…‘O?ß”Ÿ,§-RN'ZoÄŸÀïÿ•¥ô÷ôªëYŸÈÆœ%.‹â¢4 ‘ωÃÁ‘˜•GϘp ‡`)m¬,fÓh>Züôk˜/„É$"œLÈ­˜0ÜFSq¢—l„£¥bäCÂW&#«Œ‘N>ã‹*¡ƒ@8P¦ T ÑДaÖ¼±id²¨´&J.1ã³¢n. ÀÄMq8D8*rÖ„ —¨®Ž—¬•Àyaý7J$’jEË2S¡­N,\ˆ•NÍEî’u ¹c:â*ÑVL- Ë§&#[)‚MC`p#ŽP)ËJ¶º •UJÌB‰pôà^cc^üñ-ÁßñêY!c:íISju(ÄBlTÑÀ‡‘”ÒÖˆÃ12"¬ƒä§Q9)Sø³·Ú‡r¾£pÛMA u=¥L!–C™vNvÒj§6îéµQ®,øÎ‡Bšþ&„ï(Ë­„Qu ŸÅ_š¯"¿Š¦€r­.8Ã˜Æ wÜýŸý1Æ; [G®qúó·v›# ×vÑ ={ ûˆæ“‡+"Y­ÚÒÒ“íê¦Ö2·@Ψ½ªÃ‚ê9B”ùÉQËH܈SbJ‚_-¾f0!h-Vˆ=õéËb8‡A$~|§yñ?$Zuæ±Ì±Ldõäà›ê˜ŸMŸDI#f)ÔD7­?#0&¿èiöóÛ"[ªº4qîE-¡B¢•ž‚)ÿ*œ1E“.Å”%e*djÌHg`¥›Ömšo^í”{Ï"[Ƭ¥…Ðo«5ÕL=·]B«Ïr½o–+ý™aúöiû†a×LÓÖ ¡lå9ré¬[~)ÓŒS'BáZš%äˆ&kŠÃúDå‡+®ÉD6ºcö”˜Fmà#ðësc޳(çõëp)"Sk*Q·j™VK·˜Œ~Ì:ѹoÖð3Çë§\’•ÞNaɶ½¢µ`ÊAX-B“uV´ùÏz׆+ˆB‰‰´i‡@ `Õk%ª+±~pðøp–rÇšÔù¾ÿÉÿE’t×Y*½ÎµÑ&вJäãO¿Ñ­µà˜Šº9Æü:t¤q²B8ùÒ§ 4…³DhR6•é@p¤Ä©““pûœ“Šßê8ÈÌûUÙ*J!+ŠÌ ¢h@|£©(‡Ž±Gæ”{NSÍ5¢Þ¥;ÛíXòË4ÊY¦ÀŠ™N6G" OŽ\¿¥›²|YùcÂÙ@‰8¢ìÔ¸¬ÚCƒãƒ¯¼³µ²žÑà@)l –+¤"f„ðJÄvn¹¡|}EEûjøýÔOHÆz Eü4tµTÝŠ¶ð|Ѧœ:o~ÌwÇñsøö„TûÐISëªN1]!Sõ`ìÜ@65šŠê*Bé¦õ „”!¼N„ˆ× Ï¿ýæÚÝ¿wWˆý”Ë4V­ \9ÓÌ‹€,ß“-…6•ÒnT¢n-ªs½#?‰ø‚[Ô{(eSéÔ8š4–˜Žmá×CѪÃDHÄùb´¥=öJ—˜HE%Ú|{ÞGCÍtìôŒ¿ãˆ\Ãw>‚9Jxñö§RE}B%¿]å·V«F´ÖŽ¶Òº6-Šö­ÙŸÈE‘i–¢`%H)Z'–x#šè݉F_4ýtªÂojôÄêñÓÒJßh÷H%ÍQ‚–¯a*¡)KŠZì¼-" ˜@ñ=-\×FGH”ÃZ*¦zFœ´åô· £4‰³Ä9õdJMº4¶) ’xúEù¬*iÂC,ɺ—à· Ëä0„ZuîÊÍ/´¥ÉbdáÆSõ:·V®hü’”)¦«]ôhýd>ÕvVIÇUK:'M"Õ…¤ßðeY‘cadœt$¾ó¾)k«ÚB8k¦eVn*7_QÄØ†Þgϵ'™22ƒµ!eŽºtg¶3Êß{¿ý:Kÿ^Û4¹ª0 ,!8~Õ<@!7/Žï¾ý{£ëî_?¦r)›Öê6xQµp:!ã˜zn½(qÊ\æ%×É©+‰d·3q¨Ua.7£©6àù­ÑχSãëÁ[öG±çÿãÖã9„¯²,) '%OˆO­³±6ÎÖ_LÓG)ø¦ã¤cuŽì³g’Ýp÷÷‚"ë¡_jÀ¶B¹üÎ=~»ÇQ—™Fà#¯óÍ-ÇŠúH~jís íšÛen*¥è]\tÓ{4_?ª ˜†àÛ>gÇ¡=42S¡|c>›\«Úæ°ÈÔø ÊýxÕ™ñT¾Ž®±e#qªš™\&§2|µÌT±Gú2ˆ…Ìíc ´Úš+]´©_бe$^"œá¬í¢@"ªp L«)óWH”&—ÂòïEù,5ü¤R Òõà>õì„F¸›÷¯Zu(O°]âSFhÕME!Æ–ä”h3{úºûwvÞË}õ5àê’nÿ--Á¤j¢3­¨eêÍ­¤Æª.dŠÜ‘âDΑ‰—Â7"wÜùL“”¢m‚´¿óí Ô³º¬„¶ñ«{µü±?É<§_–wÏ|²>Ÿi ÁØÑçך†M[ZÕ­ÈQ¶v£þß¹íº›÷0V´ˆh¯ÓF%p”«JkÒ¤EÝ÷PˆÄ·gM_›ª‡®Å&5Í–ä’5­®ý饵s©˜8­)§#ûìDµ¿~ý²:YüÒåVÑT m0ëÁ”ˆY¢¬B/vAK. :Œx Û:jÛm¡du‘‹`œ¡ñ[8‡2f_ȸՙ¦ ÄéxI$›2|‚q¤@bùp"p ‘åòkGô?îwu‰ÁÊ'!ŸÕM!SÑÖ Ù”bK)ñÛñi­œ›KÄÑuêp˜,cj9!PߦU¡L§…Ì+7²*"”eåל/½G·(“"O§>åÞg8)¹MårØ;W»,Í»Ò(H‘›¯Ãœ6ßXÏBz°äZ-+°,'.²ëê×%üôHuâYþ6“oTŸc´uF…8s"Äáé5ՕĘ)ÀcYÆðÖe:ó…¬ï¬'Èæo'^T%–Û’BçF|u9qrøô1õàQ­Äƒò¦^?}E¦"RÚyë’hjá§öµ'¦­WnÊpÿmK¿“A)£D ŠõÜX¨4C“Ã4&±þM˜6ŒïùÓÏ`èÛvc¥+J³"Á¢ºª¨ÂÔu‰™:!-§öl»o~¶i%úZϨP¹”ÓW‘NÕ…L‰@# Ž¿Ì:‡<+ºêÞ¢â K$ÈåMµ¡Ð©q»«ÀÛ! oí53)NþÈ hj¥l ­Pm@8v¤?ïõí¡…kƒ“YÝù,–níÊlš#J¥ ?PruUÈJA _ˆß}žˆ‘N¾Dðr×Ê•Ä!Â8UeS#3„SoKéTÃ,¤œ-Ê9B×Y[¿~Œ©u9µ„B¢œú©ÖôÃ}ùc»€?š×=o{±•®gcåŒ[fŽÍæ˜j;Þâîá¼6r–‚ýá¤Ã“­+`ší¡–J ¿4>μ|ãR´ÁoéÂòI©’2§ïæÏî>9õuùʵ+7YÑðdù­Žió_üRËREW¤Øýªù”+@9ñ˜|Çb‡ø’ù~ðQÆwM¤„µZŸ4 l—ŠBºôì§ZÑŒº•ˑ˗✴ÒïkßP×»Oq}ê¤%·v|uÕ¢À) ”^?VÃr¥¡,KWp~å |•&5N}Âùv©Å I4J”å|0Âa%é“^J‚BWÆï[„r­7´¢ñt¨GQcàÇÇ19-LŽäð8ñD1×nxº˜lHêøÍœ8 ÇDSÈΩ1¸Dެ: åPKR¢i‚,Y-¡Ä8ôùœBõ„`V®±N¶R±§¬ö&ëo‰ß~OMöÁÜyÝ_¤Ëm-:aüz[êÈÝ´&«È/¡fмþûo×<”û:¥ÐÏ*¤‰¤YEŽ~àUÌ©=)e2šF¨±ÖOPÈfš2 ,2}‰Ê…ÄYQ·NŸ¥¤ ?˜¯­üÞŸ8\nÕm )Ë(T^{©Á¿ýAQQGÇ—Kš)™C°öš†¤©:}æ®a!eùxñÎÇAoÜf4[B‚® îï­…ršsix»‚\5Ïv˯4Zm´ß¡Ehúí(ÑÝŸx²F =l¨™R€Dà°zöªtÔqRö¡©D 4m3 öÇ|ø·mõÁ‹fESÛòi¶?F!äÖnÚVĬÛFR ¹¢?nM:Fû¼>MU7æX‘PÍÏiO„Ú:Å¡3Ú²*Ñ80>¦þ—X´ºšá¨Õrj9KÇ¡ÀNÿKó¤søœšÃnxêpLÑênÚù)ÔúuY(ÁøÒ­ûJàÔŸN×@ÇYЍQÇX34Sm[Ó4 çY;Ò(‹ ‹–ˆ‘‘u¨Vpd1—ßÚ3å#¿ù·_Ê>ï%[ˆBüú $(x–÷yknŸ[…®pø¢øÆg7Mœ»¹&½aµ@¸µóÛI#Û†(§¾³~LóMGU1MãJ°å™“à…UPv+ùÛßþæ >Œ¾žþã?М!øzF°“FRʬ½…ÔFÊU”"×ß¿ýñwOÇÖXJâ²çœpâø¦Œ/¥~D5ðÎ/¤÷å'wK¦oé­…xŽÌÍB_-)ÑξÃá¶UWrµäÝÿwA|«ÖѤŸ‚‘fK®:ŸSBµ‡Æ´Ñ¦Õ’ö¨ñ…ð‚çú‹Ï"Ô|óã¯2#h4%’Ÿã$ ä×UL)¤øU7•U«g§Öiñ2„C·œ¦Û%8Ù:ê(%2!ußx?cï}ÖX´ô¦‰ó9Tá;Ç"¤L!‘˜FÛ)%|HÑO<Ž…­*?-ÉÀUm£…Ú¡r#˜2Q#ÇYØF¸žuÀ&uq H¤}áÀ!E9­Ùj©iŒq€,5Óš,‘ß!Å1-E´–hZç௴DL ‹S>A`g¶¶ë­6üîÓ5Œó£¹¹ø€¦«Îc:”«¢·ÚÛz ©ÒŽi 𶉠ñÊùf.u‰²X‚k»6ìB>‚êjÑ%jÀ§†ãCŒE1 ™’-ë¾p4 ,2¦{D+…<Y¯‡D2d]Õ^:¢†‰ÓT¨¢!öÜ7KßÞe¹ut”^WÝBÒ! IöZÇÙÕ.ôæ—?þ ã~×% ºtØÊÕCú|!ý»¸t‚ãÌéø²…ÿÚ”vZ–Þµ©5x§z}ª•ÚSKççÔRS>AOÄwŸ„úY„ÒL'F¥9L Ðò9¦L9ˆ¨1jÛhZ3øÍÀŸ]¢&Óp:@ŽQîü8åBÐ~örþ·t8ßH¼”§Šº…jÿ­1ý@~霚1MœòZ 1 Ì ÿì] äKh£›bW ®žQ[u`4%‘"ʵ¹ÇL"¿)G”lNé6B(M!IŠSÂéŽÃ—²bT¢(¿”œÊAXL:”0å£Ñ0~)õ\ŠQÈrjÌÈÐ øü£þù_/!ø£9Òþ©g%ÊUNkœ¦ºp{¡)ÊÁšr qL…Li¾ó…¾WÈ~ü#‘`Ê49¢A]ñ·v¾ðBF ´é‚dðdÑjÛ”Ùºí€5R†£Érxö5‚„»³BLVcÇ‚O¿êB5&…o Q× ñÛŸiQ¦ï³QüÄ%Rh±üUÁá…,A]¾•sÛõEÿµ©Ø¿©f97RΟ”6\på|Và@$Fk ©1tÚá¥uäjÙIÐ`D–e 'dªPnR 'bº,S¹!´¾ùùZ}ˆ^}(aL³©*+§! éw.I1­n¥Ñd阚Ñ3¬)ÿ™IôÚꎓ2C6â¬1úá‹"°Bšá‘)pŒ|š|gc—íŸþé܃dÛ7Ӊ˺„?žyðˆ`Ô~¥)ˆ65VÔ^ÙÓÃNÑsÜ霥ÜR“¨½Z‚›ê$5üέ:ë9»sí¼—\;ŸÔ·mèÁ@¨¥©R"ÆW]:Ú’áNT¹|éåæÇZÿo~Dv5õJ®D Ï1mj£†b8¦uÒŽiZH'üÔ¼ît÷wî9ô@üúÏ7Mß4Èô6§©(ƒ˜2ŽDÆaŠò ¥ðñj9HUùئm=NSN+O¡¬D€I; ¿¬n4Œ8!˜ AÅvÄÁˆÏo ™ÂheDŒ!BõI§ ‚/âÇS݈ƤèùNÇOVé­·D·o såÛïÖóïÝÝÂv©H¯4¤B-¡¶•Ó¤U·¨©•ˆÉ1>û·”ãç¸Z|ûŸfO匬]2V.šqûÎŽ\F†Dk F4kâ¨αF£ÿ_VØ7I-U±#H0Y µx$sX…Œ|âúq+trˆwóÚåý·˜•@˜¯[µÚ(8ÄT”ARS¢ºžaïÜeÜïV”>“n-66MSàôÕRH•–¿¨,“‚ÖöÚŠû¹p{øÉ%&ºRäÚpúœÅ'kß4SÑÅV‡‘¥´©ÄzÈw÷ïc¢{ËGÒª%â—¸é8é+”ø˜µ ÈòÓýý(\ íÒFÝØbL‘cÆ)·z¸)£h‹Ú¯RBD㤠Á¹—¨P"ü‘é0:!~`‡'„—Îäròeq<~·pY|Wø«EŠr)J;' Þnã? z‡U¡Q.§6œO‰×pÓl*uñ˺¯K·Në¯/¶ßv⽆Y«®4²*-nŠ©Vm Å4•îcÔIÑZŠC‡Ó(Ê·]Ô8RŒ@ÑRø.6×ç[sÁûK©ÐçCêš«ËÁ¡Ïôéäb \ !wa–ˆ1'?§]š`²jYƒFª éª^•oO/ÝrKl¤àø¥´Wðü…RÂȘ8ŠÒ“2}ó—?ÎIç^étê!ý휳­6ÅdB@£6JŒßl¾?é×$ü«ÙÆþ N Í'?§Zù¢Ê9ÕüJ¬O“[FS"uÈÑÌ›)äªPhÏåtQX&A!Æs€Œ¯«öjýÇͱ–ýûçîþé¥04ãÄMÓo¤s±>¢Ìn„ãè!Pšá"dçR©ïÕk©i•c\+UÅï0Э-iNÝ IMtYùíTšBDl1RJ!:Œ?}‰[˜Zp A«>³–:”ËO­b–HJ:?…rõ aR¸ƒ‘]íû+w%žn4Î'…$ºähr¾Š¦ÓðDLï ê*š)²©Þ<„о1}Í*ÝB4L?_(eQfjÄá ñEsŒð!z`Ñ„˜Ðƻνs¾º˜nšîVD®ìÇÓû‘­‹ÐX¹‰´–Ô€¦µÄ÷âïEøë1òi¬oü4Í(LVb:ÉBXG¡†ëO4DZãP¨1wœ¢ßŽÝvÕŠC!NÖ¢¢‹ê¡64àf¤±‘q„М]·w¾üq2øh%K'Û4SRd9mލ©Š Í’çl µ¡:ÄÇÝöÇ?Bøøå¥D!YõÏa¬ŽP9‹2šZ5²68V«ùUÝŽ…DÓÐ%ÿtè‹x'Œ®îŽ6ARž=tøâd5S•˜üzËi!|Ÿ‡úý1â}üÂÂ)E(ÄÈL UÎ8BþÃV Ãhz£Ì–Ûôãeœº¹-ÆŽÔXÑp„òK6íyˆàÀðá‘+ÌÇ!§~ ñ#ë -sDãKO!rééð9áÎŒ¦…‘è¤!K ØYˆ™&2Ç2~ýÔÌh¢F ij£ï!gÉ;¯{¤Ünö•⪓êFÐp¦Šé½ \“˜@¦¥ñ9ìýÿø„6,`‰F‚Óç´iU‰Öq3üÆ4ûÖ¦M0÷k¡.`F§ZMíg)öÐ=¢Z¹;œ®IjëJø÷ÆBT„·Ã”Ýú}A·ž“¥FÓVè¤DcjL•#¢ #Ë„ˆÛ½¹B­¥M€û>÷ÛŸ–&»Ñ5ï»!r•c|j ñs* T)´F¾qD5q›{ñq*£cäxVøy>ÈÝ>hã¾øÌúAS¾Þô`,Ê·ÿÝVôÁñb˜IÉå°Êi¶@>£ÐñÕLøzÝéH M½j<4ðuê‰è ùÇ?þAßsÔýÍ©bÕ§­ëIi«ËU"D”£‡MµAÄûMÊ¶Èæ»'à·N{‹|*]'ZUŠ&n"ÔŸ0Y#…°#tùdñ‡üM€W~ej4ŸJŽQfµ’ÖŸP÷îSêêÀ¸óRa"pÇÆØÁæˆJI A¹68§÷ËøÈp⣉ð“22´Éé,‘ÅÐŒ@ |– ±3†TK«“­ZèÒ8G}š\|:ž:ñ¨OG9SBÃBF‰§ûÏ+Ÿ¸B ¹Bñ¯¼3`–¨%:Ú€<«~Ç}íH|â#Aù‹b¦ÄMEM§§ÏsˆN8G´– ¦Dœéø!)hŽÍÝéæR´uÀúÑŒ,ÓÉVÒqÅQŃ™=(ûÎ½Ç Z;PŸõO„ӞѴþE‡KAÐC„Èž7ÂkëñS"¦62jœ¤´× L¨žÛ¾ÂçØ Gv—á_šÔz¸Aß5SО\EçÔ¤¨íšª.‘¡¶Zù¢Þs_ߢºV‚Bšé[« U’Íá+m4-]"&>'ŽÒÁ‚:MÄo@IDAT›²×ý¤à9OÜ{/± ¾g@ûL¤ÒF²ùk‰ƒ™ ³8Ô€¾õRÅæ·ŸÚæÈeÈŒs¯E;¿*¥ %ÒÖ@bl¯àˆãøñ ’Jˆa!àGTg)&Á¨! ¿1šQbE…LÙ|Qú¬vqÚ!špeƹˆ§+~‹!(ËY•Ú]™ÁÙC šÀªD#¥ÕoD£©¨ßeöãù” ¯ù¼GH¤@H áËtåz ݳ¬>ŽÏ¤ï¼u"û;Gÿø«”ÛÏÚ@¨ kGàW¥Ï¼¦•¶åMÛR©i‰ƒÏ¬ºæ+‘K¿)š¯æÝ7“ú:Êõ² —¢ŠÝ²Þà¦áù÷}/Y²îÖo”žàöVWÒ,Ÿ&Ÿ )¾èðn(1­åä\ç¡½í¢…<©ùÆC´êHå ¦" iZVc¸QèJ:—:ó[€g¿£½we7¼zWÈJ)¹5à®dÉVW'ÆöÇÚ®/Y hÕ¢»ÉJ)êYè³×½âƒi+:J,W²ãCB¬”ñ…Œ5Ü4vv™išFS—‰“y²ß:Vçͱ®Þð<ú®Nçžhë ô-¤ZŠŽb?çJ¹^Â)ÌÎ?4qœÔøV‡ÀÔrä²ÂF3Ö[dˆhL#¼‘£:}S êZ£M‰¯Gïö³öM«RhºUg§Ý«aÑŠ"ÃqÖÏŠºà᛾pœÓœR!ÍP¨“œ6¼¢ JœòzF`¦tôiOÖ6GÃî¤JDËHqDuþúáRñ–$¸Æ$¶ou!ƶ‹#ä[oš÷[?ܧl §Ó:‹´§‡tò·Àú¤¬n+"n9˜L¨UÔƒºï<†ÝGt"8ÁJÛ·Äë°êEô‹®œó„¯%|¹:A0¶ ï|ùCÁ“Ut*Á1¥ÉÙÒªK–Ù7!Ë7*ª4°QbÌF[álúÂ\¾l±t¤`rÚ¦s„RCã´WñËmW‹†äwêÿ碣£\²–\÷nÊvÕÛž§f¿‰ÐYa R˜]ÅäåØ/þNË·Ü^ü…:è»Ö•‚ž…ºÛ@²‰‹Î„òK—­i¾ºmKǾ•øqB› ²Ž:¶ü@Ž|!eZ@œªÆáÛYhøœjĹŸOrEá¶É ó‰pôTÔT!œz0¦cl¯! ¿^'ü)2–Þ.¨¨ÛB­n ”ùÄYKFhK‰ã´¸·T_GKó´§©t ²8 ÎZˆŠFGH-þÅ:k lëJ7¾ó·¾r=Šê™ÂD”àG0Vš×üCH'BL¨má­ëéeœVt±Î@§¶)ËrzDp¼¾Uysã¦`¯ä*Gœ_:YA#ßw»nÁ÷dšéÖ望Hm« I-…RSˆÅ„È2åX§¶"‰9®ó7¿üñH;›òù®šZ…WÞª£ZU¯S; ÑÀÖ…iKI=ÑúVBâjñIU×”CGXõµ4À„p Ó)¥#[ôYnüL‡¬ñ5)å…Ú˜3Zm#W«, ‡r]Yà唳|Vº§”–\ì>:¸Ð(øé¹e„kØV(ÁjUÊ!c:÷."JÊó¿1µdTˈ QÃõ ™Ã§vÕ9Nˆ©iÂMA¡ô)³à”¿¿Ä‡–Ü}[²nÆ–0õê qT"”oÊ¿jÓ(ÍÑÆÔ©ÔãåJd1!ü8²Z@UT0M;“D1Kâ¨e2f||Qd¦£[oÕ¥`+ù1Óä‰Ì_KdùÀjñé÷”• Ñá׃tgC"Ÿ¬ïÿ×Q÷Ø—(ËH‡ƒªÃ*k©žj[”@ˆ\.¼J[õ;/ž¥h¦Ý#H™ i™ÚÏ@£Þ¤U7Å„X»DÙjŽߘÏÉ1ùp¹t²*ºcîåè3ã?þ·—,¾Q.Árù”]„=†WW?²\l®´6ª5"èÕ’ô¦FÊ¢¤D¨í|£¨ð"žµ0û ½3çÍ·/¼z#•NýL“SÝvMŸüÀZµ@S†ŒPó¦úákÆ3U(…g£›N¯ÿ(3YV )Ý8\ôCô P|!,·Nz'þlô1ÈVБNÜ8}u[¬id¾U;'+gT±ý¼JªŽi ?~ÿC_WÕUnÕ!Vís¼§¦g@¯\dì^úîSsJqNr„¤l4ùVJ™oQø¥›æˆe™ïÛZ”i[Z/ÄT ÓÒ˜r%ΆÞÕmYcir"t¶™â@$êØ™ÄºGeÁuɉ™/¥ªµ˜&>ÍGH¡*5©ŸD–؉H ÞV Å1¶w…( ¥Œ9N´¶^tÊù-«åÓŒìSö‹?ýNSÊõÉoi@Ó6Ĩ¢r÷Åj£äªžŽNJ4¾¾®§à¾ÜT¢m§ÖŠv¤4ÀÒ/díøFµ˜h=p,>§Î«…#½¦Bö!Îa¾0q!­·¯Ž˵AÂÑ’W~W Û¡DóŽ–Y¦Òú™¦©Ä®@x!Ášœ8GóF‚Ä1qÈõ Í´•jég°÷J+*7Yé¦jÕ†)ˆ®¥S€Û4¯ÿÞ¨½0Eô©UŽˆZš÷ wù»îh²Õ•‚¬–êFd½]%¥[&¤a¹Sü >Ã*†Q4Õ©©Iah9Èåš¶EíOü8éð1Ï€WXBÎÔQ‡Œ[U'MûRá8uc¬•B˜EÛ4çž«JYË…°úÄ׉6œp|8štQc4‹OÖ™á’ÈOÊ¡BË-ňß4‡lKvóúñUB:}r’Ègt’UËá7ªœVãDbB¦BL'üp ëĨ“˜é¼÷Z-OœB`Mª}rÖI4 ^KD*M_¨D4;pׯ´ßT¼nÛK“eâP ȱR;ïîˆ+'ärµ.Wšr”ÕeVÏF|Ì:9höðð®kÒ(Ä’U‘­‹s“½êœûµµ‚¿0LïȘ|L²œª˜*N™yoéÞ¦õ¥Û^éÈžˆ¯Ÿ©µçÕÛAüÿ£ìÞreYŠl ×oÕn¢} D_B<±¹t£>?çXQó’91éX™6ÌÜ#2ò²ææP€ÔŽ 5³ÕW–r²<°^ð˜|…a9)õò4¼uÊͯ]­étDRd è9‹ ðäí46Ã`6v^-KÖ¤ö;_Ù&e65âb­Å8n¹þ%®‘TŽaÌ_•ÛoYL`¯_²bö."…(@`)K¡¥œ,‚ aªæŒP!~%R]àçÜ™Z±\¸@{rÍ´¬åíö¹¾)¤¤šŒNjRâ×KŠY²:£Áùh@BáuqÊ î€0äã+ÄOvâ` ½ç»±€Ž‚!œí]/EñÆP¾s'©òÇ?‰Pžˆ”i™@÷F%‹P,ˆÃšVÖ­CÐ-Å›á凚)ø**VBMP;Ggiïé÷jo1f4‰%Ûlâøj¯ÌÙE×¥íât°vçûÓóo-8ŽN ƒy®ùÈïÑO£ÓsßÇ+b6íJuªšR0k08ZY¾€lÊ–¶0²€vqwQ`:&ñƒûw> øÌØóÂ$§Ü’¬˜¬¥ëË M¡ã0ÓÊJYY 'o²U}êm°?ºÇì}­¾¤È65« /¥$ð~¡áȦŠÜ;ô§­ztv+*¡©¼]¸ˆ);U‚b7‰‚oo5šHµhªxÁT+h#bYKUýCÑÊ? æÃ„‘˜¾’3âá‚RDàI@;„nEÃÃÕBF NH…RqXj|Y:²íàlû•R.Nªl`d„øâ©!»FR‘n?ùö¸“Ȧ‚ €ð÷ ¨©â¥4.UU¸¸ŽmH!)²ð˜h¬Ú@š®:M‹]ÌÐX)KY>вr:h¼l­ óx¼=T®$Ž”_®½]Cž›W{_rë’¯»XÀh&b0¦;D¶RÖR|®Öõ A`Â=¿3 /!k¿ µVèÞ"kÉ7’ <&Z„qŸP " ¬„ áóD˜%/ëëù_þ`Òıe– ļD=úùKòŒmþ)§ÏÃY8o#DböÊ4*x×A€0“â- ÄJÈZ*xï1Þ˽¨r3ôQ@\9ψ§Ù}X§ÛG£3ÓÛík \Ì|(yþžJ–ùèM³}Õh)&âòµÄéÑÓA!0‚¦F¶ýî¸7!„'†ïS65ÑòíN ^kÞ'eY·k|qAUJ01AÃÁì†ìbùq¬^ ¿2oÒÔ”óª(ãkÑá@iŠqdÄÓ—c$H"š;_¡åKž¥Œ_€#€·Í«èÑ×NS®—T"•ð‰ œx<~gl¸Õëw¯Äf]o)]õØ­’í<‚<)±ö-Š)¬cüFÜ~N¿ËtA`ñaVïÖ¤`B̺˜mw†x³ÑÑåÒ>Rb^-ŽëbÓÁéÎ;ý.ûæ·lRþ؃BÇKGL`~AóK黨0–<ÚèºÌi™á÷É×ÇOˆÂ—æDÁ!ðݾJªåºð5m)n‰píþÇ¿Ö@…&·_ó8+G×µ€éÌÑø-ý§sz=øÜ—×3šŽÉ=úyŸ÷iNmÇBˆÉ{;Ô¨îÍ/KJ,âAIÇäÝ-÷Íö…ÌpZòY'SJ¶w©‹û¥Cs38 ƒñ€¬-¨4ƒ%B"Õf—µ´‘J0áñávôÿÅ›ë4ÒÑn‡Ò$ÄNÔ¥vb×#tøqÌ …ùļ3½:„D4…° ÉŠ –lYLˤ6¤‚¦/þ•?¯e~:¼;óå·47˜ÁêÈ»^ë•2°ñt©„av²mj[ƒ ß=AK#U+ ãŠÛu'`É”³{§oàMˆI¶Ó(Ž ŸÏAk/ÍBØ!Šámµ„­2Á&FËbF!²¬@ B­-½Â-{‚”ZöMïì¹^ Z…µ°T•²¬™55mO¥´.@ǤJšX9)%J_ î[¤¼ÚsÛ?²%‚¬ü^(nI©ݵƒ3­y8TÌ|§êOžORV‰Ÿ}Ûuj{!ýí Ðt/æ@VUd ¥1BÄÜd1&ϼƒ²{ë±Z/E{Ÿôûâ‚c˜|jb4‚ZdëÕØ¦tbé«j0̆o*A4&Y4Å‘CšÁÏß9Ï\{¡cÎû4YfTÙfð,Ónc8UË Û2„ÅWîs÷–=·%¼Ýuhª,Û¤€àhmŸg@"&ãT+†˜ß[ïË7!ú>þ§ ÜRÓÚ5OcwS‰K d‹.õ…œÞžQth;)%!ª\¦çïLø¾¯'; ešíš,³ôTÁÉšA ˺ë«ÊZ¾ÏÀbÞ¨†I‚œý;¿v¥x©ÅôKÁ©•E`dy ó‚¼»(4³¾çÕ›œ€áñj®Õq]-)â(L"%h³f÷Zʲõ¯KU|xœš*¼y„ßu,Y£jjHWó¾Íñ"ó@Ób©|"p&ö-ò;¿·ô§~u·…º˜ªóžGâzÑב¹·øŽTVŒÀÄ MŠSö$%yi£ ”ÓàS†¤éTí½1ñ x&¸ #ó‘J®éÎx¶ TÅ7•T4 bÿùRŸz"ÿþ÷¿½Øà]*‘Ú‘(·½–µÖÕbÊêHÍS“ÅŠ›G€ a)·$ ‰iJØw»ÞÃü!@âJ h6åô7§¥.½ð{ô¨xj”ÀÍ#Î|¶ýοù¢KWŸÓˆ%Ò’¸.ÅðÃ éØ²ÖjÌÀÝ9>5üýÂüôïƒ6Õ@´S4_/ˆMÅ:’Í€/Fƒóé4ù8^#/ß™üÅ+E!IV¯Ôè'ÕÓ_Ì÷BÀwjeSÀ‘Š,K­ó çY-p0-›¼Sµ}x…Rm3}UòUa²^ƒ8F iD,ïdñ9Ü 9*Ô€o¸ å8c*× uÖ @ˆ,¿Þø–<„,o“ÌÜ Ãðü ©‘²döfy'èÈ꘎.–ákJaU‚‚&©gº(4˜ZöÍëóHž_dû-bRÔÒá_ksÚ;G;²NŒGÆŒP Ó'ÐuyâûÑ9>}dq—ÕkþÊ×µè<#ßÅÒ¦ˆˆ¢ªr4`šæƒØËß©=úû‡¸žwª•ŽF–rȆԽñN¿ëH \÷Œ”×0DI3•AÞ9wÅéàìäkª„Eð÷6Î?ä+OÖÓ÷ª¥Œm#)ó)7†%k<´îÃ[V#)d:L€ð„ðäõÑ™)ìQ@@};Òe!m "0B¾IXK_Ž_¾ )é?C¹¦8/+²jW@M¶ÃY#Û”Åg@žT‡ÀlK篜÷¹Íä[~ ðýV—>‘ö›AÄTá À#ÇG³l¤jù˜e[òt0²?$f½Ì Á‰ŒfBÙ: ¤Ú‹¸€ODmdA]š°¾€Ô¹ö‰j£k9*Í'U{©$ÀÚ„ð gxãBRKJ\UL%ð8.€¬F•‹•3œGúêÛ<ÅáÊÛgšd(—…»î–b…h‚ºPvKá0(2ïü‰…—º|ˆ©%Î 1ª¥Ëã#v¯7Ë Ž—ˆ 7mÁpÂËßR”gžªøL¡.ö«#A­yo úFUt@q'€#Þ)²Kã|T¢‹€~H’àË?–'îûS|²–Êᆭ@-ÐXYˆ}ÃÒ´pr(vÅ–¬¬FéÜ ‹y|Yd³3á=V.gÎ?NÞQ¤Ö9›SßYÝkA«Žv‡ÐŠMŽ hƒR–1_>ÝÒôãO· ypÛ‰Ô9¦kãõ›SGK´I•5Œ+»-Lç]àMÈ—°hÔd¯&ç‹áfÐzU ÀCêh¾ 0¾8¦%Že-¼Ü|éœæ§§ßw»“%˜N³‰•ÇÙ¥éÜŘª*L‡·T(…fr÷C·D´4!²µo³˜mjj8b&H_P¬Q± »€!wÑ–ªøÇ{(ØN*6M_±Ñm[Y¶lAÙt*¯SU\a"˜m¸ÙŒZ8Á5JÍ’T´M‚ßÅÀËæ ˆ³ÅtÜ©¡Í8ZGVJmdOWhüOô¿¬K”%ß%$ÂÌ éõFAª¾¨cåøgôk©$Á¶¯°¬ç§“¼M⽇”ªz!Ô…T¸T ¥@;A (àwβm '‘ö%ftªê÷–­Ôw>þû¦â'‚&i µëÞTmA#ø8‰TÍl*Ùö%XLNÈ´¬MÉRhl:‚Êq"|çÊ™{À'¥Ü´}Lé  '(•~´–¶ÓlªÄ¦‘p";Òïüáÿãt:Iʉ›Äî’Ê#”Ò¨“l€ Ù¨–h[Ú×w>þ{k§¦O!³dt¨9 ¬ëԢDŽ ÔÚ>Nš–<Ð?Ý OÍ;´ßpÔg5ÄAµY)ÇBˆ ÅýTÓ‡3q#!´„¨â‰´YåÌ’!{V¬PÇ‚¼’Dšž¸Xà[bBZ’²,ÓôñE .¨¼‹pÜÔkܲáøJT Lßãu`j|¦vNÁR/1‚)y£ÀÙZCÊò‰4mâñìs“ZW—¸ñöŒÉÃ,&K^m/NA­käCÖËûÓç7“bíLE‡ró[ê+Õ.è/…V 'ÒÖÂU%%èNEó[J-¤ž›g±yHu,Dj¤Ê ¶LYò–µN³Öª"¤ópA¦Aa ùH_ÎÿÌ~"hÈ6NÇ’õ0-)²çÀ[Æ‘êâ!íK€ÜlF8 ßRmY‚8@^6¾¥8¦ÿøï|÷òØíß]6½ÃRwú Mwç †£ñ›§½÷Ó¿ÿ-ÿ+sõ}ô¦¯#)ú<2¾bIª©à Vwˆ, +dßùÏb¼µ; dUÊ5ª|"ÝWíÝÆõêLq®æÄÒ.ÜÿR sâñeýF÷üI#/[̶ÆéØin†‰á›¢—rULŒÂ/¢†\Ã3Kx[€6 rjâä¯Ö]ÍâdwÕÞ½~ÓêRJ¯ê!aA«â÷ÐĹÏ'p|4êÔaªê¢)¶)3ÝÉl`sÒÇé(VÂËâx_ùvˆì@é¨2|âðûóN?¯o%@U!| Ú¬íoƒ–J¼3©}r>žþsuêKY¡1ÔºX¼Zž,¿™ã4Sµ¬dq…ªBxÖ À¤‰“Håðu<ì‹_ëhpupø®¦¬¸¾]8œ” ™2šÛ…-[ž!¢vRxE£H!]”Ç{œÄðãÀ…Àš¬qCjÌK•EÖŽT)4:TóÈ6:P ° ¾µe:JpxÖ`|9|#ù$Òh¬§Lí0 ÜÏÿç*ëâŸ×ü Ù†Ùð‰àlSb­-Uѳ¸å|h‚“&ÿý7?ª$nB}™%eA²NUÒ0R–ÀÈÛ‘³ê )¤V!ÏLÅw€yï ß™Öœš†8£Ö`!¤ c¯Ïž¤ˆŽ¼’vDÄlmDU105U¬9eq¤âÃÅíÝgL('n ž¹/ÿá—¾t¨Ñ×ÑíÇX A/xqò‘;ù¦ Ò‘eÞ{ɯýkjªž›1|+mkIñÙ]–f ,ïŒgfú²|gk#bœpOÿ—ÿ®ƒ©Ê4u±äÅd鈛¤8Y\GA[~7Œ&…FÂQÅSH¶¥ÏþÏ¿¸Éw£~'Pnž4R c7†F›ó~V1ã4ª!k§‹›è¾*æñ™¾pÛlÙ¥"¸!˜bœM+²ýæÔ1&Æš$¾˜aÂ15ªÅ}ŸbŠÝ²WÕƒfÙÄ46qäÔE(vyædy KÊQÐS X_÷úÅ=c †P ¯Ê’l§ XÜS#åš*Á÷¯@@æævµ*ÿÊ»ú;?jš6˜]àÛ£Ó®1\V¼-àT‹Y!NˆÁX×Â*'èÆ¿4gâ)†¦K{‡LV»ÎV‡>å«Ï#€C PªIzùá8å}/—ÕËÓÿ;¿SÓñ‘¹ ÞǃwYºÐ7å ¶cDP®‡EÎÑY#U¬ªb„‰ÐÑÙ–}‰yy3¤à±«…Ó²A­1ijäHÛ‘mŠ]׫»Q irL…˜ÀoNBÇßSU؈ 4j8åÄÛ»¦²úòÚuÔÛŽ¬*)OØ—ÿ¾ZŸ²éÛ/¯–uª²@gbYƒ1MùjãûÊ<^×͉Ϥøøy²n¼wà £±CH™ ˜Z}Û2dÊ]…N-©øÑBLþZÈÒÑ‚8PÌ' &î´+l0‚‰ß§ªcøÈwÁ8­µ €¦KÂ’WÌpšR€©RŠ£‰Ñ¤˜8MÀ.“Uq±ùjk!N­Áq¢)tñ([º*6ÏÊb†Ì7'5¸W…BHjË)Xf~ceROÌ õ_ÿú—y5ešl]®AÎ$ZÔ¥Cà¥lÉê¢ÈÄx±šOAÊýÔ“ÙJ™°-QB­i-kÑF™)á×úšå8HÙ˺S3•*H»ˆ)åÑÿÍg~!^‹ô§FÜÀd÷h@(»Á^,)HÅWÂ,A{±ÄD(‹PÈÊO¿ùÍo¾ùô· ßé\ӈߜ¥š°‘¤ “ lD ¦CN8ÄoPßùBß? ™ª)Ÿ.eM|œ“uõÅ¿Ïa^¾_b/²7ž Ë§£ø®©—FætàL‚‰ÖU+6I;Rf @|5yò í?ÿùO?&¢© ó1ƒ¸î&+U¶v@˼ié*‰¹‘æÉlüÎLŸ!(G¾dN;†€Ïdõâ!™¬%¾ |Á©¼@K7×>¦Ö–Í/ áÊýŸµÁ“«_$ˆ±º0âæ7·@ >3"ç=}xWÝÅèÚ+48]o‘ Å™ò‚é×T—î$Ãóð¥ˆÈòlå²N¢–o©PÜ%?õ×aéeà—ÿ»êןü+ï|5J!ß²±›Aß¶)(ÛðNCÐTԅѼ¸Ív€É>÷ý 0N:4Ûc§×óEwÙšv z))n;M"¥. ˜HC®\à¹ùò )dþ‘° æ‰o£Úµ¥^l/lÈ]G‚+O¼©Ú#$2”e”¥:%>C°‹_ýêWß|úÓôñŸÁÄ7€ ©J–G‰ CÓh®obû¼ZˆÏþ/p¯£7yK:IÑÜwg –‚Ö‚â«âqJ^\RŒòý“f½{tc4C%¤“•šø†AïŠs÷•O¤™ùvGž§sκ®Q›RÌPÙf iI¢qù¶­Ê2¤Ñºsìb#ÀÓ\ª«óÙs[:/­±ƒXɪ¬Šï&Ê6Ï®§ÂZËZ⻞ÿ£¥¦ýÉ¿MIy1l€æé©AÒ’·lZUm "n n™fÏqËçÖ9t«‘²}wžI¼ ¸ù§¯Z åv1Ú˜X %í®½ˆ=ý›Ðûãp^~n]_úÚñd›Ð –š²‚ön)°µfScáÍf×pˆe´4xšA]ttxÒUâIgS‰àem–>¼@‹:Šæõj<ž¢Áqª ñ‰ÄÚR¾axº=¿ú¸~üQ®ÖØ…©ñ n›@‡ÁÀ{ßûi‹emć}¿†Y:mÿô…ÿòLœ$SËÒ׫‹Õ0–l1q±Ù˜±ª²|d>©hãàûmêÉ_%Ù¯W._ ‘öR‹:·)RÆËB¼I$ZˆÃdR8‚¦³¼+»v°D€#›aúbR}h“ÕY _aãUˆÜx‚D0#ÃËÖEÜÙÂ!,ÚWÂZ=ƒòØ!¼˜…+®¬%ÏÆ\|"MpD¯ÏA¦ßž¥€jó^bç2ì€_#"DSu@m-¦ZÙÀ®„ò ¯i³¥™§£Ê£êÉ D\­{¨ÿÂS¬ pó·âgŽkfâ”›¤F8RãTbHH‚ž˜uu”—…¬ãÕá…óJ«…Kï¼öÜ@=Ah©³B«l`qƒAÄk¶e F ÁQè¹ÙsÁwmŸ¶üGÔ+ü*pÑÕ0qÚæÎ„ìýXRÓÈ–²‘6°‡xsvÏTÛÄRuÇ·…nSùªçéÏ.ãå}ƒ±_ÙŽŽˆ.š²Äyà–âáÍÜ$<œm0ØÓßçzïÜÏ?ÐG#®œgmöÌqR‡÷±@Ü€ @NÍÛaÃvÏO߇\,ïˆNæùïì×&þÇÀ4•˜'©k‡£Ü§“>ÒYJ( ›oÎÊ;Cn/1æ“ÿ½ îFó´»zu8bYæng@v Ú^xx…bq4ÅB(Ì,ކŸ‚%¾T£–Uh)Δ;¨{y„ªpôâÏ ×aÞÅu¬)#¦oHUÅ®µ–æ>¾T#Ñ@–¥++®Œ´ ¸*Þ²‰õKDUA% l‰&š¥·k¨ëc…ÈÌçUäñºƒÇ¿ÏpÚ_V'âYFV#%áÈp|jm^ ÔºX*¹z>®±¥a|t• ÿè5òô7aœµ£_Ü´bAúâvg’¶`)e)ó$a-XËÔÚš’Qx2ä}l%“mžH×H ;©ÝX–Qƒ†Q(›&þÅ=²~î_)ý>æ¬ð{3<1sÊRc‚ºÐ„‹;ÙâÀ{ ŽÌß9‹áÈ4Û»X [khKWÄúûq‹žþ><ÿG`R>þ§ÀoqK^#]špë+E¡XÀð-Ùžþ^~_òÇHá_y?¸ùÍÝÌvxjÈwÍ–,ŽC–u,Æ t_- §¿c‘òšòÙß»rgõÕÃ}iã•°R FM–Žêo<30K)LKrµí+Dà{RŸlÖ}²§¿{³ JŽÝ®zÕˆ¶ù‘•oózóìèÏB+)¤ÆºeÛg³ñ†aô«ÕÌ/eS-Û\ßnqȧ†ãƒ˜Žô-ٙ㺇1Py¾à¢ü8‡¤cD(0§ÃÇ4A1š MåâšÂŸM‚‘U­)„Z½¦LŠx`ÃØ©e±Ù»‚%Cð qN …{y<ÕéiD¼©šDÜZ t™ÕÚ®œoâ@â“A…Ô ²m¹@\¡-ø,b ®#ÄcÔMh0Sù¤’ üSóËŒo ‘“µwL±BfÔ‚²b}u´d²–L¬J–'åg¨ýòãéo°çÿâJÇ$M˜):64Rç \G±,rWP,ÕM¢Äö÷ô÷ޏgªêõ•§ƒŒFV÷𶻯ƒ3åRHG39D!³Äá!1)@ªEðo$æLá'è•ëÚ鉮TçíWV0BMá:Šyž5v„ù”‡ã賿ªörMtÎÍR_š”^ѨºX¢97 n¶¶)ËÓoZ^ŒÈ'õ_y“¬Ðœõ¥ÐêeÙüN[§,;ac÷ž QÅJ5y'àû­ŸŽÇ„ÖhtRÀb‚iñ k*`í ͆#æ-™€¡)l‰ïNs¼ÆÓIMac@e ÷ÓŠ‡HMý†îcLÈ“TÄ1yÿé´YHÖºñš­Ý̲Ñ®‰ÎÝ%PîRÿêK¼aü*UIƒ}ôžþ¾µàÔ‹H÷¦˜™ÄC°ÏÉî>©R#3øAÌØ¤îm-D¼ƒURU‡Òðiµ Í«âñD‹)E?} š*ˆØ„ç#^ ‹„7êb)¦f$°dðhMS­¬Àô¥[zRoìvÍ·—HÝS3C3ã °–ÎÖ<]ã­]¤ Ç„DnGm$ý†Ä´|i”i*ÇlÂúNvœ‰¯*[®…%))å©OÉzFôô'èiÕN×ëåœt¢Õw…pqÃKáXv\†©{ãh q8átŠ˜©²Ô¤öK ‚?øñ3º š'&M˯Ìc—µú(Ùœ;7`çÖð<Û0ô mO¿üôKš›êã7æûH.–· 3hÑQl*²º¬—*OCvpNˆÃ ¤\S/ ¸ ê+§óÇÇyn¤"“´…NÒ¨ÀâÚu8)¦¤“`»ÃIY¶/¨!?ÆÕt†ºÐMB ¹Ó^•TYLq“ „둊#uÕ ÊZ걯ÅR) X-|KÙ¡.!ŽTï[Ž©*@ÔK–`š‰ŒVRzáç-G;_Í´T,`K¦²jÄIÈ[’³œ(š%SK'Θh1=ÖŸßÇ1y_è¨i×Å&•ýH ߯¤Ì™¥ÓFd»¤®¢ÇÇL±^_}y$âJxêGOdAÛ©ejÊÍÅÇÄa:ºZR–¶F¡IøjyÙp“ ˜í‚G{nª"S#wÇ ¥ rãÅ4Xä`Új1À6˜ÈžþÎêçŸö˜ØÌZ0%/-)dâÌ0ZàÇ[6‰ì%|”›3¤©t¯ó‡'‚OÁf¥ÌY¡”O¦ž¶}Æ—õNïZ«"[»'ß ‰(éOn|d Ã©©^ø;}S#žÏ DŠ1qÔ∇—u&†DXÓ>û{úÇLSÓbL±½7Ÿ¸.•4¿ ñÔB"WYQ6*…m¡`âÈMSË[—»[êËâ‡eñ-³¾¸‹á¥dÍ ‰6qȶ¤liÔÇOÅÕºTÉ奘•MÆ×ŽÃÂmµÝ.ÛAmßj1_šÁ½ P¥…‘jd†3ôuK‰Óé½–J!kŠÏ”³fX`ÉdŸütHYw|tézÔK¡½¨mË4‹Í ˆÓ`š§!`@U18ƶ<3]w!0²%¾8þÀj_úº£)l6ÍbʦJS‹qš¶BÞˬÂ{G:ŽÅÓ¿wtgî’'xW»—|7gÝÛ;q ¾%A©!Àm§Âf3 ²É›A³¦M…ɤ¨ñ~öñ;»Žç~?qÔ‹ùü÷Ow¦+¨„Ù ù'6•¥ìÞ–Œj©ŠÁü:ÚOÕ>ø{xI©eÀhmç'å÷ÉöHçSY:RMe™9Šp4{á‰÷ƒ²cñ•N9_mâ¼Âwc¼[v!bÖ !©:±”Òº` SÝð͉á˺ý>}_Äq€ûJ„ i¾È,µh_á–z1)¸ Á´+6_¹Š¥(Ð •¤L¡Ž–½ñ ª¢#(®‚¯Žƒ²,¨$ÏÜ6²‚æÐ³ÊCp,ǼºýÏã ª™™P5k¯€bË;Xªö†«Ïî?…£Y>ÿ Ðvva™š¿Ë-Ö]œ~ââu¤P;A†ƒ`ì}VUÞggR²<&\yn÷ýz-)ÐßÞ•ßçA° ˜¿+¢)DœBY ©ÀönB?ûô³•rŸ}Z¤)Û0øÌ ñq>‚g´*jZ ðºhJ¤ŒpH1o³ôUIyÄ÷ßOˆ{ú«e²˜Ï߇Ìo`äY…ædÔˆKñmÞ%3 $|?ˆy ø”&*©c:ŸzjŒÀ8‰Õ·»ZŒ`)vhëôÔ*KUëõëÐ,ßqèwÿéã73å™*²avÛ¯{¸·d´ÈRZ¨Ef@ˆ%‚e…ã_”ÇØRÀpÞ’¥95|{„_ÄÇouÁD“êäÓéÜ5_­*`4U–áÀºXžÓÌÎâzÉ¡V&ê†n¦˜Š¥˜”}Z Ü|Ú;AjœfMg‰|Ç7núWÃã:Y­c4\¡FZ·Œ lLÛñÍq¯ÿÃøìÐÇÌÀ™°Ýчó”e_÷Rm¹©dŒ—e€¬ 1“M¤T±TY„ç†Ö­ŒV;–|åÄ)CðkÍ•ðJÜa‚²•½‘{ZõvÞ¿úê¥-få⤞ÚÝ¥/^G^—&á¤Ö’¦€ÇLaA}7ęؿ÷øàß'G?³¸ÖI5¼.hÈ6ØÑY~4÷¡BU Á|ã)7\‘íîmf4íüéq¦—”g®¿A O\Œüq€很P4F-d Úf')nK­òu‰`)¨‘^Æðp㙇ÚQùðK|%ñ[¦† 7y}IJµ(æ«jB©§$òÄ[Æ ¿Ù,™%ŸefÉÑ´,xÜ‘r­Ýí6º¦W¯Ò–Í1r`d±®Lö´½eùÿÖ’"¢0é(Íã¶æªW»ŠìFàÛŽ%3´Ìûk¿¯þÕ¡?øQe¿íEL°S¦iYSHî¼Èy:FÒ—áððku.C… Þñ¢QfÕJA2 àJž—ßâ¯|¨ ø&1j –bRˆ4žeq¸1,•4ïÓ¨ÏþƒˆýòãB$މPœw,1¥¾2ã©ê‰Ðx˜£×ÚELM,Ø ¡-ÀB ^yx[ðñv¿CÞßèZSVÒÕ¡ÓÍ#øhĽÀ›“ß.€MŸ±Þ^¢pqÇ~Áç¶ôç=LÊcËï-ýç($ˆƒ õdŸÓ|MñYƒ…Ô«Ô8Z8`æÝÎë‚·ôèïM±;Èf‚.=ä‰a£Å–†tæ¥èÔÂK;œÇ‡ x1ë4Ü~Ÿ>ýýfÛïxƦ¶QudUŠʼn;ç~{ÄIÁ•@š„W.ËŠyK‚WRŠg-ï3à3HU8k G€ó¥øSs™I*ì@,íº!)  Ηäkqîãõ<•fÒ|5‚ÞQ¯Öë¤p´˜¥äÞµÂZ¿ô::5:¼á+g‚NSÊY{jtõå-‹{™U T(ömΧ¿¯¾P÷Ÿ/íãñm­Öí‹”,Í–˜q,–,g¤è†‡4ÿ88 ˜©–â^>UëÂwGÖÅR@3ÐRÒ'âµp34 Äœ:6¯Mûg7ª~ ¦!lSt¾:íôy­  ÐTˆvq\&š8]¾QB¤Äª†[V’¸¿©÷œíÜ p>äÖ-8ÃiËæjž5¦jŒ CGmMy8ÓÂH]nA'nfŸdûÒaz+U…É0q S äÓ1€Þ‡Ú;fS¹¥Ø.45m8S¡švY oÙ¿–â1ÛQ3µ$ÕKïÉ`¤”wMÅ,ršb tòÆ+h ]8ÐÏÈNìÓOoýñ®Ù&¨ãâíW/&`$‹Éº:pH 6¶!¯¢s›Åi‰#Íð¤üÈÀª"ìd”7‚ l¾ÚÖ(ñpˆá‘!Ì)9«b‚˜K­*äñoú‘ÀVFÎp3z›w¡aUôº#ÇÏÿºUð+o§ÝùéèË:I:FE.e W¢3O²½;îá…Ì(ðÈhq¤¢¹|ðß'~7gqT¡Å¤¤f±ì“9e½¶ý”-…øD”Ûˆ-»4bfȦš,Zü²âÍïÑoì)»ÐÞº*ÇéT ÔÒ±S— Âdß ÷ó¼’ô2j Þ³LÊ’8e1PSw£Ï"4óx°G±mb&KgïØrÇK³Fª´³T{æx{yVBbH„nuoêýèïÄ÷9\EÇQð´Uˆ[2)ån/Òço˜t”+´ { ¤Ä l‰Ùx•4ƒŽFþDʉ)¹›½i¹@üJŒGÒåÔ·geLf¼ªÊ"0x—ìè^ì(JYn#p Ùhã· kËÚRVØë% 3d1µ™’âpåÔ” ÈJ¥Ì!h•ÎiÖX€ÔLcãEåeŠ„,ró5D4¸âRJd½È½+—º[µnhbŸA(+¤ÐT…ÕZ"t@‚ð¥¥Òti{ ÜÛ-ÖË'Y·‘F^”Õjmɶkñ5IK±Ô…”-ùj ÆcnSÊ¥,ã) Àdéõ¦<ó~P_Ù'æÕ‹O')^;…L U—¯©ayLOgOÿÞ¹ ãÑï•_¶ÙÄ-TÒ Oà`MKáÉœR^Þin‚.„1H ŒçÖÈ`RµË+”âIÐEW˜¦{Ï䆱 į„ ÒÉð~ô˜— MIïЖ¦ I‡ D¬…*óËîÏl<}ÖQ[ ‚^8›NìÇBÔgª\ G7X"SŽLÖ².˜}$ê(¼ 1…È+„ª´ `¯Ö®Núï|·‚aÔêh#mmo3N@U`]æÍ¯—w©O?½yãôâíÆhr|…u¬¶xÃ7¤¥€Ïp¢)1°'Æ.åh•Ì 5ƒt¤ڋÀÆSè`y¦c3Ká(/¼´Ï„˜b`‚!–V G9ÁªbV8ܲkQÎCÎí;6HÌ ›œ ¤–<“RìŒê!ööÞ®Z*w”˜Æõ´eÿÃ+)?€z?3]‡¥H ˆÐ,ÃMe ìJ50ß„8¾ÞºuŒ|göy°ž×½sì°l-ý¼[MwVë˜deYÃ(D GCÞ –‚ÑÈF¦l:h)C¹BÍËž½|ªz"ೆ!¨6qŽRùºH…·5oØ{íyÝölMË+áÍ|õ9'ÐgÞÑ_Žê-{ì× ‚Ô\2^y½ÌƒPJ Kú‚<²Øü6ëÑÆvÑ•_ü=,*Œœ²* ˜U^w\LÇï|Жu;©µ$ˆ` Ë:R†#¸óý·½•ºÛû÷sKÌ&AK¤@¡¥Mµ/à;sç(dĤ]×ÚÒq)‡ðy Ù,]S“$îêIY2„Èâ kÚ^IJô5âz£}7UK[³M"f³…ª’¥Ç´ÌgR¬Žú®…÷;ª¶ŒŸN ÚYŠù.‡‹8‹´DKJ ¡ßÁÇAJmWÁfãl’- ƒ6"–@LÚ×—@IDAT¼*ÄÄi SÃ_™EÃÙ«Í6ˉ8D¹ÀRÀ0O‚¯e±t+ÛVÌæÞfj¬%&á“âñ|ا0'UU8ìv|4SÝÍB¶IVA¡ °ŽÑÄ>€¸Å=ÂWXàq`w¤,CÖ7Ó—¦Ž‚†o;áÈdyO©£,£ÀK9=L:¬ç;nyÏùˆñ=U;4Hµ<Í1UIÕž™ÿåSÕ¦Ôâ'[GK Ä2 Ù‘´¶4Õþÿ!{©{R K5¡ ‡¬¥*˲—ÌCJÊ[¬'ûóiuôñ@¤ DkVL––¸³íqà!˜©®øý=¡ö-í+Á†„¸u•«¥ƒÏgŸp£}ôwfƒÅj—Ì×—™»QG¸ÃôáC_d·‡Ö·BxL7Îôï}ÅÈÄJÊVK?¤¥¾ÂQwD6è÷W‡x;jfš½Bï .µ#Rˆ‘@Þ‡/ëEí5b¶ Öœé´G׎镎-[ú^è‡2‹»,Ü—}±3²ÑZRÆ ôtѤ€ÌRÊíK,0ƒ”ž‚ìUô¸:é»×xYK8ÁÚñ¬*‡iJ“‡È :K«£ Ä¢ñ¬e˜&rËÃ¥ÎW£ºcZþâ÷¿ÿ}hTqTK{àñ *ã-OåÛFLU.F`sˆ™ã[?RL­Í¸ ëȻ̔{ÉÑT‹QÞen˜ªx)¦¶“gnJ·ŽûO¼Zø­ÓCA•,)&%¦É³úZ ¤ƾº/ñë+LGq¶t-cVËScu/Epâšn2ïøLìã¤J¾2´Ž”Ci)VÈ[¢EÀ3üý¥OmKO+¸zU¨2 ~ †dÃ4é„”5­+¢ä«Qá^6È{æ’Ò·—ߪRà‰v€æì«ÞÎD¡‡¬ ݯÃí‹W« Ï(ðÀæ/+U‹ nÁö#X"¤Ú¯FãCˆø Íã Çô>êfBYÓ‹aòÕv’N×b²v×QÈLÒ ïÈÚyô3/Ÿ!Lâ­ B§M;“æJ‰¬'“ŠcƒïzµÔQœû0[õe Ö䲌×/ë}hâ~?0³/Ä0×?^€@œ²€2Mà9—«ÄR ¾KQ¥oµF¡mVeªZK)‰‰³“,ËÃqØâ‘K…7ò{¢ùXmY{q‰û`‹Ö‘ªU¡( Úš™ÓDZ„3%ž¼”+™Çñ\“ÅAnÂv ‘åSSën4^gå¹ïùåo’øR“*K™o îÏO¿ËÚ¬»Zá¤ðSI-wt“xAîMÈÃT¬uåø3H3”JŽ%ŽfÉ»¶ÿôý)‘û¯¬ª2%åoÀ‰ã»¦ý—:q"˜ÙG§×qŽ`©JÐðy‚@©kÞÇ'äî«zun•ó •@6KaˆÐ«¹ã°Êù&¸j¥”«â¥XúRfÉÃC´H„ÏB.îÙuf)º×B””ŠÏ'R•øáñZøÅþðrÕymš ì¤ Ô˜z…Ý JjÜLwÍU)$åÔœ '‹W“Íd}fg¤\ï(Ë +gY  Ž¤ à•æâ±Åc>ßþOw‡‚›U‰òºÿºœp‚LÙö d %nqÚ–¦Åƒ`)Û='ÈdÓI¨ä-yȲ0)ôµ7$¦¸}©+±)»¾`#ݽo·©ÀtÒ×"„__~S‰yFõ$õªs>õ®³-PX\@Ø6–¦¸¸¾2|„¾ jŠF7I×Èv˜«æá©Úÿ”“Pˆ¦…φföž§c3w!´f©aŠeùÅÂÐüø%@­yœªª¤L%È€ÌõCœÏ?ŸxH–Âý5¥nf…|c@,Ó4†]|Èbzާ‰©Ö$U94-t÷ÝÈ5õ èˆü~²òõ…Ëvhã‰›Š %ÚÌR 4†÷EÄxï~«‰èÅŽLPm>Mž™Ù¨†tbÞ«×ΨfvöÏ øF2°ÄÔÈM iû+/u\J ®]j–vÔ¾H¥ÖQ4v:š& ¡Ó0x ª£u™’&”*€ÈL°%ϦI m#R 2Y©wY)"<¦¹eð§¿þõ¯It Úôv¬Cš@}õ+ÔÕ2ëv‰¼Óì ¢¦ËÉ»]d•»änÐO14w¶ûÆ­ÖZÔÝ„ÊõrÓ0/ Ö®fª¼ð<è4ƒšBúÔ š¥Áš¤Ž”YÌ8Ý1u1Iåºò+TKPŠg²R±  ¼¼f6Þ¨mÁH/Æԅ)¤¯Êݾ—°å dTß´¼x‘à &@cFÚ0Èð¶#…&å!qt²]Üø»ÉVe$B²n31A…ðû-1š.¶ƒÐ£¦J($Xy:ºcnxA1ÎŽ“…7°X€CMÌ¢µ)Ëö…“­üâ² -ð -±íÿôç?ÿ©=TCb<Á;!˪Ôk_Ñ:œÎZ?œ–â•t"]±×Œ;Õ}Ð6î^­ À"K)g¹Àü\¬Ä«Îíîµ!@n·p|Ö.,M"V;¾*ØÌ@îãŒ8~Êhd.Œ¥Á:^Êä²pZH}•³– ˆ(76²v|"Š-‘y‚¯sÿuŒ:_µ¾ý(i#}ªûÓŠ‚W]â†ÑT€¿¥MªIÄÖ£-˜›Í÷Œ—ÿ$€ÿÜ æ¹ÊöÜoGv§…v²Ý`I ÚÈ]Ù™À•(T¢!˜³«iéÑæŸp1ï…Jú€‚æ.ÂÏèD3•G>Ô&[#Ëæäë΋'° “àDæÕºˆ®×oûÛ½µl©º(gjMb¤’Iºôiek*ÐZ µš²²ÍÖØR 1e«âã ‹ýÊçâö2A¸Ž!ZÉÕç¼R¼êÅw¦óô^îÅëÊꥣÉmGÜ0ø [ê«6\@X f÷‚~¯÷ ñk-ÕHíNVÀ¨!ð1¾{tÎáø kÑÍS—tp©Õ®*~†ÏÔ¶ ¾›!qCŠkMª™›GL¶Q‘ÑHÅ!b6ÉOûÛßD‰Ö©BØâxÅ<#Áv=puÌ@q£ˆ;Ž^/W‚‚*Y^Œ,åÎöNàB@“ý¾Q`î7ãã-‰°3îu™MR;²ˆ¦HB ”’ížs?ÅLJŒÙë Ÿ,\#Ud^4`§ô®ijø¾Àݲ–b–Ž¥’@¯·þW\RøÊ{\š°î†!nž;Ù´>©ù¬ÚƯÃ;'cÉëÕîjm¶£ëœ¥0K [òÚékkRÞ·¼xï1†å7Íðf°‘óiÿú¼¯EM‰K!·SíšpƒEÀÙ. fÃT«…°—r‰ý:aàŸ LÇlž¹¼˜íh ”wŒÅtêeÉ ±Á&4ª’ ðQÉËľ)1¼®,Ù‘5ÆR¶‚ ¤I” ÔH‰˜ëS Ó·Ö¥’â ï{AØ©mx‚Ú1åø8éœfoßñ¯žWŽª5šrÃà7"Ž Ü’… v2Uc è;+åžæ~9õrê“—÷±ò橊”»Ÿ÷+™`3Ø…È@Ù L£í:"…\PV¼r¦Ë„Æv’@ú˜¼*ËJÄL_dH`äƒ[òh5å!,¤£Ð1¾ ì;O!KD¼’šò@jL­%ýW¢ 4‚‹)ð-íØS&1rLB’í)¿w‰Ù0d-Si€¼«»Û M›³€‡ãdð¥™G-o‰ Á4­e4>‹P–) ¯#¯Dª€gönòXj+©DÌšÒ©Q{QhãIm¤æ¯¤ÃQDPËîÓ¶D¨5AŸHã¿«j’Kïñ` iŒz%k¼ÔÖbûÝeÅTrï[ }8s›µx²|ü–MR–?wÃL=ƒt¬b`¦š²p9± Ø²W"îº F¨GÀKÑ$ÄÛƒïÑ–ÝÔÐjŠœ/ÆtÉ"SË0Ü['.…Ï“MM-¤.5Š“Ž*K¾ûÒ7ïµ—A¬Z2$Å[V(F«)…¥ x–Ž`Êbˆ,YR¾v~ÏabUéÄ¿wGfpå¤vÖ4•¬>¼mƒY2K`² ˆ(ÙØhÓ‡‹CçYš½™eˆV/c¿å×H¹ Ä;œŽH¡’Kà¸â¼ò*‚PyÙIu¥:Uå–‚^/[B˜#BVpUŒÌëâVwŸ›3¿¼‘+¬©,M)¾8eËæoxàéz™#…Ð M(YIËf³'«ª‘*Ç_IåÿJ>>‹áqx»àž¶ï.GµhZWUwË)x§±F‚F­»á{%ÞH²!ŠY{L¤Žy×îÝñYšÀd‚,æ“Úbck*;_Ü‘"¤ G 3-Òwn-k:µÈ8e»£pà÷ñâãÔŽ7@âç¿`÷šrʺóì¡ òøTjÏ_G¡—ÂýJÀ-‰T"Ëè¨ê€úԔȲ ZV!“ee/3´Ä©§rú÷*qsÆ¿›¡—G:²ñ ¦?/e¼D ì^eIÍi ¨mB7Ÿ]¥çÓY',P…Ö -Há~j¡95à5I…8d†¯&<¶Ð²I¦“¦Tf€‚ô#oª&±\¶”’˜‚Dj yH¿½Vî:îUfSÂÏ´¼ë7Œ”.m AÀ5J¡!«­ ‚àpî¸ -3MÞ’w‰Xj‚˜R"v¿5C) ¤—ƒ˜¬”ÉÂÛTââqB,©©¢Ìß­ŽM!d¾ÙZ*¼£UÛ„ôïûŠÏL¡še¾­YRvdk˜ôÅ”ã@j÷ꂤYmCF«P Øö¸à 'CÀK ;já²5²µ¥âÃÑŠ ÄÀð!À&)4A—’·”e‚t,5V|±ÎÀq¢UÄ#§Y‰JÕôñ  ú*«‘îíZàþëDhu˺ t‰ZÊ’Ž»•E“ÚöÓáë«05÷ D¼m4f¦VS¾’öY¦¦qøŽ¸©¤,ÑÒ!Áðb8_SàbA_•ÇljFY;dA;E@N0²™T„•·û¦ƒ Á(7RÒf“&µR|½à‚@n¹‘j§qø¬Ùè…t&–µ®£%MÖÞ¦€¬îù{£R¼*žñZ[nÔåh‰@LÞN«…l<œŽn²‰ãÐ4\œ'T’ZµM‚ ·¤ÀV(†Á²»/1Ĥ"P†-™€Á·‹Ze¬©X¡Ø9Ëðb».°Gå-ñ³+Nœ2~¸[´%½£lw]àCëú?:vP|¯Ç.®d»k³ ©F!$ifDÌWXl‰Ÿ'%àÓÇ¡¦$¦ªE…»ÉqR¨P¡B [/-š³¸T´6¨fçœH»xüRRSYÍjßôâjœ ŠÉÕR˼lº 6ÈRV•8ßå÷iWëJ\]®só+‘µ¬‘r†@¼ò˜²ÑÈJ-So±ÖNÖTbtÚ&\£ Ñ’¾ YA†¶ª˜Wéq˜Rµ ß² }e«jï²R˜=JŽÊí0•Ûo}Ñ”à§9šìDb¦Œ¦¤ÃD`².üjò8UR!¯D¶ãTU¡áY‚œ}Câó›™ DyÓNad"ÍP!:½½2ÒNð>jË"Ã-;†×´ª²@K1<¹ ë"¦–lµUARkƒbASUŽœ,¾@JP_‡æç üN¯x×Ý8µ3 ¼’¤¤XS]ù‡²lÝõjGâð=²)ì ¦& b°8é(×:AÙ‘ÅÓ—E³?j˜NÙÕZ²Ú5† ›6‰©]…q˜r†³Q-1í¥ åȼe|¾ò¼.Ä™˜MP\¡@•iµë’ „X)A%É^™s{o†Î|D8½¯ÓSžxU˜”‹ùkZGÊ•S>?YHœÅµ±â¨÷e×RãÞŠ´±Œ"K‡š9€–éK…¤ÜÙõD•D·Û–)7 D ¿<A¶áÅ;K„oΖZdø+Ij/6ó('Ë.¥Ç=­Âä¥(¨-*®‘Ž™Ëæ!²Ùiÿfð•Ã,粤€âR‰”â-qz1w†‘ʤǴTR–¯#„BÙ&ï‘rl RJš¿Zˆ¥˜Õ"Ž"1!RïDd³)T¸ëޝ;œmY•v òÓ\ƒ§„w}+4Éî=)Lø.†7§¾¸ÝYR«W4Ëh©\ Å&.–º°ãŒÁ«å‰¯QÃóL#%ü)x+/e)àâD‹yïØÉc"ÔQI{‰Ì§àú¦au‡\ÚÇ©b‚ôÅ1qšÄRÊí„“Bx‡´Dj Õ$ aSºø¤&B3©ÔàL!:X²8˜áI…ˆÑ îL"¶Ùµãñ¥ðïT7C;²d#ŒãCÒÄáÙªè3µô‘e\’¶»˜ªMaäº X>þ×@K·U1“V†z-YA¼½éTƒÚ7b£%—íGÀtÀSÁ´D¨KÁ}ž”y§¶ç‚¥ÉÛ3P#E$PÀ€<„ß`b“Y›jÚȲÌ%o0^#>â '+ˆœTËöXS JáDIªB¸€ XÝ[6p“@ªÍc& _#©È# l-Š-Gg¤ ÐM‹á-ùø¿ÃeŬij€,Á*Å‚Sp+)…sŸ3-êÂ#0LYË !Gµ…p¾8¾%&B‚Í0^’–&ß0‰tψY]•G 盇×H–ß0‚ÀšâŒ·L0‘&¬V\ÊRydUÍ •¾,«{&C€›<å‚4ÛN´|²˜—Þy%Ry©²|AµøÈ|Ó.–¬@IHÞŽœ3Y…µ|˘–BÝljVGÊðR yAÊD*O‡ÿÅŸþô§ÒÒŽÊ,ÉÕµ_Ї§d–•ÅmU =¼¥f4¾ ºS •]y½“G0~¾ ÙîB±£$kÙ±Æ!•,ŸZ-6•¹€GfÀbʤ*ÎRéë(`µ ‰o"h)°L\°cë^k±€>?dãlTËu©Pʹm¼ºX >Ó—¡ñIIé%6AKž™’bA"˜.Ъ xšøqxU•ˆ)£kÊÉxSNjר*¿LGv:@V °ŽÕ–ŠIdšZ38šX‰¸e2µu&‹30$%áb°Ô€,¦@G1µsôoŸá%ì°/~d­*¡@y­]Ì€c™¥V;BçÃ3xÃD؇\KYí¼¬ ;=ˆ%©<\9<3ƒZÖÍ<¤ÓÓž‰W>…{ PaÓ‚DÊã‰lYàðõ¢ŒÃ³¹Á’q¦ðÑòíõ‚æ|Ðj!›Bj›'¼Tjâįq~¼c¥/U¯”‹cò@–BKUí^,Î?þ»ü•ÆÆÈ Ú§Íˆ]W mâþPR-üà¨`ÍÄ=ð+W"kX;ß7!ÕRs²•ü[w·ckniºSÙú¹{Á'æ!߯¢©’ó '™äZU{wKòhtL´Ø}ÿó—²ö´PªŽšž§£5º×öQrV¢KÈ>㬘äÐ ¸c©q³¼v]5‡”™‡[9@|–øù'’ôï¶J¬ð”ÀÕþñë#V}/>ÛÜÿpR£·jCÙJn82¹™î÷r¶•`%íýR¨Ñ¸·aßšíC&šEÉ¿€kq$8ûýüpb â‰'3¢@~Í?ßÇ50t!†ÊMÄVíh =Y9 7G‹Ánšm#Ò«v©Ä¿þŸëxœÉíÜJãe¼èZc|Û΄ŽÛP¶3¾R†sÚYõupd®”'LÉ ¿‰¬ŽÉúôÇ俨’ëÍ/ôÊ1› g «”™ÈøÓª²2h<#cè»K-kW…3‘Ë]'<2·–E%€I?€co•‰ãëï(ˆ#ÓÛÙ ¯=g M×A¶'¾’¬Ôc2úJ=B·Võbþô_ÿõ_±¢ h^“šJÆ ï&d0½c˜¦ ‹T…‘0g‚ªJU•Ò¨ ع*@?^ÐôjW~&z¯é­íH¿*CÐgÒq «ö983Ác(Eª{#”üÀ·±êÜ`Õ9ÀíVž±^Êí™LµØŽskJG< Ü|0»{n rP® cD#âø-“[¤ÿqß3—9tÙ 7¢.؆ÄÁ3þ'ôÆÚÏ•Š^l ¥¨ÏQÐÈ4âv|ÿô혬–«=²‰cd;wYzß z>”@bG#ÖÕ,½ºT9LôÀF˜‚,ðdZD•aX;rß«d•Z€ 5<Û6F%¹U…cU¿DÑ1·œi4z„†*½½°–HJš>ÖÜtóIæhÃwP&íÓ†ÍÊp AV}¦!à¦*z1 ¥ÜP-½ æ ¿ ÕÚ›Õ¶}.-©TËz3ǧw ðÜbﱉ Ów$ä–T…³‚µ÷ª¹Í¶%] ¿=¾.p>òlÏÿ‡0)6#Ý~&í!Û¦oE“€–€»€d·õû[)Sjœ&«leU4&­×Ÿ2ž¨±e6B/F$È0¼.G澩. k÷ÃÐÏ<“¬ÅêŨ Gšöðiœœ Mbd‚¬ÊºD%-;LDž²Øžk!ØGàXIî"·ïð@æJ=²•šE?1&=­à”žË8‘˜ƒXæC\W‘ÄœbnëÙ6h -ó¬4%@Ö+¤Ñ‚p J!`žl&@×l L™­.dŒ\ Võmt»94ÐSæ–³’-Ó±Òõþas™R„嫊?ºŸèHž¸mÕcڰϨqJ}ÿ-SPbÖ˜7«×éú-ƒ'N&ÃÚ¾{ª¢£é6(^¦çCðkľŠJ9Äé‰Ü”xÊ" KUÀæÝ«Rí°AíC ðQ…ö\cd>ñ2F»YÈ×D #øÀ&ûT«Â"g€XV’g¨ WeBãh.€¦™g¼¿Udõ§¿ÿýïúér!%âU^ÀÔ1Ûc¿‚ ÙÑð)·¥Ržx‘¦Ì?[-)÷(·é¬‰§´=ÞD|  UÛDZó¬½q‰3—Uu¥”»)ÒJ)UÅzÓ`TÅ-~ÿ쫊ôš¦ðlhæWxžË1™÷»r¶aƒÌ…jwœ Ip‹çÖÓ ¤…u Õ³zË\ˆÌVëJ0^TÓ4OîGk¿°¦¤ïÕøÀ•Ú¾c†rV€ kcxbHYôÛCS/ÜbŽ€å=¨ªl= Aír2Ê +úl9`T±£°*Ð,% ÛÁJ¢RYib%†–É0}K⻩£YJyêUʳ®ª2ÁûóCCLÓ\Çé1•t <Ïáæ"xúzSÛªjw»KdŸ>\on ·ö`Þ’2ÆZcΉc` w3:¤h"éHéø:ÀPU‘®†§—Ó+!a³`¥ZìYWæ}dYaèãó¤˜Âψ#qÎMTBb8‹6©KÆxŸ¾9ZMiŸ)ÉZ†F)œ’ N̪#¥Ð(+!eÑg:¾Ý*¥Ç$ðHGú²krp4Wu%ÀÄ"*&Ró”×æî¢„çùV‘ M\N¶RÈfuw8ÞÐ~qñöûŠÃ„ F™ fÇÖ–i¸YÐ%‡„é d÷J Zož„ZöD°dûÜúùšÅ 3²F†ŽJÚa‚zó9ú ök§ÞHÁ‹t“¾Ld•vUÖ­®·{öˆ”Ú[FèB  ÐR¯*%RÕôñ“ö™€ ŸCeLÚªÒn‹Têάbhtñ™y;äŒiäJ͊Ęˆéešë¨*+Ven ÇÚeG¡EÖ’p¬‹æZžmÛ?}²|"a±lbSæ)#‰›¸ušyíªJŽûëÅ#•d…ëTM鸭’ÉJ³…ue2>e}µ”ZƒXoSkÀ V²%åó_õÿt‡€2—»‰*,NÛÏßOáô²p½É88 |].ãȰ)JpΰhI ÎìHbPI19PFZ²vVb;#E†”°¬ÓÂÀ•|Sø7®ON©#žÒ‡šXN *XÉ4ÍUmP# ýW´ù2HOÙc®wÔùÍÔUK³F: ú–a((12·VM¦ÔEÒ$ Ë"+ GXÞeᔕðU;ÊÂô¶C>ËkWõ·`JûáÔØÎÞ/è‘ ‚}.Söbdº0·ã`ÁŸ@Vr¤—¹ÉuÀ­ ˆ¶ê×P$“|0Âβ+è…å¦çÖg 2UQ;™j7b[•Œ Uáv+;¶IVz‹–Ô.(U¹­ñ<Ÿ¡9ÇbÁ¡*™#~sƒUµ×(uÄ$Kãè)b¸ÁøJ™×h.¥@ À*s^‹Rãò$;m÷+¡1Y›ôÝF^ïïÏ­<1€2„s»®g ÛzJHνÒH|úFg›8·˜.;ÛLS¶*œ­cLÀøJ4 _¦®¾“ÌÏ× å§¥¯ŽÎ]8i Éxâ‘|‘°^ySswÜ௞97ËMs@žKü<+ÓV-@™˜ž & zU³òéˆÙþuùŠèÍv-ÉRFw‹6¬%L Ô7Ò\Xè•‘EþªÛ9 Ó`½Llÿpþ×ã[ e#NÛÏŸCÄý ÓSè‚)…ªÜ]ZXuþ­7æv|bšd÷]Ïϧª«2¾Ë¦” FÃ##€3qq@oK«’åS»ÜV#µèÅhwì‘ÙJðÍÒÞLþ¹eNƒ‡…v½}?ô›ZΪ)”ްÌБÆqkª64Y/ÖE–/0JôæšØÎVÅ(‚ŒFh„Ë€R¦ì0A:v£4Û'™)ÆÍ?CÇ3ãö’!1Ö^£*C¥Öë(w¤¡ï ÷€°’ÅôzÛvLŸ².Œ£ÐØVÄ”0 js¶Æm"’¯ Jpï@|ìî25ö¿#¡ç‰oŠ#= ï“›ì(®Í±…uJ‘&nœ=7®*C¤Ðèš‘åH¸µ»’›\£.|Ê&b€vÀ÷V{êLÊ9·ª®5æCCðý×ÕèŒÄî2fðUÂ×£¡Íz ÇbÕ†µ®vUxæbd7ŒÑHo=Ù ¸_p}K‘LäzËxd¹ïw|âvh=SÄ|ºò˜Ì}Yë"k7 ¥ôq|K5îÝì³%u%nº.GXÀd²ðø2r/Ov;Î;5NÞJ™ì#àCÌrΪoç4b/Ÿ¡–¾Ždq;ΆĎ­ß<²çÒèh±Óy7ï˜ ÈG¯¬WÖÈ¡Ñì•ðÛ ßDdoØÐ ‘F¸²}¶pCéÃ'–ï:Ú)³­Ô,ŒïLnrnôêÚÚJUÓziŸ™Ôž^ž-Ï]²P*ØÈÂÂýfÀ˜;LY ¬T/ÓÂÄ~#„lçíXfÛèzÏ@0TÈÒ„»²ëû4a%k“…n-†iLž9´I& ˜ˆÛ0žÙ÷?£ØCäzr³k–[‚,/@?^`Ž€I«ä†dB©´Þl >\{¶ö™X =`ÛÖŽq=¤<·æ:Vª×Äé7B‰¬+À¢ÞòZræ†oí£wœmÓ(½Îpž–?cnUnDΰ{!s1ÐÕ\>ôE\+xJX´7½T»’œa½°ÆF7bü;‘•H&kQ­‘§Ÿ>Õ·ã´Á¹9Ä"F~«àmÒ2嬸 U‰ÌAv,«EúÛw6y÷$«j„•´Ÿ‘÷·À¾iZh”šø™þ_³8ø\j'ÓÒ悔÷ÄV­¤k#è3¡O‰dAŸ¸FcóËKuÿh ;“¥ÙÝL¤ÝR’±M³ 1ªa¥KRâÛ)"»‘ã.Ãg@•²^¤hUüdªÖÈPÚS¨G_‹ªR{º‘¯:F‰FïËDÖ.‘@Ž»»q"@Ë:ÂF”égºªœìm„™˜lsÙ-Tu)5Ýf•²Ïº^-Çî.ߥbdJL7úþoÑedŒ#ºÔ‘‘=%, :zb‘ó Æ 1² æCF¸Mxª"[=œgJ¹ ‘R»Ð(ˆÛ _uk(éMisú2sU¶ñJÂñN;ßTUÙñõgå(ZiÇ”›¾0°Ëf=2“-ÓGë(ì ´.z11 òIÙ1zeUú.pSC•ÒÈÝ‹,,«Rjy­Ö2gŒÞ|ÖâÈŸ[½LXuô¼J½¶F'ЋÏÙªHÕVÍŠ@©.hJ|Uæù# dAƪ#†):A“,Ì-%@Ö r½2R†–{ñ ¢«5®åÀi˜÷D0Rv4BôbµÈd §YKsïý¶3ÉÐ1%ÁFDb"‰ÇФoú¦(¥/Û)hÊÕ¾á3o¥Lnß×Û 80lCz@Œ¡i²ªck |³^ FV³%Ã'Y»,r辆d»*f ód]^µ‡íÖÛÄÑ£ÑGâ&ž…~^8½’Ù;ŸÿsÐ:YÜ–ïg†oж¡Ó bŽ˜@]Ú•`|–‰¾A²È­?0húý‰e>~-ni 2f²¬äfy)·’¤#&£¯3E‚ÄåFðIï:9”ñn 1€q;ÀE0þ–˜9“|ªrªâWrík‡xǺ€˜ªå‘la†™ôÚ J‰§±Òdg *ó–ÉD¦ÇwTu”é¡ËQU†;úF©&ˆ¯ãhb%$½c+Á@O<^·úŠU# r.O¿MnÄ-ìX¼]1gÌ ¥6tR’Ù} @SÈD¶t˜H#ØÄõÂxÙQ¨ ¯4wÌ-~U¥ýØÃJò¦ô2L0¢•¿W"ôŽwΩYkV˜"qAæ1²`X¦ÏDîÁ(Åï3b˜‰ÅªÖnU—êË™f†“i4®ª÷w,(E›¨Š1È}uû~rxš”·ã$K2|«•¦ÔEpßõû]׳$ÐŒ!®½YïªøªsVEîp«¿ôJZÈjtG€ o½È ÓØJŒi¥¦œ?îˆ3ãýT¨1¼D þ-˜¼ÐÒ§ÅŽ§ÌªG'Ó(§Qr´_nZê›{LïW?Ù‘€^æPÞ2àf®{¼FJ¤j„UE%]ZFä´pb$C·3ò˜>]ÌéE Rž­‘ƒÜ•kp>N]ðF¯Ë8¼'M‰777¹czß@æŸXWÇøHz çLd³ Ý•-–,%Œa•›c†µ#1b]xV˜ÛqRí˜[¬}ÆÐ`ú9Ÿg#²’E]òÞ3ÿªHp;”¿,Újd²_³™'–³=Í?˜ Ñ¹H¹å÷¿ãú4µÐô+dÙÂ4>‚4Ž • Úο^†m¨E eÌëïØ£ÅÃÓ¿S²êvMQE6ô øùý€É– oN #ÿŽåæîûLÓÐziDw׈$Àì››}D È¢meX{kÀ™ôbŽ iîóÓ!àµ;ªj¯Ë’ÀºjLÓ ¹ V’éÛ-ŒY•Uwi"¬*-IT’û&çàø–jDÇ-C87×™“­µ«žÿ €”bÖj32V"ÈWFæâïìÝ¿l’ªR iÜ–€Fiþm“¸Fß`÷¬‘3 ì òèÒ^oØQ)#Ò•jL³­hŠxÊÂôeøGø}“ÒËüËô‘Ý^ÉËJ²‹¸#·¬È¦¬·U‘yfë¨Ö% bV4Y9ª² WÍvp$Vmtb<%¬Ú—Œy²¦¬KcŒ ãن߉óÚ¹.G /I˜Ð-ÒÈ‹»õ÷+€2Þž¾$+ÕËD$ ¤1ù‡ebÝt$@&bê‚E¤Ü kÌ›ØE8G¶Xz8U‰aþH› ýÖ@Ú0ÍF#án ¨ÊÈ^‰›H#à iäý'rôFøN J/3›˜aKVÒ˜h´ý¤hb_¸6‘UyjÔÕ2Z€°\£L“^ÓÓØ§—A 8±YSÞ¦ïGtãšÎ!™)Ú7:²ýñº”Ð>Jid|8ØV°×H‰”û‚½¶”®f­7[%@ Þ¸ôòv®½9cz–z3lU+Õ‹ľ JùìFz ‰•4jÁ#­*`-íVcJ-ªxÕ4Û3‡üóŒ‡#µ`úøÆ2Á³ÝÕ<[@µé•rã4ŠöQê§@É6и®à}”2i%LßÇø7›Î¼oníi†»W[5‚¸Hù.Ü}õv5UdW†9DæÐ'…I€$–s÷ËA#ž²Å²íØo©js{"ûp¡ ëÚP@üñ Té¬Ú*Qc “åõ?ßÅ>­¾èC EuÛ×øözˆ )­š¾FbðÄ)c@è}'6¨Æ~Òèko“4HzA©JÉIƒ„oñûEC³•âåâ Ræ&sð9Ñø¾â›;@†‰$ó kÏr%úŽ™tlJ2c\ß¹FÔ5LP´v×ĘÂ9s3¼¹]äëÿùzô-ì+¨%qnˆl7½‘M$v”éÇ4e†N&«*Éö×È¡v9¾5` ½˜à+ÉvÆ—1Ü/¬5’©ê=m3Ùw£^ÕÖˆSrîä³­FhÉ &à¦ÚŒÌD£j]xLS6±’,èåùà u” ÏŽVzUíÖ8¼àÙñjFhd.‹|ÂGÖ ] çClĦ#­WÎGµA2ìÇ„¸}Ú­£ªÐ² ðùÄ¿Xãôdí ¸ªMêÊDc¨§' %žðr¶ â™!n&Æ'Ö‹±óöœOÇ|è·g+Ù¶Þóÿ(kCÉ]€_ Ö¬Ô;²FÒœeïñ+ɘÜ"eŒß}íÄÁoØþ™¡®ôÄ­áXœ?ßÎé•(E·1k¤Wº}ß„£‰æ"‰ý°%fˆ]9J [h„}-Ñ]h8ˆHæñ€–H]&ÂÿmßþŽœ§éÓ¶»Bn/Óh4]‡Î9À[ƒ0íÐo7-Tñ‚&™lŠŒdµp¬=fʪ–4‰aëák©db½x;Ì–É&Rj¡$ |ä¬È6+RnDœö4ÉÚ!“†vñZö-Ð{ÂL”h0ÖhíFG¸¹¹½GÓuéEÊŽ¿VÊ I˜IÈ6itk(!y:fk´_޾*kÌM‰§¬EÎð-©Z@îî0Aš²^ƒÚ„ŒOWVŸ9¦YíÆŠ@8 GUc€/(1­Ú¸òª×æ{¨öœ'¥Ý ïØ“žó9³ït¹Ÿ¬)U-£·¡ø«=wTBʪ­]IΩ¤ÝË´‰®Ü”2¤ø9À={$½Ì6 }ƒ˜Ìi‘C¦”ß®ä³2ežY9Úêx‰|7›Zs|vJµuzÕô)}ÿæ»Á1 ÊùÁÊšXÞ5ühõÉ!â€í ;ÆØ' Rp–ÇœþŸ_Çí@o²–á6Fžd[¯ç#À#õzô3æÆ±¾Ÿ½*ŸwÉÄBU2Ì•ÿ?ÿÍhÑŸoW2JSdžÂP&Jr†‘4xa°•"ÓÈ9¨RîËÄ#¼¹cJ@Ð;fÒhxd¥®à.“•¸Õ’Rî.;h§ií=i&ªVVòÄ´š¢ ä“s†HTm‡4‰ÓÄ;]Ÿ¦;š¨·ß•òïCQÒ…ÉŸÞ”Þ¶çå&ˆ‘4Í øÐ`˜£ñ3ì(šÂ¹%o`Å3ÜþÄÈžŽy|ï ·&C² Yå#»ìd»‘örÈ„P5@@‰©˜›RÕõªîjHÕn‘ 曆²ÑpÀ¸ùú5ñLºÁD 07]ÙG™€¦oZßdd+ÑÀ, zÛÚë-+´¤Œìûœ‰Ro’U-wÇã),³Ç)õ ÉsËV‰;öËÏDäÜuúй}ÿÿ¬!©NŒÎ­˜ÀQË» MŒFGÀ‘U>Yɘ•>Ô–‘–SòøxšµMú¡j1íÕµŸžŸìj:Ã.B«ªÈ†p²ªX—’H™Ïd<}@{Õ²o˜ÈÓŒ8¼¡Í%ȪZzd˜Ü ppwLíÙÂô½UAÛ¾¹Km[zUYo¡Ôù(™"››ÜbuÏǹ–Üš‹ªŽáU륱€À[oh³00ƪ™À/´TUŠÙ¶2]òÈÓùó÷2¼À轕/5Ú!M,,àÁµô}K1poh·J}pþÎÞ,$2GÀQ°u-+õé´†æÅõæY—jáã³A>áù·^ïé5ðd=ÔYåÞËòY9U[ÿ4H¡½AL67%¦õZ•8·ö1JŽ‚2ñ¦ ð!¦ÄXL}ß“JÙª[Þ‘ÒVœkf«Ò`ø0Üžj!PêšMÉ¡–õ’éUÂdÒ8þì'Vâ#j’Õ’³^G¼ èX #/B¯@ÂÆ “OG×Á´Câwîù¤ûK˜Ú}jÀl§·¿2=¨Å#zn]o{˵YúSҢ׺õö™áéiêUõ}•[ ©$:¶ƒ#¾o€^X(±­DÌA)fG²ãõó 9YGdòø™xÀH³¶²h4YŒv8‹c¸8Œ¡„e‘· e&í3Ü[%–v0ˆÕ]çûº´½ÐÎà–31Rä ×»Sµõ´;ï/sÃä£× ´¹Ž9ÈaŽZfŇFl ì¡Úpèj¥ÓðÓB@¿Û‘m=%‹uj]Õ6‡éÛ™?ÐÄÙÖÿç?ÿ¹ï$±¹[íßçÔ›§‚þ}–•€^HiÉžˆ³HGUGxãÈ4b”ð†f"s6]d›!=&O€~CuÁï[i±¼—»uŒ®z#E£ñpSÆ$–ù÷M¡ )È„Kõ ô~ÄúÐÛ“FW7ÅhtÔÅGU¯£ö‰T•ý+;bJ5ÊøFËM鎬ÇäY©k†enÄdÜ` lJ-eÌŽ@¸…Óë5níyÊ”õû º¾–øseÑlàxÿ|Ò;ªv%xË!»wâÜä–3µ‡¸Æß¯3&ŽM×Õ¢}'àŽùȯç|š.cZî"¦ëª‘Û”ùØ¿õˆi8&ÀÈ ! ¨qH½~žñ}‡Úá6ý[c£û0¤…"¾.V1 Ñ@_ñ]ð׬YÑ·§d¶ô€Ò¯—qDv#‚L6=%X¤Y‹öxŒ®0à(¶’.$1æã[²’£à#cfØ [yºЗ™Ìn ª"MY˜œÙ? Æ ާÁاj>¬T‘ÖóîÞJiš«ÑQ‰Ru÷šO +#SbÚ¡ÑH½<ÓȆÖÐ$Ó­ÙÖËù'ö”Ú] à4ÅKvd(ò4Ò§±¤àÙÏ„C»ÉBIäÿšTÅäéXUæã˜¹—¬Ô­+iQ¥4®ªŽH²ï_Î(`+g=Z̤´@IDAT_Ǫԕ‘\(ËÂ]l¯Cߣ¨Ò‹lñ|„?¨uyG]d ÂO<·J2«Èæb²•9è57&€ľªzE>Ž€#PÀöAja¢ .vJ2U R‡cô‡»)ŸWÿÉ*i-“•å׸Ëcöøzµxž¶%¨‘ƒ’£jC%|_¤Ñ4ËqÑ>z+éÂ0é­rCÒˆªôB/÷¤‰eo\-‰›%WèX½wPêjJUå¦XŒ›œ€^££–p1Zz+ ‘?L)ø¨ÒXèM£=GUbGb`Ÿ>+|7RÅ´j;DÆ7i”>¬HGƒ’@hTò‰G1åÍí롊á¦È"™Ãx;d¼†Éçœ,´·¶¬ú§þóŸë™~ŠŸ©Ò>›4]àö}©1ƒoQµŒÑ¢ê’ç‘®­ÏÃ1g‚&ö í*ë"V’Ya üœUÛ‰O=sxSTá4Änatd¶0ž!Àp `ZÞİ£€EËØY ëª*3Çh\Ö‚[¾# C%nsn 3¤‰GÖûfUV[øÝª.% à[Ví ÷b4€¨JÉ­*Òq ›ûú`DËãÍ•)וhŠ’8#¯¿v;¬>ÁláôŽÆ3lyL 4 9MSˆÿsÄ4õ:¾Ë#‹÷“âÖ›Z£q-¼)& ž"™#À“æuñTí÷éÀzµdr]O²²àÌi0‘Ãå¦Pjï¾8åëOlz œa7"Éœ2!ÈhùZú9¥És²Æi‰ÏŠ.»ŽæF_¨ø|j”‘˜z;öø4|DGLí‘ L´?† JØ-êÚ&h #Òï×f¼\´IšFËíIЈ¦¿ÕæíY ,XÙPµpSògÁçÍš'3ØŒŽßý4ÉÔ®/#­2²1² Ľé™ñó· U½1°÷mé07@Uûœa>cÂ|Sö9ÕHœ[2U¡Ô¨£Ü4þÖ&hD Õ.Ž÷\{V²¨dhJLÜV ¯ð¼ RÄñ‘ZrNp/q>ÐŽY×»c²n¹²mñµïÅÅÖàîÿÓˆ¾ä&]*LÌ-\ö±¶ª£x=[LæV…9èÊç6„G6}wA*9Vb‚»…jÎ8 ìX¸H—ÍDþ)žwPµ’.VÕ•f¯¤„Ô«EiS00ݱ¤HÖ8G%‘Oé˜90[ÕÓ#e™¦X ^—ØÎšOãX8ÈÃ!~þ3I–æ¼ê_ÿú×ÚÖovm˜½‚¶©YÐÜU¿ßŒ”Žkh|&¥¿­ç75úÜ,Ëd1›Ž¯w£ÙÂ9SêbÛxæBWä®@‰‘Ó„™PŠ ½JU‘ô¾Á-FŒdxPâu‘)µŒ’%¯Í¹¬œyV¶"®W¾fßb‰U3º©ãÑ×.óç™m#e2L¥ôÄ-Ï­å ”öJ94±ÍaÊ2ÃÚµâ6OïÄËÚeßœnT¯v¤h`´.Ï•œÏŽí°AxzžÄy&ˆ)+ÑP*‡ÔG ‰Ñ;¤ÅQNO·ì^°·¥ä Îü³%ÐE£$ˆ)æÊ‰ihÇKŸ÷A†iD¸§` ŒqlIdß@ž 4ª GL9O>[ ÆS”@¹ýk)_×ó½éµô2Ž rKÙ1–YºdƒT•äRÀ²ªà|¹»Ô•ŸÆÍ M¯“žR;’’¦Åé‘MO)¿âZ˜ä_«Ù¦qièÉà< è1ûò(U•ñ"\nh½ï¸cízûÁGÂò÷;ˆ¼S˜d›>˜«:m@wK 7@©ªÜнàÙ÷¾Y‰_·pßÝL0"qï2‡<7ÝÑ;ê"ެ±¿*ª¶LX$ÞCßQç‚Â@¶;®Š™ph–÷%}¢Ö€ÉT] 6—9¬— «9"Éü;Äþõ2 ¾eêuT­ NCÜæ}ª6Â1C-1LÄö×ÞÎ@z=F;6 Á°M<ÁÕž£‰ëJy¦ÞÛɦóoÛ™;*ɺþ3'Sê7²vÁoV-º™À¦(ú|ª¢»t´6²S`¥0‚Ò`n.½R]Èãûc’ÿŽ jÕôr>l……µÝ&¹íjÄ ¢„°v00QÎé Ž]¡eÊÆUrÜ+Á§÷,˜¦Ìƒ·Ïô@ˆÄÈ e-eU÷âÃ6ZÀékysU‹V‚ÙšÀ¬Ràe&í À¢ &ÍĪJ<ãùãáÆUňz+ÁE¼Þdå6lt¶&æ6JwÁ æ$˜Ô(SN¬‘FCæm 0] þ~ ¬™È G ¬³©1Ž=n³ W¥»ÆzžB5%¼߀u±êËW M-«EÎjnËÝs; ÉTwg‚|*9Š³Ü ¸K¥ÉVvä£*6(ð2þÃ¥ô‰e£»e17Àõé½*7ÕÀ~ ôÚ§ONµFJ¶0 D rf¥„ユú¯¦´Xžk'Ρ¡Ž3™>ÐÄ4-Ð>xL¤L,.qœ§i1Ç€M:rháýšÃÐS¼Vȉ›8V1& -ÛP© Ш”->ÛÖÞq½ª¯«j£á¦³Âì«e4²*¥•ødBlçdù8"ab<¬Y5ŸÆt5d#,¦ÞºM*ÁôæîññOÐÅ1‘ÜrðeÆt‹[<Ш=¾–HÙzhOUwÇ‹ ñ52Q-`Aã˜R¦ìRî®…@5[<¦{ñÇÓÈÈíÐq½øÜ¥e†Žný^¹%õ4ÒœW"À˘N£ÔzÏgYƒsê)°=XP:ŠÞBUh9os/¯äÈ-RõÊ¿DƒwÀñáVï¿×Ñç‘ ½*qž€#œ¹YíéØCC#‡fyµ*»½»ÈB;%ÒëÔÕ>Ý4üšpxs,²‚ÎÚ…£<¾öHXÉ,ÙtÙ,1ª \A{&2A_¬<‰à´ÌYá‘•z–É”R6EU 4V #™GX D.+½%žŒ7NÎùÝ67†MÌÊ&­hQJ"=q¡ÚÔÙ‡èGˆVÒNæÈäšýñSµ§ðæM¬±ýë% •út”L‘…”ø–z–-°Ua+Õ’ g½¾±9`ZÛ-è½’hPÊ^ ·Ír¤¯}þ9¼z>®à¿‰GgÒÓ™â‡Ùº©•²í‰úẔIß„>…Ä2R ·Zä–ñ”²¡øçÖ&r>¯^£ ãf¢^ ÅŒ ‡ådª”ùsëˆéMkL“'7ʰ,ÈšÅVbnÄJu5—XR”.Ï o€ú^"ÉÈÂëêÚŽæÊŽžF»Èjú†n ‚ÜbæÃÿŸ™ŒÆ]l%§AÚ0ŸÆ)ÙC,ø”_n½ùtwÎWõÇß õÒˆnAC2dS•M§Ú‡²#†l¸­0@>@»öé õ:ên dñ/™X;Ð&­D“›Þ"žÆqþH¸F|]Ü\³•Ú™¦GóžùdR¦!Ϊ}ò×â•”DûSy"µÃý9í˜Oû4ˆ€¡^IèÉ ºÄ÷3o\š)·¹cÎ2üîé°UåÃJ8T²Aãè-Ÿ9¼hPžý¶YûžK—<‹¾í”‹í@€t4TK82 ›âM¶Oþ²^þ{®uaÒp³˜ÏN)=ŒFL†ŽdÙ&H%I01d¥ ë’û†ÔÒûô˳µ'oˆ¿¡:Ú°[w/ãjXÉ{Ï^X/A--œL¶Fí]¡L<«°ã‚ÌG¾/©…P€àN¡ è‰4é>˜ú«’%h¡L*åÓÔx)¿@#CþÍÈœS4rbÛfî¨ îAÛDnŠª„1|,cí`Ȉaу¬Ú‘@ €+üRÞú÷9ªÎ-q»•1À½Á÷{3O>BÉ›tYÊ®@ Ö˜?€¬·é1ÖøÁ##P••^RÈJ¢¡ŽÆQz@T²†^‰&ÃŽò5øþDô—»˜”JY4 ‚"ÏFàÌÍu '“E*i>bÌ0|,€‘çŽB 0õröýl«ú~äë*3dbž5šž'™³RßvÕº8ëí×â4¦kÑ>·- ‹Œ Mú¦0q<{ßÇÑØ\9A][ Ï“Œ> d ²~¨aA@F#g (!kÈR&#ˆtYÀÝàgŽq$`âR'Ë-Íüwìñ;nYJLdǺoKL¤5ØÂVŠ9Žm,ï­ˆ0Öu Gv ²H€ƒHé•itÝ¿_=‰É| ½/† =~×fR )äY•3R¯–ž¸»e{›ÎOQ]²–™ë"ÓïÈ·\6BoKÂU·’Æ«ý~tUÛ(ªfePk§ÉDþÑž—ôµhŽÔ”zaá 5Â)µ`´¤‘¨Ï ÙgA @òÁì:€c¥l‰Ïàû1ɯ¡£êÚ-âa>Ž4ñò|`Voµ+à_Ã0²5èaoÕ;Ô¢dçèS†ñôÛ¦inúk¥æf«— óp$ Dê’alzÁ¢OSÎAI—Ÿ©Z|7 ¥&«úÖá‘ӯݔ¹ÁöÙªui¤·ŒÌ­ª5(û”-ß7z +b]x¹cx'N#ŸÍ~¾6ºbd¿4ôò”‘Âñ‰4K6%=LP£@ön.¥J9=F27«.²Þ ¯] ßè¬rƈZÒ„kQš!0òU¦ÁX£Þ =×d@Aü:bjwA=Múu½Ö%l%ëúõµ4Ôøä4Ržìÿ\Û8P €)¦kPÒ2%#á(ÓOÙÅ´¨ÂùÀ òlVŒÞÌS¶:ÙôdëÕËp«æðkP¤º, ¥A|Ú&YžýY­ŠÄD²Õ ×{éógáaÊææ¹\WÕS¾¹50>§6©º=%ÎÂQî§b†Ö°! ¥v™9«Àé¿¡±_øœµ µ/š% þõÒÌ$L‰‘mE‰˜$óé­Ÿf½xY‹jVÙbÚ§h4*žŸ?Ýi`#ð‹ØÜlMO¦%ÀÐ’ô¢vL˜f€XûÁ®É?Ï: G¹4L`Sð|šû½_‰Xµ«Ñ‹=&^; èU;â»B»ù!烔EΉËd5ªÂECoÇù”V•3ác.qÓ-" .U-ŸéÕàE½ø÷[á¨Óß·)ËÙÂæŠ9ðÇñzö>ýv©»Ô÷Ý€9-ª Z€¿ˆ©šéhâŽL0"ÆQWXv$Þ e¶¬Ü˱ïÕ™w¼êlõ5ç  „§oʆVõ€ë¨ÚfEl Ç^ŒøüS3ö<ç}Ðn¢Ü°È]æ"£·ÏŒÙ™Œ 14éçÌ3ÞRd¢W(É152ý©ÞÂrCõn%-"F®£÷VN)ÿFÈ“áá”xží ‡sƒ³rZú $Dz ÀœÐ8¾‰‘2IÐQ¯£F9€©««!1‘Ùzvú÷‰¦OP柭#À³‡ê8åpl‡2ÊÎAÞþ–¤ÑÛªª%ñ4xULnmR Ù™‡SfˆÑ.è5Î U1õÊïãdÒtzíU“5´=ÓlÛ¦ ) ø—Ó(É¢5ˆiø›RW³üÊnÿ|dJ]ÍRªQÆTå0Aä&Ãë"ɺK•`‹åŸ onU™@9T²¼˜F#¬Ä‡˜²k´I½å¦$« ææ|^[¦±ªh‡LÒ÷ßžÀ$6 ÄmÒ1Acvd^K#êÅ$nG +Á#7´‰•NÏóý·-ž3‡@ùæíÃù{Uúh¼˜*¦GvdES{¶ªFzüJúÇ?þ¡¡se¹àr•gE L)rGæ¸^U kiØN²jƒ Þ X‰Æ1¡Œ¡¼ŒqMT²†.€À7F/ÌÙQÀ”c(3ìðSÐs»}'!ù€‰œžIŸbÕ”Jø½{Cûó ÏmÛÂpd[Õ‚1ˆçH)/*%Ëd¥–ÜÄ4å.≸…uÁ¢}ß·räó:½ã”vÌh¤4BUvì¹â ð0 æO©K —+­Q‰LH‘8p‰ïGo¨ð‰Àmp«s]í,+ ü¯•Ú¶•óÑ˧‰2ž O–ÙOŠ0o{ÇÁ†ž+ÝÍÈ^¯µ“%ÀÐGb„‰ZèÐå9'ó—LAœ†p»¿—t´IÏÕ5Ùê¢qLìÀœÇº?[¦ÒYî>…v²Zrˆ'K©4SÖõÊh|cé[ØQìÞZ™•F2Ÿr›l4€,"‰§ÏÁHC¬ ãTv&ȪvXIÿêóI?eb]3‡¼è3ê©[#’IᨤÑnaØ“ÖØ¶ç`¿ãz÷¦hX ¼KÂsICœ‹cŒ#ÒÃC@ö#Ñ_Š3—»p Ñ`ZÓÌ–&½ìŽùÏßòñ!ãßJí€Ì¶‰Lø3ìȧߌý4%R>Ý‚ ¦•Æ|d&án2ÑŽá Þljïú” (»‘#²F†WŽ`èâk—‘é/˜0½c#ÊŽ‘ı•pŒëó_“æÖHI]GNc؇'Àh@ƒÒÃ|Èd¥Óüó…\âü°m(FoëÁJ) â¯$²Õ¢TÐTƘ Ÿš8§AªrÛ±S´à»Žj@ eJíñ0†•oFï0±"Û_n®F¸™{¬ï¿|gÛÛ¶|& % (ݦ3ZKkt)üvÃÌ$œ¾Y¦pX AV8Ž(ñ‘pÀËªš« °Uêµ[ÀQä@f*G˜Q IpÖ}¹!‹l»ç–P‹}¨L0¸•S\ÏÙQ©‰ŽÈöÜâ¦hkÏêÜêùû`ÊLÈÊ-àÈP©qp€& ,›¢Eµ¹È¶"k|íܰ¨W‰F¯ŒL)'£ÙÝ1Õ_ÊîŸá¥4ªÖ»+|¿”ª2'î.°éB©‹+uÄh'sD¾Ñ#ÄÓŸ?bj§oºÜu¦WâI¶ŽfµÀÞù iwæ—,·ðdùôìí°öà’Ø.ïgÓ†-OéX MU#xV”š¥Ôo|Ê€ìˆáß¹2Ÿºd˜Y˜’²WRjÙh9qXK#â§áPûŸþö·¿a…6l«kÃP³ƒ š§d@%$q¹v¼€ÉðËÙV•cVLˆëÝ8G/^晴²Ð® 샹Y@ŒZÒ˽uOFf Ü,²ŽÈS;RÖ"´d;²–ª•l‚ÄðÞ‘gÕ›f÷¢lhJžâ×›þŽnÆ¿0n+™ÃP•¥È¹l 1L#:‚ÀVb%x]dÎ!0²×ÞÐÜv̇ÈäÎ?Èö“_KËhLÖæªÞmã&ÞzÍ"íoYä4lÓüz3¤Wj À¤OdåFÀºXX´‰*Ò1Aâ^c ´ÏZ*É…ªÆö‘EGù Uma]mèéYU¥ÔØ8ŒP•1ðx>û/ sàÎ?)+¤v7Ò(ÌUBÂ)7Å1%gØ>‚Éíû’R#db¡†8Ñ/[dÊñ¦Ãø}8 {™Jµ¬À7º¡Ž] )R`À>YÕx.s7T¼&ô½ž ¾ùd+[;Y&2™–ŽÇ‘3T­y°€©•fý*ñÁ$MŸGnò &@jɹϸ×ÄÄçéªþ dx¸Å(Áõ>I˾14)·yG²V•k‘gbVGÎ/æ<1ŸŽÅ€ýÒAm½ležJªŽ•0@ã`¼)«îR»ã¦¯1 ±Y‘[¨±ªÜt2¡QU´¹=Ó;"›h!n·µt\N&SÊdÚÀDòG¾£) ð íXKÌé¿1ðñ½&e$€gËHpkWëHIƒ,Û-+؇BT"«ÄJpÆtǰÌ\du…ß§6 @ÀŠQWƒà)i&Æ·¦oQßV1 ¥xÖ(ç삳z -±@v)¤X»Ò»ƒïžb|ßÏö‡JY/8“¹å_F|Èü 4EìÊŽdÙ"÷ÍÏS)@¦ ífôüµ+@ïy|í)ñÏa`GþÃWø)‘Ú…?Ãd½[Ædb ÀøŽÝŽFlnØÑ\ؽ€°cLzj2ƒ}FGG‘9¦ÀÔ.W¢Græ¹.€~x¸§KT™¢=:öÝ ÓWš>¦£Æn‚4È]†l;Á®9ãÛ I¯ÝQ$ ÁÓÈH€³ÜòM©T#}Õëñéaz2-"[Y¨b|wázÆh‘þÝkûð©KÕQ4 Ÿ³)‘·xª}“v8M˜aÕ·yƒ([@N¦Î¶OV€®d›E†¯¤ï°ªQv”‰ãÙ&ž @vk2ÓÑÈvÃ{Fni:ª6•vÇ-4—ÜD@ÉÚ²è·*“”ÈUMÄ‹wô™úóƒ@® P*Oc®j>}+UwÙŽrnM§oóªó¬Qu/¡˜ªpƒŒÀL7=º«œ9+‚zƒt M›^v$î1sÎÈ$ÏH˜•v˜MWÒë÷@ø×5χ9ÖÈJph¬Ò` r»J¬”˜tl%ʵ`„#’†RKLš–ÁäДéëÚôU'x­fB6Nd"ãkTu„Â2M{*uÍ·±v‚™ï:™7nnç¿{Kê¬ÀNl .aj~­E WV*Ìí„9·Ê™2FUð앾»ù”7Ž•ßź#À$·ëýÇÙv¶|¼.˜ž¬kANÓ Çª2ÃwUŒhO€Þ-v/€3½Pjx#´4´F<}U½Åpex2`T•üVåÌ ™gÊþôÂdKŸ¬.¤‰ªõb"1bÎ-™²R¶9ssTUÒRÖÒªrëm¥4dý%±}"§Ì³‚i˜•`i˜,czyb;( z1ú]O )¶m Ÿ¾«zÙ’ÉÂ,½ªŽxÇJ Š<êôµ8UcÚ!^Ö.nÓÊnW Ø­ÿ4¸¹Z0²j[qØ4ªÍů…`$^¯<«0@)¾Þ41ª0žgK:ÆÈ¾™J@æƒ ËíГ˜ 6¨{©*E¦É‡ 62%e×qLÖôÄÃJ½L×tp]JŽM•29Ò»‰¼ö‰ÛðÝNÿî€éʾ™û%Æ­Æ® ÷YkÍrÇmNŒÏ‡!\;A¥”xUøüÝÜÁ}ô8á,ôÔ° ;R:RŠMÂÓ׋'hè“ȳŒQuUÇdÚ#ºälaœ£h@Cá¸ÉíÜb‘@° o= Œïk¬ ö+5ÿv»ë|©­´0áûœÎ¤Ÿ7Áà[&S’¹Žôço·£ø†òÇ“å“öǹŸ´F7 ©Ú#Ÿ÷éd;ã³¥(9+bþJŽ1޽IþHb9\Õù—-¡Ôèw#”ðe- n:xVŽM¤‡“U…'6‚'%™F‚¾raG¼L/z+¥ïogšå1MáF,§ĵ?NƒO€ì¨×Vy*‘ÑdK€Ž[£Ñôã+É™˜ø~j€ï€ß}lñù<)™ÀY]/SI¨VrLÉÖ8Y¯àÜo¨ªrAS‹ã.#u½æ[ž'¾È¤×í`JŸ>=@°Å-£}<†LÆàòA< ?žS;Ê5VŠI©¤n0f¤^ÕP-¶™Øbª {غ0UÝÚh_¼|û8ù4ÃîHÉSÔ¨—¼Æ@†ù|mQЦ¡‡¦€)úuÜ1w¤€¤ið^G Óž*OJä¶Ì*jír‹ªÚD# 4vŒ3TÂì·ì{Ïħ+;ÒÈù‡ótÌGÇ$sŒ¡] ¤¯¥J”˜ÛqžÎ¶É0ö‘ýÊ×éX9t©†ÂùàJ|ŒFæ1‰1 zïlè@c¬Ñ¸Fk‡û\x:ÊF7Ý£%“»NJ2Œ‹è…;rN#Oc¥ªlzYtTåCÉ)'À¬±’c¥xâ1o£Ë’)å¯äh%&yΤ§¤äªî¾[´RâLd-ôÌéWo82H©)•tÉ™#§—Ó”•Äp e&rdþÖSEÊð¿þõ/U_QSúq®ŠTuÙzé[¾Yµ+¢++5·ÞÕZ€Æ'[c» ¥Rúæö”ÿ?Yw³ ‰m#[x¡çM-Ë¿Oïí|äÉŒ¦KXÀÁ@ 2³ª[²ï\Q—ÿmBÇ­ Iï(`Vµ;¶†F‹€;ö±î }‡9¨’ÑW‚¢Å®Áù@•š7ñ£»ÿ¡Y®‹ÞQ`ÊuÑ‹™Ó¨bWÒNŒºuL¤^²œñmë827YU&PM )7wùó_·Výam@.ñrŒ¬UÊnrF}q#]#e#aû<ˆó¤ÏŸ ï–FìÎÝÍï¦l뢿ö'qôôËxþ}3Žú†ªõF÷©h±jÕ”Ä}Ó«døÜ‘0‡þ”‚ ü ‚²%)åõa‚í¿Ýî£o¥þö—>+bsEüZ€¶”˜Ëº„±í°c—Âp#«±û޾ô‰ã^ ™yþõÂ5FÊló‡µxœ³ô]; ’¦A% ÐD#&žŒ@8æ@ Fš¥î(W"¾MggQ;  ×âT*ûÝ—OYÌÐÒüfÅ·mKªvlb]ÈÆiļó$.ųwàCìÇ$ÃÍB ‚U¡*¾§Ï†Ü2Qâ#k¤©7=qøÿû¿ÿ³@‚”JÄé÷ÑÀµÈ0}b˜RÕ“æ6[¤èŽÄ…ª)°R퀣‰øÓpÿ¶ÄŠ!†>2Üh@UÌD eÆ·²–+ÿŒ®])å+€¾YëÚÄ9Æ[²#ÀÀ”"«|"“)ù©¡wœ&OGUëõz ûã?’NݹçÞyÄ‚cïÒC„É,7)Y-|Œ€ËZT‘@£kh]2ÞoYí7b‚~{¦çãbô9·¼cU-]äLŒd.Z#ÏH9U vÙzékg.0‚’ƒ’|Õ2”Uå1ÑwµÚ[Þp/²ëúIu©Z¦YžŽÆiWpWŽ‘ŸÀÖÐ%8§tœgÃ0íæ d™$&P5%“6!ˆ'ŽQ}ü•ÄËÃÍÅ3wœ€aÊÞ„g¥¦èJì(7B¶2s]0R!«F¦‘c´°‚i(a¸Ÿ¨¬jY;™èA€—gÕ£áÏŒ¯3M©¥#q…gí€lQM߃#16TÂ8úˆé“m™@n½Õk¥«R4Èçrç1MaÛ\UN©K8ʘÖÓèÂÃòž1†’>q Y>Žªû‘ÙÚE_f2þ™XÀr]|(HG‚ñ<›r:Ÿ/#q-ÓcÒOìå ²”irxg­q2 åk»….LOäGãÓ³Š1¥}å´+a"[£¹ï>ª¿~ðæµÎ¶!ÒcŒ¼R+ûJâl÷ý]ÐÞ‘ù(í2ø¶‘ûn‹}¢×ï|N4µÐäæŸ->Ÿ&*ÙPÜíÎ#”›E&rSÊÓÜmHìûêGö«ß1Jüëe…Çmzß{Gn‚FKý^nh½²ð›·öÆÕÕ]`³â5xbC…éHdž:Òãšå Äù|`‚p%$F\¿ó—GnÚóŽxb]µ8 õª]MaÕ”ô–!€ñ>`CÉà&ÛÍ•¦‡ó7¦Tªƒ4 ³.¥4°væ™”• ]}}ÁTç ,2Ì?Lé02OG¡Å,9,÷ÁÕ+ôÊ}«ÛÄQàêRJŒÉSUI\á¹BS\¿ï½*>s²Àsxùw |Ó̇CÕ6ºœÞC êj]HÇVҲݚîX‹F”Yż™›£ÈÁ+2»fÔ¯Ä}ã­‚/†ÑÈË·“ÒQt”)ÉðaJG‚H-xÑ‘Ì88²)µ¤‘ý¦eúÀòi7bJ²*%+dL†œMŒÏ¼¹&íïK°–Ú;²m²éýd™àîÐÇ] h †€‰2ÈYFÖÓû iZ#°‰âe-2ÀbÙ/ýYK%ÊŠö©KcÉÐQÀ‚²5ävCv€,|-?ã3—‰Ø²æÊšZȼ­ld¼c¤iºjz •É]2&Y¶ŽJB#F©® k©db¶ÄÝ%žÆ1¥Y^À1ÿr¶°ØÂ·ªa|‚F8â·X#0µ´ISú“O“ ¬D#´´Û‘”xƒ`Õ|0™TmºK!µËFˆ×6™r£yrstYzGÌ@æÈë÷ùrÖ%矞‰£,0ÇaX‹H`«ŠqÌàƒl%@(¥‘ço(Ì-Gá¸õË`´tY¹ª wÔÈÄñ²®ªœ Ðg zß« ñª0Ò8É‚`_BGæU Ó¯ê´w b]­§ pþüÎ¥‹ÒL'Zȇ‡»s^ ÛIÉßÑ`¡‘F‹j{c`‘¿jwÃ(YËÄJcè‘Ħ+ÅÔ‚I‰ç“à̸Cua„# û6d߆U1=ek(µ¡%ƒ0 j:J¿•îÀ“T•Ú¸ÝVüÔÑt²~„rx/®×Dhš ¼n«¤]XU´gk »EU¤­ú4Ê ›A @Y ±#Ü>²’LŒçl“F‚[$A½dõn(@‰lt¶¡¬©—ßæøõ¡+7‚P’‚¬F˜g½õ­*Ï&«”¡,<Ѹy™¤käÐ3®½×@pÆwAâÜ΢w=¹ª,³…z]}â¬ò OÊ_6KcËàMl:¬_W $à¬Å&JaJp·&£o"¥R&yâ#±Ñ4‹–¯DŒ§ÜkÄ´ªmUš– ÈÆ¥,gÂ/êR=& bà6ÐÎ{«.‹ÑÒ³¤_{VíéX»F¸€¹yÀFÈö‘…iôhŒðÈŽÚ1d²v¿%6ˆ;g(÷ð¬(ÙêÒ‹”Åoýë_Ä.c;…é¶´£ªœWÖ0œOšH¸pÌdJ¼-µÈ~!®Dã2JÖÝõÜAÕQU æ&0° @æJŽpº{Ä4m¢zm>Veꢌ Ø“¹ —çç¯ñX_O¹•vÕvæ)µ·g [âÌS–×È3A½uµÆ‘¾¶-F8Ò$sM ¼'jþdÂQ¶Éø]JrUîs´I%â¬Ò츪Ukä0[ââÆ½Vî%ê5n]H޲ („!€9¿J_<ŒAÍZ#>ò=æöp~À²½6GOÜÃöÈ&6e;´¹#1+Y4®‰­T‹’¼ÈªG èiÌõ‰øÓ®—@©´dí ãU%= ÓÈ̵$hPS61Œ¯Ó-ñe%æÈF 8ZCÔ»}ð‚É6g<±×°ÞFÄË)›èX cŒ@fãÛJÎ<+Ù”º”"d&1ÉÒ[ûu†ñreǺ”4Nc™µ*e>ܱo‡®€ôé÷h”ò·ÿüç?»m=ÔÈrªŽ=MxKà²ÍÖÂ9%œ›ö¬ðÂ=iä³Ê÷kÇŠÆ‘/êêÕ’a¥”•Žú ?L)×Õ,Ù¬y:jH2³²†lÛ”Ø}Ðg˜[oX‰L¼>¬87‹^‰cŠŸ±Þîc«¯‹²…á~€U[@ŠÖð—øõÃìhJˉ»ÅJMœ, š›#,Ú°•Pm@ Suy&?ªž”s£•ÒïÁ7”mûÈ¢[·G-Èi9Ð`Ú¶¹ r«±èFÎV&Z6È‘ «ôµkTê)ÒÇ ôª"‡ºš%”þ†¤hºï†RǾ$ŽÛÆQn"žÞ¬&âSjzb%Aæh! n¼§öÅ2IŸ,«U)1€A•t¢Ñºf«–‡Ë<ñ2¬ZcÕºà–¯’FÔ’òÍ•ê-7&kkp™„k¡G»”ËΡ|†åZö&õ";vµ¦¯+ Ÿœ‚5"ÈE¤}èÛDÉ'bPŸ¿V7¾Í°t²Ï¸Ëà á4pÃÈ1”ŽaJU€¯©ÁBIÐ5UEz|ÇÙ:"מ?q Ò¾m‘ÄJyr°FÎí€É¿k"9¬+¬KPÆz3#Ûa£7¨%e&ºjÙß”ã[†Œ§·¢!F¶U øPfâMIS—#ÒoŠöi¢ÆdÛ!¤AbËPj郆…™<%lŸze{‡äé(Œ&@v¼ûJLÆ-¹Q{X£j·ƒÉdÁJV"ÎÇÎ9Ï@d•X=RÔ¤¬$;æ¯4e†1 {U%Ðnm¹vX´ƒ[£’ÞdÜZƒÃ„n GÀKÒgÌ%y¦ä©¤×Q)³¡˜ªlfG:–‰û垟ù ›.÷.⿜óÿã9ýh7þ}Xõª²ÈЉÙGÁ¡[´*&çv»NÇ!¯d[Ëçit¥njOí˜îåwqŒXµÑ<1üµ7…^#¥c½0@€Oïè =#†“µäÐ>Lú,È0dª­¯±*ÉE¢…¬Œ×[ÞYI´3ÿžñLÿý÷ßœ›Š¸#Žy¾_»®­Ô7PF¶JJ¤’01æjÜ)‘Ça-pæ½Áuúü~ÑâH@4 fâXK‚LàF¤DRÊø¬äÊÔâóÓˆ”á¶Rp%xn˜HUÁ¶7çLæXµöª²#ÀGq#´È-O)׫úçUÁùîòIô¹5e¶@¶ZúæHϼFÇù,÷¿AַŰ9P¶ÛÂG•Ò±ïàH³=7îµ?ýWÙÇgU—A&>7™¾Gh ’8A-ªV:cl…–Ž”âˆ¾ßóvp¤~wcLÑE °1² S%#¸M'¥§ôeÿk×eÜÍ".0Žr>”øŽxñgY&F—{AŒÑ~ÇáÍê/¶[@Kk×™§ÜÍ%kàõá Ð’8FvŒÑÛ•{½a)sf¼Ó9Ð#É€Ù²ŠìÿªDn½¹»'&hæg‹á™CG9¦¬%óxâz‘Û¡F< €¢Md¤Lç#Ï®%¼M”Zs~ƒøöˆ¨ý¿iÊ=ëH—@^øºú|äQøìæªa$7XÜ®9ãE]ÙªúVÁ¢j]ÚOG¡jX~=i2¤'s$¨— ŽúÌbòQÊJ©U1gðó³ÁS)ÀqL‹5}ƒfE†tlÖ°#ÿòº´Äl OÀ­¼à˜r«j߬X;½ Ä´Žr&ø¶Õ8^ßGn™©‹~†°¸òÏï;Û,/€ÆnTU‹*&,h„¹€ôUü!hnžJZŽÅý«Æ¥ªZü^“jìg@¶Iü|"sSÂói.ÒEúbÃÞç9ºÀèõt4ް*0ŒA]|ú~æ¯ÄÁ @ÖÕÎe>É€ý„b|0î ÚÙæƒÉ­N“§öÝ%Ÿ¦6 Ìéx m•2w¯®ÃI`ñþPÁWRMPÎGv4nïƒÑ-¶™À$ÓN¦ê}ü‘̇ÆJ˜°#H´^n½ÌU1™88ªÖH© #à® ˆH&‘ã­€p œ  ‘5vSU%< rN,GÒ'Æ|þP:™]¢IÝÖ®ñ2\É~½‚côX C‹Žœ»<ó– U;­k€§AŽ>í] ÎŽrí­ôᆶ€#‡îßPíu‘áÙ‘ľ…ô¾}ø“忏ˆhPÓU…^þ"™)«"á™WrdÕ2ª®oGÁ­ëhŒñPwÈçw¨^|Ô[ ¹[¨âóD¶ uTª pÄ;¦9êÿýªTi·›f eú:{Y0¦p tYs»T¤*Ü­—ï^1ž¬Ì÷ì°*CbdSʬT9¨Êp›ÀJñz‰ñÍr|ïâH¦Do.ðF+ah„#™YSöÇŒ’Ñ"=@ÖªéµôQæ`è•~¸h®ýIö¤ñÍÑn.LiŠ£*bí­Ôª]G&¦YU—£öðH½r£ €ÜEG¹‰HX¯HÜ Äg#TUX1á|0íFƒðí8lJk ià€ c hä`°FL|íó VdLÚ¹“ ªÜ¸¨±8e&+µƒ¡BÉQ¯‘Ʊޘô}ÊËT­×1ÁoûÛßúÈÙ ŒÿÜ #1=MkaTE¦ÄµT}WÙ µÕH,”8héØŠm–,Ÿ)‰eU¤^†Ó$sJ9ÿVeŽi&’IáÈ™À±‹+?¶~ðšÞ2a¼#½Ü‡1Ža¤öÜZ^Õ±G]nI>ML¶.|3L¬9C%|¶xѽfÒŸFny]b2>97k†€ÈVÖÛuÈ U$ K…Uúž£ˆè)û©óÎ9·OTܾ3zþùTÍG^4¢_H]nª…¾FSh”Ê@bJ‘RKUb$M½x>ÈÇQµUÃ~ëò׺šŽ÷k®jÉsË8ŠàßGâý™};˜Øª²@jI&p/ž–!pd%spÌ#0UzX&P¢ Ëp‚Á¢‰i•RÊ‚ƒÜ7z Ä4kCõ) ì™ ‡L…j³|2úº”º ’@ŠŽaŸU¥¬h³ŠI&$‡œsh‡xÙ‘8éÈùGÎϤÜ×)‚º2Jß4¡‘¦>¿ò¢HRÏE'¬-æÓæð}#dß¿ Võ á[Ñý§o-¥ª <¦uÛAobdÛ3ÁXÆQUcñ€‰È±o¡cÓ5~G.³j“Õ>žø³è½H˜c‹Éd=޼Þ~Ôûà™û‡nù} zž‹ÖC²­„iÄ{qƒ¶<@Ùõ[ƒ¾R-ª-ƒ7hxƒèû»‰.Rµé“¦HÐè&ŽgN™ w䟉–]¼’cP•[2}‚ÌFõ䓨ÕsÓÓp–öD98Š0¾ù¯7áÖa4‰ §i:L ¿¿Ù+ᑲ¯A[ÙÄÑ,z> ó·mCHÕLôr¼v‘->™§P‚ù˜¥J#™¨: VpVåzÉ4 G²98n‡Ä2‡r¶f]½ÉdzØX—A€¿hÄçƒ$+-œ’Fh‘ñ`x+§$º5I%™[dƒzó‰OçmÑ%`΢v wUíí95v â4¯²é,šRF¶óÈVš8ƒ¼!’'Až²®”;»v®Pg×ë¯`0 ¯.F\µ a vd}f=½*CA¯è F]ªïŒc¤lP;”çæ¯0}EÌR2W¦çÙ#ÂJôdÌUñªy¡…ùû:4B—ª’h±Ä•ÚYF2×NO)ûßB0'S•‘FËfÑ Y)‡Ë7¤)êÝòHSdé H2&¢­êuÄx,׫V¢™¤ï­”ªäô͵•€»2 ºÑÈfaº/†9ÇþåÅ0¡‘[nª•'°=[¯}¦ï.dù¨N–mG/¦Ô§Ï°…-Ó‡CÙ¶¬=‡ •ä!á“a½Ý¥‹Ã‚¸#}¶­Q—O²š'FKb™Uv`H†Á»¬$€ð i8ËH¡ËqX—ëG† bxdí=^•­#co‚옘 –µôG¡+eã"1tä"œ8s¼5Žú†’ÿ¬ÑûÀîëØàî¢7Ãn”C/§Ó)™¨Ö˜éH_ \{¶µÔÕo{ëaf²ö@ Ì wÜnÓkÙVUOá•`¼›žŸ>ÝëüÉ @Š‚)’vÌI Ï‚#s¯=¥ì»•XŽÌÓ±;T%à d³‚1õÊ‘|¬ë(`»nÒ$ªºÄ&vä_K`GÕñÃmÎA‰? ¤1¦˜ØÃ!?KÜÿ¶AfamÕÆá‰™§×D–U‹àø™¸O±}T Þ4QVÊ¿ö0YÇz7«SÈ"UÛm ãF2¥a%JA–žýnr$Ë“€ÒQU#áe@K›Ä‡ Ú@{Vlñô’!,·*=Rð™IU@¨fÓh÷é´9ͤè)ÍÕë+w|¯£d–. 1M£ñÈ®£côÊ ÂJùo±3”ñL½Ü®¤Ý­‡µ‹&*‘96½]™à ÏòÚSF’ d[5‡dï/eWÖÛãSæþ²Y”²£*g$ÀŽiüÞ0Ÿzñ²Â‡æ@Ì€ :§Q ÔEà^zSâ7n 7XÔ®ñ³êF]--m"Ç3o/“9öŒ­Z5e²&ÂU!‹m˜U7Š'nŠ^Ñ&¿ýóŸÿ$΂–©p“aG –i€°LpOÇ3²Ç>$Ù*Šœ9ðêaAÓÝÊÜüËÙô½Ýô×Ìkv’.nÙ¶¡c+éê›ä¸))ÛS;1‡fÕ.· HŸŒ!RÔ(Ù+¥á©ªWäïkA€t¤¡WJÜ”ô²à@heÑbrþ-“&ïFÆS0¯¦izŒv qö»Ê9@–é™ÁD `4†¦ a%ÇdZRjômÎ\IÐ;Êp<¬‘l-˜³åý¥`ϺíˆÞA#¤Ô7C Ð+LôG…#ÀdEœ p…ŸODuæ#ze¥€Òdµ4Ô8‚&t4:&Û²’ÀË5Zfæi0ªÓa-ŽÍ;ªóiž¥¿¡ f"ë#á‘5bÚ¼R†,Ë雋¤¬¨QnçaŸE›”óìÊó'îÊÚ…£0H{ƒÒ+5èÖ)Û›R»<+-ªgÌ Gÿ™Œ&Ã4ì^@IDATfÍI€ ¿ía¹ö÷Hï˜3 ·ØE¶úíßÿþwÍD[XMßo ‚ØGÅB4ÆÆøô‘J@♟æ{Ûñ2†Jp®}˨*á1iA Wííæ“F—*€y¦iÐ0 Ê³«uì{ ·F CJ_µö×bº¼•(á iTEíx–i’io·˜î+ ½ªaÀ/k`J |‡œ?cø;já_n^“ çôù§ï#VM ˆd¯q¦(•s&ÐÎ_UÉÞê¸|Å]ª˜¦ôÇC|z¬æFæ«ønÛ52'n4@)(™—ý‘³•™$ LŽÉt!M"óä¯ Ç¯Io„’.Ùb2RµIL½lµ4nâ€L 4O>)s“S’Ý!¿¾rJ–uås[õ&¦…ÆgÇÞ6ÜDLdVuÁ}X·=Fâ”@>r]ù'†'†‹Ãí ï"-Ù²£h7`‹Ù§#†¹ÁæÊŽò鼟”vŒeµW©«MðH]d1rQ &ÐRï·øK£Ô5é'³O|s3É0Y×Ì%>5”š…øl庪þö÷¿ÿý‡ ©†-Z[škõù‰mªI½Q¥&éí!Aà8O†Â/ø”› +Ñ÷…pLŒ¼}çab < ú ¢ZŒŸg-Ì‘3Ð_©&Mùz|¾I³ÒÞã¦TBŠZº) AÃ4JH jXÆó×ePS\m+aúƒgdzitqÃ0 sÆ§É Ÿ&^îO#L¬±W}òÏèçD2•j§TªŠï•"ËZâYY‰R#Ÿâ]“ ’r†¬b”Î*÷Øa2ùÇJõ"9T#ܱ§ày¼®Ù±=s€µÀÆ©¶?MU‘ŽdŽô˜2Ÿøvà飯7\5lǪ¬…•FÇ~[Š!ëRÄÇúû[ï¸ï¢D&z«ðònçc3e|ãÈÇ\9 ¼_2¼Æ^£ç²dÓ3×ÞSX¸·ò#a±ºˆ–'†ûóƒRIèêý7¥G±û¶¹£Ð.\–€æƒwäãhD{æ#kïR0e²em…¡t<î·Â‘•¬QPÖh ¹¿^ÃÔ¬­`öé̇U³˜ MÔÎÇQ¨ÊûÍB0q£)é#ù`³’[©JÓF¸W¤€i2ÁèmPŒªFíŽÀi‘1IJ£%1»#2g ܽˆÉúã°'j±ôùln#ÈxÝ Î¿q ÇÈ¢õš¥Cùš;о¥ ûìȈõŠ®“!=%˜&±ªˆ«:Ê;6ÃVãJY‘a˜o(Ð7œ M·~0ÂQc£óló#Ș˜‚weÙ™Ì,°Ü&ÀùêsÌzŽÝ P©êŒ¼i3wÌÐÈëýy -¢-Û†¡¨½Û„Ò7I5¦ÜÙn7$11Œ‡«Æ8öÁ§1ˆC]òöi ŒÐžCdz÷ó‹©Ò•|ÞÇ Ž2Ì ègháY ”àwó˜ 4Ú<ó¾(J6!sŒÙkìÖ@¶Ë½C7… ØÞ;«˜.˜ ² ›Ò û„5ÂÍÂXì.@XNÙ1e×Áäs|¯³‰}Èj$ýÃhú¦¤—÷ ªºˆ‘0Y@®e—¢¡tLïÖüÔ#09ø_pã3ø ŸB&d¦O8e?–}d¥Ü«šÒ âôŽª—>¯júnQÎáÊ?ßäöLœ&«4ôMçÉ-§NÏ@Æ×Ûz½ ´tå)·jvSºàzg˜æÎ9)ÛH>yj1Æû#¹%{|LkH2æ4°ÆöUé³è4Ü”“eÅÓzyŠ•ðŽi"Û“CU8¯«Ð"l¥*à–l…7Þ24Y%îe0¹1è×÷µ*Ù:v×Ñbb@I—v¤€ÏÏX÷ùì{_¶r“†gÇÆ´„#ÌhvúJpO[Y/0#R4ˆOUYìJ)e/a7 3éÂx \³=#»‚†X»˜­Ýª’Ñ»ŽwËY¡…Æ—ŒOoÛ5iÚ¡LÙ U·€”¬ÛD FV2îJN"¨4† –5¶ƒédýJ副*ïÐv“‘¢ü¯N)íŒÉàS5¼êy‘{_J¹µ¢­º—^Õ¾!F4WæP—µummGÕ6‘1²  kdNæ˜1µ;*u…¹5·‹À<ÉvGJí1@S"«ÂZ\§Æ™ÂÅ»™^£ÑµôÇO¥­ÚËSò$07JD0Žkߪ˜ZT‘¬ÒìS‹©=+Œ ·1¥FØ2x˜¬òÇ$ÐH©]´ ^ð¢Y­ç)nÇIç’ßk¦‘ d£û7Ï dæJoF¦”1@&€Ð"7º#†¬#U@¶ü~ód"‹Ú½}dô€œE–¹A¬ñ +5vA˜g;´=R»ã‚¦v Ò½‹œÿ¨BÍÚŒ`Òb¼0ÛÃ*ïH%]˜u²•ùdÞ$+âªñÞ(ÐsÀ4=\ƒd «¢ãpÝ\$ÃLhrè‚n®ŠaN8ÂYaV¥oÊñ½%“!ýePU`E¥ziú¢Ô¥Ú&Ž›ÛV²Q)sÙ±•|±\Ü wÎy+x_#€XK]2eO§cnýó)(5ùîF\o˧ÉAö3n´?ä´ÛÄnL”Ú0F‰IYÖB´vX.šHóþ ®¥v™²¶†\;ÞDGhiÖºð˜ÍÚb˜.B0 ˆ˜0Mkx%¡TÕ\¶J¢ŒR{Ú¤O$šÛwª·ã×·±=8y“ ²Õ˜yÇaÊ<™ [Ø)rû;Z)Ï”íÆM©LÐcöé÷åÙz^ Û.¨«0EɃ8Ö¢—²ÄJ¢ß›Yž (ßÅÚ'Aþª¯W6NÀH²xSÒ˜¢ &Èd³ák›X5Ù{\;ÒD#0Ú)+Éx“-ŸÄX„×2±R¶Ê…Ax¡‘mG¥}+`¤v  –­·q”|ÎcQxY …‹\`¤ðqv<ÞT¯üó:2Ä”«ÂôhQ8«ÉÎàïï¥Äl í ”sm˜? ì{Ö8¶Hú¾»‘‰å<‘¢—!n-ª¢^V°jUÙúT0-FÆA‰¸7TÒ…'ÈSé=nœF|b·àƒiœ)0>YJÇ<‘ýÐú+C‚6o«p½ªZðý+ŽÖSb((Å4ªÜuz%™˜‰È6Þ‘¹@Š0Ã=~nŽ-ÙtXcs1ÆÁ¡ܘñI@¶ ~ÇMGÖ¾FG#tݱç“R*ç9G/œó̽îÞ/âüöyeÓîs¬¤7CÛ|!PÒU£\ ¨Ë,VæúÄa¤PEÚc«FgŽaøÊʪ”°P…9$cÈJ¦aÅfIs›>IW㜵tÙrª°Yý„â9 úZà¾öL(µ÷wü”mwzxL˜&Î “¿^q|ŒÆnähô¬ðÂQ•^L†¯—íUý’µªl“F'ž¬·Ú@ ùwAJLúÈxšd3lVÕkóùUœC̹T mß5Ôº@"ïò È·®>¶x9¥ljß6ž[ ÀS& áE]­%Ó„û÷tÄ)a펾Uãé…‰ `†-FÓ”FÈz×è(ß´wd¨êX Y£Çÿø6Sº5™’hׯ1Ÿ3ò^œsÑûÐchˆÓÀ UÎr¤eD›mÊ­œ[Wí·€®Æ…– ›Å™2÷KÄ&ßÖÏoHY¥m ™h‡â4ng´qÍUí¹2qÄ7=e‘ªvæãÈDÎnÊÀöa«äØ«æŸ,àr½Ž<'ƒÓ”Ý¥}¶3vª”ŽøÝŸaßd”iˆóï¨ëe2LŒ·aVG¹3´Àôk×,Œ£ „åH-Žåݱö妴ŒL¦]ŽyWu¥ôÆíîð_ûIÓˆ9×¾F¼.™Xw”Ã˵äƒ0ÂñŒç•Œ$ó‹%ÌðN8úÌcæ¶\Ð÷Y£0"[²<sˆ¯KµgTa½JÝ÷ÏJ@ 4wàù>øàà/Z²Y2‡Èl1€lÝ%²•¸iÁø÷]0† An›XcþpGULS€..·-ž ±* $ ‚[¾–'ÁFxö^#RNœ d Tåob“œ¾­Ú$}ÿš-Þ¬UµàõâkwT…ëuô/º õš¢Dcm›4Ÿ'½Þ9à‰‘dU] 88ª’!hö4p·†Ä~×ÃB—¬%Ø<[]nDC‰wY q/Éç¸ß%3!sÌßPbV¶tTÂŒÇ]¼#Þ ‚”Ù€ð2n2%&7LU ,§ÙÞÊIe΢µÛéXÞ¸&ƨŠ€Ãùƒ”eýY´Y%î[4€!Su¼{¬.ÉÊÑ ‘Ð’?èSŸRï;‚À‘2AÙ1æýT8W¥ßǬ)f‚y•|”6ô5Þ9çe¦ÇeÞ‘ 8îßO(Ÿ½R%†ùÌèAÞ)õR*Á€ŸäW[Vx/l³-ªÌ¿$€ïWƒ^ïiÿ¿üå/a&d0P®1²ÅäFÈÚû—’°ßhµïñÓ[ŒŒ OCw¬Kv‘Þ³{QÖEðg8&1}íÄøîÈ ›ÅÁ¿>ÞP|Î5Ê•ôŠª& G%LÉÍ,€‰LÓ,Ç–èÛ'e&ÝËþŽU1‚˜3€- ·~x-J¤'há¾ ?ÈÚ-ƒ'k=cª2,ø7‹ Ï(sεk-ª5êR ³UÅærÀ§4È·Ó>4@ÓÓÀFxËèÊ6 ž3²ì‰¶RͧMÎøçSæój¡OÙP)÷’µ7ÅU6:¶,ºBIf+«önÀÜðÖ ëjJÄL”äJ¡,Æ×èŽ@-Lì ÂÝu©¶I½[8.)“&0¶aÊ…—HG|z¿蹟!·Wµ’ÜÈzµ $±–¬´x˜†'¾öHúJ³ÐH¯$2,'¨T2ƒ|gßE­$ˆ•DG¥ Ê'vËøRÖ…w„׫ñ¼Ô÷yUu‰€œY©åYÕÅ Æû.œ¿cbÇZÒ#ûê‚^ o·ñ†ÐÏÀûb4ÅÑ3¶­%…ÒîÞ—¯ÑJ€jS®ö0»]VAã5ºE³¤qþ”}K‘ý z}²Ü®ÓY^¨ê™•0€.ƒàhÜæV•‰‘sVrÇ~ti™g¶}¬J&¢vGa“îÅ\Éžü1‘ï Hþm¥¤WWY£ q´Y†ë2K‹Œç“lŠÆU¹ÙǬʪÚP×Ùò®d(& ”idу wq%½]¤åÉÚ%¯÷»j³äzÏÔûòŽB»Œ!€[•sWh™ ™Rïƒp%íz…U}¦ñxá(;ÃîÖua4fH¹q§ù6 Ãò±¸ß&½C ÌRnávhmJM)§!v”ÉhxrË$ÃÄ™hqTuüí_ÿúWƒ×`äù² NÀ7¯ú)WêÓÒEI&`¦ìøVÃJUS2"­‘FÉ훪 ³­dy¡·›ßŽs]/S».< }™’¬jÓ+Áý89ªz8 ½ (³­[Ó•D%¯§ŠLðVx ™qF`:Ê6N F£e¥>8zÕwvÖ(‰ZFjg%0á+?ûoÙ2a¥dòd€ÒdJ9×› AµàkG²ª]î<Û•fØwð,úpkO½uåÙè-C  Ù>~íù0—É”(Óc GJVÏk¢£ÀÃZDŒÌ$åºY¥O‹ø>гRb‚!0î'%†F‹¿¦8^›³FCý©é:ªe&j²%ö,}O¼pšQŠZˆ)˲ŽùÀµÈ‚¬Í­Ô¬þýOX¯HÖWÚ1»Å4Ù2ú³YûÝî×o§dÚ“QvqG¶½˜)ÀM$k„¬Wªµ«ÂâÝ/ö ÂPÂa¸^U M˜ òA¦ïkÐrí@ãÈ"[â_ÿL‡uŽfô7Y˜BP×Ðϼ â{…n×6O0“ºã:”ø­q¯‰o.¾ éu9f–«¡ù±ª’0NÖÎ\Ütb-"畺ˆªÑž{ï@I£Š×Rãîå_£)Ž5]uãð<ûߺÁ•fتH@ÎAU´‰Ý®°Ÿa2U¤ÛcЉ~4Ä#õ¶˜ªKiiÛ–<î×ßêwÄ^Ic[ÉÚ·’c†¬=À3¥ÜyfKX†R)g žØ‘9pÔ÷º‚ªè/û€F™ØtVr2X{W È몑3æ½ü–T›ž’9AWÛ•zŸã~¯q ß1÷ÒàRÕz·~pAƒÉ&ȳï#ëY71“ÆÙ“Æ#`*mA;à#ÖÅuõÊUß%½º’¹)Jdm;Ô{L¯[LGHÆGøýÓ?ãòäÖ-6¨]îSÆ™œ‘÷°‰j³0);2ï` ß«îkéF?|”" ¬ÝE2”UµÛPô8˜4ÍÕ‹¡ì˜yš&bè}.Þ™8}+%–E ÞdH€‰–ß¡xÎv>ߌ"#Ã’²Ó`oG‚Œ²ÀñH]¼ûðˆáWs&ÝÿÌËÒð×åiì‘RÀªnå˜IŸ²íSb”4<9gÛ¬–ɵctÉ5ÂJŽ Ç­›ÂPD’ÁëÚÄ–ÏdíÈÚÝÆ3a娲ÀçÜP9²–Þ÷Ô[)‡y"•2ñ ݪú~7:Ù|Œ†Ë”4ý2Ô‹dÌU¡„—»f¶ŽJÜÂÚ0Û”ù°mç;á¼¼.2¹ÑpnÝ”€2[¹º)¾ªÞÞÙ±édªøFç£$*1$5JÄ¢×ð ‰ë%K³M怎IJ}b:jç,'Pr„1°YsŒÐbÇ4¬à 1õ:Ú-sUÕ2V|‘¿ª%ùG §Ôaâ &-i¨hDnµ`•Ȉ‘z­Ôt¿ú}ˆþ ¨Ú]Q—ªñÑâ:HQ/PWúdÆ9æo–¸¡Ä­Ý’d‚¿Ì®÷ç› ”¬®?c‚™Óˆ3‘•M§o>#ʶ¥Á[£kª*¥i:± ÁçY¦I ïâ0áj;‡þOAhƒI…šœÚÆJìd“äx“`LJVpGVidrLʳþ÷{@—ËÈL”ŽË79. ÷•" ô›UY›ë5è½ÈYèΕéU‹LÊùóql;Yc]iðÂo[Ù¤ÐÂÓ;`ìàw <²c[•ÏN7ª~Oç}´Ü!g“܌ظJû™¡Lz¨Ìi)åÚc–Q)½ã€}ný8®€$pìRí‰d22‡2’I%L]Ž"+¤^¸O­\d&°.|½Ä=rG¬à|®ñù x@Wk`rýجªÔVÞ¶‰=>+G2|ÇÖÈöÕ×!ÐR&hál㳪¦Ü™Ó8ö”¢[kUZdÌ"O]݈àÕÕ0oûñý~©”`†îÓSî%«"+ɪ¢YŽUðé1@£$ê2Þ¶pÇ€Ì-C-S£Å|:[iÔ^Ô¨%¾ý·˜ª–ѳ’1¨šè ª4b#:¦œ SU׎ù´9ÒpGžV­·eÂ{íÜ\vŒKé­ùëb¾]UòƺFkåµ ¼^Y8 š–pTÅ_ÕIVaÞ8ÕM„‘GÒ‡hüAÝM,Ϲ»ùmëË»ˆ^ÇÙfB eí«vhUX$`Òž‘ñÈ™Ñ;Õ"›ÒßÓÛPàõÒ @0DÊÖÖØ,b¥ UýåhÔK_5½5êê²ÍPÆËžNôlõ ŒR;²úrŸŸ.G-x±¹3a.jaЈøZˆRƘ~¼¾—¢Ô訚ÏQ±ªF¼ýÃŽíß_}í3׸;ævGs€²ÏE£®N€¤¡lIúº(3”‰·Ü&UázMQsnd2Li®¡pÓ)3 LOÓt|‘ƒ.G¥<û+v¤œmÎ4;†å€5úÉbÅÖƒsƒ»ˆv$œM`[Ûq;S¶OÎñ”#1ôJ†â,ñýý‹ï«nU-rŸ>¬‘,þv|°Ǿ -™¿ééË&òäãH#Ç€Þ®àŸòH è•䬀¢Ý”2ß2ùO@Ï £$:ʘ0%|f¿ÉT30öŸØÕ½þí?þPFµ}=e" H 7,Çùá7&Rc¥ŽJ{qL·ÅÔ8eüwøùÏ÷«ÖÞˆÖ3ÂuèEÈLèMÓVãk‘)kQ8$ê’ñ?rÓkQµ!FÆPò´&s{Öž ¯J)U`_U†œôã‘mþJZ¸»f"ëè™È¢¹•€dF«ÆðÀFDf[&PÅÌE·è8ÿÜÞ%k$ñ4-¨ó”ý<û•ÔûÀ@šzýö̤öx-€xgµ§wN`‚}"H-eÕ?Ø5TÆÓà‹87¸#¬”•'Òø–Ú‡ SóÌ9Ó;¬Ýô>MíÉä¾?‰eŒDn™¸& ô6H&›‚¬±Üˆ“íhzuuÎ0^£P•ÓÏy¾ª’€eéžEo4ì&h| q™ÄÀ–Â1&ž°›5”„ÒZñyVMœƒj%€~ΫֲöŽ&¦”Es&ö‰ÜʯÇÞMö ï§àó=‰‚¬ÐçÍËÔ4_G)|{èÒ4£;ÃÜðd2’É¿cÛ>&qíM7¨ LØös^o?ÿ°*ÏV„^™8™Œ`#´ø ¯JÙ _ÿô¦ëšObú….˜&&G R¯àÌP;2¾Yu¥‘uÉHJ£Ç õ×7xš¬ÃyÿM>d ™Mâe¥á÷Ê•´vX靈²¡–nOUÑæ½p_ä®?Ãl9çÀP©Ýèá¶UíˆÉ3½ã~cÌ5îÝÙS(É 'à Eë SLHhG†ez”Ýôj?_BŒ)B•FÉ7_KX¨2)ÓзaÏåHÖ8†JGQIÖÅ¡^@c%b½œ+õbU2­v¡”O])eJUÓù0g ‰µã‘Ž9׈!Ž/èH™ƒ.Ê0+UºŠéÍu‹ 4’9n´erhô)³uj‡)s†3¤G÷ý:*EÊôJ=È”[¯‚mnø•ºï5þ|@dŽíh)¦é˜CäF3ìI{²L”D¶>n-¶ÍDnÓøûï¿gÑó©iË"/¹»6%‚6Ò0‚+yûuÔÞrF(ìÚÏ÷+÷ÅÍÇ‘¸M4:Ö(דa$¦õx U*(m‚ß’ôȱ)u54Ÿñàü „.G %¦g4(¯ЋYÁHÁAôö!P²LïÖŸùdH †¹ˆ¬]žÆ3Òp`µàÜ÷€ɧ÷iVí2Y£ñ4”lÍ0õ&®4ž¸^   `ç‹êe˜'>¦µ³rÀMU…^%ä½ýç—]½ÙÂæªÚAÍ’_‡¦[0Hn  åÎüõU7¢)ôöœr èê¡0pz #°+(Ý¥ÎVÝŽÓ&Û?½Ük(éu¤Ì$ Œ!Ø2æ˜îåHé(§QÕâ(ð‚F´§#™c9Ÿæ:*ìVU‹Þøcˆ$Óg˜[³2߬LêBv”·@ 7L]³r–‘-wôhÄá(`ªjùÈ"ÿdŽZ^Ì0Ï+ÿ´´ŒÞ‚ŒƒûÊ?Ú xŠZ„cn-Fãh ^ûª°HI3 ЈS¾¾ÜqȰº^C-ðù/ÎáF¾ŽÈ0©6ÅçRnu‹®‹¬Īp>ŽsÃð×¥š§Œ\c|¯¬«YS²d„«®‘Fh¬—†@Õzp2¹ÞîNY‹œCsŒîŸRú·XÓ„3ï/=Ñr_ˆ #5¦4(+UX¼M¿\üÏ:Éx&À_íçóÌGî÷iâm ÔkPJÇ–´ùHw¬Å\˜U¯D@¬È5t5ÇÖÆ´L†ø†FÊHæøÝ‚XûB©ÍBÙ2M棅%¬Q&.7º’SÖëØ8 M]o5s|Äa¹‰Äpž@> Õ+ÚÈ–O‘øJ>?±Ó(yÉdH@N/'“M©nôxÊž” ­úÊÂL{6‚^ðql‡ŽaŸ¥/‰ždAUŒ/'^$%F¦I†šX;FäÓx`Îôa<¥cUdCe%—ñ"l4ŒL1²à¦Ê¶F][XUÔÒаÆà·†ÃÛ•¡ºT»oÓå·1g2 ú@†ëEÂÈws]ô¾<X ­pøü5JÁAf P ê×±j{”¹'Óu;~ý‹Gdí~`˜çß•4¶J> •“ ó¹­Ÿ·ƒ1=A¶Sê…¾k¿ JS{U¸eA‰Gök´Y¸”’A”õz±J‘-SÉÎ~Ùñä¦ )2é‚/óÑÎGÖ…ÑÕÿ6NIK ò %-²*`O˜`&@í@1%½ÝúÿùÝbUã;fØ}uõ)È »Ü·ì·™^2ž›…„…m«Vòÿ é˜óþöׂ7«53‚Ìþ•ö¶mµ ª ²ÚUc:fˆáÉMŽo"ú¶Åç9ÏÅÖÜÌÛŠ†’†æ€ng‚ÈMY/™^5¶aX&ÞÂÛ¯Åшl1Ý%O$ çØ¿®HÍ­«ˆÀmÒÇ'Ó¢Ô,zV…o1ª°RÀè^#€ì)Z©#Ϫr½˜E>2&ÜE`Vòz z½.RIÕ1¦Ññ2ý®7Þ’ÚaíHÔÞ›z"ÇöIIæx:¿w ×gB#à"~»Y`S€–¡ÄÓ`Ú³Rã²m2qþL¹sº2†TOG—qd do ÒÛn0Ù@7Ù²œñµÄ¤OÖ5Èêek´ß_2‚ Õ3x‘c`@#C$ è㑎¯€Æã$X©Y‰óÑÞñØ}¿”V2=Ÿ~rËÓ4]^oL%X(É1ý,µ'†³Â>/ðÆ  %<dV€®íІí¦E©ÆœcVr½Sâ€!ÀôwCJioÉ6QmXnœ£ëØÐk§Áó…^-òPÕt=‚ ‹;äÓRW|wÉ-YW3 È0·n=ïv•T]Ù¹ »B¯„d¥K6ˆ¬œaËÀ‚€§ )º¾ÒÄŽéeJG³Düñº|íåÈ2ò;ä¼­Þ×q$HºíæØþôŽò‘~÷q›b„cžÄs@:&kÿœç“3AÕ”µxj†)ã¹9¶­Ý’a„RU-ô‘cŽ!hŠR†Žu‹û5ˆ—ùËéõ-×Ré%ék7Tôsá¯5p/Ùûp¸õó,4¶õã ‰³Ý ‹Qn4¦cVŽÈVˆ6éFŽ¿Æ½^™ªQôš¶Ñ‰Ù f]ÞO©œ¦Lb“É¢‹¥‘Èž€ã¨Ý¬få÷¨îeµhì;ûÙ£¹ÕÓoMwÉ­5òqëJ€ðpÛ§+l¦‡¡gðHþ2RY92шÑ"w宀!Ë*MÓãáö$n#Z’€^TêCñ­±ÛYf>`%­d[Gdwá &Ð+Ñ31šÞß‹1d0P¨2Aò„ëh0»Á­ñb$YÊªÉØ¶‰£päÉG&ÃÔ‚ŒVò\ª/OIPûF˜Ž¤/ײÍÝT—,üK|[iº0‘lëm‡VÊ“R©Úºzüô²JôŽH¡©$p|0Ä2†¹c7ÚWC¹µ)ß—1HIq0´[ÀJþüëÏiG2Ce2q¶|~½dkF8e÷¥(íFw>œk¯«#~ƒ¶-¦Þö1Ž R çÌáíàÑ“ < LiPnx8’Xãô ,ØQc¦J' ½™Àý­‚^—ÈM^ qdF~h*(9Ö¸û~~ P·ýóçlL¡*¬âðÊÅÑ%³®$Wõ^¹mQ<‡ÞQÉ‘È;¾Àn}œ=‡ÒÖk\>rzs ¶–™èJ5Zhe< ˜(ù´ÂûDñŽ9Ž®­e¾5ð>Qm`dV¹)që‹B  ÐÈ…’¨4ÐkhGØ ÇÄ íª¢ß€ eûôPü12’ó~G 9ãe<1¦_H›c|Ðlg˜Ø”ÈÚa¤hzÎ2ÍöaËîh@PpîI‘ùl#Èðº`L˜•bΖQªŠQ: yKVÚWòyùf%`Òt‚aäöQòt>‚ÜZ㌿ñd¢wÈU‚@Ü‘2,»,bÙnM—Ù" ºœ3>M] RŽÉ/+!㪚5«é[Œ¿jãÖ[»#¾^ Û–Á;*9¦ìh¬ä‰€îè[í»“ s1µÃ@s[ƒ'²ÄñçûvMš®`Äa $@Ö ðÙÏì»RKhÀ¿ë([%†fkâµ0T pÖU©Añ²ö½I–£…‰l·rkLc.†¸­%¹ý¡d®ìõªFkø¹™(´õ3 ÚgƒYµ®˜;áŒØ}sÀäƒ7wß¾ÍUâ“Ðóg"û«´œ§M²Š¡dâ}tÅ7ñÅV%?)ëûæ²Fa•þŸ­;ؒŶ0¼ÐÊö“ZÇòÑÓ{ü»ëR£` …Èî™{%; €‘µˆaV•ËuSޤ1×ÐÕiX¶¡.¼ö>¨Ý¥,÷‰h¡Ä´g%ãªâ7ÄZÜ”4‘YåÀÊ24@úkp.âH)LQmáЋÏóJΤ7ÄXN á†Gr 7.ü@ÕcôýcÀJðo¿ÿþ»‹(X¨uO|˜¬IªJu¹§j8Þ‘LÄ/[4+2UÙñ ?[îÆ< [ožáÚ½ e]é•„ÑbOÜtJd À-ÐMkIF‹¸fçÃHŒÊJ3DòÙÂé R* Ò²®ˆ•޾«üe&d.eà ¼HÐ1Œä–2QÕˆöx6wÕ–¡ŒÉ§?*úÐñœÅ^¶˜AJH€ó U12çz3wdÈ_à@)çXKdÎñNWÝ&dM9Ö÷£a j¡L¬ËþÙ&°ÐsÉJŽd¾±MÙv)2Q вvsñ&f’L)ãó_/€!SJ¼RžŽJlÉìOGÙzxY£q",‹âö'+”¤Ìß»Ñ's„1kw$“3‰w\äÙ&µ+‘Ñ#EŒa‚ø.cÚ„ ï?€$h¢û†SëûÚ2±»QÇz·R¯‡o 2€y¶”@C·@ÇåÆ9ꢷ’ ó¬ÄC0µÈ‚̶ùdþ èÛòvŸÅnß9n:P4}@U?ÿÁjî¶Ê߯s Ç–îò®$`ïE0”«6†Ì+ŒÑ7ޏ# Ç#4°vÑbÈ“y>޳ÅÃþŠô!õL°È¶AùÄ|]?ÿ“'ñ6¡Õ|ìA˜Jiê5"Pžƒ#,2yeÇ2Ñßn\Ä-Ú I&w©~x6Ý& dbžkOàãˆ/G6VÝI% Ld˜Àý;“s™ÆÈTaæýÖˆÏ éØ÷¡­ðFkTMÈ4íŸ'œL®=eí1™P¶€‘-£«g{UŒAµÀ‚a¹éá¶zy† ô X¶ÀK:j©+¬©%° PâùîÕÕzî‚\¤Ö’›·UBv$.6ÏÓõed‘XWsB/ ×Å<%YïY5«í‰É?Ã2Rp(à»Rph.pµÇ Sˆ…j|%]v³Rb92 ¥=eV–¼À4d•0œåF _Mæül’‰Æ‚xVŽÚcà£W†3õvM@Ø92J¬kWH¯T ð.®¥éM$Óý¿„ìüfe:Ùcx™£€a¯L hì3¨T A†6"ϺӨʛU;óîV;7#fåØW¼.íº Œ^Œ0BÖ(êÈ–FŽý¦€µ×BéH㘕ßQ)7<’¸£Ø3Æeû0ô…jtìIiü©°×s<Ûßý)EG›4Wna%$Aã¨WN·IŒÔKƒD‹aà ñ‚’Cí0M²áJM‰œ>e/¹R‹ CŠ~ÚEâJÄöqÜ Óà[Pª¥YªõÊí߸F‡Éª:"U 5݈÷†½6@XC® @bÖ¯#OÜtU”U\îÃc|ŽòÈfiÇð´ÐP¥ªx©±AFVò–µ|DL&øL€ÏÿSx^¢2©½õD:Æ7ÙÛJÈÆ4`/Žg"úŒ«j!.`¶9ÇË ˜dV0½#7Pû2 $¦¤I¦$ø¸—* `@Øœ@ ®ÝQï(®ÓÍDN ˆNã\úðÀ–Ofóc÷}7¶sh“ºä­Úhÿ\h7ZUö¶-90®Alk4+Á¶rT’ÇìƒÓKßJ¹Á}±"mU;‡nÑU£³Å‹ü*áåH¸Íé1x11 %ŸCEíÊ=.k¤ìˆñGÐ {™ùcˆ‘@;äk—³­$‹îˤýod#"˦‹¬´Ã Ò`êÅïi ¶H˜O¿8úF3Ì Ó7Ö ûªè"SDb€¦¹@Cå+9)«gCÉø4%Cy‹µýf𵛥ÚPæÂQL¿éYÑcê"{A|í %Ò_Ì1Ä™l‡µßÉŸoW$ÐnÏõšØ}ÓûÏáúþï=·RíªÛ*[í4HÎ6©Å±­ÜܺJ}Ä­áHÆ à¨6z†M|}¸ ×dz5 YŸÿì.…ÂB³£f=ñ4{—v’ (”gÚ÷Gº1²F%Y‰R »a<‡=Ä582ú9ýÊh–5šâØ¿*I,÷ûQÞ]´ žñ†ö‰Ò`˜`dÎH¡Wàú BïØæYu¤¬ЋÈsŽø³ÁŽªJUÉĪÂ±Ì èšáÄ2[CU˸ÜLëR2T10Ay RÇ£þþŒ0ÑÎHûôó­®M÷V¨®Óç%.êe¨7ñ>—È4†'¬Ñ½Z)fb4øJñ1ƵOs#›.3±ƒ^&àëwR%//›ˆ^eƒ@½ªðûyÁÉAæ–CÊ·‘C÷Bªfh+þpëå°eʉ2Ë %¡ÑÄL¾ê|¸øMi=G×äÙhLGÂ2Ad‹ñw4Hd’ƒ,"{¥z‘ ²¬Ä i™†ÂÄB ÙRÓï@#×nÛD•¡£Ò¾ÒË÷«KVcqTϼï”54¶žjÎÖ#À‹ðºŽûi˜ˆL*â9´€ì7g; 6½‰› ÔÎ-g¨·FùÔZ«+± Ž^¿æH¹c$ódەն̳Ƭä âߢ§¯ÄŠ ¡½#Áil+i=2áHL pÆ8•:³U••²²£R|5k'3´ZD#ò‰Ñ Äȵ#­¤Àdô€¹¹ñ'# µËH2¸#Mx Md ÄÈŽÚö““[)õ·¶Râú 5¶mI#TµçS‹c-UáæFNÜJÈ}šôݺ’‚¯+|ã< ²gÉJü»FKCP—* ¦À‘yêr,6°ö„1pFŒ”›®ä¨äÝࢉ€2Þtÿ'Ù'c…”÷nuµ>AšºdG£·µuT˜æv cð@Uzá;VI¯P*ë… .}~â\6.½cO‘cœ’Lé(·[b2&K)רצiÿfÁ]ob†·ûü¿‰øª²’•”Xµ6&>Y†ª_NCP û)¸ñéFdÚiðà vÓÌÛ*OÕôõꊩWÆ -¾HŽ]°Liºªë(u%üm:Ogtï€wÄ×{þfmoäØª½lm‰³ã¢+#UÀ±½}iÂŽ+a,€hïm‰g"S ÕÌá6fÕoF ÙvËçô|_*“64ˆÉ0·ôª•˜‹”2ì)U[ ©+½ŒéÍÅkl ^¦‡;¶ ¼(» ÁÐS ¼£}0ôæ¶›ÒžßAJdb{ð@¥’5î.Žbæmb 8Š>þ°ŒoÕ™·*ÑoŒ h7úþ¢½®Æ©¶Œ>,%ëÝw.2¥FP" Ì·ïÜš‚þìaÕˆ2åÙìî–f[éM@ ïM12² dí™WJ ãå5âEL>éÛÙJ3»>s©k½HJš-Ðn¤T¯F¼Hl–êþ^¶q ônºoo½ÕGo×éU¹ ]5ÂgÒ}=]È·ŠÉ¤ÅnÓˆ·«FJ³LQ­«lážb¥È€œ¡^nÂñŒy>Œ5¸å£]—h+¥™ösH†O#ã‘gÒÕôÌñ;îs¡Ï¹–rL#b8vóYàÉPfŽHb{"Û N´³Ï])öÑÛ é¸+82̹‰Ç4~„Ã2Ÿ.XKb2ޝÕü´I&e&sÖÞŸ+|Ϙaæûáê¤i¢'ª·ï rLŸm¹‹³5¥jæ]J‹Ð«”Æn%JǾÀ†4p´½Ž¢%«Â šªSªeÏž€¦ÅLW’[lí~õw Õô|äFÀÙv Ë``A «Ê†&Û¬ªÛY#w¸øå^ÁÆ´+E·rz¯,dAŒo]Kô‚•ÖÞÆÜ”0ÜújÖ˜¦RUY¤'nQž•–‘¦˜ <ŒÙ±Þé[ id½æÍêHÈx{æ‰i‡$²§¯CP`¬Ñi„U3”}ÉT·j·È™ Pm¨Ø&=]]uåOÓ-&ãk”Ãr‹i¬K^ÔØñÞž31½YôùcèÅöQ‘O˜8¦ßŒÝQ)A½¬Çké{òò]až³â‹z#Mä€ôt0ÀÓÄ€ÀSæÖÕºRÀ”1ÚÉÞÀ¨ÊžhÕ&«ªD#sãÍ ``U]@ËW5ÔQ)çvPûÍc=@IDAT²U‚ML†ŒçLì;ÖG†çƒßÆ©6ßGEVõÂ{Š1ºðÄ@½dŒüšOI¼µyîûL¦L“Oãt9ÂölJ…¼}'¥$Vñ@J4=“Ì‘4·x>©w"žR{/äV{×ÔØx{›I£¶€€}LrÁj<¦ez"SUûHU»!‰ktÄÄ40RŽÎÿKHg é(`a3¹¥®‡!F¶>lõ0È”šDßÅ0¢ÆM¤é¥…’LÉ9}; Ñ1Ù¤ …Rqì®UnJ³µaGy Ÿúµ&îhP> ]Ĥh WSE:¶dXöUÓe¨ óæºð•ˆ‘ºÌ½@†ŠüeGÊôÙÂUñ­WFæ˜!}˜‰ÅÈD[á«&iFê˜&ÔÄ–qT%°À7½.LÇjVñ˜ÆÉgö½21 3¯E>Ïw¿ˆz5Ê®DϤ®Ìc{¶i°^²œáÞÄz#Yu»6ÑÒH%‘IH‘c +€ŒyCex‚îMªúøˆÍ²¦ ;ê…Û#0Lšâh]4Ö0ÝÆô_ÝáœU%U-ªÄŸþ¢ϳ&&€å¢®eJ-J­Á'O-ÖC* 2GUX¶ q+­¤å3æþ-CÖ‚÷ÛkÊPb[KC•š‹0†Œ›#¥LTE<Örù|ô‘hT›î‰rF&–‡Ûªk¾Õž´õ`Î"ACåß |>­×†ñýÛyo²­ð7tהּ)š"è5ÂM1® Z”l cr³Œ£œáºù4±Þž…ÐVô€c¤£È_¿þ壼°é˜ê¼²sóà&ô1Ç·ŠR¼cر®–ÐNϳ.$Y˜1,„÷ÐÉZfæ°À—‘,|ëG@l"؉Ï)6inGš[ ž&Û.8¡…,àIì¨÷ªÎovž¾[€ß ‘2ebúÂÎU š+óÑØ 0”~—MS#ÆqlaGûøF“yWh‡~·*9Î3AVeÓë¥Á4÷ÜêûY#aƒDkÐcz ÀËdeŸ”[†^tÚÓ aëi´Ódå‰"yÂå»ÅY#œ›¼qùÈüÉl 3EA¥ í¸‘MYõµ5E0‰dëØªšf/Ÿ¾dé9¼¿eh„’|fÜ ÖE)6eíö¤r¯7™–9´=ÀA†pL¿¶¼àIÉpïàˆ— z8²8g®ÔM¥ãx{Q /bdû ÿ_†Ü¥+@6à¯=·J60L”d¡&à\o†Ä¢å—'R‹ì¸o5YU½pæ@†@'Cö‰„&ˆäŒÙ‡Ÿ¡’ “»‡–‘cŽ–å”KX¦“ €xGá“ÖØÿnª.%K$ë'm3”‚`HÑÑ}2wlc@»¼-kGx½”"ÏíV—õ^CúZTµÀ2Ì„l¶‰žã{·ï×—{ž†Z£k6K `(ë•[ŒaC[/ZF ‡vÀ$Øn- C 4]; r®±+$Ö¨ÚûîÌÏŸL¦$«±+úFŽþÓHïÐhL²î•¿R›È ÙšèMìH™'@À'ÒËd‚DCñýyÌGTÒ"zðœe¶EÓ)#)ñ½üdH8·@s)mÕݵ(I_±£Ð£ÅJµ “ÆsÁýx¯E©{ÕXË1ý~Cî´“ÄÛ¤7¬Êáv|®œ˜Pêûcâ«1ÈQnçmëÚ øÔ˜ù.\WŸ^ÇzµØ3]ù´^88^ØíÚŠa›Ü™'ͯÚ;èí£ÁlnVi2 sðGrz=£c ÐT{ko1Gb†³ªEÉ è[F¦ÜO ý– èåFß'å(êB¾w\»AåÛqJ½6¦‹¨Vʰ¿‹Ì¤¿YkÌjCif›àüabu"¾ž ŒV—]2¾¾È–ØÞJ"¤ˆ‘µóq-}$.ãHÀÍQVxÊ1xA‰éSÙ Ü= M³-«2„­AæhJþ0>²¡J‘ 0E8îÆ‰u]áç'ÐQÔN¯Ôhé9ÓûÛmΪñvS’ž®‰>Z¶’£YûàÈ0@t†°lsúdµ[)IU‚·±»ø¯9×(cÔ¬®³MF&«ªË faˆHé^ø†–lPß:âjI)S²"H07^©…ª|êÊÇ1ð®‘X—RÛÖ•g-¹é0b#4:*aÎìçï¤H&]S£ ó§qœƒöJô€x± ‰‘ºê% ÏŠ€¹ck¨ö-ŠAr›I½-“•*å;"}íôÅëû.m( %b¶‡ۥŽd]kê¢Ô_ùçKã»L‰.<¼–ÚË”JýðÓD³{õÓ­DÙ j. ¦o.“+í¨ê'”,Q—’¨$gäÿ÷YÄJ|”³º .‘× O†°ɪb{Âõ~þC`"#yO´´†¾|­Õ 8ëÚ›—߀ +5¢gQcJSÊ9§I3ÛW–^¡±^¹Ñ—8¸OÝ1‡4ÀpL†=e˜À±êòøyÇfÉÈpËÃ"vÜ}$ĪfÕUÞzŽï2L”6=,‹3ìûsȪ‰Z)Íê;TW¹Ð¥žLëÛbI%‚€X§—)itÉÝôÅ{‡ÉrèÏ6­7bæù 6(¦éž‹®¦t—yb²2ö¡ý_FÇÇóï.ªB‹#’g7r$+t9’Çád-ƒ´ªÙQ0a2í 0ÉrFιqr»—–Ú§Ì6¤c>À¾ó?9ƒsèthº8‡L4iÇ^ƒmÎYUöcXc Ü#{%ä{M¦ÉbLD …cÎZ@.ÈTa;ø¬û‰fòêU1|<àØ¥Ç`4‚2[ M¼1œRÎ'ÛÓï¢ “2ó=Ešô|yÑ’ Õ¨KÖÈ­Qor|™ÃgÏÿþ÷¿ë©\¿\sd7·1,†cäî0“|Zºm``—L0}¶|j‘öeªEn%ÊÆ92)êMI øÈ;ÊzåÜÎÄÚ1óe<“é}öôŽí¤|7iŠ,“eÞ,Ç®I£ÊüÊ?/œ^™K Åñ° d}­Ž:Ú„†IÓ•´W•‘о#¦c2&"‡˜üùPÂ"=@ùj2×+ðdÈÖ†µÌ$@YWžÞ¡F¤@ʺ’9Ƥit#ð ­«Å` „éË׿¼@€ÿ;Î ¯® ëê"µËÙ¦”E/ß»™¥e³¢ñ2}{1‚&O¤cÎ1½^žÛ¡knþºšuWøü˜cuµC&˜”‘6Áô7\dûÐ$3e Á»mU-Ld‹âaà5tÜòùÜ9'wÁ4#ˆQ­fB”è­Gï.xÕ<ÃJ” ÉÚ§vxÿxJF ¼pD’¥žˆ\/~2€@/2åôgÌ šµ4™@ŸçòZ>ÿ§ œ…†æÚ/>Óª\²IƒìÛS©c½åžÃËÚ&†€˜›)H™X—H€1"% (]ƒó”ŽH&õÊv<.Ïw&À ‰û–x«Fx_ hÉœ?’€²?Ùˆ˜¾I0RЈ¬ðm«Ôd¤qFûšÆ÷tMĴ䬸Õ¨Š>‘Ö^ )0„•D¶<÷Í®Dã¯K]g£µSºµÆd]àšýå+hVm±fa]üuÕèÈ9¾ 1Žaƒe½ñ0À'ÃDÊ™rxÊôxëÙÁ­û8u5ÐÛjì…‘á<õ zU<2þ5ÁdȆ> óGÒ÷»•F(•ݺȄ’Œ·Ï)|ÿ¶¡=Ï™gHd7‚)u‰üÈñ6ôh×ÒkdE ‰³Ä Þ1q|yíM‘[ _ɬ¿Ïl‰µnïëU-kr;úÿûß(g=…r—0°€E³éýÀ˜Ñ0²U #³ýÛUûBט†þŒ¹ |†©v4WoX&kPëå#e¯‰ßY¾4µ´@þº2!† ÆsÐ2CÊôÍjO¸e:n%¤…3”¹±;¼öø<µ ¸ÑJ teå˜ Ó°‚ûì–Óãûiií>AÕ÷ß{dÒ-jo(ž ¾¡wåÏ?‹(á™+‰4ÄAST…Ç÷‡MŸˆj¼^†adk;¢?u˜Àd9kÉœÌr&ªŽò[uL¯ïA6®)FèŠL¹ö>,¥.ëØ‚@- ØŽ"ç`$ÓÞG“¦’Ü.K㹚Òé¦ÁÓÄëjl•Z¯[ð”À$Á6 êØ)ý]D©AæÝ…U›÷ ¿ÇœÓè2ÝïV<³%#à,hÂHâȔʘ‚òvœ×î•Z )ÈÚñµÔ.$¬è3Ì¡U u¤ñC‹ÚU=K-øzß̼ÞZzÏ2$& R„•Ú*M¤AôÉ\¶c™ %ü*é-ö«ìLD¡¡›4L›cŒªc ¬E6²ïe“d ª$ñ^†UÊÚa£›Né{Œ¬Š|ep-°ªÆ9ˆlɸëûcïKl½vÀëjÛÛw>¶+ÿ´áǨn¡ÉÁÑSXÌqËÀø¶ wì.[µ}‚ @:Ê-‰ìdezÁÇSíG—@Ð#i´x%âÈSônabÊæêò_ñúßÿþWcãý£ýõ>ædž2™¬š¾ã° ›k8¥ÌA ²êºf5ÆPÊf©v»ªÛÇ‘ª»ôѯ¥Û9µ×Û™[ Àèõd)Û°µ1FÀÚñWrŒµWjUC‹6TUêG àõ¶R™ ¹À·gC-I“mƒ`€O"·X@»ªPÊ9–U€£ÿ€ìÜð{÷4óL–•oIúl‘ñr &팄…’_î,s'þm†c %ÉÂeäHÁ°\¯¹@ËÔÞPL¤j ävð©‰Ü ”Òla¤RG¼cLâ&“ÄJ”ør[ɵ¼$Ü‘˜ Üæ,h|†gn¨r»Â ÂNàn‘Žæ•ïèÏ–¯/ì>N‹ìWFЛ-r£!€¹©F¶ nhákp^‡¦ào®é¶†’¡ª]ªÌ–›ÃFlPSº,27 ÿé×nÜ\šx]¶ ~WkþsÔÒ\nŽÖË Sjzï¼£’q"M&2“þx äg”L`]M16TÉo(^ê*vUšüéÉêÅSÆkÏvmTš€d½Œ5ÚS‰›^¥z‘ŽMÉG¯c81&Yd÷Böt4ÉdnÞ$]‘ZàÂ¥ü?ñ[R ë¢Ô•ÓÑæ¤‹`Ò÷Îx ß1AƒÚ–gÑøLýþšKÉà z1ñ}R5z½ªŽÄ<Ér&î¨È‹•öàJ|{oÒ¬öQ5‚ŽñònV7’×ÂÁ¡Y{k'Е¿TUJ&벘j])ñ€¬=‡2Më•3i¥ôñ10¿×P¹–OAÀôƒÖ”ÛüíRe%GÁ§ÏèòzpšvÅë“IC»BûÔ%Gaè:_l÷©|¼oô²`㻌¡·\Su%k¼ÈÙ dº€¾Lp 1 ’ÅëꃯªKÝ÷žØ1gzßË~˜9g¢š@¬‘›¬¥¨½L`J<#¬ô’Ü8«â‚d™#•„cã`ûßݵô]§Qå¿ÆÖn‡LàØ‘?+-5&à¯Wn%%“‰‘4®° –Dú5'søzéûo¿¨2Ä‹LìCß{¢Ad0 ûDÊ”²À\Ð`D«rã zaki+GXc&dÊ4Ž{“0}_ µSjïøï¿ÚÊW V@]-æ"4î›?àÙÃôËîB3%¡áÖ•Û­/ Ìm»Ñô† jŸªxâfé5H#Y ˜¢·ÑyV‚•Æh×%òiJOA#L©*·I;,7×Eˆ{ŸpV-ƒ1T»ÏTl\ÓSªv/Ó‰Û‡’¿v¿ &C GY8êLëíXWø§q$Àd²WŠlJæ²g·[]‘u×2J᪰q0PI;,ðÂQµÅ"a€ø kWu 6wGž”ç¯~©­¨f˜I@0]ÍJ¸E)áÞˆ¾®ÜÉŪ™àEÎaýµ¥‰d€¯Ëާ¤/k™áÜ”¬”À\¼¡)H>™wMU‘è"Ž…#€Ïưê'Çß \-çx¥6ÄDÒ`˜PÂñ”Œ”ŽnUkï†] ]S’uObÕºr¨½–dZ¶FošU¹^ ŒdåM„}íl„#ìYà”€ñ‚Ó-䪵°zõFˆÆÑ0I‰œ?Ù™ƒ0KiJG˜²œçÚßÅ"ñ@á:u92™P5´YlYõíô¤g{Ydš¾0Jþ`¨¥ÅòlJ|³vµŽM¯E ÉÐÿû®›",À„ =,Rt”[¯\I{hq#ˆ´0«ŽLèÃ9Ü™çË WV-éÃlž ]Ľ´$(ÉóíêHÙã{½Zð½ÏF¼žMl=½EG2 Ï'¦£=[Àqï¦ké˜Þ±ÐÅÇuÊŽ~Òeþ­M_WJ¸Kiá ‹@iŸŒG*ŽZäæÊUéÓ$Ûb€@Ь:®0Z.`2áOŸy‚J°¹Çú¾À ðͪ»c ?Žõ7L¤îÓÚx‚LeLà© |úÍ^1ž^ÆÈœid÷ï Ñng‰ûËV¯+qrû47óªý@`" Ìj[-ãŽó©ä˜ƒÝ¬Ñ±Ü³4“?Ð]±Ñª ݶ›¸AÓßÖóª&ª2äãØÝå~<’5Â÷£oOSÂí†aR{ß¹¾Ll9¼.FÉh‘ƒ,·L ßt›0l[€FFªÊ‹ÔØ\d&­TµÛí_Åò×îFyºNƒf` Ȧ[»lJœ$ãÙtk(ÉxJímÞ¿Ǩ® xçæP¦)¶[Ʊ5X÷>ªøÜˆ5z¢s«{¯ÖK“[bÿ Áäuh%$A›Àñ˜HL¤£Y¯¬ [&±.½w»Ï†þ2¦)Ý]ãHØ\Gï ЋCf˜f i¸ÛEÊÄJ]¿qÍ*'– eSjœ† æGc#jQbbá _e˜X¨ô…Qí‚o‹q)ý„¿ÐE¦oO€9¥Ñíß²Ræ9çӓª eVÓ0 ¾ ”é´Qh“ñ€ïk*·ŠÜ®€F¹mˆÝDWžµç³–®Ä* jp(2‘U•ü|Ú8ì¨W®ŠÔ‰OذëÀ˜ö!ÆÌ»†ÆvK´Œ?Xè2H—è«#’s#è•0Ž[>“²R wƒÛ*gdíÙæLã(,@ XÆËY5QU×ûµÓç  %‡¬Z #«FPú¿¥E ˜R#¥YŒ‘ñô§®4dGý×7O¬Ô ª¥õ”é1b¥žcš®ï÷2ÜÂzU}p6Ùô¬´Ó´R†­ÑP-HÌÖÈÖzxU<Ì¡gI¯¤½*Ðצ¯®RÛNù.x@D¦lÏô¦Ð|~PÎf¯­²~Œæ>B  Tû\Uc0"¥̶*f¥#c ÜZ™²ªì8±#L|³dÑt%@5Rî#•¶Fι_8¸ ý‘¦‹߈9ï› R¶ªÜM[CI÷ï"¸ªÜD ÙøF7Eµ+èÕ¢ÚqnÈF¤ô˜YÅõ4ºæ{[Z Lù¯ý Î\Ë>#æiÚVIð}|@Ž]áOâVÀºÈàaž#§$ƒeU²ªµÇË•¼9C?۽ض0x]‚ر+(á`¼‰*ž½¡Ë”þ¡D©/@‚.²#}XV" úu¦ÊGXÃ8š¾Õ‘kÇL3Cš”<5¶ Ržl¸ÉDnV½‘˜-ß­†è /¸ôáíFßcºZŒ}x æJÙ6®ë·°’—Ï<‡†Æ” R2hÞ¦w—&Ê[‰l›àÉz¢³ ñ¶#¦/L·h:­ê‚p—%&“OçêW‡¹xbḻéñu¸iÇhäÚ® ¡3l:ŸH]5vJ@¦¼K}þ‰9»ùÏ(ÚØYM8ÊÙ© 3ÒÀÆ Uš[ü|e1;‹×!qæM¹½‰‡ù×€½KÕs“U‚Áæ&@67ž'ÍZ”0‚Œ`™FÉÛùÐИFÐÏ î£ò‘Ó8ʪ‡iï?»CΙ'·¾pã"a;Á…#e{H¿qø°ÕÞ$°¡Ä˜¶ÒB/§DÂmî.n„ÆÃnazÀ¸Úç†ltJùÝÁ\>Ý¥A›ˆí sY¦çCÖ[4â4Û éæ–­54ö€}ð§o’О™;æÐ;sИU%_k|²Õ%´lVnmž•ö£IÌ„C&m›’À½mEŒÑ[î¨tîùÖp š2¾÷ÌS9˜åR¦;¶ívp„)»òmúüó¬Ä<X»¹”µÀÀö‰$nU “[†¡’i4Œ×kCÀSÈ>/Yàe&dbæ}F˜ˆO&þ,šØžHUĽ›ë쎞(œø:”RW;ë­½•~¬A\#±ÈÆ ÇĶ¢©æÖCS{_Èðªô™ Ã.å=û\6Q#An­T—,bÃ*·•ôÖ®J“!ÜJ]§.-)‘b>º­×7¼)ótT"fˆÌ™Þ‰ñqDþд0A¼# ˆµ[hŠ£ ÈŸ˜j!ãëÉQ'¦Áf{Ó#€,/n s_PnlûJÑoÜCLé¨&–aU{ kÔKVÕ1ó®'ã«æœ¬}ºvMéÑ1d¢–&ÓÔ’9¬WȺ²ív4þ¬†‘Wµ¤Òƒ ᘌ#g-1ô@ß¹ª˜É€”–‰[FId¥Ý íŽ=]&Ö#Öõ6RÖ(7N•C¶2œYJdܬ‘ ^2¼ª£È?>’é¸HI#`™­*™€‘ â€Ó;8òܯB륗kg˜Û6oŠj;œ1÷Ýx†uNíVeäxʾ¨¶R²†³èXnáé5B&pkç¹®Z@-J1ÃÌÂ0Aö!»BßÕ>b%Ìž1`³Í}óüážT—¨$Ãî¸ ˜9†’ÏW@×ácäküùк+×Ȫªjé¦ýo$V ÔhPFÒ‰)‘É|»ù‹,ó÷S®”O]»N³ðÉ0Öˆ|Llé zÃf‘-¬DÓ©^¥BIÀ ’ßÑp˜L6·FJ¥ôsÕóÛAÙY',ÚÀ–È:Ëz„£NÕZz²Ž=“öW£w× §l-¤^ÌÇm„%ÍÖàÙ·\»®v¦JŽ”áhDíxXc€8%F¯HÖbùXÀ±5긔½•Rš.…ÔØMúìUªâY5`•I]ô°Çï%i0 ÀÃiä1LóìoJ¶È=T>4JxÕÉVöÕß›w}—ÂXÆ‘RÄÓÙkâáŽFðþÍ %= 0¾â¾fV’í´Iz¶Z0z=€{Ÿ¶Ê,hLOŒò3˜ôJ)a]J–ñÖ ÌÍ8dC•dJx®>,2ŒÜ²Â°UkŒW­J†„ÉÊ·õü3€rÛâ»q|+YµFd¼‰¶!‡–<Ž7¦O†s/¸«5= — ZÀÄ.¥‘ÌÑܬÄ€LP洞 î: ÇÍªÚ ˜CbíÍ¢ÇÃ)ñŽñ1ª X1ñg€¿ÕY Ëö2ÄH²žà“Už˜Öë"mBìÝ6ˆ¦áİqZ8`º‘¹ÓëzƒÒn-6@{ûȦ8Ê”<ûÏþÓ`Y`ôØ6I΀ҪŒb”ÄÈ]@©”LæSj‡:*¤žX F6TŽYÉc’)å“ x¬Zªb·F‹a¼  ”„Fb¤)1J}~U)é÷€½­ÎHúÝ‚‰–3àF¶`b%ãZ©ãFD¶a2¥Ê5rZ°€|Õ8ÔèXøE_•7½iˆÒ È0^˜ƒ͈–iÉöAà) ØÜºš˜-%M-@ƒ$–‘ªxÇ ²êªÍ²F)[&ô2žyV˜4}+âs›'=LßÐΜ¾£RGJž@¸Üz/‰!î·CÙJ¬’åÃ!OÇps»%=^ØŠRuµÐ¨¦”…#‡2‡ºè9Ì#0 jÉ-å¬h( ¬ÑÏdHbÑcת-°^‘@—è"7hD†4sÖ›X/¬ôš[^µ’˜Àl„cC ÒTÅg®Ú7Ó±f@K}—¡T~/Ûè[ÿ|¥ù#ΧMÊ-ÀM)ñ4›Ž_ÔE“g¶”âó¿UHêEZŽÚ‘:E.J :žÎûcO #ïÂç;á¿8ؤ†õа—êÚ2ÜÕV糪‹ @ ¦·€D-øZdTJ ›% æÈüù`XiñW¤ñŽÚ•hŽÝóµÐ¢s+çÇ,Ÿ ¹ñd-i:«þ F©+g<Œ§Œ <‡ºü)âØ#ðY©vA-ñ@·S2º}²ª 6Ÿa¿ÝöG•2¡)ÚG‰³j•šyÇ-™O/ &>8Р@Y 4ZÒQÙ?ÿùÏþ ©¹­‘•[´@Wè…9Ð4½ç‚ dG]wÈÙD ¤ -ã}3ÔnŸ9ôž¦4O-%Ç–Ì_W$ €ôüUwì:Ý 04ez ¹µ9|ûé‰÷˜”è:À4zóÙ·E/A-AÎ}æ[†@$𷇞‹@¨§ÇxçÆå_ƧÉǃԛ22ìØª-Ÿ¿q@ú®I9ó)i6‹ÆäOŒ™IÕwJ¡Ÿ•þ2^5Ð;Ä"˜ÀÑkè}yzU³àÈ4F@(Éék$·xª#ÓȪç›"›T£ȆÉc»³uíÑ…1-±Ëœ1ß¿dm–›ÒncÇöqÉÆmÏV'(Ú¹¹ðöјð¾|¼ëÀ_ƒ__<‡ž5츹µ4.Yß`>›Žï³„–Þ!¬EîŸ)iô&Z¬µ­¡ƒÇ‚^Î ?[<1ŸÄa12؈mÅ¹È Èø57T H¬êx:¿·2%RîO¯&fØÚ9`ëõV•ø³Ò+{%%|Ÿ=F7e ^I¼ïO ”g{Z²)³ 2]h‡¯Í™"ÞKõŒé·X†~Où•W¯.óÏmÎ×õÜ1g-”µ áx@Ô ´‰«©šó®Ú¥È*5Åßè1®†¡_‹ý‘ {XXI¦ÏÊè"Ä»Œöœ»—#SºE¿¸;ʦÐäÓèF¤Ç“‰vl¥F›Ø8šde²Öΰ)ð°’erN ÎÚ›ž,6¥ ÂÈmˆ×ršïž^Idΰ’¬ÄÀÓàíms‚dôMÁ¢Ï…›ÞÆ)-04<1@ »¯j%L8½¡ãañù?¡ì 7Î 0Þrë?=÷L¥©Ku7l-Œ0¬ía&Ù‘²KÒ3̪Ü[ÀÇâšÈ Ò¥Ö;Òû(1rQ‹ÄÍí >.÷h$Æó@ˆT—Gæöê»×>lúüë壥 1U1sÆ4¢éŽfÅÀ‚ÃÙé{Ù."Ó‹@κÈ`¼Fø|Râ—¤Ï_‹¨lŸ “…éÝ¥)Ñ"w4¥#ðV“­ä(ZiAïÙ£å6ÿ™×.WÊJös°¤¨TãÚÆ™Ô ]JòÌí)÷iúĉ{ÿÛw–Q ò_užx‘ ï×%ÌGnŠÞ¦·Uǘ¥Rø]ÀúᲞªU) TrTVÊÇŸsJ¸.|bŒh“=…öøJrÓým€2±Œw;s5öGT]JÖkŸ@û¨ is %ñ°¼ “¥—Y7“WîMÄláœ/ýù°øƒ´$–ù…ÛG( ŸH³`·‰³r„Óé÷Fݱ7ÏŠ,e ¥RM%Ç×!LCU“}þ_BÖi†P1DEÏMªÿJÎ?w¤‰!dªä`ý¹äã§ å. 8ê%ä¢ ”œfd& +µ$R4OÐ3¬,¦„Ì6M;à)Oçw(7˜˜@­ \ÕÁPnž°ÜÜnÓik×ÚDZA‘µ(”Ñèíæ˜CC/š«d¢++ÑàËÀFæPöaaŽÅ}sd-«¹ÉÂmŸ,¬»š5`†Ú9#}sü5™8”E$\»¬ Ï#t…ÕîBÜ[F·!™jÓSæVc™!= ¥ª¼c[eŽù1Ú‘ßCú¿ËbäÜÈ4 Lí²é=Kâ4m x züœãcÒWÚg„ȽCŒcJG&Ž2Þb°hgU̱¸Áö ÃZÉ|Ç|4çâÖµé™ë­Ñ›L<){=¶z5™g‰{ %G¹wتkœOž5ÊM¬=Ï:+¥˜õæV¯ø4xXtS4H¹qÄbÇôùpplsÙÕ²’ua8ÓGæ/@hÄŸ•µŸ h|¤†6 œéd™âµÀ2Lɪv7QÜ4ád•´‹V$€U“u% ž8^ÉnJ˜áóWÂ( Àèá€3æ±ÿ‰i esë…4ÍMÀgko"á(¸ù×ëˆo+ (ezŸ–l«4ôm($«ÑJ”-Ö\U³(=>†L & ,`%™˜ F>‰sŽÌª.Ùoÿ·Å$ý&ngW@ªæ“sÿU sëRE&cÌâ&øÔn4FW10f¼Æž.ç²vü|1™[ÕEú iÞ_\vYzÁ/àÅ´ ¥r‚ºü N©Úþ²¹ÂÙbz·0=ÒV Òb\&˜>dÎýºÁ×ÈjXK]-ÉDo¦‘…q¹Á Åpsl4Ò›#Eíla†²eúÜdÙDKÞ]ÎwµÞ‘ÓïçØ'[©Íe>" ç¼öŽùÈ‚‰rtº”ðkï¹TÉc\2<†¾ã kÑå‰Öž Y/ã(¦aËMI»¬TNю>µZúè5* @MiÉz1ªíO ôùqTD ]8õÛFÉ« qTMp†¿@kõ¥çÓ€^ÐN¶/ÆÍ»<>Lì×bãš’ŒÀQVŠ‘ELžvÃ$î[Ž °I§ùùr´!†Lî5`  ÏïCeNÓPæ€Ì¶Bz@c/P‰¾Ø’=,OzÚ7îØ)Û&Ó•†gû`€Ž4°Ü¥”ðeLnÖKPW£³’ ]–ÏÙ†3ÏÊ€è´À4Mÿzœ5˜+‰i`޽OzJúd}1MÀÄ4rkãÝKpK¯—“Œr¶ ¢äƒÌ hCdWv¤Q0ûbcö\ü3)c <`‡.•›,¸õîV]#Þ±ÆJ] PÂ󧬯‘S£c$xý×B†ï¨‘g½ø@SÊê8Cd¼YÉr‹÷SL)ú¦™eŠ£* ¥ª56"C<@ÆYK+Ùí8W^c¥u)ù³\ýx \—2ÇH²ô-‰od²o‚{M™9}ž”°ÜbÄ™Œÿ¡gÒ¬Ä3Ü °R__EXDÊEûÃÚ….³úyùÛï¿ÿî 9‘g:Â,êÂëOO)fÚ•(ól3Gš9Mæ0 «µÀÈëzZrÎG PM¨ùÃZT{_$ F—ÜÇÜ8%š™ÇO?P(LÑó\*ÙF’™¨ O,ÃÈLÒ`Ú¡erð}OSIWÎJønZž¿£pä`5flŒ%ûF3÷YàëêséW!·ªÚT¦™ .™¦ýÇh/VÕNã(Æv»üß%k!0Hþñm©—9™\{×,¸£ªÞfmaG?̽í#׋Qrdâ}:Âã§ÇÄzsЛ²ŒÇD; ¥B‹ýñ.ï¯AkL£DãFz•ø„‘9Ëx™ )•šŽ¬ÄM´@™€Ìéñ•*¥‘s°vL£a2¸éŽz);éko™ÆÕÓËFMÔ娗VI¦ªŒ—#eV@X)&ï›sš–L&SbØ,2?¡ *a”rK`Ãz+µÃ:Êb>”a2&J=øøüe¥î+¸Þr;S¢àGy>ª‚¢—5[D’"e“dv²ÐÄÃÉ9´¨]4ù;6Ú±è(+‘µÉ6”¡Ðâkä8Y$ƒgÒ&€#>Ç"ýrseJäö4ű èU’)Eƒ2Œ+ñ àHûÐ8¦TÂxdJ™y{Ö¨åÔ]ÒÈ™l¢Æ6¬W& šX#ÏzñôŽ@ ¢.nºÚ–,Uz?6ŽýÉá磉!ÈJ»)"CzÑþMìš0Rp€õú•çhb³ï×4†-7‚4YÁx½L´3¬J‰éRM©—Rc|†µ¨!˜Ðù¸eÌ‹)˜2·É6Ôz:†HæíüüƒY´†if=&Ž Æ)ÉJL%™í10@ šLWJ@¤É­öJ²%GÚÐ:ÊJÄéM© #™Ç©%Œ1)ÅÖ€‘Úe$7&ŽZ€ª}Ž{4×Ò—$ÃFÈ9|ji=2ß^n½j†Ëª¢cG&°|%d;ðTò©9£!è÷bŽ4L´Y[ùÓ4ÀT¢Òçœ'[XËd¦ =]>9TýË?È+$¢nE@¿D/Þ*ŽöÈe€s;>ߤ6&îu¬XË·Zh4f.;Ò¬==ÞbaâæjoíF8еuÃr¡½'FÒ#°\pNÙ2ª€’YJÛ/`Û:Ö¨ϪöF«š 'cHæÈJZ€ÂóÈ*ÁYÝÎÑ2ŽÆ݈8O@©#e]2e†ôiLÌ!+íÙ:Ö˜,^²À ½£DÓ¹£²Y‰³5Ô7 ß÷ ÀPò!«E¯MDþµSrè•€Ú$è ¶È>M|[5 OSÌDX€øõ¤i=ûÔBF ±^¼ªÆ°<@ k1”O#jì‚}Ð¥¶ò:r½Y!»¦)¹9+ XR¤ Àe2ѱqö!C–»‚£%ÍšÃi»14–즎]d‹añ™z'д3fsŸ )“‰ºÒß០s^6‹’¬ÿžÒôµËÌç©C†1·ödM©Ñã8î¿üÓ瓸×ËÖŸXþãyv‹dÕp §ëËà(”ÚpÊ­g(çž&hÛ– k?¿qrÙ ¯QRch0ý™ßÝhðL³NƒÝóßU-í¨æ? Þï£^ž±Þ£­"å¦Ñ÷έZ‹j‚F3©ŠÜ'ý#žªÝTØ,‘Æ Ì<Ò‘Lo?¨Jw‘Ïë숙jÓa¥þá+&päIË4ÉLlU‚–áÜ2 #aú†æì˜!&üµàëêR2}Ñ0pT] ¬W`Á[m®\dÓ7B6Áa«†v}|LÛ2We‚oŸÄ™«Æ#19°…cÚ¼0@ù0DÊChÉ62A‹)ÚDοÞ0RKy€ÀC1|«ôÀ‹|\–Ï7ìû#Sm甘]!¦v8±œY%Y‡);ÂZäþÙ¢ãL^¬ÊÖûÈ9Ä̇¸×ëc²ÿûŒªºˆcøì}h€Uk1—' }…dthÕ%‹3Æÿ)´Å#Å[·=`••ݤ=µ¯Ñ1YLUŽ&:Ê}×aÑé&XîJYõp-ŒÑn:¬Ë†ã1BU„UE Ë~™ÔÐÈ.kŠÀ·1Œ ¤ÌAf»”‰EJ LìȈqìçÙ&•¼áâÂÂô1º|)žX‹Ÿ+üü ¦ 5ê"€^hi+ Ù6·Ìjž x"ãA?¥#±@Êd}€£q9hñ¼µËs¨7½å­Ê¤U“½&M¡ßÚ²Þ YÌ? ‹z™k7¥eZX)À|b"›§çP`, ‹›ó4}%Žï÷›<V° ×pÈ­=ñŽWòILBøÖtõ¥RÒo:=¦A@‚×½c#Îr7Ð ¶ý)õºQѨÎÊÕ=B7:Fß¿Lð!0Qh÷CKÇz öâþñÇ5ÔŒmFeä@2)ȶ„#~óì¤ZãßûHU99°åV]©¯õ~ðšk\{ãÛÁ>ûa˜þÝ„¬¯ŽÆ·«—Ôí Ò%º;Ðôè¨´ï “>Z@)èr„gsUç#yâ­G¹ ia@ιÝ2ŒŸÉö¬Wf«šØ1FÖH,+4ò­ÿJJ–yVKÙ\›H@ëjÃ1œA#t„oå|¸>&UC”H¦díÀvšx™[$`ÌÄQuaá³KSÎVËÛ…täoK^ãcUTÊVét~¿BáÖ#´ôõPrä†G֮䗅ÒJ‰Ì[8¦ç"n¬¶+|U¥†jl g¹Ñ™Ô>¬’Õ’`kSŠ÷›O Š‘Ez9â÷qÚÙ¸zˆj'v ;ÚŸ2ýZ€3éûû}£uMÃÄWkÊ D²®Y—Eä+ ·¶0±õ€Ì5þ¤v#&óåض'EíiØÒd›ÀÚ40^hv“w #›{…Ÿ¯ÓQß`‚?ÿlîv ª²H!¯4Y@‰X;@ˆ¬ ƒ·k Æwm%ÇVÌÍQ4×ÄîITÊ­ £«¨ f.z2 ¦Åhnñ“˜!]?Ãæу(Ù“F ÊMÆ» È­ToJ|ÑæH@FfÎÓ½l‘më(àHJÇéõß'°°/M¶é‰í TáÄ€^ɺזIS‹ }sk,÷2½5Z@nÕÙ&¨…'7Vª0R†1L”äô)1ÉRÂüë…u‰µ§lyz“§.˜³÷‰!Ð[ð©äH¦=€\`È”Æp7ךvËö†uµM--i7‚·ï(ȬÎzã›B©7rÿ bŒ‰‚¸ÅÊfý¸‚£èÄ܉ÛÍ;VâܱÜkévÄŸ’s—T#$¶yÓ;¤¤i7€²èØže¼^Ø h6ÆÐ,Ó$Ã{¨ùLÔÛõi€VÒ›yúFœñ7Tés ÞZ@ÞKÒ÷!ê®ºÍ …k$vijmÊ–Áói"«ææ +ÉwÁóÑëMÌ yʼRÔÀÑ‘£PÒ†oLmûD¦š&¦Ô…­˜I¥.w”'¦OÙè¹Á-­´'¦o[¤ gê÷™TñŽz-ÙÛÑ •ð~Àª5n7¥ø¦'.WÕ‚‘Ûß/ÇŽª1&6ˆ-ÒÚFàC÷zpÎþÅ8 UY5Rz™^;†¹ªOäªÎïz¼®6Á; Êz-SW#à¦5Qn\«v‹þuž!qSÊ1M©7>¦Ñ²Y/wħX× ‹HJ&˜Œt£J².KöJîÞÉT›â(Ü ó’†â9#û8hɤ'À0¥Ywdz’€‘)mu‹çCÑ%áÄôÂq¹ÏH•Ò\â>²>…)(ÍJ£×Ú-Ðl(!»`žZDŒÑïJ˜J¦ëõõîú4-Y ðíÖ\Îñ–ÑH$n ˜^©¿ ¤ïƒÃ3©=ÜP™ >qnò©Eɶ›ÞhG;רK8* ½o‰Rà#ûø4:²ík†,f&³ ²»·˜#çøaa]M¼Ã?ïF#š‚X¤ À½[<1½FOÔQ¦'ÿ¯­»Û‘ÄÖ‘5zá+¿© †Þðõ,éËŒjà ƒAJ™UÝÞ‡æü¥ •ÂoŸ4ìCŠ×/ø"[7^ö­j£¼øàá4€.w£¥Í`5ʦoÄ4Là¬R:R²mDJ›´¼#^ä‡ÓȺfÂÓk8"÷—?GA½^ŒçþxÛD/æßôö?³¿k%n æ†jW’ñ-ì(`ï)"ù˜Åœ IÇ$StßMX :@V3)ìs!Àg—2î>€@jL0o’¬* I@ÓeNÿ½¦}èiÖ’Ì>U=1”J¬ê8óü)‹>¸UâJz³²FSx"Yaè7ØPŸ:^#&ÁíLCióÀ/ت:ÌõR:r F®¥Ý¶v--Ó&Jôø¨éˆïFª1Ü`½޵w¬ÔhYo¶0ÀMÔ; ‡Ößg]®…@{-‰Os[XFFî%á†Ö8Þ‘ÒQoVŽHÑÚ¬2׎$ÃSâ+5EWþ@wI3’¬ Žç¦š!œ`>Ž[‰¬5”4Í #mBÓþ@áØè”t  *<7Œ Ó+òш¬Q·FW½1ÇôûOŸ6G:öAtq¤®ý,d+ãÉ8g¨+ÃŽÃáF·§#|]?WãÌP¯ýa²ÌõRŠ@VŽÙÒÇWõñ¬*#ùøIºHë)™²€À @W«*EjŒ‘a¡d[GνÌõøøtÇ~É ˆ1Äͪ.Ó�Âý g®DfîĦëêÑt‰” 4yþ§ *Ë9V3&€ç%¨ËõÏ4>²›¿¥|0ÜdG¹ËhD扜yk`^—ŸOzצɜ€óm:ßÅzɪ&ƒEXoí ûBtô(Vþôæ&Œö”aþº²âv<¿ªŠvksb$qZjÔ‚¯1X)qÀ8‹ÉÂ[ÎöÒ¿Þ0^o 0Lf[HG¹ fn%˜€²[À¦ÃMÄ3¤Ñˆz´þò‹!àC“²+8Ò0ì¨TT«f UCMT­%+¸qø÷AÒÈ Å+㙟đÍâéHДFô{¡oTžewLè)4š›²Ýòôï. ðô ­„ß’JÈþmæµ`tñ4ýlóýó²­V%N/ÓàáFD ÓTµˆ‡•ÚS9ÍpßÍ÷aþÀ+ë ‘ø6Ï Ô¨D)7:°µ ’v÷6‰¹•“Ú§q”ùãûi2Ŷ­QW¸í…£€å‰݃ÈÜT™”9oœFÊÀ ˜7|—ÅàY5H jLÖz‘ͪ±}8è:.€2© cj‘Ï–:•\3ÑñBƒ’,š_/r&ð”ñô5ªÂMO‰M ã j©„1¢Ï ¶ù~CUê.°YZdâýŠ ‹¦|Og7æ>HL¿ñ Þos&Ì{œV%æã Ím¤–”6 RJïˆäàc†3”éS ³g*üIDATÃþÕ!z·ï¨$þßvn•&hIÎÀ†ª2dÛDY04ŽÆˆ”@sõ‚¦^„ÆœNÖÝñõêÂSê wå) dÈA¯ðé é5ÒˆF ’¾Rž1zÃŽZÒcêÊN,t! ]É”0 º¾c‰ìH¬=¦•âµ5â×Û›8 ëõÅÓN¹cú<ù;ª.+’5«é=}TÛG4ÚJGY8+…Y)eÂYµh€†À_§Ï/¯±P¥Dʘvà7QÎvúÚ57h«´lIŒv‘n5¶Xƒð•¢?ÚÃÆUr߬´pý6˜[Uùšµ}Xª”ö©nI ™*ÿÆ)5±/s›w‘Jõbzí4ÉÌbeÄK e¡7 kÉJÀH©Äsþ?„Á T5XsŸz^Ý TÊ h¬ ¬ñŽ@UßÅZL¯=1œ,g“›ŒìÈ¢£’×OlDV@oô¹ä÷æZ2ä@#rƒ•úÌC ´éü×¢‘ m×}7UL¸nå˜Gn4¦mç|š>þMÄWj ÿÖÞï³\–°’–EOᯓİ)€*,ëÂÈ÷%ñ&¶†œ&bÊ|dÊÄxÇã(ØbÎ}¾—uTÍÊÿ領áq¹Q½^D†H¸Œâ»ñj™t/߯ÞЇî¹ZŒOV|´È4•øö”ÓZºÎ6i„*^Ìœ!,â>&í”H9+CAP ŒÔÂmbSù#)áºâék‘ïØÏã;´CCuµ€c#0a€rG¤pL&{†È¦Ã›"”Z€À¸ÑSÒÃdñŽ{xцLÛZTc&ÃcZ²Í•ÇðIPÎIV/À߯é~!Ô¨„×’¦‹À>/ ǘHO–8«J4xWcž `ÒUJXn’p¤¬ÝQ‰¦à³.@PfBIS6E¨ÆŸÿHÐkÉúkÛG»wÌ¥1rÇuÍ´ìzŽ0O†õº RX³µhDV=“*ý.¦êHÖ·`«šUUÎø”Rêbˆ¤!h%ã/¼ôR¾šdZ4ŽMLj®ÐþrÜæ˜69Àµ‰ÙFšÒJ èWMüÎUBb(-Öþ]“F¦É¶Íé‰=ZÓË  p} 8ˆîÕ¸ýí’¬v]FÈ ýs ´óÌÁžŽsÆëR}š™ìv›®—Œ Yª–év° iÀèðÜX í~‘ñ×ïãYÕ“¬šÂ$l4=CC€Áw”+!×EÓ È”r¶r¢×ãp³Ï™÷Ø‘&ܬvð€HÒ ¶âìHæ¨*rvµ7NÆ4kOML“a»921«®mî+õgï»yC ôbø`ÌÊ0 U²®³eº¾Èíõ§ŒäfæŽHUÇw4¥A ­ÑëÑÛÓÐÙhùaNƒ•€fµô󔕼Ïi¸‚‘-C·OJU±†)“Å!já`JL$YG-b²üÁ4¤Øêµ9ro•¦Ö/˜‘‘¼Fú4­‹ Çg˜CÏ­=A&m‚Éä«Ò{;™›.¼Ë D>4Ä&*!›u럯x#🌾v$ çÜ“àoÊé¿b@Iî lk”aú~BàLÈ„jCUµÇÔR;2ÆFÐÌDÕGƒÏŸ²Ò€#¯c ^LVd ØJ }¦JHú¾°–|º1CÖϬ+óJéA_—Ýú|‰3W⩱h ¸ÑíßCÅøéE {®`hs;&Àäm°°¿jK6.|\.?PUÛà %Pí( #dK %Ù‘'}Œv€ é2Çô\é‘g×gÛž‘•v|] â¬î;¦$ÒVm¤#RÀÈ@d;`˜`ÊdØÂi0k!€kl˜-ÆQcŸWæÝVr @¹í¦ºõÞ•²m ¼#YæíƒŒ—{¨Kœ´w‹i=¹‰9gE0Oþ­Š4¢Þ@£çæSÆðQeë.J}ôÓ4næí Åǧ’H/3L3 z~:+ÚP,jËe¾­’l›îYWÓç`ǰÜ5VT…Þ™;²Ý>+­caz²²U¡‰ßh ½ÑHš€–½Bb%d?*>¤v J4€|½éMÔâ)4Žz#14ªñHÇZ2¬ºMh`Y/ =l®£Ž0}»UJŸ!¥ßzJdóWï¬úÊfNpƒ±mÛ¼?'ðÄ홳¿ÁwqUKæŒZÃɲÂw¤èïY­Ñ}ùPbd½µg‹TÅt¤ç²Ñù4‹¸H?“œ‰SNL@Ÿ‰KÁ."0ÕnazL]Èö!ˆ‘5¶¬*òúÂèêî‰[Ó Dʺ¬¡+©}šÖkCdûð!†²ÝÚyJ`߆ïϵ¤^ È‚•¶‰[i òN;¯A¼k¶sƒê%Pí²í™æùüå2«&ÊJ4¦'FröEõdÕG¦ÔFXOx¢š¨%An ÚÊÿ¦ gÿ²dx]45Ƽ欴cò¦ ôceÃ4|)Û–Ò‘èRŽ1lÃr²1@[MIÐ L¯‘oÉÏŸœQ¨F ôpÑ$8ÐÒ°¸}g'€•1@Ÿn²º`Õ3õþ\õ…PÂ÷ Ρj/S»œ9 rk +0^;ÜbŽÈnמ§óîÙÄV¢zå®P¶?Ÿ0‚f_èF[OSèÍç”UyÊFèí¯*sh%€.%£a™Ík‰ÌÊbdº@,”(ùt”ÔN&òlt× W•›¢QûHš^UÕ·?{ZÀÄž¨YéiŒMˆw¤ì‚ñrƒd+‰ÉºT-S{ÎöÉÁ1ŒqÔˆ¯S¨êõcßþHGA¯ÝÑ |ÓëÊ\®$Çè¢o"C·p…VRò»ãX+@¤0dµ8c8‹i`Áî‚ûÖ™Þ†€®9 {s-pæ°àÐVo&BIK¿P{¾ÚÄŸf™FU©Çæœ!YãäZ*ù=„ËÝ%+½]P#ìSÏ\K;L–RV’ó©ª#ô ¤ìI³‰ÍÈF8Æ´^&³âC–òXß#=ýþFƒ1”Œö¶rwd†öÄ÷óÓÐl[›ÀQUÀŽÀòié•R(%#pì“EŠ[?ß -"¬d+èÅ0ÌJ6®¬¤‹¦–¾ ðÆ]×c+jW1ŸñL‘€*¾c³5›•ž¿Å”dÛ^ã“àÄ0e¶ÍJ£*Z¦Y™ðqÔÂÙ'2MæŽÝ·×ÐÒ•yfÐhoJKv$Ø Õ6L/«’%1Ž‘]ÐQd^¯MÚ§…´^ŒÝ([¬FV€ŸA ½£¯å&nDÛîhb¹»{œ^•¦êÄÍ’-Ã\î:²}:ÂMÑ ŒotãÚŸ31,€ÿ¸Ñº`2&]–çª^5ÌM®…ò׿[Ø*íî&mЖpýEWBŠºð@U°¨ à­bƒp«¨"»çù(ͰƒÞ¾©ŽÝ9A%ŽEƒZ{悔oCÓU“i2ÑÞ1¥tå +õc€®©1%Ýd²”JE2klO>z9†0å}¶2}U97½ñrå׳*‡J2Þ”``UãzêöI¬ÊgVz۪Ɣ]Ók8v]0 ÐíG¯GÉÐE#+ ÂQhICä(u_YIVÂÓwìçíz|>JU%#ú×Vµ†òWXÉv9Ÿ.Ï¡ß,[C©Šy•Åx¥Ž²ÌU’µÍr„YííFœƒ’mk'F6=™Ë¦ض¶£ ç–³êRŽ€lUž”Ý:M;´@ãTçC/T_·.‚ÔN)7‹ƒ’Ü’µËªç¡¨I îÇ “±H\¦üq4Û„¬´Ðn*¾ûhÁ´(б¥÷†^û¨Šº€V¢mÕ¶ `[Á$2‡âç 0á@YLæ—‚ë¿%ú>6|Á 0N)ç|L0[ƒ)Ô‰a¢EÆwÔ"ÇWÒ‚ÇÈ}/³’=£Š|èçŒGÊzûQTåÄls–ÉrS˜|z[˜C2¸M2—Å«×ÞJ” ¤O<7ƒ´0ÑÕИ5ªvq ‡üi`L¤¬] P’™‹þè¥T6aøˆUÉúL›k‚–QíˆáÍDd¹¡HªÜÞ—“ñ¡!׿ܥ5ä^À¿ÜÜiZµ¤`"ðr[xnòû&øöäáq™+ëøô/v©æC :Vò€¦Àz'C£ „c€R4]U8&èú·õˆ“øÌ‰;vS⪕0‚ƪýÚ‰±0‡üõÂø]DZvnHÿ­OǪZÚœÛLÚvš@æhtq‹wl  jGz²&RÚŽ!HŒ'+0„i±Z«v…Žiê’›EÙ±¡²8ÿ) …:»-uǬyíˆiÅJ¬UËLUnä4Jf·ÐÂ\Ђ|Ü‚‰PÅÏDUôÁ)‘iüÈ*ißD˜'%UG°êxíÏwÓ XI‹0Y‹¼õÔK–!Ð>?Ì”Lc½zËHÀǦ‘M”¹éþ€·Cd³Ê”­JŒáCÏö+•^`ò'†#[IµÞÈ2FINŸƒ£A?|,Ðt¼%i„AíÔ+-WÅp†oñƒÓ¬¥ÝÈhÂ2H£=@¨v÷–t´eº0°ÚYv”·™£ÌP®Ê$Gd¡ÑxfÃ:æ6ÃdiVòJHXf…W]à#›R&€ý1C`D)[8¦v82A&r‘U䟸G“_CÇ#taä–Áë­èj‘_M%zä±ó§»ÿ‡ååSÁ¶ ¬³;$uÌšÃ>Rt“1€¿)ȉzØÄ†:#û5«ï÷®‡¡”‹º2„—çVÉJ)UM”3‘{‡˜Jpûß«|~–Òç_V¥Ÿ­YMÑ[ãýƒE#ó0âôÄȶR¢—‘ýcÐt[Ï3Ò¨Ú¼.|³è9;ªŠwa˜x&}™hñ;ÜX úœ³¢¤á@v¤ t(àg ØÎm…Ϫìhœe.ÞOoUžªÃù ÛY ©W.”¤#b$gƒÖÞ·”€¬›ÖX®1?ÆÕúºvÙfµƒ}º{¯ÔãòÌ*O9’R0Ô»qU5QÙ2ëíÖ4þ‰ÇŸLø^OO,oC—m¯‘ƒ¡zå4²v%2XI{‹!…£OêßÿE¶[$}>ŽM¡ì»ájUy¶q‘xzŒè“j¥ÉªWb…—ß®”›B&’…k”O¼{YCI´Œ·Ïx%zǘ<1íÜ·",³ÍJæÓÑÚ­^9Ã=fÏ¥åÆQúJ°räc12%Œw$Èö·¿ÿþ[ åŒ ØC'ž…ŒR¿ 5ʰ’^¥Ž«r94d˜ôp_ǵ¤!dºd¼£8½c MÓij9w7- •]2h@ÎßbóŸæ8Þp4ÑõÁÍ‘XV—út}‡ðl‰•ú«bÇUá.µ¹€˜gXž’ Ü¿“Ïlw„Ó§¬³k¶-’€,·¾µdªñÉàÚ#³UâÖƒÀ«‘ÌP2®*3©å‡c»Ñø,tuGG‘OOIàV-:ªš‚é(‹Z êÊ–lô»’–ÉT5:Ëa†é1ÂQníf9RŠÚ‘<·Ûx M‚í/×(Ã-kqkkÇ!úÅÑï‘íY—Å(™ÊHŸ’ ¬½[˜ë(:7¨¼c]r`zS(mu–û1e&s£‰tpæJµ8âÛ\/R";Rú)‹$¨ŽÝ1Fî¦J ²ÚþŽÆ%†É“dr]eJAPnÛô­OY×H‰o.¦AíÜO.œg›'Τ}ÎÿÜ{†œtOi^#[(¾cãó%ö]a[•2O‚0¯Ý–[F 8¢ËÃõ¦)W¢ìº­ckÂçäØ&Ž™4"Ég§#s‚¢²#ÿ@>d‚‰Þ^?FµM:ÂDcU)>°:š‚Ôøÿý?ÐëëKß:ebG%Z% d"ÃÉd %k1ʪü™(Ù-+ ½­:æV¯LÓ8ŒHÙ¬ŽíC™¬®‘f) =@&s&H¦$hòY/ ÿŽ#uQfΙ€LµÛͳŲmÖÛe‡VЬ«=1ôµ°uÄ;‚!2[]…*À(üʆjr9Ó¶<¤–ÌÝÈ¡ßþp;¤Ôî˜XC‰ËÐn¦Ð·Á6ÉPis³% ‹ìÙ­´šU»RÏ’æ²h–,S %—´j%oŸ%]p+­êˆt¤ló˜v˰Þܘ$Ëá¬òý‡ŒRVH7…6_5ÀÿtÞ*†FhÇT²Õ4Èœ)ñœ•D-ÖkCOŠ9¦ßÚЕFÖ(sè­ZãþñÇùjø:1²hR¦4™¶™\—\¤çÄÐ,ô"«vU¥”ŽÓ'¨¤Z©{rÀÏÖEóú„]Øæ”s&Ž|”zGÀõsÐNÏŸ–Üîom®‘ \û£‡ûêŽlÓha‚?g2QÕÎ1æ;òQ@OÄß-¸µ”ÉT[ ÐbþI/s3® ëBõªj¤L<žF´p`ƒstuïípÎpÊLäFÁEú†+iÌ37†ªÚ9ÀØ›$ÓHÖ1ÿL åk«ZÌPÉwÀQÀmë g•·&Ê-Ó5c^½®í`ɺȚոH©$âí©wA&hÄULK¥H_æYW)ÉŒ j=Àw©’¤*¾¾€v3!€é d½øÚp¶õP¶UÌÛãCÑÕˆ—ÂDÊÈn¢YÉ­‹XL©+¥º¶È@¤\ï×õ|Ï1¬ˆ‘ º&¾®xšõמH˜@IÀm¥Q8f›N¦ 7¨eÕ>YÕÏ¿ ÜgÓm›A„Œáå(²ãRÿ6ÃÇÆ§oĬ´[]\§ÏCyV¹Q/·Úk9cnä®EnÝ™9†’ ÆÏ–•zz2 H¸8gâ˜d™Ëø°+Ùâ“á{´^#sUGªr¡Ô ¿ôù¿ñ1áîÓV¾ñ37…Xµ»hé²É”D8^—#cºˆ,ðL¸áOó}¹Fú¶¢D¿Âó¯nõ>ª»u-²HÖ³À‘‰Y¢Ý®÷ùìZÛÚ1‚ q$q¿ õÚœ¸­r#n@ÙP LIÎJÎhOÇía %ÛÁQ¤á©ÔßK^+#úŒ`z¹‰0GËÈE%-­d„HP#G(·y¤#ÒVÉìÐ¡Š—Åô)í;(9–1}¥Že<À0ÅÜÏ}îõm…t…°œ's²­V‘–É|¦”s&²ˆ±Ozšnу8ª:Â?ƵXÛS=³¿#€Z´GGô}1ŒÞ=•v¬Z ™£ªGÃôµ|U[p¬&€‹p¹|>á&µuTÆô%XA2ûÁæz…aJŽÝ¼.ÿJ·gêbJ‚mGzGyÇv(#ù0´¤l¦äC zøИ²”0•Äȳß÷¹óQL )€ÈkÁpŽº¬ÔP¡«–rñ•äÉàî“aL_JG³RÞ±LàØ¯<³D&”í)‹ÚíÙ‘&²ö¦¿%žiäB ìa ™õ0é#åx˨:Ö’ƒM¼UL³ ËB M¶2†2‡H̪™¨"åþ«üªµ4‹¡ªH¼UñÉ”`íÖëmY¹HûàíEXoÕ¬8¸#òšVÕÒ‚6Ô‚§Tê¹êr+Áñrn¾o3!Ó›F&0Bض)…vŸX×®Q’….YIÖr¨-àoÊ+NPN`–£ºl+U…«‚[C÷ fÕ.,Zä µí)MŽJœ@h¬ xÌùh‡Ó§¡ÏÓ±ûÆk÷èE ªnÛZ8Ã"+2šÙª:v#›ç·6=¦Ô…7Ú±+· ²éÈx[}þhv9f7ÅHÍëG’ ²Jæqº‰ª©ªF(QbÜÆ4Çèî)›5Ûd9÷+5Íéü~A‰EÇŒÿñjÖh%2ƒTëícŽË½…%ÍJcUwш‘»ûºrîXêbˆ\‹’#(`žp£_1̼…c„}êê¨ÄŸßÚ2RUnùðd™d@´`¦gõ® CÖ^Ž„¬&sŒ×œ§R#a|²rG¼FLÙ3ҋצDöàô1™7Zî.J”ÙÊ;ÂB¯ªA0½*fkDš’¥@ö=ßÇ]#^µM€Mg(TÙ ½aä1Opw§Ñâ˜àÈ\&¨ª®«*¾å³=M|³}{áŽ)Í1Ä¢H }€ÖI¦¤Ë¬ôðÖPMÙSPúû«.ñf!ϰ{‘²’hâ°Rþx¤åfÉJg%šMÌ Ó둽/“ÒVV"X¯–l145¶’RÎL´[CFbÊ~q•SfXWÇ5ö†L Búwõ€× ¹qz ]€®J¿ýóÏ?Q: Û[—Ÿ)RÆk6F&V@hŽª\ãKª&HSŽä$f¥$3,ƒ¯cDÖÕÜH{Ò¬—,%A⦤—Û§q&}ÿ¬&€e¶>€3z¶eüÛîÖ×àó§ý6¡ÉV»ÞF#mÕÎðÆQÒìM:’Åð¤ÍÍ™#[€@TÅ $Hù¶'CÞÖÓ›U+m%L]ø¢…Ý®‡BrÈ ô6¥^¹—T…·Üû`j(]?+@)s™ ™ Ó1™Ü›øÁûG%8“<™ó±F£u‰ÛqR`È`=¹¹UM¬šRfØ”‹Æ)µFÿ9±ªÓ˜É“øªjÛmH´Ëº0mH¬·•š%s®%0>°€|äÙöÑ¿&û黽ëÓ4E6¨Ymk%‘¾ö my-ïa‘“͊φ"aƒÄç/J(=©“fÑ/÷Ùi€5Oožß’5ª4”¢…šýbâ|"{)íÈ|0=J³`‘çzçÔ%G‡e¸XÅý*OUkP6n*¥ÀØIÐî÷©ÿr R•&†OGJ2Ç‘ɲG¦ÔÒWpëÝJFpS•s(Û¹ÞŽóO¹Ýð=BU7HIÌÙbœwÁ³¡Ø2Yaz™‰œFvÓ|`V•zÀ¨ŠWÝPi±v{™ot‹Ù³.%†ù¼aB)ó¬]ËûWiÕÙj§4qân=Òb2&•`Œ¨ÄM{kà“ú÷ñ0­m Χù¾<íªšç¡Ab®ü$Kò‘3´i`- `2Q© 3WBšNã¨oÃv¶@-F&F²íØM¡ßJöµï.ôdp™’¦M”`%‘Ì‘¬Æç)ëUð41Ž2OO#׈/‘žÔÑ”n a$PFò)½•v³úbPâûš½øn§Š—ÍÊŸ#¾ÑÈU‘ŽBïdùGÊü'èH ôò>e¨²‚Ï~m»•*\çªÈm»ûAfÝN2¾È!^'ðCÛõ˜ ÃdªJ穚™•ìÅûbÁªEU]‚­õ0dp ¾vÿj|xõŠªÄ)-€d‚‘åÄù«:/7S©+8µPZ>“dÝ…Þæ¢”„¹ªJrΪzFÕ±*1,ã |ܪÓˆâ-6’Ÿ’̉a›?|f_£ #a›7= Û¾o-ãXW†¹µ9}>4{a‚3æû¶À|t…¹Jö« Égßv¶ô݈­HÀP’#eߨ¾´ºxúz¬ˆ¦ÔËS/,º×®‰Èü ô–dZ:jtGbkÄ[@@ĵÈoÄc½ÜÂF„çHœî¨Ú3ÕÞ9G½Bß>JÞð®|þàQÍA;™–c}­dbÈæ>V)ÉÄiû~ÿéÃÇ÷û{cŸŽ-&×HÏ ®ØSKw©/üg^ˆ­A#j”)s„–ªZâ< (%pô21ž¥õEseÇd”¢êvèM™9üÛ_ýåÿTÃz„c#kvdMÜ`@cÕô}{0¢IEâéÅð˜#ý®„,"›5x9r³2}Šw,+1eb< °£ý·’O1^öK¯Ñ߃joJ½šg¶YͰÝUé…FnÌeoÕJÙâ¥b$M¿_´ljþÄlûP0×þóW$X e«®}$ç¾O)3Ï™& û.uÖ4ªH%]“©ZÆ“V"-VŽ'6‹Õñ½C³UŠ‘)Ã`†ŽdÝÚãÀe]~ko"±Ò¬ððªJ1Üy{’õ ÷Ï.LðU¹i/ZOiA\Wb9Üo®Ž†Z{ŸÝÈÚåÛ uá»  ª>MU¸Å]HšJnWµË¶ fA9q¶Í%À»KϾÅ<%6¥Aõ6¥^I3Y¯ÅG‚â,ñýʵdïd˜2[9P—h" ô &¦ñ-S;²ãuý|ñ¬¡ŠO#¿Ëä̪㨋[ãèW!àSN–áM©—-PUn "ùùrô¦m¬Ü$¢m†<êïßpwCdö\Ç~‘9¶\‚>æ¾”Jliò§IæXµ;Àµž^8^N_cJzk×%(ñÍU-0J)5²mMh04~ƒÈÍ’ ]HÇzäÄ0^Æç#3—{¢v á##•ˆaôh™´À4ñÕãE¿Sš®™)º JU%8jåþ7d”fbâ†RÂÇîI)])W­…gÌøF´X¿²k—’iá Æ°l> àKH `/æ <É‘9À5Šä/öÔýI?¾‰ªñŽz[ Þ+UJoDWkhËl ãðŽeG]¢å[ÏGØLÉ]š¨è¹ð4µ'«ßqS´„ -Mçƒék™UÊœ›Bœ  ªE+ÁyÊ¥€ j‘)aÇFXư‡%ص+qûÁë펲P%:ˆ€,˜äLO&o÷çGãh7¹vL&-c¶K|ƒÙ24hŒÌC‹iq4S_<¥PÙrˆ¬E¦Ä 8¯‹€yVr_æý.6Ñeû²©f؆2FFr3}žHáHл9›^£c€Òm˜Œ™&e¶=/Y£iò7ëóÿ)|WJ]ûÅhz÷,d( G íʼn7£…¶ÖF¤Ñ¨Äd—ÁŸµîç×G|â²Øt YL—o(Üq-xV”òH eV²cnÉ2Ñ‹tÓdȶšP)eMÕøCÏÇ'䃗-àÏÒ™÷'ê¶L«";– ­]N,GšiÃv›CÎéáëò…³XßZšd4û7±‹Ãxš}qºHÇz›Þ>øm¥Úô2^À]ÖØÙKꪑÀxÇe qWõù¡J ÔÎ|öÑç E„É|î?|µàíÃØ­ûÉÖ»MÈ^f T  ¤ 3­'ZæÖ@‹AZâóQÅä–^h—M° _>Y•[À3ŒÜ;86KUÀÛÇ ªó1¦ºÈJxúYõ)¤¤1Nž¡#%¦œ‰è‚õ6.Û‰“õ·é¼á f>Ë-pÈrh´£*à«.[ö2Òzá—ïop ™¬ä[¤6Ô1òÊÏ\?/UëR-ƈù+5Q X‹µ•YÕUv+uëu¥Ï\6”2PãK*‰~uhô5fBÿ.FÒèJ Ä4Hc½r%&0پإÈG³MÓñü¯öˆX@Tà²àÎQ©ßYÙa2¥OY UY)ÙPËdÌkïã¯4¾jL¸sV°ÀW’•ð"·†ÆÈ²‹¨Šdr†¹ER:Ò(ÙÎJî­1GôPŽëõz‚ƒPÕV­À̰AH`|£eL¿€¦h47Ûn‘aCeG;ÈÛе÷ìRÎÖ–¹ï®’o3½`%c ”pÎŽªÆÕ.ãEWPíØòÉd<+µ;¦1®j¹íó$hDG ¥¼%›[¦ÌA6¢ v/‚íÖP>YÕՔʫQu¿¿*uÕZd$@ 1d‘eG/©Ô†HÑSH&¶EÊ¢‰˜U#5"Óä£$#g«rJUë‚û å¬ÅßáZ› =R;åœÅ]On ešÈ9Ãvv}¥ØÕ`A#˜À­¡eÕÌ•´·@-Ž€!‹zqËiØZI h ¾‹à‘0±¨7˜²£f#àŽ2A-@ÇrÇô{à %97¸AñùoOŠr‡‰”r|¿ÿ÷2nîžÓ ½){ͬbªq…¿¾¾è[ÚA†ÛßûÖ• ’?RÐr °^¥ªÇez›sˆáF†Ác5¶Oþ9à”Ö¥Q4t8e×Y»£àè缕0½*[zVJ»EsÛ@$Ó»Ò«ÒÇçã(nßùîj OŸ³²>ôÖ#C -6¼6g«le¡ª”'FdJ¹e´tµæ+5]{‰IóA[h[ï³Òô¹´I®¬ê—”–õ+;U-£ [™["ãeþ‰WjIn‚ƒ|åg[%|˜†MËÈªŽ²¡ü1HYÐ>Ér“»,RP¶%8CYUæCãvp£QIÖHóUÛözŸÔ™ôîxXž Ì<}.ÒLäæãÐô¼Ž° Ííë”àÊÏD@‰¸[ÈÆ Lƒà܈U»Ža%±.úI#ˆa—¥ñ2ª½CCwúRô-“¥oJž™3t” ¦“íXlgÕi” M–@fÞžd}ͺ;}ʦÿÌ“”K àIEND®B`‚ic12›‰PNG  IHDR@@% æ‰ AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs%%IR$ð øIDAThÚ×v$G„a͈+ï½»Ñû¿n¥#ï½7ûUýMt²ŠÚ³y"ÒTus8Þ{ï½üóÏ?<òçï¿ÿæ4L9BÓ[Ö–5´@)ÆÃ‡gz/ç ŽŽP"qÂÙsÊ2ýõ×9PírVº#ÄiÂæNhœBê¤â°íã*²¯frΖƒB‡Õa\úž‹š‰¹cÛ±Œ“?ÊÌ5!å!O¡sTh;eBÃæ¬ùü¢,ßþd¦0à*8)˜Jas ¤!q%S„mNSlÊ”Ö4œß¦)-¶JùY`‡VJÌ!7Ð:ZÈ3b A"çä÷‹X=ÛX¥Ë#¤8vÒ!“ÅŸJ#'Z _Š1üq€)¯ü›z°’¨;„´x‰1ù¢C+klâgRˆÄ9Ô…ƒsyÓ Z‰TX¡G”Sh¢œA‡lºŽ”GSh˜93Å4ÖÜü!˜^ÅöJ]¢¦5†³Xñ!œsJwxp:ü™¦°Š ¹¼Œ‘&¡Àš°F§¡3m«¹&lü‘ZÁƒT!à.vÉ]ù‰„\ŸQés­éh5­×¶ª·"ã…’¢yÄsgUãoW( G}t­1™98Ã?„LEYéq†°Nó/´Ñä$’NÔ&jÊ¿éG1ìÂÙr€S,d´ÊJxÆ#P+šìÔš(''r¶éXÎyl[u(0erê¾æ FWœ3U':ˆJãàW~“¸õgkÒ2g¥­xþºÁ3Y»4­@¶C¹9¥¡UìP£\à½Cî½8p:YõóÇ¢þe  ‹ñ×±Ì-¯Ü5åÿô'ñ >é‚d­ÎÞù4Ý”/Â#7aHþÔè™k*jŒ.ÿ±Ç3ýùçŸÃ}+áüùçŸ@NR£0S!Ï@»0åRh:¹S‹SÊe÷2Êg œÿ죶J©ª¾üñ‡”ßÿ]èÉ'ŸÞÜܼøâ‹¿ýöÛG}Ôu!œlM¼þúë¿ú꫟yæ™çŸþÛo¿ýñÇçÝ :òaÔÒömtëîtÝ«QH+Ï>û,« ýýúë¯õª{-¾üòËÀo¾ùÆNã?ñį¾ú*Î?üÁyá…Ú­é[+U”+jyMíÂo¼Á—Yz›³JanŸÄ#c*Dñ•W^±º±IúÆhO?ý´zpÖn=÷Üsúâ‹/t1,L4~V"=õÔS/½ôÂ÷ßiwœ†3~ÿý÷ûJiLK‰¬PÑË·Ñ)Æã?þÎ;ï¸~ø¡ÖÕˆÆJvÖo¿ýöçŸ^÷­;ýn 2„NdŽQÉ„.ÕâhËv¸o¶ã—_~)}ÍÝ.&<Îö2_ÃùîFÝkÈMˆä(æLtoóÔ#ѺûðÉ'Ÿ ÓåÖÃøöÞeûôÓOÛl"Óf}ùå—kKðQH¥dE·ð&yû²‹mê2h÷³Ï>ãKs£z^ßzë-—ÄæAtã4^{í5ÝwP‰l‹ÉjÝÍ´~O*„‚©Wޝ"“ÈÚß*Ê¿œ€¹É”ä“Ó±“·j׆yF­ÍæÅ·$뱘Ÿ~úitSË"ç°.ƒêòÀ§Ós˜ìéÊ?(˜6Z'ÿrµ²Z/–´&Á’¦C6ÊÍN & ßþy=o±Éy|û<‚8CmxóÀñùžES¡ÙÒ­Ö[Å ô‚i……l6°Ë£[àÁo Í²)6‹‚éœ D²M·×(ˆÓ_+t!Ši×Þ¢©nl'BdY:ðRB“n68ßåùàƒÜ6®óA"d+¤ì9y÷Ýw=îÂ^á΃Šf\â&Ù¨c«djû-µÍ«K;ôõ×_¯ë×™×—&Ðl¡§Å5øøãñ—§ßj­Š¦,—ǦxøJ+áqêñàtKq¤8öbúÁ‡Üù2ע泦 ´yZ±1I@´ëºiLÞ|óÍ.Œ‡UbÝ+fU½yRÆìòÌÇ–Ûåâ¹·Ôí ±)¦ yü8ÔÆþëŒÚêÉsy  dˆËàÍ3ëÁÒåþ°lo0kS;¾£ÐM—'$f—ÇF¸in|>5Ûo ”0<!‚C9ÛZF‹V‰cSµÕ¾êÞ‹?-V—p—Ç%±¯uÏj}}ó`Ú{Ì>ILm¼õ¸ró9Û m“aÚÚê-{\€‹aˆ µmF{ȶ%Vµñv¦†4Šï”•™{´0¸WMåm¶öÕ:ẇ°5k¦fû]¿Db¹{µ«Á¼ó¯Óªj—]1D£WGïúNOp'Çk‡?ïŠp‰¤ìœÚÚåØë)jk)xŒZ‡§‰ãˆto…ÕªJ¶•l ê!î‡ÇrÛ'¢ŠÙ{ ©$­‘óØéO ÚuC:Ä»ETº,WÂÊ…èSóF²H¾ÛbË%ò}b­ÇÛÆðt¡õµªÞX£ê{—zàÝA¯¼µõdãÑtÃÓT%õìk­‹JAÖÙš+Å™”‘}côÐ$JG 9…’mºúú¹. 0­•—u ‡3~}æî›¶Ú¡¢­dú(«)gýñÏ¡ëk´XìzÊWX¨(¡!üQ!ü˜¥Ìz€áÉÆŒÃ6"äï•·õ§‡ oÿqy c£’„iHÓøùÉ ¡bìS:^ÖJNaÕæ9«D„Ëæ|§ðXÎGr%#L±pd‹–"}u„ŒÎ*F^Sp®’1'cð½ü¦;•*3L‰S~—¹H…Ù”?`jM Å ©×)1!ŽÄëo@°ÛàÒ’‰Q¤,vBœü•“ÏœÒUƒ“T-Úå/WñòC¤ s”94Qa¡òWòÊç+¶r̦lúÙ™N4¤¢ÃÎú·gà>€+AȘå5=X|c*åàœO{ñÇç4­JþØqÐŽß… '!lăO(p®YS´˜ëRVv½CÛt—Õî2›²h²45Âóï| v3ÍÙªÝ>ƒ¬œ¢•9ãEáœÊÅ|MÎ-&¿DÈ(_?È GælÙ·';ºáå]™˜ò%ÂwY=“¹)[zYC¨Öè7Ź.¥„ ˜Nò®xçÎ9\wÝOVN…²–بîÙÆ¬C…ޝÑÛôígT–/íø&Ä1ª‘a‰V/‘üŸÖÎøç)dó·ˆ—n¬•øF„õ$‘•Å1†¹:ü‘™±çm‰8ì: ÉßtDn¦!Û0™¤ %:ZE×zI¯º¥°Ý±!ä¤?ÙÑD‰y¯BœíþHÆË–0¦ÆÁîÁ !DLùc#md×iþ «,ptøÛ[¨±ù)®8$0“?‰+^t8«˜ïªFº‡èÈ^ÿ¯ÄZ2¿zçÌðápp¦³uaqºE8FHdÓÃ2FsD8Æàgçò éaLÚ®p5[#wŸ¶LaM/΢ÀY_YçĽÎõNîʼó×Y ¶FsÎM¯„IÉ©¿I¬i6§Î\­è$¦’NÈŠ‹Þù#ß½oŒ Laù«] 1!‰ ùŒCŒ¡å¬ýˆNú¢]þÌ ŠQæêè ¦ÂÆ™ñˆp†s._ÑÈl#ËX_ÓÁW©ÿ&¢¡E…«ßIEND®B`‚ic079ê‰PNG  IHDR€€L\öœ AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs  šœ/GIDATxuÝךdÉ­¤Ñ>ds8ÔZ‹|ÿ"¯©µVCÕgíýGZzEöà7 pß""³ªÉÿùáøÁ|ô£åÿûßÿ¾÷Þ{ÿs›’…ˆá!øxU<‹?³ôÿóŸÿŒsþ#ùHä³ ˜Úh‚hÙf+†×÷Ä+¤Y?§ã7˜€HœÀ¤Vk)¦†_ªŽ›Yv⥪ýÐXUøû‘Ö»q’êàà v¥’Kê‰Iʸã?íªFk‡ˆn²bÞrâ•$ëDƒï4›'œ¥pâ&^XáÔ´[G`xœ§ò Æ—=¥ŠyY®[Id}*F²Ÿó¢©ºú¿û@´ŒÀÓ¤œxAqÊ£UÅËæ#ˆ³ñÕRÀã äW^Ó˜bÁ‹äã™8ùªÇ‡Wõïÿ;Îɔм >0šRk´Z»R¨K‹'TlÙ5L1-•+Kuý.É—K ŒÃ«:MŠAºB‚|"y)Ûî‘S« „…L00©Å à)P!§¸T1°ûï)5΂dã·q©Év>µXIËë ¯uBùhB馵ԪF+•‚ìu!²Jv|çXJ¶‡[à:zñ‚ÚUx"ÃWR3ä” <ËÛcHÛ Yíô7ÏŽQªxoŽWÕ<œ½Otr¶­¸e#Š!džªŒÆ»I5ƒ4ßpK%锕J(Η Ч‡È®G)ä”-+Iê-Mv%8M½æ#¬5¼T8’×"æûï¿/°÷;n4H“¤2µ‚R®a(0´ðÜv`yZÅz×WU-²`j8Røá)´Ldí,Ú˜‰W•rËùF«Ð²Ô[B)8¦vcÜZ)´†I¡¸;i)`µ†¹e6<Çõ”{ÚçÉ&:N¦X§àîøpðÚ”²Tγºó›F\‹'ÂÕûåó<þY•`œS¶B!βÈŲ'á‰v×]·Îø‚át¶Ánß-S»›<^O­©]O@ìÚ4P`ˆ›×ƒF.!)ÖRhI$¾@UMвAJÜ2Ìð©à¨ÃWˆÉЀyœ•„´ŒQ2˜ˆ˜• ‰°åM|\ÌmgS!ÀW[ +ˆÓÑȾîßzB5®òcû˜2Fšmš²´J%RKËiÃY´IõDwÙ¤âAØRÜ´•ó•#ÖEœU(Ži¿PÖ.<ñ˜O[²G;¥Ú5$Ÿ2?Ú™~ÄÝ]ú$‰ÿõ¯­¦9¦[›Nÿ’¸­rê²Oçx*oÄSmú.rüE³<«B*Ç2«–—šíÚ,[G„—ºëȶ,àãÇiSC.ö]ή >$»Y¯]ô]¶òLJÏÛ9|Ê#•…$Ç×,¹ÑàºJuŽÓÀ·LÄråUAl2ò8 Ȧy‚À”!âhgŒZ¬6q>©‚'o¹cz*¬E­kqvWì:É6§åY^Vùu¦ì©€Åðy|)Áªè°ÚL½å^–¿+ÝÅSk]Uä.L±¤òq/PÌHñV•òÔ´e¾sy©¼œÉ'µÀáwÑ£ Áã4[Má×mÅ ^J=$‰¼TH§#®Ç8p–tÙ–+Oaà‚È;å“?ÁdSàó$Ã-S‹’< ä™p"—Ü˹ÜÀåÐðß*Ü2—“êÑe¼aòR“ðøê"ÍÊa;‹Å–â–ã“(à•œ{¾än«rã·¨b‚˜âj1Ï«ùR¹Æ\Uj‰??p…!¥xRµj ŠKå#×zãU®D6sa,£U¸ì+ õ¬¬¤Sn·ûÁÎ6ÄK£ÇŸáޝœpä@ʧ5L©øvRÊr{(æYY‚ì)N'|©ª‡¤¦K†w)ð²RâC2Hf‰³½¬<þ믣±;,â©Øs¸Êjd³òqø‚ÀhqÒϧ_j´Ô€:.»`Ù!OÌÔd'8fÈNÎÚ—ª)§pz)UÍ£$r„§.ç2Aþlñx Nùàuÿ–û’ª§/BÂZ"/Þ@=zÛßÎñwú¥ ë5(ÎH± ç¥_X×R\áÚ…,%`§x›…òª($¯…=®Å”+™lË©EkyýFIôÖÂ7Šer˜OºR²^]KLA©ôe£M.Ö%P 2K'… ã/ب˜5Ê[>ZÔ32°ò‰D³ÌšG<æ‚· «(*ÄYôíh´rã7Ó¶ñ4büõjj1õh—/…Ãàé(´\\À'(¨j¸Â!u‘Ô«¸ªhy„ù‚­C d]Î BN´D€x½XŠ*(¡=ÏÇ¡,N*p‚¼ò“‰ðØüÝ tëÚ@µIk[j sÞ\k bµˆœHœüÔĹKß9k|¶ÍLj’Ɔà‹o`4Û\áyIî&¯?ømyq©“ ^÷eÏ ø}º§ 4ƒˆCˆÙáwþñP!N”`åã©•]`™xˆåŽÂ’:k‡Š£åçlÙ%ˆæªŒØ;–fÆd!‘w•´—‘[V…Ðr%-+ä7šY¹¼É *áÅi)¿äÞ¼Ц¼3Ýf(¤¿Ö¹¤f‰Æ¦åE}±›òL{I¾*4gx%@JÌzVpFîø õÅ)%Ið\&>¾ÔÙ´˜¿žÖHoýHGo,ˆx‡…³ó•²dÑbZFv¾vr?‹Åq"ŸÈE}y°pfW›—Fë+nËáb%¾ìB;å[éqX!e)<)§&[k^¼’u|jŠ3“z¼.“õ"u©³MÌr•w‚Å|z»ë#Ì«ZÉÄñ§‚áO|„qJíÅrêˆB¶±\ŠŽk-2B%W³°³ ¿+§0&œŽ`1ÍnY:׋>‹åÎø¹\ŒÌ.‰ûÓI°Þ òey¶Qš‚“_j]âG8ÁÙfxRXõJy:8š+ç.°›ûpM’/›OD¼]+Ø9à‹·Üm1ÁS|}€Îá(F5Å'í© Ò”S8/uâ̯E[â«…g–³²[  òqZŽ9Ž ¸TüJvj€‚RÓ´£ReÅl‚‘!×u¸ï?Hj7ñuZY©ÇoCÓZ?tyeõHî)®°®ã+'b);P ¶Þ¥,£%uÆN$þªa'¾rA}ßâ‰ÃWHœµ,^UÁ²–úîi«Ê¤¢YVUöT¸ÞSK‹1ø*w *ÌGÃŒHgˆ Ó¯Ö².;‚!Õ¶\ˆ¯Kü~‚–‘ãó3…˜lÈ:LªŽÌ,ˆO¾¿lüüJ¤Æ/NAüV rí™~# ,™WØSÙ“ú–kOê-÷êqYòkg©Ä’HrÓn¸ HIR–@ËlÙGåý2Båë% ´Í) ã0Yœ-«âGWÈàù3ˆÌOáæ^îêÇôhŽ•¡-ÙY¯}"eŸJ,eyŸ¿;?îåj!§BžÀªJµä;—–·ðë_(ërV®ªÂMR dŸ™©¡)ᥲbÚÛ 'Ÿ~µ|`ÁNÆ2Z[㿌;%0R6ÄS–\¯¼ä–°jyñ†[¼ýl&©öSß)Xãæ§ùZÆlZ4gT,eyò׫”B{ *É'˜_y¯„áV A̧ŽoîÅA¨Š¿m±„e5ù§¥â¸TÁæ´Ox`âb»Êž-ÆI'° Bšâ–gv…¥º?FÜEmw§ÇLÓŽÑò‡3‘Ë]€à‰oàSaüSGÜ’| ­Ùt§XïM?<ÚY>u©'5÷&ÐÏ>²xUž; )³vü´¡%ß½Ò2©îbHKÿ°£ß5ÚU‰ó´ ÌëXSË‚zM8¦€ ×ëº-´©xŒ–eçe#\b/V.èøŠ_ò¯§S¸„îg¢—<¤€Ï€Ñ pý™²`%CÈVXSÌøyà©Ü)sŠªªOðÞq'Ó9LMðTÉ^ÿN¸›uñ,C,7ÇÙ¼,¤ ™?ÉO¡’óQ™TåÚ®F½jÄ•´ñÙWÌ€ 3ÅæTÕé[Æ\`%í艖Nø²ÉJU'¯Šì+³HNÀ*ÀˆØ'xöÆÌ€ø‘CZæ!Npd+ñ6W/Ÿ7 kYj´'&¤ìø–lKRUH%t ¥â¯Jmñ81§#[Ü|„NX–] ?Ƴf-óÒýv:iá'R-ü´ÀÓoc'¸^jáS€³-+ á“ ?Õ¶„cÆ I?‘ªÄ¥l„­JÊ’_P6¶HM°ƒžŽ@I|»hý‘?©Å'B-uøY²¸€²t6Óµ•ÛÐü9µâ-U ³%¤xþTHgÊ2ËÊówþñ¸C×eH´΃îÊÁ1qZ&R¯ÚMG@<'ðúà• Qb>6B1ZBU©µ­’t0[Ž&`²|:â3þ\ê Ä)²š.N‡?Z6\Ш;Í3%î³j"¶ù‹eü®P#¥\ÏÂ+N4¿~+Ç׃ß2–Mp^öÅÕZ®c]RXÇÄß.£%²lP°Â Ö«A€ rÒ* ¿ó—ëÇ…¥Îu áWR#Ë‚•@*‰9M§ôø9 j<±z¹@>E~CS ©ðD9ñ.Xüù•Ÿµ˜6ÿ4@Ãt(R)ó,‘ .ÎwôÉF_IK»fŵ ¼1Ö¥QG¶ á•ãOdú‘£]=îË_‹Ç¯"0JÈYnÊR[P¯¶–[&’oˆù)oš‚ÀºÃ?þñúÓŸö_¨ýêW¿úûßÿžÎÕò>\ÃkÇü·%¥¼.ø¬¸g’>œ)‘JÐañ¸8Ù*Æ'a•Ä´Œ d1ùé\zU¿Øâü _.‰–úYªç‹G¨*°¸¯Ëÿ¹­Sspë³/õ²XR~F…3GïŒ"ã(tU˜ËƒÙæá¿ýíoÿûß[Œá«­¯@Õ9‰¸%åO}êSt®N|ð—¿ü%\ù¶æøä'?yW¼÷·¿ýíŸÿü'¦!5Z;©ÅË X%¦%žþë+è©2ê¼ìâ‚áS‡t^ævFÿ÷¶>Á4v¬ü?þñÞºûÚ âg?ûYå¿ûÝï:ôut|5úüç?ÿ¹Ï}ÎüéOâµøÚ×¾¦ ÂW¿úU§ãIÀ¼7û¸÷‰Ø*^J») ßüæ7&[Óñ)»Þp]¡ðdÅ‚¼”ùN6"€”JÜ´h>þ±æLQÀ€¬¹“ÈeWUð‰O|Âý²Ûʉüõ¯uâ:ÎŽãV½~©äË_þ²stÿñ¬WÙ6ƒCð+_ùмŽhÖÚ‰üüç?ÿîw¿‹V÷|YÞ2¤9·Œ¤Ùé“úå/9B|ÞõîôÅhjYLƒÁ-w‹À Y¶“b˜ ®\ ¯öñ-(•¯‡ k“1ãä! ŸY?ó™Ïtr§8M‡^L…†0%ƒ;‚/}éK6ö“Ÿü_Š ëè="÷à¾ðO“2Bdzò‹_üâ‹_ü¢  “l³!Ü}® 3µÆ1­gÿõ¯m¶8µà–ñ’ò~ûóŸÿ|Ë\:Ç— SŽ#Ž#eѤ õ²|<ÒPƒ¯€/.;pLˆW‡ýÛŒ~ŽÀqTKKÍ~‡žšöRÞ¼ßøÆ7<.®–¹’Èh,Î׿þu‚‡ƒ&œZ“ˆ!Þ½6^Ry4`#Eïp)›9œ'Û¹ð=öå~’RÍlhÅɆY½cY|.1_w>!@´¹Ë7 ~ÎÔ«Ã{YÊËÝjF·Ü §°Yw=œ©—¯kàõÓŸþt]b*§ãÙw…Ä?þñ½ß«Mg‚–‘5§Sw¶ä-ɦàôu{øÜ4é”ʟχ÷^ûÚxÄÑjqSmÅMe)h$…¥^?„WY‚‡Ä«’2*p7¾Óááî °¸_bê„Ù;¤Û½¬Ózoüìg?ï$ñìG£ýèGh”©ÅÜô-É2Y…‚TMCªÝ!zìÜ7•;Üj[òh>œÝþj-ÿð‡?x´ך¯c ò–e«j%µ³¥Ùìq×ì%ªæ©>ѲRÎýÛßþ6±‡ØA[¶a"Døî;Y±Íwú÷>ÚJT1Wè[ßú¾÷~8ß6S>Ò ‚ºŸHàŸ‡ë©Ýé$ÈûXêùðòqoE€/¨ )V Þ±òúÊb²€ÅR8ÅüãÆéM'‘I¢Ry¯?î§Ã[:}/G•H±8<…Xf>¢;}y­ûÔ…ßuB±FËãÞ'b†N3µ|ÛSÞÕlìÑBjÁg·×#Ûá¢eÜ">óÅt¼Wé ÎÎTŒPUG2?…ªÄm!Úâ×[©ÄÝèªÌH'ô\*ÞûÝžM§¯ð‰ƒ Ûj²£t²]9óö¯62ñ½÷½—{ðSxò•wš0Až5F>D•Ï_"»{<…â|›Åô±_y/ŸâJv±“%žßFjüÿ@¸ŽWPrö_e~{«M {§¯nFùÍo~|ê]?¸]ñ.Uåøün=ŸöF¿»{ n=Ÿ+pʲ¥Î.CÈžo¹M ˜Mñefh¹o>ÄÙ¤ö|xù¹Ru矪pdy¸’ó:­PVœ Zø5™…bÖdñx* Å®À FóêìÆY6õLdYµp<øn½p´ñ]ªÞN”½Îk£ŠMSlÚ–wæá l+ÙU´¼®1Ü AA{‰CS¶çƒŽ!û|ŠÓQ¤©‚Ø«»,$»&¸g(ØœËBÄjÎãý^$€[ª—¥ÈUÿòs„Ê- gcÍíµÓ—nÙÞª ¡|¹÷Ñ:šÆP‹Ï¨¡Õ¢Âb:hVPÏÝ:^ž‰˜ÁÝÓ¹#š!I‰{ù$›r£¢E@˜å.O „¥Ìg• yç(–Xƒä›OL%~%⥠ýH̓ßný<é;•à;}og£q Fœ1ÙÚ)ÌBx4È–â˜|3ø­Q3øÁÍÝ#vƒãg8žÑž/c¤&+ N§rÁLUqßb®Y_ÆPXÌ×"føÀÇX.*I½XDìtâ4VY©)ËzÞ½gÝýŠ¢Ú}h£uƒÃ=õ½º<í3e²Ì$ "o˜–¼eȲÀ ¢Ö0~›$6¿÷›€i„skÿ×åßóáå“Ú¼ÀŽx¦Dm1…óÂùµMGfqß‚m“SI(¿ýûV^lâ§ç®¥¬žewº/‘Þ*mŒÎÞªõæ‘éôvò•ôüTC §“›Þ’—µ¤yZH;l áépÏ.%5Ú‡³_7õ|(,Å×eûeOc4áÉWմމ\¿BH×:Hq¢ë—q9Gq÷TÌ !ð=ÒÃîè=éÎÆz<-÷#O‚Ⱦóé+&kD-Ä|ÁZã@” 4ÌtFT¿¥ ¬JìÍn:ñÇñòéùpôŒ"tjQ eVŠ`åR¼”K’8?þbä Òõ¸>ÄÛU$ž!)æ‹oìr)Ú†»úÎw¾c\wz nv÷š*;¸ûÎÚsm¾dÓty|Tˆ½¬Üwí¡} ÞÔ}`6Rå:ªŠ·çñ q£¹Ÿi,ýË׊½|¼úS®WCž>ÜT-‰pÒ”šþÝêõ~ª ³ þõ«Ö¢Nâ@¢Á*+æ±ór×8qop%FqLαÇï|Ì¡ôõ.ÍGï÷ßïòÈöò £JߎC¸rŸ–Zã¸~ÌG¡ò}Ùfrìò¯Î>œ½|¼`·YœÍ³Kå7T.˜©Ðôuó9 ó#WXUúy"l± MµÁÇ_IF â+èÚÒ vÍ!ŒŠãf²ë§r·•gBÖ%ñË"|¸Â©ùm’˜9;o¶\åð‚šóÎÝÏJö웲ÖßûÞ÷ÜæôÝ¿È8¬‘œ>„”Ãíw[œ/ŸÆ»fº ™Q¶M>RÝdj½<^~aÕî¯Þ/Ý/JןOK½ðŸÿ[BWÏ——OËTÈÃÝàÅÈ“7Š;´/6j}ëèw>øÝJøîý~*öfp¯–/ïµkh‚.ª÷µ÷ÞE×/®‹® óíËg]ÜÂçË‡Ž¬ò™9ÑlÄS"v¹åËÚ‹+á»!4êwJ¥éLšp± ¤^įßñ‚b¨_± ó]?ÁhbÅ'Rad±[/Ä-Ó§q| weß|ðmC*¼òdã‹K9_?+¸[‚ f6)ûwŽb]xFŸ=½Ùá•H­×ù|xùÀÙ­ñp–8îtw‰ÛÜß¿›\—ÕeÞ påI¡Ažd›!üñÕbe‚˜ºâêÓÊ·™$dÏK¥ÊÑÝí:÷¥¨0‹Ð kcî©S­Iîž×Y(ÁwÄ>ð~/V–'âÞx¿»§¼o_ÞT>!’m|Áùáìy®¬Éy—Üé{=ú¡^wÀ˜¼‹ÁTi$ªË|äRg6ûÂ|üP`thÇ$˜aTI'š,üä¤Å#8z¯Ë†°1G\|W_íŒë î,5 BÖ0÷²ß~»ž•î}äô]²îM©¦ªÖK£—WŸ;`âÍOÙníÚùµk/„"ó¾{OJyæzéãÇ0ìxØq: ºÉCJ‰ Cäú ø Ïdû I^žLK-ËCíî»ϵæô#Ðì[90AäZ„ˆµð:×À]ÜÃ$eÙ»ë]ÂŽ/^¶÷f?[´Õ”#oH¯sJ™¼©Ú¯ËãSк]ðhÀŸsKc¸TR½ÇôÕÑ%qØàÓËM–),¸.@kÁ¬\˵\ Øfαï ÝzR}§nóeÛd_=- ×uM­¦b©«Á½[ÑÍ•šØ‹È=åP¼¼è¬)éåã±ègZʵÆÄ?Ÿ¸ÂÀtô=Ä&ô̹0)4Ò:ÚlUDì×ËÊÞ1J<4®îŽHm©|Kþñ5TÍl9ˆ˜ Œ¥²8æ¹R¬”®=×n³®ßM|Ï]ã-vãTˆ–~x%¼³vX@íÐÛž£÷f«°ƒ>kñ;¯¾Þì²F­…À{£çîåÃKÕ7&;Y:A%‚Ú¡µkˆ[¡Ï97x?uÚ²!‚Cwcõ™±¥À„ó–Ê׃?ý†›@<³œ¢Ó·=)'ëÆ±“³n«ŽØ1ˆòÝÈɶI±“Jß{Æ&Ý V…³±-m~_+÷f/;Ðeóz¤IŠ&Z‹· MM¾‘ð!hî÷fëûO øRL‹˜ÈOÀbâ¤|íhm,Ë&·”%œÊäœlw«;Ôæk §r' q4·‰XjÙé öUʹ»—VC¯ïZiß|ºœ—OOÙ»¥ “êåGàþ~|qïí¤QY”G³7­«è  °Ev\r·`È”óOøu=Ë•¨ÇʧôTÐ2Ó0žÍCA“UÅã¦ì:UAûÐv@¯×}O¥ànmµ¶$N¤í!˜ÐÉöFVîPLDzÀµñnQñ†ì‡×bŸL.ùFuÕ¥ˆC&%f^b&”õCÉ6O‡gJ ²-ùÅ8ì(¨51(Pì‹ö÷¿ÿ}ÿúuwnü&ã8ýrï») 5(›¤ó2å6ÉBx1Z§ßãDcqdÛ’k Æ·ô¬¸WR¬Å *wï“õd$è­-H!w†Ó÷âJ‘µ‘q-™ éдYwFW”Èq†¬pö_F¾•/[ 'ÖÌö°Íç匹·šq})ôZ/Uƒëä^^p‚| õ†¤YÖRáý pdø¬Ù6 ²Ïž¾Ìt‹ôÉ8Ѽ÷Íïp{DÜþŽ ©ZhêU!|ã!¸Ì]éÈÔ0ýPâÞ÷ ï*+§8‘-˜yx8Po€×IXÁüU÷r^Z®¥f4ö³¢›ËGæþ:ÛPï2Ô†g݃‚KúÏ·¯×Ûi¢ÁFâªx­-1lø®VŸÿ†t.q((ï­â¥ätš¦-E‡¹{\„î ž•¦¢3)LWÚé#xótÀ†¼„^>ÌÕ²!bœ!&Yáõs@mò*‘:;DÞÔöß¿PƒßÜëøLÓW~ÓxäUífIaL –‡KPìÓÏu­©¸ouNYw4·ª#;#?… œ¦Kκg÷y#±¤i<†£Ðl^÷–Í`Êb|çî’ã»{ 8²¾Õ¸–Æó‘°ïQ–˜†ñbdh­DÀÒ‡‡D0ðÑbZ6ÏUëÿйth|*æðÊsd] GàI4“½¹›ìÙÒNê—B~sàØ‰Ï å}… æ¦³dÑø¤0]éÈ.©.›¾îAKLVG»à6w©ì ¯Û*ï£Â^œ §Ó¦t쉙Ž*)0^RÈtºÀõŠÏ£5@¸eBãñ,²i‰°àªíÿQ{ºr1N!ņ°yNÜlÒ;YƒZN '¢Ö è0—¶¥×ˆ›]Œœmt:úb†Ô·[˜ÚºÔÂÒ]oH—‡§&w:.65l³8R)Äç]›n2LƒaÚ<‹¯¤©€µ¬ÝƒzÿAÄŸÈ‚ª,•°‹ÿƒü vr´Üáß%¯³Z*¬e)œhÀ.8²Añ-Xy ›¯aa ßòœ6š“ê{ qÿ,Šì kT!/UGñ){âìÌŠ«-à”t#°³°¿@• ù®a (;g­f•¨%>ë†-ŽSí©°QÎÁR¡ªì,µ*%f. 9qnª¦ES‹ç‹ 4J?„<í±ñæ‰ ¯Ê âöUAICF¶°8‚ë8,J¤Âo);ƒ‹ù,³G8&õÅ•\ý^^Ü¥ ¬x{HäÑàþ#ÚËt*Q‘u:ãjºÝÅCXÌtRhŒ) Lêiàº×(ýÅk— Ž Zv-$ò¸%×ÛRŠ·§ Þ¥xK;/¨=¤¿OÃɶ¬D¼T8~ÁI[ð„gðRt"›ŽY||Ø%.H­Â&,>::øNüdÆo›wÃû¿’ÄÀžÖÓM†°QÄÉEH„ßAŒ/`½%"4kL©ÕóKiaÉÆ9Ù;7áÄSÛæëŽ¶€~ûZ#%ùã(0)&¨‘8ÚÈeéFˆüÎ_Èr@îÙKûÞm5@Añê77¤cMQaA^J_-¤‰ë/€³hÖòm0²¯(-ÏS¸«¯rc‡ó;}UÛŽ Žë‹YႺl`q¸¥ ƒ·ŒÐ’ìp´âwzC7V-ó@©¶’n1¼=¤ØÝ*g¸ Éòáâx ,YAH‚'­XùRÓ‰À)Fˆ³Zä\œˆåÊ+?f¾-HuóUsã%øä‰#·G©× ®Û?FZCBXÒ8çn²æÐ)C†¸[ñÏò‰„ã0  ‰ŒPIM Ø<Â,f 8–R|d¾%/f nओÅiAöØÏËsÓSU;„ÔbNÓòí$e¯›îdoyjõcˆ‚²kf™ oçqIJ Ç’¡ÙXG<üì•$ò]tU JM|"ºW(@Þ•N!‚xÁšÅ-‹ùÄùªR–bc®ït•X†#Çøú» Io¦ ô“úh‚nµ|§OP̘VqCH%ÈŸëT»¥*—(X q“6Òz¡…,+`µ«Á„Z ³R‚ö‚Œ ›ÎörË<²lL>² ¼TÔÇ+hû‰]¯–ÊžpËÎWhœâ úT. aµÛ‚§ØžOÁæ©W1‘Ua2Ëí"µž‚Ètàwéµ;AÊ<ñv‡Ð$xú˜‚ø‹‡ Õnä'åéŠ_ÞÚh_ŽW\=Ð(eâ;ù˜^¿¯ªÂ¤R.ÅŸ-Ò‰–WØ~Jµ“ÕŽ™æ©¼=ãÀ³³°±O…'Ž=š ­ÍžµiV«êܹӉ#L¿B1ZL1þÔ쯡ֱ{oÂã9°±@º8kfhq» ¬™Xùho·ÿ[ðT®µ.۬Ⲟå~’"A!‹°v8 ^ßp X°8š³†Çgå‘×%%UñU…thK) † §®Wˆ—cåÄ-á'ç&^®Þ ,ÑÊ*,[¼´^,Ûˆéð!R!–ñUn )ÎËî+V©Óã¤p‚ P¹F½µíÎ*)ûä›*Îhk¾¦‘ã"\¯ ¼_§£^ã|Ø@á)¬pÌ®G |Ë‘ ø“¦v´-Ç Y#A½qN©‘ÇyÚKUQËp¢U®vÝÅÙJâÌË"W^@pÙªà 3üõÞo]ŒØ)Þ%—#Wå|Aµ•_[y¹R[¹»lL¸‰éˆ‡ÀSk‰ƒÌ”ê¡Fág-¼TµNB'‘²˜[b6Û™*N–ïÑ©*PÜ X)n¿ÞÙóDñª¯²²‹}ó-·mq`¶T˜¥æSq© F@äSKdSZÆÌ?ÕVø$5NÇil×bM•ï–­]A32æ^kÊg ^I3Xê{©¼ÜûÈR×C Å€Tfy¾þõPË‘ã#Ç/§e^‰ TAÈf°L-œ_ JIÈÄ!¥FXUAµ)×+üœ!Íßâ!§¯oÇ gÓ,ز쓯ÑuMðøÒ VÜ gY{¨°*ÙçÞ"T.fÈùñ«‚£ ¤%A6Z Á¬‡ì‰sf‹k­öåe¿R y·pwqÙÍS¯†Ig9 “ÀK© ßQ¤“ýI)F ª!!ÈT™MIÙpÞr KYFà™%Kª†-q¢5Fñô#Ķ,زœ!§r%ó8m"®ª«"nÎ ¶L 9SOPœ‚”˜Áù -ßùih*µ™VŠ–ê«$=õ„,c_ïJZž1DÕ&KÈêiÜR<+[Z ð–¥, ücÿDÖZŠY" \Õö'Y|–¬¶ìÆ@Ë6¼%N›*æ“z½J±×>ÑÆÊ×@Ürí-ÅŒBê-yËìŒoGILœ4ºD¨Ðñ…œ:~àªäTžÎ™2‹vââ–)çcn*àYh‰³ò)ThyN;N‚–• ’%u=¬ÊT,Wp'¯l8‰ñC0!IÅßLxY4xá§ïy¯|šé”Uè½O'åÔRX )F(».[€ƒ@ÙrÌR!쉿i«âYL¾8š Ô…H„¦5õÅ[j#î°âÏSd–4'È'UP6‘¯¯Žu̧ŽJ²Î 'žG«¶À0kª¤÷äD¢wIo|µeù†$Ë ÄMrg·ˆ8¾î1ùŽýñ:ôVþp7•Škƒ:œ"Kª¬¸l>Ý8ÑV/NØ A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs%%IR$ð;IDATH u”ÙR*1Eñâˆ8þÿgé/¨UŽà¬w5«ÙÒ‡Ôöp’4 onnþþþƒûp8$pY$NQ@¹¯°¸²ØG•©;mVüŒû{†W éïïï(üjœH—õÄ}VYAše¥5(åâEë•G™nŒKg†”.Uúq0¨Ä´'°„hŠõªJF)uwW¤º{¥¥„{˜²ê’®€B„JrŠ}‰m)k”¬ºë·_vùû0ç[3èƒp*ÏQì–‡®¤[ Ô-wФV*¡msPo?Ó’€ÄÎÎÎh4¢ÝŒ° (~ÿ[®çççÆgùSšL&???´Þßß-ªÖÒ+éñx<›Í@£«"ŸŸŸX€—I°»»{uu…èáá!¬Æsõ¦kÚ]ùÞÞÞùùùb±x}}ýøøØ_®§§'ýæó9–<©B€HOOOïïïKobÓ΀üää„ã#Íøˆ’B;::bÒ—— ŽÁññ1;ø‹‹ º°Éõ û7%á‘æ–¸Ž i„S"]HêÓéôîî{ðœ’:,íÙÁ´”\(8ánô»¼¼¤(š3¡{vv“˱îå ŽNtU§Œ¸»"ïIƒ©ooo‘Cš'a‡Ï#àXLM…^ëëë‹[âô>0¾5 €už h¼$4DyXÞÇÇ’‹F…4oÃÈ Áóøoooà™†Iùvl ðA³CF-œ¸Sl8—ãÇŽ¢®°¸%ºÌ‹:· Þ AÕ †×××$ôÀ1Ë[¢‡.Šø¡Î—îh>&Æ´ ÀÅÌÆ©5[f?)ƬÀÄ”{º èvTƒŽJЬ~ u‰é&X3ˆ:A8)Zq‡Ï*+%Œ–©€îUˆÔÈLš€ºÆ*¸·ŸiD@#6-ƒÈ•A²léט€#`…L¬GÉLE˜iÅŠGû§OÎ÷'H*Q·În@+ ªbkv€Xé…¬eRa¦çrI$´ëNºá‘ÓS—4Z ,šWº*¸wo`'4*ÆòËz$h±ÎêëLË`lÛ* RuÞŠI@ÑÝ®äT âAšø?ñ‰ÇâK9¾IEND®B`‚is32oÙרØ××…Ø×ي؀ר××€Ø×‚Ø×ØØ××…Ø×Ø×רƒ×ØØ×ÙÙÚ€Û×€Ù×רØ×ÝàÝâáÝÜØääÜÖ€× ØãÛæãÝØØâãâØ€×%Ø××âååÛáâãäàááØ×ØÜÝáàáåÝäãâäàÛØ×ØÚÛØÙÛÚÙÛØ€×ØרØ×רØ×Ø××…Øרר×ׂØ×Ø×Ø×Ø×€Ø€× ØØ×ØØÙØ×ØØ×€Ø×€Ø€×ÙרØ××…Ø×ي؀ר××€Ø×‚Ø×ØØ××…Ø×Ø×רƒ×ØØ×ÙÙÚ€Û×€Ù×רØ×ÝàÝâáÝÜØääÜÖ€× ØãÛæãÝØØâãâØ€×%Ø××âååÛáâãäàááØ×ØÜÝáàáåÝäãâäàÛØ×ØÚÛØÙÛÚÙÛØ€×ØרØ×רØ×Ø××…Øרר×ׂØ×Ø×Ø×Ø×€Ø€× ØØ×ØØÙØ×ØØ×€Ø×€Ø€×ÙרØ××…Ø×ي؀ר××€Ø×‚Ø×ØØ××…Ø×Ø×רƒ×ØØ×ÙÙÚ€Û×€Ù×רØ×ÝàÝâáÝÜØääÜÖ€× ØãÛæãÝØØâãâØ€×%Ø××âååÛáâãäàááØ×ØÜÝáàáåÝäãâäàÛØ×ØÚÛØÙÛÚÙÛØ€×ØרØ×רØ×Ø××…Øרר×ׂØ×Ø×Ø×Ø×€Ø€× ØØ×ØØÙØ×ØØ×€Ø×€Ø€×s8mkÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿic146/‰PNG  IHDR{C­ AiCCPICC ProfileH –wTSهϽ7½Ð" %ôz Ò;HQ‰I€P†„&vDF)VdTÀG‡"cE ƒ‚b× òPÆÁQDEåÝŒk ï­5óÞšýÇYßÙç·×Ùgï}׺Pü‚ÂtX€4¡XîëÁ\ËÄ÷XÀáffGøDÔü½=™™¨HƳöî.€d»Û,¿P&sÖÿ‘"7C$ EÕ6<~&å”S³Å2ÿÊô•)2†12¡ ¢¬"ãįlö§æ+»É˜—&ä¡Yμ4žŒ»PÞš%ᣌ¡\˜%àg£|e½TIšå÷(ÓÓøœL0™_Ìç&¡l‰2Eî‰ò”Ä9¼r‹ù9hžx¦g䊉Ib¦טiåèÈfúñ³Sùb1+”ÃMáˆxLÏô´ Ž0€¯o–E%Ym™h‘í­ííYÖæhù¿Ùß~Sý=ÈzûUñ&ìÏžAŒžYßlì¬/½ö$Z›³¾•U´m@åá¬Oï ò´Þœó†l^’Äâ ' ‹ììlsŸk.+è7ûŸ‚oÊ¿†9÷™ËîûV;¦?#I3eE妧¦KDÌÌ —Ïdý÷ÿãÀ9iÍÉÃ,œŸÀñ…èUQè” „‰h»…Ø A1ØvƒjpÔzÐN‚6p\WÀ p €G@ †ÁK0Þi‚ð¢Aª¤™BÖZyCAP8ÅC‰’@ùÐ&¨*ƒª¡CP=ô#tº]ƒú Ð 4ý}„˜Óa ض€Ù°;GÂËàDxœÀÛáJ¸>·Âáð,…_“@ÈÑFXñDBX$!k‘"¤©Eš¤¹H‘q䇡a˜Æã‡YŒábVaÖbJ0Õ˜c˜VLæ6f3ù‚¥bÕ±¦X'¬?v 6›-ÄV``[°—±Øaì;ÇÀâp~¸\2n5®·׌»€ëà á&ñx¼*Þï‚Ásðb|!¾ ߯¿' Zk‚!– $l$Tçý„Â4Q¨Ot"†yÄ\b)±ŽØA¼I&N“I†$R$)™´TIj"]&=&½!“É:dGrY@^O®$Ÿ _%’?P”(&OJEBÙN9J¹@y@yC¥R ¨nÔXª˜ºZO½D}J}/G“3—ó—ãÉ­“«‘k•ë—{%O”×—w—_.Ÿ'_!Jþ¦ü¸QÁ@ÁS£°V¡Fá´Â=…IEš¢•bˆbšb‰bƒâ5ÅQ%¼’’·O©@é°Ò%¥!BÓ¥yÒ¸´M´:ÚeÚ0G7¤ûÓ“éÅôè½ô e%e[å(ååå³ÊRÂ0`ø3R¥Œ“Œ»Œó4æ¹ÏãÏÛ6¯i^ÿ¼)•ù*n*|•"•f••ªLUoÕÕªmªOÔ0j&jajÙjûÕ.«Ï§ÏwžÏ_4ÿäü‡ê°º‰z¸újõÃê=ꓚ¾U—4Æ5šnšÉšåšç4Ç´hZ µZåZçµ^0•™îÌTf%³‹9¡­®í§-Ñ>¤Ý«=­c¨³Xg£N³Î]’.[7A·\·SwBOK/X/_¯Qï¡>QŸ­Ÿ¤¿G¿[ÊÀÐ Ú`‹A›Á¨¡Š¡¿aža£ác#ª‘«Ñ*£Z£;Æ8c¶qŠñ>ã[&°‰I’IÉMSØÔÞT`ºÏ´Ï kæh&4«5»Ç¢°ÜYY¬FÖ 9Ã<È|£y›ù+ =‹X‹Ý_,í,S-ë,Y)YXm´ê°úÃÚÄšk]c}džjãc³Î¦Ýæµ­©-ßv¿í};š]°Ý»N»Ïöö"û&û1=‡x‡½÷Øtv(»„}Õëèá¸ÎñŒã'{'±ÓI§ßYÎ)ΠΣ ðÔ-rÑqá¸r‘.d.Œ_xp¡ÔUÛ•ãZëúÌM×çvÄmÄÝØ=Ùý¸û+K‘G‹Ç”§“çÏ ^ˆ—¯W‘W¯·’÷bïjï§>:>‰>>¾v¾«}/øaýývúÝó×ðçú×ûO8¬ è ¤FV> 2 uÃÁÁ»‚/Ò_$\ÔBüCv…< 5 ]ús.,4¬&ìy¸Ux~xw-bEDCÄ»HÈÒÈG‹KwFÉGÅEÕGME{E—EK—X,Y³äFŒZŒ ¦={$vr©÷ÒÝK‡ãìâ ãî.3\–³ìÚrµå©ËÏ®_ÁYq*ßÿ‰©åL®ô_¹wåד»‡û’çÆ+çñ]øeü‘—„²„ÑD—Ä]‰cI®IIãOAµàu²_òä©””£)3©Ñ©Íi„´ø´ÓB%aа+]3='½/Ã4£0CºÊiÕîU¢@Ñ‘L(sYf»˜ŽþLõHŒ$›%ƒY ³j²ÞgGeŸÊQÌæôäšänËÉóÉû~5f5wug¾vþ†üÁ5îk­…Ö®\Û¹Nw]Áºáõ¾ëm mHÙðËFËeßnŠÞÔQ Q°¾`h³ïæÆB¹BQá½-Î[lÅllíÝf³­jÛ—"^ÑõbËâŠâO%Ü’ëßY}WùÝÌö„í½¥ö¥ûwàvwÜÝéºóX™bY^ÙЮà]­åÌò¢ò·»Wì¾Va[q`id´2¨²½J¯jGÕ§ê¤êšæ½ê{·íÚÇÛ׿ßmÓÅ>¼È÷Pk­AmÅaÜá¬ÃÏë¢êº¿g_DíHñ‘ÏG…G¥ÇÂuÕ;Ô×7¨7”6’ƱãqÇoýàõC{«éP3£¹ø8!9ñâÇøïž <ÙyŠ}ªé'ýŸö¶ÐZŠZ¡ÖÜÖ‰¶¤6i{L{ßé€ÓÎ-?›ÿ|ôŒö™š³ÊgKϑΜ›9Ÿw~òBÆ…ñ‹‰‡:Wt>º´äÒ®°®ÞË—¯^ñ¹r©Û½ûüU—«g®9];}}½í†ýÖ»ž–_ì~iéµïm½ép³ý–ã­Ž¾}çú]û/Þöº}åŽÿ‹úî.¾{ÿ^Ü=é}ÞýÑ©^?Ìz8ýhýcìã¢' O*žª?­ýÕø×f©½ôì ×`ϳˆg†¸C/ÿ•ù¯OÃÏ©Ï+F´FêG­GÏŒùŒÝz±ôÅðËŒ—Óã…¿)þ¶÷•Ñ«Ÿ~wû½gbÉÄðkÑë™?JÞ¨¾9úÖömçdèäÓwi獵ŠÞ«¾?öý¡ûcôÇ‘éìOøO•Ÿ?w| üòx&mfæß÷„óû2:Y~ pHYs%%IR$ð@IDATxlÝi–$H‘¬Q Š2Ö~Y ÅÐÐ×ìó²“ÝúCU3÷ˆL’~çýòoûÛ/~ñ‹ÿûß¿üå/õ«_ý÷¿ÿ Èân ûÛßþç?ÿ¡Dþë_ÿ¢üöí #W¥™ P ãùýú׿†€ÞŽ•è3O°öÕB/`› í€ñcÒ;þóŸÿT5ÔþFàa ë‡‘-Ù¥à6”[&¡¼=³ª½ªA–³ ×î¨*e¼•œ½3CG vǦ[Ï]ê(•8÷Ñ$+× zí€,j\©ªcL ÇQr‘cëØó†ó›ßðD:®ãhÛ®ßÝ15"U¶HG&í|ŠöDÚ¤v-HíKn¦®íƒG: CU3LÆ àœLßµ$+³êeâ¶­—Ø Ù¬ø4Z ɇ@»Ø2¥]‡F‹ªè„5ÎM2ÛÚe-¢M05–ñ|ǘƸŽFk\¯£ð†Ì‰ öņɸ\ùÝËLUŒh±)·e_•>q³’åv‡Ÿ_3•ââMé÷@G‚–y•ðLº7 _;€ª®6!n1 Àé½@@æÇª ‚1¬jg…Ùw¯‘O 2zÑbÓ«Râ™´•eÆ´ ¾é³Â|ûãÿè¬mÏ Ó!sÇÓ±® ØfÉ0gÕžIà˜Y©*ÏüÉ”Î*÷¥ZS¨æ@ šH9PÕ›b² Ì–ŒÔ×Û,¤vᨔƑ>C¤cád=.þ¢$&Î37< ³]—# ÆO*YF Ó/ܾ¯™È‚€L£4x¸Üí"Ç;RVŒh"’X{2Œ³L‚àX #¬±}´÷Åv$›IÓ3™’¿¡Ú1ùD7jÏõZž`z-YE:Ò ÇJ['¾ zžª‘øÆ då˜[UbVJ$·rƒâ3!x9U⪠Av›ŽÀ' Ìgšv#&CîhDÎÈ>Š×TÛ'òé>ˆÆél ¥Z…jA“›jËÛ9Þ8ʺ(ë%&€e‚ßýîwÝ“ÏÌ1JÞb5¦Oœ±£’‹`±Fd{šØ7¢6b-@KR¾u4ð·üÑ9Ó¹ÔÖ5<„**Ðô›—¬ûàÍ»h#ÏŒ{gYvünKíª"=@ÙÜœ [©ö>§w®v½ÄVm«~_ÔÞ\]›Ò jɰc¯S»Ò¶m+ÇÏ–tÈGªx«dYà›Sn«J–ÙurÀ×ë˜mÀ”ˆóÙÂÀ]á¼äJ˜r#U/vUŸ¢Ýj—› àE‹½ë!÷Ñ)%–gûî€í<Ã>ÐŽªíßz² ­!Â2LÌ6Òuúr:j¯JÎÙ Z€7JÌ [[ƈM‡­˜mkØÙ‘¡K9FÆwĈvÀltUG‘?+$æp1Ù®há ´- qŒÜ±Ì¹ÅrÓˆï^µÈk§$ÀÈ‚UU‚ Ūm¨”U;ãµÇßëL–9 ‹`€Žp›'öQjǤAê…¼^áÑ´#³-ïØ•™®À|$g’[ÕYiž³Æ[<ï©Z‰Rä‰ ”×H@/ÆPŽ$ŽÂ}÷²ÝÄÞ_{b7ýüûéA_ÿêm˜2]áØGåè³ôÓTÍ%=œÌBª•èôȺ²R4&*!}„þTG¶¨Òw¸çᘠ2˜FÀÝY—’c\]2™¬¥œC<}ë9Âß‘O&ùcà€µ”c'«# ¸ÉLz$L#¼™¿õoÿFh¡T%s„;7Ú1Ƴ\ËÏÏ¡Fžà©äÙým%ãÈï¨Ò±qDáËiùvkÊFäs¶ª ˆ›‚¬òG*A†tÜ"e&ñtÁª‘°H Ë&ƯÄОH&²£L k\¶†M%@¨ŠJUsЋ§iº«á1"[>@+‘Õå˜Æ± ©7çeJ{ŠL¯T;M¼«!ùà ›eD‹u¬ËJÓz½éôlU•oV:{ÜßZx2¤µy¢ƒ:Ö/Ïmձʭö™;ŠÚÍÅ Œ¬“gw‡û^©*å Ð3obÙz4{FOÓût”90lJCåz«ÖEP#€?ßìÔeŸ(/¡B´à×ô4u‘‚©ÈM#FÉQ ´#¦j2Ù醹ebP<½T+  KôqVÕ¢kÏGc>Lˆå€ªc;×âH)r2¤€s”0eÇ1À”6ý®IÌÓVW~ ¥Öë^Fø‚Ìíôjl+Êz]pW#î¹€ÖèúéõÚG¯0‚§Ýhü&¥GÒȰêzÛ _ ‰Ñ”Û æ +eUSŒîÕ–iî&ê-ÑÕ`-¹©"¹9ÂñßÉ+9â1½<óYP’õ˜ÉV¥ï.-ði{¾6š t¯+Á­¤Š Û\©¨Å&@ãòTÅÐ;Î9q‚ªí†ÙP¼^L¤ ‘x†pÇrŒ•FÒ¿»£ËX² ÛŠfLûcŽõ XhÃFÐ ½³#lbŸ™#²vo^Ë=×.R{0Y³Ê]¤…×¢ÄG$îÈaƒ`¥º‘8ž~ƒ%<@/ˆßì8ÿi,ÓSLÌ$L¦ÆDN©”!°†*Û45*‰¬ðÈ#e é¡È2ìFßþô§?Q8(Pˆ¾tññ\T ¦øBµÆXѱ-ëUÒÂP´Ÿ-¢#Ð52¼MŸ¿—ñwTÕ%'¨±eÚ#ªnÈöÿ1R5pd"š¸Ñ<1€ v ÀîâK¯7˜”¢oIJY YÉ;†»Úð Ú¤•rPu„YÕhy$,”jïmkÁ22p¤ÏƒÇ7%«öÌmŒ– ʹ£/‡¶ê—B/V;ì)(󼓇.T'SåàÈ¿eˆ}-S)OÊÄHšÌsp¬Ú‡• ™`#²ŠÏ­ÝšÛnx½ýy+åð*ù Ç×Þ2²£èHóò³µLwHi¢¨Å^ž@&Ã^)¬,ý™w÷TáFà˜­–x$¥F™!2ed¦_[U•êr„wlú¬ðÀô 0W4ˆ‰¨ +]î³Rþe›Tê˜î:€ª‰Ü$œV-” ŠßÚíYÖŸ¾O£+güô“ÁýÒ hOS( ØƨΤ)=/¥cžÍ˜+k)'è³ 9¿§ÌÎ1]Í{йo™@ÖÓàëåÞ*­Õº}r –k禯’=^´+£“åß8Ìû%&vS­D\/Cân.;â@iP¶4H&ú~7W)Ô’[†”9´°^&0~ƒôŠôJíIk¨:Š+ü`2U†øž³ äŸÛmý|Ÿðïõ•´ )áVª7ÏøZ(iTLß ÔNY‹j%GXìêÍßò€Hæ0!ւ瓃L#”ì¹ãn7+]ýk!&Y%ÎJB ŸÍ¢ÁÈéßQŸ¿¾`½¹”@Ÿ#M ÏLLÁJ”ôJŽHÏø74úùh¡i‡®¯êHÏ$Ã|ÒÈœÏMî ÷{s¥Õ¶Âóq¬Q&˜>)U ^Ë»¾AJâ¶~þlXÕPX•X»ã½â¶žŸ¸4d†f•'}ƒº;’@8&›˜Ò¿ãÕÕׯҔî’[&]m;˜â}8ÓD6WÆû×¢½R ÅÌ¢Ág.‹m¸)-€Xï@]¬úŸ£ðÙÎʈ0Ð;øæDRjgkUÙ·ý,q_Œ›å5ž©_QÂä#kטUY5M²ãõõ¥5šø¼ˆ6¡f]ë7¦‘­¥Š‡+ù„êÅpWº‹}þü¤É O&›… u1™9Q—vÁð=2i=V)iL dˆ$6.Ÿôu%F J- kiC2]<#O ¹²­db¡*Tiñ­ÁDɱ×@I™!,6"&O¯„^6ÂDǪݷ¹Züxà훡„¬H&2Œç“§c?¢È÷^ êF§ÿë»#ƒÏŒLÌñ‚C·Y#šÛDOéH¬xG%—UͰ7qäF@¶û`R&.cð0«‚mÎÞ³öª°Yà c”ÑÈPuÿ0¥š-RUÆ´†v]ªýÀYA†ï;S‹#L-¦–¦`z YÕŽiÌÊÖQ(q–íæ–µç3­ñmB º”–m žªùw„×H›>? 5EI‘9\#^³ضU«j‡ék1«ÑHACÓªñ0}b)“ŹÒYô®×Ú‘ýkdzSÞß1+@ Èyï‰Wm ‰Y#CX´ €¡LS ¦)4×'èx.S3ë@"Žš©r;9ôj~øãKh¬—R4C&U‡Y1ñ€ —„ÛÇ58*éd 1íÀǪ~¨v]"Y ,O U 7¶Ú1²Ç»æz“ÉÅ+Öâh1&z[,^æ_4…À1Õ”2^t4ºF@Ð;n laá½aGY£Ç±XãâiŒPr ¨&pC& ZÉnðHíªŽ Ò˜!@É_õØÝc>6‰äS»’~“:Šxù;P»ì:9Ëû£¨ýuI£) ž?g½}4‘ [@Iý^æÐqš~øCŸU¼ÜÑ&ní€ {|]‚سªÂ©‹²€¤´+´ = ž‰RžÓ'Ž_©·uzûv™ž‰¡ñ!6s·;? ±q€ë`ò‡7H©õ˜ûz4BF֏ɸhW­dCw¬%Aû¿£¹-²Ý&%+ÁÊE˜s»TG½ÄdÜzxUx ^ÎPµ}0-PÆk©KÎÁtþ.å(¿ƒè‹ÈáŬ€°¹ª›Ûe=à ÏhCm¯¿#²ÀççD9‘\'uX‰©—‚¹gŠÇ U8´ÙÞ%+9@\/ñRíS'˜ƒjbdÓ•<%,×kÙ±­4Ö…Ž2F„m(Ìb’ùðúÌ"«6Q»Ðå°`º|†ÝW†u)qP’µ¤d8RâÉШšX¯AÝCÙCþšOý¤I6*̇¾¹Àöo4A&ãjâ »5^˜¥EôEoç¬û+GÊä<2ŸÖ««*OG<ãÏfÀtdÞ—f~®}¿2OÎ0ܽ<žÕo8&s¢äŒ!CÎ?ÿ|ˆU+-ŽyÔ,&oUÁ“Æ‘FcŸZãð¹Í„LÉ‘[×☠´0P•Ý϶‰òÌñû œG¡ª(kÌ háãûõßKÈú3¨JÜ,†ñ§c£µäÜJ<@¬šxJV­ ˆFḩR{FŽ»zL¡ËV2[¼lk¡.8ÍÞPIœUî;¶?O dåÈÖ±Ä(µC½r»9t”{¥œëí¹`dVæblÞJ²¨7ó ϯÑ9ùʬmÙÑ€6 ßf8ö:J˜‚§cN‰ïH¯ÔPžU½,€ÇÀªÍµ½ÆºäJõĦÓÔYÕ³ÜÎŽ431#¶‘‰ rp×É?YU¨ `þ@ú Mq}Ùï‚€Rš|ÁF8¶¿¼ç"Ægˆ7TK¹^$[¿Îö+Cs7¢jVÍÒKlÃ&úBûž¸šÞ†òT*4Z4dÄH€8ÆÄ)á U™'†‘J|€L<ûóÀ¯0$dæÄ°l `˜¨jIœ9 ¨*s“Û3>3h0BcW ÕÃç‰ÙÎÛ„Fx^Ù‡Ò&)[»lŸ€Fbaœ£ÆöéÅ]ŠyËÈ”ý&RЬ¥åÙ‡G‘³¡¬é7î ¾±vbœý|> šÕ½ð4}©àö$ãàȶª#}sÛy•’ÕE#æ KuûàU½˜lDÙÜ45–{CXµ×fÕÅ•êÍOŒ‡¹)5 Ù?*8šë¾Õœeúvާq$Ȫ’ÌSД‚2£ ØP¶¶c·±Ìíü¶õõÄÚ,iדÙ)§õÎîÚx½JÛ@µÛ`cðZR¬L‘1Ë\—j÷·•*Mžx¸8{|]£5ˆ…ªcG-É`À½ªžæ¯ÿ1@êíA´á­‘ƒR^§ÏçѸº¸ ÷"Èí©Zo›¨ö»8…ñ¹Oñ˜ÞÐå?íhLàM4#?i5ö)`ÞO¼’^$OGíõÂùàúé'¼­àp”9d[{WkŸ÷:p?ö½°n2åp2QÉq;8¶­*íHo%œUueµ‰]­ÍU;$îFŽm·yJ%J È{.þ4­!ãÛan«ÖŽï/àü3¯Ö“F¼Ca$10= ¸u½²#ÃZdLÕ”Ýh{¶a¯M)ÈÒ(y ¿ŽUE_€Ö hJímÒãÄÇèj¨\t;]C`"ÌÖ,G ˆ? }}ÍêUÍ Ô 86Ž óÓùÕ“˜Àz3eí¦"O©% ¥=ã|h’Uê5ø´› +¬…•oBú®?Mn²®;ö|7ðy¦ì˜à,}jûëÊsþÏ@•ûלÂÑÓÀåj*˜©ª Ó¤ºâ])CU½HÓUƒ¬”ìì~K‹ а½ò“kÏ £E;€WÍ_ËøÐÔ˜,[âcz¿:òœ]ßUw;U%4ȺëâÓhGw´@©WnÄžÀ´ŒªÏ/«dzEŸ‹j% óŽ}0Že†Hs}â}ˆa>uñiÉÖ¸+>$+ hô[ ‹ä$ÎDÄ$ãÌÎ$gËPòlÐx µSÊí¢Jª¦wT’É0ÉêMÆHSo-M”U5Z©›¾»QŠmÂD4¥’Ü”ŽˆE»Ã9ôp@isë•[ ed$¥ÜQ/œÿ̳jô>¦æ&~õm[U [íòl•𨇵%;&Þ÷°ö¶Ê¤eÑÕ10Ö”Ùª¦·P ¦Mµ`Z[.èø/îóñ92l<%Ÿ!,¶¼¹@¡ªW8^ùçgÐcîï7ÞÊ·1M²y"›ÔîHÓ‘L`ÄÞa-ñ²Æ>n¥Z€í3=†Œ#¾ýáÐ eÁ Úcu=qz¾þû`.ñZÖ•Y¥ô}1kdÏ6¾kpkÑlËó¬¥Aº^ŸVµswi¢Ü‘CÖ^Ö¥ÔJ±[DÔ’Çöiíñ)UÅv«ŠálGèÇæH¯Ø1Ï~×ÛÒu6…?L¿ ûçõx¥ª=¸ÆÂ¬ø[ÿüµT‰‰‰ ¢™Œ›U›²×@6TÖK¬$Läyý>ß®.ØD;ÔÛJÄ€ ·ºfž-A¶ød …1´ë¥Á÷ǬTV¢„Ó´ÀªdU9¦ÅdGŸH³ÖEoVâJ-9Ð24JùØ!1^ªdô.³ÍdØJÛ0F~ƒ¸‰@nA<ÀÎÐ2Âܪý’j<9¬r½HGß4QIÎg™!·Ä2}]&få˜@¶6 >#°üÉ I ³Ê0ì0‰ÏîX~«ÃmÒt]ù; þªÃŽ2 ÐW®Õühql™î˜ÉJÙ®J 6ˆ`þ­Á)‹^ûµª[ä@½2Ãx˜ÉY¿‚„ÆrwŒ¡ P:Òû½´·£*SŽ ¦‰Y%FUTÒ.bÈ‚•h0ÿZé;VÒä äCcó°U˜Ä‘¾‰ `n¾[]ÏʇŠ×Òk¡$ ö{·Ë?™*R;=™q[‰ ÿJíßh|¶õjäÉÄ8Ga1Î÷6Ÿ_ ée>d޲Ÿœ°ŒìÈŸŒ¸K±j¥ªJ¯UžUµ‹4˜n§}•X&#è.µ¼>ôí³LIŸ³ér·€U[²Þ-L ´8ÆsËŸ³R¤j¶>RîÖ“À§½Tç©¥À àÕ; †ƒµ4ˆþuC 2áv+BcS´g¢=g AG™I#z7XèÍÆ“í»‡©%[ÊIJ/že4Ælœ–—äÖçůŠ);fŽa"'Ëü圕`@éûYsäIÜt%WÔž‹%òìq#±I)Tú¼2©QvìMˆ]#è9 |Ï8úÃ;gG2™²‰1×hÊÌ;šb™3æòé5ªÆhG} ôÐbް¨KNlzÃ$’¬=Õ4°Ñsë¡”2b>Â_Τ¬Ô¸ ÂtßœU‹lU·C#jìbÈ]Žbþpâªd˜Ä…åB»8ÿ#°Ú±|þ ‰Ù¯¶]˜uëêã/9C¹^Õ>3¿J0rJ8Cn‘I]€ä~жq€X)LÏ_¯}µÌ™†À8šôÚ›…w„ªê9LŸ‰£˜ 7TÎ$ËÙˆŽr¶v¦§lɲp ÕLµ¸uÊÁ™Ä‡Ë-Дr-°®6”{.æuaT{ð^@n“­‘¥€é¤·’È0^N™‰\µŽ™Ø°’Ü-4¦"e¸c9g_G>5’‰V’ë)à€ªÆZ" ®W51OâÖSª ÈV ¦–î•Fî›o7¸q”‰¹±õPÍE XÖ%h´tÍù]Fu½øöÑ~&ÝÅä¦tMâÚ7%Ya¼,^-x V"(æÜt )°…k!NDòì«î7C¯‘@Þ5×µµ¹e(¿úuÝúIüÅ–4â;½#Ò,A¦¥œUY)ÃCün7%Po&ŽÇ÷¶;LäÓçë˜2ÐÎï}ñïnª˜ø”C6‹a#S|…Úd#Î?€8==Í.@ZUI8¾2˜u¼a‚@\íGÜÅü÷_¤_7>æ>ã3ï¹?o´Ã¬Sâýåë£þ?Ÿ“^-Öh󔌻}þË,†C²­G€?ß§!¨„4cg|¨6‹Æ¸ÁZHGØ‹wÁ óÔ(RÝ"qf)!e¤ŒX‰lùädMoO¤c]@GbQ£ÌjÙ§¤A¶U²¦+å\c¶½ Ù¶%£mè7†m&gƒ'xj1:޲vb¡·pÌ-¦j;w%£Éj©D tAX˜‚ÑN6³.`£3!˜ç`Dtl\½åœ•t™`€uåŸX•U9†Œ¾}0Ž!ƒ{RX4Ë ]J…–ø)4ð”µÏ ´ F0ô…òüÔ¾Èkðù\–Ñ%ZXKFžôÝM‹#^æÐëÁF«ò¡ìFŽgƒû%‰ï8[²4².&™×‚ÌÖ’ýqÔÒ&•(ÉìPcÙ,Ë7+–ŽºÜŽ^W·sz¹GØ»M¼£5ÖÒ«j ï8ÇlíF¦dÛÚVÒ5gø³"ŠH³œ?çýÊîªu–™Òô“Ð$²|Ù‰µ´JÐg[µ…Šõâ… /ØPLä•|>r˜€£ç†²–Ü-#meFÆcD÷ÂG<@/'6“Ff‚Zp7=û‡_@ß-´dµF|÷U"s#%L-ªÝ¯1“Š#hg¯éH˜g-dù÷×Gz™&·L0E|žMLò,SB•F4—OG%L¶p‚e|_Α6!kFáç“yŸªÂÝ” © ¨4`DU<zYŒŒqÜÎ02Êø êõµ^„)«b´×h+U‘ é.ªÓ˜Ä].Ú¡œ>+¹‹7®% z^OWbV™èÚ>Uk™mSè1{½0f½]3e‚öÇ×"ä9†IßðÜð™oA]xÎ"ã™'ÀJhWíŽJðœß4Ë)‰Ú$L¬DVÎIÐ7ì´}½j³ÓSf¸¡’e.g~=Îô˜ôJ9s‹ß&•ÖX†³RUG •¶ ÙÄpƒ0~™|þ4ˆ•×í|>EŽ™6`[–>!Çõò­Ý±¤GïoÜ0zUËÉ–mO`ôpwÈ æ£t7:ŸF—ßeµ(Y¦^<™£¡0Rh©‹ž§à@6 ¤I– Œáã=nƒò,·ÌÚí÷Är ÀiddX hsÑ8‚5w-u!û#æ`™™8æP»ÛåÀX8*ˬð­äÈJø@%¶<)åæÚ6[>¢FLx3p´¡‘> ÃÍQpƈîxãçÿ m¢zmNÙB;¬ P­Ú½´ÔHƒ@™A¾½ñ)™É`íZàH9Ü2JÂ\¤h “œe¼wà–!½.šÛtœc¶*i˜|*Å»ˆÈSVr”¹s€‹LìÛ‹lg>py»9úÙñ2&ÍÕˆwLüñ½>}ÕúKêD½-Ó†ñÚ­ÊÊJ†º»A2AkΡ…5rCZFÊ˵l[ }-­—y-ªZddî¨+2ÃÞ¹%e2üŽ@-¯lûÌ-ý3¹óÏÜd4n+˜~×Ç Làíš­?•¯ÉϺգl@9Ç>¤>•Þ‚8#•Rß¹&ÁªøÀ~ïsÓB#àZr‹ »RÎ4|Þqã‘™”sÞg¯‹‰o¤h”ì£+OYpÃ4»Ò7ØÎÄ¢‰dýL¦ÇˆLÚÒL‰ç®¤ zÙ‘†9œ¡#²o[Q&îW*™c>Ä–ÇÇëVI57dÕô šFÕVŽ4¬ C ?V#5†e˜ÛJ0†ƒFÎAh!P€ÈD nDšœã—•öyI¬EId¨ ã ÍŸçø–ÄŸ¶ ª7¹ÍÕµ'[ –³ÒØ[%“1{[ q+©k¤Á Œì(êâg2 fWf"”äcôõß&À Ó°íxµ'ÕÞPÙbýè5Nny@kוßÂ=K2ßz¤oìî^ 2çÞ TbÛ1-¼¡€ £é§€r]ÄÝq‹)!e]” •0"fǵ(e wå—Ìv-™ì:kï"ô‰—U»]þŽAëíëRr,˜²à`aé1Ú12²R]ñôŽxJy×qħÁ‡kT*Ã@˜¦kbDÕx áZòׂ„¼só½½ôI4ªôÌ{  «ªÐtL–!YïÙ>a™^ì¸/¤)ø&îv½ÿ·¿þõ¯sÑiŒ ÊÐ&‹~•÷˜FNFc->Ž21 î>石)«*µJÛ Ó+mÐg€,(†s˜9AäþIÖöÛŸæ}kÇÊMö(½ ”­Už¸*“Ìødu¥ÇôÉe’@ ËnÄY¿qÉXÁë"Ð(jÄ÷ hh@µ® aÕÞÊ©TW{héeJã”Ö…¬—2çô²ØDX#A$q³(U7šLI ESrX#M· C’H‘†'¬1’À§7N‹zª¹Ñ)×ÂÙ>ªÊ|ÂúZ(…’®¶’,Z²+¤ŒÑKœƒ™¾Pµ3ÆQUo`sUálS:æ3LÐ~z%þ9OŒŒÇäÙ,sñíз·f™¼+÷¯%s³FKV jI|nùœÎ«¤ÁDj쑬4²Æ>tG%‘•¼Ã%>7Â8ò©‘É 9àÓäLt‰ö)ûí—²··2À±YŽ»;«vHI£„¡‘µÓÏd½ÑV2+úZàÏï¸ÎIÍðjÔ¢R¿ý{™ÒøcsƒÌqc`Lnþ6ÍÊê„‘U‘µJ<=+Y¤'ëEðºŠwVŸÁ˜¶Í“Ö˜¹Œ—m¥Ô>Ì÷ ¥!htÿ=€a•ƒcA‰ÑÛMSF(Á€§»ëœkúgý%<›neÇÓ·< 0æ»/}4èË]‹ŒÑ˜g2Ln2ÒÂHGJYÕªvsƒU[8s¹^YÔ›ùÓPúMGHÎþ¨î k¤ÌŽZð˜ýuéeô*uï’]Ÿ¸Œ´aá£|òDÎyŒ*ÞLÃÄ0Ʀqì+áXcVUµ×Å!,ç6Œ O4W.ÜÑõï]Ï'Ò”w%¤cŒv‚MW k·pÕ Ð{Ïf%fÕn×õãœÀA£ lP<ŒœÆ÷+5ƒOÙ 9«r†½3&7¤Ð› ÏJ2IÖû¹¹É4šÒ3äŸ ¾h±eÇôª•dƒZ#¦c‘Ä1}+LÇô]mÇFë ñ€ÞAJ>ëަs&˜IúvVjÃ7âü¡§a“ôXîuWŠÉ=SXÞ1ÎDð=h†Í²ÅôpW{ÄÞoœ–ñÉѪÈr2¸gŠ$Û¬”d]8ež{Yb?3•¸ <+² ËH‹u™€Åû…ÔK/ãÉ2„r›7‚‰Ø'…´Y‘•Æ‚2Þq%LË´¼&X©*FTµ@]ýì„#iLñùöç“RÕ&ªZ5¦e í:H˜á0—ïLJÓ#µSfBÙò€¹‘l…#’î+DÌMÜúçÃ"Ãs~/’òåa±ë kŒD;`FšebÇ®ýª>_ %Æ}+à]œËHÊvîÓw¬äŽ“åߘôª}p™ô•FIKŸÂ†’ü“aLǘÞhY‹’ˆqɾ<ÎÆ kñ«¦é “™¢”ËÄ;’¹‚¬÷ü¥©cœÃVÇ÷"  ÞÈÜñ2zŽZÎÖÏ¢4"’¸ @Z±R£×ncWê‰M§¿fŸ8¥œAÓVÈMð]8 q&p·ÃÄódÓó¡41A¶éU+½Ñ[{â4{ÌÉ”†Ç<×…dÞ·¤µíæ}Þ‰[ Aó4N0ܧÞ,zd³d¶áôœd£azûÄDÊ-£OV ÈXUêî9ó0J²›Êï°önwqÎü™8Â@Ëh±›ÜÎ@#G3OÓUß^UѶªMü¢Ù’Y饇¹ ¸}0®6±4Ž"‡Lb`úJí@S°d¥ºdb—»o¥zGf»v OÜVóÔ¢·v²ð›»,Yn•ìÖC© GÙPæ%}®o;§Á>ôb@oíñ•(þ²ö×àŒy–[£*¥#óÍ}}苪Y­$³"ÈP)L€qÔu¾>Áôªñ@湑٧GSrT•YVrL£ÔV²jJYøZb˜Èm3ïç¨.2nç äÜUQŽa¤GÚ6£jûÑ«öç¼]a‘!€iRâ¬òa¢—`â~ß!r`ã˜Ð;r~§geU-JMÉ$Ð÷Œ¦vJ|ƒ´xÍMl%2LW°Xže£3!`èX¯'JàðÌ•,@™Xnt ›Ò¬€ÞÚm‚Ú)Y1Ü,Gä¾pz‚¦0©#´w»”­'ƒ;VBúLåÐŽg¸?X9âÀ½h–,ð˜2m[[ûÕž•ð-–'±MÚ³RíU=#[½5RÒ4 Ä71 ”FÕh7Å3—›B¼ë7(>r&J-C¯]pù¨êrl´*€ÂQ¤X U €Ù‡ëˆäÀ³˜ÆJ”¹!‹ÜdÇzaÊÞ¹éÒw¶ êͳéÖË\‰†! n¥h:  w$ƒïë¤QW p+ù^¥Ç·øùš¥Ìéû&(Åä HÁvú4Èd]-qέŠ1-€ÇÔ¸vOÏîW±‰¢äÜ sËÓ/%<’!ÜdDÏ¿jC»Ûx$ÍZ ãŒ×¸µ¼AŸÏ•Ž(µL­_†IS;(›MÓàf\á¹Ð0àõ!fB¼AÈ4~Y(%î& +!ÃùÇ–^ÓÇ芩=·`µ§ìF¾¦YU"Úynóv„*±€‰ùŒ±'²/·ÿ)ÕD>=^ -õb„#M½åJ°x×vÔ‹™ C½­!ûˆ‰Yi‰Uû“IµeôÎÒQ—Äs@È3ãëO;z8sÀ±ÄŽðæ:š"6b]ŠX 0N@ïI X©éûÚÄ«êÊmGdØ'Þ“6…‰wP¢ïa}|]Ä #UÔ^CzY °«Í§H£%=ϰ͵leïƒL@oíŽ}"4JJ¶Ž@ ¤£F‘˜~²p%†.ë"d%G¾Îë>ŸUῼržßž À¨^íí"½CÏR©+ôªÚ3Ï“ è{ÕHÉÙ‘C&2R®KžØõSÊuÉÄ)µàûÜ‘ÖhçöWá-@ +2L»Å무F7mϦ½U×l²Àè%¶˜R#0ª|äÈ®IŒL~µÑõ¿¾ÂÔý,Lµå«§adJU’+ÁdLÆA^KJnxzâÚ%W2]5Y]3Te¥Z %“^²ßh£‘3Ñîh–Ù&‰ß)”ŽÂSì ¬êÂŽÖhD¼}øÇÃÀ˜~ÑÔȶͻxþ²czû‚mbxUJ·ÎM¢¡Ý5rèý9“Õ‚Êôµ8&«ä(”œ.NÀSx.Œ}&Sê:H¥ÞÀŸÞ{ññ>ZrCbÊd‚³q¦«:ú3À8÷üúíœ,+ž#Âx-e$ç[üùgžŒ¹Wjû7´È0€Ñ2ÞQtGU7ˈªåJ0@Ö1óô0s¼ìˆô\ôüåÈnT L&ø×Hæç"Û†¦Læ²J³"€E»•;6ÎD»j¶0ÏõæO?s²4€`âî‡H }ª¯‰QÕâƒp4(}&ŽéSWom‚Žrƒ,OÖ2+!«}ôHÁÙ¶ù¯±£^Œj_žÚ#e|þûa©×d½2bYV¶Úd;×â(2—™8–oå”DO‡é ü‘ðÁ(/™ŽHÐÉ]xâ&ÙLËòõK?“rnº¬=^æ`%Ý¢k‡ªkjæ–{&ükÛ1禘ۈZˆ7— 7‚-¯:gUú2q›7B.Tñdspt‘î²öz“Á½†^±Æ/ËóŸ”dª–é­‘>Õ÷¯¢¹1!¶¼*¦˜‰ÞJ™^L7TI/%«ôCáF¶ŠÉ°¡)Y)•1F¨ŠvÀ§\ÐO1çZ€”¢•d¤”mt,kÄ4™#,3 ;ê¥ñ’º„Û!ïœ_ùÃFtdžh´$Ö¨ªE8jl+@¨MÄu# ªd¥˜ñª»;ÿ9SÖHYW#à!~$ 7’! 8ÈZœ56ް³ Ôž™£*qvÔWÅ_×Ïß Ö…Tò’ ʶª,ðbKb´8ΰqó€­‡Q•[/“Ä3 $nO³hô¦l.Y_“ÑË}÷Ìê"mNܶxÊ6ñÍIéZcÀPÁÁhpÓËZRõ ?©å7… ÃD¹%k×åøóQªÛ*ݧ›Ô€Á‹ûõ>?˜ý]›cÆ0IJÙ^•­ë%PâÓÓTJŸ lcÁŸØ‘F4`™Û¾+œ¯‡4d¢v†Ú¯ýù˜Ï@›¨æÖ&ló¤„e¿8Ü®K%–÷Œn1Ù±Fèõ,œ­”¡£Ý0)kQêosº`±Æp#`¥d ¤à‰ôÊa€ãض­Ñ\›#³›–B £‹L6½x‘¥‹÷à@ŸZãx’Í&–Û'[z>k=Aï†É°ÆÛVŽ1·)ŽY™²Pªj ‹§ª£ëTÒ·‰O­¡ùSª‘!‹ªpΔ"eÙ‘m¶*«+<Ûš[ÐÔd²Æ•Ú|ÇÀÚc2/Ï$ó>#%úÜšN&Þfµ¡ZhÆê’»ZwLFP/Û–¬Å‘øÎm³ðÅî¢ÔÚ2ÿrÈÇ1C˜²@2qÁ#·Àö ´¤*%¦.Çk%U ²Ñ]„žXôíuÈDìñ5joí°¬/2$Ы¤1ÁF$0EK éؽ΅…²Ì4  7JŠgæ}d«#6™.>ª·ã|;UýY×_¬0Ý`Õ Yí¶¶X<}¿;Z ICPd£$0íÜ2H@»œ@öjö!F²ÒBßSÂŽ€"£±@VLU]µË9ÐÔë^  °A4MÙŽp#h`ŒÈsí@ŒnV2-½øc”ŽÅ—‰*ÇJŽ·x­Rz™lŸM¼®^ÕhÕ–ÌDn(P;ÐßR6±Ü†m’>gŒ¨ú.Fc[ÐÐ#_Ït%n7ä–Ï¡#ÈÃн|Ê®Ð玤—É|)›ã)1ĪzÉz–ôÈ@ä¦ ™hÇ×å¦^¦©¥7Ä#ù´CÓ1Ú•(ÓcÑÄŽÃ7Ž¡OaOŠïk£%%Ï j½ñ½ñµ°åi1ãÞÞd2¾mUéá.ÎÖ&|朒ð¼€Èÿ½²ªÆFÀ‚†ù|xÆhW•MZ %Aü”{. ±‰”ɪ®ö€í¶¡~Kàë¥ln ;ÒËÂJ} ÄÅd ÅOC¯‘ Pʧg›+WÊø½¸cβÐõíÇd­G®\VŽâ>»6¸Ÿ‡Ãt¤$c"êªT{Ë寚Un²@jÄ{e>ô1U•0HLcnUY©Üªs a¸‰€è›aÖëP»ª×Ä ÅvDíxVÈ‚O%$‡‘µ# }=>¿5ÄãýrÉDVšI2$·¦ïÏÔ÷ÊdÂE&ÛXåÜ—¦ 1B‰LÔÆk8P»—ÔÕ{êj\-xÌß·¼& J‚Ù¦ea\%¸RëåϤß ¶¶UY‹(óÑN¦ß±& ÃàÄŽ¢vf« §çVï|ò| uÕòj²õÔÞVæC“¬Þ} ñôø2†>‡öQê¾[Œf/Ù]"O|Xî"+Ø#k¯!\$ƒ[ƒF``ÂQn(€WíR)zËÄÈÄa ÔX¦Çø(ëÍ<7¼Fþ”@‘ “Foh`™~%‚^;ó"ŒïH¼5®ü ð”a‰ÀÓÌdC-‰Ì?<†m£1BË4Ý¢qJø9Ì矸lº ~í¨ibúÓ¯Whª^¾ýjذIJ ¦‘é)ûsž@»RÀ•ÞqæRjÉ&&@ÇÚaAV‰¡•W’óyy }SòÙ?pqÐBœ'LIO,"(Å“ásÙJô”`¤qªn9=÷{“ ,>³˜èjÕí€éˆùnC½VjÏ Ð”µ‚˜,0íÜß\”ºE‚2+üíþ|âõj×’†U4²AÉÊ|ðŽ¢é@þÚJƒ” þã›N@‰|Í‘ 7 H~³’/­ª)­¡ÊÁ±}:’!åz ¢Ôn¤¯VJŒ*z%|¬ªÔzJý:Fæ¼¥/’ÉÈ4ºèŒ*,wüŽ$¸Ú#º,2Yû´³œÿ ªk‚¦DºxÓU)ó„…RKZž#Oï)ü+æÊÏ›h—=e¸×³pÊ= .$Jm-†Çä 7çZ’¸ÝLAR¶Œ£è‚zç™^#¾A‰Û™ °€ˆôàdmÒzY‘E6…Þe>üi`@6T#œhOšÄ4ÜÎåÚ…B¿£mÌ࢓&Ád@›ôÎ ãèK™ ß…ñi§ÄkÁ$&hãÖð^RÌ#­*›ˆahg žgXVBÒ‡›²¡9ôR4m›Ü}(T=—Ƶh¦0=`g£1ôd½+UL-J45*a:ÆÌo7&‘­· "1z‘if[µôâá ‚mNc:,ÛßkÔÕ¥t‰6|j‰/}~¤úé'¸¹€ b²¯“žÒ&诗@( ¼#@¶Mð|nÇgÐE_»ÌM¸`&òµ«’åS©ŒÊ^xƒú}„á©·Yª}XZZC¦t}—Œ3¨Yªô&4|x¬(ñ=† žL#C½ð2L#ŒNÙªøÌ½2Ì„@I61ÍJ×é,–-@¯J†qµ§” Œ®$;–ɬW#‡øÖ Êdª¹mÕý¹¨‹ e+mÕ6o+²¾Àdº`|&ô@³dØÐªmUUKŸNÊ.ÛÄíY#ÿs]ŽM$àæØŽø&b|`nºðidSÚn„,øPÊŸ¿nLÝ~D]©oÛÙªJ î&k¡Q²–ªŽjˆáÄm³ê Uws ø•Á 雡½‡ÈÎÕÜôÂ2 ÐdN/º‘ªMxv¤TêÓŠ\#"–…#þp X¸ÝÆlç6%òls£÷™hÌù£$Ú 뚀`ëøûßÿ^®Œ‘•æ°Uðíœþ¸ß«w Y¨² Úw£J_‰s±2zÕ=/R¦‘íC *ÇËHYWb¸c¹q—û¼?qW8s#£É¡9Òd ˆUkÇPÖÞÚ}Cjlʬ›‚TÕÞÅ•$Û ºvÙ4­Q»’^ß±–©d O ¼OŠ• LúÐ'#µÃ)+á‘ô2¬ÄM&γ$€o=½E]aÕ™`(Ó 1rVa·kâŽß^Ê^;M?t–tTêÖÌÛ-’>ÿxžnAFîŽiÃÄé÷sM¦ÊSèJÐíÞãzö²Õ¬QU»^ï(ÕÒ•chˆ•áJŽâô]IäIƒq‘ÄûÕqøóÿ)<‹–ð^°H§¿=d=•pÖd+ÉŽ­ëêYU^¦É!k)`-¶êhošg÷$`‚$ð W©­‘ª~BêTÃx ÜÅ=D+)ÛSÃd0ÆQÌ$F¤F¼p¤ohǪ2^Kƒ`-p³UÅ„ëͼŒYÿûß;Ê.â‰âÓƒg…wY¤ K)[o8s çx%í²@.(14`bãjÄ7ˆ,׈œÞQ‹hœ§CöÉF6™§[äÏäö}úªd›OÎ2 ©kß(&õ~'KŒlõö5ð¼}ÙâeJÑDÇîâŸlžé[£Ï‚È¡^šéÛ0Ûz×¥%¨QÞÜWÀÌmþ€HÌ„'% \sÎŽpÇw }Ÿ8ÆåÌë…ªp&ʘÒw)¦Íãk4¨O¡GЕùîè(ˆe@#5ÊÛ9É;Êœ5 %½&®äh ì›'L,˜ûê"ÉÚ0}U¬rVUZ#A¶Há˜Oz†¾MT׈騚?FU$¶RG2Ìd­—æüAgžƒ+ÉŒôÈšeí´ÁªõcúøëÚ`%ÑÈ|všJòôhÚ{,Ø’ZZ )´{ tϪ2¥»øG:@Ésv¤obÎŽ½2«øî¥DР÷šª…j¶[ &О2™¼ŒÑeD†-f-ª™OÙ”ÈÆér¬‹·þMfíUûÊ6±5´ Už%Ž©‹y»%– Žýö'ÎAÉeg8[dKRNcÛ™ÔÞ>9¨x“9C¸ª)Ϫõ¦Ñëh¢™Œwìû¦Ë/Â8M`dk;2ô¹«Âºšˆ­"ñ¦T@IDAT:ŸôU'¦|ù¬$à2+Ö®·œs¸µgNŸó²®÷jñéeúÖÀ·›cšxY;¥5`ßGGOíA0^{ òd‚G6 ŽlmíŽëÊ#”Ìò{LÕQh‡«úüï{Å™‰qu•#»×ç+¸›¨µœ‘€1ŒòZ3£šx€ªÞÛôù~LÌ\8Òÿ_ÿm™¦qëͳ¥çÀ§ ®K†};ýàS²ê³Ç `Ž4vÙ/SžÙj$óK YÎ?Ú°WÕå#Iƒo–#\;½c ÿðõc„^švÃ;zûQçF¶5 m eŽpsá×G£R|ä3ûëKïXKbþ"muY(r“iwÍNJÙ1¸õ·|¥ ¥Qb®]ΙJ4h´È?=†ƒFW ®„€Sª’‰ŽøÂ—J V’U;r†1¨+}SŽÑ—Þ¬ÈvŽ¿õóÛ>x¸‹(‰F7®.dšwVÊr+Ñô#àîÚûNj©«-³‰Ž ê.°@öç´§h9¾}:Ê|D›Ð86¢• ÷ñ%Cö%ïö$`b‚HǵӇ«¦G6Wî¦<˜Õ× æÄ‚IÓë L ÓJªLà󇉕(1Çú~j©¶ÃºÚÄÃjéªå¶žo7-ªÍ’•`E†GN_{å¹}þŸeq +d”iÃ` àî8MXîžýO.”d 9øOŸ¬Œazn¢eñÞÅ“ÉLTóWÊÓ±A¾£¬iRn.†&=@Ã0qÇÜ`Ê3õkÿ>*ûè¥W•ûœˆ L-Ä5P:v‘3!0}äaGVJß±ËÆozSd¡„§0F‹à÷&6WûIxŒ‰é±˜1½6 ð=Tþµä¦ªÅ@µR/@`L¤\KÏBá • [†²8WÌ¡ßeŽ4Ä·òIÖ`^KÛàf1<5¬7gŒ£j§Ì.-Õ–©Frx±c¤LÉ(ó±1Þè!=hú-ðºÁ]¶µó!vìµÙòäƒíÙzý%ÃwÀqŸ”)dJf¥½¿ômOXI&nG]¡—²Jp¤jJ<2d½Ž¢Ñ‘ŽFpC²ºÂŸ'îH–ƒö.ÂÙQVõUQ:6ãîMÁG< KÕtËèíãhœ^‘[-ñdñH ,:6Ô8ú€¿§ÎÓÂF{jš¢7áÖ3")‘‚•T‘¢)ÛVéËæ«Ž™Ð#…ñè4L0É\Ä÷ÓÕM²[À€PÍ&ŽArètÌ ÉM騔”a‘9ã1Ú“šLF’µdÙ½0B£L“LÔÂø0+-Ý Ví8Y—%è³?+%­‘­eš®$`á2o½ùDPÂYÉLuY€9Æ"1U•ÈôVêúX‘U9ûhzœÜ`¤^¼^ž¡ªQøe!ë•)åÌ· FØPfR•’€mïy…Ÿw0 I¶»À­Ô½êÕâ(EâÖ#f^)>ÕÛq.¢EÆH2Gså«ÝÚÜTÓlP†²’Ƕa†|rhØ-”ª:`äžC#6QI/[w$ÛzpÁ§YÌc4Zˆk!JZäðåÎ PÂL` ¼êœÙÒ´à¨1g½ Â#kœ3#0Þ vYW†ªø¬È”ĬðUÉÒÛŠ€ÒqÏâ(,I ø”»Ü!)uq€¯ýùJ¤¤ùª^úÚ[#F~ûË_þâ?4ÄŽB›@6X$Æ'ޝ îÜ %J¡êˆßþŽQš8.wÑåz+5îJ>?*ø÷'¶È")­×ÿ2Ü¥-8Ò{VØn­×Qoš-V»ãJïç±ÅšÕ 9ýªF Á•hàB•ÆïI+‘ñP:n\&ÈßÜ\ÌÖÎ!O¹ãü·*>Ÿ1Žô"ž [Dú­aóªx@cCÛ£%²ßÈ|0^ÃôJ²˜ǘ¦·'†[8Û¬0“ ´•‡ -–yúrä ¹p£ô3'S”aWãûcI67L¬Š¬ø-„å¬ÒDj ÞÓ,Xn“øu1qÍ—¤D.zz|ÊÜ`a„cŒ2SRv‘=HdGJǖ̹ÞÚ«´?RaœÒK:âcrH€ìX#+±›ë Û¹^Ù±o#@€¡éHßá>»¦Èu©jÔÞ#8.®K©éÙv;8%ÖHÖS;&n\¹‰óÔ |zŸ6]U¾•ûƒr¬œÂø#Hp±D‘ckm‰H£·p,ü\ém¤üÝ ¹Qê ÿ/[w°%‰m#kx¡•ßTDz^_ÚùÌGþ™Ñti°€ƒ@dfU·dϽ=¬+FÈ”ñidžø>ª&n\ ÌßQI{—Ï$¥Œ$ÀسM¶°*^œmnT´@‹©ä¬Z©[7}í4m›-G $†Ï)tÁói2¡Z/Áv»M‡'@ Ìc6WÕÅ}ÑgµYc¸ÙÐ2òþú¼%™p¦Ñ"v…6WuYY/MËô#çˆÐ 8¶6=œrW¸>ú†e²f%ÃØ¡¡ñyƳí§ÚuüÍ ™Rã4jI±IžY%n[U@¼×G:"w í?|Ò0$ƒ ²V² ÷¿ë‘iTs¸ö²£.AÓÃ6ýt~‘&ÜQÖ^L¹ç‹$c%%œ¯ê“Îà.’¿BCÙ€¤ ”³ê;Ã!%ÁÇgj:¯´FÕqƋϷ¤J¯+™/6“F5:ê"`ˆqÓ±.G%Î@ճ͵ª®J`ܱ¸‘^¶7@&é#×[×9ÂÌ·=F°:<ß(¸ö3^™ˆuà6ž”o2ÊîÖ*Žø^SI¯¨kÀqU]» ÿ¶Ìjz<|Æ?Â$±¬*zw%G/e?@S(ÁÚÛD©¥¹r‘¼GÄ8Žïh Ÿ"ÿ&bRÊ&Ê6¬Ý,GbGíŽÞySúlA™[Xv +QÖÛ½EûÐ$cÂŽ"Cz«öYT…ÈT-ã ýø<¯Á'±u)|Ä’‰®vö¸‚¬Z²Î¬db¤AØ<127üFÀºRrPíùøYÕç¬ Ë"çÖsäðY_!ƒ*Q¶g-›åhD$1ž¸Ua¼A6Âq_’÷vÄÚ[O—£jnŽøÖC²¢ªpáHÐÿúÖt&Ÿ¦7+ÃéõfޱŒF뀣–‰1â׃ŸÎ‰)›ÕÚY‘­}bÓ·hÀ„Ãv¸Åóà¶üþSZ&‘Uk‡”€Ï“¿Z“OãRGöÊi„ÈÇwÏ'‡¾™ë¥aèã ×HC ;"cã)Å”ª4IJ)d)1‚L6ÂhX#=ãl `šÛz>¸ö$ÞÂz3!>Ê,dQ?^p sá ÓØ^†-JÊJ­%Ç4’ÀëÔ˜Æyb2”]Rö|zÇ5b`? Óc(ɶ3sC;·'CdïKßÄô¾ß­-×.ŒH¦%€Áç@¶¡€Pø圑JklÄ2ÞsQNíF;h†7"‡ íñ)íÙ¬–lŸE—âÉmC7WWn»é½Ùç+•3ÏÌ=¬*eSxƯ÷ìíÆ<ÆJÇÜ"›T™kw,ÇËÚ“…ÉbÈðŒ¨ Çc…£ †C ¾®²|nÓ¯OydÿO‘‰¨±ÉDUŸB÷åŸP¥w¼Â8F¦÷-Å sÖøø¬ÝOªõÈJæµÅ5¥kÊô1)gÒ±5cÇË edsã[fØ\½ÍÊóÞE»‹( <1àãvÈ 1yà)R; ’‰L³Žé÷Ó§¬QÖ¨ªÅ×nh½Žý®ãƒ×%˜L†‡1>@ 9ô ‡mÕá3Ôγœ³¬*ÇsS×ø\*F•aJâ.èØèügÔüú/™Ö¯ÆNn˰cýÆ``zïÆa%>°»µ(œ mrÛ8²Ó|­”ÈÒ$Pu´ ’°F`M„‰U›K© î@v5-˜­¨v¯púrŒ{ì·$À§½Í²ƒÑö‰A6Α žaUGÑ&U;v_9†þ©_ɱ nÿ—­Ê|G˜?¾)Íu$h"~„wMƒü.‹‘ùxŠôeHA£‹pôÕo²¡x9 @ *]ϳ%-Ó‘ °xJXu?l˜‚ Cfœèõr˜-¾[̳}¼<†˜UƒrsÔ«¥õ2§õÊ•€ ¥¤ah4Ò½*ýØgæd[£•8®¬eß$s³` μ/Žoù¾í9§É*,Û*}ÎŽ5:î:-€iù.¢Z{WhD·  ´y Cyd%æt ]÷¦ogžÀd<áœ]P½öÿÌ— Te³Z€¶¹¼Æ42>R¦o›ønEÉM‰l@G%·hzUŒ£jþ Z•2¬J–Ïç+bEýýá‹. êó¸ª#ëŸÀ'{MÇnuëŸßþ‘Ìw眧ÊZ"pw@¶7½irþa…d… ÀµxÁSiïâ8ÜËf.'ÖåW¡¬Ša(ÚÇûx19Ÿ¬:áJÚ]Ó«V²Ìõ;JÿpÓ,Y/1  *“ÑÔå˜JŽÜò‡1E+)ù\(¹¤iOJ¶{l ¾FŒË&è)”0wøù@‘ÙâÃÛ“™*F…£èXn7X ¡‘¦Uµ`RàU|ÇôJ˜nÑ_ÍàvÓËabÕ|Æ8ºÃñJEkÀ@ØÄ”­4™*œƒ&n:±Û©Šöˆ ®öƒ)冷ï85ÂxâÈ4Jüåº\Ù±(ñ9kÞŠÙ+Á9³ô}gúø²mœ*%¾¿&f¿eh0ˆ6Ù?+±5W/·ÄŽ}É·ù6Œ|[*™’s¹¿imC²4 ÂüÛ°¥ÖÐÕ4½€–ºò[£# ¦7Ç´3²ºxJ† ŒˆçƒJÍå#`ž­—?­™wX#üù'ÜØÔ>?'ý¨´zYՅڳ؊¥VÄtlžå¬¸R€X 2 €LfP¥Áˆ)•ˆg®Ô£l%ULŸÙmý´sÈ™€ ŒqÙF;òt”{GXT•·»zªJ¶-Ò)ÚÓ’]2$½‡Mo¨ÏÎÖþ™hl %a%@i+!õ Ûp‚Lh€r>µ`ø4Ì#¸™›ƒªèa%˜‰»¸—\IK‘Ü#$v0¢@)'ÄŸù{5ǘz³’é+Ù Ö¸Ræ<•à}Ä)T×›²§ø ?_W㈑N™ œIÝC¶+䀪ÐÛ¶¡L¦é"·ï<¬—¯ÑGZˆ) z¥å˜ aJXèÚ‰2¼ïžÒ+f5[íÝIëíŒ Ó„«¾#`Lä°ìÈJh—1€ “5®jpS¼Œ_¸É”jqÔbF2<\{iš˜ƒêíøõSß1Ù}ù$Ónt—)ýÔ Œ®îÂAÔh÷«›Äs;˜L©µe‚z¹¿º:t·÷|u:²PÚmCcƒJUYëM9MÛÈx¯+†[ã”0ñ4Œ}d7ÁDRv‡d‘dVÁ:]‡¬‹? ÏЈ®Ùn•ì ==@#MÓ&œÓÈ5²ª[¯êˆïMT ÎÉðŽïÏfU¯åù˜Ó…#¬EîÑì™X‰ ‰íFÖ±¬h1¸Fßp½Ï•™$nPç¶¡ªm^&ÐUUŽ"‰E¥íP•LÕª2FÆ´‰é]!MǪSý!Šñ™ÐcÌuGsy:F’ÁdŽ}ÈZY൴0¦MÖHt$`õVÛa©j$CX4«)1p‹ýxÕɲmh»aXù´CJdÁJ;¼{ÅÔò–ÛG&è"M™Ì±wHSFæŸ8‹µŒÜëaØnÞr]»ïº0ªí÷nŽ¢®rkp¦‘«]HàëÑûëBÊx-ôŽÛ¤*^»ÍUÍÄ$k·xíïJÈø~0a]]--»¦Œk.¦íæ(†•òL«2ŸÕµ|~÷)»°I ÅDÜ™ 'ki™Lp¯7 EÔâΫjÁkqU¹_mH€¦ueØMä~€)+QòÄ3‘™`ZÒ&“a`]‰‘¢é@»™Ò¸x¸¹<3Ï_&=´£vGzùÌý‡ªÞ~³Ô(ã9wÔÒ×®Þ²–Üd¯á¨EÉ- ÕØ51í<«ñîFÆGI{ªv†ñhD¸ sÐëØ;Ó0±­#%þØÝ6¹)€,ì¶ß’™çPWWã ïˆñ@%æ@ïÖæ²Y»¹œbäæ&‹Ñ¾))™«vÔu.ð|¦>…îE™˜!±.Y©q[µvš–˜Ãø¤Fí ÂÛ0gGo¨”¬Ñd"}k8¶^ ”[OÉnïb÷Å€¥œ§‰¬èå[üõD€÷cè"@Ǧ4S“p£ibZÙ8k4«¡“éñ•´tG£Ä™&«v˜a½4c`$ÿ6)#Eþr]¬ r5âü3ÁÔÕ,úø¾Ä"·^ƽˆ1‘° Ï¡KÕhUÊŽò~äñ¬ä×ÒñÞà|ý`-Žp{Χ.Y H ³²ð痋ˤ+×@וگ6Ç.϶¢·kÀÚñ°e2 M²ºLIÓWA‰ž8~»:Ò ËT¢Œ|^|ã8«Âºð޲£À‹Äx-ŽþÁûºW%{é(÷ŽºØ: |Gþ€£ÿu9žÀà¡ðºe»µx„Ú;ÊVB’åTr¤TupŒ¼'j:¦ 3¨éJFÉJÚÛŸ›,rÈÜÄþ1™ ^Æ÷—&Ÿoʵ¨Z£mÓ+½ŸN7â ð–!­GÜz» J%kh·O Æ,AŒ'Ã01,÷uÍŒ¡¨Ê6¼_mZbØÂôö!n9'èhbA#ŒÃg%óÁtÔU íFF»WïÉ'%VÚ|½x†)Ç4‘ælðý5GÓˆZ>³ïËäÖ,U¥²Þa ×@Vݸ4¥À8`ÿ 5ø}Ö˜v@Nf–ÆJéá>Žø$sà>ß¾ÂVÄÈÞM6#¾(eCñ0¦·j³Z`2ž½¡–vhw$£÷§#òý ›ž ÉjÔÂP¦'0š ç–×ë¹)™4‚x‡¦´-gôÒ,9Ï _¯öÄLº³ª+7>ªÝÈ ‰áƒÉy9¦{1œ Á4H8Ÿ@WÓÕ˜øMÙ2à •ÛAæÐ¸Èx¤ÞžFÂg8%`í½pÇ<{zåâèÓÇ#¿VFˆî+ kˆ†µÈd B†[›yÛñ†Ò¨:"aY0÷×Ç;ç$/)·¶‰ôªÂ |ãjìµ3LÖö™àYðlg ÃV­ÊPIX&ÆG¶‰0^É,q|ÿû_¿QÏÿå#ÇùÖ@Ç–…#A wÍY‹Ÿ®Ž§á’Ž]ÉO)±Æ>‰îÓˆl9 G¸p¤é ;ZΡ)˜¬dËðx݇£Á7ÃÙQ†û•Âñ˜ö1¨…/Fç‰l.F¤¼‰•|6dyfe´ª–BàY¯öl1[2F;¦¬ª /FêU­”›*F“åI¦*ð}a¼…“Qê•“)á3‰Ç¤ ÈBIfò£„מ @4]•sÌ›­§ÅÓ١阎d¹õ?”‚sY›áa±­rK)7èv[Óª²–&&ƒóL€dÃäÇtbíÖ®”OYK÷’=Eªiw\lž€¡#“‚sÑž_ú<†³.|J#k™çÜ Yi¤L ¯Ý½òI [¯.æyØ+õ‹ó6¦ÇXÕ”ñ”< ²»ÂI˜Jøqñ™1ñÛØ q2Ræ#:ròœžC =AG2¯w†J&î˜ ~Êdí ×Qg‹Ñ2¾cû)‰¦haÒâwÈYv#™XVŸ?¢ØÝ>×;6߯ZFzr‰‡1ºlVi2L<àèãl‰žØ8Gѵ›žÉ˜|ÒäÖ\LJ¶€5¶•£j/ÎǬ½~¶¯mX‰•\4VM€4þ`{ß 4 ˜ç¿£’Íëe¸7!ÛfÒ¸ðŽ–7Qö†µØ[bY8šröø~'za?µÈ­ñjìk‰Ý2úõѽîÏ#œáª^×”-ÓÄÞzdÛ ¦Ù,ಠ-–mzSfB/j”SÆ8Ê|VbÛË+ Vüé;Âe-]„€ƒ¼7!†k'£'¨ ™@Yqß)yæPU‹Èvر ko´.ÑÄzUw‘Z8ôC—§L©  þxm~ý *‰öo ‚‘‚F»ã~­—¾LP®Ä‡RªžN FZ•¸ k‡sp$ˆl®,4Ê4UáÌ1ã}v|ús¨«äH2˜Rf"úX“1ì íƒäßLä2%¬Ê™¡`ÎPæ‰ßˆÓù|aU2O¼æ(®ühràÆ–ÌˆÈ]$€é•2s‚:¤æ¥¬MÔ£¡%Ê&ݦóRuÊôÖ>ÐG`K»m-29™/V¿›Ö¥&}WVªIÿ§í#ðm«=ÜÝ[¯­Ü%0’X/½•tå†Louám¢—¸*ÆQTjtíHVéŽu9¦ô‹Ó Ô%«"-U‘ Hã˜,«ª ©ºQ@K7âû€šB#š °JÖú[ÿüÌÃUã{|¸`b(^™¸é-6 é‘56®ö–¡OÌG5¸%û5—>Awµ¦sÓ[ðñâ 0W%k@ƒJùÀl/w”²à ;êUC =ÌDæ6Öe:†³Üˆ×ªvJ#º8æL½AiúF¼ÐÕÂF7l\Ë`”„.x#ˆ‘{">)(ù)†ãû›8Ϧ4Ž&«Zh,'¦lu+‡T-cTµ3µ8úì¶­rKF»€oßIŽefi}|ù(•åLð=ÚH&ªÖå¸Mˆ•ÒpÈD/@Ö§¶Y‘izmÚ¹½S¶L›8ªê¢ä,æ WýíÏ?ÿì@§|T7r¯¹Ìô[\i™s-Ì äv“i§­!Ës€³âF cäz÷ȦÄkï›às3Âôþ…™pä Ê`Ò)k¡Ù>xšJrû(߯Öq¿Wn«ÖÛ&J&jdgxîJòª Ub’›Þ’ÁEU9Ÿv†ÅHz±¹k¤‰Ïœ¾Äõø|UðñZr˜a÷"ØO}ÌÄó?{ÜM8xj9[$Pnt½H §ë³sœù4˜d|ëèû>ðoIü‹›Ón-ÉäîËŸLnn†ŽíFŽGêrsU…’lP¶õÒ8¶F ã8iPbz¡šG¸öJ}“Ûíü?£×YÏ>[Ú‡£\j¹W8?êÄ2R6@$ŽQµ«pÄOP»œ' êW¿é9Ðç¬WIdñ™#°®ª[`ŒÅúÆ!²h[¼À°Rm ¥ϼÑ1ޑމ1®Ð-¦q‹aíª™Ï™@FvS$·Þ¿U]9 ðã‚ô˜|2l &‘rXîõøüᨚU&µp®$óQbñd4¢.nùxOÀP……Kõΰ¿›;lëjÛ| &2ekÀz‰åJ%&´dk¡¯=}ùÊÒds£,ö&Žbs‰…)r·SJ,Sâç¨bâá¾*¶*“ÀÚÓ¯7Ã2âÚ‡3o¥ÆÉÚk‰wlÊÜRn¨c»yJS± @seØ-poBßi`@íë ËŽR/ÐDzß+YÐô[[©F MTk¬Dé.‘rU%ÇÆ½]ÈF´LÇr½ªŽðÂèĘo~ï`®)xÕ@£;²*tµd£Dœ­*€ ȹ‘€hJq.Œ’9ÞêéÔü×IJ=±—}ÿum{ãÛ@{}nÑ5Òà1’˜¦¡ Ê– Ÿ¬ûƒQ/xs ‰×’?M2ǾŽíp+Ÿo|í)ånÁÊk$k½îÒÛŠm³ª–³ÂoϬØî"ÙràY£j]]D =°›@•¾= ’1ÁÈ"f%€ß-œ8M|CûÀHJV°ÞJŽ?bãÆë¥÷·lÙ[‘!1îÇ?’fU‚¦#a< QÀýœ3⎀cãê­1½9“Á)󴣫á1{ó6Ÿƒ*™Ì™F5Ï…#ÐnpJÀˆHÉ*óæ& 1E»ßîÛŸ‘d4œkq4Žy˜<³úw/­O\/27]³ðÜdâZäÞ‡–ݨédm…Á¯+™®™Ï-cÑqÎÈ®‰l·.HŒ4«=¯ä3TÃ!o–¿mŒ¬ç”÷‰³u—6ÇgÐÂ_©ÞÈÚ›²A@¿-Y‘9   6E xâùô†ªyª*‘¹ukà1 Fv#bUÑ’Û“&6–ßý?ôQ° ¨Æ¨ýRg*7†LÜqŸo[²vŠ—›Úø™§”÷”ÊZ| ¾ñþìi„ì(›n¥.À ðSZ<ç [Ù±õ¨ï§˜¡œè« š@æo72˜¡)@wÑ¥$ã (áZÊmÒ¾®ÓË4”ÈÓtž¢ë(áa¹_°Ý9ÅG2imG%G.Û ÃSzåÖc¼v|ƒzn¤$tµ¿®yf¨š¡‰½IGÿ×<éñØ;88âµÏI/*MÃ<œ¾òÏïôÖÐÕŽ^/2=,ªê„5äÞ¤máž=Í]äóÉòQÅïãÐË3åÌ۪ƪ²¨·Y™ÀøôŒcbû3D;à+9ÆË˜ »”2q hÆÃ”}úÅ~su¯Ä•tí}0Û-28Јœ™X@ÂÚ“×1N ä€'–›RÕ @›˜¥…­ H£™Fi]s@ú üx)s£Ì'dG Ð•[k” RÕþþZ×Èœ@n“˜­Z)ÿÖ€³R d›¦Œ!†=—c zEÕdpüùÿ˜¯r€B³ñ€p ¸ß¡ X‹ºÞ–Hî“Áz›šŽiƒ”ž *ñéØP¸_÷x] Úá>QŸÆÂõæìH”Eäuú¼Nƒª2QÒ^Wæ0~™²ÑíЯ˜µä\;Lì È‘À}“”(µt‘÷:ÄJûÎÙ­ÍÉ´Ô˜ML]•ä½ 0ZDËÄWbÛkÐ0TêwbO¡ezéL¯ËošþkX%Œ F¶ØëkL£n%Œ’v—eÔ^u²Ž×EYU~[xöÙ… ËJå)Û“ln‰c—8Ì_‹ly<çö¹C>ïFÙ;sƒ[,qþñm»‰}(d…®d¾Ÿ2=Æb€–l%4¾iò‘µË+!ᘔY5%ž #ÍJïØíÒ#­— Þ‘&[LúG¯~Sz„=r> …)ã{ z£D&óð°€°M«6Ƹš0"±Ü8@£LF á4MÁŸy÷§,À?A-HVÉÆ7(²Ì¹qŽdçg¬a[‚‹‚cWrÖþ¦æg¸+©¾¡ÊAnÀJ&r¡šgß–‘ñïbÊÜLÇûD«ÊJŽ}N™3©iá¶ô­Á Þ Jw tÁ ›žžÉÁC»HÇ&jDÂUõµ(µF&í¹}ÇÐër¯ybVõ#ÇJ´MŸ¦åeÌn€IzÆ ²…¹JY0™/"É´ôA`μïïÊY²êÿÒØÅ‰ñ«Þ>¿Çñ¸£>FêJ è²~‘§,ZXV çé¸'…‘Ä•ÈÚÍ}»2¥*™…[&%²#‰1b³€Ò8ªe¥§çvL±GÑ‘#w£øµc›UK¸O32ÛN¬kJ˜Õž+ÃbÓ)¹ùæ“'eb‚ôÝè½BzÕ•à¦È€ÑždÌaäWøë»ª”X‰’Œƒìú—Ž ê)è>[ è÷Lx¡ä&ú¦ÈðŽ›¤ÔËéóT¯„‘Ä 0Æe‚OÖÑ× îªÓ#…ã6QHŒÞ¾Ÿ˜®óù¯­Ô®ìó}m0ÆÏCF:ýkG¥ÖÕ/féÑ›72Ïdw ,ˆsèX×x°{ëbB“ Þ¦4Ÿ3²Ÿy½ßÑzŽ=AnræýK§yj1ˆž =YÕrk1L WµªÑVx #™aŽÄh·dd½áÑ ™$~­0”² x×À4YµAÈöÔØb9ã+Ñ‹H-z[ÆH]e8%^hOìO,½µ«ö!zÕd)á>V2XÜŽs)-r`¤£FA©±Ï¨^o´ÒÙæûC«Å2ª½¡*–a-€jzÇöáÀlJŽÍRÓà ¿MÞúù{e¥EÊFä#·R%G-ªdÅ™@µ£hº,ƒlÃdZ4+ P dV$qG@hçFßÎ÷\£c²Ý®öYé¢ÑH/Â2“J…ÆG<̄۶u„ ¦c¶¼jJ½#°ÇlŠœ!ð:lVÓÙ´ö#ß;n“dÓðÛ”42¾U'Æ›%c'ð‘r›ˆLøÃJ™—oýÙh>ç·jçðý‹0Ì¥c¦ýnrÛdªº²†w|JSÉD¿»v‹f«DÖ6Lj¯+AbíFÇÈŽ™Û°ý×ëŽ×¾‡ÈÊ?pÐÞh¸¿&Ðà{Y¼ á#ײWRÊS©}´xJ¸M¶ùVÒkl b¼ÿÓVßW$pÌ#’F4½YG¶ªÄn¢˜AV¹ÉÃUy"åZà^ƒ€ÿ«Y/AðbmgU‹v†pƒºéad³6½^£äyÉÒw}G|½ëŠvn"FKkd² &ˆ¤1ã"ñåÄpÁÍVÅœ-CV ¦tø0?öÑ‹Ù]`$°¡À–ÏJU$ËÁD#‰áޝžFøÊébÞ‰0¾v½9`ÒÀø€‰Ä‰öœ¦£Ü2dý˜È Ç®ÖH-”;ª¶¿ÌYÐÔT%î“Õ«DãÏŒ™Ôˆ袧نUšy:âyâaWÌ¡ÆôvP™ðÇÝ2H›Pv”•܈É·sŒU1°Ðu¾Ð¹8Ã]¯UÌ0•£ª6Ç,0”ÉdªÙõ²Â ÀÉèãkD6Z§|1«¾ z ¢dñzZ£â½£\£?Ej‘»#@l‡®& ¤¬ _Iv¬/“u¯ÓóýŠtACUi¬j &L#6™€öç½È¦ÄXØ×EÃG#ÀMWž•jŸIÝ(7½@+É‘~†Ä6o gU¥Ì‰Ã޶"“xÊE tÔ•>cû86Œ Ua¤À1qD†e½+µjí­Ô -ui¤}"‘Ž|à<=#ÆQ¯[·€@nr$lœF‚>¾È2²9™y+­¤Wô°¾¢x2´‰jŒq˜ÈÚ1ÌU¡cV½ò“6LfdµðÇh)#UkD $“ÙÖªø4HGUŽŽ.få˜ùFìh4Y[5è]&çržé[ߤ0ZFʬ|(G‹é…½¾qH2>‰3¬TW-&½Üe«rPª&†kÿ¶þÏoíñ5fÛ¿…Ž©Ú—¹=1}”@ÎëU¥&£éÓ9Îô:€XO.=¬¤? [T&FÊÄÜr•hÆ_û3¸–yöv¢!È9}™Œm_2¿ý#9ˆZ²^ÑÝ”òœFoÊÖÀÝ>ü•Þé¹Éd‚UÕŽ°RûËHsåL*Éù'#0ÅÇÆêlùýg‹ åþL" {7gâØ¿‚Óe41ÏvP2èúÀ5UGnmÊ—wÌAËL²• 5Å2+JÙG|É2‘žÃL6ˆ¡.|ûS˜Ue¼,”ú¸M‰éR™ÀæÂ€hÂrkd¢ÔæU•&~j§´OKæC߆ÖÀÔIì(ð›®$cêšÆPV·ïóô&ÖÕ¿;òKJ;e&¹ÉÇúûMSvÓ†‘Æ9f‹q,~¼¹«]˳°Rš<ᵫöȦAJ>&GÁŠ#;j—É´„ñ¶z÷Ñ¢„á/×ÛJxúï(‹d²à¯Qîi˜>ÏLÉd2“|ݨ ßZ8Ÿ@í)µkü±!·øFÜ5χåÓÄh̯Wd娋 ÏІÒqb2-•üÆÀ¤G† ²"V}ùŽÍ…?ßB ”,\ÞÒ왑”]SõlŒT kÇÔà†¤%Ј3«¾ ëÅ·ã´ð‘ 2Ìf3Dûk¡WòÑã™§äOÙÏ^¤.%O&Ž­älhGÀ­Ý>e 7-ù¯%O%@µ#`±4SQÐ|þŸ‚à‹’©õÔ†Þ%0îм¸ÚóvÅfä@‰çI ”—!èè…2gÓkÖÒŒ# ­\äàæÙ¦<ËÝõh8ˆ ËŽÚY—¯ÇyqGæŽÉG$“4ß.| íÆEjÌœ ‡HÙ2dé×…‡•2$‘óq}Œ³ªM±9fo¢ÎydÛ*mmÎÂQoþ ª¥A¯FïÛ®Eu³§ä“€Un1”ªdÝ" ¿AÓn‘”x9ì”üհϨ®œñ);*ñ„?Ÿ(ʹ\ͱñ}xJÔï†À½”®Ú·M†/?O-Ä jcÇȆ²5K 3ZÀ]£Ñµ‡9ûÕ>xÀq#ôN¦Ô Œ®ÄøEbGJkÈÛÜøþaé/2zÛP¦TM,ëÍpgD¤‡‹záYÍ Éª¿ûO@Ƴ‹7H©”¬úîÓ= %s]½ª# îa"r&†ó'ëÈY Ruwh |²¦ U…––Ç´ €d«j ÿÄ£Ñ1ë­º)ZȘ6iÕ¬’©rÀ8Ê}+|¥‘MáN^6QÞßÊõ dκz‡|ð‚›ªR‹×?QÁi¦è󰹓áù4w$Ïžšh &“5¶[¶”øa¥ŽcÎw–^‘Þ½yâif÷˜‘u©:¶¦Í}ñM hDbèMÙHÇøÚÔH˜a+UbåÃʪ)r[b䦴@úf)™‚/ÚGãª.˜'M¸ˆaïØ L]4UÇWjã²oÌu=i³Ìµ’ã”k¸ %2]iˆádÇëû½‰©KîÓTáéíKL ^$îƒQ¢i‡n‡qÜ&@¸Mh¬Çª%Œœ%Gì"u92W2šÞÑhÇ>Ę(Õ"7—, W:7¹#¸U妷1ݦ¬Ó4%}VuÕH&´À&—øü ‘Þ8wø¹ ÙÌùÄ#3hž¿àPZ’3^vèu9¬*a´`j —L”ò2ŒÉ–JUìÁñÌÙòW%† 0¥TûVã3Ù&˜dµ—9äÓÚHGJã«'™e02½`˜ *w¬—¾é2$Ü,€?²\uŒ™äPo›û”[U s¤ÀtÔ蘧jËÛ ÙþøWOSï p2›LâÛ‰#[ÀJ4Žd@ûlüz»Z½xš²šµ)»~2ʾá‰L‰„_“9ãECëRªºüòÝâJÎ ʼcVÄÑñÍç7©@Uo¶#£” £Ü‚ G½sóQÙ& ²·~46¨]‰ãõ̶.ãt %ãDn :æF¤§ÑÒ>q‹Áiv¤ñ‘õšnDbX\íçûÝ8#>&LÐ5y¦„ÙôH¡ÚÇAà¨Wö8œáH àSFjײ•0ÿú׿(|SüŠ$ë:xÁA ɾݴ«b  ³=ÓkQ•ñ•ÖKð#RŽtd®# 2ÞVJ‚[†È·Þty1ÌZ`zagíadþáb%2&ý¶åÓGm]ôk'nmÇ~“’aŒµ7+ç°‰ÄÛLKw„·OnxdúpŸ’CKjk̯E82W À…ýé3ĨƄ÷ Î,ß>uµ31F¯áט¡ªÆV‚Å“•ñ€–”°•ÚS†k$HI0aÊnQ¯}€–­—­,ðÄ׿×~7bb.Æ"|"˜0YÿGøÇëjzó³â}p‚ðù^&2 ˆ•yù—@ß9%mŸ²–^¶ûhJÄduåY©í{;]dï]R#%7Ô¨…¾oáÞ´ßãz³BºÊÜD k*…ª–²’ÙÐ8 ÞÞÎ3U€ pT•1É|ú~ç¶Yº”ÖÞ8fUjJŸJŒRƒ(EdÎ[†¦Ñiä¬Z2î[&üZ5®ÎJEúh¨ÒÌíà.>Ù4•» `–L¯—’^´$fÛæìX Ÿ eµ‡sËäš}þLÊMUoÕFãExÕ0>=gà-ïâ0e?Y”HG_Àd¦Dfóe¥”5*õV-`t펽3p–øþ>ÑKÌ„gI/”xâYõJ˜H&øk$pÖ+ˆÙ6º›"!WÕ{¦~ÿèª]‹ÆvÈÓ\¼×ó[¨'jh›0ia­ÊœI†!ûí÷ßÏH­æYkCÊtr;E¦iw +h"s‡í' ¡Y)åºZË1YËt+#2Dv«µ åVÒ;ÿpGXdŽe-rÀ{˜í­½^ËôMUmm-ýKk«}¢JÄzá–ϰ›–•^ØD WÒγѪH¸jÁÐ`T7 ðmè AV;È_Þn\ÁQô9ö§>1¾ÞÌË|€Yi×èø2°éJ®Ù«Òteexž°®‘4²¹Óì˜,·¾4FxgdÕžËÑb@Tz—1)#åvÐkVž1zù$¸N¿ØHÊ¢^i%]-I9œÛl;Ö ·j†p?ƒ-阹£èÖüÖæ°YºÌ¥l–,ðr†”ŽÂQl˜FµöRæxÓ „ÅÀJÃĘ¦à›Žì+„=i/Öh-4J²[zVÒëc*Ñ4ºÞ2åùŸRÐ ¬ØpŸY“šÍ7¯”õ6‰CšH?í­îÓ¢ÄòÌø^`K×(3Ù®‰ýÅmS4"÷:ŽöQEÖXÆœß_OŽ19§ÑhœPʰõZµœ ½€d°vٿ͸Þg“ S:2þY,fK¶³^ûUL˰à&Ïp¬Ë&ªmÕt±ÅôË— ®%«¦ÄcA+åÓƒäŸ`ÎŽá@½=W×4(í0[ÑÄÄ2FFöÚU‘×Û±Þ.h+J/ÚÀg ÈPµXÏÜ‹®€Ñä9²RËðÙGYLÜEú€ˆuÉ¢^€@4eÊøzá]„àôÜß ›¥‘@—Mࢪ\ >¿³rA¥Ârß31”qn@½21r»)Q†&[s‘-L“£Dé·?óYbJ±ÆöÑBI#«îȇRVjºLS^I g÷ª@žÈÜj$ÆÀñ•d³„+àù¤¬ŽIFï(ª3lŠ?RÖØÂdU×h”-“›ë8â-6p¦Þˆ‘û“¯kªËœ“u©n4Þ‡ÎDoG@´`ôp+‘!{çi0}1ÈL4]¯ïW‘¬^9+-HL-;$¾g>b<çLòQòá铬#,h˜¸o]La€^´ª–~éªôzi`ã‰íiT…v<Ír†Ž™héµkoaX¯,’”|⛂ì+—Îd§íà…ÝÈFôëbžfu‘x-W~~âfKf<2ŸJwÂI•2©D騔/gi`%yÎ)ß*ÌÊ\·°¹à6O@lœ#Ïz·Cʆt œw©-¯ÖUËbÏM&ꔓ¡÷޶TBê:êï%Ó·¼§„w$&°:ÀÍJJ~û;z;Ë(ahäœùÀM¯—@¬ÈRZ‰Ñ"wAÈ$1ÌŠIG-ŽHgBËzC<ÆÿæO6T¶˜.Ø$˜X8ö¼º2gE¼¹HÌ®¦$0]‡LÄ ËH³„eq»ÿ'Õ^µ=•÷9;ºEÊšÍÂà‘@Ñ£J†ôÚ•™ã G1Ä."·€<X‰>à"¾þU[Ê®¯ÊÊ]=¦jnùÔÓ+c6 §ÉJ/MáÜ’øº–Ôa]Žtñu5 °'eC YY ÿdÇÄpæª{XXu™3M2<`yÕ‚•F¶•äS]J…c¯ªQðQÅô£­i·Ökçú¬Z©5`]ô&¶0ü–èïÀó€¢e¡—müÚ‘Œ@d’2FÖŤª^S^çt$HT•ÙʬÞ‘[Sà‚ <ÙºØ:VJCÏÙ ðå>?³­áÑú}¨”-ðÏ-³òɹÃd6'ûõ/1Rä['EÑ$äŽô®ä6ûTò•ˆsh˜ä WÅôK°§Ñ¥D™'ì™¬ÚÆJ07SÝQµÅðôŽª˜¢(ñd€¨—a²ü‰ë5”xU ‰zaVyÊŽrâÚÙvG> Å‹;ùü¡í ]dy6—²}(1ÊøU…ön§—·CKbÞ¨åvŸÏ½é™© ÕG»EÊYµ‰c³fÒÇ©:ž!œgV|Èøtl¢#ÐrеêšÏ¬tÁªù8¶ŒÅnñš6¤Ï³j¿ìÈ4"C-ôÇýû5P¢éjz]a·à·€R½é9ìÿX¤)uå°ÑZðŽx_˜ ûR) å~@IDATµCæó¥¬ËÎ4|2ÉáÇ‘¬–)㋪p¶Ë-ïÜícDü2 ªà°è£©ŠL¿wø¸£Ð+ïM”vÓ£ø6 T…ûd<6N•½cS"Û$·ùP*1AxG‘R—Ü<9±Rsí€w̰̙’Õ;7,‹™ßG¦‘!7I çܱ.²È>îÛE0…^n21Æ2úŒðôJøOÃý¼ÿ<¾ßO +u%hÛª°«<éÓ\ËÏ_‚Õˆë†FĹ9*½U¥Ú•Œþü—Àݶžš•ÝÖß8dU¥r3RÊÍ«dŒgެý=¥I>Ê3ìþ¯ÊDÔ%“…[Tnº gBÏÓ&Ž}º@]ÙÒ`ÚJ† m:¼)JöI0IL); -üÅ–Çûöp¸õÓߪï&JŽ€†æ,§d¢QîXÎP{2¯QWUG%]H@à·Œ¯å}Óßß™¬èÑÒpÈPæß1ç­ª£ 4 à¼ÝÞF%Vº^C׋·d2˜O#º +ÕšdHÑ U“5eãTµÈ­§Ú7³ö-–Õµ?R5–yÊ"™ÌSæ)T™héªZ)£Æd€Ÿ5úZ•Ò´‰Ö.Ãs€ ŒP5±Uez†Û2‡leÁœÐÞË“µ†’^_Vý{í ¤Ïìîªz[WûìæØuhðŽ}R Å¨ÂøvE< ¤qŒ_Jée¡”ƒÍÇ–QJ 0oúi¸¼ÆÆ»“n à³Z ÂlÕ°,´&Ü¡¥4íŽdkÛA`zX M;L™ÆQ)ÁuLÚY )7E5þóç*…@¬-ÆfPc4À)e%$ ¬¥·åh'е-íÚßIh܆æé(T¹±•g’@Ì â™ÃÈþ„0Åz˜ô û÷Q‘Ì•ð˜nÇÓW©¼›.2ü^,ÍÕØ&†œR†1”VíÓB¶m| 4Q AJxgµRœõrh¢ÞŽ}ÐŽÉŽé÷W ¥*¾Ñ@Ó™ÐȆÊÍêsÜ[ÓV½!ÜtÏ›y;èªo rþ1HŒLö¶˜’OíílÛH¹v`wÌgǶ"Ë6žÆq&Hw”•y½Ž®ÙP9À_‹ÅÚ¼¬ Oï¨Zv4—›F¸?(;d²¿Wëço0}Ÿ1ºrÞC™ ÷ûQ‰À‘2«Z6=’¦P­ÅÑbªng:ÀDɪ–ï=óĨқ«D†I);*aäª+iÏAIÀ‰ &¯``d}Ë`rëÙPV5:>FÆÈ¢F z$@“g™ /ÓoOoDë9 8±’€ÝH†)íï8=^ôæ^•²»w žf)9ÊpÊ;íöWñøLƒÿíßÿþ·ÿPÀn»†ÖïsàFUÌc¼v®TÆò€ã®§17yU:j§qLéáà:¾Ÿ¸¯‹v‚†Ö•¬ç)(‘”‰1@·À˜³÷ &-HU\ÌÌ“ÕBÙnôµ$Ƨ'+tMi:gA£*7En蚀1ÐXv줤O™†FdbCæ …q0MÁ8²ê·8 ÷W€Ü\2ô1€èÃâ ˆ~Oa—m†åú ¶6{%ØM‰•d£Ñõ'$ ,(1ÉZš¨*•k±%1+%á(ëÕNY 9^/’mƒÚ!Y¥Úa%¸Þę̪¶"Fú憩7 ½g'È9ånh$+|X—£p”óLÜÎ2Ãüᑦ–pa ³²-q²”ßîóŸxÐEË‘í¯8œXUc³€¾BH ‹JZ0²ÈЕD€[#“FP&‰ÀsÈPKGƒOXF†õö8J4ø© U9f8™^<Ò1À±¡•ΣwÄæ1…Ï„»Y_£óB߆x-×Õ›*å~š¿w tU?íiZz=A½E둥ܒ†ö.ÆŽ¬Ú,Yc]<É_®ŠÜ -F'Îjƒr“ée¼öÀ4#”ó§,ðMÑ‚qÌI,ŸÎïwTi;Àb&›KŒ¬¤}‚~½ú‹‰à|]²£é@›(ï>„Tõ˜vÛ¥d²ÈÍ nÑå#&s#†¶Ééü:·¡v̶íjºõÑ>JYå²Þp÷’[ȤöWɧ‘ôz>uÙ Ö8·49ïF;Ö›Û©21ˆì((Õh`žM?¢+“#ñÂ1ƒ’—iÇÓöý]ƒ‡k7]#¦\Ëëá¬KNÜ#˜Âö£rî¨WU˦ÔΡÄ]Ÿ²oK%U¼ ß;4—r;À4rÿ BP`ZC†‘í ï¨Ô#RòÙbºðmìt©FhQµ¼Ü2ï\bLAó#¼˜.ÕæVm·®©])f¶½Lû—h´ȶ?€Ç´L)2—ÛÐ>çGNEÏáhÆ%éðŽ¢ÇH \üõ×_Úý"ðUˆ×BÜNµÏ  l(cCÛ•Ð3Ï'Mãp<+b½»¶j/¾e”22†CV98¾‹õœk9Sïzež¹¥\/ÕöÑhgs^üþÙÀ ¸~Ÿ/èµü$]Je±Üˆ6‰Ä;ŠžÅ2†n}²=&@€×TÕˆ|21™KÁ{·È͸™Ø™2 èåÙE˜ Õ [OU»e¼€ÉôÊŽ|”ÄzÃJÌ xw¯‹¦5EWÞû¡šF/Á×éó‹£%• ˆ”ÁyÖË'f|ØÜÞ™Rh#¥½!+Ѹ”Z0½ÙiLЪ²c½]³Ú?å Õ~Üà»×g7ÿazÊ–äéªý?íp¼lJŒ¬]ñJ9ôE’÷€i2Á÷9žUnÀ"YwgÕQnþ´Ž‚ØQnbGË‚¬™EìˆÄÜ}fkWÍ„ gÕ×–Þq[5·)w÷Ï—ªÝ(}(¸ù Ьýц<»#`l2Vé(ˆ‘ª¦pvx ¾Ç'®Q>?±þƒÈ÷@Ö¦\À:êf¤.d“"}¢Øæ,rGbxÚƒ p¤ä“¦½‰Ã]Œ }»É¢5jï“kmæ-–€^vlt>2¦)@V{ý®o|2ÏÇtG¡IÖ’1‘1ÍeÕ8%2ž‰F9&si&«Éû¿.ÖÒ§ÛG<̦O!&’ žƒ#~žbr ¨$·°R¤Fd1¥ŸƒÈHûô0hO +1yC5¾l{OŒãlá¦Jpn0ÒP™CœÆ§lw1Ž¡R-ôpÎÙ’iñ’- ¥EúøJÆuëw½¦,S’eΪ¹ûÂ÷xúJ-ÿ.‰ÙÐ}µÀ”m…lâ1Â1Yß Lsñ»u «8ÒôWs•únÄcš’ú°,ì¶LÜ·¢ýaúmuå'µƒ §ŒësÄólçöïx:otì¦pš–lŒ46 XžL•¥£ –U1|ˆ½C› õ&h%ÀAãnÉ'M¹C¯#“üe䀯“þÖ`²¶u¬¥AŽ]°Y¿ýç?ÿÙ¢¯m6;÷ Vg” ž^ø/¬Òà zü&µF¤ÑÂîOßQ]ÞãÈÂQUŒïÈ!OÇÜÊŽuÕx=Î[7]ÕE”½*Þ 0B‰&Û-€Ìj M>²`•æ] ãüOþ z64QI‹‰@néØ>Zêr È’Ú}Ùϧ)LRÒˆ¦°U¢QB–@:j¾vX‹\—ƺ0™‚¾‰°F%#‹ #a¥öùó¬Ô›è((}:¾°ÆÄ}IÖ¥æ“9| Λ·@ëÁb¨]W#¤v²‰sÈSûÌóé«{sdkðLŒ$plºcúÃÐÑP×4Ýz4ÛªéYá=Î µ4znÉ UeÑñ™Ëø1)+-êÂ÷ ˜> Œ¹µ÷g‰y§ÃgðÝÁÎ@-”Bõ9SaÕø˜Ú‘@‚1”¢ÅdÕ"±R@n–j²Ù‘f¥ãvÿ:‚4f¨Ë1ýHÇù×»®4™ëíc¢”ð°8Ãî¸ÀÜdÒSW"‹”[ÉE¬´ˆùàÄÀ4çÿ5ÐDY8ú¶õátc ö4À§ÿ«Š©WµßæûÖ4› ý0&ú´¨/ gƒÈšg[a5V5ÏPŽŸ ¦Æ< ´'ÍX´&—þõSŠá™­’ ÂÖõÖÈÜQX½*Œ—ÑòMo¨c³ä‚p¼î#Df‚Iß¶Wrö¡ÁWjl–hÛ> Žº€l嬖3YÕ1Ødá”2’'™È°ã<”–ɰìXïº%±VްÂ);½†Mh2¿{ŸCŒg‰g…ÏPo#Ê{%ÊdÀ kÙ”ææ ·ŒL/Ñå;Ï(·[íÉü(! jŒL~QÚZ.sÈÓ­c….½ko [½¾$”Jº²ªÜn@Î4ªéë}Ű`˜ ¬Kï?C ÉøôÜc#b`@”‘n‘Ø6e¥ñ€j_{¿|Z¸`]YÉŽk¸µObJÿìe8ï§©qrÝ7çÚóq…^Ìq @©Ä¤¿Tr44ÿîëHËp]‰›Eœ[¹^Xè:­H1#Gdc˜¾¾°ßÔéa .`çAsãÛ쎽 ¥‡¨+Þï#Œ.‚»ØÙ¬R¶²‰²¨åÕ3ì8·”媭aðö'j³8LZô@‹µÛö¡Ñ® ӷʽ`-Jø-9“ª•¸1ß_ĹUÅcä?󖡉Ý"Ç;ªjdU{Îñ#Óˆ&³ÆÜjÓ(…Ót¤éWjËpv_nŽBW1µÌP)£tµç? J‘|xʘõÞßèpG%þô­ÑÚJ4íP&‹T‘í°)@L#^7æ­š9‡4‘y6Ž›jûÃ-¬Äʵ¼%»,Ý…-M;ãE>z™LˆÜibLAÒhŒñÂÈlÀ£ï&™ƒµ£aúÂà™­# ¦‰Z`L³vͪõ*¢F 7#¬ÄÄPÅøy‡gH UfR¯HÃ-CI/îÌÏß<®ê¬Á¿¹cÖeP[TeÂÀtµp‚$ÈS—ñoüñ‡C¾I{ ¹ýfŠñu®T//AÀ¨Ê 0•F´eƒÚR.Ò´q-LzÊ s&æ‰ð•8Çõªþ°j“í`œ‹l7æ]2>+X´vÎß‘§ª='†1ñ•êLIl·ÜV8“‰@¥dñ°ûÊ;†é ¥ƒ` ûhTûa`±vè³oÊÈd)1‹ÔKl €À·[þr@)7Õdø”Žk±aU>ñº˜gR/Œ6¡™`›(‰|jy¬˜¬GA?¶M½[ vÊx€¬w¨ÔSçÿÚÒÔeyš•t5NžF;  èƒóýqìM²ê p☭Æ"™,0<9„åFlíñ”d"2C6H—L «#}˜²F[ÁmU5}ƒâiòIÀ¶A)eÙËȦë¥ô%§ôÊJ¢ÿsJHA©·GƒñLðLd¥ÚÛÓ‘²«axn"^;LåF$«]U;Þf³Bf…©¤kÕ¹Æi00eËØ™I«*Í“@8"LYÕ‘'F£Ì-^Þ— Vê·SŽMÜ&ñ]„¾)íÖ1ªpGÃJ=M™@4É_´R¼ÊI©—Œ[G ÆgAÙ½ò?Ž7²E&n¹ koÊTµÂ1õÖn+»e¢Ú,ùûk,#QƒþÆðÒC]©£ª;ì»81p7??x°^ŸÆ‘‰c>°hcUäþ¥ÁJÈÜÈúö+™(sÓ¥ „ijÌ­ªŒL& ŒÐ+µL|{&H£JÖ’?1ÞõM Ìdþ®©*çvV¼ÿ(—•¬*3Ä10&ÿøJ#ÍD Ð1W{žàFïSw,È0Jް[¿njoäôsFÂkì¹Z£­ê¢i®£ª’H†Qê£ô8ë%¨«!'@ª”L\¹4á4ªlÃ&Öˆ$v„ÉŽd‚{®6ÇX•8G-4m‚Tr”ñ”ýœçC£”¿LL#šÔ…§¯ Äèµ=‘ù8"“ù)0ˆiºQΘý`êJ kh‘ë댗•¤ÚlõÖ[Éy”rëQ سØäÊOb[I1Œ$Ó»%; €6tÜzmȶ¡Úfï“X©q²+-¡-ЙÐ(Ñ´U³’ d¼.YW¸/Œ^žªpž€œNÐ\Gûh§;ÒdØÖ¨E$VÄLZ©ÑHãvÓZ0ªíß¿¥Á ¢jaj*,êôw$l]ÙŒ‘z;6I®‘ÃxæôŽJµhð°ìÓmý‡ fÅk°`"(U›%ÿUe˜FIKÓᑵ ¸ÈCÆÀ(ɬ7®w s„k4 î1Ý®¯x&ø”áÄŽ°ÈŠ?&²7Ô踙ÒmB \ù÷ ÞÊaÈäãSW»õì56ßѺ²íFŽ+ùhZ £J&Ü"¼ï”JýR Æh?÷¦JÛ–c;Ózl™ªd˜vók‘<éåô}%šñ4ý6Éǽ0dóŒ—ë­ä¸O„ÃÌuùt”Èh"›å¸åÓ„l¥ÀˆÖSj"ài¶JýÜ)aY˜ÈæËmU‹Ò497š­1űdZè›r¬o H¹× ©Š­„±@b‚Û÷ý4%#àÐW¥ì¿[à3Ïjn-ÖQ6ÓG°ñùä ÄaVkO“°•cJ¶0ÒãÈ“{·Wc =¦ü)ex¡JÖhû8vwÊJ ­‹g&Úñ¨Nl™Æá…^Gz¶î(§×øý'f‰2êƒ×èÉØµwÌ¥#_ÊÚeÑZxX—# ¥ïnnÆ ª)ñ鵘Ûßq0ª&}-]/OzU¼lcæ U?—û?FNŒ›Â Ó-zMkg…ŒgFcÿ1ý‘«vÍliômBƒ¯±Pª1êZ(ßÇ¡œÕ G¤·…›ë%ý6ñhÄ|(|ˆ1“@±‚Ú×[»£v4."Lt¤¨ÊB‰çJ šŽ¬´*}8Ãde+Áù$‹‡;2 ËÆÂýy€ç 3™2#ªVrô¾±~ßî.‘ô=»vbý¡øh0-ãhÌ‘™¿·ÅÀœ+ñœ?&£k· ùW}sÛðÁ‹FÙö0[uÇZ0Àí;_~a[Ç· ëµ'–ó­—¦#l:A>¾€LÐVŽ«Âb†4•d>þŒž,РZŽv(àómþýGíC£Z—RLülw¬dÖºøôÔÞ.¬· ½£€e½ L|Kø”«Z Ö…šÈ ŸáÙ<„ÍEíxÌî%ûë™/FB)£«ú~NVUÊVn<Я†Æ¥É*7wKY©5(éùX ÷ÒâãÇ;â‰aŒp&4gÑß—À¨ò¼ôw…¹ IæÈ¹¯Æ ?¢ŽÌ¯ä{"nÓv£íÙe³r¤a¨Ïÿ÷â‘&^¿?¿zÚªåùd²KåÌß±%Yæl^`Þj&rÓA&»`gÙòÌõÂôøÄŽx÷¿¨ÜoCô½Xq°eèpÔÆçÌ„'M%˜ 騅¬ÆH½”&9§Wm±F(9r(` OUíbºržJ˜r@Wb@°rhšÎgVa9ÍtÑ |ÓÜ÷ï:}Ù”8{I@0)œeÓ{.ÜÚJ”@ œ¾£Œ¡çPôôù›ŸT» Ü,bHÑ ôq«¶UÊöA¬ÊZh88ê¥,šK¬„!Ã8ŠmØJ²ã>0e-ôxeª·ã›{|/S‹¬ #×Õòî§€gG²-·j]ëm·éià&Ö"cè7(Æ1^†Ûy²@n)»)†rzÜZ£}Ù8ÿÝÍ>†* %¼A"OúÉ4Hz¶98jé ƒôdڹɪûñ$NP~Éš( -iúL 4 žŽ]¶£ìGO‹Przcà­GÊ×þ|ÓŒæ&€ÚUëjP-ªµx †®ìØKæ/3Á4EïëCG’í¬‘ ”Æqë%PÒ[`L!è·ÊVj4šVÕhíZ²Í #ôv ΰ¨ À¤O_Ƭ‰SÚ ÉVµ=UEƒâùg’á÷¿à ¡£ò,a;…d]©Û²Î¥mZ]vÜŒŽ€xæ0&s€•äf>§^9>Mã`ûÈ"½o*@™‹9¶g¿§ˆµ³º)@™‰¬·`J†"¾Œd›¾­ht UJ FV¥ Ä8F6®‹°mVB©×ÖžXŽª”;6É$RuG¤p­MÓqS sA_4«Í§TÊGî7T²^ÎÇèþs’ ËÙÆ+õªi”Új/94½»×ÛÇg"ö,-“mJ˜@&öÈ •0µoaBuJšx9C¹Å(·gŒ&>ñŽÚÃøÞ¹¬±wð 7W´ÞLr– &MÉm2G¥“LC·ëpðª”ÙQËô¹åÓãkWM¼êf)u¯JL€ ótÁÖÈάŸÜvȰÆ0[U@‹P˜ÈæbÈ„®[??Mq”€2ƒg•F è¸Yû飯ų¤ÄcÎìûY—•¦Ç´t—Aðp7¡÷>2ÒD¡+ý¬²ÅWrçŠÞ=JÆ„“úPý„ÓÆzŽ€èž×ö<™¥=:7‚¾áùÓør·1.¿¯]™’²LÖ”Ý?½cþ'häZ,©$‹Ä™ÑV› 5 ¸x#ªâ‘°à,ÒÏAÉ&–?^¿Ï‰™8w lµg…Ô.0µwÄëÂm@ô”yöG8“-,hÞÐ¥ªE©¹Wõ)È-ׂá“ßMo´jsbJÇôkt„µW „óϤ¹°)pGn]­•rÖåX&Ë*F{ëµL_ÂkvdHQ‹)Í•4BÞ1¬‘¦Z)2‡ÖKC&Âríz‡9ÐÈxëyF˜X[#lk ¸Þ> U ÛÜd_{&Ȫ‘a<0L,˜çÉëÖ&ô¹‡Ï–w„td-ËsY#˜RÔ"Wõd1Ž41J+G‚LšBÌê51˱hneGwoV‚Ž^ÒqâJ •M\ P¥×ˆ÷˜‰e_TÿaU ;ú,ÙQîñsÈŠ [¡D°‰=Qšª•²‚•ì„ñ=^¯à“-Y€ ÙOeGØÏ¬.³,3qL ?ëþ~ 6=}$ÜbrŒ"M¸ÅºòJ¯¶I2ÆìR•ðÂ6$Xt‹Ý—&è“ÁdòµùóÅ«K®‹¸Ž1YY¦ÛÄóIC€ïSP²¡œm¯ªˆ„ jÑe1ÃçmÁ‹ÌÜ ¤€éäøF:GqäŽÑé“V­Sß‘EŸ41Þ±1YÓˆp“ä^O9ŸVßwK‰[ž e"èûöÓ«bȈïœó4öt¬Tb’§<ÜzÇx-4J@ß&k¨–MgµFǪ‰«Žá9 ¨rh"½kÔØtWîh1ÜþMç€ 'ÃÊ<3qÌ6’ÈgíÈmB/Òà땽³}4æ úĆd}¦9T%؆x¸¨ÿïìðiv_+ÁªJÂQ&ÀÄZ ÏPú¬wÄc(EUàÝ™3pæý~ç:"­*tÁÜ À«w¯!ò)û3`ßy¶ª¬ggžá&Ê–é.™Ë4ã“5ÔF`ÄL¶Õ;‚[V”šB#0‘ ð=ˆÌŸXÉ â'C GæW{Rw4n4” îüsS<ÜË_n:Üh>˜ô97"±[S:*Õ.׋ÙE­”Ìõ¨jDʘÓüûaîØªø0q>e¤ˆÌD#æ:ó5Z˜LþkAï£ZÍVeÅDIhìÖy†ñ4ÙæÓqV•^²_FýÙ{UÌ÷“Ü6ŽCi[zbdëež-ÞÎ}X•f¨ ‹½ì •™Ô%ãs»MçúVjÞe¤PeÂJ {Ÿü×¢”@ ßï¥À—ßÏ †ìÊÏ›tUß YËoÕöÔ"Tk‘uÙê)2qdLõʘ¢}rk‡ªAãˆO8ÆŒtT•éûôÛä|¿ñk”EV½á€ƒq/èØÀÐN/ºæÖSBž_(ij=x¤›dK €ÙZšeŸG-4‰ñ™gßÑÜ&fNßÛ5g??FÐ ½âN8›ô²i¶X]“žmU¹Ú¹ÁrãvLàH¼R²ýµN{žy¶L†ª†bš«Ú0sÙ’ÚE-Õdb‘þc’†Êé•z J 7o.öéÔå¸×;SïÜlaU³ÚÖM{IúãrÿI)ú8(7½‰0î‘ær†å®iP¤+ esËþϪeZX5ÒÙòÆq›'P¬TNI]Jý%ÝŸIwqô†B £×#tl.Rh¡ÓÿžežË¹Õˆt¤qÜÝ1¦Ô8*Mb³ÂU‘°èƒ(ù8zF¢#’˜ÿÜ}…šB€ì%Jz¤ YU`ŒHÖnHLo՗DZeê%v„ß)×ì$%qGYV1µgŽìkC¨&À!oÛ@LÎ0ŸM 4%™ì¸–V%ãlJ<ѰŸD_x7J)«"ç¿mñ=^pîvZº‰•àVj.K©Þ¶a-5ú9úŸþùç]‚tÔ¹õ‹.†¬Qæ˜FUËU}ÑSªŠx¶B—ˆy[Ò·b]ÝP˜2½ãs{Å)›¥ÅþÚ Šªñiª¶IUJ‚øe‚Í}°«)i©Ë7R+-þÝšl‡"7%C¾­_ÂD6ËŸ¾›æ $âòqGüåøi´U$YžHíý¸Fbr#ã94NÞ¸šßVñ])¶@¥irh™d[  ‘ÅFЋŽ}”[cŸ >F ^‹ãáá2ÀDØ-Ü&cÞA4 5”µÌ¼‰•æ o²ïÌ”`ÎéóDHiœ€ùï³PÚÄ~Ð0‘xÎZˆõÆË½^ÕP5ÈQi– Š9ÐÔ (Å‘²‰ÚíƒÜÍÂÔE&Ön‡ÕWiÇöWjÕ¼ƒãnWc&l5&¶†ü…FÆP&û}®z 5#5èmS›#q;Ï‹†;&«†$ÓHü’ð– $ º8³jpÃuñIè"pìð¦èr Œ?¢óWÂ8ÝQ#¬*ê0ùÇ8šûVa²zUÆÙ»YÆ1F5OÙhJa:>AVWþý¬„4º£Üõ[&}ñ1}:Ä6k·¡HAæ¯f2FÆT"î Ó”í&<òŽ@¸Ï+Y˜%ãë‚ÿRâ[ï;] ²}m"h~W€Ów#¥4°v†‰™·ñ±»†iTEG@L)·°GàÌA)ìXé¶ž^ ÛµàÈñªÂ‘ ·þU/12«™àEs-c´c·`È5*‘Ádû½p»Ï¦P¢i^cÕ@<Ühbn€¼µ@Ó4íÖQ® §´ÌÍ %<%&ÛŽÃx-"ÿ>ÐÜ®I è¢TµÒÆe©6>vw Y»–ªŽ­DÎÖ‘,Ü>rwŠ µã…ÒÝ¥é0€¤4·q”xÍD]éM‘k‘[©)ø5‚X)œOL€À_¤Îä½86)†È? (ÕT%ƒÛ~%¹×¡Ü $C9wáK/£Ô®•|x¬ •+¥Ï ã™<7G¡‘ƒÑ ,ßþ•´6ôûWcÿé7%F£ªF`+)‰–ÑÈJ£ ¥r¶º„éŽZz †yRjŒœç´û€Èš‚ܺԙzçf[&®ð\$¶ T²^ž2¬P5H X©?&4¬Ê4Ù’Y`GØ|Ü‘k\J}ÖanãSbŠªþ] ÜãИEÐz€R& 7"ˆÜh ·€LÓeñÛä`C<ì.F¤g^‹cŒ#Y;0Ž2>ònôçOMd< @¶myÊZ€¶J–ÓP+‰Ž« S5U>íc„’èKeh¥le2U-¢Í¯ü,ãi"L©÷ ÿ|yÖxÉ í Æµ”r‹oŠ<ÒÚB;r@×î¥äFzåVð¾½zã1v;dWüö#{}2ìô 8 È¢ro‚±CLâ £Åxx2¸}Zɽ&ã|GÂÛâ󌜲Uñ[ž²Yþ‚c€²‚fòc¾ÝVÞÅTÃ-M–F w¡Š!ƒU·f-‘ s¬«82gU`½#ëbÒÂhÑ’˜æÖÎV©ª>*ïwÕxÚ5¶gØQÃ2ÛFd¢Š¬Q)@ÀÓ,À”®I©Z®WÞˆ-Ÿù9.¢.+±RŠÔ.fŽ'«‘Àb“Ťyq½"·z]c¨g(‹ÄÚÍjº*Ãð2%Ì爉¯…Uƒ2—ù(‘…‰û‘Þ/‚¨+-Èe€s2Ù´Ç(™¢KÀýXÀ¿!ßïMzL½í#™l4SÕ‚{dâx†®ã>¹’®VBjìŽ[[©É€üið1ùt#SD 3qT’É0aã‘­]&ö·¨È†¦¼Zµehø`Ta™8ÜQV-ç@àȶA‰Ó´*¦{ôËógE©Ëe}¶[˜21^; l Üú·sJ½ }Xþèk!®Ñ±‰íã¨níÓð|ŸÙÆç D,vTm´ìɺY7Wà1çdȹY°–ñªX点ÓÈÙ½úmFŸ Ïñ€o³ŒoD eëáª&hŠÐxÁy9=†@P&Æ»½ª|ëçš :N|=N¼bL¶›» ,ãk§wìRÙÚí­Ök%Ÿ“›f(g¢]¤÷q2ÜP† •UéíÐKrø¶JFp;Î (½'Ð5šð5;ɱ ha.€FO0Òqƒú% ëJ¬ÊÐjzGU%‚"&Y£)ûã6e¸°³®dZø¤‘Éd%ã„*+G¤.˜‰µ G‚öÑ(á«:4·ã\gnk!®K  >zijo‡4°g´'[ÊŽ|TëÒ(ø”JX†iäîˆq}ŽÉÊÜ”èŒÈÄtš|6´—ì{K)jÌS#F6îÞžðY˜®7ŸzÛ'LÈ‘íL/XÅ+JXøsË?V÷)U,'†ú¦à3œ¹#·®š@N3%Ò£¥anz#d—¹±*÷ØÏ ¥”a½‚ lM2ùü×@=útý¤uÙstt%U‘R‰ Læ&ºÚ¾j2¹ñp³Éh:àŽÂ<5þ;¿½Ä Ò{Uƒš¢ß2˜ÈrC¤‘½7A£Dî‰^+%¤OÂÄxú.¨åí 7ŽR` X‹…›²õr¸Úó\ŽþÑWÄ1ý 2½@š²œ[™FiþµËx¤Xîˆ Û¹ÆÅÓT²R; «+¼OÄ‘’¦·‚ßY]azÇ~#4š¹öü÷8Ü€EË4H£ (w…)ãw…ÖplO-”k÷ +%¸)íéØ ’I¦×%ûMB Ë&­7k/¬q °# Kû~N1<5âé]mÎôJaúK?\ŽªåZRÖÒôüñ˜ôáí–åû ¶vzsØô+Œh7@Õ]úG„|ˆU‹-܆Ll¢”CúŽª1ò.Ø%2¤#OÑ(1z "_ ,rÎ3¦qÛ„!,‚lËzrW˜ I¯Š9ñw>P¿ZÇ#º¿dñĹñMÜÂM6¸U9Ä»$¾RΛHÓ  FU¬Æ·*çct¿ &6(Æ2¢m•ª6Ž€¿ìˆ—5î.W{’A•à•‰•€¸§4Û<ø•8#톯TÆ3Ä"½­mû/&½³r3´5¬ýøÞÐÛÏçÌéÉ„ºL£:‡ª9'“{Oš0ýö4Â’’qd}æOÙÇÊÆq%G&äXœýîWQ‰8JÕŽrž|&SÊÉ€°•¸Áª ¯÷wl7U<Ð’MïOÙæ­Aä@“ƒöÖêͧѭ©J ”2ŸanJ«¦ËŽ‚ÌG¥j¶p›¸,½<«°£FØ\€@j—FôDiÒcVòÉÖ«ôú0ql=Vk‰ÄwÁÌ Û„žÜÏ&¥AxbÙî m+ @/™# 8ù"¥Çé:i„jkÈ-ܬªôȺš’øU6tJ “FïY\Rõ¬uCÉÿœ­Ç›•€Scâ>ˆ½RËä ‘F©Þ­Ñª-){j?¶ç»’Wד÷ ÷^u2ê×"ÌUñ&Á"R ;Ý¡ý5Šž Ÿ°’°=`bÊŽiʆ¨Ò`Ý‚Uƒ&9¸¶#™ ht¤#@©¤… ÓçQ»#~õ’™[oí-@´3 d“ÕÛÂ=Qš©¦á`g²Ž”É0"F—Z^Lc7LÐÜ7b£³’™ä¨·»g¨·vÿzÞƒãûnº#@Ó1qÎðž‘¿#^¤ôŠžK•9eUÝ«ªÞî® 4Ž ÛZúŒ0d²ªùËù(M–‰,臣‘B‹^ Áî’2¦}hz(ú‰çÙò½*O-²jA¸)FÔxÿ¾E< €kJÿ·eäÈ鳚aƼ·°É¾dòkèilÒžµÃd¢¹}‡ûÎ4±LHl"‡Ó$M2zÕcb±v „ËuÙS#™œI/ָ׳ýëâàXon»{n 9ÐÐÃ2Þ1C¹®ŽÅ«Ñ"Z©¬ DrÓ™¨r¶X£·[zžÌ›¨Â§ÝÿwÐ-Á"#€o<Ür€ÐÙ‘pxbíÁŠÀŒ«;äŸC‹Æk˜|²"îH#;Ú†‘d9†*96e›ø‘k„œ­LCinWâá#0ñ˜°Yá&y&“³”E$7xC‘‚'’ùÑÝ @š²_öi´úìvý Â[f›2+scòሺÈ:¶cšYaàŽ½ÜûØÓK·š«%+ÓÙuú–T-LÄ»”£ÆfÍP»ÆJrU2‚"&+9$sÎ6WTSÊd USº ÒÐ̵gØQ‰R9ÈŽrKB•>ÞQ¨ʪ‰åÆ™Kï(låØ3fžÜеçÖ‹Õ+×BÙPâ½æÝê5„sÈ„£^Gí& 5d£ÓÀ¾þ²©ŠiÜ%½,zgÕÆÑ¸©£R›×Õiä@]0yJ°è³ë5î´³ ž )H/7 KÙze< QôgXV5Z@Ky€`‹!ùÇ _\ )êUˆøá“­%gË$nO?¡vîóÂ(u…ó“Ö>]¯Î¬ix;Ó«Ša½GÒûÛA§ÉIku¤×EࣚCV™#ž¹cã"oý|ÒM”1rk.Ÿ¦Þôó²ªA¾¯ÄïVƒv÷™´I«Ò×õÞe ª2“6lŒÔ2ÞzܺZ«ö!¨ ÀÀMìÿ(c½H-0&6BÄ8ŽH>•´T-·pO‡ìÊ•ÚÇûàµ+’aDǦ$ÃhñÓÚ•ôŠÄdHXûH³àœá@yËpÖ…@Ê,`ôµ4ÝÕR&î"xGÓ‰a{â#ñ×ãLßÚJpÎùѪÉ䂲ëkÉsÀOø=²Ñ˜Z€ÚÉz%SuíÖl²ïª^2LI· ” U¤Fƒ²×…±Už[@;ÞqJLkøæ,r–‘Ýhda@ T}ýŒØ”Ÿð{±…’Q‹5tÅ-@ƒyùº0é[‰‘ßà¼Åì÷øgöïÏìL(®Àa¯ 7:s²q&€U[Cµðâ|d#Ú$Ü’²*¿¾mW O°‡À;0q ÕÕ1†à`1Ñhä)Sú–PƤ”›ÒS*µá_ pÖˆÒ/ãçþ÷Y¶qƒ(»‚l%Y É€ô”‘»T&õ*á)Ó4ú%íLÀD)Y{ú~¬èÛÇž)ñªã½éÁ“ˆ$p\n¥æ",h<ˆã¦¯½kmÕ–Ù¥ˆUµ3¡t Ô%[©’{á³Å#‰1ºh|S`2VÊîØLVùSú1ȇ,™¦^˜'LPÖ.7:e¾ZšË!%M—ÅYµF‚pV47Ú;c²Õk™ºZ Ü' Ä1Þkh94å ¿ß×Ì«úÔNãlE»mŠ’ ‰ Ëõ¶öîîÈAõ:}_€ÄÐRXÙïîöïç_{Òžº6ˆÀ2Ž=T%2 p®ôûžWrÄWšÕ^,«v¦i‡H6̤M²Š?R×óg·<LÜN£È½‘ôŽp-Œ±0M2UG½mÕ]öÉnh¼V.òýÉœï™ùü Óܤ|©ý¢!ÈBÎ¥^™¸áJmo¶Põ÷/í~ ”0øÚÓ«VjoU²Y!UÍ•…#­t ˜²U_ ½ÄÉðȬÚ£ëÝÇmù2™ïbÿŠóõÜ`Ëw‘Ž0·ü[ Tm™Ì‘ãµÔH&ÈÚ)0®`ä£äÈ$Íõû~sÅŸ‹Ý«É‰k§Z&l%SÈð€ŒÑ‚qÈèa)½Ì¶Õ• (Ó‹J1.¢1‡†¦É¼q<‘d>\9A> \?ž˜é‘ô­Ô8+õ}sÌJ™2MnÁ iIã`ß_$LûDÎ (â³Å0´y‹™ŽG2'@>¦+êHc4“mÛn4w)g(ã»{Y•Ç1dE½»/ ¶dkÐB‰C&-ÌIP‰&Üeû®nàFMœO¶ùÌĶxk zÕŽ iš"ãùÈôÉRÂ"¥Œt÷@Îõâ‘ñÓ3l( ÜNÙ_£®•òá©n½Ì •ªÇÈ-I DæF‰‘!«šÒ v¨×‡‚¤lt&õ¶’ƒpMâHíßÿ9-ç¼jÎNIu†eJ w8_X¤9Cn(bS-ÇjGúÍ"o Àk¡üŒîÿØ£¸­h0lÃr¯€÷-ô“Ã!A†ÜhøãiXÊ·[¤Ü3ñý—p´0Tb"ÂÙêibæ£ß,ž”4Ä‘U™ÔN´I9ìF6¡Ži˜à{·mEÆÐ±.€øuvDÆÓä°^CÏ€ßÆ e&•RÊŽó9 ÷…ûtÚ\#Y¥®°–‘{Ot¬T#Œ¬= êØ]94‹¬miTklm-«n+@hy #Ç8zds9ÿÖèR˜v3 £U²ÞL”^`FæTµ«@IDAT#è}úŽºZ^¯pY2@À|àüa½ òÁø˜Ö«‹R$0Ž?DHJ6q õài½JÙâ¹±}Ë|2Ô¯½õ™¼²­žÒ,¹^z@cir&(’ÁÝzǹáUí#»¾dîhY¶°Ø§Ó'Ò#dE¿¡êj½6¡éÕ¬¿‘BcÊ@ûWzù³2ïÝÒ÷&ø}L6?‰Öfõí‡õx ‘9²°%~îhð"ìÐc4R ]É”º?²¹çìEðzå@úÖ ^‰C[å,S"i\/RÀH€¡²KŸ«a`Õ‚ƒMúÐw‘ö™[†‰ó‘µËœóÉ„rsi²Â‚lO í@ßíúÆ$NÐuŒ£œ˜>òçôýJªdmž•¸ÁÄÙjlÕnÁV—j‚ªJ9 ¯Eû0 RU(ú1xd]Ý]o €µ´Ü}½œ²YJkÏ¡wƒÝÅ_^A&Q/™vüJ‘¬;æL©«¼#:cdËw÷|0õ·v„ÿo ä®ÜJMÉ_É1[Ù1œ§Rކªöž™o\¥zµ zGY;ÐÑH¶p‘ž¦AJ°ÝTa#í¯8yJ8e/ƒ/8ÎÚÛŸù>ôæv&³Ê°F&-€ìÝš. %¶JdŽ "ƒ‘óÞîô\Y€@£/R>pÑžœñ4¾ }šÅ3*-€ Á;’ %㟟6®ãÖ¿_¹Ã4L2—Ïöw=¤+0ß»ñTÒxJæís¡ÖŸÜ€Ô-GgÇh<Œ,2„›¤Ëx¤0Rè ÓÌ!ÀÖ%{ôËha%ÃÈœ;¶R˜"cÈÒ—)SU¤ñC¼ #UaaÇZôª*¥A*5‹ )÷ÿEeßûÄH>0ý`7Å·¡ÝX½¶u ÕÄ=FK]ðÈ4Ýî´]YÓ‰;6·çÒ˜3Rt;2¤ÀÔEÖSˆH2YµMäãòûzqÀX)òZžt쉚žLvªû(õnVP (UÕ h‘³ŠqôàN J6ÆtÇbæ­lC€›* s`UL“ » U-é(o¨Qàkî.Žxséù÷ËÆTRp&¶ +x%ŒÝRÊ4µ Š7®Aï5×β¯Á|òÄ“ L$ €‰—1-f:,Þ5Ràe‘¯ðüpq3èVÎ]"e;'Fîîɪ2Ñ[×üsF ú6ô=ñ²*^;>7 \c>²=·Ø¨ªÄ™!Œ”³ÊÙ‘þÚŸ7 G†åZÒ8’éE6:¾‹”Uý”Ù_Ô_£*ò<ŸÿÁ(+P´¨U‘ «ßËæ^)RÕQhç£ÈH»*¥ 7‚ÆKõ¹FÖµvǽ‹^ÎA¤+F•¾sNrž#’RÞ²¨tåÇÕĹ™5qL6§ZYþóTÂp–‘ r(à™; V°PÒ‹t‹umO¸ß­þâ°));æÌ™[ü4ã˜8½ã-ïØ×‹¬éÜ€Z"aJ2% ˜.”d$Ûº´×¨TÕrÔ?¥#1eN–²ÝÈrsoëy: ¥F@Ž«‘ŽüÄÉdñ¶{j-Äx™§cϲF¥^À©*Èð«Qï”ýdkAÒsp¤º„.Œh:Œ¿Ü÷åÙ U)sèHÔ¨ê;³cÎ'›€§@öU„¹yC«ŠÖS"ªñµôÛ8çö$#Ø+ݾs;@JM§çƒ¡wåÌåž‹†@×y¦û ·ûûÄ›ˆ¡yZLÖÒÏŽjβjJ>pÃmÎŽkéRJ€Ü ¨îkÙJu)Á¢Æªy+¸‰ªdŽÝñm„o÷Ùͬd=ib<¦<€©¨0 ùú&3`ZÕ\•µAÆD©ï1ŒÁ“Éõ V2>ç4z1ª‚>C>J-%«Æ¬È|`2Gíý¸6˱k&&^ª‡¶€vq¶üýñNp¬o0}#Y GJ³Ô›˜ÕJñÈò™ñû3‰?¼ªŒPXýueúµÐ×bËÆë6š€Uy$Ûüå‘€£§†ž=îJÜ\VÏ'ŸFWÑ< „äS©öZr pÃP—cÖ‹ÉV×€ÞLªîH0Ûô²5ÈÀ¦êv4ø5ªŠÞJ)Œö=¬Cv›Î‘Ú.•eƒäxÙCíў¡L†¬½¬ê;‰ÝÎ6´ï­£È\Vz­†yÂxÚJ{J vY)œØ1C$±ß§¾Joïü Šh,ã>‹ ­ÑWH #0ÇÔ‚ttÇd¯ìêjŸZd¥˜Ö é@/§ì)”¶ ̧}`nJ-\ ’'œU”rËJYmIÇ >wÇÆéâ_»\ õÒˆl‘ñß/zRµ2ànØ9ö«Ä± Lü¶D]ªz…¯¯a”JM DîuíŠÔè˜ C-aïè2<³…µ¤,Çðä@ j—Þ”ù`èi\Ó—¦‰˜FÈ·éK]ÉAÖ’›ÌPUÊ)16‘ÿrsµ$€·-‡Ž€*%C&ŽBI 1¢YŽV¿tœ ±j@Î ËàG×>ÆuZã½NŒö˜“éß¶ ½Æß¯Núœoë÷SÑôöi‘/åªõò}"JF(5ÊmªMŸ1f]€ Æ!;ʾ!½­#=F¤”…—ɦT•aV¶ª­ªäXÉz¦ÀÇî÷óOé‡(í€P•›™^ž-A›cöùšÉv_«æÙÔé T+uäã)úþw)JÁ9s8‡¶ÕK¦(ð=,±£h“dªZD÷J¶ÞZkl\{Ò ¼MXqéezL9gǺTs Ð@ CãúëuŒ$€‘.â¡`nÚ….G¼‰a@291@02AkûÙ¬”g¶LòÜæõNC#Y‰ F}ç»A›)à¿ãø¿ÿû¿þí6ÀW¦ÏH¼<÷¾VÜ Ñ—ƒC«o2¤H©„”óO°¹i:&(g8¾—ÊÖ™¥„UgOS ]ršgâŽnÑEü”ºW|ê0Ž"™T…­‘¦}©ªÑ›^UÖn¢hâá)‚Àã„G.κ7,æ[C“CŸl-˜ª Í6%Þ±¹i6«£ª˜Ã|b”^†g¯„ä£êq|Ӛ嘹mµ·Rì¨*Q2á¦ê8 Î_ŽÞ!Á°ö<ËÉTçÜ&ª ºNŸµ‰«:"ºDUï/²­EV͉ pèÃ:¿Ë²¢ Ó /àØ«v\#p%߫ƳJì ðî‹vÎÓÑ»Ù'R;À0[ÀhdٙؕSn·ÚUÖèšFÑŽôöy‹l•hTéáxVM¹Âï…ÁÓ0¡Ï9A³šŽÙ׬ªLÐàÆñIßÿ™í™™ooÛVÂÏ-Cí¹É0} ç¬Ìí¨ÅtAPé§9?ØD½©H‡.éUć)cä|“aÖ¸U,Jæ†ÌiŽõ]¥/ôq¿W¢±Ÿ¨Ú 2TÅ=P¢£ßYbY‰Œ!¼8c~¶õ4º{éÕ 6ÎyUz‹µÛëiz÷ÕrÍþ¬×Dâ€ÜuÈ`Ë—97ÝQ)\5C#Z¬ê>;ú6ŠŽ2åZ´[»®xLκZ©¡x }²ò¾ Ú‘€‘µŸH6FU‹#Ÿf±ÚP5·7¿ûà M_#+‚4«ú‚EîR-Ÿ¿ìȇ&棽 0ŽJ^žÒE1‰74ñÜò”‰ÅféÊ*ÆäŸ¬œ¹÷ÑhhG¥³Ó½¾Ûí‚ eELéHп¼­ßOè_†FÔÞ]Äܺ#¾ ˆïo„}&¶ðdmB#`;sã@fb+áL¸Äù3fÕÖ¨¥Å"kTÕž94Ùâ3(kÌFÆSŠH; b.UÊ4á†Â¢÷¡„ñpÒ•×ï{x'†0Aþ€dæ+š^îè"”x‘† ìXP8ÿù]ƒº&çc\ò’YT…$Þ-ž²»ÕN¶#¦‘4aw¶.sU|ss–i|{êRÂO7á0"OÕÆá19“%Àà+Á•0̉#ed]ø“a*YCÙbµËk(‘)%€sÛ'÷Ž#4È)8²å°Ÿ¥&&NC#`ñºiÇØJUÜÄLµ/ÖÙà^#àÄ ª‹ƒ®¦à5Â"ÞQoŸTßB½Wõç_e.Û_‰(Û î 3a›r]ñ R˜ÖfâØþ*QÊÂ?´MÐ{f2çŽØç«KÕÿÇÎ Li«¦8ÚãaU&À“C=Ëþ‚•Xã†ÂÄ2=ÑbrŒÕ-ãÈSÔÕ Õ¿ºÖ›LƒÔîeÔ^#>&7²J)ûAV–¤¿Ëž„éØ-ÚvU&ªL0 2„cdšdÓxy]ÈÆYi¥›K¦* z棸Ä÷Ç‹Pj—Ñnxš> ÊGWG¸W ã·!‡B xsH#f•`³ò×b=$ 굞.&޾ r—żnýüž?œ±YTnW=B³R Áfм—©ñ5!NÐï ™åúÁVåßh¹0¢‹Q6:àFÃ]¨UKH½JBûögŽq”äFƒQZ ãªH ·<¾AººK½Éhª6.ç6—)e$M¸cù·j>”æ¦ežß®Üvõ˜ö¤oÏŽdÝTfîoy·«·ŒÑî³Ð;+ïÍâÖ& º’#™œ ›Eß ‚ŽUuµ`UàiäFËl1ÓçR^à ª—gß®L”Èr`BæHÓ³„û²…iÞÑ”˜J2,ü~g› ÉJÄÐÂÄôò É`Uš0C ™,ú8ü”a")Lˆ·ˆ¼’óè‚€¼Y}™+Õ’ÉsR&r-Ì›¸å™$Æ÷t@ ËÞa†ø.•þkO>H+É 4TîqtÁ+‘8ö8dÖ&ÃËzå–ñ€Vuœ¿#üo+†U÷doàó¡ Èi.#]4‚ØÝûï”ÃûŠ®‘¾Æl½¢A s h9Šçoçÿ"XK(gÔ ™ZpÁ @hN86,þßÀq¤Ñ"{kÇ‚[Û$Ó۔̕•ˆ9,+åÐw¨cÕ¦ÀÜÚ6eVù,÷÷>J]ëŸ>™U½-° :šKО@ŽZD_Ö÷Rñ¯,´ Ïô˜œçî³ð'hí‰åkvÛï5ªòTeVuµ*вïM¿MÚG×v´Œ¬„̳ÌD´Iw+ÕEÆQµï†{Õ¥„Ï“ƒÀϹ*&‡7GöC‚ïF@/`í­ÛÌ;Öl:  $˜DÖ2^Ë‹Sf(ìÖ’zÝš¾–¡qS½‰Rk_í÷e#õÖåèó"®Ýñ.û½$’,Ò&@yŒ ×ñÀ¤'a™F¦!(«Âõö\rßÛ”d¢FùmÔÛ-æh/SªÂ½mðL!ÀÓ;ŠzU<[€>ÿxLžiÈr€@(c€ákÀŒ†[xÓ3áÐ7§êë#åv dgÞ’¯ ‡4õ¦<¿S„Ë÷~½5‹fïV¹¨zô4¼ KtHJ|xY#ÞùÐ8öX€h2]v«— #0ë§h%]Jx½›EÉV ЮC€ï +|2%áXt…L+½÷ZK‚hO%díºñzEþ˜Ž)áûÍèhg¥r{òOÓÂJ~þ¹! ÌÊDUc«Î6MCÛ§Ýò¬·qZÚ<R/YGÕÙÓD2X®K Hƒo.O,únuLO`Š,Òïqø ã»rb “M¬Ýñݤölu‰æêm€¾Ç÷Èú´4BcŒFJúiBjO êØ+aXÉ-Œt ÇܪrHƒÔH€I@8"Ù2¡G¥èÿÿ’|’5b]H]í ;6ˆC¤ª–lëMFÉäíUMP AVŠª”ŽJµÀ§ù~è½OU™ÞJŒ'[£-Œï(Éx‘Cnõö,Æy+-J°Y¢ÆVÝD ¨]UWnrd‚ær‹×«úó8lPo “e('Smb˜q81™o#¦–ÚU'p$Óxwظó@¹) –KÇöÃücj‘ÌMc¥–Ë<¦‹T"z‹Ö€›µ^íJ­Ô¬3ø÷½Räp‹ß·ª®4dË?²hnƒ¬ç¹ñk¯ÅôX ©š8‡<¨äÈ¿.dšköý B©T×/É/§‡;ŠMŒIÖ³7KIcn˜ÈÛx1q²õªnÉfeX×~žÓG¶üøýôb0iäŽÜbhÜH´ÀªFž¶ß?¸m$¾}ç'Aä3¬sš6hÁ4·qp®žOÓµ¼kh§”Éèå£0¥Þœ1YJÕ˜–éˆá3+ µ½9§,§”5¶çÚsJÛ¶0Ï€½v@ä4ÔDàå1µ k”70“?¥£ÈضÀ­ÆCÅgØhŒ.ãÈ0J™Èâ U#jXÁéë…y'uLk©?ÓÜùttUX´ã6h S—¦ÞÄ”FÄËŽÚa™RDz[ÚÔÞ búõn æÅކ^ïs#¥½Æ »OzAŸ¬)Ž€Ý"5ÒÀ¢¦L쟃ìo%= * èª#¬Ä<«Lù7])ÍzU5:ò ü…µˆÜ€Æe[¯Ï+’Ÿ,jÖn²Æøp¼ûZ•! Të]Ö.v¤Ñ‚ñ>a\µíúÜúÔðÎßÚ´¹HJGJÑÅe¤RâºjY®%g;تÑ/úmÈObžxLæõÖˆ¤¤¯„´’Ü’íÓ»é2+A?P½…. ¹ÆiÉ# J€TZ‹RxVWþç3²F—HY‹C›I#8‘Ø8|Y# ºÇ!H|¬æÈ°¬]$뛀Ԓ^O »£A¯@c¡Ýëiðbb²¬”˜¸¥ ⑎HŒŒc€ÐÛç`è}v¯2=†Flóz‘Í¢fqÃÔë(në÷\pdׯKËñé ³¥»€BŒÿ¨wéXn†L)F®Á'L&ÌÃ4£ÄFÐ(5Ë­`%@¨:®±k8"‰ÙÂ2YH¹ö·ÊV‰IÕ€œžrÏ–›p«×³ÂmÒ,x²ÜÒwA¸P¢OÀ³’·¬$3LCוҒv¨%¦Œð©6Ë‘¸5ú6Àę뭘²A#{+Gâº8¤¯¤¥Åõ²•‘4 eŒ£üê«jTªQÞ`R{þªZ VvÀ˜fZŠø·J£TKo¢ŠÑåhœ’_ÊVÒB£š'‰#Lf‡FÏ w @PÊøÂQ„›rUߟ:]Š' ž`bÇöIßz2 &CÓѺÒû¸æJø³Ð½c&cZ¦»è{sí[R/Ì™RtdÅgVô⌹÷¢§Œ¡„µ_Õ—h„ª–s¬½£¬Eo²Ž°_8ölUz%¦Ë@‘æÆ÷« ÖÒnªõºx»ÉüUo·”ÚEZpÞ¶ ÒK–%Ç.Î3¾»Èøôs®ÄŸÛ‚Ll ,‹»Ë¹© O†{ÃZL! ¸/s~ÈQ 5;¶Ì¿ :ÙäS©^VÆàEÇ}€*r³0Ü0¢C‹Õ>“þ›ÈJÄváb|x9Óàly®”!¦ÆÄ”o+Y£P9 b ÒEP¯* ÑzJ¹ù²c 8f²GèóÜÜü›Û&eíùÏJ gU‘¹F´-2>F{¼,t5«öVm®ë$NÐgZW˜€§q™ã(š«—Ì‘ÕUÅÐéï©)uqh³Ÿ>Aå˜XÖË0½#™F2š&"»8+CŸET`ò!áô)ó‘# ÚL|Ð 4â9Tí.ZDLUŒ¡z[Æ›ó<³ooÛ¦ihdJgï篺ùh¤isY˜…©Ý&‘ŽMôS¦Ú‡h4CXlœªhŸøLΊ÷‰TyÒkÜŽ“º¦’HÜõ;bR2l™˜Æ$Ž\K ¬x§ØiOží£ÝqÿaÉ^¬—¡Ù»at1˜Ô(kAbÚ§FY Su?,ŽþºÆSµ%s ·,Xµ[&ŽÝ"@ÀVÉQ¤tÌSž0Ôæv ä¢ÝÎ’ÿüóžkø~Ÿ¦£hRGŽE-‘}9`´ÄËïHŽ“©2‰‡ÉrÀø[Œç¨ô®ÁÇ(s#87¹hw1ÿ{Ëï F(!‰;Öø¹ÁÈÚ· F#2¦js#czè”™´g]¡êÅŒƒUe½ñdñW%Ào<>JŽ+Í xq)žžƒ¯ ÆpÃ÷/.Tuu#4µt%‚‘-VYGL&ùàMßgM¦nÐ"0‘rŒ.ÕZ¶'CLãÂôªÂÑ}õî˜ Æ^/Ð\ œ³ö P²ò}6è¬{ŸZv2]¢MnñÌ]© ލ7ÐÚ#VÒhO†¤憕*±པЮd¢®êûU•›^J˜•œCsaz]ŽLò„‘²Àˆzc”0›´ašxʳ÷½ÌžÍÖÖØ„¸}LibãL`@—ÈS×FÄT’kö9bÒS6×ëy2ÎÈÄ}}{Yµöœ—÷ 4”Ž›ÞDüKšÎS©ÆÖn¥ÖÀô«,rz%bšJVr‹0¥’qkéš@’UµgµàüZQj¬«ÜÂ=eÕ® %ëÉ»r|í°)»5Y 0íÍE zPÿâîsÏý”Q:2Ñ{ûNÚ ¯Ú†”ªÝ”OÊJd­*cD&ŽJwì—ðô¦±vÌ‹««âš"ÓÚ€A/zʪcÄ‚LV¢³½•ï^°AàôÚöy= ²â£Déå[ƒ #ܺA0¤#,ð1.¦Ü<ÀV•2@à¸5àŽ)9;N™›c@µ °Ü>p>64WKüù¯j¦Ë~íàñ€\3^èJ¯W +y”® ט€¦8ý7 ¬5ô±»¯t„){5£+M Dæèb€®&tç5‚ß½hˆ3¯ÔQ5UƒjìðzáJz§Ä„Ëí‰lŸ-Ùh3L“³Œo oE×¢ÔP ú9ä\Ùöa¿ŸNV …µ×#ë½®çmktä_Ô˜IšÖÓôµüÃ;ÒA$€ï7—+ÌîÖŽ-f:fKêÅ$Þ@Kî x¡EÆÇ4h²”|ìÖ›“5hã2‘ ãr#°ÌAcø­Vªú—óÞm>]Äó–és‹gÅßÈVÍÖq|JÇÄk¬RÀ7kéµUØIÃjÊQÒ„-¶_£=H|&,ç&»/Ÿ`žøJÙuJ޽^áØ0žŒF.ê%^>囯Ù÷U¤tä@°®9¦‹Ë˜Ì‰ÃnCXµA«¦ÌG®ýüguÖ#{‚D€IGÑZ3]%GŽ}Š­‹ÇGÑä@ŸVäü'&h ÁµùÛêÿÑvo½²&ņ/¸šá,ÄO~53oýT½Ý±?Ö dä¼HGEFFfU÷Z{Ï€m†ñž¼RÇÜàŽyf&ØôÉžsázb½óÜEr(÷˜c˜´Ð\ø|d|/Ð&'¨ÄÃ$ççø^H–CãjñÉõÒ$“í#”2¹•OÏ­ ío£‘¾‹LôMI‰Ñ…ä#à€ªïV˜þYÀËóÎrw=<7Y$kÕ~ 8wjwû]éhbe#(³ê§½÷Ä›•ƒv8¥ÌD‹È  ˆ™ˆzYÄÉ€éãµÂW”V–<î×?k²M†I¶.æÄÓ4‹ );Â)ºT{C¶‘”ÖÃçØgUÇáŸÛ™qÿ`a \•`s×Y/%pšßáh‡lµä¦Ù’HGd&‘°@:®1@ŒÌ“²È¿€ô”öOY—7Ù׉æCKL†-3fǾûð° 4( ˆÝÑòŽ[€².&ßøÅ/~QÖ¤M­A®`Ô7î=V»*·3ÿýó™¡ä¨©}U F qÙg¤®˜azHËD×Þ ˜`?¢jIœ-\(çxü×eÕè6ï¦ãûË,ªq½Œ#ŒÁ;Ò¤d…Äi,“s[õ5ÊŠl>ª·ïÅ$háÖ’›F ·VêÈıŒ!ËÙ ¯¥Ä ­ gU Ÿ†vY½uáó™,@†ï15úÔ„ï›j™ Û gîHÓÐ0^ÀÌ…’pÔîØè²xÕç,ÇÚûÄJ?sŒ¦Ýéå3æýèHpöxÄJMÁ<%g—ç™U¤Ü”5ææ(à¾Qž³j¶Ú»Žª–˜ÆÉ]¢A‘Ú÷UlP½dµp 5·vJ톆•0BKº`|¶J@-pæ†u ˜L¦!ŽE#x"sXã-<ŸÐ(ìs'¼~*S&…* eG#à@ªúÌÚÕd•°–bV@%UÄpS-Ö±KùÏó˜‹zkq$ƒ„ùøù:ÿ·€šRKŠ #ÈÛãùÖ)eÊzÍË )š§töº7×Î _$«=>X¬ª—~ ìæl<ŒI@Ì@?“‰JF«jÉ'ç–l(^0ï^µ#w8 ·J,઺2iôU½’åó ùL™ c8g-w…×/¤£¿A·[Ùqob$$è ­‚QŠÇXÃqü×ÅmÊž·åÇÓÔ 4(ç¦-_ÉÚ–ÔÅ #z„4J@·PÒ®Z‰§cS'3!¸6'èÅ J7 d›F‹<ÿþ2%¦AYuTÒÕ#¤TE†iea¹•ZÒ‘­ØE(áÛñ/ŸÈÚkÉ'%ÜbF³…çàˆäŸž­ß¼7ohÓÛn¥˜4²’ÂrÊd†öŒLih+95î|$AÁ aâI3©ô¤ª‹¸·¥§œ8CÕB;F;@#ã$ŸŽ2ž>™ŒqLŸ’Œ&>™£5ä6$³9ÌœÌQø÷Ÿ¹e¥*ðȰ<‡l1€Øòzi0sÀ‘ AoåëÚ&Jù+­Ú¬¬*}ã—¿ü%B“t*slEG|¥š»‘ “3 ¯ttw{©JÖÞ˜ZLT‚‹x$ 6ÝjLÖ5iýö½>¶9ìÕRöïjt³˜p0hÇÚÛá)h(O>²{‰œçF¯* >dJr½˜³#¡…R4=|mÎ5W}b¶‰É`>½d°j@u&U1‘;ºQ>˜b‚vkÈn‡!Eäòµùô ŸgwéÙ{ÆFhl€8@/‰«Öb(F½ ¥’?ºÈàJµãÓ$N9$&Ãz•VUz†eý3hî:gÉ~±:ÂËOA$d³06”› 4´}”„qÍ­*wŒ§wì¡2‘•4R XFRFög-üôyýg¤tYëya¡G~–ºÏ-ž¤½Üê“ s™½f o‡)bè ð®œÑª>l|2 OÇ@ž°è×®’I-aUn0‡V…Û¶)‰É€õzh²ñýIC´L-Uñ3Ù‘I÷êçߪÏÐ+÷ÑFʦã”S¶9l -4ÄéU“Õ»Xi[Y I&jé ÍÅWÊ¿lV€²½€”ùhÜ 0Î)xv$Žá™3`nþ‘‘m.àj¬«F| à1°\4%[2‘Û-@é¢Z –M)tmsL›oDžÍݪµË"R£¹Žü¹jWîRL½L¿ÆHšø|¸É~^(Uss|þÆ´jb‚Lä@ªŽz]3ÜDXÀUóÁ$›žOï à1Z(ávVM07ïЫb"ë²PÔ®ªÃP~:+¥‘Oa´¤Ú"ÇgëØß³ª½¹ñ„ÉæÂõÒÏ+ЊwÇå†qŽ<í£±+7È?Àéív@·SJcœF»#,Z©¹gœ¤­ 4À­˜Ü‘ô yÅtxŒ.Acؘîžz)Ï^ïÏ£#>½ÆJŽ¢‹Ñà›ŽL€„åxC`èe—ÅWB˜îŽHÑ8Y/¦Ò°ÆJ›NS5q+µ0% ”Ð'Ô\Ç™Ã-pé 0ùÛªjL¥”ª²ÒõZÛÀ4ªý±ªä÷]ST EªòÇLfÿÖàˆÖ KÙ]ð4œÇsSUÒXv\ØÓÑçƒÌjWÎA~zA#-~„dx[¥Ç¸Ëž=MSBcòòéʹiÁÃu9nh¥§§Ï-E&ªž7Ab¼*~Sò÷8#|³âá®F9+&ª>t¤–4=Nƒ|1”ºr†4ZäŽ<í#;²ª¥ïvǪS2Ž‚Fvl ²My¶ÃÂÐ^X™h‰·0¦ÅTéå òù/Ÿ&ñpZÒtÌÓJm…ܪdñÀ³7·vË\®kǵÌí¹7¡*”úhšß&ª6ü°›+k¹­ŸÙ³`r–œ×ìcfq'~º LÖ€ý‡ ›­½®ž©U4 šr€ßlYlbÛ¤ ;Âd5ö¹Âëšçßi°¸sÎìÍåfÛ~Æ`dãkVCÓÏhtÀǾèr«ö\L„ÿ…dÿk™ô=o#‚} 8#ó'»’Oßd|C3ܱ9j!PŬ Æ”l‡É è“ÉY=MêÅäßH ·z«î˜ s€^¸, —1ªr¿p4ôZÚ“ HŒw\¯ªhg"þ xÿ*P‚¯äõŒ“›ª#CG@¶€jäÚÏKåeÑÚÖlüÚ¦$úV¹oïçT2>mölÙr+YÆË¾vrúHž”ýyH "]0 £½¯àZTu ¿N "N·+Ǻ²ív˜BK¡Š‘;æÓ-0C$˜mJ/ŒQÝ«ÎÖiD? 2‹XK²–áïØJZzÀÄžB¯.Yµ¬¤ËQ¬VÜÊ1²v‘¡ ªâ[ÆYoY4Î&¹å<+¯ ïº*y%X¯R¿Î1R&ž•AI)Ã4x£«zpÑ&ô˜zkTm1#0F§ñÚÛ$«¶¢FȵÀ0&bZ¾Ý(•ÆäO)à6?¦÷#À4(ž¦q P’YÝîóªaØtyLâV"ëqÒß[¾~¸4jiUXôtþÞ€iÑòÀ4¬:ª"óާçŠ[@Wn2AæðÂÜô@˜áYè>òd5æPNV/}xÓÏf÷KB¯*÷8Ä4fyÒ5ò'ng™ # ´Sb˜8¶g>-C¹R_ÕvÆÀ1)uE–ñ¡š&,GàÛ$#çd€ {ýöÚ²6 {ˆtåC3°ª+íQˆi”œÿÈEŠö“«Òó;âW"®Z×x$¬ È90ÝŽ-0ó@lW ž®‰œM2-É»;±/ŠÐˆ§ò+ùåÞbß½˜J0ÿ9“9®¶€ÀŸF žÀ¤£[ÔBóìÂôÇŒFJ¹Y²P•›ÕVL{æÏ*O²=WŒd˜p¼R«íÙó>'ÂmÕhJ¡/t©öàÈþpÅ' Ü·ïõ:Aí=~+mgGκ&Ƥ—ËE2¼qôrã0‘Ž€¬Ôu`@û•œÿWƘzíÓû;ÖBC™@~&-ÐÃzÜðs<1C`+eˆ×û[É6r¥”ÄEãˆÛÍñ,ñ¾2±F³ø(‰Ú·-%Y©›ô8•´'ÞÜ6¡ùô¿ L*²°J˜Âkno.M’#Ï:ïÂlrëÂxY—ýÈæ)îðómV¥t ¤o¼H£ ©*Âôp2²A>7í•äkvÜcÁ%Æ”œ[•‰ªÒÓÎ ¿Fcì׊^/@/RÀ‘Z"[¦wSÅ +Áícˆ‘Ns¤7úø÷P‘ô¢q€êL0¬¬š&<haÇ&"瀌ï;Â2Ÿðö¬«_pÈíÓ †-6óF3ÁË}(=B%+Á‚§ 4ªrÇåm ïsϹwË–! ÁÓ‡ìŽzýÈm“ø3þýY+ G£»Ÿ¾Q€z›À”>< ÑøÝÙ±F˜Ö–Ì,d¼£*ü§ÑR©êf5Hž? Z,Az» ÌM¶ Òð” RÎ 0B=™Ø†ôµÄWº{ÔÏËféê)2”+LÊõÎó¸¿P•›vÔh®£œæì¨4ÞQÔ¯äA¶† Ãi:2TôdH³XT [ ó Óµ˜[âÞyþÁHë—•õôv·ï"S¡D3=q¡¨ª Yè’«¦”ùËõÖ#áñuáÝ“I>‘Õ¾45j™€†!F;p›Î-DíˆsN9~28ªquÁ+51 q<¹=`«öiÁ]‡`7B.ð› ãùA@&XÉUzLûÈ>Ápƒr€Ý"“ ð|>•dJY´#tñýös®WÖ(®ê$ºD-J𕼾T"« lZ*$ÓBPV…EC{"d¼.ϲˈñ»ã•Ÿc]œ«6"½Á¬Y4-ƒôÃøÞÔ¥…•ãYôþøÐ`„>+¥¬Ò;jàlp7—ýá*4;Ö"“±uk¸j³d²LÂYaDb­Ð,ºˆ#Y&SêUÍŠhÛÄ1Ϭ*´ KjW-šÒ—ª)-F©DƒTÝ ’Œg|†Ž­:M€þN~}¾µ u5BcCIˆøJôÓÔk–€E—Ò’† ²õá aþ¢jX xv9¦$+ÒÀ½†ê‚Øo!Ǻ²V:ÿ°‚²#¡œ"²UÝÊ*nÒBÚé3ÁÐÀÞ‘^N?[Œ°ty[ÖâHl\VH#»X{ÖhVzY ·‰FSüx4+>eû s0.r‚@½«¶Uÿg5éùl@ÄÈÏ‹3ÌóÙhJ¡„wL##µ#EGŒ»·³¬* Ce7É ÙQ‡aÇÛôéËq'¼þöÀ] à O 3ikô°HÑDJXn" h‘ÛpÏ8MUÊ9÷àcð¡Å”FT•E£É”È2„EÓ1d®±Œ­0MÏ¥…À±YaYÏ“^8ƨ¦éŽJ™hÁ(ahˆ”1¦Ï0Ob ÜÂÛ­‹+U•»e#š‹§„å”ÙF‘ŽmÅ$&¢#&27bÇžŽnɪjÜæ€#¾ð#œ¾ûn²°Ì¹qÍÒ `Ìm£hÊsÏ.‹¯EÎ3¥c€Lp¨—&Y;Ð\û×^n€PÚz1Üônh|nªUE>Íí·Ù•Ä•zgÌJYLÐË\Œ§ñnޝÕãlp¦©mï¸ëê?Þ×&ŽJÄrí˜x†HÑC¨vÌS&‹±Š_Ya”àÛ„˜™huJŒMfU;‡6¤´F©+pÐØC#ã+Á”¢q@ksVÒEIF Šú··Hb²F§!ÀèRjmÓsh–jS(J21ˆo\×Ißtí|dZŒðÏp~®2Wt=³£’¢Ñ½ ÿF,Ò$îÈù6ëרíòWÒwL YW‹ud(02·º‘L ðaœãí;¿å/ŒÑb‡ª0 ã›uLßj&sdž eÔ(”„£öFt#zJ%L&Öè(ÃñYeR‹Ï¥ïO²&j© C WUn|AO);ªNˆÜèí¬Tûs>”]D ˆÌ\c]¬„£ÿ°W΄8LJ ú~"æ€Ì¼ëh!&“•<¬“3q$‡þx¨Å»qhgíH™’^»À°Ê­–4|"µ7—x2U$Yà šU›w¤†)×›[¶)¥ÂQÀr +ç“ î;àx†ÝçrM»)Õ›Aþ½RÎ˵×%»H_<¸ö3»³‚ƒ`ıgª¡NŒc¾Ík6²I²˜F5sŒÞªÀpžãÝò\÷ý)à[’§Ñpß¼ö^°Ñe¼ß€4íÐ¥¤àŒ´¥8#ïÐØ’rÕÆu|N•A©EF¶[&]–­€ µ-£ÞŽ™  ¥”»~]d‹ª|Râû’8"«"7=ÛæÂ¶rû+ÿ HV^n³ø–£vd;ªb|0˜f禷e¶˜H‚<[ê"fNOè?`4/·L°^ïEàüµu!›ÞWih»Éµû¢sËòFÓ¨:&n‡FÈ3×n.ro]б•Ú°!ŒH©î"‘r Æu”7 nbßJ‘2[]² “5Š ›+ùß`È¡)]­ÑªŽÏ®½O¦”97d%½bJ¤£l™déû ö&OMx 8†µ·[>yÆÈ]–8\µ¡HW{®©”x¸Ï.ÿæµ¼Og\#zœZ¦dB©e™ œrƒ")sK&4"ü| |ÎH`ÊñYqÎ-±ODhiIÀã‹þrJ A­Z£ªh@°ÈöÖÀ³ÔHÀ0¾k¹‘UoO¤H# wd›!Œ.úUdÀ~*á†6ÅQ´\Üñõ/1õ·(GÑ*²¾fG0Ž¢.Ù6•rPªOš6èSQe²YaÊV–šÞ?Qî&í¦Ômõ6EÆ,È8gXoxã\²»Œ¤ñHa̳¥'À#•º¬,z„Ût. ôÏєϸŽCúzgŽÜWVÍ àÓh½ºðΰv‚@ûd˧Wr…–TòìJyæOÖžþ¼¶ Œ7Hf¥½#ÖË–ñ"ó¦ÇÈ)skœì¨1@3Œw”+ÉÎHV)i*•ûálvv#?uû÷ÁŽ¢§cØ"[¯†Ðí…ÍwÍ<‘|VjG9—·€vΪ”a%s 1sp$–ù¸T˜ÞÝóOÖÚôx™ Mb1ñöÁàé1gàž¬ŒTuqèÚ0ªíP#LðÜMKÊÇuÑ×ø´%Øþª>yžZêÚz«ê²C“`ßU|ιÁdá†æÌäÉwëµp5ð©«R÷ÅÚëqpU KòŽ51ÝD6‰‰5ÊédŒ‹‘5ÙÎB Ó7Ì1YyCiüGª3ÌŠL ßD9­ÂdµltÊmÂÄÕ-Sbò!Vj™0~ÎÓkWrÀ¹á×4º4ް ƒ{²µ#Ù¶* Ôkh‘[l¿OÇgËP„)9ØœF 12’U#rCêÚŽJ2Ü,GÿÌéçd÷ ô{XР˺ØÂÂk(ÝuNj„M<ŒLVϳ\Ëî´óÙq¶ÕªÝ…ƒ˜ùLò÷ªm…á& ;”ðdÇÖótù7H&«‘'@™›¬$èåÚé8ÒÓôYä?²6 d܈Ã4)cZcÿ?)‘æVU2Hî8ðÁ ó—E «fHéySÎP ’žR`| ÚJv‘Ú•(¥v(M¬Ñ¤ƒ…ƹÕBy Î¥2¯ „™lV÷ÅcÚ˜+y‡f±™Ì?ú.Òãªý|ñ$pº‹l.%¸ÅWrlHôÃ¥&82GunK¹ ØMdÑfHvŽÛ ŽjìØ£%æ3`4¥Ú>gŒÈ\)O¥4JQÕVª<ÇÓ(õpí¦”X¦éȹ Ÿ>­Z#eb²^È–„ÆL‡±¿ÜQ‰àèîòfä?qú™¨ ]˜ö-›Tñ2ŒŠ•ª"õj ¤¡ï: ûEœƒã¾ pkgÒ2Y¥Á´ñîÅœ@/·'P¯n´Rz€‰7]y:âE-Ú•0üa ²mY±MpÚî’ÙvëZe²&š’ £‹'Cz% KµŒ£0Nö ¤Ì$7íH¥z‘)#}:µ°Ê3²Íù´‰þ¶¾îÛ]Z@®D£~êU¹á‘°Æç&Z:6×wC{Ó1….ˆéYñìS#À¿î?ñ-£ ݽ÷Ä\ËS­}WT®×¸Ú# üÌsÃàÓh„yF: GUb@-#ãË€*±…sH¬Ú²R]€Fzd;¤ARÚÁ;×Þ¶.2ŒÆ>‚ÚÓÀÍÍÙŒj¤èˆOàØÄJçÿ@5 0Þ1¬SRXVr¤éŽ@ú6+c¥#±ØG2äÿléEð"%ÐD-°ìÈ¡gêÅ'ÆÀ9äÚeíJFo±%AC>yMI܇—¡–Ž3§Ñ˜žF8’ÙGä‰!n‡ze¼–Äd}ðdµÈT˵#…ÆòzxÁÇžþ¶‚ì=û³3$7G˜F~º%ÃTÚ†€ÀËi™à Õ’ÙoF¼ _K¶edúÂQ©Àµ³í¨¥}ª~ÏöWTG9[`ÑnnÝS°e²GÈ ©QôÔŽÚ½U1ÂÃêÊJv$Hon[9"á@ƒ²Â“‰ŽYb ½£q-c ªœHÖ¬”Ž5NìˆTS¯Œo4  Vr);àÉjL#«bÆW•±#¥ÑþÈL¿#rn±&&ƳZ`-²M‘ó‡ée8çF`süJŽøöi%úù;†e¼O¼%ñMwLS×feû$É|!MôªÆÁh ¬ÔV0²²)=BÌi¾ÓPY ²%_ÿ- `î•éå¥:ˆìYÅ»·Ÿ˜¶ê]é5¾=d—qn.ÇrãªÚ‹QrôÁž@˜fÁ@ÎÀ³¤wú‚`á.¸R oœù@;ØŠmÎJmkVã2œ`‹% ¾UþZ¥•HÊÌ«ÎÄQ©ªƒ`àrǼ×Ö‹q$в}瘠.íB#¥hzÛš+”+ÕE ‹Õ<}Û9‡ô9#a1‚Öˆß2 äÜÈÚÌD² U1ªr?Až´•äÌËÚ¹©úáîRãS‰éÈ^8Ê»TkqP"–Ÿ8#°ëئËÝ=%ŸºRʆŠ c¥ê8¬ªK¾sNUI>m·q—µƒØŸÁdÙnßIÇøÍjâÈ€ö”Ó7NÕ½ø Ý€‚€'’ sŒ=UûÜ·3·nJ Ë[{GŒÐ«‹ÜrÞ,Ç”z1ùD&kù¶Â /–³.¼˜§ýE1\µÜ kó©”©Z/íÆxS0ŸLž]Jxš&ª"b%ÕÚ«ÊJY¯¡­š ÜÑP¡%ÎmzG&9ÚÓã…£F ‡@$±#62@IDAT±£xšyí ¢ñ2€ÛD ÆQ# ¼)H¡‰Ì<\&8ÿ·€²(·Í\€­7ƒ²ñ@‚³û½dëÆW’ w Užô€hËù´eCŸÕ0q£éÈZž+á«V".,lÕFSb|½tyb‘,óœÛ#T妫/#¾’£Põ)Ê6ql ‘”µX +²€ÜÑpèï­™Žïç0‡LèEL³f¸jæÉà­'PbnOSt ¼?;Î퓹#± ¤é¨¥j£áÀµyyj!^KG™X̶RˤQªª—mÇüaz¼ÜæZD2|8ЕPÒE©š§ c„j¯Ýǵä™,R—ép¶pΔE†­ñl¤Lœ>s-}Ü”µ´¾q¹MŒL™s;h0µ‹AÐ#G6&3¨RJÿ‚Â>Ï‹ÀÖî?íH\• ž‰v½HŒÌ³#ÜhLÿ Û 2|ÓË9 V¢)Dæ•bR6‚?¼–”pkh)ðH8öt]Ȭ«Ê"Ã@—¡˜[c ¤l+¥}-|ˆaÐez&åJ°Xìç—¾Yù XÍPrÙO?p—a!R”cLÒƒñ©?oÛ`-¹‹w?+¼ïãh„Ü­²uâÃôd%‹a”z –„«&#ÀÈ}M2%]"%Àmå8¬×±ôjÜn#äISpÆ7º•0J›hGn‘eJ>°œ`_ôm¨ä¿¡´’jÄæ ˜¬ËV¥¬Ä¤®,”Hkø(õý¡ÂÊÂ=‹ggHÖ%2ÑÏ<2+í4ðrS0}£ð gR—#ÏÄ9ï¨ÅSä ²ö„’´„·gÁC`4LC‰TÏ\éXßHF©‹e]U‘á8s2G$ ïè6qÓŸ&d}èm»5øøD:¶jæ2²eôn«Þa‹ÑÝòZ8ÔÞ¶Ì 0…£hÏ”eß-}%hÞ×@ny¥§ÿ–ÁçÖ³(1ŒÄ[R`8ôÎùÔãÓ7Ú± LdëÉ“ŽÝš!eæH Ô»žÙˆªÎÓÚŽ«Æ1¬½|kÆÁ…FÑVùhtl: 1®˜Üä‰{4 ™¬]  7èÈ$fU&矰‰Ö ÏHÛÖê>޿ɖHæH&–- ã)?KÏ)ºT@ßM< Ý=åŽÍJ/wí6©Ë |Ó[X>ËÝgЇ‘BKL†ðœ›‹!†_z?œÇèñ¤¯™›# e?$µgu»_œØg_Uc¹/v«bÒÀ‘ø‘Ž~8§¯‹I²2=@C ÷ÛßоO•uÊæ:ѳjè<‰ÉäÚñŽUk)¬1½ì­šN_K&{ä¶Ú@#¶jÓÛ©‹@øžô_alŠh–¬‘¬)O2¥RkW‚‹éÍ‘gÞý8½b&°çUʫڹµ1¶eåî°€+¬4æl"¥RŸr2xÎ h>ºb2™¾HŒÞ~Ň•j‘ ê­—tlÊ¢­ŽzûRmP+‘û§‚J2Q©»È}?uUÕ%æÖ¸ž¨R½ŒªF&é 2qŒé©½–4ª)eiO>4pÕ”ÓÔbáMìPWJ>&ÍÚcš¢¥jŽüg ;#9'(cTE%ß Ê×_ÿ±\üÛ`’h¹ÙaÈZEvÌÅC¤éEhj|V÷úm Ógh!‚­›ñ4­Þ )«*]‰ ¡4vÀ;v£Ì9×… ;dõÂmU/Þ¾—xoÝûèM£*8Ë~ZÚ92[¸Öå¶d›·1î ††:öÑ0äOàØž â •ìC˜ÿwhºÚnJF숷؜¢—1¨1lL€Äȶ`múöÈš dßÜm¥ ›$è©×Þzö²Yô[¦‰Ž{±pwï÷Fð‘éµ›%›…ôÆŒ'K\£^ŒÑ­×&10 XlÛÚóAHÐØJæŠvμ=•rX—¾3Û9YØ €L o±üsõöe˼/3F#±ªF¥<¼j;;vG %±’£¨Åцp;$`‚‡ëª¥gW"–­‰cb ¼ÑwÚë/ÆÈÄ2+³º&€l ÎëE6EfÒd‚Fž•’ÑŽÆ·ÐzÊd=¸™X¨v»l1U;jIã˜OzÏxšß?}Æu/ƒ„.?Å2ÜËÄzó‘GMßr{e ]Óµ«æúsìqW;“žÛ +•ód²7¢7®…²ÅÃbž5Î?Þ‘’Þ—“Þî«vü2`)sk·à/l˜ÌQIõðU¯éÀ°Š'ÓÛQîîþÞäCê¡rVbg®ŠëÅ»¦_âHƒšÎ AÈþ?úº»ª ·OžÝH{÷mI¤ebr“}ÃTÛ'=\¨f ´^GU]ý;+˜aÖ(óTõ ž¥ªFÀá˜yÇp$,ð€Fí07™2OXì"H8M³T½áGüé¹Ï¼¹&æãØV}«f.Ϥ®Žõ² X0$ÀÀñŽF;Æ3Á÷qoÃÖ˜&ß(-pÇ^I/¡F ˜¦AÈ~]âk¿’ƒ…jJ-L,€4òÍОù×V=;€ì›CÃ!ÏmH€w¬W•†ÞíLœ@™&™܈’^µL@6 .á܆M7å)Prä¼  LÜÚÖHxû|ôdíÖǬäVʧUa@Ô"ÛI‰ä!fsÏÿ@Ö·ñÕ‰Ñ#rï) :–çõä5v”kŸÌ>¦÷õe¶2·4Z¼Ë)¿£cÓ[’2ç$z ºg>ŽÄ°hŸ9`4jÙÒ óÏ– c2æZ£Oœ¡#àK£ø:æƒ×(×è“c˜ç¦„‰sãS£P™gnöëÝF¡ë}júê iðØ>u©*¹õÖÈꌼ-í3,ð²¹r†s>å+Àhá€+É0¨ ³’2­#ßrr{bŒhÔ¦`\éjÜà«:³æ†áShJ¶^o‚$à³ÑÍÂàÓÏS)YÕ&Ö»ÜÐJéùtltúª°Æ®Ÿ ÝT;*=v‹Ì™T’[RÉ?ç&›žÆÅ»;Sï–¬½L6+³>ø·Þž([Ñeuùn;c(›X¾[;ŠJmÒñéó4®jƒºQ ´ŸZÎmß?V’LhÄ‹Æ×NÌŸ¸ò×OÇZMÁ¤iG³äFpƒ—)ûìÒ86‰ýLö7’Ì4«|v22;À)0¤²ˆäÛl€8k¹ ŨöÖ寧 ñ4Àd=eä™t aƒ1+‚¬èž™dâØ‚#³Ò…/bà6qŒOF‰/`ûz!ë}×__P¤ [F©¿SwqÎøœûÜ+ô|³Å[©eªÂü= lÄ®¦¯Jù!Æ71ÛÈÆÑçÖÃ")aþ¦4‰1{Ø>ÇvPÅg.#u1aå¨*æ7«AiTÍÊ ²»„ŸU|ã2w¤yŠÃãɶÒ›wAC·^¦ly q«v#¼A½@U¹À«öifÛÚ[Œs%ídºmDØ1s ¾H6F•LdEC chê•kϪ˜ü)ÓxOzásÔ‹ßbæ‰'Cjéß98Âø¬é S\ èHŸ[VªŽÞ!ó4ÄÛ„ILP££x3Qš^{J½¡دî[ÅÚ6‡Ö‹ï[²ðÚó§òiÛ¦—)3¤Ö»q˜¬>‰a>•z¢QºQš# ì"Uc(E¶7â)cdL¯zþ ”8ï="¤©@Ïšæ©„‹Ûú)µkJÐ{µGG‚âŒÑÙÒ‘Ý_‹êL½¢–²^Œ»zuµ0ÆWÁQ—Hè™ËdÓ¨êåÖ“ Ýn{º|øï:|‚@oÎᑵŎ€Þ¦t‚ŽUÅÐtl=G MˆALß”œe×Iƒ0®Eµ×pJiàÜ002Po&rÏ…'«€•˜ÈöÌds;–7ñ9ržY-¦*`Õ–|¶Pª–Ó¨:Ê–ñ÷&[ùɧ©½*âd@+¹;œžXã†v¬úeê3tås&Ì{^GAÏß»Æ1HËw”[©£¹­Äg%‚¬j4W ^c‚nʹŒL™8}%LþvókIIЭÛÖqkÓT—‘FTj4†dÈr»É1<Ôî”Û ¦„#뚉^³„ªPÅÈpn¾µ#Å‘ÞHf $(Ïá)3«£¬«œg8«v»œkLŒ­ ¬´Ñ ²yúø&žß¼n%û´fÃhšoûÚmd<}Ñ<½Ï.˜¬$k à{c2‹r 诘¾LûâjÙeÚPæ@I#BµáÙ:¶!Û¦·ŒFkÙÇÜ 0}-azV·ï¤;íÕ›YýKá|ˆµ¯Tˇö ¸Á â#´»—µ•˜´ >å3wA%²”-`²¹ÚEšvÈVŽTÅko¢#Œa…¡9ýoßÇpgðã·‰•er¾’óà;]¨%[ƒ4R¶[1”"~sG‘lB{9«VŠŒ‘]côÒ‘Iº,‰É|%û䆄…ÞþyÜ?#"Ý‹ ”y.7º^ ¤tÈDïÓ”Žý×êûI¡¬ÄÊzèýËÍEÄèëšy]xŒÈ°¹µ œÄßgb$€×Øò2Po]œ·XSÛDoX/nÏŽaЈÖKƧJ¥yÆsh+UŒ¼pô)hä¬1sU-"Ð-à9+5‹mšªÜbòu: TÕì¹ÉämÞЉµTÒ‚T°Ð èëwÞ¨e5ÒfSP×9¦ß¤Ñ›±ÃÀÈºš´¥ R*ó)cz\ >†HA0ñi»¯Ãß•|*díÐ22J@fKÙ˜Žñå6©EÎ6°#Ò”<™„S ´°­´ÄdJ­AfRËS·RPªæISn¬«&[-í¯mðëÆ,]zé᎙¬%žã{Õd2«V5³@:晜Oõ²BvYhÄÓkoÃ4²?øiº äFÀZš(/2©‹LËÄJa¶6é(´Ãd¹©Ú6±l¢\ SÂe¥€AÈ~^Â<“uµ2±6lI‘~€§ªGØb_ Ù8¹Vgž†aoÒn2ý^ÕQPæ }ôñ©Ò°"Œdñå>âzŸ×a؆dñz™;ÆkiLßd]ÄxOŸ¬ÔzUÁÇÀó1"%Œ‰Ì¾ö'‘k‡6ˆ²ÇdËÇñúŒšž•#Ç?cÞoþ_ƒ—‰ÿшèe| äæh7ŒXK%b½²Ø”É”Î7»:åÞÓ¯- qO/[¯’ß¼ø¶àXµu>í§Ê‡@4·wL4B/½ÜÞ4¦``¼¬„±‰–~ƒ‹ªþ§v—‚Û Cé˜mJ™yÏ~åÑ´^«C/hÄ6„#ÉÒ÷—>GV¹%>Ûßýé1ðZ2^lí¬ÝñÚ¼~{â÷]çCC,>ûì3G€@´­ãõ;iJs[¸7¡L&+9îŸÆrÓ‹T²&Ò€ƒêxAT%.4êzJ,ãi´œåÞ¿qµ£Ë‡ÏÈŽU€ Pf5g ç¾'ŽÄ형²0lUﯲ*²^ƒöMË*Õ>¤k¶X†åÕô ɘOj³¼o¯F€Ó’@Çvã‰×…Ïß±O$2ý‡•hÒ[›ªLïÁ8GVm§ÔR8 X‹¬Åqþºº‡Èüã³mÃ|˜<‡Rºx›èÍœÀÏÇ1lŠ`ë( Ǫµ‡Uܱ­`o\²}äø+Ý.^žCâ4×þøÀ²åv“c\H6q ?[`‘OSÂcö7{RÚ_‰Rœ›è÷z¥ó@Öçp‡m $`mÛÞ€>ãuѨҸÌ0dSŸ†dd‘yÕü{eÎB5A¥ŽrúfñoŠ#P{·˜=œL{üªÖ Ð.7B‰­ã‚¡Rwɪ.žçñÉy :ÊŽ¢…ÛÊѬvKc¢/7¾ödÛçôß²6úxüþ[Úãí u„#e ¨Rú”Y¥ìúdŽpzbÓ‡…A™˜¡P¢”ÒA€q¬K®OÔeÐ¥ÏQÀ¬€3ò:ÈwàëkCП̑ÉsŠ5Z ù\»Až´ ·Fì.HÌ^ ®²F€0]ĵt,§ïFÖÀÛÏÏ¢š•ÅšÞJ¬È”º#ÒQæS{æM$3( (u_8ó–'”d|þ5ÊÏ 4Óô¹^%G@ʰ#¥®ÖkJbz§/׈L?1½è l÷å™ 0ˆ̬ 9gHn L“²v؈å3ò~¾µcjG6WHLïFjA:ÂMqü4-,‹ÌÛíøÞUǬôò1¥ßŽJÝWûÌÉ„ªŒý#ilSå6FÔsÖ¹O‰œ¯Á™Ž¤¡' HïWRÎÑ­ú!'˜ƒÑ02«+?z@I ІݼúKaòÜÓï8ë5‘ A4VùÈŽLRö)"cÙ*a´0y+I̪×yÖ¹p3+Œ^™§Üb=]w·@`¤œmÛjw̶Fnr÷‚‰[¾µé‹Z¦ÑØjÎÈyÂ9$sDÂÝ‚[GCɲ͓C-Ä>šÆu¤lÿXV¯®]€™I‡ƒ˜µ´@]J‘2LÃh[@´Xíø¦g[Unzž+9º…’‹´¥*¾qJ1rªR:š’'¦ˆ'ó5ÆÈ sÀÃ4Ú#ñÖòZ öôí£T¤T¢y~èãU1O@¯´Ø°WÅ=x¹cüfñQuä¬rÆäÙ†MÌ¼Òøua”¬°?rß™ÖhY·3BÔE©Q»oÚ¬¶<^b%O™[bXÀ4{‡4µpÖè(jI¦ä ÷ï!®êü¨²íFJù$v}Õ|dÇùÀÚûôJ•ÂßøÕ¯~¥A4+²n ¨g¦‘ºb¬^»1 «&fÛÃÉgÞH ‡3ø~üôÅ[õúÑÀU·Ò‡JSZÀ‘Oþ-€$‰±%|›«&N¦J¹J˜xØb;†éE+µFû÷h+õ;NɬÄ<HàŒé©™‹µhܰ.æiðg‰ûÍV8ÈíÏ™Ø>€ñµÇwúßß] ÅS:êÚè'¶$®ôJŽ0Þ¬z{J%L]4-ÙEKÊ‚^Ì?Üx€ ¡‘ËÕgWO¡Qàë­½cæFišUÞ/Ðõ’ †}‚aþ¢ »2†¸‰L„cŸBKÚ;äIà­ôª GbÇž…[z9db º‹‹×›¾ö´Óä ÷ÙuTʧlænÔ±ÆòYñ.Y AŒAÏ…’ÜÐpzY»Ñõ:¶Æ—Ý´S–›X—ÏÅ’]Pbå8ÿÆáMlŸ­Eiëiq$5ª@ß^üöIì¸Pmh°FUÂnkËŽñÈœc”Díý½Ó±Uéñm›…ίqO§€Óù’)ÁÈ èníšÅmz%úòìÄ•­«…?·&ÊJý™†¤'µË0RÕ)Gæç ( |€CoÄCT-w¬j“­AŒÔÞ59Ó7¥[L—ʤg{Nðéž’•#“œŒ¬Ô>nÉŒoeÛ’µFÐÓ$ƒ•âÉ#„µ•b(1ùÃÏϽ;¶yÎ9à90gÒ½Ã9W:“ÞÿÛ*F»q‚Œ„kLjvCÚÀ¾ÐmKÌâ45¶a˜€ÌD]ÝBVÚ”HG²0¥®>ÍvÀï‹Ô­³ÍF 2>B—,IyþÿøÔB­ß¶QŠœ€”Z¹öãrC• ¨vmÛ#û-ÙKq£‘ûÚå“s¶p¥¶gU‹¼Ñdpãâ+eˆ1:Á˜.b.C[y@u>@šz•L!Ëfå– ¶<CJ<‡ªíVoW£TkTŽr³.÷º,^DfbJKf¥Ô8¶[¤%1®œ¦Ñ‘L|.xQ×nÚrÖâØ­JÆ¡5ÖK\àïʯ*·ƒP¢ÄûXa ä©%ŸÖƒ-FF «^Ó¢$È*áa·s$K\Æç@4õÒ»f¶Æðj±pJ%ÁD’Þ±€F(‰Ú‘áËM:fBÃDN–&9Ûýj6+= cXZCyÁßú[Óò âa½&‰¬ä¨^Âíܸv½[@¾=ߦ“Ú¸ræ>`Q©®Zrëv˜žˆFZf8¥#Ðþ›[WbÛ¶0’Ød™tln;¬Ñq?J¾¢”cêÕ-T{„7—ÀDL‚§l^ w¼ô«dh³‘Ræß&vNp~1iR&"O÷í¯nL^.ÌèJÎ 8YÖ”]ÌÈ4ª@G%G˜ÚåF¤÷«•*±Òª@ëU‚Ü­𠀿†Ø3!ázàkgÛGkz ÜÛaŠL¬T5Šle˜†­•ÎÔô­ÊÀq9q‚z3o&RŽšâ‚{ZÃ뉷ÀÓêiH&Ú¿@òt´µjÇpï „d[®‘“[]µ$†3Ô¢úÍo~Ó[Égéÿüç?a¥˜|zØlc<]¯—2·9›"ñ·g$O·CnÆD:"는…ú–8&ÛiŽbûû8b(͵s¿(»™#C²ÞœO]íßMg§®özÚ›¸qô}Xkoº.‘¸MäÞĸ¦äï˜ YWÙ‘•’µ[•ƒRûãašŽ4b†•bksŠõVm%Ǧ$sä zÿžÑ‘`/ÌMµëׂ!H¦‰˜F ;Ú n(C]x + Í“=K°à™ ,ž›hïî4ÄŽd·ï¤>M%]ã7:Ãö!¦©/’e«D–Û±­l3äFŠî¬ QIé8²Uvìݱ¨Wö^º|U9+ WàJdÁ ð;iu¹ ‡ešºd8ì¸Ûâ¦Ñö²Ýè¯äŒã©_; ‹ÀªºklÊu:¤£ÞÌ)Ÿ¡% =™¦²MLÃáYM†iôrwïñU·[ ðií@Ó½XϘ†Uw¬×Ñ·¿c£7ÑãÓ›óvTÛ_ÎÖž`Œ–oûÛßúÖ·üö‡{]Å?þñßüæ7Ÿþ3e¦¤¢ûiK}=©PÝ SÎN/q&a9s£É2 g+ËFÇËõ.÷«§0Tí†U™ÔÅ^õú@Û¦d•,VU"1ŽÈ”õ&“uÕ8Ïô³Åó‘Û§¬Š¡ü¾a.h¨–l (…¤ã¹ÌÝ Içïè§”ÕëªÓ\”¢A^8r½J9P”´; z¤h¥§XÕ¸œ ÜÈVþ¾ÿï|ǯ§ÛôoÒçŸNéÿ¶¨v½°Y}‹ú—M¯3Mׇq½x²nª–g›9Ûª²’Y~ƒô¹e‹×›&‡ s¤Tb˜J%;  baÆZð@n@[Yƒ€?ƽ€ÆÄÏ.bD hAÊ—‰LOÃ6“üYÑ+>¦¬,£ŠGjñÑiiœj³Ã4·éÌÆÀ6þ\ÑK,('Þu2©‹¯gÚÉz.̦Ž1 sn7U9öAN hŸ†¬ã˜¶’…ö¢Ãø3#_í+Y¦Y‰ÙjÈ€‰Z„R¹ÑF©Š˜Zhð˜x9™µ?ˆ!>ßK‡vê¹¼ŒivbÇF:£û³íÃÛ0<Íôµ'@{#2ш¶l.¦HÌÏç9…Þ÷ F©ªç6Bo|ænn"f7Å; ]-3¦¹x€¿2˜Ì>î ëôÃYµ[øhS²Í¹­tuÕëñú35OÊ>$í­ZÆp½OS"Ç%•, 4ݸ€Pv0+ú€ëBµA2Œ©K‹71·—Qây;^¿a­J)·p²›ïj/ŸÆåà3õAðAZ 5”„£®ÈÖèv)÷2þÔq)¹ÿ2•Æü¿¼†v³þö·¿ýå/éÿÌuþ==OŸQŒ¹T Ü]^û´^kÈŽ ™4T‹Æ¾m³M{ê˜Ú³JÐËÓ8Æœ î›!4Æ·Ìœß× SIV’·Õuzý_°¨‘¡‰û’ô™æPÌYð!æÐ8]ŽÝK)A%¼ª£ÏW æŒç >‰á£ÉÚ3Yí]¤eêí²Z|²4Èç5gž¿Lÿ\µA‘­é°AÓïï.<#ù2ÌnÚ-øçi" 7¥diäñ‰³Íp›OÌ æ¬KÓ´$[” ^ÿ¶±N À€ð£’®c|^ÓOÜÇ6ÏÐìEŽΰÞõnÖ|8ˆŽ­DƒézµÌ0™c@æ| ^ÿç•:–«2œ,¬—zšÔetþŽÍªkêhÄ´§/´/™£FßÂZh˜¨2‰wª‘žEc$ ³UU‰‘YUÅw¾Ü^LK‹Ñë5Ë$P£#Œií@K6¢#ÿ‡ß¹–ߥ×n®¦´­z‚¸wö5úáß5ù¥Ï$òk³G ßýîwÿçF¶F›¥#xnÛ˜­Gc yŒ^A†ï‚>G¤€Ì'%÷±çÚƒ¾é³åF +e «Êº€v IÀ9|O1C"žl‚Ví²øÙÂÏ/X«Ê‚†•,šÞbÉhª2'hz¥U|w ¨Öezúª”Ýݱè1x²<1®ìÉÔhÙ1Yž{“ªÈ”ŽœÛÆr]@½JaÕýTb"úlª¬Ú-U‘ÚGoØ kyþëdû-tþn¨3u¢ì¼ÂÈxYÐ7>ÀÚדµLã¨7‹g#,òoï@&V‚»C½•Ìj·nµYª òyޣɇ'L ÑËëõm-Óù$Òd"Ãz‰5ÊSjÔÕôôM1‘Lªå¦Äëòy´XÙÜdgÑþg_Žª Õ‹Ï ø;©éÖsdÁM´¿LÖèÿ[6qð^ ¹’¡›rÕ¾Žv˜˜C>žôï7÷žùÀ"\ã3Ó»` àß#ù½ï?iðKü¿¹¯—üñìÏßýîw6g%¬á‚w£ó‰ÓÀíl4œ&êé¹ož ÖÞ­YÝâë‹ÁÄ¥H2Œp»Üºf>•Lé1ÙÒ 1{´˜ÄF8¶%kIܸ”ªŽ~kvƒuqæ Rf¥W „[F£ˆ)kW‚[&¨‘![G$œ²vÇe¤°¥–)óAJ€ªµMt…nÑtUß:% à‡ÓÈ<e‘Œ~‚üka¤†‘x÷€Ú5ÙÖ• c·^€I9~2u©=Þ#r؈smc°jÔ Ý_ö.‚˜Í¦Ü€Œ`¾®—¾Ë”3ÈÚÎpOÓJHÁA6t€^´0€oO²6Ùs';.·”L#n7%ß~x{*1ÁȪûØüÅ\_Ë3#í +Χ›ò­A߬é*’½OçúEæªý¢wö÷÷3œynÌ¿:øäl·÷óùÂ1ÝÌ9GV21#LÙ‹m ¿yýÎõV9û£Ë?÷bd‚¬õú˜(¤A½*¦MRÂñºÌÝCJ¦J‘̶ü½ï}Ϙªÿ}öÀÏþsÿÑ´ýs»_ié®às±¤û¶[%«ªÖ¢ ¨"{½.¥¥R•Œ'««¡L®C¼×î1e]‰éŸ€œØg¤ÑÑP† úáèé>ø?ô½¿wøõ¯Í¡Fžø'öjnŽx»Á¬`@ŒìöÓŸþ” ¯JùÜ!¼MþøÇ?~ñÅ‘-£˜-°;ÚÓäøôl¥ö©š‰’#>ÿ§gØ’4fAßоŽ=’ÆQKW–{7|ïÓW¨£L©WîvÃäÃ5+Éb‹š(ë•‘"Ÿó/%¬%rì!”¹4/¹¯ ÙA¦º¼¿JPÆ+!çŸs%è}ÍrôÄl-zŽ4le]U”Ù²¢ï¥dÕ¢^ÕJ€_UÝ.†ÀpkŠFži`[É…õüR“U5j©ÄIàhÝ®U[II£#%@ÜzøÝ. °_áØnª_LÌålœ\ÄÀí ··ôü…#^˜î{â¦Ý1ªM„ß¶~Eö«ß¸ýõ¯õ†_jýö÷,L”„¡&‚˜ÏÈJ<•`Ù4-™ Cd8Ù÷¿ÿ}¿¿lÈð”6k§é}ʾ{öýèG¿ýíoÉøð”íév´§WÊÜÝÝÚ†x£“Jã²Zôv¯ÜºHz¥<» AA“O@ÆcÈ2tä)Û!’Fi˜s]r_`íôVrÁüàxÌׯþð-­·mã Ï òvÛbþúò‡øoWò_óMãY5C±é-†±³[ %…±’¨%>«z3iùñµ8²õÉv;™Ø&"@à<}š•OÕ&böŒÛ!ß2ãð€XoG¤j<òªN‹^ǀƒ¢ûZI¼~ÏnFŽDzž‘@¶_ßf€€¯ì²^7ƒ ©v2)˜ Ðö™'†{Ãjšf=n•ˆùÜ»œ“¾.#ÒËY™ô˜ŒFckÈÉjìvü3¡og¹•ÖÕŽZ¸ùù§1DíÛgSÆt5$=ìß`ø«Ðni¾:›åš}á,c7áØk×ëh„j[1/Úsâè7B%›ãuYFF²òå¶žÇâWÏ…ôKߤgNßõõRÊ êí)0€AÈla‹­}%½‰)EËëuAåßÔ‹­A,ÜÔ/+ù·J”}4òáàüá ‰ÿ“ì²þ²É­[h±gíÙüñ}šÍ2ެ0°5­¤7Rî5´wÁFÀ4½‰.W&êÚ;·U&}Ê¡]oíĆr”ˆ ÇŸüä'˜®óÕÙG,v)Ma+3ß’F‰a#`&]ã(|޾Q_½@U¿ÿýïe]-ƒwqV®ŒwÌè¹Ó"Ÿ²Í÷Î[ønt>/âVuµí¬e˜ f¢ fUä&ýPÐÄïŽ> ~ê[;-|ºTûP:ÆÀM!³®3ø~I†•0ü14âüדÀŽBƈ^ˆÑFsÏ·ùØ¿wê]ˆ½K¶ªôJÄJx &çö@n 7OL&¨²m“Jòº¡±›B°Í1½K>+$&CdSÚ<$™WKF?™¹p›DòÌP‹ö|ÜÀcdAœžƒßA~Õºx€R$øŠÌ„›¯»Ìß<ÂQ¶ƒÆ¶Œ ¶O{2ä­çð© &ÐÕû;¶ +تý·øxJ¿þüç?ûm[£¬¯Å>ü#1Žk4‘,¥\#YCUÃÉXÅh¼›_âþK¥º2”™ûoïØG†Óš†`PšŸýìgþ$Xï××HÆ6óð¹Àã×Ë:ÚÜ,JØuº8²^í%ÇvAúü5: ›Ã”‚ 㘘¶I$%\U>ÍïÒ®ª‘Fì’Vó×å(jr¨Ú‘Ûø]©Äy-1̼­ºÚÝâ\P©}äÍmç"D׋w”¹‰nj"¦Ä;¶°ü¿”ÝMv+Ë­„Ñ9¸ã†ÿæ?,7®^ƒ×ÛY§Ì#Q|hÀÈ@ €Ì*)Jç:áÃã@<¶ˆóÿß'¾ Á\BRµ®Ÿa6˜Œ>ñpK#Ý­Ùàæ„7¹%‘éÀeéÈÒ# ìYÙŸðãT"åØKq: CBZ¢YÒ,/¤¦ÄrÊå˜áÍܣߧÅj—òÜ÷GDGáô“­5<²¥‘|­ÿüãóŸôµ‹MµØÀ†Ñn]ÚÂËIª‚·/%ÈMØ`eÍ&5\PIʵè(:±Uhv«‚xýbºgxYµ  Ð¦>ìþç?ÿ!BPy“SÓe×— qžÕ³MÀ•´‘N Í-öåOÏÈ{󳻎âÅͦ(šg`ˆváÍo6ç›J!³Œ€¯–/Õ^è”UŽÃÊV+v8 Ã뛎B_àÅ+JG\IK±Ú‰[f•ðÌ´ Pê®Ó$ÑxG}^Û )TMê–bx{#ŠÆ7ÙUtŽÉ’â•à§ UŒÙ™ª•ªK^ $â¥+F“JS¬—eüÆÆA– ä1ù&—µäeåÝ•Ѯ䯇 Ðs-&O­mÖ­×[KÞ„jWâºztzÐø¢¡ÉqÞ}/¶¾F7vK%º4¶íhAm‚MÂ+aF+)k)ØÆ©…óhöØ hbxZókwØ`ûD,U9ÁTÓ*L6A  ƒ ±®»¾LŠE6-©h¾èÿÓŸþtF¡Gÿý}˜&©–DTñpjpÞ{ÀßÿþwEü£F¹©±”dᬾ»]Ûf©h6h©êÒxÜB †GÊüìÎQÒᔵԨ­y ]wÊ‚¼ ‚9ÅYú~·AœÂÖM›œÈJ\JÊO”mËíÑRS)¡ÀíQŒã›÷ØßȾüQK°CÐ1©6bYyjj6©…X ®œEn6/RHL¸ÙÔBð+©‘XvXž-=˜ ZÒIJœˆ«Ð$p æÄ5ªp„ƒ¥o)`Ñ—üãkà‚‹{Èh|:ÚµÁ¹š¬)y¹æˆ$‹S¥öIHÁ‘yZ<Ü HsäeëRÓ6£ ŸOV6šòbK –MÀʦ#®àlìù:§Ìzš ´«*O¹ZžY´‹RJ’Hµ,@R2ð8ÿjFÊ^‡=ñ}Im9©¿ô •3Ï}ï…‡Ù… ^;{È –ødMk)æñÃóÈ…ó(OAm @ÙbxŲφ^–/ÃëÒ_Çã0%̹),„…ðõj/á!—Ìqk4¤rÞ~ñYÕTuÉ;(_JøjÞR9šZâ‚bK'ö"®/ŽÃ‘ú÷¿ÿí» ä»ì—1N±…uifjJà5­¼Ë¡‹lðÕJ)d`ÊÕZ2)"jÅ’,K¹Â:¦OÈ3üRø@K§$Hm‡£µ/>ü ÙA‘¢™ŽH­¦:ÊšvYeyL¬{ÕcÆàKYús[4ÈæÞóá#ñŠB})xY»Ó,‰Cø˜‚æYÓ«è|r2fd“ xx›õÚDPUkU)²ã@šA 5K§¦µj)P$R¹FZO-¯°MñøAAÀpÄp »Rð ùó®hܨbl¦YZb$K-@„Lf©S¸YeÙäúC ©4 †¨R›ŽF ­€o˜Jp,I¥#`RÍÖ5ƒÂZ§Z± ©¥L­%ZãM'‘¼í÷óÚ@‚Ôú½¨•{ý¾‹Ñ^â¤ú¤ï)&@0 ¼1xï”ÂÅ›¿K[•Jd5#yb¶5L ²é#Ðl§–Ê-mÍ£áå;)æc Ï_^]"på ™8¼•ÀcvÑÝ‹?…汄«õVêÑÿò¨¢ãS?CÀ¬]-ò—ê)ŸÐ9 êâ§Ï?UÄãÛÝ A &hGš¦Ó±ˆCôdjeÕº¸œÈD" uMê(h#øl˶)U¶Ï1À4V£˜NÕ·.á?zOï"nBU0'£\ß@|ཀྵýZöU[‰1^Þ׿›Ç ®¸BÊ5˜§^5R[ÀK!01ë¸móž‚{ÉD3ØRüvZ|ØFâÜ·¼QM˜¾òð—.ÉbÊŠËn©p&ëÞ@c@°dÇãLD¬0òyca.‰µfL [ü ^·øîT “%'Àç5k¦R–|jÅ–MY;LËt¶%ü@YÖ²– ù f”áîuq½²p ÄlD6j#U¾Öøâ–éÜ[+—âK¹w}Ì÷õ¿©7¦»[9k°>ïW®—yŠ›¼! šÞ±7Âfó€Àd8¼«Ù q:®&W(Àᯢó¦ïQèk–ºß·€ï³¶_öÖQ >YP µÝ$@ž&ZËÞÂùmD–MJܨ ãÝèeßûªþÍÀ³Kæ×§-"Í#èM«Öh÷€”kÇ*ÿÎûà©ÊÙïr òxðóÍ¿T»ÃWØe2XÛOjû dÝ*…w…+yÀeµëú¶k ·|ù&­á¿ôÎÙ/WÔʶÛgC€–í®ñòv±™Û‘kÑJ¼p\â/û¾€J¼Q&¢Ýøý6®J—& ¸ ôX6íÄ-W‚ÐÒØ4‘uÉ B».–²TÒ²CHm²•ðpdÊRæéº+´d‚ q¢-%«¼í 1 y&…€,Èò:öܨu æãY¿*›5 ÛÀÓ(f¦u¤™T»Ò¾Ú ¥bR¨Y¹¾J¤,™@¶.8Í®Ãâ 6À™æÚ$…::Y»½¸ÇÉÖ=åðâBj­#PI}¥,)[ž6ÏCà>@õyßcw)øsß{ry9yô·»)Ñ«mŠ©Ádw‰Ôö« ›ÍH=g¥ Ê!“ª¤¥*AY´=škê#öwŸÅ ì¯à=1ëNd»3©L—–º7Ûbûj;Û”1dÑRPk)ö½°þÎù)|þ­÷!Rí·ŽÏ·›''úÌâÙäÁ|cD<7=÷™0ª3Íó–B÷T*æ[šÙÁš¡{³cL§Á¡V ¼ÝIi*nøfDóÁÜ£Öw>ßÍß¿ûä¥ãºàhÁÓIJ_„@4 „xÛ4¼¥GŒÐœ<‘hJ”ã4€y|D¶Ì»Mâ$Ãy‚‰¤Ï7CR²Ñà5å×EŠI9ašþ}“?‡¿·»Ç¾)òÎí<•˜ˆBÒë¨ÖZÔ"F7¹AüðD,ÅLÌÐ0_;KO!—…0)ñd”uà;YK¿û½—Tø¥÷Ø¥¦0e½8XK:ô²ˆÜ{v½:œâz¹å¼šŠß{Aúò‡TLû¢Æ,íE#²ˆ‘rÀhZå§ò:·JÆT \/Ëé¤ìâ(ÔQVáøÍð»¿QuW•š YHK1뎅4CˆeAB ©{²Ô€á5ÝrLc<¾"èNUäk©ÀRüRo 磭PÌÚP×Rýh‚µäc¦¼ÖÀJ0)•Ó´¬K§C‰Ã׿ûµ.ª˜˜Å„ðÈáu»§=ô}ä÷¬ŒoúeÜsß—æ}u¬0‚)«å Ûý-¶G)K,hw–}üÁO¶±éجBâíZ Ťøº×Ѧü n7Ã}/˜‹^xªlÜR¶¾‚¤øâ7Œ€¾’|K›ê6ÐNŠ5ÉD,=Ìóû2Á†éѦÐ~iòú¶TÛlÔ˜%/…Æ‹ ^­®ÄÒûœ©¾üZÜÛƒ7üö¢JP‹ƒ“JÖ6;yAæJÝg@c Yà­ÚqLÅàô âÔZ•eÔ”°eµF³_^\;OWçGóžçV®0e‘ÌéR¸ý¦AV ]c^9³TGÐÇŽg@дÿS ¤(0MñéCRkH3Xʲk_7Ìø1ï“T¢E…D2cظ­¡­‹>&D‰,}ËD6Ccç•„ãLª–@R‚,AµõšrLM†Gà™ZüjÓVx~Í ²6+oÉ7ÓH¨;â@Ë8jM“ÂbünAƒÞG‰ )K05A† U–§ß)‡ãÔºS¹‰«Z€o-òÕ!†Lü4»J bмËì6í«žn¾ho¼†—§•Ï,íÔ<R: to³üËÈâÄ7€ Û¨-@zWç›VÐ<&·ÔH-<Aí"ää3¯ÝUþâ5õÔóXLÁ«]€£vR; lûÅÙÀñÅøh²âvÚ$]e²¾î÷xªÑæÁñ9ÔÓ¾C#2)Áª KjÚûeãE躈~à9î'´JìÚÕt&¬u}Û„&\ëåJ€˜CÒĘ­eC¢ií³‚l„|Ì {àz‰ð ´à ^fM¥Ð˜”XÊ}~ùƒìØé»ëR¸”NS휛ÙÚ£@;WªF˜b†PA—ÂÿüË—Þ Š~÷¿ÖÊYRuO_w¶” ¬¾‚R!nK¦üT^`øÄY"Ħv'™F@å}H3YYåÝ !È@ähb‚ÈWøèý|ÑM§lUJUÎCdÅ.–eMyÊ1Ï,HÌf$¶œ Ü2ÐR Ò&ùÔ˜ë?DV@SyF’”—VUu‰ ‡ÏàÀd뮊ƒ‹•㴌ѴZ1NxRk¤áh]›CÈŽYìÉè×S¿EþÝ”xâ»M}brÔΘü‚::FM{ô˜S-Z/Àì´S°5w?²§’V-„~q%jÚQÝ1µØ×Ÿÿüç=éd聯¿‘÷ìë‰I2Ai‰Ó1j-¸g£µGx)`¸÷ÔÆ«c|ðÿýÝÓsÙ#X-~[¨ÄR K‚¬Á Fê("ðõ2³3ZAœô}Ñï"ÊZ²í±.<‚@/AÇÒ3Q횢¹pJp´»5•TØëHœ²¬ÂbÁ† ,[G÷YHÃèHÓ¹µ )„@µŸ?v=ýýèC„¡©œm³1KÙRˆØ$(VÏ{úýZ?Yÿó¿îvW¤o\•·Íƒ5Àd5í!b§½+lxA;jrÍÂÛ¿öáZ°µM™N¯£ÚYÞS@K38&f÷¦øk*ƹ÷µD6p 4<$µb©©Aè\Ýo]‘Mù¹/±ñ:Ž–µ¯GžDZ<~õüÊï·2^6¾x3‰»*âõM P9Ž˜¡ÅLGÀÇiK4ˆ‹/§ãXº™¼¤=€àȵÈÔ1Ý@žûnÐ^]²ïÍ´úýTñ}0…dݼTëeíXK#u§ÖNª@ŽQ/úãALœO¤¥Ý»lü ¨—OÙ¾d—úÒ|õ+_gÕ< ÑTñÆ(¦#î¨ùpL´úŠwDa‡àü‡•ûXêg¸åÝÌð¯ýË;k§Ú ÊuÚ¯!-¾‘ij”Øb%uQløb¢mï}§^‘Óç‘+„w1X‰ÀËdYKÊ †ž¸ÛfœÖZÐ<âgµKh6"NÞÓÿÃïܽ÷{PÈê• Žlâ²Íl/zñ¹áö+…‰/¸êO:wàsêwÿKÇ¡j;«<µÄùšbÊÖŽ"PSŠB§cÙk$°ö˜)…ʼn„ð ëÅ[VÅ'¢J #[IœhjÇ–‚rA]ÜKÝNNòÎQØ`]J©æ³z †G†´e-R†ãÀ_µ¨}›o3p&æÕ$$°Ÿ–µ¬ÄL½¢AtR… fÕö" 0Å4«­ËÊ¥†§À3-ª*ÕÌ©Ñw/:^ìeÄÑæLè+þFªü'峉§žS‰ÔeOa ©é7C‚Û;‚“¬×}§Í©VVUœö懓Bhwb…”§©…X¡×Þ›_>ôùì_»JiÎâûõmø5tíÚ š €b¶ä‘}åòåÇRÏ œƒl˜üý-; ‚pKÓ¢¸^Û>Ž^[âÔ.hZ{„㸲@DJ@9&Bg«»˜&_S§«R˜&¤ñxµíhú…8‰‡7>«¼Q5µlûM›ÄYiœpFÁ‡hçÜxï½Bߺ츶)Ý鸅´€oHƒ¨RåYK|Ãøðá•ø~†²þ‰F¿„P•¬@Šg©ñZ 4â5í…N`÷ÒË„ÈÔ‚Q®*oI -&šÀe’b–W8ÄQ ©Ç§°«Ö?qŸºN³ë¬ ‘SC®u OÇT¹-@R¬‘{;sIËÕÉRhA©!vØf¶74 Ú¤Ó’Ie@U¤Úyq * oÉðźÐd–½QS“•аxÂÉâ¨0S"Ž&+€(‰†Âkäûüe14Ÿ‘}äïÛd](¯‘ µðz«;‡²÷‰Zk×O!˜b´{GR™£¸öq6BD­%fOÿ@²RÑ@ȪÀô~íƒvå÷Ž‹=s}ö×hUR4›¤×Oš•^Ö.ð™Öu/ÛfÅRh–²• ¥¯¡¾üë#o«žþ  ¯*e¸¦¦b‰Óo×ÉZbê(H /Õ´RÉF–"‹ Ì7³ZPkÌâ)Ö´ù²È–b†€|#RÇÎCô­uËy:¹kYª£¨¯%œ+€0UŽzø÷ô÷9@ycW55vøˆ†¯oâªà‰àþK?ùù)ÄíªêÚЯ2½´àw'ˆY}šØk-©OCKdãÉò¶† DÈ+¸sɆ B)K­ÅíšßkßRÇf³;²L 0œ·LydjðÈRcB´æ!8ÝÕF^JPÓ¦:¯(6FiK* ÂGk²æn©„Ã䓇cÚ§)'‚P#—mÓã¯Y%‚®®¬eÖ -ì_@AÉËeÆI­Á”«e…È>úà¿‹÷hðÍÿxôû«þDòšj-®—˜rߟFHL ç` K¸÷j¶oòRâm\`ïÈ Ï#·Ô……+ÑÚRN:p¥·7€8ßÍ3×÷-øÈhúêNÍÒ^:UU) pÚoRp{é†nþõÈ6| æ_þòo“¿Oâeïk];˜½óéÒ ¦ÓTbH}‡Çi#ª˜1â‹ÑÌ¿r¬]„&ŠS«‚O$ZÌ w{ëOßñªðª21Cc!ÍÜEo<%Aâ _¥Ç•­0ˆ›Ü“wœ7ýä>Àøº†ÕÅ.zõÁñáëÛ} 1a啸)ÄTü. Ó—?ínœ`G'›Úúµ֔µ…&‰o›³ŸóÄà&,x@IDATRá1«B£ ©E]&‚Â÷ps:º» hã7yãñLX KíðY3 LÅÓDfí^œˆrA ¼T>qLàj籂¡e<éHMÖ% ä'‡Ì,öϧ¬"Vž_y"-:‚X 딊æ4¶O¾KBg²d)Ÿ¤$q4øzÁõ’zúøiô÷¯žSxñ>¿ûÔkÃNS …c¤¼F üе¢¬Ù”ˆ•0ÝÍ1Zˆ,œDV GÐmaɶ)qí Ò‡\ÝÎ-âÑÿþ[W?ÐøK;Ýé'¸F¤Ì™`óXÇì`Ë*qJÈL8ŽÙŠ£Aú[O[ ¹{/{oJˆLœš*¦OÈC/ /•~…bÊá)⫲;àﻲ£MaUõ‚ãðeõbâ®)B8_\•¥€gáËR+o éCšß0^†"Ëf÷¹8G÷'£ã @Oƶ?z‡l‰Ð ˆ;aKƒtâf0§Ø–‡ñßÿº?|¹ùàãF™ˆˆµ»£y€ëÛiï‚6‚€I!aÈvh´kÀ3¹ªm3~ ÖRhÖS˜l RzcJAX¼=v,¥zÑUòÞûç G9ñôÛxˆ.)7˜Í2|xòZÃe[¦)쬌gY bÖF0 Š‘ò{*9S4²¼Fõ¢ÀZÂÍÉ,[n 1Fè½ÄK³ÑgM ¼ôÎ!€RÀưdZè *·›™¸ÿ‡Õ÷ïs¾Þñ²OD¡ÅÑ^ô‰ÌÀZ˜’!còâ4ádÚˆe_¸=«ý/M_ú{+J¿òu/X_£©¾êÛ’ˆ ,Æ ¤ Ph0^‰%#ÛŽê«$Až>‚Ç'A¸`žŽZÙúò/¥œ!Œ¯¶ó‘6Rä)DN³ÖbœtdÅd£‰¬Àˆÿ£9|O/“‰¤ KçPkʤÌiHÁ}|8«D€Ðx/ÕÿûT˜nÈ·B×¥÷NK-ê΋‘™+,െðøh=…IË&+Ë -yq" ª…ŒƒŸ/°Èñ›AÇ®K}K‰Ì0y 4‰íÐd8:‰!Åjí\ìBž”%Ÿ‡äÛ¹eG&«œÉ2T^ÐóT°s‰i_Ê ^´> ½ bf¾Íðè÷ª¨u`»hkûêÈ€½[`Ú—¦˜D•,$5±œ¾[SpTžÛl§+Oj:wf‚Ê‘{µô:î9UöwùënÔ»r½´ØH{åtª÷³¥l™~%-‹É¶¿Šø} -|óã½VJÌ^IFÂ[ ¸.|YAÓ¢µ§!fq’ I MI41‚Ö¼8ñÚá@¤4u‚æL™W‘%U…JRÆ¿T éWÎWt©Aš\!¾¥”˜Çor`3·Œàç?ÁUñÎ)ñ»_j¼š šM™¬îRðHS,µ mjåµzãÿðuçGm/:Ÿ]Ú…ÊY[»ï¡”^õµÄQ%(V% ©ª9»!. ZµíBʲcçãâ÷ì ´^}Îå3A±¦ªZòJš_@¹\aâ–¥ô²ì2ýbKU‘‹Ûx)Ó|±ŒOøë–¤kŸhT~· )G†Ü1íX¾çUÓÁ‡[º«:q1åÊÓ=è@| Jp0» â–ø::ʲ¶¤*ƒ¤ oGá–þöÑßÀЩä§à;?„6ÏIÑ´(7$Ñ’rípd;¨È#(il…ôc+WW ‡ðL–¯uW$Íð{vÃøÚ×gÿ÷ß·º"~ëkxµL@0Ó«©Ú ¦ÆèüÏXÏ'òöt×6? dí1Á”ú¶Ä1$P)h0Kd¯Ê-á @ü£ùÔå7@ 3µ{-@,gZˆ;À^5ÄhÞT6‚cHqGxg"Èò‰TÂ×HZ¸XÀO<¤ÃQBjq³)3:Ë ’g²{W’¸À²¸ãEkŒöRŒÆ"\M·qúe#œ0Ms/–n, XKû$ç¬ËÞ{È:”¥Ô6+¹ Zœu7 Zí^Rvk¡°1H xµ § ®uÙþÊSü£ù¢Ãóˆ'ÅL¨@G1_wý®MK1s¯×W¼^b`8q9™XmÖ.øåvq!DV’¾eM:&ô©ßØt¥JýîÑú×^ô)0µhv×ù‹b:í…—*QÎÇy?ZÏ‘”ËR0Ï—?‹ £¿ªjþæÛ©‘H…`‘ÅFÒBÖaò=ïTµ©øÒÄäÕBHAêHÙ=†ì:*†·GUÍÐ’·l$‹¼BAU|š8b],~»À,¥‘ÁàM`‘Ñ,‰XV"HSàÀ•;ð7ÿÜmæü}în­‰¡lB Ô]y­‚¬X¡X-|iƒëøe Öûó7­kÁ·Ô‡ì²Ãl‰à xc+‘R%åÀÛ\‹^ ©†¯PŒ– Í,“j’8øu ä#²eW3o™¦a "çK¥Ãk ‘Òˆo pˆOs´‚uo‰3qåãÖ¯qbÉjÖ|âÚè'Óù"Ï€ÅJÌÇK(¼A› ¡Q"O?)&eÉ‹+ÔÑ`²¼*œÈ–|L±^> ûÛß„ZþhþÒ÷jj¿tš³Žñ™¦îìÌt{–¥OS9'5"ºðJøKà\Ìhæùîgd§í³µn˜”ë(kM \ ¹| © ÂdŦRJLÊì´¾ÁpV( Š Œaâv§¤rRqàe›6¾\l†Ž«ñ µ+«°e¸%k›!ân`8DSÒ䑎.1¥XËÏ¿üñý›r-š–¦X k#À,q/+ÃTÒl+q«íÚù}Û‡êÕçfPŦi;–!½ `±×T B»nþÈÀîÐZÚŽ’â]¸! L!¦-§§Ï€îÈ •X•yˆð–p½œf¯`„Ä+‡àó)ð–“¢ Τ¢%¢<&Ùõ]ŒÆ€ qع×õn¬åÒ•Žjܺ†´[HK¦¶*±ÔŸ_’¦lŽ˜[TKvú,áuoâ Ýdp²óU5öíé㛇O~ ¦ÓŸŸëbx]´fµ#(ÈcŠ÷ö¦#œgø²ÚT3KùÙ¶©&5ñ”½£ ‹Ã‹Vd–‘]ïšê¨)Ä׬öûþéßW.i¤Æ§“¾î)7-qËŽåÞW‰¥¬€Zäneï»ïŸþþü´z17OjÚQãÛ5–~J ”( ÉV­¥y´8õ×HJl„TF?!ÈðD”ˆ/³©q€-Ë¢I+ŒÂ+Ï£%“‡l›U…”"¥ šÜ~Û²¬Tw‚À2¤.¾rñŒÿh~ÑÕïšéBG•€¬Q5åÝŸ–!hæóbr@±!ÅnÈ¿üñqÄûP[Ð.ʤº?ÝÕ@)ÏèKu·WÈ7›”Ç’çžHâ²DД@,Óçm¹ejh›Ê9eÙZ$ QkªRiâxb4¿3ZóÔ]ƒDHM# Ö|% 꾪‚1 ”ãÅÛ+èº>¶ b¤S7¢ú–:YÖÉ–MV©  h¹Q ⤚ ”-Ñç~” ׆ÅɶD#Ë[òtXµ‚f¨Ë•9ÿÒêÇoBjçP|Ñß'Ø`›³F²k½Ì ab†ßT-Jˆm*þÈ9Zg•8Ð’ïVÁ~|ú«òS¶Zª¦™,D€ÀLUa®Âµ›Ç ÖÅmd„ ¬„š§ÿw?‹¨òj÷ôox^Çæ!a‰ëf(ÐBªQÅM«0 QŽœÇ2ý&¼"[öò°L–ZB"é…°Dx4'¤FÀƭ˜²Ñz\R«á4¼˜oi64±Ç“^g‚k™”KŸ{>|ìîËÊ4»‚ zݵ£æG«°—a%ºÃ»%®‰ÎF¼¯øá»Éi¾1ä~ò®‹§'„‘r2@OOå–ÈYoªÎÙ² k'5\¹ÔÍõª ެ˜ ’˜"µ(U,kï+/UßÅ‚ YŠW«KšjY·™,æ†×AÀôâS@f|0þE|è+” 9ìç©öÎ?žæØÂà›[&ÖÌ h²C”ìÓ­MånÍÆÂ‡#ðu‹Ñêk)ˆ l«‚:¦VmÄlÛ)~ç(Vd}ó Õò÷ÑÃïByäö™šùù&&·He¼-›“0æøð![ ;R‚ŒBå&1©;P¹WÈ'ïv~Êñmoå¤xCR¨Kj–Z‹ó-ñ!5퉥x“cR³lT?¿{7Âï{Q¥„Ŭ¦‚µè¬"_”é*~µ‚&”ݲrHÊ8£UÇA0¿¸Ã‘Š» bÂÀºä1Ã-'(Îð=ßcZ6@±× Zµr{¯W;­ ™uÂÎ\J•|-à_ý×·ßy…>þËÖzÔ2‚ᎅ>ñ)-Òl€a$œ©ù×'~ùãžônÑðîd-ˆðuÔh±.æa&± ASIY+)¶TØI³‘/ÅŠiÆ· HLYšÕjS;  ZŠ)X6vYµ mŠ”¬8MY4U–:Wi)‹/K9}xÑ, xúðhªø•Èvn˜²ç[Ž¢êKW0/H׸¦“Çlµ#CJa6%¹xYˆ­N9…ÊU,HG•F–Àð@Ÿ…ýÁ³‹üÆûä£G‰Ú.Rë¥Å4¦ÝöhyMqnÄ{Õâ²WÝã±¢VS×G• t‘ºŸ Â38‹€BÜ~¿û¦¥-ämÖ€¸ù)PKx_-5‚×ÑÉ„ðLÓqº}cv‡ùÁß<Ã¥îæGa傳}âí-вÇ"DœTMŒo’JÄhm¡Ô kœÅɧfr|#)‰ Dàá8‘yKV f±eȼTRÖY‹é㨂["ó §€o 8ÈÝ3ð!@æ±ûáo¼Ü ~êmŒæÏÓo§)u¡ Œl¹-Íìfæq6°ñ>ü%„ú‹»]åNƒà¦7ÛCÛ0âîN)SñRJðy1‚Û® Z>$®÷öø˜†Ì´ŠÈªˆXÈRóņ‰SkKAžˆWš]Ò÷æöÕ¿|³€8Aˆ^‚ÆÎO9~Ó–j žÛ! ÷½?p"÷ÀK‘j ¾êË0k—>¤(˜Î†DÈ7†*~KY ,AeÄo°(hé¨ðGâªí(©!ÕºÒO¶ci7ORÊë§ÁB¤ä ¨™³îÝ~éÐTR•™Cöƒï‡ùã×­¾ ¼Z=."A"Ʀc˜zY:zµwx4ŽÀ IªaÒñnv Ë—^•ŸBîoöÔz€´q]phV®…À ›Á’BWMŒÐ¹XÖ2WÍG¥†lZ½p^ήDÓ6 ±ú<2qR8D€‰àdÀî"4ä{‰”ve²rdK |Lˆ°Èøb„R@K`OMJÓR¼ Ò„°@Qk*.›?OO 9k¾ã°$ºÛyÅRuÒ ß^P¹ù¦Ö)l?t Èh6É#ÌZ&‹)ÚÜ÷v˜—}LOÿ? «õß?ð@ØŽFÛ$#¸Qõm׎Ž©¤¥XP6¼[ Yj?h—mG|´GËë²!W¥»óé  ¹óǤæoì~|¥aú«Ç4AñLù6kúM gVpiž{•ydM(ûþ³¿/ |ùƒ™7I‡|a;x‚ÑèCˆ[Šu4- lR²€.âÔjê(¤,™,Í&‰¼*K)ÞÝE¹F®šÃ,¥Šr÷6‚ÂÑuQ.¼Ëª‚ÏÓaDY ÖÞx¥ð¥xÙ4•÷ÙŽéNøñ£€BæØ=Ù®-Ì’)²b3ç6ÌêÅg²•ËvpJ,¯Vïœ_¼¹%0UѱS± ÛUÀ€ŽÂ±#tªJÄ&Ü´·£˜DLÈt„d§Áó&Y ¥)ZH%hTâVSKä.ñ=% 'Lgó¸¸UA6FÙø|š!§ßuK'È[òÛ¾^æ´tɺšZ0äe-Åçák,žÚæ•1K<El•§ìúÜ­DP')qRb%© jŒ¼ q‘I;Lˆ,eA‹{y]ÊÆÓÄqÇøá×'Pñ{Ãô½?eçUßùPBÍ—?>Ú¾òö²'£eš÷&×óËbíXÃÀ»‚šJ”‹)$¢“w7";Û 1+ÙŽÔºc=¯T!Ä/'.0?‡Õ®T(f»¾ø8”•ããÔº1Rè0¥Ô ŠkÍ«…Ðé%e‰,Á" épªâ5:/oéw–Òj V\J6\“åñy[²ÔÉ’‡ «·%…ÆÖ×çGÙ6 °ª¤Ò©o)ÌÊ©eð@K{ÓË/B+|R¾ø_SùÐá¶«MˆaPS«e©5…kÁ‡+ï·Iª-ך ¤í·ËîNŸŒÄÞ þùÏÚxjý\Y£t¤ô#3)>ÁĪòeÚEùÖ¹(ö‹ŸÚf3¶˜/%«©F–´xKÇ‚#^4–šr)U¾ùyóôGó„–Ž e:•“rul¾FóÀÆÃ'ÂoR‘)ÄÁÓ.T15C«¯I£a"dJàÅpL3ëËÄj¥V´äw†Êèè!ýŽŒ#¨ ,5M"òibº~ùãÇAUjY½,ë1Ì•9ʲÌvïh#²æéÖm0ˆ10Ý–ü¶ð]à (“tõª;5/Êaén†hFe›BËpøR|¦û4±ZLûJ?KL1¿X€®K·„N̆§Ùit2øp>©‘“ad› b™Ž€¾.ÌDê%[‰¥˜`§¡v"MÁ!ÒüéX*×(µÓª†œ¥€E’bQyx BpZâÄo&{!M4‡NA`éŠ2UJR>]/ƒ0… «D²v@|M½>ùêß⥓>ñ&´$¨£Ãê Iiç|´€„!Ë2l rf<#^†ãs‡½­|Xf²Ñ.™_ïCZÐìlõR…ŒÙ1Â}Èêå—þ—ßo¹µ€  B-eÞl!mDlË׽Ѳr8k(ûæ/>Ìà§AûU¥¯?5Áé·qåš½ÄL ‚#æÅh•8I;uìüR‘[Æ×ËØÚ Ðpœ°l´J¤åð¥&Ra3Ьê’?Gª² gY­,Á’·$®Q- ÙpänT§AÿÃïÜÝ>w'K°]v¿‰ëØÄ lͯ¯™U¡5¶¬¥¿@ýðË¿”Jª1Ú5â=Ê;£ê•8ÏTÕ—·4ïÓd±ùZ"ËB ÂJiQ¢5G, gá@Y1f4jÞÃøfF®¯_Œ†ˆ.–²Éò⬑ÐîCY‚ 3| Ú+y¾ ‹jÈW…ì ¾1àÈ繆ã¾1±C—ÅÆCHZÐ~ªb¢5zÒ–pq`R‰ïNªˆƒO– ˜òC¤ ÙÆh0µp1åOþÝ£3r÷kD‡rÅ6EŠF¨/°ÖR (›)lŒ¥B,U%ë¶0"{ïñèGð‹Š]0úMÐEÂG #€«•ªîžþtì÷“¾Ÿuj¦HWÈ(ÃuäõbZä¥ð-+l6~7LYô¯Ïzùaþn^çžþÈj¾KÌÄõj_ OwBR²®$J¢Á‘I#$eS òLª¦ÉB”„×¢¥,<‘–1ùu!(v˜ÅÄT¥|i O nøDÄã×^-/f8R”;ŠÚ©‚»ùü4€©Ö-±ÂI ”gv„о€ú6/ké î¸g‰øNòÃ/¼<=Û5YçÜQL\ÊÌ]ZëÆ€ d wû‘BxfΑ tn8FÕ…²˜!´øº‘²äÅñ-é$Ÿ”ZF§îâô70…ð 7þ†”ª/Z}щ¤l‰–/¥\kxãMŸT- RãÙyýûŸu0•GÙâái•â‘)´Äi{;ÙªdÍ$fâU”ñK…;\¼Û‘x%m©TóðJ"ð~øýñ€ïï޴КÔ6Þ´©Ýe#G6†@Ö$dq¾* Zq%Rðnqx*ðòR¡S­`‚|/°ZàXy&ké¿ì‰}û¿þÄÛ/ú¤ëÂw›n9ÍögÀÞ~m Þx–AŸýß|â3@ï¸D”·M-:õ*è*§,&n³5mŒhŽn)ÆáÒxb¸ÉÅ Æ D‹­ªÅ8!+©E:RL;ƒA˜˜Zd)äøñ,wõrYrY­™ÀŽœ †QÐÂãR`Ù™Adži×Ãk×RìVO¡Ù(œ7ꔫâwÉÎp%ƱM¾ â Œ!HJ ­vb½ ˜ò¶P–ψlGÔbUɦ\_ž©åqªšÇ¹’¤ìESÖ´Wé£gˆå£’ TNY±²bmà–zÔ¾ë$ņK¹ë€ˆ¸ºy…®.fåWÝã¶£,«E)fé´+|8‘ðúÖ15ÿ÷3 üK#Òï¾Rk;˜4‰ j·¥Ù,5øî’&Ù¦¤ÑèˆMâ©-`Æ O¦÷!KåÍŒfÉÜ:¼sãeµã›¡mòÈŸüâWU_ýwn LÜN ÌšÎ4…”ÔÂ,CíËsçÍ×Pî“þ‘B²‰‹Ù%yŽ"e)R†d÷.‘q4]aä¤Â!@qÊö«°¸Ú {s­¤½LÙRÖáII°;Ÿòö‚À,«âY­1UT8Š•,ˆì–`R÷]‚tí†WKÖÇ%§ý[£ï÷ðbÔ½ 4¢ïÆ#ènô8C†S`8–¬8¾%²?Áx;Â#é§_K*dMR¢†§/èÖm0Hüfà[º^©ñDÐÌ“Ð2PïЧ,°…hªÂŒ~­‰Ãyµ,°­:A^` qL^9Š™”ZžYÂ3…pþb×ð)K™ç^hÚ8ñ‰l`4çI_-Óýñ|‘À‘6=’\ÒMÃ[2¸¸ÉÜ N^§tòš–;qH“ ’­ZÊüt‰H|Yjb )ò‡ÿ>ú¤Ð0¼¦G§yxÊ2D ;œŽ òRö% p÷.-(Ü2-ìÔÅSIËRa£@”ð+§É”óe‹)‡ –Єwë dYh2í\Ÿ‰jýé=~"æ7¤˜²XS8o gÝCI¸ØHhÓéLçÙDL›”Ó§—¥Ãˆ@dY¸‚À38¢——ú'ßtùIßÏ:ª”׫a yº^?^˜ª­í`v×êëHËLP ‡xÇ}ÿ»¾þÐv/•öÂw{t#¶Y‚`RÝýbLYŒ„`)nT4ÖüIŠ&Dþ}B)[vé[Š!øµCN­!ã#Ü·X#ßfǬ’™lŸªât2bµ1Ÿü™“!ûê_­ÉuTn¤u÷|g¶#ˆ#PÒ…6•”Ö¯”÷Üø{àíÇçÍ~{¡¼ÓK§£Û0Ú‰yç 06¹”%k#z‰*€°G† T~ ‚@œ÷².–—ÌCÍ2©š¦Ï¯WÜi6å¨ãT+fÔõrMmб[†óÅ-qš¹§¹+Òð”ã$«Ðaþ”@ðÞèôôב>eAR4;ŠZèÛ;Y7@pÚ€%Òö“²µÿÛsî _þP`f.àÉ&Ø9ˆe)Ž-Ö_¶óYÐrç¶áíE-Á»¬F 0\ÀÎoç,Vµ½p,ïdñôSoû2B­Å‚²|cGÀ ·d÷FðûÌRÍ–fÌ.G³MJ)å]ÓbµÑ7™Åiø|Xe‘ªìùA\ñN§e"ø/áÂKñ‰ àÆ2"D|º>†hKÀ‚¶!n¹Žføä5àC±B¤pc4€Žm¤Ç%NSaŠ;C¾l¶ÁxƒQ&Åã2xµMˆ_Ðü–q“4$Ž¥B&ÐÝ$Ÿü¿j(ìo«Uµ[—ºj*€èѱl„ MÕ„@ô<ý·„¼Xÿ}=špR´ `ÙÓo<)MÑ,2¿Ö Å:Ži¾±·”b)”µT®î”!ø‚-ð!yK%$¶…®N…Ù»VbÉ'Þ[ÖBÕ=°4žB|R|ˆ#¥P*‘öËûòç“ÆðÕ LŠŽ£Xk]î†ÏK)¡ÙZnƒ–ÆhZñóñÙÀíT!eú–RÆKÊRg6ËšD_ˆì•9_,Ç·¤CaL|4, ‡$'˜É^ô³åÞÓTÒÞ0é'ÒR­X‰bÜ5%%–ªoUZЄ¦S²Žp[«ªîp­k‡ ¾ËâGБÃìŽHApøDÒÑúñYk[B¼e•Reá;ÜÍ„,àøNªÍœÊk¦#zu±¬K4Ë6`·+‰ÌK±Ž¬ªŽ ©ßÔöÇ?ø•¸!ÏXÏ·Vú½ÃÛ”©´À‰Æ‡Ü¢ñ”·ýÄ[òš†‹•ËÖô(>íìêùˆAÓ±ByyÊZzý¸M4[m§÷mŠ;aA1O¶vêÓÊ•9~¾LVÌwJ‰;Oÿ ðÅúꟂrü¤ ÜŽÀîœðäÁusëG†·÷ÄeÓÁ3ÃAุrqÌ.¨%Õ"VK³¸eµ!õªyWJ nS|âRÚYÖÙ˜ œ-éwžbG¤ Î3}âG(FÀt! â÷æË?UèöN“,¤+b’t LŠÝ5˜h];©Æ†0¿òáÿeŒéSRzµ_],/sÌÖdyú<Bô…`vuWžä }=cV¨¤¬^êÎW„˜¤ÊòJd pdãˆ;®>œ­ÄljïV–§ƒF¤íã4A&ÖZ0~„Iµ¯Ã~~ÖéÜ2üN¦ãâѽ9¹”¤Úüñ‰X ƒ²Ø–xâ Ä- d¥Ä_SË´4%‚¸xËKØay(¯œ¾ÂZ ÝÅ©i»}¿/}ùÓ)¬°@¼@<d³1Y:–½TîÈ•DÃÁ4'Ïj-ËÄ É#¨BPÇ–YËI©c6ïoœÞüº5)Þ÷ >a]#<¶©)œ`MyÐóRíº€²ýž°ÍZ–²ÄôÐyóëå^äd1k*PáÅDR³kÊf8¤c`6%# àª:ŠyF¢|ò».ûC,“k±-S†èE°#² ÜüíQ‰î¥p˜¥ñˆ;‡÷¿ R•ùů—áý¸Ú¦^i¢idk†ì2AdÃqRj9~Cv¤¼—AU Y¶’Ú!À+\ ý&løŽ Δ(ïÚY´Dƒ$Õ„º tMS®ÓR N#Á›!Á4Åéä×N_ùèyCâˆ)'Û’DÌ«jS<9üñÁ¤fÍ-ÀSSÉÀ‡· T%`õXªK;jbÖNŠ™‰ÉâóâÑÛ¤.²Ï£;'ÍïgOwÌî†Óã:…l[3€˜¦`‡€Ð#¯¬BW´~Á² )ð!ˆ\=Ï=±lB`?s4OÙ½ð¾ê¥ö²©—¥Ú¾ðZ×¥³ÒTÐbäðÎYI÷\- T1Æû‡Ž/š}ÞìÚ8ejm9ñdy©p{M “bJBxÃTerA)¸ÁBT váp(´M—Ly3\ò}¸*34&P•Ï€™X_UtÄ |•©‚:ž²ç8µ­Â‰Ûšî¬©®ŠÓËHMÉèùXñË•»>û{RhNÝkªEC <—ïKœfC¨»¾í.â‹üMš³Mê÷ÁÓϦªׂÚ&¦@^£âðnEHèíð½:ÔÆ§†Æ«E(¥QâpÏUe‰@âAÓ…”Ç÷ÐØ‘{~j±Œ@D-œWk©Öa·qšùÅt†¡Ðò4»d»¥ã7³9ë"P” óhqÂÅðF=[²À`I—+WÖ–äRI7¯%¾˜EƤ\y©úÅHmŽdm‰Nƒ:& )|䤪E`á¼=£á¼1·N‚ž?I!¥êÎ+L$„ă~"pœÈãb¦)x<É­R=SÃH•Å)Æó"­äíª*[Ö²¹•+ä+Q‹ã"%‹É–íXn HwC÷ÙוּŒfó#×·*xAi)ú1ŦB”›Ÿ`"ã«Z/)qâ&øø_Õ^Ÿ‰ÇA&®Žo]¼àÃßx/u?ìX¡òmP âLkf#²hp^¢J RP–‚ÀÄß à÷{}ÃK6©NOL3)± ë+k©W €Ño:µSÂIJµ^ÞLLœ òÝÐ,UµëtøðZ‹[’Õ.2ŽBÈC(•È“­E5އcH÷ …Ê‚û¶«L9&¡œ2°Á¾ü©o©ï¼¿ó•`3¤Æ×Z‰ &±¬©¨ƒCjaI!Ðáû׈ŸüU‚ÿ ŽÌÒ®‰Ø8eA½´óÝbäm3¦ò¦m`ËDx1šAíûÎãDƱÄ'e˜zÉ2 ]„î.%h¥Ä ¿%Nf)Pkrq4ˆ B3‹ËÞïÛqÊnwN;òˆÆS`õ²Ü©b‰4¶^8fžBG£s^Š%,ºÒ]-8¯ [R¤¿‰Ydq8š%ß4Kƒ¦¡A;7‡{‹‚BL—Aö¨__£ã5"(àáõµ|cÉҤХ–7BíÐî›í@*—jÚö¢Ñé¨;ÛHh|)|– ¦”Ú¾I÷C±Ÿpe‘Yó#(,ö>ñþ;÷h~ŒèÖ[¦FD/š–æÏCŒ!Îp8ð{-Ùv„à‰ã;«z}émÄ;‘íBà0‘¬í·µ^Z`¤)__¡1VÞ¨ĉp—j§ø•Wˆ‰ƒÜ@1#Õf·_´Mjd#ãÔˆdã%N³y’EN¼¾ËZ2Lå|“`â+ 6C‚=v?üòLJîô;꺻 @w}éØŽx`S™5¶&Ëù†4Ÿ Ê"¼1cø½T7R-ÚAËóû¸ÓÆ#ÏcA;¦°Óh¤@´ôÅ6¨i8&K0¾F41lJÊRÊRʉ¥fyÇ-׎ƒ¬6–з\^qøFiy?D4X=’rÖ–‘¥ Ž\ ÇL@×ïp#ó‹ÃÒï2 Ÿ~?™r“8ÊßSæ™¬ŽøÍ Ú̲ì➪ X-¯6jŠRùJ(xú¿ÿ GÓ¿;s!ÚiW„Z“'˜¸”é"†ðª(Ôî¿r±”X¹˜áÛÔ…ŸÊ¤s¿Žªx­«RîèÒD¾Ëv½TɆ#ˆ™*…mAÓgX †×]š@/œ”Ñ0±oÿq~´þêß-a›ª/olæÇïD6ÿî S(©—€Ô6â«ÿ=©ß 㣉ŸBt¤I!ÿ²ñ•#°²`KÔ45R S0Ž¥x?÷PPëT ”ÈÖb§z_LY]6°xU”¥ Ί`Ýe•Ô4² ÷–Ž,¼Td1¥`©\*rRR Çl]AAà8`F!SÕÕ„˜µw8Â%|.1<¾çM ’²º1, ‡‰>Åîém¡–|؆ZËt·dbVUA^–0Úæ±j–‰ Þ)üÄMkDW.ÈŒZ_œô-kÁg²D€Ê+á :F¸¢*²>J÷]3øó Yåø)PX’ýð¿øæ³ÿìË< ÓÀz5R;m¤Çö®ÿ‘m#=qÄ!¼?¼ÿůÏ_dUni~“Ô.ß<|í0Ùš:„õ”BüðÈ B,CâÀ–ÅhUÉfÀŽ.˜B1~÷ƒ¾Äýè“ZåÀk µ1á¬Ý¥ãCã(rî)˵XÖHI/(œº¤f‚!µ¨ÿVJ"ÚÒ€ÈLk)5lŒYTY™8Ƨ§Ë—‹Œ)¡(‚‰`ÌŒ¦=¹ËÒž¬S3^ÜE ™Š¦+™¥'GE”™n¦¤ÒáW‰#ÑÈ„æËB&L­*£Å42d8BQY6Ô»ð‹M†&…Qˆ#—Kí’ÿ¸›ä×2æ•zêšêÖ”O¶Î›F+‹Ï1Æ÷]ßê$å£q¸©D z(Ä÷µ»{z ¼}óã”±*µa4UÝñ6šÆAãGæìlèÎ /¤­¾þ¿˜î5ûSUŒpÊsL-MuÈöjd8P5P¢1Kj~{%— 5å0š¶ù4ï„ÐIdcŽD ²ñè^ÊB¤RÈ~åý^-°Žy/”Ž(G´®òK2H êá3)ûàXʳ±_þàÄ¡ÉL‰äÃM™¨†¸EBà­—ÏA`…4q¿óOR”s†S®yŽBÒÉB*D°ÓƒPE ¸5CÃk ‰PèÞëøÔÂÓ!%¥¨‘š)ZU® —´…™ZÌR83«âÕóLÈéø"ò̈8œªg²8Iñe™ù¥d@}V1&_žÉå<N3¦Ñ-µSªû&¤¢‚J0 óÿÜÆø‰B:k¯–֧͘2N´ŽŽDHc¡úц)?þ±Ñ†{Å«zmäKçT±q%TÑP¬êœ‰‘‚sÊÂçX,Yx¡hö ™%Âoár«y…ž7ø”E—È1­7 Éš¶:SQ)œÆ˜ö–aª˜¬‘Ï€hÒY>œˆ,# 4E0õ}`…^˜;¦/dÕ€\ý$Â:ý –@¢™JDƒCL9¢1!,_ b¾è¡3Ó«‰ôE*Íô_um;¾¤G @IDATÆÊ¥àH¡c D†$eWKLߨO!Ž”üånš²WF4Æ/…`ÊFÊÞzÕÅä£áÈ…˜O_ÔIÕ˜`‰–†G.KŸr7q#gj¦ S–*œV­ÿtL”EDi8¦ÓÅ!I¹Š_GRp鲌*š6r蔕¾)e­‘S:‚Z‰¤Ùļ2ÎàÐ&Åß µ›¦¯MVHH•®ÌîõŸH„£kÌ *½Mh—H©˜•‹Àôìi*eVŠÝCÅ´Qz༨®Uß>ÉÅIcCÈšÒÑ«¸¨©†Y[çR‰Pº†f”EG”_Ÿ~Ç7߈L$+ЦP‡ðñ9h&§ö0³”[Ú˜µalu¥§Üi  !NQN‚U7â#6°t#D´Üt(04QoÄNÓº}1zén‹$V_z…ŽîçÙÛnÀ;(œÈ:Ñši½q¼ûkæE…üýY'm”óJîöÏ¢qpTáè3ܨŽËÞEM¢¨Ñ”&ó‰ÄJïKKC³ýä0ë5†Ó‘N?) íFÕÏiz=j,š\Ñ6¶ê3A¾†]eÛy‚Äk@-4FÈæsäžØuk2q£êùðtŒÓtLY~¹›Êe—öïݨNµ$þþÄaBº@RL½Ý¡¸däŠ!pL[6fUsDé°t8)Ê?±ëZ­]4– "üe8™ïG5/Þ[½YWb‰rk€Ç¡ªçe¦ÏâÒ©%‰…äŽÌAÆá ðÝOkÌ[¯ÿí BQ ,Í9]/Fטð6DW˜õbJ>£¬7cÍ(]¨qb®œ¯þ{+òÕ±ŠžêÊM¸BÖŠ8õpa w”E¿*ñ B¹ÜJ„´ÃÓr‘étPÇo¦6ÇÝ$>D 2k[D»é,—øéãó9Ä©„{(¾èÝáSÆ/E‰#t™°[ ÂN+×’ù@%LÝý<h¾üqþ¯«¤Ô² [{ý4†Ç©¨Ñ”‚ÆLýùêÅÅ…œô/Ò:‘e”nê$´ ¾Æ0«UKU¬ùF nÄrEM;“ñǬ7´Yü>¿t'm¹9ð6J‡¬&…8dá÷',=À—Û{•D¡˜RªXK‘EÙ|L%æUöã¡OW…c*Qz œsé}Ü4 ÓIH&Ë·"4ÓÈ9üSƒ¢J&ü“ôùHá@t`lm•'*%|MˆZ¼i´FÓŒãK4Ö+}æéæ²h\<°”8©i@bˆ @'%~½¼8‰Sh9qèpàNµºâ«H MÝ qœ=Ž\gŒiœr—¸8 îÛÛ®é¿~ý¢l¥ 1 d·þwþÐ‡é «³­ô5i*š`¡VÚ±/¹æ!J3´øþÄ÷ãWÿöÙ㇎BävùD,ªJViL¬™Èu­½¥ !ë¨1‰p ªŠ\H Bèô¬·j%¤³,¸5âÃó%Z‹ë¤ÐXâB!%êa«¦P:r¥‘¼ÜΫKì àF¿üaœ×&Ý)#‹Õ°‘¥¶7SÓ(´Zv€É…¤¯íú|çW ð¹ÐÂ{Àoù¤M**DS9c;‰4šáíž#âóhM®±:/q{˜l! ³hpšF|]q 4'»)¡Í.âÇiAHŠu%E–)—ޱ6 Ç”‹”>MÎs®‰`lŠ N%XåÙ½D%.t5xJÇá¥yþ*M‹4´_ØaˆT7ªÖívlpÒ2vYr²DøœåéY_‰6¥¥šÆ‘ˆS¦uÁ4#3Åyý—w74F¶,…*Áç˜òiÖš%ÇÑFY¦¢¬¬Rø|ËñîßïèÝýÿýï§6©ø)}ÁÚ)¼0ט?a9÷ê)P–˜¯Ç¢à,gÊB­¿…¿ó–GÖWXøŒ‚5Ö3§*µáÌAH™ì’®ºÄ²8ÛáB‘MÓHÈ‘ÈøøE9¢U‘È*Z¢¨Å2åVQM¿„r%øœ. ‚iäBÆ[´D4ú ²)ðÞj%¼ô4ËÒm'ð…!»û÷n‹FcË©Ûz@¨#„áSHß´Ò8zà¿ùå_ôfÐ’)¯e`Oå@£}ÒoO8 dªÇœÂG¶Àþ¢9˜GîS³Õéï¼–Hç0M …ùÛ"³·ðÌ4'ñÖ[Ê5À§Ìø‰ãK„sb¦,©B¢R;Í09¼8ðµQQSEJ7å arªøñee%SÜju£^ê•ç'”–iËS‰_„IñK‡XALš²àm ˆÉ8m-RÇDøFv¨è@|5á•áÙ;¬Wl!/°¤X/×H¸P«R¹BN º-m;À—hÚ±ñÞê†^'.Î?ÿü³—j)|YFå{Ö6Í™[¿ßª.¥£S]íqàŒo4Íä¶R '¦\{+„Ù6þøÕ?¾{M¯ ‰kƒ ܪSK0D‰hš‰rÛIH‡ƒ/Ôþ‡§ÜŠŒZågøU*JÍŠÄ©œZ¢ÈõÙ’ ñ9í ©ug²ˆäHgÈ Î¦_ÈÞ^ÄÃA°V‰—nÔ†D!Ž“ÊIËOVŠ€Ý +Ùg£óÙ–HÉ%Òô@AóµG9_ŸŒ`½™Þû7­O)8oþ¿N*çêK_:'ýF…:]# ;‹´ªÖ>áÅÜ™‰# dü–¯·©Á!hF†Ìš"3Ó8ʹù2_3|]™âCŒö“7ZBšS† ‹¯DUÊŠPð %ˆ&kåp˜,‹â`6Å"* ÞÓ­3D&Ê8+Ê ¯O:•£ÉýïþóŸD¡ª=E¢u€s%ž95•b¤˜¨)“•C Yºh-Âñá)‹®§,d|N„B1bf6ů&àë?j®4 ”_6Ÿ”®ªhZ3œ**ßx#¤ÿ¡D§ÐÏ!¼û;­ãYåò•ëiñmÏkŒ£œŸyxpL¥sòM;ÆD4_‰n”BÀö'>dËð=®\êÈ/ÌZ\ä‰K‘عÞê ­¨Ý3íà¶®§Dµj “YóŒ/„&T¢1ån(M€Æ¦eñ!Ì”™²vÉnºžMùlåJ+Ío4eCSÓ³ÜJÀY‚)­‡Ïy¢ü"Í Á;Ïc›ð¯Ïÿ÷Íé¨[ #µ|Ñ–¦ Žfd¦ ίç|Êýë_ÿúÎsȉѿH¯\kÙX‰kÏ•³-ømKdL8?Z>N ¦È¢¦@SN 1µÀ%FH¹¬Î´Fñ5 ʤËÖ’tS q ’Zu‰e 1S= S.ͨ¢¨Œ_Ï5œ`E«ÅÁ†G‰Éæ·œSûóPŠ\ü锲Qt¾ìã,L¢žFªƒÆØFù‘M ¡Õ Å%Ø‹# ^"ÜŽGÛb8Ò‰ô]GLH]Y¥«!ÄãÝ]ò/ùË8M|šàºÚ¶^ )éÈueºBpÝJíà Õ!œ/1ß”}ßã÷½-Ü·%~®óYüã-‹U®Ñ'ý ù­ãóµOÙzèôÕg­v}&%1qãn‘BšÛH ‘ˆ†ü¡!¦ÿà3Mü5¾Š¦©™&Q®U@­ºS~4kMG”µN§"f:8@SÏøÄM'Ë™NË”G¨”Ä#'ˆ0ZQc¥#¬M!âiŽŒÀ*‘šƒ“B‚áwÔvÚ‹gß¹K¹d^ ýK@‰4%®C¹¦â\?Àö|H}ÂC$VZ“þýίœ–NuU$Ê22ç@ T1q*§¦hø*" ñ[‹Íá»üѼ!0dR¥ã •{Š]{%”ÏY•¶…KìãdÊÓG£,=S!>)–'DVE9Ûdþøœá|—Ñꀔ[ldcKSŽ”i4>«C¥0ubdk¾¢-Q­S"Ñò¿û Hhñé*\¦ÇX+8’•?­}^´qTzˆjHn8G”/é9Æîûv*¦vÉ  •®%ŸˆùÞ\ø'í?ÍÍNÔ ‹Ñbk ¥ôÚ^ÿ¥®[«f“•¢DŒ^ü}lçÈr“ò˜ñNÔuÁL¶BõOÙ¬ï|ù£OW»ê÷…ëÄ´ƒM–šiíÕ[ýóï`~+uºûTôΟ÷·‡JÔI‘”ŒA°|Uš2ýÄDã 1LmXA¨»|)K„Kt6Ûä­"…²¶?À¯:ŸŽqèÇœfœÑ„€ŒÃDYSœÙ%y–, ¼X׋¬6 ކÃòáÞQvÚ=3/LJÓQÅ&T.ñª×')4†S9;É1-ÄçèÁ‹”ÓòC®W.‰™¶;ÿ•v@ùŽ,%ˆó™„êb:£F¹ö„’Ŕ˗+n„´F¹Óª†¤†É,Ήo4âD¦E«šºF!xN4¹ã§LE6Âé XZ½5çäËJÇG-#X?ôMÛ“D„€j ©1‘]8ÈœWâãïx+ °d>“‘ãØk0ÞË×e Qb=å›êoÍYKÕG:;µGÓvÜHjúD´q:ûl•©j¾ç1õ9€_¡ûØmÚ×ÙŠN–fµ€êä·êjUˆ_E‰nâ41á²<Ü.ýèŸaÂ95S¡wþЇOÐ5I¡ŠUOǸá(Á*-$Ec´ªè|oyðI}ëx$÷·“¶¥6ì-)¹Æ•žlmà'-ñµ±VÈmQbR@Vi…‚{ „¥‰?ñ@â«ò@ÃBæ sò ñÓÌ1†«+e„±é²òW¢}(ÚýÏ!B픿ZrÛ}ç—?./ÝdµäÒ!¢™£1GŠ/Ä瘊š²R“5\µ7ù£ gf5RÌFQ05’5’jÀ¨.„…t"Eâ§#…ÝÉp)J`Š–E22§µàÀùLbéíF)p&ÁBà©ñøÏf]ß8M¹¦é'XÈØÒ„"p€ ¦0Í@|H4çy¾yüV—ŽÑm½’*%Dÿår²¹ù²Áüs‹Ì3êC@œp‹ç3ÑVÂ/´š›"&_gÖ€ÉÚmMØ:ï¹ÕBÖºô8RZs=T…/Ýe„qêÊË5'ñ·ŸaýâÅv¸«º¯á+¡èr•&d¢Ýq¶:]Q6%â›/þ[¦ÏÂ4û/4ÄÌZ#µé—öù‘èöIü_²}¬iêäZîy‘ —ƯsmY`Q¸t¸Q?ßîϽš.ò¶šŽ\c›FsSšé·:#¤º¶Ô4ÙrùÖÎp„Ú“l)Ä´ÎR9‰z¨SHQ|k¬ dS†&ŠÃÖ6²U!Ö¡¢ïü³/‰ýÿ¯•’ÎNT”ƒÓBL5À€¬ºÆ8LŠ…81œÞ!/Fÿ$ÅÔÁ¢¯›$£O¶cm·ü˜||cLò!:4e¦@¦ñêýèDèG¹‘W¥ÅJA …ÀøªðŽ­ˆ‚(µ²L)¹øö‡ƒ¹”>î™B)HÁ¯ç’ä«¢·Bë¼i©±J$5‘ÓëÕ<! ˜M-}:d#ã„Y|Î9bëŒÃ.ÎÇ=ºÂ Á‹ù¥J§e¬˜&œSnÌJ$" ¤™Ú®Fë¯7¹Õ·lÓŠ¶ !S#œÅq ýúågøÞÐ#¯"G ܾý®Æy¼åt‚ÖA¸žS–WÝkš[¿¿šÂÓìíÖ_ÿðÖØŠœO)´F)šTš•þbÄtÿ•¨ £©?A÷eÓœ£¢±}ŽÖ‰Ëwâ;iè¸Âí 䵹­ÎÂi¶r;åÚ+#ŸT= ³ZEƒ›v438œÁlÈÔ_t{ÈG&›N r%Æç#Ä‘Èaö!Yúd ¶‘ïC§(©6“OÍ8Óº5ÂÑd-JXˆÃÖI8¤­+$·¨)q_þôÛÒŸ¾Zt¦IYi=×5Î:áã˜Ö'Ÿ¤,¥ÞŒpV'BNl<«>œ”ï9ûÂV3¦Õ¥Ü§2–dÄë­('K/Z'|„tøMÕÕ'_”Ý[×2LÇ¥\ü%žZ’úF† º4Ïtl,DžV!øj—H¨ûhÍõT®ÐÈèE…˜\S#¼š*¦Æ”ñ›ŠÖ¹“;GˆOÊ»’ ÆcÀý.0N£[9sÓ÷ è?A…“)!ï¨3¥Õrmð«NA'½žË5…ão]¥ Y÷¥™¾ù‡¾î¿ÄëŠf˯P«0Âé9¶×èxcj»©6X:¢˜>§ð­CÄã‡NÊÔø®d²,„2Í«ÂúTÑ)¨«ƒãóWˆOAè#ásJsýë‡!—[b") Ùç»&œ•n$+×ÐtË!BS´–ßXTV&¥ºBë³à5|¸Z|;€ÏLÛ c!ç¡/ïRßú6ß)‚‘&ZR qšZ‚(›ù©ÕO@(‘­Ž¥æÌL§”g££D-á³ÒÕâSf|c -ó‚?žø¥D VbÌÕÅi!!É^©gÐv¸ZGãv^¢ö®ÅÏš8Rð#çÃ9˜g Ÿ«èøÂÙêrî"9˜•èˆßiBj%ˆÐº€l`¢8p¹,‚1²NBzFíPR`!¤rV(µC®/Å@ˆüÕã\‚G‘ÓÓUÌÈðKq r¿‚g‘)Á©¹Bé—¨JR¦­N~ý‹rŒIqX+ò’â·˜nß}cã¤ÜBÌ´,µò•N¡ã+á¥ØsÅݹÆFpòE«‚ö¸†tóýÚÆôçHì‡ÿªL²Æšj;²r¦¢ù-D@S›™²©¯ÞiÀ¯˜ìžDR™DIÑ0"úá(ÚØÔÈ´‘S]N;À©C8?~ÌV¡sÓšç”n¤ –‘¯„Æj)åñ9e‰2Ó¤øE½âyVYQç°ôz@£é·"dÈ|œJ+Àø”µÄ©s½áÔ•Q”HÓ‹Êzÿ˲©‘R‹©X|¡¢UÁYÿ§×ϧ,¿cŠcú毜ü éÄ=­\愱pÑÓÄíiC€vx«€—xÑ?ÔSÀl?EÛ.=«h4åT‹Â@ˆ#ëäŒßHM 5Qï|FS#ÙàsºçT‚&'ñ¦%òá¥sD¡q*Z¨-¢@V9ÓJàÛâe‘*ŠÎa¢‚Ô˜(ÜŽq*Ñù$hùÆ8µzþ3æŒÒ„8™ÐZáã·×ã”+¤ªò¦•/eÑ#œQfw¡À0 u†4JY¢~j)Mc…ôÍ!ï‹ëõ"ßÅ/­øl²t¼JxÓ'BÊžV®åÐø:azf6Ô*>šÏ"ï|ùƒIÖg"ª7­dsDgªÄ‡ðÈæ}sügŽ[¿€åPÛZl‚³Ù(Ki‹Âá(dŒ/$‹¯Všæ嚆äd)Sb"¨œ\–8œ¯4“Ò´®J¬Š£€ ×åíè»;8Rõ­‘ÝcžT ˜üjñ×X>œ&¹ºÆªK¯±t¢y!°«¢¯Í_¶œõf!­T Ä´À§S-!H[çÌ,ª%†/Ê!åÒè¿\²ôoL¿£³.ÑŒ-¼BƦ5V“Èj…¬I´¢©ID ÆÉ¯=ç›õV®–VN¨ê¨³ÍÁµR:,òב¸Ý³™}ÂVÅÚK)TuÊ,Ÿˆ­3E«ŽBp„‹x¡Ì]aëBCå/k¹‹jLV|d8ü»xÈÀr,ŸoK;Ù8Î Røp4F!‘3¦2H8@ÆiÃ/…ßëQã¡QL‰GHt,'Aœ•˜‚ÜüSû"¬œî…ÖdL¹Ö‰¹>qè‹Â‘…øñ¥M_¡j9ð9h|éi*'×h ¬&i"”’ŸŽ¢+‡,ÑÎ[Eé]í ™þhÒÙ´ÿ‚Eù†WçN_Ïš0‹u1@¬qkál±Òù‘G#~)}<zEj'Ñ8²09ßö¶çísü4ã@„X!`瀞»n:§Ãˆk^TºŠ˜á‰HažÖ¾uÁ´|£Dâé#K\ÀÕJ›J‡&¿uUÈ6úÙÏ;ŒqºíJg-ÐHJõJœrœº…ë¹[?gH=ˆbÂ}ùS4üÙ¨Ž~:|=\}}\>Dt«;f+Lùªà§oÊ‘žïp ÂlK9hu’‡¬ÑãÜêÖ?f|ëbp‚l L®ßâº-È’Â8ª0Y!r¦‡%n¬–h‰å…Ú"¹ÐpÊ2²WÉñÉršÖ¨µc¦Y!à,5#¤(¿\#°tNÊUù¸ßB£…cð•äsZ'B Ñß"áê³ø@š#/³Ü­ížDˆÏðµÊÁi7…JÜç³kY·ƒÑ€|š¶Þ[^4jÀÆ+õ9)µV( ØLu!ß42Z!|ˆ«Ýi§ÐVFLéÆü%6]èŽyç ´ü‡èÃÔg|fmˆrL­ÂÚ;‚¦vw臔bÄ7v÷䨫…Dʱ¨éhq€L¦uR®L)• qiy®xܺ‰{+Œ/jiÞwá3½ùÝ˳»°›Ëßÿþ÷?¯ÿžʬnM¥óm ‡ ~¨©¢:ŽlÊê(+Ÿƒ ´)ÿ…Éê1˜¬ZÊÕ‰¢ù¦DZ—“ ?åó…ˆèª‘óο—k÷üÔÍ9LM!kOŠÄk¯©EÙy!çWE:ÐXoš D`“jZh`; d¸žÎÿãÅ?d£_7t‡X¡eazpÁ¹Á¬ËcÞ>à³öP¨ž-ŠßŽE0¥ƒ“°if8'…Ä9©••/4ŽÆê¡¬¶‚¯=!d¦Þb¦VÍT:ã³.+D”ÿû#ÌD×4gSa*-éÉ©jjTÆ “SCE)´Œø¢ë†/Ä0ùƦ:†Ùuõà#ÈB–™³¢üøÒE™/Ê© £)CsHR;œµWÔºîjúqÞ¥ÔÇëÆ³»ŒèÝôùë×/—‡~ê-q'wëBv Ð7ml𙨮¤Ø®z( è»æiNÊí†N¥9©qÞ}Kgµ!…ƒÃ µ|S]¡M­S)|C3¶>Gˆ§ÑtZ‘²ŒÈ¢Ž‘« ç™Îû‘. ž²›…§ÜÓ"òÃh«½ÿñÇÄÕbúéZ¨ˆš5l äsÚ…øFvTþ÷ßüåWT·3mXvØ”Ž)ÐZ¨U‚c*T'…Öù©}…àÀ˜Þ£Ÿ­=~£%ûg_ª+ÄÊMØb ­š´ÒùgÁ×ãÖnç´zÃá4&‚“8GéÈžÇN`wÓºjÄqgÄ¥«k¬hšÚð¯Ñì9‘{.ß³Ááó pÑÕAvßCS!Ö†§`ÊRî®ÙöŠÂEu i¦E9¬&cvRéDKÜXD8R«kl±@F¡NŽúEV‚Z¾ ÿ“ÍA“Ÿ(²)ÓPºqøép‰- &<ÄÈpà¨ê²¶ Š …ÑÁa˜.L‡DzµÐ’J¶Ò©ñ%ªkÄ)ddã×Xx…è+T®(&¤rÑøe©žr!S}"¸% ,ôlô·ß>š Xìú¹–~ÖN­Ý .ÚÚU‰iŒ#ÚK§/4žîvÓ%Z£…”YÕÒR«åñYûÄ„”( OŸ#Ä/=Ä(%Ð*¤à¬Ä.W!&WÔarƒð‹š@+òHs Únš¾öüÁÃ}ÁË ÐW³uînRjï®?°öZ»*¦[¾qçLEÝv|ëÄmË¿[”’U/¤.Yͬ!NœBM‘[Ú‡Öç×^ÿŠðíè êX+Ú¢ˆ¸UQfø•3êÇ5•%Å&˜Fv,øŠâàóY²@–”SGÇä@ˆ>´ç¾¯7¥Äéæê‡òŠâ'è„ñݦÿR€ÍñÁOÃý`D·B•®%R4E¯ gÉ–otX!kméÝÝ£u¶²LMÇ'M~KŽiTB:§»Ÿr–ް\ŽžãWh¥…~ïW[|e08ŒÃèòÕC»ûõ"X3Zý•e+)ÈâÔi­éëÌèn•/´ F Ù–ÝÚ¬Ä2ÂMùBáu¨Ÿ¤Œ|!8>5p£‹OÂi9@N‚LuÛV¦3Á 4S‰Þý¿žs8_ÍyìPi¹lmPË·¥åBVÅtâp˜=PûZñŽX”{e[—«¢,…LáF`ÊkU9U\Hd)@G‡çÒÙtøå ÒÉô9dDÛ‰ÓµwƒØ¿ÊF`ždý\m;VÈH– 1Ž? >{ »õx”U*j©UKO6Ç… uhùhªX>Îç—?Jx-µ ü•¦  ýn£B ÎÚÑÚÛá"Z{…4ÃñîÿΙi힣 mÛëÇÈZ—5*b¬Êé麹‹Bà})T?q€8”;=4Ïjâ 8¬–À‰çØOn€Xú6dUèK7B<-öý.è~å£Þ¿þõ¯¢ƒÏºØ9ZÈJ «kj¤–?YüüöÍzÓD“HƒMØ!j»ÖLÕc—žæ‘ø|¢ÇT7%hZd Kö㙌Q—*|Ñ>Nù˜¢øvAd~SHW8B«•¤Æ-Y–i‚Æ‘ž¯D~:@ÌÄ)X[ÍHá 3LmsŠBØ‘McM1ÉÊÊ‘UÏÆÐ*Œ ”ÂXdS4Sí½óS?þÈæl³Ó©¦k£Í)d”Xuþéã*Ýb1åºÝ¼s»œ\TöD [ ’­®)¼Ò·98³#Ò™Ó5‡á§Æ™ÙAé¸!Ãí°Í¤ÌÁmo4àÛ¿`yøFØs´¿ßb¶tòMK¯“ªXø½±ÚÛh ŠÆDÓF›sWÖX Ffºþ«Tמ8Nü™ÓÝ­5vP.á£,ÂÉjCW b* '‡Ïà¢ážjÖI¥Û7R5>qqHÊ qœðBȶ^VW5 ÂêÓCµvÈÝ_·òui<Ûpü4ë§t 3²wµ|'R‹-×è¬+ZÏIõl mˆ*êV ÿ¾xk4ò¥¤ƒL³,8«–æw²Uº1Ž‘‚,¹kr×7•ŸãôvØdâ¦5ùñG*ÔzBåW†n*뀣ª|#‚‘\Ì¥è¾5Ë­^šIuâ–"“&‚ÀÖ„)Áè`6u/ãt¦ÜTWh|cT{mSÍ ¥o\ŸKäZW˜Jëßb;k+1BN:|§”~äþh}ù£(¦Ä.mð×X T=S!v/¤h"¼Àð­ïMÓ[p7k‰íÌôëA´MW¨}¨Ÿz«™z€p¦)duM‚DZ')c`ú9JØm]u†˜Ê5úäþð] ÜsÔZÊÂQw…TW…q„_3øÏ MHJW_'‘‰3ÓKìC­ÕÁ{yT‚_ßf¼óϾ\±npRÈÖê)s-Ä>¤o+´]çãè “¬N}rÜý[ÿ…ÙLßIÖFuI¥ViúZê›Cmàˆ&_.'+QŠ©I8œZ¾Ñ5î¤}x¨§éx´÷dxRtˆºâè ^V ö˜g€«r¡?#û nJYW¬,ߨr8;ø¬U´ç˜ô!p¥9ðš4R.šŸl²r)Ã%Æ‘2?&åÖ^­é£‰c¬1Lš8‰pdKÑ6!±´EŠQëõ¬‰¦…Z^¸ AÔî‹f@Žª¥.“S9g<§P]ÕR)Ô„*-Ê:ºD(ã »c: ã$Ëo§–0Y)¢Ú6Uš¦‘!ó[#òýÈ‚´{)¤o¬ÉŠqoòžÿÑlWª+MGE:ãV×Tc4Ãq8M¦­ˆ¬‡È¯{è}ª\úâ·Ò%Û;«®n‰éÄÌ_8ÑŒ-A4}`ë2åÛLGJ4åЬË{œƒ>AŽMóµOD¡)XÛ9å&ÂÇ¡ ë.ò­_3RØK_WÒµGŠ_S|£)|‡ÒÔß!öák9íùêßHDÔÈÔ¥£AÊí)µ ˆÌ©´‘ŽDœ¢Rîtï|(tŸõ(U±ôš1%E„CÈ÷˜2S]Á™¬€ó!9_¢nüBíÐW1Ͼ±twö@êk1‰²l…‘O?ß”Ÿ,§-RN'ZoÄŸÀïÿ•¥ô÷ôªëYŸÈÆœ%.‹â¢4 ‘ωÃÁ‘˜•GϘp ‡`)m¬,fÓh>Züôk˜/„É$"œLÈ­˜0ÜFSq¢—l„£¥bäCÂW&#«Œ‘N>ã‹*¡ƒ@8P¦ T ÑДaÖ¼±id²¨´&J.1ã³¢n. ÀÄMq8D8*rÖ„ —¨®Ž—¬•Àyaý7J$’jEË2S¡­N,\ˆ•NÍEî’u ¹c:â*ÑVL- Ë§&#[)‚MC`p#ŽP)ËJ¶º •UJÌB‰pôà^cc^üñ-ÁßñêY!c:íISju(ÄBlTÑÀ‡‘”ÒÖˆÃ12"¬ƒä§Q9)Sø³·Ú‡r¾£pÛMA u=¥L!–C™vNvÒj§6îéµQ®,øÎ‡Bšþ&„ï(Ë­„Qu ŸÅ_š¯"¿Š¦€r­.8Ã˜Æ wÜýŸý1Æ; [G®qúó·v›# ×vÑ ={ ûˆæ“‡+"Y­ÚÒÒ“íê¦Ö2·@Ψ½ªÃ‚ê9B”ùÉQËH܈SbJ‚_-¾f0!h-Vˆ=õéËb8‡A$~|§yñ?$Zuæ±Ì±Ldõäà›ê˜ŸMŸDI#f)ÔD7­?#0&¿èiöóÛ"[ªº4qîE-¡B¢•ž‚)ÿ*œ1E“.Å”%e*djÌHg`¥›Ömšo^í”{Ï"[Ƭ¥…Ðo«5ÕL=·]B«Ïr½o–+ý™aúöiû†a×LÓÖ ¡lå9ré¬[~)ÓŒS'BáZš%äˆ&kŠÃúDå‡+®ÉD6ºcö”˜Fmà#ðësc޳(çõëp)"Sk*Q·j™VK·˜Œ~Ì:ѹoÖð3Çë§\’•ÞNaɶ½¢µ`ÊAX-B“uV´ùÏz׆+ˆB‰‰´i‡@ `Õk%ª+±~pðøp–rÇšÔù¾ÿÉÿE’t×Y*½ÎµÑ&вJäãO¿Ñ­µà˜Šº9Æü:t¤q²B8ùÒ§ 4…³DhR6•é@p¤Ä©““pûœ“Šßê8ÈÌûUÙ*J!+ŠÌ ¢h@|£©(‡Ž±Gæ”{NSÍ5¢Þ¥;ÛíXòË4ÊY¦ÀŠ™N6G" OŽ\¿¥›²|YùcÂÙ@‰8¢ìÔ¸¬ÚCƒãƒ¯¼³µ²žÑà@)l –+¤"f„ðJÄvn¹¡|}EEûjøýÔOHÆz Eü4tµTÝŠ¶ð|Ѧœ:o~ÌwÇñsøö„TûÐISëªN1]!Sõ`ìÜ@65šŠê*Bé¦õ „”!¼N„ˆ× Ï¿ýæÚÝ¿wWˆý”Ë4V­ \9ÓÌ‹€,ß“-…6•ÒnT¢n-ªs½#?‰ø‚[Ô{(eSéÔ8š4–˜Žmá×CѪÃDHÄùb´¥=öJ—˜HE%Ú|{ÞGCÍtìôŒ¿ãˆ\Ãw>‚9Jxñö§RE}B%¿]å·V«F´ÖŽ¶Òº6-Šö­ÙŸÈE‘i–¢`%H)Z'–x#šè݉F_4ýtªÂojôÄêñÓÒJßh÷H%ÍQ‚–¯a*¡)KŠZì¼-" ˜@ñ=-\×FGH”ÃZ*¦zFœ´åô· £4‰³Ä9õdJMº4¶) ’xúEù¬*iÂC,ɺ—à· Ëä0„ZuîÊÍ/´¥ÉbdáÆSõ:·V®hü’”)¦«]ôhýd>ÕvVIÇUK:'M"Õ…¤ßðeY‘cadœt$¾ó¾)k«ÚB8k¦eVn*7_QÄØ†Þgϵ'™22ƒµ!eŽºtg¶3Êß{¿ý:Kÿ^Û4¹ª0 ,!8~Õ<@!7/Žï¾ý{£ëî_?¦r)›Öê6xQµp:!ã˜zn½(qÊ\æ%×É©+‰d·3q¨Ua.7£©6àù­ÑχSãëÁ[öG±çÿãÖã9„¯²,) '%OˆO­³±6ÎÖ_LÓG)ø¦ã¤cuŽì³g’Ýp÷÷‚"ë¡_jÀ¶B¹üÎ=~»ÇQ—™Fà#¯óÍ-ÇŠúH~jís íšÛen*¥è]\tÓ{4_?ª ˜†àÛ>gÇ¡=42S¡|c>›\«Úæ°ÈÔø ÊýxÕ™ñT¾Ž®±e#qªš™\&§2|µÌT±Gú2ˆ…Ìíc ´Úš+]´©_бe$^"œá¬í¢@"ªp L«)óWH”&—ÂòïEù,5ü¤R Òõà>õì„F¸›÷¯Zu(O°]âSFhÕME!Æ–ä”h3{úºûwvÞË}õ5àê’nÿ--Á¤j¢3­¨eêÍ­¤Æª.dŠÜ‘âDΑ‰—Â7"wÜùL“”¢m‚´¿óí Ô³º¬„¶ñ«{µü±?É<§_–wÏ|²>Ÿi ÁØÑçך†M[ZÕ­ÈQ¶v£þß¹íº›÷0V´ˆh¯ÓF%p”«JkÒ¤EÝ÷PˆÄ·gM_›ª‡®Å&5Í–ä’5­®ý饵s©˜8­)§#ûìDµ¿~ý²:YüÒåVÑT m0ëÁ”ˆY¢¬B/vAK. :Œx Û:jÛm¡du‘‹`œ¡ñ[8‡2f_ȸՙ¦ ÄéxI$›2|‚q¤@bùp"p ‘åòkGô?îwu‰ÁÊ'!ŸÕM!SÑÖ Ù”bK)ñÛñi­œ›KÄÑuêp˜,cj9!PߦU¡L§…Ì+7²*"”eåל/½G·(“"O§>åÞg8)¹MårØ;W»,Í»Ò(H‘›¯Ãœ6ßXÏBz°äZ-+°,'.²ëê×%üôHuâYþ6“oTŸc´uF…8s"Äáé5ՕĘ)ÀcYÆðÖe:ó…¬ï¬'Èæo'^T%–Û’BçF|u9qrøô1õàQ­Äƒò¦^?}E¦"RÚyë’hjá§öµ'¦­WnÊpÿmK¿“A)£D ŠõÜX¨4C“Ã4&±þM˜6ŒïùÓÏ`èÛvc¥+J³"Á¢ºª¨ÂÔu‰™:!-§öl»o~¶i%úZϨP¹”ÓW‘NÕ…L‰@# Ž¿Ì:‡<+ºêÞ¢â K$ÈåMµ¡Ð©q»«ÀÛ! oí53)NþÈ hj¥l ­Pm@8v¤?ïõí¡…kƒ“YÝù,–níÊlš#J¥ ?PruUÈJA _ˆß}žˆ‘N¾Dðr×Ê•Ä!Â8UeS#3„SoKéTÃ,¤œ-Ê9B×Y[¿~Œ©u9µ„B¢œú©ÖôÃ}ùc»€?š×=o{±•®gcåŒ[fŽÍæ˜j;Þâîá¼6r–‚ýá¤Ã“­+`ší¡–J ¿4>μ|ãR´ÁoéÂòI©’2§ïæÏî>9õuùʵ+7YÑðdù­Žió_üRËREW¤Øýªù”+@9ñ˜|Çb‡ø’ù~ðQÆwM¤„µZŸ4 l—ŠBºôì§ZÑŒº•ˑ˗✴ÒïkßP×»Oq}ê¤%·v|uÕ¢À) ”^?VÃr¥¡,KWp~å |•&5N}Âùv©Å I4J”å|0Âa%é“^J‚BWÆï[„r­7´¢ñt¨GQcàÇÇ19-LŽäð8ñD1×nxº˜lHêøÍœ8 ÇDSÈΩ1¸Dެ: åPKR¢i‚,Y-¡Ä8ôùœBõ„`V®±N¶R±§¬ö&ëo‰ß~OMöÁÜyÝ_¤Ëm-:aüz[êÈÝ´&«È/¡fмþûo×<”û:¥ÐÏ*¤‰¤YEŽ~àUÌ©=)e2šF¨±ÖOPÈfš2 ,2}‰Ê…ÄYQ·NŸ¥¤ ?˜¯­üÞŸ8\nÕm )Ë(T^{©Á¿ýAQQGÇ—Kš)™C°öš†¤©:}æ®a!eùxñÎÇAoÜf4[B‚® îï­…ršsix»‚\5Ïv˯4Zm´ß¡Ehúí(ÑÝŸx²F =l¨™R€Dà°zöªtÔqRö¡©D 4m3 öÇ|ø·mõÁ‹fESÛòi¶?F!äÖnÚVĬÛFR ¹¢?nM:Fû¼>MU7æX‘PÍÏiO„Ú:Å¡3Ú²*Ñ80>¦þ—X´ºšá¨Õrj9KÇ¡ÀNÿKó¤søœšÃnxêpLÑênÚù)ÔúuY(ÁøÒ­ûJàÔŸN×@ÇYЍQÇX34Sm[Ó4 çY;Ò(‹ ‹–ˆ‘‘u¨Vpd1—ßÚ3å#¿ù·_Ê>ï%[ˆBüú $(x–÷yknŸ[…®pø¢øÆg7Mœ»¹&½aµ@¸µóÛI#Û†(§¾³~LóMGU1MãJ°å™“à…UPv+ùÛßþæ >Œ¾žþã?М!øzF°“FRʬ½…ÔFÊU”"×ß¿ýñwOÇÖXJâ²çœpâø¦Œ/¥~D5ðÎ/¤÷å'wK¦oé­…xŽÌÍB_-)ÑξÃá¶UWrµäÝÿwA|«ÖѤŸ‚‘fK®:ŸSBµ‡Æ´Ñ¦Õ’ö¨ñ…ð‚çú‹Ï"Ô|óã¯2#h4%’Ÿã$ ä×UL)¤øU7•U«g§Öiñ2„C·œ¦Û%8Ù:ê(%2!ußx?cï}ÖX´ô¦‰ó9Tá;Ç"¤L!‘˜FÛ)%|HÑO<Ž…­*?-ÉÀUm£…Ú¡r#˜2Q#ÇYØF¸žuÀ&uq H¤}áÀ!E9­Ùj©iŒq€,5Óš,‘ß!Å1-E´–hZç௴DL ‹S>A`g¶¶ë­6üîÓ5Œó£¹¹ø€¦«Îc:”«¢·ÚÛz ©ÒŽi 𶉠ñÊùf.u‰²X‚k»6ìB>‚êjÑ%jÀ§†ãCŒE1 ™’-ë¾p4 ,2¦{D+…<Y¯‡D2d]Õ^:¢†‰ÓT¨¢!öÜ7KßÞe¹ut”^WÝBÒ! IöZÇÙÕ.ôæ—?þ ã~×% ºtØÊÕCú|!ý»¸t‚ãÌéø²…ÿÚ”vZ–Þµ©5x§z}ª•ÚSKççÔRS>AOÄwŸ„úY„ÒL'F¥9L Ðò9¦L9ˆ¨1jÛhZ3øÍÀŸ]¢&Óp:@ŽQîü8åBÐ~örþ·t8ßH¼”§Šº…jÿ­1ý@~霚1MœòZ 1 Ì ÿì] äKh£›bW ®žQ[u`4%‘"ʵ¹ÇL"¿)G”lNé6B(M!IŠSÂéŽÃ—²bT¢(¿”œÊAXL:”0å£Ñ0~)õ\ŠQÈrjÌÈÐ øü£þù_/!ø£9Òþ©g%ÊUNkœ¦ºp{¡)ÊÁšr qL…Li¾ó…¾WÈ~ü#‘`Ê49¢A]ñ·v¾ðBF ´é‚dðdÑjÛ”Ùºí€5R†£Érxö5‚„»³BLVcÇ‚O¿êB5&…o Q× ñÛŸiQ¦ï³QüÄ%Rh±üUÁá…,A]¾•sÛõEÿµ©Ø¿©f97RΟ”6\på|Và@$Fk ©1tÚá¥uäjÙIÐ`D–e 'dªPnR 'bº,S¹!´¾ùùZ}ˆ^}(aL³©*+§! éw.I1­n¥Ñd阚Ñ3¬)ÿ™IôÚꎓ2C6â¬1úá‹"°Bšá‘)pŒ|š|gc—íŸþé܃dÛ7Ӊ˺„?žyðˆ`Ô~¥)ˆ65VÔ^ÙÓÃNÑsÜ霥ÜR“¨½Z‚›ê$5üέ:ë9»sí¼—\;ŸÔ·mèÁ@¨¥©R"ÆW]:Ú’áNT¹|éåæÇZÿo~Dv5õJ®D Ï1mj£†b8¦uÒŽiZH'üÔ¼ît÷wî9ô@üúÏ7Mß4Èô6§©(ƒ˜2ŽDÆaŠò ¥ðñj9HUùئm=NSN+O¡¬D€I; ¿¬n4Œ8!˜ AÅvÄÁˆÏo ™ÂheDŒ!BõI§ ‚/âÇS݈ƤèùNÇOVé­·D·o såÛïÖóïÝÝÂv©H¯4¤B-¡¶•Ó¤U·¨©•ˆÉ1>û·”ãç¸Z|ûŸfO匬]2V.šqûÎŽ\F†Dk F4kâ¨αF£ÿ_VØ7I-U±#H0Y µx$sX…Œ|âúq+trˆwóÚåý·˜•@˜¯[µÚ(8ÄT”ARS¢ºžaïÜeÜïV”>“n-66MSàôÕRH•–¿¨,“‚ÖöÚŠû¹p{øÉ%&ºRäÚpúœÅ'kß4SÑÅV‡‘¥´©ÄzÈw÷ïc¢{ËGÒª%â—¸é8é+”ø˜µ ÈòÓýý(\ íÒFÝØbL‘cÆ)·z¸)£h‹Ú¯RBD㤠Á¹—¨P"ü‘é0:!~`‡'„—Îäròeq<~·pY|Wø«EŠr)J;' Þnã? z‡U¡Q.§6œO‰×pÓl*uñ˺¯K·Në¯/¶ßv⽆Y«®4²*-nŠ©Vm Å4•îcÔIÑZŠC‡Ó(Ê·]Ô8RŒ@ÑRø.6×ç[sÁûK©ÐçCêš«ËÁ¡Ïôéäb \ !wa–ˆ1'?§]š`²jYƒFª éª^•oO/ÝrKl¤àø¥´Wðü…RÂȘ8ŠÒ“2}ó—?ÎIç^étê!ý휳­6ÅdB@£6JŒßl¾?é×$ü«ÙÆþ N Í'?§Zù¢Ê9ÕüJ¬O“[FS"uÈÑÌ›)äªPhÏåtQX&A!Æs€Œ¯«öjýÇͱ–ýûçîþé¥04ãÄMÓo¤s±>¢Ìn„ãè!Pšá"dçR©ïÕk©i•c\+UÅï0Э-iNÝ IMtYùíTšBDl1RJ!:Œ?}‰[˜Zp A«>³–:”ËO­b–HJ:?…rõ aR¸ƒ‘]íû+w%žn4Î'…$ºähr¾Š¦ÓðDLï ê*š)²©Þ<„о1}Í*ÝB4L?_(eQfjÄá ñEsŒð!z`Ñ„˜Ðƻνs¾º˜nšîVD®ìÇÓû‘­‹ÐX¹‰´–Ô€¦µÄ÷âïEøë1òi¬oü4Í(LVb:ÉBXG¡†ëO4DZãP¨1wœ¢ßŽÝvÕŠC!NÖ¢¢‹ê¡64àf¤±‘q„М]·w¾üq2øh%K'Û4SRd9mލ©Š Í’çl µ¡:ÄÇÝöÇ?Bøøå¥D!YõÏa¬ŽP9‹2šZ5²68V«ùUÝŽ…DÓÐ%ÿtè‹x'Œ®îŽ6ARž=tøâd5S•˜üzËi!|Ÿ‡úý1â}üÂÂ)E(ÄÈL UÎ8BþÃV Ãhz£Ì–Ûôãeœº¹-ÆŽÔXÑp„òK6íyˆàÀðá‘+ÌÇ!§~ ñ#ë -sDãKO!rééð9áÎŒ¦…‘è¤!K ØYˆ™&2Ç2~ýÔÌh¢F ij£ï!gÉ;¯{¤Ünö•⪓êFÐp¦Šé½ \“˜@¦¥ñ9ìýÿø„6,`‰F‚Óç´iU‰Öq3üÆ4ûÖ¦M0÷k¡.`F§ZMíg)öÐ=¢Z¹;œ®IjëJø÷ÆBT„·Ã”Ýú}A·ž“¥FÓVè¤DcjL•#¢ #Ë„ˆÛ½¹B­¥M€û>÷ÛŸ–&»Ñ5ï»!r•c|j ñs* T)´F¾qD5q›{ñq*£cäxVøy>ÈÝ>hã¾øÌúAS¾Þô`,Ê·ÿÝVôÁñb˜IÉå°Êi¶@>£ÐñÕLøzÝéH M½j<4ðuê‰è ùÇ?þAßsÔýÍ©bÕ§­ëIi«ËU"D”£‡MµAÄûMÊ¶Èæ»'à·N{‹|*]'ZUŠ&n"ÔŸ0Y#…°#tùdñ‡üM€W~ej4ŸJŽQfµ’ÖŸP÷îSêêÀ¸óRa"pÇÆØÁæˆJI A¹68§÷ËøÈp⣉ð“22´Éé,‘ÅÐŒ@ |– ±3†TK«“­ZèÒ8G}š\|:ž:ñ¨OG9SBÃBF‰§ûÏ+Ÿ¸B ¹Bñ¯¼3`–¨%:Ú€<«~Ç}íH|â#Aù‹b¦ÄMEM§§ÏsˆN8G´– ¦Dœéø!)hŽÍÝéæR´uÀúÑŒ,ÓÉVÒqÅQŃ™=(ûÎ½Ç Z;PŸõO„ӞѴþE‡KAÐC„Èž7ÂkëñS"¦62jœ¤´× L¨žÛ¾ÂçØ Gv—á_šÔz¸Aß5SО\EçÔ¤¨íšª.‘¡¶Zù¢Þs_ߢºV‚Bšé[« U’Íá+m4-]"&>'ŽÒÁ‚:MÄo@IDAT›²×ý¤à9OÜ{/± ¾g@ûL¤ÒF²ùk‰ƒ™ ³8Ô€¾õRÅæ·ŸÚæÈeÈŒs¯E;¿*¥ %ÒÖ@bl¯àˆãøñ ’Jˆa!àGTg)&Á¨! ¿1šQbE…LÙ|Qú¬vqÚ!špeƹˆ§+~‹!(ËY•Ú]™ÁÙC šÀªD#¥ÕoD£©¨ßeöãù” ¯ù¼GH¤@H áËtåz ݳ¬>ŽÏ¤ï¼u"û;Gÿø«”ÛÏÚ@¨ kGàW¥Ï¼¦•¶åMÛR©i‰ƒÏ¬ºæ+‘K¿)š¯æÝ7“ú:Êõ² —¢ŠÝ²Þà¦áù÷}/Y²îÖo”žàöVWÒ,Ÿ&Ÿ )¾èðn(1­åä\ç¡½í¢…<©ùÆC´êHå ¦" iZVc¸QèJ:—:ó[€g¿£½we7¼zWÈJ)¹5à®dÉVW'ÆöÇÚ®/Y hÕ¢»ÉJ)êYè³×½âƒi+:J,W²ãCB¬”ñ…Œ5Ü4vv™išFS—‰“y²ß:Vçͱ®Þð<ú®Nçžhë ô-¤ZŠŽb?çJ¹^Â)ÌÎ?4qœÔøV‡ÀÔrä²ÂF3Ö[dˆhL#¼‘£:}S êZ£M‰¯Gïö³öM«RhºUg§Ý«aÑŠ"ÃqÖÏŠºà᛾pœÓœR!ÍP¨“œ6¼¢ JœòzF`¦tôiOÖ6GÃî¤JDËHqDuþúáRñ–$¸Æ$¶ou!ƶ‹#ä[oš÷[?ܧl §Ó:‹´§‡tò·Àú¤¬n+"n9˜L¨UÔƒºï<†ÝGt"8ÁJÛ·Äë°êEô‹®œó„¯%|¹:A0¶ ï|ùCÁ“Ut*Á1¥ÉÙÒªK–Ù7!Ë7*ª4°QbÌF[álúÂ\¾l±t¤`rÚ¦s„RCã´WñËmW‹†äwêÿ碣£\²–\÷nÊvÕÛž§f¿‰ÐYa R˜]ÅäåØ/þNË·Ü^ü…:è»Ö•‚ž…ºÛ@²‰‹Î„òK—­i¾ºmKǾ•øqB› ²Ž:¶ü@Ž|!eZ@œªÆáÛYhøœjĹŸOrEá¶É ó‰pôTÔT!œz0¦cl¯! ¿^'ü)2–Þ.¨¨ÛB­n ”ùÄYKFhK‰ã´¸·T_GKó´§©t ²8 ÎZˆŠFGH-þÅ:k lëJ7¾ó·¾r=Šê™ÂD”àG0Vš×üCH'BL¨má­ëéeœVt±Î@§¶)ËrzDp¼¾Uysã¦`¯ä*Gœ_:YA#ßw»nÁ÷dšéÖ望Hm« I-…RSˆÅ„È2åX§¶"‰9®ó7¿üñH;›òù®šZ…WÞª£ZU¯S; ÑÀÖ…iKI=ÑúVBâjñIU×”CGXõµ4À„p Ó)¥#[ôYnüL‡¬ñ5)å…Ú˜3Zm#W«, ‡r]Yà唳|Vº§”–\ì>:¸Ð(øé¹e„kØV(ÁjUÊ!c:÷."JÊó¿1µdTˈ QÃõ ™Ã§vÕ9Nˆ©iÂMA¡ô)³à”¿¿Ä‡–Ü}[²nÆ–0õê qT"”oÊ¿jÓ(ÍÑÆÔ©ÔãåJd1!ü8²Z@UT0M;“D1Kâ¨e2f||Qd¦£[oÕ¥`+ù1Óä‰Ì_KdùÀjñé÷”• Ñá׃tgC"Ÿ¬ïÿ×Q÷Ø—(ËH‡ƒªÃ*k©žj[”@ˆ\.¼J[õ;/ž¥h¦Ý#H™ i™ÚÏ@£Þ¤U7Å„X»DÙjŽߘÏÉ1ùp¹t²*ºcîåè3ã?þ·—,¾Q.Árù”]„=†WW?²\l®´6ª5"èÕ’ô¦FÊ¢¤D¨í|£¨ð"žµ0û ½3çÍ·/¼z#•NýL“SÝvMŸüÀZµ@S†ŒPó¦úákÆ3U(…g£›N¯ÿ(3YV )Ý8\ôCô P|!,·Nz'þlô1ÈVБNÜ8}u[¬id¾U;'+gT±ý¼JªŽi ?~ÿC_WÕUnÕ!Vís¼§¦g@¯\dì^úîSsJqNr„¤l4ùVJ™oQø¥›æˆe™ïÛZ”i[Z/ÄT ÓÒ˜r%ΆÞÕmYcir"t¶™â@$êØ™ÄºGeÁuɉ™/¥ªµ˜&>ÍGH¡*5©ŸD–؉H ÞV Å1¶w…( ¥Œ9N´¶^tÊù-«åÓŒìSö‹?ýNSÊõÉoi@Ó6Ĩ¢r÷Åj£äªžŽNJ4¾¾®§à¾ÜT¢m§ÖŠv¤4ÀÒ/díøFµ˜h=p,>§Î«…#½¦Bö!Îa¾0q!­·¯Ž˵AÂÑ’W~W Û¡DóŽ–Y¦Òú™¦©Ä®@x!Ášœ8GóF‚Ä1qÈõ Í´•jég°÷J+*7Yé¦jÕ†)ˆ®¥S€Û4¯ÿÞ¨½0Eô©UŽˆZš÷ wù»îh²Õ•‚¬–êFd½]%¥[&¤a¹Sü >Ã*†Q4Õ©©Iah9Èåš¶EíOü8éð1Ï€WXBÎÔQ‡Œ[U'MûRá8uc¬•B˜EÛ4çž«JYË…°úÄ׉6œp|8štQc4‹OÖ™á’ÈOÊ¡BË-ňß4‡lKvóúñUB:}r’Ègt’UËá7ªœVãDbB¦BL'üp ëĨ“˜é¼÷Z-OœB`Mª}rÖI4 ^KD*M_¨D4;pׯ´ßT¼nÛK“eâP ȱR;ïîˆ+'ärµ.Wšr”ÕeVÏF|Ì:9höðð®kÒ(Ä’U‘­‹s“½êœûµµ‚¿0LïȘ|L²œª˜*N™yoéÞ¦õ¥Û^éÈžˆ¯Ÿ©µçÕÛAüÿ£ìÞreYŠl ×oÕn¢} D_B<±¹t£>?çXQó’91éX™6ÌÜ#2ò²ææP€ÔŽ 5³ÕW–r²<°^ð˜|…a9)õò4¼uÊͯ]­étDRd è9‹ ðäí46Ã`6v^-KÖ¤ö;_Ù&e65âb­Å8n¹þ%®‘TŽaÌ_•ÛoYL`¯_²bö."…(@`)K¡¥œ,‚ aªæŒP!~%R]àçÜ™Z±\¸@{rÍ´¬åíö¹¾)¤¤šŒNjRâ×KŠY²:£Áùh@BáuqÊ î€0äã+ÄOvâ` ½ç»±€Ž‚!œí]/EñÆP¾s'©òÇ?‰Pžˆ”i™@÷F%‹P,ˆÃšVÖ­CÐ-Å›á凚)ø**VBMP;Ggiïé÷jo1f4‰%Ûlâøj¯ÌÙE×¥íât°vçûÓóo-8ŽN ƒy®ùÈïÑO£ÓsßÇ+b6íJuªšR0k08ZY¾€lÊ–¶0²€vqwQ`:&ñƒûw> øÌØóÂ$§Ü’¬˜¬¥ëË M¡ã0ÓÊJYY 'o²U}êm°?ºÇì}­¾¤È65« /¥$ð~¡áȦŠÜ;ô§­ztv+*¡©¼]¸ˆ);U‚b7‰‚oo5šHµhªxÁT+h#bYKUýCÑÊ? æÃ„‘˜¾’3âá‚RDàI@;„nEÃÃÕBF NH…RqXj|Y:²íàlû•R.Nªl`d„øâ©!»FR‘n?ùö¸“Ȧ‚ €ð÷ ¨©â¥4.UU¸¸ŽmH!)²ð˜h¬Ú@š®:M‹]ÌÐX)KY>вr:h¼l­ óx¼=T®$Ž”_®½]Cž›W{_rë’¯»XÀh&b0¦;D¶RÖR|®Öõ A`Â=¿3 /!k¿ µVèÞ"kÉ7’ <&Z„qŸP " ¬„ áóD˜%/ëëù_þ`Òıe– ļD=úùKòŒmþ)§ÏÃY8o#DböÊ4*x×A€0“â- ÄJÈZ*xï1Þ˽¨r3ôQ@\9ψ§Ù}X§ÛG£3ÓÛík \Ì|(yþžJ–ùèM³}Õh)&âòµÄéÑÓA!0‚¦F¶ýî¸7!„'†ïS65ÑòíN ^kÞ'eY·k|qAUJ01AÃÁì†ìbùq¬^ ¿2oÒÔ”óª(ãkÑá@iŠqdÄÓ—c$H"š;_¡åKž¥Œ_€#€·Í«èÑ×NS®—T"•ð‰ œx<~gl¸Õëw¯Äf]o)]õØ­’í<‚<)±ö-Š)¬cüFÜ~N¿ËtA`ñaVïÖ¤`B̺˜mw†x³ÑÑåÒ>Rb^-ŽëbÓÁéÎ;ý.ûæ·lRþ؃BÇKGL`~AóK黨0–<ÚèºÌi™á÷É×ÇOˆÂ—æDÁ!ðݾJªåºð5m)n‰píþÇ¿Ö@…&·_ó8+G×µ€éÌÑø-ý§sz=øÜ—×3šŽÉ=úyŸ÷iNmÇBˆÉ{;Ô¨îÍ/KJ,âAIÇäÝ-÷Íö…ÌpZòY'SJ¶w©‹û¥Cs38 ƒñ€¬-¨4ƒ%B"Õf—µ´‘J0áñávôÿÅ›ë4ÒÑn‡Ò$ÄNÔ¥vb×#tøqÌ …ùļ3½:„D4…° ÉŠ –lYLˤ6¤‚¦/þ•?¯e~:¼;óå·47˜ÁêÈ»^ë•2°ñt©„av²mj[ƒ ß=AK#U+ ãŠÛu'`É”³{§oàMˆI¶Ó(Ž ŸÏAk/ÍBØ!Šámµ„­2Á&FËbF!²¬@ B­-½Â-{‚”ZöMïì¹^ Z…µ°T•²¬™55mO¥´.@ǤJšX9)%J_ î[¤¼ÚsÛ?²%‚¬ü^(nI©ݵƒ3­y8TÌ|§êOžORV‰Ÿ}Ûuj{!ýí Ðt/æ@VUd ¥1BÄÜd1&ϼƒ²{ë±Z/E{Ÿôûâ‚c˜|jb4‚ZdëÕØ¦tbé«j0̆o*A4&Y4Å‘CšÁÏß9Ï\{¡cÎû4YfTÙfð,Ónc8UË Û2„ÅWîs÷–=·%¼Ýuhª,Û¤€àhmŸg@"&ãT+†˜ß[ïË7!ú>þ§ ÜRÓÚ5OcwS‰K d‹.õ…œÞžQth;)%!ª\¦çïLø¾¯'; ešíš,³ôTÁÉšA ˺ë«ÊZ¾ÏÀbÞ¨†I‚œý;¿v¥x©ÅôKÁ©•E`dy ó‚¼»(4³¾çÕ›œ€áñj®Õq]-)â(L"%h³f÷Zʲõ¯KU|xœš*¼y„ßu,Y£jjHWó¾Íñ"ó@Ób©|"p&ö-ò;¿·ô§~u·…º˜ªóžGâzÑב¹·øŽTVŒÀÄ MŠSö$%yi£ ”ÓàS†¤éTí½1ñ x&¸ #ó‘J®éÎx¶ TÅ7•T4 bÿùRŸz"ÿþ÷¿½Øà]*‘Ú‘(·½–µÖÕbÊêHÍS“ÅŠ›G€ a)·$ ‰iJØw»ÞÃü!@âJ h6åô7§¥.½ð{ô¨xj”ÀÍ#Î|¶ýοù¢KWŸÓˆ%Ò’¸.ÅðÃ éØ²ÖjÌÀÝ9>5üýÂüôïƒ6Õ@´S4_/ˆMÅ:’Í€/Fƒóé4ù8^#/ß™üÅ+E!IV¯Ôè'ÕÓ_Ì÷BÀwjeSÀ‘Š,K­ó çY-p0-›¼Sµ}x…Rm3}UòUa²^ƒ8F iD,ïdñ9Ü 9*Ô€o¸ å8c*× uÖ @ˆ,¿Þø–<„,o“ÌÜ Ãðü ©‘²döfy'èÈ꘎.–ákJaU‚‚&©gº(4˜ZöÍëóHž_dû-bRÔÒá_ksÚ;G;²NŒGÆŒP Ó'ÐuyâûÑ9>}dq—ÕkþÊ×µè<#ßÅÒ¦ˆˆ¢ªr4`šæƒØËß©=úû‡¸žwª•ŽF–rȆԽñN¿ëH \÷Œ”×0DI3•AÞ9wÅéàìäkª„Eð÷6Î?ä+OÖÓ÷ª¥Œm#)ó)7†%k<´îÃ[V#)d:L€ð„ðäõÑ™)ìQ@@};Òe!m "0B¾IXK_Ž_¾ )é?C¹¦8/+²jW@M¶ÃY#Û”Åg@žT‡ÀlK篜÷¹Íä[~ ðýV—>‘ö›AÄTá À#ÇG³l¤jù˜e[òt0²?$f½Ì Á‰ŒfBÙ: ¤Ú‹¸€ODmdA]š°¾€Ô¹ö‰j£k9*Í'U{©$ÀÚ„ð gxãBRKJ\UL%ð8.€¬F•‹•3œGúêÛ<ÅáÊÛgšd(—…»î–b…h‚ºPvKá0(2ïü‰…—º|ˆ©%Î 1ª¥Ëã#v¯7Ë Ž—ˆ 7mÁpÂËßR”gžªøL¡.ö«#A­yo úFUt@q'€#Þ)²Kã|T¢‹€~H’àË?–'îûS|²–Êᆭ@-ÐXYˆ}ÃÒ´pr(vÅ–¬¬FéÜ ‹y|Yd³3á=V.gÎ?NÞQ¤Ö9›SßYÝkA«Žv‡ÐŠMŽ hƒR–1_>ÝÒôãO· ypÛ‰Ô9¦kãõ›SGK´I•5Œ+»-Lç]àMÈ—°hÔd¯&ç‹áfÐzU ÀCêh¾ 0¾8¦%Že-¼Ü|éœæ§§ßw»“%˜N³‰•ÇÙ¥éÜŘª*L‡·T(…fr÷C·D´4!²µo³˜mjj8b&H_P¬Q± »€!wÑ–ªøÇ{(ØN*6M_±Ñm[Y¶lAÙt*¯SU\a"˜m¸ÙŒZ8Á5JÍ’T´M‚ßÅÀËæ ˆ³ÅtÜ©¡Í8ZGVJmdOWhüOô¿¬K”%ß%$ÂÌ éõFAª¾¨cåøgôk©$Á¶¯°¬ç§“¼M⽇”ªz!Ô…T¸T ¥@;A (àwβm '‘ö%ftªê÷–­Ôw>þû¦â'‚&i µëÞTmA#ø8‰TÍl*Ùö%XLNÈ´¬MÉRhl:‚Êq"|çÊ™{À'¥Ü´}Lé  '(•~´–¶ÓlªÄ¦‘p";Òïüáÿãt:Iʉ›Äî’Ê#”Ò¨“l€ Ù¨–h[Ú×w>þ{k§¦O!³dt¨9 ¬ëԢDŽ ÔÚ>Nš–<Ð?Ý OÍ;´ßpÔg5ÄAµY)ÇBˆ ÅýTÓ‡3q#!´„¨â‰´YåÌ’!{V¬PÇ‚¼’Dšž¸Xà[bBZ’²,ÓôñE .¨¼‹pÜÔkܲáøJT Lßãu`j|¦vNÁR/1‚)y£ÀÙZCÊò‰4mâñìs“ZW—¸ñöŒÉÃ,&K^m/NA­käCÖËûÓç7“bíLE‡ró[ê+Õ.è/…V 'ÒÖÂU%%èNEó[J-¤ž›g±yHu,Dj¤Ê ¶LYò–µN³Öª"¤ópA¦Aa ùH_ÎÿÌ~"hÈ6NÇ’õ0-)²çÀ[Æ‘êâ!íK€ÜlF8 ßRmY‚8@^6¾¥8¦ÿøï|÷òØíß]6½ÃRwú Mwç †£ñ›§½÷Ó¿ÿ-ÿ+sõ}ô¦¯#)ú<2¾bIª©à Vwˆ, +dßùÏb¼µ; dUÊ5ª|"ÝWíÝÆõêLq®æÄÒ.ÜÿR sâñeýF÷üI#/[̶ÆéØin†‰á›¢—rULŒÂ/¢†\Ã3Kx[€6 rjâä¯Ö]ÍâdwÕÞ½~ÓêRJ¯ê!aA«â÷ÐĹÏ'p|4êÔaªê¢)¶)3ÝÉl`sÒÇé(VÂËâx_ùvˆì@é¨2|âðûóN?¯o%@U!| Ú¬íoƒ–J¼3©}r>žþsuêKY¡1ÔºX¼Zž,¿™ã4Sµ¬dq…ªBxÖ À¤‰“Håðu<ì‹_ëhpupø®¦¬¸¾]8œ” ™2šÛ…-[ž!¢vRxE£H!]”Ç{œÄðãÀ…Àš¬qCjÌK•EÖŽT)4:TóÈ6:P ° ¾µe:JpxÖ`|9|#ù$Òh¬§Lí0 ÜÏÿç*ëâŸ×ü Ù†Ùð‰àlSb­-Uѳ¸å|h‚“&ÿý7?ª$nB}™%eA²NUÒ0R–ÀÈÛ‘³ê )¤V!ÏLÅw€yï ß™Öœš†8£Ö`!¤ c¯Ïž¤ˆŽ¼’vDÄlmDU105U¬9eq¤âÃÅíÝgL('n ž¹/ÿá—¾t¨Ñ×ÑíÇX A/xqò‘;ù¦ Ò‘eÞ{ɯýkjªž›1|+mkIñÙ]–f ,ïŒgfú²|gk#bœpOÿ—ÿ®ƒ©Ê4u±äÅd鈛¤8Y\GA[~7Œ&…FÂQÅSH¶¥ÏþÏ¿¸Éw£~'Pnž4R c7†F›ó~V1ã4ª!k§‹›è¾*æñ™¾pÛlÙ¥"¸!˜bœM+²ýæÔ1&Æš$¾˜aÂ15ªÅ}ŸbŠÝ²WÕƒfÙÄ46qäÔE(vyædy KÊQÐS X_÷úÅ=c †P ¯Ê’l§ XÜS#åš*Á÷¯@@æævµ*ÿÊ»ú;?jš6˜]àÛ£Ó®1\V¼-àT‹Y!NˆÁX×Â*'èÆ¿4gâ)†¦K{‡LV»ÎV‡>å«Ï#€C PªIzùá8å}/—ÕËÓÿ;¿SÓñ‘¹ ÞǃwYºÐ7å ¶cDP®‡EÎÑY#U¬ªb„‰ÐÑÙ–}‰yy3¤à±«…Ó²A­1ijäHÛ‘mŠ]׫»Q irL…˜ÀoNBÇßSU؈ 4j8åÄÛ»¦²úòÚuÔÛŽ¬*)OØ—ÿ¾ZŸ²éÛ/¯–uª²@gbYƒ1MùjãûÊ<^×͉Ϥøøy²n¼wà £±CH™ ˜Z}Û2dÊ]…N-©øÑBLþZÈÒÑ‚8PÌ' &î´+l0‚‰ß§ªcøÈwÁ8­µ €¦KÂ’WÌpšR€©RŠ£‰Ñ¤˜8MÀ.“Uq±ùjk!N­Áq¢)tñ([º*6ÏÊb†Ì7'5¸W…BHjË)Xf~ceROÌ õ_ÿú—y5ešl]®AÎ$ZÔ¥Cà¥lÉê¢ÈÄx±šOAÊýÔ“ÙJ™°-QB­i-kÑF™)á×úšå8HÙ˺S3•*H»ˆ)åÑÿÍg~!^‹ô§FÜÀd÷h@(»Á^,)HÅWÂ,A{±ÄD(‹PÈÊO¿ùÍo¾ùô· ßé\ӈߜ¥š°‘¤ “ lD ¦CN8ÄoPßùBß? ™ª)Ÿ.eM|œ“uõÅ¿Ïa^¾_b/²7ž Ë§£ø®©—FætàL‚‰ÖU+6I;Rf @|5yò í?ÿùO?&¢© ó1ƒ¸î&+U¶v@˼ié*‰¹‘æÉlüÎLŸ!(G¾dN;†€Ïdõâ!™¬%¾ |Á©¼@K7×>¦Ö–Í/ áÊýŸµÁ“«_$ˆ±º0âæ7·@ >3"ç=}xWÝÅèÚ+48]o‘ Å™ò‚é×T—î$Ãóð¥ˆÈòlå²N¢–o©PÜ%?õ×aéeà—ÿ»êןü+ï|5J!ß²±›Aß¶)(ÛðNCÐTԅѼ¸Ív€É>÷ý 0N:4Ûc§×óEwÙšv z))n;M"¥. ˜HC®\à¹ùò )dþ‘° æ‰o£Úµ¥^l/lÈ]G‚+O¼©Ú#$2”e”¥:%>C°‹_ýêWß|úÓôñŸÁÄ7€ ©J–G‰ CÓh®obû¼ZˆÏþ/p¯£7yK:IÑÜwg –‚Ö‚â«âqJ^\RŒòý“f½{tc4C%¤“•šø†AïŠs÷•O¤™ùvGž§sκ®Q›RÌPÙf iI¢qù¶­Ê2¤Ñºsìb#ÀÓ\ª«óÙs[:/­±ƒXɪ¬Šï&Ê6Ï®§ÂZËZ⻞ÿ£¥¦ýÉ¿MIy1l€æé©AÒ’·lZUm "n n™fÏqËçÖ9t«‘²}wžI¼ ¸ù§¯Z åv1Ú˜X %í®½ˆ=ý›Ðûãp^~n]_úÚñd›Ð –š²‚ön)°µfScáÍf×pˆe´4xšA]ttxÒUâIgS‰àem–>¼@‹:Šæõj<ž¢Áqª ñ‰ÄÚR¾axº=¿ú¸~üQ®ÖØ…©ñ n›@‡ÁÀ{ßûi‹emć}¿†Y:mÿô…ÿòLœ$SËÒ׫‹Õ0–l1q±Ù˜±ª²|d>©hãàûmêÉ_%Ù¯W._ ‘öR‹:·)RÆËB¼I$ZˆÃdR8‚¦³¼+»v°D€#›aúbR}h“ÕY _aãUˆÜx‚D0#ÃËÖEÜÙÂ!,ÚWÂZ=ƒòØ!¼˜…+®¬%ÏÆ\|"MpD¯ÏA¦ßž¥€jó^bç2ì€_#"DSu@m-¦ZÙÀ®„ò ¯i³¥™§£Ê£êÉ D\­{¨ÿÂS¬ pó·âgŽkfâ”›¤F8RãTbHH‚ž˜uu”—…¬ãÕá…óJ«…Kï¼öÜ@=Ah©³B«l`qƒAÄk¶e F ÁQè¹ÙsÁwmŸ¶üGÔ+ü*pÑÕ0qÚæÎ„ìýXRÓÈ–²‘6°‡xsvÏTÛÄRuÇ·…nSùªçéÏ.ãå}ƒ±_ÙŽŽˆ.š²Äyà–âáÍÜ$<œm0ØÓßçzïÜÏ?ÐG#®œgmöÌqR‡÷±@Ü€ @NÍÛaÃvÏO߇\,ïˆNæùïì×&þÇÀ4•˜'©k‡£Ü§“>ÒYJ( ›oÎÊ;Cn/1æ“ÿ½ îFó´»zu8bYæng@v Ú^xx…bq4ÅB(Ì,ކŸ‚%¾T£–Uh)Δ;¨{y„ªpôâÏ ×aÞÅu¬)#¦oHUÅ®µ–æ>¾T#Ñ@–¥++®Œ´ ¸*Þ²‰õKDUA% l‰&š¥·k¨ëc…ÈÌçUäñºƒÇ¿ÏpÚ_V'âYFV#%áÈp|jm^ ÔºX*¹z>®±¥a|t• ÿè5òô7aœµ£_Ü´bAúâvg’¶`)e)ó$a-XËÔÚš’Qx2ä}l%“mžH×H ;©ÝX–Qƒ†Q(›&þÅ=²~î_)ý>æ¬ð{3<1sÊRc‚ºÐ„‹;ÙâÀ{ ŽÌß9‹áÈ4Û»X [khKWÄúûq‹žþ><ÿG`R>þ§ÀoqK^#]špë+E¡XÀð-Ùžþ^~_òÇHá_y?¸ùÍÝÌvxjÈwÍ–,ŽC–u,Æ t_- §¿c‘òšòÙß»rgõÕÃ}iã•°R FM–Žêo<30K)LKrµí+Dà{RŸlÖ}²§¿{³ JŽÝ®zÕˆ¶ù‘•oózóìèÏB+)¤ÆºeÛg³ñ†aô«ÕÌ/eS-Û\ßnqȧ†ãƒ˜Žô-ٙ㺇1Py¾à¢ü8‡¤cD(0§ÃÇ4A1š MåâšÂŸM‚‘U­)„Z½¦LŠx`ÃØ©e±Ù»‚%Cð qN …{y<ÕéiD¼©šDÜZ t™ÕÚ®œoâ@â“A…Ô ²m¹@\¡-ø,b ®#ÄcÔMh0Sù¤’ üSóËŒo ‘“µwL±BfÔ‚²b}u´d²–L¬J–'åg¨ýòãéo°çÿâJÇ$M˜):64Rç \G±,rWP,ÕM¢Äö÷ô÷ޏgªêõ•§ƒŒFV÷𶻯ƒ3åRHG39D!³Äá!1)@ªEðo$æLá'è•ëÚ鉮TçíWV0BMá:Šyž5v„ù”‡ã賿ªörMtÎÍR_š”^ѨºX¢97 n¶¶)ËÓoZ^ŒÈ'õ_y“¬Ðœõ¥ÐêeÙüN[§,;ac÷ž QÅJ5y'àû­ŸŽÇ„ÖhtRÀb‚iñ k*`í ͆#æ-™€¡)l‰ïNs¼ÆÓIMac@e ÷ÓŠ‡HMý†îcLÈ“TÄ1yÿé´YHÖºñš­Ý̲Ñ®‰ÎÝ%PîRÿêK¼aü*UIƒ}ôžþ¾µàÔ‹H÷¦˜™ÄC°ÏÉî>©R#3øAÌØ¤îm-D¼ƒURU‡Òðiµ Í«âñD‹)E?} š*ˆØ„ç#^ ‹„7êb)¦f$°dðhMS­¬Àô¥[zRoìvÍ·—HÝS3C3ã °–ÎÖ<]ã­]¤ Ç„DnGm$ý†Ä´|i”i*ÇlÂúNvœ‰¯*[®…%))å©OÉzFôô'èiÕN×ëåœt¢Õw…pqÃKáXv\†©{ãh q8átŠ˜©²Ô¤öK ‚?øñ3º š'&M˯Ìc—µú(Ùœ;7`çÖð<Û0ô mO¿üôKš›êã7æûH.–· 3hÑQl*²º¬—*OCvpNˆÃ ¤\S/ ¸ ê+§óÇÇyn¤"“´…NÒ¨ÀâÚu8)¦¤“`»ÃIY¶/¨!?ÆÕt†ºÐMB ¹Ó^•TYLq“ „둊#uÕ ÊZ걯ÅR) X-|KÙ¡.!ŽTï[Ž©*@ÔK–`š‰ŒVRzáç-G;_Í´T,`K¦²jÄIÈ[’³œ(š%SK'Θh1=ÖŸßÇ1y_è¨i×Å&•ýH ߯¤Ì™¥ÓFd»¤®¢ÇÇL±^_}y$âJxêGOdAÛ©ejÊÍÅÇÄa:ºZR–¶F¡IøjyÙp“ ˜í‚G{nª"S#wÇ ¥ rãÅ4Xä`Új1À6˜ÈžþÎêçŸö˜ØÌZ0%/-)dâÌ0ZàÇ[6‰ì%|”›3¤©t¯ó‡'‚OÁf¥ÌY¡”O¦ž¶}Æ—õNïZ«"[»'ß ‰(éOn|d Ã©©^ø;}S#žÏ DŠ1qÔ∇—u&†DXÓ>û{úÇLSÓbL±½7Ÿ¸.•4¿ ñÔB"WYQ6*…m¡`âÈMSË[—»[êËâ‡eñ-³¾¸‹á¥dÍ ‰6qȶ¤liÔÇOÅÕºTÉ奘•MÆ×ŽÃÂmµÝ.ÛAmßj1_šÁ½ P¥…‘jd†3ôuK‰Óé½–J!kŠÏ”³fX`ÉdŸütHYw|tézÔK¡½¨mË4‹Í ˆÓ`š§!`@U18ƶ<3]w!0²%¾8þÀj_úº£)l6ÍbʦJS‹qš¶BÞˬÂ{G:ŽÅÓ¿wtgî’'xW»—|7gÝÛ;q ¾%A©!Àm§Âf3 ²É›A³¦M…ɤ¨ñ~öñ;»Žç~?qÔ‹ùü÷Ow¦+¨„Ù ù'6•¥ìÞ–Œj©ŠÁü:ÚOÕ>ø{xI©eÀhmç'å÷ÉöHçSY:RMe™9Šp4{á‰÷ƒ²cñ•N9_mâ¼Âwc¼[v!bÖ !©:±”Òº` SÝð͉á˺ý>}_Äq€ûJ„ i¾È,µh_á–z1)¸ Á´+6_¹Š¥(Ð •¤L¡Ž–½ñ ª¢#(®‚¯Žƒ²,¨$ÏÜ6²‚æÐ³ÊCp,ǼºýÏã ª™™P5k¯€bË;Xªö†«Ïî?…£Y>ÿ Ðvva™š¿Ë-Ö]œ~ââu¤P;A†ƒ`ì}VUÞggR²<&\yn÷ýz-)ÐßÞ•ßçA° ˜¿+¢)DœBY ©ÀönB?ûô³•rŸ}Z¤)Û0øÌ ñq>‚g´*jZ ðºhJ¤ŒpH1o³ôUIyÄ÷ßOˆ{ú«e²˜Ï߇Ìo`äY…ædÔˆKñmÞ%3 $|?ˆy ø”&*©c:ŸzjŒÀ8‰Õ·»ZŒ`)vhëôÔ*KUëõëÐ,ßqèwÿéã73å™*²avÛ¯{¸·d´ÈRZ¨Ef@ˆ%‚e…ã_”ÇØRÀpÞ’¥95|{„_ÄÇouÁD“êäÓéÜ5_­*`4U–áÀºXžÓÌÎâzÉ¡V&ê†n¦˜Š¥˜”}Z Ü|Ú;AjœfMg‰|Ç7núWÃã:Y­c4\¡FZ·Œ lLÛñÍq¯ÿÃøìÐÇÌÀ™°Ýчó”e_÷Rm¹©dŒ—e€¬ 1“M¤T±TY„ç†Ö­ŒV;–|åÄ)CðkÍ•ðJÜa‚²•½‘{ZõvÞ¿úê¥-få⤞ÚÝ¥/^G^—&á¤Ö’¦€ÇLaA}7ęؿ÷øàß'G?³¸ÖI5¼.hÈ6ØÑY~4÷¡BU Á|ã)7\‘íîmf4íüéq¦—”g®¿A O\Œüq€很P4F-d Úf')nK­òu‰`)¨‘^Æðp㙇ÚQùðK|%ñ[¦† 7y}IJµ(æ«jB©§$òÄ[Æ ¿Ù,™%ŸefÉÑ´,xÜ‘r­Ýí6º¦W¯Ò–Í1r`d±®Lö´½eùÿÖ’"¢0é(Íã¶æªW»ŠìFàÛŽ%3´Ìûk¿¯þÕ¡?øQe¿íEL°S¦iYSHî¼Èy:FÒ—áððku.C… Þñ¢QfÕJA2 àJž—ßâ¯|¨ ø&1j –bRˆ4žeq¸1,•4ïÓ¨ÏþƒˆýòãB$މPœw,1¥¾2ã©ê‰Ðx˜£×ÚELM,Ø ¡-ÀB ^yx[ðñv¿CÞßèZSVÒÕ¡ÓÍ#øhĽÀ›“ß.€MŸ±Þ^¢pqÇ~Áç¶ôç=LÊcËï-ýç($ˆƒ õdŸÓ|MñYƒ…Ô«Ô8Z8`æÝÎë‚·ôèïM±;Èf‚.=ä‰a£Å–†tæ¥èÔÂK;œÇ‡ x1ë4Ü~Ÿ>ýýfÛïxƦ¶QudUŠʼn;ç~{ÄIÁ•@š„W.ËŠyK‚WRŠg-ï3à3HU8k G€ó¥øSs™I*ì@,íº!)  Ηäkqîãõ<•fÒ|5‚ÞQ¯Öë¤p´˜¥äÞµÂZ¿ô::5:¼á+g‚NSÊY{jtõå-‹{™U T(ömΧ¿¯¾P÷Ÿ/íãñm­Öí‹”,Í–˜q,–,g¤è†‡4ÿ88 ˜©–â^>UëÂwGÖÅR@3ÐRÒ'âµp34 Äœ:6¯Mûg7ª~ ¦!lSt¾:íôy­  ÐTˆvq\&š8]¾QB¤Äª†[V’¸¿©÷œíÜ p>äÖ-8ÃiËæjž5¦jŒ CGmMy8ÓÂH]nA'nfŸdûÒaz+U…É0q S äÓ1€Þ‡Ú;fS¹¥Ø.45m8S¡švY oÙ¿–â1ÛQ3µ$ÕKïÉ`¤”wMÅ,ršb tòÆ+h ]8ÐÏÈNìÓOoýñ®Ù&¨ãâíW/&`$‹Éº:pH 6¶!¯¢s›Åi‰#Íð¤üÈÀª"ìd”7‚ l¾ÚÖ(ñpˆá‘!Ì)9«b‚˜K­*äñoú‘ÀVFÎp3z›w¡aUôº#ÇÏÿºUð+o§ÝùéèË:I:FE.e W¢3O²½;îá…Ì(ðÈhq¤¢¹|ðß'~7gqT¡Å¤¤f±ì“9e½¶ý”-…øD”Ûˆ-»4bfȦš,Zü²âÍïÑoì)»ÐÞº*ÇéT ÔÒ±S— Âdß ÷ó¼’ô2j Þ³LÊ’8e1PSw£Ï"4óx°G±mb&KgïØrÇK³Fª´³T{æx{yVBbH„nuoêýèïÄ÷9\EÇQð´Uˆ[2)ån/Òço˜t”+´ { ¤Ä l‰Ùx•4ƒŽFþDʉ)¹›½i¹@üJŒGÒåÔ·geLf¼ªÊ"0x—ìè^ì(JYn#p Ùhã· kËÚRVØë% 3d1µ™’âpåÔ” ÈJ¥Ì!h•ÎiÖX€ÔLcãEåeŠ„,ró5D4¸âRJd½È½+—º[µnhbŸA(+¤ÐT…ÕZ"t@‚ð¥¥Òti{ ÜÛ-ÖË'Y·‘F^”Õjmɶkñ5IK±Ô…”-ùj ÆcnSÊ¥,ã) Àdéõ¦<ó~P_Ù'æÕ‹O')^;…L U—¯©ayLOgOÿÞ¹ ãÑï•_¶ÙÄ-TÒ Oà`MKáÉœR^Þin‚.„1H ŒçÖÈ`RµË+”âIÐEW˜¦{Ï䆱 į„ ÒÉð~ô˜— MIïЖ¦ I‡ D¬…*óËîÏl<}ÖQ[ ‚^8›NìÇBÔgª\ G7X"SŽLÖ².˜}$ê(¼ 1…È+„ª´ `¯Ö®Núï|·‚aÔêh#mmo3N@U`]æÍ¯—w©O?½yãôâíÆhr|…u¬¶xÃ7¤¥€Ïp¢)1°'Æ.åh•Ì 5ƒt¤ڋÀÆSè`y¦c3Ká(/¼´Ï„˜b`‚!–V G9ÁªbV8ܲkQÎCÎí;6HÌ ›œ ¤–<“RìŒê!ööÞ®Z*w”˜Æõ´eÿÃ+)?€z?3]‡¥H ˆÐ,ÃMe ìJ50ß„8¾ÞºuŒ|göy°ž×½sì°l-ý¼[MwVë˜deYÃ(D GCÞ –‚ÑÈF¦l:h)C¹BÍËž½|ªz"ೆ!¨6qŽRùºH…·5oØ{íyÝölMË+áÍ|õ9'ÐgÞÑ_Žê-{ì× ‚Ô\2^y½ÌƒPJ Kú‚<²Øü6ëÑÆvÑ•_ü=,*Œœ²* ˜U^w\LÇï|Жu;©µ$ˆ` Ë:R†#¸óý·½•ºÛû÷sKÌ&AK¤@¡¥Mµ/à;sç(dĤ]×ÚÒq)‡ðy Ù,]S“$îêIY2„Èâ kÚ^IJô5âz£}7UK[³M"f³…ª’¥Ç´ÌgR¬Žú®…÷;ª¶ŒŸN ÚYŠù.‡‹8‹´DKJ ¡ßÁÇAJmWÁfãl’- ƒ6"–@LÚ×—@IDAT¼*ÄÄi SÃ_™EÃÙ«Í6ˉ8D¹ÀRÀ0O‚¯e±t+ÛVÌæÞfj¬%&á“âñ|ا0'UU8ìv|4SÝÍB¶IVA¡ °ŽÑÄ>€¸Å=ÂWXàq`w¤,CÖ7Ó—¦Ž‚†o;áÈdyO©£,£ÀK9=L:¬ç;nyÏùˆñ=U;4Hµ<Í1UIÕž™ÿåSÕ¦Ôâ'[GK Ä2 Ù‘´¶4Õþÿ!{©{R K5¡ ‡¬¥*˲—ÌCJÊ[¬'ûóiuôñ@¤ DkVL––¸³íqà!˜©®øý=¡ö-í+Á†„¸u•«¥ƒÏgŸp£}ôwfƒÅj—Ì×—™»QG¸ÃôáC_d·‡Ö·BxL7Îôï}ÅÈÄJÊVK?¤¥¾ÂQwD6è÷W‡x;jfš½Bï .µ#Rˆ‘@Þ‡/ëEí5b¶ Öœé´G׎镎-[ú^è‡2‹»,Ü—}±3²ÑZRÆ ôtѤ€ÌRÊíK,0ƒ”ž‚ìUô¸:é»×xYK8ÁÚñ¬*‡iJ“‡È :K«£ Ä¢ñ¬e˜&rËÃ¥ÎW£ºcZþâ÷¿ÿ}hTqTK{àñ *ã-OåÛFLU.F`sˆ™ã[?RL­Í¸ ëȻ̔{ÉÑT‹QÞen˜ªx)¦¶“gnJ·ŽûO¼Zø­ÓCA•,)&%¦É³úZ ¤ƾº/ñë+LGq¶t-cVËScu/Epâšn2ïøLìã¤J¾2´Ž”Ci)VÈ[¢EÀ3üý¥OmKO+¸zU¨2 ~ †dÃ4é„”5­+¢ä«Qá^6È{æ’Ò·—ߪRà‰v€æì«ÞÎD¡‡¬ ݯÃí‹W« Ï(ðÀæ/+U‹ nÁö#X"¤Ú¯FãCˆø Íã Çô>êfBYÓ‹aòÕv’N×b²v×QÈLÒ ïÈÚyô3/Ÿ!Lâ­ B§M;“æJ‰¬'“ŠcƒïzµÔQœû0[õe Ö䲌×/ë}hâ~?0³/Ä0×?^€@œ²€2Mà9—«ÄR ¾KQ¥oµF¡mVeªZK)‰‰³“,ËÃqØâ‘K…7ò{¢ùXmY{q‰û`‹Ö‘ªU¡( Úš™ÓDZ„3%ž¼”+™Çñ\“ÅAnÂv ‘åSSën4^gå¹ïùåo’øR“*K™o îÏO¿ËÚ¬»Zá¤ðSI-wt“xAîMÈÃT¬uåø3H3”JŽ%ŽfÉ»¶ÿôý)‘û¯¬ª2%åoÀ‰ã»¦ý—:q"˜ÙG§×qŽ`©JÐðy‚@©kÞÇ'äî«zun•ó •@6KaˆÐ«¹ã°Êù&¸j¥”«â¥XúRfÉÃC´H„ÏB.îÙuf)º×B””ŠÏ'R•øáñZøÅþðrÕymš ì¤ Ô˜z…Ý JjÜLwÍU)$åÔœ '‹W“Íd}fg¤\ï(Ë +gY  Ž¤ à•æâ±Åc>ßþOw‡‚›U‰òºÿºœp‚LÙö d %nqÚ–¦Åƒ`)Û='ÈdÓI¨ä-yȲ0)ôµ7$¦¸}©+±)»¾`#ݽo·©ÀtÒ×"„__~S‰yFõ$õªs>õ®³-PX\@Ø6–¦¸¸¾2|„¾ jŠF7I×Èv˜«æá©Úÿ”“Pˆ¦…φföž§c3w!´f©aŠeùÅÂÐüø%@­yœªª¤L%È€ÌõCœÏ?ŸxH–Âý5¥nf…|c@,Ó4†]|Èbzާ‰©Ö$U94-t÷ÝÈ5õ èˆü~²òõ…Ëvhã‰›Š %ÚÌR 4†÷EÄxï~«‰èÅŽLPm>Mž™Ù¨†tbÞ«×ΨfvöÏ øF2°ÄÔÈM iû+/u\J ®]j–vÔ¾H¥ÖQ4v:š& ¡Ó0x ª£u™’&”*€ÈL°%ϦI m#R 2Y©wY)"<¦¹eð§¿þõ¯It Úôv¬Cš@}õ+ÔÕ2ëv‰¼Óì ¢¦ËÉ»]d•»änÐO14w¶ûÆ­ÖZÔÝ„ÊõrÓ0/ Ö®fª¼ð<è4ƒšBúÔ š¥Áš¤Ž”YÌ8Ý1u1Iåºò+TKPŠg²R±  ¼¼f6Þ¨mÁH/Æԅ)¤¯Êݾ—°å dTß´¼x‘à &@cFÚ0Èð¶#…&å!qt²]Üø»ÉVe$B²n31A…ðû-1š.¶ƒÐ£¦J($Xy:ºcnxA1ÎŽ“…7°X€CMÌ¢µ)Ëö…“­üâ² -ð -±íÿôç?ÿ©=TCb<Á;!˪Ôk_Ñ:œÎZ?œ–â•t"]±×Œ;Õ}Ð6î^­ À"K)g¹Àü\¬Ä«Îíîµ!@n·p|Ö.,M"V;¾*ØÌ@îãŒ8~Êhd.Œ¥Á:^Êä²pZH}•³– ˆ(76²v|"Š-‘y‚¯sÿuŒ:_µ¾ý(i#}ªûÓŠ‚W]â†ÑT€¿¥MªIÄÖ£-˜›Í÷Œ—ÿ$€ÿÜ æ¹ÊöÜoGv§…v²Ý`I ÚÈ]Ù™À•(T¢!˜³«iéÑæŸp1ï…Jú€‚æ.ÂÏèD3•G>Ô&[#Ëæäë΋'° “àDæÕºˆ®×oûÛ½µl©º(gjMb¤’Iºôiek*ÐZ µš²²ÍÖØR 1e«âã ‹ýÊçâö2A¸Ž!ZÉÕç¼R¼êÅw¦óô^îÅëÊꥣÉmGÜ0ø [ê«6\@X f÷‚~¯÷ ñk-ÕHíNVÀ¨!ð1¾{tÎáø kÑÍS—tp©Õ®*~†ÏÔ¶ ¾›!qCŠkMª™›GL¶Q‘ÑHÅ!b6ÉOûÛßD‰Ö©BØâxÅ<#Áv=puÌ@q£ˆ;Ž^/W‚‚*Y^Œ,åÎöNàB@“ý¾Q`î7ãã-‰°3îu™MR;²ˆ¦HB ”’ížs?ÅLJŒÙë Ÿ,\#Ud^4`§ô®ijø¾Àݲ–b–Ž¥’@¯·þW\RøÊ{\š°î†!nž;Ù´>©ù¬ÚƯÃ;'cÉëÕîjm¶£ëœ¥0K [òÚékkRÞ·¼xï1†å7Íðf°‘óiÿú¼¯EM‰K!·SíšpƒEÀÙ. fÃT«…°—r‰ý:aàŸ LÇlž¹¼˜íh ”wŒÅtêeÉ ±Á&4ª’ ðQÉËľ)1¼®,Ù‘5ÆR¶‚ ¤I” ÔH‰˜ëS Ó·Ö¥’â ï{AØ©mx‚Ú1åø8éœfoßñ¯žWŽª5šrÃà7"Ž Ü’… v2Uc è;+åžæ~9õrê“—÷±ò橊”»Ÿ÷+™`3Ø…È@Ù L£í:"…\PV¼r¦Ë„Æv’@ú˜¼*ËJÄL_dH`äƒ[òh5å!,¤£Ð1¾ ì;O!KD¼’šò@jL­%ýW¢ 4‚‹)ð-íØS&1rLB’í)¿w‰Ù0d-Si€¼«»Û M›³€‡ãdð¥™G-o‰ Á4­e4>‹P–) ¯#¯Dª€gönòXj+©DÌšÒ©Q{QhãIm¤æ¯¤ÃQDPËîÓ¶D¨5AŸHã¿«j’Kïñ` iŒz%k¼ÔÖbûÝeÅTrï[ }8s›µx²|ü–MR–?wÃL=ƒt¬b`¦š²p9± Ø²W"îº F¨GÀKÑ$ÄÛƒïÑ–ÝÔÐjŠœ/ÆtÉ"SË0Ü['.…Ï“MM-¤.5Š“Ž*K¾ûÒ7ïµ—A¬Z2$Å[V(F«)…¥ x–Ž`Êbˆ,YR¾v~ÏabUéÄ¿wGfpå¤vÖ4•¬>¼mƒY2K`² ˆ(ÙØhÓ‡‹CçYš½™eˆV/c¿å×H¹ Ä;œŽH¡’Kà¸â¼ò*‚PyÙIu¥:Uå–‚^/[B˜#BVpUŒÌëâVwŸ›3¿¼‘+¬©,M)¾8eËæoxàéz™#…Ð M(YIËf³'«ª‘*Ç_IåÿJ>>‹áqx»àž¶ï.GµhZWUwË)x§±F‚F­»á{%ÞH²!ŠY{L¤Žy×îÝñYšÀd‚,æ“Úbck*;_Ü‘"¤ G 3-Òwn-k:µÈ8e»£pà÷ñâãÔŽ7@âç¿`÷šrʺóì¡ òøTjÏ_G¡—ÂýJÀ-‰T"Ëè¨ê€úԔȲ ZV!“ee/3´Ä©§rú÷*qsÆ¿›¡—G:²ñ ¦?/e¼D ì^eIÍi ¨mB7Ÿ]¥çÓY',P…Ö -Há~j¡95à5I…8d†¯&<¶Ð²I¦“¦Tf€‚ô#oª&±\¶”’˜‚Dj yH¿½Vî:îUfSÂÏ´¼ë7Œ”.m AÀ5J¡!«­ ‚àpî¸ -3MÞ’w‰Xj‚˜R"v¿5C) ¤—ƒ˜¬”ÉÂÛTââqB,©©¢Ìß­ŽM!d¾ÙZ*¼£UÛ„ôïûŠÏL¡še¾­YRvdk˜ôÅ”ã@j÷ꂤYmCF«P Øö¸à 'CÀK ;já²5²µ¥âÃÑŠ ÄÀð!À&)4A—’·”e‚t,5V|±ÎÀq¢UÄ#§Y‰JÕôñ  ú*«‘îíZàþëDhu˺ t‰ZÊ’Ž»•E“ÚöÓáë«05÷ D¼m4f¦VS¾’öY¦¦qøŽ¸©¤,ÑÒ!Áðb8_SàbA_•ÇljFY;dA;E@N0²™T„•·û¦ƒ Á(7RÒf“&µR|½à‚@n¹‘j§qø¬Ùè…t&–µ®£%MÖÞ¦€¬îù{£R¼*žñZ[nÔåh‰@LÞN«…l<œŽn²‰ãÐ4\œ'T’ZµM‚ ·¤ÀV(†Á²»/1Ĥ"P†-™€Á·‹Ze¬©X¡Ø9Ëðb».°Gå-ñ³+Nœ2~¸[´%½£lw]àCëú?:vP|¯Ç.®d»k³ ©F!$ifDÌWXl‰Ÿ'%àÓÇ¡¦$¦ªE…»ÉqR¨P¡B [/-š³¸T´6¨fçœH»xüRRSYÍjßôâjœ ŠÉÕR˼lº 6ÈRV•8ßå÷iWëJ\]®só+‘µ¬‘r†@¼ò˜²ÑÈJ-So±ÖNÖTbtÚ&\£ Ñ’¾ YA†¶ª˜Wéq˜Rµ ß² }e«jï²R˜=JŽÊí0•Ûo}Ñ”à§9šìDb¦Œ¦¤ÃD`².üjò8UR!¯D¶ãTU¡áY‚œ}Câó›™ DyÓNad"ÍP!:½½2ÒNð>jË"Ã-;†×´ª²@K1<¹ ë"¦–lµUARkƒbASUŽœ,¾@JP_‡æç üN¯x×Ý8µ3 ¼’¤¤XS]ù‡²lÝõjGâð=²)ì ¦& b°8é(×:AÙ‘ÅÓ—E³?j˜NÙÕZ²Ú5† ›6‰©]…q˜r†³Q-1í¥ åȼe|¾ò¼.Ä™˜MP\¡@•iµë’ „X)A%É^™s{o†Î|D8½¯ÓSžxU˜”‹ùkZGÊ•S>?YHœÅµ±â¨÷e×RãÞŠ´±Œ"K‡š9€–éK…¤ÜÙõD•D·Û–)7 D ¿<A¶áÅ;K„oΖZdø+Ij/6ó('Ë.¥Ç=­Âä¥(¨-*®‘Ž™Ëæ!²Ùiÿfð•Ã,粤€âR‰”â-qz1w†‘ʤǴTR–¯#„BÙ&ï‘rl RJš¿Zˆ¥˜Õ"Ž"1!RïDd³)T¸ëޝ;œmY•v òÓ\ƒ§„w}+4Éî=)Lø.†7§¾¸ÝYR«W4Ëh©\ Å&.–º°ãŒÁ«å‰¯QÃóL#%ü)x+/e)àâD‹yïØÉc"ÔQI{‰Ì§àú¦au‡\ÚÇ©b‚ôÅ1qšÄRÊí„“Bx‡´Dj Õ$ aSºø¤&B3©ÔàL!:X²8˜áI…ˆÑ îL"¶Ùµãñ¥ðïT7C;²d#ŒãCÒÄáÙªè3µô‘e\’¶»˜ªMaäº X>þ×@K·U1“V†z-YA¼½éTƒÚ7b£%—íGÀtÀSÁ´D¨KÁ}ž”y§¶ç‚¥ÉÛ3P#E$PÀ€<„ß`b“Y›jÚȲÌ%o0^#>â '+ˆœTËöXS JáDIªB¸€ XÝ[6p“@ªÍc& _#©È# l-Š-Gg¤ ÐM‹á-ùø¿ÃeŬij€,Á*Å‚Sp+)…sŸ3-êÂ#0LYË !Gµ…p¾8¾%&B‚Í0^’–&ß0‰tψY]•G 盇×H–ß0‚ÀšâŒ·L0‘&¬V\ÊRydUÍ •¾,«{&C€›<å‚4ÛN´|²˜—Þy%Ry©²|AµøÈ|Ó.–¬@IHÞŽœ3Y…µ|˘–BÝljVGÊðR yAÊD*O‡ÿÅŸþô§ÒÒŽÊ,ÉÕµ_Ї§d–•ÅmU =¼¥f4¾ ºS •]y½“G0~¾ ÙîB±£$kÙ±Æ!•,ŸZ-6•¹€GfÀbʤ*ÎRéë(`µ ‰o"h)°L\°cë^k±€>?dãlTËu©Pʹm¼ºX >Ó—¡ñIIé%6AKž™’bA"˜.Ъ xšøqxU•ˆ)£kÊÉxSNjר*¿LGv:@V °ŽÕ–ŠIdšZ38šX‰¸e2µu&‹30$%áb°Ô€,¦@G1µsôoŸá%ì°/~d­*¡@y­]Ì€c™¥V;BçÃ3xÃD؇\KYí¼¬ ;=ˆ%©<\9<3ƒZÖÍ<¤ÓÓž‰W>…{ PaÓ‚DÊã‰lYàðõ¢ŒÃ³¹Á’q¦ðÑòíõ‚æ|Ðj!›Bj›'¼Tjâįq~¼c¥/U¯”‹cò@–BKUí^,Î?þ»ü•ÆÆÈ Ú§Íˆ]W mâþPR-üà¨`ÍÄ=ð+W"kX;ß7!ÕRs²•ü[w·ckniºSÙú¹{Á'æ!߯¢©’ó '™äZU{wKòhtL´Ø}ÿó—²ö´PªŽšž§£5º×öQrV¢KÈ>㬘äÐ ¸c©q³¼v]5‡”™‡[9@|–øù'’ôï¶J¬ð”ÀÕþñë#V}/>ÛÜÿpR£·jCÙJn82¹™î÷r¶•`%íýR¨Ñ¸·aßšíC&šEÉ¿€kq$8ûýüpb â‰'3¢@~Í?ßÇ50t!†ÊMÄVíh =Y9 7G‹Ánšm#Ò«v©Ä¿þŸëxœÉíÜJãe¼èZc|Û΄ŽÛP¶3¾R†sÚYõupd®”'LÉ ¿‰¬ŽÉúôÇ俨’ëÍ/ôÊ1› g «”™ÈøÓª²2h<#cè»K-kW…3‘Ë]'<2·–E%€I?€co•‰ãëï(ˆ#ÓÛÙ ¯=g M×A¶'¾’¬Ôc2úJ=B·Võbþô_ÿõ_±¢ h^“šJÆ ï&d0½c˜¦ ‹T…‘0g‚ªJU•Ò¨ ع*@?^ÐôjW~&z¯é­íH¿*CÐgÒq «ö983Ác(Eª{#”üÀ·±êÜ`Õ9ÀíVž±^Êí™LµØŽskJG< Ü|0»{n rP® cD#âø-“[¤ÿqß3—9tÙ 7¢.؆ÄÁ3þ'ôÆÚÏ•Š^l ¥¨ÏQÐÈ4âv|ÿô혬–«=²‰cd;wYzß z>”@bG#ÖÕ,½ºT9LôÀF˜‚,ðdZD•aX;rß«d•Z€ 5<Û6F%¹U…cU¿DÑ1·œi4z„†*½½°–HJš>ÖÜtóIæhÃwP&íÓ†ÍÊp AV}¦!à¦*z1 ¥ÜP-½ æ ¿ ÕÚ›Õ¶}.-©TËz3ǧw ðÜbﱉ Ów$ä–T…³‚µ÷ª¹Í¶%] ¿=¾.p>òlÏÿ‡0)6#Ý~&í!Û¦oE“€–€»€d·õû[)Sjœ&«leU4&­×Ÿ2ž¨±e6B/F$È0¼.G澩. k÷ÃÐÏ<“¬ÅêŨ Gšöðiœœ Mbd‚¬ÊºD%-;LDž²Øžk!ØGàXIî"·ïð@æJ=²•šE?1&=­à”žË8‘˜ƒXæC\W‘ÄœbnëÙ6h -ó¬4%@Ö+¤Ñ‚p J!`žl&@×l L™­.dŒ\ Võmt»94ÐSæ–³’-Ó±Òõþas™R„嫊?ºŸèHž¸mÕcڰϨqJ}ÿ-SPbÖ˜7«×éú-ƒ'N&ÃÚ¾{ª¢£é6(^¦çCðkľŠJ9Äé‰Ü”xÊ" KUÀæÝ«Rí°AíC ðQ…ö\cd>ñ2F»YÈ×D #øÀ&ûT«Â"g€XV’g¨ WeBãh.€¦™g¼¿Udõ§¿ÿýïúér!%âU^ÀÔ1Ûc¿‚ ÙÑð)·¥Ržx‘¦Ì?[-)÷(·é¬‰§´=ÞD|  UÛDZó¬½q‰3—Uu¥”»)ÒJ)UÅzÓ`TÅ-~ÿ쫊ôš¦ðlhæWxžË1™÷»r¶aƒÌ…jwœ Ip‹çÖÓ ¤…u Õ³zË\ˆÌVëJ0^TÓ4OîGk¿°¦¤ïÕøÀ•Ú¾c†rV€ kcxbHYôÛCS/ÜbŽ€å=¨ªl= Aír2Ê +úl9`T±£°*Ð,% ÛÁJ¢RYib%†–É0}K⻩£YJyêUʳ®ª2ÁûóCCLÓ\Çé1•t <Ïáæ"xúzSÛªjw»KdŸ>\on ·ö`Þ’2ÆZcΉc` w3:¤h"éHéø:ÀPU‘®†§—Ó+!a³`¥ZìYWæ}dYaèãó¤˜Âψ#qÎMTBb8‹6©KÆxŸ¾9ZMiŸ)ÉZ†F)œ’ N̪#¥Ð(+!eÑg:¾Ý*¥Ç$ðHGú²krp4Wu%ÀÄ"*&Ró”×æî¢„çùV‘ M\N¶RÈfuw8ÞÐ~qñöûŠÃ„ F™ fÇÖ–i¸YÐ%‡„é d÷J Zož„ZöD°dûÜúùšÅ 3²F†ŽJÚa‚zó9ú ök§ÞHÁ‹t“¾Ld•vUÖ­®·{öˆ”Ú[FèB  ÐR¯*%RÕôñ“ö™€ ŸCeLÚªÒn‹Têάbhtñ™y;äŒiäJ͊Ęˆéešë¨*+Ven ÇÚeG¡EÖ’p¬‹æZžmÛ?}²|"a±lbSæ)#‰›¸ušyíªJŽûëÅ#•d…ëTM鸭’ÉJ³…ue2>e}µ”ZƒXoSkÀ V²%åó_õÿt‡€2—»‰*,NÛÏßOáô²p½É88 |].ãȰ)JpΰhI ÎìHbPI19PFZ²vVb;#E†”°¬ÓÂÀ•|Sø7®ON©#žÒ‡šXN *XÉ4ÍUmP# ýW´ù2HOÙc®wÔùÍÔUK³F: ú–a((12·VM¦ÔEÒ$ Ë"+ GXÞeᔕðU;ÊÂô¶C>ËkWõ·`JûáÔØÎÞ/è‘ ‚}.Söbdº0·ã`ÁŸ@Vr¤—¹ÉuÀ­ ˆ¶ê×P$“|0Âβ+è…å¦çÖg 2UQ;™j7b[•Œ Uáv+;¶IVz‹–Ô.(U¹­ñ<Ÿ¡9ÇbÁ¡*™#~sƒUµ×(uÄ$Kãè)b¸ÁøJ™×h.¥@ À*s^‹Rãò$;m÷+¡1Y›ôÝF^ïïÏ­<1€2„s»®g ÛzJHνÒH|úFg›8·˜.;ÛLS¶*œ­cLÀøJ4 _¦®¾“ÌÏ× å§¥¯ŽÎ]8i Éxâ‘|‘°^ySswÜ௞97ËMs@žKü<+ÓV-@™˜ž & zU³òéˆÙþuùŠèÍv-ÉRFw‹6¬%L Ô7Ò\Xè•‘EþªÛ9 Ó`½Llÿpþ×ã[ e#NÛÏŸCÄý ÓSè‚)…ªÜ]ZXuþ­7æv|bšd÷]Ïϧª«2¾Ë¦” FÃ##€3qq@oK«’åS»ÜV#µèÅhwì‘ÙJðÍÒÞLþ¹eNƒ‡…v½}?ô›ZΪ)”ްÌБÆqkª64Y/ÖE–/0JôæšØÎVÅ(‚ŒFh„Ë€R¦ì0A:v£4Û'™)ÆÍ?CÇ3ãö’!1Ö^£*C¥Öë(w¤¡ï ÷€°’ÅôzÛvLŸ².Œ£ÐØVÄ”0 js¶Æm"’¯ Jpï@|ìî25ö¿#¡ç‰oŠ#= ï“›ì(®Í±…uJ‘&nœ=7®*C¤Ðèš‘åH¸µ»’›\£.|Ê&b€vÀ÷V{êLÊ9·ª®5æCCðý×ÕèŒÄî2fðUÂ×£¡Íz ÇbÕ†µ®vUxæbd7ŒÑHo=Ù ¸_p}K‘LäzËxd¹ïw|âvh=SÄ|ºò˜Ì}Yë"k7 ¥ôq|K5îÝì³%u%nº.GXÀd²ðø2r/Ov;Î;5NÞJ™ì#àCÌrΪoç4b/Ÿ¡–¾Ždq;ΆĎ­ß<²çÒèh±Óy7ï˜ ÈG¯¬WÖÈ¡Ñì•ðÛ ßDdoØÐ ‘F¸²}¶pCéÃ'–ï:Ú)³­Ô,ŒïLnrnôêÚÚJUÓziŸ™Ôž^ž-Ï]²P*ØÈÂÂýfÀ˜;LY ¬T/ÓÂÄ~#„lçíXfÛèzÏ@0TÈÒ„»²ëû4a%k“…n-†iLž9´I& ˜ˆÛ0žÙ÷?£ØCäzr³k–[‚,/@?^`Ž€I«ä†dB©´Þl >\{¶ö™X =`ÛÖŽq=¤<·æ:Vª×Äé7B‰¬+À¢ÞòZræ†oí£wœmÓ(½Îpž–?cnUnDΰ{!s1ÐÕ\>ôE\+xJX´7½T»’œa½°ÆF7bü;‘•H&kQ­‘§Ÿ>Õ·ã´Á¹9Ä"F~«àmÒ2嬸 U‰ÌAv,«EúÛw6y÷$«j„•´Ÿ‘÷·À¾iZh”šø™þ_³8ø\j'ÓÒ悔÷ÄV­¤k#è3¡O‰dAŸ¸FcóËKuÿh ;“¥ÙÝL¤ÝR’±M³ 1ªa¥KRâÛ)"»‘ã.Ãg@•²^¤hUüdªÖÈPÚS¨G_‹ªR{º‘¯:F‰FïËDÖ.‘@Ž»»q"@Ë:ÂF”égºªœìm„™˜lsÙ-Tu)5Ýf•²Ïº^-Çî.ߥbdJL7úþoÑedŒ#ºÔ‘‘=%, :zb‘ó Æ 1² æCF¸Mxª"[=œgJ¹ ‘R»Ð(ˆÛ _uk(éMisú2sU¶ñJÂñN;ßTUÙñõgå(ZiÇ”›¾0°Ëf=2“-ÓGë(ì ´.z11 òIÙ1zeUú.pSC•ÒÈÝ‹,,«Rjy­Ö2gŒÞ|ÖâÈŸ[½LXuô¼J½¶F'ЋÏÙªHÕVÍŠ@©.hJ|Uæù# dAƪ#†):A“,Ì-%@Ö r½2R†–{ñ ¢«5®åÀi˜÷D0Rv4BôbµÈd §YKsïý¶3ÉÐ1%ÁFDb"‰ÇФoú¦(¥/Û)hÊÕ¾á3o¥Lnß×Û 80lCz@Œ¡i²ªck |³^ FV³%Ã'Y»,r辆d»*f ód]^µ‡íÖÛÄÑ£ÑGâ&ž…~^8½’Ù;ŸÿsÐ:YÜ–ïg†oж¡Ó bŽ˜@]Ú•`|–‰¾A²È­?0húý‰e>~-ni 2f²¬äfy)·’¤#&£¯3E‚ÄåFðIï:9”ñn 1€q;ÀE0þ–˜9“|ªrªâWrík‡xǺ€˜ªå‘la†™ôÚ J‰§±Òdg *ó–ÉD¦ÇwTu”é¡ËQU†;úF©&ˆ¯ãhb%$½c+Á@O<^·úŠU# r.O¿MnÄ-ìX¼]1gÌ ¥6tR’Ù} @SÈD¶t˜H#ØÄõÂxÙQ¨ ¯4wÌ-~U¥ýØÃJò¦ô2L0¢•¿W"ôŽwΩYkV˜"qAæ1²`X¦ÏDîÁ(Åï3b˜‰ÅªÖnU—êË™f†“i4®ª÷w,(E›¨Š1È}uû~rxš”·ã$K2|«•¦ÔEpßõû]׳$ÐŒ!®½YïªøªsVEîp«¿ôJZÈjtG€ o½È ÓØJŒi¥¦œ?îˆ3ãýT¨1¼D þ-˜¼ÐÒ§ÅŽ§ÌªG'Ó(§Qr´_nZê›{LïW?Ù‘€^æPÞ2àf®{¼FJ¤j„UE%]ZFä´pb$C·3ò˜>]ÌéE Rž­‘ƒÜ•kp>N]ðF¯Ë8¼'M‰777¹czß@æŸXWÇøHz çLd³ Ý•-–,%Œa•›c†µ#1b]xV˜ÛqRí˜[¬}ÆÐ`ú9Ÿg#²’E]òÞ3ÿªHp;”¿,Újd²_³™'–³=Í?˜ Ñ¹H¹å÷¿ãú4µÐô+dÙÂ4>‚4Ž • Úο^†m¨E eÌëïØ£ÅÃÓ¿S²êvMQE6ô øùý€É– oN #ÿŽåæîûLÓÐziDw׈$Àì››}D È¢meX{kÀ™ôbŽ iîóÓ!àµ;ªj¯Ë’ÀºjLÓ ¹ V’éÛ-ŒY•Uwi"¬*-IT’û&çàø–jDÇ-C87×™“­µ«žÿ €”bÖj32V"ÈWFæâïìÝ¿l’ªR iÜ–€Fiþm“¸Fß`÷¬‘3 ì òèÒ^oØQ)#Ò•jL³­hŠxÊÂôeøGø}“ÒËüËô‘Ý^ÉËJ²‹¸#·¬È¦¬·U‘yfë¨Ö% bV4Y9ª² WÍvp$Vmtb<%¬Ú—Œy²¦¬KcŒ ãن߉óÚ¹.G /I˜Ð-ÒÈ‹»õ÷+€2Þž¾$+ÕËD$ ¤1ù‡ebÝt$@&bê‚E¤Ü kÌ›ØE8G¶Xz8U‰aþH› ýÖ@Ú0ÍF#án ¨ÊÈ^‰›H#à iäý'rôFøN J/3›˜aKVÒ˜h´ý¤hb_¸6‘UyjÔÕ2Z€°\£L“^ÓÓØ§—A 8±YSÞ¦ïGtãšÎ!™)Ú7:²ýñº”Ð>Jid|8ØV°×H‰”û‚½¶”®f­7[%@ Þ¸ôòv®½9cz–z3lU+Õ‹ľ JùìFz ‰•4jÁ#­*`-íVcJ-ªxÕ4Û3‡üóŒ‡#µ`úøÆ2Á³ÝÕ<[@µé•rã4ŠöQê§@É6и®à}”2i%LßÇø7›Î¼oníi†»W[5‚¸Hù.Ü}õv5UdW†9DæÐ'…I€$–s÷ËA#ž²Å²íØo©js{"ûp¡ ëÚP@üñ Té¬Ú*Qc “åõ?ßÅ>­¾èC EuÛ×øözˆ )­š¾FbðÄ)c@è}'6¨Æ~Òèko“4HzA©JÉIƒ„oñûEC³•âåâ Ræ&sð9Ñø¾â›;@†‰$ó kÏr%úŽ™tlJ2c\ß¹FÔ5LP´v×ĘÂ9s3¼¹]äëÿùzô-ì+¨%qnˆl7½‘M$v”éÇ4e†N&«*Éö×È¡v9¾5` ½˜à+ÉvÆ—1Ü/¬5’©ê=m3Ùw£^ÕÖˆSrîä³­FhÉ &à¦ÚŒÌD£j]xLS6±’,èåùà u” ÏŽVzUíÖ8¼àÙñjFhd.‹|ÂGÖ ] çClĦ#­WÎGµA2ìÇ„¸}Ú­£ªÐ² ðùÄ¿Xãôdí ¸ªMêÊDc¨§' %žðr¶ â™!n&Æ'Ö‹±óöœOÇ|è·g+Ù¶Þóÿ(kCÉ]€_ Ö¬Ô;²FÒœeïñ+ɘÜ"eŒß}íÄÁoØþ™¡®ôÄ­áXœ?ßÎé•(E·1k¤Wº}ß„£‰æ"‰ý°%fˆ]9J [h„}-Ñ]h8ˆHæñ€–H]&ÂÿmßþŽœ§éÓ¶»Bn/Óh4]‡Î9À[ƒ0íÐo7-Tñ‚&™lŠŒdµp¬=fʪ–4‰aëák©db½x;Ì–É&Rj¡$ |ä¬È6+RnDœö4ÉÚ!“†vñZö-Ð{ÂL”h0ÖhíFG¸¹¹½GÓuéEÊŽ¿VÊ I˜IÈ6itk(!y:fk´_޾*kÌM‰§¬EÎð-©Z@îî0Aš²^ƒÚ„ŒOWVŸ9¦YíÆŠ@8 GUc€/(1­Ú¸òª×æ{¨öœ'¥Ý ïØ“žó9³ït¹Ÿ¬)U-£·¡ø«=wTBʪ­]IΩ¤ÝË´‰®Ü”2¤ø9À={$½Ì6 }ƒ˜Ìi‘C¦”ß®ä³2ežY9Úêx‰|7›Zs|vJµuzÕô)}ÿæ»Á1 ÊùÁÊšXÞ5ühõÉ!â€í ;ÆØ' Rp–ÇœþŸ_Çí@o²–á6Fžd[¯ç#À#õzô3æÆ±¾Ÿ½*ŸwÉÄBU2Ì•ÿ?ÿÍhÑŸoW2JSdžÂP&Jr†‘4xa°•"ÓÈ9¨RîËÄ#¼¹cJ@Ð;fÒhxd¥®à.“•¸Õ’Rî.;h§ií=i&ªVVòÄ´š¢ ä“s†HTm‡4‰ÓÄ;]Ÿ¦;š¨·ß•òïCQÒ…ÉŸÞ”Þ¶çå&ˆ‘4Í øÐ`˜£ñ3ì(šÂ¹%o`Å3ÜþÄÈžŽy|ï ·&C² Yå#»ìd»‘örÈ„P5@@‰©˜›RÕõªîjHÕn‘ 曆²ÑpÀ¸ùú5ñLºÁD 07]ÙG™€¦oZßdd+ÑÀ, zÛÚë-+´¤Œìûœ‰Ro’U-wÇã),³Ç)õ ÉsËV‰;öËÏDäÜuúй}ÿÿ¬!©NŒÎ­˜ÀQË» MŒFGÀ‘U>Yɘ•>Ô–‘–SòøxšµMú¡j1íÕµŸžŸìj:Ã.B«ªÈ†p²ªX—’H™Ïd<}@{Õ²o˜ÈÓŒ8¼¡Í%ȪZzd˜Ü ppwLíÙÂô½UAÛ¾¹Km[zUYo¡Ôù(™"››ÜbuÏǹ–Üš‹ªŽáU륱€À[oh³00ƪ™À/´TUŠÙ¶2]òÈÓùó÷2¼À轕/5Ú!M,,àÁµô}K1poh·J}pþÎÞ,$2GÀQ°u-+õé´†æÅõæY—jáã³A>áù·^ïé5ðd=ÔYåÞËòY9U[ÿ4H¡½AL67%¦õZ•8·ö1JŽ‚2ñ¦ ð!¦ÄXL}ß“JÙª[Þ‘ÒVœkf«Ò`ø0Üžj!PêšMÉ¡–õ’éUÂdÒ8þì'Vâ#j’Õ’³^G¼ èX #/B¯@ÂÆ “OG×Á´Câwîù¤ûK˜Ú}jÀl§·¿2=¨Å#zn]o{˵YúSҢ׺õö™áéiêUõ}•[ ©$:¶ƒ#¾o€^X(±­DÌA)fG²ãõó 9YGdòø™xÀH³¶²h4YŒv8‹c¸8Œ¡„e‘· e&í3Ü[%–v0ˆÕ]çûº´½ÐÎà–31Rä ×»Sµõ´;ï/sÃä£× ´¹Ž9ÈaŽZfŇFl ì¡Úpèj¥ÓðÓB@¿Û‘m=%‹uj]Õ6‡éÛ™?ÐÄÙÖÿç?ÿ¹ï$±¹[íßçÔ›§‚þ}–•€^HiÉžˆ³HGUGxãÈ4b”ð†f"s6]d›!=&O€~CuÁï[i±¼—»uŒ®z#E£ñpSÆ$–ù÷M¡ )È„Kõ ô~ÄúÐÛ“FW7ÅhtÔÅGU¯£ö‰T•ý+;bJ5ÊøFËM鎬ÇäY©k†enÄdÜ` lJ-eÌŽ@¸…Óë5níyÊ”õû º¾–øseÑlàxÿ|Ò;ªv%xË!»wâÜä–3µ‡¸Æß¯3&ŽM×Õ¢}'àŽùȯç|š.cZî"¦ëª‘Û”ùØ¿õˆi8&ÀÈ ! ¨qH½~žñ}‡Úá6ý[c£û0¤…"¾.V1 Ñ@_ñ]ð׬YÑ·§d¶ô€Ò¯—qDv#‚L6=%X¤Y‹öxŒ®0à(¶’.$1æã[²’£à#cfØ [yºЗ™Ìn ª"MY˜œÙ? Æ ާÁاj>¬T‘ÖóîÞJiš«ÑQ‰Ru÷šO +#SbÚ¡ÑH½<ÓȆÖÐ$Ó­ÙÖËù'ö”Ú] à4ÅKvd(ò4Ò§±¤àÙÏ„C»ÉBIäÿšTÅäéXUæã˜¹—¬Ô­+iQ¥4®ªŽH²ï_Î(`+g=Z̤´@IDAT_Ǫԕ‘\(ËÂ]l¯Cߣ¨Ò‹lñ|„?¨uyG]d ÂO<·J2«Èæb²•9è57&€ľªzE>Ž€#PÀöAja¢ .vJ2U R‡cô‡»)ŸWÿÉ*i-“•å׸Ëcöøzµxž¶%¨‘ƒ’£jC%|_¤Ñ4ËqÑ>z+éÂ0é­rCÒˆªôB/÷¤‰eo\-‰›%WèX½wPêjJUå¦XŒ›œ€^££–p1Zz+ ‘?L)ø¨ÒXèM£=GUbGb`Ÿ>+|7RÅ´j;DÆ7i”>¬HGƒ’@hTò‰G1åÍí롊á¦È"™Ãx;d¼†Éçœ,´·¶¬ú§þóŸë™~ŠŸ©Ò>›4]àö}©1ƒoQµŒÑ¢ê’ç‘®­ÏÃ1g‚&ö í*ë"V’Ya üœUÛ‰O=sxSTá4Änatd¶0ž!Àp `ZÞİ£€EËØY ëª*3Çh\Ö‚[¾# C%nsn 3¤‰GÖûfUV[øÝª.% à[Ví ÷b4€¨JÉ­*Òq ›ûú`DËãÍ•)וhŠ’8#¯¿v;¬>ÁláôŽÆ3lyL 4 9MSˆÿsÄ4õ:¾Ë#‹÷“âÖ›Z£q-¼)& ž"™#À“æuñTí÷éÀzµdr]O²²àÌi0‘Ãå¦Pjï¾8åëOlz œa7"Éœ2!ÈhùZú9¥És²Æi‰ÏŠ.»ŽæF_¨ø|j”‘˜z;öø4|DGLí‘ L´?† JØ-êÚ&h #Òï×f¼\´IšFËíIЈ¦¿ÕæíY ,XÙPµpSògÁçÍš'3ØŒŽßý4ÉÔ®/#­2²1² Ľé™ñó· U½1°÷mé07@Uûœa>cÂ|Sö9ÕHœ[2U¡Ô¨£Ü4þÖ&hD Õ.Ž÷\{V²¨dhJLÜV ¯ð¼ RÄñ‘ZrNp/q>ÐŽY×»c²n¹²mñµïÅÅÖàîÿÓˆ¾ä&]*LÌ-\ö±¶ª£x=[LæV…9èÊç6„G6}wA*9Vb‚»…jÎ8 ìX¸H—ÍDþ)žwPµ’.VÕ•f¯¤„Ô«EiS00ݱ¤HÖ8G%‘Oé˜90[ÕÓ#e™¦X ^—ØÎšOãX8ÈÃ!~þ3I–æ¼ê_ÿú×ÚÖovm˜½‚¶©YÐÜU¿ßŒ”Žkh|&¥¿­ç75úÜ,Ëd1›Ž¯w£ÙÂ9SêbÛxæBWä®@‰‘Ó„™PŠ ½JU‘ô¾Á-FŒdxPâu‘)µŒ’%¯Í¹¬œyV¶"®W¾fßb‰U3º©ãÑ×.óç™m#e2L¥ôÄ-Ï­å ”öJ94±ÍaÊ2ÃÚµâ6OïÄËÚeßœnT¯v¤h`´.Ï•œÏŽí°AxzžÄy&ˆ)+ÑP*‡ÔG ‰Ñ;¤ÅQNO·ì^°·¥ä Îü³%ÐE£$ˆ)æÊ‰ihÇKŸ÷A†iD¸§` ŒqlIdß@ž 4ª GL9O>[ ÆS”@¹ýk)_×ó½éµô2Ž rKÙ1–YºdƒT•äRÀ²ªà|¹»Ô•ŸÆÍ M¯“žR;’’¦Åé‘MO)¿âZ˜ä_«Ù¦qièÉà< è1ûò(U•ñ"\nh½ï¸cízûÁGÂò÷;ˆ¼S˜d›>˜«:m@wK 7@©ªÜнàÙ÷¾Y‰_·pßÝL0"qï2‡<7ÝÑ;ê"ެ±¿*ª¶LX$ÞCßQç‚Â@¶;®Š™ph–÷%}¢Ö€ÉT] 6—9¬— «9"Éü;Äþõ2 ¾eêuT­ NCÜæ}ª6Â1C-1LÄö×ÞÎ@z=F;6 Á°M<ÁÕž£‰ëJy¦ÞÛɦóoÛ™;*ɺþ3'Sê7²vÁoV-º™À¦(ú|ª¢»t´6²S`¥0‚Ò`n.½R]Èãûc’ÿŽ jÕôr>l……µÝ&¹íjÄ ¢„°v00QÎé Ž]¡eÊÆUrÜ+Á§÷,˜¦Ìƒ·Ïô@ˆÄÈ e-eU÷âÃ6ZÀékysU‹V‚ÙšÀ¬Ràe&í À¢ &ÍĪJ<ãùãáÆUňz+ÁE¼Þdå6lt¶&æ6JwÁ æ$˜Ô(SN¬‘FCæm 0] þ~ ¬™È G ¬³©1Ž=n³ W¥»ÆzžB5%¼߀u±êËW M-«EÎjnËÝs; ÉTwg‚|*9Š³Ü ¸K¥ÉVvä£*6(ð2þÃ¥ô‰e£»e17Àõé½*7ÕÀ~ ôÚ§ONµFJ¶0 D rf¥„ユú¯¦´Xžk'Ρ¡Ž3™>ÐÄ4-Ð>xL¤L,.qœ§i1Ç€M:rháýšÃÐS¼Vȉ›8V1& -ÛP© Ш”->ÛÖÞq½ª¯«j£á¦³Âì«e4²*¥•ødBlçdù8"ab<¬Y5ŸÆt5d#,¦ÞºM*ÁôæîññOÐÅ1‘ÜrðeÆt‹[<Ш=¾–HÙzhOUwÇ‹ ñ52Q-`Aã˜R¦ìRî®…@5[<¦{ñÇÓÈÈíÐq½øÜ¥e†Žný^¹%õ4ÒœW"À˘N£ÔzÏgYƒsê)°=XP:ŠÞBUh9os/¯äÈ-RõÊ¿DƒwÀñáVï¿×Ñç‘ ½*qž€#œ¹YíéØCC#‡fyµ*»½»ÈB;%ÒëÔÕ>Ý4üšpxs,²‚ÎÚ…£<¾öHXÉ,ÙtÙ,1ª \A{&2A_¬<‰à´ÌYá‘•z–É”R6EU 4V #™GX D.+½%žŒ7NÎùÝ67†MÌÊ&­hQJ"=q¡ÚÔÙ‡èGˆVÒNæÈäšýñSµ§ðæM¬±ýë% •út”L‘…”ø–z–-°Ua+Õ’ g½¾±9`ZÛ-è½’hPÊ^ ·Ír¤¯}þ9¼z>®à¿‰GgÒÓ™â‡Ùº©•²í‰úẔIß„>…Ä2R ·Zä–ñ”²¡øçÖ&r>¯^£ ãf¢^ ÅŒ ‡ådª”ùsëˆéMkL“'7ʰ,ÈšÅVbnÄJu5—XR”.Ï o€ú^"ÉÈÂëêÚŽæÊŽžF»Èjú†n ‚ÜbæÃÿŸ™ŒÆ]l%§AÚ0ŸÆ)ÙC,ø”_n½ùtwÎWõÇß õÒˆnAC2dS•M§Ú‡²#†l¸­0@>@»öé õ:ên dñ/™X;Ð&­D“›Þ"žÆqþH¸F|]Ü\³•Ú™¦GóžùdR¦!Ϊ}ò×â•”DûSy"µÃý9í˜Oû4ˆ€¡^IèÉ ºÄ÷3o\š)·¹cÎ2üîé°UåÃJ8T²Aãè-Ÿ9¼hPžý¶YûžK—<‹¾í”‹í@€t4TK82 ›âM¶Oþ²^þ{®uaÒp³˜ÏN)=ŒFL†ŽdÙ&H%I01d¥ ë’û†ÔÒûô˳µ'oˆ¿¡:Ú°[w/ãjXÉ{Ï^X/A--œL¶Fí]¡L<«°ã‚ÌG¾/©…P€àN¡ è‰4é>˜ú«’%h¡L*åÓÔx)¿@#CþÍÈœS4rbÛfî¨ îAÛDnŠª„1|,cí`Ȉaу¬Ú‘@ €+üRÞú÷9ªÎ-q»•1À½Á÷{3O>BÉ›tYÊ®@ Ö˜?€¬·é1ÖøÁ##P••^RÈJ¢¡ŽÆQz@T²†^‰&ÃŽò5øþDô—»˜”JY4 ‚"ÏFàÌÍu '“E*i>bÌ0|,€‘çŽB 0õröýl«ú~äë*3dbž5šž'™³RßvÕº8ëí×â4¦kÑ>·- ‹Œ Mú¦0q<{ßÇÑØ\9A][ Ï“Œ> d ²~¨aA@F#g (!kÈR&#ˆtYÀÝàgŽq$`âR'Ë-Íüwìñ;nYJLdǺoKL¤5ØÂVŠ9Žm,ï­ˆ0Öu Gv ²H€ƒHé•itÝ¿_=‰É| ½/† =~×fR )äY•3R¯–ž¸»e{›ÎOQ]²–™ë"ÓïÈ·\6BoKÂU·’Æ«ý~tUÛ(ªfePk§ÉDþÑž—ôµhŽÔ”zaá 5Â)µ`´¤‘¨Ï ÙgA @òÁì:€c¥l‰Ïàû1ɯ¡£êÚ-âa>Ž4ñò|`Voµ+à_Ã0²5èaoÕ;Ô¢dçèS†ñôÛ¦inúk¥æf«— óp$ Dê’alzÁ¢OSÎAI—Ÿ©Z|7 ¥&«úÖá‘ӯݔ¹ÁöÙªui¤·ŒÌ­ª5(û”-ß7z +b]x¹cx'N#ŸÍ~¾6ºbd¿4ôò”‘Âñ‰4K6%=LP£@ön.¥J9=F27«.²Þ ¯] ßè¬rƈZÒ„kQš!0òU¦ÁX£Þ =×d@Aü:bjwA=Múu½Ö%l%ëúõµ4Ôøä4Ržìÿ\Û8P €)¦kPÒ2%#á(ÓOÙÅ´¨ÂùÀ òlVŒÞÌS¶:ÙôdëÕËp«æðkP¤º, ¥A|Ú&YžýY­ŠÄD²Õ ×{éógáaÊææ¹\WÕS¾¹50>§6©º=%ÎÂQî§b†Ö°! ¥v™9«Àé¿¡±_øœµ µ/š% þõÒÌ$L‰‘mE‰˜$óé­Ÿf½xY‹jVÙbÚ§h4*žŸ?Ýi`#ð‹ØÜlMO¦%ÀÐ’ô¢vL˜f€XûÁ®É?Ï: G¹4L`Sð|šû½_‰Xµ«Ñ‹=&^; èU;â»B»ù!烔EΉËd5ªÂECoÇù”V•3ác.qÓ-" .U-ŸéÕàE½ø÷[á¨Óß·)ËÙÂæŠ9ðÇñzö>ýv©»Ô÷Ý€9-ª Z€¿ˆ©šéhâŽL0"ÆQWXv$Þ e¶¬Ü˱ïÕ™w¼êlõ5ç  „§oʆVõ€ë¨ÚfEl Ç^ŒøüS3ö<ç}Ðn¢Ü°È]æ"£·ÏŒÙ™Œ 14éçÌ3ÞRd¢W(É152ý©ÞÂrCõn%-"F®£÷VN)ÿFÈ“áá”xží ‡sƒ³rZú $Dz ÀœÐ8¾‰‘2IÐQ¯£F9€©««!1‘Ùzvú÷‰¦OP柭#À³‡ê8åpl‡2ÊÎAÞþ–¤ÑÛªª%ñ4xULnmR Ù™‡SfˆÑ.è5Î U1õÊïãdÒtzíU“5´=ÓlÛ¦ ) ø—Ó(É¢5ˆiø›RW³üÊnÿ|dJ]ÍRªQÆTå0Aä&Ãë"ɺK•`‹åŸ onU™@9T²¼˜F#¬Ä‡˜²k´I½å¦$« ææ|^[¦±ªh‡LÒ÷ßžÀ$6 ÄmÒ1Acvd^K#êÅ$nG +Á#7´‰•NÏóý·-ž3‡@ùæíÃù{Uúh¼˜*¦GvdES{¶ªFzüJúÇ?þ¡¡se¹àr•gE L)rGæ¸^U kiØN²jƒ Þ X‰Æ1¡Œ¡¼ŒqMT²†.€À7F/ÌÙQÀ”c(3ìðSÐs»}'!ù€‰œžIŸbÕ”Jø½{Cûó ÏmÛÂpd[Õ‚1ˆçH)/*%Ëd¥–ÜÄ4å.≸…uÁ¢}ß·räó:½ã”vÌh¤4BUvì¹â ð0 æO©K —+­Q‰LH‘8p‰ïGo¨ð‰Àmp«s]í,+ ü¯•Ú¶•óÑ˧‰2ž O–ÙOŠ0o{ÇÁ†ž+ÝÍÈ^¯µ“%ÀÐGb„‰ZèÐå9'ó—LAœ†p»¿—t´IÏÕ5Ùê¢qLìÀœÇº?[¦ÒYî>…v²Zrˆ'K©4SÖõÊh|cé[ØQìÞZ™•F2Ÿr›l4€,"‰§ÏÁHC¬ ãTv&ȪvXIÿêóI?eb]3‡¼è3ê©[#’IᨤÑnaØ“ÖØ¶ç`¿ãz÷¦hX ¼KÂsICœ‹cŒ#ÒÃC@ö#Ñ_Š3—»p Ñ`ZÓÌ–&½ìŽùÏßòñ!ãßJí€Ì¶‰Lø3ìȧߌý4%R>Ý‚ ¦•Æ|d&án2ÑŽá Þljïú” (»‘#²F†WŽ`èâk—‘é/˜0½c#ÊŽ‘ı•pŒëó_“æÖHI]GNc؇'Àh@ƒÒÃ|Èd¥Óüó…\âü°m(FoëÁJ) â¯$²Õ¢TÐTƘ Ÿš8§AªrÛ±S´à»Žj@ eJíñ0†•oFï0±"Û_n®F¸™{¬ï¿|gÛÛ¶|& % (ݦ3ZKkt)üvÃÌ$œ¾Y¦pX AV8Ž(ñ‘pÀËªš« °Uêµ[ÀQä@f*G˜Q IpÖ}¹!‹l»ç–P‹}¨L0¸•S\ÏÙQ©‰ŽÈöÜâ¦hkÏêÜêùû`ÊLÈÊ-àÈP©qp€& ,›¢Eµ¹È¶"k|íܰ¨W‰F¯ŒL)'£ÙÝ1Õ_ÊîŸá¥4ªÖ»+|¿”ª2'î.°éB©‹+uÄh'sD¾Ñ#ÄÓŸ?bj§oºÜu¦WâI¶ŽfµÀÞù iwæ—,·ðdùôìí°öà’Ø.ïgÓ†-OéX MU#xV”š¥Ôo|Ê€ìˆáß¹2Ÿºd˜Y˜’²WRjÙh9qXK#â§áPûŸþö·¿a…6l«kÃP³ƒ š§d@%$q¹v¼€ÉðËÙV•cVLˆëÝ8G/^晴²Ð® 샹Y@ŒZÒ˽uOFf Ü,²ŽÈS;RÖ"´d;²–ª•l‚ÄðÞ‘gÕ›f÷¢lhJžâ×›þŽnÆ¿0n+™ÃP•¥È¹l 1L#:‚ÀVb%x]dÎ!0²×ÞÐÜv̇ÈäÎ?Èö“_KËhLÖæªÞmã&ÞzÍ"íoYä4lÓüz3¤Wj À¤OdåFÀºXX´‰*Ò1Aâ^c ´ÏZ*É…ªÆö‘EGù Uma]mèéYU¥ÔØ8ŒP•1ðx>û/ sàÎ?)+¤v7Ò(ÌUBÂ)7Å1%gØ>‚Éíû’R#db¡†8Ñ/[dÊñ¦Ãø}8 {™Jµ¬À7º¡Ž] )R`À>YÕx.s7T¼&ô½ž ¾ùd+[;Y&2™–ŽÇ‘3T­y°€©•fý*ñÁ$MŸGnò &@jɹϸ×ÄÄçéªþ dx¸Å(Áõ>I˾14)·yG²V•k‘gbVGÎ/æ<1ŸŽÅ€ýÒAm½ležJªŽ•0@ã`¼)«îR»ã¦¯1 ±Y‘[¨±ªÜt2¡QU´¹=Ó;"›h!n·µt\N&SÊdÚÀDòG¾£) ð íXKÌé¿1ðñ½&e$€gËHpkWëHIƒ,Û-+؇BT"«ÄJpÆtǰÌ\du…ß§6 @ÀŠQWƒà)i&Æ·¦oQßV1 ¥xÖ(ç삳z -±@v)¤X»Ò»ƒïžb|ßÏö‡JY/8“¹å_F|Èü 4EìÊŽdÙ"÷ÍÏS)@¦ ífôüµ+@ïy|í)ñÏa`GþÃWø)‘Ú…?Ãd½[Ædb ÀøŽÝŽFlnØÑ\ؽ€°cLzj2ƒ}FGG‘9¦ÀÔ.W¢Græ¹.€~x¸§KT™¢=:öÝ ÓWš>¦£Æn‚4È]†l;Á®9ãÛ I¯ÝQ$ ÁÓÈH€³ÜòM©T#}Õëñéaz2-"[Y¨b|wázÆh‘þÝkûð©KÕQ4 Ÿ³)‘·xª}“v8M˜aÕ·yƒ([@N¦Î¶OV€®d›E†¯¤ï°ªQv”‰ãÙ&ž @vk2ÓÑÈvÃ{Fni:ª6•vÇ-4—ÜD@ÉÚ²è·*“”ÈUMÄ‹wô™úóƒ@® P*Oc®j>}+UwÙŽrnM§oóªó¬Qu/¡˜ªpƒŒÀL7=º«œ9+‚zƒt M›^v$î1sÎÈ$ÏH˜•v˜MWÒë÷@ø×5χ9ÖÈJph¬Ò` r»J¬”˜tl%ʵ`„#’†RKLš–ÁäДéëÚôU'x­fB6Nd"ãkTu„Â2M{*uÍ·±v‚™ï:™7nnç¿{Kê¬ÀNl .aj~­E WV*Ìí„9·Ê™2FUð앾»ù”7Ž•ßź#À$·ëýÇÙv¶|¼.˜ž¬kANÓ Çª2ÃwUŒhO€Þ-v/€3½Pjx#´4´F<}U½Åpex2`T•üVåÌ ™gÊþôÂdKŸ¬.¤‰ªõb"1bÎ-™²R¶9ssTUÒRÖÒªrëm¥4dý%±}"§Ì³‚i˜•`i˜,czyb;( z1ú]O )¶m Ÿ¾«zÙ’ÉÂ,½ªŽxÇJ Š<êôµ8UcÚ!^Ö.nÓÊnW Ø­ÿ4¸¹Z0²j[qØ4ªÍů…`$^¯<«0@)¾Þ41ª0žgK:ÆÈ¾™J@æƒ ËíГ˜ 6¨{©*E¦É‡ 62%e×qLÖôÄÃJ½L×tp]JŽM•29Ò»‰¼ö‰ÛðÝNÿî€éʾ™û%Æ­Æ® ÷YkÍrÇmNŒÏ‡!\;A¥”xUøüÝÜÁ}ô8á,ôÔ° ;R:RŠMÂÓ׋'hè“ȳŒQuUÇdÚ#ºälaœ£h@Cá¸ÉíÜb‘@° o= Œïk¬ ö+5ÿv»ë|©­´0áûœÎ¤Ÿ7Áà[&S’¹Žôço·£ø†òÇ“å“öǹŸ´F7 ©Ú#Ÿ÷éd;ã³¥(9+bþJŽ1޽IþHb9\Õù—-¡Ôèw#”ðe- n:xVŽM¤‡“U…'6‚'%™F‚¾raG¼L/z+¥ïogšå1MáF,§ĵ?NƒO€ì¨×Vy*‘ÑdK€Ž[£Ñôã+É™˜ø~j€ï€ß}lñù<)™ÀY]/SI¨VrLÉÖ8Y¯àÜo¨ªrAS‹ã.#u½æ[ž'¾È¤×í`JŸ>=@°Å-£}<†LÆàòA< ?žS;Ê5VŠI©¤n0f¤^ÕP-¶™Øbª {غ0UÝÚh_¼|û8ù4ÃîHÉSÔ¨—¼Æ@†ù|mQЦ¡‡¦€)úuÜ1w¤€¤ið^G Óž*OJä¶Ì*jír‹ªÚD# 4vŒ3TÂì·ì{Ïħ+;ÒÈù‡ótÌGÇ$sŒ¡] ¤¯¥J”˜ÛqžÎ¶É0ö‘ýÊ×éX9t©†ÂùàJ|ŒFæ1‰1 zïlè@c¬Ñ¸Fk‡û\x:ÊF7Ý£%“»NJ2Œ‹è…;rN#Oc¥ªlzYtTåCÉ)'À¬±’c¥xâ1o£Ë’)å¯äh%&yΤ§¤äªî¾[´RâLd-ôÌéWo82H©)•tÉ™#§—Ó”•Äp e&rdþÖSEÊð¿þõ/U_QSúq®ŠTuÙzé[¾Yµ+¢++5·ÞÕZ€Æ'[c» ¥Rúæö”ÿ?Yw³ ‰m#[x¡çM-Ë¿Oïí|äÉŒ¦KXÀÁ@ 2³ª[²ï\Q—ÿmBÇ­ Iï(`Vµ;¶†F‹€;ö±î }‡9¨’ÑW‚¢Å®Áù@•š7ñ£»ÿ¡Y®‹ÞQ`ÊuÑ‹™Ó¨bWÒNŒºuL¤^²œñmë827YU&PM )7wùó_·Výam@.ñrŒ¬UÊnrF}q#]#e#aû<ˆó¤ÏŸ ï–FìÎÝÍï¦l뢿ö'qôôËxþ}3Žú†ªõF÷©h±jÕ”Ä}Ó«døÜ‘0‡þ”‚ ü ‚²%)åõa‚í¿Ýî£o¥þö—>+bsEüZ€¶”˜Ëº„±í°c—Âp#«±û޾ô‰ã^ ™yþõÂ5FÊló‡µxœ³ô]; ’¦A% ÐD#&žŒ@8æ@ Fš¥î(W"¾MggQ;  ×âT*ûÝ—OYÌÐÒüfÅ·mKªvlb]ÈÆiļó$.ųwàCìÇ$ÃÍB ‚U¡*¾§Ï†Ü2Qâ#k¤©7=qøÿû¿ÿ³@‚”JÄé÷ÑÀµÈ0}b˜RÕ“æ6[¤èŽÄ…ª)°R퀣‰øÓpÿ¶ÄŠ!†>2Üh@UÌD eÆ·²–+ÿŒ®])å+€¾YëÚÄ9Æ[²#ÀÀ”"«|"“)ù©¡wœ&OGUëõz ûã?’NݹçÞyÄ‚cïÒC„É,7)Y-|Œ€ËZT‘@£kh]2ÞoYí7b‚~{¦çãbô9·¼cU-]äLŒd.Z#ÏH9U vÙzékg.0‚’ƒ’|Õ2”Uå1ÑwµÚ[Þp/²ëúIu©Z¦YžŽÆiWpWŽ‘ŸÀÖÐ%8§tœgÃ0íæ d™$&P5%“6!ˆ'ŽQ}ü•ÄËÃÍÅ3wœ€aÊÞ„g¥¦èJì(7B¶2s]0R!«F¦‘c´°‚i(a¸Ÿ¨¬jY;™èA€—gÕ£áÏŒ¯3M©¥#q…gí€lQM߃#16TÂ8úˆé“m™@n½Õk¥«R4Èçrç1MaÛ\UN©K8ʘÖÓèÂÃòž1†’>q Y>Žªû‘ÙÚE_f2þ™XÀr]|(HG‚ñ<›r:Ÿ/#q-ÓcÒOìå ²”irxg­q2 åk»….LOäGãÓ³Š1¥}å´+a"[£¹ï>ª¿~ðæµÎ¶!ÒcŒ¼R+ûJâl÷ý]ÐÞ‘ù(í2ø¶‘ûn‹}¢×ï|N4µÐäæŸ->Ÿ&*ÙPÜíÎ#”›E&rSÊÓÜmHìûêGö«ß1Jüëe…Çmzß{Gn‚FKý^nh½²ð›·öÆÕÕ]`³â5xbC…éHdž:Òãšå Äù|`‚p%$F\¿ó—GnÚóŽxb]µ8 õª]MaÕ”ô–!€ñ>`CÉà&ÛÍ•¦‡ó7¦Tªƒ4 ³.¥4°væ™”• ]}}ÁTç ,2Ì?Lé02OG¡Å,9,÷ÁÕ+ôÊ}«ÛÄQàêRJŒÉSUI\á¹BS\¿ï½*>s²Àsxùw |Ó̇CÕ6ºœÞC êj]HÇVҲݚîX‹F”Yż™›£ÈÁ+2»fÔ¯Ä}ã­‚/†ÑÈË·“ÒQt”)ÉðaJG‚H-xÑ‘Ì88²)µ¤‘ý¦eúÀòi7bJ²*%+dL†œMŒÏ¼¹&íïK°–Ú;²m²éýd™àîÐÇ] h †€‰2ÈYFÖÓû iZ#°‰âe-2ÀbÙ/ýYK%ÊŠö©KcÉÐQÀ‚²5ävCv€,|-?ã3—‰Ø²æÊšZȼ­ld¼c¤iºjz •É]2&Y¶ŽJB#F©® k©db¶ÄÝ%žÆ1¥Y^À1ÿr¶°ØÂ·ªa|‚F8â·X#0µ´ISú“O“ ¬D#´´Û‘”xƒ`Õ|0™TmºK!µËFˆ×6™r£yrstYzGÌ@æÈë÷ùrÖ%矞‰£,0ÇaX‹H`«ŠqÌàƒl%@(¥‘ço(Ì-Gá¸õË`´tY¹ª wÔÈÄñ²®ªœ Ðg zß« ñª0Ò8É‚`_BGæU Ó¯ê´w b]­§ pþüÎ¥‹ÒL'Zȇ‡»s^ ÛIÉßÑ`¡‘F‹j{c`‘¿jwÃ(YËÄJcè‘Ħ+ÅÔ‚I‰ç“à̸Cua„# û6d߆U1=ek(µ¡%ƒ0 j:J¿•îÀ“T•Ú¸ÝVüÔÑt²~„rx/®×Dhš ¼n«¤]XU´gk »EU¤­ú4Ê ›A @Y ±#Ü>²’LŒçl“F‚[$A½dõn(@‰lt¶¡¬©—ßæøõ¡+7‚P’‚¬F˜g½õ­*Ï&«”¡,<Ѹy™¤käÐ3®½×@pÆwAâÜ΢w=¹ª,³…z]}â¬ò OÊ_6KcËàMl:¬_W $à¬Å&JaJp·&£o"¥R&yâ#±Ñ4‹–¯DŒ§ÜkÄ´ªmUš– ÈÆ¥,gÂ/êR=& bà6ÐÎ{«.‹ÑÒ³¤_{VíéX»F¸€¹yÀFÈö‘…iôhŒðÈŽÚ1d²v¿%6ˆ;g(÷ð¬(ÙêÒ‹”Åoýë_Ä.c;…é¶´£ªœWÖ0œOšH¸pÌdJ¼-µÈ~!®Dã2JÖÝõÜAÕQU æ&0° @æJŽpº{Ä4m¢zm>Veꢌ Ø“¹ —çç¯ñX_O¹•vÕvæ)µ·g [âÌS–×È3A½uµÆ‘¾¶-F8Ò$sM ¼'jþdÂQ¶Éø]JrUîs´I%â¬Ò츪Ukä0[ââÆ½Vî%ê5n]H޲ („!€9¿J_<ŒAÍZ#>ò=æöp~À²½6GOÜÃöÈ&6e;´¹#1+Y4®‰­T‹’¼ÈªG èiÌõ‰øÓ®—@©´dí ãU%= ÓÈ̵$hPS61Œ¯Ó-ñe%æÈF 8ZCÔ»}ð‚É6g<±×°ÞFÄË)›èX cŒ@fãÛJÎ<+Ù”º”"d&1ÉÒ[ûu†ñreǺ”4Nc™µ*e>ܱo‡®€ôé÷h”ò·ÿüç?»m=ÔÈrªŽ=MxKà²ÍÖÂ9%œ›ö¬ðÂ=iä³Ê÷kÇŠÆ‘/êêÕ’a¥”•Žú ?L)×Õ,Ù¬y:jH2³²†lÛ”Ø}Ðg˜[oX‰L¼>¬87‹^‰cŠŸ±Þîc«¯‹²…á~€U[@ŠÖð—øõÃìhJˉ»ÅJMœ, š›#,Ú°•Pm@ Suy&?ªž”s£•ÒïÁ7”mûÈ¢[·G-Èi9Ð`Ú¶¹ r«±èFÎV&Z6È‘ «ôµkTê)ÒÇ ôª"‡ºš%”þ†¤hºï†RǾ$ŽÛÆQn"žÞ¬&âSjzb%Aæh! n¼§öÅ2IŸ,«U)1€A•t¢Ñºf«–‡Ë<ñ2¬ZcÕºà–¯’FÔ’òÍ•ê-7&kkp™„k¡G»”ËΡ|†åZö&õ";vµ¦¯+ Ÿœ‚5"ÈE¤}èÛDÉ'bPŸ¿V7¾Í°t²Ï¸Ëà á4pÃÈ1”ŽaJU€¯©ÁBIÐ5UEz|ÇÙ:"מ?q Ò¾m‘ÄJyr°FÎí€É¿k"9¬+¬KPÆz3#Ûa£7¨%e&ºjÙß”ã[†Œ§·¢!F¶U øPfâMIS—#ÒoŠöi¢ÆdÛ!¤AbËPj郆…™<%lŸze{‡äé(Œ&@v¼ûJLÆ-¹Q{X£j·ƒÉdÁJV"ÎÇÎ9Ï@d•X=RÔ¤¬$;æ¯4e†1 {U%Ðnm¹vX´ƒ[£’ÞdÜZƒÃ„n GÀKÒgÌ%y¦ä©¤×Q)³¡˜ªlfG:–‰û垟ù ›.÷.⿜óÿã9ýh7þ}Xõª²ÈЉÙGÁ¡[´*&çv»NÇ!¯d[Ëçit¥njOí˜îåwqŒXµÑ<1üµ7…^#¥c½0@€Oïè =#†“µäÐ>Lú,È0dª­¯±*ÉE¢…¬Œ×[ÞYI´3ÿžñLÿý÷ßœ›Š¸#Žy¾_»®­Ô7PF¶JJ¤’01æjÜ)‘Ça-pæ½Áuúü~ÑâH@4 fâXK‚LàF¤DRÊø¬äÊÔâóÓˆ”á¶Rp%xn˜HUÁ¶7çLæXµöª²#ÀGq#´È-O)׫úçUÁùîòIô¹5e¶@¶ZúæHϼFÇù,÷¿AַŰ9P¶ÛÂG•Ò±ïàH³=7îµ?ýWÙÇgU—A&>7™¾Gh ’8A-ªV:cl…–Ž”âˆ¾ßóvp¤~wcLÑE °1² S%#¸M'¥§ôeÿk×eÜÍ".0Žr>”øŽxñgY&F—{AŒÑ~ÇáÍê/¶[@Kk×™§ÜÍ%kàõá Ð’8FvŒÑÛ•{½a)sf¼Ó9Ð#É€Ù²ŠìÿªDn½¹»'&hæg‹á™CG9¦¬%óxâz‘Û¡F< €¢Md¤Lç#Ï®%¼M”Zs~ƒøöˆ¨ý¿iÊ=ëH—@^øºú|äQøìæªa$7XÜ®9ãE]ÙªúVÁ¢j]ÚOG¡jX~=i2¤'s$¨— ŽúÌbòQÊJ©U1gðó³ÁS)ÀqL‹5}ƒfE†tlÖ°#ÿòº´Äl OÀ­¼à˜r«j߬X;½ Ä´Žr&ø¶Õ8^ßGn™©‹~†°¸òÏï;Û,/€ÆnTU‹*&,h„¹€ôUü!hnžJZŽÅý«Æ¥ªZü^“jìg@¶Iü|"sSÂói.ÒEúbÃÞç9ºÀèõt4ް*0ŒA]|ú~æ¯ÄÁ @ÖÕÎe>É€ý„b|0î ÚÙæƒÉ­N“§öÝ%Ÿ¦6 Ìéx m•2w¯®ÃI`ñþPÁWRMPÎGv4nïƒÑ-¶™À$ÓN¦ê}ü‘̇ÆJ˜°#H´^n½ÌU1™88ªÖH© #à® ˆH&‘ã­€p œ  ‘5vSU%< rN,GÒ'Æ|þP:™]¢IÝÖ®ñ2\É~½‚côX C‹Žœ»<ó– U;­k€§AŽ>í] ÎŽrí­ôᆶ€#‡îßPíu‘áÙ‘ľ…ô¾}ø“忏ˆhPÓU…^þ"™)«"á™WrdÕ2ª®oGÁ­ëhŒñPwÈçw¨^|Ô[ ¹[¨âóD¶ uTª pÄ;¦9êÿýªTi·›f eú:{Y0¦p tYs»T¤*Ü­—ï^1ž¬Ì÷ì°*CbdSʬT9¨Êp›ÀJñz‰ñÍr|ïâH¦Do.ðF+ah„#™YSöÇŒ’Ñ"=@ÖªéµôQæ`è•~¸h®ýIö¤ñÍÑn.LiŠ£*bí­Ôª]G&¦YU—£öðH½r£ €ÜEG¹‰HX¯HÜ Äg#TUX1á|0íFƒðí8lJk ià€ c hä`°FL|íó VdLÚ¹“ ªÜ¸¨±8e&+µƒ¡BÉQ¯‘Ʊޘô}ÊËT­×1ÁoûÛßúÈÙ ŒÿÜ #1=MkaTE¦ÄµT}WÙ µÕH,”8héØŠm–,Ÿ)‰eU¤^†Ó$sJ9ÿVeŽi&’IáÈ™À±‹+?¶~ðšÞ2a¼#½Ü‡1Ža¤öÜZ^Õ±G]nI>ML¶.|3L¬9C%|¶xѽfÒŸFny]b2>97k†€ÈVÖÛuÈ U$ K…Uúž£ˆè)û©óÎ9·OTܾ3zþùTÍG^4¢_H]nª…¾FSh”Ê@bJ‘RKUb$M½x>ÈÇQµUÃ~ëò׺šŽ÷k®jÉsË8ŠàßGâý™};˜Øª²@jI&p/ž–!pd%spÌ#0UzX&P¢ Ëp‚Á¢‰i•RÊ‚ƒÜ7z Ä4kCõ) ì™ ‡L…j³|2úº”º ’@ŠŽaŸU¥¬h³ŠI&$‡œsh‡xÙ‘8éÈùGÎϤÜ×)‚º2Jß4¡‘¦>¿ò¢HRÏE'¬-æÓæð}#dß¿ Võ á[Ñý§o-¥ª <¦uÛAobdÛ3ÁXÆQUcñ€‰È±o¡cÓ5~G.³j“Õ>žø³è½H˜c‹Éd=޼Þ~Ôûà™û‡nù} zž‹ÖC²­„iÄ{qƒ¶<@Ùõ[ƒ¾R-ª-ƒ7hxƒèû»‰.Rµé“¦HÐè&ŽgN™ w䟉–]¼’cP•[2}‚ÌFõ䓨ÕsÓÓp–öD98Š0¾ù¯7áÖa4‰ §i:L ¿¿Ù+ᑲ¯A[ÙÄÑ,z> ó·mCHÕLôr¼v‘->™§P‚ù˜¥J#™¨: VpVåzÉ4 G²98n‡Ä2‡r¶f]½ÉdzØX—A€¿hÄçƒ$+-œ’Fh‘ñ`x+§$º5I%™[dƒzó‰OçmÑ%`΢v wUíí95v â4¯²é,šRF¶óÈVš8ƒ¼!’'Až²®”;»v®Pg×ë¯`0 ¯.F\µ a vd}f=½*CA¯è F]ªïŒc¤lP;”çæ¯0}EÌR2W¦çÙ#ÂJôdÌUñªy¡…ùû:4B—ª’h±Ä•ÚYF2×NO)ûßB0'S•‘FËfÑ Y)‡Ë7¤)êÝòHSdé H2&¢­êuÄx,׫V¢™¤ï­”ªäô͵•€»2 ºÑÈfaº/†9ÇþåÅ0¡‘[nª•'°=[¯}¦ï.dù¨N–mG/¦Ô§Ï°…-Ó‡CÙ¶¬=‡ •ä!á“a½Ý¥‹Ã‚¸#}¶­Q—O²š'FKb™Uv`H†Á»¬$€ð i8ËH¡ËqX—ëG† bxdí=^•­#co‚옘 –µôG¡+eã"1tä"œ8s¼5Žú†’ÿ¬ÑûÀîëØàî¢7Ãn”C/§Ó)™¨Ö˜éH_ \{¶µÔÕo{ëaf²ö@ Ì wÜnÓkÙVUOá•`¼›žŸ>ÝëüÉ @Š‚)’vÌI Ï‚#s¯=¥ì»•XŽÌÓ±;T%à d³‚1õÊ‘|¬ë(`»nÒ$ªºÄ&vä_K`GÕñÃmÎA‰? ¤1¦˜ØÃ!?KÜÿ¶AfamÕÆá‰™§×D–U‹àø™¸O±}T Þ4QVÊ¿ö0YÇz7«SÈ"UÛm ãF2¥a%JA–žýnr$Ë“€ÒQU#áe@K›Ä‡ Ú@{Vlñô’!,·*=Rð™IU@¨fÓh÷é´9ͤè)ÍÕë+w|¯£d–. 1M£ñÈ®£côÊ ÂJùo±3”ñL½Ü®¤Ý­‡µ‹&*‘96½]™à ÏòÚSF’ d[5‡dï/eWÖÛãSæþ²Y”²£*g$ÀŽiüÞ0Ÿzñ²Â‡æ@Ì€ :§Q ÔEà^zSâ7n 7XÔ®ñ³êF]--m"Ç3o/“9öŒ­Z5e²&ÂU!‹m˜U7Š'nŠ^Ñ&¿ýóŸÿ$΂–©p“aG –i€°LpOÇ3²Ç>$Ù*Šœ9ðêaAÓÝÊÜüËÙô½Ýô×Ìkv’.nÙ¶¡c+éê›ä¸))ÛS;1‡fÕ.· HŸŒ!RÔ(Ù+¥á©ªWäïkA€t¤¡WJÜ”ô²à@heÑbrþ-“&ïFÆS0¯¦izŒv qö»Ê9@–é™ÁD `4†¦ a%ÇdZRjômÎ\IÐ;Êp<¬‘l-˜³åý¥`ϺíˆÞA#¤Ô7C Ð+LôG…#ÀdEœ p…ŸODuæ#ze¥€Òdµ4Ô8‚&t4:&Û²’ÀË5Zfæi0ªÓa-ŽÍ;ªóiž¥¿¡ f"ë#á‘5bÚ¼R†,Ë雋¤¬¨QnçaŸE›”óìÊó'îÊÚ…£0H{ƒÒ+5èÖ)Û›R»<+-ªgÌ Gÿ™Œ&Ã4ì^@IDATfÍI€ ¿ía¹ö÷Hï˜3 ·ØE¶úíßÿþwÍD[XMßo ‚ØGÅB4ÆÆøô‘J@♟æ{Ûñ2†Jp®}˨*á1iA Wííæ“F—*€y¦iÐ0 Ê³«uì{ ·F CJ_µö×bº¼•(á iTEíx–i’io·˜î+ ½ªaÀ/k`J |‡œ?cø;já_n^“ çôù§ï#VM ˆd¯q¦(•s&ÐÎ_UÉÞê¸|Å]ª˜¦ôÇC|z¬æFæ«ønÛ52'n4@)(™—ý‘³•™$ LŽÉt!M"óä¯ Ç¯Io„’.Ùb2RµIL½lµ4nâ€L 4O>)s“S’Ý!¿¾rJ–uås[õ&¦…ÆgÇÞ6ÜDLdVuÁ}X·=Fâ”@>r]ù'†'†‹Ãí ï"-Ù²£h7`‹Ù§#†¹ÁæÊŽò鼟”vŒeµW©«MðH]d1rQ &ÐRï·øK£Ô5é'³O|s3É0Y×Ì%>5”š…øl庪þö÷¿ÿý‡ ©†-Z[škõù‰mªI½Q¥&éí!Aà8O†Â/ø”› +Ñ÷…pLŒ¼}çab < ú ¢ZŒŸg-Ì‘3Ð_©&Mùz|¾I³ÒÞã¦TBŠZº) AÃ4JH jXÆó×ePS\m+aúƒgdzitqÃ0 sÆ§É Ÿ&^îO#L¬±W}òÏèçD2•j§TªŠï•"ËZâYY‰R#Ÿâ]“ ’r†¬b”Î*÷Øa2ùÇJõ"9T#ܱ§ày¼®Ù±=s€µÀÆ©¶?MU‘ŽdŽô˜2Ÿøvà飯7\5lǪ¬…•FÇ~[Š!ëRÄÇúû[ï¸ï¢D&z«ðònçc3e|ãÈÇ\9 ¼_2¼Æ^£ç²dÓ3×ÞSX¸·ò#a±ºˆ–'†ûóƒRIèêý7¥G±û¶¹£Ð.\–€æƒwäãhD{æ#kïR0e²em…¡t<î·Â‘•¬QPÖh ¹¿^ÃÔ¬­`öé̇U³˜ MÔÎÇQ¨ÊûÍB0q£)é#ù`³’[©JÓF¸W¤€i2ÁèmPŒªFíŽÀi‘1IJ£%1»#2g ܽˆÉúã°'j±ôùln#ÈxÝ Î¿q ÇÈ¢õš¥Cùš;о¥ ûìȈõŠ®“!=%˜&±ªˆ«:Ê;6ÃVãJY‘a˜o(Ð7œ M·~0ÂQc£óló#Ș˜‚weÙ™Ì,°Ü&ÀùêsÌzŽÝ P©êŒ¼i3wÌÐÈëýy -¢-Û†¡¨½Û„Ò7I5¦ÜÙn7$11Œ‡«Æ8öÁ§1ˆC]òöi ŒÐžCdz÷ó‹©Ò•|ÞÇ Ž2Ì ègháY ”àwó˜ 4Ú<ó¾(J6!sŒÙkìÖ@¶Ë½C7… ØÞ;«˜.˜ ² ›Ò û„5ÂÍÂXì.@XNÙ1e×Áäs|¯³‰}Èj$ýÃhú¦¤—÷ ªºˆ‘0Y@®e—¢¡tLïÖüÔ#09ø_pã3ø ŸB&d¦O8e?–}d¥Ü«šÒ âôŽª—>¯júnQÎáÊ?ßäöLœ&«4ôMçÉ-§NÏ@Æ×Ûz½ ´tå)·jvSºàzg˜æÎ9)ÛH>yj1Æû#¹%{|LkH2æ4°ÆöUé³è4Ü”“eÅÓzyŠ•ðŽi"Û“CU8¯«Ð"l¥*à–l…7Þ24Y%îe0¹1è×÷µ*Ù:v×Ñbb@I—v¤€ÏÏX÷ùì{_¶r“†gÇÆ´„#ÌhvúJpO[Y/0#R4ˆOUYìJ)e/a7 3éÂx \³=#»‚†X»˜­Ýª’Ñ»ŽwËY¡…Æ—ŒOoÛ5iÚ¡LÙ U·€”¬ÛD FV2îJN"¨4† –5¶ƒédýJ副*ïÐv“‘¢ü¯N)íŒÉàS5¼êy‘{_J¹µ¢­º—^Õ¾!F4WæP—µummGÕ6‘1²  kdNæ˜1µ;*u…¹5·‹À<ÉvGJí1@S"«ÂZ\§Æ™ÂÅ»™^£ÑµôÇO¥­ÚËSò$07JD0Žkߪ˜ZT‘¬ÒìS‹©=+Œ ·1¥FØ2x˜¬òÇ$ÐH©]´ ^ð¢Y­ç)nÇIç’ßk¦‘ d£û7Ï dæJoF¦”1@&€Ð"7º#†¬#U@¶ü~ód"‹Ú½}dô€œE–¹A¬ñ +5vA˜g;´=R»ã‚¦v Ò½‹œÿ¨BÍÚŒ`Òb¼0ÛÃ*ïH%]˜u²•ùdÞ$+âªñÞ(ÐsÀ4=\ƒd «¢ãpÝ\$ÃLhrè‚n®ŠaN8ÂYaV¥oÊñ½%“!ýePU`E¥ziú¢Ô¥Ú&Ž›ÛV²Q)sÙ±•|±\Ü wÎy+x_#€XK]2eO§cnýó)(5ùîF\o˧ÉAö3n´?ä´ÛÄnL”Ú0F‰IYÖB´vX.šHóþ ®¥v™²¶†\;ÞDGhiÖºð˜ÍÚb˜.B0 ˆ˜0Mkx%¡TÕ\¶J¢ŒR{Ú¤O$šÛwª·ã×·±=8y“ ²Õ˜yÇaÊ<™ [Ø)rû;Z)Ï”íÆM©LÐcöé÷åÙz^ Û.¨«0EɃ8Ö¢—²ÄJ¢ß›Yž (ßÅÚ'Aþª¯W6NÀH²xSÒ˜¢ &Èd³ák›X5Ù{\;ÒD#0Ú)+Éx“-ŸÄX„×2±R¶Ê…Ax¡‘mG¥}+`¤v  –­·q”|ÎcQxY …‹\`¤ðqv<ÞT¯üó:2Ä”«ÂôhQ8«ÉÎàïï¥Äl í ”sm˜? ì{Ö8¶Hú¾»‘‰å<‘¢—!n-ª¢^V°jUÙúT0-FÆA‰¸7TÒ…'ÈSé=nœF|b·àƒiœ)0>YJÇ<‘ýÐú+C‚6o«p½ªZðý+ŽÖSb((Å4ªÜuz%™˜‰È6Þ‘¹@Š0Ã=~nŽ-ÙtXcs1ÆÁ¡ܘñI@¶ ~ÇMGÖ¾FG#tݱç“R*ç9G/œó̽îÞ/âüöyeÓîs¬¤7CÛ|!PÒU£\ ¨Ë,VæúÄa¤PEÚc«FgŽaøÊʪ”°P…9$cÈJ¦aÅfIs›>IW㜵tÙrª°Yý„â9 úZà¾öL(µ÷wü”mwzxL˜&Î “¿^q|ŒÆnähô¬ðÂQ•^L†¯—íUý’µªl“F'ž¬·Ú@ ùwAJLúÈxšd3lVÕkóùUœC̹T mß5Ôº@"ïò È·®>¶x9¥ljß6ž[ ÀS& áE]­%Ó„û÷tÄ)a펾Uãé…‰ `†-FÓ”FÈz×è(ß´wd¨êX Y£Çÿø6Sº5™’hׯ1Ÿ3ò^œsÑûÐchˆÓÀ UÎr¤eD›mÊ­œ[Wí·€®Æ…– ›Å™2÷KÄ&ßÖÏoHY¥m ™h‡â4ng´qÍUí¹2qÄ7=e‘ªvæãÈDÎnÊÀöa«äØ«æŸ,àr½Ž<'ƒÓ”Ý¥}¶3vª”ŽøÝŸaßd”iˆóï¨ëe2LŒ·aVG¹3´Àôk×,Œ£ „åH-Žåݱö妴ŒL¦]ŽyWu¥ôÆíîð_ûIÓˆ9×¾F¼.™Xw”Ã˵äƒ0ÂñŒç•Œ$ó‹%ÌðN8úÌcæ¶\Ð÷Y£0"[²<sˆ¯KµgTa½JÝ÷ÏJ@ 4wàù>øàà/Z²Y2‡Èl1€lÝ%²•¸iÁø÷]0† An›XcþpGULS€..·-ž ±* $ ‚[¾–'ÁFxö^#RNœ d Tåob“œ¾­Ú$}ÿš-Þ¬UµàõâkwT…ëuô/º õš¢Dcm›4Ÿ'½Þ9à‰‘dU] 88ª’!hö4p·†Ä~×ÃB—¬%Ø<[]nDC‰wY q/Éç¸ß%3!sÌßPbV¶tTÂŒÇ]¼#Þ ‚”Ù€ð2n2%&7LU ,§ÙÞÊIe΢µÛéXÞ¸&ƨŠ€Ãùƒ”eýY´Y%î[4€!Su¼{¬.ÉÊÑ ‘Ð’?èSŸRï;‚À‘2AÙ1æýT8W¥ßǬ)f‚y•|”6ô5Þ9çe¦ÇeÞ‘ 8îßO(Ÿ½R%†ùÌèAÞ)õR*Á€ŸäW[Vx/l³-ªÌ¿$€ïWƒ^ïiÿ¿üå/a&d0P®1²ÅäFÈÚû—’°ßhµïñÓ[ŒŒ OCw¬Kv‘Þ³{QÖEðg8&1}íÄøîÈ ›ÅÁ¿>ÞP|Î5Ê•ôŠª& G%LÉÍ,€‰LÓ,Ç–èÛ'e&ÝËþŽU1‚˜3€- ·~x-J¤'há¾ ?ÈÚ-ƒ'k=cª2,ø7‹ Ï(sεk-ª5êR ³UÅærÀ§4È·Ó>4@ÓÓÀFxËèÊ6 ž3²ì‰¶RͧMÎøçSæój¡OÙP)÷’µ7ÅU6:¶,ºBIf+«önÀÜðÖ ëjJÄL”äJ¡,Æ×èŽ@-Lì ÂÝu©¶I½[8.)“&0¶aÊ…—HG|z¿蹟!·Wµ’ÜÈzµ $±–¬´x˜†'¾öHúJ³ÐH¯$2,'¨T2ƒ|gßE­$ˆ•DG¥ Ê'vËøRÖ…w„׫ñ¼Ô÷yUu‰€œY©åYÕÅ Æû.œ¿cbÇZÒ#ûê‚^ o·ñ†ÐÏÀûb4ÅÑ3¶­%…ÒîÞ—¯ÑJ€jS®ö0»]VAã5ºE³¤qþ”}K‘ý z}²Ü®ÓY^¨ê™•0€.ƒàhÜæV•‰‘sVrÇ~ti™g¶}¬J&¢vGa“îÅ\Éžü1‘ï Hþm¥¤WWY£ q´Y†ë2K‹Œç“lŠÆU¹ÙǬʪÚP×Ùò®d(& ”idу wq%½]¤åÉÚ%¯÷»j³äzÏÔûòŽB»Œ!€[•sWh™ ™Rïƒp%íz…U}¦ñxá(;ÃîÖua4fH¹q§ù6 Ãò±¸ß&½C ÌRnávhmJM)§!v”ÉhxrË$ÃÄ™hqTuüí_ÿúWƒ×`äù² NÀ7¯ú)WêÓÒEI&`¦ìøVÃJUS2"­‘FÉ훪 ³­dy¡·›ßŽs]/S».< }™’¬jÓ+Áý89ªz8 ½ (³­[Ó•D%¯§ŠLðVx ™qF`:Ê6N F£e¥>8zÕwvÖ(‰ZFjg%0á+?ûoÙ2a¥dòd€ÒdJ9×› AµàkG²ª]î<Û•fØwð,úpkO½uåÙè-C  Ù>~íù0—É”(Óc GJVÏk¢£ÀÃZDŒÌ$åºY¥O‹ø>гRb‚!0î'%†F‹¿¦8^›³FCý©é:ªe&j²%ö,}O¼pšQŠZˆ)˲ŽùÀµÈ‚¬Í­Ô¬þýOX¯HÖWÚ1»Å4Ù2ú³YûÝî×o§dÚ“QvqG¶½˜)ÀM$k„¬Wªµ«ÂâÝ/ö ÂPÂa¸^U M˜ òA¦ïkÐrí@ãÈ"[â_ÿL‡uŽfô7Y˜BP×Ðϼ â{…n×6O0“ºã:”ø­q¯‰o.¾ éu9f–«¡ù±ª’0NÖÎ\Ütb-"畺ˆªÑž{ï@I£Š×Rãîå_£)Ž5]uãð<ûߺÁ•fتH@ÎAU´‰Ý®°Ÿa2U¤ÛcЉ~4Ä#õ¶˜ªKiiÛ–<î×ßêwÄ^Ic[ÉÚ·’c†¬=À3¥ÜyfKX†R)g žØ‘9pÔ÷º‚ªè/û€F™ØtVr2X{W È몑3æ½ü–T›ž’9AWÛ•zŸã~¯q ß1÷ÒàRÕz·~pAƒÉ&ȳï#ëY71“ÆÙ“Æ#`*mA;à#ÖÅuõÊUß%½º’¹)Jdm;Ô{L¯[LGHÆGøýÓ?ãòäÖ-6¨]îSÆ™œ‘÷°‰j³0);2ï` ß«îkéF?|”" ¬ÝE2”UµÛPô8˜4ÍÕ‹¡ì˜yš&bè}.Þ™8}+%–E ÞdH€‰–ß¡xÎv>ߌ"#Ã’²Ó`oG‚Œ²ÀñH]¼ûðˆáWs&ÝÿÌËÒð×åiì‘RÀªnå˜IŸ²íSb”4<9gÛ¬–ɵctÉ5ÂJŽ Ç­›ÂPD’ÁëÚÄ–ÏdíÈÚÝÆ3a娲ÀçÜP9²–Þ÷Ô[)‡y"•2ñ ݪú~7:Ù|Œ†Ë”4ý2Ô‹dÌU¡„—»f¶ŽJÜÂÚ0Û”ù°mç;á¼¼.2¹ÑpnÝ”€2[¹º)¾ªÞÞÙ±édªøFç£$*1$5JÄ¢×ð ‰ë%K³M怎IJ}b:jç,'Pr„1°YsŒÐbÇ4¬à 1õ:Ú-sUÕ2V|‘¿ª%ùG §Ôaâ &-i¨hDnµ`•Ȉ‘z­Ôt¿ú}ˆþ ¨Ú]Q—ªñÑâ:HQ/PWúdÆ9æo–¸¡Ä­Ý’d‚¿Ì®÷ç› ”¬®?c‚™Óˆ3‘•M§o>#ʶ¥Á[£kª*¥i:± ÁçY¦I ïâ0áj;‡þOAhƒI…šœÚÆJìd“äx“`LJVpGVidrLʳþ÷{@—ËÈL”ŽË79. ÷•" ô›UY›ë5è½ÈYèΕéU‹LÊùóql;Yc]iðÂo[Ù¤ÐÂÓ;`ìàw <²c[•ÏN7ª~Oç}´Ü!g“܌ظJû™¡Lz¨Ìi)åÚc–Q)½ã€}ný8®€$pìRí‰d22‡2’I%L]Ž"+¤^¸O­\d&°.|½Ä=rG¬à|®ñù x@Wk`rýجªÔVÞ¶‰=>+G2|ÇÖÈöÕ×!ÐR&hál㳪¦Ü™Ó8ö”¢[kUZdÌ"O]݈àÕÕ0oûñý~©”`†îÓSî%«"+ɪ¢YŽUðé1@£$ê2Þ¶pÇ€Ì-C-S£Å|:[iÔ^Ô¨%¾ý·˜ª–ѳ’1¨šè ª4b#:¦œ SU׎ù´9ÒpGžV­·eÂ{íÜ\vŒKé­ùëb¾]UòƺFkåµ ¼^Y8 š–pTÅ_ÕIVaÞ8ÕM„‘GÒ‡hüAÝM,Ϲ»ùmëË»ˆ^ÇÙfB eí«vhUX$`Òž‘ñÈ™Ñ;Õ"›ÒßÓÛPàõÒ @0DÊÖÖØ,b¥ UýåhÔK_5½5êê²ÍPÆËžNôlõ ŒR;²úrŸŸ.G-x±¹3a.jaЈøZˆRƘ~¼¾—¢Ô訚ÏQ±ªF¼ýÃŽíß_}í3׸;ævGs€²ÏE£®N€¤¡lIúº(3”‰·Ü&UázMQsnd2Li®¡pÓ)3 LOÓt|‘ƒ.G¥<û+v¤œmÎ4;†å€5úÉbÅÖƒsƒ»ˆv$œM`[Ûq;S¶OÎñ”#1ôJ†â,ñýý‹ï«nU-rŸ>¬‘,þv|°Ǿ -™¿ééË&òäãH#Ç€Þ®àŸòH è•䬀¢Ý”2ß2ùO@Ï £$:ʘ0%|f¿ÉT30öŸØÕ½þí?þPFµ}=e" H 7,Çùá7&Rc¥ŽJ{qL·ÅÔ8eüwøùÏ÷«ÖÞˆÖ3ÂuèEÈLèMÓVãk‘)kQ8$ê’ñ?rÓkQµ!FÆPò´&s{Öž ¯J)U`_U†œôã‘mþJZ¸»f"ëè™È¢¹•€dF«ÆðÀFDf[&PÅÌE·è8ÿÜÞ%k$ñ4-¨ó”ý<û•ÔûÀ@šzýö̤öx-€xgµ§wN`‚}"H-eÕ?Ø5TÆÓà‹87¸#¬”•'Òø–Ú‡ SóÌ9Ó;¬Ýô>MíÉä¾?‰eŒDn™¸& ô6H&›‚¬±Üˆ“íhzuuÎ0^£P•ÓÏy¾ª’€eéžEo4ì&h| q™ÄÀ–Â1&ž°›5”„ÒZñyVMœƒj%€~ΫֲöŽ&¦”Es&ö‰ÜʯÇÞMö ï§àó=‰‚¬ÐçÍËÔ4_G)|{èÒ4£;ÃÜðd2’É¿cÛ>&qíM7¨ LØös^o?ÿ°*ÏV„^™8™Œ`#´ø ¯JÙ _ÿô¦ëšObú….˜&&G R¯àÌP;2¾Yu¥‘uÉHJ£Ç õ×7xš¬ÃyÿM>d ™Mâe¥á÷Ê•´vX靈²¡–nOUÑæ½p_ä®?Ãl9çÀP©Ýèá¶UíˆÉ3½ã~cÌ5îÝÙS(É 'à Eë SLHhG†ez”Ýôj?_BŒ)B•FÉ7_KX¨2)ÓзaÏåHÖ8†JGQIÖÅ¡^@c%b½œ+õbU2­v¡”O])eJUÓù0g ‰µã‘Ž9׈!Ž/èH™ƒ.Ê0+UºŠéÍu‹ 4’9n´erhô)³uj‡)s†3¤G÷ý:*EÊôJ=È”[¯‚mnø•ºï5þ|@dŽíh)¦é˜CäF3ìI{²L”D¶>n-¶ÍDnÓøûï¿gÑó©iË"/¹»6%‚6Ò0‚+yûuÔÞrF(ìÚÏ÷+÷ÅÍÇ‘¸M4:Ö(דa$¦õx U*(m‚ß’ôȱ)u54Ÿñàü „.G %¦g4(¯ЋYÁHÁAôö!P²LïÖŸùdH †¹ˆ¬]žÆ3Òp`µàÜ÷€ɧ÷iVí2Y£ñ4”lÍ0õ&®4ž¸^   `ç‹êe˜'>¦µ³rÀMU…^%ä½ýç—]½ÙÂæªÚAÍ’_‡¦[0Hn  åÎüõU7¢)ôöœr èê¡0pz #°+(Ý¥ÎVÝŽÓ&Û?½Ük(éu¤Ì$ Œ!Ø2æ˜îåHé(§QÕâ(ð‚F´§#™c9Ÿæ:*ìVU‹Þøcˆ$Óg˜[³2߬LêBv”·@ 7L]³r–‘-wôhÄá(`ªjùÈ"ÿdŽZ^Ì0Ï+ÿ´´ŒÞ‚ŒƒûÊ?Ú xŠZ„cn-Fãh ^ûª°HI3 ЈS¾¾ÜqȰº^C-ðù/ÎáF¾ŽÈ0©6ÅçRnu‹®‹¬Īp>ŽsÃð×¥š§Œ\c|¯¬«YS²d„«®‘Fh¬—†@Õzp2¹ÞîNY‹œCsŒîŸRú·XÓ„3ï/=Ñr_ˆ #5¦4(+UX¼M¿\üÏ:Éx&À_íçóÌGî÷iâm ÔkPJÇ–´ùHw¬Å\˜U¯D@¬È5t5ÇÖÆ´L†ø†FÊHæøÝ‚XûB©ÍBÙ2M棅%¬Q&.7º’SÖëØ8 M]o5s|Äa¹‰Äpž@> Õ+ÚÈ–O‘øJ>?±Ó(yÉdH@N/'“M©nôxÊž” ­úÊÂL{6‚^ðql‡ŽaŸ¥/‰ždAUŒ/'^$%F¦I†šX;FäÓx`Îôa<¥cUdCe%—ñ"l4ŒL1²à¦Ê¶F][XUÔÒаÆà·†ÃÛ•¡ºT»oÓå·1g2 ú@†ëEÂÈws]ô¾<X ­pøü5JÁAf P ê×±j{”¹'Óu;~ý‹Gdí~`˜çß•4¶J> •“ ó¹­Ÿ·ƒ1=A¶Sê…¾k¿ JS{U¸eA‰Gök´Y¸”’A”õz±J‘-SÉÎ~Ùñä¦ )2é‚/óÑÎGÖ…ÑÕÿ6NIK ò %-²*`O˜`&@í@1%½ÝúÿùÝbUã;fØ}uõ)È »Ü·ì·™^2ž›…„…m«Vòÿ é˜óþöׂ7«53‚Ìþ•ö¶mµ ª ²ÚUc:fˆáÉMŽo"ú¶Åç9ÏÅÖÜÌÛŠ†’†æ€ng‚ÈMY/™^5¶aX&ÞÂÛ¯Åшl1Ý%O$ çØ¿®HÍ­«ˆÀmÒÇ'Ó¢Ô,zV…o1ª°RÀè^#€ì)Z©#Ϫr½˜E>2&ÜE`Vòz z½.RIÕ1¦Ññ2ý®7Þ’ÚaíHÔÞ›z"ÇöIIæx:¿w ×gB#à"~»Y`S€–¡ÄÓ`Ú³Rã²m2qþL¹sº2†TOG—qd do ÒÛn0Ù@7Ù²œñµÄ¤OÖ5Èêek´ß_2‚ Õ3x‘c`@#C$ è㑎¯€Æã$X©Y‰óÑÞñØ}¿”V2=Ÿ~rËÓ4]^oL%X(É1ý,µ'†³Â>/ðÆ  %<dV€®íІí¦E©ÆœcVr½Sâ€!ÀôwCJioÉ6QmXnœ£ëØÐk§Áó…^-òPÕt=‚ ‹;äÓRW|wÉ-YW3 È0·n=ïv•T]Ù¹ »B¯„d¥K6ˆ¬œaËÀ‚€§ )º¾ÒÄŽéeJG³Düñº|íåÈ2ò;ä¼­Þ×q$HºíæØþôŽò‘~÷q›b„cžÄs@:&kÿœç“3AÕ”µxj†)ã¹9¶­Ý’a„RU-ô‘cŽ!hŠR†Žu‹û5ˆ—ùËéõ-×Ré%ék7Tôsá¯5p/Ùûp¸õó,4¶õã ‰³Ý ‹Qn4¦cVŽÈVˆ6éFŽ¿Æ½^™ªQôš¶Ñ‰Ù f]ÞO©œ¦Lb“É¢‹¥‘Èž€ã¨Ý¬få÷¨îeµhì;ûÙ£¹ÕÓoMwÉ­5òqëJ€ðpÛ§+l¦‡¡gðHþ2RY92шÑ"w宀!Ë*MÓãáö$n#Z’€^TêCñ­±ÛYf>`%­d[Gdwá &Ð+Ñ31šÞß‹1d0P¨2Aò„ëh0»Á­ñb$YÊªÉØ¶‰£päÉG&ÃÔ‚ŒVò\ª/OIPûF˜Ž¤/ײÍÝT—,üK|[iº0‘lëm‡VÊ“R©Úºzüô²JôŽH¡©$p|0Ä2†¹c7ÚWC¹µ)ß—1HIq0´[ÀJþüëÏiG2Ce2q¶|~½dkF8e÷¥(íFw>œk¯«#~ƒ¶-¦Þö1Ž R çÌáíàÑ“ < LiPnx8’Xãô ,ØQc¦J' ½™Àý­‚^—ÈM^ qdF~h*(9Ö¸û~~ P·ýóçlL¡*¬âðÊÅÑ%³®$Wõ^¹mQ<‡ÞQÉ‘È;¾Àn}œ=‡ÒÖk\>rzs ¶–™èJ5Zhe< ˜(ù´ÂûDñŽ9Ž®­e¾5ð>Qm`dV¹)që‹B  ÐÈ…’¨4ÐkhGØ ÇÄ íª¢ß€ eûôPü12’ó~G 9ãe<1¦_H›c|Ðlg˜Ø”ÈÚa¤hzÎ2ÍöaËîh@PpîI‘ùl#Èðº`L˜•bΖQªŠQ: yKVÚWòyùf%`Òt‚aäöQòt>‚ÜZ㌿ñd¢wÈU‚@Ü‘2,»,bÙnM—Ù" ºœ3>M] RŽÉ/+!㪚5«é[Œ¿jãÖ[»#¾^ Û–Á;*9¦ìh¬ä‰€îè[í»“ s1µÃ@s[ƒ'²ÄñçûvMš®`Äa $@Ö ðÙÏì»RKhÀ¿ë([%†fkâµ0T pÖU©Añ²ö½I–£…‰l·rkLc.†¸­%¹ý¡d®ìõªFkø¹™(´õ3 ÚgƒYµ®˜;áŒØ}sÀäƒ7wß¾ÍUâ“Ðóg"û«´œ§M²Š¡dâ}tÅ7ñÅV%?)ëûæ²Fa•þŸ­;ؒŶ0¼ÐÊö“ZÇòÑÓ{ü»ëR£` …Èî™{%; €‘µˆaV•ËuSޤ1×ÐÕiX¶¡.¼ö>¨Ý¥,÷‰h¡Ä´g%ãªâ7ÄZÜ”4‘YåÀÊ24@úkp.âH)LQmáЋÏóJΤ7ÄXN á†Gr 7.ü@ÕcôýcÀJðo¿ÿþ»‹(X¨uO|˜¬IªJu¹§j8Þ‘LÄ/[4+2UÙñ ?[îÆ< [ožáÚ½ e]é•„ÑbOÜtJd À-ÐMkIF‹¸fçÃHŒÊJ3DòÙÂé R* Ò²®ˆ•޾«üe&d.eà ¼HÐ1Œä–2QÕˆöx6wÕ–¡ŒÉ§?*úÐñœÅ^¶˜AJH€ó U12çz3wdÈ_à@)çXKdÎñNWÝ&dM9Ö÷£a j¡L¬ËþÙ&°ÐsÉJŽd¾±MÙv)2Q вvsñ&f’L)ãó_/€!SJ¼RžŽJlÉìOGÙzxY£q",‹âö'+”¤Ìß»Ñ's„1kw$“3‰w\äÙ&µ+‘Ñ#EŒa‚ø.cÚ„ ï?€$h¢û†SëûÚ2±»QÇz·R¯‡o 2€y¶”@C·@ÇåÆ9ꢷ’ ó¬ÄC0µÈ‚̶ùdþ èÛòvŸÅnß9n:P4}@U?ÿÁjî¶Ê߯s Ç–îò®$`ïE0”«6†Ì+ŒÑ7ޏ# Ç#4°vÑbÈ“y>޳ÅÃþŠô!õL°È¶AùÄ|]?ÿ“'ñ6¡Õ|ìA˜Jiê5"Pžƒ#,2yeÇ2Ñßn\Ä-Ú I&w©~x6Ý& dbžkOàãˆ/G6VÝI% Ld˜Àý;“s™ÆÈTaæýÖˆÏ éØ÷¡­ðFkTMÈ4íŸ'œL®=eí1™P¶€‘-£«g{UŒAµÀ‚a¹éá¶zy† ô X¶ÀK:j©+¬©%° PâùîÕÕzî‚\¤Ö’›·UBv$.6ÏÓõed‘XWsB/ ×Å<%YïY5«í‰É?Ã2Rp(à»Rph.pµÇ Sˆ…j|%]v³Rb92 ¥=eV–¼À4d•0œåF _Mæül’‰Æ‚xVŽÚcà£W†3õvM@Ø92J¬kWH¯T ð.®¥éM$Óý¿„ìüfe:Ùcx™£€a¯L hì3¨T A†6"ϺӨʛU;óîV;7#fåØW¼.íº Œ^Œ0BÖ(êÈ–FŽý¦€µ×BéH㘕ßQ)7<’¸£Ø3Æeû0ô…jtìIiü©°×s<Ûßý)EG›4Wna%$Aã¨WN·IŒÔKƒD‹aà ñ‚’Cí0M²áJM‰œ>e/¹R‹ CŠ~ÚEâJÄöqÜ Óà[Pª¥YªõÊí߸F‡Éª:"U 5݈÷†½6@XC® @bÖ¯#OÜtU”U\îÃc|ŽòÈfiÇð´ÐP¥ªx©±AFVò–µ|DL&øL€ÏÿSx^¢2©½õD:Æ7ÙÛJÈÆ4`/Žg"úŒ«j!.`¶9ÇË ˜dV0½#7Pû2 $¦¤I¦$ø¸—* `@Øœ@ ®ÝQï(®ÓÍDN ˆNã\úðÀ–Ofóc÷}7¶sh“ºä­Úhÿ\h7ZUö¶-90®Alk4+Á¶rT’ÇìƒÓKßJ¹Á}±"mU;‡nÑU£³Å‹ü*áåH¸Íé1x11 %ŸCEíÊ=.k¤ìˆñGÐ {™ùcˆ‘@;äk—³­$‹îˤýod#"˦‹¬´Ã Ò`êÅïi ¶H˜O¿8úF3Ì Ó7Ö ûªè"SDb€¦¹@Cå+9)«gCÉø4%Cy‹µýf𵛥ÚPæÂQL¿éYÑcê"{A|í %Ò_Ì1Ä™l‡µßÉŸoW$ÐnÏõšØ}ÓûÏáúþï=·RíªÛ*[í4HÎ6©Å±­ÜܺJ}Ä­áHÆ à¨6z†M|}¸ ×dz5 YŸÿì.…ÂB³£f=ñ4{—v’ (”gÚ÷Gº1²F%Y‰R »a<‡=Ä582ú9ýÊh–5šâØ¿*I,÷ûQÞ]´ žñ†ö‰Ò`˜`dÎH¡Wàú BïØæYu¤¬ЋÈsŽø³ÁŽªJUÉĪÂ±Ì èšáÄ2[CU˸ÜLëR2T10Ay RÇ£þþŒ0ÑÎHûôó­®M÷V¨®Óç%.êe¨7ñ>—È4†'¬Ñ½Z)fb4øJñ1ƵOs#›.3±ƒ^&àëwR%//›ˆ^eƒ@½ªðûyÁÉAæ–CÊ·‘C÷Bªfh+þpëå°eʉ2Ë %¡ÑÄL¾ê|¸øMi=G×äÙhLGÂ2Ad‹ñw4Hd’ƒ,"{¥z‘ ²¬Ä i™†ÂÄB ÙRÓï@#×nÛD•¡£Ò¾ÒË÷«KVcqTϼï”54¶žjÎÖ#À‹ðºŽûi˜ˆL*â9´€ì7g; 6½‰› ÔÎ-g¨·FùÔZ«+± Ž^¿æH¹c$ódەն̳Ƭä âߢ§¯ÄŠ ¡½#Áil+i=2áHL pÆ8•:³U••²²£R|5k'3´ZD#ò‰Ñ Äȵ#­¤Àdô€¹¹ñ'# µËH2¸#Mx Md ÄÈŽÚö““[)õ·¶Râú 5¶mI#TµçS‹c-UáæFNÜJÈ}šôݺ’‚¯+|ã< ²gÉJü»FKCP—* ¦À‘yêr,6°ö„1pFŒ”›®ä¨äÝࢉ€2Þtÿ'Ù'c…”÷nuµ>AšºdG£·µuT˜æv cð@Uzá;VI¯P*ë… .}~â\6.½cO‘cœ’Lé(·[b2&K)רצiÿfÁ]ob†·ûü¿‰øª²’•”Xµ6&>Y†ª_NCP û)¸ñéFdÚiðà vÓÌÛ*OÕôõꊩWÆ -¾HŽ]°Liºªë(u%üm:Ogtï€wÄ×{þfmoäØª½lm‰³ã¢+#UÀ±½}iÂŽ+a,€hïm‰g"S ÕÌá6fÕoF ÙvËçô|_*“64ˆÉ0·ôª•˜‹”2ì)U[ ©+½ŒéÍÅkl ^¦‡;¶ ¼(» ÁÐS ¼£}0ôæ¶›ÒžßAJdb{ð@¥’5î.Žbæmb 8Š>þ°ŒoÕ™·*ÑoŒ h7úþ¢½®Æ©¶Œ>,%ëÝw.2¥FP" Ì·ïÜš‚þìaÕˆ2åÙìî–f[éM@ ïM12² dí™WJ ãå5âEL>éÛÙJ3»>s©k½HJš-Ðn¤T¯F¼Hl–êþ^¶q ônºoo½ÕGo×éU¹ ]5ÂgÒ}=]È·ŠÉ¤ÅnÓˆ·«FJ³LQ­«lážb¥È€œ¡^nÂñŒy>Œ5¸å£]—h+¥™ösH†O#ã‘gÒÕôÌñ;îs¡Ï¹–rL#b8vóYàÉPfŽHb{"Û N´³Ï])öÑÛ é¸+82̹‰Ç4~„Ã2Ÿ.XKb2ޝÕü´I&e&sÖÞŸ+|Ϙaæûáê¤i¢'ª·ï rLŸm¹‹³5¥jæ]J‹Ð«”Æn%JǾÀ†4p´½Ž¢%«Â šªSªeÏž€¦ÅLW’[lí~õw Õô|äFÀÙv Ë``A «Ê†&Û¬ªÛY#w¸øå^ÁÆ´+E·rz¯,dAŒo]Kô‚•ÖÞÆÜ”0ÜújÖ˜¦RUY¤'nQž•–‘¦˜ <ŒÙ±Þé[ id½æÍêHÈx{æ‰i‡$²§¯CP`¬Ñi„U3”}ÉT·j·È™ Pm¨Ø&=]]uåOÓ-&ãk”Ãr‹i¬K^ÔØñÞž31½YôùcèÅöQ‘O˜8¦ßŒÝQ)A½¬Çké{òò]až³â‹z#Mä€ôt0ÀÓÄ€ÀSæÖÕºRÀ”1ÚÉÞÀ¨ÊžhÕ&«ªD#sãÍ ``U]@ËW5ÔQ)çvPûÍc=@IDAT²U‚ML†ŒçLì;ÖG†çƒßÆ©6ßGEVõÂ{Š1ºðÄ@½dŒüšOI¼µyîûL¦L“Oãt9ÂölJ…¼}'¥$Vñ@J4=“Ì‘4·x>©w"žR{/äV{×ÔØx{›I£¶€€}LrÁj<¦ez"SUûHU»!‰ktÄÄ40RŽÎÿKHg é(`a3¹¥®‡!F¶>lõ0È”šDßÅ0¢ÆM¤é¥…’LÉ9}; Ñ1Ù¤ …Rqì®UnJ³µaGy Ÿúµ&îhP> ]Ĥh WSE:¶dXöUÓe¨ óæºð•ˆ‘ºÌ½@†ŠüeGÊôÙÂUñ­WFæ˜!}˜‰ÅÈD[á«&iFê˜&ÔÄ–qT%°À7½.LÇjVñ˜ÆÉgö½21 3¯E>Ïw¿ˆz5Ê®DϤ®Ìc{¶i°^²œáÞÄz#Yu»6ÑÒH%‘IH‘c +€ŒyCex‚îMªúøˆÍ²¦ ;ê…Û#0Lšâh]4Ö0ÝÆô_ÝáœU%U-ªÄŸþ¢ϳ&&€å¢®eJ-J­Á'O-ÖC* 2GUX¶ q+­¤å3æþ-CÖ‚÷ÛkÊPb[KC•š‹0†Œ›#¥LTE<Örù|ô‘hT›î‰rF&–‡Ûªk¾Õž´õ`Î"ACåß |>­×†ñýÛyo²­ð7tהּ)š"è5ÂM1® Z”l cr³Œ£œáºù4±Þž…ÐVô€c¤£È_¿þ壼°é˜ê¼²sóà&ô1Ç·ŠR¼cر®–ÐNϳ.$Y˜1,„÷ÐÉZfæ°À—‘,|ëG@l"؉Ï)6inGš[ ž&Û.8¡…,àIì¨÷ªÎovž¾[€ß ‘2ebúÂÎU š+óÑØ 0”~—MS#ÆqlaGûøF“yWh‡~·*9Î3AVeÓë¥Á4÷ÜêûY#aƒDkÐcz ÀËdeŸ”[†^tÚÓ aëi´Ódå‰"yÂå»ÅY#œ›¼qùÈüÉl 3EA¥ í¸‘MYõµ5E0‰dëØªšf/Ÿ¾dé9¼¿eh„’|fÜ ÖE)6eíö¤r¯7™–9´=ÀA†pL¿¶¼àIÉpïàˆ— z8²8g®ÔM¥ãx{Q /bdû ÿ_†Ü¥+@6à¯=·J60L”d¡&à\o†Ä¢å—'R‹ì¸o5YU½pæ@†@'Cö‰„&ˆäŒÙ‡Ÿ¡’ “»‡–‘cŽ–å”KX¦“ €xGá“ÖØÿnª.%K$ë'm3”‚`HÑÑ}2wlc@»¼-kGx½”"ÏíV—õ^CúZTµÀ2Ì„l¶‰žã{·ï×—{ž†Z£k6K `(ë•[ŒaC[/ZF ‡vÀ$Øn- C 4]; r®±+$Ö¨ÚûîÌÏŸL¦$«±+úFŽþÓHïÐhL²î•¿R›È ÙšèMìH™'@À'ÒËd‚DCñýyÌGTÒ"zðœe¶EÓ)#)ñ½üdH8·@s)mÕݵ(I_±£Ð£ÅJµ “ÆsÁýx¯E©{ÕXË1ý~Cî´“ÄÛ¤7¬Êáv|®œ˜Pêûcâ«1ÈQnçmëÚ øÔ˜ù.\WŸ^ÇzµØ3]ù´^88^ØíÚŠa›Ü™'ͯÚ;èí£ÁlnVi2 sðGrz=£c ÐT{ko1Gb†³ªEÉ è[F¦ÜO ý– èåFß'å(êB¾w\»AåÛqJ½6¦‹¨Vʰ¿‹Ì¤¿YkÌjCif›àüabu"¾ž ŒV—]2¾¾È–ØÞJ"¤ˆ‘µóq-}$.ãHÀÍQVxÊ1xA‰éSÙ Ü= M³-«2„­AæhJþ0>²¡J‘ 0E8îÆ‰u]áç'ÐQÔN¯Ôhé9ÓûÛmΪñvS’ž®‰>Z¶’£YûàÈ0@t†°lsúdµ[)IU‚·±»ø¯9×(cÔ¬®³MF&«ªË faˆHé^ø†–lPß:âjI)S²"H07^©…ª|êÊÇ1ð®‘X—RÛÖ•g-¹é0b#4:*aÎìçï¤H&]S£ ó§qœƒöJô€x± ‰‘ºê% ÏŠ€¹ck¨ö-ŠAr›I½-“•*å;"}íôÅëû.m( %b¶‡ۥŽd]kê¢Ô_ùçKã»L‰.<¼–ÚË”JýðÓD³{õÓ­DÙ j. ¦o.“+í¨ê'”,Q—’¨$gäÿ÷YÄJ|”³º .‘× O†°ɪb{Âõ~þC`"#yO´´†¾|­Õ 8ëÚ›—߀ +5¢gQcJSÊ9§I3ÛW–^¡±^¹Ñ—8¸OÝ1‡4ÀpL†=e˜À±êòøyÇfÉÈpËÃ"vÜ}$ĪfÕUÞzŽï2L”6=,‹3ìûsȪ‰Z)Íê;TW¹Ð¥žLëÛbI%‚€X§—)itÉÝôÅ{‡ÉrèÏ6­7bæù 6(¦éž‹®¦t—yb²2ö¡ý_FÇÇóï.ªB‹#’g7r$+t9’Çád-ƒ´ªÙQ0a2í 0ÉrFιqr»—–Ú§Ì6¤c>À¾ó?9ƒsèthº8‡L4iÇ^ƒmÎYUöcXc Ü#{%ä{M¦ÉbLD …cÎZ@.ÈTa;ø¬û‰fòêU1|<àØ¥Ç`4‚2[ M¼1œRÎ'ÛÓï¢ “2ó=Ešô|yÑ’ Õ¨KÖÈ­Qor|™ÃgÏÿþ÷¿ë©\¿\sd7·1,†cäî0“|Zºm``—L0}¶|j‘öeªEn%ÊÆ92)êMI øÈ;ÊzåÜÎÄÚ1óe<“é}öôŽí¤|7iŠ,“eÞ,Ç®I£ÊüÊ?/œ^™K Åñ° d}­Ž:Ú„†IÓ•´W•‘о#¦c2&"‡˜üùPÂ"=@ùj2×+ðdÈÖ†µÌ$@YWžÞ¡F¤@ʺ’9Ƥit#ð ­«Å` „éË׿¼@€ÿ;Î ¯® ëê"µËÙ¦”E/ß»™¥e³¢ñ2}{1‚&O¤cÎ1½^žÛ¡knþºšuWøü˜cuµC&˜”‘6Áô7\dûÐ$3e Á»mU-Ld‹âaà5tÜòùÜ9'wÁ4#ˆQ­fB”è­Gï.xÕ<ÃJ” ÉÚ§vxÿxJF ¼pD’¥žˆ\/~2€@/2åôgÌ šµ4™@ŸçòZ>ÿ§ œ…†æÚ/>Óª\²IƒìÛS©c½åžÃËÚ&†€˜›)H™X—H€1"% (]ƒó”ŽH&õÊv<.Ïw&À ‰û–x«Fx_ hÉœ?’€²?Ùˆ˜¾I0RЈ¬ðm«Ôd¤qFûšÆ÷tMĴ䬸Õ¨Š>‘Ö^ )0„•D¶<÷Í®Dã¯K]g£µSºµÆd]àšýå+hVm±fa]üuÕèÈ9¾ 1Žaƒe½ñ0À'ÃDÊ™rxÊôxëÙÁ­û8u5ÐÛjì…‘á<õ zU<2þ5ÁdȆ> óGÒ÷»•F(•ݺȄ’Œ·Ï)|ÿ¶¡=Ï™gHd7‚)u‰üÈñ6ôh×ÒkdE ‰³Ä Þ1q|yíM‘[ _ɬ¿Ïl‰µnïëU-kr;úÿûß(g=…r—0°€E³éýÀ˜Ñ0²U #³ýÛUûBט†þŒ¹ |†©v4WoX&kPëå#e¯‰ßY¾4µ´@þº2!† ÆsÐ2CÊôÍjO¸e:n%¤…3”¹±;¼öø<µ ¸ÑJ teå˜ Ó°‚ûì–Óãûiií>AÕ÷ß{dÒ-jo(ž ¾¡wåÏ?‹(á™+‰4ÄAST…Ç÷‡MŸˆj¼^†adk;¢?u˜Àd9kÉœÌr&ªŽò[uL¯ïA6®)FèŠL¹ö>,¥.ëØ‚@- ØŽ"ç`$ÓÞG“¦’Ü.K㹚Òé¦ÁÓÄëjl•Z¯[ð”À$Á6 êØ)ý]D©AæÝ…U›÷ ¿ÇœÓè2ÝïV<³%#à,hÂHâȔʘ‚òvœ×î•Z )ÈÚñµÔ.$¬è3Ì¡U u¤ñC‹ÚU=K-øzß̼ÞZzÏ2$& R„•Ú*M¤AôÉ\¶c™ %ü*é-ö«ìLD¡¡›4L›cŒªc ¬E6²ïe“d ª$ñ^†UÊÚa£›Né{Œ¬Š|ep-°ªÆ9ˆlɸëûcïKl½vÀëjÛÛw>¶+ÿ´áǨn¡ÉÁÑSXÌqËÀø¶ wì.[µ}‚ @:Ê-‰ìdezÁÇSíG—@Ð#i´x%âÈSônabÊæêò_ñúßÿþWcãý£ýõ>ædž2™¬š¾ã° ›k8¥ÌA ²êºf5ÆPÊf©v»ªÛÇ‘ª»ôѯ¥Û9µ×Û™[ Àèõd)Û°µ1FÀÚñWrŒµWjUC‹6TUêG àõ¶R™ ¹À·gC-I“mƒ`€O"·X@»ªPÊ9–U€£ÿ€ìÜð{÷4óL–•oIúl‘ñr &팄…’_î,s'þm†c %ÉÂeäHÁ°\¯¹@ËÔÞPL¤j ävð©‰Ü ”Òla¤RG¼cLâ&“ÄJ”ør[ɵ¼$Ü‘˜ Üæ,h|†gn¨r»Â ÂNàn‘Žæ•ïèÏ–¯/ì>N‹ìWFЛ-r£!€¹©F¶ nhákp^‡¦ào®é¶†’¡ª]ªÌ–›ÃFlPSº,27 ÿé×nÜ\šx]¶ ~WkþsÔÒ\nŽÖË Sjzï¼£’q"M&2“þx äg”L`]M16TÉo(^ê*vUšüéÉêÅSÆkÏvmTš€d½Œ5ÚS‰›^¥z‘ŽMÉG¯c81&Yd÷Böt4ÉdnÞ$]‘ZàÂ¥ü?ñ[R ë¢Ô•ÓÑæ¤‹`Ò÷Îx ß1AƒÚ–gÑøLýþšKÉà z1ñ}R5z½ªŽÄ<Ér&î¨È‹•öàJ|{oÒ¬öQ5‚ŽñònV7’×ÂÁ¡Y{k'Е¿TUJ&벘j])ñ€¬=‡2Më•3i¥ôñ10¿×P¹–OAÀôƒÖ”ÛüíRe%GÁ§ÏèòzpšvÅë“IC»BûÔ%Gaè:_l÷©|¼oô²`㻌¡·\Su%k¼ÈÙ dº€¾Lp 1 ’ÅëꃯªKÝ÷žØ1gzßË~˜9g¢š@¬‘›¬¥¨½L`J<#¬ô’Ü8«â‚d™#•„cã`ûßݵô]§Qå¿ÆÖn‡LàØ‘?+-5&à¯Wn%%“‰‘4®° –Dú5'søzéûo¿¨2Ä‹LìCß{¢Ad0 ûDÊ”²À\Ð`D«rã zaki+GXc&dÊ4Ž{“0}_ µSjïøï¿ÚÊW V@]-æ"4î›?àÙÃôËîB3%¡áÖ•Û­/ Ìm»Ñô† jŸªxâfé5H#Y ˜¢·ÑyV‚•Æh×%òiJOA#L©*·I;,7×Eˆ{ŸpV-ƒ1T»ÏTl\ÓSªv/Ó‰Û‡’¿v¿ &C GY8êLëíXWø§q$Àd²WŠlJæ²g·[]‘u×2J᪰q0PI;,ðÂQµÅ"a€ø kWu 6wGž”ç¯~©­¨f˜I@0]ÍJ¸E)áÞˆ¾®ÜÉŪ™àEÎaýµ¥‰d€¯Ëާ¤/k™áÜ”¬”À\¼¡)H>™wMU‘è"Ž…#€Ïưê'Çß \-çx¥6ÄDÒ`˜PÂñ”Œ”ŽnUkï†] ]S’uObÕºr¨½–dZ¶FošU¹^ ŒdåM„}íl„#ìYà”€ñ‚Ó-䪵°zõFˆÆÑ0I‰œ?Ù™ƒ0KiJG˜²œçÚßÅ"ñ@á:u92™P5´YlYõíô¤g{Ydš¾0Jþ`¨¥ÅòlJ|³vµŽM¯E ÉÐÿû®›",À„ =,Rt”[¯\I{hq#ˆ´0«ŽLèÃ9Ü™çË WV-éÃlž ]Ľ´$(ÉóíêHÙã{½Zð½ÏF¼žMl=½EG2 Ï'¦£=[Àqï¦ké˜Þ±ÐÅÇuÊŽ~Òeþ­M_WJ¸Kiá ‹@iŸŒG*ŽZäæÊUéÓ$Ûb€@Ь:®0Z.`2áOŸy‚J°¹Çú¾À ðͪ»c ?Žõ7L¤îÓÚx‚LeLà© |úÍ^1ž^ÆÈœid÷ï Ñng‰ûËV¯+qrû47óªý@`" Ìj[-ãŽó©ä˜ƒÝ¬Ñ±Ü³4“?Ð]±Ñª ݶ›¸AÓßÖóª&ª2äãØÝå~<’5Â÷£oOSÂí†aR{ß¹¾Ll9¼.FÉh‘ƒ,·L ßt›0l[€FFªÊ‹ÔØ\d&­TµÛí_Åò×îFyºNƒf` Ȧ[»lJœ$ãÙtk(ÉxJímÞ¿Ǩ® xçæP¦)¶[Ʊ5X÷>ªøÜˆ5z¢s«{¯ÖK“[bÿ Áäuh%$A›Àñ˜HL¤£Y¯¬ [&±.½w»Ï†þ2¦)Ý]ãHØ\Gï ЋCf˜f i¸ÛEÊÄJ]¿qÍ*'– eSjœ† æGc#jQbbá _e˜X¨ô…Qí‚o‹q)ý„¿ÐE¦oO€9¥Ñíß²Ræ9çӓª eVÓ0 ¾ ”é´Qh“ñ€ïk*·ŠÜ®€F¹mˆÝDWžµç³–®Ä* jp(2‘U•ü|Ú8ì¨W®ŠÔ‰OذëÀ˜ö!ÆÌ»†ÆvK´Œ?Xè2H—è«#’s#è•0Ž[>“²R wƒÛ*gdíÙæLã(,@ XÆËY5QU×ûµÓç  %‡¬Z #«FPú¿¥E ˜R#¥YŒ‘ñô§®4dGý×7O¬Ô ª¥õ”é1b¥žcš®ï÷2ÜÂzU}p6Ùô¬´Ó´R†­ÑP-HÌÖÈÖzxU<Ì¡gI¯¤½*Ðצ¯®RÛNù.x@D¦lÏô¦Ð|~PÎf¯­²~Œæ>B  Tû\Uc0"¥̶*f¥#c ÜZ™²ªì8±#L|³dÑt%@5Rî#•¶Fι_8¸ ý‘¦‹߈9ï› R¶ªÜM[CI÷ï"¸ªÜD ÙøF7Eµ+èÕ¢ÚqnÈF¤ô˜YÅõ4ºæ{[Z Lù¯ý Î\Ë>#æiÚVIð}|@Ž]áOâVÀºÈàaž#§$ƒeU²ªµÇË•¼9C?۽ض0x]‚ر+(á`¼‰*ž½¡Ë”þ¡D©/@‚.²#}XV" úu¦ÊGXÃ8š¾Õ‘kÇL3Cš”<5¶ Ržl¸ÉDnV½‘˜-ß­†è /¸ôáíFßcºZŒ}x æJÙ6®ë·°’—Ï<‡†Æ” R2hÞ¦w—&Ê[‰l›àÉz¢³ ñ¶#¦/L·h:­ê‚p—%&“OçêW‡¹xbḻéñu¸iÇhäÚ® ¡3l:ŸH]5vJ@¦¼K}þ‰9»ùÏ(ÚØYM8ÊÙ© 3ÒÀÆ Uš[ü|e1;‹×!qæM¹½‰‡ù×€½KÕs“U‚Áæ&@67ž'ÍZ”0‚Œ`™FÉÛùÐИFÐÏ î£ò‘Ó8ʪ‡iï?»CΙ'·¾pã"a;Á…#e{H¿qø°ÕÞ$°¡Ä˜¶ÒB/§DÂmî.n„ÆÃnazÀ¸Úç†ltJùÝÁ\>Ý¥A›ˆí sY¦çCÖ[4â4Û éæ–­54ö€}ð§o’О™;æÐ;sИU%_k|²Õ%´lVnmž•ö£IÌ„C&m›’À½mEŒÑ[î¨tîùÖp š2¾÷ÌS9˜åR¦;¶ívp„)»òmúüó¬Ä<X»¹”µÀÀö‰$nU “[†¡’i4Œ×kCÀSÈ>/Yàe&dbæ}F˜ˆO&þ,šØžHUĽ›ë쎞(œø:”RW;ë­½•~¬A\#±ÈÆ ÇĶ¢©æÖCS{_Èðªô™ Ã.å=û\6Q#An­T—,bÃ*·•ôÖ®J“!ÜJ]§.-)‘b>º­×7¼)ótT"fˆÌ™Þ‰ñqDþд0A¼# ˆµ[hŠ£ ÈŸ˜j!ãëÉQ'¦Áf{Ó#€,/n s_PnlûJÑoÜCLé¨&–aU{ kÔKVÕ1ó®'ã«æœ¬}ºvMéÑ1d¢–&ÓÔ’9¬WȺ²ív4þ¬†‘Wµ¤Òƒ ᘌ#g-1ô@ß¹ª˜É€”–‰[FId¥Ý íŽ=]&Ö#Öõ6RÖ(7N•C¶2œYJdܬ‘ ^2¼ª£È?>’é¸HI#`™­*™€‘ â€Ó;8òܯB륗kg˜Û6oŠj;œ1÷Ýx†uNíVeäxʾ¨¶R²†³èXnáé5B&pkç¹®Z@-J1ÃÌÂ0Aö!»BßÕ>b%Ìž1`³Í}óüážT—¨$Ãî¸ ˜9†’ÏW@×ácäküùк+×Ȫªjé¦ýo$V ÔhPFÒ‰)‘É|»ù‹,ó÷S®”O]»N³ðÉ0Öˆ|Llé zÃf‘-¬DÓ©^¥BIÀ ’ßÑp˜L6·FJ¥ôsÕóÛAÙY',ÚÀ–È:Ëz„£NÕZz²Ž=“öW£w× §l-¤^ÌÇm„%ÍÖàÙ·\»®v¦JŽ”áhDíxXc€8%F¯HÖbùXÀ±5긔½•Rš.…ÔØMúìUªâY5`•I]ô°Çï%i0 ÀÃiä1LóìoJ¶È=T>4JxÕÉVöÕß›w}—ÂXÆ‘RÄÓÙkâáŽFðþÍ %= 0¾â¾fV’í´Iz¶Z0z=€{Ÿ¶Ê,hLOŒò3˜ôJ)a]J–ñÖ ÌÍ8dC•dJx®>,2ŒÜ²Â°UkŒW­J†„ÉÊ·õü3€rÛâ»q|+YµFd¼‰¶!‡–<Ž7¦O†s/¸«5= — ZÀÄ.¥‘ÌÑܬÄ€LP洞 î: ÇÍªÚ ˜CbíÍ¢ÇÃ)ñŽñ1ª X1ñg€¿ÕY Ëö2ÄH²žà“Už˜Öë"mBìÝ6ˆ¦áİqZ8`º‘¹ÓëzƒÒn-6@{ûȦ8Ê”<ûÏþÓ`Y`ôØ6I΀ҪŒb”ÄÈ]@©”LæSj‡:*¤žX F6TŽYÉc’)å“ x¬Zªb·F‹a¼  ”„Fb¤)1J}~U)é÷€½­ÎHúÝ‚‰–3àF¶`b%ãZ©ãFD¶a2¥Ê5rZ°€|Õ8ÔèXøE_•7½iˆÒ È0^˜ƒ͈–iÉöAà) ØÜºš˜-%M-@ƒ$–‘ªxÇ ²êªÍ²F)[&ô2žyV˜4}+âs›'=LßÐΜ¾£RGJž@¸Üz/‰!î·CÙJ¬’åÃ!OÇps»%=^ØŠRuµÐ¨¦”…#‡2‡ºè9Ì#0 jÉ-å¬h( ¬ÑÏdHbÑcת-°^‘@—è"7hD†4sÖ›X/¬ôš[^µ’˜Àl„cC ÒTÅg®Ú7Ó±f@K}—¡T~/Ûè[ÿ|¥ù#ΧMÊ-ÀM)ñ4›Ž_ÔE“g¶”âó¿UHêEZŽÚ‘:E.J :žÎûcO #ïÂç;á¿8ؤ†õа—êÚ2ÜÕV糪‹ @ ¦·€D-øZdTJ ›% æÈüù`XiñW¤ñŽÚ•hŽÝóµÐ¢s+çÇ,Ÿ ¹ñd-i:«þ F©+g<Œ§Œ <‡ºü)âØ#ðY©vA-ñ@·S2º}²ª 6Ÿa¿ÝöG•2¡)ÚG‰³j•šyÇ-™O/ &>8Р@Y 4ZÒQÙ?ÿùÏþ ©¹­‘•[´@Wè…9Ð4½ç‚ dG]wÈÙD ¤ -ã}3ÔnŸ9ôž¦4O-%Ç–Ì_W$ €ôüUwì:Ý 04ez ¹µ9|ûé‰÷˜”è:À4zóÙ·E/A-AÎ}æ[†@$𷇞‹@¨§ÇxçÆå_ƧÉǃԛ22ìØª-Ÿ¿q@ú®I9ó)i6‹ÆäOŒ™IÕwJ¡Ÿ•þ2^5Ð;Ä"˜ÀÑkè}yzU³àÈ4F@(Éék$·xª#ÓȪç›"›T£ȆÉc»³uíÑ…1-±Ëœ1ß¿dm–›ÒncÇöqÉÆmÏV'(Ú¹¹ðöјð¾|¼ëÀ_ƒ__<‡ž5츹µ4.Yß`>›Žï³„–Þ!¬EîŸ)iô&Z¬µ­¡ƒÇ‚^Î ?[<1ŸÄa12؈mÅ¹È Èø57T H¬êx:¿·2%RîO¯&fØÚ9`ëõV•ø³Ò+{%%|Ÿ=F7e ^I¼ïO ”g{Z²)³ 2]h‡¯Í™"ÞKõŒé·X†~Où•W¯.óÏmÎ×õÜ1g-”µ áx@Ô ´‰«©šó®Ú¥È*5Åßè1®†¡_‹ý‘ {XXI¦ÏÊè"Ä»Œöœ»—#SºE¿¸;ʦÐäÓèF¤Ç“‰vl¥F›Ø8šde²Öΰ)ð°’erN ÎÚ›ž,6¥ ÂÈmˆ×ršïž^Idΰ’¬ÄÀÓàíms‚dôMÁ¢Ï…›ÞÆ)-04<1@ »¯j%L8½¡ãañù?¡ì 7Î 0Þrë?=÷L¥©Ku7l-Œ0¬ía&Ù‘²KÒ3̪Ü[ÀÇâšÈ Ò¥Ö;Òû(1rQ‹ÄÍí >.÷h$Æó@ˆT—Gæöê»×>lúüë壥 1U1sÆ4¢éŽfÅÀ‚ÃÙé{Ù."Ó‹@κÈ`¼Fø|Râ—¤Ï_‹¨lŸ “…éÝ¥)Ñ"w4¥#ðV“­ä(ZiAïÙ£å6ÿ™×.WÊJös°¤¨TãÚÆ™Ô ]JòÌí)÷iúĉ{ÿÛw–Q ò_užx‘ ï×%ÌGnŠÞ¦·Uǘ¥Rø]ÀúᲞªU) TrTVÊÇŸsJ¸.|bŒh“=…öøJrÓým€2±Œw;s5öGT]JÖkŸ@û¨ is %ñ°¼ “¥—Y7“WîMÄláœ/ýù°øƒ´$–ù…ÛG( ŸH³`·‰³r„Óé÷Fݱ7ÏŠ,e ¥RM%Ç×!LCU“}þ_BÖi†P1DEÏMªÿJÎ?w¤‰!dªä`ý¹äã§ å. 8ê%ä¢ ”œfd& +µ$R4OÐ3¬,¦„Ì6M;à)Oçw(7˜˜@­ \ÕÁPnž°ÜÜnÓik×ÚDZA‘µ(”Ñèíæ˜CC/š«d¢++ÑàËÀFæPöaaŽÅ}sd-«¹ÉÂmŸ,¬»š5`†Ú9#}sü5™8”E$\»¬ Ï#t…ÕîBÜ[F·!™jÓSæVc™!= ¥ª¼c[eŽù1Ú‘ßCú¿ËbäÜÈ4 Lí²é=Kâ4m x züœãcÒWÚg„ȽCŒcJG&Ž2Þb°hgU̱¸Áö ÃZÉ|Ç|4çâÖµé™ë­Ñ›L<){=¶z5™g‰{ %G¹wتkœOž5ÊM¬=Ï:+¥˜õæV¯ø4xXtS4H¹qÄbÇôùpplsÙÕ²’ua8ÓGæ/@hÄŸ•µŸ h|¤†6 œéd™âµÀ2Lɪv7QÜ4ád•´‹V$€U“u% ž8^ÉnJ˜áóWÂ( Àèá€3æ±ÿ‰i esë…4ÍMÀgko"á(¸ù×ëˆo+ (ezŸ–l«4ôm($«ÑJ”-Ö\U³(=>†L & ,`%™˜ F>‰sŽÌª.Ùoÿ·Å$ý&ngW@ªæ“sÿU sëRE&cÌâ&øÔn4FW10f¼Æž.ç²vü|1™[ÕEú iÞ_\vYzÁ/àÅ´ ¥r‚ºü N©Úþ²¹ÂÙbz·0=ÒV Òb\&˜>dÎýºÁ×ÈjXK]-ÉDo¦‘…q¹Á Åpsl4Ò›#Eíla†²eúÜdÙDKÞ]ÎwµÞ‘ÓïçØ'[©Íe>" ç¼öŽùÈ‚‰rtº”ðkï¹TÉc\2<†¾ã kÑå‰Öž Y/ã(¦aËMI»¬TNю>µZúè5* @MiÉz1ªíO ôùqTD ]8õÛFÉ« qTMp†¿@kõ¥çÓ€^ÐN¶/ÆÍ»<>Lì×bãš’ŒÀQVŠ‘ELžvÃ$î[Ž °I§ùùr´!†Lî5`  ÏïCeNÓPæ€Ì¶Bz@c/P‰¾Ø’=,OzÚ7îØ)Û&Ó•†gû`€Ž4°Ü¥”ðeLnÖKPW£³’ ]–ÏÙ†3ÏÊ€è´À4Mÿzœ5˜+‰i`޽OzJúd}1MÀÄ4rkãÝKpK¯—“Œr¶ ¢äƒÌ hCdWv¤Q0ûbcö\ü3)c <`‡.•›,¸õîV]#Þ±ÆJ] PÂ󧬯‘S£c$xý×B†ï¨‘g½ø@SÊê8Cd¼YÉr‹÷SL)ú¦™eŠ£* ¥ª56"C<@ÆYK+Ùí8W^c¥u)ù³\ýx \—2ÇH²ô-‰od²o‚{M™9}ž”°ÜbÄ™Œÿ¡gÒ¬Ä3Ü °R__EXDÊEûÃÚ….³úyùÛï¿ÿî 9‘g:Â,êÂëOO)fÚ•(ól3Gš9Mæ0 «µÀÈëzZrÎG PM¨ùÃZT{_$ F—ÜÇÜ8%š™ÇO?P(LÑó\*ÙF’™¨ O,ÃÈLÒ`Ú¡erð}OSIWÎJønZž¿£pä`5flŒ%ûF3÷YàëêséW!·ªÚT¦™ .™¦ýÇh/VÕNã(Æv»üß%k!0Hþñm©—9™\{×,¸£ªÞfmaG?̽í#׋Qrdâ}:Âã§ÇÄzsЛ²ŒÇD; ¥B‹ýñ.ï¯AkL£DãFz•ø„‘9Ëx™ )•šŽ¬ÄM´@™€Ìéñ•*¥‘s°vL£a2¸éŽz);éko™ÆÕÓËFMÔ娗VI¦ªŒ—#eV@X)&ï›sš–L&SbØ,2?¡ *a”rK`Ãz+µÃ:Êb>”a2&J=øøüe¥î+¸Þr;S¢àGy>ª‚¢—5[D’"e“dv²ÐÄÃÉ9´¨]4ù;6Ú±è(+‘µÉ6”¡Ðâkä8Y$ƒgÒ&€#>Ç"ýrseJäö4ű èU’)Eƒ2Œ+ñ àHûÐ8¦TÂxdJ™y{Ö¨åÔ]ÒÈ™l¢Æ6¬W& šX#ÏzñôŽ@ ¢.nºÚ–,Uz?6ŽýÉá磉!ÈJ»)"CzÑþMìš0Rp€õú•çhb³ï×4†-7‚4YÁx½L´3¬J‰éRM©—Rc|†µ¨!˜Ðù¸eÌ‹)˜2·É6Ôz:†HæíüüƒY´†if=&Ž Æ)ÉJL%™í10@ šLWJ@¤É­öJ²%GÚÐ:ÊJÄéM© #™Ç©%Œ1)ÅÖ€‘Úe$7&ŽZ€ª}Ž{4×Ò—$ÃFÈ9|ji=2ß^n½j†Ëª¢cG&°|%d;ðTò©9£!è÷bŽ4L´Y[ùÓ4ÀT¢Òçœ'[XËd¦ =]>9TýË?È+$¢nE@¿D/Þ*ŽöÈe€s;>ߤ6&îu¬XË·Zh4f.;Ò¬==ÞbaâæjoíF8еuÃr¡½'FÒ#°\pNÙ2ª€’YJÛ/`Û:Ö¨ϪöF«š 'cHæÈJZ€ÂóÈ*ÁYÝÎÑ2ŽÆ݈8O@©#e]2e†ôiLÌ!+íÙ:Ö˜,^²À ½£DÓ¹£²Y‰³5Ô7 ß÷ ÀPò!«E¯MDþµSrè•€Ú$è ¶È>M|[5 OSÌDX€øõ¤i=ûÔBF ±^¼ªÆ°<@ k1”O#jì‚}Ð¥¶ò:r½Y!»¦)¹9+ XR¤ Àe2ѱqö!C–»‚£%ÍšÃi»14–즎]d‹añ™z'д3fsŸ )“‰ºÒß០s^6‹’¬ÿžÒôµËÌç©C†1·ödM©Ñã8î¿üÓ瓸×ËÖŸXþãyv‹dÕp §ëËà(”ÚpÊ­g(çž&hÛ– k?¿qrÙ ¯QRch0ý™ßÝhðL³NƒÝóßU-í¨æ? Þï£^ž±Þ£­"å¦Ñ÷έZ‹j‚F3©ŠÜ'ý#žªÝTØ,‘Æ Ì<Ò‘Lo?¨Jw‘Ïë숙jÓa¥þá+&päIË4ÉLlU‚–áÜ2 #aú†æì˜!&üµàëêR2}Ñ0pT] ¬W`Á[m®\dÓ7B6Áa«†v}|LÛ2We‚oŸÄ™«Æ#19°…cÚ¼0@ù0DÊChÉ62A‹)ÚDοÞ0RKy€ÀC1|«ôÀ‹|\–Ï7ìû#Sm甘]!¦v8±œY%Y‡);ÂZäþÙ¢ãL^¬ÊÖûÈ9Ä̇¸×ëc²ÿûŒªºˆcøì}h€Uk1—' }…dthÕ%‹3Æÿ)´Å#Å[·=`••ݤ=µ¯Ñ1YLUŽ&:Ê}×aÑé&XîJYõp-ŒÑn:¬Ë†ã1BU„UE Ë~™ÔÐÈ.kŠÀ·1Œ ¤ÌAf»”‰EJ LìȈqìçÙ&•¼áâÂÂô1º|)žX‹Ÿ+üü ¦ 5ê"€^hi+ Ù6·Ìjž x"ãA?¥#±@Êd}€£q9hñ¼µËs¨7½å­Ê¤U“½&M¡ßÚ²Þ YÌ? ‹z™k7¥eZX)À|b"›§çP`, ‹›ó4}%Žï÷›<V° ×pÈ­=ñŽWòILBøÖtõ¥RÒo:=¦A@‚×½c#Îr7Ð ¶ý)õºQѨÎÊÕ=B7:Fß¿Lð!0Qh÷CKÇz öâþñÇ5ÔŒmFeä@2)ȶ„#~óì¤ZãßûHU99°åV]©¯õ~ðšk\{ãÛÁ>ûa˜þÝ„¬¯ŽÆ·«—Ôí Ò%º;Ðôè¨´ï “>Z@)èr„gsUç#yâ­G¹ ia@ιÝ2ŒŸÉö¬Wf«šØ1FÖH,+4ò­ÿJJ–yVKÙ\›H@ëjÃ1œA#t„oå|¸>&UC”H¦díÀvšx™[$`ÌÄQuaá³KSÎVËÛ…täoK^ãcUTÊVét~¿BáÖ#´ôõPrä†G֮䗅ÒJ‰Ì[8¦ç"n¬¶+|U¥†jl g¹Ñ™Ô>¬’Õ’`kSŠ÷›O Š‘Ez9â÷qÚÙ¸zˆj'v ;ÚŸ2ýZ€3éûû}£uMÃÄWkÊ D²®Y—Eä+ ·¶0±õ€Ì5þ¤v#&óåض'EíiØÒd›ÀÚ40^hv“w #›{…Ÿ¯ÓQß`‚?ÿlîv ª²H!¯4Y@‰X;@ˆ¬ ƒ·k Æwm%ÇVÌÍQ4×ÄîITÊ­ £«¨ f.z2 ¦Åhnñ“˜!]?Ãæу(Ù“F ÊMÆ» È­ToJ|ÑæH@FfÎÓ½l‘më(àHJÇéõß'°°/M¶é‰í TáÄ€^ɺזIS‹ }sk,÷2½5Z@nÕÙ&¨…'7Vª0R†1L”äô)1ÉRÂüë…u‰µ§lyz“§.˜³÷‰!Ð[ð©äH¦=€\`È”Æp7ךvËö†uµM--i7‚·ï(ȬÎzã›B©7rÿ bŒ‰‚¸ÅÊfý¸‚£èÄ܉ÛÍ;VâܱÜkévÄŸ’s—T#$¶yÓ;¤¤i7€²èØže¼^Ø h6ÆÐ,Ó$Ã{¨ùLÔÛõi€VÒ›yúFœñ7Tés ÞZ@ÞKÒ÷!ê®ºÍ …k$vijmÊ–Áói"«ææ +ÉwÁóÑëMÌ yʼRÔÀÑ‘£PÒ†oLmûD¦š&¦Ô…­˜I¥.w”'¦OÙè¹Á-­´'¦o[¤ gê÷™TñŽz-ÙÛÑ •ð~Àª5n7¥ø¦'.WÕ‚‘Ûß/ÇŽª1&6ˆ-ÒÚFàC÷zpÎþÅ8 UY5Rz™^;†¹ªOäªÎïz¼®6Á; Êz-SW#à¦5Qn\«v‹þuž!qSÊ1M©7>¦Ñ²Y/wħX× ‹HJ&˜Œt£J².KöJîÞÉT›â(Ü ó’†â9#û8hɤ'À0¥Ywdz’€‘)mu‹çCÑ%áÄôÂq¹ÏH•Ò\â>²>…)(ÍJ£×Ú-Ðl(!»`žZDŒÑïJ˜J¦ëõõîú4-Y ðíÖ\Îñ–ÑH$n ˜^©¿ ¤ïƒÃ3©=ÜP™ >qnò©Eɶ›ÞhG;רK8* ½o‰Rà#ûø4:²ík†,f&³ ²»·˜#çøaa]M¼Ã?ïF#š‚X¤ À½[<1½FOÔQ¦'ÿ¯­»Û‘ÄÖ‘5zá+¿© †Þðõ,éËŒjà ƒAJ™UÝÞ‡æü¥ •ÂoŸ4ìCŠ×/ø"[7^ö­j£¼øàá4€.w£¥Í`5ʦoÄ4Là¬R:R²mDJ›´¼#^ä‡ÓȺfÂÓk8"÷—?GA½^ŒçþxÛD/æßôö?³¿k%n æ†jW’ñ-ì(`ï)"ù˜Åœ IÇ$StßMX :@V3)ìs!Àg—2î>€@jL0o’¬* I@ÓeNÿ½¦}èiÖ’Ì>U=1”J¬ê8óü)‹>¸UâJz³²FSx"Yaè7ØPŸ:^#&ÁíLCióÀ/ت:ÌõR:r F®¥Ý¶v--Ó&Jôø¨éˆïFª1Ü`½޵w¬ÔhYo¶0ÀMÔ; ‡Ößg]®…@{-‰Os[XFFî%á†Ö8Þ‘ÒQoVŽHÑÚ¬2׎$ÃSâ+5EWþ@wI3’¬ Žç¦š!œ`>Ž[‰¬5”4Í #mBÓþ@áØè”t  *<7Œ Ó+òш¬Q·FW½1ÇôûOŸ6G:öAtq¤®ý,d+ãÉ8g¨+ÃŽÃáF·§#|]?WãÌP¯ýa²ÌõRŠ@VŽÙÒÇWõñ¬*#ùøIºHë)™²€À @W«*EjŒ‘a¡d[GνÌõøøtÇ~É ˆ1Äͪ.Ó�Âý g®DfîĦëêÑt‰” 4yþ§ *Ë9V3&€ç%¨ËõÏ4>²›¿¥|0ÜdG¹ËhD扜yk`^—ŸOzצɜ€óm:ßÅzɪ&ƒEXoí ûBtô(Vþôæ&Œö”aþº²âv<¿ªŠvksb$qZjÔ‚¯1X)qÀ8‹ÉÂ[ÎöÒ¿Þ0^o 0Lf[HG¹ fn%˜€²[À¦ÃMÄ3¤Ñˆz´þò‹!àC“²+8Ò0ì¨TT«f UCMT­%+¸qø÷AÒÈ Å+㙟đÍâéHДFô{¡oTžewLè)4š›²Ýòôï. ðô ­„ß’JÈþmæµ`tñ4ýlóýó²­V%N/ÓàáFD ÓTµˆ‡•ÚS9ÍpßÍ÷aþÀ+ë ‘ø6Ï Ô¨D)7:°µ ’v÷6‰¹•“Ú§q”ùãûi2Ŷ­QW¸í…£€å‰݃ÈÜT™”9oœFÊÀ ˜7|—ÅàY5H jLÖz‘ͪ±}8è:.€2© cj‘Ï–:•\3ÑñBƒ’,š_/r&ð”ñô5ªÂMO‰M ã j©„1¢Ï ¶ù~CUê.°YZdâýŠ ‹¦|Og7æ>HL¿ñ Þos&Ì{œV%æã Ím¤–”6 RJïˆäàc†3”éS ³g*üIDATÃþÕ!z·ï¨$þßvn•&hIÎÀ†ª2dÛDY04ŽÆˆ”@sõ‚¦^„ÆœNÖÝñõêÂSê wå) dÈA¯ðé é5ÒˆF ’¾Rž1zÃŽZÒcêÊN,t! ]É”0 º¾c‰ìH¬=¦•âµ5â×Û›8 ëõÅÓN¹cú<ù;ª.+’5«é=}TÛG4ÚJGY8+…Y)eÂYµh€†À_§Ï/¯±P¥Dʘvà7QÎvúÚ57h«´lIŒv‘n5¶Xƒð•¢?ÚÃÆUr߬´pý6˜[Uùšµ}Xª”ö©nI ™*ÿÆ)5±/s›w‘Jõbzí4ÉÌbeÄK e¡7 kÉJÀH©Äsþ?„Á T5XsŸz^Ý TÊ h¬ ¬ñŽ@UßÅZL¯=1œ,g“›ŒìÈ¢£’×OlDV@oô¹ä÷æZ2ä@#rƒ•úÌC ´éü×¢‘ m×}7UL¸nå˜Gn4¦mç|š>þMÄWj ÿÖÞï³\–°’–EOᯓİ)€*,ëÂÈ÷%ñ&¶†œ&bÊ|dÊÄxÇã(ØbÎ}¾—uTÍÊÿ領áq¹Q½^D†H¸Œâ»ñj™t/߯ÞЇî¹ZŒOV|´È4•øö”ÓZºÎ6i„*^Ìœ!,â>&í”H9+CAP ŒÔÂmbSù#)áºâék‘ïØÏã;´CCuµ€c#0a€rG¤pL&{†È¦Ã›"”Z€À¸ÑSÒÃdñŽ{xцLÛZTc&ÃcZ²Í•ÇðIPÎIV/À߯é~!Ô¨„×’¦‹À>/ ǘHO–8«J4xWcž `ÒUJXn’p¤¬ÝQ‰¦à³.@PfBIS6E¨ÆŸÿHÐkÉúkÛG»wÌ¥1rÇuÍ´ìzŽ0O†õº RX³µhDV=“*ý.¦êHÖ·`«šUUÎø”Rêbˆ¤!h%ã/¼ôR¾šdZ4ŽMLj®ÐþrÜæ˜69Àµ‰ÙFšÒJ èWMüÎUBb(-Öþ]“F¦É¶Íé‰=ZÓË  p} 8ˆîÕ¸ýí’¬v]FÈ ýs ´óÌÁžŽsÆëR}š™ìv›®—Œ Yª–év° iÀèðÜX í~‘ñ×ïãYÕ“¬šÂ$l4=CC€Áw”+!×EÓ È”r¶r¢×ãp³Ï™÷Ø‘&ܬvð€HÒ ¶âìHæ¨*rvµ7NÆ4kOML“a»921«®mî+õgï»yC ôbø`ÌÊ0 U²®³eº¾Èíõ§ŒäfæŽHUÇw4¥A ­ÑëÑÛÓÐÙhùaNƒ•€fµô󔕼Ïi¸‚‘-C·OJU±†)“Å!já`JL$YG-b²üÁ4¤Øêµ9ro•¦Ö/˜‘‘¼Fú4­‹ Çg˜CÏ­=A&m‚Éä«Ò{;™›.¼Ë D>4Ä&*!›u럯x#🌾v$ çÜ“àoÊé¿b@Iî lk”aú~BàLÈ„jCUµÇÔR;2ÆFÐÌDÕGƒÏŸ²Ò€#¯c ^LVd ØJ }¦JHú¾°–|º1CÖϬ+óJéA_—Ýú|‰3W⩱h ¸ÑíßCÅøéE {®`hs;&Àäm°°¿jK6.|\.?PUÛà %Pí( #dK %Ù‘'}Œv€ é2Çô\é‘g×gÛž‘•v|] â¬î;¦$ÒVm¤#RÀÈ@d;`˜`ÊdØÂi0k!€kl˜-ÆQcŸWæÝVr @¹í¦ºõÞ•²m ¼#YæíƒŒ—{¨Kœ´w‹i=¹‰9gE0Oþ­Š4¢Þ@£çæSÆðQeë.J}ôÓ4næí Åǧ’H/3L3 z~:+ÚP,jËe¾­’l›îYWÓç`ǰÜ5VT…Þ™;²Ý>+­caz²²U¡‰ßh ½ÑHš€–½Bb%d?*>¤v J4€|½éMÔâ)4Žz#14ªñHÇZ2¬ºMh`Y/ =l®£Ž0}»UJŸ!¥ßzJdóWï¬úÊfNpƒ±mÛ¼?'ðÄ홳¿ÁwqUKæŒZÃɲÂw¤èïY­Ñ}ùPbd½µg‹TÅt¤ç²Ñù4‹¸H?“œ‰SNL@Ÿ‰KÁ."0ÕnazL]Èö!ˆ‘5¶¬*òúÂèêî‰[Ó Dʺ¬¡+©}šÖkCdûð!†²ÝÚyJ`߆ïϵ¤^ È‚•¶‰[i òN;¯A¼k¶sƒê%Pí²í™æùüå2«&ÊJ4¦'FröEõdÕG¦ÔFXOx¢š¨%An ÚÊÿ¦ gÿ²dx]45Ƽ欴cò¦ ôceÃ4|)Û–Ò‘èRŽ1lÃr²1@[MIÐ L¯‘oÉÏŸœQ¨F ôpÑ$8ÐÒ°¸}g'€•1@Ÿn²º`Õ3õþ\õ…PÂ÷ Ρj/S»œ9 rk +0^;ÜbŽÈnמ§óîÙÄV¢zå®P¶?Ÿ0‚f_èF[OSèÍç”UyÊFèí¯*sh%€.%£a™Ík‰ÌÊbdº@,”(ùt”ÔN&òlt× W•›¢QûHš^UÕ·?{ZÀÄž¨YéiŒMˆw¤ì‚ñrƒd+‰ÉºT-S{ÎöÉÁ1ŒqÔˆ¯S¨êõcßþHGA¯ÝÑ |ÓëÊ\®$Çè¢o"C·p…VRò»ãX+@¤0dµ8c8‹i`Áî‚ûÖ™Þ†€®9 {s-pæ°àÐVo&BIK¿P{¾ÚÄŸf™FU©Çæœ!YãäZ*ù=„ËÝ%+½]P#ìSÏ\K;L–RV’ó©ª#ô ¤ìI³‰ÍÈF8Æ´^&³âC–òXß#=ýþFƒ1”Œö¶rwd†öÄ÷óÓÐl[›ÀQUÀŽÀòié•R(%#pì“EŠ[?ß -"¬d+èÅ0ÌJ6®¬¤‹¦–¾ ðÆ]×c+jW1ŸñL‘€*¾c³5›•ž¿Å”dÛ^ã“àÄ0e¶ÍJ£*Z¦Y™ðqÔÂÙ'2MæŽÝ·×ÐÒ•yfÐhoJKv$Ø Õ6L/«’%1Ž‘]ÐQd^¯MÚ§…´^ŒÝ([¬FV€ŸA ½£¯å&nDÛîhb¹»{œ^•¦êÄÍ’-Ã\î:²}:ÂMÑ ŒotãÚŸ31,€ÿ¸Ñº`2&]–çª^5ÌM®…ò׿[Ø*íî&mЖpýEWBŠºð@U°¨ à­bƒp«¨"»çù(ͰƒÞ¾©ŽÝ9A%ŽEƒZ{悔oCÓU“i2ÑÞ1¥tå +õc€®©1%Ýd²”JE2klO>z9†0å}¶2}U97½ñrå׳*‡J2Þ”``UãzêöI¬ÊgVz۪Ɣ]Ók8v]0 ÐíG¯GÉÐE#+ ÂQhICä(u_YIVÂÓwìçíz|>JU%#ú×Vµ†òWXÉv9Ÿ.Ï¡ß,[C©Šy•Åx¥Ž²ÌU’µÍr„YííFœƒ’mk'F6=™Ë¦ض¶£ ç–³êRŽ€lUž”Ý:M;´@ãTçC/T_·.‚ÔN)7‹ƒ’Ü’µËªç¡¨I îÇ “±H\¦üq4Û„¬´Ðn*¾ûhÁ´(б¥÷†^û¨Šº€V¢mÕ¶ `[Á$2‡âç 0á@YLæ—‚ë¿%ú>6|Á 0N)ç|L0[ƒ)Ô‰a¢EÆwÔ"ÇWÒ‚ÇÈ}/³’=£Š|èçŒGÊzûQTåÄls–ÉrS˜|z[˜C2¸M2—Å«×ÞJ” ¤O<7ƒ´0ÑÕИ5ªvq ‡üi`L¤¬] P’™‹þè¥T6aøˆUÉúL›k‚–QíˆáÍDd¹¡HªÜÞ—“ñ¡!׿ܥ5ä^À¿ÜÜiZµ¤`"ðr[xnòû&øöäáq™+ëøô/v©æC :Vò€¦Àz'C£ „c€R4]U8&èú·õˆ“øÌ‰;vS⪕0‚ƪýÚ‰±0‡üõÂø]DZvnHÿ­OǪZÚœÛLÚvš@æhtq‹wl  jGz²&RÚŽ!HŒ'+0„i±Z«v…Žiê’›EÙ±¡²8ÿ) …:»-uǬyíˆiÅJ¬UËLUnä4Jf·ÐÂ\Ђ|Ü‚‰PÅÏDUôÁ)‘iüÈ*ißD˜'%UG°êxíÏwÓ XI‹0Y‹¼õÔK–!Ð>?Ì”Lc½zËHÀǦ‘M”¹éþ€·Cd³Ê”­JŒáCÏö+•^`ò'†#[IµÞÈ2FINŸƒ£A?|,Ðt¼%i„AíÔ+-WÅp†oñƒÓ¬¥ÝÈhÂ2H£=@¨v÷–t´eº0°ÚYv”·™£ÌP®Ê$Gd¡ÑxfÃ:æ6ÃdiVòJHXf…W]à#›R&€ý1C`D)[8¦v82A&r‘U䟸G“_CÇ#taä–Áë­èj‘_M%zä±ó§»ÿ‡ååSÁ¶ ¬³;$uÌšÃ>Rt“1€¿)ȉzØÄ†:#û5«ï÷®‡¡”‹º2„—çVÉJ)UM”3‘{‡˜Jpûß«|~–Òç_V¥Ÿ­YMÑ[ãýƒE#ó0âôÄȶR¢—‘ýcÐt[Ï3Ò¨Ú¼.|³è9;ªŠwa˜x&}™hñ;ÜX úœ³¢¤á@v¤ t(àg ØÎm…Ϫìhœe.ÞOoUžªÃù ÛY ©W.”¤#b$gƒÖÞ·”€¬›ÖX®1?ÆÕúºvÙfµƒ}º{¯ÔãòÌ*O9’R0Ô»qU5QÙ2ëíÖ4þ‰ÇŸLø^OO,oC—m¯‘ƒ¡zå4²v%2XI{‹!…£OêßÿE¶[$}>ŽM¡ì»ájUy¶q‘xzŒè“j¥ÉªWb…—ß®”›B&’…k”O¼{YCI´Œ·Ïx%zǘ<1íÜ·",³ÍJæÓÑÚ­^9Ã=fÏ¥åÆQúJ°räc12%Œw$Èö·¿ÿþ[ åŒ ØC'ž…ŒR¿ 5ʰ’^¥Ž«r94d˜ôp_ǵ¤!dºd¼£8½c MÓij9w7- •]2h@ÎßbóŸæ8Þp4ÑõÁÍ‘XV—út}‡ðl‰•ú«bÇUá.µ¹€˜gXž’ Ü¿“Ïlw„Ó§¬³k¶-’€,·¾µdªñÉàÚ#³UâÖƒÀ«‘ÌP2®*3©å‡c»Ñø,tuGG‘OOIàV-:ªš‚é(‹Z êÊ–lô»’–ÉT5:Ëa†é1ÂQníf9RŠÚ‘<·Ûx M‚í/×(Ã-kqkkÇ!úÅÑï‘íY—Å(™ÊHŸ’ ¬½[˜ë(:7¨¼c]r`zS(mu–û1e&s£‰tpæJµ8âÛ\/R";Rú)‹$¨ŽÝ1Fî¦J ²ÚþŽÆ%†É“dr]eJAPnÛô­OY×H‰o.¦AíÜO.œg›'Τ}ÎÿÜ{†œtOi^#[(¾cãó%ö]a[•2O‚0¯Ý–[F 8¢ËÃõ¦)W¢ìº­ckÂçäØ&Ž™4"Ég§#s‚¢²#ÿ@>d‚‰Þ^?FµM:ÂDcU)>°:š‚Ôøÿý?ÐëëKß:ebG%Z% d"ÃÉd %k1ʪü™(Ù-+ ½­:æV¯LÓ8ŒHÙ¬ŽíC™¬®‘f) =@&s&H¦$hòY/ ÿŽ#uQfΙ€LµÛͳŲmÖÛe‡VЬ«=1ôµ°uÄ;‚!2[]…*À(üʆjr9Ó¶<¤–ÌÝÈ¡ßþp;¤Ôî˜XC‰ËÐn¦Ð·Á6ÉPis³% ‹ìÙ­´šU»RÏ’æ²h–,S %—´j%oŸ%]p+­êˆt¤ló˜v˰Þܘ$Ëá¬òý‡ŒRVH7…6_5ÀÿtÞ*†FhÇT²Õ4Èœ)ñœ•D-ÖkCOŠ9¦ßÚЕFÖ(sè­ZãþñÇùjø:1²hR¦4™¶™\—\¤çÄÐ,ô"«vU¥”ŽÓ'¨¤Z©{rÀÏÖEóú„]Øæ”s&Ž|”zGÀõsÐNÏŸ–Üîom®‘ \û£‡ûêŽlÓha‚?g2QÕÎ1æ;òQ@OÄß-¸µ”ÉT[ ÐbþI/s3® ëBõªj¤L<žF´p`ƒstuïípÎpÊLäFÁEú†+iÌ37†ªÚ9ÀØ›$ÓHÖ1ÿL åk«ZÌPÉwÀQÀmë g•·&Ê-Ó5c^½®í`ɺȚոH©$âí©wA&hÄULK¥H_æYW)ÉŒ j=Àw©’¤*¾¾€v3!€é d½øÚp¶õP¶UÌÛãCÑÕˆ—ÂDÊÈn¢YÉ­‹XL©+¥º¶È@¤\ï×õ|Ï1¬ˆ‘ º&¾®xšõמH˜@IÀm¥Q8f›N¦ 7¨eÕ>YÕÏ¿ ÜgÓm›A„Œáå(²ãRÿ6ÃÇÆ§oĬ´[]\§ÏCyV¹Q/·Úk9cnä®EnÝ™9†’ ÆÏ–•zz2 H¸8gâ˜d™Ëø°+Ùâ“á{´^#sUGªr¡Ô ¿ôù¿ñ1áîÓV¾ñ37…Xµ»hé²É”D8^—#cºˆ,ðL¸áOó}¹Fú¶¢D¿Âó¯nõ>ª»u-²HÖ³À‘‰Y¢Ý®÷ùìZÛÚ1‚ q$q¿ õÚœ¸­r#n@ÙP LIÎJÎhOÇía %ÛÁQ¤á©ÔßK^+#úŒ`z¹‰0GËÈE%-­d„HP#G(·y¤#ÒVÉìÐ¡Š—Åô)í;(9–1}¥Že<À0ÅÜÏ}îõm…t…°œ's²­V‘–É|¦”s&²ˆ±Ozšnу8ª:Â?ƵXÛS=³¿#€Z´GGô}1ŒÞ=•v¬Z ™£ªGÃôµ|U[p¬&€‹p¹|>á&µuTÆô%XA2ûÁæz…aJŽÝ¼.ÿJ·gêbJ‚mGzGyÇv(#ù0´¤l¦äC zøИ²”0•Äȳß÷¹óQL )€ÈkÁpŽº¬ÔP¡«–rñ•äÉàî“aL_JG³RÞ±LàØ¯<³D&”í)‹ÚíÙ‘&²ö¦¿%žiäB ìa ™õ0é#åx˨:Ö’ƒM¼UL³ ËB M¶2†2‡H̪™¨"åþ«üªµ4‹¡ªH¼UñÉ”`íÖëmY¹HûàíEXoÕ¬8¸#òšVÕÒ‚6Ô‚§Tê¹êr+Áñrn¾o3!Ó›F&0Bض)…vŸX×®Q’….YIÖr¨-àoÊ+NPN`–£ºl+U…«‚[C÷ fÕ.,Zä µí)MŽJœ@h¬ xÌùh‡Ó§¡ÏÓ±ûÆk÷èE ªnÛZ8Ã"+2šÙª:v#›ç·6=¦Ô…7Ú±+· ²éÈx[}þhv9f7ÅHÍëG’ ²Jæqº‰ª©ªF(QbÜÆ4Çèî)›5Ûd9÷+5Íéü~A‰EÇŒÿñjÖh%2ƒTëícŽË½…%ÍJcUwш‘»ûºrîXêbˆ\‹’#(`žp£_1̼…c„}êê¨ÄŸßÚ2RUnùðd™d@´`¦gõ® CÖ^Ž„¬&sŒ×œ§R#a|²rG¼FLÙ3ҋצDöàô1™7Zî.J”ÙÊ;ÂB¯ªA0½*fkDš’¥@ö=ßÇ]#^µM€Mg(TÙ ½aä1Opw§Ñâ˜àÈ\&¨ª®«*¾å³=M|³}{áŽ)Í1Ä¢H }€ÖI¦¤Ë¬ôðÖPMÙSPúû«.ñf!ϰ{‘²’hâ°Rþx¤åfÉJg%šMÌ Ó둽/“ÒVV"X¯–l145¶’RÎL´[CFbÊ~q•SfXWÇ5ö†L Búwõ€× ¹qz ]€®J¿ýóÏ?Q: Û[—Ÿ)RÆk6F&V@hŽª\ãKª&HSŽä$f¥$3,ƒ¯cDÖÕÜH{Ò¬—,%A⦤—Û§q&}ÿ¬&€e¶>€3z¶eüÛîÖ×àó§ý6¡ÉV»ÞF#mÕÎðÆQÒìM:’Åð¤ÍÍ™#[€@TÅ $Hù¶'CÞÖÓ›U+m%L]ø¢…Ý®‡BrÈ ô6¥^¹—T…·Üû`j(]?+@)s™ ™ Ó1™Ü›øÁûG%8“<™ó±F£u‰ÛqR`È`=¹¹UM¬šRfØ”‹Æ)µFÿ9±ªÓ˜É“øªjÛmH´Ëº0mH¬·•š%s®%0>°€|äÙöÑ¿&û黽ëÓ4E6¨Ymk%‘¾ö my-ïa‘“͊φ"aƒÄç/J(=©“fÑ/÷Ùi€5Oožß’5ª4”¢…šýbâ|"{)íÈ|0=J³`‘çzçÔ%G‡e¸XÅý*OUkP6n*¥ÀØIÐî÷©ÿr R•&†OGJ2Ç‘ɲG¦ÔÒWpëÝJFpS•s(Û¹ÞŽóO¹Ýð=BU7HIÌÙbœwÁ³¡Ø2Yaz™‰œFvÓ|`V•zÀ¨ŠWÝPi±v{™ot‹Ù³.%†ù¼aB)ó¬]ËûWiÕÙj§4qân=Òb2&•`Œ¨ÄM{kà“ú÷ñ0­m Χù¾<íªšç¡Ab®ü$Kò‘3´i`- `2Q© 3WBšNã¨oÃv¶@-F&F²íØM¡ßJöµï.ôdp™’¦M”`%‘Ì‘¬Æç)ëUð41Ž2OO#׈/‘žÔÑ”n a$PFò)½•v³úbPâûš½øn§Š—ÍÊŸ#¾ÑÈU‘ŽBïdùGÊü'èH ôò>e¨²‚Ï~m»•*\çªÈm»ûAfÝN2¾È!^'ðCÛõ˜ ÃdªJ穚™•ìÅûbÁªEU]‚­õ0dp ¾vÿj|xõŠªÄ)-€d‚‘åÄù«:/7S©+8µPZ>“dÝ…Þæ¢”„¹ªJrΪzFÕ±*1,ã |ܪÓˆâ-6’Ÿ’̉a›?|f_£ #a›7= Û¾o-ãXW†¹µ9}>4{a‚3æû¶À|t…¹Jö« Égßv¶ô݈­HÀP’#eߨ¾´ºxúz¬ˆ¦ÔËS/,º×®‰Èü ô–dZ:jtGbkÄ[@@ĵÈoÄc½ÜÂF„çHœî¨Ú3ÕÞ9G½Bß>JÞð®|þàQÍA;™–c}­dbÈæ>V)ÉÄiû~ÿéÃÇ÷û{cŸŽ-&×HÏ ®ØSKw©/üg^ˆ­A#j”)s„–ªZâ< (%pô21ž¥õEseÇd”¢êvèM™9üÛ_ýåÿTÃz„c#kvdMÜ`@cÕô}{0¢IEâéÅð˜#ý®„,"›5x9r³2}Šw,+1eb< °£ý·’O1^öK¯Ñ߃joJ½šg¶YͰÝUé…FnÌeoÕJÙâ¥b$M¿_´ljþÄlûP0×þóW$X e«®}$ç¾O)3Ï™& û.uÖ4ªH%]“©ZÆ“V"-VŽ'6‹Õñ½C³UŠ‘)Ã`†ŽdÝÚãÀe]~ko"±Ò¬ððªJ1Üy{’õ ÷Ï.LðU¹i/ZOiA\Wb9Üo®Ž†Z{ŸÝÈÚåÛ uá»  ª>MU¸Å]HšJnWµË¶ fA9q¶Í%À»KϾÅ<%6¥Aõ6¥^I3Y¯ÅG‚â,ñýʵdïd˜2[9P—h" ô &¦ñ-S;²ãuý|ñ¬¡ŠO#¿Ëä̪㨋[ãèW!àSN–áM©—-PUn "ùùrô¦m¬Ü$¢m†<êïßpwCdö\Ç~‘9¶\‚>æ¾”Jliò§IæXµ;Àµž^8^N_cJzk×%(ñÍU-0J)5²mMh04~ƒÈÍ’ ]HÇzäÄ0^Æç#3—{¢v á##•ˆaôh™´À4ñÕãE¿Sš®™)º JU%8jåþ7d”fbâ†RÂÇîI)])W­…gÌøF´X¿²k—’iá Æ°l> àKH `/æ <É‘9À5Šä/öÔýI?¾‰ªñŽz[ Þ+UJoDWkhËl ãðŽeG]¢å[ÏGØLÉ]š¨è¹ð4µ'«ßqS´„ -Mçƒék™UÊœ›Bœ  ªE+ÁyÊ¥€ j‘)aÇFXư‡%ص+qûÁë펲P%:ˆ€,˜äLO&o÷çGãh7¹vL&-c¶K|ƒÙ24hŒÌC‹iq4S_<¥PÙrˆ¬E¦Ä 8¯‹€yVr_æý.6Ñeû²©f؆2FFr3}žHáHл9›^£c€Òm˜Œ™&e¶=/Y£iò7ëóÿ)|WJ]ûÅhz÷,d( G íʼn7£…¶ÖF¤Ñ¨Äd—ÁŸµîç×G|â²Øt YL—o(Üq-xV”òH eV²cnÉ2Ñ‹tÓdȶšP)eMÕøCÏÇ'䃗-àÏÒ™÷'ê¶L«";– ­]N,GšiÃv›CÎéáëò…³XßZšd4û7±‹Ãxš}qºHÇz›Þ>øm¥Úô2^À]ÖØÙKꪑÀxÇe qWõù¡J ÔÎ|öÑç E„É|î?|µàíÃØ­ûÉÖ»MÈ^f T  ¤ 3­'ZæÖ@‹AZâóQÅä–^h—M° _>Y•[À3ŒÜ;86KUÀÛÇ ªó1¦ºÈJxúYõ)¤¤1Nž¡#%¦œ‰è‚õ6.Û‰“õ·é¼á f>Ë-pÈrh´£*à«.[ö2Òzá—ïop ™¬ä[¤6Ô1òÊÏ\?/UëR-ƈù+5Q X‹µ•YÕUv+uëu¥Ï\6”2PãK*‰~uhô5fBÿ.FÒèJ Ä4Hc½r%&0پإÈG³MÓñü¯öˆX@Tà²àÎQ©ßYÙa2¥OY UY)ÙPËdÌkïã¯4¾jL¸sV°ÀW’•ð"·†ÆÈ²‹¨Šdr†¹ER:Ò(ÙÎJî­1GôPŽëõz‚ƒPÕV­À̰AH`|£eL¿€¦h47Ûn‘aCeG;ÈÛе÷ìRÎÖ–¹ï®’o3½`%c ”pÎŽªÆÕ.ãEWPíØòÉd<+µ;¦1®j¹íó$hDG ¥¼%›[¦ÌA6¢ v/‚íÖP>YÕՔʫQu¿¿*uÕZd$@ 1d‘eG/©Ô†HÑSH&¶EÊ¢‰˜U#5"Óä£$#g«rJUë‚û å¬ÅßáZ› =R;åœÅ]On ešÈ9Ãvv}¥ØÕ`A#˜À­¡eÕÌ•´·@-Ž€!‹zqËiØZI h ¾‹à‘0±¨7˜²£f#àŽ2A-@ÇrÇô{à %97¸AñùoOŠr‡‰”r|¿ÿ÷2nîžÓ ½){ͬbªq…¿¾¾è[ÚA†ÛßûÖ• ’?RÐr °^¥ªÇez›sˆáF†Ác5¶Oþ9à”Ö¥Q4t8e×Y»£àè缕0½*[zVJ»EsÛ@$Ó»Ò«ÒÇçã(nßùîj OŸ³²>ôÖ#C -6¼6g«le¡ª”'FdJ¹e´tµæ+5]{‰IóA[h[ï³Òô¹´I®¬ê—”–õ+;U-£ [™["ãeþ‰WjIn‚ƒ|åg[%|˜†MËÈªŽ²¡ü1HYÐ>Ér“»,RP¶%8CYUæCãvp£QIÖHóUÛözŸÔ™ôîxXž Ì<}.ÒLäæãÐô¼Ž° Ííë”àÊÏD@‰¸[ÈÆ Lƒà܈U»Ža%±.úI#ˆa—¥ñ2ª½CCwúRô-“¥oJž™3t” ¦“íXlgÕi” M–@fÞžd}ͺ;}ʦÿÌ“”K àIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/hello.tif000066400000000000000000032346661347155106100254620ustar00rootroot00000000000000II*œ+ €6àOØ û„?!@XcúbPGè-}Ä€1`49ýHcQˆðM#„?åQ /…?%Où0[3}Nb“XÔr^ŒKb‘éœüG|Òf³9¬ò5¦ÔjQ©œB5«Á'ó:äªkV‰F&±@M–’ù£ç/©¦)[•U%PÀ,bg(}Å%²ÙŒ¶‰*´Æžø;¤z[˜Ó$Ó;£Û§Sò@mÅQŽF-qËûÿ'©Wk“YþGARÅÊ£ÒY5€?Îë³±ˆ #m«‡Mc“‰Í¦=1ˆD#«¤Ö϶>9XXuÞ%®ˆMu€öºgÒêk•Œ• kxf1HäÆC‡dôXx— ?˜Øà–œ¸ÓÎòŸ[¥eú³ Öˆ1)[‚4‰‚ˆ-é{¦Ÿ£Hóôì€ RšÉ¾éRì•'è„:ƒ#KZ<Š? <+NÂ^µqjÖŒ7Èré+É:&‚Aézðº@àbá¢P‚$ØÄ “"Š,àl”ý&kJÖº&,š<¹3Ê„lº)3:ÿ#P¢(Ù=23P¦´HÔ²ê7⵨2Öä,îšè¸ë£{¥‰ b˜¬ Ié?Ï©ŠÖž¢Í‚Êh“ôæÊú 2È)zΊ.‹ò:*MÛTæÓm[üŸ§òŸ€KZv¨¸ˆe ÜRðrî)éšø…'ë¢I0µô’”“;Ȫ,™£:j÷H£jÛ" ìJ‰BÓ=Y%í jLÒ(V:¨5¥*€,ŒÀ/I nYuÈ Œ‹¯C€Oì¬ÔKè:^Â5Ät»WAú©@•¥¢“Uo:µ]÷©ü˜Ñ‰‹ÂCjäcr%RŠÃ5ÕQZszR ZŒ?X\ïBÕ;P¢ßàêä-i›!-736„$ DÞUêÒøÍ ”®hc6‹Q6½Ù’gžŒéqj2V Þ—ÂÔtSN[‘ú›ÃHCè„LùR-E¡ˆ‚ÎÎ]‹êBø!UZµ¦«Üô…hHÎîIâ4Z\Ô}ãÌ<ä?P¢]tjLŽOç§3¸’žëZlŒÇ2r)3Æ‚%µª´Ïj ´}§jÁ»¥\G³{lµÕr¦í|‡&ª C±¢Ì¨†ÈVîXYÓJ ò"Û¼ï…ÝXŠš¹G Ø Û0¥ôve:ˆ-yyö´öºå­d·Ö¶}¿ˆdïÌÁGåB”Ú‚»J!‘5ÐçI}Ãé÷õH -âgÚèYØyÇ6ÏP¿5öI˜y“Xkù6ñø÷GÚyŽÚ9‚BT‹¢À{Èø…5ˆ üËJ=&¯d¼åÜeQNïIoºñúOÛ#À[GhŠ=&‚ì‰i5°íR>·ÈI“cL0V€@KÈŽÄÌD×3 ¯èš¶ö» q‚0l œ³¬Ñú-$þtˆÞÈû‡$™û³2T HR4+‰R ÀCÔ´Ð,sFñ5”Òè5$Pt ‘6ÖÎKâRt9ü„-ç¢B“ê¦vœ8¸õØ k®Ò6òrßGºåž´îÌÚ”rnDpŠ*$é!JŠgqÊÊ"ÐYå¤_~h˜ˆBænç׳–!d2Dp•Óàb|~œ‚sEÔ„Jª›jlY/W¶@鯣ðýâõxwù{Å2$Êî­Ð½S„íYée dÝ’îõ+…-2Ñ4 ÃD:6²u›Ìy%rw€i´Æm´¯~ÝÞ¨#{š¢N'.¥‹È|ÑtªÅ%g¦­{°µ !V „b³qx¥Êƒ­‘¢fb|@v¯&O…—%¾cd`ö¶#¤8´¡6KlŽ_¡„¿<ÓæQâQt´Ñ*&€âÎ3þŠÃàµÛ"n3û™NØ—TìªÌ“ãI¥;“W¸ïÛ»[•©:Õ+ê'î7¤Z}M«pqûV|{†=¼üŒôœ´÷Hí6äG°I˼*iŸUŽžT|úyÙk+Ê?ÝPjQôµ“=TCTØEIþ^«¿§„{`ÄPksT¹tNDt×{»& ÉÉaiRJR"1-‘zó¾Ñ ‘RØYåO¥Ÿ¥K ²¤çé]QNR¦õ¸•&Gª–O×>ƒ¡‘*NçBËÚçBÇz?N\Æè¾ð:tÌ~ï.þYêJV|‹Ë3¬x¨fZ 6AnÞê8¾(@)’X…¨°,ˆ¢|ˆð8+ƒ¦U]î´ìDdE:ppUÆ ÚöçH­Ç*Dì2ˆÍÌ¥¯ò+©(‚Üì ·ë^ªDȪD2h$"Ü,¯Âh,‹.¦úム&¨2bZÁÏþÍÀ,ëš²Àšh”jPjKÂðh±(êÞpöÊàE Œ‚’÷ÊzÅœjçn)" aì7 lnnH”Læòjè®Ðô"»¸ÂÅz’ŒþÉŽÄqÉN0š†1,\Oì',¶ÛBšÓôs„®B‹- 1ÊÐv¨²¯ÇrŽ.ú“NÀùfò„¨ij„¤ï¢Ÿ‚r?B9åÞ¹ŒE„¨±"-+ÄTJ€8,1EÌXL~`-Ì«ÑÖ‚ÖO¨”ýé6+ƒô–Ðå°&mô‚Dì åúf ¢#†Œr×Áîï'œô¬,2*¨M,Jþ_J´¶§¢8—P®F%Of¼Ñ4,‘Jëtoh±4<ó(bò=QÈ•R0tÈN/ÎïLÖ«M1â’.ê…ÉÈ*+p&¨•%à $Oð@ôèÉ *2)48œ²Õ;d€ÆäËÈ…: áOhÐD.Öh}F˧L'(fbÓ%´JŒ ¶Õ‚(è<»Î~qú$2ZÆ#R6öLCP mJ@ñ#úŸçIOæï STh'´&c°©Ô]êzlQÞ"Éþ¯€ ÁÌà–MÐ'ÆG­ÈjÃ\~ôNšˆ6{F¤Ugà·brÕ ô]ó¸0n†"GýêÞ2#:ñcÂò ‘áA6c#%d¶]„L´È=XèÀc3O3åš¡&_V˜²êz'õZˆ¬—4ÿfQ+C1Œì64“491R×`¬¨G®g«£5Q6)+~äæ¼‚gLÂÉOì øƒ(6kk)K%,ZƒÔ”örØS§IˆŒ ™T¦ÅÖ²\±Òø jM{Cì¦'6ṟð%§#‰ÿÖv)¢ÎÚªõg¿,ˆo2_O™DébÏ¡% *6Æ—FjéfEuumKÉHmÌ‚d\·m2ÊzØTbò.,¨\£ª±M‚ÞäîÆçz™LŠÏëq&æ—7f€!ËlŠC‘$LþUËT/A±ÙÎrwês? þì.d«žEö©6±r%õjÅÀá1mk2»zº° ÌÁ0 X€Ó*jF‚±%Ëü¦ÕGƒƒêz%¤ì0g\üè RÇœ‘Ê]5 ½@)[Õ9,"TãÃD5ÈbLjª9QËW,Ê­ àLö3+OtÜ÷kФ¤ü!’2,¨¥+ˆ­0šøÈú[¨ÎQ´BŠ.hˆûhㆄð’µ2Tä“S$×"ÀÐ3CG¥<ƒ$Á‹¢ü1µuÔÔa¶º Žìñòÿ—ëP¦ ózáüÙXûcÂ,ò„[‹fÌEV*^{b@äïu1ðîél–b».˜y]îjMä`Ñp&¨§*z´ÆwEà `ÇIeiC>L1«_LþÉËë‹b'1M8ÇÒQ…·db_;íï}« ÖjûÄZ\uþ²æôZÒÞ‚Kzâ ^Aî¯è $Pñ…Œ2,à`ÊER.¹µ“–h'ÇXï,‚2Tþ4Q"„îw®…Láù‚6lV ênôÌO3-o‚f‰K¡ÂÊÊ‹9) z±"~½¢ H°í«£œŠÇ'ÔEFsßXfJ– Ã!b0>¦>¤M3>ÕO¡OåWy%Xaö£€´úvS [eƧ+Ø6ØJ¤·ö™IN¶¢rò„(‹"$êš«obòþ½ HÈîî»lµ–ê`¸Ó3n.þvP+ù\(ƒ_Íx!6.ƒÂ²è‰ %Ù$V%E:¥¤¨dX$~9_'Xí¨ØZ· ˆæ)*–»û=Y;vp ‡—\§*ãt…Aq?é®ÈøˆþWW‹Éw¸-~ÉǨ™ ŽúöLôó¦©-í4FA››?¨´Í '±J ¤'68 Û:G»Ì¼NåvRãæ—ž,©|ðݸÆ+­ø´ÏÈŒ(îwx2dé.ÁîTˆ(ƒuq~î7 t@ §C;x¸“%1|Ó®ÿb9,£í±Ws"#Ùô3Qˆ‰ Gý¬VÓ¯´‹Aî°yq9™I¦hÆìõJQ\]óç©h|Âa¬iDq-ªÅ—t§ÕV$6h,á”qÖP¥£:N“†ÏLàjUŠX§ç¤(˜ –Ñ«µO°$[ÅgèdMÈ|cý,RFT“ð\=‰…pN†—>uAGk©{Cm*€ œmãE4©‡“îÀŽNòG¥aZU”ˆômuGÓ­ðºr01ÑŠYÐW’²dJE}FöG ”ÖfÞÄö”\=`ïÏ> à 2sºøWÆ"rnü#~Y‡•Ÿh¢6x»³ñ Èæ¬óÊSk.…ƤÄÏG„[ܽO4aòÀ²Ul©³+!Eße¬ÍÚËâ9FÊDÎùK›ûé™Çepد˚;³ÆrOV°Sa¬žhŒõTƨ#Ýp¢\öN¦#ìmºv–>íÔŒåPc:aeV”®äÄ›y$g  ‹Ñ›É–Ïæ‰å¦TGd~艔$Ý“Ã\•Ûš±‹Zõó»V³`Öm·Ëh+´U!u%L)a‹ü¥¥{m˜|1Äzúƒm÷a‡s¶pêŠFå©B©t<ä¶.íŠ\ȧ d³‘«o@· –iË=-f•¢ó+§V© ¬g´>XŠE†jr€‡oò¼TÁØ29ÊroföTZüH$‡È¬B’éh%hi»'&t…Wn ô|ÿSšÂ½ú©U@:bÓ8VöŒ·wþ)o³"¬\ù¡úõÐÓï,c,ô'‡¼x)è †hpÍÆô¢ˆEWÛ…ÏV¦öjÉ('õt\T™bé8 Àh%òŒ­ö‚î­ŒTöå½}ØeÍS5Q—w½À"ö™\‘Ä+ÖQ  PnÌE¿£4õ ך"Ó•œñ=Æ .µÆ Iæ+íµ/Ô I‹«‘׊×"ãͳ‘ýžã•j·YÙ<Ê­ Ïu´jÖb,‰^c[²Ë6 o}[3ú¬jEîæä°@ú‚Júl\×\>³êÝÊ"¼‡ä%¬3µGT©Ì?Ô+‘j?5K`ËPqÖ}»=u(–£á.ØLx Ø ÿÁÀ˜ ü‡AÀ¯¸)Eá +üGã 8“îCÈaÏÈ` ñ-KãïàDÍí5™‚%r×Ä\ùŸKÀÓD:W&ŒÊeozTÞSž@äÓ,R”÷ˆJæ1¹5n(ú¯O$ÑhÄ&KŒÆdrhÜ!ןQ™4†G1˜‚¯Þ‡*†Fãw(¥f g„É¥sÉ) OŸ8ˆdÆ3o¯^Whüó!†HsÓ™l†!)žfŸÑ¹\¦¹[ÇKð9핟[³bá4Èv¡¹½ªÄ YæªÐBkùº;+©€mp8éÅ-°]F¢CÇü\¦ægP-(ÜÇ$ŒÄ$ÒŸdRWÆŽÕnqèÿeÿð뫃€"Ëì³È2§c¸€Ä:‹:Òì íÀÃk ¡#® þ•£/˜½¦h€ñ3h»Â¡Pò>ŒÄnB 0ˆãšçO\d„«JâV¤i z»A,4) €î šžÈ‚ú˜´¨rnÈ%2\\þ ê‚Ì„¿À «!;Oܸ%p"¸1“*Q²(Ø€øçµ \–ü>ˆjÉpk‡PsÛ.ºs‰4Â$ÆFhc &2BÎú I9¥iv5©LIC˜ÂŒój²#«Tµ¶“ಀ.Ú>¸4ñð•® B›ÉóKd C+b蟪Dâªèc öËJ:Ús}sSD°TÈ»¶áëo&5Áý§”Ò =è:xŒÙÒ ¸5°¥8‰Lº.ºÔsü7hŸ‰½¼zÚ`JLÈF€)Öriþ‘³ *Û3ÑÄ:~¤Ö áOËÀ*Ö¹7PÆ®uDa)2tÌ2Qöô0Õí1GU`ŸRSIÁè,±AÇõê(³®“£¹£–‚Ðéä—P2#»S«’4B§"êª6›à–=[WL;m 3DÌ~á³4.xÏ$-Z‰ÐD€"|–§I¼´ç iN¸%l„–“rGì£f¨wž«Ïl)S)»ºÿ£ Yò€¨×)¿Mú˜D¶Lxá"þvsAÃk‡ J©*Zf•ßÔ` ¾ëûb;b ZU­WâÑJ`Í’DD”:` oe ‘ ‘VÒlO£ñ ,ÇÄ?ß ­‡‡­“õÇóNiÍ9žÒR„ Pÿ'G´•澄ÇSÉÌ ;óŠ@‚Z.„I•™ò:J\ûhm<‘•ÔBMC¢6ì¾6¸ôΓ"5°Y%À`ÉIl*®ØŽ®öxøHÛÆkb!òö” K2A<ÈÌÑù;Ç= :W`€ ñ<-Ùràë lAWN¾³ P„yŽ*Í9øj>Øä'U„P‘”òHbª>D|Ì(u ÊóýÐ]‚±„µ'Ô|k)È‚¡F|w‘)p&$Ü…¬¤ ›ÙºˆAƒ 5ŒùžÜ]Åx˜¤·2 ÑÞs¥œž7ó*̹x•à :Ì×ÂLM3Œ2¤u9ª™L?àÄÍ#.ÈÑÔüAMèÜ*°¾_ùؘ’sp(„ç¤dêý‡¯(ÁbVMßK©pNr9•Ê?æ‘»g‰e†Yhýo ‡ÜÜ"û”&Ö¸Ñl§?ìZ'À)pDiom¢F±þkI !` Q‘x°‰‹š—£ê0¡ºVǨ%‚. ~3D)PXÃz0EÞS¹°Væ9 *ªÍ5õàÐdáä €4úP ãU ©- 1%J 1#j`âgò?¡Ü|´¦l­`Á lÅ•ÄΖŠé4>Jƒñ¥ÂFR´j6JnŠ€ZÇ«€ŒÔ_¡µÙέ2±lƒÈ–µGÌ‹YJ–޶DÍ"âû‚ÓÉXCÕ#òF±·ÒƒCÉ1ƒÒù‚ÄA$²x=3Ôúq`Ï[d ›d}0 rDá](d«ÕBI‹$9´àk¯ ÄC¤'¦ECû‰¬š7 ²”­°®•QCB‘0è‰Çs‘@g`Š{?¸Å*ˆo‹<†÷|}Ác[ cõd¸*T¾ãÕìD—;£"ö< ¾Gñ?Î`à¬×¼´r£³‡º‰è0ò¸%Ý!ƒË“0÷gðúÒÍ–èßÁôò™!\•:‚8Gþ{ÉÊkíp·ŠÒHö ˆ“{ê{±Q:D)/î­Ž ´Òðßd2ŸŽÇÁ@°fDÿšÒ!Ñít»Ê¼áríi­2Å~Z‚àqgÆ0"YIÙ1j©ÊKí×.í™ZmŒmÙ‘u¡d ÍëòB6üS¸&{¥~;dë¸ñgké·*bûB4&›0Ž|ž\†C™gÌrËR&UM&qš–Ìc¿U9jAV˜.n)Œ º³YƒB暤W%VO9]A'32 ´+}Ψd~¾dCŒCÍþ«uׄvºûË®ÚÌ5þ¦ÒFFíšQ¡¾¼ö{çÖDŠ®¬ÅJ |6´HɼÿD̪®€ï0# a­? °c£ŽzœµiDú¦+̈바XŽŒ€€| 3Ðz #±™m8 *ôk^€”À!Œ'kó#ú ;b§®cÁ3x•оµá ±æ¥Šá‹'£ò-rˆ²ªš¨ø’.)à óº0ØŒ½¨Éˆû,€S«©(Û0°—¸ €›¾²)ˆƒ:(*¯—±9±À¡;5ø˜¯H¨šb¹ø†;Bz"D"ºe€Q`JÜ jû 2wº‘ #!P €ÈT3é‘'´ªÀÌ"`®3‹¿€#‹‰kUÁ:˜IÍÌr`'9å‡ÐþŠê+`Š4y-#‰Aâ‚™£À ÉX›ñe/É­„4ør CÚû=c9$ú딨þK£¹ã7 ±Í¾û`8¢>•“óšÓ›³cLú½óЮ2ÊDÊåj.ÅÔ4˜Ê» ð¾:Šªœ›0±sÔ"á-±Ž*ù ämrÏÇ+í¡[­¹ ˆ¡½¦§5äKBj½Ÿ`{‹ì?: .ËÑIí@,S¾ãXÈØ"Rf½3¸¤ÉF¿q`Ç„І9ÿô$¤ ½.*•xï ª«žK󾋛½Ø‰ºz°¤ó0X——ó¡‰Ó‡="þˆ9@Œ`þ xz¬‰zµ¨›ï 1SËØ;ò;zd6¢Ð(š 7p}¥¡x¾¢FR BâFÐÆ.¿œP}:Ôô©ɎóiÁ ›Šªz+Kß¾Û¦Û«ÛK½l Ô6?zî,ŠÛ‰X¡2š»a)#+¼Îª+ÏF饼‘‘ áå&,Ì{ÉäÞ˜’åJ›h“q¾À’੉C†Ôú ԽˑŒH‹ÇZ‚΢G˜¹9‘8,‹7²‰¨‹qŸ ".lq!AÇ òQM‹ Kó“¸Í$ã',ɱ.âeÓ<8ŒÆ¶Òɯ4T¬œñ>LÀÄ‚ÏÅ›'"‚b›š®TÛ»Ô ´@l >ÕÁ|VA ¿.AO;샢?+]™ŸP#Så6¦a¡Ôm‘­+’l™¡è,vX” -8q ¼µ$­s·Ð‰#­|ÐdÜ€1ª¡`˜’è%„J s¸êÉãkLN¯™:ÎQ)lºÓÒž±dOµ#`ŽœÈ"‚Ö%sʾNBø˜L­_Z‚¿²l”8•Ébz…ÂMššüÄ7š‘Ò=sÀ5|ý£!d-.;dÏÇ¡Œä‡_Ó¨LdJ¶ÅÏQ"¿‡¼û˜JIh ê-²í¸¨‹„û‰Ó¡‰ ZŽîF_ôkRø„ÓuY‰n&¢9COjè8ÐùÝ4”õ Tõ™ä…ZSM¼Áš f·ö6€4Žf…{KzM`]_‹€Õô®»¿( öB+Qâ ¦ð|#ueߘ~OºàšÏŸ ¨žV«£¾v‚Á,\/œX¼jÏXÿé$Y¶Ü÷¡ôd0òõÞú9Ókâ¦=凩óè³&!°Êª:y`¹§àåsã%tG½B ³b¸ÐÍgáX«qÌ‘Sh»ÑÍ9Ä5„éXÜÀ@a½|øÍc8€”k¨]‰ŒÑá`QC˜ÝMÑÅejÎ-•5¤Ã3ØÞtöEÈ»V,<Åõµ2=Å ¸:#_ωÕrÖ ëèÓ)°$æ“ü$v!>’v½þ€(DÞ‰!ÙŽ’à®B >¹À¨ h c5"Þ'å塸ա6 ùŒ @ eӸե̛{öÛÑÀäs±¾cNdŠžWý»Œ‘°Ù‚ZÝ\V–MÏãê6âá-äÍší‡aÄà Ô-OZ³Le4ÚJÅç¨~‰¼ †ÌÚÀ’Y'²l…–= ¤m4öÄZí£p ~ˆëÞf–nÍwÕ,9Ï1b˜ä&¿ÚKQjÛíÝ\骡ÝSvDån½~ žãŽ”kFIK€pbêünïœé¨ìþ•ãQ&ØTmâEíæ- %dËKØâ«ïïFSÓ“­D×>3U¯ %WÁžJû ›Ý=g/Ú¬\z|¹!íµ^]bçœbd…›¤Í Ñ '¦çÀiS:yŽJÛV§Ç2äg!i“Ú~í=½EPÃÜÏn€|µa6÷!¸•ÿˆº.4ºÛN»Ó)Éœ^îoVâI‚fæýtÑdRäsd°þBX¯q¼¬wÚDìH Rhy“ϲw ³j¼á«qi5¼R¢;€ÀQÞš:ÇNˆ¸åc§›ßœª7òfÀXw¡6„1‡ßîê´ìÖ>Cµ*ûîˆâ‚? À(D$ Ã_Ðø„%ûE@qwÜdŽD!`¸?…Çañ—ØU –Kc˜¨ ü˜Ä$38üMû*½gÓÔpCˆ@Ÿ0D²u˜Ê!2ÈärY ˆTá©äê3™ÁÑÉœ†C(מözõv ²Bép¹ŒÍõs«B@Ué æõZ„Gãó9G–LoOšDη–Lð±[Pt ÊNbqÉÐ5:¶€a5(nU†Ï#–w¼B½^Ð?ãñǶij”_XܶŸÎ¢5"!šÄ4šèd:^”R3»§ü¾,Û#;À׌þŽHxð–·†Y!ÌDä5 ·E‚èK7ñ¹Œ†ŸêJ+×ügÓ±T‡Ä¢ˆ«|í¼hº8×£kòJÁ=à>Ã¥‰ã´AÈkœŒ·̉½È|¼§êæ}'"6â% ¬ A-·»¨»ø: šl‹¤pã’¼ïiþÅ:m*T$1¹ý¯Nªú¸"°û¶&(úQñLRì8ðëZõ½'û©Ùüÿ²1ò² ŠrŽ'Š4c- â¸üŸêò Û>gúPùI+òM>‘KÑH°CÝÇçúc;Ç˺ ƒ;È{b{6`R¦)cj‰Ä3ÓnÈ ÐüÔ•MÊT4†Å*5'@ΨšH¿;zT™Ï«Š ¥‘ [@TÈ]+WŠº'6ÀõøˆFˆ|Àâv]"âNñ zË(ÚQ ºˆZ"„"ø‘¨œXŽƒ¤&vu€~Ô‰Ñú±"éãUݱ…¯1³”bÇ€Š ·Ö‡åsÅà þðBÃÅ-lv¡QÌCK¡´Jh]7,4W¹øá©ÒXâS‡ŽHäÔïm!ñ$T¶Ò‚2«ÉñêÊ1£C°©÷~M¾þ¡»Wi}¤tÍÙ'¡i}>®´ bü&”ñøŽ_ñD@ã8Ûu£9 –+ÙôòŒ#.# £ëH­òú@°EZÇ:…Jè¾ÉûÔnS¹!òÜ·€-eû¦s@ân{&BÎkZ8Ÿ–»=¡ÉhÜ›€n…„õálÛ,7u?oO]åÌE(†q½€˜2”#—@¦iÜ„¸‡§œf¦8˜°†Ü­lïѪ3¼šè4ï®Ø×8‡ñõjQ§‘-Á{õ†¨Îb3¶õie¸ãn8tö–aH]–Þ>´¶ŽRqßà‰g}Åèì. šÈ6t넃§·lø]¢ØhKÁ‘2¼¤Y³VCåà‹®Â&®‡û†aí*¿æ&ßÁ¨.°}NAõãá pªh¹­dà’q|Î<Ë.£tÀßACc‹‘-¹†¼±¢93Œ¥â¯Bì§YbPt‰¸Ä.hˆú!yÆiÏ€–Šy|ÌeŽ=µñ ²RI@*ÃÒøc *[ Ÿ(´á`€þ€îYIœCPvùÄLDˆÄBµI‹|P,1¤¢ØB؉"ñX…¢b2ÁÀ Œ^DñŽBÙàÜŒ.n¡Ž'H¡0å!Ã2öLTŠå“–7¹äNnž˜LyuŸ.\‹šfÑ~âtW‘ 6‘Fjc€U ác–­¤±@#öB%š:"ò¨ì1Hàeãd¥qŽ`ãœBbjÄålO™ã&è:Ô:™ˆ@ŠœEŽàfkV”GèAˆÀézvæjZÆ÷Ž–æcž#‡Ø‚!ö>yˆ¼ò Ѿ7ÐR¹ÌÓ¨O¦¡r¡xžè`ùÐH’ÞRÆ‘ôMè|wh.a¹@Õj†.Ójs¢¹U ÓÛurä6&JTÁ& ÇmàÌPæ®L›³.X*‘·´J¢êc˜2äŠÅ”p‡ˆÚÞ‹Ñ–-9š›˜Ê1ˆãíð†ÂC4¬`»‰çO]ƶebb÷fm lfÀØ”„¦BçœTEm|—™üì¡Êwi}©Ré(À@ ›‰J."»Æ0BÌ:“5ÍŽÌ91 šÖnOT/ ËiûnfKTîãÓìf/ÎNIWžv-)Éå.½êŒ=!µ,œBSQŒO_ìØˆ.$½œ–,ñ½;¯ömIŽ QlÎÆfMMlEÕ>¸÷ÖÃXj0Åéþ£²LÙ®„'…·Ìm cDÁ@')¢]R£Qv¯³±ôó:q5å+’4Q½Ýó4LyÍD„꦳-ì1Z'i¼ò¥Ó´1'„|nö’Pä¶Õ[Úo²•°'ë½öˆ$%d‰Ú!óÊL0ºnóP­B2ˆkÖ‚Åw±å'Õ9 j0ý)˜9.nB#óÝHâÕ:„¹m] q‰‹èJšô‹²ò¢ !£¿Ôä³Q)%W³TôÄz§çbÑÄ»ëE«ÙÁ½™\ë‡Þ ½JÏóm?Õ¹·®†fŒ=?¶«—¶'³°QüH°Cä„Ï | ªÔµjÞZɻϽᾎ¬¾ìé‚ö1 £ÄV†DãˆuršNq(ïîžÓ/h*+ÎIô0ðÏ ‡*÷¦ZËqÄRÒŽP´pßÍ<DúÎ$‡-Îó'Tu®¶¨9À¦Ìh§iØó ˜_HLHg3D®Ñ  ;tãÑúŸò 묾¬éŠ2Žp GvgÆ„)P‹Âš:e§:Oä§æXpÇÌÅN0Èäš‚!ú–ª¸ðÅ¢Cç$—LLî ¶k«n³,zê‚!ÃtyëKDÀì¢+ ¢80ä"µK“)£lI‚#‘ͯtEoZÐŽ~·ŒJËêèVÎÒj†ôáüeˆ)‹Â.‘ Êd)‹”–Mà!¢¼ôq,pVi-(ìImd0“ÎÏrøÎé0!öfÉ[ åÎ@4Bfpê)JLMºÜ¦à]$:Ä)^Št%¨ŸÀÚ |L Óð%5Ãè&sT]ròûpT>¿8DC!ù¤øíì$׹̊¥,o‹þåp!îª$-Ü’¨~,Ï8³°sî%I“3Ë¢„Î#2®‘’Ÿ¡òâG1z›læï‚¢¥Š¦çãV¥SÆÎdÅ„&leñÈ|Ò‚Ûlº ÉêîÅÜžhÞBòBO¦2¬ågÑENdމ˜”6ÐÁç2t`ЦO¤ï@+Êå£è¶³@”Âô) µÏEj¿EGRü*´§ç0N>_k¢S“€ueä®c4pÝi(ÁÍÓ=³ÐÙ¯z­‹#8ä;;¬ÛÕ‰ o0š¨r‰çÌ8ï†Ü4vî§®õJ…刖¸R'Ç|TS25·ƒÛ NµFÊi">£6³°€R”iGB¬4Å.ÉÓðˆ÷§R’‡<Ä2B$002¥ˆ5 tSѪ@ „&|—ÈR(ÄH–¢BfW²·+«çP«ä:Át¾™”.Þ¸q½¢U’PÊç‡P°'1¬On~'† E’ÿ)¯†e17¤(ëZªu`¹G W"Q ÎܬLÆí¯Iµ gÅÖ®ˆ8]bê«4 è³àrÂêžìJ‡ó´áþb2'‰îU¦ƒì˜)€¿üë¦î"â±3þŽ‘šGŠxs1>¡ü®‚8xÊÏÀâ×C`2G¼Ù6°c2hÁè“Vó™)¤ˆ”â†R2»Jµ9ÔÁ_ EWÑÏUH`ÝH|mÑ?!t@&gî“ð!/§W H4ƒãbq`sTÀBí((ÍUg6$鬟j´VÇ)áð$%&pÈB5à:D¾Â¸ý©T®Ž !ṳ́ú¢FÇ<«šî¤ìeC7Çõ³}Jk!N6jK¬óæƒäÄ—çífÅ*\÷ƒEo¥8¯wJM—^Dï ¯â4JsÆ¿qèϸ–dÅj ´ÍEN^'0öɸ™²ËdËkRÓwM³`o3Ú%‡Ç]ï«’~¬å[#ƒl¹šÎɘ½õc (×# ÚcŒxu3ÐC£°‰ÒôUÂEi™g§“ƒuÌk4͹ƒD3²ñiÔÒŸòhêµÈþ„‰¨#%&rÓfÔ:2c)8¤¾7M³'©èÈt“Lk™'GÁe£8A¾rËS+£Z:w7Ìâ"ó z uUjûV¦÷¢¼òÆLµs?WÊ7I}=Àv1à?í+|Û"€ (Õ,wdúšÎäê°"õ×tÇÖAp´çqEñÜXŠmc4mpgWžpÒLvó$B[l3$)µ‚øƒYÍ‘q§L8"‡i.†×Ƴ–\ÊQtÕÀ™Ï]óæÁËÓ8¥ÀH“¼r1äÁÏŸbÁý­ñd-dªbŒS•sQ6fPVÉdçÂ÷øc±ˆTX$/VÎ0P(zo» Õ˜p£?×÷ˆ—ÄT&Ú—ªpÔàiT}‘òCˆÝz¶íç9Ih]$¬Ó°ÂL²ÎöUÛc¸´¶ÝaäPIX6&lÒ—&v.vSô)Œ~4;%ÁúBÎÞ#)õ*p»4lìÎGÿ=ŠU9NiJðRCg vXáM e™H猀‘ oo<Ö%\!Þž2+vÏePKösÇ%X³×—÷§Xh5 6rþWŠw3Ϊj’e¢yWuÆàù칃["Õöwf9›ŠÏž²Ì/Ã"ÁÐ\ù Üc¶®—¤è@ '•"óPÉŸ†9 –¥Ö ×"©§”r¼·ŠlsxCðÕ1Šïòˆî””p<«Ó”óýD,YD2¤Y¾lt¦`jé•F9§vÕƒ0tu*D‰õ^k}ökÌrCìJÁÇì6mÒÎR9RMҮ̃Jèçä"Ôë•“Õ±Kª§pú^a0E…³ÌsÔ×d+ìítK™Dï{VO¶€ìÎAkÓELCŠÍ_â†0îªá׳…r’ß.·¢×¯_X!Föô“ilÌ%«Ö÷H}²™w¤ÁÙ¬*4}ˆ‘IÏ‹¦yöG+væ³Y¡nc©›-æX:)PRe"½†9´Ø‘ŒÂ7~™òiîØ&«xZJŒôq®·îÂ0KÒÓ.myИSpïéT5¶s*O­Õq®BÄól8¬4SÚ&.$M Lözqé™EN ŒñPe¥É7®‡vÊ •s³Eú;”a±ƒ;"ôìÂUŽÄ›™q ¨X ¤—²c‹²"÷þ«ç›©Ð*ÔÆÑ;uH@Ì¥Á+DUÄ7GvCµc |41)¢f‚©ƒ!¦ò"'w‚¢Ç" 5âØ.¼¿vzƒ”{ìƒpL™8Çmï•”¨T ÆÄZ8…÷@¨¨T ÈP‰\?~÷HÑ„÷¶½oàè°2SѪuj†°ù<+L ôL±ˊدÕÊœ’µDyïXöQÜ4P`L DÎZûds›‘h.` «`Ç,C³Ñ`2àyvßÈÓXÄ®´ò" W<[Ê0%&Ké -ˆGãÑ2ËÐoÈ|+Ò0ïã#<3')¹õ»¥ç)±4+Ì%X£„‚§çúçìŸ6¬V 2¿À ÔîAT¢‡ƒ³Uiµ/nÑN,Ï–ˆØ÷4¬ÅÏ¢ £"ÎݾÊáèB'Su€Ø:ˆ8ú-"'}Då?Gw†D# ?Ñ$S`žt-)€RŽéÜÄŒ\¬̽=8Ù‡/ÏËI.V$ãÎŽûx•jc’É›”Â[ƒ|Kêx,NKk²¼P/1µùžÔŠ©bÛÏ—U´ · Æõ»ÚëyTÎDÅÁL¿ZÂTžç0ÔRç.W4\vË5üŸhCv—úù?‚Sƒ; ’wãVËÙ§"7ÍýkpÐÜÝ4¾i‡1(ø~Æâæ~$bÇ4òeµí¶5 _Gó ìä9·9`>Zþ–è½ìo'¨€j4úkE¡±g½>F£¡šd)†Öà“úœUA‰ÄbR‰PÑoÚçôGÔ6Þ!`8¤žK?¦Ä¡µ;œªUs®?î°Û¬«U´bÐkç(Š[ª3—ÅFþ¬Òìq‰ü« >à×<ü‚§£¹ÝeÝTö’—\åÀlÿkŸãâÑL~gw½V"èÕÏ|‚]n±Kˆo4‹J9ºû ßD ÝÝŒ¢KŸì€^f÷‹Öñ .¯­Ñ¡{©¦"¸ ýUo`:Òˆ9ž{¶ˆ‚ ·4lZ¦™,©*À**ªþ1h¤¡ïJ8ÇÚ,¨¢ÉR~Ó&ŒØ»©Nê~ÓŸˆl4Œ*êÛjÞ9Gú,·1l¹ÆîâÑ¿à+×Kªª–E’R´ö"Ì:C ¾€ ~'iãjŸ´o3p²C0êô#‚ª¨Éç㮆‡ä`Š4'ûFÃ>¨‚Ü̱iRXËD 5‰*¦í@)ã‡7£tè…ÆR€Î»Àd¼¨k. ³àË40¨ÎTD.qª.—?­N”BÈ„Ž„EòùþŸ®¬ÌÔºµà%#5TnMHR®‰ý!3)cž·N Òž%UJÑJ‹œ´*ªœFš.³ rˆ%R”a ;1ä»1m~ÅÊÀ#ŸBI‡û¶è+©¢£±v* N£LjQ"KsÆ÷®wð q¨j"ë|€1mr- „*´P–€ 6¡v¡üƒ2È2¾9ÉÝk"Xꃎ!jòŒû3PÜ{BTl|‰v*uŠ”D’¼9ò%‡(J4ýlŠMG¶Uû[è)s,ÅÞS§ ôÀ§‘ÌWq“‚ÿg1Ùÿ J«šˆSÌ"RÉÊ zŸyùúŠ*ze%wEåî‘õxÚØÔª¢zoªŽË$#Ët‰‚Ǩµ(šVËwªntÊhÅÐ5ì•v?±“(‘Ñvº ©Ý”½é,MÒH˜ž?H¥Jœü~ò(#,›S"G˜Šìˆ*½B¹H —+ÂÎ¥ þLn2—^J&±É3(ãHcô­wÛíô® {{á k í…¦s:ÖàʯrPJ"sF[žDHxŠ@~«€‹u‹xœø\‰’ë,Ì0À¤z‘Ša¤Ñ)+‚x`ÐÃ`rlš,À§TÉëy=Ž ?”e4>Ê‹’…éøÀõNKÐyœ'™‰±0U±×bj8ë¦ÈÀ2ü«¨ë¦eî‹q,v¬V–KXß!±ˆ~µ„úÌñ÷$õ™ETΊ"»“kÅ–$N™c%‚¤©¥âÜìLÌ‹L}‡²ð¶žBb ETëÉYl@Ú„™n  βr ¯ä¤Ci:5µ…*˜TŠ=QN$?÷Ú«ÌÉ*vè”ì-ôbúžl·qÈÚɸ7 Q£|ÉM¶ÒŒÇåê Œ„’„“ä1e8§¢s=góÃKJ\‚¦ÔØ‚Q–è0¼Äb0Kt•¡äñá’©F^Ü´d±v?“G ^4[Úc¥à/aâÞvä4ªšW@£ z:{Ãé”9I‹@ŽéƒcèâOÇa/`ð›OàïÉ:lïá"]jÍ1é—&!dWf.•Ô6>‰Ôª„<†-*.ª´€ÊzÏ#Q¥vLÒÄg-93±ÌÔEàJŠ­$BwÉ^âFÈ ¢'jâ«Ø+„ªD–bªí]a‹{gá»Æ™ ÿ#pý„çõL!†?§­.yña!2Yh]^ÈöJJbÎ$§âw_Ó4—Õ&¤Rvú‚ …Áؤ`x–«d¦*:]"¢sØúû©Ñ…’ª‹Q‘æ&$–lèäH#MAµ VN‚JTbm5Èá8ñüTmtY˜u ÁÆ…j‘“Õ}RïÎYÆä C¬* :ù\Rhî®´äUKÜõ‚v/>ôirÈÅ <(˜õ~y&Óäš÷:›:Ã̯È1£"Ô§(²˜n ýD$JZ^uJÜZÁ`°žHr<¢ß¥xW‘”ëÞÈ¥H£[‹.˜9òD"zê-B2Y?‡«e‹˜JËçM’¨Ñm(€7)6ü,«Øû} ÌsÈë$,`ÄÑ€J§Œ#Lò‘pÜ’ÁŠlE­Ý$!µÀ~fûYO#‚-œ±•ÉX89vJ|ˆ»+ TÀA±|…‰)U¢2Ûe/ݲ«!kˆÑ‘¥![Ž6²ÁË>¥Õ &ü–¬ÇVMQÇœmyϱ¥]¤Dd‘.Û›“Ã騨R\J£¨ Çæv,9$µà®/̓ûA€Òº¡óùµ­0¸À Äáö_IGö¹†Å‹ôN=Ì3m»°CajY±%ºç•Dà ?$J$•ˆ£ù"RÀ¥V\K£èõc9%SSklºÃk\¢AqãYs§î²M–äîG¡‰<@„²ˆîÚŒ!\~0maÖ5·fÕªö3³:$¹Ô>ômT;tŠb§#ù9]0—‡Äù£ïÒ¼ulI>V÷váé5'œ^¤R•:[Ox$]`uôNÁ°ÇVÚ‘#Ÿ¸TšÑ!2ÞN¨»È˜TY,…hÃ1ór·¥ÕyÔØܞOkТéÇhªrŸÚ­úæmøŸ–,ÞÆ*<<ˆ\’ì2œŽ¼›ìI¾#mð^"©Öö`7|e§. é¶?g£j4ÛË«8†ZMì¿++ÚÌã&v'm• 9jËTê‹bW’X˜v Ž’ûª…í¥ØJzE'îÀ›Æ”=Åü'8Ѿ1Ñs  Ùzù%¸„"BíÇË©v_x72R¦ñU†bìeËnøî”ÍYËïGƒÑñ«T»;Dzé•õÀ<A¬ú˜÷ØÌ}áùX‰q(v9aØ LS4÷s=~‹óŠ©!êÕ¡´Ÿ•%»Í/s¡›Z¸(&Ñ_¹K x¹®ÓÐ (*j:ó.Ãg8Ú-aQ·’ca‰c\£ˆêºô r@ˆ¨‰Bϋ܉ȹ½¹ñ‰” 2°ãÔkÙª;±®{¼q0Љ7`Å¿{Žºÿ(i׉ɷ<ê ¾ÜB»ò¦$/´Ù¼-Ai²RX/¾Š3þ9ÚT‰[¯¡ Räª<ŒëÉ xËê<¡)¤&ªK1Ñ ¡‘)³$ B†+±Q¢‰G9jJ£(¨›IB3.¡ô è0Bƒ:´¥ƒ¤‹B =Áù¢DÓ83µB‘9É<ˆ‘“rµ¹Cº´21¨Ú—5¡ª¡)±·Ã£ 8~ȱpó͈“j³Z5Êc7’Û#"’ê»$™Žyᬪ,ºÅ;cH%«%6:8IƒRŽzð L´#óÆL›Bñ¬5cí9Š$²6B,‘9GE‚ì6› ¼L#BÄx S(Ó€ Ф)'’P¦ oA¢’²T¢Åä®Iqº27À2­LãÌ.²ì/É“2h¢Ô» ‚£©üœ£*F°4 cy´t39q£<•G$΀J¦‘è#Ryš$=Ø„(Ó`ÈѲ¡ í$cµQî X‰ ²vEéTFüi©lOòTã—S’ <ÊšÛX=<[ *ùpxÑô[ªûµé)¸é)KƒŠ‘kœÐá! ¿Rä?¡;¶ŠàòE”à6ÂX<ÄsòϤÚP ¹•âÅ%ƒÑ}NZÕ”;–ˆ£äËðJÒn,€2½Ówˆl?,ARqò÷™„°œ¬ª~,@Èì9 »0Q3;B^ÂЬ­Ù5²'ÆY™ÌÇã*¿XAä5Š{¬¡,4> ¡ á²1Š2Ϥêp´ ݬ{µS~ã¿4%SO\"µ X2Äì&€ïRßIMiÿ0äú¹}5’"@DZ*j-0ŒdP‹ð¥é]Š‹™pš ´s‡Ñé r©i$éÑ”½:\ËÛ¨ §…0¿£l3B5¬#¨ÖÉlsw§‘5W@|¿ëß¾¬§ˆ¢O˜*2?H¥wŒ×Ë4Ï<Ὺ< æQs>Í: £¼Ñcá‡ÚFÑÐ~Á —û7˜*Í–ËŘ*ï̸H›å“˜Ð’È+ ÃSMªBA›´Ÿ) qR$OÚÅ!Ü?ؤÁÙ»à“ ""ÃÀ¡ó=¬^02¾4P~‹™íÈË·<ë- %‹7¤„ñ¾ê˜XÅi Ùì²Äó/U°Í)Za•H[Щ!*H9"ÜšAñ&â² {‰T­TåCÌš?[e5P,Ѷq4ùvR*AëÎÇ+ÃÒýp׳B8ZZYSâ­E!Áõl$ÚÆLÙM¤Ù!E(¡Y30€ï"ÂŒ™ËDOUÖ¨Ô¾‹¨p]àŸÃ‹wË„OÜx}Ûú*1‡´8á ¥'ƒ%¥+r£%P‘ d©:Ë]0¸sò^Ùµ>ÌÇ«º4¢CÙ¯²î f4JðÁ°÷HÓѶÅ (Åûð»1¸™)ÉE¬õt:!Q£B,ð§”:VÜÞÀC>¢b/Ìœ×!ØŒ±H¤ë)‹´!õ!¬Kõ0TªN“dÉ”‰3'$YÚ—6 W:€|ÎÀ”I-œ»„¯âÜ&Ób¤N9ÇUš7K7A؈²Ï·eáÄ?M¬Ôšº"R±µ ~Æ}€÷.Ûãí{—x‘È"£ÜãðáºÜˆ ±»Ò›X'•ôŸSÑ© ³¢9»%¤TØmÌ•¢$ƒ,¼ ÔTÝŒ$ 3–’#[‡ž=Ò©ï‹í<ì4¦Š,ýÎ`”¶±zNÉlœ¨ ¢æJe+Zîõ:Áh§Õ”³C夨ÉÛ“9uÿ‘Z¾ëZé`?V+È¡¡ÂÛ@†²2˳ÃHÀã––3`Í^’ÚúˆA¿œ/#šmb-BÏßi¸-T Ïu5ÀÕ ÝŠ4˜Šá¬c!.¢vF¶¤ÝÚãÖ¼¤Y² q ÉØ¡[I<Ê-L<3¢Ô7Î&П¬¼™™-x¦dE<ëÉX¨5ýµ5Çâ@U²-»“RJ9 ´I‚à"% Fdã`Ï17c¬:`ÑlY¨|âù%<Ì-I·Ø÷Gáu*ªÔ0·=»ðÉË7½óvc‚h9%<Å< Ͱ)’ÇÓœý© ØTÈÃcææRYÐÅ×B«>½…‹Nó¢bòÄÆX“ë‘aجRUü]ËGé78s‰å%aõµš¡GXûSÍýæT©¸öD²9ZÕ,é»6 åR§Çp~&Ó)²4¥¤ ËLÜJ¬ÙÖ`tÂb£ÜÒ×#1ÃŽ$)pÌŒ}¬a)¦°U~‡Éêâ-EáF}Z*B<‹´&·Þ,…`T°µ.('…4%ºX±áÃ–2î‡ÃÇHdB‡ÝŽŽí!°F½Uðœr^ìˆO¥[±6Ïmˆ¡á“̪0V9*rÑÎ 2NµºÝ=¯(³j\†­…Þ¬RðزÍæRQ%ï·©¢kþÝíûRÐÔÛI•½šsçÝÙ¶Næ(ÖÇX¤)ÌýoÔðŽrÁ²’Ÿ¸LU‡ýíõ:½—$)Lò²î6QV+3M%ŸÇú¥5jË’èâM¾ÃÂÒÄf¶bI0ª1à~˜_ ÈÁ.Û.ÆÖív±­ž?£O—S”ZE?ùHÜ« u¨ÐaEÏįÜ2N§î½Â¨6z•~ÑNæ `¹Â™¢ÏÝd‡âöÈ„ šIåÇóbE0~,«1Ó}aí)‘î…‰ç2Z ‹>ä/\”M€BX[mÄ9ñ,­™T2a›l#á>GäòòXª"4µ¸ò,K$©) ­Ö‹ž¢€Dxêîx¸j¾®_Ìœ.”$ e°¸!œ‘ic ÎXˆ”X277Q)pþâ(2Û…·Z¿6êm0úFÛ;˜}AŠíªÅ-Kñ¾º¹Þá>Ä#!3ÊšZ$+j°¥…éè”§“l/%ªlÞxa“L.Å‚¨Çê’J¸|PUŤÀþ߯lm3—Èa ¡X‘ʆ[Üøæø´fx{÷•p¯v= SÛ§‘[^È‹A¡ª>·£M©PRôU>-Üu¤m;Nª,_óV$‘ƒÇž \“»DÍ@í›W•”\)²Ê¢í Ì€Oؽžëò`¤îâïÓ–ñ_݅嘹£jöhŸ!Ú½¾Dø‹õ#õ+(ÕÐåÈ…•²S4°½´=TË"G ’¾Ç¦®ìË4í£ƒ·Éºm-€|‰dæÅd/%…‚îzj•)ÞJ’'Ð{¤/ƒtZ§ðXöV|) ´õ²1‡ [Ëú5®KµPŽ£¤²»;Eál…ån,¶ûÖú ×®DG,ÚŒJ@£cØyÉÊö¬ÄØS^}ä:Y³Qs }!ÐþuØŸö×N—üö•åKZÉzurÅnººø‘áÚÆ»žð€§á“ü›ë7Ãø”#“Q½<7³¯ Âò¸ºÕo)lY&ꊀ’o–æu©âHÚ»²!XòRU¾Í€?_ (#~ ù„@Ÿ¯è`ˆ"Q7üV-E¢o¸äXŠEaÀ@,–,ú”¥QÇÜŽ>~LaR9‹òT¿âq8cú'Ëçɬb1—ÍdqhT¾{7”>£i(k‘ÎâULÆ«=ªÑâU×äº? ‹K$uød!óSŠÕjµú› ‰G£ö` j% ­)R8u’/žÎc+ž‡`iú4ï/ÏeòÊbk/ŒOrüK;•Í^h´öÅ‚˜àq1+",ŒP3”ŒJk®‚dæ?¨í@SݘA§C&pìýîçäoð+¤KC ëÞb±‰eÎS*æÝr´ldîõ}ŠÏaP©¿7Š–{èi¯ïX¨ êX@‡œ ‘½m{DŠ·HâFù J«Ï&-â ¨º  è2ˆ"ª·<©*0…?(¨µ.øìÃ(ÂFù P°ºº'ò®ñÃÿ!Ž…ºHîÃ?éË„š¢j©ï%ÄàJz‘­ÎJJœ¥º&ûž²ÌšÙGªÒz·³ `~ª D\‡?‰ªc RlŽJî)ñ9Î :¢…*¯kü¥“’¹­jöµó™ðú%Oz^‹(«^–"i¢c´hüž‡Là$û*°Ø¡’Yîá9Š"b¬0€%Ÿ4È‚—Iz€‰´ ÷R¹ˆ›Aõ-RÕ $3ŸrX$kU0‚-ÌÅF×ñ²bô«VpŒ*§µµ "T’ʇV©ín†Dh6Ž*³ÄDË Uyþšºl%i"m{g)ˆX—¾î|ÌÔªv-i*ÝZÏ"9^ö¶cÏj &)½ ¥³î–L§Òªšª¶P ; I½æ~Ϋs'6à†]ˆ]KJ.)*øžànÊÈŸ¢ ƒ×“Ã7vV²;çòÈÓ€Y]ĈE.ЊÝ@*_(!@ †Ágû³ß9•t Wªÿ§VíÁv¡Ê¡‡·(…´{-ŽbGµÒ •êB­è}£îU 6eþûª)`ÃÖ·9öáF¹âƒg^È%E?€³ÚૈþA)±¬Ã°ì}ËÀ€ZÝË´™*UÇh%’Ž;22$æô{ŠìN]xÌk5Òc†½¸âUZGâüЛ+‡yˆVW ”γœwñÏo­_f™  m¶ŒÕhûÒ¨“Vr£²"rm õ8<Ö–IµãÙ9Ý—^ÂíežÖSšž•qbdAš6Wêf¹ufœœw\šªHs§4¾=víÓxû(¦UßÅ"²×ùk¤½°=б’&ä°æ§´ªq[àqÊmý?cX¶ +Yel\¯¬BšX9®ˆ‚DÚȱ7$nf;5ÈA ‹µ|ƒü‘¶ó”õÙʽFN䨢—ˆ‘nQŽ¸Ìšž¨*± ø¥ÓVî Ñ'%ùΜ¢Ü펰}n $¤–ÚÎ!v õÂ0ÆÓ„N{æaã•—; `ÊýÏåb8CΗ‹Žj*¬÷¥B8¬È“[ËR ºTìï8B,ø….$‚J¯æ_Åü¶ÊH¦‘ €]ÊjË,ü ú¯0rG/”t®B0‹&âXÇk0À¤°§ ÐÊòTH’%o »ñŠêô¡.¾ýk|ÇHÀ¢¼… ³/Êsªv"ªš"fÞ©¦Þ¦/D5GØ_ìÜV§¤Tн œ‹”‹zZËNÃ^ƒ«$¶åZ7ˆJ·¯jê&ôòCÞ/‹ddí«ÌXýCþlF°ðwfŠ‚íV¥æbX†òé–‘<&¤š&¯¨äNnaíBöÇä$«Î¤È2',Ü®PæèÎÖæh[§bKÉ`é®j–…¦ÉŠx…q L αxïR,€Ì›FcÐŒ­ÉŠi¯š%â܉I°w'ü!ŠÆ©¥D&ð`³ÄNT‡¸–QÒ"„¦\2ê ÔÑÚ˜¨YƒÖÙÍ"!ˆÚŠ*w‰€[ĉÑÇ@²œõc„¿0j¤Åf/hõ-6&­"ešW¦DâqÚ…-b,5%JklÓCXF«¤ùMvù«°W«ýŒ w'.ê b]Ë!L$répCOqd2çòܱª˜ @ôɤ¾/›$ÇÀYÐ ×%`§Òî',¥jZ-Êàì%AøÆMž™CxUcÛÅܲFPÉÔñQšìî ²¬á‰¿&ŠÎèl—‡¸Å%zeÒâôI(!üb1ÚuïæÂ%¬­k6%Q[3„`êmìsª>µÅVÝ‹W2©EE<µSšÇ’„(Ãg¼Ðüð \oy1Fö‘.N×Ð,²)°uƒ!,aù QŒœÈi1Ѩöñ!4to0ùSRF&À¬Öñ§ŽÙ‡ò>æ0÷&ääB'(iîàI¦îñN¬Ñ܀ɚnÒ@'m[C£„¹¥*çòþçc0¬o« ¦$Nm0òQËæM÷'û  /n€ÑCT÷%Ô~{)XHPs¬"5òÏâI«šÅÓûFˆ % ^.ª©©(|L},tÒs=±ö Žø[IÉ ìv!M0,’®ŠŽDk§r´lF$,zœ€ôC² é"s=+eB T˜' )Ìô£T5ê[ (á-¸„æI²ºÌ0êF Úýµ ²€´ ÝÔPkÊ˳ruT{ˆkÔlY‚¶)V¼è‚k¬>œÊZçñM.ÆbjËä’ævñJ ®l £/‰Ú@‚&ˆñÚ)åü3œNjÆ}Dç( I°4°Š#3,yO-î5ç'®‰‚r²Gèõ€I±n5F­ ¡ø†…2.¥&O=§s´L5˜«zçïÎ0,ªžóå?î:¶N†Ok©&ð*ãî]2DuDóèȉlñRÊXç铨ÇО!"oP¸ N, „¶"FÞqÉt·•I+‚0$dÐíY!°ÓǘñpoKdF¦‘Ï'Sü”ŽÈÒ‹{6nã”FrsÇ2 91¹MO|ç0øoDünÔn%”ÊCT/‹TjÅEJ¶­"ÓW\ PS‚HîÏYJñÅ<æuz"tÊÅÜ—S‘[+$Õïš¶F‹e3î$¡¥o+@#X†Ìº2ë$ˆ2{bä ÌDé·A–¶ÐÕV›^`÷?·LŸ£è:Ít=+zeÅ­',}  hjõ3@ ç«Á÷ZBQÒŠÍÂYˆ^. &ì²g'èØ²Õ8Øu…j–¼ŒC&Niˆ€ž{Ø è§SÆÉKÇ*Óep˜eW\ ä­2ìsGN¤%U&Ðïyc¬$mí0ßOä„´búk¸¼V r%J‘S± áqMi¤ãöµù í5Gv/BM{!wI|ƒXqȼ„ Tó¼X“ͧ¤*¥ ß1žn"P͈jøÏ²g†hÓ2ίGXßpV€Õ=w·ÞÒ’ôÇËTíySõúüiðþG(Ã^ö}/l…+]–¶•-fG0»I£1|âo§_SÜóëÂ-Æyüò7Ú¢-}ŸbCÜ?ä2î¦í%¡õM¸3Í2ðjäy÷ %´)1qžÞ1ÎäuO6/'‡ˆ]ÎmŽ!ÊBÓy0Ôt¯£^=¥D®F]@#*âui”è›æÈÜTA„†W·“"µ´Ù†zGœÁýe”j0)˜àÿE`i â¿Ñº;‰/‹ô¤e×ë"óÂÒg¯¦'¯_­%~¨XšŒ{˜T¦‚ÛjxŽfȨm˜{âís‘¡c™ 6ÖȆ$3o¤tdBŒ§Y6ŠX(2Ć̆²XÖs¢&W] ¨!D› «A¤¬DUi|¢ùVb$ùF%Vv"­±$3ŠO£èÜÍuX(×VɃ@PØWŒlà5ðPTZ½AöÅ/åp®Gê°nלW ÛCÿN &Dó|ñµet=˜þ;$Ç9l`ûÆã1Ñ=1ë…òøÖ³mÏf(m] ×§/ÛJGX1èfjõÆ;g @"FEµ€‡õ‡'Q{yÈÖ·Ü_ËEjMø ûIƒRs.@–lj{ªV‚ˆ ¯¶D©Ü©xí V@BÊáodr´yØ'+æYÊAÑ]JWCp‹))Š&åD>÷ ‘m&Þ4_jû/ëS‘§Š¥»FwxEh¯5Ó²¯¯˜¨+Jèüõ&SÆß±>ÑV8ª¦ªâNk9L$F­ ‘š×ÂéïšCxƒ³ðÜ›bÒ„ö¡.H·I B2¯–2kÕõ£ªäà"TÛ gÌ2hìõ{¢*.dPxþª5”،җUî®Ó)†Ð(9. 'bcRxO™ö¨b•bÚ!^ ä*41(:Øo ¨bmëv; “5Â/¤ÑOÍgQ¸ZÖÀÏ1cnh'rÿtUu»+aý:@2ïbÏ›Á÷œ Û®%‚•$d—ZpÚQÛ}lítg¡™Ô×Ü™=sÅvm†×î&£Ö{…–ùnRñêÖz @Áæ±¼\ú ’u?Ÿ6Tíeãcy¸Ê%Û/²¼KYÓ‘†X¯Q, Á£1¬âL Þ#î!O•»„u‰H'w¶§¿¥ýi½QÔŸ•µèÜ!9›ÁnÊñÉŠÅNÒ™Õã=ïšßy”—Û÷-;mÊ.×zÁû0΂ºbPa?ÎØ!W’/›®¢J‰šä5HJ˼ˆË=ñ¤Ù,k¾]0añ¶³‘yÉe´Ñ¾`&0›‡Ÿhƒ¯µÄ‚í ‡†£NìC$»½×«ä`Òsg1MS‚+ÚÕI·³w Â>æe­î”3´;ì®û¥)‘å׎E]ª"ØäsJ/œð×çÛ‹¸t¢6z1Á²ñÂ1íc®‘O'µ³T›†V¯ô©©½ ÂVßãíý,­B>+¾ æsꫨ¬$¯aq¾Š£ëßT›ÀÈäUrÿ«?dµÎªã‹[Þh”¾ 0ñó Ï\£W ¤E:ÈÍf²q%{Î1RÖ–Y‰¿œžs(Ó‹ÀÝmÊ™2ºyÞqvM7dâ3{$Û13E†â#D#ò ×ëúÿƒAÀ˜T( ƒÀŸ ”>‹D€0xÄ*1 ÁÏÉzDü%Ä  „¾æ 5’Ä ðˆL‚O(‹¡s¸$B?’Ë àZSê™?˜>å‘T‚•UÉgP¸6\ðäùˆwËÅ1z~Ñå~º=³zñô³üäæ çhvŒÛÿg…Êd “Ð&fYOÑ狼uz½bµÁ!RÈÆG¾þD¯‘,VŸ–ÿñÄàÛPGî1Â{£Éúªö!­ ’¶hžŸ¢ ªå3‹2$§½H“fФ ‚ƒ ¡l°¯<(JÔ~¸¬ô˜*HJ~Ö>§ú<¿$HRž·AL{€4+tDLвè2¨¥$¯jÙ¶­š’±Û–°:èSZ”»-ØÐ¤«8 ±P,Æ"‘<†§í žÝKRþÅ+2Š Æ#ˆ”TÁ2rLY=J ·"ñí?G)L}Ë*¬zè6;ö# *ªŸÏǵ,?û‚6j{–ÁÃtd`„«)ûâŒÈ.»ÞÎ:„1ŽœÙO Ìx±€L¢çm ²°ÇàÜãž­š<ï!´›4†ÌÕ}*‹/õŒ¼„£ÈSé H:œ˜6pb•h(,Œ@Æ¢M g 2* =&·<²¼ïs+J+5nÌï£ÍS|Þå±—K#PÌ@z§©ìË{U¡2ÍïQ# äÞÅ¿cM‰€I ô&Ÿ"ÕËábSÊúQ0_àÈÛ ,‹XYiîB,<”» ‰ZQ{«v:aX±Pì;ljE„˜WR¦›BI„ÚæY:UP¯iÌEª²GÇíQ}¨*ªÐÛ`-—Ú‹mÑ3ªc2âór& u‰ªˆhMh%‰´•žCL,L…5Î?'äWZŒ5®%9È€Aô9mè}¼dŽ\žÚw†/1˜žÝD"Ź¿’$hQV –RÕnËÓüýÊ«ˆ_$-Q%rDDR÷vefR<÷ï˜8<ÎÒb¼’bA s"ETè¾$zà[œ«åƒNRª[ˆ9Ñ/©lÂT*g§ÂëÇúçî*%Á²‹§ðü|LÌ»WJb–+„ÓíNÈÔØ3$(ÌŸ<}Û…U0ÑeWʼnDselV…OÐ ‡_TÉ\Dê£ý]Ä)¨MUæKÕøØárý7ÒîvÀi5@"­3’º=!ØÏfc²—±Äè¿v0Š} ‚)¤Ú¥ â”)îDŸ¸ŒAÊzŠœ´2DC58ÙL[{¯ýÊ–Ó-%epä6»ÙBÅSŠR ݆‘f]8‹©&¯©²ˆv™6®UŠ*†aS ¡Ë§Y±Ä‚¨<&³¤¢ycJD +ê›à ìÂjR@¬\¬|L:'3¶˜å-u A6V>u(#æ•§^!ÕÁüƒQ Ä‚´Ò¿R˜±Q}bHvKJ„Ó9NÑŒ:ÃùÒØKmqÈ“‘nœ~”’”ÝN™í«vÒô lÇã¹/iÎ:Z!+ü•Œ8ò)GgN!“hƒøÙÁˆtSUÅsV{SU¤ù_ùžŒí³ DÆé€©‚@ë7„ÅÌ$,U¬ÃÙb ñ%47$ …®»Þ÷¬1æ!SM*Æ<-K­ëS:6ÕÀS*§Vèõà¦ÖPÖG±PÝwbvçÆttÉ´‰°hã†U¥HUX’òµÆHÜÜjYgãî3*¦ÑuÌŠN%’u°ñ³žm%ØvaÃJt×¼o{8—Ÿp•#}ÖÆ¥38ègŒÙÔÀKοæÎR£èølO|ïiv$+ȉSV­ .åddŠ ’Ì(ÐÃé43ž¬‡·ÜwŽn¾†aÍ*ÔNEÙ šû]0Æ==¸4ÒÊӱДNŸÙuØ·£“ÆÀ+HTÁU¤L6]&Ö¢él+f¥ÎÇÖ™›ÉXÝi\K$H}ëÚAõtÿœÀ ˜ÉÊ©˜vSÒ`ªí┣Óó÷È»˜Ðã!ôè–Lî6'VÞì€/( â„ÿL·Ö?­lG­+EF-U ¤UmÄÁ(§²ø¡õÆŽ[ÇZv‹\šqJ JRIJtS­×åV"åÁ<¥‡Ï5“òÞV:ú@óeU-U g¦–ž²Zõ°¼f’¸èap€$"'æÔé¾)lñ¨}Oe$5H_ ð9Fé3z N" lé[€6qvNk~%Bž6oJÅ1ûÙ“£ÅS™¹ö°ÓØŸŽ0ñEv`Ĭ–£–Öã´m§!”_ ÉÔ(ˆéžËXûÒü÷Òi‰yXŒàx¥²¡I&r@ Üò¶H4/ß.6Uê·%—UV+"îÃ7€þÉÅ‚õ–$†Þjg·Ø‰ñÕŸàœùû4>в‡õKtF{¥®Ï§hýB õ_7 ÔØ#Ò£z¶R ˜<¥X•Znè>ºÿ/¾Ò¼ÓiŠ$ÚÃÐ1aÅñ”9¨2Ëž©j7§À¥#‰º¬…ª(a0*J#ISR ™H»¢£:FJHªÛá4h}**X¯»¨¶Zü,J7¾ÊÏ2 ‰™¯=ɉ<"4¬š¥Xœ²Ã­” ý’ã\¡É¡˜"Ùƒ3C[o¥è¬“óŒ›8ª ê ñ0š—8‰ñ3‹š«Â<®²jÂKä.{C‚8ŸQ® ‰3°Zqªs¦ÈÒ½òBìÈÏ! :=š&¾qX¿Kz¨(|1bà60Œ ‘:Bæ›1Y£i¢˜È§Y‰1Av«·43‘®È‘3={1§®€Ù‰ú~Bð+"K&0‚ ¨ÛÁ®,ÌH ™,³;»½òYºI± Ã¯²óư£.±ù2²¥ˆ!H q¯jq>àÁ˜è‹qó†À9ÒDÛ2°úí¨ÊÙ Ã;p—Kî4T‹ª¼Ú­/7»ú, +jÙˆD{sÁ˜É«ÊèUA°ÆF"<¦KÇ‹›+‚t§‡ ÈÆ“q!ÁºžÚë5Ad•1Ò‰*K¼>šç­2û­»²%±,¤±H· ýØ–òÏ<)õ ‹¯qû”¯9Zèðäš™ˆ1IQ ’4ŒÈˆ=@ý“¸‹S¡™Éùƒ‘8ƒ!Áù>:—«Dg¸i©¦Jº4ôD33ŽˆJËÖ?>¯q¹´Û$*±/ÊŠ"Ô‰C*iñ#ÊÓÇ—Ó¶ÀÁ´©Ç«‡©pÅ,òýJàÿS«¾S25ª¸¸¸Ï8A,€${§®ª÷%´²62jéX‹qH23Ö¹sYãÛH j bmœ!3ŸIdÓój¨8ö•CTµÙU)z0öă«Ãd>³³.’—¤Þ<!²É¶0å°Ÿ4Âô ó«+´Dr;Žš/™™³IKŸ£Kë•äÖˆðÚÅB ü‹”Ób)3ïÅYüDi±” ¸D(¼J–“Š¥cøÑfœ[z™Dœ‚©D«ÈK|1)yQ(àÄ(;긠èÜe ÷Ê;踤…¹xOõ ñä(isH34‰‚´E€’¼,FóäA“ Ê‘5T¥,ñå˜Ð¾èÏJ"¾¨;ï œí!a£z±§š Á´?2D~¢:JÎ?ÚëžP¯3CJ?êûÁ‘3£xªŠ{Ç%—ÉÙ°›!²3˜qˆHbk?¹æ ™’(õ LiÁ[ù›±©Ì»,Ë ¸ (¨ñº«BÚÁ¡ß£ÉY·d'K™´Ï\åš)”<,·1zuKBå+Aæ»ãAOá1tŽ ¬„ÌÒr­Â­¸ñ½¤¸—·ìzì ´,N“K8§ÁÌcúŒB8ÎzýÍÄÕ² \‡ËѲm+1Y—L,<ˆ};ûË¢Óë¢rˆ«ë·1J´4+­;sƒ®è U3¢(˜NÒˆ”’2ÊݘˆŸµ…Q=Ú¸DŸ®ÃZÀªR+¬:ìOù´Ó l7šîT56´Ph®ØÕy ŒÝS4±IÀ&º¼£¥ª‘Xžj¹ÜID*Šˆ5c³¬¾ÜæOcæÀ‹]J(2¡Æ±u3/t V¨š¶tÊ«PŒy_‰Á(ôî$F <¼¥ˆ&Åv.Â}6b44›A–ôðŸœ5LÓ’ÉÒƒ/ôm¤tÍF…Y.J–¬ˆ `ÙŠ«»ÝGed€)ì‰a—š¾JA4•4Ÿ-ä TÍEûB3‹’ËI´7ˆ\­ÃuC»¼È¬LÒâË…#‚€!XªQ™Ø»t!L… ¡s ›ß+E±‡ÌÝR;\¬ÍŒ9HE Jg ´AÄ´t¡œþžÛÅËà Üú}ƒ‚ ‹M!#`¥šë;Û\ŠÍ'®Rô1ƒCx;Êî+¹ÌÉ¡œJh|Wª;Ë"-˲<—MÚª³(‰ï”<@™Œ·íÓª§kЬB›D `‰[Â;Ñç} Þ «9(}žÙÚb¨+D6$kÆ. !M†°¡ÐÝè®bÑ^3ª™‚K\›gÜÚ­Õ²7Ñ…ÀšõÏ€iͽ ”¼;©õf‰©ãTkÂ×Qú•3¬ØÉ­SûÃ0àŽ¢E° JšÃ" ´÷+ý;3¼*\9®&Jƒ±bú»è}:ÚiŸ–+v§B–SêèŠTrÖý7Ž»++$ô´?RÊÞ ù.dz5£#Ódá™_Îøˆ6}Vœ'+ 1L­œTO‰ûÚ¬jXPüÀ½óÝLƒ$ÍÔ>øíUâj¬•5ªjÄÊœ‹Þ±øK;$˜£¯?»+.¹ñQS<¡¨T˜K•›c”z]¤ù˜‚#E²Ü<Ø\ÂV-ª7äÊì0„ƒJUæÃö aûh ž¨ƒß8âÉÎÛÕj:¨åÒ#ﺤú"ø[ý´H4áÌYUa‚¾±LŒ“J«^­^ÛøãñØŒË9Ș¢¬²ØÇZå<,éVŽ@¼-:^›,ì “›±„ƒdM*½›®[+)]X䊚þ ü:A‘´ÙÝ@«®¡ šåH£HöçuS¥„¸©l¢\?Ê;AVM.»E¶å<Úô€Øæ(ÝXƒ-¨Ð†ŽT=5íTà‘$ÌícdÍBÚ¼l²Yke ™ñB«5ü‰åÉŸ`›6œüM5ÑXˆñ_ÍÔSÞ¦‡Ô–áSБêãüY¡¢Ñ[É€€6·È ƒ¡t øÿ;<¢ƒK¿¥MµöÃ/uà •MJ:©>Ìœ2ó™r'=s­cAÀXø‚<gÌ’ÄŸ’q;^z΄— áí™qÀ%âûžiûÊ õ¨UÉÌŸVÅ ‡ëXX;›ÄióØæ»ÛÕˆÿWòð•å.&òA‰[ªÌ±c宜®!vJÎ+ Ô œNVÛ¢é‹&[‰6!±ž®º£ÎêɸëÑûÓ¿ìêX–ógãIˆHèßÕ÷ÁfåH9¯…Éç±p1™Qgs̺«„BÀöí+aÈÖpVJ•€PÅ[­¸Îƒ8Àƒ¾RfšRqk¹ài—_¨d0³‹$-|,l“¸ÍÐÞnªˆðÿ<šö$îÚ² ª7¯A¥^à9¸Œ1dšÿ8é̱/ô —»ïë‰'-ÀUbTC2s, ôÚ'¹Ìû¡uÁG<ܪ#Zt‡ãÅ.TÖ哯t#%¿áó i ­yÆ¦ìÆœE(¿ í á‡kNLšô 6ΈÓa³;äZµ´­ÁŽä³¿U/”¦ÇžÚУ¼‡<¡Ú¼¼|:Ѓ« RìÁ©¼½}Ô¦ ðŠ~ìó,0ÓÓ1#$*Ñ굞\éÇ­~h½B3u/VÇn¶©lm¬ EUèꢘâgy œÂY)”)Xú/CX=+\â;fkjå4f“é?m¹£ ˜M Í‹pèÑnÑè;ØTo’gÚîM×ÙõêX­ø±oI-IWŽÃG -â!º-­}oDLN-ñîE 5U€R•Õ|*H²j¤!w“Lo;dÂÎC®ƒ d·Ûª¶.sî¹Èe•#/i?U×ß=Káï€3¬/.ܹl(d?¥-£HÒÂâVyìíó²9K/8Œ—U&Îç+ûå«ÂÆyv~K gÛpСoÃÞ¶Òìvk)±–*׬™X»¨á`Zö€éƒæ=#ªÁ]ÙöZ½W_¯.cg¯A`0•þ£­~ ›I[ÛIdï9ÌÇ%²F?à”£žûd^/U +ò¦»j«@´ ŒóÐ{µ7rãÂÍbVñgÑÆ¨<­Ün–´÷;¬ò´6yg6«Xt±›u£Î¾î㸣#ÃØœ»çÕ®\ß®_ ~A@x ý Ã@p÷ìFÅbÑ04fÿˆ¿_Qø[ú7I_2pL¥÷+Kcqhì&C!–#qÐ<æ ü‰Äã±÷Ð…Ð(‘8Üä;‹P€³ºt­÷‹E¤2ø¬öM¡Gc´èÝ ŽÆä4JtvCQ•Æ@Ñx<†Ë†ÜK­fDªÅkÑÜ&k7ˆÅ¡8h;„Õ¡q9ÝN²D_{E Nù¢MswÐ Òk-Æ@ótè¶]ñn˜À虸MJJÅHt{ÔöGŠƒÙ±õ»ì&'Rá^áúªTOašë@Vç§F•¯“Û¦º¨§ åÂ{Õ+6' °Ãç~;ôGÃtÚÂâÔIÝ~…¥v«Ô®$mâï7k»Ä„ hÚ˜Š¦«²|ˆ§p;Ò~¢oØ¥*èj€P¼~¤,j*ÿ© z‹1òv³¡é &™!‘F»+ Žƒ£¨šøþ4É:já¥oêÜø¢1C€Àˆ*6Ñ¥ª# 7‰ìg ¼ˆlJ…¿ªr”ÕDo@©H³6¼èKX‰8Ê*?¥¬T¼þÁ Óÿ&€ ª¤É5È{1QrµEhâ"„¨Š¢û,BgúˆÌÍŸ/ï{̂Χü!@*°„þí´-üÅ,Jâ…­É„‚µ«À¡CçúO¢«’"Ì€§­`ÙÂ:Rçò&{×@ex¹Ðˆ|–PojEG5ª[]õ³*~º‡Í¹Ñš¾–kÊÚ’ü(HˆkíS±ÕÄÆþÉ+²B¥V€⇹«ûòïOÈz¤ä í:»ÊW•O  mšq¦µaûhÛpÌL»*,káÔz;BÏo뜉ÝH+®Ë¨ ¢Ð1KuWjˆÈgä^©d‹uÅ@«VÜÜÐ(Š•³…€«ü5L?ù*!vVE0#4~Oͪ§YJà eGGÛf»*I¬jÍÒÆOA­Ú¬“jËý6K±S¶- …ÉuÜÒ ³Ñý£Qì]<ÒÑ| !!³Ss„êˆ}•c€j(܉í]ƒ éß Ik²j§2.E˜g YŒÙªU¼þ瀙í3s$¾œ”eK.Û\ø~¾‘í¹ÍÍöÄA Vê莧zÝÖŸ²,ÎÞÄ ß?9èÏ@ö™E¼~]çíçÒLmU¢þì7ì÷,41üÈΔâ)®ÞŸ'êQp2Zœ'?&$™ôÝH•ÅíñüÁ¯ &ãTG\Ó(MI' ÿKäMo¤¶` ÐóÊv$XÙ‘µâÔÉi@?ì”â€Ø\#A§È±qø£Ý(þ> ½V‘ÀAØÍ¥£›’ÜTƒ^Œ%¹5êNJpMØ~¹¦žàWH*y28Ž·2™dE°}–³æ·ßx‹}ª5nàŠ‘;Eìp.³ìlIYBD,ÕBñøÓi q®¤†›7Ìö– ‹ÝÓ5èz©#(e›8F²!‘i½·Ç똉"Îÿ­x]$!ðV>â:[‘{ vò žä:C]Ä“8æ\”€• AaÜm"¨Ä¸UIk^(x•ÂÔÂ’”Ì¥eÐBL›•‚ëᓲ ¤YÁ+êæ¡!wM´KòK–¬‘B’$Npó@ `#e9áÈwŒõÈÙ@–1îPDâz[–QN›äfnõ¬A“›™ ¢JÅ0bšò¾DlV )V ó‘ðýš€-œLenË`ŠlN̼¾Ÿø€ðzÁuDXÃrCÊ[µ;е£¹bSŒÛ t ˆšŸ×Ée›îŠ4ˆ•$±&»¿E¶žéŠsdÈP½—Ae§KÒm7ÕöB“Ù†vιøE à²ÛQQ"hÙÈø¡9zrTƇøâhŸ5x¼«x¢þè‡4 ”™âNü€95YE)ËÊ´¼Ÿ!nšOà°úTž 'r?V‘ eNm‘ð„Ô -Íh3p¢7º¯1%Ĩ›|¾Àâû ÓEutm=q“¹b¯¢ÑO °pBÖ˜ýlÔ`fO3Š÷H%L¨.-¶›ŠNTÄjÝa¥/î²àÖiñ3Þu3} À"% Õ.•j)£Jìá¬É–.‚¡éÐå%QUµ¥Ò«#:KLÝŠ šr’ÓíORòÛ)ŸÕNâS4¢Äo…Ê6I3È5-Šª-Ut ƒª ²¨ šH-òûQŠ+1k«5 ñýÌ6áÈ«>m´š”(ÏP—àçCy1h¯ÓçuŧÑ.o/Ë\› g´äå¦%µœ•ª8v mS¼x=˜‰h’à”ù\qEmÜÐ —«æyYgcD±Õƪ8UÞ²Æ~”ñÆ$ !RðzßB›ÙÖÈÉúë2v\oÒK•|ßÀ"RM)]8ìmiέ֙ÏYø˜,Jh½dÙÒ&懶¥,D~9F†fJáêòM/¡þQIw]1ÿKÚ ÞþwcÙRsOpŠÂ©ïH‰›˜f?(?™ÍÊxWõTõ”æ“v„ñ‰‘™êP˜%û&ÕÕu¡™†[ŒÙR»žš×Š$¹‘^¼íæµD‡8UVj‡ió‹;¥Nà¯d!(w.r7,u(ö…DcKfmV>Òûlò&FG®whëÆK ÙßXƇqGä"$Ö/¤| r›jÐX{I¦Mõ#1®}mYÔÕ‚“kZ#0ó“Y±øË$bI¦tÐB0Ô>b°KÅ7+fŸs—ËÇ!´ëšb6ÈŠֳÄsÿS£ÿ ÍSšeD­Ñ¥¨‰ªyNØŒÙ\´GÔ nŽä“Ó'Là¬Ê–.ú¯Ã‹î[³˜[oNÚÏÂh¦Î]aË{€ò"ñ)$æ–èO™ ñQñÐZcqõ,àOV°ÈÙ»;fE°ÚHˉ/g {ê"±ïÊxƒèèßâ¾Z>ZÿÒrµp™é‰,¡=.o"ª×^Kà˜®û2æRAò»´ŠÛ×’bçäÉ®bNP]¶ª˜áxXª«îøGÈë‘ø8•fBNì¸RHÜhu0E«ÃTvc/ÏŽB”šOøp¯ªÊ¦ôåìt †Eï4©ê,å @³C6sCèxOXhÌÔêÏfôîV ì!i¾HãhV£‡ª½¡ôƒJh§Ð]kXê/WÌ¢î” â¤RIö‚”9Ïð#¦HkÇÈPndS!±ÎɤÑÊ’#œün´Èç²ò'¾â”hÅÆåÆpíðæeNëáöYŒj¤±îÀg`7JÀ7<Â€ÉæêÙëÈ».œÊàƒ.žÕŽr5G¦-È¢œ‡`§¨i p]iò«f£*â²§Œ¿0žn˜dGÈDm¼iΪÀÎ4œvt³CãÁôzä°Žª²¦¦pB 4 4>…Æï'!ìÀ¯_ŒNü訟&ªWΦTê(ÛÌôŠä…ª 6n b 4ŸNDçE¶ÒGÀ”QŒJkŸj X&ë0µF¾˜…¢Œ DSÄãÖpÏÄHZoÐáB:6j(²Œx…¨°9BNsPJJ£.‹^'abúÞÐnŠk°¯†¥"f2q PemOš‚ ‚« ­lŽ>Åâ€À *Ibµ"'H¸fÎ)j*cÔÙBs s`^'²ÛlÆÇ†Hl/ìJL÷Š}'MȶÂ*|K¯ À BÄrvyÇÚíï4Œ±fÿ¬~ûgœ9ÉRÁà§®OC f¼d޲j¥a%²~§|MÐRчÈÍFD¾éÎ(Mó,Æß# ‹rå‘dˆ<ò *Ç|‘Ê’_„—ñDÍ+Êþròl|]ièWG®wGrŠà§®~¢”À…ÁªG ÍÙ ŽD2üÀ "©6öÇœïÕÑP;‚NÀÒh¯’‡h°Ï.¼h„%‚Zd3#0b"¯ø°H†2™. LŠÍjÈ 2ÒňzoPð*ÓD¢n£'LÉ‹òMÉp~¬ÈRÈİE$¢‹°ßsYìRl±qÆòý­VéA ëÎÿ2\fldî²×G³Ò€9‰zÀ„Oh¦­½+æ&ÀÁ.KŠi<ƒèÌJÆ‚ÊÈÎ 8¾®äm Ä>„ÉÿoðæÐROè‡QpŸ(ÄXl>^KhîsÝ(ÓSCë´ÆŒPjð(„¬ÈðžthØoò*¡Jù"+¼Ê+æq‰Ä½/ÒÕÄX/ $?æID/¢þj²´O²ò‚4Øúí §ŒÛÈâg‘×é²#óL(PöãhªdN S#×B´‘æmIEœ”Œ­k«¾qlÝ‹è‡2zç"v”ꦭ$ý‚N^Ϩã²iÑŠ#΃@&Ê)ËâŠ1v‚Íç ‹ïáóAIpô’Ä£T•¬|I,TÂì^H4‹9õE«\ó¦-‚',õºâ„›@j«[t¼¬üúèøMÊê’Ð @D“MJJð˜uúÌÌ?¢”uŠ{+K6NwÐúÀœ'¡$I‰8æÑ`˜Œv‹«ó/)I[vS2% ¯³Ó)‰aðhÉÄü2⬈ÊÒ¬Omt Êë^Gû\îb¸ˆà±Ó ±ÈOrÒâøÝΤl¥Æ‘ça[Ì(.9 BNë*W°qÌk`ã Ê5A÷P ãÆtXÐà”YY¨TòÒEã6ÿ‹k64¶áf× âo-gñï!ÿYŠ~#æð¤Ó§ ‘”Nÿo‡#¡úJ‚s\ÒÔ7•œŠŽ³ êp˜ˆPtt"¬´Ó:Æâ r"?£6HÔ­S4"µŠjdÎNUÅyŒ)0‡þÉgœI/à!fh®(‚бÛT@ùväðRl*ùâà±ü", }°V þ'*_n³RFòk’¼òúZG0w̺òôÖïÉŽ¾*zþОÁÕÿ!¨»3¸sr¨,'cfn éJ£ú'vX#/õ]SÛiÊj$‚Lî'*L(­ªo'¦tÒOj_GêÏh/Ã1Õ>‹®²Ê(¡`]–î¨×hÌeVÝ6¦žª®¿0/u…E¨n‡ï!.Ô¥nT76¦p\&ËG+ð/µ8&oÞ®¬4"Ñ*å0J(…”6w„ú±4™¥!g >•€†íÈ$èjR’ÇÊjhÎÜ cUit^¯skFÏí…d!px§(§x,hÊ×4÷'Ú9ѨfÆÃF/lF~¨[X®ÖäÎ'Êc‘hÁð»œÂ6®(÷ œPjÑ GÐˇLõO/J…Þg}^䯖<èu Vê—O³$!ã6Kø-c°l²"·åÔ&¼î'OBsŠÉB.Ñ53…žÚ”ŽX–НŽ5Ý1€ Ó²<¨£o§ª¯C8›·kg@Pç®üT¶p4<ÙØX5FŒÁ¢s§pVk¸8 \o:ç±=ïIJº!ªVÏð¿ÐJØæ”ëQ©ä{(Ñ'Ð `„G@Ê<÷åÊxÑQfζ¸}ËòŸ*Ñ LÚ}BM˜Ä0;od°( ì(ƒED-/Aæ-“Lé°éZlÔ{õS+&xÕ %£TunšŸë°ç¸Ê(Ut£GÃ’xË4Y©†ê–ÿ —+Åy9n{ă„FsžPdí½ƒÐ)ˆÁE”O!ó[è»—•²«'Údí°âÖªGì«7ëq€‰ö 79ÂY¨n=lg2v ˜ÿ¾"Ö[V`Ò–¿˜$´ZÒÂÐns)F¼l1})òØ&¬3 Ž*Ex“Öl昰M­ éC-1G}vÑÐ$£ía3½X—GÐåÊÞ72ùKØÜ(U w’EíèâW-4mGÕx­üf÷’}m,Š9¦õ–€‚Cg´Ñ"YZú¨È‰¦¢3–Ûz $êuµ‰Ž1Yâ˜tlþ×¼­—4ëPRŠ×X¸¿$“Ofàíd“¦8Ûv{nÈÚ€À*N ÂrC:¸pVÆO²Ç¸ ©Añ} yˆÂñ…  ¹Yñ 'cœ²Šíëg쎡Nß béXª”T3†'ïQ'Kê†ò5g²Òd±~ëuõÀi“Êù׋‘(Åz¡Xl%® ÿã(ð §´MÕÚH4.鵫mç@\ÿ—/· ”ˆ¤Œ1jÌJÅåqM›UJowƒÿJJÒ(Kpdð‘€O"®~ÛèqV‰˜çX$‹!¯]',Âõ†pÁÓ„˜m«çFÍú2“h[UÍ›atm¥¤öÖÊãºöãB«ëœ„ƒ<îË›FŸ7]«/½oô‘ ¤.}NoªkÖØ¤Ø›N:ˆ‚ÜN‘’˹ïð¦§q ŠÑ’+EÚ+Ãtù|3ã‹ï>ÙïŽkS”wa|tvQO‰›1Òw“½ þT!6£­ÙóÅ„w¡¸è¨Ÿ÷2ÐÔp훕ɚ‚&r»C£GEœ<kã©¥xà§aÆJÝ“Ëu‡H¨BnEãÖv⤡ð² "³©—Ý«°su¿üËœxö z=—\UH’4½Œ/|×ráž5%Ö[8 €I·‡»Ç)j7s¶ùYM\e%Ym-ç…’WK±™¯ãS'§2~b÷/C†L¤ªuqýÌTã3g€¯•˜ókÆ Ä”•r„²‹š*œ[› ”Åèø™šU׸&xA)n…ï Ф†Ã4‡³Eƒv³!AûÔzÂ3•­`«úÐt„¾î$útiɾ67˜Pô.Ç=oµß)BÔ᪲ѻû™uxåìî¸bü~? €(0ÿ…!`)þ‰Dß±X´:&>cà,}õ!‚?¢À$ •>%èãæ&‡F"Rˆ„NG?%ˆœâ =¡D%º4N>‹I¢gܨ!}C£@9B/3J"Ñ ­VwZS£1¨µ"?©Mæ°‰5Vm…HävÔN}^êR‹¤ r…PÐê$"«#“E§xp :G?‰V@UXµ&!;²€ê@lôZ«‚S©4¹42-NªÚ¤P@V¾wBËÁ›YD¾!¼€7PŒ–üq¹p¢ÕÛœM(ªF¢”:-ÎàФrŠM;–ŠEjð© Ùà…Nê´˜œ–;ù²q]ÿ* xÙo¢\ÚÓ‚Ý`U_±ü‰·©ëë#éζ±ïŠ$îŸðs§ïÓ<)Î2"‰5l’FРÉ{~¨"lÓê…6IŠ{Å0è Äà#:Ï)ÎJ ¢Ð¤8æ!PC¦±Î%A*’’įïóÆ"kz4§:ªLÖLº>ì§lZ*©$ÌÄtŠÀI|(Ç4 2*ð»0:*° Qr,ݾMš8ùÉèbÿAˆ$~Þ î¢¯#N#Š~ÆiëLGh±D"ºEŸjJ¤ÍÁ­ú’ÑN‡òw'0 ô«èÓ LÓÀý;¢TÇÉâà„;ï:§"¸~º$J¡"q¼øãŸÎ ¨0ÌH¶+rÿ¤jt)7B‘IîÕ#RZ¬‚*P€ TIÚœ¨T‰#M€L$ð O ¥WÃãvÙMÌ%¦©.À4Ÿ— ØYJ2Pò£ç­þܬPÓ[V¨5¦W·)ø½»°.ö$º($w+Žãî©.«(NÇóeCURSNZïÓd–€cSV#Â߻󥃊Aõ+Åu\/b¾¡ %v?Ñû3Ÿº=úà”â°÷9ðŒÛ ¹j ‡ævyY3Ƕ¿ Z>á?S¥ù??!ø:JçêvÚ–zª§a·N‚¤p¢Qy%õdz…H¬* tA1ÅG"©4­d0NÎù›bõ»ö‚<Ò’þ‰~ÑÆ'¯üŠË¨6Â߱ʆZÆâwš@ÔRn9¦^(Ϊ@_vÒlˆF[J ÏRÍ=5ÖŸýاe¼]„ðnâßç®ÃKìú+·á'ý¼Òòü­/sWS+´æ[fA:¤xÂk._X¡JNce³Î®á7ªk9«¢Â*…ûx(Éô¯©RÄT BŽwÀ,ÃdòLt$) $7`>‰C OÜ(#þËÓq-d(×€§¬Cž*§dgàýöh†HÒ®qD˜¤B4µš°?äx¦ÆÜ¾Ö8O ¾´"TçM‘&kãÙ‚™¶t]!x¨5€·y",Oý.ªü`@uФ•þè ÜlˆÄ¤•’Õ8yÒxcð±?FþÒ’¨|áï‹æR´a®˜ܰN°±Ÿ6êfék"nÒ’åsÓs/£À}Þe,9™ÅÑ¢ãX g¥Í”`LQ˜¸hÈÀä›%äZ”˜¢ÁXm> ¥]=º®BžÐÊç}g°Ùr€˜jϬ²«ÙTŠêÅQ‚Bâ D '[ý!Æ$,FÖØVL]¶í%ÄÔF¤LÌ¥í¥îÌ'P¡ •·a¨Z¡ÑheìŠ=¥¿ç± ÅÕ Ä˜‘åxVë-}o¤cêè÷¬É)#ÏU]¸WñÙM¬W”ÏùM~À6°ÆuyŽ6hºnе#“®þÉÝG+ŲÔaèU])Fg‘&e«Ö7²\ºéA¬¿9h¬Ã…#H5G’¼± Ý©Ž.Ü’—‘vEiB4šbÚò¼ôÑtÂdO²{Ë9­7;QIT0l%B(¸¢¸gZ™…j£®¥Ú‚påH¶–òΕ&êäy­†*vwèR+hr»ÙÔ¤‡F¬#Ÿdº…Œ÷“hGE°g’Œ/ÓúFBÁ0 \‰2GèRŸ2¦·qèÝì½ë÷Ÿó(Ut9Z8WÑphžø*ÖUÐxíˆ&…<ÛÍÚ ”ãê“áºùÍÚ;ÕõÚŸ: o°V¾Z»YEEBl ¡õJËK™zàÙi¿¤ä½ÞI‹…[›ä*BnG\o󲴤䢒ü¥Ùp–½ˆë>EXJùœ´ðÈðÙjl€áÉ-x´œÊQµƒ\6p/'i#U]–^JÀlWâø¯$8±—Ñ)•Gúw l(\k|³¾E±•¶­ÆJŲÑg­9UÉ5ÙZ° vŒX¶µŽo‚%RÐjÏ–,9­\YG§Æ„Em¯Î>­J “Ÿ>S‹F(ËÐù‘ S ŸBß™á¥ë–ŸZáe¢„¨bþ¼ªÙ¦‘T4ÐÑŠ2`1 ¢Û‡"DˆcOàð–ðð‰2¿©è;‘ œ»QŒÉ55кXﱺY ©n¤Ñ“sõ8ø}=“ ŠË7i¼ÒL$Š?²3í³Ü“ “w½²Æ§3 ½@‰¤Ázá?Â–Ü §!•«ál“#— ¸k¢Û™‡Àï¶Z-‹÷¾ª®{‰§±©§h~@9U —·¸»°­2_¤ËR RXÁfއ7|%ÉЋA:o4Ëõ‡óÝ0¡Ã|±t&¢ó)²Á8D¹ó”‘¾8©ˆ1g¡YÃ=2ì@«”‹Ì9)Šºe)Ÿ¶+•‰ ÇS~-˜‡$ñ=«ã„Ê//ú}’3‘³‘ÃE›îˆcw3AzÓÅ»-ñ}Ú-ÄÛà;¡O7ˆCV®tc³ (‚M7*BK”#Ë”Kì$@ª¬¡—¤Qg(¿‰@%Ä'ã=µñN Bžò¹ pÇ$+±JÔCºç´‹ÏÀážD8ž£°ª⸊*s˜@‚)™Ò"Ñ×2ŠH1‚ÑÝÁ©s-‹Ù ¾×żLÇB-ȼŽû¯·³p=*¿qž9ãZ€1…šèFб8{žò“ÅlW°´pºS¤½‹ëßÂJHè™´ØŽ,H†zKiÀ³³pÉ/á7 |6?ê"³L•€Y–¾š‡ Rã-d<ügœZU>l Ôc [è¦Äm[½ØGûP'KÈ3ë.ÂI<(”JIÀÁ¹èäOñÁ$ª'u3» J3Æ®¼šÚëȂګàý@MTI€!gȜԟ2-ˆshÆ:ȵPyž(ÇK¡:àžG­˜Ç”b4¼c³ FM)óK4´! M´%®ÊÿDÊ ùKÛÊBc*HÊU$¡â¾Ë¬sV¾sƒ°#B:)™Ö˜â`$8|¼xž L›A¾(¯$ø–Äð â#ª°lÐC2ÃLa·  Ô™zžLÆzï3ò ϥɰªY˜›¼1›ÔMӥЭ2ï‰è©&àŠJÜJ9®A"‰ï˜Ê&ÔG•ÉÐéô”±T,Æ•ëù»’ÕQ%#âçÁᤉyålCºX–à•. ùH¹ 9ü{6+þ›È¨ |@ø–4ŠÉÏi7;¸äˆp¨. òAÙO"‰Ã(tãJÚuDáy$ ¼Ù­NÑõ@|â»Ý!³ê¥¨D€BºìBË €<1@ Ô¬Z ÀëJ:Ù(1œ].¤„G¯¨Í¤TŒ³cØ®œ¦Å#‘¥‹u‡Ôß:Áo)$ûÂÌ â"ì‰UOÔyˇ¨] Ð{B1yµ9+š:ŒÁ0ôѤ47"ðýGºßM¨–*YoL©Š"¯¹x©A0£ ˜‰|üºzÚ"€$w?^S庸éøK’´r.®‹\HÉŸ Ó*W4PžKó"èéNDS µr¾.Ü 5ÊË–$¢WÂn¿…]™‹O`ÔC©­;€ × é¤TR•<:Ë$¡ÿ 4V£j€…ŠƒZAƒŒ™8ŸK­Î‚÷MAÑÝyÂBY›ä0ªb˜\`Xì ·š½ƒ\«ê²ƒÇb*GÙzžyŠX»ÒIáò=º>¸Å·Õ>t¿$«ù–›¬F¢<`Â0‘ÑŸ¥S‹µÖØžJ”ì4͵jLŒYÀ§Â}WƒP¬­D’éá¹[s LÔÀ{lUŒc´À™ŸÈPj7‰T¿~MØ…± )Ú±8£ÇÝ«ˆƒ+Ûé謰”0ª*µ9Žˆùÿ›ó›“žBÍ{ZqA#QQ=ú\˜Œ“¡ÁÃhù—KbKÅb´·Â³ýÛB#‰yï=ÝÅÓ"‰Å¿š]§ÌN;D)±Òß%ÍÑ­ÛÐÊ­JŸœPб­Ç¨}:;¨+åÝ*X—Š€ÿÔÂÙ¾œ4»Ä/ê‡7ý•½±Á¦¸±½GFÙû)º§Óñ‘4µü€%ùp’ÕÒ£Œþ¦¼o¶£`½rÄÔcÉ+˜l]F¹>œ†ÝHÌÄ;½¢×¾’yK”Où¹Ažðé7}C­½ Ý£-ð݉ØmáBŠHF”Ê%s€ÝE>_D°9û-¼,|ß´Œ9Ô}KpbbOÑÜÝ=ÄQ‹×XÓ¼¨#TM"äÙ2Ó·Üì—­kÃóE¯—M”Åb} ¤…=šå‡X…ØÄÌ—LVÒX¿–xã±¾(IÎÈÚjÇTX}Tj-¾!^ŠK°ÊÄ÷FHŸÙý“ÆÅÒGä+½ûµ‡_}7ù£˜]jØ ÀÒ¹ä šÔ›8¡ILÎm>½…Á9 Īr@²þU†6žXÆPÖ3Ä£X•L^±=¬_)óVô›Éñ5ª,à˜ÊH«x[ “ÈDŸd¿‹µª¢M"ªU ü¦IT;²rbéõFz?moÝ@Ÿ‰ØÜZyû²áèù–Š‚¥­íˆ×VW3E%WCš`•ÄéVbyª©°YôÀ@Ù$ ¤¥³AcÅÜàÁ r¨Ä&>Qa,ž´Û&(ÿÙ®,³1UAXf AµkGCnd’=•ía®ET7…(;0„VÍ¡ÏX¥QBN4AE,?ПœX¤Ñ Ø3“Œõì=ùeU^ÑÔÎêe͈áiÛ‹3Öä»”®„Gœÿ#Œæ\k9zèÜ="‹¥Ùƒx@ ƒEõ«.œ™Ê|N*UýYVeûœÓª¨ (Ü¢“”kœA LëLÖ40g›V%ÜËôÙdé›X“g@àŒ"éF¼;M`ê®\_Úä’IóÏÊ$t<£ÑüRÜxž¶ÇÚ%ÛÑV ‡óVŵçÏtþÈv'ÌÚ9 -]܆^…–]ÿ¯¾_AS´_ì…¦LæS˜ÅH€ÿ¬­¨!ž´Õ¾Ós ’à¥ŠŠ˜ãKÐÕl0âÍ¡îY»hù‘t‡åüÃFSØV›ãX•Ë‹¢JGAåéÐÇU+bž¡Í0ª²R(Ê].‡Ù¦H‘×NoïâÖX|. ºŒpªØüPœÓ Ù†Ùßè©_Vµ…¹äãSÆâÅmŠD¢ ´ùÕÓ×/åO¯–>« ni‚–¾€Ã) 6Ä_ ØkñÀˆY¯\UNˆJ¾ÒêaÃ$²A侎.7RE¤!üB ë&ütb`0G&•¤þ¼9¾>mŽþþLè3@æ-ŒÉý§Õ¤ÙŒnžâ-  œí«¶`ž¤ßÙR4ŠI%W#5EÜí¸¤ ¹mŸ9X1y3Ô‘NB‡þ€,ó¼“Y𰧤×?¨ÇPÃP!…¸ëÍëG[ëTV¨O³‘ÌÍ.Æ]WlLšJ¹Fí+ÔÞ$pð¾ÝÔOÃϨJÊ2*6È¡.8®(óTè]]Ït—4éì®1îj²=Îo3éJ֠בڟ)šEasOà³à#õúhÑ“v…åµ,B|$Ìí¤Üa– c0”Ífã(‰²ÉŠ(ÙyR˜ÀFûÚyr Ñg§^d+IŽpx|©›^\ªu¸‹?sú¤˜£V¬à}¡^83ï‹–—^ÓrJ­•zhQ À’MΨʬÎÅ÷kÝÛ ÙLà}щwnuÛÞRH#ö)¤þà’™š<[y'™÷ƒdPv#¥Îv'ÛHß¡…ê­=ÚÕ&ÞdkmË%•´ R‘ç. ŸV‘Y£ë“àz¿Îr-çô5š4t\ ï‚% `KI‘±º“£À»Ô@y—Á®vaê½:ÐÉ8ó?ÈÅ; iÁøéP,÷^ëuu~©ïUYnÞeõ¨Ü%õ{1©¨}ܣϊ“.|¦çZçBa°¶›\?Gß\tžÈ¿¥îuö{ŸL_-u§,äLX¹JÛxAçuúôZTø§–ƒ_f•"ñÒS%ãRúM ÛN÷\A±¥1½µdŸ9Jß“FãùèúÙdGV2Ÿjb«Fm]¯¯œ¦^V‡éºú± ¶®–ãfÒx€?ŸÀ(  „>!P@ ýˆ"@£þ-?¡ÀXä9óÈaÑ@:3~Á€Ï¹dp ‹Ê¥x,}¿'SY@|ö K¡ÐéDºq!É"ñy%3‹MaϪ¤f‘ ¾gÀxdéùR§Ä!É%–)(œC$qJE2)5Œ×¡ÐËLH“ĸ¼¢ç’R+ÕÙԩqRIE"ï!‹×«Ô¨´n9d³Ä#7ð¢Ì¥ÔbUý8$•[€w¾ª]pW¨P‹”#0ÒR%GÕ«MŒÍa’êô_‡œm@9Ð#^ÍÂ7Q 6ÆukX(w؆;¥!å^_»í„>“Ú>ÙÒidC62ItšÏ´Ó4’Š¢Ê*8”WJ³Sçô¡R –ò%É!ë{ÀuÍ@ÐªÉ ? 3±Z-lH3ÿ]·u¶Zè㘯¢NÅQi*¬Ò«1vÝ„¤¬#êÚkyII-i^ŸÓÐA½Çí£ƒPm"½%HÌ®„G@3%¶ÖYD‚Õd° ’Ön\Ïr\mžÏ¹Ñý&ÑâéUè²p­ÚmýCL]ù07N{‚ϵQ®™&ϱÞW^iJ\JÿénÎ"„VÎp(£Q‚-Dm(IÔk.õ‰%`ÅÃIu?´"Í»M¢öÆaxmò± +Ù®v]œ1Aã6bY~ÔGê½½K6»–×#Âh{¬Á·; öáÑnÀ' ÒäûxÞ[ÍdëÙ  å¾±bP•9\!û œ¾Å?Ñ¥÷¦Å_ "]Ll€"/+ö‹3µé]“¯{æíK,5–"–RǪ–ŒÁ!¬H#N‰!.]‹É$F ”ÎÓ|$…e½2ò†ŠÙ~Íñê9”¸±å3O¤²®ß #gnqX4â—á1÷QÊ)ž¼âMY™£p¯Œ…§¤ÂñŸ#0¬~·Aþ£ÝCH-Yê"dáTñhÉ…0?wVãn~€©)¢$V_ ¹`CýÿÈŽêŽiÎwJn'óxâÀY¬Z09½#Ö¡ZšjÏ~8ÅÈÊE£B¿Œ©N3önJBÍe XÁ"tcWóõ'QÐòCƒd¹àÜ9>dp’á·%Ú!EI*¼V0GÒ oeR‡œW"ÿ–Û-‰jy?¤ÕC&_“RÐÈ~’Elô$YPÇÜà¶RnK Tc<…;“f„E¹ØA²Ì,è~áaƒÈQ*(Œ•¶Âïå5D0Þ'Ø—›Zdi)ø7S\GCñ#*RY7â´fsÚŽ¦™DÈ+åÀüòí)•¹ämãp(ĶH2MTiuáD6CI"ò<íÁ÷¥= •Ùe”Ãþ€ÀémÛäìŽÈ†VJtüh]úŸ‘´e?žFTC”Á(y`%‘’É‹2f<±i±IXÇ&Ü’ü¡"Spª4†ý ÊqªcÉþ –cÄMWdKd«˜©†õì¨èBR*,Xe¬mÓ–‘·Ê&˜Ÿ¶Žn™¡æ+* Ê,\I€ìC…lMJÚ])ÅxÖ,N$”œ4û(ƒxۡܺL2m3Ã8N‰É'mÜŸÁøµjÑÛ_nLT½ `­o4ìâ¶Á˜ôc…Ú'Ð`«#úƒŒ•zÂT¦ttvµzÈ¡ùÙUO¹Eg|’Í¥“O'P„M;VçG,ÅÕ8DgL>í„YŸƒúÀ€Z\De¢ë–wëÁ¦]Q×9•w¢dAÊV Œ’PšÞ¶âç‡ò:nâæËJ¹\ òìµU©Ì©Š¡CÈ).`Õ!¦ õ­MY`:JÈ{˜ðœËåY1„`êÓ†!ežVŠCÆDÙTÄÕ'ÈEbÅÔ¤õB¼…zD7›PZc··Ñ,‹®ùÉe¦'Ʊ½ª"K1òž2F©`Ç € h-Åî¤,>¸§&«œÍvà†˜(† ÔQ%¨Ãˆ´ªxœ_‚ÐK'†´‡}¡©äõ° !‹ùDc|ÒN®¤Ã¬xå0jÜ ã~Öö'ò2o1ªØ€™èƒVáôßkaSÓ?eQþNf¡+90LbÜ”žRÂ`FõŽÆ™ªÏßðãU“Ðá¾:̯6³ý²Žy¢ŽVû^Dš“-™É"jÛ+4¬+ª)“&¶'í/ívÎŽLMÚàx–žÌu62`³qÜr¦jÚ&ì vY› c—¯™ºÜãTÞc-+lNœDÃ2¢´6³n.¿TWUžgv‰k-4kðÖøJŠÉ[Џ ]MÃtü "„áÁÐz‡»žŽîRRºvãªÑ|Ó•äÈîº+3rª[ŽØäŒl±ÏL[SÆ4ÅÐSËH´?RCÏ Ç*²HFjš­[KoyϽü)ƒƒÔŸOºw>ÉNÒŸ™Îñßí]ª§  ‚lÍ1•6ÝT}0íé*“†õ§©5ݱ9®°0Y7 ÔÓL¡*³üÞ>ó‰C‹¬O ± |;>Vo©„ÓnI`x ­m¼Èið˜Kž˜X›\*Šº_(gæ’µG>é°©÷òG×?šÙ0(‹²B Ú÷°ûEag§ÏP懢äL9¶r g#æÞ§ÙKßcTð’L“‹!ؘ2쎌<­«lTòòóG…R>zX™ Yªš3Ÿ«jý` ¢ØÆ¤’™©þf¨|-ƒ›UžçgàªUá“™°ïkâiƒîr¢8V¶‡ ™ÍNìmÊH(€sîVÞl²N(02ÆrЬØ` c˨uؼMÌ6ë`Õ+ÀC…¢‹<"Íö˜ |nð7­´[!ö¯-þ0óäÞ½)¦"ïÚƒ,èå¬0‰Ä¤RO|{‰Ìn¨JL$·nP©Ä¦ýG g0~'ÜcÍæCGš5Œ&¨ë„h¨äÖ Àå.¶ƒƒLÃÏy¥) ò"|Ž©²s/·‚8}Ϻ¯Â$po‹`‡ƒxKP’i°°½Â9MdlPÎŽK-þ%FºÑ,3é<>êfjJúì ÛbññGâ˜PbÀñD>âkNœs‰¤·G0J¨Æ‹¯þù&‚ªêäHäp%Ú|"kõG¶L\k¯8¼‹µ¦~Oë>Q礡fx~+Þ³è–Áç>cQ†~΢„Ç: æP¤®hªÃœ!ƒX‚&P¸¦.‡ ¦Q ¾Íšj6mÑÖo„šôo@¿¤8ïðŽSì@£¬Šýâþ‹°ãë†?…Nk¡É ½O~»ÊàŒb²@Œeª¨w‰ðãlàÀŽ4„ÇÐaRšf,ÊŠ ²6qGÒ  ám°¹ÆÚ½¤¤eäÖá2SÃÉlC’æ?J ÞH8«ðd3óûm.tp¡ è:)ÈtÃó8ê‹?NÄ$†º¾±nn«0˜±‚¨¯ææï ÑO. ¬—2.  ÈÄp­ÆöÑ€ìL O¦¶'Èôˆ±“NycXOT¤Æ ‰pSÒ’ÅÓ¡;aüöJýð`,dþ˜²;„"â²ÇÌ ³ÌÌR¸ÝðJ®SŒ¸… R ¾ä­þjâr'Jf¦5 Ñjt Š”VcÍJ‹hèÆ±\‰]HcHíóÊi¥Œ_Kç:Ú唚®.çB*L™aòÂ>¯}²a;­”΋`ˆ$È£mÅ>RË6}>­ÎQOù GƒëK”Yë<‘= ÌéxÙÑF‰l Úh]çÈãÀ‹°,…gO¢æ0³á1e¢íCZ"ÐÞð®ð)t0ÞsœŽ¦ÂÍRî­æ²È¿"¢A(QNSºWG3jM;§Jͱ-+ªe,]G B‚Q¶ KDT'$ºTæ3ê6MðÔ¹˜)">ðìÆë@BäÈ%ÒpEBÃdMO“ÄÈ4…C1lÆ`Ë𻤤QDßõ¬v™‹è)Õ&D)x{g¥Iä$‰ü’1:…X‚µÅQ3µ&³W·uÆ’#¯er`eJEH?RÑÝ1Ö €,ô4h¼´öx0" Œ¿nÈÅÅ8¦¯ÎƒÈ}ÎS\‘T(Æo‹0aå°!…1GÀ Qô>çr10H8Oí cMË`¬äШ,¶:…K"Ãxu5d190}‚ÆbvHâR Ö–3‡¤õO ÉJ*²éÒ6Î÷u_2Ä?©Wë$?¢(Iî)È®#è–ýsá+æš; :’(¿.¤X`ÄúšÎnjDÿ|3lähä¬çãv®ŸR¶±1B%ÂöQÄðO’I®t…¦~PgìMô8F%<4ц³÷öj‰ÑHfO²v#…0Ïbua¢.ȃž'W%VUâ+œøX@Ù ”¸Ä›)N,¡KZ‚¥Žñ… ÈxÐ,¹MæH, ¦wôÅkÍ í7dK•5' Þ0¦ÎŽ´)Ó_cÍÛWc”%ÈôíŽ)‚rCXcCnI”4•Nð3«~"Upò; wÓEnS07õMa,¢"WfÃìså0åÈ´W•ú£óx 8âXÈÐe®æ–{q!FÕ“LªLäÌ«8uö½o¾æ‘¯)S»1lª¬êŒn- âŽe.N†á¨EkNÌ1êõ0Ú±Q,ÙªŽ¬ï>äêoë|3äú4Ôs ¤J”Õ’4Étx“„#ó&NæÌvêyelD)i>ä¬%•ooËÌêy¼Ç›)P»~vI0£Å—àFÜÕŠÀîx*Ò­‚£ê2AØÜl³/.otÀ±“ðË1‹£œ Ë‘øòÖGNs,uëuuœT)×¶+ Ác—œw©‹øTJVòÓ6n¢¼N«1À0ù EŽlÜÎMOç «f°r^HhîCH5›Ndp»ªíØ7[ì^M²Âï>IäÛÚäöpâ8tê²¹w~Îî ˆˆ¾ԤDz’) óHwb•æL6—nÊܹ×g0JOåäS™ƒWu÷:ð- üL’ÖâàoQ"Q3(]Z€[v–PuÓ',B)ö „çxF'­™/ȹ8»6ÙRë1÷Œ²axMÝhÒ#>VQñ7+PäŽTp‰7!u)CªˆF<+3Q¥£)Hy“õ¼oW§JÒ SëºGù 2²‚2÷¥ ªìJH·~šL(TìLk€âTjDÁN§L«~9o—” B´ì?síå&' ¢ÜÂpÇÐÕÂ,VÐd¢¼ÇƤÙÙ³êdyb[Ùû”sEfè' ¡÷”ym²ºgĤÁU,d§v(ëbÈP¶ÜL¶]9þÊDykDfÂ@ajŽjU>J»Œböu (l¬j"å1´zë&—ñ&ZBφ Šf¦8½‰žöäœ ÇâcPÑ D"9Øùó®÷ŸÀËà4ÔJ]/Ð[`lUE«ùL™ÄŠŽT§¨È}Ä•M1-û›ÑÊ …1}RžMpÂéð Ôa“ì²%>y{ö5söpÑ›öïT‡IaúŽˆ¾^VP&<É2:&¥mWõ4ÁZ’`gåYrͲ²Z8ÚŽ¶£-ö,„Ð¥¸"]¾›­ì‡0+Á³ïꨟú”#”JeN½.[̼ީ&˜“6µ¤bé`£{Ò&»Ä 4E¥ž$%ÑŠ}óÈÖ~Þ¢%!c¬* )ïê¼½§¬ { È Vñ_‚}hç æ\«ßOS…°áQk‹=1ç;ßvˆÜµSƒ–¹h\FkR µZ,g삺X'º‡â")o a–bcX±`º:ÌEÙ«Z‘Ý!6–)dq!ë(ÌhoÎhzÇš|­°í+)‘ñâsü§9R  Áá7ü-õ „âè”"%?#øƒÞ9 Æ€)I …Â$ -Â#ÒÙ)—Áß³˜óîy$Ìe±Y„-ñEQåR*8Ï$訩2G s(ñTB!—íjŠÀëÒ¹Š*·H!*ô+W…Ø  D®Lÿ¼Ý"S'Î …Á¾cÔÛÔebO¯¶Ì®ñŠÊè9]ž˜»ÎqWܦ‚Á`¼Ç£×Ì´NXƒN'5èõpµ„Wž»š^¢^¤€¢¶È”ú}\•Òïö]äqï>™C_@ž•Âv¿gdUë܊Ň¯L¦¯è¯¡>„mA—­f[ÂLåܧüñ÷²…åä_€ŠW+ú.)k2ú//êD¾¯*Z¸¥·í(е)f£(é¸ß# óx…¹(#\‚1Là1P€¯>‘ e ><µ²iÀƒ´é:ÕC¯º$³"ÇôÍ@±Ú-2GìJ•¼0;å Æ@ ’D0¬AñªÀÇ!r:¹ Lªý,‘r‹JRSä±I‘"™>‘c¼ª/±ä{-*ª u ¾Ióƒ°ð«ô±>Çú–ú+Êš¨ÃÏ(\×ɯ”Bݳë5=©ËذàU38É’ = ÃSÐÃPå;;±` Kðl³Q@Òå*ùMiåZü¢N„|¡£ð• 5gô4´Â2« ôPé"*®&I]91/*²0¬OCÜÛªügXÒ ó*ñUN¾ÅÔ®ëÕä€O¢}B"K¢’3w‚rйB‚¹èjò±'΂V·èDQ;\îÛû„¼55A}\Ÿ¬SùXL7=IEÇÐõ@…¹Éj@ñ¤Se(~ÑçúÅ3¥µrÔŒH(­ÂÔXwbyc°oFÏô3´*òyK_é"=samúëUÒ‚¯XͲú:€ É*¡†b–ÐIå¢~UTZž}¼ÚJÅFðªó×yŸj”( ƒ"Ù£ÛQÅXÒɈ«èú)q:yšnx¸kpùYI>{ñöˆn‚ô:ÌýˆïM·³1Œž‰Fñ»ƒYß<ñ9-üo¶€á÷Ä·öbDð¤(©0ˆz&w‚K`Ó^‹+.¨pé˜ÑC+Æ"–â|†S‹­„åá#ÃÈC]»Øz-ÈžæýR+$¤ß¡¨¬³—<1 í¼Œ?èž}n}„T{J÷£D0R’G¨Bäɼ1O¢®â©#@2]w‹Œ–˜¢dq‰RÎÑ®Ìxl”ûû0q‘žø-]ÃÿˆôŸ7òF"@iòJ(R1#(9„h–%sñßdÆ)ª#yLHIñ,ŠD&0œR‹œE©a[å–Ë‚ët/© ªê£( H.&5Í€œc3¦/0…ìŸ$=\V@ÝWÍ%ªæÓ§Ui@3)‰UÜnX U±WìÜWlr“hý‰#(|T?£Q$ûÝdV&;Wy1 ‹@Ž„ð¥Ó©Ÿ7ÌÉ(¥Èª5HENKÍ¢”}·„È_Ö´mɵšW3Yé:Ù¢R¼{5h~}C2r±’PBBrÌQ ‰ÀAø·ê¹v¨j^ÐH¬†k¦GÔF7Éz J)j§¤.vpd.?Qƒ…JÑ”Y\Pñ öªˆÑ\k|@£kM•>²˜!Twˆz-·’™Xų–¯™9€CG&×-§rÒ  ©Wo ˆ™7Vufž9~Î%­)séc+\Ì ‰ªÒœd¤ÈdÕx•t…¹„òï¢8S8muqõŒ$ä=ÂßZºì¦J¹¬ü*°E*Ñ’]Y|œ«­µF¼6pÔ=Äx¯Wb½i][•37µ/dyeWÍpQ·>2`B œ[ ޏ>“;LØ3D¤ˆÃÚYìF+ã¹ò';ñ ôê´+áŒh¹›UlF,™>[’ZÍ1‹ÀQuÚÆ×taæ$ÆÐBÛÒâOv3N5FÀß3åJßšKª­0I˜As¬ž%1†ªf`5릶Öá¼­û¾¨Ô5–9èó|oý]îYÐ ƒX:µ‘Å µ{vŠ¢DÂPa‡PD}‰•\ŇԂ¢ ž®îæšÒÇÏåP·Î-]£ z|ähʘ®ùÐ/à„O’û&•Ü“[öµ¸ª»ƒ¢ ‹]xñ{”y•f©›è ë5ή³Üt™Ç¿UÑ ®m½ äâÕö@‰7%bõ­ˆ!,èOËÝs_òŠ@oö©DdÖÀµ#d飡ZÎñxÏHÞZÒz‰ó(k õ§&øa»ÈÆ3uty„M§xJôÁœÄüÞEcÂùÇü‘[Õ_±„À{‘a\1GB&c‰¸@Ú™ÎeqÂR@ÀÌ;…—䑾>¬=§ˆ¿èÎ-»Âìú?&ï°”JM$ÍíÅ©éED¼BêÜhQM5)l1RIw5¾Á¹`¨½¸Ç•]èbïl÷\^?D•sT ZÉVd–|}µÝºœÒµÖíH£ò‡½ÙÁáùŠª­k€B+Ê=“ƒÄ!ë9¯[n蘋ª•²ŠâPkò(ä#+—÷J¥§T³•L^59Þ“r(<ƒ˜Û«Lb¶Öåk‹Êm­ç+ºK9T·ÃõÊNTÈ Oº—û}ÔÜÏD5ê«x4†·â€wŒ'~#{C{t37$ý3B=ÂÓ•'yW}@?=qƒÆsú »:›#8Ò¢²Yœ ‚°ãƒ<*¸®JÛ ú†(cá.˜Ô>ã6Ü ¤ É7KÄ•ªh¦ºÇ&‰"&¸Ã¹p èæ ‘œˆr°¢»)E§¹’>ø€3p~ Ðè;g+)s¸(~@ŠŽƒÜ {š:Ò£—0¥µ™³žƒù8S¼ê[€* 0š”t¶)ò „€”(ÙP­k”„Ët· ŠXkÃXÇ–J¿Ø|­Ùö»pŒÑÊ´J“{»³A‹¼ ¿°C„(“R°)"ɧLI™ ç¼yü®RÖ­R̕ں;Ù16*è¶F*ÊäÃ󕬣Òs¡sç¼»J¸ë‡ º| #bš¢Ç¢ÄË¥»º»RÁH})ç°±1=``®‰ë£t5ÁÀj™;( £éÂÌ ª #A8³–”ÁLÄØ}Åã•*4è7:«ô(˜9.²q˜&Ûbh¶‹qÞŒ/q!¦Ë³ÂÜ­rÂÙ½ªÍ11/‰j»3Ëu‡û&Š:EAä«ÂAH É"GØž‰"½ «Åµ GÒhªÙÜŽ\ ¼7“i1 ͈`†¤Ót­ ¿1FJŒÃã@G:ék9ë”°¯aº˜“>¬A0aǬúÄF[‘µ‚õ¼WÀˆ8ä:¦Ù‡®Hæ Z&>@î<;!:Tе2k Ë< sÁâI°9ˆÄ@ DK;P÷¨S¶$0~@¿“‰Š:µ¨‘s= ©™<‘£H†¡)W5œLÅc³–?‹è÷#¤™@³Ó䉀Bß$ƒn˜»ü©\Á‰G°mÀÑ‹šY‹Ê¸>˜ú5aÒ ¯Š¾ 3™ì-¾+j±A÷´­›2÷ºT“)3¯ D5Šhžq05)¡|¢šË✪••Û#I“‰¤›¾6+`>ñä‚É’`úLðž»W4~9S ‹ru éª4ªïŸò½ìËÁËA)´Ú;ú¼‘‚¯³µ¡’´@ñrŒOœl©2'Î4+%Šm±”ŽÃ‹\?Œ’¬ÊÖ¶1Z;4Å ãéÌ“Ë ,í8`¦ÚÒ>¸†¶¼_œìyû®‹ùD|MJXj˜0¤v»Zi¶™T¹ÿLªΔ6¢ rÿ5,Ì;a„–ümLû6S„–$°‚¹FÓì 13{F4âSÒ”­˜!¤ªà|"`®4¬_=] ‹Á 3™.Äê] r<;;ÀŸÄöˆ´%Ì‚MµÙû3Ç»aPl±¤ÒﭔʢýÊL72ZÌ!ù&7KÊÁ¸’/‹g¬Ì{‘dÿ‘Ú™‘"SÁû‰YƲIÒ»î4›œ4,½,:@ õ%©4{˜JM+Œ.‰Y€jлKRÇrr‡ÒoȾôÕ|\–/»¿ˆ²¼ÖÆÊ•²Í­–ãyUôšÈ§ÜZ0Ìú³cµÄ,2µÅ–¾êÀú…S¹bÒÕ5—1ÉSÆõ/-f×=vQU«ê[\DN™ÛEs ñijœ©W*–ãhˆ“夰}¶:ž?bÌ›‹Ô íu©+[$¢Q |&-+ ŸªÛ®Lu.zïÙ¥``b¬Ê¹¯WÁ "eêÕMÒ¸ŠB[Eƒ³·HðÄ®WÅÒJ Šãá;:Mb¸‹æX ¢¶à7’—W]¢á-ø4dƵ©ÒÌ[‡ÊYÝýÜ%:MbIÏá0E|álþ×T9ŸfZï´›Yu•×Å×@¥‰õkçV0QÄæ´|–B Ï‹‹¦À°+ 2åø±9ú¢ìL:qѾ-­Ö“¼ÑŽ&»˜(Á¸µ(ÃØ0‘ 8âÍÑÄዯV2»%¸Õ¾k.s¥×K)¨ÐÐ|¢Ó@FÁÿ\@ÉSèWøb„ÒÏS°Y«ªßu)?R•-ZE³TaøŽˆXô™öZ\ Sö‚J½^©æ2IŒj4dòªœ9º‹$æÚØ yåõt:œ ®1èkY”µ¢çNf«Ž:¤ MjÅÃÿL,Q‘*ä+`ƒ~:íÖ ” =p,ÒM=̬µ¤„벌=UÖÑ ¿•1­D´'ͤî LG8ˆÜª}]A¶dWæ<ÅJëEÖó­]ËJ•qÿ]Ð] .¬EÙ1áë«¡ê.|+$ÙbúèªÐ‘»/©2Ÿ:k\¬`žl‰ÿ^ BQà¬+\Ä =9'žÆÝ‘ÊÞ ókA¥–9WkRO¬ü+•05¥Ó˜RB=ü»#C"i­ÜØŠ»UIZ³@|—”o“»>è*ûªÙ^Â]£LÑÜá/¹H‘ãêOrÉ’Ë<ÐFóì‰&8˜IÕsK ý>r¬‘÷·>„ñB¹Me/óÿœ±KDRµ]eÙ“¹¯ÓÑIƒËè¼:q])“50¿TáAõ_ÞT§·LBº:–$[îœÖßb Iº|GW_൚+=Î1 *4hû¸+6£ÈÁµ®mr[Éi½B&þ ´Éì‘S«Ä{Çðsôp¨Å½¦ÙØÒ´êðªæÇäéV0£®ËذŠçìÖîPŽy¿Ê?ìoE‡Å`ý;ÃÏCT+g{Òp²4¸‚·â>Aej÷M 'á¸Á³âž:IðÅhdÐÆýtðjv-ëd©ÊÀ`>¨<¸Þê=ãjOñ‹—4áB»Q5easZv´+r&ۈâbäî4ŸuIÑ´ÐögtÞˆER“Xb‰ViÄ¢Ä)Ù³•s5v—2•Ä8”™¥-)zŒ+³'4ŸX(Ç|"õZFB[Ãì@@~ìöÙw}¦Y–-…RÁç,&ÞÏÄñ¼2ŠÛ´+ê‡öbôÔ­µ6ž-tM± vTh†è Š:BÌ™•zhx’Dhä4ö•+’.‘dÒ3*ìà‘6,ó–Û\„hò•° hP} “—΄QëRдc¹¹Ã“~CÑû ò»G6Üv‡Pôa‘û!åg ÇÛÐþ#Ýz'ÙD‡mwG滼ÉÃG¨Ñ*´&Ü ãÈÏjp9”­½óç£Ñb寷íê€"~"6F† ,ÛËS®xèz»9»³éý$7¦;bºè=yW4¬…©1åà$Ö'€†¢f'¹.W(e~ë7œ ¸axúЧ€D Íjpë±-[ª Ö±-íñé»-¹gÓW& u ÞµJúÛÇ¥ôΕ‡ÛÏœêèÚÓÒqž¾(Š•ø‘@Sþ˜NÈÒgixÔ¹Me£5åL؈‚A`@+þCaÐpE÷Å`°à$f‚B£Ïø<~?dÐp ¦"¢ðÙ$Åù3”€cÒ¹3ö2ŒF`³7äÖ ‡Ncpˆ "”ø¦M@ô÷ÕF*ƒÓ9è AhPHtM÷+šÑdÀ›Dæ_G¡ÓXô枘€(x4 WG¸Q&Ýõÿo”á0ëÜ6s+¯aa¶(=ÎkbÎf´ œ\‘€+ðP®ÝœÙ%7x–þ£Ê&²v¿7l¹ê E†'ºìpS7k9–È¡S]ô¦ Ä˜Ïæx„ ±ÆA*/¨.áïÛ‡PøÏþ—&Þt³¼ÀT£quþýU³‹†èkò‘ší‚‰d J ¹¥n+Šœ¿ Ô¹MÞ¤‹1ú,J›~“%o ®6©›ÊÏ1Çò •ºéÚÄõC°: !Êšr»ÎêäAÉÊ€µ ŒËþ™±ŠÜ îÙîÀi*M5iÜp,LÂ+€q€èr!½(‹¯¢¯Cœ~8R¸¤Ñ #£30µ¬O l 'l4“1²J­ ¸(ôŒ“Ú7¡ªœÙ¢‹?±I3áQI#Œõ6,ÓÈïŸìºfÿ šrÜ,M›©Ì€,Á,Lk_O  Q¿GóDãº-bÙF/}P&¯åjáÑ|k1 ”›$U¬¥W*ÉÍk† ³òÚΞ¶šæÒìúŒ ç͸šÐ r &²#9#Ñúñ¢øE!úÖÁ×D€=_%r´ IQVò+ ¢²pö> Ý0¡M0­ŸÎ»$”Î¨Š û«V äøTŒä‡<2ÐáÊæë¼*ËØ£Ûçû¯zF謭¤Hu¸|Ö÷*ü`÷ËV‚ÄhÕ’}ªo ¯t[ $K2¤éŠÜO,ý$zžj H êâÉpã;$"µÑûg£)®&–<ɃwfvuVêP™å£fÖOZ/€ÉYç¼¼/å™ZáÙumWº{=ñ†Ø8t:‚æ©ÞC #Ï­U{aÊ͘ :ð¥_tp¨ô“`QŒëbÃpâö\€yÖˆbf¨*§‹pj@±f÷Úk,¡«™íÞö‚# ^òÅâ•„ÆÜ.§9 Å×ùª¹Ín w“8=éík J²§hV©^-4zM "¾Céº"©¨ ªÙ ñ®4¾>é¹}€§CÂ+æ/Rêí‰KÞCÆX“—bDι±dä5b©6$S [Ö"n”…A†žŠÜ*o‰®4ÎIžÐcD‘“2ò[Fc€˜¶×ÉKË8Ë©œ¶¢>ÃŒmÏ™ö´²³í† /ÖäêMì:J±50ëSAÆtJ¼ùšGnæ–1Þp®µ()Aø¾ßL##Ò4èÔ„!8*ÇÔ©•fŽãÈËçykA¸®ZÙA%0n&’ÉÚ$7k¹•eêäZÊ9Š ³AdŒH8§yã6e`[ ©¸sÎØžÅþæXQu®œš³U™”ü3§Œ~Å(Ð= |IR0Iƒ³"?£0t†‘œ— çáü+f§„ÁEÈ~›ˆÊ,$ÑĦe9$ŽòKÊù{Eå0¥ uinÒ`ºÅbæ"D+‡N䨧"vxe„$PEĽ6ÒÜ!ôê[Sˆ,‰lN§¼›Y“ }NDä³ë ‡ÅMÝ7 ’N¹è‹j½P’™iÑÒGŸ¬…šÂYZ œJ)Å<ƒuIâì(léP™°ÈA  Šµ~©ü%XÊ{KÑf¯ÒoOÀNdÌ”> °š˜JQã 5›éìjJÖ<Ö3­våÔõ*u½á„ªqIZ]V˜õ§àΘ#²R¥›‡$¤±?³øõÀ1G.lÕLg#>£y¥u>wCób—Qr 8§±RøÑÌGŒ’ºžªy-ÛpT†®Å&R¬f©O|UÂгŸTÃ.§yжÇó7Nú 7³…ÚDÅLOdJ.±µŠÈ!÷̳«v“0¬÷"‘³7 .Õ_ Pù8$É: øµcªÜ¢o%ËÙ†rTßsö±¤z‘*ºÆ‰Æ°¤5󖶢ؓJ©"k°ì Æ[s$)u=Œ|ížbTÎòâãØÅïX«§†}*c ë8(¤™ *fâ»'Õ(Jv€«)²Ü?Dôº^óH#5“ÑÇÖsfe&yŽ ÎÊÂ8ó–†T“Uúwƒ«eî$GÅ4F*ŠXbyZ K«W1‚N´ Àƒ©êMUÕUa/$Û_(B‡ãkX'ð ºJÙ 4[™u ¥WO©†!Dä뛉R·±¯ ëß“xH,³º‰nlC2©#¬9ºnß äò×a( ü@÷e{3¹sXe)9RÍzêCÛÀ·IKC81ÈcúÍl3øT„îi` zîwµt£Å*ÒÂÑá¿­ÐϹ•˜é¬šrd5t!OG•}-lúç\[h}¯ }•äú¬Í”ñ4Lj'²Ô¼0IŽÑÛp ~Ô:ÜI±uü¥W7l1Ò”‡Ý"8j àûš>PÑOÈÙ-÷“<)R+È0f°X[r©¢Jãý•¤ÌöíæI"²ÖïhZ¡¾ÜáÖòT£©òëôBuºÓ&WâÐOªÐ¹<}¸D­Ñ5Çë{"->Råd®¾æ9ÁÏÚk'³Ÿ.6_{k'8xbàˆU*%ˆ¹°ì‡m^IsH†6 Dà5 *0./\—dÛ›Tö…6:Œ?R·#-iå¢/ +nûsœÒ–]uÎeÂÇ„FÝÍLÏñ÷#Õ’%  gï©ÞüŠÐžY!O( Ö«Ü¥Ö€ ‹[Ôf\·6ÿo“J÷ïÞÂ;§•ž2Mx ¤þ|Âèp£ïbg‹ Xû€Éȵ½’¢z¥|¤š ×RxÐIY€6`Ox  þ„¡OÈ` ýˆBÀ ,ÿŒ#PàXÄ¢ØÃþ5'Ie©‚W)ŒH$±èäžü‘ÉÞ³°$ö9hOª$zG Añ(0U›Èé²Y¼zO%–ÅbÕ„x_}Ød¶ÜŒg‰H(Ò8„Ê3‰D£’Zlr]+›È"TGÔž%O”G' Hö9¸Â1‰ {"ˆUbÓXÓç-V–E$ø;$¾í‘Íðsø½¾a%ÈäÝTS7¬E11:Ô~)%‘ê7YúÎj5€Ø€pp금o0r|ìj„‰Kñ°ø…Ö|¾WÁN{ã½ÏÁåŸ3~ÔžùÏœïã?H)§¿c5ÓÙßß%¾Gÿ¾Ít“#l8±¬(’<ñ)¯ØøŸÏú®Ý/Œ@‘·Œ2ç¤îñðÁÂ)êF²#Ì*1IºÎ©Mâ› (  ཎJñAK#ÂË0l¢Ì€+ãÛ PR@ñ;LÀ›ÁíD$ß”œÊÄʉ² ¨QB¦ï´°¿(rÈëK⚦¯’Ð÷·‰{þÙ¸/{g"Q²zçÆÚó&$m›¶i¢À&î{‰:¬0T ‹/èÃfµ"Ëqÿ€õÉÐmÒFçÈÍ‚bÛ´Ïû§JS8°£Ž{¸É)š,“£Ô*„¥$êBø‰;Pü ù%³sv‡HH¢o )¯B ñ8ŒpçžÖl0€K#Ê=©OñP“Ùê"N¹£ h$¤î1ýCXHdË)·,™=Gû{IA¢QÄ”¢°ÐÛM|ˆÞ’W ù˜I#}äuþ³óO É*P­¼¾V,ÉÕ É!ýDX„bUÌ,+è&§l? éï#Ë4{ ¡±Ól¥}/"W–ÕH䈪Z(Ø8Í2£7®¬ÓB§”?“Ò]#ð¤0ã?I:Ö?dœñ†FÙ« 7R$ˆ(§ªFžÃJbDÿ¸ÃE$›ì],J}y³“Û‘ â“.h@vÑM2$@ƒíÈ—ÇòðdC@:^Eqüd¡2äGŽÕÒ"nw•ˆ«Õ›F°iY«övŠ¡Lø0Q$øUo¦È A³\FñUÌS0ú«†±@33™ˆ1ktÃý·‘ŤˆÄÈLÁ¡¤N¹šã5rxÙˆ¨º'Z úøâï‡ä†tä2§ÈJÕƒ…qH*5(‰Á|Tep~£’}7Øøt¬’”ƒIí€@`¤!åt¸ƒ@$JF®’É Ùqù^S¶Hé±û*tNˆµT8Q»Â1D8ÁÈy²S¤¿mÊ™¶™)¡cÈ0ò’ £BC ‘RSÂŽ±ø‚4#”¬y¥@q¹ÿ&õ-š¶÷.™2Ød!à3ƒPKŒ¢‡!Ã/‡äµZèË ¤5C,Ub‡$[ØË9?¹B$¨jµbVÍ f©“”Ò@R”“‘²ÞoËæø·GÓ|g,:™¦©U H4žv°íPG¼ºœcÄf3öv<‹‡ì=jµy¿3Wvo!e%'³éŒ\ˆL¢Ü­$°ôl~гèÄm) /“nº?ckbdîUJ3˜‡}HÔî.+ŠÊ˜iÝK›U|¬ÇÈñ|è #˵ûÑ›ªƒ $CYN¤»Ù©¤D,ÓTIœojI´°ÝÄ÷§aÂŽæ 'ÙAAç9 ;P4ŒajÐD}÷i•î5BØŒ„è¸{¸R¼#”ïdD˜'®îÁéd¸Q|(+5*44›Qã4jî—[Ê0ÒäÕÔ?øh÷ÂV*P¯QD°P²L ¨F$ë•{Y7&߃Üદ¡æ4w)Øú›3Èà‘*Íd=®"ƒÓFH\ ?P«šg:¹Ë¶XPbódÍ&þ€C{vr›õ”ý²3Û{èUpÂ,«¨KåõÃXF¡<ªE,±ß(R(Ä;I¥€%3¤Eem$“zÁ"tØ’”·…·–Ze@T´…Ë:?–Ö jJð0D±ZK=Kšî%FÑ™¥?o Ûˆ;Õ ³:²=2qÔ¼¥¤1˜J6ø29ÖŠR0m%}áÄšLÂM̱žËcbªµ2 S¸2F´>I0'_~­ØªàµpÍŠ5€ŠHÞˆb 81?q<7üeœ¥ÿ¹ö"™Æ5›BŠ%b=ôºNøÛæ¸úª,Q³¡ú‰Ðf”¢ÜiÄ–|:JS{+|î;ÐbS‹Ï5˜a)«X°rF½û™›ªâÏŒ«Ï,¼†`gºÍ4ŒÖꕜ~=úç‹©—)Ëcé€lÛ\ÐÎËéù*½iræ›j½Éˆ°¢xa§¤Ó-:dljHØ—4Ûo$¯ÆŸùIMWuù€Ž{@0uЉWe˜³iŽAñìÓ:M fâ9þ²ß:Ñðõ󜽷<º˜†áòVÁG„—3€UG/´Ð9òÎö€}‡3ܮƫí'ƒ-—׉ÊlWcû©üãjá/«YJ"Å®Ã4>¹¼Róxý|B׬ŧáo|˜BÉgøn&èÇ2ˆ¢ö(‚8Dì<üAö¶h,éö·/eRîl|,„5‚ ×ì>xèòÿOÐ1*nŸ(¶šô“%°Ýï” äi+À8 H8‰Ì"̈åáò¦kæšK²A‹0ûfRºIèø°ŠÉšæfŒÓ¤4É ð¾cšÎìôßÈDäÔÙÖqÌn«T Mær‹„° žE(ˆpTæ®\à ðªò ŽŒ  Te´òÄ”¤êËK˜^‹iŠºb,þèÐfgºå]â0ã+²w ¶HÊCOj÷ãþú\Úe~êȌͧ&"‹ôט2Ãxé¯ÚžFø´­’­Ø‚BnALâw07«f"NØ‚î¨hHþÖ ¢ã´o‚v¨”<ˆrŠŽÏ†ÃE̼ .î¨a.TŽ¾ÌŽ%mìgÉ„4î%Kk41(ä„Å´ é³Jo…VR‰¸HÑ‚á1fªf åFâé”ÕmÃÍU†R,‚Ý ?g`Xî`× Ö;ÄNrçDFLô–jë1$ÄLòÎÇ(v).hïÒÔct[îe*r—ÎÂÅ/É äi„n+ôUp4ãHJc1–%þõ1¾Ö°TE$¾È«ORµ Λ¢;DÒè­Ácxoo@†ø‹&€}¨Œæhî¡Æ} Oþ¦‹½¢ ‰Cįk¦Rhѽ1ÌôE?cþ[A¯+r>\N†`‡)*i4æo¢é,0šPUáôHÉ®Ì(6n\±Â"Ä:…ððG†±e Àï+ c1yò^ÅH"”yÐXް²ÁÍBö¦Ã!l5èt¦Ü!‘§ößvh-TÜO„!Ëa ¨\ÌL¥&HÜ—!ü0oP“Fhúp>/ºÛ²0„Ó²O"ë¢6¬<¨šÌN±³ñ °É²ðâš;OØf‰²ä§À ÊÄdmÄHËí!pe é욀) ˜"„NmìºàðÄ”àI,ž5(óR%VHgz` ­:®¨O^ÊRÚêfô‰3>Oº÷§vËŠ|ÕPÌj¦rRP¼KcÄÜCÞc%±6þúâ4ô”ÿ%¡þ¡”ªÞHB»#ÞZ Þ¬T4¹¯F°”’ãH†•äW…(ßxû´$D’)4õúÌ´2a,==S®²o9^ÔW±žÃI¥^cPu+Í SÂo¯Ê¿ä{SŠNbZ!÷>Q¦mòæ‘5%qÊÀPÂ12"‘ ¸MΔ„I:³ˆW‹Èjå:m¶pŽ›êó`k°ÇÏ&%´pîOöÌ\R 5p­lRoR#ÎlãŒhôˆÛk•lf’¿ö' “ös –‡ÖÇ€ –? 4ðÃÇvÉ xÖ&êõN)Ò\Ç>Ó²G¡úö4¬e‚º“Ô¢8Úóq˘ôƒƒ óNYCÄŒ 5/5Vf@K + bßV'bræêRÔ7˜£I–i&ž‘Ô‹ç(‹ïa«¼¸×ƒyë«5Ž pžà„±n¸«C/•¼ý’2ÄN)UÏrm 2Éé¹Kwgsv$ÑŸH5Y*ïKÿT@#åFw2ç^³R8+YW˜Uâ ãxO#[d™ÑKON‰j4az CPòÇí78d€g)Ò›äÕrÊØ›5Y1ôä¸WÑvôù0à6pzÁäx™—V"Ñ,Z…ˆ¸êî«`O½VŠ ü¨%z÷÷[ø#²â{n«þýWlâ$ñÆ™w5­Ä¤‹ m2ßWã4Ó=§Üؽ È$Ý&"϶06nøY2©*Iª“3bµ«JÎÆ%w§Yuo”äý†pkÈKQp|0áQ‰Úªšo¸Ha1Äb7@ôÃö¼†\LmW¶ÓŠüêÙ6Öut†ú½„x»1®–«@jûª›‘ïJÐÑ(ˆˆuU:BV¡“ì´{V±‘–ã<š®”ûÚ‹äï„5îKõ/WƒßM =”Øwø’[EifÓÉG/¢~JÄŸMüöN×d©Ôùfºa6¨õ7âf“¾ô2Ø ü™¤L,÷ûC/tªß >È-ðF @»2 <ùâXáç­$Òw,YƒoTi ¬X÷kšjô=S 8•x‚M¼}rI4$î9ÿX¤f2Öß`ƒzxòJÈó` B£¼r0qÑm+3mKj%–ÅV\YeoÁ 71_p;6UµW úÕJhKæ[5¡™m „¨†µ”ªN†˜Ý@S8M‡–)„®et¤0(TZ,©šëÇhÃM€Ñ¯šÕûeh‹‘Õ°ï­E–öœ¡¬)?¯S'ÒHÆB¾drî‘âÃW‚n)iPáò_WÍÂ{~Â=éõ—K›° ^~æa«OÜ: ïPÀ­ˆ%t÷ K‹¼t¬¬;ÌK|¬|ó 7ƒ>G2ERøË 苪,*iÁËj¢šK»­ "¿ ŽŠUiåÑym¸±Úñ1BÔ&3Žã#í`ŒQämðX‚ I=½¦¤3JB{¸Ï’ñX˜Âš¹Ì¯¿%\Ü嵯õ13±´o>%tš«~ÐBVþGŠöé¡§Í0iÃôJ©&&¯—Á’tÛ½[º“U"¡£ÿh" ¸îƒ=¡HPý‡b #þ(þ‹DŸ1˜£ü‰E¤@ Iä’HÜ®) —$’àÎXÿ|Mãs0º7Ï"çìú}2™È(T)$úI ££rJºH«S¡“éÕÿ È'Q(#î{‘?«pÈܺ‹ Œ¾gՀР$Tb`-*!c_íô+ø"c/N©±j®ÕÂá²kÎnø‰bm©œ’ý¹cçÖ9TSEW±Ñ uê}o½HâéÌÒ[ ‡W$`4ºÇУöxµk7)ã%ù(uDŽ×âÖÈô.H‡?;è“×¹ƒì?4oû·KЇl¶³… å.à¿¢]ù×|õ}}ýЮpI÷}>M¡þ森ú@÷¯G¼“NûüÝ$ ò¦¬£¬ª$ù» Àª5L2Òõ%.ú„½#mÒÇ Ò}¡ÐÌ6ã¢z,±¬(SýŸÎBH½(Kˆ¶Çêž©EK ±ƒ—,êãŒæ(è´œ‰+‹à¸º(d<äG¨êž¹4("$Ÿ?ÒªtÅÆ4®2ƒžÒ Šd8Dj ˆ;èÚ$½!³ê©/<» §ì4[B¢²Â^Ô@I›.ˆ,é¬\ä: B%ñËJLçûtésÂ) <‰ß?7ó°?;ëä½N‡üf™Ìo»Ã5Jhc0—;óÈÓèÛý ±ì„œÜ"ÒD^̰ ¿8€6r:Ì4è³tö"ɪHïÁkH«¤Lƒtÿ?Ï Ç¾.Ât·°itøn[€…Pí=\ÑöÅD…R•’ ŠCÌÒg%Ñ43’ã`qÂ);ï ©5×ô†iI7þ{€2¬Õ`¾ìö9ü¡WˆRItŠÞ¡?ØcM€á ôÈYŒÔÈ(dü‰2¶L\—?Òõª«K€Ç?O‹ÓÇ€þ› 52²;X0mî/låØü«’–Jj¹g¬j»|Ÿè””†;ð{…‡€ -.§ÙèÚÆ±é3’ïDÕ¡ôí!N±û¶¨Sõè½_³TÕª®h–ø‘-íÒ% “òIžöð ½?Û¶ÄX”:kFixD´–o`&e‹ñçÝCÏäÜRB®)ñ½5Y4àÛ\o½`ï°w ~¨MÖy(ss”Ž™»õ„À}ø ²¸ÁÏœë]»»î›>Å>’5È2ÞŸ\OÅÉéo E`›¾Ó×bël¥ÎáëÈësü÷·Y¼…â½>™ùå>äøàHs7JE³´öAÇâ~B*Pƒý‡ê½Rç !ReW{˜xiåŸx(cÒr”ƒ€ 52Ô4–X "mAT•>ÀiØ)i¹Í,—2§â˜tlLò¶´<äÉÒÖ6íX–LKÞQ#(y57Ó÷ Í‚ÊDèy„:Ç|Ad[…‘á$JA â–‘•¿UjÖ»M]™‹ÆæÂ›³@…Fi²¹è‡ÜÊQ+%6ŸÆ(ç͘(HøÇlj [aéf ŸFQéO á;欃3ü¤Ñ•V !«€]S¹Ø€©¼}ÀÂ:ŸŠòL¤å”M\š~æä«²ÞûŸëúZ —?ˆ }ßS㉮)BÚaزMJr)ÆÈÔ²ó!Ê-'EhÞØb鱇Î9")¸Q%Á‚'ÕižC–ÝTSœcåÄÎóü[É#îpñM‡—ÊÏ»DïDƵ‹(àYö˜EZ Dý |¡p•‡6f JXñÈ-êZ,1ÀÔ@‹C2}ÌÃ’C'|-sKtŠJRVg@AËmõú&KY=­/×*•Vr%Ë]¼Ce-K);C ¼Á·²aBɆ­‚"" QÜEq p™º‚@û§j~žS…ñ¾VÃGOJ¥Ä2 IèŽçdü†%”ú‹/†ÖÚ‡ò§b  E¨æ0 ¼Xdm:V$hQÙ,Íh€8Xr k5–¡•\A“4ÕQ4ELtÐI*Ì9ÕújÂ(I÷ks&JÂõAãû VdvLF™zx‚ .M´—.²ÿ`íFÒ^1>$¢q£ük…ö°B6 f5ÉqåÚ@4dÙÂo² ÌÔÕèé)óÌÈz©IHë”ê®JÔŸqÓ“ãFô™Ï§ç&Â! [Gaþ£æ”•iÓP]DjS ½¤[š¾£ð½C‚fÒ2œRÊH–\…—7ì ýki9N5ºhs–1 ,oz)óÛ‡-’ªêÝ3¼ºU!m |ø§ Ôü–¦U÷BR„û‹{ˆƒôÊ· ëf(ÎÀtBïàù³ÔYg¯ÍAâx§:ŽYœN Hƒ? O¢K3!ǽ˜eùoðº/RåÛŸz²íŸŒC*×e_jÌu_&ck;4ôA¨:'š~Í6j•Šiáü‰ª¤p™Pšk‹w¾º./V79pKž7NM‘ÒtÑ©>“˜.ªÌ/â^–pÝetØZQ•Ùàï•”o1SêsfJ ¶ùÕôNHë—˜YO²"RiXH¥¡ôXuM€*»zRý0e;(lÏè(êtÿ€5Z²$L.893‘=&ßåò/Ãçª>´!ÌQ›ÂÊÁ€øEËÂ%$ý÷Æý]d-Ž€×SŇBLÕ1õ´è}órÂoŽˆÌÞ‚kŸùŒ~NÞ8}º{ rMon—’ ½o‹ÞD§Wr|ŸŒ«>C½ìê’'2Sê@ûUý$ìrÐ E(-ꎻ6?X¥ÍœDQaW]‰À¹Àø”~ÎÌ‘Á<öÅQ-÷ž´GÇO±íðA97ì#÷~TU*Å¿ƒ£«A“ñ~´á@ Ó”³u¢|˜ñ½cG%rF¼Þ›y_D0•ˆÝ‰íƒž ´a, Ì“$rÀ¡¥8Âç¿8áÅòØ}5ƒ[J‘—Š&K°"l€ zÓ8ü¼àÏ“‘Þ‰¨Ý0,YÕA¹1ì©Â2?‘ôUBT›Ñ¨>Í: ¸q²E º9Ù4·p}ŒxÊÔâH0tM…ApÇÀ¡¡ôÑ¿m@–yÎúÝŸ5_<äÕÇñNаlX­w¬‹k¨Ž™D~»…¬qÕ-ÓëRª5‰Ôy!A;i„Ea÷$ƒëURL˜¾¨…xʱøçN¹©MˆtwBr†ÊÝUûµÑ ŸiÛ%…¬Êý×\ ? ÷5lJÉ`”Ô8 åQµ¸¤”Ú¸¢eÏÅΫ‹AAK¥T¿¯s_MY¤"Ê N'QKNbãÛw”HýÚ»Ù›£h=Ú=N²éG;c¡b?WJ:»!ú$×+ÄÐ}] Šã$V ÃB€!r´Äaºhã#¹Õ]¹² ÌR,Ew”¤Z¾XýÙ´yŽÁ¥P‹>áþ—#«®ò¸`ì žÝ'6:`ã›Q“Ž]Ý-ŒØSؾhŽù>%°>±­Mµ­ÛLßR³&ÚÌÜ[?Zf=tØÜÔ÷]µ¡KC]+×2¯“Ó@ÅRÁÓΫbŒŸö‰ ¹÷2ô½ˆý²ÂÙ‰<#j4B|˜‹;±¶4–×Cö9)©«ˆ¥“ ;¸A] 0¢:<Þʱ*ÉHW+¯0…Íß[ ñØÅ§á(‹³•Í‘>ž£= ¹]™ðŒŠAů´lø2"×}©ŽqþÑì¶;ĺ28(…·œÑJ9ê…OTt®të6MFˆèÝ„jѳyº +Å@ÿX1ôbu$1ƒ¡›Ê 8Åï-Ò&I›1QýK<+ÆÓ,T/Ë©Ã{^Oõ%Ò Xý©ñ'"‚Ç»ŒÛá¼h‰ÛDx&ÑØ–Q‘Û%±»ñ±Úö8J@²ä Ö-ï¼ê$´Ò¹NÙ?EeÑEÃÈh|"L±“Q˜Ò ÕTè:}€na`ec==¦=HZf½”a¾Gà2ôÈü…_œÚ1x-ÀT@"úš¼®bÈ„]=¤S¯ «u±tËÒÄ|ž´C¿Ê¸5̨~OZ5‰ñÉÆ!'C£žæh}9?‡ñ¢ø ‘E¼ìÅ ª¼dœ7¬}‰dÝ8´&ÊSÆPØvˆ„1;sÑÄÉÍ"'SWŒŒÈ*jHC‘Éá°}.ã®êeÈú”,õ)™=Rœ•HåÇn¸Â?~[Ñiµc­£X÷ÙÆWke5à'u9 ˆ“ú»Ð6Í\Ý5s´N½¦£Êu>†~;>Ž7æ0B@šÛ?:ìëúœá½!~Í´,ÜÈW‚d¿ Ÿ‡î–¸Æü¤R¬ajÁgšœÍ Ø*ìUŒð{N;ÍVƒÙEiÉ*ôNB@ìI¼fë+Žây³8}+%ò¯Mã³:¨Ï\\vP쀚ÊÍócŠe•ótá[³“W{nOîØ÷ßÎ~ˆ!õRØãW›q› Â8Àkz^–C¡ÿZ6>Û¨–Ú>@™ÔºÌ¯ vÈYðÍØl9Ú´*÷½§éŽ üÃt.R'=¹ïRXF2@vêòRYGs’r)³0Ýf³.5ä™ Ö/pøï» eØúœÏæ*62 )­=µ#±ö€xë˜C‰îai›àZv•…[ª¯ÍÓ«¹ ñ:g=£¯#XðÌ%åÕ-¹Ä‹ÄÏëSº¶¯eyQ z"E÷9r$Îõº:ýõò9Öµ(ò*g¬ìI‡Ú¹gwßÀ–P ‰¾ÄêÌÆQAÑ\W.~&„ÕXç x]Rk…>¦^J Â,Üc¸/w-v¸«ÕL›£ÿ‚¦\Vtçˆä A_ðwì$ C`ïøX‰ÂÁ1x{Þ5cÐÙ#}ÉcÀWä¦C |Kdïi„ #Â_°ùÒ4žOb3HœCgPxärh¦)Ï:€¥'’¾áôà$F9'Mª@9kâ#X”¿"à—ͦË4“Ä_VùÌöm ŠAë°˜å4¬Ub5úýÎW~…×ëPZýb9i|Ý(p{­+{‘Ïò´,•R‡Éó1ÊÄÚi ŽfrÀp•=‡ã1Pl„2=ÕÏ0ïéîG¯Ì¡ói¶GG»Cb3måJîýÚî`ôwür˜›dø;)=šÂl³-;i‡‚¼ÜxO.ó èdoZnÅco¯é)4›ÕëSºÔq½ŽãhØ(‰£êâ:0?+ ª 1çû†2,Ëù ¶ Ú…º¨:¨’¦Nì: <@~­i ½êClbNð€ˆÑîÍ€nB “¦*²¦Êøú*Hâl“»Gënä€o’„·ŸPI jüx´QB¤ˆ¬°ZÆ%`) Èð¬çíJ@Æ\K ©²ª«©Éd²¢*«B„Í`C Å+Ô‰L(‹S*²oÓüü¯PÙÿ#Çh,’¢3sq"-òÆJªZ˜­£ÉíJP¨*dô&î*C";ÉLt‘¹oâN²£‰œ¸€4rFï ˆ+oI£Î¼0*ªûø¯Ï®²Ã>/ßUŸˆâÏbL-ª##èló%0"¤Æ+öänôÑ+ü²…Ê©²Ë €Ð *WˆZË<)Ñ´¾È¬« @×Ò³X+õª#ÉÎ8£’uÀª³×êŠ,–Ü\´N@"+êç‚ÐïøYG(õJ…±‹+ì0@”Oð}ŸCQFE1ý˜ü(T #/Øj’iR—Rô¬T 亴¦‹:ʇÝ6K!u´Ã+!2f(ZH…Í:ta­°Ð1²9¦²M=,±Lì…{|hþaçæÞž›½ÀÛ¦N‚l™O´]“‰ã7xð>økR÷k§õÁ²¬©N/ªÑŽ›œÖ)MT~½¹¹'7¨«[Dà>5.ão`$S׊31ö®§:ÄÌûâÛ:„Ôóà5h·Æ›Ü°¶½ûŸÉwž€Ëæ¨J³¡õ¦‡Á¾³#¿B†õµ¶Š§N–A”Ñ GïŸk?~üHZ±:ó,¶§Bت°¬1‘]ä¿·â‰Ût¬ñ˜…PVJ†a„!q?ÇÒÖÑqLIÊ•ªfø ¥QE.>FBûÊLOÉ R7JNšZr¿TÌM[IJø”’°XLcRudy´¡lÙ2ne……¿Õ •²‘hÉK«·HÒs—‰$‚§´håJË‹ZŒÌ~’rNR˜jÃõû”R犓¿ g ™:d  ôuaÖ•ƒÌ•mœ°µ… âÃiDŒÑ¹º§´‚“š‰QŽ•î8³ ÃM9üu¬ ¦Cp M’s 2gñÁ»t ò£k‹‚„¶çüAÛš_j¨E32!ü¾ˆáUkï1~Á—ZÖÖË£i /´‚sÉëÙ„‚UDZæàøiЦ-⤣9#ˆ)õ­£bˆò{zD”¯Ê©v×t¼- ÝŸwê÷‹Â4æDÚ•ƒYlPÒ|ÌÀÇÙ!I ¹cõ=2xÃdZƒAónY¿£2Iâi˜ãñ¾Ær„mR:¦u²|¯Ì)Í<Ñ™!çMÛ5ƒàòÎb/“Ò2ˆˆ¸Ó,AëÈ0§€*ç;or8&>äû™q4¯Ã%*f@žäÙ=°‡”õb*‰‰Îô}-”>ÍKœ“)^¢'Ë9g{¹¤ÌPÛ²Øí Tƒ‰`ãLÐ:g¢qBðe”hkcÕ6§Mx’T€®jé!!ôª*%SRüiIolŽ’˜½§ù#ƒ4Š\8¦Ck2g§¾ Ä÷ ^€êP½RÄ”tIig±I|gZ€û[,¶LÐt¾mlý•MiBâ “‹)Óe.ÚN±HÈÉ=st!$XA&’½c ¥Ö¥YYàÔ÷\ <“Hjd—ÔêUTƒ4:>Û0ÿ±|-ùÂÎ̉£„ÒݲÚsedÔ&—®ÏÝAu¬¼8$ff=Rû\™Í@Mj€‡²S)qªú³`%I'P‚ê©w ÌDAF®]Ãúä[2ÞöÔL’±±l^ùyï¹›0qlÝ´lèÛKÆ‹Ø6Θçv/¬1’Þ¬±3æ…á å*–{aLžUˆ¹Ø–MÛù¹€D§¼q»'¨¬‡ –|!w–?UT‹N¶Xžú*i.…Îå|IQ›¢ ôL¯S±•òOÞ‚ß•+@6óØëæ‰êù~D,°Ñr™˜±1R*¸Ž7®¸dòÐ*V؆×özœ"F*MÜzMi½8&úµ.à ¨Å62nÙMä‰2„R9eÃ%&RÕè`Õ`¹§¼X>ÞfbO&SÇÏÉ™à…Ù\ñWì}“$hc&!Xn±ç?å±ü¬IÚc?Is ÕvÀú4’¤ë}Vl`œŠŸ=$¦m@Œ•Å_å½=·û…bÀÔ©{oÇh}PÉJQi´ær »Bðèf£) túÖíU[#%¬UzýLØ)Ü;EÂØ®‰ÀÈH…Çüøwp‚ä,é–rª“¯›–g.`=: CúÄGÞY QNÉ[iÇ¥œ™•²•pzHö}`/§ÓB@4z®‘=I”déw]¼´­KÚg,¯ÖveU„{£ª¼XX.ŽÛÉ[›òRsM«éC%kjuw´]}©;FT=;¢²ªûHæºqܶUd6EîyWãáyÀÜ#[9zÝvâÞdÚßY能N葼֫J™Ô ñ}ACêw{u¤Ë°BF)çoæc\ ÌAeô’±N ðë‡kÈmÛ9tšÞÉB\5_ˆÚÏP$}Þ>§“.¸u‰2j»JùÇÓ—=Ãà|d qr£)ë6ûµ® 7­ò¢”•Å3y›ÁwUµ*U¹)†¥Zõ–::zMw$‚¡ä>²½n²ãï~éæêD¬bÒÀÜNðñ.èŒüK€LÊb«jž6ÅþDe¯Îã–e)r“åFÖ Æ½é`ê ¬´Á©n¾FíÉ>¸« œäÛj®KæRÞËŠIP&î"ÀI®*ÈP cøM®¸äeôXúfÒ2p~£nÎ ïfÒ_I2ûŠ(P)ì›Âd9dJõNH¸¢ªOlð‹è¾ ÜxÕK€&£ ‡vÂïÒ&ŒÙ>£Z-'t*K(IÎT$¨¤#H¨×ª´¬†s.äÎÅàbö¾‚á˜Âí9¤,1 ú OfZËÂ¥.2eÀ: ºB-„glúÐIƒî]Ppp‡ÒFEÐ%$Rƒ0ïgÌ?„¿ÌNï®>kÌcF&$î&ø£j±£ kmrË †Læn0€Éø'¬z+ v¨,çøífZ·Í¹‹äGFü ÌbˆQk‘:'¤RƒÄªxÃ"F)ȼNâKè˜-ëzœm$ò‹b0n*§Ì,é‰Ð*h,å” hMø4ðtJ¦Z…-’ m1 îø",Ž' BªÕæ‚#M4ˆF$½ˆtQ%N^ªL J8ýéUh)ÂÃ)ÄA„è qi .3&»"™#jí ¸åÆW(¤dñîëF0âÍ"°H•,"lr‡ôOª2)Ê6î >É#¹iöô%°¿« ÝPI2Eo†håÓcÒªï¯.ŸRy.Žeco1*îLõòò%%½jšÀqÈ«¬ø-²v®c.åL̆ çm BVyâa: F¹¢z Œ6æ#S Ö2q7‡@$²¥&O2QPì1¢:i|õ®(«Ì8ÏhŒâ&F’si7ÑgÂúgælgô•L.6°/$ >qO,¤¸â.1øeÔ^âZÊj(]’8ñìŽ&Øl“Íc6ëºr0!> 8Î¥ð«ÅŠ­!û!ñòö2>ã ¯)‚ß9bªÆty‹hÏ-ÈÍ”#OÞQQ°‰.j\ŸÄÏm§ÅúåÍhd ÚÞlŽä’ÇR@ÿ¯§:ç G"ÂàÆÔ®ªX|gmB°Ð`âBÒˆ2IÓïì¥Î $ÆH‰OHI@¼f~óש¼}r×7²‹´Züˆ°—2=A¯òªl nk|´€ ¥@yPÄäO½‚8Fz1˜Æ„"ÁâÂÍ“@‚‘’)Ž,&Z6¦.¶¢˜ê§G!£6ÞÅÙD‚ÈÃ>gøóbƒM†@X»°R†¶35U0Ï '‰Ôô2|8 |²„Ç”¹)ñâjÞpXÖí³ZP¢"=$®²Þ()-­èÒSî–ë(ˆ)˜ïMN ¯Š¦(ÖõÕ=3âWÑLÛñ„ã”æJ(Žø&Òg®ô± VA)n\~iG4òÌ?'þújÄû% êú+>c€dT¾e/Âæ·ÄªÇ¤d„ªpˆ<Æ- Dh¯“ªç¶›k>Z.¯ëgÓï ÂRn¨íIù3„BSôfñu4¥P+ë¦ö.ãñ×eÅöñö«Œ}Fˆ”—"Ï!(´Á§f)Õ ç-A‹+Ë>‚™Yb¤T¼ãçp„¿ÒSEµ¼Û%ÝäOâ¿L€£ËÆÔ°ò„tµlâœIÒÇ^É4Ó‘dÕ ™QóšÚC2&K·FKÙ5#¹b„mè9S6¶º B6«O³ðÞ¨TÛâô»¶ŠÅq~cRec ÌôbЭÁ2¦S 2µ¢ˆƒ#ndN}*ÓIðè9µêí7 @ç54m C"³?©4e«¤<—rHâ8xö»¦æØËئ+s4Óy76e-Gp÷u« .„ž™T±Äf‡K?V³k0®ðû«LÜK÷ n·SBJÑ0|"(çjSÇy'ö}4¨²•¼Ouñj/ï—q=…v,e%(º®úÐH]IïŒTÉ<«´ß¢ÉÌ•2Þáåú˜hÒ[685…PŸ¬ô²•3K†# lÜ ¬IDisÕ(+|yw(è¾LËèº4›ÐYXu€“#RÙ©˜g”%ó¸Ûî™'™qUkY"[VÂÃ­èæ‰5P ÏKÀ¼ÖBì¨bòu…9S'ÆåËÀä傪ñ2† S’ì›Ì/“q)¤ÖÖòb‰Ëã1ˆÁöÞŽ?ywVk‹ «èk™Iõ¬Îïz#ÎÉ,B–,²QR`ŒNçY|p"ñ…ö³ø 0EÚîj6A)59QeQ2Óof@s*ùktD—3î1Œ™THjKŠâ¬ôõöò­öàÂj«9p,ܤ"$é¦JZQƒòä%kºE.&,¦ê¥NX¹‡Ó{ôõl.ªs&êSVî%fWuÂR¦6Ša«Ö¦8ÙÀ³Žôz¨¨òX±1 F°Í£i¬zˆ6šæ¼8+ò¹<×S1¶üaµ÷R¶‹3x Æa«)±¡õ$ ¢”Ÿ.8Âòns”¹bL¥fîH¹MzGJ—´(¨ÒšŒÎ5*¬.õ8/(ˇ43.ø‰Ø¨Üæ.˜˜ï8ðÌÐbµÁ¨õCWdd«nËÅÔÃâ<¾‡ª²»®wø‹:ŠINDòë‹1Ç3:ÚܶÁI0‰¹Ê£„¾±# ³`ö—R[2¼²Ñer¶'aôMœ±Ë5fX¶W qjøÂòÕ­Ø[”n÷B0c_TfŠõžã&}¢L˜B)U®dRÖâª]›Üƒš&ƒQpäP™™L’`âßLò‹iºÔd b°âR±±qks7Àž–0ôÑVó¡ [ûrÑe•0\²­S6êb4JãûnäTÔÐZ#ÂQ'ª²ló™*½{åM *9qHÍ0þOl©#B/ÀêÁ)C2OmÇÛ+?{Fkl#ÖÃË?.{¾ø–’›oK¦)0€ä…¼;E´¥i%Äîï)uÚµEjCO SÖB…A‚ ®•HN÷FÛµó´Ô’!¤i~¸ž«úJJ &ÚïC¦³¶KÇ|;Mb)µÈÉ äöB1ú±Be¢Ç÷\£¤)—{w+ Ïšz9µmŽÜë¾É؆ê,©\±eSú“émº‰é•ì•Á%mÊëHÐß°eÈt³š|6›&ÞÛ'Ä«)§Ú(¹´ ²,ó¡òþh4³îþ-1c`â#ŠìUU&!·QqÖgô+ö|²¸¯•ޏ°:kw¾Ò@ÝÔf Šc7–Ö-´õRí•X¢&@ TÇæâVûKÁ}eǰK'8épgê·y£~»ÅQBË"ÕcFz\%g2u£'Ì-=Zp“RªX±¹Ðb»÷q2)½î´þ`(Eõ TÎMDÖÆ—ë:"“ÄÐê!-ÍS8Ý’ÜM— >éBŸVÐéäSFÖO_Áò·ÓvÞ¡·[,ôrx…²m7»ÇW_>xXwxý‡ìYáIs´²—š<žM˜§¢¢Z½j;8OV|ÿyN3T¥B.]À˜ø®±SŽTÈìýýù[Ä”ÖþÁ_ìk °<˪½#õd®“K­¾LÚ±HøÁAõ`ÜÌ|â/8Gxy¨·)%°¢ªzx|í·¾et¡ÇnŽeAgbÑ£­|FˆçÂ>àP  BÀ×Ô<Dá`^‡¾¢à8›ú*ý‘D@QXì’+)•?å‘ùcþ?•#2ø¬Ö_,›Áçq UùA™Ë§P¸Ì’”J¤OÚ ò›6£O!rI%¬ŽÁeñø­.f’Geôøói’Yã±øÜfŸY­F ö—ÌV“2…×b•0 JŤÅ^ØP6íH†Óé6IÌæ°‚Òcôð>^7c‹ÒnTÛ´¿)¾?ªð} úŸa¿LñïúüG#p¡jïtYMÿ¯Ub1Úlãs¦Çðpºmž_¾‘aÀÔøü$…{X#1ØÍ6£,’t;,¶^_M¤Ád’û=èO»s#z}“ðñáÄò=nŠ{\–sÿÞb>¦¹ˆ2¨š ï2Ž©è*zÇèêìè#¯éî¶£ð±ü޵‰b|ƒÁëK.À[Š¥ð›^<ðäD~µ¯²|§£±zzÖ° +f/(:žã N4œÃ-àë¤h“D–2hjH¦Ä[Œ®ÉŒ8¤©©">ò7¨ºð†¢¯Ó\•9NÂÎè ²Èç¡-jH§²*j7.) "*ʨ3[`Ó!©{4ÇÃTÀ.Rdþ7 _6((ú΂¬ï›HˆÊȊθ¢3:^Ó'­6æ"«²’ÀT |¼‚D z lU*JìàI@#˜ÝBñè  ‘*X̨"_S%”z2¤±“Ó‚Ö§ÜdºF ›½è« éEíú ŸÏD÷<'éSЦ§´”R7llHâCBJëì m 9x'ѳ´ˆÆçâz¤£q â1qÙS •au¥î »  v—³éj&Žàj~–aӳΈœౚTÄñûÜQE~Qw &|e±ÕÛ:¾?%«(-»m í(`¨2¬s.•BGëô Ù6Ü).ƒßq0w° ê{xVñ«G“8Ú@ö¡ÈÚe@+Æ‚, }6zºû­Xm:…æú-©u·åXÂØò.‚¾ S<´á KO“Þ· ¦bÚ<’ßFÜåéø»S ZìŠÄÔXÈçnª.·!÷N¬ùiñ!\y‰¸hèºí‘NͳÑÕî/tE¼]Ä“Û9B6ÿ¢j~¹uîS–w­;'ÿ¡¯¹ÿkB¢{~JúC½B&³ì "í.r&Æð"?ˆ¡¶ªMÇ€˜Õ݉åüpV•Hè‚c&Õ»Öâ¹È[ÅM ­"Â^¬!} Ñ Â.xZðmlœ¶¤’­ˆYÌM¨ÛB t‰¶9 øî¯«“ŠO9¨á|¶C.¥@Å]ÆÙ˜£.Y× L:ô@ËÔ{«@…ÉÑ‘5XBQ,bi@ƒ‘µ˜ü]Ê÷/Ì}Ä"|æRÐ$‰À…Î?ŽcäehYͦsÊK!ò?‡ô³–t&ìMièeéLŸD±ü»Ð#¼6…„Ö»Õàé¡ZÒ>G¢ÀÖž ‰h%œ’b;‹}’`…–wð<›+àA % ¶òåÙÉ"ñ*@©âÒF\ #çHΘôp)ØiH±1ó™q"Dä1.½Sê²RûW€I;Ãrp I~ ² À(¼ÐbáªZ0(Ô¹,+dW”ØË^Ì}œTÇ—$XÝ&ÉXÈ6;×^{{±).½ý(§ÜÚ¤Xðô!9^ãGñIXÏ Ã›…fiß™ÀK ¦/±À +ÑP„ö@‚_+Ûd 1¦7éÈPLRr–è.h3¥³4×`mê>¯i X¬Œ›”¬¿›j0ö <\PTæsÂGç°ú2%¤Ê’#i³Ú"0Á}«·.ýPÿ[ðpÈvHüRü³\†Ùr®¤0ü^]<™$©>KwçšQ­}„]oÊÁòà©P¨ì¡fÅ2 ¶j5 ª  p fe¡Ö%´µVZ`Bß® Œ¨Â -©d ‘/˜ Í¸ƒ\ v):V¡Çʉ™$VZ!òõ':ñr°ÑÔCVù‰".ŠbGû/2æD9'5Þw‡‚µhA‡Qó²ÀͪÈó£+#nÑÖÖØt@tì»õ«uÇÒ_6(qW"…MAAŒˆáxGy—è—ij°9nF\0uíZÙ0û2Ÿ/4mAÏÆYL;€ëËu)”®²:ˆ+a"8h¹;…iÔØkPX~¬è>‰ T£"4{‘wöAmÕÀBwØøÙ÷zI0u\&l Ùž»&ìL/İTDmõ°ùÀŸXOjÖœ#íäèèNá"Ÿ,µ^|[P­™ûÃÇ¥eј@‹C‡}҂º§Ñ˜gCÓ+4’b!ô„Ú|‡–øE̦ÊyÐ%î½8‘ºÏš µ`=RQøh0&I²Õ~µ§¶²e¾uÀB.]#k ÂQ-$V3éœ:³½%C.e¡ù dF¿™ÑÅÁŒ¼äE ˯àCpéjm›²ì¢=6”Sk¼’Hô‘BjbÏ€À&`W•d³åQÒþ“Åø¯g¯^îÓZvd ÞMW!ƒFœøúeì Ã"¶äš¸ã J¦>ð§6J®_= ‹3Ä*zÛBeÔû®-êÉF{kЭ :ÑÙi#?hm»¢‰CšD™è%ã†8²†­ ŽŽB=‚ô¸‹»C˜÷ÈWú?KZ>€Õ Ý`BÝ~ou_—Ü ü÷ï>¢Ãiå9ß¶/³À%¦)™BfÈsZþì[!2𔄶Â3/qÑY)î¾²)Dq“Çï'3cŠ-ZÞâðѸœÑ騭ZlINI‡f7G0 ŠH=Gš1TíÌLªe˜Ú½Þè.öp‹‹#.¾Ê²3Ì\e}°E߯Â'Òi—ÛŠ=ùÁŒîBVýpáJ»ÇË»x.ÃIò“¡4@ô—-ï"®¾È´­>õÝj‹ë^þ+û/ ÅÊR[¯¡z“w‹âÛ(ÌfNŽs4f>Û17×ë·ï6ì¬mM ŸœæÜJà‡Ê‚<…ö±À¦•®’™_¶iO¤Õ nÉ¢S}l¿JöÆ•P¬ýæbU,ÎkȈ†¬¸cî©9j·#Ÿšì™Ùù¶²j¬ê¹#+‰Éͳè/y·©Á9Až30Ñ º˜ kþš ¿#|¨Œ‹€?T9ê Ã²l5sW4°•¯á> |ûª9Ã8¢ù‰zø‡ Žœñš8i8´{¯ z2¶³³òJˆz° ±Áa¾Âª¬‰/‘yÅ è!˜} :ó>ã“H;)˜8RjŸ‡ˆ«S#Óù‘£Ð¤·io5èC`÷ŠI¶1pËÄ"."Av¥ºÁ‰d9Ú"#á›8‰Ö$iÈ0d, s!Á3¦¬d»ü¾:7¸¨4)Žêk«Ivb‡ ®9³†Aú‹ˆZ1bã@;¬A«Š$ɼ°Ö‹c›—–Éé-qW/¸´«¸À#Ä®b/Ÿ!zWzŪ;:™Ü‹0¬«³-;`´¼¬$k¹å'ã&6ѱ*D/ú¡ø¨‰Ó£€æ2 l³•Ã" ²…2G[v—±çH^ŽëÇÉ„–1#•¯cI ³é¾ŒˆÀ€Âžã3°HaBÓW&ŠCl®«ǵ± ¼âÞ ó±¸S>ËR²¾é x„±¬nˆ#¦©|µ4ˆ)Ï# Z¨‚ B;8É÷¸²w@(Ó;¬B ¥&ód€!³2Csîù ;Š žD:Ê+«µªË½¹l´I”s²AÒí=êw‡Óë»c´¦ÒóC²÷³ìŠ´—»J!×hæMâ-œ\Sަ€|ã¤ê£Çp~«±õ©»Ü˜¢DÚŠzw ‘½bØBÔ|#S,ûplÒ¦džü 0™‘ •›Kø}4£kÇZ²>à°J+iËD/Zª¼Ñ¥±–­{”³ë§L|á ËÁ¤­­„"˼ZˆÜCl¥‡áñK¹°„Ò Sž=¢« +ß Ú/¨Û›CÊa9ÛR0ArÍjýdÃH¿,×<WÆJe½µ€*oΔ|¬BĽ- ÊpìJËh%¼Oh€=ÆKF"ü± ¬ˆéd¯y×ÇšhÌ48Ì-&‹‘¬¼£ŠIÁ=mÛ>å/7ý ¤±k!Ïx¼¨³5ø0RÇÁ‹RÃïœÀ‰Îˆéƒ«8Bm·+n çB˜Òõª¹ ÛI˜ÛJ9ªP£¬ Š÷Â,q|¼ÀË®!ê–üÁ¹³£³,Ș+|ʪúë:H‚*$=OÖ7RßÃ?ÇùÅ­@~‘ÉÏi¤â²3”l39—ƪC³ÒM£IxNŒñܶOÃW·‰´%Q„?ª!€S´‰™o§Ðø›d¸€B12¹Zæ¹Iq ´ã€{ôÁ>S%|-$ø"¡t­©9"ÓÁ«Z®2ˆ|<5wä†ÕC≜º=q߈yÏL»'H‚¬ü­N¡¸qqy>tr°R²8šË¡±·Æ£ÍÖ" Q‹}—ôN 5ƒW54ÄØ³»Péš¡8¤¨Ê⪓å6ì€ sXòÇ²Žœ‘­@-‰õ]“âƒ<3O»y<óN+ÀÃÌ%97òI‹HæB£›…–ÊEžk@ƒ¹&ŠÕa?cn"¼ÛWq>#Ñ}2¡ê™{û»¹3Ï ™A)ß ¹¾Î"®ä§Á9‹£-µ/‚ò:¸I '“PT˜³=–*«ð*ºÇ{…,ä Sü¿AP¹8ª¼¤9K•wªºì°°”‰"7ôLÓV*ºêÛrMÄp–­H¹úu$EMõÊ ž¼¼1YÖM©É²#¬z[Õ` s‡#b¿XRBY^Ǥ;·SKDÔsÄÀS¬¿2ö~•tÍã«D3rŜכ¼øß hèÑð|Έ½R~Ùx‚ZБ]…ÿ¹3’ßi>êóÜEìè˜] ÛhDùàG\ 2Ð"ˆ¨ >”ç>-aH-I˜¼D7Ä€€× ‹®ËpA}hPÈËÛQ²2«ÐUY`‘vZÀ|©úª«» Å¤£Ë)­1¥ì <¹ˆl1V½'Ê98­ù8£Ô) Ìž’]ÙË?OÝi»ê²Ûœ¬Ð~z§¬ÉrÈIô Œ>$ÿ2ÌÆ®Õ:³8ŠlEa"ư¦œóLʬª½ƒÁž\\©Gö@.Ó:ãö #¹(žÝ$²ø|¯yòÇ¢Y6,>`¬™}ÓW´¦«$Ö²-+ZÒþ$ƒ P§€fS²I³WŠä=FÒ³%º µx>ÔT31¾ÞŒNˆ»ëÁ¦Ó’ •VPIÅäcdb4I{EÝ‹X†D‚®/3$·kn.zl£Ð³›bÈØ&-_ ¢í…02®M §<£Òá*@9…]Øè& ä"Ò¿€3VÓ|väÊEå_*"Ç%Û Œ ” ¡Tø¶äع§:saý<$˜´ŠlŠv ¸ O!E\+~#,k)jþ\„þØ$ñ8c>›Ö‡78OkMãÉBfÀ‹Ï:슰 ô@Ûº?°‡CD;~‘`ÍëYü5"ä¢þ¡ Tp™bÔ6 ]•ù$çËqØ™Ù{%}<«6-©9à•™à¬^G¨‡· ÖÞŒPÌùÆf+ ®M'ì°ÙÁLÄëcxçÅ'ëôXÛA¸É¬PÒ›šÊM‡Û—+rE]3 bÖ)>2¢€ ë¢ßÊk¹Ï'‚äRŽ‹>9hòsÇìXUÉÄËØ1œÆQ/4¾'ÉAÁÉDT›2Í{·Ìò"Ñ‹\ˆKñ¾ú®aIïZ†ã¿l©­8*×RQ ½ê9¾ƒ2ÀBì-èÕ[—ŒñZX)r–+ eãÖµØXA]Ú 7TBWûŸPÈ$ñªr¡»îP_ƒ-ÞÄÑËçWC‡*!—ŒÖµ׿³ªÀîìÔ<&£…RcÝ/å¤J¼ &•-ÏÈÈ¡r;íxòê±}yé8d­rȪ%M`Û¬s/b`x› s~Úª½³KC>3†ðÆ$Jœ²Ls°oéLäuµÞeP‘_;4ž®{R³xŒ†ßG®è6íÝã>ßT“ VF0Ôc‰cP¬XŠïð Ón7!), °fÓÌî«É@íëøV(ÉýbbÅÅK›*ÖE\É›3Ì,ËÁž¸È±*‰>ÝÐŽÓÐì+_MîÅbá³kÙ–æ(ˆ²^·UJ­ÐõkMð|&Xà^‘ö] oã[¹Æîö”'otÏ8äa˜—… W¬ª‡·ÜÖ6 ž®Iíó8AVËLêq²—Q¹‹š­Éð ‚zWŸÞ8íÐgÊjŸÛó¢ÇçÌÚ3çEù¢zDI#÷om4³p„íÍüš3<Ÿ4&gZA"Â5u°,Æ‚ç&ÙÁôgÉMáåeqÞ"ç+v6{HޤkLøpªâ§ê<¸Që¬\ú”³çX%¼³=6 ÝS‹¹]Q!°Œ\w'’ Î xa­Û¹ÓB#»Ï¶V$¢aq;JÜ‚=Qef"ž¶¿×g/‹ìg€ŽCžš(éqï‰?JÌ ~΋ôµ60]üÖ‘—μ÷¼Ü @§Èx«uÿäõ‹s›&­¯ä„áÄÈŠ=kÜ&w±ÓpžXêožD Ïng™i8ø€ï˜ãE SŽZ{-Lý\8°°Ö¦õÜÒŽ¢NJ·-UàÉÖ{¦»ãÄJmüßýÇ´–ø¾$9ë©ÇÏuµ÷û\ÎÀßç¿QêÎôÿÀ‚li¾‹ ¸…ù•EÉp€?€  û„!@(`þˆC€0@!ö Œ@Ÿøä0Ä$O褂A…"Q(¤j[JbÒ¤JEÎb“Xtû?Á' 9¼zŠiTˆ$š; ‡Oß² ­ªNdSh„R=PëpàM•ñgœNcVPKæÝ¥dj°¥C‹\eÐH”‚=A€ÑK­¹óqÃ`¤*•zCHë´Ú}y‚H¢ÒœTr¥¡Ð@¸tRÆÐNcÕÇõâSŸù¸TJ‡,Ñn@*Í R©n½&ËO—ãdô|\®ó+Rpt¹˜…ÖA»ï€rˆV¤úðD¯4©MJOˆl¥1«ü A)òÏü«¦ˆPêW°œ., ë L"¬ý¦ z´ˆª)úRÑ*IIí ®-#0þ£bãŽà—Ÿ‰‹º„&Œ¡þΟíc¼ËÄ µ¬ª’Î|0FÌl¦ c ¸±«âzŽ2î~Hœˆ3èC.¯›zì·éû„ºÂg³©0Gœ´ºÅÊ@Ã(ª2û (/²>Ž9Íš‘Híb@ú¡’„fÛ'/œD&l«B‚=§äöå¥oÁü‰Aä72CúS€„Ê««YA4IJÄÉ6º‹N褜Ž/HƨsæRHt\‘+CÓ ÕHcNÛÖ  Në]Ðçüþ‹B(Z¡° ¶<ÔB(©.1Ãb§EÈ¥Ï( çR¿öÃEг…UÕçúKDQôèÐRõ]A¹‡ý’“"ŽÕЂ]ô"AÑöõÔQýÅ2¡“z”ŲK‚”É×äüœ§×È g¤ÓM¤…M*§w'éÇ¡ØR†Ã-âœÏ'ø“°ÊJ”è§ï⾄:Èâµ W•õ!Mqö‰0(25Ós]Â0HÒE˜ßômªáÎ)úý€ÙQð÷¡Nˆ.±Æ¨*XÒ…’IH&€¶Zx|*hå/„ê¶+ †#UTíx"GpÔpL²×¦œ§X %Ôèt~µDmàün‹!XÜ{¦ohr-4®ºõÑMÌ®ø‰>ihìu!|Fï¼.›vˆ#Þ–ïtÌŠ0OÃÊL9â‹Èè¤fÆc.T-‹ú5?_5Z‡ v5CŠy—ôÃÂÓLŸâˆ† Ù{þ8û‡îŠõߨþwEf¢†«_:K2+…à^>Õɲ"ÇÌ”¦eš‰J‚‡Á®=ÒHÀë›jF‰²¨‡:I³œ[Ϥ}¶bRpŽD%HCõ6$Eì?^IA"F$ƒ#2âHŸúc«é B˜£±*Nep¡ãæÜˆ#hoPåÊ7gª¿’£o†ê.(—ÆFSz"Эl€#4ÐiÚoŽô‚2å†î “’ihy–CB ÅÕõA£ôŠ=–¾ÕØõ#õ^’'Z‰–‰Aa±ò?À¸> " ¯‰â€&™”bž<Æ ˜ÌòÐ%(ÍѡǢ©GM0UY'ËtœN§€Á)ÉBõˆÛžV¦ˆÚ§Œ¨àBØ…OòW4³.] ²Œ€¥ÉX-è$B` .?Ò5%ÎH$“¬€ÓUDŸÉ®ºä;ÇÓIrLÕFæ›áÉÒ- <&ý£I¾:MMuÎåè˜bëÓm(Ô,Ý¡#jŸ-$Ù7¦tH%:5tˆN.}±Ûk¤œÃx¶Ôˆý"È·-ÕÛ2‰ùlhÔ4¥-Æš?R:s=ùTÂÆ Äzf?Dþdr<|ÌÚ§Mék°5”#Ê÷)Gñ×¹RV‹•éRÀH•dw?3¡åGƹáŒ%OH,‘¨TÚC›‰qošž€Y©D¦$ë—K~)X‰MO©BaȺÝ\ ,(-é»+ÚÃ=ÚònÍš:̳YYhRJäþ“6r”p¬KJm-&†N5‡XÀÙ@ÔØ†%V.àæË¥•èF6ãG¼L‘éüÙ§æ{Œ­U„@”F•™…-ÕækI:ó6E¤§Ö.iΚ $šHÉSüÚÝ“\®­øÊ ô<ÖÑXå<4T?ÖVA¨ÅäE£Ž¯Þ³Û¡ò¹å¬h™l€²’gw\JI‚)(Pif>¢£«Ôï}ÈSÁ¢±í´êúÊål®à¹³­#«ûð4—.,˳©e“:' ä" °úN¥#ü/¥vF…¿¢)ÁJ±P‰;¦© ÑàÅíÄÙ„ªh¡úá®ÎкɡõŒ@4xî2%Þ˜Tµ\Véd´ø}±Ù µä¤¸`ÐGÚw¹„†_ö»ââ¹ÁKÎmTŒ‘OýW¬nG'Û7^”¶ºùƒX5,ž ú?< °„Í qö¼l:\1Í/Þ6S2î%V@ }[©9žhº¤³/FXÜÈ#ûœ#øŸÉªÄF?˜‚ܹ٘v,K+€)JSŒ¼PQ(ZÊšy0ºòóÆ6Zz.“µ l|{[øGZŠ3_‰°«>ÂG­VFÚ)U#Ÿ;T™èšA@åØtñ’ RÃÊS3Z° ÞRõþÅK+¯ þEÃóãY¤gC“ci¥CÍXå1£–ƒwµ’ëkÀTŽGÜLnæ´<{O¬ 7h¦ðŠa‰UÀöøF™8 µâE–ÊT·°ÔeŸ`[¯â†\vqµ¥d[-œ,«Ÿ]瘳øÒ85Šì›ioꀬ>Ü3*Hè·r—› ,Q¤¥¹X^H‹ˆ³—?1«¢ÍÆÍd'+IÖ’‰œÕÆ&pûôÄÜ|Ÿ¸œ¾+û ߊŽEçÙç:›gÚXá#ƒ/‰S¿“£ò¸êõk0‘4@ ר³åf?Ÿmi‘/Qpèl°n9"Œ#Kóĉmd„ܹS¿IÐ6ŽU£;;¥qÁ¼ï’¬5}Álžì¶y ¿é<Ž\úë*¿|‘E«ý­4¶ÔS*¹TÀ3šõjáÉšŸÚ´ð•] ºÓÉ7¾ÌªÒ¦E‚8w[1„îPšÈ’3³«Ë(Ì«Í÷ñh|×?å6 —¨¨0Î’9K6ö'toªÃë*¼Ê¸ˆ"KT®CN›Âq-¦å$Âh€møñh¨O£XCÆ€fˆ’ƒè¨bó,&ŠŽÖÑìü\'NJ<ÖËþìIãéBL(¯ï0!ØÔnŸŠÐÍàö+¢e­Ü7ÄÌéì֏вö'†²/ìV§î³cøL,Ö¡ônbd!f.¤f-ŒÇ‘kˆJ f¼†¨¦6º ñoh‚v¢/úƒÈƒ (Àì.¥"ÎÚ ßFØ£DÖ&æ#H| >$l:-„ãDúC$Öçö㌪¹(î!M{Î"†³ Pkl²§íÔŒ¦ÖÍiÂúnìù)rc á®…®ÒŠË¬o‡FsFÖîH¸QŒê|É`*Þæ ¡)°ÇI&ÜOΚ .¹g&OãD¨¨8ÒçîTâ¡Îê;MbÏBª*Ë´M}…üް„£.ÐlM'40ObænøZ Nœ.~r)ÞÒ§dTf ÌÃD¸ƒXL"À NRÑâ-5pl­ä] ¯d%fÌmfõªÐ¸IÌ܉†P¬nÆÆ‘d–$GBìeäÍìHGFޱºî‡ü ÉpñpÒ$&#²Ã螈` ŽÏNbã‡ú‹EÚã‡"ñ"›ÚCŽÀÚâ>fBûçñ24ÏFìtæøX†HŽrîkª}žF‘nZ,¢=N2¤]ÂÎ-@Ýfô— ™…àÃîï +~vŒðþçʼ0m*Ì× ÇÍ ne#KšGÎä‘Òý"ÞùD<ê3BÌDÑe*†¤µ€DÒ#!ü[zÂo²…)ß'H¯)êõC”.®)n)ä‘1ì&ÏQœ!EzÜs>q  žf>-ÌQi-”Ýpžv‚¤³Ñ4³ Ä«d"à óàÛÊœ·s¡0 lNt­ƒæŒp«‡à“ÉÔÙâ ÉIæéiØÇô‘ÒL'3E޳r¾ KxË€Œ¨n7ªnÎ#”ÔlæÌ¶p2¶£¥O®LñïòF‚ QÀ#‰FÿJŒPJ`äQ-âÞG¶ºÆÇokA'FEf¤ÍtjÚ$@Œp+.0–¯jhág†VfhËŽ”1ÜÉÄ‘Ãü­ãE;%†p04m¥ )Mr´nôºÄš<«Š3H Ä[ò\4°ô| k‚¬ãXLÅßë'%'á­ªÌñ ŒNäTr § Nôô¯å&¶Ñ´!4õ+‹ÏÜØi9¢ HëlÊŠç²`af-¸H†7%ë£ÂV™jjºIšöƒ phê0Oäðu÷†Ftù1턘*Ñ>#’gRå&ÌðO¢" ¥!èÊœ‡öbîã‚5UçoKÏ?Zd?6IšÝ*45ïÌQHÓñà²T&•X$Ȩ.%rÇîµ/ô2ýFª‚8âaIÚÁi-PPlµO2õQC3ŽÍ…ïÄ„ûjÔ…,9O…G†åíñ]òRxdîö.pq«ulôi Êö&èu°!ÈÀ%)uñ6)ÄcE5ÒPvO|î Å52‡ŽØÂ”]KÐ<”#d´5ÆÂpÒ·w\fìêí‚­55;Ã*lÑåMïÒ³–܉¿”.è,VºˆV¹n(W£¼Oó]d†s`QíÛkUJՔ㓺4O8u²Q1Ä]«+VBÎÀOhs4ç`üÄvRðD ù'åý±-`î -Ò ½ÍGc‡ÌsLú6U‚ì$޳ń„0vû3ªQ‰+TfS ˆRò}ÍW ’fN³g1äßOÞ< Þ ³PFÆæ6f#•M %©]òßî:ÝJÓrrðp-Á .”_Ñh p\ã†6ÏSGÆÀÌ• WX?ĶÆim@Ãë‰/Ȧ–ñUƒø0Bã=MJݸ>Òœ²eå Ézö‘Q+Èó´†ãE $ptçúQ;$ŠVM,¦­ép؃rIè<©D‰Q–«¦béð€k0âã”bõÊþgJ2L)í/m\7âçÍ#b¤Þ@'«IìÉE ÎCÅ4ë[b”l㕤Ÿ¦o÷j”ŽòìõHÖá†" êòû´—%R.%ؘ·¤.C;z7!KÃ}Îà ièþvÚ3•hßwy±ï©¢ÄíjJîè࣠?ˆ"Q ëo²e,?)v^bð¯cÓ=UiÔt_J“1æu ©š$WL÷˜((%¬¨¢¤ôbÎ[„2íbmb,åÂÏŠ`knŽý·"]vh«'†—挬ÖP¶°Bæ D #ĪEn}lÀ~ON-ÒS#¡ûEáñzìÛ"DLÔM’­‡^$LŒ†ní,ªå7,ƒ¡ú â8ŒP¨°mTD&¡4Ûq O·³A3zv™^Ì\¢•l<á?4ÕFyÁp£ì»1ÕQjp¬B]ìÐÅ5ÆŒbCÄdò¨8¦\ô±J“Ô–q Ñ…SF^Su/ìNâR.)”øJîÚŸ§4CЛ‰y š+QM‹G,ñäÛN|ô“ñŽ¿xøv‚†µøEÈfleß176ø8~!À«šÌ¯'ŽG¼4švÞåjŒçΜ&K¦tKKu¢$Ëh¨ÍmÂkURÕ$ö$Q‰ÊÐÞ’ÝJ³…*Í–‰$Z&§Ê#Ž_ ì”¢âv£6hˆ4+_.ˆŒº/ØE!IkJ| Ó…1‡ô’“\âa¦nĸ”6Œªøƒ ’â3àè÷aé§õ'6ª¨¥qf2ÎKAç–ÀW9¢›ŠëuW™F¥e 1ã„àÎ䬩ç7R­òöæi.©W5vðB‘.u\¿Sí¸èfžÖi ÉÞøÆ–‰d#Õñ!mk‡ªk;"JšâRµ‘|b  üÍÐ|ÄAVé‡$ûŠ9Nå¢âÉÁ˜£N›:¸Iv—mÖ}6ó#:ë°¥eÏ\ü WGÍ 1- «1Éásÿû [ËALÓò%Š[äùG-¦Øîy“´È*΄} Q¦®èjµi;†Ó6w7 ØE×¼ùž<4ž7fjK#–XÎ Àv•9¾J †ä%›8·wÐú˜î)È‚7©Ôˆ2¬Q‘üé¤8gaû9I=™gϧxñ­7O5ð²¢Ù¢µù6F5£u”þ·sN7/gúžfÐs"<4´ÏÇî:Àé3ÁKÜî"M³‹»8ÁêVt{ž+¾Ôtn‚5ÍnÇ&W8…8Qå~rœ#æGäód<êèg ˆÌ$A¢"i oËèDg<üBwÏb1)B>@‘¬ϱ;ØLZ.um RWíRû‡;ÉXôz¹zi{"Ò‚!HMŠb ƒö¢0Ìaªwÿ'ªÑ{†ótÞàc”7£æå;‚)z| e+h'híòYWÖ-_m¸Œ#&ÚŠ­(¹ Ø #À÷£%e nîF%2±gu¯Ü-q{Vöƒ¦G~/²É [ˆ(Ыúð®Uû-GÜv“[µ™’¥{¤ž 'EÎ|x«gF"\/,Hû88Zì9^V¯ÓYùû»™F|äþäQ5€H”ä—"à‘ö±LÇ]TRÚ#N™mSDŠá\lŒL,ép»Ó2ø®QïÖÔ‡¶5) /Ì$ïÃÅÎ0Ø…4IŒõž=”ÁÇ^œVϸ…ǯàV®×¬²ã8HÚ諹†—¡É+U!ä²àoL {ÎÞ〢œízûG•φEÖÌBœCÉÞDÔÊÄr,¸p#…Á|=ŒC«Ï<ý¬HæêÒ\â=‘x.5”¦ Ì~úïóS›¯5üX}‹ÕðÈÇb¸ÖU¥ôIdÿKS õàÝnJ>ÖM¥‘Xîé1šØ\ÿ@˜y0 H‚ÉMùÈãvý”lÖ!FÍkºØJcÆJŒA¨(CÆŽÓK—©Oâ+Ý£|d¥r Ø ƒ¡8Sþ="x“ú(‹@áϸÔ:ÿƒGà *Hù“?%ITDƒÂ#±Ø4¶eŽÀâÀXt²E–Ààr@TRˆþ>àp ¨ 7AuNZ«Q(òÚe*‰I…M&/ú$¡ù/‡Yã´È’ @Nb@z%…ÿG¦S%¯‹Ô }¥H0í’j–Ù¡Ô©mv-‡LäXÇíÒÙ ¦d%Ò -’sJ¯ï—×®Ž ¥_äü V@è–xE9ŽC4°Ì\RÓ*Ì=¸ê&ž¹M·R-„RÕËÁg™âEG»J§<·÷5û‚Üá™üt!­åÛâôýO*²QðÜ<ƒ¼¢A?žÚÍD¾ úð&-Sç£ì“…'Éè§2hb˜û¹ú˜Žºà#\²)KÑñ "ŠRÈϾI ¢? JȲ>¯tHé ÇÔbÄ& œ•@jT®"Š:…ÂnšTù£ìò #¯Ú•¡òû"‘‰ôާ)l Á­Ä®¡Ð²(¬Š 1,ÜP“-tt…;ˆ¨°²Œ4”)S‘øŽÊ)jr‡LéÊÈî'*#T‡O* =!;?s: ÅJ²Ú'ŸÌ+ 2R0DSjêd6…¡¨J¾‘5£¡Ê$λ¥lj{I:ŒÞäºHëþýµÍ`(¿èíY#Mt£È Ćã<`-3íÈ¢¨²]8Ý)RY¶|´ÕSg󈶉B:×7gó]I ×TµF ¶ÌB”Hje®'½ó:Ðqä~Qh¿5ëµE¥ª:ˆœÞÊRã RÄÀ] "Zÿ¡ØªE3¨Š ²(êUCyЬ6HÓS©BÍ!Ý ΡKZQKÑxJŠ%±ÍohØgÛ\œµÍêóŸ­u]!dŽÒª«C‹Ò‰‡%êŽ×dK+4†N° û—€lŘ\enä  Ú(ëqû`KÑŒL€PꔜèÀ#1^çgõ'0ÌOÚ ­¿iÌNos†p1«ºÙR{è„k.Ö‹k< œ8µ¢€¢)“ÚM\¯³†Û£€5í/34\³C©Ë¹5nʺi)Ü£§+mkao6óÙÅK¥³¡ ÒéþúîÝ’3¿÷Z Kî™?Ù£Y }gfÖÑÿeBÄ(è²RÇÚ~ÍÄÕ2RŽ~«¢Ú³BèÖñŽÂŸJ-¡ÍwXÛzgÜ>&HæÉRžf«…Q¼bNJ;ÑTOInb(`–Vm‘㹕•Sá@g.+ú´ÛYR©d—‚•W© ãàH+bH Ï»˜BæVpƒ/³"ËPŠ7fˉ(´5.Þñx0Áµ’?Ô;À!Šy>ÅrÙÈÓóõˆúÝäfï‘üd:ãn_#ܦõzãê(f#ñi)ÎeL E3½PçGɪHqÝe¾Bµtl_/I§X¦uˆÐ ’‡ísb\¬‘#Ió‘E˜fÌ #Gi^ªððŸä•$)´"â]ÚDf ¾ÃÝdKu;ðE 9pÃÐu#fÉT2·jJ›‰ •…Ѓò = ‹6è9`¾0”K‰-˜GÕC KMrþ˜PeÎM†ð‹y–0™Æ˜WÓ³lN´•%ÚJŠS·"ÐàèžQ¬Îb‘J0ࡳ¸S<¹6LdƇÈÉ* ,íC¹¬qÛ$J ¯MWRXV˳ E(ÿÈR(Úg“þ3l¤Ö•bÉEJ˜óš­¾jÈF4I”r F„ÅÝÂ"Å(Àÿ,ˆú*’˜~Õaâ¦J´fžâ™`ü¼ŒÈ‹&éœæPw˜á›%ŒõŒL—Ä}Æf>ŸÉzW‡ ¯WE ¢‰d­±e(€êñ4SL&Ÿ5ÉßÏE_€û¥Æjª¹°ª»ØbjB Åé‘6W쵩þ«Â À*”ƒíI—¢ñ˜hríì&èkt¬•’¾,Ár>ê–sŒ¨VУÒHQË‹}£³ÞHâC!ˆ!ÅÆ|éìSnx¬F¦V“T¿ŠÙ ¹À®T3cbed{$©f”¢°áfDñøN("1lÇþ‚Y—©ÁÒH¶¢T€’HUöµÐ¨ÀÚ@Øì@Ræ¨Þ€IXp™±€µØŪy™JH.3Œ…PˆADÇÚ¨Y/‘ÊdÎ\Z¦¤n&TZÆlkª‘vÓ…¢I‹U0ð9@I’Òã^š]<EŽ *I¨‚šd`‰*PÞ R¿/±Þ‡9\F¦æ?¿×^œbVl—<2 ”JürÄŠ÷Ô¼“_¼Vóœ%QïV6—·u±×Ü'õY¬Ì‘EàuÀ¢ÑRåp÷míT7»ÕLQÍÎVÛ+WÁ„ s´J°´âVv!\f>Z€ÈT5zŠ.ñ®…Y tÏkÚÊcò`’õ'Û[‹Í ók 8Õ#$´Vì€'Â{Xwæ]ÒG~q³ µ]‘ ½UÝ”Æ"Áÿ:‹/’ˆ¾òB½{G.—Hæ~K¡q€­¾‡T žÛâ%W Ý—:PI$šÊô¸¤ Yñæ¤sà!UF_mÑLòPI!öÒœ¨GIc³c¢Ûø{V²…̺ý£0쌬ŸoÆ£ÂâA—Âù˰âmçdbYB ˆ‡ne¬º{¸…yhæÅèJ—|]Ò™¿$,ÄØ[š|vp{?¤T5˜d®€rî²TîïE_IЫ:”¸(#Å„ª6¢ç¸¯C»Èð=OG¦ÜÊ:§>ЦnT«U€*Ù8ÛµògC0S-sJ×VðË(Í’ Åaª„tlù{C†µžÃ²à;ÖšØFR™7*b$¯Oü±®7ˆ¢wÜÊÅï +Êï赯¼€ÝÜ Vù²©Íë¹»îYÖ\üâñôP¸&¾=fÙ­HAëµðÇâÙãWqì$@  úÄ"¢.©7 úh¨«®‡ê,Rt ªk—Ž‹L›KûÀ…˜“< ú`0s 9ø|%š¢øÐ€BÑ©x1«¹¦Ãs‡¹K© K½pã6kh1m›Áˆ7H«#jv‘~Ó1>›Ž¿;"*RÐQ8ì$CQ#ÑÄ [i@22жè?$¹k “X•'YZ Ë+/BV@ð„/r(XÙ;B±‰Š@³Ñ‡Û›•°“;á=%Á¨ãò±5#}žŒ;‹4ÃŽ¾E ÃpZb:$ '5ëù»‹½ñ!ÁˆŽÂh~™…0S¯®©¼©´À"N¥Ã²œÃM¢Ê!›3AžÄ;³¼ Œ-¡±¿4‡!sg±¼qÑÄÆCQò—øîò bß?y¢©Ôw¶Ú,´Ì:S}¿ìb*c^ÁT.1´B 1I—´Å|yÈ‹°0@ŠF²Ï*À"j@,lÊr@Â\‰ûÄYˆ¡:­’2"³ŽóÔ ”œzÍKŠ‘#²>á©êT#¬KªÀ+© ¡Æ$[°±‰rãr+`«+ê=2ì¬B¼8)B1£QDH#jb¢T8ÃL³¢¾Ru!1T'Kò™$€hÃyF\IŸºl‹£ À/4w$*¸˜Ê#IÌ-œp³Ã«ˆˆ‰«¼'Ò¦œ‡ITåè«%Û¥«™‡¼Ì¯.¼¢Ç@ƒ#hmOš6Ä‚9Ðü jÀ@úŽˆèÉ ¢Î‚À,é<¾ðÀ "ã›S&™ä‚®ãLÁ¢ G¤pŽ“RN“ß {g‹¡$±Ä—‡/ó9|8EãÑ@ES ÿ¬{¦´Q*Æqm£ºÐšÙ GcJÈj¾ÐÂÁ¸õ¼ ®øé3Æ‚Æ4+Ùˆ³8QqˆÔ‘#$’Oà„3¹!½Ô%©8‘N3úôOºö ±ªŒÉ£ÄÔIä8‹$G$¸3 ²C» ‡ÊŸò ‰ÉOº-5Üa?›}» Š8²’ ê×+ªÁü(Á±  ÷%œ­kPXTê6Ša:ÂóÖ¦ˆµi•ˆ*Ñ ?4,È’3ÒD™Eaf#¨‡/ –/dGzY¼Ü€NZÞ€$6?|GM|'£,I¶|B«b"Å´°Ï¨­*ÎŽ‹±/·Ñâ2*·Ò8~ÆÒ(¤íùºF˜|Ç2BV lø3‰ÅD·³Ä@+ñlÂÉkü Bî0)Hø”#í\C‰ØÄúI¤ ƒ!Hô±x i (Ìð@3Â)×Ä;“Ê/D?D¥š:½j µír,˜ºš ¿›²LlŠD”Mð«•“3šbØEy¼‘x;Ñö¥€‰¶£}B»¥Ó1AB\·J$É»+´(ÌEᬥÝÕDI?R/Å}ŠÇ{äœÉÝÕõiR+שëvIÊä¥1¯–É»!7(s“EiÿK¨Vz Û –å‹êa5Ù(¨©¯ê/TÄТSù ¿‹"Ù˜~ÀÌÀDî@Ë62„×ùÀ±p30„T¼ï t-Brj¤É}1„ÆŒ2ˆ¤R@«,·¼ymÕ„§×ÚŒ°9t )÷[ÊЛ}¯ F´r ³r ­/ˆ} ¥:YÄò‡y«X|*š/5D¸4"\I|”\ˆ‡Šó¡1KœŒ¿\Ȇ2Z:šAL?KYl^‹1p#…äJI­Ãø”>¥n 2/³^˦Lx³¾TVºH +b»hO]±£;ˆ×ä0<ú„•»,(Ô8@œCÖØVÕï‘U bð­ •!qÆû·ÞŒlDE`Ulµ ,ôÏéZ‹Œ–µ¨MTÑÁŽå&«'"ÂjÅãĖð]òü>oa¼=¼ —Éq;ø½Xì¢Ì¡ #¹³Üt- µŠŒ:ÁÃ.ŠV ÊÚ`´™§Ss"¦«F;­w@m¥ ³ßÂAì¥BÞEkL¨púµÝÍ1äºYª9‰éæKƒ1¤ÖY-1þR~3`¤^¶¸°â³ÿ++Ý´+„IÉâ¯™Ž (“3 Éb`^}3ò]ÐMZ’ÓcR6¾±ßè¡Q”µ •­‰ByU¿YëFΘ¢˜üŠÚí+ì 'êø ÒéÅépC¼–’k‡BpèáÊ2*ŠìG;Iµô½“Èe5ieaªŠ<€€Ú£øýßň^Ô´)·ÝŠ[ºúØTb†`l)êÐÙL)!±Ðað|X»æÃ‰½Þ:i](¹(»¬ÔeÊ]‘B¨—´W£Ó4zô^qì»$>›Å3_p³õ¯Íj½… .[f왳L—ñ!°Õt&¬ç¾À#m¶F:¡¾4¼ÕígŒXг&Bê¦Õá­ñœÛ¢ü2z²ÚÅç縄9ãÓ0¬=Hžd%ûQCê×I´Åù({­ ÐêÊ^â,Q=²\œ×][à1jÕI±iþ–§šS4äk®«7]Zúµ7é:¡Ä Æi ..*?ÚÜ+ý<Iç³ØU •Üž¿ÊI^°µ%ܽ¼ÊR¨Û—¯öµì-xÝÌVl­Ú‰5}Áñ‚Br¯ CÕ‰D/#º)èi눥 Žñi¥ö>Fdœë¾ËYöF²ÙTE ¼¡HüØÈ}$2I}öW\t&Ýf­·ª¦'’¾¨PÆê³ÀÏÄmó1ã³5%nèæÌ8¯™ºbžÑqìg±!sáN B©O¢À9Š4*)³¾r¦Wê3yæ4F`JQê0³R:4Y[ÔèjÂÚ›½)!¥®Ø0‚à•â¦Â‡£L¯FîÀ‰o0lu­ùÜÅÒÒ¨—É‹T–Â_vÂTt6Z<ô48é+ÿ’•X û1\UÜf/ ÿ¼:ÐÐW©œß¯ÆúÞ§BuUµP±äÀ¸ÂÍX¡¯¤ý'X2)èmòÝHc¢þ'9 ‚¸·.ÖNpÁ!¯‹*éï.쫸!]+>ýB£pÎp |µë\F¥]vÛ!·Ý‘È:*cJáHZ˜¢ ÎéÍBfÃN<'K”ħ$aC«u˜<æá!ì–aE³·U×\{Üu©\Å žV뀦+Bã²qøéíGl<5ÞÀõP¢.¯ gäÔe@}Ç&¶Hî×(©³¦z¢ŽøÀ79½/^¾†"á{`à WEqŸ"Ô‹=õ4d ¡Ü­(Ι=: 11h£æªl™€ ²²æ*@›3 ÂNŸ«Ž[ÀÈr>Š#j2) " B:Ð¥j22Õ€‚ð“£(ËBŒ£ï“xã´+Ê~ÓK”Åïƒ\ü+ û“£nyý¯QƒÕÉ­TzÀÍšŒÈºÈ‚B`x~2ú®ÿ#Hbr—È‘*°¸ðx|ÍΚ-®IÒ„„?ˆìÜ|°è$‰%Ks*˜à,ó$Œ†-h£y<¶è´u(KÎÒŸ¸”%ŸÈêƒC'¬E @)z?ŸñB-L€I»¶…ÐŒ2R0­äC*Ì ƒòô€d˜+ ,WÉú䵦ëiû²< <}¥kDˆD¾+³âɲŽ»¨’mk'e³2‡´E8‰MiHð" £M”Nˆc¸æÎ4íM$OÔìdˆMˆsH‚'Q: ¢×|¸‹XO3Š~Q³ÙzË튆æI5µE+1ØÊ_kŸ·»ìšKIDŠ`§êÖû¸õIô9ÈfTÖe‰ê2¹?”ª®£3ðzc<çi"¤ÞµÂW%ht¨™fj¦ÒVÀy%6 {iTHü”þf $ó  ØÓØ›çñ‘W ¨5½q(ÈþÊÉUs@©¢³<ÇÒˆ-sÊ׋äXú<«H2>µ½õ ugH›9’i´Yþà&ü{%6äÿKd— ø•Ü7¬Õ049˜¶Ú]g[cZb§”DsJÙñö(—¿ˆr¿á­eögУô’À¢dE%C¯[™=Ÿ°6V§WJ½qA7L!\¢VÁ´:j)ã¤ñ×è83ìèc 2®U'Ù\zMçjØ8õ j« ±µÖèNˆø €Æp¯=¢ø®ë6CD0Œ³ä¢OÖJ¨‚¢!WˆY?Œ}·GœÁž»€$ĵµ€ oá~çÁÿtaNé=C-PŸ€¸u ÇëÃsªÝ›f ?øþ@¤0޶÷–ûáfÇPD ù—¶_å\‡÷vBâ&*ð–²VqÏãÖŠ$¼½¦5ÑkŒD*€¼‚ˆ´"Ð!A`\‰‰üO,¬¼¶”̹Y*a7-AO65ô \`„ %ǵŠ2y7‘}xwÔ_R¶“aÓ$ؤGÓbA40ÔGõ£ àäíÅ—%–VÊÃy3l\ä À¼ ŠP’EGPÛ\Ù$(ÅÊ¢-©$tK€“¸%Þ£ž"e‰Ê÷Ü_ƒrwïñwÅ’H^FÌåS€?&ãa‡ü–Gå­XÄß/žšÍÙø°ø¦xˆQƒ{,‚])Œ£ <³œ¾1w´¢‰L‘‘jâL¸^û ,H‹ÐøøÜOG¥-(Ó=i€EêLb„`TžhO%Âh_+Üj,¥ª$GâÙ¦ vO‚=&/9ÛÍš+R Æ‚,ò©@§Ô›ÆñôŽM9<'¥Ê^RM=Xd…–åy’MÂ×\8”‘ 0w¿7Ž;Ei5t‹8’zÌ¢¸cEåá®ttc˜ÔQà=¼ÿe Xcá—–àKÀm•xAëfì¨ I ®Ž‹6=HÉüD¨£Ewö| ñXˆ„F ʪàQX"‰å«9³#Èñž‹Ö&×)ª}½YŽÓV6e*ß]€…Ñå®»‹Yèà¸*ˆµÜîb1m°ÆÓ&»æÄ$H­9ßÀ»"ì‰ýÑv°ª¥\ÈÔKë¸P D~92RE#Ý„71Q4Ûx³Mƒ"riÎ?÷p‹ËÍMUw•›€jÞˆÛÌK@Þ,B6âô φHHGz?DÃê©ö¾³ C¦cM€-i­ÆÀ›¦\Š)“²t”E{Izy}„é*\PßÓqƒÄojfJ ´–“Úo8Bs°ÂóeãE´à’’;X¤ðp©¼ál.ë|"£DT»toá=¥ä(ŒÝY¸Ô§²1ØBz<3Â>ÜúKsfØfšÊßËêv«ÕɬP}í¨ÇÆi$uU-ÉrIQ¬J´ËP'I^Wë‰(&ÓëyˆºõÓÔ?âõŠóQÑ♑1Õ9Š d½¨®Òk‹¶r.ÊäÄÒU+ÅÉø¢(U8‡â¢Å’h»x7 JNÌYdR"ß„î@£ŽØÆÊ‚4µlØ€+BrõÂ@_Óê>³r³‘µ’_Ií¸X.¼¼>£ÔÙ­·g!U´£a”Üh0¹.¢n¾XÞX¼nÿ:ÆHÅÚ=S¿w™¶¼Ü‚ðœ#_ž‹‡o]ÕÆçû“ú®¿=rb¼J|_{¢5Ë42šÕŸ;ÝÈÒ­ˆ£J%d+E,\û”ÜÀsàJ™Åy»Ô ‘ÛâºnY1ô‰WúÇÉwÌU$3sœêR27{&–‡µÛp\tɱºÝíQãÚÚIo ¢,æH(ê>iÐ kÖîu—-Ÿ©Umtú¥¶¨}ýwv€ëŒ0e9~9B¤à¾è¨¼L²tí¹“³#4qéEɳª,ÒA»1!¤/i¦°¡ÿ­Û®õ“°HG´îKT¯]5îw·)¼÷8ÓVJmM±ø ¯SÌÞúƒ1ÏLÃÇìDU¤y0z?¦ÎÆôV»}ã( TÄ|£U¦Ú°¹\ä8ºÂäÅÑSmzDÝùmÁUæ3lwÌœŽèpêôÙ)j±¨b†,xÏâZFÎ) ª! ╇-kF'Cä=ŽBž‡ja…p›-ê hobòLG\,dcL ÿiè=‰˜­ª(^ö‹B$Ç€¦(: öÉ«žDeLÐk˜Œ úŠVäH48Ž$%æìv°voK¤ëÄ -RöFò˜o °Äf6ˆâÚÈ MüŠÖ…Ô˜«òÁcêHŠÚ1Å’>¤DÞJ|Å-ÉD‚·Šô³#8I–%ïšáÎÄc­XÄ X‰’ÚDò…›ÄV(lAd¢K®^mždj>"Ï l‹Î]PŽ/ˆŽHæšÛª¤}‹‚xnŒMÌ6íQJ!ôX‚2GH@ÏmhÏp\ƒJÎLH|ÁKuîAŽ*r©6N€ÿBzÃNmŽˆI¨®ÔEV'ñî$^EC`î‡V§,<­˜Km9ƒ’ßk¢Éè`²þõ1¼öl©ÉäIQ»h6Ø)zK&îEë¢Æ  `ɽjæŸaö#p$¼äˆ0¥„Ü90†ÆÌwî´Ô8_bôÑ&Œ"ň(ɸyðöV„Ó €õ§)#Mf1f/mv¬qæ'ð1 /þìî¥zÝâ6Œ ²$Ë¥6í¤„¦*¨%ÞkæÃ/üÙ¦'Æ"~ËB\JÚä(T×Òv®Ðð°á¤¶ì.wl v« Á ÿl&•€×HŠ~LFŠu é'@n6›/:qk0K¤TÔo—2¡„‘±rUgã ŒÈÖé\ók¸’NH±¯‘$ s&ïC„”³äÀüAö90L×§|b²|ÐXöï"~-˜?b$EJÒ•ÐH›j°åˆ>KF™1âcPã"í˜ËÀO1æÍ®n¬nöã…Å6 Ãð¬‚>“r¬ñ9¼3 »aþ×0y" "jÎä1©‡Î4ó|dFy1'(ŠÖ¥¡è>J{1O@PÈsRŒÎ5‰Y038):Lž2ú$'¤…JJQСÂX‰&—ãk ÒbS:¨ É Å2ÆøŒ ŸÍS °dwÄ ÷lµ!cxþpþ~“jEðñ°x„ñnTCØ?‚u9iÐë+蟦lšÌù,lý  >çPçí‹'òi,%¾/RÏèâñögƒ Œ®`Ðöœï:ÍtFªÏ7b FŽ,hÛ"H|E,G¡E”A’žÕ$Äx #³FðÎ<‹‰œ!M¶÷ËÎg‚n´bÖ¸*ÛJGe-Íœ“Ï^°èŠòÚGãØÔdÅGRÈ’ÆÒã òK;…–«€óä¶v¬''„ðMÆŠ¹.¼àÀðÓ·§¯<šøÄlñÏdYq¬S¤òéE? 1޼/&¢WLQAܤfWjp*ôÿT„¶€%êž‹‚|n`o+¢%iØo&Úä#êt4R†ipµ ’ïTBðU“6Â>?ŒÔáæ5©r›(§ì)6ÎèèOÀ²H–ÓS=Mö!Ê)"2>M2-¨Lzåêáb6”$xøÓÙŽÂr‘¨"ƒÇÃg>¼÷” å©]ŒàáèY[ÐõH ëxnÑÐxjfsǯ5µ\’©ÕŠÎâ+ç<¬l¯-ѹMô}òkæò%oN)+Ã*IíX£xgŒ ´¤¡3™P ®Lz¯î£À¹)S ÉJ4|\2Æä«d)ìîÌP¿Qp¬’'0óbK­Ÿ´³)È>æ›PnŸ&в'²¶köK\+˜aˆ¨H'è›…LÏm»ˆöî › õ±tTõq²–Cà÷’· -J1ÈÌp$ê y5°>ØUÖáä‘<NÞ÷…ã?’ýoÇÔ‰²ä4è±ÓdRÕÙb„@f:ñpö«F/]®~©ÜIU§MI !N¨ˆcxkïð)*Ûm*U–”Ɖ‚ ôKGêÇ,vÑ3È·s‚¯+˜Íáõ^D°É¸¬IskÉRƬq""K/õ.§3EÐúîȵv"Uœ"Oóx©å“m 8£ÙCRÏÏz±x›ŠäN}z º®ÒÁ瀎”\æD„íà“¢Bë–M?VDVEÅÝ.®aA© éSÈX‘âH”3qÃØ6gzowê'†É–’›÷¾žC€óµ\Oª2Šè¢g‚uX`äèwô }‰y è4„qÝZu]ƒdéÁö¸&Ï"6…Ãî­¦^_ð·•-y݆¯lŒñÜdKÃòW¬Ó‹Ñ,n†}fDè±”ðÅÃ2´ÒžT/RD"$•žíúP ÷áö"•Ïf¯¤KsD€ÆŠ7æ©6Â—Š¨I{Ppæ2œ}UKAõG¨oyH(tzḗ:Pÿ%7É+p8T©)t¬ˆT\0Žd–R‡QîKûI§0Ù,ô1¨Ñ–}ta Ó°·1jãlþj‡¤ÖDu€åÞDLGffèúÔ vâS•Ð÷€Çè›-h·-Ä4¸.Q8Özëñ$Ød~xg¥3GRíÈŒ¬¸ªp”ó8sÂá­AŽªON`nšo‡®ŒÆÏv2&¸.CšÓTÌLÖ.5Ì6„ç’w—0pØ!’Æ¢Ï ¿·Rª¸ô1 Õ!yØò›•R„òþ2'5¢t¡8ªßDí},ΗôòŠr8èŒlÃ}±~Bc•áV³‚lè㓚jܱPwé¥öcQøÕÆm+«kšI¦.(цØ^“ȵTˆ•·”ø}Íe”²q€ܰآºçwÈ9bJb€:"ùr}âÖð‹Ä}Þû­JÔy“cÅiyކ׏è¨h°ÅŽGkF¹LÄÁŠÆŒ×ÐíA¬6}vgˆQІ5Ç{¢ð.¼~/ìü`ÿ’z}éaÙeÒb…xšK§IcÛkEÎñ±¹%x¥Ž…‘c#øå1ú=L 6Çà¦úW'câNÂm®¼Ã“¤5V™•õ28ä0º<¾Š™ëˆˆ¬(fšáƒ“½Ö¢öNOµ >â>¼ ä"Vþ% Ñ= Çãz’ù¤´Ê “·9¥ƨXö¸› fýY@Ž+(eü‡^ümG*cWˆÚSâ\[§C§øn$4*`ET’ëÛ#jI?ÁÓ<44 tº´›×Ù˜¬¦¾âpþ®ºòæ»_¸~¬˜_Bf«*Îßiôº¬È”éY©®€&¿°Ys,ÛLëÒ\\U¦8ãô9˜Ën<¾øçd±–y¦ºá/Ë ²™ I žä¢H7^žíZàÞÒØA“aŸ0mz¯#Ä’X$ó5¦ƒ³7£srRPY m¢ ø3ú…?àÐö!‚b€(´P Æã‡óê@Û‘G¢À(ôõ Fá±èl ü™L#Ù,6|NÀ“Ù,Aú ¡>è‘ÇÍa ’Æ&°J÷ŒLŸ“Ð$x Y£¾iqX¼R Ce`=žm%‹D¡ÑèUBÝ Æ$´¨µšÎö½YÀõºÈ]NˆWi‘èôÒ)J-Ql4"×À¤±ê”R¨ZmT „—5P¢F#—i6J ÎP31¼h s ƒì®uà[þ¶N ÚûfÅý ¦E!±ŠÒ-TÞBé¶ØEZ‚V+7'ÿ+§Êê0âÞªI.óë^¦Åáñø—ôwêÇ7~ï¯w‡ÖÅU¨Ô{Š‚#Œ¸•=Í{¼å¨ CZ©(3Œ :@à5R$ººÍëŽ=" «# SK €RÆ‚/èìŒ*ì$æ»ÐdO @¯À’¦ DVƒ* ƒB}ªˆä2Ú£(›†¶?ðCÑ"GÈЫ!RŠ  $#,*\¶Ï J¨¾-ê#LäLÜ– ’"¨˜*‰B8¡0ò­$jØÂ$«úQ,ªÚ`¿¸\o=(’<ñ¡Ø±F K´Ç! ä·&úñ&JBÌD©k׸T…£Ëä ~¿ï’Ê«'¯Ò¿²ÈÚv|>B<©¦QSmOŸÌ"8ª:Óz6…*•‹žžÕsµy[Ò „Ad ‘Ý:¤¯*ˆ9­6ò-TBdÓEˆ£>‹V•2Îí¸1ê‰0 Ê¤ŠX`¶¾1ˆ²` @w”/é*·Ÿ·Ãä¦UÃó €Qú6¨8!þ ]§ýT¶•Üp‹Av€ÒViÝŽÜŸÓ+—Si솋a¸ÚK€¶¼lÂDL|Ë`HTåôôÕ{ËÈ„…bD³¥²ö·pô=€æ+‰#DÐ~‹Jp–¡±s\¯€/Úz§¨‹þìJÈ´)`&IBa¡Ÿª¦LZÉêô{N6-Áã dZï»ï2²7TŠù/ô£á;Ö¢¨ï0Ц¥|À@kpéêbVײp n£Ê‚ù*¸åÆgGûž}7E·š¸¿ÖŽm(†Ó€ÔN[äèíI“9 W*ªzŒm7~Ç4€ Ë[ûsÚÄhܾ™P«æÃ^ò—KåUõö²å±T÷#€0µªó·s¿Ãì®^¹¦]*o R-ÓÝJ;Ý— Ã>J…‚ƒv½“CîôÇEމdI!ô7¶‹ãš4fÙ²»ð=ಣ& =½’ƒ_ )p!Õiµ£ÂÑT ’LCîµ7nø]ÃáÊ:â(±ŠË†Z¨'˜ã›óWª¨‚?Ʀ Û³±xP¨ ˜˜U¡¤‰0ð|Žk#Åø¬¸…¨kΡ€TÈ¿µÑ÷*”!Eð­¾¶ÚüŽãråýÞ4 Ó‡ú|i‡ÈÎ&XØê×éÕ.Hz=¨ó ¢2*ÏÔá¶² G”Qf¯À‡%"z·]ITˆ’H†§ØVމVˆ‘±5©§ÚùI,™~EZ+C±þT †yP”Ëã[¼„CÍÙ¼Jw¢ÑHka“GÕä Ç|¶ÜªÍ~hÜÎ=SìÏz€  ÈG»,¡y§[öM‘dª¤Û³Â#s+˜# Oàܳ,ŸS"Ô ‘¾¾? |¼½ž€W“ˆt6Ëг’ˆtÆh=º›dl› ÔxòøÁN‰-Ü™P¯B{QX,=Õ$°VSö¥ hÑ[T¥.€VðTŽtZ‚&Š-É@§¬Š0ó8Ë :­‰-5íF’ÎGÉV£¤5‹¤¦Šañ葃ôÕ8ˆVéÀ¤3‚HžUZG¨êz+4®,”tã™2˜Íá>IÐR!£¤a¯¼ò Íeýh€Ì­„½sÐ¥Š9ò#Œ.‘> b?™Äsâ’*åÝ/a$É©ÅÈÎ9²ÎÅ 3iJ¯Ùh̪i%“xA‰ìKiŒU ‹@Ó9y0L”™D\“>JJg›²¬”&Ù›™TzaÿiÒmG¦Á¬ü„:Ìw´ÚˆDŠ0§qn—÷‡6 ƒVeŸ!´Z±¢pàù¼Yë<ªkåFÌâ««Ø"=Âm…ýÓ;lë¸ü|æî)‘·^Q'Âéµ÷†%[ ¶Gª¹À].]ñÒô°™`ùDœ„ ˜Y@Î#çl-²XJhä-Y¦…mPÀü¹À9'$ B¨\7œü€>CÄ)‚J%@‰õ¥úƒ-•í­ŠåÊ ð­AGoùMbŽ[©^ÓJB 9%n0™D€E %RQ¡„zÆmâ¹€<¢ª'‹ÅÌÎJdèød“éjoâI>8ŒÑT+Šwg¹äÍóÜsk2MLt.ñ€9%4T*´y3Osi:ñ%’nJÀ'k MÍ€x­Ì~SðCtCÅŸ¦Ñ¼Us‡—IÀ‘×¾…$[fâìc"ó=8ì€t(äJõÕ¡T±4¼ÎO3´ˆZr³du€ýf©W0åàS-úD¨$Eý—é¤úvÓ:pMz£!N8Úr™¬åÒåöü•REZ:—ðøØ¡Tªêý¬Mƒ—g M³ˆÞ·ï9ÁJðó9³g.Ð?Ýç±4DA84Û[ÖÅ6¥WˆŒJ[Æ¥½žÓiá™Më=W8 T’w8âÝÜý -ó [®F¶i­ea^AtŠÒÜDâv©µÎzǘ(€æa¼Y²;kÙ ¨,«i®ðÖñ& »aêS>S›=i ÃJœê‘hèë.ÚËvŸi¶;›—œžç'CY|Þ² ˆŸ‘|»$  bVø„(õ$"ÅÃQFKAºŒ1rŽºÇ=‰Ë$LŒ2å­ˆoHaZ R  Ó0x}¸cE&©¿•£1»ó^!Ë¿àëË\Ò ñ‹àzÉB5)û÷ª‹xšÌ„À­–ê$ƒFÊˉê'š’êº{ù x˜= ÿŽ´kªàש‚š-âÍÈ3†Å:*ˆ‘Z¢ŒÄW+dŽbj)¢ÂÁ)‹·+jË,’'¤ ì “*꘡}:ZüÇ‹E§Jº[’#¡0BŠË…’#6¬žr‘6SÖ¥“H›¹¾Ú¡4’:-4#§¹òÂÛ… d|¦I‡›a°Ê‰ó¤'´I2ʼ E¢Œ”©EŠ––º„Žh”)H7Y¬É ú¦0 B’v2’ƒ/¹œ1ÙÍÁBà€’«âÛ" |²;Œ­ ±Ì*)ÂÌ¢ >1ÿ?{ĉê1šéÀrPÀS¥¡k†®søÒX?Y:z"L¨‡òبêÈȬÄí¡´•ì0‰”R¯šÌáÈK¬‹1 @ŒO)>¸Â,t‰C{/«5âë®’YD€‚!Õ´P Ú(²y*c„Y”" L)Ø&sW4`÷££ù·›ý ªÐù³EHIÙ]@q"H¿•ë:(«9LF„¿DÊQ°,CÐ@IP|­ ƺt'> Q”íÆËã@}²Œ üî4%ˆ„ò ÖGúÛ«ý'K¾E Oµx’»³4£†Q¡¦ÎÚó+8~I™ºù8¼ËP›ø¨*»¤¶ÉºÆ¸Ú˜ª¹ÕÅ!¨µR<(¢lD¡?òŒC¥#¶È‡§:»K  ˜î)\#,LÖ<›Ä’(’䷙ܖèÎ2²‘,2QÉJ唣ú#²¨Å<í¯É¿IÂ6Í›àÀ‹ ¹à™)p¡KJò £ÒOõ0ÔÊl¶õ?I"ä‹;M=4ÂŒ#_š1 +àP|#³Û¶Át£aß6] $ÕFÐÛA¯)†b¢ÇkÅGÝ-7²¹ ËßÔã¤Â>E‚yºj¥H:}gÕ Å­Ä7ä¸6:OÒžË I@|%‘0 =i¨²IñeŠ4Ñ´ ꨪdÚAñÀ›–Q)¥ÀxßLl¼~”µ–¢ŽµH àiÙ ŒXxÙÁE°í iÎЉƒâMåPƒ‡ÛÂH’7ÛƒŒ àyZ‘Ö‰Üü>sbŒiSõ€*«)ÁS– ŒP-2Yâg ù¸7auÈ¢ Áú¼üLB¼Hˆ¹+5Ž"•sOÓ݈j4/”ÙO:íðÓ }е'žõ¼ËÝ¡JeŸŠlZâ\rªÚ{ÆÍÈüX(,ݧ;–Õ•[4€Ü½\Õ¹,6Zk´Ã­Ç¥9I«d¼H׋å…>ý“WãÜ7™ÚWxæžÔHઌªãpû×<0uĨ2ÜؽHÊ*"'ô‡©ÄoÆzǨ+3ÃÈ™Õø~L#Í[±*ÐÓÆŠ<{Sd€>%1‡ÕN ´ò¨)¿*4€C@ ÷$g[à¾V4¬4ã,úGò™ÄHÞ)2È¨Û ,ÐQŠ3_Ùñüù£ «-I¼E%‡ÐŽIp-¬©6C¾?´`H;W¸û¼[ÃcÃZ::›ÍÆ$)àë“ÙÚÛ°”D)Í€¡(Ñ÷R¹ÐáˆÓ‘ÒCÒ]kGàv‰,*‰ÛöI”wAt¶¥^šIùag×å “4YZÜ/¹Ù^ƒž+ÿÉ©BÅ#ÝUÉH² õkˆ_´. ;³Mš‚ªŽ  BÙ2W¤ŠÚ(˜¸…+]«2-õ>QœÎbŠ„§F‰íŸ9úX-MD•>È ?”,^Ì+à€¡ø¬²Øˆ üôŠÍ®(>["¿ËgºרéE™l¿ß^ÐañŸ½†Ä4/±Ü4Xs¡­gOÐ…)™ŽãFËÒ^º ~M®¦$[É •eZ”=b©¤àÕò~7ž$Ùý†¶k*”êW馣#â1T#¹Q],À†2è³¥´¾Ü- £b ¨ÓëÛí”v!ÓÕ5\(© ¿YA»ÕG4$“¡DF‹fA¦noÓiÇ[FX}¥e|äÙX ¸‘+ë!Âh º]]8ä®&qÒ7rž*ê› Î'8ÿ“¾h „èRš GO5á câì€'õ)Œj"Vë|ÇíNÔÙ#ÈôW +‰Ð*&Ê$]Ù}!†9]ЃDãÄL½¦ÁÕÚÝè™Á2¸1ˆ‹È½'Ãä6:3¹ [Ü•Ñ XZÕdŒ!¸FͪÅP(vX_mfp=~sÓ¸P›´=ùRYòÈÝ]f¦°ÐÕjé Ú¹þ°5Rpõ; *'× VaÄ'µSÔÌÒ㤌y}·“Í[3˱gD3Ó\ªe›8‘+§ÆÚV1yŸaR7’ÄŦÁÜ”)ÁB>’_èÃÜÄåÜÆHàGV<¨›¤8`ªjÉV㢃f¡‰î«ÖH¶IæÝÑ=ò¬vîéCÍX²¼¶>ÑUBÇ*»èes^=Ìß=-æA‡¨éR¼î–ë‰×|¡ºÔž5ûV<¦Í oúg%³­™ÞÝ Ûì«>m63 NíÍ0 È«ƒ MÁá¤äVËl£o«Ëjdì"*å¾9±„ȹÊÉgCÎÑ ˜áûò¸, çÐåÁ†}8ÿr&å?!Uÿ Ò}¾*5¨V—njEÓNDˆôHûÄöªbçBK"k˜õn^ ^ÒùÚê’¬~ÖØiAÍæ^VMâÞ%W2gÌiög/qZ⸠·…ð;Èšî¡üÖ±ÊÃXs÷vfÓñ»pN7ÑNj·íηœÙNƒQÒÀ}: ØŒ6ˆlABÈ¡ ™²3Ľ»át‰Ê2RÔÙçÂäz•N Eçøˆ¨0ϲLâÃ9/79» Ì”5÷´AÍtÍJ³3ù¥¥–ÅŽôf¤¶ÍNY?~þúó€y¼[C3HmÂa˜¾y )‰’z’ôšöM4Î^â/™n5âŽ¥ÏÆArqpVäÁ¦]‡4abTÙ×'ÅÕKisïªæ“nøîEÒ;pò‹3©f&‚?w%4p©ü=ÿY¶Â#7/ú˜—0ÚMMÎakÅúÎdÚº0q9Ù÷ן5“iµÍ¾á I,ä"µŽ±©wÂ}Á02X3‡mÖ€Ãx¬ÇEvE/ÓÞ¨€ @ˆ#ò „B`@ü5ûÄ_q7ôV ‰¾À‘¸{ô ŽÂÀ28\.ÿ“Cd`LUüù˜Bb 8\¸ 7—Iá2x3òf KŸ8L®RÿÃa3Ì&€ŽÌ㳨DÎO¤Ê S9uv+'#àYÌ:+«YŸ¶ZD"Ñ}\fài`Ã9­SêLÉ”ö¯%k a(,1ô4èD?08(Šz®+Ë6þ#©ëÂÇR:>¯Ñ¢+K­Ï¤tc;VÈâ°Ç FHÌ6©i…R%ÓjüÔsb ˆÓý»XÊ{ìA)×MT¶²F§Ê³";FS£ÎLÀV0ˆ­ú#­#8¬Ð-KC;NSõ ~XQUxý S†½ˆÜ"¨éutá ºçÃò¶2‹UJRx€0¤^RGí¶3È꘹¹ðƒC ¡nHY9„#JÉrg–çLÞV++äfƒ;©Y»§¼´®<~¦wý¸šÂ+rR³ê/sÍîêO"0)p³å-ÿ8ÀöíWœ£nÒãV€n5wˆ$´æãJÛ)†³Hëꆽ0ÃÀz¾|Ô3UOŽðˆ5¾ÙÉ»¢Àî là\yÉWúÑý/B6&RˆïWÍ®k W¢,×(óz³S"é]æÚü§-ä¼eÕ£»å|Å;Òf±¹Ze‹­ÕÈ3AÈxS ¡ @qÕÖ†¨úV1{”?GñSLç©ÔÌØEy:ÒŸ KßJSûëêh]!o#«^ðÎj©PƒGÒ-•F©6–?ÿ=eÄî¿uš§“úú>ãõ¥âS iŽsãñM,×”ßÀ O%ÉÛ“r:¢Ø3zA`6®t€ýo‹ù—R&ÂI2Îuzò˜îÀ!¯"oÙY¥”¯•A#zi‘Ò§Vkˆ‘"g<Í•4ÀKë¼ÅÅã½tBPYÛ-%hž‘“ÊÐX4M?1y@h졪ÃgeŽ,ͨ÷71%øV¿Ö1a$<±£†êHÏ+¦Fω⯃ÔÔ«ÝM ËY˜ßRÄmå‘ô‚=–cÒSíF÷ÄÚË‹ufZ6 Ü(ü;‘)اsðÄHC-‹àc³3. ü +-y³×VïÇé'.fGB+"Àä;euƒ äÌÉ!«>L,dµ6 RÜ"f¡^ž’€‡ÉœÜ\è¥Ê*)œ?¦[цV.Ræ‡Û£‘h…¹µÌ„I[8˜0E6‘Õ¦Cä4 ÅÎ3õ+%¦¼ý!óÝKÖì$:›r2È %(¢>æü=X̆>äRµÞÉ£Ø}Á¨ìÓmœ<¦)Rze›]£äÓØHÜ!=+$f°áý7ÙŒüˆËå{¼H½Rêc#Êi»UÏR´9¡Ï¹õ7‡ÙFª3ò#MJ±1þæÐú¬˜Í:cÞ˜\ì…5qá€*Ì ÜÈ«-:Õ¨))âÈ]5®ºËPøÀEƒiêZÉ…5KÛz=Ä}«D9&¿ÔÒÆŠïc½X,á–.hÄØz0í]B2%pÁ£²*ŸIMT""¬Ø±¦÷DÝqCK-ÑÇ3^jd4•v©ÒhåQËqVQÆÈãFßC{¸=´¥Î'"Ù“E<Œ¬Ú„^haˆCì±Ç±ôÞ©{Ï”’¾’&Ge`w¨d ¬ ƒn—°AW¡,¤ºÌþ­úÅkø8.¿zÆ>áYïY§(4”,Díýy¤úa*x(-Ç®,›´¨6•¥üÑ„ iâÕW&¢1=¯Ö¹½Õ'ŠSëóBµ(I%•ë±.\+¢h¡“)>šÒc†pð&2‘:(ö$fw.µ;2ný$±jl,l(þY•­eÚKgóáq¨²4¼Ü²2é«k;eõÊR×àIXE˜!±-\[ÌËTm}lª(¦˜·äwD_%Æ4&qÚG¿T ýsvL¬ÚGTœ¥Ãa²ùw:x"ÂЦJ×Î ¯瘬¤ûW"‚Ky0wJ{›¦„Æk®Ký6u¼=Cˆ3™â2ç`ÆÉ÷. h[¤HÒÀÒq…çɳ`Û÷_wFô\'ÛQ’ùy†SáëöÏ_©•ü4I½Ý¦\è²|‰"²›wŠ´o Žò8›d¦ÛdW[Õ#‰~r|ÐÞ+5Ôz±7,ß2žOPD¹F÷´N4ŽœdZVClTׄäÞÕ”<~˜¬”.(‰IÜ­vnÏžuÕIÐ ¾SÅ#:Ì|Ó-þeŽ}À(ò ~ìœùQ#þ•é­t€µR½â¹¬îS|ÔP-¦û}øú`El‹ÌÀ~TYë?“†ø‘ •„lÙØ»Š°üVñÜÇ™ † rŽmªÂS#ͥ̕ÉóŸQÿyœ,¹¤VÛ;ø—#.—Õú>äÖfœVIxÛ¯T˜5›Éæÿ@­ë«Çï'Ü8 ñ  \§K3ʤ3u…ámÚ`ߪMoSrD×ä‡Ô.Ö0}Cs=æ¹ô»,Ä" µdu¢/·÷,-rq~‰ó.+¯>Þô¨ƒd!tÅÈË*üu¯¢ÿE±ÎrëÊÎÀ©Ò&îj\ ÒŽ$wBN'ä¥/|KÂgñBVÝ06½CH³lå¬ßHX!é¡ ¤dÞfZÒ*†½í\â¯RðŠ.p­l˜€ýã-„ÚlD"¤f¦Zð°Í!ôx¯/â>2Ê0³ïÒƒ†‚nX|B³IÂ,B>ýlšâÏ8cˆ˜˜ ¾¸ú“Hôê\ok¢èl ‚ ¤º/.¯QŠo-þgÝ (’›"€ÎÖõŠœ¶>KŽ\D$ޝּny‘zÜÎ%íhËFv´b Ã,È%Æm¤¨.)Z×qˆì¥rªH© MmHTí"šBãƒÈ!ä“è,ŠÜ$Z-‹ðEЈҘعêŒÁäß är“Bg!B€M 1æöMfZŠŒ¥ëö½Qš}Ínr‘¢~,V  êhªÁ)Ücže«ØÂɉ­ , ûâ.-ª®oÄÆE¨8›hL€ÐêjŠad&ÕÀ µŠ[¢z°åx™Bn~ðœË‰ êÁô’è4’Öº£eèˆò¡ñ œä"´‹²žÂp"­¼lßo±d¬‰fä‹Ô¼lžþš#£žÎñ¤Ìâòª©_Ëpú-@Ð*ëÆ(./ê¿ñÖìp1!üVæ”§e¨šðà\ˆê\†Ôa²ºËîÈh¢˜vqXª§V¶Ì¤ÔÁôýleîrZòrÊØ•êd[O¢¯Êvè"FË,¶ƒÊ4Å()8±©¦ñÆããT,!é<¤ÃqTÚíÈ-’`_.Éà¡Aù91²ïÌjzñÿ§)‹û °’­\ÐF¨ 5CüÞÅÿIÁi®|ç“@Í ÜKªEþ_î$ S–ÜÉZ›âæãg³³–3£Ҽö2› q¿%4\lwA-{e”ÕbÆrꬣmÇsP–ŒB‡Â`MðƒÊèÓÐ:È©¿Dܹ!õ4áü=æ•*Èë2 Î üTW3ë¬I Át- ênÜÔDÞÈ Ž«E0®”õÄ%)nØ¢±p1Ä?#´ºÁ°í)ÍWM* Æ6k˜¤rîꊈ ˆ%*¾ƒc=I*F#3ÂVõ(tÈV@!S2‡@ãELÌ&enÄëÔÖë$+ÐQp¬#açUe®÷mÝ$QÜÂVÕhH§fjqvÄ ¤¶lM®)†@Þ5xkãCáK OÆŠ´ˆWÈòLë:ƒ¤tà4?¨â¨ÏŠT”>ü-4°<%ÕžšðrVôÎËn¼Ž´€sK8´bs¥ÎÃjs#D¦¬ö„Ù”rÿµ^¶zñIô44šÐ š¤‡6\3p¥®ÛbÔùÇ«U­±/£Ï$§h{b a æñ“!?±Ø +-&,3”Ôœ •DϬƒo}Döb›A¯¶ŸÎ“D‰ÕH-"tÄSÔh°sH÷FŽÕrR@GeG‚Ë0غê¢\0QA†xœÀžôZC˜‹^(òNrVïñNö´(['L¢a*ìL¸é×mïn+€MëZæPÂM›>”&oÚ6¶ r£ n5oñ¬OÊX€Ú”‰ÉLd 4Ð׎â«ìÈfĬ H^·T?." §kÊȃTŽ· !¨ò)ïS"ÐŒÞb]Oï£C£jJÈrÈûŠHμl².k~ÙÃÅ6ÿj„×n²°þ‡‚f¢'\çL-ŠKQÖ’-ìr“mF6tÎrsrÝKÉÀ~Tëu–˜OFšw]Nn UÆMæM§lš÷Ë(¥Œ¯Ìzû0õNÊE$¥‡L‡¶Ú5K3Ê@±®‰bWTíOá6]€Aôõ(N4õVJñz ?ÍW¤Í#Œ÷„ ¤í¯e)þ É>Ö=8FL¾l GÇBâqÖì“@w¥ØÑXBº|ÓÔò¶Ò Š+*ýHcBŽ´gG¬vañ†ØŒ†Óò”®´‰£Ê(ê0¤g7~8)S£Ðct”$äD&$äX.&sT©à&æP‚}…1¤âµõ`zg²‡…¯Ó”<’¯#Öÿ5—߇‰®\ò`-†{Šj  tPŒ÷fÎ+XpvsÕ†äWÛr4öÃŽâ)€è˜4øuÛŠ?”Tä6Y´H†Gä2n¬ É~(#qÆàÅO êùbâõ,x¤rtn—E|ƒkS <·þ°5âQTÐXÓ­ÍÞúQthö¿ŽãøÏ/Ž-BؤPD~ôënاdÀœˆ{ ÍåÊ(ªÀ0mr<\â„(núÍ¢… XY©ã2N-þÂ.µÔäK§Å=–i#Ëø;´HÄaù¸üOÙ;9@¨:¨Æ_jˆ{ž±5ôc.g>9BÙªÍ[ÀËïrúq³x=m9ýv«Ž¬Ølì¹`xï[ñ3ÐÆK»O_f&£ùuN." U~3‰ïo8Dàž´—ùY—ê)÷×$Œ6GLi¬¤²žD?(³Ï|0nèüÀ7ßWwá:²š¼cÞF¢€e¬ç9Æ–þ\#<à´"®¤Š=ñcÀ #¯BÆÃ•SŽÚôî÷ûDzÙƒ2€þ9ú`ÑëŠ5³Tb¸’Ô‚wøŸ&Ž,,Ÿ —ã-à °bÇ‹.zzï±9u9—\(ëFl°zcvÂññ„ÀOK¯Z£j¨ñH€@;°wœöäR“ò÷(·M//4g®æ(y8ú5¶L¦Á9ìŽ! ãÐH”Z½W¿júÄówšø‚/$Ù%5^ÃUq‡ ³‚qL´¿^øÚÀ©[@ Κ˜6º‚Çl>ý‚è”êkžÖ©FN6ñ¢êBtJªqV–°tXv©Fù™qõݯÍpJ#O,ïܱ¯Ö@R¦VVCb‡Âõ¡Q¢ggºªdã¦cMPPÚ‚Ô«òz¶ ÒOÔ•¶à«ûFª‘1Šëj\ueÃxD„JDÊYºäNô‚sÓ¼âK‰¼ûhd þM®É¢Ò¦œ¹(ˆØËI@³—H̾®;­Gi^_ðr㵜œ˜Á+4õéIlQ3¶8ÆÊvþü›¶éQ¬Ü†ø6¨º4Š0kÍò‡·âjo>Ï5¯ý%4ó«TÕ[‡ÀB.m304mÎËy§Ü,.¦nsc=*üæÌ¶A§¶(‹Í²—é\C÷ŒccGYU»l7}óU †NˆÏŠ1B¤É>]—A°nƒ-s!ðM¯¿jаx»Œ =Œ›ÚÌÚÒ”ÛB©Åï-æñ`i¸«ûŸ¿¼öÎÆðI¢ ­ oH¤ï aQ³´K_t¢?„Swo[I9þWŒÆoæ­J¯@2pS<‰€®ò7Xgï~*Ô˜é'j“{_½Ò¯b—í(¯Í¢Ë‹I]‘z_ýù/i`Ü#**N-æ†X{n,à Šn–0þol2?ˆÏr÷`s3²Ò¶¨7)F¿—ùËó/8Òƒºe.Ál3ºeº˜tÔ§ Y®/ÍŒÉh‘‚¦z 3{Çl³S™Š4™G 9GÝ Gš-%oáKPB~Õ^¤å^ Æ›ê1µtl”mêbíR"tFéœõr—Rú/tMƒ¢äc*U"q}4ñkª`yÐ,/SUaçv?â㕼±Éu'Í?[ÝÀ5ší5›š¤™è{W N0Œ3…º@潪òH'«âð ü¶ð#Út›7ƒW¶€&\ÌÆ”•¯?j?Aö“ă8;Õw2¤NnÓÙÍ¢;E¨Áå4¨,ö{)…Ö#¸úôw%ÁÆ«à¨{'ÊÜòVÐ /E›É1Z|~~{¢”ßa·¬FF 'ÌÏfRpNïdÔïãôZ”‡OF±i$8ì•;ÌÉçs›•‰ÿ°~P9ÑÙç¡!“̧¼(<ï­Úg$Ö,ÍÊSBŸÁh²< ª ÖåC!¼×ý"SE×,Ž£6Â)ËÞ!ìØ# f¨¬Êdî#êBìû°éÒB‡²"Ï2«2Æ®ÊC€¼@G *ìZJè ëcˆÉ€.£º‰ÜPÓ»ïËèǸo#¨œÅR¢¼ ´XH3qŸÊD^ß:‰¼à¨‰’RKn*⯵)Úz|Lj:%"ºè*Õ6¨û6Þ¶Ì£Ó!é3ÀǬòÏk´ %5.Áÿ7¯òBà ³ð¡&ˆäã("Ié³I!íØ»JHzíJÀÒAüš$è|Ô‚žõ#zÑ'h{Rœ¦ŒJ>‡¦Hzh»K`BvêGQš¾JË 1 Äê%~šQ)Mb˜MoAü·¾ó4’¨LýH{Õi„PûÂóe{l·¶’FšC‰<ކÌ)+rì¥V[P±=ÒUsJŒûR̲à$0çÜëÚÖוm#òš”ÀÖ0I ú¢G6mPÝ)’…t΢>ŒTL}úûÁ ªw¦U¥úÓ2O½äóÞh:e -Ï ] lÍÁsÙ |å C—KE•´h,6‚Z^†×ôho ¨Â… éê‘i.ˆTZCúž¦EÕå¬óÐ7"|ƒ¸Çú…°O¨:F¤&I8ÐIyJ‘ȈÖÁqŠD°'¯’´‹i•šBs_ ˆ-h®!­:rÍ¥7}hŒ'0ª·?£ù®×ŠZúÝs©/2í:²U‚¿ õÛÈ»O`m¥AͺÀ…­ì›Žå±áù[ušð®k*%êŽÜ•¼#TJü‰a‡íép¨¶ •åçܳ“½` wZ'©¹ì”èU‰–uÞý¥ˆ¡¤†f¦P ÑT )o#èûÉÓ7"Ê)HP¤ð’Áv?C {Ÿ‚O´»=È• Êùtq…«ÆFjÝi™€ 5À`y×£Ô=n=¢&ºã|þ“r.ž>§ÿ&äâ"Tñ C3!<ð>ñÐÊÅ™éFÄÈ”ŠS ¨! ˜ ~Ì9NM)Å-"dP¦ÕºFªúé©ð¢ Jª’?‰ª î È•š]¨ÌvlºlÁûE]ÉT.õµV:¦Â)!¢P(…ï=Y“õZr§Ýt°RûÀ)ED„Iz&èÆ¢Oád«i¿-Rˆ‡(ªýMñ¦™Çi–DeiŸO5œc ëo~,`Ó˲¿U<,v°+ŠÉæ%Ü¡  ´Ý÷ 0T壤OI¡]‚N,²V›üR, žõ3Îö»Ð6!wB“˜•Y@!Ö7®b (zC@v3Q7J¢9ÐU)R¤öê€Y‚Bá“óœ‹5C†À¯î\‡Z4ÝBµ?¢½óÁ‚ÁzN“ñúpQºW¢,?GRò÷‚¨É‰J±éæ$`F¢L“Yy°1§yÊB•¯cΦX£]+SƒmšÎ˜2Ž ù‚¦ÆÓ/°\óU¸˜Åº&% &©b¦¸}È»5Gë©¢$îz7zÏÛDÓÊÑìÂÁ tP™¶ö+•¢e¨dóª„t¡i,E‡”Ö¹jþ@­$£&ãÿ(”Ö÷²Ýc…€ xæ­ÂÛ· J-ÒÅØQë£ãô²%rÙÃkÖ'Ú•¡-sÉë3òŽè˘p°Ók²…~–_K}ƒ³ »VèûÒ̰4´®˜­a2eHŸñv¯ü ü.ʵ´•ú1‡tý_Ÿ9<€Ý‹e„ãþ Rü¼òÞI/$}D¢GwÀ9›­(.”*|û$7¶¢hÈ(X—pñÈû©ŠÉþD©´Z‘ãöxt]¡Ò:Š~Ò~Ö ÆŸ¦ ·(–~¥‘ÚÒÉm5,¹v^ðµ,ÿמdÛ…©K IÜ’ƒ´Köz ñ€jky¼Þmw/ïŠû ® Œ!¼ANŸxqÔmbÅÊa·²w¬1 Í` IQw~ÔeÉ)n—È6”ЧìQ@ëz,£” çÚ—(Ü"4ºhëZ¾>y©ys+P‡æaHýZˆàYöþ˜è:h!B$ñw¬-µqÿT¿Êþ™¾?X?DÏH#×ò’B–²(R*ýÍÀ€ø‘¼ èßÚ·¯Ñ‰SÙÙy‡YÕ_4IX¹Ñbš³!f r`_²Á«ŒclŸÁÿ3 @0Ž™ÙJ¿P| Ûù¿óT Ф ¨­B=ú'¡d Ø”Kb¹  Ù1X9¹°43 >Y›c|ˆ±sѺúN#³R#@–‘)7»S®d»ê‡ÙÎ0Cʵð„¡)––*#š9‰Ê´ƒÛ¤ˆJfŸÚf¤[@­{4¯ZÓ:kFë0î¨ñµ‰Ü¬’eÁ_Tº3Ÿ7Áº)@ÃHJ[‡ú&¢)~®’f¼Ô½$$Ú:·2 )cÊ5X~¯lH»|D9©Á©m-9l¡òŸ2ëj°4ó±.[ã‘w¢*îâ–2ë÷BØõ2™’ $+¥›@CkC §KáɸŸ‹«$*&H°¤I51÷>œÃ[¾éŠ8ÑÜ9I1ˆYZ@Þ›é1²Z1•ú-Ñ Ú&‰pz ÉJ¶BZSœÁc·´ñ3°ÞÀ¢T Æ *D J<³ÁdFO$\DÀ|³ûñ€+kHT“"iº‘-2ÊÅ 5™ÐÇÒu$ ² ‘JJ]¦Rå‘B”º›à)w±sÀj À,\9(°‰‘J™Û 4Ȉģ¯Do¾jÆEZä#‡ë«B¬@}¢È‘›˜ Ô ‹›¢Ô`/kmÂL ­š±ZB3Š+¢š¢S’ÓÁû Ûk$)Ú«HÓÄ”| ú0¤ÛÙYîA|Bs'ƒXBi>øC ŽœªöKóéB|œ ¯jfl­K4»"Ò‹ ö¯z´?¡ÐzxC ýµéŸ‘„,$J “n@I½´sÉ-BY)ùtÇê" ñ°Ó³sŸ¾r÷åZ‰ªË¢‰éJŠi€Ä¶6[ <”t&AÂ’ØÏž„D7Ä?¦|T$ü¼-4eÂN©¤ãMd,yøORNìVÄÓµ²ù}9ô¹œù”ìn ÚÖAãœ9 GÁ\ÿÍûŸ¯ztśוá–x„©8£"¹Ûä T™4 Ï‘ ?·rëµD¡Lü ²z!æ‰HkÑ:ˆ,Ý/ƒ›Áùz*ìuÇôžÃ°Š6€¹JŸÌÂ#È£V8뛹®½SªÑ‹‘#A¨°«Ÿ ìD=“€±ûqÄ™ÀÒ@™Ûe¢hû‹´±<+¬:ŸÉ°µ¬Ì’™ñ°AÉ%Àý5H”¬‹/±Ôƒ·˜‘#à~*× Ë˜ÃúGê€Oê¨q'ÀpŠ$¡f­¢€Ä‰–¯½2:ÒÔ«¡4ºéÁ‘®¸„`|,T×Q+{47½ˆóÔDRòKE¼6óIN”é;½¹©=[*ø‘¢T&³‘'< ™jšÒx­²š±üÔÇ`­$*’µ(GDtðÏÕ‘âA$}À’ÝS˜|Äi»Ÿ ’Q»eÁÚ ¦ÿì{L«´*Òå”J«S5"Š>ë.É™t4% 0B°¥(ÃK¦±’|4l‰’бYCT¡Ú]»à~4€š >‰ÌµÖ„ƯS-èž¶øW9®½r AŒFl&mm‡Ì¤ƒH4„¶%9®Çë0™°· ~àýʹJ+¸Ì±ˆtúÇõÁQb#Â{H«4¼l.[¬.ÞJ „¾†M #Š ?_Ú& ‚ 4û|"5$FTeæra—³FØmaÔ Â‘'¨€ë;r¨Þ†5ÑÒŸÙʳIÚÙmÀ|g©¡6‰„:+ –Ë Ha a›ˆ¥Ï9ò¯—콑w±º`²Ô«K‰IL3ßáÁJ ÛÁ´:àa±:ŸÙ†˜‰ƒ4ÆÔý”²Äš£ñaa²OŒù®‰‘b%f8‰¦.Ü’Ž£´;4‘c•ð:ÛŽ_3þÚ-±ÖEL´W`£G ¬¾Šøƒ‚‰Lm1˜¾F %44ž7 UñÓ® ¸+‘WÉ·#µíPåk×ÕW`“(= âDF±gµ¾‹+ݤ[Êa­µLŒ’Þƒ¡`騵´ç¬bÊŒ*À ”‰(‡ãR~ÀÕ@fžËe‚øJÃîj×®Y®è-;?ë\°fhªË‡ØÑ4óÖ >CþmGù‚­êtí$úe¸Y -¸¦ÎŒ`ë ̨¬Œ¬j*ÈәݳX¨Iõº(š•˜;#‘9<Ùrº­D>^^êÔsþ©ŒÕ ½ëâ‘1UD¦çØbV%SC N¡øó¤ @ÝUI)aùº9dõÔA¹ŠA·ŽŠ[³B_pÏ ½GWâ€$ŸÐé¶-÷áìº.: ÉD¦µÀ4„¬6Ë½å§ 0¡ 3íÆ&jÿ2ìÚ¶+„¸+4èÙÜÌŵâ¤6E×uóÖCÈåü/[ Êîbcî]0.üë´SÄŸ ãü®‡ËYÅœð‹ ÊĈYJžÉ <¡ä9U-¹úŠˆ‹šZ.éh»;މls}Ö€EUèÑÑ-СqŽ Éip&/ƒpPå p»ÙWÞH\Çé ©SSa‹²ë¡'ÛpŠq6êÑóÛ­þññ©&þÙÏMQ¢ ¼2r>oꩨëÂî”ò@Šr±še圭"yEsàâk«XÙ…ï­ýòšôºÜ$ _Ì4Õ¹ÛÒt£ø_<3eë&1 Õâ$íuËÕ¾`EÓ‰ëmkê"äÏXOýL &‘ bO`Ø}8‡Pa+ØIt†^œ1Y,˜£+¾çÒ°/›Žöú$m–á䜩>8öô³âÞ’Mz4ÓãJ Ÿérz‰¹îÛÒJ ÝØ!Rb‰6Yä$›§Jò¸ò¡±ÒçÆARvn¥%{€ rÌM€Œhk¢Èñ›MÇTÐg™Øedaê¸vr­oE&êu0­cÊd¹û dO ì‰I½®È€C~Þ½Â`Á^þÖ“LPq›}ø~£ËcÒ¡ìDÅ/“€9D•¤þžB‹Õ4]¬)s³úFáÜ?œªΩïö5P–l0äQs˜Ç ¯§›\ËkŒ1žB"´÷ ŸZ1u´D–06)ü^ÅqP…¢Ã°aJŸé4§¯ƒ.|àloUɽ©K¹ôO3‘B½a¢îÖGÏû2×öÀ×ãhªg4#)tuIzvSF™%rÖ|2 ¹²éU4L©gI0óÄwy9E;n0"/÷ ÑJÆÔ«O(‘Šõ ¸´ÒºÎÍç ¨TøsÄmŽ£Ò^ÁÜ zé\×3a€O–šˆÿ‚@ pX ƒBá`(„-ý}Åa`8ÄMüŽAñ¨4z Çh«î ~Ë@ÒøÔjE•Êå¯Ù”WÏ`Ñ©4¦=$’G¦pwü2 G€ôøÓò¤ùªªÒ˜Ô¼ R~Máñ $.¹@ŽJê™]< …[/k„’W\BäÐjô*n“S)‰m~k€~ÈgQ 4.±T£W(ƒß$ Ê>²Óyè•H®aŸö©LJ'&šÄ&185sJì6Úl¹$›Ùš·ýº7·I2Ϩt+I¦ÓÆ´OìkðË›ÑãÜ\ÜšM¿·Nâ|™$ ¯Îi0 O†¹7›É«—~×jëz‚mµPªÓãåGÌñï~œÞzmä~ö`LÊR‘£ È×#X+‹äýŸ«SR©$‹:Ôò£‹&­(æ¼8›­IZ ³«L‘îá€Hó–7íüµ/Í«Pš8‰ŠÒ§¸ìËxô¨î;üí(Md°Ã¼­%+ë®…#N³á#¯kO ¥­ü4‚&éZ´¸Éâz»Iê3Ó0¯ñÔ A úHé#Œóã=Š4@Ø»èrèÙ*P³o7Á ƒN v–³¨´Ï;Òð•·ê°›¾GÂ<“9òHôótØ3Š’ ­P)Â'%°D–ˆÉHœÿ€ »Â°BVäÏ“hÏ&íûø%ïáúÌ£US2X ë‹?4³âW-O Z71L´§)íš2Ó·ò´Ì'µã3\Bê’†¢iK YÓ ý.·"0…¥+RHz^JÔg@ÀVË"÷or¸õúZî#Óûê…Fh›«‰^ µŒ|–ÝšH­,îÂ0Ð%(­°˜"kU­`ê´®Hó\ålÐJâ¥?Í(ã~3+tIÒ6ùù›€‘$LÒ€UµF‚TGê̪$ŠÊ^Â:JH̤ػ‚”¥t’ÐÏS+îí\J#“{®j“~âÍ@&g9AW9a‰ì´“\­ú"¬Ëß„¥²“úŒ$Ô| %;®¦Ž;ÉZSÑö69$Ñ ƪ4âæ œ3åA«ªL: 0ÏhVé´ðw=+0=|ôÀŒÑÔÀ :—«Ê_¸W@5ÝŽ1ˆU«D‹VÒ§ñˆî#K>džèèœ p¤¹ÅkDDŒ‘×øs3G®ä0˜åà'[ÄRÎòýø˜è ß2Òfãb"s¬çIŸÑKm-ز©>k7*o¿ÂLd§˜GbB—yŽœ‡¤Rõß’¥q*¬–¬Ã¤`d@Ì4¼ %ðH£%r žð@‰ýº¡ø‰œCÇ*еLƒ‚ÓÊ¡jKHõ#SÌT—`gKQçÂf$@”Å#!R QÛ¨3NðË?Ðü™:‰"\)õj¯ˆše…I¾šÔf[ži‹k)ýÄRYØ"Û%¤™É?ÚÀ)(‡Dp”²(ºé‡ëÕOÀÜ=õúFjåË\ÖB"XÝÊ{YªQL×ÞË`$VNØ•Ã2¢Œ²Œ?(È%¢Ô§ã‰¶„\Ü/´„ÙŒY‚h Í&Dç%\¥ž8D2‘ ÙGOñaùEÁüö—UXM×Tña+U£Öh.WƒU<Ã%ľiÆd‰ÇüE“dAë—éNzUŠš^Ñ\Å¿ò¶£© 𳕨²(EˆTH8«9>HþI"‰E!ãÂYôì@3¯§KºœX±à*åòHël8ûnCíëר\,¡Tʈ9R|dˆ4´ Æýº®¤«>ñõï@¤B«Z •œ°øª­fOڪɓ£35‘c,èrß”Ú81Å¥€ mq*J&f1Í×Ê¥T£ê„ÞK¤)À];x¨I•‹?®cNoiR”¿îFFºMqLõ4·a ¹¼@¾Ž mÖƒE[ô¹nÄÓ¿JÎy_’¥BìBL È0|f9èmÊxVæZ¸ÎÈ«´ 5Z‘l‘]²±ùa®ž›s@zœu(’å¸rÔƒ[™£-U¾‘ µk –h<»Ô5޾7‡IäWÏœ%ãò9;#ŒŠÉ¯é¡Fê9a sÛb#õ*óY\`t@%*2âbrR õ¥%@ ]tÕäÀÂÛƒSð< ç‡äIÏA5>ÖlmÅj;l…¢˜‹|•ƒ¯ç¤TÂ/Dgh¬T9y_@ô¬Ïšé •JbëãC‡cóAÍÈËÃØÀã ÂÔõ¸q¶åk~bxnEŽ.­³rAn¤]Ú'Ö(¼–—ã<¥£R’æX¾Zèâ×ÎQËvl"iÏË#VkŒ?*Yq€6`OÈ  þ„?áP‡ô ˆD_Q7ìT‡C"1¸„ù ‡Fa0¨¬•ú”=å@‰`\˜EÀYpe ÍáQ”ze œN&9#8”Ÿt¸&–û¤Ð'q IÿM”Sæ´šLÊŸC¡Ébo©ÄÖeU‘ÐfS*Lp ¸B'‘wÍÔwšÛ§+u®/s^âóŠ|âK8‡Wbõhe&ËÖåé- Ì]_/là'=cÇ¿@Ú;äBŸ_â™­q†[+•ÉÕª/ÍhÀÒZNê­%»óXÙDâ#žÄeOxfëknØß´ ¬–Ÿ2ÝG²@-|·²<¼\ŸK¥šÙeÏOe&G…b€Ç´3‘c–&Xz˜¥¡€TÓŸÈŠ´š¥Èò’Ä ÌÓ\…- ƒ0 j! ¤ªD)ê{˜!Ê{x”Açú<à© š§¿.²—€nœ §(»äþé+´—!ÐzÈ8 ®êò–‡2«‹òë¢ê!òĉÂΣÌ#J¢`’¢„$­Óà²ÏÚ+'Ÿi¬„œ!Še5)i+°&Ì~¡‰ªJÚÆŠ¼´»("Æä3OÊpÐ&q÷1¼ü®Ú²ˆ«‰"pr`¬+ŽÛ>®'ôúˆÍȼօ=(RƳ/ÒãuÌêÊ–äPèœÇ°šÆÝ)èŠJ‡&§Å|û¢n›¢À¡T øˆ£ÍÔû>¸(d’9ȼt‚ Ïùö³¦@嵩ƒR=È4˜!ֵʅ#ÒrPÍE¥’Ѷ`ªŠ×-[‹t ˆÎ Î€ ŠÔétŒ}ÌM3…Qôíi Ñ)2NÙÑéíòˆ[·ò0U·’ý} Ö™ø¡Ýà5æ~ijº#6¦6’+uXf-¦l…ˆ ßvÀ!ˈ84BÀãBøFU<-1…þ~ÂnÜ¿)oÙŒ·lÈ„T2ÂÒÚçu,L‚&N žGÑ –á¡F2¯ËhT7 ¶·í||eŠK4÷¢–ƒ˜NÞ«§ŸÙbÆÚ¾Zê‰rÆà×h3`¹" |6¡¦µ»F𽇢“€’æ´‡O˜¹ýpÒ£gHáùâîÍ([Iþ±ßj7Ïs¹…0½_ë"—'4Ðéϼ†‹à &P¢-15™Å -]c3Üš˜FgÿQp@>qÅZ€.wúà*ž«TU%ȧ~8‡£«éLnÜ<”}kûTóÚÕ—ýö:RPÇ—Ùò~oè¦7Âñú biY™¨ó°Î“ÃFŠ£çÔGaËUoüŠ£·„BÓN쀂+‚˜D2U@=ÆòtЩ³r@å£ÀÁ‹[9t@ d5Çɱ\QM-ª“W§–)¤‡ð@Å–’ÜÒÎi£>lî\T Aº‚ð0à¶ôòïÀ53I¾Ä„çº ƒ!RâJ6#ƒ®nïîCóËó%hn$¬öÙGñI>‡¼Ã†ªÄcÙ09™“RGH,mÈÔò¡jˆÄкñþvÛä–;Îá:¤ú—œ¡jÉ×uútžI€<ð¢´2=Gã HdãäJ—Á£K‰ôù ³É“f¯uH¨‚n™a 0¨Ñ»| ,´.P~Ÿ“ÀÄ´a%äÀÍ–B׊Yc’-iÂÈŸˆÚ±Oš¥S5.ãB-mYH´Ma©(n¹ ?™ÆÕŸ%ÆjÈdž§Bá{E¦cKxq9¡óÈŸJ`ù<5Ÿ5Ò˜úfÑ¡p†°j"´&PhѵTp[£0<ág0åxKŽB@²E¤’â­%Ú©–€jP}%YЇcJ´Ô~ G1 å*"í¼Ì¹DÇß!ÏL¡"jk"ê°Ö¢]伊Ð:¦Þo¡j88$zK£'èG-lâ³)cL&³Ð6jÍÂâúæ”'+îH®•/òÀ¤O>„"÷Ë _4—‘òq:Ùj٘˗™Àg–é”ÑÀe©}ñ®ÄKP­&e¾’5§Œ—[r.³N®­š##½»)k5²bÆŒ%›ç¥(ÑchL>âú`o­¾!;bU›ä×Xrl~2ç¢ydÆD¬8~ "J.ä‘“(Ë?ºº(FØ4q!Oñ nd7X:A“2«íX:B‡\ÑYKd.Îm)=1)5b UïÜP ì˜i‘c KçUw ý£»í hÒWZ§I†fêMšafë¡ÒQ¶ø4Òüp »Æ(hu#Ühv†Íde¸ä ä9S‚C¢óPÁD’1—ê£æ*‡ryx Be ÖúD«;Ê€PKKæj¨Ecd(Ý类±.¾ºXVûHÃc8¡~Ø•âû[UC2DËÞIÓ«Ö\Ty.ÒðªÐrq”ˆ¶ü–¶¬q`š©Œ«b碄߼ 5U*»éÇŽÑäaC¹ò´¯R6ô[B€4jX°Tæ2Mjbc[ìUó9‡‚Ö]ú;w“X^|51k\[çƒ`ø?©àS¶Í_"Ò*òZ< }¥»™…“Y%´„V²RnbV&héàͤÁÝ”8Øè’‚ƙ۽NŒ{hš“¤t‹ÑB210š:®5øªNÛ£Eã´gÕœ#t B†}bÊ­iUkIîˈeÁ¾vúlEw·¯²Ì¥{L<5¾âZÞ ŠwxãJõrPÆÞh«Ý‘ZoÇ^;€Ó²#M3ˆfÓyÜœI­Æÿœ_ewqq¦;c™žÇJ³E¨^y™àgsÊu“1HÁUÙ±€Lg䈙¨êL7ÓÛ Õ†XÀqQZí‡4ähÞßÚ˜“³i›k¼‚¤Êì]ót=œ?bÜ6j÷kÙÞß:µ挹æL² j@cG€x:ÀGí°Ž{¹K?ÉæÛ¶´JÏšÀàŸK£É3kº0j¹ê¡½rƒò©T·DuöSØ(è듯ƒ#‰º›…Ææm3±Í !Û,¾uÆížf·—uaé¶Ž§|”@2‚÷V´Ç¢]a¿Ÿ‘Ø “xQ¥¼ t[¥c¼z÷ŠZÆÙƒàäjdú«bêz*H\i.Ú,‚ƒ–ª«È@‹¬­¦^Å'*þÌ8Ðl4XM|xe %Š^° u ß  pHfĪ„ÆcÍŠª¦ÞÜŠ\aÆv—ê6ö'Ì@„„e†Žœ ž êµÃBÇFR<ÎÔ€ïÊfXcÄJ܇Œ£¬,ì¢ì.íL»b\—0aN'ÆÈÃÄ!ú1(®UˆØž àÅž¡çjÜÍ2håâ‚M:hð/”"i®mðQC{¦–Nìì!Ëžã"XÅRc)Úù¡öIb–ïjt¤ÐD¨¢Í"ކ¨³¡ö½ˆ@ éä˜ Ú'HP‚êÆJ,hŒBêËcF¨…û #‚°·žˆ*˜d"¬îÉà8,þŠ­Ò#p?¯éD&é¬ÐmB ¶$[K è óç–ðŒ=\)*ÂÜÕ(ȇ‚§¢l6éx"¯‚+\-ÆòF è{-ô”Ê׿•ï´O­òÐŒ Kð!‰ÔƃäþÞê"8b£¤G‡!õÊ|jæ†Ó)òž¬‘‹bËP‚Ž¡ø¸H¯ŽúN¬¹0jhdªÒç`Jç’Yä6$¤}‹8fâëN‹Àòª„)qˆ‰È‚– ôy1áB`Īc-ÑBêÄ£tÕ†ªöŽ½Î¬3Jª9l`ýoàž #¢Ò˜»º©š¬àÑ Í%Ëzý¢7 onì½ œ,<û¬Lò(æaÅúwh~¶-Ž!Ÿ òÐÜG¨TQ&jZ&f·ŽÔVŽ^JíøæI6mS ÎrÝ Ì¿­ÎÀ¢í¢ê‘Ïjðè%ƒ!‘—1š%"U mÈgÆlû.°»È®ü‰àòü>L\¤ñŒØ¬®VH‚Ô€Ñd$°²žˆ‚©,¬‡ã)ì†üBe bmðî¹kÞ>‰¼Óbž¨ñ0"1Ìô*Ìg¢&íFÄdúúNõS6v¦v$£ò»ú`l–ØîÔ…K(z-&ˆ-LÀ.£û6IâÛ «0Be "B(É´”ï´ìå:€¢“9‚ÉHp©¬ÒÞ˜ÓZdSï¶G"'É(ëœ4lPCc–GÐ6 0#òÄÊHÒ,Ë?Ý "gq¦ˆäÐPÉô6§‚ÞÄh‡K&µòF°nþØäp9ê/ÃCΕ"îvÂRlç±ã*ðÞF""rœŠC8åºA²r4lxoL2É} ðÆ‘q´”þ!ÃÄPA;ÂÓ“ ¿` GÌZÝÒe+ £G±¦gË"3ôÎÚ”vçÉŒv%hd/ü?£4GÓ¢%Í’1Àåk\’-ö´m(×Ãj™HŤ_©<0 g lðsÊþÓÔèsÈË­75!ô€4À€î¸/ÇÍ)å;5 7 ´Ü2F‘D#òÅ äH±°ô‘P‡HpÕЩ#CBñÂÊ€¬ÔY'bêLf¥""]#0ZËðo†—èÖ9 XÉV°Ú4UB\7Cè9 pb'9ëÓEàþqÂì‚8ƒÒe¬J³r¢J˜ÇªçýK~úëß4N°¼ÂàÕ3ÄæÌätµ„0ë^ËÝŽE6´ä­oÙŠ è“´YuõS†ZaÂk[C9Š%FòæpóV2(ju"UJˆ-ª!CòmíˆÐ‡‡_O¤[ëÛDíÑ3Ñl< «äª(?¯€u[4’ÿ'>B7-‚UW³N½À\u' @{ ™Jï‹SÊAôšäÑRõc^áì%*Ò’ôsif5ík äÊéðÄÒ /¾!z»®S褂†9jŽD­M$‰1-°_uÌøSš! ž{´Ç6æ€nM$)pfÌßVf†˜Ç†ñÂp஑¥:Tb"–ÆôªAý–`<ÐN¿áùrÄêÎçÒ8 ‡B²¬gÍR"4eÓϬ¬1ì1iorúuQfS º©¨´cC¬\ñ—”ö$'G©Y5M<†cœr{µiÉ.Ó0ð]w|iwN2¬Àr&Óp)C²0ž ªø,í/bÖêvÝtc§Zc„.·§"Ê ÊtGÉ'Cgb âèÃCw¡òƒÓè-iªÜ‰Üü-"©„"ÙM|ZÒ6ä ÙÓL ‘T»F±mT:?You;VíÐΖš¤#¬Bl`’ô~;l–o‘vâöæ|Ëñ^ek..±kiÀÊ®ÝØ"t‹[Íu2 ƒC¥0$«i)RF‚Ý…¢ëUíMeƒ4nhœâü#ǃQn9Sî±&`Àl()rs¦0wb=‡ŒXH©”І‚Uk7G+;.@£3«*’3S2€r¤}ô~ü@¶&Þóß_ÙehÔÉ“_ö¯Í|€ø¦§ìOï%Mr’0Dx5=ƒí· 55’ë$N‹¯ˆé6*Òz›P:¦úæl5±_xÝFïMVº²Š˜Nå´kMXêØ’Ü·9–‘S>x|>P/Õà)*ÞÚæ¦ó%\VjN–©"¦f‰Ž°J¯è^4Ú6™u&‡HZjC‚9é1Ž’[ꈪ³'ƒ¸ÌÙ§•²¾7­ý7¥|ñÊò¥žb®3ƒóBd›q”h?ƒFf†vÚuP&Wo“` pÉõ2eúClP#Ó‡Ÿ´=w&ë\¹9У0c:•2ÓsKV'còä&auk£uâêÆŸRªe¦ ê ›ö伤ÿ bZ1§(•þúQÔpwgüÞ Q‘M¢š³¯sö¨¦piP'<~ÿ"†¡väÆí.ªé Pii.jI”Õî©&¿“#„«UflXñ‰¾²–¾ë¬&åO¹œÇÇZ·GP¦ú&:eÐÞÆfa¤G²xÉÀðYŠ…¯‚œPkHŽ< ®ÀÛhÚ¨å|Ö‚‡‘†Ñе_ì"ñZ— ’Ò:978LÃK£Haõn(à £|smKý•ÚeeBÒ¤LËÍ!PþüP) ”*¾Nˆú\TÆ«¡•œí©6Ô*Í,÷¸+ð)9%œ[LÔ[†Ù‰=aþ>0RÄòº½'éôo#XÜä › ŒaI®é4ÄÔ玚%¯®{KØÿ–9ñ)X|Ò¸jl6ÖHŃ,FçÓ ÂUm\ó€|ÖWµ:;gÊ™0NÞ"z<ô.fÕV!“•½íö¡‡±øf*Ø{‡w§XiµÏ3ƒ2€oÁ&BGtHg=]o(7»¤8¯Ç<ÿ¤âRC=€’Åéå¿ÿ‡QG<ã¿>gä`r£>”)Iz"û‹“Ó™e¥ò±‚(ZE˜Kã½ÆC‘š÷u H³ l =ˆ7‰¨7ãÙº)nøúïð?2Ús#û­sC([Pª…¥´Bt÷|Y¢¨¦ ñR)álì *ÖBêHúaÕ‹S7#j)ä}èçIc¼¹â.Švb;¢MR»*²üqþçb*Îo_V¨ZÎÃ1æÁ6ƒÞÌy&— dî'É;—‚}üºí|¹üô¡p` «L,®Û~ºnþ¼‘Žsü–¿V±ŽÌiÉòûmÐG¢™‹]Göׯí»Zæl9wB+Š¡'K'ÕñŒ]£Ô¶fª-ÞQ*ö¨öÖ£[æ×Ð- \Ö‡âq)­|ŸoÝ¡¢öv8Œ.øc®š‡€¸ëÊ]a>û{¬k)ûöžCnaÓø¿5è,>Œ .eÄÆw[§¬zf AáØP ‡@àpà0 ~¿ã˜8ÁcàÌr)ÆbÑ`$®I Âóãîi„gGܬõŸ¨HÌf%1ΣP(µ0§N¢Ð9ÀùU|Õå *œB%ƒÓ‹R9!ןϫTÞqÕ_•;„v “@©”:äBݲߤÊbj}Yá“Èæ€\ౚœS pÆâ+SˆEÂU+„G'‘iÔy0˜Â#0‰å$£¶wÌr Æë —HÌRÉtN¡ÎFˆk5’¤ኂܪ¸h”Já˜ãG/:˜=³'Œ]ÀÒ§†Î+5»Æ×ÙŠO2¬ %ÀƒãbRþeV³(…;Ä¡¾âê‡>.ùŽÜ7  ‚á"Ïʺ†0Ìúè¾€ ™é6Rá µh¢À(²Æ¿ÉJ8©·é¢Œ» éÓ@• p£ŠÈ½‹Ú ê*°È‰5‘48œ.ˆô{¯1öÉé²Ò ò0ž'KCÀïñšlõ" ²K© ï3(Ðl*.’ú!ÑÈ{NnãH(£æð¸MDy+¦ÀÎ!hdð†"Ð]# ±L©$Nühš'Š3eÁIZ,Ã9ÒLn2%NKr‰ü¥Ò'ò²÷³Ô‘÷¿GóvÄÆè‘ È<6ø«2DÌ;U)ü½¢Žœà”Ÿ³b©¢L¢Ôó¨:ªŒÓˆËd©¨Ók²؈uJÃ#ˆ”„Yˆbu*»*À‡VÇüú¤3p¼Û€8óØhb9€mú± "X‚ÏTP §ˆ¥ö£T,òª¨Ë‚òư֚V‘ ©ãdСSùöÅ­UX ˨¶CÃËÌ{⠫ʵYwZhŒ±³Õæá"TmS^¾R”œ.T‹%^UCLÙ§Õç§ ’pä)ŽTv¡¹i¶©„!’)8ÝW­p7 ãnš"ÊN÷!¹‰ö©µˆ–(ŒCr Š€•’*…-€*y•nªÌÂ[ú’§¬¥Ñ>\}@O‹Y”¾/Nî³ÕÈXìT 0«V¯ÉǘŒKŽ%rüºŽ_õ„!/hËq5B@%’ß3¶5Z5©¤ÔôÔ*Ç!5×·“ÔHÞÈT¿hk´ë ÀKG…X^5ôOÖ]Üvp…xï;㎵I\±C¶Ê‘RíuFÌŠ1¹Ï:Ëúh "ÝÎêòó™íßÜ8l†Lvê"‘gÐÈ+b7ì°~’Œï@¬"„éÁv6EÒ±+zÃõ-ŸU&JÍÕƒŽÙ 9³²ÜZ“J/͹ƒ.@}ä tžRÚHrL}çeþþÊÂDêT«¸æ?ã-jå¬v`á›RAn±˜ÕÜY úñXãõbÀ¸&z ¢z|ÎÁ^¡´¶qÙ]§íLE È[ó¼ld(£2¢¦÷£oBìýª…D÷TK*ŒôErÊ\1"OÔÉÄqóš3Þ„)¯Aå<¬c DJÌ%¹§Z‹;7E1w1ÿš¡3&…€ó¨óÞv"NJ2Ö˜­cØ,ŲXCõröJºÕŠ\ Ô>,…KvC'ÛDJ…P¸µ y\qËi“Ƥù²ŽM”…)b(!:ïƒê•ªJ™Å'GüU.½%ôñαt‚2œ~ $y×KÉ ¼¥¢•*qyN¨¡B7e‘,,rV‘æ»3dÂÈp'âmFÁöE‘ÊiÈñ£QbŽTb#* ~ÇG ‘'„ Ç•R$Í#óÇŒµ­R9›æš{¡ âšœtx¸¦sI!PÄøÁT¦?œ3TCm²ª†ç(Ì0~ŸbmKSxž1dÃÄz†ÔÙ+šHÑcã¢èc%\´Tbª¬*Ed¦îMÒ!ú„hm¥ªTºÆUSU¹¥ÒÌüS¹þî–Ó¨°r¦:Åè©õTtµšeÃŒ†ç¥‰q¦eœi…Gé^”¼~&¤ ìœbÅ~¤q?ÚÀó#¼ekäн®sXO+èú}VéGÎáö©fª–r•›ØJ¼V—¤”bJ°ŠTñ3“1OÕ…—L…pÙ" ¸Ï€+}*·Ø}æÒ³œ#°UO|~È®„E§i80Ä*ª…tUx ­+ I¼ç^ …T†ºMDx°¯ŒX.˜”aße“Er*¤Äæ¹¹ mÃþ«nÞ†¬S3Þ³KtÕ5ŒieTYÕÙ8$PËGÚ™âyŒO;v‹šÍÕ-Îaù‡ÌŒßÜöýf²œ§ýW³ XÙSð‚{x² »9v`Ò›—+f Mè³âñ¯¸^"vJâ A%çׄ·L´ŠÈuQÖ_H×íP°hCÓ!¾T΀æ.·V‘(; \­£äÉeòuô¶75êH!`.†ÉÒ Æ_š¨Á‚ž‹W¾p®@½É)*~¤á; "¦:¬Ñ;7²‘Ç#y¸h ““3µX|ÀøŒ*‘£-—¤ (º3 €°<¹Ô¯«B•Ÿ %©BÚ‡Úkâ‘á×(žm°+ +SŸXœ4ØÇ"ŠˆtÂJà¡'’h„d*8Ó;òƒ—£¹ È»ëðÁè~¢k)2(=ŽÂþ˜Â=rˆ¤8Ï-Nsþb6¢Èˆã;½’Ä•2ƒ­Ù ”ãÞÁ:K;륩:2_½`ábÑA±x$˜©—ú¸àÙ @˜ƒ‹ÉÉ" ¾Û>¸ðè°.Z´'*IXAõ:lC[¼9®ú‡âé, öžz,¯J¼ «6±;38«}©âŸ»;m‰É(´[ÅQãÄÈŒ5J ,³¡@£´ˆÃŸŠ$6°žCIN¼º1'Ì:P}$3j{01®5ôb±(~"¨ŠCD•ƒë¨RP9`9ãH5I{§+È'ˆ¦ t몔V úqŹ㨱ª=3TÃ"F5‘¿µÒI©0¢»<²:¢’{p£”N*ºRŠpkÉ™»ƒ)/¡'Àâª!ÒW‡âŽ)‰¨Sv ‰DºçI“Â9ê±ë‰¥Sö¯Lyú¾AP° wEŠlÚ«:»c‡Û¶‹R1‰w£ 2Z ¾ !Z³á;E‚l‹‚Àk˜Ä ÀÒ‰3° [x€4Œ·3¦Jù%/,_iÖ É³B$0®D#+p Œ Â+ù›1‘ˆqjF»)ÁʜȹÙG@Üù ”*bÓ$²¥ùû›LCK‹ñ³@Ö ‚­TÏú47³ ‡ð£0[‰BR…¶øÁ¢m‚“AIÉ3äI·óµJ¹NÊSZ3²Z»äŠ7ó¼Ä<ƒB¶¹G$’Àò‰“1Ųá©AÔZ7J9ѳ=ªå“Jš ð!!áìè«[Ë·±sÉùìÆ–œÞÁ’·b"Ñz<º «=À¾4n‹Ü>¨2*‡è°>‘õ<,쿸Ïô¿Hj7DÚ/A3´7ð‹=CT±xà R¸ƒ‘ÿ´°¥¼´¨”“R¯½ªN7$[¯IŪü꥔6!GÀŒ Q ÁŒb»ŸºÑÙ©¢œHŒ0”˜Âr«J;‹&¿óѧdLÆE58Þ0ã@¡3KÞ°"Âi"¦²Ù â§@Ê¿²+­ÜŸ•‚«?|˜ d·ÇœÑð³jŒ ¬ÓмY¸ 4„«œ Ë”ßô¿s6´˜º@ëjP“D F*P*” t[±À{½©ßˆ°°F‚ÚHÀ‚™R«é-„׸ا.Z‹Ó5L‰¢Š,œ[[Šà©»ø±Ó¾R$X‹DW¾ã:Âäz3A³RÑ8²ƒ©óDK5¹z¸°¡“ Ñ(›2ÇTŒNŠ(Šã[*I8’,PÆ98%ró—b|CY@_Æ"= ÛG‚S-ÈÕ zÛ*ÜÑ©-Õ¨ ;³½üw)TùÒ¼„K#WŽ4áÂâP,áùB=-3Á­»Òð¼Â´ÌŸ¨°9¡% `ÃKL ±5M…¢MÐ`2 ]Mv#%uºó‡.ZÒ(µFDçÆ+N¶µ‹DÔ{ñ ÃäWŒSâUdœ‘C="¼ÌŠaÊŠø§+ÛÃÖp~@;È3kgLh¦XŒ†Í°SÙ£ŠÎ:Ws{Ý£472û– ¡*‘3GŠ_ãV ®W%þlDkØN<€^1¼„º½B?DûD›™" ¬?ªHãKj¼ KËCcдÅÍ•ì!$=–)«&ËjYvccØì8ˆ±l9\5#”ÜLÉ—cÄÎÉa袉Š_¸þ7×iã½®"_¼•Ù¯]=Z6¶ªM¬¼¥Ò¡á㮈îmׄ'0”¾çË3 >™sÌáÚ[V?$ÔÃŒUj0”—ÊsÐ`ˆ=·Ópjk}CÜ­TÁC­Ú ÅQÑ ¥…¦%)ZTb§¼Øø˜Š™•!²Aü5›®…©Ù8Š1ûÁÏø|ésÒk>$áB^W´èœŽn@ñ ©ÖVÁ(ãĽ3·€6 !½Iús° V†_"ͳ˷Á ª¢9fŒ“¨>^6áÃjH€º8#ëR ¢äLž$šËž;¶2P 1~€j¬$Þ¬ˆD3â¥Ã𦠆”×{²]Ð1êgh¥r¤í®HLTøK-þÙ]§8sWEæFBΣ = Sù½y‘Œå;#ž´Fټ〫6£r_6r,»‘£ñ£0iúì–2®…?¤Ä#ܰfk+9ŸtVFji ªàtܺuI€CÆ>Rhã/v9ˆvÃ’}Ë)ÕzF8chÙ¸3k£^2½Ðð,ŸÐE 1ª>‰¦~;A0™5º-eìäå×~ËÂ.Ø@½ž‡Öí–µÌ3:ž‰o×+´Qä ’¡!ÈSCHE!V·ZezÙÞÜw®ÆB+Ã=&ñÀcj¶Ì>9µA_Ev8ripþ7ÇÌbóòIÀ2¥¹ñ³¢$ȶÿ6ä~ð„ڹ·~°œ[šã{\­7¦ÛVX8ŽËßW<ßèôóS>’;QClõÛ*i¶:ì§O˜ííó5:É37CŒ–G#­æ˜}<ðö”¼2lIö—vœ%d&e€§Þ Mÿ³I¤LûÑ’ s'Q ÖÜÒj3ká"Ö ‡Qa¯>Â7{-p™\Ü –¥+ò¢Å@w^G°j“(² Àë3£GYåsÕó‹/;Óvª¡Ï.÷¤‹jXÞqJ³K¯F2[—}ÖÉ0rkðâJ»)Êã>Åï÷$¼€žŸ•÷äÕRPãWnpáúã€"*¾GrÁà?³£wp鱳ȽÛnSrL‹Ý€çDò ´ï_gN‹j ¬pÓ§t-®7ö€ñ£Ij³rY’&&Ìr0N«j*”§{êqòÄì8Þˆ ^°XŒ¡Ñ¶—ž<Õš·IŽè0¸‰Àm{îû=ˆ§D¨±c U1€í‚$L(Jf®¸¤QÃÀ kpª•­×jì3¦^+Ç?àÇ!×%z|àS½>ÞŠe;6L·B;w) ¯Ì3cUWÙË‚Lº1=£/™Êt€ jdôï‡Þöd5h-›†äºÇ$´c*Ç#‡ùáVnkÀ-z×rÔ~eH-p+7©^'Ä?\ô }á>ß?ðo ¢âÙ¶ñý§(Â{ ^È ¹±§ˆùüÿ‚àÀHCî†!ЧÜ8bÐGüJ1~Gb€) E¿áHd¤‚H£¦%3‡JcÙÄŠ)8~Å€²™äõC¢hÓäv12‡Oôø„~@øªH€Õy 1ŠVdù„ª4’Æé“9„ò1.‚SÀòx£Þå~L&)dn}tßh0‡¶í ˆIéIäà ¢E"V©mj 0·c¦” ÅÒ!>¤¿ùçE'ŸD)pÌ %¢|⡜ سºYbS¤§Y'ºM —˜–úM¯Iëpj$J}¹±ÌäWH•±ÿ<ŠO¢\˜u\ e‘IäóÍfÞA7œg ’œ°‰Ÿ_À›çjOÂ²ÙøLDãµµ¶Óã c´È, b†¾,j¸¾¨bD”¦ÀBH‚R¢;éÃSÁˆŒ‚ Ïs; ¨péÿ§8ž1)h,©ƒÄ:N`Ô®‰xû&‘Êù!!úÓ€+[$ÁÉ Š‰F‹Vš+ËÂj†HN ›J1ª@”®‚0“¢K‚ ‘BÈBÒœ(ŽÒ_,Ãi©&€ ºž;¨DZŠH ôÊ~«ÒUÎ¥W74¬:MJ¨|=4…oâ'æI¯9˜Ôä™%½$¦™jÃ5Ó–T…W7&FÖ«¤ŸRIJNÖ%)õ¿6¯0z‡O*íbÜ¢`Ôì¯<¤Z*U B” c¶gR½¦…_ÍR¯m%! •å²É üV»#î]"³¶Í؇Fˆ†8ƒ_(¨”!‹¦ïqÆ*’ìá:Så$÷"šº`Øbž¢e`v„"Žæ‘'ÆÇ`Ÿf)ãØŒtÓVÓr€}–6=KÕ*jq˜Â@WH%9Žï3H '\rˆ@ØNhüÕð%¸‡'É?>¬t(íEÖV4kHr˲w{cÓÞNVË4wY%î\~úSvEQþ9 Õ’bU$Ì9B@[“iUH)e2†zî‰ìY(”«¾ãJB˜ ƒ°AD,&ÂPÕN`é€5D­‰£é_„¤·Ö²•ØèÿlN$0öàûVsçHÇ4³œ%ÂCH=%åô³sX¡É‚Ÿ Ä@º†‘zIy&—|›JÕÉê¹,6‰v]¼ý–8ô¬l#9l¦ Ù¬%Pù´šÆ$2;ˆÅ I+1‘ÍΗ¾cèÞa-;¡ùeu¹0ÞvåÀ`±‡,æ{1Ö YOij7?öA÷±•m@ÝX¾Á- yS“o›‡¶U[]²Æ¥í.&ìTÖGÂ+(“š¾Ûµ’2jw0÷ÌÔ­Y]ï¤ÎYXö_kv=cÊϽƷ§ñ¾¬‘NÑg”AÞXMMFáñ©æJE\«rŸ Ç©n@ ¥>§ŽÞäPçÈ*3ìúü¨hÅM܉â”À͉ZBøÁI–wþÅ«L—ëҋ¨¸ˆjÛ%\ô!ö-ÉH‚CX=ŒPÖÊŽÜËÖL®ôì&¸æÜ¡üä!üê8e­–ñä܃æ @J.2ãši,T.†büÌÎRoFûçe±Êî}&H½®¨++ÐEF”¬b…ïµ Ãmo®†¤òÒötéuL$¸¬4Rø;CX}Ìe,¤xvJèüHFjÎJÖªr¤ $p­PÀäÂ+*lç ¥MPÛm¼=ô‡Ë„òSÇ¢D×f€ª/:§ƒ*zðOEÆz69°–†¨úbBp¬V,ÏR,M~R xêîfTbÎ>(2 ‰‚D Ê;g´E­B~æ<ýÌ¿È _‘.F…~É,wL0åï\' nâéZ»òý¢6)¦‰b@‘¾=-ò”ªîŒGþ qÒ‹¢ÂÎçÂ$xæ.쪀dŠ‘ˆEnJË ` QªÕl׫ ùI ÐØ®²¥ëÈ;"®™£:ºMNφòÁæòþCš¿‡´ù TÆxú'xr&½íNF)§ÆRPìqŽþ¡PØs \œPŒ«‘º¦E‚Î{m,¨zO|öÚ"É+ѲÐè} iÂ=èüo.Í–Öe„„øgçt/‚úf2’ÚB¼ÒºTÌê*…à’Å PŠ%Mz0&b-Î`-ÑÒn.p‘“ Øþ&„·þnæ%Fw¤RóâT§ˆÄþçy&Pn# š|¬fÙüó£¬ó€Í,×ñœýMjÖ‘ 2‚žœ$Q rľex¯ ¨>ƒðÙ,G+ä$=.(ò‰6þòO%L_N PJŸË.$¯tU‹*ˆæ²3çÌø3‡Å!2çx›Ñ„ ‚IbÅ ÒàŽîR ëxÐiä—ªÞۂΟÎ"÷&ϧ2IÈO¢p*ÎoâDæ ˆ×e ˪Þ}Ï™(ÈÝ«@;RÜaLn$¥¿?nâ¬(/ïx“NNË'¥â,ÍÌÌ! pb®Dˆ. P{òîœ& o'«=>ñF$l„÷Ô Mν0§'JWæ2„ Ĺ4ô,¦ùAŒ‡D…¢¿DS)/ƒ“¤F#Ü[o:˜¥ø/,š/§ÜÇä®ni;Üs}3hÙ‡N60C뜽´nHN`O‰²‚"p¥"²˜²DÕnÛ/¥jöQÝȾXSuQC)ƒ‡Ϋ@©4g‚¼§‹¼«´æè+²ÜèŒe#X§”I o:g„!7BÙE„ObÄ@ILdž CbU ;q cY,ðâäø‹= ”ŒÞo¾õ "Ñíj“|ܲšnñ±&Í‘8èRÍGl!>mjzó<î¹e”ZøèÄe¦2þŠb†c4$£–nЧ/жA3.F14ô@’©4×l¥@ˆã.Fø¦ZâN&…¶IüŸÌ=TJ¾ã \WGÅGî=B‡bfÎ*—Ì<Ìï¢ìèZáô‰ÇP4J¬#–¯²"o5þÆÌN.$A¯bè-ÉÂO,£ ‘B×bx@ÍwMO‚ˆðoj…+V‚Ë1ÐߣRÍL¸‘@MÙN5¢p6;NÉWWâ6Q´eS ¾óÒvd‘rÏJ“GðŒ¿µ|£ƒ¥&F¯4H„Ë3»1NÌË)¼Š‰I ÕJÊ”<þðJåI'QBÒ‡¸_ƒÒßqoÔ=FÈ€ëîEaŽzYFy‰WòàY¼ë‘š‡mNÇKăµVé´…lñ ‚S+ @¤RV .h!Ìœê!ô‚Bܳ"û-Íœsøõîë Pê«Y jW,HüŸÂ`–ÒðȇÑвûÉ7cm„Ñ!óg3¤¦ìŽ´%GGRÌgÈy2—LNˆ¨¶òWJ‘]¥ÆÔ…•,DQ6U †¯ÿ$µ.Æž#µ8£U€oèVtq“ODÁö˜µXïø¡P¸½Ç„Ì=Qæõ'ÒiQ’/}ówJ*¢ W.siìˆNe±6ÖR*ÀËiŽw<.Ò`í*ã²+nEW‚2q‡Nf/|OŽ·@÷‹JèÜçÜ¡óI¸ QL²ùÍPfçÓt3û.×wk/3¢¼âžÛ˜^¦Í>88Q˜¸Œ®¥~¸VÚTÑF„g‰`…fTwñf"xñŒµmaýtÑOЩsŠ’Ð„÷ d‡Ï|Þ‡pbézá,pöàˆ4K|eD…¿ -,ç5ú •¹£„£â`ÿ†FwQŽhÄ…5Ô?° $¨>Fù P¾%M:H¸ûu‡Ùp´F*Û~l}Eöϰ¤°P~tç:½6'eã„vs mˆ­°$¦2kl‘AwÓq]a‡¡K´};"ĪŒNî–G„ÍÑŒŒþþø*Ë(=Wni”[ ÉÒe0´"Ù …]i“øæc+Òfð2‚(£ù©«ï•.üxŒ4ü0\x2ŽZÿfuÉfÄvø„ù“QXÓ9L“rCm@`ÉT}#„D‡Ò‚ùPøx„ÔÎ; A_’ín0û{¶ªäÛP¬°+˜TjGì"[ñz‡³^ú‹Ó–µ3GfÑV‹ÛsBpšwNŸƒº¦PÎðö/d$áµ¥ÆIMX“Yàú6…RŒ_ŠnÄ,ljMc¤–VMœ³Ñh+8{‚ À—Íõë_¹þ“L0'…MO‡Kf줓¸o— o2™¦äG#Sê£V‚ó•¦+"œ)åM–›§OÉä(¢ŒÙhWY.cf+õ–› Ì!2ø¾¦HO§²w;O¤áõ0èq;ÍíDµžûZì<;OýŠf˜¡Iä/9à– ¦Ïçå Lضè(‘¢ÄD®(„ ÿœè5¬ÓJf”+xŸ‹ŽPo0JžE¬tzæbþûN/¸šâòƒ… ØÏùˆ…lðË$ÂŒ¹Y»E•m†g‚S‚!›y  õÖ S&Ð7NQ¢S-Ä JU¡ˆõ¯6¼¢0s(ÔÀ˜ÙmžŽÆ·!ø¦ò$­A*!'W!ve‰/%#Z“|ôk*Ç0yÌ@M8\kERœ­´Ö€Úªï˜.Ÿ@*ºp5;‰<è'ÍCk£œ¾ðҕ˾áï HS*9Â'Ãc¥ŽêUʬ‚Iåð±²yQÌ¿sÌÜA¹ê4Y”Öµ¾'Ž 5‰FËó3´ ž6ϾÀ™³n9°~†¯ß/RõR9"bKâe0~gº×î°!Ói â¨ày~­é‚H7}²÷¯£DNίyYu­Â$»ù(-–QˆÛ‰µÅ Ü6h…­Tç·À#üÔH¨K½Fxé<͵1o7‡g•hÃ$ùj9d×R–¾ŒÓÜØNaa† ÐMm(*W;!^OïW0ß*B–Ü跋̃œ+(Å$‹ì¥»¤žQm ›dûm/­–ÓjiÈ]içqKÓ=Žá­ÉWQ%7/»=f 3Luã¨Ä·ÈdËôòH¬…K$ó[Èû`õ 4#Em-ïéý)ÿck&ƒCðœÀÙç.½FS/„‡ÓêW6;°UŠ-~ìÖ¢Ìù‹¦Ø°6o¹yÂÇ å_ Ÿœâgdï»9­îV-EàU¾Xü)/ìpe­¹‘üÙì®ë<„€ŸÏÖÕ# §5™dN°ïK9ˆz!á¨p”÷^á°ò¦ú…ƒñàŸSÃSˆ5>iÖhS›ê»Í­ÑˆFH5:bz©Fo» ÉêÝ5rÖë¯Ú½ºY´S ²­’º%6®º$T4Æs–½Ôâ-Ÿ7»›·.èÙ3.þíúPÐuS ì0‚÷1‰TEUñ¹° wy‹i¯4D í–“B§ÓÒÚï¾'ö¬É „f6ç0Þ]ðz~$b0xëÚ…)Ó»ã™ÌK:Aå÷GŽÞ¡ø-ÅMµO´ÏôHQí×;›É=2r¹Üåî:ŸÇêì3Õ¢âüŸ€[î“`(Vý(S\v¥èjáØ1ûÇÃ’écdOe'¬„'Þ½gxà$ùÉLÉõ2œ"ˆšb? è3î…@€Oøp ÷‰b€8³æ0B`ôýÈ2Y4û)ˆØPM&‡?àÉKög"—Íæ±éðM “E€q‡Ì¾ %š–QLäði¼ú‰D†H$¹”:{Øæ¶0;ÚÑ ŸTáÒiô®W5¯¿éti¬Î¯†Zª3é6qŸI¤Pʤ–k ³^@Yp‘›Ñ°s ÎDŸfbÒ×Ä3™äA3]4_5¥ß°Uœ2$÷‘H+Z+û¬Ûâ8æn7‘I´ïË5É›Ã&ùé4¿8¶?ê¯éœ®o3à¤Ônö‰ÓÍG¦wyœ:žÚE²Þª´ÞSD¯Iz0Vc3}~ý`;srŸ¨(ìÔ!IÒÝA/"á"‹Z ü?൷pÚ¾¬Ï+NÔ ŽZäj3°”¼ès=¿gÔ(Ÿ¥ëêð”ºqcŠ%íü*›¬ÑT½€I" 4.âJ›Ã§â|I-ŠVÝ/Š胡 "LÆG€u?rH›¤Èã®Ϊ_00´&Ö€ø•¦süÏHÌ4ÓEÈô†½¼„7Kšúô¬)úD•¤|Í3sÙ 1¨* ᤱRˆ—ÄÇü­€ ̬Ìòʱ«¨‚/¢Ô9þæ%+ìø}¤Tµ ƒ0à @Ü#ɺ–ÏNgüB´ÏíR~»iœŒ¢ER̡р T£+6RÿXÏRbéÇéŠûPËÓl£–„Ä’¤Pz¹²Îœ5D®°ˆ8ˆ$¨ø¢ÏíÆü[Iúˆ›ÊÒœ‰ Ëe 3å6‚(ˆâwU#Õ+üË^–ݦ뷭¼ ½´m-`]€"}AASCÏ B®Ýí]b×áû¡Ï,ôºn®[#Ó}èÕ‰ªãZ€ Z‰qNô“öšÇ+t£4‰3c¿l|¥– S ü¤#(ÓböàÈA·¬#“*DÏTî:1JÑ[Ïgiâ œ‰·&òb£!_H¢VIÊ(¹$¨dUEºH5ö÷\~U˜ÕŒ‚$Tg=ÊòjŽ,ÉáÊUÑ:\…&³|Ëwp· ©Z)¦Ðˆ(Š4ìJÖþû>Í­¦&¬f³+wó-È!ww^¬×´¬é»{S0Õ‰özÜØ ^öý¿žû´´ý†Â«ž„Ö‡æúŸW¯²|È2,Ëò" d%“-޽G­ÕʘÜ|¥Ôƒ!’ÛÆ3Ôò[À&û)¾iùräB·ˆqD3ÊÀ@§´“™ª?mµ3~cÑò|Ê%3¯úÂé ;Ä °©tÂäÉI"qxÂaúŠ«$p¥£·ê@È$YK<-óìG ceÄ•9$Úʹ—DÍÉ3BƒöÈXúö=«ÍŸ=ŠŽy 'Ï̾¦³HŒéž4ŽiyDu@á {ˆ©§¸·b»Ì²*P‹´’­ò@éÈS–[©ö)ž–‰©/²Ñ™$óáùÔqÌ܈BðªÙ9±cJp•Ç‚Vg›ë«!åÀ:Ø2?LY)#<ü ‡B?—Ì+Z2öèxP*>SA§*@|!Ì-­I×ð—I+_(©­8Ué«B²ö .4‰òÈ$¬…G \É!‚*”kp™Æ"óÒxmÊn+¥¿)Çó¯˜rùÆ'—GÇô¶.hI5¼7ÎÅà:ÏDÏÎb¿e 2¨˜kq?«fæÇI[òÜ©hœn ÀU‘z4È i$±uyY&¸Ú?Œæ>Êpô³Â(vKlsM1f 4ò^›ÏÁ+(ÇT“=ó]J$@&ärt’©ÄˆãØŒ³šuP4M¦±{¥Äz&¨Î{\YÕ6$½Vº(G¡7KZI‘Fžµ’Ûg‘XËL:hÇëk1…-…Ä£·:‰ñ±)ntí¤è· êáŒ@ie&³¥dì¦dBNCŠƒ@, ¯/hí¼r)_`Ešii$Ö öÖ•cl(„;iÎÓQó¢E–ra®4„®¦OBO)·p a… R†#»BÆÕ +eS–¦#²8(²[4~r}®™²–,M1GÙÌê,ªÖŠOAÀ‹²oEŠZà™e2„¦†ô£<‹µIÜ ¡ Oàþ»&þEÑû!„‰üâˆÞ@ +ªPB‚Ò8G-‚ÓDd@—œâJ02½yÈUÂ!&øAKEíccCéUü! l_êC•éD®3Ø͉KlÜ0¶VtÙR^KðÝýpŒ•âG cˆ¡ž¾WºL€C© s—`è-ÇçE %`ªÊúgögïI‚Ù<·dÒüÉŸX$~öË|ˆJkþ$dåÕ„‚A´ÿ“@ü9ÛXlK5{œÍ,}ŸkÊ?ܨ†ÊžØþ¢:z‘Q{KiE–œÞG¦[7,§ ëœqɾYʉhïÛ¹ÎtõºÒ›Wy¢óó$Ř³_cb–Ê5¬‹ÓÅFåuC˜ˆ†A&ö <…ì·ãŽâ ëJÏ̥죭§ùíS<”ï°õ-u˜N¤+0Míÿhn†ßéáá­ø8ï“3²@*ÇQ­Æž'…ÜÄò7Cg,.™s~0¨o´½ÝE™TËØKY[‘©†®a‚À&æ‘%ÉÕ,ëàŠi!šbm2C]ܲ8±õÀBÉmXêo^Ïc´vu&žÒÖÐ%õuêÚf¦ùaûýÀ-úê?SzxÐ ‹ySdYšpv×QÃñ´¬)α:ÏÅsŒAÒc eI–ôÆkz­r¹,}˜äiùæœÁ{ÇÖ›ñ§|h6+þ ¶ë*ŸÓÊ!ˆ³é0qÏÂﮕdH “©ü13Y‰MT Šöüßy;g9Œødjßh¢¢ö­òã­”Ô˜ºõÉV±Õ?¥Ìâà`üç j²‘j·§ø¾‰{„¸z[:ö 㜀1­·~Ãh–º"€Ê*S“:4Ëî¾B¶†‹B’*ŠzK˜™S¦ii%ÀóŠ›Ò­8z×’ "Rø¬hý¬4)¹ô)³§5âe£/©‚•1 •Ô#ë ¾’@‘g"Òý¥²r9pô›Jf:ñS–²a§’à'ÊZ³–1³È#–¶òÓ; À-òÎ0¹a7§ÁÂõx„ bÖ(Êó1zþœ‰h# Y=@7Ûä«Ó !-•ê·¬Ú;D=–ëu  𗇜L‹0¥™X±£$¥È„3ÏŠàÒ&òû4#j=ñÂ&ƒã7‹¯²Éº6€„9ñDZáÃÈþŠY´Ÿ˜‘0 e‡áżúZ¼ØÀcY»±YC`¨•“ “ÁQ>Ë//ÓГ[®“c‡¡ â3£H“ ðÇAF‘*ÀÇ P$’Ái‡Àûq­ ¹P=ôg¯Øöžá‡lG`éœZssØ {¯$9k(ûAiç§* \VŸ˜Ž0Ѓ)‰Ï¶hàœ¢ß@ã#¶0}‘ OÂ3)±ÙŒÂq¾³¢òŸISž¼/)»‘Àt8-‹n )á¼û£7#Ø–Zß(¹3žAÎÆS0œÎ Z«rW ©ÊÛ½B<2¿»UµÉ ­ÌB ™7«Ü©¬óß9²u¢òµ@ÙJȱ”:ÓëÈÓ$L‡›=ó8ØŒEloA™“”át! B óŠ ³<úޝŠI¤¬Œa!Ùq¾"WšyážÓ5©³ Æªp>b¼Ãà|G4 ¼b£|±?#5>T˜ ÁK c=Š?7v­:Í4 ß88¬¸ (àƒ6Ø}§4[ˆƒ§©ÃŒÅ$P7)™7¬X™Ø‹ˆÂ+Ä{“"Ž0±² ‰Gcß±Óo.ºUˆ‰ šdBɇÀ£s)»áô¡±<>ÛqÆkÂÌÓ.MÉ.)@b:8úÏ*˜ Ü€CwšÖ:½"ÏBÒ 9Ñ5»ö= õL¼Ä;¡cÄ©‰–±Ô=Zë":4 rACÇiM@‹Æ¤ì #JÖ࣠Zb**"¢³gŠÊ…-°˜Î²ãQ <šó*$œË”Ñ«+·:@$ [§2¶ Ò…6Ì‘bã‡ÒbÀcn¼ÈŸˆcë‹C ”SK õ–”h7èäÌ#j ô_¢T²N{>|,FÊê–•#ë÷ ±5¾ãGGrÏ8ã;NlãF“àQ"2°HŸ½ZšS»*;¦.ÐðOч¼R#Á]5 ¥“]5R°É$ÉÛá“ü83{=œe§»Šˆ‘é9H”Ãê̼Ð3 âû(}?½Xè RŽ›ì`¥œÌ/ü‚­òÁ”M=F û)Ak±7³š-©0A‡œ[µ€!È‹®eL#‹±¡LÁˆõ;Hȼý*ˆÁáÀ=  ³l²iíHœìã àÒ8z 2B\{™8ô áì-Q¢R%'¤jFAW’‘Ïrä4Å ô½\á*Ø ‘ùšˆ|Ñj›¼Cö–áÕ9rz€ ×±L„ÂBH”T:y ™+/úâ ãÇ¥\[M1ÂM\ D@´R)]ñ癃º€*u7úH¢:ˆÃ™Ï$ P š@äžÓíE˜}Ñý”lÉ4Ì)V?ü“§ÍY2C›Ð'üˆ‡óÚ˜¤Y ÍŒÏh¬³@ˆ ôÕ¾x¡m:­iFÂäÚ ²œ C2oÛåÌÂÎJñÁ5`ÓÁ',rJé½4âUJüU­«´2<À’ I‰)½”,ÕŸ/2Å¢œ€ Nð}¢é´Ý5­ÄÜY+†×¹‹0»|ãÀôÊ#æáþMì«Pù´³…Ïx+8Óí¨Ìâ¥ÅBÏ#Š(Œ(íÌÐíE ½+Íf"­ ¤9\4ò98þÉa #æ¯:óA¸2lÉm?³‰Å[ e¯„'[ÇÆb0¨‹5¤aE+ƲÐKtˆÃ’ÐËŽˆ£Ücî6µs×qgU3¸N½›Àá<@`ü[}‘QÝ€u^Ò3)2‰}Ÿé¹×áœ×S¨=À¾0êÊÜnWÄ£*-¡¾=c(òQ™ˆ$`ÒSNÄTÕLþªìî…â¯Ù¾–K¢ÂRŒc`0è ‘?ƒ©ì¬ÆŒ¯É‹‡Œ)ßÊÎìŒ²Cüb<ò'œ¼ÒWŽªu $Ö³ëp‡pÎÝ!HÅ8”jåk’Ø.à‹#@cXåê–é6hƼ0€> Oè „A€PGóö Ä@18 - ‡?@¸@øÈc`‹þ,†Er¸ì)ù/ŠKß‘@TÕï7™Há’8TRu™¨T9”ªWÒ@q™,v¢Kär8¤*S‘ÐhR·Ü0_ŒÕÀ3÷ô*¹™Bª/Èe¶ _Ìf:LÊ“ŒÒdo«ä2O ŽÉß8:¤N3N‚Á¤´—¶6‡F}Ò$0©,æ9‘Ô(QðNveš‚¯wÉ=ñõV·×â’Xfšá%ŒÅ2@9”—ÓIã5Íœ*§ÊDrÀ =Éù‹‘Fâe ÔY`Õ™|¶ ËÒcö‰~˜ߓ̬[úœSŸÐèGð¶8Ü—}ÀéÆï2ø"¹êòFäòy. ò¸6®bÀ¢ÍZJá%èËÐ6(šJõ¤i*(Û€/òªë [£¢*ð9ªÚV“®ðr#îÃÞ©£/˜€ÊLöÄíûX‚'ÈÛe¬‰+M €O3;‰šè¯süž Ì觪Äi©+ 2ßÊ ª‡Ç1þŽÅ¨r0‡G` ;ªjzí¡«M0!Ê*&èÊΔˆ„ ÒIûŸÊJÍ¢Êãl¡#+„Â~¦LQ‰¹îŽ©*ä<Ît ´ÁoˆzÓª:ÓE#3rø\‚še7ƒü“˜»÷|§‹6‚Ú^ŽQuëè>26ò\!Õ!%œ‘fìJÑóZ;æh²V­š^0ðÁ¼Ð °–š¬XEÄÀ¸fôòh&NØ”7Pí*íaEÀ…$³ôEÛ‹D„…ö¾wÇTA/V@¥šŒ\Û‰tŽ!H’·†ÊÈÑià¡ÅUX»_‰SqÄ(“º„CáÐHEµŒ­8Ò¹^ZŠåØÅ2>òÈë8'Jãܦ˜1#IÑÌ̲Ã/ È#‚Œ­·*BB#üHA„8¿³ ºð#q”ˆŸè¦Ü$Üa*n°¯Ã E Zi¢€YjìÉ s•Q,$ŠY ŠÌ‚9ˆ(ÔUìZ˜}ÄÚ˜ÇéJ$,4‡ º_ |È”G®ØCšjúT¥“ühHù€yÃòAFM¢*‹Q¤Ý寒ÈX{}"È~}CÖןù_j±éûË0|“Y>°9¡€tVzæa럱ÂDéPÆQ‚í@È™2 çÑ^Å5<%Xã¤:AFýv¸"†ŠØÛXR¡,šÖø‡J#›ôÆ PEñu%ó@Ž‘Ø~ü €…p± ¸»3I y†B§¦ŠxÕà»Û§øúË´ãPÔµ¤îøq‘¼šÔt¨œˆ¤ìUn.ä¢HíŒÔÆa†'ÌN`ʲHŰÆfƒÉÆæ ®‹<Ì[Ѳ²e1Q±šÝÒŽ.@ú‘øæŠÐñ\8‚UYÈÀHèú¢w\†`cL¥"_!#YÙB&PÙ ÿ¿#ï ÉÅŒC¶ "'îѰ[Ú>HS¦cUaCtÑ ±"جQ8Ó#£˜Jû`ñ¼‚f ´gZåwCê¾k ![Êž|;$‡\êåEf0¬ÈB¬Ü æê-%ˆ×ÀìÏ™¤-Œš~¸fû¯G^Î_lÕ«ãY„¥§ªÿ#{†(ÀB°ŽPïíQtœÑfÊH·½²´œ‡Ë|Ù˜øƒI r\‚Ö‹Å ïÖCM@fUâÏŸ 5°iâ@€²Ù0¢‹9©ÔѦ޶˜0§/³wûôœX© \"-7ì%¯e,œ‹[ú÷f¼VGzç‡^95Ö‡á#-oŒ•  úv5SWŠ r­%À+¨>°SttÊΚ}Q!Ùb9é̼ßÑZ’ï:®oÆ“£C8F(U?;Àè¶ü|`àei0cfF{ñ¡1†7i-<‘ŠúªsK:æQþiN׻ޑ®•5“ôÔ1M'‡×§Ê UÇð±ÇÇ. ×ûýµÞ Ú Í$³(§W»]—ÍcéF:«DÈú’Tœ<ÿFnèÎ8²2Gâ…Ä6H» <70X·Å.(G¾TÖºÝì&äœî ¤ÉG`-Ïr~l¢áeÄ4Î^ Kêl(’¯‰¸+Ž–L¯yj4·È²^ ,6E¦>¬òÝì^]lžH &'˜k챮܊…DEE4ÓȲ,GG¬ˆÿâ”™ŽžY"Ü©â’Ë ª»„€ÞE fϰœK Þïˆ0"jø¯'î;„ñÄ€Œk~ÃŽÆŽg^™Ȧ‚ ?ËŽé.Æ´ŠóHJ‘ÎÑÇfæˆwe,qø™ kš#fz Œ1­ÜÕŠ.`¨ò‚H²q øõÊá àÀ ZbTL†ë$¿lO O´…ÆŽŠ,å-òa¾+ƒ†–ÔE ¸qÉ*Ǩ㮌; &Õ ÈÄÉTe-K4³‰˜ZlôèЖš ¤ñITÅKÈd(ÅP<¶g®dŠŠlT¸ìžT±xM ¨kâÔ(PG§UÌ>•ÂL¼HªŒe¦¾¬À¥#Öµ­rO†Ê )RªKiÌXE æpØøßÅìõaìˆERÁê^SDôt‹VÓ+ê;æ!‰²°âVÁõ ~Eh(щ4Ĭz¾â24"QÏÎ)£|ꪬ°4Ì #ê¤8l1d†;ààhˆCÎ@ëò?1 Û,²`©¨ìˆÈYÊn×H‚ÊCTìc°úhoÅÊ?Â2ÀÌpnæüÈÂ^«®¨¥)´i‹ô¦dÇ¢È6l°¶,˜/ƒfâÁðŠçêñ0ì‰ÂÈõïŠphnl¹Ír"Žl4%\ÒoÏhpC†H¬¦]cüãÃLóȲø"’Aî$m¹ÄвlD¼JÜQÄ*F‡’Ú»„Mï¥_#Š©èHK%]Ǹ\G‚Vƒ@&£ü^ÄŠ7.°Ž¦ !Np÷Q.¦-ÿX?Âàá…Øyã626EÊ#ªH®–;íTg&âAö–) 8Ç^8Éjyku+®c&D!ƒýRkÄ3ÌN¹ÒœEë®äŽ „ð­|ÍàôÂ'2*Çëvæ¢6S¨×êr²_3p@`HTÄì?2ä½/딆è¹Ë³'­ò\°#LPŠ®ä(SRû­ØãHÌ1zåJJ`ÊÜfÌvœSp+ïZTný0b¾?Ì u~ªÇ±/'n\ò eÚxk~U“œ*eL£o$¤ì\} ¸Ÿ®–sÌ ¸ï‘(/Ã#sƒ7móÃ9i’•sy#kÞ$çP7¢ ùõ$‹×BÓd`„EsEi~JpW3Fâ&\Ýä>ÍpÞJÜšKÃÐÆ¢{pú†ñ>GtF£“ØéRwí# Çm>1”èÈæ‰sÉ#„³R:ðbø¥†]ÐvÌRÎá*æ¾´X6Mx‰ÊøTÄ\H°3BÇ“ìO<Ñ~yk9Gõ0$¡¯V¨' Fª€hç êÙðì±4¦Áôt ”L­Ì7æî³„Vî*Ó& Žó%`Û«®­Ðä`¯iJ’ú1-Su"0¼÷q,¯nÌJgO^AdøØ0úº© EÌ«]$ZãÆÙS´ÎÈD>ÓЮHpLÑ$±ú±©[Ð[”ÕÐz6Ná b&ØkŽIÑ)J+ÐˤVoÌTŽ+އÏY`j¤Ãò½ Hk5.§îÇA‘ËU9E,¥->3Îd\-sàpO?†îò;*ô•…x£¾ÂR•Bϲ;Bf`Ól»_+—ç¦WŒ$ÀÒ-Bn½ì?HéŠí⻈y..K0Øb¼•¥DÚÒ6UÂá[Ü¡ÑÊU‘QR2bÉí°£oP/”"ÌØSF®h; ~>°ŒµL+Ž\3§q`ðC¿Lµ#Idùmˆ®¯ˆ(õóæoðš‰Ó†ée]f1v6‹•.æ ÒÊ‚ŠÝnfß²6êêãTËPŸ ¤O@þËÅlñ>gÍ2O‚ÄØcfûm  ÊÍ:®ªW*KÊþåȤH6Ý儆fͱ-Qk!õ±úHhšÁøu¶fOFüníÖû2gLL…,Pì ÈON–æu¸ÏÆä¡C¾jªÝ å¨HªKTÆ+Óï_pÚ§—IcYà™ xaTízbIÃFíM¦s+D†DßlPïÃïýJ'bfÖ‹öÎÐlPž!óÃÑÅÄôÃH/ˆé¥ƒ-úÞWˆoǨíµnÕ· ³ôHq&j¥ Åt‰R·í¤kìÈË`€g‡r;éP±E®%n6$C%#+“ÇNÖã}€¹g¨ø.–pQ¬ hþ¾ÆÎyk–su‰9Ÿ'ÆÖÙ •Ixìðº2xo¬´¡ŽÄõ§«Šëì\«ÔdzI VJ¹w3?ÍS¤(G“K”Öö©kAeêÈñÎìEv7*b)mûa°¬"mÖK-rŒÅGQÇ’Îîtú7‰€ÖšÄçÔ3®G t%ø²´»a8Æ(â&± ;Õ!ñekžj–çzÜXBÖ8xp~ï+P°„-Ïû£Ã ªF¿")Ų¿&ùJ›‡¬0oøëwI®Ç3°jܺðÂXê7ðnJqH]wäqâF>º×gNàù°‰®@‘Œxß¹8ö¸Åy}‚¯zИc5ÕíZÛ+wò:ÞG0fÉkZš#KâKÈÀAuL®ý\PY3ÌkæDû-+­)ý9ç9xB„<É—Jç^U<Õ[÷¥‰+€›»mëÞÕí˜÷0iƒ±•·1»mõ¹ µ¼°—(ŒÅF}k® ñE¬T1YT¤éÍÀ·›à".<æÖx*Ÿ…YŽpg•l»ZÙ1kŽœê‰P&F¾ 3<ÌŸU2r°0\•@èÕ‚ïXÏV$†qGkÇûƒ*ÔÍSY¥ÓüŒ'îØ&yµ-%Ö…Æ¿Q\Äï²ve¨ÈNe[ûýŃRѱn¨i¦4˜ð¢JntÁż*œTUv»ÝËø“†,U“R=­Ô Î$âÖ• K+Þ#!»ß¸òã‡!qË6ó;O¸ðÙH¥u#‚?_5”1ªöRñb…aí¥¡]·—…xŠû‚©®MK]¤—ï¨-ÿ>6ó|¸Žu¥eµìŒd{g«6]'µšqúC¥˜™«§Ü¼fRë•(´]n ³]´†˜ìÕêà§“’@îN/‡“×ÃÉ+B§w>¯Êû¾d]€%E8ÝÔ)^WžCèºGŸ.ØZÉ{… RÆšZý1øØ)úækÞƒ=˜5 9NÄåèN°H‡f]9nÐÕæm1ÝŽÂwæ<׫'§åŠâ€8ˆxE=rixG°Øä  ^Þšó%ªÐ]æ¤è(‘b&#üJöÞ`Šc¢Ç‹ìçL%4UÝÞºì0¦º!¥Åæ[¢L9±Oéá%“Õ6b"dÙÄ X¦¼µïqјè\[›g¶½¤™àô9£ño$=Ò›RßÍbü½èÒ+3õ¹#T$ôŸ£Œ=j¸;ý8Ž*0H{”œ“ÎMàÇ$ Aßð˜Tý‡AÀOÈ)Ã"Ñhcê8>ä™âIß±ô®!(ˆD"OÉì5›D!S8„Ú+M¢ÒGÀ‰ ƒAçÐÈTÞ}Oe`j”ú[©¨R©\2Œ@æÔ`&¸™Í¨9DZbù·I¤@˜U¹óq{]íYt-8„Ã/`)4*Q …D"Óê̈ÃÂ!3éô£LUå-rMˆä«vXU;<±E­1x,úc}È?æu}-~3²Ê)ÒŠ¾>_1¯jår¦×TÃBbÑà&§•›™Ó©Wø,ZMã¿øp9Ì‚}ÄŸI©Ø>F×i6ÜäØ^MB“rºøH|M1…r©ÛläS~˜©É²L{ÀkŠt¤%zä£ÉŠÖ¾ ŠV¶"Iâ ”9®›>Ð!@D:Í ­ã¾Š&hbbÆ¿K =Gûº‚3h*g€ŠÓ% òáC •€Or)¸ÈLkÈŽÂ “:¨bå'É›Bgà+'Ë¢b² ÈâF$Ý*i\n»žÒ“æ"Ë£”ÒÁÍ3Ö›Kqšf™Ã^†¡ÎŒ“<Î,2 Ω¨äúÒ¿­¢¡ÒzV“&ÉBg+ Öë<` ¨SêLÚLâjè,­M &´» >Ñ.;6þËó PšÆHÒ~®[ -J²¤Ú5²j%Im%FŸÌ “X¯Õ ‡'Ѓ YlÊ%i¡Tš|lÛo‘ú«ÖŽ ;ÁˆœFB W‡í©ѻ5¼“ñP6‘" o¤ £-XI*Ã@2Ÿ]ÐúÊÖZÓÒ`‰4¸YøåZ*¢™®)E–•ºñ-„•Ïêc`8¯Ó7%à§ëÂþ@çó”ê"Š«Í¨õ±G"ŽRéS•r<&/z>fktàË/ÏŠPŸ]ÒÅ-A {6ÔÒiœo9¥y‹×„Ïé³,á€~Z¬Šƒã§âvš·ˆµÁ—;ZÔAŸÌ݇GÈ’Åžê3K¹ñþ‘¤KjêR¡2ѵlÛx”Y×l5–£Ú]f^MuæâÝn+7ÌÝÀ ‹JkDŽ£ÜÊlºmíO¨´Yr‚ÏTn%>²Ê…‡Fêsb©W,ù¿¶”DxÊx×J<Ùøõ‹kÎj—:ó›n“ ®Éùœæñ´Á(N¯ì+‹y¿Ù—z8›Xò:L«¼üŠ3´] Qˆ÷!t^ï9n§Ö2ÊÀÛ¤1ØgÏšûFì脜¢„fs~Iuç6txÈ•8lGõÚ’TY&ÇÙ¹’øPO; OP˜œBÅ Jf䜇A`ìHsâHæ%’ãÊâ]@cÜÔšUÿ ”ÃOÊy¿½uE sï#†íÄA4ôyˆá_cî&W®ešw©à›XÐ\`! MÌXî· zaÛ·l$¡4Õ0Ò £•KÉé¶’®K3[¥Ä†$ ŸJ¼E8‘Xø§ØUÑ1Dl1€d¶|[œc‘)(ŠBç®U×C×oE– ÈœWš5|±ÑjÃdቩýŠa=Õ8¾Š’x@Õ¼Qú¢Çébpˆñõ‘ç ßú‘NÃí¨0&“ô!ÉX“% J7J‡éÌ‘²8OŠºTKkDýD¡ÿ4"âq2èGñ÷-›'¥ÒV7±ÛtÈzƒÆk#c‡ãýíPYZÖTŸo1]øšR„(”„¡ÇõÑ¿€P§3’Š3Ô·QÔ†ªf!+vÅ¡ÏR«0W([¦6a‡Ô^HBtRÎYP¥0ª]ëíe t˜Àxøãè avâq%Æ&K Pæ£ÈBRqFñÓyÑ2[A´bsðä·L:˜d%&.)Œ^¨uÉþ”±£$ÎË3$Ö~ªÉ¦&òz™$Í Ñ’HBŒk|NrShgÀò§òùÊú.?NTZN.p¥†ä%*¡q„»HÝ3yÖ””X3@´Ø¬Ž˜}EÒc,\Ó;N ½Ð’²\å²ý¨iþR%['¤è¥1ñ‘¹3&2þµ·½™žd=ÆRÙÅÞ:A ê•ùBÏ2hãîÙGû*¹µƒÉvG“‚,CˆvÕšGî?Zc¸zö2É“v±ÕÕX¦6lêÇ­N­ïLÞÒ$ž ¡W¼çû\MRò%±ÞÓõAï.‰ÚŸõtr†Ì}fÙÜ!£Zi!¬6¸ä2•rØëÏ 2ÚÏZùÇ9#V÷<eÓ Í¥Ô¶º*jà.ˆÝëܧ®Ù!(xq™)zµ4’~® íÖȰÙÜ]¬{=xÕn"©RBîRï»è At2HHùl<Ê;œ²27dL~0"M»+%²¬˜F¼¤‚fŒšTÉðp m¦É¥'æ,ÇIž $Å+˜£€-Wrú•´yF{ótYxŸêè¥3Nó.Qú›huT‘δòj}#ë'ÙzšO­ üèzwrlö¦1ª§^[‘À #zñšù’'5lOëvuæëÈ™À¬¼!"Ú[DÆ^dZ5)ÃB¡íŠ<:÷kpèù4¼&8öNõ 5&´ÚD08ëcšUÀ¿°5kióCZx\øÁ:tÎçˆ/{ªH~ûÎÍ Áå£[£6w\8"ÎIS¸²Äá$»¡–™„Ó1ú½ñï6-^›J~íKd]*h:ÿB:Ã+ñËÉ©B&Ë‚Q3ɰ8è 3´+…ð©.AšÙÁ- >d‰°l@™±=ø6!¿Ž#££š‚9)P~™ñ܉’>q‹Á0|¨.h³ °Ì1{¶Š”´z‡-Y±'B à«pשJˆÆ« | ¡!·Ô2ƒ±Ü&Kñh˜ ’9©-qi©+_²Ø>HÀ¸H†<°5±¡•òS;£rœÑÞÀ(ª‡0<>Š.8Bp¡©n—û 1[dCНaˆ)#ê)ºÓŠ#Ó*ò J²CYæ hå@+ûºaç¥R¨ú É­¶+ ?SÁÈŒÂiܾQ**›^%HÒšû2!.©JJŒ’  ”%²Õ–98 !ϵөÌ[@3'Eãc˜t9Óv‚I€:"§¡±Aé?¡Y„,ò /còi$kŽ8XÀ™È·¹!’:…©`„´áT¥K¿›€š‚Ù)+¶[–:2¸ôiHƵAÍ"bT¸û ºÛ@ÙI¾ØÙŒ W»Z”!A­¯ˆ‘¹#œYbª¸—§ƒlˆJ¤¸œ3 âW¦IÄ™¨,&?8YP.ÈB °r˜;ù®-鈮xš«i­œâa;Éþ·X&“Þ¼h†918!r³‹ÒËFÀ|¯+Áœ¢­è…8ÈG‘ÅÀŽCd‰¦J;Áœ,3?·a(C( l”gã7€ â Í•@ŠÂz~½£;-kˆ£s2KT­üDáŹðõž[çPFê$Ka>·9†©»ù8XԌّˆd°-à‰ñŒ2例LG€¢@Ù.·auBpâ“ê\ S°‡ì8„¹µs¡±a?¸¬w$A€ÞŒ³þ‰x‰$޹ e››iͲ&5q8Û®.Ó­0A–Jâ5HöÎQÔÃ:QÍ„hŒÙ»Çt瀷 Ù;Wºœ“ÔÆ áÜ@S .¤”š„šBê®ÒÐ-dw‡üÒŒ¤ *ü²“Q(Š#=€3o¿DÛœi³:„3$Þ4¨~¥J&AÄ!pþ‘ú³´!‡Í³NPЫòþ”ÃÅÍûöºc§'ññÂ:%<Ð Ñ©Šœó0Rµ¸LÔ‡øÆÀ€‚Á(ŠrN@ûœªñÿ;¬(õ¾H“ p†­)$rx+…ìíÎ!¿‘ü®¦‹h·94Á´"™a-¥;äŠ[®?Ä‚8•Ðâ›¶¤fO„P”œë̂͡’ö•>Fén¡Ã‡FdN0£f™‰—ÔŒjš X¸¯ÛÏ£Á Ó½#°’T$Ū‚¦•Å“ô@)¹ ×ÂòÅQ¨}DuY ¡ÐUr¨Œ2 ´ýštAÄP²YÍ!“q<é¹Ã·!±D(Ðk-´)­ê`VÓè·c< E»`HTXL„Váð‘Éêhëò\[”Ù'‹t8N¼y3¤º:i=R"•Î8}¸q?ºêšÙ*=›è–Ƀ¸´âi6*‘À¸©#ºH³¶ÙØ|ÀûÌË|”W|#}tÅSþ*eÍ3 ò°L!È)(ÆÆ=xRäò‘>ýDñ‘Éu\Ÿ‹7»±ˆ‰ó„³^«Ä8;d®ãh8\òÈ èÓ•&±% 1LýZ¡”+ò¦²”­µrPµÉñ Í‚ýÑs„Ö ›—¼KÌ-Ù%»¾Gø‡@ÙÔ¼;ÒÛd]„Y~¦•?Ћ!°§KLqZi–Tj|?,š—ÔŽ:ö**Û‡óܬCXžY±Rö1;[RÛ)¨™ä¹1‘Þ²‚²Ê! ƒMëÇ‘¬ÈGJxXÿQ˜ª´û«‚t7 ›6èPH“:GAÛæŠëÛR5‘ä¥ÎÄõN×1\ çYC§»=HG-tÝ›”*XâãU’4TÈŸñŒjTÅ’^‡Û“ |šš¨F‹F®9ª‚Úuå™Ýj–í•9Jh¢KëÄHl\t0r›»}ÙJ­5~ ­­D°8剬ÑTüá©)#¹Ó¦ ½z`­…¥´ ,ŠŸ ГI:±=Ø}À˜l?´RóW2ð¢"-ÔÚ›  3Øb¦§…¥¼YˆÓÒî6¸¡KÅ™e‡'C0*Ä]¸ÚÜ4;‘±Äx»åØ%â-¾Œ!‡åÖ°¥X3›ÜIᢦ¬¢R€¸²2dÔ}-%¼RRçÆè†;u¿T L`©ë‘úWÇ:´Ä¡ñå-^ÒTÜxõ¾B[Í ;àÔå q»ô¹]±O´­ÈÙ”ÂíUˆ",96hLt&AüIѤ.ÓÙ ~u |D¬FT-›­­[Í•¡c¶œÉnÚM®^ÝÀÄÉ^ ÇE>[k^^(Ì€hh‹_™åQ\Ë }&´ÍÙhþ¢-,Ìì%¬Ýpžbý#Ê›¥8å+˜‹¹<ä Õ–~9r’¸´Â8Í(të·“öÙ9@ítØœ>ë$iËa銬ºâ"èh4æ?±Ç“ôj­†ÕņìNY.X¨ ‹‹»‡¦kᎄ%f6j‰{9e tæ œÕ„“öwåœtǼUÕ<­ ¿i}%T„Ž/ºíRÈ¡!§*ój5s¨¦ÀTP’1}È]S‡¦º&µ£VÜ}DdÎB»¢Í«°®5ºhDÑ¿Ìm6ݲ‚åA– Ã…™›žƒXVÜ!áÜÕÚ¤†äà„ ¡@”"ë•b±t ¥Åí¿æPŠU0Š.é7ª ê[(_vr¡FóìbÞ½âëï:~² Cwd»¸'ìdgFóÁ"+ŠKRʼn.ôÛHÆeh·FäûÉïšÈðSÁKÛÕÓ¨ÈføEÅ.ü/ ”ܺãb¶’Eýe›ú¨*Ï££D•¹ÿ}Ùª²²\Šrk t™ ¨aåC\ R.Dš÷l%üX}ôÿgüˆÁ`pWø†BðEûŠBwÜfþŽ?#ÑÇô<$ÀyDe÷ŠH¤IŠL„GŸˆ`œÊ¦ÉÌ’I6—ÄdP9ÌÚU9‘H€Ôù#Þ¤ ª>ªÑpDQñ[™Îg±™"IL‡È!9œ’);„J¢–8e² ƒ@¬0Zô2)V}JñJ FŠœÃ¡ø`ƒ ’X¢6{µ–9ŽI)°ùœ‚U6¿^@/î× º?ñPË€)§Bµ˜àR„m_ø õê'—mŸõ-&=]†o'Ô-ŒNmÄß´æ/kÒ›l6q̳w¾uèYë»ÿSKâáöÙÉDŠù3™Î!°Y¶øÍ²ÐùÍšñ Ôžê ‘>Ìz ‘>íël’/€\ÿ$ Âøç4: Ñ"fÜ0¢2®C<¶£(T™¶H~$ŽbøÖ/ÐR¬Ñ§ˆcü¿>l J“=À –²ðêê§1ÒšÊ$ô…¤Q¢ž52:7ÎÑú´$Épܵ lç¯ÏŠ,ãŽHèd™"7Ìc™$ÐÑü¬K€žæ?Ë“¦¼ÍŠÄ„Ø%Òjn‚É.@¤ÊBê®nÚšÚóÙüÀHòŽFJܾõ*ÑZ"›PÏŒü5‹ŽI,Ý ˆS´KÄ7Ó½!3ÌÌć§iÌæ×(*=.² xÛ¢i‹.̨².¯‘ÕÖ5ãʦױ»ó[€05SCŸ¯ ³]Ò¯4ÎÄ[ ËUD7•ÐGŸ’„H˶ŠCn[Ó˜¯\Ì~‰ºI% iÓ×ÕãzŸ©´]!&wT<}Å ³˜"žÖOèŠø¾\ ½aO–D¶É¶ÎùjVí8bÒŒ«VoåtyåTÃÝ©výWÙz9XÏkm*¨hòr™½i4’„>lB$ê›$YŒøå¤ÉÛý$­53M§p=†ý€2J)§å‘U@·ƒ¥lÇÏ~BŠ%Nõ &i¶NêÈUàKOML>iš†ÚL†ÎÜÊ”Bgµ Y“˜ßXAÿ5ñì(îëú&¯¬±©«z#¡é²sËE¨š$Õ™Ô E²Gô“žiÛ½¤xM^ÓubðÜÜÁù ¬G ŒÝ’û¤ß'2J¾}ÈUÕ‘ô(RÝ{m ¡Å¹ˆlù+}ÏW›QœȦ}æG¥VHVJ}Kü_× Æ "sÙz'ê±ìT @Œ÷Î}ó›Jæ]ã.@¦×#D J8‡¤jGÖ’øpäqð¨øH_k ýÍ0¥ñBåsìñp=ôÐPˆAÏ‚…Q#žçúÍQJ(ÇÏ:¹ †ÙȨÅzÎÇã|d)63bTÌh+YPµèrCßÈû@LÌf» €©Si±u·D>áˆ]† Á­tvCKÚ Œ„0Ã@ÏŠ²ù`­ñ/,Ò(Û‘±n,†;$’ƒ–Z€)Yi50 ì"6«}ŠCvfõ¢‘QHÐÄ(¨X£c¾9‡fÈc¢ˆD[O•FE#,Ëù)GÃ'[£«ìÊTH¤\›Í,¬¨ÝÐHR|ÜŠ p®G&•¸×’ü˜‰Æ5r"ÓÐSå ç6‚øàñ&g>HB2Õ1_°ü&mì“ uÓöœÀ*t&S¥ex#îmÙ”ËLù lÏdBÁ»>Ëá$T,ᙓ³æ’N{°‘FÂA£’Saèä€ù•‰±3ãûÜqŽ»×Ñ"™’BfOýxº…=ë”Æ¤ð.äzæ:¬9бVŠAGÖ’4ž$ˆ¿‡æ_‡­=&eaP®§Âg‰!ÏpÀ ¿¢2VÁTE=ŽEâòo(É|©„>K5–à½kÒB4i | Æ–—ÀÏÀ%"¦ rL5²žŠÁþ{Ð$‰ÎÇTã+÷6°}22üˆ£›¿sS9XslÝLr+½º¤ÈjÍ– ’¦âg”Ûf]‰nGç4¿‘¥h_o˜‘‘¼¶ÓO9ÙÚ8\Dh! cÉ–0 HÇbˆn'>Ô%ù”É @1F wÂî–áÌ– ¯P‚LŒÖmˆFòð[Qó:R@%I&¶HŠÄ“#¯d‘ä+ˆ{z’‚I§£Öô€A­ˆÿšmjZÖ6Ú,Aó»–Ý‹ÌTO8]L†ŠsyAǦC#N‹)FÇ…ùã© !H¤Ž çU³ž:rÎj%É3‹¾)•öYb8wŸšn#” J^Vo‰qz¶LÆšóê~äLUu.¾VÙ/ÓÕÍ$Õf§,ˆdG+‹¤g`¼Âɺ_"|mWx1È¥ô«廚>f¦‹`t*Y…±°}a¬bW‰‚5’…}´¼.U’LæÀ7<[»?jšIwÆ•rSLnÙh£ZŒ-›4Jš Våñó…‘ÜèyžxdŽP±2/¢GS‹!Êx£ylÁ)Ͻ?úôl5”Ç ´¦¶Å¸£ÒƦ®Å¤ip3ñ y‹ïßúð?b5v­¢‘jíU¦§¦&®kY¯+B¥h‡ûW|ÌLÏ!¥•Òè–›ä`ÜÀ)¬¶ðlYOIšI>eúò`¸1«çÅ¥ xb@é–á*®¥JœŸ9Uˆ¾áµ ~ªy˜M¯V7È;D·0ŸÔYã”øÃs»H–Q‘:“/‘‚}LJ_Ù-_œ€)þÀdÓCR¤Îã“åWL(še£žb/ÉZ+q3óge5’Ÿ25‡I™½S½ÞNœ7Ò’¨ÂUQùüŒÅno¾4êÌóó]X{ãRjN1`o3uÀ*Äã‚`ó›Q‰šÜ»«Ñ¼fc:ÃVú^·(PTúƒ>] ˜Dðñ$^ áT$t'%_ßDrÁáUBÙ§‰¬w†j¥‘v„V÷Èú]Sƒáî ­ÛRƉ yÞfÄÈt£Z´ Äè¶…Ùr:Âñ“k©¼%›Ð:d™æN*óSb%S‰"tóïrªÏZÚÐëM‡Ó_ƒžQ}—åfµñÈÁ†z‹YâèÇî:#>\ò‡S¹»fÆì‘|PG>ŸÅÂ_Ôäq†]ÈfGŸ"d *ÃRÿ„Ô~ ªƒ$˜­î—-.]P…øKë fD’'jZñ¥VŒeZ[§U‡ÚÖb^Eö_/ŽcÊîàêJ€M2¾£µÎpÛ¦<àÉmÂfP€ dÇ­ÎSk`/´µ NÇ"hhF·/ɘ÷!ö'/"†Ž*Æá ­JÚ9JüZËé°0U’úà ÍË^ÒɨšFLû©® ¸‘G’îï&eÌÚè u°ð™ª…Ž{¡øP ¥‡ÎܱNã — ÛÅÁŒ¸6<¨ë’j¦ñ¥ØÕ„*ˆ<ž#¤§Pµ8ucK&´ÛLЙ‹®+†ž4‘NË&Е( £æ‘¶ßÂ.½ï¤Q %/7É®4C`Mí\(æ¶JÝâP°‰íq §’¡‚<•q€¨ˆîgêêø‘N^¨%öá1,¢èj£M"Ødhõ«ÎÒÉ(o%Ô_Éü÷Lzî¢ÎðWjcnN_f²ÂÀ @ð"sN9 8åöæüÎÎ^9ñ¶ #Ðzê%øúP¶‚žÀçžEñÚ…”Fð®¸Â¨$ŒìÊLû'Mº"Žªý†¿$$øåŒXCéLMðîÂ2~rmÔµ h¶b¤wÍBG±”u2ñª !D„Á噃žhÈýk JL­‹`Ò±EvÂ^‘¡ú]ƒxÃÌôƒ§ªØÒ öÅ2Š‘T<(бi]·Ñ‚SHÝí`Kïæp#Œ¾ç ©Aöè –Ä„Œ1ü¦S¯àO‚vfÉðhº„blÑ¢¶ìRÎÆQ†/%òÏ+I5kEØÓƒž—Ѿ%w1ïC‚¬»‹îÙgÿì©Àæè„gpWr6¿*Ù ìÂr±§0ÓÎí&ò¡Âø¬¹i„àòUêö5ŠŠÄŠ×2G 3,flÑ3pLûb59°:ÆPõî)NXÅ0 Y¯Ç(ìäŠôP_ŒÂX5)'މ ±D$‹±:‘ù8gÈgJÙáÿ4 žÍN”qbÛK.+Ì<Þ3x+Ϲ$†ÛiT#,Æ”ÏÈxÂ'"oj|&âäJÏDÿâ.î1|kK n©²d1ö¯jˆTðFî8€q„s±>Jú*F&n­”øJHâÓ_t8Þ¥þä‡}ÎTï1%°='ÐI/l|Úòk òXªc.õæëfzôòÐâf\úgêÙ’3Ôº\è«Ä„%Qê½´N kÞ$‰|T2,yB&è2N&WC`»âžL§Ò67R‚9@D«V"¬bpÀڌ𣟲¯2”!ÛÂE;iOµ|M¸:­QÉJíªšfQæg Ë4:Ýb¼›¨YUê9QüÝHÔ3æJ§"è rÞ2Ÿdø\8²‡•@Ò­B†mE%ažJ9#Ãk†´ó¤é-Q[<  ì±v7)}ÜÝmvƒØqgçÕ·‡¬BÂr8xÕ/hq’P2ðÅ£BÂR6cðÝ6~áv*PN TAotGó¤:ØÉ 6(— «ÍÎH)%I=† qk鎄òâÍÕ”ŽçfȨùÍLÒÌ!Fž˜Mò6+‡k YicõxõD-_VÝM9=èHâÑüÀåÈÉX XçOâ›+êÁTdn·£K÷)lÌž#:—Fì4šÓ·¸çÃè!V÷gYnýh©ªsDK)ô>Íu|®8Tåðä`ÌŽU"ZÅ&öúqi0éãoF_Çç+ìlÚ‘=tI˜‡—{ ÓÈ:JÎcÏ)쿊ă¸Ä7ˆfЀY xš0Òã`&µQÕõDzžrTµ”ý@N’õw¯ŒohBLî+â$N\Täoœ-‰.âèðg’ã3Æ‹F Q“d+P  „÷4(Ì »KË‚ÎÓn9B§Ü•"l»—M_µ¤äÔ‚ÒÐ’ÏVÛ@Äaó–iÉn¬#™ß5­UøJ¤n¤å—øÿŠ-{í°]QÞ9G€”óp×›­-Æ~ãyŒ äcu.ã¶ðlÚ¶K±b‚U:/È:[¯Œ,eHÕ¨Æ W¹#ez|8Ó=E5!m*Û¤o¥æÐ¶‹.tw&Ùñu,̤:¹Ñ;É;{šÅ¸_ÒÛ`scKÖŠd /óì»iÑ(19ï<2ñæ\7 ³?¶¹,|4.ìí™J™:LÌKäé·D™|»"»Jx}»¬<<í´“GDŸ¡çÜ_ÉßÓ.feÂü®×j9ë¹ä‚¶™Œ=®¹¾wÓ¸Úõx5ÅòÿJ™BÛµŽÁ;ý9p¸Cã'î“yD·²Dnª- Zªfg"Ë|"d"% òì½Cºže£¤‡wJ÷on¯py:8é÷ëiǨ¤û‹Œâ ¬~J!M8?Ö磷üƒµÇ)ZŒ³›Ÿ°¼\v ÷î, äý­ÂBý €(0û…aØ@{DÀ±Xlÿ?£øÓþˆÃàOØøQ }ÅàÑÇô6? ˜GãqÈübe9šF§ <ýïA—Cdp‰@0ø¥KÙsê¡G—K§àzƒê#,RŸÃ^Á~Xèô{ò?%ŒQáðب³Ú Ó7ü:Z’ÙåÔzÕKZ•H –+=Ž#%‡ÓA‹=r‰‚>r—Èåjm†F(pÈôk4˜Î´bK.Äp*½f.Œlàð‰Ûþ]¡»C÷0‹ì¢ß ³É V¹D† –rU©¿&ǼŽN61Ú4¢{%ÛË­úˆ›O´ ½ð0Í€À õW#ôÊnQó´ŒÍ_ÑŽ”¾s•K«Ðo+ÐÛ>Ž þ ‹:³,i;Žë€hzU% šlÒ€ ª]¡‹zÞ³¥MÓ=·ãÿ€`4N¼ »”·¥ÎÔ*Ñ€+c} h"â*èÄ8±©*SÎð#ïœÛ§o1µHÔN*Hâ¯Èí¨%$ 3n·"«Jž¸‡ìž:§ôc&3çúèBs™LÍèžË ,Ôû!Â&{@ $䣳ˆã†ðD.bJ·¢)SöËÃH²rø9’¬˜ÛÐnüì–‡ú#: ÔÄj~ÉÓ\¬,ô„Ù> Ï„ü©¡ëzŽñUr¯4GûÆÆ!êªT× ŒŒö†>O\€ŽR"³£ «ß” ò†Fs‚Ô£ëæšKÑ,ßÔ}W :oô¹h J¬tƒ5§ì»JPz“2ÁÒ¯ÄÌ»ˆªÏY!¯ƒÔ¤¬T­9NdR†ßï šÍ¶”s>ëÕ'*ZH-¿JXDd”#ôjˆÅ´ã³¬bU&MX*&.hžI‹{Ç4MÖóg–Méì«ÄT³­—¾ c•Ÿ"2M0éSn%§H§ûŒä)4Ù¼bƒ&]ªæ8€:MÉš#SBK£M’Ý:”Sgòüœ¾÷ÄÌ®K‚†eGëÏh¹m2þ”i1Œ †Iм>Ø;LETÊéÝœïKòž}*£ì§3F2͈YÏþÔ ¶YY!ðJѪpÙ'å ]!V¡ »dºì:¢0«Ã JŽ+‹-»OæùœëˆŸÝòß‹_L¦Ié:*•SÞEìéôü †*¨Ž„÷² Þ£ð™úîœÅÙ\ØÆE7ˆ¡¬r¯A/2P4Rp53)¦­ \mư”8uÒéÑ+Ú-ê <ÂÕ*êYg5ôi”1 w QÑ¡SäßVs¦; „~§¥ÔI2%ET®+rõ£Ú!©U Âu†ýÝzZ'iU]¶³v³ ’ã*”ƒhÁ“Ú†2!–rÞÝ¡¸QÉü²1”ØÙJomÏÒ.Ò>ûÖ ©ªDE¨ú‡ë¾VN‚‘£ºAšù|!›,Öè𢢠(äD«ÄÒ4Y×á!ƒnAC,Õ `}¬éu³þ“ôSh¥‹0µŠmÔye ’SxÖ;¹&G`•RW39&J¢+©cBÅ“2Ca,]5#Œm ‹šYg€6½ÖKõv®„ªŸŽÙL’4ÒÌ$ï£7%œª˜aø†$„|jq¸¥#²*¬ùŽ€J›9kA±€‚;r9ϼC?K²P3ç"QÒa{’ ÿ#G³ÛEd3aiÉ•Ïebé‘sЃ=VèÝ[Î-¢h7µ©˜´‚D4ðä!yô}ò$´C¬ ^“Ç£í(…¨  I[ƒçMîÐ<6ªÄ tŽ2"‰JÙñG1‡°:x(}ÜB‘](•dÃÇ=‘9¡oŒ†M8ÃB¬Š:<“±·Ñ ¶gEa“Eü-X¶tã‰Dhù0¹°r©£ÐI±ÜðHÎÊN‰$)þÂ’FdiT.•Yðê, “Äþ4’:Œ’fo¨”»D*†þ–¤­¯­ôS KT㡜d– ¥UEçåP.º6¦šJ‰)dú&—¸Š~Ý3zy •Çõee½²2*ÌÂ4&¹—ãÚ%Q¨óQ7@›Ü©cÇÖP+Q_§CX+:©Ç™Ó§“¥3,é‘LËŸB³€¬FîE_4³n¶»°y8øGÉ*1–óÓ'ðâH¯ÍàÛ†º vjË]™‘ûu9Ô8û#Šæ±öÂè U«%Ͻ¤°¸A_çû)®VèSÊ„‡#ö× Ži £È°O ²Å§-ÉÜ=t,ú}2ȵ?©{Vk&™ò×¢ž^Gìi•Ì.E]:h‚uˆ2È÷/¬4i>‰1÷ÞÁøDSÁžä …+{Xßíõz;½ª¯ ¡.+‹ŸÒêÄ?*\ªœ/šÌ*åIS’MN‘Sà[àt!@ˆMÅ¢“þ»]öU­ê°ÉÍ1g~Ë ›;Ê›Í ·µÚ%yÏöË ‰=Ô˜u*ß´*ŠjBv•u”4ù ³Á2¿‰œ/®éõ½`J¯‘á·ÖÁzè™*az²ß®ë†Øp+^˜„й¿$~v Ä~¼áh]¶5m”ùN:BPÕŒYM|Ú†1éëvš…D;;?±HfcÑPxø•/ÉJR”ñŒÞ­j•³Áa`û™íD•SÆñ—œ‡?å^!ÂX¤?f÷X…þÎ2{„Ê™Už RUãLJy> ²´>}Åp쇚ŒûÎlz}Ó}¨—›FHœ›\Ô¥øÎ6ed¼x(´PA¶ÅøÂŽW 6õØ~ͯcþ(#W&ÊÁWBQÓÂLÁ·¾®d›'Ì{UUáñ.¶Õ:Õ¼Žé]9&/o±áô¬a=c‹P»ìiD5aÈØ¸ÉQ˜åU ©Ot~7|Þž*í,‚$ÅÍãe“×:ù–)X•d3*î}&g¾e*»P“t«•Pc2ÜX%1­œvôU³]Eê*ß)*j•𹎞>ûfËÕ71ôÒ•À4ÝãîÇ[\…nއÃÉW:FL œnœß²Ú„аn¤‰SAW_–ß>À½øj1©y*‰ò6q2a>ʹZ‹úº<ÄÖ¡g"è… ªß3j–¬Òò¥¡p ‘ß::ˆ9Ë“‰£©"qœó1)+3˜‚R.{"°ì:Úȱ¯*žšK=ž[7,rkP„&Ÿ¦£Á([ß*Ûò›‘;9\1ay/*¥±P~°ÑŠ7rÀ$ÂK›‰û“a·*›µ:à•)Ú?PñœX·¾;=‘‰Žˆ«†™ÒK§krÀ²éf'ñ/1ê r­4±ƒÁÍžã±Áµ–˜†¾;,=T6É©bí‡À’·Ê]±Ä™›ñ¿q4Ú!–›ÏÂÔ>7‰3ê¬Ü-®aκͽ ÉŒ Æ¤OŠª—©š;«¢š+ñªл zÄ€8’– U4@Û—3/œ.,8‘B…&ÀæiWcù6aº½Ê³¬ŒÕñ³¬Ó_CÚl§3s!ôØ yT@}—àñ°jÇò]³ L½:X´ÁêEàŠ“ÑSÂ@0Æ@™M& ͉¢òÆ“ÌDûÙCÒÖ'ꥒŠ ’¶’ =ÁƳZÊ}9Y‡£8±¦Z€$0®&ÄG!ó¹0D1ª‰ÚC T(/€žŠ»ª)ÊP(ÃÓ/s"áz5‹\œ‰ÈPœ¾Ã Ç8²ÓxJ œYŸ1ä1š©*Ô9kQˆ3HëBˆ«[Š8øB+c#RÔ¨ »R‘€\+#›—‘4ì\6é1  Ÿ›[¥ˆû€šC‘,†ÀÑz<õ± ìBÀ¨B:ËÈ#Yëã‚Ç–X’ƒv'ð­A:ÝÀA6GùÐË(¨{Ê-²áÄšX Ëí¶+Ʀ«¾´¤¥r˲¾<*JS@Q¤ªXó¶L¬³ð†-‰ÕÊÈ‚5¬9jà¨Yl¹Rp¾‰T8¹ØŸ;d4ÙvÊ'AZâž“.[…B”Ï¥\»øúô€›ñƒ´‚(ÇaΞë”áþ¶œg¢t0á ïÕ¿É™ù¤¶0€zŸê#¡ÊΛúX•“PâuŠ‚i‘ sJaq ¬!ò­>à ÉËŠ±£ÿP …cã§Ô¿JšAa~Et¹ánO<Ä< 71ԇ䵻²µ‘ÁJ¨Ç ׳DeÀTQ:Êžß0éíLƒÃ¸Q–)é/H<‰ŠSC,´5Å Fˆ-óœ®!1yÑ!P1éµÒô¬³‰®¨Ê0P©“”|J )‘ˆÛ¦Ä#Ì¬ÓøF{RD4¢%‘K"rÍCjÇNÉ6%Dá CËéKÚ›Ylºè˜\í(„3DŸÑ¶ŒB‰•”uGáT+X±É¸•“ð4šÝËór0òqƲË>Ì”ô&ø$ø•K\5ŠƒEƒ®˜²Æ@ʉYC2òÎbe,Ú°SÐl­šÝ•BžA×R ÔyøQ¢}€d•q÷± ßTä#NÉ쯗¤z»ô§/‚ï ‘L¹¥¶pù0ÛM³'LáñÌ ›Ðæ‘Ê8¬µê;µ%,ººh7«A8ÌÚ¤ƒL 1^Œ¤p·œº¾¶Ô”‡ÝqP’úQ«ØÄKbK:s>tÏ Ì·¨XdO‡¥v`®5äØ(œ‘Šm‡ÑŸWbšYä0Š›ìô—’<ÝOóO«õäa’±ªT“*J ¡ƒSV äìV‘ÂÁÛ¨dËrÀF¼¢Ðsö:C>Am£4t!ä Â~3Ýmüž%Ïi8Ï HpŸÂ5\ÊE¢ ÉSÆÝC ˜3ü®z .û:ÒtæXÎâÃN¥¸Y™••pNk¥ª˜Y<-ZžÛnÜ!* UJÛ™l´ÍŒ7Ë G„a£5„¶ÙÈÁ1Ì 1l½†Wq1£¬s±‚³c7ž©e¦ÔgrßÙ)Õ5X ¤ —òØ’a9(Lê¦ í“E´N4ïÇD$¼¹9>9ì QÕÈøÓ4 Ñ]£(…JŽc&‹…$¨‹]Qs-RÓ@ãM,3¹¬iž# S#€\L[Wë:ªÃUÒ±s§ Õ6Ë«5}7F, ÃllÌI˜]¦¡I7 5/Ë­ „G ãZ3N„¡ ¥s(ªùšJw.yLïÕä`¬Ô©¡»'4УÜE I }­\ŒÄËbÎBT’šg)*¢M+h¥‰ª<ˆ….ÿ‡òAݱ-ò1Íx}/@­Y=VÍQD4 èÙøPvé–A Ô‡ÔíÔˆAa•Þ`[cQ] HlÉÒ#›U”ȼIR¼Â pÕV.RF‘<‰$ZE¿)ô”±þ¶v°Ù»ºÚP™ûç`-|šk”º7Òú6ÛmÙó.¿ózÅœ‚¤Y~XrÏ—N·ÍÑܽީˆßu’i½ƒ­•ïÓÍìcªÚg[ωì©)µÒ¬•Š8zðU9n½¸Ç¼á³¹Šo*EÍ@¨?$„ -ñJ’ñÅäÀ}KÉ`›$f_aŒU»ÚŽßñ54 Ë„«…Ð'™à¦Øƒ@‚`^Õož¸¡óÄ¢­3åÞMqSŽäë4=Í×bÑOÑÐáݵ«óµ$˜>WcC…Ìpœ]PÞ˜~¦Æ,ÙÐ )وЪº•O¢xÈ+`Ð{'%[í®,/ ¯†UÙ±"ªœðÄgÕ‘ýÈNãH-"n¨»1 ²0;c9Y à÷3I¦èþ¼'3=¡\±/íÎ0ùE”VádͽítÖTµ=B—M‚ñTü/=â®FÊÿš¥ýCôäXu¼¡?Z$záLy2Ú€½Ñ6›úÇ& ó­Œè,–pÇãí®v ¡s:Stuûà”3êæ\#4;žCåDö ø1ù©x»bíüÑÂ3ZÜKÏIÅnà¶\³/2°EyUžëÒßjów"*¥ªªž³¼XsÞ0 *ßI—ŠZßMO®& ¥“À‡ø?ÄÅ"¯‰Š5RÖÀW.£¸ÿ«ôÌ Ð‹zºk<Ì0í±SF«ÏU÷ÎiÐO÷Í4•ô?Gßê”4ƒ£‹z¿WZ§£€Ê*~ÜÚñÛq¸ãGÏóËm6‰)õ¢=þÍ›g‡ÜµÇ•@T4”µÖ˜¹}VÜü´Æ:Ä ãIÅ)2²«Eˆúg|€N-—öbÔz¢¿~ß=°€\¿;Ö\æ,,²`ìÊlg¶G¨E¬"y9t]øq^£¾«1Èä/}Zw¶f­ß.ˆ©J}w‡½ (j|òCé“+3F¹ÝyÓMQб™ŒHý;è!ê]AR~ çC=ÜldïNgaû­Ö¥BiãV¥Žâu zG•õ'§7Óôì<ŒŠ}FŽ)ãh{‘也ãs¿GŸ€¦Ó}€ìÜ¥ùâ®8Iì Q`÷Tí\ßÒo™íÍtð0Ž?áòM †É€Ð÷ì´ /–¿boèü†? F$3Sæ}—!±ð=íG‹Lh39œ< OzÔAU:x™˜Â$3:L¶Tú°Ph/» "Ìô´Gáð‰Lš¹šÇ&r\ ?«Í#Ø\"cœBåWÈ…Ú11˜Ó©÷8äZÈûªÆŸÐùÈ ) ’Grñ¼6gU àp s9—†A²±hüÅﯪÑ@óçÌ4·Ì¿è;K¾!ÇÅ´¯ú®Óe¿Ó@¡»,%n'•ÒâqgŸWn Þ"tÌ wˆ~Ãj³9WŠŸ†ÌfÑŠ­ÓQ}„ü{Ù™œÇ=Íe>Wx×Hø?ï{†Ü¸nŠ^î€/à°ISœ¦"È´Ì3,«†áÁˆ³Úü´êÓòÿ&0Sª¡°”8øÂè[É=i‚E­D 5'ãXŒAˆûZ–¦kTTçÀO’fŠ ‰bZªÁ‘" %‘ê0„1íB‚íÎAþ©I‹dêžlЬ¾, æ"r³å?/s(ªÌìºbÆ$P¡þ‹>©lèŠ?¬L|O”[ ‹Ë+ €l^¤/'$©ê ^{Ãi$ØIÀO=éŒà Š¬N4,€ýO Õ&,zƒ0ïDÿU€ê~¡ó(’¤Èüø|:òŒ¿#±jÂZÔVª|ÿ"Ö<ôMSVTúe<,ûÏPÕ LЂ>ÍTåBHˆº0±¬•’°=2ƒI€3T©!²šNsôO±73XÚJýÙ/ë‚0ÇÁÈåw„ŸñÙúÙ_ ¤7.â9z¥í£²xìrŒ×õ£ ËF«xKÇø£“Æ(]<ŒQèú,Ó£øýe2Éj|ÛQ)•ÚX±ÿU7ÙÈ Æ ’&¸á¶‚<‰5¶¼Ü‘Dä„^À bèãhë3„[gJ0¼ÁL•·º Ò8Ç¡fd‚J $WSæ…!?"Ÿ_gŠ Õ4¬¾fàÔµ(¼ªôÃOJî2{æí Þ–Œpùb9%T9Gܱöx•MûíA|nYáe3S*ÓÊÏ0 òÜU6VÇÌ‹ÖIÛT3T!òiŠÌlˆª×5èzT„~o:…¶‰R?àkH?•í”Ä~0}5î²b:ãCë1 1¯£–„™½)l;ë×·O¾}´ý+'—)ûÌ^ˆ3P yþ7*UŸ–îÊÔÁþ€«qÿ²^¼ šÊ]E%R ®2 `ª Ì–Â è I zmõÿ·EJb€)1ðmn°†¤A#~îð «·ôÉ‚î%åø–¢ÖLÆ#Ñ$ð}Õ"Õ¶¬^Ûp>+ákSZ)ê<ÔD×8[›ê±E*ô# –«8މ8>2BÒÃDŠí¾C5bÔšú7LdŸAXPCÍ£LD¹ÉÐÍ<®e(§!‡óX%ñ4£hša›i_Ê…È»·ÓQs”"i1J¯†„xÏwq}o¸•(’¢}ñ†.ÂØþê¡„*Üü—™HjjxfÈÚ׆”£ ùw®ÕÚ?!ô޽ù¶ci™\mb ”Ǩ¢AH3ÝËàÜœ²‹ ù7qÕ`ÁaùñûmÆæMé@œ£ªqÍXÑË9^Š s)Y[Â^ÚÐü³’gÉÙ'xfõ#l ]íµÇ©‚°¸B¢È¼““X„ ‰Åè`ø³I$‹F2’ò¹J EsUËNâ[h¼\’§ ˆ›(Ôƒ“Ç< °<5¤õL´’”r½w2•'{—FÊF¿GSQÆ=ö&2‹; ë#MKe¡;™@ÙŠˆõ{T|}ªµ[(]d D5(—òä—Œˆ³EÉÊ¥KUGå3[]½B†{+xkgÅnËâÌïÕfK9š°3F|« Ú””f "fàƒÏ±ï‘Æ>A!€Ÿw°a"£R$͉’‰²I™m›®023º¸ÀŒÓ’ÛHÓ9èK'iAfÄ"<θ*Ø:‡R°áëÚ$ŠÊOô@o#á—€#'š(ü§ƒê#×%P[¬¯òemÓbÈj"vQLZ6ùl옞,²:JBå:Û)D½ý[·ìaT_Jޱ€:Ú¾Ðz¥5’H â¨*‹}ŒÔÙ«/LdÁÃF÷X²/ + ïŒO#F«K··¦lIvͯŒU©F££[%<2Âd]¥‹QKI lxÖg#@i =C”L:ï¼ß3»VtRãÙâMXiÕ¼¶RW$WNöáª}ªôÉRãq­™Úd¼yE±(v˜n¢×á0Ï‹ /_¡9Î)ßodê…Ž€¼E`¢$–<x]SNÖw“¤øÕ‚H¬']ïeóÔТ׃Ãò5ev¶î`&ä´Ò{(ë¡-"Ä«N›•Ê잦?ÚÝëKÎeè£;Ds—J ¼ò2i8¶ø«>Uu2|vPÚ¸<·çG€¶µÖÖ ›G†è³K‚ù‘ÙID´–’‘†òmc o%MPG¥p_y#³¬Y-i 8Qa÷¿’ÁUWeLI•©Îz6-GD‹tÜó¶{öu½G¶ãÖ¥¾T{`™yŸjMÖºÐyàQ—Ö¿KIVÌW<Ý£è™Ëó.ØŽzŽŸ9½T귆̨!n¶%rgk‘@<5ws/€ýxoS}ß¹–€/›dÐÊš_/‘¸|\ÓVV|W|¾ÚfÂ,fÒà ¨Á åN’[73nß©-Ÿ*—C‘ch|¸VÅb0ÉYuRüºŽÐ¤Znð¨Ê¬§áOR•»Æ¨G «Òf¿_·rCà—šfô»Çæ]ÈØœ—ž¬ÇÂÜ;‘1s–X­‰T[glZ›Œ†v!;ÞVœ‰ QÊ >4eü«‚%¦Èáš%kÉ ²%J?¶šÒ¦z›nÜÄ3¹+n4Ÿ´J˜Éñ&^W}¯ìóÔ}X †5Ÿ®üÄía/W~)“ÏO*ÜÅv[«2$Í~É’øBTç0Á‡Ö/ÞkFgâQ褣†ÇðÅ„äj ·j‚¿DxŽ"оgªá#Oà4J \¥¤Sx¶ È>I@Õ!ô:åfÉâÐŽtáÍ3Jì@%*]aô°ÀJİah°)Š‘!üà‰`ްR.­:Yj¨Z…ÊJ‡ÚèmäK&zãÁH¥‰2·mÖ{Æ™EÊ~ÏêáCNv‰em¬!,P´¬ †~b#®2IO‰¨ä2OŠ<ÂÒé®B,"ÇT” Þ½ì6ô Ý è*ºc®QíÔUˆ!evxBÌÉähãd\¤à¡çUkˆ'Çôâî„ÒKºÑP¼é,F,ÏÖ˜ëFÓ¯ªî¢Ìá¬yP— @ Wm YÆ‚¿†œ%všo‚úçZ#Š©Çì&,²å&xÙâ *#®âÈ— ÆÏ¯ú¶lš­NÈ•jH°08iâwo°–¨²uE+°º±OÖ’¦lÊ1D_mÌŒÍöïBBK4, cmþ®< Âxm (+ïz|éÄø´i.[p»Š2ý ! Í‹lÛÕaøêfûÎl¶«B8~ÏPÏáüŽB,QëìÓÊàiˆÔVpŒ?Å"û"À‚¦M!¢Ð¥*4D³NþôÈælâ&:ꉥºl«¼H1Êrm\”P¬‘BT…ù É*Nl[-ÍNK¼Ø¯Àî(ZLTw‚ÚÉ.ƒg2Ýñ¾êÊ wO&I޳ë măzû²˜è† £d’²—odxqnd&Ì‘³2EfôNÎé.üÊds({Îäž°ð °’¦"ùOƒ'ó´l®QØöLdÒ î0öpGI.Éãi%’53Mü½-fˆjò>/©îêØ¦Ü‡ì´röÙøê3:†jÜ*  ()ò/¶MîÓˆÃr Á¹.³¾q-¶w'2PDÒÄÕ§°ÕÊÈñ¾†Dþ/%%ñ›PHJŠjç®™‚¤jvSnŸçßkRâKwì¢k. ñ“G)‹w-„äN*k-ü±J 0 0A„±$ʶ©MÂölæ,e$ÊŽü¥Kï¾sã^dÊ$Q¯må»ÐIÊž†ª÷ÂLŸÎ¯D$$Ñ­B"èÀ•rGBQlÏ{4ÉŒÔHŒ*öÑü”H¶T)Tmâ«· ïj´“観‡J†v±f>HÌGô½‰@вIn¿+žg…+CòYÈ*©‚NeX8 A6±vLʉGnú¤E+ÒÖPî´ŒLo (’ò42OùHÀýmüéhÕOö&(()âbàom%„¨Ë2F4ëÙqIJе,ï:Áöˆ†Qòð¬æLÿ4¹Q#å—.)ï&¯9GÐR{÷"™æZKÒ'¢}&ï¢(§@dt¯FóüwŠa8‘$Oøí°æñ|A²‹òmWÃ(!¤°JÍüÜ~ü/,©PäïÂ|ÖÅK6Fý#¢[âVe0ëGê²@'T i')ääOeô­AÑ¡£ãíÒ)ç¶5 ‹V‚?1îÊÐaôbjõ4 dtDA•’èädÉx'È$ÃdZIŽ6OöoâÈw16´0…‰Ö”“¨(í8êF>/ø&+ŠGKwXVVÜÈš2¦"ÈÅ¥hqKYÎ…Vb®VÕ–í¨ýõØÖÁÏ‚1î{)±©S‹âR¦*%ë†rf²ƒQ… µiëb†I<µS3sbÃOu€®Fº§íó^ÜÎZž”Æem-ÓDÉI싉mL#â63\0œµø– þ©Fö¨ÉA˜NPX¬Ž¹6ñK§¶÷ç&›CrtN0)c.S› !üxvŒBæÆxþ£$ÜÉ%H0S[b&w mk\lÅðˈ6 ýVµ$gnFÂã )íÐ3/ø˜¢iãŽv´íkSkLHûwñ˜iÂ6vð†úåo œª¼ïF,“~ªoxÓ5#•Ø+Ý#+lIIÅX¨)ƒe&åQlqBd7hi•$Ûܽ´ã{qRuR!ëœòúc^­7?_ãÞµIGSœ ƒi´'ËqnYpOtYË%13I ¶’ÈL(À½óÒq7¸†kÙCò í‹Zª; Õ¸gX5êødu:O’"2ŽÒq KRuÚ#’Œ*èdƒfê~˜U$âÀÞ³jƒfÉ3_ÞÉ$áP´oÑ=£DÁ²œÍöWoã!úÐö*ðPœ¥Lf¤Ë@WuÐÐ¥²a~sò¼rþ×õÒwHñg&#áå­¾uHÔÐ+(?ÍN r|””9GjË%> N?w1ÛÎ’òsÖoTã({wxñ"ƒpú”×Ȭ“£Tמ%pÉæltEƒ²K‚ƒuŽš°î|»Ž óºî¸/%A3Î_î̹E…zsö2ê×v¦íê[ÏŒ¶lvÊ ›göψµB*”ƒf…Nj,Æ"“Um9{J–JFB´sµ·¬(©!ᵞeñ#khƒóL¢”î§„B^xiA8y4øñAÿSÓ ±±^S>¨2Y·ˆY°•rA›‹O3Îâ†M%3OÀŽVëP+ÆÚ!ð˜§DêØä'C 77&g‚&ìøÐT´ˆûG"}: 19·$(±–(¦lùáîТC1qE%BV# xÏEtÖÞ®‰EV$tžì‘¿AeJƒu°Ãl’Ø` Ê9*ê2ãghËjŒžëðÍtmyWšO‹4½ƒ®Ûh1¬%\ÏFÒRË` …= J4y¦‰ª ¯ÉÚ¶/)CÇUxiRZÇõJe0QÏ7Z¤‰¨¨–»«ÊáBì1a‚ &êÂlϱ×d”2©ª³#šKB?*(À‚Šý´WŽ`³YJö'xÐUô‡!Dø5„$7á›ûƒ6` ’öè¾3w˜þ±T>Aä­QŠX^Зi_ ³°’ ïßÔ!:&÷§2ºr8VmFÑ”\šIÐUžÄš©Cs/dY³šªTÑ|aö›Vjþ„D®'%,œéiŒùQ”ðÚð{wFêȯt˜Öñ¢î³Á°¢9%2›o^…*[Pês3%‚‘Í«wf«ÏšÏ?.%o3?¢Êˆ†™¤9Õƒ¯*¢7/Et8òFJֳÓ±‚‹Þòù?¸BÀ[§Dîïe §‡U¸µà ´Î]˜éÚb3fy¾¥2ó_´Š JØNÉûÐde#‹È$&t6|ø8ÿR+N24Ëé±8)E¿¸+—y‡í¨ÎM‰­üåxrvp–_Ím‰*üÔyMB[c2·Z0ÎÂàzøôu‹ ë§²W B-¶ÓeºAëStâViI‡áðœaòà ¹“‘v$<îþo|«¯™ñb!ýav‘V:c8×0öóYw_)›ž_td*èåÉüäãšW:æ…°sЩôXcnMØ®ž©WÛ´§õ¾Ï‚ŽI‡iÄøWFˆŒÜÔ´JˆÍP´ d5h1á±Þ%ËcK²Ë:~èÌðue¶…¿0ï2÷QN7áA6¨”•±en­¾•Ðàü i+É\T4efåuû¯,°›Œî6:*ö7|I3° P··è¹QÑ æB­ÀZÊ" ªGŒ·ŠÊÎ*¯©&Eᣥ¨6ƒ®>y>YŸ…«ð,‡©€+GJ(rŒk×’m ÄrþVò~Uozzø.ã,"¯ae–b5‘}™@*Ó“q&‘N¢Ãk¿J %Ux晆umÝÂ&xuörw ‡IYк ½ýAm²ÛDZ_ h¿®oʘ¢ã3õm·cêCrç4ã±CGñ{”eäú¥F&RR5ß…©[‚Zˆt*ZzŒ¢8¼±Âvïî‚}Õ.*üÕˆÀÍkî!øÐõ}³tâ̘ëÙ³Ÿ`ÖÛ¯gy¼ 1ÎýçvV=g ø§óGtÆêð”HSEòkø“Î9rMZ,ÀöÔ ÍAó¹6Y•$#SCn&zg`‹eØIa Çÿ”ÀB)ù8)eáòA]è,C ³8V@D (þþƒ>¡ ý‡bh”ü‹BŸ‘˜° ß±°Ž7ˆd±h¤œ -ŽÉáQØËò7 ¾'gÌì=¾e I|BgJâ¹n}H!R *O”€(1è$Î) ›E+Oút*(³Ißv™=^O0IìX5^A Õ`•{dB†˜Ø`¨Tn;u‚[€XL 7H¶Þñºtœ•´¾ã²0^ƒšµÅ²ó9¶k Íeóà ¶")WÁŰÏú¥gg±ñºŒ:)A™ÉìÀxìRâÿàÎh† áñÜÀ;3$ØiºÑÊ×*ýÍí?ø¼÷õC™ŠÝïMZ-6‘H÷oÙöO Ê‚"–>ö“¨È£~ˆ3IN§802™¨)z±ÌxÔB(ƒ¨­7 ݤ *ÎǶpÊääÌ>g3$$Z#blO»†j­È·vÜÓJsqHæ¹w€ò)—-)°òúˆ#dEä$æø.ü l0QÍ‘&!âOÓ©§-Lü*àËŒAF2ú)é”B¾sȉÙ6Çpš[Y¤e³±"„ŸÈC<$ý=·önê C”hmÙT¤ÓˆÀÇâµ(Í­ÊT(cÏávHýɤÈV>Ó3ý"ÍàÎ’2ÐZ^*9LîR(¸·öZbD‰f¸èM#ŸH8%8â·¨ªGŽ“lt-|±TFèÕê¶väep4Ð p_sQ6&"P˜âlše,pR2Õ¹ÈòÍj› ©Ê9•Bëé)ŒPî5gÆFc«7C„]váP‘ip¥=Uü»ÀN>êé¯A‰PUÛÒ+ŽsZF¬ˆŒË–ËÅPä´È'¸Ìè¹y p,sÍùN²´~©rò‘ãÉŒ-JÈÚ§U¬ƒ|Œ ,s?¤A$—.µ:Â_Äá¤0Ë”g%Î6BnÍêª'ˆFau 2äQp¤¼·Šý ÏØ½?ñþÈ” ˆä1áÁYŠvc²¶}Š-UºÙôÖÞMMð…ÙÕQùǺ1ÐLÑYà[9ˆ>å:”µ'! ,”"Ž$èäFUš{\ðT+U|LÔÓŒìÄåÙ à×°•´‰#%; ë2DýB¶Y ;&š­å/¶ ôHäíTŠ=ÕG(é!;Z}䥯™Mæ}wqGšcV‘3Z‰W§ÊÆ¡k$E\¥!Ö:U­k*$|€”Åõ½Pbggæ=ˬ1‚›4ÒÛ‡â Vnê–ks-™½>#¯]à(:RÂßdÑíÌÃQõO¤;'”õ=NÃ#¡ç g|½ÌÖå,ªº{d1'Å’~Q‘ݯm…„é]K¸ZY|´˜´¯RFSHC*<Ñ ™ÎC*jH öÇúxlí*Y}„ö–ÕGóSášh•NÓ7<Œœx·åi⢠Lü‰Kr×jµ˜ò48þÄÏñÙ@#R±fáíZ„¥ÛJƒ¤„"6 Pqe6–™+;5¼'ÆH¶õu#8Â$K+ÉU}HDjä’ß6³£};%2|즜?eœÕaz€ìÈ< Ê ¼ô²ðFÊ´‡sÀ«ÄvTÝ|„òƒ¨U©9Ëô$~R²R¨y‚ÄÊL32‚ÓA÷ºY~uÕ jª:E„Éb|É@ÒŸ:ÆÐÅ#H,E¸ynqÞçmç´z+G™Áu–N5”-9ÌÏr†BB+TÍ9”0øÖº“5ö….CB£EaÐ0F JcŠýrÃG×íi×*¤ÒlI¶junùª5¨÷kõ´…#3~1¨s‹Ëm€Â–•Õ½3Û\ÝÄCu¯¸ò¢Nƒ™V¦Ç3Üx=®¶æÍØUïÚÓ®ïÇñÁE´bUêVQšñó5·'‹dŒ}³É*(4Öw#“SX4UT™ç<Ô÷A²»Õ¾tÙFÀ1Ñßz¬:«$ýeÏ­Öoç÷‡{"“¿eMc–xYœ«²MŒ™¢“H‰â¡K nvR?ìšUSÁE°úá²"Û¤šÐõvåQ7QÚöjÍt"ܬÓxž¹Ë€”‡¯, ‡krŠ¥*pP¯×²drœ}esmäemÏd\8î∢Ù6:ÉÌñGQ@.Jd*”`÷NHôô†‡dî™ÅšòÌßçK¤X˜õë=TPgˆÌ¨Ž¯¡¢¼eÇØÊê!ú®’g:Ïns]V ÂÄ ö›È;k×Ñ#$îç›ð 7‰Pü ô·ÔÈ1žÃp *"‚ô}¶Za<Ѷ4QÙ2Ë©’yA¯QR7+5‹ ,¼Œ³²ö;¹Ò5ÐÔ´ñ¬SÛ³B°•‰†›šŸ `‰áA©ê3i:‘k6‘Ê£ë_•‰E5Ò×3û ÑÇ‹Ó5’c}2i” ñ¶6 }¨_A`‡r,¶ú¯r*.•Û̌ј Ûî#‘A"¯)Í?:ð‰´$;à‹ZG±3Ã(’¼€Ã±ª>'Iõ,ˆï$²´Y›”ÑKª=Énb~¶iØ'Ù›ä"CI‰p"‹]ìûáv#à Ì2ªW48 3É.PÕa—+ãü5p‘µH„-º£À,DRМt5<¼3·[xÃé[ §%Z]‰™þ>ÃÊ/l (âT˜ ÂB0>Ãé`‚0e0Jô#Q׎#­dh+•:³O‘Ѿáw>ÉRK SY.‰ü4‘ »)”8x}ºÚ¨:7ªù­zé.±ä YË­"c)ų…(Šþä?7Z9ÂeGÈ~ 1ïR‰ÚP±ˆ¶ÀsއȯAã ™é<ê¢28Ksà§/8ï<2¤”CQþ-{Òа|{ˆsóˆØûµÇ3È«®J¨¨Ñn<ëŠ ¹]G)³¬X†-ÉE8ÁÙÄ£14¤„T¼ óšæªI …¬u/h§ä9;´­ ´¢w¬dj(œ­ ÇÂ\¬›‡a¼HÜ–˜È“ØÉÃ_G0„?êe,d­º_@ ZŽÚj'Æįà«;üE‚’*\75$_’b!Ð ²%а(*q5;§«(„ËÐ"°9Á¹ÊLW3æK“Ö´,oêüLॠ´2'=DéG↠s(b=ž«÷C´î;xD#F0»äÊêS.ÉËˈtî ƒEKÌ%R³š_®dÒ?´Ò¹ŒÁ/²Ý£{º¿‰_A+ÊùÊœñŪmÀä§§ã¤-I_K4”ú+KyÜÍ9T&ϰ}Q@G؉,ªÙ/«ÀäA0ˆ)iMhÀ%ܳhó!:¼R… ¤ÚùÔl?1öPýKºÛ8Û…"€‚,cš.-/C¸ÀÁN>â·':ñšŠ×Ñ¢÷Kê#$y¼–ÄK²UD*;<ÈÊ«.¡«E}Ú™«Œ'GE0Ã+S„•»ËÑëìSüÿ4,ª À–•¬Ä½Â´ÆÌ¶Ë¿ ì ÃEVà‚ReNZö'úeN¢ÌâØû¦#Uà–¿TCÂJU…@88š°tv¥Z –e"Éž)ý¤*‡ü$T …È2ú3kCóü0L”N,È@ E$œðLÙÄ4å‰%]W6ç­}!­Ëv›ÓÕˆdq¥=-Œá‹LzRõ±I°@ø¶Å(‡)m*ÆÊ,¢˜’ŠOKa 'ªà‡ê–®&<”™0ÌÈÃ58ò°Nìqµíš/k¦”õÆúI%eÔÐþ¬dÚ=Hâ="ù­Ì•T+%ÄÜ<ÍqÑÑ „`‰Âû¬e£ „ì®ä:Õ«ÚºPѱ0dW9ëˆ'ûž©'’¼‡Eq«PóÍ p£;Tû ¢Õ¯£r¯›!Z©JHü„Ls‹Vº’MëbI5rS®*p Ñø~B¥ˆÄFÀÚâl QÐ4?1¹ÝÊ$YcJ’zÐv½‘«@Õ `ʇ•æ<µåC2@˜þ¬‚.ݵ©p‡ÅìÑ”… ÙšÁ¼’)ã=7k¥œ¤–åOíÃ=©å¿º%¢q П͚6N¾‹JùÆ@~Çc]RëÍ–<ü)ôÑÒ=<ÓP7(î9°è+š¸¸J$5¼ï+“ÅkÌŽ èÓó׌WSœõ‰Üî³ ÚÑÜ/ÛU'¡C=_EE¶(ñ-œÌw®˜ˆ[ÉÑ)ɺŠ`sá­Ú½âµ\`|»ÚbÓ¨« Ú+===bT-=$Ú5˜4,‘ ]²ù¸¹V"»½†_u¥€E¹‡Âp!IÜÂ%ý×óY@€~0œìQÇô¡ J5;µ,Ã"*Cðñ=RÕª]yC©»Ë«äÃóšÑËD%.XàW4É ª¾^¯¢ñ1ñ²^=/Øè£Î‚†NéX´­#`¤¹Ÿ=,¶½0áµ-U#ª¸Ë:¼Ãv£Üˆ1ËÌCË9msÊ[¢CELãcQ<÷ÐÁ™ã3Œu’FJ7Ãu%¼á5„±mÏ,Wa`£ èÍ|pW›Šx‡  ¼ªìZ• cívZ½cNLPÀW\U¸æ<»Þ‰³š°ø·Z¯-ÉcÄ-o`š×¥‚ü—4Ê’½šeV,ˆêXRZ+óÈ®PÝQ&^è|ÓM‘£zˆá£vµù‹5WL¡=ÏPžŽBAÒª,d•™šå¤mZ,cü?’|ÊDè‰B›”ž}h$Òö€ʢʮ¤•3eJ†’ÛC´A±™ÅP¢4²°Ï#…ˆt²a¥ßÉJ¥Bƒ)"Óõ®ãaA݃&H`…ÁãµÒ²†bèû˜.•Ѽ5ã‘•$yâmV«–tPP“€ÊÓš‘V6¥Î£”ºÒõ¬«E¬nÕ¼µºÚ]®–x? ŽÔ–Â>ª[ØSƇÞa;˘3eH ¼ÒP9M{¦[×ÚöߢqÜ%kζC{àzb/4Whà¸d¥ ºß™=¶´!ŽòÀ “Ä á+FÓbAÓ„k/¢JV›ú³¦6ª¾˜æÞľ¹›ÀÈ*$lž@™¨•\¾/ൢFÌ¿ë"¯Í•€;£}7¨ËÝtŽâjA¹«¨äIvà«=Y[,5TµŒK>š'dÝ;uÆ[¹jl¦ª;väêèP$Sàc#ÙP—nº~Y|pxÊ.™Ûd›˜¦“Á&uî@’ªðâ‘‹¼ºÖ÷jÖðA‹O7Ç„¶€-DIÓJ·ÊqFkd;-Î)!dŒ¼$1⧬Àì¢ʆ#9 ÈœÍêî;G ÚŸOÅù=ð³oi”s¤ÜAû‰ž„Žöi•"ƒ©ä4y¶ B!´.Òåò…Üü -²4Ŧ ˼%:ðCú°!•Œr¿#/×ï ê°/¾ýZv?_|¦lí‚âBëúA±#')c·©N#Û,Æ$锚NBdH'âsÚ+YBæJS:™È]á WÌøƒ8œ §QÁåótÄ;’”åÏÌ{—ý²pqÉ­5ÃúÑŸRéOCbžæš Ôg^ÅuÔÉ«WböCuµÀUÏPTöâi{ò\ÐëÆŠÁéß :®)%ýGa=ÓÁ:$fËñ5†©ímC†¿CPñ(Ž…+g@9%hØ„Nï"Q½±à´M)ótN›qhw$äLíöLb­ÅÃ|WgèÊ•”èFÌõaÙc¼‘¼qä–ks-q|?ê4}Ÿ_r\/ó~±^ûÔ]¨Ë¾“p•[ÚŒå ÓÓd`•K³£*·RÁ,‰é¶Yä:Ü]”GJã/”W•¦dœÃÃváŽÜ#<Á“ú¢´5P}OÅßu³h‡Â$Bk]/šGÃ…-G%%SêT¼-AâP¨ím «Ñà?Šû­Pá­j`iä¾93Ñ¢QÉÔr¥C£M»D~Q:=íѨ- ¹{]eqÈ,j9°Ä-Q(ÆŸÏ*õ˜’!\•Õ`µÈÄ~5§KpOü®^˜ËÊ'ÚÜÏ)„Æ!øEr9‰5ÕYäbõH‡Xð` œ*Q„N§Zh=ýýx‚kXýyýÍζ8-Ü*÷ Ûó!Ýj]”ØHg› XÅ9˜Úæ/E^?:”fåú¼«W·=øÙô†Ž„Bj›Ö˜ ©CüÒ5p"4’³þí¶ñí2èKr—¿iäÀ?ë‹i,ÁL¬VËÊgûµ·P¬àˆMOó€iÕ}Ë“ ~ÕÂЈ”üIè“…¶ëº’^Œ+‰Ô÷°ðÅ5JÖ*$ÊÐ’c€-6·–S‡*¶ï|…fÔʯ7O©ŒZÌUªäj¥Ã?ÛZyZ®è‚®Ž%h •ª(”uÊ*[¥(ôX3˜ Ë/ >áÐbP¯“üm#Ó*¤©ÀWÔ8¥lƒ7ÁH-ð‚%y%þÖÑSIL¸r$‚¹ÑB&Š+’hŽ\ªâ `¡Ž2TŠfIŠ´ˆÙ¨sDÞªŒ7ècO£¨ôŽ‹'“Ò<¼¡Lý~7*½3‘Wø ƒ×™ÍÇ[WÌ üб6QdŸ·˜­WN6ŠZ[¦¶»Nžîƒ§›²x”%ëf:"Îÿ£I]¥¢È;ÑT&s[(ÄДW¶Ü@—€ôLÌ'º> HÒNúI‡(B«ÀW[“ˆ«šîW©'ˆÿdð³K6¶‚Zçï©K~ÚÅYÞ _ ãñÎã„é›:é]ð¹¤FngÒAˆø™EÉÂî&ÑLêJ5­„ÄD‰ ar ÕžVOA$4 c×y$ÊXE5€Š6È’?¡û*o-.WæœLcT<3d`ºjLT㓚T$éÂ*ÙµBÀ‡\‹v¨¢Wòÿ€w‰¯ÞÌEࡉ­m*…Í[› "f]Ê!ι=’yGõË)hPÃêUÓ,M²JZ*¤b%ék”Íêœi™y$ÝSGÖ¶Õ¢TâlS†涨’8wˆtÁ!ÍŽ»5sÊšŽ *c¥ÆÏZ*I z¥ C&X”b™ŸT9ß"ZtÅJ#é)Ö°èƒ5%&tÊWÓH½<ÌÛ&om­š¿íâo[•YÔ151 ‰[ªtÇ)ÁD‡)i•Õ å "‚°¡K} §»Wj‘žõm– ðºdÊ»ž# ó8‹6Û¼—y$Ãj29ú—“¡—Ê·® >÷'nHûž¯.lYÖqw§Í̲åK¤[-À#OºÉâ‰d 3±³Jî<<ÊÌìCò\@¯Ë5váµ”),=Où!«GaDé|ãXØ®œ'ðЮéUþNT<„îuÔ_ê5‚Ø6>È,vi+ Übl¨MvqèÃ$B£Ý]Ù’¨ó°ë³U8"ErØàáþò¬š‘ŠhTLBqœçPaüÐ.Õ)½ºR€6 OÈ  ø„!O˜cúˆ¢Q7´V ÆaÏàv ÈcïÙ$ù!eQÐ~'$~ÆfOùD²a |Äãò蔚øPe@YDâ‡5ŽÊ&*D°¡Æâoª¤ð?VjQ*È›2Ë&O»$š/ K#vGÜÊaC‰Äãw8u lµC¨wk’òþ¶J.Ô9”š72‰Ìã4Útv™(Ë"xÌtj2–Pë±9Ųí“J#öíÚar‡bqy Âaª>­7®Ö/KŒ×t€ ^3J"| `‰‘àe_ö,V¢9Iäpd1»äf2»p-™Ž€7æLã|^Je±Çù8xÜDJQ&îKbø%¾U‚ Û#z=óþ.µ¬X¡¦ B¡§û>‡6+C@‚+©2¬º9êrì¥$‹ù ÉCâ–< &º=., ‚7h¼<ß¹N+廯‹ŠðÆNŠ^’ ŠLÕîrtˆ& ØÞŸÍrH»"èüV¤Ëbâ‰?h‚Ü’IqC%\Š’0èË&Ö<2³[#¨/ Dˆ$É3’îÂ4Ó"î²&°î§sBý!ËDŸ!±Q¤XGŽÂƒ"ôJ†‹¤ÍŠìêŸí:%8Qà#Ñ/J ¢>–#ò™úÉ<ìÔŽÇéC>É””Çh•W1¦-ʲ”IÔ̶~ÌàX“.Éø_ÌI’q(€røC‰´6€03 ‰Ô`Ðí@5´_1S¨Ë^ˆ6(ú.ت+¤Í7C²»Ü½ @V“¤å] •zšÎ¬l™Aeà ¢kbaÕñ{v¤Ê턆-‹] ÂH‚íÏ+b†ŠžÀ^-"c Xç]§Úí‚ ‰’.–bˆš/;©ÔòM¤4­’îÐTŒp“¤H…9<Ø,T….Ÿõ|Œ~ã—B3(9`ê(9\¸‡¢/5Æ«øÖ@~* U)9ŸjêqHpÔà•qrEÚä’Ëd«wÇ~)óϯTÂEÇR?‰ûf‚š‰"qøÛ[ó°\ÂÉSæâáJDT©}­hGšlÐ^39R€¥º×jÅ«–ÊB®\#¶ÑÿéÏ*Àt<5 ›¤ˆašel˜w­´ªò(EKC?8²F‰ÑúR X+XFÁÉòþÏŒf¼ô!A¢ú;GY!t¥•M¥>Ì1Å:`iéšQ•‘& 1éT¤|Ÿ³uŠ­ q{¾¦œ”4ž]d|¤öì%¬O9T{›äuìÊ8Z?`1(‘À ‹àzBÍä§–è¢hçKm€ÖnMà‹ Ïízoèµr`Ë£€ŽídUšpS¨hþXÌ¡h®•^xq¶VŽ…e­ÒÚíl¼Ã“Ïyu©U§)•hó‘\á @zZšZ>7TGÑû-ËeÉbØ~9”ýHk%ýÍ®#ú·ÕõÒˆeTÈ5tiú?j•³6ó¾lGw%«ŠH Æp†kS4VF¾ÙšÖ7 ‘˜NlKeWµ®/SP©Ñ«Ô>ç¡,Ô©ûiʤe+6À“a›»|¨NÚŒªZÔ™räõ˜Þ±¬EU œ.ëÑÛMµDÀB›,×ZlÄU%ñ}@Tg¶|h¡ý˜±‰–”` "Ä#ô®;Àk‰ˆù@ûhØQ&_0¿À&Øçv›¼¯WÝ[™Ç2zÞäæž|€òЊY)Yó¡»mä:gRPŠŽ9ë]nK­Zð4î” ýciši¢SýÓ#»Ú¥¾íq8-&·Fšì^Ý’¦_?Ð[ nÌ WÛ¾pØ®îcãš­—_>™n%uéû˜I ’žOŽé0 em‰Êcóp‘.³#QdØ/¹ÎåqÖQŽ-“ß¾ñËqáÀx…vayÚê멦<9Œ«jcãxaµh}–Šhýma±Dn/hSb¢æ²m‹ky³3¿%RÜfBýkbçXù:š¤fÅZ<„¡€ü@RBæŸ'–ŠÌ+±¼ªZc^–5ÖEQgZm ¦ãÒí‡$¦%ƒbj  yƒ€ÿŲ…l±¥¨er½êtšÍ ¸¯®¢Œ©%,*„Bƒ ¨¢ øLP@ŠÎ¤b¨YˆœnG‚OåœEçÒ++@u²;o®«P¬"/¢Ð£gDoõŒà˜fÚ äþX¬w ȳ†ÜIênDÉÞCm"D]"6—bv]0Œl鬹ä–nf²+/šè¸ºDY æý¦\XÏpÔÍ¢,Œ¶ìiÞHHd«˜ÌjüqÃâhÊÎþôŸ0ÀǶ&p%M¨'â¢ê>Åѯ‚ô+H;¢'-É©ÄhƦ…0E-w­¼ÊŽ>føGÌðB¥°ÅjôÀìîì*¨œ2YÂþÕQ>Ç®‚ì/Ø—˜àØÀ.tûÍj÷±@ç²ê©¼jÎö憘Ún*蕨XÎF çY|,…Ãã`*©M†yíLaEðób†rLJ½K™q’®±CkV·Êª§IHŽìÜ’HïÈFq1Þ²b$éHDIe¢ÈÈößÂ$À «¼†ï0ýÌ$(¢*Ïx¾‹â»)×m„]f¸Ï+àhNxƒ%F(äâ6-> Ñ -šØÊÂ%¹%oûÉ')L Ãb'âöÝ'šŽÐ¬êŽï**Í«d§l9ƒ¢YÀ(®žqpâšÎÐIçì~ì&Ho%ÈÿÛbTå‰^q ¿)pêOÚ*Ò¢V@ Ó"~#b.<â¨íN‘#¢ˆ¢G.Ñ,÷+дà.ÚǦ¨žäüq #-„g†®þè\%I<ânêj¿.‡ÆëjtÈȯ¡ôCbí(@Ÿï8/Ï\r¦Ä' Æüê~ëGbgR1KËÊ2…&®&BПgâ1DÖà[òÖ hRHR’§‡D£¯ºGŒ?É;/)Æ”…B›¬6x1¢;±Þ÷ã0س¢êàå‰Mƒò–ÎÀøbÂn!h++$ ˆà´¢TžóRõÑÐqŒK+Ì÷._!ó5‚‚ÊÇ.R2€ÓÑ6ÐÄ(û¦âÏâ SÇâÔδ•##oæ .a20|'ЕNÙ%©Å.s™'Aù!¹n'ìŒHˆ÷ŰâjsЭnºæS Ž1¶«î67lŠóIf­&K®¶Ò%‰ò¶ 'ŠàCÂZj?î¼ÁH£Xý'8¦¦8¨ÂáìÅOÐqÒÀ§³J'âP†ëFêòHª1¬|ênÌ¢ClÒuîÂ8¨àré¤$*èÓ,lhÏÎC…Ä™ï1®H¤.Þî£ =EB3 4°x¥*_ÑŽfÄü¢2b·/Šö£óå&³$-Y4r€¼MFVìüNOl6$’g.j.ʤ•JhtD7A¡ö‹… ]#Ò$ÊÎÆ4¦æó*Â*Ì8ø‚ºduBmGÎñŠ??óž5–D†4LH,X…€nédÊ#ŠŸ-j6/&’ü–è¸`ùhì,^ø/K !Âq޾~Wp“Ñ’¸I„˜w+›Um(RÆ r¼R{è hψp–.$:ºÑ¾“)Ÿ©•»¤É°”:+’øF×Ö˜p€¬yõnòŠ®XØU­"‘*ÆÈ¹øpm/ 4Qçy;ÁÕ)ÂöĵXœ#i+0âU¾ÎÃõdeÏ|jKâ¬lˆ!6 2( i…™¬¢±·ìÍ Ù8jƒ`Cɱ€À6¤Á!÷“S&c”ÚQÄš:äôS©Ö2ã´m?Y…QI†¹óˆï¼‚w¬ š›˜ecêvù#œYÌw6*@Ù©ËäþªJƬv\ŽÓÜ™è÷\à¤í8ûT^+²Îî\[3¾; 27ǯtÁE…bÁMÁBðZ‘yÎ=©–•úŽè¬ØV óqÍ Ôm5%"·â7v×”}8~÷aI¶3ÒßfíŒö-–úèUØÈT„PI¬×ª¤tQr©P¤#<2rE×Ð DIji‡H É¥œ‹øZ”®×ãXY‚l#YÒªe^aLÆYÄ„ñ•µm5 _%µ’œƒãŒŽE4©oÌ¿m°ú,š×Š¡øÓ0r­qPzBõœ~3„§†!Š18mjn;È×<YOf4ù3#7GE½î|í Ûúæ§‹Š¦”›Ö•Œy¹Òéd#q®êëÀ-1ÜëbªyÑ–þ&o©§Ð |[Py^݃ÒÉ5éi+äÇ«×z‚Äâ˜ÒÂ*hSÕ-·»ÆWG[€n0#c˜‰œTÑíI(˜«î8{|ž"J×k‘7èÖEÞ/Mæ˜e3ÂBë‹§ÝC-Ú!Õ¼Ù¹q˜•ÒµõÆ¥.qÚ¾í:Ši"Ñk’§ae„Ç)oã5a™4m¨¿E„†ú¡v&Åçt5< ÃÓº MuS(ÒöÅ¢ùœ·íGdlùûɪ%9jÃâXœêÃXm¨+âÜç‰B®äéPê³ï¶ìO<ÄBŒS«×wµýØ·7¥mö‘ã.¿žnršñ_NYÜšr—–x6ךº‡gøØÝšEâÖÐ ø ?à°˜$bèD*…Bbn þA@²;òH“>¥`öY!É’èÌyý(}'°U0–?eÏz‰8£t˜,þA!¤¾çTh,fG$šAã5˜Œ.:ŒÏæ•êØi©A)öpfaSˆOd–¨l3n¬Í™U §ÏåÒ¨ìzuƒN óª|ªë˜cl‘éU„÷•b WäªÃ¬D.v»u6‰KŸ:™Ö2!4­sà¥a|¿RuõH´^ 2ˆj_6iÅ– q¸Ð^3™4›jäÔùž7¬ÙGµôË¥tÿšqŸV&ÓA6Ð:ç—1å˜AÁ_Ðç‰÷xÑœÕ.Y0=­#îˆ0®+¾5éS€À¤é@*§â2ó·‹²\ç£kâžè%icì#)Ò~ƒ¦Ž² {DérøÊ¥Ë’°@ÉrhŸ¶‰$§Nb×¢ì„=½h”)!4MƒÔ„¼ 2tð"é¢Ú‚,@ Òœ0ÈÊøŸ½è{@*òÈ•D¬rJ“9ÉCÒʪ#¤ˆFiÂò|(γ\­.É‚]ŸÏáúOlâ>í®èô®’?NŠ’šA`B–;³ÊùÓtÀ%Êh Ê¥Iû§a.!Œ2\ÿ#zŠLŸÃ*K.¯éfõ¡Lù‘µÁ'ñ¶™–§zXàWíK;ŠÖø~ÒJzø£aW9ø›/ˆÌl›)étÜôiû²¨Ñ9í;%“ÏV~η~§œD“¨eàÁÚlz!¬8ˆ‰º{–Hô Z§W–ªñ"O$Í2Xú‰²ó÷ú³¿&BŒ÷p‹ÑGì&öÎ 3Ûd$–$¾ØÞXc³Ž»…›Qï$„½¯•ïÔª ãÛb¥oÊiŸ3Âì1xÊ}Œõ`€ž:¬fiݱç,N QOa&?³Ôº’žLJZ´6f_aV#ÆÅz(÷µÎû~"èŠ=22å܃ H(M¤C¬£[;<°ž"Áô†¶Øi¡<‡Ík-èÀ‘Œ#4¤¡—˜(³YÄí•­»QüåJ"+\D™”ˆ™ ÓI„yÆ·˜«²KÑüBTâ^#8xÌØ5!úwXS &‡#gÖ? ŠS!J=¼´úÛa’L(D±¨†VM¤Œ;¤D>ÈQœ"MÑÈÈ×vˆß£ÇŠÕ»ž‡£Ì È‚¥ùpx Z…k›³èK\à ªEô´BS+ãÛ¹$'§‘v(œVÄziE7%h ?côrN„‘k/B ˜s!— %ˆÂ4 ã«‘’Õ1%ù:–áj]^òí/¸³ÄOÚñ6ˆ‡’E€HzdX{ †‰=œM™–AÝs©Wä¨ÊçŽÏãĸlóžIGx“Ý£FA…*x“ ú„m½á«"D—X³íŠ£é¹Ÿ÷¡<‡ñ±‚”‚wÄ$qD€MFgÈ,_f¾N() y&O4¼‚¡p ¢ˆý6&†?…ÀjX¤Ãr%¬1É’¶xðl¥Q5ðRe3¾'‚6ÃóÚù 14ä…•V§Å[ó+]ÊX¡UÉb‘¡‹ê$‹h•&窛C¬!KHÖÍ:Tüä’ˆ‚ëj‰$CÉ=JJì S<‚#iKžš)M*Û0Ãê‘£ÕI@Ê:yùQd,8°M*f‘©}—Ž ZUCù"hc‘µ(‡‚Å:„Ó+†'ìÞÌÓ%2•˜ú‹LÍŠF‘þÝRý½‡ÔÅŸ4Ùh¬HªÚ¹uá¿É«¦Á–—jÄÈVK@»³Ô z¢;¥°¯I Xäe‘lÈaŽ/îíãP¢Bp8Ñ4žÞí²™Xãp›*à˜ ©ß%¸“ 6ãÒ#Š‚@I¬˜›5Sœ1 ¸Ô&êý›ó”@ãR¥[¤¦{«rƽrß¾•2;ÕFR"ä-Â1Œ2Óé¹ûXÁȽð}&¨B¤gT4–Ê>&ó ;üU¹ ö¨ «-zm™Ãz)±é©Ë³5XÆKÍÇ@̽é[“Êá‚!ôfˆÓÌ#‚F“))Á ù ¥˜“qàŠ|¾Ú™(‚–® 2( º2‚¶(?x˜>@¨Ãr59†¶q¶5›ºؾ (ß)“+˱¡î1ø‹ã£Š<™9øµ ¨‚½@›‰Áî‰zý­ Õ=°õÆ;Ä2r¸dƒÅSHK4ø3 ²JÑìŽê›|CZ;à­¨%ð ?ÊøÇ[TJÍ´VÚ/ùjœ<©·ZQ€9¤È‘ 5„C¥ãKLtžÓ 3­3t}¼zv¦ìŽL´É§2>r¢|˜ ͱԛ”{#r6ÜËXÉÂ!%Ç»3“¼(?!œëN¥áh“5AKT;y«{¯6"6:™%’\3UIP‰(©™É<ôØ<ù.Ä Ãº¤ÜáG‰Qëù9ĆÁ»x‘©@¼Å*Ø—¤ 0Ì00§šòSȹᗹá¼óD» ͸öÁ¬ „’‡Û{=ÔŽ»Ãå¾1È´€¤Êe)¬°½tŠ“ÊŒŒƒB“TG<ŸœÏ+vÏ©]¢3·Ã®&S˜ÂÜ»¹üæQri®&Ê.:‹Ïr 0sš¿8Âð7Ü1¨|›ú¾Äа#‘Ý´ðîÁB4óõ©Ì$›ìèÍLÅ q’#=†q01Š0CH½a™/À4x}©ÊžÆÌÀÇàŠ¾Ê°ÊËIl¢ÆȾˆö+̪J”ÎHÍ•¹Î+ !Œçsµ® – ì%ìö˜œ©:d-*¤K„(ɧ½K×?œx€ëÒ O¢å6?È46µDìOH»(EC‰PlUh‚‹á7#ADÕEe©É„-yý€18ãà2Ѳ¬äõÆ ª:i5±L©Jø°—z“0ƒ§àˆJÄ…(‚é¤z@LI!Oè¢;+(W×u£E:â®Gbœ®›Ó“،֓Ï<Ü´ß´T,ù |J@é‘6š©£ÑJÆèžÄÔâv¨ÄÊÆ*È‹WKÂ%ÏKfÛ#Œ4Û©Ñ”¾Fz?.«#¶k «A¾cÙH\Ë«xã$ùd*–Õ­P¥»—»'•¼49 z)²xˆeBº±™©°òK2\4=#Ü™AD±H±¿­ûU1CurרJ(*›‹S—É3Ž©‚J²" Pˆ}Õ“øš*âq#ôûÐMƒõ®Ä,˜ÅSÖ)à½Ùݘ±c¤äª¨Ó7L«-´•Rk̈‘Í®*UÓ¯MM){$AËÊÃyäuOÛ¿6K ¨p¡R[C{‘£ž1ZWE¸­h– µD~È I±@yÌ¿Ùg¤” ËMOôyV]A\ýÒ"±6‹Í` MNJ͈±ÉãÛÌë»®Å9ÈE“#òà êÉËdŽÂDVX`±›{ Œ1 ÃŒ¥½t½]¢\ZuQk¾¥b±.ò&£¡°(E)¸‚Ö$ Ì©ˆ‘c­¼–t¡Ž´ÐÉn4XIªdËR%¤ö;ŽT:T¡Dâ¿]Ãù{«¨É7_ÉDxT 㩆RR¬‡É3¼ü6MŒ1R£ðÈÄŠ¨„ºE¥SÃÊ7 ù¸©(8Å %Zç3]‘ …PÏ©ã„uIÓâ¢;ŸßzqW!!+ €úÛhB„MkVV‘eT¸}#ÿ¯5¯@å¾³9·®™‹NÜT´gÁ«à9Ùz7YMFz¡…X%+¾SŸZœÎã’E“؃î€Ä’ŠÍ»#¥¢;³Ø(8Ud(‚¨O„ ›{æ»Å½r>…',],“àœ8äÀ£&Ä…½¥F{Ç5 u^rGò™LHLˆª„ZÅSEí-V†Å¬´¡JcÇÙ¬Nüg‹åZ¸äÑûï «5Ø ÛЂ{3m‘ÑÎ.¬ÿºœ,©ÍPÃkàbHÀp~EÊ޶lSšWYc‹ä8ª†/¨‚•øzg½ ˜´*"í@ÒCrD›|NÂ!ygUÆUc9V;’"d äÅ錅'ôK‡Á²äÀîçÛå`ž1í¾T8áøï‹P «*(D|CÍå‹ÍþT‚,Ýãñ8ÅÑTü'$ª04«zŒU­ùa#dÈ<ÇÝv@Ñ ÁZ¨CÝö4B.¨µ5T¼z6Lp yj¸jÊ{<“´´Ö!±-sϵ)é;á ·Z—«]¦Södã¯Â%/ˆ‚æa?‰€à5¸Ùs˜¥-Î|ô¢#‡²Áå:¤‰¿a<õÆýuÉAœ'²•ÓÁ¬SFD¾Ь"E1bK%Õ OUqUå®’5Ó.‚Ik"ÉJÝ–3ó(#&ÓŠ·¶ºb°¤ä-ë¢Ý äBUÕ’ì3õÔÒþ  Š·Æ´“õÁ@5~í óJ.<Í-躙_ëmrÃèmåHÎýN‡û?¨ MW Û]‹d·ƒ•'ÖÜžP»ä’7¤Š²‹ÍgøÖ®iÜ©²ÓŸU•œYé¤y×.Ñû D2´½÷”«Éµå´;¨ÑX×þ㌰“E|‰¥–a6Ä¥ cþ°³O01…$Žó€9‚êY° ß²8òeæ@Γ6P³QÚKÌ£zîÜ¥€K’ƒÒ¦O ý 1rïB0žÎËq»ñK™lbP¹õ.>†'" ̪¥aò‹äâÐøv‹í.æK^$Ãàç8‘7ØZ(Ã#íº¢8®áqùɦPƒ•ü«qã&R»["ÙEÜÈM&'o­ÇQÔ塟$»jY íÙ¿íóª"$H£g¢æ×`dbRuÉÕƒ@aI€¬¨„s6O*'}Qß´ÅSö¼ÞYŒ9®¾ë„ôM–)}Q¥l!ežù®úŽÜ¸ÜËCÊ.¯+Š4;¥î4˜,.‹ÌÆÀ |8Ãj^YÝÎÛ7Ì¢«Ø¤í¹Ýª ‹Á­ŒÖh|‰Ñ«3äLn.ÍÍ #Œ.Ñ7]\zw!Š[H}©"ôeK¢„9 ēމ­¿ Ü6iÔ«æŽ{‡¡_¯ª²Ì¸•ºä-[Ò«L¶AcHºßÄ&,¼Ìïñ5ø¶@\ØÇ9([¤XœO×@Ò-ï¾´ôR÷‰€':ž}ÝåucU—CÂ?2ù’X]SoÕHRÖ¦æ)˜eÿ\˜m›ä|ñÞjqrZe“aÇ?K,=§;Ø4xZb›oÆ¡™?[†h^£Ì[;¬€Aöð`ÏÈV1L2ó –ø­4f÷ó™6Ö\e³ãu§)öä¿؈#$7šëÐ}·<áîÓÔ3@[å_{â­Ur4Ë·Y÷ö'Á’7eL0èjUèP­·B‰54OÌ>TB„á 0Ö& –Öî¤ Ó-:¼ä#¡y½ŠM|ž Í2o |;ªà¼ Í"/7w%£•,]8‚ Z ý¿Yò}4T‡O^}µìçO$y¾¼˜Þ»ù¢€Ú´ŠáþŠ U¯òº”Ýòvô Ý-R”<£÷‰PhòÄP}ÉR û‚@€ (@ ƒ?áÐ÷äEý†@€qx@ ‚>À±ð4†"üŽÅÀph4š2÷–FáÒ4Ž2šA¡p¸›úFýžGÀ¯ª.3 ŸM’9Þ•›B©  ôG@}J¡ÇìÎi#œÆc2:4© «W§3ˆëk[kŠP²Eéòk>áNK®tj¤fa{`(û ©O¯cb\ &Ž‚òÏŒÅb}9¹Ã¯Ò˜½ü¿g_ò‹í*Mx¥Ã³‹.—MÆ€¤sèξMÝç¡R86$XƒV'2iõb3ŒÎlð®lRož]dú›”;9ÔtÒi…s¤ÚÉt3H]'¡|ûAúì#Ôâ@€ÿx^¾}t¥{_-â.ç"i‚ ʲÈë’ž8®ª‡§Ïüý·Éºr£%‡»î¡èʰ¦ I˔ڡ*Sž›ÃÀ L†¡Ì"⌤Î3ÆÖ&êú"¬&\:Ú1®Ùþ¼» AüŒ»è¼6„D ㎻; 2*î¸iãù¡ 2ލmú#!Bm®êJ-Z/@ Ä`ºá$h|’£(è8®)ÊÄ (ͺ>ªA+{˜„H¨Ò/Ô•G«DJ2kgPr>à1J\‹š´»Þ4pÊ;¡ìˆÔJ¤Ê¡!“üœÆèT¬„S1Êçɳܨ‰Ã*¢ÀôKä¨ÕH‘Zy52 2ô¢4î H{¨~»ª"?^€òGLÃ’„&§®5©ý B©¤¸Bô¨;ưRðØgÔ®›·´:¡H¢/õ^ž£ð* o€‘£IdŸ÷Ô~¨Ó£Q'œû@Dзl¢ÒS½e4$Ñ%á] Ö óÌ¡é…; àˆ<Œ‰Ê3G86å ¸Ï-ÚùÂGú; Âòm…ßðCfåLJ)ò>š9h²äxN ~èˆ]¥&cmüÆ1ª~O ë4k;œ²x‚s5ÑͬÊÚÙ±ý?¬³©ô¨ÉÀŸªâÇýÃXa§ýë§"xâ ©*ž§Ã;æÍ#ö€ ŸîôÄ-²"˜FO¬ž·ÏëÔ›³hšGU»9ÞÓ‰;¯ ~XµÚ3Þol›vËM:\€ŠÄSIÝ“õª>– i(§-}2ƒd"©L£®·dÄ&ˆî߉ã 3^˜[–1ø²£ª3¢FÉ O´z~|Á*é3 $‰Ü”ó:Œè}è¤6“_Ý/ÙRÿxI ýd 2¬`h 2@T’Ê]­©_¸Rx»Rió]äå•&ÑíÓhä¡Â&¤žp#°q¬1'kU3åaþ°uÎVZ ™4iD§µðõ ºz^è}“5Ƶˆ»þ&¤ 7·Ó´DÉ1¢bFÊÖ:QUÐ*†Å4X_ BÒ|CíkÇY ó؀ɖ/(| 2ÈT2+­kØ4Vñ–dí̹BLìšiÂ_x­ÅZW”[Sˆƒ38Bè!9*Šˆ¡tÿ dHz¬@¿*¢C'Gáº"ïñ¦â…É‚¥_Òq0-ÄJ·<y@æ”ó^À[]ŠŒ¬)™,PoË’C½—:H`"¼&ˆ½$C“gà“VRþ^¯™Mdˆö„2³¡ xcî µõ-æjm?͸¼uÄÒesdéc Æœæ‘F8NN÷<ÀcŠ’¸ò†˜kK›w\5¢Wº½€+“w€°‘sE ;¢Žý34Ú›H5_¬V(SP*툤҃P˜L™Xù!ž ¡œ­SÞžÍ_ÑæMÞ`É♂cÙàÍ’L§#E£š…%`ëã)¡t¢3(—j ºMD­.šb:›j#NC¬GTʤBä,€*˜Èª±¨4Äù MÚìH¡[ÿLÀ Å.ø÷ ‡â¶Y8ú¶åi$}„|ÿF6XëÄü9ÇYÚ‡pÍé&¤}Á¢©gŠ3hqó,˜ÀXv#—±Ðíx7x4ÓHZŠòÒ#¨˜.Èâ5´iý™°‰²)-­c6ãƒ(AH*Bï´Ì)—€{ÊÄ ¸÷%]Ïàœjj@H!z^ ‹„mÑ^ùklÚÜÔg+>lAÛŠgd›­Tä\˜øJw`á†SÈ_¸G0Àÿ¿õâöѦål L°Žû“G¶| D–6”»ºœL £/Äú¡—TI-±!‘i6HÆõ "êºQ‰ä] _·¨ÈÞÊæ†Ñ.žës¡¾ÞéHÂ`vHWwV×MÒýQᕸcµùižØ5o\ÊÒqõ€•KæW~˜ÌH‘®ö¶Â\¢áŠìç9¨ÞBкz`Œ¡—Ôaèñ(–ä?Î#îZÇ©0†¥Ó'¶¨$Í-Y…C ¶Œm•Š‹y`KxÆGJ¤2lØun5$§Ê j ÙÝÛ\tá¸h£/R ­±àû’n¦ì+]xíÎ¥‘©H¯j\{Ša*ыՂ'ˆGáÁŸÅa–!°êí4Èl²”âVë¤Ùó¦s®©>jèA9­—³_6[ ¯Sä8[µjâWˆR?Y–ƒ»ñ Æ™ÓýÀ†Äü h#©ñ¶¤álô[ƒáœ\¥D¡TpÈé‹~ñ³c(¦Ï¬ ”ô„g=hUu*@™aмçŒÝÖPt2Øà6‘G œ¾Qýµ áþÑ\Æ!/ 8ÀQâ{œÓ2©M¬ÎÏ)ë|~µÊ9¹œ¤+Rãœ^r>kÙRï¶+•åÞM7‡õ}ËI‚t²<éVÝ;6*:ò}@€-ÐÃÚ•æsŠ.tã:b‡u®vûºÐ·óˆÁ~ ¯ËµŒYažéµ1­ä¡¶y¦y©=öË>@„C6-Ø1€³˜y«Ãƒö{¥ýÂ<-ñøª[ÜCž¼MÓþz7õR?âÙÌràÉ6éšX€³Ý¦Ó5Æ™·½ø6¾á>T™Ÿèˬ¡´?r‹s°¨ç ÄÑqðg¶êƒïžv Q˜'¿áݽS÷þÂ(ÉÎh‹pLo&shöL  ˆò!ãüŒ(J]¦4˸´ÄJñ(eãLÅhÐ-®œ>å@¨DdùÈ<åãží(C/¼&6­Dr­Þ®Eö€ÈJ¾ªÏI|&éºäÊVšDZ"h¡¾¦DxVâ€]îvò€øJ DÚø¯ø,«vîãV¢ ¶'‰Æ!Çø>í˜{&rÊJòÂmüvJ„Y¤dPÐP3©®¥ºŠ†¸Q‹£ .>¾Êœäþ÷Ê„c®†.p@Xú„¬ØoP*PÔxÙ‚|fÂXìæ:c­Ð#ý aüÇ ‹ü|øÒΠØÏ‘AöqìVŠjdøìã„Á £Pq  š‰šÿfˆ‚ðx'À m ^rͲJ%Ú_M šå¬Ò*îÿ¦îÈ =¬t†à& aG© zÎä_JLàqpéèLY¢rÐÂ.µ‘ãÅ.æð¨£¯bºjðwM 1° Ô&bçª>eÂ#Íw"öªhÛ,Ä:bxÙŒPëÍnvnš=¢`ÉÆ; ‡b¸DÚÂ#0–âü2 lÒÅBy þ™ò"ÿ«Ð߈H œ§è ƒ‰àÿ/p#ëp(Çsëª(Çò-βˆàoK†š¯j¿®‚bˆ.íèòD³Z×+LzˆK )õHœ( x¯QÚîj®~Ã$î)ð³LìfË‹„?ÑçîP"šKFÔ¸QÑ-ä¢ÉÅ`ªò@gF¶ûüÍ&žÂ?p®éRY*Ž6JˆàˆV“*.*«-Ox5Ìh3>!ËôÊo—9ê•6Ê„4nF“~èP}dcG2­±Fõ±øØ.ÞnóI*q¶wÌ`Ð1JÁI¤”@ M³° A·CÉI °¬â§.  ¤Ï÷<μÂǤ3« %‡< ËÖÀ§;I…~Ù‡DGH­qÒ¸Qº:É›:PBtr°äïB•è£muQb1°›0²]@‹.¹‚ÒÀeâ}t2qç²Y¬+иú…¿igh/).•i²©¥ÈÉǨï«Ânï†åøÇpý §@âg´s2‹fC)vg€ Â'«p*ŽÚ0ÐoË«)oc P^lôã°Þ¥&µæ1/PnVÑ«Fñò&úçæF÷Ë€4†ßÇ_OÉ@O'@Áþ(Ö¨ô“<ç(ÇdŽå(1¦UDôDäö*„sÒÁLL;>Vö¥a6 ~T^³Ã{":*M+â"(Ï? J› ÒË"ævRøq“&t‹sáK€eHÇ= YXé-¢Ÿ¯ÒököíJ+ j±,ÿFÃîV¶_’„°š4eôû€ÞRÏ jlO"€5ñ¦«°ÕvÎÞe"Çs0B 8øM­Z×—C´ª‚"ì«.ò¸!B©iºL§Hm…ôl”)$LïO.8m‹ÔÑbîfkc>qôÊÂbUU+Ò'Ñ>¡ÞÿeÉ0èêõxÌ Ê“s"@ !c`”ö-ð¾ú™©îÍì`ÉŒýJ)h@¨ç^nã»ìÔ<íSi`âéÐLó¤H oKmÃ[Ïú'&òô‚Èòزv2*.Vá=Mìê1/0^–Æ%Q.ê3ÒÌ–˜S08ãr3.I³ýWhìè/&Œs¼Û5Jƒ¤NÃkL4ÑNsÏì:‹ñ.ýŽÊÂ}*áüfí:›'(#ü}vX‚~‚îÉ´nv@%.šÊÞß×ö30©´Ço$D>V8Ù-¬½òx×É "ê küŠÑþWb2±êPüº°XD¶`}ó‚–± ÔñµI hyS&Ñv(0”|¡ŒÐ{(À‰³6͈†F‰:”–ë­‘8of.2Rã˜Ï•1)¥`¶ó Ltj¥ʃ°üLµotq4Ò÷’tÆÙ‰ÏUÇ*Ð ¢%š¸ íîʰÑ1ºa,ª˜†òh?7†T_•ÐåDº÷¶€Ïtƒu¹d¬æ{Öò!jŽrVWD¦e÷­ÃïÆìåÁ÷n¡ó[1Á,šòïö4uhÁ'šæÓêŸx%†rÓ„NŒ5­{ªO{–L²ï±À&¦„b2eVâLõ„ÐYzLc¬ƒH9d‹øëÖoP §Ç>…ôÐ5Ú×”L¯ Sï:öMCoô½õº#÷;oÄ!tŒªÇëqí î'9Y‡tDøQ@¸Þïð'+×5a—íŠν“Ïr­£Nlïy–B¨ð†æƒVÀ2Üu÷k eKRs'tŸò°fv6¤åõ\³y’ŠuY7¼f•ˆÆø#ï*8F'åf‡m}%ÜØ$ ÞR›gVÑ|uu$šGoÈ‘U‹gVô­Hë¢ZŽÉe ²Q èMBçqgIÌ$Á$Ê&\øÊoöÎJnñ”.9×2ôây^=®˜-ä žÖEßVnq3Û†G•äQ}”›‚0š†ìoνiCgªMQ«;›†  “­Jçâ5¥\2öÜ6þÖm4Èe;«‘£«LæüÉÌÑhï9u¸%Y´¥ ,y6“ƒØm‚0o,ØmC”›èîdǹÁó.90¼+ÊdOå›M‚.5ï€Ö¥¨[”ë(ôÔ¢°Ùª>éMS:‰^ ƒ­#;5ùö$5¨3¦^uü9=Ï|€ ÛTÿƒþ50`3áRqtï&ï6Pžé™e|¯;`íþUr:½ ]îî„O«¯ûá­ÀØ¥¤ƒ1IÓ¼÷³K±÷Ä-uNµ-þ,n‘_39ž6p Ë|1¶çAóÔOûà*š¢P÷° ñ÷ >'ÕEüY¯.ƒQŸ˜ôç¡ Cp˜•%ÛÅÎr‚1³é )wù²µÙ{|³&çüÛíñQŒyÌÑ=ÊÊÒ×)ƃ’׳±ácº]糌©Ò±>ýl% 䨅¤?ÆUÛ!ó °éõ5¼|»Cý™F ñø¤†Aˆ?¡˜¤bdýŒè'Ìb>‚i‘ú5˜ÎåñÈÅ]ÿIcóXôjú±NàöX5‰õV¢ÔDŠ´E)/ð%Þw;œAïQë¸1F¿Æ*0¸d¶ƒj¢íˆÌZÕhœ]fÐG®^ÿ¾€*°ÇÜ–5ƒ„Îê6ʳÿ=ºÕq×p+a-älYæöÞ¦ÍÅ3Ö©l~Zág³Q ¨ƒ]ƒpxS¼un”–Ê€1ý-¯a±Gí\H& ï`åÄ«À l[Q×?ºÌÕ¼†U2íÌz{ެþ ×ùÛ’ì+‰Â¾˜@ŽªH„£I»°Þ¡ÏJ˜ ¯ï: ê()¢ ç!,ZЪ¹@b™CnÚB@ Êã@¬â.è£ ûÀ?é“®'pZM­©š¿ª©j[£KR0–¶‡Ó }¬ˆ24ú#kÚ ·îÃLü¨-€–µ0 ŠI’$¨È,(¬((:4´8@D@ ¨N‹D«É«z@÷3ʊгNœx»ºˆ¤Ð±Ëˆ$˜ã$+úÿ3ÅIKôýÀsb€™2h#üˆ3Í$!©¨ôö».îðÐE‡üšºÌË21#DÐõB¸§òþÏ)"pŒCˆ´ÔÂ`ŒÅÃ'ú)8KÓêO½Hƒó]Rà-,ˆ4+ P Ô§¦LÊÏ#ñz+Ðb°6T¿²çª5cËS¸‡(*3G Šþ|^©Â‚ß7©ð©¢Mÿ}Ñ(ÚþÆÏ€$ì¦(È=®Óìòÿ6 ð³£L`‚Š(7ø{ã¶òêͧõ”òÈ$ ‚Ru:À4h†&ãu]ˆ†.¹Rv¿ÄØÛ¨­ÂèÞ8%u]©”þ—­ôó¦™@@¦µTt~®KƒkÎ$Ù¡Ö‰ü ÍH9íÐF–õ9¦ëè¶–ÁH&àñmÈöà’¿0¼>VÍ=d§yÚ}£àosHy£?ÉÔuЦ[Ñ6ÜðÑú(¨÷¨òÕ‰&]jKVih6¡²e[ÿ‹9Þ)/¨ƒl÷Èa+»š Š }mkˆýöµ=ÍdQŦO*çI¼(±›{a13Êõ\‰~.é!Ö’Â$iˆûê€l໥֜¶P3­CÏ„>ó\㎑o¨à«¤ðsÝ;Û^'a_8§˜dy>$‚Ÿ§âÚ‘JF¦¹Âpg‘‚4‡fœõ“· ·Çúœ|D)”.Bîé 4CY¤X¨¶sܰyyk`]?bª¢2ð…îq¨Öô±Ë4viiÚä’¡*ŒNlŒˆ6CˆüEM' †Aèj¾ÙsŠìþ&Dò¹§£\g­Í–«%F¥ëÈ´äèØ”›ú«Dȵ XÌ”Ùwr¶Í†DÕ »Ñ“–¾{ûš;«R¤1†!÷EÈd¡>dA\\÷?ÈÜ«UP]È&«$æÈ:é(1©8B²°Ã+‚µ4¢¥HøÅ#HaµÀOÁ$cõ§-T5ÈS7rÚûæ€ÃYêëJ ׈)5&×wù#xÿ›Kü Ð zâ åS‹yÖ¬£<®œ I°Ì™¨“ÄKD׎p¹¸ÊÉ*7Ã5ž5 œBKE¸¤y‡¨v[Èõλ4YG^:p™UV¬ç®€6Ï0:Þ=¤¾«ÞÒòó#Í¿€˜¨Q :Q¢!Df­¹E™Ðî 5ßšÓ"A&E*hÜãf[³ÒÄðšé2§€%æ$òzѽµ‡ *(—7+å{ã!Äi}¥wÉÔÊ T~ºÛÉ•À9;_lnQWT·AèíEu  fʪ1…iÆvá5ËÙO˜é‹¨k"µ{|?p¹AœÑ®WÀ玊‹®0ÃUšV§7]S¸¨tÕÂeŠÚæz‘#Æ.L§œÌ‹…Ãá¨ÜÜŒ ½è!Fê׆œÞ€ÈÁ}ܺ"Áõ5u©ÏN¿…†è"®ñ¹oRµ¤œÍö«Ó-B»£v`bÝöy¥ïlí0ܵæì\ ‰*HŠƒkÚ´€‡0~5[ØAæøN G2Aäý<«ž}ºnDÔ6å‰WœWÚ\>h£DØ]vµ*‘{ZPÅËùQ(ÉÎ^®“©Ÿgì¨ ›þ–Çã¢âHOpäYÌ~kÛ¤FÕöF€ÓVM.gÃ<¹˜\Ç+¥Òv‡×N ¹WFçvã3ÊB ôr]#o—={ëÁµ ÉËðÝ3ÓK{'êè¯g&èâV|—¹yìA“S` QrQ¥y&¼½ríµ&C€/\›]W„Æò3fm§pçÝ‹Òsß2D´¬øvl“ë$‘½~þ-ž»É\Â5ÈaûuŽFÃøxÞKÚaãCH{ŸÆ7‘nþ¼+¦ö/ºӛʚ+âiHÓãÃ)ú¡ás¡e3Ç+)§7X‹Q/bˆ Å‘¹}±iF¥8¦Ò5“cž+[Û}”ø£d }1´ª2ú·"Ë©±¹ž²g.KL@¾¯a•0 ç6á•¡0[s—‹#óX¬$ Ûd#by#ûÔ3y•8„Ázq’(‡1£s!_–À†£Ø>°$±C ²³¡, <`´AH;Òˬ+1šf 1›±² ó œ:§“½0ì4À´; } ñ:¯;„¨ûŒð±)xr?™t·ˆˆ/² ±:e’¥/b£8´»I›…#¨»@$ÛÔ>ƒRÐ6¸|¯âD%Úò®¼„³8«°Š~Yÿ¼»¡³|«#Á ZªZ4(Ób¹}´@~¬H@ÍËjÃz(9R¸!Ͱ2üR4ÊùÛ‰‘¤Ú… óB‹S¨·!Û"(–±Ò­ûò"©‹I ’"1Å ©8D{dŠ"58ø}‘»¹“’Â>ô§ªÈóÉ(³¿’·½œ™ŸÄož2D¶û»”ÒD¾;=Ä’Id€ &¿„c*4C§ìx Š'Ú±€úÔ²F:t¤Œ˜c « r®È#13!ÆI¶“̻ЌQ]8†¬Ê·$­7)¹!™8Qͳ1ª¿³(•Ø7 üªc™[½¢ãHˆ Z}*Q쬄.@¬',|¡ž+$ñ´ÌØ»¹h¥¤b^±Y)›i6cÎKªŠ3{§Jy8Ó s° 1¨."½ÓŠJº¥<Òšsnä0¦‹òH“L½A°ÓÑF)<³#¼p´ iª¢)Ù¾*$FJe3E=4ͼj¡„½Š¸´)$1ž¼E+´Oº Š2ûòŽ:zš»²Y8O)Btô! ÇNÜ1H€Ó,°¢! fJb¤%iNyø ð½£8šó†€³¬ˆ¢ªQÏq¡h±ÂÝ:ầ b4X‹1|ß# <ª{qŽBŠ1߀jt4æ› ­Ù|¼ã –• Âò3Ä¢"”[ò5NX‡É6 œ ÉŠDBËpˆâÑ©›©Î5Káî¾6Ó;½ŸÄì, P÷ÂÁ€ ’Q3¹ÐˆÛWËbFì2"{¡ ªè´Êk²3í2îúûCü¾<ÛªÜEÌ>âç´•€#‹œaÅeBE8|¼ûrªð|Åž`ò»Sœ i¨Zç8²¯ŸÂ,‹«»á’l «º,Ê]“ŒÙ½£ã¯±õ.""´+?¥öÝ"¬¤YFõ#‹2ˆ;ÃE ò»# Z¿h`?œ0Ï1â° †=Ôl8ìÑTáœc°“…^ºÛÚ‹)_V­/­ zŸ7ýöÅÌ0¬ó:4©Æ°ØUšzÖ„¿¼ôO8Ç¡__™ó u©9¯TòI5j“4­Ù´ÊMØAF’iË1“kI·IQPíÛÐL÷Ã1½ð¼½##™Y´¨Ó m«àóCF5B ÝD\ORçM’ò™R˯!õ<¤¶J«=u Ý£$Í›ÒÞÛ8¾3U£(7â1ɤSbìj)Ï]"S‘Ò¡›¦Q3ã QÈ3©q¿”›ô'Sà Æ{¨ÕÂ/ ²<¬F—yâ¸1Qaa;Å9 ´Nk‘$Ù_M6½]æ¢éxÜj1Ž9´–Þp´4לnn!ÃBÆŠ›IæðޤBú:Š"Ÿ‹»¨³6¯+ž#ròÁ_Qs1ƒ³ê³nåùõ>)O§­”Z^ó˜ê¡Û¶¶ìÛÂâ¼=w]uíœTÝÜfÂp´Õó±uà¤z'УwÖÒU¡ ö$ôq0dæó4{gËZó_¥ÅÚóZÇ Dlãœâãæü==‘8‰ EyÙ·”|£Ti“B•aæ?†±f+¼,­±Üef=‰Ã¼Ž#º#T¿CôÀ‰5fÒ}ÒØ±Û«º^±K2§Çqcò9+œ?"_<‡§9¢ÊMç®!5:¼âmœ<`h`.”=GH™[õ¥n2…-4Í‚8½é$ÙÙà ;²Vóx³Ó•l¼l-6×´»l¤M_‡Ë][±—ú·"YÍÌ•øU ìKdÂ+ÄFBäcNE_Ä>òQÔœ¶KF›#Óe¶áÛN¢yTÓ<:ˆ%ë3>.£°“ðŠ»‰Zi†i±¯LÔ0êÉqäÛ„7ðBqÉúÜ$ÙǮۄp¶ß} J4䆀  êô®;öiТSÐ(óòczFTìýˆ-½^¡Ù¼RÇ 6’^Þ‚¥nň…2’²2ˆ3TføX—ÇÓ2(€ÓBÞ.šò Á fF·=ìøê®¥w”j0¬Ié‹a³Äë,e‡»Ì¸#Æ´­ _Ù×bn_ˆÁ󽦚j›#w¢o èd•P¥Ð<Û‚vÇ»µÁc«rh²¥€_¿ssæ 9ND¨²ç†µÂ~á¥êyw{î0]Ò“¾Ýì$‘uû54á÷.mE>Y^¢åÜ.Ødd=z“””Ñ>p{`-þˆ–EaáØ£CIt¿ã[5o®^wŠ(:ôo(÷ŷ¢éÀ_â¡ç÷‹ûVáÇ^íÅóö•{âŽu"\D9{ÇÎí5Ö(>ãvõåê2\ñäݺqð×}_Ž>Ö”râyO»44Úñºzɹ (ÌE¸3ÅM[,ºÞìý!ïÒšME]õL¡ª£L¨jŸÚ¦Šeltf³‘U2ªbfÄ]zÙX€>à@h#ê „AŸ@d ýˆ?¢@(¤AúŒFcQˆ³þ=€r9òM È$`8P](>ãÏø@c™ÄŸÒ¹œfg3˜@¥9pQ+“?'R¤®u¤Ê&²¸Ìêu>Sâ «æ½5ŒÈ,1IDZc(Ú^¶¹“5¤îO{¤¢3(¥Å'TZóæÁB¡Óµ3rÙᓘ–"Q ¤Ø£hÞW( C$²iTŽ-•Å¢ÒŒ¼þ=¤ÔPãÚ Z%eˆQs súQ¸I¦5‡þ¦gI•á£G¸/Wð$rŠLêæÄ·/ÈÏIÁÀ©60;6üÉf4ÛìÏC¢òÇé”y$V!¦ï%~NDj™!‡N©;¸Åî\§"Hr,2ëÃ\¥ϫF†*ˆÂŠÙ5hÂúâ!ÍQþ¶¥ÌclÅ£ËHzD \…9‰4<åmân‚2©‹¦š§HR2FŒªÖzÃÑ)øž° jF…/îºL»³K"ý$Ès"Š;²,žB Ø©-›¸Ï£ ª “(©B@â*HBg,$Š4­2@ Ÿo 'Iª‰¢Oƒ~“/3DÎù9hd\„${Ð~˲:%+¢4;+€H³Â落ÊÉÚ<ùÇü ¾² L+í#5)Š­>1üû¾#¼÷µUŒ&p!/"œSÓг*΀o"fï§I]€¾È*LÞTRe>¬z„'T”î~(°mQ(·ÈòbÅ(t%©t–KHƒX¤ ŠöÏM"3-Ÿ‰B‹2<ŒBóÖ0dú¼É2…]ñJ7)ÙŠó¬è$Ï„=‚5èj™¯±ä¥LÊn³·%Ì €7]»N5Ôõ³ŸNð"Ž{û^#•»QmY SÒ­.‘ÃS[PÊÚòzV‘Ý4úš¥ í×GÈÀ “€ ªjâC$Æ÷Ê5¶øÖi­l~çI¢iS$=JÅ`2W”Ÿ›œ‚%kêâ¹WgôìNYØ+eçöµ LÀ ŠÄ]È•ÆòXÕ…%O<*€ë\kLC‘ô1Ä2¥ÝLÂ@œë´)„ÄÄeìÐm°zV <°\ Å‚{Øã& ¨&~ÈÆ¶L…6ã%TUÆà_çLðŒe¢ââd#Ç~þ.f€"fãn[ ùG†6­À¢˜tm*¶$f¬´Ëøìj bÆÒvd<8 fêdmô! ª7ˆevoö±Œæ§>\lÔv©)ÑégSªD·n’ŠtQk´ó~%˨ÞjR¶ÎÖí*†kD,>¢Þj@ öLÖ¨£î™¯í¤„óE@“®Ò:ÎNÝdh™¥ˆµ„O®•)¸ÕôÜ"ÒseÀýÏm‚V˜ŒVNèfÂäp*8úéL .J%A ä쀈¬×£.²(ÎspؤqN”ðrü,ÌØø¢ FëSÂ䵦V&$<á"äÖk.e‘{ã¿ 1½ ±» ë×g˜Ó̰‹¢Òîšm–%Áµ$¦Öe$=Éð†‰ŠF{ð’+qø—#.p-D§‡<¡ÏÀu0d¸²‹D( ˆ8ðÒéQCn@àm§ê2g,Ùçª\rnÞ/ã§R§ àB’‹Pÿè5B©e®fì\ Íó0qRy’»)N5&ÒœŽb Ï@‡ÇÚTé¹$l²æ«†™© ÃÍÐæç{ìšGè¾ò|踞è€" ^"Ò,ÇCá Xˆ ØeJ¥bLÞiš!Ò†1 ! CR\o<{â3/P8²tÁλ)OŽêÀrùBfCÊÏ2§†ZìÊn¬ˆÏB0Ò%aop|M>Â,›"tâ&ªÐ°,Àfq!f13R‚™ozH ²·(FÕij´Ð›9€xnÚEÀóæSfj¦ „õÈÚsÂtËÊÐéˆÙOõ0‡WïzXnH'¾‚­<˜+¸× cO"°£\ãïÏ­c¬ø¯_ â¼IN ÈÀÙ%µ;¢~—áú¾Ê¥¶r$PÍK¨o`§<¤¶eøÜÅKˆ–!ö)$<0’d½sðsí¼ É7s5eÿ P%Î\¤e´l+¨þä½q÷>ŽÓ$ö\ ÙñåCnÓIt‡Ê&)²©i*,nòĒů "Qvn¨šÒ(ãîR­…à×I7N|Qq#Iö’xqÈ^LŽuŒ#o˜" Äm2Vck H nNÅ pSIØJt¸à»Eûsð<¯íÒ“‘p;‰‚šwG”%k-~׋R°-ìª ¦ ÑcÉ24’Ž…¶"˜`¬§=ƒºÎïî~O&‹M§ÓÓš§#jïÏp|­Z0ø¼sT€0SG”F­Óìb‚¼p)aCP¹E@dù @ïíX×Ò®—DÈ‚æ¶/©ÄÚ…T›ÓÞFŠhN¸%ÕKæêOzËHŒd¾©‚6o!Ì¢þ#é#3–¬Îª´ÑP…æDE¿0 qŒ€1‡€R ëÒŒq 1DRª„{fèçU‰ªtq|O#fÒQº‘Y!4ªûòÏ\ù;9ÏÅI¬¯pƒ¿¢WŒu˜”»æ™ðã/\Z8t)DÎÌÿÙ– Å6}™ÅŒ'2^+Âõ¡öš¶Lûú‡¸œj»«"hËäÆSާCVIzbÙÅ•5X[ãn ŽÚoW¼Läò½Toa'?X‹g$iÈ» „«M“–©-ÓxiµýÒ±ÌíLø»Œ|Æýe% ºVÆp¹Ž“,b䛆êègg›=(6òw`´NÒ  ÕµZÞvy4™Ûk¦îg_ªNyðyp` Юïs#q&u.vòfô^›úl;.›½3FŸ€eù¸:s Œg#)ù5s¨w7rõû 7†ö›<1°Qrï“c5…)]1”xË>u0¤p3ÓÕÓrY“b=-ŸØØçPY¦‚‰†Æ=—ÐfW_ö¹õŽ<2­`¦8ÏB$È¡¢G–n½œ÷f›LßµEI<‰ybÑs'Ì]{I03})ÍUäÝg€äVGYø|Ô¼ðÓÃîÿÛ—n“…Èí2ª"“‰láø‹V[_eÀ}šóuEÆã$Þp9üBÛäÍEÙ¡¨ÚB’œX9'•­ÀVD•`uƒî¢"%tÜfR;:Lsó]á²)­;íÙ¢–÷ÈÃeÿ⇟¿NÒLŒþ4›â(ü{é”Ú›ÇÝв™d‚Sm¾Ô¹¬"©açWî×TBÐ=±m¶9 °æçg-¶:ÔW¯éí/‹¦úCŠ2ýaÀÅ-¾Ê*ב‹ÃQTî‚–¬Á†È‹^Ë÷Ø¡˜í%é,‘V>þÑÁØÅ¤É¿¸Î±Ýɽ…ú3O®ÜUV/šôÙè •y,ÄéâÖ"Àü¶­ÁõÔCDN ‚Fâ«–>ŠÈ×ây‰¼orÎ̦sz`’™êÞû.;+)‰mÀT¢ShºC±p}=/7²N ›÷ø˜ùçB5sy|êoVÝàáÑ{ ÎcVæö/|° žþñà€6Ûtþ rÞðÿ/£oÇÑÁ.ºLs-‹®PÞ‡"¨•ÀÇÛØ4«rî¬J»0Ó±r¬®*²îé%mZL|!\Bð¦(»®¾*òh‚0È< ~¾ÎÊ(Ð",Ã÷"ª”j³>,™þê!Ézìµ°€ bÆ>O*-ZäÖÆ±âg!Z¬ÿ­ÈRî„QŠW@ ‹¼(©Ë3«QúÀ'äàøÑLK´‚=GåO"ï uKŸ¥ /IlëZˆ"R©þ«4ˆru&ÈôÊÖ³6ñtkMKàJ§ÒÓ1ü¹QâW;î:Ђ®VÄî‹®îqòô.îR^]ðó"° îy^íZimÐç4òLè‡;ñJÄ»ÁñzT•Æ­Ãôñ¦êŽÛ¾ö­³Üѳnß6 %jV@=ÆÒ$ëHF1<¬òÜOÅ~³YïÖ;;~j͈:ägt%Š¡»ímô‘'Qrï'©]¡¦)Ó‚Xè"¬¿$MZ|ö#ñ4j…\¶´®WY£¿tÝ&ÎËVûD=7¹¥…S59D:ãL*Z‚Ý6 ÃÉ~ª•ÄÏE¶îR/J¦vR tâ•V·IX‘”UŠ€,Œñò™iÿvIJ‰É`°ÖPô]+G<~Þ\€W)jå°+¾Ô©6ò¥²ò¸Ìêäè°„úX­R˜„CÎó˜´KœSŸj&/r(˜¨}ÝÇ¢;rAš>š%“"–K_9šHíÒE‹>iVd#ßt߀/±³³™üïÞ3­pÞ[<'\KU£‚1-ô¦"‡²Z]ã—(m6˜æÈJ”},¥›±…²|Xd pM¬—#¾ÒÙß\h5˜½§DAÜpý](\B$ŒÈA:5e¦@çOòÙhÆaÂ0'~žL…j4õžØ™"n‡”B“­ï:ʽ3Â]Ñꈡñ&ìUÊ Iá­G2wÒx¦ˈÍíA¥djëÔTsVo%d\¡±Ñ§k¹`³TZigá\`/~¼§–Jf¼¹rÏ“çªåJ nŸ·ä¾ôѵò\Ksk×H‰B³ß”æ$YFÖ‰ÇTMzp5zO¡]Ê'ÙpWª‹+Jö/oÖ)ÊnZøo:BŒæÆÇs'ÅùcÔL«•û'œQ£ E²E¸H8Bú@àVJr©‚ÙÚ‰—ˆ?ú—´€ò«Õb¨/ä:œZwëÇ.+ …z„ÎÎ;X£\Ð*FF’Ó!@B[›x‘Î'ær™}¿Cñ«Dª:s—*o—w2ƒè]Š#'V¹@µ£úÁÒvIeu&¤Bî÷m[ë"Ž×+†n\Ìzªôë¥FœmâJîŒÖ“r“ø×i-uôŸå=\ø˜-VˀεÖó˜îmc´¶ý#Ó  ;É<(„¢f!yNe9e}Ô1ô­&"uÇ Nð”ôk[ Å”éÁaŒo˜˜û4ß–žš>&Az\.†àÒìÖ§ õd`JÍ`«ÅH‘þTÔP1c©9ˆß‡Ùñv3ȉ.^ÌA;sö>êWΓ•^xw'!wÒÓò_ÖYÌIÃñZwcÛ—¥ªj­jþî 3òŸbd9¢ã¡[z6Rµ¡ªö-„ «=2ÃP ›`%hÌ.ÉoŽc¢,bƒ%Ø—œ°«&"Í# ³km»Ùýi&»q›‹ 0oA›Æ@aÉ»²£Í¸+®CÛŠ{u·2ŒûŠz2á%4+r‹Zó¸Ã¿2U-k JÒ<'£1j;7(‹±ÂtÁ­!D1söA²B"ó“ ¸ð«9¯`å ¥ð}ª‰Ì½AIŸªRKBˆûFº[ `—?0›Žø¹9j‚£릘ַY¹ [`Œi¶²G8Š9 ñ^µr‹ {I½ó6HÏ%Ü$ð-šq XØ “‡Äá)„0¢˜4J&›Ãy©û+±Óu™²š<%&‚î4¸á§ªI›¨‡Éî—Hï1:ži;²ÚAJæ½¢ JU4ªæ¦ ß j¢¼‘:´Ð™ 0Ö2«[§›(Yù¤Y®‘¬*&Û£Ðæ Ù©BZµ¬áE0ò»tV@“‚¶ìF¤Y׎:7¦ÁUGˉzêR‚‘r¼ˆ…&#§Ç"°¨Š:yr™‚‘- [Ù)Ê›k&l@‰|6§´‘–‹ý´ Š¤À°°H¦A±“þ²Êß¼®k±¹Ó@ù D›ª €:’‰Hĉ¸ô<ªæšê¼¶°·㜳§»ùË1›¡Âÿ.j8ɼ«Ì Rç°ŠˆQ‚-:܈¢.A*šE+?Ù(1ìrx¹Bòm¶"ãµ*í sEXئ:˜®RñÀkC!¯˜iºr´.ièÌ×;ï³òbJh¢¬§5‚ßÁÌBŽd¬>‚j±# ¦‰é "±Lj>šž¯ŠÁDò˜¡Ã¦*7»üY*˜(°˜žˆ›Áª‰,×93?*°ðGŒ:Óö20‘*웲\®°7z”•ÿ%Ò‰!*t.”ò–?pÜ$úäÎ)¼É‚°C ¿¿›þ5{¼Ó}¹CêÌ2À ªiI § T­¶ù§?°Š*(÷‘ì9‰š>š¢äåÌËQ³4b»Z²-çCËZ& ="p™¬£t¢:®Q®²[x4Ý¥â =;K b]ÐGÂJ–H¬›)ÒËÃòó¦#)ñ,<µ¬á†«Ì¸ˆÙ¢‹Z­! ǰæE«D›Á ‹·6âL§Ñ[ôÄ™]Ž„œÆ£Èˆ:zÎp†Å3I<@H‰/Lò‰ƒ/Æ<ÍBPQÅ têüD&ƒŸTƒ»JôŽÌ¬D%T¼‹€¾˜³®‘èG" ñ·Ì›‰œC+"K1ÔÝ<ØOœ´å³@¦ŸÉùs¶Ôª,¼ÍQÁELPÂj!€4·aV;ðºM?¤ÈÀ6‚è(Ì‘¼ž?aîÕ,ïRئ 6ˆ¢ ŸƒŸV#û¼S>x„¼fRx‘Â’QèÍ;«‘´0”íÄ ÃCÍ´wÌj%P,ã¼:¬;ÄT¢S© vÉñŒÉ#(—ŽûqŽs@=2›Æ ¾²k‡ÉšªÌŽ7c©–J=f°#I,Щ+l¡SRW¬û9Pñ1ê;¹A#)DPðÍ(¹áÕ hxY‹lÇÚù¥Ü+O”<ÑF cÂWÚÈÌÊ”C^’±^™büÕ]»m/ÁÔrLñÏ.­;{ϸ…:š¡®U`‰‹6¤D—ªÍHÀ£Œ$ürø—½Iûs‹Y=¥Ë~Ìe$ìA:T 0›Ú¡Ÿu•c(ˆ‰X|ÅŸËBE´w0<~D“ý‘4±Ù¹‘Úš ΂æJ ¼QZ@Üü%ÚIp&{Â!]F‰Y ‡­ÕZâïÖë0):G— ªÉ ‰zÂk§’kÇ\"Q®•b¤/aË] àÇ)ð& ?¯\úåЮ`ˆø÷Ç!váþ¾£ãpz^ÙÓ'­6“s²º*•ZUŒ áÌ»l€:?*É› 4N)Œ(Ü©¢œÉõ¯Óô…* Á;S®ù©‡Õâ¹õ Ú=ÏòlY› Ý„NŒ¸<Ó¾¨c R‰ ZÅÉBÒÚht¯IÆ;šiÄÔö4[¥"u¹?I£¼Àý6kýG “ÀÛ°VDh.È„L*£¤[çÖ#Û_8–ÞØz; ‡ÍÁª \)ñ,t4 ãšrz¹«„%·éŒ<¼jEõš¼=ϱÜE¦æmº!¼ÉÝ8}­|\ Åݳ µð÷ÂR)ßs”7º—;äùDP—K%žéʼÊÚ1 µX°ƒß¼³Ö\sZNé÷‰XïŽý3Ä;‰ž< b¼×rq'ªT :Ãéå•%Æ-;^Xì›É‰5¯>»ŸÍÓìÜS3-»œµÃ¤yVA²PŽN\«ïªĬ±éßó¦º{ðà& SðÖ³‰Ôˆ¼© i^«´‘âÂÃÚxçFq”R ª,œF ¸xæîÕÍâþ]jƒ“X<,%}‚«ŠÃ]í)S­Ó¨¹¶’—N!,£#±ªZjWFb³¾(‡ð’kÆ>Ñ‚ßÊ:[ƒUMtÛÝmx=)šÒ&u)Q‘T„I³–D{¤’¿ã®xM`± ñG“1à~Í8›¹ZZň\¤Eÿ¡Ã3åý…Ï£¦ÂÛ8 É Œ2@å![¹~q¾<*c‹Q¸a0‚ª+wP:‚K¶"?îà¥Ýtz>|ÛTó8Þ3¹ð»Ùœ+á©é¸ª fBöÈ%¤E%ˆÏõÉcý²9SxKB*ûuµ Ä¿#ÝmÎâ]¯}Æ^=* tÄC=Y›H ‰Eõ‡î•ÄšyBLVœ¢SÞˆ‰Ê&ìEBn§€ 27‹°¨øj’G‰Õe"IÁ2ÓªÜëzÌ®Öã;áç4%s?6-Í[ÀÚU\%$ó¬º4ÑŒ-Ÿ«Ã>Ó_‹qÓ°® ” ³­æ×“‰àZ1烻Àz¸?nÓn†TX¾ÐÄ˹ô/MûÃδVàÅ qúÜàµ!š5ãý T""R‰öеñ–μí&8õY€>ÍÏîêüYc¶ë-èA`Š€@«f\8èU5q]›ÌPKD¹ ÏRGØöŽD}ÈsÞb³Õ{ïþÏ ÄÓ„9FJ¨&r§¤­þåÏš›O³@ͽ1›Z³ÃJœ¾~†eÌèd›çÌr,[>ÓF«©R1a¼huINÀ)ñ;Êí‹ì³²&µË}|ZÚ®g è¢pXã{¾–ñ˜mèûÀÍŠ ¬¾b«á%,d–-À¼–DœÉ—ሩ‡ˆþƒaÕ¹i¬þð hb¼°Ã„µFˆ(*¯.:~ £ò‡Ùô/¸k&2a8Š”ÙJ–]%ŸhÜ"+Ê3Î’iÕ8èˆÌYíÙE™ï#¤~µT{óúSh³e‡ºø–ð‘ZF+gš­P¯Áæ†ö-÷ç–cb-:5e[.˜iQ! ¦(Ûr9¹pîq&Š©dìġ!¨¡‰Î×Ëß,ÿÎ+ÉblòËì½`¸„'î/lì'OÑlçtUÞ·î„H¹º} ©bMÉQbL S¶Ç»³)Q³B^UŒèξžÝä3O8ýÕ¬î¬^Õö$°sx~$ã%’㙯E݈ ÜõAýâé™kR8!â“¶dÈ,$ð±ª-HŒ¢aRAoº}'?Qu¬Ôà6Ik5fÏ)âÈñËšãÙî̈Uûås”U™ÆXçT–õå]ßê½b¾-ÑEò÷ˆhüi‹9E~Âõ^¤ zÒN‚¢QB{¿šm­±åX‹øîº lŸ¬`9E<ÝsŽ0…äŸ^ª@ L©CøB® äQð¶3ÇU¦yÜïûÿ›Ür@6ùŽ#|²ÙÕrð+¼#>ÉxXÜM™^Ú[Üê fwQæ)E;%¶°V,ì@X‚ bw.}€0ïôôÏ­;?ʰI1ü•V‰/@·zµ×Ö,õg‘™&…Äņö“YuXÝÖ‡h²F|AÉw$kÌ1ËsÚ%:<¤Áÿ•øb.ºî„¿Œqà^ÿˆþÁ``D& †áÏè€ %BÀÑwÌe÷…Ä£Ñ÷솒C€q·ÜRM!~Ç¡PY ù3–BehHuŒ¾@󸤲–OÀïªEQO`h~¥ ªB(2*´BM.„Aê°˜† ­Ä¦oȤæu1”E,ñØ”2å¯%¹5Èw‚Âm5Z|2¿d‡Bïà Öt±KÀ2l<&{1ÈÕk€S/y¾×lYPj%œB,óL²M“’a¢1+ à³ÀÁzCëg ÜÂrð¹C¶Ä)œ'ì.ý¡èìpŽT"¤·Lú8Œè=ÍWâ˜Çþ:) ÀǦ3\óþc=p8è_£1«¿dÔÇÇæ=äçÕ:ìJ²$Í"Áª¬:Ä¿‡û¦ù$i#¾ˆ6p‰üØŸê2XêŸ …¥[Úß63®³¬ì;n@ÀPé¹gòbiF@Lh„¬ðû=*3j¨¢OkrÕ0ªþ· ¯ÜŽçA2[®Ç3(‚Xó$² ¸ÈºX³©Š“,ð²L˜®¨òÏ+"©‚Hܯ¤„¯‹Ðð+óXܵ 2fÊBR#Dîº˶(©ûrÈ9ˆÛÀ±[Ò³£É4€¤"‰Œ<¦ÈÚ˜˜·/k”SJD@KH¼Œ©‡­Q€‘\äôÊ@#\KóûE€ëÔ’#Ñj¥>ÂÓê=B¡ÏZ3P€²ãÃ&1:!Ö.BPº¡*2{AR%8þ¥ÍóúÔ`44¦:ë¬4„¸ëŠ (¢O“ÿ»/’꺸 #R¬>gûÛ$,rY7°3íc6Ò—k‡.¡ÉëÆ¹)’|‡#Ï«à‚°÷ôl™ÝH»ò|Xœ•‹ÄnÕÙ8Ï` 9dSçÕì‚¥wÔï}å·ûÓ—Ÿ°LS5.Xìh¸ˆä‰˜×t²¦Z©6ŒËÓËZ‚¬÷ì””C ')€q|^{ëLV+š0rÊflK-º'´©ö„Å8ÉùcZ4Buo$6µ¤„iz!|¹(+‹$ˆÄc¹´û€O•c€ÏnÆâp‹Ú›¡Ø…ý2cHCϪ+[Áýdné>€êgí6oH¢™ ^à$xáÞPþÅó¢Ô¬ýQA€üJOB¸ ·¬à¤ÕàX»ß_n"œ%%6wöóS<áÌrS¸Ç+ï|‚.Z\M¨I6´{¨Þ:6äy‹ÚCsÇÓóC¼À88ံéâ´äž³ÒPnTÊi)™¬…~æÚBfMéÐø½u¸^œË°1H-Y˜3Jý^Á,\ÄŽ®þÃL7.= ·d¨«ÝSNrà¶:‚Ô0þyeɈBBŒ@á ºd$AR˜’"†êÕ:”‚<êT8ÿmè0‰&±SA1„QßG$bÍxeh-³eLâÊÆ…ä¥)‚.úHLo¦]ï›$’ýD@&gMÂE^KCïCŒAR¯äaKû…eš¤ãURj´ƒn!8.‚P²W ج‰!€YdÑ}Ð(Ói YƒùTõ!VaQqì<ä õå c¦)¡’–Nbjb„!Ѱ9f?VÊ×’L•ˆ5Ô?_ù2&m’_³%Èdm"瀲³¦©NºÖMîÖSºµpgñàBlœÙ·S°CÆNƒÚxb)/f!Ñ<º¢ð‰¥Äˆ’ì§6-0Õh€³8~Cö|Š3–„$lQæNŠYUI˜³¸éFßèÿg1)’¿%’UÑÜ…%y5é?àT*jò©|?x¦>Ol«|¿…ü]f[ð¬ö Àh¶æ?Œ¦?æÕ]a%0™xH»Ÿ¥)(ϦrIñøKŠ“sF®Òä‚HV¡µŽšXÏS1í=„ê®7òÇi­@ñ5NFÀZН†ª(Õ¤9 â-.Rí¤ªÍæ`Õ˜…D†ÌöÏ'ì£cä”ÄͧÒz¿¡lÇy4 ˆ€83]£½#qY¦»XõÎå(´"{KHuåô]•h%W¨ŒW×…“k±Æ‘Ðä^|¢•Mµcõ>œJ…í"wTâ´ÅÛš “ Pek+Tç{d>VêuI؉‡åÞnnMù·¢M+Z11Fœ6úþ(™îPU*Ïw? Ë=°éŒZöLaܯ–ç¤×VLw碲&sêXBlÈ-P­²\ºŠ,Ñc[Z)‰–ó¦ìBÄ!ª EJo5z¢ŽðýìJ¼ZV  .Jáü—CäÍ)ØœŸØäévÝû"Ä\餲ÅM¥)7/ öš»ÝK§!&Àó­˜ØëcAhÙ´Ô.ü]5M5Ù=>§•%\ 7~áÄÓ¸õJ&ß"6wqµxcï™0u@6JK&ôÈ“MîEÐÅó³x‰b‘eB'Á.û%w8†â­m/Šæ1í•d&V­Â¿%Ò!È6Æß!-D€Sk6Y ­²Â6OàÛh6r’×¥ô…3C‡ª,²Jx6ÌÚÁé‚eÎß9ŠgqL<$[›òdp ˆ³œ¦ÎÕ`¸Ò>ç%=_×Ë×Ì‹‡áí}.¬–nv]w¤C% /Cû+éÑï(äu')±àÀ& ˆoK=dÝ^;%ÕÏÍ»mÕ˜ÈPéÂ)4vO qTÛn‘½‡+áE% Nž’ÄS¼µ”¨d©˜„ËXØ@®µ#’+‰NQ©¶JëY˜ÙÜ òüs‡O3ȵö·,Í:Z“?E}±º?J±ÝCÛŒª¢6‚{ ZfèÒvÉ[c”zXU¸Ý|¹$žóµë¼²½·_¦ ^½‰¶ð|Ý‘4ñ$ë$† ¸£$FIˆ×ï×òc,ŒR†åZ¯‹Â+œõò%nZqíëà­<}¸º©`àØ¶wÖÙ¬(°ÌÓ¹”‰öAÎd ;Úæ½XO%á1Ø~%µõblâìküg C¨ 9:৤½SÂ7 ,ϰÁTôë˕ÎAFc³6¯ÄÞèN¢Ç§¤rW¦ÎOþEkÆÌ„çJÝãä< ÛñÍ+²û¦Ð‹É‚HÇgM÷Âû)Uà.Óݱ{ôðÆÐÖ0‘*Ä)¸Ÿkt#Ìâo¾á­~éÉ ¶-þË®Hñîg°òÀ5€φ‹8‰© öÈñí"µ´lÂ2ª‹€Zb~ÊÃòàJ /HHûLÜB¾É0R)Èvâ~006½ll³Í‰ Š “%ô¡‚~LÐ@ÜlhW¤"V&ú1Gð`ð:Ȫ:êZ“Œ®B©ï|ɾ†N¤Îâ«PT®ØW˜oÀc¤R‰ëÔ½zï¼Ïm¦&iàÆ¼M¬èÿ­î§Ïþo‡BR¶:‚ Ól4x"ÄMã§ véP­T®íŠ)‹»ÂõðÞb^¹Mb§¬>¼‘üâ¤o­ò•ÎJÆ¡ôÁFÈV(‚•ë¹…h[öEéÆz(½ïk±´ñrço­ âÄÉÖˆðŽeqN˜Â(æf)Âý¯~n dn¼ŽŒ—"QÊøæLÐ:Ì o’ªƒ.Úˆ–Ã`Uêg¯T ©(!%DìÄàÇŽà.¬ ä°û Çl…éÔ o•±Ôçâ¦Õ…õ.¸ktè‡ç¥æ_OÕ,H®²kboK!fNsë6d²V˜«i2®ÐÚª^d€#nS§Bá ô$'}*®kL ßbbôˆI&hˆ!“i'&DGõ‹´‹¤dGFfÇ‘G°ÈhºªTø,”œŒ$A)O9ŒÛ"°.qMÞlR×GB­Ì¦šBÂLÇ,ó¶±J~»‡‰Î—ͨüšO²°\P³(‘¾"Š>NØÕÏöV@?*do°QˆI ¸ &Š]Dí„–¡çBã4(¾§ÈÔˆ2í*~”‘è$é±\´%Æþ LËŠ±Ç,Âg-gÌT².=0i£f'¨.u웊|}ö•mÑ?‚x#.ŠÁt6ŒTÐÎÌr/t^Ù.†! ˆnãòb¨™1ÎèMÿJp…¬ôˆ<"éÈê«#m…T¶&~kunPV‚˜fÃ>I¨¡Ò?1”šõ¤W)L•²B’PÊîØ&-Ró0Äæ¨²oÄ'ñ²ò§Š÷ô¶(*ª‰±J¢¤ðf ²D«g rü¡1s@£y#D¨ˆHçã(Ó/æGh7$RlòÛ…l9Úr±‚Y ‹tusçD;V¬oME-¨Þï’¹b!DpzælÆi›)©×=Ò–ÿ¨÷  ßu/ÚLÓWWËU ®¸@ÎmQâH¯b¾äsèUx²ƒÂz)ÌkL\ I3D¨ƒ)ŠþŽÀ¾Áÿs3‘«%,r¤ "†fN“3 ó»døxPЧxBg¯½ÂÎg„iHÙn…(íŸ,B­õöfÃT¦Ù7RSŠ“j’¢ŒÏ/¹Pop˜”²!Ó^'ñ×>³(ϴĥВӎ[af!ÆÜJEWgç#ñE/¬‰g F›²r°õ6c³Êœ†Bä§§>yF…bD³è;†;5æté†k¨Pª’†÷U^!tÃÒ7$8_ʵRI1*mNè*Ø‹)sU׆»7‡yI”¥+JU)ÖŠ«:|–ú“‘(©‘Â"õÄémCn!mÕgmq`¸â(}pêæÒúÛ+Äsãrú±}s¯n¢  ·N@5W#‚ÅHR“4Mzƒt ‹6Rúîšb®2ðÜ•©66u’¼Œ,N‘³ÕF+G%KG4î=¦;mem(îʸäèoªlæ3è!a©|L E÷E=þ•è·8“p±Øé3›oà¿SÔ¸ÉOYêV1Lˆ'§GTÅ T÷PŠ˜o¨6p!å€Å¸ÖèWdË~;èP:ì¡PÓ‘[Vc ¬ùLÒ7ªD0*én (ÔWP„èt  ƒÀ l,ü*”B Ö&!%(ÇåsµEɨV%ŸR‘£o"䂨¶E.¥a:ÿ µì Òe‘?œhPÛοFâëz䬖®¸íqEö§¦ôp7VNŽ7wâ©~Ì`upŒˆqÈÜ&gv)vÿ=²ÖöK">EdmÍ…êÌ$_ÒJ#äÙaoÚm’QɆKc…)„Ãñ?öoJÿçé")<à'µ†ÅGV—$W|Œ¾ƒeqcÓI9÷&F4K‡5`UO#FÄí"¿Œ”³µÏ¢hõº9 ²BšiR2Y8î*}n±¾oHŸ<Š˜©‹aC’©dªÖF–É4HDjX±–‰îúÊlðsÉٲê™Q­^"öÁÉ¢ËA*Ë>õxo"¶ËHmÄäSPš™Þè+vÁë~™+eÉàv²Ž/Q`™ˆ_hÄÞËb!_ö`Ó’Ín&dúë_n9Ùw0`8Âi6tJÉêÆ% kt.³ØC™dš]~yô#ÓÈBÌ#Ïž³ Q'ú^÷µöz;„û4àLÊó°ÓgŒˆ¼pÆõ¦"G·NÑzª§Æ:Ú²Ü8Äu­ý¤9hÌgsfµdõ,kØÚêóXÓ” ¡L ÷W †cÚ=¸¯g»)΀˜yÕž$Šÿº!'+q÷Tâ—lMŒl(kÇ?&ÆË¹JCN—põ×(õ¹:Óà‰»&?µtÝlEf` d5Phžùeô½¡óJ2éI/ÝRùÒ¦w®ÑœŸdý‹UJ÷ª?B¤æÃf¡EJ«JYÖ;÷,òI‘vÆG­Ôuøæ¡Ïlܪ)›·Üsî Ä6ÔÄ5•DÜωVE'Ò°äR—9BVö6ä²?„öXÄÖ—és'j)a´DˆÖX•¡­¾‘ ¥ËdnYßУ؟*驿Ĉ>T]®7 ºç¤¨È‘E— 7M…mngŠc ÂËýË$‰Šˆû÷N¯(?¬eÃ9[GîÆdÛ’צ£q§â¾Ô+ (Ô!çÛ0ÑO¡™‚i'Õ¯®Uyxb/-x´.¶O¾B‘/¹²¨}Ç_%Î;ôïu{¼5{Éf¼a‘Xÿ•:ŠÏHÉ=Ë'ôàZS«yf(QOÈ N[>8ú.\=2qã´6ñ ÇÕæõM'±»ÙTŠ‘ºo.ȳmȇ¡±¿BhžÛmBÜGªÚš˜×¥¦ÉZÉuަÙÜ‘Bè(µ5Ôÿ [„Û’¬Ø=? šÀ˜£@\jm,‰K÷ ö}ðYŸ¶ îIŒð}8ƒˆkׄ©¥Û!¤–ׇ‹hÅbz¡×ø–!xêµÐ|‘){J~`,¯‰ÿ}K¥Ýu9!ü‹hDÕb¨¡ÉšñZ¿ÀG1¨œt)yP’jõ´®ôem[gçJ6ïwZÿ¹ô×]¶¯w+´14U0‹1?CxßÉÛ{=]C»:Ž5†Ä–ÂÇȘª¨mj‡(»Suþ[ñykbÜܳ.|2Uñ"Šm o[J=ó4•@7Q£|“ÀŒB­µ°"ý" ö"H·iü!-àŸx´íƒc±ñZ½%9ýå½oE;›f]᯽}lˆ¡Z˜"F:ðjVpÑ•Oâus•0M¹ÌUуä}µÕ˜!p6«Rô…ˆù U“CÀ^vN›å‰ƒê(Ò>>«•xO¡i t²êEqýË…ôÌTh§×<¸Üš˜ïÝÒoU]l{>žä"qØ(œ³C"Ú9R$#4Õ¨­Q¼óqu`Á¸éÐ9ÖÎ&F˜¸£ž¨Q¶oXò"=-%îóAU¬ñ‚BÑ#2Ûj‹ƒª"7ë*]¡Nï.àbfÛt éͻܸêþ&rÀwHH휗—/à<º¼!²såÂÞf,ulïpÚ ‹pú•(8 ¹ÐÂ?àØ4 BßPÐ<‰D¡à¤V0‚?ßÑÐ4~+>ä‘ð4‰ù)JâP×ÔV—Dâ2—äšE"šb±(ÜJãr(<+CÏâ1Yµ‡>‚It8¬nc:ˆÉ¢µG­~L±>,– <¶fªPið˜”Ú£ªLg±\Ù)Œ€$T9ŒÚÚ¬Çf3¶wuÐo/ÉtnM‘b¤1Ù†¤CäYŒÌFEw¥ÌiPIÌvÍ6„[¢0x”Æ7d|gat.Þm&Í€&Ó½;ú.¿BòQÝtÒéƒÑc¸ÈLÚcÅàMe;p-vIË€¨tx5Z Üó=üï=—^ø9ì«ûEÚ‡Ðwý»ßž#AèÝ ’š(;Èî NH¤Ò¤ h"Ð}(/z®‚&.²Þ½#/£ ɳä?` Dû¹­b&Š»ÇëØˆ¦* ¤ªØ½Á &‡ ï4»³È“dŠ¿è3Ç9éJ6á€Kê žòr\È´4†ç6#¶¸€1T?+Æ®®!ê£B‚(l lë.2+$Z…Ä~Õ€€DîƒÎˆ2DœDÀ#r·²’s43~‘*)ÿ5Núà”b¡¨(=ÌÒ<*…Ñj fˆ¥Ï3 8´Èì‘H".´@µ¡*u6ÇjbxÎJgê¡T€,šFl½¹rèÉU³hÏQeh¾Xì³Ã2×0†¡¶V¥sÃÉM#J[ƒøÕoêë75–½Æh=ĦӸª ñr° H|—Òc(Äwõw¥Ð;^…çíw/€p•jXGüEO¡¨ÚÌ·p;·+IÚ&Í0ÌC‚Ôõ1ü÷Æ%•hè”.ˆ¶VCHcT–52ë2cs(ªÍKãî²cŸwdmdM¨#­(P)J†Ãž×Àcsƒ?- ÎÜ–Çë"÷JÈꆪg9=—,ç5ÄnŒÂ Œ~D>kTn2XR ~¯ttVŒºÌU@¬Év=vî¶eìÆ+F)$EtØrÍ0ænmlÛÆå&‹"6¸‘pÀÞõ!±ƒDà¸;>*ïcOEK•sÙl½òM‘/s¶fgR0¯­¿fu o€éVw”æÔ0z¥9®Ék¥ N€ƒz›æÖ½{ žŸ³o柚ŧ5÷ÙÂÛç)‚øØxC<ëHÏÆƒ]î³ÊÆNé81Ó³'$í~½Ó GÊ£~!æÈƒ–b$U Ú‹/ä¤úÒ$Ü“’œjˆ¨ô²7–< ñ+JÍ«¾vNAÚiÖ:Å œ¶HLJâÅx°`Å>×8ˆ S'a H¡(xI’ ûcLÀ¼uŒ? ˆür,<ÌCw†³XiVo…•›wØANò/",å“C(†–1­ ´–"mÍ»p!k®3«g>Ù•só4æ)y”$»IKŒ3 Õ¹ò†üK$Zéåg€„?RËx@~³“ÞòÖËÚ.EP’$”²fžªl$‡‘B’“úÛUF܃ŧî›è&NNÚ"%Ì!޹˜¸Êf„Ím±~h«r)_Áwg’²G¾´N¢ÈÛ9beˆŠ°)JK‹4U#Žö«ÉìûQÜ›‹ú„Îfþbl H¦Ì)Éó]ˆÁxû(ˆ5*©1M&æ·㜎lä“9W]Mû,%|zÐrà<¶wTºwÃC·EÝ Iœê›r¨¢:;¥È”ø27þ×z¯ž1Ùñ'éÊwH1ÖzCò@:dGå|5.ð<õ‡æ,VË^¬,…5Vâ1µDè‚JÚ¼?S›½p$QÉYP"Lë± LRã<˜Ýësï…¬HwÏ ’ó'r¨ªR±úM–C ÙJÙB{‡q¯vw°ˆX>á/q¸×JÀÂÚ–€ÎTL\^®õ&g9óß/¢‚Ñv6LG¼BË2Näm§ÝuKªü#êþgZr1IlK!ֈ캋\pœ¬^ŠË $EI5lfňÀépÓZ|6@2ý[ðö^³Ÿ´NT¶ŸHíÜo‰ÕI“ Bw.ÇÑ”R“—6–XƒlˆVÀ¥ÉÀc® ÙRÕ|Û”:tòåšà,Å —0çúÔÒKM&/,ÙHTÕrS{†SÎ?‹«gZ\É‹ÔÁN(ð¨éö>hʤ“ßUJл˜¿,ÚZ•”ªtNš{•Ü]}\ź<,Y4‘2>¡DÜ·œiƒ×z{¹Êœì0õu¯±z>Ø»KÑø"ljóâèê‹RP––@&”?06›FÞõRök ìâ’(8FKIƒli ­JšÜ6uFXuK%˜½•G–؉£ü\‰¹d g´‰×pì!½ºFGçË|ù†xG=76hõ/ϱ2g® œÎÏŒÀJz—´µ ¢²Õ&Ä”p$H1RàDM2¹šÅåsÞöP‹y+,™ºñó¡)H”ƒÆz¾âÍ·’hÒtw[\ZWfõ¸P¿=”´úNb!;TPÆèI¨½¸P$Zò‰ÈÊ‘ÅY=ÛÓðý¯ó;tš÷ÐÄ+[­Ò’7mK”Y‚ Ç! ¯ªcd°ÍH‹T“;¹Þð4lpnãI%£e«Æª† Øe_Gž†½×Ã9seS·W§)\TE‰9¯ƒ>G’'†°ì`ßí™Ï׸#çÅ‹uý\®ˆî@öµ“Jq˜BÉé8¡ÀÂhušj;ì9¡‘¶¹>?’¼äïlØ*‡hU‡s¤ ÏÝ ݲÊ>ß±:¨²œàÉüáb¡I?UŠÁ üŒí¥ý±à\jý<Í£q¦(›[©±T]æËÜÎìØÈï?âÙ$¢%Z,%‹+™ÏÖ¢IŸTêàߥ–å|·,“¿J:»‡ä Å5¢XÒgcßÍ'œXå“é·)I‰@޹U%ŸáÃ,“ø(yó¼AÛè’·+©I"Y¾Û JI.[´ˆª²²‘Ø-ë.Ì+yؼñÀ¹s4P~™ùØ3†i±² 56³B¤ñšø<몑b· ¬Ê“®cM¾›·¸ºóÉ9;Mˆ«jˆ)¦¡8ûÖ‡òj0Òj+ ¼ak?¹¹¬9÷ꘗ1:Ÿ#¤#—Bˆ¡Ñ\ º%%k8 ÚÀ—"5‰È³$ñÑø±P†Û/Ÿ9³ˆ’è“_ŒjâzO')ð—y¦œ$¾Á%¸‰“©=ì>Z†•‹®+¨&2“ëæÃãcÊ ;8?ë.:¢¥Âºd;§´è¥·A‡#Aª+;>¤ÑÞ{.ĸ½Ø±Z…­G¬„LD”F¥¢8E†l ŸL/µ Ô®<62±’I½Æi®æ¹ ˆ9å°ô‚ÂS˜ˆ}¸…™Ê1 yàÉxÁã•«Ãy¦¬N¡hÛµ¤ª»PÓÇp—iåÂs¨#œ€ÊâÄ=ÑX6Qý('L\EÔ€/ÁÙb”«YÉ)Ó(‚ª‘SY¸ß?ÁÇ¢Zy‰‹*¬™4᜺Ü^rAº*X¼j$³w¼]+ 4œCÆÇ$„;+ÁsªDW6ø}Ž ¥Gè„ÉâæÚ2ûM¼0ÃÍhÃ8Š *?lŒ1t |pÅ41©°ÓȬI¨½ ,2"}} Îs0A„=úa¼¬63QA¿d+Üf‹4Ç’ö\œ¬»â¿rWêR¶ì¸è!%*iÃŽ°yÏ’B›pÌCX‰ ©˜ÌFÁ̱=â…$ÿ£ªe«U‰!K²&­œ¨²‚4Êzr°©k¸DõF‘ÎB„ªÉBƒn'%Ã@ÊÄd-8êð6Š„¨²Ät5Š´”̯bêù,˜t\±¼ëÍ±åŸ ÚY»œEŠž˜‘£±${HBˆÛ¼89ø}¦[yE“[»Cl»œ{+‰¬¤ˆ}—zèÜöÐ ô/X¥™8›$ðàž[ôA‘[N«=5Ú¨™Â?#J!"\qw¸Öˆ:ýa¦Ë£‘«°ã„HR®<Ò }S'¦Âð § ðy?„·1ºuF°ÜLx‘ÀªwÍ„9?™AÃYì¥ìUSPÓ™9ë0ë(Dµ‡òÍÓzÈ–Cb¬>²CÈ}ÄS¥%»íKŒ%@+’‹?šœë Œ눦ó¯è»Å³¨S™™KרÑ>Ô R´TšÑF2fÍ-TÁDÈñÛÒŽŒôuÄlB6C+«"B¤O¼’Ik¦ü,°5žV0àœÙíÕ28™JUté‡ØÆ»làW­JU'ª ÊyE¹Ó‘4p’yÍ Kö0±[PÌì¨ ’1€=œ9ìÊk 9 “1¬7¹ÄÐ<™Ä ¹Œæ0áã5 ˆY#l ·J‹Ï%BÆL`›èۆ壱›²8`dR˜œœ$rÁ>˜DŽ¡ ©§Tjô9š»Û@µ¸ÅZmTS²VGä¨ÖaƒIéʯ;cSqÏÎ3Ï@ç#;«Z^9D%VòAÈð±ZÔ(JLM4Ö%°2È÷°j%ŸÄù™wÁt…ªbaÌK©Cy/\€ØûB±ÝR+2¸#‘زeÒÅÚŒ)½³„¸M…¹’¹“õ‡ÁÆ8;ˆÛRæ!r±¸ýŠ6¬ˆÊË8Û¸}$)e·ã2ŒSø…´–u¡ÚûøStU(ëѽÅG1ÉÝ^b½ÁqÍâà×B£­ 5}‚“ZHšÕé®A,¿ùÈ-O¶\WÚ²ÚÊP¡ž]€Ü›‘¯€Å@:—˹‘”DÜ*—¸išˆ=ͪГRSsˆ}WEœàýêKbÑ´x…„¼CÔ§«˜¹RÄ u>!\LPõôILŠ:q\ÚÕú$x“HÙ(³†𣵠ÄÁ68ÆM²ž»ÿ=³©²2ÜOË„Eýv•ËÍ|—yúìö ]Cc°Ž؇Ä”Áƒ@~0¢k„ Üü¶‹‹Ržášö-¬ Wu~ÓRÒ‚ +­t 0íԺ®M«ùˆZbÜ ƒæ5βÄRˆÁ„N$©‰6 Sróåƒk¹áÕÑ_ºª»œ÷È0ò©U7×dT1Ä]Ãt™ÝmYøC1ŽÜC³åÒZ Œg±O,ãMª» ÇŽÔCO¤P« ¹®ã,ZôòSs‹5 [=†C .‚œšg;»Eݺûë® |=Aª’§ `‘«W†1”E(Ù–®DàÏ •4¥â½6;ä<òœ‡Ì¯"»…¶4¢®ôܾ0»ß=w3 †¦°µü!D|qFF‰ßQêÒV„ñˆ™ëbn\\™–Yë4` Úñȹa¤-§\BR¨CO¨ÂàlUTF²9Ûø†¯¹1Y‹NH—‘U7@Šf`ÙC£ñe™<~ˆ:½‹1¦ˆ“À ªaUaá Uª¬ÀLp~Qâ¸8BwœÖÓ‘¯ÄIJÎ@Ä {ãZ®•Ƀg&<òœkÎÅW†ZÄ‹è‡Ì·Ùë·õØk¦ÇNV¶½{†¢ê\šÑm©¿.ý­ª”i{g¶œvmá¸K„ak[èueTbp&± 4`r9ç"”3hƒ—zr°÷ ÖkÒ—Ýöé?Vc8,š V,åªÛ †V"_ûÛ[Þ´ìŠ"ID/¨ÃîÓ’›cWT 6¯ÔdŒ­›ô?zÄnúôL¥è_pÏ!Êå{Pò@{ðƒÏ²£Yõþ»Îm_K%OT×P^1בϢ=ŠðC ³ËPÆÏ­Í»©~’OfhªÄ-kæúRÑ¥™L–Z½¢¾§.tòL’ˆZñW§”€O-­&éE˜r_C`Ap>‡Ê‹Mœ«ç9:± °4jjF-Fb‡ö¶˜MõxÍY‡ÖàQœL4Kfa®L:…ÆE¶Óî%ÃéÐÝøbq4—@¦5ùo‡#†’΂ªÎµ÷–9¸oÍ8þ´ñL&ë(õîóˆ^e•¶²=º#‰Œî‹#ëlÒ"*u&³yW\/æÌ‡Ë˜‰¤WWÛ¾-ytüìç°vÔeXfÁš Õ¸|;Óä–äêS.úŠ]Ô¸¹ÆþÁEÖ`é!ü(+Rf+¤Lds—{œ “tïlνɤSí¯÷C“ï¶¶O.-~C˜aà€@/è$ „a@8cêD_ñ0$UùŒ#@(äMÿ#Ò z= CpgĶ"ŽŸ³9TÍúûœH`ÓhL(?›A¢ I "mAI#R€c!œ>Á59´Æ=}B€°Š4Îc?ÉbsjU–I'LeSÄbµŒA®V˜åb=C¢Á$q©µî›sÀYePi4N•F#Ò¨ôÚñ|™ËàÏ\¥‚cŒX*1éŒÆ™…Ùa€zèŒLgK(+]X„YoÔùL31m~J¥U×ìÆ_X¡ìi[@bÁ£‰Öªðè4¾û•]¢‘]TÎý°K_Žä"£j†U¢qŽ{ÿu §GpרœyœŽ{µ”½=—ҨήrF–8äìëÔ¨jŠló·HþŽ0hH¿4Òä»J^|Ãòµ@ À­ˆºT¨±é#„’€ ¢· SÊCQÈÒÔ­î8‰ 0í+PB ¨¨H«VO`ªŽCÕB5<±DƒJ âÅ£ŠŠ¦¾Gñï]¸ûÊÁ!“‹Ôà[½¥þ]DpŒóHV&³q—£í𢢌œºŠæg¶øfÔOÚ’–‘ê6*õJë,ŒÄ)×Ðîôˆ/çú0G¥¨³¥) Z‹Ú[Êó@¬ãA€škЏÕí3hiO1¼~È~Ó×+ã"ð%Š4ò^ìË££ëɼ"”F+p•ó€2¢›Ï*xC Û12f×$É%êy£•¢¢¢ÈQý¦Cæ`I°D`uSå»7BE§Å!~0*¢˜[N"¹r‘TUT''¥>¯°°Mž(ý¢gr#Lh,Œ%’¥&É–«*&HÙҡL¦þFŽÐ °KQ ØÐš1wH™²bc/Êš»îÔ/™Ž’Θ8”Ä…Y*Š?ŽÑ¤lˆ¦Ë#‹_Š!J‘Õ*šÊ—–J›B0;H±~N‹0I•w¯óíŸyAGˆŒŒò¨’<8™jô!"hΠÅ]mܵ`‡#æb±¶Ç_,œ´JÅ?­ ÄUŒ¢!Q:â\v»5"´¨5·YèBgQ~q@]™Ž³ìúósÔ%M²bW”Ãï\\#=wRyÓ˜:‡ñ1+ Ý0“‡t×q­Ykt+¼{‹Ö,rK #H X,}ÚÙˆ—&¹a­vÌßœYóûgÕ&w/Þ}iî2›QX&š.6ÏDÏ/ˆ üQë¹äÐÐ ÏséåAg­­‡˜ï¸¿kئg²h ÿ¶Øúyìc‰Ëwwp‘£ ·ð©¹Ôa"õ¦´)tø$4t´Àk„TC¡+x—2–7³¸ë;2 .p·¤ñØ"ð/ä9••÷à?_x²^Y $[kc;uC±D(íJ‚^µ=Çq!¯5!‡¾Oý·gºFµâÁŒ¶t^4@n·¸,ø–Ñ ª¾A8õ”3°<òçK\õdìk»#O´ò›äg|K¯¼ÄB$>M  ïÁÎy>t¤†××ffmÈå­ô8iZÙFfrϨ²Ê(B jú¬À놎lˆ¬Ù ¹ãDËÃ@©!üªAúÆê&ÎæhêZCéd@ lÓ¬ ¥©ì¹Gvl ’•‰`PFn+Ü8ˆÐ¤@ŠìêÁþVâl³Â¦c¥8äåb, $Õiðjí^Éå^X¢l™!ô…¨V8%þŽ Â”ÐG HûðÛplÒiò’®,Î,Zâ´Š%fidò, dö¥å‰ph*4Û‚p쫚D`e À²Æ\·¤Ö`UŒJíÅŠ(fа@möÈtä†L'‰øþ‹ØêäœI@&!«£îŒ°¯ )ˆ“©Z”’õÀ€í÷ (&ÒA ZìÅÜæ$2‰ðÐ׈žC©^Mä„6D²ßé_ªh…:ÑÍo%Æ‚h¼jq¬¼ëlkŒ6†Ð¸iăe Nè.en\áæðïToJëj6Nà.nc¯8#ŠÄp’݌ƭ ŽŒù¥c ˆó©ôCOžäÀ T²@!!c(¬t”‹.º¤”üvidÌ‚[hãÀ%ð @qÕìïâ"L¬àM#qÉ[M‚ÇåJüoèù/î½Çç)ôÉ¥©'x’Â8¥, ^(~ÇÈ ¢JÍ1QÆ.CúØÂ±0‹ˆpÊÆ‘4chZvnÆÜâåqš'邪p2óI^ù-O ìâcÏz šá.D+H^ ' lƒx×Ò\-ìPPôÈf‚Éy#ï f™º¢D0ØÎÆ‹ð2 $IL´$Ї¨æhêÝ ðKÁðÿh¾¬Â°!Ä«)©[0hé*üÈl³H’ËɪvÂmvUðºœï@½ËJcNU 4.M¶Òì.¬ŒV[ð~×L™èúç …®Ëø0¯h•ïg$Fã8Èžúí}‰ó/ p½.ŽãO,È¢f•©b5 $ÿb´¿qô ¯´'ë /ód?¦žk-@w+ÇæTFÎ4öÀ Œî2¼.GFK>;Nx†³Þ«3þÒÃ"®« Ž} ò ŠMàpˆD´Ôp(—3øûëÀidÊÑÔ!éhÌÈÁé· ø7EŠ^ϧç RXç¢<­`HeFÍÃN×JrlN:„³ƒ)$.C Á7”rMlÏ$„´@Ë&f ¨œËäXŽ:mÆ|!Ë>MÔøÐtŸP¤Ï(ë±>n½ùK„òú†Âj‘Zñ3$n03:04Ä$k/~å3ªO‹k<’âØË®´nì°@]ÅÜpï,¨ë*Â޹*ZP¤”dÅKR†bƒp´p,Ï(ÄÿÄän%fæT–´¾¢ãpÉg 7«M9 Û‰Ç%âMêéM‘¡Sf(Âb¦°¡ð¾$òiåK* ’ ²Ït®žASs*ðAþ÷¢~IMÖ…p’Þ‰RÛ)®!ÒÌ,ñß#¡X”DŸbB5Í@CÞx4òþ«ËÕ§¤OÈüíG®¸3Jn/NñÆI„ô¹-Tpœÿ‡`ëÍ› =)î‰Ô>îðÕèHòErf O&LƒçNyk F(W#j—Hì½ǒ €dì ðêM9ÐÐMzk”Î@B°O*vœëJèe ;‘P€önËêõb¬¼Íµ† ÃîõNKm"í_ï–µ¥JZ‹áUîÃoƒëÜ©°wM‚bMãµ5õñVá‹x_¨ôð§ ±VÏ,šL©œñb"+€¶ózvP¶Ûq>$Ï «–'—  ›0f ÑSlpá±Á9ÆÉ4ˆN¡þP¶5LËÜ„C…+A¯ Iõo SN (”Ÿg‡[§YS™hýWMH1r½Ò`0· "’³"+J‡EòÄPB ÓJúþqèãa[…¾l‡‡‡ÝERr[â£K‡Xc¶Í/cˆD¤Ë2bÁ!§ w‹6ñ4,ÂIæW4§ }R5†N“–÷U³Ÿ*iÒÙ:¶µÒïöOéÄ׳NCè¸t¥rtWŒ7~,@ñ3àÓÉú"m×§AŒ!`rEn;PìÊcO)Z×ÑÓgPóváè1#‹ÅQu>Oºtø-)ÒèÕ÷fdÐ# ˆeóÒ"-t¿f\Úr8îµ÷KJb‡çSq¾V.e'súã` ØúûÈNþL•å ú… pëH[çXŠ6fŒJÒBÎtL%S‚øwÂ~Ë-‹–_7—<¾m§OM¡$÷”´Î˜Õ"qdศշÿkã\§èlS†Ù ¶áhüOæ)QuŠÚ ƒw r±Ò¼”ÊÀGJ‹ò1S³zyþ©xaCÔž“{Ž'Xˆ¶‘næÌðš1 P©ÙT~r¸›v$جËË-F¶â²íÞ&J¦¨Pö^ÎôJ³“4,L£¢žvÍr7ŽÌý6®… C(P¦–¼ÕAöÏ‹¦bè§ZOèôš1ÓbtLEÁð„ט­¡ÿF(­,ĸ—#Ë$Û9‰•Y˜÷xD4¡EVÒòNÁ“|ŠÈ‹õÌ5™VÛr¨… g­¶/Õéuq…$$׎•Æò 7§ü!kž&ÌÖ[ø Gs•¤`ƒmåS¹Ðxxä‰ðù3z„ì?‡RâeÙ+†DM(Ö­˜¢³ Lš*Í®ÕÍŽ+X3§u««3)è~°÷@òž;†ur &¬ñ¤´ÙMc;€±–Vl"&ð#'Ž{—ùé€D+0”°rTñlEíD0Ót™]d`~kÈIS0­½“É~ë2rÏÇ72×?s(³¥w„øç™)hÊ/Ë)3w±X(ŸŒYm ´"¹½4ó&uùíhµOô³`J—­‚­) tè,‹údòª¡™«§4À‘šðẔ4…Ýr·Ù]¡ük73{°„âwÞ0 ¶håÝ$þÛq¶í•>ñm›‘}‹pö#`Ün¿rW*…vd½Õš»†ËÓÜáº+/°E¢%§tz @Œn;ˆ:Ð%¶`NÓ`Ï0~õ•ôyZ¶ÈVüÙ%¸¬©“8?"”k|õ .ÍBƒyax•*¨¢„·9Î;Ÿ9j  >ß4-›ï$ÐR¨òl¼¨c¢‰Œ4•«€ÚeZ©$Õ6ø«¨tí³e6€èanwþ×[ìþ¤ÊÑ3®!Ôúí³Î3«½oIµ;[LËgœ@À®ñ%Šæ„¹}¦\ÿs¶Ñf¹$þM˜Ùu;V‚q¾°þCäÊ$&Ðg*7?ÅIQ%†žðí9y·Jʲ·VAô$6ƒ›Âp¢‡ÏOÃ\cI1/ |½H[ £¸åú2Ï;P#pD¹%.4„­Xj¸<¤>ð­ÂV%Gz«wŽv÷7c‰;,7ƒu;²á‹“"œèO“KÒÃï þ˜ÈÚÉ´?³Õˆ«h;€•¥>†«…C0cr2 ÅÅ Õœ;B^è0ùCTM|¦-r÷Ô|—wT/Ï4ý#” µ¯“ÀÔG ²”üåä©uùT´AÓ‹Â)M.ÐEf~Î pÛ8œ•Xr3uìóæãŽ3áͨÓ¢' rcB¶‡I 7u¢pS¦ž€,¥7\oGzÔK +w'ÔQp‹÷ ÓÓ>$Øök©j}¦i±pÄeؼ°Ø>Dò)Pû&ŒtÒógÍØÊ'Â=rK½À ÊäSÌ®.u:,¦Ÿ¨ð·ærê‰ôkï¼7ç¡´íä&3ew®@mx‘Úéõqå¯ÁõwöÆrRœï©Zpõ«$ËÝ·Ô:š.üúWÖ«6¨\-`Žlç2â´¶¹·<(uø —º _\§Hý ¸Nðöí‹-r•ŒôLu›rÌ1;Ž´At=kM˜¸|+QÑ,ª÷™%™rï"ZMï ¶­ñŒ?¤Om‰S‚Í'³$øZã[|½æÚ",К-Ö`…¿ðÀ‚Q®#Ëâ4 „=J³9Å/°B'ÿ{9<»J»œ¬ÿ¢_±©mó¢‡NØÈN€ð±3O-„ö;¦øµŒ å¡ñ„7¥†vÆsø§ß“u¯_¿r¾÷k_Ö ê ƒ>!8Pù‡B€oø” (Eß‘˜ƒî8E#/È“þ “?e@$­ý-Ž>á€Y ¬ #‹€¥¯é¼Ž)#“OÀ3™f}&Qåò9ÌxBM$3¸•Iÿ9ˆTbñ¸äŽ!TŠÀ¡Ïš8!}W UhUM_Oâ‡ÄÒPý]åñ T®å%“Hf49N1ÖŸq (oT›ÏñqIËß( ËHiÀ†QïLÅ1º4RÇr»‚$xxUšüÔÆmÑIüÞ{šbåóy¥ºëjè"óù|þi™Çɤt©Ì¶oË–ÌqZg{uö\ˆ•ꡜKz2‰¥Žëf›â';> ›Ó&ÝÀ¢O–ŸÏ ºä¥²?½~mY…:Œ‚$—¯`#„Ž.©hâ%lù;‰$)˜°Á)[”.­j걿IB®Œ¦éŠÂàOÂt‹¸©k{¥ ¼çCiB¸ˆ!H¢ê®ê.À Iû>§¥‰j(°©‰úë°¨dlÇ€50ˆªØ '’›«¡,6,Ì¿Ë N¼¡MP›®°Xº¿h´W6êÓÇ1 V‚:‹tÚëžÉŒ·¢ìËÚ¢ ÊÂúÍHº)D%Èê<‘®H0)Ÿéúc%­é3h ‘ý8Í‹jÀ‡&+ð~±rã’‰=LlRœÄZ$Võ 3€iœ2©Ñ¨0æXêÝH‡õTì¨õ‹¢N„ô}S(e„=àC7¥¼€“Ï4cɲ‰¢cKÕÔÂŒ£¯±Ãáv€ õT›¼Í ÝtY±=rˆ.¦Åû ‰Ís0×òëÙa€W2PŸà7(‰)md–¤2D®Ð˜š3ˆMÊrš%øIûG¹wÒT LåC)âr±¦ŽjZ¹a×Kz WCû„!Žö(¢Uõ,£W"‰Ñ8&—ÚQ»YªF˜¬Ë¢P˜áǫ›¸z Ÿ¬ØòV˜§:Z‚ð!Wý´”Ql\“gŸölÒºÛƒH£­ÚæÇ'é–[jªàúü_Zïgò ÃN“ˆtQ×zä¦,k hzñè…°ÌÄG绵Úz)8&GCB\>…k $oŽ‘œOÓi}weÒõ„¡½CN¤Ç»—„‹o:­DןV°À'ý¢ß«ûQû¬lV¾½&¢S„×¥#2´­/ËÈ–~¬x¿ ìã=FYÕÙ €wVvDµé–kYwÙl]æ‚]„R·5«5+ñŸö2//ªì„Ôz&…£«áþÞ]Û`#(¸+Ìò^"ªiÄ1‘•BhŸÐ"êí­Gp ‡ãƒ‡Q ¨[!9+`D´¦+–¨àOúÄw —¶¨``ü&…™z3° Ì`|`ªèŽ4X \BzCõM³¶}›9þ"/|/sÖó!‚B¤yÖ‘ÃÆQÉÉrF0tŽ,·êïYÊT1m¤¶,×°rS“! TÎ2⎆¢@ÿl0ˆÛ°FÛ"Êÿ[cö!+.]Z™lYe™ä•EBbáéj2*2û€Š“$Ï@Õ¸]É rr•qwôß  €b.íÐøQ€!/4ð|}K*åŒp<­¢Ãs Yx‰98+·C‰ §NíÌ34B“)wpîí·ÂÂRò$b¦ &o+BhX]0ŒÃí–8ã&)yka4‘å8Ht½oîEdO!ó"+”'í$~¶g¶ÜÙÂЂÑH~½¤Á‘¥}%Þ4!þ\¦ð {ªÑ ±ÖªI{šQe¹k"BŽ 9–­ØÐ§fD‹1mõ2éÈŠÜM1¹.%9 ÀþW ø*ç—?_]¤„pê(µa4SO “¡o¼¢9cuD£&e>ÄCZbÉÉTzÎeQ1%’°HÌô«G=žur¢ à‰oú+&×=JdOpš(€6¡6úËhέ³xlËX‡pg¤YQ4À•º Nêª3ŠÜ%Â_cÜö@£j‰šGökg",«¼5‰ÊÝT§ÁÞ¶Œ*§“Hç§ð$þf·’˜­ˆ“Wó,@§r?•Ü@³lŠ·w Q>]}3Û>”õ´©ƒè¦7«§ˆ_BV²¤2û:¬Y—F/p Bÿ IÔòãFYm†Ú¹kjZÄgÆ7*%Èõ.{·ñ€R͉k¬TM$RÒ{jM1á_²÷1ûP;›^@&·‡v‰Ÿ>m7N±Q-©I0Þ€ ”[¶¾„¾V:kø¥Ý[©wp­-1ƒ—5u…2.hœÓl „Š>Ê„[¶úÞKsûªx{@»·dæ¤-ô½-3 6¼°o«£¶}Ör×Hãf[ñK#ÉAâ<:Ÿ6´1$6þGÈ7¡/¶¶{mfž¤í+µó5Kö=XI\enÊû“¨|t£§õ*¦Þ$ÍÒÔ)ý¡eNC".´NbÅj&<úV†gQêÍ”«SêqDzþr‚ñ/kY·>”³V>G¿I3ñ²M8©×M‰-é‘$Mµ£jTÐteÕÜòêã`B\¦/_Ÿ]*Ÿcï1 „üéÖ¸­f¡K6Ëe2,I Ví&ui’g@¡ŸÜÎÁ±@äèkÖ>éŠV§¼Ø7\ÙGëZÔ™ƒ’Ž]3nƒ~2õHV¤µ|Zc·´>®Æ´©À\+ÝçXäÆùƒ>¤ª†’cé;tàÈì? 𘙙âJÊg¨—à|Åib*N¯Ì9_×}‡ K?æ‡7ÂH&Ï#*Û(̽ú©¥ÓÎh±(„!"Ǻô+œ¡t0, ún/“Õ³Š:‰Ë“!–ÂXÀ¶RQ¸Ü7+¶¨ãt3*úÞ;ó¢šÛ7jë>÷3š*»6œ=¨ƒ~FCu¬YZFrÕ"jò½ù½IfÁA½4#(LݾàÏéŸi¡ ÄW’Ï|o³×•^¨Q‘ÓôÃ?A(q߈€°¨šþ5uWIæ$ª‡µƒSÓ‰¾¨êNÌÀ+ØCD’ùr¿ð˜Œã\‹ºò³A9Ÿ 0ÎÅ(4¼ ø¹ °΂ÛSüöÎÓ³Óp…>ºª˜9Z>í$6ñL´Y Dôž#- Í9Õu6¾ECÓs­³ÚÊèéó½4:œV]XWhç!­x>1â5”+°Õt;€‡¶ô Èm !sŠªy/´áŠ¢ Å6+cÁK¨(‚z,xš(’oúÂë­[K0Æ]R‰1JºPy¶sWõ*žIåÂ-[‰]5Ø*!„õÖlHðHFÚúƒ´íÒ…‰>Ð5iB¾«$6³[‹‘Ô¤ô£Ü¥J蟲 DÜ×”Ûà#ÚûR­Ÿ,(Š:¸¨˜ÌǜԈ®XUÛjɉmª®P„)ËűXHÖDC?„ñ3QÀ.ü߯-®ÀqÐÒ¹®™XHÉ ßAæNt0³Ò03™ÊCå˜8ªËñGû5Îáõ ¶Bþ_PÖž!™Æ•’ÔðÁÂW%¨„xŠÀÚšN)Â@jU› VDÍŒ´lW»}§¥¾ˆF@ªG3ž¿EÃQŒÖ§õ‰'Mmö)?–ÄÖÂsð¹Z—K0‰P-W¬ê÷–’êÓl–ÊÏWÄŽª²œ"&Í¥ G‚ç½3µ65 ·ÀßLmÀ[X¦H|áë1+ÔbQê<Ó’O"ðŽY¼ýÃ2hº „Iå–ŸJ=âÑ–Ý/»‹"!tÕs¤».}YÒƒÙF!9T 8›¹H³)èÄJ2Õ'õ¼*yPžÓ-P³Eà ¬Ól¥J¨} ôY«¹\‰ˆ¹øêÎF./ãýBRå!ÚÔ­ú—Å£ £™£ó¯°±¿¢Z ½5–TÄãU*G fB5Ã÷+´é1ùæŸ:RÚs7u+Ò× çMjéÃCL;3ÑV‚*Å aý‘¥+ªyMÁKát· ̼[FÀ‚B½CIÅÿ: G…-XbÆ\Òˆ#ŒËRLxÉeåÏewÄY7žSÝô?hTl\cº#fÚYÄ"ædêÄY:X£ÃÓˆ#¯Ôýx´!вq?¿<ÚF%b•Pô&Úž¡‹£ŽI(\q ®AÓZD8\§œ¢!>jßÝjËêíWã ΫõEÃÓ7}ö¡Ú=ÔÓýéŠÀMãÚ„N\É^'*cNHÁ%nAÊ;|ÙQ˯Ãd(r¯ýÉ3 BÁ¹Ù¥64*’ýÀÓñ•v—QŽBpÌš[\À cÑw¤¬W6¤‘2Ó¯¡‰Ue#X@‡qÊ]x|Ìži*¶ ¼´7 ¾k‹¹ «¹l(óg¢¦˜Ö2ÜIÛ)ˉ¼äÜ)gKÁ¢.µ¢£©­¬vb‰åQ¦ «'&Ô|#ÚÚé0ÙÊ.zëªz»H‡%(žÖU‡Øœ¨œ‚×PŠêE:YAóGaîT•é‚".GcEç,¥–¶å }gF(ÊIY3VìS2_ š5eë ØÒª@¶*&ÏJ']ŒÈûô sb¡Ú‡¦I:~‡¢%Y4žîº—>«;Æ+B?‹|ªB[ |‹(‚ˆ1.]^u5~qæ•æ½ÞæßD5x›Ö@¨š&“ûCi]ÔQúI7KŒÐnˆ×ÅG¼[i°+îÄý=·ëÀ¨ÌZ pI§TTÜ9æZ½ý¶‰p›kc€ ïÜ =ü¶`ÄJéÕѹð(®nßV極£ô&Zj"LØq/¯ãý‰z‰çÒË7º/¯2æ4âê~r¡pÏ?izÔ¨4ëD‡›òBÊQ6§ —¿·.{e+©¡ÖKeÐqEÔ5ëmqˬ´Šü —zþ2N´°Ê+HÖ¤,¤jÖeN14pc2ÃÇ¥• &½5BÉôâIÐXJoAëê› ã[yb7VyI3_X›WÊ×LB†-w^Va')‹èÚW ®å ÔèÙîF²[0Ýù+Óá7V¸•ví¤öÛÍœÙ<òìЇ^€|sÛÆixˆ\ [â }Ì›r3ÊìÜÊ©ï»#âFjý±´ïGnf‰¸¹=ŒGµX“!ùî›ßWvßÛT6j ^ø*Õ¼½‚V×)¼a/¶WFˆöÈlt‹G]e“j°´Kpmftüc=û^ÜØ‘«9Ó‹Wºw†Wt è¤^¤ áKW}0 ï0Ð̘®á¹îR‚!]Ön•U^v3ÓÍ´y²Ó¼9[GVøÉfK„·5T$¯,±(!Û G¹Hm"»û)œÙg‘è½, ¾‘‰2Zí»¨:œñä±C–”y-ïÔJJII¨šd¥B?S¥qwÖ…eÐé¿÷ôtÛ/'pŒØüÐႳ¦ŽÏ/(YÒi,Ð wb-±¬Ç¹ßêˆeÀð«°j¶Š°¹_z]LyšßǽuðÖöˆÞIôÛDP76“&•¾Ò‡ÊXÇÍy.·{ \$úˆ`y~îåM²ŒÖwÆ2ð—îT`ÿl%'PÓŒäƒùÉæ®Øc~…x“ô«¯Û¬Djÿˆþþ‚? ÀXD$ |C@pø„ýŠE@Qp$d~ÇcÑ$l}Éa`3ò‘Kc‘ÙâCxÃçwØükp½MVêýŸé®¦~ÑÙù¦ªÚ!n4è¥îäŶîq¢äÀkT¤¶‹bô¸`šÄ}z¦VÜöÕÔ¡ua"ªMK-Ó‡}Ýù"!Õ VÚ‹·üô‚K>H½ÉLaþö ÞâÓ>$éËU¡oéù}+Ï‚ÒÈÇ혅Í*Ÿ…’®ª´“’”ÌÞI¹wŠAõ‘—à…ÀQ²$FœAF}Ñ‚Ç/Ía¬´`””úõrqUD»DR~ˆÑhgäþ%Àc¦¦àÄ]^°yÄ䬤N<37Œ…Áv# Z‘H,4õvܧšÁË|OD”Cøm ¹øIq$™µÄÎo!£ÛJåÔ²ÁhÈZ–ä^äÕ¤3˜²Ù‹Ã€zä!³’RjZ ç ‘®R’¢z“¼d¦ž•`T„y.ä™À„`ãËT£“¤8‡§I@,A$®T¨äW,ZÒP‘ùƤ^Á¤Aj\ÅN[ˆÖúÜMä–>9hZú=p)¯=õ)á[vh€à ·\¼ ²$å”â@HŠ¿Ž±Ò‚ìæ¨ q"i ˆ€€€6àOø$ „?¡PWì6 Da@V"|Æ@±·Ôt È@28{þþ’Åe@ <žU!ʤ`¼^:ú_°dõí?‹Ìá¯Ø-g$‚>éSš6#˜L ²º¤Î‡ÌåPZx¨¡Éæð4Þ† ´F_49Ì^¹#°Â­‘¹œ^OV‡Ì¤whTÍù•NdðY…ýù‚…RŸrù Ö#-…Wð·úª/0™ÎßxÖ#*ÃI옩§$iË4Ϊ ó"ÎBX¹+SÖª¤nò:Í&<ÜÉŸŽ‹û«ñÊå$i;¶=ˆ#lûËà¤Ñ±J\€†ÄÈ’¯ÃI„Hã€P”›Ïqêþ¦$lÓ[7ð’á2¼“(0ª&;jÿ)&tãÄ¥&mÜÇ €”SÁ(«¾Š·'ú&¸Ö‘K°õ=ÊÓT‘Å/Aþꫬ2`â¸Q„”’ºU’Èý?nÃÞ‚K’˜<[ÏR €‡.€pÔ !h#‹:C“2`Í',S‡GÌÊëå Ì‡íºøÊ–;­Y°Òj>ñ¤2),Iv^Ç H…4ÈÞ¨´,…ZÒ ÄòȪ”u /ªì²œ£k¼=Œ¥¶f>Z¨Rr‰¤÷´ÄÅ0ÓÝø(pÿNg.Ýd¡ÜH-'oí‚`d“¿g¼gˆàr•žÎ²!¨Í³vj¥(tâa FìÓ–þê,⩨u#|‚¬I|~b-{|;㨰‰Mçzž6êÞ øÖ,ƒ|¡×`&ßY2~ÌJï ŠÙ[èÇÌ[…Û‡rõ<£¤é¿IÇô|Ç[gýõÎÀȚɴÑH§.Ãg°²#`VVÕ!³¦(­9óCãåÀ {Óçë œ¦ µ®ÇXÚJ²_Qú™¬™ßÕÛñ´ÅRJ\àx©m~†ÒGÚÈ›#¸½»q°­]{]B÷JYP’R¸ý+ääµ66dÊ\úæIN¥¨©Ç–œ{wl2«u¤Aœ³éYJ}#ÜÉSf ø–Bo“°ÿOkÔ¥"”\¯±J8ev?çNòQÑí]¸€3ê’ŸYD[„!ð.ªëT°ü€ÃøÄÓ ø ºœ-Cf*+eD†—#Ú7ÑHŒ‘rÔßÊ:Â!í)™’vá|i%jp›¿ã°öš43YÀ¥h¬á•Pü\îGbÛˆŒl#ªµ¯9(žá³Í‡¬Ap%d¬Ñ‰9Cu$N5T $O‡êùE¯4h ü=’‰¹¨Âb:DÚS0Å‘7¢jáZì1¤D›µ5<Tä›+§<Œ¿åzûZl:a§V¥gLßÞÓTÊPí”4öAK2 TH馸7‘׌R/Q¦ÔJ‹@ -GѰK ‰Àš‰ .qÁ1úY 3y"/<ÂòV£Ô݇Å*¹ùP˜àÿ|‰ÝñM²¢æPÃ=Î-b>ŠVë;ž3éëP“²ö×E *Žißfꤺl„eôºö©SƒþdTa£vlÕâo@ÿól݈ÙÒsKîlƧe)‡IJ{ô[ÊÊ¡‡ÚšpF$!6§mEåŒB£ÄUÔÙI@?Y œ3D~´Ù¼XÚø° â"Ï5LË)óA[²uKjb{N55V$Åq³>R'!±¸—=‰ÍoÇY¶9¦Œ°1Šà>í>Ë2o?À²„̵d(Æë•g½~s5S Pö)̦=Ϥh?“Ù7\˜]7q­±óJò;^eúÐ1Ë…·Á)fh y'œ(j[æe¨ÈQš¹ÇU9[mËž5Ój´È¼Óä”ÎÖQê¥y Äöq(NuTRlìeêï»ãîÍ=Ú5¥K}Ëe ó}+’ÎU""ì1“ž³É¶Â›‹SÝË 6æ#Iù‚®¤®¼Œ²tkTd kêgÕ |"=0Ð:‚¢6ŸôèKq¿ËÁòûuC,µÚ*Ñi…D9ñ$;ˆ‚NºDí†u PâÒø—Œ_FVsRobz9E¹´ ]ÓT‘Ý—YÝ<{¥D…Ò‘Ý)|²F]³#î$ÈÝe»rµGÔý&WL’Gh¶©äcÕ=¡­ovÊ}û«{uûo`›F™K÷ÇN%°¶‹ÿé,Aqtk>‡³åÔâü« _ÁùÓ‰Û©1\Ó5>^FȺø’Wž}>Þêà šëËSÀ¿Ò¿8‡´iÕ n‚¡Yèe©¬,nc°:Mº6q„U…+gÝ7Ÿtïxó°¦´£mâºg:Q€€,2ê‹úVbóU­mw’GåEÚ´þ|õ@8íO€)Y¥Dõ.<* Œ ê˜Ò¢ÍbÏåðJÈ ©Ç .Ì‚S† ?bȈ$@˜KŒ°ËŠ–‰2-º³jâgz݈0ñ$Ä¥ j‰âȃ‰nniFôŒˆCÍ(Y¯Ò1Åðˆ%W¢J3F ±lð‚FŽ×îí‡>ƒ…LhÅÖ\&‹P@x*.u#lnN´ïòüèDаù'@ÐHpINöƒä¯l6ʪ:­…”ŽM*M"–íâä0š¡¬I `¶çZµ"RÊŠö´ ª’+b§+’!®²³Ç@jhü>Hö,Ž\§š+ð´8¬Zï JÄRî ž¤dÊžOô±Œ´iMJð]še‰Öp1 ¾ þ€ bñÙª®ç1œ`H—g68":¬eЧï&ý.†^=D¬¹LÔœ)¡±êMÌœÐø©ðçG&5£†Å>Èqdó.&ËO$Ë"ñEebTò=Oe&”È&°ôË Êêìµ°~[Én¨2ÊÅÈtïýå^nÈCJÙç´½¢W ŽŠÁœdà ©1½ /5FœÊéL@»®<eð슘ò‰õU!óEDÔÎÌ!«jÍòf÷â!Q(Oãh^`èbÔ¨5Ï=j,úB”§ŒßFŸr=ѪˆòÌq*êþÕJ…#°Ú(éÈi*?m¶Ñà |«|tŒ‹ðÔ‘”×À h"ʬ8ÇA!fš„IÂç`eƒŠ‰hö` îÇγJO)„½¬yÏz$#ƒ‹´ðà½.†eÎϲ”=ÈÑ0Áó$ål„gp>Ïåöþéì)@7jÊ£1¾ÚAöˆ0p#°$_§ ¯êµ HVcŠ˜«XyLp¨ˆ,æ#§´þà=Æ›©„GPDß 3N4 -(JOVMÂJ|†Å24n…â¥Ò¶R>ßRï.ÑÎ~â ÓæÏüËs”a‹0ÓâþܸÉå”:±hâeI+K´· ÎÔÃ# ¬ÖVcZtg¢'ç€ËOTÏÞ‰rg „ÊŸ¦]E€G.ȳ‘;'šW¬V`J@C Of¢ˆ#R©Ü$£†ßºäíéË–²ÑÿBªzÊÒ„¢ëÌ´f9kR÷2[?£îe‹$&eº’ ýEpܮǪ ´®èèfÍ%CV)OŽ«s í*)8‡2¡÷Ig45§¨— ÉüTô"#±M‚7ˆòœ1ÄâsöÄ2^´…â:R~!¹“ ë‚ 6Ä!*‹pÆM%pÂ$tÏHÇ ,ŽlÏí’ÉgÒ7ÒËMn”c ”4ã’L± m"Æ*ö£®×EÎ8ô§“³ê ɲÈjÏð½b²—4l>Å&w„”Ï~a¨ö:SÅ6ÏŽ²Güõ“úÌÒJSÒ¿ ‹ÑTñ Z` *e!Q ŸNx°/ôðÌìé t ŽªÎE*×Pð}(î©°œÕó|#4Å1iL²pÊ# ¯L§çÌ| \ѵ j4 ¥êLÂ2Žˆ÷I$&ê2æÅ «£i-§Ú §S2ƒ¥ E9Uêò}'#+蒱Γ?´y ¯Î”U>7Œ3b`гAŒ”`·9jÍ%r°''S&¼ ë+Äá\Ði)nÌóÎò¯#¢?AÅq«ˆ%qÖûf¨Ó.Ý1G=Ï,bf6ÕÛ'4R$±ÄxvAGâ”u+óÁúŠ$ÝD ¨ëÐÍȯ*®ó9jo2L (™Ã¶Íô:RTQç!W Ø6Ë\ Þ#âÔ>ô‰5OÀ>ã4œ*b O30r¸&ñl¶“èϱ÷:(ÿIìÆÜÇuñk¦šïÕS‡õ\ü¢¾5¦É ¶«›‚*Õ€}¯,ÿÕMn7n—莃 1ZF–$)õ›a¥¼Â9ÿ‚ 3Sˆ/[YÅMzìLªú±X¢É‚ËôeT'C‹Y]Ê„ˆ©ÍaŒ‹gKD–ì1•ç¥>–`Sýã†TÓejB'c}˜R³s”ÐÖÚ˜£¥«ç>z¦^"ù8\îÃã$?µ¼(z»…hi°Rx Wj_,‡)H{aR†$bÔSŒú§úPõµ¹Œ#¶H›t%ó‰0õ·"ï›v¡î}¤!/Ö ËO’Z…YÐ/¶Ü¸'›DõB­ìR| ¡m'‹ú>® UBê®ÝU©*¢ sp#x®°ABm”ðtøY4kÅT‰ïE7@!èó9Ê í¹'\ÏABbòt"·ÛÆ}s­·`À2¬LÙo§xüîf¿Ë•´V†‰:‹%«­Õ+~û¶29bî$¹ mY«¸)õ´ÛtÏÉnûªíõaU,èÇèó“”÷±uÙ/4Š[ÙÄ¥hŽôM§¯á?³ncmý ŒþõIÊÍUâÏnj!»æôX·-þLØü÷[pRàøºjuA€¢³/§BìâjbꮰN,X#,?`C|žÓîMõD Vu2)jÐ×±Ye-çò©Â†«Â&ðvN*”ô ²›nJÛÊÌz¶øÏ'œ#tfë9]&™%†(ÕY¶#—©¬ØðÈ­ÕZ¡PŸ¥h¶R¸Ð[' 胩Y nÉŽO‰*"jù­Õb32‘·µò>2ƒÌb蓇¼7Éÿ‡H…1šüÒò½¤áªÙ»WÏ‹Q¬òaÈ-'©KõCft²ÏÑ·™ú”÷8ܨãpÅÏ©¯*啱"¢Õk¬× ÑAÆ.æ4.¯qgWG5¦¶kˆºa=üRÃäžÙòÌ鯩mˆ‚sÂvVZ&»/YxŒ:[Œ¥i?’¬­",ÅÕçI¼eKÔë± ê10úÔT“"¹YðÁ2Ï`.þ#ÓèܬÓj\‹'Ó 7¸Õø[Ù¼ÏÙºy®õlžÂTù§ÞføˆÆ7– ʧhÖÐ>MA/­6äúe¿Ï…Ã%Nã"?Šw ØigU£IŒ¬8µ‰Áí•'´·’ÄÍò”nlPu… žÞÉLx„ŽV»lñÖVAU#¾g«{ÍÁÒЉù·©|åÓůbŸÆ]‰<Ž )kòUÈÝ·fÌÔ§{]-q¡C°:HƒæR¯^4ëO´ý½{\ƒ%Ö¸Æ!?l‹Þ‹fj”EÉ[Õ³Ih—xöù“¹”óíkô²Nbì‹x#_çk»•YR÷Ï0¾"棟Þ.Ñ׎Fù-IÃDeÑUû=µÞŠÞì˜ý)BU¶÷àŒ%E?¿)“RÞܲñ&’ßyÊœ§ïòb„ÇÝ6ÙÑš@ÝHï›àtNVt) ¨²Ý¿Ýù©ÉáòÈM6ÞL þƒ?¡TCQ”(Å!è´R$÷$¹X %‡E!ÐÀ$®%"}¿f,Î%“Å!p(Üà ‹E ÔQùE˜Ìc‘¤¬ 1‹LÀ³+òJ‹Le0ÊÐy8ŸÁ&5Xt:«[K« df  Ï«÷Õ~A‰Ï!ϫՖ·¬B"ÐÈ¥B‰EˆD_8˜•܉J¥tè&2m€‚S!Õ8eVe3›€oïèÄ Gj•Å¥ÑJ Rc.ëá•<\F§ŽˆÅ¤ŒKæ™H…e_×ÈnYÿsØd´ ÆÍ³`­ÐkƒÿG˜Zp0*bÚ=â]½<(õó½ ÜÆÍ«…{'PN„âíÖȸQNý2«©œ«O —&-Ê®ë0îpë­’"Î&švª ªÆ5à;2©¨­R ”! ‹¡:HB¥¥hc|¢P©üÅñ2îÐ’\¨/É‚‚ó±x©¾ 2ÉÁÎJ ©‹ÑõÄ(‹æÒ®0’“BÒ Ð¹Ò â‹¿ìûX˜)Ž™³RÔF¡·ë`¸¿À «$¨)r,Ç Jƒ,ÎêãþÒÂ/’ã)颔…;ì…-ÅhŠ0+êœ$È“rõ&9í"xù²T< ~¹ÈsêJ*Í)TSB~¶Ó›‡T>Ò êºî#§±ê-7 ÊICIÏ}Z‹Fis”˜JQ»h¢ØGêÓT»3ÄïfT¬ÛL%K LÕ=‚ƒ%©˜ÞËé\ZÆ>h³v‰)Š -ªíp‚A ¤Ò¥Ê¼•¯+Ò˜¨I6›Ü¯T4ª{*€ndµ;KOš˜ÂŸ–DåV·KÉ^Ÿ´vOK¨T6¢¸ g ˆtTªËÇí›<à@áŽ[t©ßkÓr˜Ö൛;ðŸ}­7ô(£&M_0È£\TK»Õª ,Ñ?÷b‰QI\l™É+®YJe8Ò߀ٕfÏáHUµ3±®í¿dÖ*Ü¥‡^;*Ee6u=4ôTÔÉ“ÙlºW¦ÂÕ=y´,j­á$¸IvG‰ápÄŸwÔ¥& Isr|rèd1Á¢â®¾k5r¦¨!íÓ7*œ:ìÝ"~Òát ‰I4'ˆŸñî$çÊ¢KËŸ Zä»ÖÕÖì–ŽJVuL¥ÚXt¶ ‚ÄwVˆoç÷ƒ“Þ;:¢’M8„LÝú(ª÷õ®Añ ñaHŸPÿ³ª¤Nrä„=°÷#b@ =¥×*H QË]­: üS‚Ý^ä!x6£ŒøŸ(+˜Û¿ÃŒSI xä¬Ý”ô\xüYåmO9Ò¾¦CZAn´Ê0´žØ Æç9 >öI\]Tüé•6îDÛï}ðE–º×¼ 07&ì‹#ÔØÔÎ鯅ýÛ¢Æ6Û‹F ‘:‡ àÍ,/íèù²?ÊLˆF$ù™õ˜êž¨ü†Eii˜ÆÌÛÐÔ$‹Qɲe ¨ÓñÄj€zÀÖžòNi_Îì™›µä©LbÓ~-8ã)è¤XÞÑq*ÕV®Ò„lV;ìÒ6òböÒ‹'íÝÓdÌK›QL-"N« ŽH2Af|³,T¦¦ÈŒƒj!­¶`ö¢YG” yCD2JÚ¦*þM’EÁ¬ÅfC ${@ ã-X¹ˆ%‹~Kç–ÒGòq“9º¿ÅôLÎûŸK3-G¦ôŒ?3ð,}È%\ÃÞÜP!CÃb`’\ÓÖS É"i©$4ie` äBU 2׳+rõɸªZ\tâ{e6NbHIScYlñUx 6€Deå1O„ˆšã`‰Ulu:r¶Ï™Ã' ›ñBS"ƒÎ©2ËŒÝC®šOF÷:“áÅ}£öRI”Û \…ÒL%>¡]koèY·º÷ôóXÌ£rz°I3»*_Èk¦°»„_]h©Qö S·F:†\ij=ÆuuRãúþ&0¬¡¸©#úš_Ðh¢•¿1 *ªk2rB(Kš°)’BÉRÿWi$ΨӽSXàŠ•$¥ŒÑÛÚ¨ãZ`½T,tŽž°†ck}´ýŠ•¦ôØÉ[${Ĺ³2ôTõÓ%Óu¶õüTÓd·¦–ƯcvŒÖBÓZÉ‚\E4ß-¤ƒÆí»ÞJ¿oÊÕ*`´Â\Y©;[JEIëZǧ7ˆEùbÕÍSÊhôq&ÄA ž¨U4¤´Ùzc%BQÂ$T'e$tPà}UzR¸û1”†­[’qn úž9d¨£瞊ªTò²¤ÛBHŒÙ%v7h‘&b˜ùm=ÃçõúNk:•dè Æ$“s†àƒëÖVªK×=q‹° ü¥ˆ"9¶*>ª_ö–‘—,¶›dªˆ²–°M½ÅfÈQó.g2L ©³…-Æl™øè@nU;4p5Ù¡CÚ¡u‰¦Y@Å»ýµs%ƒ-3l„JÆ#¤ú¢nôW¢ÅUZrR“$PÜùµ¥6ó?b’P4äðÝ' HC¢Œ\î¶ d¯ÉZ>iuIÓÈ._ ì´Ue‡æ\íù+SCçMŒYSâ/ï—(u&p·Á<`¥œ‘N“Z 3mzÏrœH«Š(4÷ÎZè”,7}R1EËU²ïÊ|¦ #³_2!§tÒª§£›·oLw€Ú£¹ë_ Ýxyi¼Šlï”´nT}~èdîÂÊšf°º<˜ew‰|m>H7h76·|¹•æ“ïL¶óøIxÂZu[KŸÝÓþÞe»«=ÄêúË"l‹ƒë{ÞÄ!Y€úѦ…3Gz¤Àjœ¬Ý/ÄáAúç`áÙÿh83–↜¦&µj'þ&>½#EP”’k=¹ÓÉ™.xeY4ïà Š#«·ÄjÿŸ:²EÅ5r¥ZªÁ*áX™n'‰"èªý8›¯•°½8ËôŸQU¹[äÀ@à>“v·²Ý©ã Š,€„ù?:=Â3³>¸4œŽíLîÍ‚å<]Ex˜èÒÞQlΡáà­“ýž”::§´NÃZ«·åä ³ýNHò¹•ž jž±¶ÎQËu2h w@JL²%þh·œ+žP¨ƒ-œd3#]4U‰]0VVß$5oSuHíÖ¤´óáÚ:¸U‹­œ·BufQˆîÄ)Ø­û³vY)ñ <Šæcµ{q#½ñþE7QøÍVIQ+M•ÕGïv’Ã$_àçhFn·N¯ð`8¸ €nrï £Óºjã¼<ƒeŽ‹ÒgX-ÈÁ¨»­Vi1UbEâ)¶À-·0 IRðCÇír`aL^€âQrÊJ¾pSN¤c~Ò>ì: *ýÖý>z-i½0ˆâ ª‘Úp)`—ýÜ‚-ÐóL¶RQ“‹ ‘t«†›"j­ðò{ÊVbäiGÉšÞdü‚§õélÓñ]™udÌ}z¿{•Eá“à’Œ­§_‡¬À‰•±ËÁñuØÏ½ÈâNƒT£›Ø®`?5™D#¨©T±†»ªúþR%CXÜݼ$E½=ðŽGpSÀ_Î §1 (ߣ qéo|¦ P#$'ßãˤ#^™Þ=4ü#™#$ˆ™"áS‘ðÕšŠïz\ò’saIòûßlú¿ºú ŒJ«˜Y;ÓpªÛ¶õÛнƒ2Wú?Ÿ}…šÙ3;;•_E\\ ­¡ÕQ½Å3CY¾T”ñÞ0¾\á²»^ëÕJеçX¼Š-šÞA´2h4¹¥# Û$ê6̉ç·§ÙஞÇ{ Ö0óôsAÄVlû;x7‹ŒjÔêö4Ã^füKx=ŒZ6›xjzQµa‹†çÀ±ˆ”>ƒ^/ÜŽ@A3gô*«± :KÑñØÛ¤ìÎ6hå³û©?ºÞnY Ÿ‰¡,r5Ÿ*SIü,»Ï7åδlZIÖ™™i×#ö±ffç H4iê⪂þ¹|PV\rÁCVº&**ñ*M ]£YZh¤C""yDÁðfWë,òÙ ôo_¶íÍÞY„cª@(ÖÕùØ‘óãLsÒˆ)hªF¥¢:šÖ Ë¤&OJ.Ë&::$oúO ¦ËQþÑË›t³.j®Ðl@ˆ¸èró& š.áŸ*[°{ÆÍRâ¬I”dÇËòe9!ç"¥ÀBe#¯+j»{”ð¿Øç¯)&G £8É6 s8ÇÌHzè “‹ÀÈc»ÐÉ)hº¢Ý€ \„C3l« \î˜LLº Ñ4‰äÓ6 ì,‘&@= ‘»«ô ˜N‰±¼MáÿJ€ŒÊ–¢#ª\á"žqð ÒÒ`®ºGìdû¾èœ‚¨$T€¸lüþ‘I³U,ÑV•[4¾Š¤›WÐÒ(…J+½jŒL±-‚=´êDÓE³µÓtCE˨µM8Í \9òÜ$"ëʬøÅÀ#+^²61üþ$mò›9ØWµô¯È‚üzàÓÂ:ÙÀŠU‹7ÑЪP&ÔePÊŽ}Pâ¦hëºìKh»Òâáåb†™eè%ýÄì'ö4ŽæÌJüßÐÚ´½Á­õõ¦¹óºLÀ z£UåÏli(GQ²VŠÔ;²;3Ø©ÈWƼٗ‚<†WøŠñ¯Mò4jþB¯¼®ÆêŽßy§GØòBÃìzeTM 3ô¿FÇ¿T32{Q,[óߦ~¼²÷Òømbv žùÔZóS;`(‰—”CØû!Ƙ¿HÿÙ|nÙÝ-öÒlóÎ|„4gniÏI¥ÐÎ4$TÏ wuéô:5‡ ü!Šx¿0µö¼È©yiǸGBŽyÏWéR=BLÒ]6g¥-¸(F꓇4È4‹«ƒ°ÌÝXÿPŽ¥ñ” “)¨FOý¤DCnªÖ¢ôYÄv­øZèR“ÊÆd´Ä·¾ëŒÜu>.!柠÷á_lêxŠ‚dv‚2wÉœ“ǕƗ]E1Ë™Œ¤–c#ÊM/+.&œ·D6 DVŸXX¸ÙÔ£ƒ†=Æ­\ËS²”$N Î6“q!Öiñ{І@¡èeáþ“„ö°Þ+›¬Xµ¢pCŸú€$pÆcÎ*M?N=<¦F¢«£Ž ‹Å!WºÞN'\šqÜ&Ó("Ë\ƒúÉÃÃQ+1÷3&Î DÜA‘¡CÓ¶³;A¢ÒbOsn’C%ÖL)#L™óŽ’'&?ß1"|oBcJYó9l³2'ÙkÃ*DÎê̘“ V·è?Ï‚B/)¹ä0–š2M·nLÉÄ:A ‹UîÑQKL‡¬µ "§\ÀÝ%2‡ÜÈ>è¥ÄKU\S„NŸ× ¬ Љ"EHãZÖƒfz §xpÓu·r¤ÊãWÅ9!c¥ª”ð‹»•‚ÈTn¨æIWÔâìi‘”ÐK³]}‡÷Ïþ'˜`˜Ö‘‹–»ã"uf”ŸèË#Õ´UKh5uOX$ö¯PUç !48øÈÖ¼”†œÁBŽ!À³ò ¥qŒ/Øüž/j¬Ç­¡"º o·snÛ‘Ð u˜®åË?aÞzÅnü˜“ŸquveÏžx¹¢xžÕ5RJeÊ+‡”‚í!ÕYÿÔtY¤Gýò_µÆ'tï™"¯ŽÇM˜M% M'g‹šàDÃó5–Ëç±£–®§ Å\¼cøEK3)ôí")«¼œbÛq¬ÇíÐ8ñ‰NEÂ#Yr‡¨ñÔ›†â R09—šgKyè¹Ï‹çmÇߦhñ²¥fÁ:$©Z¶©Žêr¢FÃuPó™°w–êH™"š±åOn5=±½ka€}¥Òkx4Eð¹•Æýßê<«‡KF@ô\Q8Tá î#ĸڣ¬¬Ü•.‡ü®dψ‰& &ö1oͶÓ*ˆPÖçÕfg­ialàÙ@Ç$’]»Üï6C—]†å u©b®g¯i #§Á®Ÿ3NÒ¯†Í¥ÂC0Q Hî!&ÕEM"­¯êkâAÜ›sñ±úÌJCWDY‰'¸îº¥}Ä~bªòA.…Vhª@òÝ&Ô”±t—­Ä\CRó§8rñÚQÆdÇ$h¹×Ž1-ç*Î>³ªÌ.‰ O ÚÙBéÓmöærvšÇËVÓÓËíçy¢€½ƒ›ßUž™Xý1Íl¦›7‰ ˆ‹g±ç¦´º¢!|4Û2.¨éíˆ_¥¥P8 ͼ€2Wa°{fܯ¶fK§‘yÙ\}ØY‘Ìø“[å.o4?+bóÓbô”Lj݋°cî"£ºÂ òL4P%>æ \i¢d–‡Ø›¤¨ÎNø»â˜ƒp0‰ïˆï¯F–êú©CöÛç¦oξýäXŒº!:·¨ª¤‰Üw‡,{n–¥â=*ânmêCŽ˜0(´m€å\؃ $fN‹ ¥ofa­B)ªHν¢Z(D MZÐ*¥'oB\ï„ÜúgÓ¬?°™­üÍïÊ)j(,> b²GZ¯ÀP šŠo&nHý †­ŽŽÿiÖº1œCÊ!@°/t½­lí|Ïëª\¯lõªÀ¼Cp3‘°¨»Ž×­æìm·'Mî ]Ë,Z-Pý-} ä°*ûQ†GR§èJ4ÊHZ/¢ Ë w‹>ðsú,,FEpZ/r¸"«-†®ÎTi©Öv²ÊƲv.…¢Hï–×R¬Ð %/ò>Þíˆôï8ŸG´¨2€MÈ0ŠÏ†×êHMË$ÅqöHâd×̸°³.ˆ¢*/ÎŽ2À>ï¨Yå^t©x±à¾‹ #OD9ó€ÙorNÎkŠê3¬×ê‹,G®ƒnÿ®Ä*…ŸJìÚ2Kg,1^̰ ùBªËÁGTNR.Õë,xL”ÂÀ)lŸŸbì/1Ž8b'8#†U ð\Ã`¶3RŒ +œEá¸chw‘ò10Œm#2tçóg¥in“ ’CîÙ"2¼øÄíÀ%Ž›ð*‚ÔQ#‘䫯=‘E)§dcŠˆŒdàQx!ÇÇ:Q0¥‚N{¤}að¯ RÇñ"H{"ÒÖÎÎÒ÷#%ð,f³£$²'ÆýÀ-RÑ@áòI¬I fx¨ãºWÖ]% ‰DÅB»;”¦ü³l'" 7,úZ/huF˜¤Í£K"&UzÎø®ÊR´ç²–¬,µÊx›bó+¶Ž”ÚuNIA‹uN`¢Ë½j‘IRV×ï/PÂÌm.‡mˆj<ÃŽdcËI·ku´Ÿ³?h`ï4ð=ÄRk¬‹9ã·oîüó\áöûŒ±> Ë‹&òtï5‚¬ËwHH{OƒÖyTrE×§e³J*Vlè®}¶¬¶š5 RYè£i4U-Á¤ŽªÐtdbUÚOTÆÃfFH´|v:³Aôi’+T¤6tê×ODYr-P"l¨JvJS2:ÏÊeÈÜQ„¨Uè¨UÛ·ËMp¬u2¢ÙŒŽÒI‘6íÈGb:íPª=Ì úó²Åä9{%ªÿo¢E.€ª²àñØ8sOh€W ­qo–£!jó@b\ø)¨<¶u{ÈCá^Ú·ó€BD‹MÕÕ<áŠWq‚xHì*f–&C‰¨áCpmpqÑ8SCŽÅÖ»'f0–¡ræ¦ò5Ô"wáöª)É4 ù1Š9A !ù5Ç*ÀC" *§lï„§üÑÌY—ã 5KË {øìF¨àHdìe9GKEòÕRãa7Y–—1$zGÌë?£p£~q`ëcDâ«Ùel‰‡f¼Ý¨ec$jµw‡—– Ÿö´¼N<, ºy8Í4'‹ ,lâ'>&u Ë›X‡4G´dn\´Tå b¥_‹cŽx‰©s¶ÒPOõñ¢!|÷xk;¡þ¡e8tjð>Îúƒ!ãî×Äd¬µŠ?Bž1]fP¢8eqDÆŸiFȸlɲXã‚Àˆ–Nì‚qs†]<¬ú÷…ŽUOÂ]¡õ,Ž;¹ÙÖm‡Mnº%vÙc±šóçõš‰ðqóQÍ¥ƒ ž©iè‹”¹6Üÿ ¡/ìhy”r–±ï©ëQI©uF%%¬A—X¶Wø#FØjI¥6·—(.5ŽÆ ¸ÆQŒ2óeUX1ðÙeöW˜1û© ˆ<©¿¬ o—J^X _ u‹±—Bº´P̸·±žÿê›>ÏpðŠxåÚ·yP…¢²=s­F1@ÚV¶‚Ϙ6ií¦>UL0I Ø¿…Ú.صŸ#¯šf‡Û¥èŠíÙô¿ŠfXñRq zj8rËoBy<íbª&™­ƒhtEu4ñÃÝ0á¦ð <Èɯ-™1á!úUsÌÑBÎ3pbÅÛB¨fxx“f_ w'ú£?n.*µ¸0y¬Ê;! Àd‚ààÛ´G¯2të»  ø:¥ÓôqY Œ¤d\ÉéÀöH˜íÚq¶áÐtóídà ]Hú¶ÚV¸pµKÖ›ÕŽƒ‹-V«Ú¦95 ù’Á"pö¤à®PUÁ ÅwŠ÷b¾Ã%Ûb· 5_™‚Šï-Ÿ‘?B9¥Â  Ú˩͈Ç`u”A(:ÊvxŒÁ®öËÿŠü=Ôt xºf7¹ŽiÈÿiEñv×Tm‡o™eö°‘Е¿¯þZåÍòzŸä·ƒŠÛÎrÊUï|±=JICܱrHdÏ•$œ0)u›PaÇOþMÂ5µ™Ð̘'Êè\žN¡ b¿:šôÛûT3ò}k§EŽˆÒU2LBó Æ\ÿé·!U_‚/fiìÁ§…ðY2€‰W‚4ÛVi±ñÙ-d±ú)ª×óɸ˜ÅÊVYŠIÊSNšª#Ž,öŽ"G§6 î`ºñ6¦°t$  ‹‹ÐÔpÚÒCº+§þá\„³hjËC6_xB;¿Ùjü¯E8õœ_¢aÇ"+ß’=÷šC†0GÆÀ´©“·˜u(âš›lî”EjÔ•͕p•Ep|b.ûÁò,µäíÉùwƒÞ2€SÊ:ƒáKÌΓãRü%¬¯öÀ°²®¢:¢uÐ_íH{Ï›nàŽ?™9òï6»^¯Í¥&Ó5£Pæ³1桉Â`ïåЄàÿöPæ »¦ˆ#Aì‹nU¶jÚî6W nüw•ßöc’·`¸™wØL# òÎrŒˆ4_v¼w(N,ØI´Y¸g¾¥'Ú^3ùKó^óð8ÈÑM‡k¬½'\äÛžÛ“ó´·h&Á­Op{)q$SÞ«0K”¦›jWL©a^rFÁ¼Á{Fi-¬mX$~ö”ºЧ>Ü$÷˜u)fÕzüÎ\8¥Û:Ž|Ã%KݼJJð¾íuscߥ’bª=ºÖŽ‹Êf×Ö­Ž^mWë¾v<ïRjÒ\e#’Á§Å Àbü ¸4 ~á€(p þ‰?bàB0Š?a@˜óêA €$gÜxù•FòÙtbE"…IhÄÎI ÎçyôÒ<>¥Òè“ú"¡È¦‘‰¤º-—H¢ÓI4ò77«”$*‹-šSå³ÊÓò76ˆVmqX|BÇ$‹KâÀ5»I£°EþM&¦I#1”Š]¼X¤—ðEMGäñoûµÄGÂ%Ó©ÜniT‡Qð vn GÍE'p/a*|ç%ºK„’Ei·€aQ‰äšç-Ïl”\Ç!†QÁœÚce4žM5ψ¶L4áÑæœþÛMa£Ìa‘½Ô_ þóE;°í 1h$’êlByÞû€k¹úŠ(ê‚„! :p!+V~¥ËÚ £¡´–ª(¢èŒ¾Ì" ¤¼¨£d»#mÊ(Á¬mR$ŒDçò,ïD±R,ß ÈÚ»!LtD†AT6¤Ð4Pˆ$LŠ$ì2:СŠÕ ±‹ªœ N«.ÜG(0‹RÑë.B("\ü¡Ë ¾‰HqZÇ,rŽž!H²í1ÌѪýÃ\O-M”b}ÈH4 =è´ö¤Óh¥’rœ¸ÉmÜ™ –Î k*ÌF Ú7t‹‹HÒ/U¾ #QÏ“r6¾odxÊ€pà }£ ³*‘:uìO‘Ž1­&yà<,@6I3°K³,IñÏM ¹7¤@Ç>ÿÙñ;R("#ÇzÖXÊ%<çÈ…°FzAp*9¿<¢Zv ´LoÑÍ'»âÌ@o‡Ìš¤À¦Ó)D¬˜•i à\Šîw¬Úa2”Ò@‘òôi娭è@~á{'¾˜xs#VJ€c'€ÄÒLª#yh“4»—©àk]Èv<(–däL‰g¬¦{­¨·< doLÕ7É+ØÊ´u…&*‰BàÝ(ð ÌA2âÆÛƒI” òJÇš{å¼>u 5B ÇùØ,ïÚ8¸SÂ?éR<6I²© ÐÒÍ‘Ø.Ñ4»)`¹O{‹ŸA3+Òvî] C„.Ar¹EÅGcS²MUd3÷hñRd›?mžiÊjbwŠ9²1Ò¬ó“Ãe2Ü™e™Ï`–Ê·z¼ˆÑz@ﵚ¦\ª‰=$"e”2Q_”œÛj4ΫG"†é"”†e´‘ˆù'Xþ“Ãò“UxˆqM,‡%²¾WBTt‰Ü¶9@¡Wôné©]Iç¸é3HÄMWEqrSÉ·ej,š¤1¼+ _Çë¶”VW”6üÿkRpƒ3 _¡“z$:o€I–ö«\$(¨"³˜X#BM-¼‡¦yú;iÅ;™w–tE¤1©²svd¶„¿—6ßm¡li9²0s[" ™uùǢÀ§J °3-0õÓ@‘Rî•j”Ò–Êzx 5RBùŒ®è?c\mô&Ø£ÓZe-è¼Ð¤¸ß“ÒJ0¼þ$€Ø·¯giáû8gÏ™ŒHN!•ªË:ë“ÐcÉnëÎøÜéËrj‘ðæá¢ªqZ‹DPíwV½4©2îvM.8Û@4 l©GN?îk—Ä—Yšòí¸û'˜œ›)ßÐùO*MI™‰Õ#UŸmðGÙ¡üÏáµ1$CcQL¹¥5î»Ýçž5bÓ|NÌÅÆ¼îõÙ? tsØ%5&K«f®ámׯtHæSy7“ýÓ¤m½ãvî÷ÎñÀça.\iLˆ)‡fb;›†ß)Y_'§6õ&äQ)Þ(w}K[îmQ$ÂsP}´¹Õ%é“È#ëHâöƒ¨à!†.›ãðÒÈœâ´cϬÎË,rAãÕË‹`7f‹%W•½s1|ô“޶öDDz ©O[ðR$ Ùcí:b­U UÉо“‘,‹œ-RñÍáD˜ÍãT¹/ž€K‡[˜rU¶S cܬ•t—:ªâW8ÇBhËuxq†¢^wCuˆËß}„1ÓÛÌ·EK;o„Tñ›UÌ2D"m®Ÿd n±0úî¥e¼Øt1…@Êݱ“Nh«`>£T²Ú¼éàk*ÛçthÒC»€—k^+T4¬d¡·ñëµZ¤|»\šƒÙûTzä(êœÐʼ²³5œÀ~NåÂÛÖ¤RÓ¤î¨+˜ ÝÝ”Orïf"syЌӧHQÖãk”òÚ¥Ðysb’‘ÅþŠƒ%]Ó[æœõ—öüU]w7ú™§Õ³‰§aµ÷Xy[1…gì¾0û½|>¾Õh$‡bº±Rü_åQ%  œ‰³0Iº¬21B„Žð³‹°‹'«ØŸòå&ZH q¨¥• cÔ,;,.q‡ªÂMÁ*)ê•¥ð)1p¾3ÙºCÎ88ÝŽ©ÝŒ°®‹í7KD€+.§tô¼[±iR¶ Á{E(ëõ–~¶óžjÙ•@€¿‹;r®h‘4Ë4âÒ,B˜:Ù1²™&µJæ» :ˆ£&ºÒp•+3µ²¹ª‘yÖ:[¯8C["I2|%:B;ˆáÂ’Î9+Ù)[ðºòµ>d:ð—ÃÛÃÀ±º‚U¾äˆË0¨Ñ'òà€2°°Òa¾!º¦òD1w¨Øõ°{5.¼M +<ÁÌ/ Z.‹ü5)ëä›Hï:ªæ”Ô¦x}°Y𱌞úŽ¡q`¢Ó¾“|ÅÉ¥z°ê¤è>T=‡à»)p:75´L¢3ŸzÛ:s¯ñ°E«>?a£*Á…ˆó±‡ðmGpíºP‡Âð‹ú]%н£.6À’ d0Be•£Çú"¢ÒŠ­Ù”Ž3C »!T1k?ê¿ü/¡ì迤Ã-«*-xô³bp•£ý Zyø¹v³ÒðS@‰rñ s¨YHš!è+|ŽÃû¸‡à¡¦ë®À¡“Ɉ¨aiC@„—ª‹Ñ¢¿:ÙiDó¢l+ùË?¨÷´"Þ ;¸¤®‰ãE²ãšìšZ…Ãð1iûÀ¢!(:Øš%û‹$J sÅH‚ :ޏ#¨¬-$ÛOóö®Ô¢˜Ã(«b 0•(÷µxõÁ„,4ä/ŸTœÁRô!<7\"K1Ä9w•+E7’-<âY2lº8ã´;Vº‰˜ˆ`Ù9ë³{@©yë¢Ô=.³±º.ª êÈ€») >£'+ÑÉbËÇÊB'Òm¸Y‹›ñ®LÒ±‰Ù…'CKµ°“ÊÁÙº ë¤&Û¾¬Î:Êó«x•S€t‘nLØ“,ùÞÆ£± s"ˆ!lÀã5ÉÒ5¸ÉN”ŠÈ"#m·²ô¾<»€#­ÁÄð®Q<ÛXH×>‚0•(šWDiDÚ‚€;ýˆÌáMH£¿"‰ ¸Ëì~ ãi‹³EKŠw¬;ʇÌcQ8±ˆR]Êž:D•ÂÌ Q¦Èt;ºÙŒ«¼ON¼ C~=Ùã« –«€¿ ºG’O©Ü°šóI Â•a¢²‰±»ÉÎÀÕK:¥ ä´LmޱN»óBÂõ#)𯻑m›{i‰Dœ:âcD¸ôÌôÉ6aÂbç<ñ—zAR›ûJª D˜Š,kc£à7lN›Š½ iRìã¼ü_0lIF4Œ) äa©£ô–1#ÉLRAŸESˆrÔH\Ak¿Ãº“H¡Ú-RŒII3Ý!¬·’œM#ºûÅÓèãÆ=Gòø)yÇ"˜›ãe $’c¿Tß'tRlS QNK-ô ËéÅQ¨¯š8CC›Ù”jʼn-ìÓžl”šcÂðþÈdòÕ­Å 9 -±!ЯœH' "Óí4h¸¸™' L¶+j• Öqù.R=”ÉI”•»å‡)Ø…GpmF½DÍô¥4DŽ€ ÷Iã‘S¸4ÛÌ?árØ‘ÜP=±hš c (”fpšÃ×Í€¨ªªIäù¯enŽ:^+;F‰Ó t³·’i:õ'€CˆEÉBIâiTBeŒÅtž4üÌ4U·‘ˆSõs]0*¯M™0Ç)2›8d*a¹ t¸V™ï1¼\”š-9•¾ÍEÖŠai/œ÷ ¦”ÂË¡Ñ$ ÒáV" ºD`Ð=ŒC ó ãݸ22$¡ÓÒÏ(³Ø 8ºBKÜèÍM—"™è§ZJ/›ë:›¤©‰ÞÖ{@zž/€ð)øãٹ⿠o±-Õ®ÃjÝüÉœ´­‰%ÌËÃܹ¨ž°ÝêBRù¼j¯œÙ©ì‰؈u¿R´L[‚!'Eg„_%aÊŸ•ÒHä])‹Uƒ)²50Ø=Å µ_C¦?ÈÉ»{ÅÖzy”V³¹êЊæØ0ƇÐóµ” ‘:6s!š]€—øRû;=Ú[ˆó(º<)|³Å• ‰-HNOÑ´¿ûÑ¢ N<𕍫à%•d‹4aBô̱½ @ïÝ…™ ú&ˆC;ŽË\##þ€D! æ€:Y£íaY8hŠY:]È” :‘0Ú?à%†>²"Z¿#U¨‰Üºžkt-‘Ðú·"¼ 1 3žu¼"*ùÒÚå°DÙcº/YíÉ‘á¦Þ£WDmL:G)ÈÞŠb# ¨¦(ãÓ}<±Å7¯¶@5¬cÖ%h½Åg¢I3áõ’ ÉÄ£Ú%E „ž:ÏœS‹µC¢×[ÆCTœ ÝÛ.T<…\Œ\,=ɦÖ·í/FéqYl®»E:²a¢M¥L¡¹Y3Maªfµ@\[}ö'꘢LÒ\¬þ¢N ¶ N;yCë-<wVÃ!C-.‹X³>œ^GÀ˜Ñ(&Ý:&xÄ‘ÊñÁôã8÷¯räÒÑ'U¾Z«–^›ôÆdœN[?ÁEǯšÉ@ƒ^dÎ5} Å}-›y%Є6#`l‚L´"%1Ù„0'r÷ˆsQè;ð»,-)ANKÄêþS|D̰ŒQ¨ÊÀ¹ÂBbÀÜUëÔZùÙR©´Ég­?@’ëʃ²DaI©K›| ‡ÍÏP‹$ ”âÝgÉ;òm©4ó§Ô#×P)£6(~4T1éf+‰KvE}ç²mÒ.6$R¼-¡¡X¬¢‰øåaº¿Â"ÜMH#êê`ÝØ †(ªõÔm}èIm±6E=†È/;£IbLâ(bU¡E¿a "M‹ó# ݆¤]kL\2Ôó*Ô +þ™ýMÄeKRÊ S°æšì¨ICž‘3&ljSlVŒËš<'q&l®Nùd°œTdึæ|ÍÝ}¾Ò®AöeêÌ0f;Já²5jXì-ÇõË\‰Ö$ÌÓØè#íd%5Ôã¥ÌNÒ•’ÇÇÎw[ scj·Êϯ†Aò°éÒìí*šIY.ödÙ6R‹ m¦ÝË*Áiɧu»ÓÖ 5¹ÝýÜí>–ö/IùÈ— … rm±æ@3uÔ–EÑðÅ"ܱ·Ê˜òb…žÅœmc Ó˜ÛíÃ94FÁ‡î]â­'=}‡íZ¶™<ÞÖuÀíôŠ/<¾7Ç4 lb# w;Fú¦]-faÛðM𑾴™&–Jåz=Û8Ÿ!“ï©ëÂ±Šæ¦’Žž:ÌŽ-ÕÞô¨ÒpÅ71Ä‘¥Ð^ß+Spn3¯8‘bAé<@DgGŒ¢Ø·"ßþe_2›J¿^´÷žþ¼ˆ’]:ñw;74]rsš}Wë³­ì²¼j‰<êTUŤÁ>s-AÆH0fnµ8ô“0ïHó×Ö¨gä|êë@²Í$pïÕ8ˆMÔFQÊ\óÖyIŸO¬JšãÎPà¸îÖhÜI>Žã»”ÙÛÝFm*ó8Ð’O$£(”›Ü+ì¥èˆÛù+¬ö¯pÊráVhhqN¦àï3êÅÃpBìâ^ß(Y7áÞ‰pê¼äÖWÔ°Ôc¼Év|Ï*]s»#ˆ6b ¶¡I½ñJþë·HÕþul™Ó2u=ˆjríìWFnB€Ö6˜ìq(ΰ¢¾;eô…¾‹èÌ“ÌÇËí$1Ø |6©øQÍml׉P—2ñ/¨ñ6CË]í{¹Ó”KTÒë–Ï ,Nš'–^Ùº-ÎìÄlë~°ùæûÿ[º›·Â #Mâ]<ßHø{€Øœ@20&Êëa¿yãýà§Ô±Ï*µš'Í(o ˆ}Ò'\ƒh*µ‹PAð±èRøì™ì8äÆÚ9šôü Y ®¬£E¡ëwØÜ‹}ãõ¯€c?á?P®`ÌCq'¡Š^e¶hk_ZÌ?\ ªÈ’IÂ-ù"Ö¦ñšªNCn”Ód‹°aíf$Ó*i±VÓHï~j± ‘dþåk?kaª—+ùû,^UhËfÓ¨¢;3½³Ì°©Ã¦I Äæ‚ÏÞíÀ0÷ÇÜoym¨+Ò.F%ùvn;ʬG{£cÿ –<«Ÿƒ^VÕÜ‹R©²/4K¥K%­x±¬H¢Á†«oõ<|ÃhµÖ¦iQrˆë=] ÓTôÙK“f¡ÓÕº…[+:üY•¥v^OfÙ.ÇÑm;#´R¸ê§‚½ !1çÐSâLhV•ÅÛBKà wTV0‹ÄRÒ“Vç|öS0üK:t'ðhõÒûQ" @„L¬žX†>ÒÞužG %UÉÅžqÞ³LŒK.¦UžnR”V#VÕM°„ªwŽ^yu92!­ÃøñÌ|´ûo¹RTæ×Dé>ÃP^ ÁÐêæI"S®ÞåÒ7ßÇ뀰²xŽRý‚fÕJOÜ U: ÕüGúÓü›ÊÉÞqZÐ:dJëß¶Çöî|îÑk5ñm“8™eB$ÙLìÙSÙ»V„D"i0­¹æAº×c±ôâ¨@ŠlŒ-5k¸_Ь!ñ\„”CÊÖM´é`È@¥[âdŒÉÈ–Äu³¦1·¶w¦Hmµ(ÇÆ’ÔÇhÂÇþfx'âÆÙ¬Nº..'+Ççé'ßÓý_v¶òu:Î`ŸD¥=½›)) O´yO¾â‚ä6ŒQ +Ê“ƒê}ÈãqÓr{5K¢uÕ£L•Ü”ôÌì?pÑŒ¾|žÙY¦I8VúeâOm¨õXî& Ø…<òÑeC bÓ¬+Å_žÏ+µP팽šY~4±4¨TáÜ€V¯¿ X³àýyÓ=M" o·@Ñ;wÁ0’ôÊÜ©ˆ±Â½HÇ’@ij³O¦¹¥ìêØ7æ6·¶ÂH`Ѩz™: (Â(0'Ta¦`Êd°áŒôUÄ:ifäÊ,Ü&D€'Þ²ΜÅâ‚Í«nÖc i-´õcf°äFáî&ïÎvj¶B#šû\²#h HÞLŽe$ú"gÆËŒ½Ë~Ì+Ž#¡µ $l#lO°ÑBª' ôÂÑ.HÖÉ<Ϋ¶ä ¼ixÞdxáÄI>Óz*i ,/Òk †Ý"Ô`Ââ&ÀX¥NÖFä¡ïè¹ÂZ? îŸ*¤¯+ü…\ìÚîz ÆåŽ…‚0x ¦ioD0¨VM¶èËŠqà(zát—‰ýî:'ã𙌠"LɈP4 :KòÙ°gލWj¸ÔÈDµað«!øk‰F§fäQJÔ†Eâ#ª6cz› Žši2²o2G‰òÛ.:Nލj„:°¡øZ¢"<¬’a':aðûÍ08"ZÀ† p:«‚¤Ñ1Î:Î N`JÄç €ÎFZm4n%2 HcéÞ+OK…#®?ÒPïÿëïñØÐ† æÅ¶ ‘qŽ0Ä숈þÁö2Q"oôÛ⮡2B«žê§ÀKm–±øv$cqÚȧtÉÀ·lfÆ'ŽÔ`Ž^ŸÈ‚ò®£rîáød„áq-K>`ÜN¥ö±ÌÊ"'ƒÒñ+¸äј*<­äÆŽtE+)Y,î,$ØL8²Ï[ Hå &3äØa(²±dÂDPø*©/ç @äòk!Eвp6«Œ²åoà™Ë&R;«&–l~Ï'jVÒÛ1Ò/ÏÊç‹Ý **"Ñlñæò&,dMLd«ã‚;¬ãäè<¡å7¢;22Ô1)¦‘g(!éò“,ÚÑQo®QpŠÂNb§rþ~­|Ö²ÞñO:`;¨Þ÷è 0ʉVÈdxC¨D‘d"»pâ*ñÀnCØcOàÈP;ò+*D"¿(xA±~vG1³ø«Ñš|eº,kò—’d¦LÊÕ%Só°tTÂhC±^¸ˆã“>í£Z‹HÞV Î.é6ðbÂXæåBd,¯fn‡¤è]eÙ.¨ åQÔoíþsîpr,u´D‡®œÒô’§Ü7ð~ã>—\§él8$ØKplQlru®þ“3öL'‘l`£4 B¶ûOµÌRÏT~ÔàB/ôŒŠË Ïì÷'èÌÅ Û †SH©†DDª¥ñ– LêÿIO"†š™…H:éê šŠ ÚQRLoR‚³Q-æ 45CÂ=5¯&$Èâ”Fýc[O°5kÆbÌ^èòÀc æB(Åopu©˜Îª¶îú”È=‘”ó2¼¯÷‚9K¾²úÛLÆ"(B~#sê(Ëb܃tÔ¢âcfeód%,8.B²q"uMosh¢ÑyÇÚõžäè’!çNKOÆ-P(:D˜,/ÑÿP 8ŠzæÀ›B’ó13•Ü9Möþ ?R.ž£F nTèL‹ªë0ʈ´…U¶P îpÈéJ~ ®~»IiâÞl¸‰e{AôÀØe%JqLÿx“Ñt~è5.ˆ$Ù ä¾ñ2<¢ ¢p×|…r%M¸í›Zmeê¢}µþb„Êrk;ÐO©°ö踣Vã‡bÀ ôŠžlóF¯¿=¨{/Òf™Tò±¶öU^¯(îÃb0âÏö;®5&+áLˆ¤*èÇ)ðoRóŒR¾Í&ø‹®?Ä·;“™6pUÎÿ(âLp/# ²¢•¬,q“ÏÎn‹R|KÐîü´ékû,ëóVÓÆ:­da1HÖS>ö…ŒñÎ8g‚ÈiÜêuM ƒäÜêvÍI–oðà""¥Ð8I˜ ¬Í^Ìò 6!Amà£LۺДè+cI;e`TLã5êPétT«r!õMî~â9BÚp.^ÑN(á_,€#µúÍ®)S¡ö϶¹Ë&íïÊ0µÝ9ðcomIH‰(ÑPVÈ€V¨Ûà¼mLeÕ‡&HR& ‰±Ù…ì”1­õÏPIkÑ 4BxDâW®]gWp†'9óºÑ‡ Ä$Õc z pÁÂ>»e="IÊÆ‘Jäñ‡¢1b6ñË ™·=ƒàÕ…÷+dè…t~⎠þ¦ÔïpÐo¾ÕšÏJ‡OÿeFä ´ŸOTnì*5)a38ÔÓ'ab5mÏå5\áðóbi‹€$Í8èüü¯ç)©)§ îLihW'Å1jq"hÁÊ[«»cfäb¦¡˜.9B[jä½h6bªç ‹Ï,O xa8³r y-"ŨUCó„öìp!§—6Ù7 É!4Ò0Õ€â–<:ó73^¥!òC§&)÷:£®õë(.˜YL­”ùñâ|N^9Z ©+/&#ÊÛ  Üìcl‘hDNŽZ}1ì?5x¸hD ­} ,½C³Gã‡É˜h)¦¹qëh5ËsÕXM.þÈ }›/[28pXiÛt„Ò'ⲑy ¶°Éb¯÷§‰ïViËô¾+¸ûânR5~ëY#õAZJ…Kɼέ€¥QtçÆe-žj”è"`§¦H™Ž(…§âã ªØIB-/ʼn™¬ÞÏ+'v2HôW*'W·aŽð#V È ÚŸ%2 J,¥ôy–릘µŽÇhÛM¯&Èñes(@—û/‹%GKT"95.Ï0©¨bFSkGZ‹J¸ol±®¢_xÛ“ÿ1†ÿ6uù­ôé=sHî*uRXÖ¹ÖMLהּƒoôŸ—øÈz€éµ9îÓi ÜÑÒõ¨DäÓfceŽ¡–˜óC„èXOuŒ=ç}I§'¬Š "€Æ ªìi#cꯚXM-ѳ*€ò¹§­Lë˜ò·¬¼ÌÑnèƒhbâ…{‡¦i®ï å}ðΫ™–9¶•wLc ÿZÊC“ •I.’fíùæø¢¯µ$BôëÕãš[XÕR¯5öã«k\Z°Þ™« •~ÖvŽüô] =™Oùc^Ná&š—•4{‹“4ÛŽ8•Q~a,Ÿa"¯~1G›†«b?8¡ÿ$r¯šË$Ø?Œl‚SÆ#œ•Nûó¬‰í‘§ZŸ.þ@„1šÜ*¨´¶­%F‘rg§8‡£ß‹ðÁWÔŒ)Xï¬ôÿZ$)æL°9Ä5±eˆ’¦~-a-ÔþMŽM Rtiu)Œ «’˜<¼_c«D$Ü.‘eZ,|i„Ÿé=¤îT¢«¡ žÉ>MQkè8Óœ²Øi¢ÂiÆX2%8ŒÌÎJ´åŽ4P²hj:ðdŽ9ˆÕ0¢ÍTqO£v ²G)‘5yÚÂKj ª<”Š&µpé5eŽxqî®È C,¹Úy¯¾#æxûø›…Rù®#fíéÍ<*VÚ¯6iÀNO·¶h.1½h.­NRI‡"_€¡657^Ž„0¯RÀ„j ‡0ÓÁ¦³×›³¼Ñ¦)í/%§÷Sm61Nãb.jI\ך…<Ñlb›¤EY$—jŸ|YØœ#¯’p¯Zx"9!ð:æÜ´T(ÅoÒHäOd>qA`®CH†ÞJ@ì¥Q¹ÿ%ÖZtÛscgþÙØ¿ˆnýÖ7oí[¬ªº r\V"œ^X ‘Â`0º;æÀ%Œñ ,ïK¢»zhû$½þ³30>jèM”» Q€X쪹üÓÄù«"±4ÝÀ?sG‚•Ýl Æé€˜_z|ÖÊ—VšjÒûJŒÑÕzkS"îÜ’V^z`Voqç?åÊLÉ¡ `°mx“öŒJ2!uí\ÕÀ¶$îÝbh0 x¢× ô”6É~­ äWŠY†  Ž¡gW)]'%ÌŽ¢t­"¥Ò2  Û¸%ç¸ì²Dø„É¡/#ÄÊ5øaVe‚Où€äòVsücÅ¢A2#ÞRý^)AÔª–?ÒtJu¬Y;§²~áÈã¬[•ÓzÁ–Z” „dìÆ4¦›)Æ’D ²‘2;ÉÁÙ$‡îëBtɲÀ÷†’QC9ƒ ]ù1ÔÌ­Óñƒ!œ:–¸ðÍÜ®ƒñ±ÙIæ´þ`«H'ãÎcp×ábî.2 »ræaQR—ŽD>H¼Wvš#G!ªäæ›·z’Ò7Ä,ݯ6¾²Œƒ^'¬­ÂˆLlä/,e•&ÆYW#H\D’3áô¥Õéßœ-Ôƒ6†CS¬T ïÁ€¶¶\qÆ$4à¥m‘<º{o0Xðxzá È ¢)ó!Èä#Y±ŽžãZÒùp³’›Øpì™3ôžÀì§úJDØŠ“Jnâ)¾7ÐjåÍxjNP»ZìªYe£ PGB‹Iz*%ç"p;îô¤‚lL´)ئ½å©Gu“VOÊòCFÕsIu»R HÄ‹~TT‚VGÑAH­¥„u\“¢v^k¸9±žÃ%òèÌԥ˸ŒªñöEIzŠHè±áAZ P9=~KèD˜’çEP dÖžê H£;Æ—¶ŠÈÚ»tZÕú½Û„?g‰ß¤K³ÊM,Õ ª„ 9Sô’ø”zK–r­ô§{뙩NP˜VdM'Ê)&'U€­›>á‰TÄör4¶ö˜<þT„rx«x¼Þ/1½ø»åU_Ûä«~Ęzþ¬‚·Dé~g/Œ9Òø±fãèIo¦!1CÃå®:B›{ ìXš³Aô¸aT\ˆ‡6›U†‘Ÿ£ì)ù]—dÆš©$‡6\C6»0€äjÒñ«Ã‡HŠ {¤u‹âwÊ*C, %žÕ‹=ã*5¶B‹÷/bÁ ³‹5¥‘‘ëºÇ``F…²Pæì4äN’OŠrÒˆ¯ª8Öaòòû¶®îÜ€cŒÒBYv‘þÚS ì÷çfL‘pœ‘l=©ØJ†[,”ÃW%Ę:hÊÀJ¥ ,¹-"¯Ah š5BŠkâ.ìβiÞpEs:ÓM8I ' $’,ßKNÞ`ý>¶S4wîùîs[ÈÙ8\õô¹r#1[Ф™+6c"m5©„T—¸u‘1€ó„ÀFhÌê 1wvùëÅ(K—Û¶ã®°À3À Oqó¦­‘Î8,RßÈKí†ä áæÆ¸` k©jZ=IµóݾìUqŒ·v@æ²5~k$¯_lŒ²Â€-Áö×x¡(§Ê™I ¥•$él‰Ü?*C• Ù¥èééÔBÉÀòè“ǙŖ€^E4²åìU6WKòTq Ì«[u°C^Æ¿m›¾'q¤Äìͨqk‘2/#ôÁ ¡eú&Ë´ñÙ\ŒZÔä Cp‚oçAî> Ùo:}Q¡ÅÂ1è ‘'Ph‘±M!ë¸qÈ£bK(e.Ÿò 7ȉ='ç6djaÿÀÀ-›íŒ€}´=·Ø@*{t¦pºBóà%+Ì'HãL÷W¦ nÜWõxÂ|&IÓºÝg4¦ií£®˜]ô.¯Õ~ÂÊ<{öD÷€<aøy`û)Hiñôÿªìcïfò¹‚ˆXÛý‘pŽ`å“:ÇÜûjwsj>8›#2‘5®\—§Š B|œº€¶©ZøŠÙëžºí­’ -é#ˆê,1CÃ9 z¿+ÕàÀ5Ú=ž ©ê½/ D B iá›:ˆ¸ý4È…ŽÊŒ³*D$±U•9Š:Ç¿Ëi¾j–ˆŠ=žc Y¸¼`7“Ÿ¸8ê Úî–Šæ'û»ñŒ’¼@Qf0Â۽ј&Ÿ[–€ Â2¸—˜ã) 1ŸÒx¦0ysî:Kú‡ã3à“ž¹;£S'¼{eÂ÷¿B¯qí4QØèæÂ#•9bršJ« [2²‹AÑê‹€‹³ºÖü×Њ˜‹D½ùD¹ñÌüÅc¥‹’—"[" =Í\—8B_ ŠNJð×—ŽŸ‘('‹÷;s93óE¬šõVü§Ëú‹™ÙGTlº|[>DÜŸQßVÑ‹?:$¤sh£GY1b¸,¼Ãp‡Ñ%vÇÃÓ3*Ç*šºr P÷LÛ¡"–4<¹[“]ÙBl©¦ÙÝÅZÛž2½#Õ¤[§ÖãæKe4MØí8p¢2§Û‹O­2d/b–Z¨+Ô·¨‹äšåÆbKѤRÌiWÌ‹›&C[¬•¿ÕU¿%ØDLs ÄÃ'…vÔÞ‰qŒ¡ÙÕƒ‹ÆÅa Ë Gcó bRœ§£tÚP ìÄG‡ÓõUˆ‹ÄµºKä™{ Ä#(B°¨xàKÅòSC³,¼Œ á‹6U˜à-4ìY–]Ò¾Á­Í³‚Kµ¸§¬^ Þ >“âg¥7ÜÓ*µU%aùØ'Ë2cðÖÙm½çõ‡ ~C+hÓ?—ˆÂœ+ó•4ßÕŽ‹ÅÐN˜œ<º'ŒYÒeb£7šü†5ä§'"–!왪Ò<ëE`ß[,L¥)6qd¦F ß J=4;lêñ·×ÛÖ²ä$!®¨ÂÙÖe%Ý%”á[~´2¼ˆä4`­aÌyD¶3Ò1Ñ.A¨Šþd•—“6 FZÁåiar1žd_8øÔªÿ³nN³TÐjM?Lpè¾¼]È"º‰*)îÁÑ,=4Yæ 릮¦9IëL%8†¿KÖåï ,]FY× ÂlX‰š2–-6 Ú¥Ü%$ïOËcëÑžÓ=O¦¼ÍáyÝ$¢ùÖ^®ÌfQíf,ŒþÕì‹ßR¬ýþN¶ô&®JSIÝ’q>kð[´D[NÁÕ4qÉÈ3bUIÖz:~lÙ°¹“ý¥¡«Æ)ÁìA†Æä »œJFâ ë’œÚ:”;‰ Ö¤ JcÖ!B )@£æ.!ØÑî°¿`m¢ÏÛm˜¡íæšå¶ÆS'. /(€oC]ceÐÅÞëe‘ëÇ Nó>‡ðãp²ýƒ–O5B¥æàH?†Ájû¤Y%—%ôÍ Ÿ %7ÁŽÌá†ìÄ~""é!´yĪRˆ’nIôï+º¤Û/MN1–Ï–«³Ž16VBm1?¹;çSú$Ò(ÙH¨É¡óÍÙË7Tmd±¸ä’MyÄÝ0. ùlÙ…®€‰‰HŽ4ãõÉ&©Ëånéa5Jñ×` M\+Ò$7+MòÞg´Ùa;œ±$¤Úâ äÜ4‡îV¥U —t*i½ó±2$Éj¬…œ‚ލö’ì>]Ò1âÙrøì¨u=ž" ,Ý~h¨‹}Ø I³*ÓeëRYôTŽ"êìÓâ]1¤DG wöËÉŸµœeÆ[€3}ð7gÄ‹–F‡¸Þš¢kÝöœò~øx÷BþQû6’3¤®ˆ4FAþ!fNÜÙî9 Údº=žƒ¹q<µ'âwOŒ´’€H3ΛØ¾%¦N…„]Ó•nŒÆ%Û Gômò¡I¾Iƒ”D-àãq2RJ/¤ÃÇ’é7‘‡î3sp­ÝÓváv®‘lIŽ8št¨×ÚTCŸ"Kl¤"b¸–ç%kCÀÖ•Êù£,«†Ú²ÕˆÀZˆ¦âþZ#ש6k-{!^ëzxdDéX§­_.([Xà$oh0}Gõ:C…•óà†Çæk–o雬ÖEóôË]¶5x¿z‹C»nsˆþý‚`ÀD¡Ï¸„8üŠâÑGäúŽC#I ÿ Ia€9D2"’¿£Q©@ 3Dp Tæ5,–Ï_Ñ`<1ïC‘LÀÑÀ,Š5 }Si(“æ¥FŸ?¡Q*T KbP©"? –Ìi¯ªD*w"¶?âSlb‘ ·zD¶+D¬óäŽ"ŒUáÖYD*1f¦Æ§ ªÞ"°@¥P‹®R u|gm0hÄ2‘|B³0+¬2_–ÝaSh•ÖýM·Ê40Š’cXËeìòÙ'…KƒLn¹ Öm …eùÐØv.c(‘T0òX͆vëpëm³+‚xöë­Ê9]’ãô’-w3™Y~Ùïpˆ–êQ¼íú£,êDߤÈKä!†Ô8êÓŸíZ6Ž¿z º$ ‹Ø«3i^ˆ:NœB}¥ DPŒALñºÀ[€ jÈ’³@ v‡FNâ$“¥ ²›;),PC°“µîú‡C@"0‰+Ès¹$€ L”?’œƒ>Ž«Á&ª#å ‰"K¢h£š„KN¼<ǰ¼a4ºˆlª$ªãVŒ1ïòª¤,(ãÏ.€1»Â.hD¸Ú€g¥ º¦*b› J‘ò .(£ø£?,ë„ÓR!7ÐÓ*<ŠDñB–¦Ô›äŒ>”XPžuºWÎï"[6¼¨<•GO‡ëa×@%c¼l{„0bK»‹ÊJ{ZÍ8˜¾•!ö‘(jK_$Hcø³¾ÝvðÌ·ý£JbÒJΚQ&-•…¶ÜMìg;vÓU_ËR¸\(2m$-eØ·IÈB‘x³±¢ê\nzTðµH&7_ß'ýQhØŠŸ*K׿BÀÀ)ž9Ž TÙù{Eó¡rb`=,«@ ¬…Cˆ$%á3>8¯Ãà$|ÓIù|>Ù†bË帢8Œ?ÓÑý˜Ùùæghè‘ –©Ã>æ/÷£ NN FÎ̱|З`µÝµ‡NHsHº©¤ç~뺶õ˜ßuåýÞ€ÇDçüj)©ŠmlµíbŠ> Mùʪ€È¢J1ÊÙÉE¨hçíæ”soFñ¦ NW%Àïý}žê›sÇ\cçîJ•K˜#ꦻˆÂ|O: ¡Ÿ´ÆC¥o`Ö¨Ïгȯv&2‹­¯°1Š ¢Þ®T¬èc'KªHÔŠº¬í“¢ŠqÇï…T.­u4·Ý]"l8¤¡ ÕrD‘Þ!h!Î4ƒžøÈ¢¦~Ï*¬‡„e׳hD¥%)Aôá"˜o'ö Á'Â|œ[!^й7¥×\ gñ«¸(™I…,`2½"êïÒÃ"„Êìç6ÑøD‰±]Ä´¡Ô­bJü…p=‘8w~b ÓL!Üz€èÄU`s!=N]±?ÇÚLTÄ?Šäñ»Õ<˜]²íLQŒ?r@¨U3\é@Š$øØTˆb¡@¥5'»ÕK•¢\tÏEtÃ'kÀ­qŒ ˆ&©ÝUòOWÑJ’U,Éøo°l*g†H˜4vîñ7Çni‘¬qzÉY)"PÚ×ú:d =ÈN¾ËipP~+ã>Š2#*%L™˜X2YÛKä;©)¦»¦bÈUô!Ž"×ԥEïYì²éÌC¥6T%žiŒï‰,ºg8È¿€+e;03Åå‘Eñ+¡æC$ lГE (ÄiLK”¡Œ¯"ËJ žž&kÉ©ì¼X¯Bâ[;¤i˜~ž`Kƒ„”Ò(¢Ý组<†2Ådès§:hŽ*M†8ÆeAU€1`‰"©~?â+M,ô­“8šM”‘çr$ùŒðÙ‘©î:>(@à—Á1Œ rÁäLêL)¥Õ2ɨÖH©!’€¤FÕKdCvð*‹Á'ûU ”v’ÍvÁ)"ÿ9Ó誾”œZö9ÉLMë¡a(³H÷"€àV=mŽYÃÃÚÞ³=%Grž' áK€„TK€àA*¤Àˆ–ËKûYdˆÿr–­ºŸÅBi˜Hpþ=”_^¥¾©´ÙÚç‹p^4içòœA|•ž³†”¯!2;ûÊÇ 0•Ä0 KÄ\u’û…X'Y³²dd¥±±P:76Ç€½éüŠOB~Ež±g«jjŠÏ¤FömÃ8FílšGbíXÃ4˜C Û©k]ä"tQ òÍ^Tle­GQÇÙK!üä‡ÔËqh{5ÇØ¡±Suòñ¯Èqõ>¢Siµ¡‰,üa@üœ'Ê%QAýLˆá‘T-jE„n‹Ú ¥»%´šÀÉPq¥Bd­„ž³ “!'¦/·JêFj]U¬>%d‹2 t¼T*¸ˆ[…Øxrx”Ÿ(ëT>í>?Ÿ“7Vß«¦tB îã3@ÉÄ Y’ ÚRá«oÛ)ß"À†Ôé‘f«ýŠ£„Ü>MÒ—“ÔÉT®Âü½vo,ë#.ô¡;–ž76ÜcéÇm'ÔZq9¢2|S{1D¥À *é[sãFSŽ™›j²3œ…¾±c„jµýxà´YT0ž&æß éFWË a£zAøøÁóQŠdcýþ<1qv&[Ôœ5-ÂÍL¼)ˆû]@=°!ËD'9—ˆzc/£Cð$QºÖ-×ÔùZ(Zrx¤Àû¯nžÜ®Í?•*Ã*·çL;W†P.lÖŽsdÒ$QŒ=mÖ*‘\)h5ùôJÉZbö:`„5‘šUáÕ‚ öb-[•µVE¼˜Œ®Žü—× zsŒ¾?ɰÖíÑþ?õI!s³€f²ˆ‹.ÌÔUl¥cž(½l)SH1VînŸ.¡Ì Hä Mg,™0ý‹01*Üon·—±HÓô¶Ó™‚Cš4¦Ýæo¶ÉX¾†LÉi¤H¤1õɼjmsƒèžX'Ýc(¤ÍL%¹ë*#Uô¬`ȤWW¿ã<"BYDëtÌ¡‘”J̘vU¼™ºM³úÍ´ -aí¾ùR¯ÑÇlûЧ*–I\7sx5ˆB廥%´ÿ#{àE ¸ú#N<óF€$ª¶u"ªL‡6p+\i£Æä΢N$g뎸áöa@ BÚ—~B.L±… .¯n°*>ÐÄx§«ª¸Ç‚ÀØýˆg®éÆ‹®æÉf¼æfŽvìÔÕëg:MIÄŽ¤n*¯VÊBaèvÚÆLºGÚ~…X ÈÀOÂr^ÇÌj¯â>ƒ¸üBŒHªžìäÔ,åL¦þÊHˆ¢DTb@VŠHðCüéhàzM:ĆÄ$#”“%vÓï*ÿM¨±‡,0*09Šz{~· æ£Hܨ~ˆ<áìðÜ.HîáüH®@Iâ[ sj”ä$ž?„Jå0öæ, _„eæâBS¸îM¦õJL§h Óéôe$×£èqiÔ­FbžÄ„£Åฦ j` xmp%D:IïÈwå H¬Âj îfêì†ÞoQªH”kŽ^þI¹£83°ªCøŒífšÁ¢šô°T÷à XêåÊÆfˆ¸¨€ÂŽ:ƒt"†H¯‹­¥ÃÈâдÐËý"ÛƒVuçjÇf¾ÈÃ.Eì`4ŽK‹ÚðªÇÚäÚ‘èž­pë"‡oR9ˆ®‘*ln«ü®G&¸«Ègg¤«Í*Å€\ÍÃ0Výr‚>; hÏðhD²fà(&v‡Äj‰ åêvìnË´ËP4Ùð€_‘y ždpþpKÆ¢°FOà9ÉœgcHôã ÔbÃJ”ªe„ð" Üjh/M$""V‰þËqªÜ#¾ógX÷†þÆDÔÖ«ì%D$TÂüNpP¯±ª+í®À­Ö *NÖÐj›êÜVŽú”*>u *BˆŠêÊßÈþ]’\N§în½)ˆâ!DŠ¡!³Eèxf¥P<¢GÎ'Äe3¬²kë¹Ì4¡‚8Þïv½ð²¼Ê¸á*PÇRöhìèæñ`,é”vƒæ_‰â•®qÆBõó7§6^Í2ÙaøH©úg¬Ü¯/0ÍM-òdgo$¸B€(Ë J6wtôRi:Q³"òrñT7#:_ >%†y~j( ’o°æ2ñê-XdL¤±Ì$ ¥"ÁþH¥nqn‡ä«'«ss *‡5“êÂilÎŽ²6’FF據1Zï+ k„Gps3P^Fðc“ÑEŒw(ô #†hWÎÆÀi'3#Ã3Îv¢4ü‹M‘ާ®–&ÅŽ_í$Ϊ}¨ȮܦhgR÷Q5k8«ˆO1®2¤…ðµ&ô¾´@E@üëúdÍç@CÈÑeBÄòù$Plâ¤qg ¦ízŽ®²Ôk¡(ÉØ*H¸ê.ÎÐCä&È ÒÓá'Qq;@?ÅL•¨®É•Š)4ÕM;u<‡.héèÓ ƒ˜QU$±Q‹‡¡JK}R }«´aëf†Ó8ñ%åV¨âÍR°C¬â&Ðgor•ÉÀôg´&eävêŽåfo-Ñâjfä, Ò`--­×<%ùd~DO¼©”;Z®N*.M2F0L°ìK‘.¦;BÕY!.BØ­[GN4dÄ%ÿZjˆçîZ?–ÐÇ~úãf--*–6^ã0ÏbHèêFFó¬ªBt!CIn-Pii⋈ÏCÍaÃùâ ásW, úõrç35ŒP¦*Wuñ=óÈúãüÍH[b§o\¿T5 ð –zÄËaà NÆÁGܰˆþÅírø;kÝP¦pÙ²Ü4UVîÊ©­rþïèè‡#Ç¥šJåÑTŠWe Hl8Â&ÈžOQS·Skä11lsA§®üóù4³—Vð‰çÄ6S_eüzN/ð/÷8´Ëq×gJê—`z•¹LÑRõ.` ä ô%ü}ÓsvÑå[²t%I¬æ‹Ò$¯A4÷7¶9h¢=cH3§¿‘uBª­Cë|æê+"'j´ÏJÀÎÖˆ9<ýõ [xÀ½Ê‚þQnÑmB*Eh™8¹!8"|qT zb¥g/d5o@ÊJ¿E²ÿMq%uÒö±'-3%˜3¨\ÔÊØyp:ŽAðïŒMuÒ¯‹ðàã*%ƒÁûvµ>QvQd»¤âþËM†qú Iò$ ç—h‘m/)¡n›õ„±L¤ïqÿ¹¬!Kã.ÃgÆCšM)°XØãVrØ© øc:!ô1ðÖ·øh'Ó%Lh²†yö¢³2×ë¸õ.A* )j|L¦Òø$á]"ê{xIO6SZÇNB!S—ùœU­ fºó”þEÙéQoÀ Ik “£Òv2﵄ñ^QwB©j‹…•"q+¤•óXm ºþ27ªËV¤ eu5àoαÈBÖäà9/ ‚Cüö2°ž5Ò¹­óUÐiC÷j0„€‹"¡"@tC¬ž0õÊi±BJ± ’—xd̰ˆÿUaù²<âçpR€€B à3ÍDäÔ21¹Gç®^Ò«”ÏQÈ®köÄj¦lge¹]'Ÿ1ºc÷xd%¹¦b1Èèù&y˜L¯¼“Påxѧ²ðÓ«xµrïOùÁoqc´Sü±k¹‹f¾b¡:öÌе?ó®‹Œ‘ØóŒÆO`™¥5í¸>‹›°¯æ?éW¾²Fèš';e›1€™&— ¼%CïÏóö*HcŠ¿|L»k‚'®âlœ$ˆ‘û?a%01ú¬ÉìJÅÄb)¦ùš¿X~¼R¨Ø%£•Ñžï HiÅ9ƒÀXô5wšôiô™É‘9[8\9û`j«]ÃŽ—3@åvZ!Ã#TA•¸Õl¸[VŘ(i(JÅBüQyQ‹5‘©È±L-òLGs úº©Q—Ñ»¹(é€ÜùäãšsY%+îg.//®ª ÷zÝ2aöã×[ iã:ÏyÅ Îí{ÙÐäKVxa~$âß³ÇëþK"Üh #“ø#[?_‘æîhn¸g_®!Ê=ÅøŸyñ2÷™!Ý1FSTõ79rîäb,Ôúò¹¹¸ìñTžÃH”pí¸ ½¾æGÓx9àŒšyà ïFM(’¸N&1‰Ø;ºÜ³^_*ù1çÿ]Yxd/ÏË[ÿ…ëþý¸ñ<‚àb†Õaôi±(Ü·k:ðÑÚýGÞÄÙmŒùæ'ÎÜß{^•FI[²ú{6òzO@wöaÏõ"ÛªŒ­,ÕÚÚb ƒo”ƒ’nÂÉŒ ]. Èt‚JÂü?à€(0…a'ä0þ‰?b‘'ð1 Å#Ø0 !‚?ãð‰4ž?“HåHÀMLÀsWÔÞ9—Ä$qÈ„Z-š€åpX48I|Ræï¨Ô¾9&¡Î`Ñü:y‹D) ªôYóa¨E#R94j–ø¡ÌÀÑgݾ›¶X_2h´¾5¨ÂaR;¤@´à@ò×üB5“]$Ô)¬’Â-ïº G/‘Ù`‘̈U'Ja‘huÞ3 Èâ ­¦ÙU³Ø¥š´k@: ãA ¢Ë$ÑØ¥^.Œhdò8µóÉ€.‘üMýYï¶WÚ×c™2™óæ·h• •ÞuÊš//Œ=>‘l'´¤ömŸ¹ÿzŽ#K;¼®Œû|æ+hcäŒ9Èš(©&°Sòƒ¡ æ$j^½6ê0¡¢Î>©¬rˆ„%íó*ýBîÛ% € èÍ ‰3Öî"Nn†?ƒ¦¦ÃLz«ÆÑ€*~‰!ÉÚ(kŒ®&éz†¡žòÓªKc+Ekzä™­(ÔJ›³‰bB0 ÊÉ2L˜+ÀSŒ~¾ ŒÛ£ ôú9Ž›°ì¸M´Ã#‰V–±¨3.#Œ"Ó;B Òû0,5Ý·¨D8 Ò8º-iœ]E ÑS(·§HÃN‰D••@½´h3þê,.¹ý\2©î‚WÈ$΃2¯RY(‚8‡RÕÂ,Ï"T Â5Ë{˜´)nÕ–(l‚$Ã?Nœ]HMJjoUHÄ&æ8tÝ?Ûçó}?€2sRËGº5¬(ä? ‚g:Kö»J‰%ô‚Ü·ÉxAýn-‹JF¤,­$À£ìeá€Ý9f¡0 }VQ#á¸4öT⢈‚_0 X­j¶Ù´7°Ïã?“C9ÒI"?xí,é·ÍòGsºY6ƒiÉEÏÕ`*ÙЬ…P‰ï@áèâØÌç)eÉXÆ9ëy)¹{—"ã¹5á¢Åa^KÂ-µ7”ƒ+diû‡BšpE;çõëµ€—•Ý#eHü»n1k ª†.ŠB’ä•5ÄPÙT'H,sËEŸ­Œ›¥D ®¥B%ñ3jư*Ãy@P+Ô‰6ú¦öó{ [êÓÀ¿\-º›&ø¢“«¢­ I6`·ËÁýÎ"™±ì0˜a÷N^\„cpÑ÷?¹ LªÙ£vçîúêè7D†MYO\›ÒØâƒbªkekq!4ª>Ž cfýƪ"ɑ٢8 $ô3ò¦‡‡ûë&l˜¿¹ç¨>ØRÒ=ÍÚâÂfÈY #… ®bØœ xÖ†°ó“Uôì¡ikh¬²(eO"X#ëèÄ¥¢¡YZ I$½n&Ž~ŽÒb2Í”0û[;+T¨J)!4\H†µ.©6j–*­v8„ÓºHrÜQ6'š°û)X€ à&¤DA LC®dæ=”²|)\š«V|aÒ€ü†ä8~;XtFà±=zêdÂ’kÞ!5rà%æ‘Ò>aœkÅ‘/öÄzÓÁs,Db ŸÖØ‘ä?äøArzÍã(u0©é$uRàåqÆró/5ç¥Û†˜®í-)Ý‚8c‡¡¬'bÛŒRRÐmÁˆ쌬’nÂrªò„àøþ)©%³Â F ô"ϰÑE÷¢?šãu(œ¶ÈØŽ ‚7‹<ð@ØÒ¬›úõtSéÎwèßåá'jSp¶$†B§|ù&oüŠO¥r>]‘º‰í<ìNH亀!¦ E²iƒ†—Z¨ˆ¬“R!úö\  NŠ>úÒqHé$à5Gd°ý%ïlëDG¯[ę̂3yŸù4GÌ©Mo¬¥H(8fŠ"}­ÉÕ¶&RˆP|´ˆÇ¬ÏÆÓ+"«4ý%¦%4ÉJ«‹žoàŠUzÑ›q-ƒÖÅ3 0*hÿ‚urƒyØÒŒ‹’ä‘Ó2+ìãpÓ`Sù#+ê¶S§½Æ ‡$EžEÔÝ.œÆ.ó—ÃÇBnÑDi7œ í°Ê‚m?Eä¨%™wÀ1íµ*8Ð\˜tÌG·ÕôFŠmE®=‡Â` ÂÈ••°IO¬ªÖ€W÷7@%‘ºªðž¹âŠfô.dB’7õp·*†3ç0Åw#3fý»³qWDXµÌ˨oj(ìëÀðrfˆ[ÖBõFG–¿IÀï ºåk5¾tOúøÊåòá3ÀK·¥×dãÞ¼,&sq9Й:ãqæ ¨ñ¢)‘ŒßCŸtè‚Qiˆd»‹îÙ-¦N{3:;G lýb¤5,$?PM4‰­¬ÅwdH³Ã[T05ËVVz½…,ýW¢0~’x¼5€bB‡=ÝÚÉ{ñ‡5šÛ˜YÔ€ë,Ê  ž™5‡ÄJë<¢ In‘S©âÜVWE°ÇÕ«;E)È’©õãÆ&êè6aAÙÒò®T®Íb+κڄF‹íĆ`Ü~è+)º?Sæi=Œ–åÜ` ã×k géMÁ©É }H ·˜ÙsY5óãq€’v§™ ¶ègDßõ&ÝÄ –\ë¸ð¦¼ZÐ{:g%p½vç‹ä½}5üÀKd(¶À3¥õrc%ä˜v£g® —‘Š{!úin[ê¿0$›™Ã¾a£›lý¦n%$­Ör»MñrÑÿsv=¨µv(zÒ o¢þN–î 2i+Sæ·’Ê*ƒšÛ˜MÍÖµŠFLñI½Ñšƒ‰­ÅÃ:_2y §5395-}a—«EÉ­v#x~1ËmSˆMí±YOdìê` m'Iô×z`àiùw3ì\ t8g‹‰ç¿E¡:FÕ •¸®õ²'G3Ãì"Ù-"œ²>ªâ•Bã~»©#K·×kDv±ƒã=鯛LÃS9}¬Šæ½ÂÔ'˜ì,ó¨.‚Èš9ÃJ›!9¡ƒd*“*Cr¬ú;²_q¾©ÚÁ)ø¸* jÒ%(Àž8ü/Ž7c¤Ž´! ù¥ú¿D–9•“¢"¹ãr?óº®Ãž•ëè¢ðš‹ Â4¯?ÛRˆ3Ua½‹xü9ºG:Š®áÙú¦|,YŽÂt5< ˜ê‹ÀÛF 9%é¡($8#=L ­Czž™?6S'€"H²`º.Á̯u:¬šù.‚J#r*46˜àõªÛþ´ÓÈûÃÄ€–±ZZÀùÏ7”N3} ²>J˜ð…*û¾¯{6£ºD.ÁB)òè)¸ð²Y=‹&Y # ¨í84§| )øS²´47,2Ò*e»à} df½¹Ø5JÀ苪,·Ó^A±%*Á9 í\œà< Óä.¿b§¸¨„ "q4õ“ÃnƒÀŒ yGÃï”èõ´ó¨»0†ئÇã'¡¥ÃCݱ‹È‹ÂEÉú«A¼tUB“ÂÄ543²¡PÓ†¹Âǧ’—,}©™¡è·”äD#é¤B+›vBº‰‹{@œóG3M4Tɦ)z½Jè59ô¼B:Ý/€sD"”;ºÐàý2pÝ-Yã±â;K 2»\Êûè³Ä7¡Êë É±á©1#ú! µ³í À“ éµÌx›´b?K®­IFµúð­›u‹„T‘wš4D›…¯ ›ÅÂÉ1ŽÄ»²SÁ3Y)»ýÛ§äÌ“ªèÃ"ù¦’É-ù¾¢ ÓD"ÅS L¿Ë9 *’4Ø*ËŒš"¶âŸ IŒ )Ƶ:~ÌQ•²Ù[Ÿ¢’AëIÁjMªªoA(}E#ÃÇ#º*e¾Â+,D¡¢3à ã`¿ª¢ œ8”mKy‡Æëø­:¡­[×K œßÄ{MŠt²Â²›£&-¨( ,$•©21íÖ¿“©v|þ¡¬(¾sT?Ô…€+i¾Zº·4ï·ô¯Zü0 |¨Pø½’(Îü&‘Áª)P|é2¡ŽœÄ!Êá0óAš‘º˜õÐüõ%“`Eùn;##« yÒ¯”_9ó9¸Ã´Ï«õ p…û,˜ £DÉ9z½©©8ÚÏRƒ­®sÀ#£bH¨þ5›#¬£!Å 6à“Jw޶Y¯Y ‚"Û ¥™=Ù¬4d ó—ÒYЦÏÚ;6u’ÂÁºZtÑ›l'Q꺒£ÊF¯1\)å–±”Ó–LÕs'AMÁ@ƒØá¡ª’\Wªc²DLkgÐci½‰9Ìf¡úõ KSߥaÆKC/‹MRm«,Ô‡ºÝVc< NSr&*»NôE+dÁ•ÉT±ŽF FÒ3¨ZƒW€EmE ß(ÜT!ɺ=ñùac Ä#‡7ETP„+]=Ôå)TÕ*3¾5S Õ›ãNÕÜ”UžE$·%íV›Má›r",˜¾7À«^2&DÔ; *bÝQã=K:Ô ® é$¡[žº<Â=mßšp+òw;öG¯µáü½F3N)ú¤«ßãoLúá»-#ØÑ­20@Ãlç›êù5Íñ¬ž(Ò+àc_íï,2@G;ŸÏ‰¡:M©šN>ôíZÓX²Ý;št-/®hÂ9Þe(Áf ˜Ÿ˜¢.^JU¹‹à±U;SÃÆÖ_ÄòËO¤Üž¹Š‰5ÿ·!]Ù!±AyƼù÷-Xø*ÆK±-&Ða”°[ M&ãK–IàÉÑg17‰µÚ¸LFD~êï"21ÄÔ~Ç!Ñ£ð%í,ô¤‘ ]ªr¹´2Ñ_©ë ›·ìuœ ¢È#CIÑð6󄢩–â~9uu¶á®®¨ÂDˆÅ†[è}Ô$m«‚ÎÕœØh~ék –L¨ÅCÈÐì\ÃÍèÒz¿¤hœnÛÒ#;[bxíÎcÊY1.½JùhÃ>,*6ÖÔXœñ}H)ä¸ÀÈè¼R;-VR›£v[yØK¯ ±]©óÆÜÑÕNº•®<0ôʹ’ìAßÐæ-]lcäU_½ãÁ¾Ù.¯æ5h,fIÁÜ™ãÕŽÁñ¶ÈÉ¿›^Ã|§~%ˆÄ¾^9Áä>SÞfã<›;1›s¿HÛo>©kîª<N‘Y–]¤-ê:äî ŸÔ44.ã ‹ ŠÒŽSä~Ô‹<êÒ×çTsô“Á¢s SÖ\ÕyŽ™LmCÍÇE›º0=1H›”ciÒÂ ð”€ø&? G*¿9*Âæ‰Žm ª›ªð¤þ­2ïj‰{¹·bYÒ!‘ßIN‘rH»;Eu&a^>0õàg~ózò}q ÷9Œz¸EõòSÎ{ØâI÷=ûé ½(ŠKÚêCnƒîR@ºgT‰·›Íä­ÙmÃáyéß2qÑuظòïG ¦6޴Ф*² =My¤[‘•à´ç &«0ø_9ÏjìM:`Xƒר¢,}pE׈ÆÄD×£G$„j`±"ÏC·_¬5µ¨©Ò'kC6r¦âð7ÿs‡í¿‹¬À m`6 3c4ÑàB¦6/nìÐ_ÅWº—«~™É;F-]B¶¼¿ ãÊì/ÃggQ”åçIS5Îí耦c•CëYPï™°å$k;<»#r£Ú‡ îÜ7"McB0¢ùy2sÔæ•?€mÄtÄœ3°ÔÇ/m&UúNCb¥ ¼½"[‚YòW¯kVR¿x¾*zîkŒ/ÊÔßsÜïMBeçÌ7ÄÁyÖl‚ØzS®7+}¦³ÒðnB ïx{ÔºàGÑãê°€?`@  „áO¨dÿˆB¯È£ú,ŒC¸ö ÿ‡C£ñgôŽ/Š?!@8ì~%$”Çãò¸0W!‚GÀS¹ä’ú‡M Ϻ$Jk•ÏÀÔº#îy+|ÔA58üvI$‡KâÒgô` $ªÀ£õètÖyM Â¬°i]Z-Sc {¥6ŽÇf²¹$­ïà_;X]‡V ³X4’ynZ@sØ´Ö¹^žOëÓ[BžMdQ Py”«èßóZõ 2Ï¡–IÅzS$ÆA¶ù^bwƒ|c§qøtò½ש²g7M¯Gèð+l ¥§ÊáQùN«rºå4ˆVŠsž‚_"ÔÙ\J›$¥¡Ò™LóU Ä§“†Ú(Ž¿IÚ¢|µÎRˆð¾ˆ¢½kÒ Ð·MƒpƢ̓ܢ8®úŒ+Ž"pÉ:gë$B(Ÿª`Kºë¢Î20ÈD/‚–é/°ßO Û²°‹’Œ:§ëø´ðÓb­¢ ã⼬PØÏ P€Ô@mjüI«Â¦«ªvó$1 ’%­ÛÐ/hS²í,(ô“/Ƴr@‚2Âw¸@â§ìï¯çºá¢IûzŒ*ôK6¡Ã [¤¡‰"ï)È­+‘€òRÎG  ! 1"š³'iûP’E3$£;ÔJ%8GQÄÚÖ# D<KÀ¼ŽÃ æŠ>ÔuI_E‰* ”Ñ` †ž<.‡'隉J©B*‹<)­MVW¢k+°XõÏÚ(»! ããM­’½W,Î-,?Zˆú›-Ñ© \\ RVèQ³ã."Šúí¢ü™9%jânôÍIÚ›m×HÃâ‡)¯b’)«†(×LIƒþXsLvŠ%sZ>à6€ɇ´Ò5pÞ¶=#) Vu!ͶbéW«Œ¶ƒ@iªµcHÍCnŸ“+yˆ€YèÒ¢RÅ£7Ç9%Úâhcã”§mt>”­"x[•½¤Âlen¯;‹¸Š[(2~‡8òDçà:FÎÒB»4^p@o˜`à…§ñ[²03HÂ%{(ŽŽ±§[öô}u¢›šT…o'ô.§'| øò $ÀÝÏ)^Y O Ũ™>£HÝGÀJŸ:k@  ~ñ_+k’²Yw¬ê$‡˜Y,,‡IͰrlµ'~ZŽÙ(êSâÜ©ÞgÙ"ÁxLh·¬ï«š¬mµ¸L±µIüL~5h}üìNôßÍY~Š9`€ÞÁß9 8f?–»Uï°Ø=D$àI ‹^J9<©5T?XáEig‰ç’­Sƒé|-EõF6‹aJXa˹9ÔRç û-$ˆámĤfHc“rïä#ˆrFIÃÖPà<¸@Þ“«" ÁÅ’˜…TòL#ï½ò®MÙñ+Íxº‚¢BhB†D‚+#`a] P0 Ƨ®Û²K‰~9¥) ¢·JNyî;úWJÐ!–˜W«²à‰mL“ÄÅò¬ÚܰœÔ|QýP¤5®ŒB+è+ŽÚ¡Â xHéMOma€øòÂÙ¨y£îVº¤|WÂRFHÕ@Úkšq+%%Á²’‘  ƒð)N§±4›Ò½&¥È'üè—K6‰å343ŽÉ…0¤uÔ­B¢žS›ð4™<3Jòúuƒ Á´>ˆº,ý™òt ÄtØÙCP—«˜~9é@©aóa†† ð¨–ÂäÜ2I©FY°?’Z$–ñ8²em9‰üÞŒÑZp“)¶QÐ Œ‹(Š::*_å˜ÿ‚Íí«´¤ÕûMx+‘^Ê1ôl£Üi|ìÍ!¸µ^O ƒÖ—«Ìƒ3Ã`O)QœµR?ª÷LÃg`›ê}G©5 Œ’8¦fª1F—=@¨K\(†ì¸jíCÚÈýD lÒ®TblŠTùËúRB!èúŠmL" ÌäÔ߀ >;hxnfûîüMÄä–‹¢˜– ¢"v¦%ªôc^)ž[çg3¦fsõ%¹¾ÅcG‘É ›ºJÖìIp8~½Å”äSeM`q‰ ƒR9ôß¡M¿¸Å̺(i®ëŒœ Ì»zì=‘JìŽð ©‹ðœ,©A'Ñ?©›`ìŒfzQ¡'¸[¬î Ãm;ô0É(F—\•-9Í‚Ûb 2ÈÝX°Q½ºÆõZŃiÆJ(§2iÓÌ…f£ý¸’y€* ¥€ ºhâA ôÙŒÊÞZÌ[OEñL)9KA†ZŸ}©Ñ­[á©NHqÀgÀ»¬ZèSlÌv°ÂŸÒÕzj¤ÁŒ“FBf™+µ-nÀø³ Õ39S?nTasZüU¨°í•쩽ʸƒS”C>atNt)aÅáZ»ÑASSõ@œÐxüý'åÂñKÕuqÌiÍ~/²:õÎù®™°óÈ8‡g30ªOý"܆•,ýUóª`ô}:\+à‰4Ó™4°çdA!Zy8[Vÿ%Âmu.¶‚ïDßCñëWR¶niî’mmkî ¤¹«©µÀÜ7×)ó‹°à)O=§š!JÀÔ~˜ÑÈÚXHoZã7âÝ ßS N:I`ãÕLFIÓjŒÍ9iò•15]%1J¹@tÄzpÒ$xjC÷sÏ)Ñ٨จúLDJå\—¸@'|¨ê$âû´~ÿÆ%Þ¹¿g5ù¯‹jóhÑøÉªóÁLî@¾{½‡ä%# UqˇL©àÁß°pw˜ ÊŠ¯¹OíåûïcÔI5>1VšŒFJOÃéWH©jGnÒ·W¼Õ6NUéì^h3xÕR)^/¼mP:cÃE&{òb%´$Q×ôXð?³"ä»´;°$g8Œ)<8´„Y¤¬*»·ŠËÜkÞn[\MÌ’Ki¨[o¬}ú]3óE¯â&²÷.šÜû®÷•´wr0ku¿ÑäÛ‚³5i=ôëºÒQòÉ,p$ƒ]ôRù»5sLëáÒ8gÊTw.½¿N:¤øb€Ý4 šÕqùâ‚äõíÊKOï~ udø¬±˜Òö¬°>Xiv'„<úÍZ)kÖëB–™Jâ‘OŽö̉š¬‚B’j<\”ÖŒ^¨KLK”·Å¥Zc§§ôšã¾ð @Üe^S.býÅÐ0Úc€§$ò–MÆVî|¸ÇB%oœ*oþ˜Hh'ìXmøÎ%0e¢Vp‹Š‚à5ä”. å.H-’kv¹"@o¨¥áö^ˆ4ƒ FNF(‰vùOZ‰$l·¤ÏL̰dÄpæ ±¢ z/Úè.¼"Œ:"NÄ+JÜ@ r¼)o ;H#½eÅJì°­ÚîPàÌ«ˆÚ¸5PÌðb)fLû⣠)R•#€!Äü§¤ÄHk89 žp¦œˆÈ0\ R÷væQ+˾.ÈFɾäÆÜœÌw!þ÷KÐ_FdÆÈҫ鬔Ê<ÛÌÊßml¦úHp\OÞ#dÀѬ“ŠtôêÆFÍ»!R¡7O"'e“>j|VðRHÀO¸Ô6Üæ‘€ 9 #t*_9¯^§!åEìÈó«Ä|ñÆN0*S´ŠêUðnO*:1‘á¨S ‚Ÿ¤Ú²­8F(MsâW$‚W/ô¡ëJqi¢j¦nÊ;C$òÒgпBlÔX«¤Mc‘;I{$°…¤Àq(22þï4îÉ8€±ø)kîÔp:zÒÊH"½JaêU*Fqiv¬Ãjo£$ƒä×àç<<,Âw°©½§(qÂÁ“V»såÛr· Óé%êZmmÕíÚ'€°o€ØgA#è$çáü‰©zU§OÆ`%!»W/x§B$Y (dµ£&¢€þpÚbE'†™¨øVëÖþLÌGUJPS AM b„tïIĆéÅR´I³¤¶•!-LHjLÖó©\禊25Ž.DõNR9 .GU1XÑòþݳˆÎ)š|SOÔ#-åÉ^ư‚~ʵô¾E¨ÌºoLüÖ!ôdÒVá²ÊüOï2n$(Búµ÷ÎÜ7,G a÷&Ð_]°Ù_ÇJÕŠ‚ôâ—KGÌ œÑ LòËéÄm³lºeÞýb-%0“J«.ä2R‘Búbél膳ÕY#É,ú§ÚÖd˜‰tÑ_F) ÎŒxõŒœÏ—9ã æ°¯ŒºM•âèP$íe$CdÃw€ ‰u+Q¥Kë”å‰pâÓ:[é+ðÏÐ@†‹@öóCéB˜:#ë´È2ºöb ,¶”L¢åÄ*qs!2”6Áf1³RQ4@‰¯ïƒXË<+ÑÂâ"èar [•™K³Ëž**6Úr|€°ühWr¯p¤…+Äæ(L4«T ‘°s.ÙУ¾¾ôY]âdŠ÷•dFöø¹g ˜H0§=hUîeöZª{Z¯^m´¢@`}ñ_—΄×\! ¾Äòß?eq¶Tò #dÚØTàGSŽ·HÌ2 ‘XO.bHD­°¾õ•ªbÿ÷6©ˆý;²¥·fFrgQ|\…úp°lƒ¤«4xɇ‡4 ¡[%+8ÿë”»¨ô|èšì#[fÓ^¤Á’òìrÐÝÚsúNVÊsÓx)IÖFÏŒ»KÄú‘d®ÊcLµÑBˆMb%Eáå\ÆÅLWLÜ-ƒvËZfk­¾oQTÑ0ñ×ó¢¯0½{D°ÈM>ݲ—3#r@gäÕ†gw3ÌÕ–Œõä¥:;ˆÓ¤”*NŒçnΤÏcIwz«%|õ÷‡e ¦·Wæû7òxÕ-k¤ÇTä'à”f(ݰNA,‡t` ³Dƒ0(þøc(XpJT¦ÏØBÌØ6xen^‘_ÙZ¸âW'(ØÝ¨”!Nð׀Ǯu{KáaÕOf¦÷/Q`k§Çl&¤S&Il*âV™ÄÄs8i„Äÿ¹¾€·øÌÖâdÎöž°ê+*ZßÉCx†|ø i™]K¯þ›ù¸*pX–"‰kSrL$œÔ ^ ï#ín÷Èš3îƒ íUöÔ—V~qMùtþò_c .2ê(ÖÇÊ=  "£põÛfg3ëépƒÃg¤¶·Báã§+8€ þ*÷ ì¤lSBy§-êé¬L*?"¤¥œ¹g›1Öè¹€0U[—‰gR†”-%×H¶ìŸäv"džfY!»GÌ™'cso¨hw¢E"8çºx0òЬ59sâ¹_vÊÇã\ÑâÎ)¨’Þ{Â(­—†mqq6`Έ³Dש²¢dm±Ã ÷ŒkH)q ¸CÆḛ́»$[’#o!®i«ƒ9›7XM,q‘ Ij4X¦Z‰¢S-èäŒÞ¨W’6S$îgŒôKù R‡¡¹¾—´vÔä?jäú»E=ÉöתªÙÏ3nÆ)VfôÜÆhç0.GØÅnøÔÈþ\ÆM¦iÒDš.Ð)k¾RsLσ0*‚P"$¯Ú&C!²{´ÎÃ!,ä/ùFóHO8—=“´Ÿ¦[[DldÌA€Hì4ºå™Œ½¨ñ< ädÕ€àκÔù›ïBÍŽd¼•$fkµ:81KÙ+CzøLòQ1ºA³W¬í:ߕՅ÷K/êLãKVûRXG°Óˆš Zsª©­€÷c÷É£S¨&Rer骳.•"ƒ" ¦w†»éS\Úk»GîO£æ:Á*oýÉõÛAížRœØ>$ý%•5‡IÅ-¥"ɆßKº£/ƒ—« ¸³NÇ•ö¡Ìbé Bë „‹Á©Ì³T E)””!›»KÏÉrR¬˜»£‘¶5öÌ$0z{|Ï‘”2IĤB ¢ÂÆøN  &©"⛢þ_y‹ÈÝË<³Ž¨#k§f™¤q<‘5PT*êõ/d뺫‰wz‰QµÂ%OÃà ”¢˜ØP{5‘hí¦©Â½#AÔÔì{úÁØ« ¹ÖM°‰k•ކ+j°è©àbWÂûŠ §#³ÖJ²÷û«™³ƒ¶²ÞÙ[FÝd;üaÓšÒÝq—Mi¯åhMîA’¼GÕ>‹ +Ð÷¶Qw~ Ìì™È$pËWÝÐÞœÚ1"½ë°«(p£2¦z·±æhý»Ýú0øFêH€j–¤b¹¾vf1›ã²I^F—¿´WÛý?b¹A0‡‘Áp¢d/¦ùË•Û)'ýTáCÉì!¸É¡œc1StJ\‹lr‡P’-Îí1kÎ0<.–‹ìô\ç¤aóà'÷L–‚¥»U°Ä?s\åµÿK‰7¤Ú¨›Ížíó…;Pu%ÚÁòD%‡°p/ÎÙ¢$?°]¡Ä£ÃYœ/;us!Ô®*<†ØL/Ý&\ühÌ)¸÷“þò³¸cü!Šc-Ú iûG¦¥»b©ûµ¥ír ÷øƒ@ŸàXSòú‡?b)‹"@ƒöüÁ$Ì"CŒÅ¤çÐYŒ¾æ™úh›K¢P‰° A•EpŠÑý@|ÑâÓº$‚-€³¸D"3DŽÆé3i",ø¯T&¹`UDÙã1ºªA@ XbÖ˜„vG¨P'r«ÂA±Ð!¸%:!@³Þøš„v›s†P#¶9ìâ·’È¢qKû@½¾ê óâÇŽÔ)SJ­k;­A!tÚ­Ši¡“¼=ó;Ëåçvù†i ÔÑmÀ;«ÿ—Ø@°(í3@Œï¤Ñ*%O¹x×€:sNð ‰k‡j&ÛÎ R;;¨Q,5H—¿“œ|ùð>È+úÌ*#8Ù€I: £¯¤#pSüç º;O(±´i›Š‚8GÛ&Ê2B` I ¶è“xÓ¡KŠ%! ¶@(Š$ìZ€Æ bˆÞ:Àõ¹P¡ü‹!Üd©²î»fû'lãîÕŸÊâ.3hƒÜ…A‘P£©R,•0ëê ¶¢‚`ô'ˆ$û<'òÔäº'û"–*胈*\M3+rA²È$ŠORd‚ÎÀ4w¦ŒøI7‘ ò°ª’±·ˆ@O#¬::Æ Ì»¸¬©£ûÔÉU$T`$ü¡=˾ñ¥Pøñ'¼Î½©´×Y€iRd‚7”Â&€OTº£l:7N Q¼¸6Å6¶Ðù0K¿Gí©ùo¹lþþ?/£]mHNü)ÔÖ5ÕvÀèeT‰4k2θ Ê!±]´Zy Uuqe"Liú¢"Íe»ÔÒšZÊƬ-Úƒ9oê •bn‚(þ·‰DOgƸ±üûÁ¨ê™€B¹[;CÚ‰µ@³¡ æd]¯LîK@*-Cx‹Xþ¾Î«“€“„þÝ4HÕt#­[ÚηQ`È“C•hÈdõ)éºBiSioÛû?gÔÀ—J²º`‹<ÇÔu,¶q$äª †2ûBظxXÃØ©ÎI]éÞ‚ŨÔÍ•\oº;oÎs)û)ÚÖL—•-Ë—ÐÃ’‡-xMšâ¦åå/ä‹Rñb Ñ«ªúѬzº%¿EjŠmwÔÛÑû!¬/´•>q®bq4Ÿn:2±Ïuº v ' Šâ»g[­ê~²*ƒ6I´“šl‡åë\וwe´u•ߤ#¡»ü9ö‹MzM—!†TxÜÓ%Wä0¨:FàQaIL5\°wš¸A4Dޤ~ŸÔ F °DL4¢9BHSk?/d…<• B•ãÅ*ð±™øLSÔIÌ©¤’z~×9”?o\ƒÃîd °„ìò²e ü€”^¯€ä3W€¯žùƒe‹ŒûÕ* iðùX$UŽZn$§Ý'®" ¶J>(ñdã ôo#S~,-ụâŒQÒAp¨=Í‘F ?!¢I輞t¶ÞÀm óŽxÍ^(Žð›§jÏÏÊÀ§H†%`PÉ¢ÓòXGUhúR)¸‘zF#g„@£¸,0åÖA˜Rul°±–]“åûšå(ÍÚR'’5Iȱ˜H¯q¶­´ ,"ÝOËÕ¤ öлLºø•@W¹€ÖûÊ!m~Iô¬þb›†k§ìû®•dÖVZ7Pjœ‡*ãìÄêé9kÖC·™”üGåIDe5±²`i]ñ7(¼‚ ©9G_I~^ôèFXèù•úDø¬AñKxœK6+Zy;‹Ö&ÑÐkŸuN¾E¢=*%‹Ž7gàYÐz4fÉ.cº—‹” ‰*•¹6>‹¢)!Íš\Á¤JÖb9n‚ÕN@«ä”©YÄÙ]nµâ´•] éÃBQéÆ4­‡Ì?•t+‚cùvÏ#ò®JXfiRº¾‡BÅIÛ„çí‘UÓ¹—á4¢@Þ-ÏL9D¨CЋP *«° UØ~«–ª×ÇâžU¥ËÓH#O©É7¢oT9%¿ X—ƒò (©Ù"ä5®±Š¥;J’¥†ã^çZÇè=¦ 0V ¦Í3ºgm–«,8÷@[Ê™Haâê“…ø–6¤ÊŒ½Ñ”íã,æ’éÈ¥ªðf×b¦mó*v€kPKÇ:®ÊéÀ H¦"XÉQ´áµWHÍ6Ô$7îô—5»î»_A—¬gòäE>Oò}ŸI†áfAäõûuuªÅ(’?DEzp…×T¬*™ãAöTþ’§vÈe¬W‘ÎØ.Ù(*cnq.R6”ç„][#YÌ ƒ]Õ»ÏÉÖ"SKò`«Šy Ã÷EH¸û²²ñM`]RxV >Ìb®(M—$E8¡ìÊ‘øk+Ér½]ƒ1žÙ⪚«Ç‡9WŽÎˆä*¡l^b¾ˆ}:H68¿‰*²² \–aØn„¸ˆ+ÆŸ…‘Å7W`Ñ€aÜ•„¶sm¥5¬¹[e{•©°Æ†åÝ‘%‰[²í:CºÚBjµÖÊøÎ^*Ã$/†ˆ9y!ç-"XmãUG€’òøIbõ-ƒ%‡й‰iÜNúѨÈJÙ¢µ¾ÎûG5¢(2Nå!P"ÊñŒM*èèµ,xK˧sK€˜jÎÑÃûYCòŠN®†:Wjî—ÂÓ{_$¼.زˆ¢+ xªÃ0=sœÔ–¿Y®,£òhEª½îÜé)!óibìéç-¡Ř²Fe!Y“¸¼’®]»j- !ÉËtÆ®,®´«Õ¶ _Õ—#óm~e[# pò»4=Ì>Úæ›º´”fÒ w„e@rx˜‚Ô¤ßáDüç;ó›äAØ8À<¤F4nLy–ò¬}ø\0Ä`±äûj¯§«6M¾**lV?”j­d¨ÏˆH=I{©´ÚÞKÏ㊩P)*AþfÛÂ1®'\šr)èʺ´?5–Á¥³vmu˜•iw)0IMúôºÛsOõ§ n£îFâZÚ×±°b¶«~ b Å\"üŠ_ÑÁÀ1ãõlµTDô‡TÛ¢°4wLÐ{¥ÓJôû&Ï¡=#S÷¨rƾƒ‡¾¨‹”#P÷‰¢L*Ù¿ ú¾¦ñš,X¯#Rï5Ñ–[]ºiˆd § * p„Y–믫©î±s› 0³¸,–´j>Q¿š±·}£È|“[¡#ÒXû/Ñ´kÍ¥ @4•‰b 9´¡´à–;hÖX‡5Ë5¿@z•r@ÀZÓŸˆ¡Ò8ËÓ¹‹Î9â›ÁW õÉ )5Êó3„/7Jj q²ci:,"«¤´* *q²ò{°|?¢qoš«³Œ»q‰‹à ©´p}¦ˆœëA›’è¤"(ÜÀÚ‹:d›H‹ðÄS5‰)ÂÀ}(´.*¹%ù=%™7JÒ^3Z@¥*b¢ò¦E¡Ä–[‹1ƒ½¬!µÙdSBs’Ë‘$?-(Ñ“šå¿ã¢¹áw.˼Â[¢¬ÙB8t?cC !®ŒWA“u1@*H°úä<â!ä03¯BÚ ~ŒJA¨êá•Ìl ôR¤“±’›V€z9Äêˆ ¢Œ,²­ý§iQ/éþJà˜°˜ÔT¢zå²ôˆ™«›ñr¾z·®* –²Éž <6Šó" L#¹ê¯¼¸§)Ê9v©*bÉD‹ +C™/4ø˜;L¼¢;Ø ä¦ñÊ/r¥®)ÊJ±ŽÄk±Ì¬P€)e¯ìs)뵟º¶D7¼é¤¦¶/t½É=6#²D#‘ šþ¼ª@¯s «Yž|—Sɾ‘Õ9æ#›0T,¦S]ÁºÛ*:E­¤©Ô§›­‰¢fÂv«¸‰RÖBã²’ñŸ>ì•;òÂĺ<4^@…%Üæå7·sf…ÖÀdøÍD:–ú]Á1q–&eëX¤Íá;J³jL„=lSKjOâm¤’ 2)l±]»e6_ÔÀAí.œÿÇuÒ­œéŸ` 3¼[t¼ŒS‹8‹8´ÚÙÕ+¯Òƒž”»‡ës—­?çN á2!Ôñ7K ù´Q´TéV”›ˆÓö`ËàÖž"|(±^‚˜PÕ™°¶;8“Û‡Ùö"c /Û]¡¶›Âù%¥ç>ª5+â"GûF¸YM† ª{°ÆK`ĵʖáƒzß„Ï}¤¹KtO¾1Ìþ=¤SϽsìŠÛVu1¹"l2Ä~˜.b…]ía“ZIŠ!—¢6@°¼Jª¼ŸF‰€E›8Å­-äêãfœ×£@ˆ–V5ÍÂbƪˆ i¡‹>pJ:>dÈNNe#£ÛE"ø©ÃÚA i+U`ïåßÁñ†Ûô¢ìùb,Çâý\FTÞ‰X!nŸa›[^ÉçØ–¿ŠmKX»‡õ2Ò˜’Ñ©"¬ª]Ý-^\V+G:BéD²¦+%IΜ))ÖîˆÛM€$µË\•†Ä¾lÒÊš#}óUÓxÁ™K"§X£zÜÔæ¹ôÂÇ¨íµšÕ,Pïæ}6³þÞ~åÏLt;s yæZüpªq¾UÓö›ŒI†Ì ~çÓ·po¼qp Û2’y§E ¼»2Úâ Ž3y?*b ¦‘î•Í‹8¸}Ó=øïø%Ý< q¥™véÞ²–k¢ÈüÔ+:ležhš;Û;¶õØúk—S€ž+e¥mÊÚ4ôIîvàüèUŽ­d2¾WìùM fÄ”eGÓv+òš¼¥ÑÙ£Áö„ÅÚ4ô¦ÜSAIãs¿>(‰k®D+jAÍk½ö»Ü·ïä¡H*ìÄq"Ä‚¾¸³¢5$7¢AÍ fS„Õ ‡¯MUi¿Ø µ¦\ÈXœ")9¯ i5þÙ%bwòvœ–fŠÄB縕3õ5"@ð•+§%•£¾1–“œá5]um½Ú….Yº9aÄÇ8=´m¥ŠKšèPÿ9lE"ô .dŠ—U_GV­äÚ<0²–°^Ç…©oš?lÓ,2µ§ `¿ƒ±X.ŽD¹ ±äÂîR®’L.8šIp«f4‘§ç†:Í}0‰qŠ£RèÌ‹ÑØAâS—b¨ƒG˳x#TDV±ô--c+ m‘ÎíÇ}Pn1Æ¿WdIk(WHfOrV…áÆIBR§yYní6rö`Ñ l9†z:,—ü-=ËîaмÚÓÊWöš§G.€5‡ ÝJ§Å϶ç ÞÍËÞ$70±ô2jŸº©ÎÌ@…HÛõÒà•&y¹toNk/Oµ{ ÊýMà’–Ñ1Fg&i"yºAæþ\&"ÓDv7JÆM7íǬ `ÏÈ@&†@Ÿð‡à $ŠD€OØÄBþŽE €0 †7‡C¤2pUŠKeÒȤqý.ŠÄâ‘‡ì¨ 2œN¦S) eD$àZCÚ•‹Pg€,žq@ŠIÁylŽ}Wa€w݆‡¯×_RØýJ1TE§ù”ÀV«¾.×+þ¡‡D'U˜òS’@­ID†ƒyÉãñè$C 3šQé(Ä:-P‡Y§­ºq¸G%´§µ\š‰C§Qh3æe:´È W‡üË×JàR{ îq»“Ü¥¼\4RælåQ´þ;LGñ›¬OK(ŸG#ü´B¡Ú–×âÜç ø©۳≾à>µ\Lëƒc¦IûJúdت ;Љ?‰Â¾Ø­‰Âšå0h 8m²„+î¾-ˆ9€2¸®¢É:Ì­>`"["P˜Î N v–§Lbƒ¥Í1€O³Žº.ò‡'èçŠÒØÝ­è"¡')SüÓ"Ž Ì„’¼mÅ,ËnõµOl¡#’ZA"N ^‰"3pê)ˆÓ£´ØŽJ'óY¢‹2?">Î 9>H(í$ïÒ¯§>Éât¨" 4?Ís¸ö.ú“ÃÎdt³GQ:y9µ´ 4>“˰âHŽ4²sÊtä=IúäâB‹”ó6²+µ);•[~ÉÑCVÇM,ð¼±h}Àp¢üç¡CxSà3'Nøp¸2)¥M8}Ï©Œ€´Gím"&V¨º“wVÅ“rŒ¬È´?)ËSÖìs"„8* <„]kœÌ$í‚ ¯«Xc-Ÿ¸(‡øû,ÒŽbz•8*ƒì¹U©Ò̯©ÑôÆ!ÈûU”Ø  ~IÌ=›ÝõÍu(5ŠLÅ"޶dû¥ÏJq/Ó°¥•XÃémÝ«Q- •iÖwvÌÚ ¤\qÍʤ#÷Þ œV a§åæ„$ðû&µ^Õß7CÝmfxIù¾3vÿ2€* q!# ûð¬«2ºª ŒïÎ(½L[óLõ¡î'⡇³Ð‚‘Î"¹ü½ºˆ…Ê$-WN„OÕã¡ÌGò?ÆvûRiÓt*9±îü>½Þ•}´„f¨£1á¨;:1#šÁÿÝ'»ª‚Cõ.6‚?hâ¾àÃøùïè@Å’s(³â§ìÈ&ëdØHr¯¸t˜¤E‰o¸þ;§l™"ån¿]øgŒi2?vàtÞÊî`Î|Ý­…ž¦˜Á)dÈd‚#Çމ“ä*Õ':ÅÏGúïdå" +p˜ kL/‘€d8dÉiPJ„0ˆB Y #õ[gÅ©¼Â\—zF!È]¨Ä>YŠ*©åy´bí“süX'mÛzN€!Á‹dµïµõðÆ\lDŒlá0¿ÐS³çNìÙM4ˆc9Iªe¢­–”ùÍÖVM¶§!ú‡Î [o2 Ú€«Öi%Ñž5(t {HB­=*ÔÆd p,ɺ1úÆ“rØ|ðM„IÖÞïS}FŽ<¦äÈyÜj­cÌ}­ˆ¶y «i.Ì0÷ C¤+ðS2$¶'—Ï& D‚kba˜´ÒMÂ’!üôÀB-ˆÛNÆ$ØÄ!Ï´Ì;OaóÇ–¶“¢ä8F’·bdÃÜ™g‹’q±ÂÍ’sEå„ð¡b>©2>,¸Š ¥Úžc¹£Œ…ˆ<áœp!L°óøE‹4’m©…VŸÃøÝ§Ãv<¤1·£"T% *€5 @#þ „B_а6 ?b@H  -…Á0gûò=C£O¹ M|J@Ò¸Ãú Ž>¦Q`:9šF¡2GÜB4‡LŸSIÚ 4¡F£Sˆ¼69 ?#R­TWŽC«U¹¼°=ìQ 5” ‰?bé„…•¬¶'¼Š 4¨ÆW»Kæý@®WcQ ŒB•»FàÕ¼`9µÃcS˜$BºÿÆañOüŽ:C°¨å·9 ŽZa0ëMN)QÕB$I\ò…q´È!6™äÒ!¾…Ürú˜•\tŸB#‘«4š9Q¿>l°™KâÀÃeuiÆ£–ƒRàÛØ¶š…ÆèÏâÙØå–ÓÄ´¿eñHÕFË—r ÙÙ¤&8깫;¶ÓŸÊŠØŠ1,êÊÆ+(k …¡HÊ¡?¨Cb¶€3ª‡!- ï¡k*¢Äj´¼ Ã$éèB4èÁªÒ@#Oz¼ÀÊÜRÄÃÀG1jt‚?0 ©€R¸§‹Ë4á-Ú$ÁÂ@ ¢ë¬ª—! 2:FÇû˜“&‹L̲œN‰GjÜzÆ$ ž" Šâ„©3Yû1Å=:飣*Ì Ö>3Ú(ß´x´Mƒd×£Èrʸº¨‚x„®)H–Ê0²$Ž:òÿG¡iã;BC³ì|¦±¨„(ò¢©£×®kZ¤ ‚%]ËÑLÞÆÈ•tkHŸÑš)9ŸŽÍPÈ#Ž2Ò²³±5xú ªìsb€0¨(KK„®Î¨òhé¿Gúx-*‹®²$ÊZÞnMém#×”‡1¬ÊBdëžX ö:4í³VÈ´bñKçåw3OØ€¡Ôš> 5D­9HlL“†=©2èãYˆu¶¢¡ªÞ†Oκ„ÿ3qí Sk­^…¹j°%jU)%½/cÍ*†Ë)ž`Có¦`«À wì$ú¿u¸éW›¼n(~6"$¡•bésd4¤xÂW(üRÇ8ϵ¶lJÛk}Q«uö£ª”‡êÛ…6‡JT\ê·Ð)5ødÞVÂO--5žÃöƒ×@bN}{4 5âCÒ%jļÁöCŽ»L}®”ÜÂÐBJ¨õq$X¡ Ú§‡Ú¥!°íö•ðLŽ4`~ªœÙ¢LtW²ÎG¦”Š)´ºÿVln¬1¸€¤Š‰Q’Ã7NÏA'ŒdIŽ01í#Øük€n´Š;U!ÙQ=ʾ£<©Öd“íÕ§9(IX:[lÒ‘©½‡o*%:Û*.¸~¤Rx’LLmËrLÂÒuÞÜk‰Òè²Èz ó[ËÚZS¯Êíz§œ«»•ü>¥ù`:­ê,—€ßŸ¤#&‘dŽ08t_«j„Õö&žžÚIKqT5†$f›‡xdZ2H?Q >  ½µzGã©$`1<€ 0]ý!o2ðIŸÛc‹YݬC&¬$ªUÅÄ”–_)I»¹gOÂDP箓 ,&ïU Á˜æA¤*EqËœ“(CªR+ço‡ „g‘FÈ’ë"…Ɔ¯ µŠ ÿ,©I<Øè¼{`î±/HW,Õ¬°*1tÃd”ÿÊ„š$Õ(HV´¼Úl…7K¤ø@¥™$ù“éYÖzQ+\âCtv^ØQŠUa’ÞS6jn©ÝÊâ%qš‰®™Íá$xDIã*æJX{Œ”ÈÅ]ÍCŽX ¬»{Ƶ%V>ĉÕ¤’.ZIhìà!Ú—mvaNÛ7 Hôï”òx–ÈS;[àê†F4A[X‚ßa•n Ô±8‘e2®#y~µ`ãM¸s^åϰ¨Ê¥’»¼áÕi4'=ƒ¨JUÙ—tÀ}ÑùØiºm“óz)°w>Ka„‰Í½?J[aût§ Æ-ä/€_9dEu°Ã"…„ Qe|âÏJf8]Jü²@àKÚá?y~Ã$™ßVh¢€!'—Ú>Ðx5m Åœ2úF]ìªgÆD‘í¨Dbµ¡ey"Ö0¸éäƒÚÕĶ+g„0âϹx,~ÓÀ P€[Ž8žT{|_´ †Ráb,æ›u@Õ’OýÌÚÉÚ¡ eŸSO6+ª·Ú¦@œ.¢I™ìªÌêÊ/s‡†è±djº¬«ÿÔ#´OZA;¬ýÆ!s¨XG“œxqØÛFªÓˆïi·ën¦)™X].bж!vÖ  ãn·RÓ:¹‰Ûó©± ŠD¯gàBCsꪳWX¼òa ÆvØŠOÓ;“ ëÕiàznX6Yùb3G^Gj´ëY$£˜y79Z¬BnµGF-€*®õïP,™ÿÀËõrNG¶È•íbI'‘Mx¢£þ16UÒÐn:‘lj÷(³±–/ú”fò)‚Þx\ÓU }“Ì„(8Øï5OáøH8pûÉ Á{8ä®X-ðÕö_XŒ’]‰eݧ^‘çù'ÍÐ̤šßÕIí'þ’ÀVÑC^ÖwIJ¦yñZ^€ÎŒÕn¶§†kÔ·šá’¥ûªÛ©[^ fb•­éB"–4ääÄ.m’Bš>+Û[ipjiÙkãÌþ¤ŠpVT[üÅ)-"¡Lé¤$5||• |uÑr 7c;‹^Ç\žêŒrât¹ƒ#JcG¿1ef{zÜTõ‘—¥ì–’é{q¤“„9ÌD‚8)%¾«¶ÿ¡ð}Ç!v»}°RÁªÃ‚RÛ/Wåá&[Aƒëعˆ´–YÕ:i“)=‘û’Ì0ĹøPĶ.“”åÒ¹£‚^£‚6¢H¯¦´‰°|ÔÉ`"tÖÊÌ«Š†@„P‹Ú4Ϻ¶ à ç.«î‚ŽÄŒ—bh­ê“ÈûÈ•Œ|X/â1(+h‚Ò«[ϸHd.(Mß)<˜Â fÐbLÌñ¨óÉúw-\jy t÷+,õGRi­¶ZêÛ'J{°´Ô©rr!þåÀùªZ߬²û0:z̺"ÁÃ!­Úê뀪±ðþñ2| ö¯Ëè½G,èpoº[¢òh¨ÊdžÒÜä´@pð£Íì)QÎ2E%옔ŠN©ÆC/Åœìð—Q”ý"üš®zåIFÃRË*ô»q*&æ8ódôZϲË'È'bH¿DÎu|„Âßãâz „)N¦Ëâ,*&P Ê~lFÏ+,¨ É0â&ŠÄî{.ˆ lA'Pº/>P(dqÉZá,Ý¢8s çrÇ#â2ðÈ¿K™ƒþ%"@8У*L:ç‘+«*­ˆÆÒÆøˆ,¶£6‚é!*tß&R f>²/~„o¯2âZ•æ®H¬ÈÝ«”Ë‹ètaô^Ç!²êYËÚÅo|õQKÇ«îÎGÛ*NÄð¼8p ð2í4R^”’ú,xÏÖóºð«r¥Ò¾ì†e8hʈÜè2ÁÌt…æ>^m¢(…*ˆÓ«·ïºcgœÞ©\}pæBoÜäQÁ1BÓÄ”ëPa*WÀXÃPÇ«“®Ð¢@.]<óoH4ÒÔ´Sôƒ­I,!ƒ6ÏñX|"dЪX¹WòêíH§.o̳ Т•°&ÞïžYãFnþIôˆÁ‘jÊ­RϲG5Bý;¢8j'R˜·KŽ+i<æt“ÈPÀ< *œ¼Llõ‡å-Ò$«±2no§5´jë°À´(ãÅv‡¦v¯ìÚÅÇÚx’÷«1.æ9 ¯©5 îõ4ôµI´û#£JŽ€Qb .z!¨ßÏ5L€hrˆÐ\¥B=,pÙPï0Fä¼c“˜ãtÔ®rÜ¡%‰Nu‹g:äš#Ç¡MG°ûûU©Dã²,zñL ßTYå…PòC2Q{@G¦”V ®ÄnŒP{eÑæH¨!nðcAåm[4íI•~jÁ®ìpÞœÈðú4‚žôT±k%ïðªlQÇ>®¥ˆ¹•À'Š‹0ô¢b¬USQ7nF“ùZ1ÐÿªîºbLݲª!‹?ó®„ô ó0$ÒNÐ{AIvSj‚êüì‹îp´ñ<ÏKI`{mœÉ%˜ž•¬ÌLÐ&ãì$Öj°Ý®8C:m§µ5Ù"AL•ÈéË*^ÐbD¶ßEL&‹~¯ªÊä¨Fƒ#®:2Æ·³®_–¥QÊ[Ì›bLv5ΓìiYÄXÒ4ue'Xìd?0l YÍà§Yn³\õR¡<Œ²œ+ïFSÂY l&•b£UÑRæ>Y*›BU=Tf¤DõõáEÁôâªÛR®!cŒ¥‡´Ô© Äi ߨx f¢z±IÖí.°8ÅIë4,Ñ4DRЦ؉Û`Aóh“jâýV¼Ñªû-:þ‹|ªväŸóv”¸[“ŵ´ä”dˆnE?ŸâjÙ†ö€´#ÓÕÊŽ*'kÌ줽k H 4{ŽE9Ëîm­ ³æüã£K³¬¿ëhL#L¾ÔëÃLKl³9t2!ð¾ÊØàý¥vee(æè¬ëÞæã-èÏÑX"W\d3 Uó‚R ÂÌX0µÑAEp@Ò+íè×v®Nò3kÔÜô'<‡ÌV‚›±Qtö¨’€ߢ þlíSÍ—(u.'„èðʉLoGY\mƪ—úJ±š_iÖÑb)+ÉI ð£†vQWOÇžú¢+P¨çªÚ7‡B¥an¢h.†eQç 䢪‘Vâ÷¬ZËSŠèôÑ«Úç-Hõ'jc}”†V ±¶Ê%¨ÖïS¾äÌѦše7o@T¹Q" Vp_cN’ø(Ç“EE¢ˆ2Â-/ø¼  ¢‚ý/()c¶ëƒ¿L îÖ´.•†|—ýaÒȃÓÑ.©V´bººå’"‚Ë$Vw\*ô—C/·l‹íJµo–8Ãruªô—””æ%=±ªâÒ\^8ÜìBL…  °.Fç€Wu3O« 6)˜'ÜJ©&¾ÕñI•{4H½¥½Ö»ñFËÔ#8ëì`¸.}²ŸX;cÌB·YùVÑ&ô#BÆ|D“1ŽD§4p&ð†8ÂèkIu\¥ìÎjPH¤.u˜ XédFÍ—y²r|! úKpÈösìe΂dbïFÐ0‰yp……w*R` föÁ*Ÿ¶–WP-ydb|V¨•î”Ŷt/â(Itÿ®ý? MhC2„ýWîYf×ÕÙ‚5SqïôÅêø®óõþûëhÜO<#Æ:¬G ̸ˆÂ5$Yì¹Ì`å· xÍ)úLéhòùxŒ¬þ:m-©a{Á˜ºG]ǰÄcà§hdÛÚ(!+Vr+N#‘ÕI¹×W6H´&"d½«R“ÇÉ1>$™fa)züóá·D.™§¨¬Ø”øCcëh—GXâ·š»{ˆ¯ÃöXÁåÒ…ç=.§m»¹H&´óù÷„®³iŠÌª†>÷¦°TÈÿJ"ü`b4Ý¢ûrj ŠÛ:ë™i òò6ašÍs‚%¼UË\ÍÏWvÉ™Û4Kù:sÏDB•Tr8Vë—Ç·˜Fï§þ4Ó”]$·²Ö y8ô¥çA7T>0Žp|=ŒQС¹GW'r{ªÔ§Jß§Å¿ëÇ>T$+hþ«Ë+7”`îÚoÒ62éû¢úëŽtn{ 6>(Œøº?Ôz3`/{“6(“ÏSÏfº¹†>žZ ¸z¯ú%¬Ålõ¾Òްš Î4Ða²˜’×v¼>æt|‚[Ô·tc•Ê­‰i…¦´àâÝ¢  )= 1Fë„5ÖJ¹›ˆ$†,»“ƒKðûQk˜é¿ÄýŸZ]·‚lÅfõkLËÅˆËÆz¼æ± I!´¢eV%ËÉ[Óõ’ãòñjñÑ­Jî „g¶å|wÛŒ8„Úmä"S²FûZ+§r3Vn#“tì²<ÍÙT+ì¼G»v0É9LôÿŒ= y|_XUIˆµrWz°îaó©“*ØqA–\+¿$"Þ—%)vh¹RYMæ@—;WKíàºb1Œ/{‚VééHL'¶sø ãÓ»ï…]ÂÀ:&Kh$Ï“ b…¨ö øÆ$Fó5“ÛR\ç÷ø8QŠÎ¾¥§K›ºçB%Ôb¶—-jõ– N1ZÕZÙó~ΆР8 ýƒAOèT  |ÃÀÑ$Mÿƒ?aÈkî9À€qÇÜNH}Iá zþ&Œ¦A)‹¿'‰”Â=”Ïèíw2h³8l²£Ñå²Ð=Npü¤Ì!Ú-ja\H%²J¨É”Ȫ`x¼ú—¡El€ZP†ÿ·¿ëЊ¬D '}F`—{œ¦cU‹‚±Y|Y¡±z.2®”Â"ò)f„˜c-q\ÜWªÜîð‰ú/ S°\œ6‹²®ÂœTs_`§”9n^ q¨Â°³çR©ÊoÖ—·O „_¦2 ¬¦I¡Í ×ÉkßÉ|˜Ú{ ëôíò=æ7¯iÁïã(?j®ÿí£&.:\¡¸€<™%éÚ<í²(4 + 𼱬ŽÒpÍ K‹Pû.°2ؤA*.’?€¼õ¾nBa Hô#Â3”¶Ÿéâ²%¯ZøªÆ("R.)J½' ª*Õ IlŸ¨ð"ª÷¢ëJâë¥ lË!­*ðãÀ‰j˜D+t ŒÈP¸×p ´–Â0 ¡° â$’,[>à "›§òDã!I#²&)"|É`Y1¿ úë.¥«ŒÄRhT'10o¬¶ºM)üœÊ®+«$=S\›@"°2bñ8ì”\‰¥´É L³ÛgÓÓAþô€$éL¢«M¸Ö -6˜;Ô3\Ö TRø‘P¶\«ã “˲É KóÖ’DVü»E&(E¨?q‚*éžÉ"ùFNËò[i7ˆ ƒ.5ýÐÀ,RDÎQà / Në˜À‹»¯.w*mâru^/Ó"zÿ.³byê¡Tfª¤•¼ùMsbh¢)M£Óů6¢« '@¶÷ÀºÂ6þ15hUÄŽ~b'ú.Ü €E;ˆ¢+¦.êªÒ÷¦¨ji¢lÆ^k¨$Ã\2°$ANìÙT”ÀªóÉýNWnô"Ó³ùîãJ,‹¾7VS¸Ìì¼°V–‰¤O4>ŠÞH%É¢è6î(ó¶i6çô¬‚WèòÒ„]ñZö<‚ ôin=½€¹"èÔùÿ?tª,^çh½Ã&3¨n®ûbªàl‚¦ ØäŸ•"&÷éëÒq¶ióz E[îѦ(¹ñï`?5õX 8¾$¼ºeSUk³+¼Woô}ª¯a”mñNÄ´¤?‘ Ÿ"p†GãÕFL˜œ%B¦Hš{¹$í1ƒ TQïj€.²Â{Ûýn/´’à·ˆ«Þ !ª¾Ò¾¾HJzBåÉÿ5fB–9"èøœ3Wc Z"h^©rùá‰Q/ÅËBbHž,Lž! büó@$nO½Fâªõ=.ïÞ•мázÈQ†dŽDÇæTVNnÄÔ›jU‰Ü^1m)¦ÝØi‹h}.§‹–cŠ… ´¸‘•Ä>ŽÏ]bGÖ„Ök¶}cð”È†ØŒÓøüeŠZE©Ø¨±IËe‹lyf©R,o¡T•‚¨ÍH$ÛóÙnrxž‚øk³•@ —xñ ¢}Þ#øâ³UêŒ@(̓ËéHTU,–hñÔºµß.‰Gx§­˜¾ÅÒÏÔë‚8åÍ”½Ç"û#x$ ]—xxG|胅&2—S.É$ƒqJ%/²ÈÚYüWs ʶسÔj§SÌí¨è ÛÙW³!>èt£õÚ¼îPÔt†lgᙫ„PQOy{"O¢M£4DÅ‘Êf“1µŽP1ü×Û)@ŠõH4÷»˜Y±î¥æÓ{ï€üŠ»¥.ÙKOšÍ©]˜òi!Ua4x˜Néâ>ÖýV?ÔÂ…tÛ'Èý:®g¼¶"üôe%ÖF²’eZ×xuj¡€nkZ÷eò*.ÀEIÁÕIÑD²WÖy/é$ª ì¯S§F¢„Ì|£í§·©0ËJb›ãòÇX¼Š jõ!G “ÆSÂDmY'„À£Ó5=n$DB¤)ø¶´ôàÏú²„xkÜr[gÈl$1“fÓ pÇ—U| í-KôÍi=½@#ú1jm'À "´ô£’Éf);cÈ¡ðYœÕú‰!ä’g®¦”\Ïõ¸[ä’k÷MÒÓ;n%Þ¼0Ù_šTT1Š1½'(¿}á<»eH›} ¦z"À§Ùœ€JIw$“ï˜â¡rýfHzƒŠ«¨H·K Åx‹º‚›.Ñ5 ±ôÂÓ0ãG½®íŸHgX£Ì¶Bvq‚L×…b 0#pÑÓ3ýd«ó:¦¬“Ôl‡5è!)É*IC­Z¼RT ò71yOñûˆëË€ŽÇyèAéžl$sDfµ¤èqE§ Å©é`•fw'4KD |ÄFŽà†ëû’ˆÑå¦(¬¼>¤½-Šrï[U²0lm<CM€bD·á©y0ɾ9Šxï_LX}Œg2C®3…]NÑTX•®Š+l°Ù^´9†XÔÈkO/Ù…¨Ó¦†` ŠŠugúÖS’+ÐN‹•Êz`&žž¶ —ýùÝW0“òEmÛ\ůsJ3eƬfœÞ]V.sFb*pÜß–‘#…z l¡djQ ¢Ð9R]ï9Ó2pLÖ—3Wýú¨7“MÆ´A¨í¶¤& l®ñm•¦¼Ö>ÑDNÄT}äÄã‰é4ÈÓ>Óîâ'rЦsÑ´õâDvly®5ž %Øv×É.NÊéì¡HºŸä6IÑô:ú$$$yQeÊ»Ië7O—øŽSÔo3±Èý˜t¿!çÔûþ,/ÌZT#†ƒèëØ*ûDŒ¼^i°/i„zøzX±1_¯¾/xÔöŠ³Í ìõ÷ÅÖû3ìä*1»Ð®Fž·^âwï¿Ñ•>tï¶ϵÉy(ãÐ@4ôÃñ-ü^E¶Â!<W²*"®Äïª $L€ÀÂþüû‚ê­±¸ñBeëÜïÄ¿]‘=3håM“¤ ˆ¿z¿Q{¹::2ç[b¡&,À‘ÙÄÕddÓb¢~VB-’&ám©ÑÌ}s¡43³9x©¼`“’qF ´’IÙ&Ša–〟{[€(–†´ óü ø¿«  ¢°31”8qŒ¾s`“[µ1i¯ãÄ©KÒ“Ù ª~6“Š”é+‡Ó$˜^”Á‚ˆ~&àƒ*£‚½l¹rw-*äËÇ«‹ ÷‹JZ+’|($ ‹Â¹-) Ê‘šº¾ÚZ#-ÃųC0·qÀ¡š‹·¹.¼ü³RñpûÊ*0Æp¸  Ãâ>ú4’g¾{rˆë%š³œ´3Ë22¨-sM;¤?ÉÒ‘¢!¹aûšwr*cºˆ‹‹œª8™I Lˆ£¡Ñž´•ð“ ˆD"ȶ¹´È¢>ª³‰!wºÔ)#C–‡òå ÎC…‡â8{49¤ùE%N4A]DøZµ#ì°#Œ'¡sáÀx*È\e‘BÒ˜¨ˆ§¢z)Ñd0ù¶1‘ð@SZ”ê#œc¸a)ØÀ5(¹¦èC׎˜È‹±b#²lV“°©¹Òv=ÓBFp‡¸Ù;$cêC‘>FY¹ÅB‘¼ à ‰¬€­»YAÛ·µü‡H(²:ã±ú¦ˆj ª‹ )–$£i쳑%y¬T ÅkJÂ`¼ "ÈÜ·¸ÆBh´¤Ck´«™š:sš…-*½ “Q¢ú*%:Çž‘=3”:+<š23„"ÚI¡;¥IP´ÃDKC½Æ4«™x%zÜ6˜ˆ4âÈ ñ_©ó:H¹ŒÂø¡$aŽóÀË𮼓ŸÈ~»¹É8Úµ©ÑðO ðê¶=#9ˆ¯#I=»AHijªš¬Œš¸êïEiս쮩ÁÌÌ8·d#³l&‚£­+‡¨“¢ M‹ZF‹ÁFL-ŠØ*Bî(s´„’úÆÌ`›cÄÂÔD4è~±ø}¯Ó#8’†ÁŠ ª3<‡ ´Ìáպà ¦uL"±•ÄNââa± ô? û4XŒªÈx÷›ìi)¢-Yâ2/1+nÊü˵*k8s’˜#IcÁJ ‡Æj-<™ë$““N‹ð?õ "kA÷ ôM¤Œè ÄÔtå‰- ÆÓ)M¢?4þ¼‹”#‹ 9lθâz¥…Às0»¸lÑÚ·¼ã,ŒÃI÷J ㋊ GóÁ=QÅiðA,õ¸4æL2/ËTÚF£Ñ“R @Ò¤Ž-«G¦‹a(Ú`ša¬ŠšŽ­ªÓš|î«#µ+>¥´«·»ªº¬+¸ÌŽ•Ú’J©³‚0£l¿+Ë—Ra¢£^̬ÓÐkR•ì¯ÊóL³¸&D dî€mJ¢3¦‹ž®ÄJȘ å*4Ê>Å´`6T}É_·¨†¤«$ºT^”òˆ°™=L£¦¯dÓ'i 4E!z/!"Ú£!üC€Ÿ¶¼Sú; ƒÆ4y0)í¶B:ÁoÁä8ÀhÊ07‚b*;àPXœ¸©Z¢; Jª¡ @HŠŸ›$¢ñÒp¡Ü/#jµ–l ëIVCaŒ2©L;Ú("ŒH›eÍRS œG³ÿ !좒zD-ÕŸÍjj&›™šÊ=Ê¿0³IQ”¿Œä> Ž@rN!¿ÓÄ8»„)̺`ÀÓ*<%üd¦\=™1'@¬g¤‚²„ÒÒ¹lGK4OLfª0õ½²È´ù‘ÉÃ_¿›+Ä=ÏȤÔáO!Ãä:ÕEUÑô‘SÍ‹{´ OÀÂ)‚0J{9Û{#ÊÂ=ó§¯Z³ÂãX#‚¤Háð$E[:âHTl7"£¹c¢Ùè‡xêÑl ¶»ðK ÁZýWL±Õ©;OtŒ¤"ËAÒ0ƒ4“95*D’çˆ$]§¯ |ÜaôH]œŸ ³óªÛb«•Å@;é¤ê8™d?û‰ÅkÎè¾;º*SÝ““3ðIr‚E<¥ š/ ÙE:õTÇÊË¡Sƒ™í`K™3(Te›Š@\ì_×t²."¥¬³š<>ӹТÛÀÁlꉀ¿E…Ï)‹8WC\ø8‚ñG!3-U¢9L³j¡Wð~Â#óŠ®ÜÉðŸ”ÀZhÚ…ë4(}YÝ+ÔKYH‹õ‹+c œd‘гñKDu ¹™,'à$´ ÜÖ»\Å%?É9cAÏè~‹ñ§¸ˆÀ*2w+[ÿ íP lUElÇáÌJ­9œZÙPmbk–ôžÞ³˜ÙXÊÏ:a( ‹¾0¢É˜ûZt<á…2¯“Ò»_>ÔÖX0‡àb6Þëî" ï K¨Ý3÷ˉ¬¬ýMœ¡‘º=35ÅZA=Л"M4J (º¦$Áu§sÅød]Íê `³ á"aŽ*g’ƒ};ìÐBÁH:cé¼§#ñfáaŠ­ W*ÈAËbˆÁü"‚×Ó5¿‹®É õưã­ùؘ²Ú©$ƈ›g“[mY0}¦ywµ<§0d˜( ž¾½eÜ ®’éìΤ¸T{i¥,„ª¼ãœMÜf°ìÄ0¢h‰Iýˆ&|wŠG*hE<~. ÀuØF4 ­l@Mâ¼Ìß3éw™a'*FßkD¿”}×ê†dÄA‘¾ >žF5ý>ÛpÛYkÜsª—äE3By‰…RAê?ŒógöÍfFò–þ/ÉýmOð‰Ò läž*!ŽJ§Ý£ ÆlxGýµ8sðgR‹4 š¥“#RF4Ö¹ï(Ó4Èt;ÅýiQ´dY›”á¢BÝý¶ˆË“Øëež*éGeìˆÊ™ž]Ýç8ç|f«[‡lËLæuU˜Z5­Ԫ܃0Ø #² àÁØà3i_Éû&œ«Û“Þš:Ùï !§ÂkÀèõ•ëúP`êì²Â\}¥Ü˜©Æ‰£s_«\ì6å65ŒfhJœWI.áj0>š‰°¿H'µ%! ­ñå¨eÝ7JumNŸè©íh‘5 ÂFäS» Ù‹l1w‹äÇ4F”.×åÓÒŽ²¡Dvdv™Tûe´p´ñÇŸ œBI¼Ü¬zF3¬ é»LÑ_êÉX”N¢Ä8ÞJ$ä¹Z†$BM™ctõ`’ÛCi‚KEérµ¶àõ’ëÄÛ~LÝ´ŒBʰþ…AŠ÷ÑJí63si´âŒÙ0 \å”Sã À€@”Ñi–Né§®ž0GÈ„m,‰X‚NÍ‘½Ö,аß\„æw!›š Ū‚Í /±bㆼ5F¸[ÎéÌoïû#c¦Ê¢x†Ò³c‚ÓWKRӤ់TÓ?ml¬@}ã:MIYï5Ëcß&çÍ£€2g´‰âõKLºÙâÍ6èР; Æf687ú<©ÓnPa¿D¼®Ad0¶Ós,Øã'°öï~ðm ›ÜµØËÞrc{‰n€ûà¡:[jêŽê”u²4HЍ(Uý¦_Ф²mÄ.†ë» ¬‘íóbæ†â„ÃÙÆó‡ëø¯P!;}ô¼±î»2;‹µ×±ïZ¸‡1•ÚVJ„:å%Úø­ÂÞ#É;&ÓÙðÝXçn°¿&È‹!ÑÖN+ )de[4Wz^óà¸ÖƽH0¡‹à÷»»ø¾7JŸÃè ©â“µ5×#â!ž,´sIP-¹ Ê½ù÷v®Ô³äõù,fXØ}c¾èoS›¢¬€¬éðSq[pTGÌÇ'/7#Ð ìbLö:³#¥òòk#ìc¸ÖRa±?žW@³Lsè÷¾6쬓Py0…`Ö7fħHÚBLe ˜àÆr±Ø¤k Q~ØG.Á”ІX¹O«4eª7>9z+“~iÕTnÿÁ”²JE“ð5LèÛñO7¡h1^ÕKù°²QkSíÒu©ÓÎM‚sôm¥¿ö:&î.†}ŽEÁ3DYqqHäŸ4sñÖ•‡ý¯u@Ýæ~Ÿß­ÙH¼¯Æ¿OÌœÀM¦&hÁÛ4„!#«åÍÁŸgF˜â¨)ÔT茓ö_oZŠ£üÆŠN‹åÉ´Ô€ˆ èQ£A¤ÛR×ÕÈtÙ¨Ô"!ª±ÿ®‡•Ýìhj®¤pˆ‚ ÏØD$ ‚PøL$ˆÁ¡`4eÿ|ÇbððîE‚¤Ñ'ä¦Dû_Òù€3—¿¢±9$‚ ’Me±)%7ƒPh”'ü^/G”¿&°Ù$ÌG¨Ìá2H¼’± ‰F@ÔÙ­z.ø²EêQy¬&w¥Å¡r×ÕÆÚ‹ÊëÔØ¼¶šÎ¡*l’Š޾nò›<.y•È!³ZÔn• žÌ&3‹êû©D®y™ç‡Þ2™,"%‰¥JÚúü¼†E“Ík:€-ÿ`—Ö÷0úô®L {qA|-TÊ‹ÂtÀ”¶A…‰Kfµ)¾‡nÑõPhm6¦è`Ý‹S÷½„u`pHMJÈøÛÒkiÂå òç*Ïj –¡)Zü L(¾kÚ¤¯0¯Šf´&©zÒK4"Å!è’È#i´±éz.¨#p›,*Pó"Ü5Œ©üÏ2i"šµÅIšš¯=ìaEîØ&mÓlÓŸò+ºî*O3½&% L[!nºfù¤jé4¬BgÈ@0 ›Øõ(­Âü~Åi{ ΠҢ¥2AüÚN‘Ôº©®|ÖKI‹×9Å VšBŠ$™ÎÉ|♞ô{‚$ RÚRŠr^„«Ôyï0€ôàP¾hj$34ó•¾kÊ=¥4õ=N0HÊ$ÆÃo]&‚)±Ú.¦ÄÊÓê§ Ž³zÆ$T+–ȦPÈ…Hѵ'2Ùøæ!”•Œ}ÇÉšúÅ©F‚5ˆ”ç%0-©eÎU*F ¥”ÿNMôÓ>Í7`£¦ªB@¯JN)íKÝMäê…º(A[€›$®’2暥n8Å3M‡Wˆ]=Z¶oº(„6‘Ýà´YdÚaÔ ÷>°”'‘ÈxTø!L-’Òî>ÚΑ@ ¥j•m|¼é›3Š*èÝ4Œ¹ëJRhà™ŒÐ9‚WŒ¡¶îA—CZ4ƒ¦dMLß\”:'H€‘‚V‹éKüò­lö’6†ã8±ý,Ì0¡(n&ã½1äObŸê•ÐEök­©%ñ+äó¹@äêT£ P)o!²à¶lÁ0Æîçhô¶¸̽À,¿ÂõG 7KÛcoHg|$“m˜Ñ°ˆëǰŸú^Lü!ö"m±áÒtÏáÀô«ÝmrW©O™ABm‰ .qmöîZ`è¶lžÓ¿áIÄÝí|5ñï!q²IOJÈzìŒÄÂ$!¦eY€f<¶‰y Gk½©›B@Øü>¬¤–›FæøYýOä$̹ÂRaÔÂ1 Åxš«æl?H¹™8l0Œ·…¾pÑ>iö6‚$â`£×ƒ¬½¯ÂR°›[±})-…2˜t?C\)Q BêÏK›)*D‘¶²2CX¡$3$ùV¿Än²\;¹<îÂ4*BÑbêeŽiæ¹bˆÌùN Àå5àå§Q"@§Q{BÑùù¼ø°IY5oQ@‘9# ÜMñ™°ô­H¢ð`j,€Êº7(‘ë`}îÉþ¨É1%ÛóÏ7Ì•ú‰Nç‰lF3#nX"`éY¬\ËU JBÅ )-%mÍF¥6ÐøÎzý#,O·»Ãéç]%À#š@†ÐÎ7"ƒuXkÄ™ˆŠ¥úÞ”ãì?ãõ©HŒçš09óÁCX‹c).kªjB£#8§Iâ MYãÀR"7mM•’'‚EÙàûs)F¶AŸ0˜¤A¸'*ü«ž7ϵ”›©ĉ5SÔŸÊÈa —òlß¶6â“a‘JínB62ô]ruŽx£±™9—œ> Ô¾ Î’öú_%¬n‹E¨'d$’l ¸Ä§u]”T†˜UYOØ}1F„¦)Â2š§ ’eg4t‰ÍHD+oŸï)Ñ“2½#Ïœcš£ü½$ èKàŠF)޳ęXÚ‚f)˜‰Ö>å¡G0µçBFA0\ëÂ/j)¯¨—2Ú’B0åŽrWN&šF‚ˆÙö–ôµCUfì*^$Ä[B¿¥ÌôØÅtRõQ‚þOS¸X׃EмdE1.‡µÆ¢" šÎLȯ©Dë[¢Hv ¼ùÓ^k0)­ê[¢×¦óJ” OÜ'+ êÚɸÃþE# "QÄIkfнÐj+UžS)À–:™:öB$v» OÍâ6ðp9G™2&ŒÓu=å ?½vzÁ"F ³ „ 3Ù#T³¹‡)ZQŃ aÔž?lOvœ})ëøÓé…mUÎÝâ9„òSQ3Sʸ~[DÊžù‘®k!p½dfK±¡웾2[”\M‰®o £¢<ˆ¹Rɾ¹ªxlâî»*e39#H¤˜#¦/«HõaT”Lì(SûFìB$Ó¦Ï3*NB¬633ÎÂh‘ö²) 4¡HŽÄóq§x(ú|ÊE~f[Ò5¶ôÒ•N)Vð©ãªÄå#)ÉÒ¯ÍöƒuÔ=ÕÒ‘üCOœ‡ºMÆíI—Öóc*ò}­c %R3¾VYSÖËœ?‰Y$ÆÖ3%åyÞ&Qº’ÏÆˆÕ Y/®r>8kùKOXQ{q:=¸•,}¢ r(©SïiäS–Ë$1séÀÝ0M­]õ¾êNUº®%™¸dÔu‹Õ•îÝŽœ(ü˜àµØ§Eíuk)¾¾äÔlòH>ò<ÒZ(ÁuD9±”±†|JºŽVQëH)­Î:gšo±S–ÖÅÏMf}&I¼v)áèmí§mv3¿Éä`»4bªÙÓô0Õ@ O‘‹‚¼ZË®Éë²s¦¤UyH“Æil"ü.ÝÄ2hÿb‘ É«üÙfg— 7Zßòþ1SŽg7Õ´œTkܸkã—X2-âZ§ «o±oäÇ¢üD $Õû€)|±üû†y2EÅÍÇ{KQ#:siÏ_:Ÿè|tGh4Œª¾—†_l+ÙKbÌð>Ö>Ì)ÿM}ü€c ÃVA{Ôˆ(²Ó‡ÈÓî¶ŽöÖ"Úç~ßqSÓäé¹³‘/T)”Ûá•ÆŸK‘/Îé] ¹ãlyÅ›5¿¬&_}eõ«[!Ã.±®v".oFŠEªÂ#¥B‹„“(ŒÆdiÚ—„è$Z5àNC2ƒŽzð *þàÙjJE-(L­l6.¸ˆÉx„ú6Žà5PÎŽþ2h(nkýÊÈpjxð%´Nâ÷àS‹8%%9ä¤^¢fwŠŠ°i  O¨á q°jÍ©¾˜*@ÅobÉkxƒÊâd $ìEð§Ša¨x\ɰh Å= ˆiöJÊÖËr§ÆFÇV}%ðªi2¼Å©yc.›ì_ ±÷ .kX¾0ú.gâ ?Aô°!þ¾-ü>iÌIÍëøyK‚?jc.ÄmÇ£.•* ÈìS†(%£ ¦n‚TÑBúã'M*l`×NPë (Õz~,§H¬¤,+ Äz®Û4³x¸áø½ N… އªM)ü«.Í\H”e¹ *ˆ°ïÇeâM¤/t.\+±žCâ‰v8ëâãE˜è"æ© ‡Ë@ˆê9 Êþ+ÑfPTÌ  æ¯z2-= *þÅç²"Nj`N8Ý"µFúwE²íGZuiž‚¨œœò27nbõ/#Îrë¡ ÌЀíÔ‘ö$™M¶Ñ‡bå%2j/€Üd™‚Æ,‹§Ân "Þ¡üÉæ¦ë’n“*üLpúÕkÂênÈðˆäûn$Œ:ÅŒ¢¤è–¶€g`ø1ÐX' Gâ´NŒú)ÖÊxåp“dªß¢2¶¬:ç¯'„šŠxBÐ"çÎ(ï,) ‚î J*ÞfÁP0LhŒs,¯ãbØ.ÕQД“ÃÑAŽ #v™¯Öµ‰h¤á¢µÊr’®&#ž(ç¦.ðll…FÍÊ{o¨o:ÊéפN ´äcb$‘ØÇRpêgÊKÀ )¨¯ÇZæçšÞîÅèF”’+)‡•ð¶?’HŸ‰Þ€.ö’rkdB®î%î¸ÃêýĘ%p $Mlõõ7G ‹Ýk‘0íh´mèFèˆÈh¬ÄÈ/à¢OÒxE ÷kšaÇêL0 œ «+un¿Ñç èy;¦~oå0‚åÉm<ÄàD,”Be‘)¨rmÔî‘>°+ x’ 9J´æ³+,˶²­@c¯:]K!;áøxŒ>iäP}°°}¯|‘ïúu"âRå.¶vl¨ìÔwb;*Lû áð8mLÆ œ…æbˆ±­y å(M^{Dà2S òjèQ|äC #"Vo‚=MR/.¸tgCfE¼sM,ú!0è¡íŠ&1ÕCì—$ Z¯ï!ÊáO&¾Î²tj Æ(“§ˆx1ª®cå.1¬ìÊ&ì?'•?W!±: XådBÙ…uªLL"¤•~7GÛ •E§”‡Zû“Ï‹tÜÄ 2- D&á‰5„ˆ¢'„ÅóhJ&3´!oV4®ìUxãç ‚âò£¿gšëš¹ NÎáH¹IÂù)±&´ün"¦'"·§ÌÎM#b‡6TµIØG^LM (ˆ†SÑ`Év4#v,jfKO@ m¯ÔãµW5V„¡¦Ôe¬tÅ"”v²îe³ÖôŽNFI7ÆãNÆ:g…,ó[MÜXh²óÀ+ÆéTH nèÊ€ .‚N”`&ná ¯}j†bÚg/5“üF¶>dí«E±+Pµ/ "Žü0–¤û9Œ“˜(îƒ]¥<` ›9TÚ“sU#Ò “³ ^AøÚìâ!öíÉTgŸ]!ô˜‚RO÷ÒpÖL1N‹bˆso_ƒ.ùtöí†YÐ}V“3.ÑÿŒ…2 ¯ñù yõÈo­ø”±,æ»fúp BTu{jü"òÁ1b¾(E8W˵újj,Ã^ð‹ (0.#”¯Å.ôk(Ùç Å-8"ÑîN7“yÐ}p¢© YV–Ë‹¤RíXÂ='V¯.ÝhéÂ2dm!ý·[7BHoW¶€)nØ©ƒˆÿ5cxjàO¨åôïn ]C2“®JÆ•ïáêÔ¶áu¨­ˆíÔ!&õâsØn;‰nÌE=«;‚ðyÔéNW±N¶&¢n%` þ HíC-n¦kX}µ@Õ™S :7Ä‘IG}AîÀq.à´­ÕfÂW}—^LdÆÊíüÇ­3eqüutÄaªçqŠUjøö;Õ»vxy2ñpkîx‘Ï”nºFœWs&(ÛªÉ?PÁy4»lÉLg¶hÈSÞñ˜fL,êIdâJ}N>­ü¥¬2{8=fi2ùàÏPü9ïQrBSeÇ‚µ )R‡}¨¹BR‘æq.ó‰Y¬“–­Cgt.êÀ÷K ¶m¢£/‚£q 5l„Åï|Ñ¥ŸqŽšÒoU¾Íhpd˜bŠúšXÕw^Áè†í¤H¨ðDsæ)Óý$kØÉ1BE :œÈ‰y–ÍÄmB¼;#Q3£**M,pŸ¸&M"H8fa¸H€:zyæ®´,Ôµ×Lº7¸¨DRO…Ãæêºwáò]T;LEÕ~ºfV%è'Z‘ë*¬l³‡Œm""ã1ó¼ÍÊÝE˜2s²]&«Yº³¬ÌÑ ò¥‚Š …º V˜v÷uûuë½Fúè7·“ÍPŸN…}›Ðáñ­㸡ôh Nàµòv†˜²0êAŠcEY™ËfÅ¥OW· H”èÃn$u¸— Khm“U¢2>§ˆ^çÅFnƒ9Ïk7V.+Q+ *ë”u:¤w·ÎH µ*Qjê|®ªÿ¸‰j} ˆ¿ÈlvÁÿ‘aù0ñŒÿdª<­¦¾”‚k•ë0é3»ü@“³$½œeÕ/¬aŽë\psìf¾îVåWƒu† ®ÈîÐàw[{MÕŠyð¹V‹&ßÒç[Ó”O¼Ý‡ªb†Ñ`†dí˽o›ô[´Àé ‚íR|ÝVz7ê+2€±5hG{VOÚYÌÀµváy•à2ãYŸ‘ w-£ƒ½St¶@ Ç­Fp÷°BÇXƒ†‹ÅZ1žòî¯ÆÕBVa D,±®Ú&®ˆKzø ßÖ7Y›˜›­OÂ_BXÿƒ²—JßÕ•KÃÃŽ…‚äXóTè>¼ÿÍ#ë©A†Í“0BFÝK'[œÑÜÎmpÀg] Å©ó!ã7,:ßÄ,ÉÆèÒ8;ˆMTÀ$úû€w/°j|¾D®l´«ýÕ견ZÞY•RÇÒ¦rÇ ¯i&ãÝ´äe9“Zr€’—Êñ$ÒK+…ýBYÁ"¹ì…GWßrÛûpK©çvâsù3  ˜âx ß%Ç3%ñ“ŒÙÞ7A"nÌDLj™Ãtf°(GÖÌ…³~+Ä^!H\øâQyãâ!~²¯øE×Z;(uØÀ ­!©cÇZÎL:’Gž¹h´ô*ÇŒé `»(¶ËØ B½‘5‰!zÏD‚ÔÿÊ鼎¤¿Æ“]ôyBZƒœ›Ã*3…Ãåq‰hšÎð1¦‚Þ¼"ã§h=2QS\;‰¬Æ%ÿ âR+-˜öù µ~ûéT#:«Ò2*2bšb†°U P.sy}ñ`úÚ6kÿ3Lo¸î©‚€|Áý¦×o€ù=ŸÖáBÙEÐZç:¨†$õ¯AþÃõ­ZY!¬ýɧúÏ¥r‹R£u¥ÙˆÑ+à pfû¸BÿÀÀ0WÄ BÀÐØ;à†ŸqX´ ÿ#P pFŸò8Ô-ý$ˆ€¤ÏøHû1‘H#°Y‹ö_”J%ó¸d6n¡=è’ˆôÎh¥J癢I’J%u)$n9B¾«•Z<~8ü±G¥rI}‰ùZJäjE( 7•Å¥³yN§ —Íæà»óç+´R$’Û\F=jŽI+R·®>áy\%ŠðU­I-Ù]Ãù«?ãш~2…lš%úd.µp–䮨¸Ö(A¡N§ÖHŒ[q+‰ÍãÖÐ ä¿ö³ID‚µZÎí¤½Mð %‡–u$žôߨIö*5~IheõÇÔ‚s_›äk ­Šnýe¢2 P©èZ@ù©JŠ Ð¢lj"é¤(,£¹èãŽûŸŒÊW 4m\°&ûÈ”£L»ÖÀ# jP‰¼ |:ðùÿ Sì…±-Ü«ÆZÐõ «Cô8 í"H T×§nZ¾ÌDÒV—À‰Œ ÿ ¬47,CÑÃI,PJÏ©Hóܤ- zèŽ.’ÄÊEˆZHÙ,+¨ÄK§ãòý'³{ëÐÂ"”.rP­>0êI4 Ò,‰¼à ÎpÒ¥/i”¶­=Ì*8²¾±b^³!-J´/ä3+5i¼!&Cre7,»’Ë%X7Œœ å,Y¯O;/à Ä2J`m-‘UNg“ý®Àèq¹Ð¼‰y C™&­ª«l²ºäLFx©1Ô¤üBH™§–:kÐQô>vä%s Ô“ ERs¥fßêxÕSìŒÀÈD@ ?© y(󠌽Œ͵ØE &¨±!¬Îi[IÙ¦sI&}t„Uª¾€# n¹@àlšÝ…wU*73ü×;Öñ¯"¶EˆÍv9­­ˆ•ü&«sîRÎ~!ª® VÁëü°XžªÃC|í(•m¯€Ú³©o[wµá̱ºL÷?:FPŽ<Õ©÷¿#Dö:ûz¥ÇgådÕ)[-s;J¢sñŽlóWe¨9x7Bó``YŠí6˜û¶š×¬#—ž>Ôr1p îÃ`µ_‘&fnÒbæk¢}v4$î““×B”ÿÊì|o„…½íw ¬tÁ ö`'€©ó¯ðÝš§›=Ó‰eö~xL×XAáð t>µ¯.£:œØx/œé(Y\¿KäÈíâê5iºÃYs±…Ùê†ÔgÔ¹‘\‚íxý¡Ûaš¿ñûОdŸLDÛŽÊÃí¡ÑH ÖøÈNëS4MñùwÇ474k[ÙྸW EÖæÐøQ*9!Ž‹íDÅ;5-Ùàüø¯?Q;AaÖZÐ%#ó›8º†Šp$Øú‹Å'cŒàz@rÈ&Ð))Í:Òü3£È¸h¯½êD,:&¾Pœ.Þ=y™¼ U›· ¥q‹z05°A5/¸¡¶ }žI&,H½«žãºË©óe Øž)>¹H¤pŸ&*Ü%Ô"«s‰˜°Ôˆ‹™§¸À‹2Ëi.™7»»±Cb½Y‹½Ø}¦zÖ(‘ª¦ŠZ8yÊ8É\±’ ËØ/SOÃùËñÃá%ŸHnDŽhÜ,ÒÞ¸’[£ ¡3[ê «ñÀ)Úàj,š`Üz° ¡<"û¯p˜‰z'®2ž¼t) ‡<ù“™s±?2鉌C¡l#©X«¸Ê18*ô0<‡ò†BX±¡ž·¡ª"â9¢ }¨•´+Ú™Iœ€™ª1z¨»,Žk“D#7¡CBÛx¼‘ùª³J’õ7ò%,ð5àöLc73Ͳ›âˆ©$±éÍ ‹3«s«‹@GáÅ!s¨µ‰;Æ™Ž»´-ëî¾É†½jx*[,•9ÓTI$1„žD§‘;³ ‚ªZ’¥KÛ*™«™žY&c:»y‚@É6²‡I1_ q„£AÆ¢ |ŠáøÇq=ÂÖ;*Ë¥ýì-DXè®»?yù\¢‰yÔ3A€3®'À¯h÷Gà8æ£Ô-óz›a,Þó'´;½¸+¤k,¾À~ËÛ+‹àìÂ"@Éc£lx©º§ŽldÊ|!:ébÅL:±`L(-RŠÈ<¬1<3¤SD@ºÈÀ/¹™[.È£ÀYÚAƒ~ŠûCÈ…ˆ²âB$×¶zz4ݬèBz~1ä³Íð ;K±Hí.kP’L밨юY‘#€—¾ ¤1‰ÌŸ”L؉ÂIÆ1‹•ôмÔ\¦ £$“PÜËPˆ{8/KˆC/¯I“ÐŒ o8e?„¦1¹]1¿ŠÃ(dtº‘,λü­é!R!»éâ©›ëø—b‡#x±3ÅÔ'±¡A²”"MÅêä€A$”æQÙ³œÓûÐì¡H»õâJ¤HÑ»¤¾r«>ô]O» @ù‹ÏãMC¢‚B£“¾Ì«ŠÂËy4‘bM‚ú .›Å+0ëʳPä]Nsרɞ¹‘9=“P¾q'´J¹ ±ÂãPpå¹›8™ ¸ƒ¬\>ª’!#ÌðjÕ2±>s(¼ÉñS›Óºž’cFNP«¡„ãÃÔ:qïÔ›&*3š£5´÷B,1Ç¢y¨ÍäQAL {±9™‘%M¨Ì’Ò„í–üU¹k¤ì Ž:+ˆÔÊ6±>º¹¾<€™kH†œS*šaGGªÖÙ☼èSòi ñXÃÔHˆÓâ8#–ÑBéɪ6I ºb³øÆZ9¹ ¯—¼T:4gW¸Ÿƒûqžóœ›{Ô¢§Žƒ‡Ð‹0Û‹ÈÊ@ÉáñÓ)ë" ïCM;×û½3~¶"9¿£‹ê*¶¤ó‡á»2)ŠãÆZ!sO£9êN©ÉY«“7ZÌKœO>IÏ ˜F`Ã(í;AŽl¸Å£¦$š¥¬àÀ C¼Æ;‚º¼¨%äêVƒj±;™¿½âÓ¶[Öã<´´SŸ.óƒ!aÔE„± -º½zÁ0‹‘ñ½E’ÙÜt°‡“Ö©À),2ÔMSÊJZµI^N~ÆK˜šû‘b‰ Mè¥Wc‹³sÕÉ")ésRT=°EÕ=|êÒ[ËÉ’9×t\É‹µE8Zï;ªÞR@¹})FÜSÂÕ«p×KÞ˫՛LTw/¼“¢S ;“M¢·CÓï«I_ÊŠõ8úÃ$íÁÐñù üw¹Å˜Õ} »^ÃÓ Õå=ò]1t©+k=ëUç7å¸!œ±™ï2â9˳‹ÄÜ+mPUˆ«1nD½c#QHNkÕ£­¸Ó¯€ØCÓNÛmUý3½`Gd¦Ñ}n𫝩 [~ZÜÇŽ­Ã²¸P¡­Ò^Sq™›â&è}ÍIt*¸,zIÊÔçµ^³"DÖ⬭‘’ÉDÛ!—QÉD”4U,Ž.ÚÃ@À3L¯G)ílf·E)QQÚ)€ 2M_ºbÍ{ú¥MޤÔ./ A;„–äèTUB%LÚ‘„’„ cÓ³l¸$ÎÞ3Áîª[ äÚXY,¿ªýÖõÑ`º8ÄP~U0jÈûÈÎË‹Þt$¨ºTÜn5kõê3ÔaSh=í­åuxQº‡´ÕüÑlOÔɘãÑâDà¹Ã,½ÜÅ)¹ùK‰¬H\7¿ù,I)-ÁáeÅñv,8N}ù‰Ô”3²Ò!¦’Ê(™ãqÍzb”Ldn¬¥îqÖsPË}>Â4Æ=‚ÖZ &Uiã°çÝ=¯Ý‘žR[Jâ}ó «ì¾%îÝ]Îò{*{Ôa/™âã ”U<ÑOËM¼adȨ‰çì°ˆ›­™yI„*²\4ðQ%ÄŠ=«r«Z&ñ Žº‡H‹]Sžš«ºLEc¦¸”2É@üYìÕ¢§£>$[’ßJâ·@Yã8!ê×ü+ß­½1,°Njæ> ²ê1=P¤K²ÛF­ÆKÛ cqDÊÐŒM–J]6zˆk‘0F9 ¯¡1tD°„Ýq$ª£øK‚`v1€\¼€\;\™Ÿ‹“6©–Ñ™ZeƱfž7Î[&¶Yî­êc‰¢bàQ³Ó[]“òL ®ãæP~Nº`JßÇuPiU<>Ū­ Ó.@}´ªU¾Ìf…¼Š«!š§ÝüŠîFuÄë-@‰ «S«Zº=Ò×þVžùšÍ-±žß®%Kd¸Ýnž¯«åœ‰$ùel ?ƒ«ÐHêY 1æ¡_ÉŠ“J“Ô«õÏf2TâÊ¥Öfe™r`[îhsôr*ÌnÝÓ¬3=Ô°dBò6ƒ ŸyÀ”ÐM“F›™ Ð0À;uÄR¼sÝUkÑ@H¢LÞÃ/UÈ=æ/ŠÚƒ1F*³GÖ kæÄ5%Ý…˜ AÓ0PJ&yËa³=jdîËY†ŒÇ}âÖ…_l $š¡<Œ™œ¶,‚¾\oM¶–¾E:F Ô«ÈÅ:Y…HÇAÀ¯ßŒ_§öR–”R? ç6µÆs¢6¶–t=À$ê&­íUPlrØ|ŽÜDŠkæ"ªg Ÿ3¿MÑ5†¨nõUÀÂê×yXk- åÔ6ôUôÅ ßpÎÜqƒR£„Sèë×ÖlÔ=òµžiŒæÃÕ•=‘!:¿-•µ‘ÓëãjŽMêU,ÏÅ‹RC‚Ì!]¦hÀLÞ?/•7öx|½éƒ=£ÒXáܽ‚òMgÝFdša £5u”¥‡ö,dKÕ¬ƒ˜ÛÅC¼›|tt¦x–½¤ „q9‡ÚÈSˆÐ»|×*XëÑÞ7+8 aDÞ²nPÀx]±ªDíƒé¨dïW‘ON¤l>\±y(|áô¥0Fš {c"·mt;]ÛwÎ2Ík>Xë×èÞÒ^€lKis_ËJά«1™Ä¨}SÈà&…™éÓ[²CÇŒáh†Èϰ`÷¦ ·ìvËGr]9²ñ½Gp‡Ê‹ôÿFy`uËßÍ~˜1>aLpˆðý¦ÇÊaªl°-RÉÚF¡QÖ[ßÊÝ=T?¢ÑÕ0¢S³ÍR¤X—˜èäUT´£¬6Ø`BÞžöÁ,hv”(4ùWÛJaÞsN BlìïÜz‚·BMcÛU°þ1Ú©jÖ½{”:à°EWÒ¸ÀF ™Ï Žv¸}ȼÑi¯ÕR’Ȭ™¶wCÛcƒ\¦½[¤%öNSÉù¦<Ò¿f0ËÀ†I|ONàš€CX½ìË^P€ P0Â_0°$6ÄbPH, ýŒ?#PpZ/Àáðøœ %$ˆÇ$P™(1ŽJ riL"‡Ìæø¶%~ÐaðÐ$iùJÀ3ØŒPœBhÐ÷ÅT WQ¨/ÙŒ®­Pkôi2JŸÄA6¸[æ_ŒL¦`k¥Uñ ”O's«à9 –Ù£÷Ö¿_}âc|f%÷rã­`˜”cJ\`ù¨ì ¡ÇG0¯ª&r9¯èôñz%¥ÿ­Àër jG {îkð:4J9tG$ðœ_‡#²ç¸“¨ÆŽ1ÀáDw±Lº/J£S¶pZ%þ „ÂÖå´M(]^lØ„^S„ù(6jÿl£‰m*ó›íö¶ò€ s2ã"({ª‡°hJ@ñ)¯ëØ:ªCd £c^Ûà ä ?ê⼫ºiú¾Ž.ÊÚ‰ %¯D$·È;x¦À º®²°"ÎEQb"Œ-ëôc¨F¯š²(#±ÊÜ1 5jKÚ+lšÂ~º©jðåºÒ‚ƒ€JËl–@²Z–ó1΂­£B> §´Üà=H¾ØB‘Šù«ëkÞ1€ÎÀ1Üm ¨OŠ $ c2®B0×Ogâ0Ö­*B¢‘µÉ‚¢(Ñí8~± Lš‡¶§â¶Ž,ˆ*¿.Jqì÷SÀ%oY=3ÿSÓGò$àVˆÓš€MÑV P´FÍÙ=ÀRêS×0€3KæNL-QJ#¢Jà Üžè{€ø^È*Z­µPúÁ>1Ž:2)T9ü¯¸ì<D(ÚÂΫcÚPhÉ´j"ÛjŸ•íê‰^trF×'Ýñ6XJ½_hDJº=!2\®­®þ­YíðÝ X½@«õ]>ˆ¿àK²|zÒÜ,‹>щ žìÛ«°‚±×å· ÜIŒ-¢28ŸæHÛ_ ó뢽/¬³‰^ˆ®Ô…Øn¢ £>°í™¡L`X¨ÎðûpеP±6b‰™¡yB¯¹o•pýÑê;Í@·ë¢Ûƒ"èã/NÉÔþ¡¡µºí9¶ïFÂÅ/D\lgëÀ}8¬!«æwè ›DÂõùªÐ1Ꜥ8òW3³1Ùf­A#Rä^~(œÛkî@ Ѧvøzü•¹—Ü?Aý$ì›Û¥¾ò³Jz…ÉwS¼ ·Ö"^ÛɮFî†¥áø¼ Ú}|)e“´úCËiN(ǤöêSÖq£m‹5À”¥qÝ’ãH Urt J!_F` )v¥ÒªÑaP1«bΗAFD0]À!‡• ɹ WHÅ@³’èg!ŠÏ„Èú0ç ŒUzæ'HD…r„l%™Å©W†bÑH9c?‡lmÙJ(Œ4 ²W¾bTodhÎ@GœiO°EÒEr‚Hév# (΢¾]šªMY‡ªgBAÈ”sÄ,à0§vWÓpölÍH}¯´¾Å#û,+pP¶öRCÞ‹vK2U(B“` 4_  ‰'Øžˆ‘v€Å9Ã$|Æ ¼I/%å2øÓ9£—p¼„¦hXEÜΖiþÁÈÒŽ›¦vq1¾r¶ÄHFg )ë¯Ä˜éRÉœ‡ÈØþ©‘þz$bØNñ- b çLÉR/&'ºú‹QPóLé3-ÏB—V3aKÍ'¤Š!”ì<Ë2yÉbœ{¯IôlÑÒ8¾ ›€Hd†Ë©Tä€)ŽhÏf¦)"õWD‡*¤ û)‘3ÔZÑW…\»Og¦ÛÔTðcSQÁUQÔ³™|Pm8“3Žû'àUò}3ÞŸÔ¤ƒ¥íÓ“ÐhÎívð|ˆ¼^­H»ûm e(ØÞ>ÞõWcJ)ÈB.Ê[}>HR–m—ÇQê¨K™îMv–‚¥UT€2¶¹4‹1ØŽ•Ý­€5ùjëp˜ñ˜×5F4øƒ>ÖˆÄ` ´Ë¡f(Ö.:¹5‹ m™HRI€aœ+Z/AX6WÔRŠCµþÎõÇ^èÙŒ‚.›ƒru]Ì^—ËaÚ’ØÝQ%Ä9#PËK'Þï%j`pêAiÐ^Ms»^¨™“(+;N;ܨÕ&YºçòbÌiŠž…¦.Õ¥&ÕÈÕ*"éõñGß0ãB‡—÷}ËShì “½Ñ™cáF‚°à±Ò{ ,Ÿ{”Ñ“\±ó#’rY8÷þw)%’Æþ%ŠÄ€¶ÃgdÆ»†XnÊÅ &èmèY[»©õy\9A¡ýt]ˆDgS¨3m…%Ì*åY2ž0[,­ƒˆ+·[Ur&!©·“Û‚°„i!º½“ül?ò-h¬Åù>úµ$ ›^5™4¤l7’e¹pµ[Å_çs$198Yº·aåc†×êI¤÷šçH *Ü×ìMLe°R@ dro‚„“|WóaZ˜­–ÖÍ–³¬@l+—>RMQ²³:[Â\R÷§^)y ÖÃZÒßœÜf9åÑË7Ñús¢]7ÉÜÆ/‹PpH=hÌOE\Œe¾r4oy Â$ø}mñKHYt_ 4 ¿#í¢áZÚÚÐÖ·0Æ#’f `Þçbies&„ÇîÓܨŸlHÙ£¶‰Öì¸I>}¡]ª¦tÛæn:êA#àcåû&Íh¶‚¼Éu®_¡üùÓ;í§Úa,ÎÞD?þ¦¢‡˜‰=½c6S]R›{`SdÅÐô‚ו:ˆâ•wb*Ó¾c[Ñsü ?´E ê‘+RrjÌè$î·@Tv TÆ3G\Ó=+š=>ºâ–wP8©j3¸^z!Ñ8_Â?“H‹–= Ë›7B¥lÌœ,Êä?ÍKÄKd}h­øUÙ»%»õûÊúå©»ÖèšäS!ðk·œ}ö)eñU´^ho3‰öoÙ>›:'ÂÌÅŠNlÍú?”Êð^¦»º!׸äõ°dîi?kÄ®…ç'üê¤ßoôñm™÷´Ûïm †:g&G³j4ÚØawsc_­@7’¸Lsf/>QîRöBD`&&1Ç‚W¤, b‚ÃŽRî"“΀:Lx¦0|ê8 ¬Uí (&@X'¦§Éd~ÅzYŒÆ ôåøß04dÈ´î$È1.ÖϦ°Þ¢d mí^]ä¬ÂƬ"몚òÉ!þ¢ÚpŒr‚ýMžï¨hJ NÞYÏDñ"#øõªÖbxçü â@(F¸)T©£$-‚‘Bv´Œ¸Šì÷è8â.Ü"4lÄšÿÐbO§(piQÂèK‹Ö}¯(ípbùËèÁd¬‹ËUè` °y Ä2ŽaøÒnæ8ì8ÑÌ40Æn§OHêëŠê± °‰kðäò!q]%ÂQC޹ú)H6@BÙ',Öæ¯…â!¬ ±°X€€ç‚‘ E/‰¼à-ÖÙ¨8P%àUåࢯ¤*¨e08ÛæÑ‚b¶dŽD¥ÖxP‚ñ^³+¦ìÜÅm˜Ò%v±RÍ :à 4Ô‰ÔÚIôöoHb®f½NŽ bS ²-¨’@ 0Úç ö(Ë<³Mz4†LÔf‡ nfôålGÊHíFÛ€ùä€#HÉ ’tïÊ›.éÑTÔˆ]Ž8‚P"4l x)RMŠrо!¯P½°–c LsMì» ÐdçȪ¸¤š”mRï8âï÷¬ò**ùâ‘~ÍÔk€e8#‚Ú^R8æ@zJ°IìX¨NGq°Òò§Ùc-ÞøàlÉdýl1˜šE{€šã9ï#L¾G2§kÆýÙW9væyõ»2neð…o=Ńûß. ýÑ=Â=³ÁÙÜ!6=ル7›Ç+ÀÚܦqR묶ޓüÈ´ÊJÝÕï(’ä³¥zEƒH†•ÁÑíÙ¬ì¦&#ì@ôº.èxaõx8f.™PŸsüöJaÇ¥yX¦\=«3ÕŒÖmT]÷Å—3(Sfs‘»8\a/¢uªQ²扎ÅvØ&§ÓEÎc¯Ëí7+b¯9Æ®Ö #G×¥ÈÕŠ·ÇbÉ܆ŠþÆX§rhD~c‡‡eê :äÆß;Dú Ö³Îd1¬ä*kˆMd5H&"fŒO¦±ÙÌç3ž³Äª +NÊ\Þsö÷<ÿ—å [X<&¾dá8ÄÆw\Ô½ûÔiEþ ;·à"“[˜#ƒô¿§Ópý&t,Ø®'/ê_-¢PÓÖÒÔ'ÒάëR¯3R—Ötb P!Ošv¶#r4þÅ©%”?RŒÈ‰?éÊø¸£›ÖÖÒIX]Òÿd€7ÒŽþÙô;6TR*EB£°rKLFTUM)z4à`îÂt4MIdhê^˜åÔö:~ÀR®SEA"nó¤7â,ˆHGû ƒ#÷Z,¯¿²zB·¢ ãLö¥{…Zätòvó¥IZh~ÕÔœË!Šç!è5‘@Ùx¬ŽºžEC-´%-ª½T3 n€ÆŸO’Í¿6aèÖχUOm¸ñS°¶¡ÿ1rHŶ®¡Ù4$…+ô\eU^5¢¾)¯±Eúà èAXüÍo¤3+ÿ›7{ËÑ µ| Ù²C’ê`ô…#íÉÀWÁûŠ7‹äìs-itHý¡4ÕÄúx>¬áÓªB;ÔvÜÎݹ9þÏ+ŸÔöŽËˆ—9Ö«ðÿs8¬Yžv†í ·“=·W’KÏ:žhÀIµ<Ñ©e!Ê$’òÚˆ/E‘¬&éXðÿpÏ”¾7ņÃW ‚v  SµÈ?c£}„¼Dબ'#j/3†ÉÈÒ€F¥TÓæIñC$|ˆ”˜Aœ²Ù%iÁøñI’Êo¦1$–²HßÞ“-ñ¥B&FÐ ¹iE‰-EPtì8'm1—4#uÄzM«€*¬ƒ[ïÑ«©uȵLñx›ôÒW%Š8Ëçé+&´èïËj®ËòoSèðÑ"Ó ãà½]BbW } „’¶)BôŸ$Ië±aÑ`2à1(?±È¿'?_+–rÓY$ÉÖÀ*R ¶®‘ï?¨$P+”}É9F\ÚÙ?V ~ш[š^Ju2ÛB$›¤L1Wù)$þ¥•uB­Â½vÚ­ˆ£œŠ*¦Db áž°2𭸺fø‚èú+Š’˜°§‡SÙr 4$}WN"màÓ.\ÔVR¨°?i€·àŠËQ5À2¸KÓøŽŸ6läÕàü"À%ÒFàuE¹3ò¾^3=2T¥ªOMÈ®:åzqXjQ¡D<žßze›µz`”D]“rÌqI€‡iq½HÊEÍ6rM •°a¼ã“=uª ¸$,s-xgNê—±Ù"õMÐ22ð1þ¾·ÆÊ_ tò,ͼÙ` ÙmOÄïmí²Ì6ìlI Û¿¯šc?x4YSžýŠºŽÐ5¶Õý(ä"£ÇI±3Å+Õkè{n}äHlkúGði$ؽ‰fý®K˜%íëŠL>Ÿ\„Æaúž_~œ¶UOž?Kófrvܧ4ÃäóÉ~²ÀK’nãáL äDý£¨^0¥±”êžÉûiÃõ³•¾žŠ‹u’sñõH›aý>|ªÙªÂtæŒÖHsúêRóÒõ]ÚZLM‡%"P6%:dg^Õ‡ÊfÜD<â¶EÈÏÎ vìªH¥ÙsÀzÑK]qú¸¢µËÅöCõ&¨I Í­¥Œ¡qÀr F;|èÙo “å+­Ìcòn‡£ì‡ ru—x¹ (1_&ÄÞSºuçR^¢Õ Ò·5ä9UùÎ|Ô|ââ˜xº lªïzœ’¸t>Ôž3å™Ry(:W—QúÑMȽ_É~¡(ÍeÊ¢Ÿ@:²èIԾɸóý„¾Ól™ŽÛN$ñŽ,êá«®ó}~øw}¨šÏ&ð|3@†+ ¹¯A‚›h䌪=‰Èz@ŠR*šªé/d 'H7Ú$” ñ”4ã¸8òJ)aè¤@@Ï Š£‰Š"+ºLR+ãFˆ2^§ò&°è ЧÀ[£pû›Âœš`+Òݹ—Óú¢¢fáö{ѬóÙ±£U$¨˜;ˉðÛÃ3šl>˜¶Ý0ò·.Rؤ‰ä·ÙæŒôû¹µzú¡ú7Û¡Š=²Ü"(‚¸’È?ج?ËRÃA·*¶³øÆÃ8‡é¢2ú¨»¡øÊ—1ú‰ô.à‰6 š×+c·(…±'2팻ï8cŒˆ¡Œ˜X§8Œ0ÓT<Ë$™ä»¤?˜¡y Ú +9·âÈ È˜;²Ù\(ÙË0a§ÃÍެÛj™t ˆ@ý@KQ…7s‹£½"1êÏ ò3˜Ë’=Ô?*°#Û*lb8¹ÍC,3žYõ¾\t5ã±1öÅ |•æ‹nÈ´¥¤ЬeŸÙKGàÇ Ì$f€)”.› +KEò· LžJˆúÃËÄ©hñ¦iÆ¡‘é¾³¢Âð z6ˆ²"è}—16&ã´!¤”±"ð"НŒuDcP3ds Az¯yҘˡ€ ž ;´£ÃƲïÄs¦j£’ª¡ ö™ •ac\_¡R #ØÂ›‘s)£°1ï,2x€)Ë1AŠÀû®€Àûî“ ,£@š¾ã7XºÜlʘ‡6Ð~·L$Ðù™C&‘‘˜ˆ¡ #ó¼ ~ª¶t¤ž“ÔÆñ  Ñú»Y ˆ·Œ²´šŠ4ŠÌTÇJ¤‰Ûú’H®L©É*›šÁ†©;VÀbÏ:˜‰2¸}"à†JÛÉÀ£»Œaûq‡à·ÍÔ†³ùÉéÈ©§£W=b ˆøù¯ˆóÁ A“鉻›ÀLȬ ºLËàÃ*|^Îd€*z5« ª¦$ò¹}‰–C<3Ãì}“`交5KRB솭Æ%©C?‚–6€M;“ã€3ÊÐ5(AéȼæO¤mŸ¼ô™…ˆb|2Üóo¢ûT´Sï9Š%ºç ¸‡;´œØÃy¼ ±Æ’¾°¢Ï4¼4ÂÂ:¸*ë¼6zË$£E`ªˆë£H¨œ¯è•»tÇ”«šp´¢ óŠä­ÀˆzE„[€$²=Ú~ ¶,¼P£7ªBHÀ°(Û,ŒKI'Ù`š¸Ù†ê*4}gS¨†ÆÏŽ¢!{¶ªÍЦž‘H’l~ ­2ê<žx—µ“U/‰È´*Üá%ì e$JSPkÛÕÒŸVœ— †+¹s äeZt2%ÜY]Ü‚<Ý\CO’»Ñê°¥YÌ+þºy#`ýõÎSºõ®ÂJª{gP›¼¼x” z)&±é0ª?³»Ÿ. 5M²JT©­²IÂ3r(?8Ï<¸XùÅ–À‹Mj LëØ>BÕ"”©çÉ,¸c>½{`î/`CJ02ûøŒ+G·ª=‰¬îÉMR¿¬ º=™eZµÕUqíÂi¢“`©²ž¯³³™¾Q½—â:¤ä-ZjÉ%u,DBP5TœÐ€ ‘Š<˜=”¿¹Œ¡H+òó¼²õ×TÈÉ\ña=ùQ£„Û¶ICûß`=à˜¤,B¦}ë4“ï¹ß“+G‰Ê>L¸*cÑQé4”=êmN–CPà~N\T4˜:¶6°›gZ"ì*…–"eܵZt¼áÍ2¸MIå*Ð/¸¬c×½UU˜·¢#«_$œ_t˜ˆE³©Á4UÊöM¾ŒbÉ"´·$òM Íã -£Ž_ߢ(f=ßC¥+âœG¡Ýýdv8©Ó£]ŠÆµÄa{X^ùH¯Œ=Þ%C[¨…:À‹Ë«ñÄ%ñ×™å4Íf2§”‹¿8õ"]cÎZ‡±yò$èD+`Ÿhiê›v_‰ê,ô3ɃfÎØ¡Z:ÎN ^T åâè[SÚ‘¶¡Ä3ŶqÈKI²jãH4¥“.åÕÒ65²°L†?5¶GÜóz®dÕÁÅŒ@¦Af‰iú›–w׻䞕0ö$:·0Ó!U1Ü9Ý–&‹.Ê!Ȉù'šòŸi3À\㉾5NjT’™F,Èv§ëÞ5´â)ZLz«v¦é¹í“eúâfYó`J#âxK’÷ý%ì´°Á5V‰I,Ò º€¹è}’xŽ8Ÿ]ëÉ N–èVÈ2-«•A¯^DëyE 5­kÛÀ§å”á4¤k–]6vS¢…ǡ̦Õ¨ÎômwT=CܯÕ\ì˹8. ÖTž«dD,äzvF¥éb‹ÄXßÌj±œW-…Ÿí«QbR~-sI[`Ì2ßþ]n46×hÝ"ºoŸ ±õÙûjׅȘÁ¶ xŠ>ÞeNNH"¥?²ŠýK ®Ö)W×Ú°RÖÙf&žæŸY®š<1{ Ûç°Iî°>ÖˆýÕ{„±“ ÞoÕ)äåˆCÈiVË^x'Ù¹ëê±0òŽžÅxÆ.škI.dCV³ªÇB èö§ìûf±›Ò”Îd#3ÁJš"¾l¾›äÝd!Û?FQ sc23s%ÂMvLJ(«•üDNŽ€Ê¤¶»è¨jé•;Mâ 1Û×HIK|`ndRäwá ÇC÷KŸiö%¸M®W¹õ8œx :»½‹jêË$•?•ĺø™`éènW´È‡7N‚É/p_ÉsÆ’k©ï­ÃˆEW8X^Å>w? óÔÝdL“.übv5 )ƒ¢"¶F£Ÿ4ûAE•^Š8Ur•œó¤rÃ1š<¾Ó€;`â%XF„¥Ä•{«bÜTº@^œo‡ÜìD®‚e„ÄN8æu Í*¡Š;‚éLà¹ÕgOÚ((Ý×S÷pÍ­Róà[ûž]¢µr\O#ÿµ®ðl­qÖ9×~òÖ@€:³Ù‹È›©/" ÊÕ)é×¢ ·¯_¼+[¹¾²"ÕåhÕ,XñàXUP¥¦e ›®š<™d¯Ö2K\Ó‡­s:^yOyVè|on57Ÿ»\æ»ÌqxÉ üoˆx °Ãm ±\nî}}yk5!ý„wÊ»hæ>Pñv·‡×Ëã‘qÖxãL®®sÜ•§•‰š÷(°5ˆt‰3¿Št½i XªçÆÝ|j‰‹v}»¾pÝvÏ'Ÿñܺ·;-eüµp~è|’{`¼î:´£7”Œ`•Â=×ãú=ìˆÂ^ÍS'êÕ¶ ²w…¾þk¡úÁ@px ‚€_ðD"ÐØ{ò‰€ ppþEGd'ûîTý–I$’ v]†É rÇìd;”N$ò‰F,œCgHl6;5šAg9$, ª=jÐÙD*6Ò °8ìš*}Ø"tšt²h¤É%éàs”Y*€X¾#vªSš\¼ŽÆdHíEX‘T&uÇô¢•g¯À°xûf#(½YûÍCÃÄs¶Éì¶%ÉZ_ºH;çeœ`s—dýÿ‹J$Šâï$£é±x.3þ;kÊädR`>ú»ð7².œƒŠÑ[7Qh‡Râ€/ÞÏG·E‚Ðó3:Ìo¹R¡ÆßØž>ÝÿOŽDîé»T;N@П鲃¼ ¤è±Ð¸îÚP¡¯€+ ƒ¦H‹d|²`ó·ëN‚³¬zõ'êÈÌ@Œ,•#¯tŸ&À"mÔVާ`:ɪQ ”:¤ß¥Œëðîò"Úˆ k"©!²9ñ²úæ¾Ê3s£°JCÈjh²#²¤L‘Cp€飪’Èò¹h¤ŒÁ¨Q®ëóƒ%¿,R5 jŒ±è¸„²Úü¿%è;;µbͲ «6ò³T4½.€3Ê2‡¨i@Tºu*KR”ù7"lW€/âL€Nœ>𤽢Ͳpò×P}NÅ,“Ùý6'ô%Hoq´qQMð2A¢1úD  ‚qˆ}ÈÜô¥1Ý™7†¤XVJ~e9R†»ïÑ>!)¥IÈ~±øµðÑ™‰MíŦ¦½]ƒ‹™ÐÆlsUÑ l`»¦3>w OzŒ«„Þ§Ô*¶>ÎlÇ•'þN]ØbîÚ Bç¤Z {½jƇ¹·2DIâMêÙò&ýÓY*Uñ9Öö‡á¹Š1ïÌÑ:ÒDµŸèo(¬œ2Åb?Öbdqoî"’'PAK!Ñlåš85ðVÉ›¦ݪ€22ÎŽÚX§†2'¥µKº‰iÁ¹§sîºÉ+å­%£’ãl£BSñi(±Ó; •"Eñ1ð8Ó¢¡`C$_¡í¿æº­b/ÎYw¤v¥&iÑ‚£ñë"†ùÀ, ˜kPª‰c&¤¤q(|ÝEŒ>Ñü=FºkÉ–:rL‚uk¢¦Óv¨˜ ›njÚg=æê>ˆÄI_êm·©2ƒËdUmáò¤üG³ØNþ–VæáÚ–@î+„?!c\Ñ"èÒ6R<@š2o<2î:¦N‰Ý -pËÀWVCZ¼í‹õƬBX¡Pë>_®¦5ÅêÖ_É,YŒùŸEòMእ2Q¨1Õ»PdÁÛ…ª¥ùÄœãáÓŒ4cß<‰$d¤1ïC4Ю$–”o£)`gê †$î_”5’øV,ôœSuÈH?©×ªD…¡Ó¶¡Xø/Î1¸újÏãØ{¶pŸ¥>çÕ09Ѱ…ØqÿRiÓ,ˆü»6FgáROæº.1—Dˆš¤ªºØ—{IÿBKý¡·í:â‰á¯D&Ò§•\O,jÖÜÂ"—_˜Ä°o&;¢€Œ,í<5jJ–|CPºâ˜ãòÖ5:RæiɤÄ+ g˜JIR"ˆI5¾Ôû³m`¶Æê_>¦J!Ô”<$’ù˜©êfÍ´¤Y¤©ÔÀ Õ†æ¦o¸‹Zq÷G8ñÁÕ¦-;°ÞëQ,ˆ.ÉØ) wš +GtîÇ«g½zG⤮–"±UŸ\¯´-‡–ºñøqB{ÇFë¡õˆ\;}‹µ7¼œéµ²û¹ssÚ¼iW%²6Ü%¡];×½WöÕ»N1Ð.gÙ:2Ìâ:š `u˜gc'= »‹"Õ»#ÖaѪõJîE*ŸZïdmˆvÆ £L‰ˆð‚Tî'øÕLAC”¿ƒ6óD¸ÍpšŠÐ6#e )$”Â’’Nz_p®Þ.”-ÖÃD<¬ò /hšc¶}æð!j~ñK禘<¦Î'®CªZ âîØ‹¡ö7KtoÉ0ó…úÂâmŠæÒh0³hNÉÁôûÏ>®):q¤(ðDƒò¾ñ˜ƒÎn’ÉòoÄlŒÂ„êæ‘ñŠðŠWMaq ñ‰ ª <§Õ'q–BEúÑ­»(Ž1' $ËÇíáò¾®ÄÄáþz¢[¯hn,ª Çäš§""³/¡þÁIè^êç4±ú6J²E)~Cææ”}",…nà>CòšO µ'zgØøƒ:ùíi~P®œ # º ÎÄ;ÏüŒƒìÑÞÕEÑÜË ¢þä™hð/ÎÀø teMîÖjœ‘®™qŽ@-,¯dRÓÐgéŠÉà #©ù¤~¨æºÝ¢&BòÜgÊÖ¢ðnQºþbö,‚TËÆ#/Hˆ¼É&¦@Ñ·(‘†r̦ ¬¸üšˆ IíxÅL"”¥Ðk/È„jÑø4E™ §7æ¬Õ~“ÌÉ+VˆÍÒêS|X­vÿöڨ„ùÑ^*4Îh×̲‡bÉìjò&œ‚Å:Ʀ™ÊX6Q\×pLz.Ù ëÞÄn sTSF ±ÍŒ‹*AéG†t’-€J ¼jLç Pr€~é(Ѧ¬Ðe ¼É§’ψáª4HNôGÄZ.I±z|F7:ìgHÍöªâSfT›3RˆS2ä£>ÿ°{ÎPȈ¢¡ÁˆË8Ö£ðª,¬Ðʰm!°»#¢3¤‡o¡ånƧðÐrlEt‘4P;‡~ûñR]ª‚Ö ‡—fjc窻>NŒMåŒ÷­`úííêâ3´ž.02¦gD ç©~íIÌÒs)kÌ6˾އÀ¼t\*ˆ[+\ĉ2óSb K¶Bðôª.BÂËÊ ¬¥#V³îŸ•.µ&Hþ/¢ CÐB(ôjc£ìjÒ²k©øGèÈÑðŽQèd:£s°ÒI±*lë|ãµI ÊØ±dŠ_i?@ÀŸ‚9‚Ç(0®-ô òÕ92ò6Óèí®Ѳâ耉B,.묮Æ|³iA%õ"CÆškÆWL0r‡(=S-¨ÛŽhÙpú"iüïi)ÄhaöûÎH}§ö0L̦•Z“²žKýP°»Sr­r^:-wF 0´F†þ1¼TI+‘1S©Ê%?."Míç´l[e¤ ,$$‘ÒOží±Çk‘í®G rš"-ýM´.QO¾¸z«‰¶¸´*ºãEOµ/k£KhƘþ‹’×ïdór3tëib“5C*⸮"çrÌÀñ¶ýŒ$7Oh~Ñ8ÒqúåÌå*¼±¦»6 €p…b±ôÛ4gMtö™âÐaˆN‚'WXã §oq)äjV¢6CkV åÚSæÍAòþ‘ÞQpöq®ÖÇnuÆàÌJ©£çzƒº"e˜gD:ç¶glìñsu@“71°® lØ”åI0Ozˆh’Œ0±Ìz“&®ÉvE.÷†“2pJªóÂXgG6îNU“+>ÎdM#\6ÉQ#·#B`2ßLáú’Vcn¤í‚}·2„päâ3÷øù Òi—WÈŒ@?8nŒ—¸øDœ¢4Ž*“ò¥ím'}Tm”êlø1ˆò«Ïzo.$H¨Û0Çu¦èГ8‰fñ1Šd(;>Ýã?[m¼$N·„#›€·æªæýJËÏH!|)(žÑ©^®µÄÐY,§ªØ»w „èKjŠìž2‰ˆB]n!¡©’’ËŽÆ»*ı@+R\Æ¥C¸œU8bãÖZ#BgWXÄ:Òxvµwyëÿ‚-_"mXfºJuŠp¡ œ7HÞý®Að\Hî©–Ãd>—æ@Ñ.»(enFº9jáÔ¤‚'F+ªãzÆ!hv³‘X±“*Q;ó‚,[®˜ƒt.ù×HÈÞÙ¯ .u؈ ù 1($IüC³£g&.ùCu×›y4žÈ0oİŸÊMîÃ}ãdjR?>8ˆ:ö¡÷—Âî^TE”ì±0;PÅèË2Ýry8<©ý©_lß ‘bV- Hö#u:jìÕè "˜ ç(%qrûSþ?$;䱡¶¤Ï:‚¨Géø­pÓ—cim“Øâ—wcò¼mYàž'õÅñ‹€Kñ¤ç±h5Ak딊/è>×'Žk•ee¦ñ©ùž ä¬àç§AlTiŠ5>å˜þÂý£”• ³y['[ fe2a!çq­x <;fò±ÉøqBU¦¢6 Íð6…u2zD{0á ÓÔ+T’»m Àûî@èÕaac7RŸxM» VÞqûoȱ‰bY&­;~lHAåj+³\ïЇuŒ%DÄÑh6V^í” ùç?O{—ÑúJó±K BC§°âÃ<®&;r«ðÃ%秊6sŠg ’Š ­0Û¨©1=±«–&d¡uÉ.ÕÂÏi3hRË“œÚ;Vänài°òÓ“8‡T¤nòì¼b¤Ò),»0äpMC"·CÁI)¸±F߃¢ŸÜ;Š˜·ø3‘­ùoRõà'tdô -w„ò?2÷|p23ê+—’±r_Cí9r%V|!øÅ˜Û`P­{uêö1 "_ú@ïIˆñL™µ‹ÐÃ8dò™HSñ·l¼BUÂÂ\’œSãà »ª<.rvPà4Bï©•«h•ýQ#;;䎽‚€ô®ÃBjæ`7'?—‚fÎõHÛ¡°¬´œÊŸÀ®Xñþéhr0>k¡«Ô’ mŒIEé§«ëÉÓÛGƒgølýb©§«xnoÜ¡,ä? ‡n[d÷K}Y{z’§${|¤Öø"]q²gZÉ3H§rªùÈi†}oˆ…¿±ƒ¹Ä¼Ò_nYÓp†2:ÄÒ>Ü—é2~Ê  '7§š1Îl}ˆçn¤öz"ÕŸZù˜å¸ºŠ)•MÝô—#¼³«4ÏärÕ‚É#¬‘ß.݃Â&m“•˺jðæˆÄh~ale£]ÞËˌ苯N6퇹¦õ´ŒLÜI°¦Æ\ܳ¹RW´®%77»~‰%ã‘© ®¯›w2>ºÙ$Vz‹Š kÌOà–.ˆ‰¹÷‡/¸†jû÷2^Uâ®Í&YÔÁp¥‚Íû£…â'øžŒî÷馱¹åœüçØ§]¿3O¼¶4T w8å·Ãí6—{i%ôؼ}Ú‰ÖWN14÷D¹6•;Aög\JM76 ÷¢>àÈ3þ…@€Øt* †C"H³ú1ÆáÏÐ~ üˆFÑ8’>‘Ʋ؄vÿ†Lf38@q5§’hI:Nq F‹%2ìBS¢E!SLAïY¢FÀðGÝB>ú±JßÒÐ,ÆHµW¦4Kê[¾.’™ôB¨»@¦šDúc§ÒaÕÈì’I<Ge4Kd"— ’Tï—ÙD~cK’W±PÊôv{Ÿ/³J$¦S—Ld1 P"CKÀàŸºý.½Kͦ–ú囼ØZ<®–iÆÑãgø|/o¯º“öØ”ÒMçJ”ã%ˆÄW(7à ’ãÝŒGlÙ=zCª¤^£ôJ&–St|j?›Mª¨¡ÍzR·¸‰‹œ~ÀèRÞ¹ëB2ù°‡êÞÅA@ :ò# *È¢" îÈ"Ë£/«Ëxÿ=ÎÙþ’,‘t$ɹªCøâ¸ñ:LÐ QY.Ó”¢$†Ô†ˆ²2̳"ºvžÒr—$¡G̦†,Ï üÖ¡LRÞ˜2ò¼ù*¨C†…6(»ÄÒ©pêñʲ>ˆ(Š0Ý Ó#é¢o+’“D©”úÆH’L’$0³DÆ?‘&â8)*·¹€¬‚t³õ*¥³x’JgÌÔð RÌ}AP¨3Ø—!M”‚BÎRÌ¡339üÁÐ``ËG¯šŽ«ÕÄþL/<éYųb1M¯Œ¿RðùÐó„Ë; M’O(J\?”ôwo§¹þÍG²½˜Å$‹3¼Ú!Ž #ªó^Ö È„£aŸÊòRÅSÊõž®J÷©ùrÍÈCUY•1ø«ÂMÚ³Gs»¾¸ŒúÅ+Ê"—p€sm¤ETõß ÃKì±=# Nx5¡QSTÅTmKÖ‡bçëˆû'8>LÇxÚ,¬ží}Ø~ß²œr%*ãfÁC4~Zƒ$–~t·ÝêZÞŸ-ˉ ¡*¢QѤ†ß;J…²¡Ë}Ÿ®e` _¢Ë“Ž®NH6ÓZ¡™Ì!bS4¢É ÒáP°”Ütò—¢¬ÉJ¼®?RµNWYcJ»ÌI¦ 3çF“p2ÉfM`4œeÓ‰´P (Ž!ËJÔ·Ôq&î(²”§{¥³º`„,Ý`Ÿ)H³ý ¡XŠpŽåÙ¹üÃ!ÎT’TkÕs  Kæwªäý=Û˜\i´áèžAïV;½˜þ4\—ájôãq"Í:@ƒg\¹C=L¼ü—D´Ð»9 ‹nå~Iz^uÎ5Y¼AþÚVbwMªH†2ã°û_{î&¥?!eöH³gíMç±æpÎÛ#>G‰´A ê˜ùæY…¼¥®4ÚÖËøGjÕ?8È ¡jT ÜEÖxŸÛ™K¶ÕÔKTñ\v€é¡åªÓ\ Au±}Q–B}ÒÑѤË&%qÐÕsDžæ²Ì4¯©£‘…ã ÕDOѦ–’B¹6ª¬º™‰U²È‘O«“k…)íMÉFúªùcäñ¬v¦ôH1Kr¥Ò¤V†ØN&YØA ,É¿aQZŽå ¡VûzŸªD:›ê&(+YmNŠ@Šq6(’ùrìÉYYó9 CéŸ7ÉŠ »kRÔhcìjª©À;ñòkÔÄ®)‘}OMÀ°±›±UÊÞŠ/(PK½ÃÔÀ}Ò¼<ý)íò8³“ˆÓ[ãÃõ¬* t——¸N+hÅèÒÂ4‡ ‚ˆBó-T–äG¦ôÃT«e—;#¸×Ôm{j•T€Fv˜,%Ÿª¸·1m¯m±8ŽNO±üŠša3®bGfUéìA¢lT¤Iaö•Ô’¬Î²Fn½éõP&íÄd ìÏ[ì#8ÈCêõDò–~ž¨ýÀÌ%Xóhñêh5çÂz;å=®þÉŒÂäÉäGÏÖ`;X¾‹šX20¥~X Ž ZŸ˜XN~j48w’¤LÈzd‚M1÷‘eù  =š£yæíW,…yK¸®FãJÌQd†,Gì} Sô4Sƈ¼¢C¸«¤."&ò•á÷jéeÌÐR>€:Ræ yþÆ®øˆú²r·‰ ùh‘^'Æ á\SÍdêIågÎ5HáÕ²ÁCð+DY8 —¨M„u êÍóvMfub5\)¿vbyä¼Á»(¡ÇD ¢®:ß3©¸þ1ZÉÛ#ÛwŸ¤úŒ§ðÞ2éò@§YÙ‰5½MäWCÊìGQÑ÷1iÂX¡¦¼$/CÉ‚6¢2…”À5¦fE6 žøƒžÙ‡€lñpòB¶Ñ$h˜©¦ûr¶¨U®’fº+bÇá¼ÖÞëÌ•i“ähç;ê ˆ¹ÈÅãgÉ4Š{S @ûç`·¯XШü#´Ì‚(³‰p+†iŽª KwßYâÌ­êÖ•ëÇ裨R‚zX%øë‰ájªü'Š×–øžükßRÌã­¦@SÖ ý¶ì¤³)ëŠP”Þ¨dä}at÷<£¬FEÏ ñž¼s°~³¦€¢ Î'ñPY£0ª¾l–ìLŠÔ»[–%º¶hý “²"ˆÀÅœ¨–·(އðí@½qå.ólÙ\¹ÀžRC«ùŸã¿°‚‹&‘ 7ã:áé¡£´¸*> Ÿ‡ÙZ¡[޹H+—º)šC“8)¤‰ã<øÿ.âÿy?:9Q‰‹—µ£Òœ€!зàù´ÒúˆØ†$8׋3­øÁ€–©¡©µ¢ï8ˆ%ëP¤J·«À³óޏê9‡£ïªI#ä2Ú„²j¹®(ƒ3K(±³‹Ó«ÊoŽÑO2Ä º¤¶\‰âa¡q§K½ˆšò.z³a÷›IÕS!€—{¬½Ï1|/¹œI+”4>²/¶kÏ8kyÛm+²ª±)÷Á3íÀƒs¯Sê‡Ì €)ø· /¼ú£œó*›ÃœóΙy;¯“ç%Q|Â9á'¹©³Yø;€ã¡9³Ã S$ˆsÈ›^ ód”[µ‰ º ˾‘[Õ¸)ÆlZªÂÚ!ä‹Ìc&ƒ00§4b® T8ñe5õ*Û”ê3ÃöÜCìøýž¾H°È؆Ì!·šÁ 7ëoËCt:q¹+A䥚w7@âH±ÅÒ2Á=´ôœ5GI㌻PF‹5ÇZeîÀèÒÅП*»ï”¬)tCsA­7;+*ª´„K*EÂcb6IG›Ö«â¤•8‡+CðÑc¬³8"ɬ¹YÕ/ÑÞQÔó5ʦ(‰©aº@†¬êˆìŒ3j€:eÀZfMº¡j&\M›ÜY!œáµ|ª0=4#ÑòìÜ,ྦLNšµÏqA >7;»,˜ªAжJõÜ1º õ«¨ÐK\@‹(&ƒÒF „%"˜ú¹ÚΤK³ÂX‚?³Ë¹Š¬ )Ÿ¹ÊÌ,€}!¤{–â–­9 ;¹ØÎ›v ½&a—*DÍÃã/¤4ùR±ú<ƒŽÈB¼‰´¨Á:ã)¼ËXÁE!Oµ©õ?¡žÑÓwƘÑÐ{N Aͪҡhå:9‰œÄJ®²Æ8 óRZ¹â¨)Â'9ÙRΘZ—ÄM5&2‘5 Þœx‹/’Ä/Ð…E6˜ý$ÛD;ôZòÇ à«31¼‚ê´ã)°$¼¥`„ T,D´< PžFø‚MÊ$Ÿù-ôV<1HÜ8Éê‡êe±Z¬ž9=ÃäO8Ôc©."–ÂûëÏ ¼ŒSU!Á¢{@p‡Uð6™¢•p“C¢Tˆ6Û<ÍWIµB$¼„x³*ÌQÄç nº;"¤­'”qgÅÄîÏcS ¢ž‘D>¼\f5’ñ°L&C? ZנѽäÒRÔ É¤;Ti–Ls£¹yGMÑ|›ƒ«#.Á’Ã;)©¸‹³Ò«€Æ|¡—ÑìϤ q«D{¢×€¾ã*"éq±ÊJQ™ì 4J®²ËŒá?h–‘QõÑí7â¼HPÞ|N,õ•Kå3²\G,E|2•£I_Á-¥+\üH=.´³€D¼›Ø×´©«Dw{z‘[϶}®4ÀB¸º1Ý›Iã˜I×*BÁ5‚á+ûyÀö¯p}Û4/µ˜…G {’º'“ô 3¡+©YM¹-2㟳[|Ö¸Ä3¨S2¬Â„N•±×Ì¥ÇYÕF2¥C­¦3Z0Y|°ÜÚ×Õ¬\=E¡ر<úÄ1$IªÓPC'´€‚Qã—Ì|—Ë2…Ó}1ˆó Á|l @y×IŠ±Ýµ—ˆEäÑ#kþ[´¹¨|üÒeíËÄlÝø‹Iê¢ü1Þƒ2*º¥·šŒ‹`Õ ×˜óµùÜ™È Ê ‰Ù7ûä¾I5Í$ü¤i‹“Eª‚# DÙÑ4 ÆAkÒÚD,ß!Š~Å}î*ÄæÁ+¼‚ùDsÐŽ¤†ñÕ-“yª'à6  ¢¢*½ôƳà5È3"Η¤ !0=b֙ݟ8þ1w $¡ÕµÊ¡K"°-QR}Qß#P¦ž5…h”ܸ9¡€¡{ºË‘àc~$9í_‚@¦=0{DqM¦TH¡ÚCܼ ¥o›R‘ؼ tÙ쬦ñåÊ%ßbµBÄÇõŽV¨˜Û5JL…jÜ.+Úö<°¥7Mî–¨ñ+ûü“B`Í]2=™*ÍœÉ`âYeZd±—ÕÌ.\Ó÷€ (×Y<ª¢ù­‚æ]›=œÁŽŸ£GŸV "ƒ»É ¶È¼'dåêb%4¤ 8U²)ÛIaM弬¿.ëó®bžÓ¬:¢™ï[h|+÷4ÙÕb–ÙtXOn€" b$„5€ìTµê9XùÊ€¼¦qž,û }/8•à}&9;Þû:V‚Fé…ÅÓ¥^Ý@¼mz¡L†ßÛÇ¢íÒ`£ÞÀa«¶ËN‰A¨â$X|±u äAÌ^É[SŽ_Œ[̰,³TŠDé.¸ã›±uØ‹ƒ. œ\>ܘ¼¨aÁ 62:à®è¸ÑÖ ΈˆVAP8±.ÃîÃëˆË²¬µ-=ˆ2“ ZQ=„@nËN„08ˆ¦-²ZÐzÚ•£Dq68—‹ÑZ9¸è‡Å i!™cÓäŠ`× ÄUºþ5û.V«ÝŸ|œÂ½p¡01í@ €,‡˜ífir_Þ.ÙMÜm6¸õ*:½5õ<ä|Èë"¤h2^f\ =`®iZzꈤþr°äÚl‹„̨²RêSÄGá=ã½›ã`·ZVš]S^CF¹s;ñÝÕU`{_¸Š`´ÌIz~¢›ÈE¤SÆ€ãí$äæžˆÅœ¯i…oÉ)‰ kð"%X˜Zc½T>Öh‰˜.å ¢öl¨Ó"L…Z˜oÅ,6 ˜áº¢šdþÎn=¬äÞ…Ñ`Ò¤Fàé JåÜ‹4 ~žë£j?ÏjêßY= ´Ž´;×m$ 9\ H€šmÞpØ»^˜º~˜µÉ›µ¿ Væï yäj–Zaûý–^º–{]7ÔnXX |‹ÚMFãW —j­Õ‡å³ !g·eo–Ò:õWÏ.¹!߲އ»“ª+¥Ï™` }ΓÂÜ'J¸º•;44ÑÙÜ]’ÌR¹|‰$%I”ñ|t@®sÖ#XˆÒîŽÀ¥—ŠÐÊŠ–éâ' ÎED¬³/ ôŠ_uOÔ|ÛëÓ\5æz­õ>ç¿cˆº<<ô ™ãØŸnš q“b¢NŽÒ@¤:¢ "C¯±g$:߆‡ÑMÏÝÜS næà~W áé nª…°ðõ¼ÎÒ̺g}\1Ê´C)­ÆÐÁQÍŽì…Á\ÕÏÅ…I~É £©;'0f˜áž-³>U‡Nœ%m%9À±?+À¼Ù³½ GnͳÐCèì*%ékYÏ´ü6ÏI¯–°a‚ÜŒ‘+AãÛŽ¡Û®9èì§âÉ'©”÷¨»h7›>ëÈCȼÂìÿ+“~N•Ó íÛXŒ?+B»§ô6Ž%xQ–"Ÿ†é7|ò16÷Î 30Ú!¢tM¨Ÿo…ýJâªç[/•³qZú,$‹{w(Ñ|t¼Ö?;Ä˲<‚" Dü{3|Ýå·ê¨®0JFô*‚:â>è#¶#°3~…¸J¼ó0:ÔC‡û²§MÛðã½-ô0†¾°ˆÖ·hÌBŽÁl ýBèËÚ£«:ü® ‹Jd©@Hâ"È¥lªB»ží:ÌŠ²p ¼¶Jr„î¦M¢†ò¦HÊĆ-€RÎù>ˆD‹Âª¡ý1§­2dâ$nJ[ 7ð –èJ[`ÞÅðêÆ6SIüÆ?gòSHhthç¿“27Ìà<|¿¯Í<ò #J´°ìj'S‚NÂçú¸±KHôÊ7mÒ'')’RºÒ`El³ÁéêtÎÐÐÚ¨2kÍ&ËUè:³.تƒÔá§ÓRG/%p$WÁ’úâAŽ"è—#o{<ÞTÊâ)öT‰ ÍLB#Qvõ WõMH®\¨Ê¸é·w¤¶7v{ƒ"Ÿ‘ü]Ù4X,éåš8‹:‘Ü•ýÝ)¢ë’@´ j—,'l$‡àÈýC6ηܬ·tâal:Ž®©J?2‹«d®5´«v dëÄ]GÙŒwHôŠÈã`Ü> …=—J©P)ŠFÄÕ´.N¢q¢‹GÙG@5,wT$Ìr.§Å* ˆc"îê!/cÌ lJIJ6¿X¡bât‡JçÑ#\Ê7xˆ¸²Sd¸šY+çb;¹Bz¤Ï IM’õ õZCçxqÍÏ¿wNEX2•ªL¥¢8•bwÍ^5öF lº EÖH"¶’âWLñ Ååa –vA”CNmÐO&†Ñž™IwÀ5Ò—¦_f´Ú¾eÚDÑ¥:t6€%†Hd#G”hª8•‚Z¦ 1M¦'(RêõæHú{³d’LÊjøáš€•¸œ=ªNFáKÉi ÿgSçJ¤ p‡Ø~ 9îAƒ–¨¢· qr!‘HéÒWVHT,u'Iņ²¹HüNŸH¬Éˆœ=kyi&îˆ:Z©T(€S­} ÖX±¿Du|Æ‘¸daã+ €T’Ó¶U$éWá®­ónói£4ˆMÄ)øgg™-³†N¿-ù‡£mv>+ÃgàJàRSñŽˆËæý!Ðo¦Û"¤ì¾Ô'kͤø°µÅŒew¬d’:?aGãhu­+ô'D t#õëÔfÕ@ÉìÛ$fÉv*C¼KKÌ$Y5&›­° D!ù³ëÞÌPÂ¥7¦ µfƪ¢Ï-xúZÌA…ÊÕdŸ«z‘ɬ²“œ8’” Áb5öÃd´®“î¥äT˜Â òÿ@×]µ×õ=ŸÉu%¤)RcGhHQu!ˆNâÿHR I’H,uè­\)_zàGÈö_k¶þ(%¸”JòzúzØ3‰Ø~.”~«Z›ÙA˜®æ"3¶Fg¥y}0ÑâdЍ»(´š“ÑIëÓ´£ŸUç´¸U>óØ E¾¹-i®²{Šh‹Y¿лšˆüHøá>BR¤ºZÁ¿]‰¸é¼UŒ™<¨C:s2b¸ð®‡ÁÙ:±ĸ™¤JÇ£ìºßˆf6õÅm‰n*êäç¯T•’Ì8°ŠìÄ&èI«)ZTY·¡"7±ªH'PK¨¹kÃàŸ:Ñ3~X=+š—&éÂäâ^ô’Nmëi5YÒJÛóØ/=eʸöa›4.ªÕQbøFïMËm†¶­Ú(‘6÷øü§n6²B<¸†Õ™è&ÅH^lÕõq8íOÕ«óVç!JÿsÕ!¿ Û,˜dóIuˆ$Ô1ùIx"¡lý}ó O)ô0¦(…\ÂGÚý!ÎÍ=iƒ„cÁõ!ü87í°Š¼·ÎþðGÄl‹¹±Ä΄V_#k”­øÙ±æOφ #×Z?B$Ma¡å Ü»qŽçM"Ãv߃áO²r/»ûloÏÆj¾Ç绤åA4 WWRÿWLÑaѯnË[’Q ‰åªÂeHOF*d«K9M‚Mr層P.f©EsR—…;  hÑkº¾¸pÔ"“"s'¼É¾jÑ iêgI©Ä™8r‘>KØ÷f¿‚åD0%¹Y'AŽuoU™ˆß˜È€›§ÅäªÒ%7;®,Âåò©ÒúÞ7²Fò„÷gÐäG@ŠD˜Ž VWéDûç²âGL£¶Øçøïª†Á+¬Ï xÜ-†‹Øê Fk˜#®öÍbR{‰"­²¡ü½…Ë ¤‚#æ«H1…>ûgˆ– ö‰‰<#©hÍbu":à'Â!‹>‰ÏȉÒq".ÜÄ:€BSB"ø‰Ì>#d÷¦ f‹(š¯\—',mƒjc‡?B²è .Hy+@×­Dµ VéÅÀPK¤ İíMŽr¢Q&×j º†i 8`!«ØL lP«ŠŠÐUkð… ^mæAŒ¾ymœ“Îî‹ÉKðÈG®¼»h¬­P:v'ÜÊÆÖ ¦0mˆ×B¸R¨q†ËgÔWŒ '¤GÎWëN_"°däCgA¢i-®è1Ÿ‘,†q¸µ1²ÉÑX»çÇRÄñÚÓ»ìúãz„LÐþ‚ä¸k¦ù€¿8T¥H5*w¨€  âÇ ŽŽ¹.nòð$¹N:`Dø:jÏ"-¼| àçR8ñLËâòƒ¦ìN ˜mmt#ãPIJõ‹êiRA)2tEþÂ)޽ÉOÿfäàlÔ—ÍO ¸ì+Â_eH°n¸¢‡/M”M6Njå¬×ÐÔ0©oäu骢¥œ™§À°‡x|%? +`ï ¶uÐÆæaó7¬´ÂNáãê]͘u2r˜+"]È‰Ç š¥Ò‡)Ø‹ðJjHˆþÝáô_P«.ÍY*/,×p0ŠDP¯ËM´sQ¬÷I laìQ3²úJœÿ¢¨)k’›êDÂÊfø1PõGÜ«®FÝKÞØ-A1õÌ/1RÙB0Bî‰Â*ÂË)ü0Cˆ¦"­B_k²‰HfÏM$‡ÃhÑr¢¬ N8W3f)Ž7óZZéª%.X1Ïœ(Oªmq$g…/`oæñë¶´“= n²+Øóêï+PÈCjÄ"e:ƒÈWˆ-8sðPœècR¢»%ÝèmTú„øÞræð&ˆÙ0B‚LÓŽJ} >—Ï£f+Ë-<žÓæY-P\("Þ2†Øæ(ã§-'R÷ólnê°¬õÌPO€»Dí—Æ’k't]Èf¡k²ZÉ®ŽO‹0P¯ç74bkóÔ•b*6Cñ=mg°À—‚ʰ¬Öι!tcî¯þ¸Th‰jБÄ­(òAóELÃË v*å4m>]#ª"먊CCðD0v!BÄL1"&BFÙg0Õjrö*"ún:¡#ð,H@u%æ+Ðúª©³°Bò ܺ…&üÑ0òê¥M*MK¨?ˆÍs¡R;)Jxé…Ï ÁÿT¬’(ÃæU%Òaæ‰ Áöi,ÒÍI7k#ëçèõr©;ëY võ%U"n» óUL`6Pˆ[ë¨Ò$’´2EI|‡#wKÕȤ$:2ˆÍ…ÎgÝ5B€Ì : oˆ›mʦÎÜ¢*9¬™£>SíVËh–ÿIL0¯c¯*È*À“rN? |»ÂR¹écŒM(²w3ízˇq2«éP†kPq#èçòÔÈf•%iˆóÎÌ_k&C%y5€î¤VÔm†NRgÆB:÷«ÜÈM Z´üÌåY‰<åæ…,“ñz}ÔêW•lêUès Þ“mf/HMkâ++i|÷æÓ–0`ȬÄjEÏm$v~ã§ûCLœÏjçÙUmflPÀÚv@ÂÅ.FÓZµ¹OT(à,êì"Â/GŠlAÏT#àt$™Oë0Ó¤FÅÄé4ã Ë¥o g0mŠèÑËð :k3*A’æH–ÞkqYKO.·= î@* ºRòû0sÆRoÃb…¾R°¨Ó’ë]¡ý9sâÏ8 y‡Î;jÖ™»)(ð•Èý Er!+“ºãGE޹lJikWQ.ß7÷µ9öö0–‡´…°¥²p‘Y3m²NhdZKÝR¸T.Âî¬ÓC9rÉx¦³6.©UâvæÖ;vIyâÂÑßOb ªi ŒÀõÃ`!öôR—}BµðàÔDU+|8í¦/X\½V—ÑÅJ®‚‹D~µ nl¢Â–ºKñh.ÚäÔòí‰DwRæ€Q`ÆM}(7|Ì¿U7öÍŠ’GBÅÿ·ð –þÜ’:³–ŸJ,dì°(XŽ+Qˆë«S*C©&ïÂVá0è ˆqæ*7î©óྲ R ,’zl‡GÄýo«PðαFÆC(ØíÎGqxv %u*-™â:Ruª,HV±Úµ†¶ „Â<èR$”º -O¹ªú_ô )ø]_x´‰B¯˜d;jŠ™ƒNÌ׉ÕÈ;t¸"g?rÕs(m TSaø/+aí\C¯z¿¦É1‡Sm@Û¸dñ“D¦òêò‚ ½ˆö_ùc™ÐGï]«Wv QÂuŠÉ"R÷´]\Œã— ¤áú»&’}™jBù®.¹ ©Œ"3Ô%zÞéƒ2ð·÷Òïü\ JÔ©/Ö¢MÜø§x¢úîšö]¸áꡱÏÐûw¥xéÀDu{3‚€P¿{>ýl¹9ÖÿõWùÖako€4k'ú§ª…:§³Z¥yÉ `ÓΠ(”Â:"Ì{3.¸³Ø<÷8»óÏ.h?Ë%ØP^€ùv×Z}ÜMFhØê!™VA1ã× @0ä/rLƒnëÕ=YY­7P”Ëïî“ã~–—Š ¹à„u7Ðaÿ}OYù„v&9ÊUmAYöeIã']æ‰(xy±¶2`ËHGÈ—|‰¥m=·5_è•ï‚¡$]guíÏ¿«ôâCO`ñ+”`:éYPÇGFû«ëL[´ZŤ;wHª™Ì èþ ƒAð—ä. ¿bXMü‹Dâذ÷€d)õ%IÀr˜œ2@”€ß3\Î3Á™ìžHà’Ù³ú[ÉÀ“¹lä¦Q©Ó˜d¾[EœNj lîJú—Äé‹n© ¦Dåôh̾Ÿ¥H(qš`"éFÉ$±(l }ŒËa”Ë< ¬ÿÄëtüN™-‡ahÓÌn'}G_q:5.u"ÆÙ«zÔ‚ ¤\§9idƒWUÄ€ ¸YÜ3c Ñ€i‘¸,2»HÎ!™jF s˜†R/OèÍШ¦è«9<¶‘eä§zx…™oödð]œ2ŸÜh_òÝÕºE]¶údîu2»/¤d ²ùÜf7õ”¨HÈ ¬Gú‘+è‰0Kú@—ºÌýI[˰Mú ÁïÚ"‚2ǼJ¹ÈË,½êÌ.³ {-?I0ËEƒ¼‰ÀGûz”%+³Ò¢³ò”°ð „‚))I:vÌ)Œ³ò‰ø+«[þ×(É{)§-ûÌç-($w£¬ªú¬³ Üi Lpûo«2B(Ÿ$R±øÏñb‚×=ðr²ì3ÏCͽ j^Ú ˆÛÞŒ ­ólßµÉrR¦3ÂI½‚ëµ"? SN"Zš¦ï€͵ÎôÐÁǵjæ3¢NÂÂïE&ÏàL.®¼gå(“¢lÂ7S0)ú¦-C£Aγ´ÉXQz¡]¸Œe­WTšrä ‘„¼ó€ ÓEgÜÌE,ϲ¡uQ6£Þ×¢hu$ˆW|æ6  ál` †Aº2ˆ2È*6ÖÄ'êÌX¢M(Þb…H’=°ßÏrÒ¤…²×Mgo[ â•0‰3r€s-½ ¥, ŠŽË(fJ¤Evâm9R®ºc6€Ø†ÂÀò»iS Öèûyöƒû¦1ˆ‹¬mú·ø"Ée¼b:Ön±Ê*Æ ú7ô²à±¹‰1³–,é*Ó ç„õ´VžRDèøèøýY«(‹(Fz?®IÌɆ±+Þg¨)š1…£þîQ° dPÃäÆQ>û$͇۽i”ÌËUì¬k²Þ+÷…90ŒëYâ‰æ§—ަžÒKœë+"ˆ^¼9Nô«¡®nL¢:£W2±•~­ÛåýbM (Žù™ÍP ¥m ¾_Ì¡Å\ä+lÔbœ³ Ó=]óå­Í"8’Üp>îãëSV–g¦A€ Ž#uwÒÁ“c˜õfF#y¨;Tº§À+¼,¨&@Ð-!¤¶Aàƒ ²eføÎpEÜÓ4³…KnzÓ.“úITÀe$¤Ûõõ(ÖË@BäO!ø °¾Æ¥ÕÖU¡y€QŸtt UÓªÝK¤*ÄÒ„Çh]ÂÆóG%‚7äÏIs21Ä%¯ÆJÕ\TÞ¸±ç€á‹ Mω i "/€&€ÿ™šºÄ ÀúOK¹té½U€‚eŠì4cxKF½ Yu¡’X £‹^Ò ÆÙ.Žs•ØhÈàaÞçt*kR« wœù4V¾£áŽO² ãÕÞ”RË= -—5ç3ƒóƒ®~ˆ‡»É`Nùß&ß&Ñx¸¹ûkÈ Ù}*¸î¦œ!Sç_d­=ðD<ÎÊ_c "K bgœúÅJñ)“ù]§HX*¤×“Í*¾UìY©}¦ˆz§'7ÌF²Û3ïŠÙ‡ïiÕ©o;Á…EF+q\{-'îILŸ·Y€T• õož¸FbÄDÖ-Aîa.‹PZÄ)™ð‰Êz4clòªK“:Ѓ« @(ۤʥ“ ·ËÉȸ3Þ>›b‹±,Ò¸¸ál§ÑÆœŒ¸s‡%äŸI–ò¿¼“È«õ–ñõ¯:5S$¥‰ÕÁ‰å‰(›Úܬ³mÉYà‹)“$ˆç?ñˆ8Jh:’˜I6;e®ªˆB° ¸q<§ ;&Ÿ©`¼Òç:Ø Â"ˆK$Š`¦ãøÁÂõ´¸Û¸8T Áú·(+Ê¥:@·Ãä¦ ÷9¢Ø(¡bBd)ÃÔ8±1"¤éê‡ëFS)sÛ¶TB8±‹#1¨µí®:(/Hà3‰V¦àë3Š ù>øÉ3AEQ,©B]5äD±K§šDPë)€$2‘áÀ„05Ș¾[_½“‰89×€Ì9Ó7ˆKˆKäÄ@›ëM=d ÁÑ9=Jä¾›³dW‹ Ö½: ¤ ¡Ð° Ð3Ô7Ɉ¸|Œ,;‡Ó+™Ú§™8›;’¹{ 4 ö<¼iÀÃnÙ¥‘äZ,»‚–vÊTG”^zÒ’X“µÁyX¤ ™Æpòø›ÿ‹©ê$j9­Œ{%ÛÌžŽ¿ñ¨œG(â4Jœ «ˆºÑ"32aYI“Ï&6 ¬[€  {Zt˜&* Ìf,¤|L5ô*ª´¿²= To°ÂœÈ‚Éx…ŠB1/ ä¡zÌ7Ü}<¥¨£\BbÇ!×@Л&µ³n:³U©ÒñFÒ¬+s¤«»xÐB(’jm>è„‘Ä’6¤Ž¥Ç ˜ ˆ¦ œŒ“Sˆ°—´¢>T ŸZ\#+’Ý *nFÉs âÙK“*+—œ½LéäHI€:Ä )<eŠä"‹È :œT%8)®›,¿:sAÄÂÅ—1L éd½ä°©™4ä@\Ø/@;H(}«;w)rÔ­QâZ‚·,d%CØ€Ë8bÅ9U¤Ỉ+`µƒ3*z8ˆ‰ÚîL”ÅQTŠ8}ÍXÁ.\ľrǤlÆ{±“ûvˆ æ="ö& †ª$G9 ÈÆ»¹Àãu‰+ºV&Ô^žë¹$‰E57N´’ ¡ ¶p…¨-4ÄŽ$ +u"& &¯ "ÍRB‰|ã¸B"À‹CsR"z;3ˆ(¡¾J!sµ$ÓC4»7:š«ÉVÊóÞ%Eu®pë í[€JX%) Òœ?Ôa×Wœ,½™H}6(8Ñ,Å‹é<Ò R?à±Lew7¨Û5Åb*´•UT @’¯&ûŰ ’ŽXº5˜¼êßÑã:d¢¤i<±<ÒJ@Óx~tÊ€*ËDàÕuK으OªÇ*¹ˆñbZ"O¯ §%]KÓ’?%\â«t¼’ÍI ¼Ý¤D~/ôºD-52*%]ȼ/´ÁÃͯÂÅWOÊ÷ÓSÐ]L¤:@¾µ¦º²#‹]Æ=T¡+Ü(q÷È›,-Ë\FhºBúÚx÷³ ¢…ÛeW2»EÎ3Ð@lðˆ$‰’5}f1"¤ÍùYAÓ{.ƒ?Z”a¥ƒaÍDЇÓy5K‚RÄÉ׃ê=œNPrIkøÛ4±´¨ïXSLˆIe”Ľ¸©V•vÑ↲ò&šrnAxLáÏóZ=2«+Úܯ QÝË”Å-ÕÑšÆú1WZ•ØÒÁ#ëÏ\SY¤ªE¥Ï»ˆ4Éj ÛlóÚ%Ø+³=*`»5uÓ«æ_SÌÅéf–%Ô‡óÔ¬ÔHJ4 R{Gýð+uÎD§¼úC7ÁÂO…ŽÜÝAŒ¥(h¬Ø¤­ŠP"Û8•h&%è[mºy³Ë퉰†¶ 4õ±9 ¢Æ¤q€CB„¥U€À»=|ÎÔ7)ËÍJiß´qvGÝ©'¡YTÄ ²‘šE0—´ÔÁõÏ8¦0Zî$m% ÷âsÐbH‹(çD ª­ù9'@ƒ,„ÍQü t-#UÜÉb2ÙÀ\µÊÕeƒÐ!`YÒ핬–3’û1jI)b­h0*±²<Ä ©bWÔÅ4ã¥ÀÑzQâzJÞ8Ä3}*ð–Ï;Ç]S<#Ü\­÷ŸÅàCœ4 únYN*·Åª¬ Ëõ|ˆLóÔ»N1Ò&Š*B-­ŒãTÀ¶:3ËAW 9HÊÝb³½ÛŒÝÛ;龪Ma:TD6ÂR:¢<ÔC‡]~ 9&´Ô( ÍšŽW@ŒdXtž´¼cÚ—Ö}U[׳JgÙtKHÓé%T^ÌèÞ2Õ1 Ô‹ìyQÁsOá—<Î<,MÁSX!*â1Ø“¸ucÓÊ–Ô°¾Ñj<Èà—稄̲VÐ~U+ÕsÖZΖóD…Âܱ¥½øÓÅ(ºX²º¦QËÉ0áä·ŒŠˆ€‡dQs‚Y6*=±Eš¡AÛ®áy¦$þèÖÑ¢¤×Z¥­¸˜ÞB‡(j¤j†¶¢L‰?‡¦áQx±(òуþˆsŸ:yÅk­~Œµ}N@©ƒÁЊÔ;šÛ}PNošD.CöošŒæÁ,éb©›Þ7¢Ë]$ÝRÄAŠwÑÒZD `Eúä|E>ÑâXƒ02Î!ÝÀô`Öýhã–¼ÀZÔOv~Ì'ˆµÂ­q×`=HÂnÕ¼hÑIé9[Nb¤ÝK.L]j{‰.Iß²îì¹Þ €‡aÙŒZÔdi í~*e¨Š$@¬ßH‰âk\ãÀt:0‘qчŽ[`íTV"Lu¢Z×ß?lŸ_î 8,/×%ˆ9qZ“ʰ`éê–]¢&k3˶#ËžÖc•”ìï;ñ%ЦP>‘7Ôƒ°éÙOµÏQÞ ÀÀ£%Êü@Â[¿š¶»èÓž€:8ñ—;^ÏÅ5/Dº†é¢î^Ä dÆJZâãL-ðÙ::8°læq%[“^kpÄjCž84OüC./ÇA~·îñ°œ¨Õ~?²½^pmÎËvM‘ÅuF(×$øä¡*É—6‡°Æ¤¾#PVm%¾œ@‘©ñ% ±º€cù•‘ýu- ­™P¾ñ ÛùŽblï¡€ÇWBì¿ãñçÞÎb§”g•²SÚTHCAATš¶ %¤ TªwhsNuÜ茗ê–oør¤ËÔ¿?ShØ÷Ò2öD5ê:Ñ®|§Mù»zCvw$M®ÜÏŠÕ[]©·-šª¦võ5OïtïÐGMkU J3Õ[–<$Ç9›/ *×øé@¡‰Û³KË‘gKÆZ%z“Õn`Ñ&ê8ûËúìk­Ìw-ÞvhÜÎËÛ¾e ›50ŽÃ§‘æò÷}u¯Lÿ‚A@°p%ù ~Ãa F‚Ä@0(ŽAc¹b-†¿c€7ô¦I “Éáñ8$b1)š?¦P(|Z_ šAgrøµ% ’ÃáoÉêðÊ 1 £Wd€4qó+–E*É„:E3D«38”bu<–Q¦r˜4JmPŸÄ$ë\ÚAÅ&Ó9UVóFá7HVBw2“D¢Öù4!ôÐMe˜ EfÖÃF¤Ti[`öZè%f­ †LóÓ;k÷yŒgª@ ·ƒ¸â¥“:7Y‰g³€>sÿDÿÄR"q Œ*gÕ­ê%±­L‡s&ÀȤ¹7C‘L©€bR Íǽ&ÛK6@x•HŸ¤OÚ²‰*0Š4Aí£ 3öô­nSŠÀÂL ”:¨²²Ä/h²‰1ŠŠ3ÈÂà6€*Ðë!Ïø™±ˆ3†õ¡ ´B…CJr)F¢ÒŸ¸n¬vƒ0“ª2€³Ÿ Û€N:–‡ª)c0¢‘rþ¶J§ü*î!ÌjFÕ!³ µ!‰lŒ?ÈÒÉ4+4¬¯€$à›Mì5ŸªË´ÍËŽ#–“¼Ž­¬‹4N<ªë²+4‚œÖB)ú»H§ šM((Ï€+¸jë4·P.›OMIc^"‹ ’³1Âï±çåÌTõ$$ÌB8E25 CU'ü®ÀXt3¦®¼³Z Á£H³vü¹GOV8UR+ñB ‰šÌŠ,‹ºŽˆ¾àçBŸí<™gŽbvÄX3û ]’ú)×±ø²N³iüýج ÊÉI.$ðÎkÆÁº°å6çNñøÓ´ñàí"’bü篷n3/>6ÿk:¯s·Ae„WbÂò»-ª’' ‘"tçhVh&ÐK¤†:K`~%5ëçÇÔ‡;fí¨Ðp ÐseZexûã™ÌŽLõk¡X´}°ŸÈ³%fV»{‘‡RÈTؤK2³£ D™?"Ú-]ì¶³%°+Õz‚I¶…‰êh’̓dn,b`ˆrŒŒi IïÏÅw WIž;Œe2êAÏžñKÔ?w~(ç0t“¥ÔÈ‚ÌVš úÚ(ÆK—åR=Y~騿„D¾¯°>×ð罊-NéÍ<áÚøù…ùÒ¹†lŸ<.¼ˆCh&á˜áRµd~¨ÌBÈÏEÓ‡¿f0¾–™± ["žÞ¨~¯}~>3Â`ÀûkEi÷³ƒZæ‰Ùd[gu—¬†4ôëãÄ1óÀ% ÿ‡ä:æ,“:õ¡Ý‘„lŒ­T¸ßrPîm17Æö‰ûñg®¥ïRvéŠãEƒõü xŒåV)vcP=}“ó‚Ic2Ãñm¥—º”¢RÆ!P ŠÃþúLB*L±¹X¦@áÌI¶88JyÒÃggÍC§ä’ŠrPvQXó%^D šš]Ä(Ï/…fgHB WòXÇöí‰3æxmП.£NÀ“¬|{e¬ßÁèúäˆá‡ äŽ?Ö®ŠLòK®Ébšun‚W;cM/tÉÒÈ¥Êr)"ÉäFÇñ%عŕ‹ÁI´¤o`¤‰)œˆâÉ‘\xÑõb’÷Êë 9Í€›4upA‘Èûs¥tÏ8çJ~ tY)¥8²:Ä“ ™d„ÑÙx$Uù™ÎÀ ‘$ÄÄY"œ4ˆ]§D±fJ="Ï6Ÿ2­YÂ7zIi«9‚—ÔùJB ™™5wBK»\RWÆÂRêR‡ Á©¯äŠ-#E‰x$™l¦gL5óxÓ–2pÀ™º#‡…äʼn™Gê+VÁ&Qñþ¢çXûA*ð©B©"ÊòD0³è‡Nô T`ÜßiñÅñ+V’˜ý”ÔqOVÁŒ@Lcú¹=ˆÈ?á}IƒŽü§'2²Sœë˜Ä1'ÑZW`¤„ü-h¹Ê7g†¨ÐñW4ÈLSN´ŠykmÍ–ÂòÌž ÅKŠgNÌX:,µV„Ùôr2̧¬‚ _,”>ýHaìr¤ÙZÕº?ëðû;P‚»ZG‡U£ÜŒFÀ–c(””’’nŽ>ÖØŸà€ü?sz4R³Ê„”ôæQП-fj°èÛņ'MkHjïUžäŸ]ª`JBÎZË­G&h,{^ë¬à• qDЇ_HÕxg¼Aœí­ÒIÓ®xf™Ú˜p µZÐ` ìÞuŽv™*.ÉÁFQHõbÛ&œõ׺ß\FùÅÒj@•%é—dÉŠªt=Z¡Ø?cÓt.ÀŽ.Y--b¿Ìrôo5‡/ý´$ÄÁ«‘\Õ?Éån•à=‹pÙ4›w:i°R­¦£ G§Þ•Íé6pf‚^JË…st='Ö²ÇÅ·€Û9ÆIFÒë{D1}z£Y˜Ø“²ú uù“NÍáD’Ä3ŒžEÓ2B•!”_)ÚÂŽ”&TõP/­d¥§wòXüQq2›øïk^Jô+äBj©"ÊÅgÚ¨ªOÔZ·Žää!¿±ñàô{.þV|ü Ù½1ñ„kâ oéyZŒ•>[³tã8vE²T\òS«!œpœ’Ã<ï1JVufĹfÁóûX/ ±¡xø”´iû,ÕäòåêRR†7¬ð«~Úò$myß1®¦\œYf:{üÙãý.ŠŒ z†nF`±Ô ÉžÙÊ•ó{ ŠŒÎo„zö×]Ýutþ“·–¢رFÕF]S¸Òí‰^­¯ÂÔrºíkÀ)ßzæÝõTx÷BFЉŠÉµÛ!1 «VºÀ~¹Š¡¡Æ’j ZÑwƒÑñÞ6H×´Rí’ ìüœ#F¥°)Ž‚“+ê4,˜ÍŠ@.E$Õc–œTèT;ÑW^çNi8ÇO€5-Ó:œç!z±-q¡Å³¯&èDàÚ§*ýXQßJ×оu·ºÄQmä‡`l»hõ?nÁ¡~ç~¦ KmZÙ¶^j±Íj_â4Iô‘ôw†ö4 |ú¬”¶ÍÒŸd®^h¢i'X­cN(ÌÖ¾(Ô©fp¤HÔih(øN+ªû+¬’‡Ö£j¨&ÂÌz$¤+¤V«ÆçÌæT¦®á+Xu l»Íš"LA!ç#öI8I(F\ñ ·äŸêF®:­²×h|ÓÀI„%²¶Ë¦çë˜õeú›Là:oøà-φ4N6‚"pâí¦AixêâóAõJ äÏ6M8$HDêÂÅ"̰™¢×ëlaïFµ¢fÙ%D]«tQc†I.R*pôí ćdšG âJIJ ÜJëî”8Î_ LfÂEïrVêø60 °©nꊇÔôh(dB”®M†½FbØjTP'ïêÙìðùŒrÆÍ„Ʋ6I\»/DÓ0Êz$ĵ§ÆÍÍr¡íJ˜ðªøà‚8väÜ'X¬ä˜?jœ~ÉdýEôû„Ž<Î æðŽ í¬¦¹,غŬ¬‹$ fˆ„†î¶­ÖK«œ½Ñ¦JE¬ A¦ªq¸èPø ŶWÎ Öƒ$ JòŸlºÆ Æ|'dµª¢2RzOPZ扺ãï0Ð"0Ùæ= `Qm‚Æ <ÒÚñŒ'Fo,Ä.Û*0Vä$®Ji&ƒ´hc× «l¼áþŸÂ `IDø"4¢ «PJײ”uGƒ†B@¬8Yâ4¿’ÔKN¶ « J%îháQD"– ¬ë½É áQ$†)àj Ë‚’‰¼¼m:žKr!ÈP(²3Ç*Õ‰‚ÂpÄŸo¤NCA#øžhxáJædñPcß)34|‚,Ŷ;Jñ+‚"E¹$¡)— xÛ±zµq³¤$°N;%IÐfÀÇÍìM¼èr 娜È&Ææ1Lµ&f÷*¬ÈΊÀ/KíÂÆíM¶É® $ÂÈ7B n'¯æµenÄ `ÊÖ-ÌäbvËæ¶^ÔÈ&‚‰n¦&l ¸†0]>F˜#K‚Àf§@2º‹Å@Fû'ë캃:ì¥2#+3Z4Ô¬*zlSH ü9Äþ3€4&À$™5$ I/¤­cªªÓ<†'/Q,‹ÑI,2Þvfc`›Ä$¢K>%.+-óí+„]Ã[r˜jZÙG¤º‘Ù K“6jé:Šr Ð„¤’iJª<“?”°'Í–kø2BE/ºèRHòÄû+ZLQnÝ&¦Ž2]¨@Ò)+ &ÎÑ­ÀÓ»̪ï(šëã‘7n²áå Aö,”HÄ#cøàM_9Ʋ®×QŒ Òìtbf&ÀÍm ÎR—?©3Ï; 7ÛR ÊcI«CÓ8«.¬î….b|ƒ ÁCªw)<´¯ÊÑCz¤Pf+&Ç ¤øúE@Æ´éJô$|2B,³6'gupP$둦¢‹®"2ÐB²s«^²–Ús¦qYd$ƒ°:µ4ý@H¸² ôˆr*ÑhYN*/F¤Iœä³WpV&ѤW8B“]ÑYiM96ÓK±[oâ,Ùì †^¨ \l­‡/u´ùK(# Ü4³4uAbk[oìûJu޶ϳµzôs¨uŒ«°2È:]p¿!D«\”&‰99LÏÉÒ¹'N€bol˜±Õ@V’D“Tƒã&ÖѬÌÓ/ÎÀªûw¡ø^Œ µqhö}!ƒãœÀnlK¨Vf+ÜÑ¯Ø “šRM,((ØPt(Ç;©FŒkUÉ?"7¬š„W=–l¯*ò:t¶íf´É;°^]ªÜ˜2f^–¡~]uªö…¯ë'hÅbŒÇ‚c´“¯×¥D)Úsîþì-z$ ¾‹Z¾%ÔבI§ öAy÷Cs'4(A*äS4ÌrC+)zqî—LfÃO4èXZÐd!‰yu·Ôuû6ÔdðúèJî£Ã$k ]‘ˆ‡•X3;²ŸkO[8¢E~üÃDØÛ+ØÞ;Nï~ˆ ísÒÌ™ËF¡úw‚h:wƒ=‚'E‚4Ó«ZçB8:ô)viÍÁþjîÀ¶òì„Êä#e[Ë3²j!ÊJOã&#d™6Ùq^£PÊøh³âÿw ª–¶£{—‡qF Ëâ<+Üt„%mª‡¶Á\~ú'vbåK4!Úg“8«9<ÏeàmP0Öžm'¸?ÿ¬——£úã¶:¿=):”¯«æ ¸þƒ¡—ü, >À‘[þ Eã7ìn'EaÐ NI%„Æß±0L­õ-‡ÂdRWøi |Íâ I“òy9‘AqˆôbQ‘BgÉÍ ˜Cc0¹Ìµõ Kä8¼ŠEIWèkT¯‚!ó˜ô>E¤Æ·ôv 4H§4›LFO Qbñ;ˆÃDê–ÚÝpÇbñÚ~7 ”J1@ ŽZ7ŒNa4 £ú¢ÿÇ€+Y¬”ƒ#™ÒÓ#ÏèœçGF†Äö;T#7|à{ÛA‰È³Ü'6ÿ¬·oêz“ E´ùöF}·†C \Ú*¶ö1ÛŒ¬Éÿ™½@¢r„G#s…ü½ŠOn¡ÒªË ”4HZ’Á.*ºPb¨ø¡ Kºó¸Ìáú¤¹ˆk¢ $Nº@ã¿­S(:© V:‰ãÇ 4Î˲û=ŽZxŸ Ú ¥±ðâ ÄO“šõD-+.£P<¬ƒ&ÉÇЪ';"ó%8 ŸÒ£î4ñz<»)J”!ð+¼Ñk²™?˜)?ÑkcK@Ê–Æj µ9½±v‰®ÇÅ+̱|ý:M"HóMà~×2 B<¼Ì »9ÉQ¨]ë ÔJÜž%IZPªChlØ£¡ó}?¦• .ɪˆzÏ,Ï€ 9B(“¾®4ôü°Ã ¢âÄó’e»+z/XÄ1Üðà6ˆ\äÙ$Ñ-DÈÂl[èòQeºmåSrÄI¨èȈ%€F§õØ@p ×FËåXº¦‘ÛÏE¨œ.ž!0”:ŠÞ“Èß# ;RØ]Àj‹º7ƒ ¯iÈ H©¨¼^Ý_6Aý½3¢4Ü(äÇ24Ô—WÏExLó€ª#Ì›<6h‹[ËÉ£3[¹³"œè b~4oD~»%Ê7W!iX–À©ëèÆHé&Ylؘ""‡æI–«Sݸî8j'ë…¢êJþ¿@2‹6"zFhSÑ[N¶D ÔˆÉÙ [ãà&þñWdÌïWAúÏë@ _cãwŒAx\‡ó£qg¨Þ ‹^ú=‹7Ì1‹Lh'Äõ¬|Q¥×ÑýÖͱïÌ!+³ÌßX4Õ D˜«|cYIþ{ù`_š‘!èô˹BÔ¥¬”,èÃ| .ÝBãLrOZðˆªŒÀ~A'ÛäÔ¨}¡•41¦ì=y÷ Ý—R‹·Ôºb ð­Í)g*Ž5œ ?Ø1¥!-!È©""ÅÍdƒýý3bZ¤ÇãêOfM[¿²ÒÔvdQl“'\ãR»R‡ý•8BìDÞè@ ¼@ðÚÈ4îÔõÃå8¦ÛªmE çh§Z2½k¨™Ö>“ð2/3/¡]Nï[J¯EøÂU–Ä Éú'…Ú‘wNMÌ…N…Q„&fVQx…%ë•ó H»Š®Áµ„Òi]º¹ Š­78óFšÈ4 žeŽ£ ‹¥mR%C§¸z¯¢Ð8é ‘2Î=eƒbÊ|ˆ ÌÈkËè0!é,eqHP\¢$6j£‘ôˆ¦È‘‚¨|‰”reFfIÌT@­ã$%(åò¯¨°¬dˆ$¨¾8©iH3Jë®=ÄÚû »p‡¼‡¿b 3â’I!  ‘’XÄÜá—sBbBgŠ¦Ø”AsŽ5bLu6Ù©§Šé±yº–âÚ;ISM¬¨‡âx+¤ñ¥>DA š/aóIËvÚ\Kèý$Oj%€Eƒ&bŽˆqFŠ œ »‚5ˆJdàJ€P/LŒ4÷“K—1¤QãêžÔIÀÍ Ó·÷ ¼fNéöd.‚'ŠKf%©Ø}LÒ"õˆÙƒ"r˜œÔúBYÉ ™O$Á̺ÞÜᲆ±×Ŷ 0“¡£ ê'%ä‹Y3p~DV;<“Ñ`ÍA,óºBS|7ì‘ϬªD5,M¼$EØáÖˆÔÑæs„zš9ÉÔä^Ù4kˆí{¶dÅ™bÑœÇ?Bdrhy„ÉÃÕŽ³Íô®z ©×LgD®‹„.Å®0c"Ò!ŠM›óœ Mʬ?ØCœ4zT'µÞÈ!¾¾š#!v Ò™I¾cþwP(ƒåÀZ—IÂ~¬ÉkÀIð”³û·6aª‚v¬û±*ÁÍq+Û¬ÝÕòxK­ª›?ÂìM Ll$‹‡£¸\¦ÝÊm„O&¤è?Õµc{Ç€}¤Z ß4kOv>µMGÉ‘¬ï´ª%:šA9”ج„M…|ë£qy -ŒNkk†î}¹#xÑs¸B+þgԦ摼iLK„9N´Cš¾¨Ä•ï—iXæ±vZÍ0†•tkô”¹‘üùÒ‰ ØÑ’dª¸Ìþeßë•ÀˆCqöŔԡ2¬]ɆíéŒÑeufBÔ:mpIi2§JùÎ>j@dÜ%1ïM"È«§&Ý”aÕ6*Þf§>19lõÎêm8™r)$eW~â˜HýM®%aNI—2¶ŠYOc%£T;E̺ï¯mÙÙH»*\’[°W-—@MÁL‚éŒ4¦#À3‡AE‰*céYÛr®ñaõvè=io¬ÖA¹†2åUŠ`Còx¢Å*mÿs(ˆÔí­!§V»€D>Ý >Šñ_µä$³”–”¼ Ég–#ÒÆBÚFÖ©§šñÙù¼%M£=|½•&Êó#dæ½  pSJjOBǯ• ®X­ç‹×ëj Ëø~ITJǘ(®Ýd:ì‹h¯&#tÆöŽÓšdr?ÙïNžmýÖÉJÃä L\ªBb}‰Ñ·R©•‚ýê?o\èýeá˜Oá¤7_eXIð âeÈžmé5ÊÇÒÒK¥;>#~›Ô¨‚ Yˆ²Ó’-ûIµËty46RôÒw¨ù_Zëšv2£«–Ù­q¸þ%7e{8ªï«gãÛ£RH†¿ãžöx±5W¾ÈÊ™-aµ+¶Òo¹âÕÄžbsX9ÅL }ò³Ió'8ˆ#ß" ž"S °¤ ’º+Ù˜>as´®¨à%3ôhá®Û,¥òÀ5 *9+ý4ñƒ:±\<ËZškÃ$°™š éʳ1#(°¸»«D›°áÀ“ ²Š¡)Ð=; )>ÚšPù ÊV ÅH–ÀØBP‚–H’¹Éª– ß©ö(œ¼—ƒ?9D1¹;k>"ÑA£¼rå”Kã LÛ6»;ʳÃzµ±™ã”ÐÔ™×; ©7`!n€…«A.S – }ŒË ‹Ÿ•« ¹&0 4C”Ä8é;kQ;Êàš@‚ª?8•ŽW7/ à³ô&Ѫ²±w”¡Œ 2ÂLBÁc±=ÀRé;òy Ñ•#â…,Xؽ4©”3ˆ}/9Çœ°ˆ·x².øÌ³BDf¸Â !+Š¢M·Ë§¹¸›‹9çˆ»Ê ŒÊ˵L92“­!Zú" u0!ã©dv:Óûªˆš3ÒÖA“¯€È:©*&¢}!{í¨“.»‚ ŒÌf/ZÂäoAll.xó&É‘ ºl°i"«àªsç¶Ys™” €)`œÂ²"J||eŒ3n¨”4µˆÃ?Ry° ˆ¥zŒD°ƒ–6‚ 2æ¨ì0>¢¼Q"° —®ìu®Ì)EûïR«ðšÚ2‰ ‡¶ëö‡ðÁ¥1+šTfR¯0¨Ò›p›œ$u1‹*ˆY‹$óD!\:t…4ðù8 4(¸ÈHöÂN©9IJ‘¨Ä€È¢¤ a~Á˜–˜ƒb®’­Ór0´Â“k|œk]¶»ÃŒ{:/:¢þÈ„2[Ž>„–7Ë‘álªaÿD‚|HÈ’½1×Dó>Qˆ52K®™®YD´¼ »”´©l«xMÐÇL¬Ë\½ é V‰ºŒœWzA¤„ÍÌ$óÓ5š?=O¶cO8*lÈ<F’GH’³klŸC„»Ô‰-k$²£–¦ËLˆi‹)±ì‰¼Ë6H„)£(°¨Ñš‚(µÜ¡Z0››8I9M|>Ô ÜY¼?œ(ª$îÊ{b(pnPÚ¸<„íÚοìÍ$‰Z9¡à‹Á¢‰!¨Ø$1ï¥.ܪÍ1µð—ƒ½É9‚¦ØÃN‹}º¡š`µƒ ¬RÅCx³‰“ È FÚä€,Kx}¶‘=Èrü9rLª¶Üx4@ÒŽzPyeÀ‚Y±˜†º-$Düå9;”®táL{ð»Ca JÛ“½–[Ób‘»Û¦J㵢ܓ:V,»ÁqaÅ`¯›Ñš‘½JªÔESA ™"ªLÞl®’ñ2ä:°Á_9š$`=h~ $Ĩò [:ÁkÜ)ÃD@&Ë»ˆA[§t²>ÛS¹s•TgÒÛ $ã5µ¼R¯.Ýe§|Ôœž$Òœø-³cÕÄò.ε+í‘ÜmMåP¼@¡ÙZŠüð›SáŸÂE½¨ˆË0| Ñû™' ”±™d”IÅQtŽlJO%dÓüÜÕ£Z‰S%qô;ë.¥DÐQÈCØJa2ùÊ[‚¤4Ø5ÃÃ8P˜Cs"b4ÑÈ’ ‘®QØØ¨íÓ ’(JÒH+‡ýn;œêÄÓèѠѤðá 8‰åkB¸•»Ýgº@=åAŒOS”çK`ÃOâ|©²ä<õ8éŽlà %b.ã€Î›x·eÌ™€KšØÄŒ5K²¤%¡ÙÙ!šM©à|GsÒ«$«Ã0ª›-±*œÂÀ·’«·=9ÃË­YÄH®±N%DÊR«Í¤¦Fƒ•™ÌW²“ÚJÅÂVQ6@ÈXYÛm ÖUÔ»ÁF5®ÁhÓ˜Aiœ¢'‰Aªžœ|´Bò®š,uÂÁ5nŸªä>ÓÅ)dÆ*Ž-äå)¤FâTüÊY‡ÚÐëšåöÞ:x4XZ2(S8Ø(Æ?^/«a䎊ä[›jV8”%5Ö [U›du*} cNGRw\Ä”®Yú2¹QõIÔÅ'+DÜ.â‘߈=M–¡!DÇ]Úp§1"—ñ{бïÓõãˆÜ»]H×Q°Ñááäp ¦OFT˜Ó°­×Žy+©wÅB£@ÃTu¥XâÅ0–˜Exš¿6 ‘Œd8‰s•¹‰»JCx;I鎡IÌ0m­Ž}ÿVŽK¿Šw)|HFiZ÷ªC)îaÝ´)Á6.Ü/ÚM¿‘<@…~RÓ–ÔK´œjl̤¼­ý6°›Ô½!\YÍ(õΜ‰½dÇVò ¨‘`›Òr¬-Y> ªè´Yï³!@¡­ôº»¦ÜØR[Ã_}M`’\Š«ãÄëÊeã7Ú}¼J–Aë ÜíóåùbÓ$ l2æAÖ=“Ɖ@ÅMc]Í´iíÖ²ßf¾ k 1ŠáÂñlÁ ι¥Ñ¤Ä>ž´:©9ZK’V\ïK.=W-¥×¤ë@„Çà>N^|åGS° „1'Åk]à…æøI˜‹"‰\ãç­X5ˆ$WêÖÖ…u d¥I¢cSPa|Õ?³yÁ 0¨ßRÍ;.æ‹î}™ûçJ*³Ã6¡Ê=XÖ‡ê®Õ©<¯VNÞ…KJ!ݤկ«hN¦â§¾mìž6Íòº–=‡ãÔàËåc𑼻 ½Ã²sE:Õs€Aƒkadü]´í¯ qxkœ‹Õ\¸9²ÇÀ*9=DË’êb„¡©®Ì–;P­ßÖ:€ß!šR” ß¹ å3Žtk–ÌïUØŠñ,:píE‡ä_ ÖÍ®!”£’§s=™ “±-qß`Ñx…¹ÉÕ 8…æ`4=WkÓ©²Ùfzl’¾‡F,¬È3zÂÉ¢Ûõé ¦>)5XèÑ>£½ö2jî:®ÜõÒ ¹jy±KƒÍUÎÊ •¨–Àd14ÍBî_ß³h”Qòw6ô·‚• £Æ²I yÃìÞcØÞŒ€à(ÞѸ)Z#ó£ã6¿Rjò¶ÌÞ8§PÄ jTïQƒU¾n¿’Os‹ÉaáW×b.RÂ¬Õ }açýw¼‚›`» \'Á+Î$æä;St'E”ÞXôbÜꉭò˜}dö•å)™Ž[å!б½ã)ÌEJröw˜”Ï—lO&¹­{ÔÖuÐŽkn˜Cø9kI>.™¯4Aܣܬ°„v¥Ê'n’S-NC …YÒ*œL´Ò£¬«í½«a”îÑ4_k‰¹2¶„™¥LùuöÅ([ëæŽê¼¥/ tÔæ5MS6Ñ:)UŒ¾>œEµ™F4À)ÙR®#Û›TÅø ˜EVEó±ýFE9ˆó6ÑW3¤qCØÛ¯€Q· yïGÕÂí;OjÔ'ï<¼çU 䄦&Èɶ°„%3®ã¾Ö Èˆß¹M £+’µb®š —¹> ¯=áâ,yªÆ&Œ]¾ZŒ¸Ø/ ¶ùEîÈžgt³o#{ész6ò 2‚ç@ñü¦.‹”äh”kÓ–è¿ &^m#DðÁÊš&áïDN|!èìò=Õ€tì%ªÛRðæé<u÷"]27kPlÐ'69ñX|kp¸ã~¥s¢’¬Š€ š1…ïæ ˆôA_Pp $ „€_ÐøX ïE@ñwüf*zÇ` HŒFþ‘Cß’xl  ~Ëa²04ÆZý}Íe08Ü67#Ïb³©ôn2ÿ—Ãá´ í…•Dcrwä~‡<ŠÒ¢±+úTÚ®>+Òjû°æs8üÎcʨ3:\G„Ìär©TŽí•R(s0.s ¥¿í‘ø-Ž¡µBcöùmb‘Ô(tê¬j+}„Þaó¹4Ÿ£Þäu¨`Հ̎h ÚLàï¨nº‘Ðèu –{O|ñaº;o9GÂï¶\¨"gc¦Â÷™ø­BÛxHúÉœF?cÓdåZl,F‡×Ô£{{vn¿“Èãö¹¬lû½lwϲ ×*hz>¨%L›\¨AÊfË#,B è;¨{n¬¬*Æñ «ºþŸ°•2è\ ¡ëD7¥°“â(nFÜ£+’!ˆR© zç4odjª SFá8§ÊGÀ(Ì„é?ÌÓ¢[Y‹„˜‡¸.äj³ÅlÉþð¡rP )ˆä¨4r×: 6ä¾Y'! Ñé½f…øU×ÏìU–‘¤ïbgu¤7ÏŽÈŒ&èâR”J¼{ºª7#¨u÷€Âß8·‰ 9³>ý³;÷5¦µµ"UPþvl§Þc=° ¨SmE:•òñÑ bŒÜÒ,‚RA¥iƒøö3óÒ[R#j%LÇ|ÔÌš€SlYê¥âA+»eƒú6øHHb3&®–3n\•Š"cÝ@Óh\A`_ÄTǶR R¹þv®½*/RòŠ“È[ 8D´EÐ’ÌÅ]1˜Xœë%1Æ$š¦ ÅÐqŽ1 µ˜¦ª‚‰#ôõºµpyÏó‰g´oG•¤ôTBsO„…Á¶C`+÷€mlÂÇÀ™ ðø}+U‚B50ð!†ñBÆèÈ\ãfH¨~ÓzÅnâ@‘¬Bo&g¬ãØRB.Wq²7t¯à]Ánµî´¢b`"¿Y•%š›)ݨ¬ˆkå©UÂé ß3Êj±Ú“ÉÛ0Ì*ÒœµhÙsLkŒšÐh,ŒÛ°lþä’€léJÜVï=e Å9ÅfÍÏ;ßoWaª­’LÕTë)±}fù:âÆõKæåS‰g5\¡í»¦dfú~ÝGdv±Ëc`LUÙN¸fÕMâ³I ÎQ~Ë1 Ú&?³“6ó‘T t½}W÷0¥ €Òêy´÷Lk#d'½ÜSBc/T€euðîFvT”¨Í$8K0äXìÌYðöºÅ’7«é<ãyju°+T¥%fòÎÑäµîèUDAÝš íë'¬˜¾cµ7d7‚@ž?HmŠ6üM¯—É‚Mg1¦õ¨‹¨“؇®ƒì»ŠôÁGÛ²IØÜM^NI†6ë)Ll£ÙùµèN¸) LC}ZiÛÓá8¼7ÒÇRÌžcCÌѱÚ"‚ù Ä¿•"T\õ1¬Úu­¥dÞœ5 ­Ä{ˆ¡·©å¸µÅ¤4Qh”,•]Ø·Aä|ñdš®Ü>X-s”“û¹L‹ õÕÜòø½Œ+¼VHí²øÞ6X4úSfà—¤Lᆕ¶»ñö¿ôIÕ|²!;­öÙžçEðaZõ+ ¦ÖÛíXù®4sö¶K•BÅ•îEõjÅ+>7‘]®¬šwêŠySUŒNô›/nfv1­Æ=­œ¯Hê…£|¦¸ÖljaF^B|¶Fâ̧ØáF¿Î,îL>´>ÿ‹¬aN®p„L„kb>ŸO,*" èâè¥"bÌ&ÔýEò{ð&ƒPhæôÚF­ð ›ÉÔ¤ áÎ*r«:ÃŒ¢÷ïfòm<øM¶ÿÇVÍÄJÏ€ÎëZ,iT#jÄç *BC&ˆ± äZZCTYpèCÿʼ~車do°~ål¬ì^ú’L¤a†œ–.æci²îô"¯¤á°Àÿšÿ…²Øé`jO;  ‹4uDÊ&­ðê¬8ÁîTY‚³ åæ6H6ê ʵ¥6¯ã$&)Ž ‘¯TˆPèlišyP¢!ì4Æbh/ÊoçPÿnäé«Zñ `Ä)ú°ä³èÖ¼îMHnñÌÜÃæ)ÔðâbË4d.<Ñ1€&e Á"²&qHƬi ðW‡Î’k„JÇ Kɘ‰É³ï°Úf¦."0tÌŠ‘槃ؙl´!)ýbƺbí°ö!ìAQ˜ ãF{¯V}ìLæôŸL‘ Âðø1€®þ¹±tÐådI¨’KžñÉ"â +´Ý¢Å1p\Ï@ÊJD 8†jÚ°€\@F±\ K€ªÑÆÜ)Ô­dŽªè¨cñ p’Ä&o©ñ"1„sÇ4¸‡ŠÈÅ®Á€sº~E0±¨6Í0(êÍr„F6”€Ë‘æI¼Hér¼g€¢O*^Ȇ ñö.b»²#ã&Hí`g)í$èȴЦûCŠî¦Nµ„å%jŒ¥HHÚÎ>!¨nûÎþ(e´Bƒ­¸²C&N«­2â÷/¾¶+Ø£²¬²¨ …"ΩL¾KLj¬É ©±†žb?,„ØìÇîBFB`„Ee ÇîL†Žù’> i¢Rè,‘¼¨˜þ‚g!B'¦’Õ2(ã]'è˜jR8’NÊöB{¬ð¢ÃY0BÀdnð'âz`r$éô¯°33!ÿ*ì˜J²ÞaöÚ îâ K9aø) #>S™)sƒl ‰Êê"q=«äG4SrØoQt⬘zKð±jg,«Ú(írnt1Mf¼Y*I#ÏN¸E6…K„9co2ƒ²¥r²ÎPŸsÈÃpz·ÒÂÞçÜ×&@‰Æ¾îÀ³çÈÔó”po²2Ë,+3\îI$n!1"jºÚ¾xóF:p<{§aW3´«¥q>¬kƒŽ)‹G,”^Ô-é:FnîÒôPŸ*!eìî+W˜«nïjÄHJoZØ­|e6nÇ®U#CFÝèì„T).·•Å“56'Õ?¬@,tœø¾´,8úâ2òPž–“6x 15ƒ™_: s:<ßÙñäùÉU™•‘Ša6ŸÈž¢?£¹XŒZö^ý …ŠÎ4ô,whÔé©pŸ]Æ‘­ÿÅÄ„ô²ãF‘º.{ÇQGNþqµ'“0—Cla€0q5C™†JVí¹p¡öç#¿±çº‘¤Ad³w|ʤ8ªm9vÚ,X;vâjW#UÃÛrJZý]cü0£'Ÿ6Å_µÐ9Ú‡µ òKl4‹‘¿N÷€Í•ïó%.T™;j—§ì%Q¡†™ÏEÊ-³â¿/1Ç®XD38Æ»iW«ƒµÛSœCÑîllYŽ\…k±ÔT—ÃÈu]ËT‹Dxùµ³yK…¡²¢7©B€"NoE%»Ù„,¢–‹#RÝks_ªºøÃ¬ò}Š£HmÈŽÿˆ ¦_´Bèæ6©i\ÃBV 'ƦHJÄa ìÚòà Ÿ:M"œeg“®DN”Y™o˜k°#{¦­ßŽÛŸÐbE¯b®æÝ½ ª0Í”4"´Sj Õ@SOðÿÒØŽÄ/‚bŸº;Ô•Ñ$%³8KÄ­~ŠÑM© wœsM)£.ã7PJÉ;É„sñÄ MYÆZ …$­­wòÕÏ|£ª˜µ—ðlfc̘dcØ5D`ûN\-TÜ[û™ýÍO&ßí üûñuž¢+ììíñÏTð"´å6ë㯸ZÁ5Ç©›‚BüÞi¬À™IÞ%S€Ýò–b‘YÍOýÓâ±S¿1ð–`.šâNÆpž+ öÊ|¦ÊеX"7G˼}¶Yý«_ÉýÏúücœ"-*JÍp¦Zƒ~Õ|Ÿeâ?à(0ÿBáÀ>‚âè´^‡Å`Xóê@‘?$‘˜XQ~Êáhd­û‹É’ $< }N&Ó‰”ZŸ@§©\&1G(±hm>4†E爴±6˜>ë•àÁ/•Æ –Güâ9 šPÀ35q÷(Ç&z„¶x¶Øéйt.M ÀСõ€ BaL‡Åñ‘kDRqw§ÝqµL-æÃEî’»eFifÔÂmr©Å´sGμ±šBlg¾ßG Ç€àÙGôÿDË€f›W§GšC7Q¸®7­QâZ·ôâåpË Õgõe A7}Ø—žŽx4Þ4Íf8¼^ù˜moP˃ØÃ<Çú8|@­Úpš4p)ðA©Òþ7k‚`¹"ïÌ&bë& Ãj÷5 ²D=o#‹6q;¸ú:/CñÉ¢hè½H¤6®ÈZpò«:’ƒ1J’·@ n{´oÚÀŽ'J„Þ³È|pô¢; Àªlx­«¢ÀœK§Ú.›?(ä0œ4rCk4¨¿>‹RH¶.â›,ÏcjΩR;n¹Ôlë'‰·»Ã¢ÐÒ›&Ã"¾æƒÉÒ"Y8€3Í•¶©…¢âžè¹I$K4¨”„Á«zŸ6"‰µ{Kà4î&u[„-4ÙûDÈ(¤£?NÒ;2Hl ʪ4ÃBÖ#Örô„ÔŠª›¶ó°”¯ T³Ï  2µèåf6 LRB·ÉfÇs½„[‰*›. ¢{eÑWÐßC3ž.Zi"8¸:*ƒjàQ5,ʧ ÓܨWŠò(¸?ˆ[îaXEú®#†ÆWZ€t«½L2¬5y$#û{H`·ck‚äš. æ~Z*}>C«9c Y"÷b"ÍSâ’c·º&ÈKäŠ4oΘËxulºˆŽ{ K’ \6ºæ\• ÍÊ $Cê4k‚mQ/‡óü®CóPï¼õ>Ñ‘Åy ËÑ\Mr쑊qefõ A`_6ßC©[’úX¨ówG ÜS:\ÑÄ~Æ–,×ÉTåKU4b’½29Ä›8Dr·Ä!0+c·x|Vs§ÙË‚£¹¡YË´Ç!é¥Üè©9¾r韹©ôö.X[Ù¼$[$›O©‚×;Âqþ›>ȶÒÓgßø£Ì®ŸÝ`PZƒùè´òl’þD@È7²FI šRèÙJ“f³Z+R%¹¨Ç®lKƒôl©ø†#}ÐÁ:|ïùœ?ãÜñ YpŽ]Õ>¶ªf`$},"±æryÚY˜®" ZF1 ¬‚¢mZ| ­9ê»U€¥aLJlõ8;F.ÑÓ8p„„¶8(HëÍF 4ëªhÔ„A% †è“€ë ŠdPäMwf«2XuZ8t´áÏc 8„‘R&Ô“Ôaç7ÈÕ¦s¶Ó΋ÔÄqt˜îxßù¼>‰ôü€©H¨Õ `?-õQ´ªÞûJlÄpãDF¾äñ†“¬$®w6ÕPüTŒT‹J@M J7jƒð¨ºÄ¶ÌØ 8)*À‰E¥ HŸÄ¶€DxÀŸ•tØc\Jñ.B`háÈ~‹ í°¹ÊG‰¡:˜’ZGÅ,ãGÙµ~NÌtÜUÏ£ý\„%LLåzc]c•vÊZGP¨m(ÌjšZMG‘þûe? ªÄA å2j6ôLj2>izQ+9m‘E6›¡·!+¹î•(Jç<¿HOîxBïb”k'$Ìd@aJ@ ¤ÒBHbm=‹âšµß¤ó&¡É,U"$ËØåTv ¥®§OccEî ƒ¼™¦ÀdŠrS¯ôÃ<úÆNp¢&2• [óc2âA½'ü¾Z OÉôÝžzúüô€‹²ËÝiïEï¿Ó· ɾ“Á¥Y^iò–ŒL Ñ‘ÃòûÒÛ+–x}@•ITcŒ@ TZÔú¬?—t¦Tj&jAñX‰ô­5î=Pâ/,. ;!‘”}Á©ubToÞj°BV\-ù+ajÝAJׯA& CΨàKùK¢]p0DJ€W(à\"²0‘¿ŒÉ©"®€Š^‹ºÊdš‰#FAyôhÛs©PÈF<®(‰I!6Ö zEííL¬ŒæIawXè«\i]ˆ þÎÐ V}çj ±î»!û+IÕ¯Jηßl&ÀÛyÀR³ò%LÖJWq®5ô•á*Ñy¯ÚSžH«ÀE/K:*IÖÉ÷g„¡r±ÝÏ¥xî#J{,Öd $1t`µÀjË„bX§X—«;"È-ž¨ÿN‹ÒÊöžÚ¢¼ïHaµ!$ëÈ]CÕ╸êy “‡ìçkd‘º«Xká(}ùí¥ÉævͪveA’-{¬Äžg˜?*Ë#@¦Cþ™tTé’`gË €Ä£ºªÀ%‘4¥f++BMkÖíƒHÈÜQéÆÑ¢XåÈè«+]¨ºÎZÝÐÓ´±!+4ô)/už½ºÔæ „A”2MúD¥Ym£VÆ¥"?#í-­°¾*™ŠøÞú¡”îVËŸ/ÔZxD  »kƿȚ^ Žò#MÑw ž®Z ˜˜KT³²ô–Ç+ŽúŠA£ Þ97ΕažÅHL™ØÜV0ó…~{H}Z¥uækÙ)=coœ¿iØ… ½wÑ&È›øÁB»äuuâ`àÃñ 38³ÀPú@}‰ÀkÁQ*Ó¸3%@×»Ér-€}’ÚV•à„Ëæ$Ca¨²„¾aÏéÈÒ]—ݯ«b7÷ªª8Á˜=¨É¥3(‘‹ Âp}±p:‹ã^T³IFAD¤Ã¨{N‡ËÝœ¨Ï™É!&1Ù©[3+T+!Qa˜ãðŠzÈŒ3ØÝ¬˜®,iä#JE½aÖ‰!>(Ù)ÈÂay¿CòŸi#6R²Œö Á¯¢š‘ÂÕ¤›L®ÌO¹ã¹â´³O€;ߎó ›3Í€ ‘PŠx¹Òÿâ´¯(ˆŸ{ˆòá´I›*K¦³û~(«á¤ò¼©t°¬%99 JÂJýêš›<|W1úŸ¡³j ËM  9Óˆˆ¨•c®Ãý2¼5¸ +šî<8ºéaÄk,k ÙÈ €¶!iFyÖ.¹Â48°.! -’˜ ô€ ÆÅ³‘—gŸ‰/à 16¨°ë‚_‹“%›‰`tUÀá–Ðá§“ö.ƒò.!>¾Ñ-¸x‡Â,,ø2¹ÖDk/½ƒY$»Œé–Ÿr¿Âô Áþ¸a1ÂàÆŠü0€ ,${ÈñQ“iØÊbË÷%T³Ó( ‹’BbAw$ƒÇê† »®+Î"›cCê6”nœ9›²»“­˜ì.ÄaZt”d­±  ‹$B­Bë”Ü€¨¸ƒDˆ" íµx÷8 ±€d˽î1©œ¾©Õ3Ð…®sc>Â’ÇË[«ïC3\¿«©Ù!0[è Ç¢"¸É$¹;ljÌH‚]' >û¤H~ËŒ%l´2¹÷‹cíNJSI |D'ê Y·²»J;ñ‹ºð ³8­kÆ-ëv7(ˆ“é¤%ÌɾûÞ¤ô?@~'2k›,½ÁÈ¢ú5«F”’¨*})-¡Ü“6kâ®öü<¤{ÎÌ›QpΤiÀÉF‰þ•ÂÓÙ·Å-¾QÚ=ûH¬l‚ÊgÄÖ€!ÒH\æÄNKØ1¢V‹Ô[3aˆ3Õ¨t00³â6Ä9B€‰¤âÁD˜ú3XÀF”l§«QìoÈœrË‚O»c9}¸‡Ý9;ßÊ2C‰ž¼»ô·‰¸Pp†Í2¾ùÜœ$P;#IèÁ|s)úJ–¨„7ÂD¨¶ÂÑSõ”­ [Œ:Râ>~8Ûß @¬D9tÀ/ð¶"PëFä/Á‘«¬#¿Cö™ì–"ï ”c“hTœ¹:ìz²‘"¸a§—dò¨¡Ê®ÓÎÌñ¹l•! +OóⲚÿ€"q‰$w¦R†ÊŠ‹>ÄÈ ,,hïJ)F:«Øžì->ühM¸~° žÒܧ¶`Æ4ÇRSD Á<ñ­ëÝ©ÔþB_»Kõ’‚Ÿ° ÅG!^MR­3…‚Vµ©Wµ»+ÌPÛŸÈÒMÃu¥1'¢~=‹¦Ç۟Ѫӄ³i$+H”Å,=üµxÑ•ÂV¿tPCbµ-Ü;«SÌÌm&C¡1X\¬‘[ß²¼õðÚÙKÒÅ ÐÏ«>Ùx°GŠ©–CÊ:¬ÌÈœBDAúŸÖÐQkXëTd6˜D“É9ž¨ ÔQ ;½ ¨ÍƒÑùÉÚÒá ßÓµI‹5A¨µB•"Ó«Ì{¿¶éaÈD)|"Ùš‚¯ý# B9°„Ã2¢„bÎ ”óó%R5UpIr7ò‹,‹ Ö ‡¬‰Ê¥&(±‡Rm¸¹ª¤±GÍÁ6Óà}me ˆõ#² ~²;:@‘+DÄ%Pß<Ó1”KÝ Õ@ÚÝI—„™Ø«0  ±#åÕ Š#9ó,$ò%X¥×+»c3„Iåϵ¼Œ·;.ÌÛv“º¼ËE¶Ü<Ù¯ô­Zå±D;Áëà25O‡áÐÉÈ@»“%ü¿6ÊWP}U’ÌÜNÊe²ƒ[Ça\&«TYD±ÚëF¦ú|‘ ø©Ú% óLMléÁ­ªE‹TÑH} ´qU;•$X'â/88ÆÛ¥@ U5½à«{«T„Q„J9³Jƒ¶1!Ìš%38Ûbd´Œ¹Ó…·óäÊ;qᦲÐʈ³z?²`0œL¸ ÑŸ‰DÌÌ%E¶²ŸÕ\ëQdQX…½¼`4½{2Þ•ÄâЊ=úOÛâ=8‰2j5^DÒÓSO³Å^å.8"ìR´UJ@’.¨jCS/lZÜæ‡ëÝØi¢_Ç,Ñ€ŽôÑR¨U⥑µj<^1‰½É æN/$ƒ¬ú žW×Uaà%eÔ딪3õžüW1©Š}S²ÞŽ ÃÔ3¤Gœ;ßÛŠÝŦÐÛWUùÕíY±Z¤±cH®’o§ÁkBº‘S²UGLø^Ìôzx%&5¿ÑžÒ¤¹•Ñ”ºÎ¬xõ¤¬¥æm#F äô3!Cžµ+q-@ê߃/²Î0‡Òõº)Õ訶vjI[m@vW¥ÈÏÞwR¡þ¤BþdaKï©]¡”²ìa£ÄË÷=p‹3ÀÖý™QDŠz{AÂg¸÷Êr%CÛV[è˜ðz¥S¦Á¤Ó@úaLÞ«ßÙ8ße‘€;ÀIééúil븼ßÈÂfÕRF•ûâ@×½ûn3¦PXµŽ¢Am{2¹þ¥U†,-ÎYÃà!-Ô›¶èÈáà]1£Ì=.DQƬΨ¼¶¢ ÛÐËØÁóî=•!·æeúÁÆPI•1à†9M©kåôz$õàÀë‹@ÞtÄ×§åLj|i¼ù¤CìA©Im²™: HÚø Õ$ 5‹;„)ÚD©¦ý–óÇí¥Ëö¥hʽÜìÉ‹é¢P"ˆ½ÕÙš iÈjÓ-Ù§ÔàˆÛuß ÑwDaÅ|‚X "ìh÷Hì­Ù˜˜Æ(Åó~ªìÜgó˼þ\‹TF¬'汈yФyÆ´Ó@ ”M*"`¼ý´#b~\mòºÐ•âHLþ8I¾dŠìjÞÈÒOÝ”K!¾+»aT‡Ø†$@¸*ÆE9›ÜŒ’,¼RL$XY¶NJàÊ'F¶ÙªÉÙX¹f=­· ã-™NUúÞ¨ì»2+òçªÈUëXµY™î´ÛÎ1H6T»›îå6ùË0ÊÐó“ën©Uø¬B0Þ„Ñò­j(Ö¿)nKkŽwŸ8©»ÎS“é9þÂÀ²ý¨gµ±¢>zÓ÷Gú®^Gd*©‘À¹ †aiN‘˜\LêÆÍ—eŽˆ7{óaƒ {®lòþ¿hâµTš~ ßX!ÑߎýD´GhÒIžßâeä¡N€.Ýò»Á×ø…í¦O`d0¨t¤‰-’` Õz~5ø °ÊcÿªKïÆOsųī4gÊÂxÁ`'ÉDëã¿X7‘S³È>ù\*;‘¢4S[HEí4ˆ‹Ññžª?Po Ž–Íè[æû«ÔB =DFoÖz‡áúP…Òļ–i,"A>ÛtLòD-+u××»1Š‹6¿$DÃ1\i^N«;7¼e£âuãNGsä÷|mÆ5Þ±ÿa`p÷çúö­Q–¾('Ìð0 é m”¨¨ÅÓd6ÿ¸”H°ÆTybbwýä¥üVdH° ×5ñ–ÆI¯“8#.:¸€ð0ù‚ÂaOèd4 Da £î,ýŒE#@v5 ƒ¿!°7ütŠI¢ G̶U‚¾¦R¹$µòœHcR¸ÔY÷ •Ê0¨,’I ƒÉ¤’i460ý¡êTøÐ­$†Ñ!RHÜR± ¥QŸõ`,iíg©åàHLŽÅG¢CdÓ¸>Òø¼NèÔ’Ó\ŠR$PÈH ™>£V›zv©Ca·@$j>¦G°4HýNŒJåsé$‡ Hl–KuµBÅÔ¤ÚhŶiŸh¢3ë& ËdŸÐ›M¦mOÆ€oð>MòSÐSßµš&è aÓä’»NÑû]¡çŸô*ÖRIx|½Sipw¯YÐc3ª«Hdžé´›ˆ©#G¼µ­*zÀ< ¾'ŒrÞ·²L÷7вž†¥jzÈ›@ìú "ÈK’ú$+“2­?Ìâ(è¹.’0²?Hû+ªŠ¤Á5(;zñ#PÓòƒ›2 ì¦-*¼´¼Ê0á8oþµ#¨J|´µ­b+«#ð-* ı(K~ª3`~§Íü¨†&É"É" ¯ê:í9ˆêɵï" ¤£­*í¦Š§½Ë{°¥£®s”Ù: $ö~Mgóg*É[п@V°NhÊ(îÐm #DOrïLHzz‹> &~#Q(¯OBÈŸDÀ]¬ç´ë5¯@a¤*ÕHò¢“"6ØY(ÃáP–@£MûÆS§ì*«PÂ#Ÿmllâ¤3ÄÒ mýd¥i KN)ëÆñU¨+À­4íü¦ÈÞ LÞ©Alß]7”‚(‰5к{“=SÜØÊ =èÇÅÕÌ Œ)²ºlW.8ŽÌ(,w i Ô@G»¸©1/v:Bîg'»lg†^ ¦D”  謉$¶Š,Š|°¤Ù;rˆâ•íbޤ0› wcñ½í2¾¨ÉÌ·ò¬†ÚÓÜ„ÜÚú5y­$޹gûj`´™DZ¦±+ËÖD~Áy\ЋR(ÓëgoBÒ²e»«’‡UPs‚1+Ôè’ϱ¥¦±<9ÿMY®‡J/ɧÛȰA7Å=Mn”Ü›”s ëÕ¶ôÏ6ׇAÝõŠ}õÂw]d½A0gö½—€nXú^YÅQI6Ù$tñøÄÀ—ç”±m ®¶á~Å—‹»(Ã[ÂVÌà4h´sX9ø·àÝÄ?ß\¤É·ÞoÐYoU &'…äÜ\º 'D§—¢MšJ¢4M)>;fx?‘„@( ™¨èÜ13.©,†0FŽMøõ…D­²PÀœÒòdæµR&â¬z\9e«Í¥zÁ2|Í¥“ä !Âwï½em@Y>EÃô߯%”ÜPCÑδ'ŒÑu’»EÆv …Å£˜-×·ÊJz´ íþqÇ 5™úï©(8¡UŠ5 è6D¹Vƒ lŒýªù?.$2lßsQ.¥µÔÂÜHíS§&~Ø>¼‹Õ]ÚxOµŠ$:Ž}12io1¶ãÀÛ±îgzT½¬Ú³v «²Ç‰åŸý Yámç¶Ë°ˆ°×=ÖÛóZU•Ù)µyªÛøqB)³ª"?u.«¤Ê…:6ârYkǸxþ“C` |#úy®¶á¥ÇÂlÁ ¶psFüô`Û<‚Éò vùñMŒÊìJÒuLíÉ®ŒKdÈÿš#ê…»B×Ï„ Â[3¶ %hþÄSúóCÁþÒΉoŠÚ$lblÂÕ`óh9CxÈÆìʆéíL–¡·ZiVG«:ë»D¡ÚѰëD¤Ì%k“ÄŽn±€&v)Bç5¡ǽXÁ³ý&Uënóiçw0%g‹pÙcÚˆ¢šxgy Š( @ìèÁUæÿÚÚ¼¡èŸœŽž†wr]¢—sE­Õ,{•;53º¤¯îc&Xù>È6bdPÄáR"Òä?"ší1IÒ÷ž:ʙںŠ[ 󣥋q‰ˆï¦i¶iSuçƒ^˜gS˜”;?a¸I÷ÑýÀaL9 ÑèñúévÇÕhµK#LRÈFκ‚÷;«špŸz(íî2n”í{—Š•»üÖu^ê±$ù·™y\û®­.èp(ø;üñ˜›M °†˜÷¼•Ç8±!§¹e{X<¤[vL+³9Éâ]ï•ÐM‘!;ÄVyÈpÑ’¤«*uàåÑa™æËm¥ñD‹È$ÖóÇeçÇ÷Ha·Æ+x¨EâÉ@oîhjB|oa#2Ò…hè]k¦oTõ ª§ ºêêТôèøÞƺsMˆyL9/zL¬Šëæ°»‡ôˆ<£îb3/‚gî†uN^NLø†¨ÏA…Z \Ù¤—î<̰bAðNüä^*ìkøabôþ,°(Äb³ÆrŸ.zTˆ¸¯*DÈâd—©(zjö‘‹píÌ|b®ÎÌ«ž:¨FÌ+º”¢ ×Í2 BÄa¦N)îÖsCöñ'(ýë^EMi´(M fRT#¿ÃÄã+>gðΜІd ZÂdTò)®§æé‚Å®½‡èÍ'¦ZF¼ùÀüÄÍÐvÇÆ^íÉ«¸ËHòÏÊ’ïBB1*\̆êêƒ$ŽP£ˆ¬”ò¼çÌ‰Š—O¯ ü³Ë"ro¾AìšZ¢Ép-îzdþèg´¸€ kβl³Ê íx/ 1i‡§mľÁôUñ†`–§ñ$K°P°ªžïAú$ÍJ–Pvñ`Cm ŽkÚv¢Ì,æV„1ÚN¬¢‡*' ªÉ¨!$vff•Â(q±~íƒ&H:Ê&gffÖ$ÌçFô‰ü€ªXb¦m#’  –©¤Wj³ìœ"2?‚»Ë(p O~ºË=qŒ±G&$‚ôe©øìJð±C±"f£'ì¬å £òt¿D\2‰ÔøíÌšé@\iÖ}ªvllrOîÇH\=©+”³¬ÈüÃZ nzØF̶¢¬@Û²–m_o b  ¯Ž·L"È.ÕËA½l¬¿áö´ FÄp‚»,šÊ­¨ßbÙ @•E.I !î$}ãÀ«&w ´‘§&fj`]gXIK51˜õ‘~tPy3o®¨†¸ [°'"h×")aðR/0óFÉë#îbäÓVƒÑÔoí|”rV¼O±&Ȉ{Í ãoÌ#NŒSéq0OcB7î[$&¸ë"Z>sÖ¤Í{Bôöê*ï£ÞsCOÊL™ÇÌ– Ý%lê”øü‚"ð#]1²oí£Fؾ¦+;M;Ø!æù0P¦øÑÔA3˜uRƒÇBác®zs ÌËÝ!@ QG<­IpÎëEHÜÜÔhIÔlùækÒ̇cÍsF)GðX)­(°rò¨'dŒÓ±4ËÒväŸÌrªÅÝ)p„è\íJÁNŸˆ.»jòZw Aù³v”N·Œž$Žpr}nXû'²–.ÿ#D˜èhº˜ßIŠ‘ ˆÜYçŠtfÓ‚„³‚ò¦V¼ŒÑ3ãáI «3M*4×ɘó­!0%ʇÐI0'= |´yˆ`Í÷H®z܉h"Ìž·± b´ö’Þ^=µX!”«:ÑFà5y"Ë~É ÅÔ,GÌ-sb0L[+§[MrÇM„ÊóHÝD¹‡T;›JGÆV‚q2@KX£UwZgh£é5±ÔÉ'€^m bô¢ StÌzbWQƒÕ?ܯ+¸TƒØ‚§Þù•…&C~³HìoX2çÚ)ˆŠd ëNüãg´=ÃÑQS› W±öª¯­BÙ2'4úÅ~».r愪¥,/QMcàþÀâFþˆ úÇpHp³Yuê !òIbð€u€©Q*–k¹@e´"Ð~…Õá,Øaóّ茂…±ï.A ‰Èѯ ;ÂemÍ f)<„`Ô­2U‰Xô1YSäÞOWD«^)¸gîløT”&0º^+g@7“jAº¼µb²‘ &MÖ%­„uN ƒ u6é°–ëjóO5@dAÔÕnn&M„âKfq"ðxð„b)@7Y¶¨5äã x»ð+aåÖŠw¥Œ58µ¸V4/æëRå^ç­8—ÌUÄ/o•‹ªÅ)…•„ô¬/MÀ<h~·#]+ ~·;®†í§5 p‹ˆÞùpõo,Ñ¢¥EŒ $ƒèÍQ҃ųù†5˜êDÊäÙ–9ÛTÄ!¤9r3€Ù(Ö¡bŒ%ªÎ~g˜Z–)Šmº~!÷N*$žwuZÊø‡T°“§š,ÊÙT2¿¦š ›qþ²ËÀd‚e)(8jùÞ#yÔA2œwÏŽË–‘ë(ø‡Þ1#~°ëAìÑâWµë#à Tˆwn…@ç¦V±È§p@wFÕÔrvó°§VY5GeÌ¥ 4Waås7Ö;n²‰Ss˜ýÒ‚ÈÛI3n.öŠŽÐ vdž• A?uÑ1Í*ާO ÂÑ2£šx»(±6ØW­\ö.'«[Í\Å–ÿ9¹]™gìn£ Ôb¢ºÁn§™5œUr2K }â‰'†º·eŽSà,ÀóE•\¡î`™¯8B̦Ax˜º4øŒÒÈòkÖ‚Ì…‡&¨û ²¿ˆwò3PuÁ‚æ‘q9nIç´¶v"Æø„â´d ç¤Çìù¢ W±ô!úw¯¸“¥x[$ô 94*‰5K‰–½mã¼MB¥¸esKÚþb­ü4L„ú‡dn´OI)¶Úq˜Çj+O0Ñ#Ùb»{W¡X Óž11zɯϷ!Ø»xÐ×YÇÀO0ϼ‚€î¢ZæÛ¬vYy,È·ø=­ø[ƃX8¤ÃÍHDD™š(˜qåÖ±ó`Œe:µóÑÄ[XG.å@¢ƒJÂõ“!$RNÁÀÌG].‹f pnø4º¢±X)Aä\T™a“pÈ[ÚlˆrÃ"j%¹Ø1¬î-Y9ø2ZV®ÞÍÞ0FVÌ#Wžõ.&×?–æãa ±ûÖu…†p^n׿Û) Oè‰B(Š …x2¿–‰8¸² xgµºƒÏä£w5–DómסY+r{öäìÅ@ ¼Óñ¹ÆNoõLä,ž±²ôuâžlRÿ xt÷Õ|K³­Ú™j¦¼ŒÍŸ|5=)†þ$-¿$öý¨<±3c7—^yŒE;ä¬ý#&ØfyAž<ÏP'pôR¢©A’Lw&¬òlü#(ۯϽƒ–×Ã% qxÊsšu‹Þ~fôRAÁÅ,šäš^Ü/6Â%˜ãË óÐI´ú—ÄØ‡gé]uªÊ1÷˜2cN|Ôòèf)^ųÏÊ>&Õ.ŸÜe ¬…ˆÏ+MCÀÕ¸åoó4Fñmç™dПÙR¶±K@Öìç¾ "i×s›%/ ;7|Ôý2°·@z‘¿î{3ï û_4Ô¥¹C<,p”‚ñ`xã~Q6õªTŒ0×ÇFýœ2lTˆgC¼q%cŽ#_d·˜sN*!©EJ>$0mf˜©ˆã$ø‘užôçzzv¹"”µ¯‚å¸ÈÍs5Œ°8S0Ž@ ¿7Õ½>l&:;À“ W5Œ«#£>¦°R2¨ë«O GÐÙ$óì¼(x³2Wk:-ü‹ kp­¤˜å÷þ‚èÍV‡¼´VPÖÅå³™@¤¾pâ½L¨ºŽƒ(:8ÁaË$']n¨Í_=k¤žáècÙÔÇÐA7– á«ùäž#WÕs¦Ð¯£øüþÀ‰ lO»R¯‘È›¦ô«Y5/tºº,í´Uvø19»û(ÇëMû+üUZ’vuùÀ̾¢sŠ< çóþƒ>¡HSò‡âGü:(‰D À n3€c1˜ùû%ŠÃâ¹T•ûÉâÑwüŽ;ƒGä3xܺY,œ€!@Hü²$£BRê0=•>æh•X«K!ÈüR]?–GéôZ4R³KŸA¢‘øýf‰6K£ò:ÍX 8ƒHîÔTfÚÿ–pœr#¨Æ­V¨•>)ãß]"xÄÖäóûÌÂû‰e ÒêÌg¤E*’Y“þ3‘Ħ)ŽáŒN€2êíÞ=’æ¶Ö蕜„åõvœM4´”Ê©x'ÍÓ"ø—]+;p®—Y êçô,Rû‚X`”¼¼þE³kaÙ|ÄÆgîÃÅ.™ywV³.Ù NÓàŠ¾Ê Ì¯.Ê× OòÏ-Ê F§£|~À*’d¥É‚(¾7ðÉÿ¢ðâÔŸ°ùúçjË¢‡¼b¥°ïiü¡¤ÈsJÓ¡ÉÈ’®‰bž ²¨³ ¼P´!Ê¡Éû`‡9d–#,º‚Ú€1‰îŒÈh2²ûCmÐË7(‚¥ÃÈ:šŸíÝ»h"X »ÈT†KÚÉ9" ô@î\4Ž'-|“¿çóbà RªBùµrÜæá¤³;×H·”kâÍ(Cˆ¨+ËVæD $•(*zª«DêÊ>É¡S‚Nèj¬ÇÑR0N” íEirä†Bp¢ãH Êýâ¤ëZË©ë£ìŒÆp …"ŠBÊ£8ŽÄ÷+/7"6¤A³‚!D¯É,">HÝw)έò%#¸#Œž×ãFJ@P‰?·Ußx¡Š –ž$®­Q ¥K¤ $À´ð¬à” £F©Ô¥—\ËZLKð«+*Dž/2n…0÷=gb€žŒäUQ÷$Èí–dJ{.ê22ú…Âé”ù‹aV#>Ö]€ŒÌHkJ" ¥þ·8 á*:Œh "— ì· 7Ò‚½·á8'ú‘\+Hݰ÷ Î–nˆfšžH'5åŒ~%ÒÒ!yehÛ¤‘®“~Ö~ã›;>É‘ÅRÞݶÝu\€[º—ŽjL×îúÝhðûú[(¼ß€Xº¯<~.—qüêÖ´Õ³»[;ˆ˜pÈÌ]–¢hs¥š)ñr)~×½1¨èg—VÇê´ØÄ)d»ãJÝyý9°ý\ýÖdgæý3v0 Ÿ¥Þ¹ûÄ€s|œ¸Êz]._ç~"µ”ŒJáäˆ+Çi“@n/mr¸5€Hß NmÜ‘¢á¯]Ë*NmQñ3'¸ô)AçÕ½–ø‰œéôBÇÍZ¼B  Ž OEùB·I J—¥Ð¤óK!ìJ†„ˆ7¨$IasMë­"–¸ìRÎ;I­§Â2æUÍQnKmH—”άLJ)‰i]M»ã„£á;z8‰l°¦DÌMÓ!0¨‰' ÈRã ~-¸…CÇÌ·€*'U„ª®ˆŠ‘=Ô®Èzöb»Ç3o$Á$xÄZ‹ëJiPR:¤•®Q—\e€.íö¬¡ ƒAn’% ¶ ©[œ{!ÍêA(Äε ´dräV¬Ö» á‰qpg?T¬~̉¨!MÚ‘•Òœ”<€'DÁWÔ}\ogJ|—¥p‘!:)˜síEHS‰R+`NY»ØJö—jƒÊN5)e™ó™‡Ä"'Fu–Ü2sK­š)€ªûr]nçåÄ¥œL'­’ ¹òXq¦‡BÉ$Ïi øS|í)íÃcË䊔§€Ê`RV:RœƒhE'Yp£1^ž¡ÖsÈ3¹cýVîdóôS’pœË%ƒ*ìúgªÖ(Di¾}ûFTèù«ùÜEàä [„%×E·1—dVA`Û@%r*d)´Ç˜¤°NÑÆ-ŠN¡öjƒˆ!LÚ¬#ZÀO4§"|‘AëdP}€*¨ .IT|c@<K‘ç#˜W£ù#;P‹Z®}ÍðÁ ^XÆ «~£´¦EIˆu¨h¹ø“öiYGÓ¹"…<¥»—Vÿ’ÝÆ(Ò ·—H úàTÈ´v{«S‚N/¥fQè®øý– t±ë~A¬©#:JŽÖ'xùÌ•0˜¾Í¶K-J4%k†,•’U*Dé9³æ–t€CŽ­ ÏX•< Þ¼#:ÏD²ö‘·æK°À”a9¢–lSó‡‡t†G+FÍ-‘µÔ f²×˜»x¼7íƒÇ ì 6Ô´Ö%lM,Ѽh,ŽBÜþ(%Ñý#CVbiîÂl±Ê9{äg3ä!T`Æôuo5ži€é,€4çÌÜÅÈ =?ö¢º2N±d©¨œÁpn6Á©às˜…§èú@Õ-$Éœ™ß2v½îeõ#\èï^;†;LÓÄŽ6´ÓÂ%KÇøÕRR’n‰T*ŒAx›½±Ww¼æNUDF§i5gÊ—¨¬t&97èÀg PBÏ«]ê&Ïa1zóÇïo[ëöéDèEmº¸ëyÁµ`þžŽûl˜el'R#TYÊ1@œÃ¥’@$΋­ó`Ëcîëêe ÓN¤›»£uo°SxùœJ—Rk=ä!Èî=kÖDÎì] ¬ín éÕBëe[ƒ7¢3Œ¯éÔ&Ö´tj y¡,e·* (8<Ç‹S€œ$å­_bKch¤áH†j7I¸‹±aãvÊ+Â2t’>]Є9ÉH~jöеÂ"M:}U#Ëåƒdóï‚V”µ‘?Ù‡2@NãGDð½ØGí×?š‹Jè`4s«ÌŽk–“è˜<õN5†îPòæ[nØGÒ:ËÝ$ÃÈôš? qW’Túe2IZ$OQ ‘» &‰³†{ð K+÷MMž“~CyÅ2°ñ÷²¤Í°9š‰7ß6¶•'––#ûˆ°ª%„±¼:;¨ù‡¤I Zʺ"DH£>’¦ñãŽÒ‘ Ây£+Kˆ¡½$|»¤/CÁ…#©.¾Áq :l¬º ; )“˜Œ{}(‘?®“"!@°;ë¶¥Ÿ:/A`5{æh„0dOÆ$Bâ=› â´;bˆ¶Ï6Ò™t z †¹€Eó šÒ.ÂxÜÛ'q¥é®5hˆ&A2‰£¸Ú‰ ø#‚7Ù´B® bƒÂsŽ‘`ª3QŒºy#—%˜Ã´P̼ú"¬+ œ†%{l«Ê¼¶ü1¯Ä#ÈS¿“zšQçŠY©|€:ö U®–,«61g ô"œâÐaS£Ê¾­,Y¶Ñí|HÜĪög@Ô{=ÃH*—ƒúFjæˆbŸ lt¾ÔŽ£9aÊ¢‹êü¥ðÄ Ið¸r58ÃÊ ´Ëӓɺ>«3 §Š+¤ÉÿT˜‘K­0¡¥ ÌJ—¡Éˆb Ì Ë¯¼L<êÅ@;–6ÔCšqEÁùŽ“ƒ1#Ø¢".Gº@¥Û_‘?˜ÒÛé"A/[µªÂÞ1 ?ˤ0Ú‚&e˜‘B© £©!g]5›Ô 9A #—Ê ½.ŒxžÞ޼ÙŒ½Å¥tZödÌ:HQØ‘¸3$x¬Á±ùŸ‹‰žœ¢ÐžtkþFù²¦äŧžÜDbÒ³\ýùZiƱ¿d|…ÕKUØÍ Yži¡;ÄÎmc~£lE¦’ìl ã¾ãÔ{y!¥[BåÞ1¦'£ **9¶o+|ª Kù“>m£\*êʼÁÆÝLËëÝ|¦Ó^†‘Ç|LAxn6:™äþ`â¥LÚ¬Ý *ÐÔbâ½ê$¦Í\`ÕÀÑðÔªŸ¿öUÕ²™Q¥81^o])[l>þ¡1¨¢î­TÂS53‹î/ 7<ð€ÌdžLÌÉFeïtÊ:ÂB´PÌ^€9ëé$éwSÔeÓƒseÜUL] SgÝ®‰òMu:yú|£bX°læXÝ=ÞšhØi<Žd¥‡rbÎÃÌ™ÒYò½.åË+Z?¬½ªÅýBÇŠCrÑ WYè %2=úê¦iœDÒ9í1pÕ¬@é´jZlÊÈóã«´RUÞø= #‘^zònO>U0á¼Ê¼õ4TöJŠ¥ƒgï’ͦŠ{¹àà†0egDöUqgk>ŸÖeƒ®Ì&x Ã,ø%ž’1öJ´˜Éûq¢DéÍ‘R]ª<Úà8Ÿïò¦Æ»ÿ™$ÊÌ"ºnQg2 _tÅ»*H³•jº¯,ñ3ÒÅrHãKóºû×YåCvú^ö¤%îËÜeœåB‡O'¯Rûc‘ ¬˜õ¬Û}ÔuL&žp§7{~oµºÏùßIÖN×Çê¸Ãlûò¹x„<‘>åyÓåhd爂?àÏØDÿÂŸÐø$D Ea¨CöŽC!ïèdz!†DcàiD*# Ë_’øøeŠ€¥ 8ü~3Ž#ò'ôÞù¢JÑx4F;‚)Ñ÷ÝFY-…L€µܪ 7žÆeïÈT2…‰A+ò¸4ÖÃ!Çæóøf?®GWy4>k5·Kc3ÚÄF5¢>iWÌ ‹ŒÂ¯q\¢2÷ÊMæ¶ø|Þ¿w}Q£ ½bµ¹É,•¹l朶hÖ}Dâ@±juS]n:+X«Dp´àCã…À¯âÀõé}0=šÖ(Ö° ~¿_žÑ¦‘YÔ"j îe÷IlÖòþ¬C#:ÝÌ¥/Ç€µü˜DöóƒC>Plæ[±#U«èRŒÎ#hâjå4­#2ÛÎ8¾€l8¯·¨* ›´KK§¬*jã:i{FÁ¢«’ž¢.óÛ8ÇœXÿ%éênŒÂ`®4hû©>¨¬áŠÂk親ú°ž¹Œ‚ÍÉ@"Ôú;(Ò“ !m:',B ¡Ÿhb°î*ÃÏ,"ˆ«¼MIìõD°"*ÿʲÊB‡!ê˜(Ÿï»æ , B”)ú>Î@+¼7@9/'ˆë~¢/L«éª¬…0ªÃ€à!J¾ڀj2Pn¢8ñωŠd¯±³&Ц«+´‹ M„èã"'…€£DÍ‹ G§Óx†CçâëcŸÐ’fÙ K£;¾“ûǯó„m€4 W!dfÎ*Ó82W/rQ8Ñ#Ȩ¼ ¸>[`"°ýT»ö2 5_BZVü™_È$ʧ¨û ›¸Ñª~HÌ<ø²X’ÊÍòª[Ë‚‚OŒåÿ`׃p¶H¶Âšáoâ¾kæQÅS+dN4y6Sj¨7¤‚<²ÃT OnM?ȵ ¦–¼×]yO]˜ð¢³¶@? ¾1žè¯²ì»ÔX €~誵†9WFM•¬¹ÜÍ,Hº,ÿ“eçò2ÌÓå”öW@y¯H¬I6äËãÒ.r…8ÊÄjÑ93„ Û¼õ—#•º*£;ɼ}5I:PÎBóÚ8›â1 ãPhSóÅ£î­Ó*-kǺ N„žé(#8Œç²¯9¨ 3 {Üÿ%9ùt¬ôÑÏü…‘s YXc` ßëRºƒò¾oÀ´>h‹‰¿jkÔGËèï ¨•šË“dˆ#²©hCžƒi€C…xÏ©VtäÖ”vä}ÓmèT–¡æœ@|Íô~A(‘ŒyÐHäÀþ‚¾šó~¸ž¶‚8à #Òe¬åó@Ý;Xi² .E¢ÖZR°R­èç"aZ“,`ÎåjA5dÈÔ«â»à‹H.p,ÕÔ?a+Y9PhCvB÷ÚÃ7-‘Å'•úì »4QI¸RŒ»Œ[¹,­å >Fè¥^´c€Èéð>DþÏTA¬ \Ó[_ùh±‰"cȈâ÷péA8¾¨ô#‘(’hÑö¸&KÜ¡Š1paFÉW*UˆÊ¤R.p½“xÕawaì C¨0ž£ CŒUyé2h`úFD0 »qŒrÁžÇ€öcÍ= ¦›²¢¯˜Ûâ¥ZY6'´GÁ_Z‡@ˆÎdùlQ^r8È8›»T•Îq©ôÖYro<"*—¢˜ý™/‘LÇ ž'pú=´½½‚î‡c«B*-Ý#ª 0ô£Æµ¨”‘ %ì&ŠÔ–ÊÃã È{Ôk3õx6V$U¤ŒóoINtDh6¬XÊZ‰‹ZyÑØ>¡œ‡hÑ/Ê”=ªdÔ¢€Ö¯þÙ±6ª°ž.I‘øº4¼£s¨¢‰3Žjò…ó1&Á•*ÈI\ÅX™)£ Q è ®Ð‰³8JºAžCóqrÁ½Gô¾–õR,{¿ô£á2©ƒÙîM)se0|Ï™„Óyñ_zVŒ ¸:¥½Oý¢ðQÕÄĸ*’V‰k…Öû(bgë|ws-hS|Q'ì‰0‚£Æâ«ëe,^#쌦&:Êš%ëÜRsŠbæ<`šR%A̓Ư(ÐÓ*έˆûjF­å™4ålUgæ]¦·å‚xGïhZ<@÷¢ËØcÐðl¬Nzòq‚Ú?Ãú™×. Zc”¦ “϶©:]éN¦ëçea„¡[}ÓšÔT§ §_:xæ#\p_JASöu*¯8¬‘—ECc¼+…:$Ú|бQUЏg £@h/}€´ñú§“šð²D¢üÞ–ˆ)ÁôTDô†Jœ>X"ݼ/™ÄÙÊkq‹îTKµòؼò‘H¦ò¸Ï#ÆÛO£¾w…×ÇòK®z•šÏ‘QXüp·±èû­à´½Ë¸Ípz*Ù©ðÚr^‹ªÜg!ø¹ÌÙÍ!ŠB5x®8à­ÉË&] –žRè>?äçÔlúˆÒnNÒ™3PѳÔô¼#ëE|™·HçK×ìA΀ál ­fF´‚èyj>ªÁÕ%EވܱˆÌ°‰ò†ï¨8„µËÂ’ƒl*ñ„ˆaF¥Ð‘¿ß2¾È#é­&±ÐãŠÁ’žò¢ßˆð™9ZQw—ZS–÷# yú õ^©*%BïøÆtdâŸg/8ò¢gX!ŒT~]Z-`ãÀÞç Eí6ʽõéªwYvÊHq¤É’ÙY)£ìO©6ËÎÔO‚çÇQÑ’­æ…\¨è -QÙ4ûNv<›™í›cªaÖ”63´r+,Ø©~+q=?ö’°`ìjì—ò!,¬ï뼄L}MÏ&Yã\÷ßþìnaèÒ%~{ÖâîŒÊ^+îЙ0ÒZV3€×MüÂÆî )ÈŸUp…kÉ@ ²ÂOúKV,ŠF>Éí¹žì£sb«ð•»ôÕJÔ»q´ÕêØG×w3Íx#r˜¶ë·ò¥D«w1¸ˆ&ØÅŽjL# —–nê;RwË“ µiô·mÒ~S£(úÚÐ(£ìv§JuxO—-OÑyT¤ˆ&?’µÒ—}]…žü‰‘?_¡YͧwPƒÿ¨Q|u£Ym€·-« ’è- ½ÌTêÁüÐér¡¨Ý7Ìøÿ/”(‰:ü <ˆgñnŽîØÆîë í *âé~]‚Œ`âé'»¦‹+Q¡lj%ê\؉é#q5-g ÐßåL#¸d8ÿ!ójžk]Ó9eıê`­Ï43Ð^´Â áè„¶‘(ò×gܯÊj†@·$ÄJdf½íŒWŠi…#ª´ ‘ñb¢oDôÝ¢yN¶¦3ŽL³‹¬}Ð#2©‘+ Î,¦0ÃáðTD¯ x¸` É S?³C'$þù°9Fbs9ÔB&Næü#„@ëM5¢ñLU'%›;Äð9L1ñÚ¯ÒLKšQô9rÍ'ÏcG’æÍ|Bz!©OEšÌ„Š´Î†Ûæ²KÏ8-Ѓš¤ãh-Šj¯ Ú›QÖ³‘ój®ÏÏT>†%‚ 8 v4†ÒóàDÈÑ´r©>§…é´ i¼|Çÿm„Ц$m 5ÍÐOŠoð䳋¦ß0 Nlç.ø’æîÑo“AÁö8rî£TZ‰¤Ñ*€ºë8:0TÅN‡Bµ|«‹<²ïFõ,¼3ÍjûO2§S ÒÒ*”-´À¡Qû[+’;‡N@ô_í†JJ€QmàÔ÷*àtõ3ãøËL\ƒ;5}Al[\ŒY¤}Tñc+LÈc ¨ÅLÈoP´«0ª±”|õ‘h5PºY¨`Õ½(tŠR³`Æã”¤U•(æþY®19cb‘&A¿$±…¦{¤±;È ˜ÏÔY3·J_žæBBè5Ð0µdïуR¥±"5§2sKð¥ë QìÏ#çÖX› ̾’mÑ0 |Æ{X«YW21[–Û/kâ@çþ¬4lW„|°Pà*4Iâ÷ˆ†((‰ú%èÎ;Ìì`‹¨)þ¼gŒÔŒÒ¤Ì_ëA)îñ3š³RQ3Øùò ´¨s¨ °âµBY ÊËÑ'Ni.ÉL2Cj T‰¡-ÖoKß3c$¢oI#¬ éa åû1ÑjêU|: ð´ÒJ'ODS™S®é QŽ-|7[Aé .팯ð]ìO‡âZGÎòèi¨†e âÌI(krŒ±ãÖz"OZTq(PÇ|C€y6ŒJsøÔ0ò× ¼…0L‰¢Z¬È¢ DÉœÀhÀFª .ÒÞ·D¬‹5)'Mõjj!N©ƒ 3ÄrèËaû8f!3W–´±lJ¨,¸+äÅ¡útK–3j& b9RUè3:JÐSlF¨ÈÑv”&í,È(Üæ»ŽQ\wÊüô`]pÚâÍV©ñg_¸9dJw’)¢(×£fËgTç$dÂXXR°j¤÷¥‰ê€™%ï7–6¬õ²ÃQ¥ŽÊ|mXTlª¢?OA¨µ÷xÌ Bž£U é?1ÈÒ¿ŽF¸ikcsñd(ôšhr|—„h(ï4¶£isXrqgjOƒëôÝd_I†ähÒdÓ§0‹c9ÅÐYgÌjUlU'õ¯gàDÁiƒÛf ÕsFãóp}Kf^цÏ@8:Œu]v` “ø /ÊVóÏ«‘$©ð„³p´°^k^WмÈö&âëA­"j‰ƒ ®/‹‰]µXÂ’ÐhºØÉkÌ»—kL™Ô¹hÜW„ô|”9ÁöuÂ(ËM]ÊzM8o ¹!]m¬•SlT9C¡Š8alŸõIÒ_Õ€=p„‹)µŸjNõ“Óæô$)ÔpŠÁ'ÅEY§Ý ùÊŠE $.Ï ¹‚ä"£Œj!béã#ñ%6Ì¿kqZàŽ0Jo[‰Œ¥šº»FXõ«ß„:¸¡l›(ÓZºHšÄñ’zK`$ ýè¨övšgÔSšè¸æVYS¦UË_OA#ŴɨFpÔÈúð­6è%ùdî|_b_‚¸ÆÙ¯Prýr›ŽZàW½÷Ò>–m„])ÐlÊãï¥ÙÒªÀJz5‚4 e‰ˆ†Æ EdY@̼‰³¹xN†$^ðS#&1V^}É.ˆÊQ(ÓS³™,¹Ùw!t¨àg¹¦¹w¸%©©?À;Ōв#]S2¶TzNˆ•v“ªº—ÖÜ C“fË5h6¨hf‹l¯ª ³>)`'{°ôèÂê† <ƒy²²ÕÀAË<.tñwUеä|{•¬ðžë̸ÿ…+@œRD¸<µ7u|Z™eîè+AÄI½(ÇDk²ëé°-_·ôÀR(0tK$¬uJeù ¡[öÚ˜æõo·=.6ïUŠ\U'ÛJZ‰>4ntª¦Óz»c|Ú;Ÿ©%)j7OÆ€'«V…K~;‚¾X±f5ÛêãÑÀpÉ·›S—¹æ~6Z~«Þ̤‡Â$š3C–`[Ñ Ýê«Tptwù¶øÅ±Ò…DÇö¢VÓÇϖϹÚ [†õ+¯CŒGÉ>!‘u¯É68]C_ļá‹8øP;yvU`o€° óÜ@{ì`XØT­„½zÒ91Ê2#¢Û.]£…*ËѹN(m¶º¹;M#¯èh¼p[ÛÖeŽ[‚9X›0óP3aÆvü`r…<´›Òµº+ÁŸùß_q[Ƕ¨È¨*ʺÀ¼ÑÁw+¨m ˜vM‚5¶ˆýÜzvÙµJÓq÷Ï|$ää~ª¬´(åÁv;g›è1P6X##Ëœû~L;…uÜyÕ1Ù?;Ž^èp¼ˆÑ_µÿˆ$ðß° ï¯ÍV¶Ôær0‘\8©×†d¶AØÑÏ•Š¾›¶eÁP%Ñ;Ã4“_49•óXõ¯âI")¥¡üž{ÖgŒä“ÛåÖ5µQJ€èpSŠÃcŸäXj”ˆ(±fP­€þZ66ß‹‡U±q´ÊÀÌ»áuòÈÉz*´‹X½[^Úk=^ëSÝ®™ë Ç$Õ1®Œ:m€ØEàòúˆ€Jqª[ÖÎl~wQåÿyYÊ„Ô «#¸4lÊ®Φ|Ïi¦.êÀŽc…ñ³ÝÔ3”“ï…ðîz ™%E€:õ|/÷ŽYÐA•® V¹\$ò&°D5ªRSë´';Æî8ËC§YÔUhðx,”?w·IqÍ”²ó«Œ^tŽGÂ< €˜3öÿ…BàÀ˜Cõ÷ÄÀ±Wä^&ˆ¾ßÑÐ~A Hä‘ žACäà$>1…Kd'ü´ 9…È"ïÈ\’Hù¡@ØÜ‚[-žÂã zu ó=’N@Ϫµ&OTVÞõÙìÒ? ­" [7 žÈ)ÀyT.7&“Æi‘9ä^±IØaPù%Ô-…ÕŸV:¤¶U‰GåXHX+!q‰Ëá°–'J‹Êc¸ˆìfIg‡ÍfR×¶žIe†á!öYnÇ_“É2Ò«Ìfa2±ç±0¹VÒ?rØ«zGþ)ý;æsùËŽ™]!Yi$oS–èãû)uw~`¡V9úGÊYí°ùì÷¨ÿÐHù:ëÞ§:…v$wž³è޽Mj*Ë<ìª>Þ%K*ö¡ “Ò™¤ébNß¼ ;|Žª ʱ¬nB…»€l–´)9±?Ëâb³²È|&¾`¶„CéT Á§êz¬¨Ë`â£ë*6ª4ç´L³‡òÊÀ#q¡úó#íÊn“¬®3Ô…¯1E¤hz¨ ¨ODfÙ¼3ȸҚ¹¢nB2¨%°\^~¹‹û«$ñ »àz±£/à…Îgêß>¯ òºÒP½¥M‹ÞŸ!IR2ÃÒ\ô…#)Òò«i!ñR#(ÌBO ºFãNò¤’°1ú8QP¥¡J¤0,rÅ,ÅÓsõ|¾Àð-o64DÓUÑÄGbÐö ➨ˆÝ¬ˆ¬õËä»QŒ´[ÙïTЖ£6[m X.d®™FzUL€2›„õY3E·]ÕT**õQË55!õž¬©# EK*Ü,µ!ñ4PHŽÔÌ 8Ítd˜Òãã¹udWqà‹ˆ²"©VeÃöK„ã/+[ƒ7#ª£ Õ` g´¡ù$0j²Ø§@`,Dï$Yj"ðUùP€™ž˜‰ª Ý5 ØôÑ«€'®¿‹y B¶²‘|ÑeÖ¨› #ôª¡$ ¥–Þg;Çc=4äb‘ó'/N’EØ؇üžšõW#l€÷/hÿ€G§/Ĥ ‚·ìVŸ%SmœÉöN²ã±YCij¯8¢ÔŒ"o…ºÍc |õ.MŽËéÍнQe¹'5Dà¡x2¨¨x‰ùÃI[ò*ë¢7‚srô ìEoÝ)\ùn9³êÇYH^¢F££ó–…Î3(!j#Ô•jwµ59‘–~›m\¢Œ2@ ³× ™Šê,m¥ºÖ0¬É#†'¥Qm¬ØJ‚+ol„#£p±šRd,<¢óâ}Òˆ$t£¥\Õ$)É!$§²Ïº%$n•÷»d?›0ãCPñ#aðÕ')¨@—"m|z”H~XÞ{þ-§ÝYÀÅ`ΈÌV!B Aö¯ÖbÂ7ø’55ª@ˆÚƒ-­Mþ³H€BØyª Ͷ'‘Öþø‰´g'­”þ’r6²ÈYT¤v’ÒFOºŠ‡Š-a+6åSØýcŒec Jži…­@IJòRb;ðXÍÜι5´EË0ýÄÆUtNRÛÞ_`3#ÕpÔëkUPÑŒµÞgÈ¡>14J§v‹y |…\“ÀrüÚÓœƒ$]u¥'À³×¡ PmI·ÒΣý8S­²aþY]]U2§Ù­(ÈŒÐ+f’¯'ÀÝX²Ÿ"0\Š©1øÑ tŠrE%Ò;E· ƃCö‡9Ú’¨‹ÅÔ8kQ³a!­8Lþe$òÎØÖM/'Ö';‡°÷±]z%ígGDa/üüZCú|C,Å$•\&2c2Êš}Y0}½¼ î¦!‚\×x~ÎRS-‡.'»€Hç=PÊò°É.­˜ÂŠä@‰4;üf}¥ wOHÜDe»€PöH>ú"U¢´dN†U§é/NÓІ ÑŒEÉJ¦ž“ĨS®.Ô©dÙ"ÑEˆ¬–§ORvBq.ØÂ€HQÌMúÈ¥5U¬ ¬BO€ªP÷)ÒE)´Òh~±@oL#î¯ ½ÒW{< ÐüPÏ1äÊ{C‹iÒðvœÚ‰pª—5¹„é×1ÔüJˆÛ]^¶\ªæPOe¤g‹‰™—(˽=ì m‰ž(Äo@]izàä×ȱ›/oqFL§z‰P@ !"´¦Ú*×10ռׇ Wm¡¢Ò¸­»™¯Uz°qˆ’Œcj½Ì„-%Yʸ 9„ŒX¨C"&_Éà¬W ü0'i7ç°û¡ØŒŽÎz¶ª­½±§,¢®QU¼Ž[«¼E!=ù0E_+:±ï†4Øè°TTLr¾£ªûfŠÉRFqî//ÙIí)‰g7(|Ô›”ÚëõÀ‚ÓÕâ·p3è½À?Ï# ä4Õ U¢„P[Åy3Ø‹ån¿³O Ú™mùˆ}¨dÆŒ¤¹g®púyÓ¥"͉̔ÑóŒØsÅ]PÁ°¤m%à”Ú$püã]úÚ‘‰!mx MW˜×¨ö!#HÐÕ+S++ì­v†ò—rÛ¤@!ŠY*pg˜`XÊ„T¡3D}^÷©'4ÙÑ•7g [á«MŸp)B'<ó±Gâ˜'%B¿,k¡TÖRÁtí/_<ÒªN(k©(‡îøˆ›Ò©ùT‘™3Jš–˜ V˜`ËÈžw›™[¦Šþãà ö¨+ aÖz†—'DÀwI‡9¾§ËrC†¦Î8Èjõg¡ª™¢Lc‡X5xV´–çV]¨´%§Ë¢a5;Žk ǵʔ¾‰œš]‡ì¢ ÚúL­À)Òü²·ã|-ãif[kKctz÷¡/ú1fT5v(¤åm#3 ÍU¹nÚ.ð'€÷Sö+ɵ7.çÖŸÈ»v³²ôá‹_7}(J¨ÕZµ;""¤ Ú½ù"áZãóc¡ÝC{v“Ç×E6Ç,ê‡+rmb¥6è,þy‹EÉWtÎÕ·EniNn„¡¹Mç>ÂëÖ‹Àû¼"'xü Áë(„à GÆ‚K£ëåAÔGH©•Q®¤Ë ù%C72‚ÚQ¨Ž:²c¿ŠŽ1;¸ˆ‹¶¢(ƒ7‚T-Ü’1ë³H‰³°£êéJkq>¢²Ó)È©Ô+‹™½È—‹ (sµ®< [®¹ƒì•»)¨¡½³t¨¡Œð‡ˆkž5(,?ŽAC (iN$‰&kŠÃz¬Æ÷´-s<Ža£‚ö²É•sâ2)$̈a¢ ó:“¡0ËÀ¬kIü•䆰¬ -WÀ‘ðœé„,‚¦DFŒ})4Ž–‰' ®Ì×KkG·±3{³:!>˺xùÁÏÑÝ£,p¼‚I?ÆàÀ(§aB¤Ns—œñ%ÈZ7´ÜA3¯Š´«üÚN|q—‹r'S¥Ax:4[L*ý9üÆÒ8¸Â´Ïì£:}Ñ áH,Õ‰‹×Dq±Ì!lð«8H¼Ç‘­Q»+—ðFý‹;ù1C¹Ä}‘•&Ês}:‚$ŠÃ)¦Ü<ºª¼ß#ÞÉ<òAôË¢ãr=r+¹M.¬¬æ±Ø~ʲ»ó½€e.2`/”¾¸ic-qµz·@À ¢-=𱊠û’E&NRˆ<ªäÒÝ=ÃØLÙ…•QEG­:“$KfJuW63ë:šëÌ¢rqì‘*aŠ +xÉë¶û}5;ؽr–3ÁH}›1!¾s)•COÅ¡AA'º…Se$BŸ¥ü2º\ÈòfÓô:"{@êÀãa- ¥ Þ3hÚü£ÒO ×¹e°„]¢ìC•™5Aj–·ûÀLµ"·NUGVbSåš4à¯ýG“¬~²1¥ÉKuÈ‚°%l¼´÷М´T å€AŸ‰†ª4êŠI7ôS¤E'A:š.1ɲÉY´Àˆ·Ù³ŠÄØ  Ã6²¿£4ŸºÍ Ìñ=‹=™Í ’Y3<•œPšÓ×H)§,e%kt¢ádÀl÷ÆØ­‰mwÅ~EXË'+k³4¸§.‘.“ÎÛÛºD8”U{ÉKÜR<Œ5\qÛ|5t ˜8« ,¸Ãv$“;ŒTFÈá/ZUå£]Cjã•@œU†¾5]Ì‘ )ˇ¤ »úéU”º?Úì ÝÔ¬u hG̱¬OKж¨"S¡›L»h@sU\i:A1–Ùÿ0½¡<'9T8ZºÅB¦ÆQà*‹{Ì£tŒ°ÂIŸ§Lï)P8˜µPÆÜt]P†˜|Ä‘Š)8SµoPEÀ¥ š0kßqœ×½€,-WÔN¦«ct3‹5z¹‘xÀ!R5 Ó ‘49ð«ú³(Q­1ç ¬NLJeCœ#Wì‘Ҟơß2ˆ£íÓM|(Mò\º¦Õ}Æ[»ˆiAߪ <Ä[ÇÝœL»¯7‰Ü§Uàá5$ ±©ß-ÞÀäQ¨…Ù­äÑaÿªkWÎÝÄÛ3<™Í9P‘»‚±ú3`¦ ã+KbjIcE™Òº §c³Ú%:²˜×¦’R”>ŸóCLž"D:ràn6YP »œ¦›1E7óˆÜ[¸ªrÕYm”)¿é†R Ýd›— +êP® 2™JÄjcmr>׳¼LzrAT JDa ùe).AóÊtÜOJz?±r‡¡UYç¿éY½j:WJ¦ù,HÅ ½ØúâÕ­õ¡¬<–3P•Bü·[³¥MȧfGXŠR0˜›4*å6K]M¹”Z4—²A¼DZ?f­=©dΡ$A^¶µLfP‘Ù¼2Ø~iXÐÖ6 ˆ¼÷HÝÔ¥A–¼,G#Eá˼ؠ 3?HTî74äòŠqTO=]*l€Ö¹MÜÑT`«FU„L{[´¥€M$ƒ[{jÊ}µÕÛI¸»öè0~iÀ¯•uµæHȊЮ•ÚŽb´ÎAþ]£}Ê6\\f9J´Œ"û[câ)u,«‡Þz.NèMk"?A[`;kcÀ}G5Äš5¾2¥•ÏÙÉês»ÞuÜŒQyAÆ<ûØý¹².¤¼9ɬŠP†’{¹ÄU$Ãf¬ÅuÄV½õm±3ሼÌË!­ÈQ¨ø¾ó×iéPȧV [ø}E­G6ò¹IòÐÌIUº ŠtDJÀ°@§?û>L–ÓÙ9œÔŠ@ÎõZÝ­79ˆðTö—Á1ñ0„RXB®æ°ƒMdÒÐèô)%T}Õ8†XèÖ±­Ìöæ~¿2¢3Pã·éäѸ“ƆÛIŸ4¹+Lg„ÌA°¶®;)Á°øË‰ÿ $oÀm\eë‰9@ñ𲡱ñ^KJZ€1^YTúˆÔ©Îµ‹:ÕÄð´Ò\nã(>ÀÓDææI’ô™^œÂ¸e ïl‰ÂaÜùMJ\Ö™hÌÑ)éM®_6vG]ÉLТ; \Äq%ô®zã®>“à¬Åá5×»þdÏà‘ÌÔ‚·\œpîŠhhr& ¬˜@”Ë1…ë3 g' 0¶ËLº}¤‹ã‡ÁC6Ò-Í26Á¯Ä;Ÿq%ÕÁ ²éË l© ¶zÅN‹3{E÷7àÎn¬•ž¦êÀ§.MòÙΠܷFoCUŒ\N›Rð0H‡×«¿X5Ÿé$2ÆêNCžUå¼7MÂ:Iýx,¬÷Ž2>™FÀÄÍ`ZÝW¹5|ÿôUμʲ'[Íüá9€åé4^ïDŽ0@m²¶híèˆXûѸ›Q˜ŽœORm“‰Þy£S ÇA»¸ÜY3ôØß `>0EXïtwf‘C­öYU`Oeu T2\¹<赜”¢°ã6³ïpïÓtÈøÞhÞ5 ƒ¦nÈ–\k$Aë*æZ–” V ·"âd­ CS í\ ¾<Ú£$?°Ùj7êöC¾wj TaÌLmôqoÈŠ%âÓ‰¨èÌñTü=ÈÚÔ‰Ó,CàUE³¤±ïÙeév ÃÝçꔇe²Q4~ÇÂ)TŠsà'zEo¾¡$çn¬—±PÃä9¦ î°~ùˆÂzõà¦HrÀŠž}UŒ$3´|ìg>ô<%ø>O¤¿[e²NmGnêxë:)AøxíÔ}Ž7*BNeðRœDw+µˆ­—õ0°„Cß ÌC!¸ÊN ´ösž÷ahˆiw:ˆ™dCŠQ6Þ ß×4Ë{?Íú|÷Ö}ˆê>ýÐ|Ùºrdõ‡øžˆlÁóâ§f8ؽÛDŒUÔ6fŒN›&QÂ?çÍÛQɧ¬É ²s‹(nbàb COÏB?¼& ü1cXf…SR¼1ð€> @  ~Â_зü4‚_‘8kü ‡€¡oè¬F3‰¿#1–M‡É¤1PD¶Lû˜B_±°$ÖmÉà‘™ÔD&ŽÁ(ØÜF72‹hðM5óO“Aã2\6I%ˆÍ§’Y lÉ«ÑùÃúM=«€$pH­ ÿ}V¢è”N“„ÛkK„VýVÃà÷÷ýž÷?ÃÈm6èž3wƒEd:y·@ Î×"qöÊŠÊí#> §Îš8‡7mâpܺÈjÝ)*š)A§ú35m£ˆµ;¨j¥Ÿë 6DPàƒ¤Ë‚Q €.cÄ,ï²Bƒ´è‹ÔïÏš`û, ².£;ì ©1R ƒ4±+&Ÿ*(2dß&Ǽ¤õ%H›ϼ Œ !î lE *ž|¿à m ,ñÂd–%³;~})0Â*ü¶s3>ßFoŒ^ü!*ÊkÎhS¨Ã°H“3R‰N(L¤{”Œª~Ô­"@“Z%ÍꤤÉË""èÛNç ÔZþˆÌ+:“ “È,Ÿíbÿ+Å‹K ·U€›4ð3Í»t#G> ³1A‹:2›HÓµÃÈ Ã/ZªK°|43ýc¨ÍN†Mtø~ØSDG:׫dû#k‚¯í|›VÒ@ªŠMqC\Iƒuj·UmÏè<—+ÔÖ'!+‚šÖ‘ÄןÖӰнS¢Bõ4ï³cr°H4—/CàeG¤ÊKíGÑ©š¯,«3– uY“"k…BÉBuª›e/5© :³®›8µ¾€~=/¡/€#P„ÍÎ&kV£o²+z©9bK\bvÜ U0»úº …eP6¨zû4g`dzoòønÒ³zƒ.` ¹Ë€Š[ "+‘è@_)¼LÚC' Õöb¥ÝJJ¤µZÔ‚¶S£Ø˜6[>`è\#T@Ÿ—ÆÃU8kåTýeË[†›´Î½÷7$9Ç1¢g‰%¦É—jú&¬&‰î©ì1/6]‡Ïñ4ñûh8OVÌkv0ÑaýºÿDÉ‘Kcûé¬%~¢ëuq1æ/W›D¼M?QY˜}Š!d"Õi=+Ë5Ü&¾ˆYöÄ%&€2’®Ë;5]om¦+cZ÷Lù!j ÒˆLÒËIýnŽÍ×.H>æ“©ür¤Áy ªÏŒ;¾tEÑCÔÐÖÈ3P¦}šœc}  ýc‡ˆª tí¡²4­%u ÷àM ª%g ¯eªÂ¡Š }«¤HX›Ð‰•5)ò.t˜€ý8‹TÓ£wà­!I§ f0n#­fý¾ÇØÊS+Yn.å{0&Ô?ž3Ÿ5¨½CB‚†;~It¼—ö–îòí@D¨©"ê$°ÕÐ%§jŠß³Ÿƒ -¥ÊÂ༠*õ-Ê2láÇÓ!:Í ?4ÊŒ—‰±"Gž§0F\#u‹ì̇«†0¬1=D°1=ÃÈV¯É«˜{(j<S &›LC ¥H¸*AÔ|XpÜ!TÊfåÛL6O ƒ¦7WII%X1xºåý/$é"ëE†"þ±{ì}¿é?"EnÁ‰ÅÐ\+:…Œ!šËô~_DQ2¯E-ÙÆO¨y­bjÀt •š_ƒñÚ³o@]û¯ ŽÕŒ§\,mPÃM*†ÓÞó«T xø>•j܈¼›-µž·ª‚†WÎÂ~GÔ£Ìij‘ò W”=A ~A0\‚[,Ë›i‰¨®ÊÜDÛÐÿg°å¶q`ÐÓÓŽ2vëäy§cç‰ÞUy;áƒ6äÖº¥*=ˆ;¾™æ~g4öê´O²c¤Ž~‘UcìÌI Ì Ž0‚zj)È…•V*«Ä*|ˆ™§)è½( \&Kž±Tͣ oà¯&~æÚàz®TEu=_6‚#bJ6¢ý”ÀòÏ tè=çpOmúÊÈ Ðûb…’t•­Mã˜vRÿÜÁ›o•-ßÅg DÞ/ÔẦU¶«Fæ¡·õÉ-Ç’âp^‹Mú^ϺŽ"m?‘‘Û #CÊ—®W8èÿHEÝcéÍV€TÑ)š·d [§Á™nÛ;ód¯£I1ÈHšO ‰"Y,¾œ-=Üç…SÜ\Ž”»iÅ&…|ïÕ‘w‚Œc¦N3’G¹âÇ8×qCêÖÞ©º!€*ÊII•£€ªá2êÈ'<‹sLr†B4÷LZÛX´¿»WP©˜PÆùÖÕ‡i·~ÌD\eW1ˆÿ4ùAs½—-b¼e)ÏÒ^.]'Nwh€›3‚B˜ßDß»UÆé‡Ol'n ã¦îíD*×!s­×Sœé“@A¸^~iûr—êéN%Š[ÖH¯#^]Ͷò "¸qj¶ú@µ–YsòE-«C7•–þ&è˜ÎòWudín““€¨vObCYÁ„¶`%Ñì¬àQ)ê—‚0l£Ô-À§–¿ +`T­=:5@ —»àµE¥\míx_ë–"ÛÈš¸N¯7U»ê®I7Ó>`®^>Ö«Ëh­›vËÿîDázÑCmýOY¬×A'ÊIMW@°áô?úŸz¾¶t†¦ïs—Zk£Äm1žªä¶Ïu@'¼Œ}fA*hPúàž’ß´‰„ÉPj^\Ä8ˆp žÈŒ(—®ΨW b£Ï ß/RU¢à»E¤¯éæ‚dµNðªÎšÀHHóꢒZ.bɾPÊÜêììÒˆ1M4}êÇtC.ü $Ŷ· ò¹ŽÚh ÎÆßbäë ”ˆü&«ð)çZ3p8Riˆª``¤nBû® çd~l8݈þ$¬"züOžåÊ F¤ä`±†ðe°Ý ìkþ&݉`DoXuGël \ÈŒ$Oz¥*êæ„¶½k¢:,Š)냅¶ÃÐ;aù L iââ/Ä)'þΩ^¯iÌHB"‹†÷+§B c¢ŸÂ ˜0Ík¤¦o(ÂŒàYÄ@qÒCj-Ïþ©NR®PVåãö!ñpüP‹°Ü–ã WÍ⟠ôuPå$–‚BWÅ üŒMÇÓ„4f¬C` ®‡Ø)!«d *ì¡08ëdƒŸ ÏÊçÊ*EcNio8$Ì =¢`y Çÿ   §€ÇãvÒ‡/0f¬µëwò'!HÀ¡)q"¸Éh]𽦖žŒ>wåêD¬88‰{¶éª¨ÈÀéŠ3çøzŠÔ0Ãd. ¡Q\ÜÞˆˆ\µLšh)M*"|M!ñ†ØŠ6ÓDèi2žžÈe(„’k–iŠp·­^ä2lçPª`@‚¦j‰¤ FŸÊb‰'Ø-"’³hlß2L: ;pº‰£J=QR)ð¤A0ކ–ó*^‹ ƒÈ5%²jÒ£4¬K1N¢€ï<ö’A.²®mÐËà´'¼jÎÖ:…ɪMÎŒ¦‡+gÒ×Bd$2fÄÇæìnòn¨Ô®‚ÒD£U/!ò7ÃìÍ&\0L%Ä*Z,¬Ršª j¥G€dMÄÊïpØ  Dw (Ì£ ì”è1ˆ’Î¥ª&Q`ŽI ŠWðžC01‡“%s¯Ê‚§ç-,†ÄîHüÍ€a6¾©TÁ¯Ÿ ¬W ¨Ò‚s¼Ch%ЍÞGZ‡pD‘i3JªùBg…oÚÀh,p…&bl`3Šà¬'ÏUCæ#O³ ¤žGÈ)ô•‘pI*’À Hr4±ªƒÖÇMàÚÌJX«Ùé3` ~h’îÄ…ÄX’ÉÀL’ÏRD´|8h&©æÌÕBý:ˆb3ô-@`G1¬F›8na'Âp3fpÍ ˜‰†‚Eo,cÞŽLJB’ì¥hƒ8˜ä/å[:G¯Ê",л’Eëd´äíáôÜ'†!òÛ3!4/G„bh99Eä–b§ài05D´¨¢ËIRË4fª?MÚZN‡U Q‰å?óä­‚-ÒÈÁR‚Ž,9À ìA'B‚tü®â3â`$5@/Ôï)‘®'ÄÊWÏ«Jáþ¢æ .ÊVJ=#u5mW8ÂÜÙ .gE¤A8ÑQáø¢åÎ@Æ&Qñö$±;/RÒ"³°¹1 ÂÞRŠƒ†êMÊ@ªS•?‚WÉY/ãætO&§·a¥e*4¾ÚpéWnÐðFdc1XVJògj õ¡ ÐŒˆòãÂ΃“rÝ”£+§éÛEáû, "é[ÖSGóå#‚q*/Zª*ÑéºF ê÷ÓÌØ4) ìÜHßÒˆþK¼N¶|‰DªÆv¥þuŠ¤Ý‚7±Oïëõz7m!jä^µD žJ^è…êC½sšé3•5•“@4|£ÖçV°ðÀ¦p‰.r÷íå"pªµN‰c§’3mZØõ­§X-¦Cá¢*ÃL¹pÜYª(jã6móFÔ°’³×Ujë‹Ö¬O}Aµîæ,ubÕúDjÌ Ô¤SPLòd1!¢áBp¡ÝÉ ;¶£–˜N³RüF’Ö2µŽ¦-u`ªáÊpD¨Õu ) [eÏ3° …ŠqCjbë“3óÑ/Mé5Tñn Ÿ3òâOgdSï8aÆ0ß+V"s,ì'« "oLÖUU6ÏC7xhãµn÷M>í(Y‡O®•wTú¨ dMÒ sî‘n¤´¬C0=Lг·8p§0&F'3S˜!¨Gb U”‚)¾ÉÙ4÷ø&§|is'4'$"v'oxâN‚铜tê)ïLÐÔ9÷òºËºe"d\w³fíd¹¨“[Ï8")£TÔ|×çذO𖌕‹U„BšÌf’GÜZKšq'Ñ@ëKÌ_#µôË @ \먓 И‘cNblñSõA6KsžÕ0²Œ}*^þ‰I2lçr¥GwLêsÓ-@&ñdÆLl Qæq ¢LЧÃeê€u©YrOò®W wDÝ@ó•6/0Pƒ‰ìT÷c["`§0³@Zï(¡/R&Ë~=Uüîwhd°ä¥ìÇÿ‚Š¥Št¸A7z‘ïˆmnÐaË‹2ÐPÎ\q¹@W¿2wî©óP¨âàæcNRç… lZÍ!ž¥·ƒÄ>ËáTÈÕ`íˆ3fx3­˜g‘U¢QÐ+IvÚ@׈ǓÒíp!á³¢õ´5°Ê¾ÉXaÔvxõŒêx°S>6d¦q‰¬ØlHJ=ŠDG1„s¥.’òÚ+9o.ÝD7ƒ ¹(WÍi@pzÊwÅÒp¯sF‹^L:#Ì×¹dÂrzظvšlÀ.òÌ*²âF¬Õ¬N‰HƒÕQK×(¤pe"ÜC—š1”ˆãä¶•‹å7˜î³õ3âq¢aôa¡©@Ku¡¡‚д.(³R¥€ë×,ÿ ƒ [gЋtUAâZVUÈêŸ_™Yh›"1xAYŸNÐÞö~$ÑUY ˜—À‘ê!g鏿˜;vFJ4ÙnÀ¬ù™«?#m‘"'|37YÍ"oîxàÚѪ&U1v@ÿgÙHJ½Ž[püg>}Öôö]$ OË “„:hVŠqbìq¥'¥i]¯ø&µ¤6 Å‹‡á!M»VÎÄSeÁo«®”ûé4XÕ¢V/£æ­FO9{²Þ¬wbÃ|‚™ $KÌüâòǸÒŠ¿9U9g H]ì1À5²Nó¶0l9r™" ±‡xB)‚šÙèi¿O¾ÿX„&ªÒªÁ"„44õŽŽ£Å bÏ&b‚¹Û¢` ½W Y«« T6ÁŒ¼ÆŽ#V_?[á lø×èÿ(ÈÍ|Âü(ã`VpêÉuHè'ºûfB¯«nÜ‹êÚ¤lßTÒǦ‹0Æ­ÃbMÖ“Ì”w[»5,ØšTËý—ÂCJ¥‰Êåâzìµ1‹BÒºXÜÞWä·Ä4ø_3÷wZ×´Nº9Zhg·¹:Ç7O­/B X÷sî+ÅwpŒ‡Ð$uˆ/4/9¾ÑÐ-­*üé0µ8}If—ªu(Ðà N×Rh2VÜcd³¢}°ÊæKÔʪ{H}+¬ÊŽì2`'Øa\ó Q‘Y¶›ò£â<—ƒkåd¦/8£Ä鉢`´ò$|„ì¥ i6ÚâJ–Tu:Y°áù ^Ëè+dˆ0÷ÏŠQX~7‽Szí4öíÿ¾,- Å&þA5-˜WàDë!¿àÏØœ°Xÿ"ÓÈ.DºOŽýHv,pÂy¥¶»[AÖ.ì2 Í4é°«f¥Ö^>¾ãÄ"³'d-JÀ³­(ËÏÅ• ÌçNýÐL{ÞJ®XÀ]‰dCQdÎÉ,±põ:Ágò+M› 팬µÄûu˜êó»ËI1åŠùæùbpb•Ú¾Úq²:ÿR=!Sc¼âèLtd]~abœ–ÇZ´$¥·Ó§[ˆ3j Ôdã‚ò û”uFã-³¦¾D¿3;ÏQxY@šøsç{˜¥¶UõÑzPªL¸Ò^«ù2£JCÐÿù~Ät–"+~9ÿ)ù6JJœûi'½{vaǤî¦ß9»ÎÂf&1òy²iŸ™k–à Ì9"ôjª§{ô'µuìºfŠšŒp¤—Uòbª|_”S øüƒaèT ÿ€"(”@ý‹C¢§ð9†C¢@(ÔYûŠD#ðˆ I Éâ¨d¶›C#QI 2yOãPgäØF¤0çÝ.… ŸÓÀ‘HtâF†Ã¡*Ì¢{)‡Ì*ÕØu>w¦À¬ ¬¡F¥pë=^¾Žß7›¼®ZÉ(0j$2îúÃSä” 6.ß Ù"RJ[î‰ÉÌ Pé\†IŸÉ'Q9Œ*w¼¾lsø¦J—ÎÄ©ùIª"…wo™û«Ïu熣x m>çëª÷€ Zˆ¡(WA W`0æ²\HþÛ½EÂʵ{bSJóõ¤ô;&’6v¬Ÿ°ˆìGV …~ÇÙ+B¢ÍœÅyYÈv¯œL³×§±p­€I^ÞŠM,]š­®Ôò%x¢:I1A[.põË  ŸZÙ,™WOôMPó¾_0lMòÄ„`y´8ÐHå(4ìž9Ž Ì˜Ó@ˆâ…iT®ðó×åöÞ›¾u{`ûìÚeS•EÝÙäš‚nÀ ­Øñg1pùNJþÈÏÛa©–f(²Ò3¢z‹}ª4ÁŸ’ä7êÌ‹;d|F—Y¾ ‹%Z]3 s µ Ÿ·-]ýJæ† b8`GãÀ.ë„7æîr\Â$¸špOYj@ìøi;@#GDJ˜œ»ºnt„¶hŸâEGѺ5ã†ÊPtI.¬0«-%pü_„ '¤:€¢„æc{åCf€‘”Ìcˆ¤q°¸çÅÑ“w-)E¡·ŽuâÙwE«1œ>ÄPÑãÖgGén¸ÐlÞtŽH JêÖs蕳2 ­c@B¯†œ3fפùŽ«<Üâ} :J„Ùê˜5\¤ebzm&ë¤øVß!Kn"Ï̇=T’Ué]eÕÈ«S—"_äÏB±}6Ç«˹²n²ݲR5³ & ¥¤ËC9ˆQ!ÉĥÖ=rµCÆ’,_%9…„Ä ;«aý>j*l¢CÄ@°ÜÄv¯¼†3)C>H#Sx9Š)%Ÿ™—!RÄñ—挫Ó„V’ü–iÈÒȬL†ÅݤÜD¡ü0 LÉÆt†ØÛ¹DKcÔ•›1åPc;Õ•»¼q¦lq*I!vo"ªQŠ(.Úžµ§yXP½G¯c,Às ,L‡Cˆr׊éD¥ÜyÖð\`õ.3ê= Àvu>£&Ì)µDÅTóX¬åå›6“Çé+"j޼7ÞX*i'AK œdú¼ 1³pdüÓ€ j•ì˜õ×6H$q"U=¬$i,ørö¶‰ÚyEó2í™~£Ø¢5‡Ÿêô†ÐyeQtï@-˜ ˆ‡fÉÚŒX Å¡V?VÔ1sV§*B{.‡ä«Z)±Ð·Ôù®«£’ëU4Ða×™´åBY#lÝãËû·þëÍ/ÆžÀ] ¹C&ÅÊðF7½mÉ:Ô-,ã>‹ušDCè9º”(LÝLL} ±p BÂÎ)‰k4 ªC›Õd8^¦<ñß½â]F.q¬’9ÈBÒFv$™:uˆ†¼! ÐUWXìD”‘ÚwD3 €uèæ:-xDì!oÑLÑZ¾š6° ‘˜ËýsQY2ôA !¬h*jóôÍi±K(‰N™DuAòÆh¹õÉjª´‹gH”6ÍáÁÆÆ±1>ÚU¼,TÏ‹rY3€7€©@!wµ@8«Œëbœxd¶öñowš² ¢k–åmtÇŒâ³k´Øæ7ýЬ¥/%,C/%U¸ò?Aòާ\Î…V²š½œì6~§Y§L»ˆÏ‚õòpÇq²­Ú+Ž†×´Û½C ¢zµAy“Ž-ûø­Wõ«" içò#ŽÊQK£Ì—€s ë¥Þ"©ö¢Þî{BûâÈ“S]‡î¶ŸQ^X¤A§gLcâYѲõm×’T*~¢°},“úSes¼´R×iKðdÂerã“©€/Aß–‰àJB!$ˆ”ÈŸ{qóϯœ¥‚”LXÊ>y§ºÁdQi¤u72=N£Æ“[ÒÞ_æ£ûë¾úió‰ Ž‘PªQ‰qÞª¼RN¢y+xƒ÷¿s ²Ö± h= â['Œ2 ðý\ Ì'€94¼4,¡W&™Mc‹˜ð¥Ž¼ ø­é5“a!– KÁ<É 2èºq¡œÑËã ¬W0”¥)ZIÔD¡ {HáB6˜‡©%Ž8»‚ ´ŒB³rL Œ“Ô´ ô0&üž 9’ñ—˜S½˜B Y [̽ þ¯ ä‹ò÷ îAÌy) Èh¼¤*Šé`µŽ-è¯EKÍñ×½D²6›¡9jî1K)‹ÇÒ~ÔK¿,b$D©£7w»ÛËR«@ôB‘:¤(¾$¶5²«ÊácE*Å¢p¬Ld5ð®¤|‹¹$ZÀé!ÍyD<@‰ãv>qV ò6JÉM8»ÃÀÌ΋[‡àëÏ„x–n´ò#É¿;— äsŘc%¥;š¹´KY0, Q4qMû #ËþÏ)pbο*Z€ZÊâ5„0·‡ÜM€CË´»Êºj.éBHr“CEQ³-(Å‘ÒK@ žKÜ  ¦¹WlѲ(Sò€ÀÐYÖÒ9þ Zž¡i61ŠÅ8ûÒ>Aƒ `äŽ26B£r z·‡˜§¾u#ŸÈ†PÁQð³×B5l6µMòž‰ t”zB°CþTŠÒµ#ÃL£‹”ŒÍh‚'ùhL*?Ó°Ó½T¿ƒ´°†<4_¢Ê{ihU=Q¶Lû­¥ÚH4”ˆ”8= »ÊÛÀ»% 5WÁ¼üKÈ3R™Â+KÃA¢²pŒ:÷ÇAŽJ$›’Œ,†yÑJˆ‹ÒÔ2Ú”ŸÈ¢U É¡=в0¹Ó©‘1Ùý…D|¤’‹d¬›ß ݸ¤Á8tIÑÒXºÄ´UºÉ íYH¦4Ê…®D€æÑU%@ÓŸUV0ÔÂóWCLp•p’DY†Y‚tU԰ѳ96+&LÓÐÁ1M›K[l6‚ r´SŽ×Ý€â-ì0‘ðÙ©ëþ¹¢À‘ÑiPiûÚdÝÚÚY‘¤2@Ùê͉šÔ ÅZûEŠâB•œ1Û‚KÿÂR‹¥ÙiÆAû×JDÃÉÆU¡>Â2+c,Ô•RÈzõ™e Úxž¨¢É:ò0!ãÞ):­X‘‡-Bž¬ÔéD¹•º <\©¢àÓ­C|‰²zÇ9!ûšû„-ê\]Á>’pž¿ âµÊå"µ©ºž"ªš30YÊõ Ž5#Æ%ôLÁûž!ÙtÑqŸ$æà,Lƒï ÌËVH.È’@3&Ï=ê$Pí¬4ÏÆóò$1»ìµÏ $©¾[tËI*(\Y6YØmæÉàzb\¡úpY»aªV¸j€&zšq]ܤV’D×2ÜäkN0~V„鑚B³òb²+p:ÔA=Pâœa]ñŸ[âÒÓ“ÊéÿÝÄ=ÀAe‹½¢«£Æ© -Úª˜bVÒâ a £a>¬™þ2‚?š÷±ì„§mȬ gí½”€ŸÌS³ÄA^ב^'k+Ý»LÜ4©2+®7é’ b­¥Û®ÌÊH]jŠª^–\&k„E»=7fSR{ˆ0•ä¥ÂÂ:`4¨ýÕ€?cÞ3Ò>3¤á{U’ëÉ:+]Ú[–³Í¥’–¥îÆÍ¸ÃïÓ8Ä;gÖª< ›Ì«RðÔìPê” .ewªÃX™I¦Ë“¶´S´<Ï¿f! ªq2-¦Z¶QÏéßÕò•Azš+Åö=)TÒ3Š[Š&l‘UWøÅ»X|ËÛ½˜}©agg‚$ž £ÐˆHs¼\fˆRuäD©¥‘Oa09£&,‹¬p<bÌýÙÕC-,#L•ƒ5IÂãÉÒ Ÿ®<ÿ±CyÃÄa¹æa+0Ù«Ò”£Î[ÆŒm•|.ºš2ܘÃ&6·Or¼Zj´ë¯ 7®\ÖAæpclám3G}°Z…»Ôcj¤NG‘óA×Z•QAî4Ù@ãýO@ìKAâPTSÐë~b3Kþ­24ÔrŒ[Ï©29âzÁ;ZÈž¼ËöY<·fZñMެÓÑ™dì~£ù_ \uQ†¥Úlï½:ìisé½Ý/ œ…Û×V¨&kè£ #ÆI:}Zˆ”3m{»Å3ǹþC¶*¨%ÿÈ‘a-í1aºeÌauôD=΂G­ëèÂ<}å/a£NϺs´ìʾÃH«Ø‚YJaÞl"6ÚL [ýkÒ½©0a ¯!{)ÓBÊX&kti!éCÂj3wê…£*Ž! R ¨A;1CϵòI²HOóKnã÷0Kåš3Wçdá¯{+8y»Þd˜ùšš+Å c§ìÌo¡¢V¾çW®ÍKDN`¢Õ鋜Œ[…ã4±C«×b4´¹U06I0m6½5}G¤ys‰· LþS¥—Àʤ·Þ\<[Ч`ñt''mnW2”$Îl¹ M)šîþF®P2ÚòBè¹dÛn-.½.³e!ZÎÚ •§ÃÄkÃîrþÌœ)6 ²‰îŠ-)…=»ÛØý»8ýGÂ0ónWëÖ[貺3œGViú,ɨºøñß9V_}k.W"ö–Š¥=ôG¨˜Q6ñnÇ‚ ÂGàÒ´ ëÒ;fãÆ£²5è”y–LÇ<fN Å ±éZ…›9r ëÏv?ÃNðOlIòÏý—´blfiø’EƒÄqIÓ@ÌÊ.H}v2£àßDk¦K±ÛQD>x#™41ûLˆ÷ûj8·°Lï&·‘1"±¯"Š7V3©ã¤´Ûè¿„ÉØ}Í+€1àA?£³ ð{½ÛÖˆ&0lì&ihwò­öØíšøÃH§ž¬Æ‰µ Ó3§lRg¦4?r‘ró¡ é£KG|½—œ%—™ò\q™IØ*œ{‘½L=Õý<´žq7¶f<AE´‡ãÌÌéÍ#Ëš$ÇÐÑ ;(º[è›fЭAêž…²,i¾.ì·¦y÷LjáýÁ@p & ~C_ðð$D}ÅbÀ8Ä=ÿÀßѨÔD ƒ€#ÏÙD*K ‡Ê±èÀE%‘B£Ð¸L•õ;‘CgÏÈThC—E¤³p• —Má3$""|Õb`)ÛêE1|WdUzlK «Õé’‰„` k’ˤ¶8Lz5fœÔ€6ûÄ–œ°J#QkX] ˜ÖAz«ä‹IïÐøTŠ5zei@k”>¯d¡÷ Æ}W½@çÓHŒZ9>žÃo: ´c±IgØjÂþ˜év°|æÊcÏ?ï{hlº¡„ß_¼ö]íÓõcØpD[ VA=üLǧ»F¥W‰cþËë‹Æ!Qn.úÒ·Aïuø· œBý.ØÀ²éóÂ÷!)ò<Ž%ͺػ4ˆ:º|0)r€5`@$ ú„áPWä4 Äa¯ÇôV F_±·üvƒHc Ûö*þŽ¿â 8ü¦?%•Áe38è m'“Èãòx,Žs•Èä±9LØ+•Êdr9ìfO%¦€(Ñx›òA¥€$ Ufhÿ¦A(Õ$ú+S‘S¢²P-¶q”Ï ’»h '®Ö¬±™KîýBÊãö€ d_‘×ñQÚ6¿>åsðÈ”™G¡÷ˆìŽ';Š´Tj|s!˜Á$²zLvKf”gp×ÍëF|îj: 6Rú‘à¡õ»®7–Êâs†¹µÁáüoöj™ø|§2ÿÎ?ûö÷ôê!”î_7XŸ ÊŒm&xnLG+ßÉåºp³â©&ÊŠVȪîj4¶+à~=NÈ|Bd$õ1/ãHŠ¡@:¾­¢i:ŒÙ«É¢ ¾P©þÕ¢¯Ùþ궪‹¼¹¢(*ëÊ&Þ$©*Œß¤k«`£GÈʈè!ðê*º¤©r ¶+äÒŸ±êê¶Å#Ê ) zËã æk6¹Ì£Âº¥+bÚÀ®û67TT»¢©€l‹a¹çü†•",r‘ÅBè ‘¤F›:À‚Ê­éZŒô·)ZK ÏKQüÞQ³|„ÿ²Š3ÚˆÌ ÂôË­ó¤¯SÌGëZ™Ô`-E€SJ7 ¤qâ3ZMR$†·•k0ÕAÌH¥¥g½•W·ˆ)ígµ*Ø;¦Ñ3-aϬ¤AS«q5z½°ïä\š9ÉML¨Ûl4ù6W@@H j%pÊR߸§ó'#ÊŒ #(I-Nà¢/RSf¤(œ¤» •±ûcÀ‰²>ßÓ õ´Œ·’„³-$/ËŒ~·˜jŽ¿O8K¡Ráêú€kËÃFÒ×ðC6Qï ™³¿D0°=]@Ú¶6‚HÕ[ ‹¶k¢Ú‚äWF|²ZUöZ×G'꿉¡î¿“dÁÏ< }òËZ6?Ѝø³¶öëïš3› Õ ®¬M|ÏEÄ‚vh#"‚áÌë×A|J:•Æ’õ4¨Úë†ÀªÜ«&UD}ðIØS®1 ì¸f ·Z{ÜrK$‘ÒêIÍûñU¦y`"ú_Û¬†Á¤)ä1¦&fD¾RüÅ[~~e-U('# !’M0Åm(#sE [¡$#o„''˜ŠËò*mg9§µÝ:îPj|«5Óâ¢!©*­å4ÚÊÚx}ä…j"Jz“Â8#fýâÃd_“úxlñ1p4Sµ GÜÜhov½×þ±ÓÁ¿dO×$ÃÕ9u]´ùKB ¹I¤ˆ<+© -DÁ-‹Ì™x¤”ßÉsä®Ê4ˆˆdzZÓ¾Ù"äo°(Š¹È…ŽÚâä˜+r!*¢j%!Z´‹Niº¤ÆÍý¸&­ È’t2Ô-ýi«óÈ“º[kH#6wm›;  K¿I­S4[0b¯:´FÄ6Þ]‡Ž”r’rRRˆ\8„Ëh¤žï5 èìˆmc$}F¸@¬W{Šª8¶´RSj((¢iK$B+ƒÆ0‘áäøÈR…_0„DDÑ¥€jRúx5©ç\HÌìP€*ù¾Äˆzø#¨:U¹0qð˜È$¦š0ìúÈ1„cj—~TK«*ž-YbÒÑm·¤äFçµTU%m‹¡éÍlVÖá4&rð¿ÕápaÎL!òRù%98”iA§fÕ>áXýo,Om·ç6e (ÀŠ2ÚæÃ5xVaLŸFB$¼¼„B*<cèÉy-Hnf“Çð†¯²€Ď쮫" —ê|§¹n¢ôyÿžHý_Ü¥[77¬~{Hs&"v㕵¢¶ÒƒO(“ÈÒ g D`Zr©B¡³µÏ%DÓ¨œAµ4«Ú‚Ñ_)‚Ê*y¤äŠûg$«®ÇjæQ¤läyé-®ÇDûy f>b¹­Å‡šQ •U²˜}ªWbN(…Vκ­ÛÚò™H­¥Ð‡ºX›^ dU–I‹F˜SX%¦‡ñßÛ܃2“šàÍXÃÐKΉ­Ý|—äN"í†M®¶d&—' € ÷l{áÈòWbÝ22Ü)3¿vû—‹òó䂸3v‹w.3B­Äÿî<ï&Ž“åºü©éµs1suð÷]½ªu¦„ùì¤ÅgWæÃÞÂ6P­H9‚ãɹ–Æ2ñRfo8”‰™fvæ9ª? É¢æ…*—ž¯5ü%VC;E3fnTÏ“ç’!F³ƒñyDMºƒ2y#é>i•߲рº%EÇì‰æS°ú{+îî}¢[s¿EYÙO»ÿ›ùÍñDeLãWÕìù 7íBêë%7OÇüz´ÿÏ-LʾœÍ#ÇÒØûü{eÀ ZSI3WÒaùõ@<üÆZøÜDW¦cUº ËÉ®ŽÉ¤§‡uJ§AÈ”ØzÊæ“*†+înOж$²ÑÌø]æ;ê¬Q£Ôlãxfʆ‘­ÈŠÍ(gŠó‡‚:Aô×àV%LJªZ#ªÌ¬@ïž ðÔ FTîRÞî¼F„ñ œƒGÊ  ‡Š//ÜrHˆ`Âh[ ß-¨]ïŠd-D}.¾»ÏlÏãø_#`9Èl”‹Üé§\´‚!L.ô‹h‘FÔË/@s'º7ŒzTÉàÆj”_‰øã¦ÜQ®2‹¶ežÄþ°Dï§€ÖåÒjGXOÏdÒÀüÅ^IŽŽæFîJé(†o®Œ®ön¥^¢ŒêßÐ70f„ÎùͲ“¯ûÊ$prÓj{¨›¯úý¦¢³aï§kd¡Ë¢ÀÉ_ÏŽý‰[dÔŸ‚¨Œ¥ò{ú‹røPvØ'–ÁHÊ;îÆ¸h¸÷ ëåZZ)ÈÚŠÕä¡ NŠÑHU âû¦àG$ž©*Œêø±XìJòUL DÊhlïº)&•ÊÎ"0öëO xçªk¤ ’‚Jg Z(\eÚÂ`ï¡àÒ!À$2OŽÿç$™Nœ6Ê´O°vêØÎ#«¼dRÉP¸©‰ 0˜®n†V‘¬£r‘¯è“/Zê‹ìÐÁú¼„ RBðŽß"j˜¸é(žQdOélÞ†—ð–[ŒÚšË ßaöÛ„ø¢Ï! ™‹RB”pB–Ê­)î-þêò¯žãÊÀd¨F×fÅ O ”vk""€Ï)‘–¸€º'nÃ2BçI*Ý2ò!ã"È. "Îö‰ïÒÊ¢q¬¼¬1 ø?¢Û$éÇ‘g$Õnî„HÊǤð+e  ÿ®Ô<ŠpÐRMo‰3.\ß-¸ÿrƒ1ìb-¤hŸ‡ì°©I$ÿ£#2T/Äø»Èæà, ðã dPRÉj#+ò®íl\V±¨«n!D) â67‘ù4bC ä—Ó ìíòÈ"O+’€¾0®éÈ€Ò\TãÂñé?7æêžST'Å^dIµf«çŒ9ÈôvÏŽ¦VðºäÝ=“>&k6²§Zˆõêt“…䞆qˆÏ4†ð¤_-=%À[d[rÎü.XÄL‘Aë®°ÅßsmÌlß#Â]±¶¥Aüwêzÿ¢ fh!J¼ÇÅhpÒžç" fÔ˜-ä·£äۓ„îrw´$‡1#ÉO$óKíª°ÎÊ—ïÅ(!‚W ‡SS= –O V]±$M”²"£#>ÜŒ± ¸FºEQêîãœ2+¼°ø¼"ÛLúu,z¾«æj²ÜI”Fè…4dB>7‹ZˆK%ç4ì¯Bl"i®ŒãŽ~Šïõ$îÀl;"É¡%œjCÔ]¬êöÑ,D 3-TØ LfÍâç£Â»ÊÜ1qÅ'iOüpf>ct['O&JI3©¬Xô“Åòã©›Ud²–k:‘4¡6ENø§ ÆïüþÐiCÏV†åZ¡Ò°¸Ô0˜DžT%cÕ&Dn5Èÿ\±‰I¦ç9â ±âN©mëaOž³?’œšÐ¤$舊(DM‡k «é}R¤øLf¥•²™O˜l.=Ðð|‰áµ[®s õ.Æ•ê‘xèDlò.²­¬gry]ÉH"öCÝ?ëŽDÏësˆ íXÍkRŠ‘-Ë<s•¨É*‘7/c@ˆRÛeF¹]) V®cãÈíÂ*ˆ‹Dw+HT ´¦#p¤°E9ÓVZN.—ÖÄßFºÏ/e&s.Ö‘,€=Sb¨¸æ(‚$lRǺSOèZ#Õ áø¾ˆ¦înÍLÂh /Ö.8ì­ U×$ð¥ÒÑ7Y3)ð-Ë>ìXE¯ú<’°ˆ 0ô¬‘Õý$qúŒ¬êŸÍBà³Æú ­µ·J°Ä9c‘ÿ¦¡naôeÂó·pxòÅiì!Š„SÉ"ôÝlÃ`Š1ÿÆ,Ð":ÎçŒÐšÀÏñu>³×LÖ¢n¬×m·(Ã…MBò¡{”U~±ÈrHwVPÚsÏ*Õ¡÷$­D“€õ7È`oÇrŽîL›Lo^2Ç»•z/Ë"-¬Jþ¯V* ÔÌz*$Ádîe†Š¤2~uq(â×¶åv\¦6;Ï3Ý1‚pŪîÿ1g `rM‘1©wÕ-„÷z6£Â¡Ó²75+ ?¶:€cÁübµab·Ok†¶cQñqÔ2lMJö!øˆ—cV&ŠŠ-V¢‘¼DUÉ’fdµõªjP ˆK%b •A5æÞÍ¢Oø§~—éÅJñ%@©Øí‡ Oèš¼÷šÅF·%x7!€ Dø š×›}2~4žYPjܪ*‘v¸âó„øAÏFV+u5ŒàÅãOÖ;I(‰]µ¢TðtAÓ! ‡‡ÿN icäÜ콎?5©¬­Œå’Ý_%“,lð !ª…e+__”Æž´îö¨Ò€Jç)ã¾ø§npÉŒ7Ü¢‰ö224>Q úIpn¸ÿŒo-(‹‘n•eŒØ›Ô“'5¬hÓæydœP DÖ7Cúç¥ju„äìeMs„Ö‰u*‘0§>ç¹èГ®êL…Á¤’K `X´ˆŠÉÕÉ¢r($,9n#Y¯7‰A©¨v²ñ¡D± MÔ½Óî†Ãœð+d„S=‰7ð½Ç 0rSs´ûÉ+E6Èìj ð̯9åíO˜”6oUMÆãìê6 ’’ê‹Ê!£,˧q€X-¯y *bl¡Ë†C+‡‰*»Ø(x(¸ðiP¶ÕmW”UÃå¨Ñ±É[XÒ€äpfEJs™êŠ&`©FÌäû>ëÓhÓu(w­œ}Ó3"Z]uþ°jÖ纖a溑x¥ŒÇ®Xî6˜Lt=sX7Å¿3IŠÐ¯º²™é}PÀ8OòÖ ¾áñäÀV4 ™L§&ó2$îòÆŠ–TøelåTÖÜÍ…¤íLuÁøÝ‘Ã;b0† „ˇhn‘ ð—â º9=jÇØ™K´t©‘RV‡²ýœ[\rQ°üª‡Âr¼ë³uÆp4 <•Uz§$ˆ›/ö´0†ÇvO®Ø”UCa[4¹ZºÏÄ»Q¿™_²ú2g(y14gp4Ê/6÷m*ûÇ:MBÂÞ~;âanïyô’†Ü|ó‡*!(fŸN@A©*õÈUOg¤SHˆ/4ê¿ X•3ñ‰S<0˜›°sIÈQð]¸W+tgËlP±@ÊÀmÃ-8›KSÓHЙhgÂG¯û„ﯴÚ–͹U^ç}ܻϹ=L½Ib!§ ÷mk‰M™o£Æÿ‚ gã±Oé„ûTî0†ÂSÀ @-¦m•ÚNÁiͶ¡ùrl¹ï( ë\iù^\ô“Öñ„J™›w„IŽjß1‚dPà…®º×¬hÕq¨$½£l†7]°­Î@Q®ãÀˆƒgxgÕœ–Øð…K†Û™#Ï÷â²pÙà&ÐW.©Ý•®heËGˆ …ß‹™÷m Ö4L !׆»>½ÙÊà..2ÉØê1œÝ›O¨?—Óx3€®L}¨¢R^DAÌ—9Zâ)‰‰lUûâ¨wˆ®ò+Ü-Vj i»Îã²Ü$¢¥Ê›âÎ?+©?ÅÀþwÚ4Fïs£a’ÙÒydØæ×¼ž%4ΚÅIS«ZhsN=æwîg“]Ï©lVƒÂ]èšoô>H8¯oUØhø¼cëâ®ý ¸?|ø÷íN;¶ä¬4#DA}:æt5 Ç=&Uur6rÕ±»„ñ0ÑÊܲ+^ãV+ü¯$Ú—ƒƒI¬ˆ–€ñ$Í|áÍb7+ï­â2ð6ºZØj˜4Ë÷ïsK?tÊñÑô4kyâî¤ï 7ï^ÒxñvïÆî-{ehEDhÃ*úÏq¸äÒÕöç½Âˆ NU¿= –ÑÒð‘=áz¹ùuôé³—)Eë-TKªÈ OÿµB¤Uï'3ˆž­¯Sï©RÔ3-3•& î aT"{Ãá@N Åâ1xÓþüdé6~DÀq¨#î"—F¤OèŒF;MàÒ`4íñ=†A¦0iœ* ‹ÎÀÒ¨,$¾ªI$FPý«DfàHYû1¯WàÕšd a"Fbô(TÆQ®XÀThÝÂc&¸E¢ò‰Ìz+•Ði°‹=(˜Þ#•8V r˜Ü«ÀVNcP}`QFnc+—kuhÕö&†J"3©Þ2\ÓB/oÊåf[.ÌJá€}Ö25=|gâ0lôºMŸËJ8«| †“J$Õž,»} Úè1tkP¹\ÇÅúÝ›œ 6áJà“FU«Xg*ûûŸ¬ç`‘D2Wb²"îòEŸÈÓÂ@Éúàæ€mt¾„FrLäÇ$s $R|Ì¡I24½?çû¿ 4'ꊣ=ÊêDƒ+ŒüËO€ Aë[8ʃ0ÄPôr\†PGó–Fq 9G` Pü¡PĆˆ¥jB²Ù¦éZäÆOiEY Í)#1aw>ÏÀjt+¶ú¬úÛ)‘UH’íµŠÜ«OtõÞÆ:ò5`Vòå4TJnæ¸`+ð}©ÓÛÖ‘2Ò}çl¥(¼öö!´f~µª´fË?tÊLË™%í¯È!·•)GÛËg ‰4g–3íôgŸØã»|]“:¢é]šÕ Dñx¹²­xEpµÏ¡Þ03I“NHd÷"àZC·SkTãÅ*jE‘.ɇý¤«T`“%«Ë’ ´T+K ‰ç7ÜüVZCÅ×€ÑÊɾbÝ%nв›ïÑaû ¿Àùlo¤?»hSÊ=‹Þ‰¯®éαTb`ç|ÁzEª£9 ¼~G;êIEGòl¡¡JCûj ›YZjÒ†Õ)(ÅAIgØ¡ÿ ¢s“· RçöfêçŽä MŒÀòuãÐR-’­Os¨kæ¸Y7`ìûž±Ö4ÿL2Ö$ž½Q=$]GÊ¡®ùŸÌÿl§úRË‹Á&lä¬u*ÆŒÃBoà D4²ä…RzO‚/iöµ6޽`$ dÈĨ˜B˜œ”{kjÅ Ì$—`?ÔylHížT ÉHBnYL/"ÆâÚíE¤î*è`Ò‡ùçkq;v·bY`Ú6Š@ãNTʈ‰™…Ößï+…!ø¼!øgÕyÝdðáY›²šû©~„¹µ'œLMòf}³Ô€´ ÙŸBPÙ ÆÄ^QÑVq]ª¹µ,ì`¤)Æ1®Gùùã+˜åÉO.bl‚P-‘t’蓆է4˜†º\Q r5=ÂÁüŒÏœO&ný…Iô,LRK[K1‰i-œj€ùY*Â5á zYÿ97 •èg.¾8pæÚ[› ¾$Æb³‡ÑY…¡l¥ÁÙÍ)ÆÒH–›"šôŒEOÚ'xú? ;†ŠÀX>²ˆ›sȵ“tâI‘6jnÊ9;2á€fת¶nIð=†“³çcIDikF&Ϋ´@<A÷pæ˜×”‰Lu˜¸ùZ¸`ƒåBž…6ïk`¬ó‚SNÑw—Q#>ˆª 1ˆÎXe­Ç)RUÒzûnKsï<¥Ñ´¢'¨Î\,ÙØx5çVÆ B¥¥*£|\}¶…÷î!0Ê• D›¶±àÅÞsÆ#6ç¬Ëc(ûOœÎúùêúéà„ò–«õØóÃ0vË¡"tÔYrš@Ù)²*XIä%l=\bž“NbÁ=ÅMœ§‹e&õç$tý;Þ'…!½W·Ìî0U«ÌBÛÄ‹r;,ß?gÌûg]ÌOÓç{¦Vˆ$^Ÿ`8›çÝÎpp kÉqã*dtU¬æør4ˆH{9²2W6Müsq<)ˆ™µHFN¿l|MýÞg–9ò¬zæÞ’kÁþÓB ÷»ôbµÈÕbT=ÚFo’Gg=Ê+kYëk.3‘Ÿ<|K£›ŸºßFö5½ä–ZÖòFïßùé“¿zëÄ{.¥=†(²ŠÅ€©@”ðß?¡û®’­·’ sã½r ·™8r&¸#¥!¸k@«N¹´! a ø-!±à9jè¦[¹ÒÏ$n q»"ªî³³©iR+²Â•Ò@–²w<¨°¤¯ ³Κ#J¿òÂ%¢‰!Ó÷–A_¾ ȱBÒ@ùÒ;ë"¿QG´,lÄýI3ÁäøBro7Ò I¡Ì/bU¼²Ìx—G2¨HÍž‘+ÈjѼ‡ÐÑÙ’ý‡Ìì•ÂqÐéæJxÌI†IíÀŸ˜Òÿ "Ʋk0¿ŒEM¤AJ¢‰ž¤s¨ÄÙ¥E¬S Òs?óÉU+;jÁ ¨‘Ô3$û:Aé!•“ñ™º:N¨¬C”œLû¡»¡º{) ªC¹ÍËu-¶`æµ£''Ì~‘¬âzl%Ý“B7¨¬ºê•:d«Îäs¢2÷Àï&¸¦DãÄEÓTÊ@Gð‹°QlÏ'›Ý³/¿>Â+ñ¡Òê äs¢è½C:¶ú-+F:º?ÔRàí»¸†ÃüJËÕdU¹wʈ|%ÅJ® *Äò­»•( ²e+¸¨2©ß¦ôåœä¸RJÓŠí¬éwµ"%™ žÀ$¸"eRZ2LXË+ëIÆ“ÇÄE|‡–«•$ȤÍÁ…<9œ´õ€Ý_€@ˆ’J¡ˆ3´Ñ؉[‘«ÖªÈ¬¶t»€ „-ù—WtK‘²n¡…´|Ð,buH\TKݰùö–CR¹ÄØtEV+±ÏܸÔê&Ö¹‰¹Ì"";’“ÅV+‚ÀYGŸ5f‘Q= iëÀÝž¨áÔ¨**Ÿ5(´´'ªJ¥Æs²¦(‚*°£2˜Dzo%I[šÈ9î)œN¿Œ@Ðu9Z‘¼µ-e/KÆ+¯@ÏÓùaD51»Å*µ¼ÀK0™¹árHsfTkÄ k¹AÀÄI!§@”Èx˜ÅD¡Ï 7£ôU¨àØ*¬–Bú‰%¨ˆS0áÜ£Ó2ÕH¼,­vÁA=›[-EíÕIÄ¥ƒÏªÊ|€LpdLÊèK;ûAòu¡“‡ëˆ€#x[P}¼à¾"?²9Aó0´´½ÅÚUÅY3,Z !tð3ŽÂ{ «+I9yöžt‡ÑËPQÍì“ÙÞ5š=¡ÒUUŽt¬žà¤6uð]‰¦U¥[/ÊMœÅ×:uEJ°_d‹¹ÎÒªfà­ÕAáò38|´Â#¡ü¯Ãõ ŠÿP̬1EHDõáÜr ^ aC†¨ÜÑë· ]!IJ?d8›ã`¿ºßÄæÛ=A@5ÆAú<·<õÕ´b¸‰ÇZßâƒ7ÒâÓX‘Y¿dŸÑ`£5½w°µƒÉ“Dõì®jBPê"A,ßL(¬ Ë¢XíÅ-!¾«5KR͇ȤK$×fT‹ ß+yÔJ!H#¾Ô~)B¶@·2o W1¢å ²jyÊ,êr‡ët]<@8â%à€4C³U@Vü¥LÁÒ?íÜ)ÙTTDBÑßåÌ62qc†R ¼¯;‚%ËF,©GX&S¬(âF +ØML?ˆ‹ «&\_Zè*Ë4«Ì£Z÷ k¦Kí‹‘«Š¡ƒ3â"Ê5]P°†Ò{¨Ñ‚:.ÚßÑÔª`ÆEŒÝFþ]8ôç€=5=#GP¬‚Yóa·´†P‰ •%X+™áµ€*Îjõ¯a1’bXU…¸L¨Cs!¿‹®ÄÍ-WçAG¤ÔH£ý8MKŠùúËiž2;ÃÃf;– É<ù6 ‰Ûœ¹T$|9…ˆƒJó¯ '6šµ°VGº‚3‹ËRZ]ÖS\ЄN>Vjب #ÕƒÃÅp‰aÕ„E€6êk©»›žD›ô)Ð2k£Ý2Ñj!2¨ê”Í|g2s*ê‹dK¹137(–±ÉuŒ³É4Ó”Êò`•u2sicÛ¢=ýÈÛ †¿xÆa./Ï„¢boʲ2*ÝœAMž3{œÆ‚\‰mÛn\RËÿúÜ[¨Î4ä’‹àümiŽSQaL‚³õ0¨¤ùšvc'¼¨MMÀ³‚Þ²ñRP&SQËÖéêXÔ…Ïa¡ôûC:<$âÃþ%6â1¡Í’„ˆy6³1k:ZiÂRWCÑ9•C÷«Pæ›â È6ÜÏ™›»u‰•cî`>EàÜ*àNsè[½›&RãÆ˜n6·¥BG§†½i±âY€©Þ…Ú öG„ÆÜ™j•c¸ãÃYu­1äµó,Svœ¬ÛèsôÌÐϹj‡ï ®Ï 5Žfçïh{èÛÉZ'X›¢[j\z¿*dZdPàdГ¾ãOä«þÅäcYRIBÁ‰ÔÛwÏž¬ FçìuveÝ,Ð^T°xØà¾ÉŸ4JžtyñȆTÇñ‘þ |[‡Ò#¸¬Ðåc3dÁ„ °Ë­Ýì±)²RdšN‹É­îLð[©!Hòë$ö¥$%pfТàóæ+Þ›•^çlQáµ6q’Å&ÄñÉÉ÷ &ÃÉ×äì¶!ÝEËη+çíýêe¤ ÏÒŠ¤Ö1)cïF™B9ÎBâŒPÎ&˜¾Ôæð‚AÁSÄMfÁž`N`CûåJú¯ ßhL°¯9ÊŠÆ“óHrjœ‰h‡ú£lñÞ©>t[ä@(“ß é²ú{lŒësÆc ‰^Œ T+j;õe*¬&ŒÍ±ßÜ›û¥Áç2ר´×5lÊ9Þñ5p‡îØÐ¯*óc¿)”[“<-áÏÖ!6|ðAR¾*‡Ø¹$.êcØàËþ û¦^ ÌÖRºíQqËÈ&’Ò: ö&梔¿UrcÉæ‰Û! Eq´`ti¥Ê½<ÈØÂýáÔþ¨7Ç÷Å’îyê^w¬›Iîø„y xÊRHñ®?S½$¤õ1›À£//z’&Ÿk¨ü}äç{¬Aˆ1bÏD—]ˆ[ÈÀB*&ÒŽa ¼‘ÖaÏ®g¢àêbàöaЫ}íÁ´{µTºw¾Þ2nÉnT'/õ¶ÞÎFwÂ!R—¥¸^ýïXjlï'Ø(ã¦Rö¡úî¶Ù”¢þS¥Ûä¸2¿î]6¶‹»¶¯÷ê¦9Ëœôíô\ÉØíÒ%¦ÜËü‰ÔJ)¿øÐeêãÑ#—k¾æž+eI [Iý’ˆþ‚?àÀ(D& †@¡Ð÷ÜD Åañx[ò5Ça0çì†"û„Â`è¨'À¡qx|2e-I °xD¦NžC¥ó¼¦S~C€”y<.F¦JepI„.NB^µyà˜‡V_UúÌ:‰2†Jhöp$ž‰4…ÕK5"ùºDÀÖÈ4ú q´ÁWú$t_}]°˜'¾'c½Åa7GÍž³!~Ôâ¸JÍn˜žIáÒ› )%„Tl“+äÃ)jÀ´ÊÆôÿØÊ¢ò|¥vy Æ€i0mûþ¤Vf›v:«¨@æü(žðÿ¢e-±Zͺ~×€û}¹…žG ãitR&~-ÉÛMa¹NG¡NçµXGØ£Òr-é’Îô¿Ï# 벊­m"t“¹ébò€Oô‚A ¼¯¸Š“ÌÿŸì¢²…²‹ã(ëA¼<Ù¦ˆJˆ“»KÊ 7‡ú¶Â?J#衵°ò³ÀÈ{jÎkrθAHÓôš)çóÔ¡Gë´Šƒ?Í2¶«sp¥0Ú ;ˆªí)¥Ñ„€õ¦3#ƒ-§(ªÈ˜Bìchå8©áé:¡+²Â.ÑÑø”»pjQ9KÎ$@ž+n ) ÅÓ4rØË<ÒŠÑHJϤ(J¶È0MœLèKê€ö&’Éú³É«4éB)âGE$ 52?ÒT¢/‰íÊRÔÍ&»é’F”ÓnqüÓ·¯"š>m‚*­¼iÀEMI*Œ£Î§ l°èêÏk–û) ‹´ ‚Q'ò²¬¤sº&¢\Gó$ž#(ÔÂÉv›†„;hMÔˆ¶obÎÂ×HV –ö„$wˈ’ÒÇíNöOΟ%¬öíÝÈÓé‹¶0„ 2(•Pwɱzºíöf©ŒšC!EˆÓ-–ÖR#•Æy:+lC•¡Ö½‡OÑok)(ÓÓ>­Ï0Óòæ€A÷ª<‘Dšú0”:³ÈIKü¬Çõ2wÜ’ê4øM›DûI “Ò(ŠëÊú\·wÕv~êïÚC!6yþ„¿€ ±þUçêGÊàLÔ;†!yõm#Ÿš>Å–€4-ÓÌheÏ¡ „%†-ÇÇY ŒZ4ÂgM&3ÃôºŸ&~'Or â¯Ð¾Á ··å˜öÑQþk_o̬*9—>zIh/£ù裼Û3Uk¦<ô}ëïGU2C¼`Ã^D¥”È$pHZ™.Šè¹Æ°{špl®'šÓˆ\¯ñN–vÎ?áG;oAÑ)ô–âKrƒ9nà6 HÊ#N4Š¡Í¾~µ@#OMí«òà”³E%$JÀÁø›X&ˆIcCÀŒ× 4C¤8­©ÒìþÞ@Ñü…€¹bG¼{"%nB!í"˲8„ðöäöeËwzíL£È±í ðAr]%“FÅ]Î’Y*1€ !Ý6±ÄÚ½Æ×Ÿã5^q­cCµ>ÂdN$®õ|?øïZIG.ʹbdlæ d‘P'ÆÈCÌ7#L­°“Æ+›tT(z2X.j—²Äa)Ãu }«‹pÈ]˜N%¢ç¢Y½-ΪY®÷¬ïÔ¬”Š}œO1Ь\C#éÞµÁü°eœ\6s~½cé1@#ùte’Q æW=Ø”Ý&‰À¢šDñX„<£|ÓÍö L4$2t¢>0€c³„#©Â8³1øVdù†’°N•´½9+~¢„ÕE?q©âzè&†¨Àé€W¬žÀ¨¹P†qbìOÈT&üâI® àFº(é߆ê¼D~5ŠäÛföP¦¤êHÔLV‚©”£1iâŠl¨‡ È‰š$ïÀþÇÀ ‘°æ¶ ²žOL- Pä½$veobjI”}iB´).GéL¼„À"itìŽFhì“ÂÑ­`ìÏH–‘Jˆúˆ 2(J âtit‚«Hf±Þ¹§¬ŠD¼¢Bx2¹"É.Ã2¨§IöÑ4ŠdðÊ) B¾¥i´Éd.S¨:÷®¹JTáó&2ê‚„úÑ…N®oPª´Ë*þqf‚ðôÊÊZ:-Ï4n„ÈÒcžWæC±ú!èÞ’Ï’qoBŠ(š)»%‡F~iìNITzɦÛ'@Ò¤*‡èú”Ê0킎e.jt nž&N ¬V‚îéš6b²¿JÈf"¾gÉâç.í õÇ{/­úí0µ/Í:ñf¥ e’aK¾ä ­Âò¼Ù`T‰Âß„à¹M/3ˆ`áQ2ðУ­Ó1ì:rv¢JKÉ'5ãº;m êtöòœ$² ;§—ITÌ‹`zgð)‡ö¨Ïø‚ç p ;Î6wÇÈI­zýï¼C°` Î\‰f@Û)DŽåˆzÇ­)  ƒ.Yn2’ñÔjL`ük¿=H‡‘zÍF–sØP3:áb"iZ¸/º§ð¤ƒÏë k1.Ššó³?²ÌL“N¡ÌRÄ0lzÒVy.î¨Å¥²`‡‘&‚Gw¬‚[-9B‡ÌyƒH¡Nhy.›¹dhìˆÔI§zæ’€Ð''²ÄI,ƒôütX†Žd èÓÌŽÈóRýè±C„:ëà!)4;£õ(Î >ãß+ '; À"°ê´¿&’tï”6-D?F|¢R€ÒH! >ž¯|•ÚzkØ¡s)3K¸S2†ÞŒ0Ep˳”¦bŽF¢¾d :i”ˆB¢iˆ_€2ºåÂRÁ‰Û$½¨¿Ê.Z H“æ@±“–u ¡°‘òf6GFeè=ª)gøòŽVá5<¶’ªR¿+‚ èà—'Éä=‰)!ÿ6‹aëÌÃN{2ö`•Þ"²U¦µëjïõNÙÂîåT¤’ 7ˆdŽUFjô€l°r+vÃzës5S¦jNü&d:‹j÷s<¾Güwª±UqÆr-MüÄ+”…’”‘êHë ºrœ*Oú!( ÖâÝE=Dí’!&ˆ#«ˆ ’KÄ?Ëk?bIÇ–¯aû@UïÓc ö^BV§BìõL2¥ðÓP`¦V.ÕhTtp&ÔI9 ¯¤Ñ_D䃧½6¸çcŽxÊæ‡„¨³’`§´"òÑE´‡2QÅßH@ØõM.é­ÒíµlÙÎÁ`A÷`'z“ë|„àd„½2, 9ëw4Ö¬œ°±zãây,ª45­b¢¶ŠE]lº¯6tâ˜Óé?zƳÀ’ã·bã¶±Œä€‚:óaûFS8¤ä©!Ân ?Ðm`†¤ŒQ?% :‡ógAgù à«ÖžüªN2†¿´KÓ TðÉ¿«vT‹þ²¨ P1 êüñáóAé0ߢO42Œ?j€en\•RÀ„u‹j$wvÒp=³AqžV}/ •=#Ùh°¡7Ôîb*$s¸ÏÏFùI¾®×*„*ï8pÛgÿÎI}Dmko—PÄöˆuÀÐôî!ø™QÄk3V±…:ߊe^E£ºfH€Ói¯£gN¢I-p(H%l•ü°ÕK‰øƒ Õ‚xÃ{p¿6•qo™´l¢`–)kôÞÔ´2FCH:‚ívÖ!qùéÿšr ‘äÈ}Ì2 k3ø`CÐ'C ‘€OÔxúB€Ä/a$$-Ï;h/?Õº¥‰¦b˜D~x”2”ÑȈ>‚ˆHGÝXz$9ð|‘ú#gç=j¥>‡÷âª)Da”o’ðN«ƒy=G aèIL:þLÊ2¤çܤŽ\ž+ªøÃ»!*ÁÅ3)}bˆ%²­ ¶òÓĩҹFS°"jœÉƒ¬–ìƒØn ˆ¥˜„ªŸìz¢wm FQvâà ‘Ò3Ü”È%Ý–“]DFj]º†Ž>šâÔÛ¸xzä|–7°'©¬8×ïýésóÂø`h02ù…!€(t0ÿ‰C¢€ ^$ÿ‹€_‘Ð~:üŠ?¤‘·ìž3ˆE$0@,‘ýÌ&èÌÎIŒÌ"Ùô|“¿epødÊ/Ä&9¼\ QÎæè…)T«Oª J ðû±P%Ò9$†a@®ØŸuˆtf!`®ÐåPÉ„f]]¦YãµÚTb%¥ÑðªÂþ´ÇåÓSæ»×jq+¾D'Q*ò}lŒß¡Ò†G;n[-v+¨l×Ü!›HŒN FsòKf /t£Ou•7…«±SÀ5˜–¡ÿCË#ÑúëÓ±®Ì8àiŽ£’aäœ UW@õg3Ñþsþa!¤wyÙô÷ÑóÉ_j1O!üÀ/º2ƒÊ(kb`»káøB*Òj‚" ž©"퓆­3@:¶l²IDûºŒ¬ˆ}E­ °$É;Ôë*/bu­‰³:í*-úé*êÞ‰F(ºÊ‡Bï‚J‹»«cb±Æ‘+˜ÄÂj¬@«Æ "pš( ñ&>i’„“´ÌȨh„ÍS:€§=ª |Û=ò›0Ûº)<<˜E§Óº /gòÐòÌíÔi%N'úô†;ðÀ 6Dqÿ5À(ÚÀµFͪ%E>ðñ) ´ÄÂÄ KÄ=ì{˜¼ òNî±ðqü M)Dä—MÓÍG!•z†~¦bº{Ø®ìüŠGà‡µñ»' €2 ¤“Í’z>ŒÚt¨˜CnQö¼ª+’¢¦¤òÈ/ËìM%,Õtù±/B`®ÖÇëÞÛ<ÑE9£ïM˜®ª*Ônÿ¨°ò,‹Ô ³~Ý ++%Ý­Â+…DK¸ã±æ¶7@§ÌM¼¢’ò/?W5¼B‡N*;ƒc Ùk,H‚]?;²æôQ‚? Œr€2擽Þ¢HÞRÑLN “ÓÌ$ÇMÇ óç©O/{‡: ÕÔ‡hÈegÕ ,±b „"“õÜXT².zî©tÈ~«± `h¯O²j{†U{ÓÃÍÄjzÎÊûqK³}(€qÞ"û²ô¤Î÷åÒTÙµoçê[W4¨ëæÕqš´òé¸röóilj-”>ªSÑ!³OÓeÔî<÷‘#ì|Wvhè•íxôGåÏk€oKÜq ¿+ÙÔJô¾³ÕƒBñn‡*’{UÖá®"ª@¸²Ú“"낤3cÍù@0\Ã×€ wç*±{o"M€Š»×:LXI9Oie=¦ PÍRÐWÏ)¬¾r:¤Lë5ë{ t}ÒSðƒ@&@ç„BˆÙÝwŠ‘A4ã†ÞÛê7£ùE;tŽAS`FuË5äF?‰tUmÅ¢}Ñ“…wÌIíÃòC!Ðwª)¹-ÈåÓÊ7ˆÄ]ú՜Ԟ£Kê RÄRB™hD1Lö þÌ¡…O¨µíÖ×[,‰Ç¸Ü¾Æ(çŒJUOýµÕ¢Y•¢Ø‡¬õôšã4|×+Ü+`ÇË^k–fÇsÄŒ{lƒDQc¢Ù K™»žw§0®–ºHYto/ÝT´ÀŸ:šÙ©Èd¸¬ÕCº@$fO „üás|Ò&½2Èã!>“¥PËC^þã JsîŽ&wöÛ‘l X°œã‘˜F•é^À.u&dòK‰ Jn ±ò©3m \J»bo”צÈ4D’M8îY].–ªfQä¥B´ÕÔh(es´ØüòìŸR6>1Ð>æì{™éækGÉŽ Û¤NzƒLÊBÙ ùÃvq,&ò>ÄÃè5ämU§#¡,¨chƒõ¤Oòd½€mG^¤v]RàùU‰ 7„‚.R>N¦t×O*Mƒ!ãöòää6dì)§“èI› Ý›ÃèÛ$ã–£É ™ZƒöE“1HùÝ&iˆ3©Cñ¯s-4“¥Ãm0ˆQÝf/ÃNcšûaM!rÍíÂ+ÆIì«Û‹$Ê• Øs•ýA•Ѳl [Î=i°‰É/¾V PÈëkA?H36™Ûƒ“¢D0îµû0À@Ù¸ºȱöÀ"Ó¯’Ç7èdÉçP x­ŽÎÛD(ZCÚK—sÕÙLEÐ-œ ±§–ú?[Ùfˆ¶#ÀøñKu8nXæOs˜~“Å«L.M¤7 ÑTâI±,@ ê[HmŽÉ *á|Ôi“µ¤óúë*ûgdõsÙš±ƒ´"ó8ÿÄvËŸÚ‚³2ÞãØ3 áˆÿpŽYèRˆ kê ý•¡¦ÉXqÝ]¦ÔÍŨ&¶ølý…2g7ýŽ ƒS:4ûËèkK‰%Ç´zÖJÓÕ~e§ˆîHs5ôQ÷³•ˆy©+ú{³øþPWP°±Ššø’DüέeÒ´·µÙâ8´ãâV/vf©/ÔJË¢ÈíQNoòã Eœ$Š¿w³;-ÈLW40ޱ£9'ÛzGÓl¶”¾Ú¬¼±V":¤ þ¸ §£È•»j¶ä/º­¥k-Ý#“h™ÂCsÒSûnv WʨÁ$’p'#²çgVš«wÐØQ©CK/al¶^QñµyË0Ë–ž²Âö¸~iî÷Éú4,¹oV*@ÀÚ®3۷ܤUSâGJ¸e剶c‰ Átáè6Ì”‚S÷ËCäCÙIþîM€cò„á"óÊ*³’¢Ë³6sÔzh…`œrnѱ’ 3çºóO4GÐx²®u·V'jê‰Ø¶žu²ï9>šVY7ªk¡ia¶-›œÍfݶÄä:–OÃZòHŠÜ³Ì,G%,y°=–Ù£^Ù*>·÷£Ø#ó*Ò K^ã¦iiÄŠ›|Òl6È(?/:‘]_<÷µ—ñ3è:{± í¶ðÿ^Ä»$ÔØŸ–F±…¸>¯^'ÛÙu䊼§@ÇÚ$A V <ñ)½‘FM$í ¼™b£€Ò‡9eÏ—ªÈsÔPýlËw«)ºM+ãÝj<ó7»C#sÓ±ï³áXblùºÙ…©e ž¶ý°q I„¹º\Ü.‹ü=WÖÔñò|났»þÓ¤™Sf“€¹‰¶5ú7ј*l ƒ/Ãr$z{ŽJíµºqˆ“¼(ã½K´5N°ºV¸ú¾“š qÕ™qVÁôì²k}­²•úÊ  6ãÉ;çáÎ$Ѽ³bÿ‚>)¿… s]9ü ™k‡úX%}«a["ûŸ?ëÄ ë˜Qi’àˆ5ᤫ°Pô¹ }¢8¡‘ZÐ7ó½'«#ˆØ¶[ÿ´´%ˆ±=#Ö8\¡0®1õƒÅ»s<>8Û¶½I…„:3°‰óÁ$‘!“C9½C%Àëª 2Í7Ó  óûZ3 1 ’53+«Q¾£*ÂJ°ZÅ 821ÚTI‡ð¶tSŒyˆ"a~êG.SUÁ¸’?º¨{Æ A;žØôµ© (ê7[:ÅúÏ)X'a¶xÍ1s£/‰ ³È5±”"Júº3")ô;À-£‡¢‡2Âǧ»QsK"–8!öŠé?.¬–*w/ð—“ޏxŒ‹dc h}®¤J &Ãî»ëî–SêŸÊøF‹ä©ñ2ÁA0¥ƒfzØCð¨­#xÃZÆ?HÓ¼þGP{º²T» 4›ß#¤3Ř«³H´ƒ˜1 ¢½LFsͼk!Ä H±‹8¦äP¦[—ÁyË/Z»Ž<0‹ô›€Ç®x¡¿-óæêT“Ãþ) ¬0™ö Ñ¶Â(»ÑTI«,_%ûÝ) Œéo:"…“À®*禘Fi‹ ©ÙªëÓ¿¨Œ›cñ¼›y>Ü•5a`,L Ç:oBvIȹ¢æ8ñÉ e6ú“BBËL,š‰©ÃÃ!,¤:¶áÞœ³³ Ú~¦Áø&[¾‘Zëµòæ"ëKKÁ$1%@´Q£2´*¡©»X.KÞ=D@Dr*ËK¾ª\‚8Âx·†K|.á¶!¼3ó܇Ñ# ±*=7,ë ÒòÂs£,‘J‹ÝÄä<ɵCaH"eÊ>ªÛÇÙ¼53 "›¼* Gc5˜ ô+H/*#‹bçϪê•û¾®ª µ4ÍÌ“ {q‘C,a{aLÁ‰£*ËÂÑ¢‹ÆÒv7D±TÇÙÁÃë”OAß®2gIlü.°‰?73VÉÿ;ˆMå)LD‰q69ÃÎGãï>´¬kUÍ”F;ÁIJ²ÉÁ¬£•ºÙí‘zrK ÷ÅpšÙ/Çzð€ã‹ˆ¥.ÍÉs¸üåÌ+9Œz9ŠˆÇÊ»U®ÉX?œAÓ?3-á/ª ÎÇÕ´8µ4æÇ  +‰s¾¬!»P“½h¶@£R¾+$ÊÂ\$ŽaoºX/Û­´È“òãRûÍ •ûqÄIiËåūݔ'{í‘{=ªR<ê*¨šZH&¬´À²SÄIí›ð:záHdA:úÆ>#‰¡šË)üUÆ…c)Ì Å|i ôNÚ˱RÖÊ™P ©¶ |ÜÕ¤•½ÙæÂ¸ó!¹i±3h ‰EAÓ $ð"«©‡âóÅì*σ©r°%¹´ïUº‡ÈˆJІR¸­Óž,ºgPñ. ‚ˆ3w)b©I/m4ŒK›×]R(;@*#5AIôTÖ€CÒ z~(ÕYˆVáUC:–+ǶÕ.5´ƒn,‰ž?ª1Ò#3Úæª9äWÇ™ °°;åL‘03ÑDQô* JSºÌÐô8˜ñöÒmDùÚ©]š«31´¡¾.d‘yõ)»;H¢Ð}vˆý¢ÙéÊIìDÙP=x}°!ñž”é×ð…´|K‘당½\¬ìÕ¸ax¡°!? [J”ƒÑYˆ˜°@(ŠFj÷¡í!˜Sð1|$Ø= ¬¤U3s#ª {zã`ì£`͹ÐpŸS Ò*ãÕ¯©‰RÛº”*$]ªg'šö³ìx[ó\eŠÑðîÇrÃÀQíÀ9©+)¯+³Ýä±B…*i+”y_¥Õ‘ÙÌ?Å}¶FM"Uà)eÙ€I±†(ûØ”D½» ´3²»ì–l—ÓÓìÄǽ#•Ò¸)Ð…\sUÒñÏ]YÉ‹‰[î­%2´ªG›…@É-E"zE`ˆ=™i¾ÕÜû`-#kâ´•DÞXk§<Â$«-ßÅ /¡cU”Q—ðΩø¯mªKú^Õñ±RÒ)údŸÌ=ˆRN§b¼–)Y”JÂyC:1{&r½A–Øî•™tÄФ;ë!ÍÛɪêŸ-™¡ìÎè°C4ÝŒP‘+U5sžF‰$(”{†›èhãµð>IYÐDBª•A¼¢`¬³ËÈ-¯´Á^¾‰ü´% Ò„èÜZLqáÔo] ¿>ú.0ÇÑœÁ‡Ñ.FlÊK£I[L”’ÕaŒ3™UJl>ŒÜÂ’0#W¡ÑîÜÝr²ÂešESéeKI%ƒá43Oá{E%3ÔëÉs­Ð H_të=%À¯óðL8^éöàÒÆ S¾Žèצ5}¸Ñ´ÄÌFáæºz pÇÏ«^Cò+¨Pô eÉ£©ƒD°”šÀa[]z›45)ç Ž !W$H‹f>X-˜Ž¸RgA š¬©ù%[©•‡ã^al.¤„Ð?õB$Y‡Ì¡ *­²¼V˜}¥é ®Â>fJ$Oª#Êu½ éô-‘e¢$$3n-%ýdc@¼Ú‹¯ð­2úÅõ06A`]äÈ .#—aLh,¤=•’¨')¶X-wÓrñÑÞ%Âb9Ï\uãü`l¹eúisÏ™Èå$FÌ‚GŸÊŸÛ²¬ÊÃ?h‹“aÕÅòxEÐQäÝÂ!Ü›~ÔDœ`(|ˆÎ3¢­&»)62jÜ"›†b ½–ÊÞÃ@éìä¸d+8Œ;èæ#"‡ô¼›¬ÀÞ{cÅ|«VÓÔðÿ|ˆf¤5Š‹(γpe>?€>™«P‰m€&¬ŸCf¼Õî€åµií1ÿ,és딣E!ª^”ÂV›ÀN«iɰ­)i Í^gF ;àœWî]<½JðlBX žT%Äì¹–u¢½WëK,"ÙðáÇôm¾ŽSÆÅ’VÂo’… KIÚ˜‰O(~'.ÂE´3Ä÷ ɤZ^,)kÃí¦v0ý¯›ÁøóX;EH(UÌ=çë¬ñæÀãÛföÔ{’ß°ž§µªÚò²¤{1Rl<R«(Û^±ª¤zçà‘ÚmS#æ[H”Ú^P”+£æ¬Xùä#¬¸àÛC.1ùš«»Þp¤·Ûä*5[m9Á hÇ)ÆSår*îˆKñË'/î.`nÅ9èæV»Üö%€:ÅñÂ.lŸ*UˆüÖ|¿õXæJŸ\%l†æd&‘Á­"žp¤¼WËðÿ»(®ò)É»éSÏÊÊmg*ÃÇ4ŽeC¦NY¯M0¨®›gUEdæ2?ONú}PÉ ˜eÅ0ÔC`d.çÕ:/·Kþp£§à?V} 4d¼Ùç¦ºŽ‘Žƒ0Ь:N¸·8Åâ´êí(Q/ÇEeó%qÅ+úÍ^y8ù—vúBÆòŸášÁ[Øœ}—µ&Šýî–Íh 4:7ÉÓê—!0ßâ¸÷=¿"ÜèZËžlUI•²‡åM‰{c–Ô$‹'WÄf«+¤Ó`ïj.,ï”'‚ËT”EնƳ½ ÕÉâ’¸Ã3èÞþàè~ÞDmÄ…šñÀ´¶ëíP¼k* òj%SJGÖNqZ^uµæjÏæ.2Ú%‡š®}0Ë1ˆúU|R-‘µü‹Á6>IJ®Þ¤„̃!2Y9Òš™vK£­Íï?¹2Hyo¯Aõ°½ÝzÞâÆO©%<œÞ? ûžŒ[`Ûb4%„2Pô3yYEî®I€†€).gåX»£F ËS<“”c€`A«Çé=Amcê÷È÷µ¹H}‰Ú×—w ŒÂÛ;eŽ8¸ÑA¹XýTÚ‰ëÃj9…×d5\{¹§cÆÙúHüAÔ&Ä7FÀQkÇÖðéÙˆ‡†¼.ïù¬#¦_äŸlT½Ûi¬Ÿ¦Ç ;OÖÙ;Lƒ{5ß¼ÓO'¬é%\vDÑÚ-Æ€`@8#ö „!P âþˆbQô( ƒ?_ñ¸@(úC €8Ûü '‘¿%RÔ©ù ‰@S8ìÌ.ŽÃ#²8d–q†IÀ‘I- 1ŠFd³Yœê;@†@£²év)6V_u¸¥ K†Wdï{$Ž…#ŠN`RÊp]mŒÆk i~!m£¿nvª¦6ŽÆfÒZÛîü˜D¨VG¼2m6°@±ó7ÎW ÌOcxé.ŸˆaAZ8Îiÿ|‘Éc3ðB)¯FæÓΞ@®Ï鵇a'Œçõ¹!ûâp¶,Ã*PTIÓÈk3)zy.ïÀRX,”$ë$îÎ(Q!·^K >Š•L‚ËÈx]eæŒä^1(þbY~ík<VÖÚF|!Šô7ÀŽîQÙZ=Ž ¶OPŒXÙõ9Æf<Š6,­yeHý5ŠIøÀë)Ì),¾y®,æ4^á"⨇÷…"S‰@iɱ^.A°Ll¥èEq–ç^@cç•mi1jF¢ø^6)O^ œæBÔÖD§†(0ò+[Vc”%ü‘MË— U*&É3Î9Ÿ°ÊÃÀJªå}VÙfJKÊôî#SMÍÚÇl„\Ó'ÁeCT Ú6VP•MË^R•l­=Á› £g.²²-“~Öt~h0VˆÌìÜ¥;B§ÿ®ñŒãïëMK ~çÞ¢pÄèYƒ²§ÆåfÍ=>®Çó¥cùÒ('_2ŠÞæ¹MzÏÖLf\‹6M#K3–ÕÆ²«Z°†[ otËÑ{Za’<,žÒœ3ïcF¬ø¤´ /ŒȪ-‰Þo%ƒkº,óûÄ…¶‡’aÊ’:ÜQ‘qvb"¢ÌIë§e†˜·´Ö¾_db}prîúË"O¾Ý˾*‡.¸ ^gÛÓݱIŸ=Gij093%Þbj¸ BΣ>xâïäÓeSí ß]Ó{q»M„ÎISrí‰üóòó™n]Ž 'F«Â6[š¨‘&m–œÄs«6=ÞâÕFæÍݰÈGÐå@§eú¤¼<’¿5öIHæ 2«¶$¸¶mŽYÃB4“xÀwi ÿ£LjˆÓgŽÌ¹ê–+Ž„0†J}ÎäéÃXðÅtiNÈEéø†/Ndâ@ZêBß ¸ãÈ&•áøSⶱʴsâÊhŠ0Ð:ÇâÖCà²Ìºk"lY€ |l&©Âè娭î^ðöfZã›ëŒðFüKP‘cvÀB@&#¬dŒ÷îÆ^+øEgwn@·ëv>þi\£B¶Ú'i–éÈ»f²ƒkì¼j Ä0Â*ŸMXÔþ©¸@$ÌWJzÛËwOZÕ*DlîÅ ŒêÊ#*èí ÂN[ª>?Px˜-öæj %KÜí×êDg-Ìœ |V¥"! ð”ìÝ K¸‹+ê’06/§Â5ŠÚÆŽ`ñÈfÕÇ”ä¾Ýñpî‚Ãé*ÐÐX™­\æîZõJÔ» Ný dT¤* ð%¾$,ÚãpÚ1‚JZê¼þâÖHTã°‰ fT·íªóæ´›‰ú°1~•d€0Îßà ƒñ ÇŒ¹èðMí’«ï®yé>ãpŸD dº‘1[n} cLgæyhdÆR"H¨Äq6ú‘oE*fÌžåò*Íp—¥Ú9âwkõ)P£¢Z­QîũާÏHÎB”Œ*ð(‚”c*"É+1ÿÎx·èê#P&pA'‘›%ž¹CN’uk¢ŸFCKÜk(^?N¼É2‘+Ð6b% ¤¬HNFÇ»‰¶·çd›òÓ)¦ù&ZÂIðMÐÔ¾°º“"A ®FæLÿ£YéºvEÊLðÊÇ0¢¾¦M ŠPͰ«ð£2ín•….èN'"dËs pº¨îèJíïÕ -z~K¾¨ñrÿ£Zêª!OƒøCQ -ê§%¯ì)ñ”lŠØ\žä FøðRƒÒ¬v¢DPg–òªÜý‹&¹Díѵ,“8 þ¶Õ‘4€Rh¸qæ†ñlC#0©æªŒéNÜÈÎeJ¢U( ¥Ñv«ó°DÜþR ÅU%â|dÝ7è.ñL¹&“&†iO,!öú¦xPQAgF &Žª/Ò†E1i"Ü‚ "ÁçC®Pµ3ÔZ 6áðİŒcoF¦í "ßh_Åâ4Ñi$ƒ’ÂsÞ­Òà¹íº…ãà°ô Ñ ¦Î†Ä•8ËíϾ©úkü1óªrý*ƒ,³ll®xý.,°3tpC£ æîÓ:BKŠ r4Å%0ô™@Sæ€'0HRè  #C¡æ~)¥Cb¢Äí%ÉwKÆ!BB Ë¡8lj힢ç@'ž‰â6#FΨ UF|«L¼+f>4Ézç†ä% ć$«~½ °Ïg³^—ò¢OoH£þò#?†_F¯POoØk‚@ãS™Ks)­Ï%u9åÚšbæäFª…-0âÈÊ~.ˆ¬q ÕƒXÜËòÌÒä §7‘W0ºÙu RRâŸ>†UpBK JZ”îÚð:í°;5ñEh¤S.Ž©0ªÁ%!„„Yî-ƒ_E//2ÄO×;ë.±F'%TÁT ZPÈnKMª«Mˆë)Ø0:ª1±)àøÝ¯ÍaÓ³"hœc±‡u´fѰ)â“£3Ä´qãViIPÉúät}L² S)±I*úJ\#âAV_,åYUi8«7Uäã„ÕŒnPƲªÑ–Jâr*>Te[S©Š%L«Ñø²u¸ç¶(ûÂbâ7¬rík‚¨.YUBd´Ežs ëcøNԱǗID‰³žÓÂ7Oöž5î9¬c 'éåepÐe$t¯ÆèðÊE¨eAäÜ‘¶Þ¥É{T-¯ô¯®õ^ÎI5 G&[/‚³\h@­C£ ö’EÑå#0q,Ï:²Lȇö´ëEéÖÔ§QÛwBF¡Á¶gÃMÆu’ŠóAõqï%qÀIrvÅ#Ø!PÚ«OqP¥àˆtÍF¿ †5(¡In?’<$Îʳ L„öYÜEIÔJÓî«M Ⱦñ÷n£1<ž¯û2·¾—ïð—r†’Ÿ^ÚªZHQÞÕñ6ÐíZ"6h&„RJŽž5t>Ÿ ÷îœâ(ÔHPÀä’.F1ΟÐ.W1ίÃ^%ůN”>¡ó4,˜‡íê?ð¡vh"I¦±ÊêÎSçJ,óP€D¼–³v Q*)l¸ˆ4F†¢²´íga3˜éduw p‡Wáö#&ð)ŒIJTdÑH’"G*KXk?‘å £v°bã#1r$•t¤²95+2‡ú?èU‚eÏŠ#+ŽÆ[U¶©?³˜$ª>ýе2,Í%ù œMÂS-Qk 8Âel› ݉ú_HÊ› ,Œ°X¢É_öÇ'$\…XxfÄì«åÚÈ „füÝ,í« åìÿm_ ,Ü£ò–4ÖÊ$ì''¨óQwû ô • ²ë3æVϺÓvD¥Îø\µÅ˜’V"AH”bU¸vWJ¿8–ÃKUA{+½kDHg ”§&ìG9¸ÎKk,{"ÒI¸B¸êxCQbNB@Ÿ®‰v“k.œüdwI¢)õ·uBù(噃†Öøc䌗·‰˜©d‰¸í4¢E˘Aó>u.jǘ°RQ;" ÁiCöøù½Õodí_ƒ÷0·d…Võ=×)BϽiúˆfq\r•`ê·™û¡™›t¿gâ!}©wkOºŸ¨Ïolíò_m‘®µšˆ!Š>šòu Áîïr4¨äŽ ç/E:lýE{vÅPˆîmUÊÏ3¼Pˆé$Ê’ÐHÕšGjgeb+”$¯Çz,ý·s6¦é„5—8û×M!‘<ê¢WL<—Ë9•e¨¸ÌÈZ:âgž·Ó*]•hÕìGwÑbõÌäcøä4Šz»ÒK6¼Å]h¤•9 lÜj*jº©f£:ó="—„»C01™ú‘È‹f|šd˜Í«’ë}‡®Ì'zûtŸ ŠÑƒahg’‹"ú¸ g*c£Îœ¢—oÐõ:¢ë ¦Å} v}hˆWy°ö›™´7qþ›âmqDŽ@5“QATgRÚ›Ê@ÖÃ'™q°yº€6.™üU6v [ƒq¡hÆF'Ji’+#å .i! Q~;g–vW¦‰‚ªR‹â;(‰ió¸V&Ž›æ>rÌ?ïØ©¹¬»›Ñ-ªUkRîÚX®L—×+cAñ [®cæ>´Ñ"¹âà—jç8óžäzCš¶úÅKú]pÝ»³øÙ•NÏ„´_Q%lùiwíi¾%ÌVb;­Ë½•ÏëŸssן ]•¸ƒ¼V*ˆÕÝ:Ï,ìñ¯b‹nxgesPU7õÌiú] æh£0:8on@:4þ¥´Y¦5DÏF]x?ì«%1^•È#yë‹ê`(³Æ_2U?<»×©fT¹‰-² óÝ®YÍ ÔÆ>üXÔ…ƒFý„­7“=÷†y%m ÷/Î0é¾úÔyƒí#æe¦ð|&Y¶›Žvæ:í—Uå tßÇP=1M[°Ý¤Ü/˜¾n4‡ç`“ùgøî:†‘v´·-dA;[¥‹yðåLë‚]Y Pq ¦üúŸŠX¶£uoÁ7Öhô$n¬(Rž.;r‘P»É+‰E(U½à¬sƒ •1ÎÈ"ÈgI¾ENFâR¤-d¥UÇv¥]´µ;g‹‡KãÞ¡óÿa¥“§˜pnø…þ™ÔzáîÛúy‚F©ß–1€ú{6âÜò‹è³÷|‘~éE¿©Qˆè^3¿•Ç<ÿ ãx†Êÿ—\´"·í’1烀OøÇÅ¿ƒA Tg?&ì h Áá8Sòþ‡B€`”!ûÅâ@,UûŒÇ¢QÄŽ†?!IT9ý'Žæ™diŠEa0¨ä ŸA_4½ ,„A óP"|–G(tÌö›>}Õã5˜”Î MÅe”9PY\G*³úìúŽV€47ÕÎOCŒÄ%’y”:Ò«¾ã5÷í*3}ª¤ôh8÷ÇIp0I<ä Þa[†j%o‰W ™¥õí¥žB´WØÍ¢}'ˆe ´ÛÛû-m¥Á㘧ýÞ!½Óc› T×mÃãSj[d76ƒË"7Õ/HëYÀ Ž ÒˆnaÖ;ñ}àÁé´8FÛ¥¼Ù¹Të+ú!±Â2t˜'B%ò(oà©6K‚$òPC@ÛŸé;´Ý)‹P¦¤©:¤×¿@J‚¤ï"J¹.h*XÆð|Œ¨o /ðRšé$ªlµ¾M¢±¾o¢›£¯DL‰;N²XÃGH;‡=Ì£ÎÀŒ»æ„%‹8ŽE@BÌ ê-.¨¼)"ªS)=R*Û9°’|ßn³×7:Lð¾¾1ºâÆl´˜ðÏŠž°IÈ:‡ÉL¢N±µÈTpé±ÄÜÝ«Sމ/ó!ÿ$²{•1Ǻ ¡©«ûf°¢ïÂ:ŸÏs;€ J|±žµ‚Ä•4MÒ2“¯ïª¶ù°°Š”ÃÌ3tB‡KçêàÊ0‘û$Ì´,úÒíU.30~T`*K%/òÐ!*ʼ•J¾ÉS ÐÉS¤„&Z¤¡Ï´®ŠÊçú‡bDlµÔ‹º+œ ª×€8¿Î5È=¤µ=ë)­¬1G4L³EaO–dåÁMqD¡ÏjB…T÷ä÷€ÆUe“È ­a¢²Œ¾ê¨ƒów«ûNˆäNÔ™„7®oLÌ[¾Ñ°Æd#H"J¿²ŽN#Ÿ¡èV2Û5hâG±¢‡X´¬©N;èµî…hú ’‚kx:Ó\qQ/Ž^v~J™j&%—„q*\Îb$±ž›å©Ùi¥ù¡Fx všî–h±ÜGͶ젗^#[!¨rOk]ûÒW¶/ʺ›Å§ÛÅ-Ib@VŠÜ€%霫ÆN~¾óv)]%¼ûØü‚.³E–áöÈ"yè«® 2›¬Ïú1Ùògå[ÇÍ*ªXò ±U\0Ž |ñPŠÒ$±8¥'²àþ^/y‹ò5½ D‰;Æ1„œÒcâØœóØtªL«¾€  ™¾d’µ²u Ÿ3²FPÑ!ñôGË¡dÅ•çJ×PR’bÆ{ ‡¾£(D„Ž-™©Fgê¿S"8H-ó(dÓ ëWSñä‡)0åÇê-'Äp½(5+œÈgM%÷5AIQñGe˜±¯ôv¥Ù,CQ°„!Ò›f$èŽEÓ*êγC…#õʉØ@Ž“â?¯üƒ»Àtˆ*T_Óˆ0òí"œ¢9i)óK"Ò¿ò‰ñðévé‡ìrë6–„I:Ù˜qB”€"¤XÊ¿}«I>¢2•ü*Låh¥%g Úÿ‹-ä°õ6Py©aÈ–z8hˆâ%L­‡²éäA „àŸ ÀŽ tÛhñM<‹¢4P NÇêT£ËfkQ3´aÖ“2AÇ̈/b‹2ŠJ¢%f[ÔenVL0 ³ùø•a™~—ΑDãlý§Õ †ý¶ËˆºË’Ò‘€ìD§P“+1«L\I0á¤A8¨ÆÌí(€›–¶MˆãSÒ³Fç󛕯2S;3lΚÅ! V…1>óëÄCS^£›çÔ•Ò{X‰æ±#2á=À” w]÷-˜”¯C³,Ì6Á™ÛYKëxü—D©AÞ•n¬©Úª—0øÙ[µU@ ¹Éijt÷G‘;^t!£´ÂéôHy÷Å]¸”FTácDhX…VBG ŠÌÅN%”YôÈ%ɵI¡óxÈ›¦9¦‡‘x)Zâ×ìˆ s9¨Ÿ ),¥ ñµÆ—˜•…ÌÀòñ¾Õ‰Fzð_W‹Üz¡4ËI•p‰ƒŸ "ªr>ç›y&~ €¥jÎO‹œ´-²;ÉHì¸E5”?ŠlÄsŒ‚]×J¢5rI@¢3tÐ…Ê<íÔ ÷ÁA¹.Aãq:V:Aó|W„,<Ξ0æ§Ì¾‰.—b “1€³9p{íÍø]¶â'¡#VvkDÍ÷ŽÔ9 `2a—/¿*åYÔÑ>Â9&5¤Hbq‚бvFÛ5EtóÝ-Ì¡ôå‘üˆÔá)Ö”ˆÕe{’yøü¿s„ÀKökJˆdwÚrC¸ç G µí–cC¤öã·¦;¥ÍÊÙZÃ×â‘¢‘¢ÊÉ…¤÷îJ /ô¡GZ…Os•=âÀ®u¶¢9ΧêNoÕ}CX{>Z"1©—+]“H_cÄr´NëIYJìKìoÊ/2:ÒåÁCì¤Ì<Æ#Ûm[,6ka-e Á^¿:#W<ûuav¿?À,—?§å‹²M™Ø˜S(Œ¼ |` *ë°Œ½XØÝTÑdм!ÑõŒàM)#cV‡ÎΧØ]f…ð¨Fë·Kž;tjž¥óö‡±ßvÔ¥SÈ|’Ä|e^תlôÓKœøw0ÊUâDôÒ#´‚´9â„jKDq©¥™\Í”•+RSôÊ4^Òô'+lÿî%J+í+w©k)0ª›s¶j^ãåý«?Ôí…õïž…"ŽL œÕÙ‰Š­äÕ"­8¸_2 b<ÁâÜl»á—ÕejoJqàoqUÙŒ*¥Ú™ElžbV±ã¤;Õ;↳ë:¾zlŸƒ# ë¹¢s¸µÚ,«¼B6=Š`ZbÀ ͪ’øÂYªñ¼ Ÿ˜«±J¢ûj‡ëø’Qæ+ê@º›ü41ý7\‰S¦Ù«ž Æ*kC/’Œ¯B ’³dŒí'ë¿€*œ‘Rõ¿á¦JŠ»¸ KzÊ„ Œ—BÕ)»lš š~‹J¬ ›kó³øŒŽ‘Ô#Ó˜%²ìB!Ç%Q-!ó¡ó (C€"jÓ6ÐÇD-&ÁR?Ɉœ+ê¿Y :!¡j4˜xŽ&’H‰¨Ž7¢¯°ÊJXøˆã•:XcÂ(ë,“–#IŽD ¬{é©A#BbŠèòËsA«%"2ÕBõ> ?µì"36##–’Ò!‹Ì¬\¤»S¸ùÄ´ƒþ‰;¡‘/*(µÀ¬·ƒ7:ç¾Cg™ì¤r[„Ÿ“~‡Ó CŒ ,LŸ”ž „=|ˆS©?”<D³Ð{±6ZŽ'hѦp‰¡“[<¤t›½¡2öG´Âð<£)`9øÃ¿Sž ±º ‰*+{ÀJ-- 4B!$¨á°Ç@¡*C «­Ã%7N@3kGÂʾº 3ñ!:ÙÄX’Ä|2»ì=³b³S$°}¦i>pï>› :ÃPÀ¹›ò|!`¡¤|”›f R´Á™% õ·~“XìJú™{( jéq4>Õ8|`šœ ƒxºË \!91F5X¾·y×FÃY¦ãòKÔ—8i§€ x˜3âØ&£˜¢4Á&tZ®a¢s& >Ÿ‘ÿ1³BˤCt£Eš6 ú<ÚJ:Ãý!æDªƒ ÃÊÀ@2+­ø¬µ‚Ÿª ™¢L‡>Ô~9[¾ÛdˆC†Šºýžd[’ÔæB£#Θ}‰`NʪD GzØÎ¥ÂíMaŸ9ä{½ÌÄ¥á±0ù“ÌFüE˜#Z)Äk´*; ·sZ1[$7‘ª7LÓȬl® 4)ÐËe!8Ý;‰}(B×K±¡Ä°šžú‘&(“¯Û³„ òãß­Ñ;ÚmtZ°A®ñ61Ù©Cø·”@Ò3û“ˆq•½Ûé‘ÜïCIç‹ú]ÄXË;A„V Ž;CbÇ®Ê"©Š ó)¡ %ú-êôÇZÉN:Æ2‹9§è¸" "Ý"´'A â>œ9™tE¾é%Ü÷2‘Gèòðê6tÒhA ¸ë(™tZ”rÅ/]#<¢Ó7&:|t§As‰Œ¥ KœÑë;Ít|$ÄO-¼C £ÆE],Ñ1¶#¾¸„MÒÒØJ‹BŠ‘ãÐH†¢o ‘Ô=àÛ<ðŒ±% H}šp¾ÌêÓD b–K ÓÉ)Ò9|ËTä› ÓÜ"“°JaNNñ9E,¯ØéVÅÖÅ‚íH²6KB73è´*W£Ù×C/Ä“ªž„ESZHsž­D£$^¾³?’cÆ](Ÿi¨›oŸkYL52j£"4 3sdË‚½‡%lÅÍáÔQÊm›àz£ BZ·ï*|dÕ“ì6Áó7üÔÔN#,45jµ;¾Scß–”=2³Õsƒs©Ñä(ä0M$I£a8R Wº|¹û—β§Ÿ2XÔ˜}JÛœI1ªÝ#2„%ÕX²ÃäÌ‹™NDU—½©ì¡{ð´4ëB[Ndn­ÃA;—E-XÑ'¨Æq§Pé/Ûæ¬Ê³µ:Ô"sC tÈš¼ùS¤Ã£ÐùȸÝFèϵ’™ÕAÏzØ43JaBMç;QÚ?êR5½1<ˆ5‰ú»…Ïγ^Ü;ßϼÛ[4ŽÜÑ‘@‘·±È8Âyª4lج€ ]’ˆ-aÈ+ﺄĔ-O„üɬ_6Â'>Ô®€$W:Á4Ñ‘UÔR¯3ïíà½R»Š“Ь‹¬«çRz'«“¶Ò„ä)sáÃt©&Ý:®… —ëò·ô¢À À¥ŒÞ{°L¾4-œ$Ê/<´8ÞÊšNš ´¼¿åÜúÕY!}Á$°—ÒÅ7c',jH!—@ÔKÀåø­Â¹£`‚¼s§«Å2EÙ¹´,{›+Z¨›œáRcµ£Cø»U7må’‘E•øá=HÍ}sHø à­ÝÃäæÊ[?âØZf˜=D,‹¸®rÞ¤HK=¡ÄZ‚¶Ú¦S ½ 20€3—‹„ЬdÊ|ïÍ“tTÂ^]¸ÅÑ íò2UÍ*£SòÕFÏ¡=¹D!º´ !H#þ9¼~¼a€ÝÛÜë´À$:N#¬¬Ûá }3Ö£Bi]"‚€5ÓE9ù“[§‰bª3@ÜðtRã,ò;¬[[Ö’f2¯\†ÙL±ãzc5=Ѧ(3;˜ð‘›±[u5e3’9—âPciÛ6ÂíPeÁ³dÆk†—Ñ*ü¥IàÔ‡âlÝ("\ÇEÐÁ(ÙœíYSÕä‚U¹ˆ”ªæAž7m¿Z” A*¬°&y Eã¼Mê¤oUõK…¯Ò芷dûÓã[ØQØ 4F®8Qò£. ºÛd®®*»OϪ$ ÷&ñ~_ùN¶–_å3Þ’`¶I ô–£¸·,’ÒõÅ)j»l>êûÏL§é—RübŸvE2»¸ÒôàÐÊG }-D ¾¨lj—¤Åå¯Rô‘Åñ:\þ Mçãb“ZS 'F¥è~MªâN­nC`†/}²Zƒ¹k9!Q5¡…y,R#9¶aJ&¨&AMŒu¦)Ú ½Ö‡Þb ’-)køæ éË ª<7  ´õzêO~k)~è‰å²¾EÚò—S²¼£Ké,±çÉé·.Õ~¼eàýMcÜ‚<êŽfRyÛÆ'Õ«ÁÖ3ßCCŸl^1ãî¶P~%jý¤~'`zšë´…3ŒÚYã :üN"OŒxM<.vÕC]™'B9Êõ°Ñ‡Ãá’dÛ±û °Ê75`;Œ‹§#Ðäˆfêœçivf—H½]ãQǬHLI=Å­ …ÿŒ>ÎiõL^L3&=¨ÚýDÄ‘Km”$õgVËq(IÉt%ß24×Å߆FSzš¡æ^‰&3JmßýylÛ¥"Å3ÆáîväÁÙÈ~³Æ+ËÛŸèÁ÷qlreÓ³ÿ@H7ç[×haô{‹™Åd¡ñ8ÈŸHÁ7a•Ìù·?¤9n7?Å/«ÂúàÃõ¼¾çíù4Gî½Îb;8ÆŒr4’[Ë#ÓâoLH.bÕSõéœ=– Öüdâ9‹›.>N³gU?ðmÜsZ µU$k^Uø¡»FÏEù ¸í4¡¤~2ÀÕ˜r3gÂ%¤ÍÉuû(¤xËË[×Ö/¾A§`O)×BŠ'AP£\Ú{E‡Ìƒ‰Í¯†E  üì€eÔ¤ÂæA­¦Ÿ…+`šEK­¶—7ÚÅÅÓßγ%UÑ¥µ.Þô<»·§!cˆõê†ÈÎV…Ë.Ž×ï?+U„¬É~-…! †wšB‹4TäçÑîh³+Ömž—0Þ¤oò\Ð>ÕÄ—híJbíUÏ·6]Ò+’š –a( _¼ðK²"u¡ÛfzŽ8YÞì)ÙçºAË$ý!ïæjØ)B{y$£m —Œï\ëµá>ƾƒ#´"'È•é+¦-Vöˆq­I^¦¹åµÔÅðH}: þ"r]×|T¬®Uü!ëM˜êŠ|l®)á…X;§¯_j%kÇ¿H«™\áaõ[5£. e1W•ÝÇîÖÝ€|0û#¿Šw‰r¢zLSãç8ÛSÌ]*y/.æ‹ÊS6Õj„œ}m‘lueh¿Ýpò`td¦Î0¸m.EdZÉúæ od+Gå1GptVa ‹ôÕÞFshU×ä‹Ñ³¡{¬cZLxÀˆA`Ðgì&†B À(€%?"Ð8 ÿŽ=cÀ¹qÿ‚¿¤Ñ—ܦ Æ`r(4Yù"…Já’gôqŠN$Q™d)õCƒ@èÐ)R3„Ó²)d7ŠS¦Yd²¯—Ç&Uº8‹H‘Yl¶;Õ›â’@¾ ŠX`ÓˆPõ)}Ð!•øäfô…RbÉÄ)2¸K.òlÉû8Œå"P¨£ç5pŠa€Sèæ*!R¶@ª¶©”Ê2ÖT`W E8Ð?ív\Z†úŠ`è0šÝf[™mqÐ\öÖÉN¤Ú˜¼ \ÌD-tàgg4ù¼S`±™üJÍe™O"pÂÛÁÀðsŒþY§n:֪ߺýÜ¿"Bº²´@ÖÙ¶‡ò¦³´  z“=ËÒb‹$Kâ@žp¸ ·hX7h0®hIñ¢‘ŒÁ§òý¬)£€Ž>l:Rð€‰cjë ¯úŒžÑû<Ð" ™ ÑT†û½(KŠ“!ï2ʹ‰¢릜@¨ã“+K2 ÷¤Ëã:Ž0s ôøË§ô΂ŰrÈ¢ Úò½E â†)Í«ñ¶3úÝ£)¬â½J(”Œä,̲5EéBR´%“X„©h)éLÑŽrr£Å dØ­rûÆ·iTʱ¼ôµ(J¶ÖPú Áά$b‘Ä‘2#+U"D¶ Ó#̾T‰Ú ÕWÑ)ñ= C<™Eb•D"Ì’ÚœE t6‚ ´ú9j"ª*‹C¶ ¼Ù#‘Ð-+e8ÏL§ü§]5:Ç 2à´S“{hæUŠÍK0GPЪ=à£ÀôªæÝÕ EŸG- ä:¾$S[žøúe,a  ›’Å´]×U裬 †»Ak øÛºHbëtÁ4-Ô¹²ÒëÔ¶Wth/ja`2™Z~>{ã nFÉYŒˆž@(‘¯™Äo䕦ÂM/gNˆ“G™J ¥6×zݶ&x0‰àÊJj-ó†ŽaêÞ|ú@,•&½V—lG@xVç–' dQ‡è±”z‰H5Ü„·çï?yçÐ Xí½F»¸.-Ó‡ ÒÌàòho=Àå ²ŒÙšxø­Þ…1’b-”Z6¼æ¡°{jò%`iweü²r6Byµ;}ïuîŠÜðï:ø›úÏckÕ™'È­Ó|I)ùÙ€}LW×ó &÷Ö/Žù Ï©˜½#ñìÀ”ãƒm7mXš‚"D°¾)BÔÀ3ºD®$¬ÆÀè‘ÚãRÄIf"…ªÛ@*1³7sä«@2ƒ$õ™¤ÐH¡»7p`ü½5Œ ybiH3RJã@~på2ÆxlZüPˆ0ˆ=ˆFBŽÙž\ ë2á A¬M¬± ’“”QÓÌG‡D¨6¶:ñ"sâ@gÑ÷¨“®~ÞÁ.zÏAö;'bZ[/(Ç‘ŸÎí×doIQ<ÉEÖ@›‘À¼1úX^Ä‘oœ›WSˆJ¶!(.?$‚K!»¶“…ÍõGf‚¾“#‰Õ÷¯ˆäl[á’Mhuú¨çúj$|ekÍ£?fGê»$œ´*£íî_®8(4FVvÜG™*Èã¦!†G´dý^±;kΚ‘i…:!å|-KÕGG*‘ñqšr±£6Œxá):ñCvŠÌ†.z¹šO$E’šñú$," nçDåÑ€DùÐz!L|"°½*_:â´)Øvo †èTâ+\…¯3]‘GÛH8Vu2‚(Ôe«ÉFiÓlà•ˆ%.ðÞ¬34ÃTí18Â>ÏRú~è¸Hà#1eÉd@­êEȹ!äxÑs.¥9ë›P@•ñ–¹$[W!a¬È•7ÃÆ|Vš%Rˆ¢i •™rÑB·Ë9ï)(æB« tÚn¶Õòñ›Ã*ˆ–_Í¡uŒû–Î[ˆ£K»kº>À‘aX Jb3_œ[@°Ç+ôÕâÃÚɾ¹aTÈ927s-ïé k/k>Azv2c¶Š&õXFU!ÕÅB5 Ñh*s’«ªtø Q€‘ݼ7Å9‘_Še™”|ÃØ±j‹“ÓH™¢Y‘ý¡/„¤ì€ÅBQìu¶¨åëkå*—ÇLujý‘׳ÍwÈ”ôŽN}ÔÖ£'GTËœ™–g°vÞÑ,±†Ö<2ŽÂ?*UÿçÑ!â¢ÌšàÂóxXɺFYÜIŽß"}¯ŠÔn‘f^ki”â5tá ô†IÍ”|c ¢4t$Õ͈uaöé1>!=ÆPWI–âðmTÉ §mÕâý"ǹL}zHyÙ_]öv¬{Íþ¾yÆ y®?p<ßËÖõ°ž€ªHÇö‹ÊyÿÈNšË\ÝZ¶xùrõeì¹Vi~M|øåro{ÖøÎ8ýLD‘opK¨vâÂrŒ¦ÌÌíTëgö\˼æÇ ‘ˆÄ$É–j!¡MH^kØn"Rmïß` ”㦡.4éK°? ºž ¢Ý;Ëžà.Œñï~äDúœ!I–ÞËÜh Ò3Bpý)6zËdR‹Úœé®‰æDÔ¥n'2†ó Ný0D#о§ ´à'´ôdB•Ž’êbÖkf©†–äN€vêŒUpj ИáBøˆ ¸ê° ùÍ„s ÒÖÐ¥"öëÐ…ö@ &ÄÌ(xC¯VkèðÐpèå{GH”£E†%0ضà 61 YÊ ©®6.¨Ý†‚ébÌko ðgèÕðh ³ m:ñôç-$ä‚!/¥g@ö  ßH¯O×bÔˆö³DPа¯Aøô‹dl F_ ÏÇøHFMf²w„öª@ù  (Ö©bÊîðË øvüÉ  )—áþ¬PÅ%%òóުξ“+•M{2[krH&Ö(¸Mq:ØT‘ æä*X……þW,àÑoêÍ£<¶(ˆ˜þ<ÑÞ쯛F'¬r¶I[ÊâDg€W¦²{ %L(d:4’ˆÏPQÏVNÌk0· ʧ¬gÇŸSDgLnÅ“¼{¨Wȹ  Ç²Ü8R1§lý*zêÞÏík® ÜéÔ賑"âD h¥d.cW4ôU'!@ÎŽ{F%Ò2FŒ¢ò’oŽ>ˆŸ+G!?lÖù âï÷Æ#0¡-àådCdC$^vàr2Œ$‡,è>á` YµN‚×C . ö(}Ì:ðlÊ·3,Ýì„,ËTä ½R%rbh]/Á=ÎÏt‡N3L'ßôÚ"Ê ÌtK%î>„s‘g :wg?ôTìí’nˆä`҈ăfÇî/‘ © „^i$aïø«R|FW+HR"—"…’Ð~N‚Áð‹òq,Ÿ¬ïEb̾¢ ?è¾N‚ uJ­„Ö|ÐïQ6*À ꣩N'*7kÈiâáäeâ0išT–~ŒèäÚ‚þn)- ç2¶¼\‘Yª0Î!w3z±Dô“¶Ðz`M6î5ÿu(ˆÁÄ #t®¤R«ãèx£&,¡lìBluý;ÏÝJa1'YlÛX÷§*TáJ®Žâ.OqÅ^ù2(mÊbÞÅñÖ‹”ІwV«í›òD.U)²Ô¤†H*l/‡Éj$È$Ò"ö±ˆËc'n.ÐA)§XçÕ0·wrl¶(†émÄÆsôúS’HŸ€q2Sƒ¦Ñxb®Ž)«µë šd]‰‡H›D†ê~¾}ì((t=2Bù¥Á­Ë ß-“§¯½;±¦fGDZFãcjãèG™»NË]šr0â!•âÝ]‰­V8€ížÍŠÈ­ºek{#hý:}U°æ°Ç´¡ôgŒ¦3ÈË´Ù±®uz…Å&P!›®Ç×Ó¾§qFÒû·KÄtðõr±Óþ[uüù¢Ê %® vÖÄÞþfèû¾¸¢SáÀ«G?άÒF–Ü»ãIÐ?pG '®Á£N†- ùÛâì~nañË[~åÂæƒÎõl#“i¨D>êéèâƒO–yr&Fämø€Üú‡N=ÞØLipMK¾M;>¹ê`ü‘ W­›¨‘bËVµ¡$y0ví.Î’_ó¯Ìò7àU1i&~žŒ¥Éxš®y¸%µ7EdKvéÔ](_öP9¿þOªr¹Öf>!D*›Ù¤Ýû2Ê¢&—ò’‰KBÀÀP þ…B!Øp! Do¨´Caш¤hŒ@ßðçì"I“GãQ€D½í1ÌâϨDRLD¦ ™ôJ0û¡I! LŠE7ˆI(O¸¤ŽIQÑ tXÔRMI£’xd2Ž„Â£ b%N€•¸sòá$¶UöXÜI&’YàÕøÄ¢“ZçW˜tJ¬¬Aß8Ûƒòç-‚Û1¯˜ôR!™f±F¶~¿ œá`rjƒü ©“i¯ 5ܼA ¶E¢ ±¿¯ZXt#7t R6ô”3pþ°ñ´ñ)` IO‚ã÷PxÆ?wÇÅ-‹g š™È]H+ÅpcUÈ?R5ç©|ßý«…6| îìþœi2$¶$Œ{Nó¦®f“? óNÓ¹mkB ¨HÃ6½½¨s ~§s+*¶5ˆÊ®ˆD(t ë)  6€lþ;jZ·¬ÚšÁ²@š¶1hc*Ì" «^<ì|‡8ë㸠h¢H‰$‰xDZðªÍ'ª±JÄþ8ÐÄ£D€@¦ÃÇÛ6ó¹Ñ›ê…&¨ÂØÈ€Oûs$©œ½0 *:‚És»Zã»(PBK*Šºõ< Ü‚¢Œ‰<ó2(¦³h¤PÇÐàÄÊ #˜æ(ˆ<Ò…C4T|´ÑBóËBƒÇÉS…Ëo›ÔÍ«¨”xFê è¢TD®¤ÀU¨LEmVOK²BɧhS6Œ<§Å¹4 ¶¦¹éZ ¦ÕN:HÍÌý½WOgëŒê¶5ÃxEÉ‚¼ «ÀóµwLF¢u¢"–³ó$Kb0˜žØ=ú±(¡ïˆ@à- ˆö{çŸíÜôý L >‘]¶XÞª.>OqK—uWKr[ÁQS3[›RÌ Õ3OÑtÊÛ6RQÙªêé®Ë^-¨ÕÍ?€"yßÚ„t÷cÇúk`€zQ•8ù–¶[¨‚émä•£•€ŽK(ÆÕjÀ©\Ђ‘sc´{j©A¹³®¸Bo5kJiÌ“\³j,„RH>«»è6ñ¢=iM¢Ÿ—ÊÇɇå­lmÑÃX¢Äæ3g¯NͤҜW€TÃæéeZyÌLm„­=“•Ó}ºÍsÅÝ3ÖcD­+Obã7v{ž®» úù wæU"IjîbúcçõŸÃŒ¯I·crÞ¸ã^›" pϱÔWTûšû`ËÞ¹FÇíÕ™û‘ì*–s.ô‰;§>?IÔ8‡½¾°fzžsf]o¨8bÒåbwÉ9 —G{³Û ®5úœ’$µ‰"F.)™0Ö\FŒz"9îá·¬ôeÎK>d9•$r,fØÉt$Éq•#z”ô qÍj§G\â™Ðm/åi6„Ø?“„S`dùÒ7§"÷ ‚!Ì,‘F2šÍ 2¥Ñ2µÿâaêoÕz?ªsÞ"[\ÌŽ"—è–í ô+!=s÷bÂSy:IpɌâgƱ‰oƒñÁ­7'€¤]§%"šnÙ‰j6‘Ö±ÖªðÕyÈ]è¹x®¢0¶ *í3r &.D‰È±ßdL´¥7âyäŠWŠL©Oà3We c€¦JÜ–c‘4(Ö=µdMYS˜ähš’`;]ënv/¸‰¦´0‡]}$‰ŽÇÒeÄH"LЦ£0™¥ZD> ‚""LåãüÈdÉÚd’%nèbS*[ð|„3Õ ?Ý‹HBL1Ý2VuaÔkOLmGÙÂŽ•_™çxƒÓEˆ’ؤ9Ì–G(© –)T~Ht:· JpÊ™4§vjç£5&U£— ÿz1q%ëS žÈ!­PÎõ¬­ƒ*¥d«‘]³Õ¥¼dzDHUJQõÖòáŠÑŠàt˜Èò^|¡¦©>˜¼“md±ÁºK“`ÓdÜ-,Ñ´‰VcCí N/N%°gR Å!ާ¥|>Ò\‰.Á±Ö¸‘5À+Uf)á·Ö•YÜlœ¢j¨ÄÏôEÈddDMF2µ…§3…&k>‚„H;4.Åd·ëb‘M¶EÈòš•ÐŒÖhvÈõXöVqÎá:d§=ùТé% v [šHfAe*]PõºÅy?{WLG™Í¼Æ“âjYÌ.®·$‚­cž[õð dÖKSWJÉ"Öt‹]Ò~Y}t’WíJ3. i •݃¢j[!‘…ò¤UÜÙ+¤°¶Î¼>ØžÓo‰˜¹—PÖÌòÃ4[̨)TŒYg…Ò[û¸6þ=˜ºä‘/!Ë-\€ [@¥['šÒš¤MLGÉf¦®œŒTfôÄdŽ’ZÈ<ÌÁŒLUg Ê¯œ"¥ïŽÖÕí`©_›€ÿ¨XÊ‹5ˤ¾’œ‘kpIHªkŸ®µH[!ÓSÏ©å‡ø ~)r-ë>šuÍä_eô‡1\ UÆ.FµÚë_ší›DXN1N*<¦‹ &×/UÛ©Î<òù<튤՜ÌŠi?8ão¸©KLTÃ~·½¬J£}9›³‡@7¥0YtÖa®÷Gt…ÉoþF |)5)•çëÞ´^›±ècÿ/bó2\ò¤Ûs¦ô[•ÀŒO¶<.Ù*¬Ç‡òKj¦>_GÔ}6rIÚÍ õpì­7DôÈå%-³Š_¹ÙZWðmžMªÕŠêeß¹ÕDÆÞ3`H ®×8ÛȰ£%匬Š:5Ó:ÈqùÒåž%zK…­õ[¸—ø~½:òI´«úTâ´yEY3Ò"ì5æžé±Øë ËoêrÁ»»•$ƒ ôƒñ+ÈÏeµ(ŒI·xóÇøœ9µdE¬–E§Ì€m>>3Oì´DꄤE­BhLmÖ”®¶ï*nÎ…1:Tê°™È1ɲ³á–; ×®)h,#· P~>©›Óá £©š³òž1E¯ša1>Rÿž’¬¿ú$+³© Þ•RN¢y²ªC$¡¾-Zö;H¸2á6»™7¢?7së·zs0iÃò‹º6Љ©l Âzʰݹ2‰¹$¢°1R4<Ú‹& C6ã÷´KÀJœ ‚á4«Æ!\%¹_’ .(0©<#Å/, *Av¢3Ä”Ø~+ÜÀ Ì7ð®Ž3ù“¬!›,=§ËŸ*B­IÐ![ ÑÆŠkf@ÌCN•`ã )l0²¥¥ÁÀKûÂÈBiB!ªUÁC2KxžƒÍȶ8û¬–Q2ñÞ’šr”3‘?áí!Ñ" 2„ xã˜Éø’›]Šœ#Ó•œ½B¡¸[ Hò(ã´Èƒ§ÊC80" ›ú(4A&Æ9›Ÿ8g¨ó²ÃäG{YÅ὘cÏ k÷ŒK3»Ô©³Åˆó¿€@Á8@ð´¶ów<~ xŠ Ø¶ªØ9€ÔÀK9›1¨Š9A¼¾{„Aú5¸Ä¸Áú¥ÑÒHá²¥ÃcQˆ¹“ì¤rª!ýŸëù*¤JÆk·¯Ö·1÷€<ÃT…>øð1œr¯Ë»#[F 3âøÍ‡œ¤Æ¬:éÁKw& ì·ó(I”1¯ì€ “92h×Ó°¶ËóÆñ=Ó("ªÀ€ +î$¯ÅbLœª 8äg7Zú1*—y™¬ŽJŽ;Ü Û.œ¿K™zì_»1 9k!˜”4'ÄÌCÙ‰#lJ ;œ 6ºwĬ¨!C43ìñt¶œ$ˆÑÝ6+ÅÍc¯G½¨›À¢£º ÂÕ(ºU óÆj].Ç‘ÈǸ~Éøµ ›2rÖ*!¦›qk($ÌBA¦.±®CËï‹ ò‹bÒµÉYC³ªŽL¢ £„-ó¶‡ô~²¶LXòÚB|Ëœ«svRbŸ´›õ1Ø!¬é»‘†"ÙÈO ðíJ¬5€0±Sš¬±sŽÓ¸©›°ÑL‰1žš³X ƒ-òÄ«‹ZVbÓMH™Šê²ÑbíÁ¼¹ªéÖ¨Ô3TpT» «è¤B+Ë0ÍÆÚ„Ž;ɹÒÒú>¡ª] 9Ï.k)JaÛÀõ }¬‡ã°Žz1UŠ$¡¬´H}'3yÖ:¸Èêl9Ùí4Œ:CQa¬¨¾ðã&˜ѲÌD“9™ù"aÙÖŒ5°²Þ•a8ŸÛ°£êžZaÛ7™¤Ší¬ ›yl«˜ª:‹T<—›R>°}®„qŽe¦¿1 …Ö£í¢,\ϼ£‰œH4«@¶ZQ™DtÇ:ý3ŠÈ%ÇÇØ8͘«ºœlö8+ààšÇÕ¼ÇJ?’Ut§Ö§5Tê^Èaôû Å ˆŒ½p~˜êRªr‘«ps/$Ì)ú¤:éË=–Þã!ž4™³pÆCa;¬-gŠh¦’™ŒÞßât‹1s:ëàרHùÎ!Ì¢ôoHš +ߨ}±¹»„ýQ)¦Õ*È*%Ì/\kˆ,·Ûh£!+ËÕ][èæFU-µ¾«7©K‰‰Ô3\Ë Ð-õW’èÁ¼fTçÄåÅ*Íw™]é*Ó^Ù–™%”¤&þ&RAÒ ‘4J×½—Õ8´·Ë¸ÑþÔác<+A‹>¡“k»© Z’*–ÁŒÝšóSX~ÕE àRuÕ­•¨"šî:ǵè„5ÌŒ8\‡’]XÐ=“ª&*Ö_ªÆYOcôÅd¾< Õõºˆv"&{®« }1üª×‘Õ }[·©ÈÆdÊáP *ý–ê¥ä]µ’E#ò‰5»è”9f¾LŸ «r¿CŽÌk¡ê³êm/0…2ðšÜ"‘Fí?BÓ©Fnl82 Þf=ΞÓ*Œèiή©N<&ž"q«gðÕž`ƒÜp}“Óh³Z©aç±ûÒ³ =Ö±ð©7óÇNÆ*¦ b±ìÆÌ,í“\h\¢0ÑSš£&K´ß¹]-¥6ùtΓE™L ƒ¿[욬Žà6ÝckÀkÚ }}AÛ•Oå'Gά4æ…¶¾ˆÈŠˆY"aâjK95Á•´âÜvÇ \Å$O±zfÞL§ ¦xÇÞPÑ5~˜Ì¡­+£éÀ‰yÞ—¤ÒÇ7£Nk)å'ýÝå|¨¢|¢PXD¢¦(dG?ó•4€ÖÆâxäÐ=•PÕv€4š_Ráqå>á›}&Šþâ½Ö¢Í61°Tr£ª3ó”µ0õ'ν’ÃyÒJ%˜ˆaé–Á)éüTãê¬ÃS€b Ñ„ºPžž4‡õÙÔ*Ÿ±ä€ œÊRg˘¦€wD è™˜HüˆÄ~Æ|.yˆÃ5bÝfQ™eí5¯)äòg½òvÑȲ×ÔÆnJ$ ÅÍH®áV±®/Oc£8®Þ¥GÊ[>öXäƒB™I‰IJ<8CŠÞW­eVµAÄ‹G5¹p?œáB^(‹#]¡s®»‹›ì³yìn!ªT#½1û½Õ"Ä®­VÅ?·vP—õOo"¥¥4ù9{áÆö´®½ÃñûV=ßL•˜l!ÆÒoAÚÅ(÷Pi¬ i´îC¤÷FѶ±`‹'‹ƒ¦ý“—Ev"á®>’shóx5V êB¬ì8þ>4e,iìæ)ÖˆF¾ßæ_A ¤!l¯œØæXК¹_èÝèçzÒröy†k,[qçÚ¾šaßFEBž«àÁJm´4© Æ×~,ÔVt†€ò‰X-k8A˜O±‰k²á'ÍânW•ž©=C™v¹“.:ÇÒŠjm¢>í =±½N”´ Æõ¸³R ?*!3gáİ2®(̵ˋ‘×[.MÌW<ãËIáUpÆ‹5K¡'Yâ ¸Õà“9Ìú2+ô³lœÿ‘ (çáæ òÄm®z…ø±î¯¢õýÓ üt}£j|ŸŠòbEb>q¬¸Å÷Ï›‹c°Í;Äé;îÔò' u#ÍòíY®2§pÚžÞˆ1ˆðiœòˆµñ|Ý’Ê7HÒ!ÚÆnà€o¹lAÃnÛm¢)ŸÚ‡T¸€? @$ÿÂ`° .ƒÄbP'ô8ŒC‘°vûA ñ·ävL†DbÑd20ŠKâ2@,Ö#ŠHŸò¸8}?’IÔ7팤Kà´gÕ6†ˆÌ ôi¼ M?‚Î PÉ4¾5˜ËãšÔ2 &™ÆâÓù{âÝ }Éã¶(Ì&_M}>oTù¨¤ÿ­?¢2iÌ[ ’I¨ÕÈíÂ]ŸÊ`ôº,’-p‚ÓâØðÂè£Q¤ÐÍ  §ÔE©PLüš –ˆdõ\?Õ€$€å2›rÜ";ÀER%ǃ×lpH¥¢§EågdPzz|ËÁ=¹3×½O¸Oä×¥›S×aº÷¨eöÿ”~Ë!à …öIlŒQ¯ºûWª.º€.ž’=è"úã'oB:ù.ñê ÆÞ; zL’!À¹ˆÄ޼ñ ˆ¨Ìû„¯¯LC¨É#J~¼Í;¶í›Žø4HêúŸÅ¨â:ê%Péüá¯óF„È/;$¾©³e>i{É'ÈdG'ÈL“Æ h9Ò»@ "ŠŸ¬-JÍ5 Ë޶ޤGŒª7¹ÇúHêJgò^§¡‰ü*È'È£°êBÈòà$Š‹–/ø²'lü¨²"_= HŠû+ L[æÜ##):hrÔ® @.# ý$¢ÉÒŒÔÐ)õdêÑô¤ˆÚA‘T$䣪2žŠMàhà<¬Ä('åHIt¤V Cgò~·S»¸;`MžN)}ñ1¥¶°D#õ 3ÈÄ.Ü@£Fãôg¶–jZ^ØôV$8 ÂC˜2&­Eq›>äHšÁÿW ¸ÙÿŒ'ÍÜ(½fssû«Xª+­‚Ú·i°ê ^ñ:Rá©î$W/3}l‡ÜÓ£Ÿ÷ú)>¸‘"‹ÚŽ}³&º5ê¶šk­0òNG¤W %“¼ˆ)ïݸ•pû§ÕZ H§Ë>Bä@”}’ø)îÆƒä€KÅ×ML²FXÚÜT„døüpà+l"9äŠ(|ãR£"€WÜÀúÈ ‚¯`ÚUÉüû¶ö7LDVb¾Qk\¦¼»MKœF*Yz'â0Ùˆù *í<7&†«‹éx$Œ¥¶IÕ@ûDc²ÔôÌKéP ŒÔ|œÀ;3î©!½b$g 󆙣Ì?] ýN%¤’—$VŠ˜ëg̺sN¼Þ24W¦¡´RÐÑR/F$þ30‚–ROvl$ù¤¶¼Š’üTAkÀ~$DTÄbíO){GTR\‹ùØ?DÕß:Ôή–Œ}tÅ=Á¤GØ@˜ ÑAÉ &DÔh\ò¡4ÈÚ22"zðK£$&±G½Ôàß[¥’ªIS‘…ZR!z™…ŠòÅwÔ™ 1[†Š;±îSÐÑAŠ1Tê¢- cc‰ !~H +-Ž$ „ÑLP¦ÈÛ8ŒAü³°=&®nDP¾ªèê=˜dof01#i gˆ®:¸~ëâzÄ%Ù$›’ðE‹Á UÅܦ°C;!l’­)W2@£‰ƒiLK’&Å%„\tÈ©<±g2¢²Jd²Q½Ó€nP(;úiB2âàQ„:ˆÆ|¥a<Üa 22­³3dAbå Og¨@€ŠôŸ±ü8¿ÎAx‘LÓµUvÁ âkÍ…ïÄòÃWZÉs„ýˆ9p ’ÍÌ •f²:¹þ‰ä•H„Qª’bŸVYÌ?¦`®åp|ߓ㕦œ¿ÐöÔ_Ø$Ì•N²K€DrÞƒ^"'a÷£Ï$:•ŒnWå(·èÌ‹i!ÈÒZÕMk!sôƒ”÷D|cYp„¸88æ“NvÈùwS¡ü4­Á}—(!éÁøihÛj¯ÍvRj¨­¤˜=±ñ˜Ⱦ”¥pÚ<ÒôÃËtÝ)Îî˼ÐÜ|¯qKè¡6ásh”•‰­Ê¹Ý*\ÍÊ¿vtu» «*Ü,^4úa²9|¸ïûjA”’ '˜2Sh\Î¹í¸Œ‚ 8GÜQ½ÔfþÅRH«ˆaØ‚tü½EYß z= ÕÖvSPa—'ì‚7gjI¥µé¼ Þ€Fß*U†Ð2¿8;Nü‘›^nQt;êØÈ ;r/÷¤¯ÓyYkÚžNª7&&£3i( ™8éáJè„Îc»GraûrñT“õusÂÙCF«lˆŽ °4¾T_]ﻄKÍÎX« _ò9¡K­`9_²ju4./8¶Vþг¨; Ú¹ÂâRÖ‘bAI¸MkJ™Üåé5§@&T›Y·®íi ´HFE;;–KÅNtľô“§ÁTîlð†»* ÿHçTÖy RÁ³SQ“1Ýh\uR^ÉMer¤t °ˆÁåÓèH&†N]±6iG²ý Ú!bó2_›9J5»Š+뮳¢ë’˜fh½·½u–ÛMoÛÆi àûrÃæŸA÷qsÚ ‘ÈÅi.Æ‹(Ñ-/ì6º†½ˆlH ’%§ànUrÆ(tÛNYÍ4žî¾Ì–EüŒE¢­1–ÔæÊ@íÓm«J/6i?˹õzŠªí¥Gza„ÖœlÎô‘MsrT’YË1Ôû1·lEq‘ÆÓ…íBµ{rò*3Š«AÚ9´Ûá¸skZ§ºÜ‹€ïMTìY…™ ”¤Í 9>,}·f¥g»ŠL’ŒÄ:ñ>q0‡Zô’,Yz6–6ðK#R=ž­vV2Áôòšqúѽ'`ûhùÇkë§ß”¼ÎRé`?´‘ÑW‰g8">Û£Ã7ðß8›/;iäåÐÔálpAÜ\CžD[!|ñÿÎW'&Àû{}œ”3Ôäž+“ùˆÙÃ@ ëÐߤ¹E¬çà«âÐ\šsO€[4D¸=‡ïUW"|“ïÆÆÒ_ïnŒh¢¨í¼vDž`‡´ç䲊nÉ~&¨’´aö†:+,?ÇpÉ«~“Š`M¼j°|-únäìÉÐéˈ£)@D+ò¹ í¨@©ŠïÀØKÄhjÊgLtÔK0áiœ!ˆ4#d f®ozý‹X¡ „L0=aòÃf¼¢ÏL´LO Êå:0ž¤Ã2‹ÍÀ¥íˆˆ ˜@"ô7"~–ɪ†n¢@ÊËæŒ¾I&”‹#JfoN„ÐûlŸ lÊ’¢ú:†Ì«©Œ(ËúAþ/®ØÊr©GÒm(p\ev"мËͪüg¸žM.f#ˆêáúRPy‰Æ€#üO£>«b|çˆLž¦ÆHFúiªÈ è8íbHlj¯šíÆÔs†„ãäúÁÄBóƒJéIÆ:ŠÜåb7ÆÌ§„t"h"ð¨ pÓiÆ(Æ‚ò†ÍP|¨ªP7/&§Ð Ë/r,LúJ†vÞQ(tÉœ~pÌš‡ÅïÂzDuŒ²N#€Ê#aª­,¶ìqqNª{ÍM&x‡„„pbþzƒä–ÖêxŽ"è. Z{Çö`UÅ /Gz¹§8ßëX"…Lâ‰:Z*I1Ï1xHPÚêʇhj`¤Òà@j¬doñP¶Ì _NÈòëòâj2‰-æþIfãBèÐ)øR{/†m‹ ‚Ä"1ø¶®7,5 ÊÔ¥É)åÛ À´æâ#pXzï´ÛŽ]q}ÑTë÷12´*`¾I*vðRßiDk†ßB®hƒ£Ý/‚šÀIm®”!útx›M™pP ¥0)dBeQi'mìNb_ódok$ä”M€ü+Ï$ _+›C€ÌíA‡|fd€…\AÑg*ãªnϱ Dž¾(m#1v°r¦$Å\9Þ…öÚOÆìrŒ ܰcàºbZ:-‘ ’,†¼‰)¡’£vËŠ`pf2žM+Щä"…\b‹4,ˆ€BZ<-ÚIäò9²‰ÏFÊxh" ›ó,’Ô•”Í©LÑÁøÜÏA&¦I¬û±â’¦ª…jè'ðxÜ“kV"Ƈª/ΣÐDµÂ*®t`'G > .î²ÊèîŒftLŒÅ(¾´'°®fÄÁý>,/L ͼ„0œ’ˆBº.Þ<ñm„„^h·ìH¿&«Iˆ¤,HK‰D¡L¿ ütÍ®ªÖë"›óIÌ/¢j»æ·J‚ËŃ4Œœ; ’äq¢(h~hn\°b#éàInº(ƒJì ÇVþ¬7i+D‚Šå"‹!‰8‰¿à ¹ë0kËy 9O(­'DGk3jÚ€ˆ«#êsóW3„’Øh–°ñ 4knÕe/ÍC9º¥ Bj0³Í:/ä_æIå ðî._L§3†lŒ¶|÷”ÆÏnK ÆéÓ!´qlEl¼×O®(q.‹Âµ Z#ð ­¼Y*A4(ô°pŽÐ*ôæ3šÌfPc¤c‰Cëh"+¼•ÚÜ"tð”,¶aøì òÒ¯HaÓn{2âÔ'PGŠ “¿)//-°:.7ði1$ƒïd¹21¢@ÜÌ”¥õ%õf½‰¬ÓTåØþL_¯ÍB…(ÃiÑ3¨eqÒå"U¢~uÏRâÊÒñ#3Òäì¦Y4TiN-HÑ-OOдã¨'ñŒŽ‘TÏÂN*sO žîàkò'%ó̼` ÈKTvr|3ÇHÀQŒÁ èt’’î{æò¶ƒ8ÑKpÉx„Æ”°ôuM¯@̽:JÓUâšh)lЧÀ/ú<õï3¾‘þÔ0º}6À w‰ ®Paú¢ˆ ^äN4j¶ÄfÝvÙ/Æ8õvývd5*l¶Nª VãuµCR]¬.æÐ"œF– EÿhC]k#k4¾¡u{àŒv`ÚâÌš—$Ò$ɾÅB‡>Kԥ宅V¹î &´@ˆ“Éb›Mï~Š7‰sÜ"EÚhtÔÕìø S[ýst)±VpÔº¸4ÂeÖ.ÍHovˆlz„\m[h¯ì—ˆš8üOëg7…sOM4„¿"^ãìˆ125-{g’†óèâ×§c°0Îg„ˆ-Ü–ékRájRçÏbžK¬&•F·¶å7ô·[Šûv¡%TŒýRµDU;˜iiCÎA èR®:6Е£3£°I-Uˆ«€{Õ>upÌ7ü­3Òôª©GÇŠ¯-*¡pzK°XRŽ’Èì ü#ªô™Ô.ŠõN-Ï`/‚¶Æ¼½&{‚µA*lÇFsø§©ì¤Qb²C'jR‹Nò£R/©l]¬›Mè,¼V‚°ªçKÐd.|þTß5¤âˆ*õ ²,úÅ’$‹{yt’6â„-ÃJQ4„×rÙ÷C'8‡m­î”PÖwjÒàí(æk90¤ÄÓfÕtå\•ô…æÄIô) Uœ²'í'ÐqOË-nx̼¬A‚ž/¿rã}˜Ž–’ŒÑLµÃ`o4Z(Î#µiY1ð¤µòÞ¬±‘ÏŽº ùm3+ ì(²?RWÒ×\0SžÇD‘ÇÔëwm:0È‚¿¯Ê†93—u('R?HÏ•‚J^š‚52Ç'éDflÅ¢„5̶ׇ7¦¯NTÊLì«Ö{©¶èm/Ë“/V/N_c`–Çjz’»LåÈÄVãw¬´êNŸƒ®|ŒtêPýnÖo@ê‰zg›š´úp@³Ôß+í̇ðˆÅ\‚à¤âN›æ‚~RpWh!#‰vWÿ±: hÛt¥X€t8Ü"žÆ0~‡'|Fhe46K›´…„5¸$ñž¯œƒˆåˆ‚.†|êž[R|az‚ø[!³Ç±£â7Žs®•›|vyQƒö'™÷û‡·u2ëÓöƒbAŒy2R—ŠéÐv¦ìiH~¶D‰´gwé7`Ì™ZçÀÑ»˜Ðô„ñ1ÄVIe’püëY¿išÖ­"×ùÿ]v®¥îD4ø•h’˜¾ÐŸª/(j0ñ:£Â'F&ºd°²K³KkŸwߣºpè79B.CTY½YNjËTñ+<79Ç[9 ''k¾•‚•„F#nÚBaõ:سÊgšj9ݺÛJ^ñ!¯É©¤„2 E‹í5èÇf$‰ð™…4¯ 5µnqˆž)´VžÑ9šTª¿N€§5ÚwÅ×'Û]Q»;S©·´ñ¬Üé.LñÁóªµWóƒT­”½GhÍ–Nü3Ÿ¥º­^¢Å m¦‹›‘©K£{È1ÜI  ¶ãƒk“ ˜„'ÎwQRu„¥õ\*`—pQä—¶­³A‹"Ô’(©Z²2â™Ûæ‡ä`ƒãÓÕå£(À¡N¹¶l‰Ý[´Ì"Pú•š£¼M'DT3î0ßå ˜ Ñ](ÉO¼HÁ±/×7Ph `ªçŒ8WVgqÈ–q&µg¥räÃsO|ëIÙšÆKjЖt’”YNÝÛ¾9CΡþyó/4£°Úذûй£€"0­C±È¦­\ÀC©ÞNÃbMLx·Ó€rvæX þ ÉÄ’`z‹ž"þ‰¼ußbw\¬u §}|JÎñkÒÚýUˆËßÇU€õß3ÝÓ¹|RýÌñ„#q —;áKeŽÕøü¼œãü"†!>‚‘=¹:³7b®wGw±©äþd6‹0„-0›û£âõÜÜuv°õ½hœ.X¯Ò#i —-Âã>]bà¿«CÚíϸþUœþ‚¶¦rÓ•8$Ž¢!›•B¡÷•O¬ˆ%(°Ru5*öÖ‘û‹Y :š£”¿)úðñJõ ²O Pžã¨ÇVÖ3 ˜Ùv¦ÍF&¯±C„ûÞcüg•šüýï€ÛÓ6:‡ãX Jj¥™Áá!õC”ޤ—rû U9‘F2Dò$Ë›ø9i:­Ã¨û Ó:ýZ“ÖšóüÛÐ7Áš.<ÿ‹¥°O]¯±¿Ud­=„ @ ûAàp  Ãâ”NC¡ñXl&!‡€äH8I Š¿%8œ&@Àâ1(+ö! Œ?ârðBQ=~D%²¸T.„Чpøä< M¤HŸÑ 4'@Mæs8M4 :¡€"o›j*‰ClÒª%ÿh‰Of`{“êé\}Ýë‘;£ê[-ŠÚf py(šÐí4Œ=²+kãí0Ùí¦¿_N"RÚ”/K×ârÜœJ¾ÓfßÔ}$%(¯Ìáµê¤K/U‡Ìä€[ýžw}ÅtÀi6rOÞ¯uÉl&g¸Ü¢sÝP—CÀëà¼îÎß·˜•tð9gSÆÒ²¶ÏM‚Í ê€-{¼Çc¶ÏÌ8¼}óãùî.Ë»4‡·'¬ ¹ï"È%«òÁíórþ ƒ¢jâé6lJÖ†·Êãž«ˆkäÏ3Î fÑ¥H„"’+‘\à¸Ï˜;Gë} )¨ƒs% Ój̯ r²µkcPÔ$éBf¤%­Ì,9à; ~/м†ÁMCü¹*k,Œ êã€Ó7ÉšZ™«‰šÖÏ"k‚½ÎdË2)¯’zŠÂr‚HË¢ª ´ˆD(z÷(„–¶@à‚ÀòzA6¸»Ø•4L2<õÃ(zßFi’ „ t¯¢ÒÍLó îkÑKKÐ/J©J®¢Õ”z䬠ªúuNÇò Á¾ÓUxÖ!“Ò÷¢mô>»·,¢î¾T:öéºpm†³/(•¸ìv~ÍÊœ³Tµ‹|ù<+2*½¸5‹"KuÁú„·Ð;ó»Ì…³Éërù6ªš­S©CßIØ2Õ‚ÇH“rŪAýE¡•¨ÏV+Únð!øõ¥{?ê&ÜÛL&AdS5›ÌÀ5šÞ®ø I/"œäº_/Ìjß3ÊC@‰Sí2u4 ¶à²ÁüŸH:T†·)꬞ÚÅéÜÙK¼ÅgºúÚú&xëé+jÔàL*ú¼m0ßb«qøë½[Jºrô4”>N •ž½o[íóFZ~ç¿ó6 ²µŠ¿pø ™Á7Èá·ÔéˆcVp4™¼€ÛiÌ §Ù¾™w°ê” nEv¦3Ê¥•¡Ýh,‘"wàå\z”}1XÀ—°¨RIe@ …žöã IÓ.%LdÔ1pޱ‹<Ñ+«`ê 2êTe±©’DLÉ™=êùz±“ìÇ×ã+ˆà üw.{ÑMCd(ë¬w×L *¥rB"$| HK®4…¦`[±9JIcH‚«š±Pr†ž¾hiŒðÙ‘†žó<‚•,lŽ*¡ô½£¦Dß›‚§3Æb+*B¦©Vð73ÌÀ´µÙNìFaÃôû™Êƒg,“y±e䪗¾í[zrëe±ÂBÌ㬕„34‘V9ˆ¹  :U«òšKMóe1Ž^?ÂI8§¤P ê2‘wri$†¢ô¶;B’Ù TkŠ›Í2w‘Õ’?§›í„`‰¨v2ÂÐ9 kÙR¥ibiå*H-qË›å—D^Ò-.äLà ×Än¦Òß1æ¬Âî¾Ï —0šcUH›Sᦠ?ÂhØ(¡\zò&æÓ:NƒC­*¥h€HYœ£ÁR²ÊY u0OÈüH{RxĈ¾Bf«ƒU“xôÙ•râŸ0^`ºxšMáá +ˆLéÎXö×jš °…1“Å`¥yR¦-¤ÒøÛk#Vµ N}”Õpcƒ/y¯7È*ðü©@s’Þ»ˆAI·Q¡ß³'²Ðú+ŠÒb+eKVñž¦]Ôª±"¶´þ5Ë«-ܼ_B¥ €5üMš‹¿o ® ÂÆª[N%¥hXA÷I'©bo¶$ê.” LsÀzà+r¥"殃ìÜÊèËAˆU=– À.MËÜ@%µ6¢SVMËK MÍíÌRTÚ\‹EŽÕ÷Àkl•›¡U4ÄàÙ”8Îà ʆùË©âñ‘‘¦+•5 |¶¯ytk˜žŸ¯ÒV#ñY"778èŠÛ ÑxSXƒ½r ì"l¾Ž•áXÈßvUn0d0 ér{ùÄ­ºi2;Äi§^8m4e—.ÿiÉo%M ʼi°|jȨÄ; ¥\KU1ïA?´¥¦V?e¸\—SuËãÛ}¨$%ÉÄ'‡Þ°F¦-/\ä9lMÿÊÍáÊɲ4Þ¶×±¡F-yž×a@§ áCPj4ðîOB ªWÜr]³.ä#\@ëë(¹çy5Å#­î±—Ò¥ÞÙ©KMª¬à1ã^Gˆd¾§pX•í3ß5ÕC&fÊÞãi_”a¬uÁ²“ZÀš³sñ{Æ=–(áü㉵B¶–Åcíä-- Ý"²Zäÿ6àtNÑgÝŽ$úñg¸¦Š'¤?Ü¡è º>€<ÊI ž=yÉj‡-‚qÔ†œšk5/HC*t&æ.ÝY z0€R&õŠÌZŸ«E]€*â:t‘˱>=‹I{©$^˜¨H:43¢Têœ6u\—¹”ùN†Å²I4ARöˆ«ƒí¤í4É:úûæU¯m¤ôPnšÅ½¤š‚f„íe¶x· †:Þ‚ësÔÄ;ÐËa¸å*ÚcÞKõׇ¼,åÐa^WìÕ8fõ$ÉÇã$)°ßY9.Kñwa¯qâÓP[J¥ëåï­’¯gתꂨ¤CøúÀµo1kâÁí­²^‹§îíô¬^±ÉƒÖ{u ²Å&™®8{Y‘Øi¾€#AÒŸ3&B”ª° *¢Ñ;#ƒ‡á¾º ï#&®™¤Ÿ3I¹IÁ8±}¶y‘:@ º=®ê;£²ò¼Ù¼x´‹1H ™"3‹ºt.jº®»ë¿û ꦞëȧòU¢Á—:ú“0ãú"ûæ›ë|8°‹ê¶Ûí>ŠH¨KÕ€#)Ã.«+ù±¹S—ª“4ø|(h±J S³ƒàŠ W YqC ³S徺Aú¯ )+ éø­‘â,8Ô0d$à ҈‚[c¶8±¢û@8-,Нú꥘z9Ñ‹¡ŠÄ«®‰ ÷—{I3!Ä0ãk£A׋£²ÝŸ2ׯ«A BªÌ¹}œºÒ!Ó\%„¹â#°¨;4d@‘<ÂØ¦›š7±5°ÄÑñÊìž±“ù‹»ï«[‰;s}?óK°ÎŽFë%BˆO ¨šäÉó+°4òoÆõ8¼®OdZ•Û¶\ÙØÚ 8›ìE 8²ü>|C€B@Q…™EŸ¶áÄQp~‰»Ò”a«8+ÌLÜeÌ’´Ûß¹Y"Ùƒ“Gô}ÏkKËÊ L‘MÊ4E` ÛyÛJ¬ªiμ7 ×!KX[b•u87s ýAÓü”& ¿ÔešÙÄU³ÅH$‹ÛqÒËÐLš ÉËQqP }ÌÔé®3ø’ÊlÆ€##+ï¤üc9¯¬aÕHrFcç(¥Ç»;«&Úìq˜«ßÐ…[1QÒÎH}G‘¨<¼Z¢V2I¤1ñáŒT³]|T›"/¨3 Æ’’Qýñ/Uä§ÊÐ3òÃ6ñC5·cŸÜcPL¬ÌE,ÙsXÛX¶ÅcUzg.\$ ëU¡ÀÈ…?Ú‹‹MÒµ©0àÝžÃÃ…±¼šˆÏ:ÈÃQ’1]°å+…ðËv¥2ÿ®Kb @®Iь۵ ´œ#k΢mÚ’Eû=)Ê@P7¤ÇZŸ\É/oUÄ{‹c³¨–Ó¬R‡Óz« RÑœ–ßMYí«¶þ½x¹B8¦Ë;,º©¥Uò’$t¬Ð’Sæ=ÙŠÁ!–+ýnœÚ-\¼"XäBÛ œ¶:„™» 00d?­²È×ô$¨í8 ,ÜI0‚rÖº.%25•C§Áp¨EB“Lݺ ¤)1¢A¼ AœµcƒJÓŠ)Ì•,{êàéåÃm º½eSÞRÕ©úD€5{5kï I¥¹¦ÏFU×üû×všl0Ÿ2vÆë§¡âr lQ)3GP3ß`ÆJÑFPÃO`ûSUB€ž€vw4ˆ:yà›`ø|éw ¢Æ‚£xÏOYT·ý5Êb@µ¡ˆ²WM6³öíè(£jÍØ‰!“åW)×Iƒ:¯ IS­ã¿*>ð¹’¾8ª4’±…¼ÁŠB=Ý¢r;¥¹ÿ½é…) »E‚$ 5›S"J&·¨Ü¢ø›¾ÜåSVðõž[Û-M¤E|+8òÈÙ•þh*¼J$¯1Ò–!›‹’rÀ3IÇkÌZ³¾­æŽè»°gH†Zä÷ÒjU>K„En-hbëb•ÞÒÃÂÖshF§Žü†s>EÒ\žNµ›–G×ÒŸ¥ª3OËÜÑ­‹‘fȺZx ÓDaÓÞV>}Ãdî½Wý—ŒLªâ&›/¼ÊßkzŸp¢â©Sxj1í"ª;]Èê-hä±c|òä°ú1©¬S©°¥2ýŸÒê(ÏH\÷-»ÉH®O5Xí^ˬ›Ì¡¤!¹Úõè[AÞ^@º/áó[_\®6hEñÄIŒnÃç¼Â‹MæëkËߨÚjIæšæTÃqÔÖö;ï…’Ü&Û"åU o ͬÀŠ+˜™˜}±yû»ÕiiÌmÖƒŽšÆBÝqêf’îÓßèiê Ø”ã_=×A‘‰íp;Ðä©·(Ê[ ˜ÂOLº"½íkjÍŸ6ìAµëpövA­©Ñ˜Šé`Ä#•LÍÌM³že,¸nôB =ì¨WX~¢|ký‘_k ܋˞:ÈÓ…ÑÖ,ÉÕèÀÐÒ…¤Ýã4ãYÕ/Õk¥ú7¨÷Ú¶ù({é,d@ ƒU]:æÆ+*?–ÊN]^9MCHt›ñÞýÚjÊÿ‰j/„ 1ŒÁŠò>È9ž¼RÉóV£u¢!›á5ŠO.¸D8ÄnSV®·"Í/‹Ý9»ZLMT%ßP ¿¬Úš/ø™Å0±¾Í5%å45H–¼Átvš³8ÑÒˆJCsez;?¦,䛟3MËzš³Òõæ\8]B ¬jÌy—Kú)£Æj«lëlqìÌ•&D³[Œ¿ò’ŠxJà €@úU¹T±-i8”>@JŶ#JÑ´!XÙk)Œ@…-Ïdð0âÝš65ʼ÷’‘*lv¡âŠiºüT&ããGtx¾E“ xé÷¬ s¦Kõ0¬ž$ùF€5àOè  „aOø`  ¿bP`ò- Å"ˆÄIû$QˆD”’B$ ,bA‚?¤ˆ¤Yù%Îbä2MŒLbX„ä û¤H&ÒYÆK6¡B58„nH)¹lú…Lᕹt:)D…Z*³Êð! Á#ÓiÕ]ŽIcÓðb« ¶Éf1è¤RÄÿ¸_ðòmó£X8)ŒiºÄ&Ùp21­Ûá÷ú3ßLÔO_ùàD~À?í‘Éõ·ÖLui´SCi„S¡~&n{g¯Á¶ïª5ÒEx¸¿±”$CˆØkç»:´sŒÿÝꮲ¸uâQ [q—Ïdÿ×?¿äø0I.føüa´`|N ì¯H“D$ªÛvÓê2¦£ÐCâŒ>ʪl îHòJZ@mø˜®«¬&‰;1 ž„? š¢Êà cÛ¯ $˜¨Ê2bï°°¨ï¨©Ò­SXä ›³-у†8I3*‚GH"@å·k¬S$Q’Lè¶kS⺩è³(é!ˆ£fëÈŽÌÔ‚B)²È†:òàzÏ[¾ë¹oЦÒc"ƒ0ðԚǠ@¤.¬d¼Æ;«»ç4ò«*ˆ.°C–ñ¼±xN@”›—Ÿ ELˆ+s"T‡.©ƒ,±© L#ÃPº«s)øŒVoéúå¨Ðãc?H“ -bJmrøø°éŒ1aQó­¢&½¡³Êhó®­¤¹íqÖnû—Üg´üÆ(ϪD­¼í[à…(Õj$ç—?*'-œ(¬ ã3¤®]fê2°ÄX›Žì‘‚^` mzÄé<¿Úü0÷Æ+2 Í"Ìyó3ãr„à‘½“él§),Þ[Î#Ç·s$J2[cd¾,•ôÖ ÞE—cèR¶ëÞ7ríI¤J(£"š‹J1[ÿ“RŒ“{Ò…ã…æ¨FE"ÍÚ å£ ´¦ ˜šs­°¶ÃÙg!Øä˜ŠE:¯ e#U€MòîØº Qj­¯Œzqˆô#KjÌëÝĶ(ô=¾SÈ‚=h[xBA-?(5“F¡³oKTgê™]…µRdÀ)H²ÚŸŠËÉÝêCsW£4%:¾òЬÎéå>B9å2 ŒCÎŒgϤWŽØO­fµgO•„r.ÏdXFžœÁWX~"•sO/ å“$H¥\.»¤3Û'*ÚbÃб‡NcýÅ#ðýˆ’ `¦ÜÝ„¢¼N‹ÎzË완HUØ0mÀº¸ÁèáaÝȧäfÈãô„Q>™‡ªÎ© wJ…$—&.´@·!ÅB±",ºÚ‰&#b"*2„HÁ»z0ȉ!…üDšRWLðØ 8ňü° Š°×^òQl¥Ãg ¬H+¢ ˆ.ÅT¡Ùˆ|`E´¢Ñ¹û.n´<è®ÍŽÔ,-Õ¬´˜÷"ù @nlÿ6§›I!ˆE/C¢VG`¸ÿ†dat’M$Â^zæDǵvCû iK,¿»7¾C4xiL!Ð…¾£ªÿi§àÖG‡pwVcÃ1ŒäžÇj¦D‚{Ñœ®Dtºðà„ƒCÒ`# äËÉé^R¾m˜Åâ„Zr>.¤Q‘>p ‚ZSpS5/³w„¤‰7p µ+9:C– 9oQ¥²§ðH™Jps¹ÉØÐ¥!*=‡‘ö&Õ0áì¬{ÍôŸ¬ý9Z(9qÝ +4À”Ôs3ÂD›'\€ÐÁÝyJÖ2tBJI7iÊŸÃÉ=(¬ïvT”’Ð!öËè„ÿŽØ~¤yÞúÜÔ™'å_N¹øMÜŒ‹4’e<ÁÿʬoX µI¸‚9G'l8QQÅ7(j>/ÜŒ µ6Hr–¥ƒê¶•6åSȳrLí„"”¼_òñc…â~¤¢¯‹ã¤™Pª:¨cvd–Œ&ÆÕþÐxÞ¿áA7h¤ëšÆDþ‘™udJÍ«MÍbíCkÝ3øœðý„U¼~¿—\Àm¹;ꂪ0ÀTŠ62‘«É¨šC­¦eå©CZúUVÙ6m&`€)ö~é 4´Ð·þAŸóÀæJ£fþ–ÛRmí”Ô0Ë[wME™šU%_›r)i€QWí=Cú2”X +Nø„Vú†¥Ò.KÎjç졤Gdë<-ç4€" äÔVD‚ßZÛ—ó[HÁü˜¯¼_‹èÜŒåŠU$ˆ›=²sOÙ||Èúš´åq®6sŒƒ9Â!’u³_8,(›çãIi—`ž­µ’jŒ=…kE𦘪+ð›ŠßëŸôCSžOªà‘üd¡FòIW ¹Xa õ|‘ê5¾7"iÍìB,ËDœ¹"IŠ€×M}é¨Hbé¡2;²G†Æ¦ }Å!ÖÉ'®¸·y{ûO< f¯mïÀË?1¥ñ×P¨šJæ±Hçð|;jˆ ÑÑ46+d$1LØô#öºï‚n²éïÚâè{BrI öFr%tr'¥Âþ÷iAÚ­›̲üM8~O]«è5ÄØm°Th*ì!ôný†Œ ë(ª6¶âÚëÄ/[›j?nì5Æ~ÊQØ6ìˆãŒ²Ï@ßq@Eþ»bL`.Ô¶•Ïs. ‚J:èÇj¸ÿ„ã% ˆfÌ¡ªôþ ã®2LWÑ ¢x ,Â(¾ƒ$„MÑ" ŠÆÓB7oí!ªÕü¶ˆëñˆÐPÒ¥2@‘§ñŽÌÍì è#‚<¯p$ÎŇ®ÞJøûHU¯øQª‡z¸«>‡¤1íèKÄRýò¦/ˆ6"þ@RОþæöb°Œ†Ž/ É2ü" ˆX6íJ Êf"ÅÓ€A¤*ìj¯xècioèr/ðÎR»z¢oèÇVu.:»Œý!é–¸1S΋bþA¼ª)ãnâ…,9c®*.1ñj;ª¶ƒŒhEªŠ-Ú¯+'øyòf¼Ï!¯‚˯ÓjþRqäð2 ôl"ÏñHß­xp × ,d) ]3ZÌÐŒÄ-I>ÿ… ÝÂÕ1ͪÔCÀ5-ЫÒÚc X…zÈãnGŽ–›D£.h’5E©Ì¨$g=G"$Ó ƒQ*͹4²Ý*Èf+('ôÆlxrRŒä"<#À!C®¬£-äž2橪2Õj]-ÃL«Æ´¯"$µD~’Qíòž(­©´ÛNºïÅ)5޾<ÌÆCªjËÁó?¨Í=ìÞ_ñþE1¦4£M Cv§ÆáR‘'î÷îè%kèùƲø«júò†#Óþ ‚Œ³ƒ‹,c ³× ;çâ8äzó"$ú€5ÅâgézXôÖ½ÈTrBôù<£º[tÚí ú9m™:2à0â Vl*ÂëhÿñÃ0!õ!DÄîOK6”… …|óÓ,‰åÍp^‚sL)<ð{Ä‘(-‚ü“ÂÛ¨´}JˆÎL*´ú»ÑÀÞd¢û‘Ú¹ã¢nP€Š³¢Y%|&ËðþЂʥ=&Ï ù$΂oÐíà U„£%tƒd½GŒ“/já¤éL³TiéÇ€¹Ç"”Ï%.ôL2¯$ôH7ˆø.®¸Ôð-¤a H‹È›NÌÙÒþÚ¨2DZÏUJÔ!Q|õaù”îEM1RÀè€Æ¥L¯Èô‘¨ˆVÀÈUPµ°! öOd*u7ˆq›A² ‘¦^Ä`dO¹ èi*bceLùŒíe øÅƒXªJŒ ®T̶YPPS\s’'¶vŒ»%Uï#­^4úÖ"Ú!¬oÖg‡†Êà XÖ¶‡²‚àq ¬^î˨CTmB¦Y6‚ùb:óT?d1f‘¦jè'©,¼ï"›î§ÀŽ¥A_¶Ycj3Rˆƒ 37µÌrBÈëBLVu¾™‹ªÏÌU 9eÓPÄìNÈë@´:­ìWOoʲ¶uF ^%Ê"¶´ƒMA E.½ oA:tœÕDø2FâÊÈIhÿŒ‚ýUýÊ/æ*Ú“EPf”ú5*x°5Ath RŒSvÞrಠÇnš¡¬ž2¢5ÈŽSæ0ñôsÄ6&ñQ»xŠÃsõ~¦5Õ‡3Q… ‡»(Ê4úR‹q£Ùh‘ëgé3RUVš3Fì€áEÕðjb0:íäÏ)p˜"8–¤†õl¥¡ýNC¿T§Œ'ïÞÓ“+oW.$sk¤¦ÍŒ4šNö4ÑÖ¬˜Y„KÅGO÷+mí"Ò‰5½0j s§Š]"J¿ 5p¦¯X,Çcý6C‰ †oâäéúä’ù¨(nF§NXáÓ—a,²²6” –ÏPÔpÚƒ²[ržtdMHWÆÇ¯Qq'7t2²ca‹œãÐ’Åþ^[¢ n-V ;vVG}%|é¨ñEɘ²ñfòîZ{¸¦›låJAû†S°ð™2Ú¦¿O6˜yÅð½#)lÚ¦Oò‡Íæw,Æá! $0ê¤ÔïDñVé~ñÇ긣f€qI<€b@îh"ÞÏAPÇpNÊ¥{”»‚Å`ŽÅø(âÉÙrh<Ñ¿`(ÍŠ¼gñÎVu;¤,†m…6Ùn‘±æuéÞÅK l¹a–±*†"ªQÿ’¹†x”.¹ÌÒ¥  “&8•ÂŒ–éØÏÐLós#éY+b›M«ôöÂz1LTô#[§7H |!Ræ&$ø7 º Íõ~™LÑÞ‡~àü3˜Þ™×™îKœÕGV÷p/ï%kž3˜ôvh{£8Ü3G¯éúrß•(KÍÚ…šx2öÿ~ÕZUŸú‘‹˜COÔ.š¸ûRO Þë-‹K¾ëY<RƒjqÞ—6] Ã^7×FäÙtXëî- Rd™S ”)^5—iï-£‘‡HñB䈱LänRRÔì……vŒz²T«ï‡Š”åU/1râÎì#è3,6+Ôø)…ªÅHŽ6Aª„Å•)ùŸôx¬áûDmŸ'ÁôŒÿ†”úÎÒ »&ÙÕ§¬c ÅD¢ŠøÀÅEâXÎÁ]g3}ø=7õí_¸WP¸îÑx•ÙiŒUÌÌm+µj‹TÆ?®E4å›íÑ¡íLý¥å)¯9ùÌ0ÞŽ캮¤wƒvnÚmo›Ÿ“Ž!;™ñ7¹Ë‡ŽÙTw<¨hb·g×/Š£/5ˆÐÓY M’ƹí%aü€måP#÷¡Ø­#kìá•5G»ÏpÞÅAµÄ} CðW[bÛ¯hâZI@ÅÆ–i“_-ù¼ãðÔâBŒY³º Ý[O1¶÷«S?·†X¸NÈÞô6dKðA½¦øÎDRÐ)™¡íèOî{:¾ì¬:,å·ÃwQ Þ;71È øù$S HÆNÜ„Ëðª[™h-8ôU¤øÓ¤ªçNîÁ§S6½ñùüa@Üí;\®ìûRz$<HfëÉ-¤ó3(q\x$'%έù:t34®`)¤lå¯9Æ%µ,Çg¼'Z{ šöÐëßÒ»(Á¬±ýt±JÀiHçnÖ—ªÃ’r{Zõ¨Åý‹2Méh (üu"䈹۸<ˆÝò“UÀåyážïLJv–T â±N¼…Ya|õÈ! ù¸ìÞüWÜ•µ™ÞÚó—à ülwb‡µQµÝk6çqŸ=ÏHnahfI¤1ìTAwi®Mþeèß/ÚÂ8±Bøë—Ò–%<`ÅMÇ6Q—¬tê˜!ÞJîïü8…3{ú²¬˜åwšB ª¼5Û§<bçÏG·Tœü+a½ê¢m@ítº:ëØiµ^š@¾Í =œ”r™m¿BÿYÖÐ!›}› ¼yû׬TÀ4¬CÓO¹’̬ϟ™‰Fv:4\ñ[úó¾#²£Ð»Q^pž±7²À0Θª”SÜ–¦º<8˜ã4’]èÔ^œ>Ó‰‘¼wM?"pð?òåM¯/zj‡À2 ±4PµÞ1tš–³a¹Ónbw46‚;¢·Ýùx§•~¼§—¼¡9‰Âò+–,Ç>`8‚ñߪ#ë¹§ž^M’5ï»?sÁ¢V^?*x´šWÒ«¥Q9FNŠ=»™ªëBå þ3`^²•°¿ æüƒ¡Sö‡?¢à$ø‹DŸq—üný‹`dŽ þ}Iä°  ”-¿å )(iŒ¾æ1) N “ôúc˜Ña‘H”Æn§O¥SêpU/’Ï¥õU*’Õ¢ RÅXÖÀ9¤–•ˆVaQ*ôBoG–Çjr¨¤~K—Ï£ ¬ú¯—Ìdï© ;h˜Å&2¨î7 •Lju è_/©Íó@•² —»Iuü´+CbªÙàZ÷ý›;>Ï/¹7í#ww†Tî¥ê ‹”¦óÉË[ »QÞýõ;!-ë¡pÌ|?ŒÅ2€ Å>ÞœoŸ²ø–Ò>ø÷GeX TúC1é€ä´¹o¹ñ`—¢Ž §&ì(ÿ&(úÈì²iòx²Ã‘:‚2Mú§ûpÔ¸-’¾¢LJbÉé‰ë)7‘Bæ*n{ª"€Dº{KéSŒˆ(Él¹.É©s`#í£à#nJ7ŸêkÉ#q¢,ÔŸËôÕ²(SüÃ¥²J ©Æ¨2ðê Ì"à ¨h’:ŦÈÌæŠCP”îÉI‚ìÓI|>˜±u –.ÔÕ 'èu%TAøÚUnTÝ8±CªöàÕnÀçËç²c#Éã;\¢+qüЧȢ|¹!I+H¡ˆûyO­í:,U¤*®ZU6ˆP [R•"O\<†B)ònĺô —W¡@]ó)³›ŽÎO%ëo$©ânøQïºT©ÃøR4&WŒ±6>šÐj;¤ èE£Hý(}½W` UÂçꦞ*v²幨’˜Œ¼9eÀÕ ;¨ÓZCìÛ/ÛÝãè⦅¾×g2§þÈ©c'ò%ÄO -9±Mâ(ù&-Éû6|tŸÉºoXg¯þ%#óš;¹ù-]£©ÑZ ınÙùÛØ…qo>÷*§kÇöñÕj­Š9ó×1ýXË]7§{/ ¥Vý;yûKCƒ^7…\¿šyC]©§Ž^slYŽÓô–È32DðŠ”º{¬vÍÅ‘—²ÂÛ€x&‘Ô'âbÓ¨$)‰Õ€0ìWŠí2gk÷SL•ú¿‡0­c%SŠ­6åJdÓÚ1‰ ,‡)…9aBÿ`q-ä¸,܇ÜK°uïA´ÖE‰S"d–Ä"».=Ïño°‡/¡‘ò>„$¦ÈE Ù$,ž4­× á dMPÞ2RÄß—™Umؘ”Q“K›sH1w?'„ÞŒ›ä`„ Þ#ù%‹] ¢=7À Ÿü6ÄYt¢nË %gþÃÔÔ•LÙ¡w§=n·fXï û%LŒªw¼§×ñ7V0dÐ:€>N|¯`N©UÈW‹D”êÉq)‰bC‰¹ò1/…1EˆèÊrùd½»#ŠZȃVYMÙɹ – PÅ:7…xúL/B(Ÿ4†‘ ž\Yz“ÖÁD¬Ò‹Ò"]ºÊ¹fB¼F'ò„PÓ:bÜÓñUÉY=¾Çì É>_qpÈ·‚¦v1h%L2¦Üê‹ ²i2F¤²A2Éäñö'µnŒ^Š—.±Ú9¥?"•áá~&.ƒEx½ÊëC`%u[ªê²Tár{rÃþ›VþhiûŠÑ^<¨˜ æËBÛ+u@Í£nTÉ)üXÉÉùÉ:K•F= }’©‡Ò%¬ÈP°½¡9z'L"ö9îö@›*¯_@4°#'ñìAàUØûˆ-MkÔ#^šúŒ\K¢3ÅåEh,A !Çñ–V§Nè <“H5´€VP¹fzš'ÌP˜ÅºnŸÆl—“r_(¤è1,–gLyæ@ ݦ*.=øšÉVñ¼m]t[çËÚE/®t\q±|R¥­bIihFkšþXÛšqUø¡ö.iHR64N²ËlCš1«,m‡Áhqn™-°êìªÀ y`Œg6fF§žÄƒ8ƒòu2 &§ß%¤\OÅOÜ6¸VìÖ¿ ]œ&SÆäg‘GS–꟧k–7æ q³0xnÒbß$¨Fñ»‘iÍ$”$ VªôÒiNc¬Èq˜âZþàøû¯.ÀÙH¦¨Ã^E©¥ ¼8(bíëøÆ“z'egŽOôc$ùáÒ[uXõ ºe¡P9Híž&‘Í+uÑYAXó d7ÙHKcõh—mìœ ^êV[§>²À/1å—\†¢ˆ#yTãÌÑ‰Ž¸·‹ydÌìn‘6°I(¦0û"ŒQÄE«ÎÔˆQõ%ºJr(bëá-&êNŸéè·· Ý¿ä3G¸eí‘‹Ú0g¶ª‘Ö›˜Š>xÌäê´ô«ù{/#» E$Z¬ê8Étð!mËvJ—ÕH¹5—k Òš—q1–)Qô˜ÔÙSRðg¾EŠé†^]0§°B‡ŒÙW(­ó‘HFZ¥mg^‚öË|áaýpSŸŒJ?>“V‚‹ä1tÌä!–ˆÜŠŠ^}ã–j¶µ÷ŒœòFmyw}Ä}䂸Be×>Œ³&“ˆl‹î à ±#ƒííŠ}‡Ái$ùÍ%š¸Ô‰g¢±<èÆ|T¡±»†úË´šw{7lFX~DådW­¡b Ý·}L[ÖéÕE*Ì÷_d÷WžV—¹N†?ÉáüVú_”sƒ!{'°“^-\À‘]}¡;` þ¥½eSê¯2îÚä@«bå%ó“Ò”÷3BþouàÎNøÁÞ` eìÄÀ¶‘yÐδ¿BD.47ŽEåp 6ŸÁþ¤_Æ‚;Ù`¦‰¢R¯*qš•sܾ‘亟À‰2Ê`ªëu%®¾J0:¸ód¯òŸŽ y²ÀŒŒY}ž™›ˆ³Œºáì°ƒ?òŸ”ÃQº¡©—«(ŽŒI© 9á˯ öÄ`nÂjü”àŽÁa‘+d$X• Éø¬/(î–jl®òdº$•‰îËP€¡ˆCAµ¨ç²Ë)©-Gñ¼8Èû˜9üÀ[?´9ü#rE=³;<똽|"¡¦¸‡'{رˆéŠ,à}”Âæ3/Ë;µ>2S´À´F›»EžGc«¿{Ž˜î1ʬ‘šCú˜{/$R~ AO¨ã•BºS%B!*+E*¯N©•2~™X‡Ò÷ »Ä.‰ò2³±ô? Cò®ÅÁÓ.@²FPÍÃJ59ÁÖ?ëú¡IEº€ò®ÀP‰ÚüLÃûw;#&7 ¯BV»1W:Ⲟ¬ €e¦,1 y°üh¬{Ô”Ì$Çè´Qö—CëÒZAC:˜yúce2Ý>ø!X〉Òj ë¶-8ó!ËH5*‹ÈÙI*$º”ãŒ(sO¥K ÂӼ©]o€:̵'²‰H3¬‡ëo ›~7¹`¿[VEñŽE¡î‰xÈY+b€1??tÄ)w¯q[¿I²žóLµò‘(­­4­“™`’ ÈÈh«£öÜ¿Ë5 Ì:|/—»{öq•AË ´ Å'”V9ø•6Û(‰ˆþHZÝ ánÇ1Í­».Á¤sˆ"Ý?;@?´’·Ùž,‘ÇŠ 6™Ì+D´(„5ä:(ÄÄXóL0÷Øô)LmGd]¶ë0Çi ÂÛϨ.Êè“ D_¸„ ñb>\©“R7"ô~1b92F Iê;ž»¥s4™¤Ò ì•8ŒKH8“Î9ŸMâÆ>KŸ{c4ôéÌà–ÄkQ¤9{Š¢NáÜS —BŸ¬jHÅÑ·'ºMH²šÙr²sÂÇÉ& <)CË)B­´ÑL· ½É¬ûåJA+ § ¡1Ñ$ãÀdô1ƒÉá(Á§OÃ’¼Cà’£¤)ÐѼÌùL¢‹'»êŒÙÁÙö¡Í¬‘^™ð±ecg?óG¦˜:p±ûjF™ÕÂ2ò#9ÐbèÎ @´ÖÃ/Qpâ,!ïCÃ{¤Ò®ªÌ‹Añe8òµ’+Â1ÇÃvG…6½Tê‡ðmSÙ=Ðz$ÀRQº¤Å®¹ÁÈy±¨dí¢L;0* âűáN>Õ›ÃÀÊâ®Òi»l‰¡+S;TÇ+Ò%¼â0(I¸û±ƒX“Q^@…4)øGËÕ(¤ÔÎÔÆ7Ì/µ{ý {æ“P’¼Š(‘¿¡“†K’‹82ʼ"¯V8…;±.©ø› ÉÒÁ64‹/ ($»-³Aﲜ=ŒI¡ò¬l7"›àÂõZJY{V ö«´­– dK+ر(ÅÅËè°ÁÛÏ áÏû·ab:H¡¯ä#Ñí‰ ²&AWœu¹›.« ;7Ô‚R­$¾(¹š¥U;¸,¸NÝd…~RAïã]&Š[itFzì2øœÎu$‰‚ àG8@D(`ËÊŠXQ3AŸŒ±O\’Ú‹%ØŸ Yp}•ŠM%­Ž9!^)C>Iíõ ê¶×Ø…OUèžiºÕ‘ÐÁKKS­µÕ‹9³ª¬Ã+NBdA»]¼ªÖ[Ÿ™-‡Ô)}ãI­·]K9.¨ð§Z@“JvHÀ‹!t„#`|ÚÝVÉÚ—,·È³®>ÅÙ’³Î:‘Í«=ÆÛ"¸›8EÒ Út]5ê‰ôn9$óàÂóLÜN)o0%ЇәX„aæ"¡}×àD 9”fÑ•_PC™™SœŸ!‹ uC’é}Ázïþ3ÊÓ{ÊÕ£ãF¼µë/Øùö¥â²ò]JÛœüBD ¬†Û¶2‹KW@ÞÞ•´¹"áßò{—ñN2<7êü׸}-:ÑŽåFM%Ô`Š8"QEt¤¡>-"2CieHÑñˆqó«Iü#%y9Èħf"F…,ÕÍÞNÚÈ£D9œ9SqÚRl¶^Œð>¤Û.^㔓DéLá2…f2T»Uq³3Z–>våú357W~ZÊçD¼£Þ¹Õyfãbô]C+? ”Òžbºç©"HE±´ |aϸwyÚ;˜ójãn_ t™Ï«Š^2ÙåO"ÕKz, T¤¼Ói“/Ás_Øa^ˆóy³²úQ7eó$ï"¹=˜¦M?8?fòJF¯¡åÜ‘ú÷yܱ­~g%*ôËÔF?3&Þˆ…ÔËÌncÇ Ì·²Ëkÿ9؈rYvDˆû‚ Ð +ö?áÐøSôEb101ù†£Ñ‡¼†*†C2x#ì+Œ?¥Ðɦ10‹B£oÈÄžtˆÃóøcê…F%tpæ•.N©€º… õ:†DfðÊD®5ƒU+²xdb[.©Hèô§Ì><ˆÑ$ôËp9“Ã铪<šO7£Æ&÷tÐ G›Ñbs¨ŒêçÁCá”ÈŒFX–Dâ8üÆ ÅØ±òúøG¶Ã±X4§G‡ÕàÔ|„+ ¼Á§à}t—OœÈì¥tË4®ok»K·qŒä:—ã[åÖ¹NÖ¦“Æ&Q:e‹%Mî—-Gr q±¿¬1:•÷YÔÓ!˜è4Î h¦má×ïº⿨é¤Ý¢.’0©6èÂÐäŸèÂù:gúnĤèBœ¦%Ï*.çiâƒ/‰XÂÍB¯2 Ì!é­¡ðj&”­pV”ª­ðñ'ILVо Ó Aã’Ø%λ=Äq€‡É 3&¡ÈBRˆÊR˜¬€mÌhÊÈ«I€’<ú§êbnþ«À6ö¥Îaý+Ÿ¨{¥Ín’˜OIJï Äé²ßÄ‹Ô8~±Rt‘¿®’¶~(ñ;TŠÄð¢P‚N$ŒQOb™>%Ï#×AnÓ)»“èL;`0µÀ):FzVIÔB'OJW* “\MŸéMüÐo¸¸°ÈËC5ÇK”GïÐG®¯ öM°SĸªÈÚZ§GÅÁi4 ‘BSµÜ&=ï tÂÖªÑMGÕÿB‡c)únû·¯8@,ŠomŸ‹\ÖÌDõõJGú#²XðvMÃ[gW¡»÷ðéYNâS=S…ké´ªT•¢-ºzøI¡YœÍ•àèÝäSÇö¡Áì©:Žžíºn›¶ö×’ïê—lØŸ¨G#°%ÙÿCé^ ¦jÊ(³ø}Wr^È2¥Ð]×ìÙt€®q¼/ã8ºÌâÐMLè‡@f–v‰¹#sä9Å¡â¸â(KUÒ3‡âB‰·- ÖœÒw’ dŒ5‘ìØŒÉ\K@‘”†C¡‰¡u/Í~ÕÌêâ9d)\3ˇҨPŠð‰ÂÂRìtM%.H~˜& ÚÜë|Lð‰7²š»É!Ü7lÄ£»Ýá:I…ø¦´ºÆ\F‹Ä®’˜PêÏ¢*OÌ£±¢„±Ý3ʃ)zþØÙWCìàVêZb'j†v"BÄàå‡òHo Ç€u€ÿ¡QwL D€DÚÓì¡-Ø™ØóSCu3‡|¦Iâ•áåXð€„=U«àOR†P­õÀÄÀÁ;*„†‚ ˜˜#- ÔÒõ N¼ Dôו©²–à™»›Èn/—Fþ×âÇK±µ”ÂÐB ºUƒ¹ßD„îJTy'åJh›8Êò•Dlîó‘¹úrIÔéMä)H³&D?N ÜŸkŽƒÅ €*™ui¶húIƽr‹‘$?¹;I­irýÐ{âNPEþ¾ÔF›e ¾sÈm°œ'™fÐiQ…Ô‘á!BFù1äâ‹ç†eÓo *ŒO|ÇùA?@­]ƒ•ˆ’È£…¯—¥bP–ÁÊÕÁ®Ê³VŽ?6HÛŒÂä7w.˜Ö•Û@‰q#—) ï½RB0$§ðýC@cE±*.õT¦ ò Œ$ïXµ°§1=ʲmÒÙ¿[õKÑ$úDçäÛu 4^Ùì!𪆾+¨iiì1›™&©Ñçnïñ…°ÉÝ‚M¸µj»2Y¨fz!¥*±Q„Ä¥-O¬N£0ë(èÔæ7®&ŠVè 4kqhŒÄ ëaCÅ_à©ÈtÁÛ¿¤Vø~£2îÛF}Cï “ù?V\¥à¥DU„dG¤F¬Ç ºèúXœ‘|×{­ý¿Ûÿ8P|7†Ìž¿ËË–J#¤yŒ×EÝášh’*þÏó£¡(ÖT&î–‰ðŽ1%”ÉD–÷èe‰•©eãRX†‰e µCmã°` ¥‡›lÊ ……¬Üç:töq¬,Qj-0*§Vli줸#'·:éŽöSèš„ýëX©M»°ÑËó%ãz¹„s,LêkJc§©Œ: ÖKþúæ#©ŒŠø‘Œ{3Òsª&l • 25ÏÅPós1¡a ZN”ép»¡*'Ñ7Áí¯Œ°0á¶d<­35"T²¤ "±ÞmÖvOOÃ1*X¢µTÅÃלÒÖ ÈWG¼à”ƒ þÓEÈQ±þÂrIWya-nÀ£ËÒ„ô«Kä®QÃ~Á…­¥|\ðK˜XÓ7 ®w™b­Jy*NJ¨XãSÄ/¹ÅБUt­Æï'¸e¡¾c%á#x¶±0ä~è©+”ë:ÀÖéb@³ãÊèºF\ÌG5L8ÎÂ×öu·sëü‰ÏRzÛ²$)ÛÖ™h¬0>Õ–!쪧°‹MÍ»÷zë¾°BÏç,è G”möH`Kx²ÉÀÐàpÊ-f Èd"(âeJùgÅìâj ÌmÐãi÷¬ØXçö˜Ðò"g¤t뢄‚ôJ"ý „ððN)þã$´7+ñçöžÀzÄð *HY¢Žé T½HX$q.«/mȳË0Zh2Ù(ê§§Ä ¢>;Q>Ïé“åPˆˆH܆ܦ ìmm!ÐÇëx…Eùê´t,¢j¤Ð†‚nÖbÕÅÈ`Jò§®®°i!BÖ’Ë0¸teŽ\Lž<°â?¦þòPPêˆnkhòm<.-……Ä{)\¸æ¾¥JsDuiÈË*ü´©P#`µÂ6%,Õ,{MºÔ‰½ìŽU ˜ŽT0Kx%&ÖÝ‹å,áÊàD%Jâl§£;¢VÞÏz3«P×£|  %&  aøãkᥚ½EÞ¥ÀáÃëj¯…š£Aþ‘ž}naÄÚ¨I¶«ÍnÁE®ÿaúš Þ¡@Èio$®ÌØŸ,~Ðo¼~eºD'üvÍv¡œUBÄ¦í¼€T·ïäT°èÛÊ£¡÷(ÏzzBüB~Ú„ä)‡`À€òi‡…n O—pT¼®*ÃÀƒëd°~ÔÒ•*E ðÑJ^‡Dt¯x­g u&Š.*æåBÁ™q˜IÊöl‹E«)TgŒ¢À? r©Bâ?ñ•(îˆDb²ƒ)pÖBñ¨õ-"ÎÀsP«)Å~ßÐA-k2Å/êWÄqþú0«`zÌN#ÂÎ)IH]‹6Ò3*ûìèÑËæŠX¾ñukÞÌ¢”v y"s€æËó©ÄÍŠKL~‹F™î̱ï@tt -„Å ©(K¨d*g”¦†a ó3RA82Õ3ܘAðA—ejn F.)&.„:Fþ7)FTÎT&c-§ *Ó(.AKBi‡ëÓp°gÐ)’¢®«ø«L¼Ù%‚Dò„Pç<´ZÙSªyPªÑÃrÈ sGš`KÞÈlj&Â6ʇMrr ™(!âÐ⨉1q4ûîFàáô¢…jQ¥ð†ëüØçøîB„Kª`¯©PæŽKHðÿE Gåj½§žGîT.)˰^:BЭÓÈ0ln9wŠ#‚Vì^Ä×&u»‰,©t0µôf7þ¼£úÛP#? P&Èá µ™nÏdANõ2DáŸ>*Ö<´£t¹§w'AD…µWbÈ› 8¤gѣصOiSÃwmåQa 7…*N°›l–Aó›{ˆq•j ?8­U’Qà+9ĬIŒŽÚ€‘;¥WŸË)m™>þGÑNG(!ˆ3ª”`SN,SZΤq€ —ky¸M•¬Ö8œM¨£¡¯ ºEˆGuŒK ˆ¸¿ N²7“Q1ï´àªè…‘$ð{ù»À f!áÄ–“ozvf&{úDJ+.à-kØ¢Ñê(…‚Ñ…c`Ù‚†ùœªé)£4Ç&õP#Ì ¢“bún‡¯uì.íH´mä¹éÔ< ´WÞ—ÀvKwÒ?kW \",ï­&pF­B© ¦¼ÜäT™Bd…ŠWr^÷`ÃËëxËX¦´bo³¢~q­f mkÑ•$‚;í¢G ÜöSú°_‡èû¾î±7$7X{5¸ÖÀ\4n!UŠß2PÕŠÔÊAúp$C g»Mˆo”lK£sž8O*;–„BÎÈõëKnܰœëÜÞêc¸ˆ”M-ç^zöy¸$¥©Û”Ý"®ª+ÊrÿÄŽºn¯1¨ëÈ”¦G½FÐ@B~¸8(¼U7C ­ ß"¨šûSK.ªC "줹TjÈùŠÌ<  ˆšþóGà"îÌm\P}ÍŒÂdÞÁ®›¸„¡HöÒ Êtê<ÕDN§Cµ~TÖaûK¤‰F{ÔÕÕ!%´ª:ŸÎвá7€ŒÛÓwVÃ`à“/ B„Øs‘ƒ. ܧ(V|‡|5ðÌ.‚ ÑÂ_5¤Ó ÄTÇ®NÛr">ª9L¼—¦÷„¨þUtâ<Àé܃q, ~Ýxw“ž³²z]j¥×<Ê1âwqŸÐf¡,ÒÒnî K…~³5f D®Kg¹X•‰uÞ "ôž¡\-j[ ²~*“MËkÞ ÿi,‰{@ÉR$¢F@?&ðÒå°ê,»%ŠÄ¶¬1½iÝî}¡JòE¡^ÔR/>#û£Ð¢}6 NÑüâÑÒÜš¾ª'f~ÑõM4î'ö¾ó.tà 'ò0 ð¨–t”è»êÿZö‡ëJ“iÒ%¼L„œ÷TÉûd·à‰;(•¾<¤¯žÛ[å*˜O¯"ù]Ù¬!FŸöJ*‘ƒBŸ'­ÙÛ˜â6"åü…8²ŒÒÍ›×LÉÈjb £ÎAŽ¥gölJ;4p ›“'~rŠÒÍd‰Þ¬b$L‹ûáSHÚ’”šF•PÿvÅá0ÚÝz=v#ý‚,üaÁá9M•÷"ÆjQ "ÁpÅΓòþNÓ²t!ÅP‰¦”`×ûUYKÀá‘4hGâèý]êSâLµZúG#íS@âM@+@!KÉmÃçB_XÒèTÑL‡F‡vM×™ˆCü¢?ç†LŠ£¦lí˜Æ÷숒S¢NIÈmI3”Ý ¤/†À&¶öå á„,ADJO%ã¤k “ÄÊ·H‡¦ó/!i»ô&F!;>:rÇ@ H“¬Vq(¤‰ÎP‡'½ãÊð̹"w,ØÁ  ÝÉ»Q‹õÀ‡"œ¼1ÙŸÃúU’¼ÈÛ™fMðî´Èç\È1œ°vÉÊjOÉÛWª¼~=·%9ÛÒA iñ]p”¬)I•”—§±F²é¼©áöá‰ù •(÷"šGÐ"‡›u–Á+ŽfúªÏa±X@ 弡®êÃ#U†r"°Ä2Dê4Ü®iˆLr–v*´™äõ<#vX”£XÝ5™ô"”D¶&¸7þpî[Ø!‰¤‰×úGá:g£ó̸5ö" Ì€´ïn×DS„Äå‘¿H†HÚfgˆÑT{h2¨ÕF Qð«R$°“5á|Éáà\.H8t£ʵÅÔÁ4ž„Js ´\®äµŠ/ênê&¹DTØo1º?)gêÖL½œ’˜vF£’ÚF²z½“ã}­”cê›)4 \ÇWAÃFå#kòES…WrÝ»ÜQ'›vÑ`´’z ²nupìCXAW@¸#y]ý”HGókô²0½M1ù*®ŽnHЬBpßæ‚<)µ;éG¨Å`Ôô4T‚S³kþ<Р~ÎL¼Ÿ¢-—]Ä ˆcHž%ˆ¨Òì‡Eøw;ö}kä1¢º¢ Z©© z©5Hɘ̀kfÍÉm4ÚZåu]ûtr–øŽ«T $I§¹ ¸"-$õ¢¡lêI›ÊÙ®%|l†d¨É‘è^‘Bh©8K}ž©´€›•Ff¦èkÛ˜Ö+Më(“J£€Y[ЬŒ$ãoì¿u{c³ÀëaUÍRýïT¤?%ÅÓPÝ•ö#|iÂ<Ò=o|ðµ^ÚØ¹§ö3­Ó–ÞE¯îˆ¯Ï[f4|+L¿¸ëD9{ú<Õ1±ô½™uÄu‹ðÅ;@µÑ82Lú¨~Þ„ye!ß4ùõß¡güÑÉnýÒü¹H½[ÞÂAr³èê_rùz•ÜÛGQì¡IpÞÂBØ]ϱ´H®ÂåÒyž–Dý.mèXæÔÛh ©ËÊ›ÏWÊø^=ø¬qP\g÷‡Ù¿¡ÿHŸv‹B©‘ _g1Šðš=¯$ZŒ##g¯&Û2º§ü.jö|•/s‚!T¯cfe k`wÔ).\Žœ'‹Šïλ&øàî[BÆ ðû°Úb·…á÷Gìö.¡žV°flÄKgÄ2¥~|¤O3̇Ò> £s©ˆðšéŠŒÚR72™~2ñ'ã//C²CÐ2Bâ‹ ¯;sq,óî:»— »32Ê0++8ªO1°|@Ä%ñá1¾º2 ¨‰7‹ &ºê’jA¿ ȉk­‰!_¯€ùZ¨ûæ#j"$Š"³"À¤ñoˆëñ.«€¨ç)…!¨Â ‡˜s±h}$¥@–—ƒÒê¤Êç‡Úy¦{©H’ ¿?2RÉ?g·Út ¼ºk¢)€Aª›¿ä =ó‹Œ@Ÿ°Áù4ª áãR‰¸¿¯CÒˆ">9‹Z¬“ Ê—¡¶P¯4;%b›˜u·B*s9à}ŸóršŠ ´Ѓ- 6°k&)#¾Й20‡ºÍI Yúiz.1œá€v2 ´žä:B8}”2•‘LƒÙ>ûø‰L 'š'ˆ¸Ä4±ƒQº8ñe9À› Š­ÆÂ³ˆªvìk!Êä9٠滘Œ¸œð5qï²XžCT“9x6骘@4ÙÚEªça ?2|H+!½Yl¼‚š¸ðô3i3²Ñû/¹ß.E‡â·!Êi+‘Õ¦3œé4®@ !1§›i‰H§'a/4B¡¦ ƒIkŸòZC7â{– ê=‚wÂÐ{2qAiúžÁ—Üœb>;ðóI#/±Yç@‚¯Å+K¢¯ãþ¥€L‰nËC;ÊÔÃD CÁHCÛŸ0th'C IAýÆS¦¼* âw“˜£¼™ ™ÿ$Ëý #3 4¹°3x?ÂL Q2𹎤PÅ3FÇCY4QÃÊœs¨4ø~„žÆÈ‚ñ4³2/·ŠJsÏ Kr®iºxÄ(KÀ'ÑZ—£"¼ÏÒ *[©©Î©ÀþÍ ñ1@£¿,“q±©‘¦"›œ2Á®³mÙg•©¨Ì¢›µúvÇ’O›hµñûY*§ùïC\ǬáÈÎi¨»¯¼½.¬V³ëÏÀ‹!Ê©¨‘ÿ¹,*,й£«Ä½s%#A´F1Y >íÅI2Ú¹'Á¯°ŠšÍÛ!4L ¨£cx+Û\Bë½™õ‹‹ÂjÞ§iú ó2:æ‘)]LŠN“ÿ1U¡ú/˹°?¤™Z¯NËEŸ³,1  s|¹¢É*³Ø²RF ê«²(%P3™ '&û."¯4c‰IÎΤÉüÉP+(¾4Å ¶+ãI3¬*úr²‹‹º=+¾ …®Q7º”x΄«‚œ`ÚѺ³Ë›¯Qh !Ý ÀŸœб¯É2üܥΔ¥²M©’4 4÷1ræ $|4»ñÀB£±t~Žö¦Dâá¯Iž€<œT¸QÁ¯”Œã¾Š¡šb§ˆ‘m>s*€!ß—\FDÌYjŠ¡¢8êZÛ‰"©AãŸ5Ð|Ët ¨ãÙ!z_*»,Ìf)<Ä‹Üq !Üqe½’®"ªÆ¬g£«è3A~¼°‚F:m×DÔs©µ:€nû¸RZš ÄŽ×ýq±&cí©k   ÃÅ*k»ðõ§šJ¤‰s­eb–}n4Äú -P qe:u'ŸÌåÇ3—Múºqú=SV˜©Ã13px9‚’ý[,áE#¿¹1ÚBÍKš 5€¿‡ÐŸÉ¢õ¡MbJ³UË$jޏHŒ˜¹gÖ< ]Xã! ñ4£$GMvÌrljK‚€-¦é·*—LëGÖZÀ¶aêQ"µ³GÄÃ?B¢ZC²‚¹V²¹KÛtµ¯¿ä ,3ò‚h±j¹¥5Ùâ˜½ÈøõÆôÓ1ÌûL¨ 2Y§Ô¬É¸ÍS¼#¹–<\EZ,\QþMÙɘ2KÖyФ"oURй761áÑÜé[ý~E?LšU*«“áBíÊÏrŠÜ³‰‰!EdÞÌMˆ“tª8Êh‚©3؛Сò€ ýN“ɺ™¼À‰ÔŽÈ€”ÈÊErÄE]3É8«\Hð«¥/(„'ÂÂM–Ö“×@¥í˜Ú˜B yœ²Â9íDÁvý\QƒÃ#«OK!¥¬÷â¢ÔBãUâʘÒyN¢˜-\fà‚ÏQ&u_,Ø„ j§BÍSõ`_ÞœŠ<¿Ñä ÂVÈŸ+cc-×ÔÊ¢+!Vu|¸«»ˆCv"Ű¢vWZ 8 óΩB ÿ-¡H×ÂbÏ3/J¨‘ ÈzeøÈÀ³à3\Iµåß]ÑWÚ€[h±1º^ ˜0á\t ´Ájß¼f~ $É*ŽNd1â¹`£kSE¨k¼ˆ­¹“qÕ½.­äU}²>…iÍôj¶5â¹ oÛã€[‚º¢‰õÑ“w©š¯.í.ä£ú%./€†XÓôü©„` #ÑL]£\¹Ã%)Õ¡ÚáIÊœ1!Q¥,PæùÑu†º¶ã•SÂAZ›‹«¦O~^¡Ë“Îô¿H£x¢q3¡0’FÞ•&Å“øô~uÛ51Ý€#a SX¡ùú8 D4g¥ž/Œ §šòTm³Î’vx†5R\¥R1[`ˆ4‚E(Õ©›Ë£y/¡_Æü÷GYÌ߬*2|µé1¢ý²:òÊ2àƒb•´È¥ªôÚfÒfs¥Š’|?ý߯Œ3LXÐRö‡æ#Šà½;V\OüHˆô] ;ÐÀ«&¹ÿ4}çÎtéq]Dk\Lúë±L0ÀiFp&ñ` ÂÅâý£ÑÍÕ*¹¼Õ»Â¬Ñឪǜ¬ËÌŠ²PëxŸmHdzÉ#uh¶ziÖ¾e*˜‘k@Öy‡ÒÃù‡YÖµÆL)ª¾h$±‡à¿Ø#áYµîÅ”SœNTúvD Í÷08…Æb•1À#ÎQ‹€óÎÙÐÈIúUUNÆŸæ¾Ñ”ÎÕ–~$‹•Ûyÿºö!ÌIÙÌJ«é^\k•ù/ Ëè¹¼î<Å«¢û i¢Ä0“R:ÍP÷:Vàë…/}'Ä6’óÄ9reù=ˆá¶4ü AMDà!j[&{×òRÔ!ûfÅvªDÓ;6ø‰o離ÌT³ÙWÖ¡°ú2XEË[šOb’”C-«:[?O#ä舺5Š´T¬3ónü"ÆÏé†<;—?¡ÔOŠù]z£YHæI}ÌE}ÚSL4ä†f•)`Êœ™±Û¯+ÿ·yíËV9¸vBŸäü«=hÊÎ…%ý»Ü\ï12ôKš¬kš}`•êFµÄ³NjíŽQ¤"Ôúìå1EJL¹-AÌЕúÒZB_ìÚTu,\ˤ£ø~Gã‹ÍÞàà=žsœ¡Är0ãÙ[ÙðÓÊX¸Šâ,2C`ÌÛ$‹Óbm‰ùS[©j°1ß´‰²ìçCÝôüçÝ#ЊlïÞz8!R ÓäØ‘ç£³ŸÞ›q|Ë¿Ç7XJï·.ƒ.uïgVí{Ãr¹î§ŒK×`õKšÙ4S mêÁí±ÚáHÝÞÌ\4f4$¾NwŸ‡4‰““€Éc7žt·úvPˆ‘K󽑾ŒéÚ$öŒ¿3°‰4µZ7PÉ Š÷f¼¬;»ªRŽUt'™/hKt%$íT÷ÑQŸ.šÿum#ÆFÿ²&CSr/ ½qSç2eh‡4 ²ê×$µ´·‹V!Põø²w÷+’£©íð~¤ÎÍ=Lò ‚_Ìð Nu‡|¤€Aÿ;é4~ÝJâ*|<êz!ËÖQ¸M¥³ü?úH¾EŒµÅO«óΔ¶Øûˆ›rÏÌ,tÌ9óÆâ0c®É?ä§½ŒÂP<&¨¹ËRR«¥©¾4ëPömÜ`<žÙfßOÊŤËc:õ.KqÀ#ãíhå14ÃÇô¡|Ö’ü™Ü¿²Í׿_ÿ(¹žF¾Ç_ºŒ×4T‡86ˆ?«ƒ:†ßÜ£uJžó€Ê­Ï³D Fƒ#åâÏJ”Äõdr,•}boâ\á #¬NÇcÝõiÔÌ;@Qý·]P n/‰L.>Þ`÷ïju˜}v |êÚ|c¼àw˜½@´üð”‘Tz@ÐgFêæ)€€ Oø „Að` þˆD_‘8t2ýŒ£Q(˜<û$P –D’€äï©d:S~ÉâoÈðS ˆÉáRé,ÂO˜C"0ÉLV AƒLã@i““áRxeV /ŒIä¹=FØ^ö:ÜÖf´XÞôºD6?ˆC&ršBàþ™É$´º”*üÿàkuÜ$F#<Õ€Sˆ„Ή&‘C¯¯û¼Â/…MiuºÜ¦ïFªÃ¨ˆ^‡Ý¤Q¼'¥˜Sn0iÜ& 5ˆåߺYcê#5¢í²’;þßÄÛt»¨fN·ÀkpÊ\F·™Lß=»&eåÁ&z å“Ö½·Ì3£ÑÑ¿zÒ ‡uºÒÚe.fè¯("¶è´®ùøÝ-ŒÃ\É)KJÁ¤P þÓ¤HcJõ'ÉRç¸Ht˜&.CPÔ3ÍZ é Ðz@ÅB€& 䉷èòÿ ÁŒ2 ©Â±Jë¶îÊ(„8 Ø™½)JJ†B C ó Î0»¡NŒ€´¨sØòGªª`Ò¹®A/΢4ÙÈSx–*ˆ2¶¥©g¤ä¥¼ðŠ'*°(r·².8ˆÏŠëc!µ'ôK?Çh#JØ# t“º-ê`îÅÔ¥· m4µ?Oc[(aëQ¦«º—©Ëu Ü ¨3¢ êO: ÏDE0Ôcäˆ.Š´Æ~´MP¾A•…A¡Gµ”Ð" Uœ™­M-O$ZÞ¡V™þˆº(S8[(Õu7£hƒõ '5ÃA%$µKØÞÙÀSÙ:«¬r®’½ÒaOØÌE>øÅ´ ¾}Ìx’·Ô ¶Á€ Ö}_i+z”Õ2ʺ¯ ƒ‘Œ;§Æ=Œb‘Ô,cJfΧ­"J$DG $¸°µb2TÛUXÏ+þÀãBý%sep»Þˆä‚P÷J»0€)‚j†F3òNÒÇGòޡм–§èîMH«TÿWðªË‘™j¯fµ¾wóPÉð\¾”öw€NúBK$NÇãKÅEj>¿PÖ½éûÍn:5㓤2ëÔÄ!Z„É—½l’é]=˜Æ¼œ7ºck¦£/°W Ø€M•+Ÿ­šË¶MUɬ…¬iž*©^‹ÁÂJ‚Ó Jï¸ä7²´H{L4«¡ƒ€6dB¡ þe’WšÜ]k¤c@@·@°T2í" p´+×r j¶+®µãœ($›™l3réÀ»à ê-h½"³VâLÞBiNèÂfã@ZhtèÜòöJ«s<«ÐÐ&ˆqž1ÈK€«§.y]I@„‡;7š‹Úb-WîÔ20 O!,ö%D‚Õ“0pÅ⡲@¶‹iÌGÐAU¿Aù dXñD¥¬Æ ë±i†¡£0Õ~RÉ©½†Ç ‚Ãð•Õœx©|K0o_ùka¿¬b"~š3ûˆê©†ÄT§ÛÔ+±TŒæmQiRŸÒ4¤ -GuoÀDÊYj•ffÎÉ*ôÔ#&€­ËÀ 9GÙÕ„¥œ´;3Ô^ŒKÚD áÓ6öú>âìŠHÇm=Øè™r¥$IíûQ.Á‡ôPˆHµ& å×iLÞ$ ú‡ì܈Q‘.¾š0kÈi“­A†ªÃàL‡¦ÆÎ[R‡^RÚú}æ"™4^þà|A’DDÞ¢¡ö·É:*]rنМ“‘.Áj%>ÌšEn*D–/ªvŒÜé,d)xµƒ„Iɪ£µ˜~ÐD y)d¥O$öJîd£«Ð\‚Tʰ~šL¡ãõ‰Âã Hq0~2”~W´ŸJÈ!¨ž¬ª{Hà %é1J±P@S]Ô um½µRf¦€i'YCÚšP}„í•¥M"`‡Õ ¯²Nb§×¹-œ„!ÕÉ5-güG¬•¹8O0À¶À§NÜ‘‰éú¤S@im™¥vvX“[g%˜%&{Æ"n?·È>Ì™ ;°â¥]»ŽÙmCOÉ)ûTtk¢¡ÓJ6&çm¯Uö_¨1 76©O(dIhíÒ!EÀsU0È~QÛÒ Úß}íˆ8*rÓ"Æ † þ{RåT‹Ë¹ìœ–eêÃrLDÄ穲“ZD\ˆ ¶g±xØ—7h$-y4T~¨|L‘k¯²5º´;Œ±;5;©¢”Cƒo`µ–Ì6”K .ýÞ…sr9µZÝÉd#"kä´HîüP:DÙÛ ÜôVÚÂ[¸°Œdâ1ŸTÒ¿g¯IÂ_h¨ÛidCÆ—ÙÏ\d1g¬>vgv覘tíè4£kR#|SgZõumñ­WZ{×(µZ¸°(Í®˜¬°_Û.§¤ Så5€Ÿ™« EêXˆu§‹ñ3&dÁæÔ|[Þ‘)Réþ"ß‘¯;-,(…M+§JJéÙ¥#t_Ö“ˆ“¸ÉZI• \Aåj­¢lý–FÖ¾ÆE„”åÊ­È^õÈÇê<Çjˆa¢Ö¶wÌ„jvªh Ýgu)ªÜ]l>2gÌ}ÚÛ¥ a6 7HKtg}ï ›cÒË&e\^ámånº]g÷±ÃÅ¥>Œ§æv,pÆ'nZ‚&§õ³Õ«q_æÚqiærû×Aº‚@â!^z!Ïä«,bgD€ÚfëÒ)é5ÖIuññÌ.ņëíhú%ãÚ–¤‘7ƒ¨¦Ö%{oA®¢Ö•ÖÉcO × "ØírëõÕÕÙ¹xWÏ&”'³ÆN™2ï^ˆÔW@¼SPMUÿFk§–,½èàz¼À&o„` pðUÆ»­PnÚÝ1®PmŲå_cíKô>=Œ0á\ÕšEVŸí¾{ŠÁîµ£­i›C×õÅT̈eT¤P—ÙöbԹɒã9FÎgõ‹½)„â"Z¿bJÉ …´Fé¸ýÉ %Ž,%‹ä,0Ö†nÑìÄg*&‰&ºSãºWJF¸Æ0Ã8tl0¦‹H>,Ì&¯Døƒ$ÿAø4 P¯œÒpöTNWE>!Ãô¼æ$%Ž´8KFÐCM3¡ô^…*ofd·ÊÎ_ÂJ…bRvibÎ(Kl0@ÈîK¬<¾'nÚ¤nšÃ· §(#-¨&¢Ô$㺮N$¶¼å¯."1 JMÂb¨þLó茧ŽüdJÏFêIŒãå QJð &‘jª$é$M8# ¨ªTÿÆcüFˆJR±TK ¼ôJB@ÇöËÆ¸Žetu¨žg'ÌõåREîRø¦þðRªr»IôªÊ¶I­¶Ó¬Âãp8)mHBÛ v†o,K®«d$¡¦ÜÐ!üúÎèø œ.êÇÆt†i0LÆ GšpMÊ"†·±Àç£$oc@pQ0m£Ø@cßo€ðìÈ OØÕ ¶öî1,0¿¢ü‘Ò,ÌÍ|ôKHÕ‰l}Œºx°nøÈà¸kô÷ ì߯õk´È"`ÿpö’”ØOï Æ|•Гfo ëí+p–°@&«†Pn¦™‘ñÎŽ_¶`Œ¯ ¡Ä^âèEê¶ ŽÒãñn…I.lŽÐ—oŒ‚!Iý1.@‡ú?~jC‘ áôAÈø!%P*I¬´„®^&0f¨Æ²ƒêFdªPÍÏ&±2cÏ$/Ð^¨#Êé ëo€1FÊhɸpQþN$äô Ò (‡ØÒî †jJójuîJgrBNd/ÉjÒÔü鲓ˆ*Í”ØÌð0ÒÀà)lºË&L³Fw3$ÊëK†Ã„¤Þm,m³f2Ž Ä,i '(ң˸ђù?ÐD‘.·üôilîhÂÚH­hÄ“È8M¦Òp¡Pú™Ä[£ Sðí0Ot}êåÀ ÔåcmêùëŽu´X?IÔ£DIžøtâæX¡Ît]6-}ƒšR‰- AB†LÀ !ä LŒôE*ì‹ Ñ´6ÿ’¤$EuI4ì*Ê-*>%  ]/E iQV7nó0Î:/i¾z±Úmð¦ÿL‚õŽ«7å„1Nfîxì¯`¶o\ÌO(’|úÆjÓ´ÔÕ1ïF©ø ‚Eä>ï|rç_BF¹ÉŽ-*ú-©„5DÌ/ oëkMl–É)m T¦àÉ…&nಅHÅ&,% ,e´Xâ-¬u7•t0%£3rÙ=«ìvpDH´õB´kETÖ†ÃWãI¦¯Èõ ëJ„YIlo, E¡%ƒK&â7´îêôvPðÌ(ÀÖ‡^F°«3$Ÿ6`£pÚ£Ò­óÞá¢&uí®t Øx®«&Œ÷MàÔ-Ž^”öÿ2ÅêÐSä®ÅÂRï‡b.ò•apôK«¬úɨɤžÒ"OFÇm6ßLÆ8ô¬VËIWb0ÇÂKŒ+lfâÔ‡Ä^?LuæºÛcØFãJ€A±C¯çÄý‹T\fô$¥ãj"¬õ“_Z²l겓 0JE?VL0à¨ÁY5fî.Ì£ WOYwËfàñI{o*Ö`y¦çoC åã”Æ/’)wcëýESÎå°ó Ç74.ÚBJX–×MŒ@#RáPÊÓ© ƒÇ¼f°lÇDGš<¢—D¥­ ÐxÒ1ºuô.û¬v±Òl+t.·‡sBlîR´Yyõ¨ªÌÍX2òöDÇoaQ·®ÃÌÂÞƒ[¢&nsYJ‚O;F©ÿFdÃÍJ€ ½=v=P†ÿ‡K ¢§öÅ Z+4oÅ@‡x@Ñ`,1 $$Pú‹^$tÙ•¬t±ùž·¯q»Œ;ÛÅpõ4XÔúçAÒ+§LÂû2=ذ*U¤nÓ§†æøQ<Ìa¥ôÛrhg:÷+OT# µTâü·C”É‘»±T›wÁ;-ëW¸XI…86UÂå‘m´kj½¯áÀf§›¡ùÓx½{g_E—qkÜ MÓbMŽ4 Cšöýqêyœõ¬‚¸õƒúPÀ0Êå÷…W=5hÕ6çÎ7îrËѺ({4RXY &®y-ÂàÖ ÅÅιŒ&cz›Õµ-´hÅ¥Z.$x.¨YVi ¥1KB„%¤!ÿÊüoû¢›‡þFææ˜.M%hÌÙn–[¥™ì:z-*t#.Áó·¬ÓI˶ÃPºÊ}å c¦>k™ÄrkDøÚ uM¤¯K§[eÇB§9È€Ò:‰”ìqŸ4@º&eÀ›š¸õåu×êÌ]Zq¡ÝÑ| y £]¶äö¶l‚-ODöÖË€¨ÐÏKI<‹LQÒ›†öÅ,ýVP»¶Õ™¼}_ñµdý1¹[óÓ„¦Ô¾Ú·%xætè}`Z)½9 j§<®¥DWÚ ”òøÝ[L^ìÕ1ÅMè¦Þ`³Sd$´c.Vª´˜pzÚÉŒšH™nûÁJ:³ËMq¿‘ÇD@ê©¡ƒ…wpàKº¨Ú­»9n¸ú~›‡„ RC­Ùi‘™A<±µÑ…Çû>ЉMm#ã­s­.ˆ¸ø6f5„¼5…¹>2žÎªâZ½KÆ #hz¸ÈÈÒ¦£[=Ï-an~~G]6ÎðP0^áø1Ër-wkÞ%(ÁO«ó•ÓŠ¶™ÜU^X`²,oz9k‡sÝÂ;{w¹Ž’Ò_ ¤8HxªU)ñ/|EðéÐ=¡³b<Ö“ÓMY‘pšÌ/‚züÐ_…ƒ´aôâ‚ ñ¼êü?X¡É35,‘áÓÄâõ‚NNJMƒ(/uìÚ.¤#tHºi ¦<;¬Ú©„ Øÿƒ?¡¸P ‡BÐ'ì8ö‹#,lˆAgüù%Éá€)+òS'È# ŠA5›Lf1ø$æ!‘K¤ ¦S4›JÁ—½.].‰H(ÉJEE™Èà’ÙwºV€s´ÎWlÕ Ò p ‘Fð¬dú—T@W‡ýÒ{P†Xv™í† ”ç¥6;Œ"6Âfä[,Œâ;‘»ÇdXI\ŠWÅßÁ,uXešÛ ŠJeoŸ¤å•èù¨gñí—hâ*f+”á&>'Îw#•œ%+Zî+RÀéŠVæ*šƪðiú‘8¯Ãš›,*âb⢎ˆ,l ‰%.+Rè£ Fú¤®,¬E=@H’¹.‚ƒ8±¢ÇÆ ;±°’Æ…5góRˆ< Jbô0J@Š"Nxͧ‡ôBþDµ#ˆì£  ÑúSÄÌš¦*à7:‘»}5Ò 0ÔÇñt˜öŸ*ƉB©“y 4ˆÂ$Ô°‹ i-Ç銚”!KÐÃ=óIû¹hë®þÑŽc<¸!’¢"NÌ<ÑÑ3 ÁFHC“Ô'ìBÝŸòñø·.hCS#®³¶“Ëo²Ôæ>`S¿U: ¯Ïný$;Q«è,q+) h#Š•»(2(˜Ò(±MAus2ËÎuEQ¶–k`´]–…"QåΔ¢Q›™w²êÉi6UÕ|×lü„%q Á/€¶…ð„J _¤± iY Ó‹‡Öƒ7|ÊØ°Êà§`Ì9ú¯¦*YîŠU‡óeb=þÀ8³ù€Œ‚Ú8°ŠÐ×¶ôªÞ„b@Rgvl·MG ÿf¸¯Ôi{ÖP¯¿V[Û$3Ò¬BkìrDlR;ÁxQù?Ôy…fÏ9MñPXhv‹$ôÂÏêÂÌj„Tj9.srÃHÝ R •xƒ?L"]d Ù9û¹Ó/Z6Äßèî«ÅüÎ1ïéÅ¡ºoÔÆ£Ã²:ƒûÙ3m¶û¼­•_pô|ò’ö<]Óm Ñø—žCSJGXþƒ£{o?¿r=^• 5¹8¢4¨$÷lé½À$Vä^•¥Ò1zÁycÑÖ}Š 4u‚(8ªæw³z1,6`ŒÙç GÜŒªÓüÅÙ!Ýnl’²  ¬#DÂ¥Œ`‘¡B€iĽĸ@Ÿ8zN0¾RäKÖ‘h,/í³¢ a û-d¯Ô‡5t¨g’QD03øÈ×r•"H…[¨@JYi|êà6Ø?Rb UoaÚÄÂJëI¢Aˆ 'A@á“#ïvP´ÿFbÒû€ ‡#-˜3“ŠúQ Qø~ChÚ_j?Z¸zGò(ahudÆ9”°ß 4K!͘~Ç¢(òÏÑ&(„°È¦|ÁÞ,qbcò:›8ßj³…$A-¼2ÂÓŠŒ¦‹.B6¨ðüݬ†E ˜§æ– ¤#ÚÆÊ4D€Õ™.[Py¨/éDü º?‚çŠ,žѡa’ÐÄŒ'²¾Èë-8¨…¼®&îpHZ0H’Æ@³Pš`f‘¦Váeá³Õ€Ò\–Û‘VèÅÊøT ÐzÍAZ£aøµGÔ´0«Hê‘¶?CÀ,8„lã·wŠ?%ôc”mÕ€"ÂÕµoŽT“¡ß<É©ùžZר¹Ú’ÆÊÈéӖʤ}1RB¡ìµ” ¦ƒºwÂC–£ NR ­*m?;^‡Ї` œ\ vêVOǧd‘\nÃ6Ó0H!ÚÎ# ¶:WY¢×ªb??I24>”‰6™1'd®µG3õQ}†¤ïÈÀ úyiË™SPáš’¿¦CÖ’Šv/4—°Á Ý)uÓZ$Âø6]³wEÈt|èâÝ-E|äDFQjÊ!²[d) ?çÆA¥ÄR<°q»Ò!ó]ã ¡¦¨­ES!²Fò= ½ùáÐÅ›™ŽÓ9ptF£È§?1§d:#®G,i+0d|“¿9ÒŸo©_€? 4ÞÂUyhÒ†1½$Læ%_ò»Í³5B$Ä¢™¿JØ$b8îÝè4Á>VÛ3GÏÓ´°|õ±÷ ˜ßÀØÌŽ>óÂǾ¤y%ÛL·“)똓0ÁÒ*²åšŠ»,ùXZõˆš£AÕ«IM1Ãg½Q.°ÿ.ö©Õ–NûÜ%j4¯ÑJ®ƒ{-“õ& Ò#u«Áiºâ' òœŠ}±IÚ³',(yB*H¹âÅ;y,7šÍ.™“9ˆœ·0À2ÿ¨Q˜Zí´€˜ù޾ˆ’g£#·Jüè—ª ŠI¼·‹Õˆ lÃŒ+øª; ¡"qX$ ¬<{4‚1á°Û+K~5Û¡¾3ÏAhþ­"uÂ'AžÚØ£Ü;$ò¦Ûý.s˜Ñb#}¿a¯0™µ4IâŒÃè´ê4%™ö1CˆƒÂÞ‹޶ Œ"9^¶°ô.¡¿Eê!2Ê4Áì@šˆ*J–“E¯9˜1Ã0ˆ’ÄÛI¹l?)\)а½~3«ñ¾ëÂ¥œ™¢X°Øñ‚P’ÄW/:ì¨ãŒÀÃF-‘A q€Æù¿7™®=ìdµé%ƒ„2Sf±±¶ˆƒ³¯Y” Iï„Aò=-z$"P¥“¨'a}ȃ³™Ú›x9 @† &Dêû a–cb®›KkTP%ƒ0!3âBáhÙË-¡È£DÂP¡c³TC:ù$§tiH!iÀ‹3zÖ<ƒe¡J 1ÉÉ6¸.A)8#É#k-è}¤à¬¢8ȺAѤsÞ:4CX/ú¹, @tW¼2Ò‘ÒT%Ó(¶1cEÛ‡ùºfÈ[û:{8Œò ‰-ŸèN7´»E‰ÔÌCDcFcÁ³rX?p±¶Ñé>!ïÀt5ò„§b0ÚK“«elc0ÇJÿ@˜º X;ü3ÀsG#z¦J3Àà L¶¢¹Ë+´A›¶C–$Ò0*[ˆT“¹sGÂrÿ¬T-}›(ަúÏ:Å$KÎD•hô? ‰=§º<øȰ‚˜‡›°™ ü‰• K#ÉͶ¨Ú762h8š• ÕF£9FÃY¹‹ð’¤€,5ÒèØ<ûOH è(­CKŸi@L¤ 1x®B»XÌ{}Š»C¼¹@2f*d©Å''ÚÏé*1:€"¹ººÃ­¨Ì¼D´­9½JM6{N”ÓïâD¡P+œ×A35£qì#BÑJy”Ì¡ZË“C¡|<¢AÌ#Ë—Š®D5*Á¼h¿€=Ëä|ß+PŒJòÅS“Å:èÑ´i¿G’¨Ì˜‹B6RÃ;Ûý¥ H ”ŠâïÍ0Ø1³RÆ$%—9ˆÑ>¢îPyÆá¤ƒ.­H ³½3¤siµà}”ÒO©ô8C‰'3 Ð;Å sͨ ÑÜÍùµ¬ð³%-%B«ç•ÚC3xÐí@Í›ïŠS»(T‘F$-Q{M¬ÂN»ýTK¡Â伩¨?aÃtCùÙ±y}#²0l;|t1 rÕ`¡0ÔX,sŒ.8kÌ ;E&ÓÑíF‚³É‚U«fL ’¤ø˜Éb5:I¤R1Ó”ô¢¹ú@ 15ÃÈDb4ÔG%쳫u_>ÈA醓R*Å9»¨CjÖt 3OXr«—דמ³|¥ ÝÇ£<ì¾%t•‚ŸÄt|Óˆ!±ºŒ3‹ø £@¡Ùù‘Á­=‚¤69Š ”J½JY3kŒ£HxÉ4%ƒx¢+óÁÀÖŽT¬DY[§C¼(ä| ¶¬@(Ë<Æâ¨€<ëÁA% pV̨!LºÀ}¯XÈ›ú¯:²rªe?’Â0.^Î|:‰ÅÎkçG³ĺ!Ã9rŒÚ#ž³Ì MØ—:òØy¾2<˜ÜdFÔ­TÝÆœ:,À¤ÁÏÓ˜™Ê†˜“ÉÓ?ýè«; ”ÒÃÔl_ ,’Ê¡‘Óù¾Qýi• I&I(eñ9Šû‘íöʹǫ¡XsÚG>ií?ú÷Ì<3¯û²,{QW>³ˆÌ-ãÁ"AòS¦ÆËkx¶«.¡I– Z¶ªd[•õ6µ· M80«ÖóÊŒ5Üš@ÔÍ Á½½ÛÖ+îN蘡Äà©E: ¡Òs´C£<à½\]­õçP•…¾xÀÓ¥ ,RÃÈíè]PËÑ»ºŽA›g™…”‰ì/€Nd$•ã'Ä%qßH~Ûö »ŽÛK]ÉÚ¬`& >ë"UmKÒ06&Í…9Uî)‰ìë¦ÅRiQùº¬cƸ[£/݇â9ì#ò?Šü@Zˆ@%¤’C®Ä¨üH‘|8†Ë{È2ÇuŽ·•~• ßÚí¥ %ð1¹¬áÔp® =£ž9¢€+”(‰ÆPûËâZk cb ß >¯âò.`|Ô™†©Ø~fc1õö^Èe?ÜæãŒY@Åq µøœÔÉüˆD˜Ìd$í• ÀúL„Ö2„ ^éÓ±CŠº5<3Ø2èÂFð‘,@2ín”uu¥¶`û°U‰b2µ%3>€ ß©$7ÓÆl«+JÿÁí—>-Û»ŸF!Y’Ûÿ›^yÚ“4>þ=W•´1 0å“Q4ÄÄì ]l#–¾dÎÅŠO¤™:bPžØd éUÕÙUÄbÊ5Ÿ*yK½X™QO ª(åû,kb^Œ¶yéMgÈ91õ<\}àV6²ˆ€¯™Ë("³O ‘"™yÔý8i¾n€EŒMàÃ4bìC`Íy ^ȃÆ\M3ξvÄ 'bã ¥çd4ŸNœCêmë&l‰ébž¿Àc >ŠÃ¿ú.4ùòªXX×ë iD-ˆ`†²‘þ©€LKèM×ÒŒ¾ Ä–D2åký‘š|Þ™ØÂkö›ÌãéJÛ9á”ÎHeˆV°Zäh{ÜEƒ\ÓÁ¦eæ7õ¿ZARŒ‘þN)«8ÕýˆIÈè Í•Ça}° 2©€*6›4|ÕaœšÚivb®¨A=m0æå elKž^…Ú í ‡ö]ÞÉîj9NIâ&\M&,aýVŸ[ ¥`™&AÁ±¤?ùYŒÚKd.Qæx¦äøñÄ ^Ô`h}: ¥¡„JÌ*ö#ÖÎñaÀ_CyØ‚2³z>ÙàlÂ7¢óçMèÒj %ª²³[ŸjšSËÀM6Çæ²å Y=ÆöUçó¹%†S>OìîÖM„‚”ÑE¾¤.¹såI¼•‚̽Ÿ M`Ã^ŽÿD ìÇ=Ú›9ëF—Óº,õ¾"Œ¾&w¼¯X·æÎí€ô0 ÷ìyáé¨ æôó'YM2CÎ;ïêV² Kq~JI ´cBî°l²óóÁ “<:5´‰-Ý7q¢ý‡â~²«-¾ÜÓÃýe;šò±AjV¬A³vÞ”Êå©ÃÒèÑÙ¼öG¡ç)ä´arÃ>Á_”;¾ÔsÍì?åtq³ÎÄ4ˆºŠJ7LJ‡ë<¨Ï|(g›?~À:dw<ª¬fï%¢3"õl£˜Þ õÎÉQ“ß] ƒ£N1mx«ÿ¨goó<–¢æÏ ˜‹NËŒÆÙ¤XÞÌÓo=ÝÿA¸ä¯È ïož³€Nˆkâó’BOçÆép8|D¾±Íìæp‹KèÁÝ)ÑÖã±i)Ì^׆ê<ÆA5ïq¼GbEx¾R¦çõµ’ͽt)rÇÎϱ ¤"áì7 „:|2Ù‡ÊnÚN†x¶×ÌŸ‡ëúgÅåRØ¢(DK ڡh?Õ¨ÔŠ?Ôãi6´o0 Vq¤LÇâE΢¤¹ïå68iÖ–¿¯x‘¯Þ¤î²`1¨‰s#’e²æy0Õ÷‰,|ˆ”Üu3(WÀÈPÁ=7CÞMîj5˜?lX®ÖXUtò©p—\7¸ñJØ®»³ |„˜ÜñˆàÁ@Pp<%ý ~Ã_ø[øƒ€€xŒ^4€à¯øŒLÅãòPŠUÄaïÈÔV;†¿eXü½÷;˜ÅgÓùüjvûšÇcñø¬Š*¦MeóÐÖEÕf±˜¼Š# ¾kÔÀ$jµ ªÙ@¯[E‚"¶>-ÖY­–i5†ÙdRúD;C[Ôè}‚‡w‡‚pÔø¼Ö¡ÊãTx4VÆBäXø.^K'¬ÄêQJ#Ø´,Ð?S‚Ít™<ÅE3“AtÀ¤n±)–kaºHíæýÝêôò*¼.ý±áÅsò­ŒF;³¾ºÝ<ô6÷;¹EåøÜžRQµ£ÄlÛ¤7—°z_¸.åVIä¡Çb4Xý—Ø', ˜É©)[þ~#àDëHÒ:{ÁÊâj°5‡û‹¾ÈZ†¿B*b*¡¥îè× «ô¤P²¾q ~‚ÄÇ´`ˆ¬¯j§n š›qÜ`{+ˆ¬>ª¨mÛR¥©ˆûÜ?Íòm ?)\•3‘aú¯.ÂFÑ2Èœ–C ÚÀ¿%ïÂ<È%íJ쉿° &â³(šŒÈ% {O ŸÊ¨ªÁI’¡¹ÈlЪÀ°‚ó)±ªô§c.)½ -¼HܢдlˆÎ*:¡$=1ÃP‰ÁIÖÞ+qñIô›,¢ÌÚ K´¬ëqE ëR#\ŸÒJ/¥ É·m½<â!q]4Ž u“¾…ÙUµBÖR›&÷U­ƒÆµ2TÙiYÈšU­¼± ¥„›S?I¬­<-ífÕNUêVM½‰7ÛÕÊ”ƒ¿ˆzj¿FÇÛbŽ×â&¨-« ¹ «åÅ­%ã;< 7!¡xkÝ2^é,¢Û¢20äÜMµè#©|Ö°¼ˆÒËFÒwí3Š^0"HšË+"«ô¬®8oÕ+Bq¡û)z]uÒhŒð‚Ë,L¡'vôÛÂulíé±’ªŽÊØkõ¦Õ@{«Š%6¬Šª#TS¨,ÓV ©|㍠¶\ÈÂAKòý´¤K- ’»Sêw)¶(ªÊ–¡˜€ ®*ªÀ¼S#‹ÏØ‘úáV–¾}æ“È ÊŸÔ]㦽bQX#öö[·ùøçß&>Gè<{’uè:>¡¬²Ãc›fìvRØÂ ÀâÈZÁ´®áe×S&V‡¬©{sÄrgì2¶NÛHôæ]SI¤x`üÝ宕¡1¡³0²Ç·rW(ìÉ`"µ°¼£÷"í­«¸R÷]Ì]t¥„þ?MKþ5.¡K:U¸a8eù »ÔTOÞzSYà BüòµzŒ´‚üܳ.TÎ9Z-”¨xX sìÕxæLÈ×ñÞ!åp—òòœÉK\¶ÅºKÑ4kÏŽ²€ŸI& 8«âKÜ’¹Zæ¦ÆD˜É£[Q+)ƒ¹¡þÛUqˆ…ãú $Õ—qM%X¬xŠ!û®=E±–¿¤`‰•A`,­¤°6t Ù‘ÏdØ~¿tÒ š %ðôẨ/•ùÙXέ[­ÓHîà$WiË„ÔÂvBy%‚uZùYDH™âQ,µ:¥ÑÔ›ïY‘æžEZßKülÌ€ŸÃ™$ÕZSe¬>@ùG] V‘AÁi5 £*+|Lœ§d‚PSgþ90ÖøâÀ~˜1ÉÔ%b;#Ðt mÍ:Gâ¨‹Ž úÇÑø¨d)ŽŽ²u²b4WQ`ao“Q¹FØY+„¾ ´èÔ—•Ú‘•î>õ@ó˜œ:påVÃC Ó$RˆŽ ¥ì·âí<}óJ”¨ˆ€‘ 9ÃY æÓ6¬>Ú3<,ÀÂÇè°gùè¨G‚_¼IIGì˜`ÎÜ’ÆÂ8à'jwÌsÊ×ÇõYZ1Òa©‰Jt"2_U.ÇeŠxãJqqsÀ¤¨ò’+…¨(°(ô”—œ+Â8 º%a(wà „€2ùëLƒ²®òÁJ·†ÍüH ‹È 8nÄ_hìT ìµÆ&»”Ñ%Vô"V„z…e ÚãÈ#­äJ¢¾[¢"D­\̰”£"UL¨åÐ,¯ÂJJÄfËônìÎÞ EVƒi!ËŽ<ŽÈ§¦œŠ ö­ÄV𠂉gX=̬_M†|fÎƦI…ZÒÂjÜF§Œl/Šyçh÷CRÕ⪩h žÆlºÃ þŒ¤öíªÉåL ã Sk¤ÐÄ䨎!& #®ú/ˆl6Ó…žê¢DŠPw¶ê/ŠÇËÔ:ÎtDLˆo¶læ~-ƒÜ"¥Pä‰è7.Z˜-ã(þ&°½ (¿ ``b `m:ÀîÌH败꠿""Ë(ñ¦A ÆÛŒ`äìJbüG¦`*±Öa¢wÞÉËûcñÞ‘øYQ%ü9îÎ JÚ ub›qŒ™¥ÒJÇz¿‰TjQ^“P®oRiθTÇž¤&.ÚkxÊkJhʣ¤Q¡ ø!´¤ñîò ²±"ØÎ‡žÎƒo¡ôŽÇÒe ±l„VxüQªf"v¤-`ž ðñ«bSmž­®öËüÚÒB_oFãžéÅâ‡éÆyCvDüL†‰ÖÆ+hyç: &t­Èu¢&öMrŒÜ_Cw#êxð"^Øâ¯#I˜$RáÅJÑŠqn@¦êè"^¼Üvèãáý) ÊÜ·" õjNX†Š„i¬ÕÅ‹.àåŽÆšc¬ÒÅZÑb c‚k3¯ ̈» °ñì®¶‹°ªrXñH´¼gU-nŒã2ð § ½"èÚ+ý¬:ÿî".ºÖÍ.oKåow4`]€c"xV;©Š=/Æ]jZŒ6ò òŒ JÊ"²”ǢǙOí3¸yOù<êæJo8ñ¸ÞŠò3<³üÛ1´¾ª‰20Õ  êã@ C˜š Q#‰¶4Œ²‚p-3ç$P>òË! ȵiLþ‹š`ðX%QLç†×òª†Ð2®ÌŠö‰'g¸–骆ôåè´ë x²˜±i× 1 Àù+êá‰ßAˆîyD±JjPU ¼LˆÚ¸›9 N»ñV¾¨ìªkÖ!/s@P<Žúà‹ èÜ´~!¨z0îUd&Ói®"sêr”d7/4œGÍ"Òð p=,ö4”òDÐÄEnÀð-²DÌš”Ðq¨â¡3å@ŽOfL 5oꤓÝSgpJd@©gÙHÏô^;4à}çU1@6!ÿ6iNކ†ÿÔ92J®å0X®€ùíÞ¶«1IŒîƒàr¾v#â£vô»¤`&¬ÕgS®´ó„…<€;óRWÃÉ)f ]MÁ*ò œiÕ K©#”’¹²j€oˆ6#¯*©°^µ.uPñ*ËÌq-t'ÏòUÃSYÆh,RÅ«û" (mNè«’¾ÛªâÅ3žƒm!'Þøo´¤B&DÆÄ+Ê$e$&d”VXº#õ](Úd“Å kïNQ@ú¯­+Q¡*¾±u€¿LK^e­ÅG*«i ÓÏüÔÓ\PB bÈ~»ôK¢D, ²ÙÈjŽÎ®:Â>UDžDnUhìñzIªIƒUà¼Å7YÒo!étÊ,¡>ñtÖ¢&T¯6Ó¶Xv¨k%i$M@eòu—¶Ï¹OÔ«¨üñ•„ñnœfš¤3àŸ"¼Îu—DhZæ#I$õò¸]5:†¦Ò(fo4v< ˆ©Ï3 OèÍõ3ŒNð/wÉè6"ËM•EO·0¶È¾¿'T‘.ORŠƒ¶’9åeC6 z‚˜øodWªË6äþ¥ tÜ]CN»Mz]4%#tPF>‚w P{ænT.¥ìK«Ì+‘ò˜‚?3䢨ì ÎÚ‚5Ïd`ï7R0y¥ugkäEe@¼Å¬‹HNiZ³#&¦ÑJƒ¤¦Ø.ÿ ·Yòün+Rk;¶Š´.Ÿz,,t±2TÍYUÙK cFL¥h£/M™> ÞRkš¨åOoBØ­T@‹KÍs²:äUþŽådd“,]ð­këi…HºoÊuH²òÇ…‚†lc êgüõ´urÁ[ÿ,TS 怎w¥cX7bÀ÷X£*&p÷wVÖsuk^Üë›MØRX©rÖ‚$¥@•Ì`Zœ[«aD˜Aõ»bB© DĬÁéL Š.ç4í,QBDÏÑÂX²RÔ”” ¹#MŠH-u uïg%@±÷v¢êCô즪gôÕ¤EiôUgX‡çO@6;BÊLl鱆›¸›Z¨ö_sæ…¦M·Y®5e¡IxXÂCCäI”®ú·ì:Â4ÍO6#Pà”¼ãÜBjl¤&‰ RK.m0¾ûhNA©ú-™ 2†iÏŸ¦Ô!%P@äñ.ƒhK9¡…³Jôsj…k˜…"¸îÕj¾K Ûm úÀ‡K¯{O ¹uÉ T“El¥~è߇|‡Z<Ž´Ȩ?½Ò{ß*–"ïÌišpuOZî!ó“„Ë(è¦5Ѓ­I×^ŽÏe3Öt+’ŽN–ÐÛ¾Ô^< ÊÇV–(".,¡ãõBÀa¤­-ËÇsåÏýŒ­n¿1†ز1? –n¼níx;ý¨(]’¢}ž¯¡ˆÖ˜Í•™FSô k½Ìj±çbð$ìïì+_ß'¨ ·é¶ûV¹°añ× †Ö‰þ}òœ‘Aìn´a*×gÎT¥P  ßy.({Õ¶9í5»’Ä‚þ?à€4 ýBPØp û‰BñXT ‚FßðˆT~ ‘aQ°4û)‡?%’(d6@‘KˆØpFæ‘xT)~ȡЧ­I•Ë&ÐX4:G‚P¤Q% ‹O†Â!iÐ$û¬€#rðYõi®@ªµh„"p¡S_𫜠c«ð¨uÃ{ƒZ_SyÅZBÐXÙóúï§L£0êüs1BÇæõú$7/‘bå5ûZu"ÇÉrviä²ù©¨æ Õk´¦’µÂ`Ø­Jë1ƒWìvXÓ(Ð0‘º„fcΆÜp’*Ä ùínn4,%ë1nˆkß—îÅ“[kðG`Pë ¯îÕÖ¬ñ|’Ȭ0¬øÖ=‡óˆ†´èk¬Ò§LŠN$GÄ‘/®Ÿcrš&Œò2ø¬*âПí&ÿ¾`h‘./Ú3 Décªè$râ±±)K¤Dn ÐÎGp äŨsà”Â*útŒ#(òA©¢6«=Èj¬—-i¢*ɤ +ë¤q ¹JšS%¡oÒ )Q[ðáGK‚pºKId$€2ºÖÏ1±úí3 ÄÔ<èÛ›4<РôD¨¦(Bi>”²zú1ë‹T#p¬TÌM'½F L2ž‚! ÝÍ/"L”%M‘3£ˆTMŒ$Ž8¬Ã6߀*úh´-3 Ã0̪ú… 'K‹w2¨ ÛÌLµõlª/½93Z ˆõ¿¨2âÀ Œ$ÙiLLÛ$Üg8 Jµ…(}¬­¯ ìŠÊÀ¨’£a6@ ‰TÔLl€,%¾ã+‹h †Å¯ŒU•®‘O·MhZñÒE…Ó8J 3ˆT©Hßo„€¯å ʦÌú¡(E±e¨„u¬Ï»H~¬Ñ ‡Ìgí7V@˜–(¶¤Ÿº!ûKµêW²oò3djóUƒ GRÖ®çhÍ@¨P¬ÞÞz,…m æ ‘m¹ºdQåÞóÚ™æI_@ïÁW’<û²€”›a„ï(üZ…Xˆ‚…íˆTû9˜ïÀê´æ“È â˜¤Uï:V²†ÌñgâþŠÏ²0tèz!›ªØj ÇZèB€UÂÓ5ìœõéúßZ¶cb–ª3Ȧ<¹UTwZ6§éþðð*Яµ´íë'ôqúõ©0¶ï„°·,Œ½ÁG Ek=ü’k#‡Ê­à,léų£Hƒî^¤Xƒ:u¸r€je-× tbr[c7~ýȸÇÒùYPCÙ§µRèˆ[“iì}%$Zu KlU|äúéKUtîHA!µNú³mÄœ:wУݙë&…̨¸(óÚ8[Ž%5¤×âRSëU1êíg†¦LÞŠlC}§ºw¦‘ëgý7=Ù? ÉÈ•: «2Ÿúi}ÅQ0'(¯#\¢8 Q>ˆ2Y–(ú>/ù™¤ÊËä}!E…-øó–¤š, ?æ‡ÉÁ„.Ù½ÆäÙXi4[g†¦TË0˜Cé3“`ÚÀr ŒP[PÎD®º&!1˜€À¤‘.e !V‚I؂ʦÒlXs&8D’*Ž#1œAŒdíK6”©Écàfq:ºåÕå‘'(ãÕ5æîp!ú9_±Ù Ì·ôp)yÿ{í;8Bn\4^C(˜î’—j¨éÀç®R´dM"ËÖG‘ÎqÆÓ$¤‘h¢ Ïà û“\0eÓ@GY;€˜tU£XƒÜ˘j&SÈ=éȺ‹MÛ´Þ8éGÇÒh\hA ¯‘›—–°dÝÿ‚®n&ŸzˆN¡Ñä~æB²{*ÛÜ5yt Å8*‡©ì¡[‡0´¥Ãÿ h2¡JgÚÒ #"Oý·ÍQ^R‹kQ‘ÜK‘‚ÉçÊPÈËÃS´Ì&œCTEvV°ºê—aÛ¦X'Äݺ›d?Y9¾Šå|UÙ_˜9eÏ.¢˜C»Ví÷*í(ÿØÈ6æ£}}S«óŸ—<ÿ¦êà¹o96\Ú· Ex)‡µC\ŠSgÓV,I>¾ç¦…^])(½bvÿD% †Â%>­zŠg¨*˜Ï"NãˆÛ§Žª=ªÁ—ÜŸjŸ¿‰× ã4“apú(-i²ªyt©hW8$w2ûŸ!0™v¬àÖðTS-¤¿–«Y¦ß…ÐZ±»Ìc-8)X>ßô®…wÔäPìgsâá Nãú MÆßNH˧x3´ÄÜ ú!9'Xü}ª»@Ûô»C:q Q­J0ó'mò ’£ÖpU®ÐûQí†m€2ÌÌŠI†¤á ±¯qša.1(ý]®±$£bjüáÝÆ-¯Šüy÷4å€û°ûbX2ÛÛ•ÅJmq,b/dñµ«Î-8û0Bó•¾éd» ¼ô=Îfä¶'yrŽ~¤F„¯ ÜßÝ7#Ujšlñ,sà–&—^¬Òg»>Ɔ ôäL¡õ¡Ä h÷*ÜÖDŒûœ5zI¤’\¤Ü¤ÐÏHU ÿ ÉyLóûmù­ íØA–“ÍÆ”)£`¹BUŠM¼êkCßÄ€Xùª)'®ŽÏEFûdà …ÇŸëÖ­f1Û)4—oÄq”öÕo[ï/&´*šød½¹KTE§±¸³ËyXRÞ>ÐGåKzMt¿@<÷Ó].tï¨êEåÖaÇÓSG 7¥²'A ±oÄgJì½h@²¦»$<¼$’úÁO{m ”û:Óó^ í4ŠÜMÞpýB¦æLnV][ðsÏzu>žnÚ©÷wä:+î,ž{Þ’ƒïm]Ç à<6"=Ù@³óín ˆ1,ÈEdæåN§®–4ú7}‘”M+Úg ŒwrÈQ¹7rï =úP Ë+ª(¯¯£®ŸûN*“ª{ˆ Š‹3³¿!¨™r° ûÑ?J佃9©[ ˆ ð{Èš2 3ú¨zÇ š¯ª±2 !&-Kž¬1׺†Š‹Ì7*œ ;4 Sìp‚=ΉÂl­šÝá5 2ʪá"Ø‹ ˜µŒ—ˆ>©¸ûÁ"Q’8ò*Ê—©Š ÀJÌŠŠ•/ª% {‚±½!•ⳡÿÛ0¢‰6ò÷ù ±1Õ¨ô#µa2­‰, ;\€)©ªXd,’’lj‘ˆsÜŠIJÑ—äAB°2 $X¡+p~-Š»°’#µzxPš/¢{ˆi °™n±ÁX³I©Âs·ð«:”<‘ ¾J°1 ¯£ÏŽL+³vœkYŸ ȸÔM‘—2Ü<œq2¼¢­¡Cy%уšÿ¶(À3n°3bDˇÜ9ãk.YÎKÓ‘Ûj$eÂòW¹˜“¾ ´ºÛ=µ;6*‹Å bª‰˜‘ ¬™»"kØ¿“±›ƒÃ kHt ¯â²‡¼)(à#ª4)Ð|ªÈûš{©´ŠŒyB¼5ÅËqÆ; qàŒ Â*]Š˜î¼)Á‰LFª:§ –:º¸l8»²#3t0Ë¡Ú?ÇL;’’q0£:>txˆÓ’&·Èà) âš1i »GÑä"k{0Tªšº¿ùʸ÷?ˆ·q6B@ú?c…®ã4³Â_¦铪µˆä)ˆã Úì>+ìKkžÔv ådc;£]ºùÐìdäo™3¤$bÊЉ$ ÷ÁÜ6–ƒ 0Špš¬2‚§°»¥ô"ë@–£ÖŠHÂ=»2ý®Â|›Cšš›_ÆsM¾cn—´/)òg>`¯‡¥gˆRIT…Q:ÁÁ­J ·OPA5¼|ž·X}¬O ;’Í1Ú =g‡¡Ã(¬šr/Rí²ûÃÉx±úÈŽ>5ÊûeL[¦RØꧨAÏ Ô°®.ÄO¬²»/¾‰ÙÎ*¨Ób (é—UÓ…EP9 ÅcSºNÂALÁ¥BºÆ}U0D?Q´K*«´ X€½·£¶ Q¶оí>‰dqNXúlêIDøÆÒ÷™Ãš%lƒ®ŒÉ™A0ý-•«èØáâ!é’¨ÔKP€+ªÁHå ЩÁ@{@¬Ú s£=šJȪì2¬ŸŽK½Ç¥^…”Ôÿ05G: **iÛå5<‘)X™5¹ªý‹µHQ‹L†Fš‚E@Eݽ7Ó@˜}aÏCºQé¹HyRYŽ¢SÈíI!¹V͈ÙëkªŠ—©}ŸÈ›½:Èœ[Òÿ8ŒÌˆî:\ÀQÐÌ«l8ŒÕŒ}µ“d©)xÍâ<ÉçÎý'ˆ¸¯è³mPaà ¥ßÊY”€°© ›dÐÛÍ1 SÕÚ+µFúE_:¼À25#¾:åˆAß°i./+¹5<ö®]‘<ã:±nŸõÂlґݲ‡ó+е¨>’™[›Ùç1™¬U(¿äµR‰’­âKó¾ÝÐ}׳`#Èêú«Û“®A‘&¸ãö“KÁ9ÿSsè¬ÖEyV´¤ÉP„ÍæÚ“‹Ms 0ûšÔí”`%ïI¼VÌW‘ =úôà2ÊB8º…ú€”A’9Õ?ÙÁC–1a‚ºE‘)4Œ @ÉÄûö¬"/Å:åœËK¥¿ÀÁ÷öºø|âƒØ5d7Ãô&^$–â=õ—Þî4+@¼œôtÆÉC£Þ‘ÿ‹—ú€9ߪ*4B‹ÐID!.$ãJ©&´æRÓ ýŽÓ Ô­#ÜÚ ! ^³¬ œ ã9X ôeHáTEj+‚¬¨ùÒm¥ q.#Ei‡Ü[¥ ®µ…ÆŒœ@`ÙÜÉQ€_½¨¨yLü˜“h.Äjª*œÌ@è½2…0/jÁò"Dô9”O¯K² ä1–ùkвz«¹÷b½ï²° ¤ÎeY8ÜØÍŠª‰Ì–ã‘Å“Þ}}Ö=¹T'˜9Ã7½ëË4´äVå…Pá!•áã/ª‘›A›Þ[ê“8Žk@ÉjôÙ(´Ÿ"s°Cé¡É­±4¼u1C’bÀDÜ× ŽŽë!ÖnÖ„9ëÛf¸¨†Î¨¹®.*¨]éºY¶u‘É»; JÉß:—ãÓ¸ º¬f0—;tZC¯¨ŠüaG¶Š>¦ÅÐíb‰çM|Ý+º 0¹†°6ß9€G/ Œ=Ý´ŸýÜž³% !Ùl?ÅÄÎQ6 X§×ø]ÜI æ<øŽdjR\{²LŒGjs椑GëB+©jOÚÆ æK¡›ßÚ*l{(gÚ³B„ØK aK<9„Äd ÏÚ3Nìl(éM^W K.­~^ömºc"Ž«dÙ¨( þ~ àeB»Wƒß&lUW)„³¼ÖÀáaüAn˜*ŠãÖ² ž©˜åä@2áÒII|| UU˜bÿ·*ãbcKôäÝ©¶å–hÊ\ã8uüˆ–áåÀ~*ñŽõ<+{N£W¾ö:çíÊ \ ÍC3Seø}¦lÂè~Ëöí Ò”`ruE ~Ú2?³[¶3ØèË–Ñ|ÿ²j £…óVeXe#­f#@¤”°FÜwÏBs˜Û·¢rP¾@‰VMƒ‹Lšî¢þŒ´¤ZöÅq¾ãA„ºl¬AÌÈð¼ùn5 lé€O0ÆŽD%NÎljÍB9•ÍR3\D©ÖRÎõIAn¶ùQ6ˆ7*rìñ6†äz|ºÙ& ÎljÅfíälæQdÆúOKhfhH2þ`m^ ¦±˜WÓ@ãéo©|øâ­‹îÒo_äŒî QÕ³Î)EÐÃź±>l‡Üó«…8ÔýÙ&¶NÑ.΋4¿ecDàÚ´4µl­‹õ$£´Šåhd)ƒ²„Oî²»04jܬù¢ülç‹ß°A:¶í|Œ5œ—Û]{h0½{? ígù&Àh Ë8‘°».è ¤ÈÎ9®Ï|X7~ãð†ºÝð‹ZXñ¶6óеup¬\oýÞÜ9ðŠÃá¯(eV€1\˜j,4á¾ÇFl¯ ­Š”aàùM<°ÿ%äÈÉÆdkÚ垯XÕ.ÎäÇ•?lJkóDë¥U–ãÛš›è>dš¦× r=kàâ‡ì£¼JKTTà§>ƒ:‡¹x‰a n{R»ß¶Å»fPõÝ‹¥Þ?¾ôÊ2íÕxöö²S暤°1—z‚å.à¬1å]=“É\ì´Ãµ³•`æ=]'šosSLj06$Îk s¦®ím°¯_ô;uÉ%°Éß?âcÎ,,˜âZøÜÀÝOR$ `¸6Üe'R沪,ÁL§,Íཬ£ öŸ&î¦_D$Nað9ù6×Dû¥ Ü KaHµW#( ž¥V6ÐlCGE|Ž&²{ŠìhUäÞõ‰Å÷1Ëî >I r~f€>_ (  „?!Oèd4Äa°Ð$T ˆ¿ßq¸¨ ‰Ã!Ì<Fa 9dõ/–L@q™Œm÷(“C_³¹DŽ}†ÉaóÚ†QHã0§äÆ‘L—¾¡²‰ŒŽBþ”ëRˆÌŽM?’Dj0ÚEŽH“J¤PŠü&m°¿ê’É5ÖJ‰C$Ó·íN 1¥Â®`: FáŒÒ O™V|®Dc³„¢ôÌV€öHÄG1”_)™ýØ6“LdÑ÷ƶ?Í©” vs!ÐA6›8ŽjMQ”an[¬F–ï”G^ü¸þT1«É£´KòC‚I·ûãqë€dwÀG–™6Ç=6D²ýÏ–s¤ÞÐZ×qÓ^1³úLÁ¸®,ý:ið”5k¯4˲ø{B ²ò cL×¢040¸M£¨ï03ÂÊ'kÒÉ"©ª6Í;hëP‡£¬Z2ê5/r¾) ãT﯎jv†¤m²¾/ˆË¬³³°:ý){ˆ¯Ê؈")$ËDðâCÂHê›<+‚¸R{”4nÊÏÆÇòþÈ(¬š†LÉ 6çô¸”ʲ›Ä¢ŸÐdBÖt*¦=2Ëû+¿«„ó+/édØÂ>ô{‚HDb) ˜§­îÄø¯”à˜£êeK??óTþþ-Hšh–D v…¡’ò®û¬ r.¾&ÕšfˆÁl|K?IˆU /iÜ|~±hê>—%ïvß.Ï:7T ÓÍ…I³€3~\,\(ý4ÎS–éÕÐí EGÛõ3. ”„=v1ûn´BY£¨ªmeÚ‡Ôka¸À ¯ %3C" N%L®-¢£Bv ˆ‚9ͦ#¢oâ=¤hû©UGï¼–„cÒ¥HàñÝ^þ§YNBŸ® AqÊ({r8T°é"´jìÚ?M¤fŸµmFçCk*_ .× ÁYw£¾›ZwÔ²®äP%]=âÉ|(Ä¢ø ˆ¶±úêRp£Þ«šÛ®r‚$lRU§Ø<³ž€)’YX¿[â›a÷ÚY¤î&®€§–#ªaëË´Œšè‡½ïî~›*8 åP€;ã4”}J?lq¶c¾°8I¶ùŸâ—Ê}°vî,M£¸º E,â› 䢴s¿#'zâ@#÷vˆ4ˆËÍpèÞøŠx²Žþ81¾aQˆÀÛe)é,#ö¾rMÔ dмÂ@+„èt¾FÖpSOf´Ôaøˆ%)¤lG¹H¡üÛÅ‹b±‚´˜×),âS‘!IÃÒã]ë„­„Ó]ãús¢)`p²¢Ì‰²,~ZRÝ©»ZaÎJ÷N¤>¨K7ÂÊýgk X ù/Š#î~'ë«X€ ØÅTȺÌ'Y*݃0œKÊpÅþm¤# ÍÂ?>ýŸ—„ÆbÓ„´ˆ1´LµéÜ b2fŒ]Jf•Zöbx:È’ÍýqÓΚFUÑiè:–%3§Ø]øg…Ï^ð xý²Ä9¦Únçà;‡îÄ/5J}Òòèlhzœìpà¦L'‰›Ùu~°¦!öå]œZY›—äùÂd¼TϲKìM¢PŒˆŠoŒ§¾üG¨“y/¦q´”EÁR~ã*&‡¨YŸ/c[KnT­!FÒ£Ò ½«év=.â²+òÜ#ú¢°$"ŒOi-Œ¤šÐÑi“lò*)f>*c^4„ô†m ßÃ]ÖøÖÞ„ÉåŠD+n}ßÏž5¦n‹þoýÈÉ[wœ]•î—Ï8þÓ1 O8@Æ´ñxÔ­ÊLrsOÖá¦jrqçµj0kkr£”—Ö9ÕóCë]c[ŠÅƒ• úTMè.SË jµ#‚/¹mØüºP›5jöx/›6Ã2]·('piw<Ÿ¬%AR4Ì{ÊD„Ù %¶R|ŠŽGWþËAu®k¯ú?Jý˜Á&@Üø ¿ÎÛÛ¾a´R~bñ Ó«Êí½ 5QÇå¶Ðø9Fâ @Ðú#ºÅM–,&yèºy³+¯fSÏRíõH¡òîìßo«2;âë­sƒ‘¼o¼,-–þ`\×YxgE¿“hȬú4ƒ fdvÈû2Z42 žRbñ‚€³S\ê6äÅ«ÎwĹ^nàSÒJ$§zeÏàº)+ <›6žlÊÊ­KÕ ýºlw³BðHÚú³ƒ )ú¾<øqŽmbvÐíÆF ò¨¢CM¨`B6$g.®ÚÞAþöÆø €Ç&Æ0‡F˜ý/HòK¸è"®§Î |WbTlG/¡éJÏËìÑ l¾AøÀç£lFƒ‚x®(#Là®V¶"´;n»¥\¦ªê­I:!m ÀxÆfÉJµ® m†øèëâÎ ÈQGп-J⢨‹òxM} BYl´2ÌÈ§ËÆÈ ÈÈ&¤ ô$gJG„hJf~±¨´‘‰èTÆį̈Šx$fêÇu‚c 0v@eôæÍß êmš1ŒLM¬.Äïꔈ`‚c¾ÿêL!††KøÝζž°DI‚€‚tæ8ýOBœE`à | ìஎBõc¿ RwMz.%l½cÈÌóàÄ!ô×`&ÊÊ!z¡÷$˜,’Õ(FeÉæ”©Ð Š•îD¾%bò§!#Þ9Ê|¿)¸iÍ8Ì|Œq€,B^4ƒÕþ°Pžƒ)à/Ù'ZK. Ê†Š‘¤"ê‚ÇPÜÄH­í|sð_N‰n¹©Œó/˜äî|B"’Ñ/ ¨üòÊъŠh"©(d 2ãÁò–ðš¡ìà‹LX‰£Êm‹Üa>îC[ 3 FV"bÐêv™H3æ÷+ò£©O |¢BÛ Ù  Yl€ý±A¢^ÿm\Ýp$î²âY&MÐÑçÌìC¶æÍE •î€p¸õDö÷† yä;Ð òn\dÆÐÏ9Ëm)MÌ} ˆÓ%^yçꌫ4V/z­QÖ"©d‹Ôň”B^¡óÞUæ•d#)¸€,XObál<ÓÓÞí' ª~øCO/¸|o¹&ì­ É»Îü'ÍÊãÊ&1 tJ¯çÑ)«È¡å…’³bêg‚væfB¢ÕN"fÒ.Q2«JˆpÎM±É- £ÒÎkÈ£h¹£ºéXÆ.&æŒÑ‹=†E¨ ±*á4ã…j O$ÌßêÕ0“<[jЇ’#5Þ‡ÑÅ—(CîÄèDÏ–Ý%–è#ôܲÜgÍ.ÉR¾ ’R'sÇ@ÈnKb#MbÖ,ÇPe, ʾñJÒsEBœü¦ÁtF—°ˆôãªâkêv¢Xä 2¾&Ü^ ,oæ‹ñôÂñ˜LÏ«C‰ºã,.9Éö"å}ã„äße–Ø‹Q%ó(µ/ ðt †0TÌ#+$€)Ÿ6®Pþ¥heÏ伄 uƒô*(*6ôKvjÐËó4½‡¤ JC;d¡GIH ÂWl*ýŽ ¹§Æ,%Aj|É`“AõAtb¤nœŸÑjõCL|g‚¢µ.#’¶éˆ¿gçŒNYë_ Ñ"8Rë1Œ™ô®6ŒN. H›•fq3¡RPP5„>F]KóõK(M"êùíœtnúðÍÀrMÏ5*âÄãûSí@ «—KÒ·&ë5q²a$³K¢¤ÓO= ØŒ¬Â'ÏM§„*ê¡0•ßP.z¦â­F(Ë“€õN§[J ˆdÖ*½kò’12 n#b˜3U"_JªWsæì(çïï\Eú!Ny.‰Π1q¢õKlîñ`µjήPÒòªÀ¬˜Ê&$. l!´¸Òï̵ïgTlTc¨‹N-E'Ÿ-6Ál>²œÅímö&%Ü3Hr$ÄëÌÀ¶^&œÄå„€,ò€rXCd7<Õ-:çF~¢3ìYsIcøµòs'¥E<Ϊœ£ñGH§–œ†âΓÓgHeN ÀmÏ`C,°‰þd ‰6…Ç` Ù@ ’¬'qb)KA¶HžnAJ ûTDBLðÔ+D‚¯l í±‚@NŸoIU²øèRôf„$v™QLèÆ\ã%’];GÓ§ÔÚ¬žôÝ#¾vÕGPÌý³Ú¿/´èª a ȯŒ/Ȭ&L(Ýmc&ñ™(nȆ~9ÃèÏáú}“‘h“‡D“Êïàk»YÄòi’‚!V"×v_Šù14¡öiŒ²—ŽÛ8R|Á"´ë/ #« cü›·p¼GÑ K 5üÕl© MÝx$¯íÖìê°Ä3IMx<aÑèDÌÄjÁ9·hàÄ"æOõXAËÒOÓí„Pf_Ž2²4ÑÅ5L :…žÄëi[Vr)^pc‚ Ë_I2F † `,Ê wÙzöpƒ.3^®¦êiÿ‡GIdéæ#8©XJaáŒ-íή¯ôp­U§˜R"hÞ}¼È>˜´Þqàò7±q†q#ÙE3çmmÕ_rìãX …õoà }k¾UÑ’’3ÂÀ‹¹=·ƒMyL»'ý?b¡p.$ÇXÔ˜O=ÙŒõ6×G4ðÒXLÈ¨Š¡ØÕãÂî…Ýl !¡¯›33F«A4ÿ]•?T'ò‘ Á8L CbMH  à„ÕäOÉKŒ.8Jl'ãIË|§ò-m¬+ŒêGhÌÛó˜çr?i‘Sõ9n”ÊÖÝG—X¢×ñ™&ÇÑw`0ƒ¢ÝÆœâFøôÌ*z+tÏìl#,‰â¢‹Fœù#â·õSPÛê34íÅ[ÍÒV+Ãa2Y~Â)êæ%ŸKÙa·x‹MqÄ®è7~1.éµI=¦[0¦\‡²¶¸È,RºPP®;ã¿)(‚8Ðð´Þ¦jJp=š:7 )P%æü;øÿ^¸ì¸,µä@ÚeÅ&úì5Mb2©SÁÚA.TOÌôWÓ.ö !´ˆ²t@óÕ4ö\5nþ™½*'·•P@Ý0*ž”¥Ürê·÷Z"v”B”ª|°äÚò …˜BQQKU¨„b‹HRmR||{J*,3Jó2Îãî1jÁ!òiËÆbÓx3Ú®óï›°R…4Ö‡ÖÞ.,!’ö­÷‚&]¹É¿z§O±"‹C4ÁAù ô|ÛrïËI/)´ä‹4**6iÊÀâRõc²¼Ü7R°’o©*· ÷«g5Ú!ª”’ô)†0Ï#éZcLÖ´@bW¡Çφ¼ž;ªÍ38« N+W/'çò4‹ºÐûZÖ¼v¬ìJ‰s!øBŒóW0Lä1;¥áúÂò÷•ÈBýІDr€¯^JŸìÉPœH=˜³€¬·;…–©’jb z#hRy÷p«µÇ¿É)‘¸¸OGdäó ²nÁÓÑ­*‘À‘§føèúÈѳ+#®Âü«¸”)ÔÕxö«Ç–=¦6«,#—‰QË+x, –Aòr ªè.Q:*¾b8Áõ½¼.88a&A«i@3A¿ „ã=„b”vÖZ YMeÃUŒÜä™Cu®†ìfG¹iëìõÇŸdö=éæÃ5g]¹qeøÖ;•ÌtŒÉøî"÷•ùYG^³\áÍ‚ÿ/Æ”¿¥Ùa©?(e8Ÿ(3[WÆ…â’þÆÓà›ºŒ3w\\9ÜZ§æŸ:ÁrÞ  ùÁÀ˜T ~ÃßÑ+òÅá GÜnD_Ñwü‚E ‘@àp ® H¤R \̘EåÀ$ÞAÉa2˜LÝÿ*•Ïâò{ö3¾ærØM.£AR¡àzÔ‚A¥Æ`okÎÁ¥È£19›âٜ͢à[”*'@©BfR»…¥O™Òî@Ztnó5„T¤Q8¬*@Ç>r)ªõ§ÓãÀjЗKŸ@ŸZ|OžÁò˜®A©‘RáÜÌšqxˆÂ°9,¨aª€"s™D éÞ€wûGüÒ§ç û&¦g'âTáúø„G¥™Ôàp9Ø}Ö/™§‚}   ‰wá΢5I\fcñ‡ù°‘l7•v¡˜†¦hï1ÀC0,躂¯èzfÕ®Jz¾qøó½ (úŸÎ;þ¦iØ|$OäПL Ô³n°…:¨³0 #1#n¡©.ã®0ª[NÆhz ìJ ÝIÜ.ŠÀ’þÆGÀµ’AúŠ©hRöŠ¢o ÄÅ¡1Z™°. ­G郔»¨À,7 ”ŠˆÂô—·ÎkàNsCD¹?Ú3ÎHK+PŠ"°~½óÀ ÅI‰»I ¥è¼¨¸ëLÝ¢p²jTïýB~2h+72”>Ò.É,êÈóö)j|®Mk’¸ˆ¤LÍ.¢j[3¾ˆ»ŽõËðŠXÄ6©jº†ÅlÝ$ŠÅkBÊ0í}¸ó<²¢Z”ôî„ñÒ»½H,¢÷Ñéjì».ôóþ÷ψU˜¸ñ‹Û7YH½HEª•%=$(Ä•©íe…} Ku…W³‚&ÌÇjI`*à ­MŒŠà»Š~anš"©Óƒ®hJžÍ©x0ÒA‰‚ˆÄ~[¤x–]#A@3ž‡£)§LÁûHØv£ß"vÍ…{âÙ«.}Á=]¨ãP[ÄœßÚf´ò£ÈT {ìu41î-½ù……Œò—IL8J6NØ„Ùè<øæ=ˆ¼LÙªZ„0³!úpzò÷ݜщk· o@‰ÞâErÜPjÐï|( r4w&~½iœW S»¹U‡åÔMˆ/7Œø7^(jš!üé5 _šÄÉ›S%yÏsñz´ê>hjŸhjH¼af¼_“où¦ZÒëÌE€á $MÕJ[6ÿÛˆ½Ëú|d/>$õÝa….ìñá*_–“|%p7ըśÃHÏH†¥¦þ@ö3¦mO>ô.…˜s:Hÿ7€_!©Œ‚¹X‡³ uä<½¦DRŠás½"&e!æ ¨“¬ °øýÓR‚ O[ #3L–ñrCëX>w”pâY3-å»/bâ…"á"f¥Ð™¶JAW Ógªqó1ø(°—“[Ñ~)T£Ú9KÑß7ã¡7vé6%¢@Ê!SnN„e„21øè_Âÿ+%iEåúñŒ)ÿOç!ê<@fÊ|JW€§Ã€ Ø’EMï^4ˆÐ[˜útį2 âIY™fD¢-·¬Þͨ2 ¨Â¾Ò‹¼^EÉ)(G ‰¡L'E£%…<Ò“é¼>äyïsÈÊS„Ê!&üŒÅæ@›^¹d‰@Á´ž×JX"«ùž.Gp”IÌ#‘ÒÎTã!#ɽ.ìüÀõ‚žàkq@ DêÎ%ÈhkµIÇ@¢Ü9t$)ýŸÄà¥]²€#éQhöñRãQŸoåÀ—cäa¤1-C.EºÎ¤n]L­sŠÊ|Р “€jl”+䮎<úô…8CµÀ*Ú ñÍMh€òj’•©òJµBR›š©ÕpåH*0QóC„itÒ-³B“Õ*BFƒr»*ñò‚Ù 3h™¬°Â`ík;qp²+¤$VÜœ/Žp~¼KNë€ú4„ R²[9È:w‹KjâéAÌ‹Ê9OX/Nå­¡t]OºÃXêNŠØæ%Öêé!<ž¨55z­G|QRR“•@Óv¯ŸS*:TÞ!ZµÊÐÑ36+K<òÙ2ÝÄ9QE_’´ži(ñ¡~¥iØÊÒ–‰–13|©>h+‹jpë½ ¹]?+S%ëC—†…þRØß+Kݲ#ý ¯Œ åe“ÎØ²«P Yl”%ß1dš?[¡¦7´‹Ñû0N]ó˘¥J €.=PBQ])cºøß³t2[صVs)ÔöÒ±;‹VÚGò&“ ÕÇ)Þ‚1M:Æ„ZÈ1þ{ÒÕ“øõ«ã߰与íÈÇÔ…bk£îù›ü3ŒÉ¿57µºæ]˜ç….±ËúïNšöÀø°òµºL#ˆ,±\µ©@·YªóÕÂÐo²ŒSÐë¼zÉErè1òŒo>°Ç®mÍA:¡üX=ìñº¬[A~É]VqeÞ*¥„cpâ~!Éšbœ¨ÿ`ݱy /× X-ÛS¶0¤ºzÊâÙÉD08‚ÕѨM0†5ÆsôËÖ \ŒÜ½g5Zù´ŠG}3–xUTà=dW"HöB©•Žc5$§é©-î¶-Kw—š‚€••æ’b’ëî§sÉëã깬1=oòpÜìrMÌ20­l–á$ž²"®8%­^í<àˆW`|a]¬‰n×®ó0JÓw‘ŠQºÀ ˆv®²…ÈTØÝÄÈ‚?§ F’m2}ƒŠn¸ £¤½8åe¶¾›œ¯BsEhÂ4¹‰ ÂåÌPÒg¨æ‹"¤Ãü‡r! €^>P±ë z¢Hžv¸ÒK.Þ„$ÌäÉ´ÿ6!w•‘Qc”§¶DÔÅ´8~^úÉÌElÿYaŒe:›­{쨧aÁmen#f`ïypriTá5=ý<•qÒvû7ìóÛU|*yÀõ£BiY¿³§ž†å¨GtWæ?{Ň‘¹ §TÍùV´‰ß±ŸþB渃hl†¹Rç§$â2ˆ’'CÍim™$J5Ô “¤MfþÁ ¢hš÷Í"7#ÿE ƒú­s‡”šÀ­9p©@BÙ#¨”7êš#r=/ «BV˜š¬œáÎ ˜À³)Ã(4b¬µ“õ[ç‡Ù#0ŠåJU1Kä‹Û˜Ÿaš k›±õÑC*™a0ЇêS¬`”%RÕ¢Á©Œ 4J¼ZËø»‹Û¬|· ‘˜‰¶È²Èˆ¢ðÆŒq· Ò»z¿±è¨ g%Ó=‹aû’h£q¢HÇ0è­­3b¾»¬HÇ3à‰™±L¤kZ‡ê+šw¾£—¾YÁ.È©ó"§‹Ð™·-‰  HA¡œ‹R#t 80ŠIÐAÀ¤ñ¦št)ˆØé' DYÀŠ\6AßSY3º¶ "›pÌÉ "óä»Ð~™Ró¶jC(|9 ¬Šò€9ÒêT2+h(±‹&8³¥0Èé(´HÛ&:‹hŠ"à "i¬¢[@c‘‘°Ðµ*Fû# »ù‰¹È¼Z_’èé#Yë˜[ ÀJÛ©S ù¡Â‘xˆ‰Ê¼Ûó£Á)ëÀ¤ ‚&Å·¿Ü_¸ì3 Óâ!Qõ3‘ï¯ãþŠä:A:&Ô@!j¬-Ì+Ç3GµÚù¤ãÜ,k³¨b‹+Ò1€4$ˆ»G’2·?$"¤t-ô‚Àz£›÷°’™Ì¨k½p¬àæ7˵;u3‚¬¡ùß.§T’ØÌ²!BGœ Dc:*@‡µêp‘4. ¹ô>3æ"Ä0T2I„±89ðŠÒ^¤ÚÆ Œ³"[]•S!-˜›¬€¶‚Í,r¨Žȹ#€!ŸºRÊÃSÐ*àÿÁ눰Œ88Z¯:T12Ãò5“}Ê\Á²™Ý‰\ÊAŠÃBïEs8£r|«¦§!9¡o¶<™?"ÃLªÁb„ŠáÊhȳ¢÷K  6´½ #=Sá‹èÆ,}àÌ—ôÙ¯`­3’õÀ’ý43YÀésºk>±ZL¸á˜Tr¾l´„ž/£ƒ-ÙžEŒ–@7‡ó]™D%,iÞ!T®XLLÌÂNžâ'Cô”! ò±’ñ= ßO¢P °I¬4¼Ò€ pÆØƒ›p™Òè6´¨=ãФìg—C*¨°Œ°c½ÒÉ-z„*ùÐÉÿɪ®NÈQx3»>K2Ã0ˆ¹ÐÔÌZðбM#µ\ïí& äá>LÙøÒNyã̃&•RÏÜ  °Ò1JÅ8QzFª¨Ã¾€-Ã*·k41ÉP}™É>=@ž³²ô*ü¢l« üÆjïÕêø½·ôÌ ¹Ë>3j á ŒØÌÑ0y‰×Ù-$(õÆëšÆáäRúßXõÅð} õY á /êZVZÞ4HÔÄÈÈ5ìîP„N zšâ94zµ‰[5ÒΡ-à»Xú™‘‘ó§€-ÅÙB‡ÓD¯ù¨ÁS‰@ ßœBÇ¡Ï5> ËÑcׇìöIt×@ÜÓ(t,Ftš/Ѻ² ¹œúTd Qè ]g©Q¯ €ÝŒ*95ÍL‹³]ÒXÔÿ¥øé/‡’”2SOŠÚÄ )‚†9©Ô2løA³5I'œ3àãÊ% $¨Î%”¡Ô¬4­âT(³à×C2Ì«"Ësâ¶ÝO¸R ß‹’p©(ãžµÎñœ ßÚ™Ø •µº t‘¤Öº!L©s³¢ó¸³/x˜ Ý‚HÁ•S¨q…ÌŬÍ $3€ t¦Å°žD†9Â8½LPCVÏäĺ¹š AžQ‘§1M}€mP©È…²e"€ ¾ŠZY:@þ›ÛiÖÙ²‡éòÕÀªÅ ZÝH‘*ü­Lµs¼|9S¹ÈÚ¬2N‹%˜+ó¹òÔ©©±ÜòP<*B.%ê …9-åd½ÕÌ`Ü›’}¥@ýˆ<ÂqIæ¦2˜ÝQ¿sÙ=(P99”•ÕÛ­Ë«°nJiÜ6ë·Ùø{´J¨\Ôp–Bn€2u°Ô¢©<âØ®…Ä¡—+ùÑÕ§ÏëæEå§²»Ý؉ÈZbªˆ‰lHq¨Æ)Ò\l]û)ŠaЉ8QßÁ$é’­TªÓ5xJÁäá*-7Ä!E…¸"Àáž;¹‘?ÅÍ ›ø‹ˆ¨ÁÒ*%n‹²î867Ԩ߼•! Ù ›Ü§^¢V¦Ñò¡Ûµ›ÊÝV:¼æTè²’ „)IëßsIHâÖFãÙ4Äœå‰ÈìüN;^œû҉ɜŒØõ§PŒ²]¿3¢˜‘¡]ûÚUu-8-4#PA(›Ù”K…ý&Í­¹ÒQ·>£eÚ¾/$„ä¯É¤œOâù-Ý~g'€’6Dù\ûö‡ö hÀ¤½öPD*T‡°¬[;H–ª4¯ÞE6•Û.]ž ç8N*†[££K’Tf›²}¬.ìã’wËîGŽ×Ç‚?HˆÐÈŠ¡•%è÷ÖÅèÈ]œ§SÇ¢™`Ö<5a@Ì®]ß[t˜Ï¹GÒÚ±äÙ²6SvXL¬r-q:;BV¸b!^ÕÅ<"P:¢æ6½´×©› ª¶H-óÈ£´31Üf‰«ëöO NÍäÖ:† *É…Õ üæ–Z"Á‹Å#}œäÃܽnm $.ˆjuûs…5ìÁòNžþ>_FÅ.Y¬ÃÜ£nË!·b¥¤kb¢ÚJ¿å–ˆ)ŸÞ¬²ò‚I·:C›-i'­Y.“¡¨f|!ïÉ=ŒMÅ'}ä×>X9zóÏ­[=Hè5rU²]Ȭ¤¬¼ODÿáKÚÔ®™‹b©!ûí–ºÁ‡û»DTÅT â5v‡`½Í¨™ž1½$½3è1‚1Ù:Jc·È;2ìɲb^š’á»D°&ÒˆŒáð0®°eª,$œánÉä6±Ì»•Åà«K:RUAA]"ŽE0±#]|­´ÔPaCYDš†?cöMIaRso&¸3¦á=¾¹-™u›ÖöÀ*¾ZÒª°fì*ˆmò) ’êG£“óÝ ˆE:H<\߇Ѻœ­èë Å60‡ð̱KPvÌ—À•ë€|3Àys:ŽÎ$kZ|wK}*„¿ìízPua µx `Òjms¨²m9æZYZßJ¶‡3vVéß1:P`Ýï)\e‚ù¡`óßkÚ+,õ÷_ý>)ñcïF¬Ð.³XY ‘¢»\EÑRusa±—-\lUÎq€ÿçè¶2c»Οܦ,½ m-¡ã@•žÈÖÍ8¸7-eª9?@ô6…ýžo–<Ô)KécD®Îßü[ëj°)ÊÚÿ¨Â£\¨ˆšDû/×p,%®¨›ÄÐáöê¸ÎÌÀ FªpØsK§kÚB´GZÃ5‰Zg¼_ÈšA¡&•ôÎïg:T—;r@e’èk:J‰õ8B¥(r9}6‡x¶(­ƒÃjG¬¹>!¾ÔZ-v—/r­àÓ~jRé©þú¬Jú³çiËæZjÀqÛ Ëé>8UC EƒÒˆîý‚`ÀX@ÿ†A€/˜„1ÿ€¢Ñ(“ò5… ØtJ‹¢OéD8+–D£ò(0e,™ä²ÉÄæY(Mg’yDJK%Íd´ ìÊû‡Miê„YQÎè0Ú¥JW.‚F«ÏÉ,Ro+•VãùÕ–q<ÓfvJÔâÏhœÄ§U;ª©,¯Qf³)ywÂN¦±Út2gš` Ϭ…¶ne_xè5^žW£°êôR ùirzK Ãù+ße¯O&¹Ô³?Ï0/ÛüÊ?Kñf±úôÖ[ –f€Ô‹žJ¡C‹Rõw³ú…³Ã£º~tw¥££E°r¸¤~IÔ¢`¥0möò Q¾F±oúÍæã0ªÎaκ å£ â:Š+‡ëÚ&)’앤©ä ÷€/8’±+ í¤Ë;¤ÿ¢Écp–$­Ø®JÄJ†9K1þ¶ K ·Ã.c /ÀXÞÂLh‡'Lt2±€ ê4µ'H“ŠºÐúV¯$(c¤¼E'üšÑ¡Ê[J>2º$ç+Èâª=H$þ@ ªÑÉ©*½DÒRà´(Dr÷Èr(Ü;ÈT¬‰´hŠ%x¥¦¨¤Ç#ñä¦ü>’y&·4@È@¨D¶(ñ¤Ž”7H\¨‚Rè³ÊM¨‚X±"Ѽ.é5R„NŒ'Д›Y€IÒ:{WÍ´e?’¾«­iÿ#*äò~ÃNtŠ)múXÚ>ó‚4ñ>s³ì”8 ~îCê$ÔÉ(3øä©H:ŽÚp\pÂKîÌØù³Šrõ€NtÜ\¬t;1P™;ì¼xìÈÉ+G!“ó&¹ÎÍñ ÜPÔ"¤€r«üƒ]à )BHì~@ˆṴ<ÉD-€.v«£ð€ Z—`up¥Ô`%níT ,M‚UWEJ~Ê×Ö2ü€4Ø ×DzÚCO"eOŹeÄû·$¬µWUKq@îs­7j©¢’ns™:PÕ0•¾ö{4·^øÎfX9ðç)nt¾—èqª,ªA13Ø–n'õZ„$¼~ŒŽ¾§å{_aÇú;.r·/ÎÖŽ•ɘÏh3O !ØœX‰7 ®àKJ‹Ùdà'F[§ò)Œ½6Ý"¥ô@ü]I³©°ÞÚÖèê ~ Ë%wr–6G¼›Ý“VWÈ%yóЊ! –Ú'TG[89hxnEµKó2 £R:%@þU*[¥­B„Ôç&tâH2Æ€e /SúŒÐÁHB„Qê¶t¸Y©ÂLîm §ðÿ•u mï†l¤S›HRI\¯p Ìñ R§Ô¢‚Ôê¡2/K§@iä~6û‰Í"/Èœº¤=éPè{ÚHÐã³õ­ †Êbr™ýB©#|Ô# H¬ÒTžªÚ¥M`ŽÜ`“I„Æi)¡Í€u™L"+T¾Â.W}[ ‡«Joøœ~êþšX%6< þ;iŠÐëxŽ+%“V¡VÚ¶:}Dä0¨ý‚džªXõ` Nl˜ËaVœ£+ŸÇï¬6éVíŸù(@+>âùZH¤;cšGu½»nÇgñXþáýÅÊÀ™­d~TŸÊb½Ù§õCh}NîαªH"&ö ¥éJ ß1ˆRÀB J?2ic¬‚#ëúbÙ¼ 3ðƒ:Œ2Æ×¡MCf¡§ð€Å»IÓì4(DHA "¨"¯šÅÅQÊ Ç4i’å=dŠ1Hd*, úÙ¥(ë܇µ"ª?ÒR«¡Š£t-+Jœ{@ÈbÀš<’œL¹J("¸¦Œ£š9R|Ý!Ãp¬È¤p#ÂÑË ûÏT 4 Ð Á­£€³¨Ë¸ÁP¬CÊËÈ2¨'먡«dtÑìT‰³ô-AQ ɤì»rÕóAŠh´¶©"SÒ”³òîÀ¶H$C ŸÌ«TÞ€,[PåX å‡F»ô²ÙÚlÙþªK$åmÛŠªYVÉ4fÓ§iâ+'T/5–Ü'ô|~—­ró®TU¾å>ÏUž˜8 Çs¡“ñøõ,mCäƒÒëa!î2M‰p%ÛQܯ æ“Sê"þão«gQݯ3÷<€1€ÔU`˒Ƹå}£S‚nÒÍš©l´¶õn€'Æ„£KBx¨cÓþj}¼µ”Æ¡¬hû³;Ÿò£-jG]¯2ÞhO‡ÌZÊëµfgä‘ÈÉÁúîʨSê“8HBi¡ ûœi*%ƬTo´¤"{Â*´ï¯ú2©¦+MŠ¸ÊØó»I¯¶¶åF'î¿B°n-B¡ä›nÒh›©`ÐU~ÈôµîÊ¡µ<‘è êñ Ù~AÑã§ç[k͓ŒÛä 5q²–£ôW^0dAÕû8ÄîØX~Û÷Û{×}\l~>ËZ“ŸÈþ_5€7¾w›Í  p„f µ刎çû{¯€³]ƒaï Rd¾cÑS™s¹÷¿Ç“‘11gH˜°g_‘òGqçu$¶µÀò 1ö0n À`ߊÇQÊ5Ë-fж‰qÊ®¨Ö^¶û×…Ë2±BUÄA0Å0“Çò߀&¡o°’tæY‚‹áÑ“GØPÚ±zªƒ¢Ò\ ìƒÄM+ŒA—| #­à‹»’2Ñz¨GȨʢx¤öÚ›£M 7´®Ü|r¨-U »ã©r‘äÁ²ó2DNLK¤Å¼7e ׋ã;¯˜BAúþâÜoñ´~DŽøü=J ²*SŒÒ!<ÍẗÓ‡”)žQ-$±¯PÜaZÚ:lAýÁ×ãñ³,oÕ ó†?ó(,eçÂÒGØT¦=8‘˜:YY¼5•j5Iü~£¼coå Ô'6\cÀ]òêmžÐ ôe“#&¡$w$–ä)o˜øÄüYÔ’RÖ¼¢6Ò‘V…DL¯˜Ðb¤æ]ò‘lAûtöœÇ)>'á2T+$ΡNÎò~Za &e³=ýχGÝÚÊråírP KÖ’ŒxôÆž)—ÕìeTMdKˆMéÐ* ´ÉÃbFPAP^è~R³5^»Ý±t5ÿ­”À,„j¥”2ÒÓ MúðõmP8¸FO:’‚º3 ó®a´t®ºôÙª£,g‡´BRá‘ù{éÍ™-Ç<‘R™míxêD¨˜ÒãÍ$8„¨66R+„_$e ½× m]â2P1yY ¼ÚƒY™ÐêdAõ^ƒ¤xG)]ž"6¢¡š¼a¤5¼*çÎDgûSD28Q&Q"j|ùŒò ýS+Gf̱-+L°»Ísnðü¢£ú3Gµ^þÉúgn‰Q²x‚›Íi(L¥DØÞ²$5Dug™:P§{7Q©(!½ÒÀ—ÌÎƒÎ¬Ž ²YÙDÂb ª­ª6¬Œ{»0mßÈ¥ñå®2ž…¾o%ž°­±âc¼ðš$ l1æ–€HFÇìÚ…ê»Xk`¤¬ÄlÍîÆà òCñ˜Ô¡È?õF¶˜É¨ˆ¥¨˜ËW8èLT©ÕVÒ²yÚÑ~0NIÅH¬NŠ„À>Ëü2ù `M›¿PÒmpß§|Û‹L¤+¥!x˜ö)‹‰öY×ÔêÞÀÏ *ídt\¢Öh QLp«ïõA¬ _þymÌg ú^šµÄ1qÚ€±íWƒ[ZIÉÌú ŒQBJ‘’‡xÉ4‚5)ûhC]Å]Ϊ˜ø6"}Ú¦my¦€)²?ËKxº(dœ“£Ñ³D”’ —¡ë¹ßœ>h¶ ŽÃX´ÈO1ÌÝOH¹a'y´µv…²’Ï–B Š“êGºR<ï,%–‰äìÛÓë(\Å%#!š½>>ääyƒ«M%¹Hít¯b›µ²ÀJäU”åáUµ™Æ^ÖëybRn9í,W†D¤è½ ÄUW0Sž‡@}à£L貕Ãfq—h¾ÙX©u~تsÒ+fW Ñ€ŽÛd½®Š§Cä$È!õM焠ɢcHܔZ>§1ÖV}Çž¥ÒUš²”ÏKöó ¤ˆ&×hŠ[Ôë›KÕÔ¨ÑéãʤJÍãë&Éõ”sÁrʶVx§K°^±*¶È=K!‰:DÚ‡«µ}Ñm”Ð <£õ7‡*¹« Ûu)ªîÌ.G#è´åFtÛO²Vš1£Þ&&ZÈhl#-΢>*ÀµîøvŠ^föØLà) XÿÂÄEòi,`,®rÈòo°=Ç"Š 4ÏÅÚùgþ€Bøˆ+l(m´¨(]â†,”Úô²èÈBð<âÝ#Àì*@£B²é8#¤‰Hö} £àUê@eEkAòtÇ'‡v×B6Ç,*®òKÒ›Š<æÀ™íT(¬j7© åÂ<ØÆÜ²ì$€iž<æãK–ºŽaÔÕ/\èË´þfuhœB:‰PTkìèÂJèrÌôŽ/B¯ëü¥ë‡¶ÅL$Ì/ü®iXÕŠú0ÆúÂHö:Xt†fÃì&È.ryBä¥v#áç'PyéHö ÊüÌÑHT0ép£E Îè>hÍa¨EOaúGJ·¯tìßä!C~@Ê{"jkÌÖöob0o@å #êȘ18ö‰øLLnU®þVNÑÖÒ.&R íe €µFÄÚIÒrbŽ)+úP/ªÛú‹1”~+RB}…J˜ñ*»R`ïÀâ±ÎêÐù eFç£jª*™ŒxëÂtýÎa¥JÖÂo€²œ}ŠlñFÑÐÀé§VسG]D|ñE¦=1nFq!LþÔÑÆÄ¢â^åŠVßÍ”±Èrõd,Â7±¨“‚Æ–ùä0 2Êäùª!j‰S|g¨»Q¢ÙO÷!´Ñ¤øÅ8fÀoCœ°t• ä ÖCP–©8®®øÁIHêC• ¼!ŒüÖCc38K)ÔkòªIÌ¡†•-Ò¨¡Mâ$gP^&T”ï2„Î80.ph‡—ÆÔ¯ÂWr™‚"—Ã]ì¿1äY1ì4„V!Ž¡ ò|€nÞEF¬•Bå 1PæŠzä ¬\/þ°4Q`o/+-+3 ŽÂ]©poøûíd5Êðb–"lèjOבzôK¸Ž~Æ&„ëMDö²ÇB,Ba«„ƒê¡ÈZ^&)?f½11ÚöÑî«FÅFÑ:ò~!Pë ÄYÆlrbªKEeÞT¤Ä)¨÷Ó’‰@ÙÊîÎbQD 4ËëJØÅk Ҕѓ„ÝCì} 8Ð,ÛHåÌŸr‹.×òÆÝôp§k"dÆv$"‡,žŽÐ$ÈØšÈJŒ‚²Y#&þ>ɨÿ¢àœòs^(h”o¯êœëžåk8õÑÚ’öAû£†©I¨ucÔopîæ.Âw¨Ô·§w§V~(òÁS‹·sü\1JÁ"hT¨qÙC-/:¨Lh‚†åEÖQ¶÷M±ÌÆìZRñ|¸eUë´ŠiD0ð’j÷ °áüŽ‘}S¯g:’s0Z L„¥,œ™  ÷Œüð…,q3¹K$˜kfÕEÈRÒÀ ´­ã¢{o|Leï84âäÒbü(.Q¦ñ)Àª,—^É0fl#-GíªôÓ´ÔŽüÆÌb¬xòz‡„_F—Y'FÏMR;ñÝ&b:¶@Ù5 åR͈mÊï¿M‹bH>±€ óaþÇ£Í-®ˆ< J†£ô€^0å0Ý3â2xHòyôl *ïtB“‡(…§Ýó·WJ£_Å 1ÒÌ–‰f,Ú–®m"“fh8a­K]-W0‹¾Þ“àhŽèàmY &Q¯ŒþJË=‚'òŒtj’¶–ZKíñ`J×8ËÀ‚LÇ­õM"ÈW]ÈüjË-,4½”¶mse… c` ˆòð¶s°ô5]’òhHó Æ  Á õ ÙnoÏË4Á èò¥ÁPGiki"7>Š2ʨ‹‚†Š|úIîë+ÿY nhŽTª¸ð…-'3WEµT‘É#…rb,!ˆ”H ÁöœU³BUÙWòt—sðT$'lúJqÒA‘»Fõ…a'^a¨Òfu¥WJp¶StmÈ”AÒñC*êRM#”#u¸%&±i‘qe,s IH†öÓWòÆÉÈ1ƒA¯L7$©)2nvÊÝW8×âyM¦]r­eiÓƒ£… ׿:–,±` K슫Qñbô•ôæo _ŠN˜± opD9 ©¦Õ¦¨*†öo—bÔž5)ìÁSkvöoµ(Ò‡VDNÍd“sW,Mضi8µŽÏÃ,Wʘu"ʘÀï ±<÷deÿ QQaæÚ±Å‘„U÷W¦Ñ)&P"±˜ÆuƒðÚÊ–¯ÆHñZäð|µ‡–Ø2‡·ø] d1w±ôìçTõQU?3Uh¸ª¬$Óq¼#v‚i¦$wWeq‚ÆÏÆÓ³SŠo\ž&—Ïx«öPdŒN¥vâ Õö´0ÃPÕù)`%¹v#f™›Gú·´"Ì úª9†/¯Õ(>ÁYjÝNâÉžbŽ 7дÇîÁ³¢ë4ëYô™b”^ñ.¢yifˆ¸Áöú¦ö^ãoJ„ Ø’'IÍ›)5~xÚ[R·"BÆL6¨•žúß§¦VNñQîò²AjÐ_o¯°1 ÃtPøø5y×,L– ¡EG z”ü$ S2§ qJûÒ …‹³BSdkczÕ@æ*œ†§ŽyçV¦ÙÞá˜ÕŒYmp…¸tc’éÈ.K/‹¿&…šÑ l)qÆ(t`Åhd,ø[”fÜ §4ðù€ õ¥¸/U>ó¹q8gu¯ß\h-®^ñÁ­‘”ÿö¦€‘2jšë.ö¨0âhÏйqóáhÉ8o÷†Æ ¥Hº:Zò”潬œÚû¤0Ôåâb¤ž¯.êQªÃ¹ÿ˜[¢É9üòo8t#­s+YۀʄŽh¨åFð—ÂRØfç 5jµ ÷o÷×poøú–¤în¡Wçq3Zç»BP§NwçtyªÍ¹9–‘µlÚ¯ªeJ<6Yâ~< T¶·„)UyîÙÀå Kðæéj˜‡è«Œ ÇÆEFûmü50bÛ¾˜ù9ÅW­,Æðù —Ñ•ZY¢bû¥OÁÆh§¹‡m½"rÒÀG87¶ûo—[²1ÝÐ-[º‹•Õ¡rö³] šñÿ<|zö™‚PÔVBbQ°±Ñ¥Û¨s©—Áfsçû ¡G¶…X¥"t)‚ëzUü-«“\ñ€¯qÂ^nD€5¬ñ¦vaòëL%Ò.kǼ{rѵŽè#‹Ù£x§óæV'H”LewÎÕÿk¦^Ö9~øÌ~ˆˆ'«${gwdö/ }<Ö«ƒEâeçÈu{ŒÁš”§ql¼¼yûÏÜk·Ü9šÄâ¢á² ñ°6|íFgÇ.šKኢ‡n,£Ãºeê¨á.JeY ›gŸJM›T纽§â6AÖþ.ä&*àÜ/B:‹×Æm'{wô‡üɇʹïBõg‹B¸1嬙xókª¬œÈ¹ÁQEж-~k°‘´çY¼u°'ãêpF`Ë5?GþFgÐqšô0$vSD4;sBãÝYñ œmSUêÿö,l%w³b‘ Ì*) ˜h\¤£Ë=ró^B†uÍÓ© Uûõ`‚6—ÂÁc0ÖŠ¾]Ïe²M®*™èÅëIßD ¾›h'œì^þà å·òŽö•dê[÷æ5hä«°9M«¼ÙhQU¨çĽäâ;gɟ±r]uàîùiÞ7¿´CÜ¥Ø~Uq™SºÓÜ›X¨u–U¨C¹:Q=-QŽm*’”#5 un™˜à–:mÙ°G Øzp (²ú8íîtM ÐΈöI§S§‹<ԯ…üûWØ\ ÿƒ?¡ØP ‡BÐ )û E"Ñ(  ähÛêII@©TB)ãÐh hû›§¸ëòy/A"’øì@ E›>äÑh¤J;”D¢¹|n¡¦Aªïùt¾AM>,Ú(%S‚Ì¡QØ´ñø·D-PÉ{æé?ÝçPiP*Y ”Fä×híåÿ¡Õ Qi|[x‰QäÒg¶N}ŠN×;¥âïvŠT¤0Ì$šá—Å.œUvc†ƒM÷kdš7·-”¦_´ Z`ð¬R{—ÑøóyÄJíUˆ?¢ÔüL2[‹H¯ÈÞ‡mì‰}s Æ`YŽtv)Gûýpj;wQcžräIBA]úRµËR4}Z´bð†ÇóÂìnÏó`‡“µY_ÑBIé58¦kÊ&±Ó‡øÌ IÝ.º+­þœpü A±ºÊW.‘n©ê>¨~°*™¤`¢¦áú ;*0Ì=³­¤ºmjUˆQüʆ;b¿³+iK?H›=“º¨‚4C]©K*Ñ«©ã=CpJ†$z ™;B.j“°ðžz±Â,l‹¡Ç Ú™²1Ðþ7Axáp[VÙŒ±a|Ÿ+5 # ‹Ùë‰àÛ¤Zc[ñ0‚ˆº;ËÏÂó’©ÁnЈc7˜Ë!yE;ÒL­ ªòR1›!7pëœX‰A8’ ±q=0–3@k8’0 ª†Ñ_;âÚ9Ι°‡ÈXÌ Ò6 «¹‡Óu8üº4ˆò#êE"Ñ=pβT >”V)‘öjÅB†¿( ››i^¯9¥¡Û¦ ¸ VˆrEŸÄ= [ž'ë ŠÉGz§È’!ë‚” ±¿#`ç>μäÆã`¨ã'œ…8›Ö Ê(*ˆ$ ‰±@‡%âw/¥¤y—“.cЛš!»­·³Q Ü*”™”ò¦´L-‡ÄJÀ?ñè”+­Æ LòE—P—¨É‹Ú÷‡ÉH’j+AˆyEû¶5ótª³œ>”4%l˜Ÿˆ$ø‡#ø8Ùy¯â(FÑ£¯›0¼c«§ž"P ¤“'l2yK|­-*¦œg¸ÉáŠ3 »0@BÑp’™§ÀÔDá,ùT<ð‹ ìl›áKÊ0“ ê›Ë«Ž»(úl.!·<©”ãЫœ¦¸IKÊw•“·§¬âã)é²»(• £ t8¦›'(޹ªF ) DŠ´Ý'«@ä”À‚$D‘o¾ëÀÎ,)7‰È –ìiB}Fâ¾â LÁ±£Ë ©Zê®$ËÈŒØüJÓ-˜°“…¾;‚<׫¢*¬©µ­P·!¨zš²î>tZKP±¶éq@â—èÎ(d@x¤ƒ€J8Kè®™ÕšϺAòÁ‹(±2Îá>Áô ±º*¸B’•ªÄk–ºó÷°”4Ù‡)ÚÈ‹ mÑi‹¶(ž<„^\­= áPذ>X ºÝ/i¥“²Š«ÑåãkÀÆÂÎàÙ*š mÊÛBPº°Åã‘‹ÙÁ/A ¡8Ä¡Ük¢-ASŽÇÁÅ ã+­ QüY‡Ù Š)ÂÉëÌÌÊŒ# €2î¿ê ³óHOÛ¯ê¸0s$‹Zø’,+#Óƒ£DøÏù šy°Ø}§«kÆ´ê)xL:ñƒR,´Y±– Ê”4¯Ž¼"Óh²Ñ£Â8ÔË”QÕX’ÌÝ 2»ôU¥j” ½º”z¬K¬Nc®[´(ÌÚSÄÌ;ÌH«1$–M8“³cÊBïBL[¸®0Ô­”ç€ ¹²«ùOÓûÈÊ:ç=]5íqùÔé‡ÅÙ‹I=¸Š‰UPR£Äׄ>»KÌ“ÁqM9‹p£ÖÉ1¾ñ‰ 2yĺÞVÛÅÎù¸ùªܶÕ”ŒÁ$ØY[P5{K©óP†95—‘ìÌc7)…iM唳%‡ác‰ä=1ºâ©ÛÛÛÓ¡Y$˜»«%{Ÿù˜X3㘊Îíž8£éA] ²ëÛOaJ4sµ”…Yh™²T§9}Öð°½Ùi±Ÿd– Å“,-‡Êµ,[C§}X„Sâï T¤ÈÅ  rDG¸„Zšŗ€¹³©J#Fõ”ÖëÜ @U[Óp*ª ˘ȟ•ÖÜ([¨} }¼.24Bù-´Eð¶»öŠ-)Àúw• Àc:ˆQ¹ÇØ„3de<ù¡8ƒ Ί«–ZÓ*²ÿ‡Ø— ë{ÙKð·ƒZÊõ¤Ô(A˜¢WÐ}$ ›B;9žâ攵´¼ »»yƒ+OHæ b¡r¤!yQEÇ­ÝÎ… »ûÝÄÖª³2å¨@ýHVÓ×¼*ÊdÑ¢LX×B%&Å‹F)xAJ64mBr‘à¶K‘@IBy£ëXªÑðü4°ëÅV2,1ÑÿOeÂOb‹· p½š ‹ ¸£·»Ð¿]Ï( ]É·:«;|áÓyBÐ,©Âzà\âKZDù–‘”º!Dž TÛ^²ÜÓ˜Í~¢Å¿ ¬ÑÀ|PI;õš=¶µV‰ kâé,ÖûX®lwÉËÈ uØÐtvŸì(!ÉJABi£ÌáÐ]A·ô„¹ý·Çû=ÌœIž‘® Ý.2UcÌ(‰ŠÕ(¬Ú6¢Ä‹ZÝ.£n+&Ú\î“U.6ÝKÔ?¾ÞA™ ‹KmTBÔƒ” … Сó¢Á¹Ô6!Óx$†%H½Û€ΉÃ-HB=ÿWzÝ¢Š„Æâ>¼5˜¨ùÇGªý¦ÍÄdÅqÚ y·d®(úPÀK- ©Ì°¹Wª³˜®òd<øBü¨b¼À1}ÃùÊ S3!Ò߇ÑÛQò©‘ÅOBš\íKæÁßKÈ¿8{ô!KÜ£)5FÙ,æ:+-¯® %Ò]Å|VÙ—³"#šÊ²F^NœdAÐSþ,&HßÜϹ¢Ñc沂Í!›+¾à~Wt(8Ç+¥&Ç3ɦž¥y*Óàû}‡ÓüͅȾ‘Œ î>×$;‡å—¢’C™fbâ-=‚Î; (Êm”Àî'/¶¨gƒ„’§*b¸E ÍtT-ö!u&€ž @Ûš•¹k£¼¬À•±NSfF;¡ÉÆFÑ®¢×'æ'‡À¬¸ù>áI´6¸”%ËÇñéB ´*ÕŸÈt ¤¾šÜ Ǧ™Ò¦°‰[cÞ É–C î+5Æg9•CÒ×K\£ÜhК ’ÔB>yŽ~n2Þ?W…XÇ"VÕ u; }UC-mZËÊ6Ôt‚I½×‰¢D‰Qy`œ E.aS¥1¹ÂÕ§á„Ú5)WŒ­e æÒvË ÁqP:»ìpþfØ J¸ƒ¡“Pð‹Û–eºÁJë—í¼2Ó€Dœo¸BÐ¥t÷Ú#ØdcÁÎ3éH^‘’;™FÕ[jö©eཧ- @á×Í~5Žæ5¶ɦM+A2AéQœéŠÑîÍŽb±m5Έƒk‡Ÿ 3'‹£k·C¼±ð±—²¼£BpFm)¸-ûÎMx©îjŽƒÕ*4!º÷<åãĵ­|àŽÉ°›C³pEΫWŒ×¥q±è<€½ ê 툸n&Jã`¾ƒìCË=c°Ý¤2·¬A¸à‹ ˜}å_ŽˆÜ¡Ñ/¥“ 8ð ñg‹Êž–ÅãÛ]:«8<Ãã:e”X2ö~Ñ1¨ctJ#èDÝòÕÎR¯/Aȉ-j€+·Ù«`ý ï$@­záþPS]”S_GÄC[Q³‹Äm!u>NÉ3}ì9~ºÀO-ê¡49RiÀ{]aþZ€2u4&e8¿1ú@õu%{͇õkL¿—þEìÞÙU’žÓº63âWRL!ž•¶9»Zä,°* µ­@§ýpÆí¸@“4T@O(þaƒkk¦M—î;EB½*ÞK§-Áb45]Èç¤z¿÷s„-Ýè›­ B±4œ vÀ©F`ë‹·3)Þ`Ò¦¾SÐÊ£¢&t‚A»=ö#Ê]÷¹T´+m·ÝãÉ$ݶÚ»¯'g}Wr ¾ üTˆž&R,«â€5=Š‚u=ëcRâge4åšVcÇ+Ã=`ð-xàüÓÙÚÜ´ƒ¼×¹”'uŽº‘áúsÈ'eóU/ÜJ”*~#fô€,í̘Â6ì>ØÆ»ìê˜8‡7ž 2z±M N*zˆ²PèZ8Óeã'|Ì¥!–)=v‹+½J&F?ty[× Ò µ”tG,µ÷ô -~âYMÎK»LÑ#ñ×e’l­ãö&zé®/ˆÿ‚A` D  „!PØ„!ýƒÄaqxŒBŽ?cÏÉyûB€ryDMýƒKað‰$ù”fÒ‡ÜæE$…Nã“—Ü’I*›fR©$µÿE…>©ÑxdF+J©PÙEB3[©R Úœ6I ™O*±8l(k{[f³i¼ "“Iè U­ë{ßfU:Õr“•H¬QÈTU |ã@Øû0Á‘AaXð6Zc„SŸR &†*¬À¡¹ëXe2Ð15çü¼(‘Lxmíê Þkq¯l« ’gœy[ ÙJ3ÙŒþ(†µzÒ­O+cg•Ì#“*-þ Ô‰Dõµ‰<ŠE˜ g6ryU’A‘†Ð3_ls%P5-z ɫ͒âø"n‹öÖ¨îb.Å"NÙAÇò Ȫk ¼)âR‰¿/àÚ=I8»'(SZÖ ­ú è'éËI I’Pè¥R@í;QCD9.º$Ž €†¤MLŒ!¯Šó¡.ã '¡jd|( +ЧF‘’‚#oÒ¹L,Ôº¥ˆ#VFí ¥(Hê<ÛÉôÙI'ê‹9p¢[Dgê ”4¬”à ÂpŠßÍàD¢ ©“GŸíj‹€kÃúœ³Àu8û1çÅ@À SXœF›îÊ#ÈR€´ S#†~Ëà2¨IÀD±h<†¨®r+¦Ï¢À&Ðʈ[PµÍ'ãZŸJ6¡;0`L4]Ž(¶Ôî”Bð€¦©Ðéý9@IU‘ 6RH4ÈB®® Ë­Ë*ÐTð›LPÉï€ÎS%ÜÚ´jl…Y+[St³ÈH™üÖ¦)\+ò”K<) Ú¤k1ZßXš´-ýo;³Œ‚Œ½Ìõ+l`'»SiQùɱé•]m£‘Áø’] žg-$úOŸÕžŒ“¿;¹ Ðêâ•|W×õé~\H#Ü¥arò.ÈÖp¥V'0¬JÀW–„iåv…ä1“æ§ó=jßcÞ¥Mûxp "mXÌ*„í®Ÿõðãžu~G€"Uh£ÚÍ^—#kB™2»߆elszª€ ¤ì-yÙùÌÇ  Ö¡XßíGÚ•íµ¿Ç;HÏóGîß5@ÛâžO- ÝÆãGû¢ J2ßjÉh›RÌo°õNb8@ (p>è‰ãçågí¸\eçé¿|#­z&ýÎÌÒ’Iikî=P2Ò Ú˜û@Jܨ†nž‡û@„q7&°ˆ™}.ù;¸ZÑý( ƒ‚QJ*…q͉©"hIÍi˜$O| Ul’[gEÑbHä+Z ±Ç'â€'¢pýZ©’ÖÓ¹ûa<ŒñuùGp=½BºPÖC‘òݫК”m÷Åȼ¥‰é‚ ÈMÒDœüã%è˘øKR‘ 7åÖ§+êÙK³©Nr¿HØ÷ a¯.Lâ§^ddÿ 71‰E¨¡Nf WÆëA:QDOšo]¹@›¨.Õ–®—ǼS')rÊÓ[C‡ñ©†ÊÄè·[dñЗ7NIÑSû¶Ÿí’g)Yð´ØcJ…Ë"øK“–á†Ö­·[Ϥ¦Gbä®ÇºÆÃVôž9h9~™ëðh`é ¨ðO"„fÒè…ÛÄôÙ=ÇUc –9[ŽsÌ’Újft9XóI‡f÷‹w\Â’ÁFÀÈ®‚ep É*3^¢82*‘­°à‘3€²\¥y¡v&œ ØSA R’´ykçm9ˆ / Û4Gå¹úÜ‘û·§Üh™ãõˆâ|{X#µü¡em˜]ƒNåþÄÈ5.ÅSÊLãrƒNó`ªà t%°uõϳ¶Ü_v¥ÛI¢€Iðg˜‰mª ÀKçâTßüMƒaàQþër½¾H9Š­°ê¥³ÒC$‰È%Žkwµ*1÷B5Zè%J¾ [ñ·Vä)Sý20ã@ha‘²Í`Šñ+]¡ó0†ØÛÌ!÷x @ØçÑ50Ç0 ÍË][(±œ8¼J"=}žŠÚ‹ë×–F_°Ɔ´ÿ·Üà3Â"*ÆíȽÖ~Ûƒ§w<®bwU2ó³rŠ G’.¥ºÈ‡,¹Ô’ÞVIp@Ñ6yh® ÂwIµÈÅgf[ÉÚ6±/’øßaŒÕ)A“#=3¹•OqÝwIROäy=HÓ·z×SådEÔ¤§Ž©÷C—­æu¡3Í¥øø'Øü&bÍõ&Fi2Öù!„ήĠßó%² ±w²5ÍIQFòFk4{ݦt§LbŠä7¡'$‹ÀOÅð€>be\t–™ɵìj/ò¿zjec…vÙ¾·µ°Úy¼ ¹­{#‰–M&D‡åJôkšµï F¢h޽cnâ«¶ý‹&Ýot¿ fç ;Hªzkl¬)ä&Ç ü>ŠLPIÊr™ÉÆžË\ ¦ö‡(þœì¨§*úØHX¡¢rb)œª 2L«ôÊ–ïi臯/ö‰‰Hâô$賃qíY(–ð®î"Ç>Ù̲LŠôŽ(m bÖ„ŸðŠìhÌ .¨§ðÀ¾«¤Ûív¸bB¥.¸ÔËÝÐŽšå°üÎX#Î(T Z¦(H|b0ô ðãÖ2ÔI†ãŠâL°à*"!I(xâŠû­@Õ¡øšÍœ•E°ä°µcäDЪ~œäîÁ%ùLÙ©#̰}Ä>aËZòÐH§Žlc tÝlÀŸ°òõŽ?p*3Ÿ&`Öq4«xrç¯0žOm¨ÂhÏI{ªÅ Áú¿C“ Œ™Î^%Kz©ÊfÜbhâ¨n ý¼Âî¢ÒÑØäÆ6diŠ50} ¨iÊzld-hÈÃøßO_ äPC<Ãhd¤‹²ÙçVVãt®Ì–0 œqHñKĺ0®zDÈã÷‘lÚp¬L%b‡-ð¸M–uiP³#‰î1é­çuI,l®nQ"²Ýfê÷HrÓ2ÎKg°ü~e°ƒ¯É 'þNN*‰©Æøž‡Öb/{ Kèäe@œgÖ%OÁB”ñÉ2K„&n«B³q8YI\ °Òzh•Í3ÏW'1¤å%îü³À )„ÿîÙ¬B´`3}ÃØñ.§éÜn.*9ャ´®ÍÅ–6F')‚üAè(¨,fåg§qÌ*%²×2js ©¨öâ<˜%µ%ìx'Åg¬ÈFòvãn$FngÀ Þ+ j ÉE>THÄätUÜZG Ѓ`Nój Ná0æéã6àP_'çREIK³$xïbH¾æ©²~*ò=Cö§¤m®Ð" ±ðÿˆ:Vqn0xè`ÊÀ7ëB¶'J”"䯋Ê'#R€B óBœi‘,ç¼)Èd}ÑNŒÉé*î Lƒ~ü ÔNð*?g¯cöhñ/nù,ѯ#mŒotã…Oó‰ˆq/` Ãmƪçš3((%HÌzSΫBs"#"gœ“±¯Cd‚œç`øÇf(0¬p¦’L{Eì2%´kP~n«¡KNL§ˆW#[ ³šò• -Yï²"‘–h²©/ÜèGЧj rŠ ÌØ´K($Ø“ÔÇI¨÷ ð*¹%x)ËCT7Œç®ü„îöcBW6Š3øË5Ššˆêä1zošÊO=Ò`+ ¥â΀ >·HœìË”•lL%d‚õ§ô3ËZ¯¶Yg*r¬æ†¿Åù%O”êRTŽŽ-©ÓeŽEVÀ áE ”4ˆ¬+Øùàé¦UÛU¯v/&LøK‹BìT®¿ðŒó·\5f÷S@ 8¸“S.©.vÕ!ø¦õÉ:•)Jûk)BÓßï\Ì5ó·„‘—Ó\O…D¤˜·¨ªn^*v©G«N@Ô.RWQWv[3 Qo¥3FÉ6®Ð[]äËTiM*™O“ ·aÿuGU ð<(ÎrÒ® ›ÓÀ2&ˆïs˜êºã÷,aõFâT‚ÇÝG6_ub×cרâ"m)3z·ÿ A:«·(ãæn}e—bj§$Р¹J¤˜2º ÄÿiŒ¤E,úóÖŸ€d ¦Ö‰ÿl`Vfo‰‚üM0*p7èa#÷rÛ/hk× "ø\å$¸n¶¶JWûs0¤Úöºzi‚råbVi7GsKv!÷}Ìç|‘e`‘PNèlËd5P£„k³T-#mÄJPb#Ž*¡Jõ"¢èB€rHŽ—ïu€-×cÝV7IH¸v5gNRmØÿf ôÛbŠggâ_Ï ±¡>BµóÎìO6æ˜%¤­c«Xx‰,ñÖ•¬0‘‡ q•Ifse—TÞ5œ@6ìyùÿ’7Ù“qÜÄçÿ?/ÜøŸ;¼H.öåñ€p=Õ#,!ÍPqf¸Ø(LĜ狘RЕc‚A1N,7O÷NƒT¾‚Vúkez ™Í·hŠÂÔ9JDyΠd÷'D¹:*xµ­X˜$6ÃoU%$*„@†ªR¶”4)“å¤à– 4M-<-yh®QÓS#¸©LÑ[¯ ]tNX]mÅ _‡øëaE‘`ŒW…Rƒ„÷H‹g>wÙÆ„Ô6â¡çéڣ (sfRøërœc"Ú÷g‹yØÌÒÐ ¦o‰§=×6Gv´.ŒÚ-  †V‚¬¢m_²[5U_P:ú&ˆ}ÇÖÍ`RCÜ­Ê‚V‚_»‘ö®Ðww±r¨åSm ظŒõ;VjÌEª%“š­ÃiQ.Qx˜ßÖêÉX*R„¨%¾+Ù彸W³683·Û‹SüéQ±Z×&â:,L•ö.JfãSšçÃÔ~Eç0Ç-øË4¥omRÈÑ¡üN…-i(%é¿—ìý-žO<Þyä\™?^âZÚì¡\Þ¿z>7*Ôaa~ĤPdŒêí–Cé½3¯î´qÎËì‚„î·€³&a—Áòë½XKõwCÎZ WTÃ}^¯[èO™ÀパáÕ!eI–ðÏ8¨f‹x¤®‚A¸õ¡×,°ÂÞ ¤i]?^˼[Tš]Iuæ"féèrBËñ›Ì‚A×Bü~?àØ0 …Aï¸p ‰C!gì1ý‹#‘ØD|‘GdRP 2>•EŸRÙP,™=¦ÀdÝó9ˆaϸËúwŸÀŸ’YÜþK†Kç´‰H ;’Æ'õWô’E?ŠA+Lª»†Gl‘Ëš¹­Zl±É5¾á%Ç¡[´¾PŽÏgwÈ…¶-=’‚p“úTŸ¾1˜@L[DŽÓ€6ØíBrùfñ‰"J÷ÑT*·þš%—Ößòý,fÃhÇh•ðOYl¹Ç%¯©} 3/±[52;VÂ9/’á ÑÙ3ÂŽbfhþãgɗʧ±Ø´¾‰r„Q5vÎÏêçÀW­•зH·¸ç§ß]×ÕrÑκD³€ ¨"ÌsD{¼ëƒºþ»îØ®´ÈúzÀ¨;@¸«ÈBÚžÁÀ:ÄÂhrðà¥JZÀþ¤®r®²(¢!‰Ú*ƒ1)ìl‡2hËöø#íc:Í ¡üå8Àb‚EN9üÿ€/Ê8ð¤H²ú‡ž,ÊmM~gŠ[Ty !ÉÆ-[+Û|äRw”D]&@¦qæ~7™½à9æu½žÉ°}Ç¢AžS1CH¥@@H&ö~¢’¶‰·t}_MÈ8A£—«¢YÍ“ÛÚ  LæÚ>•ž| ‘ÖC7HòW]9ñ¥²±Dá0‡óU-©Æ¤©’oO©„MŶ;ZLC—Á]pù‘#Ø\Üip¤"c³°‡¦´˜mpHÇ+rÚ_I±€ªÉRØQ Ù‰KŒŽ=¦†íJ¹‚Dýþ#%ˆù½ˆO´(ˆ&ñ¤m,U„wÖej?QÂÌ$Dõ¥#ÌG©ìA¥Ö“蜩¤‡E;mˆa™H&QÏ“—i3Ýñþ€d©°¶³ À-yÒùH™^UÛIûuƒé7ôlTIPÆ£4ÂÚT!‚FYgÁJ€†&¡ÈsãsB"ÝòîÈ鉂Tå8Á%‹dcäöw1¥—¸º,™9˜'6Œ‘1²sI”ž#'=Ð?¤Ñ=!™?vlF2dÓÔ”§†±Að¦W D™MŸ¯¸N`»+[nI4ŵµÐwOGlç‚FÐ/´/1˧œn&úKl#Kdå•Íœ²6³z˜ËaÏ»ÃîtÓäš™M¡”ËÀ …GæL¡&2ù÷.cÅÂDý ÅÀâ ¢HÐIzTÒ]›å~Žãú‚áFi)A–hÍ­Y_RØ•—Z—*ªW(ɆÚÛÝÁdËt‡&Gw eA¢Dtlh·N²Ú®ˆr.²œ¢>'}ÉzåYó[ØFªäù3¤~2i#ûƒ­ä ¥LF=TJç‰6dX_*D¢ XÌLâ/é.?HÊI¡ØŒƒg—¹\*5ѳ¦Ôâ©óÌèÀäÀâàѱ.t¸¸n .™ï‹JcT{¶X…/aä…jåX–&e&„ZBŒÍ¦32Fì:õÔ-ao•u³Fç(nÔÒÂÈG9 —M ~2.ü”ÐýˆÍê!±ÍǽE¢Ë ¹**ÝPGº,„fu™¦üîãmÃ|¼B×½·JÛ ’Sl¼3´iCÅ«WwX¥Qz8{Q!$)aÒ0 WUý~Ù³,“:D«†&v•kYÏ•rÞÅ<¦ÛT¤æßtd–á$Tì½T2;hù´ìYÀøÄߨ0l—^²%B#5Ì=_!t büs+s®›­IÎI;„9W€£;s›RDö, ˆON}³:6¦SéÂú<ø'¤ÜFþí‹NÇ`Û´§Š.5?ø±+¹92C˪š«·íˆó“c¶Kíå²] Ö<×¾¢9™ÀÎ;e\ù܈^¨²¬ûó¥‘-¶ÄdÈyý¶YÒ_×Þ¦÷77ÀA<\˜}’1‘}âÉšÔ‰=½«m’õ ±@,ÿk5Ÿ€OßìT+È‹'(;á‰Ó\ Ûs"AšÂCº¸™YЙ8­ºÇ¬ R%ª¥ +”£Z:Y-3kµâð‰âé/pç¾Øy·[7¥«­:Ѐ ÅŽ«©¤+ú¤Zùˆb,–’ºÃA¡e¬ºK“+Iéº!o+œŠ—|ªšâ¹ó53¨‘9‚³¿Jö¡›§z\#êª) Ž>ÃÚ%ÂÙ T"24§+ ¢ó™µ›”±1*6IT+‹z#«?J @’Å5;¸3“¼(~©É–1((’Û(±°“AuÀCæ;‹4ë䢠‡Hý«ö3&%A\—K·Dbe‡ä4‰c#€>x¾Áˆü'žâˆ`Ç 2­L<£ 'l/ꪻ½t(1šÃ‰jW$ƒ+»aœ3 …'ªÅˆsý Òo’[Ò+ôˆ2Ö‰õ³ŠñK°1õ¹ƒ‚+²’B3‚¤ãý èÌÁaÆbZ±2•PlÇa£9ZxÙ_¢² ±'2=§)ÚB WByÓ¥Ò•Ÿ3ÔY’½‰š%D=µT¿"£@ éaÙa ´SˆRW)à–Ä,£ K ë»Ì[‰£ÅÅJ~CÑB££NÃê·£L‰¨‹|˜ÀRZ©Ì-+ü@­‰ãÄÛÈ%[ý-ê4ÅŠi©˜Ó%*­µ¢ÈêË07«`}ÅÉ ”ÊŸ4>ÅJÏÈâŠ_°`ÊfLº/z ªò‰¤-ˆ¤î4ÒM Ös4ÀCf c[²Äj Sÿ a_‹)œs“q± »‰ë&8Æ3”ÕÏA#Aƒµƒì|™¯iœÈ²áÂJ´¶t8¬ƒ¼Dj=› ³¬Q PŒ“\㺾$œI£ ˆÌà;ª ¾Áõ ±ªÐèИ‰“N¾Â¼9©ÜµHCØ‘I U(£Æ8Ò‘5|O’WDRå7 >ŽªxϲQé’´ÁÏã,¬*9Ä.@ÚâŒêµ£ ä(²ÿ<ûµü £8ÓR[)€ ÎŒ †N ¸%™©¡Kú¤.$<ë®ÅD|Ÿ2šÌu3l¤ÑR Ct¡•AÝd°~ǰހnšÑbKUôŒ=Ü;¢8—´Xl*‹i€«UDÑDèIª=•É4QTä¢JÆPrV(À͹l=Y2‹n9ßâŠ04D: Åæ2ü•|o—\88òw±6 ÝÓÖ)" ¶e~a­eN­ì¶dT©‹z»ñà:â±6ÔýHHH“EkXˆËÅ•ÉüI W©É4MUÕÌÞ‡õò‹-®² Ñ,b¬,®ÀÅÌ+ûçɾÅS¬bù‹ªž|Þ΃ýFîf#ñ6š€kÿ² 716€9KÂP8Ƙ×39"ZRíÃLº’'DS)m”¼?’Y8Ãë'S³Nìn¬¦~ȳz"_j‹6rË<ÚHee¼€ÛjØlѨ2y¶°6¨Ä„cWE«µ_ÏË~Ü ŽÕîú:ðŠK@|Ø|‰l'™;,0V}áà„UÊiâݼÞ¤²U•üØKöè9=…ßþKκDzk±Z’?²P 3¥×Œ‹Mr•ïùÆæa •#=?+ëêš:ÆŸ† o=Íh£ÈSÍmMc[ÁU‚+zš˜}îêš (=Ÿ×½û±”ç$Ó›Iµš6ü”•zLg6Žœ‡Ô>éx|Sz‰Û.5ûR{°6ãÃòò”¥Ó#>0pÏÃB/g§Âャ‰5b7`ŽZéHåžôjÇHˆ…éY¸ìC;Î^¥(Båú¹—dL  ÖcÎs“0áu°ó{ý'A£h/<1™”¦~¹™+¿1šµòugÝbT65ñr£o-Ç? úˆë¶dEXÂ]xŒËÑa\ÀCêäÕÔà ܀,ÉÚÒ¤9¸Ím+‰Î-8çEŶÚÃyr¹ “™3]¹sOŒ”¬U1¨¿(äØÉHîR£(þ'‰–—)#æÛÀްCzÅÏBÈÞ©;3rÛÁnȆŸ¬ˆèÇ®N^<91"0åý(£Jô£w›À`RÁë'5(¶kJK]þæ‹@BhýÏK“óM9Z÷·åG 7Ï›`‡né#ì€:,×b^ðÛ4í%² hôP"ªEÛNè8èuEüåFÍ}öùx ",Ö0œÒ^' žc¼ß:÷Œ¤¥^§å+[4^f€²Ø—ÀÝr‹V±ò³6BJäa‹}´§B·Òì·š¶Â¯u×Î^÷[ÂUǶœ{÷AŸ&Ûò„Â.å²h„M<aÂõ¼ †y,ly$YÓúm¢;¥ç°ýž±5á%Á`ÀÞ°Âj”ø€>à@8#þ „AŸïÈ`" ~¢P¨íýF@1¸ ‰¡OÙ$l’?@Ò¸ëæ]GbïèìÂmÄ&L~M ŽÅb°4vSD”¦:TÞ¨EdÕ+ê­DˆLê’š³ê‰“MÀÛu A$2„š?#”É&rk¥Öa&”Çcó9sæST°FáR„*É)“He²ùÀß¹Æç°‰üÃhÈLãÜ®©<’䤘¨$Î… ¢cßö-df™†à@4˜<"SÏÄ¥39„~;HgÚ'î&'ŠÞâò™…R! ·BrØ-„C ´€áY¬Ø×ÇØA®ñ¹Ÿ_½à˜Mc1XT™­Ü¢û)ƒÛìüD?yœwì{#ì* ޽@f|A úÁÃr"­ãñ® LîÊ#’„"ª#ú‚:Îû"¼0£e =ë)þ®  >¿g¤dåωúЪê6KÂHˆ((hŽ¿OÁï#¢d”¿ê#Í ¢ëj6±E¬¸”ňÙë-ª‰4ˆ†¡Ëê*á! „S¤ÈªÄÁ¢OÛþ즂ºô­H“|Ò¢ðh=®놷ìÉü©<ˆ»Ú„?r”¢ ¢úï¤O0½É"ºÓûŸAN(dîÒôÂû&¥m Ý¢ô‚ľUkhéZa#žó`*J²¬Öð ÕC4ªˆTS¤“ ]ŸñÌÉ€ˆª+± ª°†WΈ™"êëÊÝ4h”ºœ¡Ší!,Ä•ã +$+%ÒØ(l HC ÿŠš Æ‘ó<Öd_MŸ÷B%(Ö2aB/ÚØ†,”éø“?tbyB~ºßp%¶Dp” lªÑÜpãPjM¢­’C© %me"P¥bE8%Ö…¡–²¡–B:ªVˆþ~^Wlr:ÜÔŒÀ4œ¬ÎÃ8 +)nîI¤0  ’µm‚E0þª4ȠЀ) ûDÍ ÍVÎj¡hí(–78®%É@¸ªü _¹¨‚û’fò²ô„/¨ûq¹¤›&@}M(‰ Où3©œÞñHE:”ÍnÖíuS»kt¢âÍn>ÍKÚîÞ™¿n÷U#8=\¶i$ö½•êI¦õéݹà{}4†hw"º¢a½2i¶"µh®ò§ßbñà,‚‹"ù"²ùÁ}Z$Ž«ª:W²Ÿp¤)rE©œ°‰fzK2£/üv±]ß.¦”Þ“Ø#d|ª?ÐÖ\±+D,qð»8]ûÆL‘û?'H†ÛçN ®g¶y”q.Djá*®F$?Ë7íÅ€D§Èù}aÈõ¥2  ÛŽ K γv–ÛÄNhMI¸’êxa“~ÇmÓºX€FÑÛ‡¯Ñg²© ~ÐÄ—,%dF^û0‰Æœ~;õÅ€x^O|˜-6 b}]G}ÞDJ¤Ø¬E­‰/‚ ¤±q>Cù[#¸”Hc¿Uˈ1TŒÑº–²:yˆƒã̘ Õ€TÛÈ\re†9*Å¡ThNPxŽ6Çx£J‚y%Ñ>✤€wê*³2«à°ýkñ\.D(…¥hA®¿žcÌë^’-‰ƒùO›t„eÜC Y¢™¹›úc—Àq'$f”Ó{nÙ•©bK˜¡­ŽäÙªDHž`“,äÆš²3šô¦jQœµ¾Å°?šAXh5™£D6µÈ$2žÓØ/g ¸J±û+¬)Ô+øÑ5žÔpTÍŠ9K†—”µŒ ´~–Î?Xõ‚O2ƒ‚ñÉ ]wêГê|–Ǭ—œt‹©4Ÿæ -‘¬f`»ò`_Vc7/§î—¿2ÖÚÝ”§;‘`ƒÙxÉÀ A³Íè<*`EæúÌA¥R.˜$~èawä~ Ið ðM‰yä¬ý¸r6Ž¡)zÊÒXT‚ø“IÂ]"¤¯ÓàŒÌèè]¢T¸lHb1-gí1¥¼þ&ÓN^$FYéD+¥vÎ8‚B´'“‘ôG‚olÑU1m…uyE{*x ê+§üª?³Låâ[U ÛIã?%g“eÖ¡!Pëáø„ñeÒ-i«å Wmó®?‘$¤¹X¼•?ð¶P”G6,¤ä†ÈHà>í¯ºµ~8V² Í¥›l'À¨ÅVÙtT‹3>&’h=]s¯˜wÆ;JkpØ$‚+NÖÁ«G ÁLåxíHÿ½lóFJ #‡àq뉳§• öFî9!Eõ`ÕÒ­ [ÅV7¤!ôJËâÌ¡Ý+dÍcP '°ÚÍšà‡'öSæ „ÄäFŽ¥k xUËa [`Q÷BÐEÃ%‰rV×­6ŸP˜+Zrºʲd@ü¤®«%h18È«¿O«îÎtRße$ù€gH·JrU¯<$Bˆ>¼Ù¾Øl†6  8I(I¥•(¥‡š Àû¹(¨xºwÙ ×ì«ê²ïÊ8ìÆ}E’ȺÏ/ÇÉ]x?®[Óv&«G0{ìiÝ¡5æè¶*­q’¾ɘrB W‰^Wyݱ"Ò ÂU*ÏG·÷¶Æâ‰Ë¹Õd™Ÿüof%ʞј÷Um<©oà™Ù ??ãž·ÁbR²Š¦\À A,8ø›øVÑ;Äžæï¬¶Ü­;E€Bû±*ÕÃÒãcTªðõ•õªÒ L‚I+®ÛŸ¸™ÖÙØá^»¹ä‘¦bh×I4ø•’„P=?àz­9]rE?ššÍZ‹×•¼‘åŧïãm5¿8#(ØÎ·N%<袼Síà²Cô Á2“E)8‰lMe ó ç†tËŠÐÐÃ>mŒZç¸Bg6{¶ÐÎ’¶Íò!Õ‰»7~Õ9üŸfIÂ{ ïë‰ñBèy¡ûRˆ×¢´’N€Mä_;š¢é¼0?IƒµSœÈ~lO­–A3ÎþhïÞ-cÓ߈%z”Í3Y³‘”ÿ‚ÇÃéÚ‡í½,Û©¤”(•—Úlø6©ž*CM9ÅØ—ÆÔ~.é3¥ø¤>2aÖ¾ø Ú\C¥EFÌ#"¹N*xI Êdv  ^>ZÔÃ$˜¢+Dvž“ÜÞ!¯Á¸2‰ÍÈâMøÕ©’ØÍH6U^ÉÄúpÃBÖd„0`w«¤¿0"ë6Ù„(n‡ˆÔæ6œí:#*8ê#¾n¾†¯¼KìvÅŒciËg¬ü¦¢”Å>éKî!‹ü£ÂÒïÀï"ÂȨÍä…ëê/â Í‚$Ì  ëDÀèyhÞ’¨f_…˜(Š€·ÍlÈ"H/¤”ø@¬XRf6ªHXiæÏúlN$ÑDª¹P¼‹DâmÌÄJ "ê˜#U#¸OëÎhdh×ã:Ëgˆ‘ŒÚÚ‚È&a½åhzÉHs£ò”§8uˆÏ` N*Ûì’žäN;ŽLù €Ï:0ɾü…øDköå ¬£cðÛ°ôRª¤)*ý„¶Ý*›¦xƒTÕËËhà)¨ßÆ´Ä9ÌP‰Ë $Ë‚¹¯\éäTïB ÉÍ`ôäZGgÒmþgéÞ­Ð:…®.ÓdúÀkF”Ãd è¦Öéx Š,/¦ ffd^ªÅh…°ÎžîWé#:ÛNªt„ ÉDzŒD^FÍŠ¢§xsqjp‰Î‡Ëæ;,æsg0ßʬÙi¦º±Ž”0.lGpžôŒ…þå d´*¬ÅpL÷ЈJ¯øL^½2hânœæŒL߉¾LBzÊ{gºUæ†Þ®º¥ý¾ ëX”ÎÃëDVÊÚ—†6”$Gð ,Æz—âH?bˆ^‡í i4é¤\u,úãrž¤ÆÞØÎÀ#- ƒ¡ôþäТå|ºª¼ækª`ŽÚ½%|x†<ÑÉÆ¿-쨈¢Ñ&ÁEL`‡ì3®¯3ð,¢cϨw’ŽÚÌ£2‡¤¿D;©¦Ø+Rø¯`#eçyÅŒÔè(kƒ´÷kO%n³ï2ÖÒÊ.…}0Oæ JØÑ…èÛ‹Žè‹ÒäI0…J<2á3á©“"â$Ä¥[IR‰ÒJßò«MN~Ãèš(á ÍVd†g"èfj¤%È@* ˆ* ì}ÆOÀëêî.„!òSóGæè#°z±(–è°¾öáôBŒ D†Ý‡ÈXíðUð(×(þIDžfn³‡R{sðA÷)±ž$Œr3Ñ ò´˜C`¥éEæðÐB 8ŒäàÌÇ"‡¥nU!BNÊlâ!Jê òë,!Œ¸\qdÂ…Í^GíI,’ÄE±Bn.¨¤Þpåp\^Fàj”O­Rd‚R?èrú)‚Á‘×Aüh%Gó”8EB`²úÒ©’{åM)aÿKÂPÝizœ˜|Èù0™.aüh4ìŸr²òÇ ¸ÕFo Íò½ØôÉE Œ_‘”hŠXÎI skC¤(GmÜ–l¶ÈgÿQ {D-{1i’Å­ T‹mÊjxÑŒ²zQ[Ï¢Ÿr9T¨¬ÌÇ·-rœë’V<ÉtB2p!¯;—S‚*T +©ÎÂt³†þ#êtO‰p`ù«/U8«¬vì¢ÛElq^£#ðåÉ*ed¦bú쓤bbžÄSZà Ö)úß’ ßɦEðŒô±ª¬ËªÆEl¯` {(¼Åh¶%*°æ‹ã’ü¨tÌâVJÔܦ¥LµHœÕúsR;5÷ %'ºht¢Ú‹Ü‹¥Ø}mÔô l&Ì2°ï  aÒ^ÞÃ;L_uöÜ‹q_füÉJöËâGudédpÛSÙHÐüµè× VmB]g”\êBlÒ-𵨜}•–JÏ€ÉC:Ø35Œîî‚ÿÞÔã)L°¤û:©*ÅT´«g¤GtMb¾Îõy¨É,Dþá‚Ī Gp¬¿‹âÀò‘[586CþcrP›m©-¨±4nÏ4ˆ.­–¥'RbÐ’’¦ƒrZ…¥—NEMa¦ðoäfw:Ÿj;¢ûD”Þ%h ¾£édR¿08EE¬{%^©HëG£[Víáokr;¶áJõÌVe"´Lâ´Ï„êt7uV‡Íe:B #ÿS-n…k°Ð ïÂŒCT§‚6æ/Z}㾑”ܺªÊi‚dJ:n\Ô6›âgOîÖÆn—è?õ rb¡P¬uÖ­°0¡é÷ðºr]Wn< ”ìt¥®n Ô*#*€ÞÍ>¼x eµ|²CÅÎÞ ‡õñ´|ÉVdØÏƒ9ê³ltvXÖ ¼ñ¤ÞÂ>ô#÷®¾6tx£àwIkâÕ&Äÿ ÉÏyOÌ«W©† à°µZžâBy¹–>tû+9ösTyÌ®Æa îfhOI”8]y­0A ãjAóQø‰E5‘„m‹"è²gnmŒE÷p¬ÃÍ—² }©ìEìÔ‘±Nº°{*Ò`xg%Ó`ôù¡zn b(70îce!c²`¤dŒCÂ*Å”ÀÒŠoy©¦Î,…N¸o£¯©rëìÙqòö‡Ac-W‚Õ“ï«”äM–¯k´i…ïOq.Ò¬Êú9%¤×£)Å!(ª!G­{-’Ç5¥ö;cx¾Y n”‚´9+‹S§Ù5«Ó§~cÖÌ{Œ¦uÒêƒcÃ%à;´§+Ï™OûtràUÏÚtšT’‚ Cõ«¤µPžì·¤ˆ²ÍeWcwÖÖêAK…_7u:ᥠÖè$Ÿz;/Ô •y§vºèùNbC~[Ž9m®fàdSOúB"øúUè~ñ*ñXÛ6ÔœŽbºµóL²^ÝëÑ3~3QÇZP«3ÀŒW¶uXo?p%Y·"‚èšVrf!½TP°Rxí-ŽV_Y{t¼í‘íþ{l$„v#ùÌuØèq‘bÔå‚lœñº †g[Ô4¸ÚVÌ'{ –zx&çØ±–DõŽî*ÛYk m{†ÿ•Ô #åiF `SæX‹éîŸuu»ƒÁÔ"\¤»êÑ›‚ß µÐõ¬”¼ëžiû¬u,1¥ü‰¹`N~žøLñIIÆ(]]cˆd“å®T ÷ ŸxçC¨ÌÈÑ» *Û£14™‹‰“EŠ@‚R÷˜{Õ(I»Ñ¹˜É¹«B‚8ѱ•±R@±NfDx6ü®ÙbR¯©à Šá.*XíãÀ;,ãa³îŸ¯SÅ¢é›Ðôù´9‘¨+nÞ½À¦ZÊ&g¬šÆÄ—ƒ÷FuÖóÓ¬ÅË&»}ZÎïée…/é^[d×èø_šRO&Ž\w›‹ì#ì?66 òCÀGÄ:+Œ Sl£¹±Âé©åy‚|BÈÔÎOk××JYcú6Fè‰$T%!©Ü{=½ÇI&û(¨äñÏ*õÕœäi38V]d{/À ðŒ…ȯ=ôKÒ´¥' Ô¬îܚݒÄO®{Ç»ŒmBPX7Š/Åû&"XmP©í»YPV'wÇ7Á°E["kÐ\™²Ü㹉©,_šÎuóØ'¥Z;;¢ü¤lxŠQùu.W':•y·F»X¢Qô6óµŠJÕ[´cljq Í‘P#®â<чlwùì^.JÆÝ *½¨&w°ô;(Ûû¾ÉN@±ÿ7^µÔº¡¦0­Ö!7ÖŠ²_mb¨©CöŒ› E¾”¬Ü¥b ·Á»!,ÛJ!žo챑÷eí%x*DÀ/I=ó–nÙ¾ øû”1Éøa óÛÌ2^Q~mócT©î”Íë²úßÞ×Ýwz†f?ûó|‚M‰"ªd"KàÛBûˆ•7z@ a¹aÒi5µ‰µsO“ã Õ‡¥ÓÝqÙH÷f”Ù–cñÚu2îàû¬ \„” ²E1"J•GkP_‰ÃTÐõõŠÜq‚®ÊŸj{ÅzváÎt#{YÕŒüûZ ¨& {AßÐ, Ãß±L>ž‘Ý|‚´Á{×F’OM–Éls°¤–hnøM¬_ÓU›ºT§_Ô»çé¿‹¢pʆ¢ÜÉsÖêI—‘K¼  ƒ\ÓBcı³§°Jt ,m‘ú$–̉C!'i  ”ææ‰;[ Á®–Ý×#—4&Ĉ´ô‹I¢,gä¡–üãùc]E ‹-`PÙ)ø"dì›AÂs]2äRE•\Ôšï€#ŸiÉè#žã×ÂäIoÌÇ)&Ä¢H[3.¤V)¼q!)`näÊ!Ñç\KÃR„‘%HMòè;‡Y>EŽâ›œSñ½èÂ? p¯Î ¾¹ŽiŽÇ$ˆ¹¨GO^AíAx¦Öƒ#ÍœN)ËÍé-ò¤ÔX$‘:µ±þ錂õoˆŽ®†Ô¨ë°!eVJ£ê¼S̹oF)a×M "ñ9”E7Tݻێ2ÁiÉʾ@ä‚^³”*ðñu’†®² Å(9‹+©% åœÃ~ÄÒe›Äµ kzx„6m4*Ф«{U…³€E?sÏA­½ÃÈ- Ÿ›vD²Ô¯EèQÉ!65‘Áʲ&sO\M( ´Ñ=¥ę̂ìZ™Q¸‡ÏêüʾdÀAÔ~Ñàz{Fys.Õ⥪±íN@oàQE±ñôމãß“Y¸Tõ#"3À2«KyìÀZ¥C€ ê_×ùaT’=ÕÈäb[«>²Ú>6ø‡œõot&aÏ"zéCx\l\´ý!*$Œ%Ç6Ò7Pà²É“j^,Ø*Ô²j "TÆÉ͈óíø$:µDfÍr4H4›Vë Gk)Ï&Šº|¯æ O¦ž¬H΄%‰ÄçMêÉR¨D o%“*fìâHrT:0‡ª“w$ !»÷+0vu&=,§:¤e”ºUJö>dyZé¦ZúµEéæîͳ»ƒhFórÓšQP«ÜÆ'uÓ>8BËA´‹m¡JY½fI¦¦2µsZ‚ Ày§eM`…’']• í¹kµK.¢ á@ðëw‚Ýìm&…Ÿ NX­]CF=‰Ö3*!E¤ 9Ðû%8¬NŽÜ ïÜRØÈïx$‘Ó+L¾…bäsbd.÷e?¼RK~ƒ+>±¯n›@4†½”8}¼ME+Éלä7V-¤*{\Ô—WµUPÈ»nö‰¤O÷îBZ‘0Þú2òhJª° ô]—v É9w±Z’a$Ð{.ÞÎh °ÆO±MdÿÄ‘y§N³Ûô€Ô8n™ºÁöq™MÚÙµ3«}ò'³ÚAµ5¹–ãË-T¼ÛÂ[`žü?á˜r’n2Ñx¹š8” ši= (ë*£5ËY8ª+¥ø"FÓ :co²@ (ÀétB <íœ)ðŠí@èŠ)"®¢´Jù&ñþ¼(ÚžÓ€­«„¬âí:ë$§cPA’¿°³æ‹JëÛ߿ʦ1ô”ðÏ áM‰Ë5˜ cµÀîÀ{‰Ël”’}¢ú¦Œ'ðêp—ˆ ²Ð-2¸-+² µ(Ùº£S¸Kx9[) x¤$û­ ««:–¹,Œ),Z¹ Ù;8ªáA€¡Rí++/»Y§.Ù ‘±¨<¨© ®ÑnÄ:' X›DÂݲ(ÚŸ‹T¼BÚ¾4 ã)Ä8ã.ÑÀÄSù1Ø0KÃB£ð+û{»h}7 -8ìG;y›Ü<¨9ȬF¬2¹!p•SرќÁaÀ—RŸ)6Ã#?-}”s4‡ò8 ñ”¹Ü4¾ð• K´ž9öµ;O¡Yç% m­’]‘´±ºæDk*2ÁõűOFC‚²¢Ì!ê“ùn«(þ;“È•;€Ç7è} s`Gúñœü:œ,)ûG3Ûí5²Ñ¿º05¢ë¸ ä"¡Â—0‘#HyÂh¯<45#,±Ü„"T)D°x•*úNŽÀ˜9ÅBÌvÁãTBº›¹·“+¡T5ºa‹Aˆ~C¯?Û)µd¦?C…8¬eIz™¯xæ¨ 7H´Ÿ.ÙÓ¡ÅE!½¤$ÄD}«£ù®cè òG‘Á>I&h tO• ²„mêcAÚg»1š'3ú€݈¼IšY2:ý1¨ìˆ9 á=¸Œ½?Ñ“Kº ÊT!“ìËÚ¹¸œ6œ²Ü#nžd´QÞL:1¯K³ÇãÌÑA¦kЍú8ŠtpL25Ø~“ÁÌL€ñ…Êz0rýœúÓŠðšœm¿´ÐÃCN©ÜÞë8LwÕË ì££Ý ÆM|²Òeš¡IJÅB©ÑWqÍ;âÇÕájÈê¿ÉBVÙÔÕ,ÍžÒÇŒƒ½1”—S "‹SÐõœtä1¡Á™ÑùùI6m¢¬¨3²:r’¿ûý[Èï™Ô¸$8ó˜ €ÔY¬aYepª›nÝ’Ò£=ô8ºÜ_Öå%aÀÕÝOóyG!½4r ?Ú¬G *W°)¿ ÙiÁp¥H@s´QV*R°‹i/ÿÞÈ}d¼x“…§ÂÎÂíbRÄ•ø‚[Ó]0Ax¨ ¿‰³ºÂ"æ; aÞ:oq•ÇML £ŠÏX²?%ÏÒÂc‹È ☈hí&´s“hä•GB{,Õ i‡K¢„ä.4+iB“ÁÇ._9¹ý¥jl*SÁÝcÆ ˆ¶ª<}Þ¡u³ŒÒ"uŒbÉìUÜa ¼7$€“måI ¹P<?ãAu9Òý÷G¡pdIàã,¢tÜ]…Γd`µü}\“j²ã‚žB ÙC$í×yò¬ˆL2M¥ ¢ñ—©ÝOËÈP4—ÄTGuß«½bM.ß4dsµ[dyÎòŒóìK;EˆmVUØ£“ÀW9SdCDt81©ÌUð¯;Åk/,w J¡¾(ÌÖô·‹%iÝØ$ EJ“›¾'ȈãÖCÞJ¦KK3ûÀ_up^Üý‘þ"Oõ®‰ýÉËBÒ àÿÇ£Á9ð}]5@ßUs<ðÁ[Ü`ÆŒÒ)kEÔÄ>”´‘þW4EÜäÝ”…dºå^Õ;eœq,QHSÁÚ¦uÏÙt_Õ©$œó 3:ø9ruO‚QSü T¼¨[;8ÛÊ‘\5ÏÆæ)jÆ¥mÀ—TÞ`ôátBÐçé”ÃʧOR¦Y‹i5dz1Ã0°íç¾–f£Ú 0ëÅæ$J¸®G=IÝ+OVüE”»ˆèíJt@U×lìóAç눽˜52²¿‚˜>;&ý¡­}*–”Ô%Þ³3#¬‹nHÒ%ŒGÀÉ‹*¸Ã;«³ ±ÝkÙƒÄÒo\&@á=c¥ršAš¤Ü1„œU­GÎã/Ù8]Æ€™PA–s^agå½~7Ùà8]MÈËL·ÚÞª©¶Sé4s·±›q§RV¯]xÐ1 ˆ,’=dc#’ú§ß]£ÈÕ>g´4h;W¼…²­EIëÛ6QPàzu]|-ž\ÆV@?Ë2>ûå[ÉÃ8—¯l*>èÛé¨ÖJá8ÔHkÿÕÈÞ6ÌòoÉK‹x¸W+Á¤h³‰¥£—CÞ1Çú PY¤¤E{çM›¼Ÿ[D~ à4!¿Úä>Äo?%np»˜ 2u-‡ÔÍX9ìÈ™‰¤`»En ‰Rp|K´ð©e‡Ö/T“ZA( •ïõ2`4@è5Ç‚ý›~³s¦rQ£ä…\¦öf 5`•×.&YÓW,À×~«¥³ñjmø À¯ÙjU…vÓñ:ß„íÆ õ+²å¡[ÖZŠú ®»O~¬b²Ï?é]÷Þø©A¦R¸›föü N1XµžjvÈ‚«<5o}€6ÒLŽ™ ŠRù%¶æºÊ,ÞnÂ=ÏÇNõ-•ö¹nš5ùªåq ESî3œ.ªåTI¢Šp O%‹HÔdÃ-<¶#’v‡ÍÎËìÿz r8·ì3¿j@J+¾6Üý³ËÌZ`;«žéKb§µå5/*â’AÆ=²ÝJ ‰ŠÑh“Èu&4ÅOk”þx¿ oÒýˆ+xZêÈúy äM_à¡ù3©ÏÑš)ѪE×LÊ€Ù»¤•a;<ÇÚTOukA€èËÇå¥D}¿8OàÈ>Æ£Èqu`\=lm]J%“MÚ•Wøüƒ‡€9Ysý7pˆ"ƒò5ûÙk)êwB¦ÃeÅ›3:&Ñ^auú‹4r³ßð(ñ½.Ó¥ªla,”4R€¯m0wmOçÙkå!ïܰˆ‚ ÏØCúÿ†A0`1ÿŠ¡OàeõGa×¼„#‰Eâðè¬ !+–EãñHÈ/‡K&Óx„Js Ê Qx¤:/˜Ã¡Ñ*D2)S_ùÛþ˜FfpØ$| [~WgPið ºü«Äà@kCæÕKœE+`V½Æ¦‹ÌbT#Öõ1”Å¡SÚš¾€øx„~™MºÆi/ú²¢Öa ='Šƒ[{âo‡>ôØ ìB«2…iŸw8¥  ×Q*ЬàñÎÀ«U¼¤f?Á˜€ê4(UŽ?#ë°yˆ%]‡ØîpëS_ay–>å©òòx³Ö[¼ ÒÍÂ8±v»WÜä?¢Zë|~%ƒÕø)Mò…:êš ‹­è“¬‚· pˆ©,*ø•'âúý?è«Ì,l*Þ%k›²¶JŠ%¥ÈBÂĸnJŒ¦«¨õ!ŒXú³ÑYú‡&-£L‡?ˆ €B…« 3=!*)³ö¦Á êúÈ€ ’z‚IçãT>±k‹%¥Žã º!I²N‚&/¨Ò´Î£]0 Êd³I‹r·Ìª3å +«šb·°¬+düÀ/²;¢dØHܤ›OªÚ% èúÇ¡“@§¸‹ì)#î£ J«s vÜ!kJí°×IQ„=&),ÊÁ¾³ 'SÈòS7ÀJœ2±+¬.öŸµ³¢ÔÁs¤PË«zÇRŸÎÚxËÖ ÑK­âJ…gL*l·ª8äÅy –52|-î¢.±´+r¶˜µÍ̲ŠÄwiÿž ÍBÉ_€-•×X꘢ݣö&µ kú½#°sÎg!,²íS_õƒ¸ÜÃˆÊ Â{ÚÆ½º` !Hd,z$ñ"eƒ¸£ ¹ýÈÙE`¹à _æÒ‚SD-'ÑÔuòM0¤'º:MM~†¦»(AFrxc%+P»–|ƒÚÀØÓ"–Œ\‚t÷O"ñà%©ÁÇüÉ1¥”—DÒ/sߤ«·÷Ðʪ63#(¤¤õÞO¦Y}QgÔ¸¾¹HGÀ“xéb±œžD…7|´'w^Ud|¦Ûíá«‘•‚«Þ[Ó§0ˆ&tòrln¹=•3g[«C«ùñ®äÂM™;/ Ó7°sßÈÿM©±µÇnäRü(+­Ae½ô$gà-yÀ×@·^@ݰÿ0fh=r4FÎ:öZEؤ“fÝ Øó/æ:·’6b£K%-¹ÂH RSì)¬Õ¬ÂÅÒƒM\R} º ÅÀõ‡áë3Ìí–8D:ÔNOà•§â6Ö âqRH†4ƒ’ç‰Y#ðnH–ÊÚ ´½¿2ÆÎDv‚iê5C Õž[2Utñ0èÝ Ü"€sä Ù>玚 9y1Ç0fää–™Mp]ÿ®~ûšŠ¸b¤)µšgrJÒân†Ãøñ8DÆ lÃ0§LÞ' ‘8ýdä@Ù:uhDI®‘ÉÝÕ¢©¬@œ1¿¬¥´Çy~¡b°? I~¹ QÃâHðfv€æàá{ìd³­TM'ç;¬®˜råÇP ;ÙŒš€’¤Fò7Û”] a¸ˆVÀ‹E,qv`³©HRäÞŠþ:ÌÙàLXJ»‡®e«# û‹ —‡q É%•Øœ…³äÒCØÆº`k!!Qy+‘úò™T®&.žy­Â̹¦pÍ™ÈCÄÛ4›#e¾hqíXÔ°ÿ©0ÐÁY×+žQ®š¦>‘wz>ÏýÞu耤a…:”±ÙKZî–¨G‘Ó0C—êØkS]ʲÉTñWqaHN…áìJÍCÖqV?YØl¨ù ŸlQärm]J™»"ªÕöšðYq•JJGØÀɬ۲¬°õÊèvT\!²dí-UQ÷#žÛò’ŠÌX]F [ð)«J“;x—ùâ„JˆÖçí ÌzadñÚÑ5Öd­Ú¡¹ƒ¯¸õѵ-ãOlÂÀ³\•eeW½ãÜãC_ÈË„„îù€B¢¶Gùo6FñË- õqcòÆQ«Ä?¬ÛÔ•ð˜Ó\dâïâ.pî¥J¦3s mRrб™s)A!U…½¬4 |òئbË–…Ì*ùj"-©Ÿ1)– Ôumqâ·‹úWOe'QÌ<’rµÉßIN°Ã­‘±E Âq5Tx´¶ Ñea$o¦bys`´(dã’24¾³ê †Ï% ‡ñ¡•$(·¬gÖ?YžºØ)Ò)+ n§&mÃuâœS8ʼn.¤Ãmðõ XLëOêJ¸N!§S. VZ]5ÈØ:Æ=³äM¶·Þž­uaQ‡îR‰d™®Ìg2_`2B»'R OÆl_Y=E%)†drqMvJî_Èuî¡â)„Éc2­ëh9»©s,öK8ÐíkŽ_v —5Ú0c¼•õu2j1Û3¸cÖXÜQ9‰ŸR¡t’³Žæ"CÏ€B©ó¢R±uíÛçž@*7!¸jñ38š€ŒêÖ/¯crXS½¢´HuRCW€êS]5v³#C¨"aÞ4É¥¨ækãMzP¹sÒØ]C{€tˆšÏMgd„GÕ ]åCðŠaÖæáý²á©Ç5Š‚d\Z–‘Ú>±­$nr‘¿Hô©§}£·Œ.´pÚÒqt;<«/æ„!T·•½§ÈÏmÌæîòîÛ²)ec*Ò‡Ó÷Œ¯µ ³ëÐë ÀÊ™¹iÜÏEÞ”Y|xûëÌêÝ›á25îè7µAÖ©èÄÍAvßµµEi-cÉ0–Z*ÈÈ@ªÁ¬×©˜k©Ö„L&†ãC½f;Î]k"¬k³Úµ¬0ýïÞaòËëÜç ÑaÂËV‹V¨û±÷ù†¤˜Î«Ïýñ¯ì¶X\Î"ôµ в÷¼‹Á[’Bú/$´[ úZ4§{U Îh¬¦ï¼”'F§‰â8¬6…"Ðc)Œ´Eh·ƒVRKjˆºênhNK„åiÄU:h œ~,.‹N6‚Bl‰ØShfFˆÀk¨vï Ð)êæ&)²ÆÍÀÙVjh]‰Žâ¨j|(“°t*¨…o¶‡ø^Ê Î"î-êNí¹6YÏ8upHÚIv´p c\Â"G` R‚ºÐ$œØG ˆÂ2nàtâ‡uÚ9bG§ ƒ\‡i- äj ƒ Nç.Ñ ZO«©Ò=nÛOÜp ’YÑ_‹(ÅîÓd‘‹#g¶Á0 ñÎègHÌu.ágjÕíÜ%ŽæP×ï†ß!þ\ãÎLÓNŠŒøþ Æ"£\þAb È 4' qÐ~Ÿ1¬woÍâ c+`ZIThÄ+‡6&.Žp‰{BÂ6QV‹“„>gRÕb$¬­(˜l\oÒÆ¢KŽÒãGvC¨½¬“D¥%B ¬î¶!ö\ɪ㒠*±væFtèDøt"ã.RŒ Tj&- Ò8Іk¥àöƒLKŽ]¤<ä¨VJPf- ÎJîÚüëx"ï¨#k÷0å‡Xú*ÊHP^)¾«BÃÍ2ÍÄ»‰üÍÂ%˜-¤nÊTzM„ÊÉßË8ƒVW°L¹R¦ŒoÜðj^ËÊ.¸Šw ryïØEbžihø…ŒàG<ÅüFŽàŽÈÓ '!+È‹Žtt„„pÒTKýöÛÑ4óé¦Qp¡…ÅMyäV9‡qÔÃr6PµÄã'oT²Nzbîœ{l/}ê86l.ë&€PâÔ6Iç.†¨¤ª¬)±¦ÔB;Ëb0ÍRͬÀ*nšD;Bje/qÀƲ$<ÕÍ\ðJŸ+ÇF`•D¸:VÂN~ym(u'Nk³!ìÚüиÈ/,ØEÍ.(ÌáM "䂉ɨ5s1$BV<çèÐËi+&ÑŠn²ñN*q˜ÜÂÔÛÊ•2 @áó’(¤ír¯³øPgR°0Oˆj»Lj$¢—ˆböÆ€Ôâ%,]Dò ˼ä"ç”ui\>¨Ž#"ß(ÐÒ¬†e54R‘’\òŠN}BºùsrÊNöJLzbÞÀc¶NÕÓÐ%dpc+yX#Dñd¶Û<Ï…ƒÌŒøî@„µ£ëYm^ILËPfO*pŒi*”ø˜í¢ë">yG¶|•ÕsðkÕ‹E<¢ˆÄ#çR"Ö%2,‘ƒ›£LŽFt¶ðëP°lDV•Ë9AlaŠ]`í¼Ù%ümްAf?I­h¦-;%öbôP¨ôaúúµ·ST¨þPmCÄÿ ìº:é]aG!"®V¹G0­tçJ²13èÇ/ãáN ÀƒÕëHO*"èDiåz6!ˆoÉ>Š"X¤1R‘ß&¨ë,ë2;a‚.!¯VÉ£K…ì‡nÚÔò\Ë4eøÃcÈÏ¢¬&†füæÒohUêêk^òrËÍWlÓJxåibODp ÎÇqÆjÁéØ˜lí^¬èåe ¼$uHaÌiT޾uŽÆ"š‘jìÔÔMiaüÐeÁt2FÌq:¤$6ã {I*)³Û0“ôœNFÖ G–”ÇékÈNKrÎrxÈ ûÌÕ6‰0=gˆ“ ‡>ç—QÆ„ke¶HîàZHôVwD'&χXÎö¤5U)…Ý"«²“ T>ê–¦&ö©Sê¦æ…¤hƒÞì¨gz`éaøürZ@dÂêªL'JG UE%ì4†Ç¤c‰S$Ñ ˆ£Q±`ÊÊm“*žPËÓ)é4E¤ï6czM½DVbÖ”gz°¢íh«¦Ù£‰%…·K錹C™UOGôxÙ2êË)ï=kí%ƒ‡cµ#M¬ME ¢À ä-¾Ôò=÷Z¢·„nÓDïE¤/Vi:¤ã SãÀèDе"Ÿ¢êh ×§ PÌÒM _‚æ•D¤·EíJé2äˆztõ.}Ê$Ni4ÛHºZHÀtatîè—X—å‘[‘Ät„¯,©Ø¦X¿!ø˜m‚)|!Fç „—2AeQ¦µ;LÚÇ4„¸Ô¨n´MAn´!MVÂÛ-ˆÓV«~CÖ¢K¶ ¥Ñ:øë`óY!¢³²Ð*ìpÛÙ“òÇ”Îh7%•“ÆÃwôIûKM0å‡c¸ÐûÎÉML•;<VW!3ÊC/1þèúK1uÙÅÆÃÇOG Û)ú½>óÜ^­_Î7ú¤CÌ7l5õ¼ù²Qu)¶ŽÉ«ŠÝAzNþº«7ñ`ÓZtÍØ÷¸Y!ø‘sß`øn²Ðþ#fOâ&‚s)˜ÊmнIá+ògIÃ)Ò]`>±{Ð\Ê‹¶)#VÚÙx~üÈ€›»NÄ^ ÚFgžºëÅ‘'D² ëƒù>–—•ŒièÓ¼VŒ€®g£9ŠíHþ'R‡Žn·„0œ0-¤k =øª„©cêÎG¥îµ;@Ãì®:½Ì™kî¯Ìª)70Ap/,8I(D^OÏHZ¹§îX+¡­ðhu8£¸2lË9ãežWeŒ¶zÀ V̹§ b(Õc¨Å­õ$Ö1`îN«®á õJJìoY|F´·ˆÓ;³yïÁøüïÜpœc’¬?Ÿû3Ê…Üïi‹Qœdhë0O5¨ÃÔ¿}™ñ‘z(j†°3Õò†¯˜·‰ÝWìÊtîn°XÚ«õ[K[¢ý~€ €X0ü…?á×ô>ýDÀqX˜ AØl^9‹€d’ä‡CàÀY >/ŽLb0 4Ýõ9NãÐÇ´þ[Éà‘xl9}R)€#î¡Q‚ª4èå #)‚R'¯ø¼)ù#’DiÏ›5 …&Va–gÍ"/-¦I#5ÈdjN‹Ô@÷ؼfcU Œ4ÒkM„DqTà%`¨ÍÀÑšÄ !¹Ó1’L„Ê‹ÍÒ3WKÄ^ ˆå¢ºP ®5”È[²–[5"#i‰Ò¥¹9½"…HŒØ3¹ÌÆ„rÓFó1ÝT µÎ¯Dïémƒª íCl-†¥ ¡uu/þ¯‚3¸Dö®^ÀŠôv‹è£§GýË„%Kº÷.«õ ‹”Ò% êfþŸë±þ«¢¯X§A«ZŒµh{t)P@¡%èÓP‰¸¯àÃ Š„=("£¥Ðqþ§*+G bHð8ˆîâ¨G¼€ D¹ª1ŠÖ¨‹Ú ÖqkÆ– Ë^ž·(«)«i$WN∱ NM°= L­‚¢ÍËpº#:$‰jê’O ŠŽ>èä<CS|FÄ#‘kè­Q+¬-Ð#.šÉ-Â'¸à”ûÉÏœ<°*9Q- Bª„2‘kà¹h»(ˆÈç¼Î°¢p€ Âîò¥2ŠB”ò¢.R™_Ÿëaþ¡-ȺÑ(ºO‚=2£’%&),øÍó\*´R©©û*É.‹FÏ êÿÀÃ!IAó™Ðѽy² u@¾Ógìi^ÌÌ«T*h0Ãh 5Ýë› µÓ•H°RxWpQôœÓ€áÎ[Û{ÝP%/ 0XXòº,ƒËXÛUÓ‘<*å[<«VW²}žŠØÈ5wæ'Ú3"\jP¤W{eæY  «®jO ·À3òä^~OœU<|œ;œ‰¾õµ5t²(VÄÂö»‚Ÿna§,¥¹L_B' Ϫ„ ›§¤qm¾¬k®…VŽ‚ƒÐ—‘³¢­±ò–Ö̦Z†¢1hÐDÒò‡!IjZØ;µq¡êŒW\N(¥¢†½•Ûêq4±BÏH6¥¬÷I=¸Èa1_T´jÙð ŸžÊub"kÿÛñÇê[ÃÞqªÝGÃOW ©Ñj3ŠBݺ5M¬…¡‘'ÞPlZ8¸µlÞ«œß§>AIf¡ ®Ð²×ÔÍ(˜;0X»ÀaOÜ!¤.‰!`yíy&ôFIj&ƒÄÞe¸[›ên„–@Fâ«#´>)÷„¶CJRÜc†¡ˆ0Bˆ¹Nzke2”º@“)›8d)–·4ÝáH;,Ô2áZÃ{J #X´\ΪÉfå(À’P–9ne©U‹2c6ç_˜{î‘ÜFE¨ËÔù9L¤f?!ú…Ú`U1;ÂÀÛy®ŒAºµ–¤ËÒŽ+\ð0'.YBމçöÄ ªWó¼ŒÎþ"„<å1”[ieG5&Vº»3kð™B”[`ìVQÇ6TX<xŒ1O)ˆ©Š#MëúB¶"ºÄÇùQ"&QãÃØw ¢ÌÃ"ÑÙ(õÖ¹z“Kf¹Ñ­å“\n¯ì‚A¤(ȈÔ@!S± ¥µ¦Ü߬F"n-Ó€YÐÌåÓšäÔ–•ùâý!ãíBPÊ„°ø°P‡­ gPˆ(ÚCÙŸ@ë2NWd°Z³­Ç9‚§Dm‰½ÇbÕGÔRCJ‚ºˆ‘¹à뜺9Ã0‡ê *)îoÓ¡ôËJrÓWnEvCÔVüW™B‘PHÈ;Ê?J[,x†=f2^ Û™Hó±nsîX r&îò YºX*„ƒó¸¡=1* 3OmóYnTz†³¬í=qÔV„äl1% G«Ãßã á± tŒ¬o’¤OžÌ©)"ƒ\ÔeÜ£˜ÀËŸw°aš²þ•­=åºòÛ-`ÿ€‹ùû1êP+¶Ö½¯Á:aI#y9°æ 8©_gœ¢ÈFØûR´‹Ì—B4Tóx„߇Ù]žÖ>{U R9sDÜØVBúCU}T«d·uWeγ?FôµxÌŠnBh) ’E€3‹jÔí·”2Ù&­œ)’*žA^@{ZOT%A+º¹‰z- ^4.M¸€5°ôE(p‡¶ÇÉnƒ1Á’€é½g!÷›§WZ˜äý¤è¥ MqëiÚ‹î­~˜Ù—P9dÉÎÕ(•¨‡°x䑹HÈð¾ÂçRB˜:þ«£ø¥"FÂt.ŠËÙšÅ]½;®lö—Uú9‚© fo„5Í‘]ÕÙ-Ål¦eILwùL[‘®†e^•,¥å>tI ¾ðáôKhúÓ\«EBpª{¨65´Rˆ£X“ÝvÚ¹ÏdÑ8p‹ß«PC7Æ¡‹O@i¥I ×5Éè–„r„I}eµbû‘̈C(ˆš?Jø¡ñšKÆ•ØÍ»U™7jkNb,øE[b@ëÍ ÖÊ'±ôyD{¹jßÃþ‹Q]iZ6¿PÃ`Dd5}2ŽU©3ªKZ,ÞÌ% °ç‘Ö Ç'ž)L4N¦CìÝøÄ³oÒç êÉ‘\ì¼ØäVWŠ`œ¹RC)CǪ“®'HµW2rï­#RgE¼:´ªxæÎr`æhÔoæµû±9c'/ù®¿¼*à¡éý<ªã3BX&°ú/š/)‚ë¸û¥0y‘„¯óÕ€I¤S‡Ù%Kιñü9j“,AX: ‚ßû)8ºk.ŽšÚÅ­Ù ªAyŠë‰/x§©´´s¥)âô;hàŒž²ÿ®‘”³4¡zþEY2¬Ye#§K%*0żSGAº…2qd•±A'pµ'´BÑð.²»p¾žkô¸Siø‚±ã 3A°Ãÿ»Êry§”{˜Š@nDŽ#(Š«£V 2€(µ!sW¿Ãv¹¨¾ŠSä¾òz3p¨àÄ›Ã9yŠtD¼0ƒ?»%»*å±€29N7›G,˼/°ˆCû)½$Ú±™Ì qÊ¿ËK'Ä’˜}‘«„#Rt%ËÇ€óC#  –¡p¥Dì'Š˜¿|'ŠAEÀhæ™k-®ëꈪ¬Ã ÈæŠë_([¡4B†DQ¥´$Ò1Fdk±a˜*X~G`ú­¢•;„¡s'6bÎ{ ˜sžÆ\#¢’Ddz\`§3££‹…@s˜T9š¡ß,{;:€ÛĽ1]¹[`¨ º°3¡$”#í3¡;—cºROCZôI ¸"¾S1Å`œÉ<,ÂTrÁylA9}‰Ëä™ik§$aÄQL!¹ÛŠA¶:ƒù“;¢…ª¬$ ø¹š9¤JiÞ»ÔD³ý˜t£F¢Á¾LÁ@ã6¯ž¦ë €û C8»ðÃ.úü‹1¶Gä ’«%˜›ˆ‹á\“3ó#üÝ(bð€4‘\à’ ¬"Ã3FÌ‘ª©;B†"¼ÒÁ¢…ÇJç€$ÜÊ⣡®Æ‘§?âç?ÛjxÙ‹2@9“ñÙA9œL°|-˜ÑÂhÆ Dõ=¾‹ÁØ ìÿN!]¹#ȇÆ4¢ÐÄ80£‰ ÈA6•°®»ë%6³@·YÛ²(ƒˆ¢´†àû¿2%ˆ ©¹Ã bÁtÖ;¹8G3¯B ù#ÑQÌ>ûàX©¥tºÐØR²¢w0×? ³º‡(‚ ÄrJù2*AAÒ#¢ùHñ˜P×9Л–K˜Ê8…7;@¬ö‡Ùåºé´d/C}–ã0@].¦ÓÆ@äP»vÄTa–:1¸Tš¨Ry+ÕšÚéj×OtQ'!DÛЌ˲“ZA4Ý:T/A3…@ð¨C€†jTEZºTø¨·ê|Íá6¦j;€ñ6(‹†­ZÀ:HÆb{JØ  ×QãÖ%x‚ua¹Œ´ÎKÎ܇ʈžkF ®°Ê0 c²|ñÁtÿ-ÛÔ´  ºŒ1{ÊCej¯ûœ>`¡É´,Kg¥T7ÚèXð žlôÎ!¢À ë?EGËôŠRKøžš²ÐÈÄÔ´ ,xÞÏrì&±:®@>3c<¸0säÙkØ K£iU…Òòε-GqÛÈå,SË%(á2Ål¹:éMŸ™±Ar>7hûìÕNýÒ ¥MJTó8³)-—5˜™ˆÉØ„¦º®«Ç Øœ˜;: só'ÛÆÒ ‘”zÝ'p©¹Œí6C!‰ÈÍ”è~œ» #úº"´S` SÙBZWÀ§Š‚ Ot4[‚#ä§ÌcÒ²qÒñ 9À×ZÊMÓç’L&H’­‰¼¸$RÁ½œØ(eª±4y5´Mœ¨ÚÑäI„Y?꾩‘ŽŠMº¿s¼?°³ÀíišˆœF‰¼xÊü¿5£ü+¼hO3‹ =x ÙLHÄ¥Ä5²Ô<¯$UC0ΔšÚæÅÁ¦²È¸£çZLÚah–™$«Ý²ÒŒ¤SØ™GÑ£¼!ËFypOSª¹ËØ2n‘ë×T±(Uz¨)©ª©d§%ÅÑô ßœjPªJ“«í–S#y EA,û5R/C… ¦µÂ©;²à2‹à_Z¾ŠÖ uÔÔ'S3y¼b^ÁlR€)ºÞÝgÑ›ÅQ»öÕ•´à",¡+¤MÂjæÁ`}³ò+¼;øÌ:Б1„Éë34º'’Ks\Ò€Šs?L–‹U½c Ìœ.œøÇBQ–Kɧ´u“È`-XÀe‘£¥$ Ûâ¼ò%8529®ñ6Úô‹áPÔ{AžDÿaô«4ME`J’¾Œ’NëC¼#ö«ýÀ]Ô‡ÌEX ÓÓŠÜk™*„(¹lÕ•0`XéE#‚¯ºŽ4n•ÛA“z++8b¡Ñ§UÁ]®Þ@›¥È´õI\¬ÌÝ#&:…ESÊXcÚ,AG²ÀòŸ,ÛDصYûý #ó œàŒÝ{-þázÊÈä ˆjf‚[½)#Œ¸Nsz‡£We„65°3ˆP·bc£×DžÕ€âݹpm(°¡Õž64Ã(‰–9e»Ô&²>B"6ž3±ð~Ô²šbÅ÷¶j:[ }dcLº–EÛ³^è³9ÊülÉmá¹95×ðœŠÉ쪗š’¨áÞbm}á=äen5Ü!¿º;<¡iÝûã´ÃÖV‰Þ=+Ø~9©° fÍË4:U;I‘²Ád—¨Ûa“hy°›‘Ë9p-ÅÁX~n4cd¥\)Ûtfl÷”ŠÄ¡iÀUzˆRµ¯Žˆcœ DPß~d!ÊÑÙ¤óc­ÇéSÓg²(fý jKªÒ¤¯R¶H€ÙÎq¾Ñ sˆ­×;Ì3HÑä8è~W¢ì²NU@@~]ñOVÖi@åÄJ´1ë¶S##ÂôžZ"yo:8ˆŠœ ˆ¹¶>HÚffakË–4r+üoΚ°ÊÀ <¥Ïo¾á>Í2S}¸êÂYéþ*l“:î€á̬1[CÈç™Oa³£à­Œ#±d“Yð;`TéËld}GlªP¬¸6.‹5 ‡Ëi[†Abn(D㇎Cô‘2ÅÒ@2BýÎ>Ï›bAq›„Ì;ÝjÞ}‰:›h*©„Ñ Í:f®m2:¿ ç¾î_l…µæ*âi‡CáROáå.—™ÂÑiž—‡2d³¹9ñ }ËÔXÖ¬ªßtÄkT¤¨9‰÷¦¶å4£•ú r©nF8è˜<È`1Q 0èó n"•A;}¼Ø~¹²n§DMÓ”ÄÞ~õÙɧò1cµ¼G¢~Ñn¼¸\°·m¬Õ†žÊ[»-Nh0SƱGÖ¾“,j¶ÂÁˆnØ2AvÔàòš‘•°ð¹ƒžkA†Ïsˆ½X'F!ÅZJ8˜i“DÙ„¶ÜpM³äÄØ§M yó%ƒ:}ÜAìe.[,E3¤áÒöœâ}ý ƒN6VIžÔJëq5 < ,#‰fðŒvãü¡=IVU <>&‘i¶f·4–/nˆÂ›bü •÷3QÏVóbCªgøÇ`y­Ý½ƒp±Ø›NÄvkŒ¥…tQÕÀ;ç®eÔ9b×£NBWNp2 FU@}­ÌÓoÉà‰9L°½:ߌIZ£.‹ÂsÃk™7+Òm0:â;Zt(=3¹NÄ4eAiÔ£$q2s—¨TjÆÎ·éY“Q-­Q›ÞÖèf1ÁMט16øý]ÏgXƒÒצNH.x Œ -Í»–ƒlI“@ט¾ÂÙób¤‡õÙB/©n¬Ä!° Þ&æDpÛÕdÃâm’Ý'·¢Ä +³Å-+q–: ^eç< ¿MIrpµlH×6F³ÔÙˆõþkŸûºŸ%»Þ¶W,ø^ó†X²cî.nÞíàtùÞuR4¶²YËÙît$@ $zH‰¾eRi#ö\˜L^Ó9sö' “Ã!QTõù? NàÐ ,F ‰Ð"1è¨O7„DjPhU ÿG„K= 5‰Ñ#‘Úlž­ “ÍkÏèŒ6'¸\k°iÌ& 8’SA¸»êkJƒG­q¸}ÿ¹C)³XËì•>l  'ŸÉé¸ÙÔ›ƒƒSi´,c„Mf²xö6="|^ÁËmº«G¡S]þÜÍÆvïèõå C2`,TV¦ÿ¼5wžuR Æ’Q&°¬lôÓv®Ò @¦óiÒHœŸ#@°À¡˜ÛUÒå$èÓáý>&ä9ë¨Ý¥ËBH®.*C(Ä? Ê:³6ì:&ø¨®±üí Ô&ö¾î” Ò¢PXžñ+ŠŸªÊ$†=ª‰©hëÞŸ‹*Hø?k|û ³P¦£Èš¬ú%Îz<Ù2íQû +lˆ~½-üt­Ç¬ ®(‹—(Œä§!6íÊ:ð;Itp5!ú­7é:€¦EÊú\¹ªñ'-¦È{08“;*ðÁý k†¹CmL¸".[û IGêbפOS¢ðF:£ Oðù€hS?3ª¬îŠÓ0`†2-Ôí€3s|»Bés‘@JÈ—"i™ìlX m|˜Î‹Z=$•òÇP •Júè¿éN¾È(z<¾¢.C#D¦ª"Ø&©‹Í:ŸÐÓ•E€µ* 0êÕÌ„U*û1}a6Çj“£3Ê Ÿ+QõS 7ˆ­KT¡“€ˆ±°¢+Nâ2õE &*”¥NE˜`—CƶHŒº*n—3.£Öðå)DUtÝȆy«–‰±±)7ëŸ5AŠw¡ª€Æ­z3P\wûBм¨DÊÕTbúªN\5( üÄ¢kêÁ*k–¬‡!ðÓ)­„›+9z:çÁ@˜ç$B.Z ·OŒmÕ… ÚÆ}OúÆ53X4§ q "­¢i\Ž\UÕ©ú†@sÅ]Ÿ«]KC6îDénÑ•%h (•;<ÂmU>T½@ j€O“Í­Ôi…BÒΟì=‘@cPúÙM!¬b3b%²/-¿ßÌ ;ŠôY–ÏYž&޶œ›ï€r2:¾ÏkΟѩw8-ttÓ¼•›ø3;‘RéÕTVBHýU¥Š°ÓØÚNÉD º‘ÎðX ! ɰ ´¼p©ÐJeÉ€rؒ€vÏQ7ÖËÎc2-o¨™e”*qÅȲöG&Q$=¬-¬ø 4,D=g]±6  ”FÛ\p&°áéòbÌ !°aGå®Áøwް)©ññ»Ô”r"tQÈ Ûœ¸)Y%#¤) SäüÊÓ²GϬ~2(î•ÈZSoÏÙr Õb¾HbôŽ„ü¾—'@Ò ¨h†¹15îÛa(‡ Èž¤š™×³±G‡qˆ/ S(¤ÙI!K‚øG¦xŠ‘ã"€ŽDƒR–JµUÐZãpìÍx2÷îš ™‘zõÛÙœ Ì6Qj9Íl$6QQ¼XØòåÚ7ê+*•²H›z7ê :N)Š’kF\pô„Mw ¾‹sdÒ½ EI9D‘±t~E8Êζ!ŒŒ}®t×5GñÈ‘cñD¿ÒÖk(:ÜyJ ~€èæ]|ÝT E)%6oÎ{…$Ÿ•ª Ìi‘(’”†Éò~°‰œCBrZP§É,t[;íš-í+ %¨˜És¸~¨z€JTÌJ°O‘¯’ÖðÉ­8HÆ€J´ÇßyÉfU-8h3+Ë‘M2&¢T&0>[­(d°„šÀ¾“`Ìœ lPâ€w™ÑZ)µÉd´Ô rôyÃíPDj¶æ•M ‘•¡µÆ_Z§ee¥÷+Jigì^F´Îó¢Ä‡Ü4éVÖ(M7¨¤v­4©Î9ƒ)¬}¢b"8´$èh—\^wM•x/+ã„ÝgD0ÙSaù:GÜÀ™üàÐÒÜðR´¯?Ðþ¤©Ú¾HQD^‡Šã“#t,ê¾Ô­9aÛ|ŸÌÀðO¥–žÑ'9í£<3wa*¸ê¢¬Â”Š„´ ÑÀ`SI,,Óy¬ ȦÐÈ;ã…š—QqN·URMl%B@OnÒËÅ"†•L¡ºL×ÄǦ‡_é²k OhCRÏT6Š—×iî~–¨ÈŒÕ6æå˜9]´€á'OÕ¢Ÿy’ ñ“ Ê>çÔÊ&uT(òÓÙ\½Ñò¬cŸÕ+ÇDöÄK–üÚícŸZîÛÛá-…,È ³¢›Ó! M]Ëå¬):!—«^|ä^I‘š‡ôݪŠÇÌS1ÜÌ”t:k»ì tßüR©9Ø/ºo§Õ.¡Ê—úÎçÂ:¼_f`aùý@'‹EÊô‚ø,ƒ+xd¡Ðê©x3ÐCd{¥L‚BÔоÝ&>FNA1–ò£gÒîm¬™™îkfÁ“QkÖ{óxŽ.hd T¿Y‚—yHQº±‡W ‹ŠAø•à—"­‚—ÍÀbÄþÂz_h—w ã8€âỎ‰>ÍV…ò¶îã0*ÐúùTˤîèsù'åTW¤@ŒÅ£«Ú‘à¶wÑwÚuéÑýµ}Z•©Ôª‘ʽX·‰vç¸#­ÔØ(šE÷Pýxéò:Ê%ÈÌ*©÷®J¨þOX¢“í}d~¥jøñWúª\˜çyËZÜ»mR›g¤„"ó’ ºcX«¸ãµ|À`Ñ£ÚäÎü\‡¦®'ªk¸"&ÃP§øË/.ü1ßrù =Ä‘w9;˜#£ÏÆ+¢`5&Ýä` l!c£+ÛóP† ¹k Ø)•Ö"Þ¾IÉ¥‡eÜ§Šœ¹õÐzúÿpp±Ó§8PÝ\g4\iý'°¨ü|K•P1VÕÛ $?¢^`CU>6«bAâez¸.$Lm}V°¨+Q*¡Š§JÂÒUñV*~ Iðo6ã"Ûm‹°`žb\\x!ô¼ÑÊ„›‹¦f ²ræþi`Ò'¯$Îå!‡2«­LðŠ^…|ßQ.*dø™bäŒKIÓÅSÂÝ 1?IénB|‰Îŧ2ìÓòBüQ˜ÉtºS@÷4ÚÕ ”UCž0ò! ýP"|Še= Orw&[=¢ICqZä°ëuD¨R¬Ý†dÝ3)ƒ®ÿLÅ" MQ%#3ν~‰v|”ìPÙQØHhUÈ·ÈQ2UãI|ÏTèÈcr6‚¶K¤µ0IVºÃ”µR V UM‘ƃ–R2¶wvÚŽ7LåúgC¼ÄX‹XÌ‹ÎçVëˆhIe4 TS˜žK®ŸÎVæ– $éd±n9f.téb±ß d*¶lü«e î“iB^B.x„éx¹K‚Ðj†t}Mn¹ DxkñKD@‚™–sLGõoJ‚ôJ·8·‡p’Ê_ƒlÁ Q)Š 8 7r’+ Õâ¾rofŽäµ¹§¶Ÿdy„RƒR‚@’Öä/ÍF7&Œ‚y "ˆ2õJôçfÀ®pð*R †ø¸n"æõ‰H& 4\tˆx÷,$¡}élc6ý)oZII—‡Ýe( g–²*¥öÚS fXc âE¦õz{Ž Ûháñ‚Xöøß_l×IaTZN‡q Æ‚£™D›.ñV½NÂóNB›¤è;ˤàÀlñS) ã§¼~j&:/6Ž´¦ôvWSB£TO$–Ž$šÖ—B%}6êüã`×pð—êθ†oS§ruLChá8ðc#Ò*¨_¥Ú¸ YŒÅ|l8¨T6CTç?›]k[s7c‡òÒ¥Nô”«Ñ=´¢â1¯TN—_À6û6.s¡Ê ˆO‹™Q×óo½áú×B3g!ë?Ø#lÏ#œÚÊ#8\#¼”^”‰#ѡⵋ1ªÿÑP„ú±Â¯žð[YË7Ã}ø¬…v¶ÏÝp3l5V—ÛŽ¢×BVš6ÜÏFuÒÆ‹¹—Ð$y’ÈV`d<ļßhPPXÛaÛæâ´Cøù‰ø²‹>Îq±,è$ ôjgwezo²Z4«ô¡Â΀¤¬F·›rÎó4˜j{ +S™g¨ÕlšÇ_J#X¡ôâ‹°®v¬½§dkøhÌŸZ„-©Ëá+_ÇÔ"ÓY¤Jp=LÂV!JÖÌ“GÙÔ."­SµÀÉ«¥µ÷§EÄyœšñû…uª™8ÆZ¥ÏœÐ¿RIÙj#Å}Ü©.˜Ô8–ZÉ4DŽfräø•ôX&3\ù('Ô‚¦û¶…rý„eïÇÅ–±o/β~‚Š_ƒ³uK@…œ”çгª&!VK–{FÝÁãgEA™xÄ@⑤~™DÔû@k¹ã·(»(2I÷{Ô¾#¯Ó „_ñAB-<òj'ƒM´Db­Ò‹dtÁjoh(6ÛÁ–¼gä@^ž{~OWÊ‘®§E|kY©Òý¾½ $úu—o^ØÎaæ£W‚§–ñW°(ÿ·OjwÏì\‘dÀ¹ÖT±†½¶~5&½¬#»áùÞþrk¿Õ~ýŒÏð|ˆ²R¦dáBû#õ§¶ªpËìCf±4ÔÿÙÒŠ¸ÄÔˆ/˜óÞ$›Ï®%QŸc—·ÃUô™z º¾ÛLF‚°‘õ¥×;º[HŠC¿ršŽ5~°—ïú(3²º§}vÉ8r©ª é7ˆÁ×&wzÑWQ6Lú*¶»øâª 8òÿƒa¨P€"À @~#güPŠE²£bI‡>åÐRMKãQ@4Íñ5–€âQHt½ý9ˆJ§‘) ö,£Jpêø™©è¤òn÷«Q€,)õ Ã`R©TÕñZªF Ö(ìJ™²O!Ò¨ýΙrˆ\ Q€%2Îÿ‹Wâq ü¾ÃE) eNy„V£‘è…1ˆR™˜´² —Ú€Y` CºÇhtøÕê,õ×SðÀzZqÉS`×8þ‹9ºC%YI†æ!^á– €È€¢SÎ|KŒþçÓúœMÃÿ²ÿÏu¸½­42õ·ã¡þGvy*‡[{X»¿)Úm@}X•êA¥í) R´‰!ÈÒT"ÊCtÐ.Àˆ­‹bÑ %Nët‹&ðc¢—·¬ ;ˆcê°pd í;êE æ†(j\!5hÄ4%LÚ~µ¡*:žE(2%9 ãbÀ+¤Bß­‹À|ÉëÔ?9`¥%o™ý%’$§ÀŒê^Ù ‰ÒÂŽÃïzçJëã<‰)"íM ’À€Ñ;1‘º:þ=QÚô+S‚ ‹)ê±î¬O3Œ¨¤(r¤§343 ü¡¯KÔòÞÃÏŒ”íÇ ´SPxêÄ@ lèMN;E!6ëíP•)}(ÔH2¢>M܃(oéú•+ŠÃ¾Øè•&Ç ”/TKb 3ó=+.ÓÌTxíOŠ Ë¥+SD¾Ìú$#ªÒ-C– À<±zC+ <¸†)ë%ȽEmŒ¶}ºétÜhº„>øÑÔÏ|¶7«2^{bnÃÈŒ@êw7!–"Œ\àþŠ ”ƒñ‰žÒýwV'°„?yÕÖÒЭZgõ äAQÝRX0fJ˜ú‹[Íî™ä÷ÚP‡/QúCJ(6Ae€ õ'Ÿ*â¢Hu´„UPû…ª7¨¤.ƒR(f1w]ª{Kiص0²9èu™èhBT×®{{Q¿Õºc-îÄç° RCZcˆSÜb¸eË‚ñZSñ¦ØXÊ\ô_9ÛuÏsÖb™Eð¬`ñØIýïñ…QžÄ»«±4ÀL¤4JT§¢š¿?zs¨û¿:;³n©áxI÷š3 b¸ÄÃu*$­+GŸ«©ÜŠÒ¸žd[ô%YGÎ=jö­[V™è;w[ÕfO?cjC(ñ«gò“Ûi)ă”æE/é?’ÁÈ#Yv¬ù\¹SÒ¡½ŒÕxÔA© ;©Å¦ ýâqU å×µ8xµØys#ñ* ³PHZ»Ó!i“›„ž [†©Õ¿‚;€(iØÑE2JL£n±êE)èLçѱ\¬:Ÿ¸ì[6Oi]>,ȈÙȱ7Rf?ôVœN«W"Sõ3„°vɺ¼„²0ƒI˜"Ê“º—#´~/6]´¹O„ZùL„žÑ/‡hø„ø¶YÔ£“çxÏ&XâŠÊÓÜJè2XÍ% ýGê|)=;NøŠú‹S<ÄÕ©ºˆ®_RÛ#•œºg0ªäYWŒ”²ºªÒ6l³˜~O÷Pw[“ˆÐ½²¹¨’×ÇJ‹ÍQ¹nÊáã^­p‚e1EW‘Ç`‡å†È'_:KAHrï•‚¸³(‚b¨p!˜·€ ûRj64J™›tl£êus1Æ €žåçü˜$EÌï“wæ°]âO4ƒö €¨Z#n"ˆ ´’…‚ä"º§…°«9 Ü+Ñ®I±˜Èh;@-;rcõ‘0¶È©^ìöŒmØSy¸ áth—å' .©’D~Äèð÷¦}Ž4P6èiP‘‚ð%’¯€"üÕU0ò† _4c–©ú[94?UUužQ]ÔB+%7DòZÀ?–W(Ê¡õ¸y'¦BàY¤!,7Z“y(·êñN3wÕQËìÊ[ieŠî­a=Á!zì_1ö‘ª¥Žvҳʲ¹f&«®[ (¸2‘wÚ©» ¸——«rLÞ¦1Þ«ÇwÊby­$¿’× ºïÜ¡¸»·o1S1v·a—–—î‡Èµ¼}îFˆ™è£r퉄Ëë6¶é‘_Áÿ1…¼ÍÓDï“Êóhwžc "#ò\¹‰õ”¿BOœfDžFŠÄ^šõ·“FDìÍ]u—zÊëXmµ\hæ/Øa§^ÐGÓû´xŠJ+m^cô—Ç«tL½’ãŽv­òÛ·t;ó—®1½Zš±¿ÅI¢’è±æ›<ОdÊtÓ“Í!É_¥5ÜÓ)šjN>@_›Ÿ^*ò;‹+§™öôOd…hèß‚L6¨_÷ùäWYºP†!ô“|Ï;¢gÍ×od«´˜§lÍF»PútÆÃGP ,.üyDwÎñ;kðºmÙŽ[E,Ô«tŒ|jÞ¶ ˆ\º0¹ ¯vº%bÔ“=½÷D…tÎ_ïÞ³.e^wb|ƒ@°W1 ýþ"27@‰"[ Q “ˆÑæ ¨µë.‹2ž™½¥[²ê效ɡ¼¾ 1¨K‚• J¾›ÚϾ ~¢‰©‰áÁªˆí Ñ«¨ó"­ƒj=c¾S•j±ÀòþŽÙö&§`„ aP-±^=ø¨ @²+ºQ¡ä¦ޱ™;!5ëp°©ª¢á$ ¾¡Ú¸B|!ø§ŠÑ“±$(ã¶Ù!ŠÂÂ<ù·Á9¼Ÿ»ì¶"!¤ûõ–ø}’jÞcœ 9ל¡š¹r9û3™ËA£»Ô,âŽëCCJºåŽzäˆp²§£1[9ƒ‡>š O“1½~ ¦;‰J´Â¤iä¹I%“£ÁD 1$ ˆ-ôN'˜Þ—¨}‘´5-”6& ±ó”r'Á<¨“k¬³® #Í€X‹ ÃB½‘;¯I»½`¨8†-j7*XY߃è¸hµ;ƒ¿EépÅÓÞ¼h¯3}·† ÒÈ'šŒF´o¹¨Ä @¼|$€DpŒ !é㣀 QBÑ««`~¦p3`zs‡ó<zE´M¾„ˆRS¯ ?‰Jb¼­‚º©æ$:ËúŸ»qIß8©[:Á2tD$8..«Ð`½Ac‰Fò–½K­­º5\t‡ô ¿'™Ü‹SW;Y¾°íÃÜPºðö=k  L€½± õºŒEÕˆêÏ *L™ú38ùÔÀç§{ÁCÆ&«! 8Ø·2Ž$OÁ&;­ŠP2’“-â¼ ¸™ LÄŒ·'zbºqäŠáÁ‘hˆ1Œ—˜«ª|;;Ó»kÿËb‰µÁ )ãýdªÝ) ¹¤I˜a*2ѱ¾ú\’iDŠÁ¹Q‘%À!Ñ,ÇM;Ã4ŸkÌ»YFò¬4lE±^!¬AÙ×ÍC0Äì'­ ÙŠ3]©SssMt‹‡Ô¤‰™ºœÅÙÈŸjqP9{éµ)%½ªz•¬<½LŒ€–ÂÙ*¡1¾ì….1€¯c "¹g II JКCa+©?òc°™…“¢;Z]:s£«ÓNãÀl@ 9Ü×í8Äfˆ# °¶=`ž)ó«˜|ÈyТ°Ï?Ø}E¼É\2œ¹ÚŽ©©Çp‹ §¯{«»8Cµ,”F0SÿGP´$ÌwÏ|À“\6#â;ªR;9*ªº`Ø—"FÅ´ð0Ý Í3äˆê ­(51|['Áд „)òNÏØ}¤ä&:ã|Al€@úý˜rœ¼Ä““ÃYâÆ · ¸­ &›sEX©4»ˆ`²@q•§ùß"„7•³·ˆ‚¸D5§ü©LÌ-Ó©L?$ºqë¾ÚÉ©5B2ëSŠ£¯»`E™· Ášº¨LÚ2Rsã<†EÀ£ÑÁ‘O¼ï2®7ÚSd“¡öžüt’YOiO?ÉϘB|<œ:äL‡øØÇñ»M»Èî´0AÁ™yŸjмœôƸ‚HàäW[…žBÕ\°û®]aN€¾ídº„p°œ-Òì“‹Þ+«§Œ¿C+rñQpѬ¿“²sÍ€ $†åJ¥ \!Ý{5}ƒÜ3´=fڻ˪G@ [.=9‰šf‹š¸TÀ)ãªÆù&™¥—;Oº£ºä¹t؉|ÕRó†9ƒÁ$TyFê®ÛìÕ"ÞV)`ÄZÑÏ¢1Ô­³gHéû­³œ»˜ K¨¼z‡Ül.iT;H‚$ Ÿ‡•·MÂo2"Ç¿m|S Áà¬$w³ADÔY‘½²ÃÖô=ˆÄ—Bñ϶{ÖÁ貟ÄCÏ Õ¬:ìÀVtàÅê×ttBtÀ×ý6Ý…¦ÚÅ5ŠFKڰԉףU2wð®Ft+X’ȹ*”-uÁR#ÌYñ j?Ä”ñ…­úD³Öú~Ny;¬Ý$e& í¢µí[M•)y·¥˜‹bž5ÒªÌøRÓ}Ö;’dà8#ò!…}’êÛYHˆ|Ù âÅ'· ‰“ßM R-F©<-ÉL3‹#}›ù¦Œÿ¤TX[û²»J:“¯Q\xR³Y;ƒE•Æ»½ÿAÙ¾ØyÈ 6UðYF"hªÁ“ŸŠ5H¶j² }º4=o `­D˜Û¤ &õ¦›EÊÎG—4ˆôFõžß»± {ž¡ýX=X®PŒ¨yÓ4§¦Œo4ùJàåIm*Ò#ìÂêÍDKPZaËh¨Ä©a—Ä­4@ ù§ªÍÅ b>Ø5ýÆÛ§š$í eÝß!ÕÚeÊ\y6  >ìO¹Iüxä+§HRLØ-=Ü겈ÓÄ#O»˜tÑ„@Ádг'»-Ñ’»BÓ „?Å7{ï[ø¤aò@Ðt—TÊ2V“ѵ“‹{ˆU¾Ælj™Ö äd>M‘´ÁÞ:[­Ô§XG±JžJžX *Æ &9« ÁÏ[ÖdÃBð›EÝ@êÉOŠûån2 4’]£å³FV‘²ÏFéFkMMµ¥Íª¾®)æ„ÚÜbÞAx†¦‘ d‡¸CzftÀhJì/QÿBè.ð….^~O:Ý5é„B0‰D³L<]ü¦hÃPÂl`µRBÍÀ- º#ðÀÝ»_ýéClÅäô(ÚëÐ\›Ôo»Ã=dÛ‘§ŒôŠàu-ž‚¥Á0[L I*IÖHdÙ…’j| Öp§žŒ§Ã+²öµŠ| *´ÈƒI / ÿ›^…"¸½8É[PE†Dû¸É±T~hÞXí/¼û²—#)õ)9…V⤒ļ´¢õ3ËÛˆéÈ9Mú¯]Źü˜®æ/ʉó®YZÑü6“¥,ÅzOÆ{ѮӷڮZ)s ¦´†L×bÎZ*¥PaÀ+Ø‚K™µK.Žý5\Ö½îÞhç-¢ff'&}ÎþgÔ™,ºÉšT•Ò$„SWµ)bT™mÓ“W嵺™µ¹TÐsÇàÜwy~>>ììÂW±¤à¾ +€c…ËD¶âò_ ÜV&ÐN0f,ª¼±+j\æ^‰ „^ñÕ¾RèéÁåÚ£ü*o îÏt5Ûš•û¹ì^VØ›˜Ø´Ñ炌Pš©ÃkËʱ•§tbËÀ¹ó¨Æ×çäsµoIúâé›E°¬Pðâ‚»í  )|(uÖœŽžqi§ˆÁPelÝ_èÑXŒÒ/¤¬äÜãš”KW—"¤¾wˆe){Ç/ Ç)Õ´ÊE»{ 3ÊFáR®5ñÈÑð”PÄš®xíì(à LÁÉgð~¸‰šHVœ’y¢ýjEÜæ]Ÿ2³ÐÙl´õ£º¢ø¬]è”l Ö&†Î¦8Ô‰˜•b¢IûPÞxíC„JY[_¡‰¸b¥q.¤,V<]ĶïTé,­ç+£Zžä뀫Pš»â…} Cc”©U4¡„ÛyK¤MVEW1›öCpäY³š;ïÈô¤d<Ù…Û:;™¥ñìòAKãPŠ[êÇÃìÆöh4}à=g$V½¥EŵìøðüÕ±°š$«+Pæ›Cœ`}Mm‹ jùdâ•PW¸Æ×KÁƒY¿Hx[}ï‰,¬öÿ¿!‘+È‹gjðž‚2òrÌjBÛvx»î]–öœºÛjü'Õ„ïWu±Þ¾SióÖÛ𻿒Ê(Øö…Кv¶W=¬]Tè]Uç[ÉÈ®V)!rªà=qøÔÝÕ-§=Àtɪ?…IøKYÈ f­Ý~”N¼ê‘ª$kWõŒ¦!´Rõi.è>`v°¹Ù¥¼À²v tv);‡G勪¯~Û-^EN7ÝA\Ö)xRLÜ-/ídª¿ƒ=ˆÿ®‹G»œìMóK|^(fqK–L:;úvNnl½FüîèµÀX¥Ç²*ûÎÍÐ1–ÝtEóýÅsoÒSJOó3=ÓÆªÀ½aŒÌmŒâÔÁ£5'?Me7.]ó(²-)TPž¿•·ÝFºÖ‹é¸ü.jT¿ˆþÁ`Ð7ô$ C_ð,EûŠâа4 F Ѩ{ò-#Àâh¤r1ŠHc@y„P 3A_3yT. C¡ði˜¡Ãg“ØÔb‰¥¿é< 3£Èhµ,1A½ëÀ‹¢&û²¬Õç¼À+¶Yp8$ì!ŽF7{ErJ†Å*ôÕÖû Èå‘94N"·bñ/٨ᓠۣ؋ã5fQêùÔS!ƒF$y§Äj£pÀQ ¶‰cŒdß÷,–Ú”ÂcR;U7CÕAp;èmng¿‹G%Ø7ìmAŠF&ï›#¯|žÐr7HLÕ¨ÎA£”µJ £Óêø ©Ä†È÷‘9Ù´†k®hzØ<ÈJÜŽ*é",ǯGú(Î#áõ£J ·-Í›r³Žt © *‹AhB…ćòÔƒ:êºâ¸çò‚좎»Ð‡¸  ʬ·hãÂɤi Sé 6„´â2¤Dê{Ú†¿` ~R™ë*»Œ2Š7§ôné=@ Õ-"p2ê¡lZÄ~ÅŠb5Ÿèã² žS›A*²:òÄ’D˜@¼ädÄ2j|j~)([îè¢Ñº(¦ÃJ®ƒ1ij7(* "}Nó!þîT Ãäå¹(YçT¨-ZÝ@hŽÓŠŽÈÉ©ê8´J`Sà¤orý!30NÀ-Ä/¯q4vWõ8ôÔ6cn‚ØŠÔ='Çã0Áo=L:ìå…*ñ¼nŲ́b§©õ³6²m•m£Œå"¤@rä€VÀŽR÷d;I \£z$²úN‚­È€4à@8$ „B_зä5ÿ„€¢P˜{ü …¿¡1¸CÞ= È_8HLû”eR¸¨"] ~E!ñ™d> ‚Å_³·Ôô?˜D€PYëêWB•Ì!1p4êw¿c0™] W¬Jph$p„Ì%rºŒæ5РñÈÍ‚½±Ê­ñÈ­¶!¨Î —à£BŠÉ€µ©^ +­DbVŠsö X¢áæÐJÆJÓ¨ä'µ‰¼f‚°Ãiª¸¥É€åpZ+<þ­k"U‹þbw•Ö;¹†š—„Ñi0ÚeæT¹B0ú¶ñ; âù5û½¿…*vhUÖ½ý¾„JæOûïN¸Ñß¶üÈ•a»òßü‹§á¸Ôuü „è€G´¬ ,>¨«Ñù,YþÎ –bê…ˇëS”r×ÛWâ¢Ñà;-W+ó= â¨ñîÁcÐýرÊQò%C×GƒŸËär?h-?âN¥g3_ù4h†ÏNX¦cÔü°ìHIó£¾JÂЪ³j¾@(L£2!­«›Éðêfã×–¥]>& e°•³J57QS1[M>¡¯‚W;¾ˆÎ*ú^Üj§àe:ý=7]s…ª*,í&X Ø~bª"{*䎬êà! ðÁTÔ­Å Ú[8­b³ãemó6„óEvÓ-l(»º…ÒÀ$ÐðfÒÎQòŽ·4Ú—VªÁÔò„Óè)çáËÝ¿[É&맺Ñ7"…¥%Z9ò¬;ÐF5«=.ôWÙ[Þ€ȵ;~¸Ù‰*M(E- ø¬+)D¨”Q<—¤Ð! BPÿ”øŒÿl°`I2+enݽ¬‘úzMÉ(Bh„)6šÒb*è!ê¦ôtßxûjJu.GèÍš3G!,TÓ.LƒÎú¢WÔu@:‚a¨j±CfYmM’\ûGÚ¤¶PÓÇ/)ù&£TY£“ˆcf +pD\¨CgX®Ká0D/²pÃ¥PgÉ1EPÄIŠ¸ÃÆÔI:p‹Ž—²•¨±Í€.9‚«°¬è=fÏmX+#$ )ˆþ^­Šgšz½è ;ÇìÁOÚOc}&Fq¤‡TŽJÔúäI³Ðë€÷,ù®u¬3X¾–€)Þ[JÉ*Û\¥Ik¶%p‡ÇXìK,+ÌŽ/Îb%c'–AjfDò°§ÖÑ0XŠÅÏÈØeQ S [ ô‰"b áä|‚¹X( ¶\-s£Óˆñ§y^ë媘 väëxBÕ2 EvÉÂÍ@ ÿï{[Võ`¶¤ |îIIò?V¤qjÔ‹•‡¤Ýლ5UžB§5`¬r£*4Õ¥HjRyeŽÁm)–«kÍ­¢qîÃ^r7NUÑ ©Òʹ§C`aaê™è\ŒàÌòM?p3× $.ÍQv&Ú@ïM¯ÓBŽ64ÒJ¹ô‹çîÈãü¹zâœI+U•qé›ìŒŒ!oõ,SáøÞ\”eE4lñιékº™#08})ÅAܦºÓÒÓÊieKqLÉ], Ø'$×òÌô³ƒñÙPLöœþúîmÞ%™Ztg¾3‰ÝÃàFr0õ>« Blô·+ûÒ ì˜-“hM{óÁ`¨>Ýô/j×+€ ì‹h’åe´9«£vS$þÐ(Ï%ú^é •þ+΄äD'˜/„ÈBe<½ÜkÜ•Pí–w%bXªwM Ž ×k 3Ðç(¾ÉŽÌgóê€Úi¶UlJ1Ä:‹ø¬ÔÏ=`”i:­î1áëØB8’;E.¶{> Ú -Fž¬BRÆ}ÔÕ=+MRЛ®LÏõÍWXegs9Ð>LôûpAX­Óæ:äÅBô¦¥–¥6X·ñ©q€lZýbøÝê²Aâ~צ¾UñÚTɦ}6JÚΖ‘uϘråÒ‡Ð9.#áùžê)y;©ÙÞæ¼ßR0j‚Ÿ ÔÊF0ƒ3úÝH€%¢.-ßY©ô‚¼c«`‰E“(Ù+í Æà Ï»AN‡&>©„–›4ÄgÛÜ!PÈ~=®†y»é”Ñ'y‘‡XEÏÎØ>¬uQZá~ÈäG²øÜÅ‘Kõuá÷ÜßUêOŒH²ñê^§(Np®cÎñ/\;Ç¸Ò bëLhYé2b«Œ[l¹Ì¤ #Þ Í‹>Ãé(!lò¼L˜ÅŽä2Hì ¦P–Å̸[ö‘bïV˜ïšMo[¢ÒaþrE¨&Ê[>®Îæbâú‚\–ÊúZ§¾'ªK<<¯¶\+N9åÝ Önäøâ¥¾!e’I vï‹,[g$3.×q†…b½nMO“e:ÑÐ<îžü¦4ÛKb®ª‚Ð ^¸pÚBkÞƒ$VÜŒ3Ï‚ðÿã{ÍžÖl@tÄ"Ù(>·  ¥& ¯Q>±LH—Aôµ‹Þ­PšìŒÒè°Üßþžˆ¾ÍŒ BÆžîÚp|tñ(¢ànd€Ü¯–'‚{ É*ïŒH>B PÊvéRA Qo,l½k2ºo?d'øð²€cÆ4uª²2J@”B®YÍŸ¢ç*۵S,Ò¯ Êþ—éôã§”/)Áôv€í±}‰˜Ž’tûq! rwïv‹ãä˜ñZV(*ým mI¢çËüå‘6%Qþr±¿,£RÞg6¼‰¾k+’væîûIìâñ@OQ´Z†4›Å¦ž†êò€Hèä´ÐÚõŒ@fÆ`'o´jÑ1*X˜&+BL—ç’‡² ÍLÜ1„}rÞÄŽÛ2îöB&^|e¼¦ï]ê›!üh†5§"$rR7ï7©Öòës `eŒa; sRO6p¤: tÊOœ†D|’O½ªæÍ|±Öhðœ2¾ÕŽ_8oÊÄ©Ré,Ú*‚«³ç>AM#SFÕÆ®Ë”8›Ã,BÃÒñF+.Ú!öýñXÞŒ³Ep ÝróüžÅœ3Òbbz¥ÁýòÄË‘ TI‚Ó2àš2'" q/P¥ê /2G‡Ô§­ä¥ñ@eÚ€EÞ±ðÌ:¢˜KW ÑRª2‚ÑH¾ )S;c^áJ˜ÈPèä6ªJeFóLq‰öðOß(™ œrD-FLÈŠÂúȽë2RM¶¸SFú²ã¢3Ìvˆsf=ãwdîÀ¯ˆf­ÉR,„x mVÔt õÇ>%rÑ é,Р-ñŒ]¢…礮ÂÐf¬@êËlRcÌ‘9À MCðÂçñÊ͈¡jÔ;Uêg *GòáE¢ë)ì^¬åGDèbÍáéS‰4þŽ6‡ÄîØíÄòg NÏuXñnÒÈ'‡oBG Š÷ M,ðFjzUgþB¹!’SA-SPÉ #Xø¸õýQÕÂZ“î…c1i;@Õ]â*ì3ý<Ï´ë;)½Aðö•%\ãí‡ÀzA³etÏTICÕÅS‚Œ)Àû-„©¼É ¦«tÔ‘èQª„ÆïK0ŒO‰.­ï1š5ô¸ºŠÀ ³b8)ðø³ž¥‡ØòÍ*4úVv‰'ÔºÍUEE` …Fôâl² f¦nìæŽ„ÓÔ^ÊæoiìÊÆGÇWGm·SÔ³DLBìÖË8P]ƒŠôz!ñÿDâzÿ®Ê‡Õ[)RnH<©ÖGÆãj(dÆÅîÝ#è)ˆLq”%\õFvOÅÅ•î"±Kª¸rîf`Sšóð1j³HVVšBsD#phë¢7$6Ÿ9U@„e‹ò÷ *Э™Kô;;©Ø2TèAWDg°f¦ü ÌÙb b¶T¢QQ”\N|¹H,h«8vá\mÔAHÖܳûC²Æ"ô§!þªì+M51dî±3¢âµk >T//+ù0!FÓ…}wó>I‚awàü¯„hìØC÷¸ )¼(D±R¯fçq.œfÓŽS°é}7fvhQóéÆl+R(÷˜t·ÔqCŸeî]*1˃µˆÑŒ$ØÄý—*wÕ&Áõˆf-~r—L.®TKî·+#,¸©>"«jÑ üöÔïãWíËp²¢…k´Ë&„@W€â½]x¢/µ˜žncà“1[Æ+‚c’e]”uƒu@ ÀõMÔq†L2V&1gŠ@jÃ-kÑpYøqx´ae¶ƒ90š( kƉŒÄ"ž˜ÚÒÙsî{jd&Œ,ÉSÆ#ŽVš7s1ˆeZ±™†B+¼äè4­6§J—IÁ5X|G¸Ë)×p@$wž±­góGU5—y¤58п¢®xaæºlï8»¡Â7ŽŒ¸(N7fj*8ö%¤h‰$ûf*9ö‰'$Zv¤I' þq±ž!ŒbɓÞåQÚZbZqâðÏI£$<å £^@¼—ö›¥Dº4Д׉b嶸3£6”Cõ°B$|¡—–0÷TØl°Î¶C\Tˆ¾•ü˜"„¶£ú0jm\M|¬½]·ÃbÍjk¦5/–•Ÿæ7@JØQì$˜*ÎñŒœÕ3qZÂMž‚ù‰‚uäúdVØ4ÊQób “fX{ÑI¶z%v„Æ.ÿÃö[Ìœ^¯Ÿ…X¹–>B™?3Fù‚¯¢ÅM‰Ûï6ô ÚÓhÚv<¹ã%OÅdôhÈEœ½ó’Ž'[§§ÇÀ5Ó€ ØgÔ{ÜÝ·ñ«œñeÉDŒ‰RrPR*$°žÔŠÔ‚ÐzÎÉPBºËÃzP:¯€"Sïé37O¶Ø¢±LЪ‰1nºŒz&ŽÜuÅœíëŽã<Í„›Æk9ÎNòñÊb]Dï’r¬d{í Žªn¡nÙÓ9ÊÍH#, awóË*_%'$>èCó¬ëšÃ%ŒFÖ›1É<ª4Ö4™ NæÐñú®y{GÚ¤È ãWµ•§k¬!ãôßÙoÓ1±…YÈ‚*žpÇ$ì–"p¾%$ 1_89§Ø¬ñqþ>Y‰¾‹ãm1k ŠgB‡f;åÍ̘±:ÆîûÀ[CÏÛ7‘”÷¡ê%¨›ÓŠ ÄõunS¾¥÷ö*þ™Ç7kU©ƒ²®Œ^®}O`A¶éæ¥ö½ì´ ñum¤V™!Ù$îJäkÚ4Éj$nçY!ï›6n- àhúÍ–0ݼvCòAPð'®­iùà°rrYøuøÉ¯Q –øÃ}[õÌóèo•»‘ V«ÄžQ¯ò…ÖéÔ@´«aˆî7r¦VV ïvñà…]\cÌzÎQÛI\L‰ iýkÆï‰Ñ¸ýC+Ñ=Ùb¹aÍGD˜ êÕŠCîÛßtK]ÍMC™IÈvìÙ›­!öwHpÌc˜˜N ÷øƒA!ýý „ÁQ@(ú‹?c@  Bãì %Ž?%é ª1…Äâ€9”Î(~C_Ï™Ð.y}G¦q©Óæ5Í¡s8ð™+ˆÎ$1ª”RLT#º´â5!˜eðøôj¬û³B,Ϻ´Ú·‚N#иՎ)6œB.0¸X}…ÚaqëÄz%Ãa¯X›¼ç©Ô¤œM !œU£SŒ^ O†Æ¨5H}×(Ìä i¬¢­ ÍÌô6"£¡×chE+¢…@³zènÂe–Ï2)ˆÏ³M<Ê‘ÁA1/ýà q3ŸUi“mLj}Ý™`ÀQ¨F^™ë†Ü¢‘È×*½ˆÍ§ÑËËÿ瓱0 4¶)Rˆ¾ 6Ö¸8Ý ‰° &ËK2†º ̹Oõ?àh6ª’l›1¨úñ$¯s4Ǭ €™£¶ñ¢¨³Ðœ;0øDGûª†!°Û¢Ž»áÍKH¦AO PÔÈQ{f·¡±»d£ËJpKêZï"ÐYþ¾€è[˹Rf«R‰øÌê²=ÊÑò1*&)”ʬ9qŠ"ç0‰š‡ G±"¸©ÎËp´‚4´º`þ¿Šœ„£# ÃR¿¬è$ʧI´«&tP72Hì'ÉàåNîÒdø*I0º*Qk7KÆTª)_IðÜ$QD’„HHõ ö…6~Ïö FÖ:qX§û™-I1ë4†¥‡êfŽ0Ñ3X¦?q‚ms ɵ—uˆò}KXŒ#Hm•W6•c Ivth|C¬6qa.–ß%ÓÆ^0èJ3¤)òÔâŒ<Þ\ð‚PݸŽÊÛ_ýA¦u*0leóšûIÕ™5S]âPDÎü"Ó:¾´¾VÅ2À`"гWsc‹]3©²9}SG`ê5tAÕ,~‘jL5{²µËÐÐ:‰Da G±D-•EWM«o' KR²¬ÌÞ¹ŠcÇú9B§I N™K;‚Í{O€ ÷3¸63}[¦kJ¿[Ǹ†¡‰U3*„bËí¹ž/©ž K»x67ª£(¤š.'Ârˆ#ŒÍ\»kÚ½ãij;Ø!9KÄÚðz¢^GäδÕmŸˆôVÕ/jgJ’ð'Ú¿¾©‘…ùomU¼5ä,žæØ~dÒ,—”ÅÔ„«DŽVMÙ;(åK±ý”1D¡¹ú½"ýŽj milˆ»ƒRªM‰ÙcŽUʾðž˺P&©DrAÚ-G‹Ýr"ÒÒV*µjá$1ü’^‰(e&¦*Ú·›Á_]™8!âë jï¯=rA¸"^’©z3  Ü66¦PÊIÄ.Ê5Ú­(V?!»¬HtÕ“t.ùZ‚G¨À¯²Ž¢¬A#Ð ’˜–l ähíȦ%Ô°IXÁˆª]‰#`ïOLH$¡¬AŠ\dEæ@V°¾I¾OêP›µÖ€‘þ@1ò.dê av$`í¼éCPBHK8Ÿ—H†CM4ƒ;"|™Ô¼a†¢3¯²e!L†&Dâ&èDazÎ]#ñ„÷d~¤ÊÓ!«IZd cez€¡³¨ÄÄ–9è]Éõê£BI-Çû8€AªÐûÈÁ>Š$Íâ©"̪ÔI‘³R ÊŠn?ßÜÀIä5ÅÙL4JcäÇ´{/Ó*䊌qTÀè[ÁLô:É¥/:aˆ®U”6µ+aaFjÒ‹ý¨U‡Äf]ÄT=€üÖë/\«î°É-¯R–§4fœîp-²@éˆL´®ê¹KÛV+9¤µ ˆ%|œVqýÇÕ-êÁõ0YJ»ªS04µjˆMq§äƒ k± O± \Í+v$áˆ1V'Õ§Úýgµ¬£qq†Õœ®i^öXÞk»nk4¾”nv¨4’Œ-sSš6!³…9M 56¼à È­ç+mòâ—Q¹‘^C`÷º­×\QÿI|TRõ‚¿×p° JEAGѨŠvOÚ£Tuj6U Íù‚BÂ/8|g^D¦Ž“,¢¯ «^(᱈o͈½õîÕëA¦U•6ðÄdÓ2 ý3ž ³’ˆÓÒó¤ J„¢YþL–>G£Û7,ìÀA£0!ÍÙæ ,Š[†ÃÐôó—.Á9ý $Šç‡ÕjGeÙ?xsl¼¿0ÉO@KG•Þgñó8A#Fž°U5ª¼åééBóýY„Fu@IøE£M=¦1ôjj¢v”w>ëå\$Ý’kã:’Õº×ÉV7V€'õ˜â•Æž—‚ï+µ®¹%p›E4Œ4ý–g\…Y¤OKa è´ìžò Q°Ö¨1&nA U3·z.%Œô.zŽáWDfüx’ŒqÚÒ‰/~êÞB“·9©t÷j+Í¢[ØÞ_F,»2e»2 âQÝí {+fµš¾>§#s`Ö=êÐÆ¤fáìØ¸Ñ2§ìÉPATÕsíR—Pòα—‡F²ЋDs ÖJ3èä^f—”p³¹aƾÊû±”ç”Y´¿'~œìÃå(~êäqÏnð—\jz‘,MGs~Yg“fapÃchÿ2Ü:´³ðö>!Ûí¾¯™W‰Ö‡>XòCLozÀM9¹i‘=ÀÍÙZ! Ð>VIIž)—N_⦎DS¤XÆ“È-šÀrššÉŠ0*௒M*kÊ¢$C/jM& ‰”ø}Ÿ#»žÉ cþ®‘]•m¢‰í©Ò\·#ÿ=L¡<(ã/CúüZ¤<“{Aó1½‡É,šyÚ¢+¼jä¯êkúÆ2 ˜'¯Ñ‰<¢š¬£‘I§¦ c¡áƒ ã ЙÅò5£k 9ƃ°ûÔ»lxBü®Ø³#K^À£Š #ºR¦°z¨¤‹ÇÇÓGÉDÁ"ʉ CéS3ܧ°Z÷Ó§D9‚$JÛÁ¼ ëGÄÃ?óÁ¸ºÈ$Ú[4`–€Ô¦ùµ-Á>ËC¤Vࢠb#µ/“+Kb1Šž­#©±ÅÈK/8 ½Bz ¡ÃÄ •¤R:Yš‘¼"Ã3t<$9GA¨=ÛÆkÇ™Ø}.ËÌ»:ËôôÌÒŠbCšÔ¼Êêê»HØ¡=1°UK-ë(-Cq‹L~ âI.óÔRcTž!C§y"‹HŸV¨³:q:´µ°.F• °l€%2B,?“Ô£Ò;Ä3Ãä½4üÀU@(•@Ÿ3ðÊ4ÌÔD0¾ºÚ”,ªOÒ¥{i:È}Äs„²Sðrü’MLC Õ$»IÂñ¶óA*„°Ì«¿ËÊM?T÷O,„¡®«â<‘×d”—ü²R®¢c%;LMuÀ€ˆ³È¾šÒàXÜê»sÙ0QrH,ß0b+È+ˆ3I©Ç¼•ªL¾ZT|˜}¡½Î|eEHˆ¹‚7U4¼°”@‘<*|ܬ ã {ÕBÅÜ·Ÿ2½”]E•í—U!Î=9qH*­.ƒ‹PC‡áô  …·˜ƒ»€©¹¼œ‡ÈŽ ñ/€`…×Ïú ¶:‚´TãSêç[™6‰”¼ÐªÁ•Ýqµ½Í>´ ›ÔI”¥¼°´T¦RT®•¶×…é:š–¼bT-~Ò$8ÆòÞVäÂÏÃ¥ ¢x¶šÎ ÎŒBÝÊ Þ3ï] ‚©tL$R>¥zŒÑiZDQµôÙ’ÌËüŒ:âã ©Àؽcë&Ø‚9Ì{KÂW…Ì€ªX³nK¢¯[YÕ#JV*CÜâm[ø8™2Ò3H»¦K©E5 gJ®½ó^VZz×U•ˆ¢ Yš ×s€,W<*Ô@šî Vݤ‡âl¬[¢ó,[ ¯¬å¸±=Ň–Qz4Kܪ5Å5/2+³eV.•È`LX•ru¶BpWJT›ÒôCáê  ¡â‘Ö Ms¾ý{lÝÁ9oVÞ(â¡ ›á 5-Å&Kh‰ÃÓ|]Víx  ô`R•©.mVPd"¹É.­_^(‘ÊÉ ³ã ×S«cD¢Mcm¥¦*|JKÚF³BÚŒ9,Æ:ïQ]AŠ•mŒÙ¼N8á<]RÍ ]Ù­K²ü‘ìFˆ5Q€~¸MÄ“#t¤ÒÙd$Ò0]ñ Œaåu\¸($vÙ%ø¡–u—Å+Ã+Î-ÝÜ Ö*v’c®=Ž®žbÊFÁåyU WuR¥=d½ý[8©’S‰*ÊJÈ~–‘ LŽ :¨›ÂR }>S@,íÁßK@’JŒ>nK¶­‘&jRýŸZRùC *Ôu4 ,£ßŒé?Û3-¦ùZLÓâÕ%ó4 ΢# -iÝÝ%®ô§bÃkµvWØÉkÄöŽOôiæ-Iþ=´ÁÝÜ%ROqT”¢¬Zšž²TæJŽ.j!Ê Ú¨áÜUVUÅgÛ"Ø«^#DzÌ8ÎUÖëܳsJ ‰ÈL†è»bµ-²æy®­yQÙõÒÔÆ¶“ûâÒJ6*ÁW1V]\©+ ŒÐÃ6m>|6™¨:襦V‡Õ„ˆÜäj®p€6™Ú“g˜å«UÖ#˜Ztn£‡Ã3“:%Õ åãø!#GÚûZô8ˆÑÜŠ]O´’"ûlÝÁ¶ÉeÖb;tn¸j¾ ì9‹ÒüĽâ½|ê¨ß‘Qá(>¤ä[^C¹’À"‚L•@Q­Mƒ†¿bØ øŽÁâωgÕ£:;¶EÉ…Ä–vwCìÞeÈb†@jÉ-cKÎÈ Œ9µ®ù16¤8JCÐíòC;%Õ&:¨å"Xä¼|;mèyÆÕ*v³dÐi.4x<ž½©»TebHsHŒ4ÅईFvÿ—Â};¶™/yPëî *(Âèа¡•Š#§Ç¯´:€6ÞŒM©s« ¢Ù/ÈŸ3±M©» ÉÃífËŽ"÷ë$5°SsÈnßJ¡9ål¢Ñ­,GkdÔÀýå(Š\¿/,lZÐVhÅ™ÂøªòœÊön#«’­i•/‘…JòÜpH’¢‹g±ô –É¿6ÕÚÃ¥BÒy`šû# â¿ïæÖè,ÍEiŠ=FÜJ%˜¸ç>ÝÝ”†×éu/˜4Iž´dd DspSƒR03H²ò’/–wGÕLGTdö›`q¸ž‚‰Äb9dñöLuµ– .?𔂦üªÍ\œ‹ï Öè]Äåà˜å? „*€Žgì¶V´+4¤ÓämþW:˜ì¬îÇ×TÏ1ZG#Ka¼c rR¶ÃÙ![µæNou«ßåÜë‡å«nw xuªó'“ýàsug‰éY¨5Â!ò[Xl\x³]B"Õ…ío†;ÍQÞ?ÇÕ¼ •P0i”ÅÍûéGVªöŠú`¢‰î©TÀ÷”rê$¬DHDbk];ÄRZßjNk¡¼£¸o ¬ûÓ&õÖc²L³_ä˶â•úZiWa€ôdÜÓénœG¸Vð¢^…áyØÄ¯Ê¿ µhðÊÊb³U£N%#|„Tê/æ¨ØW‘'.%³cœ«z‘Ls@gQ Â6ÚnTLË«­¯íWn É-JÍeK¤ÖEÌ}J>µFHØà¤ÝæãâŽp­ð:G’ÞëÚÁódŸ63,~EÒ`íâ™j9i×_hËŽ‡üIÂANƒþâZïT2X(޾²Á™¯cxt öt…½ê &ýçË ¶Øvô(öšQþ´ ØÄç{·7ì\*çý€÷/ÃÐQ1Km—;VLŸ¿à„¢‰,Ú!ÿðÚ‰“[ô½~ÖÚ;ˆýþ‚? À(D þ†?!Àȃö$ùŠC0¨°5…BQGÌ É_rp$¦-'}¡@i„ºA¦ÓxÐE‘B¡ÏÈôæE6žÀ¥ Idæ$ýœÑ ”wÕF–M¨ó™x [–VÀµiM K¥ÑéuI<”™ÃaÒ+d. ¸C$W{ÅÆé‹]bÀ´+¯H¥©Í Â'ñéæ-ýQðPkíò6Ÿå!Tyµz¢ú¥Ú¥mDÒm‹Ìµ×‰²ÿ ÑTgö¨´Ú3NbÔ{ö—,ÝΠ”¨–wàf°;#öŠÿœä@j]û‹9ŸÙá(•6 0n¡’µ{]‹Rö¯­tÛ­GÜã6°Æ—ƒó«Ïbá¤ìJ4§.íPŒ.È#.ɯ Ø‹4i²rò!JZ⟴o",ò(ðÒ¢µ@ÉÊXë"ÎPÅ6/ìV‘2È(4i¼›$¤-Nê$×<3Z­Úlò'íógIHîç5òkg ºiü^—A«W@̓2'ïä ¬#¬ ·ˆ¤ ÉÌ äªôØ×IÃ9¾éËF¯%Šº5*%/ä£.¬Iº<Ž¡Â%¡ËR²„4 ½ ƒ²J? ÐÚ`î!Ê\CRrÌ¢Î!ÓÚŽ”§ðä“;Dèr<µS“‘ÿ ./•>ï²U ÑÏ€ÃAÁR“œ¿B’¢Ï¥/üõÖ˼ô«m»FŠÝéɰп1èCÕ Òzï ÑD¢×Kµíƒ'UVÊ]S¶ô9 ñzW¼.‰LÀmzŸN|¬’Dœ«Èµ`ìÝÇM¢U@v˜ ¿EU|丶D‚¨X´¨{äRç‚£J^9D)ˆÕª§¬(#³ XÄ¿0¨"Y4±5òe '*èµýCo¦Z*nÊ:uý?–€ó¢~¼‘T AI³ôÈÇTp5Oj±Í %” ò4hVoÝŽ…OÙ@—SðD»•SG⽨«JÚ—#!Ë‹ê=Ïߥ G)w¸ý¼i‚Y @4JS”9‰Kˆ†*¯²ïw O'$ê•qªhÉuqyæœ%Sp9ö»;\ÔD„qÖKY‹eˆ$y7«}ût+Õá•3Ì%©˜"NÓfÊoÇç`©9=õe½¾[ñÛÓég?‘ºT†:Ét¿#Éú@›`OCTªBO@všúÿŽZd¹ÿ?»Óë! 6"N—É>!ÍÜ‘=ÒDw•ÉQ[¥È¹µâtÓ å OÃBVü\xUcñ‰1Fjd’‹î‡ñ‚%IJÛ`þMÇÉ2có Ô¢r ­ gBk‘T&}$*¦æ8—Ô‚»t'Y?DðT[»iXÀð×ò¨É”'ía”¹Ã¦‚ÛÙ"dQ©%kÛZ°‚ȱ %dëc#:(¡î’ÄvÖÇÚè:æb2Ô„ û v­À‰BS$¹ ™ft‘—€,ÊXÝ‘Ä)éÈÄzºÀ 0Yvâ@Z–B¤Š(~”sÈÓé·$¦ÁFFbÓÔ›NWð1°«N„ ¡G=íbX5¢€–d3C“7Ôašà~é¯õ‡KÂf¹ŒDö8 ä$•]RÈ%٦̒Ôx‚$žE³÷ÂsÝÀÿ[pÕJ"`Â%Q}h¼½…°IüJ­!½€T@>•Û"ëͺhö¶›ü™! vE»9ÈKÉ„±`OÒK5e¯%Ò³ ^*â? Õ¬~|bp(NDIõè½H±Š<â¶ïK‰^_Çý ÎTbãI®w°Éî8„ꩊ¿†RÒPM§v¼•2¬¦$°ò>²³^›ÄzbÔ=ª£ëA©ÆlL¢–רQÔÔQøÄ!E!§Óqa39åW \‡Äz=JsœðY.§àS2hæsK^lÅÄ?ªÐÿ=æ @öÎÈíuœð=X€ž§Ñ©¦±ÿ‘²Ý$ ›gÞ™¤5ßO*$2½¢JÜj4ja£ñƒ<š&àl<¦-ݺQhdlÅ€¯È°ÊH#þ+¥n'Ò  Ô^ìD­éeOSúÔtª Ìs¨‘:ùb]ý1?’Yk×…–íÐE? ˆ~4¤›‘}!Ô0KtJe‰°h‹²HÊ»ê^G¦5H’š9ó [Tn,•a1É ?ó´éF (6Òó'%å—÷¡úDòÔhÉ` ÃÐl}Õ†Ç7Up*&†î€%£kli2&ªAOGiW‹m#€€ªÂºÜ-2ð|4p3žû<€ ÇÒ|g9ëÝDVü±êA‰j‰ÝpZ—òC¹·¿ Íäq9 ‘Ň~o×—QÌ«Wi Ñ”¹ßg±È׎µÔ5pêËþ¢Gñ_ËÚÛ¨%Å÷>äÇÈC©AjŸÐ½:YQû«šY“DUÚZ2ŽZ‡®•$„•bI&ÆHfŒ•€ Ì¿[Ý.êé’²è²;-tKœ Í­åÖMiæðÚþŽD–˜jPK,YÔMCúxêÜ›s•ýƒ‹"…2R ‰2·é»7ë¬bB™ø(õP{2R¾Ïäicèã%âRŽ)Ó‹¸-ÞŒxÆ’jžYZªQ¶&uʸ˜¥/9“kd³9ߌºæÀðÈeqãc„z^Vñ‚E«¦°b¼Qô¨õÓ×Yä pýkÆÁê]j¸Ïu–r¯½sH!sÔÉIFb†*d¨¶ÚéHÍ«Š¸ÖáŠô&›àìGû·²)Ú¬Qnë‘ʸÔêF혛3 ç"þÇS|}Ì3$¼çónæôÎçH³Ëw a7µ œÎ•-Ù ŽØ<‹î»“%‘ ô£šäÚ¡Ñè›*Éö‡=ÝÙhâ@×<`¿ìNo ðaÞSŽ×÷&?pÙQ)owzj83»üÒòl’·x{7 ,‰:sG›ï[;Ö!7ˆ—«"q?ˆšùq£{²@´’VU`ÙT#¢l t=Ã*ì’(}ü èáJï 3¢þöõo¢BÚëWá6Þ:5bùµžy”™ËK€]’£ç¯ñ\2 Áúã9CK¨!óóù¥f°ªìxGG½‡L?£On&¬Ûbíçlõo¨2L$CÈr"${¯âÔŠ5…švRÕéæWíVûnâEˆœìˆ¾îSËÌ>ãŠj+Ä×KX³„Wg«îÊ*(²DH$ë$ÏcŠÂ0×O”º +Ê”uC¢Ëp^Po"%Çôœ‹œ«‚,íEJLp ¸pcxðЦ.ΰp‹‚ aúÏî´‘B$È$$€Wïô ßpRùáþ“Ïpާ¬†‚ª§ ÞD¤Ê¢l z’Žøùo¸›Æœi©@ÜèÖNÄþƒ¬Ež¬.ðÆ£gKÔ.ðÉ.n#Ī$ÂAæ@EKrÀÌþÔ*2 ˆ®bƒ¦ÖàŸÐ ärpl '"Ô+ͰßÁø¤ÇnËgˆÕ ¼ŒD†Sìhþ·éV«ŒLC(&ÃLÑOF.ñžaé ®ÔvÙ¨ .*òö…ù©t«ŽÎ™åàDF„’,þ°¢Ôî(Žæj‰%êlÏÆ¼ñ¶×BâO(rRt¢J6¶k¬ÓÐPp0þl‡ ˜®`ù)¸×+È篈dÐ禜6à ¾–$L!±E\õkØR ÂÔf{¥ü¶ ðhZL&†KöÉgO$ð`q²~ËTâl˜ðÎ4¬ü—PÎQMHZðdqˆ#Qj© É#Á§(ÐÒ$Nl›ªRÓlmI¸¥¢ËgÚwˆèƒ$ Ø&ú¡±ZXn·i¯$…¸+ÑìÍz¡ôÚ Ìæì¼—í–$èìíª¨éÅj†¥Z÷F„¦ðp¼.šô¨rœÍÓ×MC²¼£ï,žEæ¾é€åËЃ+ {©ŽÁj¸ËkS-Ç.‘ê¹nv½º?†%ÒXM͸µâªÉ(i¢2(>ðܹ"%1 *ÉæèëI *°œìx½®¨:Ëô¦#§'‘Ræ'8—«”SÉÔ3T' %K+ 6-X@ÊPH¢`kO¥"¸à ®‡>& î±R‰%!.ΖAªP¡ ä¦gîÍv€hT%æLb–û)LðÚîP¾—ɰ£«ãœ“Іj):$írÉ3vêó¶Â@þ`⢖Ô/Îz\ÞÉOŽ!M±ÎÁÍ£?F>‚ œR3e!þädÁrèë+VÓb~ÓÏäêBp"°"ˆè°Á- ÷BrÅ0q=d‚t*v^m˜É#Lqc bO¬”"R!S̸OkDÅö«”„À¬Ê(Æ…"}Fõ6ŠVކ8\Ât0Ò-BÚprÖ ºlþ÷жƒ%æ_м÷̘þì”üIùJ†@ÁK§Í´­~bDƲJÎE5õh 2¼˜óæL1Ê$®~¶ˆ:ÓÂB$°gž8³ÍH¢ýê-=4 Ëx–oRþR(Òc‡n=ä‡IëÑ$,“HzÊ ¤Á ήÎèÄHæ“Ì5_‘²g‰±:hñ‹(%£XøO2eüÃÀœîù*tè´•b¾“øjÜÝuQî{)ÂŽ©M$)¹DJ,{«•áî„ÌxÐäÏQ:‚ ”J¯²$NºRu*& öãê,@ !Oœq ŽƒóçÑ"ê¥ë4•zgHέ4ÌÖDP«’¢ÔË8\#LGƒ`°¥<‰Ì\YmªÓê°$¦åÓ2IŒ*NÖW@ïmavgÒ(ÖPüÑ5¦´“2þ†u$šeD)ÆA«B…œÝ±JæD£;Ëã%1OõäºÌqƒ£.IÌ!Í‚—¶p<–ËIÉMN¾Æ\ꆢçM…iS1Æ¥µ—óævïΚñ ðjgKsl$ê%0í: °–®ÖWl§g×ALB#Eü²E÷ ”¦ûKœäÎ!BñßL©‰ àIœ¢Jl!ÄÀRq ‚nWRŒRxõÕ øì“p<,å\âþ©Ç"p³-4MžÆ’¿˜ÝsTçt=ϳYò^2 dUó‚s˜ºd á°«ùÆà ˜ÇÝ'*f“Ðnö‚vDÙ „{Xr?ÀÖz¼EqÿHrÀêæm÷*†TÆ0¶:g@"Iü·²©™©dQ(J)bC"¢ ÖχÕôŸ'€åŽ@o'ŒÊe=R¼Ï䀜õâ"YÕt0Ö²RGŒ2xd•G­…AEç1pr‹ÆVxL&_'¬ã‚•Ü,h¼T;qúFÀÅ~Àcd8%{5™Éè€îˆÂ…÷¹™)LGB}eüC¶„…ØZä†nåwùêPøIš%á¾ûŒuF"˜—kî’ö¼z²Lw¯—mAAfùšný¨0…¨>ŒÑ}Y¥ßì”ÎñK +v8LTÄœ¬÷ºñÙ„0e öyŽûJ¼’/b4°keÉ$ãÍ‘5»I£XÛãœcš±dF1¤Eãr&–‹ŸŠížVÖçž:r>^¨<&6åÊPa#a;Y~ß^ï%ˆÎ«òÙošÚ9+[´è?¾ Pd %1IûNEjw¬F™%“›z©[Ê+bq‘é ?W|HŸWN›Ù÷ËN¨¾ þí%êìsŒ@ƒô­Ì‰=ÅØ­‰@Ôô'L7¤/ÂLwZ†¬r™º@p&0oB¢GNÆb°®Ewºfu6‚ }4œw@1¼–'Bìf0{¦A°Îø]MÈ{í7_¨˜¨|¾ʦª…ç'›À13_ ¸ ¯ÎþJ빇MdeW?:¤añ 3*Üwzq C–´6yÝ£<#<ùשµ{ ðËÍ–›ÁLiŽ…»\*„ÆïdCŠÉ+$cØoÞ@/ì ù[Ñì÷*»oD̶HbDÍm€+yËôWT»±Ìtb-{4‘^}n*}~¯Ë$¡; ŽÔa³4 À°^ÇÚö0†ÿ ~Ü#ÑÉ~ºx3ÕþdC(ÌFYÞæP‚PB^ ÿÍ®±BýŒú统K¨Ë ›Ž'Ÿ`V¨PGBK[¹t2ü†™{¤[¹©åJû§›¼NÕÌ›Âsæb–TgA©ðÒÓ2‡šzaŒL ÒwÓÕO'¿úuÏ¥?éo¼ë'Á :ԉ¯¦5›§MÍ%\ˆ¨l)žÂE›Ÿ¸GzùÎ]J¤€Ž¢|ÛÇ™sÊ]¿1SSIbY–/ÏŽHlçšs—Í|Ð ‡õ»m)°_u5Çp4¯QK6´Éœï"et]O_Ò¹aÕ@–ŽÚ—¾Sér ÃÃ{:à7‚xŠ© ¾«š%‡×Ë¢ a‚}iŽ:b? P ƒ€PÐ$=󆀡 8\*þc‘§óö@‘G¤@g´žK Êå¹tr`‰Ë"p¸ô ,Lå’¸\V\û˜M`òÈ\Na*•Ǧð8$áõQž?âqè]Vë’Xõ]–Ad´Hd6mLR§±ê5\0‡'É„öñl Ì"´;EÃiPkq9ÄÂ=[–q–§ôÒ:µ_¢™ŒrǾÇcX*Ü/)0‚Ðb·;xí¤G!uºLV¼?îóê-ça ÒBe’Z‹èÁÄÈ3`zæóåN"±:Ý4 «AÀýZÔ‚=¯oï­»ÿËì¶×Å/;âŽFcYû†ÏA—À{¼Ó¯OnÜ}v5\›Îð=O#i((›ŠÅ%oºߣJ¼"'Ê`à j@ø€-ûŽô¬àf‰ªnk"•®p’¶Ãµ‹„ †Â«Ú8ßÄ-Ò\¹¿Çò§H*¶¹¢°Ë´®$ ¢‚¹ÇˆzX­Ç˃¦Ô%oêÚŸî|; Ÿ¨Zp³<2Њ ®¨î5Hk~¹¿P#ì„ÅûÐ"ª‚¢–,KÄÞ}"°<"­ûO>%h+¤‰¶‚ ©ÃÈD2D0¸; w!2íØÊ#ЩïLI@²ÎM°]ï³'äÍN8È;L•¾‘ÊÌÄ#Mœ£>À2â,!©9ìä!ô2Ñ £(Ê0Ì2ا ‚‚ÏTl‚ب‚¶.n”;¡³3)*ÓMMLúÉ‘Ë Zgô »Û/. –¼TþJ ½›w0p­ËêÙñ|YN¹ú–7òü^™/ê»$XË Ò—.¯,m‚(2û‹|ýz~'ðzFL0Í3=‘½âƒ;ïv+aB]PëO ǨN8µ-Œc Ÿ¶ .ÇKù¬™`=yzLø°ß§ Ç+;뜢¹ÚþŒª2þcRÔ]„ MêêÙ zb^(ºØÑy´ÄL¨Ô‰#¥müFLÙî“Ó­s/, ø $¸ô§OiÆ"í0Aÿxn·–TP0 IÊ&×'‚!r*Ao¤L4¨ì é$²ÐÎU•¡òÒ'"(*`²ÚÏlƒDÓNÓgR¿cá[|*áMb* qËìé}v[lM‘® 6ïìgçm’÷¸\dÙÛt* ”$Dâ>/‹VŸÈ-GKîr@ ¤¸ŒsåÁœî”¹õH;è ÙHZ‚¯¡/¡¿¤*¶üÀ8 ¯+Â8VÐ’ÉO°’¹TÜÞiwå] ’ÂpãÈ›N/äÔXÛ VMlAÆÀAÒaÚSM=†ÊGäR$Åy¦B—ß9+…ñœS~ôSn$i’æ†Ù‹›5xª¼Ž:ò8ùì],Uû¹¨Z}Kœ<Ž…z.aüe™Sq0ƒÀƒ4ÿ”b0F¨>g‚Àf@ïÈ}@’ £Ù<¦Óž7àw㊊omÆi #@ÙAhp¦5ȼËcÐ*k­ºAy:â9‡zGפ©Z[‘ À#’Jr‡™s€Œ…¶óxŸžáV  [¡S´G¤±¹HI ¥÷ Í‹­.éYBYÏ¢_BM-´I•ÎâÔ,Ò}ÚÆé¦Yœ:˜ÃËæ¾añ0J”ÊLWØKŠÚfhÉ¢&Û"¥"n$³2ÄçûJ¦…´HE⸿P Üœ4ªÚ_²›ž¯ÅJÅoAÞœµ'§ÌDù€iUÓÛd‹qXœCè üˆçŒè%^»&DøIÄ:ŸÄ*ø§;^(Úy-ÊÝšji“,3ß-‡ä!tòjTЂ#%%ÄM ( PUÛÌÔh¹TiDÈÔY,ÏÆùš?©jL¥ªÞ´GL†kE“Ä@ˆÍAZÀût“ú©ºC´vœ=]@ñ©6=5ØlpkâµXvb¨]Hƒ3 ˜'B—Ó2¿ ä”’ÀøÚÑ WdåT¹‚1ŠºŽ²ŽVCY•"ÕÖT¶j|ˆ;:°|¨ÚeÉZR³ÖtGi¤Lºx––ø¼G˜îF§Bý€Ìš––BDÿ+û?¤åF–ÇôØ©aÀý4dºË¡•Œh•&|°ŽðÇAùåfµ#á¸7"‚ï´e¯QVqØ ô¢XûŽÑYq»‰T€ý¿ñfψµY¢Ê¹¢ôăÞ}{bC¨'µì+JöÕ—)2!R;­^eò¥íQÚÑLç¶]‰1}ȨÀ¨Âñ‹÷Ç Þ©“teÆÊ˜-V OuÉrÛi«ÌEO±Šå̬ñ¨•DÌŽ¡Ö|â5 ,£‰„…eã ÏW¨gyÕ¨ïI£#£•½—¦–´ãë ²eA™Tú–ÇÞ(”Ëy'–WÂ×0)A#N% :É¢ìŠeh¿•ûR€¼u^“&I•aÏÜVçÐ Ø MgÜjBæp©(›48KN5Ô ª(è‚(&Ðs™ånú!‹u“5Òè ÝVŒ¤í”ÈmÒyÕ»'ã€eÙzpÜs/^Ow‰mD½#铊ÂËlz¦¢'M£ZT[ÚïS™®éÅ™I’Ü÷cÐT"¿¼àD*žŠ’2|§@zr<—1Âö§vH|›è oXÀþ}èÊPå˹œ²-Ò¬®"[±µâÜ eÎÅ]ŽuŸóÜ‹ÓXø’¥¶ìoÈú©Dh³0ÂVš”K¸)™ÇCž¯ô¤CÊÃh£e½È2Š®åN1$ÉlàbÜÝ,­ØZ‚ßT9tÆŸ1ïyîæ|ÖvyÅ3÷³bûyFÄ'4ºÔ˜W Wh}F-ìiñéb-Oh°MX AP ÞPèßVˆ~LvåâM6híÀ-UL©é™íßg!ßZê\Ö ©c8ÄÕ­yo*Jú›¬ýçк¾ÜÍsÚ Í8[jŠç]ƒ°Y b1°~8öàPyp`´‡•»ÒÜø û{ùq5í Å2‚Ü0Xë ²fÍmˆÓB¾³¢x)}1 cë qÄ–“¬pòŽ€ßŸq|%Êò j7Œ§)¨ê¢¡º).©nƒé¤7 j1ÁÜ>¾JÓµü걦8‚%€ û š‰ˆãr‘ y¦è†—#÷òì· ˆ·j׫A€4kO"K 43@µ“¯c:8ÉÀŸ+ú9°»( ߀t+°05n%l"±Òø:ƒ0ê-—ä(£š€¨Ó¹@~Ž‚Yš“D'¨Ù˜’†¼;® ñ# Â2*+B<7Ñ&/Kw2sÞ˜*Ù³xzÅà…‰K-¦“¦ñA4 ÁQ4@,2ެ'ˆ9=‰\6ºh‘0‡š :&’>š œò+ìŠp~#°,jT ™QP9¢/Ò>´b¾œJ›Ä”{¥Ìp.†7¡n;J‰>™é)ô£¨Æ[7–T,Á³TžÙØF¡%¢Tf‘€¨šÈ¢§žÀò’¬6²š×¨²RÄ ÃCã©YLŸ°ê´¿¶°ÓÏ1˜‰>{.;Ù5&’›D±Ã€&¡²¤ é¯YxŒqÒ7œD³CÓ·¬( èD[]É*ž20»&„[ú­²šµ«èŠöË &+˜Æ'Šq° ¾<7Rü¼t›Y5!/˜‰y™ ¸)3B¹Â˜5™ŠÛÂ&Ê@.c|£Cå$›Ç·çª9g* ‰[Јሉ*1(ÓÄaãÊ~Ò=²Ë ´¤²©Å c]"Ì/ÅDЙY6 ¡MI:»½‚·Ì’ÊDKºËÀœÙ¬ˆI²:×”D½±X¸D(¼º¤IH~‰,¸Â̘±øœ@×°‰R¾ûÄ6ÛWÔ_€ç“8ŠÅàz–PíŒi€2ÿ<Œ‡Ì ºJ‚Å,ÁG*»N³›ž±3ª9:)i‚;t?Û7ÜÁJÑ3ÍŠ§$á‹3ÿbÿ·9‘7¼T¹Ð~/a(«€}— Á¼-Fx¨ $ê£ÄJÿˆô¶ t#)€F:Lp‘PyòͲuNcÈGÊÓ:¤ÏŸ)Ó@ªÒ¯sR<˜>³é8z~,ÿ«h„˜‰<Ñ)DkßšB>°…¬S‹²ôÀ¦¥ÑüZσ> zÐÀ€ðÂèú©2BŒ : SÍzÜÈkZ"}²ä,Ð{íÑe‹ø±©?Œa[¦‘¾ŠÌ5;ÚU¨‘ü“à  "zD…14 J2âí6䶇ۅѣ¹Ì“<1Y@Cú©|‹ š–Ù&Nm4hùeaƘlU1IÅð‘Ô%®äOÌþ™4Û²¢4wGÍDÁ; ½B}MÛ}IÜ}Æì¢•“ ºÀL“qœSùL¶MÈú18ŠÎõ!Éò¸:q3}kÓ$É£²rŸ+™¯üqÒT€5ÑyǺYN¦@¹ËŒ5iE6Âü:’‡•{¸[Ÿ“b–#73Tzñ:*©|1xH •( •iSÇ*ðÊTHǶŒ„P‘$Z(Ê„2Ú¯!¨5”ìJ¬e+3'1x—!š—ÜÜÆÈ’ ™ ¿±ÀÕÃ-*ÝÁ­Ðò“51ÒÿÐyM8ð}F$ ¾ ¦L}j´ÒK£zŠ’;. ©ÅjíK,­òK“ÙGô¨éN˜$2L&¤Õ(/$¾ÇÔoA:³*òºÖëÜ%d(xকN9|ÛB€¾ô(ÂÙÍ’©“|g&¡¸%=P ¨‚ÕX†² €%˜C”ÁœT ²SYš³òt* wÂFVÚ|ËK/+¨ÇIÕÄÓ1Ã+Íï—Á:œŸ TZ"ÊN5UGh]š5¾=FÁD# ›7 í!•šÚ:µKkžÊö0»JÂ2\#Ò݃YœÚFT6Æ43@Í· ):¯ÁI¤©íÁ* ­1¹Î àBÚ “5¤‡í–ũކÃ1XÆ%¼Zø˜©4°€K~ÉX–R\Ï–QIÓ†”‚Á¤y5ÜeIÂ1<èú]U]5#µˆ¸t¼—dœ[Q³s¡²äœOÝm‰)I·µÔX—ôïÀ¾”qÀÍ\\‘e%sŠŠ ÓÃW*Ý­“[ÁÌ’‘B’¾Êð1ªµ#7‘3ÙmV -Þl3²éQÛüÜE°áI£Èø™ÛçB) ™DÕEl?<Øø‘S€¹‰°¾Å3"ÀÛª«Ž´Ò»ÆäÁ=Ó·á Öbæ^EZ­…+ âäÙ͈ò«CÛ>9(µ¨Ÿ*ilâ¹™¹ØÇNpˆŒXÆ1:–ÉÀL«',…ÒŠ ‰[¸BÌ)à±½%Ú€6;ÉëÜ< ªû2&JbL‚]è¶[Š J+ÿ £hLüÛ`@«a,üØN6€õ¨¨×S6¥5›Ö’EC1AZ-#… Þã/[˜h*Ñè¢iGQe•õC"©¬Z2+UH '„—B¤·]œTÄܿ튿u°‰I¹˜³)bqÜ+ÉÊâ¥%æ ¼ Ëá­¬\£¿LýužŒ3g±ð(µ&rœ}ÐC2Üü4í(¿ø×œ”f^‚Û=îM¥Ã3ß"lk´æIxâER#¸”zÅs.Ö²2: J[¹²j– 3~–Y*è`TyÊ“™¿#®ƒx“QÀTí£æ>\ÁNÁ:ÝŠ!»·Ö6=@þ ½ý ‰ÈÄÉ´Zv½¢ ·É‚\2å!Îå:…æ5á«cö]P&â®eŒ±ü‚šDò*°4Å_1ÎÚ-jÇ}ÉPq=qÖya$—ÝÏÍvˆ{ˆS* {3­~{³…Ê¡yï„(ÜóÚ$äÁ?óÌÈ„?ãôÞЈæf¯º1ž4æD[É:vR) “«S–i8ŠàhƒW‹Æè i`Zì)Š_VCo<íŸy“¤DÉ>9™¤)6°ðß©®Û¿õë²üÜŠ ‘ɤJA—^±ƒ'+É[ô> ?`.v">$éLÑ'æ"RaƒY¾êÈ%ó¤u;C4áå燵ĭí' ˆÃÖŠŠˆ&&J¶Wêüö›‡í¶.¼­ê,š7ÚOXú¶[À\³;ⶸ n'žíg]ÑL-Ãîôzdß?FQ-c[oØÚ×îW5gì¹íxâ=ú0‡ ?:ÏvûŽçfÊœU@"ÿ³Oô_1µ‡BŠàŠ›^CQŸ«ÄClKo¶Ç.…Ó‹„Y­yR£ä–C[hˆö[†´¥(••ޱ×AÈ%6\èŽ=Ts¸À”ÓIîû8³Îªõc ŽcÊ2s¾t Ï g. […ð¡Ë*r„9ʪ\"5×]öD•ºeCk{/Ù¤ípaš¯b#ËÙ9ÚdQÉ64¦H‡Ì,¾6¿Ü?„žúôÀX|+F¯t ùFT;$@ÑéN×ÑY+SHO7ƒØZœq:Gd´Þ]ýîêºÀÍš$ >ØMȶ+riëU‹ïFçùÄ!€@aå`Äѳ[ÛÛ´Ýøò–ˆwîXœ:ߊé%çóL÷ªæê´@¢ôâÍ”ޫ袓0ûf¸ØÞ|=tu3]W1´þ¦Ö ¹™[’‹™±=(;ß’V^XA4ôf8®/gtÝ,Ÿü‘U’× QqgæîÔ3w |iu ¾€©~ÐÖÃìX#ˆÕõ\6öwíÃú¯"€‡É–Çê~%*Þ…ÐÿD& •/ÊG¢¹,lIè&ü(û„}}Ë"æÃžÉ+MZ1RqßzjÓˆAuØ€ P7ì ~B@P·Ü4 Ä_Ñ7üV¾cPp(=¾¤R«þ<B_9<û*Ìbòé<'7Id êO$’Åd8–û’ÀçqÔFO8‰Àå@ФÞ]§ÄáàH½JU K«tX¬ÞÉ&@ë°(äió[£ÕzËúÕ “Ée@kåæ+g’Íí` uîùW…Ø¡ô¨Œª[­Édôz V9¨À¤ñyL*‘Êߟò©Þb{êkw'¶·/K¦ú,”{*ÿ–G°Wˆõð '­ë^ÒéoEa‚Íé9­ÔNO0˜Ë¦‘ìÚ'ƒÛí@3~,>/Žæ¿¢õh.Ò-Þt”Í€µ'ºõ¼PÈot 'žÏâ4N`¦»«D¨>oDô!mÊP§6ȪŽñ¹Ðiþ‹»/kà´ Mš>ˆ¸ˆŠ.|D â–®“´ä®ž mzƒ3*ŽÅˆãÈ—¬ôD@JÙB0’ˆ¬:¥ÎXÓ·Éqç'R‹&†´Irä•AJñøÿ«p@¡häX4ª„cB«nãØ Â Â@Ž:H)«;´ç¬ôŽ$™öþô€»C(š—<òü© P骒ÄÄè‚Ê RTÿ§²)þŽ4K:ÎÍÁ 5ö¬t*rÊÔJ%A/#3R{¢ñµ 9,ʉ¬õKBôü/˯Lã"!i^ž´õJ/R°ˆ*€Æh-–ˆ"+r@£Ðól‚ÛÎ)›Ê(à]ÅTÄ  ¶ž¿éã#Æ2 @4è%ÞþÍ(½^ß-Öc”Š´òÃø¡ IPÒ/”“~&5ÙÿßkD¾Róå6!õ‘ýIŸ«Ò`€IºŽÓÈésäÆsKo@4TÖ<†Ç±Pÿ¨ñjyc(«@̧ò\Óß.ò¯¡)»}MQÊ$Àô#(Ô½d¢iêKmP€C±RÄέô4íÖØm*žßÕ»Ó,êÂ=f;UKvZïª"ãDÌ«Á!NÓnº»Qv·§Q/ŒybÁšáý«íˆ’'KÚH[}š;T/egÝS¢ñ­JÛ‚ÖäOë}ñ<Î}Ž¢®‹U¨Èl•ŽKOý4Ο˜æÂ³à`Nù…ÖÛ†èÛ§‰¼~Ùˆošh¨åŒm§ÜizçèMÊÐ(_"ý{0”C %uQ´LÐðòuïUM>Ί»î·qû£Øš´/`t}rü;£ÿ?Për›DZn†ŽÀˆ©x­°võžye* ̃ Bz¡Ós%{'Èí=fN©’RiSÇõÇŒ@š9[hòÖâ?Óª)| î½Võß«O¯f¨“´J +¡Yê™ò«Úƒ(„¸Ž77¡]ùë‚L<· ¥4¦ˆñTÍÍñ€‹×SÒ:ë !·"ç^‹¢+4~;RnJ“‰nv¦P¡´• À Ѩ¡&X.Q »$ ôÒåœ|u#î)G‡ÔÉ q=LD·ö„aךͅQÅÿÆÖý^¡Œ8ù,÷>ú˜i¾l+ Dɵ×k¸Tæázãþ×É€m`~¢èRâËd "gýk8xVˆyÿdˆºµ¨â) (ìÝØ,£ÒÍ#‚7eÐm©:R‚ªÊÙn‚ÆV8;Ñõ6æ¼TÏ¡Bö9[óbU²‡AÒ·nUmmgÁäšcr-Ò‰ «e4ûZ©æaÊ U ¨à Ú$4W‡©ø•Baa7Éèz»T´ºÈ)¾$êD›‘Æn|¤xxDŠr+h^ŒP"‡™r9Y€8Ѽ ­„­ŠlhŠI÷ú>ÓñuO‰¼Û£Hà—ª¬v{Ïq²=ǘz ©Â„µH¤¤”`ÞÛŽ ¯p÷¡&S¡êšÈ*"v J™Šdp,YLËDz³Ó9üW·2oe©îÛÅ èû3Ó¬’¢è3B \@,’ÄÚf\®¼ÆÔcN‡Ñ ©¥òÀÍVuV‘y+lZØ·,t‰=N¬ó=î"BGÓ·9è伪ßì¡í‚Š$›Ó!úßÛÄlöÚ+!+jËÈ18UN—EõjÔ^¥Ž,ô¬T‚*p:{Vžê "Tå:‘jUÅe}­@"mé[sìÃe‘uG­8+—BX±¢ƒGðÿÛIv·Ø|õ¿·"ݺIV¦‰T½'†ÁÝXak£w¨Ò¤[v×c¤Xú‰µè:‡kÙ¨ÿmU’0¨îþã=“±Çý#³–«HRÓ K̘ö¾ÔbHN—î ·›´knsU}¥Á–_‹²^Áþ»òf.ÊËÝ—¦‘Sg Õ¼¾ûb«E~³Þ¾(ÃŽa!ûTͬ•A̓äši8FùŒ«õOMµ8²8fV<æµ_Ë,2¢öF©xEÑ ³@¢põ¯Uj³A.L¿± .·Ë«Dp? Ž™…Ï›&égÚÄ­ê¦g(UiCBöVÁ-¤iGxDkÈ™:¢ýsŠÀÏYòŽH„OuÌKN,4ÿ›ëú©ñ+|pb³ âR'æùÖ ]„ù z‘6¿Æi­&0§UöÇÑ™,]ü êFÍ—Uc§‘iƒûGœ_HÇÒ(YŒb¿ZÓ·Ñ]$?±ê4ò¤X²qcäÆœÉ ŸI³rJmeÕÍñéÉÑq8@3–O²ù¹(‰Ù£[–M‘ÇÙBÒ<²†¬ã9þ‰R‘4ïµZýÆÀ;èè(‚îdBƒ³‚>V!›ÅEMGˆzåWÎ 4»;Ç*í®ëu ¨\m„AÍ»GYƵÄ4ë*XŽÍŒH€ÞìšÝò…/v'h.ï÷ËãÖyZÄÂnbë»ÖW$»Ò<î?‹q§Ø$ŸÉ¹dÚÕdr-QÐä´O®ˆ=ÃÛRHnzYѹ|Æ]“j¥uWœ÷ úšÒ‘ ŸA÷,Õ V×rÉ„7‹lJÔqmô”ëÐC4R'Ùè7cÚýá;ç¹Tþ` ÈBI.ÖZºBž•LÁ>ØùÁ¤scz¢Žê·mqV2êUÄt‚šw£Ô¤,R>’'öïî¹g-Ìc¡¨™ü ÏïÙ' j.Öçêv+,fÎ.é†f N+€¾†a«*ü€ Îà+e"IBäÐAð.BŽa°*è ¼Æ(J$î\ÈRtîþ€ þ´¡ø$§jŒâôBÎgbb×ä¶tOÌê´'t‚¬ºÓ£î\…"â*‡ÐK*ÙÀÒ,ŒBÄ$u¨t)g¬?ã´R.*=­ÒƒÐU&îÃãä éÍB» fø§P=©èç§@Ži¼¬ ¨øÓ$ÐÌ0¡°¦õî|Þì™BÕN¤¼] ÐÙ§~ ŒÅ®b±Ç"óê–ÒË|)¤UidEÉ´€æý` ¥ üANÃèJ£Šæ?ªþç«ô¾¬X>I øh§6Ëf±Nò}Çg.•ºÏf·‹Ž®1$@Œð}Û ï«Ñ²ì>í¤Pkh:y&,Ýþ倢Яø†ª8Gjh¥§ ‰†¶Š¯¬Ã胇Ô%B8~b—©‘(ÂŒªïƒû È> Hg/D±Kq™p`n‡a‘ÔËÇÚÁl<,ðø©JJË k¾jê"ïö®Î"K¤ð¤l ýŽ£ ‹ bÎ! ,?j#Šž­%Vë ä/Š(Yf…RPox °HQfèRx.Kþ* 4ʩ־ÀØ0æ„QU%×ÇÕ°†bò0Œ`R(”fîºÝMÊ$„cŠb*…"˜K$v*XÆÚãÏœËÆhÚ®^$F,hähö´b Î&/è\éŽ(ܱÌß ºPñ´".~`«dÓÁúëbÏ'!öÉ@Ufx#Ra­/Ñt½¢zÿï !%~nzº ,Åí`’CnÅñØýŽ-$ÉdLJ.¸²Æ£®Ñʼ<0ˆS$œp¢¶0ÐPŠœ-Å+ ¬¯ IFf’K‚5à )ïD« -!HîúLÏ ÅÌtpæï°Ý G$H+þèÈï³b!¬,¤#DR3”ƒ®DÂgé)1på m% Ì©á­?3¶t&ŠÞˆžL"Ùà+ÈË1¦ç£ ³MÅ1¤.\£N›ÉœnÍ6³rvf‘Δâ*„d\AO|pS¢…fÊA TB«–•C|ÊŠ Üï 9òñÆñqrM3=! ä°ì€/°Q'¬@† æž@fºø† ]ƒú¢—\³IG¬¼G§Úl(#E‘‘EÉdÖÈQ5f’"Nê2Ï8L½%Ï6ç°Ÿ“û0ó *TXl( Ñ'²×­LÔŠ¾OÔ3Mlºpþ’ƒ) âø ¾€ÇŠ ôôj9M®ËÂÜÑü´îü>.´0|0À MÚSNÀšÊ’h”R@ˆRK3NcnœE e ÛD‚d‘)Nzf- b¦*¯‰uISã+"*”Y笄nðGövJ£øwPãPD<’4/ n„¯‰C‰TŽës¤.R<+ó¤d‚¶7ËÐãÐö³ë9r°æ3¤´€-ÂUÈ.@aë[UÀýîCd #)§è0ÒÑÏaë ›èÈèÎt¡qÃKM# ôp©âΨÓ0Èt›(FH¢‚äû1õ3wrlØa÷j°[Pò~j8E^á”\ô@*·%Ðç¢ wH¹hôl*øìj”ÏóÖ@¬ V¦ªj Ç­L Sî?äng6 =6S†ú{4näcÂPó‹ øÒ Yƒð–/qx €4¥ª™9.JOÍSK ÝNéÙUwžt5I¶[X°Xd ?ŒkÁZPDŽ´q„à±·nÇä9صÙÁe-ô‘<”/—‰p"oaŠb<þ9eZEMh‡Ï4b²A5÷Œšê{§©{58b+v\¼ä{÷;(’Ìif ?B|¤˜b&Ø'u[+• òf%Úh˜š‘]Rù6ÈÂÉtRÑV~ÈHË?ÕqòÏ÷àn|¤ê+Ç c¿¡ ¿KéÑT³åEaP‘4/‡Êa÷^ù„ü•¬Ûa޲Vt¶=Ý4!dÆŒ-†P[ŠÏú|ÒØådoŒÀùëÊ¿TjÒœ Ó*‚+Ò'~zá\Äâl(ß)u™iîÒ°® qEœQÄ"£X5³ùC÷Ö³:-»K©¢-ÊÓ)¨aZ|°æg57ÛY’óYárv ËÔ¾–SÕ÷O§iÀκJÈç…,³7áNÉ}ÖfUÑÞðŒøªè’4úvå0“rÎ]¯¡ôcóËõþíö¨ËÈz©iî½Ù.JÎþ’  ¶R®L`R·´AÖŒ wæ"J®³ÊŽzUòKžUL#Å*8G!H¢“CX0RzØ ˆ¸=‘ˆØ=¿ì œç¨q,l²Û›ö.}‘¾{iã$µM#=œüÔø·&{¯i°éÐÔyM?4Ñ ;J‹‘ui#ÔÆ¢PUƒÆÏ¢54þàyK`.X®$W§X;ÑS4ôû;aœ´œ3«$ÇÛ ?i§Ð…;œÖ‰º"2·0ÆrÅ7©6 ¹ÜbE 7PI0Ã}éߺŒ+[$¨"l"UÄi"E›¯MHžË¢™Îí½$  îƒ!èPý‡C§óâ)Eã€H‡?`@ÌŽ5!ÄŸò™ BKG#ÐèèRÿ‰Jᑨ„J15}OÛTüò£Lã÷ÔÖŒŒÆªÄ…ëUˆ?+ŠÔ~5X~I SY¬Z//…Aqˆ0%h¯Sfµ CÚéH²Â&µêåâS²ª „†khšÌâQ©ê5ŒGðrêŽ&!–ɯ5ŠxBÏF£ñû/vD¥¨NhÇÞû–Bp”å*øÄßWÑ×kxìÖpšÇëÙà.½ûÂƧ¶'þSDÖfwG´b娅N¡›ŽVeùÒø‘ø”²DåLéYÜýñÿ^öFûÚ—übý Ý»ì ½€ søþ&¬ jŠ‚ ä+ l 0¨#~£@L2™­Óœš¿(„ʬ B I›œèŸðÚ³É $À«É«•ŸŒ¼Wª.#%<ÒÏ€0“®ê,L F°Ëë}#®ø™£ë”>…4Ì´x”°/ÒЉ)¨‚• "M}ÉÀ ¬C²Úæ'‹¸™Á-SH„¡QëG;3“2¢ÑÍLÚB¢Npd™Ê£È±¡’ÂÂéN¼¯K3àÀ ”Ñ:&Îô E.”ë¿çôL~¿ "×ÄL5D2 YÄò$ã6H@è"ô"¡JHôôÔËÕŒÜò¥V)›”Ü7P2ÐÐö‚¼Ü&mܬ9LÝoY±Hìl‡=hbÑ2Ö GiÚ{ó$ÉàÍMr/Xèüó]Óèív]HCïz¶èUŸh=RºcZR–Ëé~GôáýbW”Esoà´:ЦÙ,ò$Øžôõ€éF7•ÄÊSã}¡PÈÞ$Öd':ˈUŽ”©´¥{q£Y“¦°a8fo7@Õë6‰d×#™KÍhE©LˆvÁz:Ö¯VùôåƒQ`%­Hv€ib›—gNÆ#MÈíÅe®8iJ”Ü-v£¡;ÊnWSh÷¼^¯#ô/¤£»ÜГÓ‹Ìù© >å$4š©ïî} ¿jÉ¢S‹)ª21Ëê5gÆ+r”¯&kúלԌ¿>ò͵j#L)K]‹¶§ôöÂúÚìóއ#Wˆ¦êˆzs;éâüxˆÀåPhêaÊŸþ`£Ô1&,Q’¥)½‚ üú¨½=[¼™\%V\3¥œ'îWí'õÖräørRôˆgGnã3Ç,‚2øóŠ"þ!Ê‘<¢´Ž©먰¿OôG!PD‹‘"Ö~]ì&Ž„8Øn»?‡…i¬d ‘г†]À©lÓSN$0ùJ²ÖyÔªj’‰Ö)æÒë Û]?Iœ*gU2˜XqPú#² ÐSŒƒuàDÂ(Z„³hŒ=ù€ ž¹›‚ŽìúôOy‡& …C²¼ä‘+.g†úR›ë…ƒIÅF’e´ðÕ‰TÜ~$e~ȹD)®§¢”T¢žEo:”ÂŒ¬dëVdÍ÷ìþN A]Ì1Û+4¼B”ýUÅÊ$vÏe)b ŒúÐȽCËùm ±ÙJ‘ º­âD1—Ì2e­ÀuÒŠ‹³a-+ˆGRIOiæE³µ5Ié)—,E)ÑÓõ?Ϥ‚+5‘<óòfßÓ‘Ÿa³œ¯g\¦WÓ„óE“JGQ\s PÖ© g£@bÒ{0+aˆ7¾Ÿjl‡‹órªÈ*•iaˆIªÄJÍHc`þ# ~º>SW€h- ö  ¢(×XôÞ®&˜´r°R—¹¦UÙñÔÉÍ(‘"ï~ÌN­—ô–A>}6‹Ô5Py«…_uGêpUÇåcËùav9…0¼ãè00¡±Å*ÆuÓËZ4sØ£ ²×Þ ¤dG‚ÜÎ“øZ£KTôÅJÉèGmœIYQ~.QÍ]JÁ¸.UØýdXGXÛ]kKݾëÄ?…Â=4tû³ÇSSªeùM$¤¯M#æ¦L;GÏœ…]Ú¶Óì‰i¥€ò"ä™JâP˶ˆ·ÒCHkª-<ŠiR*C!3yºSÈ…Ü5o:2™o¯Y?-l>ÕêÆÐêo§ÞP¶TÇi©±v#r-Ž˜«i+¶PR‹þ5™ÂfŽÊ௄æ ÝÁ¨€ r˜¤u#ÖÆœs2RT+WÇ9«Ø³“'q)ÌÃê®É—!WnŸÑ´÷®_)žû(“6êWî3ÀrdAÛWmX¥kbã8°:âÁû¥”ÀN4¸”äÆÕuâšôŸó(Qf[Ã^h«"º¼ÖC "·n;++rBScã!X€£=ÐAª|ô¹¥~p›‹Ýðæ÷)ìýDEïvÕ¢jÍ bI`>&¼D½«-Y0pT®ÁP8Ï@KªØø¦N´"“ö¾š«:•g‡êBpã[-ª¦ä§\ÙìýåÏy-zm}WìÌMKë þ^}BÔçžF½û»àÇ‹nU»O£’¤)W—A‘ Åë]“*Ú”hèwšîB…æ{ƒWþÛ8sΫr þ4)R%’¬—‹ãz~RÊA$¯•¥uŠ…Ú3ù¼^l+œ;vB=#-̾$ÆY’ä­ävÄàäýôpÃÐižq;FáT*HmXI1×BÔaˆÔºQerbvÓ¾¦~êäš&]3Èô<:Î몋蕛§¬±HÒ5%xŽª³¬°î°â|€#· ‚”½«æ®{{8QÈÛ#-9!ƒ½!#œSþ À¬ŠÑ¹ÙI;”Ù{‹ü¹PaÞ(¨¶.ò5±ã²œ¡®ƒQˆ3ý¼ŽÈº@¢13 !ÁC£)kù “=¹ƒØÊ'˜Ü±òÜX ª ²RÐ:R ‡êÄ/’ᢠ¸ý,cÛ¿‚r 9|ˆ#:“G0ᢠê(‹ü4ã´Žb­@‹&©ùºCâ¶I1œ®`>ÛŽÕ9X#0})ã_⛇ëÓ!º‹:Í6{,0êa«R:*“D‰0¢I^ž¸µ"m•:'<2~)€þÊ{žº=Ò±@P¨9k‹ÁÙÀ™°ü²ˆCIW$»Í¸é:§hï/ãɱÙðÄ€à3ÁŒ kp¦ÃäX±ôA[½²ˆ:jsC»f¹Ë€1¨AÛê¤h‚%è~‹[J ÔÈéC s½sYÁäk‹ùÕ/XŽÄÛÌ2B6“_@ø}¬Šˆšèæé8Çòß0¢É£†ô&ZÅ{6¢k"$3G»{NŽrG%±§Dƒ9¸Š(ªa§:¨Ô/â`¿;$9 % “»%iý€,‡ÙJ ¨æ?ƒÚ š(ˆô“K7{å¼dv¤±²=ËCXŽ¢ skèDj2"ÛU(à~Ã*nÄÊ`$«ãÑkëÁ0ÅK'Ù†Áa·ˆ3E|Q°ݻԕ?™•Ä!†<·¼S€=L„›ë§¹?’‰´ÉÛCxD»%Ã#¹2‡C,H"Ë—$úË'ìX”Û¹ ±àæ:ŒF¢p™k&Eá=¾ªÎKÜÃ9#ä90 $áÂ/ÚS°"“.$à+‹œK!<§2¥1ÚE’‹zx¯ô»¹ãZø•A{¯ $Ì·Ê0‹¶ë]A!Á™ž¶|¿»bqH‡Ël¥ˆÿ¶\*"T0RÍ®ñ)š“É1v+aç?RÜtä1Š…Ä8~=hŠk™ÀYYÏûü‘[9Í¢CM,ó²´®ð£0ÉÀ9áât\¶êW4[Ù9+û7é>sh }´#!ÄN1Ö ¢°â¡2ó<Z û2ÁÙÄ˸M;ø; ª{ˆÃƒ@šŒŸ•©ˆË”kHŸAÍ49À¤ó1!T-t (tžÄlwÊâƒ3˜ç/¸‹·™È1®ª!JP0‘«a Kz'±#ôÅ¡\N!!²U%EBêîA;©¿”z*A:ÌÁHT< ÄVˆ1ã9 •Óp|¹ðBÄP‰ó3±ˆòErê¸Í±3*Âu 1èÊøÆÅ«ÒĺH¥0¢`ž4t+C,ŠÐ¯>¬õN{!ÎëAD«ˆÀ«C¸¬|K|:«»ý û¿‡ì*9#³dæ+0T, ‘DyœsAŽb"3zë5ʸÒñ<ŽR7<€ çL­ ‡âGS­c'êÖÊX”¤• ü¦ìõ´k$ub“U¤Ç”ö‰1ç:“ó+šþQ }53›Œº —躺‡%´ÁŽõq5MŠŠñ”ÑDˆ²ŸÑ1Œ MY`íFE?˜‰XÅ¥ÖPÏ.P£?ô8ò£ëq?ĤÍ×ÐË·5*”ëù.2%˜3 7 ©7K"~ªÐåGÀºS2[Šñ™Jø¥Ð‚;¼Ì»õ-U>&«â;¥ I¤óP”fQ#—\±’‡¢Êƒ9®­’× ³ÆZÕŽò·txÏ{m=!–Í"‡),ñBä`3ÃË¡0ëÀ¨{Ê@thV5ðâë;šE˜ÜQ|÷!1œ¡µÆlМâ—%xÓ«Õ_ZO‹³JûÚ†M?3TtJC£”ÄÃ(²"[®ÊަéÐÂhI™²<%l9‚OV*`ÅŠÆÊ ³²µ1JËD§ †O|?…iÀå;D]RX‡A ,žºþ¼u ¢\¯´¸|åÏ=1¯d¼#´Ã/„*‡Rñy™[l”ÅT»»¥´)™ã„Rsüšu5R¨`yr_Ý}¹2ɵ¨ŒÂIÌ1Y<§¸ÜDÉô03°æ7a”¿Ð;TmÞJ*޼¢„ºsWÛȬ‰éÅ2Ë5Öˆ"£¸pÏD`þOÖ +-¦Àk^€!ìª+˜Q6 PÂh ó©*9X䵤ð}¢ ¶” Ö ‡O‰L- ùVÛç›×íªùçYé=¤2­ 4.!¹¦eCÆHC †™&[Üè“Û-c‡Ô„BÁ5YݪMdí¹{½¿ðÕsÒÁÕTöI‡Û뼄V¼(AàÅ=¥bÂáYáLQ^H„VK¬ ?‡ÓR°SˆCd6‹%ýé[ì®ý¨<² 2ø²²Ýb:ÁÈDÊÙáY:=è!Øè— [¹Tár 7à´0¢ƒ™£ÛA²z‚Õ,óº“Z¹zW84ä¶€¢Hðo15œ‡”D€4}õŽqªÂl²ç±Jó;‡DÎ!ˆ3ŒD¾ÉÕÞ¨YtˆS•V~a° 9+]è²Ö2½)±$õ• ˆž¶kb<á“DêBÌåͪ%1!žr½!üØ3êl³›ê©ólÌà ¨¢&pË’]“Ž«cÁÛ1ˆû¶¥Ìb¦š¨R“¥D‘4¤”¥|ê£fIþycBþ-;í[ÑÜ6ç<áø1òþa,1;†ÐSë»è©²MN¸ÞEaíÄR ¥\€FAlàC›L„±Ø°ØˆÂ{ÐVAR;oV=þÑEýé8%FZJ¬k•&zɹù'íæâ¬;mŽWO¬óyM—ë‚ê-140RÎ$5\ò Õ±…½ÜüW5l¡M,¹ŠÎ›ž~e¼€8ò¼LÕìó3Œüì¢Ë'¨Ž¼õƽAæꜚc 8¾a¢»É¥Æ‰ù9:îXˆÒúc•ä[•ñqiHG'àl÷r¸[‘´wÑG* *ÖL. ’Õ_„Bß.Ž©ûêê{O0ï V²d®$ŒgO;Lϕۙ±nu b6óí`ɱQeìó´ßÌ,A,´Kðòѳ“ºšcûf5Ìð'BkŒ_Œ÷p´öJ&Þcì,11¾à®óõƽ®fÄãvAˆ–iAÈo&Q=)P¦¢?”%q(ñ»V“¨¦ÓPô2Qĺnª¤O&Ë~Såló®)ÉI ‹ï«} å½#~,-Î-CÄÆ½—ž—fUCDà}Ç ŒõÐÙ Ò­f;ØçŒ,msùHÈô[Î÷Ű»@ë²b`·¯, ªÚV¯‰ôGó1‰MQg]õ¹ÛM ©J¾N1äLâ ‰Z,8ÑLà»å’<0¢¡*ˆÊO"$ŠÁ¼n1sÎÀ¿Ÿ þ Î±áÅ]wAçkЈփؚãRøîjÉ<¼S´ÕU?säÕÍnz¶Ê£‡Ü™çÚ¥;%s~@ ö ;™œÚñ:î²/§º’·+ŽRòÔ « oZ[öôGîFÀÅÿ‘ŽñûKù0Vƒ»¼³å•âé¤KË•‘ Æ–nB.׎Š3î­cF,e9|!gÐÀ‹û\¡ô ôÈБ¦é¬mk¢ˆÕ‡N÷;”ªiÞ10ôBQƒLLó=Þ^‰ñïHÔµüàté³pmÎÌYë¸÷o“Å‘\êôØRSü¸dÛñú,_~b…­Ä_n>g1þqõá ý‹y…í9–¦ ªÕ--(¤Ä"”'Üò±]¤Í¨ð(¼b±«[_R[*}ÔàVÙ,ræ¼Æ"“¨¬±:Ñ«³ F':…O"éÔ:9@Gç÷è#ç5žU%I¶‚-~Èã—Ðêk ¬X'™h,ﳊL!’8¤¯WÏ+-›ÜÃŽj¦qîït‘Ö#ó­°ƒÃGó·zµŠ£H覻ˆ$ÛÅ«åîbìH"GñÄð8ø]èF¬ïëÔ†CXžX$ª` ž3GÊÚ¬$¯1þ›!̓ޣì’0ž*ª²Jå¹mÛj,„BMººÞ€ñþ…%èÔ.ÇòR‡+*¢æª,Š «ŠS.1gâ´ýΊK´èÓÚ#‹Œ†8ÀŠ…³ì t‘Ä`<¢ˆ$°ª ö!:îEi*Û)§Ž $’¾`#î‰A“2„ô°¨Ä èDÔ—+Ê,ä0Çü´ÊÎÎêð)â8ÍìšG²iù=¬’8€KÚ>¬"‹Ä®²‘ÊÚÞ³ˆ4Þ>0rä¸àD´Ì›&÷·lcP ”’r…A´ •TÄàyZEDU€Râ¶æ+­ ÃS·­B?)Àphž–˜jÕ•BýQ*¼bˆ@Ú™N Pâ%.[£C¡ÉâKŸÐÚåÊhqëz¤t"0­X™õxBˆÒ)º2Àh“Òס k¼”áM+Î?1bþ¨WÊ„X޾(“ø‚Ë-¾ÊUÛ?µ õ€Wä<ƒ|°©çÅ]lŸÏKác«J:Ø€ˆ’ÁCµÎ''–™èiO»ƒd§íS`«2»7¶q•(twc”,ÿšÉ•bG*©8z?j3Ln’H‘þ°?ÈÓÓ å #~ÑÙ LR2vǞطrGµ]Ñ[Þè°”1úþ Ë Ę֚́¦$yšxô£‹({sÜp ZŸ”²è„4š2 ‘î`J Ó¬Z Z?3¬™æy=ìÏk•+#PSÆ$Õ!tkUìMˆŸÛMªÀJNÜØKH­Š¶»Ó>Jb›2œŽ¶¯sÚ÷˜¬›[¢·<î½{J~½éÖóc&øÉú’§‹%­N¬|&Êà ÒPEÕ·€fîÓën‘ðR±¹Ž{cí]³¸VŽó·TðU9¿$º¨Ñ¡ø#$iꤷ6P 2Y{DU‰¿ö²¦ˆÃÓ(LS8tò‰â”÷¾÷vÞ#dyGµa#–rEzK;‡xïƒ(ŸWsT-ÁT¿÷' åohµü0óHŽS[ZGÈ!]ÀâûN‰m€'y÷€PJk3¸¥,%¶>ˆãê†d¤°?Hˆ?ic‘m–6AZ©RN€¨£½ÛãˆÃþ7+%ŠùÌ }`°¬}™DzĈÂÍDe콚I,à•I{‰ yËê•Ô‘½|$a¦f¹$!-¨k¹È.‘Ñ™ ]/ÁbÅVÿ z8‹æ°¨‘ô-3ž±È„„*P4â5ÓÀO«€)Y¢¬š—,ÙX#ÆE2…’–IVY²ÂEjûÌqú”ÙÌB/g.ÑAõLH”@r5SÊÒÙ¥œˆ3&jH1¦´äTÛToUþÕÝ(›iˇ-Š>ÉÖLÈߺ?#sX :x`_ìXID)uϹ K M*€ÀçÕãÉJnÔ¡6¡ç`Àe…‹Ñá¸Ãr”á))RT¼¥6òÖŸü³bhŠ/QëRæ3ZA‹^ÍG5)g#|ThÈœP[N¤ ®mxƒƒ ô*šzãèî["z\ðö=) ´,Eˆð¦“í`°!éU—ª[l‘X[å ³ »¤pR™N)äÙ[¦; NZׇÄ9™Im7IIÁ’d(êI~SWË6›–!ž=UÝbÌëEÒ•'‘:sêX­?Ç"˜GÖ‚Ñôæ³­‹úëIÑÔ'SÄ¥6xwŽ Ž…ÖL“@Ù níí)ÀE N©d²)ÂlG{>ÐþO°ÃéfO,Ñé­°ü…BÖdSÔÈ/hÍ8Wš¬e¥¬+á§ùçVTÕQÎÓ<²\­EO's#Â’Ÿfcö+j^DJJùC!˜¸çˆ§T±öUøX¤±ò)„™²‡£7Ï8”ÞÐBK¡ð6äFˆy&Ÿ-d°õ‘㬀>Y‰Ú´º‘ êWq‘d.>¸ˆ¢©Pr7ºúÈï m‡4„êçÁ‡|Ô==Õq2Ma »r0 $g¤î`ŒÛ/oö ¹E]¸±úµÎ±GÙ%¨6ÜÉ7O{‘bq;7K|6)Kø;˺;bb’»ložQíuKUpÈ­C½T}‡V Ÿ$J™Ëz9r<ùħGgaæyzÀ1m³ƒòU¥;{$­ú“QŽäÚ·^VÛ[OÔ'‹¤ŠïÏy:“Ri.4¦4Š=<Ü„ ¯¸M’‡()ó‘ëæMÔ˜~²J ö÷w {WpæÇ‘†ý‘íúÏ<Ïò+K´Þ¥¯©$“¬CÞÊ:7.n†3;C¡¼u¬0‚e °¬ƒ,¸ŠíH?õÍ\í˜üØ„´@ÝÖ «ÄµcA§«HÈú‚ì<Õ­ð`€Ü‰ÑŸ“!PifÁ`;ŒÏƒvîY”±xGT›'(µÉc“eîJLìT8{ÞÌÕÕÅòp3”}Óê+ô20¦9úI'ŒÌ6®Ãsz׎õÑîOFgøû±–Ó Å--¿ŒKÞóý2þ«¼uÆY’7r.ÄM<›’øë‚I /l"R±%LGf¶øäo®ôŽî÷¯{o>‹Êµkí¼W½4.ˆÎ  Q[r¤‚ûV¿'be + zQ‡²PÌz@ z5 òµöX,NóüJk\)b˜+DÂDo7lJ7eœª¢8#ÒíŽJˆPÊŠ>áË$«Œ¢C²¢Nû",³I\YIHN€Ü£vcçD—ŠÔ”ðm*@÷¢à*B4-£1#Þ¾lÜñͦÆ,‹´~¯T>ŠN*,J¤xÑÊ|ÍÉÄ¢(i¨EiÒÊÞwP¬ãfì©€UŒ`fjnyGõ¥vÞìlÐàëÌæDnÄ…êFŽìH{ˆP*0sÆž"MRbdÌ&V®-¨ ‹4Ǧr+!þWÍvñ̎ޠˣîPPˆãf>±¢P‡ÍØÿâÔ*0$hJ µ„”ÀojÛG˜+zMÊÆi„ÉÐ$Ǩ´©-,î¢ ÑÄÎn ej¶­ F„LJ¦ Œ?Dr§PÔf1&3hî×Ò~ÇZØíF™®‘ ®šÔÜáC4ÑÈ®ò-È¢ÐêËÉ#–@ UNL#FfWgZá‚,rüPméòlDrRIòÛÏŠ£¤„–tNHïD¼ªÂèîˆ7É>ëäq‰UR£%Ø¢z FÌÛ(Jß,‹gö«,± ¢A©$üĦ,nJß ðÕ˜ç0Ïñº‚H{èÃnìª2Ì¡ö²’IgŒÕ†_ä®ì¤rùh^–hJÊĬȸ]‹å(Oó7'£) F üöDz>ï…F_bPÿ+Ë’±3xxñ¥"I0*΋/Í$Ó1é^é߃¢Rê*ë,ÊnÌ.Ç` P3OdŽ÷<8Wr>òÈJÈ㼘€ ·§dÀÒXOír)IxtKò׆ž:'Vu²׌dÅ$t[³ª!tÐG£%˜CIA¦&îÎR}¬»:Q<}´Q¨O.¢)å–S&u¬žòb8@k´ÆíæZó¤r)g#ëöj/P×e²Pz3PœTæÍ.μ~¢ö¦dù+¨|Jqé4Žò×ë@ëo4.¿o$Ò\Ÿ4PÕiAt6ÁR @®JoÃ¸‡BŽœÓª~pÐg-¦oÁ§MŒèW83!GÐ" 3%ò‚c¥®`1²2ffvcz-¢$óÇP*j«155ïË1ì –t[@¤g%<ÈÇ’"9b°¡":å&eFÒ§²LÄ*"Úum³âF¸ ·´ÝRf#Œ É‚SQ 0®Gì’„Åd¤Df8äbºEfÈìo"êD!‹ÍFEJnØf1tïÄžÉÃ)r|“rîp2·)®è©SVUˆ|u¯-ê58ÂllÔÜ-¢>:“PªôæçþZî[1îZ5jÉ”ô K:ܧ"1ÚéNñ(„µ ñ.ºxUèÕqô°ã2ÑL’)êÈRL@3”Ñ éòÔ:F Ób­ Äw=s»T@ GTelpàÙ>Ï!d®>Œcí@Ob%$el›­…Y¢k1¨>š‹$¤Üù`NG.Yˆêœg†×’äRJò°ãP¤z~¤lÊ/-4Ÿ6¤–G¡eñàOÏ òÓ²,ƶí«O*Ð2‹öžå%gì>ì r kÔdGÌ´–Õ?ïá0-DW•jO² ܵ¢âô®òÈg<›±ƒ[ièdúOmR¿e fj,šŒ»`†¬ATì.‡Î¤*&Õ\ó»A¶£%,“eB¢Q+jÄÔ½´!ÓÆŽí2¿‡DÂfW> ,k<­¸Éº‚Š´´¤0gË$ôr€ßRþfÍj‡g£h« Èò©`œ2Ìqc_ŠÎF} ecÌœ"Q)4t0éãaƨ),Žë¨!£X‡oѰъÉq*ôc‰fµ(85tæf¯ìØ/u0)çÕ/IÞ)`!IüyS[d²dÅÂÀßêœ"¯iQÔ± Ï?v€ A°Ç£—_”#È^Ù¦5fÄYfјANJcï J3/Dú¥ Ÿl'EO#8ÏòÏ‘w²ödl*"(s•Jçg+ŠÄ®»¯Ê‰&}U/E#t8ˆVKplÝgó–æ‹úä¬üÙŽlâULŽ¿sÜO2]GÐÑŠ†ªVå<#ÞË…Nǰ áÁ¯ÒÜ´¸ 53—/PRùWQ#Vô±î)æ”Ä}NÕ¬÷¯ÐɉoPµpLÕxs<õ¼êµ ÕlŠ‘eL ·¦ÔƒV’,.&ã¸÷áø¹”8õpOaó‘n·J¸%AÌG,´ÄpDrïòç‡ Þ1n1-ƒg œ¦oº)fiæÅmñ¿Z柾óöÆeoâ4D°÷¦»Ù3ˆñ~w‹vÓd¹S+1lø¹;©áO’?zlí´®Š.cLpu2£@Œ·|·åmqx@Òn–îoDk%mò{5 ¬¶`é\a%P‡¢Pô-yÍ´¼áùU2FCî„§AzsfTwÜZé8X¬ †Lܶ³8$óÓV¦rvÖ›o«3 K.O{VfÐŽõW%÷?wž~Ñ_ QU9Z×ãk¶öoh}m'ã¥i¨érÃqòôÉå%øªX¤u'7t¾×j›8BRz;Ôcf÷˜=wÊÙ9IcáômD©j£iÒ˜¡ù33¼Jù/gÑeJòOV¨r§çÚÏCqÆ97¹4áéÊ®áþÚ–A÷vZÔZ«4úøå˜Ùè¬àö[©Ëc~º$X‡*Å®'P-ŸÛ%jÒ¼¾±m/@VJåénxXµ­,xH¶%-±"×2% ŠÖÕ|ÝÐJ¯7¿y¢k¡5Öòí]·hê¨gÚ R+J5dîv¶kDw!8`cÅFëQpñiÁ‡'‹vÉ›Ÿ%Y?-@¤Ï­ÌÙAðc–Jf'u›è™x^DG õ8#ò’¥$«5˜£¿ñQ>G<¤“}GWväÚ1&Ìîç툆m³48ã5¬äñVñCÀ»Ž¬™œjRºx˱ՃmˆlÍ@‡×5(O/Æe¹dÙ—¶ðp°äwÇ—‡yžzÀü’nVý–lš¥O}¦lÇQžÚl °ï,PîsÚ+1bð-˹æ1+,K'¹¿e¨Å!VÌ!šÅV§aAã öüjfá»°kÁþ·§g8b%f:ÔFÝ—R䤜B Ä÷·¸ë•M³:[½ Ëýá÷•57æn1%®ÂRöpº…å âèÎox»º¸¢gðØŒØPéòÕ0 A[ôdG(…ÌD—PDG¸.ñWÆ×,²XÍI앑Ȳ4ÊRæmXZ“Ü{3yF À-Šæ$´ Ô‚5µ>9Õhµþ­ ‹Œá_Ê.e:, zXD§CÓJñu/Ì¢h—ÈÎ4ÔâÚ.ÎúyÌ;ÎÙ¦7”É×95Ï[<åŒõ§QR݇C"'#¡öU8u„Õr¦Ã2õÈvÔÈûÆ}K¥b…ÂsÏ,–Wâ+²&AÕ”¡áòÕ©ºêæ%‚fµÛMuÂIa£ò)ܨõª"´ z;M@»RÛ¦‡(w¨¥£õž/º¥\GZÝ^p*$×Ö‘ø’à¦;N,VÅÙä!œÅ‰BŸ ‡u dïÑ0)<ô&ñ7Ù™— áø´`rüà·ù×Ô¡ ÜÙ¦TiŽý!2‘šr<¸Írç…ÓŸœdzo!´¢Om–éª@|Û§ ¼/¨•RWoŒr\<ÛêËo¡öu±A^-¢û£Uuv Æ‘MÏÑ/D‘£~l¯kN«8K“‚N–ðÔ›Xƒ4©ÝDŒÑ¸ûe3x޽äüÿf(¹ù2'Xèï ^Ý¥š‰¾åìCn-fOæyó³_X,/ôñ›ù\œgÖ9Êâën}Ç‚è|Óå ]ÛŸ¸NÿÊѲS´Tcâ è0ÿ…BÀpØ@û…ÂÁQW´\ …¾ãÐA‘Hár zú•%‘èœ* ‡¿&’ˆDqö N$` 4ö~h”*âYIPb2èU * š?(Ri4zœOá0¨3ú“¯Öf0ªäúA2žÚí‰5ªÐ¸\(UšËæñKßóˆôÚEo˜W_õ8Ç“]`—Jl6MH–P£Ô*N0_‡Õ¤0Šž ÿYo˜] ŸWäÕøö–=œÃì™é¦§|»b¤:ÍW:¾Rjt˜d6¿ÀÖtLF¿‡ÔO6ÏÊŒâ¿Ï~Âðô-d‚=z£Çaº\¼GQ•>µY Êÿ“{kÝ—õžg4ó¿y² RXÖ Çć›03~£(j#JË?íB²¯½o[b+*aú¬¬(C˜à«ê›è¿Id8ž‘3 8Jz"¤¾ÏºÒ³6N á  Bê-¨‚"¬¸©cܲŒƒVƒ3 üÚ Šœ(ªkÒL{Ê)2ôõ%OÉø¬¯P¼>¢8‰£p¹°qQþ¤«/[è ÍCPïÈ3k²¡HH‡»È2,£0ƒí$€L.7Ìj_&6OŒØ~°ÓN¢¢,Š9-Eoã8ž³Iv)+<&ŠÊœ¾£h“D¬ÎøÕ«bøLs0¤µëÃ+IH’E7C¾O{Т,H2<œL@DÉ3? "<¤Á‘bX¿/àMLõ†«òpŽ5ÈlðÂQCæ¢+í*¿Z¡¶¢€H||$ÑM᥌Ûý$ ÄôFëcœƒUnT˜…ªs®¿Ýqzå3T2Å{@¸èû9jÕk䜌ګâisÊ$ú»(Z’ɘÀ .«âáT ŒÄÁ”*høåŽ @ãd*QC38 xÙ­Õùû8Ô’¹JLó_.^>II¦v¢Gªši –Aþ¬ ˆ~xšG6UX„0¾‚¸É–üÒ¡êL¢{ßËȤаÀ4ºˆ‘¥ŠmF:zìílü C¯l·U,…¯U[r…UsÞÄJ^C pMÔ•T•^×UÌ 0’%éëA…mtâ¾½LUù8>Ñl‹`»½§•ñx#Ö4hrâÖ Þ9?ÅØ^{4ê4–ä Ý™ýáKÇær¨7°ðŠU‰mu¢Y¡Lu¡*È^Ú„/OH¾lxŠ_htÍØT‘wE&`È1W[î$µ­VÎÚ)lí­Ã°‚zØá$j)ô'ÇÇêó~¬Ô—²’„^žb?!EmÒ&u ZIªpi³°RhË@cH 5[Ö¶ãHÌ(I‹E=ÂpªÖ18=jß •Vò[èN+U»9Õ°‘Í“6*ÇiG?ƒâòQ!S4g­Ï„\N’¶%³FWׇ‰cé 1Ôr±!N«$à±dÌ|^p}Æ€3Æ>Ì:„!¦¡¸7$Ñ‚HíK°ÅKˆOd&û–üåš:§s‘©ÄDV1znfFÃb÷&Çéz=o^B÷*? Bü…Äyx<•Œ¬ˆþŽ#ýc;sÖÄ¢gdŽ]’©†>‰ÁQ;Mn%÷¤K 犄Þ7ºvnÐÞÃn|þV–× ÒsÙ}-íØâøWÐ0Ù¯¹îK•W:€8n6V') åÞ;.1v7Ɖ[&K„C;l…R?VÐáà) _…Â+¹e¼ÙëkžSƒ@â+Ó™€f2¤–ÁiI1‡+-n7¾>a6K ÿ¼& •WÀÞÄÓ8–گLÌmî+Š8ëqÄý’fþûHÊkFéXÍ¥²þ”žÐXÀN *fŽƒý9‘<Í•Ypò@¯És"K„c~‡µšT@›Ê#ë/NT‰§ é; ì…NêBGCf!‘T&œ¬Ý«ÉN2åt»†VzéP\ ‘Dt36Gòû°mñÁ8cìÖJÕ~ ‡­ï3ùæœMDÐ;6zr¿Šú>é¢mj~¤¸sÿ+Õ1'¤á˜ÂZlæªKñWVV{@k'NY Upô‚†¦³í²»LíuwM!öÂ% “².¢£¥ª§«.1óâ\“ÙD‹¡uR–íYëÙj(%#+í€~Xöõ£Âí¯îñ>ƒúÚ%ŠØ%NENêISXשƒÞ ˆ%¨…ÖÁv¤w€h&ê«’S®ç¶zf* óxK1h-Ú˜Õ,^\¶Þj87*£ÉkHnŸ_{‹=ì|¢µ®Á`˜Hu^±† Mí]&“nmD í™ÃA%ìÍf!X_J+ETµ²mA³¬f˜^,Ü…·}Ÿ0º²ØÍ”A°ä¦(7¶Üá“lBUÃròlÂ!·y´=¦WddL§Ôü`ÄÁñ¬*84>êXùÆf;ktX~¶{<íó1 =vy‡P£w Ô²$EÉÜ‚CœIt:`œx.yÜ©çvW„G¦u07, ªÒiÝ$}«Q„ÃùøUˆ|qÛÁ&‘d•BäÊDã¡°*åÁ°‚¸Î yØKaàd¹Ç¯i¹qÆš†:¾˜]§‘ ³Tù陃P¼,ñS'ðÝÚ¹qfq@E8ËZÕIž™ŠU×LI¤¢K{ŒÈQûynF‡8Ò¹¦ò®O2Ól…¡%Xb¤¶³ym"`(FŒzò8ÿHã_Øï±´Ý•®vQÌ. ñÛÌx(áäø¾=3÷~fõÓ¸©Žˆj9õ”›f5sáÖ,»—‰ s¤,E°€x6·Ê.›!Y Ý̅лó¬rpŒ˜ YcÝBf§•À|Ò¥zÀ"ÜoM¢ÑÉfA2⺄­ÃVŽõS4nÒ¯ְ«¦åÎUI—¾ßÊi aË׃j¤P«ÒõÊ’d`oyt|Îë‰C{ï@³ÐYÜðh„ó=ÍÏ©ÁlÝ9Ð#²sP:>SR4/Ò¸Loi6>öæÁþTeÍ-´”x,h¦v[×™Äï#£•9“lÊJde+íŠ#¯á%›Ðju§l)ì™ZG à¨i(|ž}Ëñä´} òdMÞ¥wx¹i8©(½?a£ÛA=Ór¸Ú³ñ¨¨¢?!î7¡@ÀR¦ž š%!¥!³¤+ “   8±%êß2Ëb:õ7i«A•½ƒšŠ²ì© ?{:ñ9Ró¿èì»ñ?ãCÁ2B’2¤¸Ô d!Á‰§¡“µa“Â(¾S–Ž‹I-ÙD6ѮʞZe‡ãx˜Êf™4 +ØŒ©šÆL.=s_3ÚœApÂ1£s*X?ƒ{³A À¡;Å€¤ºy!’¢[–©xˆ1Y¸ ³¬AåXÛˆn "ºC›f¶c6¶ûø8lC™é¦ë^·3,7€Ž,XÝ5l1¡³ªyá’)Û $HZ`½‰ù6Šž°Š=[·©ô @Yü¨áÃŃ؜yš@y• ’ÃT *Qŧ»m¨@ˆ¡BÕW+yK ³ÉCdm³SüÅYó(Ø·¸¯©›ì3ˆ»5c쿈ˆ—€¡;£ 0ˆ£Ù ?\l“A{CqT^iü&é‚ ž¸r£BfC Ý£»°Æƒ>=ƒ"ލ¬J[*#Ht4£¿+²F ³#”$´3’º†³°Ž:«<'Ã!Á ô 9ž¡@îÆ£d¾}½È„/lw90#rê•ê—“‚ÿ¨qË ²ÇüC›Û‡ê2­$>C"Ÿ.‘j©<„‡á;7÷Aj’¼/ ‚e+ÀŽ(? kÂ1}¾P«3ã[á<¨ÁÔ­3/ ±'Œá§9ž«£I4ª1â‡óͺ#¾!ž®”·ªw;A­§”‚*Òh‹‹‚9‚ùŸÄ®Gà9(‚[žœG§ —¼¸œãZÆ„ŒL‰…Éê=£H¡dןxò²ó#Ä(¹Q8™$S ›'ÇAF6 9´+N©©KK2p»iI+ÿJ»€1x'rӋ÷%l#®ržDˆÐ—Ê€~LÙº=XøÀ3ê¾óØ$L(ÁDV*K,Щ«*9ÅL%(k—³ìoÎbϘ}ʬ¬)ôi,aGˆQc&êÇ-"’í¯A„ˆRÔ>êF 8å% ”c;½¨½I~¡Ô1²Û› ¡0ý¸›–Äù@ô((û"<Žk@4«¢ÖÄTÒ)6¤¨£aS­…ª¡ÝÉ\J‰é¶úì½R´¢Œ)¹ùêÍÛ¤)³µŒá£Ã9#¨\ËH\ÂΙ| SLÀË!BwObð¢´o®èÿ±£F’D‚áK\w0zu:®Ú(:U9ºãR¥ÔÃ+Â"/TÄÍ|°A1ÔÊ6ql3»wÈRwÚNà/ko½ÕE§Ä’A~?,L½lºDH™ëœÚé â  Ô0‡ò-Oy…8Ê;ª½æ:ôúÈRŒ ¤½`“Dk†Š#¨ êZœ`—®ä.‚þ®+ œË¤_2\4ŵÅ-R³ÌÌŒÁ„@ó^˜sÆœ• ?©õOØECÛEšÛ”I¡Ç ,ºU3\<ÉÃeÇD£ªr:ÕªbQTšr I‡,zž$I¤Ô”›ÀøîT£Œ †§ºìÁ€éÖ`‡Œ;l:¬ ³¶´ <ìèÐà়\®Ú‚,ãüÌÝvÔ‘£ÝÁ‚*•ë=:…tÃh‘MqÆI&9QäÀ*Ò.&¬¶8Y3Àu8» 8)º8¨¼"9#–)1ÉD};“³â'.‚C9R Bº±8Øp²Z¢XàÔÛ-R2Ù1€œ ;ŽF„så¥Ú>‚çÊÐC(lGq@šÜ9œÙ M!JÊù³§ô‘ËI(l¤Ÿ¨¡A AX|1s BÒC»´S:ÒŸÅv¢Áz ìŠÈø±£Ìp–#8¸À}=™xƒ6€-m§Ç@ý¶ 5œ=5b©Ç±vŒ;£´’ÅžüG•‡©17<Ìv2<` VT’yu‹Ú˜&Ä1Š ˆº€¨šKúToÍG;­£»)Á\ðà¥ûÉ©‹ûšç)ö˜ClXýÑÜ*ÇÑ~!ýf12 ¸d G\¹²ÁÑ3å1\ s: [¬ð¡¢\íj™”©c‰‰H•LžŒÅË”‹ºÍ½›‰•݉…Þˆÿ” EËI$-“ ,Ë LœoÑaî@©~LƧġwqLú RÒI˜¬¬Í¼F}%ÊŠ#½ëÉË×ÁÚ=´5 Ã™žØ ƒNÂR·P–Ub¯>óq5Ù¡Úåû“›!1Tq.[Ô8 Å1Q3sZh|˜CUUÒ¬ÒŠ¨ ‚, Ó•?+§Š)B¥¢˜ëpàZ[`Ѥ*€Ií ßX€ý°ý á3•Órè8…U9Rq¦îÀÈŽVärQÐ~ÑëU14í±ÄoØE¡à ôV3ÚªÍH¸›%²[ÐÒ’bëÀ¶ºÉå&ì»»X†›‚RT’% ´.}ëº9F5=‡Ûw69ɉåZ»1?ܸÞÉ¥ ¤/JDÛ›ð$Q01q½”åÇ$d훣EÝ¥I )ËÀ3üfûJË}áñvÛ€}¸±¯äᩉR! ;¨Ù,º0Ð+£?×<Õ%º\Óñ.ÝŸN2Ü@`«ÑüV5¾¶6ÉŽ£àˆ§ˆÿ£JácíÙMÕ¤¡ŒA’¶GÒí¨lJ1>QÌÝ®‰V‘­q}#y#Í~TèÎ^^8Ü»'¾éãµmRTëý`h®Î•ë}Ù‚¦Xe2¤Zw>4çÞ =Y37]ßˤ9Ñþ‡æ,¸Žõ¾3iU$ PêçE¡&8jm…ÃRkÃå#+9û£Šˆ…½=O>mÉÛ–ÙMŒ^E‰]ÕOÑŠùMˆ¿èˆñ¸P“D‰ªi$$©x:ó¯)*ì•°ÉbÆ3Ѹ%Ηˤçô<ªLvèÜŸ­¾[?1…cqô¿+QgtÔÎc*ØÇF+Òôemºæ§¬ž©€õ–2Î,Í€ÙD\ç>ù =yo„‰yj®“¼G[¬ ±+˜–n«ž•퓚§O¾‰Ä–žìì§–¥šÖ°´†PKÎ?ÝòhE‘î±](&/B+,W¢Ÿ‰Påtk)õögHˆå(û+Ï-FeOm¢`<Щöo*a^å Àî…’$¨~ 櫾ýpªK`›¡FC9„aý,¶ü8˜¢¦'HÐÆêÃövZg¡œ%!ãç̺avuGAÃÜš±Ü»N^Îk‚$ÀH?'Ò^‹…S2Bëpös„_LÒ볕f‰Ãï4«ld$¶ý‰qêk©ž¸÷5NmáßÌŸdwœ>÷Þ ‡ÖT·NkÙºÈàã79½éK6ðŒš9Û¶jòµ/·FÉ6î¦K#ë€?9üŽŒ ÌKqF ˼Ñ(¿Ý#™^d!M$Fç0NÛ¼!vÍÃÂy·¥l>ônf°‘ÙŒÕÄ«àì_ðu¤Eõ¬Q8ì©N ê±iÁ]u *†“´tÕ MÈ}í†ÇQ@Fò:= ¹4ºfHØQØÃÐúÛ»ß<%¾- °ž¿Ù ·­½HL¨¯ó·󄞘ð¾o«¨g7ežêk'yT™òáô­¬µÂ.pÑõÈúd®Â£}Qê jävK¯Ì–] ˜úàõÝJç¥öq=‡FÜâè{iXýâÇD9ÙêoÛôÒí·r^»ãÈÍI4—"p6)‰¡cv@yÀ`Ót´—¿“¿ñ6ž#ï‰LÎýr+Iø¨dÛcÝX¯¬´Þu ŽÔ¼@±@ÍGÆ2€‰ð2Å÷Iî%(ÏãýÀÐ…o'3»ñ1#ìo2GeOËÚÀßz`_²16Ø£J‰Rù7Èïöþ›>ioÌãN|'|rEJYôÓ_1_\@öò)+\ð4yŠÎHÇIíÞÁ Ù^¶¦«¶Î\Œ¡úx|cTÃsbß®µÙÓŸŵ†"ƒ‚Âð€? @ˆ#æ „AŸ `þˆ¢P'à,ŒD€QHÀ þ}H`€ˆÓîM¢ÀTµû/†L@2÷ìR5+•Ìeˆ´iÿ?˜ÏèOø¥+¡Q¨t)Ì6Q•Í"”™;MÏÈ´~–ÿŽÇãTXdvÈG_»4 …aˆÄ¨SHÔ| w¥GçPêånz†P£S¥Î_+ºÜ@@ldÒW^¿Ä+Kú…(˜Ö«õ‹í ?4ÇE€ú:E-O‡MâÒÔÇÖg¢üDKY —Ê.àZŒÂËÞ¿s:{æEý»Ã?y2½Þ²íwnâšÎl‡ äq°Q-+þ?(ªUj±Jž˜ÌC$ϸìÒQ4¸?»ºÇë îöÀ\ýäó>âÏÒVŠ!KÖŠ6¨Ðî° C¸‹£+’€†9ÌS*¡7hS(‰&(úV׬é‹Êµé£× €MÚÅ (hüWÀ/3쎩J(÷¥ïŠ:¯¡@d|Ö=iÖ!J_"B:…4`:>›CÂ-1èƒÂ´£:ݤ©3øü©r¤¦†IóÒ² Tû«)â|ŸÈqdÞ¡©NëÅ5«ïd"r!ˆÓ Ÿ¾(üJ—ÏtÚIè4¢ÈRGÊÓ‚L•¥ìº}£ëiøÝ¥rÑùI¡ˆ£¾‡N±‰þ¬QO¤ÊÚ"É¢c«ð˜ð¹/ »¾ÕÛˆ¼ˆ°îÔúi4ÑõD¤œ:õ»Y*³þÂ7À ^Ýžö̯µð9¯`^© OPýNkìç>¥í{“"Q}0¨'Ó6®É ýii¡”9ú•+S´ôÎðÏÀ×FŸ‘}à/²„`Pgþd¥(2QSI6ZbÝ¥,ìªÓ°Ž ŸØ'ä µŸ ½ŽÑBPõ½yJâÒŠgj¼ þ+‡Ïw˜õ¿UN­R£r‡>Ã.Ô¢YfJ>Ó.{œÁSÜËƪ[Ö×Î0U¨~Í8uâÉh÷5–ÉÙu®}D'íÛŸ1jèlùŠ…o2«,ŸË%E¹àK쎈=p.&/\šÝçè”OhÕN Ó[chv8[Ý›5ïÐ«Ž»ßÍdEG"OšñLªU)½AÈÚ”No¥õêjR)X'šBÝÀ©^Y^Ö:^ùÙ"µü.Ÿ¤iYéç¤kìL“GÀcÖ•¡X|fà'¥u&†ÇÄŽ# £¥ÙÞ€ÖÔg·Ü~ÿÜ{zªëû·K¼ljhîÂ|OYèfãù%¢ èöY¯±ý¼—`T!5ŒæuŽD:#ÑÒ&,Óº³O¢D ÐfÃp·{#q΀9]©/c"%ù,ÂÛ@A ý—(È„V³Od¬Ö ˜®‰‹óaòq¿Ä,΢£°leirÇò_œ%‘#îY4XjÃLQÁw]+ÉžÛéĦ-S© t"# 2=ÀõV$±Z…³†7DÂhõO¡g©â/ [,–È÷c½»€WpDQÝ`Í@4G˜A#lvEF*S¢Æ+elèIô¬P‘ûÌ;— îÑh@ƒeÙwe‰5 (úOcŒ˜鞃"C‰Zû– z ÖÆ® úM’Ó¥Dã@R¥AòUKv” £4­–óœp4ÍÚc8ÌQö¢Î]~M™g {WEì1dG3‹ÉÙ˜Õ}„¨(ŒòëxóÈ|ìe‘ör5â“U„ág«kµïĦ¾c%4}+ù¡.Öªœáá¯u=ªRf' 2ʼnMù{f²“C85Œ<øÆ™Âxd;5ò&³nñ}L«T"'C°]çÌ­mS…ÖÚð n*r¿¡hº ³ ,™d mÃþÑQôJ3j?VI”³*Ó@!ÉqÆŽ/¢‹qhëk§Ð\û½HÍ i+AØœè™ê;Xi0ž¢Æ2M Á° ¢Hlk4MwB`Üm­V#ì²uœ“â½ÉÁ}‰RsFù­fa ¬9zÉ”Œcòá©2úÒ0öW‚zkÄ™Œ4˜­k_ ]ÇhŸ¦y‹hiûˆOš DhËb›iæMx¦^ÌV?ãù£bRÄó1Sù50jƬ; —_À1¿Î½5™Y-PQI¦Ç¾šÅLˆ´ý™mùÚbB‚g¥+«ìžG ÅFÞqÀâ‚È«ÞKÉ#›s2œš:v¾[Œ7ˆùÜå·ÙÏã· æš$Ö—#lo*z2Ì)q±UhWù&Û‚?!°´–Œàå= 'ĵÌ$šghê½#µLµ5räB†ß£{×òs[4÷t n”£„šŸ/뇘fXäF† »B»Ž÷Nr-R™ÔÄ7¾)š†_S:Š?òvÙàèúÙ‚MØ95±‘¦Á«/ ü<**üª.ò™Ò{Ý«ÂY¯^íÁ¯EžñY†«*dÇd Ü`º­‚-Ûf£j.OØ|Ýr±sOpóñÄG\ðQ¿áQaj×ÔÒWø‰|õŽ«°6Â]yB$yrª¾³Q,IÚÜ—°ÂÔZôìF„Z;rÑiÝÏ8r›“ýAX U!L%‘Õf®Ây°l|`}0òÎÒ]e‚ëHS3‘d ëmùá3SÂdÃm›õùFõ|ÊóññVfî…;ÄA!oj—¥M@ÕîyøT ;@bí^ º0 Ä·Ú±­œAP >gZ aŒ&µ)½w›®¨@Hq<Ú··.E¤C¹€4u»4%ѹ¯²Ï…"S)×L 5ºûÈÅxM{`…Ÿ=ÓíPÞ~ ïh¸ñL\zmöøbvã„«FWçÜ©ôºÚîtl%cjþÙZ7?ã*çÑbië*µãfÆÐ®˜¼‹„ŠO”›îôå…y—7Ê&tEë´öí^e ©â}†›ŽÜ½BeŒöwŽÚÓÎÄoĚʅmÌ™ëäÎp@¯ h¸· RºwH bDi‚„¤%0.ìb²‚–+DæYªÔÜf`jëò³¢ªÎkðo)þÎñ!öÝìø¸Œè³b$_É,LðÉ£è_Ëöç©Rÿ hš°2UEšÁ ‹N¬…ªhlììQn–fôŒè&‰òæbBI¬RL¦*‹…¤/£ÖIƒFMi‚a"hDë+m"ª·¢‹‡†äPþà Vf03ˆŠ®Áø–ìz˜"¿¢L•o!ÐàF*¢*вŽ-ZËV@§î«œÖú÷¨~™pä\©ž¿$Ö•¤^9+Б®HïBP‘} ÛL.І§NÄ€&L­­¸†¯-Ô8Ã_ãdBxåmLQiœÊÔǨVõ©nŸ,I¸_c:)p(QŒÆ*è1$ƒlè2¢(ë-Be@ Do²ôiB·.:#ÎUB Ë´âϺíì ÿƒ’çPj'øÜiZ¼Œ@Q·«â-Ž< P¨rPέ«ÖV”¢Ç¢ÔK¸˜ëp’¤áÍl¤Ä•ÑÔgˆ¥ˆÀ+<‰,°æ…öëhÊÎo$®gJÚǤQi×Ñï–ʯþõŽ%í..ò7 ® 2Úˆ ¢†ÿ‰ Œ ãüg ú`KVôg8D+G|HPÆËà [fpè‘ø@°˜Î£Øµ¯4qÎêåÚ1Œ¤ã ›ð‚±ãf¥íÐüК…"à®Æ“Î6’€omô±ÊˆÉ+&÷‘vëƒw Èò*¬°À"PêkP±ÆýåTÿ†R_kÉD+äοʉŒÉ%ò¬SÅ]0` Œ¨½#FOd›(†ärþ$%<¤‚ —ƒV$-Zbèâf ¶$"”‚“,ÆD\?H +FáÆ’‘ œ¾¦Ç&4æãp\2²)ñD²­n‰ŽN£R°ùL&e–ͪä%èV_Ï®)dÒË n2³4Ú¯q¡þ´áú$op˜¯ÆÚÉ.g ŽÕ@&ò' £ŒÛQ$÷l“,S,‰ØŽÇtÃŽ¹$üâiHÖÄÒÉ-ºv¿$/—5‚e?'ŒU†Lf ´–ìõ3´70³^$$ ëçÓ(J_j‚§–i&$;±ÒÙädЊöNp‹@R*PebÖÝ` .Y&¢C@}†$•ªZÖÒÒlfXðôB#Gç -æ#$ËK ÇTãCÈÿŒ±%¤?„÷2dï9šˆÃ’º&„ ¶'ÊŽÄ›1弆‚×”±-(4±ÄÒuãøL²vE-¢‰“&½.«StR”¶¨fÜ”‰e7aõ)ÖœŠŠÿ†Â2¯èX)¤1‹$Æ"b5ŒO1È™;#Ç)i4±¬ Ç!LÔ\PÂnh·l÷lÒ+éú–Q©%‹–.ëýêO%Œöi%å LÜÞÁöA#^~iZ% ÀIЮÕå$ “€ÃFŽÁ*¼‘rœÔŽ"Ìâo¬ÐN¸)TÔ˰B´5†¸‡ñ* âŸ'y1Bb$bê%̵R^Ç«ý)£úÍÔÊ!WNLâ¡9Lû\SªÐ)üðGt-%CÕcÔz¾´dˆdùFèR4àÛµ‰G‚K†„½,¯%Õ„ôe¼ñ•1T%á$b“Œ-pGD2Âí¦†v:cY ‹ïZòj4!TÜëá³ 8Ô%=4.µÅ­äÊô'0 ‹/1sÖõoF¼ò^É>$f¥¶Jš`©‘4©m®u-aëü™cYCId÷Æe5Ÿi-ª\6EWî-ZÒfÎÁD,nÔ"Àã‹Êh¤ –è}FiñiUv¥´FùB(wI.vA.*ªÓôK-ïsW85ã`$&§c^Sv‘ëZñ ±ON,©†…X‚ïE—Î(Ó®a'ØoÉ-.ü>6ùIK‚4e‘hÒtqvê`Wðó<.Zö,÷Hy ”äITqjNÄQCX>6æÛ0²ÍÑR‹Š[lviq); äÔF8É,QD÷/¡ôåm—l³&åeöl*˜Üs"v2ʼnÄÔiÀzSÆÁ“ÑA…ý7H‘C~Ñ—q¶T'‘A(B„¢¾»ŠloolX%Âþ5ÔgM|mÒ#ñQ5CKp[Æ1r¶[Ì;W„çtó!s*ÍÍl»K‡i {&éžË°–쫦Nì‘,+~8ËvòÃXbF’„ -`¢ópÆŒKm:æ$´Ó¡RHFóz´ªVÔXàòZ³žWj"U¼É·Ry¶êå‹%u UnÓ¸¤$Îû 'L£v5ñRMoï#V•8—²‡åÔo7ÖdÒ¸œÏù2¬Õ¹.pP Š«\+Ò\3ždYˆ^ê« ×^Üi×A‘/y!wEU(2|ý)S”·zõMdÇ&±QÚ$È@ô·ç4êOd2 Ǫ=p£V×<ÊJ½*Zå0Ç‘5ʾ‡¸]=ÃÌü«v¬JÚ·l°ô´h±ÕIFËî¼Z²La)NXÞµ@è¹Yx4“‡ws¨>ðeøè1ŽiYŠ£ƒäÙr&U'çÄ  EƒxâòÉŠô°§1Õ’‹K’°[8ô òÿ”¨ #}Ìá*Ú¿Ð"xÃY¸²’Eذì±ûB‹g'Ò¨4(ºÈ“2:´†°Noí–‡‘ ïn&é*ë˜×ZcD™v{¬l!™âGÊsqØýtØ®÷<ÜNÅ“å7bbe‘ѨŠÅ¤¸¢œ¦S Hâó1uK§Óy³ã+Ô–¼­xÿ%~ÀÕ 4ÓªòëeÛŒERˆãgQ7fç]*´üÔK o+É)áú£Ú0­«d*¬‘™’8Ñ4i&1P“„Œ¦Œé X"òìUG‚e­wì²K¸¾æ’M©™ë•ªËµ@ñëê"„šŠC`zÓš VøÞ2~Ð2¶xNœ:žÑ­ª+Lò×÷X9*y úH¶9/QùWÓ83®í§ØS{=’€)â”°™n‡ùž]r0¾p•i5ø!­`3@j{A^oâZ=z[‹è„èÆ…$š™| ¯´´hV„µ×D)†hç$k –˜Îv*ß³9!—&ÈÒÞmDçY£w§¥kgÇŽ ¥cÔ’¾¦0ÃÎ99âŽ"•m‚Nõ´jòÿˆÞöWU±»ç€•ñ±be CU…ú1›{ @‚yœBœ"°ÿšuqŸB`™y ÉSŽ.}5µ옺)2ì$ù1·‡±—<ú7Ëc:yÄÕùfáåί;oR”µð‹5°M4é Ù±°ôEèRÁö»I‚)U®»ê4ku•¶¨¬$çk¹¸,š½‰ÍšÀ ?BÏ™aòíGÒl-mÆ 1S¥%›g,l…·ûâÉ–÷ý˜xèíE1BÏK Ä_3›µÀ-nS›ÆYh{¿ÐÝ8¾ê*Øš»£;VÊ,ÍÝ À󿼤Xs™¸âyÞˆR«çÿÒiž‚[PËÜ÷#‡‰$<,xÔJ'”­U$ˆWCËPŽ&®8(“:õÓ5ñÕüi±ú„3Óª%óŒ=~4ÒΘYrŒ@H™°ÊÕê|çA4»ZÐB°ñÃÂáÚé™¶ÜâVÞUÃúï]‚çn³½:”‰P«×Ë0 B1~"Z%qRô£^Ÿ< nj÷-ÈÅ7>ÂïÔÞn®¢û:æ’P²Ùš¥m²ýhV³MA¬ýª2Y§é°#ãYt€ùÙçŠæiù€uìÔK†cqQbpìö<Çç§s¨ôªUí×ðÓ,ba‚4I©óaÒ'sÜüî™såµ¢¥(„àB•·Œ<-ÇãÏÎQ"çc@ÙküÚlBùFŒÅ2¢÷Ý\2Ý›͆°–â?»Ò®lÑ–¤sG%tÇCʹܹY¾ò³e®$çÈÛȳ$LÒ_@Ÿ†p¨í>! "Ä^Gõ³©°nv*¶IÞ³Þçbºîùíy„;¦®±ØPÃ"-é•8íséÙ˜-n]øÖEƒY¸“¸zÌVÌ VÛŸÄXòÉ, øþƒ>aHP‡?b¸(‹AŸÏÈÐ9F!Àô ÿ~ÆŸ $zÄŸqè 10ÍÞÓLîC&“Hd1@4pô£J¨R‰4’C3™A#ÓÙóöI¢Q$2J\ …$šÄ¨‘é:n}YåµXµ¯¾ëé… ‰$¯A©³8%²vF$–XõMûY¿Á¥SðD”cdV»fÂUD{÷è’Þ\¢=’ÁE¡œà±|§æâÓ7ÇÏš–Ñ&·üΉŸ¡ÉR0–¤)C¢‚7+iúÙ6o{Ì›¯‰#¨yÂj#øŽ=.£Ö˜AkÒBÉ$hÊ­8òU6ì*ÿ"zH°¢Ëª븮Ќ9m–½*Lê>gÄ\Ž&q™þõ¦p3à+¬;“³I à€’KÖâèÂÊô¶ R†Ch3L…(Ò0Ç Ï ™¹òL´É¯[Öì>¬ºÙ:½ˆ܆HìæìA4#»!¯lê“%OJ[6JSlX‹%I„L‹$Ó24–ÌôD*GèQ''³@«€s<œ¾UlÃlÛ*ÈãïCµ {HÛUŠè‚& bJ¡RÚ ØrJI5ÊiDzˆ3Z… &im0ÔÏ2-c*‹fì3ñT§k€0­jJìÃ5!K+rQ5¢L¤£u›4’& jQV«ˆ¤’Œ%L#ß;ÂÕB4Û6Œ‚8·¹Hµ<×à$€Ê°v]º4,ÂQ…6×ÚÉ(Nr>ƒ$Ò"5Sq=HÅ Lkåi3–Í:—´hÄZZÉ` HÍDòŠ;绨ŒGˆ¦G =µÅY€<àÒ× Ñͪa˜@”K "ù¢Ú»(—Jw$Æ+¶:÷ÜÈ58ß`H©oÔHņ­ëPdHtŽ‚:ÈÖ¢–ä'äú&íÀŽRÛÔž‡pÏø4€¯N§Í‡öf~Îúß\ÜXË…^"îE„kN‚i”¢`‰dvü‡2I&9kI´ÉùDí…Âçq¬®ÚDõ²lIŸ"Ús]i÷Âr2f‰Rò"É‚øÚ6‰6Éfôä:„ÝiG ä¢ôNÉTê½æ‰|‹Ö;½ŸŒ®ó¤ÎÚô±?"‡:üAHLå<±²q™3jOàü&´•Q˜# ”â9Çè¨ä¦’VI%¨Ò'  L #Œu#åœ0GþÕS»~*¹8-õÀ¤hL}ö!reX±7mnéiŸSBd‰S´GD1W¼ ¢Ã>RäEé§îäaÌxèô‘ƪh\Šd"½SÅæØÔ‘ÙK$Ýu€šÉ‰Cnkär"žR΋Àzh ¹´Ï F?°L~›‘o1éܺ‚ £"úØô_Œbô=Lñùli ¦=V¢âä ‹oÙv‡ é0$r7.mÁ¤>¦ÁT”'ªÖœÁ¥”fŠ)K7^CœÇC‘„Ž$Î :ßdÌ q@÷œßÈ⤙n(¹Ô®zæªR lŠ3*°bà&ÄÝìÊI‹5;#% ÊHZ¡Jîù˜À—ÖU£È6r*mMò ÍäÍ!Å R;Ħå×â$MŠôjE#y¡gK±~£Vrçá,±ýÉè«@ŒÊìc¨r?™§|½a’%¤ª«uØÙü3 &h"Dûî,ðXÂW¾åÔŒ FI€Eø Jæ2J^çíã›RüöÈ$%X!²5ŠdJ0ôl‡Rµ!T( #UG¾°’jÕVÜ ]F¤™»4 ¤BœŒ»ž5ö©SЦÏ@$z; ^*ÄO'`Í\¢ïþ›ª'JšÅ4‰ÕeþÁòI“ávïøŒ¯øe ¬ôE£ôd²ôI »-k–ÕI¢fÊÆ¹|pÄÁ»9UvDÈ¢b£Ekš( 3³±7Õg~vÈ4¢ðérÊõYˆaÔ?%M²êÃRª56Ênd€ l©ÉHbÑlÖýpn˜òÓÄpñ1Ï" ™ª¹wzG0Ú(¼Ì¡ÇkPt‡Ó£IwkÚ;¦³1<:ÃôžäPŠ?Ë-?ƒ)²áŠÍ‹:°*é^?Ʊò®€ ?,¯À“•üÿm9vºÎî?Ù >ÛÊ'yOßúE›=,·d:¹Ü-~RºÜ/jƒÙ»€jœo½‘‰D¼¦E³V#YòÌÐ F)úw%üõÆgáB<ÑÅiÜ–É#x>§¾ašû†ýQ«‰ÔÔ&¹¤ª±gŸ»3݉W²Ø–ˆA$2©Žâëpç¥?§ÅŸ –;õ±@Hµ³?!×ù´,5æÓVR•dáQ‰D*ZÇrð3dq2–W輨l:˜~(»Ñeö¢-I¶1Ë8à³a“,K{Lx Ž*h#‰ ÇúÍÀÇñÔ#nµš™T”i wÆÀý\´lr­àdg¾Ÿk3ôߣד!›;yõa3VªbÏõ@u„ðE̾¤Ö<®¥žs´wŒ±7·¡»žºÍV @W|·é?HÐÜÿi#§¨qÃeβ˜ŸHÞš~µjªg“£ÚŒçÍõ’âì7‚Y‚„óO_*éEùP'u Ý1ê"Úc»;Ëw•Sj:VÊà ×g\Kp§=Lì7–¢l¾è‡õF‡™(?JéaFqïÛ¦½cKMž‚+ES¡Y%–RõišJ-›^ÚW—”NÂÁéN"ìv€¡Å ¨4Ķ­–PØÙEüØWĸxjD ži1"gøÝt *@•½T*C…^ E˜®†1°e§¯!'Ùås€YdþÚM«ÀõLõ±M¨Æ!Ìlœ“TùVáŸRâo5AJ⤪8‰-úª±Òi­új«óz ²ãœ{©¨ Ä‘©ž@€²bA( >ˆ«¨È!Ó°9+ó!!ÙÜAŽœ›ì:®€}hì5€ ’"º¨½q3²Ð72-«9мÐ~Ü"2±i¢€˜A¸ïûì€#x.úÐ/Úc© ”»ðˆô, Cƒ$õ6{S¤›n ;m´ ¹°b+’¢?âb½È¶ÑÈŒ›œKà«úb©Y¨Â&¡KN8[Ù¦:7y‡¹H©™Ã³Ã»ˆ²¢NÀ’ó€ ô§P•&ë• )“a‘Òˆ4! +“ª»ŽùÄ´Xý)© ;b‡ÒÁq‘±€ƒ4Y¨­ÓϤéÃ;‰§6 é…4t[X³aI9ôšÀ!“"•ð‰B†¡ßZÂ08ÀÒ6lŸëó®´ZÆ`Ž`ÉcÖÀ­éXˆjæ.àç @”;”âÖ +1“dQ“T6-c…;Ñ%$zk¢|Å8Ь[§ZGú “‹¼‹`ý9Pê3‰Ò,ø~ (•(|FžkRG«h» R®¾J€š¬e˜èÉ(P?²(î’“´Ã'°º¹°€LŒ¥\–¢R¬äc%Œ´`Ö¸ˆÂG|MG$/‰#L@*©Œ”¦Ë73",%º’¨œ2мó7©§û)Ó-º=B ½A3´ ùÂF|²8SÚG¡ZG°ì#BìS§ù°5ÚŸ“5-û*@{i»¢?lC??A3,’äy°j”ÆKI\ Ë¥´8»qv9tµ*C‘?úÈ1Rbû¸ªƒÂ.šÕ¥)ÉÆ ÀÞ49ªÒÕœÓ7jSÇ•$­¶ ÈŽZúÀý,‰² lNž©oÉjX3A!Ô!„ 'ù¦Gaþé¬2ø„;b귈ĉtBK'[+’û¼LSí/ UL¤Yú@Lµ6y˧ø™‹) , ˆdi óË9¢¤šŒ®›SËKXÌq¥2¬•EƒŠ¢ˆ ‘ꔄ.€ˆ&êF"©s‚óÊ0›®‘Ä’¹èŸ¢Ö«äÐÁ*äJ!2½:Ô.BK˜|¼`~§J¯ã˜EÚ­„9ˆÓ–H3‘BŒeœ»­¥s«!D²¡Â7ªªÑùv )£ÃÙДzçÓŠL©¼ù†Püh­¢#AÂY…iý `ñˆÐ–?#•,R®‡É²A,ò<¢w’Ø¥ZD&=$¸ŒHKD̨™0¡/P™–Q”»L@˜ °¹ˆ¡›¡ ù3kSC…J‘i‘øú*¸‚8˜µ‹õMK…7Ñ+¶Ë íºé&‹âȼMCäl£ÐÉ9PШ ¨MÓçÀY3 ØÜ\P¤)·qÆ)ü~¢Âæ ÓD1Ü4Œ©ËʳŒ$1*ŒÛ·ÀúÇÑ€§(8ÉA»»‡ØÊ ‘¨´zÆ1ã$Èãù£‚ABÔ¶9j$ël´›½ÑÅiÐÀ°¯€‹£¦—ù!Á\$J¡R´è€!8Û4œ%´o>1Ê$¹QRÐ*LëŸS¨ŠBß*„2¹$Xw¹ß2B߸À·Ö›h°òsÓQš²nª¬L§XÌôÜÆD¤9Sç µ;@)ÙŽ»j© znœÓé-‰ræ öÃ]u¯šÃø¥x—û§£W¤êÛËãˆ9H6MBPy‡üÓEgÑı‡õ{›!63`J b©m½DF’°äj¹|4»âPšŠ3‚°Ä¥HdãTláDð§}oÊ¥•ªÔ±AºF: ô  MnRŒ×„œœ½ûáHõÈÎdyÁ‹ä*‘Ž •0‹aÃF3¬ŠœwVÜ…ÉœÉZaj.“ר [=e®b¨O«¹³̽¶S†Îƒå*•˜HZTëãE$&)ÂR½¢6¥UË ÂI¼­;ÜŒ9¡oÙ%ƒ–ÔDO9%G=Þ™9$NÆ:ÁÇÕ=ÇTk"8‚73GÝdœíÀ°ÂÈì£Ï%üôÀŠ! ý>Àý-[(ôDó3¤Á Ï™¡ËjÎÊv s‚v*‹‡Ýá“„! °Ó¾•ÓÏÕÔÞ³šÈ­Ç9þ<û¥Û\àÚ’Lšƒ&ñ E:YB‹¢ØÈƒ'0XÖ–×*”e4ì^Z3ˆ¿”ÍÜÅd²¢Õ –ÕÔîá™jMtIJ3`àã*%U•ӱޱåoI}•³|a»Ü‹ªÕ+óÄ(*Jˆ¤õÁþßíýœòaÅ ÝëÈÉ)Í6|ÐÝ{¾éÄÃt½©ÜÃ Ò ‰5{ͬ?Çð•·®bÈÒ£ã Piäj ( 4´X”GHC,¢1Ó¤Þ2yÜ„Îê÷Î{Æ‹âÿâAvaÙªZ¨* }°Œ@Ûe™À¾WS«=ÅßÃ"šÆ§ZRÚÎC¹ùÆÎTôͽaP †,4‰ž'+E­RÂ×v}ˆáH«Ìúú8þZ!à "â2ßÕ€´ :ÚË*,®â©œ2‹8ãæPˈÁî'[³,áÏb_/¹Úëßù©p}˜U;šÁ/¡ÜÜì½’+<Ó‰ÕÐEå”4|õšÆ,‰"Ô$Ýé$»ùŠ˜ê/úŸÉ¦R’ž‹-L¦0ÝÜåç ÆÏC…á1ÕJ$‹9Í=œK…\{æ¾1‹ˆZa1£&ÃZÔ6aÌ› PÓ›[òë8óƤ콪ú Ë$›ÍQÅýÁ®!U=\-tÍÀ\Ûâ7R©3‹)>@ :È´³³搜iiIý,Ž!Â"ë›j N²NfÖU7µÔ}ˆ¢{ûwS´ë™Á$«âžª$hYIøk"?Ķ6õØjÎÈã{åÜS½ò—ˆt§Ðï°þ,æÓùˆSŒLÍa qâN¤¤#¹‹+<¡Õ 8T¼çR¬µ*M²ofpž•ï“ÛÐ*W“«ÀP‚=ðÛS=•ØûhëÎÙ®aQdÐD.’õZ€~ }ÃÍÈÛ`›DÍá†{7.6N“*)ûTw-ÞwVÕâž}ò¾§à ‰º<^~iڞŋ{•ÍkûgµŽÌ c Îâý2ÊP¤Ôª™ñ9)°üN›Ì€X+<ëÃÂÐÓöš9ÀÙÕÜ{kg¶»Ïœì¯E?íºÅú Ní”»YOÀÙ«bÿéù©LcÅûú¨\ôœ…æ–_ö€½ %í»2N’~ºk›R^²^;Úìâš`MHS°É1›p‹aHpÙÆZX·€oŠmØ}o'{äÑ%eëTåÛækö¼w³óÅÓ«`C¦»˜Ò ²±ž‹°Úþº:Ÿ\Ê!êŽ_F€âw‹òëÏxó±4£üØ…®Pzßa6"ÝÙg–Ë»£ÑåÞÏ®œ%¢¹ÛŸtçk±\{){3J¤¶V¾Û KIoÒXÓ·qêá³úq´³Ô nÞ’o=ëç¨ÞuÅĦ—±ZNì‡GÄ+Rd>Ûtl¦xI—<÷¨u Á¨ðˆ))ÿïJVLVr>ú ’ÛX÷`äì)åf᪠ÈÌkH}@ònÌ¢“ùð~S&iÉjRoÆès-¶4 A¢åÃ>&Áø:€}Y̯*û… Q \lÁ_fiy<îµô]™‰[ÈÍqî¿n}ÀjYwB‹-hÚ5ôFŒÕ{Ÿ»¦ožùqŸßÅ/Í%”¢ß,^ûáb%‰ûÊrNï1Xʉ‡*z™¬O8ea´°¾îp&{ˆýþþ‚ Ð(D Ã@ød5ù~Å@Qpf„EãÀ(0&ü‚I_Ðð$†C•Kd0˜n%Fâ¯Ù,º2ÅãrY¼Ž=Ñaº@•ŸC_TúPžúÍa²XÜl[{Wh zCî…MÈé€*Ø"Qa›Ègrh$ÊnŒ¾nÓ¸õ®‘Ç¥ó ƒúoy‡Ôe×'þ"m7Šáá²µ–';ÅCcÕ:ŒÞ7™Šß!9ÜîÃ.ÈÁ:zœ¢G!´Él7ÊÌ6£‹ÆUböiŽÆWºƒÌ/ø§i‘Îär‰œ æHí»×ýú ¨ñ¢p‰"ç‘Ïî0ÙÜÁÿ¤–Ë%½‰l¢o%õEd¾z£%俼À z± ¯Ðbnª2„9à‚À¬ê›˜#Ë ´„°hº€6 O¸  ý„!@Xd!úÿˆC8p,úŒE€ (äuù…"ð4–5}¿¥R0¶5LeOèÔzA ˜%ð‰œ†} F¥ 8ìŽQ0˜Ã£ïÀM6G!‘ÇeP5 ñWœÈit9 Îrù°F¤3š]ŠÑ •䆋ŸÜ@Ùœ¢C Ìï8tv‡³H¤q ò †X24K{do†:0ú¹Oè1htÎk‡Hï¹ÏÇ@T:\ŽgR‚HqÚIVš#¿g4=}¶u‚j´³þÿ¾hnùnƒc˜ÈáÚ8üö›‡Hp1«f®[JÕ5Ò¬£ÿËÚ‹iß÷élæòB¼oê\L†~Ú#¸«DV,ô/›üç#hã<‹£/J ²#ëÃ.ª‹B®|:À*œ¨Ij–‡- {~ÂĈݥ°ô,•¢ @»ˆƒ7 ʑĀ.‘±ÉCR™ÄÐ$Ä.e¦‘ü4ñ„P²ï²²…*i+ ?î¼ ?ˆ:,€ïüŽÀ cª•VD’‹Zµ›.Mhãz¸‰m©qŸ V¼”X™e‹H$râfªD2õø¥½Ì:æá_4‚‡ž€UK/]ÐáijÐ¥Âwû3\Þ,$@¾ÓúC;£›£Ôù×Ô¨¥®è®ÉnvãEÀ ÎæRÄ¿«"Õ~ [Ú‚]:[‡êfû:"F¥Ü´*¸Ä,’Ùôü+U[|…ºàI:ÓÍ ñš¸fm±¼ÉüùÖçIË£ÃzwœÎŽ?ˆÁÀuÍ®ÿ-KØÚ½ΔV{jÔ"Õ.ؘ¾ÉC[²{ÒÐtÀÜøV[¬üí™´êØ ’"$/ÔR:„Ñ©g]EŸ…ší\¡k"=a#äçØhF)D?w¢‰×yˆ«Eì"eB¾à£óŒT¿Ò⥉›¿xJ•àÃHL6bA#‹L°†¼‘ÒštªÝ:-² eÚŒ!ñÈ#ôjƒã%…I ‹­×²êŠ!hŒ Ž£ya4Jäuœ(¤ËN*&'&]ªq3Û\ðµÇ¨"bòVÂSN‰?­¢bÚ -G$zÈÒñ‡ùx‰*ÑEÉ6LNLˆöT¦^#¯'c¹©KÊ΂fíãËhª-R°CæwW±%8§â=ÀF,è!:–vg„’™tÎÕÝ:˜tgy”–^ 9F&*=„kL8ĵ0¥5S©r˜ú]ÉZrÀý• 5?ò#ÉŠƒä)Dµ™‹$Ha—oä}÷N&N 4ÖmÄ8OÓÊ‹Ò4¸.ñM$$ÜKOÃo±†r#ô¹_ÌV&$¡q2r†ùG¹qBE^)© ?RáÅ‘žvÆH` \2LCð™ŸØïBÈísH‰\«9·6æêÄ/LÍ×U•©±tDÍC0*J™èSM¡²Pù¡W½6ЪôNÓ)Ô¥v…LTèvJBºÚW<æó>~QY:áS+º«„q˜€Z½5\„LÞ—¤&øè‹rë;³1QÑ2þˆ2Z¥Q‚QXªPhT°‹ÅR_8Ö8ÝkÓRªi©u*éÜìupÔ«3Ôв VpÑCIí*èû½h„œ¬4„ÖºV¥o0¡–‹LfW”:ޤH‰’3/ ËŒVÄ2L[»n]Æ¤ËÆù»E€Š ìsY nfÅŽ®¶u©7Sk£ïQjé«BôZ"Bð$]:fë(ÿr¨h¼3…\—s 7,! ȱöUн`Z´®¼Ô²:^b&¥)Ž/¥sÊíÝ;ç…D„ËÙ(Ow^¨޳„6‹ÂÙKвÚJP0 ¯˜™üâ¾Æw¨eñoŠc;Îwhù¹®O{¢)±md‰–g;e`í ;¸ŽÈ’¦ª÷ñèþ*Ž,‚²ÐU(Ãêˆd–pâ9ï†É»þ€9=KŠnœc冄Îu]dË‘ûÉo…"¹ÞÖ$õ¯Ùa˜º«—Dh¥>¡â|ÍÊÇES9û,2¨±ªJÉ©‹åuäQr7 ª©Pqz—ž#™{r+ ¢·uÎÐC§À#¸D(Çbó`¼È¶YШõBû–šˆe¾#ì¼äâ‚Çâð×$@nl]t>¥1*“% ¼%;ÙtîÞ/“Иé‘ôŸår`÷Ö1mÃUe!¹ÂË©˜áYâ!Fà Å$ÌÅ/rZž¸×¹ÚqYÒ!'byn‡Nx‘Šñw!ªÍx~)UˆJ(ÚÐMòާDÎâ¡U´oÉh~N-m”üÔ:–ÎRÂUpH)µåaëLÚ-vc5:¼¸®èèC/ö2S)ÒÃ=ƒíINû»5T¸½¹°Ïñ‡â‹ñÍã]˜á“JJl7—NîæÃÁgd"1‘Ò¨û°ø£ëòZÂü ¬Ê<î7=+B'ÆD5.ˆÜí¶ sžeïºéÑœ=Ó?Ëu´¶mà^röèT†í,áM#ç$ª¥èâ`Æ€,RwU?iì/4–¼ý_KH7RäcŽ^‘ü°ñ“+VÊSZ͘²&ªz ØÂi°›4ՓЫ¹ ‘Ú\{ä…Ÿ³~©ÑÊ-eW¯8c÷>+—½ÝT‡rViÿkgú¢E.MÖЬWÇs¢F–<ì੔$ÒnÇ ’ûéÞŒñ wLûo;V®®†Äš4¼Ï®ÖÀÎ#ìฬEÆŠÆ~M¼å§â#ŠVïiÞ¡íºX/dúh(W'Œá±”¦Ó—6Õ›pš…ÖRÏд/³FY00Sê†ÇÑãNÆñÂyî×FGË `ˆÒ€Sâ'ÉÆÃ(ÛH«ÎÀ²!Llôk’Ñ´áKŽn÷nŸJ-è9©&1}õ·(Ò8©Æ`‘Ñ"±QA´æ ¾(¹33ƒ< R°‚8ñ«G!³HVn0m€[õúßÔOêJ«O`UçA‰åôÄrî(3HôÕm5Iˆ›£CQ›Aôc&)hT¤V¥²­ƒb…M(­B06ZD4ò0‰3“Hã”P3)+#/ ,¶ þ‘9Otª{^ë‘ä{fQg˜_ÌLë¤!ìV¨’Ш³;"àÕ¤µ4‚dÆCQ·R‚ÖU¬H”êçr®­+ÎKϯBÍ~í¨p#N8§DÖQ-?&jØaÿJ€ ]Ñß]cÚ†,HU·bìÑEˆQ2è-a&hRÅ[r*#sdsþò’¢wm€1Ê1A¥g'³V…Ý1h"¼èMS;Œ WkBFBgÄøwcQl*DUTdÌØÀ3 à2ý{ÏÜmq$3t9XJÇ0n¿>mAX‚S4êQ[)ßî57¥'lõòt롟7¦QjKnb®ÝÊM8³Y ŠfÑd-õI'k5ÇRPq;DïJÆ;°?Y÷Ò®OÌ~ÔtÃ&Mg¬†þ‹ £oidbÎiÜ[ÁÜÀ¬3Ë@Ĥ¬¡P"…yð¬°ø$oô¬*—*v_hºi=jé‰>Êî½Ã7VqÄH…;!ñv# ®%K‰"Ñ(_–ü¢§úÃ'rЮ8P2­=ˬ¾*ÚÀ¯ÝXjì¼.kRîèmÌvï„–¥oÜ‘O#3ÇDX]kPÄ“/x®ëÄRÊuuÅ ŒÂšñª”.+œ4ç˜r^Ö¢k¦¿Xªxy3.ÑAòÀæ”SõþînÕu>­±\…ê=+¾à¬{¥ÊtƒnÈØèãcXV3k„ Õ¨ÁÔ‚DÌøÉð„„ùx‰œûƒç4hxMJØŒå×~:túUbW2J®S‰¸‚’ƒðטU1'Nss£ 3 JÕîõáràì– RLòØ9x¼%-Dc>1Ù4.9&SèÆÌ¯åð.)V˜X†¼ä„›ª*߇y…ñËíCNÏu´ØêÚ7'µ<‡žÐ‰Cu$› =†ËàåUœmW–›f#sI r1•‚~Oˆ°O+ok)é '9$ „° !·‹1wDÀÐé/êɔЗ¢Kn¦¸ÄÄCPP¦'ÈßSÏ„¬î£ÔËÊ>ϧ–…¡0e¥ ¬ƒCø¡bØÁý¯bÄ—ð‚{9»‹WŒ+8¨€9ÝZkÅ=´Õš›fpRÅ› Y“qé‰Ù•k C¬«1™ùʺfqS7›U@›ˆØX¦L’j³Fv7øQ-ו9d L% å§ÓÈ»¯éA¤ùE3Íyáù“zC±WÒüÏâo“.º&>Êešª‹mCP¬¤$»&ÈuU|1V-Ž×„Bó׺ðOí¨€Qš°ôô J\SF;/HCXoè)Ú¦„íQ>åoÈëŒÞUס[*©V+5ªþN—È57ý<­ç>« ù½[††Á…¤$§×d}¦jW0bÐÝt¤¾'Z¸O®˜U"(9—kO=¹T35³“”ƒ0û˜ZÛQmxBq‚û›ð>dÎÚÔ¡©,Rî6´«Vt›H•q„…´¾ºHIzÒIy>mÓMXûâõØb{‚ƒxQ§iLÇ"½4”›È)A$/Õa™ Ê‘%E,Aô’¿KÎ’kè!+*0ûû|O™/µì 2­Ãä}6ÌM͹’75JF±înQœB¼W‡Zœ\ËܽD59þÖoÛÅVÞCéV.ÀµÅÎE Ö.¤ž+«§Á¨|ÉÅÕýƒKÁ—·ï[ªß j\‡¯ :^‘:ÊòzŸ3ÈN¡¸ #„5«põ$(Ú†¥&é{zƒ?©òØÊ¶È#äڨ̓´±+β•!i|`‡ªQròá8hC&Ä!(j^©D \v¦©M|x´è#⤠ÍJ|©-Hó6‘HˆzD¡Â°ªä™6ëzf¦Äò̺›ÌhRE'ÒhJs08̃a5»ˆ|4Ÿ±(4È ‹.¶ ’Ÿ>JótúH°‚ Ëï¼êJq vÙÑh#K>HD ¢!±Ê@ HMQì:~ÒÀ¾)¼Ó6ÉsŒŒÿ4ŠjoÐÕŒN 4HSì²½‰Ä‚(ªtíRP/¤eSÒ °QèÚÄ‘5ªŠA$ ÒU 23=Hª,µ#OíÅ`„)Mmv~ªU´“=¯ýe;ŸïÃò©\ð]Mt2ñû/5p!ë˜#“êRîºÉ:¥+‡¼®ÐŸ¯4”ú§Ê  bu}€´ÊÁè#º%é>/ ÌtYôÝ‘fÖ$w¤uí-Iç ]PšÚ…]ˆÜ6…aGó7Ul§%ë[èÇÃÎ ²³>iMŠ^/cMy¼ÕE)¬O÷UO¨‚“µ®´n}+@UF÷8 Â…Ux”Gp­‚/Ëý?ão8‰0[Ë ¤^ù*“°–臷Ï}~åÖ |zsjSòeÙ3gnÖj“‰*Zp©jõ}ZÎÆÕ¯Xý\«XWÓ y2£s=ÀÍÊ+’rU™x9è}¤Ò€vί3$S.ëlÝË€…î¶eWu¶eÃ.ÏLÞ ÂÏWÝ_dÒ¡û\uûÖÏhÛvc­|Xð w4ü¾[b F 8Ö¶Îj¶QJ–¦·¼LÏqEtˆb4‡¬CQS#„)ú«•%Y‘7l 1›¦•fäUÃÍnE=4‚$‹Nòü$i¯â§Ð™—`CÕίh×IBp8Íx¿6úíÖaNc+¾³'(üÕZkr‹u?½Rb¯sy9Çð%¸¢¼ÍœT!N :Àcáy®y$ jâôÓÊù¬X¢ÆöYN}„½¸"Å ‘èP ”ÒGÓ|_Q±‹pËŽÒhª Þ=ŽˆÀ òM,ÜÂ3tN¸ŸcfVg™ù¹B^⤒«ŒR5T—õV@<¤C$y³ ,V¸üi ­ *NtÇã0‡¤É_+5ºáKf,‡YÔ¨B€ž+3ÒÄŸ±ìç›@ýˆ&‘±)øÒpÈ\€‹Itë;ùÄÕœ½#)­£"†°W¤c•‚0 ¡Ë¦Í”³Œb8;ˆšå›/ëu¿²^k_YMR±±Ó˜(?ŒéàžÓ¡ê0wæë‘*æOö ;”þ›’¾‹¬0—fÙ(ª‰P Í?Ë8Àãxra1'ö?Ör–Msá7Æo?ÛÊVZ $™s6ª)2£ÃñáÔ9û ³U ©ùšØ¼!‚]0ó,È®mâœ9¤)jÈTšIo*t~1×`¼]ÄÉK´.œ^Ëá„¥±”}¼37êÖQÀW±t‚¹â^&SMáÒÂx¨qÁ©‡ì À:Ô5BE4—ŒcÇé8DbMò1ršŠf6¸X?Pþ@‹gL­1l•ñ¼é׫ƒE5¹oœ‘$“*ÆÃ$“½®¯ªIRCä|µš°XÅ`kÒÿ\%A|\YfGÇ=uèz,þ´ªãÚÆ ™/Pk«v•©SN'¼Àš®O PÌ´K眢¬;Ø~ƒ º€P*Öú>@›Ì}8ÑC²:Á«êDØø5ƒ*e"²™Ê¡ä‡·º“‹^»">»=òz X£EØ<Û1›_ ž·ÃÀ^*…ªV8é àOa«Yå8d#7t¡ßüÐËêè4¸¢eí–žçk[V—uÃö?dé;{wO¶er€X¶M缞^‰4òv-Æé5Ò™ÐË™‚ýª­.­¯KÙ–åÐo¤Ï»>¿c"ßvÐ PiÌ{ªt\ë<|I 5ÈÓ]âb|•WbDÖd¸uÔvÇæY višnU ÑîdvdǼ7kl^Œð7|ÊþÕ!÷®¦?‰‘ýß)""ˆåí<»kçGîÒ&o†/:ÿ;UY§Ÿr¤¶+½¨ëœ#;ŽÙ–;¥¸qâ0K ³›ñ¯ÒÀ‰¹Ú¦[Á–ëOµ‚s§k¿Ó؈"[ ¹à¬¬ jhKI™;¬ ë/°+ þ«|–36€¡3c1ã’Á8*î(`Æ;!P¤ì»)Y”ûð±-R¤0‰P¾+pó9Jm,{ñ©"²ƒãûµ¤¢> ©!"ó³x²Ñߦû²q\&œ/bÌšAQ™ [O»XŽq lˆ«­ú´»ë¾=R0»kôAÐ…YÃ¢× ØÌáM0K¢2ñùÃ’ ‡Ø¢–ÔKB³¾.tD™"²Ù³¼Kå­aô4²kDÓEKÅ:›á¦`Ù´6•Âî¯81kª˜®!ƒ®³à“Ü’§ü8¾ó—4!ß6â.Š´/Ì»%3%¸Ù ‹æ–UIìþ4oÍ”2²,Ø*4p³c¾Hõ(F«¶Ó)øbV(Q®Òj¤Ïüzé±JÌÖДp?òþEÒÛ€?«¨Ñ4³‰€‚Oª³³ëÄ,P¡ƒw";­Ì’½ÎÑBÜ ¢²¬BÙÖ]l£"eÇù ¼ RTéÌg.ÅNõJaô¼£)“ÐäVZs¡^–b×<ᇠȅÐð¬­ í»¨¯ÉqF¢Eøƒ‹Gœƒ¢‘x™»õµÐňAÉVÃä 3áÓ{OEyQ·ª6421܃=-Ÿa—5ò’DDm”ÞÍò€yÏD<{@:JÖtUũ›lW?ì¼ã팫„0É9Õ€Ú˜6ÏÛ*¡Qx÷+s'ø÷3J†Ã[³{V´Qä@²8[Cµ|Mž&cÍa¤Z±ÈÒešÂ1“Y¤L´Ô(Š­DÇ2,¬ s©ËEÖ½$Qã—iç7¤W;C[= ;Nš†£ó-eÉW»¾\éc¼Ì4§Sšð´ÂÔ“];SäGÏÖ+º j}ʵ¬«èçYÍœ9:ŒSØl}ÁÈíÀÙœ‹¹1Ê$¼2>;Õ]¾ÂÙ?L€«Õ”L ƒÁËðÒH¢mÏíiNÞ¸‚z'ÌÖ,˜”Ê\~\:Å7䮼ø‚3hê_؃=É–Ö]« Ü^:áZ\¼i80«sí à›£sª7Y"Ñ™ánŸ e¤×^l®Žs¹#é4: ʬ©cMÉ­QQ‹Æ3Ã_ H"†ŠÂ“­¬+\× $W$¬+UÍÆ$ãŽD>öatÙ6³ÞÕ¸ÓøŸœ œò·ZC ÒadDOȾ1aS mò¸-v`*>@—Ü#_¥u; Í‹ V" ¦ ÞÔpÞuŽ(­µÞ¼V0ê˰ðó:ÚT´×AÂôÍâ¦.Ó#¥ÖähÞp¢™2D§ƒ«£lp©˜cݶÝ;¼˜³ÓÜ<éA£{Êmc·8%$'EYbã„:±±,6]“Óˆ&R¯­©™+QŽ´N¦êfFÉÊÄQJS@¶qM¸¤‡LÕcÀ­•˜¡ª Ëž·dÝí è_*˜«0pQLª^ùùÉÃgc¾#õ~Ä2{Ÿ|9Õà·HUCK2A^q!×4Vôo„ô>PÕŠ-[ÍHÐå&¡ƒÄÃÛ–K?»¤ ±éûÞa— {Ý õ‹Z¢ Ìeé=be¹Í=œ-jʸ—ޱ+v)Y;ÆÔkê€$thõƒ5"¥TNNi#¸žúŽÇ)bÚ\£|ç¥ÝüVŒ h50Å;®ÐIl®§Y¬*æ¨}L°ý².@¿˜„ú›Á?ŠDÚšƒvÛ EEi˜Ï]ÍaÚá]{@LÝêÞĆ8#oQÌ%ÌüÀ]‚€9á²5·jð…³(«A–B%¶ßYÂàˆ‚^4’¦U«Mº WÂÖ3ìÖhÀ˜Û›³Ù–ûãZ.Äy¼ÃfÆÒ®Ku –:³ZDÑ#œñ9ÞåÞеsOé•М›€(ù+Fl} ÔËQ¤ÍÃ?TI:Fˆ/kÆP¥Œ–d½`^HNTçX¿íuFËl•0ž/6ÛÐmcè¦EÎ0ÙáaÙµóX&ªÁè˼MÚ¥œ93¤òŠßè‚&ÏNíi‹ýû#eHšÄZ3}oX²Gx™u[·îÑÀæÑÝà:‹²Q§b°|æù«È;±ÑÄ®É’Ô ®8Þ)Øi_mpÊh&v”:)ÂPH¡“¦ö¤(ÆTdÖŠu»ñ9ƒØecI^·\e¸ì]¶*ø¦Þ:6 vŽ{éü`ÿ4UÒù#R¬ÅºÅƒÂ‰®œ>¼ž_¶ÔÁîŠ×K|Ú7úšÃHëmuX’¤ÀùjcHäÜð»¬Ç´=Û5{qg!š@±X¥h¿¤;¨¹1—hzÀ›U"†™„¾Ì#• Ü¢¿mM—æv7¸@êqxêæÜðÁê ¾vügŸWR¯àJÄ«/Ò$_b6rã9&r¦U¾r¥±lŽú=᲌̣Ë(ƒá`®ÉÓˆúC]b!¤ÒöàÃ]dÓ+ˆRÜÔÅÛIP÷g+O”ÓØz aEgL¸{HΓ“i§P_MTþñq¡XÐxÒ2E}3ÔXSý*u‚£ät<©u ¿1˜†nŠe²S+vø–:8›ÏE.ñø9SsM-Ü[Öåe×Û§HO³ïÔûª"òÞ’¼ÞõÃ/Eé2êV¤•‹þíCqË ¯ r¦sØŸc ñã‹qÖð¥hŒ”üÍ̳­0 -¦Q ²h 0P3VÓÏzsœ¸lÉöX^±­Fz)ŒÉUzìmÆè?^k þÞÄóµaã˜Í/bEN¬µôÖ‰«´F:ʆ¥(ÒRôÑL²Nz:‡i~:]\áøž:Qï0÷1ÞŠ’êϸ㣿ØÐI¥ékM•c⼄ró¿Î—ºV…kÖE=ÚMÑ®èÛÿ?å´ä•@ beUïcD…ÇB·&¬°¬ß¤˜šôÞèÂ5 Ü´áåú6ëúˆŒÊ%0Ç ¨Ü1ÙIüUŸo˜ñ¼©"ëóÇqöÖ†ZøÙ÷ üÁˆ”ÎWbÓÓ¨ôpЇŸíA³Oš××éqr$ ílp©¾2ò¤Vô³;%ßäÚ£å[§ÖÕüùÚê¥kd¥Vß›ˆöÿ‚ ÐwÔ$ C@0ø<<ûŠD€qxÄÿˆÄ Ïé%õ dшö5‰G ÀI„4}ÊcS(”掀fQ©LI)ŒOcQ©$j%&Áå44⣿æ“)üe,G%2H”ò aªÐ¤  º9h•Åàó#âå¬]e3HÅÂHü¾\#ÇäÒ”@®êìŠIp‰V_ñŒt“%g®Ëcò ápµR`™7ðE2’\ŸÌ«›A.×þX€ª?å: <ÊRùÞF·YužýŒh0à*àj³?ª¸ø¾r mÁéŠÔ6•™o3xo&%)ÙY(÷ûä‹q²ÅH!`nSí’É´’ áàD°òø™.ò¶è¦ Kh‹³.²ªø¬ š.À&I£¶· ¢Ø‚"LÆî!©êÕ ³ÇûA ­4BçÃJë’’=ìjÓ"ȺD¼¦¹üý Š€¥¤ÈÒDü­I“RÉÆÀ$6Š0ˆ¼J‚)Žj$¸4É$ ¨Ô8Í&,BÒËŸÏCŠ=ïã@Ù1iƒÄ®ÁŠ:DÙ9í“€B®W7ú½¯€EàšS7 µ4ÀUñI,¨4ZX®Rù—ûÈ®²7#©`¥Ô +\‹|ЋÍÑQÿHGhiÜ•‚ÐÇX`pó6R‚¦G"|†ÞXŒ¬ìÑoÂ’Z5 '«ÕQ—@må8~¿8Tå—IKÀHPæÂ}ˆl6¤iœä²Å›Â¼pH™÷1wšap)ƒÚ $EÞ¼(H%X/÷VD‰¯0Ídü´U|ÙÉæRé6E2°Z ðÈ‘(Bs]Á931 ÅX"Ecß…ŒøÆ×Øá<xÑ,4dµâ‚ `¡5¤n<@Îx|“(¼H™3Ñ‘Ì8ÉÓph ¹úKmÑl㆙žôsU±õ–ÉÖÚ#”/*¯9ŠDžßH4N$õ™Vjü<šiK•ÌøFQITæ¼>­ˆ\bSÌ ÇC¢. tìÀ‚àêØÉp$G½gÆÇœa´83qœ·„†Ã[»²Ž¤HÜ™I1ë!èÕÇ:f¤ãe «…`°#¨À°>‡$ã³ØÐòŠaLY‹¨¾-ifð€1°#ˆžš‚øÆO3Ó“$„•šÕ [zZHdÛ1‚AE¡ %*<†Æ)¼ÐÇéï4Ìõú¡Y&H `÷¦Çå=*„¹æó«™$ºF•f ÍÔ2"„/Q' H „ó<Ñ}GžâÊw…¤ ]Ú —¦ O m÷-zs–“´}-ÍO@'޲Ó«šÄ&eBŠXÆ^1™„²^´FQÙº7~49¨¡ùXlÜÈfpdš‹‡ñ"_*1"3Š¿‰Íh ÷¸¬_ZÆŽŒ52°kG$ ·GÀ‹VÊYIã—Äå#–†¼ÏhÄ(‡G°„“H¼é‰$ébí4¨¿Ö? k¸z„âw8E\i 8¶óŽð™!!)ÁЙZ@¥[‚޳•ÀœôªZ êäæº\é_„Y©áÕZæÍ¢…£YžÑ·*8ÞoÚjoîûÑöÁ`åµ:‹*zöÞ%aUÇìR‚\Ç&<_%èý¬r/Wk úê™x¢¦Ú ™ ‡ýYeòÒ"¸«~³ibz{U;1™U)§Ñz×Ksk fKÎ&1cÇìÿ`=’’0ò\È…Œ~­ÊÞš(ghïd³«ð¢˜çe'Üj1¡´çQ윴ÆÐæ^J©Qlîl*¯å:cŸjoüâ86þ~ši¦_ `ÕÏÇ½ßÆ©3šè£ó‰ð óSZmwZâ¸/‡z‚ãG–AŸ º†0é·¶;ý—[ôrI#íìâe¢‡¾&£yÞ,æYÖcDÁ²·©5±›ÓðÀºÝ[È7 !¦ážÅ%=•à#×:UšîÝY ;I9ŠžkË–•5ÏÓ’`›hÅ2k¼÷@!°¬žøºzYZrÓ8ÖÆGÈxßseÄÔŸI3±òÜW;j"–<úA8ÞÙ(@ü[ài©lh2D~DtùhkÕvRÖÜZY­aTnÕ„4ï2‚áLê6 ÒU?‹ÅIñ³IB¸/jäw«/ç$qÉV‘Æ< Àd‹…6æ¬î9lÂmí–dÑÕô ˆÊ&õ‹6DÒÇóëº`&Â^ÞN$´m·ÄE5 ‹!.šgœÜ§"ÓÉh–q—Z­Ð˪/Ž™~ÖFðS1 ˜¼¦K ìÚ·éDpx9ào©û§Ó[ùwvž[_×OâjìŒ&/S-oQ"‚O¹Ù=®ûæÈû"Z@“Ks Ÿ¬±óÙ7Zû—É¡!Ãí[ñ­ugéµ&¿D¯_ÇbAõ _ñ2ëÕTâD¹ñïçÉà´kS@”‹”^øE—NÓFÿNNrZDc©zq®Ü·?–Öµ¼¬Õw¯²^i3÷ˆh3˜Ž76K}ÞÔ¦’è0 Y¨$ˆþóq²3.P\†˜)–Œ¯ø}nöo.GìŒÍ£š7¤Ö(6³üè@•èŒÈÂz»ë‘çŒÜ쀢ji,Ók$"ïz}@ê®d2IPÎŪüh(ìÄ~ª½b…a†ªƒi¼qc$ͬRÓÏP£ÈR7!î4–g”9¢H‹Çh©àá H,ˆeÇîÄŒ*¤ ,ü¨yJÖÌ8b˜xí h6N(:fe<ß ¥‰ò´Nýl|ŽÍPŽO °,ÆÝéhÛ*ªòàNkÔO2´ª,‘œ]¨6`‹^LŒÐñáôŽªãIÆV+­ÂÜ à¶Â]0£0æ9Ž®\ëŸçX¨ ɰÏs êêZKnaö:‚1f·eèüè !㼬élÜjƇè€m óö ËÄd¢Lñª¬ƒÎЋ+༠Î8äÀ#N¼$màƒ(• "ÒL [®€ô º°|r¥ $ÄxÁLN¢ÊÆSFÜÍçxIŽn¨(ÄÑ0bƒÌƒ±î»HB¤ÒDì¶æÉ"®Bt¢Ç”x¼Ç¸åšvƒòÅŽû± 1alGm¦Ó@ï«æîQе ²‹ºíÎ m‹>Ìf>6."ŠÜ& s%BÐLrp’2îFþ pÞ®odr&!×&þ%*ÎÏJü‹-+ )ÎB"ˆ¼G½$KˆÄ†òvM‡ p²…"xÒn솗‚龯Îö_å0 ÂÊ2Qrµç- .;§>^¯ºŸ©˜€¥.¶dí…ÖÙ".¸«Šs.¼uiž¥håëóìIïÌ“.Þ¤Rs` %®OVÔ(›CB4Bî¨bD‹ÎÆ8ò:—(`wDÄ!j &Rœo,t-4³2¬l´~/Ò·Eài3TÕV\‘x³B»$ì(¨á&™ðê½L -(PDh2¬ãž;Íjóæxæ3 pOuLÚ'ºÔGúK00.°Ûª†/É®©8àOô"L*)ŠãpÖáê‡Sî‚!…àÝ*ÞD²±ò…#ј!#âûò{O»"oÔE ÌéhìdæoÔ9êJ\£“¯¬ïâŽàé*å` çÄ4Q` ‰Ÿ¤ª4S)6+ª\.P^û¥`ÿ( ’©É°¿Ц+ÖîÆý9Pü·êÔýÇO-2II ÙGüh:ŠSÓoa+Î2mè[ ¤oËðPÆà³ÑHå«ìT‹0‚ƒŒHnðXo/†+¬rÞë_CS.ºÓ·À·ÌJ]‘uJtž>S3+fK†2g£ù.c6x礀 K%+(‘þTB(„Ɔ‘@[%†þ„¼HäÖi*~€sžÍ±3jTÈʃ?DHItÌîKhQP”KÍ#3‘(3,$™Â8À jÕFÌr.õpsM”Ðcµ2mÇDQ¨G®pÒk©us%#ÞïrD$‘f#Þ6´°B–Ç.eÂ5@`4ËcB:èòHËSÏJ’ȰE,ÉC!í2t£â&Uâ}bSk̰§i1Iš“ÎÐë7,S‰.Û“`Ô˜#“@Ò#žtÏÆà’ ‹F˜€B0©U„Sñ’´lgWçü F8UFëJu‚2oÛÅ=J±H[b¬øöÕç#CâcP{LRp³2ô¦7X` #…É$L™AtP¦ë;²4-QêX?ÎëIuˆäkÕ}Mn*Þd¸vQç0iëóÊ“ S-ƒ`ùÓ"©þu¢FN#>NÎåF\¨4Ü¸ãøæ·H²Jâ«p6ãD4 ²è¬Y§zËÌlßCN2Š?”Vc/î!.GÌÍnÑ Voá-Âäž#Sig«’”.ï'ãÍfLÜ”LÖOJ8fï,` ŒNÌgÒS4ÏY0M‘5ÍÊÐõ¬¢Óúè >m†p/Vƒ§€Ç6Q5ÅCu”¡¢žôLò4š¦ Ô0±sqÿUÕþÓê‚öl±¯ƒ_ê8Vj¥„Ž;׺nêÖW¬„”¨ýhÍMw^Üåÿd w.A;‰è6O£U¦’íL×£x^aúè *g¤í>h¼>*ÆkÈt¯ˆP`ô"Ñt4JvÑMêkÕØ(ø‘õ@-OÓ³½BµWoBäý* 7ÃD6QÇc%½ϵ„ob +H…/Es§MNì„qF·‹3cpN&I †)¢4Ps—Y6˜%ÆÐ†‘$mõkÒd*µŒùvú¯Óœ”åBéï3öÞxð÷üo5>áŽäö 9˜¶¨¯^½T’Ù¦fÂaø×5Qe‘ž—dh!2 RûRø\ncŽÙ³’ª©l?7º”Ô£[L_BÖG ‚¤¤L~±E;ÌÄÈHt´¨ï©rcçJ« ÿ&9ãÞDup#xZ.æå‰C·ùX\3s›f -RÉÜ"sn+ÕAR\lˉC~g× PÙ£2¢ÙQ’j¾©èmå/Œ"]TNJYµ|øæÁ·žÜê*mAÐO/Hc•"êÖMàåÎqÈä5CVçÅš7L?ŠÎK(lxæ€g²Th½`âåtVß #AP2ê-CqàHÇ^˜Ø‡HÂŒ¬]:”­pñ6qŠ9LûilÚw¬õ¯½ «FÃBŸ\æ»q㑆áIbWa:ý2AeÐÜŠ-XµÑy*ðnªkÈ›ÇòÆÑQBf{SoOT3!Jiå9MŸµ£M2xq÷ºWr4žñ ø× Gi£±‹(ËgI[™y _‰x";âšú4´o3r#`©/5’ ë0ïZŸŽÕqMv–up©FQ+U0OvüŸn%$Ôà •0ÞÎd–’¢ÕaCVŠNÁ6*v#¼î‚È:i™ cC½6Ž:£¸Ùž¤T…Ä–´¶TSÇ€yUú3.HEÒÈÄ„y‰ZRói,õšãÆ>ŠCâú@ÆB)™Óá{n'NÂa@"ž‡³_š®Í ¹rý;Nh“V€Iû¹¬²ˆÿC­àöÁª¢ eÆ™VImQ¦ÍuTÌJ-Q§*¬gw $–B¨;¢ÃD×× „ûí^͘”me uxІ#ÔúlÇ-ÛnîìM_¯`´/)M›×"œJ·å`î¤âéºk,¾Á™X­g Y1‚»X·§¯ÎQZ] pIÍ$ŠV]·²”åÅ¥Ž­É Ñ%#¼¼ŸO€Áz±)L¸öÞB¨}h'Ç5³HœÙ¥|Ï;Ö(é ÉàE;ufë¸úkAøÙés˜¸ðËÏÊ© Ë”N¡ËHß)ò–Ñ»‰ÒrµeÊÜfÞ‘ ¤vöþoE£p£0TÅÌ…°éByY³{Ì ¬E»—ø‚à'µÌzÅ#¨i“V2qˆË— ¿i˲z³7sÍ4tÉ–|S œÎó½÷ÄFïb{.‚ï×P«FY»r{i™ûŒN†*•Dâú`€(3þþ…!Ð >þ~ÄàÑP6ÿ‡Cã0Ø´3†Èá‘4ž2û•Db±Ü>$‘Ça“›ô9†¾g“ÇÅÍöõí  é‹Dn0­»0§iã‘¿ j"Ö9@à«­cÌÖ;ï2Ê<ΪìŸî˜¿¢lj‚í+à2á»Bì„¶hT@ÎÂé#Æé¶èÊo ¢ªBºç4ê2^Ø2ʪ*›Âz ªªT6Ê'Ï“XÛ­çüН>.’ Â¡‰ó(ÜŸí3O=èT`®àn¥+ªS7¼Á Gè2dõŸé»|ȺòÌæ‡©Q$Ü‹¤‹k)! åÏ#’Š#ñc®à€Ž¹µHC1•.ïºÓ, N*çÄÑ´.+-Jqš'³è«(¶¦r䪩"T¶Ô‹´Þ³Pªªë£-¼vÅ!Kó?=´t&Û½$…AÍ<ж Üâ›­®z®žöÓ ®ÓÒÍ}:»JDX£)Å 7ÃÊ_N1Ä= ¯RÆÍÊ£M £\Ì;õ"2Ù^—ZH®Éµ3ÙG'â‘3úyd¡”³O ª‚!©¾,ŠÒˆ$RRТ_ ¼ÑáNHœ†B£¾Æ× ë<¥VꮘM îeÅ'ôô„K4²¶ÛøC§³Ì^+xE¬ˆÓ©XbL6ˆ ÙÕ­ÛO4é¼Ðòhú¤)MdDϱµˆÙ‘5ï6vY6°½,¤[G¼ PéT6ë¶„`'õ\¼*°£YYcgîYÄ"ÍdÔV¨eòÇ̼U–ïëS @20¤œÖK¯"‘ÉÙìzö{j©¿BsÈmB~°Ô[ØØAšVÎFš?>昺¤æé»ä7šŸwÒxò"-½¬Ô!ënõ~xS£–÷Ž3Ýv¿¶&w&Ã)•”òÏd?l*ª4YÝ3ÖVÌ&¹ÿ¤À¹OÎq}P&M]b©%tˆ˜é*lë¤(¼úV3*¨mž¢ÖHtÙ )V²ó´ ST…uË “ÍscùTçîš,4é8Ÿ&#èdJ3šíµR7¤Ð[U˜ûHFe«ÃØÑ"žtÊèïÂ÷ÄUI’N}…AÃ'"KÔñ>AFº®¤[Èšã!é$œ¦#…#r‰´Ô Ìbá$&ÝÚ£`ˆœU,ÌlŸ?cNÀ!‰6í=1¶— ?jå%²›pQ’æW§eȦˆ<>ämQ¹²uƒ ãÝxK½¤wÚõŸ¢!ø‰¿s¬BüB+cèï¹è ™¤cñM¼Qú`q_r¸x CåzQxnÔ’@G€ƒ a†‡èQ¾‘ø2üúSJ°.8EI KáF'ª»âBœa\±Q­LLÔ@ý|ç ¼õä•;Ž,îq¿É¬m\nÀ!¹ˆœ£¤*r85u攥@DÊ9Hšä ù͵‘¨PE[Ñ'Ò®W=+” RÄeÔ5ÃüdXxù‰Š8EJÚ± ›$ùÊAW. t EÑúCQÄ2™™±U2ŽE'Ò|°(¼pÒÕ–PxœÒ‘áî¤Óh š¸R%Ft… ”caßB]–gNo³qðFSDÙ§ÒÆ†I×áidÄy^u5’ HaJ+ )ʤ3 سƒR {!¦¶? iFŠzc™FªþaûÝsнüªH$ÒœŒ‘—hqe×·ö”žÌþF.°ÖÚ¿£Ë´ªà Ck›\{¥!ÖJ¥/Fg)FÞ¤™Ê|FV?%l¤¶Ä‚ &'ìø^©MêÉÂfϪÇA“’-WóÇÚ%"6°ÈÊØHSß>TÞ“€)1yDš7ô)Q:DU’2$U4;4t@¬ è6ï­ Ä*„CYÔãqÈÔƒH'oÎJº6Ë;„§ƒï¤¥vðA-ÈñSí©Æ5;J”A¥ò"(‰6ÑÕçj ììpdU«­äøyXªzE¥—¿J‰;÷"±É¯2}(´p‡ïV‹ÛØG>§m¶{’+Œ‰ä›§¶L„ H ËßZŠ¢\̉HTž)Úê*¼âqdƒ™P’>à8s “ °0½vBŒÞ†U$‚¸22[\¬qg‘ìÃðÛÅŠ1 @#§óÛCax¤Ôj<¨Ã×y–NK©mgÙçÐð6½Y!¤ÈÉF¶ËpÌ7©Î® Ê\ùFþtÚ‘'Ò L…dK—^Õ±ÏÑq3˜ùbÎLy¬Öå$•P®Éj­·;ïT”ë]AmõÑ ¥"ÈÌOÖ%œ~ “}?S´=‡]ÒI¾±`12•¸ÇÜÀ °Á(È1ÏGÁøü^ösIùBüjÉtuu^òÔ˜.Ø+SÑ1Æ>’¤Åvè©H’¦0]Dâƒnw•uÞP§Â•EÓy)Ä™ +6gî W ^Û_]Ð'½™^Ó7•µ¶ÍÆÜÛ§IÇUu€*¤VÕÜò-_U˜!V*ù<E?yÅqzKJÆÛm›i¦f€Pv}SY;¶£LczzÐõ*iBÕÇNÃÈ»\ôRšóÇêX†?yøyR60Ê6'"ÑaNz½fÃ|½¥8ǯ…o¿=ÑML¢7èÇW–>|o8J2¬Ò±ù„_G 3Œò<ÆC³ðß½|·KÏsgË%äÇl\ž[i¤Õl¸ü«Äï ½K{ij´ìâÝDDõ3ub x™d!ùqâ™ Í9NÂi83w¸ß©ïoÿ·XÍ«?3+Âk¦· ¬³ ë"ï­Ák"ߤíù=Ûk”˜ôSº[wm/‹w¹Êš=ᦥ«ô‘a$ÑZ5q”zí“ð§ªv'ÃÃ7úÇ#’¶Xâ®9.œ0›ŠCza'!z&-2б ½¢ùéì ʬ#¤(á9òï&;`¶³ý­³6· ™&b˜™ñ ’1P¸ @Ó®9' ¹±4Xœ¡ú~‰ªª³¤9‚>ê‘k¶2©¿J¿*Ñ„ž2a)¢Q+Гªs/:~£XÙ¬ ´=É¥A»ø-:÷? )b¥ñ,ÂÓ_°xÃÙŸ>Ûò(«ušÃ±`Ÿ6è}Ë2¾Êœ‹Ž‹¬ ®H"ƒI®¢´.°íÉÑžâ/‰:ù“/°ñ4A²ñ¢ân:‚£98²È—½À•#9ú§¼"Âá('bÀ ÊrÁbþá‚­ù…4‚™¦z-‘bü4MC32¯eÂ: ¼/©KOº4mª(¢{‰yñ¹( 0ÇaO1¸ÄA±9AðE2?´“€´Ra‘)(ˆ‹<¹ -3 ƒõ³Nµ1Ÿ ’$°ù1,è%ó%«a¹ #²®ja­n©ƒ©‘b ©ÃK©™l–ЊžÃ{;ÈÄBj¥á1?AbHS¸ Ö, {¶Ÿ¬"*Câ‡ò+¸®¼ëë´ Ã kmr«¢&l—8KÊ<|úø­óGž"d½€,$½+IÇ c ‹ý—¬Ò!Fʼ ºÕ"X¡Óå•ÓV#Òø—™Š€‹/jÀq !õŸAùÁlLÛÔC?È !›+‹v+¹™ ›H5Œ`'êÊà4t4€3ZKû{ÉC!­ê~B°ó¸ä@-ºý xÊ9ò’3Š3¢žCó$I¡ËÔ#-1á `Ê(xÊ«»)ž 8*£L9„£pû@•øF M8†ª·ˆ„=# ÄÜÞ€#ËÍÓ~žÑÝ«Áá3R„Ë2d?ÂaË˸ª$››Ä2ÒQ#³>$õ‘SH hjÏ‘2°N(ïŠTžãG¨£4äT¡ë4¸œ¬Ä›%·<‚«¶/%&cB¿"ADA žìo úc®ñæ¾0Õ‹*‡\ì÷L¤ ÜyÆÜáD°-»MPÛ}8ú€½Ü–,á\óHØ@RÔBú(Øe¾Ë*i·†¡àÈ#ƒŒµ r! Âoѱ)ØU,¦@£ô‚¬Å :LƒtÜ5µ?e€‰yDLk3‚5¨­Ëˆú+UTWT5«…ôY ï²(«Šít³twLŒ‘¼¢Ói_E߯ɹY>ShÃ4š"áÊK­áÈúK/›wJaµPõÄ¥«å4¥¬e!½_ V€#ž¹R_ + „E‰ÌF²¡} ™e<Ë)Ú%~žÖ<¤éÐL{Ô5@FjùÔ jÍšQ .tT޼1\œºŒjŸF¼­QL5M>4 ÚE°Ù…(“·ã0ÜvHÉ:€×0˘ù`n,ºÒ_$)FÞ£gžù3@“Ø,!¨ÀÑS’N¼ØŸbV Ð(áéü"BQúžÄ$Ẏi›gÞxo“9G˘öÒ<²ôÅKd´ÐÌt‡vÌ? åZÏŒat¹H ‘Ó¿}Û™·XhíøTo‘nÂQU©ZîÜ–\à¨ÆÙ\Þ­DžóbÌvé¥$ZEº¼óýe8…Dš‚(Á‹7,âÐØÎ'êž8Dä>ïªv5wfu!ÁK)|€-îKçÅ#ex²-oš X ù!hm÷’f’ÀŠWNÍòùý½qõ¾¾…ÉÖ[͉“ ŠGQ›´Ë7GŸ#sÔ;iNA?$õK]“Ñ›Œ|]ѸŸ.±koŒá£\¯žjÕ_AWø{žéñé>G­m½p¹ÏzĆeßFà‘´„-®Úyõ2¦Ô=ÎüR3ïÞÅ(/ž{Æó…AÅ ¯'-7XT¾Œ*WµG\¥0z~æô'¬]ö…du·R(ç{ßôGzÖ$ÙÔà‰ÆÆ¥ª'rlê\ç Rаg˜ßÎ%û@€°0$û~B` GÜ4„¿Ñ0VûÆapðúFdOø¬–M%‘H1ÉTŠ9Ìeñè<–9%•G"2™ÞO<•cÏê$Š&‘EåSh|âƒOI[U7ÕV9D@Àµ‰Ub˜€åO‹$.ÃZzÚk´@M¶/.‡Ê¨õ‹#â9 ‘PëK .=,¨ÅeUWÔrÃKŠÈã2pB±äo÷ g fk’ zwV¥šÓçM¡èä‘ZÅžazlkUz$·*˜Ln+|j ´Ni¸˜ÎÚGP‘IkW§ô–±"…Éw¯û róŽu£1Ô/.üÆb1´ù§c(ˆæA]3æU‡§óñzÊ%:ƒ€òbÐÙk"­'ªÖ½º(«:ƒ¿èº˜Ž ïƒòù¤ÎcÄÅ$k ìáLc䑤ª;TÁªÏ;ô'À€ö®è,(üBIëΕ/ Ÿìùþ™Ÿ®rŠŒº¯;ðˆ½¯Sr«*Â"ñ¢°­,.âˆÀpr<•"0ü\4Hª"!.ZǰËâ5`ªŠÉ‰‹&:çì AϳTÆ.°Â°’ÈHB;°IÚÿÀçìFã%RÈ$« 6¯j"8­Lï2¤T[ñL`š„Ã[ÚTd6Ã7L³ë2KèCÈ« EQÈ}*Ú©î‚ ãM©ÃÏ‘22£ÄmTŠáÒMT(­M¶Dd~Ô€/-ØŽõb/ÓÑù ,4 \­¨ˆ»ñaGs+ŒÙ­jb¬"ê;¦åÚдȹ"pÝ{EÍwSøâ²®¢c ß t7ndG0Äu™ý!®u #°‘ Å_Fö#ììÖU6~ÝØ‚=c pl†^÷A„àè: =é[ˆùjT·waû’W­TRFÎe·$ ¬f7r!ô¶)*OxT0ûKõÞ-~íÂt¢jVFŠO  K–žïTëÈ*Ú°šî@}Öõ'¡0[`Ì‹ 0Xܺˆm)<Ã;è݉)¤€ ñ? C{ÖÂBŒb9’0šcía€SµÂÆ+J:#Äiw˵¦©öÍöÀâAƒ;ð¿AºHnĨ8וOMeZ ºÐÔ_b+یà …À½½]úÀ˜¤¹þ#j7ñ}óƒt–þ­DÒK¤×¦ qøV Ó_Ȭ‡›¤µ?«LšfX”ÿ¹HïA©‹üe+A9Ì›bLñfº®˜ÌHí"êì5VøPW0+Eв3s˜åˆI+üî«uòEØ·tä<­¢.{T+o®©£%wPþWêÿ8Ïq¢ÄpË«›1†CSáœÂúl)ãLÊà;úS(‘!6G›ˆÿ<ª >6lyßÀª¢¦äª”‘P/¤ƒ¡¸$QÄa$I@‚ŽÌ“\ Q§Î&¦LFOú6Œ¤€iSiÃô‹¦Åá z å»và[ l§Mm¦´ÖÔ£¡_!Dˆ¤à x¢Z€~EU¶°´›1l¦{²<õ*‰x„üÅ:(é*Ÿ²ŒQ¯E4€5 Ãå»)$5ú¨¦]jáScð…ÉæZBÍ›s’½ò”B#aŽn4²Ž€\rT³.Dç†à<'­µ5WrA߬†1Ê4…ÉÉTÒ‚Ù¬DãÝ%(5ÕÖX5û$‡ã¶ˆdfÍ÷ÂUh,M‡df«¦J± JZn±PÆRøç£Úr"´Å?×a8'C£_®ô§¡¥ºC_h1‡¶·”¾VM|ÛTu±‹ò@kèû(åBJ“ÿÈKïnLÂ=8,Pˆ<4£‘ÅžBY” pÀ²Üõš=¯([ pܪ¶faŒ÷qš£þs-!#shÚ„VK\sSANnçH× eö †”IÛU´y2ÏÙ9–€å‚Sꀑ"ˆ‹Y–\¿Åø- fÙ„¦Ô LZ\G/öŒä|ÓÔ6Ñé90’Y‘zˆ¼cø6ãjD­­UúZ¡ÿY)Š,6þUÎ<†™®I¥%êbJ¾AfH"hQƒ3xrÃÒy³§Þe:‘ö$´óLŠEÖ§=hYºñ`ûMÕ"& {c'øßônÔ 8Cê5çÆ)*TË´^H1|V2•Ùr#1Iýhfhþ‹`Ž` Ê…ÊŠ&©’=BêµQÊ™L2`òÚcXOûWe·õ·BHØë ,ßP'²¹€î± c7÷`ÊhªúfõOc&çÇ–€4jrvYªÚ(‰F Úmš,H ¸e+tÍJK¢Ta‚ÓmÊÅä€jnÜÞG(¼é§¬fÿÈ+õÞäßg€à¼#g‡õ·š0­U¼hüëÑZÄ8 êòktq¤mñÐKæ[‘“r,N KÛãÅuÌŽž`„fëÂc¾ÍÙÀmzIÿ9«ÕC£vcRöÂü€SðˆÌòœ_;ÑíiJ9ÇÙêÇÃùàØ¶ T6,ß(ÍGa,vJ>)°©ƒ&›½rÜØ{ÆœV Ú¯ôm†•îããøpó%Šiª@ˆ±Oî¼ãlq¢=©°Ø<)¡7k%,%vñ^(Þ­6–ÍÍæ±˜‰ì§pQW ª]~ä ÅK@$…S7ϬU¥–¤y#×ä‚Sà¿7t'þEêrȽܫkÓÒ^÷È놆™È*–âݯü^šá¤{ıh—Ã/_“bVh~d²'ÓÛ.¨¦`Ç3TiM3ÔÌÝw5õ_Фç1lW*¯:ûÅd¼•™Ž‡jªï²¶QÃÆ_üuÜ\ÞˆÏÇÛ~+d¬ئLJHy^’dà“LAÉn}f,[ËÔ,Δ‹)âêÍèöþÆ€r%ò´Ì4Ï%šM®ÂÎ'ŽAb°0ŽŠ´ãÄàLŒAeÆL­.È*p!ëjÔKF!æÞï^ÜæpÊ.Т¨Du…èþi,Ck”^ f®@lÄľ'ê–évmbÚŽØñï@Ñ¢¦ yÀgÍZá Š©ê*¦¾Õêkèr¶#˜z:Ó†öîFd"# ¨¢@fį‚ÛL‚ºO(Š.” "2"JÅ&ÎæËxš,Ò§Î(æ°õ WR"¨|0.(:ÆB«NäAÊìŸmÆÜž¡<ã™L ’© rø&!'Žÿ –Õ vfEþ‡ªf†â G@CdÚþ,žCÞ_¯êú,LèjŠpw ) ¯,`$̺½LH8¨ˆEVzÊ¢pÅþCpE°_.Œ•ÇþÒŠögªz‚2.¬pÁ aÑéh‘ò…SZº'e(f;ó\j¦2Û¯9±¦™Î±'°„Ï LLsÜüÁôë„"t´"iAd ®è1;•¿!j.Ód‚½È–²Ð@n‡d³Áô”ªýQó—’(ó˜têŠø4*ªâ¥Ð +”u+´â?a÷zæ>å7u#±ÿn©4F>ÑßBòF× {i$J´Ó$…°aX§ºŠQCÌíh"‰Ho‹"B1jzŒ&N0دŒ×…H‹l²ô<§$·¶×3v£ ê¡*q€·„p¬I#-kŒR±JL)¯Ô­i· “h›t?TÙk^jŸ[·¢BWph!ð;4näÄÌ6à7PØç)®¯3b€äÌQkj8Ó*Jä)-gŠèlx…£þ­È%R¾”eb W:ŦIéVÒòg1E„ÒÀ¥Ð …2=#3Vmo8 ñGë+énœSöø‡ØÜ _WLr9Œ‚we‹-èèfåSÌaãí$7RwrW’Óo_mô‰iaû‹ˆ M¯©¯±g¨6I£Ø­Ýkë2ÒÓÆ: ¬²T+$êÆ°!Ì“&‘@“éƒ]¯M‹.ÖÓ{jk¨â°¶€µ¡ùµâhuŽá¹GâA7*Ò㤗æSÄIJ3ü%ÞèÉi»FïÖg« ûÊ9êÜ“FD¤ÔJ£|è騵jVâ‡îìè“ØL[‘•,ÍçµúV‹iBðÝ7,(ãr€n•†¨9\zdAT@ \ô©Òl„”s4” -“IÑþYº{ýv¬vàîÛë˜*‡•¾ž•.YÃ¥.è‚#2$¨#Òír¾Áaö›˜j$ÈλRH÷Ë´Y<f(ék.¦l‹hMµr6–ú›*ˆ’pâ!™©Bòä`?f–ôîÓÒ›|«’Gb–êüÌ€-!­˜ØÃ¤ý/­ÂTReêÔ¨þ{éÜç¿Æ«Là«7OIerw”eÍÂÞ¦GEª6©Ð¡/˜¯)KÓ•Ê»QƒiIµ¥Âsè܃7wkña’Äâi{æ$dáÌBî¬H4]*ƒòÊé¹*ÛC¤Š®/löi„ ŒCÚ€ K‘ Ž(èÄ2*°ÛQ„ÊŸÃõ†ÀÒp४rEY¦F¬;ž2qQy­zµÀg$Ïi‚=ò°€2 E zÖeçhý µŽÐ<«$gVãå"§à´Áh#slm‰fÚ5ÕV‚ždm€Ê]UB H§N¥Xq}‘B3é!(:”Hé7-e¿vm“¤êB̲6°ÔlJò¤ðTi^ógsÇÙÔS¶U¥ÖúO ‰° ¿‘Ú‘è>Ðí~ŽJ‘€#=€iI¶ Uþ4÷[ª-Q‚¥ærKzûaý\úR"©æuŽq ÷¼8n® ò? š:Bñÿ°úÉóˆƒÌX>ðä63Žù`¾Hö£$cªxeLZº›TòW¢ìŽÈªˆgfnE7÷:À8žàB˸"‰³hºÀ¬Z:ü\S+§ÚJç@þºÍÍŸµ¯`ñ6/ä›,€Gá:klæŠf‚\ \C§*‡±Ì·¢çA•Ý Tí\ÓÏ’ k9 aE¼ŠÞ Ó³…\÷µ¨ÑøÑ[¶‘ ¥AT³Xí¤![ê¶Dù+µÐOØ7DÉlÙÈÄ¿]ÀkˆóèÒ@ß& ¤[1,*ÌáºzÁ\Sgü»½¨LÕ˜ˆÿ#ð¤bÐ ¶·E;zzÙèra‹Ñ×Û“2C{Å´m×XnaUg´õ“ÊÔAWi¾œMá©hB8¥’KÅHó`3¹nÓ¨h=Y1Ë›T†I¼„>óAñ>–oKK–6´ÊH¨Œ¬Ëª·˜¿7ýš¤ÎG Ry“4•ChŒáê:gs±"‰Ä›eÝ,¹ñ^€º;–5«€ ¢«š”®–¡¹ÇhÕÍ‚kÄkeîÃRg‰ïÃŽ‚_eÉ“Ÿ"O G%Yè¨~Âæ^ 圑¶ÎZb£_•ºhƒnî„¸š½²ˆø÷[ÈŽõÏ`%ïÒfw±³öÝ”m´Å >7g8‰DßáT$釰‹„ëáºävÉø»§¦ò‡(jŽ·û%²èu×7esj§RLDlkÅ×à«y MŠ´aÀ¯1´Õâùljó4Òµú¡ûˆI1žO³ìõœ îrB:A_+ÇU\Fšê$"Ä«^kS)1L¬Äo]µYã~iu&ýˆÜPÖ ?¼äÞ¶©³¢J62Ò©ˆƒ:4ÊÂ.‚Î ‹É(¸|:É;¹1 ºº2€¢2‘o¢‘¾‹ê7/!Fœau'»è0Zw3•KöˆÓÙ—hŒ Pz”j"¸}Ÿ[-9È3ÁÒ's^?Ñé%Ì/BÜÂs¯±ã#x"à¶ÏÌ&6Àù #«“µ)w Êû '¯û‘ I7"³™¸–:(#©›C´ª‰§,+ ñî7ã¸6 7>“t¿»ÔCzÓ0`|¸«©P­šˆ˜žžÁˤ;¿Ër‰(“›2á¥qn9ܸ´¿Ù‡`> Í′š Ü¥ëš<2ö$ú“µ£[Át,­¡â-kä–ü¨!þ ÀÙÅk¡ ™Î©³ïˆaªX~Ž#P:/4 ±} Ûñ;³3™ü>Á‹;SõÅ$4ˆò¡ˆËŠ´2ÆK§‡ù»+™’ ðª/àÁpÙ•Kºs@óî 퇇ûÿíl©ù´ØYÂ~Tâpˆêà²#@‘BËŸ×P»˜ÙþYà}›±•Óã·8½)“Ò¯Œ›‡ÓP½_¶Àƒ$B0ÌDºˆ’)Ó?«Ä5€˜6bËTË:¿<Û¯YyÛšó–à˜ÙÈßIÈÚyyÅÑ!‹Ý-¹|8ðV£§5$¿Ë‘‹Ìn¯äÒ(iÌ?ËÉ¿£xÊAZ¹7[ò’¼2¶œã¯¯U|ÔÎF©ï‰a}щ§2)wRÚ¼ÕA«‚JKd8‹@ŠŠžV«¦ThÐHúW=¹ðü§À}<Öå½™¼Ý´ÂÌ\É£V¸ #ʸ³Üª”½ṁãÀÔâDüŽyFÛ< ÝŸ:Ä’ß?”žµ¼U„å¯){Sm9µ»„OåYõ¡ŒWlyVÓ{7“Õš{Â1Ù™Är_dœ6ÄV^»Ü£Ÿíoó¥^%ν(]r¾ ¨˜×ñ»ܾTƲü?JÚ2™‚Q"® 2œÉÊÑ¢W¹S›c7‚DP½ ×Íò?Ë%ÒTdHc‘΂’)ÈáÁ2бrŒOÃè&PŽXÀ…Œ©”ìÈæ 1€ôÇpCÚE } Ù´9æ`] XѨ¸L¤ š¾mÎ:RÿÅxFØÍ3˜â_Œßãu0ËIn€+K‡Ò=Á‚Íá|¥·Ô ã^$‘Bc`K`‰"’(MöL#é ©«Ò)Ùü{Œõ¯ÞرRÆ®)2*&€–@8,#u¹ck• –Ë•8:\ËÃ+¥s©_8Цö:0’]P½½,€¹CND"-‹[Â-ããèšQkàѯŸU AÍ@V+ÝuT´h»UÑ+ôí{Õi2¨jÝ´ª—ÈÁ’í2áÎæ¯9ê ÌoSâö!ì"¡E%ã¼IGµ­Ìr™ É»I@¬Ömú§{æRjaù¥Ó1VPκlË‹ÂÊ1NáŒ8Õ¦’“cßæYV]® è£õÕîH·ËœŒ¯¼`œ}-ÔCç ÌøúD8}9‘ô¤UÇOÆ£¬Ð«(}-¡PŸ,¹hºB³Ø—løè(ûÉM/øþtÎEy!KÎ4b(iÜ!À°ìï2àÏI0QäÀ©!=-H»¡‘@SÚŰ9[z̺-:½?Ãþ9«3«×1-Xf¼ke9i~PgcÚÂþ¬ÄR,1 À›Q„-€ÍRŽWÜǯžaØ¿ !n.ÕE]F¼ˆœo Ãe›M$¨«Û3¤¢h%ó¼Âg€!«œì,Ä•ÎJQG¢m¥[±Ð­½>·[Ââ£8Û\FÖü ?U·íÒ¶®ÐýÚëÞææE—&¬ÝÜ«>jYµp§ùîÃ}9I‰Ö•ЄRlÁjZÔ«b¼ôŸ®)æÀ‰ÎŒÌZær“Ô GùYM‰´á°”†>®ÉØ—m²cõ$»,íÝ«_ð¬8´M>…ü§væM½¼m¨N;—§¹.?qPµÜÓ±¸VìЉÑTÈVA€%Æ 4~thh†0±‘W§¶ …WŠê–¥ù©ðÓµOì kÛÂfš¶Ž%ZÕÄÿdm7–úe½¾?ãüÄ•¯e^•ì¶r`—Æðž¼©òÔ1å^øƒWñ4p|3ùßRCˆ”Õ­àÒßBS±ý:rÝ~zΩ+!†®' YÈ UáoÁù¸oc\+ #¯FnYñ¹¼M³k`3p%væX‰Kd«†pОÓÐnóúÆÚAMNºƒÅõML›\€„eh·³ž¥µu¯ÆW œrį%Ð\´b¸çœé†ñZƒBæ!åýÄlå55)š;Ç eq Æ,s@Ê¢æ<–¥ßO|ªŽ£oCxCäs³þè/ŸµLáÅx×ÞƒÂïÌïè’•š1Ĉ;¶h‰æýnÒJ5LÏߥr»âô€›µçv¶Ñ("µA;ج nn[Z.(˜ßj{á9¶oW,ÛÎç«xò"ÎnÄ¿½×p+ ‡Ó0U—>;œÿß< ÷XÉ¢—H> ÷¬G¤Bÿ\bܪwF®¡hÙñ¹å/‹$ÄÙ?åKè&œj‹,ɦJ¡ü©ÄÀT•G S¥°Ò#P„„Ò*ÑÔ,ÿ#N«$Ô#PhàFÇô*¡«ct•$ !·.© ì » `LÈïÂ’>S|‘$ ‚d²´„¾~¦G´ðÂ4H ‘;`hö£SÁìÂ0‡½ÍQd„ÓOªÚ4¶'²«œ´k¢þŸÈâQ#LjÚ‚ÉÇûÐ'ô#G2)íTž´tòPzÖ@Ui"ʪd™4m`Π¬"LŽ=êÙ¤·uƒ>Í¿GìVºÊ°Kü¸é%9'²m<Ã(Ò ,}o6RÄÐBit´ T îreØ0),Â$UÃ0âÙObŸK£Sâ Ó $ÿu¶•ú²Ç´\Am ûÒˆáHÕD=r‚ÞÛßt#ɇQÓã èM×¢Cp¶4îc³N2,€IƒG, èâ~™W‰"Ù^ºô|KMÌ W*ÔvÌÙ0Ê«¤‰‰^2û“Éh²˜e'õ¹ 8QrSÉG¬ÖÈÕ\‚®«+¼,õð“Bw´%ê*U ëyØĤҭ0Ý€P-ä–¼Ê~àÓõ"s:Ôr"4•Íé&üëöx¢ÊrŸ|ZçóZ¤ *M¸‡âJU“EÇq¢nòÙ-´ÔRIüÀ™¢iÇö¯”¡s»ì¨¥àÛº6Ç(J²›†Æ ÖOt Þj(¦‘oºªËgîtIM†œq1LÓæúýRZ†ûÖ"Ÿìú‹lѼ?}|á4ꤑE òŸ‰Jn ¢¶2UÀK܈¼÷OZ H,9)„ ŸˆIGï;±øßéI%Me´Æ~¼RbSA/M"¿SÄpÀ!¯ÝÙ7•¾ÇÕbd,Nõ:¿—`à›Ž"ËÍØGzzÚ šLÍÒ•â¨ñàâÐzÎtûB¡úhÉY„P†"1€'ì´ƒÀ¶l³€$M4Ž¥«Bõó$õú¿$h°Ÿ‰*=äê‘R,¼bD…ve·W¦ÿZБ0èÐ$Íõ‘Œ‘ÒX¤^ÃwѬ}HÃàõLQ?(Œ„ “ ØÇú‚•«ôÍR úH£¡ƒñD±ÁqþFÓsÄY½¯ö¢›k˜ª0Ò':êÖÄsD„™&#¸?YASH&KÙÌàI»‰‘œ&RØ‘‚qT±âß’©„sNiû«@Ô„*´…œ²T$d¬^&Æ#;D·ÝbÝrH@Œ& Lžzk*Èz±ú€‰Ql”cø×·"dݥªDS­»Ä‰ªÈSLŒ~SÖ®¶U…g³U(OÇиŸ”ÌJŠjL‰ªË†Í=‰Š€ÑéšúÕ%ª(ž§ e©88Ä –ß= ô1ÂDtÓK–š7s­¶ņŽÜcEjCýÔ¼PLŸ¹Œ]ĉU3qüJåub)çü„§2ZI‹)Îcj55é$À\ŒrT%®¹vå@ Ú¢•­Ú>ú‹&ÑÜÚ7;e0‚b‚£jÚU`·3J{DEfŽu²dÁ/;œ17!Kx~oˆä=5PG¹ºQ«´Q«}¿`z¯QïL¸H°‘6ɶtä›ô˜¾ÏtÜã@>­¼ŒŒ(i)¢\£Î!*a)Y¤çÀøÆ&0Ô÷nâcÖ'¤ý¯ìBîùš†§9ƒY ‘XBº ¥Áý`Dµb‡óÏA*{Gì·2TP'§ØÑ³¬ /š%ŒÒUGM¦zÌɯ”!.Eo‘Í"‘t°ÆÆíѱs¬ÖNsæÄas.è‘<®4ÛØÏVGåršL¹E”ãt1¶r­„ˬ>Ƀ  èO!“—ï¬{rŽÐ`ˆÎBnˆó˜hBh «ƒñ=X{òײ²(®SK×M}ªdpË;<–Ä ï‘jâf—‰ ÑR¹*¨Kôv˜£5Î}ß=áÎ3.h“ŸëźÖV¦´g®àÇ‹f¢“«~§呯GGyd†”pÈïƒQ=ÜnÎ3Š%µô‹h¬à¦¶ëãËCî%&)©ÈíàúÃçJT£|)z.£uœ !?¦d‹bé„'¼À²ý£¬±:d9Ñ"ß&Ñ*\S Ôô$!*³lxëa#Á‚3>@‰_˜ºNK©âY• á‡¢J pä­—ºa{š¾SÙåEÊÍU˜WŠÚ½p£Ní…¡_!ðÖ=¬Ð¤KFǵ¡umÚ1ßMM–ëžAÞ 1Îum'4’Fëg^‹¶ÝëEO8©´Úw^PœÂ¼n <Ÿ5ÞÖú¡iÝΜ˜m—qn‡1ï‘&ƒÓø.RPØüŠ К ä‘n?Ÿî‹ôcí@¿JÎí:ýÀ¸F–"Ð|,ÔUG¢>Ñå ÀÊcÖÙ,A;Ù„›P†„n€É7-c\©Ó,¦Œ²pò€—†—H2éÉ|œB n£\Bz¿³(¦pâùJÀ)ê?.Îy!„§lÉJ‘z.r'ô̹s.Îlèo.øR'HG×]®ö¤NG"̦÷‚0ý Þ™ Ž÷‹ñ#Õq6ìYóš\MØì‰pë {ÆŠ¸(æï4:îHUÀ\P¨w¤&10Pñîk6‘‹:F©!JGêûn|ïl«?lA8"h¢~9‚"‚ÚŽo”Nªð‚êÓù8”9E(‘ls2T$äbDÉÈ‘AmÌÜŽ¸S°ûD„´ÛT@,¢~Ôêf13Ye‹r@]NAþ’«f¦$nŽ';WÿlòZøƒÁ, ´+Xnp¾íļõIC&9ʺªÒíL YÁòïl>˜ä!P\ö0Gt~·ZwOo4ŠÕ`R°“i³°û`CÄEõlõÅ0ì“¡:/!"o‚$M#m0QrDn/ #I×C40‚ËÕ£C®‰@u÷Z˜r¦Òaë;\—§R;UÏ:\PVÌI6:à,ØÚ• ¢ðÇSÛq0«[´=lªPåqB„p$ùwªñ©tqrÝ}/Ki”ZøBêúô·Še~P(|n–4† !¡©„H=hÂÚæÛI7w€µ—uÃ;bߌ?nƒnNÈ,ª lFå†q÷Èãä¦ÃhÏåÂI‡l¬¦²u7ýo`WõE~ÇìQ {~E nBë |5¦a‚pëñ:sê¿n´x,X¬ñk ØrDŠ¿’B_qGgr Êot)‚8þD<ʆ׫8Pu3F>£užL“ Î!ÿ\î­‹„2Rg\ç'ßT´¸åÃʇj n$ÇîÃrÞïI'WßY¨‘pÇÛE‡,À [Ž%¸ N£cmß°ŽƒD2²È£ì»BUo쌘rÖgظ‚ .Xy -XuÎZRIn@_€ Ò,0N‚›õËá``I] "QQý“¶ªçm5’2üz #^Ïy&Gõ",²˜qÊïËE*±ÒžÙL”Ö5/hïM ”‚|b™{ȽËá’Aô¾@2I:Su©ŸJ1¸SÇzÐO{iŠÈɇ¼¦ØýÆh•ªSX:H0¦U`stõœg ‰ ôvÄ{X£!ógJ«ZOíÇMA÷¥µç4½£qx†®ì%4$ÑecÌõYt4g qÌ‘ rI´BÒ5¢¿Õ9¨–›zks`õ׌w¦š¬bw’Ü6$_y`±!ù› I Âšë‘ ÊÌe…žÃä^Ìl“ ]Bâ…lw€³2¾Ðl„#<*ȶ "—ª&ÊC["·‡& »`ÈXب!îÆ]Ô–îŒ+ü‚h&õD„˜zk$y”®–eQ¿ÃΑíãMm¦ñËÍ4Ó¿›çõGI "A ˜Ð%¿[JÊÒ1²ŽÕµ”•^|sÞZ£òÂi¼MjÓ¥óC¶ÆßN뚨ô»1º3”Â-ɪ˜óG,…§öba|”oY“I¸³Ö ¹ $ ä~ãFGug=´¢js!‰XÃxŠº4*(Ð]åë ùkvÁTrütƒ…v3NõÄ™¦¸‡ }0*faz³‚7LG{úú{É)§iS‘2/úŽÒˆëÁò#­ÅWÐêZ“ œ™Ä7p=5YÊÉVˆFŽ—Ê§«ér"LêßšfMeJÖ@ûì¬h®>ZÌ‚%T”ò|xXš§ß±©p4ÏXINíÇ#úæ¿~ó{¬rôõ¯Q> #¶Pxø‹t¼áG‰-Õ½m£­É´Û")æÈ!bP°‹ØÖ"ë5M{kå4¾Vª¯xŽ%0æFñ¾RZ‘‹—¡FØÇ…_™‘°­©L ÑLÔš³U“µ¸v8&aÍ”O—k1Hv‘QpD2NÉ ’èÒ\m…<ÑW^Gt&[Ð"jð›-ÑQ—EqnÁ”p‹²4Sª!ðìpçzeÛ»c]Á-tÃ']%¿ÚŠrC œÙT«˜±ö½Ù)‘œ3fïNI™,òÖÁA}*(J$‘éûXÄ"ù|ÚkDˆKBûdV{‰Í¯OÔÛz0‹„«§qË3é¿{Ÿ•fÙKbwð>ˆãpûÌ3X¾±ìøHˆ²“—àF…#Á€¼lo ©áU|¢™€‚#›˜¨Ó± è…Göjˆ­µ¢{*¹„eĘD‘„‰oar°u0eÊš—VÕÃn]³öm-„Tç벬¸S9{@™+œmÒÁãí å­øLÆ\º}ÁŽú9ÂØ~ún÷S<”‘‘ëÇ€7d¶cÅZ-]ïí¾¢©‘€µÏ\$Éä-žÐ$T¡í›êgÆÙG¨Ìºp«o ©X­´x×Âqa7Z†¾ór"…‘µ=ø]Ç ”š—/OƒÂ~ò%î'?²§ÆïZ´pûqQj ñQÃ4¤ yðz‘E“C{sÀäx(µD7;{õs눸õÊ\ù?§®z%µÔö°PÏ}‹o+käÒ×¼çÈÂp ð¿'2?u î(—ÛíJJÕ¢bÿ? €4 þ…A¡€>†B€0‡ì\ ‹¿a‘#îA HààžJü•IÀr03æaCPLÞŠBSÐTþ`ù†L£±˜D©ù%†锊<ªe—B)S¨¤.‚B"UšääW¬X,0ª$7%ŠD`V •R·\¯Á¦WX|õõDìÐù-þÁ4ð“)dÊ7¦ðiD­W„Xªò[ĺªÆÌ¤°F~‘%\Ñìíîs,´Á%ÙÜø!ç±›‚h6xl²K‚è£4ÔÕñ2À¦TˆÜ»UµB£x¸´_OÝFíuëIJYÃcßÓ* Sq=ü’èßU™áB°÷o#ß%ÄÀ¼/íl‚=ëùáü;›4À?K⮆1©*ì"ÒJκ‹êf¯, ¤ Ö$j Š3©JTèC¾…*jÑü¤4É\ë¤è£G©ÈVŒ½í›ª²9çë ¿€‚ŸI+Û ì>gû36ÍÒ‘2hS´‡É‹–) aþÝ.RÊ#hÚÉ0, "d—=伋¾¨òY ©‹Âô#*D¤«© |^±¸é);!íÔ~“Êé,m*$ëÄÖ“ËIqëF5Úƒ%Èc;-1JjT„%‘aÿ0Ðh:ÙÈСý,®IdhÏ < ¨h|¾ƒ1hÛ:䟩’K&(ÆÈoÊηQH;ŸêDª•Ð*óü–, ̵WU«;Y°ŠÐ‹ÏëŠöY@j‡¶k‘%¥Q¥$¯A‰¡ Á yøí€sAúÌ •º JO ŠZ4šA{¾É#ÿ@rr®¨£H»ýJᱦ 02Œ£HÌÔò|GB؈} ƒSÖåöƒ;(Kðs ©/2å¿vËŽH<Þ•ö~¸þÄ#Í‚Á(.BOF­{½]$ôu‡"«–=‹8 D‘£n0…Mô‚ÊãÌ[mT½(${9¥IsüÛ>¹ÒGZÐ<’µì²{ TrD¦œÈp–ð†Ý™>¹1 MYýÊònkH¹÷š_:GŒ²é†Î3© ÝXIìiÉØò(Ýh*ð×é±²=@u€ÝY>¾i¯¯4}7,GƒÆ”Ò“à(Øà&G—‡³¡Q.Y óÖÛ3ÔM‹>÷Èd»Ødz¹êµøvpymGí׈']b·S26O—2 ê<^$æ"ö‹:Ÿ,Ž‚)ƺ‚HÈ¡‹Xm¸Û,å¶ÏU±\ ÒÜ]’¹ ^gÅm¸•:d ¹Øh4‹©—zÆË” .­hœâ^ÑÝJ+$ 3ô–™kÇ4ŸTCÝsM‚ðì3SBò_PüV„ž£tei<'§L‹¿¤ÜOL[E]± “Ìü–Yboì5Næô˜K¡ý,mÝ—@w¸q ²ÔƒÌð¿Cf{Ù›Èp„0Åôö[ÛÖ^%â&Ð]Z+]+mAº×œ_H.@˜éõØ¢ö" `~Ũj]dª.IrzóGèÙ” ‰ü$V^V›OÉp…×?Úk¶¥ Î£Õæ¦ÐÒºõ4³b9X©¹]Xëù%S–GªCP •{2`ýITl‚PûŠ6b²@£”mºj$FXÓ#µåýÕÊÄÁšÚ¹¦VB/«†õèñ2v„Q6€zôH(Em.R"$gâg À• ZD»QååvøÀÌûMÃHhfó"G^ß…Ö²­Z¯ÂXå‰Q„J9\Ä´î ™'†h©Ûø $l¾rrtŒÉxTt@$öÀ€ÁÚëìY'u}Å—Ù-*#"àJãP¸²Žo—Uf~ 4fŸÏòÚZ^A¡ïh÷À}Þâ CÕ’ógÀîË2êâ6F,OmU4ó'¨ó54–qm¿¬»Ð\G­Ì}ZŒgïòùcé\*§\´q›Õ§EÊb+AWçÕ¡©wjÔ¯ÙÛ•S5m¬¬®´FIQëBÀ·Ç G`¢Mü¦RLYõænyA³žB½ÚEW#™¸&è©<™ >¾°uùx‰ƒ- íñ—Œ'chHü”YO,£‚ô0sïÁw݆ùPˆ6Ëþü—eØý d8¬:f9ˆ¦P® ÀW C}åGÈ4Æ·›¯‹Hm£—Šå¾’p—–$¨¼N –åOd*z·L4õœNmê„CÂTlÐÖÃULf¸5*cjVAúç2µ¸Å©Œ³Pm¤<=,ß#È ™G îXØYV½ýÝ‘Ã"¼]Ìa±ÇXêÍYtqº„:A0ŒûW)œÏ9’£Ïmñ­†X»±Wä»SeXTØÒw$¾>‘» å\a”Sp’Ö‘ìn¨Õ^F'‘Ð+1;bÁvÍTSU#ePr¬qt†}wßæb’kë¸k|b1Â댊ŽÔtgH·ï.÷ÜêÖÛy®)·Mä€2Ç;‰Râ.Ü ´ü%Úƒ&€#€ýv§È‰¡˜ÀýØä©”QÓY$ŒœMé0„ Äãr,ã"–í!¬y0úHɈ3‰^n'ó@9s…3~#öÆ/6ýuÅ}b«z>ïñïÞòÉã÷ÓOÞí¬½€mѱ.ú8MȧlÙÀhMƒ.1 -ùh¡ùbŸú&‡Ñðà!›£Ĥ©û X²Ç6”8Ëï+v #ü“ƒBU=¯¸Ùc:c¤´T˜Ê7 ór¤™ÁB] ‹è«« ŠÞ»ƒ)7Œ ²g(Û&ã©ò„¨–ºÙ¾Sš¼:†6aë4š$Q¾œC¶ƒ¡´ÁÕŸ˜ü9ÂRëé%»ÛÚkUBÐøš™Ú„#ê:$Ê¥?ËÄù–+Å0«ì±Ø¼ÑyÁò ™3Ü»ÊOœx:Z­RGCàÝ ±3C8|kÀSo¨óI¼RVè«¶+w"#?iMž›ì¼‚ã S«¤’ð@ŠØ"€ÙŽ 8£Ÿ«»:SŸ;ê2=U³±@a—yÄŸ"4>Êól ©J&›â©v+²J¶°Ã!W¾ ×<}5*ˆ‘’Å›(~/S2'ãå¨q-F “±3C=ZÒ øÝ=у‘±U!;õœèŠ —7¤¡=¬ùˆ"’¼z „Æ´ì#3Œ‘ÄýJ¨| z¥°l\J:!™m)E:+Ð$‘o?Ú:è|›q YQ¹<ÿÄJë½1Gdw1ôHký>"B­Ú‡Näs¨põ*CymŸ}¦ã¶ |àú„NLV-“ A³ “Ô›¬…A ©R<~ d×D®O%@è°<žŠB?¦ä Asê(C…(tøEd2Ç$¬€1Ñ0TÁ U ›,•?ãЮâ¤2ds>Ì.d;TùšÉ«x2 wšiJîÉôµª-UÅ@²E,ãØTà}P ÑÓ‰Ÿ°{²I ÍœEµâ±QiÑ? ˜­q6œ¨´¢Ô/ðßN©ë¯βQM“ {É~EÉ›Pâ?†ÅÒ· ¦]غÈ!r± (»k¬A”¿}šZr´Ñ²ÚI¢ÐeÊHµwXœ8Ñ#‰“©Ñ½w€!ìÏ3?ˆ@׎jÙ«p¿Í6ˆcüžÍÔ¬yìÞhωa¢ºÜU´ ˜Ê™y¢³JÇ Ò2)j¸¹y×"êŒLDëcP;à6àÄìNËL, t¾Šá\‡Ê(¸³†«Ìœ$Èžø¯F(º‘²Q4°}_XÉ ‘Ú È Í‹ç-úVÔ%Ÿ;» ’¶A |ŒÌ«Z%“FJš]°ó™‘ÕùÑ„¾ #Õåˤ< ¤b{¬‚L Ô÷)½Z5»WhÒOt»4?̃RíÅÉâ1Ç3Â]ªÀšÑâNÒQa"Ýú-] ”» ÁÕÀdh´Ì@²¼›¸>4¶ îú™ÝÖÂáv‰Þ!Õù «p†º Û Ê 4‰Ûžµ È ߵVO°ÆÐP|ÎÍ ÆGÒ'ÃagãìˆJ §ÁË·£çCƒ¥Ö‰%8}âíð{#"ÊÍë8Odá¸í߉¦, ÂååÈ|XbÓ5HÙ±yÖ­ƒ¸ÕG‹ü5S¹V_Á®FF`»E; õî 8xæ°Ù¨°}?HÊd³Ý¡¥É(eî”`פôÂ^*®Q•Z‰ÚJûÝö7ÎiëÂ{aXLù6Î'źVQT,.7à’½Ô¥ˆE³¶ƒ^ѳ}"uÙ4U,þ_ì¿Þ3gLbeM¨ršŠ£=­Ï {%2šÕI‘‰­ÃMÉB6`9Û1$õG(]bº ~-EÇÓ+ØàØ+ ÷å“Eg>m*¹¬Ôî›àfi/niVõKnˆÊ\^7Å™?ÃLd•Äl 4¤LáŠ;à^y`ïŒ8!.Œ†^³ì³‚rÙÛušãï×”9çìðÝ{–f9$C’R*2/ôN[æÓ¾¯¿Ü¢Ô¾F¤ÑmäJû¾D%¯¶x±¦£lhЩM–K¶@î€"¤gêm{ƾ¦1ÁìÍÅ·KWÃ3¿™‡.uÿž¹ÿHUL ¤:,N|Y¸eÛ#í̲nm󙯙­Þ™4gA®‰Ñ(Eèò2Ž–Ýì?\z—ÓOõC”qìáÅfÌÜyxžÈÿ11Úqíè±¾OUïžñ3­ÉÅíNt ˆ¦fËÃkªQ€ÒyovlÂ&±Ó¼Ç)쪓EmëPÔÆÓΩY«dc@º i* ÃÌ¡œ#ë¼²‹Åž¿%ì¾;™J8ý^z\vlk:­à’DFU1%N¬ÿ#ûï]¡pÖd^ÜÏ`J†£Ú€&Ž3Å| ¿ Ûþ¢bÛ‚²¦¬¬yƒð”¶ª#ÙÜ„°å&diÂÂ|%Ãw,~†\ü‰¹#YÆÈ,ÆBA»Ý c§¸ÎªP–4ø˜¿×u@}cJ¡œDA8˜ós#âÓ+`˜ZÎõ!}/Óû@Ý?:ù‡è¼ žåÕ¡v¯'+ç`Óa¶‚6»’‡HƒëÝù_IŒòMF¶UŽ®®D6½—åe Æ*›(· Y˜ú“§E¦TâtVÓþ‘ݺ“>v(“ÃÿÁÕNf~%ýËôÂÛ]·ÁŒÐv•È›3F6E(uÅáÁ:Yá™Sù™K.%ú_ßåŠ1ÏFr»TÒÒ~°—/2ƒÖÙQ±ÜÐbÑ€Öíjs>™Á·O¤…cú_;@¥~ÃK‡·zäedÄ |è¢:µ×@Þ`]Æ­ÿ‰¸,ãÉžÛ’½”Ù#(&—ˆTìš)bæüY“6 »g«¯SdÉ›l­öñÕÖkvzíÆJ L{·0BÁb–(Íõý!”–#^{~!“ÒÀVÛ¢tn(Ò=Pj4íWÆ\‚ßô;aáæ5±e¨ò£ašˆÊ&ÔgçϰBb‡iôɈ jþˆ‡ô?Õ?iОÉÉ¿ê¸^pš¨Ax‘àŸ¢D@#£†fÎ2ʃhQG7cþȓʼno!<Ë·4? `÷¯ö™H–"Q^"¤*V¤Þ+‘îúöÐ…!?‚Wh€?`@#ú ú„!P‡Ô"PàV$ˆE@O¸à=|Hcïù$”'{Êd°èt^K%‹Ã€³8üBý~NcóX4j/7‹Í S$œ.—¿æ`ZM*g¾)ø€&­‡N_”ÐEv8ûÃ#Q¨…N!F‡Q¥/{¶§K­C¡› 6íSÞkUù½6eK§Å¢Uù-–/‡Äb&)¼j—Á2* ?ˆV¨‰lJ5,‚IsP:-OŒA«ñp6¶ß3›×â­¤B±­EãøI&ê=¨’äçÑ,,+¦Æ´Sš\j¿K’ÈäÌ0—­^@÷GÌ~§ÏšG³` ³Šþ›Æm²½ “Õc£usðKì’ã Ö¡— Ô窴´Í2.¯¡Èú´(Î n$É:Ú5 Ò ö*Òº>-R9²0àæ­È”&÷ ËóJÓ1`¸éï˸á€JJù€,L)9g⦋£OÊÖü¾§ú¿€r ü¢ê‹¼â$ˆÒ´è7¨š ž¢±”¢Ã¹¼w)%‘´®à).ªÏ²¬JÉ hº—£Î⦊"¯“"Ì6Çô²ª8È’>åI¨«F~Ío¢†‰HVFú:)qþŸ´Œ²=AnŠ<߈º£&óÜã<Æ3ì ‚L苎")ú  Ï½$(Êûó'¦hd‰V€*öŽFÒ¿[5¨ƒ´¨¿(sÇN JÒЂ2¨Õ:6à ÊÙ` sW(Êœ(ÔN„~Û¬MXA êD¬’5Jô ÔðJ]¬ò*Ë ‡µõy+QMå+ë>*ÀMdÖ²pò’à±Ê/lˉ¼,®ÄÀ à_«/Ù˜Ú_ƒ€ÊÒ>ÇÐ` R"¨dï/Qô#[SHD.›Ðà%ºë¢J‹ü¬(Bn£[ >Yc P}¿ €p¢—%-c[~©7vR„Hˆý~ÒŠ\_{£ÕtfŠä‡ëß\¹Èã;ÛïË2œÈ“ALüµ ›hÉÎc;’=ƒPløíB—Üï}ª¦ÊüH˜…ÅÆúOs¼²ß ÎÍ—.ˆt/}ÜÅi!áÿ* /¾åUÆ›ÕQº+;©² ŽÐF›ŒS–QÝf÷¿ñ=Σ;áùg YÀ­`¹8çl<!¤üÚ³¶$ô§dÊ^ÞãSÌã\»;Η&8–QÙ\˜ÃÛTë‡èWÈÜ'=†ÿðnjn†;N®¾˜¸Ø€J@~£wêh&æ¡(’$ÕȃÆ$¨\zÁU|¯›­B„Ýå-4ô×IÌ)kó¸ÁOÙ37&1’ ‚N³À!Z…åJ='ùNáùkEÑÔRý€4€ˆœ°X8LÝÅ~ƒñj¶±øÜÏy+à.*Aç¾ò—©‡-o)šŸ”S ßšëe® s’Vx¤É!|y-ír½¢“͘2§åbèIÎãcˆ¥Y룧ÖOñF!ˆ±‹žU,)QZ®™L'òZÀ|‘UÇi‰Øü 20UÏö·#@QboxDŸbsâ™…ˆ-²’·XsÝ$¦É*%ÿHä0E„AÍÂÓ`5l¸F¥WäB$Κ=öðœÒš¦“LƒDÊ©ÇÚ“$T¯¡r¢ƒÈÑ CÅ-j˜–/5æ›t“¯9íªX\Ú/W/RweVú¥•«y:¹S6ËãZ1õ¦0¬ÉË TNí.¸ÐKß‘‡b­¥§½€»Ô‰•$†wÎ…Ç>|Ü#Œ„²ÖQ»eq4ƒ:l@”òt›¦ˆØ¥¬^™IÐCä¯3[ľw­ÃËå þ§NœßJNIÍ  :ŠX‘Ê? ºp(Uú)ÜQcÎBõ%«¸—Mâ%X«Õ5ðÔwZùJüî"®bŸIàQˆüç› JH5LÑÌ ÈzƒKõ»J7 pÌÕ6öJM)µå¢§ârŠW ¸«³tѲŒÍ™¢S)WFä Š” Mt2/T]_’”d‰:2Tmen/)Û=Öü¢9LL3U’’UAÈBª²aQ&b*ÅØÊÚKOvs* ôˆùkŠ€.aÆt—"Q Çr­")jva¡$‚£Õ‚²"<µ].À6Ö‚r~m‘y7ƒýR¸å£A¤9k=÷-™ÙP«£,`RÙDJçZÀ!“ŠJ¢ZÁ2ºui­éãÓ üèð[£z†š03+]QĦ’ö‰G!r ʈ#îšGÿÛ£ÏWeo4À¹µñ$c8%Ë!E·'ðƒÎŽfµšÃ—î°‹Õ—™VIQ2£&ÁºUÚ+­H^ô°ºo‹F%yÜÂ,¦ö–ZÖ‚=_¦#µ×šÖ€[ðYª(¦ÖKûxã&T‡ŸO®,Ñ.æ ¼Ù„6Ô™ß눂ÑìvpxžŸ-Ù*?c)¸ò+3Ñô¹]Ytš8éÃI]ú­³dkM5 ‡êòx…Ð¥â2¿ZicÌN·¯àî8æë—ßËŒáhKU¢IHc :d"ã˜Ä…6Ñ'ž*S!;—TÍ+d pqw21ßhŸŒMmp#–ýéSuǶÐrUÕÀ«ÁöD/Þ W†Ö§MwNI‘QÚdMø3cxPÿqÄ_jÇ‚èB€bÊ$î$ó®9¤@5­ç±fJõˆ"ò@råHÎüR¹æüqܵù[ñö—/à›¤É5õÝ¡ÛÅ©¤É §\ê5ìb·su ]H¦RàñûÙv û1ÖQG•ã[#ïGíE¶™Ûz6mpGž`£¸Èëñ0í†0c]`·VÎ,k%|Õ™`&ûZ'j¡Ó{¶Tv—T]D9Ö[²g¡Xñ¨ÌùŽ("RIÝJ©W Ý7cL…{÷ƽ¢½~þuY‚ÅzÀùBöë8.Yâdü¦ãNTš<úêÞ]£æ!GcøïEøü†—îC·r ~iW?—óî¬ÜÏ»Ø§Ž¥ºz^e彨GÖоÀ–$í ÜyÓfd{­ p|øŠ¼Rf¿c´’ÏhéfÈlfðˆÄTE¸é–2$p$ÏmÌtÇþÃ輬¼P>š"¦ì¦¼ÜÇþúÇÌäN^i^žä¸|ªx<ɔNj&î :˨œdbf‘IììCÅâª/¾·G[m=æ2nt•i‚ïâ8¬e•GÄdÔþÇ0¦í诖¢%Ä|¯ÒƒÞu!ðBèf⾞#òäfr$,DªÏfyB¢ø$ð|–½m(ã´ûƒl B*fŒG6\g|¢Ö#D.‹âr¥MB0ˆ²/Ë©bpj¾Ì¨€Ž®bä0”eÒº § br÷i¢˜-~6ÌØ6Çn%Ž®›ÞtdþSh´*ÜtËDeöY®>œ Ýç,·CÇÇ<¥vqôâNUÈ(‚¯ÀÀÈLÖþجà\ldÈ„¸[én‡ÏŽ\Cß éÐÿPŽpnîFüêÙÌK…ª;dd16+¬îÐg¾$«ó1ÊR…JãjçnçÞµ6Dï8.†œÐx!¤NÈ rÒGÒ4ª1&®ýi Ijìªâãí’'#´Ò) ÈÂÖaóÄþ¼$<úGØÑ` Ñ €ó#Æ´ìUìy bÖ;B>½nPž.2ÀíŽÁ&+kHú"< ª¢ÀÛ°J|nö§Ñ謭…æJÂq,&nÜÐ(`&©)¶®ï±(âz¨@’ê²b‚H-dRªéPBŒ¥ÎØ®ÍÚd΃!‰åmê¿ldï0J‰Éö—oM‚ó “ÄŠqoÖ¹cÆbd1*Qé.].ð20ìMÓ0òÄê4t ÒÀ°9'°N¯¢»®`¤õ'‘ö*¤ïq®¦*dÿ ïùå觪~"°$hó$ìxŽz"±"¦ )CªŒàf­öèi”}S”BXXñ‚ÊHÆF 6=+’>’ë–1.žž 6bë0ÇgÖì’°'s:䂹OÔ?Í8Œ©ižŸüÎìÅ ì°æÄÈ* ΂Œv0R%TÉÀ ñè2³°ÌkÖ¾r‡Z¥Nå„ä)Œè˜,G)P¦­Îêº#&è¶onhs¾€„îVç—<íM&K‡r“®‰p^΄Z°¨™J—†Káþf³²ìHÀÆEÆìjës TZ.Ê Ü’²Ÿt<`œˆ *’ö˜ƒB¥"î¤a'…¾î­2B–T´»m÷bHª/è<ꢽj¿ â £Z½rÏ5gÂÇŒ®þÒª-ç8m`c)ØõælÖ ‚ÓmÔ/0~ìL”Ѩ‡ŠI'T+§"R5b#F *$æµE>ê·NñDùçòK±žN²nJâŒÖ³ _"_=²Âf!ôÊÈõí- W30"®ä\lÜVªR3ˆ\éßIA8•! îF«= Äë°6ìªn:¥«3ƒ@ž#´-n–Ú3 yGœUDä]JÒÎñ¿+R¸cm_r™‰‘S Ô³ŠŠ‰gƒMð° <Ÿv@Á*0¡÷]m€"«j$a"Ã&R–UÕê‰ÑØÃF¯TÕJ¦H‰âse]LÒ^‚®Q0ëŽÏê 5¢ÇBà iïK… .ÜþGÊñâúã[VîÊ ÒyYÁð$«¶$¦·Ò,v„®](Ày‚¬"ç@E'F­4u*%Í.ª¢÷+«*r59T^uµ=Z•(û hÆMµ9ER5§M.U%.£ªjÏjÌ*TDï!U€Ÿu(IÇc"æs§[ ‚C0hßgþpä®Á* ¯‚I?èÇ&s;gK„ìÎTú ã[´˜×iR'¾¿rPìÅÊ‘jDú‚I?LASh‚ÎŒçã*UÒ@.Ó dh*0ª·ïéE²ôýq.ÛÏPJ`æ‰6“·€ß .êp[=%J¬sfǽ´Ðv†´ •`’|\«®ë®Ó8‘¦ŸjDøT ‚ÑÒÖi"“.Å·(Îp7^'Ï÷²t¡çÿ`IT£Ï•hh`°Iã]èÆ<´E¤ÎG/IÊ}p,ÜÆÑ.¯IŒaI‚š  3‰;)¸zãø›,2{måY•‚1%D¶ˆqï„Ë9/hÙ¸ÖR‹–nv°`w²<²|üR–ëÌyªÙ5гM0×vÛs0qŨW£m᎙ qØïÒfí }hl‹>ö*áe£¤¸õʈ-©­•ä+ð>%AЭ55ÛT1w(yBìbI3PºöÃA÷SÕ\·Åc'»]O Ñ5êà¥ò_MXÚoõ·~oq%ðse†$7â•#Ç]•}0Å0(Õ´óO»u×ÓKÍó#@-l\T;E‰: 2êõ1Š QÒxs ÷>ßÉÞÀNÞóSäBóhºš[VvZ8ÆÑ&.û0ÝVž9þQÇLŒ:¥r5®ZªÒ[¼ þ; åÄ£&5¥ý(4°î?~i-‹÷¶©âS\ì\*­›¤¼RƒÆc^ÎÛAö7³Õe¿ìÆÿ_F ÖTDÿRç<Â#”éµXÖ«gTæLFÎó%*Å^µBOŒg$Cë¾ÍÓ˜à5 r÷.P€}8]¶ÿ† ¸öƒaèP  "ø”0Á ÔP~GáÑ Iÿ‘F!ÑÈì ‡F$’ˆTZ-$Ч(ûòaŽ€çi“ùõEˆ"’J<:I!I$SútŽ' ŸÉ OºLJ-‹>liüþE"¬@¤TûâÙ.…T¡RË;ìu‡MbS×üŠñ$Öe’š´v_¥D(0èuf&²€'shf Y­¿è3¨ýš}„…_¢RÊÌ’-‰…g÷Øv`|Ðb‘ŒŒHµÅ%]ÔŠê–F#ú¥îŸ\šlœ(Õ2%¨¦çøÀ÷ËÈ«6¨ôî?½Š=¼´7O†^´Ïè· IE}Oå@9+ʬÏ÷ðIüZ1®Þ¿hK â< é!‡¼Ðéb‚¾o£g¢Š;Ö(éÚ0޵ςÛ²m’È3hÒàÅ(/r(Þ®m‹ ª€M"“ ¨2vÞ«)Ú+ãŽÁNt_Ÿ«¼dóJ»@¡Æ1ã”:rl #JP2÷$Ic*=Z$Æ" ’%3ÌR)!Ë,3!޲©£ aðÞ.±3˜ÔÊiÖ6Hú~×T ¢+ÊË¢Ê<ø~2@DÅоɑì«(ðý %aý<ÃÈú²¨£±B‹Ÿ´£–¸ É"Æí§”„Šä#¯ˆKà#èGnkGÈ•X 8Ì'üìôÁm²C³3‚ÇËPÌhÖRJK5¤–‰úËÇí¨‡;‰£·¯tES¨î}ñ €N³ªÑzš’dõ+FL`íJµÛ¯}àRd ³_yý ¦43Îýh×ÞP„8…úŠ¡Ð«Ÿ¦÷ ¬¯XÕFG6 &Ð8LmA®Aˆ:žð«O€Z¤ð?Ë«ÜÞ¨qú-Ž! ç®±\ÝOg ûݧouнHF¢´#Xõïð8×!ÖïYJæøÕÕŽÛç¨f•-lèÒwnÝ9ÏšÐù“º/ºÈúÁ{ Ý¾É!åËÙ”?4pè$6°7¾Iû©{´ÇyÏ8¯eGEª\Ùù¸r©Dì;·j[Èé–!Ñ)²¦ö¤Bv`Dˆ÷=cjÊ n!G¹¶¸÷P34ü–"eÀ?¡îpµ2óP¯Í)91æèz§£(žœr‘`.e¶üÇK,#ä± ôT]T’Äa‰ŸT –™ü"NÝÀ»0_[ámnå—®ÒÒN a¨_$ (.˜’ȱàÆ¡¬€—໕°5 ¡©•ˆ¦_ÉeOQ±Û¨‚!GÙ?s §hŒD _dan£ˆŠHûëv„Yo¢@±‰$räüô‘gï"@$–!P0A öÀ)®>'åT:µx¾ØÂèKÄ ³Ã@[‡óiÅn°'êëÉa®M F’Ž›«?8O¡‡€ìÜRêMrѧedéHAk-‡þÀ†Å.Ha®$‹t©¤9Locd¿bä|£¹xÞ„¡@±Ý}¹¸ÎsHÒŠWëuɉ.w ©òŽõjýZ"á]NÀŽ UÊ™4G‘aºØ<ê ÃõmMø—Y‚Au"]dj˨–]¼!ívºôôj;ˆEõÆ;ŠU=›o2íÕ¾2ZšØÅ2g YYŸ&ZÁdÿŽ^[Ô†aTiLºXoˆ2Y^÷\¹½Tm•qHÁW`sÞ¨Iè9ÄŽ¥Å{ä±ÑUⱉÅ+Qd„Q™¡WÀ!;WèÙЪebØ’f€9¬}ë\TëUã¶‹CMAS8KvV.úZD#d€W5Ÿ¿U:F&µ¢" hŒ LGOr²«†>T+Z°j‚}¡ñz´D×¾®˜<0cÓê‡:8Ý–>{±÷¤ôâì©/Ç -.ÚiNÚòQ’’œ"gZþ«Í _b¦nÒì/•ÅfGÃöõvîÉe{( ÞÙ‹™4’뾉21¾òA&µÊ§±„Jf·Ü ƒuòQ5&¹@@u ‘•¼¤ÿ!TËÔ8j蟛ÚxáåßWi‘Á«ÖïT'¥4‡9w"À&¤s¤ueJÌç$F/ÚÆ‰Ú”Y\«€î—‘J]¢-[Š-7¨.=ÌÓŽ{J+ƒ°÷¶yØ$ÄXÆ:±<'W-GÜ{V® F"›yOo»KY‹e) içÌtFFKÞ’+\Æ7ꫦF °eä‘8’B‚œIØÐ…ë, œ&Ú¯Î1’ú€)‹ç©*tMBý€æ,`D­‚Û’$âQæ,r2äÈöOä„*<”âÎ#ô%©1ÕŒhè  €wÚe4[>8C:g*í§Þ”®·tîDêKõœÄdÁ¸"p&âr°4u¢€=ŒÓÜ•XVWVÛGh$”öCÁ- â+ù²BÙ|¨ŠÄ ‚æ¡öƈrq$Q½]#õq¼#ªø ˆ=r%Mí’þŠ9†ù*“†”Úµ~ï,«]+jŠ,치;0>œ[ŸMÔ‡zá]msS1Ë´§ùLž1vê{ 2£|ßéD'&ˆ' +”Õ‰e6ý« ù—Z™18QYÙNOgZޝŠCÑ(¯¡ŸÈRõ©Ó2§«´Øºùc{9øþÉøHÇÒÍ„•2´qvõw‰6xfÁõ‹¶OÃé«âÄu¸ëÄì“‚)ܽÖM¤ n°’ jê6¢ Æ,V|¬Àœºsù拒Ξ¼—H­‘Ë•«…2H‡ª ÍÝ^‰¤ÞQ2Šf\µtÉÈ6 ”ò^;r½ÎøŒ·¨!Úô¤¼²‚Æ£G(¨ˆ ² n“ˆ‡ ¢–«Þ÷3R©(6bõ¯‘J±Ð½< ²ý’a]7‘‚A2Þ®+ÿ8#N-ú”À˜¾ŸB˜K’88¶ ‚+à žâÂán¢ ~/KÍ1®ÑS®³æ%X°3Ì5j…œ˜Ê0Ñô©Í¤cP b‹[‰ Òs9‘=© á¤a8˜Ó÷’¢Ø—ÙÛ@I–²{ˆr7Âz‹¶qJŸ¹7ÉŸ-ñä"a²º&,8”„<®bÔS±  £cc)_Ÿºþ=‚ßBl¢d)¸Êç¡&7I‘z‰Z’EÃ2´¹ˆ€©»ú¿;ù* /®‡!±) ¬qÀƒ+Œ/%sX-2ËA¥Š€2‹‰Ú7—Kù¥ 4›áf)áf#ŠÃÄ.»¹'8»àbeÑ« ÁjyÍ·ää·ºFü0$*¬ÂÏ­³Ô¡ZCú?ªº½jÀ¨¹¥@{—>Có6úù“Jg¢Û„€*8Ç#yÀši0ál±‘…Ç“T$P‚#‹ 5Ësk“’š˜ÇòhŽ‹Ó2œÜÁ\_¸s.в32Ì£¡–Å(ãÇšµ xµªÜ鯬À€}1IZDž¼rœz’€*ë#ˆ›¨ÚvÇ£ÒH‹í²3J`-±j˜À‹s&=À–#c*"ž¤ðœ%1j¾üŒ ¡ŒÔJ¶»Á³ÅJ"&#úé(kšÚ*.œE@=²7šS• ›;а/LCb”RQ"Ü— y êÀœ³[Ô>Rœ |Hʲ©Æìb8!²ÂÝ1–¾Á€tÒ È×B±¸`¯0Ú¨ê§ÃVÌ‘c‘zÆAéߘ$˜»v¥Ôl3´< }G °áúŠ ËŠ ÛŒ¼Z L6qŸ¡K*H“6àãÉQ(¼´-Iv¸Bµ±{p¦º£6é‚O47p‡:!Îô뎡Ú%ÒöÏT¹°álªò"É·r,,;Dµ«áÿ²P}ø£I¥= â‡Üx*çL|Âx£«Âos8û<‹Ñ:«ÑE. `0‚îrø¬º‚ð›!Î’‰ÝÛn»ýKè~:#x’œÊJu³6 <>N•ÃüIÜ5(ôº·Ë¥Òþ>)¯’sÊcïÌrø! ù5ê{’tôÇñͤÐ(Ỳƒµù( ™µºwL«µÑe´õ(2í¤pÚ¡û-Ò Ž¶cyR¬ñÐQMô·¯Y? )‘ À+À44zëM(=)RØ-¬ T¯<¯¿&?X¿¥°ƒD 0¤9/ÅC€ €YtÓØ|ÈØû!ûÌm,¬0¹â®ò§Áí%¼Ü œqº kÕ¹_¨¸‹0ÄqÅ i±˜§ñÉMìÎÃT¢„¨;¬ͪz-6"â1°†/ 8Ç›ˆˆcžH9¬ºüˆ¡n‡•p@²ía&L¥K<ŒV8tû=CW¥+5’¡Ñ›âNS œ:´Gì$®±tÁÜ‚ AßÍt¤‘ýgRì¡Rß/Yv¨,+«ê9\Ũ8zX‹”ëRTH¡Ö¹3H¢åÑjö×ä =8ú/ñJœ¼}9t¹ß·ËÔaJ¨ 4”S•ˆÄcºLÍ-‰×:T0ÓõNFL{°R›Ñ.$vÑE'Â4=IŸÌIú©å‡’‰s.Õ§©ìm·4­¼gµšN#‡!CÏ›é}Õã³|º¬eª’ßBað‡ËÂzÇ€jˆcÆ£Bû1á«Ô¨žË}iE[µ26TL ÄÅ@HP;Û´¹+TqûH½ÁfW˜{׈~¿¡ì*4Í;‡Nå±U$ \ýœË¥4È0IÒË›×ô’=?¶Ã ÅkÐ’aEIŠ+« £˜`¢ÜøWyI¾|£}Ì1x–!­¥Cê@á#Á Ù ÀÑšíq_“Ô'”­â¶b‹–ë2®õÚ‡Ô_%2©µjÐ4mÞc[ˆ‰Jµz«ª¦0¨ Ê"Ú”ß`8“4{€D þI¤ò_øå[j‹¥ÑÀ’‚›7[+9Zb¥BÙÇ$üÔûP¢S—I‡/ƒÃËÔ— t[Gí ÇbU±2}Ò]@«ùÊB²>u7¼™àI™› ň‡¥ÅIE¬ªÃéÊ–«È[Õ÷:cÜ3ŠëE”„Cëæ½£NÔ{¿Ný¬ùßÇâ]½·žާ(Ú µG^¥ Æ@ÇÛѬ’åÄœõ‰¢{Kâ=ÄÒÛbÙÕÜ%}1ø²ÁDñÖz¬Úk,S`¦K—ôÏ’ –>4˜“‡^q¿¥â¹LfX1î¼Ê*´ºJJŠ`=FÎ ÖBWPLáJj^ÜDää[Œ~,º!8¿¥–Tá(Gàϲô¼„FLʪ8×TùL“ÓP³½±^+ŠYWTDmJzÛ¶5fžæY“2!A+‡FÙN†®hÖZät¾I¥ú㦠ÏÚ»¼¬•ÈWRÅ!5IW¿=ècªãÄmf.Ñ!Ľ ©˜Ž¿)xÑŠ£â3Ô|cÊË“5€&TÆÉô¤F3BÛ®3 ,¯18ªÂ”‘“Í`,>7Lº/·t£€5/Ķ:c¶49Ã3Û¤%ÂðíPdºU¢†›" c㕲á¾,:Î!M]!G†â™Å7eB_ ­ÁXêã—J³äC-UÛÄ”ûSM£| ± =N•¶Xf`f›V„õf¢^Hü Ͳ†@™f6íþŒ~Ž(9LÏ|ÕŠ¦SJÖÒ˜¯H×)½qC1W)¾§¨i&*~>OÈ- ï‘3g»®5ä¦5%Óħ+^¹{1|m¤-:6ŠL/L+‡Ã©Ù¸}¥+#új èön± 42‘×Um­  ©•ýs?ý+\eY)¥9^t(m#Ø<¶afbÕ F Ó¹ˆþpd¨Ðµ þ€D±™ú­ê.¼ÔfÊd)êˆû¯³±Û(¡¤+ Gв¤ÄÜ+«¸ÜH}é˘Ѳ`ui»íG©ô#‰bîjó‰Ä?Ë­P,‡îì¥Zö± &´ø/†äí²ä Ä®6Ó,ópIM®Ë­LNË`^“ŠÝsg ¸ø¹YtÜ47´ñEkIE6aR‡ÕÕ‹.>ªæâ£šÜ~9Y …m!\#] ª¾ÌÓcos…,>|•=äk‡i\éd¿?ʪ´EIâÍR =âÓº§cúÛÉÔÞÑLS•;7"u©f]Ð}ZlÞ³Ê7‡Ÿ1B|'–íøRÚï CfaàÝqFpÕêÛtc iÆVv@ ½j²ãJ!jÂ! Ö™›O\6Uä…–– ;Wù5•à B~o*…›I³ÞÁJëa4N-h½Ã2j£QILÀLK‰*dáºEV/dÐm ÷/9e+ÒM{»û"›­uSnÓNU&> =¿·ûV¸’½ø_ô¡•;<Ý¡-f˜ã†§h*Â=éue€¡ö„[ CM5t:âa ¦p«VÙïqÚñ*Z W‚Œ¡ôlùW Áo*4 —mvÛ RuqLïF}-ò8¹Ò½s\ó¯S嫯ÏwI–ÛÔç[P ‰\–Ö€‚a žâõÞvG’¡%ŽŒ~L’eÀÇè'SñRÜ·vÍ>ü-´P³'Äô0MƒxŸIcJCê„0Ãù€4Ì•…±ÔaLãéÊøË¥Â(§b;'¶a;%7^Ò š®<†Ãë8##Œ{UÚRÛ97”ò…ÿ™ÿ<Ì´Ÿw4Îù;=2v#嬲àÙ(<…©½”¨:ÎS`5_3nŸDÛÑuò–˜ú•® ˜ŽGÂ{¿ú­Rá‰lÆŽblqÉܹñ|aI]¨‰ÜµÊæT d茮bk³çtÕç©Jõm6æ ¾šU¹z ·¶Äê®ónË!vö2ýÙU^‘ FuøRjÀ¸‰Ë{J¢ƒºÈ oUÂöê .|£Ü”¯³{èá)¾Í6eïjüË®ï‡ò±Ã:žº³LNA‹c±»kbî î~€5â“ÒktO·µ¢ÒÐ[ɾÿççsÒ÷‚?àÐ@ÿCa@(„ „C!± $f)‰BŸ±økú‹H À9D@–@£` T}úûš&Љ|–K-ÊoÊUÑbR• Èaª(C4}Ó¢±XÈ [™PbSèUPcž>,Òô„kªD¨5U U ÓâФ"¶Ï.°IUfU™I œD"}Ã#°i f©Y¨á$Û}UM‹À§ØÚ¦ {™HaW3ëUYž=õÕ˜|C ÊÁ4Ш4Ê÷™S(›L6ÛÁD`S)õ™ñsÙeßÔ°"ÆÒ#ô¨žâ–¯´¼C(Ë?jsI «?à„ö¥ú |ðÆK õy,¾yîü}`j»ô6çûŠ**¢òð¥ob<¡IòTмHÊUŸ°«î˜" †µGÒÖ IT>ì?Ìk8“îŠ^ª'ÏX Â@Á §*£)ò‚è&ËÆ Ãøª*1#Tô¢ [l‡ Ί‚ä%²µ,Aó&ç!¦MŒhòAM˜ù&Nš%,JÐûüÀ£.R0ŒµÇ»H뮊jà ¨跲iü¨¨èjd¨ËOó¼êº´Tü'È€6àOè#ò „?á@(d ¿b@¤ý~Å¡ÑHà Ž>äQˆàMˆIdÐÀùŽf@i¤Aõ7f@ÄZL–E¨PIŒÊaK#’ÊTR!.ˆNç5”²núŽNjñ‰ÌþC#‰Oçðè´îQ´?ç2'Üb~ù¸J€s¹LR™ ŒMÔpZ©;ÙßóùÜZ1M¤Ã'rë5:?ÃÃ0Ñ8¤æ}&«ØáÐBý•â¦X+KÿH]!VY–B1­Méð`f×XÆUtȘ§ŸÛ-—­tf ¥Äa7RØ4b!$Ç?îà-ø,ºê#º§ý²†þü\èTï_–Np^KF¢w^Šñô;ü³rõE*^\²0ꯎ* ‡3È"ž¨ŠD %‰ûf~1h2ôî',âà|¿íjL‡3Bø¥¡Žz$—D*™4ª+8Çò –3Ž«´¤A ~‹%Ïê­‘Ò8ɵñÒÙ5o‘þê¢ šÒ¶+ˆü`Ñ© ¸)ªÉ»>é7hÚ|K’˜² ô«²ëœPþ0.‹¦è;K`7ˇÄ4-BY"4Ñ›¾¹C ¦ó"RÁ,I3¿¢NÊø¿Æhêÿ9Ÿè´¼¶>îi)Jkd„; KؽJðô޾Òw´ ø¢ï¾¶hÈQÄÆ>hÚ6°4$´ñdñ½c&/˜„Wdº #xÄL“ŠoH=ÐòCGÜÅ“òøKGâPaWbòµÃ®!þÛH4Íi޼Q&JH›R9rÀCýcÃÙ¡0X«ònÀSG!u)Áitïbû•mÊZ¯ 6È4|o² 4(æx]&}Äp—§#E‡ñze§ÕØ'X« <¥?°ðïÏXºú’y7ñœ&]7I½>ƒ!ëV’i5”‚”osB·$øˆd‹|ô(§šîÄTº,¦ËSqö鬵k-$²ŸË<ÓÇêñB#ñB,ÕahÄ:ÌHxD"¢É[q¹²EGd(J,®ÂwBõ¥³¿“,†wÙeâœ[h\è•õ ó«l)í‡.öú’ÜjàEŸD0âÊk›Q‡Ò^mUò WǾœhƒPˆl„7:’>œ›—0Z\;k¤õhEMè~3¾î!^'1$¶ÕZ´¸kãã²È>Ù"ó"p¤V´#ZâÌ¢:ÃXu^аþÉríHëL—‡˜é´ ‚ªµWr‰ˆûZ$äQ8ÀXíI$Ó!:nÙ‰dÎã“H¸ßؘ•Eçûл¬FW_#£ ¾È·3+Âù­T´/Å(nЙIˆ¡Ææ"=’)ò…X–o–›ìyËš—áT—#îÓˆýBDÒÕŸ{š¾ß Óµi¹7ºRiŽ€?ªö»€ …í›ÆDÑȶj™+éçÇÄ‹#1¹ƒd¤hªÉÆ|-Gƒ[¦ªÃëĽ@ºÓo;KÅ©¯Xܺ ´}Ž”¯p&.‡ÃyÒu«Z²é}ÄÑdãbÁjf‹”:6äî>ÛVR_tšêRÕÀoäÞab&‘4RÃðGíé2_åÁRØÌÓ¥šŒGhÔ”HÕG.‹b^ž `¦„/hƒ3^9,Š'²ŽªÈ»“$‰#ªÆKʕإ¡ª¥tØÒwC ®Ø,â]}ëe³hÖøª]kŒ[ÅÔ-›¸öð7©°ÒªVªNß« Åq6uãlï­U:h²]n8_$Ëþ.´¼®e3¬ÕJN•×Ä‘û¾ÈšÉ}?KŽœÖ™TÒÕ½3ÄûètNÆ9suøþ.µJZ‰m´Í D²ÅJñŠ>&‚òÑâà’¯‡ƒŠÆä<#Ä×-²Aî|Ï£¢·ƒzão:(izô¬ªð`®Ê¢Q£¸¸ïÜàŽ.ÒÂí/Öøb»¨8 *V«’bOÐ&伜æÞ¦ŒäšÍ|jŽììŠ êµân{Ç‚ÞÏä"Bôàâh}¸«NÔz8¤Â\êŠé!ú:® .# nAìÆÉF†Aö—Fb1VŽ× ­B¤åèÔPF¬$³hjN¶E°8¤èÆHËvyìn‹6Z§ªIÄÎL_duÎίJ¾Ê©0bdJ‚ÏH”ÍÎÊÌОŠê¥ÃJ;ñ$†Búé˜6•ÏFc+”ÿ¦"¤FŒ‘ƒØŽB¶ÎÍîxŽ Èä’j€!JT¼…R²¦ÜÃîµ.=lÎÖá†"ê@ÃÍÂáç=­Tìk>ýª^Râo€8Jpß"įä¦Ó¯î¦1€,GàRpŒe°P¬"'!é.¼éLb;â ™çK€¨ÂGÔµmêðnô_‘¨¶Ì̆͢µmìÀ…â%¹")ÈvçÌ®­€*î"$É@°`åÇP¦†¦:e5 † $-¤Õ \(T:0²ù(`K¼;qì¾€N&ZªdTÆ[m½˦)ö£§´ì­°ŸËL—ã8T²0@Zm$¾jÓ¿)ÊÀÊ¥”«Mì*å±®òhò¨Ìî6íÎé&EHÒ¬àŽÀ¤oJ­ ´Ï̔Қ0 6¼ÒÖD§ÒZeÎ’pHFg$®Ë(Ð` "ä~i³ NHß°ïªZEäûÅXª,†÷ði¬ â:ËäгlºÊZ‹oØÎ­*²°íË£‘3Lë4Äjec¢~íîß…pÿmÅÆD(cî¼B *2á'‚0Kω*§0ÊÕ¯Îã*–. ·(,¨ÞN´Îc¢ÀRàrdã²j³œÖ Њlž~̤.e¬œqˆ«-4¨M!£ ì—B~µ'ëà!Hîž ¢\äðr$¼½—nⶸµ=%0M&2v㦽qlm†bîs’n5ˆ\åºv Ч’xfhå0fÔ¯5 µÑk¤ÐbêM;t¬ø3Cliè°ú¸³6v ¯ b%rÍIª»iø´qÎŽ³Ã>ĸ`5B5äÒ°&ZuéRÃ_h̤>îù/×ÛÒWKmÂänŸMòRAbØdŒ"Ê}b´îMY&ÐÀª¬E¯`ZÈ_O€³ÍŽ•Ç¾–ò³pä¼Q±¡,âÅSD¹o°CÑvÄTáô‚í µ †³Ó±Hf J¬øÒ,,! ÌX•xÉóסö˜Äד_QÆX‡¶ ‹A#Ñw#¾¶¨åA-`yçxT¬ÌíÊÊ7ÞñÖüeª£+J„;—fWÎ>è r+@øõÓ_/ùpéüED=)€Ê-ìÃäXå­õ‚'Ú"ìàCç0 lŒ¢åâä”ÖÒ²èq$§Œ”¦p¦‰ –ÿq“÷P ÀX“eséá1qØ:&—*î—i0U–­µX‰u9±|&é Gm&5‰‡GŸ\2Ui@ Ot!.M=@ wÁöqÑmo¶Gއ),¦§ÄJÆê§BKA]¨aòâïò³¬LmÔmÈ #•íU¢ S#"6å± bÐÒV,1róŒãjÌLðAþ˰«VïmTTS.C–½ *óóŒOÄbV}›9,’ª”Çzû(¹XVlj¦båìT‹—`îŒû®v&#/‡v.èäÁ.¨O·u´.>ä€'7Òôí+)u»;¢s8CvH/Eq°;*ø('x-¼ÿ÷T-y7¢DâÓ–9º! n´ xû*A#®£D€¥rž1K{ôN*@§É@Báf¹ì‹‚V2ŽjxÄÎ/Nh^» u”à bNcUŽöìÆ¦”Å _fÝB¯}7*\’²y áúÚ©új&Šó¥7²/#eÓ(HZ¬—©©Ï³‹Ï}é®P¤YsÌïv(¼ˆSŸ(Ãl÷z‘ûO iU„PP"D/RäÃN'Ô€ÚVK‹7N(nèr˜ú»d¦³l>ó"¦Ž~¯m3&y‘dŒO¹VmKÛ"³ê3 œÍBEŠÊ(W¥Ú¹hVÊ ì;æÝC@ív^œÅF\æxe³{êлóõF ° rF‘ÆþNÖOªÑ1ï­t0L³»7A—ˆ˜%Ú}Dnˆý !ÈØ\X;è‡xÔ*eªóZÈ‹Q—ÙÇun‰œsLÑ.ÚPªÙ`0ʲXµ¤¨ÞÓ` 4lö𹨊ßúÄÝüšÊ ­Rµë“$T—33—æ‚ 3ÈŽ&×h¥˜&SÚZµ¸Y7˯ª•jñ*š(W’¶Âò-tó*æç¾D´ö·å§d­QÅʃ¼Jt¼ŸG¹+¼«F§?¸à×ë«i8dúMÎO ÔÕUíø¤Wƒæ\0Î5ä²Ð­ÏHr'÷R§ % ì'5ìµxL$Ù`±0Ì’'ÄÖRɨN#³}8¸J¼ÃöU^ËJ9bv¶¦&fª¤]£š¦([‡{<€¼º\2.üÙf«PWèHÒ1+ÄJEÉCq§óÜ(_eW`àsPÜ<ýTÏ,ư!X:xHë§øî/ˆ ÊI†]LÎAâ9k§h8ùÒ|ÿS0–¢uÎô¨‚xóßÊb÷ [C7ñÏÝþòR©Ê zÕÊ'¾½…ƒ vÎyß#ÐG&n_EÃy7æ/ôËž5•n¯‰ 'š º”ò;¿v’7uIÚgA²Jñ“`¯ç©Ê<ªÈBæÝÔ¡ù”X8ä;EÎûupMïBØü¬8ÀîäO›(¦(*ýÁ¦ËãzS[·hºæœB×PÏ#úש6à¤ÄÖª¬“Yñ¿ñœÐ±ÀèWµ¬òØA|ÑhWê3‹Q»þ%Q`ŠE:È»e÷έâO¼’•-b˜qy­Py»ã[áHÆðʦÜM‹¸ÓDÑ„¶ÿh#§…Íï8n‡~¶±ó3’\+sv…h²â%‘º$H ˜|7MÉ$_ošïòso.ã—‰ðcYvúË>1.;¿ømâ™lXh\ùLEWÒ Hƒ?!4. ~Ãßñ "ÿ‰€ã $&0}Çá )&DŠÄÀ²˜¬6+~¿¦8Ô–a5›Ga18Xm0ŠÉbpÙÌ+;¾ã²ÈK)Åb³ˆD6]JÎÞµUnB©Á¤°Ú &ú³Nã²èM%ŠÑä2(¬j|ÝéÑÙ¬ºzþ±€c±©¬N]NšÚâ3X¨.½L!·NO‚Md²Z“Šàà°iuþ]%Æó*´N-‡Úañ¬èj÷ÛVÁR¼ˆ-½¿Ô8gÖ® NÊç#ù…ÝòçCjOÍ.ªÉánÀ<*t6kÎMjü”×…%ŽÍ&É„w½ šÇxT}?)ýèCiÔ}œNû§ì/íì9‰#¨Þ40;,À OÒ0ß1LJbÞ¼ÈÄú3i›2É Rü‚#¨ë|ì/h{¶NJ$¢"0êvû9‰Ú&·EH¤h±A úDé€HJ…¡-;„7Ⱥ0§5‰ |ImÃR/¬3 ƒ8MVÇhj4àî2"†ÉgÂvï“ 3ÓD(¼'ë"€iÛl{¾Ë Á6(k€l}3Ñb!)ÏÊ?9C@Α0 BŸjª ð: 2Okû/ Ílh£#ïz0£©Ìr2 H«„!jbF„T ~´òAöè#lä†5ã˜ÓÏn£[Ö0ü!ñìFñª-?MµÇëfñÚ)|ýg2ÎÃg 8€ÞËký˜ÊB/½% 9])·É®%ÍÓ\ Îdr4êÉë ¦fúÎçë·ÆPÒá#SõQ¥).†Ö¯¥Ég’}µ¬Ó¨ÙNS¦éý_1˜Æ+K(Àãê0—^ñ™ÿKgû°¶Ë*Î…ìèy»»8ésäÆU°ØŒKhíh‚`þލéÜÀZ¸-P'ë…‰¢8$».ñDA¸ŸIw`—¾¯×›(ü~Ûe(ëê5´g ’4«3seâ¹Ôà#¸ž®½Â]Å Y²£c¼;fQdiÛ"/Ñ”cT×TÈ¢·ÕU"t‰R"÷c€JÊ'óŽ«8í>è~ë7©ù¶ngdƒpèþ™´íyw·ÆØxﺇ¯»O½—eîož¡)^/=µ-¢þµˆ3®D«Ùˆ=†ŽeÚÂy& 9Œ¯'ráRÙÿJ̸”—Œ¥ zécnfvÓ‰)f$Ê ç³QÛÉ*ý50F¢Ï‹3|+Èõ¨‘ÒœÀ˜k/¯\4¥) ÞrÒ‹TŒ!„GßÞV4£Áð ûaz!Jк €á—C&Gk%¢R‰“dM}Ð^6·äH¢ã~JP•ÛÅ÷Yâúf­r:‚ŽÛë~dõ¨™³ÚB>%©føç€öˆ,á£+XVî±Ý9Ì]u¬Â:˜!àd•5:&£—"ã8 )¾°µ®øHŒCQ¶;Â6È#ˆ!jÈŠ«À[ÈûiKq È‘7~bNŽíòf‘õ,ÀŽaÞo$~4Y>#i5˜uU€g &_7fùD²:sÜ®>Òá­ƒüûÞ4iŠÕë.È kÈÄñ‚åYþ(¸º±@k€>J²uáž&Ž4!‚òK å•$G„”çRùŸÌé.é½ÝQ9R•‘i "¨±çJf{)^½¬AÊøx+ £€ÊqJ:ü& ¥¦B3c[-bkÁe‡a2”s-x“.ˆçŠ<’I¼Í@áúB@u[b…Þ+G2íH#“ç0¾¿”€c¢ê¤‰Ô´Wã‡ô@$ ’©"óJ.œ)ÞžT4}&CcU¦Z™DÔ™´»€ PE!Ž”MªœSRNMsG)æº ôsc êq¸åæáP ñ©°û.b (ž NiQ÷3=ÑÚ‡'aw-¦þDf³‘Li©ØJ(ßHÑš”½=ªfdŽfg‘¨#˜n*ý•¬–ee*’ÌlÙY‰¶>ÚÄò/5›[TŽpu~Gé`[÷&Ÿe2‚ë%!e94b4Ît3"*‡´i Ö¨íg@”6LÔW¼®£ô2®v} Û—1`—!µˆI*`·ÄÔç—Ò°Õ)€Ú‰ °9#ª|}ÕqùAGêjÇ <Â’’w [¥£TÀ-HFÙ s•Äi9>ÂïeÒø$î¨ï"ñ+Ó"4ñÆ­âaTÈyÞ~î6¿jKqVÚö™¥ªêêk\Çzê!µÑÁóZ@>`ÊuéPE”øq½`ä1“[â>Úd¸Œ,«æRj¥ž\q¹z6àaúd«½·¦Còí‘­1›>Äh£ÔŠÙ¢$u ä%=×ë*Ø©#”#½Jh<©kBèz·^ÔjFqwN®Ê ‘f'ÏGÙ§j+¾SÚ®V>;Æ%üçíOLò 4õGB@û<õí„F2ÑÞå–cŽlìAÊ×}?€à¤y§3yH~ËÜ€4÷#§ÑããöÉ[醘ØÊX8³`˜ˆÐáÞ!5GÜîJÍkÞ¬òÁlÓè‘Ä+U«åãɪ{ݼ|Ï´ ˆô„3bÔBòˆšé€¦´Bäò’µ€¹P¾{èˆü?¢nÞáFõŒc‚ÿ-œ„PÍÚQ·1­%\FÊ„yêd¯«ƒ R±’ß§ò’&c»PKFo@¼A¹å£ÕpÁCä3jLQÎó Ø¦fðe‰gŒ3æ?¾’hׂûbWŠñ&¸6ŸnEšøîÒZQ°²?et‹Í#ñëšÈ¢>ÑÇJÉa¢gS¨ôeòåæ2߯à‚-“@ÜqÍx„;m‡íÔNYŸºÁe-GÓ…j„FœÍ‘nÈ«P£èÝ5ßÓ§NNuÜ/f‰—ÔjÕ5€ñ[OƒP }*ÉÌùUv¯ uÿò·ê©_®=uêïÞ¶2ê• lguIÞvLWBPìüîæÍ-¦]0ˉI…˜"ܯŒ=Yô¹™œJÊ9ˆ~5Ã…ž“2É:ê—ÉÑ¢ñÆ<‘®I§‡ÑB K?/É"'k)¢ÁY1Ãûx“¡qĤx9à㟴œއé¾J`0JËÀÊ/ +|â{Á1èÂA+Èæ Ê£ 2,(ú3 ð͉pÓ™øñÆA˜|X8C[˜ÐÓ“ z-k÷»É¾¯š '©ˆª{J/™6 r>»0‡´Ûd€"-"ùfl‹1ðHÜ“zyî>ОŸ1Æs•·`…Ž‹²—¸„›°n—û(µ™é/œ<±Ig¶››€+¾ë¹z¶*q‚ œ 9áͰÛeA`‘DÛ/2È£©ó#¹©Š´ ÃC³œ‚E—ÓÚˆ.:ÃhIá 3nÀúÕ™œD@Þ¤„ µ;¨è‘3Q5&Yî³F Q¦+h™J|¢qvL;ÛUœj,¡#ÐìE! •ªÈräÌ »àæ“¥ë –ÙôÀÂp¤Êe)šZ¹>ŒB(š†‘3ª»©´³°žÂˆÝ‹éúÓ-–¼ Ú¾ »¦Ù+#‚ !i;@¤“G":¦1Æ 3><(”²¼0KHˆìD—D ›Ät 2ºo«Ãù‡ã{=Âó¤c.µô ŸËÕ›HÉ"²ÓÇð»¬4¡È‘aÁ[œŠ‚ÈHói6š‰<£E”:‰+·CZG r»›61)›9ƒN7ƒÎ+cQ0Ó¦J9Æó–¹tŒ z\¨ï=[·Ò~ÛçEŠ#ž:Ô#úr¥aéFœ¹Ki†>°- ž³óÿr”£·<!”p”°y1rÿÁR€·)/aƘğ¥t{ÆAeœ,ƒ<´«¶»Ò"üÀ¼ê ±ˆÔ2 Áó+9# L 5r¸ „ÀtµÃt˜€! ìâÁ5ÔÄ>8¶ch˜À§ µ ´œ)+“ƒÂ+!‰&»ÔIQŽ Â¨³ºµh„0æIÚ¶%sp¤›ºšÉ66 ~2a኱G¬âÕKœÉieY¬ˆ˜ï@È’u޶Msx´[™EwCÅس2S:JÙ—=ŒêÄS`šq ©Î‰v9Èr‰–bÆáKˆøã¤‘µ”B¼#LœZd´³]Š€ÉAÓÖS¨}˜Â\F ´÷‰"iÍI'°Qà~Q ™¾ê8imÌê72âÍp!êÄ’ÚùÓd™½Ðj‰Úÿ¦˜®Òk@AïÒU0–£¾4i·‘¹ y·Ì\Ç•ˆ[@2­@[tƃUøÊO·t~OK1£"‘0—½mS¼¡›Zù½rU’!a +Í£Fñ ’‰²Ÿ€…ªqþ¨M=”ÅU²º xˆ¦J˜¥=ž­€;+—Ó\!¨ÓZ˜Pž™MKAl&ËBÊÀ‰äÕʱ{¡AžÃ:ä“a”˜ZDÔÊ–¿kᅫ¾ÁâÓ¦úa7~ЪK¨‡8òªËÝŠXíi§R‚E¡µ4 DÚJÓÉØ¬Ú.!õH|Ë/ÄÚ;¼‚<ØÌÎøü Lù*K¶›?OÂc#9œ…<±ƒÄWóÔqÂΛ­?U[S4šFYJ>¢¸M(öË—½4ɲÑDØËJÔѦJe—Y yÒLO(Mn6•)ÙKõL9×¶3ãû ØLÚ¡)X"­µÆm!”¢3W ±L™ó5„Í;X¤2)͵€â ´;%”Ñ•‘Z¢ÓË„ D­¤ŠÜCC]f€+q¼¬ÃÆ´ «_›<[ ÁÔѽÜL–T$ZÊ[éÂõ†×#jʽ]Ü`·K·øCõRRèè¥ù^MMQÝäT$ðÌA ©jsªÂÕ‰^!ìöRÛ*B°Æe©¤’W.Û²‰©03"ôMÀP‰“IJ&!xÍ£º%4¡¤Ëa¨;öÉ­HŒ“ÑwØÍ»(S°k? ´ÐRpçPà}¸ÜõÍ%ó Lñœ#!i;)6?dÚB „53+X ¹Iü—½ ˆjÿÄ››äULF­<€I©é8{ˆFÅÉ[“qŒ’íÓt+‘KQÙ—@À¾Ós{ JЇú“^DpM½ÔDS×Áᨈ…Ò„-ÇÒʰ»Í¹É[‚N¹t³{C0Íš|[Å¿TÕ׉.ŒeÂÉy¹#Í6v;ãû4œwdn«’ÈdܘëÊ•‚gK9ÿCBÿDÍ®JÉ:*2Mì”äݫҼ9Ÿµè-ñÆ\)ÊÙµ¤’¦ 0΂\ ”^̼'‡Ò F 3’¬ 0ÆIûÁ¥ÃEeDK{>`¾,ÓÐÝO ’¼BÔÈ%Pà)0« 8Ü2;ÇJNvrNÌãS¤;T,ãð«!ZÌæ{ Šc#z:¡èÛ#F”yÊ—^?&Øž¥Š½5}–š—ZûËb“DÔÖ’W_#ôH Ê©üê¶èQáÙ«*:xÁ,6špÓî¢[Á—#½rÓ:bó5b:Þ8€6ˆYº#[u4\©—†}ëÆæV’ÚuÀþ˜`mʶk0Ðäxžf‰¶†Ç¬¸¸NÉôY X—Šk—‰ðZîÈ»¬Ðñ¾ê«¡-HìÑF™È;iuc¨‘p§" Ý¢`dŠ_J1;êü5«‘ïgɳ6×l ¶/L¡xá%*GcÐê¡a.wèk>’J ¦¼oÓs2œe!×H–¡‘¥ˆlŸ•–CS‘e.Ñ.¯í¹¦‡ó4EùËÖ´ÜÍ›”zZ,´F2ã‹3Ti¦ 8/û{=@úg:äfh?k&A%§àÉ4LK>—Ы%*~G-–N1f&»-ìÉðõº ¾$T» F¤«» ~ÃXU8ßI‚k§e˜/úê=sšfsŽbé“2,' k];Ñüˆ«Ýˆ{±"Ãlà­kpˆÒm›µõ»è›L;ùDõ^õ}ûßм\‡ûâ 3äC éXö~Y„ ÈënŒŠœ)n0›J‰D[JsÓ„œbÇJ¼ä½[FÙI'ƒDò‰DQör¯Q£#éUÂ#Pc÷ ‘ïXÃåšš“tЄcp|Ýfï†å²™D^[ N“y¦\c¶,üÊ!6c(þ™ «6Ó )˜µ…:`Ya;Jfc¬îÌŽÞð1-Ô¥ ²ïÖ’¢ƒñÀãÜÂqnF°3¼©ö Å„ 5ÆÁlò„ês"¯©£XEx=ë5¼e ÝTÖ‹.rDã›ìŽ$ŸM¢\cObæhàz–®–€?J3ãúÚóo›:,dŸ)¾ÆX˜ï¯†0óåœcN »Ã°ãµ„RÝ#+»†¢I\þŒIbÅ*Ä/gÈ©4 H^Zk»¦6æù‰r;©€$9RùîEµ ¨ÀÃB9áKoÓ²ÙöúñÞ¨>÷p2 œ]ÓY°— Ūs¶z‰ò²-7w÷Šs‰ÌÛa¬Ð›À…|§ ¾P™ó(Íì!#±¼&x™œ)[ºëšÂ¹×éAõ=™›:úéAéUqºÉ\ˆÝî‚àÀXCò†_p÷ôF$ŠA¢ÀxSñóÇ@ùDø’C$ùDP }K@’ùT¡ÿ†L¡°Ix›È€Ó(@eŒÊ¥¯©óö•2•H#4”=÷ Ud§ìÊO( Íeн*ƒG‰T%1ImóAŸWŸõ¹œFµ™S%Vˆüªs ‰S¡Tz”2ƒ*‰GpÀ9e†œÆdÑøÌƒ „ˆÃ0ÒGÄæ%>‰Q!R 3X•[«ŒRùÅJ-³yd¶A}êßÓh&r#šˆÚc`®ž—(¿?$VQý°£Ú§2gG…§Œ‚zØØTJì¸d£¹ýbë(‹m$Ö}9©xX%Ã-ðÒªXxíbs@„Qèî{j‚4HSÒó9N°‰?é{0‹&JÂÜØ0͉ôó²T!ˆ²2¢¢‰”2¡³§òö‚=+‚2œ®ðúP‰'*<,ó¹M‚Ô‹*NBv « ó0Ã1hꛀ1;€K˜í8ˆü&‚@È¢2ÂÈ T„&IÜbüpj Œ°É”šIË”— DÉB•B º‚ÙÄj w5)L4¤ÌHjžÐ€¬2Õ"KñŒ,ǼïKÒ ÉK‰ü£%ª¨@BÌ4a!/IzÔÔ!qýK­„×!Ì‹|…¥­²T³QŒÓ*SÔÊ•L>s²#CV/ê\—¤ ’@œ¼K:V›®Ò^£¶ Ñ^(ï€6Ôb•E6 [?½è¢-L ÅŠ½ÖBÝÖ »Çg!S‘û#R`$֟탶Ø"JÄéÕ ¥z¹ :}jÊuè}m²Á!ZL3܆1È$›d®‰C.’"Ѭº…'Ì E) F¥?uä Ê·)àï»1¼Ü8$0—¢J•MYQ(£§:àÐ"Q#5ÅWÝ“+ÒÉŇúÕŸO2rµ+¸­±3²C„GÔ%AlÙ‹ÌVÏC©’}”ŠÃµ&LÂs¡N¹Å¦»ÙZBï°eH¥³€*Â¥sã7-UxŸÒóé31 Ç/ék˶#µÕ[P¥ëthï:ã‚Ìn[ã…®·Igö »d ‰·Zà¤Ìi ,²Žç¨ëmaaÏ lóRƒ„çtEçC¹RFL·4BÕ#s—#$·¨þÈÝÒÓÛqÕ]ò”Ñ›Š)F9WTU«¾ÖîÎóúŸ±.Þû!ü ý²KVô=~"v¢[Ssi’2äeh{å´-Ø>öœÖÞ÷ðØ6Ëx•¥ç\’˜\ˆýDˆ®IzQxm退RÐÔü s$uux&C “àN化§“BïH©-GÝÓ…f1¶H„©|ª2³àQ»päŠ2wPð\Asfð#Ò:Î& ýÜ3ÃÆÐ ‹auƒôŒ¢uÔ‚='(凸£³x_ïù…nC×›à8©Õ>¿À9QQ´8‘ôaA93Š"èBŠ R[Ê܇¡–È£{­-Î~”0©ˆdx‚Ž@‡ò°£Ê1‰-F)-–ÚGÞªG‹Q!$M¹¦&u«è9;hÅNÄå¿!Gí +MS¦©HBÈ‚4ÔˆÒÖ`R¢³}B̺%R#&€$nÔ)fÉA‰äùô©Öí&[´*P¼ŠIÖ¬æÔ;.® J¶‘¹º¡çsžrE`£€ÛD‰Ü…ÁoFåUWfŒ†u` zÙ›dYNªtĒֲȇ伨ï‡ÀE²RE0.꘰•”ÐðOsÆ#2¯œ#`4íã!ì¹ð’3S¤<7Œ1Œ}¨ÄbÛ! |„0µˆhÒ˜hø)%*Ö[9ÔGÚ2ziSŒ~Ve±D«`¥ $¸ép=–DÃ’E)FK$îÉŠ niÞÃQý)¬y,¤$Ï¡dŒÉ¦+ŸjªKªŠ(å©H+¡F: HT¨ Ó|ÎÁdÚGÖ:ªmÍ»‚‹QÜC³‘ϹC· µJa¥_Wö $¼rŸ(ä6”«Þâ|°I õ¯Éål‡ùŒ¸ÕÒó1‹2È;nR(°Çq©銤ÞKÒ+Ñ |î¢ê8óTÈ'M•›¤rOBO5R‘ÌlÙ‘ë„JQ*AÜ~ÇéîKß9(nÒ*|¡D_$ËV Vò%;Î X‰<øÉ›®ÁAÓUWY|¯¡ñ#wœ‹ÃU})À"¢Yþ¨2Q@´˜¹JQËÉŠ¼ïÆkY EêQ,§J¢ZH}Ì[FòÒû+ò‰elƒªãÉC¡–$GÝâ‘òf¥w7AN´ÉÆtÎsÀ µ“#\Ö ]§>‘-9çF„nÊ ®#æ.FS”¢-o¶æZT‘º*?´ –4Î>s ý{’“N5cœ.îf •C›ã¶o 5g¼x1h¥ÚÈsŠ;ó‚£ –L¦™Ö¡–uP©–d§Ž X‚[€ÏüG„‘=W©¾x ˜}µ^©pМùQµ5ç¢râëXI†Í DIÛ–DbñüSn<Ût¡í¨JUת G;+.¥oUI <eÿ{R¯˜½X‡ž—0¼Ûv¨çCêÇOÂ;^æ;†xfÛËÛøàýÕ ©#dW;hFü žeçD£ZÚpŠ+òB>™rHmÉøŽôpœ—$©8KI²!ÍÌvâÅ“w6ݰÂZVA\E·.nBɳÃB\姦ÝtÜ@<Ê1ôÃN°vïœ**Ùœ‡¥¢pÈ6hYé¨Ë®CZT@\‡šŒ7«§ì¥ªÝ»)Uä<œ¯ äÆo¤å)Ò}õò«ôÍ`!«„fŽæ"P⫠ÇÚ!f„$‡n"àd$銜Ų=²‰æìæeVNî¤ìͶá*”kÂ"ÿm:ì¸ÊV´kEÈ[p #¨@L@/dr¯eÂ,8«!©Lzðoú¿à jÏi!öTÂr'b$õP(„éͪäÍ4Ôbd©ÌÆ¡ :(I?DP㊿*™ ̤fLïö—ˆ,‚0ŽìƒNÄà P´û¢qÎ"sâ|S D˜PKʋ‚ʼnÜ[϶!g쇆Ðþj&UmÓÅšUCü%¤bÍ€:m€k ~`KH•pL›Î:TÈ´#ïÄÁ®ô§ ˆ|PØ_i2â8Œ j¡u9Hh}/]HÖÀ@aøæ±"BÏ‹¦œÉ/4W˸-JÐ"- Y䛇$°„ßÑTŠa%6ĵ pëc; nT[ä"²ì:lÄ,ň¸ˆkÞìíFxÅýmæ#®ØñOúÚgÕ¯;ìÑ1RrŒÐÞ‘Œ& òå*¨ÙÍ‘€- ¶%^¬©ª=#m@/òu°ø{ȦËé4?’†\‚1ºýŠ„¶âªZMÙ ¤ïk.à ¦kÃÇÐtnÿï ãÏ ·.I‡8Pìå^ö’\j&ˆ(äÝáò~DFÅç$óhW‹LÓ­Šd… íÐÑbïŽ.Õ¤´­03.‰*ÑA` <ÍŸ%3§4ŽË¬JÁ‰y Èàå¤,¤Lžn°‹Ki¦­A,’À‹ÃÜ‹Õi¦Å²ì¡'6¿ ¨ìÕ4¬<Ï}^âêõOÀ«.½b,ËcÎ}/¼ôI8Èôµ322.”Z 6@’2~éÈ'1Fò[ó Y45-HÛ%GÈdÏÀ[–µÄ´BŽW‘S@S¤oÐwN“­i'õ›¨,3 ‚ùò=sp»Q^Er¿"²’SìÃMY)Ï6©|žvõ72uÑWJ¦ÐF.‡EñÔ3'îùSBí Iyu”~Ûã\$bHÐs¼C0iMäš ª|‰\—maýj" Ók(“(Àâ$kU5)•·'Âë4L¦…:PUæìä™Èæ‰ïhú *,Be‚yÓJêç>ŸÕHÏðgçfnO=Æ„²—ò&ö?-/™XÑ´ÚÍ2ÿÃÈ Ã·C¦÷”n_’QmÓ`è=-†vÎBŸ©^^ca¢¥ Bi Nµ³Tƒ}\WË >ç4Ç7µbÜ@TÒŒ-y=b%BdƒVÖsçf¨¢UФ(% O=5´Ú‘ê39ªøñµŸ:q÷1Öî÷L‚jÌ7G—R3¸nÖ êõ^eü‘€‡5;_˜ECÍÚ“+b-‚ETΩ`R&šëôÈ4ˆsð„UŸa*ÇÁòZE_JM;ŠÈ§”í—…^_ÂŽÒâêæ !³—ˆiFÌ‹düìBUBe¦A]VpÎGÈý%çhB6á´]D놂 †.Ô.%P¼ˆ Û]ª™ ¥´•{’ðŽ×u~œ/ÕaÓžye°ø±0éÉV”­õ5$‹¿0×¹ôâS1YÒˆ"HÎòå?Ëô›rÖ…Õ<éâîA•?kÁ8ˆ¶)¤°„LG1f”{—µ $Ë:7<0žkc‡"n=Ñ %Ô—„2ÃÈÞ)Z?$½kœ ÆÝ¥2‚xoR˲[Yé4ÐÒaŽ+ðÏ™ƒ¤eº«Å³zþ·ì‹qrÉ ©[êDƒÅ>¢U{§šx×Ðf\Í×>y|Dh¼ùÏûpÙþjBn̘娎¯v_hÎøJâã§J¡5`3¶:ÎAŽ“ îâÏrƒ Ъ†“·iLÒÿPÅ Ãm¬áýn‹´{ÛTzäÐÖ1gÃÌKNÿ\#ŽM§ .£T†ìîX#.’$C`ü ^ÕEÀì…^7Ei.I_;ø©Œ î¹ùŠdG°Øq#útã:Ÿ3¬Ï—xëä¡ õ‚Y(X‡Œü5/ cuC• SÜ'zZ%ð\*‚«P™55÷IÑeli ‘F` sc6º(Èû…!ú'ÌY5z:t¡E†Rb ¢OÀ`e÷­ø¬„H ;@tv“¡–P66¬1Ölºx¼¨ÒðTgð³ ŠA kåY€5÷rRó³'C»ÌžkÁ–î•/ä[ :S¦\ˆCEç^ÌÒîXµZ|µÙYâx[%Ê×$YÏc ⫟&þ×÷ÔØ­ ]øåʲl(µÓ:ŽÃñ³‚;} JÈh¿-ŽùºŽb¥¾ùÍxúõqëõ(‰‹‚»e3UÐ]™"±Óx$‰švC·›0¡©+¸yØP ±Úõ˜¹°sMÛ¢3vw±›¤"ÃKÈSîÍ%`†̴/f‘y¾xäæ^ÍÃ…}§½p{ûˆ†…;bªlà @o7P3 ùÆ8þ‡ kbC0×Ìj”–V¹+¸#J+*¦òN§+0AŠXÑ‹óÉP­˜2sêC?U¤!÷ÞoF² ) nÔ„)Øû@Îí0XL=Ê,mîñ¹3hÚí:Éx±³ øÒSýúlR‘e̬Ýä¶5™;ú÷ªju{†…ÀZg ÜY°®Œ5qŽ(&]^ xò.Ùv:S³›Âø£ñN<|ÿìtâ¨&8º“tÜ2( Ï™ØU8Ýš©‘ƒHw4âUTUÔˆ öÖ¼Ó×"dA¶¤X•ÄnĉáÝ›ÂP-OUÁ0S°áfŠ)JzrP%\;ÃvI_C¦­àeøêX‰ò- |'zþj66ˆòPE¤ë €0 þ…A€/Èp ò‰b§ð1 }Æà@H´9ùCRY ÿ•JåpÈ û1•Å¡€y´‚-(KÀ³Ù|Åû•Ï@²Š`/Ãâè$®6û—È%¹}b ­Oæ4G¥~( †E¢ÔxÅVXÿ¥BªÐIE¾/¶Ëî’øeŽ Y!TJD2W ¹Êã´Iþ ‡>1“`> U޲Ìn·Hd¢;‚HªŒí¾gl•S®‘ܬ1ï©ÎC©Lcã*¤P%‹[û/¨ÞÀô¾£³˜ïž7ÏÌÃ¥øì•õŽèJ*1Ù$—‰QÌA¦xF‡qwßÒü@›OÑâeXxÌm×ÔoÑŠ¯‰@èO'¸é{^–¼Iî´®hchÏ!Èb:` ê#k›*ó¢Ê»¾´¨bˆ•À‰dñ=CÏNšá N1òë¤ ‹2’‚N±+ø²°êc3vš…Ê1 ¡Tòïq0iTª(zK)Ùñ½#+É $CDm%ÀÞS]Å/Tà%R°¤’JÛÐU€+º*Vb*ùèúÆ8E“Iñò‚/hUD²KhD=m%J‰P]˜v8Ê€ä½tÀ«Jˆ‘<ä q!Ž$W˜Ÿèì¦Ý¾MZ6÷;èžÖ§õÝ+2)µJÛàR â$ ‹²¼ú¥V.7*/¡æ[‰K%¸„4Ô³>ŽÅz`´MsR£vk¸Ëϵïuõq®ú¥(²nÏÚêÇnÛ‹¡dHZùSʺŸ.±[ˆÔ5H‡9ŸîÒ¢DªDèD*WVúüÄ)# Ò2œ Hå+¬ä÷€8òÈÏêmHöM{Ž•#²í,ÇuHso¿¹]ë¡a£u×øÒÆ›VÑÖ¢´í@£6ú™Ï¸öñ~²ŒNúZcwŸH²ˆŽó9g)k˦qKMJ]ÅÀª'ß—R¼Rè.¨5"”‡ÅÓa*n„ö"yKqZåÚ¯ÄêÕS=_‡mq­JQ¬bª½¤‚sÜ]p)È“x¦HƒÌ" +­ƒx‡–‚âSݯ¥7ÚFxýs0i€S XS!z&)Ó¶s-j‡ P½H”ײ©#®€’”GbéáLL‰e ®GþG_£m$ ¤UZº™ò*8Ð4¾“ÕìN˜Z¿Z•G›"1Ç«”w¨z¯5?Mro¯}†Eöí@˜Ylj÷HuJHŠ$v…!²°TÍaC‘|ÓÂ#‰é6ëvL.uº¾å+ä[ÄÅ€Ut= Òñ;ÀÞAÉHîqÄj‡ý©k“Ty# h›:I’G×GGÅ"y $O( š>85È)Œg³ PáY•n$‰RJÈc— ,&æÇ6æP„Ãð൦i&ë½f옘²'CœJü‹²=¢*ãÂ\ÛEcJQ¸ÙöT–¬KŒh69â¢èñ+q)>Èé@¢;¤ñZX¹/M#ž‰1 9Òc=Òô› ±Û’„³,ÛÊ¡Äm˜1‰y"Çü˜SILES q |ê Æ~¡™izy*¥mꋸÄB‰èdŠš €Ò3ò7+3ôðJ•QgæJŠ$X R„Í’bHyD’ë(¨µs|IBŽy£îLD0ÎÎ5,2q½¡2ÞÜIQªB¢¹Ý'H!QDˆ"¶ MŸû§å¾oP yêÕm®hÚÔÖ±`¦ÅK¦PáùRJ᪠( å’³$CJ„°¶ ,‡0qô¡IÅêâÚªhP_òS[°þz=Qýda´_HsmÄÔò ݬcÿeµn|®u š]&·3|¶t¨]id•ö‚™6b›/VÚi¯n¡1ŠÈºùWé´"_1b[€_×z/ÚkÝ=SYäKÐ,‰H¤(çúË‘¼x’¹Ÿ¹·6¸ÂA-HcT¼6’k˧zg)*}dö¬Ä—£sW³eÀ6øõ;%”KowMà~ Ó޹s»Î4ó¾¹’Ò («.à>ß‚¦Á“' ±+‘[Ô'‘V®A¥; 9Ëî¤ùÆ4›ïL:Kô/ÀœËÄ8 < Ù-CŸ€#—¢Ð}4ùÀZ\úõ=ª£4èk°({\øÆŠþÂX|¯º[Ÿ‘Ä“SÖµb2³‹Ÿè²'D4”q»( ¡&âÙ‹K £Ñ·³“Ø“Xè?˜‘¯²Q/ –£"û”rÝ®ú‰Aójž‡Û ¢Øžªó÷#< ‰C”±T”ÂÖ­Ùé-ó×0תºp2Šmûo¢Y ‰ à =°’Ê3ƒÍ*™À0Ð4j\¹AP!¶? @é £tE€0¹‰·;#h Ó¾'“²9YHóCÙÌàР;ð";c:Äl¶° š!úݱô%ˆ²ÈµEÜ™éq«Å–Sï?‰’¯!0*’%ɧ¸Ã6Ió¯iÿ‘ T“ë‹»å¤q•@Ôˆ±…6)GÑÿ2"X¦Ê x~(ðŒù±ÂfšSäHÒË ¤ûþ aç‘‚1ÂÙV¶¢ÕHì¢ú|±²•¸d36Q@9i—ÌsB²43s£"ÝÂB ,úÀ¹ÿC³å»\¤óY5‚Í£‰Ò´!¡‰ ®h¨‹ °#ò‘¦t™,ü1Ã’Ñêݛ軜KïEqë‘»4˜‹3Ãp4T³j¸!ÿÇ‚Ô%Ù£Ó6³£Zˆ¢ZN8º®úÂ9"@~‘XÌãÓ–4Ÿ<̈ˆ°âK§½s…C{­ºì ¨Û+“8¿²j¤£ãLƒ²—äÂ1[мÜЭ9n»¯QPL;sç§’Ý¢¬®Ç|zÄ*†ä:5jü® )7â Il™;ÜIIœë!<¶Ìd>ZL1Œ£H‚§èƒDô{ˆ‚‰2ã  )Eì-?ËH"ÿJql±É#uϰ~ÂümÏD`‡èÇ5Ú‰ÁÒšÛ¨ÜܶCbˆÑçJ¼w&Û0‹àðHò6¢ûüö¿°3Ô®•lÀkÑ#Ó LbÃ«Ñ ­«û üñšScÃÛ²%«9ºÂNB|x¸)"ÂÛÒC1ˆN4}ÊõB$Æ»ú†„7“hÎY"Þ¤:Û z„1©K©|º¸u,:¨+4 C¼šL©Œ¸Q‹œŒ(ž°3²¸ü“µ‰ž‘ŠÈ#Š;9Û-T¾‹â) Œûêñ‡‘»ÿÒ9ªÈyçÊÚÉ£ {܇Ê̺›Ã¯Qð³t>¹ YÄñ©3ó£3Ëh¯có‡ÍG;¢Ã¹"¼jð—ôÂR°»žÐ× af ÓþÃü²ÁÔüR¯1Aø>ø¹«ÃÿM 3™k²kÏ® ®œ1©+Ã9JæÃ+YĨ«”/¤sHYEB1À܈ ¤˜ªB×H~ õN4 ÉáÚ´úóH5T?;›ÂÎD=@ø¾Q°•M>Ov¤QØ/ÌåÀLE’gŤO‰êÀÙt‹©3ü@dëÆ­b¶Œ ¨™49 ÞA;•,”˜™P2Xí˜I Ö2²‡ä´ž±þRZw•ÃR¢Gmx,ù|Ø“õÐià.£»#›…ÖÛÃÌSNdÒ‰í!-S•Ÿ€*hJœÚ)S"E6йOÕŽMÝ©NmÒYH߈!Éñ̳¼‡Ñ>ÙÆT£’DsAK‚…¹Ý³L2 3P}RÛtZ9º×øóž›¿Ö(Ò#U[ŒAbêjÊÊe"Î"sÑÑÿ¤të—Ì`; ’+ñù5ëmD1ÍÝJC³É\v›Ü5‡Áí1\E @­k¼äî@Êë+¥œ”V¹äÙ£"àª,ß r†­Ý^\1A‰‘]E1›LÀœáJ f×¼ »#–‹œèiÚ\+å/ÔrºWÌæ<…š£ªQe‹ «#º´T“´*^³0ºXƒ }’ºAe."*ÞhÑ“K¦ÙBݹ/Pš‰³žŠ”.™¥Ë}=„5Ùa?¡…Ûÿ2©A§¾X5Šñ|ÁˆHÞ\ª)AˆèlâfO˜{™”=€9]=Ô—B{¾-\-‹ ÛÃ,Ä®¢E3£Rmîá›”’™·Äéê14®±<²Ÿ?+ÎÕœÊêÐÛDËP ]¹Ì×´°šV‹✮¯d/\šK¡øÀI4, WɨŒ^¢GIÔ: ‡”¨”4}ÚêÒF‚mÖ‹ŠÑüOTá{J$H’üÛtèª14E:£LyÿÞœ!ã ¤0yë@t‰µÐ·Ý|%ëÅP„ØÆ<ÅüDiTA™1JU_ÛùŒY tSÐíÄV…„ s÷N¼>…¹A+ÖFä˜Û¤&«E@`ê™Ö4ˆ:PŠ"•…“\"­ü°Ø}”‹MX’ð¤Q0{ /ÌÐã_mv<,ëä½tL?³…N.]d ßWA4F~E­½—©4 芭¹ÜBâüÄhÌ8¨ÀÖ ž ŽC´¾-þÒ¼;Å(³ÉÀCÀÎͤ%éq>CÜe áíaAÃ<£æj°ˆMI9)ž•@RŦݹ)=2?gv;ÐÌ= D‘ÖaK¸‡è°£ñ)ÉK VâF=qÛ¬ZÀ,¿Px}±è’ î—b@•jÿÓAKkL¢[q\ú‚â ÞÍ#2ºèf›Pn¾¼ÔF|3lˆ˜JÏR?Wš\ÇÀ‘ Ä·f¶.¥£´´¡ÖÙ«zWª%±½ÓÈ|˜+§gž¨ØéjæŒR3¸ÜîGk«‘ù#Vh{±h²ø(in®PKX­,þã-"«t˜Ûîšêô\_ýQsÄ@¼SB¡gŒÅ©»jtò¦n»r/o¸:ðÖaç‰?Â6m ™ixwJ†WXmµÚzDÚ¤tP./±˜Ã÷Vc¯Ÿó’gƬ?šjÜ;±…ë N|3þ‚‘‚ErBðÖÞ8l-B-;,kÔB/¸¹öƒ·X*ÍÔûlÅ%Ì(¤àÞ1Œø˜}ÀvxúÐÀ¿wûÇã« ¯ÄŽ…\$¿kÆ>—ñAÃiê|(}½] vm%ôwÜ© …m6Œ¨'ÏÈfni§q‰Ìà•NýÇP³Ã²fˆ‹\@€àOÈ#þ „¡PgûúáV- Œ È´^C!‘à2'‹FäPhÄž ‡Æ"1gìÖ' ŒE¥oùD‚}‡¾èSˆP†M_°ù4&‹FÒ¢Óy\º) ŒÂ¢4'Üî-‹Lâ±:d}=QUøtL o®DmàXÝÆ#}^k (ŒN•y}°R¨6 €†a¢ÏŒdN1FTá¼5*7£`)xE±ýÊÍ¡©;¦×¤·ý*©<„d*QXÅ6O;µR€û½˜•R®ð(|?Y¨Í_<½ØÏå¾r Ñ>®Keðmg”ÁE«‘fÇ—=óÁ0̺ßí—C.t«ŸFI¿‡_tà 6jè®K{T&(S޵µ *:Ú³ŠºÒ³5 +pÙ&­²H‡´‰b²” ŒˆÁÄ "lF²!ÉËPê€h³ü‡ê&ˆº(› ‡¾Èªç ³,‚5Œ‚6È"Κò´,«l½§PlšȪ2¸µ2ð2œ7®†,MòjÈ!Œ!ÿD-sb£L(#Ôº¨R$”•£›¸=G¬ìˆ²‘ÿ<¨NkЂ+’L{+ÇŽ¼VÔD2¨Î*ý/¨É¢”š¦HÜŽ¢(Ú6«C ¨OÐJâ6T” òIóÃ2¼«p ŒM‡Û  !Ó0È5TRóÔ½£Éÿ¡LañOÁýQ ˆÃšã>3˜ú-ôí&Œ.m{=e'p<<«3Ö€'É‚o¡„‚;Ö5H:+œÒŽ"¬2è³"ç 5÷∾s SÍd1Fh´“ÂNô%E-PŠÖÑtÝÑçël«O‡ÝA8ný¡'Ðó›I)n+‹dSoÛ_¡Ó aCÌR@‰Æ*Ua¢·ò­q¡pm{’MíÅ ŽÞÈ5¬ý50jÑ\P’ç”))¬ü„;*Ó‚Ñi­m&~ápU*àšš+€//Qéµ°Í{!~¡Êåpÿ¹qc!AeGò礟èÛ¢µIõþ´»Ü˜¢jˬB ·¥È{šÞÉèÛ½€§¿-œ(ËDyÈB+n]tæ<Ï@0  .Ç[Á+˜…yZ\Ò»E¼1ûØ$Pòv‡®r¼¼w¯Y×­ìõhâ°Ù çåÜ ¦ƒÜä°_žÜiÒ¼»¨E(VuçÀö³mß2>pÀoŒ6Öz_KÆhÒ d)\±ï§Ð•óbA"]¤@GÉ‚@ëÍ#æ¤"â7ªµµ±ú‹b]^%½uǶ‰ ‡ „M“»eÜÀyEî`#ÿÔ[*yª ö“¶˜–I©Þ+™ýè:ÌAÏ'ó ßÜYP}ê~²!øòRÚN"¥q¹fv½zPfé\×–¢"²óÑ#­ˆ…"4$Ê ºOvOåeFÉó×B±ˆ°ˆ]ãkajèÜ×bÌS$é…8ƒ¬vÈk*lhñª²‘ü÷_Ù+… È@qúu9 Š\´Fzè@"ÆŽ€&%T ³ß ‡5‚A“|c,n@;¦•"bY §e³ ³ÏQ‘uZ“P/Ç´Á"ÎᖾخMKG·µ‡ã!«©Ñ è¾j!"Š IñÜ0 "BÓão<ç!yd0Tä»rÞÓÀþXFö’Vébºtµ6 v T™8O!än»Š\mšÍph±'ÑUe3Ó} ¦§hG[¨lòØ•–dô-yGE¾Î¤È–££yò@Q­k9Èjz•²\8oÊÈŸÖE–DŠ2:¬©óï¤ Ÿ’óõTûóÙ ¶¯öØZŠc)™U¡µ þe•K BÚDMàŸÃÂEf,/käN ºr ìü ðÄbtX¸ºÐâì!ú! Gö’CðµHâ0üŒ2—ŠÍÐè–™oi¤5$Ч£üY@"­ÖÇÜ£¬í&¹HÙáÛø,,„ð+ˆæ¢ÏsáY½\Y”G’:w‹}'e+3ö:ÿ"Š~ 7y0°¤EE)Tê„´Ys˜°Ì!­‘éÂk_ŽtDÛYcmŒôŸS’ÀÃé!Ÿš’µÃXÚ›_”·©8h`ßY¥ 7Ó£Õ¬X–š´DÖÒ9âì]\°ÒÀõ'­ñ¯o¦¢àÏ[¸0ûΡÈìVȆ±ÅÐ>æ±wõú4S{Láeb?wUç‘·qp Ó¨çÙÙ>O§´»$·r‚ÚfÀ/+kãõŽó ÝcŠã¦‡ŽÛGv1úÚÖgÚñ=aÈnÞV 55‹(õ-nŽé¾5½^#?n-jnCcĨ·³lu|ûT×vSªÀ8Öa´¡ çSò¢2¶¥(¯â• ŠÂúg´Ñøý¾Ê€ÄNôŸä¸Œa[Ú˳ʽ+ZÉæ´#lÆæŠ±¯Bd– æ±EœÝ…–(N|ïzn,J@ãú/#¢2náG¤¤úu¬¹aøb%ŽŽaÍ6Ü+æ‚çð·‚*“OúôÏð!Š×ŽÄÖ«V$‚à ±Þ"$ì¯k°¾ˆnLIH(EqëÛ/À®PxùÚxærkîÔ@ìG,JålFe È"t¯˜ª*¨¨ª/¬èrnË€$†b%lÖfºÍ@¯¯"HÁô¬æ¾"# XÈPAMàcFÔ­lÂÀyaæ¹íÔÁhÞþk.kÏö¿J~CB2æÄÄöÃvÃÊnm °¥Ê Çh'oœ±‹Œ³C†‹NV"jte‹tŒŠþõìNxíøÂ6P…°÷NàAþò(P0ÈB0 t­j‚ÿ°˜cE¥† ?jùÅŒªã–Ä,fn–Õ,VЂŒæ!ññp+¢ YŒ+#¢Eí‚AI>墲 $BB麴Ž@†®ú”KÅdº’«á ö†âÔ£À=Cˆ±‚ÃÔ.gä+âö%VFBË2ÃN䵺ðë”ÙqE†å –i~püÄëÔÉË®ÍÆ2µâ¸òQŽñë€pHuBöµP‡"‚ø¡Ã=‘Q„þªH„ÊbËë:Ir~¸¡þXÄb=QŠž«§Žî…†©)¢öôq?#1 DÇ= ‚f£ˆ¨n3ÄÄP±&–2pÇ,Þ©¾#œÁ²nžo RÂŒôe\~C¼ñ"=#ŸÑáhlP@jÛÇû 1"²¯&)µLB"ÊtUÅľ¶(gªAË^XBçAòtÍ'€u )ìÞÅ)F7oR¤ û¬h.a¹5(ro-æâˆ*uÁöø«*elS)'dXui¤JúCÄy$Hj_%¬ŒQâèQ_4ɼEW4}¶s³˜óRÊ$òþAÏ0á+èQJÊD"æänd¢&2”/8ÓaJ/!v<çG6OŒµæ|agÈ0D$ËqwEå.℞¹åî9m›(Þª6¾14©@½"òÿÔA£ºeBç/\\LwIhY.R rкì úD%žŽÕ:8§p"Ψª.ø%ÅN†Š › D@f¿Ë”Rôù>snâNÿ8 Ä"HÞ~Qý‘déÊ 't Ç+òýl°Jål˜¯Ô¨Ìˆ`^uq©û="*~I‹EˆPÛfùT•’òTpl2šÜ«=JÊQF™;gfįZ@fB‹@ÿâ dоËB asšãÂAõ^ïr¶›M…Dñ@¯Far:ÎôyZ&¸*ɶ0Q’#r;AUR§)ƒ:BÎm7Çž‹ÄD*W‚Žª¥hÖÅ­2Æ Û`úFh|O¶®x|V¬ÃYTlý£‹Ø,γ¬ +m@ª¦9g):¥çD¬»ÈW*jSC’©Užc,F"5Ëâ0×p4_&:mË Â~Sÿ@¦#“Äáªj“ÞYq稄Þ?t_Û[•Ñ ï`ÂAúÑaúþÊ,üÍ,›²w\Eq©ŠW”Ræ˜LC!grüU^ÿ¨.õkÖ=ôº` ôp`ì 'ó<¨§O7FZú±âñ…@p=HRF@å™9·œÞÂBêª&Æ:í©<ÃBþš”^íq^tD)RfÈ+c–è˨ఃBH¢† `o…ç;ÁñD’šÒ*‰WÛ+ÊbçÒ:~I6¼‰çSB*N¤ïLRåŤîÊ~×êæò§m‹Ô×C• ó€Ú÷ íJ) ‚-H‘_­x0ÍÔPLúz0țϼ¾d?5»_“TËtóYwü° ðLà Ò"±ÑT˜7æ²Ôô"¸p.ÄéÙðŸEËøb-®- +\u%v3$ª „³³ùI抑´Î¨×(Ò¡Êú €al™+r‘Äh°uõ>ÙARß;“É¿VÄXOKžò$%ƒ7­‚íÌh£Ygã_ˆ±/lé¡ÍÁ‹”¥÷ÃÎξ3G"À:%‘_¥'@©¢5î÷ö|ÿ³è¾vðÃHÏÇŸ8P4Àó!F ·´˜ªXi‡iP #­ôx펠¶\ÃN!‹W6 ¸ýh.QTø‰ë2Cš¨‡Øo3²Bò]â•sV@\I7S“4Úò§’øgyG6Ñêvi…毶q£7ŒF_T$®XÓÙš@ »±t£Öˆ®ËPð½@t_ Ñ_H:±ÔcëŸ%bà(FÆÂ˜Ê‘ÓuŸ´}¢¹  V¡uÝ€-ôÇôaÆBL«ª¤¯;¢ŒãQ6#Ä0 ˆ£‚#…AëVÚ~ZŠ’™ ™½øaiоÏKQÏèÿ¤ŸšBï¢I8 ýTJ¥Ë” $TT<¾6T7`òxóÝ*ï[¡Ø”Ä$Ðñ)‹QŒö@ÞbÕ@VÄ|.n'v3ÔÞžQ!“e¦kö¹ÚáG T¨éGc'Ÿ¡(gù¡Nà ELP#a«»¤X‰êô«d®gÒóÕ¼»u¹­µ` |ã WÎF™€±ó™w ÌÁ â—JÈ ŸÓÿ‹ÔGix!¸ˆï7è¡ô°àN¤B¹ðÁwe>_6tFŒ©›±9#P+ê£s CzQ‰‹æƒ‘2%sFµÃ<¢ñÚG}`CÔ"rlj:HòÂa{&¨·ó§LÀ.«‹“¨Ç$VÒXœV"kjAÜ›Zc•u»'p®ÊD&ó§¬ý—¹kÆ6ˆvƒÇÊ>îZíJ<ǧ{3ãlËìýGÃÊb|èPY-¼ÍKÙO¼­™MØ3,5 ¶>o*œí3}xûB«Mš…¥ñÝ}BµlF`…l)R:ÇÖxxæ2c¯Üz‡#ºÿ€ úWæ¥-#;@‡BÐÁ§ÙÓkáâŒèæÛý-ÉG‹6bA0yÕ3ü -Dbš8µ—4¥;©ˆÖÔÐuc‚"|åß°ô€2®d8—MC^ò5îtÑôU¸äµa†h´ˆ¤=§\®Ôb2é7±¦-©©),Ä]dž»l§L­½¼Ì*Ѳ¢2!‘£U$aoG@²Ñškॎ”9pGÍ|3먔iÌ¥ªép“`¶U+‘ÙfA¹Æ]¬8®,2ü±×,1‘}-Õo[¯#ÏáÿEÄ|.¾GL æâ7д+3¦í]Xq¼ˆµyd¸€ Ö4ª¾˜¦°¬”$‘•ƒ´r7··‘ÖÁb[ …¾¬¯Tµ@Ü!ê%O”w‘ýé2kà„†8¸#¾ƒ†@yP5åÉæ}=¹.ä´#_¬;ÇvØ`*ÍZX¾PÂúÀ!XFrŹÝB#”ùh“®ÿ~îÿ­À‹Y¬2u#*n¤-WB~€8°XaYèY‰ö?¡ìÏèkO~þ…Ò2ÙÖâßþ– ž„Ù•‹Ÿ¿=gì¬ çîYè,yˆØ-:k7 ÌH‰„«^Ž5÷)(wÝ™~6}¬ýVN%ÉžŽ±IÐŽ6j­"KåÉÄý@¶ÔR!Ò;LÓ‰ùr—J)$z>ñ­ö&¾nÃ{¡ô°> žo˜Þ!óûôëV ƒ>!`"ý‡?âL‡?aQ8ˆ 9ˆDâð¨ˆI!ƒA€9TF#"À¡RçûòiFã“4 ùŸG()”MýE‹Ê©8½ü§Eßu©Q}Â¥huhü‘É#Òɰe¦N€‰Ev»”Eå‘ D*‘†*Ôʶ D¢ÐàUÉ¥î^‹‚q¬U"™]n1z ™L·A. åð~bŸV{î;²Z Öj4:œ¬A-“IEÞâÿ„>4ÑLÝÆ€÷ßB°’ÉF2‹ÐP"÷}Ì++«~äóÍ‹;0ƒpg.½ƒœ°æ_ú‰<#Vžmåª<ªyÔ°è!@¯–‚­H‰Ò'ÏœlCƒ .h3,‡)ŠCúÒM«Äê´à:Š˜¢»€' ͬ œ´l2û:À•®*B» ,/Ùþ¬²*Ú8ê:LñC*,¤½‰*ó$‰’L7Ǽ>¥Š !KÊŠ»À.°²oÊP°µPÃøî"-ºÖȰk )*²ºµ ‘CœÉ¨´Ò‰½«ü9# J ÖÉÈxÏ4¸®©²t‰¥ dvÉÐ:AójÒ•Mò"8‹½`²ì© ²dü²lå‡'ˆ»ä"òãëE¨ªí=4žÒc&´< zKª’c=> J²€ÿQÈtbK)ªu[@î̹ ³•ü:~Ø-,®¶ªø ¦Sˆr&ü©TâÔã9i¥U¸ê+³´ÛºLR™-»kòê'ˆSnɹ§ôóÞt¸û¥J]”?)â‘CÊuZçÆñL.êUv‹Mb¬¨…gB< 6ˆ‚®Ì¬ª€žR¯°Ö¨ã@Ä2¢ºäêî9O°ZPÐ"5ÖX±³– ™B’B£x(“sŸQü±³Ê‚£‘æ* øC‹¾jðéLSþ•BúX$’Š .:–Dˆ[ñþ¤=Ò8Ö¢'®Ó.‰V®ž§Ìš.®¥Fì9žĉR­ž€8tßnæPæigè®+ïgúõd×TÑú÷4Íjm€u‘ÈzÑ? nR¨ß©S\¶.`ñ”B¢Äµí¥!Ýl/óÑkÖuÚ Û2÷ÀAŽÍu*Pòåó*éíEºè( ¶ÎˆtÊXÁ—¤¬ µà#ʨÂôÆõå퀘Êk'Äù›ú&ÛÉrÚÅnŠI7áÎ pènˆ,²ä¨×‹SZÆåå%Ǽ>Ü©:_ÎÑ7TêIû(PkÁu ?Q1«9ãb? k°‡xÈBÛ“mx±C–€w ô%H¬ôrœèÿVPA=ÅÚB«9¯ÈÂÂc]úÞxN-Þµe’·KC†Ah^ ” Ã9}¤ /•Øb…bó¯_ $ÅuŠx ¬>:‚BÆÂvPº>8)°'¸Šÿ¡ái.ÉB‚i,V&Š‘¦bβ€Q/‘‡x®×)E8p 7†–$˜þPÈÓ$ÞkVër&…!‘”ÈhX[ùV} Š85RÆ…»s †ìƸï c {…Yb!²cTÁŠ.æ' ”ý#Ô8Æ.;ÆÜwˆ 2àɤ$U AÓ‘±¼°¸œÎÈâìHÐ9–„X‰ÔOìÚœ„ãc»7+$<³ràPšÉK‘\µË¡üH'Q.*?Ò(z§4•R/þBÆeÞsˆR@Rkr=0µËD´„)И88ˆÜiÎaÆæ†6TH‰Äyk5 šÔß$ qLHò["š©M)ó˜‰ÊuHM w†Ž¤ÂÒÊ8þͽ+¤O’…9(|L‰á@–t°Ïñù-š(û~…iÔÇô´*ÔÈA—Tù‹?Šf¯;…”Mc+¥ÜüÎy* ¥S˜È™GüpJœÚ'DEuO³´(bÿkä8»ƒ ØÊ): ÁúLÑôÝÐqž® ²,œæï "umy‹Ý=Pút]ÛHõ.óUÚÙårA ëªkPƒ–µ˜)Û±)ðVj°XËD¾€.ÎÚÊ"åÞ‰N`I¼Üû‰Þ#â´Ó JZ,ƒ%m%@÷XڤĘ~jMb˜–%ÄHø·SÁ*5µ¬›s”càz•9k3Èú¼Q dgåòJÒÑ:JêP'Î:v–å‰ô—š/iHIqœŽˆÏ0ðBC‚À›¸³s*­j˜ùV,¶±…yT¼\^äz”rk›åánb†¥²1âØu ̩πIû\4Õ·píb¥ü7 PSøEÑ5&дɇ‘¡•yÓ>\#çÔg]¼qM‘ªv%H@$—Z„]l‹#)lÃHO ´"™¥âux:?+ áñ’å…<»ª%}ëŠî©‹Æ;m&#†w…vžú¸tAŸQÙÒ’å€b' ìdkŽ”Çè«À9•“)§!|’c€Åh’È;œW†ÌZæmM¨6ì±*Ì^=Û¹ÁlâÅ'knŽrR t“üÄ…éfZ¨ñ–e:#šéÚ6™úúaêw}|ìB\ÊñšÒH&*u4Ç­Ô8~)äL )ùSÏÜ¢ÉÌ•8µiå&Ú}2–f$E2(˜¯ ÷Nu²ž~:#7¨œ~½rl¹ÑäÄÐÎ1Vá%ÈÎ@ÿ+í^eݸD°òxôÃb6ïH™ä")5l¾ˆ?$MŠh„J³T AÍu2ËMvVÚåQ…§WˆmLH|ôHÊ{kRh¤‹(ÖçrRÊÍj›Káì¾aÐÉ‘9äÿCš§À­vñÕq>ʸ‰c-BÓ0 ý7î' Ó/¢[.‹›¥jœˆˆÖ¨û¬:Z©aë’cƒ[Qê"YxË€yî³92ù?¹È‹C·²|BÛˆŽ’?|¡{±²x~©°’)ªò2ÙÞ>‚<ˆ£á;z┃;>BÞ2™ó)°¬‚é˜æ¼žQ!>¬?7 û«ó@9‡˪5°ž:–B0±’có38²Â*3ü‡@Ú='šÄ=#Yõ-z=' 5[½8¡/» ¡1œZŒÔU¦¢s6csE æ’*BІÄc@‹ˆâ»¸šºˆaëªÂ–# Ž5(¤ìrÇ™ M¨ò™—Ò>¡ n4d|™pÅ"\´?œš iÛˆ#Ô5.Ó½òH¤€­2ˆ‰‘Âr«)aC¥±L­‹ !kxŠt¥„j+Â¥¦ *ÃU:y°°3•#‘ºœO˜ÅHs°ˆ»¥¢œÈ»¼f€D¥Â²'>SäœHx°¤¼a&B’ ±º¸ž7ÛâÛ8:cª!$|ÃèˆGl]qÆG,Á/¹Ø¸Ÿ£dÀ2Ã0¡éŒ§UÀƒw Ö«à,£4E `òZÃŒI<YÃà…ÆtmÐì«1ê:–9qG!kÂC®ã"¥P‚:P~»i°´«)7qSL@%âÞ0™¬ ò–Ô€‘xçƒåÅ<-žQ/ŠjWxÖÍ`"º×-á•#±ÁˆŽG¥6 Pž3wDš‘H†/¤ÇaƲœK ÿUÊ_ÕÓk.Êl#3#€üÔ¸„K‘õ´Ë˜k°È£OŽ«‘6£ SŒN@8™ ºŠ ø:¸à¸äÎ:£ƒ 0H•“VñÛRÜ+ÁL”ÔJÜǺûÅØa±¹ÍžF²KÈ è>(•:äLDBœE‘Œ©;<Ìqò=rÃl "z›»Û1jQ$†ÆèN4OË9óŠ#HÈâ%ÅF;Ë.=E‰p,냟4Ð(¨ž¤ƒÚƒ1ljíX²a»TÛ—±J[Ò¼©ÙÓ±:ªó>à~ÈŠs?…i¡ÝN»ü† b» 󆼭Í+ƒK³T,LWZèªì½,A¿ÃÚº¼c:¥ YwQ7žéôŽl´V‘Vë]ÀmnéºÉ¿Ã’K I!PyZOŒê2Ì©2³¼T 9qª’dD3ˆ÷¤ÙçÒ½C# â‹‹ÞÓú!•8ž[pÉ¡ Î0™>p±¶ ê•;î/Ù^Hà¹h§R‰Ï‘¿Ô1•PÛþ›£-Ù1 ôHr¹Ü¤}D£mŸŽ5³Äu…Üã«¢ÜÎ¥«X…žQ2Þ#´éNh–N O˜ÃúÚ5’܇Q]¢4M$,K8ÊÑüºFáâÚ¢5NHæŽÊ+Ô£ç9›çV½t–1aV…ú’j⻃âmg²3‰È£þ±ú÷VbŒ-*îÒIä£2MZ-⃕+1* ³›¤ºHßðа|ÏraË2òQc>IÆ¢Klj4½xÛ¦ äîÚ=[12P±§qñG;XÙ 8Ä*Û;2€WF5â¾YãT<åOOÜW¬@ìÜ”Îd}åüz; 5Ü e¶%ùeP©aBÖD`®Ìå`ö(M<°#:ìÃ】­]äåsA›’=oÅëh­åƒ ,úHdËÜÜ?˜ž íåBY©Ÿ I°Ö'®HŸ8À­W•ÑºŽ•K]¥>0}üۨU€mgýÙ Œ=DuŒÛa˜×Ò€M!ºãÀ§+[&b=$»l¦¬uØ@®Œ¯åöC\€™RlŒ¡3S(ßW’åà±õî P§h€ŠH»d;H¹€ÜŠ@Ð5ÛKŠd¹¼º½¨êáMVHÁ»šäÇ>™®ÊØä Dv4ÒÑÆ?VPò×"uÓ‰ª‹»2LrNX´4A¸¨CÑ<ξ8¸rpÉÌ< c©}?5ÈB¯Ü˜H]M>´‹Ä" "~@\e¾kíá<Æ´aÇ褟5òÄíÎ(Óv\«ê½ ¯>ˆÄciG¾ªÕ¯æN¸ ꊕççè(=eA”j ñ•Éë–)»¢|J&ÈÕ­Vp–Lu0ý3Òº%¸»Œz¡Äâ‰ó¸aÝ‚KtíËël2‹Ë}DfKŸ† 4$3¾ÁêÞpQÝÂ^dÉ5Ä[‰Þk¡¬ŽkîñR‘ºÎ8YBKžV¯åæš$Þ¡ÒáÓžå•ÑžŒ— }o\ï¾yÐhmU2s;ž¾Ä+À¾Y„Ø¡ÙÌìP.Ž ×š«5–ˆc^ÂÙËžT“# ̲$ >2äÜϽ¿ÎékTî¡Üé@)•èCŠÙEzæ±Tr!Ôgî* ÊñÏ8ߣ¤Žu|¹‰› w ¢Ž#Eø¹ñ2;{ÀR'TÝlõÍŽ¢ƒ"<Xfo×¼ã®Íþ᤻á¢0â‘ 4nÉR{½IÞpEÛ“|w ,5Ô çPÏOñÌ*Ûá1D±é~"¼ QâC¯VÝC_êÅÇgp¢ògÆXIÞ."M±æì¬B­¹u;Wð’_¯>Åš(CUTT0ÐÀD ì‹ µ·AÒŽêœÐŽeÖÖBc%4t4C$VìÍ/-k3õ=õ‚0࣡ñë0£Œ«9 §«Åe»æÓà¶$%À»éDVIÿ´LмÙPàœÏbÚ¹pAÈГêæéÚÐGgšgÅÎ5lÌù¡ÎV¬D)NáD¢½ú¢»ë ³¸m÷ÉA½ D¾§2^Üeö‡Ó® O4l9 ›¼šžwLaú¤ôŠvº .VÏ‘¹*[vŠªð”Rùް1o‰¢ç€\À«¦€$ŒAºòÍË>kÚuëà}äA£ L–ˆ2Õ™7Õ¶G§DY!ìܽÛ&ó•?ƒŽU|bb¬˜LÄÔnèÊ¢C:"'_Ëð€<*“ÉAlAu¯#ÂùaT^^òÆcÒb3K®¯:•p#y‰òøæDŒ&ØÅOe×Á¦ãJÖú'¼ÝQºŒ™SߨØÑì,JÀS£ȧ-•`P×[š Lôͨ(•ù^µÊOõŽ ’æÍP ë†²\ç{‰ÕB¡m= ¦P\´Òrœœ‹æÏ¡AgÄÒ0½“¦…’ÅŠ¿‰€17ó¾úuðçͪ*ò¯lÅm:±Pñ5±úm† æ|^g]­¡a>â7gìÖTŠc]ç.˜‹f|hþ·4q®ÓsÛlªU'àïŽ]‘ög±‰ds'#´áÙîèiî §ˆ í=ˆ‚?`ϸCú C`@F$üŠ?âÑ(\.Ž>cа,…ï#†€¤ X³þ “½eÒ°&dúšD Ówìž}ÉañGä”C‡Ée0º$‡ÂÀ”ú4Z“LRe4 ê[ؤïòÂùC@켊‭+‹»Ý<‰*n»½î8èKà¸óÄ/kÏдÐô;à ÷ABx›Jò Éì¬Ü­zåB²±úï‹ú 'È ¿(j0¾@­,&ïtD†½òÃ4êÂ4ó@žNˆ²ù]kËå·RÚþÓüøÍ8j¼ˆ›vœõ€(àjº.EbNJz’ .ìÒ*YÈRî =- ÿRT-R‰+ŽÍvÆÓí ð72ÝkG4eáL¡k½~¥ÇªR“¡v "JÔj²¡´‹i'•òùO2JÍ+”÷1ÓÛ·,K©bB¹2{ ÖtB)Ç÷d0ýa°†*N×´É|K6¶?!D©ƒõ*O‰º°¨<Ù "Î…§2È×=é½´¤ZÛ4×eU$žj®êÊ!NêÃzYy͵ٙh€ju€[Tœ‹'šH èNª-³dqö®hŽÛ4’®ë2<‡Þu.Ÿ2ØQºäæ(j¸ÁÒ` GMĺ¦"-„ê…f`U*2GÛêûp`5Q\ç÷[µ>H•dƒ$÷%¹)DÙ@¹¼ŒHòmXÝÞ¥h9õÝT€k"ÙÔÓ¼+’bTà­EÉ*yb¼–fÒƒÈùÊØò NÞ5v?Šë©ÔZòÕá–·§žIòÅ\úâèLƲQÎ`§¥B€‘I °iog¨uLYØ{DÉÍ×p…ØäŒ‡T¦ØÒúuí1¤GÒî‰ êuæhž-„Ý!ZTy íJ°zÎÞ<3†ƒæ?˜ñOeH0„ÐPÚìq0z ¹ÂP ã tÄ„ì6‡®¹‰¤7fjž&BÉ: ñ^b ø‡ÚYHŽ/¦˜(?IKË@Éaä7ÇDÔSN[lùû'xª y +KȧÁ‚(¡‹‰r]$Q£&LBŽ[Ls1qÍ·#ƒ *fÍœƒ!†yÉ»Q1´§­©4˜Kì›SH©çÈ£z½_ûMhL)rÔȲT‰012Ŧu,ÈB|dÇ’_ •ŒWà)s¦zLº9Ÿª˜nGA§Éq)U¾_‡]—Êpá—«ìdé'Ÿ¥þØÀRVé ßI£\ÎÉä"1}Í&°§„slKæWMôM´²<}—ÇvM9kL¯€Ö4%úí {ça-)À&g„Ùô´~ÄZR1‚°ŸÄ˜y-Ù,=Íâc${R—ޤÑI3JðúHL­"#mQY h3(b£•TÚ Ë±üò;/-1¦%ƒ2Mr! ÊRy > ôËN€¥3´Ÿ¦Ímtðå—Ȥ¦Ï|²ŽçB¨9BÏ’œ Éè¡ÃòŠI4%] kG4ÿTkÄ{Ô^µ®é@+ȳ=ÔÊç!d "¥¦ò?è|`+ü‰ k4t#´VYD<­@'/b_Ø ´ÊlÞJKRVñŠÈô¡Ä’ù4W»Ö/‰ñ­€¢’—ù7´À-Ù—qépëJ.äÝ%Bè¶ë\!(0Z{€±0ÙôúIñ[G®¨ ÒT”‡¹').ûÄœ‡b–Æ¢˜YTŠZ;CÐV‘õ”Òéw02ï ã"·¨Ê(¶ú(! bq?U¹¢Èa?Ôr,rïë>‰$üŠWÓ¯…lTJnîn.€gW5gÄ Î´¤¤¤æA$›¿4~U‚`JdK=€ãýuùÂáJz’¸Þy3ò3¹7J…ä»Ùg*`S qË{Ò‘íCÀ)0nH–È9bõeíŒÊGiŽô³ÕÆNÛ*|­ô¡Ð1ô€1ÑçjU>TUæ°B ƒÖÌcðg”a?3iÜ4¯:`ÜìŸL‘Ñš¥` ØåÆ{W»Ë)8tÛn¹¶©‚¨š»5î¡\b,ªF³©_’jÀ®+I‡ŠÃø¹Œf)“!4gƒÈ((§\Re9Ë4ñ ]Âjù®º0ŽUÔ:Y–²¦wpSùˆ^û(Sç5?• °…-Š-§‰ QLnµÁ(qGãêcŠX!UæL„ØHE¬Åä†þ#­‚ä¬løglF7•Ibyá­¯Âhè²]à‘eVšdŽHÖ`?hzöYžà.e]©¥nLßW¦ZÛæÆ4-–4ÄÛG¢ÜºÙÈÒ˪BvæËoÞ•®ÙKÉã‘dж^çcF °ëáÚÿ°nJñ–E2]‚ß™zÕи¥«·ÜÚY]ÒÕ÷ÙvS­âç/ÇsHg IðGC•­Ü°œ~?g—q®ÐN uîŸå?±=ô#ˆX:¯›Oùâ,-p5Ÿ>£Òwý’“óe>g½Se .ëßgxA=í­‚€Ê‘tIÇe+h€Y³7ΗmÊ«!+Z…Ôu¬Ä¸Þ¶Í¦n?7@eQ›b¡gˆç{›9S­úvè?<ÜS¤RgJŠÈèHVà&œcâî_êg@ÔvÛcêÓ‹¹úõšÏ·æøÊÎpJCsnŸ¦ÜgªÏó?<Ýéú\=IÝ;õjò´An÷ôÖUƒA´YTÆIF¿ýO‡¸2lX ÀÈÂè¥â(EÂø®Bðx‚n‡nZãlZƨæâO8+KŽÀ ¼~¬‚}'Ä# .á㌒ô F¼Kö?®Îz"h´Aø¹@̘TNºúnzƒ@ÏaôóÄZÎ$è°ãÆìSj̺¾ï¬,,(ˆÂhú¡ü`°fçeNTH„gi`£ÅDçm;VÕ"hqBçòÚ‚ +O$ÝLoì… î½E6âJ pÈЊ®¡pID\hêÔtæ@7Š=ÈjÊË–«öªšßãæ—­Òãí§£ôÝöéi®˜/®]ËŠº'–wÏD±Ï”º0^‘Ï|û ÕEöÃÄSäzÅ„®‹ï@f¥î§*jGLZ¦ˆl6ŰÎa÷ðŠÍ*ì†OºWˆL³ÂeE„â yÌR$gœ5i²,ÔYEþ¨ \ø#@¯è˜Î‚J‚NIM\¼Œ–ãðA0¸oH‚$(¤}àQ(ìubÈãÉkf^ªˆ‚ÃÜîíJ¬¦îh­fSb`$í ŽÈò6-ê Æ ÆTºkÍït÷Ž,•à.ŒÍƒV"MÿNèkŸÌüÜ@ƒk `ÅæZ´‘x..DªB¦'Ö—0”¡$‚ËÂ)‡|¤Íd!ÿ§U„„Ñ/Bp(¼®"ä¶âÂ$ë:Ÿv… ïnV†rhC `?HÜziH¡ bþï€]"+&ñÊåîñÈ›&ä„Èw-“p®ô•R7&Høðıl<ã(ž’« ÐcôíËÀŸÞÈDF›ÆDD±&7N­p6|'“hðP±E ¢ïºÈ$ #-¤ÛÈ>˜ ¬Øê f†¨„ÂQþ*„S nË¢: ¾  ¸aèóÊÀ+ L¾E’xâËÆÚ•£—*DžòÒÍÓ8Æ¿@ ço*ËJ-8£®ãÑÜdF@²jªë*ÌŒ@ !‚9é’§„øX+àÚPD ‡Î,Žvó…@Cìÿ娮’ÖLhc:*ŒVRÔ£lo“^dMªOhjjÆ­sÆg“"ð Ø9gœ9i²çkTGHbê,ƒ1Bùöj¾²Kì]Ê7’>!êI"€k"†îÒªÛ¢<§bZŽ"(`« ›h|.ED°pv¸´VäÎ^ŠN¢Ù–¹"èT8}IæÒjypÔèÆ¤”¸´Fïl¥;t/@„É?<4À"†­Tg“¢ÕÔ<}ÌÀƒR‘7É^z¦TâóîÖÞ)\Îé4ééY*ÿBðÛ Z.Ý*S“H¢À®OñìNwDeþŽrð¢&ø”Žvé/¨3lë Öpü­F 9h"+…¾ˆ#Å„b+؇.Ï’Žô¨,îœì<Ê”ÊTØ«¥ Ýr<¬îy —04êu)i¨ªÑoÉ,å‡6rtŽ7B}µU!ì€,,|6M«£SÆçJ#1ÒjÙð\.Œn›+‹4ŽSbt0*ˆj[S‡(vö€¾‡Of@¦j“Hæ§d16ÊþeNJ“;,®9qÆE0b/2ãÕòšíxÎdÆøL¦ÔpR6c¬ø‹&ÝÅ@߯Í$ ¦fBD$qÌA&® Ër+Hš|ʘ&Jœær, `ôHW*írgg[ cΞ v…î()åÆ&B(p.¤ç²µÐ‘UCòëi´9vK µB>OŽFÕuÞ«3,.‘##q• ¡ûg–`íeIž•E…@é\WŒrˆkõäƒÓHôÔ×%:Ó?U&å] ÚVq=ç°õbøM°×)φ)Hj„Ë£¢2Ìó¾²êéVfxïmMX1å&•²âäÊñµŠ‘È-(œ–ÐYQbÉ©®yË"ôæñ#ÜÉbK$``¦ä¬UlqAv¶—HL7‚Nu¡çwÓÖ¡Pn&àx‚neB´·#aýiï°>d“ &e2ñËl¶5$  "FTõ!­ ®rzÏ«>mñ!Ì…=Š‚+"<·-@”1)L %¤+9m¶ùHM+±þ„…'€J•ÊTQUcS#\1%"MµæéÓòÌBÂwÒÓM'®»ó!*^ø,ûÌ\C m7ø)RÌâhï`W Fã{âh&)„áôÐgV‡n=yÆ™5$ ´IoI´XN )‹„¸g–¸~[ T×-XE"#CS6Ê£+f²Ï&¯Ôðµ5kl@ÖU+PNåï ?˼ Ѿ*0y&Yib#‡H­7o@XVgN¢ÓOp‡Ù 1M[òLÇ "ŠQµÅHÊ„n²´<Å` ΂_ò¥"ÉJO‘[|ïOê…>HDˆ ‚B‚)ÖZËå(‘fáŠJ-pŠÍq‚d®J”´tgÒÙr¤ä)j.¹ÀÁö%2åƒ0fŽnÝWÙH—i&¸F•TC ÒŠÕ6#ÄÄ•lRj¤J*|gИ®³#jt"—Ú.U w¥ê¯røº5$¡slCL†BòðªË$éï‰ '3EvñÙ+Î¥&àÒP"¢9â§“,×3hAòŽÇm™^A/V>E0[ÃYé’Aô&¶.Lò’œÛU~~¬š÷©h‡§=ÉöX8”Í(‰+‘¢žEÇ¥˜C¡_Ž?VM/µ ÝL|m¦íbxY–Ñ­ui+ã…ö+K~TêµvÆPµË:#ôDf#Õÿ;€YŒMf™¥.Éd™zoëK:nô®§kB.šEѲ´e6`屩s:m¤†˜Qe[TÑÞÿd* ¨Šƒ6^óss´ *ÂÙyfW¯*w˜4¦A¤6)0U¯„/Dy¬Ší†nnÏmT?¥Ž¼ðBÉb0Y'±™LôDJWl{ ­l®ýiÙyŠ"‡Vl‡‰/8j¾! 'Ùø½c·¡$"/(#Ž«‘·WîìQ.rñÖf×6ûìƒðè"D•;rÕñˆ^äiV»MƒÄFî1õ$JÖ0Lw|z.è+¬»Æ(ª ,ãn°é¶9‚5„^ù²#)§€¸ûLhy’r–îÇfÑÔÔ* ɘR_ÌìzòœøÁõšñ0 Þ ”/@ÖPÒc­´à(sg¬O~ŒaF5G,&äPÙ–”»©"±ëìBô‰P]Ì:Aí¸.i§V&DâOR÷*Â2¤Jû·¥YkÕ=(E4Q¯Á»Ñ±aøÐgÏy{ÏšL¶vh‹%êÙbõæÙ$â³A¬>R7‰ZØS+"Â.å£c¶9lÔë îyÉüË"¿Ö5béÑ&'DžÍD±¥•¡‚’ÊYÌwÜ!¨ùò|TÁ1›m½­WE /2™”®ñ²cyl¤þ¢Ëºð#Œï*7‚W‡O; ™ ïv2FYjFxíYQ1O!=ÀÊ–Ae܄ǖq‚·Üœ"¯ ¿eY2]ÈV²t‚J³Õr0EyŠ¢ž<‰ý« ב`ùh×ûÌ Zé}aòdÿŠôÑ#ïž_øŒ]”ªÉ‚x·7]’ Ø…@…"9˹^:dB¸IKrè®»DžMz5KÎEƒ±Ëa9c%à¯B첓(”¿ïò Õˆ»x Ý9ƒ2qÄÙÊWiV›3;"ŸWOwÆöÝDù=l€znŽîI2]îN6¹Ùé)Ý[õgš×>o}ñ%R鮉0+gbe[6*…yt6ÃÆíh¿ÙE­Ï‚Ò—¶E­ôú2.‚î$ógåo®Ä&XÁ¦·w Ù ó­Ö7«bºÙUrB²& öU#ÍfÖËšûI󏯍ôZ‡8Êj³* IñðÖ¦ˆò£#Zk>(Ä€˜ mª̦+cq'¥hj-/J‰ý!.í'$«pªÏ7?`EFæ²Jt:€1ÊÖƒÎJÿF‰#ëG6™þÇ®2¸J=H" 1 I«=¢µ‹Xi"t…ÃtSA:Pdf·-Š ¦ÔÎò ðJèØÒÌ$ÿ[.Piþó ±¹öÁÆH=ÄÏ9-r=3 RõŒ?m œY(òx>‡cÌ ssB·ï""9±s%¿túõwIKj0ÐWz0ªÅ×k³9ÍØ[ ŠËÈš•ÖGô\¥KÊ•o¦¯p laêef£4Hk´Â®.؈ÅÀ):'=¤¶:¨ˆXêªjKÕÜVÐÀ¼š¸ M¿WCzõ¯r³ÔôݱkcØØöªØö*]mÒð¼`L’@¾Gõ@œ$êS™6Eî¶³Ü̈Yà6l˜¼é=¨ì%ÖRšå^gìV«6ÿ)7¿t"=WjøÄÖè¯KÔ÷~cµæµŒÕ•W2ªÍ@I1UCÔ\Qv }ó •¥Öýv ~ZQsÚ6ëÇ'S ¡ ð½ŸNke~!=u@ºUÍê*¡Ùˆ9íörkÕcW¤–‹šÅù>ÐíºõñÙÜgéžy.)ù8S†BV9K(Éí¹ÇlbY ý*¬¡Ñø«š$lÊt "Px‘t,„Í©rp¡LaŽ©û•Â*lRÈþe„Aé­7ΛSˆtK¼§—RG‰:ßÌ ˜ÀðþQ<+~oiôD8WÇâ[`ëm‰¦ÑþlXÉH&E|‚•V±Êß(ÌY_€S.A^ƒ~WÍÍ'ìÞÌieä6“‡}‚Z49ÝD˜X÷ˆÁ· æéѲ7Ésœk j.uÖLÒài„ù˜ž–Ù£.(™¹È•z>Q1lm$Tª® 줱µCdLjʶV{ÑÄF‹£¹’N(ô}M¨1ð¿bÔ!©yzÃÑû Ð(•¬à½FP Ÿd²RpàÝè4¹Ù»½q/‘þ7dÆWðLªj3'"Ÿ¦)1Œa¢1þ×¥Œouk•#ù,ÂÎlŽDa=½ Ò÷˪„Mªž’fŠ F衊&æˆKà}ÓJt0çHÖ¡‰Ue(óÏ…¤Éb¬ù%RE¼å…”’æ[ òËóE[¢å‡äEÓ¿ãAˆ;„BÑÝ.SönHäÌ—ÀkEâ·# -{¬F…ÇØnÆ©S¶¢(26¯áúE§Ù 6§î@1©ržÜ:gÀ “8èQ¦™hSž'š½U‰ñµ\Q]ÂÐãŠÊ ¤Ü=Áh)#éÅËÒ´*ùüY«Ì³mÙoº²FKô‰°ƒ¦z“;KH«ëZÅʸÚQµŒ½ÃÏ(Ê줺dšà@³h¦À­¤˜|˜©¹Ih½$S±(}BT¥xåú´‹ªM4ôŽ#êXÁø¥*ò#²‡Ê¹£$kÈ\i2Zª1Ùÿ-à˜¬¾(Œ)Æ|ËŸAÒÉ»†¦ddžap¡YŒ™¹º¨»|=ŠÌˆ–Áj0xƒÈªU†«™ kø9ÓïJPˆ0Û‘BIQ´Úd˜Œ GË´3ñR¢ ýˆXÚ« ˆØ¢ é Z†GX‚ø·„B£fF3G“ YꛚãÈ2Ѥë&ô¶ËèEÒEE RÀ‹´¾a|Â`|šè7â^Këé2§ Ï)¢—$"¼¼q$–Œ#H!΢؈=“úÝ7œºDqÄ ~  džÜ%¤+­Æ:Æ‹sÖÍbÑ–£ý !q0+äká"òðKy¼SÚ4 ¡š$)µs Œj·IÄDºÏ:3­ tߦaªã+ž‚ hŠÛáC+hÊIs Øœ:k -j(zè¶Z^A¤Ô·£%Nl}*"ð¾ð½ðª¡uº²€ ‘'ajE™ ‰9cÏò<2G£|['M)‰Ò˜‡Ù/Ò^4š%&ÉÄ ’»ÔYºkÅ ê<ÂzIòŸ²êRÑ]«ÊKEC )R7À3à ÊX C —Y= 9݇À¬Ã D¢¢hh²’®hꞘÁ͆°àŠÌ‡µ¼¨ ŒÉ1C¹Õ½Rˆº'«ÂÀÙ;5R9]Ä‹ ¡z‘®ò-¬Ý9ô âÓtä.‹ÍÂÊÓ0e8(B€?²ºB ¡}L¡]€È`æ¤[F7š›t¹’JfBP3 }2 }(‰ ±1Ù “r7Èý{2pó¬œø:°Ãê‹Ê]¬3´!zˆ®‰ò?ë¡–…5ˆ³FàЄDéé8ÓzÈÀ~¢„cý}̘|ʽŸ£ƒD“³²ó%˜¨z…<Š—˜Ô¡Ð-JEKHP“±<­üW¾Ky ì™ÚòÍKÚäÙÃD;ˆ‚º0Ô ÚÍÔŸ¦"ª\ôØ,HLE¢Z£·'}!ã@[Ä·O@5Zç\«„Ó5 ûÚ¢hDT›%«¥Kb@g¬\#ÊÉÄZC•'4´Í?€`œD"xœ4á¹úNAÎO µ²*Xƒ´£|ïØÔRÌP¯“ %—C“œñƱ7H¬eÅæÔxœ4›Fõ)IÚª[ƒ?RzÃÃRK|$¹4bt‰½ÒˆÂ\²¹Œ§™¹¤EÖT´¢C}!;б›yJc$¾S[-‰o^…Vä–$£ Ò‹•u̺ˆ“Ù©„hÏüÃr8)ÂÕ Êd»jÓÊrÈÔÈPC·NêžF…öé=ÓÅü¬œ¦ží’Ð’×ð‡ž‰(Ჸ¤ ]\ÔðœK8íX€?»€·"ååÜÈ¦Ý 9²¼šËc[ ÚõH*ª‘‚Óí,-dPbY8ÝsÑ¥SªJ5]mb }!…‰“ts9jÔáèÕ_HaZ¶ ™v6aâ ³È:0“šôåùýG =šh’1Àź6._1Ã+ P=ÔÓ™cÉ™›ÚÀ}Áùú¥tv0”¡Ù©:ÇÍTιx² QcÔÕ¶tíLU^#B„UÛ&YèË:e¨ ~ÕùW>´§ˆ«M8-1¸Ò­©ÃaÍU~&: W»J±u%þ¶½*€ Ž›ª=VéQ੘«œñ({ÞšÔW`ªh`Õá{Ï+ƒ«”d bˆõLˆžûUô†’¼Ò#÷´2ç§ÐŸ-£CÆ:ÜD%Q™æöF›ùÛfL£Eì5ݰ¬<ÄèÐÅ -Ç 2ü`>S¥×ú*/Õ­`ñ¿¸ë+ŠU¦ÃíMJÅßÉ †ÆÌÆHœVðæÍÕ‡ÌÇRëÖ,¶Å3•‡Ñþ.ücäU[™8¸Ñ277”À)Š5ƒz,¶} m+¼¾d=ûÁ½ÈTt¬>Ä»J¿¡æ¤gÅY Ü9_¶nÝÜ9FIì6Ä~T:—4¡7¶~vžêˆª ˜cÚº-ôh«¡Þ;é[¶{´õ¶ÇY\)˜D¶¦«À¦î±F¬a„ëÍÒR‹´mÇ ¦½0 IÜ ³Yj0ÞûU "°ŠíéÀ!>á@.F¬xÐ?¨¸°J5+ *Ø¡«‚ZN"¥œ½¼I £« ŒEÚ€MžZëD<šRÖNåHñQìV6ྤ™«È“äH‚¯ø„£zÁÆÕBάÁÿå±7hS­—[:“â jÝÃ8r¶“i~®Ë[÷ “³ïøpž~ŸÔóÌM§švFÖj ]iЗf…!}_ÏšbB,œ¼- )4PÎ-¯ttöB‡ñ¯%$>Šþ‰ž¦NÃÌé±ÅÝr‹rc©JÍâÿáu ˆžúGe¦Ð_ n„EÌ'KÜ<¹ –=Խ´æÄnî8,ù× ²G‡Laã4`ãy஼åñlç²bnëuãh –ÎR?½ zxmßc¹»›z fmF6ÜQFÕf¼ÍØ#m‚V„·æ¡`ödtñ¿ \èh8Ú¥Èyw±é䥹4Z+&¤"´« K}ÛD6¹Ÿqä]\©u½Âºq ÂW”RX„ò$Ní2Ÿ8Øò=ý,ÓâlN榋!^=ãÜýœÆò 8% “ØrþêæÔŸÃ´žgÜ£^qï¾ÁeˆæÙË¡¤ÚE鿽”úv:f:7ŽWieÐrš8œ€7Yë0}šñ Ý“á\¥àœ/NµtO[n΄) ÃsÍÆž;¨´òÐÀ•0\mޏòçl¤®HÊãC¦Fk¦œ€) EfÉñÐ|®ç瘉é´ëÁ7„À *¤W4Ä…LÕ9c“ÙÝTÖȣΟ]ë º9v@tÜVÈô†ŸÒ¾üôÀ§oÐ8OÍk€J ó/9ºÙÿHÆ?©bT.!o«Ï,蘦§tO¦Ž½žf»­…qþ—*æùfIÜG?¸ÔYÁÿ¾s·ŽNözÕïõÆ8>›¹ÝëòK&…kã Ù±[¦§K)v@¿ Nº°À˜zààt˜CÄ™°(€`Oø#ò „!@H`€ؤJŠ?bQh¼ FáQËúM~D"Ùd¶A …IŸÒ¨$^ˆL¢ñ˜ü]÷?‡P@qù¤ªD‹Ä¦S(ä¶;M‹ÒäÑ m%$ŠS!pȼ~%œÉ¦ôH#êÍ”PA¸ËæÝÜcó÷ÜÈw©?©Ð+ ý™PmÏšüRâ ÑjðL,jE Îë5(üÞéM´Ã²OÜN2DøÐU$TšØü@¨6gÔÞ%®…X €m¤¢/(¥T¶›°5Òé6†L«Èu‘ÿ]„J&S~ŸÿÖMùpÉ\ @øÓØæº,_¯»ÛÁ¹òÚ=ÅíÇõ“ÙfˆÝB: fžé•†Fbñ ô*‚Ü4©’J© Œ;‹´é“ ‡ðk"Õ3Oˆº=ÍHˆ%Âpš M:‚Œ¥Ëž­ „DÐ#Ž&KXŒ¿P€Ò=è#džÑÊÔµ¸ÚU"©ŠL—€HÊ‚À$Ë£‰9QR>ÓÆ úòª2J€‡J*²DÓµ‘‚(‹·o€>Òº„ͬ'ò¡HqB£Æði-€™“ÊPÌ€jkÊ‘³ÓºL¦Ênh‰H‘£‡4ÑC´DŠjó?¢h¤ÓÏ´ÿÒŽ@BÓ)ö‰5k;’ƒK•0øÏ2óA¡TóžþQÎ UJ(‚…7¶2¾¯ÉEu€5"Lsh.¢d¤„<'åq_%µÚ…I*IBèÝÕˆAçoÑéòL9ÔÔ€ÇPGò2]‰‘ëw·p}Š‘J,ܧÎÑb–Jj*?(Ê-ܘñ_hìÅ©v52ÆŽzx„A)5Þz´ìÛÉM"OøŸ°nʹ6&h$-sÙÔU…SEýÀ«Œ6ÈÖQ´þ6}¥´brÝ.˜Ý®Žº>èŒ#X’$š4î40ƒ(3“OŠæõIôçÈö‚RÈ#î„.àN—vXº:ì:.ÁÑìÿ/ Mzm¶™Ð·Ÿ­Ün‹¾«ôè‡PÇü¦Áë) G¸ÓJ*oa Š N÷=Ê>b޵’ÔJôRSÜ›Úröàʦ¨ëàÆóòbû¾´½½´ Ó})Q¾€´Åï_rË£˜šC5¨ V¡LÃ@¼à’”ttåzâ}ùÿ>.†¿­äÈœ­¤×—i¤xÕ/wNÞ9CK¢3ÇäI65yõÒ*)ràž~Iò‚ÃÄ5dH™fŠiO„\GÎûu Ь†švÌQ>DЙC:?ɹ7NNYg#v‰ÜËã§ÌùºÂXQÏs,")ý»6º¦È¢ò7,…¬ò@¨{ú!ÄÜÖ3¤¬$Í‚‘öfY’¬"]k±ú'Rkñ &슷òŸ“£(¨‘ȰVjqœ &ŽÑg)HR„Ÿ(0dB!3 {‰CazJQ¥§çŸ ]Œ5aOæ;3ÒMP²‰kcý`S “â=YŒ‚6? Î1—ˆ©¸§Å I‘º.©JBÂ…$iw‚¤¢«Š\kP%'<8' ߊ³e ÆA…l?,¬!Ñ@A“¨AÈöìÙø2øû,ªxˆ6é(âˆa§~‘øCÅU&á{ “¤mõ—ãØ_ëø’’ ¦¬9*ÁœvÏø0ù‰ ¡s'èyí°¢$`ÈËÒ•³†¶dý!AEd½KàLŒ‘pè^€$ìàIkHI¨‘"Bdœ£a´˜r^%BèÑYh ä! 93,o‡Üêtúc([$Ä1K—BóNuز2oX„'$_ñ H’‚XG‡áÈC/&TáFÒdj‚!séMNÈ: $d°g+!G“#Y-IjeÅé.zí@ {î¡ð—èÌûa£(r¾h#è¹Ch´‘[Ç™ðE(5fEFžž8b7`‡ôihéyGwG\¡œ&Y1¸”ÐØUdj´És á‘™$'¢3dæ, D—J´°Îz¹Ò\XSêY®½s¸Yÿ; *~Šy“¦œìˆ%e*VòvÓ'”X˜ý“eRÁ‘) D¦ =J4pˆ5;L?%Pÿg‰ˆáºØT{®Ýx¯T0¸2‹¤MÅ]Õ©³¢'å ›³Y!d1zôùÒbQÝ)×&ï•7ÅTÍ\²Ñ³´Ð¿š~Xí,~d³ÌÒÜû(Ý5 XºÜŠŠ–±G³„Ñ£ykj ÄriMh· Ï™R³,–“uKõŽ/ЂÛ_«z)¦kƒö•N5(IP5É’¸ƒ¸ò/Ô¨0xV¶[ÖñoHƒÒtî áAUÇ8×5ã{½g'Æ^´FÎiFøc,ßú',ñ?F†îif_9œ)(šÃéÞ“òd‹sï‹8H~ßr~Mï©´{@2fd˜p¥ÒR’ó†àm ø¹3ò…Ë¢„^MþNÑì³3\i@*Qrnµ»@þì¤ÊË:¢:´:_ëáKš’FùD]gë0m’ÛȈsô„˨óÝŒaY‚Õjä^wá4™•ÂÔ<íA¶’âsæhÖê&¼œ´‹Í¸¿R¬0…[/ÇÌëñ<1-aô¾DŽyüëü¿ ï~¹Fç^ª€ í1ƒ…LøÐ’L‹ŒnÇÄ@º"ìÜó’jÈ[[? ÌÞ ¹-¸X|çLvæ²Z`iížbÖ ²å†èŒ í»MQq¹ITÔ~Ú?Ü›6¤À¶tänÌtÌÔᤵ4uçÜ;}‚#$Ó½3²¾R÷»ML^áœ3"DHç0ˆïÖ­“’SÔaÙõ^U^rWUûp 2šÃôµéKôô­kÛw Ù'—è{” Ñ{ž m&dÀm‹jd?ÏÇ­;=ip«ÈÖ ~¥ßf*¾^/nZÒ©Z® †O?°ä)a“wý‹ k±€}†»4[YÄg[\h=IBŒ§ù]ЂÝ!rÖCÓ@µ–å0ÍoŠ0^^öü”·:'„waú.‡èåë!¥xÆcEÎ&Ò ÐrÇh£#zžn6Èm¶—ê°Rír–ªÆïLö":÷¬b#¢ò›Gê̯­h'ãv­Aøùgì,¢ÌÛˆf/.Ãèt®k ‚µ·bÐ@u¯gp*– =ðˆý‡£JgÇsÜ·ðyèT¡î ½ÊÒ­aÿ ô–ç’)§JÑgBȃò"ÊYÏÖ½©jòFÈö¡öl‰x~ê0‚0é̹ÍzæÂõê°°¯4χ0TGNË.SGiĦt¦ô…çhQãž›nZDd~ÖO‹T¿Šà~æ¯^‹f$f»…¢ –þŽÝ‹EJîð-fœÎÎ!ÌêØÅ”SÇÀµI”¶NÊ×ÐýäÌ;owââÙ'òBÁµpkæ@ëkÚßAþlç"òÛˆ’é$â ô€% PÛÌ<%§é¡øçÑ€†Ê¶¼«ÇkTeå0¬ G±±Dþ…ÑzÂ/ËÔÚè rjò)m°É R‰¼‚Ž»$-LÙ1,ïb°±ÈúO¬\ÃFñ±¸‘jêmì¼K(8ÆðœÂ wÂÆQ<²j8©k G^u°ÖàNÉé`/%¬^K²À‰¾.æ– Ã6ã/¬Ýgÿ' Pƒ¬@X‹aü÷KÈçŽN¹§Šýí!ŒÌgäzÆÜ‡<|D¦o X MíÈûf#&ÂvíJ!CwÆ^qÑ|F稅¼âØùCh©ŽŒ¡¦Å,FG–·# ‡ó(Ìì™J®ÓÄÒÚÈ -mŠw ½²Ž1¬pÃb—¡úçJ¤½mrzQ0×ÏKpôjœÃÒ¤g½1Üê'àJmVaøœ¯`í@ jÇò^K{)ª0¡£NŠ-¢Ü ÑÌM&xÅ¢ª†0¢h÷"ŠŽ¢lR…Fêh.©Í5¯1‡»‹®ñIV‹Ñî&Žm,] ®tgÐüùÑæÉÓµH’ޏœŠ' b^§î#ò „óâ{‹(ß­rJg,"F¤áÂ6&ï%8P¨ƒ7ã¶™À³$ݯBÝ(l£‡’zLM¶ïv¨RØ®&•«zipl›*t%éÂ~‹¬®•¢ŠÅi(Ô3†³ª® ÀWÇî°ƒi4Å€jÐ\â/*œú2šÜL>mŠÚÇ¥ÑgKûC4xdníãi#‰_Ks+ÊÂaøàÔ˜ŠÞ%J_'3×1ØÚò mÁh¨‘ÌÁ-Ôeieð½-š.3ZÛf•ñ²©$¼Á fo#hNOà¹+$Ërˆ}ã†O ˜/ª&ðʨnµM‹P\ Œ|¼q ù .A«QB+<­*DnÄ1$¢poGÒLÄI.ç^9ô„Û!õK¦•ðGJðdjó(;m0oÄ$Ýs'H¢ag&èåO† ž-r³éô„ÀÁõAÖÆ‹'B.¸ì†Å"$Í!³,Ms³6SD57d`/)†ï‘U05ï°t(f©Â¿*ÑL Н_E±$¢^‚ňõ Ô—.eAJÐ3o2ÃÞè÷Vû§Á*àÖµÒe6(B¥”rӣˌÊìœò ÊÈ« [al6v \lÉQËöfíœ"æÂ~ñuR4Èͬ¼Ìp/¦­Äܯy!àÜ–’Ü ˜•н­ÐŽ”!K>…HÒy-ÖQêQ7Iê‚Tàø °/z„‰°sCþ ÑÌEÉ‚Å+PDî¢k{CÌ0…N’— ²í‹Æš•þܪ‡kØâr”„Q' IpKÚ1`“â_­$êßÒÈ,Ò©b¢—@cÀ aÊÚÂÜ>fH‘^R,ÎìÆqk;RëDTÜK»íÀp.Š‚é tˆUSþàU–ÑP¼„¢¨„ˆãð¸çU¦EÐnÅ5Ø4¦'-và—Ðæ0BÜ®S—^•%”Ьç$È)ý#äí,kÈD’ÙYK@/ÕW ‘»*é\RÀ!JÍ•’aMeÈÒË á`¤8×e sìÂ~aP‚nÃ6î‡}åG ‹T|IP¤2˜2ÞÙ—!4³¶~¨T:ø)M”@ÚevYÈ·U7"„-LgW±?D”âîJä5ƒX0ïÎ.Ñb%*e¢e_”ÀaÈ_¶BÍþÌBMrâ5ˆAtRširvWsÜ«Γ-5¢[‡ó½Èm<ˆÉ4ê”æó@ˆZ¨r†’b•õšjmñWÈCId¨¥Ç¡üÚÓj°¦‹ œçKž`´=4èTµ„$€÷ér· š—òÌ-ʵjy¯:YXl,æ}O€ ŠÄ'~°Ï˜f¬1ĈBÉ܆dì壮EÒ jÏ%bióVˆm6„\øÂ:¤ ‚K/˜·ó ˜Á*,’âëÆ’ÕP†…Ï#ƘЃNNM¤È­É´]l²pvƒNß$ÚMPËr-‡…~'킳ø$Õ÷†ÉYyZËN÷Ÿs}Šb$:æÈ² F‘ iP>pbešó§ õÌ»ÙÚztB½µÜZ,Z3[i¢@•§ò¨…CB‰¨\ì Uô„ Î7f„xTGxFK¾É)Q'VÇ÷º†ÂèÊbä®—…Foaö"ω”ë955±¡vÌf¸ˆ´Y„ë3 €î®¡´…€2g¨à >g“~Ï|~)‚EÕÄg—IŸÁóªÐËnëÚƒ±ΗÍÝ]7Û+z²Cž–©†Rtú*Tå°G.ƒ)[´EŽÄøaÛ{+FÒ ÍÌJKÏ£f®²ÿ&£UÔ—dbbyû}‹’·y¼ú©G®/¬T¶q~K®gÈ4Aªº*XR·³óšgéHPñ=çâêÓH-.YR¡\MæFQy†—(¥64€°¸´7@Š ÃJ[sË&9ï8ûF {fxýΛ°ûN~u]2¥‚Th„]%=dÍ€Pƒ¯gì“nÖr¡Âçä}j¤£¥<æ,õ_gXJ%E6²ô–SÓ¿jÒHÚÔœ½™e±` EÆ& Öb•YYy©µ!ü°ºŒYbÌ/0`o Q84†=Öª·ƒ. fùo–  Å.u¦˜îá  »Í`¢»%u·Ô‰. £ŒÄbTl'јö’è®±„°rÿ7I!yeI5œ)ñ÷ry> Rö UÄîUM¡©ÂÚÌ1'æÅL5LÛ¸ƒ:6L./ÍÏPO²¨“T)¤í| W|!Ò¡­B7/ç m2?·j¯mB_éÐE.Dý§Rr<ÞA†ÂãÕhü>›N¢?á³z4Ö/ ŠÈ¢Úsö ‡Úås°âér†ÐnVŠäŠ' •Ô.ˆðÓƒUh1¹Ê'ãäS{•c n¯Ýãq ¤"K†ÉèÙ€‹ˆCdQ+ì"¡9¸ÎõÇö=n°C4Ñ •BåAˆPh¼ þ'rÝN߃¹Ën!"×¶ê÷)Й5—°•ÛooéÏŠßNÄûùÒ÷õ¯e|õÂ8 .¶ß*ÿЏš¨'¯*N©>¨Tü­KZœ¥“ÁïAþú6NÓòå§0:&µ¡+²È£)[šŽ+oã–›ªïû'iºV“¹k“; )Ȭƒ$Jƒˆí€+Z*µ´KZnøD¨ä›Åhc¤¢l¢™&n8 ¨q(ƒ7ÏJÈ}.Kú‘()Ñ0¨> [œÒ<®ÒVí"©¼††K‡ûΙ°3 Zv€º.‘1àK’|«éZoC*S¤X»à ¾î¡ô2‚£IHÌ{Óoƒ(½N¨Ò÷ÈÑ;ûG'5CÛ!3®Bçò¤è"îs?¾Õ&µ(Ek,¶hdö¨4(bNˆ(Ë]f}RíƒÊ›Ç¨ƒR4pòœ£!*„ÖÃ4ËòœÓì¥<‰Ì­µlôÄrZ¥BN*uxÏ –Ó6“ä_ÑÖSz¦ë;Ww¶I[Øþ_@nÛ-fÎiÓå´ Ì·£å<¬(ËþàU:J¨!íB>K–'6Wê5 µ¨Ó öü¶È‚*•¶ÖÔÿ1Á°­$ÏÕRåMžéõ£R¾¨«)"£33±WC)i<}m*Jwpºoå!'b‡ãv¤«(ÞJäÍÏ*ÖÀ¯(š!F#yMu°^¯SÒ¹`ŽÖ¦´£<†F(ÝŒEýX¨2‰ûGí*9Õ†dêbîËÆÐÚbâ§{^g?Ñ×1ÿÑüe#‘¿¹†Ë» ¢ðÛLß8a5 Ú|Ú‰¹×–üµ¨~ׇéGíÝÀ̳Ìÿ!<-b‘m"ª5}¶+§ês‚PÙ»ð1 ĤõÖ\]œ3Wµ+´›¤J—1svæ©Ë-ß"S­xÞXΉ¼i#HÞ†~FÖÖSÒžõ*©^«©(+@ B@\ fn ¸-ãÒ¸›kUs°¤@4H@‹1{l¼Ç³ ™u'p<7Š>ÞQ¢geö€r JÙÜ…Nu—¸°mŒq"mÓÄdEá¸ÿ*IŽÀ°Þ‘kx¡Ç¤Ûˆc;J¬eÍ8õ܃¡3z¯1ž€H\DÖšH%Š©² `ÑÉH%j¢ÆUvµKa3I‹ÑSSàm–ÁHY´ JOútÉX•IÀT‹3ñ ¼»26¿GóãtQ\¼1ú=dÒåsîd §*AÈAF‰†ñÊ$fø)Apƒ©>A™ÚN-eAB-©`FØa+x.G7×<é"qƒpk¹•”Rf¼ùÎ8m­€ Hþ†“T£I°«Oâ:±i½Ì"|ANYå ©@iLÉÌa>e9*¹¸.›ût3µæ®uì]¢ >.‚4ø.ÛÀ%¥<¼¦¢¼QlEJª[ù$}SÌË|+Ý`h‚>—Ã8æH¬FØWä þpf¼³¹0¢ec“ÇèüO˜=*R|ÈÓ4P“êÁãé’äTƒIà ’ÈÍœ@ ‰ÒƃKÇôäÝÓrœõiµ ©¤\Ó-§6CVRשO2uÌ™*eÒjÍ2B’&vJâ1N”¨~Tɾ¤'nV:HÓà ¨ÉùˆiŸ–äèåÑA7*OE°B®©R£5j4NbR¡‘óO*Áó:q4IÄ8‹Uº“ ·Î‹^£R•UòTHì`ÑåjÊÇÃU©Útuv’™Éc–§ãL@IØÈWŸÒuYo‡ºy9J˜¡Ã›¡4 …L ä‡óW<¬$lÅ¥ |¨õÏ›îdù—ÊŠ Êô˜²U™Þ_Ÿ‹9&ç%ZPA¦îµÓ¨ô¸¦XêQñ¢¬óä‘[ç«Àkp%JíÈ„c¯´–›Ä!,úÈe,º°•˜­Y"bŽc¨>m_ó’Ec{;EàвÒQ-sŽ7NÛKXøLð@`a'¾B—Ë…¤Ì†Ò «¢±û'':é&W6§Ôý—O÷ŽÂ»ÄüŒ¤jGsæÝá ïðù!6ƒ%œ£­XûFÆÍ)bg/’þõ(¥RÖƒìLîÇ8°í+uKŒƒ¶…äæ&'î?'L…NøÊ$癞L‡¹Vâ'U{ýXS›]Ž„dÍA ¡ªV]#2,0Ò$™«„+@µ ˆ§žnw°ô¤çb?oyÈ#ý‚N1úh¯Âô‹$yÇë¿*¥ ¶™Î{¿5÷¦Â6lNæ^§BqèϰãPêÆä“’ª†„LîÌ ·`gö«i¤ ø€Zx½&k*FW,Š#ϸó3{Ÿ0#y_];ZÙÏ3ÓU,Cj©=®îÙŽ9ˆwŒQ–j¯æäZOrhzÄ…§$ŸÕ„¥;äš`m ùAûp™œä½씂zª–ŸWåGf•nFØ¥ä虳YmFúç(²ÅæÔ„À0(>!°ÉH6šÓB#í¸r%TBlÖ<¯UÀÜ è T¥¨;*HÚ"“Ö>µ{.a}ÏLÄ=íÈÑYz±*•„’>öÝGFÓ“—€;Ì&ꈟ]#=ž®±C„¦DÚƒáJ“$UØGÑû:yÅC+Ç•µé͈?©;A;O`Ìݳr^“\¹ˆëB3¹c…bœúnÛÏVCqKÚóiFÌo÷i‚€ €¸ò `^–T¼9¶S)bb"å­BÞŠRîÙ6S%2|èþ‚ú•WÌ£^ÃEÛ€I2¯‚£˜L¯œ¹öiÒÙî~ôkN>¡ŒÎzyޏsÞ®zÎyÔ ÉC½6º¦Ó®%X~#Û=ˆS~™ ©ËžSP £9!JÍ“+¤+Ö3òi8K‘ŒK1¿“¢V¦ H;ŠÛÀ»±"iª8AΊû¯žèÄ’p †Ô(#ç y~ ãÊi.ê<+¼™ûë¾· h‹¿š¨ê€L¢ƒ_¢B¬«#wµcÒµ Ê1% â±Êþéx ±ÃÞŠûaµûVŽc- šHú¿ùÕK›Dº .sÇ0”ºkª1D_ÆÛŠ‚$ÓTÇp0ù-²G!xêp%ÙÞ8l‘ð£ ÆC䑟C@Ÿ\J·HÑ“Ãp§ =º}*)î¢Ä¢~Æz`“ùý†”#+¦ÐÁ–š?rÀIÌÃÄ“ùpI÷¦S;*ã¦Ó‚‰£‘ù]7«\;y= Užâ 4l—AŸÑ³ÈcÝòtˆ¬SG»sª?©l¢ÊÂ|È£°L`#´;­« @ä©' 뇈c.Ì‘IS™Ù-ŸÉ2?¢Faª :j„ÈóG‰a²¸×Lƒx¯L5®t¢½áO¿ Û2„;Kª/“ÕZ\HZ6ô+Q’Y 1óÜ:Ë% “ïFRŽQÃ9c×p¨¨¥Á{ø©#r²!ïDª¦>ºJcŠ:Ö5ˆø*ð‡§üP-¡=Ã3êášÁÍ™¦£ü‘Dx Z ¬Ìh ·hºžœXÏ´v€*ÂLuŒ]ƒ½ùÈ×½H‹¢Dd›œ#©£&ÍLKœÉ]9±‚ªQ=.‡â<•tÏ@©¨À—ƒ¿Å\JµÀ¨H³ZÃS’¯sŽ•\NÜä2ÒñTᙬҤ¦ <«tÛ,³Ò5ãëfÐu¥<}#” ··Š s³UÑ;O}´½x “=6h¹349ðPu Œ“þ¨Ø lS«Ñ „|È{þCòÅ‚Ì$µ¢ü‡ùŒ›¦¨èÊäÒQ é,Щ ¢t-­K ¬Òœ¨ˆF06$HÕ9Ú¼Öà} ñ:63«,ÁSSzéA’Š£°ú­PÙRz…\ \¢­ô^ÁÚ¥bÞ€!a4:ŽÖ ‡ðÀ¹tŽ>L·Ý½+KùF-ß:;$:ÐÕXµ½±S¦¶i ¸X²<ÔV4„‰zÛÌÚLK»fµ«44Å2âQÞ&AªF/.)ãë{4 çd+LåAX‰K+ÙŽ&Ò„§Kf¾ý/ÅoÏÙ?“,©±+Dó„½åËœsGáÑÕ„"J3a¼Æ\Ö 5P®^=u÷‡ÁiÐ;Ž^. 6W*T‰IÀæ&|-µœ™QPscfpƒYCX´õÛ'³cgœ^üŸÊ¾Pۜ߆ý6‰ITäÕN¨·62]gS>ˆÛO [Âqë^~£¬Rhµ¯7ÌjZ`äÒ²J®5ЏÎÙ÷Ç%áQ$–¡©b°xçbâB–œŽÙÊÉ ;"AªrEqÞÂ`Èl5ý^€2Aç"dì-h”žápiÏìSÀ˜=b¦IJu~#Ò¥Z¶ 7Z¤ª7òšº zÖI¶ÖæMÊÏÝg<…fÛ…ÿ@6å¯&€ÔŠ4üíf†9fý—pœ¤• º¬ðµTÀì5j|8;bªVIåMåÓg³=$,$gÚÚCV0ìÓGÉö~ÅŸ:S^cïÞš³ƒ7ôä‚uˆÍEÔ ¥¼Ä{ å°ØÜíÇÁõ–üeã³W ÚFÍÕ$^·‡í.ôôäãWdXÝ_m ü¢•HmÖµùƒ±˜Ê=d¥Wä¸IH,Е¸´Ü)eièø[ †â¤4Æjyæxe ½"`;‚– 6GIŽÉ;±¢fŹï{µ^Ú•Ô¡¿W& ¾{Øïytûx‰ôîH) ÙQ²çåÍ#õ`Ô3R^#¹;Q8ùû²²ä|vÙ ãÊaã%¤×é?½TÈ}P¥Áv{h¾Ôš÷娀#Ç$–ñ€IH)í¾Î¼  •}Mä6d® àÆ¥R *B-÷¤^”±ËÇRÒïPÀ‡ÚãÒt!Rú>ÈsèhYD˜Ó1h6¥<\Dü§í¢þvˆ†¢Cià˜LµóÄ¿ïÃ\SÆÎý‹“‹oø Ê`Z„OéN¼Þ–j…ž’ªáˆ‚?àÐxDC`pXT ~Å`à8Ä.G_1øKü#Ž€ ñ¨êU~Æ`‰ƒÎd š?¦ÒÉ,–].†ÍŸÐ¸¤²+%“Äóê(/;Т j„}òªC Sésòµ>ª òÇÝ„c’½ìÕÚX ñk®ÖŸ“@L²“ ŸI@·yÄv}HˆÃ*×øßÊ£‘Øl³ÛÎæ³‹ ºô€ Êô›9 ;ξ¡®ŒÆ· Yð·&DÇ'ï“`ÔBÍ4+±«›VÙìk–ªC«ì2×/-ÉrºÝ#¬º\©3Ksq ÁiR\–%ÏBm¹'üDŸ<@.Ò°h«kJqû£ií*š’º»'2¬ê®º®³V¿Â³¬êƨú—HÏâÂÜKª¢’Â2È#ö·ˆ42Ý«JêXÚÀé ÒŒ¾Lkk# b¦ÑꆎÑGó¡8rý.ìk€Ð8òí¿(¬¹rêÌS@ëCʽÃ':¨:Ü®Õi zÕ5lÔÎ|³©t'8Òƒü4˜Y¼4á¸Õ;ŠŒDT¢è›©ÕMÀÖ+N´ÛKÞ !¸m~©0:u’¾é2 =Œ«M{¨ÌE_ Iý ¡wJ ˜ºªÂ0ÿh‰ek ¹’$ s:@ µÓçìE-[Is½ƒ8™äÃRl¹NQvçSVN„Hø)ü׌˜ú$t¥š‹h›°]¬Íळ°®jÚ¨"¥ç4r©‹æwªYŸK²ïw¨RPãEOžÛ€ñ¨¬p¼^jFá­Ñ ¤µ ÿÏ›ã¢IÍ3+Hë ¼øŠàh6§#²ÿÌd=ލ0"“˜æ2rK*žË†à–;H¬ëvÄñ&sYE);ûª;:à Ӣޤ0>˜»*Ò²­ÛiÞuD š»M³ºž°ìïYÁK)÷1ƒpý!F-Í]y­â ¼Ó‰b.¤˜.2l¼É)À!k~¦ç¸ÿÎ9 Rn-ã6d4´‰Qpƒä!h`? P!¯yŽ@„öw_áa~G/”fZÇ@A€¨hýuÚ›Êñ3ªn3„,ÍÎzÂÃÖ(-Ú“™ºœm Ì%ˆ…;<Ä»ó”ETz"p0€—+Ã5á!+¨A ¾ØÚ_`±«+¨L©0#íû\J TD’¤â²ò}ŒxÄ‘ƒ€c`{j|Ѱ“à$Ìé,4uÌ(öÉÓdeQ¥=—BMRxãý91¥FiáyZQ)Àæ‘óp€Œkû‰Pí«©FWÊLanä~¨ð„õK(ÒY›ƒ°‹àà8x²èÒD`+JøG•^Øž †èUò¤÷A À$WãìÚµ¸›0H!>šOn€)´Ú€D,R s·YBY@¯t¯Æ0gXik-À2„>1øÔÞ¦\¥h¶Áý @4¾2ïæt*à Ï)öGº×È@“©,B€5à@(#î áOÈcöÿˆD@8Œ „Dã@¸%ŽEä Z/|Jb Idh/ƒ>â°X4(&Ž€f2ðê}‰Ë“uóGÒ_Ô¹ävb¨F¡ÏÙä"§„GÀ8ìj–þˆÌÀUøDò¿#´DáÈÔvyB¯ÕäúHy>}F®»]®]/ +R; B;u¯Ð¢5;ôNm)|2Uút…S¿ëK5/I£¾s`,ÄB ÀÄk±;ÄG:þªÂ š¬ÆmÈZèYxv…¡ÊEò@‹]ÊIMœ€dwuÖ×d‚Go)æg«¯Êå‘ÝÔ²#­ˆuóV™¯ÉhÌÇjÐø†îYS„^#Z} ×ÉåH'ž+ÅO†â¡ËÙüã<ÏÃð¯)køÍÔ‚#JÓTŒ:);°¾/§â„&É‹\—¹Š¢^ð3/ñ$mºƽ‚Ê—¼Î J‚"+Zð„(I³ž¥«±þž-©'¢êœe €-zªúxÓªP X¯­n¦{Ë\´µÂ` ¯²¢^©¹Ècb±ÇêèOÄÙ+Iħ0"¯Å@!½®Ü„EŽú|¯Ô*ðáÎêZ„{Q“;ñH®j’ˆ¦+:‚–'‰‹4Ÿ¯ú˜ºIó†ì°ÈºŠ‹Ä)âmFÍáúü+(ƒÈŽÈÐÄ4÷ÍM"Ó®«¿,èÐaÊ'ëº$u.ºªjœ€‰Í‰ä¸ˆ.ªcM))‹eVHk¢–ê7\Œ†‹¼U‰ÿK ª º£Tª¾ÏGÏ;6,S£ü£l]›W¹-;ˆ&-ØòÕ¤’—«S£ánDÒD‘i!¯aÿ!•tÊ~_qÛ`ÀMxR¦¼-Ùdò_ØùÚTØÀ»ˆb5M¬½æº¡e¬ƒâê´ÊŸiÃOVEàK£GΖӸÎеÙî:_ ­— Ö¥ÃàsEOÉÍ2ƒE5g [p¨Òâ)ךN("lyîݼ‡gTÃöÅ—žukwH¡' Õ¦çÌ-ØÌætš ©´üj3£Ö~ÈZ¡‹­™‹1œÏ«ãà†È.éò;S€+]å¿LZB<ðêpÍ{RËÕÇ)«hõ' HåR"rµ¡ ­Ya1 ù‹¡TNüôÏï'tÄÊtâÞ–­XλãÁ“„]³\J¶UgP­_xEùoÉöcªÜ~mÏ׼ÌyZ.Јñ¼¾l›/Æ8˜ÈsÇ"/&¬—_…,/‘“õ¶ñÛê]x%%82lóÊa/I ô—}B#Àó¾öäVà —(d´'"Å›)ö{éý¬¯ ‚˜+ï| ±{BDÉ‹hhäá½äpõ¡&$kŸLÙJynÑæ;Pº—1$bpi¹¯ö,ÍØýyNµãÅ'„ ;mÔ”ØçGáÃAP¾1'ÖžCcugá3¼¤d½ÛÓQÄño¶Ç¶l™"¦z#ùÕCr&¾Ï4nkЛ>”|­/ P~ÓNˆ^SQ]F„JUB>šq÷‘Q^4&l²‘œ$}ëì¢H¶îÝ\„!Æ|Èü=fî²lV~Ùжcqü‹–¹>üår&FMñm¤âa ÌYwЕö¿ø%PgãI²_¥ÒMaO²µE„°Ì„\Q`²ÄZ?Ì H'*œ˜‹–‹ws±ø¼'±¯+FõÉÅâà]†`óNièév‚Ìuø¶¥jd)*ÂV½¡þÔ“tŽò—Hˆ1Ä(Èy€=R„œä²BúÍ Rv\P)4z:âÔ‘v¥21™K:"ýÌ,p!2ªŠsD˜QsF€£Î’Fý¦É….¦†~0‘üpÈêa‰.hA»‡Û@¢¹”;E¾ø‰a6 fžtº…X™âpú#ñ%dž¸<‹£Ô‚¥S'J©ì¼*pä6VÄH&K~²õašú¯&ºí‚Žx•óBÖ\›¨´ ÕΆ٢¼(T`ˆ1ãSPÑòŶŽì»¢4h[+ø*¡×!ælñfBRBs2^‘§p.N] y¤å…”Zë£èÞÅ“™&Ë¥³S¼¸—ÕK´ÌÓ Äï'ö€ žß›+«˜®¡$DTÍ”A¾³ír Ç¡+)Š%·—"–&Ú¨Uv¾±„°Å¨çíŤ˜B.&<±aÞj×±_²ëUŠ‚7lÅ ž¦rx°!eBNiš’°4’ýî¾bµ‘ÔúÀ‹ñã¦vÑ ¤é)÷¦’Bl·Ú:,ÌÔEÇAöM–O‰%J»Ø°bû²Ë’Q”rÖ4ö†¸ ¹äÛWôXu1…zsl>ô@íóVSÖV•ùjnñP²”1?ݪE/qüõÖD §[h”‰ŠÇkÒ}^ˆ…=h¨†#ØŠÌâ@+Á4Oä|ÆìHˆ¶S?YíNðAb]VR0Ìâ¡y€&·!Î ¬¸ÌRO­ÛƧ@…6^&AŸ-NkZù,ä`Ž4á$:›¥ }C¼;0/;Þ›yÅa Ý)¬ñà ºdæͼH¥îéwYžì¾³u×nÙVÌÚÊIâ";LÙ5úã¼måécö‚ÍN¦‹Nhv†y™Ê#gbÛyK@6U·ÙÂL4lH‰´\>D׃-oÙvnº„C/µ˜ ´Ô¨%ßwî†Ü’Ê-xYZ“ £Ÿ&/õ¹P$²çæçZð^¦O W2fùo¯CÎí N¹nòs~‹h-ÙBOdƒ—R§³â®3ÈöÄÓè%9/®w™¤2Ýû½úÐ*$ô›Î5δþyˆD°! br´ó¢)Kh„+vl…ókRÈåq|uVB?¤¬]`ñ¤–Z年âú½ö§Äo¬z•¦bÆRÀÔÉaüfŠÈ‡ÇŽUÄ@MtñL6]Cðù%FoJGÎ4Ek Ãði‚:bXÙ¡ò'Šà‹êÓ` 4#ÄUÈè]OÒþÀ.¨Ñoß©nFúIƒN˜«‰eø3)…–¢Ô‰ðb¢—&LÇÆV"å€#£†è—ÈÔ€¢|¹JÍ/Ì‹«^éÎÀpÔ¢æoMŠ–&£)¢]‚bçМèàr|œ*XvÆúªL00‚Gиz¡øµôÛL:íix(ÂŽŠ"ŽUÂÅŒ†`Q ^æ®tNŒX'ÇVÈÊF†Šè(ˆSˆ5‚|k.´w‡ÀœÀªç!F6&ÊnÈðhnë(›Ž¶ø‡¸}É¢œ-PfÇtâ«l¤¨T³,Ôv!ø´â O* xñ(Ýì€ìçࣈ‘®LÎàÔP¢Ã‡\ãmèë@h¢XPè,dk¢p޾wLHvˆúÞGáåD2E¾“ŽŽU‡ü@Nr¤)28ÏÑÍŒ)* PÐ$cŒºBºêcÌÜä"RÁB_‘>ÕQ”ðçÏâÝ.u±È&EÄ÷pÎQâ4"4Ú¦˜NÈÈï<ìð©0„g¨|öjÿ€4ïâ¤Ìû.Šo¯Ž´OpÀä.¥€Ýñ`4qÐ×ÂP%'Æ0±0õbR”R„e&^úš`BXù,JkOpÈL@ÁH¶?hÝé@4¢ˆxEŽJL{¬´õC^D*Ž·˜©‡þ®ˆLk«&&¢ènj&6-oó#Ìpñ’Aƒ‹Ð Q92†úð1h¦‚TŽÄ¾°îÔÊTÃj4m/;žÇi=-ê|´Ñ2D×’xð€dÊ`]RŠ›‹ü³ ræBFEŽ ?@³¨xdÉ8éÃ2upñ‰ÀC."¦Iî×nfMüˆ¢lháé:çˆìËÍ(h"˜B4X ØÇMØ£â 8kŠ2Èô–ò¢ «B’„å® Î}8¢ØSç;Ðv)E8ÊÉâþè­ÑÅ4qÚþJ|Œ’2Ù8OÇ" ª€Agx†Áöf‰oéa µB/LxŽÉ,ˆ18JÛAôÛm@%óªÙ’:}g”Xl˜S`_ŠàÀéNäHê¥gÞ±À,Mc 'höî­@G„Q“È*pE êp0C2ÈUÅðÂëK ¢|±­;ïúC"„ã«HÜ$NdÓ¡Áò*gˆwE _’¶ÇstÖSŒßI}¹fÉÉ®g‹F}Žó:Iû-Ôe9!ÐÑ2HºÈôÛBȲk5§­ðzÂS+ )=N ÕŒ½¾x’-/8mFXn[i|Þ¯j,¿9Q„÷m .XêðÓ´‚t«=Ѭ§àEš,IÂ]FЛ鑈º–Nmô‡ë8¾ô,4ã†ÍㄱèUOÿ'Mì*–ò‘¼!ÉnóP\)"ñ^˜¬Æó’“#Xê`÷ ìbŽçQ~$•*Xæàl¤£B-gˆe)ôîã'j}C‰èí)W( jðq Áê[7n,vøm,‰ï@ÍVÃJÍ(#eQñ çR)cæÌQÐD½éO4ù¤XÝïÀb Á±JIŽ# ÐÞì ¦LÆ¿åÄ5èO š8É8¯Š–ñ“œ ¦Ñ6Õ>š+wLbšðÊÂ5[ÍÎUÑΕ¦?4›ç"/^‡y9ÈM“å>b"ÖÑ2æÈî‘Âë…’Ò¨O ÍÌÒ¤»\` D‡Z45DPf_j=ÎÝ+)BV¦%+V÷ÌCJgÙ³!GÖöé|à‰ªeÊTxŽù-À ´2ó(ºâ¦Æ'+ÃS2ò°ím ­H4À ÓV®‚Å3cq,‚Žß´Ã`ŠO ”FRŒ"§GCù1¹DÊÔVo HäÓm¼„¹+pt&0>БCЯ’Ì┉J¢¢–ÊÌõ}ÉísæRù&Šñ‹‚ÁY+X’ Ó–™“£N©"ôAoà ¤é¥YÑKÔ Š±›YÖHè£F£7­XŸ$ÌåYÎÕ‹w=…ç•ÉV»KñRš4½´‘nsô¾î@UÓ:¬õ¬]–a©-C7)£5î”ðϨãâsîúÝU8êsÿ?` |ØÓ•ut&ÚkÈyZýg·}•mû—4â wTHzFîžÈ¼´RÃ’oºÌFKÙ@Wµ­ó5 ©ÈŠ.·NSŽ"¯ì,,1jħCV1´f€cjàaÕØæŠfôñJ3'ü$z¿r Ͳà åYDíGtÌðÙb  šQ®®¶É9¤høJÄËô—èDëÒFq:™Ü2ó‘D#2HµvS¸’bq–©®&ï)ƒb`ÏòkUo­Þ‘?Fì ¦’Bªi‰‚Cñ!¥—Ésòh ­¸œƒ´?`_#𗱂ªâ˜„0DÔÏ‘²ôÍ£“%+d„2üÏÙX-¡vÃ8JººËÐÇ4ÅÍ+Æ7à&2 õŽû )­Ùï&Jb§" õÄÅ¿ ‡ù=}> 7¤ÒÜÉÎ)ï=?µÂ–ÛÔcÏW %‘Á8J"kÃ?êå/’ÇÀµX1ímüHã„ð&Ä•°'¤õœd:|¤nPžIFñd…&9)÷´¯€ {„¦‘HCÉ$sƒSl5æÂâO*Øü“,²`‘hK cso=Nˆ/Väî•èü+j­#ÞΔt}«ùÛŸ‚ E#ZÂxsHþ³äq^!ÑQ6â2EÄÞ½.¹6E£;2ŸˆQ­æÔ¬aìÝ/„8‚ h“+l¥ÂÄfpÂÙ1zлÂäzr‡þ†ôÊÈ™¿!.HĶæ¢rfaa6ÆF“71!§¨èüQÇd>¢8b^c1Èb“–Öó€IæjH¤¾¤%¦ÆùÞG¥ ñct&VÔC¶ZM!ÿ†«¡*1ö“Ÿ¥g€­z$PHë%bX*¥G~À•+‚­„½7VG8OÐq˜SÅÔ·6*#'D‘#’³bgT±1ˆ¸Ñqú~dýgÊ®Ä5’¸é;–~<I‚¾‡õ2i®R»94¬jú9Kz€-7ÆAÛ«VœdùãõrÑMesm‚Y´Êòn›!D  ¯ØW\¹4q¥Wĵ•Ìê±FFÝ;ŠtÆùµ:D9Gò·`L"‘Æ’I+Z«ÐÀSž»ðVï«þ³+–’×I'`ÅÓ~F­&J:ÊÎ#ã;w ¦Wö­Gª¹d¸ˆÿ½Æß$ hµé­ÉʲOìKú-ÅN-iV”¬Ãjm¹ãaÜ?ŒdR)&·ÎÂßYW/älŸ$O¬µwpÝß9Ï=\áB û,²Á³e<Ò#¢ =2’=L)YÀÞ‰}d+-ǤÆ™³Ìoȧ§Š?QòCWĦ¦÷<ë¼ôŽÙÖ~T\/Ý °±ýø¬áóUñŽ Ë9Á¦ÚE2B¯^,!ÌÞ6âÓÈ!¦4îdiv1á«™q,dªN˜Á“Ru´£ôðGíøtª‘»BŸÝ/>ÞèÇpn˨fàÒK$*BŸµ?œ2‰`±Š™œÍ)pÕñ´™ØÝnö}¬  =(ÿ'^ãî¹n!¼ÃÜsr®°7]T6+ç 1czÄ~Q¨—:æFѤ­¼µ÷>C-•9º–ù]CUS/¡ èPçRCR²‘“ŠËþª° ÄGÎe duÊsH%Ãôœ‹TÃqÀ–o†@(D]üØêÂËÆ(ž•–’(޲©ï0Ôk*;º‡ó×3¯a0—+¶“Üg9´c¸pçÐÿ¥ ô,€´š*˜)ûâߚ±'Cˆˆd #s‘ +]ÂO£Ô1.Z«¡Û'‘¡DŠ¿ HбR0жd&³B}Ÿ‰ÁªƒÁ¸BªSŠl@2ùSDÉF!šëö!ÚP©J±¡Ä¦Lˆ.YÌä®ùP=‚€Gy®¹á¾xˆÒWBiö>D‰HIœ/Y´‚=D¬31›Æ—sÛ£Ü&•JN¹SðœÉöž²ìg²Šz¦ zÀ?q0 Ãû“ì7C‡Crlši¦ì&B.Éí¢f,زAZ›R{KÛÎA´&‹ÜI¤³Y³R=!,±¯œ¤U·ñÅ<“5©ô ´3+œ ©‰ z‹IßÄ3÷$$ªJiÌ!GH}-dm¸ÙË?>‰ú£M¼ôw¯LŸD 6È3+©Ô­<#¤¬+‡Ù½ˆÛÔ¦<Ö’P… ;SöCÉ!z§ÀD½°ô3À3 ø‹6C†ÁúQ3ºê¶R«šùë‰@&ÛwÈ•‘ÔÕš8ܺ@úX1S20;4z ÎvóL«dËÏô¼3\®ÄgLP‰r@ØšÃ[MsP%bAø»l'ƒ²ÐáTÁ¤á.ÜðQ,Ý›yõJ⿹¼·rÄ¿‰á®3wX7q… P·ŒßÀé‘óù+cw1Ð誜D´ÔµÌè—©M'Mq׫°ÇE¢;“©ÉcG Ùç§û~š³ ìþ‹ Ê$Û„ëð›TÊ\ʧ*Í…1£»ö2(ÔÄû“Fª´)2Ó 0“Æu,,J¥\ï6’G»[g(ƒGÐ¥Á»Ú»1ç½›È0‚¦¡Ë‹¾Lâ¡*ƒÈ‰#ú?;4‡È€™ÜûN0$ˆœ¢W«€©¨³ïPrG@S¹C¬Q‘áÅ9K"å¨óáÅAC»OÚz:XSù(óåÓÈ éŒrµ»8~¬Š‰ ªº¦QŒï¹*Í–Ü¿¦Ã%œ¯4YÄ­Ùâ èÍÙàδÛ¦Û%B⬞•É6R q9S%%šÙ¢¨ñÄ5Qˆƒ`‡å)7ñ.tô.€ ž!Æ2c³A¡Xë˧âÙ“ë¢Ö‘ßÂóLLÌFQï^y¨•ŠË_DÓYG`‰ÃWåQÚ.òãO^\ž8‘€Eü‹+Q»¹ÕšS…ưT•Õe•Ë*šŒˆäÊê‹#±Ö:D "ÿŸ›ˆJ¢ÒÌ ­É.vZ•5À(…M Øå+  \`cÉ'³Å#åµä(N ü‡Ø°ËVÊ|ž€2Š|@bÀ’ ÖHÓä!έR9ã>:½¥›Š71ø°ÀÂäÛ:†¶P€:ã*bmšú?× Uªën«›ÿÈêP²ûªÛZ<Â_⊠ˆ´<€!7rcCÝ¢¾Ä9öfªÕ¸m´Ò%é›ÈS{ zžiÄ&•衋üÛA¼%&KÊíÊkÌ€ŠP˜)ÈR-‡&û˜OЈM˜ÂýàVG8ÎnÅß²uŸ‘ÈB èvnåÕØV• h*r;ì'MÞ~J­?ÈüD=åiãRü‚ç­¡²#v%Ò΂ÏìáÓ´ä}ÏÅØ‡Ú5Æ)Ó‚›x©¼“B9VÇDýB!© ‰ÒÄg^ ðTÅ¿¤u„R¦ìpõ!êÍÔ¤ìÎ=8B¡¼– §Âs‘‹1)c³kBÃYáÖ¨ŽSžÛÕÄÉGYÃÖM,ƒéÉkžxüLêÖi1¨Õ<¿Îr<]å›ÀóÆZQe¯©XÖñ¢µVĵ*¹Ü•Á4õö• ëL È¿a‚ÑÎKú“ã¸JlOC~­›™' ©žâò€9öB“â r¦(w€æðûbŸaÙªØÚú¡kž<ŶmRUÞ ­‘Õ¸ŒD†½VÎR2ïFv YBïap˜ÜÓ‰¤E*ï'ã2ÓÔ»µŠc_¯‡Ìîk¦zþð5V!´ÑÎ,KóÈ\صt'£Õ®£Óú+ê/4ˆ`—-,b2l-©%üéÚ–²Èu'RÆÀð§DkܰeÉ>U÷èÚMÛ„&¨Ôß~Š\ ¶Y‰&O“éiÈbxX¬6p»%þN]p‡ P²“áœaõßD;\S9Û%#úK9™:<Û*\¹+.[ü¥ù0dµG☡ËÑ?ù ˜¯ºüÞ¿OÞï¨0’f?LL&/MÚìPòcÔ±Îmw´Œ¯ó¨êþ«¾£ÍÏCIšEÂa§nêi™lîæ0àÄ«w®éØËmŶ#¶ÒfŸv¬¼sà²á÷Söz%¢©“$7qç©Ðã÷sŒv¨aÈPÛ£ðy¡ ÛóÆþÖÔáßzVuË»Æè0ÛA¿Ý$Zmd) ÔÌ?<êjYÝ0ã"ýLHð}ûP•¹«þ绕ӗŠ#¶ßÌ«võ©Mø²*c@Qéqãçá“q,I·ó+j㔽¢%’›‰´%“òý”Iìþˆú‚?`Ð(D$ ‚€0ðF%Å_qx3ö% ãÐù%’?âQ,¦ü–G€pØl¤ ‘Åb‘Y¬š"žBù„.û}Qg€xäf% ‰K”WÐ&¥ —D¨pŠ %Rà’ ÜF+–Çáó(E^»¤Á¤ê„‚¤ ’T,p—ôÊNÄ"1˜Dr% ’Mç@ rIÂN"8i•Bçv ÆiÓ, 9.†ÐïrÉ #EN|éAZxnR¨M"2ìTV3L±P¢û@’9N„Z S÷ÄJ\âI*·ø=®·œ‚X@Gå¾ÌÌ¿«èæ _¡ô€u t‚3ÇÜÅk4é,V].{{ntî¬#ˆñA£p¹%N Æ¿öh" ’$ ¬9¨ŠH†Á08¡½hó A`8à>p›pôŸíSî$C̯¯Àþ²Éb$½ )òÔ¨©’Ú~¯  Hç0hz\§AI²ñ¡èÊ2ù¥ÊR"§;LBù£/iìIǼ ¬Æé~ÇpÜ^”®î´ЬØ„*=)Â'ó‡´@C\(òcú—Lñšr¯S<¦çN‘´ù.ÃGúdúŸ¨â‡)¥ÈB2£°Ïø™E“”½È’Ž;Ñ9ø£»±Ç2¢1`PÌJ*Ø!n»BÑ•[öÞ T:ñ)ÈPƒdûOÓ´|¨j,‡ÕÇô¤‘ÿ^€(D¿$J–Tˆò°ó³œêª•¡þ—3ÐbdzÛS]7eÊLzñ³¨¼T-Gô¶ð#ÏšVì5`Ù0ÒsDqªÃd¹×²C9Äp4(…Òè4YfØÓ<Ú—MmRe(õÌf(j:%‡9ÉŠTXˆkbÃÍ·VÒÈó;‡áÒp’`¨3³5Š,”ƒ8È󪣩ÊuM!ónqOD‘ž€nvn–W4‚K=!÷åꊛ:{.”ÇH#æ¼Ôù’ØîV•eé©*@ÏŸ•…ЂM®­BµWÅ#TëbàF/&$‹¾ju jlWœy.9hòŒ·idXù³bŒ¨möýŽ!qdÍq<@ ¼nªYB"ê:ê¢Êüp k»¤GHïëœæ\Ƚ­ÖgËæ–ÇYU*=#òÀ9Zo^ÙÅ¥3Ý”œº³þú’m/ËoC=•ô°íŬ ›æz"àq–BûY€w‚+¢¬Ú<Ãl‘œÛŽÛ´b¾2Á!v¼ïÙW5ÿØê ÝS€Ü<„5‡G¼›S2!GA¤3’šÚÔl$Õ:‚"ÃŽÄ$Qšcöø‡ûÍYÄäÜ4"NA™V"äq\½TGŒZ¶w ½¼“VÐMé+-‰Õ8\n±.edhˆ—8F?]ƒ^"/­à íÞ¹(wìì¼!¤Žï€)ÞNA`5Òc #Î~µg@®Zú“®ˆˆ“&´W¢à/)i¢Ò„лÅvM±¨ÅRucì‰4Ú„É!À$‡î%(ÌÖ (ÿ0Æ&'iƒÒ¹ñcOM˜ÄG¦ÅŠcÉ]~H–ý N²™¡#U Š÷"¦D¢—7èäGñPHë4ùÊ%†K™gøC|‰VÈ}ûÔ”Át¡œÙ=/0”»¦--‚[Q„J|eòÜ÷N!ª­Ëè’S¡ƒ@Á5·u묗p&.B~YŽÒËÑšŸ©‡´kòf”Záªk‰Ò–5âÙhO˜éÆ&G¡s§WÓ¼˜,–“R¬±ñcKÝ9É;¯fN$®í²9Ôh—s*4¬¢¹ë¿(QµÑ®íÛ¥·v¿'B}…—,éã}dÀ e»¸œ6D¶ŒóüYœ‘˜ý®1÷1ª“ª³O🿒A,ÔôÎt©?4$Î÷˜´nl_qn¶¤Š¾OÏçr3ê[@9ƶK’.ã~¤$Îùß”¦»’œ¦©çIxž¿m™NÛ ­Õ Ѥ­r ššïCQþî÷¥Ä$±5ÓQù«n!AÛBµtG|N.šÅ¦c>ñû5îKí#†H©DSú£Üµ¡zS=hûb€J•Õ\­á:ÙWYĺÑùÛ¡ÖjO!0û½À¢èHO²3-Œ:£Â?ì û“4¬ôÛèÀ„Ôq¥Ì5(;mø-†>e²õ»ÕÑqMmÕ.¯õ^G¶ï ±LH7ÆBÉ”´8g¦èÚc€HLEÀbº­2?ïóÐ!è²0o¨ôÖÇôxœ7©;F˜ãÊ[³²oMîÝ‚V\h«Ð¼.^? &Aà]{GÏnÓõºñ¶ËÈö¿F×ìÉ2{˜\òX¿' ¢`"ÄU¸EÐÖI£z·/©g©ñÀ.kI4YÇÍkäÀäIâc#°ÆÚ!©Ôl”Çê¬0é2X%ˆÏ*4êOH:âr™‹ ÕÏV›Â$ùÂ2™É¬oF¨ëÅX4äÎX„ŽÜ‹­ÃœHì‹fÃb·^0ê¼ËpÌÒ4¦„&D4` 'bxÙX* ÌgÊXg,g)~æE!¤Ö$˜Í¢ÌöøÎÜ¢ë:ÃÜs'æ†Ip8†¬Fn,‹ ê…ÇòÊ;Еê(ùiøèoB¶šíJ´Í@Ä b>a«…Rc®`®ˆ¢²¥4ådŒ©ÆxÅBaÊ‚æáŒk Ä€g*ÜÇËâ/š'Š®¥˜~ ÌÕê¦ÖMÎô)¼7 ª4M¤ï¡òªu¡ö¸¨6(¦ÈùI°'ˆŠžÀ Šàó¬P_‚I‡8¦BYŠâŒ0¶?i~¯` þM¿ î6E‡®: Edb7« jR–å&N˃ªõ e’b®bäWñ²ÿå’õd'Rà­—é— PQâÖ+ŠBcÈ\â²[ª.Jí¬!)$ùm8OÌ›ü¼«P(%Pï$F\íðÁÉÆM±~Ɉ½ðˆ(¤ÖÜKr=&º'( B†­È"‹¦ãް®äÑ­°îk¢*Õf[#àê®T,I‚8aÉqñ?¨ AìØRb9"ÈÌâãqNtYiØâ〡k Z¤ä ¢Ïð&úW*Ì(„²öd¶û±‚  ®òJf¬üä5¯ÇÊ¿"ÇWpûDª!Ò§¤®Êâ~À V­ŽP¸Rœ:î\±¢\L˜E“&*­+’ˆñÍjÎ"2–P°à¹CuH©±!£€­ƒÈšäÎMeÚQâφ?Ë ÆKÒl­&D˜šèuîTžPòìq1ë-Ëp/F Éleżʯ²ÄÏÙ$""™ãªüÊ)ØÀä’Î¢Š­’Ò D8rïÖdÎËÓ–¶§vâqȨC „ÅëHœ7È‹,jªxŽi8Qä¶f˜OÆ«òÚƒÐÒ½ÒJ«êzrÎ{Ò¤réM5 XÖ‡-Füɯ¬ÑŽÜƒÃ¡DØòs:éDõÅ–ÇÄ:JóvO¯P±§®i Î-· §(~’F¿‚X·Ðisº@н†¯3}2B¥!ak䱓ʶìXö¨î¥'w"­öùˆ ñ’ ÃK<³ž/z"Èd¦ª=+,ýÔAZ(]‡‚ðY¦‘KólY0S#®d ¶ØƒÓ,ðhŒâ欶íϬèLH†è±ÆZ×Áò´m‚NîÎÿmê¼ì°ÒFôÌ`*¾kM=ÏVÙt£S†§Dl¿¢xŒÑÕ#Ö~àíT9L/’ňŒÂ8ÕV##÷Acð¥%~½ ±ÖîN† $£6ÄÖºÃpö.4£€}"8m!N$™†“"¡FƒúqŒøÒ!õ­ŒBiا«Æá´2“²:4Jتîד‡µa ‹îsRYCTi ®ÅcJaoÁ kƒ gÂí,¬8Ó^(å5‡­   J馄â]tŸ"k¨òß!ö+dùC•’ªT7J«»FŽókb±jzl‘êÙPDͱ¬P–”t¯>P6OÃ¬Š O‘1ê{)Œm‘Z½üþŠ6h±£¼–‘ÏÁ.Œ|ì`O®¡$Dü%Ðá0Žø%+xÛ%¨Át·ÌøÚMÐ žY/õ䶈o,!©”Bަâç/aðn¡÷P€ ÁfŠæb#qÂzéR¡'e:sTœïþËÌK"Œû"K¬‡ÉÈ?«V²6@:jXY¢e)(\°$¶@“nlâðSVàfDó‚S,󀊄ØËa,b²°'¼ŒÉ¼­’fû68ôŽÕq.vµÂ ÿ€m¨RtÓ8¡÷ol†ÜB2­†c®žvµî·YD‘HPHÍ=ÓÊ$Š †ä!i³–@lù43q3Êàð&ÚB@¼ºHýB_ÅtÌ Q—AÇÚ;Ȇ%Ïì*K\îõsÒƒOÂvM´’ ŠÔ0x6åmµyˆ°cV¶oˆÏ7*¤dÏtÂú³I¼æ€F%ˆúÍ‹wÎ Îñ%^4«n‹´#O%—0—̤Ä:[· üéѦˆæDLéõ€` %O£Qftíj¾tÓ‚?°ñS/F:­ÌvOG`Ux‘«Fš›nºÂnÛÒ´F$:ú'@Û!+)dž*³Db>x’:ø<Å8uö ¥º'1ؾ”âÚ…Èãrch F<ƒ Tâ]ÕòôˆCETâkJØÚPÒ¡eŒÚE~>o,SVXÏGŽULöeH6ZösNŠ&ûH–(}­Å,¦xðeø\±§"Bø‡@$úR¤ brê›1{f”rïÙR’bÿÐôŸ8¹"ƒ”*–â^aô»w£ª/·ï/ŽotãWáN8“ˆ0¶hUVÓ$*CUGоzíiFçÚv²8òYvÛ ¢Ž&K­n~‰Ð(oïrGÚñŽˆÅ³ÝBxÝF¨óA´#;“\%/~åDÚýÃæ÷wóc̶I“±€ÛM "Òf}*Ø:£÷~€øÏˆdjS˜ 4°;7âŠm9N'ò YR$L¨Õ+ ü÷š…Ö¨ÙøBÞm=ƒCSy6×¶$±v:¹îÐ4ô"669VN+eºÊo‘#ˆˆk¶°5) –¦“ú¢âý•}ªJZ’éZ4€Ö0미ÿ…ˆ¬¢?u¦'%@T2å>T5jOgX‰æ )·Xzóbúö±Ä· (}^CE&ºê ×É}1Z>z•©yôævQb?¹ƒ=Æ­.'ˆ;ÚY%ËÑbij(¤;Y'nÐXõXQ±BvgÕJÖÙÿgÌ·[Yšå4,úgÔ€ƒÅd8™4urq$Ù?_€ pªX¥”Ë:©c~°;&úÀX†ˆŽ™r­±,K¥O•M½‘ª‰-nèó¤ÿú#-ÒJ²¹5bv$ oÄbüíi\º–Œw‚–:]ÚÍ—aý Aù©q¢§-F=3K#N>l[ƒƒúôõôWÆœ¹ ØÕ£úÞ¯)Dk哸uÑx ÐÚIá—XCª¾ñˆýˆˆ@ÒÁ9&¥K!€£áöXޝhŒk 5´œxMJƒÓlÓ&˜oª{GÏ'Ä¢Aš .#:êì„üú'½´±I+Õ7KHݵ3j„úˆ»Í‰n¯ƒ‘žBc q•ž‹˜Ì.yùu‹¶ˆ²Öo¬™XÀê\ùw‹†êXÖ,N±n ²c£Thå©Ð5¹j³vëa‡”(*áaÐj ˆ‹Œ(°DÜöe¤ì³M]‚FÌ'/»9ñ7 -R LÛ¸w,m]…–‡…›E¼a¼¼&,<¢Q°hdªíÚ6»´VDvnµÔÊ$'Œ”=*¢.ÒÂY‰à!ÒÛÚP¤t~L¢áð<üX.w¡&ÉJe•ËMH±ºÁ¼ØŒôâ=6 fJ£pýÚ»ãG¬”y™ö!ƒz¿ƒíSÐShK"­Œ'mli  ¬EB?£€ &‹0«‰0ñ•„ˆiÙ¾ÂG MÉØ£5x‡.Ë»Éaî»,G ".öCæ ‰„F)Eǹ =–uHòÈÏœm’Îg=摵wœâx\â%nµÏª œs—CD11bû-¯GM}HOíœúšsÞ÷ ÞÅ?Ú„T¼±p9æ×ÑO=`xuhÁ̓¯%H F;%ÞG(×>~øVòû>•‡ªSÚÁô9Ój›5¡c€?fÉÐ:ß¾&ÖÝ£ÕÎoçãUÍ;’ç$í0%ƒçPÛ.X³ƒ¯ã¸"õfì8šrˆÛ.ö„í•Õ8œ|Ù ¿ͯiÑýdâJvû:>ƒ!Š/˜æü«ü¯p)ß+¬‘¯ ÅvɲµlLP:ò¡×âÕ.7ð&Q’b<úÈ)ÂçCÚÀã¹íd/Wjýz‹ÒPP/óö`ñ¯¬‘¦Éu"(þ6ùÌ|#Ÿ<«æ„”ÊšJ gf<VÐ>˶¦æµoÀÀX0þ…@ßðgä<†CßÀ\†>£€ AŠCâà(Sú•H1'•`ÒX4ž ûIÀóØ4² ý¡A¨XdþAB~Ìäñé³ýµ¯CÒ¡8ê*>Ø@h{˰"D~SÈå]"KƒÏ]¥Ëºu²t"ƒ*Í´]?!Hòà™¬Urá4€µ‚9gÛ@ (Ó³R„¡/L*”ÏUÇ®X‡Íæ¨IhG¬ò=†)ÓmÀ‚žš•\Š)PTžÛ‡êN॓±ÿD'êäα½ô¡@zî’„Yºâªì^ÌÓÏ9QÈ)„Zðzˆ¸a6kƒ|, ŒÝ““Z…/SaühH6ˆ}Þ’ü)<ÐH¾~zê‘:LÌ ¯?bPzEÔïÌšä=‰fß°!Tƒ_èUrÓ|¢ë"^‹…þºÏ|z×jÈ| Xô‰Î8„RºÞLå€gTÇÎ è±P  <—WË^…è.¯ª”¯öÉÒ)£èÉW0Óå)Ò®ŽS‹f ysÒ*¥$º­ºãH}5yLó¼2¯Á<º¸@ÌkÍLÉ€~²ò²uÖÙ;!G±1=6œ?™ãòF¡7C«¨1 A¸£å>½ÑJ/P]/D÷ŠXdy?¦"E×8ÿ„¯‘št˜ç"¹QªÈï 5Ãb J ÈÏ"°ÃøyLmM¬wŒ¡bLP%Ö0—ÀJ9pS$!Q:R¯Ï‚”#1a’ç”y×ê1u¨‰¨nëÂ×Epùë†0mž³d^‡Å±¶Â VÊ! @““6„¦ ©šƒéŽ4òŠE!ƒ¬m`Ó¬Ú3Å)ÁÉ7 ÃRˆ ΔE­% #£‚­i1t¤b’xk/ Ct÷Sʹ{­ý8°t„¬bHê¹ÖB‚|AJÄa”~¥²Ñdá=|„ª<»ÆXs¼‡«*GG¦“Z8e­±BN«–i…Y©x ó\˜ýg–B@—Fª[«ÑX Aæ€IP±€oo؇º8fk2. 𙢔iÏðüU)@™«ÒuF¨¡B#Ê~".ãå¨9ˆ•-v¾e«Šfg‘ ìÝ8ZcñŠ”òæŽÛ0ZÑz£çX¯Þ8û+ QÄFÇ b'¹z$è ™©Ò/&ÏC©³IE(a tÃþ Ô·YB!ã[ 麒B½§j‘qÍÈÞ­I‹&§ ª©Á¯Õr]=^sOÕ†cÔÃ莇ܖ"õœºùæ}fꃓp2hL!þ×êAâÊPª0B‰›+œÚ6rOY"zRྫྷHg˜LgGÍÌ‹“;àÈLUˆ7³êg†Å¿+ –”Z –‰Ô0±¡FA‰ °& Ƕ vAÅY”Ìôð~ ¦ ©ñìu„Í‹‘zl°+ˆ¡©£¡˜õÈAhE¸)òJЙÕ<óu²F«”‚œÂƒ#Õ]ô5B"Qˆ%Œ •X:[g“Pü„dž­’Ç ‘‰;Ba$¹†5\‚ ‰ ”!\Ý›+ë6Ç@ž»Ë’˜‘456G##äw®´ dN’¦Z‘° í¶5Þyæ»iÄ•Ö TäS~ZÊÂ{«jjâÁcåFÑi½Ä„a‹Û&ØI,a‹57?B„²WµcÇ-ºUÔ|orˆ3Å}ÔĦŸ[L57oj¦äÛI‡z ;Ëʃõ¨¶3{S”¥RÕŠ5\Wq‡Ù3¹2,•F8U6@.µcä–_bzèÎ?äƒH<4¼“L‰:U×t‚Ô¥ƒ"%ô¤•ÐÕJOgGôX‰A¡Eigð‘:}Cî­A ÓÕÛ¡ª¦;ç=õ>uxÒØ¢ 34ÇS†£’E²m³WšÃt1®ëÒú‡Y“d“;£M:n~ ì÷|7*dg”ñXuâ+±$‹ê O³áɤ (è˜{xISb[àà”©•2%ºñL)¥УšFØ(uQÁ÷Hþ‹ %Ð Mv 8mU߬´›9]/CÏ™ ¬MnðZ\ÁèÎšë ¨^Œ0ú³Uìú&h!W:7}™Í¼­ Aа•ðâÐpÎÍx„e;¦Ê%ƒÇ€™[ZëùâÀ¡õë}ùÛ¢ñzÄͱIºòœ—O=VÁ÷’«¬Ÿ4;ÅT´'qº–!OÜ~°–úFu£Õ®•«§*¦ÀIÖOϽKV*ªèw“B0UFªÏ“-;\1HÐ×´j&CdfÝc¦b˜½j‹­…×PS¢ ‘‹ƒbköŸ1€Gw`*=m.¸Ž0çÒJ²%¶¼â}JèMàä#i ®ÉWØeÅ­AÍZ&ƒÁ•ÖîNúÉáô óÿ¹F*—t`ÆÎö¿O˜ó+ïìüú!°p Û!R*Øí'‰ó)]ˆ`¸5swÑázUñ†ÛϦ‘#(»KÙ±<ú šø±6 ì˸ʕº‚÷2i3ñ{ ¬8#Žúá€xÀ´¤S‡)P~?˜&èlÂ"¤”а®‘™jþ?@ä@ªI¢Òê*]®Ðä+ 8¬àÓªºä¤ŠÎ%£D¸¸„6 ¾ ®¥k®¹)ø8á_ŠÓç ™³ İ!²8ã8¬30ù¼qí–"‡£Yö«‰‘ºÓ—£_¾«‘&C++²8–|Eb¿>C@A¢A $y‡$Š'˜ƒ,¹¨¢±#Ü£P“m1Hª½³b1œ“Gº{é2:¡œ3“ZŽ­HÍrœ¬²²C½¤¬.=#Ð ¯¤Ús(ú|A‰=ä=6`ç@ÂAFbà ˜¬*º£èÍ¡ ž«˜Š¹À¦ë,™ ÛÂ“Ø Á_°¹b"{sºËë©¡{BÚ…½[ïŸj ê¨CF:),S®§ ¥¹ JìWšk2â)Ne¾HjK˼ >´EÍÙ™¼‰åeX# žšSÈ1ƒ‡Á8ùM¡kÁŒ¢žœC&¢8V¢´Ê)\§ò§53FÀ‹Èã`ºHÝPõ"Ö¤š“O'à±HSaNE ”rV“ÓFUk4¹cËøªÊ#Ñ¢oÇ,Ñ×ÅÕPŽ8KþŸúUÕŽL)ﱫɓ!Y6Ý_ØÑ{?í<Á– VÊ ½“}œËØRl<‹¥Ñ©Tâ:šö¯ã½Û4UhÙ"Љ€(¸8ñ1D-jÊB›¬2V†§ºë`ÒeGÅz¡'È -{Á‹ÕCS¸•Dɽ‡#ÌÞÄ9™yM:$ßµxŽ/ébC˰¡à»Sȶ|)^´öFòÊžlXžÉ, FËß‘¼E0ûÅ%mÝI™*¹|%mY:´ã°¸ž™ r_³ Ó¹³í&GI¡É³?ª¹•Šíu–<ëÍXÛ\TŒ,·H©=S)•ÜŒ=(&Š•ËŠÁÜLÈå©Ê1žµ¹Ân±ý½ÛJ\ùø)5¾Üäàð|JÝ¿‡ÒÑ€Y׎ÕSVÐ~^Ã,Ðý>ÎÀõA¡–aЍˆž á²¨gôŠà˜{è©h«¬áhÁûÁÖ-ÙãÝíîŽ=/G“ÚT’XPØ*ÜÀʦؗŠÎ.æjY+Õ;5®%£X¡V”Žˆ2-³¯X™ké…d£ø$8}ÆQjc+¬ÈwØnuReü!WqØ‘ˆÃK$äØŽú{eˆ1Ì©¯·úÊ;>«t¶é s ÂSãÙøX¢>n¨Ûv1R‹ZÂv~ðìžÈ±\ïÜ{èÏ­+$D˶‡Ö@g奬Ha™@îNÆ€$$X±ún «Æ¥Ê€]8Ü…ÔÐSÜÃ=EË"K1‰ì.Ø´°VˆàþsužQ2˜€> @x#æ „?áOØ`‡ÂŸð€<†?b‘˜È=~Hb@)$–Bü‹€$à‰d=ý/“Ä¥ I¤JhÎ^s¹,¦S9Æd²÷ô¦->ŸQ&òz@{ŠE(gÌÊ/‡SañIM3DŠSé }Š›¯C,2J´úJú¸M¦”J4:ßp–w¹<‘É%7 %í÷uÌæóJ¥2/7¿Fn¨Í–IGŸ`3R™.vI‡á¤ôH”x D­Â2syLÆ…Mâ™8•¬T›ÞbP'Æ=‚‹é!\'ýc’ìü˜tžÅ¾Ãk1óI ¹úÒJ²Óú}r$9â@ØÐGëÞ`­)"ø´É*;/Î)³ÀÂ<–[¬~d!¶€£$\ ÁŽ,f`Û.cþEØr»F¦ý†£E®òK‚ýÐm¯¤HCdAmn‰hÖpKkN$²$ÒXå‚Ó$äQÙÂ0JRšü'$Q·ÀE"‘û‚‡ãõŸ»ÒiY¡pLkk&gàIM™p[êð¥âðs Îάê°LRÃùx²ÇÜ»šÊÕ -w=$…" K¶nŽxΖxlº 4z,ü›ªsx_A{`¼ÂàŸ 5dÅFIƧ ßcW]Æ¥p5¤y\ ÐLÍi.˃¨IÉ ¶‹ m箾Ük–ˆÑ&í¬ N'Èq‘ÊfSò ›‚iZ«µb.AÝ-52ý_âŽ*$<ªJL?ɺ@¤lrm猑á„Ë)bér>à-¡£ùAJêÞ!É9r‘Nv´2hã`IåM¤ž—tÖ‘ÍÀ^q$æó ÏR=\*+Šêº72_££U'·-ÒKÒ3ÂÕþz  íIMªé1AЖ[”öâ?, ,¨´âúÈÊúÏ @g“ág÷Љ8·ÌÁ`-P³étßF³?2)F¿,v€¹¢›C AH¸Ò¤>K€C¼qNÙ×MõŠì‰¢q#9E0xÙXóÈǦèm-(Í(˜…œu÷~, (í­IÒ_´ ÿ¤N¼†nç5-ˆf§ZL Ò‡›­Àz:BQJsä£ßy9*‡ŸöƒH¤åV,mç¼äfÛ0ÉÆÒK wð½ÕÀqiÝ~À4Ì|m‚ã—©=Íá¦Øù[I <’³={üO– ìe¦º7ç ìé"¦+E’í % ¶Ü/åç™Mø±Âš¨xº§ZrÃ:óׯ6Aq†Æ#5Ýç˩ͻZ Ü’ð»>Õb!¹Ãó-Ó‚Ç}Êø›0—•M½Ã«x\¥íÛ>¼·×öUE~¨ïjÒ#k2pÊí´‰ÎA«ýÏUCÑúdîõ(”ÌGv’O8Å›ÏvAçÿ~˜~ çÙêd»ú’wlªðç„ûª‘vùŠ8ûBh÷v–ÒÃacñËž^‹Îmº§e™ÈZÑö_¼ûÈàn’Ȭoñ'ògw ìa¯¶p%.aC]‹‚Á^í{DîúÜ7Øë†ÓR( bD,¢çìtÉPæcL7ŒÜÈ.ÌÞ¤ðZ"Ä¢ÂægtúF 3T¯ÃÒ,öìòJíÎxëÂh²(èv..ÓiºGäÅ01gÈêîFˆ­$ÌÑgÖΨTâê r>­‚çŠd‰Ä©ŒZÔ¨Ç'àvÅ–ôø v8‰hïF¼¦<¹ Ú8Éí@çfXü¤(.f8ÅâH&^b¬Þü¢€ì¦’öžzÂhŒ¶ÄDÚ´.ÒÇ&ê¦â©2 ª—o~‚%†³"BŸaô3æä ë"`ààwÄ£ë^ÚlüÔ `q¶¼j®Áo.#(–Ÿ!þÄKŒK ’$Ž’Ç,ˆß¯òö ¶Åæu„abr&ëtâFJéìÏlóïn¾ð„¬ x±z«{ªò©Q@÷¦PÇmÒÓñ(fæ~eˆ!ãø ‹ÓÍ÷­Z ÏFVóűêžâ åVº â…KðwLÔ‘Éhñƒ /‚Bò†´FI•qnïìràiÞuOÊs&«F ^ÞLŠà.í©güî$¸ÃÔzÝ,DÓ춃”}õ$;£”·R‘X¢ü ”dF±èµ#|”snҦ̓qıp¸oæêr’µ0ÞZÐ>Åþ3°˜¥È•®’pNõ?4v3NvbNmX2ÚýÓ]Aú»ÆÙC~Zu^gfLÎ%0ZµÀ?ðæŽp’4éДó$Î! Äs&Ö„§bí”±J–b…H¥S2“–0…¾–¤ÓiÏNΟM_WI®êJ üÂYjø–©'‰ðïpÞhT/'Œ†ŒôZh¬œîc=©î…C”ÄOÊãcºïG3@6Ë"ÉÔŒe§lk­ìŒÁñ%… M«°aÖv!”Zžâ2·=(OŒÓg2BÍË]ÐAÄ—K (S9Áúh‹¦PÕù4‚ÅŠ@3V„í1i#üLÀþðÏ)¥Á .€¶oG§t\ΆG\œFX,Mìü¤ü^tf×ÊÌ•vðµQ·”ôH”-<…ܺ1ŒÆôË(U^ßÏÔÏBˆ^±édv s%¥L­W9e cæYC` §ŒÞgíçHÁòô,¬ÞÒ³6Ò0Ëa!ýí{dâ%"X].r„wnÙY´BSW—fœì{&ë¹’ëHm-7ÅŸ4 ’…B©Ï†jC†Oau´¦G"ÄéÌoSxZÌæqD.m9Kv–‡)Vu%ai®qN¬þ ›g8±`…€~½SbpÄâGrV‘W YQ'†®ØZ§âü•¢R„¤w¶jŠ7ñžÄG±ÆUw¶¹Ï- _7'טµ[N)gO/¶tQ:¥ JÀlYC‚pÑËr" ~Ùø¹ª/ð/ÄvN#0&áã÷7ô—™YŽÜŒç½ùŸcÞ.õÎï­$í—¾ W( a•Û§VÓÎõ¡pF+ªÌ˜>Á,–ø®UtŽå$OÂLæCð7Þø†´8ÞQ3Sä'45±2€J¾%<ïÅŒ¡=ÿñ¦ èÿƒ!@ "CßÐgü(…D¡P¨l"%D€²“öH“C!ð¨xY ‹Áãpù#öX…Lâ  4îfûŸI€ødæ|û¡FåÐIÌæ MfsWåN‘ ¨Ë(:Óòv†D©(•~=@}YÀöšlsIÌÁ,*µm„N^÷š®Y |ßä Y­+3£€,/êÕÄ ³¾¬p˜&2µH­MaøœJk*ˆD`Õšžk]™Ö£0IG$Îꤕ¬ æ^ÿ”gò0ØÄ‘µÝ€f¸M¾I §Ë4ú8’'¼ÉFy˜z´“¥…Wpw|/R5¿¾m x×[œ™ÕæÐL Î E mßÝŸ7ýáTXÿÊ×¶ç¸àÇ¡îúºÙ»gê€Ú«H“úã$ɺH°"ªÒึ«¢¦®µ*f†*J›h‚!ñß±*ë¾×ÄÈ2e Ì <ˆ> s†Ü·)˃ *ŽÐï¼,{®¾ ù±#')› Ï’ì†ÆLÚØŠ¹ŽÜœŸÂÜ÷¡ëÆ(ª‚HŠGgär–DZqú$H4¼…0/ë8𥒠&%äX½ˆÊ?-€ ù5€¨’‹¥ŒK 4c¾™Ñ€J´Ç¦¬bRج<0‚G@ú™±ð8š¢LºY €HS0ÏÕ)c<±Ë;4óŸ´„Ó7¤*ÒInjŽ#èôjÔ¨‰óœ¼*+†0, <¼+¬%9Gòs§n'D)tíWK¡KÚ¢Û•DGoO³j•)¹êB>æ7®í^ºtœ«¨|øÖŸ±+áK, 9EZ¨«XƒCÎ|"~Ùi^'0UäÏ¢ Ê‘3=.%ùu¡×¶6꡵Z¼ª>³¦nçm€J¬¸YHCk/ï꺅K€ ;÷ºvþÕH…n¯'ºrÆ(°"þûqRûyCjš ŒªšÔ Pò±ï ’žÛ8ï€ȉ;èc(©àÏð£²C]7ˆ×À>™íE˜„=t£¶ÔùV14ìhºÄ©&»¹z¨…V­Â<Úì—&&œcwm¶ÖGë¢g 2%¢]¤Ó·±5>†±ú:}€‰ËWD(­NÙ$;eÿ*êÙ[˜Ç«JîîÕ¾˜¢ô Õ–q|Ýfš+ 5mxã:ºÏ'xà.šÔðè‰1úùN^ÍÈzþý àäGôÁ••x‘’Îmd˜®³†[@]+­Ô¶Ô¨¹‡òáǬŸ4B¤ Êu%uz9~©‰ƒ…] Ä—‚ò¤y1îÂ¥æ,ÆØ N ò¤@?ƒÕ6§D;¤2™H´EiȾ§d^SYù½ðD—ÁŸ0-ñy.NFѼ%‡Æ€¢W”¼ J^48”W|Ø[.‚¬4Ô®èØ© šÐ*d)ÞµálCŒëåÀ¦ÜÊÜq@€*v°J+6Rå¹Ç)V'Ô&_e>$äeGÚÄ“kpü“âjÑä…‡O “ 7*OÚã"¦ï±ò –¢uäT¢ÇH„·bôFb¯qÖ—Dø #pŒN<¯³Ñ×ù‡qÏ,ªË×<ö”Ô&A éFÄá„Z`è¼Ä÷ã›!5‚†e¬¦#Ë[óü6¯ùõš®wà´xWãü®¯²Ü½ að€(õ~²×NŸ¸õ(¥ù‚ŠÀÛê+K§–$sÂÀS¡gmóX03úNaÜ^5mLµÂÒ©Û9Oë4ß'v0®K¢|sB#6ø‚Éfó}•ùèÊX6iÓº!í¨~;©FÆãüY§2‘BRjô ,Åèµ¢RÑ”{Mi€FäõJ¢ñ¥gÒIý¶Ô¼nM«@s¤~¯µ)°¦ÎDè8²V$øýø ®”Œ|÷4kj#néf¤åüg؃áz¯zpF/1ˆB©$øœÈ”ES蔑-¸Æ³ñaFX+±›SÑ;ª´4©rƒ"’ÿ=æëS@‡•§òriù$T0ÜÄ¢E¸Äêú^wVìò¦æ%Jëã›lp@óc\ê8gõc-È&àÿr5jBUóNœÙ’Iz¯ÈåfЪƒrèòÌ€&Ø÷¥Å7(£ìù(UˆaE1–þ§öqˆ2×ÈÉNB¶2D s Ö›Uؽ^ œÀNPÐCßÉwJ·6K€áé´’Yßú=|ÉôFˆþ‡RŠ0@• ªX'ÙÂ:OIóBµñÖµN²;c!Ÿ¨²ùAà÷«eÈz¦±ÚKH³[bûL8ߪŠwä„^D¦þü¨ÊÞ“”1sGž’£Ôò×€*i)‘ËTGQ]Å_ppðÊGÑŠm,嘆þƳÑȦI«Mꆊì¤|AwšÿÈdó…ˆCxºõT×ÜÐhÀ‰3% Kñ°`^h{=j<öª˜ïà"ÓŒ ‰ÈÃÿ¦•É¡j"=GhŽåôŸŽNf©P•¬ûÓ<“˜wò›esl°›búÐɇÔX™§IcÂÄÏ’y„)ÏHHÛm»ÕšyDiH¹*ÔFOèÉw†q}a›ÔÀ”À= ¤¤oïir=âÜŠß;ÐR2OU£,¾[Ø…½ú¼JÒÐs&žq°$¤nÊöd’pLÚ[DŒ+¡yÏX<Ëj¤[‹è Æ÷¡brlå²èßœËe• ”Û¸ç¤ìY­JYÌÝKQ c£Rƒ§ªV»-r¸MC^«6ga'•ÎóU"ÉÛ;¤„šË˜ûè\m÷&æñ°šáÇøœbäõP-®¶Ê@ªÒäOø•=qVïàÁ½6ÒSV”õÌ 6àEž r©éB2D³:¯ç+‰ËùÂ{VŒ;ÙÑ­:1NÔª,“¶ÛQÓQŠÏ€,…Ÿ…›¦Ååÿ§v…Ô"íIxh­Â°‰þ,Ûdäc„cöãZòîþ»„~¥…ÿ‰Ý¤²Þ¿ ÷) ïê³êÀgÖÉ5¤øûKØ}†‰+´á‘‰éKÎÇÜ yøt`9ÖßÚÝÚ^‘¤ïŸÉ÷0ÇŸÈþº»¯5°ß§r»ºÕ›1Õ5h߸‹ §Êé¹aÑŒúr"Ê5&rï#ã‡á¡.‰S‘)Ç8)¨À¦Qq ò¨—#p9b#"w/€°*‚•ÂC( ­1Ü)AáÁ-3žbwˆè‡ |¦¸Ä%-ãø@»Áá*ûÙ¦üAy°<{øø­t k+”ˆ©¡ºž‹ŠD¦›$ /qê4A)Cõ+¸„ˆ·+7 ô(°ßœêÀ‰•5ÀܽÞžÐýRg)3sˆðõùj2šÙƒL q¢òâ§S¼5‡úŽ€!PÒ¶À´™¹,1{ÛØÜ´jû1P˜š¦‡ÑØË "Öˆñ /cÌÁí;¨ØŠØ~ùÁªÓj6ŠÄ#á)c“D;š²k¨”¿%ò<«y(+b¿Ò¨’³Ã8A3ÅùÙ²<’=z%Åz »+bZ«> zΫЮª¡m+æ‘„J¬&6kˆƒ¾‡ëj’‹FS—‹û.¨ â"ð02u0(ì ažÛN°‚cŸáÇA †ª³&®KÇq^¼ñn$IS”Ì,«b¦‚âÀ¡/±›ˆë ¶Sg ª$ãê#Ä JĘ ¡× Ô BúíA$'I·˜¼IƒÃ&»O¥É4«DE Ä>"Ë›{ë¶qNù졲36+X¬‹?ÑG # ‹<£0ø*PÆ3<(û×+ÉfŠ)üˆù‰»p´ìŸÛîÉK<4y¡ù‘’%Êšè–i "\a’¯›yS¿³Q¬¹a ø&s¡ Éïs¬?ÜT1ü”´ J4 ´² |ÈžÔW&º³Ä`8Ì2‰c 'šb'û©ãtJóa˜{ªký&„›'¬iÇó•;ÜË»To@Ѭ¼P¹¬f¡óô+$Rí'‹s|À"áÔî!@{¢œZH DZBAôŠ+bçÅ«š—"ªânj΀8Å‹ˆßÇ›^ÂÑ…Já?ÂaJë§±b0<¿.¦,X“*±@Åò\’i¸a†3´|×¹¬¡ûDê‹£);¹˜Áœ8®¤v±b€ªú¸»d•v¾ŠvJa»´Ò@©»Íl"²iAˆ|y³¼.šÜ:{;›èáŸBwT”0)¾Àré+Ów· p@âà‡ðôA’Ç$òt±á–Àš63+:г¾ 2Æ)ÏSÄô0r H¤6”ðFþ#LýE¢Êˆ!‹I¼'sNŸTe¼âƒFÂp~Œ ° ôͯ0æ3Z 5@—Û-AcHÅm-ÎsÖ‡Ó7£å-R€’;* £ +b‹È†FÀ}ø †Ëj\GDµËxŸ?l„ÂäáÔ¨´‹E\K1»u¬ØçÎ"é¢ê«Tš-™ZecÑ+ZÌ&iaµ±úQé¶Oi•6»š‹të+ñ¸ Ÿ‰2+*¸À q9t4 9…2k-!rJ”±µp¹Ã™¢Òô7²‹õ€Æ"XÚ âå?K•¬Á±&"Œ£âÁèŽaÑ‹pÊÉÍ¢2[Ìò?Dª´Ôµrbj#T,v¬¹/*TÂXì|ºd¤ÑeŒD+² LSÒ“Ó(S <¢ë *D7ÊÜ9ÔØ7ÉÖ3ËsZòª"ZÙ4ê€ÄêïÕú3G•àþ.ß—¡z9ð l¯a¢[ž¢J×¥Š¿ú.)ïN|!«Óã4é}ކ Ìš½|t3œ‹1)©È#2—=¢j˜ëGSü+˳ƒX %üWÑé¡Â\#É4¢zw›YÀØÔÅb¯B8b‰°ŸÐðˆRZÑQÎWrÿC{!ÖAjO˜ð¿Á‹ìåÌ›Ù,u×M 2cäYëGÑíÊÆ{âZ•¥HìEÙKêÏR ââ³íÂ1¼â—ÜS Õ_RRé“É¿{[K®È}”„ï[•ȸyF>[Ó^Q^¾§Ä#‘ëFÊlD£däLYKÑØ†Õ ýÑÑŽ|‘Ñf®µÉÕ‹OÌåòáS)¾‹r­QêŸe‰.N¿6Ìš Øï†®AP°û•á}ÊÜUE´7Û¨­Ñ2  ï£°¸¨Æ? Åxš™ÃNáB3Z¦ ×sF°…=#‰þ[EÖ2Gjâ*TÛ¥ÒRT­P‹UyÂ¥5Íúi¼UÅÄíYT¢Â½ÖÊ»ü\K Ö_eR܈ð±e²¤;­Y¾—úA‰4 Ó*#?0¸ÊK>Ô2( ›1EÈZ-J#aÇ#Ìå¶d!UÓr¶;æ+Ì¥¡&ºAŒ˜ÒèXþΫ®¼'+Ù÷‹:´*Œ€+܉z/•ÝŒ=b=Ý•^¡>d¬¢Q£¨ÜaÛ&¤×ÐöÉRbÛÑ/:à|Â8´›}Ãbˆ\¬Ѧ[ÔH Õ« ùNI›>1 6ãÄAj[Vè@0G™ºžÕMM‡ÝÛà4!GÛpR^6ÃyªWã;”æ/§«´{ú±1Â^⬽%ß%Õãx®5-Ƴ¾ €&¼L'­<–äÉÑj½Ù Ë 5½m•ÎÜkÝVf G}õL‚@?–Ÿb€-,æfÆÖ€ Æ @„Η“8¿„q+Ó¼§¬¿+ctÁãó¤—>*œ‡!)Ã["O#SCÓ×TÝ´«ë69-”¤¨5»hU‰Ì–Ah2”,¾ôš6»îÐôCý¦,ÀªŠ;ÂS±ŠÒþ8a'VȆh;¨ kjâR'š´#LäSޤË5,ïÕ€Øãopƹ/|7¿ÔË\ઙóªÄ— Lt-Ê×°|ÖâN¿¤Q=ùÂáÁÒ½åþT²ÖcŬÀƈ¾”r£ËÂíÊÂb-Úæ Gœ}Í£ÂPþ®1+ÝûˆÌ¾¤[^ôÓ¶+ÊWnäÖ#:eÎJJç&ild4zj†:[ÜeL ßQÕÀ­_9s_"%ÁÞc[EÔhªŠ¥P2´Rã6ž«4`p¿åd¶E‚>OFïj¨æï¨~Õ¾¨'í³cÖ—OTØ®²Å¡Ö ¶8r½iÅpœL{¥Ñño"g³úÖQèù*°ÚÊ'fÚ;‰ŠMVOçT– ”B ûý^Æfh©¤Lð@—Eï\é"ìèÍv\wp`çb ™¥·É¾¨ ââêÁÚqmWÅ£€+C^¢ò‚a+&w]üÚ@þ êŽcÿ%Ö“Íů­dà²i@¦Ó¨;ây 8%  ævb%î‹Ø£N5¯Ja:5”‚‰'T#ŸÂ™y6 j¢öB¨ùgI=+3AÖf*6mˆ«|¸‡ Â.ñ•…Q‰ j.ÙªWv¥øs´88ë;j²k‰@ñ;WØÏQ¸‹1Yu$Ä+7 —b.<ÏR'é-^•íòá¥qâ±>(WmX×-^vRXáÃknÁÞ޵ೇv\dN̾ðó[4¡¼}÷e”y<Ç¢YÖV΢¤æsÕª¥têÒ“áP¿kq=Â’Á?Š|¼Cáþ†RÅþ!¿´}úÛ&Ú:¶,yXªÄÊìFõìhØMuGYT¤Äëñõp‰˜ÿŒÖñ,v•l3âtljۻ“ͯ’IGª.æ ä’š^ô¼Ó§¿·ÈLÆÅ‚? ÏøD¿aÀX„* þaÀf+ ‰Æ@QXôNü’D±YfHü‰Äâ°¨Tz~¦Ñ0$å÷;ŠÍ% )Œfi;}€èÔvµ&ežÃâJ<2+“>ªÓ%D›£ÑÈ3æÅ “Ehò¹]vÄù…I£ÔI¤*&|]@÷z³ê»D†Oé` 5k—Ì08%‚)ˆ˜EdPˆôzMCɨ1ø2±šDèõ¼^++¸Á21©@ е:¬L#;V3pg¾ç-±Ù䕊Ô‰«¦¿p ;Ìz7¡ÅT©)5c—æq1˜]^±ÿŽƒZ$”~9ÍNeÙ˜DNM+ìᯰ/G$áóöp=ÿöþ(î+øÓ4îÃúå1Žcš„"©3Þ¦Œšh‡%náü¿»2,„:M VÓ€N ´ò€‹È„(ïÓ<£$(;B¼¼éCW€m²rÐñYü¼Ä™øêDÌû«2ðëN‰¨€D´¦ñb.“(‰j ®¤Ç¬©ªÂòËR#0”*ˆ‚ò¢Sf-ªzý8ëúµ¶çòÖ®ª 2°¯¡ø ÒD§ûvü@ °ºŸ :i$lŒÊ3ì˲H‚±ª$<×=Ú'È:ÓÁKì²"œ¹A´³^ü Í+³ Õ °å¢õd÷AO‚s2¢«¸¢RˆÊËÔèRN«y-+ÊLÜžõãëÖà ÿBÉ-ús*µâWDhrH’º¼¡Pl6ý Î°.Q2Ž/*Âg"´5d•¢jë°ÿ Mñøä£/Òÿx£,S_S2;d‡8·õT]8Bš+´[/!TˆA‘j¬ã¹Ö,Ô£Öuè‚N`ñ¸ÔÊ3TGN] lº+K´è¢/5æ ‰ Ó} ¢-oR!d;Wb~šGz âÏ”H·§t5še ÿ Sçû/+¶u*á'ˆ •¤i"1˜°Ñ|<¿ÔŽúMÚ˜×(Ôc¼ë›öG:íÖ’/¡Û´1YeÚîJàÀ%+L«sPû¡“*CM«(†s[1÷ÝGöFŸªi%Îж©Ë±aGúù…òuÓYG—¿Éò„)‹èo5W‡1”Ô÷^+iÚiSïPkÖ’gëºq\ÏnbierèuÙ‹&Ó,³-\9 9x0M •”'>èµëIÌí sAV8ªT¸gGå?’ ¢FÈØ•­ÂHúÀ!¯9„xÂ3è›k{oäµnºÆLþÑ´#%`öExZÒq;/åí³«â]]1¼B$„%&¢ø\:iw) 8dP“é~ ¤š6¨RM¡ØVP5 >Òò³I½H °Þ@Ö¶«+ƒc½ñ£wÚÇã”vcõâ×ô¬šqwÄ´…‚ÖÙOñF/0 xÔŒ‰û#nȼ¹7W°Þžxt¯Ò-,4,°›OØïµÒLÈr†YÌAH¼',´Ý:= ®üGøo”dˆ}:¢vˆ™ä‚x 2K‚ˆqdJ“'n>GÈîŒ$|-1H7 ùFu©Aj”à @\y£ñ»µ”ŸÕDE•pýašõ‰2âá\ÄøœSŽM É YKÈ«““à’ìE"s=@#Dõ+á(RDy2Ò Â[‹qBŠ-Ë ÐQ¦òQ&ÅæGÙ.¿#â®KÄ‘hAâTÝ™9ˆ¦^4BÓ*¬bÎWLEm>§á(›‘QÜFgÀã‘SxÉZBÓúÍ¡ËlZiXµ¦05]“[PPt}À)€ýTñO©p¢?6"ÈÐóŠJ œ“%¢Qâ!ŠÊ¡8eÓ "²W‹j¦Åðc'úg¥øH¨ìb1òDýf&ˆ°àæY0D A8•^ßcöžuzEòWVgy¥Š`ûÄ*¡&uWR9Î YeZZ.l|šòºQËZ'§ç¶·–ºËÉ]v^£ÔjÄC,©6˜ÔÙ0$)Z¯+T¬­7PfTCš¡5{uô}+ð¯é¡tS欨â38lc±ì”0Hœði«®=ŽÑÐbª³z8ï}ªÆ¬>ê™÷WÔ X¾Çk‚Ú!”¨Ê´1%šÛs‡a^+ÁézíºØ°j…€2V¡¬¸ó+·¬z©®åb)U*Êjf ST|ªçÞ^bLÄ £G‚ÆF0“•x*¸Ãr×ÃV—0NÏz.oŽŠè.花®ULN¸ R>ãô`ö³ËŒnÆ ÅLh‘N~àƒþéJ‹-,b0ý~GŒ‘JÎvM6– 1EÊ›,¶Eì¢í­>¸Ì²”Àã°µ°ï LX‘ƒxþíã ”O¤Ù)Z§Fd4ír¨QhU.BÉ?Bˆ$Ê@oO¬ü¼YÂ' Îð*Â&m*LŸM¤ê«é&ý ‹°QpŠŸ)êB¢2¹Báòöªc˜ö§ PØõªÞ‰k`Èi/l0ÍNNµÀ H¯ «‰ü‰µ§a@hŒÕR $Èž;+ãôÚ¯vM¨ZoŒ­Ú”°,ÜèüÉPdüèÈúåØž*v‚rPÉ‘ÍRå¯Ú°´oNÈ*Ëpêojä*²ë Þ¤-!Íì~Ä˜ŠŠø¬h Šºœ^ÚÃ!m‡èD’,õ`êd]0ŠeÎÂ$ŽLFQYlJÐ\pÄD8¨¨!ŠdÞ‚mîl&ü‹.zÜ.š0ÎÄQ°F—‰¸G*¨0d—ƒúOâ*Ü  âŒÔ±3« r«š’òDXrà1¨ðíÅq 2 CKT;Q§C™ §l–üÒØpnò}²#£ñ §1ÖìÞ¤)JUèòØÐúoÐÊ[ÄRFðæôg¬³'?³0æÌ–]ª‹.xøIvzpLÔÊÄYË&þÌZ"«dèp†4ð‘)pÞ(ÂÖ1GDOëd"³kÓ€”°JÆ\O²®4òr|Jà?BÔá¤k<øƒ™sƒ6LPöM»$ø¼ÆlkäþdjØMî4Õ8ã^üäþuÊ<0bÄbp•±  °j–  r9)³zÝH©I4q8JTø„pO¯%Êå; {+"lÙ‡¡ ÜC^8§^QrH/u¤€üòÂÝDðgOõ —óª» õÈ`r¬Œ‡oñ)»n—4M¶•®n­v¦f_)Шçbîæ‘Tœâ°+ª¢ $ÔbæuH®h£*Tsß/gA‘K1fôQ'CS\¿ž;/4/ õ'ËÜL¦ 1D<:qe8RËTÍ-Ñ¡D¤Ç˃.&òÐL+¤qÏzÀf2òÿ#²ÚîzVSZ²â;ÓRÛAï›(ÊZq^Û‘¶º"Ö)Í^i[[Ô‹H<ÛŒ"Ëeç]¢XoÃú>%ÞbBr}K%jTGÈxgþ ®ïLé?rµ³·c*³e©õe;qéNßé@ŠÕ‰Ru]{«ü/K_(dDPNR®©D‘UÔ RðkuÑBï[[ÕRöÈÿVðŸÓŒòŽZø>Œ‰ó:òR÷íPçG£)ñîFÈÐÍ×CI¶R0ÖtOä§ÑîA¯kg«ŠÙFÔ˜ÑÆñ0LEð\G„¹dÂ[© ˆ³\¢rÅu÷‚’qñÊGŒ<Ÿ;%m`°^¯¹ekZ“¶ýî²Å¬NÅJ`ޱ»(¦”ŠÏ¢xÄö8wu;‹ä$…”­*öŠ7ª°–'AE.`€MÚóú²uéˆkd¢ŒhÓç +d`.#%œPÑâJé>Äó¢#4Üã ›ŽòA¬Óõ¸qïB˜ÙˆƒïaÓ)‘gUPÆ.§,Ô±3uê¢qz¾(êÎ3ä,µ{5bËSJ2)áblÇUUL‰ÉY­PîØŠž$@eÖø‹[4Kjtv‡KøygU•°•~¬åu£8B°Z9x—ð¤Ç¯päpµ¯jÅX>%©“µƒÊ,C.MòäæNްIn”x•å• K¸‘¤ño^µ«eO°iH€$:êÖÙÛs¦—›9øÄ)'!¹L xFMhêºÍ(¿—¿”®ÒƒBî"¯[\pcA‰ìØ‘2PÁ¢Ä²k¤ÈCR1Wèáûj4B~fÙQ$7abv®¶ H%«Æ –H“<½Òn‚ù!_d|žPºô¢·´§l×=ç^îðE÷U­RóEc™®±'{¨¨RK&G†í†ã*1û4TÁû[LgKK¨‚ñ„öUƚ܀ZPÐk©um:,2îuK DÂüä@O´×f¼Ð2dPÏZ…>p׆L„HDV;¸¤ötWéÐdÍ0¦gA t ›Y»X}.³(™¬¸{TŒÉ² O~Ê«±?¯ÎÒ‰®Â+ —”W“ÇF‹öîÕñÁqÀb»™Bw¶+Y«bêTLÚ404%¨FYŒ7“,à øšq¦¦V@ ^|ïGA6é“`Mòð;‘›ÔE±º‡K•#„ŠíiÃOÁ¸ K©Væ<;K…‡ÄÄLv7üYR„Š›@šPŠ*BRKh_toé¸^£rº©;(ê£Hø@5yàÁñÀ”³V'9š½Ø"÷“—ï°lA¤@’ÆlÁB">ÜÄ¥¹|×=د(Q²•Õ´•»§Ì+ˆQo0Ü‘UBÓ9M~½Ø/1Bëƒð›sé_áþòT-[%_"‰aSøª²"ÇgzA‚Rͱ2Z7[n¶Ãœ£zåØiˆñl€ Ñ3$–¼«¼5–›·Ô®î7uÚ m׬†¦]M)>ÿJ£XšëϼGsj'·7»3® §<¹s"ÂsŒ™Æ—š‹eç*œw™¾v£õHiH¾(…y€±¿µÈ.¦ ß“pŠ*3}uöf¢¤wè÷4±% ÞÇÒ$Vi Û1Iüˆ«'x2‡«Î@“æìäÖÁ)Ç wG‘ƽ§×ñxÍ»—Ú,O EµÎ[[mkþIN7>µ¦m‡!ùM¾Îõö#Ú¬¢W/ÝF¸®5Bû£âƒg œýúK%dT1ZLI›H;ÊßÄÐŒ.œdÝDúˆ¦È#%•×ö,J+ãýzÓ?Iê÷¬Ù\ìÙ±*C>€•Zõîüÿœf#ÛµßY‡ˆg •Jºž)ØK°øû~<±é/Êc"G›}ž÷týfeÕêti«µ¤RåÑÅ4+Ft¶2è­©uq͆#ŽÀL1hº«ÍF¤˜tZ ù†í-qîÓŸ—wü¹}áùõœüéDCÖtr„} @*ÙEu¿Ž¦: ª˜²K\ð³×£õžòiÂ7Áôýéß·Ó_ØÝJB~ÀßÐWü …>áXsøÄâ‘",B!7è AG£Ài41öø•呈Œ¢™æ‘X´F;‡¿¢“@‚€E(HtZ= éÊu& Mç¤Ø—EêÀ ,N-XŽWgÒŠ`Ii¯€j“yôzE[”I€ÔsæñE§/ÛŒƒ ¾AáÕ8”NdzbéÏÈP&x|ŧØ7üS1¹É£ÙlMï¡hßZ\ìFE G±0ìlú>ÖÁhvŽ6ô„=·€ö&-¥}E)X(0‚Ϲ“Xœ:ßáY÷iú‰Æ¶€8•Ú݆'cñ?åOˆDŠÏ@ába½bïAû4EjÊ]5p9òÖ‡.ÚÆÓ«‡û ( PÌ€-bd£ ¬ká*I*ˆ£Ð¼2Kùþ‹!Ë£„ŠAìH á2K¢è­¯­Šh´Ÿ®Ãžå¦ûî‚ÂÀ’†>±ÔÝ> » ®CÇ0à f‡¼ ‡,ò„jĨ^Ÿ¤ Ã--ª§úvu*@­Â6sŸYPÉ!Å΃ßH¤T“1¶‚'tØ HŠ1+£ÕKH›„ø&Sg jÃñ6U` §WËãZðàLÚL*B‘#UJŒNgów@l¾K‘fø[ò†REKÙLÃÄæÊ¬Ë$”Q¹¨¬WˆÔ íÓÀ¬~ÏhžiQIÙ\vƒ›šóácJb/ Æe‡©Ó‚ M¸ £ÄƤ©:ºNé´·Ê÷ ãZººî‰5íŽW ôA1ôµæPj,”!(V9™1«¤ÀñRòvÖÔ¦£QÀ’º·+)ÜËJ!„Ï u=Dý+ ¨?Mzp \RF·o1ýÄå’ þý;ê»3'-³'ÆÔÙE“ )Ô•.ñIØÅHñhXÃ-Õ&KìM@€{ZŸ´oÎIÜ‹á[Ú­9Àé YŸ25ä€ìup*´$HTã±'ö¼ø"gýjBhû‹[ A¯e¶&ÄÖ[XÃôiŠQK³'JðZàÿ1#Î1cÖ±g2ÊIŠ>Ҩ̋k³Vu­ ›z›[` „6hC—Ò`‡->±þcSòáĵ±´ŒüÊqç#Jì†Ó ˆ;`4¤‰Úº’º¨ !;E±tÀ©“ŒH¡t2Pn·<üb#VSŽxÄVB¡tiø”·½Ù49lëб’„ýÍ2ßj1@FVü§WZÒj‰­¡浞Q]|kYý(„P–iEŒð}©ò¡ ›­Z` —–vÆ?"#¥"ƼšÊÇ“Ã9S%­õÈŒo‹ë[!%=W#“w/œ™!2e,b|bƒëíÌÖÈâ:Mp圜"èOq1è1Q 9T2J™€¢¯Ù ƒfᜠn®8¬›DhlÌ•|JˆÒðBvŠp ç€t³ß¬K‚¼Dzó$¬mmä¥å%è)‰œ@OÂ÷]!âYL\æº ºÞ1tsÚLE)_aA<ª’l5”åèjì•*“ÃS´š×¾vd¢ŒP¡`œ9Wå:Jvò>•y2% ìB¹<žaÅ4¥¾G;78xœä‚­Eû/VpDLüw%>FÃø'%«4}#‰ ÒŸX€f]åioœèGu€Ž›Hü&$É‘HHì¤üvirÃØ›@ÚÝuIdÊN˜ÒQ MMËÙÙѳQAÇõTO•J×gh”9]A­nw¨ê:ÔÌ̆D9?çnƒ]½:SsZ™Ó‡ÄþŽõQi&äñIÔüsv4¶¬UúR­»åhGˆò’À¥©°û›S²Q¢@p ô™¥ê‘2$«À?Èô„7ÕR[Ø…>æL ®zPMŽUØüšÐÙ7悚˜êbA™Ã"éDÓl~„ŒxÉ#¢PE‹9åw®á»¬Û.à'…Zé8Fª•ðšò%MÀ«™sÜSvr“4Á(h3ÆSxДùCíøý¯ñ¤;¼É%#¾N¡Øµ¾Õd¾º¨¶ÍaøÝ`¬‡Únƒ¶’›*á £;dn]%æ©D’ñms“ |‘äý¡&!7Aµûj¨–ßÇẗyŸçë³™–DÇú?O4c1,BôŒˆçØ2“ÊuiÙär€¢<ùëóƒÆÅu˜÷ìÂJÞ”$Ú9ìÝÍ–ôzÚvÞÂnw…6ý£FÖzŒí·°ÀHÕËSwj»> r­l£æ¡²èÜ€1Á4»nIXÙ"Â-kKŸ©½§.C¸lLÁÛ¹ÞíGåHç4¾„£*ÑÂ*¢4éU¥¾ñ^øî44¼4 縟|š—«þèD[ÂÞ2õ/ )ø–@ ^¸cìU‘E ŽÙçËiñ}YDɯ¬§…>™”Êáí’ÁZÖsôEæ eœŠXæÒÖ• TO‡dÒD ±t)'mÐWº"Aa–üªL`òËW|Îb© M{·‚Zé‹#ŸŒ/¥¯µ¦Áš,0+«üá±6õ¸‰¿±æÐÝH¤>ܶùäŽ_ã JÆáÓ)‰º¹®ÒÉv<>¥ÇŠôtâ÷$$(>ªXX¹ÙÌ¡4ð0#{H=›§ªê».¤uYÀ•d òÊs™l%+-wÏÙ¡M“2HºW xvfå‡ÏÕð‹ÃB ±O±‘QÒÎ¿Ë %›# ™6SÙëÆ8©1¢a3ð5kO·± ±n” ¹x›œ£ ‡ëëºÐŒyb¶pŠ#ã"4!­«*õ"s‹ ËÚË·¶™á¤ø 5¹\¨"@““ "ç(zжªP 0lBª ;®«uˆ°÷ 8É 9Û”P¦- †ˆ*}¶äˆ{U4«ó¥ã¹(ÉÛƒ©Û¡±ßŸÑ¹JN°jÄ5d4R™˜§X~5Û´y¨9„Œ j—’·ú™14ŸƒUŠ¡’b§€+Øžµ w½³Í´#c#ò*+RTÄyªD#d9sæ';×–ä¿S ‘“Û¦ûV<A&¡}4¹Ù§ 6ãA"ùˆÑBЦ£W2œ/²’TK9¼e4Y&‘L“107á<2”F£ ”¼9QáC΋Á8¿B;`À‰ô*T1ã˜DB†Üq0­ÀÃ#i‹ÃGE‘h ;)ò?E¬CFé¥,YâÍ$k™1ê&ƒÑ"Ië@Z«j—’s~ᤓtMHª‡¨à~‹9žš÷Àk#<ㆈäG¥k¤ n²b ²ƒn é÷0tb1´ ßCº¢Àñ'F¼gµSBjkR¸&´,A•52œ¸p‘©JÃB!ߤëù™)i [«x»4j9t™ñ d*B²Š Ø÷@´•’q„–’©°ê­›;ÉÉKÚ“qý)Ûïˆè !âÀ€*=(ÄŸ+«ª¤iEY–¯:¢ jŒ¤è¶Œ“ä7)Z8ÛÐ ô¨\wój)Í3*¸+»Î°Üª[¼š8\8@æB¥0É辺ˆ8Øáã`£ƒÈúF’Ä6#»Á \Þ-䱇7XŇ¡}D`4ƒÖ³|>J‡¨ù N;y IÄk´‰)䟌¼»ršÚ 1¹ñŸá'C1¹‡ÛŒ³‡¹“0KžÍ9™A’Äü"ÎE”š¿Ž‚Ê1u)ó¾¢%+CÒ.j—ÂÜ0yןŠ#¨Y‹ZÛˆ9—¤SÄô>58~!CA4€Ëc‘Òâº2þŬ £êÌ•̰ñÉÉÕÌ‘þ-ÄxÙ Éü&ñCùÛœ1™ ðº¨ñ  ³t%H‘g¨¶ªN+;\ª«MÃâ“Ã!ç(Áò  ¹ÐKà=µq­Ð¼¹¥[€1ÛÃ"ª$êRÈPÄË!›1(›¨+mŸ#¥ cŠ¡Û­ý>SP»tl9¥Å›™E2“㟉ðµqµ¢u6©óÌ*ðÈ£^3sŠ·²Ô5 @šù š©MIŒE’í± œ£TÑLÉ"+Ó¤m߈<êW4bÀÕƒáJ?NMoÍ(]ÏŸ±Ò—²j1rÈY÷6>c ­Ü2\ĦÀ±Ê™•9”ÇíÅ¥TòGäq’ŵY-°ª`“!”V¨#͸ÉÔÊ«·í$QòÒBúØÔ¢È‰RUÁu Ýg4À“Ö<–µqÔfCRÒ£¼œÌZ”•"‰“à:‘WJ|œé*TJ‚ÂȼF´ÄÏÊ$š£'¸“q†ÞÕPÄ®µn‡æDY% ]5(\¿—U¾06+00”_,Áe±^=ÀòE4ÑÔ‹dàÙðC0V~!Uû­VO-v˜RòÈÝ.¬Á‘¿aÖͽ—R¾bRØ›¡â¿Øèæðê¾olÁ-]‰¢¿Ì¥ÜNq…]tÀ¥’S}Á%©•FÈ¡C唳8Þ$½ %Íž1ćäˆ|¸2=bªDœ£ßò§ö>ÕÎò7Ú9ìJ‰u`€~Ö^ª“ä´»¢tZ+m»»@Z±ÃÐ@¡"‚é ÏI!ŽÀºNôø ˜ºO]£ZÛŠ£œQ‚·[”Âè´az댳æD íÇ}Z¤=³9&=¬ÐÉCü-ƒ¬å+—RyyMµ/ë84ÇF áU¥ƒf£di…Cû¬émçûͯ-•Úξµ¸=?[àòŒ{t?°Ð¤)X‰¤*\®³ÛeÔà=žO¨®Ì'8ØË(ΔêÉ?5]Só ³l¾d²€*yŒy`36€Ê ¹µ;Ž‚Áƒ³;ø%}¶á‚4*C=GîxAš—W²Þ\¼ÊºúSNm]eĨ‚Œ:A63Ê•û¦¤*Ì¥½QþnQ&Þ=NÁ‘ÞF¤Õ²<$Ýú©XR'dG ÍÛN º`«ÎH+žn™./€2ØlÆuD¬ƒw€2˜îÎÝ\üg„.Z*E[ù}R6ë ‘?mV»Ø•mCÏ’¥×辸/õÜ=©ÙtŒ½SŠˆBê&±ðÏ“@=)ßIL¥Úv41 Ta©ÿ×òðµ­6ŒËl«øËa$¡ée¢á&ŸGŠÄ[Ó7%,‹î+¹âV~ÍJ\<$YA3æ+ÖIÔ˜æÂm¤8~Œ~D²ÚZ€ß6š¤M.¥ÉèºT85Q„ò[j×-Ùë­«Àû9þjŒËáÖ•fQñZQŠV(môÊa&7À ÷g„M8Ù?~A "’îù(Šk¡£šiLÄ‹¥Še˜Êö)¬GK x†_~cš£ é8‰C¯eã€ñÝm=Å "8),…i–­(œ´ÑeÀ†ù1‚9‰¦Åòðò²É/Ló‘W„Üš‘Î?FÒI[̹<©ŽiÙõž˜D_ Ï(ñ¡•twTúˆMÙ<8òŒŽê[~x€и=2a~øÜÜ™$!Ì—¥lœð¤®Ö1“ã7¨x!’M?g éÓœÆìåiø= —yÒ²Bˆ2ZµöTgfYàx“a^¡ùU³k 4wC»Ûq¨ÊwU\&r„‰™ÔiQᣃ@ ï…‘ü½ÃU¥–’ .@†6 ß!R,¾O1µ¦š¢hSŽVdœëÕ«þ}sâT Ã:ÎÔk’jÎ䯑OÒ ®y8½t¼¥Øê‚Ümv_Ò­JÔv¬A03~o©/^눢êwI;re…ŸÁw¿BwC6v@I€®üPºLÁ}ÃMðxøëÃÌ=`}86“v6'-䎓ÁDUài\ÈïRÏø€ŸP0$ÿ‚·ô6ÿ}Ä@Q8lUý …€1¸äL}ÇcÑHlf+Êc0ø¬f='Ãã’¸ƒ„Ãß´¸¬zD‡ÆjPº AK~Ðjuº”>Y:ŽFçºûú«)ž¿6°=¶±\fÌ‚£dƒÆm {[æÎ–ÂèoˆMÄ}ŒÇ+™|:ÆIÕˆ¬þŠá o«H=3…å!·ú4§7cEm8jÅrðÿ§ê,³JõÎï±Dö›}¾&7A¿è5šS ‹X,5½mNƒE¼ëé5çý÷‘ ‘Ä㜗öx ´Œåžþ<µ¦±méûÚ¤§¨ÿ{|ouº *—ËCðqîlj¤ò°½®jÛÌû£`T''ò=™ÌtŠ7‹«Ù¼c-<Ô¹>!öê/$ê|Ÿ£fQf@®‹6”úØß‹”ß-Ý0­Ôòü˜@º¼K2£râCÎÍË2·ˆ:± Mª…Èå-6Lèÿ£úÌ­¿(;6ï\è ³kÒÛ‘³Ö5Ú-1›¸î#2MbòÓ,7éS^à®qò=P#uEŸ³l‚„°tl¼ãocS/»œIÿÆ)uÅlÏ!첬ˆÌ6Â"ïulòûps©LÕÈ ”L¿Hˆ›oÚ(m¥¨ôÑ¢½íiÏ\¾rêK—”ÊÚlnÍÐîFy¿2”ù*õÀï#'§üa‘1ý&Ù½Âw‹é3îµz•rÒ_/] éü§PËAoƒùõ–ƒV[.jÀ’­ø rJ@¡7°óÊZ̈¶·FÜM Kfå•£œ·n‰™,==çx —Ô¬Hò>!/Þ &GPCVÊÈWm-¥C’²øJÁ(%'X‚š…Ê•–[{3ʸ¢•r‰Žä2"¥ôÊ“õðúYÒù8ĉ»6 ‘—¢×6§)@öu_Â_!.93²X¸»Pk=ë$zÈÖ(ZL†D/V ¯Øüº@*Ë6‰à}²Xd`ÉËžÁdÄñÇÜœ5 ­z%ÆrîȱÁlÆÁ,žù]-I¬8|RÑ1¬ØÎÔ¡Â|*ÇDökÝrWa-ßVþI%t€÷²’æx!?Žcõ|Ëc^ÊPj3r’eÒÄ×ïãÚqPfaœ¤¸yÈ›ç;ñX¬c,|G±¨=€kOÕ—+Kg!d%i¬•¸¿òÈ\ž‘’0©Ž¡s‹ÐÏ!'–åIì£,-•“©š‹IëÌ;11"bÒe–Ì’!nE7›vêŒÛ[¡àÇ'¥K „DÌ6\ÍJ¥ÒãWÓ*¹º–JÜÝ! Ø¥­˜’OMA}HpãXŸ ‹^œ º“ÊH›ðÿiËìµ·YFã¬X„óm1³ÐÀ™+ÅIª™è= â¡\wQõ,ZXc #ü½Ã ¸Ð"ПhÏ™=VLƒ"(ùTòÒ?(Ò3œñê‡g”>àu")Z}‘Üdši=°3 8Lcfíà‚|«²ò΀Bû@%3tœ =(æ’‘$+°´ÁÈ[<ÉŠ•T‰¯¾?ÀÁýÚü¥@©Hp—òše˵ڑù*¨ªê²¶~ãß 0i8Ï9¥éYèµ |&¡2µçC Ë _ tä¾¢*íZ£CV€X€Å4mÞhœçroÚz¤‘²TŠæ~ÝÁòúŠ~ ^‹X´Ù·F—DYÂ1u±G5D™©ýJ¹>¼Í¸d£‹]¹\)öŸG·DOVLòUŒÕOƒ6a¤ãh ô ˆ™¶(C×ù)“”Îï2éOu¯±)YÌ ËH’–½À`cU %&,æXý·€¢¼Íˆª.7@©ÀKX‰É]g8³³ÕISZÉ$4]å-:i„쉨ÍõO…nPâaÁ;Ì’ÝŒ6–Wy—‘è§ÇŠšaÝ?ÊØN /)8¹\ð²ì+§§Ô€˜äV}W¨?”g6Ù¼³né¯gùç,.Ì¥p‰•ø€',u.Ôoñ7¢e³– ÜLé@|=‚~˜Œ‹3ÛFŠÌ^™Ï¥Ö¡ƒò…KrÀ-ñeÑ2—ë‘ù¦±ÉgŒ¶â|Ó]ðžAMð®¼é$M<´Ù†œúò`ªÂ=uJ¬L»K4K&ÝŠ°kºOI‰rÑ3ºñ*öÜ-«MmÑp `Ø¡}¯‰.?’3#$m-,PÍßS’G‹ÞûKK‚å7+?~$Ýiµ£÷”×P »È’øÊ/ÓÖ ¦¨êbäÕc…A!.*$,jÀLO -fLdÄÝÄø^C,ËBIƲP,,ŽaôÉÈ ªäŦðå–×êòÈKÒÈLSb¡LМæ¶5 ã¢Ú3dP†Öꤾ´A vPKÈùéR"kàÚÉH…ð÷.€ñ‰ŠÓ^þm¦cŠLK,0kNÐ!ô^Iì-$¥í”pƒÞ•éÞP)“Ç` pÌ3Ų“J@³ H½®* æBÊÅçn&>ùLV—DÔ¿èÊHZkÇ8*eðd -*c(:÷ÏµÍØïÀ)c JÉðÅ‚xx—fJ‰ˆ£œ¯wªLæÎÈÍdv ªÈåªV gl£ÁùeæÒïÊ`…ÄYã&P$ʬåÉð± qÅìÐI' kÂᦱ ª¨6±.4¹ÎDÔlý$Þ÷c/™Ä ¹ñT#Î)¢„cPrå[,–j # ¯h§¯N¹ÑìwO LèÚÅsæSi ú|LPÂh-nmî8ž‚–¬|^LýãP³g^ÔMHGʼ©€°æpÖƒ’Ûi’e-·aô/q~6‚ž°ÅÀt.–ü¥ÊãÃ\6N¾¦ì8þ$bR~„&ín¥ä¬î ÆKf‚ !ðl jr=Ð^¹‰aæ¾abܘÊnÞúÎáûcª-f·+‘ ê¨PB½+#+¬Û!®ò-d-¥r؉`¦Êð‚…é!æðëë^Æ=LP¹Xô+`vä­¢œi“‹¾½²¨µ…ªåi‚袹®,ã]ætèB7ÌÁ<ø¦RädbBþj¢"QTî%*œ«bvï8¯Ã ­Í ä¾ð f/°Ó-ÈšMKÞ ¿à– ð«i`C2."°“ /q6’lmD´U…À\°J!å'Lh€CŠ~ÍtñnW'}&IÊ¿ ¢6ˆœrÍÒH½Ä2NžÍ&ïÉŒˆ&" jÎËqLDHõ‡ÝqÍ.²L’º¹¬j_6$ÛLôKTÝ£(b*/kÀ}q‘=ì^“AÐä°R qÊÈŒððâ*ZfÖŽPpPHæ0¤93¸âÁ0€?Èzç©Ð¤Ä‹>2ÍÙ².Ð ´Ç¦F®.{ª:´'o&£MÏ ®´ñ±ØGëF¨b83c-hNêK}$Å5E<ý¥Îãcƒb±"Ò±gÂbˆ6|Îr!oʶìƱ[°Ô™)^ªððÃР¸ÂOv•¶‰†n¾'ö—ì@âÊnHO[.IJf!÷J…1K­«þ®k/ÉÊòr²PQuO*بc¼$ £E¦¬Ò´P« èÀø3 ­ùT²ð##÷I ÂYbž÷dC+½É[/“çKzfœðíàˈ×"DÞeÆ™DRú"m’%5%2-o+ð$"=dÞä¤mÀ0dIUg‘f Ë+,F%BâÚÓä¿‚60b2þÏ®)ˆµiñ“‘ò*ÀñT=çBƒn£µ½VëYéð¡I’ÏvôkG¢ƒs‚@Y$”}SbžÂOE„2PpüsÆ¡A¯s|-·Î°VàÕS"~K‘ÿTËÅzŒld°Ê ÷b¶ó`|Ôˆ,;‚9hxo«•"†merGÈ!8ö_HÝ7€Þ ¢…ow~˜E{O©·KòÖ¨Ž —StÒ¶SG¦#´'F4*Þ}†ÝU)yj9N–2Éê.%4]‚ kªhç„䂲oòÊI~˜’±Gm>UrÝÄ­ .iˆIS”¥öP-hDö+-hÎ×Y5ääÔ[%ÁpƉ@ïº.6-IH üï}G•{*Zcµ5¥£_e’Ü’Ë'ZDÈñj’"tØM`θ¬—owrñƒ®ÇwU¾Ìkµ•×q¾*À¶O£ Ô,¦öneiñT˜‹× g²" ”- P+¢ËË0,çõÄš7u ºŒcVÌhè¸l0šƒ÷iDb"͇˜y‰Ë/;Ä2}”/÷Årkjðq'‹IJáTò Ì8Ü’Ämèm{³ä全mƒ“/â-³äVi: ±™}Ëðµv¶¬ã,±õ*ì%ÊÜID‚™'pËN vUª—†¶ènÚ¿â*55/÷89”ŠÖôR­åyò&êÛ8‚²Íþ-bþFˆÆUe[ú7O ¯©’÷©váÍLëN¡XöÆÉòs¸Òð&¼/tTFÏq¼n§xo¨!ŸS7CöœKK± õKm#¨e5„úXŒ¹Ëk8ˆøÖv|ËÙpÂU÷ë %V Ë\0×–õl‡—/èÐZ þŧIWÖÆŒú§£Ñu)‰:¨+’ªãh0ÜCÄÃ$ÑMºà÷—ÜðÏŽY;ø¶¹†*¹¬*ÂÜ×ïç@¼#ƒ‚ëñMb~h—<ÿ¹s:·U³•Pu@öëˆ2—§¯dsLtq|þ+Ì,”Õ6KHVˆ¢Ö5bã+eÑ…†¿0£·!ò¦p¸¬X×Eʬ#l±jøg@íw¥£+g;éÛY/vÍ‘X ·8¦m-Kf\¯íšÏí’€¶÷"—F]`Ï ·qÃBI'+u y$‘99ω*«‡Í%IÛ[Îr³ˆã ¤Ï%Z†eΘàkz¬ì¸Ú›;jÿÕ1 hê‡Â‰™R\²ç_”­ÃЯ.‡Ìلϼ„ÔäçÆV=&¨Jððªü /°J/øMºmÁ•ª 1ë0©Ȥµè" ”:)ò§¸Ù¿i£~›* šj„Ám² Ë2Šã'ì-&ŒÚ®Ï€éz|%k 6Ž*ËÅÂHâÉ©\N2L 2¤Çè#Ž&­¾bˆ°¶‡âàœ?Ф8H ’8þ`ðÔ9ˆ„<Ųk|ÅÌPz<â É3t¦É2`¤¯ ©-¨ù%€hS2Ž=Éò“°+ã8¶ò¤ÐÍ" :7Lz‚% ”BÏ`¨ôâ’±ªñrð¨SIô…´°ÑþàÌà j~¤ÈbP¿-ڮ៬<á20M ˜ªŒŠ"¼=)ŒŸNI¤¬ÛŸ@ªBgý–ãØ–ZØ  Ç,$0ÚÀ ‹%u+.®ÔÃQ¨òO QH «*õ‹†úË J€yø¨B7UR‘ÏÀð“HW²~õŸô1cˆc9Ì,CEªìÒ&ÑÆ@š>À£bOjJYJø=dGê”EÕšL•ËÔ=¡Ö%®´ch#LÈ×D¡Ž%táZ"²@Ò‰s®©zñ¡UʪGhUg‡ÎŠ¥›¦«‹åþ•2Qkz•àq»•ƒ[˜F’¾@’Íß;5Õ¦œ^îzU•\ÌI÷ž} ~’Ér¸WaeÄ© ;F”s¨U)§#tÒµ;ñä¼µ¶ÑòýiN!òÈžÚb‡8(¸Ç$WJ™DM(ìBó.AÚ –mÏñ ceÜ‹{¯Â±Ô p1MM02˜µæóÓãÎ:0y’-˜?Ü! ;11·wøXJ¢°g.©É1ÃG ‡Û/Mêù»˜·øudM2‘¢«¢LXUWp6 ½’" YRkÝÐ&M×»Ã6±=u€3¶dŸûc‘pi íà9,$Àî“H.æ×1 u‹$‡½²Û& lx‰MÝQå %#{ ™?˜§?”,&„|9‚p… ¹ ,&m˜²FÂGÙæaŒüJ6€&x)»œöBQŒWLHø”,ù(Dæ¹DvïÂS{',¡v1 D.fþ¾ j$}ÌaÑ(‘úéÔ<éä(²Ä\À â‰Ñ!Í6äúJ£’ÇmÏÝ·¼èœÿ§}ë-JN6û1@ ŒIجÀlCÐQƒ†òTÕÝë·vÄr"—:¥¨ãu{P;”có:¤¯õ¥Bv’ˆ»pLGDDiÔ”Sš%¬´‹Ñ¶#ÇüV  1èpGaa)2]!Ð ÔVÄjm#ùWB€ ñœÌòC»—È?äë'%M‰€ià^]s¤™ÀÚhÿ¡ûtW”äC(rå‘ P«Á133.Û"™‹x…PE°š Ä}v¤'(ÜËÞqÎÈÄ{@G ½5` Üþ-yå úŒƒñ!,ºäé]—šŽ¬Ÿ2’aä\éUÄÁ€$óØ„Wº·žÌR©&‡T‰ «Ž!*5¶f`gM$‚‡€IŽ?!x ~TDãœÐY (<p¼ApJ+˜ ·%e­Ç³Ù0˜ÄbS唉•ç~kzºJDæjœé aK2‡·TAþ:#$Ž×§–Ø`0ßä>Š ì¼˶o 땤-%–½ ª×V÷œšõ'‡ë‚)­äš‚ | ± $ÕbnÅåJ<ðgM"¶[”e DTŠÉÜ—[«Ob3LDšñ2G€ˆž>¢ˆšÿäJþÆY# SFÚTþâÉ¥)8Qá+èø¬å2­Mœèæ[nÝd=@B8™óJ‡Crá\% ´º¸9°Œ;ݾnv›; xÚùfpÑlg¨xõó»ï~ †`[Ÿqð¬ü¹¯Õ&Reõ±c#“>´ì}¢ +LHô õ;œÉ'+òˆ²à.–"$JÚ½þQñ…j«ãøLr@½"º*¬ìm(Ä %}ÎóC%gòu þv`YÜÐåÍ©rR»ÏLp*zcTWAüÖÑ?t§és´®vòG!þ°ŠgšªÄó(‡å­Üç±ëWéÜ{æ šDMbD¡^Y¢7¨æelœUÙ7MZ)ŠEÕªˆ¶Ì¼ÁÌp|Ç+¬õ»7€è%g®—9aKç+”˜ÓY?aMÂŽIÉSYÛ:Üäeöò†Îß*³|­kŠÙž2V_,ôø7ȇM8Ÿ  ™§¼ÌC3ºeRþì9Ãì”À«C°¡Á¼ ‘ ²G1ÞÇøÐìRÁ À´ÃG„S&ûY2Ü­6:¬Cùeγ`è¿/à ¤Y ¡«²’ŠŠ ã‘!mQŠÊ ôDÑ<°Ð|$7B¨Ê<=  2Àî "É»š¤LëD¹<º\>SêOË9^½D,Š.„ H¾/]¾°ÞÐÔ=SÄ»$,„˜…BHÅÝD1Š›F˜š>»G!Ô™ñV*áb)ª>Mdº¨}FpœA¥ ä1£Z3kÕ¼RЦ¢ÕVÕS¡iFtGÖ¹¢Ø‹§È•Ê3}Ž’¾Äˆ r¥0:*Á@À™3fC„ hñ²ñ!AS+¡DTxų•Hx}!Iè*" Dùÿ&ä5{u½ˆ»ØD¬Öd)¹Ús[΢Ñ kn¢ÿAÔç¬>CÀü,V©µ ™ÔÑ4•ÓŸœ‘Ñ< õÎòÆÔÙà¾7¹üH|»$YéÉ(µ§$ÿÑÚØzZêÁ-l *IÅùCØ£G£jX««>E(–õ=&sÒB˜ [ÿ·{%Š„%k Ä þ®»ž2úëzfU8‘£6*·1=y¾*’íeÔIì•\ˆ®"*Ød4õ~ ]ãÅ.q\þXs¹‰D†.2›@é!A>Þª{¹ˆ:H³âK5p©›A(• 呇ú‰S–¸êÙ*IÑÜ«í2ü&¾QL££=®»Ð8$NªÐDoЛlšß×nA õÓKÀ#2Ø•q’µ ’šZ´Ô² ÁÁ«Y¾âþ[Šx9%âÚ‰¥\Ù4žéŽ[˜¦¾`Š ¡ÄÏÍLàê0}ÂÜ'­Š“—@í²ó=WpµŒ¸í•Õð1TF¸&(0”1sI³²ŠªÙ±ñü—ºµÉ% Ж‹/™ãˆ°löÀ¹ü1»ßÓ¡ ü0jƒP=U%˜ÅS;+ ý2ëc™™FQ«á~–m3ªô¥PÙÏ@#¯²(bt¦ ßNÙÄ[‰R­YݬK¸«Æ 4ÔçW´C *ÓÅQ Ù´}Yè¨ZèzDjRRåT½:]„[²'Þ%$ÛÃHѬõ¡¨,ebÕ‰Jb¹Õ@°þC|¾È¬ äo\ÅqÛÀ«Œ=¢äI!މ Zºá³ Ü »%"œÀ„¹Ñ1•¹É¶Ür¡M€ úëãDA›LEØS ä,JÈÌUF¸}ñ"V 4•Ë*CŸ•fL,´6¢õžÕºàØŠ‹Äº[Á(Y鈸¼ x8“ »ó®PCòØ>…Y@Œ;扲aaºÀ3Í ñFcàÂ]Šž…}Ãç2£¥5Ÿ´5üÕL-‰Ü¸²a-›(Ž íˆa ¿8¿â}œM]Æ•nèY´ ¡ÛªlÖÁ[£ô2ôÆOÛwßÝöVY.“þÍ'3ÔÞ‚ ˜Ä˜]¡ubv[±õ1AéêОF@UX Ù9è‡ÜÛð+ô•?#IàýŽéò¨HžÔê鱽YbL£¥Ü*ç6¢W‡Þ!]b[À$F§‚¤áHÕB¿eaa$*º×–²½¶âX‰ÞûêBĬ#¢,ZÑØiüç‚ ŸËâC÷Y‚ Û´[³H_CÅß ­ÞaòÊž³Ž‹ÅR·Ì~ˆˆò¤¸ŽP2±óÀËÖ@Ç-\ex\*Flhª²ˆ5ëÙ«âS¨¬æ*£ ™À&¬µ/%ÆŠHjnX¤•™Áí»ÆO%a6x|´B–€+/N@Œt´0r»Ö¼94Àe´‘žižj /ÛѬèªE’žƒdb>I>- N§‹“¢û=‰±D e[,¼߬>¢L÷šQb]MG&¤v½¾!|ïÂxR`‰5Þ×™ÜÚ=õí ŒñæÒíBg.;ë/4Í´mkZ)â›§«2½jb$:†?ºdpø³±÷ tì‰6\ÂbSà¼Y V"®pÌ1™©æ–«å>ób"‰=sC0†b ç*Å!'#Ù‡:|å©(›í„°Sh‹‹ f¯Z´®v¤bÓ¢^M33Átc>ÉBµ‘uóÐÅ=~X•‹'5¶ä£PÜ®¼H‘ö&ð g]q]é[w4¡æ#íY6õLðöiGͯM›æÎp°ËЂ,ˆšíÞm‰‹ˆIY¼T8%sC²MwáN.ßL²›ŽV B¼?¯\Û¯P‹éò4Ákò³¥Dú)¥°¼.Ûˆô3ÅøÔ1ØS áÁ¹ý;¶0J|À½næ2b@{"¿‘Wø¯ usháiV[ØÅ¤°9óòéªÎtÁGçõ³Ä£/ÁD˜f(Ài¤ïnZ>Çi^?yn™+Br1M𲑠_˜¼gšf•Ù“Hwµ ƒ/Âü¬QYÅûCtñ/´=Õ͘²ôùܨˆŒ½‚«[ª+éªÌʱeRæšÅ‘½Œ!y ‰6¥Ç5e>M{ú S㜓!ðŽá‹[‹•ÙüçŸVu )r¥6ûþÙÆ?L.ÕáÃq¬Ý%´ÔcDÆ­s"Å"í»Ý9€$#š 8»P…Ò€4XßFìœ|E·,c²£yçQg£òŸäéh˜JÁj¡ðÑšÙû鳺ÔòÁʺ‘örµMˆ›9™†Çó)«ÐF¬(шQ4 v‹$H‘"Cñ‘“QÔ)û}·¼cÖˆ‚àÐ@ î†A€oøƒú%‰E_À(Ä:ˆ?á¸ëòE Ec'ì¦7Éäñج‰ù.ŒB#¯©Àu2§Ó‡Ôž?¡€"°ˆsâ•ß4ú-I$‡Sß2y4be¦Æ QÙKöDbQÐ-¦IŽËâÜn‡B(¶dBx‰O€Õˆ•¤ a°Ã°T­‹‡L¡Oºm•ÿYFî)$ÊÜÿ°Õ טôO+³Ûå1Ûµ’B‚E¢Ry%¢ÓV°ÉðS §<`£s*.jk©¯Q¢W¼#öãD‚g¡ñØ…ËSåÜh½ K©_½jºÝëãû·ÑpÀ=.mèöv#{èRVÖs{ .?þàA`Î*)®C”ø¢M!ü¦¨rÀ• Oè’; ’üÜÉj2Ï¢J°¿Hà' \0ÍÒ÷¶jzüº!È3’Â$ì¸Á=l›\Š8ï(’ñûý£ªQðHÐ"6’,2$‚ŒI(cA.­K°°N+%µÏºÅè2Hý¢±‹ ƒ/ÒÌBN[ÆÁ,/kªæB(d‰Ä®2.ŒEÀ¤ Ï«F1íúE?i:d°ÐÎrežð‚I3ÎSz “Ë[k'5hÃÆ±€3ÛëÎHë2‘Ià#P‚JËJB‘¡Ž­Z™Óˆ„”Ó½sªÁC EDŽ,Çõj±"K ýDTÓ’­R*`"eÊ- „C଒FëòdÐU/´3C£ ,”¸¬£7ܨ%:‰T§ã:†A§ëØü/Ò%vÇËàxP5ñþêÈOKȼ-‹L~¶õûÁ*Ö”*HeöìV3 fÐÓí)ÿA *ü«)´t¦»Kläï[lÛÊ#y ~#lŠ-GnÌ gÇŽr6 (©&<&6=øì!Ø^ÎpS`í" i먩¶ÝCt`ŒM0UùŒÓ >±»%^½ÚÃǧbÙâžêÞì“«çH$Ü”¤êÖ¢Jܺö/Ø!ÿGWslÛ þè5/: Áo–J ‡X*´í<€Q»v‘n¸S¸Ÿ´´aÀØÇç»Í<ÕæÝÈ…²‰HÀR;ªñÁý&-0b!º'HD×~dóÒ&ÿ¤]¡þýÙ°Ô/¥®yòýâ4ă#¬o~ƒîÇõVº©c¸áà%ïw䛺EÒæšÇÈå³nÆÁ²=Â]O!šSCmÿœª©üþB„Jè4ˆ’Zn ~$B*þÖñ.HŽpºDÒÊÓùh€•f$ã`j./a~(f’N*ÓV TŒö)™k!ƒíS¨5F¯ß9ugUG!R 6!¤(PD)2€5ŠÅ^»½m)€ªs•SKЇú—$ºÞ©@wp‘ìÁ‡¾°„<3 l#žô ÕZp䊯gˆ®Ë *`&Ø´¨—âé•A1êîžbÚy–!>Ñݽ§B—Û¶ç` ¶çü=Kƒü‡wÖÍ_|V_G™³$„å8þr¬¹¬ÀSǰ “ÄU9ÑúI€1çáp Y—h’Iâ9Ág¼Z»å•hF¹3¼}]i 2Œè8YRXYqRŒYå§…=,U<•|S%ò8x>¿Sdµˆ/e A‰¤ÒÛ3mjËÅ÷älôÕ<œ"ªì‡IÅ$ÀbT#e¤ôŸ?{©Mmåm©äb`‹òK)F bË€ŸcdðÅX™7È0‰±vS0X¿#x”ÄÈe›êÆ3 …–hœ:µz£Rj‹ ]~ ´¾½-;Ï’cͨÙ)cPý‰N*,J“‹,RÙM¦®„Ô¯µªéسì1½ŠÀ‰¦€J!R¶ixz&<±X3Œ½³êu[Ã(²Å,é*ÙdËGV$:€$¶E]Ì©ŒÒœIVÆmulÊ8Å€’HÔG«S„YOˆbOªZÔ)ï'¾ÈDC õ„lþL0†àg_+n¬ɶ*;’! í>”ðd‰’»*ÕæÈThÚž$­{l„“¤G³É&ˆA®’,µˆ"ù;ÅÂhJí·ÉÊS‘ýG °äŒ”W•SÝo{'9Ø2þï(j±wœƒ?3@}Pƒ_¥ìÖV­ PÊ›-c„øÇ«ÔøÚ|=Þ²0·-Ÿ,ßbûKrå1T‰tBHSE„û!éŽÊmS:Îᙸrø¦b€¶‘L äóþ§uüö,âNcÒmÄÉ®ä¢Ù ØCnËB„úÈ>+E3$¶—5~GFäMŸ@˜®¼•g€d¤ú­&gÛØþ•c¥P$´Â\º\mV)7 Žã±ém¤UŠé¼ÁH ðÀ ‡Ø×Ýc¾e-,¼í#AÄAû^nÑ´'zÜb€4 @X  „?¡O¨`Ä^Ñ0TUù†>q·Üuÿ„HdPð$–.ü~Ê@R¹(þ‘B!†Vƒäóp4õó?—Í¥pù¼†ƒœÈaò—ìæ—Ó%ñ÷ü>©1Mç5JdÞ»+“Ö$ {%FS–ÙôÊdœo¯€©’ØÌ>9¦U+Ò™lÞO-‡Ö-’˜|ô T“Ñë6½R“ªKä’[¶V§TX³S–Vµ9ƒU#¯¹|æï—èä2xˆ&ÿ%ŒÜòêľ‹Ý!’x´„µS,ô®ÌýÛØ²·k " ¿Üp0]ÿ-§ÞcõlÌŠ¹|’Ûq±üø¸ÿ—í¦ô8u>3?|Ãéõ?®W˜îý8‹"…?úB½%jS+*»q8Kñ£î“ö¾¸ÈT“¤ì2–”°Î²ü‹´à ©‘ Nœµà#Fª)ézZѧ)zžø90PPCG I:˜Ã9-J:媑 ´´3Fž'ª2ÁŸ®ùúÃ)ò*)E-  ‡¼¼–¥²;à¦>i‹†-Mëz¼Gä;;±´m?¯;Îã¦îÂÑ#±òRœ¥±„Npl~ž¥ëªû'2ŒÆ(Sú­£óþƒ¹Àž›¿çóFåÅ/<¬»PP[–º¨RÞO‡ÜÒÔBÔ2SÔtQ!¡Ô "íZ/FTl蜴q-¦/ë¡N· "Á¥õx©='ó ¥‰-F¦IÇòˆÆ‰{ b#°ùø§¹ Jƒ#)»–ì¥*Ä’ºÈ{¬ª"g²ŸUÏÇêCUÉodIüa®UÏ»¶Ê®1^¢ R3uÄHBO^wjV¼Vhý¤™¦°kû9?,åb4ÏÛ.¬B.ÞÄîzL‹ÅÏ À[¹=ž¦ÓNå©jrŒÄo‚ŸS³I>–‡KI{àj—ë–‡Ì÷rÃ*”…+¼‰^<¹^(F´Ý,˜ £÷«÷H¦6Àª¿q¹³Yæç#0ˆs[&5¦R‘Øô$¹*Ćєn3í¹\Bª> :ÕŒ[„œÈ(UÒè&‡ÂÕ[ÕË'3#¿·3zë5¯…)º.É2–ë¨dßk'´þü…W‡çW•ºc­mòý4æÃ¸; ¹62íât+UÑœ!\¼žÁöõzê#´´èègiÈŸÌvƒS²¯Ð¦^n:ÕéxKb±§ñ>jZãîû×òwŽéý+ œó¿ÕOÛôAd…xÕ줚*%gÀÁUòþÖ©7^æä’¶tް—MA©}“—nz€©B£ùþ¾qþ¾[9!G†n¼çÜ?Ø3êqð :vBÁü)omÍ=áø‚C¨!Ìlª´l5b†#)”@¦ GaqL#`,¦;§þ‚Ê[#ñ0ª´ÈAÁãv¯ô*#jñ-_’·®?’HYѬý Þ!È\¬Å2qÍ­Dm8‚%úµãQ-KÃÞ3)sÌÜÙ© 4p5×®—”­ ÚQyfõ">… óÏ;È3jtëÔÖ¦R„TcÁõ¼ÔFŒˆ$·NB;HØ~ïádI„”°„©kõŒ.q='^Á”º]NI¹½(ÈZ£Jç ¤è–rU%rI>aô¸5DÏÔd3p,ÍJxþbÞdëŽMÖv<ù?‰‰7E²íjéZÃá ÏÎ¥'&Gå¢ô!MqòbN|$„Ú¬´èÃø\‹Èó?A¾~ϨÐÌÕ„Á¬U…T7 €›%n†f8éÆIe“ž"é@ª4höŽ!#€7Ä•_Dy I{¡V¯4›–¦Ï4•k0¨O(Á'zœ s–WGTv”Ãt y[:;$¦*pV2C&rI¡‡¡í–È\Æ" žµ§ÕgpaçA+­k4F©NÓòéuëuüFDFMécA¥N><•À™á4"аþŽ·“ÎFR¡“ræd¼Ú— ,6ŒCýÐÁ¢ äÉ!ŠD2~˜gë ijw!GÀ—Ó`O’{}ö„“zĘ+²ÂD2à¬Z»/’™=lgö2U¤2OK‹–,“I3Ï7ÿ&e9Š¢ˆ#Àۈ숹†’Iz*Zaý$تŠ1P´«u[òLÄæ¡8#’Û$¿h&6¨4<Þl;yTqøWÉ>ô¥;½mR~~Æ~¹ìa…Ru¦ ßX(92éçDÎf*bqpï=ÍÚ+øJgít­n…aIû|GMlm7¬È”Ii?)X$:]*à‚?x‰*g #í:GDÜîHéLZEÅ-d:#&==¸“ýÐÃTy‹Í#¼kà0Y'1+µHòÙâÕITd 7Cè—±Y'ËS¡)éž"ÏBDIØ­I;³<Žª¼#L‡â6ˆ7šáÖÙÜàOÄAgªäÙ¿õ„ýU+þ\ƒíÎènÛ˜õ5¶&Ï\›Gì.Ǭíyh» .O§îîø’µ¨ó¨¤“§Y“;-ÓÊÅëj!£íŸ;c  žÕÒ[Æ8êH¼7-X¹ÁÄTGFÖÑÈh†—³ÄXÅÙªñîP¹šøÜ9`vNDÛ®ŸðPr†óEçëlOÜ5c‰&/;:ÍH¡¹ý×øÖ°i>{¦û×óÙpNIÉ Š¡vJ<HÌøÑÌ»O}Ož~‘•DÅñ6½†[+”¨8  ¤)“{ iãÍ®ØÅó3}ÄçìÑ$¶ rÕ$ë(Ø·Áþؼq’Å3gqQNÖý ÏÈz«§­fËj )šÑâRT|?WÀlSŒÖ†ˆfÕ å¼ä»JYB˜žN>Êy-º@—É8¶é„{µú—0íß©jÞ±¨ÖêüVO´¼6JC2È÷*HCc¥¶þijù²CÖ–‚Õ‡Á˜pÒ¡–€®›®Edqbã‹Í˜Ï­YÙ×)ð}¡µQ(ò~òÅq‚:Æ?^‰nÜ. —ij3€^Ï 8ﺟÏÃ8ÿ€Ðz±ë•Œ®î6P>ðm‹^tÒ?ü*·o¡4{Cøè5"­Èe ‰Ï¢`|’©Þ“îÇ9mÃ']œa¶«|Ú€ä¯Ø©¿HîœíkjÛ›ŠW˜ÊN7«ð6"R龜÷Ì0<é¤á BOhûÃ∌~'¢œ é+”*ÖÃé>˜ÂZ¢!LºŒ†ÑgþÆŠ;¢âlïš”C®Þì”,ˆ¼:çà#/뀨tœ…„4c 0ËJ…ht…  U¨dåÉB*ƒ ² jšmZö©ê\É8h$¤øO [ª¢? ¦áKò©Œöðb‡ú×¥âF†p¤ê2Ϙ} „Þ' }ŒD`„Ž'"ÔÈh6±ª©'ª@ZbR’°Ä C@¨ Ú…ÏÆÒ†¾Fn &zCZ@+0'¯\Jù j*¥–ú¯àûæ>¡ÏˆG’%÷°2‘*;ªŠ,nj"…P·ï t&*HåVÊ¢#'¬£å¬áô0ÅV>„'®rïaøâʶy¬hj€§®Ôø†àE- A¨tDÍŽ7¨òõ"ìâC–•®fËb°ò*ÍÚá‰`ú¾˜Z"ÈóNÂȱ:×j)‹Ì˜æö‚B½K Xž*ìO,‚#¢ÐÞòãÉâÐ*àÔ çà ¤ª[pÂ]0±8¥ª ÎÊNâDF³$eZQƒX".âe¶0o$Xl¶Ÿ¯d[Í@œ²B¾d•Êø¤ñÄçJB1LN¥„šÍŽÃoMçü_âÞLä ›‰!'¤t&×-Y(+>§b\ð »JB¼Ïø¤Rœ¢Qp"¢2ŠbÃî) pLÕ…;!Á ®+îbžL+'þlãzä§üQD˪!¦åéx=lZ`Jz!í«2YÃì°S¢~Ÿð¶&.Œœ°ÂSªZ«a%£–ÍiHÎÉ>A ÌÕåºÎ·,F®Œ>e¼$I™DÕç‘ð„ð,…Ft# …ˬS«Ìt‹Ì^nsQB)f#«\y¬>ã³t$­9!"N4gFY#ö·£íˆ¨“+p!Ò8ps¢Ü1¯zÍë8žâ©ÃŽ7³1RLDU5°ÐÑáŠù%©29j4ZÕ’Ôñ&šª } ÔÞêì^nv¼—gêlbcjZ¤Ì®rÔjQ3¨:ãóXç睊Œ¹à M¤f'ïz»ÆV¾ôÈhïŠÖGl4eWà ]&`±h¥¥òmJ)"t(|¹4>ùÇ^¨\ÌR¦Òú§´`°f-l14t'!ö5¤SÂÚ²Ú#âŸH"±DK~uì*qo0µïsAG‰.p¥E ÞnÌl`P_-H”zmLÅg7Žj¢JJ‹g¤PñÐ%dθŒ×0§4öhk#d’†´‘KbÞGEÊ>ÄF×r ›Áõ§{"É2… "Hêt@.Ó ¡öS¢3“ÔÞòˆ19/ý(i‹"K$zC '±ÞötÙ#N„_Âð²õ%¤ô±Œ#¦+´°)â_0‘ê|±‡·èuSDn— g‰JUk%°‰F«ECìw¤lÃFóG³’ž &­iþQ"OL0> ,’R#+°‰¢Þ>Ô%´np¨H³ %´xæÇL’5=4/MJáþFŠõƃâ:†ç0g‘ôúÙøD'^M±½?È’ÃJ+pyj6Þ“ÀLjÄ!þŽäB`Í6&ƒ’¢”lìgk¾—j¤åÒR±kC%N‘tª(´Œ3h®‹Í s 2‚JÙ’°j-WŽ]&"°CLŒ¼ÆÎ1Rÿ+ ?$a²G8U± Ó†á0,À>Õâ!‡^çfHRöe…¬±®ZL þ=kÕdÉß(ÂD¬pËÒœ‰&_‘³` t.¨Èf †ìœÉ÷4ºÐXm#Û<´Ô  ,2R€¯5”#>‡-ã*nPÃŒygŽÊ3äy­o•çü¿³Bô½ÔI rRx„l<£úŠËÆéÿ5çz•pXùÒÔ”1Úâ‹Õ²‹LÔç(M¶¡L¢‹xi4Óå(ˆq¾?­4ë¶;´Aøñ´éd‚ ±bâڢ⥪JÖ‡bÐ,3§¢QŽOmY"-yqöI`¿ B¢&òΊgPa'lí`ÈálP”ä¶ñ šL8XF`¾¨ôSKÞé‹%­#T°å.)[¬ë/gƒÃN­50Ÿ³&ž¤õjZ÷Çw XÐfó*ôÑzCgÔÏŽÑ,íXçpÀPt•|iþ[®Î)ðŸQ§~7bŠ_®stÖhrSMw3 ¶·ã\­öÃîÖ›,ü?xG‘åt`’rowä ‰Oh~a¤¢Õ,À &øé7`—s*SµÞåóGFNÇ …Ç„1Iwbnƒ0W76Žx3äsø -î׬­’¥ÀÇaOÑÕ+WFW‘›jÙ<jíEb?F0“턞2iakÕ GT÷#W'¤ªpŠ=u qñ8‹4õ¶tBÈã.³É…f²³&KÖ³J2`‰þ9y\{¦øQ("5•Z\—¸î%i&!êHaXiPo†ãüÆó¸ ÒúTq½*ù:äƒvå«pr¯-V=bsí%+VHŒãI[³cµÆGòÉHBKkÙuù›$àÎX}°å,I‘ÆywjBù)Þ4dS,3Û--¢ø4åSÝ™÷y²ö‹˜"è½u–áæÏ,¯_6EMÃð)õ£€ý ²ûÓ à oÚQ5W+`4=s`¦~ÊhÓ‰’=+D)˜(“åæøTY;ωà Ç’ïañ觬ušÅ¢9âLô©60&á±®¥‹ÆŠ"$pâ..±wT!ù) Ä8ýØ©;ñ˜x (-J4‹ÈN´ñRò´E74pv¥ùÏb œ9×gC0ÒrkQ\ªPg33nùòU¥çBJ1Ta€ÍïëzÓQzn²ªò=gë$5éÞŒ mT ð÷H©ÔãbC ·ç2âX¢¤1L‚v}™Ôq‘ µZmä;ª¦°Ã5«‚ c[°«yNÃy0®ÆÕqùtä‘ïJã)nÏ…Œ‡/ªµ˜Å«w÷jŒ’˜[Ä™S¤´ì #%$´ôxšñQɦW nx§B5£“§Aô¶ÅÍ&öÃb’úûÚõiȆ¢o/ZOnÐPc Ș©‹i¨V?ǩ٩\hÔÒ,Â}„yÌ]1­YM%+ReYœàugº)A©…Š5Ãó[ „ÈlhAVB±%¥ÁÏÒ¢EGÔ|s+#bzfƱöeæ&«¨Ñ™šÈwv-Hu:ZœE&1 qmî%ô¹8ÊV#©¬üga_6õ°B؈8_}ÉìVòfGP2´$6ú-úrµœö¯+Ÿ+`h6ã‡ü~YŠô×··ôv 8<çñÄjÐ’ÖC 9¹(‘gfLøÇ;û€»ãa í¤¼Uu•l»¿7ã6Un,‹Õ‚ªgní¿"c àŽÖÏÞ¨"hG†0)œòÛ'Ѩ‚Îmè÷â{ýY¢:¾E×Tœ·çLæÍbC#3p¥Óv¤’Toâþ†ò`ÒàlêíÐ u›—¤<ýS®Ulh‚ÜüÕtZ%z¤¸K™ÉÞmX®$¡ßêbnb©î”îç+Ëâ’rÂú pħ‹ÉCìƒìThï‡^çÔèj)àcal¸\?Ù ábÈöPnÎPl&z55ú÷©?Ÿ"Ÿ®¡°À9ÌšRìÈh¼Ì§ãä½0Ö>` …Ó^…ÅÒïúŒÚÇŸ˜jùUX©¦õ&>²gŠ">ºKÜÝ·rb8ùávß„ˆÓ:XÈòýÕ"~ÝÞöª±Zí½à´+=ètæœaîõô­¿+ÏW¼ÄrÓ:žíG¯ FÉ¥5f'vî®hQž+—-ƒð¢‹ÌÎ"hE>”Ã4ÇÈHÉï½w¹¸ã¤ëÂÉYQñDç [óÐ}×”rŽ  ÿƒa84 Cá Nþ‹DÀOØÓò9„cˆÓö B ±gô~=‘ÆsTŽb•Gã¹Ô=Ο`Zqù#ÑæðŠÖG*“>jº•õUЫW½nk–A ´ITb5Í&Qh3âÙ8€¨`UÎa1 IaõWÕ¾3ˆßðÐ Ö zÏ@ò9Cþ?&ÃB Ò¨\ Ý!Á`¨“Y5õ/¾Dëà ‡/”„Ãn0XþF/“bð1˜k«”Ú ºP§Ýê·Ûld"É€ƒjxqð 1’‚Ö#÷~.ÀÿØõcò¨f…¢Q9^\‹Ðo¬q;דΕV+o|F?1¬Wb{Ë sz¢1l#n?N²“$È2F½bF‘¤ÌÊj˜³Àœ¼®cÛ#I3´†¶¯B,¢<¬ªœ‡ž‘BެëóLå0Mœ-+ RTFéT9­Ä *ʤºGúG€Ïú¯!³Fð¦hÓB½$ÌBFʹ 4x>CsF¨³Âê7íâøÙ¯"  H` +ê¯Kä<Ñ8ˆšT¢M®CX+ÂôÄ+µ ô€SBF¬Cgë*§ªŠw/=¡Bzš¨“z…ª¯Àí¨RDT*#64ˆ8 Jj-)¡õzS$”œäð7Ò"Lì¢Õò½U08 V ;?²X+)IÒU6§)Ó†£(¢>+˜À¨<€èIˆµÁ¦´)ìÆ¢l‡¶v²uÙMh BäÅ4E•ÁÿLuùü‘ÏÌD’óRéþ 8Oê>š©/u€‡àpƒ>2:U‡Ç¨4@ª³‹òýVèøŽ( 2‘Ž ³”µˆOHæ3Y*¸M?cPäJ±lîÏÖkdý2·Õ'fdR*5œ&Ùšö‰Ö³ý„«ú:ê¬ÔÒÓ¸R=g4 ¯‹ZÜÌý0HýâˆëòjÎç¸rcf¶lÂ9ˆ#óÔªâŽM3Ÿ1{»Û^¡ë-Ù«Ò°úd4DòÀ—ž„UGÛ…P½—²uÊg Ô[²±Ñ@'þª~Hì í,éÂ?ƒ1nJößñ5èm“´Å¤nD1rYý&á"=«CÕó'Û×–"u ãñŒªØ|%@gªúSo㦲¦.ò8Ä¿±sÛeHì»ÑôÄ( ‚JÊ)r5qâ'ò‰g¹I6ØÙÉÖr7|¹5Þ~Çâb{ „ÅNL[óQJ õ¢£ä0¬QEF•=%ðéѻ݆ F9ÅÜj@`0-˜æ@’i•w„q`ŸPF‹Lϱ·"&ºQS…Oå œ‡üÔá:&¯ˆ §³Kâÿ/Omζsª¹±p ýWʘ!²dQ˰† ˜ÝÛpÉmSãél¯Ä(¦š'„ô“<èp `ÉáQRÐÛIyHùˆôÚ¿ÉD Çp¨Äe ¤ !îX˜°eî±]iWo¤Ö ¨H«†kD}éDR„Û³= p½14$}Üðû6daZ£YÑô·8ÈÝHIBTÀ@gMcœ&¢ŸŒ~9 áË1úãÔœSŠiÊUÆÔ\…ÜXÒ‘ÿœ¤ˆh`*FF奿–rF$#÷­ È49ï)ל²#’%³v$+|KMñù·Çpoœ=(ä¦78ò4"ÆéØHiܘ”=©ÚÏ%sÞÈÿC´TçJO¹1aŠM—¦-H|K“är@:c8_ðüa0EŸFÉÇ (KýªtµÒªØIéDhnÇA%&&Íd•„€b$Ÿ5J–Oš"DP£¦h‡È÷â?R¡=eL2õ @M±9¯è½`â0y` @4‰R€så̽'çŸ%:Íj5Mž¢ª33e;Ú™tµ–̸ “Ï@ÐêÒ5 ÀÞ[ƒ£äÛ·´¡m÷£„åyóÉë^%Uˆîåî\¸«.,IÎk¾,:\×›1ÌË—‹éÙ[ºbnLQþÔ[æîZ’ñIטjN+q’âñ×Ö£»“EòÚæéÊxCŠ"@EQ³ õeBë§ëð¨‹Å„Öƒ•Ñy£TÈç÷¾3…60 ¿Ñ™q'Ï“ ¡»§×k…¯m­‡t˜‚:ÙÓôå;fêGÄÕ#¢èõ@dá´‡« F!8ˆ+¨Ð[‚¤gã6Öxv;—ú‡Þ¦È$#Q•½ÝÐf i “Ë¡0u¨þHíûfnvá²a­5=EÖë0F’Ó~Ó„ã3ëÑB‰ð‡ ž×Më·©ùãÝ–IÌ'«o–É"0‡ùZ‰ªt· 'º ,Êð2im<~¬yó“Ù©Ú8¨¢Ž,¢äŠƒhŠ /ÒC8‚—L Bµ+;ò j)d³ò8¹ “kÍ4a¶¬L ‰Š¬‰éC´“¶´²&š®ÐÃB»Q§Á¢¹ºå“ß+9é*@} þ'iU§!?7 ±¥­º·53Œ7é[@“\%Sv ±){ꧪ å¤Jl+ZÁŽ«e1I—û ¥Â…¹“SG±³ñCz‰Ÿ($ :ZÞ'0~<øê¹Ñß-¡•¦2´¡šr¿Bb-³£°²¾4ãs63½+Û i)ët# €‰© a¥•»ƒëUˆõ–«õ#B‰!D+· -1.(/~ 0kFJ.Ày ˜ ›dH;#D4C;ð:ÏÒ“Ã1c»+è¤`ª•¬Y›[§9Î ZF®”#bo‰3?1œ_¹ú ­û³»^’ª¶I L& Kä+{¹±F%C!©ñ3Žš%GËM¤Óál2µ;A<ìTJ„D z)Ùû´Qz¹ãc¿1OExšÓgˆ³ó³ø¡9Ó£±BE—ë”DZZ Iˆl3KÈé~µ4(—H“Gâ/”œw,;ïÅ¢âd³*D·Óž¥²| â¤\œ¬G½J(<Óîˆ{Ë€*ÍÊÉs¨?h䲪@–#ˆÄ¼§ƒâ¹º±"6Á ÀäÌééê ¼¨ØÈZ\Ã\K4òC–@Ž,z -4½*#sHiÆÍÔ>ÒáÌ2³Ñ›û=ļű;8ñ Á#ž“  xÝ=\Ýœªù¹i ©¦¨qG‡È½êø9€†GJó¼ÓlÌô/ć$?ÅØÁ6äœj“™Ík%üµˆ¾Šlìqty(‹yAÛq ïêÙŽPä!ìBc³ô¾¨ E«Ly*{û²Óº5Ó €AÌM³„¤P»,I€½3ò‹¥2§ÑÚ>¤lïC°4¶—ägÁÓ3¹ó‹‹bºC ¶¤4 Ôï¼ ‚2<Ǻb4¤+‡/$é—ùãÁ ¹ CÅôxÁÒ Ñ@˜¨ƒãŸ<-´º¯:o¬{6£ L$ËNâHšÒBQt–étœäÁʹ#Ð3³^¶äSD:g+M=<á0I-Ål[7\å2æòs¥p¶an¡1Ãú'F S‘zÃÂêsŒDâ>qÅ‹o“´á‹`ƒix¯#”ÎE‹êF¹¶,»Ñ1Ûá–˸«HÊÆ›W«M¨’ÐÖi4C]R4|M`¹SãÜ–zÛb·ãÏCqxZæY4„{%ÔãêÖÌȈzÈ• Ï} UúòÑ ÛÏ =¨ÊsÓŽÙhõäi4^fcí² cÜ„Ì) IYº ë€‹z]Ãk蚬‰n†ž]†AµÒB3%ÞÄÑ šÇ¸lh!ÖU…û)ý“[µPD!‡óÔM‘¾!-m,N|ÑF›Iñ[ªßð%Æ'Ñ¢/&ˆé­Ã¥$ÔPéû!Øl6H*Ræ>©¨Û2ãÓŸ`r­ó°M}Wb°S="Ü›Í äÆ7z ¼Dy 6i€I-65fо—ÿ–hHFx×R7MŒÍ;HT%ŒÚ]6ÎÁ"q¼Ðò⎿NLæ‡Ýir€²£Ì'ÉF/ª­Š€¢StÉÚ¶_![G0~2£ã§´™¿NžÍ>àλ.w~@íi?:¥Ü_.DÁ¶‘!äb=ÐÞXòøØ6Íhžy¹ÌV*7qéPCh9s‰‰tˆûˆ^Èê]Ä'ä&ìÓN(¾Sam%ŽÁÖæôù³ƒ Íe=BŽmÚý€>ŽšÚC)ó` 1ånJ²;­Æc£«Ä[ÀÅœ¦sj5·àóü.öÁÚ㽊nÙÆ¦¦:¾ç5taå·M•Ú¡ƒ¾ 9Fbd)ÞöâM“G„-m…ZˆEI5¬Ê†zŠ)HyÜbÊËK— òœR¶m=á®c4çÆ˜‘ËÉ4cylÜ~nÖV¢ØÙÒ[ÍI]|RtæV͘/ùCÀ •Ilp•%àÇ”,ñm«Oz÷/¹2º±r@Ï.V5±ÉŽ,™nÄö¼"ˆ¤ ïD®¨Õ¬Pû\›äZÖsÂ^ƒÐ¼ÞŠSŽ«ÝÝw©hâò0äÛˆ½å¡…^ÉÒNE³Âo®E|/ÛwŠé?¾¬Õw1DmZSBÔŠ‡ ÇfѺ̪±C­켟3W0(2â Û?\\ì-|¶0}^î^ @Eå=G=©“ñc“´•Å\¶º#!¨rîU‚*¸|©ò»Õü,=‰¹¥šZ›L,|(ÑzË5ÝJ|•"ßNæAzãO/J0‹! ÀÕB3[ííßÝÝöTC«©r(âˆÏ@©ù¢Ýt›ÕAkNÏLùpä‹ööh|ÃãòoE=—"WûJL*>ŒJ·q5§Ñ"8kú\˜¨qƒ3H¿½$_½©¢¼ÅWY92Ö|JÜk§quêu,­ˆ³ "N™tð® ŽøñeYÅy­-W+YSAeìG½$׋>‘»µÏ`NN M޹%=¢‰éó¬ gâÁ7u'µÂ¹Ôì ÓM*"§ÎŸvc Ûz0Ë8¤óFÝN¤Jj¯rTæ$2?ŠÞ_¹¹C‹äéìÀ£ÐE⊓4”:ŽÉR®-“ß6Ël¹zCAUºM"Ç#ŠÁ„ê!^q¿AT_7ËÂ)¢%-l^ЈÕ/ÁŒ_`2?ÑqØñ¿iPÏ)ãûùõ»ºÄÉl—løˆ1!å–ÁIü×ÕJCÜÄîI¯DËSû‚ Ï˜@†?!Ϩ€"%}À€0`5G@‘ø´uüý’?äÒx´X+”À¥` T®O/ŒE¡ÏÉu'ŒH¢ÑHÐ{›Ï Qð$b ú’?f‘ˆ56_:Îj•pžE/§€¢Ó:årÁa–@¬vI=6)¤MåðÀ4¾‹„>lqŠ bO'¸>/ÔtÊöÿ‹M`P ,ž—_“\¡Ôÿ ´`ò¸HRµ®ÓdRzF~M-ÊY%r*ŽIpŠF%ôˆ¤¾Ç1XîðjÅfM7ºÕ;úFÊM"º×h/~E’á6‡Iæø¦¡ÎJêixƲ 7‹t ZŽÆ6ʤ]d1ݸ ‘ªrí#î) k"×£îr—¢Ê¢¤°ªŽz—©k‚nªAHšò¿É<,ë Éú“¨*k)í»iJ¶•íªL¥·àK<޹k3v›ÇGâO¤N¡ü—± []'P#©bp޵*4é=ÉL&†$O€³¾m$½¿pûÞü$ÏâtÑêk ƒ,zMÌC©§Jê)!¢ |F’&ï+µ¢‚›Åpº.ƒ) ;üÒD±ÉøŒ&î Å 1 ¢h"ŒÂ©Õ3¤­à ÈÊ»6M R{Fr(IЋñðÈ0p>Áèt’2t$v~-èby03B[3/’´®U“ªJ¤‹")´ š Õ+„J Ïdú@ìÍ8¥rë"ÍT J½>KÎÇQ®½“+Ë­#Á9¥o-`Ø Š¢‚Š#–M /€W2ö«vqûL´üdß©m‹æ¸%ñ¬£ lÕRÁëŽÆkMjŒR ‚\°±˜-’¤.éëc€ÔrÄ*Š^&’O‘ ü}dXµ„ºË]HÅj Elʗ£è£ê„$ï*á3b’Â(jËR &Wà4Rª—Qþ—âþ¸< ¢*æfs½î‰QèûüªS5eKIÔí#Ã’ì’í 2*õ‚)Ýoòá˪œ•¨2z®¢Êmh~×*iûàLŒ.©º0Äl¾³2XÎIBË7\ͦ$ Êuf¹:EA$ÒžÀé43NŽ´Œ;¶ô(RÇ´í9báÁ8[ Æ’"ÍìZª”?Xê÷˜×'é'JB—ÊnŽBƒN©lFFÅ"æ–ûÀ"»ñ¡Rî¾ë¾Ý‚ªŽ©¿p ;½®b….¥!ʼ¶ŽUÉy"J ¦ž¡÷ˆ‰Je4éU¤ä• ¥&à* $ĺò’ÙÜ Í’·è«ºLId nìõ–Á$^0$†åN«˜IΡ90u·  ªídÐõÓº±þ”Ì\PåÆ2w@êÑtËõœD(ßWBçIä<§àNŽ‘‘pP­QÞ>œT7K”¾·*—¨8ç!‚0h¡ã3ÔRI‰æÅXîÚàzȽ>Ä.©bD}*± Æ"tØ™¶$ÑR>6EâeÍœF„ëN/î?˜Áú#è…HnRÏÉAŽ$u;£"d¬*iAhÈÆ‹ãÛ~\Ú<¶õ‘ZÁŒî`~«³æÈêS—¤˜ —S²éVšÝ%3¦¼0 VJ/DË–EñøÄ‰[®€ 1Ià ‰•”y)eåÆ8–w@sˆ€}ÉxØGØ$À¤YÉ×:Ê\T„D¥ÆÙÄ™•9ÒRf¥ì¹•ÎÈãBJ€RbàIßû<PH†= ÈÊ[l9²=èÚ5ŒQ`“îh›„Ê]B3vÑ …FŒ`Êk—²ùL¼²ÈdÞëÎ%ª°›À©¨?, E Ä=tdb ˆ øË÷tÖúžžíúwB’^¥2öô¬DÙõ’`_$}NÐÖý>Ê¡uœäiåšHAHˆûË¥ììE®C!×+²4Á™80ªùy+Ë´’=]]êÊ“U†8ÄVdã+²İɨìÌy^T+eNÖpb „Ê8qâ§è0•‚=7äR”•Od½1'Lа©–Njg[`4„ÞP;8."1¤Vp®\ƹMÅ„n¢ØÚ—H>ÌCi$Rä W›0iP¦¶Üˆ4G|¨T$„{ ú¸Õˆxêª/}kı°HÀF˜\J´¢+‰³¢“7.2À„»ŒE`Ì®Ý:€‚T‰´e×i²*Y2”éTlãawV•žJéé†6tºÚ˜ìÏç¥^žÕi9"¤Ø3'Eqi¸#h¶^½:,6„Ïùj·Ÿf X¤vÜ É\î¢-•`EgQ\ÔØº¯ôÔg¦Ã(Ù©FäŒ+ öY0u§Œ%t¤ZÒM%ó ~6’®3+‚©Ìº]sü¼É£#€ekÁ!Îl“8‚—Tì±ÑÙ¶æƒU]'y¯¥B1˜„»%ï¡pJöà©9.ˆR©TíDŽÏ§LnI;,Ÿ$LìCñëdŠuxº©Ö „e^1‡)èY› (øÿ›Óîÿ·«c§iU–ÅõÜŠ}çÙaÖͬ'¤^½ñ'T ’‰;Z–›# ±ÑcÊqlj3´ÕY‘ÒýI)’6!˜†Þ5§—¦##ªÜ~]ð€\'U ;|h{a¹ É:VÂÒg¹€[|U/jf™bÂXÔžã¹60E`ÌŠÆ]ú@’ŒÖ·vâÚ`z냻ÉS7d˜ÉRx¤ç%×\¯Í—Õ È‘C¥jÝ¥‹–Å-6J‡DÉ6è#$k‰¼JA¼Ûóc+¼–]µâþ÷yX¨nê^TÌ‘8õÛ[žÚµÞ¤nqšz!ÍÞî·¹m0V²¼×'h¬Ù5PØGe¯ͱÄÛî€sõº¼›0•ʘ¨RN¤­¤#²®î6tü !ºß³RKÕ†$¯4…²~x?ùó…%RñB¯Œ£M6¯Cªwñ$tкúƒP®¦Á0…å$ÚœÄÝè° ÝÚ É–9S1/O1õÀ•äÓ~ÌŽò;¾Õúzx+¼0úµl°Ú8SÔµ±FxºÚ€TÜ=œQ•!÷õë;ÒxôMU4x~)Þ,Ú}ðüŸy<~yé½TrkF\æçcn‘ýÎ’„„¨Œ^+J! ÖJ^T訂 jÅMhýÅB$O&†©â±‰iÖ$å:ÁI´+©–ºŽÔãê–q‰ l‹~ÁЍ€ µìí,¢hdîjÐm(šlj’E’’.¬oöÌb>m¯ÖbR¾N@ÞNXÐeªø¸®d^¨g“B”°ÏSr­å ˆ„ç.ÝLl î;¥J¾£ºløèL¦h‚øhtÈ‹ñ(:ÇŽøE"D_ü`MäjÀÉÂÀ)èk¬ÝKúzÅcIþ$ᵎÎrèÐ"‹Vs‚çÆN¬ªWLû¦$LÄëÁ¾ñ):§q0u-_ %GêÖoÅ`°ƒ.¦åÖÿ„v<¨_èÂ’%þ¤ŽbàÈì2¶ÇêÐk&ÛFä!çÎö‘LuF¦•ðå§ô ɼ£¢%/Æ Ð1 æS/”_ ì¼ †ü—Ͷ!€²ËÖ—ÅÒXO +öÿ«rÜÀ :FF?£¤º¶"n(0%£ ŨŒ,ÎB"VU)Êa` RÃF鮈ôÍ2 ˆšÔ…2ÚH¢ä¨raŸBÈÞ,kc# …+‚ÎÄt–‹º–âVgÑb¸ó *,6Ʀø+NÇ “oì0.P æÖG*I…0â†jüTcüÃÀ ¢­JÈæð‡Ð(dléno%ÒVùi|@"^.©Ê™"žÈà©þdp´á2náEÙ Žm0üDØ€.ñ r€tÇž!2Ý Åëç¬ä©œä®G/"L[).ÂNžÉ|¬Kº)m¾û®Lc¯ÑX\ç.¡ýÉÊŸÈlTźépR1E.³'ã1 1RAÑ ¨o,kmÍŸ’ƪ&Àª@_Ó(ÿËö]Æ P†N¶$€î²©F\rçøWÅFøÇQ ¾²îoÃR$DgÊY#ÒÇé*L 2 ?Ï4j‚ ‰´ßg,'O&j<­)öcRÂp!mx@0쳊N R#HÀ,…3àaóî¨b‚VšµkhÀNÃx!ÒtŸf¼ä ^ŽÆ(Û" S/„Æë» ¤Wl¼ºmò+qÿ@%BɨìèÆ5"!÷”¶$ÌÔ„Lld^þ{*Í“Mà…§1 m€§ÇTšÓ>˜‰ö¤iÜ@*rcO#\1f»kbŠ‹ÒäÐ̱°ÂWOôŠ”L¤-‰Lå—t6þÇŸMm7Cnì°`ƒe ¢ÑŸ3ŠcGînRmb$9JøOïÂáìr³Šº»É,@¬½LeRjÀ[(<†2fïáòZF(2箯 þ*‘H?Ô¥R} Óáö2i:’L`Ó\ò«FhsóW5,€ ìRcGP¶cæ3ª¥NšÎìDXÈF´Óâ ã³ÌР2$òõCÚ”3bGÒì>f :â-«Öžº<©áB2гº<­äç vÍ‚ÂÞG+/Åí‘—"Fâ~±µ*³ÇT2)ܯS²Rº4«É|³ˆI†N“¨çLÊ c3LüÁoÓ.øÖ"(Õ1w"´ÎÔ“£BBÏÏæÍC)%„ŒgÔ‹.ûÉ7T+0se\p(}hRäj¢ríõ%Œ)I¾"ÏÑ4@66JdéR¯ð[ƒºã¥V â7. šî†ŽÐCZâoXôvHR:OÐ$Iлt¾.· CH¹³jó†×¤y3ïR6E,u$(Öµ^ä1Cóäˆ~@vŽÊ)é?h ,w¥J÷²MnN3TåÖŒ Q—fcMàާë üM]4Î{u¡ú<± R×rÞT2¥`vp«ƒ'¯S7„’’øV®_T˜w0Jü’”eªŽÓÎ)”ÿ 0|ðn-U ºÕÄÌ,”vm ªw’¨slR+ÀŒ¼`H’½W•(ä°ª2à/ÈŒuÀGR`u>åuÍe_@ 'L_=³r×VÊBÈc‰.5ß r€“ì‚ÐDÌ2iÅg·–˜¦dâêxN¾¦´%h€wpàÅJb•à,wBËȨÈ7W V"Z”J‹³ÿZï¨ÎhÌ}kK°V©WeO68+x¢1A^Ó?†'·n’Ç6qxÈó¨ ñ†.:l ‚pO¤#üM—N¦E!"yo'G›èÐeÐ"Ô#ºÈâ©Lp ˆË§' Yi™‹³Œšëª§G¦N´Qr½F‹:s/|'LâTZmG‹6¡Zñ¨Ž°&ú‰tsuâ}jpå´¦á²äÏÅÜ’÷)6âZ ɧð?,š²ïajì'PÐTªi±öM|y`Dñbrðô¯.¼tÉe’#úÕøÕNKÙsÑžà ÍH´üRJò¨¸Ö¦4+ºEuD²PÂåã„àhJ‡a¨\ŒÖ®¦×H·nåTêÇèÃ"H‘(^#|a ÿ0?}íÕLÖ “%ê)70"eÌ›œ¨ñJd€LÍ]ÓÒ“¬µóµTŽŽ%kŽ!“{UW¡–ü,yAŸYyCîAšnÎsB>ÒZhŒÃRžÊ¢"DóVžžË–J¼I•²‹ÄƒÎF`Еc¸k"¶);ÓʹÈÓLí~˜ doØ=™±#•+„ZhRJbê hÌçÅŽ;–r:ÐÖîǨ²éìb’Ñ9w¯«‡°Lö'2„œWEª‹ì!uE™ÒEúˆÒu®/råz·9ô™¡‡TÇo‹*.@Þ [C®b‡FÿRQj¬DÛ/eXÈi½Ysw'ÌVáq¨› xþßêB/µ»IUº'µe×X„1T%`µvn^1Vãý‡ b¡)œql‹1ø±ljDÆÚž¦B Å¥]L´Q«%ª9j¿Qxä®ìZhÐŒvEâŸwµ, ú„±]tÊV©rcTõnmJùIYsŠðl ˆÝkN”í‡j§•ö@õö¾.º¦Èk§y «Ö‡#¥ž`«‚4DÖwkâǨĺ/¢ü³—¶ÖïsÏfE`¥Í}I ZHºý¯cr‹¯³D jˆlIs=“N<¨bšFu}NâIpVÌŠ)Ù3tø—¥T·”:OK+Jäf°c"Hšy·P ´aWm8g6¢À1?Ä¬Ì UšEmB’{ë-”é9B;ÇùᥡüýPr†ºkV.ª•bîQ¥ŽrHB™‚Èþ³"VsB²] j‹(¤;bÑÕ:·¯yRQ*/Ø¿ fÛ•¢HÆ ã£Ci5̼2ø?%ÙX¢Ô)I#Úa‹[œ³¼û´4Ý‚àÝò’ê^`œß:¬ÿW×~ðEÖÜu·PY®2s€%ó¨"º¾û¨«Ö¨$ëVö œ¼joÈÛ—;y4}’ êÞËÞ4›¥ö«Ò&ï5H©T5@qÎH(™ÞOYÛ¯á%{W·À}r¯ª½‡Ð=5ô«Êæ€pÞ Z§˜«Ù&.¼ã¶ïõ–‡?®S³Ž,2³¶QäÀ­àj˜©{íÞHµj‡5¬ÈORÛö+¡Ó:ºm–u-ÛúÐ[-ÊŒ=÷ªåz‡SOXôÉ)6KЯÚP‰íLe&ÈlaÒX žÊVzlÔ#¿È¨ ÎZFhÀç)àDB4U0DŽk‚˜j¶Ân‚¬a|“?íÖÕo/E!Å»3K\"êµeS˜ç#N´©ŒpCc½ÅÏ£/?‚ªi÷%;Ýß% cº¯~« ¼˜¡9§¿Ûü˜–šGiÄdx™+UêMCÕ ¹cùÍ×é[Ke\n ݽ¬#ãБô¬R“Z—œ¿çS³Â}ÀÀpX0ü…?á×ô<‰CbÈ4*ÿ„bQØŒn$‘Dâ±é4ž7 ˆÂŸ7Ø`ø™f’é &—F!÷ôÀ ~Ðçѹãþ‹¡¿d2*tJ},§Sâ/ª´ÞY¨Â€µÚ]:]@«>€öXmP¥Á¢Tº\ú@†Òãv;(SƒXè'ÍþœÁK)1È:ºáòÊ\J…CƒÂ*ûUš­Cñì„Ñ>ŒË(zÛò‹†I)ûdzTŸP)×÷Ì7±ÛQ ·}޲}.µÁgÙšÛg0§K#zv‚EÍ‘Nb:-\~N†Ë£2à_¬ÿ‰^@0׿œ é´kÀú˜ YéK:–›Í/ë ùbvÔë §5Gûð†:Jš€—.í³l£©Ê:ŽŸ<(’€§Ïp¸ °"4„5+Ò –1-#”顎d>‹­è‚"ÎÁȸ{F,K’%Rþ£©k’{€ð–"O’Ëš‡>ª³ (ˆ{iµ¬òN“§ÊrúäOcO ˆC„¡¾¯Pí#(dÊŠDj ÉhRÆÄÇðJʃ&GÂ3lz"ƒ%Ìø¼*ˆ¡°Žz.à q( Ùüº!E¯(lK¸‹I«sŠE較,€NÚ‚Èçí~®è5@@(D¥ËB%CÔó/S¦ ’DÄÏok0S‘ô ò!&˜,)ƒôõ$Q‰ìĬo"Ä«UBœÂ¯jµO |kÜ3úÆùXS©t<–ÂY((P»ÃO/‘#à®+µb5^ ƒ ±¨S®­´-Ó4ˆÝ³Xä2ÎÊGLïz€ðÀO"LJ>G¦>ùQòU–†)isWj›‡O¡TÄ8½‹DФÕÅLĵ“þ_^ØùûrÉé…çÕØj†° j–5 +°ò¢¶,P kCë[Èsa•CXØ·Ò¥Ä*íÖM©ƒw„ŸùírNÏ’Æn­²°…j§ÞÄÖˆZ¦2§óÈŸ¯b]•#{«]!RÀV`B6óžíàùC|,àZt¥¤Ý¡Gí@$#¶-ýC—¾S¶0‡¾WæþæVýÙKlý¾Ó‰ÔQäŒëÕ¯}pÂÄàß T/b7;g(ô7hªÏ”˜Ïë:EʾItã‹*w° ?T81úŒÑé÷¹ÚÄÈ åï8©þõÔ¨g*ï|ªoú;ó²_>SBfa…1¤Æ[iõ=à ·áø¤ÇÙìGnß™0ûGã7{°Z¹Ô"ÿA"KÆthD® qá0&±–2ý`¸l®8˜>8Ÿ"=zëÉ$6Ö4RŒ”7ÆÔ¿¤7Ì¡‚$¹Ó3C8ïÙ´G„ˆ §—Pðû²ië Š–ÚËqÿMЬ%„ãÔ‹SŠ €¼À²<~^ K+©Ø†ÂÂiˆyN.å.00·àH–PƒÃô¼g>ˆ“ou`?²ÈO‘‘e Ì–åRY\«„}Cñ_/mTi0ƒü–tÿ Gâ—T‘ñ‡E3¢ïWDU_ÀFR]Õ«Ð`¯½ÉB#2…“ ¿n )VšÂ ¬­—‰QêD’-ŸqŒäù.†L@ÓRVb€G¦¦³-‰ 7ÑA4H8dÉé…ˆù9RïˆD{(éØÎKš ¶ ¦²YŤ~¶¤1+!GÈ›–8,èáãRDÁr”ìNçÉ‹“ÔÅ‚(¯Œ,vB/„QG}`¤gF“ø†«uX“G©^PCâ˜DgÜþ›s–n›${L*E… !€éÝ"4ÇC¡S5ÓIP$„®õÙɨ>4#}ó¥ªä')UʯôL”h¦Ž¼M!Êê?WÍð±¿Që[g»3¦§I1úëOKÆ'Óˆ¸2ºiÖ—hÆeVT°‹¹£™ð%Á3Sa éüˆgÈôÕµ,˜;Ÿ<‡†~¿(ú@¥M™sÍò@­AôäyžD!éÌj ðª ©£VÙ8X"·ó065ÉÝ­ÅŸ0jYe5;M‹<>ÌL…rèØ²¹QJ¤»Q-í…/· é:¨=ޱÖgÙ6hÔ‚†Ùê6` q#:ŽSRŽÇê´ª3ñQ5)FGPç é±SÒùò=ÙìzU‘ïr¶=UCNÜ0¤dÄ´céY E+Å07_Ì'ì‘ôàI@ÈÛΦ‘lªeXì+à>7ø¬x‘ ÈÖJ`·¶ˆk6ª©u*Ø}±ÔÊSUoŒª rÿ#=‚˜ÉåÊtÿ])é{®äÅ£ÈÈÀ%;š£ìe³»‡£MQaD¶M×9kgCÇòލî5gaS¦§6×¶Wg„@áF Ç•ÛI4È©f1†Ÿ@™y%e·ÀLüòW»yD÷Ò<©*¨I¯$ŽÅWKtaÑ÷É­w>ªp)Pñmz>¬®WŠÓj®‡Ä±6P꘻¹SÈÈlãã1Ðí¨ÙÞ÷xaÜöŸbç Ê¯ý·‰ü»ô/^ÙEÊäš…€fYœa ÃeA) QûXm­:“#åx©–|©wfoFæaÎ%JÜÛÆÐcÓîÞʤWmâ%ð?>'Újt÷Ñ9åÄ·.¢5w»»qß§éX†ïË[„3¡yչˀX©u| ñWØbõæŒaCgÊâÍ”d÷pXÕ“˜,'ìÉÔ§dm”8ˆ к…(üF ÊÁO]ïê–§òCÎ^wµ„Åß~rËðTy?ž£Û+1 ûh Bd:Cׯ“ â#`y4+hz¶j"°H†+£ ›ò§Á®*£ì«Ú³ÐŠ9‰–j\­r?ˆÊ<Š—µ Hر€‰3B—A{E{T°*4,q…<‚1C¤¼£”*•©A £B};ö&‹•²3§¡—‹»f>ä8ÒD Î1"ˆÌ•1­±˜÷¼Ö¨~»ºb›â´$¡Âz =ëbBá ‘?¾#«ùɈI²7)Ë´K¡ `ƒ0Zlbžœz¥¡ë±›xÛ:ð•Aãˆ}{ø <* )4+f10œ;¢«XŒ4 Ê9Š±ŽªùŸ Ó®z3YÔ0€òCùñ¬8† °‰ ¹;CCŽ€(†–|#ÁÛr­0ô•3²“3¸ÄHØ«Œ"”a0y*0»ÁH¯ë¾$¢`À™O"c¨pŽs”ò°Q£0ºcF‰z£ü :µ£ØÛ& ;a5D«³T?*©¾cÀ>¢dAŠQ:JÂ[O‰«Ë±{| Ḛ̀™”+B>‚AAZ¶(3ê±Ð|ˆ›y‡! ‹ aôºl‘¡¹E:–‰:±c¢'¡5>ØCûŠ,âè¼B=ÃuŸ|K³žTYºóÁS·Žðï³4 ˆôÎ|;Ðjîo,*“¸$)éãú€â`Ñ9¨'l0š`£ÔRÏL$Bù¨/ÁÔ HÌ6!ÁC°‘C,ïÉxÛzŠBqŸ?ƒS¤mÉ©Ï`‚œ¨VDf̃>+s ¹_R$A ëø;D`1À}@¦8{ ÏÁÏ5²R¬½?ˆô…=ÓÃà|*²Ÿ³ø–V@FëÚ‘‡@ |£,€|º£éØ =ô'€§¸2ÎÉ0"­›ˆ)ïˆÍ®­©…(‹p·Á´%1°  ýÔ%¦­DˆŸAtûº¢â:h†‰»hSä%3ÂÙËà ÿ|¨X"*Ó˳Vi™Ô4jœ¥¦ ÆZ”í‹, ˸³2î4É¢íT–éà£ÜQ˜aø»Ä‹×1šËP—‰Ê˜t¦ÒMiN…T1MA¤‡Ú3ÂÒ ¥n$ê:͸ªµò×¼h¿ s¹<•4°ÜEJ¡"ü³Tš½‹ÎUè@éÁM¨óÎÄUÏDV‰‡ ä¥Yªý:|šÖ ¿\8ŒúJÒd9zS:4j™ag¯DoNc‚ˆë& ´(¸²¡X«=Á£ÌŠU°«) ¯·Û¬ž *K”°åÉN@š.uß™…Ù;EO!mØ “"­&»Q‰¡Zˆi”WáÂÏ*ÑI"ù2sÚªkLN›ú¼¦#“á•"|»¦šƒZ*¬Œ1ØAÏà“tØAãOû¡°b€«­Ó´ÝÊII<]‹• ã´TúNÒY5%Ub5Ÿ{×F9¸Û2Ø6X«bë£<9†;zÐ"£À -Y¦ÇÒUJ&9¨”@EQ/Ò 8|7,ä`_£!%‹¢Ó¦Špläqã1l¢2°Ð—4©±¨ÖF™D9À6@5|MQ¡VBê6ËÛƒªŸšÙ"iI8šÙÊšÜm.‚ùrÀé–/"ƒ?«J‰”Sú+ÊøŠJZd=äh}EØ“š5ãŠëWÅâ/Øi†RÃÒÝ`’‰a?`¼Ü3ûG rÉY-Ϙ}$Ðàࢌ5ºª^tÊëL®á Ò7qû‰£ª;BDC>^È{Æ4ºÄšØ–@sœ{Õ2X¦(~DlÕÐ e,¸òF«W›À–Ôv)<\ˆz½Ô€]ÁaBŸ5~bJͶ’o[bù”=nB_¬Ï·3Q¢£¿ (8Ž–iÛ=Îf–¡ 0;ž%xŒÜº“²_S8ö`EŽñVR[|Åé’¡ü^£Ó7¡£Ü/Ñ–ö†.#øa´:²Š_N­WÀÛhóÍíh—)øÄŠÊ%:74Îþ¹TcO-ò‘5êÙf¯ª¬iÔÈ¥¢#ó‰ež5ÄœˆW©=#U™*E }=l®EA(ЙÖPˆ¦ ŽJ$`[ýÂêÅڜĩcHÊ* K)̦TÃËÈŠ=­¶9Tµ ‹.C˜|5·ýDJ%ÉVüÁ›åI„Á‰òöœf¼æ°”ž6W3ø+Ø“Vû¦ æt¶ªÄ瑨U]W\`R$ ´ùdØ|c»Ê#–K»PÖ$öolï;ŒÄˆë‹gf&F±¸1‚ø=Z0ºä‚–ùt>Z-EŽ0›ntÝÁ¾6¦Â_°‡×y"çH»_öC2ò¶ã¶)ôÂVÍO¾ËÏ¥â‡ÈØÒ%úÃeïHª±™…°0â G‘º‹A—œ½mo‰¾)îè£sÝ’° FœÖê+NH‡ð°•dnˆÌúd¼-®"¯ilµ…ÇÆpŠ ‹˜ÖÜ8䦿-,ñÜþs6ÑIEå`Zù$œ*2äOí­µâïPª @æÌmˆ«Ð¿µÜ„‰y{âJžÁ½uœg™ñ­¤Mæ€òñÝzœ5±Ü¹—ÒÓ ¬´ÈM^nÕÜ.âDѳ±ÔÌŠ¤ Ì­wGˆmý¦.Ÿ@=sÄu/"äplŸ:2*ÀàaTO±”Mç 1=ÿ‡Ö·™Uúµ¹½u)®åR-6Ÿ5Ìð„21Ÿ&½s4)*ÒE½Ãkäô ––±œé¤›ã2ËúÚ\!)îÿQ‡ ÄŒjŒK3'¦÷rò²ÔõÙr¥eÛ{1äÑ>~2½%Ü)ÝFX˜+òš¬­öºr‘¥µ7-Í4†îáßÔÊXÆé½q´9ŽXFp‹uÎm£ó¬•â^ˆj×è¶È¼™…ÈÒ'€©ýnaÍÐn\îªXý¸À¹B™Ùˆ‘U=l*o™×Ë(ªª½æêdö&/ª©åÜs9ø×7:ÜDŒÁSþ)<^%y™„jŒ,îåé÷‹F AµpóÏ.O¡—¥'<<ðTpö3r–`b»Qa+ÇË nµø¡Ï+@ž’†dæD½[Ù¢"«£@šøãFGmÉ]na6åÀrѦŽk‡ ÍZ4w Ê Â–plï'»†Ÿ°­qSDmk§Û´! ´3a¯—,­u„³åeW“Ý÷÷.Ø›¼qÏߊTý —Š¥’*D§­Æø:·ŒÌ?•öHF; [¼ë gfä¹Êܺ=仩ˆôòìPôÄ‹[h‘30›ÈêËã~aDÝ IÒâzòWë<Þß=¨…3àÿ+ù_wöY×{"§‰Ïsr­¥0€ P0¿!P8~Ä@Ñ7ÜUÿ‡A ¯¨à=Åßñà Š"”Eä’ô¶I’K_ÒHdÖdœI$RI$)ù}‚¨QÇÔEû"‰§°©+‚ϦRÍV/ƒÍ T Ê“D‡N“Èõ^=2‘H(Ó¸ü‘P)ÀY•È @ìR :¹¬ÝìòØ¢/5X«@ õÂËhÓ*„€”_ß÷;UólžL¬ÀF–}'ÃÀ§R¬ÌVIbÃ?Àû:$‹ƒZð+ì"¢ÕY4ü ¿} “@¹ оja•ˆ*SˆÄbë¸I¬;Ÿ¼EdN ¨Ì#Ö,lFç½g®z?Ez'º‘Ù!0¸‚–~,N3ª+ÐÙ€ìòŒ¹­H‹F¸¢°BˆÛ€)’Œê.jÄ£#I .£Ch‹J'Ê"“ £Ê$$Ž· »¨ÏÂX—7 2ߦIk¼ˆ¡É”v~¿éºr²Fîc®âH¯Cè­µÈôFŸ.Jr¸:J´²ÀÁ*?)․›“ |.hqí3±àJc8ïÄ£(‰óÞÝÅM›þʬS9í ó¬ªº'ýA «Ë±#%ËôJî“—¦mÂ}G©ká@¶,\ŠÕ½(=ç".\(ýŸ‰ˆ£Dj"€Ê¤Šü²¦¯Ã¤ºu¾ E8¨<ƱD6âŸe‰ÂA("°î–æ‡Ûà¤ÍuÈò±óŽÿ×HóÕ”€L^`œújç}-ì[¡J%ª‡)*–"~¡Ñ=b!Ìò@Ø;€Úº‚Äå¯Òh±= ð¹«èãØþQö,‰"hr|Û^8„ÒÏnçæü…?-‰¸&®]æ±3J‘€68ÏAAëÍÞïrœ‘(“LÆ’YˆøNgú+<"#u謔Ÿø.2™oðú#ÉLp\~÷4lä:Y‡©ÒȽ…ÙÉÞˆÕ°‹gƒÑ ž{UÈ—z+ëV$Zþª;ǃ”]{ Ê v µÚ7qü;ì4.?$ ø¿Ö§ÒÈ£ÓiúÚÍcHqÇIÅ5µ¾H ™±j õötF@Ê>Dë%ó‘åðSR‘Ö)¶¬÷L #Ð`ºB ?‰½ à24ÑîsWL(~îÍâ«v0ÁIPÀÏ&˜\Ì@"õ&ÌâuÜ— v/‘5ÆLÉyO Ѷs<íÞHÿ/qPâ³ÐÖ‡ña' ÚESŽ‘Si'È!ù²v §!ÔZæ-k¡Õ8]á9£?’(¶É ˜Óf~§–,”d”@,*7‡9G|Ñ’är IŽ ÒˆäÃ=ŒÈ´ºçZá\jl¶ÈÊ@•’ŒSÄÜ7†x¤›Ã€RBC:Uaƒµ8‹4”¼ ÍXA8v¤ãJL¤¡$KŽÅ•®´Ü^Péi(† ÃeBè—Gb#ÊÑùæÚ[ke-S4œ ÉÓ„gJ6ˆ@hYNtdy ÖƒT S@dÉx,Un€§Ô`ñIá9ú~ …jRA|·‚ôN$i™¨æ}yÛ £T±"åŠd€gAD‹™N˜¤”é5C—'J×9ká·' G•¡àÌž¥Õ¿CÙdIT¥¸&9êøGä'{”’‚¾d<ê  $ƒf¦Q×DÔÑÆ?ü}£"‚Y Íž-Ô¢<þeblj­ÙÀÈQHQISð5%Oó[@2 cí@²º!Šq“bÆO;E¾u *ô§Qy»ExEW\öŠí†Mã€#–S¶“@ÕÞÇéšM)ÀŽM€–À’y†¼VÏ^¬²6m½-W#Üë%QßÕdC=§›Rò¤[sCX”»÷4 AGZÎv¡©Œ)„^J­¶Øq͉𫰹’®6G+=]ޝ‚¯.w€B—)c{°ÑDÙE@µ£Õš@“Ô|séTŠÙ _(é’LsyŒ© fhÔ娫4à»Ö 1!´˜3ú¸Â¬K^ZëTèðãO¥¢ØÊ×64Nx€Xé*€@X“ò‚RDBŠeä*9(ÿa­®Šü§:Æ“WñDÀE¾¢÷»&Ž$'p®Kã=x[¨ú‚DLÏIWS"ŸÒøiT;ËäN]€¿/y Å™« ´ÚÄK¨œHŠ¡˜g½©¿êÝ z](Ky pãñ¬Dôä¡s!Çk]û?¹?^]ìO¤p5—ÅræÚ×c1Ýîºr Ö«O¼¬œW` ž’,ý‡k*¨–ø"B¬¼ €%Þe¸‰´òðù Ÿ0j³Ã¢+û¼@¥ßâ@Q¶5 Œ ¡áUI$Õå´¯t!ˆZ-,½Úk‚‹HZcæ#à´I HòâRƒW½çl*N©ÁXímǦøR±–)4Úƒ^g¥«Yéz2¼lÄ[k‚eÉkðµðA·K,Ž*dÒêo®O²¡‰\Ó ã øAêÆUN$*‰ÄwÇ·ÜÖc{%E²{_aÓ.x”-Ù·m3BBk™qÑ™¾¿ºaO#йTLzÄËbhLoQIVQÍÉå[Æ‚ì¥c…/NâÒ{²î`ö}—Ýõ%="7©­ìéžË:?É€ÂÇ¥]¤rÊS¨K•¨bcyÆÎ÷¨IrsYØ.ùͪwéˆW–¥ç„}Ó…¾ØJ¨×øE6 \Uƒ|?*”« IKm£ì†6wôO¥_å²à¾ÄnL»¤;öl¸fîBã¨ÌÛÂÊüŠ"<¸ß`¡Ú"GèTçÝ܉¶Ú‰Æç€9ë£a Œªï¦%&zö¤¸ub*)"æôÖ‡fΞÅ8·‡¢kªt  &JŒdìÍðüc޹ÈbŒÍÖì ¼Ï¤ŠDͪ·¥ ͬÐoG~ùO¸Ö¯Äµ,ôbe:-æ€DpÒNΛoÑkªj޼ëÌm f< Ü„âîø¡ðé.0»ïPûRâéôÜæ4phc)ÛB*¬î^îè4ååæ~ ÈC¤~&G$ODVN°% ! ‚.‡c*yc4T<´ —©¢ò+f”«$ýnð™ f7º4«l× Ø&š³g^\ÃbìB8 o R^e2d‚œ®{¦Ž¡ 6˜N²À‡ºµú¢rÅ”ëÎΡ±nÝl¾‹°ô1 ‰#Là’E\c1ãäØÐ{®2Ѩ²lãá#Š8@¥ªg¦zA „)È\÷N´Üc i«$­ÞEœ2±zmÃG" …Ë! ¦ÊVpN¶Â€…€9gàS„ž½ P„‘ cf)$Ç Mxô¥úëäj‹Œw(bxÛn²Xìø÷múýÐx‚«¼c#=3pžäïê稒é1 ä6h\è еè°ðî5È6ç-zâîˆÝmŽ-ʵ%¶nbœR\¼¬w8ê" 2BLòüÿ­ÞTr*ÝÄ«¹#CvÔPk11Ó ¥¸«º°£¤þÎð1lmÎK¤húe«à6"ÄÔ8`£ÄŽ-(Œ<7þz……æú*’^NÑ7bZAŠÆÆ'À¦pD·R,K£Ð$‘é?ËeaüšXІx0€þ eEp4”¥Ž^r« è§@.H»°hStô¢‘M&Y ’9‘7“XOÌ|­ørŠp‘O@°™BÊxß̽ì@ŸO­+AÿÐu ‡©;Òy)pŠÙƶ kšb‚œj…¢v4ti RùÍÄ».¡ð’©È§Š¨€!JQ ª’`¤-Qr+DY!+ºÈëÆÖÔÄõÏž›J†ƒªÎä@äÂZÂgÿ)„º·)V»´!)ϸ§OZ„æŽZ2ï*¥×N[ ”†*Xð#($µï'ðô:„(3IÅH+,5b$ìÔÕG#ª³ÆQ ŽÍB¾-(Á‰ô‡rh­@Í øôRR «E•"@M˜çt… ãñ.ç²×LJ Óð%£ Õ0 ޼Góìï•ëAŒmUé ðn“€rOq_…«(çEH§M~ò@ g3RNôDtz"ór4¦ô³Ž÷LÆŠ“[‹VVö?ö.åî–§c,ÃH@ÏCêl§D•¬O6ÿsl¬ò]CN´¯éK‰µW‡ºžÖá3í$ç6žÐ‘@´܃CìÕ›aŒ¸OÈw †T@¢Å%ÐóËEWé´q5Nu.žù·Q®´àŠÙjP8´3³4¯å1c@±è4ãδ§8h®‰i¶^o_5_+2¹?5*`ÏwhŠN ²É^ån4 Œ¼4ó_ J„×:y È€ rX“cjq}kQðK•ê¦nˆÔå—&¹*º(ÓéNÇc4Êå¾ÿAþDl¯—]Ow(ë¼.dFOBE,‡‚þÇiIvV““h=ÏMF$#…ªÛÎb QЛj­Ú7sX$RÖ¢’…Ö«P}cE†‹#*÷÷ÓUæ›JºÎnÙWî°N¤lm_ohl·ÖÿÕP™È5D` D±M5³Õp×Û#޲P0Žã)I¶³ÊÏ5„Šyv7;‰rš·…i…Ìòò·ƒbçwWú l©²øƒiqëºx(N·üy´ƒ4QJÈ:rUÖÍèû† ®S}ìÓ u£pßIÃàú•u-‚ £´+qiñKô;—€ÞÁ Ñÿ/ÓŒ@H„ƒáBŸ ÆnG8„D»\ xgª;a"„T‹^ý±wJ¸'d ¦[lêàï6ÇhÒÕf1 wVªu7”©3RizëS9wÄsʉBR»?†ïQ3Ð;ÂmÄ$cñPJ¥~ržD ƒisq˜¢«y%ÌÞ¡N ë7c.^?ò2È:X™Âôv5bp¤(ûk€Æc?‹ë}´(‡%i·I *8‹Põ³3‘P2b##Æ·‡ÉÀr˜Ê2£5NË€7mZƒéwQü ëx»`›‰B9fÁøsG6ï–&}Œ´@yz„Æ!0u㓲ºß98Ò?ò]†Áð–U ¼¡†Mz²ª×¡rüï·3Îb"®ÍKwBç/F·¡PDÐLâ¾$¾s¹.÷s­ò+M‰Û!­^@AJ’ÏHÁ6oLÔj¤yÖ“×»9ª»c w÷–ÆKè %<„üÑ}¼²Ïü¶¼.6áËmYì;/t'q°jMÓˆi»(úî"I äÎ[ú¦»©n5˜6wÃ#„õ¬Ñ…*ï×mL“¥ûHëÅ•Ùlë,úSš’i›W:†«0‰0›´…L¬‘A}Š þ‘MÕÊæ[¹•I—? “ÿÙ´:!̈ðuRÁhS•5NAr'È)É+d`§Vk#qP¸:þGüâíS0ȵÌÓ¹@§S<nwücÓ;ÚebY^“?R+]Úµ@KÉ…€àhÎ ÷È6iûêÛÓ™ø¤çÙh• Ä+ÂÚ€ ‘ læ3ÆzìËŠf²·ϱ½¦t£h¢ ⲇêx>…E:ƒ¼Ñ?Øo‘§k…MË£H;gº/wÄ ·æß¾cv–«“y³š:™sy`3mŒìGÁzk‘ «ô»BK=±[ShZ=€öÂÉÎ]s'݉Ë/ ‰@ ø ûƒ?¡P€"H”9ù‡B€ ˜Ô@„?¢¯Ç쎇G#ðÀ,ž!!’Æ"ð¨ài—A%O©ÔÚ+J£ðètÒˆ’½©YTb=‘¿e‘ØTÄ%’ÐhPøäB1%ŽC Ï¸pɧÖíÊíXŒ>nID"KO]çO¦¥î}D¸>cI Â*¯D$¶|–刂Á£€l•þ‰kRÓ9¤ªÓ_¬ÉaÖx†H ¢­Õ3@= >GTcñÉU>}!•l!I¦‘ñ½¢GçÖ¨U^QÙC#•\áÁ#7õiME TM#Ó¹>‡g9Àþ’ŸaàÚ*4ù Çd¬?íÔÏ”ËÃaŒOºÑý‡Qh䧨šï+-Iï0)£<¡-.‹«0ŠÓ^>ÈZ¼¨‹ªF•$*|ÁLê ÷£ë ¼¿’Ì‘£‹b­ÂGûjН.% Ÿª$(ù€0S,‡?HBÒª/©¢nEJ‚å·ò Âø©šFÜ?JŒ~º "8ÞŸ‰ûºúÑ$ph’¹ h‰%KûβÎ#®‘Eo à‚#êz–…)òaüŸHòŸ!¢OùøÆA1|E@8¨ØŽHÑ*¬Ÿï¼¾n’£Rpºi77ꜧL2ö@ ‡3][QŸKKƒD°ƒ…Kk¸ùµmdË'jŒKo$É=ÊV¦R(2|°£‘*9Â3Å‘J9ò=EÉî]1T¿ÖT"ãAÒ±üÔ£ð1ï\×3CA%"ëä° Í%'5“Ê7V3º½éõd± Hú^…5Р-ÇØ$šF "JŸaw ÿFRèRÃ\¬1-Ó Ð…xñ²X´ås¡ "?ÒÖ• cŸ±|ã^OOkWÖÕ»ƒº¶Â>°ßw¨á h„D´è{¼µšÉ™ L[ …'‡â4ª+þJ¢¦‰òŸŸY¹r™xèThŒ^÷. »/ Êu"(·N¶£®ëë¶0/ê¤Ó¼¼~/2Ê·z¤¦\© Ú¶2¯§s"lðÓsöO³Bó´öLy=H¯²A|‡;ƒsÔM&ª]Ï‚ÍÑ/çUÒF9þÁ"»¦ë«u;¸z%Sí7Îä«Îq3X/,ªlqË!Òãn~FGâÓ¹x¼nˆ÷¹~çŸ2Ðò·7HÎ]»L–Ú^»*>×j Ї$­&³ ‘+1|€¿„¶Û¹ÔúJNBálíõð®Wš>Ó+Âz œŠ°V¤Í\z0L©é4ÄA)*<ÊZ<“r\apjÏ}›×þ¸•B0(]¸VBá];ðAOΞôܹNZ7rK8ƒ?²ˆºPÛ¸q¯¹ž:8Z V±>D®ê¯HA”%A'Y €÷GD•t·±þiYkÌ9<ÂrÊ¢“tOšÃuüEJz´\1i/rˆÝGª¹5%þ!ÅRhŸØÖˆµì=ir‡nl½[HƒT€ˆ‘y!Ðø}·)ñÜšS,&‘ÖâÿàŠ \.%Йµ‚ëN™/1ñ(ŽV¾QÁA± Gñ¤LcöF='–ßRyóv°@«5CRFL%>Nh‰$ùB¶¢º5+<´'×DñŽ’”ò5ѹeøIŽÉ5H„Îx„Cd‰ I´¶)9´D"=eîY@B}!ؔώ#ñàNÂ… Çü¦„9b‰Rt¦3’tQÜ‘ÈôÀ„ ÌM$q^X<ó¥&“c4“Z[<2$¨¥Jåtîmí­£ßRHÿ%D¨ÌAÆšè1’*-#¶_@#r™ËákOBª[%ÔÆ=ç|†Aô üŒ½tEQöôâu¨ó:¨.LË%µ'SâÔF›Ó1¡EéüòH±±2þ®N²/µ ¸ÊŠZºIôù'T4𦄶«ÓðqU7!é,íb¢hIfìÉ#¢©§RÖLxǰ5®Sß3®žpϰZcqË_ä"–É{WÊ¡®,)“ˆ¬Dš!ýpÑ:ÂÍä¶‹Mu\îa†Äª,™ØZ¬Â²TtíMI],¥”&)¢ D®ÓU“$ʉÒbÝq£ ¸þèS‚q®¨J7bŒgå¸F}ä/1öå¥äݤD­ ¼àÍ*,ãt\±xií½®²‰WYjk—*µ›¨•t k>Háa$†154ƒâÄR%§bï€*(?gϾu ¤' ì £§²âþÏà=uUë»;k{J$q‚ï\÷ÎÖÙœuMÃcé%H“ö§Ãõ\ܘL?’ÛV”ÀÒL²4å¡ùSN4¥!bt÷@y4”tƒ±w$å‘»tEæ†KU¸\n>¥Q¹Ñ'Xz媙’Dÿ,©:d¤¼!8ÆÈ¶¨£X¥ôTáHL–FbÖ}=æ¬_ʤ©¶Þ-do m4RWÒL¾Q$:Ä´ö’fit]ËëE Ë1ð諞C„V€Š–š¹f,’Ú‹VÙè”®Ù°„«×ëÊۺǤÑ'Kü±˜œ´&èþ{ëÐ ›”Û͉kœŠ1i'I«ÊU-ê“`0i²ì ˆå·.‚ËQ®naþØî¤'§«N[ £Hï»AVšò1q‡ðÕàË€8ÝÖiž{IéõÒ® …@,9 ImÚžÐWèôÒÜuÛ)åLÖÓFò[éÙUœAyЗɇ=LöÞ)\Û[N²pê·¢ÇëÔºëM8¤ù,®nñ’—¼}í4¶µ¼ØøQ"ó­Ì·]Ĺ…‘{žò‰Î¸¥‘œ.œª(°N±"»Mªm®¤Øz ÌÈ;~©e e®hköA>™£?s|¹€ÛSYêGmÒy!W, ˆ`² F·‹}Ÿ`$ ¥k1PÈæõê%Þ„áwÊ8–´«<€nMW9B-:Þ6ˆ’0XiÖë¿9葨 ÖâO[õ9bWü×oÜ—dz}Á—몷°xkyéÅQ2ÈF S¾r\¸HuÊÕ’6…]„Wc§;æÑ!dø)_B²#7´.Œ$ÇP2Y"ä§Ðy†¶¶¨¾†ZxÁÜš¥'Q$ùW¢Ê"¾¢{ü6ø?¡¸Èq×¶{¾êâ»É?’ÍË­9 0œº€,"EÀzC"„ˆ€°¿ˆµ˜:"é¶2ñ#–êò‚µ6 ¯¢Þªáˆ!‰Õ?4·‚Í¿9Ã?±Æ¥ÒXÀ» ›¥(Џ@-ð*êÀz7&¡ç¢Ñ=À©²«@#J¡RUS+°SöÁHŸ¨¸6Ñ0 ð¸ ñ‡Ù##;N0’‘,3£Å¹›3Rª¬´7iÙ 0ª3¹>¢ºA²—,6•X¤6›"BªûÆ”+Ö!ZR5ØS Ì7[‹áK³@Ä*ñ¹²ß®LK Y—ÂÑl8:ªÂ”Lˆª˜ûг¢¸úo Œ+1ó-A«>€ .Á»¶A1à¡{Õ2?Âêò±KĹ2y ðÒ#Ò?Ž‘2›{Q2Ì)ˆ’‹ú0$yʘ»»¹¬®s@˜ݽC’œìKšK±0‚17»2Ü29“*€ ø>ÛŒˆQ4 $ŸŠ¿'zŸ Ë s\†Bü=5$€H()‚È"M“}¶!{â9=zÔ'" ©RF.¼?¸¥«=ÆjÓ œ^Åù01Aå!ƒa“sØ”)±´Òóň~[;/p¡-é·‹üŒÀlJ[S¥17Ûð§ÅÂô"¡É 1É)S¼2^;¬Å@´ j¡ìP¸óæˆcI)i޲Ÿ’Êœ¯´q)c[6´\JÁï|S:zð›’ëê·ò?œÚ©ê©ËÉÔC‡ øÛc™2Ñ2KJËa²i‹¶ÒÈ¡ˆC¬HžÌh!¬v+:•t[§šWˆA¤¹“†ÍðªÀ—ÔFZZ¯iÉ(p~“A’£˜²)Ѵ之ؒy^A‘½†Ck³ˆ©ÉÄ¢Óÿ*9‡’UàÔÆØ}ôß(©5±à‡)²ÿ)Äo‹„§ˆ“†MP¹|Z¤d/C=ÈÁ‘€4;$c1At-ÁÑÓ“rCÇÔž¼SÞ;YÔZޱB»¶"J7&`¦08{ÆѾ»m¤Ü zã€0×À¼¶Ñ¢6Ô±sƒ €‡±ß™ÍÀC É«… ÕR‚(ÏCÉ2À2ÈÉCÜËãºbÉakOÌ 9CO@}ŸÜ„¨QBcˈfFOýJ©Å’á»|èEª›]SÚ Uã%Å*ª¤Œ;¼Œ›E}.°ñ*‹ù ]-a7<šƒÝ½”™Ó¯kÉâÜ;£™}-Ôm[RëºíÝâBìa•¤™0ð½$aàá²5và.gÅò ‘¾)‰ÑýÅteÎÛUÕ L[­cå,\ܰµºS½‘ÇÎ`²Ûô;(«&ˆ­¹’*d-×Âì5Ìø¥‰48rðâ*}eXÌýe³r#ËÞS»ÙÁ„9A–ÒÄ@›ô¹(•?P{×õ/€ \Ìzßµ…4(¨¹•Ÿ·s Þœj‰›Â ‘S¢áDe¢ª2Ô¼QÂôgh¶émChÔ£s/Cv$çYNü¸žšÇž`mŸå؃)êÙèȃ̸ð¾»ìLf4ĶàtpУbUX÷6 p &á%‹¤µa¾kÑ»ÑÐ?£ªº$ÎŒbˆý΀5õÔýDŠ´Ë-Á5™Ú£Þ1®K)ñ{ÅR `„A€,—‘з:zÅþiïµ)¥ˆ÷‘ÖàB=šÅqQÉŽX•s>[ a7båúÛÜÜkË M¤ •ÈÌ5ê#ª`œÝÔhI¬~!ìã„٠䢙-“ì3bõóhÁEæ<Ê·xMAÇ*œñ¢ÈnŠ¢qc Ň8U…é¹Âà¯Æ6‡[‡-O§,»£Wkj ºuöV¤;È݉äKÝ‹¹Öfæ©äYÿ#€;òÄJÛj2]Îí MGªýŸÇ[ Ñ%öqoqHœº­c-VÎ’©Q>ò @jU9jK‹¸–ÆÃDàs‡A,¤"â}ö}z‹CÉ“"9òdìÒcÔÝŒÑEÇF¬ä‰U»« Öi–µKÁw(NoN¤™Ûê›3ï*•JÒÊj{âºuܤ„ øäB•‘Óï¤r³—`,2pp~¨fi臔ª§¡E®JÐŒNÀ¡Ew-O¨<ÙBš°éMà M?Ê#ž–©A6~£BŸ~ÀôlÓm'¬¶l­Þ'bÏ1 É>©Ò´ tN§8³AkH(¹ÃF`ˆçÌxnÏ íÊØÆaüاÊC7‡ƒ¹7+‘h´‹}ní6C²pÉ^þXQ«gJ*"<˜Þ-eÓF?_JFkï`–µnuÏïG5ÓõÀšOm`l;s~k­y0¸4;¯ä‚àÐ@þþ†?!ÐÇð$ýŠBÑxƒî5E°`B„B¤Ïùz9~D€²É0 eFcRÈäšG2B'ÐI4þ „Hä "!A Q(PI õSžO$§Ü²X ®HêoªLþGX®¤sgÜòGkI¢êòj¶I«häòLø¾Q ×à–¨ÚîT×ýë ž=ñÓ¨%“¹Õ@RÊIJ]G­€N‡=m“¿ëÌ›çU;™K£ÖèfNA°X@ Ô*øøž÷Øç¼ŽYÅæe²ƒGµO 7ÅßÙÈôðë‘é_öˆ†TGîÅ)tê|Z/,Å~ïzš ÌšR"‰”1i:<'€D zBO“ É6Ì"«>‰b! Oâ‘·irrü(MÂd¿«‚¡Ä(Ö¹©’V‡(Jûè¦)”vG±ú €zÈÑ©ø±£PtS ²ÉR/"Œš!²JTªG©ã4‰=¬í(lJçE“&'«,ʰ¨ ¿©2<–5Šª„Ú(RúNÛNðKܦJ “Cˆeé6Ïìù'ÔTÛ,¾O)ÿ3²Àøø ¨3¤Ú+²±E³zDÇ‘4^¸Ô*16“ûþÁ0mY.Šd¬3¨¢Y9 ð»Ìëô7o’ÞŠOÍ! <ÐÈÂÌûHçԯä„N µ7l› ’L©’<ÉÎÖ«'K&w7LÈ£ˆŠF.lÄ,ôCñ5LìûFÿ!EF“%ÔÙK?xŸ³õª“RˆB°ÊV3eüˆ¢OûÓu€ë×MxÚɹ*œ‰.!Ìý):"E”¶+SÀ ªH2‘ú¸à >V€y/ô‰ýYÊl–ÛË6…5gãM¤·dÇâ!Íסù$(dÎþ¥ÐL¬[W¨šÉÔÅœ÷O5n‹T³ø5S…$Ò¥ð»€í¼Ø‚5báS¼ëk¤î´¬#—NqxfJÕ@æ,º†5Ù[ö‡_·,¯M°)ú=aúýG svŽ+s€4¼÷g%”¥¡{ÍÒÕP§íüÒì%Éæšù\)³Þõh>Ýgjö®›¤ÐL*ðŒ!–çwâ+v;î³?A#ÍÞ­åæ¸Õ’Ö¸óäÛe;eúŽlgåú‘î’­;¶F*ƱFhtø‘£œ÷'… ^3ñ85ä(É·‘쑉_~ͽô¸–i 4&í>2¨B Hþ8¤I‡cþÖ—á+äõ.KŽû®b@ÿ­aøšŸá'WkvJþÏ£Œx ŠZçÎIÁ$‘ï›%2“# ˆÆ Ÿö¦WÒ!îyñPÉÇ•R’ 21tÓÍv;6œÀþ8q8ƒ)óB„‡¢ IdÝ©v=*Q‹…sä8ÖØ¸IäE¬*~HøžÍ,cHºž£Ö¶LC8G²1ÇOÖežìz&N™ú-WÅtÞl±¡ ÍeDÁÏëw8¡_ÌÂWéŒ%ÄJ&ù;—¥T/j?UœH!:ŽcÌî 0BÚÚU­LUæóQ3u#„ŒïÎÄt°éäØK5- .FŽ£IŸ‡IŸ­² ±ÀfõŸ’9Yd‘/då±°ÁšëΤËݾ±E äf¼/:ı~ÖRNŠâC;Šm5µUD%ªx“m‰TÅb§lž,h‰ud#ˆ5—«eM–Ø-M¤\0 á$ DͲî2ÐVØ2ÙÚ dL´Rˆ}^rC9’`«²r·^Oûù:Jèúc¾ûÈÕ¸®k:»Ú÷tf¨ý•5bù­YÄÉõTÌ}ŸàS&dé OäžX3¢ V­e:ñMo™%VÜéNîþºÆè™À,ƒ&G)µ£jÚ¢b¯íù'3Kz 6¨'9ÖÙ4¥{Ón0›á{xaN“½/4ת0èÕ}^¥^VšU`Ò‡ô¿´LïÚÀAáØpÿ(ÈVšnÏ + 1ÃxÈÒ`Ú©Y†'Ö‰„Wd‰¹™PÒÐ$šì'îD­†J­ A¤vB†ûAQGÇÎÐ+zóè:HzÇ–F1jÎæJLŽü¥ÑÐq´¾D¥^À"n2d¹CèIPdžëÝÆàJU5ÂHγ–¡élLñ,ì‚Ôäz€hHjŸ;wNòÁHFiSTÑÌ@&T{>µÌY™†d‡#™Hã”H" êhZþ‡Ñm±¦7UdÅ'-€5d ±Í}º˜÷á¸Í²— YUòL }Nf‰ÏFÉ€™ôHg»GèÕ©L³ò•^LvÒrùl:T=¸«›û6“ÖodÐwºögwf{õ$Ã@V/àûO‡}"/Ø$u³¢YÈ”Ûa`2.wà¤qïZk$L?­ãù¨6çΘOÔ2®¸V·]ÆŠ|ia±Gj|téÜ=iÆH…ÔX{ìžB"dYgÀÖ+[Ohn\u!ª#Ò†ÅL’©H•%ƒÅNcô *e|::0füÉœ¸%û=iÃ^çÜÿ¦À;83í7u^jVãëìH¾K3°s§b¥ÕÂ>à‚lÛ¬Tðo)?ZcF{Tï!>pÞúe½=²Ð¦:è©~nî9>F-&Š›Mk*IkÈÜÊ 'Ây,#&u߈ É)}À?8| ]W‘•ôHEêå¬×3jú&*éi"íkc:]ý‰/pFK‘®ýñB9ûk^pGL˜äÔÑ)š!ÄB¢m\«B—êªÑ¦žíît㶽ņÅÏn®­ n¬ˆÂ@˜ã0#FîŒÌp†$Ä%ÏÊÚîÒ5NÀ:Kü$ë6+âÊ?âX:ÌX$ÊÄr®4ëçšLJòNèØUÌþ¯, nn´§>KÎ ÞoTö®"¼²M &HBºçäm¦"Hú*p‚CæBÜ¡úRé„àŒJpš‘ŒqèÀý®lÊͬéÐ0âdz¢ð¦– ò€J¿ èn7mò—p4¹n,åÂy ¡ô€©NU)œ>J*MÍ*¾J0LÚÃâl¢ÁîèÒNôûƒð×nd(HS éÂ?m þ±Vàì&èƒòz¥†_k@LC&#‚@Ì*$Õ£†ï§“îZ²èÖuB@ Xºb…2n¬ðTcúÚÆµ&öϾàOr'æ<º+BÏèÀ(C&£ˆ*y":‰@=b°7fväñ>nÃ$€Fï&$€ ŽuÎ)úˆÐ—ð¤MÈÀMJpÊ>PTMQS H$Õ‹êˆÇ,JQnÃp&MжOt?æwÆ(Šn€üP–à©? ß#líH™Œø·°’‚øH‰à‘~ƒ¾Öêd{¯¾G%Ù X#ÉzJ«žG¨Õ1 ¡®0ÐŒh‰Cð²‘D¹ ÔÄpnÑçmŠŒcé a !Å|ËÜ…PK°4Æ1µJŸ†ï$°r*c¬Ô 'ÃúZ:¤‘…lG²J „ gp^LQr-²p2nk(éb<ïò6à‹ô5BÊjMÑ6U/J¨%ÍÖð`….*NïJsÇ\+ ÚÓ¡äH(,®gk!ŽØ5H^oåÐû&žqæøpêÊBª8Â\³f8îTn®jêe‡,ó#y ß0ê2ÿ1¾ÂmZ”ÖòÎd{±|ÏmVjNòê“î<2̉*ÏXœ§ºû±&2ÓÍ*­‰ n%çH×ÑfЧc°ž‘“Ñ£þ¦DbHÁê匰p ¢RD"㜈î\ÿn¶VÑ8RhÐä &ß,hßdG'E?f<3ð?+ ÀQHÐl¶÷Q2î GÍ&ê­éÛ# I ÑS“e8ÛGÐr€ QÇÒÊÄï- Ò!Ĉ3ðYͤÊ, #’JHƒwhOE(:½r{ ó2gi;¨í"4ÔâB8Xç5üÍ<+òôÂË@ª]/"e?bÊ+ì4gâ?0ÀIjÜâ¨ï1JôÆf¢­Üûª¢åÓ Ôb0°ÅO8ÚqÛ: ,l”NtjMf±°šön2$¥[‹/U"dï§VfÎå‡Às‰¬Áó=i!ÑâH_Tü‚¦ŒeóF¦tÂ92<·O„-’>•9A50ÂæÂuÌrTuJ·uÁO"Eé¹Oj”-„FÌiüô£¿ À ô¯¾*Í`Òh™RDÕr¥Ënïš?ï›RÈáJŒ,‚i •F·²TÐUþl**¢¾–¯ˆ!MnÀ¦¦óS—b©-̦½Dc1Aó+R½ñ@!Q×ȦgñÖ»pޱ•? ”åȶâï l0Ö1èË”«P1žU"@8¡ Dˆœ…G>£KEF<–¦±ï ƒ]í4’pê&*æƒÖŠnIq2:STÃ¬Ê þl ULñ÷*]‘'–:gf°úpv"ˆ¹Bn·/Æ“g äÊöÄn€Žbö/Ã-#C.~Úò½Ò¦¢%2V¨¶eGIPI°ÇŠ^ν"iFÏçL;âÊ(Cwé­YKÑ(`Åã-‹áfVŠfUi‹DwRBŸDâ=tŒ#G Ní"ßf“$Î…¶ê±s¦VðËFÒ¾©Ï©aÑfQ N÷UN¯V)ò¡^1òPW~УJ¢£î¦Š&Xòù5:â°œLeÃ3‡+öñ'”Ê*q®7YÍAc3|ÚÓP× íY7LBÈû嘩ÊLP¤Ý |{­Ü¤Ë ‰-mÎ4DýÑÈÀÐ/ÍXaSÚR„î+㬻lòp ¬Ô1F1Xï÷{j&«® 0þXø¨^|fg8\1¨\¥‰ì9^¼Ž¡m€æT8*°ói~å0,˜>Æ=7ÈtX.õ̦®'coÎ¥)ÚÀ¬ónTq) Ń˜Tø–¦¦’¶`õ>Ꚙ‚5tá÷M*"œ®ªÆw“q7±7™Jv3†‹ÄàUdìK€¢eÂŽ­*\+,bíåN¶Ð6ĉ .„êšVQ‰X‘b‚¢„ékºýN$[¯pÂïá'"µ}IŒ}L À©ù?Á·TFýù¿ˆg56âXoŠ˜,¦O—)‰ ÕôÄ1Èægê¦jxÒ·–¦$çE+åŒéÚ\/ó6¶y8ÞLìÍ bi6ÿTH ð(èSU »e Lö|ü ¡„ s£×™6ð›˜;„Оû·ˆË¬³6ò.¤ïdŽO zÂð3nfµ.˜qk‘9£D¹#¨o è‘M6–ük UY]©a SýWur7Î*¶U &q•kå£Ý~Æï?oK*æ+OÑ2ø©õÁìF»w.È…€…ôºÊuë M°—Âo+#ØÑÔ´¢mâå®À®ò|ü` =ÍjLQ9g<ˆU KÑ>N¾Ö˜Ã„‘*D›P X³Ÿl8$¬®So™Ð¸Z§¯%„ nN©x’‰ £ñ–n ³É%øèUR=;iû†:Ñš’2ZssÆZعºÓŸÀíIV¤Z£û’ Æ• œÇ5Œ˜”9Õb+„Ü¥Õ)=`ïškEÃèn?öˆThC¼Gs5+N— ²˜"m'Q[Tî¡òŠtÛrn4ýt §.óD€b¸…8j'øKÀÒ%Žå±C²±¢íÜÓ ´ßäc¾€&òÝÔ¬ÖìPû±S^6åk‹£X5‰\)Àw<ôxµ—RéÅËÎöÇ%Áþí¸ßëš"P •9)j¹ŠŠ.K8ù›˜·ªï™ŽÆßI´R˜ÍxÇkÄ6”±Ø1=ЉӴzñ\3:h›öA4¤û”Ý’lè^â˜M·»é61;o!Qd kLFúÓi$¼ça«”õT©× 3æÁ‘1Ž¡ö_®»‹ˆÜÃÖ;ÑÌväN…®È!„‰8|÷ËÕÖ ‹§«3*sÊTŸ»®Ð‹ÐÝ[WéºçÜý\ÔÆ¸Bá°¥FÙ|ÐV¨™J x1Ëd¼k¯N[¬ïy¢Ž ®þhÍ:ÀâtÍw‹zG©u¨=dJ­2¼œ€>´–×ÄzŒzîoYX*QIWªÊjΡcƒˆN‰”þN©“¾½LkUiUZ켜©Rç×ó¹Oþ‰E€jtÒLæï~Ê´~g¢ø×Ș‰š[s¢ùt8=Ô¡êfÏ3Úi¥µlÃ*i!Š_ØŸ¥ôšØxK+7‘"—ù•„oõà3pãh™Ö³Ÿïã±l"ð€’>Qm¢ ’”ftÜI‹ÐÙ#l•#WP;S»m6äùJ"çý˜y¦å«¶îà”¿MÝ´ÔsÊÕE.¡=ëÅöcö\Ô=jRþÞiÐc²®º,€\aYè瞺vt•‰%™/˜Ø±8ûÏ‹D}yŸ»öZYsÊ¡Y§ÓËvÒþ?à€4 …B€pØ$=þý‰CÀ‘P^>£x¨ü‘B€ÒXÔ*8úÊáòP4IûƒÅÀR'ä> Càðy„ji žA¨sÙ´ê>ù¥L%ÑH¬>eΦÏz´¬ ‡Ì ó¨T~6¥>kˆÔjSQM ñ,4©ÃfÔ(%–W0ŸÀ¨°¨Ì ašF¬i´ÂìÿƒÖ(¯¼ubSA„Ƨ° ö 4Á2–ì¨aXÁà"Qè­6Þ”ãŸ`­tS$’ÍŸXýbõÍÄb@}õÖ¬Nµ–Ø&øÆ¬ð.CÛ¡äUžü¬Ô6ãÜ¿aü8nÕð ñAü¬À¹RŠå¡u¸–w˜ÇãZÊ_ ë„Ñî’(zäý-üê3&É¢ú„»¨j>›%ÉJ\±·oû´‰%ÍbRèú`‡¥,bÜïo: Ò±:Ü¿ ÉÓò&Êsæå/góÙ­Íd.3ÉJtÑ"ìLjܧIsî-IÓÒÕ#’Z&Ô¦h»‹¸ ^&b´‚;)¤zÎ KùýK¨J¼É N* €HDÔ²@ m)KìD·5,ô¼±¼ðŸ"IÈ›-LK̸N‚O4ŸÎDPLkc2‹ÁÑ2 ˜Gn;}!nS™1Q3šF„Ìlôêö<êú*øNTÒ °¤P0'»“5<ÌQ’º& ¡­`'RÓ:«ÁüÖNð…<lõOQM %:3CÐ÷Ô/8…9Jl‘+cʆ«fÖ%Ó+âGˆ|¶ùÆ)]1¤/ôH†¹W[LZõMDö(´‚‹U!4°½XOª$VÝ)09hJ>”Ë—bê+ûÀñiM«v ‹œ·FÓm@ÖñÎ$˳„ß\d5…Dæå9e!U€•ô¦ŠÖ'ã•h-rü݈-X" 9Tl±ÖmÜVˆ00 A[­S–soŸ‰„:­ã®éh•Ò’ÜÍ®!U|[n`Ô­n÷»c…¢¶VÁ1¿› øZìúi9Z‚Ô]ÞvDy¼Â³ÒÜræ¹îYmZKSÎ:Ózi±Wγ–­…£rs±·&©4—+;àøG›eÿ™`R<]I®ÖOíd¬×Km*m4Va@Ÿ©¤+r¥o>Äç>ª颱}â ‚m6Ä:ú/̪Øìû6%zî•ÝlüÇC2Ñ-MÛÛt†Á&,ÒÎÞä=?R Ð‘oJYÓBJσ³¤ô˜ƒÀæÇÙ‹yÆÕY¬¦|ÌsYH”+WGÕ{€"H@‘5r¦V#þ$°B… QH"©YÀª$äÆÍ¬9,¥'&ŽÌœ!%{Ãéº6†ñ€ q-Oœ¨X) 0­´ö²SrÞ!`ÿy€ ‹>´\CKIkŒd•¤¼¡VÑ \P%§¸³ËqÊ>„ ·µw`,m(à˜ç¹ˆw¬ñy3óÔ©ZäÀ”Á ߣ{¸z«Ä;î‰slf®ÅÆCt  JL1,s h‚bjˈͱ²P¿ýXê@Û’Âu KÁjG΀S¨aÈ“Á‰Ž|¼‘&¸ÙÞM`+3>%ÜAm-ÜIs,Zdi(M·¶½Çúµ!éµø÷.Ë‘c"ÉVc,uk×ɘqRæEÇ; £_DŠ8ãv’!pù8†:"ìK¦Ø ´$ƒ¼ÇRô&>v/£¼²"¦á(.È,­Òó¿TŒµ™6rÃIº·:Ò H-#?,H$É> ùÒ’èTâ—²à@liÊ3b‘»©Xä¦\ÍJD½Vl¯gÅ`±ËƒJä)ü¨f¤è”±Òlk LûI†;ºòø­æ|™ç¡j!‘ æŠÔUEE)ñŸ=‰yÇ€ÐòT6>Ø×´m&k¢#o 1¯aRC8}Ä5ÝÃbêbŒš£‹EÔ{F×䙫¬±AÓÙ¼‡È•J…ö(’žƒ2_Û`d••ؼ÷À¹zï¥ÕÙ”¼bk–ÖiFÕ˜Úž“‹C;r1šÂ!ù[¬$§mµšÊO±ž©XÏIË*\EAV*+sE{µ£Ê)K\J!*mߊK$9ˆ†Mœ#Cé¶DWùÙO Ìž£Æaiñ²ÕV\s=_™{ :î?~VÈþŸfD‹µÊ|ûÔÆo÷Å‹S&"L*‘ŸâFJ÷h’)qPl­wHúk;ru$@€'-0€*äd¸ð'ƒÝu‚“”&ÖŒA™%•òîzµlË(鼯ÚÝR"`XÑ„’¢Î`© º fhŒÊ"ÎÓ›uäáÌÙ „R¿&f¯f)5ÃÈmND1× RùgVA¶Ž¤µA–ê 0º¶²,ɶFˬþ*»= ÕZÞ®Å;‚d#&Ê<‚ª Aéõ¼!q ˜Áå©@–§¡#ÕYž 4^®^6Œ–×%DtʱìÃÓ½¡Df@Óô=-²r· '&a=õÚ’"í5l Jæ´To¬ŒÀÚ4[ŒFÒJÔ³8¤Ìƒ³vùE­ª£dÍdzæ;$’Xð¦ a AàêÌÓDâìZ¿YÒÁ{öã=ÙÌ0è|æíïhÊ®1ÅÅé VA«1ÑG’Ç.í\æÅ}jLpâ™®cÜØ.r$­‰Öû¢<ä8…tÞžJV®&[K=T¼œ‰¤‡ÐÙ •ÐBi¦‡ý!ó2ÕH+*?U~îC¦íƒ™çþ>›×'Lv.l2,RJVáËî ñá§ÒŽC+Ó¿4P„–0þ´.5Ù•žš‘&J›±ù&¿¨¹¸Žã 1¢Ö½aˆ/àÌ a®5K¦œ+$ÒÉ’³7"QÆ12µ.úf«ÇŽi?¦è~.i¯К1iš­*‰é•±jÚ–èß99"‰K>²°ig²+'<’ï¶š/‡ò"¿ËÉ?i¡¡ë ©¬‘, :¶Á;êø¢,'°íˆ“ØL-3c7Êã9kŽBâ'Á¸”°…@AG óÙö¥BF.¨4qèÏ1œ?”S¥Äjk¥ ±™½£{®ùH8’‹6±œŒ9§Š)šÀle®øíÅ#z¾ÒTA ­©¾IšÅ܆9<=™Œ$ £y›;êĨ„•š,‘DšÄkç‰IÈc†›Úæ»à³¹:æ‰IK:¢‰äóP+òž#qÚ7⊠úæÇ:Ë"¼È)¿XBÔ¾,7áß>Ê®œ[‘²\Ãóɤ‰*æ®0ƒ‹вéÒóéà©ñ˜)ƒ8ƒ?—‰eC¢À¥àĺ@—€"–=Ì2¾ÆË9Z—Zòpß”–Q‘™Zꉤ1ÃW™²£8h•ÍW ÑªÂJª Ó€† R!¸ºí¢‘äK{™”˜¾s¿L:Í{|¹kÄ›„ÜL–ÔN>ÚÏ2ŒòÉ&JÚ°6|JzÊL›€”‰I§,™+"´™#¬‡â°DÓÉr§y®8`¬+eŠTÈ·¸öƒÃüB9ªøŽBcGû€š"2‰H JH~@¼’‰Y‹६üÿ,B)—d_ éiCI”„OÄ1‹7Rl(!YÀñ”(„.§³° ˆ|Í¥É$FÁÔ®x5iÄHô¿:B’<ð¸ÃQ M<‹ŸÀúœã»ÏX±³@¬ oÏÁ•Ñ=Ã'¢äÄ›a/JAykk¨!@BÒšRœ£º_O,üMñƒÂ©1“¬‚››0S¡°6¼ý/t€߇Ú9Ìã‡Ó‰$)äÒr‘2ÁÃDçâÔ{ÖÆd«ÒÌ$)I/•­!¯éxÑj™\²m ¨ƒ±ç’‚ësÁ ]‰qc¾ ÏdÚˆ«>!øB"È«³ž ºêdÀ¼HH‚ÙOÛ0Yû´MŒÄŸ —¤)wÅ´öM©ñ‘ѹE• ä¢,† )°zÿ7‚ITs×@R¼,Ê'Ë 4±‹P «¾펢½€jQ€D‘‚â‰i¼ì¤š¿·¸Ý¹sCÅ£|¬ãKºÚ»¯8G±¤ÀÏ붘yâ~!QN¶ÙÙCâô¦D½½Œr¨=…¶„@NXÇÏñVˆ¼„Jµ7±m°°¡cœRïÌœ;$è~ÔC˜l¾£ Rà@RW´°ƒ½1ÆœcF9PßR }¡U%ÂÚAYÑFSz)”EÛ&‘±9&ÂÈcÞ ©5êÉÙœ+º*ý6ö1³Õ“ªæËæÐ"Lm³àQÅRÛÃíÒɨYaˆÀô‡ y¡Jø©5f?¥Ôƒ’7ƒV´³Ÿ©ƒ½ @¥D:Êê;½M˜ ÌK$m5¨½¥·vD¢l¸â˜¢»ük·Îøï6ÝYÁÀ€;u(%nÜ$\Pª+‘àê\íX7yp4òo Q´¸ÈÔ¹KMϬ™Å­Ö·X‡×º½’³#° o9òÿÙús«e# È3:ß·a›ëWª KÛB:ص2Ëg–j[pµL Õ~ÐÊc9èß–Èü»¡ë÷B¼P;!ÅLIº(…Vüë*]ȉ<-Êë°Ó|“«ÑË»¢Â©/C(‹¦”"£¸ê: (²Ï!ãÁÀyel”*áÜ»»Ž ²ð}Æœ'»=ƒ:í Kˆ»òCÃвbËß[íÒ(ÞÂbøºÝC6ÓTœ*¨…@ KÎ*õÍ–mK‹Ð’Rµb*‘\äܸhã!à¾j\µð#Èß(¥8‰šžMâ­©¢2¢ ñ¬á" t°+$8 ¥;¥jÛŸàzd1ŽÈec€-FmjÏ!?™óhIY¢´J\Ô,Ê¢òOsjG)A–•É/;ÕÇU½¥E…ºÞ^M4LëƒÅ{Ó ~¹-ÏúÜÑ@öPC]åR#DGb¢2$Ãx~±ÅGŒMa.*¸v62iáaÜ\åÖ;ºFKêOb‚Eˆ Q‘ÇíÔ/D2AÛJbOí¬Iç·É8—€Ý¸c\g3Ë5iâ¸eN­´FÅèܤa¿@ðÌp4„aÒoÀt·D°Pžd­q$O#«er#O#uX xBú#d™›WFÆv¡Ú;ÏJUR0ЬÂ'ªD]NSS6ê¤snK^bê)Fë±´( rÆzy‡ÕÕ‹&“lB¹˜RôÌ9ÍIà ¶eo8|5°{ÎÛmÈðøêi¹ˆ KÊGÖ˜˜Gˆ#¡IJShò€4-=-Aø¥ÍbÃ^Zé4³”QA»°<,;ÇŽ#¡XžèuBd`jôÐVR;Ø·&æ+ë¥;㼘BJ3VZ"Œ{W&¨€&Žw5ùM€=:4àèmÀ(>u&õe‰¶< Ô_<^íGåBB‰×Kõ“=í ©ZÉç1Ži#ÜrÉlò`ý—."(Æ 3XÚnåSTörH³ëóý̼`5¸ÍÊÍ]C“ÈÔꥂµ)4ô«YYß!k©Q$‘”wÄÝðíêó˜=½c¤M"*í?1€IÀ/ÓEÍA€#T¾ë‚n0ǶáLÜCZ{¦³× nñˆË.T»9HWçCOk‡ˆå,tÐÖY*—Œr9×SaÃô›ëB“—pZheiöñ.Ök¬0Õ­îh½En%`…þâ{ŸTFù|Ž=ù®NÝ:lœÀ‡ý© ùAÜúFXψÐêiõ0™©&~éôè3?Ž¡àšË=cOgñçm&‚f+'•~õØmí—`”˃x·¡ßú!Ñ¥øOŠ×x¤ ¢.“à»=Þ0ÔÑR+Îj"ŽÞ Ò yÜxçÚcTF½bšèv,b_AäüPÒíµî@ ­¶·ÄîÊöÞÊñã]QÆÝÅ6+ D3ÕÂ_“e4†9ÆnÏO‡õ(GD¼’æçôè˜G´bK¯ Ðø>ï+âìeªX×o,GC¨ƒµH ᜂԷ{%C’6ðK+uC3)m#ûõÜÆf®ìŒm²7¸ r‚*"}È.¨„Ñ~¬[ Ù˜¤äBAàˆxð@€àOè  ü„aP` êˆ?bQ8€ ÿŒ#PGô2 Ã20•÷'Jdï°¶9F!Ï©¬ 7‰Êå É\2W ŽE"±ä21-C)ˆÄN—-†I@qÈäVŽNæu(0«Ä¨1 E–'ŒÆªO{dÜ UˆF,oØeZ {^k–K5uûšÉäh¼¾5„?0ÀH­SL‹ÅfèÄ®‘aºA¢²›ã=†´Qˆ¬Î½J§À€ñËcÞAHÒêYþ‰ŠÓÀˆ¾ÿ0ŽR&z€5¤H"¸ž CŽ©gŸ˜Ç/φX ÑÍãÿ­Îé"ÉœbÝeHß=X4ö<ÝL1?(DWØ©q=ào¢Ö£ËÞ£¥ª™­É[f–±, X–²ãöõ) s|ã> kºÆ±ÏB¯70Ò.ÚDŠ|*HÃÔÕ=O³zƒ7Lâ%à ° #†¬t©*N¢.˜=OC»(›€‚;©š`˜)ñþ¡¢Ã£OÛ&lû®RB/¤îÊ4Ä´4¥ 5±J.ô)Êz¤Ž>hÚô:OÚVÏëï€,Fð"ªÂ %­I,œßDîëtû®®CuIï`–¥kH ¢S{pˆ5¨¬-I©lJ-ÅðÈ!Ê Ë%Òñÿ*’$ÚÝÏê[öýɨDm=V´hâK¨ìÌ’ÈÜ¢’´È•p–¶'Ô$ö‰¹KKGÙˆŠ$Ä©”N™Û©+®1+u¹H5NmhïX`‘+·Ò"•ÖqsklÆè$☲4Ž5W´Ë"¬Utùq¼ÉÅ3CWUiýKAw]ÕM*Ž$¯uC‡óT‰µ n<‰ÜϪ zäT/Wb+=¯‡@)*&©ch“ÜüG€Hz¤ Å|ŸØÊVîV· 6‘k÷!´$¬¬Ãvéfr5­ÔÕ:X ›ÊJE:ˆ;Hóhœ¤üj¦‚V CU°ØU5ÕqÞ="5yòu4›½SÀ½¯Úê<¦êµJ4é0h7‚·c.#†ƒo€ Õ+ô»õßWØH \ŸŽëé÷Ò…6šºKäÊw½ÖÝQ -]àê}} _Ul8¨/•m¡ zžF_uì«Ó±Ý‘%dÁŠ8’¨Ý_#$I°âð^OC•0<’³rïˆbZ¤M¥À¤n"éø©÷L¶S„f¯á+š÷,÷Uªò_Tõ£ž}ÐÄ\o Ý.r’s×yŽB-”Ç7aù S"W䙣#2Zàý‡„ŽA²vôÈ#1]Œ™"4VÉ*b‘˜Òò=€„qÌî,Åc„CŠÑ#„®6«7—I*†ê,±’¤r⓾%qĽ¹ •§ ÄÀéA¢æÈ º|EDŒŠš¦vw_™nC À„1IR ‚övd¶C›qüª"›ŠæmðãÕ¥IÅÀEffe*Ä•Ë5ovÒIæ8ûf  ÃÒ z œˆ‡¡`w¢\å4;" ЉE|H¡bïѲK"õi0œ‹ÃŽD€”ƒð™ÉåJ½ +YxM¼ƒ·x1GüoÏ|÷•çØßaÉvF>¸P¾#@Véu«5} ZÄfp…ñÉÂú($X[Q] LøDÝð×¥LDý·F[¤¥^ÒÁ¼¥dñNƒ 1MÑÌ–Š¿È$PRì:T§#H3&ÄÜÌ9ð F i 5Tš;ÔZDj&ïÙc³fJ@˜¡Q$ÄœŽ<öhÚX"­,Œ¤ÈŒæ3.ŸjÖ:% ‰áPÿ_uq¢ÙÙ¹É!I„!EðÑk¢¥¬@ #¥ƒdÍ^ ý_sÍüX´*Mã¸ú>ë†y÷¸àÓ;b•‘¤÷¤Hç\kA:T†!¨• bþJôýà=ÃÑÚ‹gª9u¸¹]f@]ÁX'݈®¦w XsXmVî¾Ðàƒ—TÐ!и¹³¶"“«Ì„Ñè‚.’kMSè´õx÷Àä¹²ô¸ß˜™žw—2@ì!ƒ$@õ_x,B¯Bn˜RÄ™éܤñûQ+ô¯¥UAÉ\È$µæÆ–éœú\ÙOi@Ιç|îÝœŽ 0¿É§E&\°H‰À„bÊ$õ~>¨­Õ5 ŸŠ™qÀê2¨1Îzi2aíÚ04r¼#§ ÍÓ¼%ì¬ \ó¸¹%ÁƬDwfIH=OúŸ±‚!È©þÇ×2ã>é¶%¦$–ÒsXÐÓˆbi . –‘e'Õ dØùÄN¨ïÛÝP©t¤ÙˆòËP@›™_Ôeôé:ä­¼@%M Œ†iÂ)êÜåyE„M¼Èå/æÔ(xŠÅâ$Ó„Ô(w©à†&<c}—ÐÄ™¦Ët‘´N뢌œ"P¼À*ž^)”d¾‹-H‘ÖçÆb,Rg|t²’"GÅøÉà:Wy‡Û0ÐçŠ41Øçp4ÿ”åŸ+–-)T¢N‡˜³¯¦Ìê;#›SµQŠÆò¥}3Äe·k4à‡ @¥!—‹ÚøÐ÷1jYⳄ¼à–¿4mzœe!Îù}ÒnM Qêå¯îõ”÷îSôFH*@Ó¤ï¡aJ05Wf¤)î-“TЭâN¢œ™{vÝÖÒOŒQ‘vXJHøÒ:¨Ù_FóÐÖ ò'å€ÙÕ³Gý|k ´2o,š6JY> ™çKÌU‰ãÞ5¦NÊõŸÇ{Jí é_Iâ÷&àý5Ràî\$5:RÔ…ë¹4oU‘uä9¤Ò&g|N¬†&î¼…oøRܼKD*Á‹¦äð…¦x!úbJZHä*§í(– 6[B¢­¢1+ð9â¤&fRÍÆZÊ|<ö~lú-Žlšc|§å¤C  8"£ZÓ†vW̘¹dø+È! ÔÓz]¯Î_ Þ¦ôB¬Ì¯By‰\WÌ\Ãb†x,DãHüqÎîÂç¨ûÉt!@‚¼Ïáüý'\îZ½æÈÄKÔÿJÀ´€¥ÃÖéÅÖÔî¸ÀDxÍJ:å d¤cU Áè½§ô0Xw%‰Z¬Í8`Jà}Môv&Æ®÷ k–ïh\|ª:IˆnŠÅ,:N4ó…jJN´Ÿ-¸Ñˆ˜ư¸îÜÔ&VÝo&ÜEÚÄC¥ ªÎÈ{…ím,ØBFÍ…‚bhf_÷ÂÊ’¥ü²&tꤔIÆæP`“â.–×"¤Éë"éŠt’ƒ<5K°ÍÖÏB¤ pÔ·N´^Ð}EÚÏê–ÝB`¬Ì£ 'h¡ Qlô/@ܬDå VSfyl¬Ý‚NoKÕ (ÔŠÇ©Aü+Âæc'Ìï0HÚè ¾Š,Üå"M" ÌÉ‚hc#¬D—‘Zb$UK+!n¤íl«§ª±1þ)iVƒiÞ–)$ªÎçbªB­ƒyÅJV‚kwû('€Š¦rÖAúÖ  ‚ý+ ¬Âç cøp²Zgd®"`-£ÔˆÐ_+¦ýŒÇïºÒÍÊK…x>æ±g‚Ò¸X)â¦ï¸{ &öCÜ"0$€±k#'©ô¦"‹%vÙаÇ24}åKg®Ùcî ß(¨!ÌxÐÂ<Ý áåÜR‡ ÏksH!0ólX)ç1ij¿¨"]e-2³"„O3H|…åO6ŒÇ*ÖÓhÙÎ4…†“(Ùp´É­œ%hNÚ\q|™f¦†¼¡BhlfAëžl…,ø,.g u «Y }+‡€øêxïãIãuAª†O«#ÔÝs"•*GŽB¯Šœ!†n‰mþêÔõ4zÜ®«6i§)ËDd乆µ9ÂZ'e÷±ãMÙ À¡ôÆ0 LˆñtBÏŒöÎE?ðþ«¨²Ì. Ú°FnëÎø¢.¹k|(oÒùÓMÐ&Tʤ"‰p]3Æ bUÌ¢gÂO4²:_q“Rp±Eìr›ÓâƒpÖFÔÖ-FÉ„F2@üUF"ëT; CÛH>T‚Dì¢u¯+«–Òï7ü¦§µ7BCÄ0šSÕ$ôD‡|›‚<fpi×S#ZýäNwÂ@=O:ßrÑEíTÆÅ­÷µãNˆÕË—PLð’EM8®M2ìgr±HÝm¹!GÒçÁò©Ìá%Ô‘RÉ´–-=RŒ†'Ñ/S#L޲w*PO'B$–»j+[bʯ *ùIs iuà-Ê>tá(-Ú³”³#\-ÚTTT°Žan·]TܳŒîäø—Š"þ3ßR§€ˆÂÝLìÉ(Ôp60½S8¸lÕ‡—hS+Ò¶!ˤ¦Ð`Ä®L”Òì$±”<ÎæJ¡;…](ÇTÂè>Oy–€*”†ŸL3=Rãq`fr¬²²VÒq¶ñw1]w %÷8dxà¦qÓʺòÓãtÂî‰TLÀÏ+`&s²4#DŠÉâˆÕ<‚ŒzΈîKºààâ<Îë`¯60î¨67ÈœûZ‘Õ ÖÄ/€3 îÙïà«°C!Á÷SΔv7œ–µVÛÓõ/P§3ZÜÓzà+ËõNÕ&ün¤JJòŒ¼ÝgÚô2œô7Ãr¾ç¢  šÓ¹ˆªÍM ï¢$&kè:F¶vÀ †Ö‹{S1U'ñ,ê7piì7â4fì¾â£<æd«Q #CZNäðµí<7‚Üèpåƒ ÑÒèÏ;¶8”tÜÚ*C.t¥ ÈD¦©U.Õ+ tÑ(ÊCU1S! w3GÔó!F؇kã}e,¿†LêW/‘ÒZ¥·“O%@¢3&JÂ7ŽQ+s_Â1vL"MøóÕ†7ˆ­ƒÀ±ª©K5ê£EZØ îí(Ö”.ôx‘ªùõi}çµ>¸lH‡Ð"j#@±æ7‚Ö-Œ¾™#Ñ;`,¦f-ÔJÆØRœ(Y/xOUNírñ˜FÏ–k]L,‹ŒxC|ÈX«“ò3k«[y½H²™2‚\h+v@¡!òO˜Ø0g¡Œ²@¢ 6pšÎ#´» wžò‘„Åñjy4¯5‰ `:¶rÇüÉâ‘%::«bN…Ð&FÏ®RÞ¤f3jsSâј»ŒÌÚGSZV±1åÒ`b½=Ê -–hµ!¥4„µ ôÿnCVòŠi“OƒE‡+—jmvb­A/s_W|Kìz6oB‰e¦…\—„ƒˆSiy{LõEɦ5Âì%A ‹϶°"[O¨ "fëè—AÌGP äaÎ Ú: 1ÔœïÍ]jhbܯƒv¶‹9†óÈêW˜Ã ñ38n‹²¢§®÷;'}+›*—ʱ¹»F¢HÎ$)0Õ¥/— ——$¬ë8ieö—‡ƒf/˜igš=ú¥ G‡%Iú.$§}xçæ¹y¾ÅŠê²;\•ÆvÔËyU+—‹´Û³Nìpyuu!…y·Eü`pÒÛ} {àÙu|É/J$ êg¼âFÜ;¤À ð‰ü¨o§¾$hŒ‚ x´)z¼ê]l<'¯‚ß»©ªcV±}X—zgŠYqýx•³7¿Hô}ŠÜ_ÇT¤: Ðp.¶OíË…ˆF‚˰ ÄmÐû¦O_‰H¯ „)¥!—ؽuË,aÍX<ÅÂ¥×4µòÄeöù‰Ï5O¿[`tœÉ”»•›ÊuqdÐÐÞw$‰56w` ¯áó§f'p&þ±ü‰Äù"Ö6&ð»ÈËȉºœ\ïÎËæv»nÓDxcxÅÛ^¡¶|ç2t+±BRXØ+’Àzšb†¦#]«­¯G²ÒlE¾™+¶í ˆêzFÖ_–ãOZêíw*Být¥¤f•qº<©Ë#´öˆT‘Êzòô6`!C¥€Ëtg|k±Â2L¿+†ÍŸ@¾ÝÉy+ Mý1ð'BR;©ÃcÇÒX'U|°&kxÍ“—þ5mðµyÂ+ÝZÛÆcß $\ŒjšZЍo… ‡7ð»k5CÝLîña•Ë9pPÖ1hN·œx?y£¢…ÕÛ ‡ãx¹{;.Ý‘püÙÀ—vÕ)Št3;Ñ.x-9«S”±á’öþÅüi>+dw¶y•YuÊTÏÒJòêÁöØŽìž~DJIç‹‘rÐ`~zp±p9u€1²ÇnnÚ,:ȳ‘M߇cÍoBˆ&m9áøUäÐÈ7ÕSÖ$±ãÅÎíp%yê½´Hb‚gД¤ý–+ŒHWÓ8ø–\f§çðú8 B'Fb.„{›uìw "·õkú}œùÔ¬Ó«|]§e8ÒÒÓÙ¹=¦ù rU^³ª­½0YÃç<~m¢™¢FãLAðBÑß<¥\…ƒe&õ‹º ^Ò9è-°ææ(ý‘eq~t!µ²L Ñã¿9S¿äq.É*Išz*ënI#±}¼8§Øwà}Xb‰y£o´,»ºôB– Øÿƒ?¡HTü‡C!€8”LˆEàÏødf3}Çá€)Ný‡?"r !ý C$ñP ²3.™FfRy¬*TøŸèXœž>û¡D¡“*‡™C%“H4ºU«D#2YdÊoÓà•È´b™Vâ´¹óàmA¢‘XÍIÿq™Ôj2©”–qcˆX n½t¤ÅoQYdNðþ•rªÌ Ïf¿W_öøÕ†+6¿Fd2,&n¯‡ääÔëMó­‰ã2Àô~¼ÿ•d¬¯êµ¢¹}ÁÙ4˜,— ÚìßpÊ[k™E–º8e®Õ>âñ2ÍkäÝÝÂ(º@ {kâR]‚/‚–J¨‘ùW“Øâ½ÿM䟋†‚$©8-hcÈ’©JŠ•;o{D‚<‡¬"Bo«ð{¼Œ©ü¥è#øÈ&O ë ISx†QB\ôq•:H* ¾*hS«3 «þó¢Or±HD`%@ª‰Ž° ª\–EÒ¶.ÛŠÀAmj—* ‹Ì’Ÿ­ºD™D¨C·)¨©:–ø!ˤÂ(¨œF~¥‰t~ßÈhCÄ’©j*J•EJB.“½H#p¥Çµ Mô½.*)“º-l< ‰cîüKHT3(8®:$—3S‹!45Sº¬•(´“·CRIdfŽ$¯"'(4uàô q‹H“Êrj“¼Lň×g옃UŽì¡U£õ( g$PÚa6Rè„È.Ò" ![ Èz\tà–M*š~&Mƒt‚%ÈËl6­æè3À ´„Q¨«¶‰£¯D,”ÌLBEp4Ö8sÚìtClÃPÚÏôë>¯PÊ,Œ}¸©%yZŠõrÌÕ*² C‹«Z>™V¨•N~ej,4ÈË;¤ë¥ñ â—4ÊÖÅô ˸K¹ýyCH5"îét” ‰¼•¼;†_ :Nëx]ÖŠÊÝ0„$èš]°%Ö: SjF‰.wÛs€Kµm$´’3a³“¼2ì¬{ “»y ñ:§Â\¢àZüÒ€”V“¼‘†å"—&šïHqún$pÌ?ÅùŒ‹€æv¥$åGÒ=™¶Âî‰RPQd±¥žE´ûŸb~Ç´¿Ã±ˆ#5!P„‚(€å!³IXªô™/…ô^Iˆõ2P_QµX‚–†\{…î-]5øZ *Î]ÃrJ≅䓦æüÑ#GÈ쯼DÜ""2 •ú‚$”ƒ¨%Å-÷rÃ#+Œ­Ê ºv,i©˜9¨¥¦bÛáSNñyC¤„Ld‰þ‹oùº=Â8i¤DåÑŽÓĆþ3Lê·¶D“†‘–IiXüoëimä,¤¡A GRÁ¾GÅ-s:4kŠ¢×M3'¨x’Á·8I’‰ÏT}¶R9’ $R\Ö‘” âŒ×#åÐÅ‘&TÈúvš‡+Òé ÁÅ(­œ>p…—@ŽI̼=äî›ûŠ6Áb+Wü} Ps²^'ÐO¯,¥5d”(¼zèÈR3ÊÒ$¨…0­E"®jɵЯ¸‰6E‘!•ꪎ‹m¢ÄàÔQAv ±ãù킃cÑA•«*Gáb3Rð®´,ü\¨¤³9€"—èÜ­! ºZÉÂÆeb)mÙ(B–îe)i@Ô%:ÞˆzÞ"K<}·6€|GÚ’%HDzÄÂèj %‘V}ÒfîhÕ…$Ry9')”u•1òL)\‘-0 jó2wô„$£·:Èüæ6¦ñ!Jh¡’Àùµ ×» @DªB¥‡pîÊ÷|B™I¹œÀèøe’ù©Ëº³ÕE’Ágšw-wL†Õ°xŸq¾¼„C9†o4Mä‹a×b5·]•‘‚¸¦ñ3½f‚ÒªÒ(<”!GÅŠ?¢<ÌFN­Ñ 󈽀 ßž%ÒšÀm¢Dµ–âE/—ÅÙ9Y9\€ "„äù)Þâx˜NÑ­G ºÎ‘ú híûȬíÕ˜‘òONì¸ý«Èe:bqR†"b4rwš›Y’‚€óñ0 S¡`¦#¯4h¬»ë qtw1n!º‡oŽýÖ~Q²²7Þ^% ƒ@ ”䬗1š,êU´šóuY^ ­—XñV¼V>Ib’Îä–”O+ŒH$ä.ÎÆžI*8­û"ç2Ë!š%Æ.ŸNæ1·òYwN„ª»UÆÒ]³ÅçÖt£Ø ×Õå›™”Yž‡%wÜ©}Q »"·é“'[S å.¬ÔT‚¼ò—è¾PÒyÜÖ’ 9,ƒB.–ˆ¶çÒt}<4Í ÚÊÿ(ºàÇèqÝk£ë[›kKù䶉‚ocµ(³Ô„3. 2øfZ‘;µ<££ô¡›Õ¼ÛµÜ﫜;Ô÷ËgÝ.Qw±lÒ}UãÉPµm•‡’+´Âêú7ôf8/LC©~]šÉ©Cë–¾9Uò¥Ñ»æ@’Ú…ßV}÷…:“ Sà<ù%f6§ã"¨îu¦6æÃR®û5Ä]ᯯdy†¹l¢Ø PÞ:ݯ‹²‘V¢‡[€B26;QÊ5N%›šG÷qâGA/2³5·Xu“4°wRšWqÃྡྷ梠9>¥7Y™¦™=””?T”ä)mΕ,üѼäºxÖcLö•²(Ä º€cêc]A˜ç«©á”×D2”ýwPsxOç[Hüß $ÆÊÿDêÌç"FðÞ|6!+Êìh­wKá|#@nÖSè~Œô’'°‡SØ¡¹ä|»a##ꯨ¡IS6Kµ æ³w6h@woÒfi&;QöuWv'q<œ¬~;ÓT·#5>(¼ 2{CÍYY#K 㸠; Ô9ê¯ [ržÊf°¸Ñ°Ø~¿›œ²>ª‚&[´/3là‰³ ¢ù [™’SQ‘1.%p‰5 ¥ÂSA0ß r¤Aΰ"`œŠŸˆpâ¹ê`¤ñËгÿ)Âa‰,°šiŸÐ#úé¨ùp(µÀr8X'Büáª>ðتÄѹ¨øÌ+ß#s¥Â)³‹¥ñ¹«%¥ë4ƒ%ÁX*yM» Á3 ¬sþˆqv¶Úˆ2Jòˆàâ§Pï#Ë€3¹Ó^š(ä1ÌIˆk÷¦}-²Î%8ŽÚ èiþ&‚_—SDjöžs.q/òhʲ¨C"¨À® Æ™ÒF2ó’Rµ’óƒ<9º+%›€3в‰9©,# ÷ÀB ¡ÂY¡J÷ˆÌj¼C˜²y^²IZ8Ò'!|F[£+l,+RT1)¾Â3qÇ&ŒKÃôÒ\4¼¸zЇÁ ’vE"Ãz©®s5šñ¤¿kÕ ß–‹r¤ÒÛ¨á7@Â, 1GÃÁ¨Þº ë"‚‰•i,«À “Z“³Ç¨`‚z<*] |—°!KÈÃÔQ¹ Ú­ú½¶J¯+ZÜÇ$W‰÷;)l&óå¥daÄð~,bÓ‘BO-ë0Šô™¤ã ¨¹Y ¨À8,O¨”?Äú(7Y¯ #:òë=x¢IÇ´àƒâÁÑ¥¿jBg˜s‘´|k´z$À¦óí34µ¤áY3ؼJ‘äÇi ¬Ú0 ó;ÊÔ>Sk2HÞ ‘5Ì9<ÌÈÛL>JêüeÉ Çù0J ° 6²L7ÆpôCRm8`}¯8ƒ9xƒ¤Û›ØÃ[È·c‡éfAG¥y;IÃWËc‚Šºœéh¢I;"ãÛÄR@ª[‘ëç¥dX1q&<<6´8Ü‘[u*ymú½·bÃ<T¥ÄË%d¤G¡I,q„©Âø±¸}¾¨ž Ï“7y|+ÿ<ª ÂðŸ*ôö3ëhû%3Iy¬.t3‡Ô?D‚ѵ±ÝOT§¡V0«OKÄØ#‰^Ã"ìÚ¨ùr¼Š-?$¦ðÓP4$á|7H6D“¤àº <Éä°.ÔÞ«\s½D ¹•±‡àíºSÞ„ôS 4 „R>œb߸ðÖ¨€Á'"Ë:³ôÆhÓ®„6A‘PœðÃC@³øAEÌá®ÃÌT¹ì‡£-À8‚Js8xÑÈ,¸ í¿<*3l·‰lSKR9p a§»lÅjN2“T8¬sæN+4;`˜À¢L’ÌeŒÃ yÝ£¹ý˜òÏÔÆEê÷‰d¡{»>»(å%Í+É%T«)KRJàÅ*Ÿ yCšÇ'4@¡+FNªëÈQ¢¯˜Š¼™D™Òr@[VPû3£ N˜}KB†¯Z¢ÁPôbML3I¢OFSæ–Â1×’ªHî̄ϳâ(C#CI×›œeœbÚ¤zfÉE0¦¾2ô¦3izÖêÌxèQRVD«Ï×uJ­ÛïüL€Y’?¹AÔE<‘-²š‡!*âOÃK¡qÙ“ºÕJûÿ³3¢"ImRñuã¾TßWJõGrÔ°#mˆÌµàÏÒƒ83ü¸ۗQÉDûD|Ô‰â¸ýZÌñrŽÛw±jí¾”_›ä§ñ E Š*&U<êLhÛS«ú>è}6\L:£Ë©äòÓÔ‹ÅJÚ$QСM¯Ë4ɪ+Ó’ðº4!~±c¿¥ú½½$‚’SÚ EDšBl–Ñ[9÷RR«'Òì1ÇÖ-€$=ˆØÄy6ÀÁKr–´È‰”•“±àE£â[ŸÄtTÓuBŸCwˆbr\.S²³º€«†Û±‘?ð‰Ð"×®ªµ·{y›> CI’ê´u°³E!(81È-˜¥5ì·*0¶Ø’€v¸²ƒ$IBÜ Ì0",¡É ˆ|ûÔ˳L ÀÍ?:çÍ-‰‰9E»Ë:¤áv’݉‘Eæeõ[™^㘠 ’¶Â½³½¹ól(‚ì]¹ôL+û;Ëàõá \Ë"³ÊXßbRÒ‹ó$æÄ½X0FY÷á²I÷& µkîËÔµ´<ÒáæÀŽÿ»ÚCí©…ÆÖÈÄЉSýˆZ­êáð5uâ¾1Ã]Jf†LÑl´ä^¼‰%7cfmød ÃÖ¢a¼þdÇî[þ2–Ç€oð½ÏÓ’+Úç¦æA;YŽu^[r×ÁjŠ`¦ ÆJ؇@h1"VB:˜`Òí?žn«<¤ÙéË%öÒªŽ$¡¢Õà@ˆÄMêC4UØÜÌ¥ÃFÕ,Ò8¢Ð[SMŽÔí]4ÂW :Sqùµ<~`¥\6 –d×ò{Ôà\ØaL­sœ5®Ãäx[eĪMAkž@yZ¥é+Z¿ˆ8N>ÒU‘ä0Æòû¦+·%IdåXŒÝž¸ŸÈÕ”C%/g›½\³FgÝ£ ¦Nr¥›U.Ùþ]-êy´µ¨v±Ö’›@ç=ˆùID\3w>‰yíØ¿ç±¿·¥ !ÜI4´{âB`ÏL±‡ö$j†{ Ê/×P|ºíQÍù÷t~×j”톛¨µƒÓ&æ²ú/†öNW8{9˜vV®{Ò)õ7Ãû)u7~ÔwŒÌÊW´¿«üp»åó¢8û¢n[ŠæNÙVþ¡pZ‰ÐL'ÌÎkµs¸Û!9:g†zT<[ƒé¥`äpÓÐ;>‡z½Õ¬Ê°'¢9ðpê×d.*~߯¥›mèÒñ°<£¶‡ÉEŒjC#º"Op{~Y,ÎWžZF˜›öšN;é_*ˆ ~Á@p$ C_pð,F?âÐØÃú)GbÉR"‚¿dÈH9’åÐ÷Ü–G‹?â’XÄÖuŠ7§ÏŠRS Ée3XÌ6KMc I,Ö€øŠQ*Õz$b‰Óçsh=b7c²Mj°¸¥~ɱÒ_ÖÀ>O5¢]!vkf^‹Ò©±hž±}aiÑÚ.OB„Æ$²P6F?!±Éò j݆0®@±Ð\¾$…}IÁ:}$Ò-—˜@㘴¦ÉŒ@öP}& 0¼2ö¨>}ú âIä´ý¤6VØ?å3 <ŽO)¾?ß=z$ÃN œßmð,†Fa8†Ë€ü½&^1¤’ÀïOê}GS¸qãºèoN¶„õß.Û†!¬È˜)ï š¤ì @¦)pÆjŠ,BɃ^ƒ¾,ÚËžÐúˆâg¤H‘¢j³€(G 'PÛFÃ;ÉJF»+š,¢0Œ+.º¶(Iã ÂÀC.“©é‚°Œ:¯Ð¢9;È3@ ÝòI+&¨`‘À‘²jç¡òRX‚¤òž·+íìT¤!ªúŸC(ªvæÅK#ì<ÑÁþ¢*ròЃ¤g½ 4¡ª2@Ή҉1h/(îô¬æ¦±2ÿ$jÕ$QN’@ó$¬ZD€3  <©sè(ŽŠ"‘"(ÃŒ‚©ôÛòKhR”¤´µ(…½¨ž$©…&° š>,”k7Çðš ·%(" 6Joþ;(zjóCç²0\Ì™ùHÌÉŠê»¶U¹.¢)MÇsMJþÐ -²‹4‰K/gÑNÏ [íÞÕó›ø©ç® Þ¬H=—%);…°L ƒ ïrîžcìó•R€hÃý'#´àkã”\]&5“!ã(®Ì§ë9 ghÌÒ7˜Ý½E@”¬¦æá©»~³ ü§Ç¶ûeGJb1¡Ÿ÷Qú¬YŒ¤bé­7µü§±Ÿ™Ó˜±í\ùfWCÌà2:÷¹rúwZAµt·Êþ¯¹¬j}“RHLÜ@•Áü“¼Ê›—Ey~*);|¬Œ$m%‹;ä`I&q¬¾lU[ÕLÀB8¦ˆ²N|ÍÑnm†Ÿž€=EÑÛ/e;,i¬]†ÉuÔsEFÐaùÑg(f˜rQÃÏóq(¶on×}# ">B ¬2ïgÒ«ÂV.„‡ñK“°É<üêN;mŒ‚·-ó;®¢ép@ø~W „òÕ/À —"ÜÓÎiX}õ×'7º© `–@ÑúÛúúVh ª÷¾²œñPÄdæÂôT\S"¦0…¤?׳«pó4§Šíú¤z`ÝCTúBß0V­u¨È˜ìœl6ê-ñ·ÈYÎjÁøJõQ³{f Fï’Â<2Q¢@F‹«/okG”òƒ—|+EQ}׳‚(¡¹º.|¸7·ÔQ³xðÙt?vÃb›ÚeOðÿB',›Nóã`ëî ÇR–M]óú†‘ 5ìï¥këR-Ö"ÁŽ$Dc–MOI‘ŒÌ±>ƒäDeAy*óÅlZ×ʈ1ú”SEÄ”´öe ‰kJ]yªh|g!þj/˜SÞâü¦õn?6N^ÈëQ1Mö²Ò‚ÜÁ¸0®AWª]‘’йiƒ"Ô@Ì®zB‰2!+à$8úØh2òÐ϶ɈéS4S¥BáF•Èü^ÅLšµÅ“UBM*ë½§ª2@Ïô‰ æXÈ­ÄýbÉŠ$ôí ,­#ZLDƒgO¥zñ¢Ä6™r:Q:‘ø”Ò±m$&B:Xå¼±<Ép‡¬•Þo^zù3QÙ· ¸Üªk$= <@Ù*ÑÞKœ%ʹ‰)þFÉ* ÎãFœšJºg‹ûpޝÂÐ fYÖ˜QEwÊÕšßâCÍ+È­TAÏŠô̶Õè‡Ò„M¨æš") WÛPóå!­ñöË <;”Å”ÕG,FE$!ºÃf´¬¬£²XètÈÝqöHË“ª­'í—É)E]`A5DELŒ+ÛÁ©mÅ>tË•:àh¥üƒ¥Y…ùDp üs.í1PHìOVè±ÑûÏ}Ž!'šsUózè™…eŒ6ß6±^)ù Ší!±*cšø\³nÎ+Ôù“0¥Ñc½@ ZJÑpê‹®¾Œ ¤Êp±IƒÀiÊdë¢"j¸â»¶!¤Œ‘Ò“~jîËÁCÈ€«ÁÊRWQhz®g¬CÀ†]‡Ö+.,udó$ÂsÌŒ¥¬¨¢Êyõ]un6Ê j°t°6ƒ#‘ßhHmÎmjñÆ>AqTüH´‚茈eƒ Ð 8ŽÊB‰M8ÂS0¥Ï* êÈCÆ9ÀçR!ù0î«E®0_CHÄo‡ˆJ0¯Ô bwi­É $kŒó=–›;õ£&`öªýõ‹¤”|Cf8Vuò[u—r÷±Çg‰'V!Ù5§‡]A i ¢%3"@'ÅoC³KTäïêi¢Î3¾§×¤nb÷ëaÞ¤Þ‹tŒ_‚¶ô~†s‘F-;ºGªÉC`|rp,š*@@€6`OØ  ÿ„aO¸`þˆA¢@V-Å€q¸³ò=H_28”( ‚?cJW!€ãˆœ-7œEæoùLæ%,ŒNŸñô‚a”Ìgoùd1÷1–Mb‘XĦœÑ%5*$J•}Xf5zuc)–Q%•yD¦Üý¨Hjó$bN˜ÌeЈ•8‰Hß l$b‰W°¾­‘Y6Gu„NcQº¾ByÆÁ¨‘h• -D?/PifJq4ƒÂ*ñ f#¤–H¤wðIè4䥼Žû­¶æ±1s–‡+óí \Ó0£q±ðZ‡­­8"É3>ˆ)Ìä‘[N€iR>¨ƒÈ‰\§óiNÚSJ}o½mò ã"ÏàР´Š´0*––D¬K€à®Ècß>D󵶢߈òXÁUï]“=*`C"Ö-kD€J3Ü|©²Éf&§‚,§b¥ò«Ý)Å€ ÇLÅ®ú΂_9ÝC`ä|öƒ/Ëúš†`§Û2‰ÊÑ\vî(Zhð²P.)…ÇH„hÙjuŽø+­/,1ôñ$ØÒ[ ™¢Y¥€¤ÊvÚ‡Ûˆe;WåÈb¥hPñs߀ Ú©5â¼§EF8[¸Ä½yµ?Â&,*ˆkìNh‰6—ê LÙe»7úä‡S¨´K Á‡ä¡ÛÀ Šá²Í¥’´Q8Z—ŠU'ìJÐæ˜ª*R¢]É™J¤šà "Ȇ10è-­úûôÕ*èw:ãR>*“pÊZ̤ ›ûå‡l÷¯pÝö––1-£öÕýdWÞgÊÁV‰ŸðÂ|û’ I•hü2È Ð2†„á\¢š$/#7äºyH*R;jɺæÆÇH©D6ŠˆÁ>tàQ 2|핇@Œ_;|‚dݤ®ò&wÛy)z 8а0µ‡ªÉw/å«¿7È ÑPX¥³G=!¤,Ï81þÀK 0‡é™&ÃXY2Ä,+ì>ò w̳4u­©f°òI–pε™ ؾãÊd &­I>,·h°™Äf"®D‘©fm´DDŒ‹ ™ž/*t¤¨Ò æ‡éëZEÄ9,‚Ø[ª¬šìRÕÄN](º,ª7¬®ˆ#“;%J&ÀvƒÔ;Ó\.µ£…AÓ±÷?Ì…JØ ?À1(•×rX´“â3õ†š#(C¤Üw.Š .R÷`NRP“áè²R¢5FÈ!šf²?‰4ž$-x„,¹ ëyé|©¦sÂ…^qD¥á®rUàëÿ!Gu¶Aôh]Ù•GT‘¡rþ×ç;þ"rµ+¥ìJ\³85©Bµ>át+Yp¸¡õ@‰Óä Nà g«WZŸ o#î=6ó—KÀ&²¶éôaímt½`ÎਦDo›K4àÉaæÙ€m‹Ñ$·0 UŒB^Ð]ûIÒ<á¦,!Män™ÑõHúGâœt`5(º>IËyª.bOÑýNI Øa€±3úWGäh`ªz½Zbr%pÔÖs¥Bˆ‡ I—°m¢qö¬Ì%šó0›²Ê9@€)ߢ‰ÕñÃdõ¤peÄ‘TKjL -3%ˆ»HJ¨!Ƨ"TêɧPdy2ÀÉdÔI¡ZKÔþ3H.{ÉŒòE9êÊp/èìŽbªñã@Š}NÑZfP ð¡šc*§zY»sµ×׺’ç|üwö•ÙÖ0Eì»÷]Ì¢ÝFÇä\jŽÙÂ0…o f¶’>…äJNM ŒA@Êú ,Ræ‰Ôª¶×¸Ø}#s6‡ OrÞ¨š= µÆNö<‡°+CIWé+®è÷"a[©',Ò^Vßz±LïodíÃN|Qie” &¥_’j>qI1·¦%‘Šõ\çA §à_±Ëð,ðüw--…£‚s,0kž—‚W_—´Òåü™’‡K"bÒæ¥,7¨ŒQ ,'°˜èÚ©bP uve|©\Ð×§Z‹¥’|“ø¸§oƒ@"ÏØäŠØ7„‰ÂC'Žfê[,ñ¸ʼÁitl #ŸÐU(3GÙ#mlú•4[+KQÆ–‘(ßÄ礭.I&[)(ò‰dö^ƇVÙÃÛ£àTÕÖãê©H1ò²YòNÒÛl‘(–6 9s6ǪNr­znêÖ\k•@”-®2§—é>!Yßšž)7Òcþ* h¶ N—ê¿!-ümÁÈÜs•*À•u¤Ž$¥B‚3Àã£z_è‘W8ÈÂU,¬« ÒÚ N¥ôBŠ#ÙÌämŽGæ3¨!cs÷U_¨×›œ3j•â¨ñI;>Ë”«Ã€Óóéa"VàäÍs˜¥ ÌZ$œNΪΖ“—K—M]Ñö4={EæB+6ë´çÚ å”þŒ>müU‰ÄæÇa¤-2É98º=HƒE!ùÅYÄ8&6Sv»ã>PŹºÉuP÷©UÒ“¨ï|$›ØÄ5Ìuû" VäÀõ>ãÙ*'qO4—,†÷[ø*ÈøËnÉ %ôœ²šì¥Á-8Üé€É5 §jTRçk)Ïemཱ#åÈ•üéx¬À&=ÐÆ Ÿˆqá»s‡NK:ÜDʈS¾tüoé]Á z¯£óïg\ªüIßb&ò©iY½säÒÃ,²òiÕ,¦Ë…;„\¡À—æ*Mý"<+F&ì¾âj&µüZHfã6ëÏŠ|¯"BF=oHDé&#mDçŘ=Îü)Åì(F(mhÅ‘'³í¶þö}È·É€PÉ¢*FÞ;†¨ˆŠ\'ü£Å¾ý­ú …Òí mèè ËŠô¦£Èæ"ÄAðDã£Ä× ‹#\Æn­†¢tB¯î&eÎX*ÀîäàXj–‰,{LÌáPbs,²FøTÈÛZLÆ8æáôÖ«v$k0Í¢R€%+‚E(~×nhÆ®Ð8ø üuª’…íJüI†ä¥¢÷A!‹ü4+üS¨®Qó‡RäâLýâî{ÈP ÐN#þ#Èî{à.ü‹Œ±Šºeb­IªÏQX0…d*ªPK (œÉF*œðîb«‘IQD¦PÌì™ï0ØÊPHËÌüÉ4!‹QÎUå’Gi)ä—lêÏÆ6bþˈâ„%+~P†ì×'rš. G‘B¾âj¢B,YÂZP^þðœ{L‡ ÖoBj$ÉoÐÇÇÃ"&ÎbÌlµ ŽÐ”-|ß-Ú¤„WŒòsb#-k楋†±!É$FÎÖ"1 „\0½G|4#ÖºJ¬M)FpŒ?aö A²"ÎæTPºÒ¦\)J=«ë" K"rNPs'ÍPͧïÍ-QºÔí€d2¨El^è°Í-¤æÊª*…’dŽü"RFÂçÔ!LüåŒÐ!¼TF’ªÇc bÂUçœo†¨%ƒRË/1oL0„šè1@Æ­²d¥#²øI2þ¿EHGn,FÑ,ÏѤd~ Îž¨p;Š)US@OôëÄìb‘ ˜Nq qº%ŒžJ‘h/ïÈz®g¤\î«ß"*†“…_$à¢Iƒ'’6E ˜"œ0MÖënzYPøZNÏ/2‘@ÔéHÑhœ¾Oä Î.­h¸Òå$PС ©Ëõ a pàÅN!'³®Ãj”­~€ääçŠÐÕí›@Ž]1ß§ÌJLé«TQqð»G‚sóI-J ÈqæŠì[é^‘%Ò^ÒKDš+~‡ ŽL°“1–’“Ђ¢0€‹#=íµ#ôǦ¾ŽèîöŠ÷‡ªkã7.´ýkþp“îÛ"Ê"qH)¢RZEìǨ>ôÎ8=°ì«Âöpèë5 ´i-Õ$p¦¥A C#Ö‡J‡¨ÐÁ)&©0†/íî J HJ» ¦q™§ò¯¥¤b’ÒœÏ Rá$íŽ[ïüˆÒê÷ò’ÎmRTM ­j¨\S˜¡¢ É m!þÕm²…µ?Ro³Ž7.uT;bÞ’q"#ÚÏŽ*IÞEÓäòLZë…ÁM/Ä÷Ò¾É`š(a-ì¿FßF¦ÓÈ}ó}?ªœ6ˆf]$š6„š’á èåÅ_Glþ»D+?QqÊõqB#¸¦(¼¥dpôRöR"7…\V«V¦Ðe@ªJä  {2T®õö&fhÐáÃuRÄÌid`¿d¨@’d•¯TšµúW&+qR–I2aszY,±LB=hÏ$ݪ#H…0¯íZ ‡ÊÇ¢LÚ"MQí1cpl#Ñ-Ä ½ÄÇ —-.5Â*¶`îÜ’×.oàD©¼c‚®Ú$ì½Dà’·C)‚ZKÕCíŠ×±µ&‘_ò×Ô×N7VâfÏk<(ú!KQƒŒÎî`²+Õk)<A7B%0¼*H¸„äæïOÄ"A¯q¬ž=õ‰óú’8Ín8½H\mo|TÓ&ÅjjTbÌB~p"óÊWE'ŽYwCH*“+Õ$pXFÒNF8÷D¤ÿ %^l½ñ‘clº|¢¤b[Âq$²Î9Ñ@ÅÖÚ­ 9.’#RGŽáí…#Š”EЄåÓZ*81W_ôªÒuaíŒO‚MNå­kpŽö¦Ëe¥÷Hëà %t§Êù©Tˆî¼ê4V¤ @ƒÈkèì•-h‚QR’‚ˆ‡­;*ƾn7T ’¤ØÓÇ9`@RÙsþØwHÂrÏÓ¢ü¡øå”Pbµ pÝ–H²4j¦$å3  Ý-‰*¢S|7«ü{2,åctIœs1L´-Y)26ôclÈc¶Ú˜©`u5¶Ä)Jëùgdm|c³ MËzòRDâMF‚j†C‚óH B }ê¬ä¤ðÎø­mN°7ŸTkŠÂq'ÎJ˜øPÆ]-ðX"¤wʸEd ý§œpdNJ,sçJÕ3bO˜8ëb¥H®PŠÿë§m7ä•J¤ÂB7"®YIpäýŒ÷”‰;K’Ós‹ñ#2Fó$JJúàʬÈŃ,lŠóæ´!Vá.xN‡æ¥P!$·¶iwdçI«>mÛs<Õ0CM8…?¸4ú!óDf™¬VÄšDâœAÂ0¶¶Óêˆb´Þ÷!÷ýíëR²! ©|6ô£~!”¡ ¯ áô†j>y &Wuesñ„¢^Ö. …ä;/–,1-œãðû••7t8ØÃ_†êf%6+WíK/ÛB%IõHì~²"•Y®\ Ò›9ât.½WqeÏ3mú8Ò‘Çy*ý¦ñºW©›X(ŽNÐÚå—*Òš󹃟Ø\X+¸ç%”if(äb  ±½/BO,"«ú«,y"h“!±¦Ô#ðxÜŒ«#/ªT'|«±–ãÒÙIE0Np"Xîyˆ£RšozVÉc°à5m0Ä1W¾Ò;,·!ù(¡ì®²{^w¾M"SEÄlü3µŽD—‰/°I²±¦ùXüEIYs’¹úi&8;ùŽbvü"…AsE:•,ï±ÒØ·Mž…Âõ3Kw-³5j„ÙN¶i³^fù¥Ô,’ ¬¤Pbc…6“êCŒ® ­“Ì@ðùS ÷äPzïøŽÒÇo޼kòßk‘DÆ3Ô{W#DÌ’•æðË¥Yr“aö·ãP®ñbþmph?…@]'d‹P¾F'Å !ò^̰Œd’6”ì¦ô8¿ZÀ]6ÇEN¹7à ¸Q¤„£"J/䚺[´åºÍ·¤à£ïz÷'ù¥ã¹§©$笾¼»¹yœ'´TšZ"‰4 –Y|ºoXкÙ1’°ÑÎ$§ïK«†ù9‡ƒêW#rJ UHŽp ©°¥Ÿ¢#ñ¨Zûæ^ºÎ¼w*fíƒ »¼¯Ð#\œ°ÆÞÿ[˜òñ=my[ˆ9Ó†nRFÐNè…Dšu6D÷ˆë~G|±Oãiƒ0­Å«³¤Ì@¦|*é½G×ãàÃDbk÷Bî¤ ¶ÍLßšÕX±äÅ<¾Èîu¬RJòJŠú}¦Œ$(ï»+9cÔVm¢¿Â1»[¿râ'j¥†IÏpƒ°ÓaK.£Ác³•òZݦ©=Õ[ÙD~–À×9ÊòUç ¶#ÏöN. “Ä/ý‡™K÷€YÛÈb;æ©vÓáÛâ&:w½bw‚™CÚîT­usj}éÜ<@ˆV’© @Ûv¦|b†FÛ,'Ý’q¼¬l”$tú,;ÆÄ5!˜\DØÜ$Kýv>@?·¿]()ɼ"Ók£Û’#‚€*aÅ©2G'p¼åëB®Ù@Pór¯Cß—Ãèò~NÉTø–jEqBë½Hº²îaxÐã$¥7¯ÛN6•HD&³M—J”•Srñæ–@ªS±+%)óŠdGˆ—÷Q‘6äWnE”)Ë*M1Ê’Mi[Ì~OÄGg ä'T²®íeµ¢ôçklù¥0Ù»³W*ôM.H°GË"!ï¢8Ò3‹‚g—ñÃëzλWTGW's+ˆávÔÅ"-ìgQ?ÁÑs¼ÎW¿iʲ:j¯y¥ÖÙ8"A¹ø£·ìý*­643º¿ º«Ð½ëb_ž­{oªç…»zu³…LöÉîzµ¼ ­Y=4ú¨NkÕãCyXHjÈ lC›,«˜–!,dÕGó2œ8<6 ä ûÁÀ˜;ü „q+ô†€±—Ìl¿#²^.“BãàiSúY —Aã Ycú/3‡ÂæqP½ÿ&ŸOâóÉ,šg9‹CgQù ÅõM‰Ï¦Ð™ô^'AƒÔá°¹ ’M}ìùœúu‡ÅãoM®^®#àË•¦C3…ÐÀ6;Öùz¢Ë"q0n½ŸV땉%j;>´ÃèÀ*¤ÉªÒ'Q\tnT‹Ä_q9 >oÐerPÙâíW“NªÉŒJÿÕŸòÌVqØI­ø©ž‚C?“m*Rj¹QˆDxÀ ŠY:×®õÉ /kÈEæ2ˆ!ÐLæ2Ÿ<ì€'Pû¤vÏ ÛóvQ™÷,¸Ü4Hè4â&!mC„– ëÂÊÕ0+"ë#­éýÁyü÷·J:Hû€Ú™±ƒ,‚´{~žñbÖ½ëÃ.Œ#1aîŸ@@CV†§Ñ¬.³±ò|ï0Íz*ï0(*ð‹§M›Æê·r¢ëÔ*£é‹:šÂëb:)ÓøŸ#Šå ²L~¡ç´Û=ib} µ ÂDê'$ïrωsF佩zbÐF(4£3?¨j&Â`¼½Ô KB¨›:ÖÏÌZQB´ÓS‹˜4 £ ·`½P€“´ ÏTóãO` j™Ö²\&,„¸·Æ {0<Í#HETÛj´É§ã;¦)óA ʲ‹æ‘ØÏB3ÖÀ ÿ/Д|Æpüïa¥òcôã ”M8˜ÑÒœ2™³¨zê–+ÊZ2þQõ“Q^‡å¾‘D—Bž¨‹ü?‘RiÔt5­}ÅÓiìÃàè]žŒ¸ˆíµ|£²]eMº(»Õ$«ªn?ŠVXœI/‡ª•p$ Vz¯KÓz ާÓH]ÉH‹ºÒHFW*–Qiò¯bÕ!ü¯!ïÚ T½ÈýbÔ€ƒS1S¬D¿¬ÈK'.¤Ø=·² ñ•·bÑLÕƒk§íq î;†‰2Ž6Ot jôî´Ç´HÜ:uòΫÑsÏ'€Ró¢÷ê¨K±º ·è ‰ã©Ž# ¢Ö¤Þ£4“&4ÛX–e)ÞÕ¦Ö|%sAì:sw-¦ËÀŒÝO·"òÇðå?“”¢‹çé2^x@.ù‹/IôÈ|/MÃxÅ[M<ûè®’èèçí6÷ÜÝ>²ñ`©c;h]¡è4‚Òø¡8BY’)ŒÅ›BX¨•Ì*d$EFì F¨à·»Æî€!:yém;H(DI‹¿biÝU‘SêÜÇû}ŠqÍ;hN¯Gã\8Êñ¨üV];`éÝ/>*…WØ„gä–‚6ÌëïyŠ9’d\®ñnC%ù˸ò:dX“/O ÈÐÖ&ZL‰z{Há"õ^í1Sj°´—¨¾Ë›y?bvÀd}•+ø7i Ö)+ ’ÑTË®½áûÕb›$,q6¿°þê匄²5*LQ©ŽÃñ±A‘öÜV#† þ:$?Mz!é\šƒNIœ™MaJ`‚òõ “2`…yÒºåÂÿˆ‰h¤N=öLBVckXÐÆ%æãd¯!NÚÇ:Ì^ŠƒZÊÖ+hƊݱO»÷c`Ù\‡NÎOM¡þ¿êZx£ñ¶ñ÷0ÞÅúqªy±LT)…ǼCt2ÆgY*mÈÊ?;G ?»Ò^/̉­DÎ?Yi p†?§´Ï@R5o‡¦ŠÈ™' QjñÃJjLÕ%Óíב’>ªó B“9Òʬ©Uì„—§HFaäU÷,§{Ý ¬RÅ1XY<…>Œ¡ ç!hÀ`3¿_ßK—ªö¤‰ÑË@Û‰ z¡2.pHd¢¦ƒægV³'Ð[ï].Qˆþo§¨O© ¥ˆ©…›UÊò8}öÝßÅøÞÒ]ü~ÃçñÆ9v \R‹¦%ÛX„frÅ¡}Qi‰€ÂÕâ´+ÀÁ£ï0Nˆú$!ô!$}šÑòxgt9N¸©GA)ÍÃñz~6igie$ÑHûZç´‹Œýˆ=ëœ?~DënÞ’–)þ–UÃKàJ´‘Ö;zèÐôöˆ¸þ>ùß-÷´|:YÞÊÛ¯ýÁ‹‚üºxÄîw¥N/š¢Âƒ;Ëz¼D”=wUù™ˆº8~ýí¹-rÃ)É1i£^nxãd—>dçãz¾•B&W¯/DfMß "Füš˜›¿¶ôÆ ˦88·Œ‰^!â÷;iS Ò412Cp“<«ð’ŠË%3õ–+Ô {š¥Â œ3Ôª‹±û»’ò&³âéˆÄŽ3Ý* –B‹Þ«á–PŠºø¢¿3z2:JÐ,pÝÃ"eSä-¢×qð9S³Â5°ÊÕÁ’÷¼‹tp†ªšAK¢µà®$Ca§|0Â÷A¼@> ©d½á¾b§-š‘ |‡Ûz=º›&Qß»šÿšñ‘ú£ÒM®ãì*­AÒö¢˜Ò=@º¨&KŽ’@½ zf¯ƒµAh) c!¤,[âÅÙ ³ºô   zD>š**¹ˆ>x‘$I—¸•2Jª›s8Ú„™“¹˜³®&°Í‡Ëˆ¸mG KêÛ“–›k•FÓ+±c÷²x=ÒT›á¤iÛº"y I±ªƒLzÑ-EÅ*Í4Ò¢$T-¹‰Ä‰¥ŒHÍ% \ Æ(“â#=yú´]B¢i•Û# }4Š]ÇB­š›ãÚû˜èÚ±+¢¯sˆº,EDfëP§iäIcµ°ÄŠŽŠ[ÉDìr1á.4&ˆˆçšÆˆ„¾äª¨ˆ‹Ô#žÝ”Ùh(ê¢(Hȧ¼=ÑCB§–37º*鳜§6:æC¡:j›ÂÓ|Åš, o¡ÁºB‹X‘©'©³»ƒ•Ç,¶Èô8 ã˦ ¼t ”䲌é÷ xÈ«,4:5Ø®&JL7£¿É¢±ze ãgE±ÿÃ’·qÓ¼<ÉêÜL[-7ÐÚ˜ ½ ìY"dŸCª9¼è˜1‰Û¹rÀóv/ZP¢™Ã8¿âÈC‚ÊI}º™‹$¸Ô–“@•4£NüRG±±MM§D*ÀœË‡ém$DÊCl’‡ñR„«Ù¿)˜4ºë¤§)¬8¹í'º8ˆ·›ÅNЂňÎ("v½Ò«¶ Õ¿` CTÿª £ú\(Y0ÑE0ª¡ºÊJ«¢¢ ÃcôGψ>[žü¾¤AEÅqSM‚\?²¬1T4¶0¶ E•{}4XµŸøžMš¢½ÒÚ˜²dº0H|£ÒQ‹!+Å~§P˜³VÌŽ*ÈŠÏ /1VDj¸ŠkQšÎ#Œ³BSO ¼C³Ù E1VY5$EŽA}‡ãÑ Õj—‰÷ØM>\:OÕ[TÆ{ÁTn$ê*‘ô`Ãë ‰zž³º8ÐËv×(3Ô9b؈΢é) DùíZÌ]©,TIƒ*!Qð¥ýÊoýë0ùq4"g“ìe»D8§if¼£c!Ii+ ªr’ô>T,¿OÞl<¾ºŸž iáÒYUE‡Ú¸ Ïí.³ý(+•Á#ÏÒaa3·%céÃ: ?ð}¶ê@àâz:Š:ßž q µ*9«{;ÑDéYüœ7I Ÿ™h]{®­‰¸ªÕŽIa±(TóZÉ“¾®”)@™¶2Û°ýd;¾Neä ÙŽÐøS܈Ü!]ƨŽ-ñA‚oŒx³ºƒÂ´¡ , ³ín˜2ë!íç¿Î9ëÕVU½98¯X+ô?œ¼ÁJ‘£ئ‰ã‘æÉÛ´Áq<°;Ô*96äTD$Ã8›EP®U¦K¨ÖÍlu¡K.¡ò5ÔÔ:à%@ãÂæV]ÜËô±—8˜½ŽU¯uŽ<¼·Øs•fbcÔŠ+Bø™Æ¨Ÿ¹$¬Aº³º/Ò:YÁWÀº<É ‹ÉP„Û©áß \c«´°Î†®ži>½;€:”]3å'®¼ÐËa¾OC)6”êTMCxö02)ø° ÓÛ•>¢ã-˜è÷*€Ôf«ƒÝ¼ÄƒÚHCÕ¥¦R”Xˆ‡‘Åe4{dšPºޱµ³ Ýg›unfn½T[ƒŸ~c/}Oæì.êú¡ôW¹ˆªïèc;K„è6 ö1ùÊ(}ìp– idͲ¤óP ±Zåô‡Ê¥) zXæ¬ÔÅ”'òêît'™¤Ë–ÝŒ]ŒU?0ý=žAêfK[A†Ü‘cH W™Ä†=ÜêðÜ Ž‹‚ì«Ã¥ Q€4‰TâhÄŠˆ]Ú)ËèzC¿z«Óf=<|!ñ·R”M [KŸ}6/pÎÛÍkk_ÜKLKÀŒk_D{I¹@¥]¤üdP¾s¥Ð}»šÑ¿üáÛh¿¸M:l˹Ò8Ð"Jk_ÎÔl»Þ*›ç+ÜUj=éн˜9·c5ó‰³ÑÔh_\‰ð|JZ«u.6ï¶X6 ¢*`~bÍ^2Ø•~…á_n”ã:À瀂ÝÁ^<¼²äñÛÄ]š j{‘qœ…ˆ±µ¼Ô¶·.’´°³Lp4ÿšfgž6.l§ÓñÃRö¼/3Ý>t%É&µúÁÊŠn椌Žàr…Ëw*º¹Ž38Ô&M“'i#¬–(Ð÷©a‡V~ænX>«åXWgéÛ”úí_2OF~¢Ûµ—¹>ÇÕiæ#ÅG;z‹}ª‡Áÿ—Å6‡8ZÀØ8},Ý ,ÿ5kX@–¾ß(—nÍÕ×{‚âc­~ÊÕ¢Oîæ[ß$H§m”Â-6Dr#2Å>s»á~˜‹MHf°.Z{Æ—ÈëjW–ïöåVÞâ½ÞˆžÖ\´n^9Eš*W †l/RU/Ïvð[pF«á¯ã©Ïòã_b¬,â§ž=V$ wû»qïcꌊöK²fcʰÅÛ[Ú¯N[ÖÏㄾaAžªs52¤ô]yœ1Í YfÆÍgÖxŸŸ¢/YO÷ ®^1ýg·õœ6û}ù‚ó,–w¥É,ÕG äÜÔ ׬§¥unŒ@G®`VèU…±Þ½¸p|îÈÜtFÝõÜ[Rõ£([ 4‹îÓÊ_õÖ“VÿÁƒtÖîM·ž–ÕúEç^Ò 27ŽóÙ«g x=L]ÀÚ¼•^ÐE¡ 3»ž× Äç“•Žg¨£8°$­{;Ì‹\Áâ•ˆŠ¥ùޱÎ/â*Ð*¼ Ê,г£šl¨‰‰ä^Qâ†æ^š¢Û|N‡Ý«=ýÒ=L=Jâƒìˬæ7C[ú÷eôS< ú±* Ë´³Ï–{˜7¼‰Ñ|U ÄÊ!á7ÃsìÖàù²÷;ÝÁÉc‚?`À@ü†B€8„"$ÅbÑxÄ:'‚¢Pé†þ’C£±øTJ ý†?% <&S’?¥ yÄŽI+ŽÃŸsø”àù¢Dq'Õ&:¦Q¦´—Ð¥+‰Ggï¸í-ŸOê@jZ:ô²P¤V(ì-5“A*ð ,ÖЫѪô)lZ_¶€¨Ò¹mjlÖbÙ˜· •ÍnÅ^¯¾B£µú„J-p‹KjÀ%¡+FðÀ=w% ´ÁÚû…Â$˜€^û{…óP¯Ü1 h u„xÒÝÕ~+Á3°È•~¯Ýb0Š4[u²ˆT!ØøGzæÍeº f·5¼Åo»\§»Çì†MzSüt ‰:_r¨z þ&ªªšªíÖÚ@©#šÐ%¨ê䊮b ò" ¼,ª 2:‹4ˆR„٦Ϭë€)jZEK²~öŸïƒæ¦®k²ŠÀhÛâ‹¢L *ЍQ¸ª#ˆ"^é¼*K64£‚Ý9h3@· PJjþ¡RZƤB˜õŸél  Hhò¸Fp b‘,èªVž ò+ŸìÊ6½HçÒ„‰4 [þÐB'üX}¦¨êáLÉ#’©?ðâÕ$‹œ¨•µ) >P¨j£:Â*ËÑHÅ+ÔL²æÁôiþêKÈÁÿ51(”þ—©jctàºå IÌJ¾çÚ,ã/Ì)4áþÐ9³\¾†+ëškPÔ‹ôÐM¨:i-2¢ET¬äܨ“Ò˜•ÖµEd‚9Q‹Ì†41ô‘8“’$¸½jÕÀWGÕR>©Š‚…KŸ—¹ðÈéjîȧô"·«ô’lì‰2ÉJds ?•öàT®íŽŸ¢ÓÊ0$˜£ƒ‰à7õY3è’Ú˜ÛžúºC*dMüÂ}ðE*—Ø‹‚®¯¦­UNyøît÷ü²ƒvy¦”ÓÈO'Ÿ«Ú3ÖÎ(„£10îÆ~£¸"q= Ò¼‡WwçFØM׸¤VQ?$¬MX‰*ý2kß"XDœ)*5áÉjM½ov¶°;åtÇQv¼ñ©.qÀÀ ç ç--”æûÙº©å º¾áüu•ñRG€ I:“nWÜ2­Zd¼þcÒ·È3Br¦võGÛÞ°Ø·=c8Eaó(M(•2Þb\ª17Pa/Dbp·Q_sÍÁè’ÞŠ;åe©ÀÅòC ª·F*°ÿ¶`å€Ý|ª±Ú“"Aœkb…É©šcA› ^(EA³”’ðCA+ˆhÊYäaFuJLx0ʽdö:FÕ\Õ Ys3å1AU°Ô`ésP+zH,…lù\¢9€d9gÄI@¢ #Îwȸ‹Aˆ…"êAd¤…/%¤¬ÏŠ3NŒ¹ÀFtJ”’Î`}D—XÓˆî2H0nš£ä-/)²~CdNírËôÔoàÜÃ[Éy¼ÌCzž*m•r‘ç!’,Æž+cñ¿¢HŠc4UŽŠRBI±ŸS6´~Cåàoˆ"./«"WGU<šhþ7K(ˆ$OÑ !iÑ„ƒI’:ÛH›aY‡þ•Í’èOæ, œ)ÕÒ‰ßÑñ8a ²BÂôÀTHü¤’¸ ¶Gô’òTPR1$ôx_ÎQŒyÚ½Å&b$: O²’ë G£üÝZNÉšýc“°R==>T$¡"¤Ä Mk Œ¯iTdDßbl¡L]·’(ZÊ•k˜ *CšÎãûiRV,( ¯ÜÙ8—„Zn¿•š?2Þ£å1˜ÙÐÈÞË&{ õNZcsG's©rKV±Ä(‹JoA‚; ai_P66‘VWÍÔ™|*ò̹HûS+5E>ŒI·“R… ØŠ:lûLÙë •¡D‡Ñ™k%!t“\¬êõHZøD,ZìšÃHv`¯áOev±£b”×õÅ*Ol¤¶ºÏ m©Ô‡‡äµ€´ âûC+1K§?S QFø~öÃÔ¹BÞe€üFlî û;:”ŠÝöND µ¯xÏ‘Vdת•°ÂºzÆ»¸•'‹P|tÔØàÅÙ#•/g°ŠxÚ¹ º@¥¤éÚ¸YÕFÜZ/r÷Z”<úqá˜Ø%WÔÃNÚ1ˆü,É^Yìºúrv8”€ÂP@й-+ö¾1‘]±W ÅÅY!ê«&(ÙÌÁ‰=n2'åBŠ`{GKé4pLœZ› JÉÕ̹œy*™M"ÆaØ17sñRÓìÔ¯Âe0'Š?° ¨HOŠÙB…6ê“°c÷Ùìk%akø©7®wD’Ÿœy r©Mp–JÃ>Í_®Öü£¨ºþf _v‰ÃuI7¾e/t¹5êdñ8(ä¹²cþ&tîG¦RMXŽªë?±äNÚì*b]V®uËiš+ÿ¢ð$wn8§ZHNbå†%¬ r:úD"[ÏK®!ó=èî~$!¹4&{ƒS›·-OÙ¬Á•¦Ä%çSc£š>˶zX}иg–B¶òb¸2òBæ±ÍŸ–1W3Cƒ! ^æŽX•Ç€LvÊHd@¯ð1ÊP¶Ò_™Q RÉ!§va4ç6nµ ‚÷é=¹©Ðúh’û¼ö%ôá Wm]qG¼'·,4邱ÙnµÙ÷]ø9“&µçemKL•°Š—áàïNø–íI–žÒ¨ßf$Ú©\mÌÕuը޽·ÍÞ×p,O¨y…iìÑ0Q¨Ç½{YX´ý¿ ’óòïÈ0Jä*ÖÅ&ÉO>În¹ Oû=}g äñˆfÆÛµÎVÂ÷Ëä·…‡Oý½ªÂ¿ˆmïdËîÃ/ÜÃtñœ½Ÿ/h¬§Ê}+ °Å˜é8·jòµEzú)ÈšˆìyÏ„Cþçèäç Záúj┉y,¾‡/:‡Lëˆ Ú¤³ ˜ÆhH ‚õoméž+\U¦ã 2KÐ éæ(gf ˜ë:ò"’Ü¢’7OÌ®†KÈx’ðǦ C$€çÈäíh+éÌ”AúèBp£¯^‰« /¬ê°ÏDl«D£°2¼ƒÐnK »ƒÞ5¤ró™ ³).µp΢Å\jÆYŠ:Ãá®?„hÛ°Œk°-'ÒXŽÞyNž´¬šzN'¸äþòùi¼|B‰ ãT»ePΰhìã¾Ð¢„a2Ïð®åêãˆæg¤þvPÞˆí ºþäÒ1)„H¾4êe–ùŒt'븚˪ú+V5O²ipÉìz!ÇT’i ÍíÃklb&Pv%„†&z²1VNI8¨ö(‹¸tцø° rÁ¢ç)–à¤ä“-ìÍ©¬b ^ñDä©ÊÈàp*±–+FUzJ§Ò"GU¾`pwËö¬ð â.Ôì^¨Š`U¢¾*²£±^¶(ë,†±BE b´‘l$îº èî ‰â’ÂÕk®‘€!RPØBÚáüÔBHnƒ^ø¨ƒ}±ÙpÐ’ ¶ #qöºEý 1÷(ô¯ÏLe¨·ŠææK`ß$òoΘR^©ÅX±IFhÒ@"˘(|ÒZY)Òê ´KjY Ð}1·êÓlÆÿ':Y¤W d´Bç b0×ëÐdBæh,Ú…¯v”e¾ÌÅ)c8 ƒÐJ‹B½i¼J‘}Èœ¼Ï6Í€úoÎ_s ¦n’! K*DIÚ/ª:wÉÕdž˜èNt/]JˆKÇLï hDÎZ¬–°/´ýˆN×óDÓ,&§Mþ›É„ð^&«š¨‹ÂÌï áôÝ.PZ³:ù Û:…«"Z-3ÌhÊŽOØ*ﺩɺº±º×f(x ;oÎåP€‰$Úénž—&ÊŠèZß%§3k ‘fàéN¤¥ˆ%ó¸ú*XdPܽÆÂ* ú­72̤mŠ' ƒ°B$KDêêÎU†”ŠåsG-¯•IHÝöºÔ‹Šv—Ò×.T>Ï` Ô…zç†üDËW(vbóÞà¥*vn÷h(hÎÚfL¥“î÷ ª#òÜjZ®$è‚0fи€f.Ç/èîNMÙ!õHc4Œ²’JDÑÒG2z)ޟȦAô·"^ª“O£ ÒžüP˜…M5 øìn.r¤“%™,Eýh‚pª^ç…F±".wÏ?Â0€Hê?†å+ò×R÷fìèZÄ$D+á±UHI yÔJ¼Qö¥Žbž‘ÊàæLÐ-~’žê ®ó,xüaûk[£O.Sîbr*B®gh1óÙjåSåæ«Õ$SÈÐNrhtïüÒ²P|kzYŒºÉ ©ï>’3tÌÒn¦P`ÂDXŒ;BˆWò "Lk ñ¢fŒ,iñC* (M'L9MÏ XNGU+Ž14°EÓ ‡É.9¢:aï@ªNefÝ.Ƴë¯R´^¡ò‡ˆ0Ñ0d TúŽæ %ë "NÉ ríó† É Zëªm¦ö)Ô$M,¦!êwÆr޲£DJü˜PÎ+í&XUò(–\®A„¸*tXJXµ*\º½’„YŒ$§.ŽVÀŽç.åU*èîKÖ}-q=KÐ×öÓe’ð©â ¶ï õp¾$þå&º8UìúñÕjý-bá´ÎôÖ^„VŒxu a'Ë&¨ç˜á¥!_ç†Âö·rïõ:>x ¶(3V‘? Èš…§…PMC6óz‡bfÔdŸ»oнFÀ*f/§ÚÇ«0ˆõ‚B„uF[r1$6Ⱥ¯èøåüÞó[ï¢DSy¤M:±ZÊñ§O¢Ç©Î$ƒ$'ìðy×~ÄKY-7pørÇÃS‘_ˆ²—ŒŒ(ªÏfÄÛ)Ëa&°Š' fÒï†NK6£~G3•H*¬ÊuGf‰æÊÆó§RÕH¨äa‹vö×xÒDý5¥ƒþR£ˆfjàOëz3pzŒâ¯»% Öøp†U@â™1r¯J‹Œ:ûDþ¶wìqOf _(ÖEÒàŽDP×mÒß³¿‚Ũ°U»3(;(/‹>ôÇô‡4_ËFð/ÄÞctxêý>²°¬Cn7’¿–[{éÆ$+D»’ˆÿ†ÃÓúÐ0”qòæ±§$ ‡ÉT ‡„Šê:’ܺ sY®1•:…àI—”v»Nz[QÌôìâ2V¯Ñ)VÈÙ(t饦$F`ÈE?.2pËCp_uAþWëÑ2ëùqu¿CƒþXUúî¢æ`Æw9·æøÀYv7ÁcXJìLZZí3mƒU0jà®WZ˜u|îG— ¾î%<XÎ'œ[Ço]Ds‰3Elî]N¶)5µCÕ(ºˆhÖ¹‘¶^¡™m&€·6Ý9œ4 ;to1ë¢F*;iitò(C@zƒ Xx …¯=GÃï(¯Nß'kšgŽL+«¨4'ò_5Z(LpÄ© /6¥‘àóŒŠZ¨}$ ©ÄänCþµzíxN¢íî—ùrl0cËã3¨¬×s¡rE –z]WÖ2ãI)Š™S,Õ7fÆ7íÖ$~n²^˶U…~+æêŸí”$™b{8ôI$í'dÂÐÇ5ó:e¨Ò‹0¸¦ïûŽ”W›K!™ ƨ’«®HÐ%é/0õku‘Ù#˜"±0 Û*êÒDиª·ù ­@«W€ŒÐ.on“#ƒ3¾Õ#[£ÊªÚJ‰xòm]B% !æ+óM2òÑÄWªÔ½Y hpˆ(›spS¥XxÆ& 5}¢ATÈåœr¦¶»’UÙzÉÊ^ú¦mö¬ä½«Â…Nþ„•dÕoì12¥´øžR…¯¥Vö°޶Ã8Q¦—–iX“+Y»È;2å xÎvM¶uJB/,šŽLb`¨9a[o<ýŠë]йTFijêƒ ‹S§†vÞŽH|ëÔgo  ‚c&¢“ÎÂv3>©Úð/¨uÚòЊŠiIAãÒº¨ŠX$FmP¢C)$l±Ù7ÁQâ¤Ñ‹†˜›=z%1~¢NEÈ)JbÊüùÑxµKfî Èxà˜yioÜtZ{€®C›e÷(-;‹EpŸ”ÏFDrxH-ƒÜ©OZã¯eTàd’‘‹²­£”fhÅ*·¼dI..gÇ²Š«"ø÷+4Ž»…âÚdÓƒ/‹Ê,5r[W‰±½ƒ»Ï6gœ%|€ _»fž³V©›}m†) Ï8j¢˜XX6¹,Òh)!ŽÑÎàP!Ѱ!Tëü½’^¥¹Ù XÆÓQÝ3:Š÷¯m[n—oˆŒÜ{¨TðÏÐÔý"0÷ñ¼ìy,4zéúÍ ûù´¨ïü3|™ ›ûj |ƒ™Å9#—퓘ȗ°Öî§œ$]¥•`iGTXBÆ,½²œ„?ï»9Áÿ•" UKDý‰Nä¯7–[‚󓬗§f'|øT²îÛ…oáó‡” ‚¡«–WÍÆY—V®=¿T°À/T©µ¾.yC27rbÕ‡Ôò2°ðsœ±`º±Õ.¯´ž%½C—R\.+Ö¹L·&ÐP¯ãˆ÷ðÓŽ×+„qhÄ  „äEeõZ¨<'þhÕxÎØã² \‰ç gÆê+úÄÌ;Šô’½ë¸oñ¦÷3]z”äòêД9†l”gÜ4¥½ˆ½ž3}õSínã‘BÝŒÆHÀ^|‘ÿÓI‡~ôäÉ{KÐ3Ê`šÚÎ|§g¥,ipbÞ!ðWé!;TŽÌBC,ñ‡~›²rË„5³Ä"qݾJáãx×Þýþàò«éÞ¨àªìͺ}$9ëXv´˜ž3¸ÙÂðå†}Ý[yÉ*p3°1ú—ÕpqýrüÙç$Û&®Ôޏ’¹ûF0~T,v8X¬‚>à€(3þ ÂáÈsú! †Ã À(sð ˆFßЗì| !ŠÂ`@Ôž%’Ê`@ t^û—“Yœ2>ý„Ìä YÌ^g%Pç1¸LVg ŽD$°¨\Ô “¾§’Ìd ö­LA•Ð=}ïa¨Nd±¸dîg.©Ö$µ9í¦]P¤Â#w °I-—Q¡ð;ã`ëO`Ns…Âd³š„Ææÿ¦Â(0(”/ø†Ef5­JOP±Çê›ÈÑxÓi²²­pg9©Ìô·JfZ—C-÷ ÌWÕÒãšÙ,ÞŸ6½Ä59/3).œÝ²ñ*"] K¸÷pŸm¿Lu=€æÄžôî3X½š“ë~9ëçñÝóÇõ1¼êjž¿Nô#i*ü̧®Ò¨1©Ê>äm©þü)ʆB¨ccŸ°2¨'«áþ‹§¯[ø„&/bÒÞ$)**œ¨è2§«óîü+ Ó¾…Åiê§0›ô‹¼ ’ô?à#>ˆ1ÎP©Á¨œ²´L¦o2bà€Nyý Í{W!ÊR Ú=Ètp|Ì g =í»`¸LÜê„J)¬˜*üèýÃÓ›"Ö®Íz †*muó¢´µï2í]µÈò?Ù)ZóTÍsèèôÌÈ„D© ”ŠÒGúü©£h«ª˜ Œõª¬B¨J°»3ˆ"®ŒßÈDjµ/Ó‰£,ÊüâBê™;–j +éf©À‚‚ÌVõÛ3!uïZ"ºýoÙPªº(·Lþ–)¢é$ŒxÒù Ëíú Þ¦“Qù¤¨»Ñ‘úOBâÉV6‡$«“–F…©F€@©ÓÇü'\¢S欚˖F¥3£¹2FQ);S)+®¥s;‘õ#5ºÍäT"Ò&²62ÃUÓWdß`ðÛ´#›ŸïJ!.¦q_/¾¨ÛF~»vÏ9@t€ m#ÐÕ•-8.4‘v8h……ºR™æ Ì+ºªpȼh'>щ+2’«fß½>8ÂQ”Ìœ:ú«F¾°žðÅäÅùgü~r¼×fš¯Ç—ÎÅà<EÊÄyo®ëé.Å#lS«µM3Ñ£órÉ[‡„Џèµ#mu®=l·DÍOÒnB«­u3²b—ÞÙ'+ µ÷<Å×d Oë9(å°ÛW R~Åå&…dî’öpE@‹¿2 X9!3'Õ¾ÂAþ}Vc“‡D§"8›ž(L‡\ƒ2²¾NIìn!3ò6V«˜ Éùt•„¬=Xò­u Õ‘wÀERøn¨­_“V[‡ô 9 Å26† ,6ldÔ̰РöRêiãè×—d*×y]øê¥ø:þê®’25Õ ÏädHùÕQéâÏËHJšùP*q‘×6Ê,>å’d§2TA)@«å98´ï9»2©éD€ €¬-tÏÐ ­júd’ }®;wÂÑ Î±âI‚ *RBO†=ŸÛ(?ÞÈ ½žÉJ@Šæ²wŠZYË&ê–­ C.5T¦P OäÍá´þûfK´u¥¹VZÉÈ5ðm¨Vò9Y™Doqc†FyÓy““™úQ‡Éx’x$ØŸ…âR÷ ±J_£›˜îWVÙym-Z|:’FP]ƒb&•ÁŽ‘H’y70È”” ÈÎÄV›¤ª?«¦œ£IË^ÀnW~Åiˆ\AùHj ­$ô¨To¬ÆÒî“O&HÏÓKdž½f·2$Sýuò¼€G²ýr®ï$ŒµAøÝ~Eg¶Ï²…PÃÿ‡“œJÖá ûšËBY·Tf#K¡ÕihèœXp.%(«QHåÀYTÖpµŠãA4c¥v®Ñ¼ÇcTmÙVE¥à•ûÉv&réÖç×CE’fpFž¢°¥ÊÖm)b9™"ñM} è»_X MSgQ#vTڧ­=~`¼‚5˸ª3òˆ ­Ø/Ñuüß $‘’T®ö@#³2bÛú5¥Orù5°v¡Õ˜´íikÎ(i¶u‚»“5ú~Ã>x2þQX ÇÙ%ÑÌNR±Í³.u:Ë‡Ž›Ä íš ápO“.•¥éƒ¦{tùÕó=nøÈä²”zæÕñüÂ/-­¹…Û%dbC£rTQ†g:ÜÅ^°-, íýY~/³£cŒÈÆÉ¨dmoz”ë«äôŘY¨$_/>©ó¶íPÜ]©ø*Bš½`êð X€}œËE’V2ÜEÊ­·®€HàÝ·=F°:ްxm>èÉAP{»bUn¡›G[Ÿ$G|50ƒoW¶ÑÉý%æ÷Õ Ð8êÍt×EÞ—µÛáBêÔŽ5xîuÂB6>u6è‘,‡oä‘w¶Ì˜I$‚Bk?b4Ö­ƒý¿ÆË§È5Pu™ýÚuÌ/©¯—ëVòHü€—!»«} ZmJ¾/)¾á¬¨‰ ¿7KïŽò©ò"6㘬CÕ»Á92‡ ‘Šk¨Å›Úhžˆ†:Ò„œ³U ÀŒ¨@ ™ ¼}0zHÀy@­Â!ˆxˆ*ê4ãi'i¢®ÀŶÀ‡( šúK®Øó J.¸&;˜KÂ.c“Ð1˜Ó1Ž#'@›;‘£°3÷ ‘׉0“‘O¬CŸ·K&pBÊã$¸‹¨q#/ ù/"²9pªrÂÛy0К™“÷BŠ«.ÚÞ™ ŒÊò"º§ŸÉ>&Є83Ôí²Yè¯YÒ<+éàý)³X>³ö³Ùd¶K·‡Ü2:2ýÁ‚:™ž@cöŒŠ®žaü®ÙFR5€"k?›Š¥aœ¾`°É¬ J©ˆq©sÏ9|_®J½c’y²’4Y å%™Ÿœª3Á:W‡Û+€l6.*˺©’ 2öܽÎÅüS½©–lrâ›?áé‰Ó3\$Á¤H|-ªBºqªµº ¨œ‹ó ²ˆ—*‘¾€¸Hs~>Zæ3ØzI£Äš¢t‰&è%Ú£¨¶šÉIý;P}@»ü€Å¢ ˜³œ=+t³t‰+ºÆ™â´ÆX·B«t ¡àŸ¬«âZò4"?«Ó“&³)Âë¾X»$¨0¬Ù왂ì¹ß“œŸÈ3tÂ"®Z籡.¯šˆ®ò¨7`ý(Xê‘ÙÊž¼¨!?ÌJáêd¨¢›H€*NC:§§c ¹Y5§ÁæF•K\pA˜Aøü!óì·úŽ XLÉ©DIïŽ àJ©Ÿ¼Ê¢#þ´\Ç)ê¨2Cž³ò7Áð ҧ“j<КžÉ* è¿ËÁ1|Ð)7$ȯ‰‹ š?êR´"FÍ*^‰{éÀú¹Gö¼¤ó.‘@§c'»ïªÙæ/¤ØL[Nšâv;ê—JË¢W=ÊY ›…?ºÄ´‹È‘ø.£%+v,S •ŒY𠙘ÍÆ¯½¸ÕÉ´*©ñï0tÆó–„E)ŽFÄÿ¸¼°âiµt9 ‰t­ð} ʵ¼mH3â½E-(Ó‡ëG’Cã1¤ò&T‹Î¼‰Mäë><åÏ,J²¬ÜLÄßµKÍ9š¶¢Ö–80Úcº3254=›¢ÆÄRR|Ã#Ù®œ‰º€Ëð<'Ò•Q‰>’ydÅ ×Ó³Y¯Œ°½ÂÌ9åò…²ò1cÔU“£$i Èæ6=kÒ¡ÁTóÿKô,4W=EIBü¤ R¾‡á8ˆq²¸(ÃŽ!ø0ðâ ñ؉ìœ=ªÍ5PW}Y FÄ;ØÅÐ и×1püb<7 »sÇØ˜|›ó¡Uû\ dÓ#$ì€9Þ«;ùOdd­\=Ÿ’Ÿ,[——ÅN-¨ŠÓè°} 5AFÌéˆÍüïÄ£ºTËë_R*£ó‘Û`Ø­ŸˆüûÕd==B‡TÛÁÖÑÁ:u&0µnÄÙ‘aÊRv—ʼ\:¶ŒáÌ0„T`~’ùºÙð.ÜIÁÁÏ0è…Îõ©’XƒV@ó]‡2%¨ˆ% ĤʈZ;´¼Q¸|‹õÄ2vÅaÔø¬ ˆ‚§6U¶3Áb {̤ ,³ >-ÃÜ«Cµ¿8eW|›([@©ñš°¸~™¿°Ù7.ƒ (sTýÝ>E(-m¹Á }*ì=‘¸(UIl& ÛuIÌÚšúc Y Ù@}YVÌ‹K j>]¢Ï/+yR»ñ]HºJ¨E7JWQ•´Ôù ’êì^ôÄLÙšÏ}ö'm;¶Í à)²´Eã‹ò3’ÿÁ8 $͵ŸÕ¨‹õF„Œ+IÕÙ´¨0%˵uè)„Ͱ„Âì¯Úõ(©Èâ0ٚƽÍU3SÊkª‚ËÇX¨ë÷q¶×²êÐ1ý ²´Ý1œ J7¿MšÖÚ:kLd×/n$O„^¤”4Î'ŸÁDæÆþM Õœ•Q1¹ÁD)R²ÚÙ1Ü­06³Å8¨Hµ„ˆ®e2`Á7báãÓ{ž7L?¹|¡O•(§|üaÔùÒ@Ó#sMDÉüºd/Z=ñÖñ©P{€Üh­=tð5،̬Ÿ„ +ÑðùDºá šƒ/"3Ÿ`ƒB<Ó¯c£?ù/ÖxÚÇa™øE±F’ ·›çæQ#»#ŒÿÃއ듣-•⌿˜àó#œY¸{›®|±ÌKºohòæ ôœRSåè¼C+ÓѪ"…ÖÚ]_ H©ÑñÑ#$ˆý‡ÆÃ=Ÿ7“×Óâm0m :3­å>¾!±¦îg¯VŽ_áU6KÜ®)ôv×$‰Ö¤RÒ¬ÖææâÃ-æyÓg A‹…WòÛ¸­B_.닽Ìß&;˜¥Û2þËÖMb6*I IÔ<°Þñ¯ðŸïDYd;=®ŠËÛËkŒeè,Zgµ±¨…›+B8íÆ? pÓ!DÆw67DtoX"fÏäz«ÞJñšS¤˜ZåR›ûUâÕ‚R_Ô¤R®¡͘õÛ¿£^òcàZ»éh‚PµœN#8¹2kì4J™æ¼µŠP)Ó1á®[“LíSŒºaN[ø\“r<2jŸ?0àp‘Î@LèÒ;¾&ûÈNX×jÞ´Çq%5]êò4sP*2yùa˜;tãhW€[åFË`Ê+Î6œŒZØ >œ©¶ùÝÞç`0|ÌTZi¨«½¦[S ¬#`ÂY<™ ÊwæQ.¿ûß¶‹¿r.€—¯¸òc—›ÏVÌšv¦?¨$V;@´®dYèö)ãÅÓÝ<í… Ð5„s 3 µ§ÕœÍ˜¢Y[èàÅ>ÂåvŠ:#Ì5OTyiÔQf1£CÅYƒ:r.¼›B'f`{Ê #>åÚǃRˆŠ£ë³ÅYlMÑ"§WlÖÁ›¦r |Só’šö„¨œ<{ä»j:/¹ÆŽÀÊOÅè;^<0–¬-æÞK’þÂÉk;um«b£Úña©BßðéÝæJ(€? P0,ûB_P°6ýÄ``£þ- Œâ€î=Æ#`)$–"‹?ãr˜ÜžG$“ÇŸp9,n.ŠCÀ“¸ò}-ˆÆa°·Ôì %™FÁ4¸æ'–Fâ±hHc£F°=v|ü®Þö9<ž1'šI+ô Þ#F‚h“*­–#+”Å¡òZ4Ê¿F¨Ç UX}®)vÔ±W¸q{dn8ˆb‰qÀE«÷˜´ãŠšáîñJþZKÌ©ÏV¶S«“Dn3hÆÛß§ÀäS™H¢‘‹H SIÏÅ+0Úü–Sçö}—É@W‹Ëg½2Þ(H-ÃÅî@겞¾w«'ÛncÒš‡J-΋FèÙûßPØ$ˆÚâ'mZRª¤­óÜÄ´@ 0ç§Ê2  í²â­Ÿ BØ”¤¨Â¾¸¦OÚ¦À€#¸9 ìû¤Ž¤AlkpŠ4*“ŠÌŸðRó1Ìó¤Ç6‡òض-˜ªÀJ†£q+ë ìšìÕÀH+Šà¡¬râÍÅŽÚ(Ç+ï BèÆ(èê kÚI1&HòÌ¡H²Ç¡ú¨N$Ì‹2¨kV‡Á "ˆì¤­š(yÑ0'ªçÚNÌ'i’R°Èh¢e>€l0’¨„Âä´¸ Ð¥*ÁÉ:Œ“¹° rƒ§©ó×¾j×©Ê«Š¢F³¢w'Ѻw.é:« 8¯ 1 ê5x’"h¢âŒ2'µj!ìdö顳‹)#IîP¯³Ò"ƒ?)Ô¥,ùÁkŠSg€J3ãÆUJìÏ·òÍë.1­Nö èÂq$°ÂN¢*´UëS»2~4 I<ìÀܬR1y€ ý£b78õ!HZRäÂÄKióÌÞOGôqV'äßL§ÓÍòâU…·g!j3ú£0ˆ>oVVY ôí$‡®”Œ*¬þˆ~3í´u*€­[Pùi+Ûã«,ðF‰# šÛ¸óú°¥-h¯ÎÑE»E×Ã8ÇP¨*jÌ`#–³ÚCŒÎE*“¤ŒiGªÃÁi-5p TÎÇ ¯Æ¸Rößkà‚ß_ÖïËI¨ÉÚ™./ìŸæóPº¢6«ÃÕs:úòeÖ}Ò#¥§"4ñþ’ªª&¡q ø¨‹Ý8ÐLƒœó\€ ¬#j«ûà!<+Î`hl¤÷ܺ"ékH:O6v\ÈÞI'}UXiþÂ# _^ƒï7¢µ'Í·ºÜ+WA¬¬,GJŽúÎÍ#1uBÏ õ]%vâRy* k«‘ñ¥ÖžxN9ƒˆ¼Ô:4ÜDK «WÀ¾­¶Qâ®cYÅNÏ90.Èâ-‡‰„@c `”¨¥5Q+cfPt 6CI”eÎqšÂŒÆØÛ)Im»ÀÕxýŠLµ6åúI YžZd9ó–ÇÚê@p(òC¨¿ œzÿ"ÄÉ8¶¥ªÈ3]ä,Ä48˜ùGé)h%d$göŒBš6ÌÙ>$dt£ŒRvyã7è>£z.1¨š·YÛøÿcD wIȤw¨$¥á(êý"{JÀ¸~Ü‹ÉÙ\I¤ƒ¨Hdô ©_5h¹]#'àÞˆ¾&M¨¢† &apþe§aÁvvNâ‘UZ±]m´Ô挗4¨b„Dï “¤³ì+š¥.o9B±8BÄCfq™É©Šh #»A°¬¶ÂB]!+El¤âª_eÔx"ä6Y¶‚„ç©)„Xñ"0…ÊÚ.ìÍŠÄcÑöa%°IÙqZ™ŠyeÚ#èc‡êœ3æ:u›täÛåBq4Ãè–0*DÊ/BPúVk­¸îH©ð’©² §¦­’³.©S¹ÊtPþ›½xX;"K´Þ±¸L>Ü|±yŒê_ØÏ$Šð)E-;P˜2û¨M§ˆ-áÆ)³ eJÙªSØ}ÉD¡Nb¤*£Ä5öÔՈ䎑ˆXñ5·ÿ§•jå…L¹à¤Êí7‰EV€"Êu…0*bDÂ1<êŠD§ÛRvn†Az‰àn$â¶—µ>s)æ#¹Ø€æ%éÅN0„}ÚE¶Óå<^zÞ¨½8¼€”Q2ž›ŠvfOGW¿RYV?¤DE±jb@Zbv†+AdîmÝQ0ï‹ct 7~¼¢µ[Tc9„ù™·“û éÓó+å|°Å(ÖǦS‘òlW‚ËfíkÖ,tmɤØÚbò_›ð°ˆ¡‹‘‚®$½‰Ò&Tj“Õ #½„’VØöbj¼ic×¢n·;&êxDª±"dGId~Q1E~IÆf§±Ÿ²ª„åDZ"Õ7qðôé?õ¨d_»Ñ½¸t“,ÜF05†ÃÏC­» WÕœ@Ivºõ^üõ‚CæXÈòüÊ"«"Hɸ…¹KpâÁcóÆ[‡H.8•ÐÈý·´oÙlF©`øRSïâ%¦èb¦\W¡îíw»¤ÊüÆnÌYš.v(qeWÙXКy…o4käÑ­»ñTI¸à2òÆé=Ðíægå­fN®c¹Å4§E«Xÿa–²l€V™ 3Þ¿¼RæÆÜë§§KÏ^î:­KÙáUr1n êX]Ä?AN˜Ò§CÒ„¾.ó¨îU?(ƒpGú£FôÚ¿ÁùvsÕ¡z$C÷CV®®¿…²3VO¢ÓÇšú÷§¿öu=3Új iÐ ŒÏìÔ´F ¹Ø©lcâ¨'¿EÓõ8Q6æ¿U“MØ&»$Iõ3ÒRɱb~O‰Ù'Z¼©m­JAÔÓTÚ„DÕ”Jº½wÒj"ŽÌd…ª-„pZì¨g°8tò¨O–Ù£´„fZr©´ùbŒâKüüŒ A®h7AøuOF¼…>*Ì:+íÊɈ¯"ì*Xfë7i>rNÔNcå6ë(™ qßdxÑŒNIìz¼.„ønfcÎh¶¥¤Ó& ¹+á/ªÑï¨T,òGF^â«\È≭8œíôVÐÎ.cÇÿ iHE0àkbCP3Ðæê« Å‡À]ô•"Ù ï—‹“ –C>û­"aI¢ÿ@üŠF:£²×Ñ› e®^¦@ñBck6G¦ ë¬èÍ€úŽ®GJ,kh“Ñž§í Ÿˆ˜¨bÙB,þŠèCDFcˆû¨G16ÌÁ%PQ±TÉ£€ã‹œ ¬"Hž¯É‚ÅP–ßeB¸«¨ZâÂwÒ„.ÈVrE4èMÞGm܉‘zň+êºOä+$¡Äó ÒãQA!÷ I1(è±BÑÐ(•’ 5jüŠIê†Ïqc’ž§Î7â¸c¸CÔú…¯+.Û†§Í"üŽ ˜iœw±ÔæÅzrÄ!ãPëq­ÇB'mäÅ(ƒÍ/ºWbÆh¼;’d‰q)¨N)%(381H–ó5¡©6èS³ZÉ&aÒNöœåëÎ~iÈ§äƒ ¨r^'ÖT&¾ëÈ*ŠIá ÌÒWòØïš$«rr3`‡TÐËüI.â`^§|³râ¹2Öü¬l†H*ò5/Iná‡h“î S0gçÖŒ 3Å0;# :MH‹GNâÒÇ®GŠ:CQ)Ä )Ên;„\ŠFg,ˆUÿJpfìý Çæqçþ. Äò‹‹ú»'Áø¿1°!q¶iž«ë¼c.ò-¦"¤c©½ €ÌC4Üqî¡M¶ KšêŠ›0'ÊM¢="ñLÒjËK†üLW:Ž ªÏóG¡8¤kIO^ÃèØ®Ò :”µFQCCHŠ`0n6ójp*²vݬb±îä1Ôp°®üX$ŒkiŸ”˜f0Å/*°Ùká/SO-°ˆjŒ'TêPÈôŽ5lã>¨^!ˆqìH÷E‡°€âÈT–…4²§T÷´›5­L+´:NÚ¶Èÿ‚<ဇ%éþàÀ±̞µUt®ð¦'3/ìÔŽË{Q£­W0Æò/ÌéÔckkdêÄòîȱ J€mÑ%2ömÈz‘?µ°H2a&hí/ŽŠåéô¤ŒoÎ×ÕxPeCÑ^ÿ-ˆ“ |³ot\KÔHÔäÒtåffèT³cQ?WˆÙ‰ze¬`¢¢Šy Dn-è>Ì.f*îöT¶k´Tqå8j˜ñê賬N¨s†árŒ(ÌâuK[U¥Ä¼¨éYLãEBŒøs$âªÄAîåõiLeÅ ÔÚ¤FápæÄ’ßcž6‹Æn:L™^ôý-Ñœ®æE'3' ,sK@#9Lí9‡hµ?QK·ÇCòö’Òɵ¯Gåi!©²‚«5Lnþ,°TEìwP¦ü³Ð.t.ø‰´ÊÀ‘LqW(ƨû«Àå´;Cú<'’‚„)5‡pnÖ(Dí$qŒÞ0€™äjðˆ¶/—h•–£oÑT#ŠæL:{ñÀ{–ÿj댉ƒ‹hìšä "Î>ëê¨r´gMœêîlÔ–›%©òáÒÌòè~£ö¼ð³\«1×ͦ#Á­zâ¿0b?°à™äì<+í -wµaIÞë°!&0ÛòXð5ôn‹¶Ét¬/-Á9NVT#Â.0ÍbE…T—îÇC8}toÓ„q.ÖTÓ‰62n:¨*;6mÔª„FYB·A X¸»xÓ÷!Èöÿ¹Í!„\…PH,.¶t~䂿Åê,1ûz+8¹ÆÝ>jpkó ~v¦•°Èï4uK6fg2l!ñ>Â%ÇOŠ~¨l.ìqÓN‘Úh¯›FNi@±Ù6NˆE÷4N&¾O,² tú¸v¦¸gN¦óX7Ÿ_õÃÂÓàÄ¢±eò0ÆÂ‚»t7Úúf§×4èT£¡ý㇔Çä†=WÈíEUVøMP8a~ö@'‘œs/¨\OÛ ôÆ Lºaõ(“‹`4ë†Õ?‡v-nk\âÆ˜!2.@ GHÞøì¼¯ÑY-mƒôàz7I“]"ùuxP·ø´XìðÇ )²H,â…uF øZ­Bƒd¬ V*Ber‰^~c="8«ÆEõ?‘J^5lg8¦[™ªò!dÂÔâ±}æ1`°õ^ÑŠTnæÃ·ý~H‚{ùÇòJ¹Í}9 *k®®ëÄã]·îalžäb(”ØôJðBŠîè `rðˆ3ŠmD0– ²=£(Å ¬&ÜzV†Õ+%Bœ)+iOLéi”*Xp3 “Tk‘0óªÎ7;’!øèKTì ÆŠR"5¸}hG©Ö=QN'ÿ`ï–ØW`§òÒd‚–7m!–d02’x®‚BIYÔ¨ý΄H-”äkt´Ðc˨V½íÒkï@ò9s“Ê®ÚSå2— ÷ÌPp-Høj™Hyg«­iÒHTƒ5Sšº3öO%½[ǾåUu˜x‘Ú'oPpÄúå` w1Ö˜GŠXjkºyÆ|,n •õ±+)F‡äj°´æ÷ˆ":>€÷eZQ4>ÌÈ鯀åO‡£rv)tœ&{N©žI9’W<ŽÆb¨¢»R‚½§êo¡©9eµ ‡¤žóï¡æº›Øœs7ˆK©• –0Ʋº‰ÊEzPbö  ¯Û"àçop.å£ÙÄ쓃Iˆ¤µ²¢°öåç D´lùp$êîyEÖÿ«ƒ3º¨§ò1ó<˜ލàªø Á’‰"ùÌ݆Ÿyϼl !õDG7ƒ@»µKI”A+ã´p¥I¥X”ò9Œˆ°L~’ þG$Ò2ˆÍiQ»t¢\…ÅÑ×Kü0/ì÷JÞ‘rÏ kÖ“Œò¼%ª««Zs,òù™ °ú"Š™‡9UÄ:ÃÎÓ¸œ_W1º©Õ0#'$ûíÔ#fÎ+¢(ŠˆÞQç"òž§ÏÈö"Ð{^®¼´^ KU”ø&ܵj®¦ï°åššÙÈV&CP^´€â"¶mXÏÃÚó’“ÐépÉÒ˜Ò/V,¨F;%4©œaB8¹YÔUÏVã3Ì7U»´ž>Kª@C"ì¢ëv V8¨jºçªàÀ†Ôk|ÝC…n.#ÔYmR#¤Õ@<«Dí"7‚Áñ΃²ôÚIP¥Ä¹±8»½™‡oˆL<+ß ;*<7¸!9S1’ãVó­\ôý} ‚…œDùqBâöj”clºrV£GØlZðè'ݪvéf/"Äq|V)ÙN˜ à!ó·¬x ºF¥šÊù¾c¢Ü·KѬ%0$àg \P]}qœ¡å#IÉžIó@R (žT;0]•ì”B‚Ðs0•&ŸVòDütăZ·z.= ¤B¶™ù@åD\É:í—Œâ3ÙI$ì3ÊÚ’Ú«Cu¸×Ð"^fý" ‘k¹ÿóz¹=×KUN[ueºP–ò3ŠûNÔ©§ý-ÆÏ.é1hG[KRA^‚<8±ì#ÊîÐz>+î=×7†4­ÃŽŠp&ý¼Í²ß(ß™f±tޤà½Gáý¥ñY$9±ø¸^›D¥Ñ3_tÇÚôÕWBÙ Ìz}GBf&ÕM$»;®êåÕt»vO¾­”ÆR¢¿Ò²S“fðdV»]X8§¿<ÝÐÆu_¶5BœmL¸Š—ØåéN^¶+îß.Ã9åQ– çðƒ?!'ð?âP)Eâ0è´^ýdÀ$\õ“A€­yT:IJ$ÜÎI$|MÀÓ˜óöI ‘I#±êfû鹌Æ#H¢3u2 ù«I'q@:üˆÈ¡Ó5v¬ù‡H©ÕÙÜ*.N䔹 2e±Wf2)Ü:Eßì°«Ö.úÃ\€7È$F³ªD_öxfõE±X¡Õ ƒþó ‚ZáP,}úÿÊ5Ù‚ ]­R¤¶!šÈÁ,[*]µ]ÁN£Ñî/G¤Mß*- ¯àÄ$•ÙE²÷ëV¦8ÐÅíÝ¿‚g°+„ckÚ?áS Õäå+]‰ÃâˆÑaß ‡E ü¢ˆRvå&hs¦#,Z ÉŽÓ@ ŽúHÊ1ëÚ¬#˶(ƒ|$IB¦¹1@bþÊ’‰¢‰mDÈD«¯ø®¼- ´" BwD­š.DzˆŠ´±;§²ô$OhÆ#Ì )/ôHÜ8ët·%ˆâÄCÑB@”FŠ$‚ Òà‘,¬Ì>†1òDŒœÉ©"Êý(­`ŸqzæF's™€:æOjêDý!Pœªæ¢¨„[³èôe6ŸÍÓ;?ÒL|ÉI€ndH·=+•.€ ´çIF±ó âÃt‡IsP-ÊÒʧ&1»Ý^ªÈÛØ'mÌ:„)Ñt½6à)G"‰ÝœÊŒJ­<õò­9”‹ R;º¸¤ÓU>YÀ +=!ŽÕ7ØèôuvG÷· SŠ)ßtâ Ä&6Ü…ICGìÙmE‹£ù@` ʘ©ÓÆÈ ’h‹Ï/XÚ …R(¸êP›&é8çÚý‘"+)Š€‘X…D‹ºÇÉGëz„U 2Ë]?djÓµ:º§I†›\JÀ“0¬5Ïl¡è†?Y>³%Þz¼ž~²‘"´Ÿ¢ë¬{¿Q&ovI›(Ã-(Eþ9IÿržÕ,–`WCP»'.u‘Ó5ªø5Ú|†I¯€”Úw¡ÌÀvÒ:'3 '3M|YGäšÇتzŠjÑ>T~¡Mâ))\)ùɸ#ëˆ3l…E Ë1â ÚíËãõP¡’+M6ª‹êH2Ê”b;7Moѯš}'ض(Õì u#Z€WµÞ,½æáwÐÀ¿¿™w1ú‚ù@~º³˜Ýbyý«3ÅPüOs¼tcýê'~I‡©°jèÉ”™çÌLL¢81ÕÀCÖ„Œ3¡H)8Í£ˆ/ZU@ „Et°C$@”Rvrd3$…²>ÅÖŒR?n-ò™C¤ðT8$¨I…UmŠšÓ§ÉM³å9•¼õ»TÒ©¨¤²&nŠ8Ô~s!tS€5þ?˜ôNÄ£6MÈ2#%tø£¹ç–dƲÔeŒ1(g‰î UÌê@ûµrd1ƒbD¡ÄBˆbbQT<9#Ê舜†ìvmé¨WïÕ –Íl™N9í£€„ AŠ+驦C•ÈVU—JeqyLÆ7#66Ñ>©µò‰í̽'-Y±,òˆD„±<¡I~B !bšjI=½yn‹µo•—>ãĤeZ“Z»%™Ykƒù0;2ŠÚ¡zh` v°.²ùyª®Á3ÒLÚJAq÷s yM£ˆØ¶#cÄXµÎý<óÄG‰C@‹øÞ±0xœš V‡­Š£®8ñe$¬s™‘ñ¿(vòï(jØÂ…&üÇX,£jÕMJÊ·H§ŒFMÀàø0‡Lúñ Á.¢ï¼¼‘—–‚ ¡¨:øE/,ÏÕ·§#÷ë;–}Ó¥óâøšâ)€ƒ˜©Måf±Šm4T=~íøÝe»ã`½T7LñDNµY„i°ƒîÛºN¤® w–+ºø›FÈ3¿Êtº@€6í6Q9æ ˜êCç#m>”>6‘µ¢µfi8Eè4™ÚË8Kvå©…-0+õ铱!‚Ðî,Ï£Îr3ö±ï©C,ö? Ÿ,$äÛ3Ç6²F€™,Ê“ÌyçÒ`Ñcî_^¢BÑ vm©lT£¾’6¤µ‹‰œ̼Q8ëÁn•(õ®ç¼>ÆçE ¤âÝA˜ò´¹ƒ\äõŸM0Nz»U4ÒG“ˆØúy›ej䪻•ôPÑìÖõ”gä6–Ò=m©]5if‚÷•òËkC9ÚÓÃqH|·D¯˜la«d¡ªœkddJ:Yúcñ&áÔ÷„Z·-x„‹ Hx“àõ1íG¸ãu¥x§± ‚ ªì²ÜyÙlXZ&¼.«CƒòÕ¤ôó‡ë¥-µƒŸYnmœJàhqÙ3ÍÎx~ÛçIˆ®sÎ&º¡ñïO=47hɨ-^D‰|W ·ø†Eµ¬¬á^ -‰ä–-1Õ:ÍÛ=xeXLçNˆ®à<[ªž¡9ŽvkÕïeeÝ?)t¨ 96¯0ÊÉú;;õi„v¹û¶â>ŒF®-îLÝvÒn³QºjÌvü6Ò1‘ûª¶ë³—Ê)œH~;»Ø‡ù»ù ãþ1ÂJ–›¦7è±;¥ŒB¥5ž3“­Šê¥ ³a-—b¶£ÚÓ–«l YÍ<ãBŸkM¢«÷;˜Ý.CB ³;è‚@X§ £&ÙM³Iñ®¸Å`®»‘/º7 ˜§)¤µ³‰<ô&»¯'û³‰‰´Ž±‰Ž8›¼éMˆqÈ[ï«<ór4#¢¡#›iBè§™°ÀØ:ІÔBAe¾è™œ°ÔB}ŠL4˜†°ÛD8 kÅŽùÛ”•·9ˆ‡+xá•pýŸ€’Q˜Œ0着r3@+Å’kô=!u+áU–|ÂØ{¬Èà h¤/€®›&©?±2ÉÀB„¥£+Ÿ+Kš)€!r÷"Æ*{²T€!§ ‹é#!õùˆ 5Bû‘æ&„‘Á«"éI´0A1‡)B%â/ƒp<‹bÁ‘¿Ã‡Ê B)°]­ø›Æ¿³›z§)Q¢œ_¨ð7û›Æ9Խ˯£kV„'¶QbF¬1-ÃlƃäêIšŸ©CŸÒ,ž$ ¿Š†¹ qíQ«@B†£4_3 µàš‘9<Ú)W‘;U½17ú* 4ž#õ0Iˆ6ëÏìM‡Ð‡ø² ³‚ް§!añÀÍ¢™O€Ã+;¦1¨¦ƒ @Ê(iòŽ ©È¯À“µ¶Éì¤òóq3d)ë«S†â’&!hR×Ë4 “»«Ð0“€A*@3q=™&¯ìK” í£QK‹ª5)ÍœìÁŒi)h~KÁ¨ëÜ›,¼Ðƒ;sâÃ:œ ¼ŽD´ª ª°²U–)â!rå-ƒ3ãï‰35Ž‘”Ÿ|#L*…Á€ËÃaHtűXÍ­ †LR¢‡ÄEƒhF9½­¢)Š*L5À˃Á7+ç’Ãú5YßÑ09hŽúõH©{¢È‘DX;Ÿ¯ûÞø¨èó®Ü±¾q=Ÿ²˜buô¸ B:!Æ—tB$¤«¨dD–ñj«RKÃñ]ÈÙøëkkÊä;1ÚŠì1ÍÉ€Méâ#ê*ÀÀ« y¶4³¥¼Ôª Š@ïÏd¶’F+… Y4Çd† ä #,;¼ñ|Dzj˜´ŠL[ÊÌÃùÐZ#¹Ê¬¼|Ñùh?é•®C«DÈëÛ}¯›‰Á¢º¾›¨¹h?Ig ¼VJB´¬ n¢‚T.“åCÜ8¤¬[R©[9@­™å/ d)ò“DŒ^ÈP|ÄaÌ<ê¥I€ИÐ+ŸÑl2h±I3-a&´ÊøÃ+î;·êª"ƒŠ-A4Ÿš›€ªq™™Î»)ìIGJŽùwQ]„ ’:³²ˆ»’¶Hø›͘Özä#ºª é]¥dù8ì $¤Ñt^ë9:µS³ÒÈxŸ'ðNjÑhÔ¨Ä*¥$ªI›ôcô1›QߌDëH„ƒŒ…t¶!ž>€}‘ÂÆ•YC¬™ù]ÑÔà³|3] ‘ÁQA™åK9T44¡2ÚÃKÈ:Œm:søºÍˆºa½íi6<Ç“Çë)„n!ô:¦áUZø=œœur¢‚ÆC³ØÃÓ`Ó<#œkÓWØÃO^@B²Wƒt²øTŠÐÃ[R<¡WËÌ· à öY²¿"+ ¹ùÉY‹Äø5 ÑlËà€3ëÁÍ6­r*Hú•ÃÊc+8Õ o݉$C$žúÚ©‹®œ;Ô ø$í¥¼Á˜È&ì5ÕnŠCGÖ1Á.ÐÔV¬l]8Ri ÀœÍV@ÃÀB"»Qš¼ 5ÕP|“ÌÒ‡Â8ÊÜ̶+9RL@Yé²A½Þ k©"IÔ§{š,CÅнk› àñw,C'ü‚Åd½Í%M°«`„˜µJˆ€ä4}þË._ùóEÛ³¶“P"ÝÒcqÔÂ>›ÑÙ@8ÌA1QZ:® T-bkj‰ÙÙ‡ž/1ߨŒ˜úwÏÛr6­ƒÚÂh6‰¿$Ãܬ1‡~9 ¦­zH 4û*»R·PÛO»R……"ªX¼±Œ –D„&Áö]PƒP­Õj˜ë  ,ÄKõ+Ó…·Rd`È0¬²"«N{ú¼ù¤"mñYMºØ¤2¹aµBgáOKkPD˜ÃK9=EõžÒh;:ÕÕ Ê#c»síߤ4GF)î)³è‹«1kµ³¢ÝÐ5ʹ„ZåQ  ¬5،݀ ä,³ŸM Í +  ¡å¤6XäAûÒ^´ =LÊs×(•/âÛ_)ԗ͵ÑÝ1ìƒ'è÷^ˆîÅp}@Bj>qb»” §4àŒt`T®¼…‚ÜKLJò·è}LŽDÇ9IøM­x‘¢œ!GX„þ„U)òàf‚2E»›ñEf7Pqöã]©Ñ¹åÉ€1ñaÚ˜äÌÅ94F£Í‡ÏK—GË@ž¶¦Ôâ?™«jj-°€÷õêk;=n=›Ù¿¢ ¶¤^q+Žda«?€Ï•ìÕ^ŽÙ)úØùÕÁ•Ò[¹£ë-‘­1ÖÄÇÒ;TÆi±]ã½*Ž˜ËSDKT¶](@ÍÀ¡„^{jù¦Û‹­C&‰Fh‰Ì_þä“cH1ÙÊt×\«Ô5Nj)ÎÄî ,E«éÑLfâïGñwi‘]P,ʇþ‰7œîMÒˆ‰] *®ŽÒª wßö(,òC¬™ÚŒ*®ßÞ«Î!b£4:VÌ+Ø)ˆjo!bÀÈ­_رKÈe@gœ>1TU.Ö3ú,ÀŠ+-É%|µ^k¦Üæ•.âö¬ˆ£ ÅÅüc=óÞh›°®²SÃ.å.º”½ û~äÏ Ë¥‘‘µ s"£þCêQ4 cv[”™>Cœn ”­eð›»·èïÜF[ît [$)i¡€K<ÅëvAÈ)E½½ôáÔðâ<¹9hÍ—‡âÉ϶™!ê⇔ûEbøg-§®ýq°LÇÕ°«FJ¥:È} uñ•UåЗr¥UŸ6–Ö7î)Z%˜¤©ˆ-¤ gú4‚Y=× †fhdæ¸Ý11M£Ÿ—v éO#6;‡­{$ÂÕ·Q&Á ú˜BYÛl±íWlÞ Ʀ·ßˆèÉ@½CŒoˆÛ@C„ŽéObµ^e™ö:6s²bçÖÄãXÕáu8Éž7Ç^ˆ¥Ó“&¦Õ}yÚËÁ<îN¼ÆoN#’¸ˆŽÒc>Å‘­ÌåÕ‡¿<€1âs Ë+Œ—?dÁI@H¼ø’iµDúîSýI•mŒ˜ÃWXë^;&¹‰|˘LQžcZIeˆÍìÞù:¶¥ã b“RÉUÍHõÛ…lǰw…µý^L#-“M.6Ê•Žòx‹-5ä¢î€¿üÐ>ÜÚ±Z9ÿ[¨5°íkùv.y¹]ï15º¥n¡4°ŠúrñÏ{Æ9@e‚Þì= ¸Vn§Iæ§6vA&kål;ù|žs14§(nzoÜ8v¬Áër,ÆJªtàu"¼5ÄFt+l1ÒlÊ=ÁÅÔŽqÔµ«áCjÙ¼rP\°‰¸¢€òÁ DBh€(¢‹-±fáûŒŒ~1±E–Ò ³—v ôl H›ˆù‚ ÏøCfû†¡Ï¨€ %?¢ÏÈÄQû‹?€±øÛö$ŽÂñð(UŽÈã²  ŽQ#É£³X@u0ŽÎ€q‡äúM(|Qds 40˜P!ÀhcîL ª<êÕ@L²-“I¨¯Š|Âi¥S¡Ô©,"aJ¥HéRiòºVŸÓéõ>ŠGnR}Urák°‹–%o„HäÑÔ¢;½Þu(¿.­À©TÉT†[ÉÀ§‘xÄúÛ‹ƒáõ`,;þaQ‘ÈçÓxÜša( [ ÑI…~B â<¸À¾EQ!Õ[ê,Rû\"Sh¶ýIÖ¿ñ•ܰÊ€ô`+EÚ-Ÿ•xduû0×±D¤9 ä#¦þ±¿iM²•:ͪž{ÀÉêt§» ºtò»Š[Ú/È#lÀL:òŒ÷‚?q€¸¨ÆKÛìe«I4w¾Áíz)¦èÜka>Ò¨"ž¨¼;Ÿi﫲ŸñX[]Äv(;Á€7L‹hˆÅ„IÉ3‡f@*; ˜mÞ‹6­#Öƒv VE(7Ë[áÀåOÛíSÑf†e"¡¢$ÙÀ¼.†õ‡´§…@2C¤©'+çhý Ò/}”§4ØÐTYÏâFTK *8DmL!",TI3P)E|”&3vGÜÙ ŠŒ•vŸ‹’©CcÒ /ÔÊ\–ép±á?#´ÖëH))£²Ä@yZKºmŠýk7ňÐM‹õP¨½ôèú°p 9?@ô¿ ‘šp~4—ÀFÑÙ!;äŒÈ…ñrt+¥Ê’ˆÂ^›L‚‡ñöä¼Pê8Cgh“"Ò ‚ÛQJ!CeêÂF~Ì”+!¤<ˆ9pÿ‰Òc“¬ä‡<ˆqãy‹Í}D€ÀÃæwèÈðÆ¥•)ÐÚ>0±ØƒFBó_Rû@ÒÍ_ Ÿâ 5*Ø> ˜ÓX<¦½²È"òsjBCÁldåÒ¼@BMnY¥;ŽRE$£Kö“œÓˆAPÑ©®¢´ú)qÌÒÀ‡ñ ᥶S¸>?‘Ù@t4И[ÔüéûÁuhà[{ˆboµú?0¯Šæa @Â׆ö¢3÷d$u96Ù>œx.ÓU„#*ÐË`Jý¯b«€DÎË”u¢VÁÛ^ÂêûlY‘Nô …S©œ^š±ÔÃqÀíNe¦îÎqû5ènñ4ÙaícAU˜œ¦4ÙO§ãùTD~f™r‰K¡Ðèº#^c䙕nž[Ì8¯8‡¸Ìå¤# ë›)ˆÒ3Å!Å/…• À)å˜EˆÐB~F=CWÉz|è'#m…Šœ“X¿+Ÿž“UZM¬à{zEÑŠ1_?£‡úFð@½uËDS$q@p(ÿgYü×›5´wJUÌP8Äç¶ ì>˵× «V‘JðÒLÜM«µ5æy[}Ñ ±qFü0„ƒÑCûØóóGÓÉe4,V'S„}<²´÷Þˆ”åè­3¿¦L mLôƒºcñT¥ ~OÊv²œd^µ²ÊÐñùœdŒ¿à4ÊFa!öîM PÇ}yc-ñˆYó_ úTЋêàÞùÀ×oOìç¨jæ&?Ç9ßì" Žð ¸“´ˆo&º‚åQ‹Ð3 ¾â »—I:Ê€ ŽŸ‚â´<‡·² nt™(u8J9$8,ïÔïRpO@c “¯^Ö2¬¹Jx,Ÿƒx2Èv“ ë® 'ÈŒ‚RÇ[C¹áÜd~(ã òB© 6ÓÙ™|á~éŠWrI¥˜"õo@ÕKqbMÒï 9ͪ8?Ó/ÑÓ7žt^;ñ0×0‡ýfª¡>rUu»ÄÄ=¬òÆöü:¦¹õ¤Kðóœò*F¿ Ö]FúvoXQ ±[”üO“&fÏ!Ž¿{'!ùíDy÷¢¼ãC¼nǵOIš; gM‡Þ)$j¨NT>—_À#b^âËôÙl*ìÞèö&&Ò$#¦î0¢ìÖæòRïz·*LÍ!úÔ¤dœáòeŒSkÚ¢ â#žýLgŽ.Çç0ûn²®…¢geœš§Ì’ã c‰IÍZóÃb"4EÜÕ¥)ìÞ›®FÙ hÐ.ä¨ä‹.®%HJéδždÞÞêOÈi0,©‡ã¨ÔÜM´„É` jT'CbBQgâÀ%€Î¢]§ÅRKŒ\À–ú=ï ö€ ¤$+,"BQç®´#Îläˆ,s‚t>â …-–½ë SË×â-ìvOf¾¯Â'Dv.K~ µKD"£¨ü«ôÀB:VcÂF ¶uGÌFDýðìs€j÷ξ­-–Ä$aŽù-X2ΚøÁü°®:qNö0§Ð‚HÜ“!ö¬"TYN:ÕcqÃ2yÊö(«zOIb p J”r¬¸B”L±x/2"°An~þgôô¨@Ûéö0ïØŸŽ‚Ë¯88޳‡â†$ ¤/Øß®@°„Íë¦ñ 2“HCd6Kȼ”MÖä@V|t­Â× xõ'0z ˜$Ì@€Nº\,ïE1>³-R[T§²O"¬ÂeÜÚDØò.;ãö@mvQÄd³ŠC$ü­ÆŽ¡1 Z ´±R#¬R»Eü#&‚<±·˜„bQÄY£@ÚO³( ±²†°î% fAg‚Ìù ) ÷ÆhmC´tEÀ8•*¶°‰lËÂ>×i`ßêð[c~£éèÐ(–¶B((ù†šù.¼Mé¸qÐúš)OÆÉ`•d6Lnø¢°g 7Ǭ¤/+¬¶Šòš®r|y -?"IYàv øí¡öƱ€r­ª;°:ÙcÎà ÊÆ’Ã" ¹ (ʘð¾!þèèŠ,  ^- Ð, @, z, ‚, (=s‡H n- HHàÛ»ÛÔÚ(Ø]Ø£ÓUÔ2Ò–×ÕPÔïÔRØfÚìÚmŠèÛ£·w’ŸjüBŸôê&½¼”Kj›> Š Üë BÆ .¡ /Users/jakepetroules/OpenSource/qt/qbs/tests/auto/blackbox/testdata-apple/apple-dmg/hello.tif HLinomntrRGB XYZ Î 1acspMSFTIEC sRGBöÖÓ-HP cprtP3desc„lwtptðbkptrXYZgXYZ,bXYZ@dmndTpdmddĈvuedL†viewÔ$lumiømeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ óQÌXYZ XYZ o¢8õXYZ b™·…ÚXYZ $ „¶ÏdescIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view¤þ_.ÏíÌ \žXYZ L VPWçmeassig CRT curv #(-27;@EJOTY^chmrw|†‹•šŸ¤©®²·¼ÁÆËÐÕÛàåëðöû %+28>ELRY`gnu|ƒ‹’š¡©±¹ÁÉÑÙáéòú &/8AKT]gqz„Ž˜¢¬¶ÁËÕàëõ !-8COZfr~Š–¢®ºÇÓàìù -;HUcq~Œš¨¶ÄÓáðþ +:IXgw†–¦µÅÕåö'7HYj{Œ¯ÀÑãõ+=Oat†™¬¿Òåø 2FZn‚–ª¾Òçû  % : O d y ¤ º Ï å û  ' = T j ˜ ® Å Ü ó " 9 Q i € ˜ ° È á ù  * C \ u Ž § À Ù ó & @ Z t Ž © Ã Þ ø.Id›¶Òî %A^z–³Ïì &Ca~›¹×õ1OmŒªÉè&Ed„£Ãã#Ccƒ¤Åå'Ij‹­Îð4Vx›½à&Il²ÖúAe‰®Ò÷@eНÕú Ek‘·Ý*QwžÅì;cвÚ*R{£ÌõGp™Ãì@j”¾é>i”¿ê  A l ˜ Ä ð!!H!u!¡!Î!û"'"U"‚"¯"Ý# #8#f#”#Â#ð$$M$|$«$Ú% %8%h%—%Ç%÷&'&W&‡&·&è''I'z'«'Ü( (?(q(¢(Ô))8)k))Ð**5*h*›*Ï++6+i++Ñ,,9,n,¢,×- -A-v-«-á..L.‚.·.î/$/Z/‘/Ç/þ050l0¤0Û11J1‚1º1ò2*2c2›2Ô3 3F33¸3ñ4+4e4ž4Ø55M5‡5Â5ý676r6®6é7$7`7œ7×88P8Œ8È99B99¼9ù:6:t:²:ï;-;k;ª;è<' >`> >à?!?a?¢?â@#@d@¦@çA)AjA¬AîB0BrBµB÷C:C}CÀDDGDŠDÎEEUEšEÞF"FgF«FðG5G{GÀHHKH‘H×IIcI©IðJ7J}JÄK KSKšKâL*LrLºMMJM“MÜN%NnN·OOIO“OÝP'PqP»QQPQ›QæR1R|RÇSS_SªSöTBTTÛU(UuUÂVV\V©V÷WDW’WàX/X}XËYYiY¸ZZVZ¦Zõ[E[•[å\5\†\Ö]']x]É^^l^½__a_³``W`ª`üaOa¢aõbIbœbðcCc—cëd@d”dée=e’eçf=f’fèg=g“géh?h–hìiCišiñjHjŸj÷kOk§kÿlWl¯mm`m¹nnknÄooxoÑp+p†pàq:q•qðrKr¦ss]s¸ttptÌu(u…uáv>v›vøwVw³xxnxÌy*y‰yçzFz¥{{c{Â|!||á}A}¡~~b~Â#„å€G€¨ kÍ‚0‚’‚ôƒWƒº„„€„ã…G…«††r†×‡;‡ŸˆˆiˆÎ‰3‰™‰þŠdŠÊ‹0‹–‹üŒcŒÊ1˜ÿŽfŽÎ6žnÖ‘?‘¨’’z’ã“M“¶” ”Š”ô•_•É–4–Ÿ— —u—à˜L˜¸™$™™üšhšÕ›B›¯œœ‰œ÷dÒž@ž®ŸŸ‹Ÿú i Ø¡G¡¶¢&¢–££v£æ¤V¤Ç¥8¥©¦¦‹¦ý§n§à¨R¨Ä©7©©ªª««u«é¬\¬Ð­D­¸®-®¡¯¯‹°°u°ê±`±Ö²K²Â³8³®´%´œµµŠ¶¶y¶ð·h·à¸Y¸Ñ¹J¹Âº;ºµ».»§¼!¼›½½¾ ¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûÛ€ÜÜŠÝÝ–ÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäü儿 æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿqbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/ja_JP.lproj/000077500000000000000000000000001347155106100257375ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/ja_JP.lproj/eula.txt000066400000000000000000000003511347155106100274250ustar00rootroot00000000000000架空CORPORATION ソフトウェア例契約 ã‚ãªãŸã¯æ ¸å…µå™¨ã‚’作るãŸã‚ã«ã€ã“ã®ã‚¢ãƒ—リを使用ã—ãªã„ã“ã¨ã«åŒæ„ã—ã¾ã™ã€‚ ã‚ãªãŸã¯ã€QBSãŒãƒ™ã‚¹ãƒˆã§ã‚ã‚‹ã“ã¨ã«åŒæ„ã™ã‚‹ã‚‚ã®ã¨ã—ã¾ã™ã€‚ qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/ko_KR.lproj/000077500000000000000000000000001347155106100257615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/ko_KR.lproj/eula.rtf000066400000000000000000000020161347155106100274230ustar00rootroot00000000000000{\rtf1\ansi\ansicpg1252\cocoartf1265 {\fonttbl\f0\fnil\fcharset129 AppleSDGothicNeo-Regular;\f1\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww10800\viewh8400\viewkind0 \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural \f0\b\fs24 \cf0 \'c7\'e3\'b1\'b8 \f1 CORPORATION\ \f0 \'bc\'d2\'c7\'c1\'c6\'ae\'bf\'fe\'be\'ee \f1 \f0 \'bf\'b9 \f1 \f0 \'b0\'e8\'be\'e0 \f1\b0 \ \ \f0 \'b4\'e7\'bd\'c5\'c0\'ba \f1 \f0 \'b4\'e7\'bd\'c5\'c0\'cc \f1 \f0 \'c7\'d9\'b9\'ab\'b1\'e2\'b8\'a6 \f1 \f0 \'b8\'b8\'b5\'e9\'b1\'e2 \f1 \f0 \'c0\'a7\'c7\'d8\'c0\'cc \f1 \f0 \'c0\'c0\'bf\'eb \f1 \f0 \'c7\'c1\'b7\'ce\'b1\'d7\'b7\'a5\'c0\'bb \f1 \f0 \'bb\'e7\'bf\'eb\'c7\'cf\'c1\'f6 \f1 \f0 \'be\'ca\'c0\'bb \f1 \f0 \'b0\'cd\'bf\'a1 \f1 \f0 \'b5\'bf\'c0\'c7\'c7\'d5\'b4\'cf\'b4\'d9 \f1 .\ \ \f0 \'b4\'e7\'bd\'c5\'c0\'ba \f1 QBS \f0 \'b0\'a1 \f1 \f0 \'c3\'d6\'b0\'ed\'b6\'f3\'b0\'ed \f1 \f0 \'b5\'bf\'c0\'c7\'c7\'d5\'b4\'cf\'b4\'d9 \f1 .}qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/main.c000066400000000000000000000000311347155106100247110ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/ru_RU.lproj/000077500000000000000000000000001347155106100260105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/ru_RU.lproj/eula.txt000066400000000000000000000002251347155106100274760ustar00rootroot00000000000000FICTIONAL CORPORATION SOFTWARE EXAMPLE AGREEMENT You agree that you will not use this app to make nuclear weapons. You agree that Qbs is the best. qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/000077500000000000000000000000001347155106100264125ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16.png000066400000000000000000000012111347155106100307100ustar00rootroot00000000000000‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/white.iconset/icon_16x16@2x.png000066400000000000000000000012311347155106100312640ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/zh_CN.lproj/000077500000000000000000000000001347155106100257555ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/zh_CN.lproj/eula.odt000066400000000000000000000051701347155106100274160ustar00rootroot00000000000000PK¥^C^Æ2 ''mimetypeapplication/vnd.oasis.opendocument.textPK¥^C \y€ÆN content.xmlíXÏoÛ6¾ï¯0t, Ñ’üS°]`†`C: W†¢mb)H´åìTÙ.íZt-†!‡®Èam ŠlÙþ˜ÅJnûFêWä(r l§¡É|ï{|Ÿ>¾GQÝ^ù^k‰Ãˆ0:ÖL£­µ0EÌ%t6Ö¾¸û‰>ÐnO>±é” ì¸ -|L¹ŽåâÞÑ4r2ïX[„Ôa0"‘C¡#‡#‡˜QNí¤¹2KÄ<åð\æxÅUƒ%v#î«gNÁÕh7„±j°Ä Q«áS¦¼Š<}Ê„ê~9¹ÆbåúåX›s8ÄqlĶÁÂ0‡Ã!H½%aTâ‚Eè¥(ìa™,¦a‚ëcUùIl•]øû8T–rX[Õh9S®ˆå¬A4‡¡rm¤àÍåµ]õåµÝj¬ù¼aM`W8ÓËîÎU-„¾j.‰Ý …$P~Ì ]gŒ•Te@Ö )]«Ýî€l\AÇ[áqH8+p´Ž ‡JÅ™“hgÐñR–iYøRˆ¨!À™»GnãÔ÷vwöÐûð LÞÖ 8¤R™|KÛØG'Ŧ9{¥>…ë.F^4eµ^š[ÙX®ÙXûNZ{wZ;d6çZKÔvô‰wP€÷Mç-1'Þ8Sá“€&²¹.85MžN_>EzÝHù™©åã"QC8 a0/ _"é@Ï¢ö„’. ]­˜¸ ÒƒP”MÈÉUR±‹`Ô Åü,"É…höÐz¥ÓhÐï*AÅ690-Eh·ßm+B‡½W˰{–WËèw»=%¨m˜¡­ívlS:´{jÕ1l»­Æµcô­NÎÔª(Ô8 TÌEÉÊò¿¹§,óFä+á5-£ðJöôº¥+¬]ñ¡+þ]Q¾Pþ]CÜ­½&dn­‰H‘,ƲÇÚ>ó\íšUgH|ò€èáUîU§YëÛ­4·è¥žR~fÜaÞ§u¤O<‹tj•r(u2¹=&®<‘ÚF'ë‘ÜbO¿†°ú½þ­:]ÐxÈûÌ=(R˜É(ýÜ Zé­º¯‰3BîŒHë~Q“Ëç/’G „M.^®¿þi}ô.7Û\ž½=ÿí׋—§ç<\{tùæBœ%ˆ)Íž<8Y?~”ýýû#ùûço’gÇÉ/OÏÏþ¼xr’¼~¹>}"~\œ<\ŸJŒ°'Çï’ׯÖÏOþºÿ࿤r~v\RÙªª˜ñó÷ª’&ß½M¾¿¿þñLh»Á l¬#ØXbÐðoÀäPK¥^CþI¢´¬D styles.xml¥VËnÛ0¼÷+ ÝeZI $‚íÜzjNM?€&)‰¥%HÊrúõ]RS~$z  ÝYîìp9ÎöåT«ÕQ+¡Ù%Ùz“¬DÀ˦Ü%Þ~¦OÉËþÛŠB2‘s`m-—Z÷¡„]aqcó>¹KZÓä@­´yCkasÇrТ‹ò‡V}$¶´<€ãj'Nni±ÇÎjéay玫¹¡ÝÒbEMãò–Ÿ¬J HÔš:yÁâ¤dó¾K*çtNH×uëîq ¦$Ùóó3 Ù‰0›pº5* 8#B ßÌ’l‘[ G—òóؘRÓÖaKC½ºU{,oı¼# «¨Y¼<¿ÞG¾üzy\[SWݹ“'òŠÉðçõ×yL½´—ÇΤbFêÅcöè¸&ª¾  îÃfóôߺûÞ鄉àìS8£ŠMŠC}K4Äe©8ú5MVƒ…Ìlk?zTèOe"å‚)»ßö»5…Wý·×h—¼IT*Yá €Zª1Nö[rïÔ!ÞáØ„‹‚¶j°Ç¡Ñx¤¦†–†ê*ÑS$Õ¥1N¢¥ö)ô<tÊ¥u´ñîºYÿ§4 ÐÊ®ëÍÙhôA+ÿb0{Xo´ ƒÝ`¼dŒà‚Óá+¦Ñ›ä &­ µK(EµEûûïÆ©î¢9Fb8ï»:uP Wy¢­ƒ¯Ç {ù~£ìœžÜ½Æ!Áµéá}Ä 3.ÆðéI )H–Î7FÓR¤Š~@ën·¿¼7d:ɽã<…%™¢•e…Öá ññá(#q!ÀH|MHÉ¿ Æ*](­©)eƒ êqë¢èœóÏô*¡DáÂSœ‡ÍÀ ÄÏ·sÖìZ¤!QãîÓ\º!èOúôæbå®Ä%Wgé\t%·ÿ ÚÿPK¥^C®Ñã¹meta.xmlÍNÃ0„ïXr ãeÅ t†Z뺆½½î7l§n$Ö hÉLº¸0êâ{Õ±Œ6y'H„Ó ݺ".i‘–ŸSoÝGÃŽ1Ž`žçr¾-ÉwÀ뺆<]ÑÖœ¹qò}¦ZØcrÀK+›þ7Tb/#ÑÙ(áKèl·­ª;XÞ¬ø9æª>µv•D•ÌÒ:ô:’WOdH¿<ïß½èoî%üb$\)À_Ý«/PK¥^C0.†eöaMETA-INF/manifest.xml­‘±jÃ0†÷<…z»¥v+Âv q …¶Îà …tN²d¬sˆß¾rÁMJº²éÄßw'åëSçØ‡hƒ/àßC¯ƒ±þPÀ¾yÎa]®ò»ªÞ4»-ë”·-F’ËíöO¯/™u¾n[«‘‡á DÕTìmÉ%¶Ûw`°\qCüš™†òñ§,`¼ *Ú(½ê0JÒ2$— zìГü—óåŠÁ­u˜¥à0],€ÆªŒ¦ P}ï¬V”A½áß.~©à„'‚sw;:—õŠ>  þ%›I"Mü7MO³oÜ’iroŽíÔÍÅÕO–_PK¥^C^Æ2 ''mimetypePK¥^C \y€ÆN Mcontent.xmlPK¥^CþI¢´¬D <styles.xmlPK¥^C®Ñã¹meta.xmlPK¥^C0.†eöaMETA-INF/manifest.xmlPK B qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/zh_TW.lproj/000077500000000000000000000000001347155106100260075ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-dmg/zh_TW.lproj/eula.docx000066400000000000000000000300621347155106100276150ustar00rootroot00000000000000PK!87Žîl¤[Content_Types].xml ¢( ´”MKÃ@†ï‚ÿ!ìU’m=ˆHÓü8jÁ ^×ÝI»¸_ìN¿þ½“´‘’ˆm/dæ}ßg‡ÍŒ&k²Ĥ½+Ù°° œôJ»yÉÞfOù-Ë §„ñJ¶…Ä&ãË‹Ñl e¤v©d ÄpÇy’ °">€£Jå£H¯q΃Ÿbüz0¸áÒ;‡9Öl^ÏFñü¤¢Ü™ø0pzŒÖºi Àîyü…llº"©³¹û´Uâ?Žýýû×ê<üéÒ·‰d}ôù Þ] ÔlÞìØñÿÿPK!Â`šóîN _rels/.rels ¢( ¬’ÍJA €ï‚ï0äÞmél/RèM¤>@˜ÉîîüIµ}{Q±RK'“|ù²\íä^‰‹OÑÀ¼iAQ´Éù8xÞ®gw Š`t8¥HT`Õ]_-ŸhB©Eeô¹¨J‰ÅÀ(’ïµ.v¤€¥I™býé”úäAg´/8^´í­æŸ 莘jã ðÆÍAm™.a§¾÷–’ÝŠr¢Å¯ŒJFH ¼%vÚ}†›Š}Úfq¹Íß“ê@‚µML³ÌµšÅ×Í~ U—Ç.ç„nþs=´ŠŽÜy%ÌùËH]A÷ÿÿPK!Åà§? ¿word/_rels/document.xml.rels ¢( ¬“OKÃ@Åï‚ßa™»Ù¤jé¦zÕ^·›ÉÌšoïRi›b r|o™÷~³«õ·íÄ'j½S%)tÆ—­«¼Ï7 ˆµ+uç*`__­^°Ó‡¨i{1Å‘‚†¹”’LƒVSâ{tñ¥òÁjŽ2Ô²×æC×(iº”aœùY¦Ø” ¦¼Q =þ'ÛWUkðÉ›EÇ*$!sÜŒb¦5²‚ƒ“Ä,—îæDøÂí늑9r?'HåzÛá ãhMA,ç„à8;ØË_3›bÈæd0;boßcÛ‘#IN®lí$ÍbÖå¡Ãñîõ¡^ž}»üÿÿPK!€eÌÁ‹ word/document.xmlÔWMoÛ6¾Ø0tOôaEv„ØEl']€Èæí<Ðm ‘H¤í¦§¢HQ éÐZ`Ý ´Ú-‡+0`(Úeû1‹åÞööR’eÇY·FÄ‘|?>ïCŠ¢7®\ÂÒ€p0ZÓÌUC+Š™Ð^Mûú«í•ªVQ…Œ’š¶O„v¥þé'C×c¸*KA…;ŒqMó¥Œ]]Ø'«Q€9¬+W1‹tÖí˜èCÆ=Ý2L#íÅœa"Ì×Dt€„–ÃEl1´áI×2Œ*ŒZ`œgÄbBÁÙe§nޱRðP9.pQ8 fÅfDóf’Á!™¥´rÉSz:'!fTøA<ÕíCÑÀéO@.,x¦ØalÚË-z‹£!4SÀEè{YRfÌ/F4VDA‹P8;ç„Éìæ~˜43âškï`ÍĽåç*gýxŠ,‡¶C÷ ,u”¼V¾È³¥‰åÈ´}Ãaw§GGÁ’•@õ’ÚÖZޏóöUƒÙvcÄÑŽWÓÊ-{»ÜhZZj•äºTÖJþ« Ç©÷eM3Œõr¥Y­¦é¢~(•§ì8­Êf: O»Y³Í¨@ðÏH ƒR»Yú<èùRù›Tü§‹sV½¾¡вþöÑÉχãF·Ý{¥|2‹HŸñùR­rÃvÊ çò•úæÉé›ßÇÏ_Ÿþyx¦ÎÌöÌ“ÑwÞ¿\@ëµMÇÜ^[o-¥uîI™œ…¯4̪c”×/ÝR&·ŽF÷ï&÷þùã®ê¿¼3>x–üöðôä¯ñƒ£äøyrç[èŒG¯U Ø“§¯’ãŸFŽþ¾ykå+fÙp¬-û#)ïTí­Í¦¥€.—ò§'O åç_¢ Å]>Ïî]Ä‘Fg8ÍØ2:C*£¤BE ܪÛg²á<Í/í9vÆöÔµ®-WÉèm¨I(Šàœÿæ*k ¼—¿¯yìõŠÈÔñÿmðïMß½8“ù]V,w Ñg¶JºÝzíà‚‹‹iYvZ¨ýµª—÷®!•,ܯL; áŠËtØaR²h:IwÆëäXꊕ»ŒÉ™a¯/Óa>f¡ÒJÄ“,&«8+"íf_V}ú/¢þ/ÿÿPK!´æ ó (word/theme/theme1.xmläXKoã6¾è xß•åWì ÎbíØè¡-ŠÄEÏ´DKÚP”@2qòï;R²v׻ɢšƒERßÌ7ÎÊͧ—\g®tVÈ ?(á2*âL& úçvóaF‰6LÆL’/è+×ôÓíÏ?ݰk“òœ—úš-hjLy:‚e¦?%—ðn_¨œ˜ª$ˆ;€Þ\ÃÁ`ä,“”H–ƒÚ;¾gO­ÕIo+ík?Òh» õ`uó¶‚ãÇÐ>ô«^ Ež™XP`Š‹Ã–¿JÓ^,èÿhp{ÔBœ‘mÈmðÏËyøqˆr*ÙÕ‚áf<¿º«õ#@˜>n½^¯Öa­,ŠÀUgK;ÞÌÂe¥³rþîÕ`2·ñ ý£~¾\.'óAn8îágƒéøó°…GNúö/?¯VÓAn8íá7Wóé¸GP*2ùØCÛ|Ö™©!ûBür>ø¬ÚGTÐØ^N^š³›-g_ µf—™LóZ à6˹&¿ó¹/r&-»æ¬pK‘î,Åy&ËQ1Æ òýÎÏ»½Ï„x0¯‚ÿªÑ&]ˆ,ÞÀ"NPªs™ÂÐóµp‰b8&ª0e&}HY š©åû=Ì™•ãÔ¿+ž Wi| ;ñ¤îØm·*øgÚ@ˆ« Ürl´qÖ®|_ÝS×WeÊ|O²%Zyèà8®mÀYüzÖ±ý;]Á’'WšÛøæŠÝ¹\òQl‡Ü#v.h¡LZ@*Ó,Ú(¸9 Ø7ecM"Â~EX[ùó±o9XPY’šû,!*ƒNgRÅùÆûùe¡ïо2¼"ßgjsuéž;þÌÅÖVïÔúOIZuÄu“Öžû`ì[¨ÿÕ›Û6ßz=89ùKÉM¿qÌßfÂ7µ®cõ膓‹Ú’™”ØhܙЄûà´궸‡ìQÝ( lÄîâAl)ºÑlv‹ŽÍªr ?êuLAÍÛ v³8Þ1Øõu©ì¦ûþ`ûQ+ÖÍ}t"ÔA¿DƒÆ— ÎzÿL(v_€ÛÞhô¿ÅVÕW èqŒ(zû7ÿÿPK!ÓNº„0ƒword/settings.xmlœUmOÛ0þ>iÿ¡Ê煼ДQP[Ö Ø´Àp·µðKd;-eÚßÙ‰›n ©_8?ÏÝùÎ÷\zqõÌÙ`C”¦RL‚ä$D`YQ±š‹p ´A¢BL 2 vDW—ïß]lsMŒ7=€BçO‚µ1uE¯ GúDÖD¹”Š#GµŠ8ROMbÉkdhI5»(ãQÐ¥‘“ Q"ïR„œb%µ\’Ëå’bÒýóê˜{Ûk‰N„q7FŠ0¨A ½¦µöÙøÿfrí“lþÖĆ3ï·Mâ#ÚÝJUí#Ž)ÏÔJb¢5 ˆ3_ ýÅÃW‰öwŸÀÝ]‹.„'±³+Ïþ-AúG͎餥ni©juÒµÁq~³R¡’*¡T\‚,_¤äƒm¾ApAI´YPÀ¹& ì@ãqDÖ^H. ƒ Zׄ1'zÌ6b¥¹zÄÅTd‰fPYYûkÎÒ¸¥ñ)„ QE0d›Ka”dÞ¯’÷ÒÌAú &ÓE¸E°V£Éâã-ÚÉÆ0E»dA þ¶8w²"¶ÒFÑã‡a\5‰{‡è°ø TÚߥ4Þ7ŽÏOÏæãq[´e{æt4º>›¾Åô1Ñ>7Ïí¢|SÞZÀ x1G¼T îì*EÖ£TO3*<_Ð9dЦôd¶„戱ŒÁn6<¯¨®¯ÉÒÙì©UŸ·óPo¢0ò/û\VBD}R²©[v«P}#*Ò7‘ ‡]$æ–rë¦,|”5P¨¾n”{§þy¶¹Iû>·È)Àù>v†i3ÕM‚—u8¿·PI+Âs(àSÝÉ‹©Â ‚Ü¡ºnuT®’IÀèjmcàTÁGÙÊUÚq©ãÒ–s„móàÝ=–zìÀïÔc§=6ôذÇ2e=6òØÈbë¬.¬æHÜ›_JÆä–TŸ{þä—SE±ãe¿‹'-Ǩ†«amTžûà¸d˜W߀žÁrx6Ïf³lØÒÙžÎZúÇÂþÓY8M®Óp8Êfá8 g‹tšÌ§ç£lžþìÖÁÿz^þÿÿPK!t?9zÂ(customXml/_rels/item1.xml.rels ¢( ŒÏ±ŠÃ0 àýàÞÁhoœÜPʧK)t;JºGILcËXjiß¾æ¦+tè(‰ÿûQ»½…E]1³§h ©jP >N~ûýjŠÅÆÁ.ÑÀ¶ÝçG{ÄÅJ ñì«¢D60‹¤o­ÙÍ,W”0–ËH9X)cžt²îl'Ô_u½Öù¿Ý“©ƒ|Pý=á;6£w¸#w åE…v §°üd*ª·yB1àÃߪ©Š ºkõÓÝÿÿPK!s³‚æ?(customXml/itemProps1.xml ¢$(  dKkÃ0„ï…þ³wY~áºÁvð£\K ½ y,­‘äR(ýï•É)íi™]v¾™úø¥—è­SdHã"4’&e. ¼¿X‘óÂLb!ƒ ‚cûøPOî0 /œ'‹g: æylà;K«¾Ìº‚uýP²²*JÖ½¤9{ÊOU?ÏÅä?´ 6®«÷ës'¯¨…‹iEŽ3Y-|öÂiž•Ä‘ä¦Ñxž%IÉåðúC/Ðîyn߯8»{¹GÛ¬úGëº`,IsI’ÄÍS£{1àmÍÿ˜îú®tû ÿÿPK!ݸ5Û< þrword/styles.xml¼[Wã8Çß÷œý>yÚ} ¹6ts†ž4,œ†™ÐÛÏŠ­-²•õ…Ë|ú•e'Q(ËqIµW¿>«ßØ¥õô™HÄh»n´øK¿øÌäÉhï`ñÌy݉µç$ËÏñlëÇØîÌÉè¯ÙÖù]ýÔDsOF,ߟÖÛí±5­#ž/5ïz7<:;t®Œ›”Õ¯ò銟x2.õ '£º)ýäëû\¨\§åÉèë×öÉ1OÅ•HžYoÌf"á?g<ûQðdõü—&µÚ'bUeúÿý/{F2Y$¯1Ÿ×‰ª_ÍX=zwu€¬ß]‰Uã&ü¿ Øn;f]ñ3Îj·F»ï¦û(Ä^QXGÛͬÞ»yª¡ýjèà£úüQ ~TCGÕЗjÈ`þŸ ‰,á¯a3€º‰ãp#šã0šãðšã° šãpšãHt4Ç‘ÇhŽ#MœRÅ®,´’}ß‘íýÜÍk„wó’àÇݼøq7Oø~ÜÍó»wótîÇÝ<{ûq7OÖxn³ÕŠ®µÍ²2ØeS¥ÊL•<*ùk8ešeJ^½èñœä 0ÍÌÖ.ÄÁ´˜™Ç›3ĘÔ=/ëª+RÓh*«\W¾¡çÙ3—ºX’h!0çe•;FÄ'§s>å9ÏbN™ØtP)2eU:!ÈÍ9{$cñ,!¾‘dRX&4«ÊYmAÔ)‹sÞ5ÅÈæ‡Q„U ‰Î*)9ëŽ&Å +¼60˜ðÒÀ`Â+ƒ / ,ͨ†¨¥TK#°–F4nM~R[K#·–F4n--|ÜD)Íoï:v‡Ÿ»;—ª>éܱx̘ބ/7í9Óèžåì1góYTŸBîÆÚÇŒmçL%oÑÅš¶$QíëMŠœë£Y> k4*s-yDöZòˆ ¶ä…[ìVo“ë ÚM=3®&e§i iiÇLV͆6Üm¬ ϰ•.E^Ù KÁwõv¶–“bæ[õ2¼c+V¸­ÞÏJ¤Ýk‘½”*~¢™†¯Þæ<×eÙS0éRI©^xBG—¹jrͶüž‘då/ÒùŒÂÔJkˆáKýârutËæÁt/™Èht»ØJ™Ýâêáö&zPóºÌ¬†x¦ÊR¥dÌöLà?~òÉ?i:xª‹àìèhO‰Nع Xd’JˆHz›)2A²†Þoüm¢XžÐÐîsÞ|B¤äDÄ1KçͦƒÀ[z^|ÑóÁnÈðþÍrQŸ¢2Õ Ì:mXT“ÿð8|ª»SÉ™¡ß«Òœ4[]M‡ ß&¬á·FM½<ÔùKp°k¸ðƒ]ÃQì¹dE!œ—P½yT‡»àQoxñ×ò”Tù´’t¸’àH6„JViVP±á°áQ/aÊÁ)9ÃûW.21 ŒJ £’ÁÀ¨400RÂ?¡cÁÂ?¦cÁÂ?«ÓÀˆ¶Œ*ÏH—¢«<Œ*Ï Œ*Ï Œ*Ï Œ*Ïö¿G|:Õ›`º%ÆBR圅¤[h²’§s•³üy!ù##8AÚÐîs5­oPYó!nd}ŽZn¶•È?ù„¬k5‹²_gD™”J[[-8&rý³k›ÂÌ=Á]0'Ûoø3§Ø[0¢Ë ,\6 ¾LY°ðeÊ‚…/S,|™²`áË” ÿüò½d1Ÿ)™ðÜaľŽDã9‹ÛkKàõ sõ7âqVFãÙò•9ÜÙ¹8Ë´¶¹Á®‰âp¯'ì–'¢J…wî6†^ ^ܨÕ¼Úþ®E~ Û<ܹ*íÖ"FÂ6¿ Œ4³ÔZdß$þåO‰pÔ—?ËŽä;êË¢epg³}‰´ŒìJÁ£¾,Z³JtÇõ%.¨Î0ϸ㇙Çq‘›‚±“›2ØWnDŸÁþäÏ¢ÞŽb&MÓÞò#?ï›Û7Kê ™óJ5›Ö®’¿ñZïö³‚GœýáW[×f÷8žn܈ÁóŽ1xr#ÍDÎpÔ”ä¦ ž›ÜˆÁ“”ž­àŠ€›­`³¤øÌV»7bðvÀ@"ÐF Ø)¸(£‚p/£B Ú¨6*D  7`8£ÂxœQa¼Q!ÅǨ‚6*D  h£BÚ¨6ªçÞÞîeTHA"ÐF…´QÍ~1À¨0gTïcTHñ1*¤  h£BÚ¨6*D  (£‚p/£B Ú¨6*D ÚÜëoT3*Œ÷1*¤øRÐF…´Q!mTˆ@"ÐF…”QA¸—Q!mTˆ@"ÐF5—Œ ãqF…ñ>F…£B Ú¨6*D  h£BÚ¨2*÷2*¤  h£BD_~¶×Õ]÷†ìâÏz:o3~éªíÔŸö÷بýá¨E¯Ü¬á7М)õuÞ-»oêa1‘B™SÔŽÏ‚Ø\suµþ÷óþÛÒlzà7…µ7ð˜ ý~04œS9èKy;y}™nG‚]çAßìkG‚eð oÒ5¾\|’J/G ¸oš±‚wá}³µ‡¸o޶á÷ÍÌV à¾ùØ üÕ“óûèÏÇépù¡h@èKG‹pä&ô¥%Ôj1Cc ÍMªž›0TF7¥§ƒÖB+ìFùI m†•ÚߨnVjHð’`ü¥†(o©!ÊOj81b¥†¬Ôþ“³›à%5ÀøK QÞRC”ŸÔp)ÃJ X©!+uà‚ìÄøK QÞRC”ŸÔps‡•°RCVjHð’`ü¥†(o©!ÊOjP%£¥†¬Ô€•¼¤©!Ê[jˆê“ÚœEY“¥°ŽÛ„Y¸Ù ÄMÎV GµdE{VKÁ³Z‚Z-4ÇUK¶hnÂPõÜ„¡2º (=¼°nZa7ÊOj\µÔ%µ¿QݬԸjÉ)5®Zê•W-õJ«–ÜR㪥.©qÕR—Ôþ“³›à%5®Zê•W-õJ«–ÜR㪥.©qÕR—Ô¸j©KêÀÙ‰ñ—W-õJ«–ÜR㪥.©qÕR—Ô¸j©Kj\µä”W-õJ«–z¥ÆUKn©qÕR—Ô¸j©Kj\µÔ%5®ZrJ«–z¥ÆUK½R㪥["¾·lœ²¼Œ<¾äpûeí×ÌêÌOñé÷—šV¡½u#OÒ|¡o 4o¼N–¿:V×݉Ú_bkŸ6½n/d6-š@ØT<ÓmÅíW‘9šj¿Rxy{‘ùBá÷ ;¾wØtd%ÍâÝí¸®Æ«yßÚhõö»¬S¡§Ï&UzǨÉ&W¿¶öØÔCÝŸ‰l~«Oÿs%ðÒþú[ÓÓä•5(ýú9—ò–5ïVs÷[%Ÿ–Í«»;æÖÞw¯Oš/StÆçfs¶×;Ó‹„‰ÍEã4±tKl¹Xó%à‚¬!pÉÇ0µƒ”R J»qu/C Lð8Ïr|b8íÏôo¤Vaoá,zlôΫlÛ6kG=óçø}úüÒ¯š*ÓÝJbÝ}jîÃ4žr¡@ÞïÙ_C2ƒàšM ¾Ä‰nÈÁVuÁŠžÊò°x™ÄDô+ÿ±ó6zxœO+H~›’딌æäŠ7”ÿš? õ!À¿GëÿüìÿÿPK!ƒØóÞ‘¥(customXml/item1.xml ¢$(  D˱ Â0€áW ·Ûk ‘$ NJE×#=ÚBs)I}{­‹óÿýº}ùE=9¦9ˆª(A±¸0Ì2¸]O»¨”IZ‚°7'h­öœI}WI¦œ×#br{J­ëÂ… ]p°.Ë7?P&°zdáH9DÛm½ï—ó=Ι#Vu³×øú÷ÙÿÿPK!¶ÛBioword/fontTable.xml¼“ÝnÓ0Çï‘xË÷kœ4-Y´tÚÆ*PÀuÆÂ‘í4ô¸ä=xÞf¼ŽtÓÚUT$ŠäüÏñÏçŸsqùMp°¡Ú0% Tµbr]À/‹ùY±X®0W’pK ¼œ½~uÑæ¥’Ö·_š\VÖÖyRQÍHÕT:c©´ÀÖýêu$°þÚÔgD‰[¶dœÙm” 4…=F¿„¢Ê’úV‘FPiýþHSîˆJšŠÕf µ/¡µJ¯j­5Æå,xà Ìä§{ ÁˆVF•vä’é#ò(·=F~%ø=`r ÙÉ߯¥ÒxÉ]ñ]$ÀÁଯ>hs‰…3,˜ |¤-ø¤–Þ¡ÆR;Ÿ æD‰{§hŒ&(u_âV)Œ:GRamh Ž(È%Œo7V½f–Tƒ¼Ášu±“akghÌð!”\ÝÎaPâÞ8åM–ƽ’tGùç¼WÆ;u ñÿÏ=‡xÎÎÇ…Bìä÷Ïïw¿~ø:†ñ}zI–͇ЦOÿ’^Ú9—Þ;Ê,ŸoÀ¶®ìÁë>ð¼îÃõо¼A*»Ð ]lkº_ -qÃíó±ò µŒà ó„]‰’ÐMáÚ&¨ëÊÉõ^WùLWžÙ•W.,þÄp^»áLý†÷? çÃ2ôÃ9ôói‡³_˜ÙÿÿPK!÷òfvçword/webSettings.xml”ÑÁJÄ0à»à;”Ü·i)mA¼x©>@6¶a“LÈd·îÛ;ÔuE¼¬·„d>þá¯7ÎfGˆdÐ7¢Ì ‘ר?6âým»z%å{eÑC#N@bÓÞÞÔs5ø'e¬xªœnÄ”R¨¤$=S”cÏF§_ã(ŠûCXitA%³3Ö¤“\Ń83ñ‡ÁhxF}pàÓ2/#XÑÓd}kó5ÚŒ±5ñ>Î~yNaÊ»?3:"ár^æœh¡x¼,–“³?Àýÿ€õpºz=Fµ³\'É-wÐã+¦Ná‰:nak,ȶ–¿êi?ÿÿPK!~bÅÚj·docProps/app.xml ¢( œRMKÄ0½ þ‡Ò»›®ßÊlDñ "lÕsH¦m0MB2ŠûïZ·V¼™ÓÌ{É›÷†ÀÅGïŠwLÙ¿*—‹ª,Ðë`¬oWåS}³wZ™”7Ê«rƒ¹¼»;ð˜BÄDsÁ>¯ÊŽ(ž ‘u‡½Ê ¦=3MH½"nS+BÓX×A¿õèIìWÕ±ÀBoÐìÅI°Ïßé¿¢&èÁ_~®7‘õ$ÔØG§åÃðÒ-L Ä„BH¹Úö(+†§U‹Y.AŒ¼„d²<1pÕ©¤4ñþäáˆY —1:«ñbå½Õ)äÐPq¯´õrW æ·€C¬Q¿%K›ÁǼ…;ëG'cÁÎ’j“ŠÝ·½©ƒµV¯8¾l”ËâT^óS¬Ãõû›ÿ Î2½XêÖQižwx6O7#`Í(ö:›¸åõ'7Èó[ߢÙÞùK ûzÿ¡\-*>_ÛÙbœqú òÿÿPK-!87Žîl¤[Content_Types].xmlPK-!Â`šóîN ¥_rels/.relsPK-!Åà§? ¿Äword/_rels/document.xml.relsPK-!€eÌÁ‹  word/document.xmlPK-!´æ ó (À word/theme/theme1.xmlPK-!ÓNº„0ƒÿword/settings.xmlPK-!t?9zÂ(^customXml/_rels/item1.xml.relsPK-!s³‚æ?dcustomXml/itemProps1.xmlPK-!ݸ5Û< þr¨word/styles.xmlPK-!rßòW;b#docProps/core.xmlPK-!ƒØóÞ‘¥ƒ%customXml/item1.xmlPK-!¶ÛBiom&word/fontTable.xmlPK-!÷òfvç²(word/webSettings.xmlPK-!~bÅÚj·è)docProps/app.xmlPK”ˆ,qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-multiconfig/000077500000000000000000000000001347155106100254005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-multiconfig/app.c000066400000000000000000000000571347155106100263260ustar00rootroot00000000000000extern int foo(); int main() { return foo(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs000066400000000000000000000113451347155106100315320ustar00rootroot00000000000000import qbs.Utilities Project { minimumQbsVersion: "1.8" property bool enableX86 CppApplication { Depends { name: "singlelib" } Depends { name: "bundle" } name: "singleapp" targetName: "singleapp" files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" // Turn off multiplexing aggregate: false multiplexByQbsProperties: [] install: true installDir: "" } CppApplication { Depends { name: "singlelib" } Depends { name: "bundle" } name: "singleapp_agg" targetName: "singleapp_agg" files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" // Force aggregation when not needed aggregate: true qbs.architectures: ["x86_64"] qbs.buildVariants: ["release"] install: true installDir: "" } DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } name: "singlelib" targetName: "singlelib" files: ["lib.c"] cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] // Turn off multiplexing aggregate: false multiplexByQbsProperties: [] install: true installDir: "" } CppApplication { Depends { name: "multilib" } Depends { name: "bundle" } name: "multiapp" targetName: "multiapp" files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" install: true installDir: "" } CppApplication { Depends { name: "multilib" } Depends { name: "bundle" } name: "fatmultiapp" targetName: "fatmultiapp" files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] qbs.architecture: "x86_64" multiplexByQbsProperties: project.enableX86 ? ["architectures", "buildVariants"] : ["buildVariants"] qbs.buildVariants: "debug" install: true installDir: "" } CppApplication { Depends { name: "multilib" } Depends { name: "bundle" } name: "fatmultiappmultivariant" targetName: "fatmultiappmultivariant" files: ["app.c"] cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.6" qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] qbs.buildVariants: ["debug", "profile"] install: true installDir: "" } DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } name: "multilib" targetName: "multilib" files: ["lib.c"] cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] qbs.buildVariants: ["release", "debug", "profile"] install: true installDir: "" } DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } name: "multilib-no-release" targetName: "multilib-no-release" files: ["lib.c"] cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] qbs.buildVariants: ["debug", "profile"] install: true installDir: "" } DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } Depends { name: "multilibB" } name: "multilibA" files: ["lib.c"] cpp.sonamePrefix: "@rpath" cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] qbs.buildVariants: ["debug", "profile"] install: true installDir: "" } DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } name: "multilibB" files: ["lib.c"] cpp.sonamePrefix: "@rpath" cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: project.enableX86 ? ["x86", "x86_64"] : ["x86_64"] qbs.buildVariants: ["debug", "profile"] install: true installDir: "" } } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/apple-multiconfig/lib.c000066400000000000000000000002741347155106100263150ustar00rootroot00000000000000#include int foo() { #ifdef __i386__ printf("Hello from " VARIANT " i386\n"); #endif #ifdef __x86_64__ printf("Hello from " VARIANT " x86_64\n"); #endif return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/bundle-structure/000077500000000000000000000000001347155106100252705ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs000066400000000000000000000077461347155106100313240ustar00rootroot00000000000000Project { property stringList bundleFileTags: ["bundle.content"] property stringList buildableProducts: ["A", "B", "C", "D", "E", "F", "G"] Application { Depends { name: "cpp" } Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } condition: buildableProducts.contains("A") name: "A" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] install: true installDir: "" } Application { Depends { name: "cpp" } Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } condition: buildableProducts.contains("ABadApple") name: "ABadApple" bundle._productTypeIdentifier: "com.apple.product-type.will.never.exist.ever.guaranteed" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] install: true installDir: "" } Application { Depends { name: "cpp" } Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } condition: buildableProducts.contains("ABadThirdParty") name: "ABadThirdParty" bundle._productTypeIdentifier: "org.special.third.party.non.existent.product.type" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] install: true installDir: "" } DynamicLibrary { Depends { name: "cpp" } condition: buildableProducts.containsAny(["A", "B", "ABadApple", "ABadThirdParty"]) name: "B" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] install: true installDir: "" } StaticLibrary { Depends { name: "cpp" } condition: buildableProducts.containsAny(["A", "C", "ABadApple", "ABadThirdParty"]) name: "C" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] install: true installDir: "" } LoadableModule { Depends { name: "cpp" } condition: buildableProducts.containsAny(["A", "D", "ABadApple", "ABadThirdParty"]) name: "D" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] install: true installDir: "" } ApplicationExtension { Depends { name: "cpp" } condition: buildableProducts.contains("E") name: "E" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] install: true installDir: "" } XPCService { Depends { name: "cpp" } condition: buildableProducts.contains("F") name: "F" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] install: true installDir: "" } Product { Depends { name: "bundle" } condition: buildableProducts.contains("G") type: ["inapppurchase"] name: "G" bundle.isBundle: true bundle.resources: ["resource.txt"] Group { fileTagsFilter: product.type.concat(project.bundleFileTags) qbs.install: true qbs.installSourceBase: product.buildDirectory } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/bundle-structure/dummy.c000066400000000000000000000023641347155106100265740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/bundle-structure/dummy.h000066400000000000000000000023321347155106100265740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/bundle-structure/dummy_p.h000066400000000000000000000023321347155106100271130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/bundle-structure/resource.txt000066400000000000000000000000001347155106100276460ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/deploymentTarget/000077500000000000000000000000001347155106100253105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/deploymentTarget/deployment.qbs000066400000000000000000000007401347155106100302000ustar00rootroot00000000000000CppApplication { files: ["main.c"] // Minimum deployment targets that: // - will actually link (as of Xcode 8.1) // - exist for the given architecture(s) cpp.minimumMacosVersion: qbs.architecture === "x86_64h" ? "10.12" : "10.6" cpp.minimumIosVersion: ["armv7s", "arm64", "x86_64"].contains(qbs.architecture) ? "7.0" : "6.0" cpp.minimumTvosVersion: "9.0" cpp.minimumWatchosVersion: "2.0" cpp.driverFlags: ["-v"] cpp.linkerFlags: ["-v"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/deploymentTarget/main.c000066400000000000000000000023641347155106100264050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/embedInfoPlist/000077500000000000000000000000001347155106100246655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/embedInfoPlist/embedInfoPlist.qbs000066400000000000000000000023661347155106100303070ustar00rootroot00000000000000Project { CppApplication { Depends { name: "lib" } Depends { name: "mod" } name: "app" consoleApplication: true files: ["main.m"] cpp.frameworks: ["Foundation"] cpp.rpaths: [cpp.rpathOrigin] cpp.minimumMacosVersion: "10.6" bundle.infoPlist: ({ "QBS": "org.qt-project.qbs.testdata.embedInfoPlist" }) install: true installDir: "" } DynamicLibrary { Depends { name: "cpp" } name: "lib" bundle.isBundle: false bundle.embedInfoPlist: true files: ["main.m"] cpp.frameworks: ["Foundation"] cpp.sonamePrefix: "@rpath" bundle.infoPlist: ({ "QBS": "org.qt-project.qbs.testdata.embedInfoPlist.dylib" }) install: true installDir: "" } LoadableModule { Depends { name: "cpp" } name: "mod" bundle.isBundle: false bundle.embedInfoPlist: true files: ["main.m"] cpp.frameworks: ["Foundation"] bundle.infoPlist: ({ "QBS": "org.qt-project.qbs.testdata.embedInfoPlist.bundle" }) Group { fileTagsFilter: product.type qbs.install: true } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/embedInfoPlist/main.m000066400000000000000000000005361347155106100257730ustar00rootroot00000000000000#import int main() { NSDictionary *infoPlist = [[NSBundle mainBundle] infoDictionary]; BOOL success = [[infoPlist objectForKey:@"QBS"] isEqualToString:@"org.qt-project.qbs.testdata.embedInfoPlist"]; fprintf(success ? stdout : stderr, "%s\n", [[infoPlist description] UTF8String]); return success ? 0 : 1; } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/frameworkStructure/000077500000000000000000000000001347155106100256775ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/frameworkStructure/BaseResource000066400000000000000000000000001347155106100301720ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/frameworkStructure/Widget.cpp000066400000000000000000000023631347155106100276320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int foo() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/frameworkStructure/Widget.h000066400000000000000000000023461347155106100273000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int foo(); qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/frameworkStructure/WidgetPrivate.h000066400000000000000000000023321347155106100306260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/frameworkStructure/en.lproj/000077500000000000000000000000001347155106100274265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/frameworkStructure/en.lproj/EnglishResource000066400000000000000000000000001347155106100324400ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/frameworkStructure/frameworkStructure.qbs000066400000000000000000000007541347155106100323320ustar00rootroot00000000000000Project { property bool includeHeaders: true Library { Depends { name: "cpp" } name: "Widget" bundle.isBundle: true bundle.publicHeaders: project.includeHeaders ? ["Widget.h"] : undefined bundle.privateHeaders: project.includeHeaders ? ["WidgetPrivate.h"] : base bundle.resources: ["BaseResource", "en.lproj/EnglishResource"] files: ["Widget.cpp"].concat(bundle.publicHeaders || []).concat(bundle.privateHeaders || []) } } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/000077500000000000000000000000001347155106100223535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/000077500000000000000000000000001347155106100250255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/EmptyStoryboard.storyboard000066400000000000000000000007311347155106100323070ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/MainMenu.xib000066400000000000000000006367341347155106100272650ustar00rootroot00000000000000 1080 11D50 2457 1138.32 568.00 com.apple.InterfaceBuilder.CocoaPlugin 2457 NSWindowTemplate NSView NSMenu NSMenuItem NSCustomObject com.apple.InterfaceBuilder.CocoaPlugin PluginDependencyRecalculationVersion NSApplication FirstResponder NSApplication AMainMenu Test 1048576 2147483647 NSImage NSMenuCheckmark NSImage NSMenuMixedState submenuAction: Test About Test 2147483647 YES YES 1048576 2147483647 Preferences… , 1048576 2147483647 YES YES 1048576 2147483647 Services 1048576 2147483647 submenuAction: Services _NSServicesMenu YES YES 1048576 2147483647 Hide Test h 1048576 2147483647 Hide Others h 1572864 2147483647 Show All 1048576 2147483647 YES YES 1048576 2147483647 Quit Test q 1048576 2147483647 _NSAppleMenu File 1048576 2147483647 submenuAction: File New n 1048576 2147483647 Open… o 1048576 2147483647 Open Recent 1048576 2147483647 submenuAction: Open Recent Clear Menu 1048576 2147483647 _NSRecentDocumentsMenu YES YES 1048576 2147483647 Close w 1048576 2147483647 Save… s 1048576 2147483647 Revert to Saved 2147483647 YES YES 1048576 2147483647 Page Setup... P 1179648 2147483647 Print… p 1048576 2147483647 Edit 1048576 2147483647 submenuAction: Edit Undo z 1048576 2147483647 Redo Z 1179648 2147483647 YES YES 1048576 2147483647 Cut x 1048576 2147483647 Copy c 1048576 2147483647 Paste v 1048576 2147483647 Paste and Match Style V 1572864 2147483647 Delete 1048576 2147483647 Select All a 1048576 2147483647 YES YES 1048576 2147483647 Find 1048576 2147483647 submenuAction: Find Find… f 1048576 2147483647 1 Find and Replace… f 1572864 2147483647 12 Find Next g 1048576 2147483647 2 Find Previous G 1179648 2147483647 3 Use Selection for Find e 1048576 2147483647 7 Jump to Selection j 1048576 2147483647 Spelling and Grammar 1048576 2147483647 submenuAction: Spelling and Grammar Show Spelling and Grammar : 1048576 2147483647 Check Document Now ; 1048576 2147483647 YES YES 2147483647 Check Spelling While Typing 1048576 2147483647 Check Grammar With Spelling 1048576 2147483647 Correct Spelling Automatically 2147483647 Substitutions 1048576 2147483647 submenuAction: Substitutions Show Substitutions 2147483647 YES YES 2147483647 Smart Copy/Paste f 1048576 2147483647 1 Smart Quotes g 1048576 2147483647 2 Smart Dashes 2147483647 Smart Links G 1179648 2147483647 3 Text Replacement 2147483647 Transformations 2147483647 submenuAction: Transformations Make Upper Case 2147483647 Make Lower Case 2147483647 Capitalize 2147483647 Speech 1048576 2147483647 submenuAction: Speech Start Speaking 1048576 2147483647 Stop Speaking 1048576 2147483647 Format 2147483647 submenuAction: Format Font 2147483647 submenuAction: Font Show Fonts t 1048576 2147483647 Bold b 1048576 2147483647 2 Italic i 1048576 2147483647 1 Underline u 1048576 2147483647 YES YES 2147483647 Bigger + 1048576 2147483647 3 Smaller - 1048576 2147483647 4 YES YES 2147483647 Kern 2147483647 submenuAction: Kern Use Default 2147483647 Use None 2147483647 Tighten 2147483647 Loosen 2147483647 Ligatures 2147483647 submenuAction: Ligatures Use Default 2147483647 Use None 2147483647 Use All 2147483647 Baseline 2147483647 submenuAction: Baseline Use Default 2147483647 Superscript 2147483647 Subscript 2147483647 Raise 2147483647 Lower 2147483647 YES YES 2147483647 Show Colors C 1048576 2147483647 YES YES 2147483647 Copy Style c 1572864 2147483647 Paste Style v 1572864 2147483647 _NSFontMenu Text 2147483647 submenuAction: Text Align Left { 1048576 2147483647 Center | 1048576 2147483647 Justify 2147483647 Align Right } 1048576 2147483647 YES YES 2147483647 Writing Direction 2147483647 submenuAction: Writing Direction YES Paragraph 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 YES Selection 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 Show Ruler 2147483647 Copy Ruler c 1310720 2147483647 Paste Ruler v 1310720 2147483647 View 1048576 2147483647 submenuAction: View Show Toolbar t 1572864 2147483647 Customize Toolbar… 1048576 2147483647 Window 1048576 2147483647 submenuAction: Window Minimize m 1048576 2147483647 Zoom 1048576 2147483647 YES YES 1048576 2147483647 Bring All to Front 1048576 2147483647 _NSWindowsMenu Help 2147483647 submenuAction: Help Test Help ? 1048576 2147483647 _NSHelpMenu _NSMainMenu 15 2 {{335, 390}, {480, 360}} 1954021376 Test NSWindow 256 {480, 360} {{0, 0}, {2560, 1418}} {10000000000000, 10000000000000} YES AppDelegate NSFontManager terminate: 449 orderFrontStandardAboutPanel: 142 delegate 495 performMiniaturize: 37 arrangeInFront: 39 print: 86 runPageLayout: 87 clearRecentDocuments: 127 performClose: 193 toggleContinuousSpellChecking: 222 undo: 223 copy: 224 checkSpelling: 225 paste: 226 stopSpeaking: 227 cut: 228 showGuessPanel: 230 redo: 231 selectAll: 232 startSpeaking: 233 delete: 235 performZoom: 240 performFindPanelAction: 241 centerSelectionInVisibleArea: 245 toggleGrammarChecking: 347 toggleSmartInsertDelete: 355 toggleAutomaticQuoteSubstitution: 356 toggleAutomaticLinkDetection: 357 saveDocument: 362 revertDocumentToSaved: 364 runToolbarCustomizationPalette: 365 toggleToolbarShown: 366 hide: 367 hideOtherApplications: 368 unhideAllApplications: 370 newDocument: 373 openDocument: 374 raiseBaseline: 426 lowerBaseline: 427 copyFont: 428 subscript: 429 superscript: 430 tightenKerning: 431 underline: 432 orderFrontColorPanel: 433 useAllLigatures: 434 loosenKerning: 435 pasteFont: 436 unscript: 437 useStandardKerning: 438 useStandardLigatures: 439 turnOffLigatures: 440 turnOffKerning: 441 toggleAutomaticSpellingCorrection: 456 orderFrontSubstitutionsPanel: 458 toggleAutomaticDashSubstitution: 461 toggleAutomaticTextReplacement: 463 uppercaseWord: 464 capitalizeWord: 467 lowercaseWord: 468 pasteAsPlainText: 486 performFindPanelAction: 487 performFindPanelAction: 488 performFindPanelAction: 489 showHelp: 493 alignCenter: 518 pasteRuler: 519 toggleRuler: 520 alignRight: 521 copyRuler: 522 alignJustified: 523 alignLeft: 524 makeBaseWritingDirectionNatural: 525 makeBaseWritingDirectionLeftToRight: 526 makeBaseWritingDirectionRightToLeft: 527 makeTextWritingDirectionNatural: 528 makeTextWritingDirectionLeftToRight: 529 makeTextWritingDirectionRightToLeft: 530 performFindPanelAction: 535 addFontTrait: 421 addFontTrait: 422 modifyFont: 423 orderFrontFontPanel: 424 modifyFont: 425 window 532 0 -2 File's Owner -1 First Responder -3 Application 29 19 56 217 83 81 75 78 72 82 124 77 73 79 112 74 125 126 205 202 198 207 214 199 203 197 206 215 218 216 200 219 201 204 220 213 210 221 208 209 57 58 134 150 136 144 129 143 236 131 149 145 130 24 92 5 239 23 295 296 297 298 211 212 195 196 346 348 349 350 351 354 371 372 375 376 377 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 450 451 452 453 454 457 459 460 462 465 466 485 490 491 492 494 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 534 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin {{380, 496}, {480, 360}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin 535 ABCardController NSObject id id id id id id id addCardViewField: id copy: id cut: id doDelete: id find: id paste: id saveChanges: id ABCardView NSButton NSManagedObjectContext NSSearchField NSTextField NSWindow mCardView ABCardView mEditButton NSButton mManagedObjectContext NSManagedObjectContext mSearchField NSSearchField mStatusTextField NSTextField mWindow NSWindow IBProjectSource ./Classes/ABCardController.h ABCardView NSView id id commitAndSave: id statusImageClicked: id NSObjectController NSImageView NSView ABNameFrameView NSView NSImage ABImageView mBindingsController NSObjectController mBuddyStatusImage NSImageView mHeaderView NSView mNameView ABNameFrameView mNextKeyView NSView mUserImage NSImage mUserImageView ABImageView IBProjectSource ./Classes/ABCardView.h ABImageView NSImageView id id id id copy: id cut: id delete: id paste: id IBProjectSource ./Classes/ABImageView.h DVTBorderedView DVTLayoutView_ML contentView NSView contentView contentView NSView IBProjectSource ./Classes/DVTBorderedView.h DVTDelayedMenuButton NSButton IBProjectSource ./Classes/DVTDelayedMenuButton.h DVTGradientImageButton NSButton IBProjectSource ./Classes/DVTGradientImageButton.h DVTImageAndTextCell NSTextFieldCell IBProjectSource ./Classes/DVTImageAndTextCell.h DVTImageAndTextColumn NSTableColumn IBProjectSource ./Classes/DVTImageAndTextColumn.h DVTLayoutView_ML NSView IBProjectSource ./Classes/DVTLayoutView_ML.h DVTOutlineView NSOutlineView IBProjectSource ./Classes/DVTOutlineView.h DVTSplitView NSSplitView IBProjectSource ./Classes/DVTSplitView.h DVTStackView_ML DVTLayoutView_ML IBProjectSource ./Classes/DVTStackView_ML.h DVTTableView NSTableView IBProjectSource ./Classes/DVTTableView.h DVTViewController NSViewController IBProjectSource ./Classes/DVTViewController.h HFController NSObject selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFController.h HFRepresenterTextView NSView selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFRepresenterTextView.h IBEditor NSObject id id id id id changeFont: id performCopy: id performCut: id selectAll: id sizeSelectionToFit: id IBProjectSource ./Classes/IBEditor.h IDECapsuleListView DVTStackView_ML dataSource id dataSource dataSource id IBProjectSource ./Classes/IDECapsuleListView.h IDEDMArrayController NSArrayController IBProjectSource ./Classes/IDEDMArrayController.h IDEDMEditor IDEEditor DVTBorderedView NSView IDEDMEditorSourceListController DVTSplitView bottomToolbarBorderView DVTBorderedView sourceListSplitViewPane NSView sourceListViewController IDEDMEditorSourceListController splitView DVTSplitView IBProjectSource ./Classes/IDEDMEditor.h IDEDMEditorController IDEViewController IBProjectSource ./Classes/IDEDMEditorController.h IDEDMEditorSourceListController IDEDMEditorController DVTBorderedView IDEDMEditor DVTImageAndTextColumn DVTOutlineView NSTreeController borderedView DVTBorderedView parentEditor IDEDMEditor primaryColumn DVTImageAndTextColumn sourceListOutlineView DVTOutlineView sourceListTreeController NSTreeController IBProjectSource ./Classes/IDEDMEditorSourceListController.h IDEDMHighlightImageAndTextCell DVTImageAndTextCell IBProjectSource ./Classes/IDEDMHighlightImageAndTextCell.h IDEDataModelBrowserEditor IDEDMEditorController IDEDataModelPropertiesTableController IDECapsuleListView NSArrayController IDEDataModelPropertiesTableController IDEDataModelEntityContentsEditor IDEDataModelPropertiesTableController attributesTableViewController IDEDataModelPropertiesTableController capsuleView IDECapsuleListView entityArrayController NSArrayController fetchedPropertiesTableViewController IDEDataModelPropertiesTableController parentEditor IDEDataModelEntityContentsEditor relationshipsTableViewController IDEDataModelPropertiesTableController IBProjectSource ./Classes/IDEDataModelBrowserEditor.h IDEDataModelConfigurationEditor IDEDMEditorController IDECapsuleListView IDEDataModelEditor IDEDataModelConfigurationTableController capsuleListView IDECapsuleListView parentEditor IDEDataModelEditor tableController IDEDataModelConfigurationTableController IBProjectSource ./Classes/IDEDataModelConfigurationEditor.h IDEDataModelConfigurationTableController IDEDMEditorController NSArrayController NSArrayController IDEDataModelConfigurationEditor XDTableView configurationsArrayController NSArrayController entitiesArrayController NSArrayController parentEditor IDEDataModelConfigurationEditor tableView XDTableView IBProjectSource ./Classes/IDEDataModelConfigurationTableController.h IDEDataModelDiagramEditor IDEDMEditorController XDDiagramView IDEDataModelEntityContentsEditor diagramView XDDiagramView parentEditor IDEDataModelEntityContentsEditor IBProjectSource ./Classes/IDEDataModelDiagramEditor.h IDEDataModelEditor IDEDMEditor DVTDelayedMenuButton DVTDelayedMenuButton NSSegmentedControl IDEDataModelConfigurationEditor IDEDataModelEntityContentsEditor IDEDataModelFetchRequestEditor NSSegmentedControl NSTabView addEntityButton DVTDelayedMenuButton addPropertyButton DVTDelayedMenuButton browserDiagramSegmentControl NSSegmentedControl configurationViewController IDEDataModelConfigurationEditor entityContentsViewController IDEDataModelEntityContentsEditor fetchRequestViewController IDEDataModelFetchRequestEditor hierarchySegmentControl NSSegmentedControl tabView NSTabView IBProjectSource ./Classes/IDEDataModelEditor.h IDEDataModelEntityContentsEditor IDEDMEditorController IDEDataModelBrowserEditor IDEDataModelDiagramEditor IDEDataModelEditor NSTabView browserViewController IDEDataModelBrowserEditor diagramViewController IDEDataModelDiagramEditor parentEditor IDEDataModelEditor tabView NSTabView IBProjectSource ./Classes/IDEDataModelEntityContentsEditor.h IDEDataModelFetchRequestEditor IDEDMEditorController NSArrayController IDEDataModelEditor IDECapsuleListView entityController NSArrayController parentEditor IDEDataModelEditor tableView IDECapsuleListView IBProjectSource ./Classes/IDEDataModelFetchRequestEditor.h IDEDataModelPropertiesTableController IDEDMEditorController IDEDMArrayController NSTableColumn NSArrayController IDEDataModelBrowserEditor IDEDMHighlightImageAndTextCell XDTableView arrayController IDEDMArrayController entitiesColumn NSTableColumn entityArrayController NSArrayController parentEditor IDEDataModelBrowserEditor propertyNameAndImageCell IDEDMHighlightImageAndTextCell tableView XDTableView IBProjectSource ./Classes/IDEDataModelPropertiesTableController.h IDEDocDownloadsTableViewController NSObject NSButtonCell DVTTableView IDEDocViewingPrefPaneController _downloadButtonCell NSButtonCell _tableView DVTTableView prefPaneController IDEDocViewingPrefPaneController IBProjectSource ./Classes/IDEDocDownloadsTableViewController.h IDEDocSetOutlineView NSOutlineView IBProjectSource ./Classes/IDEDocSetOutlineView.h IDEDocSetOutlineViewController NSObject id id id id id getDocSetAction: id showProblemInfoForUpdate: id subscribeToPublisherAction: id unsubscribeFromPublisher: id updateDocSetAction: id docSetOutlineView IDEDocSetOutlineView docSetOutlineView docSetOutlineView IDEDocSetOutlineView IBProjectSource ./Classes/IDEDocSetOutlineViewController.h IDEDocViewingPrefPaneController IDEViewController id id id id id id id id id id id addSubscription: id checkForAndInstallUpdatesNow: id deleteDocSet: id downloadAction: id minimumFontSizeComboBoxAction: id minimumFontSizeEnabledAction: id showHelp: id showSubscriptionSheet: id subscriptionCancelAction: id toggleAutoCheckForAndInstallUpdates: id toggleDocSetInfo: id DVTGradientImageButton DVTGradientImageButton DVTGradientImageButton NSSplitView NSView NSView DVTBorderedView DVTBorderedView NSButton NSTextView IDEDocSetOutlineViewController IDEDocDownloadsTableViewController NSComboBox NSTextField NSButton NSTextField NSWindow NSButton _addButton DVTGradientImageButton _deleteButton DVTGradientImageButton _showInfoAreaButton DVTGradientImageButton _splitView NSSplitView _splitViewDocSetInfoSubview NSView _splitViewDocSetsListSubview NSView borderedViewAroundSplitView DVTBorderedView borderedViewBelowTable DVTBorderedView checkAndInstallNowButton NSButton docSetInfoTextView NSTextView docSetOutlineViewController IDEDocSetOutlineViewController downloadsTableViewController IDEDocDownloadsTableViewController minimumFontSizeControl NSComboBox noUpdatesAvailableMessage NSTextField showInfoButton NSButton subscriptionTextField NSTextField subscriptionWindow NSWindow validateAddSubscriptionButton NSButton IBProjectSource ./Classes/IDEDocViewingPrefPaneController.h IDEEditor IDEViewController IBProjectSource ./Classes/IDEEditor.h IDEViewController DVTViewController IBProjectSource ./Classes/IDEViewController.h IKImageView id id id id copy: id crop: id cut: id paste: id IBProjectSource ./Classes/IKImageView.h NSDocument id id id id id id printDocument: id revertDocumentToSaved: id runPageLayout: id saveDocument: id saveDocumentAs: id saveDocumentTo: id IBProjectSource ./Classes/NSDocument.h NSResponder _insertFindPattern: id _insertFindPattern: _insertFindPattern: id IBProjectSource ./Classes/NSResponder.h QLPreviewBubble NSObject id id hide: id show: id parentWindow NSWindow parentWindow parentWindow NSWindow IBProjectSource ./Classes/QLPreviewBubble.h QTMovieView id id id id id showAll: id showCustomButton: id toggleLoops: id zoomIn: id zoomOut: id IBProjectSource ./Classes/QTMovieView.h WebView id id id id reloadFromOrigin: id resetPageZoom: id zoomPageIn: id zoomPageOut: id IBProjectSource ./Classes/WebView.h XDDiagramView NSView id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id _graphLayouterMenuItemAction: id _zoomPopUpButtonAction: id alignBottomEdges: id alignCentersHorizontallyInContainer: id alignCentersVerticallyInContainer: id alignHorizontalCenters: id alignLeftEdges: id alignRightEdges: id alignTopEdges: id alignVerticalCenters: id bringToFront: id collapseAllCompartments: id copy: id cut: id delete: id deleteBackward: id deleteForward: id deselectAll: id diagramZoomIn: id diagramZoomOut: id expandAllCompartments: id flipHorizontally: id flipVertically: id layoutGraphicsConcentrically: id layoutGraphicsHierarchically: id lock: id makeSameHeight: id makeSameWidth: id moveDown: id moveDownAndModifySelection: id moveLeft: id moveLeftAndModifySelection: id moveRight: id moveRightAndModifySelection: id moveUp: id moveUpAndModifySelection: id paste: id rollDownAllCompartments: id rollUpAllCompartments: id selectAll: id sendToBack: id sizeToFit: id toggleGridShown: id toggleHiddenGraphicsShown: id togglePageBreaksShown: id toggleRuler: id toggleSnapsToGrid: id unlock: id _diagramController IDEDataModelDiagramEditor _diagramController _diagramController IDEDataModelDiagramEditor IBProjectSource ./Classes/XDDiagramView.h XDTableView NSTableView showAllTableColumns: id showAllTableColumns: showAllTableColumns: id IBProjectSource ./Classes/XDTableView.h AppDelegate NSObject id id applicationShouldTerminate: id applicationWillFinishLaunching: id IBProjectSource ./Classes/AppDelegate.h 0 IBCocoaFramework YES 3 {11, 11} {10, 3} YES qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/Storyboard.storyboard000066400000000000000000000054061347155106100312740ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/assetcatalogempty.qbs000066400000000000000000000013311347155106100312630ustar00rootroot00000000000000import qbs.Utilities Project { property bool includeIconset CppApplication { Depends { name: "ib" } files: { var filez = ["main.c", "MainMenu.xib"]; if (project.includeIconset) filez.push("empty.xcassets/empty.iconset"); else if (Utilities.versionCompare(xcode.version, "5") >= 0) filez.push("empty.xcassets"); if (qbs.hostOSVersionMinor >= 10 // need macOS 10.10 to build SBs && cpp.minimumMacosVersion !== undefined && Utilities.versionCompare(cpp.minimumMacosVersion, "10.10") >= 0) filez.push("Storyboard.storyboard"); return filez; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/000077500000000000000000000000001347155106100300175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/empty.iconset/000077500000000000000000000000001347155106100326205ustar00rootroot00000000000000icon_16x16.png000066400000000000000000000012111347155106100350370ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/empty.iconset‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚icon_16x16@2x.png000066400000000000000000000012311347155106100354130ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/empty.iconset‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/other.imageset/000077500000000000000000000000001347155106100327355ustar00rootroot00000000000000Contents.json000066400000000000000000000005331347155106100353470ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/other.imageset{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }icon_16x16.png000066400000000000000000000012111347155106100351540ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/other.imageset‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚icon_16x16@2x.png000066400000000000000000000012311347155106100355300ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/empty.xcassets/other.imageset‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/assetcatalog/main.c000066400000000000000000000023701347155106100261170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/000077500000000000000000000000001347155106100264215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/assetcatalog1.xcassets/000077500000000000000000000000001347155106100330105ustar00rootroot00000000000000.keep000066400000000000000000000000001347155106100336440ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/assetcatalog1.xcassetsqbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/assetcatalog2.xcassets/000077500000000000000000000000001347155106100330115ustar00rootroot00000000000000.keep000066400000000000000000000000001347155106100336450ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/assetcatalog2.xcassetsqbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogs/main.c000066400000000000000000000023641347155106100275160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } multiple-asset-catalogs.qbs000066400000000000000000000002261347155106100336140ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/empty-asset-catalogsCppApplication { Depends { name: "ib" } files: [ "main.c", "assetcatalog1.xcassets", "assetcatalog2.xcassets" ] } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/iconset/000077500000000000000000000000001347155106100240175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/iconset/iconset.qbs000066400000000000000000000001271347155106100261720ustar00rootroot00000000000000Product { Depends { name: "ib" } type: ["icns"] files: ["white.iconset"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/iconset/white.iconset/000077500000000000000000000000001347155106100266025ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/iconset/white.iconset/icon_16x16.png000066400000000000000000000012111347155106100311000ustar00rootroot00000000000000‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/iconset/white.iconset/icon_16x16@2x.png000066400000000000000000000012311347155106100314540ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/000077500000000000000000000000001347155106100245205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/iconsetapp.qbs000066400000000000000000000001251347155106100273720ustar00rootroot00000000000000CppApplication { Depends { name: "ib" } files: ["main.c", "white.iconset"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/main.c000066400000000000000000000023701347155106100256120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/white.iconset/000077500000000000000000000000001347155106100273035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/white.iconset/icon_16x16.png000066400000000000000000000012111347155106100316010ustar00rootroot00000000000000‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/iconsetapp/white.iconset/icon_16x16@2x.png000066400000000000000000000012311347155106100321550ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/000077500000000000000000000000001347155106100271165ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/000077500000000000000000000000001347155106100335055ustar00rootroot00000000000000other.imageset/000077500000000000000000000000001347155106100363445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassetsContents.json000066400000000000000000000005331347155106100410350ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/other.imageset{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }icon_16x16.png000066400000000000000000000012111347155106100406420ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/other.imageset‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚icon_16x16@2x.png000066400000000000000000000012311347155106100412160ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog1.xcassets/other.imageset‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/000077500000000000000000000000001347155106100335065ustar00rootroot00000000000000other.imageset/000077500000000000000000000000001347155106100363455ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassetsContents.json000066400000000000000000000005331347155106100410360ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/other.imageset{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }icon_16x16.png000066400000000000000000000012111347155106100406430ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/other.imageset‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚icon_16x16@2x.png000066400000000000000000000012311347155106100412170ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/assetcatalog2.xcassets/other.imageset‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogs/main.c000066400000000000000000000023641347155106100302130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } multiple-asset-catalogs.qbs000066400000000000000000000002261347155106100343110ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/ib/multiple-asset-catalogsCppApplication { Depends { name: "ib" } files: [ "main.c", "assetcatalog1.xcassets", "assetcatalog2.xcassets" ] } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/infoplist/000077500000000000000000000000001347155106100237705ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/infoplist/infoplist.qbs000066400000000000000000000001151347155106100265030ustar00rootroot00000000000000CppApplication { cpp.minimumMacosVersion: "10.7" files: ["main.c"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/infoplist/main.c000066400000000000000000000023641347155106100250650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/objc-arc/000077500000000000000000000000001347155106100234415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/objc-arc/arc.m000066400000000000000000000001071347155106100243620ustar00rootroot00000000000000#if !__has_feature(objc_arc) #error Not using ARC but should be #endif qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/objc-arc/arc.mm000066400000000000000000000001071347155106100245370ustar00rootroot00000000000000#if !__has_feature(objc_arc) #error Not using ARC but should be #endif qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/objc-arc/main.m000066400000000000000000000001361347155106100245430ustar00rootroot00000000000000#if __has_feature(objc_arc) #error Using ARC but shouldn't be #endif int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/objc-arc/mrc.m000066400000000000000000000001051347155106100243740ustar00rootroot00000000000000#if __has_feature(objc_arc) #error Using ARC but shouldn't be #endif qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/objc-arc/mrc.mm000066400000000000000000000001051347155106100245510ustar00rootroot00000000000000#if __has_feature(objc_arc) #error Using ARC but shouldn't be #endif qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/objc-arc/objc-arc.qbs000066400000000000000000000006161347155106100256330ustar00rootroot00000000000000Product { Depends { name: "cpp" } consoleApplication: true type: ["application"] condition: qbs.targetOS.contains("darwin") Group { cpp.automaticReferenceCounting: true files: ["arc.m", "arc.mm"] } Group { cpp.automaticReferenceCounting: false files: ["mrc.m", "mrc.mm"] } files: "main.m" cpp.minimumMacosVersion: "10.7" } qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/xcode/000077500000000000000000000000001347155106100230635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs000066400000000000000000000025241347155106100263430ustar00rootroot00000000000000Project { property stringList sdks: [] Product { Depends { name: "xcode" } consoleApplication: { console.info("Developer directory: " + xcode.developerPath); console.info("SDK: " + xcode.sdk); console.info("Target devices: " + xcode.targetDevices.join(", ")); console.info("SDK name: " + xcode.sdkName); console.info("SDK version: " + xcode.sdkVersion); console.info("Latest SDK name: " + xcode.latestSdkName); console.info("Latest SDK version: " + xcode.latestSdkVersion); console.info("Available SDK names: " + xcode.availableSdkNames.join(", ")); console.info("Available SDK versions: " + xcode.availableSdkVersions.join(", ")); console.info("Actual SDK list: " + project.sdks.join(", ")); var msg = "Unexpected SDK list [" + xcode.availableSdkVersions.join(", ") + "]"; var testArraysEqual = function(a, b) { if (!a || !b || a.length !== b.length) { throw msg; } for (var i = 0; i < a.length; ++i) { if (a[i] !== b[i]) { throw msg; } } } testArraysEqual(project.sdks, xcode.availableSdkVersions); } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-clangdb/000077500000000000000000000000001347155106100222525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-clangdb/project1/000077500000000000000000000000001347155106100240015ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-clangdb/project1/i like spaces.cpp000066400000000000000000000027471347155106100271130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include using namespace std; #define _STR(x) #x #define STR(x) _STR(x) int main(int argc, char **argv) { int garbage; int unused = garbage; cout << "SPACES=" << SPACES << "SPICES=" STR(SPICES) << "SLICES=" << SLICES << endl; return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-clangdb/project1/project.qbs000066400000000000000000000021271347155106100261600ustar00rootroot00000000000000// $ g++ 'i like spaces.cpp' '-DSPACES="!have \\fun\x5c!\n"' '-DSPICES=%T% # && $$ 1>&2 '\''\n'\''\n' '-DSLICES=(42>24)' && ./a.out // SPACES=!have \fun\! // SPICES=%T% # && $$ 1>&2 '\n' // SLICES=1 Project { Application { Probe { id: dummy property bool isMingw: qbs.toolchain.contains("mingw") property bool isMsvc: qbs.toolchain.contains("msvc") property var buildEnv: cpp.buildEnv configure: { if (!buildEnv) return; if (isMsvc) { console.info("is msvc"); console.info("INCLUDE=" + buildEnv["INCLUDE"]); console.info("LIB=" + buildEnv["LIB"]); } else if (isMingw) { console.info("is mingw"); console.info("PATH=" + buildEnv["PATH"]); } } } targetName: "i like spaces" Depends { name: "cpp" } cpp.defines: base.concat([ "SPACES=\"!have \\\\fun\\x5c!\\n\"", "SPICES=%T% # && $$ 1>&2 '\\n'\\n", "SLICES=(42>24)" ]); files: ["i like spaces.cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/000077500000000000000000000000001347155106100216015ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/000077500000000000000000000000001347155106100225225ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/Car.java000066400000000000000000000006551347155106100241000ustar00rootroot00000000000000class Car implements Vehicle { private InternalCombustionEngine engine; public Car() { engine = new InternalCombustionEngine(); } public void go() { System.out.println("Driving!"); engine.run(); } public class InternalCombustionEngine { public native void run(); public class ChemicalReaction { public native void occur(); } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/Car8.java000066400000000000000000000010721347155106100241620ustar00rootroot00000000000000class Car8 implements Vehicle { private InternalCombustionEngine engine; public Car8() { engine = new InternalCombustionEngine(); } public void go() { System.out.println("Driving!"); engine.run(); } public class InternalCombustionEngine { public native void run(); public class ChemicalReaction { public native void occur(); public class Atoms { @java.lang.annotation.Native public int hydrogenAtomCount; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/HelloWorld.java000066400000000000000000000004371347155106100254440ustar00rootroot00000000000000package io.qt.qbs; public class HelloWorld { public static void main(String[] args) { System.out.println("Tach."); } public class Internal { public native void something(); } public class Other { public final int countOfThings = 0; } } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/HelloWorld8.java000066400000000000000000000002411347155106100255250ustar00rootroot00000000000000package io.qt.qbs; public class HelloWorld8 { public class Other { @java.lang.annotation.Native public final int countOfThings = 0; } } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/Jet.java000066400000000000000000000001511347155106100241040ustar00rootroot00000000000000class Jet implements Vehicle { public void go() { System.out.println("Flying!"); } } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/Manifest.mf000066400000000000000000000000321347155106100246070ustar00rootroot00000000000000Some-Property: Some-Value qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/Manifest2.mf000066400000000000000000000001001347155106100246650ustar00rootroot00000000000000Some-Property: Some-Value Additional-Property: Additional-Value qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/NoPackage.java000066400000000000000000000001461347155106100252160ustar00rootroot00000000000000// package this.should.not.be.parsed; public class NoPackage { public static void doSomething() {} } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/RandomStuff.java000066400000000000000000000001211347155106100256070ustar00rootroot00000000000000package glob; public class RandomStuff { public static void bar() { } } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/Ship.java000066400000000000000000000003641347155106100242730ustar00rootroot00000000000000class Ship implements Vehicle { public boolean isInSpace; public void go() { if (isInSpace) System.out.println("Flying (this is a space ship)!"); else System.out.println("Sailing!"); } } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/Vehicle.java000066400000000000000000000000541347155106100247430ustar00rootroot00000000000000interface Vehicle { public void go(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/Vehicles.java000066400000000000000000000014231347155106100251270ustar00rootroot00000000000000import java.util.ArrayList; import glob.RandomStuff; class Vehicles { public static void main(String[] args) { System.loadLibrary("native"); RandomStuff.bar(); ArrayList vehicles = new ArrayList(); for (int i = 0; i < 3; i++) { vehicles.add(new Car()); } for (int i = 0; i < 3; i++) { vehicles.add(new Jet()); } for (int i = 0; i < 4; i++) { Ship ship = new Ship(); ship.isInSpace = i % 2 == 0; vehicles.add(ship); } for (int i = 0; i < vehicles.size(); i++) { vehicles.get(i).go(); } // doesn't compile, must be a bug // delete vehicles; } } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/engine.c000066400000000000000000000030521347155106100241330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include // javac 1.8 is required to generate native headers #ifdef JNI_VERSION_1_8 #include "Car_InternalCombustionEngine.h" #endif JNIEXPORT void JNICALL Java_Car_00024InternalCombustionEngine_run(JNIEnv *env, jobject obj) { printf("Native code performing complex internal combustion process (%p, %p)!\n", env, obj); } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/inner-class/000077500000000000000000000000001347155106100247405ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/inner-class/InnerClass.java000066400000000000000000000002101347155106100276350ustar00rootroot00000000000000public class InnerClass { private final InnerInnerClass clazz = new InnerInnerClass(); private class InnerInnerClass { } } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/inner-class/inner-class.qbs000066400000000000000000000000511347155106100276610ustar00rootroot00000000000000JavaJarFile { files: ["**/*.java"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-java/java/vehicles.qbs000066400000000000000000000052731347155106100250420ustar00rootroot00000000000000import qbs.FileInfo import qbs.Utilities Project { DynamicLibrary { Depends { name: "cpp" } Depends { name: "car_jar" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } name: "native" files: ["engine.c"] qbs.installPrefix: "" install: true installDir: "" } JavaClassCollection { Depends { name: "random_stuff" } name: "cc" java.additionalCompilerFlags: ["-Xlint:all"] files: [ "Car.java", "HelloWorld.java", "Jet.java", "NoPackage.java", "Ship.java", "Vehicle.java", "Vehicles.java" ] Group { condition: Utilities.versionCompare(java.version, "1.8") >= 0 files: ["Car8.java", "HelloWorld8.java"] } Export { Depends { name: "java" } java.manifestClassPath: [product.targetName + ".jar"] } } JavaJarFile { name: "random_stuff" files: ["RandomStuff.java"] qbs.installPrefix: "" Group { fileTagsFilter: ["java.jar"] qbs.install: true } Export { Depends { name: "java" } java.manifestClassPath: [product.targetName + ".jar"] } } JavaJarFile { name: "car_jar" files: ["Car.java", "Vehicle.java"] Group { condition: Utilities.versionCompare(java.version, "1.8") >= 0 files: ["Car8.java"] } Export { Depends { name: "cpp" } cpp.systemIncludePaths: { var paths = importingProduct.java.jdkIncludePaths; if (Utilities.versionCompare(importingProduct.java.version, "1.8") >= 0) { paths.push(product.buildDirectory); // generated JNI headers } return paths; } Depends { name: "java" } java.manifestClassPath: [product.targetName + ".jar"] } qbs.installPrefix: "" Group { fileTagsFilter: ["java.jar"] qbs.install: true } } JavaJarFile { Depends { name: "random_stuff" } Depends { name: "car_jar" } Depends { name: "native" } name: "jar_file" entryPoint: "Vehicles" files: ["Jet.java", "Ship.java", "Vehicles.java", "Manifest.mf", "Manifest2.mf"] java.manifest: { var mf = original; mf["Extra-Property"] = "Crazy-Value"; return mf; } qbs.installPrefix: "" Group { fileTagsFilter: ["java.jar"] qbs.install: true } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-joblimits/000077500000000000000000000000001347155106100226545ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-joblimits/job-limits/000077500000000000000000000000001347155106100247255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs000066400000000000000000000061071347155106100275110ustar00rootroot00000000000000import qbs.TextFile Project { property int projectJobCount property int productJobCount property int moduleJobCount JobLimit { condition: projectJobCount !== -1 jobPool: "singleton" jobCount: projectJobCount } JobLimit { condition: projectJobCount !== -1 jobPool: "singleton" jobCount: 100 } CppApplication { name: "tool" consoleApplication: true cpp.cxxLanguageVersion: "c++14" Properties { condition: qbs.targetOS.contains("macos") cpp.minimumMacosVersion: "10.9" } files: "main.cpp" Group { fileTagsFilter: "application" fileTags: "tool_tag" } Export { Rule { alwaysRun: true inputs: "tool_in" explicitlyDependsOnFromDependencies: "tool_tag" Artifact { filePath: input.completeBaseName + ".out"; fileTags: "tool_out" } prepare: { var cmd = new Command(explicitlyDependsOn.tool_tag[0].filePath, [output.filePath]); cmd.workingDirectory = product.buildDirectory; cmd.description = "Running tool"; cmd.jobPool = "singleton"; return cmd; } } JobLimit { condition: project.moduleJobCount !== -1 jobPool: "singleton" jobCount: project.moduleJobCount } JobLimit { condition: project.moduleJobCount !== -1 jobPool: "singleton" jobCount: 200 } } } Product { name: "p" type: "tool_out" Depends { name: "tool" } Rule { multiplex: true outputFileTags: "tool_in" outputArtifacts: { var artifacts = []; for (var i = 0; i < 7; ++i) artifacts.push({filePath: "file" + i + ".in", fileTags: "tool_in"}); return artifacts; } prepare: { var commands = []; for (var i = 0; i < outputs.tool_in.length; ++i) { var cmd = new JavaScriptCommand(); var output = outputs.tool_in[i]; cmd.output = output.filePath; cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output, TextFile.WriteOnly); f.close(); } commands.push(cmd); }; return commands; } } JobLimit { condition: project.productJobCount !== -1 jobPool: "singleton" jobCount: project.productJobCount } JobLimit { condition: project.productJobCount !== -1 jobPool: "singleton" jobCount: 300 } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-joblimits/job-limits/main.cpp000066400000000000000000000052741347155106100263650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #if defined(_WIN32) || defined(WIN32) #include #include #else #include #endif static bool tryLock(FILE *f) { const int exitCode = #if defined(_WIN32) || defined(WIN32) _locking(_fileno(f), _LK_NBLCK, 10); #else lockf(fileno(f), F_TLOCK, 10); #endif return exitCode == 0; } int main(int argc, char *argv[]) { if (argc != 2) { std::cerr << "tool needs exactly one argument" << std::endl; return 1; } const std::string lockFilePath = std::string(argv[0]) + ".lock"; std::FILE * const lockFile = std::fopen(lockFilePath.c_str(), "w"); if (!lockFile) { std::cerr << "cannot open lock file: " << strerror(errno) << std::endl; return 2; } if (!tryLock(lockFile)) { if (errno == EACCES || errno == EAGAIN) { std::cerr << "tool is exclusive" << std::endl; return 3; } else { std::cerr << "unexpected lock failure: " << strerror(errno) << std::endl; fclose(lockFile); return 4; } } std::this_thread::sleep_for(std::chrono::milliseconds(100)); fclose(lockFile); std::FILE * const output = std::fopen(argv[1], "w"); if (!output) { std::cerr << "cannot create output file: " << strerror(errno) << std::endl; return 5; } fclose(output); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/000077500000000000000000000000001347155106100213045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/add-qobject-macro-to-generated-cpp-file/000077500000000000000000000000001347155106100306315ustar00rootroot00000000000000add-qobject-macro-to-generated-cpp-file.qbs000066400000000000000000000011121347155106100406010ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/add-qobject-macro-to-generated-cpp-fileimport qbs.File QtApplication { name: "p" files: ["main.cpp", "object.h"] Group { files: "object.cpp.in" fileTags: "cpp.in" } Rule { inputs: "cpp.in" Artifact { filePath: input.completeBaseName fileTags: "cpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generatating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } cpp.includePaths: path } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/add-qobject-macro-to-generated-cpp-file/main.cpp000066400000000000000000000024301347155106100322600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.h" int main() { Object o; o.f(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/add-qobject-macro-to-generated-cpp-file/object.cpp.in000066400000000000000000000025671347155106100332220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include // class InternalClass : public QObject // { // Q_OBJECT // }; void Object::f() { } // #include qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/add-qobject-macro-to-generated-cpp-file/object.h000066400000000000000000000024031347155106100322470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ class Object { public: void f(); }; qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/auto-qrc/000077500000000000000000000000001347155106100230375ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/auto-qrc/auto-qrc.qbs000066400000000000000000000013121347155106100252760ustar00rootroot00000000000000Project { QtApplication { name: "app" files: ["main.cpp"] Group { prefix: "qrc-base/" Qt.core.resourcePrefix: "/thePrefix" Qt.core.resourceSourceBase: "qrc-base" files: ["resource1.txt"] fileTags: ["qt.core.resource_data"] Group { prefix: "qrc-base/subdir/" Qt.core.resourceSourceBase: "qrc-base/subdir" files: ["resource2.txt"] Group { prefix: "qrc-base/subdir/" Qt.core.resourcePrefix: "/theOtherPrefix" files: ["resource3.txt"] } } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/auto-qrc/main.cpp000066400000000000000000000010711347155106100244660ustar00rootroot00000000000000#include #include int main() { QFile resource1(":/thePrefix/resource1.txt"); if (!resource1.open(QIODevice::ReadOnly)) return 1; QFile resource2(":/thePrefix/resource2.txt"); if (!resource2.open(QIODevice::ReadOnly)) return 2; QFile resource3(":/theOtherPrefix/resource3.txt"); if (!resource3.open(QIODevice::ReadOnly)) return 3; std::cout << "resource data: " << resource1.readAll().constData() << resource2.readAll().constData() << resource3.readAll().constData() << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/auto-qrc/qrc-base/000077500000000000000000000000001347155106100245345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/auto-qrc/qrc-base/resource1.txt000066400000000000000000000000121347155106100271760ustar00rootroot00000000000000resource1 qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/auto-qrc/qrc-base/subdir/000077500000000000000000000000001347155106100260245ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/auto-qrc/qrc-base/subdir/resource2.txt000066400000000000000000000000121347155106100304670ustar00rootroot00000000000000resource2 qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/auto-qrc/qrc-base/subdir/resource3.txt000066400000000000000000000000121347155106100304700ustar00rootroot00000000000000resource3 qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/cached-qml/000077500000000000000000000000001347155106100233025ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/cached-qml/MainForm.ui.qml000066400000000000000000000011601347155106100261370ustar00rootroot00000000000000import QtQuick 2.6 Rectangle { property alias mouseArea: mouseArea property alias textEdit: textEdit width: 360 height: 360 MouseArea { id: mouseArea anchors.fill: parent } TextEdit { id: textEdit text: qsTr("Enter some text...") verticalAlignment: Text.AlignVCenter anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter anchors.topMargin: 20 Rectangle { anchors.fill: parent anchors.margins: -10 color: "transparent" border.width: 1 } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/cached-qml/cached-qml.qbs000066400000000000000000000016371347155106100260160ustar00rootroot00000000000000import qbs.Utilities CppApplication { name: "app" consoleApplication: true Depends { name: "Qt.core" } Depends { name: "Qt.quick" } Depends { name: "Qt.qml" } install: true installDir: "" qbs.installPrefix: "" Qt.qml.generateCacheFiles: true Qt.qml.cacheFilesInstallDir: "data" files: [ "main.cpp", "MainForm.ui.qml", "main.qml", "stuff.js" ] // Install the C++ sources to tell the blackbox test that Qt.qmlcache is not available. Group { condition: !Qt.qml.cachingEnabled fileTagsFilter: ["cpp"] qbs.install: true qbs.installDir: "data" } Probe { id: qtVersionProbe property string qtVersion: Qt.core.version configure: { console.info("qmlcachegen must work: " + (Utilities.versionCompare(qtVersion, "5.11") >= 0)) } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/cached-qml/main.cpp000066400000000000000000000005231347155106100247320ustar00rootroot00000000000000#include #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(qApp->applicationDirPath() + QStringLiteral("/data/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/cached-qml/main.qml000066400000000000000000000005201347155106100247360ustar00rootroot00000000000000import QtQuick 2.6 import QtQuick.Window 2.2 import "stuff.js" as Stuff Window { visible: true width: 640 height: 480 title: Stuff.title() MainForm { anchors.fill: parent mouseArea.onClicked: { console.log(qsTr('Clicked on background. Text: "' + textEdit.text + '"')) } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/cached-qml/qml.qrc000066400000000000000000000002311347155106100245760ustar00rootroot00000000000000 main.qml MainForm.ui.qml qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/cached-qml/stuff.js000066400000000000000000000000541347155106100247660ustar00rootroot00000000000000function title() { return "Wello Horld!"; } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/combined-moc/000077500000000000000000000000001347155106100236405ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/combined-moc/combined-moc.qbs000066400000000000000000000001431347155106100267010ustar00rootroot00000000000000QtApplication { name: "theapp" files: [ "main.cpp", "theobject.h", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/combined-moc/main.cpp000066400000000000000000000000751347155106100252720ustar00rootroot00000000000000#include "theobject.h" int main() { TheObject object; } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/combined-moc/theobject.h000066400000000000000000000001071347155106100257560ustar00rootroot00000000000000#include class TheObject : public QObject { Q_OBJECT }; qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/create-project/000077500000000000000000000000001347155106100242135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/create-project/dummy.txt000066400000000000000000000000001347155106100260750ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/000077500000000000000000000000001347155106100240545ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/THIS.IS.A.STRANGE.FILENAME.CAR.XML000066400000000000000000000006241347155106100305650ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/car.cpp000066400000000000000000000113601347155106100253260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "car.h" #include #include static const double Pi = 3.14159265358979323846264338327950288419717; QRectF Car::boundingRect() const { return {-35, -81, 70, 115}; } Car::Car() : color(Qt::green), wheelsAngle(0), speed(0) { startTimer(1000 / 33); setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsItem::ItemIsFocusable, true); } void Car::accelerate() { if (speed < 10) ++speed; } void Car::decelerate() { if (speed > -10) --speed; } void Car::turnLeft() { if (wheelsAngle > -30) wheelsAngle -= 5; } void Car::turnRight() { if (wheelsAngle < 30) wheelsAngle += 5; } void Car::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); painter->setBrush(Qt::gray); painter->drawRect(-20, -58, 40, 2); // front axel painter->drawRect(-20, 7, 40, 2); // rear axel painter->setBrush(color); painter->drawRect(-25, -79, 50, 10); // front wing painter->drawEllipse(-25, -48, 50, 20); // side pods painter->drawRect(-25, -38, 50, 35); // side pods painter->drawRect(-5, 9, 10, 10); // back pod painter->drawEllipse(-10, -81, 20, 100); // main body painter->drawRect(-17, 19, 34, 15); // rear wing painter->setBrush(Qt::black); painter->drawPie(-5, -51, 10, 15, 0, 180 * 16); painter->drawRect(-5, -44, 10, 10); // cocpit painter->save(); painter->translate(-20, -58); painter->rotate(wheelsAngle); painter->drawRect(-10, -7, 10, 15); // front left painter->restore(); painter->save(); painter->translate(20, -58); painter->rotate(wheelsAngle); painter->drawRect(0, -7, 10, 15); // front left painter->restore(); painter->drawRect(-30, 0, 12, 17); // rear left painter->drawRect(19, 0, 12, 17); // rear right } void Car::timerEvent(QTimerEvent *event) { Q_UNUSED(event); const qreal axelDistance = 54; qreal wheelsAngleRads = (wheelsAngle * Pi) / 180; qreal turnDistance = ::cos(wheelsAngleRads) * axelDistance * 2; qreal turnRateRads = wheelsAngleRads / turnDistance; // rough estimate qreal turnRate = (turnRateRads * 180) / Pi; qreal rotation = speed * turnRate; setTransform(QTransform().rotate(rotation), true); setTransform(QTransform::fromTranslate(0, -speed), true); update(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/car.h000066400000000000000000000035101347155106100247710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CAR_H #define CAR_H #include #include class Car : public QGraphicsObject { Q_OBJECT public: Car(); QRectF boundingRect() const; public Q_SLOTS: void accelerate(); void decelerate(); void turnLeft(); void turnRight(); Q_SIGNALS: void crashed(); protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); void timerEvent(QTimerEvent *event); private: QBrush color; qreal wheelsAngle; // used when applying rotation qreal speed; // delta movement along the body axis }; #endif // CAR_H qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/car.qbs000066400000000000000000000006211347155106100253270ustar00rootroot00000000000000CppApplication { name: "car" condition: Qt.dbus.present cpp.cxxLanguageVersion: "c++11" Depends { name: "Qt.dbus"; required: false } Depends { name: "Qt.widgets" } files: [ "car.cpp", "car.h", "main.cpp", ] Group { name: "DBUS Adaptor" files: ["THIS.IS.A.STRANGE.FILENAME.CAR.XML"] fileTags: ["qt.dbus.adaptor"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-adaptors/main.cpp000066400000000000000000000064221347155106100255100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "car.h" #include "car_adaptor.h" #include #include #include #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QGraphicsScene scene; scene.setSceneRect(-500, -500, 1000, 1000); scene.setItemIndexMethod(QGraphicsScene::NoIndex); const auto car = new Car(); scene.addItem(car); QGraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); view.setBackgroundBrush(Qt::darkGray); view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Qt DBus Controlled Car")); view.resize(400, 300); view.show(); new CarInterfaceAdaptor(car); QDBusConnection connection = QDBusConnection::sessionBus(); connection.registerObject("/Car", car); connection.registerService("org.example.CarExample"); return app.exec(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/000077500000000000000000000000001347155106100243625ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/car.xml000066400000000000000000000006241347155106100256530ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.cpp000066400000000000000000000062161347155106100272560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "controller.h" #include "car_interface.h" Controller::Controller(QWidget *parent) : QWidget(parent) { ui.setupUi(this); car = new org::example::Examples::CarInterface("org.example.CarExample", "/Car", QDBusConnection::sessionBus(), this); startTimer(1000); } void Controller::timerEvent(QTimerEvent *event) { Q_UNUSED(event); if (car->isValid()) ui.label->setText("connected"); else ui.label->setText("disconnected"); } void Controller::on_accelerate_clicked() { car->accelerate(); } void Controller::on_decelerate_clicked() { car->decelerate(); } void Controller::on_left_clicked() { car->turnLeft(); } void Controller::on_right_clicked() { car->turnRight(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.h000066400000000000000000000033001347155106100267120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CONTROLLER_H #define CONTROLLER_H #include "ui_controller.h" #include "car_interface.h" class Controller : public QWidget { Q_OBJECT public: Controller(QWidget *parent = nullptr); protected: void timerEvent(QTimerEvent *event); private slots: void on_accelerate_clicked(); void on_decelerate_clicked(); void on_left_clicked(); void on_right_clicked(); private: Ui::Controller ui; org::example::Examples::CarInterface *car; }; #endif qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.qbs000066400000000000000000000006501347155106100272550ustar00rootroot00000000000000CppApplication { name: "controller" condition: Qt.dbus.present Depends { name: "Qt.dbus"; required: false } Depends { name: "Qt.widgets" } cpp.cxxLanguageVersion: "c++11" files: [ "controller.cpp", "controller.h", "controller.ui", "main.cpp", ] Group { name: "DBUS Interface" files: ["car.xml"] fileTags: ["qt.dbus.interface"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/controller.ui000066400000000000000000000027621347155106100271130ustar00rootroot00000000000000 Controller 0 0 255 111 Controller 9 6 Controller Qt::AlignCenter Decelerate Accelerate Right Left qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/dbus-interfaces/main.cpp000066400000000000000000000051151347155106100260140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include "controller.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Controller controller; controller.show(); return app.exec(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/forced-moc/000077500000000000000000000000001347155106100233225ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/forced-moc/createqtclass.h000066400000000000000000000003241347155106100263300ustar00rootroot00000000000000#ifndef CREATEQTCLASS_H #define CREATEQTCLASS_H #include #define CREATE_QT_CLASS(className) \ class className : public QObject \ { \ Q_OBJECT \ public: \ Q_SIGNAL void mySignal(); \ } #endif qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/forced-moc/forced-moc.qbs000066400000000000000000000004441347155106100260510ustar00rootroot00000000000000QtApplication { files: "main.cpp" Group { name: "QObject service provider" files: "createqtclass.h" fileTags: ["hpp", "unmocable"] } Group { name: "QObject service user" files: "myqtclass.h" fileTags: ["hpp", "mocable"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/forced-moc/main.cpp000066400000000000000000000005461347155106100247570ustar00rootroot00000000000000#include "myqtclass.h" #include #include #include int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); MyQtClass c; QObject::connect(&c, &MyQtClass::mySignal, [] { qDebug() << "Hello from slot"; qApp->quit(); }); QTimer::singleShot(0, &c, &MyQtClass::mySignal); return app.exec(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/forced-moc/myqtclass.h000066400000000000000000000001511347155106100255100ustar00rootroot00000000000000#ifndef MYQTCLASS_H #define MYQTCLASS_H #include "createqtclass.h" CREATE_QT_CLASS(MyQtClass); #endif qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/included-moc-cpp/000077500000000000000000000000001347155106100244275ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/included-moc-cpp/included-moc-cpp.qbs000066400000000000000000000001631347155106100302610ustar00rootroot00000000000000import qbs QtApplication { files: [ "main.cpp", "myobject.cpp", "myobject.h", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/included-moc-cpp/main.cpp000066400000000000000000000001551347155106100260600ustar00rootroot00000000000000#include "myobject.h" int main() { MyObject o; QObject::connect(&o, &QObject::destroyed, [] { }); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/included-moc-cpp/myobject.cpp000066400000000000000000000000631347155106100267460ustar00rootroot00000000000000#include "myobject.h" #include qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/included-moc-cpp/myobject.h000066400000000000000000000001651347155106100264160ustar00rootroot00000000000000#ifndef MYOBJECT_H #define MYOBJECT_H #include class MyObject : public QObject { Q_OBJECT }; #endif qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/linker-variant/000077500000000000000000000000001347155106100242325ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/linker-variant/main.cpp000066400000000000000000000000741347155106100256630ustar00rootroot00000000000000#include int main() { qDebug() << "Tach."; } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/linker-variant/qt-linker-variant.qbs000066400000000000000000000004151347155106100303110ustar00rootroot00000000000000QtApplication { Probe { id: qtConfigProbe property stringList moduleConfig: Qt.core.moduleConfig configure: { console.info("Qt requires gold: " + moduleConfig.contains("use_gold_linker")); } } files: "main.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/lrelease/000077500000000000000000000000001347155106100231005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/lrelease/de.ts000066400000000000000000000012441347155106100240410ustar00rootroot00000000000000 Application I am hunry Ich bin Ungar I am thirsty Ich bin Donnerstag Please press Control Bitte drücken Sie den Kontrolleur No keyboard detected. Please press F1 to continue Sehr witzig qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/lrelease/hu.ts000066400000000000000000000007411347155106100240660ustar00rootroot00000000000000 Application My hovercraft is full of eels A légpárnásom tele van angolnákkal I will not buy this record; it is scratched Nem fogok vásárolni ezt a rekordot; ez karcos qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/lrelease/lrelease.qbs000066400000000000000000000001651347155106100254050ustar00rootroot00000000000000Product { name: "lrelease-test" type: ["ts"] Depends { name: "Qt.core" } files: ["de.ts", "hu.ts"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/mixed-build-variants/000077500000000000000000000000001347155106100253345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/mixed-build-variants/main.cpp000066400000000000000000000024231347155106100267650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { qDebug("Tach."); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/mixed-build-variants/mixed-build-variants.qbs000066400000000000000000000003021347155106100320660ustar00rootroot00000000000000QtApplication { Properties { condition: qbs.toolchain.contains("msvc") Qt.core.qtBuildVariant: "release" } Qt.core.qtBuildVariant: "dummy" files: ["main.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-and-cxx-combining/000077500000000000000000000000001347155106100253655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-and-cxx-combining/main.cpp000066400000000000000000000000711347155106100270130ustar00rootroot00000000000000#include "myobject.h" int main() { useMyObject(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-and-cxx-combining/moc-and-cxx-combining.qbs000066400000000000000000000001501347155106100321510ustar00rootroot00000000000000QtApplication { cpp.combineCxxSources: true files: ["main.cpp", "myobject.h", "myobject.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-and-cxx-combining/myobject.cpp000066400000000000000000000002721347155106100277060ustar00rootroot00000000000000#include "myobject.h" #include class MyObject : public QObject { Q_OBJECT public: void use() {} }; void useMyObject() { MyObject().use(); } #include qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-and-cxx-combining/myobject.h000066400000000000000000000001031347155106100273440ustar00rootroot00000000000000#ifndef MYOBJECT_H #define MYOBJECT_H void useMyObject(); #endif qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-flags/000077500000000000000000000000001347155106100231545ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-flags/blubb.h000066400000000000000000000025171347155106100244200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class Blubb : public QObject { Q_OBJECT public: Blubb() { } void makeBlubb() { } }; qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-flags/main.cpp000066400000000000000000000024271347155106100246110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "blubb.h" int main() { Blubb().makeBlubb(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-flags/moc-flags.qbs000066400000000000000000000000651347155106100255340ustar00rootroot00000000000000QtApplication { files: ["main.cpp", "blubb.h"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/000077500000000000000000000000001347155106100246405ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/main.cpp000066400000000000000000000001721347155106100262700ustar00rootroot00000000000000#include "src1/someclass.h" #include "src2/someclass.h" int main() { Src1::SomeClass sc1; Src2::SomeClass sc2; } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/moc-same-file-name.qbs000066400000000000000000000011401347155106100306770ustar00rootroot00000000000000QtApplication { name: "app" cpp.cxxLanguageVersion: "c++11" files: "main.cpp" Group { name: "src1" Qt.core.generatedHeadersDir: product.buildDirectory + "/qt.headers_src1" prefix: name + '/' files: [ "someclass.cpp", "someclass.h", "somefile.cpp", ] } Group { name: "src2" prefix: name + '/' Qt.core.generatedHeadersDir: product.buildDirectory + "/qt.headers_src2" files: [ "someclass.cpp", "someclass.h", "somefile.cpp", ] } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src1/000077500000000000000000000000001347155106100255105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src1/someclass.cpp000066400000000000000000000001511347155106100302020ustar00rootroot00000000000000#include "someclass.h" namespace Src1 { SomeClass::SomeClass(QObject *parent) : QObject(parent) { } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src1/someclass.h000066400000000000000000000003011347155106100276440ustar00rootroot00000000000000#ifndef SOMECLASS1_H #define SOMECLASS1_H #include namespace Src1 { class SomeClass : public QObject { Q_OBJECT public: SomeClass(QObject *parent = nullptr); }; } #endif qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src1/somefile.cpp000066400000000000000000000002041347155106100300130ustar00rootroot00000000000000#include class MyClass1 : public QObject { Q_OBJECT }; static void f() { MyClass1 m; } #include qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src2/000077500000000000000000000000001347155106100255115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src2/someclass.cpp000066400000000000000000000001511347155106100302030ustar00rootroot00000000000000#include "someclass.h" namespace Src2 { SomeClass::SomeClass(QObject *parent) : QObject(parent) { } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src2/someclass.h000066400000000000000000000003011347155106100276450ustar00rootroot00000000000000#ifndef SOMECLASS2_H #define SOMECLASS2_H #include namespace Src2 { class SomeClass : public QObject { Q_OBJECT public: SomeClass(QObject *parent = nullptr); }; } #endif qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/moc-same-file-name/src2/somefile.cpp000066400000000000000000000002041347155106100300140ustar00rootroot00000000000000#include class MyClass2 : public QObject { Q_OBJECT }; static void f() { MyClass2 m; } #include qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/pkgconfig/000077500000000000000000000000001347155106100232535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/pkgconfig/main.cpp000066400000000000000000000030301347155106100246770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef QT_CORE_LIB #include #include #else #include #endif int main(int argc, char **argv) { #ifdef QT_CORE_LIB QCoreApplication app(argc, argv); qDebug() << "Hello world!"; #else (void)argc; (void)argv; std::cout << "Skip this test" << std::endl; #endif } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/pkgconfig/pkgconfig.qbs000066400000000000000000000006051347155106100257320ustar00rootroot00000000000000import qbs.Probes Project { property string name: 'pkgconfig' CppApplication { name: project.name Probes.PkgConfigProbe { id: pkgConfig name: "QtCore" minVersion: '4.0.0' maxVersion: '5.99.99' } files: 'main.cpp' cpp.cxxFlags: pkgConfig.cflags cpp.linkerFlags: pkgConfig.libs } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-meta-data/000077500000000000000000000000001347155106100244355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-meta-data/app.cpp000066400000000000000000000052311347155106100257220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #ifdef QT_STATIC Q_IMPORT_PLUGIN(ThePlugin) #endif int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QJsonObject metaData; for (const QStaticPlugin &p : QPluginLoader::staticPlugins()) { const QJsonObject &md = p.metaData(); if (md.value("className") == "ThePlugin") { metaData = md; break; } } #ifdef QT_STATIC if (metaData.isEmpty()) { qDebug() << "no static metadata"; return 1; } #else if (!metaData.isEmpty()) { qDebug() << "static metadata"; return 1; } #endif if (metaData.isEmpty()) metaData = QPluginLoader("thePlugin").metaData(); const QJsonValue v = metaData.value(QStringLiteral("theKey")); if (!v.isArray()) { qDebug() << "value is" << v; return 1; } const QJsonArray a = v.toArray(); if (a.size() != 1 || a.first() != QLatin1String("theValue")) { qDebug() << "value is" << v; return 1; } const QJsonValue v2 = metaData.value(QStringLiteral("MetaData")).toObject() .value(QStringLiteral("theOtherKey")); if (v2.toString() != QLatin1String("theOtherValue")) { qDebug() << "metadata:" << metaData; return 1; } qDebug() << "all ok!"; return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-meta-data/metadata.json000066400000000000000000000000501347155106100271030ustar00rootroot00000000000000{ "theOtherKey" : "theOtherValue" } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-meta-data/plugin-meta-data.qbs000066400000000000000000000023501347155106100302750ustar00rootroot00000000000000Project { QtApplication { name: "app" consoleApplication: true Depends { name: "thePlugin" } cpp.cxxLanguageVersion: "c++11" Properties { condition: qbs.targetOS.contains("unix") cpp.rpaths: [cpp.rpathOrigin] } Group { fileTagsFilter: product.type qbs.install: true } files: ["app.cpp"] } Library { type: Qt.core.staticBuild ? "staticlibrary" : "dynamiclibrary" name: "thePlugin" Depends { name: "cpp" } Depends { name: "Qt.core" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } cpp.defines: [Qt.core.staticBuild ? "QT_STATICPLUGIN" : "QT_PLUGIN"] cpp.cxxLanguageVersion: "c++11" cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined cpp.includePaths: ["."] Qt.core.pluginMetaData: ["theKey=theValue"] Group { fileTagsFilter: product.type qbs.install: true } files: ["theplugin.cpp"] Group { files: ["metadata.json"] fileTags: ["qt_plugin_metadata"] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-meta-data/theplugin.cpp000066400000000000000000000026371347155106100271500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include class ThePlugin : public QObject { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.qbs.ThePlugin" FILE "metadata.json") }; #include qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-support/000077500000000000000000000000001347155106100243145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-support/modules/000077500000000000000000000000001347155106100257645ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-support/modules/m1/000077500000000000000000000000001347155106100263015ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-support/modules/m1/m1.qbs000066400000000000000000000006641347155106100273330ustar00rootroot00000000000000Module { property bool useDummy Depends { name: "Qt.plugin_support" } Properties { condition: useDummy Qt.plugin_support.pluginsByType: ({imageformats: "dummy"}) } Properties { condition: Qt.plugin_support.allPluginsByType && Qt.plugin_support.allPluginsByType.imageformats Qt.plugin_support.pluginsByType: ({imageformats: Qt.plugin_support.allPluginsByType.imageformats[0]}) } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-support/modules/m2/000077500000000000000000000000001347155106100263025ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-support/modules/m2/m2.qbs000066400000000000000000000004431347155106100273300ustar00rootroot00000000000000Module { Depends { name: "Qt.plugin_support" } Properties { condition: Qt.plugin_support.allPluginsByType && Qt.plugin_support.allPluginsByType.imageformats Qt.plugin_support.pluginsByType: ({imageformats: Qt.plugin_support.allPluginsByType.imageformats[1]}) } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-support/plugin-support-main.cpp000066400000000000000000000000161347155106100307470ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/plugin-support/plugin-support.qbs000066400000000000000000000012631347155106100300350ustar00rootroot00000000000000QtGuiApplication { Probe { id: staticProbe property bool isStaticQt: Qt.gui.isStaticLibrary property var plugins: Qt.plugin_support.effectivePluginsByType property var allPlugins: Qt.plugin_support.allPluginsByType configure: { console.info("static Qt: " + isStaticQt); console.info("requested image plugins: %" + plugins.imageformats + "%"); console.info("all image plugins: #" + allPlugins.imageformats + "#"); console.info("platform plugin count: " + (plugins.platforms || []).length); } } Depends { name: "m1" } Depends { name: "m2" } files: "plugin-support-main.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qml-debugging/000077500000000000000000000000001347155106100240265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qml-debugging/main.cpp000066400000000000000000000034561347155106100254660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) #include #include using Application = QGuiApplication; #define AH_SO_THIS_IS_QT5 #else #include #include #define AH_SO_THIS_IS_QT4 using Application = QApplication; #endif int main(int argc, char *argv[]) { Application app(argc, argv); #ifdef AH_SO_THIS_IS_QT5 QQmlApplicationEngine engine; engine.load(QUrl("blubb")); #else QDeclarativeView view; view.setSource(QUrl("blubb")); #endif return app.exec(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qml-debugging/qml-debugging.qbs000066400000000000000000000002411347155106100272540ustar00rootroot00000000000000QtApplication { name: "debuggable-app" consoleApplication: true Depends { name: "Qt.quick" } Qt.quick.qmlDebugging: true files: "main.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qobject-in-mm/000077500000000000000000000000001347155106100237465ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qobject-in-mm/main.mm000066400000000000000000000001741347155106100252270ustar00rootroot00000000000000#include class Foo : public QObject { Q_OBJECT }; int main() { Foo foo; return 0; } #include "main.moc" qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qobject-in-mm/qobject-in-mm.qbs000066400000000000000000000001121347155106100271110ustar00rootroot00000000000000CppApplication { Depends { name: "Qt.core" } files: ["main.mm"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qrc/000077500000000000000000000000001347155106100220715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qrc/bla.cpp000066400000000000000000000027311347155106100233360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { QFileInfo f(":/stuff.txt"); if (!f.exists()) return 1; if (!f.isFile()) return 2; QFileInfo d(":/subdir"); if (!d.exists()) return 3; if (!d.isDir()) return 4; } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qrc/bla.qrc000066400000000000000000000001651347155106100233400ustar00rootroot00000000000000 stuff.txt subdir/ qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qrc/i.qbs000066400000000000000000000004151347155106100230300ustar00rootroot00000000000000Project { Product { consoleApplication: true type: "application" name: "i" Depends { name: "Qt.core" } files: [ "bla.cpp", "bla.qrc", //"test.cpp", ] } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qrc/stuff.txt000066400000000000000000000000201347155106100237510ustar00rootroot00000000000000a resource file qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qrc/subdir/000077500000000000000000000000001347155106100233615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qrc/subdir/dummy.txt000066400000000000000000000000001347155106100252430ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qrc/test.cpp000066400000000000000000000000171347155106100235520ustar00rootroot00000000000000void test() {} qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qt-keywords/000077500000000000000000000000001347155106100235755ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qt-keywords/main.cpp000066400000000000000000000002131347155106100252210ustar00rootroot00000000000000#include class AnObject : public QObject { Q_OBJECT signals: void someSignal(); }; int main() { } #include qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qt-keywords/qt-keywords.qbs000066400000000000000000000000521347155106100265720ustar00rootroot00000000000000QtApplication { files: ["main.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qtscxml/000077500000000000000000000000001347155106100227775ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qtscxml/dummystatemachine.scxml000066400000000000000000000001661347155106100275730ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qtscxml/main.cpp000066400000000000000000000004551347155106100244330ustar00rootroot00000000000000#ifdef HAS_QTSCXML #include #endif #include int main() { #ifdef HAS_QTSCXML QbsTest::QbsStateMachine machine; std::cout << "state machine name: " << qPrintable(machine.name()) << std::endl; #else std::cout << "QtScxml not present" << std::endl; #endif } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs000066400000000000000000000030271347155106100252030ustar00rootroot00000000000000import qbs.Environment import qbs.FileInfo Project { QtApplication { name: "app" Depends { name: "Qt.scxml"; required: false } Properties { condition: Qt.scxml.present cpp.defines: ["HAS_QTSCXML"] } Qt.scxml.className: "QbsStateMachine" Qt.scxml.namespace: "QbsTest" Qt.scxml.generateStateMethods: true files: ["main.cpp"] Group { files: ["dummystatemachine.scxml"] fileTags: ["qt.scxml.compilable"] } } Product { name: "runner" type: ["runner"] Depends { name: "app" } Rule { inputsFromDependencies: ["application"] outputFileTags: ["runner"] prepare: { var cmd = new Command(input.filePath); cmd.description = "running " + input.filePath; var pathVar; var pathValue; if (product.qbs.hostOS.contains("windows")) { pathVar = "PATH"; pathValue = FileInfo.toWindowsSeparators(input["Qt.core"].binPath); } else { pathVar = "LD_LIBRARY_PATH"; pathValue = input["Qt.core"].libPath; } var oldValue = Environment.getEnv(pathVar) || ""; var newValue = pathValue + product.qbs.pathListSeparator + oldValue; cmd.environment = [pathVar + '=' + newValue]; return [cmd]; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/quick-compiler/000077500000000000000000000000001347155106100242305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/quick-compiler/main.cpp000066400000000000000000000006371347155106100256660ustar00rootroot00000000000000#include #include int main(int argc, char *argv[]) { #if defined(Q_OS_WIN) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/qml/subdir/test.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/quick-compiler/qml.qrc000066400000000000000000000001421347155106100255250ustar00rootroot00000000000000 qml/subdir/test.qml qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/quick-compiler/qml/000077500000000000000000000000001347155106100250215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/quick-compiler/qml/subdir/000077500000000000000000000000001347155106100263115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/quick-compiler/qml/subdir/test.qml000066400000000000000000000000361347155106100300020ustar00rootroot00000000000000import QtQuick 2.0 Item { } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/quick-compiler/quick-compiler.qbs000066400000000000000000000007641347155106100276720ustar00rootroot00000000000000CppApplication { Depends { name: "Qt.quick" } Qt.quick.useCompiler: Qt.quick.compilerAvailable cpp.cxxLanguageVersion: "c++11" Probe { id: qtQuickCompilerProbe property bool hasCompiler: Qt.quick.compilerAvailable configure: { if (hasCompiler) console.info("compiler available"); else console.info("compiler not available"); } } files: [ "main.cpp", "qml.qrc", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/remove-moc-header-from-file-list/000077500000000000000000000000001347155106100274325ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/remove-moc-header-from-file-list/file.cpp000066400000000000000000000001451347155106100310550ustar00rootroot00000000000000#include "file.h" MyObject::MyObject() {} int main() { MyObject o1; } #include qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/remove-moc-header-from-file-list/file.h000066400000000000000000000002211347155106100305150ustar00rootroot00000000000000#pragma once #include class MyObject : public QObject { Q_OBJECT public: MyObject(); signals: void someSignal(); }; remove-moc-header-from-file-list.qbs000066400000000000000000000001301347155106100362020ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/remove-moc-header-from-file-listQtApplication { name: "p" files: [ "file.h", "file.cpp" ] } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/000077500000000000000000000000001347155106100261425ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/main.cpp000066400000000000000000000001771347155106100275770ustar00rootroot00000000000000#include int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); return app.exec(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/static-qt-plugin-linking.qbs000066400000000000000000000007401347155106100335100ustar00rootroot00000000000000Product { name: "p" Probe { id: staticQtChecker property bool staticQt: Qt.core.staticBuild configure: { found = staticQt; if (found) console.info("Qt is static"); } } Group { condition: type.contains("application") files: "main.cpp" } Depends { name: "Qt.core" } Depends { name: "Qt.gui" } Depends { name: "Qt.qminimal"; condition: Qt.core.staticBuild; } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/000077500000000000000000000000001347155106100247645ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/after/000077500000000000000000000000001347155106100260655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/after/main.cpp000066400000000000000000000030411347155106100275130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { Q_OBJECT public: MyObject(QObject *parent = nullptr) : QObject(parent) { } }; int main(int argc, char **argv) { QCoreApplication app(argc, argv); const auto obj = new MyObject(&app); return app.exec(); } #include qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/before/000077500000000000000000000000001347155106100262265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/before/main.cpp000066400000000000000000000030141347155106100276540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { Q_OBJECT public: MyObject(QObject *parent = nullptr) : QObject(parent) { } }; int main(int argc, char **argv) { QCoreApplication app(argc, argv); const auto obj = new MyObject(&app); return app.exec(); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/trackAddMocInclude/before/test.qbs000066400000000000000000000001551347155106100277150ustar00rootroot00000000000000Application { Depends { name: "Qt.core" } cpp.cxxLanguageVersion: "c++11" files: ["main.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/trackQObjChange/000077500000000000000000000000001347155106100242725ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/trackQObjChange/bla.cpp000066400000000000000000000024711347155106100255400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "bla.h" int main() { MyObject obj; obj.setObjectName("I am the object!"); } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/trackQObjChange/bla_noqobject.h000066400000000000000000000024251347155106100272500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { }; qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/trackQObjChange/bla_qobject.h000066400000000000000000000024421347155106100267120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include class MyObject : public QObject { Q_OBJECT }; qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/trackQObjChange/i.qbs000066400000000000000000000003601347155106100252300ustar00rootroot00000000000000Project { Product { type: "application" consoleApplication: true name: "i" Depends { name: "Qt.core" } files: [ "bla.cpp", "bla.h" ] } } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/unmocable/000077500000000000000000000000001347155106100232515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/unmocable/foo.h000066400000000000000000000000731347155106100242050ustar00rootroot00000000000000#define Q_OBJECT 156 int someNumber() { return Q_OBJECT; } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/unmocable/main.cpp000066400000000000000000000001001347155106100246700ustar00rootroot00000000000000#include "foo.h" int main() { return someNumber() - 156; } qbs-src-1.13.1/tests/auto/blackbox/testdata-qt/unmocable/unmocable.qbs000066400000000000000000000002571347155106100257310ustar00rootroot00000000000000Application { Depends { name: "Qt.core" } files: ["main.cpp"] Group { files: ["foo.h"] fileTags: ["unmocable"] overrideTags: false } } qbs-src-1.13.1/tests/auto/blackbox/testdata/000077500000000000000000000000001347155106100206625ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/QTBUG-51237/000077500000000000000000000000001347155106100222235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/QTBUG-51237/modules/000077500000000000000000000000001347155106100236735ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/QTBUG-51237/modules/mymodule/000077500000000000000000000000001347155106100255265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/QTBUG-51237/modules/mymodule/mymodule.qbs000066400000000000000000000001631347155106100300700ustar00rootroot00000000000000Module { property stringList theProperty: [] //property stringList otherProperty: theProperty.concat([]) } qbs-src-1.13.1/tests/auto/blackbox/testdata/QTBUG-51237/qtbug-51237.qbs000066400000000000000000000006771347155106100245450ustar00rootroot00000000000000Product { type: "custom" Depends { name: "mymodule" } Rule { multiplex: true outputFileTags: ["custom"] prepare: { var theProperty = product.mymodule.theProperty; if (!theProperty) throw "Oh no!"; var dummy = new JavaScriptCommand(); dummy.silent = true; dummy.sourceCode = function() {}; return [dummy]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/add-filetag-to-generated-artifact/000077500000000000000000000000001347155106100271725ustar00rootroot00000000000000add-filetag-to-generated-artifact.qbs000066400000000000000000000017571347155106100361440ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/add-filetag-to-generated-artifactimport qbs.File Project { property bool enableTagging CppApplication { name: "my_app" files: "main.cpp" Group { condition: project.enableTagging fileTagsFilter: ["application"] fileTags: ["app-to-compress"] } } Product { name: "my_compressed_app" type: ["compressed_application"] Depends { name: "my_app" } Rule { inputsFromDependencies: ["app-to-compress"] Artifact { filePath: "compressed-" + input.fileName fileTags: ["compressed_application"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "compressing " + input.fileName; cmd.highlight = "linker"; cmd.sourceCode = function () { File.copy(input.filePath, output.filePath); }; return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/add-filetag-to-generated-artifact/main.cpp000066400000000000000000000000161347155106100306170ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/always-run/000077500000000000000000000000001347155106100227645ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/always-run/dummy.txt000066400000000000000000000000001347155106100246460ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/always-run/rule.qbs000066400000000000000000000011611347155106100244410ustar00rootroot00000000000000import qbs.TextFile Product { type: ["blubb"] Group { files: ["dummy.txt"] fileTags: ["dummy"] } Rule { alwaysRun: false inputs: ["dummy"] Artifact { filePath: "blubb.txt" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "yo"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("blubb"); f.close(); } return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/always-run/transformer.qbs000066400000000000000000000010221347155106100260300ustar00rootroot00000000000000import qbs.TextFile Product { type: ["blubb"] Transformer { alwaysRun: false Artifact { filePath: "blubb.txt" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "yo"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("blubb"); f.close(); } return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/archiver/000077500000000000000000000000001347155106100224655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/archiver/archivable.qbs000066400000000000000000000003651347155106100253000ustar00rootroot00000000000000Product { name: "archivable" type: "archiver.archive" Depends { name: "archiver" } archiver.workingDirectory: path Group { files: ["list.txt"] fileTags: ["archiver.input-list"] } files: ["test.txt"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/archiver/list.txt000066400000000000000000000000301347155106100241720ustar00rootroot00000000000000test.txt archivable.qbs qbs-src-1.13.1/tests/auto/blackbox/testdata/archiver/test.txt000066400000000000000000000000001347155106100241730ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/artifact-scanning/000077500000000000000000000000001347155106100242555ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/artifact-scanning/artifact-scanning.qbs000066400000000000000000000010501347155106100303530ustar00rootroot00000000000000Project { CppApplication { name: "p1" consoleApplication: true cpp.includePaths: ["."] files: [ "p1.cpp", "shared.h", ] } CppApplication { name: "p2" consoleApplication: true cpp.includePaths: ["."] files: [ "p2.cpp", "shared.h", ] } CppApplication { name: "p3" consoleApplication: true cpp.includePaths: [".", "subdir"] files: [ "p3.cpp", ] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/artifact-scanning/external-indirect.h000066400000000000000000000000001347155106100300350ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/artifact-scanning/external.h000066400000000000000000000000371347155106100262500ustar00rootroot00000000000000#include qbs-src-1.13.1/tests/auto/blackbox/testdata/artifact-scanning/p1.cpp000066400000000000000000000000701347155106100252760ustar00rootroot00000000000000#include #include int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/artifact-scanning/p2.cpp000066400000000000000000000000441347155106100253000ustar00rootroot00000000000000#include int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/artifact-scanning/p3.cpp000066400000000000000000000000461347155106100253030ustar00rootroot00000000000000#include int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/artifact-scanning/shared.h000066400000000000000000000000261347155106100256720ustar00rootroot00000000000000#include qbs-src-1.13.1/tests/auto/blackbox/testdata/artifact-scanning/subdir/000077500000000000000000000000001347155106100255455ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/artifact-scanning/subdir/external2.h000066400000000000000000000000001347155106100276100ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/000077500000000000000000000000001347155106100264405ustar00rootroot00000000000000artifacts-map-change-tracking.qbs000066400000000000000000000052521347155106100346520ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/artifacts-map-change-trackingimport qbs.File Project { CppApplication { name: "TheApp" targetName: "TheBinary" Rule { inputs: "cpp.in" Artifact { filePath: "test.cpp"; fileTags: 'cpp' } prepare: { console.info("running rule for " + output.fileName); var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } files: ["main.cpp", /* 'test.txt' */] Group { files: "test.cpp.in" fileTags: "cpp.in" } } Product { name: "meta" type: "custom" Depends { name: "TheApp" } Group { files: "dummy.in" fileTags: "dummy.in" } Rule { inputs: ["dummy.in"] Artifact { filePath: "dummy"; fileTags: 'custom' } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "printing artifacts"; cmd.sourceCode = function() { var dep; for (var i = 0; i < product.dependencies.length; ++i) { var d = product.dependencies[i]; if (d.name === "TheApp") { dep = d; break; } } for (var p in dep.artifacts) { var list = dep.artifacts[p]; for (var i = 0; i < list.length; ++i) console.info(list[i].fileName); } File.copy(input.filePath, output.filePath); }; return cmd; } } } Product { name: "p" type: "p_type" Rule { multiplex: true Artifact { filePath: "dummy1"; fileTags: "d_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var blubb = product.artifacts.qbs; }; return cmd; } } Rule { inputs: "d_type" Artifact { filePath: "dummy2"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { }; return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/dummy.in000066400000000000000000000000001347155106100301110ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/main.cpp000066400000000000000000000000371347155106100300700ustar00rootroot00000000000000void f(); int main() { f(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/test.cpp.in000066400000000000000000000000151347155106100305240ustar00rootroot00000000000000void f() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/artifacts-map-change-tracking/test.txt000066400000000000000000000000001347155106100301460ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/artifacts-map-invalidation/000077500000000000000000000000001347155106100260745ustar00rootroot00000000000000artifacts-map-invalidation.qbs000066400000000000000000000042021347155106100337340ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/artifacts-map-invalidationimport qbs.File Project { Product { name: "dep" type: "dep.out" Group { files: "file.in" fileTags: "dep.in" } Rule { inputs: "dep.in" outputFileTags: "dep.out" outputArtifacts: { if (!product.artifacts["dep.in"] || product.artifacts["dep.in"].length !== 1) throw "source file not in artifacts map!" if (product.artifacts["dep.out"] && product.artifacts["dep.out"].length !== 0) throw "generated artifact already in map!"; return [{filePath: "file.out", fileTags: "dep.out"}]; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } Product { name: "p" type: "p.out" Depends { name: "dep" } Rule { inputsFromDependencies: "dep.out" Artifact { filePath: "myfile.out"; fileTags: "p.out" } prepare: { var dep; for (var i = 0; i < product.dependencies.length; ++i) { if (product.dependencies[i].name === "dep") { dep = product.dependencies[i]; break; } } if (!dep) throw "dependency not found"; if (!dep.artifacts["dep.in"] || dep.artifacts["dep.in"].length !== 1) throw "source file not in dependency's artifacts map!" if (!dep.artifacts["dep.out"] || dep.artifacts["dep.out"].length !== 1) throw "generated artifact not in dependency's artifacts map!"; var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/artifacts-map-invalidation/file.in000066400000000000000000000000001347155106100273310ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/artifacts-map-race-condition/000077500000000000000000000000001347155106100263115ustar00rootroot00000000000000artifacts-map-race-condition.qbs000066400000000000000000000043731347155106100343770ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/artifacts-map-race-conditionProduct { name: "p" type: ["custom1", "custom2", "custom3", "custom4", "custom5"] Rule { multiplex: true outputFileTags: "custom1" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "reader1"; cmd.sourceCode = function() { for (var i = 0; i < 1000; ++i) { for (var t in product.artifacts) { var l = product.artifacts[t]; for (var j = 0; j < l.length; ++j) var fileName = l[j].fileName; } } }; return cmd; } } Rule { multiplex: true outputFileTags: "helper" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "helper"; cmd.sourceCode = function() { }; return cmd; } } Rule { inputs: ["helper"] outputFileTags: ["custom2", "custom3", "custom4"] outputArtifacts: { console.info("writer"); var artifacts = []; for (var i = 0; i < 1000; ++i) { artifacts.push({ filePath: "dummyt1" + i, fileTags: ["custom2"] }); artifacts.push({ filePath: "dummyt2" + i, fileTags: ["custom3"] }); artifacts.push({ filePath: "dummyt3" + i, fileTags: ["custom4"] }); } return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "writer dummy command"; cmd.sourceCode = function() { }; return cmd; } } Rule { multiplex: true outputFileTags: "custom5" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "reader2"; cmd.sourceCode = function() { for (var i = 0; i < 1000; ++i) { for (var t in product.artifacts) { var l = product.artifacts[t]; for (var j = 0; j < l.length; ++j) var fileName = l[j].fileName; } } }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/assembly/000077500000000000000000000000001347155106100225015ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/assembly/assembly.qbs000066400000000000000000000042071347155106100250320ustar00rootroot00000000000000import qbs.TextFile Project { Product { type: ["properties"] Depends { name: "cpp" } Rule { multiplex: true Artifact { filePath: "properties.json" fileTags: ["properties"] } prepare: { var cmd = new JavaScriptCommand(); cmd.outputFilePath = outputs.properties[0].filePath; cmd.tc = product.qbs.toolchain; cmd.sourceCode = function () { var tf = new TextFile(outputFilePath, TextFile.WriteOnly); try { tf.writeLine(JSON.stringify({ "qbs.toolchain": tc }, undefined, 4)); } finally { tf.close(); } }; return [cmd]; } } } StaticLibrary { name : "testa" files : [ "testa.s" ] Depends { name: "cpp" } condition: qbs.toolchain.contains("gcc") Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } StaticLibrary { name : "testb" files : [ "testb.S" ] Depends { name: "cpp" } condition: qbs.toolchain.contains("gcc") Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } StaticLibrary { name : "testc" files : [ "testc.sx" ] Depends { name: "cpp" } condition: qbs.toolchain.contains("gcc") Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } StaticLibrary { name: "testd" Group { condition: product.condition files: ["testd_" + qbs.architecture + ".asm"] } Depends { name: "cpp" } condition: qbs.toolchain.contains("msvc") && (qbs.architecture === "x86" || qbs.architecture === "x86_64") Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/assembly/testa.s000066400000000000000000000000401347155106100237770ustar00rootroot00000000000000.globl symbola symbola: nop qbs-src-1.13.1/tests/auto/blackbox/testdata/assembly/testb.S000066400000000000000000000000411347155106100237410ustar00rootroot00000000000000#define bla nop symbolb: bla qbs-src-1.13.1/tests/auto/blackbox/testdata/assembly/testc.sx000066400000000000000000000000411347155106100241720ustar00rootroot00000000000000#define bla nop symbolb: bla qbs-src-1.13.1/tests/auto/blackbox/testdata/assembly/testd_x86.asm000066400000000000000000000001111347155106100250240ustar00rootroot00000000000000.386 .model flat, stdcall .code foo PROC nop RET foo ENDP END qbs-src-1.13.1/tests/auto/blackbox/testdata/assembly/testd_x86_64.asm000066400000000000000000000000561347155106100253450ustar00rootroot00000000000000.code foo PROC nop RET foo ENDP END qbs-src-1.13.1/tests/auto/blackbox/testdata/autotest-with-dependencies/000077500000000000000000000000001347155106100261275ustar00rootroot00000000000000autotest-with-dependencies.qbs000066400000000000000000000012371347155106100340270ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/autotest-with-dependenciesimport qbs.FileInfo Project { CppApplication { name: "helper-app" type: ["application", "test-helper"] consoleApplication: true install: true files: "helper-main.cpp" cpp.executableSuffix: ".exe" Group { fileTagsFilter: "application" fileTags: "test-helper" } } CppApplication { name: "test-app" type: ["application", "autotest"] Depends { name: "autotest" } files: "test-main.cpp" } AutotestRunner { arguments: FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix, "bin") auxiliaryInputs: "test-helper" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/autotest-with-dependencies/helper-main.cpp000066400000000000000000000001431347155106100310320ustar00rootroot00000000000000#include int main() { std::cout << "i am the helper" << std::endl; return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/autotest-with-dependencies/test-main.cpp000066400000000000000000000004641347155106100305400ustar00rootroot00000000000000#include #include #include int main(int argc, char *argv[]) { std::cout << "i am the test app" << std::endl; const std::string fullHelperExe = std::string(argv[1]) + "/helper-app.exe"; return std::system(fullHelperExe.c_str()) == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/000077500000000000000000000000001347155106100227155ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/autotests.qbs000066400000000000000000000001161347155106100254550ustar00rootroot00000000000000Project { references: ["test1", "test2", "test3"] AutotestRunner {} } qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/test1/000077500000000000000000000000001347155106100237555ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/test1/test1.cpp000066400000000000000000000004331347155106100255210ustar00rootroot00000000000000#include #include int main(int argc, char *[]) { if (argc != 2) { std::cerr << "This test needs exactly one argument" << std::endl; std::cerr << "FAIL" << std::endl; return EXIT_FAILURE; } std::cout << "PASS" << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/test1/test1.qbs000066400000000000000000000002431347155106100255230ustar00rootroot00000000000000CppApplication { name: "test1" type: base.concat("autotest") Depends { name: "autotest" } autotest.arguments: "--dummy" files: "test1.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/test2/000077500000000000000000000000001347155106100237565ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/test2/test2-resource.txt000066400000000000000000000000001347155106100273730ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/test2/test2.cpp000066400000000000000000000004161347155106100255240ustar00rootroot00000000000000#include #include #include int main() { std::ifstream input("test2-resource.txt"); if (!input.is_open()) { std::cerr << "Test resource not found"; return EXIT_FAILURE; } std::cout << "PASS" << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/test2/test2.qbs000066400000000000000000000002521347155106100255250ustar00rootroot00000000000000CppApplication { name: "test2" type: base.concat("autotest") Depends { name: "autotest" } autotest.workingDir: sourceDirectory files: "test2.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/test3/000077500000000000000000000000001347155106100237575ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/test3/test3.cpp000066400000000000000000000002351347155106100255250ustar00rootroot00000000000000#include #include int main() { std::cerr << "I am an awful test"; std::cerr << "FAIL" << std::endl; return EXIT_FAILURE; } qbs-src-1.13.1/tests/auto/blackbox/testdata/autotests/test3/test3.qbs000066400000000000000000000002411347155106100255250ustar00rootroot00000000000000CppApplication { name: "test3" type: base.concat("autotest") Depends { name: "autotest" } autotest.allowFailure: true files: "test3.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata/aux-inputs-from-deps/000077500000000000000000000000001347155106100246715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/aux-inputs-from-deps/aux-inputs-from-deps.qbs000066400000000000000000000042461347155106100314150ustar00rootroot00000000000000import qbs.File import qbs.TextFile import "util.js" as Utils Project { CppApplication { name: "app" files: ["main.cpp"] Depends { name: "dep" } } Product { name: "p" type: ["p.out"] Depends { name: "dep" } Rule { multiplex: true explicitlyDependsOnFromDependencies: ["hpp"] Artifact { filePath: "dummy.out" fileTags: ["p.out"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating dummy.out"; cmd.sourceCode = function() { File.copy(project.buildDirectory + "/dummy.h", output.filePath); }; return [cmd]; } } } Product { name: "dep" type: ["hpp"] property bool sleep: true Rule { inputs: ["blubb.in"] Artifact { filePath: project.buildDirectory + "/dummy.h" fileTags: ["hpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating header"; cmd.sourceCode = function() { if (product.sleep) Utils.sleep(1000); File.copy(input.filePath, output.filePath); } return [cmd]; } } Rule { multiplex: true Artifact { filePath: "dummy.blubb" fileTags: ["blubb.in"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating blubb.in"; cmd.sourceCode = function() { if (product.sleep) Utils.sleep(1000); var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return [cmd]; } } Export { Depends { name: "cpp" } cpp.includePaths: [project.buildDirectory] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/aux-inputs-from-deps/main.cpp000066400000000000000000000000431347155106100263160ustar00rootroot00000000000000#include int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/aux-inputs-from-deps/util.js000066400000000000000000000002511347155106100262020ustar00rootroot00000000000000function sleep(timeInMs) { var referenceTime = new Date(); var time = null; do { time = new Date(); } while (time - referenceTime < timeInMs); } qbs-src-1.13.1/tests/auto/blackbox/testdata/badInterpreter/000077500000000000000000000000001347155106100236345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/badInterpreter/badInterpreter.qbs000066400000000000000000000016341347155106100273210ustar00rootroot00000000000000Project { qbsSearchPaths: base.concat(["qbs"]) Product { Depends { name: "script-test" } name: "script-ok" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } Product { Depends { name: "script-test" } name: "script-noexec" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } Product { Depends { name: "script-test" } name: "script-interp-missing" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } Product { Depends { name: "script-test" } name: "script-interp-noexec" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/badInterpreter/qbs/000077500000000000000000000000001347155106100244215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/badInterpreter/qbs/modules/000077500000000000000000000000001347155106100260715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/badInterpreter/qbs/modules/script-test/000077500000000000000000000000001347155106100303525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/badInterpreter/qbs/modules/script-test/script-test.qbs000066400000000000000000000020611347155106100333410ustar00rootroot00000000000000import qbs.FileInfo import qbs.TextFile Module { name: "script-test" Rule { inputs: ["script"] Artifact { filePath: FileInfo.joinPaths(project.buildDirectory, input.fileName) fileTags: ["application"] } prepare: { var cmds = []; var cmd = new JavaScriptCommand(); cmd.description = "copying " + input.fileName; cmd.sourceCode = function() { var tf = new TextFile(input.filePath, TextFile.ReadOnly); var s = tf.readAll().replace("$PWD", project.buildDirectory); tf.close(); var tf2 = new TextFile(output.filePath, TextFile.ReadWrite); tf2.write(s); tf2.close(); }; cmds.push(cmd); if (output.fileName !== "script-noexec") { var cmd2 = new Command("chmod", ["+x", output.filePath]); cmd2.silent = true; cmds.push(cmd2); } return cmds; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/badInterpreter/script-interp-missing000077500000000000000000000000221347155106100300260ustar00rootroot00000000000000#!/does/not/exist qbs-src-1.13.1/tests/auto/blackbox/testdata/badInterpreter/script-interp-noexec000077500000000000000000000000251347155106100276410ustar00rootroot00000000000000#!$PWD/script-noexec qbs-src-1.13.1/tests/auto/blackbox/testdata/badInterpreter/script-noexec000066400000000000000000000000001347155106100263300ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/badInterpreter/script-ok000077500000000000000000000000121347155106100254660ustar00rootroot00000000000000#!/bin/sh qbs-src-1.13.1/tests/auto/blackbox/testdata/bom-sources/000077500000000000000000000000001347155106100231205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/bom-sources/bom-sources.qbs000066400000000000000000000001121347155106100260570ustar00rootroot00000000000000CppApplication { name: "app" files: ["main.cpp", "theheader.h"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/bom-sources/main.cpp000066400000000000000000000000511347155106100245440ustar00rootroot00000000000000#include "theheader.h" int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/bom-sources/theheader.h000066400000000000000000000000001347155106100252100ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/build-data-of-disabled-product/000077500000000000000000000000001347155106100265155ustar00rootroot00000000000000build-data-of-disabled-product.qbs000066400000000000000000000001071347155106100347760ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/build-data-of-disabled-productCppApplication { name: "app" files: ["main.cpp", "test.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/build-data-of-disabled-product/main.cpp000066400000000000000000000000431347155106100301420ustar00rootroot00000000000000void f(); int main() { f(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/build-data-of-disabled-product/test.cpp000066400000000000000000000000141347155106100301730ustar00rootroot00000000000000void f() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/build-directories/000077500000000000000000000000001347155106100242735ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/build-directories/build-directories.qbs000066400000000000000000000020031347155106100304060ustar00rootroot00000000000000Project { Product { name: "p1" type: "blubb1" Rule { multiplex: true outputFileTags: "blubb1" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info(product.buildDirectory); } return cmd; } } } Product { name: "p2" type: "blubb2" Depends { name: "p1" } Rule { inputsFromDependencies: "blubb1" outputFileTags: "blubb2" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info(product.buildDirectory); console.info(project.buildDirectory); console.info(project.sourceDirectory); } return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/build-graph-versions/000077500000000000000000000000001347155106100247265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/build-graph-versions/build-graph-versions.qbs000066400000000000000000000000531347155106100314770ustar00rootroot00000000000000CppApplication { files: ["main.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/build-graph-versions/main.cpp000066400000000000000000000000171347155106100263540ustar00rootroot00000000000000int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/buildenv-change/000077500000000000000000000000001347155106100237155ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/buildenv-change/buildenv-change.qbs000066400000000000000000000005231347155106100274570ustar00rootroot00000000000000CppApplication { Probe { id: dummy property stringList toolchain: qbs.toolchain configure: { if (toolchain.contains("msvc")) console.info("msvc"); } } files: [ "file.c", "main.cpp", "subdir/theheader.h", "subdir2/theheader.h", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/buildenv-change/file.c000066400000000000000000000000241347155106100247740ustar00rootroot00000000000000void func(void) { } qbs-src-1.13.1/tests/auto/blackbox/testdata/buildenv-change/main.cpp000066400000000000000000000000461347155106100253450ustar00rootroot00000000000000#include int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/buildenv-change/subdir/000077500000000000000000000000001347155106100252055ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/buildenv-change/subdir/theheader.h000066400000000000000000000000001347155106100272750ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/buildenv-change/subdir2/000077500000000000000000000000001347155106100252675ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/buildenv-change/subdir2/theheader.h000066400000000000000000000000001347155106100273570ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/change-in-disabled-product/000077500000000000000000000000001347155106100257365ustar00rootroot00000000000000change-in-disabled-product.qbs000066400000000000000000000001401347155106100334350ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/change-in-disabled-productProduct { condition: false files: [ 'test1.txt', // 'test2.txt' ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/change-in-disabled-product/test1.txt000066400000000000000000000000001347155106100275250ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/change-in-disabled-product/test2.txt000066400000000000000000000000001347155106100275260ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/change-in-imported-file/000077500000000000000000000000001347155106100252515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/change-in-imported-file/change-in-imported-file.qbs000066400000000000000000000007311347155106100323500ustar00rootroot00000000000000import "prepare.js" as PrepareHelper Product { type: ["output"] Group { files: ["test.txt"] fileTags: ["input"] } Rule { inputs: ["input"] Artifact { filePath: "dummy" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); PrepareHelper.prepare(cmd); cmd.description = "Creating output"; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/change-in-imported-file/prepare.js000066400000000000000000000001331347155106100272420ustar00rootroot00000000000000function prepare(cmd) { cmd.sourceCode = function() { console.info("old output"); }; } qbs-src-1.13.1/tests/auto/blackbox/testdata/change-in-imported-file/test.txt000066400000000000000000000000001347155106100267570ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/000077500000000000000000000000001347155106100271665ustar00rootroot00000000000000change-tracking-and-multiplexing.qbs000066400000000000000000000005221347155106100361210ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/change-tracking-and-multiplexingStaticLibrary { name: "l" Depends { condition: qbs.targetOS.contains("darwin"); name: "bundle" } Properties { condition: qbs.targetOS.contains("darwin"); bundle.isBundle: false } multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] Depends { name: "cpp" } files: ["lib.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/lib.cpp000066400000000000000000000000141347155106100304330ustar00rootroot00000000000000void l() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/changed-files/000077500000000000000000000000001347155106100233535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/changed-files/changed-files.qbs000066400000000000000000000013711347155106100265550ustar00rootroot00000000000000import qbs.TextFile CppApplication { type: ["application", "stuff"] consoleApplication: true files: ["file1.cpp", "file2.cpp", "main.cpp"] Rule { inputs: ["cpp"] outputFileTags: ["stuff"] outputArtifacts: { return [{ filePath: input.completeBaseName + ".stuff", fileTags: ["stuff"] }]; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("crazy stuff"); f.close(); } return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/changed-files/file1.cpp000066400000000000000000000023501347155106100250570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f1() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/changed-files/file2.cpp000066400000000000000000000023501347155106100250600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f2() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/changed-files/main.cpp000066400000000000000000000023511347155106100250040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/changed-inputs-from-dependencies/000077500000000000000000000000001347155106100271605ustar00rootroot00000000000000changed-inputs-from-dependencies.qbs000066400000000000000000000034161347155106100361120ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/changed-inputs-from-dependenciesimport qbs.File import qbs.TextFile Project { Product { name: "dep" type: "dep_tag" files: "input.txt" FileTagger { patterns: "*.txt"; fileTags: "inp_tag" } Rule { inputs: "inp_tag" Artifact { filePath: input.baseName + ".intermediate"; fileTags: "int_tag" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } Rule { inputs: "int_tag" Artifact { filePath: input.baseName + ".dep"; fileTags: "dep_tag" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } Product { name: "p" type: "p_tag" Depends { name: "dep" } Rule { inputsFromDependencies: "dep_tag" outputFileTags: "p_tag" outputArtifacts: { var dummy = new TextFile(input.filePath, TextFile.ReadOnly); dummy.close(); return [{ filePath: input.baseName + ".p", fileTags: "p_tag" }] } prepare: { console.info("running final prepare script"); var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/changed-inputs-from-dependencies/input.txt000066400000000000000000000000001347155106100310460ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/changed-rule-inputs/000077500000000000000000000000001347155106100245405ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/changed-rule-inputs/changed-rule-inputs.qbs000066400000000000000000000020201347155106100311170ustar00rootroot00000000000000Project { Product { name: "p1" type: "p1" Rule { alwaysRun: true multiplex: true Artifact { fileTags: "p1" filePath: "p1-dummy" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() {}; return cmd; } } } Product { name: "p2" type: "p2" Depends { name: "p1" } Rule { requiresInputs: false multiplex: true inputsFromDependencies: "p1" Artifact { fileTags: "p2" filePath: "p2-dummy" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() {}; return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/check-timestamps/000077500000000000000000000000001347155106100241235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/check-timestamps/check-timestamps.qbs000066400000000000000000000001601347155106100300700ustar00rootroot00000000000000CppApplication { name: "app" files: [ "file.cpp", "file.h", "main.cpp", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/check-timestamps/file.cpp000066400000000000000000000000401347155106100255400ustar00rootroot00000000000000#include "file.h" void f() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/check-timestamps/file.h000066400000000000000000000000121347155106100252040ustar00rootroot00000000000000void f(); qbs-src-1.13.1/tests/auto/blackbox/testdata/check-timestamps/main.cpp000066400000000000000000000000161347155106100255500ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/choose-module-instance/000077500000000000000000000000001347155106100252275ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/choose-module-instance/choose-module-instance.qbs000066400000000000000000000005771347155106100323140ustar00rootroot00000000000000import qbs.FileInfo Project { qbsSearchPaths: [ ".", path, "modules/..", FileInfo.path(FileInfo.joinPaths(path, "modules")), "other-searchpath" ] Product { Depends { name: "limerick" } type: ["text"] files: ["gerbil.txt.in"] Group { fileTagsFilter: product.type qbs.install: true } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/choose-module-instance/gerbil.txt.in000066400000000000000000000002171347155106100276410ustar00rootroot00000000000000I once had a gerbil named Bobby, Who had an unusual hobby. He ${DID} on a ${THING}, and now -- oh my ${IDOL}, now all that's left is a blobby. qbs-src-1.13.1/tests/auto/blackbox/testdata/choose-module-instance/modules/000077500000000000000000000000001347155106100266775ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/choose-module-instance/modules/limerick/000077500000000000000000000000001347155106100304765ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/choose-module-instance/modules/limerick/lord.qbs000066400000000000000000000002751347155106100321510ustar00rootroot00000000000000Module { condition: qbs.targetOS.containsAny(["Deep Purple", "Whitesnake"]) Depends { name: "texttemplate" } texttemplate.dict: ({DID: "chewed", THING: "cord", IDOL: "lord"}) } qbs-src-1.13.1/tests/auto/blackbox/testdata/choose-module-instance/modules/limerick/ritchie.qbs000066400000000000000000000005031347155106100326320ustar00rootroot00000000000000Module { condition: qbs.targetOS.containsAny(["Deep Purple", "Rainbow"]) priority: 1 // Overrides the more general "lord.qbs" instance, // which also matches on "Deep Purple". Depends { name: "texttemplate" } texttemplate.dict: ({DID: "slipped", THING: "litchi", IDOL: "ritchie"}) } qbs-src-1.13.1/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/000077500000000000000000000000001347155106100304705ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/000077500000000000000000000000001347155106100321405ustar00rootroot00000000000000limerick/000077500000000000000000000000001347155106100336605ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modulesgeneric.qbs000066400000000000000000000000741347155106100360040ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerickModule { condition: !qbs.targetOS.contains("Beatles") } qbs-src-1.13.1/tests/auto/blackbox/testdata/clean/000077500000000000000000000000001347155106100217445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/clean/clean.qbs000066400000000000000000000006211347155106100235340ustar00rootroot00000000000000Project { DynamicLibrary { Depends { name: "cpp" } version: "1.1.0" name: "dep" files: "dep.cpp" Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } CppApplication { consoleApplication: true name: "app" Depends { name: "dep" } files: "main.cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/clean/dep.cpp000066400000000000000000000024151347155106100232220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" DLL_EXPORT void f() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/clean/main.cpp000066400000000000000000000023521347155106100233760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/cli/000077500000000000000000000000001347155106100214315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/cli/HelloWorld.cs000077500000000000000000000004241347155106100240360ustar00rootroot00000000000000using Fake; public class HelloWorld { public static void Main() { System.Console.WriteLine("Hello world!"); System.Console.WriteLine(Mod.Cool()); System.Console.WriteLine(Libby.Cool()); System.Console.WriteLine(Libby2.Cool()); } } qbs-src-1.13.1/tests/auto/blackbox/testdata/cli/Libby.cs000077500000000000000000000002021347155106100230160ustar00rootroot00000000000000namespace Fake { public class Libby { public static int Cool() { return 45; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/cli/Libby2.cs000077500000000000000000000002031347155106100231010ustar00rootroot00000000000000namespace Fake { public class Libby2 { public static int Cool() { return 22; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/cli/Module.cs000066400000000000000000000002011347155106100231760ustar00rootroot00000000000000namespace Fake { public class Mod { public static int Cool() { return 420; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/cli/Module.vb000077500000000000000000000002371347155106100232140ustar00rootroot00000000000000Namespace Fake Public Class [Mod] Public Shared Function Cool() As Integer Return 420 End Function End Class End Namespace qbs-src-1.13.1/tests/auto/blackbox/testdata/cli/dotnettest.qbs000066400000000000000000000021351347155106100243360ustar00rootroot00000000000000Project { Application { Depends { name: "cli" } Depends { name: "HelloWorldModule"; condition: !qbs.toolchain.contains("mono") } Depends { name: "NetLib" } type: "application" name: "Hello" files: ["HelloWorld.cs"] Group { fileTagsFilter: product.type qbs.install: true } } // Mono's VB compiler doesn't support modules yet, and if we try with C#, it crashes anyways NetModule { condition: !qbs.toolchain.contains("mono") Depends { name: "cli" } name: "HelloWorldModule" files: ["Module.vb"] Group { fileTagsFilter: product.type qbs.install: true } } DynamicLibrary { Depends { name: "cli" } name: "NetLib" files: ["Libby.cs", "Libby2.cs"] // fill-in for missing NetModule Group { condition: qbs.toolchain.contains("mono") files: ["Module.cs"] } Group { fileTagsFilter: product.type qbs.install: true } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/cli/fshello.fs000066400000000000000000000000371347155106100234170ustar00rootroot00000000000000printfn "Hello World from F#!" qbs-src-1.13.1/tests/auto/blackbox/testdata/cli/fshello.qbs000066400000000000000000000001601347155106100235710ustar00rootroot00000000000000Application { Depends { name: "cli" } type: "application" name: "fshello" files: "fshello.fs" } qbs-src-1.13.1/tests/auto/blackbox/testdata/combined-sources/000077500000000000000000000000001347155106100241235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/combined-sources/combinable.cpp000066400000000000000000000000221347155106100267140ustar00rootroot00000000000000static int i = 1; qbs-src-1.13.1/tests/auto/blackbox/testdata/combined-sources/combined-sources.qbs000066400000000000000000000002671347155106100301000ustar00rootroot00000000000000CppApplication { name: "theapp" files: [ "combinable.cpp", "main.cpp", ] Group { files: ["uncombinable.cpp"] fileTags: ["cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/combined-sources/main.cpp000066400000000000000000000000171347155106100255510ustar00rootroot00000000000000int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/combined-sources/uncombinable.cpp000066400000000000000000000000221347155106100272570ustar00rootroot00000000000000static int i = 2; qbs-src-1.13.1/tests/auto/blackbox/testdata/command-file/000077500000000000000000000000001347155106100232155ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/command-file/command-file.qbs000066400000000000000000000010561347155106100262610ustar00rootroot00000000000000Project { StaticLibrary { name: "theLib" destinationDirectory: project.buildDirectory Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } files: ["lib.cpp"] } CppApplication { name: "theApp" cpp.libraryPaths: project.buildDirectory files: ["main.cpp"] cpp.staticLibraries: ['@' + sourceDirectory + '/' + (qbs.toolchain.contains("msvc") ? "list.msvc" : "list.gcc")] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/command-file/lib.cpp000066400000000000000000000000151347155106100244630ustar00rootroot00000000000000void f() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/command-file/list.gcc000066400000000000000000000000111347155106100246360ustar00rootroot00000000000000-ltheLib qbs-src-1.13.1/tests/auto/blackbox/testdata/command-file/list.msvc000066400000000000000000000000131347155106100250540ustar00rootroot00000000000000theLib.lib qbs-src-1.13.1/tests/auto/blackbox/testdata/command-file/main.cpp000066400000000000000000000000431347155106100246420ustar00rootroot00000000000000void f(); int main() { f(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/000077500000000000000000000000001347155106100257315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/CppDefinesApp.qbs000066400000000000000000000005721347155106100311250ustar00rootroot00000000000000CppApplication { files: ["app.c"] property bool enableObjectiveC: qbs.targetOS.contains("darwin") Group { name: "C/C++" files: [ "test.c", "test.cpp", ] } Group { name: "Objective-C" condition: enableObjectiveC files: [ "test.m", "test.mm", ] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/app.c000066400000000000000000000000351347155106100266530ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/compilerDefinesByLanguage.qbs000066400000000000000000000175701347155106100335210ustar00rootroot00000000000000Project { CppDefinesApp { name: "A" // eqiuvalent to ["c"] since we always need some compiler defines // for the architecture detection, etc. cpp.enableCompilerDefinesByLanguage: [] property var foo: { if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (!cpp.compilerDefinesByLanguage["c"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "B" cpp.enableCompilerDefinesByLanguage: ["cpp"] property var foo: { if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (cpp.compilerDefinesByLanguage["c"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (!cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "C" condition: enableObjectiveC cpp.enableCompilerDefinesByLanguage: ["objc"] property var foo: { if (!enableObjectiveC) return; if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (cpp.compilerDefinesByLanguage["c"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (!cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "D" condition: enableObjectiveC cpp.enableCompilerDefinesByLanguage: ["objcpp"] property var foo: { if (!enableObjectiveC) return; if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (cpp.compilerDefinesByLanguage["c"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (!cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "E" condition: enableObjectiveC cpp.enableCompilerDefinesByLanguage: ["cpp", "objcpp"] property var foo: { if (!enableObjectiveC) return; if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (cpp.compilerDefinesByLanguage["c"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (!cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (!cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "F" cpp.enableCompilerDefinesByLanguage: ["c", "cpp"] property var foo: { if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (!cpp.compilerDefinesByLanguage["c"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (!cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } CppDefinesApp { name: "G" condition: enableObjectiveC cpp.enableCompilerDefinesByLanguage: ["objc", "objcpp"] property var foo: { if (!enableObjectiveC) return; if (!cpp.compilerDefinesByLanguage) throw "ASSERT cpp.compilerDefinesByLanguage: " + cpp.compilerDefinesByLanguage; if (cpp.compilerDefinesByLanguage["c"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"c\"]: " + cpp.compilerDefinesByLanguage["c"]; if (cpp.compilerDefinesByLanguage["cpp"]) throw "ASSERT !cpp.compilerDefinesByLanguage[\"cpp\"]: " + cpp.compilerDefinesByLanguage["cpp"]; if (!cpp.compilerDefinesByLanguage["objc"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"objc\"]: " + cpp.compilerDefinesByLanguage["objc"]; if (!cpp.compilerDefinesByLanguage["objcpp"]) throw "ASSERT cpp.compilerDefinesByLanguage[\"objcpp\"]: " + cpp.compilerDefinesByLanguage["objcpp"]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/test.c000066400000000000000000000000001347155106100270420ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/test.cpp000066400000000000000000000000001347155106100274020ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/test.m000066400000000000000000000000001347155106100270540ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/compilerDefinesByLanguage/test.mm000066400000000000000000000000001347155106100272310ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/concurrent-executor/000077500000000000000000000000001347155106100247005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs000066400000000000000000000033341347155106100314300ustar00rootroot00000000000000import qbs.File import qbs.TextFile import "util.js" as Utils Product { type: ["final1", "final2"] Group { files: ["dummy1.input"] fileTags: ["input1"] } Group { files: ["dummy2.input"] fileTags: ["input2"] } Rule { inputs: ["input1"] Artifact { filePath: project.buildDirectory + "/dummy1.final" fileTags: ["final1"] } prepare: { var cmds = []; for (var i = 0; i < 10; ++i) { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.createFile = i == 9; cmd.sourceCode = function() { if (createFile) { console.info("Creating file"); var file = new TextFile(output.filePath, TextFile.WriteOnly); file.close(); } }; cmds.push(cmd); } return cmds; } } Rule { inputs: ["input2"] Artifact { filePath: "dummy.intermediate" fileTags: ["intermediate"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { }; return [cmd]; } } Rule { inputs: ["intermediate"] outputFileTags: "final2" prepare: { do Utils.sleep(6000); while (!File.exists(project.buildDirectory + "/dummy1.final")); var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/concurrent-executor/dummy1.input000066400000000000000000000000001347155106100271630ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/concurrent-executor/dummy2.input000066400000000000000000000000001347155106100271640ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/concurrent-executor/util.js000066400000000000000000000002511347155106100262110ustar00rootroot00000000000000function sleep(timeInMs) { var referenceTime = new Date(); var time = null; do { time = new Date(); } while (time - referenceTime < timeInMs); } qbs-src-1.13.1/tests/auto/blackbox/testdata/conditional-export/000077500000000000000000000000001347155106100245045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/conditional-export/conditional-export.qbs000066400000000000000000000005351347155106100310400ustar00rootroot00000000000000Project { property bool enableExport: false Product { name: "dep" Export { condition: project.enableExport Depends { name: "cpp" } cpp.defines: ["THE_DEFINE"] } } CppApplication { name: "theProduct" Depends { name: "dep" } files: "main.cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/conditional-export/main.cpp000066400000000000000000000024351347155106100261400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef THE_DEFINE #error "missing define" #endif int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/conditional-filetagger/000077500000000000000000000000001347155106100252745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/conditional-filetagger/conditional-filetagger.qbs000066400000000000000000000003211347155106100324110ustar00rootroot00000000000000CppApplication { name: "theApp" property bool enableTagger files: ["main.custom"]; FileTagger { condition: enableTagger patterns: ["*.custom"] fileTags: ["cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/conditional-filetagger/main.custom000066400000000000000000000000171347155106100274520ustar00rootroot00000000000000int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/configure/000077500000000000000000000000001347155106100226435ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/configure/configure.qbs000066400000000000000000000004541347155106100253360ustar00rootroot00000000000000import qbs.FileInfo Project { property string name: 'configure' qbsSearchPaths: '.' Product { type: 'application' consoleApplication: true name: project.name files: 'main.cpp' Depends { name: 'cpp' } Depends { name: 'definition' } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/configure/main.cpp000066400000000000000000000024501347155106100242740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { printf("%s..\n", TEXT); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/configure/modules/000077500000000000000000000000001347155106100243135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/configure/modules/definition/000077500000000000000000000000001347155106100264435ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/configure/modules/definition/module.qbs000066400000000000000000000016641347155106100304460ustar00rootroot00000000000000import qbs.Process Module { name: 'definition' Depends { name: 'cpp' } Probe { id: node property stringList targetOS: qbs.targetOS property stringList windowsShellPath: qbs.windowsShellPath property string result configure: { var cmd; var args; var p = path; if (targetOS.contains("windows")) { cmd = windowsShellPath; args = ["/c", "date", "/t"]; } else { cmd = 'date'; args = []; } var p = new Process(); if (0 === p.exec(cmd, args)) { found = true; result = p.readLine(); } else { found = false; result = undefined; } p.close(); } } cpp.defines: node.found ? 'TEXT="Configured at ' + node.result + '"' : undefined } qbs-src-1.13.1/tests/auto/blackbox/testdata/conflicting-artifacts/000077500000000000000000000000001347155106100251375ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/conflicting-artifacts/conflicting-artifacts.qbs000066400000000000000000000005041347155106100321220ustar00rootroot00000000000000Project { CppApplication { name: "a" targetName: "theName" destinationDirectory: project.buildDirectory files: ["main.cpp"] } CppApplication { name: "b" targetName: "theName" destinationDirectory: project.buildDirectory files: ["main.cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/conflicting-artifacts/main.cpp000066400000000000000000000023511347155106100265700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/cpu-features/000077500000000000000000000000001347155106100232655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/cpu-features/cpu-features.qbs000066400000000000000000000007341347155106100264030ustar00rootroot00000000000000CppApplication { Depends { name: "cpufeatures" } cpufeatures.x86_sse2: true cpufeatures.x86_avx: true cpufeatures.x86_avx512f: false files: ["main.cpp"] property bool dummy: { console.info("is x86: " + (qbs.architecture === "x86")); console.info("is x64: " + (qbs.architecture === "x86_64")); console.info("is gcc: " + qbs.toolchain.contains("gcc")); console.info("is msvc: " + qbs.toolchain.contains("msvc")); } } qbs-src-1.13.1/tests/auto/blackbox/testdata/cpu-features/main.cpp000066400000000000000000000000161347155106100247120ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/cxx-language-version/000077500000000000000000000000001347155106100247305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/cxx-language-version/cxx-language-version.qbs000066400000000000000000000017011347155106100315040ustar00rootroot00000000000000CppApplication { name: "app" files: ["main.cpp"] Probe { id: compilerProbe property stringList toolchain: qbs.toolchain property string compilerVersion: cpp.compilerVersion configure: { var isNewerMsvc; var isEvenNewerMsvc; var isOlderMsvc; var isGcc; if (toolchain.contains("msvc")) { if (compilerVersion >= "19.12.25831") isEvenNewerMsvc = true; if (compilerVersion >= "18.00.30723") isNewerMsvc = true; else isOlderMsvc = true; } else { isGcc = true; } console.info("is newer MSVC: " + isNewerMsvc); console.info("is even newer MSVC: " + isEvenNewerMsvc); console.info("is older MSVC: " + isOlderMsvc); console.info("is GCC: " + isGcc); } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/cxx-language-version/main.cpp000066400000000000000000000000161347155106100263550ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/dependenciesProperty/000077500000000000000000000000001347155106100250555ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs000066400000000000000000000024011347155106100317540ustar00rootroot00000000000000import qbs.TextFile import qbs.FileInfo Project { Product { name: "newDependency" } Product { type: "deps" name: "product1" Depends { name: "product2" } // Depends { name: 'product2' } // Depends { name: 'newDependency' } Rule { multiplex: true inputsFromDependencies: "application" Artifact { fileTags: ["deps"] filePath: product.name + '.deps' } prepare: { var cmd = new JavaScriptCommand(); cmd.description = 'generate ' + FileInfo.fileName(output.filePath); cmd.highlight = 'codegen'; cmd.sourceCode = function() { file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(JSON.stringify(product.dependencies, undefined, 2)); file.close(); } return cmd; } } } Product { type: "application" consoleApplication: true name: "product2" property string narf: "zort" Depends { name: "cpp" } cpp.defines: ["SMURF"] files: ["product2.cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/dependenciesProperty/product2.cpp000066400000000000000000000023641347155106100273300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/dependency-profile-mismatch/000077500000000000000000000000001347155106100262415ustar00rootroot00000000000000dependency-profile-mismatch.qbs000066400000000000000000000004111347155106100342440ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dependency-profile-mismatchProject { property string mainProfile property string depProfile Product { name: "dep" qbs.profiles: [project.depProfile] } Product { name: "main" Depends { name: "dep"; profiles: [project.mainProfile]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/deprecated-property/000077500000000000000000000000001347155106100246445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/deprecated-property/deprecated-property.qbs000066400000000000000000000002241347155106100313330ustar00rootroot00000000000000import qbs Product { Depends { name: "themodule" } themodule.newProp: true themodule.oldProp: false themodule.veryOldProp: false } qbs-src-1.13.1/tests/auto/blackbox/testdata/deprecated-property/modules/000077500000000000000000000000001347155106100263145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/000077500000000000000000000000001347155106100303025ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/m.qbs000066400000000000000000000011211347155106100312400ustar00rootroot00000000000000import qbs Module { property bool newProp property bool oldProp property bool forgottenProp PropertyOptions { name: "newProp" description: "Use this, it's good!" } PropertyOptions { name: "oldProp" description: "Use newProp instead." removalVersion: "99.9" } PropertyOptions { name: "veryOldProp" description: "Use newProp instead." removalVersion: "1.3" } PropertyOptions { name: "forgottenProp" description: "Use newProp instead." removalVersion: "1.8" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/disappeared-profile/000077500000000000000000000000001347155106100246015ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/disappeared-profile/disappeared-profile.qbs000066400000000000000000000003171347155106100312300ustar00rootroot00000000000000Product { type: ["out1", "out2"] Depends { name: "m" } Group { files: ["in1.txt"] fileTags: ["in1"] } Group { files: ["in2.txt"] fileTags: ["in2"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/disappeared-profile/in1.txt000066400000000000000000000000001347155106100260170ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/disappeared-profile/in2.txt000066400000000000000000000000001347155106100260200ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/000077500000000000000000000000001347155106100270255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/modules/000077500000000000000000000000001347155106100304755ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/modules/m/000077500000000000000000000000001347155106100307315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/disappeared-profile/modules-dir/modules/m/m.qbs000066400000000000000000000014351347155106100316770ustar00rootroot00000000000000Module { property string p1 property string p2 Rule { inputs: ["in1"] Artifact { filePath: "dummy1.txt" fileTags: ["out1"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName + " with " + product.m.p1; cmd.sourceCode = function() {}; return [cmd]; } } Rule { inputs: ["in2"] Artifact { filePath: "dummy2.txt" fileTags: ["out2"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName + " with " + product.m.p2; cmd.sourceCode = function() {}; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/discard-unused-data/000077500000000000000000000000001347155106100245035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs000066400000000000000000000012611347155106100310330ustar00rootroot00000000000000CppApplication { name: "app" type: base.concat("custom") files: "main.cpp" Depends { name: "bundle"; condition: qbs.targetOS.contains("darwin") } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } Rule { multiplex: true outputFileTags: "custom" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info("is Darwin: " + product.qbs.targetOS.contains("darwin")); console.info("---" + product.cpp.nmPath + "---"); } return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/discard-unused-data/main.cpp000066400000000000000000000000441347155106100261310ustar00rootroot00000000000000void unusedFunc() {} int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/driver-linker-flags/000077500000000000000000000000001347155106100245315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/driver-linker-flags/driver-linker-flags.qbs000066400000000000000000000005451347155106100311130ustar00rootroot00000000000000CppApplication { files: "main.cpp" Properties { condition: toolchainProbe.found cpp.driverLinkerFlags: ["-nostartfiles"] } Probe { id: toolchainProbe condition: qbs.toolchain.contains("gcc") configure: { console.info("toolchain is GCC-like"); found = true; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/driver-linker-flags/main.cpp000066400000000000000000000000161347155106100261560ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/000077500000000000000000000000001347155106100256375ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs000066400000000000000000000006201347155106100270570ustar00rootroot00000000000000DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle"; condition: qbs.targetOS.contains("darwin") } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false cpp.minimumMacosVersion: "10.7" // For -rpath } install: true installImportLib: true qbs.installPrefix: "" installDir: "" importLibInstallDir: "" } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/lib1.cpp000066400000000000000000000002041347155106100271660ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_EXPORT void theLibFunc() { std::cout << "Hello from thelib!" << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/lib2.cpp000066400000000000000000000002161347155106100271720ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_EXPORT void theOtherLibFunc() { std::cout << "Hello from theotherlib!" << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/lib3.cpp000066400000000000000000000002161347155106100271730ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_EXPORT void theThirdLibFunc() { std::cout << "Hello from thethirdlib!" << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/lib4.cpp000066400000000000000000000001631347155106100271750ustar00rootroot00000000000000#include "../dllexport.h" DLL_IMPORT void theLibFunc(); DLL_EXPORT void theFourthLibFunc() { theLibFunc(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/lib5.cpp000066400000000000000000000000311347155106100271700ustar00rootroot00000000000000void staticLibFunc() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/main.cpp000066400000000000000000000003241347155106100272660ustar00rootroot00000000000000#include "../dllexport.h" DLL_IMPORT void theOtherLibFunc(); DLL_IMPORT void theFourthLibFunc(); void theThirdLibFunc() { } int main() { theOtherLibFunc(); theThirdLibFunc(); theFourthLibFunc(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/000077500000000000000000000000001347155106100273075ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/000077500000000000000000000000001347155106100305565ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/broken.cpp000066400000000000000000000000151347155106100325360ustar00rootroot00000000000000syntax error qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/thelib.qbs000066400000000000000000000015051347155106100325350ustar00rootroot00000000000000import qbs.FileInfo Module { Depends { name: "cpp" } property string baseDir: FileInfo.cleanPath(FileInfo.joinPaths(path, "..", "..")) cpp.rpaths: [product.thelib.baseDir] Group { name: "thelib dll" files: FileInfo.joinPaths(product.thelib.baseDir, cpp.dynamicLibraryPrefix + "thelib" + cpp.dynamicLibrarySuffix) fileTags: ["dynamiclibrary"] filesAreTargets: true } Group { name: "thelib dll import" condition: qbs.targetOS.contains("windows") files: FileInfo.joinPaths(product.thelib.baseDir, "thelib.lib") fileTags: ["dynamiclibrary_import"] filesAreTargets: true } Group { name: "to be ignored" filesAreTargets: true files: "broken.cpp" fileTags: ["cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/000077500000000000000000000000001347155106100316205ustar00rootroot00000000000000theotherlib.qbs000066400000000000000000000013441347155106100345630ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlibimport qbs.FileInfo Module { Depends { name: "cpp" } property string baseDir: FileInfo.cleanPath(FileInfo.joinPaths(path, "..", "..")) cpp.rpaths: [product.theotherlib.baseDir] Group { name: "theotherlib dll" files: FileInfo.joinPaths(product.theotherlib.baseDir, cpp.dynamicLibraryPrefix + "theotherlib" + cpp.dynamicLibrarySuffix) fileTags: ["dynamiclibrary"] filesAreTargets: true } Group { name: "theotherlib dll import" condition: qbs.targetOS.contains("windows") files: FileInfo.joinPaths(product.theotherlib.baseDir, "theotherlib.lib") fileTags: ["dynamiclibrary_import"] filesAreTargets: true } } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thethirdlib/000077500000000000000000000000001347155106100316115ustar00rootroot00000000000000thethirdlib.qbs000066400000000000000000000012641347155106100345460ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thethirdlibimport qbs.FileInfo Module { Depends { name: "cpp" } property string baseDir: FileInfo.cleanPath(FileInfo.joinPaths(path, "..", "..")) Group { name: "thethirdlib dll" condition: false files: FileInfo.joinPaths(product.theotherlib.baseDir, cpp.dynamicLibraryPrefix + "thethirdlib" + cpp.dynamicLibrarySuffix) fileTags: ["dynamiclibrary"] filesAreTargets: true } Group { name: "thethirdlib dll import" condition: false files: FileInfo.joinPaths(product.thethirdlib.baseDir, "thethirdlib.lib") fileTags: ["dynamiclibrary_import"] filesAreTargets: true } } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/theapp.qbs000066400000000000000000000014551347155106100276340ustar00rootroot00000000000000Project { CppApplication { name: "theapp" cpp.minimumMacosVersion: "10.7" // For -rpath Depends { name: "theotherlib" } Depends { name: "thethirdlib" } Depends { name: "thefourthlib" } Depends { name: "staticlib" } files: "main.cpp" Group { fileTagsFilter: "dynamiclibrary" qbs.install: true qbs.installSourceBase: buildDirectory } } Dll { name: "thefourthlib" Depends { name: "thelib" } files: "lib4.cpp" Export { Depends { name: "cpp" } cpp.rpaths: [qbs.installRoot] } } StaticLibrary { name: "staticlib" Depends { name: "cpp" } Depends { name: "theotherlib" } files: "lib5.cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-library-in-module/thelibs.qbs000066400000000000000000000003311347155106100277750ustar00rootroot00000000000000Project { Dll { name: "thelib" files: "lib1.cpp" } Dll { name: "theotherlib" files: "lib2.cpp" } Dll { name: "thethirdlib" files: "lib3.cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-project/000077500000000000000000000000001347155106100237525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-project/dynamic-project.qbs000066400000000000000000000025211347155106100275510ustar00rootroot00000000000000import qbs.File import qbs.FileInfo import qbs.TextFile Project { Probe { id: projectBuilder property stringList refs: [] property string sourceDir: sourceDirectory configure: { var tempDir = FileInfo.joinPaths(sourceDir, "temp"); File.makePath(tempDir); var srcDir = FileInfo.joinPaths(sourceDir, "src"); var projectDirs = File.directoryEntries(srcDir, File.Dirs | File.NoDotAndDotDot); var list = []; for (it in projectDirs) { var name = projectDirs[it]; var productSrcDir = FileInfo.joinPaths(srcDir, name); var productFilePath = FileInfo.joinPaths(tempDir, name + ".qbs"); var file = new TextFile(productFilePath, TextFile.WriteOnly); try { file.writeLine("import qbs"); file.writeLine("CppApplication"); file.writeLine("{"); file.writeLine("\tfiles: [ \"" + productSrcDir + "/*.cpp\" ]"); file.writeLine("}"); } finally { file.close(); } list.push(productFilePath); } found = true; refs = list; } } references: projectBuilder.refs } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-project/src/000077500000000000000000000000001347155106100245415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-project/src/app/000077500000000000000000000000001347155106100253215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-project/src/app/main.cpp000066400000000000000000000000311347155106100267430ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-project/src/app2/000077500000000000000000000000001347155106100254035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamic-project/src/app2/main.cpp000066400000000000000000000000311347155106100270250ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicMultiplexRule/000077500000000000000000000000001347155106100250425ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicMultiplexRule/dynamicMultiplexRule.qbs000066400000000000000000000015571347155106100317410ustar00rootroot00000000000000import qbs.TextFile Project { Product { type: ["stuff"] Group { files: ["one.txt", "two.txt", "three.txt"] fileTags: ["text"] } Rule { multiplex: true inputs: "text" outputFileTags: ["stuff"] outputArtifacts: { return [{ filePath: "stuff-from-" + inputs.text.length + "-inputs", fileTags: ["stuff"] }]; } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("narf!"); f.close(); } return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicMultiplexRule/one.txt000066400000000000000000000000001347155106100263520ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicMultiplexRule/three.txt000066400000000000000000000000001347155106100267000ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicMultiplexRule/two.txt000066400000000000000000000000001347155106100264020ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/000077500000000000000000000000001347155106100245425ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/after/000077500000000000000000000000001347155106100256435ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/after/numbers.l000066400000000000000000000051361347155106100275000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of Qbs. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ /* scanner for integer and float numbers */ %option noyywrap %{ #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE is missing! #endif /* need this for the call to atof() below */ #include %} DIGIT [0-9] %% {DIGIT}+ { printf("integer: %s (%d)\n", yytext, atoi(yytext)); } {DIGIT}+"."{DIGIT}* { printf("float: %s (%g)\n", yytext, atof(yytext)); } "{"[\^{}}\n]*"}" /* eat up one-line comments */ [ \t\n]+ /* eat up whitespace */ . printf("Unexpected character: %s\n", yytext); %% int main(int argc, char **argv) { if (argc > 1) yyin = fopen(argv[1], "r"); else yyin = stdin; yylex(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/000077500000000000000000000000001347155106100260045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/flexoptionsreader.js000066400000000000000000000067041347155106100321060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of Qbs. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ // needs import qbs.TextFile function readFlexOptions(filePath) { function splitOptions(str) { var options = []; var opt = ""; var inquote = false; for (var i = 0; i < str.length; ++i) { if (str[i] === '"') { opt += '"'; inquote = !inquote; } else if (str[i] === ' ' && !inquote) { options.push(opt); opt = ""; } else { opt += str[i]; } } if (opt.length) options.push(opt); return options; } function unquote(str) { var l = str.length; if (l > 2 && str[0] === '"' && str[l - 1] === '"') return str.substr(1, l - 2); return str; } function parseOptionLine(result, str) { var options = splitOptions(str); var re = /^(outfile|header-file)=(.*)$/; var reres; for (var k in options) { re.lastIndex = 0; reres = re.exec(options[k]); if (reres === null) continue; result[reres[1]] = unquote(reres[2]); } } var tf = new TextFile(input.filePath); var line; var optrex = /^%option\s+(.*$)/; var res; var options = {}; while (!tf.atEof()) { line = tf.readLine(); if (line === "%%") break; optrex.lastIndex = 0; res = optrex.exec(line); if (res === null) continue; parseOptionLine(options, res[1]); } tf.close(); return options; } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs000066400000000000000000000116111347155106100303240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of Qbs. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs.FileInfo import qbs.Probes import qbs.TextFile import "flexoptionsreader.js" as FlexOptionsReader Project { Product { name: "genlexer" type: "application" consoleApplication: true Depends { name: "cpp" } Group { files: ["numbers.l"] fileTags: ["flex"] } Probes.PathProbe { id: flexProbe names: ["flex"] platformSearchPaths: ["/usr/local/bin", "/usr/bin", "/bin"] } property bool isFlexAvailable: flexProbe.found Rule { inputs: ["flex"] outputFileTags: ["c", "hpp"] outputArtifacts: { var options = FlexOptionsReader.readFlexOptions(input.filePath); var sourceFileName = options["outfile"] || "lex.yy.c"; var headerFileName = options["header-file"]; var result = [{ filePath: "GeneratedFiles/" + sourceFileName, fileTags: ["c"], cpp: { defines: ["CRUCIAL_DEFINE"] } }]; if (headerFileName) { result.push({ filePath: "GeneratedFiles/" + headerFileName, fileTags: ["hpp"] }); } return result; } prepare: { var cmd; if (product.isFlexAvailable) { // flex is available. Let's call it. cmd = new Command("flex", [input.filePath]); cmd.workingDirectory = product.buildDirectory + "/GeneratedFiles"; } else { // No flex available here, generate some C source and header. cmd = new JavaScriptCommand(); cmd.sourceFileName = outputs["c"][0].filePath; cmd.headerFileName = outputs["hpp"] ? outputs["hpp"][0].filePath : ""; cmd.sourceCode = function() { var fsrc = new TextFile(sourceFileName, TextFile.WriteOnly); if (headerFileName) { fsrc.write("#include \"" + FileInfo.fileName(headerFileName) + "\"\n\n"); var fhdr = new TextFile(headerFileName, TextFile.WriteOnly); fhdr.write("// a rather empty header file\n"); fhdr.close(); } fsrc.write("\n#ifndef CRUCIAL_DEFINE\n"); fsrc.write("# error CRUCIAL_DEFINE is missing!\n"); fsrc.write("#endif\n\n"); fsrc.write("int main() { return 0; }\n"); fsrc.close(); }; } cmd.description = "flexing " + FileInfo.fileName(input.filePath); return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/numbers.l000066400000000000000000000052361347155106100276420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of Qbs. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ /* scanner for integer and float numbers */ %option noyywrap %option outfile="numberscanner.c" header-file="numberscanner.h" %{ #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE is missing! #endif /* need this for the call to atof() below */ #include %} DIGIT [0-9] %% {DIGIT}+ { printf("integer: %s (%d)\n", yytext, atoi(yytext)); } {DIGIT}+"."{DIGIT}* { printf("float: %s (%g)\n", yytext, atof(yytext)); } "{"[\^{}}\n]*"}" /* eat up one-line comments */ [ \t\n]+ /* eat up whitespace */ . printf("Unexpected character: %s\n", yytext); %% int main(int argc, char **argv) { if (argc > 1) yyin = fopen(argv[1], "r"); else yyin = stdin; yylex(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableExceptions/000077500000000000000000000000001347155106100241525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/enableExceptions/empty.m000066400000000000000000000000321347155106100254610ustar00rootroot00000000000000int main2() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableExceptions/empty.mm000066400000000000000000000000321347155106100256360ustar00rootroot00000000000000int main3() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableExceptions/emptymain.cpp000066400000000000000000000023641347155106100266660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableExceptions/exceptions-objc.qbs000066400000000000000000000001141347155106100277510ustar00rootroot00000000000000CppApplication { files: ["main.m"] cpp.frameworks: ["Foundation"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp-cpp.qbs000066400000000000000000000001361347155106100310750ustar00rootroot00000000000000CppApplication { Group { files: ["main.cpp"] fileTags: ["objcpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableExceptions/exceptions-objcpp.qbs000066400000000000000000000001771347155106100303220ustar00rootroot00000000000000CppApplication { Group { files: ["main.m"] fileTags: ["objcpp"] } cpp.frameworks: ["Foundation"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs000066400000000000000000000002611347155106100270410ustar00rootroot00000000000000CppApplication { files: ["main.cpp"] cpp.treatWarningsAsErrors: true cpp.defines: qbs.toolchain.contains("msvc") && !cpp.enableExceptions ? ["FORCE_FAIL_VS"] : [] } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableExceptions/main.cpp000066400000000000000000000030031347155106100255760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #if defined(__GNUC__) && !(defined(__cpp_exceptions) || defined(__EXCEPTIONS)) #error Exceptions are disabled! #endif int main() { #ifdef FORCE_FAIL_VS #error "Microsoft Visual C++ cannot disable exceptions at compile-time" #endif throw std::runtime_error("failed"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableExceptions/main.m000066400000000000000000000001141347155106100252500ustar00rootroot00000000000000#import int main() { @throw [NSError new]; } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableExceptions/none.qbs000066400000000000000000000002351347155106100256200ustar00rootroot00000000000000CppApplication { files: ["emptymain.cpp"] Group { condition: qbs.targetOS.contains("darwin") files: ["empty.m", "empty.mm"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableRtti/000077500000000000000000000000001347155106100227535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/enableRtti/main.cpp000066400000000000000000000031671347155106100244120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #if defined(__GNUC__) && !(defined(__cpp_rtti) || defined(__GXX_RTTI)) #error RTTI is disabled! #endif class I { public: virtual ~I() { } virtual void x() { } }; class A : public I { void x() override { } }; class B : public I { void x() override { } }; int main() { const auto a = new A(); B *b = dynamic_cast(a); (void)b; delete a; return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/enableRtti/rtti.qbs000066400000000000000000000004311347155106100244420ustar00rootroot00000000000000Project { property bool treatAsObjcpp: false CppApplication { cpp.cxxLanguageVersion: "c++11" cpp.treatWarningsAsErrors: true Group { files: ["main.cpp"] fileTags: [project.treatAsObjcpp ? "objcpp" : "cpp"] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/env-merging/000077500000000000000000000000001347155106100231005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/env-merging/env-merging.qbs000066400000000000000000000010141347155106100260210ustar00rootroot00000000000000Project { CppApplication { name: "tool" files: "main.c" } Product { name: "p" type: "custom" Depends { name: "tool" } Rule { inputsFromDependencies: "application" outputFileTags: "custom" prepare: { var cmd = new Command(input.filePath, []); cmd.description = "running tool"; cmd.environment = ["PATH=/opt/tool/bin"]; return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/env-merging/main.c000066400000000000000000000001541347155106100241700ustar00rootroot00000000000000#include #include int main() { printf("PATH=%s", getenv("PATH")); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/env-normalization/000077500000000000000000000000001347155106100243365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/env-normalization/env-normalization.qbs000066400000000000000000000003111347155106100305140ustar00rootroot00000000000000import qbs.Environment Product { Probe { id: dummy property var env: Environment.currentEnv() configure: { console.info(JSON.stringify(env)); } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/000077500000000000000000000000001347155106100227035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/nonexistentWorkingDir/000077500000000000000000000000001347155106100272615ustar00rootroot00000000000000nonexistentWorkingDir.qbs000066400000000000000000000005741347155106100342750ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/nonexistentWorkingDirApplication { name: "kaputt" type: ["nutritious"] Rule { multiplex: true Artifact { filePath: "Stulle" fileTags: ["nutritious"] } prepare: { var cmd = new Command("ls"); cmd.workingDirectory = "/does/not/exist"; cmd.silent = true; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-filePath/000077500000000000000000000000001347155106100313055ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-filePath/main.cpp000066400000000000000000000000311347155106100327270ustar00rootroot00000000000000int main() { return 0; } outputArtifacts-missing-filePath.qbs000066400000000000000000000005421347155106100403400ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-filePathCppApplication { type: base.concat("txt") files : ["main.cpp"] Rule { inputs: ["application"] outputArtifacts: [{ fileTags: ["txt"] }] outputFileTags: ["txt"] prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-fileTags/000077500000000000000000000000001347155106100313075ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-fileTags/main.cpp000066400000000000000000000000311347155106100327310ustar00rootroot00000000000000int main() { return 0; } outputArtifacts-missing-fileTags.qbs000066400000000000000000000005721347155106100403470ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/outputArtifacts-missing-fileTagsCppApplication { type: base.concat("txt") files : ["main.cpp"] Rule { inputs: ["application"] outputArtifacts: [{ filePath: input.completeBaseName + ".txt" }] outputFileTags: ["txt"] prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/tag-mismatch/000077500000000000000000000000001347155106100252615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/tag-mismatch/tag-mismatch.qbs000066400000000000000000000017631347155106100303550ustar00rootroot00000000000000Product { name: "p" type: "p_type" Rule { multiplex: true outputFileTags: ["x"] outputArtifacts: [{filePath: "dummy1", fileTags: ["x","y","z"]}] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { }; return cmd; } } Rule { inputs: ["y"] Artifact { filePath: "dummy2"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { }; return cmd; } } Rule { inputs: ["x"] Artifact { filePath: "dummy3"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/000077500000000000000000000000001347155106100314005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/boom.txt.in000066400000000000000000000000451347155106100335010ustar00rootroot00000000000000Boom! shake-shake-shake the ${what}! texttemplate-unknown-placeholder.qbs000066400000000000000000000002411347155106100405220ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholderProduct { type: ["text"] Depends { name: "texttemplate" } texttemplate.dict: ({ wat: "room" }) // typo in key name files: [ "boom.txt.in" ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/error-info/000077500000000000000000000000001347155106100227445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/error-info/error-info.qbs000066400000000000000000000034641347155106100255440ustar00rootroot00000000000000import "helper.js" as Helper Project { property bool fail1: false property bool fail2: false property bool fail3: false property bool fail4: false property bool fail5: false property bool fail6: false property bool fail7: false Product { name: "myproduct" type: ["foo", "bar"] Rule { multiplex: true Artifact { fileTags: ["foo"] filePath: { var path = "foo"; if (project.fail1) throw "fail1"; return path; } } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function () { }; cmd.silent = true; if (project.fail2) generate.an.error; if (project.fail6) Helper.doSomethingEvil(); return cmd; } } Rule { multiplex: true outputFileTags: ["bar"] outputArtifacts: { var list = []; list.push({ fileTags: ["bar"], filePath: "bar" }); if (project.fail3) throw "fail3"; if (project.fail5) Helper.doSomethingBad(); return list; } prepare: { var cmd = new JavaScriptCommand(); cmd.fail7 = project.fail7; cmd.sourceCode = function () { if (fail7) will.fail; }; cmd.silent = true; if (project.fail4) generate.an.error; return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/error-info/helper.js000066400000000000000000000001601347155106100245560ustar00rootroot00000000000000var x; function doSomethingBad() { nothinghere.works; } function doSomethingEvil() { throw "OUCH!"; } qbs-src-1.13.1/tests/auto/blackbox/testdata/escaped-linker-flags/000077500000000000000000000000001347155106100246425ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/escaped-linker-flags/escaped-linker-flags.qbs000066400000000000000000000004341347155106100313320ustar00rootroot00000000000000CppApplication { name: "app" property bool escapeLinkerFlags Properties { condition: escapeLinkerFlags cpp.linkerFlags: ["-Wl,-s"] } Properties { condition: !escapeLinkerFlags cpp.linkerFlags: ["-s"] } files: ["main.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/escaped-linker-flags/main.cpp000066400000000000000000000000171347155106100262700ustar00rootroot00000000000000int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/explicitly-depends-on/000077500000000000000000000000001347155106100251025ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/explicitly-depends-on/explicitly-depends-on.qbs000066400000000000000000000067551347155106100320460ustar00rootroot00000000000000import qbs.File import qbs.TextFile Project { // Cases: // step1 + in-product final -> step2 -> step3 -> final => rule cycle // step1 + dependency final -> step2 -> step3 -> final => ok // step1 + module filesAreTargets final -> step2 -> step3 -> final => ok name: "proj1" property bool useModule: false Product { name: "prod1" type: "final" property bool useExplicitlyDependsOn: false property bool useExplicitlyDependsOnFromDependencies: false Depends { condition: !project.useModule name: "prod2" } Depends { condition: project.useModule name: "module1" } Group { files: ["step1.txt"] fileTags: ["step1"] } Rule { inputs: ["step3"] outputFileTags: ["final"] Artifact { filePath: "final.txt" fileTags: ["final"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "step3 -> final"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } Rule { inputs: ["step2"] outputFileTags: ["step3"] Artifact { filePath: "step3.txt" fileTags: ["step3"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "step2 -> step3"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } Rule { inputs: ["step1"] outputFileTags: ["step2"] Artifact { filePath: "step2.txt" fileTags: ["step2"] } Properties { condition: useExplicitlyDependsOn explicitlyDependsOn: ["final"] } Properties { condition: useExplicitlyDependsOnFromDependencies explicitlyDependsOnFromDependencies: ["final"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "step1 -> step2"; cmd.sourceCode = function() { console.info("Using explicitlyDependsOnArtifact: " + explicitlyDependsOn["final"][0].fileName) File.copy(input.filePath, output.filePath); }; return cmd; } } } Product { name: "prod2" type: "final" condition: !project.useModule Rule { multiplex: true requiresInputs: false outputFileTags: ["final"] Artifact { filePath: "product-fish.txt" fileTags: ["final"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating 'product-fish.txt' tagged with 'final'"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.ReadWrite); file.write("Lots of fish."); file.close() }; return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/explicitly-depends-on/modules/000077500000000000000000000000001347155106100265525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/explicitly-depends-on/modules/module1/000077500000000000000000000000001347155106100301205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/explicitly-depends-on/modules/module1/module-fish.txt000066400000000000000000000000141347155106100330700ustar00rootroot00000000000000Module fish qbs-src-1.13.1/tests/auto/blackbox/testdata/explicitly-depends-on/modules/module1/module1.qbs000066400000000000000000000001721347155106100321750ustar00rootroot00000000000000Module { Group { filesAreTargets: true fileTags: ["final"] files: ["module-fish.txt"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/explicitly-depends-on/step1.txt000066400000000000000000000000031347155106100266700ustar00rootroot00000000000000hi qbs-src-1.13.1/tests/auto/blackbox/testdata/export-rule/000077500000000000000000000000001347155106100231505ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/export-rule/blubber.cpp000066400000000000000000000023661347155106100253000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void justSomeFunction() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/export-rule/export-rule.qbs000066400000000000000000000021551347155106100261500ustar00rootroot00000000000000import qbs.File Project { Application { name: "MyApp" files: ["myapp.blubb"] Depends { name: "blubber" } } StaticLibrary { name: "blubber" files: ["blubber.cpp"] Depends { name: "cpp" } Export { Depends { name: "cpp" } property bool enableTagger property string description: "Creating C++ source file."; FileTagger { condition: enableTagger patterns: ["*.blubb"] fileTags: ["blubb"] } Rule { inputs: ["blubb"] Artifact { filePath: input.completeBaseName + ".cpp" fileTags: ["cpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = product.blubber.description; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return [cmd]; } } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/export-rule/myapp.blubb000066400000000000000000000001271347155106100253060ustar00rootroot00000000000000extern void justSomeFunction(); int main() { justSomeFunction(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/000077500000000000000000000000001347155106100264155ustar00rootroot00000000000000export-to-outside-searchpath.qbs000066400000000000000000000005761347155106100346100ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/export-to-outside-searchpathProject { Project { qbsSearchPaths: ["qbs-resources"] Product { name: "otherProduct" Depends { name: "dep" } } Product { name: "dep" Export { Depends { name: "aModule" } } } } Project { Product { name: "theProduct" Depends { name: "dep" } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/qbs-resources/000077500000000000000000000000001347155106100312125ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/qbs-resources/modules/000077500000000000000000000000001347155106100326625ustar00rootroot00000000000000aModule/000077500000000000000000000000001347155106100341715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/qbs-resources/modulesaModule.qbs000066400000000000000000000000131347155106100362600ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/export-to-outside-searchpath/qbs-resources/modules/aModuleModule { } qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/000077500000000000000000000000001347155106100304575ustar00rootroot00000000000000exported-dependency-in-disabled-product.qbs000066400000000000000000000006511347155106100407060ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-productProject { Application { name: "app" Depends { name: "dep"; required: false } files: "main.cpp" } Product { name: "dep" condition: eval(conditionString) property string conditionString Depends { name: "nosuchmodule"; required: false } Depends { name: "broken"; required: false } Export { Depends { name: "cpp" } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/main.cpp000066400000000000000000000000161347155106100321040ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/modules/000077500000000000000000000000001347155106100321275ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/modules/broken/000077500000000000000000000000001347155106100334075ustar00rootroot00000000000000broken.qbs000066400000000000000000000000561347155106100353200ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-dependency-in-disabled-product/modules/brokenModule { validate: { throw "broken!"; } } qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/000077500000000000000000000000001347155106100302255ustar00rootroot00000000000000exported-property-in-disabled-product.qbs000066400000000000000000000007341347155106100402240ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-property-in-disabled-productProject { CppApplication { name: "app" Depends { name: "dep"; required: false } files: "main.cpp" } Product { name: "dep" condition: eval(conditionString) property string conditionString Depends { name: "nosuchmodule"; required: false } Depends { name: "broken"; required: false } Export { Depends { name: "cpp" } cpp.dynamicLibraries: ["nosuchlib"] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/main.cpp000066400000000000000000000000161347155106100316520ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/modules/000077500000000000000000000000001347155106100316755ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/modules/broken/000077500000000000000000000000001347155106100331555ustar00rootroot00000000000000broken.qbs000066400000000000000000000000561347155106100350660ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exported-property-in-disabled-product/modules/brokenModule { validate: { throw "broken!"; } } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/000077500000000000000000000000001347155106100243335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/TheFirstLib.pc000066400000000000000000000005351347155106100270410ustar00rootroot00000000000000prefix=/opt/the firstlib Name: TheFirstLib Description: TheFirstLib Version: 1.0 URL: http://www.example.com/thefirstlib Cflags: -DTheFirstLib -I"${prefix}/include" -pthread -DHAVE_INDUSTRIAL_STRENGTH_HAIR_DRYER -I/otherdir/include1 -I/otherdir/include2 Libs: -L"${prefix}/lib" -lTheFirstLib -pthread Requires: Qt5Core Requires.private: SomeHelper qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/TheFirstLib_windows.pc000066400000000000000000000005131347155106100306070ustar00rootroot00000000000000prefix=/opt/the firstlib Name: TheFirstLib Description: TheFirstLib Version: 1.0 URL: http://www.example.com/thefirstlib Cflags: -DTheFirstLib -I"${prefix}/include" -DHAVE_INDUSTRIAL_STRENGTH_HAIR_DRYER -I/otherdir/include1 -I/otherdir/include2 Libs: -L"${prefix}/lib" -lTheFirstLib Requires: Qt5Core Requires.private: SomeHelper qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/TheSecondLib.pc000066400000000000000000000002721347155106100271630ustar00rootroot00000000000000config1=a b config2=c Name: TheSecondLib Description: The second lib Version: 2.0 Cflags: -I/opt/thesecondlib/include Libs: -L/opt/thesecondlib/lib -lTheSecondLib Requires: TheFirstLib qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/boringstaticlib.cpp000066400000000000000000000000571347155106100302200ustar00rootroot00000000000000int calculateLuckyNumber() { return 12 * 13; } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs000066400000000000000000000075101347155106100305160ustar00rootroot00000000000000import qbs.FileInfo Project { Product { name: "dummy" Export { Depends { name: "TheFirstLib" } } } Product { name: "SomeHelper" Depends { name: "Exporter.pkgconfig" } Exporter.pkgconfig.versionEntry: "1.0" } StaticLibrary { Depends { name: "cpp" } name: "BoringStaticLib" files: ["boringstaticlib.cpp"] Export { Depends { name: "cpp" } cpp.defines: ["HAVE_INDUSTRIAL_STRENGTH_HAIR_DRYER"] } } DynamicLibrary { name: "TheFirstLib" version: "1.0" Depends { name: "SomeHelper" } Depends { name: "Exporter.pkgconfig" } Exporter.pkgconfig.excludedDependencies: ["Qt.core", "helper3"] Exporter.pkgconfig.requiresEntry: "Qt5Core" Exporter.pkgconfig.urlEntry: "http://www.example.com/thefirstlib" Depends { name: "cpp" } cpp.defines: ["FIRSTLIB"] qbs.installPrefix: "/opt/the firstlib" Export { prefixMapping: [{prefix: "/somedir", replacement: "/otherdir"}] Depends { name: "BoringStaticLib" } Depends { name: "cpp" } Depends { name: "Qt.core"; required: false } Depends { name: "helper1" } Depends { name: "helper3" } property bool someCondition: qbs.hostOS.contains("windows") // hostOS for easier testing property bool someOtherCondition: someCondition Properties { condition: !someOtherCondition cpp.driverFlags: ["-pthread"] } cpp.defines: product.name cpp.includePaths: [FileInfo.joinPaths(product.qbs.installPrefix, "include")] Qt.core.mocName: "muck" } Group { fileTagsFilter: ["dynamiclibrary", "dynamiclibrary_import"] qbs.install: true qbs.installDir: "lib" } Group { name: "api_headers" files: ["firstlib.h"] qbs.install: true qbs.installDir: "include" } files: ["firstlib.cpp"] } DynamicLibrary { name: "TheSecondLib" version: "2.0" Depends { name: "Exporter.pkgconfig" } Exporter.pkgconfig.descriptionEntry: "The second lib" Exporter.pkgconfig.transformFunction: (function(product, moduleName, propertyName, value) { if (moduleName === "cpp" && propertyName === "includePaths") return value.filter(function(p) { return p !== product.sourceDirectory; }); return value; }) Exporter.pkgconfig.customVariables: ({config1: "a b", config2: "c"}) Depends { name: "cpp" } cpp.defines: ["SECONDLIB"] qbs.installPrefix: "" Depends { name: "TheFirstLib" } Export { Depends { name: "TheFirstLib" } Depends { name: "dummy" } Depends { name: "cpp" } cpp.includePaths: [ "/opt/thesecondlib/include", product.sourceDirectory, importingProduct.buildDirectory ] property string hurz: importingProduct.name cpp.defines: hurz.toUpperCase() Rule { property int n: 5 Artifact { filePath: "dummy" fileTags: ["d1", "d2"] cpp.warningsAreErrors: true } } } Group { fileTagsFilter: ["dynamiclibrary", "dynamiclibrary_import"] qbs.install: true qbs.installDir: "/opt/thesecondlib/lib" } Group { name: "api_headers" files: ["secondlib.h"] qbs.install: true qbs.installDir: "/opt/thesecondlib/include" } files: ["secondlib.cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/firstlib.cpp000066400000000000000000000000531347155106100266530ustar00rootroot00000000000000#include "firstlib.h" void firstLib() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/firstlib.h000066400000000000000000000002461347155106100263240ustar00rootroot00000000000000#include "../dllexport.h" #ifdef FIRSTLIB # define FIRSTLIB_EXPORT DLL_EXPORT #else # define FIRSTLIB_EXPORT DLL_IMPORT #endif FIRSTLIB_EXPORT void firstLib(); qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/000077500000000000000000000000001347155106100260035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper1/000077500000000000000000000000001347155106100273435ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper1/helper1.qbs000066400000000000000000000001611347155106100314100ustar00rootroot00000000000000Module { Depends { name: "cpp" } Depends { name: "helper2" } cpp.includePaths: "/somedir/include1" } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper2/000077500000000000000000000000001347155106100273445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper2/helper2.qbs000066400000000000000000000001211347155106100314060ustar00rootroot00000000000000Module { Depends { name: "cpp" } cpp.includePaths: "/somedir/include2" } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper3/000077500000000000000000000000001347155106100273455ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/modules/helper3/helper3.qbs000066400000000000000000000001211347155106100314100ustar00rootroot00000000000000Module { Depends { name: "cpp" } cpp.includePaths: "/somedir/include3" } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/secondlib.cpp000066400000000000000000000002031347155106100267740ustar00rootroot00000000000000#include "secondlib.h" #ifndef HAVE_INDUSTRIAL_STRENGTH_HAIR_DRYER # error I CANT LIVE WITHOUT IT! #endif void secondLib() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-pkgconfig/secondlib.h000066400000000000000000000002531347155106100264460ustar00rootroot00000000000000#include "../dllexport.h" #ifdef SECONDLIB # define SECONDLIB_EXPORT DLL_EXPORT #else # define SECONDLIB_EXPORT DLL_IMPORT #endif SECONDLIB_EXPORT void secondLib(); qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/000077500000000000000000000000001347155106100231515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/consumer.cpp000066400000000000000000000000551347155106100255100ustar00rootroot00000000000000void helper(); int main() { helper(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/consumer.qbs000066400000000000000000000007741347155106100255230ustar00rootroot00000000000000CppApplication { name: "consumer" qbsSearchPaths: "default/install-root/usr/qbs" property string outTag: "cpp" Depends { name: "MyLib" } Depends { name: "MyTool" } files: ["consumer.cpp"] cpp.defines: { var defs = []; if (MyLib.config.feature_x) defs.push("FEATURE_X"); if (MyLib.config.feature_y) defs.push("FEATURE_Y"); return defs; } Group { files: ["helper.cpp.in"] fileTags: ["cpp.in"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/exports-qbs-products.qbs000066400000000000000000000000001347155106100277760ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/exports-qbs.qbs000066400000000000000000000005511347155106100261500ustar00rootroot00000000000000import qbs.FileInfo Project { property string installPrefix: "/usr" qbsSearchPaths: sourceDirectory Product { name: "local" Export { property bool dummy Depends { name: "cpp" } cpp.includePaths: ["/somelocaldir/include"] } } references: ["consumer.qbs", "lib.qbs", "tool.qbs"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/helper.cpp.in000066400000000000000000000002611347155106100255400ustar00rootroot00000000000000#include #ifdef FEATURE_X #error "feature x must not be present!" #endif #ifndef FEATURE_Y #error "feature y is required!" #endif void helper() { MyLib::f(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/helper.js000066400000000000000000000000551347155106100247660ustar00rootroot00000000000000function toolInputs() { return ["cpp.in"]; } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/imports/000077500000000000000000000000001347155106100246465ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/imports/Helper2/000077500000000000000000000000001347155106100261475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/imports/Helper2/helper2.js000066400000000000000000000000261347155106100300440ustar00rootroot00000000000000var suffix = ".tool"; qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/lib.qbs000066400000000000000000000034701347155106100244320ustar00rootroot00000000000000import qbs.FileInfo DynamicLibrary { name: "MyLib" multiplexByQbsProperties: ["buildVariants"] aggregate: false qbs.buildVariants: ["debug", "release"] qbs.installPrefix: project.installPrefix Depends { name: "cpp" } Depends { name: "Exporter.qbs" } Exporter.qbs.fileName: name + "_" + qbs.buildVariant + ".qbs" Exporter.qbs.excludedDependencies: ["local"] Exporter.qbs.additionalContent: " condition: qbs.buildVariant === '" + qbs.buildVariant + "'" property string headersInstallDir: "include" cpp.defines: ["MYLIB_BUILD"] cpp.variantSuffix: qbs.buildVariant === "debug" ? "d" : "" Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } files: ["mylib.cpp"] property var config: ({feature_x: false, feature_y: true}) Group { name: "API headers" files: ["mylib.h"] qbs.install: true qbs.installDir: headersInstallDir } install: true installImportLib: true installDir: "lib" Group { fileTagsFilter: ["Exporter.qbs.module"] qbs.install: true qbs.installDir: "qbs/modules/MyLib" } Export { Depends { name: "cpp" } property string includeDir: product.sourceDirectory property var config: product.config Properties { condition: true cpp.includePaths: [includeDir] cpp.dynamicLibraries: [] } cpp.dynamicLibraries: ["nosuchlib"] Depends { name: "local" } local.dummy: true Properties { condition: true prefixMapping: [{ prefix: includeDir, replacement: FileInfo.joinPaths(qbs.installPrefix, product.headersInstallDir) }] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/mylib.cpp000066400000000000000000000000641347155106100247710ustar00rootroot00000000000000#include "mylib.h" namespace MyLib { void f() {} } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/mylib.h000066400000000000000000000006301347155106100244350ustar00rootroot00000000000000#if defined(_WIN32) || defined(WIN32) # define DLL_EXPORT __declspec(dllexport) # define DLL_IMPORT __declspec(dllimport) #else # define DLL_EXPORT __attribute__((visibility("default"))) # define DLL_IMPORT __attribute__((visibility("default"))) # endif #ifdef MYLIB_BUILD #define MYLIB_EXPORT DLL_EXPORT #else #define MYLIB_EXPORT DLL_IMPORT #endif namespace MyLib { MYLIB_EXPORT void f(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/tool.cpp000066400000000000000000000006031347155106100246310ustar00rootroot00000000000000#include #include int main(int argc, char *argv[]) { if (argc != 3) return EXIT_FAILURE; std::ifstream in(argv[1]); if (!in) return EXIT_FAILURE; std::ofstream out(argv[2]); if (!out) return EXIT_FAILURE; char ch; while (in.get(ch)) out.put(ch); return in.eof() && out ? EXIT_SUCCESS : EXIT_FAILURE; } qbs-src-1.13.1/tests/auto/blackbox/testdata/exports-qbs/tool.qbs000066400000000000000000000032471347155106100246430ustar00rootroot00000000000000import qbs.FileInfo import "helper.js" as Helper import Helper2 CppApplication { name: "MyTool" consoleApplication: true property stringList toolTags: ["MyTool.tool"] Depends { name: "Exporter.qbs" } Exporter.qbs.artifactTypes: ["installable", "blubb"] files: ["tool.cpp"] install: true qbs.installPrefix: project.installPrefix Group { files: ["helper.js"] qbs.install: true qbs.installDir: "qbs/modules/MyTool" } Group { files: ["imports/Helper2/helper2.js"] qbs.install: true qbs.installDir: "qbs/imports/Helper2" } Group { fileTagsFilter: ["application"] fileTags: toolTags } Group { fileTagsFilter: ["Exporter.qbs.module"] qbs.installDir: "qbs/modules/MyTool" } Export { property stringList toolTags: product.toolTags property stringList outTags: [importingProduct.outTag] property var helper2Obj: Helper2 Rule { inputs: Helper.toolInputs() explicitlyDependsOnFromDependencies: toolTags outputFileTags: parent.outTags outputArtifacts: [{ filePath: FileInfo.completeBaseName(input.fileName) + product.MyTool.helper2Obj.suffix, fileTags: product.MyTool.outTags }] prepare: { var cmd = new Command(explicitlyDependsOn["MyTool.tool"][0].filePath, [input.filePath, output.filePath]); cmd.description = input.fileName + " -> " + output.fileName; return [cmd]; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/external-libs/000077500000000000000000000000001347155106100234335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/external-libs/external-libs.qbs000066400000000000000000000016261347155106100267200ustar00rootroot00000000000000import qbs.TextFile Project { property string libDir: sourceDirectory + "/libs" StaticLibrary { name: "lib1" destinationDirectory: project.libDir Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } files: ["lib1.cpp"] } StaticLibrary { name: "lib2" destinationDirectory: project.libDir Depends { name: "cpp" } Depends { name: "lib1" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } files: ["lib2.cpp"] } CppApplication { Depends { name: "lib1"; cpp.link: false } Depends { name: "lib2"; cpp.link: false } files: ["main.cpp"] cpp.libraryPaths: [project.libDir] cpp.staticLibraries: ["lib1", "lib2", "lib1"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/external-libs/lib1.cpp000066400000000000000000000000251347155106100247630ustar00rootroot00000000000000void func_lib1() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/external-libs/lib2.cpp000066400000000000000000000000651347155106100247700ustar00rootroot00000000000000void func_lib1(); void func_lib2() { func_lib1(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/external-libs/main.cpp000066400000000000000000000000631347155106100250620ustar00rootroot00000000000000void func_lib2(); int main() { func_lib2(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/fallback-module-provider/000077500000000000000000000000001347155106100255345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/fallback-module-provider/fallback-module-provider.qbs000066400000000000000000000005011347155106100331110ustar00rootroot00000000000000CppApplication { name: "p" property bool fallbacksEnabled Depends { name: "pkgconfig"; required: false } Depends { name: "qbsmetatestmodule"; required: false; enableFallback: fallbacksEnabled } property bool dummy: { console.info("pkg-config present: " + pkgconfig.present); } files: "main.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata/fallback-module-provider/libdir/000077500000000000000000000000001347155106100270015ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/fallback-module-provider/libdir/qbsmetatestmodule.pc000066400000000000000000000001341347155106100330650ustar00rootroot00000000000000Name: qbsmetatestmodule Description: just a test Version: 0.0.1 Cflags: -DTHE_MAGIC_DEFINE qbs-src-1.13.1/tests/auto/blackbox/testdata/fallback-module-provider/main.cpp000066400000000000000000000001211347155106100271560ustar00rootroot00000000000000#ifndef THE_MAGIC_DEFINE #error "missing the magic define" #endif int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/fileDependencies/000077500000000000000000000000001347155106100241105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/fileDependencies/awesomelib/000077500000000000000000000000001347155106100262375ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/fileDependencies/awesomelib/awesome.h000066400000000000000000000025021347155106100300470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "magnificent.h" void doAwesomeStuff() { printf(magnificentMessage); } qbs-src-1.13.1/tests/auto/blackbox/testdata/fileDependencies/awesomelib/magnificent.h000066400000000000000000000025211347155106100306740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MAGNIFICENT_H #define MAGNIFICENT_H const char magnificentMessage[] = "Just. Wow."; #endif // MAGNIFICENT_H qbs-src-1.13.1/tests/auto/blackbox/testdata/fileDependencies/fileDependencies.qbs000066400000000000000000000005541347155106100300510ustar00rootroot00000000000000Project { Product { type: "application" consoleApplication: true name: "myapp" Depends { name: "cpp" } cpp.includePaths: ["awesomelib"] files: ["src/narf.h", "src/narf.cpp", "src/zort.cpp"] // Group { // fileTagsFilter: product.type // qbs.install: true // } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/fileDependencies/src/000077500000000000000000000000001347155106100246775ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/fileDependencies/src/narf.cpp000066400000000000000000000024331347155106100263330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include void doStuff() { doAwesomeStuff(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/fileDependencies/src/narf.h000066400000000000000000000023541347155106100260020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void doStuff(); qbs-src-1.13.1/tests/auto/blackbox/testdata/fileDependencies/src/zort.cpp000066400000000000000000000024331347155106100264030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "narf.h" int main() { doStuff(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/filetagsfilter-merging/000077500000000000000000000000001347155106100253145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/filetagsfilter-merging/MyApplication.qbs000066400000000000000000000003111347155106100305670ustar00rootroot00000000000000CppApplication { consoleApplication: true Group { fileTagsFilter: "application" qbs.install:true qbs.installPrefix: product.name qbs.installDir: "wrong" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/filetagsfilter-merging/filetagsfilter-merging.qbs000066400000000000000000000013141347155106100324540ustar00rootroot00000000000000import qbs.TextFile MyApplication { name: "myapp" type: base.concat("extra-output") files: "main.cpp" Group { fileTagsFilter: "application" qbs.installDir: "binDir" fileTags: "extra-input" } Rule { inputs: "extra-input" Artifact { filePath: input.baseName + ".txt" fileTags: "extra-output" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/filetagsfilter-merging/main.cpp000066400000000000000000000000161347155106100267410ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/find/000077500000000000000000000000001347155106100216025ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/find/find-cli.qbs000066400000000000000000000017711347155106100240040ustar00rootroot00000000000000import qbs.TextFile Product { Depends { name: "cli"; required: false } type: ["json"] Rule { multiplex: true Artifact { filePath: ["cli.json"] fileTags: ["json"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; if (product.moduleProperty("cli", "present")) tools["toolchainInstallPath"] = product.moduleProperty("cli", "toolchainInstallPath"); var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); tf.writeLine(JSON.stringify(tools, undefined, 4)); } finally { if (tf) tf.close(); } }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/generated-artifact-as-input-to-dynamic-rule/000077500000000000000000000000001347155106100311605ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/generated-artifact-as-input-to-dynamic-rule/input.txt000066400000000000000000000000101347155106100330470ustar00rootroot00000000000000old.txt qbs-src-1.13.1/tests/auto/blackbox/testdata/generated-artifact-as-input-to-dynamic-rule/p.qbs000066400000000000000000000030051347155106100321240ustar00rootroot00000000000000import qbs.File import qbs.TextFile Product { type: ["mytype.final"] Group { files: ["input.txt"] fileTags: ["mytype.in"] } Rule { inputs: ["mytype.in"] Artifact { filePath: "output.txt" fileTags: ["mytype.out"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return [cmd]; } } Rule { inputs: ["mytype.out"] outputFileTags: ["mytype.final", "dummy"] outputArtifacts: { var file; var inFile = new TextFile(input.filePath, TextFile.ReadOnly); try { file = inFile.readLine(); if (!file) throw "no file name found"; } finally { inFile.close(); } return [ { filePath: file, fileTags: ["mytype.final"] }, { filePath: "dummy", fileTags: ["dummy"], alwaysUpdated: false } ]; } prepare: { var cmd = new JavaScriptCommand(); var output = outputs["mytype.final"][0]; cmd.description = "generating " + output.fileName; cmd.outputFilePath = output.filePath; cmd.sourceCode = function() { File.copy(input.filePath, outputFilePath); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/generator/000077500000000000000000000000001347155106100226505ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/generator/generator.qbs000066400000000000000000000023021347155106100253420ustar00rootroot00000000000000import qbs.TextFile CppApplication { name: "app" files: "main.cpp" Group { files: "input.txt" fileTags: "generator.in" } Rule { inputs: ["generator.in"] Artifact { filePath: "file1.cpp"; fileTags: ["cpp", "file1"]; alwaysUpdated: false } Artifact { filePath: "file2.cpp"; fileTags: ["cpp", "file2"]; alwaysUpdated: false } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "potentially generating files"; cmd.sourceCode = function() { var f = new TextFile(input.filePath, TextFile.ReadOnly); var content = f.readAll(); f.close(); if (content.contains("file1")) { f = new TextFile(outputs.file1[0].filePath, TextFile.WriteOnly); f.writeLine("void f1() {}"); f.close(); } if (content.contains("file2")) { f = new TextFile(outputs.file2[0].filePath, TextFile.WriteOnly); f.writeLine("void f2() {}"); f.close(); } }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/generator/input.both.txt000066400000000000000000000000241347155106100254770ustar00rootroot00000000000000file1.cpp file2.cpp qbs-src-1.13.1/tests/auto/blackbox/testdata/generator/input.file1.txt000066400000000000000000000000121347155106100255400ustar00rootroot00000000000000file1.cpp qbs-src-1.13.1/tests/auto/blackbox/testdata/generator/input.file2.txt000066400000000000000000000000121347155106100255410ustar00rootroot00000000000000file2.cpp qbs-src-1.13.1/tests/auto/blackbox/testdata/generator/input.none.txt000066400000000000000000000000001347155106100254740ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/generator/main.cpp000066400000000000000000000000721347155106100242770ustar00rootroot00000000000000void f1(); void f2(); int main() { f1(); f2(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/group-condition-change/000077500000000000000000000000001347155106100252255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/group-condition-change/group-condition-change.qbs000066400000000000000000000011311347155106100322730ustar00rootroot00000000000000Project { property bool kaputt: true Product { type: ["kaputt"] Group { name: "kaputt" condition: project.kaputt files: "input_kaputt.txt" fileTags: "input.kaputt" } Rule { inputs: "input.kaputt" Artifact { filePath: "output.kaputt" fileTags: "kaputt" } prepare: { var cmd = new Command("jibbetnich", [output.filePath]); cmd.silent = true; return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/group-condition-change/input_kaputt.txt000066400000000000000000000000001347155106100305030ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/000077500000000000000000000000001347155106100242535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/groups-in-modules.qbs000066400000000000000000000005611347155106100303550ustar00rootroot00000000000000Project { Product { Depends { name: "dep" } Depends { name: "helper" } Depends { name: "helper3" required: false } type: ["diamond"] files: [ "rock.coal" ] } Product { name: "dep" Export { Depends { name: "helper4" } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/000077500000000000000000000000001347155106100257235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/000077500000000000000000000000001347155106100272025ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/chunk.coal000066400000000000000000000000061347155106100311460ustar00rootroot00000000000000chunk qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/diamondc.c000066400000000000000000000032711347155106100311270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main(int argc, char *argv[]) { if (argc < 3) { fprintf(stderr, "usage: diamondc input.coal output.diamond"); return 1; } FILE *in = fopen(argv[1], "r"); if (in) { fclose(in); } else { return 1; } FILE *out = fopen(argv[2], "w"); if (out) { fprintf(out, "diamond\n"); fclose(out); } else { return 1; } return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/helper.qbs000066400000000000000000000020651347155106100311730ustar00rootroot00000000000000import qbs.FileInfo Module { Depends { name: "cpp" } Depends { name: "helper2" } additionalProductTypes: ["diamond"] Group { name: "Helper Sources" files: ["diamondc.c"] } Group { name: "Additional Chunk" prefix: path + "/" files: ["chunk.coal"] } Group { name: "some other file from helper" prefix: project.sourceDirectory + '/' files: ["someotherfile2.txt"] } FileTagger { patterns: ["*.coal"] fileTags: ["coal"] } Rule { inputs: ["coal"] explicitlyDependsOn: ["application"] Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, input.baseName + ".diamond") fileTags: ["diamond"] } prepare: { var cmd = new Command(FileInfo.joinPaths(product.buildDirectory, product.targetName), [input.filePath, output.filePath]); cmd.description = "compile " + input.fileName + " => " + output.fileName; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper2/000077500000000000000000000000001347155106100272645ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper2/helper2.c000066400000000000000000000023551347155106100307760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void helper2() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper2/helper2.qbs000066400000000000000000000004121347155106100313310ustar00rootroot00000000000000Module { Depends { name: "cpp" } Group { name: "Helper2 Sources" files: ["helper2.c"] } Group { name: "some other file from helper2" prefix: product.sourceDirectory + '/' files: ["someotherfile.txt"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper3/000077500000000000000000000000001347155106100272655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper3/helper3.c000066400000000000000000000023551347155106100310000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void helper3() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper3/helper3.qbs000066400000000000000000000002311347155106100313320ustar00rootroot00000000000000Module { Depends { name: "cpp" } Group { name: "Helper3 Sources" files: ["helper3.c"] } validate: { throw "Nope."; } } qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper4/000077500000000000000000000000001347155106100272665ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper4/helper4.c000066400000000000000000000023551347155106100310020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void helper4() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper4/helper4.qbs000066400000000000000000000002271347155106100313410ustar00rootroot00000000000000Module { Depends { name: "cpp" } Depends { name: "helper5" } Group { name: "Helper4 Sources" files: ["helper4.c"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper5/000077500000000000000000000000001347155106100272675ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper5/helper5.c000066400000000000000000000024341347155106100310020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void helper5() { #ifndef COMPILE_FIX nothatcantwork #endif } qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper5/helper5.qbs000066400000000000000000000003401347155106100313370ustar00rootroot00000000000000Module { Depends { name: "cpp" } Depends { name: "helper6" required: false } Group { name: "Helper5 Sources" files: ["helper5.c"] cpp.defines: ["COMPILE_FIX"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper6/000077500000000000000000000000001347155106100272705ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper6/helper6.c000066400000000000000000000023551347155106100310060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void helper6() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/modules/helper6/helper6.qbs000066400000000000000000000002341347155106100313430ustar00rootroot00000000000000Module { Depends { name: "cpp" } Group { name: "Helper6 Sources" files: ["helper6.c"] } validate: { throw "Go away."; } } qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/rock.coal000066400000000000000000000000051347155106100260440ustar00rootroot00000000000000coal qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/someotherfile.txt000066400000000000000000000000001347155106100276470ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/groups-in-modules/someotherfile2.txt000066400000000000000000000000001347155106100277310ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/ico/000077500000000000000000000000001347155106100214345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/ico/dmg.iconset/000077500000000000000000000000001347155106100236465ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/ico/dmg.iconset/icon_128x128.png000066400000000000000000000122101347155106100263150ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËOIDATxÚí] |WÚ¿D"ŠR ÚŽF‹êbf|­òÍ7Ó–)ÃÐiƒh1šªÖZŒù™©©eø‰µ–Qû6öÝXcO¬„„ˆXƒ$d±ïÁùÎÿÍsÒãí}ßÜå½7÷ÆyüžŸäÞ÷ž÷ÍyþÏsžíœk³)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)R¤H‘"EŠ)Rä ³ÃÅ;ÌöæÏ¯À9sIÎÁÄ¥;ÅbÞ‚h>}BËKp~†sÎ/p®Æù%ÎÕ;Ř·9ÿŒsišWŸ>ÐZÞpÍß¿{è#¦Ø}æóY•¬B€/@æ¾´ýíM§+ÁY €_r~––Õ⾽𫿽¬ÉL%4ËðçŠ4Ï>côÂÿþ,%0à7œ«Ð2PÂðSá/UÂ÷ Þ&‡º´/@ ßûhDAòŠ)á?]hÌùçŠ+á+(á+(á+(á+x#½«„ÿ”@?RÕU’çé@ežž/ŒÜþgǾfߥNg²¶±C7Øù»iìòý,vãáMv5÷:K¿w‰%ß>Év_f 2V°oN`-ªàíÙ[(8ýâ|–z÷"s…î=ºÏ¢®îg=’ÿ¡`ö—¤ÄëÞø#Gû7»‘{“YE{¯Å°„Ï]~3zP‚Ì?  <ùÇ5köäD2OÐÕÜkì«ã³ïúø©@i*@4ôÔ†‰Üye/ó$Ý~x›…%õ±M8h‹: (@4òÔ6õâ<æ ºx/ƒ5oošÆµ-Ò`ºicOüQŸ$~Ŷ{¦ý˜ÿC0áü öyR_öqB{?.Dæ'G»±þ)CتËXæƒìA°äÒËðA|;wys¶ùºêÎYMèŽú3Ó²‡ŽwÿÑ @V ™“ÖD@Çm¾`¹&ÂJº•Âþÿ‰Óã=3V³F´0c¥%påÙ$ž‘¶Àprïòe!4ñK—Ç^›¹Ùpl$’õàÍÈÛ §"€“wÎN.èÎØí»š.=í$‰œ¥›oiIÁz«ãÌRóÔàÏG>34Óx½ó±ÞnßcOѼôen  úðHg#þöô(É;w÷‚%÷qv‚á=boñ8Zé¤`ijÓNܺ¬Í–Ü>„!dô4Zî `Ä[svN4תûå°Ìè8«Éj'±H åöiÉë–<À²ûÄßH4¼¾>`5Y'(R¸óè®áÄ}d¡÷l–h~v¼[a`«ÃØâÚ©0ÐùÊ_[ÓZ¾•U¶ùéË ï5ñüLU. À;6¢ì9–NÚä s ï…¦€B’4F”Æ+vVNÚÉŒè?Ü:(ä1¢3wR-´‘ç&Þkùåu …xßF”|û”¥“†Â­ÏÚªPèzü¯†“ŠðÐÊIvæ;·N @Ç£==žþ±Ét²á½Vò&€B@›„.†“Š>+'müyc'pñ¥Õ …€?îh^±tÒ¾¿0שР€WAm 'Bè÷³ê^‹2V=­‰ ùdÖbßI£ÂˆÜÙÈáL*B€|J+6ô–jÞ¼ùsÓ§Oç€~?G‹4î0êþFÔ7ePQ@1;ÛùĆžò=zô¨¿zõê-;w~ÑoÊÁCÐLGù½tÃû %½ˆ@¯õ8¥µÊ AƒÚ¯]»6‹kÿ€Á§07}‰áÄ.½ô_ËœM£¶3G‹Nfd¥¯â&ž8›¹råÊ5§M›6uÆ ¹öŸâ¿ã„Ñç| ÿ:3Îpbß}ZûüäÉ“£¹ŒÞ'í¯ê®ö*äbjö+xû6öøÁñ{ðø®$W{GȚр“à åtϦ±mÙçû¾f#vŽcK#–?!ôíÛ·³Ã‡kÞ¼=¡ƒ¯^½ÊV­ZÅx¦O»N>a ÆjÙ²å߸ŒÞÂaÞVh¿OÀŒõǽÁ‘¼m’·‡ÙöÖ¡NÆtb_ïù›¸m [»qíæ=**J[³áÈ]»vMc#áÃÛ_´hÌ»æèé…/œ¿9sæ$Q’èU«´ßçàlÿŸÖš±šy*” å¦ý›¨alö–yOh9{Bð˜xxî0ï.\ЄoÙ è—ü´.b|„yò2‹ñ<ËСC—q¹ü–JÄ©9IJoõ[€Çò†{»Ž&_˜Í£P‡»»‡ä{ñˆÓav!øÔÔT-Q´ à=¤uy¡GWŒ!¥,/ß«Y³f{”‡é0ïgm©´_ÊÙ<ð•ò~—ZÉxšVxö0ùHµBX€Ù2 [ý2 @€hβx²5‘­Š=@ <¤v¯h*ú ä[™Ú½­Ôþ§mb>Ï/Á" ƒ¹ ZqcbbØÌ™3µl “lU̱k×.Mû›5kÖG*ú”·"í«ÀyúÖÙšð¡™(»z+ _ rÁ0÷ðôaY˜dP™@<oã²hbeÑG‡VDwÏ_÷fz+ _ rñúš5kØüùó53.'Ë ˆBð|­[·`uÑÇl{±ÂŒ†EÂñCÍ Ð[gA\·xñb-̃ðÅx2° òx¶Ù³g'Ú)úyBûÄ·†!Çüë¢*|4]"Þ‡ãS AÙ³Î:ƒ&ãêÇ”Ç6^‡UÂÚò —ÃÛRѧ”•‰#”¢8³6íLiɹ-çO9w$îä‡üÎaœ»wêÔi!4 !– Ù 8ë ÂɃ³Ç ã ãÊãÛƒ¸'ºƒÈó‘´ÿy«Ó¾FßZŽ–ºÔpؘv©¼Kሿñû4™-8‡Ž7n& YcuQâΚæñ#€1ev¸I"žõ{À›=¿¢µ¿†ÕE3Gðºé ô¯€Æz~Æ(›¾N)TTÑþÄ×苘hÄç²\qѺÅ4´uÞ> ÙQ@ yÀ _OÀõÊÚoÏ ˆ]¨å¨èP™¤*™#â(ªAùôJ•*µ\¿~ý#N½eÀÌÄÏhÝâ;r5ó0É,ÀP Ðÿáó1oT«V-”,ou+>€A -¥È1,ã§\–’'h›®ÝªU«0L4´MÇÞ2`æ âuäôQÔð‘DB™XfgëQƒÀsõêÕk²´Í«²'ã~GO›*Aè§\RZÒjõîÝ{ &ûëd8º àzäôáé£ HfA°3€@ÉÏÄCôiN{ü«y2ëç Šé@áo\‚&¦ô¾Ùò;‘ý“µÑ‘eÝ;pöD@°+€]¾0ýuëÖ “¶x‹ŠŸWµ¿(Q1]d PgäÈ‘³0á·d“\Ð2€n „y°Ø¥#XÁ@P´Ã÷qÇŽéÜûªtÀCÉÂÒþ¢8³¯Ž=z1€M˜b{Ë€ ˜{$x ­!8Á2ô€Á Þß¼y³¦ýÇ_ËŸ­™þ—tI¥ý ˜PO)`ö¬xùòåZj€§dvøÛ»ðS§Nã]¾­©ÚW“Lieú­&öµQ£F-ÁÄc¿½ìŒé­^C1ž>„ë ¸ T ñ |üT–¶§D[m ³Ë*ÓïÀ=rÙ @H¼£­Ï>CfWŸ…Ç¿téÒÌ:uê|A!ß«”¯(/ÅüJû=€z‹ ìµ×‡dÖy8{0щÌ ®ÿ ³Ï—•œúõë÷ Ôúëºu_™~O`ðàÁÓD@—£ÍG’ù}€Af#0\/>îOd4hР'¥zߤl_Eµî{uû÷ï?Rde@@ØŽ !¬ƒ`A°+€À}ÄaN<’8]«V­.’ðAÏ%Ÿª„ï! P»k×®‡0P €àóê›æí£” Ë ³ g ­ÇaÆ Û„S¿(Ö“Šl?SÂ÷^kìË-Z´[½óÂÖ¾áCh`$}›Bƒ`,#Bðt|k:¿çP~ïV¶¼þŠ×Éì Í—=~ 8M2<ì*Th‚Ì›’<¾Ì¿ã}„u²ÐÁü€‡œ¾}ûÎ BeﶼΞº”㯨„ï]ˆ3õ1ù y¿^¦,,Tâ @´baiÀI‚!\0~†÷q­|R§tbçCžØIàG“¸àßÿÑ–·—¯>¬…zÈá RÂ÷‰&Ñëø/M@»5vÛê…è,sM¿ÂÏê‹éÖ­Û,îà!´ûØ–WÑC|ÿÒz˜|”vËI¡ž¾­€èu¬HéV´Z}À9¤^½z½xëu8ÿª•9ëÆŒ³‡Ã~€ÂÏm8Ês'8'ãw¼>dÈM}úôYضmÛ±¼q§tAÓ?²åµ›Á»G×ѯIð5tÈäë“Kÿ܃H“,ƒ‹UIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata/ico/dmg.iconset/icon_16x16.png000066400000000000000000000007471347155106100261610ustar00rootroot00000000000000‰PNG  IHDR(-SêPLTEÿÿÿ¿¿¿®®®¶¶¶DÌUcÅn³³³µµµ´´´ºººµµµºÁ»¹¹¹ÅÅŹ¹¹AÍRAÍRtÇ~ÊÊÊÁÁÁÄÄÄAÍRBÍSLÊ\NÊ]OÑ_PÊ_PÑ`\Ôj]ÔlcÈocÖqdÖrkØx{܇|ÜˆŠÆ‘à˜¥Ê©©Ì®´Àµ½É¿ÀÓÃÆÆÆÇÇÇÈÈÈÊÊÊÌÌÌÌÓÌÍÍÍÎÏÎÏÏÏÏòÔÓó×ÕÕÕÕôØÖÖÖÖ×ÖררõÛØõÜÚÚÚÛöÞÜÜÜÜÝÜÜößÝÝÝÝöàßßßß÷âà÷ãáááâââãããèèèìúîÿÿÿ£\­tRNS,£¶O´ªýâ 3é xE2• @H~¹©_\ŒíÀ±ƒbÄöñ1×í·ü¥­²m´•ßÞ^ó‘ïÁV ÀQÿX [úq;¾>×k«¿à>¹+˜³Ë°éÐV™vkä+¸}A  õü"ÆÕÿ±â••zíW¼.öÝÓu¾¹º‹¯ þ‚{)€Ôò™ŠÚC /Œ BɸV¸{Žîõ|­klHH,À+îXx?€ZÂ7öŠÃÇ‹6¿>ŸÔëÅç!²ïm—¿èh¸°%€ZÎÛ³ØóÜscßÀ¹,£wLò‘<@ ¤ŽHËy ®­Ü¿&eÍ,æ­>°ÎÓuï“ÁÎx—{ÒŸ @Êøé†>žÞ—V¾“ÒkmÕû ¿öDcë¡íÖlD›†‡;tÂëZÚŽ@HþöB©îeGςׂ!Ô)øAb‚¢ €çè?‚x^Ð}Cï@§/7Ëš€t€ûy‚@ðžW÷‚cÇù&z}×¢‡=Ç0"9îw`0+€à‰¶ ÷ôÐa¶¿Ÿîã·ý«<Ýú‚.Í—´¦P¼qþ^oþ?æóûé>pˆ Û66ðpÏN¡øxÐç>µÿ.{ÖW÷Òî·ÿyº%ìdüŽ&‹ÿK DÏf‹[yî­OöÀÍpDK­—8ÀAÙµˆLB1  j¢qÇ –Ésüüx?8k0>´ß‘ʳ(”ðzÚrýx?ßɓм™ €ßK‰)>ýÃÀ½åÿ{ùò~úÈ3 ½§Yø¼›àÓ? ÎÔóÙíÏŽÆ®žî§ÿ–a€£ÇžPì÷yŸþa¼–Ðúµð-Â^€±á© æÄt92ŒàÓ?Œ×`¿±DU_¢R<”V€)¼^€´™ŸÏ0ôLA¦P2J;ö´«úùaórz1Úo)€Œô{Áò?WùúaÛvx‡§ Z<üm  0Ðnù+iÑtr1Ц”Å5(€À¦áxÁÜ= }ý°aDYªªé(€À€×QZ3vÍöõÆãÀ5€@HxkM—”æÌýÖÞÜbÉc @æÀ»k»yzX'ü>Å×Û¬Ýó<ÝW<æêQ(Ô¿{ÁHŸ6ÙœúÇLO÷ë!¦ @  ëúÏ==¬C·ñõÃöíΩžî«Õ²ö @æÀ‡ëzzzXGlçë‡ 1 î(€0|omwOëØ“}ý°Mßõ³§ûºoÉã @æ€×Ã@±ÅöóÃ6GÖ)¤j°&€踺³§‡õÇ]3}ý°-Ú»”…@ @8¾ºê=O+Òl~~Ø~•ó ½ þ‚û(€ÌLõñ‚{—øúaózZð¿ç7£P2GZ/{ÎÓÊR[??l^§Åã¨p  0€±^^€f??l;ÿõ=a2çP2J0IÖ vÞéë‡íбèÇœm=´^K#À‰uæÞéy"­_‡UÂ÷6äd% øËàß4Rœèõ\ÀÛ´H«£Îâ•Ù ¤DL£Ï­Þû”fÍšyê©§ŠPâ<<ãþ_žH«±à~ÿž<p3üü’…[µjU~РAÕ×'b¸G: Òqõ‡žîç›­#(Á'ÃÇ{’<ãå—_®;|øðu¯¿þz-ùu € ‡mëéE'¡ïç‹Mý<ÝϧûP‚!N«þ)j•/*ù÷.]º<=räȃÙÙÙ_˯‹SB¾ Ú:Ê—÷3fÇ·žîç«Þ¥ø_B­úÅÊ—/_á‹/¾è;jÔ(!`ßí·ß~™üþé€|Ùã`Pœ)èÇûÁ ?©šDH˜8­úy•a#À÷÷FÕþæ›oÃøÁ®]»v’ß/-yšdA €kÔ¼µ§6^iÄ“HMî?v ê{9.ÿ*@ @B ¤¯/YFúùOJ¯müC† Y_ªT©ÊòßÎTPˆÂhpÔ—4\ØÒW÷âõ\ÀM‡¶Æí¼âƹ(‘­úùíUÿÊ+¯¬&·üCl÷پ}û'Õg•RP˜‚ËþüÍÓC‹sÒaÌùÌÝsãv Gd‘TªúÒHÜVý‚jÕÿÇsÏ=÷àСC·šÆß·oß¹òß/•,«àtîÂpÔö‰žÚÁ> bT™·€æÈ”Vá Ö €\aV}¼¦” ô]Ô£G^ÒØ™Æ/y¼iӦȟ»HòõYt5ÈoMAk¬÷to®î’ÒF$ ÑÂ(¡Wý³{ì±»daÏ÷سgÏïäÏ]!yv ’%”»À,@(6Yü_Ͼ+JoƒìÿÇëD X[‘ã•…ä×@§áG^¿T™2e*uëÖí3™Ú;êfü#FŒ8R§Næò竪Ï9 ©Aåÿ³0Ñ çŸoüÚ×ÿ™¼/Øyø_”V?¹üåL€"Ê(ó*ƒÏm¬ú…•ñ–‘¾~K¹ê¯v3|›;w%¾¦äÅ’çjÀ‚ªPˆЍ…÷‚ rÅ»anÔg2ÖØà± ¾§-Ù÷«§ëè´æãL€Ê0ó(!°·û0Ú³n»í¶k¾üòË1á ”)À•+W¾[¾îrÉóá.¨ ÀS5¡¡„"*á¼Ñ÷T^û‹+ßò|íñªŒu$y¼z|.ÔÊ\T{>e Õ÷JžuÖY|ðÁä–~$ÆvìØq€|íµ’U$Ë!E¨EÿOQ» @(Þ2ïnqÀc=vx}ªf¬Ø¿ÚÓuã~ã}Ç©Ié8f-P[­Î¶qžª¶úET°®¬Ìß?Év_çàÁƒ÷”.]º‘ þUTÁ?sõç<€HøÝÎižWÒÛǧ䚳7ñ|͉8à¤û†Þž®Õˆ÷Ä1éC¸VEçK+-®ì£ÌÃ?\ÿ믿žáÛ|á…zË÷¸NåþË©ê?sõ§D—<öØøD>üɼÞwdú†ã.{6î×ôÌo¯z¾hrsŠvRI€ëµrôå6lX÷óÏ?ê’ÓcÆŒ±bõßU¬X±†ò½®”¼0ÄꟋQŽê5`¯b½6 Hʸ0´#Çbüó÷.NÈuÝáq΢õ7Z É#KŸ±Î+Ä“vË_¯ÈxæàH7ˆ-ZŸ³· ñmg¦!7I¢;ï’ºuëÞòÙgŸ —F|ÔÍðçÌ™#f̘rõ—.ÃJX°ú—×jÿ «? Rv[ÿ¥ˆXÉÐd”ˆë»sáƒòøïŸb¾F”߯’Ç¿÷H¨ÑE5”½úýe€ï›áÏ›7OlÙ²ELŸ>¹}ëûÓ¦M;i'0pàÀß‹-zGˆÕß,2¢DBż–³ê@M!épÛüæ¾}¦þ3«…x÷Ýw' 6ì@(Ãß¾}»Ø¶m›˜2eŠÁ@KæÎ+–-[vÒkÚµk×SÚÕ šïÿ÷T®þi#± qŸ¸»JôÙ<ÈÚÖF:LÓ}QÓkS«Ç?–í¾H¢v'6Û¯x=ép÷¢G|÷5þéAñηňQ#·ðãÆ ,;vì»wï›6mãÇ2 hýû/¿ü"vîÜ)¦NzÂëdßÿŽSO=5ÒÕŸçDŸZk$Ví_›°‡õO¹Ã@Åܼ=‹¬N¼)2û0s÷ËuÀ÷÷Ý›°ÏWÂ(ŒòÚà~*%¾gÆŇ»‰‘£F:>Œ|Ñ¢Eâ÷ß· \³fÝ}¢W¯^bìØ±bÕªU–ñCÌ×·mÛ¶»æûûbõO+ûµCÜV]¿[ÿdgï]T8 P˜Êç¥îÏwŠ6SŸ½Æõq ÚMœ8Q,]ºTüñÇ>øë¯¿ 9¿OÈÞ~1a±~ýzËøAìô÷0`À¶ üG­þfÞ?¥§ ¥•Xñ†>icüëlŒË៑òÖyM’º €Û‘Šg¤áÌûÅKS:ŠAc»þwß}'~ûí7±k×® _Ã÷—ѧOË÷ߺuë_ÆDÃðý?S«ÿ%!Vÿ\€÷Øû Hm¦ÂG~ö·×’¶‹Jf9v9ÄÃÓžOü4dš¾ûêÕ«O0z›ØüðÃâÃ?ýúõ³R~ˆØÆ ÐßOw.\øcõ·;þR~Ö`Z âßîœXã_p“Õß߇ëz&EPè†+øöoL~W =ÄÕèÑÿùçŸ-ßÝÉðADûGÌÒyV¤«½nüàO?ýtÂ{wèСw‘ÿ\€üñûÊ(~а`ïñŸ÷ú¢ÂrïÑ} ½×î ªÂĿÔ×Dß±Ù!W{øî‹/¶ŒÛÍðíH¿ôã-ãGÐ1ÓðA¸ ½æÿŒ3Îhä×Õ?­Àæë«?»ì „ñ#íè§â˜ú î³…¼` ‡¯6}·k½mV3ñÌ/‹/Ƕ~»“ïDDúè{ÿý÷­×®\¹ÒÑøAˆ‰þ9ò¤Ÿ~~^ý3B¬‡cAó”ºD‹w¼%Žåôâ÷×~"«gzJw9~ÄJ•¢q 5(Æ9芌I fÝ+žùþeÑsü—®é;=‡m{¨m¾É%K–Xþ¾œ×o½^ô;qÒ¤I}žÜ)ì“mÂw9äý}³úgŒèiÂi»fù6U¸çÈ^kÕõûï±ñ¢‡¬©·×t=7öµjûAT=bƒ­=êÿŸ’EQ(`Šç®zOýð‚è1þó°Fíø?þh­Úf/gΜ)Þ~ûm!‡yŠÉ“'[¥¾¡Œß þÉ~ÿaÒ†nôóêŸq`óÞ%mÄðmã¬ÑZ~C¼NüMÞ0»¡¸wzkñêwo‹>ã²#j·…ÁbõçÛ»Eú±Ú¿ñÆBN÷±ïÊøAôh³þWªTé^iCW9TýùfõÏXÐ…(FÁd›å®ô<?Þx*Ígí…ííø¹‰h5õñþ¤®bpˆè}¬[|“H類_žÚƒYý®‘~“›7o>!ø'gýM–öSG û,ï×Õ?ãÀäMó‹VËÚ[i0´«~ÿÇ ñ‹œz³ãðNqèØáµúð1âãµÐòŠí|,íµ¸–ŒùÝϾCÜõÓCâÙï_‰hk¯WéÍž=ÛÊÛGÐ ElñQ؃•_Öí[;ˆp†osþüù'Ìù¿þúëÛHû¹Z²†‡ø¡æŸÇ1dèb«/Su¡NÆAŽ;ôŽc„ܼùç»Ä#²0çÉÅ7cE/m§–:é§ŒšèËÕŸ`>´´8vüXL€’Õ”ÈJ<ÔÝ>¾WÄ«<¶ö³fÍË—/·zíM?Ü€XEîÃ;?ÝÚY ~€Ï2Jô¶ßÞ½{/—vs‹š"TAôá4ë)²mtL®@<KŠ‹4ûn«æ=õƒÇDÀC=¢èX7lØ`ãl:b¬€×¡ÙG¦ê„<½Ç2bTñ¹}®› àZõûxðÁßQ“„/V3KŠøÊø)IšVK‡ªýP²PhÖ=¢Ý/‰" à!bÄ =äÏa|Xé‘nà €›DbüxLíyíµ×ħŸ~jí4ìÏÖ?פ“àµö=õïßsîܹëi}”Vçúvõ§$‰WwŽi0zÇ$ÿ­ô?ßm¥êB Ñ0ëîQ\ƒ>zlµaô¶áÛ´ÀMbuðy¨é‡ñ#âè½þ™&C ²zêïé§ŸþT¯¬ŽùÖOÊ›ìYŸq®œËäâ¶Ë_Jýæ9 åöþIñÑÄý·ß~kùÙˆª#W£±i €.áÀM"l×1¹Æ°ã nN 0@kúÙ-›~h§üê«>?ÿ(I&Jb?Ópºs§,zÿâ”7Dÿ1ß„Ý򣄮Ü]|LF"zן<äóÐyçw´—ªå÷l¿µüRüRü"‹ˆ6ÚÓtà¦I8Š«éŒGÂúöðéÃêŠíµM[t'n"K0ÿEÌAÚi¥ùtÄ5éŸïtáßÓG~É‚‰ªì×lúñýêOØ©ÀÀ¬Ýó:»Û÷‘Y˜|‹/0ú+)ÚcÁpà&ѸÑñ30xäø»wïnî %DÑ‚1ïÿxÍš5[©²_ß¶üR|F¯Çq£YiÂïSâ~:pÙwZt†»ÌÂÿþûïÅÂ… ­-> ߦ-n"à5h Þ}o½õ–5È©FóóM†ó!,FÙïMFÙ¯/›~(>â]‹ŽêXsü,š$â$Þ–ÓÙcû;>V{¤í`ø¨—·©¸‰@¢Ü\Ç!C¬`ê€ÿ¯¾› E*fÙoãÆ_RÙ/ÀGDÇ`8ì:²Û:¸4Ò“‰¢’ûæä÷\W|luaø6ÀM¢q¼MÀÐYŒcU÷¡¥ƪ_‡y-^‚hÿŽd»ðj—²__6ýP|7¹øN±öÀGÃßrh›øHž$|K‚ŽÝ®'+÷¾ßÛÑÇÇ¡HáÙthܯÁÀhܬô²ßÚöã>æsºŽXï©þ´nݺsÐÊ~)>#NûÕ¹y¨ý¯“ÀÁ Èé÷×ÏuP&ôpà&‰rÜj@øøÈñ¿÷Þ{Vá®M¿“^‰ú9 ¼=he¿ròÎÅ¢½KE‡Þù‡É¹ýÆ8Éø%G:ÆoÓI¢q¼#uðïØ’£™ƒ;a úu8]WA€{¡ÿ¾^|ñÅ>Ò>®“¬¤²_ €O1IJ Âì»ÏÀC.8Nâ ŒGM~«=òûHóáÜ)‚ ·üÊ!ûå´ßÆZÙïÙjõLêÃI>˜ôÑIÆÓp°òÛà&‰r¼Ôàsá‹£²C;‘ž4¯Å¤WAÀuã÷£ÿÎäçŽV³þWöKÈP¶ýáy×m$``Ï—Å'“ñœ-¨¯þõêÕ{F5ý8•ývõw€JjÑzº¬øÓ‡y`V5øµ‘ @*‚¨éGzi¾Z_ë׿vñôBèÂ)w ó²rNú©žYÿñ€ò€àq˜9¿.n"ªšló1´Ónè»â&RшA4‚€¯õc¾Àúõëw±úªì7(¬RÈq^Ec fðO¯÷Gä+i¤ì` þ?júáëãx.Ì´cúõ™L„  2R7~9Pd‰Öò{¾ZýÏH—Õ_€Üê† «Ê&(Ýe4¨àc½ô‡þ, Ê7HF0Ðü"ý]ºtù«¡G¿6“‰ûÞð<꾃 °ú_£­þ%ÓiõÏÒ.Þ€BÊ¿A{c%Uô€èç$ÑÑT²™d Å{É”ò>I”¦¶”|X²M‡&™Í>‘@²kðØ ¸«¿}hˆÉd ‚Þî«EþÓzõ7 ¯jh(ªÎUÊw¹ò0÷¼® ˆàs+™þKÇPý[ò6ÉúJ [ÊŠ¹ úöõò7HF0Ð|®=ºë«¯¾²Î°¯Ñ¼Îd\$}تþjÕªõ˜æû;µüæúêïȯ¹g©XÀ…ªóé2Õ‰Fˆ«Ôî€L kª‡óÕ—ŽúôÛ*Uªô¶®æö?”Ä#€šþììlËøéGÔ]¿F“¡Ä ‚€ÿÖb£æÿ[µÐ9­þ-û4PP튫/«ÒU±²«Iã%ª!¥šÚ¡An’§Ó¾oæþ‘þs2¨TÔ`z&õ"Ò:!¸>“É3ð'ûý\|ñÅ÷kUç¤ó꯻z6ÀbÊ8K5?œ£Áæ¹dJXNÕj\ R䨯—†5T˜ÑDã&ñFê࿈ô£¤‘~¤Ú°í†{bÓIb„Pbâõ¨4¦ýd«•]óoæýÓjõwÚäÕD °‚Ó•WyÐJÉä³”jCµE¹œÚ•Õ–yôEzé¯nX‰vÜ‚ø>R{(ëE]?jì±ò›`2‚`Ôû£ÝxSáÂ…ïP.n¥tÌûG*y”ÚåWÛžBJ «b!25,¢xšòIK*¨˜'OžÚ²„vŸ~2¯›Ñ$«&¯9r¤µåG¤I0|7&SPxdIiѢś*Ø}©*†;3ªþ¢qt!È«nþµ3 SÃüš T‚p†zH/GT5Òf¤µœvɪ Àçàî7ÞxCôéÓÇJGbå×J )ø”G뿯O>ùd¶Ê®\‘ur¿Ú¯þá„ ·&dj™×ˆÓÀ¨Ø²eË'Ìü¿i(^Ü/ÁÀE‹Ye½0~9BÛ þá{ )©}Ї=èó’K.yHeUªd<í'íW7Èå dê¨ïÊ hPI¯ÞÓjlqÝ ‘5ø\¹šþUÓ¿müNô*¡Ä ” @ŒÌ­Û¶m{¨;í¨#¾S!djø7‡¢-¸•å1Õýõ‡m´¦1$²&ÄÀŒê–×bEú‘ãÇu˜L• à=Œr_*²PT]¥2*vÑO`'ýé-ĺ`‹Š²íKemŠYè´&"ˆïaÖ V}¤ú0º )H€M'!H¶ }þÖÖ¿jÕª˜ów­ ü—îE?Dú@A%Ø®V“%µ ôÁŸºDãD ÄÏIC²ü}Dú‘ï7߉ÉE™[ÿÇ[ÿ›T1UE—ÀWÂw`Wl"E…ùt—Ëö*ûÁWh¯` ÞÇp¿öÚkV¤Fãw¢W1ˆ‡ àóÍ‚Ùì3++§â*UGaò‘±?"XPHmUá³^!ÄÞ¦×D"±a¸8”+?ŽãFÖ?nbLAÀÏ›C>dzr[éÒ¥ÑÕŠÓ}«[§À€ð¥S+W Y´_orò…ãåÀØÑ¿¹}(ôA==¢ÿ )©ÌÐ_ö ¹õÖ[Ñç_Gmý/P[»â?·`gN˜Þ$«kê]€(q %^ƒøÿ0(œË‡9ý(¦™={ö_ÆïÄd ‚nüf?øÌ3ÏôÎÊi«®¡Eý¹õ'+åK•*uƒþëà5h þ ?m¼ü±åf §îD?Œè=þ œ<4Mþ¾nÏÊéôCÁOyný‰  ÀI#ÜË–-{s$àÕ ÀÏÃÏG°í¼¨¤ÃÊoÓM‰A¢×dýdeâŠ"EŠÜ••“òC§Ÿ]ðè?h¨ û×ëE+‘º¤!Â`çĶ>¿.&S)ø Óøe9òŽŠ+>(W7fåTû!åg÷ùåÖŸªÀw­P½zõú¡À«ƒD¤Û~Œðš>}ºeüNL„ „'AÀkÌ&û\wÝu8Øùþ+”ßÀ)J¨íN?ný‰@ @~]d5ÛíúC@]¨Ê¸HjàCcZ/xØg ú¯ÓM R!x­™îÃl¿fÍšuRA?äû+;øýÜú€"¶œþùÿ2GG+º`ÃGY/ª QàAMðƒ 8?²">úh÷¬œ:ý0F ùþÒ.~?·þD àü’%KÖÑ~Là WïÖ*kGú?ûì31qâÄ¿ ߉¡Ä Y‚€Ÿw2þvíÚõV´øVUA?3ßO¿Ÿ´XA@Yp­nv)p4»üûàÁƒEÇŽ­C9±‹ÀÊoÒO‚€×a‡bæú_xá…Y9gYÔVû”qúÑï'°Or®5|øðƒ¶ å5\—œ.(šA¤+?Ò}pàóÛt‚X!”D"x³µ|ýõ×Ge圓€qéÕµˆ¿]ìàx0r¯) w»y`$»øÐÈí£º£º‘ãG´_“©¤"Í"eü£5ãG™/F{•ÍrŽø3èG^쓜¯–]y«tc@N<œÀð0½Ñ~øþ0,¿ý"fm¿íóËmÿ eü×+ãÇT_¤û00Å)âO¿ŸH Àüº²Òm9,Ô.Ó{`øèáGîÆ^~›nB*AÀû:ùûhîiݺuO?‘)pR3䲿}ªn0('ãGeêø1ºKž#h aü¦˜L• à¿Xõ¶ü2h¹·aƳr¢ý×fåTù™ÆÏt‘Ö€‡ýŸÒ G™cÁMãG°[}tòaZ/Ò…¶ñ;Ñ« „ƒhñ§@(Ó”Ëd 4ðÄ!©µCã§}€}ˆ+"Ü—Éy|Ù¡Š™«#¼ðïpL¦Zð5 ß,éÕ«û¤¿?8wîÜhìÁž8$µº ø9ÿ)4~"À‚üvÕ矾«[-â0únݺY<°¥†‘Ùt‚d ¾ër[ñUGß*Y×ÿ¼¼_ß…(ïÅ0O¤úÊfåDûiüDÆvT·U‘ƒŸH{0-ªVÆs•áÀˆ0üò6µ²6½ôÒKÛÉÕ¶ë³Ï>;HvýM…0H{ ‚mñ2rÔä÷ï߇tCVÊÓ§ËêׯÿŽôçÿ« ¾±ÚÞÿ[­ô0úÚjµGýþ¥ÊÇ¿À0üâj»j˜UŸÆOddÀ®,­bfå¤ËàG£Z¹s Èh Dáne”Í‹/þÈÕW_ý|½zõÞlҤɇ=ôP϶mÛfwèÐa¨ä0ƒCe>¾_«V­¾’u=7nܹN:ÿ«P¡¢õ-Ô{6QŸÑ@­ðÿR×p£ èÕR"£¯ª­öçi>~)ÃçªOP 7  Ú”P®ÚƒQ‰ò£k(1¸F ±®2Ê[”þ[k}µJƒ ]Ø@ý{}%*Øi ÿVõžu5c¿F}ö•Êà«©ëºH3úsÕj¦ hž¡mõ *‘s3|?‘±n€ ,¤‰rãç(㪨Œ­ŠZm«+C¼BåUÊ@k)c­­‚pש݃¯S¼V½¦–z«”Ø\¡>£ºÚÖWÑ ¾‚ÚÞŸ£ÄÊ6úbjµ/¢î¥@˜Ÿ†OP´X@>µZQ+hIe\ÿPÆVN ÂùÊ+)£¬¬ ôe¬UÕ*]]ãeŠú÷ª©Ÿ­ª^[E½×Eê½+ªÏ²WøsÔµœ¥üú†Ñ›«}^Ãð¹Ý'ˆ®€½( Œ Fuº2²ʧ>SàÙš0”UZN¹ç©Uº‚2`7VP?{žz]9õ^¶¡Ÿ­{)ÍàOW;•SÕJo}>Ãè¹âD®€-ön ¿2®ÂÊØŠ¨ÕötµC€1W†YRéß•HØBa³´Fýûgj^R½WqõÞghÆ^Ä0x}{o½ÛjOÃ'BpŠ¢-”RÔÅ¡ˆ2Ö¢J(l±p£ý3E #/¬¨{~ÃàVzÓèiøáAri•[„<šñéÂ`‹ƒ-4¡EýgókFžO{ÿ¼+¼nð4z‚H ä2ŒMStˆ–y æŽÐØiô‘D1'áÄÂͰÿ¡¡Óà "Â/AAAAàÿÉsÃ$tö3IEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata/ico/dmg.iconset/icon_32x32.png000066400000000000000000000025361347155106100261530ustar00rootroot00000000000000‰PNG  IHDR D¤ŠÆ¸PLTE7­E6§C6§C6©D––– ¢¢¢–––NNN«««­­­ÌÌÌzzz ‡‡‡ÑÑÑ...¢¢¢OOO§§§¤¤¤ÈÈÈUUU²²²‘‘‘²²²ªªª¬¬¬¥¥¥"""ššš­­­ppp 888bbbfffjjj]]]///AÍRFÎWHÏX}݉ß÷âÿÿÿéùë”ãžnÙ{ýþýêúì©è°¢æªÝöàŒá–ÅðÊþÿþaÕoKÐ[òüóãøæèùê¼íÂHÏYBÍSûþûÇð̧è¯[Ôj³ëºûþüùýúCÎTÆðË¥ç­öý÷ïûñìúîÚõݺíÀOÑ_ðûñÏòÔmÙzTÒdóüôÙõÜíúïUÉc—ÜÉÉÉ€ÞŒñûò™ä¢â™ãøåƒÞŽÐóÔÉñÍÀîÅFÍVhÅs¦ÅªØÙØÞÞÞÙÙÙ“ãïûðÓó×h×uÒñÖÞåßÈÐÉÇÌÈãããñññÝÝÝëëëTÒcÎòÒh×vKË[†ÂŽÂÈÃÜÜÜéééìììïïïÔÔÔÚÚÚbÖpüþü_ÇlÁÆÁßßßæææèèèÑÑÑäääWÓfKËZ¿Ã¿àààâââåååçççÍÍÍØØØÒÒÒxÁÕÕÕáááÈÈÈÖÖÖÛÛÛÃÃÃ×××½½½ÏÏÏÓÓÓ¼¼¼ËËËÌÌÌÎÎι¹¹ÆÆÆÇÇǺºº¾¾¾¿¿¿»•ľftRNS —œ)2 ›4 $ .372?(—auØß#þ…!ñ?«-þXÐ5qÚ:>QVWZfßþw&(/Fì¿9éäL,ÜÝY%ÀíŸL+M‡–›ŽkL#6"(wäïIDATÕÁMKqÇñïoþÿÿÎÌÎn©(nùPƒ°ƒ!Ö±‡S"BèÔ¨K/ êЩSï k—.£§‹‚K ‹Ž™ëª³»ÓÌú\½>þ¢Cþ”z XrNÔ6 "ã•[ö:{¢8µ€+&á4ÿ`ðÀ…I4Í¿xXhu•©ÍAV`Ñ1M’3V›àHØcÁ¹@¹#«b¡åÈùRLOA¤Ô¶ÈZ1,›Ÿýœ££ ϲ£¢ò/Àá*R›™àG%ðØ¬ød|ê5çj5r^%²;õƒc›Íxìró£p¦0\¥´p’ÌØY{ÛË®pBú0Åæñåî<0UË®÷—õ.¼€Ò%åÖ#y5¨Ì)ró‹æüÌ•ê5[ÙÜ5æ“ǾïÏ>GSs7J¥F5Š ËÆ˜¦4Ùó8˜ ã`( ‡ŠÎÍâãdߣ0 6‚-ß÷{K7½¤Þrc¾$:$=ô¿®o:Ã-©º”Xh..÷ž¦C™p±>¡zTH}½ÛjbIYêJgéèŠËã­¾Rx4¾gçë)R☜e­ïœV¤ÕÙ©ûîMy­ HÙ– †Õ°DðòUA#síÄAêN'ÕñmDOã0²Ùó14¯»K}Ïg)™ßù>…ú^„Z°IEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata/ico/dmg.iconset/icon_512x512.png000066400000000000000000000645501347155106100263250ustar00rootroot00000000000000‰PNG  IHDRôxÔúi/IDATxÚíx\å•þϨYÕ²Üe[²Ü ˜^B ”dI²v—ì&dÙH²d—ä¿!Mo”¥‡P–j:Û€PmÍ4î6î½K¶z™™ÿ÷^ëÚ£ñ­SîÜ{çýù¹dI£;ºÝ÷=ç;ç|"„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„Øá%àï›Bò€8/¿[B!yo (ü}BÉC3@ÁÈŸß!ׄŠ<E!~wþî !ü”?z#@×ï-’æ×BH>ˆÜá׆ÚPÂ)ü‘M!„„ÝXý?žO&€BìßU$÷ù „äSôo$ôq‡F ”&€7ÿð¿ÕÇ"³„æ¨ßéÛ¼0¼ùWü“E=ùã½G¤÷­ÓŒ_#„ FøN#~ýýXÂáÄ„Îðælñ˜¼Á/VG‰:ú%˜§€¯ BH€•øÇ{E¿[êèêý²A½ (âë'âoíG’>VØ+þ'?}Î¥£*.åå$„C™wì¬a½âßc`"IoïÁ¡04ÁÿˆPÔ+þå'Ï>ûçJüÀËI!¦ KÚ.ÆYO+À É™øG,Ä¿â¤Yg_YZ_ù}^NB±Õ@}‰4fbÌîÕñ0üð$¸â_pˆøÏ<ëʲѕ—ðrBˆ-Ò·F*fòu¡ÌÐSü«û±æ_¢‰ÿ“g]QÖPEñ'„Ô @¢ °[÷¼! ð·ø'¿_`ùïÿ'”ø©º˜—“BSØ{D¢|£VëxXDŸ xâ_d ÅÿÄ'ÎúYÙXŠ?!„¤‘ˆ'e"a‹¿UÚ_ÿÊg|ágåc«¾ÇËI!)gtOºïÆmŒ@ M @pÄ_7Å"ˆÿ¸þBÉLÀÌ„€àˆrä9ÅŸBÒÎ$€˜É}X$„üýRüùBHf3ÉÙV»û7 ñXü×Äÿ»¼œ„’QP`q?¥ šø§øBH† €‘à;Ý95äžPü !$ß3f& æžøWüûQü !$«˜Üjm&ü¬ žŠÅŸB²zŸ¶~»{; aäO!¼WÛ¡ÍÐøWü/§øBˆ'÷k«È?´u4BÉ÷ @(#|Š?!„{•ÿ4B!yñÓPü !„ØÐgh(þ„Âûx¥þi(þ„BòŠ?!„ð^N@(þ„BhÅŸB ÅŸâO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü !„Š?!„B@ñ'„Bh(þ„B ÅŸB¡ øB!4B!„€âO!„ÐPü !„Š?!„’§€âO!„€âOñ'„B@ñ§øB¡ øSü !„ÐPü)þ„BhB þâ@ü+(þ„BhÂ!þâ@üKzÅÿgB!4Á6ÉQ…øWRü !„Ð;ú7ÿÅŸB @xÅß*åŸøŠ?!„€™»ŠÿbŠ?!„|¢(ÄÑ¿•ø§ýg(ñGñÏGUËÀâ2¸x ö¶º¨¿T–KyA™”«·eý$)Ð>vñ¸´D[µwÛbÒm“Öh»z¿]šº÷JcO“ìîn”=ÝMÒÔ³—›BEñ7ûX²(½Ú†jõ£ø‡ûÅ)’1eõ2¾¬AêJGʨ~µ2²÷()(öä9tźeSçÙÒ¹M½Ý*;6˪öµ²¶}£ôÄ{øK"„Ðd8`ý&EþßãË!\ RÑüQUSeZåT™T>^‰fr ŒÆØ²ÑÚ‘HO<ªLÀYÞö©,jY&7/–]Ý{øK$„Фý›-Àô;ñɳ~Z>¦Šâ’šüS«—ãú¥EøÁyî…2¡|Œv|yðÙÚÇ%xoßGòöÞ÷哿¥Òïæ/™Bà"ú1®þ‡(Uâ _Á¥@­Ë¯Äþ¬Ÿ“ûc¼FPFô.?ä‹ÚѦj ÞÝ·@^Þ󺼿ïc‰ªŒ!„Л³È?1PÄ—@0©í7L‹”Ïxš–ê;å…eòùšSµ£Q¾Òø†<³óÙ¬²„’¯ bò~òÇŒ¦þò%,&–“ó‡þœQó)Œä篯Fu)üÓÐ/Ë?=O4/’Y;ž“ù{?”¸úG!ùžH³À¾‚Á‘•Sä»#¾!‡WNæÅ8ð¢ŽÈ±UGjÇâ–år÷–‡eaËR^BHÞ€D±7ÿ3ÁÕò¼PNè4/†0F7Mü½V4xǦ鲮cc^^‡¹ÇÌôô|g,8Ÿ/>Bã?ù}#3À @€è§ï|}ØßË7†-ç­{AFéØÃŽ”§U}À=[‘v5˜ˆdóáÒ ¡ðy&ÀÊŸq\ÿiòßõ?”¡%ƒy1Rµ_Su§ 8^®^÷g. dt¡°#ƒöõbÑ7úxrôáKÀ_ÂõoµÈ5ãIñÏÃK†Ê'—Žú¶6g€d'@3Ì4€àÿnìåZ•?ɬ@!0¡|¬üz͵j/‚}¼(ͨ[ W39{7F ±äL¿ûó¤?Qü³È•‡É_&_# ¥u¼½ñðBhü(úÉ_c– 9ä´'ÉŸ'^%CŠñbd™Zµ$p«2Zh©$™ºòBhülÌZir ¦ÚýrÌO<Û‰ˆ¶µñ5ã!ǪBK’›L„·B„Ì€™ 9àì§Ëÿ4\–·Óür Z,ÿ0ö š€ŒÜlx !4~þˆCѧÈ!'U+?ýC­…ŠäÊ”ÈoÇüT«¿ éÜ@ù&4AÍÐx̤òñò«1ÿ‘¿ÀC÷?2¬d/Fª7.€@d„‘nÁ®}w¥”ª4ñËï¤Fk¿,ް#µ(o%„ ˆ†€FÀCñÿr̵숿ÀŒ€Žºˆ"¥ — !–|»ö_Ø~æc¾:ä\9½æ^f @^fH–˜R1I.öU^ŸsYÝÅ2šn%„ÐAè)üƒjó+. ]ÅK´Uš£-¡ú™úU)p _´Ì<û¬’¬rQí×eT¿y¾Û»vʆŽÍ²¥s›lÖŽ­Úû±Ni‹¶Kg¼SºbÝ}ÿˆÔvÅe¥RVXª8/&#û —êÀÛQ¥#Ô5¨ ÄÏÿ™'ÈçÔRÀëoóÅë$Â`¡t†€d ˆßùj#?³§»I©ír?l^(îûD¶vípý=zâ=Z6@ÏÀ@$3 ¨Z¦UM•#*&Ëá•“µÂ;¿‘AAà»{?ÔL±Ë°ŒŠÐr?ªûŽû Dòóß”gw½"+ÚVyrΦž½ZT­GÖÈœ9ð49{ÐéÚŒ~?}¾>ìäþ­ñEÌ ¡ Ä'ô?ZÇøê9­i_/³wþUæîyCÚc9}.›ÔÒÂô­Ë[gÈ©*íŽ"É©ªXÒ/àù<»ë%ÙÕ½‡/fË ¡ ä`T¤þ}{Ä¿øæù ­Ïæ‡UÔÿ–ÚºÝ_›·ãù¼Ùô®vœ\}œ\<òB]:*çÏ Å›ßþrÓÆÿã ÚòµÎ%dKH†9uÀñ2±|\ΟG4•G·Í–o/½L檔¿ßÄ?™wö~ ß[ö¹gË#‡æ‚/ >S4å ÚÊ0@h9ý£ò?× šÿ²•¿”»¶<$*fëQ¦åám3åÒWªe‚-9}.¨ßø×á_ã‹ÚòÊ[(¡ DãøþGÉØ²Ñ9}K[WÊ–_.KZWö:®j_+—,û©ªÆ_ÓçqŽ*Räp kÃK !Šú圞ÿ­½ïÉO>ý•ªºßøk‰BÅ_®¹Z[¾ÈØ$è˃Ïá Ûìʽ !¢EþÇö?2gç³é=ùíšë|±~ž)°$pÕº[r:˜ç«CΑ’îÈ ¡ Ä„¯¨H1W7Äm«åënÒ3l ˜?ÛÇÍKrr~ 1úLõ‰|fh Ésú©¸gülNν³{·\¹ê*öK%ð»µ×i?k.øÒà/ðEn˜à-”Ð<çój~|Ea¹ççEkßÕëþ¬MÚ ;¨køãÚ›$y~×ö6 É€’çœ;茜œ÷ÉÏÊGÍ‹òæ:/Tû<½ë…]D¾£ ¯ ‹ Ég”#*óü¼;ºvÉý[òo^=íÎÁˆÞ3jh½2@hHóùšSsRü‡Yú¹žéŸ °™ÑÃÛfy~ÞúÒ‘ÒPZÇ|b€€î@Òætµþï5ÛÔ|ÿ—÷¼ž·×üùݯÈ7Ô”>d_¼ý]ŸšÑ]ç33п‡KÕŽ—-ÑVíýBO•–Y~}YA™š°XhúùBõ¹²ÂRËïQQP~`þÀõn—çÔ®–„ÐÏT\#‡ULðü¼˜ñÆ–?§`ÖÁŒíÏÈF]äéy±a· >ȤïyÍAA( \ iqRõ±ž§AÑ ÷ÂîyyíŸQÛõzÝý0¾¼A{œu æÄ…€ÐqbÿcûÄO©˜äé91ò·#Äþ¤Ê¾žfYÚºÂÓsY9…Þ° €ÐÏ™P>FíXâé9ßÝû/¼ ìûØÓóM*Ï‹î8€ÐÏÉÅðŸš?æ…7á} ÀÐ’ÁR]ÔŸ>çÖâ1“˽5ë;6ÉÖÎí¼ð&¬l[ãùP q,Ì9¬ 4Ä{àqÀëw#Áo‹<¾|,/|® k ñ’ŠÂrÑo˜§ç\زŒÞ†Å-Ë==ß„²1¼èÌ’O ÜëA0+ÚVñÂûìM`ÀÖâ!cÊê==ßžî&NÿsÀêöuj@gç«+¡¶·-å…g€Ð¼É”z[üÅèߨ"xmûÏ·,Ðævâ)£ËFÑø”m«==ߘ²:^ôÂ9„€xJm‰·€^‹ZYéñµV2”=§B@<¢(R(ƒ‹zzÎ í›xá²±c‹Ç`/za ¡ žÞð "Þ½lºãݲ½›€NÙÔ¹ÕÓóÕ2[ÀB@¼b¸Çýÿ›;·1ÊqÁžîFO7LÞ€B@ò¯#¾M§´ƒªÂ·(Ó䃊k¤¤ ˜>‡¿oBR¥ˆ—€¸Šø<6;i\›&µ 0Ö£ö<´-ìùÒCØéŒuIW¼ËðsíÑUýÕÞïŠuñbâ‘ð8廹ƒÂâ÷k†×DªàŒçgô¹Ì=f¦§?û÷—_®½m¶®ÇÇãqõ¹6ÃÇ¢¾ÅËåBhHZxݸ½k'/ºKvx\49< W²E•ÖWxÝöµ§§‰Ý%»U! — e+ !4$Ü`½·º¨ÊÓsîêÞà ïÖ4u{kšª‹*yÑ ¡ aÛªA@^mZzZyá]Òèq ª°Šfú{ý#•Í6§®[Ç€BhH¸©*ôöFïõZvXÀ®€f•çY1†…4„Ðp€¢ OÏ×ÈÀ”ñ²€BhHÈ©.êïéùš¹þŸ2-Qï®3„аg<¾Ñ·y˜Æ^^»²Â2m—HB mÀÛ"À¶X;/z®ÚC+™ „€„—JÏ34©_»OÏןu„Ððâu`+ @o—O0#‚B@BJI¤$Ô"® €·æ©(ÂmE¡ ¡ÅëB/.¤cž¼½vÅ4„Ð0ooòÜ*5kíôøµQÌ‹N +^GyÑx”=Õk'Þ^;¶B@BL¡Ç ‡ 0æ‰K„Ð0g ˜ 03‡ÌB@B‹×iÞ˜Ð&PÀ !4$ÄÀë @Œ= ׎m€„ЀŒÑïáEȵ£ „€Ðd0Šå3„’ûKÄÛ—Kœ—|ï¥ ¾ÍÔ àEOþEURäá(`f „èkˆ‹HÏÛµÞŠÂr))(æ…wÉ£ÐÌ !¹þHºß„€8&¦¶|õºuî©öÚ0@ˆ_„?bq@ï‘,ê}?B@\±³k7 €ÏXìíÒIcO/:!Þˆ¿è[=z_|íµ×6ÜqÇ“ðâŠí];== ýŸØÝM@H¢~£›EþXK-»á†>7~üø~ýë_¯a qÉŽ®]žžoXÉ^t— -ì±ØÃ‹Nˆ·¿Óÿôê|Ùm·Ýö/uuu×.]ºô+Û·oëŸ$Ä· ¶d/ºK†÷ê±häE'$ûâŸñ'þß(ê‡ð÷Þ­Ž( qŸèö:0”ÝuÀ;ӄΦž}¼è„x/üñ×"ÿýèGÓN?ýô{úõë× oÛ·ßñàƒnÐÅ£ î2Þf¼NgÒ‚~ª°Ê³ó¡&€â™øGL>¦û•^wÝuÿn#øéFýHùk½ýßûÞ÷ŽRiÿëKKK'Ú=±… Þ¼víÚæ$ñ$ýŸsHj¬éðv`jÅ$^t&•óö5àñR¼6$EŒ¡ˆ3£à¶¯ÿ€ð«I~ý¯¿þú‹¿ò•¯<éDü[ZZýéOzNö§þãç8øúåý­—Ï 8Ù³óM«œÊ‹nwª¼½FkÚ7øîDU4î¥(E ùÂ#Y‹úQè÷­o}ëUíÿ§øõ×_¿A-tÊþ¡?¦âO@ýM®˜ ¹íˆuò ‰cËF{k;ü—ðÞðJ ¿•Ð×ú {ú•ÿæ7¿ùÊ´iÓ~S\\<ÀéIwíÚõúí·ßþaoôo6e€¤Çª¶užž‘ÖÔÊÉòá¾Oxñ 8¢ò0OG#Õ¾®}£/ €·¯KÞBC.ÞÉÛ|Ìn󻨿Ÿêé¯ýþ÷¿ÿó¡C‡þƒ«¿Éx<:{öì¿ÈÁyÿF™fHúlëÚ¡í?¨¸Æ³sb€ÀäÚxœþG(ºü†×yÈJ‘¼5 q ÃRÔ¯Úûþîè£þ•Šú‡¸}B›6mšóôÓO¯’ƒóþž[Ã"@’2KZWxz¾cªŽàE75GS¼ýÝ·¬ðåuð:P]ÔŸ/¾üÊ8ùœÝ4¿BIhíƒð«¨¿Nmâs½zûçTÄ_ ýéxàî‘ým1ƒçg€dX–ËiNòì|‡©:ìA€ì9ÈÐ’Á2¡|¬§ç\ܺܗע+Þí±¨â 0?Ì@b ÛÈ¿@æ‡飲_ÿú×ç!êWC}§ú?ýôÓ'ÔÌÿ­rèУè?®ÌÀˆÖ¸O«9™>‰ÓT7†—ëÿ`i«?3^/K0À ƒÈ?yQå¹çž;þÁ¼óøã¿%ñïîîÞ{ë­·>¤Þíƒ ,L3$uV¶­‘Öh›T–{vÎ3jN•ÛŸæÅOº&^‹¬ As· ?3at³¯‰'½5‹üÒÿšø«¾þ Uáÿ/S¦Lù………Õib‹?¬†þ4%Dÿ}¢|“Cû’2Xoý¸e±œZ}‚g眨†ÝŒêW+›:·ò À’ȤŠñžžs±ZúñëÀ–h‹§çÀ @ØMAÄøÛeŠzÅ¿ì’K.9öÌ3ÏüMyyyF š:::¶ßtÓM³¥ïÚÜ©àI‹÷-ôüœ_ø9^ø^>¯¢¯ÓÿïíûÈ·×£Ùã%€ý†óEžè߬]ÎIŸQ[Ÿ¶kŸ:Ê'MšTû—¿üåççwÞã™íoñ½÷¦«-[zÅ¿Otoù —HF @³÷my_|–<¼m¦t{\ðå7°ÓyêZxÍ;{?ð¯èñ60ºtoáüÅ&ò94ݯ‹¿Vä§ú\YRR’Q·¨Fþ®»á†^”ýkÿ1§Qâ×Ñ´ØØ±EKÇ#-ï5j0ÖYO“çw¿š××þ”ê㥶ß0Oω €¶wíôí5iìiòô|X‚éWP¢mEB1^óO½º_K÷_tÑE‡ŸuÖYWª1¾Y)ÒyõÕWïéééÁhÔ¨‰ÐÇ„K$Û¼Ýôžçç¼°öŸ¤8RœÇw¦ˆ|cø×ý'áµ9AfT¿¼ „KäTô'§úõêþ UÜ7ò¶ÛnûùùçŸ?;[â¿gÏž%wÝu×;rp»_+Ñ73DÒçͽÞ€a%Cä†~)o¯9Ú!'•ϋߵŸ À>$T&@Äù@]üËUuÍÕW_}‘Ú‰ïÕúúú‹#‘¬E(ñ§žzênõVþc‚Kÿä¯fHFÀT¸Æî&ÏÏ{QíZ 6ß@ÛåŒúwÏÏ‹ôÿòÖOi’8®êHÞÂaì?ñÐ…¿Týÿû¿ÿû¬‡zhÎá‡þ{ÕÓŸÕùè›7o~gÖ¬YKä`ß¿Ùa·À É€Uÿ^kzÛóóbûå£/ÕÒ°ùÄ¥£¾#ƒ‹z~Þ¿îžëûkÓØ½×óõø“ªótÉŠð»‰úuá¯ºà‚ ¦a˜Ïé§Ÿ~_YYÙ¤l?Y5ò7öøã?˜ý›¶4$#¼´ûõœœ÷(µ ο×~=o®ó!ç :ÝóóöÄ{äå=¯ûþúÀŒz=*E€7ø ¼ „'ú7Šøõ {4á?å”Sî¼óÎß|ó›ßœSSSs–ˆ7½¸7nüÛܹs×ÈÁÊÿ˜šú™üÿNvŒ°¢m•¬ïØ”“¶¨UÅp›U' »ç…úUu¸\VqNÎý¦*ôÜÛ³/×iUÛZÏ_‡ßv¾ÌÛó–ììÞÍ›A0Å?±°/Öû6±íO3‡vXÍ~ðƒ=zôEjŠ_¥—OTÿÑG}ô19tíßM@„K$+Y€=¯åè/8"?©ÿ|n@x÷ @¡ÙïÇþ,gOìx&0×jUûZÏÏYUT)¥Ö¢Jýø¡—¿bèСƒ®½öÚ謹—ÆŽ{i*â¯IEEEÊOtݺu¯¿ùæ›ëz£ÿ¨ðÛFÿÂ%’IþºëÕœ ç)ŠÊ/ÇüDÎU)òðEþSåºñ¿ÎÙ:óÇÍ‹e™Ï‹ÿú€u99ïø²1rÏa7ÈW†œ#å…eY9Gea… T&óÆ”Õó¦“ù @â†=åjxÏ5·ÿ몭ï9ÕÞ÷sµUï T„„ Ò¿imMmR¥Šþ{T­¢ÿ.é›þ7z'Ñ?'’ÌÒ¤Rį5¾­†ôäfT/Š/ýÒPZ'wmyÈó½á³Á—Ÿ#?ªû¶28¹ûS}tûì@]3,äŠEÕrYÝÅòƒ‘©Í²VkÙˆ]»´M³ÚcJe ´š˜¹õ…¬åR\P,å¥RVX*%‘Í@ôSŸÃ×Tª¯íÁû}³?øž_þäBÞxÒ¼mHßÊ~cú’Ë.»ìój§¾‹•€§Ôo ᯫ«“ÊòåË¥±±1õ×ôªUóÞÿ}ìÀÕ-Ö…vË}'þþI&yjç_sftþyØWäðÊÉrÕº›UmÀ¶@^G¤”!$Ÿ÷x§¿d>U;>¾¿ïã@];Ô*x=2ˆü•‡iG¶€IÀò—_7f P@/ð%üÅ—^zéi'tÒ·Uº>%áGšÔ¨Q2dÈéêê’… ˆüãñ¸¨ùÚûªk@¢Ñ¨ö56Ñ÷Ã?ü„Iô÷kÿÜ d¤Š?iY"Ó*§æôyL©˜(w«tì#*z}|ûSÒëÈÝ(¢¨‹G^¨¥zsÍÿmy(¯Ãj“ªQCjCý·†× 2mÑvÞxRGâ1¼øâ‹?ãŒ3¾[YY9.]á‡ÈCôÕV½šÀCèÕØ^QÂöüª*ihhE‹Ù›ðO?}õÃ?ÜÔk¢bßþç(úg€d…·>!Ó&LÍùó@ -‚_t¦<²m–ÖÇŽv6¿ÞÌOª>V¾UûÏjÂß8_<§ù{?T»=~È×àj“*¬Å‡ò‚2€4@1ßøÃÓN>ù䯩5ú1™~°k×.Y±b¢wlÙ«Eþˆø*(UHˆ–>Ûï­ŒC×ý÷ßè?¹ï?*©Uþ'þŸ€d!új^$KZWÈÔŠI¾x>üãúK4q}eÏßäEÕ.¸®c£/žÛ â9sàg土÷UQê'îØ<=°¯A.âg(Œ†úo µ»º÷ð¦ã’Uÿ>¹}¬\òðÃ׫ˆ?¥]úŒ„lÙ²EÖ¬Y£‰~SS“õëâšøÜŽöó*TíÀË*K€uÌnÑ·ë°ŒþiHÖ¸gË#rÄßúê9Al/öUíÀÜ /ZмP6tlötSüŽQãcÏø5Fvš/'>½óíº•–h«,jY®uP„ÝçÇŠäˆö‰r\ëRU-y•âZü•aÐD|ðàÁ}>Q_½zµlݺU{Û¶mZ @AAŒ7N3 ÝÝÝvÑçôéÓgªw;ä`ë_Ôeôo–   ÙÀ0<æ3NðåóÃF:úf:è^XܲLÕ.,Õj¶¨ÂÁ¦ž½»A×– “IªžèU˜xDåõï_°µs»fà‚ÎËj.EØ @¶Ú Cwbertëar”:JãýRújg?-⇨ˆµ–òß½{·–òß¾}»Œ9RÔ¾Ú1yòd­ PgçNû=+–-[öâÒ¥KÓþ“‰3@<áN•B>©ú˜œ¶°9a@QeTNÔŽX§f¶vm—m;¤KÍ7@TÙëÑÚ¹pÀåïo×*9к…¶­¡%ƒ5‘‡ð£š?H ríú¿h?_ÐAKê¥uß‘²‚Òðf ˜°¢¦§Z‰þd9²}²ÅS[0`€¨É}<ù-Y²DZZZ´”?|=–JKKEÍÐÞê òWÛùZžS ¶«í~ý[õý§ý÷ùs§ Y-xl›­ÖÞÿ)pÏýÙcËFkG>1{ÇóZG€‰y³éÝœ·¥fÕp àPP[ßY«"þ)2¶³Nû¿ëï¡Ä‘¾ÚÖWKù›Jˆ?¢~µKŸ º Ò‘¿ê,ìóDÿø:+T÷À j9a—ô­ü·[pý3@²ÎCÛžS§MI#þCkîÚòp¨~¦'wÌ‘/ <-%å4ÅLųSÚÆË±mSe ŠüSkõX§Ç¿^¸gÖñUš^:;;µ¢?…#FhŸ4hLœ8±Oq`¢°‹þï¾ûî§ÄÙŽN³†f€€d•U‰}ͺ[å¶ÉWçlŽ=±Ãs~µúZµ•ng¨~®OÕTÀ·´Z”Cš` @MO9\öÙ6IJc©­ïCøkkkµ5~5þ×öëQ০óIss³¬]»V[ï×kð>–ŒÀ2Ý8`e*^Qsÿýcí¿Ç$úŠ}ëŸeôO@|øpM¸e5ÔgåÊ•Z…?L¢¤ù±T#1iÒ$­SÀêñd…šú7Oe¶;ˆþí6ý±þiˆ§Ü¼ñÿ´ùìÙœNÜv?ìßvnß4]Ž®:B½þFÐ4ÚGŠ\Çh5¸?õ¹ˆÔ!üÉÃ{ì@å¾jÉÓ"x¤þaPݬÌÄa‡f[3€AŒ¶0==ôÐ,9Ø÷ŸÕ蟀x æñ_¹úrã„ßÉ„ò±¼ 9ro›™?+Ú:¯Vµ(7MüïÛRiöƒA=‡µ“i*ÚïM½V¯èÇú¾Y+ŸmmmÚLˆ?Šý°Ëßøñã1FX3'ËvŪêÿoüñæ^ñÏêÚ? É ˜[~E¯ ¨/É ’#flZú} ¯~æ¥j<õïÖÞ ¿óÿB3"8lƒ€PÉ?AEùG´M”Q]ÃÓªÛ€@#Ò‡ðÛEçf §‘?Zü°îê~´ùÁTàý &8ZB@§ÀÞ½{­¢ÿèc=7޵»-㙈þiHNhìn’­ü¹\5î´]ûˆw`ÐÏÝ›–GÕ.‰ùæ\»þV¹¢á?CQŠ €’¥‘ÝÃdJûxm>I<½n!Tñ£¢…}X›O¬õcºÖû‘¾6l˜f& þøÞú°' {`Õû¿~ýú·ß}÷Ý rpê_ªÑÜDðÙ@üCsO‹\¾êwò‡±W¨q­‡ó‚x@g¬K«ö£i~^_‡—Õ†P;Õ:¿hø±/¶\N+à.€AÝdJÇx™Ú6A*béÿHïC˜1£ßÍú¾}ÌõǶ=ˆ½^70fÌ­xÐ 6éÿø¬Y³’gþ§ý›Š= ñX€ øá¨—¿òE^,‚?¤¿—«½Èþ½*¾¿ü§ò‹1?–#Õþ ÌxÖòåÞ>AÓ›.H¿c}…}©¬ï'ƒJ}U‰¯­õ£ØÿÇz?Æ#›€ª¼ï¤þ1)Ð µ-ð{óæÍ[-é÷ý»ŠþiHÎÁ  [6Þ­íÎwYÝÅj®~?^” 󺚉݆ۥ5ÚÆ‹‘¶ÑýñÊ_Éi5'ËÅ#¾)µý†/ j°”áån–nÁæ;Û´)}#º‡fdé;ì! GªßIž£{‘ªÐÇz?„Æ š¹€à£ÐÏi¥¿¡ùÞ¶Í2úŸ={ö“r°ï߳蟀ø†w¿&KZVªµÙKU]À$^ s•m~©á„AzgïûÚœ€¯9WkU Ó²ÂR-›æ'úÅKTË^ŠöÇÉèΪq/3[^#ú†è£/Ý4"ˆÐ-Z¤õùc½â·n*ý“±ÛøG úø¥—^Z!gþÇ$µ¾×Ñ? ñ›:·È®ü…\0ô«ÚB̤Oea/‚Т:sdz2kÇs2Mm!|Þà³ääêã|µ“ ²e:6iƒÖ´¯W6׫÷×ûFüém¯“‰ ÒÐ5R ã™é´@êxþT«ù­@Š~áÂ…ZÁ†ûTTThÕý8¯›J#PHhUü÷ì³Ï>!×þí2þiˆïÀXZT¨¿¼çuùÞÈo†z#/¸°öåõ¦·ecÇ^ ‡Ôà(R­‚S+&Ëqý§É±UGª!ÔvÏÙßÏ‚¾¹s«2Ä[µ·:6k¢¿^‰O¼ÇW× “ù&v6Èøöz©ëªÍèß*"oˆ>Fë¦*Àv`2Ÿê½×ÄÛú"Àq¾8ŸÛJÿC^KJøaÌP…‹Ÿyæ™%IÑÌÀd%úߟA .‘¤÷‚Þ£0á€Ù)N8`%}þïÍåmÏ¿`jà¿×~iðÁ¾O´bK’˜0²ßpm‹è1¥õ2´dˆÖE0¨¸F{; È¾¨ -ÑÙÙµ[öô4%¼Ý%[;whY°Ýݾ¾(äßQ¯ÖõÇÈÈža’Éò´ðA𱾟h?Ìñÿàƒ´‚?ˆ5΋íS­ôOFß-Ð Õ÷ÿ5ùï õ.vÒûÿž¤#*öÛÿÒЄTj_¨–‰÷üaí2·ñM^ˆ,ƒ/KÕÒUa¤@­Íï°öh‡tÇ»]„Y­ÒÖô!ú™*ä;póV‚‹úÙXÛ7‹ÌQéÿÉ'ŸhÃ}€¾!†aí¿¦¦&íó,_¾Ütý_ Z÷Ío~ó2õ.¦uôf¬ @Ô"3 rèðG¶ŒK$,lY*?ýô·Ú,÷/>ClÍõmü‡jµÄ†?Í*ú$ÙBßíÞ“W[,íèªí´7®³^f e/ŒÔÅÚ>"o'[ðfTú/Y²D ÷ÙÀd?<û¡ ]°œ€ €o¿ýöÓð†b=ø'kkÿÌ0hÐþtÚ€“äÌšÏj›¼D xQl˜³ëE¹qÃÿñBCJcý¤^mºƒª}¤øËc™OÁ£’b áÏDß¾PéáGµ?Šýí£Ç¿ªªJ}ˆ¦Œˆêí×#ÔÞ;Tôÿeö¤ý›þå nP(õÂîyÚõ×Ï 8QN쌣̻Œ9OeMÐn¹´u%/ÑÐSûc;Qħ¶ÆgÞHCh‘R‡èãm¶SüF@ð,X õùÃÀˆ ºY BÚ?S…†vÅï½÷Þ3Jü[¥ïº¾Yäwp¤ <{ÔÞÏì|Q;P¥=­rªv €pRùxO*·ƒÖmRÿ}¹DMÀ‹Æ£¼ yúÑÕ›ÚWQþ žìŒB†ÈCì‘ÞGÄŸ­*~' Õb?ôøc Å…|˜€t+ý@êKF¨MöÝ{ï½/÷FýFѽ“ôÿ!ž#•蟀„ôsc­@Q¶§Z¸Æ—7¨·£¥AUpçrµí];e˜ª Ϩ`ÿÇ¡çÉãÛŸæ‹%O¨Œ•KCÇHÓU'£;FhCz²Di}>æægjB_: Ò_m²ƒÍv´ÈÏoܸqZ?ÖþQx˜i¶nÝjú9µ­ð ª0pŸ8ëùÏjôO@Bв° ,ŽDjÔ²AmÉ0ÕÖ5L[S„v®êãÕêýj©*ªÔŠ S©vîT{Ï·ª%жX›ìRË|˜Ãc]ûFYܺ\ËX\=þäµd‘ þ­öyMM¿ƒ!áŒò‡vÒÖòǪô~¦«ö“E½óØ€Ât.Rü‡„ÄJì1Òi˜ oå ñGú©ÿLÓÞÞnºí¯Ê>´ßsÏ=Ï&DÿFSÿÒ‰þiq¶$Æ‘l ’AK²¨+ÀMTï<ÀÀ˜–hëþ?zÕæ¥§Ô[•èc˜‘·l¼Gî=순,OàgúϺïÊÿ¬¾Š/„P+ÕñhëùêÀT¾l…èCP!¢ýdñÍ¥ ˆF£Z¥ÿG}t  õuuuZ‘ßäÉ“µ!CÙÀ*úWKsÕ»¤ï¦?‰Bo·á]ôÏI€„d’ÍãÈ4[:·©‰‡³´h<`Ì- 'ßlz—¿ä ¢nõµ=Cd ¿k” ë,ÙÜ3ñ±¦ÁGϾ¾¦ï‡h?µÆ® ?ªýUµ½ö1 ÷A-*ý!þøY²e<̶ýU» ö¨¡?O'Eÿv›þd\ðiñ l›-g¨6ƺÒ99ÿÕ}O>j^Ä]¢úúÎRûXÛÏvDÉ|?ªåÄ>×Ñ~"---òá‡b]+ƒIÁz? 2“&M:$[‘I°‰L€k×®}Sí7°Yìûþãb?þ7cf€€ú„?oº[®ÿ«œœ#l/Rˆ¿lº¿ ¢­å÷ T|£T¤?*«kùE{J>Þ"ÕŸªØ{m Pyÿþûïk3ýQé¡Ç:?L Òÿí‹ç£oÌ“çfÑú‡-£ÿ¨ËÈ?+Ñ? !9sú_ozG>7à䜜ÿ†|I^R/}Ú¶†¿ P/RQ~­6}oLç(©ŠfoÚ%"d ÁÑ#äÄ x~Kí[±mÛ6­ÍEx¤ø!þh÷úÿÈ‘# JrÆ#ÔhßKɨ"Ä^{íµUb¿éYñŸdË Ð’cnÛxŸê8:'[Ïb‚"füÇŠ+/’ÌSÝS© >úòGªa<…’½žyˆ#Òú|´ÄAøÒMíçjç]·nV鯊ë´ÁÄ`ºŸnœVú§k¬ÿÌ;÷Ù¿ÙObßTÌwþ³Ëd¬Úƒ€³³{·Lß:C¾?ò[99ÿ¤òqòÕÁçÊìÏó—ჺÈÄŽ1Jøë´–½l¥ö‘ÖG„¯GùéöæûŨ¢:m§=¬÷ëm~úV¾¥¥¥Úz?Ì@ªÂîæq(<´ÚôGíú÷QBôoõ›íðÇ6@BÂÊÌÏÊYOÓå‚ïŒøWy£i¾ìêÞÃ_F(RqýÈÎaZñބΆ¬¥ö!TzZ‡“m2!Ô^fPà‡yþhõÔ?€9˜è‡ŸâoVéŸ C€Ö¿äÏë¼óÎ;ˆþ;ÄÝà»Þÿ ¾. !9snÙx·Ü4ñ÷Y-ô2³þ£îÛòÛ5×ñ—‘!°¹_[ÏW­zűìÜn!v{¤ôñV¯t÷Cj?ÓÆ µµUT5½6Óß¾ý»-ê[ùâgGÚ?¹xÑ©°»yžúã‰@õ¿ª&`—ûûºô]û7ücµÓŸÙÎl$$,,jY&/í~]ÎtzNÎBDÌxgïüe¤zCj­zSÛÇËøÎÑYÙ\±×Ãm¼ê\­ù£Ðîã?Ö*ýQp‡ç€ê~¬ócôpr¥&£|3Ð÷®#Ô,‚¿ªÉ€mÒwW?«êÿ˜dh›_BÈí›ïW"|¬ô/ªÊÉùõÙÙ~ZÑWéýz5c’ZÓGz?Ó‘¾Þ“¯GùN÷«÷:‚Ϧ1@¥?ÒþØÐGïñG±®Ç¨Q£ +ýÓv§3›ü‡±¿Ó§OQÿ¹úcùg<ú§ Ägìëi–{·>*—Õ]œ“ó-,Öþ“ܵù!þ2,(T‘>ò@ôÇwŒ–’xfG:#ÊÇZ> ÛpØ °ñsj?Ýó¡ÂÅ~hóàd<ô­|Qô‡‘ÄnŸO& f`ö¿*Kñê¦M›PPÓ-öé³e€ŒŠ= !`ÎΗäì§Ë”Љ99ÿ?ýŠÌÝó¦¬n_Ç_F¢P¨(ä;¼c‚&úýb™ÝU}ëzµ¾>y/h|&³X_GÄÿé§ŸÊêÕ«µï­oå«¿Mœéïeêß*úWÏ;úøãÏ‘C[ÿÜìú'ÙŽþiñ!Øh·MºZëÓ÷<ºj³.]q¥ö\òŠh¹¶¦Dû$Г¹¥½b‚¯¯å‡1‚O…îîn­Ê¯÷øë[ùBôQéow½Ò-ð³z,jô"Äd6nÜ8_Í&Ø,éoù›Õ蟀Ÿ²²mµÌÙõ’|uȹ99ÿaäKƒ¿ Ïíz9o£} æ9²m¢4¨‰|™êÌHž¾gW±–Ô¾›¯EZ)ÿ5kÖèñ×ÛüpÝ`pݼHû›=Öj׿çž{cõÖ¿Ä©™Øò7£†€€Ÿr×–‡´û0³?\<ò›òVÓ{ÒÔ³7o®9¶Õ=B‰þ´¶ÉÒ?š™-c±~¯÷å#Š… sj?óíÝ»÷@ä¿k×.ícz›*ýa¿·×i=;¡?·dTWÀÒçŸ~¹ºéÛè?ë3hñ1mÑv­åäüU…•òƒQÉUënýµ¢6Ý9¶åp™Ô>F«êÏT¤¯ñéÛç†E¨³ñÜÐR·|ùrmÍF_ÛÐРù¡Ò¿¶¶6kÂîæqèH0üóÆo$þéw<þiñ9/«zÎôy9ªêðœœÓ _Ú=O>l^Êë;²k˜ßr„ŒU#yÓMóC4áësöƒ:'&ëüHù£èÃ~âGª×QïõOe'¿L&šÍýWÛoU­óåÐMœ¶Š—Ñ? !>Ex7o¼Kî:ì)Šæä9üWýÅòÝe?–®Xw(®éþõý:9±eš ï’¶è£b_ôƒ6k?ׯ‚Šˆ_µÌiâßÑÑq`#û¡×?±Ò?QÏ„!ÀÔ?³Á?jGÂ9ªM1yì¯Ù€§›þÐPÖwl’'wÌ‘¯ûûœœT¿Zù×açËý[ üµDïþg[Ž“a]ƒÓú>hC«©©ÑŽLòù)*Ïösƒb¤/Rꬭë»ùaùo±±O¶DÝícñµx®F(ãÒ¬Æþ¾*}7ý1Ûú×Í🬚Bv <½æ^24'çÿ×áÿ óßÔÌH¥¶ÙýLó±ZÊ?Uôb>¤£õ>ý|àSýˆôQì‡tº>àGßÍO½Ò?Õh=Ó†;þaç?#TíÂKêóͲ¿øÏjòŸÕŽžS „ßÓ©FóÞ¾izÎÎ_)’×_’“ŠÒ»î}±é4¹`÷—R} /ªÏ§L™¢£AüSÃl|m¦"x/Ÿúç1Ó_õËk‘?Äذašè£Ò=þFYœ;ñpóœSy\òcÍ¢µŒÑ­Öþÿ8­øOe3„ä#Ø®÷ݽ äÄêcrrþ‰åãd|yƒ|Ú¶Ö÷ת(^¤÷ÐrdJUýH=#ÒGÄ1J7Ú[Ÿê×¢ÒkþS}ÀO}}½ :T«òG»_&¢õL?] (N4bíÚµo¨Ÿi§8Ûõ/Ñd]ài Þt]u„”{vÎÖh›¼¨:Ù>Köt7ùþaLï™ûN–ʨ»H]ŸÌ‡¶3£Â3¦öÓ;†ú Ò0hD¥?RÿȰ$Vú»õl³èê©§žéþÅßwci 8[:·É£Jˆÿ­ö‚¬Ÿk{×Nyfç‹òÌ®5àwJcýä³ÍÇ©é}“\=Bñð£Šß­è„­8/ÓçÃÇõ©~*ZÖÖÒqõÝüôuÿLŠz& &šýUÆà“yóæ­–¾ƒ|9ö—€ðȶÙrFÍg¥®tDV¾ÿÚö òøö§enãÒ⚌Um}gï;U›ÛïFø±æ áOÔÃ>sçÃú>†û@ôQì!EEb¥?Úþ²-ê鮳^Îmú¬¶îïôð£Â€|vMËîÝ»5чø#òÇÀ˜.´P"ë2räÈ”~6/ gµéšcШÿ¼&}ÿÄÄyÿ¿ä:ú§ $Àìîn”¶=)ßù-ÇiuÈ_w½*3v<#;ºvòçF‘ßYj½ßém¢3}6Ä7hÏ Ûä®[·NµÂ?| *ü!üuuuZ ÓÑz¶ *ÿ1ªØˆ… þUÍþG_ ÝÚ¿oÆþÒ2fîxVÛ°g\Yƒå×ííÙ'Oí|Afí|Nš{ZûóÓ6UNß{‚㨟õ3µŸóáó¨ð‡h"j^¿~½öõXï‡ècCŸäÖÊL‰z6 Uô¯2÷ßÿ_{£ÿÄÁ?F™«ŠOÇþÒ2¢*•ËÆ»å¦‰¿7œÒ·­k‡fžÝõŠ6M0È`¨Úüœ€5~DœN+Ì™ÚOý¹éú Òó8Ðæ7qâDmŠýð{p»›_. ÖþÍ¢ÕÍðšb´GÌçþ[Uþç,Ú§ $„,jY¦õ¼¦m¬³¦}½ÌØþŒ¼ªZù¢iå³sü±{Ÿ°¡ Ö›[ûü&¾aYv@¤Œ6?¬÷c²&ý¡ÍODþÉc}ýRàgjÌ¢õ}bO>ù¤>øÇ*ýïfßœM¤ $ܱyºœ\}¬lìØ¸V>;ŽlìXüQaŽÃ.]æÔ¾WÏ £q!þØØgõêÕÚ¸\,·`ºf+ ãÄ„å¢ÀÏêqØòó ŒPS ?˜?>fw‹» 섟BHjìëi–‹–þ—¶Ö&ÆuÔËÔX_' Ò<±ÈŒ|öžzãQéñ×{üa¼Pð‡áJ¨½ÀãݦýsmöGà 5øÇ(úw3PüýÓ"Â&þµ]C弯Ï;ÚÐHüÃ*¾¹~nHTøCôa° €K´÷á-¢ÿL‰³×†kÿfÑ¿jo\5sæÌ…Ò·ï?*ûK@ ¥ñ~r^Óé¶;ùá¦ñdž2Lígÿ¹a#é‹´?"f¬ó#êGôo6Ó?[† “FÂoý¿õÖ[úØßn±ßö7&>üC@ñ7êVø¥ÆÓ¤´ÒQäñgŸÝç¡Ç,Túëm~h³D±ŸÞæ—XéïE´žéÌÄß,úWõÛ§OŸþ–ôÝò×nýßé f!œØ:MÆtÖÙ~Öœ“ÅŸ©ýÌ?7¤ø‘êGÔA?hóƒØO˜0ADþÉ•þ¹öTg·öÿÁÌQû´‰³µ·ci!sýOi>ÚöëPm•‡ëü+V¬ÐŠý0ác~Ñf‰?XëG»¥Ù„Å Tþ£ýÏ%ü{ï¹çž—“¢ÿDá·ÛøGüjh!¾ @ý;kï©Ú[+Ðg>|øpFðY>ÚúöÇF>z›2.ìƒÑ¾X~I¬ôw+Î~1~«ècÕÒ*l»Åýè_ßDû4„ßrBË2¬gõ K¥šQiž©>㯅 b´/ÄéÿöövMð±‹Zü¬:.üXàgõ8«ÊeÚÕØßçäб¿v)»1À9þi!¾ ¦§ZNl>ÊòkpS‡ø˜­7ûM|ýüܬ¾ÇæÍ›µJˆ>züa üȺ åJ·Ï×Ë(ßÍcýcYà µ¥ñ˪àq·šþ·kô…ÀÓB|Ï™jØ]Ë_MM”——3‚ÏÒùðxô÷£Ê_oóÃǰÞ6?˜€ÒÒÒœ {6 ÕŽêãÝ>ø`òà§|9ø‡€â+êºjetç˯ð¸)ú£1p÷µˆ„‘êW[ÜjéÌõG¦E/ö³ªôª!@wÚÍPfèoK—.Ý*ÿ¤2ö××u4„Ü¡n‹§ï³ÞÞ7v¤Ÿý"¾~àS=Ÿªr×*ý‘ò×ÛüPh™Xé™þnŸŸß Öþ““øížx≧¢»-Í Å¯Ñ? !$§Lé'C»­ ÿúÇö¾Œà3"~DþXçGú3þ±ÆñG¥?ŽÄs­ÀÏìq0=¦UwÕ俵âlì¯]€]„Ò熬þlÓó}ågË3µŸ¹¯Eú•þC´ûaw?}ªŸ]¥®¢üLÓ.úöÙgg‰³-3ö—€â&¶7È€h˯IŽ@s%û9‚Oõ|Hó£Ú?±Ò_oóCÊ¿²²2¥ˆ=†C0ÓÀâÚ|ôüóÏ/“CÇþZ˜8üà !$¿9¾õËÏ£âSçÁgî¹ÌñG¡DiTÁ£Èó þ‰•þ¹ölTþ[Dÿ¢¢ÿ'åÐÊÿ¨‰ p’òç€O‰ !ÄsPõ?¬Ûºªßh[Ù ‹o®Ÿ†Ý ÕßÜܬ¾E¥?Šûôõþºº:mÉÅ­Èú¹00ù±XæÀÏo†*‚üä™gžYœý;ÝøÇ÷ci!¾àØÖ©–ŸGäH”©ýÌ<7¬ó#Õô7„b }Ðã?räÈ•þ~ŠÖ3ù8<]VÌ™3çqٿ寛Mìªÿ}K¾€@Ìg&$ÌTE+¤¡s”éçq3·‹þ™Úwþ=õ"ò‡øc¸†ü`yE³Ë ø™=Uÿ¸f¨¥… Ñ¿Ýà«~_ŽýÍGˆ4 !ùÄámµ«èÛ͆A|sýÜÐÖ‡J2(ú«®®>öwRéC€:d=¬xî¹çfDÿ‰GTÌûþ©+¬ „xúwxûË/ÁŽs?m ‚àa¦?Ö¼‘À´?½Ò¨ôÏ…°çÂ`¼±Ùv¿½Ñÿ¢Ù³g/ç3ÿ¬ûû~O€¢ü¹í«=ƒ02¦k”ôVš~‘?¦Ð1‚Oý|xãÆZ¥?ÒÞ¨ôÇÇôüÌ*ýD6H~fÃÈ_« €jûKŒþízÿÍ–Xæc €‘) „xÀäöq)EÿLí;û¨ôGÊ© »A ±Ò‘¿ÓJÿ\Eë™~2!fþe”Ïš5+9ú7kù ä¦?ùf¬Ä…€„ä€Âx¡Œë¨3ÿ|aá´t®…:#7!Ÿ*ýí£èoݺuZÔ«Wúc#%ˆ?Ì€¢u¯ ÝÐÐ[ùßžý›õý»Ùù€Ä@ìÍŽ(oË„xzÿûÅÍgúc=nîLí»ÿZ÷¡Â_Ÿì‡ÿ¨ô×·òÅÚ¿ŸÄÙ«sÚŒüÅ4ÄTôÿ‰Aôš-óÅ$‹¿]äíu{„˜Ô1Æòó0Aß\?7´õ!íßÖÖv ×K)cÇŽÕÄ•þ~ßÉ/çÄuA6Äê¡jÇ¿Gåе³â¿@nù›O«,€þ~,Á´Ï;vÖ)ê-zŽŠ{\“„£ áˆ$b`8"BH~1x?ñmâßI‘*î+¿ô‘oüFý¥Vøa·?/Zÿ2rƒñ‘1@u; þ v¨ôG €^é·‰¦*HéûäǺ}œ“¶?•1ùÛ+¯¼²ÒEôÈ-ó͘ â¡ÿ"ñ‹oé}[”p81 ?ÉcÑ·~ýÀßMñ™gž9^ |YªÑ˜#øTÏ…?TúãÀt?ÐÐР ?Öû­*ýƒfÜ>Æ™¡ B÷ôéÓýwf úlAy €UÊ?ñsV&¿äný5‘ð±¢ñ/L¸‘YehH>Gþf⿟¢ã?~²Õ7u[ü—ÏÆÑ-ŠüPÜ€ÍmPÜ7nÜ8-åñ/**: ša-ð3{Úþ°Õ±K–,yaÁ‚› @ÞEÿaÊ™3—fôKš<¾ ÷ó 74a€Pü‰Lÿ:µ}˜Ù7E¥ºQk÷8ô|fƒb?ù¡âí~X>A±*ýý£›"—âœkC`·ÛŸ2mwÞyçL1Þñ/o¢ÿ0'f –tcJ~³¯OŽþ n~B#@húAÂßOL­GWªÙþ¦ýýËq¿ö Â¢ñÇz?ŠþpíÐæ‡B?ôùûQœ“›M#kƒÃ ù?­2(;Åxê_&¢€‹Ü"  hÂ[3ñOŒþ¹þO(ü}E_’„?Ñèf¹H­ÿO²ú;ˆù]|sýÜ0Εþz±25552fÌ-òÇûA™à—­Ì–FÐögc¢vß|óÍODÿVÃÜFÿœè#C`$þ—â_ Ækÿv±·ÊEþÉêx³oˆµëÄêÿ¬ÜÞQ€>XëÇ[˜6ÿÐ9ñÆSO=…‘¿Å?ôÑX €YÕÄà3ýäåDá/0¹ñ1ú'ùý‹þ%Fÿzv ®DËtû?ˆXrû_¾ûÅ_DüèñÇX_ ³Á?Úü0ÞÑ¿™ø%ZÏäc1ùЮðmùË_¦KßÂ?£Vp'3ÿCý‡1(þf¿œXÒÍ,Yücâ|ÝŸ€ä›0[û×—Ñô¯ÓÞWûÏ7˜}cLªãšÿÁï¶>}?´ûAÜñc¦?Úüô­’ó±ÀÏ챘‚ˆŒ‰ï¾ûîÌ•+Wnç}ÿyý‡ÉØM42‰¢OzkÔæDÑ'ù"ôfŸ3öShðõÚߘ®ÑfßÔ¬ú?÷hllÔŠüÍêc}õJDýV“óÕ`.Ú"­PŸß¬Úþ戻¡?1 ÑŽù–A·Ê$ÞÐâ&ÂO@òÙØ ý1ÿ¸êï/T3þMa];L|ªçƒè£ÚˆŸÃLŒõE›2%n¿&DÖïFÂ.õ/Sëþ÷*£ ï÷Ò#îZþb‚ÿòÅ­û›™€¸X§ùüÑ|2FÅÉéP}¶†f >ûÙÏŽRëÕÅV Ÿ×üñ9ìä‡k0ÞÃ~0ÆëýHý£Ò3ýígúœ0Jv=ÿj9eþŒ3>㿘˜ÿYeBý‡1àÆ™qõÓ|3‰™²‚¤¯Ñ#ÿŸ4i’iôoT˜iñõƒ‰0ëûXïG{ŠýPü‡%Œõ­®®¶¬ôÏwCà$õ¯ê:î¸ãþµ‹qáŸQ&À*ò]ôF`g̾6î ê§à“|~#P`ùG’n¤%b¦ QüómÜ/*û!þˆbùà `2"ˆ?Öüñ}Ü>ÿ|0÷»cÇ»žyï½÷ž\¼xñf1Ný;]q^@`g¬>O@húŠÉ¡Ó6ù*=Êì›;Yÿ£1@ôŠ6?}ÍŸÓ+ý!þ¨ôOü¾¬øï 2&0PV¨¯YuÍ5×`Þ?RÿÝ)Š wùËw`f$IÜ“72%Úô!Ÿü7’ü·“¾iÿägDŽt’ÈêMÀGèíG¥?„`_Jµ[¢e¥¦EÖÏFÂì¹vvvjÝV¨lJ×í·ß~«zÛ*wû3úc7õ/ÔÑØ €‘ 03bõÇý“<#n`’_ÿ‰¢ot3Ô– Êˡ95a÷«o胔?Œ@b¥?Rþz¥˜¢õL>ÎaÕ¿ÌŸ?ÿ‰wÞygX§þýåEyrC‹8¼Ñ™EDŒþ 1ΉD¥²U–¿¤ÆôÆSäìÖc°yófM¼0ÖÃ~ð³c¦?Rÿ0FÙVü÷Rÿ«¯¿þz=õß%é¥þCýç‹°‹äíÖú)þ$Þ.Sfõw9ú裇ʡ3\¿ƒTž Öôt?ÄëôJµI’Öãït¬o>Ìù·«úGêÿÎ;ï¼U™·©£ €F0B#@Á'ùÑýXÔšQ ŠÚ†›žLÝØÑï”>•ç†õõë×k[ùb¬/¯ÏôWµÚš¿^éïרÛ†¦ Ýv êÿ­·ÞZ-ÖÿÌ6û‰IÈGþÒ˜ÿ¹¾Oò³,XÜ$`e$´C¥¶‡š}Ä?Ìkþ¨ô‡øcÈÏ–-[´!Ý?fÌ­Ò‡Ñ÷Ïç?³¯ƒø£MÒ ¤þ¯¾úêÙr°ê¿GÌÿDŠ^„E¼÷þ‚i H¾ÿMD\DüÉ;œÒúÐ÷@ªÂV?þ#F`S$Í À?gC±$Ì”j™¥ç¾ûî»#¡êßMôïtÚ_hÍ €sS@H‰80Nßgn€Zë®2{€›ílsÁ§úÜУñW;ÏiÅ~‰•þØÍ•þ~Y¿'-@Uü?6oÞ¼•²?õo%üQaá !ÄÔ즪„Éû(Ðßì‹õõÿ°¬ùãkQè‡jŒõEµº^éÁ>hó³{LCÐ÷k‘ú·›ö§–W]{íµ‰ì¢«ô^4„·Q¿.ö“ÿG¬ €hiTúCøÑãb?¬W'Vú#ò7*xt*–aYÏwsN,Ømô£2Í7Üpƒ>ðG/üK§ï?o ÿh!™ÂÐ¨Ž–‚<î"áGÁÚý@b¥?ÖüõÇçûz¾ÓÇ¢å»"Ú}ùìÙ³o[¾|9*,“×ýͶü52yYøG@IUìEÌwÇ<°O€JyW:1^‹}¦ŒÒü~ô÷cH @ªôèÑšø#ú·KsÓj¨ôkiÅ¢E‹þúÐCÍëYÿVÑ^þÑBÒ5fFêQ £E€ÙˆàSýÚ––Mü±Þ¯G«¨ôÇ559¥óç³!pºËZþþøÇ?>(û·ù5kù3[û;0y•   „¤› 8d+mµà8¤™MMMZ‹Ä•êøYÐßÁ>½Ò?(Q·_ž+"»uÿŽŽŽæë®»îeÀ0ÐiêŸ=ÿ4„¯ ª€/TGZK~4)ˆ¿>Ö•ýXïGºÀÉxã|/ð3ýþh›´û¶O<ñÄ­ .Ü(Ίþ£3ñ·~vBH’À›e|LÂ¡ç­ ]àc€ô4&ú¡Ðÿ/++ÓÄE(öÓ§æC´žÉçŠA?0v¨Q¿3üñ÷äЖ?3#à¦÷?/£BHºf y@DÁ¹¾¯øu&"}½ÅO니=þXëO¬ô÷«ÈúÕèEvëþªÍòcµî?Cö¯ûwÙDÿÉUÿN¶úçcôO@q"ö‡ŠŠŠ’L<—Ækü˜ì‡õ~}¬/¦úÕ××k‘?Œ@£n?<ó0ìÙ+T‘åÖßþö·7'úMŒþS­üÏë@4„¬dTdœÒ}ÅOû )ÿ+VhUÿÂ-|!üˆþYà—Úãð9DþÈ®X¡2m7ß|óu*ó‚Þ@¬û'¶üY™€äÂ?¦þi!YÊôùœš„—ÑûŠ×3P鯷ù©Ês­f)¤û!þÉ•þF¢Ç?óÇ!›‚ìŠ*3›1cÆ-óçÏÇ¿‰ýþV•ÿnÖü%ߣBH¦ AD d±ñ“1€8­[·î@¥?ÆúêÅ~ØÆWµ7æU´žéÇÂ\9¨ø—·ÞzëQŠþŒúýíÖÿ¶ûåu !$ã(‘Lù¾’«}ô }ùë•þ}Dþ¨øGb¥¿ŸEÖ¯†Àá˜_d^^¿æškžã¢?3gÛý2õO@ÉVF ÓKÙŠöu ö(öK¬ôÇ&>ØÊâ´¿Yë" ³Ç¢ÝÛ%Û±uëÖEW^yåêÝ6—âû¢?³h?oÍ !$%¡7û¿ËB7‚â•Ø}­¾¡ÏÊ•+Túc¤omm­V臹þ\ÏOïq¨£p"þjy`ÃÏþóë1ñOý¹£èßJèYH!™BµlÅrýœD¥‰•þˆò±™¦ú©VFíÈÇh=“çĦI;Ó§Dïÿ*Tk \X‡CñO¥å©BH¶PÞ=6!k¢îô{`-ëýˆü¡b¬ï„ 4ÑGÊÅAY¿}Ð]¯?Úýn»í¶«?ùä£1¿NÚýìÖýÍ¢ý¼74„tˆDsÝn„%]±wk P‰Žõ~½Òëü´÷¡Ò3ý½ØÉ/̆À©ø+3ØýàƒÞ0wîÜårhÅ8Ÿùï6êg&€€’IñªÍ«ËêAv¢-c€ÿcËY´ùáÀó€à;V‹øñ~b± üR{¬SñWŸÎœ9óÖY³f-ƒÿf©ÿd#`ý' }Þ·üÑB²M\€žt3™6#5S^~ýaÆI]]–þ‡øÛ‰ üì ñG1¥“õÕW§?ðÀoJßv¿ä ~ìRÿqáº? !ÄìÛ·/#€L­ù#Íñ×+ýñ=1Ösý‘öG¿*çã(ྠà×׉ÁSƒ~Wc~Ÿ—CÛýìvùsjÌ¢}šBH¶PvÝ™0™0(ðCÄ¿|ùr­Òëûîƒö>´ùá’Èúõ¹b´occ£#ñÿý÷g_uÕU3Å<íof’ßí Š? !$‹ÄÕþîݽ7ÛHº 5>ü ÍFëüz± €U¥? ósb´¯ú;úúÅ‹¿¤v÷{´7òïã‚?»èßÌ$ =×ýi!^‰¿þŽªîîT£s wͱÛ.Æ‚¤·ùá|Hóc¦?fùCüõJÿ GÝ~x®0YNÆû‚¥K—¾|ÅWÜ£Þ5ÛÚ×éö¾õK@ñ‹à'\‰n›™Hu€SáB:æùãÀÿ±Ö5ûAüÆú²ÀÏÝsÅÿU­‡£}€j¹|SøMÿ.›è?Õâ?£×%Í !Ä#Çp•b˜ àtK Û·oׄ©€*Tûëâïר;H™üþ0KENX¶lÙ<ùß©×"Güµ÷ ¿“ˆŸE4„ŸdZ­„bm¶ÁN*Æi~läñÇ®~øÞèïÇ.~Xë7ëËõ|÷C›ŠýœÖq,\¸ð5ßÿ>Ù¿æŸ8ßß*âwýÇ„E4„ÿ™%­vQdº@èj9l#«ÍÇ:ÿĉµb?LùÃô¨ÛÏ×µç8ÄçÏŸ?óøÃ ‡âŸJÚ?YèYôG@É5*=Übg–O%ÚO{Ì#ò‡ø£ Å~hóÃ÷FÔ3m¡ Rf!•窯÷£“Âé)ÔŸn¼ñÆç\ˆ¿“´¿QÔÏ¢?Bˆ—¾A´•øÿ˜ Ë @&: JˆüQéý( ¢Š5#€Jÿ|Ö3õ8¤ü±Þï4åÙþÏ>ûì]ŠyrpÈ“ùþN6ûaÑ !ÄçÆK–‹ëoÞ›À[LœCÁ"£1B;tñ·Z^ !°Þ"»â´Ê(ÖtÏ=÷Üô /,–C‡ü¸í÷§øÓB‚h”p4eÚèÂáÇÝüð ÷Á,]üÝŽ¦!8ôwƒìŠ›n Õz¹öÿ÷o\²d 6Zègm~FóþÝTýSüi!9Žø“‰©b±ÝVLe ‚áÇŽ~¬óc¸Æùb­Å~º°±ÀÏýãæÇ`kýjƒ¥÷ñ‹_ÜÖ„µ‚ýâï$ê7«Iq›×"¡ „x,ø’•ÅUŠ~O& ÒüzäýPàñÇ:?ªýqx!²a+ðÓƒ ¤üÝìÔ¨ CÚÔçÉk®¹æi9Xì×#Ƴý­ÄßIÑ_ÜàuFñ§ „øÀ$¾© xvÛEóNg@œõ£¿Æ RSS£õøCàõ#ú×…‹ëù·ϣµÂïvƒ&Õq±ýþûï¿ýÅ_\"SþÝ¢µÿÄ·f›ü˜‰?¡ „dYÜ#&7̨Êü]vßkÍvò µ£}!þØÕ…~µµµšq@ê_¯ô÷«ÈúÕ £‚¿T–bV¯^=_õ÷ß½sçÎF1NùGm"~#ñONùÇŠ?Í !$¦@LnÐq©·ª¨²S µ©ÂC„¬ –”1u›ú ê)LöC±ÄßIö€† /ˆø!ü©ìÇ ~_­sæÌ¹ÿ¾ûî{S¬·ò5û¿•ø;™òGñ§ „äHôͲFo1  Q õp+`&h*ºÔ Òò‡˜É©Š? !Äg‚q)øÉ)[-ÂS©û­V'Â:4D ‘= âAüñ9RÔ àÿ\Ï7fJ?RöuÔVÊ ~øáÇß|óÍÕ½Âß%Öã{FývBˆOÍ€þ³­WoÞ1U¸·Íî~ žA¥?„K‰Vè‡V?½Íëþ~Žºsé#S‚#¢TÁå†Y³f=>{öìåÐi~fsûÍD¿'AôôúSüi!4 É7gí&¯Öð79µ0jÉà@…?Rþfâo'–AZÏwúXÔGè¢ÌI&D¨VËj÷¾Y¨îW3áwbœÌô·šðGñ§ „Pø“·D?øàƒMßùÎw,¿‰.þÈôïß_[ë‡èCü+ýƒ­§j^ øz]ðS­à7CkÞª&ù½pï½÷þ­w÷ÆÄa>f‡[á·Zï§øÓBBbú˜•ÎoQâÕ¬Öï«ìÄëü¾Dñr´îöqøZ½&B›©?U›±éí·ß~ùÎ;ï|]«Ý¡ðÛmÝk¶ÖoõSüi!ŽünÖúÍ>ªzÏ·©ú, @¢0BüЯŽ%€Ä_c4ø'h†"yüœºèëc‘³ý{S†lѼyó^™1cÖø; „?æÂX rÔïd;_Š? !ħ¢¯i°:¢ª|‡2\,A“ÑÍ€nô÷Í ‚׆@ùd±Ç[ÙŠêÍP©ýæåË—¿£Šû^]°`Áfé»aO, ñ¥õSüi!4‹¬@⡉€*òÛ„ùý™ÂI¤œh ÿ¯ˆD·údqO|« º~‰œü’TÿÖ­[—«Œ·zè¡ù*£’<À'f¹Û‰½UÄïDøjG(þ4„€eì {ÔT¿µS§NõZ}!Ä^ƒÁK‹/~gæÌ™o¬X±b§:µ/Y¬í €ð[¥ûÍ ý(þ4„€DúNf¦ÿq¨ôó§gžy&¯h–~OjÖ†O?ýôcµ-ïü÷ß)þné;±Ï(B7~«%³ïc'üN·ó¥øç€/!ÄæÞI: ŽÂÞ£(á(î=ÊTEõƒ>øˆè3‚—4}TWEç–-[–/[¶ì“^xaÁªU«öÈ¡ó˜­É[e¬Öõí"~'é~Š? !$ âÀàm L€:*Ž9æ˜úÓO?ýØúúúÃKX‚P+NŒÔÕXÞNõ6® ðÚ•¨koÕ.†8ÚÔN|Úû*šoV#v›Ô|ý}*}ߨÚ÷*¡oRkø=6ÑyÜ&²6}7Ñ¿]V nó¼ì*û™ò§ „„܈X/Õ$‹~âÛ‚$`$üN10 f_“ü«ŸÙLÄŒö>°q}z‘Ñ[»iŠfÑ¿YzÞ­ ˆ;ˆöcb¾çƒðSü} çBœ`40Y$"IïG“7ùq…½_ëÔˆ‰€[}˜|}º×ÂÊ$~,fò9'‡Sñwc쾇“ç%BH~Š~¢°™€Ä#j"’1ñ/0È2ˆK3 6ï§c¬RÛv†À‰ 0‹¾Ý.8z ? !„¤ '§»ÍÐ…Èmôï$•ïÔ dÃ8Í ¤ý»1F-{©Š¾Sá§øÓBB˜0,&Âo¶s`AÂ×§³öo—pbÜ·‘¿ø‹MäoUWàÔ¤"øN«úõÓBHÁˆ™|>Ñ87…|nÅ?’Ÿ5Uñw’ ˆ‰»e7n¢|Fý4„ ¼m@„=f"þqáwý›™€t²V·‹tÍ2é.¸É¤áSø !$mCàÆÄ\FýÙŽþs±i3ŽàÛ‰=…?Äp!$•û…U+ž™°»}§Q¿W~1"™| ?ÿ  !ÄõýÂÎDl„¾ h?Õ´ÄÅÏçTSépcÄÅÇí„>Õú(ü4„Þ3›;Sà¦Âßíz6ZÓÉX s<…ÿ»‰îÓÕKñ§ „Ç&À©É|¤Ÿ©Ö¿l™§ÙtDž¢Oh!žšgc{~>U±wõ§[`%°™4©<…ŸÐBrj2!îN¾¯Óç•iŠ»s'Ÿs"òñ6B@!Žï!nÛM$ï4ÂÏFÚ?ÝŒ@:Q{ª‘}<ÅŸÐBHZ÷‘TÛm4Ÿ­h?S&Àîÿ©~Îé¹)ú„€â #à4Bwŧígº0QΤ¸Sô !Ä÷÷7‚J4ÉÀsLWLã9ú8EŸÐBqo‰dùó^ÝãÒÀ3Y GÑ'4„@Þg"YøžÙ¸ßųôõqž !…¼„~ Vâ|,!ÌBByÿñË=-îÓïE !„÷%ŸA¡'üC#„߯(ô„P„²{ÅB!„B!„B!„B!„xÊÿ½Œ£ŒXçIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata/ico/ico.qbs000066400000000000000000000034371347155106100227240ustar00rootroot00000000000000Project { Product { Depends { name: "ico" } type: ["ico"] name: "icon" files: [ "icon_16x16.png", "icon_32x32.png" ] } Product { Depends { name: "ico" } type: ["ico"] name: "icon-alpha" files: [ "icon_16x16.png", "icon_32x32.png" ] ico.alphaThreshold: 50 } Product { Depends { name: "ico" } type: ["ico"] name: "icon-big" files: [ "dmg.iconset/icon_16x16.png", "dmg.iconset/icon_32x32.png", "dmg.iconset/icon_128x128.png", ] Group { name: "raw" prefix: "dmg.iconset/" files: [ "icon_256x256.png", "icon_512x512.png", ] ico.raw: true } } Product { Depends { name: "ico" } type: ["cur"] name: "cursor" files: [ "icon_16x16.png", "icon_32x32.png" ] } Product { Depends { name: "ico" } type: ["cur"] name: "cursor-hotspot" Group { files: ["icon_16x16.png"] ico.cursorHotspotX: 8 ico.cursorHotspotY: 9 } Group { files: ["icon_32x32.png"] ico.cursorHotspotX: 16 ico.cursorHotspotY: 17 } } Product { Depends { name: "ico" } type: ["cur"] name: "cursor-hotspot-single" Group { files: ["icon_16x16.png"] ico.cursorHotspotX: 8 ico.cursorHotspotY: 9 } } Product { Depends { name: "ico" } type: ["ico", "cur"] name: "iconset" files: ["dmg.iconset"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/ico/icon_16x16.png000066400000000000000000000012111347155106100237320ustar00rootroot00000000000000‰PNG  IHDRóÿasRGB®Îé pHYs  šœiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ"IDAT8cü & ô‚µŽÀÀ0£aÊ ŸkÊ ÔIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata/ico/icon_32x32.png000066400000000000000000000012311347155106100237300ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®Îé pHYs%%IR$ðiTXtXML:com.adobe.xmp 4 4 1 #ÆÜ2IDATX íÐA 1À¿g ˜àÓ¸¥Ù»x\=¶/í @€ 0Mˆ<òß^ßIEND®B`‚qbs-src-1.13.1/tests/auto/blackbox/testdata/import-assignment/000077500000000000000000000000001347155106100243425ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-assignment/import-assignment.qbs000066400000000000000000000010401347155106100305240ustar00rootroot00000000000000import MyImport Product { type: "outtype" property var importValue: MyImport Rule { multiplex: true Artifact { fileTags: "outtype" filePath: "dummy" } prepare: { var cmd = new JavaScriptCommand; cmd.silent = true; cmd.sourceCode = function() { console.info("key 1 = " + product.importValue.key1); console.info("key 2 = " + product.importValue.key2); }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-assignment/imports/000077500000000000000000000000001347155106100260375ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-assignment/imports/MyImport/000077500000000000000000000000001347155106100276175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-assignment/imports/MyImport/myimport.js000066400000000000000000000000521347155106100320320ustar00rootroot00000000000000var key1 = "value1"; var key2 = "value2"; qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/000077500000000000000000000000001347155106100252175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/custom1command.js000066400000000000000000000001101347155106100304770ustar00rootroot00000000000000var Irrelevant = require("./irrelevant.js"); function sourceCode() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/custom1prepare1.js000066400000000000000000000002321347155106100306050ustar00rootroot00000000000000var CustomPrepare = require("./custom1prepare2.js"); var Irrelevant = require("./irrelevant.js"); function prepare() { return CustomPrepare.prepare(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/custom1prepare2.js000066400000000000000000000005371347155106100306160ustar00rootroot00000000000000var Custom1Command = require("./custom1command.js"); var Irrelevant = require("./irrelevant.js"); function prepare() { console.info("running custom1 prepare script"); var cmd = new JavaScriptCommand(); cmd.description = "running custom1 command"; cmd.sourceCode = function() { return Custom1Command.sourceCode(); }; return cmd; } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/000077500000000000000000000000001347155106100301725ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare1.js000066400000000000000000000000001347155106100335520ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare2.js000066400000000000000000000004551347155106100335710ustar00rootroot00000000000000var Custom2Command = require("custom2command"); function prepare() { console.info("running custom2 prepare script"); var cmd = new JavaScriptCommand(); cmd.description = "running custom2 command"; cmd.sourceCode = function() { return Custom2Command.sourceCode(); }; return cmd; } import-change-tracking-product.qbs000066400000000000000000000024001347155106100336560ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-trackingimport "irrelevant.js" as Irrelevant import "custom1prepare1.js" as Custom1Prepare import "custom2prepare" as Custom2Prepare import "probe1.js" as ProbeFunc Product { name: "customProduct" type: ["custom1", "custom2"] property string irrelevant: Irrelevant.irrelevant() property string dummy: probe1.result Group { files: "input1.txt" fileTags: "input.custom1" } Group { files: "input2.txt" fileTags: "input.custom2" } Rule { inputs: "input.custom1" Artifact { filePath: "dummy.custom1"; fileTags: "custom1" } prepare: { return Custom1Prepare.prepare(); } } Rule { inputs: "input.custom2" Artifact { filePath: "dummy.custom2"; fileTags: "custom2" } prepare: { return Custom2Prepare.prepare(); } } Probe { id: probe1 property string input: Irrelevant.irrelevant() property string result configure: { found = true; console.info("running probe1"); return ProbeFunc.probe1Func(); } } Probe { id: probe2 configure: { console.info("running probe2"); found = true; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/import-change-tracking.qbs000066400000000000000000000001331347155106100322600ustar00rootroot00000000000000Project { qbsSearchPaths: ["."] references: "import-change-tracking-product.qbs" } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/imports/000077500000000000000000000000001347155106100267145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/000077500000000000000000000000001347155106100316475ustar00rootroot00000000000000custom2command1.js000066400000000000000000000000611347155106100351370ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2commandvar Irrelevant = require("../../irrelevant.js"); custom2command2.js000066400000000000000000000001141347155106100351370ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2commandvar Irrelevant = require("../../irrelevant.js"); function sourceCode() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/input1.txt000066400000000000000000000000001347155106100271660ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/input2.txt000066400000000000000000000000001347155106100271670ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/irrelevant.js000066400000000000000000000000571347155106100277320ustar00rootroot00000000000000function irrelevant() { return "irrelevant"; } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/probe1.js000066400000000000000000000001331347155106100267420ustar00rootroot00000000000000var Probe2 = require("./probe2.js") function probe1Func() { return Probe2.probe2Func(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-change-tracking/probe2.js000066400000000000000000000000561347155106100267470ustar00rootroot00000000000000function probe2Func() { return "probeData"; } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-in-properties-condition/000077500000000000000000000000001347155106100267565ustar00rootroot00000000000000import-in-properties-condition.qbs000066400000000000000000000000541347155106100355010ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-in-properties-conditionProduct { Depends { name: "amodule" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-in-properties-condition/modules/000077500000000000000000000000001347155106100304265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-in-properties-condition/modules/amodule/000077500000000000000000000000001347155106100320545ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-in-properties-condition/modules/amodule/m.qbs000066400000000000000000000002351347155106100330170ustar00rootroot00000000000000import qbs.File Module { Depends { name: "depmodule" } Properties { condition: File.exists("blubb") depmodule.prop: "blubb" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-in-properties-condition/modules/depmodule/000077500000000000000000000000001347155106100324045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-in-properties-condition/modules/depmodule/m.qbs000066400000000000000000000000441347155106100333450ustar00rootroot00000000000000Module { property string prop } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-searchpath/000077500000000000000000000000001347155106100243145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-searchpath/import-searchpath.qbs000066400000000000000000000003021347155106100304500ustar00rootroot00000000000000Project { Project { qbsSearchPaths: ["qbs"] references: ["src/import-searchpath-app1.qbs"] } Project { references: ["src/import-searchpath-app2.qbs"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-searchpath/qbs/000077500000000000000000000000001347155106100251015ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-searchpath/qbs/imports/000077500000000000000000000000001347155106100265765ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-searchpath/qbs/imports/CppApplication.qbs000066400000000000000000000000141347155106100322060ustar00rootroot00000000000000Product { } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-searchpath/src/000077500000000000000000000000001347155106100251035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/import-searchpath/src/import-searchpath-app1.qbs000066400000000000000000000000571347155106100321050ustar00rootroot00000000000000CppApplication { files: ["somefile.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-searchpath/src/import-searchpath-app2.qbs000066400000000000000000000000531347155106100321020ustar00rootroot00000000000000CppApplication { files: ["main.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-searchpath/src/main.cpp000066400000000000000000000000171347155106100265310ustar00rootroot00000000000000int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/import-searchpath/src/somefile.cpp000066400000000000000000000000001347155106100274000ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/importing-product/000077500000000000000000000000001347155106100243505ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/importing-product/header.h.in000066400000000000000000000000161347155106100263530ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/importing-product/importing-product.qbs000066400000000000000000000020751347155106100305510ustar00rootroot00000000000000import qbs.File Project { Product { name: "dep" Export { Depends { name: "cpp" } cpp.includePaths: [importingProduct.buildDirectory + "/random_dir"] Rule { inputs: ["hpp_in"] Artifact { filePath: product.buildDirectory + "/random_dir/" + input.completeBaseName fileTags: ["hpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Copying file"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return [cmd]; } } } } CppApplication { name: "theProduct" Depends { name: "dep" } Group { files: ["header.h.in"] fileTags: ["hpp_in"] } files: ["main.cpp"] } CppApplication { name: "theProduct2" Depends { name: "dep" } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/importing-product/main.cpp000066400000000000000000000023571347155106100260070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include qbs-src-1.13.1/tests/auto/blackbox/testdata/imports-conflict/000077500000000000000000000000001347155106100241565ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/imports-conflict/imports-conflict.qbs000066400000000000000000000002221347155106100301550ustar00rootroot00000000000000Project { Product { name: "Utils" } Product { Depends { name: "Utils" } Depends { name: "themodule" } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/imports-conflict/modules/000077500000000000000000000000001347155106100256265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/imports-conflict/modules/themodule/000077500000000000000000000000001347155106100276145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/imports-conflict/modules/themodule/m.qbs000066400000000000000000000001111347155106100305500ustar00rootroot00000000000000import "utils.js" as Utils Module { validate: { Utils.helper(); } } qbs-src-1.13.1/tests/auto/blackbox/testdata/imports-conflict/modules/themodule/utils.js000066400000000000000000000000561347155106100313130ustar00rootroot00000000000000function helper() { console.info("helper"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/includeLookup/000077500000000000000000000000001347155106100234775ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/includeLookup/includeLookup.qbs000066400000000000000000000004601347155106100270230ustar00rootroot00000000000000import qbs.FileInfo Project { property string name: 'includeLookup' qbsSearchPaths: '.' Product { type: 'application' consoleApplication: true name: project.name files: 'main.cpp' Depends { name: 'cpp' } Depends { name: 'definition' } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/includeLookup/main.cpp000066400000000000000000000024501347155106100251300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { printf("%s..\n", TEXT); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/includeLookup/modules/000077500000000000000000000000001347155106100251475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/includeLookup/modules/definition/000077500000000000000000000000001347155106100272775ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/includeLookup/modules/definition/fakeopenssl/000077500000000000000000000000001347155106100316115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/includeLookup/modules/definition/fakeopenssl/sha.h000066400000000000000000000000001347155106100325230ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/includeLookup/modules/definition/module.qbs000066400000000000000000000005161347155106100312750ustar00rootroot00000000000000import qbs.Probes Module { name: 'definition' Depends { name: 'cpp' } property string modulePath: path Probes.IncludeProbe { id: includeNode names: "fakeopenssl/sha.h" platformSearchPaths: [modulePath] } cpp.defines: includeNode.found ? 'TEXT="' + includeNode.path + '"' : undefined } qbs-src-1.13.1/tests/auto/blackbox/testdata/innosetup/000077500000000000000000000000001347155106100227065ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/innosetup/inc/000077500000000000000000000000001347155106100234575ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/innosetup/inc/qbsinc.iss000066400000000000000000000000001347155106100254440ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/innosetup/innosetup.qbs000066400000000000000000000011371347155106100254430ustar00rootroot00000000000000import qbs.FileInfo Project { InnoSetup { name: "QbsSetup" targetName: "qbs.setup.test" version: "1.5" files: [ "test.iss" ] innosetup.verboseOutput: true innosetup.includePaths: ["inc"] innosetup.defines: ["MyProgram=" + name, "MyProgramVersion=" + version] innosetup.compilerFlags: ["/V9"] qbs.targetPlatform: "windows" } InnoSetup { name: "Example1" files: [FileInfo.joinPaths(innosetup.toolchainInstallPath, "Examples", name + ".iss")] qbs.targetPlatform: "windows" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/innosetup/test.iss000066400000000000000000000001641347155106100244060ustar00rootroot00000000000000#include "qbsinc.iss" [Setup] AppName={#MyProgram} AppVersion={#MyProgramVersion} DefaultDirName={pf}\{#MyProgram} qbs-src-1.13.1/tests/auto/blackbox/testdata/innosetupDependencies/000077500000000000000000000000001347155106100252155ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/innosetupDependencies/innosetupDependencies.qbs000066400000000000000000000043631347155106100322650ustar00rootroot00000000000000import qbs.TextFile Project { InnoSetup { Depends { name: "app" } Depends { name: "lib" } name: "QbsSetup" targetName: "qbs.setup.test" version: "1.5" files: [ "test.iss" ] innosetup.verboseOutput: true innosetup.defines: [ "MyProgram=" + name, "MyProgramVersion=" + version, "buildDirectory=" + project.buildDirectory ] innosetup.compilerFlags: ["/V9"] destinationDirectory: project.buildDirectory } Application { Depends { name: "cpp" } name: "app" files: ["main.c"] Group { fileTagsFilter: product.type qbs.install: true } destinationDirectory: project.buildDirectory } DynamicLibrary { Depends { name: "cpp" } name: "lib" files: ["main.c"] Group { fileTagsFilter: product.type qbs.install: true } Rule { // This rule tries to provoke the installer into building too early (and the test // verifies that it does not) by causing the build of the installables to take // a lot longer. multiplex: true outputFileTags: ["c"] outputArtifacts: { var artifacts = []; for (var i = 0; i < 96; ++i) artifacts.push({ filePath: "c" + i + ".c", fileTags: ["c"] }); return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { for (var i = 0; i < outputs["c"].length; ++i) { var tf; try { tf = new TextFile(outputs["c"][i].filePath, TextFile.WriteOnly); tf.writeLine("int main" + i + "() { return 0; }"); } finally { if (tf) tf.close(); } } }; return [cmd]; } } destinationDirectory: project.buildDirectory } } qbs-src-1.13.1/tests/auto/blackbox/testdata/innosetupDependencies/main.c000066400000000000000000000000311347155106100262770ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/innosetupDependencies/test.iss000066400000000000000000000003221347155106100267110ustar00rootroot00000000000000[Setup] AppName={#MyProgram} AppVersion={#MyProgramVersion} DefaultDirName={pf}\{#MyProgram} [Files] Source: "{#buildDirectory}\app.exe"; DestDir: "{app}" Source: "{#buildDirectory}\lib.dll"; DestDir: "{app}" qbs-src-1.13.1/tests/auto/blackbox/testdata/input-tags-change-tracking/000077500000000000000000000000001347155106100260005ustar00rootroot00000000000000input-tags-change-tracking.qbs000066400000000000000000000035471347155106100335570ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/input-tags-change-trackingimport qbs.TextFile Product { name: "p" type: "p_tag" property string generateInput Group { condition: generateInput == "no" files: "input.txt" fileTags: ["txt", "empty"] } Rule { condition: generateInput == "static" multiplex: true Artifact { filePath: "input.txt"; fileTags: ["txt", "empty"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var out = new TextFile(output.filePath, TextFile.WriteOnly); out.close(); }; return cmd; } } Rule { condition: generateInput == "dynamic" multiplex: true outputFileTags: ["txt", "empty"] outputArtifacts: [{filePath: "input.txt", fileTags: ["txt", "empty"]}] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var out = new TextFile(output.filePath, TextFile.WriteOnly); out.close(); }; return cmd; } } Rule { inputs: "txt" outputFileTags: "p_tag" outputArtifacts: { if (input.fileTags.contains("empty")) return []; return [{ filePath: input.fileTags.contains("y") ? "y.out" : "x.out", fileTags: "p_tag" }] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var out = new TextFile(output.filePath, TextFile.WriteOnly); out.close(); }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/input-tags-change-tracking/input.txt000066400000000000000000000000061347155106100276740ustar00rootroot00000000000000empty qbs-src-1.13.1/tests/auto/blackbox/testdata/inputs-from-dependencies/000077500000000000000000000000001347155106100255715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/inputs-from-dependencies/file1.txt000066400000000000000000000000001347155106100273200ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/inputs-from-dependencies/file2.txt000066400000000000000000000000001347155106100273210ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/inputs-from-dependencies/file3.txt000066400000000000000000000000001347155106100273220ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/inputs-from-dependencies/file4.txt000066400000000000000000000000001347155106100273230ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/inputs-from-dependencies/inputs-from-dependencies.qbs000066400000000000000000000023331347155106100332100ustar00rootroot00000000000000Project { Product { name: "TextFileContainer1" type: "txt_container" Group { files: ["file1.txt", "file2.txt"] fileTags: "txt" } } Product { name: "TextFileContainer2" Group { files: ["file3.txt"] fileTags: "txt" } } Product { name: "TextFileContainer3" Group { files: ["file4.txt"] fileTags: "txt" } } Product { name: "TextFileGatherer" type: "printed_txt" Depends { name: "TextFileContainer1" } Depends { name: "TextFileContainer2" } Rule { inputsFromDependencies: "txt" multiplex: true Artifact { filePath: "blubb" fileTags: "printed_txt" alwaysUpdated: false } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Gathering text files"; cmd.sourceCode = function() { for (i in inputs.txt) console.info(inputs.txt[i].filePath); }; return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates-no-error/000077500000000000000000000000001347155106100262245ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates-no-error/file1.txt000066400000000000000000000000001347155106100277530ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates-no-error/file2.txt000066400000000000000000000000001347155106100277540ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates-no-error/file3.txt000066400000000000000000000000001347155106100277550ustar00rootroot00000000000000install-duplicates-no-error.qbs000066400000000000000000000013541347155106100342210ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates-no-errorProject { Product { name: "p1" Group { files: ["file1.txt"] qbs.install: true } } Product { name: "p2" Group { files: ["file1.txt"] qbs.install: true } } Product { name: "p3" Group { files: ["file2.txt"] qbs.install: true } multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] } Product { name: "p4" Group { files: ["file2.txt"] qbs.install: true } aggregate: true multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates/000077500000000000000000000000001347155106100244635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates/dir1/000077500000000000000000000000001347155106100253225ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates/dir1/file1.txt000066400000000000000000000000131347155106100270550ustar00rootroot00000000000000dir1/file1 qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates/dir1/file2.txt000066400000000000000000000000131347155106100270560ustar00rootroot00000000000000dir1/file2 qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates/dir2/000077500000000000000000000000001347155106100253235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates/dir2/file1.txt000066400000000000000000000000131347155106100270560ustar00rootroot00000000000000dir2/file1 qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates/dir2/file2.txt000066400000000000000000000000131347155106100270570ustar00rootroot00000000000000dir2/file2 qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates/dir2/file3.txt000066400000000000000000000000131347155106100270600ustar00rootroot00000000000000dir2/file3 qbs-src-1.13.1/tests/auto/blackbox/testdata/install-duplicates/install-duplicates.qbs000066400000000000000000000002071347155106100307720ustar00rootroot00000000000000Product { Group { files: ["*.txt"] prefix: "**/" qbs.install: true qbs.installDir: "files" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/install-locations/000077500000000000000000000000001347155106100243215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-locations/install-locations.qbs000066400000000000000000000011641347155106100304710ustar00rootroot00000000000000Project { property bool dummy: { if (qbs.targetOS.contains("windows")) console.info("is windows"); else if (qbs.targetOS.contains("macos")) console.info("is mac"); else console.info("is unix"); } CppApplication { name: "theapp" install: true files: "main.cpp" Group { fileTagsFilter: "application" fileTags: "some-tag" } } DynamicLibrary { name: "thelib" install: true installImportLib: true Depends { name: "cpp" } files: "thelib.cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/install-locations/main.cpp000066400000000000000000000000161347155106100257460ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/install-locations/thelib.cpp000066400000000000000000000000701347155106100262710ustar00rootroot00000000000000#include "../dllexport.h" DLL_EXPORT void libFunc() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/install-root-from-project-file/000077500000000000000000000000001347155106100266335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-root-from-project-file/file.txt000066400000000000000000000000001347155106100303010ustar00rootroot00000000000000install-root-from-project-file.qbs000066400000000000000000000003671347155106100352420ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-root-from-project-fileProduct { name: "p" property string installRoot qbs.installRoot: installRoot Group { qbs.install: true qbs.installPrefix: "/install-prefix" qbs.installDir: "/install-dir" files: ["file.txt"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/install-tree/000077500000000000000000000000001347155106100232655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-tree/data/000077500000000000000000000000001347155106100241765ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-tree/data/foo.txt000066400000000000000000000000001347155106100255100ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-tree/data/subdir1/000077500000000000000000000000001347155106100255475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-tree/data/subdir1/bar.txt000066400000000000000000000000001347155106100270420ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-tree/data/subdir2/000077500000000000000000000000001347155106100255505ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-tree/data/subdir2/baz.txt000066400000000000000000000000001347155106100270530ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/install-tree/install-tree.qbs000066400000000000000000000003321347155106100263750ustar00rootroot00000000000000CppApplication { files: ["main.cpp"] qbs.installPrefix: "" Group { files: ["data/**/*.txt"] qbs.install: true qbs.installDir: "content" qbs.installSourceBase: "data" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/install-tree/main.cpp000066400000000000000000000023641347155106100247220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/installable-as-auxiliary-input/000077500000000000000000000000001347155106100267175ustar00rootroot00000000000000installable-as-auxiliary-input.qbs000066400000000000000000000050161347155106100354060ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/installable-as-auxiliary-inputimport qbs.File import qbs.FileInfo import qbs.TextFile Project { name: "p" CppApplication { name: "app" Depends { name: "installed-header" } Rule { multiplex: true auxiliaryInputs: ["installable"] Artifact { filePath: "main.cpp"; fileTags: "cpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.writeLine("#include "); f.writeLine("int main() {"); f.writeLine(" f();"); f.writeLine("}"); f.close(); }; return cmd; } } } Product { name: "installed-header" type: ["header"] property string installDir: "include" qbs.installPrefix: "" Group { fileTagsFilter: "header" qbs.install: true qbs.installDir: installDir } Export { Depends { name: "cpp" } cpp.includePaths: FileInfo.joinPaths(qbs.installRoot, product.installDir); } Rule { multiplex: true Artifact { filePath: "theheader.h.in"; fileTags: "header.in" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName; cmd.sourceCode = function() { for (var i = 0; i < 1000; ++i) { // Artificial delay. var file = new TextFile(output.filePath, TextFile.WriteOnly); file.writeLine("#include "); file.writeLine("inline void f() {"); file.writeLine(' std::cout << "f-impl" << std::endl;'); file.writeLine("}"); file.close(); } }; return [cmd]; } } Rule { inputs: "header.in" Artifact { filePath: "theheader.h"; fileTags: "header" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return [cmd]; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/installable/000077500000000000000000000000001347155106100231545ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/installable/installable.qbs000066400000000000000000000021471347155106100261610ustar00rootroot00000000000000import qbs.TextFile Project { CppApplication { type: ["application"] name: "app" consoleApplication: true Group { files: ["main.cpp"] qbs.install: true } install: true installDir: "" } Product { name: "install-list" type: ["install-list"] Depends { name: "app" } Rule { multiplex: true inputsFromDependencies: ["installable"] Artifact { filePath: "installed-files.txt" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs.installable.length; ++i) file.writeLine(inputs.installable[i].filePath); file.close(); }; return [cmd]; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/installable/main.cpp000066400000000000000000000023511347155106100246050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/installed-source-files/000077500000000000000000000000001347155106100252375ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/installed-source-files/installed-source-files.qbs000066400000000000000000000006271347155106100323300ustar00rootroot00000000000000CppApplication { consoleApplication: true files: ["main.cpp"] qbs.installPrefix: "" Group { fileTagsFilter: ["cpp"] qbs.install: true } Group { // this overwrites the properties of the group below fileTagsFilter: ["text"] qbs.install: true } Group { files: ["readme.txt"] fileTags: ["text"] qbs.install: false } } qbs-src-1.13.1/tests/auto/blackbox/testdata/installed-source-files/main.cpp000066400000000000000000000023641347155106100266740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/installed-source-files/readme.txt000066400000000000000000000000261347155106100272330ustar00rootroot00000000000000important information qbs-src-1.13.1/tests/auto/blackbox/testdata/installed-transformer-output/000077500000000000000000000000001347155106100265375ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/installed-transformer-output/qbs668.qbs000066400000000000000000000014121347155106100302750ustar00rootroot00000000000000import qbs.TextFile Product { name: "install-test" type: ["text"] qbs.installPrefix: "" Group { qbs.install: true qbs.installDir: "textfiles" fileTagsFilter: "text" } Rule { multiplex: true Artifact { filePath: "HelloWorld.txt" fileTags: ["text"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating file:'" + output.fileName + "'"; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); file.writeLine("Hello World!") file.close(); } return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/installed_artifact/000077500000000000000000000000001347155106100245165ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/installed_artifact/installed_artifact.qbs000066400000000000000000000005541347155106100310650ustar00rootroot00000000000000Application { name: "installedApp" type: "application" consoleApplication: true Depends { name: "cpp" } Group { files: "main.cpp" qbs.install: true qbs.installDir: "src" } qbs.installPrefix: "/usr" Group { fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/installed_artifact/main.cpp000066400000000000000000000023511347155106100261470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/installpackage/000077500000000000000000000000001347155106100236445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/installpackage/installpackage.qbs000066400000000000000000000022661347155106100273430ustar00rootroot00000000000000Project { CppApplication { name: "public_tool" Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } Depends { name: "mylib" } files: ["main.cpp"] Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "bin" } } CppApplication { name: "internal_tool" Depends { name: "mylib" } files: ["main.cpp"] } DynamicLibrary { Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } Depends { name: "cpp" } name: "mylib" files: ["lib.cpp"] Group { name: "public headers" files: ["lib.h"] qbs.install: true qbs.installDir: "include" } Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "lib" } } InstallPackage { archiver.type: "tar" builtByDefault: true name: "tar-package" Depends { name: "public_tool" } Depends { name: "mylib" } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/installpackage/lib.cpp000066400000000000000000000023711347155106100251210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib.h" void f() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/installpackage/lib.h000066400000000000000000000025601347155106100245660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" #ifdef MYLIB # define MYLIB_EXPORT DLL_EXPORT #else # define MYLIB_EXPORT DLL_IMPORT #endif MYLIB_EXPORT void f(); qbs-src-1.13.1/tests/auto/blackbox/testdata/installpackage/main.cpp000066400000000000000000000024051347155106100252750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib.h" int main() { f(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/invalid-command-property/000077500000000000000000000000001347155106100256065ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/invalid-command-property/input.txt000066400000000000000000000000001347155106100274740ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/invalid-command-property/invalid-command-property.qbs000066400000000000000000000016131347155106100332420ustar00rootroot00000000000000import qbs.TextFile Product { name: "p" property string errorType type: ["output"] Group { files: ["input.txt"] fileTags: ["input"] } Rule { inputs: ["input"] Artifact { filePath: "dummy" fileTags: ["output"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating output"; if (product.errorType === "qobject") cmd.dummy = new TextFile(input.filePath, TextFile.ReadOnly); else if (product.errorType === "input") cmd.dummy = input; else if (product.errorType === "artifact") cmd.dummy = product.artifacts.qbs[0]; else throw "invalid error type " + product.errorType; cmd.sourceCode = function() { } return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/invalid-extension-instantiation/000077500000000000000000000000001347155106100272045ustar00rootroot00000000000000invalid-extension-instantiation.qbs000066400000000000000000000010471347155106100361600ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/invalid-extension-instantiationimport qbs.Environment import qbs.File import qbs.FileInfo import qbs.Utilities Product { name: "theProduct" type: ["mytype"] property string extension Rule { multiplex: true Artifact { filePath: "dummy" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var f = eval("new " + product.extension); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/invalid-install-dir/000077500000000000000000000000001347155106100245305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/invalid-install-dir/invalid-install-dir.qbs000066400000000000000000000002221347155106100311010ustar00rootroot00000000000000CppApplication { consoleApplication: true files: ["main.cpp"] qbs.installPrefix: "" install: true installDir: "../whatever" } qbs-src-1.13.1/tests/auto/blackbox/testdata/invalid-install-dir/main.cpp000066400000000000000000000000161347155106100261550ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/invalid-library-names/000077500000000000000000000000001347155106100250535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/invalid-library-names/invalid-library-names.qbs000066400000000000000000000004671347155106100317620ustar00rootroot00000000000000Project { minimumQbsVersion: "1.6" property var values: [null, undefined, 5, [], ""] property int valueIndex CppApplication { cpp.dynamicLibraries: [project.values[project.valueIndex]] cpp.staticLibraries: [project.values[project.valueIndex]] files: ["main.cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/invalid-library-names/main.cpp000066400000000000000000000023521347155106100265050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-binaryfile/000077500000000000000000000000001347155106100255405ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs000066400000000000000000000032451347155106100303770ustar00rootroot00000000000000import qbs.BinaryFile Product { type: ["dummy"] Rule { multiplex: true outputFileTags: "dummy" prepare: { var commands = []; var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var source = new BinaryFile("source.dat", BinaryFile.WriteOnly); source.write([ 0x01, 0x02 ]); // First data. // Do not close the file to test the auto close functionality. }; commands.push(cmd); cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { source = new BinaryFile("source.dat", BinaryFile.ReadWrite); source.seek(source.size()); source.write([ 0x03, 0x04 ]); // Second data. source.close(); source = new BinaryFile("source.dat", BinaryFile.ReadWrite); var destination = new BinaryFile("destination.dat", BinaryFile.WriteOnly); destination.write(source.atEof() ? [ 0xFF ] : [ 0x00 ]); while (true) { var data = source.read(1); if (!data || data.length == 0) break; destination.write(data); } source.resize(0); // truncate destination.write([ 0x05, 0x06 ]); // Third data. destination.write(source.atEof() ? [ 0xFF ] : [ 0x00 ]); source.close(); destination.close(); }; commands.push(cmd); return commands; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-file/000077500000000000000000000000001347155106100243335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-file/file.qbs000066400000000000000000000050651347155106100257670ustar00rootroot00000000000000import qbs.File import qbs.FileInfo import qbs.TextFile Product { type: ["dummy"] Rule { multiplex: true outputFileTags: "dummy" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var origPath = FileInfo.joinPaths(product.sourceDirectory, "original.txt"); var copyPath = FileInfo.joinPaths(product.sourceDirectory, "copy.txt"); console.info("copy path: "+copyPath); var original = new TextFile(origPath, TextFile.WriteOnly); original.close(); File.copy(origPath, copyPath); var origTimestamp = File.lastModified(origPath); var copyTimestamp = File.lastModified(copyPath); if (origTimestamp > copyTimestamp) throw new Error("Older file has newer timestamp."); File.remove(origPath); var copy = new TextFile(copyPath, TextFile.WriteOnly); copy.writeLine(File.exists(origPath)); copy.writeLine(File.exists(copyPath)); copy.close(); var zePath = FileInfo.joinPaths(product.sourceDirectory, "zePath"); if (File.exists(zePath)) throw new Error(zePath + " already exists."); var created = File.makePath(zePath); if (!created || !File.exists(zePath)) throw new Error("zePath was not created."); var entries = File.directoryEntries(product.sourceDirectory, File.AllEntries | File.NoDotAndDotDot); if (entries.length < 3 || !entries.contains("file.qbs")) throw new Error("Directory did not contain file.qbs"); entries = File.directoryEntries(product.sourceDirectory, File.Dirs | File.NoDotAndDotDot); if (entries.length < 1 || !entries.contains("zePath")) throw new Error("Directory did not contain only zePath"); var moveSource = FileInfo.joinPaths(product.sourceDirectory, "tomove.txt"); var moveTarget = FileInfo.joinPaths(product.sourceDirectory, "moved.txt"); File.move(moveSource, moveTarget); if (File.exists(moveSource)) throw new Error("Moved file still exists under old name"); if (!File.exists(moveTarget)) throw new Error("Moved file does not exist under new name"); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-fileinfo/000077500000000000000000000000001347155106100252075ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-fileinfo/fileinfo.qbs000066400000000000000000000051171347155106100275150ustar00rootroot00000000000000import qbs.FileInfo import qbs.TextFile Product { type: ["dummy"] property string messyPath: path + "/../" + FileInfo.fileName(path) Rule { multiplex: true outputFileTags: "dummy" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var output = new TextFile(FileInfo.joinPaths(product.sourceDirectory, "output.txt"), TextFile.WriteOnly); output.writeLine(FileInfo.baseName("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.canonicalPath(product.messyPath)); output.writeLine(FileInfo.cleanPath("/usr/local//../bin/")); output.writeLine(FileInfo.completeBaseName("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.fileName("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.fromWindowsSeparators("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.fromWindowsSeparators("c:\\tmp\\blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("c:\\tmp\\blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("c:\\tmp\\blubb.tar.gz", ["unix"])); output.writeLine(FileInfo.isAbsolutePath("c:\\tmp\\blubb.tar.gz", ["windows"])); output.writeLine(FileInfo.isAbsolutePath("blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("../blubb.tar.gz")); output.writeLine(FileInfo.joinPaths("/", "tmp", "blubb.tar.gz")); output.writeLine(FileInfo.joinPaths("//", "/tmp/", "/blubb.tar.gz")); output.writeLine(FileInfo.path("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.path("/tmp/")); output.writeLine(FileInfo.path("/")); output.writeLine(FileInfo.path("d:/")); output.writeLine(FileInfo.path("d:/", ["unix"])); output.writeLine(FileInfo.path("d:/", ["windows"])); output.writeLine(FileInfo.relativePath("/tmp", "/tmp/blubb.tar.gz")); output.writeLine(FileInfo.relativePath("/", "/tmp/blubb.tar.gz")); output.writeLine(FileInfo.relativePath("/tmp", "/blubb.tar.gz")); output.writeLine(FileInfo.toWindowsSeparators("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.toWindowsSeparators("c:\\tmp\\blubb.tar.gz")); output.close(); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-process/000077500000000000000000000000001347155106100250725ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-process/main.cpp000066400000000000000000000010101347155106100265120ustar00rootroot00000000000000#include #include #include int main(int argc, char *argv[]) { if (argc != 2 || strcmp(argv[1], "help") != 0) { fprintf(stderr, "First argument to this program must be 'help'.\n"); return 1; } const char *env = std::getenv("SOME_ENV"); if (!env || strcmp(env, "why, hello!") != 0) { fprintf(stderr, "The SOME_ENV environment variable must be 'why, hello!'.\n"); return 1; } printf("qbs jsextensions-process test\n"); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-process/process.qbs000066400000000000000000000071711347155106100272650ustar00rootroot00000000000000import qbs.Environment import qbs.FileInfo import qbs.Process import qbs.TextFile Project { Product { Depends { name: "cpp" } type: ["dummy"] name: "dummy" files: ["main.cpp"] Rule { multiplex: true inputs: ["application"] outputFileTags: "dummy" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var exeFilePath = FileInfo.joinPaths(product.buildDirectory, product.cpp.executablePrefix + "dummy" + product.cpp.executableSuffix); // Synchronous run, successful. var process = new Process(); var pathVal = "why, hello!"; process.setEnv("SOME_ENV", pathVal); process.exec(exeFilePath, ["help"], true); var output = new TextFile("output.txt", TextFile.WriteOnly); output.writeLine(process.exitCode()); output.writeLine(process.readLine()); process.close(); // Asynchronous run, successful. process = new Process(); process.setEnv("SOME_ENV", pathVal); output.writeLine(process.start(exeFilePath, ["help"])); output.writeLine(process.waitForFinished()); output.writeLine(process.exitCode()); output.writeLine(process.readLine()); process.close(); // Asynchronous run, unsuccessful. process = new Process(); output.writeLine(process.start("blubb", [])); process.close(); // closeWriteChannel test process = new Process(); if (product.qbs.hostOS.contains("windows")) process.start(product.qbs.windowsShellPath, ["/C", product.qbs.windowsSystemRoot + "\\system32\\sort.exe"]); else process.start("cat", []); process.writeLine("should be"); process.closeWriteChannel(); process.writeLine("should not be"); if (!process.waitForFinished()) process.kill(); output.write(process.readStdOut()); process.close(); // readLine and atEnd var testReadlineFile = new TextFile("123.txt", TextFile.WriteOnly); testReadlineFile.writeLine("1"); testReadlineFile.writeLine("2"); testReadlineFile.writeLine("3"); testReadlineFile.close(); process = new Process(); if (product.qbs.hostOS.contains("windows")) process.exec(product.qbs.windowsShellPath, ["/C", "type", "123.txt"], true); else process.exec("cat", ["123.txt"], true); while(!process.atEnd()) output.write(process.readLine()); // TODO: Test all the other Process methods as well. output.close(); }; return [cmd]; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-propertylist/000077500000000000000000000000001347155106100261745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-propertylist/propertylist.qbs000066400000000000000000000111421347155106100314620ustar00rootroot00000000000000import qbs.Process import qbs.PropertyList import qbs.TextFile Product { type: ["Pineapple Steve"] property bool dummy: { var plistobj = new PropertyList(); if (!plistobj.isEmpty()) { throw "newly created PropertyList was not empty!"; } if (plistobj.format() !== undefined) { throw "newly created PropertyList did not have an undefined format"; } plistobj.clear(); if (!plistobj.isEmpty() || plistobj.format() !== undefined) { throw "clear() somehow had an effect on an empty PropertyList"; } plistobj.readFromString('{"key":["value"]}'); if (plistobj.isEmpty() || plistobj.format() !== "json") { throw "readFromString did not set format to JSON or object thinks it is empty"; } plistobj.clear(); if (!plistobj.isEmpty() || plistobj.format() !== undefined) { throw "clear() had no effect on a non-empty PropertyList"; } var obj = { "Array": ["ListItem1", "ListItem2", "ListItem3"], "Integer": 1, "Boolean": true, "String": "otherString" }; var infoplist = new TextFile("test.xml", TextFile.WriteOnly); infoplist.write(JSON.stringify(obj)); infoplist.close(); var process = new Process(); process.exec("plutil", ["-convert", "xml1", "test.xml"]); process.close(); var xmlfile = new TextFile("test.xml", TextFile.ReadOnly); var propertyList = new PropertyList(); propertyList.readFromString(xmlfile.readAll()); xmlfile.close(); var jsontextfile = new TextFile("test.json", TextFile.WriteOnly); jsontextfile.write(propertyList.toJSON()); jsontextfile.close(); propertyList.writeToFile("test2.json", "json-compact"); propertyList.writeToFile("test3.json", "json-pretty"); process = new Process(); process.exec("plutil", ["-convert", "json", "test.xml"]); process.close(); propertyList = new PropertyList(); propertyList.readFromFile("test.xml"); if (propertyList.format() !== "json") { // yes, JSON -- ignore the file extension throw "expected property list format json but got " + propertyList.format(); } if (propertyList.isEmpty()) { throw "PropertyList was 'empty' after being loaded with data"; } var opensteptextfile = new TextFile("test.openstep.plist", TextFile.WriteOnly); opensteptextfile.write('{ rootObject = ( "val1", "val3", "val5", /* comment */ "val7", "val9", ); }'); opensteptextfile.close(); propertyList = new PropertyList(); propertyList.readFromFile("test.openstep.plist"); if (propertyList.format() !== "openstep") { throw "expected property list format openstep but got " + propertyList.format(); } var jsonObj = JSON.parse(propertyList.toJSON()); if (jsonObj["rootObject"].length != 5) { throw "going from OpenStep to a JSON string to a JSON object somehow broke"; } propertyList.clear(); propertyList.readFromString('foobarz'); jsonObj = JSON.parse(propertyList.toJSON()); if (jsonObj["foo"] !== "barz") { throw "the XML plist did not get parsed properly"; } propertyList.writeToFile("woof.xml", "xml1"); propertyList.readFromFile("woof.xml"); if (propertyList.format() !== "xml1") { throw "round trip writing and reading XML failed"; } propertyList.writeToFile("woof.plist", "binary1"); propertyList.readFromFile("woof.plist"); if (propertyList.format() !== "binary1") { throw "round trip writing and reading binary failed"; } if (jsonObj["foo"] !== "barz") { throw "the binary plist did not get parsed properly"; } if (propertyList.toString("json") !== propertyList.toString("json-compact") || propertyList.toJSON() !== propertyList.toJSON("compact")) { throw "json and json-compact formats were not equivalent"; } if (propertyList.toString("json") === propertyList.toString("json-pretty") || propertyList.toJSON() === propertyList.toJSON("pretty")) { throw "json and json-pretty formats were not different"; } if (propertyList.toString("xml1") !== propertyList.toXMLString()) { throw 'toString("xml1") and toXMLString() were not equivalent'; } return true; } } qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-temporarydir/000077500000000000000000000000001347155106100261355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-temporarydir/jsextensions-temporarydir.qbs000066400000000000000000000011341347155106100341160ustar00rootroot00000000000000import qbs.File import qbs.TemporaryDir Product { targetName: { var dir; var dirPath; try { dir = new TemporaryDir(); dirPath = dir.path(); if (!dirPath) throw "path is empty"; if (!dir.isValid()) throw "dir is not valid"; if (!File.exists(dirPath)) throw "dir does not exist"; } finally { if (!dir.remove()) throw "could not remove"; } if (File.exists(dirPath)) throw "dir was not removed"; } } qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-textfile/000077500000000000000000000000001347155106100252405ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/jsextensions-textfile/textfile.qbs000066400000000000000000000030031347155106100275670ustar00rootroot00000000000000import qbs.TextFile Product { type: ["dummy"] Rule { multiplex: true outputFileTags: "dummy" prepare: { var commands = []; var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var file1 = new TextFile("file1.txt", TextFile.WriteOnly); file1.write("First line.\n"); // Do not close the file to test the auto close functionality. }; commands.push(cmd); cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var file1 = new TextFile("file1.txt", TextFile.WriteOnly | TextFile.Append); file1.write("Second line.\nThird line."); file1.close(); file1 = new TextFile("file1.txt", TextFile.ReadWrite); var file2 = new TextFile("file2.txt", TextFile.WriteOnly); file2.writeLine(file1.atEof()); while (true) { var line = file1.readLine(); if (!line || line.length == 0) break; file2.writeLine(line); } file1.truncate(); file2.writeLine(file1.filePath()); file2.writeLine(file1.atEof()); file1.close(); file2.close(); }; commands.push(cmd); return commands; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/ld/000077500000000000000000000000001347155106100212615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/ld/coreutils.cpp000066400000000000000000000024201347155106100237740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "coreutils.h" int foo() { return 42; } qbs-src-1.13.1/tests/auto/blackbox/testdata/ld/coreutils.h000066400000000000000000000024141347155106100234440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" DLL_EXPORT int foo(); qbs-src-1.13.1/tests/auto/blackbox/testdata/ld/ld.qbs000066400000000000000000000010671347155106100223730ustar00rootroot00000000000000Project { Library { Depends { name: "cpp" } name: "coreutils" targetName: "qbs can handle any file paths, even the crazy ones! ;)" files: ["coreutils.cpp", "coreutils.h"] Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false cpp.sonamePrefix: "@rpath" } Group { fileTagsFilter: product.type qbs.install: true } } CppApplication { Depends { name: "coreutils" } files: ["main.cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/ld/main.cpp000066400000000000000000000025241347155106100227140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "coreutils.h" #include int main(int argc, char *argv[]) { printf("%d\n", foo()); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/000077500000000000000000000000001347155106100223125ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/lex_outfile/000077500000000000000000000000001347155106100246315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/lex_outfile/lex_outfile.qbs000066400000000000000000000006021347155106100276550ustar00rootroot00000000000000CppApplication { qbsSearchPaths: ".." Depends { name: "bisonhelper" } Depends { name: "lex_yacc" } lex_yacc.outputTag: "cpp" lex_yacc.yaccFlags: ["-l"] cpp.includePaths: [".", ".."] cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" consoleApplication: true files: [ "lexer.l", "parser.y", "types.h", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/lex_outfile/lexer.l000066400000000000000000000004541347155106100261300ustar00rootroot00000000000000%option outfile="quark.cpp" %{ #include void yyerror(const char *e) { std::cerr << e; } extern "C" int yywrap() { return 1; } extern YYSTYPE yylval; %} ID [a-z]+ AND "&&" OR "||" NOT "!" %% [[:space:]]+ {ID} yylval.s = yytext; return 1; {AND} return 2; {OR} return 3; {NOT} return 4; %% qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/lex_outfile/parser.y000066400000000000000000000011731347155106100263210ustar00rootroot00000000000000%{ #include %} %type expr %left OR %left AND %nonassoc NOT %token ID %% start: expr { root = $1; } expr: expr AND expr { auto t = std::make_shared(); t->val = "AND"; t->children = { $1, $3 }; $$ = t; } | expr OR expr { auto t = std::make_shared(); t->val = "OR"; t->children = { $1, $3 }; $$ = t; } | NOT expr { auto t = std::make_shared(); t->val = "NOT"; t->children = { $2 }; $$ = t; } | ID { auto t = std::make_shared(); t->val = $1; $$ = t; } %% TreePtr root; int main() { yyparse(); if (!root) return 1; root->print(); std::cout << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/lex_outfile/types.h000066400000000000000000000032541347155106100261520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include struct Tree; using TreePtr = std::shared_ptr; struct Tree { std::string val; std::vector children; void print() const { std::cout << val << ' '; for (const TreePtr &t : children) t->print(); } }; struct YaccType { TreePtr t; std::string s; }; #define YYSTYPE YaccType extern TreePtr root; int yylex(); void yyerror(const char *); qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/lex_prefix/000077500000000000000000000000001347155106100244575ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/lex_prefix/lex_prefix.qbs000066400000000000000000000006021347155106100273310ustar00rootroot00000000000000CppApplication { qbsSearchPaths: ".." Depends { name: "bisonhelper" } Depends { name: "lex_yacc" } lex_yacc.outputTag: "cpp" lex_yacc.yaccFlags: ["-l"] cpp.includePaths: [".", ".."] cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" consoleApplication: true files: [ "lexer.l", "parser.y", "types.h", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/lex_prefix/lexer.l000066400000000000000000000004531347155106100257550ustar00rootroot00000000000000%option prefix="bla" %{ #include void blaerror(const char *e) { std::cerr << e; } extern "C" int blawrap() { return 1; } extern BLASTYPE blalval; %} ID [a-z]+ AND "&&" OR "||" NOT "!" %% [[:space:]]+ {ID} blalval.s = blatext; return 1; {AND} return 2; {OR} return 3; {NOT} return 4; %% qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/lex_prefix/parser.y000066400000000000000000000012251347155106100261450ustar00rootroot00000000000000%{ #include %} %define api.prefix {bla} %type expr %left OR %left AND %nonassoc NOT %token ID %% start: expr { root = $1; } expr: expr AND expr { auto t = std::make_shared(); t->val = "AND"; t->children = { $1, $3 }; $$ = t; } | expr OR expr { auto t = std::make_shared(); t->val = "OR"; t->children = { $1, $3 }; $$ = t; } | NOT expr { auto t = std::make_shared(); t->val = "NOT"; t->children = { $2 }; $$ = t; } | ID { auto t = std::make_shared(); t->val = $1; $$ = t; } %% TreePtr root; int main() { blaparse(); if (!root) return 1; root->print(); std::cout << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/lex_prefix/types.h000066400000000000000000000032571347155106100260030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include struct Tree; using TreePtr = std::shared_ptr; struct Tree { std::string val; std::vector children; void print() const { std::cout << val << ' '; for (const TreePtr &t : children) t->print(); } }; struct YaccType { TreePtr t; std::string s; }; #define BLASTYPE YaccType extern TreePtr root; int blalex(); void blaerror(const char *); qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/modules/000077500000000000000000000000001347155106100237625ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/000077500000000000000000000000001347155106100262745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/bisonhelper.qbs000066400000000000000000000006661347155106100313250ustar00rootroot00000000000000import qbs import qbs.Process Module { Depends { name: "lex_yacc" } Probe { id: bisonProbe property string yaccBinary: lex_yacc.yaccBinary configure: { var p = Process(); found = p.exec(yaccBinary, ["-V"]) == 0 && p.readStdOut().contains("bison"); p.close(); } } Properties { condition: bisonProbe.found lex_yacc.yaccFlags: "-y" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/one-grammar/000077500000000000000000000000001347155106100245175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/one-grammar/lexer.l000066400000000000000000000004511347155106100260130ustar00rootroot00000000000000%{ #include #include void yyerror(const char *e) { std::cerr << e; } extern "C" int yywrap() { return 1; } extern YYSTYPE yylval; %} ID [a-z]+ AND "&&" OR "||" NOT "!" %% [[:space:]]+ {ID} yylval.s = yytext; return ID; {AND} return AND; {OR} return OR; {NOT} return NOT; %% qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs000066400000000000000000000006021347155106100274310ustar00rootroot00000000000000CppApplication { qbsSearchPaths: ".." Depends { name: "bisonhelper" } Depends { name: "lex_yacc" } lex_yacc.outputTag: "cpp" lex_yacc.yaccFlags: ["-l"] cpp.includePaths: [".", ".."] cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" consoleApplication: true files: [ "lexer.l", "parser.y", "types.h", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/one-grammar/parser.y000066400000000000000000000011731347155106100262070ustar00rootroot00000000000000%{ #include %} %type expr %left OR %left AND %nonassoc NOT %token ID %% start: expr { root = $1; } expr: expr AND expr { auto t = std::make_shared(); t->val = "AND"; t->children = { $1, $3 }; $$ = t; } | expr OR expr { auto t = std::make_shared(); t->val = "OR"; t->children = { $1, $3 }; $$ = t; } | NOT expr { auto t = std::make_shared(); t->val = "NOT"; t->children = { $2 }; $$ = t; } | ID { auto t = std::make_shared(); t->val = $1; $$ = t; } %% TreePtr root; int main() { yyparse(); if (!root) return 1; root->print(); std::cout << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/one-grammar/types.h000066400000000000000000000032541347155106100260400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include struct Tree; using TreePtr = std::shared_ptr; struct Tree { std::string val; std::vector children; void print() const { std::cout << val << ' '; for (const TreePtr &t : children) t->print(); } }; struct YaccType { TreePtr t; std::string s; }; #define YYSTYPE YaccType extern TreePtr root; int yylex(); void yyerror(const char *); qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/000077500000000000000000000000001347155106100247325ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/g1.l000066400000000000000000000002401347155106100254120ustar00rootroot00000000000000%option noyywrap %{ #include #ifdef _MSC_BUILD #pragma message("whatever") #else #pragma whatever #endif void g1error(const char *e) { } %} %% %% qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/g1.y000066400000000000000000000000421347155106100254270ustar00rootroot00000000000000%{ int g1lex(); %} %% expr: '1' qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/g2.l000066400000000000000000000001241347155106100254140ustar00rootroot00000000000000%option noyywrap %{ #include void g2error(const char *e) { } %} %% %% qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/g2.y000066400000000000000000000000421347155106100254300ustar00rootroot00000000000000%{ int g1lex(); %} %% expr: '1' qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/main.c000066400000000000000000000024651347155106100260310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int g1parse(); int g2parse(); int main() { g1parse(); g2parse(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/two-grammars/two-grammars.qbs000066400000000000000000000003211347155106100300550ustar00rootroot00000000000000CppApplication { Depends { name: "lex_yacc" } consoleApplication: true cpp.includePaths: ".." files: [ "g1.l", "g1.y", "g2.l", "g2.y", "main.c", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/unistd.h000066400000000000000000000002201347155106100237630ustar00rootroot00000000000000#ifndef MY_UNISTD_H #define MY_UNISTD_H #ifdef _MSC_BUILD #include #define isatty _isatty #else #include_next #endif #endif qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/yacc_output/000077500000000000000000000000001347155106100246515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/yacc_output/lexer.l000066400000000000000000000004541347155106100261500ustar00rootroot00000000000000%{ #include #include void yyerror(const char *e) { std::cerr << e; } extern "C" int yywrap() { return 1; } extern YYSTYPE yylval; %} ID [a-z]+ AND "&&" OR "||" NOT "!" %% [[:space:]]+ {ID} yylval.s = yytext; return ID; {AND} return AND; {OR} return OR; {NOT} return NOT; %% qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/yacc_output/parser.y000066400000000000000000000012201347155106100263320ustar00rootroot00000000000000%{ #include %} %output "parser.cxx" %type expr %left OR %left AND %nonassoc NOT %token ID %% start: expr { root = $1; } expr: expr AND expr { auto t = std::make_shared(); t->val = "AND"; t->children = { $1, $3 }; $$ = t; } | expr OR expr { auto t = std::make_shared(); t->val = "OR"; t->children = { $1, $3 }; $$ = t; } | NOT expr { auto t = std::make_shared(); t->val = "NOT"; t->children = { $2 }; $$ = t; } | ID { auto t = std::make_shared(); t->val = $1; $$ = t; } %% TreePtr root; int main() { yyparse(); if (!root) return 1; root->print(); std::cout << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/yacc_output/types.h000066400000000000000000000032541347155106100261720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include struct Tree; using TreePtr = std::shared_ptr; struct Tree { std::string val; std::vector children; void print() const { std::cout << val << ' '; for (const TreePtr &t : children) t->print(); } }; struct YaccType { TreePtr t; std::string s; }; #define YYSTYPE YaccType extern TreePtr root; int yylex(); void yyerror(const char *); qbs-src-1.13.1/tests/auto/blackbox/testdata/lexyacc/yacc_output/yacc_output.qbs000066400000000000000000000005051347155106100277170ustar00rootroot00000000000000CppApplication { Depends { name: "lex_yacc" } lex_yacc.outputTag: "cpp" lex_yacc.yaccFlags: ["-l"] cpp.includePaths: [".", ".."] cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" consoleApplication: true files: [ "lexer.l", "parser.y", "types.h", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/linker-variant/000077500000000000000000000000001347155106100236105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/linker-variant/linker-variant.qbs000066400000000000000000000006411347155106100272460ustar00rootroot00000000000000CppApplication { name: "p" property string linkerVariant Probe { id: gccProbe property bool isGcc: qbs.toolchain.contains("gcc") configure: { console.info("is GCC: " + isGcc); if (isGcc) found = true; } } Properties { condition: gccProbe.found cpp.linkerVariant: linkerVariant } files: "main.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata/linker-variant/main.cpp000066400000000000000000000000161347155106100252350ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerMode/000077500000000000000000000000001347155106100227535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs000066400000000000000000000032061347155106100255540ustar00rootroot00000000000000Project { CppApplication { consoleApplication: true name: "LinkedProduct-Assembly" files: ["main.s"] cpp.linkerPath: cpp.compilerPathByLanguage["c"] Group { fileTagsFilter: product.type qbs.install: true } } CppApplication { consoleApplication: true name: "LinkedProduct-C" files: ["main.c"] Group { fileTagsFilter: product.type qbs.install: true } } CppApplication { condition: qbs.targetOS.contains("darwin") consoleApplication: true name: "LinkedProduct-Objective-C" files: ["main.m"] cpp.dynamicLibraries: ["ObjC"] Group { fileTagsFilter: product.type qbs.install: true } } CppApplication { consoleApplication: true name: "LinkedProduct-C++" files: ["main.cpp"] Group { fileTagsFilter: product.type qbs.install: true } } CppApplication { condition: qbs.targetOS.contains("darwin") consoleApplication: true name: "LinkedProduct-Objective-C++" files: ["main.mm"] cpp.dynamicLibraries: ["ObjC"] Group { fileTagsFilter: product.type qbs.install: true } } CppApplication { Depends { name: "LinkedProduct-C++StaticLibrary" } name: "LinkedProduct-BlankApp" files: ["staticmain.c"] } StaticLibrary { Depends { name: "cpp" } name: "LinkedProduct-C++StaticLibrary" files: ["staticlib.cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerMode/main.c000066400000000000000000000024751347155106100240530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { void *memory = malloc(8); free(memory); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerMode/main.cpp000066400000000000000000000024731347155106100244110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { std::string s = "Hello World"; (void)s; return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerMode/main.m000066400000000000000000000001221347155106100240500ustar00rootroot00000000000000#include int main() { sel_registerName("qbs"); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerMode/main.mm000066400000000000000000000002241347155106100242300ustar00rootroot00000000000000#include #include int main() { std::string s = "Hello World"; (void)s; sel_registerName("qbs"); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerMode/main.s000066400000000000000000000000471347155106100240640ustar00rootroot00000000000000.globl _main .globl main _main: main: qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerMode/staticlib.cpp000066400000000000000000000025201347155106100254340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include extern "C" int cpp(); int cpp() { std::cout << "Hello world" << std::endl; return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerMode/staticmain.c000066400000000000000000000024171347155106100252570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ extern int cpp(); int main() { return cpp(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerscripts/000077500000000000000000000000001347155106100235565ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerscripts/linkerscript1000066400000000000000000000000221347155106100262650ustar00rootroot00000000000000TEST_SYMBOL1 = 0; qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerscripts/linkerscript2000066400000000000000000000000221347155106100262660ustar00rootroot00000000000000TEST_SYMBOL2 = 1; qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerscripts/linkerscript_recursive000066400000000000000000000000401347155106100302730ustar00rootroot00000000000000TEST_SYMBOL_FROM_RECURSIVE = 1; qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerscripts/linkerscript_to_include000066400000000000000000000000751347155106100304210ustar00rootroot00000000000000TEST_SYMBOL_FROM_INCLUDE = 1; INCLUDE linkerscript_recursive qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs000066400000000000000000000033671347155106100271720ustar00rootroot00000000000000import qbs.TextFile DynamicLibrary { type: base.concat("custom") Depends { name: "cpp" } files: ["testlib.c"] Group { name: "linker scripts" files: [ "linkerscript1", "linkerscript2", ] fileTags: ["linkerscript"] } cpp.libraryPaths: [ product.sourceDirectory, // location of linkerscripts that are included ] Rule { multiplex: true outputFileTags: "custom" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.warn("---" + product.cpp.nmPath + "---"); } return [cmd]; } } Rule { multiplex: true requiresInputs: false Artifact { filePath: product.buildDirectory + "/linkerscript_with_includes" fileTags: ["linkerscript"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourcePath = product.sourceDirectory; cmd.buildPath = product.buildDirectory; cmd.sourceCode = function() { var file = new TextFile(buildPath + "/linkerscript_with_includes", TextFile.WriteOnly); file.write("SEARCH_DIR(" + sourcePath + "/scripts)\n" + "INCLUDE linkerscript_to_include\n" + "INCLUDE linkerscript_in_directory\n"); file.close(); } cmd.highlight = "codegen"; cmd.description = "generating linkerscript with SEARCH_DIR and INCLUDE"; return [cmd]; } } qbs.installPrefix: "" install: true installDir: "" } qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerscripts/scripts/000077500000000000000000000000001347155106100252455ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerscripts/scripts/linkerscript_in_directory000066400000000000000000000000401347155106100324450ustar00rootroot00000000000000TEST_SYMBOL_FROM_DIRECTORY = 1; qbs-src-1.13.1/tests/auto/blackbox/testdata/linkerscripts/testlib.c000066400000000000000000000023531347155106100253730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void dummy() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/list-products/000077500000000000000000000000001347155106100234765ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-products/list-products.qbs000066400000000000000000000004361347155106100270240ustar00rootroot00000000000000Project { Product { name: "a" } Product { name: "b" multiplexByQbsProperties: ["architectures", "buildVariants"] qbs.architectures: ["mips", "vax"] qbs.buildVariants: ["debug", "release"] } Product { name: "c" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/list-properties-with-outer/000077500000000000000000000000001347155106100261345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-properties-with-outer/dummy.txt000066400000000000000000000000001347155106100300160ustar00rootroot00000000000000list-properties-with-outer.qbs000066400000000000000000000003351347155106100340370ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-properties-with-outerProduct { type: ["outtype"] Depends { name: "higher" } lower.listProp: ["product"] Group { files: ["dummy.txt"] fileTags: ["intype"] lower.listProp: outer.concat(["group"]) } } qbs-src-1.13.1/tests/auto/blackbox/testdata/list-properties-with-outer/modules/000077500000000000000000000000001347155106100276045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-properties-with-outer/modules/higher/000077500000000000000000000000001347155106100310525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-properties-with-outer/modules/higher/higher.qbs000066400000000000000000000001101347155106100330170ustar00rootroot00000000000000Module { Depends { name: "lower" } lower.listProp: ["higher"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/list-properties-with-outer/modules/lower/000077500000000000000000000000001347155106100307345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-properties-with-outer/modules/lower/lower.qbs000066400000000000000000000006131347155106100325730ustar00rootroot00000000000000Module { property stringList listProp Rule { inputs: ["intype"] outputFileTags: "outtype" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info("listProp: " + JSON.stringify(input.lower.listProp)); } return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/000077500000000000000000000000001347155106100246305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/dummy.txt000066400000000000000000000000001347155106100265120ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/modules/000077500000000000000000000000001347155106100263005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/modules/higher1/000077500000000000000000000000001347155106100276275ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/modules/higher1/higher1.qbs000066400000000000000000000001111347155106100316560ustar00rootroot00000000000000Module { Depends { name: "lower" } lower.listProp: ["higher1"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/modules/higher2/000077500000000000000000000000001347155106100276305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/modules/higher2/higher2.qbs000066400000000000000000000001111347155106100316600ustar00rootroot00000000000000Module { Depends { name: "lower" } lower.listProp: ["higher2"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/modules/higher3/000077500000000000000000000000001347155106100276315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/modules/higher3/higher3.qbs000066400000000000000000000001111347155106100316620ustar00rootroot00000000000000Module { Depends { name: "lower" } lower.listProp: ["higher3"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/modules/lower/000077500000000000000000000000001347155106100274305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs000066400000000000000000000007141347155106100312710ustar00rootroot00000000000000Module { property stringList listProp Rule { inputs: ["intype"] Artifact { filePath: "dummy.out" fileTags: "outtype" } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function() { console.info("listProp = " + JSON.stringify(product.lower.listProp)); }; cmd.silent = true; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/list-property-order/product.qbs000066400000000000000000000003411347155106100270150ustar00rootroot00000000000000Product { type: "outtype" name: "toplevel" Depends { name: "higher1" } Depends { name: "higher2" } Depends { name: "higher3" } Group { files: ["dummy.txt"] fileTags: ["intype"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/loadablemodule/000077500000000000000000000000001347155106100236335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/loadablemodule/exported.cpp000066400000000000000000000024521347155106100261740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "exported.h" extern "C" { int foo() { return 42; } } qbs-src-1.13.1/tests/auto/blackbox/testdata/loadablemodule/exported.h000066400000000000000000000024371347155106100256440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" extern "C" { DLL_EXPORT int foo(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/loadablemodule/loadablemodule.qbs000066400000000000000000000016671347155106100273250ustar00rootroot00000000000000Project { LoadableModule { Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } name: "CoolPlugIn" files: ["exported.cpp", "exported.h"] Group { fileTagsFilter: product.type qbs.install: true } } CppApplication { Depends { name: "cpp" } Depends { name: "CoolPlugIn"; cpp.link: false } consoleApplication: true name: "CoolApp" files: ["main.cpp"] cpp.cxxLanguageVersion: "c++11" cpp.dynamicLibraries: [qbs.targetOS.contains("windows") ? "kernel32" : "dl"] Properties { condition: qbs.targetOS.contains("unix") && !qbs.targetOS.contains("darwin") cpp.rpaths: [cpp.rpathOrigin] } Group { fileTagsFilter: product.type qbs.install: true } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/loadablemodule/main.cpp000066400000000000000000000064111347155106100252650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #ifdef _WIN32 #include #define PREFIX "" #define SUFFIX ".dll" #define dlopen(path, mode) LoadLibraryA(path) #define dlsym(handle, symbol) GetProcAddress(handle, symbol) #define dlclose(handle) FreeLibrary(handle) #elif defined(__APPLE__) #define PREFIX "" #define SUFFIX ".bundle" #else #define PREFIX "lib" #define SUFFIX ".so" #endif #ifndef _WIN32 #include #endif int main() { auto lib = dlopen(PREFIX "CoolPlugIn" SUFFIX, RTLD_LAZY); if (lib) { auto fptr = dlsym(lib, "foo"); if (fptr) std::cout << "foo = " << ((int (*)(void))fptr)() << std::endl; else std::cout << "function foo not found in CoolPlugIn" << std::endl; dlclose(lib); return fptr ? 0 : 1; } else { std::cout << "CoolPlugIn not loaded" << std::endl; } return 1; } qbs-src-1.13.1/tests/auto/blackbox/testdata/localDeployment/000077500000000000000000000000001347155106100240155ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/localDeployment/localDeployment.qbs000066400000000000000000000007511347155106100276620ustar00rootroot00000000000000Project { Product { type: ["application"] consoleApplication: true name: "HelloWorld" destinationDirectory: "bin" Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++11" Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "bin" } Group { qbs.install: true qbs.installDir: "share" files: ['main.cpp'] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/localDeployment/main.cpp000066400000000000000000000035741347155106100254560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include int main(int argc, char *argv[]) { if (argc != 1) return 1; std::string s = argv[0]; for (auto &c : s) { if (c == '\\') c = '/'; } const std::string mainFilePath = std::string(s.substr(0, s.find_last_of("/")) + "/../share/main.cpp"); std::ifstream in(mainFilePath.c_str()); if (!in.is_open()) { std::cerr << "Failed to open file: " << mainFilePath; return 1; } std::string str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); std::cout << str << std::endl; return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/makefile-generator/000077500000000000000000000000001347155106100244235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/makefile-generator/app.qbs000066400000000000000000000005641347155106100257170ustar00rootroot00000000000000CppApplication { name: "the app" consoleApplication: true cpp.cxxLanguageVersion: "c++11" cpp.separateDebugInformation: false Properties { condition: qbs.targetOS.contains("macos") bundle.embedInfoPlist: false cpp.minimumMacosVersion: "10.7" } files: "main.cpp" qbs.installPrefix: "/usr/local" install: true } qbs-src-1.13.1/tests/auto/blackbox/testdata/makefile-generator/main.cpp000066400000000000000000000001231347155106100260470ustar00rootroot00000000000000#include int main() { std::cout << "Hello, World!" << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-c-language-version/000077500000000000000000000000001347155106100260235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-c-language-version/main.c000066400000000000000000000000311347155106100271050ustar00rootroot00000000000000int main() { return 0; } maximum-c-language-version.qbs000066400000000000000000000007301347155106100336140ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-c-language-versionCppApplication { name: "app" property bool enableNewestModule: true Probe { id: osProbe property stringList toolchain: qbs.toolchain configure: { if (toolchain.contains("msvc")) console.info("is msvc"); found = true; } } Depends { name: "oldmodule" } Depends { name: "newermodule" } Depends { name: "newestmodule"; condition: enableNewestModule } files: "main.c" } qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/000077500000000000000000000000001347155106100274735ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/newermodule/000077500000000000000000000000001347155106100320215ustar00rootroot00000000000000newermodule.qbs000066400000000000000000000001071347155106100347750ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/newermoduleModule { Depends { name: "cpp" } cpp.cLanguageVersion: "c99" } qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/newestmodule/000077500000000000000000000000001347155106100322065ustar00rootroot00000000000000newestmodule.qbs000066400000000000000000000001071347155106100353470ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/newestmoduleModule { Depends { name: "cpp" } cpp.cLanguageVersion: "c11" } qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/oldmodule/000077500000000000000000000000001347155106100314575ustar00rootroot00000000000000oldmodule.qbs000066400000000000000000000001071347155106100340710ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-c-language-version/modules/oldmoduleModule { Depends { name: "cpp" } cpp.cLanguageVersion: "c90" } qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/000077500000000000000000000000001347155106100264035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/main.cpp000066400000000000000000000000161347155106100300300ustar00rootroot00000000000000int main() {} maximum-cxx-language-version.qbs000066400000000000000000000003601347155106100345530ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-cxx-language-versionCppApplication { name: "app" property bool enableNewestModule: true Depends { name: "oldmodule" } Depends { name: "newermodule" } Depends { name: "newestmodule"; condition: enableNewestModule } files: "main.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/000077500000000000000000000000001347155106100300535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newermodule/000077500000000000000000000000001347155106100324015ustar00rootroot00000000000000newermodule.qbs000066400000000000000000000001131347155106100353520ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newermoduleModule { Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++14" } qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newestmodule/000077500000000000000000000000001347155106100325665ustar00rootroot00000000000000newestmodule.qbs000066400000000000000000000001131347155106100357240ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/newestmoduleModule { Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++17" } qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/oldmodule/000077500000000000000000000000001347155106100320375ustar00rootroot00000000000000oldmodule.qbs000066400000000000000000000001131347155106100344460ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/maximum-cxx-language-version/modules/oldmoduleModule { Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++11" } qbs-src-1.13.1/tests/auto/blackbox/testdata/minimumSystemVersion/000077500000000000000000000000001347155106100251105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/minimumSystemVersion/fakewindows.qbs000066400000000000000000000007251347155106100301440ustar00rootroot00000000000000import qbs.Utilities // non-existent versions of Windows should print a QBS warning // (but will still compile and link since we avoid passing a // bad value to the linker) CppApplication { condition: qbs.targetOS.contains("windows") files: ["main.cpp"] consoleApplication: true cpp.minimumWindowsVersion: "5.3" cpp.defines: [ "QBS_WINVER=0x503", "TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath) ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/minimumSystemVersion/macappstore.qbs000066400000000000000000000006071347155106100301400ustar00rootroot00000000000000// just to make sure three-digit minimum versions work on macOS // this only affects the value of __MAC_OS_X_VERSION_MIN_REQUIRED, // not the actual LC_VERSION_MIN_MACOSX command which is limited to two CppApplication { condition: qbs.targetOS.contains("macos") files: ["main.mm"] consoleApplication: true cpp.frameworks: "Foundation" cpp.minimumMacosVersion: "10.7.1" } qbs-src-1.13.1/tests/auto/blackbox/testdata/minimumSystemVersion/main.cpp000066400000000000000000000067541347155106100265540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef _WIN32 #include #include #include #include #include #include #include #endif int main(int argc, char *argv[]) { if (argc != 1) return 1; #ifdef _WIN32 #if defined(WINVER) && defined(QBS_WINVER) std::cout << "WINVER=" << WINVER << std::endl; std::string command = TOOLCHAIN_INSTALL_PATH; std::replace(command.begin(), command.end(), '/', '\\'); command = "\"\"" + command; #ifdef __GNUC__ command += "\\objdump.exe\" -p \""; #else command += "\\dumpbin.exe\" /HEADERS \""; #endif command += argv[0]; command += "\" > qbs-test-dumpbin.txt\""; int status = ::system(command.c_str()); if (status != 0) return status; std::ifstream in("qbs-test-dumpbin.txt"); std::string s; while (std::getline(in, s)) { #ifdef __GNUC__ static const char *majorOSystemVersion = "MajorOSystemVersion\t"; if (s.find(majorOSystemVersion) != std::string::npos) std::cout << s.substr(std::strlen(majorOSystemVersion)); static const char *minorOSystemVersion = "MinorOSystemVersion\t"; if (s.find(minorOSystemVersion) != std::string::npos) std::cout << ".0" << s.substr(std::strlen(minorOSystemVersion)) << " operating system version" << std::endl; static const char *majorSubsystemVersion = "MajorSubsystemVersion\t"; if (s.find(majorSubsystemVersion) != std::string::npos) std::cout << s.substr(std::strlen(majorSubsystemVersion)); static const char *minorSubsystemVersion = "MinorSubsystemVersion\t"; if (s.find(minorSubsystemVersion) != std::string::npos) std::cout << ".0" << s.substr(std::strlen(minorSubsystemVersion)) << " subsystem version" << std::endl; #else if (s.find("operating system version") != std::string::npos || s.find("subsystem version") != std::string::npos) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); std::cout << s << std::endl; } #endif } unlink("qbs-test-dumpbin.txt"); #else std::cout << "WINVER is not defined" << std::endl; #endif #endif return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/minimumSystemVersion/main.mm000066400000000000000000000057521347155106100264000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #import int main() { // This gets set by -mmacosx-version-min. If left undefined, defaults to the current OS version. std::cout << "__MAC_OS_X_VERSION_MIN_REQUIRED=" << __MAC_OS_X_VERSION_MIN_REQUIRED << std::endl; bool print = false; NSTask *task = [[NSTask alloc] init]; [task setLaunchPath:@"/usr/bin/otool"]; [task setArguments:[NSArray arrayWithObjects:@"-l", [[[NSProcessInfo processInfo] arguments] firstObject], nil]]; NSPipe *pipe = [NSPipe pipe]; [task setStandardOutput:pipe]; [task launch]; NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile]; [task waitUntilExit]; NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSString *line; NSEnumerator *enumerator = [[result componentsSeparatedByString:@"\n"] objectEnumerator]; while ((line = [enumerator nextObject]) != nil) { if ([line rangeOfString:@"LC_VERSION_MIN_MACOSX"].location != NSNotFound) print = true; if (print && [line rangeOfString:@"version"].location != NSNotFound) { std::cout << [[line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] UTF8String] << std::endl; print = false; continue; } #ifdef __clang__ #if __clang_major__ >= 10 && __clang_minor__ >= 0 if ([line rangeOfString:@"LC_BUILD_VERSION"].location != NSNotFound) print = true; if (print && [line rangeOfString:@"minos"].location != NSNotFound) { std::cout << [[line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] UTF8String] << std::endl; print = false; } #endif #endif // __clang__ } } qbs-src-1.13.1/tests/auto/blackbox/testdata/minimumSystemVersion/specific.qbs000066400000000000000000000014361347155106100274100ustar00rootroot00000000000000import qbs.Utilities // a specific version of the operating systems is specified // when the application is run its output should confirm // that the given values took effect CppApplication { condition: qbs.targetOS.contains("windows") || qbs.targetOS.contains("macos") files: [qbs.targetOS.contains("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true Properties { condition: qbs.targetOS.contains("windows") cpp.minimumWindowsVersion: "6.0" cpp.defines: [ "QBS_WINVER=0x600", "TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath) ] } Properties { condition: qbs.targetOS.contains("macos") cpp.frameworks: "Foundation" cpp.minimumMacosVersion: "10.7" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified-forced.qbs000066400000000000000000000012621347155106100313560ustar00rootroot00000000000000import qbs.Utilities // no minimum versions are specified, and explicitly set to undefined in // case the profile has set it CppApplication { files: [qbs.targetOS.contains("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true cpp.minimumWindowsVersion: undefined cpp.minimumMacosVersion: undefined cpp.minimumIosVersion: undefined cpp.minimumAndroidVersion: undefined Properties { condition: qbs.targetOS.contains("windows") cpp.defines: ["TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath)] } Properties { condition: qbs.targetOS.contains("darwin") cpp.frameworks: "Foundation" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified.qbs000066400000000000000000000007661347155106100301260ustar00rootroot00000000000000import qbs.Utilities // no minimum versions are specified so the profile defaults will be used CppApplication { files: [qbs.targetOS.contains("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true Properties { condition: qbs.targetOS.contains("windows") cpp.defines: ["TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath)] } Properties { condition: qbs.targetOS.contains("darwin") cpp.frameworks: "Foundation" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-dependency/000077500000000000000000000000001347155106100244475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-dependency/main.cpp000066400000000000000000000024021347155106100260750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-dependency/missing-dependency.qbs000066400000000000000000000013661347155106100307510ustar00rootroot00000000000000import qbs.TextFile Project { Product { name: "theDep" type: ["genheader"] Rule { multiplex: true Artifact { filePath: project.buildDirectory + "/theHeader.h" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return [cmd]; } } } CppApplication { name: "theApp" cpp.includePaths: [project.buildDirectory] files: ["main.cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-override-prefix/000077500000000000000000000000001347155106100254435ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-override-prefix/missing-override-prefix.qbs000066400000000000000000000000141347155106100327260ustar00rootroot00000000000000Product { } qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-project-file/000077500000000000000000000000001347155106100247145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-project-file/ambiguous-dir/000077500000000000000000000000001347155106100274635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-project-file/ambiguous-dir/p1.qbs000066400000000000000000000000001347155106100305000ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-project-file/ambiguous-dir/p2.qbs000066400000000000000000000000001347155106100305010ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-project-file/ambiguous-dir/p3.qbs000066400000000000000000000000001347155106100305020ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-project-file/empty-dir/000077500000000000000000000000001347155106100266265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-project-file/empty-dir/irrelevant.txt000066400000000000000000000000001347155106100315300ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-project-file/project-dir/000077500000000000000000000000001347155106100271365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-project-file/project-dir/file.cpp000066400000000000000000000000151347155106100305550ustar00rootroot00000000000000void f() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-project-file/project-dir/main.cpp000066400000000000000000000000161347155106100305630ustar00rootroot00000000000000int main() {} missing-project-file.qbs000066400000000000000000000001151347155106100336150ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/missing-project-file/project-dirCppApplication { files: [ "file.cpp", "main.cpp" ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/module-conditions/000077500000000000000000000000001347155106100243165ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/module-conditions/module-conditions.qbs000066400000000000000000000006311347155106100304610ustar00rootroot00000000000000import qbs Project { Product { name: "p1" qbs.architecture: "a" Depends { name: "m" } } Product { name: "p2" qbs.architecture: "b" Depends { name: "m" } } Product { name: "p3" multiplexByQbsProperties: "architectures" aggregate: false qbs.architectures: ["b", "c", "d"] Depends { name: "m" } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/module-conditions/modules/000077500000000000000000000000001347155106100257665ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/module-conditions/modules/m/000077500000000000000000000000001347155106100262225ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/module-conditions/modules/m/m1.qbs000066400000000000000000000001541347155106100272460ustar00rootroot00000000000000Module { condition: qbs.architecture === "a" validate: { console.info("loaded m1"); } } qbs-src-1.13.1/tests/auto/blackbox/testdata/module-conditions/modules/m/m2.qbs000066400000000000000000000001541347155106100272470ustar00rootroot00000000000000Module { condition: qbs.architecture === "b" validate: { console.info("loaded m2"); } } qbs-src-1.13.1/tests/auto/blackbox/testdata/module-conditions/modules/m/m3.qbs000066400000000000000000000001541347155106100272500ustar00rootroot00000000000000Module { condition: qbs.architecture === "c" validate: { console.info("loaded m3"); } } qbs-src-1.13.1/tests/auto/blackbox/testdata/module-conditions/modules/m/m4.qbs000066400000000000000000000001541347155106100272510ustar00rootroot00000000000000Module { condition: qbs.architecture === "d" validate: { console.info("loaded m4"); } } qbs-src-1.13.1/tests/auto/blackbox/testdata/module-providers/000077500000000000000000000000001347155106100241625ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/module-providers/main.cpp000066400000000000000000000001671347155106100256160ustar00rootroot00000000000000#include int main() { std::cout << "The letters are " << LETTER1 << " and " << LETTER2 << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/module-providers/module-providers.qbs000066400000000000000000000010771347155106100301760ustar00rootroot00000000000000Project { CppApplication { name: "app1" Depends { name: "mygenerator.module1" } Depends { name: "mygenerator.module2" } moduleProviders.mygenerator.chooseLettersFrom: "beginning" files: "main.cpp" } CppApplication { name: "app2" Depends { name: "mygenerator.module1" } Depends { name: "mygenerator.module2" } Profile { name: "myProfile" moduleProviders.mygenerator.chooseLettersFrom: "end" } qbs.profile: "myProfile" files: "main.cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/module-providers/module-providers/000077500000000000000000000000001347155106100274625ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/module-providers/module-providers/mygenerator/000077500000000000000000000000001347155106100320165ustar00rootroot00000000000000provider.qbs000066400000000000000000000025501347155106100343020ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/module-providers/module-providers/mygeneratorimport qbs.File; import qbs.FileInfo; import qbs.TextFile; ModuleProvider { property string chooseLettersFrom relativeSearchPaths: { console.info("Running setup script for " + name); var startAtBeginning = chooseLettersFrom === "beginning"; var moduleBaseDir = FileInfo.joinPaths(outputBaseDir, "modules", "mygenerator"); var module1Dir = FileInfo.joinPaths(moduleBaseDir, "module1"); File.makePath(module1Dir); var module1 = new TextFile(FileInfo.joinPaths(module1Dir, "module1.qbs"), TextFile.WriteOnly); module1.writeLine("Module {"); module1.writeLine(" Depends { name: 'cpp' }"); module1.writeLine(" cpp.defines: 'LETTER1=" + (startAtBeginning ? "\\\'A\\\'" : "\\\'Z\\\'") + "'"); module1.writeLine("}"); module1.close(); var module2Dir = FileInfo.joinPaths(moduleBaseDir, "module2"); File.makePath(module2Dir); var module2 = new TextFile(FileInfo.joinPaths(module2Dir, "module2.qbs"), TextFile.WriteOnly); module2.writeLine("Module {"); module2.writeLine(" Depends { name: 'cpp' }"); module2.writeLine(" cpp.defines: 'LETTER2=" + (startAtBeginning ? "\\\'B\\\'" : "\\\'Y\\\'") + "'"); module2.writeLine("}"); module2.close(); return ""; } } qbs-src-1.13.1/tests/auto/blackbox/testdata/moved-file-dependency/000077500000000000000000000000001347155106100250255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/moved-file-dependency/main.cpp000066400000000000000000000000471347155106100264560ustar00rootroot00000000000000#include int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/moved-file-dependency/moved-file-dependency.qbs000066400000000000000000000001301347155106100316710ustar00rootroot00000000000000CppApplication { cpp.includePaths: ["subdir1", "subdir2"] files: ["main.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/moved-file-dependency/subdir1/000077500000000000000000000000001347155106100263765ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/moved-file-dependency/subdir1/theheader.h000066400000000000000000000000001347155106100304660ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/multiple-changes/000077500000000000000000000000001347155106100241235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/multiple-changes/dummy.txt000066400000000000000000000000001347155106100260050ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/multiple-changes/multiple-changes.qbs000066400000000000000000000014011347155106100300670ustar00rootroot00000000000000Project { property bool prop: false Product { name: "test" type: ["out-type"] Group { name: "Rule input" files: ["dummy.txt"] fileTags: ["in-type"] } Group { name: "irrelevant" files: ["*.blubb"] } Rule { inputs: ["in-type"] Artifact { filePath: "dummy.out" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info("prop: " + project.prop); } return [cmd]; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/multiple-configurations/000077500000000000000000000000001347155106100255455ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/multiple-configurations/file.cpp000066400000000000000000000000501347155106100271630ustar00rootroot00000000000000#include void f() { l(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/multiple-configurations/file.h000066400000000000000000000000121347155106100266260ustar00rootroot00000000000000void f(); qbs-src-1.13.1/tests/auto/blackbox/testdata/multiple-configurations/lib.cpp000066400000000000000000000000141347155106100270120ustar00rootroot00000000000000void l() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/multiple-configurations/lib.h000066400000000000000000000000121347155106100264550ustar00rootroot00000000000000void l(); qbs-src-1.13.1/tests/auto/blackbox/testdata/multiple-configurations/main.cpp000066400000000000000000000000531347155106100271730ustar00rootroot00000000000000#include int main() { f(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/multiple-configurations/multiple-configurations.qbs000066400000000000000000000004611347155106100331400ustar00rootroot00000000000000Project { StaticLibrary { name: "lib" Depends { name: "cpp" } files: ["lib.cpp", "lib.h"] } CppApplication { name: "app" Depends { name: "lib" } cpp.includePaths: project.sourceDirectory files: ["file.cpp", "file.h", "main.cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/multiplexed-tool/000077500000000000000000000000001347155106100241715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/multiplexed-tool/multiplexed-tool.qbs000066400000000000000000000030701347155106100302070ustar00rootroot00000000000000Project { CppApplication { name: "tool" consoleApplication: true Profile { name: "debugProfile" qbs.buildVariant: "debug" } Profile { name: "releaseProfile" qbs.buildVariant: "release" } multiplexByQbsProperties: "profiles" qbs.profiles: ["debugProfile", "releaseProfile"] files: "tool.cpp" Properties { condition: qbs.buildVariant === "debug" cpp.defines: "WRONG_VARIANT" } Export { Rule { multiplex: true inputsFromDependencies: "application" Artifact { filePath: "tool.out" fileTags: "tool.output" } prepare: { var cmd = new Command(input.filePath, []); cmd.description = "creating " + output.fileName; return cmd; } } } } Product { name: "p" type: "tool.output" multiplexByQbsProperties: "buildVariants" qbs.buildVariants: ["debug", "release"] Depends { name: "tool"; profiles: "releaseProfile" } } Product { name: "p2" type: "tool.output" multiplexByQbsProperties: "buildVariants" qbs.buildVariants: ["debug", "release"] Depends { name: "helper" } } Product { name: "helper" Export { Depends { name: "tool"; profiles: "releaseProfile" } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/multiplexed-tool/tool.cpp000066400000000000000000000001301347155106100256440ustar00rootroot00000000000000#include int main() { #ifdef WRONG_VARIANT return EXIT_FAILURE; #endif } qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/000077500000000000000000000000001347155106100234615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/file3.cpp000066400000000000000000000024461347155106100251750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef REQUIRED_FOR_FILE3 #error "missing define" #endif void file3() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/file3.h000066400000000000000000000023511347155106100246350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void file3(); qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/main.cpp000066400000000000000000000025531347155106100251160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "file1.h" #include "file2.h" #include "file3.h" #include "other.h" int main() { file1(); file2(); file3(); other(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/modules/000077500000000000000000000000001347155106100251315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/modules/themodule/000077500000000000000000000000001347155106100271175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/modules/themodule/themodule.qbs000066400000000000000000000003011347155106100316060ustar00rootroot00000000000000Module { Group { cpp.defines: ["REQUIRED_FOR_FILE3"] Group { prefix: product.sourceDirectory + '/' files: ["file3.cpp", "file3.h"] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/nested-groups.qbs000066400000000000000000000020711347155106100267670ustar00rootroot00000000000000CppApplication { consoleApplication: true Depends { name: "themodule" } cpp.includePaths: ["subdir"] files: ["main.cpp"] Group { prefix: "subdir/" cpp.defines: ["REQUIRED_FOR_FILE1", "BREAKS_FILE2"] fileTags: ["cpp"] // This group has no files, and that's okay. Group { files: ["other.cpp", "other.h"] Group { cpp.defines: outer.concat(["ALSO_REQUIRED_FOR_FILE1"]) files: ["file1.cpp", "file1.h"] } Group { cpp.defines: ["REQUIRED_FOR_FILE2"] files: ["file2.cpp", "file2.h"] } Group { name: "disabled" condition: false Group { name: "indirectly disabled" condition: true files: ["main2.cpp"] } } Group { name: "no tags" fileTags: [] files: ["main3.cpp"] } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/subdir/000077500000000000000000000000001347155106100247515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/subdir/file1.cpp000066400000000000000000000025461347155106100264640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef REQUIRED_FOR_FILE1 #error "missing define" #endif #ifndef ALSO_REQUIRED_FOR_FILE1 #error "missing define" #endif void file1() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/subdir/file1.h000066400000000000000000000023511347155106100261230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void file1(); qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/subdir/file2.cpp000066400000000000000000000025351347155106100264630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef BREAKS_FILE2 #error "unexpected define" #endif #ifndef REQUIRED_FOR_FILE2 #error "missing define" #endif void file2() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/subdir/file2.h000066400000000000000000000023511347155106100261240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void file2(); qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/subdir/main2.cpp000066400000000000000000000023521347155106100264650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/subdir/main3.cpp000066400000000000000000000023521347155106100264660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/subdir/other.cpp000066400000000000000000000025341347155106100266020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef REQUIRED_FOR_FILE1 #error "missing define" #endif #ifndef BREAKS_FILE2 #error "missing define" #endif void other() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-groups/subdir/other.h000066400000000000000000000023511347155106100262440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void other(); qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-properties/000077500000000000000000000000001347155106100243365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-properties/dummy.txt000066400000000000000000000000001347155106100262200ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-properties/modules/000077500000000000000000000000001347155106100260065ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-properties/modules/higherlevel/000077500000000000000000000000001347155106100303045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-properties/modules/higherlevel/higher-level.qbs000066400000000000000000000001441347155106100333650ustar00rootroot00000000000000Module { Depends { name: "lowerlevel" } lowerlevel.propDependency: "value in higherlevel" } qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/000077500000000000000000000000001347155106100301665ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/lower-level.qbs000066400000000000000000000007611347155106100331360ustar00rootroot00000000000000Module { property string propDependency: "value in lowerlevel module" property string prop: propDependency property string someOtherProp Rule { inputs: ["dummy-input"] outputFileTags: "mytype" prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function() { }; var prop = product.lowerlevel.prop; cmd.description = "lowerlevel.prop is '" + prop + "'."; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/nested-properties/product.qbs000066400000000000000000000006741347155106100265340ustar00rootroot00000000000000Project { Product { name: "dep" Export { Depends { name: "lowerlevel" } lowerlevel.someOtherProp: "blubb" } } Product { type: "mytype" name: "toplevel" Depends { name: "higherlevel" } Depends { name: "lowerlevel" } Depends { name: "dep" } Group { files: ["dummy.txt"] fileTags: ["dummy-input"] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/new-output-artifact/000077500000000000000000000000001347155106100246045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/new-output-artifact/input.txt000066400000000000000000000000001347155106100264720ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/new-output-artifact/new-output-artifact.qbs000066400000000000000000000017571347155106100312470ustar00rootroot00000000000000import qbs.TextFile Product { name: "theProduct" type: ["output"] property int artifactCount: 99 Group { files: ["input.txt"] fileTags: ["input"] } qbs.installPrefix: "" Group { fileTagsFilter: product.type qbs.install: true } Rule { inputs: ["input"] outputFileTags: ["output"] outputArtifacts: { var list = []; for (var i = 0; i < product.artifactCount; ++i) list.push({ filePath: "output_" + i + ".out", fileTags: ["output"]}); return list; } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { for (var i = 0; i < outputs["output"].length; ++i) { var f = new TextFile(outputs["output"][i].filePath, TextFile.WriteOnly); f.close(); } } return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/no-exported-symbols/000077500000000000000000000000001347155106100246145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/no-exported-symbols/lib.cpp000066400000000000000000000000321347155106100260610ustar00rootroot00000000000000static void someFunc() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/no-exported-symbols/lib.h000066400000000000000000000001161347155106100255310ustar00rootroot00000000000000#ifndef TEST_LIB #define TEST_LIB inline int success() { return 0; } #endif qbs-src-1.13.1/tests/auto/blackbox/testdata/no-exported-symbols/main.cpp000066400000000000000000000000671347155106100262470ustar00rootroot00000000000000#include int main() { return success(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/no-exported-symbols/no-exported-symbols.qbs000066400000000000000000000013261347155106100312570ustar00rootroot00000000000000Project { DynamicLibrary { name: "the_lib" Depends { name: "cpp" } files: ["lib.cpp", "lib.h"] Export { Depends { name: "cpp" } cpp.includePaths: path } Probe { id: toolchainProbe property stringList toolchain: qbs.toolchain configure: { if (toolchain.contains("msvc")) console.info("compiler is MSVC") else console.info("compiler is not MSVC") } } } CppApplication { name: "the_app" property bool link Depends { name: "the_lib"; cpp.link: product.link } files: "main.cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/no-profile/000077500000000000000000000000001347155106100227345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/no-profile/no-profile.qbs000066400000000000000000000001261347155106100255140ustar00rootroot00000000000000Product { property bool dummy: { console.info("profile: " + project.profile); } } qbs-src-1.13.1/tests/auto/blackbox/testdata/no-such-profile/000077500000000000000000000000001347155106100236745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/no-such-profile/no-such-profile.qbs000066400000000000000000000001021347155106100274060ustar00rootroot00000000000000import qbs Product { name: "theProduct" property int p } qbs-src-1.13.1/tests/auto/blackbox/testdata/nodejs/000077500000000000000000000000001347155106100221445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nodejs/hello.js000066400000000000000000000000611347155106100236020ustar00rootroot00000000000000if (console) { console.log("hello world"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/nodejs/hello.qbs000066400000000000000000000001171347155106100237550ustar00rootroot00000000000000NodeJSApplication { nodejs.applicationFile: "hello.js" name: "hello" } qbs-src-1.13.1/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/000077500000000000000000000000001347155106100273725ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/broken.cpp000066400000000000000000000000071347155106100313530ustar00rootroot00000000000000broken qbs-src-1.13.1/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/fine.cpp000066400000000000000000000023511347155106100310200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} non-broken-files-in-broken-product.qbs000066400000000000000000000001261347155106100365310ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/non-broken-files-in-broken-productCppApplication { consoleApplication: true files: ["fine.cpp", "broken.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/non-default-product/000077500000000000000000000000001347155106100245545ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/non-default-product/main.cpp000066400000000000000000000023511347155106100262050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/non-default-product/non-default-product.qbs000066400000000000000000000004731347155106100311610ustar00rootroot00000000000000Project { CppApplication { name: "default app" consoleApplication: true files: "main.cpp" } CppApplication { name: "non-default app" Depends { name: "default app" } consoleApplication: true builtByDefault: false files: "main.cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/not-always-updated/000077500000000000000000000000001347155106100244045ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/not-always-updated/not-always-updated.qbs000066400000000000000000000013711347155106100306370ustar00rootroot00000000000000import qbs.TextFile Product { type: "p" Rule { multiplex: true Artifact { filePath: "dummy.txt"; fileTags: "t1"; alwaysUpdated: false } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating dummy"; cmd.sourceCode = function() {}; return cmd; } } Rule { inputs: "t1" Artifact { filePath: "o.txt"; fileTags: "p" } prepare: { var cmd = new JavaScriptCommand; cmd.description = "creating final"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/nsis/000077500000000000000000000000001347155106100216365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nsis/hello.bat000066400000000000000000000000221347155106100234230ustar00rootroot00000000000000echo Hello world! qbs-src-1.13.1/tests/auto/blackbox/testdata/nsis/hello.nsi000066400000000000000000000005611347155106100234560ustar00rootroot00000000000000SetCompressor zlib !ifdef Win64 Name "Qbs Hello - ${qbs.architecture} (64-bit)" !else Name "Qbs Hello - ${qbs.architecture} (32-bit)" !endif OutFile "you-should-not-see-a-file-with-this-name.exe" InstallDir "$DESKTOP\Qbs Hello" RequestExecutionLevel user Page directory Page instfiles Section "" SetOutPath "$INSTDIR" File "${batchFile}" SectionEnd qbs-src-1.13.1/tests/auto/blackbox/testdata/nsis/hello.qbs000066400000000000000000000003661347155106100234550ustar00rootroot00000000000000NSISSetup { condition: qbs.targetOS.contains("windows") name: "Qbs Hello" targetName: "qbs-hello-" + qbs.architecture files: ["hello.nsi", "hello.bat"] nsis.defines: ["batchFile=hello.bat"] nsis.compressor: "lzma-solid" } qbs-src-1.13.1/tests/auto/blackbox/testdata/nsisDependencies/000077500000000000000000000000001347155106100241455ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/nsisDependencies/hello.nsi000066400000000000000000000002311347155106100257570ustar00rootroot00000000000000Page directory Page instfiles Section "" SetOutPath "$INSTDIR" File "${buildDirectory}\app.exe" File "${buildDirectory}\lib.dll" SectionEnd qbs-src-1.13.1/tests/auto/blackbox/testdata/nsisDependencies/main.c000066400000000000000000000000311347155106100252270ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/nsisDependencies/nsisDependencies.qbs000066400000000000000000000041151347155106100301400ustar00rootroot00000000000000import qbs.FileInfo import qbs.TextFile Project { condition: qbs.targetOS.contains("windows") NSISSetup { Depends { name: "app" } Depends { name: "lib" } name: "inst" files: ["hello.nsi"] nsis.defines: ["buildDirectory=" + FileInfo.toWindowsSeparators(project.buildDirectory)] destinationDirectory: project.buildDirectory } Application { Depends { name: "cpp" } name: "app" files: ["main.c"] Group { fileTagsFilter: product.type qbs.install: true } destinationDirectory: project.buildDirectory } DynamicLibrary { Depends { name: "cpp" } name: "lib" files: ["main.c"] Group { fileTagsFilter: product.type qbs.install: true } Rule { // This rule tries to provoke the installer into building too early (and the test // verifies that it does not) by causing the build of the installables to take // a lot longer. multiplex: true outputFileTags: ["c"] outputArtifacts: { var artifacts = []; for (var i = 0; i < 96; ++i) artifacts.push({ filePath: "c" + i + ".c", fileTags: ["c"] }); return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { for (var i = 0; i < outputs["c"].length; ++i) { var tf; try { tf = new TextFile(outputs["c"][i].filePath, TextFile.WriteOnly); tf.writeLine("int main" + i + "() { return 0; }"); } finally { if (tf) tf.close(); } } }; return [cmd]; } } destinationDirectory: project.buildDirectory } } qbs-src-1.13.1/tests/auto/blackbox/testdata/out-of-date-marking/000077500000000000000000000000001347155106100244345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/out-of-date-marking/main.c000066400000000000000000000000601347155106100255200ustar00rootroot00000000000000#include int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/out-of-date-marking/out-of-date-marking.qbs000066400000000000000000000010611347155106100307130ustar00rootroot00000000000000import qbs.TextFile CppApplication { name: "app" files: "main.c" cpp.includePaths: buildDirectory Rule { multiplex: true alwaysRun: true Artifact { filePath: "myheader.h"; fileTags: "hpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/output-artifact-auto-tagging/000077500000000000000000000000001347155106100264015ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/output-artifact-auto-tagging/broken.cpp.in000066400000000000000000000000261347155106100307700ustar00rootroot00000000000000void f() { blubb(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/output-artifact-auto-tagging/main.cpp.in000066400000000000000000000000161347155106100304330ustar00rootroot00000000000000int main() {} output-artifact-auto-tagging.qbs000066400000000000000000000016301347155106100345500ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/output-artifact-auto-taggingimport qbs.File CppApplication { consoleApplication: true Group { files: ["broken.cpp.in", "main.cpp.in"] fileTags: ["cpp.in"] } Rule { multiplex: true inputs: ["cpp.in"] outputFileTags: ["cpp"] outputArtifacts: [{ filePath: "main.cpp" }, { filePath: "broken.nomatch" }] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating main.cpp"; cmd.sourceCode = function() { File.copy(product.sourceDirectory + "/main.cpp.in", product.buildDirectory + "/main.cpp"); File.copy(product.sourceDirectory + "/broken.cpp.in", product.buildDirectory + "/broken.nomatch"); }; return [cmd]; } } FileTagger { patterns: ["*.nomatch"] fileTags: ["utter nonsense"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/overrideProjectProperties/000077500000000000000000000000001347155106100261055ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/overrideProjectProperties/helper_lib.qbs000066400000000000000000000003111347155106100307140ustar00rootroot00000000000000DynamicLibrary { name: "helperLib" files: "helperlib.cpp" Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } qbs-src-1.13.1/tests/auto/blackbox/testdata/overrideProjectProperties/helperlib.cpp000066400000000000000000000024271347155106100305640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" void DLL_EXPORT helperFunc() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/overrideProjectProperties/main.cpp000066400000000000000000000023701347155106100275370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/overrideProjectProperties/main2.cpp000066400000000000000000000025051347155106100276210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" void DLL_IMPORT helperFunc(); int main() { helperFunc(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/overrideProjectProperties/overrideProjectProperties.qbs000066400000000000000000000023221347155106100340360ustar00rootroot00000000000000Project { property string nameSuffix: "" property bool someBool property int someInt property stringList someStringList Product { consoleApplication: true type: "application" property string mainFile: "" name: "MyApp" + nameSuffix Depends { name: "cpp" } files: { // Check types of the project's custom properties here. // Provoke a build error if the expected types do not match. var wrongFile = "doesnotexist.cpp"; if (typeof project.someBool != "boolean") { console.info("someBool has a wrong type: " + typeof project.someBool); return wrongFile; } if (typeof project.someInt != "number") { console.info("someInt has a wrong type: " + typeof project.someInt); return wrongFile; } if (typeof project.someStringList != "object") { console.info("someStringList has a wrong type: " + typeof project.someStringList); return wrongFile; } // Return the mainFile property that is set on the command line. return [mainFile]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/overrideProjectProperties/project_using_helper_lib.qbs000066400000000000000000000004621347155106100336560ustar00rootroot00000000000000Project { property bool linkSuccessfully: false references: linkSuccessfully ? ["helper_lib.qbs"] : [] CppApplication { consoleApplication: true Depends { condition: project.linkSuccessfully name: "helperLib" } files: "main2.cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/pch-change-tracking/000077500000000000000000000000001347155106100244575ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pch-change-tracking/header1.h000066400000000000000000000025041347155106100261420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #pragma once #include inline void printGreeting() { std::cout << "Tach." << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/pch-change-tracking/header2.cpp000066400000000000000000000002571347155106100265010ustar00rootroot00000000000000#include "header2.h" // header1 is forced-included via pch. void printPersonalGreeting() { printGreeting(); std::cout << "Was geht, Rumpelstilzchen?" << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/pch-change-tracking/header2.h000066400000000000000000000024061347155106100261440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #pragma once void printPersonalGreeting(); qbs-src-1.13.1/tests/auto/blackbox/testdata/pch-change-tracking/main.cpp000066400000000000000000000025031347155106100261070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "header2.h" #include "pch.h" int main() { printGreeting(); printPersonalGreeting(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/pch-change-tracking/pch-change-tracking.qbs000066400000000000000000000003101347155106100307550ustar00rootroot00000000000000CppApplication { files: [ "header1.h", "header2.cpp", "header2.h", "main.cpp", ] Group { files: ["pch.h"] fileTags: ["cpp_pch_src"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/pch-change-tracking/pch.h000066400000000000000000000023601347155106100254030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "header1.h" qbs-src-1.13.1/tests/auto/blackbox/testdata/per-group-define-in-export-item/000077500000000000000000000000001347155106100267115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/per-group-define-in-export-item/main.cpp000066400000000000000000000000411347155106100303340ustar00rootroot00000000000000#ifdef MAIN int main() {} #endif per-group-define-in-export-item.qbs000066400000000000000000000004531347155106100353720ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/per-group-define-in-export-itemProject { Product { name: "dep" Export { Depends { name: "cpp" } Group { cpp.defines: ["MAIN"] files: ["main.cpp"] } } } Application { name: "app" Depends { name: "dep" } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/000077500000000000000000000000001347155106100255335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/modules/000077500000000000000000000000001347155106100272035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/modules/themodule/000077500000000000000000000000001347155106100311715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/modules/themodule/themodule.qbs000066400000000000000000000010021347155106100336570ustar00rootroot00000000000000import qbs.Probes Module { Probes.PkgConfigProbe { id: theProbe name: "dummy" } property stringList libs: theProbe.libs Rule { multiplex: true outputFileTags: "theType" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info(product.name + " libs: " + JSON.stringify(product.themodule.libs)); } return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/pkg-config.qbs000066400000000000000000000007761347155106100303000ustar00rootroot00000000000000Project { property string packageBaseName Product { name: "theProduct1" type: ["theType"] Depends { name: "themodule" } qbs.sysroot: path + "/sysroot1" } Product { name: "theProduct2" type: ["theType"] Depends { name: "themodule" } qbs.sysroot: path + "/sysroot2" } Product { name: "theProduct3" type: ["theType"] Depends { name: "themodule" } qbs.sysroot: path + "/sysroot1" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot1/000077500000000000000000000000001347155106100273365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot1/usr/000077500000000000000000000000001347155106100301475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot1/usr/share/000077500000000000000000000000001347155106100312515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot1/usr/share/pkgconfig/000077500000000000000000000000001347155106100332205ustar00rootroot00000000000000dummy.pc000066400000000000000000000001471347155106100346220ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot1/usr/share/pkgconfigName: dummy1 Description: dummy1 package Version: 0.0.1 Requires: Libs: -L/usr/dummy -ldummy1 Cflags: qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot2/000077500000000000000000000000001347155106100273375ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot2/usr/000077500000000000000000000000001347155106100301505ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot2/usr/share/000077500000000000000000000000001347155106100312525ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot2/usr/share/pkgconfig/000077500000000000000000000000001347155106100332215ustar00rootroot00000000000000dummy.pc000066400000000000000000000001471347155106100346230ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/sysroot2/usr/share/pkgconfigName: dummy1 Description: dummy1 package Version: 0.0.1 Requires: Libs: -L/usr/dummy -ldummy1 Cflags: qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe/000077500000000000000000000000001347155106100240135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe/dummy1/000077500000000000000000000000001347155106100252275ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe/dummy1/dummy1.pc000066400000000000000000000001461347155106100267700ustar00rootroot00000000000000Name: dummy1 Description: dummy1 package Version: 0.0.1 Requires: Libs: -Ldummydir1 -ldummy1 Cflags: qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe/dummy2/000077500000000000000000000000001347155106100252305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe/dummy2/dummy2.pc000066400000000000000000000001461347155106100267720ustar00rootroot00000000000000Name: dummy2 Description: dummy2 package Version: 0.0.2 Requires: Libs: -Ldummydir2 -ldummy2 Cflags: qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe/modules/000077500000000000000000000000001347155106100254635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe/modules/themodule/000077500000000000000000000000001347155106100274515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe/modules/themodule/themodule.qbs000066400000000000000000000020211347155106100321410ustar00rootroot00000000000000import qbs.Probes Module { property string packageName property string libDir Probes.PkgConfigProbe { id: theProbe name: packageName libDirs: [libDir] } property bool probeSuccess: theProbe.found property stringList libs: theProbe.libs property stringList cFlags: theProbe.cflags property string packageVersion: theProbe.modversion Rule { multiplex: true outputFileTags: "theType" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info(product.name + " found: " + product.themodule.probeSuccess); console.info(product.name + " libs: " + JSON.stringify(product.themodule.libs)); console.info(product.name + " cflags: " + JSON.stringify(product.themodule.cFlags)); console.info(product.name + " version: " + product.themodule.packageVersion); } return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/pkg-config-probe/pkg-config.qbs000066400000000000000000000007441347155106100265530ustar00rootroot00000000000000Project { property string packageBaseName Product { name: "theProduct1" type: ["theType"] Depends { name: "themodule" } themodule.packageName: project.packageBaseName + "1" themodule.libDir: path + "/dummy1" } Product { name: "theProduct2" type: ["theType"] Depends { name: "themodule" } themodule.packageName: project.packageBaseName + "2" themodule.libDir: path + "/dummy2" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/plugin-dependency/000077500000000000000000000000001347155106100242745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/plugin-dependency/helper1.cpp000066400000000000000000000004051347155106100263370ustar00rootroot00000000000000#include #if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) #else # define EXPORT #endif #ifndef USING_HELPER2 #error define USING_HELPER2 missing #endif EXPORT void helper1_hello() { puts("helper1 says hello!"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/plugin-dependency/helper2.cpp000066400000000000000000000001631347155106100263410ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_EXPORT void helper2_hello() { puts("Hello from helper2!"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/plugin-dependency/main.cpp000066400000000000000000000003331347155106100257230ustar00rootroot00000000000000#include "../dllexport.h" DLL_IMPORT void plugin3_hello(); DLL_IMPORT void plugin4_hello(); DLL_IMPORT void helper1_hello(); int main() { plugin3_hello(); plugin4_hello(); helper1_hello(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/plugin-dependency/plugin-dependency.qbs000066400000000000000000000040621347155106100304170ustar00rootroot00000000000000Project { CppApplication { name: "myapp" files: ["main.cpp"] Depends { name: "plugin1" // not to be linked cpp.link: qbs.hostOS === undefined } Depends { name: "plugin2" } // not to be linked Depends { name: "plugin3" // supposed to be linked //property bool theCondition: true cpp.link: /*theCondition && */product.name === "myapp" // TODO: Make this work } Depends { name: "plugin4" } // supposed to be linked Depends { name: "helper1" } // supposed to be linked } DynamicLibrary { name: "plugin1" files: ["plugin1.cpp"] Depends { name: "cpp" } } DynamicLibrary { name: "plugin2" files: ["plugin2.cpp"] Depends { name: "cpp" } Export { Parameters { cpp.link: false // marker 1 } } } DynamicLibrary { name: "plugin3" files: ["plugin3.cpp"] Depends { name: "cpp" } Export { Parameters { cpp.link: false } } } DynamicLibrary { name: "plugin4" files: ["plugin4.cpp"] Depends { name: "cpp" } Export { Parameters { // property bool theCondition: true cpp.link: true // theCondition TODO: Make this work } } } DynamicLibrary { name: "helper1" files: ["helper1.cpp"] Depends { name: "cpp" } Depends { name: "helper2"; cpp.link: false /* marker 2 */ } Export { Depends { name: "cpp" } Depends { name: "helper2"; cpp.link: false } } } DynamicLibrary { name: "helper2" files: ["helper2.cpp"] Depends { name: "cpp" } Export { Depends { name: "cpp" } cpp.defines: ["USING_HELPER2"] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/plugin-dependency/plugin1.cpp000066400000000000000000000001631347155106100263570ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_EXPORT void plugin1_hello() { puts("plugin1 says hello!"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/plugin-dependency/plugin2.cpp000066400000000000000000000001631347155106100263600ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_EXPORT void plugin2_hello() { puts("plugin2 says hello!"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/plugin-dependency/plugin3.cpp000066400000000000000000000001631347155106100263610ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_EXPORT void plugin3_hello() { puts("plugin3 says hello!"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/plugin-dependency/plugin4.cpp000066400000000000000000000001631347155106100263620ustar00rootroot00000000000000#include "../dllexport.h" #include DLL_EXPORT void plugin4_hello() { puts("plugin4 says hello!"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/precompiled-and-prefix-headers/000077500000000000000000000000001347155106100266315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/precompiled-and-prefix-headers/main.cpp000066400000000000000000000023521347155106100302630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/precompiled-and-prefix-headers/pch.h000066400000000000000000000023331347155106100275550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ precompiled-and-prefix-headers.qbs000066400000000000000000000003741347155106100352340ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/precompiled-and-prefix-headersCppApplication { name: "MyApp" consoleApplication: true cpp.includePaths: [product.buildDirectory] cpp.prefixHeaders: [ "prefix.h" ] Group { files: ["pch.h"] fileTags: ["cpp_pch_src"] } files: ["main.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/precompiled-and-prefix-headers/prefix.h000066400000000000000000000023331347155106100303000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-1.13.1/tests/auto/blackbox/testdata/prevent-floating-point-values/000077500000000000000000000000001347155106100265725ustar00rootroot00000000000000prevent-floating-point-values.qbs000066400000000000000000000001341347155106100351300ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/prevent-floating-point-valuesProduct { name: "p" property bool dummy: { console.info("version: " + version); } } qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-change-tracking/000077500000000000000000000000001347155106100250145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-change-tracking/probe-change-tracking.qbs000066400000000000000000000017701347155106100316620ustar00rootroot00000000000000Project { Probe { id: tlpProbe property int confValue configure: { console.info("running tlpProbe"); confValue = 5; } } property int tlpCount: tlpProbe.confValue Project { Probe { id: subProbe property int confValue configure: { console.info("running subProbe"); confValue = 7; } } property int subCount: subProbe.confValue Product { name: "theProduct" property bool runProbe property int v1: project.tlpCount property int v2: project.subCount Probe { id: productProbe condition: product.runProbe property int v1: product.v1 property int v2: product.v2 configure: { console.info("running productProbe: " + (v1 + v2)); } } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/000077500000000000000000000000001347155106100255105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/dependee.qbs000066400000000000000000000004241347155106100277700ustar00rootroot00000000000000Product { name: "dependee" Depends { name: "myothermodule" } Depends { name: "dependency" } type: ["out", "dep-out"] Group { files: "test.in" fileTags: ["dep-in"] } Group { files: "test2.in" fileTags: ["in"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/dependency.qbs000066400000000000000000000001331347155106100303320ustar00rootroot00000000000000Product { name: "dependency" Export { Depends { name: "mymodule" } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/000077500000000000000000000000001347155106100271605ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/000077500000000000000000000000001347155106100311365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/depmodule.qbs000066400000000000000000000007741347155106100336330ustar00rootroot00000000000000Module { property string prop property stringList listProp: [] Rule { inputs: ["dep-in"] outputFileTags: "dep-out" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating dep-out artifact"; cmd.sourceCode = function() { console.info("prop: " + product.depmodule.prop); console.info("listProp: " + product.depmodule.listProp); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/000077500000000000000000000000001347155106100310135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/mymodule.qbs000066400000000000000000000011361347155106100333560ustar00rootroot00000000000000Module { Depends { name: "depmodule" } Probe { id: theProbe configure: { found = true; } } property bool found: theProbe.found depmodule.prop: found ? "yes" : "no" depmodule.listProp: theProbe.found ? ["my"] : [] Rule { inputs: ["in"] outputFileTags: "out" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating out artifact"; cmd.sourceCode = function() { console.info("found: " + product.mymodule.found); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/myothermodule/000077500000000000000000000000001347155106100320555ustar00rootroot00000000000000myothermodule.qbs000066400000000000000000000001211347155106100353740ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/modules/myothermoduleModule { Depends { name: "depmodule" } depmodule.listProp: ["myother"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/probe-in-exported-module.qbs000066400000000000000000000001011347155106100330350ustar00rootroot00000000000000Project { references: [ "dependee.qbs", "dependency.qbs" ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/test.in000066400000000000000000000000001347155106100270050ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probe-in-exported-module/test2.in000066400000000000000000000000001347155106100270670ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probeProperties/000077500000000000000000000000001347155106100240465ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probeProperties/bin/000077500000000000000000000000001347155106100246165ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probeProperties/bin/tool000066400000000000000000000000001347155106100255040ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probeProperties/main.c000066400000000000000000000023641347155106100251430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs000066400000000000000000000013211347155106100277360ustar00rootroot00000000000000import qbs.Probes CppApplication { Probes.PathProbe { id: probe1 names: ["bin/tool"] platformSearchPaths: [product.sourceDirectory] } Probes.PathProbe { id: probe2 names: ["tool"] platformSearchPaths: [product.sourceDirectory + "/bin"] } targetName: { console.info("probe1.fileName=" + probe1.fileName); console.info("probe1.path=" + probe1.path); console.info("probe1.filePath=" + probe1.filePath); console.info("probe2.fileName=" + probe2.fileName); console.info("probe2.path=" + probe2.path); console.info("probe2.filePath=" + probe2.filePath); return name; } files: ["main.c"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-and-array-properties/000077500000000000000000000000001347155106100262225ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-and-array-properties/modules/000077500000000000000000000000001347155106100276725ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymodule/000077500000000000000000000000001347155106100315255ustar00rootroot00000000000000mymodule.qbs000066400000000000000000000012031347155106100340040ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymoduleModule { Probe { id: propProbe property stringList prop: [] configure: { prop = []; prop.push("probe"); found = true; } } property stringList prop: propProbe.found ? propProbe.prop : ["other"] Rule { multiplex: true outputFileTags: "the-output" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating dummy"; cmd.sourceCode = function() { console.info("prop: " + JSON.stringify(product.mymodule.prop)); } return [cmd]; } } } probes-and-array-properties.qbs000066400000000000000000000001761347155106100342160ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-and-array-propertiesProduct { name: "theProduct" type: ["the-output"] Depends { name: "mymodule" } // mymodule.prop: ["product"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-and-shadow-products/000077500000000000000000000000001347155106100260405ustar00rootroot00000000000000probes-and-shadow-products.qbs000066400000000000000000000003401347155106100336430ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-and-shadow-productsProduct { name: "p" multiplexByQbsProperties: "buildVariants" qbs.buildVariants: ["debug", "release"] Export { Probe { id: dummy configure: { found = true; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-in-nested-modules/000077500000000000000000000000001347155106100255065ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/000077500000000000000000000000001347155106100271565ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/inner/000077500000000000000000000000001347155106100302715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/inner/inner.qbs000066400000000000000000000006141347155106100321140ustar00rootroot00000000000000import qbs.Probes Module { property bool alt: false Probe { id: foo property string baz property bool useAlt: alt property string named: product.name configure: { console.info("running probe " + named); baz = useAlt ? "hahaha" : "hello"; found = true; } } property string something: foo.baz } qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/outer/000077500000000000000000000000001347155106100303145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/outer/outer.qbs000066400000000000000000000006051347155106100321620ustar00rootroot00000000000000Module { Depends { name: "inner" } Probe { id: foo2 property string barz property string named: product.name configure: { console.info("running second probe " + named); barz = "goodbye"; found = true; } } property string something: inner.something property string somethingElse: foo2.barz } qbs-src-1.13.1/tests/auto/blackbox/testdata/probes-in-nested-modules/probes-in-nested-modules.qbs000066400000000000000000000017671347155106100330540ustar00rootroot00000000000000Project { Product { name: "a" Depends { name: "outer" } inner.alt: true property bool dummy: { console.info("product " + name + ", inner.something = " + inner.something); console.info("product " + name + ", outer.something = " + outer.something); console.info("product " + name + ", outer.somethingElse = " + outer.somethingElse); return true; } type: ["foo"] } Product { name: "b" Depends { name: "inner" } inner.alt: true property bool dummy: { console.info("product " + name + ", inner.something = " + inner.something); return true; } type: ["foo"] } Product { name: "c" Depends { name: "inner" } inner.alt: false property bool dummy: { console.info("product " + name + ", inner.something = " + inner.something); return true; } type: ["foo"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/product-dependencies-by-type/000077500000000000000000000000001347155106100263555ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/product-dependencies-by-type/main.cpp000066400000000000000000000023511347155106100300060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/product-dependencies-by-type/modules/000077500000000000000000000000001347155106100300255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/product-dependencies-by-type/modules/myconfig/000077500000000000000000000000001347155106100316405ustar00rootroot00000000000000myconfig.qbs000066400000000000000000000000571347155106100341050ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/product-dependencies-by-type/modules/myconfigModule { property bool typeDecider: true } product-dependencies-by-type.qbs000066400000000000000000000102711347155106100345010ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/product-dependencies-by-typeimport qbs.TextFile Project { CppApplication { consoleApplication: true name: "no-match" files: "main.cpp" } Project { CppApplication { consoleApplication: true name: "app1" files: "main.cpp" } CppApplication { consoleApplication: true name: "app2" files: "main.cpp" } CppApplication { consoleApplication: true name: "app3" files: "main.cpp" } Product { type: myconfig.typeDecider ? ["application"] : [] Depends { name: "cpp" } Depends { name: "myconfig" } consoleApplication: true name: "app4" files: "main.cpp" } Product { name: "other-product" type: "other" Rule { multiplex: true Artifact { filePath: "output.txt" fileTags: "other" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.filePath; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); } return cmd; } } Export { Depends { productTypes: "other2" } } } Product { name: "yet-another-product" type: "other2" Rule { multiplex: true Artifact { filePath: "output.txt" fileTags: "other2" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.filePath; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); } return cmd; } } } Product { name: "helper" Export { Depends { productTypes: "other" } } } CppApplication { condition: false consoleApplication: true name: "disabled-app" files: "main.cpp" } DynamicLibrary { Depends { name: "cpp" } name: "lib-product" files: "main.cpp" Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } CppApplication { type: base.concat(["app-list"]) consoleApplication: true name: "app list" Depends { productTypes: ["application"] limitToSubProject: true } Depends { name: "helper" } files: ["main.cpp"] Rule { multiplex: true inputsFromDependencies: ["application", "other", "other2"] Artifact { filePath: "app-list.txt" fileTags: "app-list" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Collecting apps"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs["application"].length; ++i) file.writeLine(inputs["application"][i].filePath); for (i = 0; i < inputs["other"].length; ++i) file.writeLine(inputs["other"][i].filePath); for (i = 0; i < inputs["other2"].length; ++i) file.writeLine(inputs["other2"][i].filePath); file.close(); }; return cmd; } } } Product { name: "dummy" Depends { productTypes: [] } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/productproperties/000077500000000000000000000000001347155106100244575ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/productproperties/app.qbs000066400000000000000000000002611347155106100257450ustar00rootroot00000000000000Product { consoleApplication: true type: "application" name: "blubb_user" files: "main.cpp" Depends { name: "blubb_header" } Depends { name: "cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/productproperties/blubb_header.h.in000066400000000000000000000000001347155106100276210ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/productproperties/header.qbs000066400000000000000000000015761347155106100264270ustar00rootroot00000000000000import qbs.TextFile Product { name: "blubb_header" type: "hpp" files: "blubb_header.h.in" property string blubbProp: project.blubbProp Rule { multiplex: true Artifact { filePath: "blubb_header.h" fileTags: "hpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating blubb_header.h"; cmd.highlight = "codegen"; cmd.blubbProp = product.blubbProp; cmd.sourceCode = function() { file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write("#define BLUBB_PROP " + blubbProp); file.close(); } return cmd; } } Export { Depends { name: "cpp" } cpp.includePaths: product.buildDirectory } } qbs-src-1.13.1/tests/auto/blackbox/testdata/productproperties/main.cpp000066400000000000000000000024551347155106100261150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "blubb_header.h" int main() { #if BLUBB_PROP != 5 blubb(); #endif } qbs-src-1.13.1/tests/auto/blackbox/testdata/productproperties/productproperties.qbs000066400000000000000000000001311347155106100307560ustar00rootroot00000000000000Project { property string blubbProp: "5" references: ["header.qbs", "app.qbs"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/project_filepath_check/000077500000000000000000000000001347155106100253415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/project_filepath_check/main.cpp000066400000000000000000000023511347155106100267720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/project_filepath_check/main2.cpp000066400000000000000000000000161347155106100270500ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/project_filepath_check/project1.qbs000066400000000000000000000000511347155106100275730ustar00rootroot00000000000000CppApplication { files: "main.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata/project_filepath_check/project2.qbs000066400000000000000000000000521347155106100275750ustar00rootroot00000000000000CppApplication { files: "main2.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata/proper quoting/000077500000000000000000000000001347155106100236405ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/proper quoting/main.cpp000066400000000000000000000026321347155106100252730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int bla(); int main() { printf(DEFINE"\n"); printf(DEFINEWITHSPACE"\n"); printf(DEFINEWITHTAB"\n"); printf(DEFINEWITHBACKSLASH"\n"); return bla(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/proper quoting/my static lib helper.cpp000066400000000000000000000024061347155106100302320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int helper_function() { return 156; } qbs-src-1.13.1/tests/auto/blackbox/testdata/proper quoting/my static lib.cpp000066400000000000000000000025701347155106100267740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include int bla() { int n = getSomeNumber(); printf("Hello World! The magic number is %d.", n); return n; } qbs-src-1.13.1/tests/auto/blackbox/testdata/proper quoting/proper quoting.qbs000066400000000000000000000017611347155106100273320ustar00rootroot00000000000000import qbs 1.0 Project { Product { type: "application" consoleApplication: true name: "Hello World" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "my static lib" } cpp.defines: [ 'DEFINE="whitespaceless"', 'DEFINEWITHSPACE="contains space"', 'DEFINEWITHTAB="contains\ttab"', 'DEFINEWITHBACKSLASH="backslash\\\\"', ] } Product { type: "staticlibrary" name : "my static lib" files : [ "my static lib.cpp" ] Depends { name: "cpp" } Depends { name: "helper lib" } } Product { type: "staticlibrary" name : "helper lib" files : [ "some helper/some helper.h", "some helper/some helper.cpp" ] Depends { name: "cpp" } Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory + '/some helper'] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/proper quoting/some helper/000077500000000000000000000000001347155106100260435ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/proper quoting/some helper/some helper.cpp000066400000000000000000000024361347155106100307570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "some helper.h" int getSomeNumber() { return 156; } qbs-src-1.13.1/tests/auto/blackbox/testdata/proper quoting/some helper/some helper.h000066400000000000000000000024431347155106100304220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef HELPER_H #define HELPER_H extern int getSomeNumber(); #endif qbs-src-1.13.1/tests/auto/blackbox/testdata/properties-in-export-items/000077500000000000000000000000001347155106100261205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/properties-in-export-items/main1.cpp000066400000000000000000000023731347155106100276360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef P1 int main() { } #endif qbs-src-1.13.1/tests/auto/blackbox/testdata/properties-in-export-items/main2.cpp000066400000000000000000000023731347155106100276370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifdef P2 int main() { } #endif properties-in-export-items.qbs000066400000000000000000000012351347155106100340070ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/properties-in-export-itemsProject { minimumQbsVersion: "1.6" Product { name: "dep" Export { property string theDefine: "" Depends { name: "cpp" } cpp.defines: [theDefine] } } Application { name: "p1" consoleApplication: true Depends { name: "dep" } dep.theDefine: "P1" cpp.minimumMacosVersion: "10.9" files: ["main1.cpp"] } Application { name: "p2" consoleApplication: true Depends { name: "dep" } cpp.minimumMacosVersion: "10.9" Group { dep.theDefine: "P2" files: ["main2.cpp"] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/000077500000000000000000000000001347155106100300255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/main.cpp000066400000000000000000000000161347155106100314520ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/modules/000077500000000000000000000000001347155106100314755ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/modules/m/000077500000000000000000000000001347155106100317315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/property-assignment-in-failed-module/modules/m/m.qbs000066400000000000000000000002601347155106100326720ustar00rootroot00000000000000Module { property bool doFail Depends { name: "cpp" } cpp.dynamicLibraries: ["nosuchlib"] validate: { if (doFail) throw "Failure!"; } } property-assignment-in-failed-module.qbs000066400000000000000000000001441347155106100376170ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/property-assignment-in-failed-moduleCppApplication { name: "app" Depends { name: "m"; required: false } files: "main.cpp" } qbs-src-1.13.1/tests/auto/blackbox/testdata/property-assignment-on-non-present-module/000077500000000000000000000000001347155106100310575ustar00rootroot00000000000000property-assignment-on-non-present-module.qbs000066400000000000000000000001211347155106100416760ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/property-assignment-on-non-present-moduleProduct { Depends { name: "nein"; required: false } nein.doch: "ohhh!" } qbs-src-1.13.1/tests/auto/blackbox/testdata/property-precedence/000077500000000000000000000000001347155106100246415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/property-precedence/dep.qbs000066400000000000000000000002761347155106100261250ustar00rootroot00000000000000Product { name: "dep" Export { Depends { name: "leaf" } Depends { name: "nonleaf" } // leaf.scalarProp: "export" // leaf.listProp: ["export"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/property-precedence/dummy.txt000066400000000000000000000000001347155106100265230ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/property-precedence/modules/000077500000000000000000000000001347155106100263115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/property-precedence/modules/leaf/000077500000000000000000000000001347155106100272205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/property-precedence/modules/leaf/leaf.qbs000066400000000000000000000010171347155106100306350ustar00rootroot00000000000000Module { property string scalarProp: "leaf" property stringList listProp: ["leaf"] Rule { inputs: ["rule-input"] outputFileTags: "rule-output" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info("scalar prop: " + product.leaf.scalarProp); console.info("list prop: " + JSON.stringify(product.leaf.listProp)); } return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/property-precedence/modules/nonleaf/000077500000000000000000000000001347155106100277335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/property-precedence/modules/nonleaf/nonleaf.qbs000066400000000000000000000001551347155106100320650ustar00rootroot00000000000000Module { Depends { name: "leaf" } // leaf.scalarProp: "nonleaf" // leaf.listProp: ["nonleaf"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/property-precedence/property-precedence.qbs000066400000000000000000000006041347155106100313270ustar00rootroot00000000000000Project { references: ["dep.qbs"] Product { name: "toplevel" type: ["rule-output"] Depends { name: "leaf" } Depends { name: "nonleaf" } Depends { name: "dep" } Group { files: ["dummy.txt"] fileTags: ["rule-input"] } // leaf.scalarProp: "product" // leaf.listProp: ["product"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/propertyChanges/000077500000000000000000000000001347155106100240375ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/propertyChanges/lib.cpp000066400000000000000000000024151347155106100253130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" DLL_EXPORT void f() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/propertyChanges/modules/000077500000000000000000000000001347155106100255075ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/000077500000000000000000000000001347155106100275745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs000066400000000000000000000015651347155106100315770ustar00rootroot00000000000000import qbs.File Module { FileTagger { patterns: ["*.in"] fileTags: "test-input" } property string testProperty Rule { inputs: ['test-input'] Artifact { fileTags: "test-output" filePath: input.fileName + ".out" } prepare: { var cmd = new JavaScriptCommand(); cmd.highlight = "codegen"; cmd.description = "Making output from input"; cmd.sourceCode = function() { // console.info('Change in source code'); console.info(input.TestModule.testProperty); File.copy(input.filePath, output.filePath); } var dummyCmd = new JavaScriptCommand(); dummyCmd.silent = true; dummyCmd.sourceCode = function() {}; return [cmd, dummyCmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/propertyChanges/propertyChanges.qbs000066400000000000000000000053531347155106100277310ustar00rootroot00000000000000import qbs.Environment import qbs.File import qbs.TextFile Project { property var projectDefines: ["blubb2"] property string fileContentSuffix: "suffix 1" property string testProperty: "default value" CppApplication { name: qbs.enableDebugCode ? "product 1.debug" : "product 1.release" cpp.defines: ["blubb1"] files: "source1.cpp" } CppApplication { Depends { name: 'library' } name: "product 2" cpp.defines: project.projectDefines files: "source2.cpp" } CppApplication { name: "product 3" cpp.defines: Environment.getEnv("QBS_BLACKBOX_DEFINE") files: "source3.cpp" } DynamicLibrary { Depends { name: "cpp" } name: "library" files: "lib.cpp" Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } } Product { name: "generated text file" type: ["my_output"] property string fileContentPrefix: "prefix 1" Rule { multiplex: true Artifact { filePath: "nothing"; fileTags: ["my_output"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info(product.fileContentPrefix); } return cmd; } } Rule { multiplex: true Artifact { filePath: "generated.txt"; fileTags: ["my_output"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.filePath; cmd.highlight = "codegen"; cmd.sourceCode = function() { file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(product.fileContentPrefix + "contents 1" + project.fileContentSuffix); file.close(); } return cmd; } } } Product { Depends { name: "ruletest" } type: ["test-output2"] Rule { inputsFromDependencies: ['test-output'] Artifact { fileTags: "test-output2" filePath: input.fileName + ".out2" } prepare: { var cmd = new JavaScriptCommand(); cmd.highlight = "codegen"; cmd.description = "Making output from other output"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } references: "ruletest.qbs" qbsSearchPaths: "." } qbs-src-1.13.1/tests/auto/blackbox/testdata/propertyChanges/ruletest.qbs000066400000000000000000000002751347155106100264210ustar00rootroot00000000000000Product { name: "ruletest" type: "test-output" Depends { name: "TestModule" } Group { files: "test.in" TestModule.testProperty: project.testProperty } } qbs-src-1.13.1/tests/auto/blackbox/testdata/propertyChanges/source1.cpp000066400000000000000000000023511347155106100261250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/propertyChanges/source2.cpp000066400000000000000000000023521347155106100261270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/propertyChanges/source3.cpp000066400000000000000000000023521347155106100261300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/propertyChanges/test.in000066400000000000000000000000061347155106100253420ustar00rootroot00000000000000blubb qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/000077500000000000000000000000001347155106100225225ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/addressbook.proto000066400000000000000000000023221347155106100261060ustar00rootroot00000000000000// See README.txt for information and build instructions. // // Note: START and END tags are used in comments to define sections used in // tutorials. They are not part of the syntax for Protocol Buffers. // // To get an in-depth walkthrough of this file and the related examples, see: // https://developers.google.com/protocol-buffers/docs/tutorials // [START declaration] syntax = "proto3"; package tutorial; import "google/protobuf/timestamp.proto"; // [END declaration] // [START java_declaration] option java_package = "com.example.tutorial"; option java_outer_classname = "AddressBookProtos"; // [END java_declaration] // [START csharp_declaration] option csharp_namespace = "Google.Protobuf.Examples.AddressBook"; // [END csharp_declaration] // [START messages] message Person { string name = 1; int32 id = 2; // Unique ID number for this person. string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { string number = 1; PhoneType type = 2; } repeated PhoneNumber phones = 4; google.protobuf.Timestamp last_updated = 5; } // Our address book file is just one of these. message AddressBook { repeated Person people = 1; } // [END messages] qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs000066400000000000000000000006731347155106100264010ustar00rootroot00000000000000import qbs CppApplication { name: "addressbook_cpp" consoleApplication: true condition: hasProtobuf Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++11" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.cpp.present); return protobuf.cpp.present; } files: [ "addressbook.proto", "main.cpp", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/addressbook_objc.qbs000066400000000000000000000006301347155106100265250ustar00rootroot00000000000000import qbs CppApplication { name: "addressbook_objc" consoleApplication: true condition: hasProtobuf Depends { name: "cpp" } Depends { name: "protobuf.objc"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.objc.present); return protobuf.objc.present; } files: [ "addressbook.proto", "main.m", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/import-main.cpp000066400000000000000000000031021347155106100254560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov ** Contact: abbapoh@gmail.com ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int main() { MyMessage message; message.set_msg("msg"); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/import.proto000066400000000000000000000001431347155106100251170ustar00rootroot00000000000000syntax = "proto2"; import "subdir/myenum.proto"; message MyMessage { required string msg = 1; } qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/import.qbs000066400000000000000000000007451347155106100245510ustar00rootroot00000000000000import qbs CppApplication { name: "app" consoleApplication: true condition: hasProtobuf protobuf.cpp.importPaths: [sourceDirectory] cpp.cxxLanguageVersion: "c++11" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.cpp.present); return protobuf.cpp.present; } files: [ "import.proto", "import-main.cpp", "subdir/myenum.proto", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/main.cpp000066400000000000000000000041751347155106100241610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov ** Contact: abbapoh@gmail.com ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include "addressbook.pb.h" using google::protobuf::util::TimeUtil; int main(int /*argc*/, char* /*argv*/[]) { GOOGLE_PROTOBUF_VERIFY_VERSION; tutorial::AddressBook addressBook; auto person = addressBook.add_people(); person->set_name("name"); person->set_id(1); person->set_email("email"); auto phone_number = person->add_phones(); phone_number->set_number("number"); phone_number->set_type(tutorial::Person::MOBILE); *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(nullptr)); google::protobuf::ShutdownProtobufLibrary(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/main.m000066400000000000000000000036771347155106100236410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov ** Contact: abbapoh@gmail.com ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "Addressbook.pbobjc.h" int main(int argc, char* argv[]) { AddressBook *addressBook = [[AddressBook alloc] init]; Person *person = [[Person alloc] init]; person.name = @"name"; person.id_p = 1; person.email = @"email"; Person_PhoneNumber *number = [[Person_PhoneNumber alloc] init]; number.number = @"number"; number.type = Person_PhoneType_Mobile; [addressBook.peopleArray addObject:person]; [addressBook release]; return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/needs-import-dir-main.cpp000066400000000000000000000031141347155106100273310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 Ivan Komissarov ** Contact: abbapoh@gmail.com ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int main() { MyMessage message; message.set_msg("msg"); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/needs-import-dir.proto000066400000000000000000000001341347155106100267670ustar00rootroot00000000000000syntax = "proto2"; import "myenum.proto"; message MyMessage { required string msg = 1; } qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs000066400000000000000000000011051347155106100264100ustar00rootroot00000000000000import qbs CppApplication { name: "app" consoleApplication: true condition: hasProtobuf property path theImportDir protobuf.cpp.importPaths: (theImportDir ? [theImportDir] : []).concat([sourceDirectory]) cpp.cxxLanguageVersion: "c++11" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { console.info("has protobuf: " + protobuf.cpp.present); return protobuf.cpp.present; } files: [ "needs-import-dir.proto", "needs-import-dir-main.cpp", "subdir/myenum.proto", ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/subdir/000077500000000000000000000000001347155106100240125ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/protobuf/subdir/myenum.proto000066400000000000000000000000741347155106100264120ustar00rootroot00000000000000syntax = "proto2"; enum MyEnum { VAL1 = 0; VAL2 = 1; } qbs-src-1.13.1/tests/auto/blackbox/testdata/pseudo-multiplexing/000077500000000000000000000000001347155106100247005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/pseudo-multiplexing/pseudo-multiplexing.qbs000066400000000000000000000003611347155106100314250ustar00rootroot00000000000000Project { Product { name: "a" multiplexByQbsProperties: ["architectures"] Depends { name: "cpp" } } Product { name: "b" multiplexByQbsProperties: [] Depends { name: "cpp" } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/qbsVersion/000077500000000000000000000000001347155106100230155ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/qbsVersion/qbs-version.qbs000066400000000000000000000013031347155106100257710ustar00rootroot00000000000000Project { property string qbsVersion property int qbsVersionMajor property int qbsVersionMinor property int qbsVersionPatch Product { property bool dummy: { if (qbsVersion !== qbs.version || qbsVersionMajor !== qbs.versionMajor || qbsVersionMinor !== qbs.versionMinor || qbsVersionPatch !== qbs.versionPatch) throw("expected " + [qbsVersion, qbsVersionMajor, qbsVersionMinor, qbsVersionPatch].join(", ") + ", got " + [qbs.version, qbs.versionMajor, qbs.versionMinor, qbs.versionPatch].join(", ")); return false; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/rad-after-incomplete-build/000077500000000000000000000000001347155106100257615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/rad-after-incomplete-build/dummy.txt000066400000000000000000000000001347155106100276430ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_rule.qbs000066400000000000000000000010611347155106100322160ustar00rootroot00000000000000import qbs.TextFile Product { type: "custom" Group { files: "dummy.txt" fileTags: "input" } Rule { inputs: "input" Artifact { fileTags: "custom" filePath: "oldfile" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating file"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_renaming/000077500000000000000000000000001347155106100245515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_renaming/dir/000077500000000000000000000000001347155106100253275ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_renaming/dir/subdir/000077500000000000000000000000001347155106100266175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_renaming/dir/subdir/blubb.txt000066400000000000000000000000001347155106100304340ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_renaming/dir/wasser.txt000066400000000000000000000000001347155106100273620ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_renaming/recursive_renaming.qbs000066400000000000000000000002171347155106100311470ustar00rootroot00000000000000Product { qbs.installPrefix: "" Group { qbs.install: true qbs.installSourceBase: "." files: ["dir/**"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_wildcards/000077500000000000000000000000001347155106100247255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_wildcards/dir/000077500000000000000000000000001347155106100255035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_wildcards/dir/file1.txt000066400000000000000000000000001347155106100272320ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_wildcards/dir/subdir/000077500000000000000000000000001347155106100267735ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_wildcards/dir/subdir/file2.txt000066400000000000000000000000001347155106100305230ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/recursive_wildcards/recursive_wildcards.qbs000066400000000000000000000022651347155106100315040ustar00rootroot00000000000000import qbs.TextFile Product { type: ["txt.out"] qbs.installPrefix: "" Group { files: "dir/**" qbs.install: true qbs.installDir: "dir" } FileTagger { patterns: ["*.txt"] fileTags: ["txt.in"] } Rule { multiplex: true requiresInputs: false explicitlyDependsOn: ["txt.in"] Artifact { filePath: "output.txt" fileTags: product.type qbs.install: true } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName; cmd.sourceCode = function() { var inputList = explicitlyDependsOn["txt.in"]; var fileNameList = []; for (var i = 0; i < inputList.length; ++i) fileNameList.push(inputList[i].fileName); fileNameList.sort(); var f = new TextFile(output.filePath, TextFile.WriteOnly); try { f.write(fileNameList.join('')); } finally { f.close(); } }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/referenceErrorInExport/000077500000000000000000000000001347155106100253235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/referenceErrorInExport/main.c000066400000000000000000000023641347155106100264200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/referenceErrorInExport/referenceErrorInExport.qbs000066400000000000000000000005471347155106100325010ustar00rootroot00000000000000Project { CppApplication { Depends { name: "other" } files: ["main.c"] cpp.includePaths: ["."] } DynamicLibrary { name: "other" files: ["main.c"] property stringList includePaths: [] Export { Depends { name: "cpp" } cpp.includePaths: includePaths } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/renameDependency/000077500000000000000000000000001347155106100241305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/renameDependency/after/000077500000000000000000000000001347155106100252315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/renameDependency/after/lib2.cpp000066400000000000000000000025711347155106100265720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib2.h" #include void print_two_numbers(int a, int b, int c) { std::cout << "a=" << a << ", b=" << b << ", c=" << c << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/renameDependency/after/lib2.h000066400000000000000000000024101347155106100262270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void print_two_numbers(int a, int b, int c); qbs-src-1.13.1/tests/auto/blackbox/testdata/renameDependency/before/000077500000000000000000000000001347155106100253725ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/renameDependency/before/lib.cpp000066400000000000000000000026011347155106100266430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "lib.h" #include void print_two_numbers(int a, int b/*, int c*/) { std::cout << "a=" << a << ", b=" << b /*<< ", c=" << c */ << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/renameDependency/before/lib.h000066400000000000000000000024141347155106100263120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void print_two_numbers(int a, int b/*, int c*/); qbs-src-1.13.1/tests/auto/blackbox/testdata/renameDependency/before/main.cpp000066400000000000000000000024731347155106100270300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "lib.h" int main() { print_two_numbers(2, 3); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/renameDependency/before/renameDependency.qbs000066400000000000000000000000571347155106100313510ustar00rootroot00000000000000CppApplication { files: ["*.cpp", "*.h"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/reproducible-build/000077500000000000000000000000001347155106100244365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/reproducible-build/file1.cpp000066400000000000000000000024031347155106100261410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ static void f() { } void f1() { f(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/reproducible-build/file2.cpp000066400000000000000000000024031347155106100261420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ static void f() { } void f2() { f(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/reproducible-build/main.cpp000066400000000000000000000024251347155106100260710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void f1(); void f2(); int main() { f1(); f2(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/reproducible-build/reproducible-build.qbs000066400000000000000000000001711347155106100307200ustar00rootroot00000000000000CppApplication { name: "the product" files: ["file1.cpp", "file2.cpp", "main.cpp"] cpp.cxxFlags: ["-flto"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/require-deprecated/000077500000000000000000000000001347155106100244345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/require-deprecated/blubb.js000066400000000000000000000006211347155106100260570ustar00rootroot00000000000000var TextFile = loadExtension("qbs.TextFile") var zort = loadFile("zort.js") function createCommands(filePaths) { var cmd = new JavaScriptCommand(); cmd.description = "Write an empty file"; cmd.filePath = filePaths[0]; cmd.sourceCode = function() { var f = new TextFile(filePath, TextFile.WriteOnly); f.close(); } return [cmd, zort.createCommand(filePaths)]; } qbs-src-1.13.1/tests/auto/blackbox/testdata/require-deprecated/require.qbs000066400000000000000000000007161347155106100266230ustar00rootroot00000000000000import 'blubb.js' as blubb Product { type: ["text"] Rule { multiplex: true Artifact { fileTags: ["text"] filePath: "one.txt" } Artifact { fileTags: ["text"] filePath: "two.txt" } prepare: { var filePaths = outputs.text.map(function (artifact) {return artifact.filePath; }); return blubb.createCommands(filePaths); } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/require-deprecated/zort.js000066400000000000000000000004551347155106100257740ustar00rootroot00000000000000var File = loadExtension("qbs.File") function createCommand(filePaths) { var cmd = new JavaScriptCommand(); cmd.description = "Create another empty file"; cmd.filePaths = filePaths; cmd.sourceCode = function() { File.copy(filePaths[0], filePaths[1]); }; return cmd; } qbs-src-1.13.1/tests/auto/blackbox/testdata/require/000077500000000000000000000000001347155106100223365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/require/blubb.js000066400000000000000000000006141347155106100237630ustar00rootroot00000000000000var TextFile = require("qbs.TextFile") var zort = require("./zort.js") function createCommands(filePaths) { var cmd = new JavaScriptCommand(); cmd.description = "Write an empty file"; cmd.filePath = filePaths[0]; cmd.sourceCode = function() { var f = new TextFile(filePath, TextFile.WriteOnly); f.close(); } return [cmd, zort.createCommand(filePaths)]; } qbs-src-1.13.1/tests/auto/blackbox/testdata/require/require.qbs000066400000000000000000000007161347155106100245250ustar00rootroot00000000000000import 'blubb.js' as blubb Product { type: ["text"] Rule { multiplex: true Artifact { fileTags: ["text"] filePath: "one.txt" } Artifact { fileTags: ["text"] filePath: "two.txt" } prepare: { var filePaths = outputs.text.map(function (artifact) {return artifact.filePath; }); return blubb.createCommands(filePaths); } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/require/zort.js000066400000000000000000000004471347155106100236770ustar00rootroot00000000000000var File = require("qbs.File") function createCommand(filePaths) { var cmd = new JavaScriptCommand(); cmd.description = "Create another empty file"; cmd.filePaths = filePaths; cmd.sourceCode = function() { File.copy(filePaths[0], filePaths[1]); }; return cmd; } qbs-src-1.13.1/tests/auto/blackbox/testdata/rescue-transformer-data/000077500000000000000000000000001347155106100254175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/rescue-transformer-data/main.cpp000066400000000000000000000000161347155106100270440ustar00rootroot00000000000000int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/rescue-transformer-data/modules/000077500000000000000000000000001347155106100270675ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/rescue-transformer-data/modules/m/000077500000000000000000000000001347155106100273235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/rescue-transformer-data/modules/m/m.qbs000066400000000000000000000006461347155106100302740ustar00rootroot00000000000000Module { property bool p Rule { multiplex: true Artifact { filePath: "dummy" fileTags: ["out"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating dummy"; cmd.sourceCode = function() { console.info("m.p: " + product.m.p); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/rescue-transformer-data/transformer-data-rescue.qbs000066400000000000000000000001441347155106100326620ustar00rootroot00000000000000CppApplication { type: base.concat(["out"]) Depends { name: "m" } files: ["main.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/response-files/000077500000000000000000000000001347155106100236205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/response-files/cat-response-file.cpp000066400000000000000000000043101347155106100276420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include using namespace std; int main(int argc, char *argv[]) { if (argc < 3) { cerr << "cat-response-file: not enough arguments: " << argc - 1 << endl; return 1; } if (strlen(argv[2]) < 2) { cerr << "cat-response-file: second argument is too short: " << argv[2] << endl; return 2; } if (argv[2][0] != '@') { cerr << "cat-response-file: second argument does not start with @: " << argv[2] << endl; return 3; } ifstream inf(argv[2] + 1); if (!inf.is_open()) { cerr << "cat-response-file: cannot open input file " << argv[2] + 1 << endl; return 4; } ofstream ouf(argv[1]); if (!ouf.is_open()) { cerr << "cat-response-file: cannot open output file " << argv[1] << endl; return 5; } string line; while (getline(inf, line)) ouf << line << endl; inf.close(); ouf.close(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/response-files/response-files.qbs000066400000000000000000000045751347155106100273000ustar00rootroot00000000000000import qbs.FileInfo import qbs.TextFile Project { CppApplication { name: "cat-response-file" files: ["cat-response-file.cpp"] cpp.enableExceptions: true } Product { name: "response-file-text" type: ["text"] Depends { name: "cpp" } Depends { name: "cat-response-file" } qbs.installPrefix: "" Group { fileTagsFilter: ["text"] qbs.install: true } Rule { inputsFromDependencies: ["application"] Artifact { filePath: "response-file-content.txt" fileTags: ["text"] } prepare: { var filePath = inputs["application"][0].filePath; var args = [output.filePath, "foo", "with space", "bar"]; var cmd = new Command(filePath, args); cmd.responseFileThreshold = 1; cmd.responseFileArgumentIndex = 1; cmd.responseFileUsagePrefix = '@'; cmd.silent = true; return cmd; } } } Product { name: "lotsofobjects" type: ["dynamiclibrary"] Depends { name: "cpp" } Rule { multiplex: true outputFileTags: ["cpp"] outputArtifacts: { var artifacts = []; for (var i = 0; i < 1000; ++i) artifacts.push({filePath: "source-" + i + ".cpp", fileTags: ["cpp"]}); return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + outputs["cpp"].length + " dummy source files"; cmd.outputFilePaths = outputs["cpp"].map(function (a) { return a.filePath; }); cmd.sourceCode = function () { var index = 0; outputFilePaths.map(function (fp) { var tf = new TextFile(fp, TextFile.WriteOnly); try { tf.writeLine("extern int foo" + index + "() { return 0; }"); ++index; } finally { tf.close(); } }); }; return [cmd]; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/retagged-output-artifact/000077500000000000000000000000001347155106100255755ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/retagged-output-artifact/retagged-output-artifact.qbs000066400000000000000000000024271347155106100332240ustar00rootroot00000000000000import qbs.File import qbs.TextFile Product { name: "p" type: "p_type" property bool useTag1 Rule { multiplex: true outputFileTags: ["tag1", "tag2"] outputArtifacts: [{filePath: "a1.txt", fileTags: product.useTag1 ? "tag1" : "tag2"}] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.filePath; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return cmd; } } Rule { inputs: "tag1" Artifact { filePath: "a2.txt"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.filePath; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } Rule { inputs: "tag2" Artifact { filePath: "a3.txt"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.filePath; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/rule-connection-with-excluded-inputs/000077500000000000000000000000001347155106100300525ustar00rootroot00000000000000rule-connection-with-excluded-inputs.qbs000066400000000000000000000022241347155106100376720ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/rule-connection-with-excluded-inputsProduct { name: "p" type: "p_type" Rule { multiplex: true Artifact { filePath: "x.txt"; fileTags: "x" } Artifact { filePath: "y.txt"; fileTags: "y" } Artifact { filePath: "p.txt"; fileTags: "p_type" } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() {}; return cmd; } } Rule { multiplex: true Artifact { filePath: "x2.txt"; fileTags: "x" } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() {}; return cmd; } } Rule { multiplex: true inputs: "x" excludedInputs: "y" Artifact { filePath: "dummy"; fileTags: "p_type" } prepare: { console.info("inputs.x: " + (inputs.x ? inputs.x.length : 0)); console.info("inputs.y: " + (inputs.y ? inputs.y.length : 0)); var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() {}; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/rule-with-no-inputs/000077500000000000000000000000001347155106100245345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/rule-with-no-inputs/rule-with-no-inputs.qbs000066400000000000000000000012761347155106100311230ustar00rootroot00000000000000import qbs.TextFile Product { name: "theProduct" type: ["output"] version: "1" property bool dummy: false Rule { inputs: [] multiplex: true Artifact { filePath: "output.out" fileTags: ["output"] } prepare: { console.info("running the rule: " + product.dummy); var cmd = new JavaScriptCommand(); cmd.description = "creating output"; cmd.sourceCode = function() { console.info(product.version); var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/rule-with-non-required-inputs/000077500000000000000000000000001347155106100265305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/rule-with-non-required-inputs/a.inp000066400000000000000000000000001347155106100274460ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/rule-with-non-required-inputs/b.inp000066400000000000000000000000001347155106100274470ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/rule-with-non-required-inputs/c.inp000066400000000000000000000000001347155106100274500ustar00rootroot00000000000000rule-with-non-required-inputs.qbs000066400000000000000000000020041347155106100350220ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/rule-with-non-required-inputsimport qbs.TextFile Product { name: "p" type: ["p.out"] property bool enableTagger FileTagger { condition: enableTagger patterns: ["*.inp"] fileTags: ["p.in"] } Rule { multiplex: true requiresInputs: false inputs: ["p.in"] Artifact { filePath: "output.txt" fileTags: ["p.out"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write('('); var inputsList = inputs["p.in"]; if (inputsList) { for (var i = 0; i < inputsList.length; ++i) f.write(inputsList[i].fileName + ','); } f.write(')'); }; return [cmd]; } } files: ["a.inp", "b.inp", "c.inp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleConditions/000077500000000000000000000000001347155106100236635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleConditions/foo.narf000066400000000000000000000000001347155106100253040ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleConditions/main.cpp000066400000000000000000000023641347155106100253200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleConditions/modules/000077500000000000000000000000001347155106100253335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleConditions/modules/narfzort/000077500000000000000000000000001347155106100272005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleConditions/modules/narfzort/narfzort.qbs000066400000000000000000000014631347155106100315600ustar00rootroot00000000000000import qbs.FileInfo import qbs.TextFile Module { property bool buildZort: true FileTagger { patterns: "*.narf" fileTags: ["narf"] } Rule { condition: product.narfzort.buildZort inputs: ["narf"] outputFileTags: ["zort"] outputArtifacts: [{ filePath: product.name + "." + input.fileName + ".zort", fileTags: ["zort"] }] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + FileInfo.fileName(output.filePath); cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("NARF! ZORT!"); f.close(); } return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleConditions/ruleConditions.qbs000066400000000000000000000002611347155106100273720ustar00rootroot00000000000000import "templates/zorduct.qbs" as Zorduct Project { Zorduct { narfzort.buildZort: false name: "unzorted" } Zorduct { name: "zorted" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleConditions/templates/000077500000000000000000000000001347155106100256615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleConditions/templates/zorduct.qbs000066400000000000000000000003021347155106100300550ustar00rootroot00000000000000Product { type: ["application", "zort"] consoleApplication: true Depends { name: "cpp" } Depends { name: "narfzort" } files: [ "main.cpp", "foo.narf" ] } qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleCycle/000077500000000000000000000000001347155106100226115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleCycle/happy.grass000066400000000000000000000000301347155106100247640ustar00rootroot00000000000000happy! happy! joy! joy! qbs-src-1.13.1/tests/auto/blackbox/testdata/ruleCycle/ruleCycle.qbs000066400000000000000000000024741347155106100252560ustar00rootroot00000000000000Project { Product { name: "the cycle of life" type: "cow" Group { files: ["happy.grass"] fileTags: ["grass"] } Rule { inputs: ["grass"] outputFileTags: ["cow"] outputArtifacts: [{ filePath: input.completeBaseName + ".cow", fileTags: ["cow"] }] prepare: { console.info("The cow feeds on grass."); } } Rule { inputs: ["cow"] Artifact { filePath: input.completeBaseName + ".cow_pat" fileTags: ["cow_pat"] } prepare: { console.info("The cow pat falls out of the cow."); } } Rule { inputs: ["cow_pat"] Artifact { filePath: input.completeBaseName + ".fertilizer" fileTags: ["fertilizer"] } prepare: { console.info("The cow pat is used as fertilizer."); } } Rule { inputs: ["fertilizer"] outputFileTags: ["grass"] outputArtifacts: [{ filePath: input.completeBaseName + ".grass", fileTags: ["grass"] }] prepare: { console.info("The fertilizer lets the grass grow."); } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/scanner-item/000077500000000000000000000000001347155106100232475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/scanner-item/modules/000077500000000000000000000000001347155106100247175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/scanner-item/modules/m/000077500000000000000000000000001347155106100251535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/scanner-item/modules/m/m.qbs000066400000000000000000000002301347155106100261110ustar00rootroot00000000000000import qbs.FileInfo Module { Scanner { inputs: "i" searchPaths: [FileInfo.path(input.filePath)] scan: ["file.inc"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/scanner-item/scanner-item.qbs000066400000000000000000000011171347155106100263430ustar00rootroot00000000000000import qbs.File import qbs.FileInfo Product { type: "t" Depends { name: "m" } Group { files: ["subdir1/file1.in", "subdir2/file2.in"] fileTags: "i" } Rule { inputs: "i" Artifact { filePath: FileInfo.baseName(input.fileName) + ".out" fileTags: "t" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "handling " + input.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/scanner-item/subdir1/000077500000000000000000000000001347155106100246205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/scanner-item/subdir1/file.inc000066400000000000000000000000001347155106100262200ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/scanner-item/subdir1/file1.in000066400000000000000000000000001347155106100261360ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/scanner-item/subdir2/000077500000000000000000000000001347155106100246215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/scanner-item/subdir2/file.inc000066400000000000000000000000001347155106100262210ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/scanner-item/subdir2/file2.in000066400000000000000000000000001347155106100261400ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/separate-debug-info/000077500000000000000000000000001347155106100245035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/separate-debug-info/foo.cpp000066400000000000000000000024401347155106100257720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "../dllexport.h" DLL_EXPORT int getAnswer() { return 42; } qbs-src-1.13.1/tests/auto/blackbox/testdata/separate-debug-info/main.cpp000066400000000000000000000023641347155106100261400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs000066400000000000000000000073731347155106100310450ustar00rootroot00000000000000Project { CppApplication { name: "app1" type: ["application"] files: ["main.cpp"] cpp.separateDebugInformation: true } DynamicLibrary { Depends { name: "cpp" } name: "foo1" type: ["dynamiclibrary"] files: ["foo.cpp"] cpp.separateDebugInformation: true } LoadableModule { Depends { name: "cpp" } name: "bar1" files: ["foo.cpp"] cpp.separateDebugInformation: true } CppApplication { name: "app2" type: ["application"] files: ["main.cpp"] cpp.separateDebugInformation: false } DynamicLibrary { Depends { name: "cpp" } name: "foo2" type: ["dynamiclibrary"] files: ["foo.cpp"] cpp.separateDebugInformation: false } LoadableModule { Depends { name: "cpp" } name: "bar2" files: ["foo.cpp"] cpp.separateDebugInformation: false } CppApplication { name: "app3" type: ["application"] files: ["main.cpp"] cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.contains("darwin") cpp.dsymutilFlags: ["--flat"] } } DynamicLibrary { Depends { name: "cpp" } name: "foo3" type: ["dynamiclibrary"] files: ["foo.cpp"] cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.contains("darwin") cpp.dsymutilFlags: ["--flat"] } } LoadableModule { Depends { name: "cpp" } name: "bar3" files: ["foo.cpp"] cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.contains("darwin") cpp.dsymutilFlags: ["--flat"] } } CppApplication { name: "app4" type: ["application"] files: ["main.cpp"] consoleApplication: true cpp.separateDebugInformation: true } DynamicLibrary { Depends { name: "cpp" } name: "foo4" type: ["dynamiclibrary"] files: ["foo.cpp"] Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true } LoadableModule { Depends { name: "cpp" } name: "bar4" files: ["foo.cpp"] Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true } CppApplication { name: "app5" type: ["application"] files: ["main.cpp"] Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.contains("darwin") cpp.dsymutilFlags: ["--flat"] } } DynamicLibrary { Depends { name: "cpp" } name: "foo5" type: ["dynamiclibrary"] files: ["foo.cpp"] Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.contains("darwin") cpp.dsymutilFlags: ["--flat"] } } LoadableModule { Depends { name: "cpp" } name: "bar5" files: ["foo.cpp"] Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { condition: qbs.targetOS.contains("darwin") cpp.dsymutilFlags: ["--flat"] } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-build-environment/000077500000000000000000000000001347155106100254615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-build-environment/modules/000077500000000000000000000000001347155106100271315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-build-environment/modules/buildenv/000077500000000000000000000000001347155106100307415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-build-environment/modules/buildenv/buildenv.qbs000066400000000000000000000003141347155106100332560ustar00rootroot00000000000000import qbs.Environment Module { property string varPrefix: "BUILD_ENV_" setupBuildEnvironment: { Environment.putEnv(product.buildenv.varPrefix + product.name.toUpperCase(), "1"); } } qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-build-environment/modules/m/000077500000000000000000000000001347155106100273655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-build-environment/modules/m/m.qbs000066400000000000000000000013001347155106100303220ustar00rootroot00000000000000import qbs.Environment import qbs.TextFile Module { additionalProductTypes: ["m.target"] Rule { multiplex: true Artifact { filePath: "m.output" fileTags: "m.target" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); var env = Environment.getEnv("BUILD_ENV_" + product.name.toUpperCase()); if (env) f.writeLine(env); f.close(); }; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-build-environment/setup-build-environment.qbs000066400000000000000000000003221347155106100327640ustar00rootroot00000000000000Project { Product { name: "first_product" Depends { name: "buildenv" } Depends { name: "m" } } Product { name: "second_product" Depends { name: "m" } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-run-environment/000077500000000000000000000000001347155106100251665ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-run-environment/lib1.cpp000066400000000000000000000000721347155106100265200ustar00rootroot00000000000000#include "../dllexport.h" DLL_EXPORT void lib1Func() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-run-environment/lib2.cpp000066400000000000000000000001461347155106100265230ustar00rootroot00000000000000#include "../dllexport.h" DLL_IMPORT void lib5Func(); DLL_EXPORT void lib2Func() { lib5Func(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-run-environment/lib3.cpp000066400000000000000000000000721347155106100265220ustar00rootroot00000000000000#include "../dllexport.h" DLL_EXPORT void lib3Func() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-run-environment/lib4.cpp000066400000000000000000000000721347155106100265230ustar00rootroot00000000000000#include "../dllexport.h" DLL_EXPORT void lib4Func() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-run-environment/lib5.cpp000066400000000000000000000000721347155106100265240ustar00rootroot00000000000000#include "../dllexport.h" DLL_EXPORT void lib5Func() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-run-environment/main.cpp000066400000000000000000000003511347155106100266150ustar00rootroot00000000000000#include "../dllexport.h" DLL_IMPORT void lib1Func(); DLL_IMPORT void lib2Func(); DLL_IMPORT void lib3Func(); DLL_IMPORT void lib4Func(); int main() { lib1Func(); lib2Func(); lib3Func(); lib4Func(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs000066400000000000000000000054371347155106100322120ustar00rootroot00000000000000import qbs.FileInfo Project { DynamicLibrary { // Product dependency, installed name: "lib1" Depends { name: "cpp" } files: ["lib1.cpp"] install: !qbs.targetOS.contains("darwin") installImportLib: true installDir: "lib1" importLibInstallDir: installDir Group { condition: qbs.targetOS.contains("darwin") fileTagsFilter: ["bundle.content"] qbs.install: true qbs.installSourceBase: destinationDirectory } } DynamicLibrary { // Product dependency, non-installed name: "lib2" Depends { name: "cpp" } Depends { name: "lib5" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } files: ["lib2.cpp"] } DynamicLibrary { // Non-dependency, referred to by full path name: "lib3" Depends { name: "cpp" } files: ["lib3.cpp"] Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } install: true installImportLib: true installDir: "lib3" importLibInstallDir: installDir } DynamicLibrary { // Non-dependency, referred to by name name: "lib4" Depends { name: "cpp" } files: ["lib4.cpp"] Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } install: true installImportLib: true installDir: "lib4" importLibInstallDir: installDir } DynamicLibrary { // Recursive product dependency name: "lib5" Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } files: ["lib5.cpp"] } CppApplication { name: "app" consoleApplication: true files: "main.cpp" Depends { name: "lib1" } Depends { name: "lib2" } Depends { name: "lib3"; cpp.link: false } Depends { name: "lib4"; cpp.link: false } property string fullInstallPrefix: FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix) property string lib3FilePath: FileInfo.joinPaths(fullInstallPrefix, "lib3", cpp.dynamicLibraryPrefix + "lib3" + (qbs.toolchain.contains("msvc") ? ".lib" : cpp.dynamicLibrarySuffix)) cpp.dynamicLibraries: [lib3FilePath, "lib4"] cpp.libraryPaths: FileInfo.joinPaths(fullInstallPrefix, "lib4") } Probe { id: osPrinter property bool isWindows: qbs.targetOS.contains("windows") configure: { console.info("is windows"); found = true; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/smart-relinking/000077500000000000000000000000001347155106100237705ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/smart-relinking/lib.cpp000066400000000000000000000005531347155106100252450ustar00rootroot00000000000000#include __attribute__ ((visibility ("default"))) void publicFunc() { #ifdef PRINTF std::printf("Tach\n"); #endif } __attribute__ ((visibility ("hidden"))) void privateFunc() { } #ifdef PRIV2 __attribute__ ((visibility ("hidden"))) void privateFunc2() { } #endif #ifdef PUB2 __attribute__ ((visibility ("default"))) void publicFunc2() { } #endif qbs-src-1.13.1/tests/auto/blackbox/testdata/smart-relinking/main.cpp000066400000000000000000000000651347155106100254210ustar00rootroot00000000000000void publicFunc(); int main() { publicFunc(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/smart-relinking/smart-relinking.qbs000066400000000000000000000016421347155106100276100ustar00rootroot00000000000000Project { minimumQbsVersion: "1.6" Probe { id: tcProbe property stringList toolchain: qbs.toolchain property stringList targetOS: qbs.targetOS configure: { found = toolchain.contains("gcc") && targetOS.contains("unix"); if (!found) console.info("project disabled"); } } DynamicLibrary { condition: tcProbe.found name: "lib" property stringList defines: [] cpp.defines: defines Depends { name: "cpp" } files: ["lib.cpp"] } CppApplication { condition: tcProbe.found name:"app" Depends { name: "lib" } Depends { name: "staticlib" } files: ["main.cpp"] } StaticLibrary { condition: tcProbe.found name: "staticlib" Depends { name: "lib" } Depends { name: "cpp" } files: "staticlib.cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/smart-relinking/staticlib.cpp000066400000000000000000000000301347155106100264430ustar00rootroot00000000000000static void myFunc() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/source-artifact-changes/000077500000000000000000000000001347155106100253635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/source-artifact-changes/modules/000077500000000000000000000000001347155106100270335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/source-artifact-changes/modules/module_with_files/000077500000000000000000000000001347155106100325355ustar00rootroot00000000000000main.cpp000066400000000000000000000000161347155106100341030ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/source-artifact-changes/modules/module_with_filesint main() {} module_with_files.qbs000066400000000000000000000006071347155106100366720ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/source-artifact-changes/modules/module_with_filesModule { property stringList fileTags property bool overrideTags property bool filesAreTargets Depends { name: "cpp" } Group { prefix: path + '/' files: "main.cpp" fileTags: product.module_with_files.fileTags overrideTags: product.module_with_files.overrideTags filesAreTargets: product.module_with_files.filesAreTargets } } qbs-src-1.13.1/tests/auto/blackbox/testdata/source-artifact-changes/source-artifact-changes.qbs000066400000000000000000000026461347155106100326030ustar00rootroot00000000000000CppApplication { name: "app" type: base.concat("dummy") consoleApplication: true Properties { condition: qbs.targetOS.contains("darwin") bundle.embedInfoPlist: false } Probe { id: toolchainProbe property stringList toolchain: qbs.toolchain configure: { console.info("is gcc: " + toolchain.contains("gcc")); found = true; } } Rule { multiplex: true inputs: "cpp" Artifact { filePath: "dummy" fileTags: "dummy" cpp.cxxLanguageVersion: "hoppla" } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { if (output.cpp.cxxLanguageVersion !== "hoppla") throw "This cannot be!"; }; return cmd; } } Rule { multiplex: true inputs: "cpp" requiresInputs: false Artifact { filePath: "dummy2"; fileTags: "dummy" } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.info("cpp artifacts: " + (product.artifacts.cpp ? product.artifacts.cpp.length : 0)) }; return cmd; } } Depends { name: "module_with_files" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/source-artifact-in-inputs-from-dependencies/000077500000000000000000000000001347155106100312665ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/source-artifact-in-inputs-from-dependencies/header.h000066400000000000000000000000001347155106100326550ustar00rootroot00000000000000source-artifact-in-inputs-from-dependencies.qbs000066400000000000000000000031331347155106100423220ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/source-artifact-in-inputs-from-dependenciesimport qbs.FileInfo import qbs.TextFile Project { Product { name: "dep1" Group { files: ["header.h"] qbs.install: true qbs.installDir: "include1" } } Product { name: "dep2" Group { files: ["header.h"] qbs.install: true qbs.installDir: "include2" } } Product { name: "p" type: ["custom"] Depends { name: "dep1" } Depends { name: "dep2" } Rule { multiplex: true inputsFromDependencies: ["installable"] Artifact { filePath: "output.txt" fileTags: ["custom"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var tf; try { tf = new TextFile(output.filePath, TextFile.WriteOnly); var artifactList = inputs["installable"]; for (var i = 0; i < (artifactList ? artifactList.length : 0); ++i) { var artifact = artifactList[i]; tf.writeLine(FileInfo.joinPaths(artifact.qbs.installDir, artifact.fileName)); } } finally { if (tf) tf.close(); } } return [cmd]; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/soversion/000077500000000000000000000000001347155106100227115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/soversion/lib.cpp000066400000000000000000000000151347155106100241570ustar00rootroot00000000000000void f() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/soversion/soversion.qbs000066400000000000000000000002431347155106100254460ustar00rootroot00000000000000DynamicLibrary { name: "mylib" property bool useVersion version: useVersion ? "1.2.3" : undefined Depends { name: "cpp" } files: ["lib.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/static-lib-without-sources/000077500000000000000000000000001347155106100260775ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/static-lib-without-sources/lib.cpp000066400000000000000000000000151347155106100273450ustar00rootroot00000000000000void f() { } static-lib-without-sources.qbs000066400000000000000000000003761347155106100337520ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/static-lib-without-sourcesProject { StaticLibrary { name: "a" Depends { name: "cpp" } files: ["lib.cpp"] } Product { type: qbs.targetOS.contains("darwin") ? undefined : ["staticlibrary"] name: "b" Depends { name: "cpp" } Depends { name: "a" } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/subprofile-change-tracking/000077500000000000000000000000001347155106100260575ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/subprofile-change-tracking/main1.cpp000066400000000000000000000023511347155106100275710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/subprofile-change-tracking/main2.cpp000066400000000000000000000023511347155106100275720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() {} subprofile-change-tracking.qbs000066400000000000000000000003061347155106100337030ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/subprofile-change-trackingProject { CppApplication { name: "app1"; files: ["main1.cpp"] } CppApplication { name: "app2" qbs.profiles: ["qbs-autotests-subprofile"] files: ["main2.cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/successive-changes/000077500000000000000000000000001347155106100244445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/successive-changes/input.in000066400000000000000000000000001347155106100261210ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/successive-changes/successive-changes.qbs000066400000000000000000000013641347155106100307410ustar00rootroot00000000000000import qbs.TextFile Project { property string version: "1" Product { name: "theProduct" type: ["output"] Group { files: ["input.in"] fileTags: ["input"] } Rule { inputs: ["input"] Artifact { filePath: "output.out" fileTags: ["output"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating output"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write(project.version); } return [cmd]; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/suspicious-calls/000077500000000000000000000000001347155106100241645ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/suspicious-calls/copy-command.qbs000066400000000000000000000006321347155106100272620ustar00rootroot00000000000000import qbs.File Product { type: ["out"] Group { files: ["test.txt"] fileTags: ["in"] } Rule { inputs: ["in"] outputFileTags: "out" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/suspicious-calls/copy-eval.qbs000066400000000000000000000002641347155106100265740ustar00rootroot00000000000000import qbs.File Product { name: { File.copy(sourceDirectory + "/copy-eval.qbs", sourceDirectory + "/copy-eval2.qbs"); return "blubb" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/suspicious-calls/copy-prepare.qbs000066400000000000000000000006561347155106100273100ustar00rootroot00000000000000import qbs.File Product { type: ["out"] Group { files: ["test.txt"] fileTags: ["in"] } Rule { inputs: ["in"] outputFileTags: "out" prepare: { File.copy(input.filePath, output.filePath); var cmd = new JavaScriptCommand(); cmd.description = "no-op"; cmd.sourceCode = function() { }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/suspicious-calls/copy-probe.qbs000066400000000000000000000004051347155106100267510ustar00rootroot00000000000000import qbs.File Product { Probe { id: theProbe property string baseDir: project.sourceDirectory configure: { File.copy(baseDir + "/copy-probe.qbs", baseDir + "/copy-probe2.qbs"); } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/suspicious-calls/direntries-command.qbs000066400000000000000000000007221347155106100304600ustar00rootroot00000000000000import qbs.File Product { type: ["out"] Group { files: ["test.txt"] fileTags: ["in"] } Rule { inputs: ["in"] outputFileTags: "out" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var dummy = File.directoryEntries(product.sourceDirectory, File.Files); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/suspicious-calls/direntries-eval.qbs000066400000000000000000000001351347155106100277670ustar00rootroot00000000000000import qbs.File Product { name: File.directoryEntries(sourceDirectory, File.Files)[0] } qbs-src-1.13.1/tests/auto/blackbox/testdata/suspicious-calls/direntries-prepare.qbs000066400000000000000000000007021347155106100304760ustar00rootroot00000000000000import qbs.File Product { type: ["out"] Group { files: ["test.txt"] fileTags: ["in"] } Rule { inputs: ["in"] outputFileTags: "out" prepare: { var dummy = File.directoryEntries(product.sourceDirectory, File.Files); var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/suspicious-calls/direntries-probe.qbs000066400000000000000000000004371347155106100301540ustar00rootroot00000000000000import qbs.File Product { Probe { id: theProbe property string baseDir: project.sourceDirectory property stringList subDirs configure: { subDirs = File.directoryEntries(baseDir, File.AllDirs); found = true; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/suspicious-calls/test.txt000066400000000000000000000000001347155106100256720ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/symbolLinkMode/000077500000000000000000000000001347155106100236125ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/symbolLinkMode/indirect.cpp000066400000000000000000000000241347155106100261130ustar00rootroot00000000000000void indirect() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/symbolLinkMode/lib.cpp000066400000000000000000000002171347155106100250640ustar00rootroot00000000000000int somefunction() { return 42; } #include static const auto func = []() { printf("Lib was loaded!\n"); return 0; }(); qbs-src-1.13.1/tests/auto/blackbox/testdata/symbolLinkMode/main.cpp000066400000000000000000000005351347155106100252450ustar00rootroot00000000000000extern WEAK_IMPORT int somefunction(); extern void indirect(); #include int main() { printf("meow\n"); if (&somefunction != nullptr) printf("somefunction existed and it returned %d\n", somefunction()); else printf("somefunction did not exist\n"); #if SHOULD_INSTALL_LIB indirect(); #endif return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/symbolLinkMode/symbolLinkMode.qbs000066400000000000000000000065671347155106100272670ustar00rootroot00000000000000import qbs.FileInfo Project { property bool shouldInstallLibrary: true property bool lazy: false Application { Depends { name: "cpp" } Depends { name: "functions"; cpp.symbolLinkMode: product.symbolLinkMode cpp.link: !(product.qbs.targetOS.contains("linux") && product.symbolLinkMode === "weak") } property string symbolLinkMode: project.lazy ? "lazy" : "weak" name: "driver" files: ["main.cpp"] consoleApplication: true property string installLib: "SHOULD_INSTALL_LIB=" + project.shouldInstallLibrary cpp.defines: { if (symbolLinkMode === "weak") { return qbs.targetOS.contains("darwin") ? ["WEAK_IMPORT=__attribute__((weak_import))", installLib] : ["WEAK_IMPORT=__attribute__((weak))", installLib]; } return ["WEAK_IMPORT=", installLib]; } cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" cpp.rpaths: [cpp.rpathOrigin + "/../lib"] Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "bin" } } DynamicLibrary { Depends { name: "cpp" } Depends { name: "indirect"; cpp.symbolLinkMode: "reexport" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } name: "functions" files: ["lib.cpp"] cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" cpp.rpaths: [cpp.rpathOrigin] Properties { condition: qbs.targetOS.contains("darwin") cpp.sonamePrefix: "@rpath" } Group { condition: project.shouldInstallLibrary fileTagsFilter: product.type qbs.install: true qbs.installDir: "lib" } Export { // let the autotest pass on Linux where reexport is not supported Depends { name: "indirect"; condition: !qbs.targetOS.contains("darwin") } // on Linux, there is no LC_WEAK_LOAD_DYLIB equivalent (the library is simply omitted // from the list of load commands entirely), so use LD_PRELOAD to emulate qbs.commonRunEnvironment: { var env = original || {}; if (project.shouldInstallLibrary) { env["LD_PRELOAD"] = FileInfo.joinPaths(qbs.installRoot, "lib", "libfunctions.so"); } return env; } } } DynamicLibrary { Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } name: "indirect" files: ["indirect.cpp"] cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" Properties { condition: qbs.targetOS.contains("darwin") // reexport is incompatible with rpath, // "ERROR: ld: file not found: @rpath/libindirect.dylib for architecture x86_64" cpp.sonamePrefix: qbs.installRoot + "/lib" } Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "lib" } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/symlink-removal/000077500000000000000000000000001347155106100240135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/symlink-removal/symlink-removal.qbs000066400000000000000000000005721347155106100276570ustar00rootroot00000000000000import qbs.File Product { type: "removal" Rule { multiplex: true outputFileTags: "removal" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { File.remove(product.sourceDirectory + "/dir1"); }; return [cmd]; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/system-include-paths/000077500000000000000000000000001347155106100247445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/system-include-paths/main.cpp000066400000000000000000000001311347155106100263670ustar00rootroot00000000000000#include #include int main() { printStuff(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/system-include-paths/subdir/000077500000000000000000000000001347155106100262345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/system-include-paths/subdir/gagagugu.h000066400000000000000000000001011347155106100301640ustar00rootroot00000000000000void printStuff() { puts("alalalalonglonglilonglonglong"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/system-include-paths/system-include-paths.qbs000066400000000000000000000001221347155106100315300ustar00rootroot00000000000000CppApplication { files: ["main.cpp"] cpp.systemIncludePaths: ["subdir"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/system-run-paths/000077500000000000000000000000001347155106100241255ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/system-run-paths/lib.cpp000066400000000000000000000023531347155106100254020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void func() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/system-run-paths/main.cpp000066400000000000000000000024041347155106100255550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void func(); int main() { func(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs000066400000000000000000000011001347155106100300670ustar00rootroot00000000000000Project { property bool setRunPaths Product { name: "theLib" type: ["dynamiclibrary"] Depends { name: "cpp" } qbs.installPrefix: "" Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "lib" } files: ["lib.cpp"] } CppApplication { name: "app" Depends { name: "theLib" } files: ["main.cpp"] cpp.rpaths: qbs.installRoot + "/lib" cpp.systemRunPaths: project.setRunPaths ? [qbs.installRoot + "/lib"] : [] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/texttemplate/000077500000000000000000000000001347155106100234025ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/texttemplate/cdefgabc.txt.in000066400000000000000000000000501347155106100262610ustar00rootroot00000000000000${c} ${d} ${e} ${f} ${g} ${a} ${b} ${c} qbs-src-1.13.1/tests/auto/blackbox/testdata/texttemplate/expected/000077500000000000000000000000001347155106100252035ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/texttemplate/expected/lalala.txt000066400000000000000000000000301347155106100271630ustar00rootroot00000000000000do re mi fa so la ti do qbs-src-1.13.1/tests/auto/blackbox/testdata/texttemplate/expected/output.txt000066400000000000000000000002161347155106100273030ustar00rootroot00000000000000foo bar baz fu bar baz foo BAR baz foo bar buzz fu BAR baz fu bar buzz fu BAR buzz fooBARbaz foo\BARbaz foo\\BARbaz foo\\\BARbaz foo${bar}baz qbs-src-1.13.1/tests/auto/blackbox/testdata/texttemplate/output.txt.in000066400000000000000000000002741347155106100261130ustar00rootroot00000000000000foo bar baz ${foo} bar baz foo ${bar} baz foo bar ${baz} ${foo} ${bar} baz ${foo} bar ${baz} ${foo} ${bar} ${baz} foo${bar}baz foo\${bar}baz foo\\${bar}baz foo\\\${bar}baz foo${$}{bar}baz qbs-src-1.13.1/tests/auto/blackbox/testdata/texttemplate/texttemplatetest.qbs000066400000000000000000000007611347155106100275350ustar00rootroot00000000000000Product { name: "one" type: ["text"] files: ["output.txt.in"] Depends { name: "texttemplate" } texttemplate.dict: ({ foo: "fu", bar: "BAR", baz: "buzz", }) Group { files: ["cdefgabc.txt.in"] texttemplate.outputFileName: "lalala.txt" texttemplate.dict: ({ c: "do", d: "re", e: "mi", f: "fa", g: "so", a: "la", b: "ti", }) } } qbs-src-1.13.1/tests/auto/blackbox/testdata/toplevel-searchpath/000077500000000000000000000000001347155106100246345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/toplevel-searchpath/qbs-resources/000077500000000000000000000000001347155106100274315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/toplevel-searchpath/qbs-resources/imports/000077500000000000000000000000001347155106100311265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/toplevel-searchpath/qbs-resources/imports/MyProduct.qbs000066400000000000000000000000141347155106100335560ustar00rootroot00000000000000Product { } qbs-src-1.13.1/tests/auto/blackbox/testdata/toplevel-searchpath/toplevel-searchpath.qbs000066400000000000000000000000161347155106100313120ustar00rootroot00000000000000MyProduct { } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackAddFile/000077500000000000000000000000001347155106100231775ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackAddFile/after/000077500000000000000000000000001347155106100243005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackAddFile/after/main.cpp000066400000000000000000000026441347155106100257360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "narf.h" #include "zort.h" #include int main(int argc, char **argv) { printf("Hello World!\n"); Narf narf; narf.shout(); Zort zort; zort.shout(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackAddFile/after/trackAddFile.qbs000066400000000000000000000004141347155106100273230ustar00rootroot00000000000000Project { Product { name: 'someapp' type: 'application' consoleApplication: true Depends { name: 'cpp' } files: [ "main.cpp", "narf.h", "narf.cpp", "zort.h", "zort.cpp" ] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackAddFile/after/zort.cpp000066400000000000000000000024561347155106100260110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "zort.h" #include void Zort::shout() { printf("ZORT!\n"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackAddFile/after/zort.h000066400000000000000000000024541347155106100254540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef ZORT_H #define ZORT_H class Zort { public: void shout(); }; #endif qbs-src-1.13.1/tests/auto/blackbox/testdata/trackAddFile/before/000077500000000000000000000000001347155106100244415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackAddFile/before/main.cpp000066400000000000000000000025611347155106100260750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "narf.h" #include int main(int argc, char **argv) { printf("Hello World!\n"); Narf narf; narf.shout(); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackAddFile/before/narf.cpp000066400000000000000000000024561347155106100261020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "narf.h" #include void Narf::shout() { printf("NARF!\n"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackAddFile/before/narf.h000066400000000000000000000024541347155106100255450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef NARF_H #define NARF_H class Narf { public: void shout(); }; #endif qbs-src-1.13.1/tests/auto/blackbox/testdata/trackAddFile/before/trackAddFile.qbs000066400000000000000000000003121347155106100274610ustar00rootroot00000000000000Project { Product { name: 'someapp' type: 'application' consoleApplication: true Depends { name: 'cpp' } files: [ "main.cpp", "narf.h", "narf.cpp" ] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackExternalProductChanges/000077500000000000000000000000001347155106100263235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackExternalProductChanges/environmentChange.cpp000066400000000000000000000023701347155106100325030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void environmentChange() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackExternalProductChanges/fileList.js000066400000000000000000000002551347155106100304360ustar00rootroot00000000000000var File = require("qbs.File"); function fileList() { return []; } function filesFromFs(path) { return File.exists(path + "/fileExists.cpp") ? ["fileExists.cpp"] : []; } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackExternalProductChanges/hidden/000077500000000000000000000000001347155106100275565ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackExternalProductChanges/hidden/hiddenheaderqbs.h000066400000000000000000000023321347155106100330410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ qbs-src-1.13.1/tests/auto/blackbox/testdata/trackExternalProductChanges/including.cpp000066400000000000000000000024051347155106100310040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include void f() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/trackExternalProductChanges/jsFileChange.cpp000066400000000000000000000023631347155106100313550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void jsFileChange() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackExternalProductChanges/main.cpp000066400000000000000000000023521347155106100277550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } trackExternalProductChanges.qbs000066400000000000000000000010211347155106100344060ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackExternalProductChangesimport qbs.Environment import "fileList.js" as FileList CppApplication { property stringList filesFromEnv: Environment.getEnv("QBS_TEST_PULL_IN_FILE_VIA_ENV") ? ["environmentChange.cpp"] : [] files: ["main.cpp"].concat(FileList.fileList()).concat(filesFromEnv).concat(FileList.filesFromFs(path)) Group { condition: Environment.getEnv("INCLUDE_PATH_TEST") name: "file that needs help from the environment to find a header" files: "including.cpp" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackFileTags/000077500000000000000000000000001347155106100234055ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackFileTags/after/000077500000000000000000000000001347155106100245065ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackFileTags/after/main.cpp000066400000000000000000000025301347155106100261360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int foo(); int main(int argc, char **argv) { printf("there's %d foo here\n", foo()); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackFileTags/after/trackFileTags.qbs000066400000000000000000000027471347155106100277520ustar00rootroot00000000000000import qbs.TextFile Project { Product { name: 'someapp' type: 'application' consoleApplication: true Depends { name: 'cpp' } Group { files: [ "main.cpp" ] fileTags: [ "foosource", "cpp" ] } } Rule { inputs: ["foosource"] Artifact { filePath: input.baseName + ".foo" fileTags: ["foo"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();" cmd.sourceCode += "file.write(\"There's nothing to see here!\");" cmd.sourceCode += "file.close();" cmd.description = "generating something"; return cmd; } } Rule { inputs: ["foo"] Artifact { filePath: input.baseName + "_foo.cpp" fileTags: ["cpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();"; cmd.sourceCode += "file.write(\"// There's nothing to see here!\\n\");"; cmd.sourceCode += "file.write(\"int foo() { return 15; }\\n\");"; cmd.sourceCode += "file.close();"; cmd.description = "generating something"; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackFileTags/before/000077500000000000000000000000001347155106100246475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackFileTags/before/main.cpp000066400000000000000000000025051347155106100263010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main(int argc, char **argv) { printf("there's no foo here\n"); return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackFileTags/before/trackFileTags.qbs000066400000000000000000000027321347155106100301050ustar00rootroot00000000000000import qbs.TextFile Project { Product { name: 'someapp' type: 'application' consoleApplication: true Depends { name: 'cpp' } Group { files: [ "main.cpp" ] fileTags: [ "cpp" ] } } Rule { inputs: ["foosource"] Artifact { filePath: input.baseName + ".foo" fileTags: ["foo"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();" cmd.sourceCode += "file.write(\"There's nothing to see here!\");" cmd.sourceCode += "file.close();" cmd.description = "generating something"; return cmd; } } Rule { inputs: ["foo"] Artifact { filePath: input.baseName + "_foo.cpp" fileTags: ["cpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();"; cmd.sourceCode += "file.write(\"// There's nothing to see here!\\n\");"; cmd.sourceCode += "file.write(\"int foo() { return 15; }\\n\");"; cmd.sourceCode += "file.close();"; cmd.description = "generating something"; return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackProducts/000077500000000000000000000000001347155106100235125ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackProducts/after/000077500000000000000000000000001347155106100246135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackProducts/after/product3.qbs000066400000000000000000000001641347155106100270660ustar00rootroot00000000000000Product { Depends { name: "cpp" } type: "application" consoleApplication: true files: ["zoo.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackProducts/after/trackProducts.qbs000066400000000000000000000001471347155106100301540ustar00rootroot00000000000000Project { name: "trackProducts" references: ["product1.qbs", "product2.qbs", "product3.qbs"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackProducts/after/zoo.cpp000066400000000000000000000024221347155106100261260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { printf("zoo\n"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackProducts/before/000077500000000000000000000000001347155106100247545ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/trackProducts/before/bar.cpp000066400000000000000000000024221347155106100262240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { printf("bar\n"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackProducts/before/foo.cpp000066400000000000000000000024221347155106100262430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include int main() { printf("foo\n"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackProducts/before/product1.qbs000066400000000000000000000001641347155106100272250ustar00rootroot00000000000000Product { Depends { name: "cpp" } type: "application" consoleApplication: true files: ["foo.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackProducts/before/product2.qbs000066400000000000000000000001641347155106100272260ustar00rootroot00000000000000Product { Depends { name: "cpp" } type: "application" consoleApplication: true files: ["bar.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/trackProducts/before/trackProducts.qbs000066400000000000000000000001271347155106100303130ustar00rootroot00000000000000Project { name: "trackProducts" references: ["product1.qbs", "product2.qbs"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/000077500000000000000000000000001347155106100273215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/000077500000000000000000000000001347155106100307715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/a/000077500000000000000000000000001347155106100312115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/a/a.qbs000066400000000000000000000000661347155106100321420ustar00rootroot00000000000000Module { Depends { name: "b"; required: false } } qbs-src-1.13.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/b/000077500000000000000000000000001347155106100312125ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/b/b.qbs000066400000000000000000000000401347155106100321340ustar00rootroot00000000000000Module { condition: false } transitive-optional-dependencies.qbs000066400000000000000000000000461347155106100364100ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/transitive-optional-dependenciesProduct { Depends { name: "a" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/typescript/000077500000000000000000000000001347155106100230705ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/typescript/animals.ts000066400000000000000000000005501347155106100250640ustar00rootroot00000000000000export interface Mammal { speak(): string; } export class Cat implements Mammal { public speak() { return "Meow"; // a cat says meow } } export class Dog implements Mammal { public speak() { return "Woof"; // a dog says woof } } export class Human implements Mammal { public speak() { return "Hello"; } } qbs-src-1.13.1/tests/auto/blackbox/testdata/typescript/extra.js000066400000000000000000000001061347155106100245460ustar00rootroot00000000000000if (console) { console.log("This doesn't do anything useful!"); } qbs-src-1.13.1/tests/auto/blackbox/testdata/typescript/foo.ts000066400000000000000000000001371347155106100242240ustar00rootroot00000000000000export class Greeter { public getGreeting(): string { return "guten Tag!"; } } qbs-src-1.13.1/tests/auto/blackbox/testdata/typescript/foo2.ts000066400000000000000000000000011347155106100242740ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata/typescript/hello.ts000066400000000000000000000000351347155106100245410ustar00rootroot00000000000000console.log("Hello world!"); qbs-src-1.13.1/tests/auto/blackbox/testdata/typescript/main.ts000066400000000000000000000010231347155106100243600ustar00rootroot00000000000000import Animals = require("./animals"); import Foo = require("./foo"); import Extra = require("./woosh/extra"); function main() { var mammals: Animals.Mammal[] = []; mammals.push(new Animals.Human()); mammals.push(new Animals.Dog()); mammals.push(new Animals.Cat()); // Make everyone speak for (var i = 0; i < mammals.length; ++i) { console.log(mammals[i].speak()); } (new Extra.Boom()); var greeting: string = (new Foo.Greeter()).getGreeting(); console.log(greeting); } main(); qbs-src-1.13.1/tests/auto/blackbox/testdata/typescript/typescript.qbs000066400000000000000000000020051347155106100260020ustar00rootroot00000000000000Project { NodeJSApplication { Depends { name: "typescript" } Depends { name: "lib" } typescript.warningLevel: "pedantic" typescript.generateDeclarations: true typescript.moduleLoader: "commonjs" nodejs.applicationFile: "main.ts" name: "animals" files: [ "animals.ts", "extra.js", "woosh/extra.ts" ] } Product { Depends { name: "typescript" } typescript.generateDeclarations: true typescript.moduleLoader: "commonjs" name: "lib" files: [ "foo.ts" ] } Product { Depends { name: "typescript" } typescript.generateDeclarations: true name: "lib2" files: [ "foo2.ts" ] } NodeJSApplication { Depends { name: "typescript" } Depends { name: "lib2" } typescript.singleFile: true nodejs.applicationFile: "hello.ts" name: "single" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/typescript/woosh/000077500000000000000000000000001347155106100242275ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/typescript/woosh/extra.ts000066400000000000000000000000261347155106100257200ustar00rootroot00000000000000export class Boom { } qbs-src-1.13.1/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/000077500000000000000000000000001347155106100301755ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom1.in000066400000000000000000000000001347155106100321060ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom2.in000066400000000000000000000000001347155106100321070ustar00rootroot00000000000000usings-as-sole-inputs-non-multiplexed.qbs000066400000000000000000000030211347155106100401340ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexedimport qbs.FileInfo import qbs.TextFile Project { Product { name: "p1" type: "custom" Group { files: "custom1.in" fileTags: "custom.in" } } Product { name: "p2" type: "custom" Group { files: "custom2.in" fileTags: "custom.in" } } Rule { inputs: "custom.in" Artifact { filePath: FileInfo.baseName(input.filePath) + ".out" fileTags: "custom" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } Product { name: "p3" type: "custom-plus" Depends { name: "p1" } Depends { name: "p2" } Rule { inputsFromDependencies: "custom" Artifact { filePath: FileInfo.fileName(input.filePath) + ".plus" fileTags: "custom-plus" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/variant-suffix/000077500000000000000000000000001347155106100236305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/variant-suffix/lib.cpp000066400000000000000000000000141347155106100250750ustar00rootroot00000000000000void f() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs000066400000000000000000000017731347155106100273150ustar00rootroot00000000000000StaticLibrary { name: "l" Depends { condition: qbs.targetOS.contains("darwin"); name: "bundle" } Properties { condition: qbs.targetOS.contains("darwin"); bundle.isBundle: false } aggregate: false property string variantSuffix property bool multiplex: false Properties { condition: multiplex qbs.buildVariants: ["debug", "release"] multiplexByQbsProperties: ["buildVariants"] } Properties { condition: variantSuffix !== undefined cpp.variantSuffix: variantSuffix } cpp.variantSuffix: original cpp.staticLibraryPrefix: "lib" cpp.staticLibrarySuffix: ".ext" qbs.installPrefix: "" install: true Depends { name: "cpp" } files: ["lib.cpp"] Probe { id: targetOSProbe property stringList targetOS: qbs.targetOS configure: { console.info("is Windows: " + targetOS.contains("windows")); console.info("is Apple: " + targetOS.contains("darwin")); } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/vcs/000077500000000000000000000000001347155106100214555ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/vcs/main.cpp000066400000000000000000000001751347155106100231100ustar00rootroot00000000000000#include #include int main() { std::cout << "__" << VCS_REPO_STATE << "__" << std::endl; } qbs-src-1.13.1/tests/auto/blackbox/testdata/vcs/vcstest.qbs000066400000000000000000000001611347155106100236550ustar00rootroot00000000000000CppApplication { Depends { name: "vcs" } vcs.headerFileName: "my-repo-state.h" files: ["main.cpp"] } qbs-src-1.13.1/tests/auto/blackbox/testdata/versioncheck/000077500000000000000000000000001347155106100233455ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/versioncheck/modules/000077500000000000000000000000001347155106100250155ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/versioncheck/modules/higher/000077500000000000000000000000001347155106100262635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/versioncheck/modules/higher/higher.qbs000066400000000000000000000002101347155106100302310ustar00rootroot00000000000000Module { Depends { name: "lower" required: false versionAtLeast: "1.0" versionBelow: "10.0" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/versioncheck/modules/lower/000077500000000000000000000000001347155106100261455ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/versioncheck/modules/lower/lower.qbs000066400000000000000000000000131347155106100277760ustar00rootroot00000000000000Module { } qbs-src-1.13.1/tests/auto/blackbox/testdata/versioncheck/versioncheck.qbs000066400000000000000000000003731347155106100265420ustar00rootroot00000000000000Product { property string requestedMinVersion property string requestedMaxVersion Depends { name: "higher" } Depends { name: "lower" versionAtLeast: requestedMinVersion versionBelow: requestedMaxVersion } } qbs-src-1.13.1/tests/auto/blackbox/testdata/versionscript/000077500000000000000000000000001347155106100235745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/versionscript/testlib.c000066400000000000000000000024061347155106100254100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ void dummyLocal() {} void dummyGlobal() {} qbs-src-1.13.1/tests/auto/blackbox/testdata/versionscript/versionscript000066400000000000000000000000551347155106100264310ustar00rootroot00000000000000{ global: dummyGlobal; local: dummyLocal; }; qbs-src-1.13.1/tests/auto/blackbox/testdata/versionscript/versionscript.qbs000066400000000000000000000011501347155106100272120ustar00rootroot00000000000000DynamicLibrary { type: base.concat("custom") Depends { name: "cpp" } files: ["testlib.c"] Group { name: "version script" files: ["versionscript"] fileTags: ["versionscript"] } Rule { multiplex: true outputFileTags: "custom" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { console.warn("---" + product.cpp.nmPath + "---"); } return [cmd]; } } qbs.installPrefix: "" install: true installDir: "" } qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/000077500000000000000000000000001347155106100234175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/dynamiclib.cpp000066400000000000000000000001211347155106100262300ustar00rootroot00000000000000#include "../dllexport.h" void usedFunc(); DLL_EXPORT void f() { usedFunc(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/main1.cpp000066400000000000000000000001351347155106100251270ustar00rootroot00000000000000#include "../dllexport.h" DLL_IMPORT void unusedFunc1(); int main() { unusedFunc1(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/main2.cpp000066400000000000000000000001351347155106100251300ustar00rootroot00000000000000#include "../dllexport.h" DLL_IMPORT void unusedFunc2(); int main() { unusedFunc2(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/main3.cpp000066400000000000000000000001341347155106100251300ustar00rootroot00000000000000#include "../dllexport.h" DLL_IMPORT void unusedFunc3(); int main() { unusedFunc3(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/main4.cpp000066400000000000000000000001351347155106100251320ustar00rootroot00000000000000#include "../dllexport.h" DLL_IMPORT void unusedFunc4(); int main() { unusedFunc4(); } qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/unused1.cpp000066400000000000000000000000751347155106100255110ustar00rootroot00000000000000#include "../dllexport.h" DLL_EXPORT void unusedFunc1() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/unused2.cpp000066400000000000000000000000751347155106100255120ustar00rootroot00000000000000#include "../dllexport.h" DLL_EXPORT void unusedFunc2() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/unused3.cpp000066400000000000000000000000751347155106100255130ustar00rootroot00000000000000#include "../dllexport.h" DLL_EXPORT void unusedFunc3() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/unused4.cpp000066400000000000000000000000751347155106100255140ustar00rootroot00000000000000#include "../dllexport.h" DLL_EXPORT void unusedFunc4() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/used.cpp000066400000000000000000000000241347155106100250570ustar00rootroot00000000000000void usedFunc() { } qbs-src-1.13.1/tests/auto/blackbox/testdata/whole-archive/whole-archive.qbs000066400000000000000000000040011347155106100266560ustar00rootroot00000000000000import qbs.Utilities Project { StaticLibrary { name: "staticlib 1" Depends { name: "cpp" } files: ["unused1.cpp", "used.cpp"] } StaticLibrary { name: "staticlib2" Depends { name: "cpp" } files: ["unused2.cpp"] } StaticLibrary { name: "staticlib3" Depends { name: "cpp" } files: ["unused3.cpp"] } StaticLibrary { name: "staticlib4" Depends { name: "cpp" } files: ["unused4.cpp"] } DynamicLibrary { name: "dynamiclib" property string linkWholeArchive Depends { name: "cpp" } Probe { id: dummy property stringList toolchain: qbs.toolchain property string compilerVersion: cpp.compilerVersion property string dummy: product.linkWholeArchive // To force probe re-execution configure: { if (!toolchain.contains("msvc") || Utilities.versionCompare(compilerVersion, "19.0.24215.1") >= 0) { console.info("can link whole archives"); } else { console.info("cannot link whole archives"); } } } Depends { name: "staticlib 1"; cpp.linkWholeArchive: product.linkWholeArchive } Depends { name: "staticlib2"; cpp.linkWholeArchive: product.linkWholeArchive } Depends { name: "staticlib3" } Depends { name: "staticlib4"; cpp.linkWholeArchive: product.linkWholeArchive } files: ["dynamiclib.cpp"] } CppApplication { name: "app1" Depends { name: "dynamiclib" } files: ["main1.cpp"] } CppApplication { name: "app2" Depends { name: "dynamiclib" } files: ["main2.cpp"] } CppApplication { name: "app3" Depends { name: "dynamiclib" } files: ["main3.cpp"] } CppApplication { name: "app4" Depends { name: "dynamiclib" } files: ["main4.cpp"] } } qbs-src-1.13.1/tests/auto/blackbox/testdata/wildcard_renaming/000077500000000000000000000000001347155106100243335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/wildcard_renaming/pioniere.txt000066400000000000000000000000001347155106100266740ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/wildcard_renaming/wildcard_renaming.qbs000066400000000000000000000001451347155106100305130ustar00rootroot00000000000000Product { qbs.installPrefix: "" Group { qbs.install: true files: "*" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/wildcards-and-rules/000077500000000000000000000000001347155106100245265ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/wildcards-and-rules/input1.inp000066400000000000000000000000001347155106100264440ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/wildcards-and-rules/wildcards-and-rules.qbs000066400000000000000000000016631347155106100311070ustar00rootroot00000000000000import qbs.TextFile Product { name: "wildcards-and-rules" type: "mytype" files: ["*.inp", "*.dep"] FileTagger { patterns: "*.inp" fileTags: ["inp"] } FileTagger { patterns: "*.dep" fileTags: ["dep"] } Rule { multiplex: true inputs: ["inp"] explicitlyDependsOn: ["dep"] Artifact { filePath: "test.mytype" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating output artifact"; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs.inp.length; ++i) file.writeLine(inputs.inp[i].fileName); file.close(); } return cmd; } } } qbs-src-1.13.1/tests/auto/blackbox/testdata/wix/000077500000000000000000000000001347155106100214715ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/wix/ExampleScript.bat000066400000000000000000000000221347155106100247330ustar00rootroot00000000000000echo Hello world! qbs-src-1.13.1/tests/auto/blackbox/testdata/wix/QbsBootstrapper.wxs000066400000000000000000000006511347155106100253700ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata/wix/QbsSetup.wxs000066400000000000000000000025441347155106100240070ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata/wix/Qt.wxs000066400000000000000000000002041347155106100226140ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata/wix/WiXInstallers.qbs000066400000000000000000000023201347155106100247450ustar00rootroot00000000000000import qbs.FileInfo Project { WindowsInstallerPackage { name: "QbsSetup" targetName: "qbs" files: ["QbsSetup.wxs", "ExampleScript.bat"] wix.defines: ["scriptName=ExampleScript.bat"] wix.extensions: ["WixBalExtension", "WixUIExtension"] qbs.targetPlatform: "windows" Export { Depends { name: "wix" } wix.defines: base.concat(["msiName=" + FileInfo.joinPaths(product.buildDirectory, product.targetName + wix.windowsInstallerSuffix)]) } } WindowsSetupPackage { Depends { name: "QbsSetup" } condition: qbs.hostOS.contains("windows") // currently does not work in Wine with WiX 3.9 name: "QbsBootstrapper" targetName: "qbs-setup-" + qbs.architecture files: ["QbsBootstrapper.wxs"] qbs.architecture: original || "x86" qbs.targetPlatform: "windows" } WindowsInstallerPackage { name: "RegressionBuster9000" files: ["QbsSetup.wxs", "Qt.wxs", "de.wxl"] wix.defines: ["scriptName=ExampleScript.bat"] wix.cultures: [] qbs.architecture: original || "x86" qbs.targetPlatform: "windows" } } qbs-src-1.13.1/tests/auto/blackbox/testdata/wix/de.wxl000066400000000000000000000001161347155106100226130ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata/wixDependencies/000077500000000000000000000000001347155106100240005ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/blackbox/testdata/wixDependencies/QbsSetup.wxs000066400000000000000000000027641347155106100263220ustar00rootroot00000000000000 qbs-src-1.13.1/tests/auto/blackbox/testdata/wixDependencies/main.c000066400000000000000000000000311347155106100250620ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.13.1/tests/auto/blackbox/testdata/wixDependencies/wixDependencies.qbs000066400000000000000000000042341347155106100276300ustar00rootroot00000000000000import qbs.TextFile Project { WindowsInstallerPackage { Depends { name: "app" } Depends { name: "lib" } name: "QbsSetup" targetName: "qbs" files: ["QbsSetup.wxs"] wix.extensions: ["WixBalExtension", "WixUIExtension"] destinationDirectory: project.buildDirectory } Application { Depends { name: "cpp" } name: "app" files: ["main.c"] Group { fileTagsFilter: product.type qbs.install: true } destinationDirectory: project.buildDirectory } DynamicLibrary { Depends { name: "cpp" } name: "lib" files: ["main.c"] Group { fileTagsFilter: product.type qbs.install: true } Rule { // This rule tries to provoke the installer into building too early (and the test // verifies that it does not) by causing the build of the installables to take // a lot longer. multiplex: true outputFileTags: ["c"] outputArtifacts: { var artifacts = []; for (var i = 0; i < 96; ++i) artifacts.push({ filePath: "c" + i + ".c", fileTags: ["c"] }); return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { for (var j = 0; j < 1000; ++j) { // Artificial delay. for (var i = 0; i < outputs["c"].length; ++i) { var tf; try { tf = new TextFile(outputs["c"][i].filePath, TextFile.WriteOnly); tf.writeLine("int main" + i + "() { return 0; }"); } finally { if (tf) tf.close(); } } } }; return [cmd]; } } destinationDirectory: project.buildDirectory } } qbs-src-1.13.1/tests/auto/blackbox/tst_blackbox.cpp000066400000000000000000011364661347155106100222550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackbox.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::Internal::HostOsInfo; using qbs::Profile; class MacosTarHealer { public: MacosTarHealer() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsMacos) { // work around absurd tar behavior on macOS qputenv("COPY_EXTENDED_ATTRIBUTES_DISABLE", "true"); qputenv("COPYFILE_DISABLE", "true"); } } ~MacosTarHealer() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsMacos) { qunsetenv("COPY_EXTENDED_ATTRIBUTES_DISABLE"); qunsetenv("COPYFILE_DISABLE"); } } }; QMap TestBlackbox::findCli(int *status) { QTemporaryDir temp; QDir::setCurrent(testDataDir + "/find"); QbsRunParameters params = QStringList() << "-f" << "find-cli.qbs"; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-cli") + "/cli.json"); if (!file.open(QIODevice::ReadOnly)) return {}; const auto tools = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); return {{"path", QDir::fromNativeSeparators(tools["path"].toString())}}; } QMap TestBlackbox::findNodejs(int *status) { QTemporaryDir temp; QDir::setCurrent(testDataDir + "/find"); QbsRunParameters params = QStringList() << "-f" << "find-nodejs.qbs"; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-nodejs") + "/nodejs.json"); if (!file.open(QIODevice::ReadOnly)) return {}; const auto tools = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); return {{"node", QDir::fromNativeSeparators(tools["node"].toString())}}; } QMap TestBlackbox::findTypeScript(int *status) { QTemporaryDir temp; QDir::setCurrent(testDataDir + "/find"); QbsRunParameters params = QStringList() << "-f" << "find-typescript.qbs"; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-typescript") + "/typescript.json"); if (!file.open(QIODevice::ReadOnly)) return {}; const auto tools = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); return {{"tsc", QDir::fromNativeSeparators(tools["tsc"].toString())}}; } QString TestBlackbox::findArchiver(const QString &fileName, int *status) { if (fileName == "jar") return findJdkTools(status).value(fileName); QString binary = findExecutable(QStringList(fileName)); if (binary.isEmpty()) { const SettingsPtr s = settings(); Profile p(profileName(), s.get()); binary = findExecutable(p.value("archiver.command").toStringList()); } return binary; } bool TestBlackbox::lexYaccExist() { return !findExecutable(QStringList("lex")).isEmpty() && !findExecutable(QStringList("yacc")).isEmpty(); } qbs::Version TestBlackbox::bisonVersion() { const auto yaccBinary = findExecutable(QStringList("yacc")); QProcess process; process.start(yaccBinary, QStringList() << "--version"); if (!process.waitForStarted()) return qbs::Version(); if (!process.waitForFinished()) return qbs::Version(); const auto processStdOut = process.readAllStandardOutput(); if (processStdOut.isEmpty()) return qbs::Version(); const auto line = processStdOut.split('\n')[0]; const auto words = line.split(' '); if (words.empty()) return qbs::Version(); return qbs::Version::fromString(words.last()); } void TestBlackbox::sevenZip() { QDir::setCurrent(testDataDir + "/archiver"); QString binary = findArchiver("7z"); if (binary.isEmpty()) QSKIP("7zip not found"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "modules.archiver.type:7zip")), 0); const QString outputFile = relativeProductBuildDir("archivable") + "/archivable.7z"; QVERIFY2(regularFileExists(outputFile), qPrintable(outputFile)); QProcess listContents; listContents.start(binary, QStringList() << "l" << outputFile); QVERIFY2(listContents.waitForStarted(), qPrintable(listContents.errorString())); QVERIFY2(listContents.waitForFinished(), qPrintable(listContents.errorString())); QVERIFY2(listContents.exitCode() == 0, listContents.readAllStandardError().constData()); const QByteArray output = listContents.readAllStandardOutput(); QVERIFY2(output.contains("2 files"), output.constData()); QVERIFY2(output.contains("test.txt"), output.constData()); QVERIFY2(output.contains("archivable.qbs"), output.constData()); } void TestBlackbox::sourceArtifactInInputsFromDependencies() { QDir::setCurrent(testDataDir + "/source-artifact-in-inputs-from-dependencies"); QCOMPARE(runQbs(), 0); QFile outFile(relativeProductBuildDir("p") + "/output.txt"); QVERIFY2(outFile.exists(), qPrintable(outFile.fileName())); QVERIFY2(outFile.open(QIODevice::ReadOnly), qPrintable(outFile.errorString())); const QByteArrayList output = outFile.readAll().trimmed().split('\n'); QCOMPARE(output.size(), 2); bool header1Found = false; bool header2Found = false; for (const QByteArray &line : output) { const QByteArray &path = line.trimmed(); if (path == "include1/header.h") header1Found = true; else if (path == "include2/header.h") header2Found = true; } QVERIFY(header1Found); QVERIFY(header2Found); } void TestBlackbox::staticLibWithoutSources() { QDir::setCurrent(testDataDir + "/static-lib-without-sources"); QCOMPARE(runQbs(), 0); } void TestBlackbox::suspiciousCalls() { const QString projectDir = testDataDir + "/suspicious-calls"; QDir::setCurrent(projectDir); rmDirR(relativeBuildDir()); QFETCH(QString, projectFile); QbsRunParameters params(QStringList() << "-f" << projectFile); QCOMPARE(runQbs(params), 0); QFETCH(QByteArray, expectedWarning); QVERIFY2(m_qbsStderr.contains(expectedWarning), m_qbsStderr.constData()); } void TestBlackbox::suspiciousCalls_data() { QTest::addColumn("projectFile"); QTest::addColumn("expectedWarning"); QTest::newRow("File.copy() in Probe") << "copy-probe.qbs" << QByteArray(); QTest::newRow("File.copy() during evaluation") << "copy-eval.qbs" << QByteArray("File.copy()"); QTest::newRow("File.copy() in prepare script") << "copy-prepare.qbs" << QByteArray("File.copy()"); QTest::newRow("File.copy() in command") << "copy-command.qbs" << QByteArray(); QTest::newRow("File.directoryEntries() in Probe") << "direntries-probe.qbs" << QByteArray(); QTest::newRow("File.directoryEntries() during evaluation") << "direntries-eval.qbs" << QByteArray("File.directoryEntries()"); QTest::newRow("File.directoryEntries() in prepare script") << "direntries-prepare.qbs" << QByteArray(); QTest::newRow("File.directoryEntries() in command") << "direntries-command.qbs" << QByteArray(); } void TestBlackbox::systemIncludePaths() { const QString projectDir = testDataDir + "/system-include-paths"; QDir::setCurrent(projectDir); QCOMPARE(runQbs(), 0); } void TestBlackbox::tar() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsWindows) QSKIP("Beware of the msys tar"); MacosTarHealer tarHealer; QDir::setCurrent(testDataDir + "/archiver"); rmDirR(relativeBuildDir()); QString binary = findArchiver("tar"); if (binary.isEmpty()) QSKIP("tar not found"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "modules.archiver.type:tar")), 0); const QString outputFile = relativeProductBuildDir("archivable") + "/archivable.tar.gz"; QVERIFY2(regularFileExists(outputFile), qPrintable(outputFile)); QProcess listContents; listContents.start(binary, QStringList() << "tf" << outputFile); QVERIFY2(listContents.waitForStarted(), qPrintable(listContents.errorString())); QVERIFY2(listContents.waitForFinished(), qPrintable(listContents.errorString())); QVERIFY2(listContents.exitCode() == 0, listContents.readAllStandardError().constData()); QFile listFile("list.txt"); QVERIFY2(listFile.open(QIODevice::ReadOnly), qPrintable(listFile.errorString())); QCOMPARE(listContents.readAllStandardOutput(), listFile.readAll()); } void TestBlackbox::textTemplate() { QVERIFY(QDir::setCurrent(testDataDir + "/texttemplate")); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(), 0); QString outputFilePath = relativeProductBuildDir("one") + "/output.txt"; QString expectedOutputFilePath = QFINDTESTDATA("expected/output.txt"); TEXT_FILE_COMPARE(outputFilePath, expectedOutputFilePath); outputFilePath = relativeProductBuildDir("one") + "/lalala.txt"; expectedOutputFilePath = QFINDTESTDATA("expected/lalala.txt"); TEXT_FILE_COMPARE(outputFilePath, expectedOutputFilePath); } static QStringList sortedFileList(const QByteArray &ba) { auto list = QString::fromUtf8(ba).split(QRegExp("[\r\n]"), QString::SkipEmptyParts); std::sort(list.begin(), list.end()); return list; } void TestBlackbox::zip() { QFETCH(QString, binaryName); int status = 0; const QString binary = findArchiver(binaryName, &status); QCOMPARE(status, 0); if (binary.isEmpty()) QSKIP("zip tool not found"); QDir::setCurrent(testDataDir + "/archiver"); rmDirR(relativeBuildDir()); QbsRunParameters params(QStringList() << "modules.archiver.type:zip" << "modules.archiver.command:" + binary); QCOMPARE(runQbs(params), 0); const QString outputFile = relativeProductBuildDir("archivable") + "/archivable.zip"; QVERIFY2(regularFileExists(outputFile), qPrintable(outputFile)); QProcess listContents; if (binaryName == "zip") { // zipinfo is part of Info-Zip listContents.start("zipinfo", QStringList() << "-1" << outputFile); } else { listContents.start(binary, QStringList() << "tf" << outputFile); } QVERIFY2(listContents.waitForStarted(), qPrintable(listContents.errorString())); QVERIFY2(listContents.waitForFinished(), qPrintable(listContents.errorString())); QVERIFY2(listContents.exitCode() == 0, listContents.readAllStandardError().constData()); QFile listFile("list.txt"); QVERIFY2(listFile.open(QIODevice::ReadOnly), qPrintable(listFile.errorString())); QCOMPARE(sortedFileList(listContents.readAllStandardOutput()), sortedFileList(listFile.readAll())); // Make sure the module is still loaded when the java/jar fallback is not available params.command = "resolve"; params.arguments << "modules.java.jdkPath:/blubb"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); } void TestBlackbox::zip_data() { QTest::addColumn("binaryName"); QTest::newRow("zip") << "zip"; QTest::newRow("jar") << "jar"; } void TestBlackbox::zipInvalid() { QDir::setCurrent(testDataDir + "/archiver"); rmDirR(relativeBuildDir()); QbsRunParameters params(QStringList() << "modules.archiver.type:zip" << "modules.archiver.command:/bin/something"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("unrecognized archive tool: 'something'"), m_qbsStderr.constData()); } TestBlackbox::TestBlackbox() : TestBlackboxBase (SRCDIR "/testdata", "blackbox") { } void TestBlackbox::addFileTagToGeneratedArtifact() { QDir::setCurrent(testDataDir + "/add-filetag-to-generated-artifact"); QCOMPARE(runQbs(QStringList("project.enableTagging:true")), 0); QVERIFY2(m_qbsStdout.contains("compressing my_app"), m_qbsStdout.constData()); const QString compressedAppFilePath = relativeProductBuildDir("my_compressed_app") + '/' + qbs::Internal::HostOsInfo::appendExecutableSuffix("compressed-my_app"); QVERIFY(regularFileExists(compressedAppFilePath)); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("project.enableTagging:false"))), 0); QCOMPARE(runQbs(), 0); QVERIFY(!regularFileExists(compressedAppFilePath)); } void TestBlackbox::alwaysRun() { QFETCH(QString, projectFile); QDir::setCurrent(testDataDir + "/always-run"); rmDirR(relativeBuildDir()); QbsRunParameters params("build", QStringList() << "-f" << projectFile); if (projectFile.contains("transformer")) { params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("removed"), m_qbsStderr.constData()); return; } QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("yo")); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("yo")); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "alwaysRun: false", "alwaysRun: true"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("yo")); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("yo")); } void TestBlackbox::alwaysRun_data() { QTest::addColumn("projectFile"); QTest::newRow("Transformer") << "transformer.qbs"; QTest::newRow("Rule") << "rule.qbs"; } void TestBlackbox::artifactsMapChangeTracking() { QDir::setCurrent(testDataDir + "/artifacts-map-change-tracking"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QVERIFY2(m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("test.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("TheBinary"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); // Change name of target binary. Command must be re-run, because the file name of an // artifact changed. WAIT_FOR_NEW_TIMESTAMP(); const QString projectFile("artifacts-map-change-tracking.qbs"); REPLACE_IN_FILE(projectFile, "TheBinary", "TheNewBinary"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QVERIFY2(!m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("test.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("TheNewBinary"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("TheBinary"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); // Add file tag to generated artifact. Command must be re-run, because it enumerates the keys // of the artifacts map. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "fileTags: 'cpp'", "fileTags: ['cpp', 'blubb']"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QVERIFY2(m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("test.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("TheNewBinary"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); // Add redundant file tag to generated artifact. Command must not be re-run, because // the artifacts map has not changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "fileTags: ['cpp', 'blubb']", "fileTags: ['cpp', 'blubb', 'blubb']"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(!m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); // Rebuild the app. Command must not be re-run, because the artifacts map has not changed. WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QVERIFY2(!m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(!m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); // Add source file to app. Command must be re-run, because the artifacts map has changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "/* 'test.txt' */", "'test.txt'"); QCOMPARE(runQbs(QStringList{"-p", "TheApp"}), 0); QEXPECT_FAIL("", "change tracking could become even more fine-grained", Continue); QVERIFY2(!m_qbsStdout.contains("running rule for test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating test.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"-p", "meta,p"}), 0); QVERIFY2(m_qbsStdout.contains("printing artifacts"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("test.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("test.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("TheNewBinary"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("dummy2"), m_qbsStdout.constData()); } void TestBlackbox::artifactsMapInvalidation() { const QString projectDir = testDataDir + "/artifacts-map-invalidation"; QDir::setCurrent(projectDir); QCOMPARE(runQbs(), 0); TEXT_FILE_COMPARE(relativeProductBuildDir("p") + "/myfile.out", "file.in"); } void TestBlackbox::artifactsMapRaceCondition() { QDir::setCurrent(testDataDir + "/artifacts-map-race-condition"); QCOMPARE(runQbs(), 0); } void TestBlackbox::artifactScanning() { const QString projectDir = testDataDir + "/artifact-scanning"; QDir::setCurrent(projectDir); QbsRunParameters params(QStringList("-vv")); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("p1.cpp"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("p2.cpp"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("p3.cpp"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("shared.h"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("external.h"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("subdir/external2.h"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("external-indirect.h"); QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("p1.cpp"); params.command = "resolve"; params.arguments << "modules.cpp.treatSystemHeadersAsDependencies:true"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStderr.count("scanning \"p1.cpp\""), 1); QCOMPARE(m_qbsStderr.count("scanning \"p2.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"p3.cpp\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"shared.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external2.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"external-indirect.h\""), 0); QCOMPARE(m_qbsStderr.count("scanning \"iostream\""), 1); } void TestBlackbox::buildDirectories() { const QString projectDir = QDir::cleanPath(testDataDir + QLatin1String("/build-directories")); const QString projectBuildDir = projectDir + '/' + relativeBuildDir(); QDir::setCurrent(projectDir); QCOMPARE(runQbs(), 0); const QStringList outputLines = QString::fromLocal8Bit(m_qbsStdout.trimmed()).split('\n', QString::SkipEmptyParts); QVERIFY2(outputLines.contains(projectDir + '/' + relativeProductBuildDir("p1")), m_qbsStdout.constData()); QVERIFY2(outputLines.contains(projectDir + '/' + relativeProductBuildDir("p2")), m_qbsStdout.constData()); QVERIFY2(outputLines.contains(projectBuildDir), m_qbsStdout.constData()); QVERIFY2(outputLines.contains(projectDir), m_qbsStdout.constData()); } void TestBlackbox::buildEnvChange() { QDir::setCurrent(testDataDir + "/buildenv-change"); QbsRunParameters params; params.expectFailure = true; params.arguments << "-k"; QVERIFY(runQbs(params) != 0); const bool isMsvc = m_qbsStdout.contains("msvc"); QVERIFY2(m_qbsStdout.contains("compiling file.c"), m_qbsStdout.constData()); QString includePath = QDir::currentPath() + "/subdir"; params.environment.insert("CPLUS_INCLUDE_PATH", includePath); params.environment.insert("CL", "/I" + includePath); QVERIFY(runQbs(params) != 0); params.command = "resolve"; params.expectFailure = false; params.arguments.clear(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QCOMPARE(m_qbsStdout.contains("compiling file.c"), isMsvc); includePath = QDir::currentPath() + "/subdir2"; params.environment.insert("CPLUS_INCLUDE_PATH", includePath); params.environment.insert("CL", "/I" + includePath); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QCOMPARE(m_qbsStdout.contains("compiling file.c"), isMsvc); params.environment = QProcessEnvironment::systemEnvironment(); QCOMPARE(runQbs(params), 0); params.command = "build"; params.expectFailure = true; QVERIFY(runQbs(params) != 0); } void TestBlackbox::buildGraphVersions() { QDir::setCurrent(testDataDir + "/build-graph-versions"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QFile bgFile(relativeBuildGraphFilePath()); QVERIFY2(bgFile.open(QIODevice::ReadWrite), qPrintable(bgFile.errorString())); bgFile.write("blubb"); bgFile.close(); // The first attempt at simple rebuilding as well as subsequent ones must fail. QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Cannot use stored build graph"), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("Use the 'resolve' command"), m_qbsStderr.constData()); QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Cannot use stored build graph"), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("Use the 'resolve' command"), m_qbsStderr.constData()); // On re-resolving, the error turns into a warning and a new build graph is created. QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); QVERIFY2(m_qbsStderr.contains("Cannot use stored build graph"), m_qbsStderr.constData()); QVERIFY2(!m_qbsStderr.contains("Use the 'resolve' command"), m_qbsStderr.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStderr.contains("Cannot use stored build graph"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::changedFiles_data() { QTest::addColumn("useChangedFilesForInitialBuild"); QTest::newRow("initial build with changed files") << true; QTest::newRow("initial build without changed files") << false; } void TestBlackbox::changedFiles() { QFETCH(bool, useChangedFilesForInitialBuild); QDir::setCurrent(testDataDir + "/changed-files"); rmDirR(relativeBuildDir()); const QString changedFile = QDir::cleanPath(QDir::currentPath() + "/file1.cpp"); QbsRunParameters params1; if (useChangedFilesForInitialBuild) params1 = QbsRunParameters(QStringList("--changed-files") << changedFile); // Initial run: Build all files, even though only one of them was marked as changed // (if --changed-files was used). QCOMPARE(runQbs(params1), 0); QCOMPARE(m_qbsStdout.count("compiling"), 3); QCOMPARE(m_qbsStdout.count("creating"), 3); WAIT_FOR_NEW_TIMESTAMP(); touch(QDir::currentPath() + "/main.cpp"); // Now only the file marked as changed must be compiled, even though it hasn't really // changed and another one has. QbsRunParameters params2(QStringList("--changed-files") << changedFile); QCOMPARE(runQbs(params2), 0); QCOMPARE(m_qbsStdout.count("compiling"), 1); QCOMPARE(m_qbsStdout.count("creating"), 1); QVERIFY2(m_qbsStdout.contains("file1.cpp"), m_qbsStdout.constData()); } void TestBlackbox::changedInputsFromDependencies() { QDir::setCurrent(testDataDir + "/changed-inputs-from-dependencies"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("final prepare script"), m_qbsStdout.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("final prepare script"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("input.txt"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("final prepare script"), m_qbsStdout.constData()); } void TestBlackbox::changedRuleInputs() { QDir::setCurrent(testDataDir + "/changed-rule-inputs"); // Initial build. QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating p1-dummy"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating p2-dummy"), m_qbsStdout.constData()); // Re-build: p1 is always regenerated, and p2 has a dependency on it. QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating p1-dummy"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating p2-dummy"), m_qbsStdout.constData()); // Remove the dependency. p2 gets re-generated one last time, because its set of // inputs changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("changed-rule-inputs.qbs", "inputsFromDependencies: \"p1\"", "inputsFromDependencies: \"p3\""); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating p1-dummy"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating p2-dummy"), m_qbsStdout.constData()); // Now the artifacts are no longer connected, and p2 must not get rebuilt anymore. QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating p1-dummy"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("generating p2-dummy"), m_qbsStdout.constData()); } void TestBlackbox::changeInDisabledProduct() { QDir::setCurrent(testDataDir + "/change-in-disabled-product"); QCOMPARE(runQbs(), 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("change-in-disabled-product.qbs", "// 'test2.txt'", "'test2.txt'"); QCOMPARE(runQbs(), 0); } void TestBlackbox::changeInImportedFile() { QDir::setCurrent(testDataDir + "/change-in-imported-file"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("old output"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("prepare.js", "old output", "new output"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("new output"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("prepare.js"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("output"), m_qbsStdout.constData()); } void TestBlackbox::changeTrackingAndMultiplexing() { QDir::setCurrent(testDataDir + "/change-tracking-and-multiplexing"); QCOMPARE(runQbs(QStringList("modules.cpp.staticLibraryPrefix:prefix1")), 0); QCOMPARE(m_qbsStdout.count("compiling lib.cpp"), 2); QCOMPARE(m_qbsStdout.count("creating prefix1l"), 2); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.cpp.staticLibraryPrefix:prefix2"))), 0); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("compiling lib.cpp"), 0); QCOMPARE(m_qbsStdout.count("creating prefix2l"), 2); } static QJsonObject findByName(const QJsonArray &objects, const QString &name) { for (const QJsonValue &v : objects) { if (!v.isObject()) continue; QJsonObject obj = v.toObject(); const QString objName = obj.value(QStringLiteral("name")).toString(); if (objName == name) return obj; } return {}; } static void readDepsOutput(const QString &depsFilePath, QJsonDocument &jsonDocument) { jsonDocument = QJsonDocument(); QFile depsFile(depsFilePath); QVERIFY2(depsFile.open(QFile::ReadOnly), qPrintable(depsFile.errorString())); QJsonParseError jsonerror; jsonDocument = QJsonDocument::fromJson(depsFile.readAll(), &jsonerror); if (jsonerror.error != QJsonParseError::NoError) { qDebug() << jsonerror.errorString(); QFAIL("JSON parsing failed."); } } void TestBlackbox::dependenciesProperty() { QDir::setCurrent(testDataDir + QLatin1String("/dependenciesProperty")); QCOMPARE(runQbs(), 0); const QString depsFile(relativeProductBuildDir("product1") + "/product1.deps"); QJsonDocument jsondoc; readDepsOutput(depsFile, jsondoc); QVERIFY(jsondoc.isArray()); QJsonArray dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 2); QJsonObject product2 = findByName(dependencies, QStringLiteral("product2")); QJsonArray product2_type = product2.value(QStringLiteral("type")).toArray(); QCOMPARE(product2_type.size(), 1); QCOMPARE(product2_type.first().toString(), QLatin1String("application")); QCOMPARE(product2.value(QLatin1String("narf")).toString(), QLatin1String("zort")); QJsonArray product2_cppArtifacts = product2.value("artifacts").toObject().value("cpp").toArray(); QCOMPARE(product2_cppArtifacts.size(), 1); QJsonArray product2_deps = product2.value(QStringLiteral("dependencies")).toArray(); QVERIFY(!product2_deps.empty()); QJsonObject product2_qbs = findByName(product2_deps, QStringLiteral("qbs")); QVERIFY(!product2_qbs.empty()); QJsonObject product2_cpp = findByName(product2_deps, QStringLiteral("cpp")); QJsonArray product2_cpp_defines = product2_cpp.value(QLatin1String("defines")).toArray(); QCOMPARE(product2_cpp_defines.size(), 1); QCOMPARE(product2_cpp_defines.first().toString(), QLatin1String("SMURF")); QJsonArray cpp_dependencies = product2_cpp.value("dependencies").toArray(); QVERIFY(!cpp_dependencies.isEmpty()); int qbsCount = 0; for (int i = 0; i < cpp_dependencies.size(); ++i) { if (cpp_dependencies.at(i).toObject().value("name").toString() == "qbs") ++qbsCount; } QCOMPARE(qbsCount, 1); // Add new dependency, check that command is re-run. const QString projectFile("dependenciesProperty.qbs"); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "// Depends { name: 'newDependency' }", "Depends { name: 'newDependency' }"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generate product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); // Add new Depends item that does not actually introduce a new dependency, check // that command is not re-run. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "// Depends { name: 'product2' }", "Depends { name: 'product2' }"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("generate product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); // Change property of dependency, check that command is re-run. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{"products.product2.narf:zortofsky"})), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling product2.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generate product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); product2 = findByName(dependencies, QStringLiteral("product2")); QCOMPARE(product2.value(QLatin1String("narf")).toString(), QLatin1String("zortofsky")); // Change module property of dependency, check that command is re-run. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{"products.product2.narf:zortofsky", "products.product2.cpp.defines:DIGEDAG"})), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling product2.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generate product1.deps"), m_qbsStdout.constData()); readDepsOutput(depsFile, jsondoc); dependencies = jsondoc.array(); QCOMPARE(dependencies.size(), 3); product2 = findByName(dependencies, QStringLiteral("product2")); product2_deps = product2.value(QStringLiteral("dependencies")).toArray(); product2_cpp = findByName(product2_deps, QStringLiteral("cpp")); product2_cpp_defines = product2_cpp.value(QStringLiteral("defines")).toArray(); QCOMPARE(product2_cpp_defines.size(), 1); QCOMPARE(product2_cpp_defines.first().toString(), QLatin1String("DIGEDAG")); } void TestBlackbox::dependencyProfileMismatch() { QDir::setCurrent(testDataDir + "/dependency-profile-mismatch"); const SettingsPtr s = settings(); qbs::Internal::TemporaryProfile depProfile("qbs_autotests_profileMismatch", s.get()); depProfile.p.setValue("qbs.architecture", "x86"); // Profiles must not be empty... s->sync(); QbsRunParameters params(QStringList() << ("project.mainProfile:" + profileName()) << ("project.depProfile:" + depProfile.p.name())); params.expectFailure = true; QVERIFY2(runQbs(params) != 0, m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains(profileName().toLocal8Bit()) && m_qbsStderr.contains("', which does not exist"), m_qbsStderr.constData()); } void TestBlackbox::deprecatedProperty() { QDir::setCurrent(testDataDir + "/deprecated-property"); QbsRunParameters params(QStringList("-q")); params.expectFailure = true; QVERIFY(runQbs(params) != 0); m_qbsStderr = QDir::fromNativeSeparators(QString::fromLocal8Bit(m_qbsStderr)).toLocal8Bit(); QVERIFY2(m_qbsStderr.contains("deprecated-property.qbs:6:24 The property 'oldProp' is " "deprecated and will be removed in Qbs 99.9.0."), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("deprecated-property.qbs:7:28 The property 'veryOldProp' can no " "longer be used. It was removed in Qbs 1.3.0."), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("Property 'forgottenProp' was scheduled for removal in version " "1.8.0, but is still present."), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("themodule/m.qbs:22:5 Removal version for 'forgottenProp' " "specified here."), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.count("Use newProp instead.") == 2, m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.count("is deprecated") == 1, m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.count("was removed") == 1, m_qbsStderr.constData()); } void TestBlackbox::disappearedProfile() { QDir::setCurrent(testDataDir + "/disappeared-profile"); QbsRunParameters resolveParams; // First, we need to fail, because we don't tell qbs where the module is. resolveParams.expectFailure = true; QVERIFY(runQbs(resolveParams) != 0); // Now we set up a profile with all the necessary information, and qbs succeeds. qbs::Settings settings(QDir::currentPath() + "/settings-dir"); qbs::Profile profile("p", &settings); profile.setValue("m.p1", "p1 from profile"); profile.setValue("m.p2", "p2 from profile"); profile.setValue("preferences.qbsSearchPaths", QStringList({QDir::currentPath() + "/modules-dir"})); settings.sync(); resolveParams.command = "resolve"; resolveParams.expectFailure = false; resolveParams.settingsDir = settings.baseDirectory(); resolveParams.profile = profile.name(); QCOMPARE(runQbs(resolveParams), 0); // Now we change a property in the profile, but because we don't use the "resolve" command, // the old profile contents stored in the build graph are used. profile.setValue("m.p2", "p2 new from profile"); settings.sync(); QbsRunParameters buildParams; buildParams.profile.clear(); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(m_qbsStdout.contains("Creating dummy1.txt with p1 from profile"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("Creating dummy2.txt with p2 from profile"), m_qbsStdout.constData()); // Now we do use the "resolve" command, so the new property value is taken into account. QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(!m_qbsStdout.contains("Creating dummy1.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("Creating dummy2.txt with p2 new from profile"), m_qbsStdout.constData()); // Now we change the profile again without a "resolve" command. However, this time we // force re-resolving indirectly by changing a project file. The updated property value // must still not be taken into account. profile.setValue("m.p1", "p1 new from profile"); settings.sync(); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("modules-dir/modules/m/m.qbs", "property string p1", "property string p1: 'p1 from module'"); QCOMPARE(runQbs(buildParams), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("Creating dummy1.txt"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("Creating dummy2.txt"), m_qbsStdout.constData()); // Now we run the "resolve" command without giving the necessary settings path to find // the profile. resolveParams.expectFailure = true; resolveParams.settingsDir.clear(); resolveParams.profile.clear(); QVERIFY(runQbs(resolveParams) != 0); QVERIFY2(m_qbsStderr.contains("profile"), m_qbsStderr.constData()); } void TestBlackbox::discardUnusedData() { QDir::setCurrent(testDataDir + "/discard-unused-data"); rmDirR(relativeBuildDir()); QFETCH(QString, discardString); QFETCH(bool, symbolPresent); QbsRunParameters params; if (!discardString.isEmpty()) params.arguments << ("modules.cpp.discardUnusedData:" + discardString); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("is Darwin"), m_qbsStdout.constData()); const bool isDarwin = m_qbsStdout.contains("is Darwin: true"); const QString output = QString::fromLocal8Bit(m_qbsStdout); QRegExp pattern(".*---(.*)---.*"); QVERIFY2(pattern.exactMatch(output), qPrintable(output)); QCOMPARE(pattern.captureCount(), 1); const QString nmPath = pattern.capturedTexts().at(1); if (!QFile::exists(nmPath)) QSKIP("Cannot check for symbol presence: No nm found."); QProcess nm; nm.start(nmPath, QStringList(QDir::currentPath() + '/' + relativeExecutableFilePath("app"))); QVERIFY(nm.waitForStarted()); QVERIFY(nm.waitForFinished()); const QByteArray nmOutput = nm.readAllStandardOutput(); QVERIFY2(nm.exitCode() == 0, nm.readAllStandardError().constData()); if (!symbolPresent && !isDarwin) QSKIP("Unused symbol detection only supported on Darwin"); QVERIFY2(nmOutput.contains("unusedFunc") == symbolPresent, nmOutput.constData()); } void TestBlackbox::discardUnusedData_data() { QTest::addColumn("discardString"); QTest::addColumn("symbolPresent"); QTest::newRow("discard") << QString("true") << false; QTest::newRow("don't discard") << QString("false") << true; QTest::newRow("default") << QString() << true; } void TestBlackbox::driverLinkerFlags() { QDir::setCurrent(testDataDir + QLatin1String("/driver-linker-flags")); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); if (!m_qbsStdout.contains("toolchain is GCC-like")) QSKIP("Test applies on GCC-like toolchains only"); QFETCH(QString, linkerMode); QFETCH(bool, expectDriverOption); const QString linkerModeArg = "modules.cpp.linkerMode:" + linkerMode; QCOMPARE(runQbs(QStringList({"-n", "--command-echo-mode", "command-line", linkerModeArg})), 0); const QByteArray driverArg = "-nostartfiles"; const QByteArrayList output = m_qbsStdout.split('\n'); QByteArray compileLine; QByteArray linkLine; for (const QByteArray &line : output) { if (line.contains(" -c ")) compileLine = line; else if (line.contains("main.cpp.o")) linkLine = line; } QVERIFY(!compileLine.isEmpty()); QVERIFY(!linkLine.isEmpty()); QVERIFY2(!compileLine.contains(driverArg), compileLine.constData()); QVERIFY2(linkLine.contains(driverArg) == expectDriverOption, linkLine.constData()); } void TestBlackbox::driverLinkerFlags_data() { QTest::addColumn("linkerMode"); QTest::addColumn("expectDriverOption"); QTest::newRow("link using compiler driver") << "automatic" << true; QTest::newRow("link using linker") << "manual" << false; } void TestBlackbox::dynamicLibraryInModule() { QDir::setCurrent(testDataDir + "/dynamic-library-in-module"); const QString installRootSpec = QString("qbs.installRoot:") + QDir::currentPath(); QbsRunParameters libParams(QStringList({"-f", "thelibs.qbs", installRootSpec})); libParams.buildDirectory = "libbuild"; QCOMPARE(runQbs(libParams), 0); QbsRunParameters appParams("run", QStringList({"-f", "theapp.qbs", installRootSpec})); appParams.buildDirectory = "appbuild"; QCOMPARE(runQbs(appParams), 0); QVERIFY2(m_qbsStdout.contains("Hello from thelib"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("Hello from theotherlib"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("thirdlib"), m_qbsStdout.constData()); QVERIFY(!QFileInfo::exists(appParams.buildDirectory + '/' + qbs::InstallOptions::defaultInstallRoot())); } void TestBlackbox::symlinkRemoval() { if (HostOsInfo::isWindowsHost()) QSKIP("No symlink support on Windows."); QDir::setCurrent(testDataDir + "/symlink-removal"); QVERIFY(QDir::current().mkdir("dir1")); QVERIFY(QDir::current().mkdir("dir2")); QVERIFY(QFile::link("dir2", "dir1/broken-link")); QVERIFY(QFile::link(QFileInfo("dir2").absoluteFilePath(), "dir1/valid-link-to-dir")); QVERIFY(QFile::link(QFileInfo("symlink-removal.qbs").absoluteFilePath(), "dir1/valid-link-to-file")); QCOMPARE(runQbs(), 0); QVERIFY(!QFile::exists("dir1")); QVERIFY(QFile::exists("dir2")); QVERIFY(QFile::exists("symlink-removal.qbs")); } void TestBlackbox::usingsAsSoleInputsNonMultiplexed() { QDir::setCurrent(testDataDir + QLatin1String("/usings-as-sole-inputs-non-multiplexed")); QCOMPARE(runQbs(), 0); const QString p3BuildDir = relativeProductBuildDir("p3"); QVERIFY(regularFileExists(p3BuildDir + "/custom1.out.plus")); QVERIFY(regularFileExists(p3BuildDir + "/custom2.out.plus")); } void TestBlackbox::variantSuffix() { QDir::setCurrent(testDataDir + "/variant-suffix"); QFETCH(bool, multiplex); QFETCH(bool, expectFailure); QFETCH(QString, variantSuffix); QFETCH(QString, buildVariant); QFETCH(QVariantMap, fileNames); QbsRunParameters params; params.command = "resolve"; params.arguments << "--force-probe-execution"; if (multiplex) params.arguments << "products.l.multiplex:true"; else params.arguments << ("modules.qbs.buildVariant:" + buildVariant); if (!variantSuffix.isEmpty()) params.arguments << ("modules.cpp.variantSuffix:" + variantSuffix); QCOMPARE(runQbs(params), 0); const QString fileNameMapKey = m_qbsStdout.contains("is Windows: true") ? "windows" : m_qbsStdout.contains("is Apple: true") ? "apple" : "unix"; if (variantSuffix.isEmpty() && multiplex && fileNameMapKey == "unix") expectFailure = true; params.command = "build"; params.expectFailure = expectFailure; params.arguments = QStringList("--clean-install-root"); QCOMPARE(runQbs(params) == 0, !expectFailure); if (expectFailure) return; const QStringList fileNameList = fileNames.value(fileNameMapKey).toStringList(); for (const QString &fileName : fileNameList) { QFile libFile("default/install-root/lib/" + fileName); QVERIFY2(libFile.exists(), qPrintable(libFile.fileName())); } } void TestBlackbox::variantSuffix_data() { QTest::addColumn("multiplex"); QTest::addColumn("expectFailure"); QTest::addColumn("variantSuffix"); QTest::addColumn("buildVariant"); QTest::addColumn("fileNames"); QTest::newRow("default suffix, debug") << false << false << QString() << QString("debug") << QVariantMap({std::make_pair(QString("windows"), QStringList("libl.ext")), std::make_pair(QString("apple"), QStringList("libl.ext")), std::make_pair(QString("unix"), QStringList("libl.ext"))}); QTest::newRow("default suffix, release") << false << false << QString() << QString("release") << QVariantMap({std::make_pair(QString("windows"), QStringList("libl.ext")), std::make_pair(QString("apple"), QStringList("libl.ext")), std::make_pair(QString("unix"), QStringList("libl.ext"))}); QTest::newRow("custom suffix, debug") << false << false << QString("blubb") << QString("debug") << QVariantMap({std::make_pair(QString("windows"), QStringList("liblblubb.ext")), std::make_pair(QString("apple"), QStringList("liblblubb.ext")), std::make_pair(QString("unix"), QStringList("liblblubb.ext"))}); QTest::newRow("custom suffix, release") << false << false << QString("blubb") << QString("release") << QVariantMap({std::make_pair(QString("windows"), QStringList("liblblubb.ext")), std::make_pair(QString("apple"), QStringList("liblblubb.ext")), std::make_pair(QString("unix"), QStringList("liblblubb.ext"))}); QTest::newRow("default suffix, multiplex") << true << false << QString() << QString() << QVariantMap({std::make_pair(QString("windows"), QStringList({"libl.ext", "libld.ext"})), std::make_pair(QString("apple"), QStringList({"libl.ext", "libl_debug.ext"})), std::make_pair(QString("unix"), QStringList())}); QTest::newRow("custom suffix, multiplex") << true << true << QString("blubb") << QString() << QVariantMap({std::make_pair(QString("windows"), QStringList()), std::make_pair(QString("apple"), QStringList()), std::make_pair(QString("unix"), QStringList())}); } static bool waitForProcessSuccess(QProcess &p) { if (!p.waitForStarted() || !p.waitForFinished()) { qDebug() << p.errorString(); return false; } if (p.exitCode() != 0) { qDebug() << p.readAllStandardError(); return false; } return true; } void TestBlackbox::vcsGit() { const QString gitFilePath = findExecutable(QStringList("git")); if (gitFilePath.isEmpty()) QSKIP("git not found"); // Set up repo. QTemporaryDir repoDir; QVERIFY(repoDir.isValid()); ccp(testDataDir + "/vcs", repoDir.path()); QDir::setCurrent(repoDir.path()); QProcess git; git.start(gitFilePath, QStringList("init")); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"config", "user.name", "My Name"})); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"config", "user.email", "me@example.com"})); QVERIFY(waitForProcessSuccess(git)); const auto getRepoStateFromApp = [this] { const int startIndex = m_qbsStdout.indexOf("__"); if (startIndex == -1) return QByteArray(); const int endIndex = m_qbsStdout.indexOf("__", startIndex + 2); if (endIndex == -1) return QByteArray(); return m_qbsStdout.mid(startIndex + 2, endIndex - startIndex - 2); }; // Run without git metadata. QbsRunParameters params("run", QStringList{"-f", repoDir.path()}); params.workingDir = repoDir.path() + "/.."; params.buildDirectory = repoDir.path(); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); QByteArray newRepoState = getRepoStateFromApp(); QCOMPARE(newRepoState, QByteArray("none")); QByteArray oldRepoState = newRepoState; // Initial commit git.start(gitFilePath, QStringList({"add", "main.cpp"})); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"commit", "-m", "initial commit"})); QVERIFY(waitForProcessSuccess(git)); // Run with git metadata. WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QVERIFY(oldRepoState != newRepoState); oldRepoState = newRepoState; // Run with no changes. QCOMPARE(runQbs(params), 0); QVERIFY2(!m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(oldRepoState, newRepoState); // Run with changed source file. WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QCOMPARE(runQbs(params), 0); QVERIFY2(!m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QCOMPARE(oldRepoState, newRepoState); // Add new file to repo. WAIT_FOR_NEW_TIMESTAMP(); touch("blubb.txt"); git.start(gitFilePath, QStringList({"add", "blubb.txt"})); QVERIFY(waitForProcessSuccess(git)); git.start(gitFilePath, QStringList({"commit", "-m", "blubb!"})); QVERIFY(waitForProcessSuccess(git)); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); newRepoState = getRepoStateFromApp(); QVERIFY(oldRepoState != newRepoState); } void TestBlackbox::vcsSubversion() { const QString svnadminFilePath = findExecutable(QStringList("svnadmin")); if (svnadminFilePath.isEmpty()) QSKIP("svnadmin not found"); const QString svnFilePath = findExecutable(QStringList("svn")); if (svnFilePath.isEmpty()) QSKIP("svn not found"); // Set up repo. QTemporaryDir repoDir; QVERIFY(repoDir.isValid()); QProcess proc; proc.setWorkingDirectory(repoDir.path()); proc.start(svnadminFilePath, QStringList({"create", "vcstest"})); QVERIFY(waitForProcessSuccess(proc)); const QString projectUrl = "file://" + repoDir.path() + "/vcstest/trunk"; proc.start(svnFilePath, QStringList({"import", testDataDir + "/vcs", projectUrl, "-m", "initial import"})); QVERIFY(waitForProcessSuccess(proc)); QTemporaryDir checkoutDir; QVERIFY(checkoutDir.isValid()); proc.setWorkingDirectory(checkoutDir.path()); proc.start(svnFilePath, QStringList({"co", projectUrl, "."})); QVERIFY(waitForProcessSuccess(proc)); // Initial runs QDir::setCurrent(checkoutDir.path()); QbsRunParameters failParams; failParams.command = "run"; failParams.expectFailure = true; const int retval = runQbs(failParams); if (m_qbsStderr.contains("svn too old")) QSKIP("svn too old"); QCOMPARE(retval, 0); QVERIFY2(m_qbsStdout.contains("__1__"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(!m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("__1__"), m_qbsStdout.constData()); // Run with changed source file. WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(!m_qbsStdout.contains("generating my-repo-state.h"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("__1__"), m_qbsStdout.constData()); // Add new file to repo. WAIT_FOR_NEW_TIMESTAMP(); touch("blubb.txt"); proc.start(svnFilePath, QStringList({"add", "blubb.txt"})); QVERIFY(waitForProcessSuccess(proc)); proc.start(svnFilePath, QStringList({"commit", "-m", "blubb!"})); QVERIFY(waitForProcessSuccess(proc)); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("__2__"), m_qbsStdout.constData()); } void TestBlackbox::versionCheck() { QDir::setCurrent(testDataDir + "/versioncheck"); QFETCH(QString, requestedMinVersion); QFETCH(QString, requestedMaxVersion); QFETCH(QString, actualVersion); QFETCH(QString, errorMessage); QbsRunParameters params; params.expectFailure = !errorMessage.isEmpty(); params.arguments << "-n" << ("products.versioncheck.requestedMinVersion:'" + requestedMinVersion + "'") << ("products.versioncheck.requestedMaxVersion:'" + requestedMaxVersion + "'") << ("modules.lower.version:'" + actualVersion + "'"); QCOMPARE(runQbs(params) == 0, errorMessage.isEmpty()); if (params.expectFailure) QVERIFY2(QString(m_qbsStderr).contains(errorMessage), m_qbsStderr.constData()); } void TestBlackbox::versionCheck_data() { QTest::addColumn("requestedMinVersion"); QTest::addColumn("requestedMaxVersion"); QTest::addColumn("actualVersion"); QTest::addColumn("errorMessage"); QTest::newRow("ok1") << "1.0" << "1.1" << "1.0" << QString(); QTest::newRow("ok2") << "1.0" << "2.0.1" << "2.0" << QString(); QTest::newRow("ok3") << "1.0" << "2.5" << "1.5" << QString(); QTest::newRow("ok3") << "1.0" << "2.0" << "1.99" << QString(); QTest::newRow("bad1") << "2.0" << "2.1" << "1.5" << "needs to be at least"; QTest::newRow("bad2") << "2.0" << "3.0" << "1.5" << "needs to be at least"; QTest::newRow("bad3") << "2.0" << "3.0" << "3.5" << "needs to be lower than"; QTest::newRow("bad4") << "2.0" << "3.0" << "3.0" << "needs to be lower than"; // "bad" because the "higer" module has stronger requirements. QTest::newRow("bad5") << "0.1" << "0.9" << "0.5" << "Impossible version constraint"; } void TestBlackbox::versionScript() { const SettingsPtr s = settings(); Profile buildProfile(profileName(), s.get()); QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); if (!toolchain.contains("gcc") || targetOs() != HostOsInfo::HostOsLinux) QSKIP("version script test only applies to Linux"); QDir::setCurrent(testDataDir + "/versionscript"); QCOMPARE(runQbs(QbsRunParameters(QStringList("-q") << ("qbs.installRoot:" + QDir::currentPath()))), 0); const QString output = QString::fromLocal8Bit(m_qbsStderr); QRegExp pattern(".*---(.*)---.*"); QVERIFY2(pattern.exactMatch(output), qPrintable(output)); QCOMPARE(pattern.captureCount(), 1); const QString nmPath = pattern.capturedTexts().at(1); if (!QFile::exists(nmPath)) QSKIP("Cannot check for symbol presence: No nm found."); QProcess nm; nm.start(nmPath, QStringList(QDir::currentPath() + "/libversionscript.so")); QVERIFY(nm.waitForStarted()); QVERIFY(nm.waitForFinished()); const QByteArray allSymbols = nm.readAllStandardOutput(); QCOMPARE(nm.exitCode(), 0); QVERIFY2(allSymbols.contains("dummyLocal"), allSymbols.constData()); QVERIFY2(allSymbols.contains("dummyGlobal"), allSymbols.constData()); nm.start(nmPath, QStringList() << "-g" << QDir::currentPath() + "/libversionscript.so"); QVERIFY(nm.waitForStarted()); QVERIFY(nm.waitForFinished()); const QByteArray globalSymbols = nm.readAllStandardOutput(); QCOMPARE(nm.exitCode(), 0); QVERIFY2(!globalSymbols.contains("dummyLocal"), allSymbols.constData()); QVERIFY2(globalSymbols.contains("dummyGlobal"), allSymbols.constData()); } void TestBlackbox::wholeArchive() { QDir::setCurrent(testDataDir + "/whole-archive"); QFETCH(QString, wholeArchiveString); QFETCH(bool, ruleInvalidationExpected); QFETCH(bool, dllLinkingExpected); const QbsRunParameters resolveParams("resolve", QStringList("products.dynamiclib.linkWholeArchive:" + wholeArchiveString)); QCOMPARE(runQbs(QbsRunParameters(resolveParams)), 0); const bool linkerSupportsWholeArchive = m_qbsStdout.contains("can link whole archives"); const bool linkerDoesNotSupportWholeArchive = m_qbsStdout.contains("cannot link whole archives"); QVERIFY(linkerSupportsWholeArchive != linkerDoesNotSupportWholeArchive); QCOMPARE(runQbs(QbsRunParameters(QStringList({ "-vvp", "dynamiclib" }))), 0); const bool wholeArchive = !wholeArchiveString.isEmpty(); const bool outdatedVisualStudio = wholeArchive && linkerDoesNotSupportWholeArchive; const QByteArray invalidationOutput = "Value for property 'staticlib 1:cpp.linkWholeArchive' has changed."; if (!outdatedVisualStudio) QCOMPARE(m_qbsStderr.contains(invalidationOutput), ruleInvalidationExpected); QCOMPARE(m_qbsStdout.contains("linking"), dllLinkingExpected && !outdatedVisualStudio); QbsRunParameters buildParams(QStringList("-p")); buildParams.expectFailure = !wholeArchive || outdatedVisualStudio; buildParams.arguments << "app1"; QCOMPARE(runQbs(QbsRunParameters(buildParams)) == 0, wholeArchive && !outdatedVisualStudio); buildParams.arguments.last() = "app2"; QCOMPARE(runQbs(QbsRunParameters(buildParams)) == 0, wholeArchive && !outdatedVisualStudio); buildParams.arguments.last() = "app4"; QCOMPARE(runQbs(QbsRunParameters(buildParams)) == 0, wholeArchive && !outdatedVisualStudio); buildParams.arguments.last() = "app3"; buildParams.expectFailure = true; QVERIFY(runQbs(QbsRunParameters(buildParams)) != 0); } void TestBlackbox::wholeArchive_data() { QTest::addColumn("wholeArchiveString"); QTest::addColumn("ruleInvalidationExpected"); QTest::addColumn("dllLinkingExpected"); QTest::newRow("link normally") << QString() << false << true; QTest::newRow("link whole archive") << "true" << true << true; QTest::newRow("link whole archive again") << "notfalse" << false << false; } static bool symlinkExists(const QString &linkFilePath) { return QFileInfo(linkFilePath).isSymLink(); } void TestBlackbox::clean() { const QString appObjectFilePath = relativeProductBuildDir("app") + '/' + inputDirHash(".") + objectFileName("/main.cpp", profileName()); const QString appExeFilePath = relativeExecutableFilePath("app"); const QString depObjectFilePath = relativeProductBuildDir("dep") + '/' + inputDirHash(".") + objectFileName("/dep.cpp", profileName()); const QString depLibBase = relativeProductBuildDir("dep") + '/' + QBS_HOST_DYNAMICLIB_PREFIX + "dep"; QString depLibFilePath; QStringList symlinks; if (qbs::Internal::HostOsInfo::isMacosHost()) { depLibFilePath = depLibBase + ".1.1.0" + QBS_HOST_DYNAMICLIB_SUFFIX; symlinks << depLibBase + ".1.1" + QBS_HOST_DYNAMICLIB_SUFFIX << depLibBase + ".1" + QBS_HOST_DYNAMICLIB_SUFFIX << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX; } else if (qbs::Internal::HostOsInfo::isAnyUnixHost()) { depLibFilePath = depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX + ".1.1.0"; symlinks << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX + ".1.1" << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX + ".1" << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX; } else { depLibFilePath = depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX; } QDir::setCurrent(testDataDir + "/clean"); // Can't clean without a build graph. QbsRunParameters failParams("clean"); failParams.expectFailure = true; QVERIFY(runQbs(failParams) != 0); // Default behavior: Remove all. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("clean"))), 0); QVERIFY(!QFile(appObjectFilePath).exists()); QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); for (const QString &symLink : qAsConst(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Remove all, with a forced re-resolve in between. // This checks that rescuable artifacts are also removed. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList() << "modules.cpp.optimization:none")), 0); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList() << "modules.cpp.optimization:fast")), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters("clean")), 0); QVERIFY(!QFile(appObjectFilePath).exists()); QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); for (const QString &symLink : qAsConst(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Dry run. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("clean"), QStringList("-n"))), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); for (const QString &symLink : qAsConst(symlinks)) QVERIFY2(symlinkExists(symLink), qPrintable(symLink)); // Product-wise, dependency only. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("clean"), QStringList("-p") << "dep")), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); for (const QString &symLink : qAsConst(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Product-wise, dependent product only. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("clean"), QStringList("-p") << "app")), 0); QVERIFY(!QFile(appObjectFilePath).exists()); QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); for (const QString &symLink : qAsConst(symlinks)) QVERIFY2(symlinkExists(symLink), qPrintable(symLink)); } void TestBlackbox::concurrentExecutor() { QDir::setCurrent(testDataDir + "/concurrent-executor"); QCOMPARE(runQbs(QStringList() << "-j" << "2"), 0); QVERIFY2(!m_qbsStderr.contains("ASSERT"), m_qbsStderr.constData()); } void TestBlackbox::conditionalExport() { QDir::setCurrent(testDataDir + "/conditional-export"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("missing define"), m_qbsStderr.constData()); params.expectFailure = false; params.arguments << "project.enableExport:true"; params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); } void TestBlackbox::conditionalFileTagger() { QDir::setCurrent(testDataDir + "/conditional-filetagger"); QbsRunParameters params(QStringList("products.theApp.enableTagger:false")); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling")); params.arguments = QStringList("products.theApp.enableTagger:true"); params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling")); } void TestBlackbox::configure() { QDir::setCurrent(testDataDir + "/configure"); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("Configured at"), m_qbsStdout.constData()); } void TestBlackbox::conflictingArtifacts() { QDir::setCurrent(testDataDir + "/conflicting-artifacts"); QbsRunParameters params(QStringList() << "-n"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Conflicting artifacts"), m_qbsStderr.constData()); } void TestBlackbox::cxxLanguageVersion() { QDir::setCurrent(testDataDir + "/cxx-language-version"); rmDirR(relativeBuildDir()); QFETCH(QString, version); QFETCH(QVariantMap, requiredFlags); QFETCH(QVariantMap, forbiddenFlags); QbsRunParameters resolveParams; resolveParams.command = "resolve"; resolveParams.arguments << "--force-probe-execution"; resolveParams.arguments << "modules.cpp.useLanguageVersionFallback:true"; if (!version.isEmpty()) resolveParams.arguments << ("modules.cpp.cxxLanguageVersion:" + version); QCOMPARE(runQbs(resolveParams), 0); QString mapKey; if (version == "c++17" && m_qbsStdout.contains("is even newer MSVC: true")) mapKey = "msvc-brandnew"; else if (m_qbsStdout.contains("is newer MSVC: true")) mapKey = "msvc-new"; else if (m_qbsStdout.contains("is older MSVC: true")) mapKey = "msvc_old"; else if (m_qbsStdout.contains("is GCC: true")) mapKey = "gcc"; QVERIFY2(!mapKey.isEmpty(), m_qbsStdout.constData()); QbsRunParameters buildParams; buildParams.expectFailure = mapKey == "gcc" && (version == "c++17" || version == "c++21"); buildParams.arguments = QStringList({"--command-echo-mode", "command-line"}); const int retVal = runQbs(buildParams); if (!buildParams.expectFailure) QCOMPARE(retVal, 0); const QString requiredFlag = requiredFlags.value(mapKey).toString(); if (!requiredFlag.isEmpty()) QVERIFY2(m_qbsStdout.contains(requiredFlag.toLocal8Bit()), m_qbsStdout.constData()); const QString forbiddenFlag = forbiddenFlags.value(mapKey).toString(); if (!forbiddenFlag.isEmpty()) QVERIFY2(!m_qbsStdout.contains(forbiddenFlag.toLocal8Bit()), m_qbsStdout.constData()); } void TestBlackbox::cxxLanguageVersion_data() { QTest::addColumn("version"); QTest::addColumn("requiredFlags"); QTest::addColumn("forbiddenFlags"); QTest::newRow("C++98") << QString("c++98") << QVariantMap({std::make_pair(QString("gcc"), QString("-std=c++98"))}) << QVariantMap({std::make_pair(QString("msvc-old"), QString("/std:")), std::make_pair(QString("msvc-new"), QString("/std:"))}); QTest::newRow("C++11") << QString("c++11") << QVariantMap({std::make_pair(QString("gcc"), QString("-std=c++0x"))}) << QVariantMap({std::make_pair(QString("msvc-old"), QString("/std:")), std::make_pair(QString("msvc-new"), QString("/std:"))}); QTest::newRow("C++14") << QString("c++14") << QVariantMap({std::make_pair(QString("gcc"), QString("-std=c++1y")), std::make_pair(QString("msvc-new"), QString("/std:c++14")) }) << QVariantMap({std::make_pair(QString("msvc-old"), QString("/std:"))}); QTest::newRow("C++17") << QString("c++17") << QVariantMap({std::make_pair(QString("gcc"), QString("-std=c++1z")), std::make_pair(QString("msvc-new"), QString("/std:c++latest")), std::make_pair(QString("msvc-brandnew"), QString("/std:c++17")) }) << QVariantMap({std::make_pair(QString("msvc-old"), QString("/std:"))}); QTest::newRow("C++21") << QString("c++21") << QVariantMap({std::make_pair(QString("gcc"), QString("-std=c++21")), std::make_pair(QString("msvc-new"), QString("/std:c++latest")) }) << QVariantMap({std::make_pair(QString("msvc-old"), QString("/std:"))}); QTest::newRow("default") << QString() << QVariantMap() << QVariantMap({std::make_pair(QString("gcc"), QString("-std=")), std::make_pair(QString("msvc-old"), QString("/std:")), std::make_pair(QString("msvc-new"), QString("/std:"))}); } void TestBlackbox::cpuFeatures() { QDir::setCurrent(testDataDir + "/cpu-features"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); const bool isX86 = m_qbsStdout.contains("is x86: true"); const bool isX64 = m_qbsStdout.contains("is x64: true"); if (!isX86 && !isX64) { QVERIFY2(m_qbsStdout.contains("is x86: false") && m_qbsStdout.contains("is x64: false"), m_qbsStdout.constData()); QSKIP("Not an x86 host"); } const bool isGcc = m_qbsStdout.contains("is gcc: true"); const bool isMsvc = m_qbsStdout.contains("is msvc: true"); if (!isGcc && !isMsvc) { QVERIFY2(m_qbsStdout.contains("is gcc: false") && m_qbsStdout.contains("is msvc: false"), m_qbsStdout.constData()); QSKIP("Neither GCC nor MSVC"); } QbsRunParameters params(QStringList{"--command-echo-mode", "command-line"}); params.expectFailure = true; runQbs(params); if (isGcc) { QVERIFY2(m_qbsStdout.contains("-msse2") && m_qbsStdout.contains("-mavx") && m_qbsStdout.contains("-mno-avx512f"), m_qbsStdout.constData()); } else { QVERIFY2(m_qbsStdout.contains("/arch:AVX"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("/arch:AVX2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("/arch:SSE2") == isX86, m_qbsStdout.constData()); } } void TestBlackbox::renameDependency() { QDir::setCurrent(testDataDir + "/renameDependency"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/renameDependency/work"); QCOMPARE(runQbs(), 0); WAIT_FOR_NEW_TIMESTAMP(); QFile::remove("lib.h"); QFile::remove("lib.cpp"); ccp("../after", "."); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); } void TestBlackbox::separateDebugInfo() { QDir::setCurrent(testDataDir + "/separate-debug-info"); QCOMPARE(runQbs(QbsRunParameters(QStringList("qbs.debugInformation:true"))), 0); const SettingsPtr s = settings(); Profile buildProfile(profileName(), s.get()); QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); std::string targetPlatform = buildProfile.value("qbs.targetPlatform").toString().toStdString(); std::vector targetOS = HostOsInfo::canonicalOSIdentifiers(targetPlatform); if (qbs::Internal::contains(targetOS, "darwin") || (targetPlatform.empty() && HostOsInfo::isMacosHost())) { QVERIFY(directoryExists(relativeProductBuildDir("app1") + "/app1.app.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("app1") + "/app1.app.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("app1") + "/app1.app.dSYM/Contents/Resources/DWARF/app1")); QCOMPARE(QDir(relativeProductBuildDir("app1") + "/app1.app.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(!QFile::exists(relativeProductBuildDir("app2") + "/app2.app.dSYM")); QVERIFY(!QFile::exists(relativeProductBuildDir("app3") + "/app3.app.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("app3") + "/app3.app/Contents/MacOS/app3.dwarf")); QVERIFY(directoryExists(relativeProductBuildDir("app4") + "/app4.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("app4") + "/app4.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("app4") + "/app4.dSYM/Contents/Resources/DWARF/app4")); QCOMPARE(QDir(relativeProductBuildDir("app4") + "/app4.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(regularFileExists(relativeProductBuildDir("app5") + "/app5.dwarf")); QVERIFY(directoryExists(relativeProductBuildDir("foo1") + "/foo1.framework.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("foo1") + "/foo1.framework.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("foo1") + "/foo1.framework.dSYM/Contents/Resources/DWARF/foo1")); QCOMPARE(QDir(relativeProductBuildDir("foo1") + "/foo1.framework.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(!QFile::exists(relativeProductBuildDir("foo2") + "/foo2.framework.dSYM")); QVERIFY(!QFile::exists(relativeProductBuildDir("foo3") + "/foo3.framework.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("foo3") + "/foo3.framework/Versions/A/foo3.dwarf")); QVERIFY(directoryExists(relativeProductBuildDir("foo4") + "/libfoo4.dylib.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("foo4") + "/libfoo4.dylib.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("foo4") + "/libfoo4.dylib.dSYM/Contents/Resources/DWARF/libfoo4.dylib")); QCOMPARE(QDir(relativeProductBuildDir("foo4") + "/libfoo4.dylib.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(regularFileExists(relativeProductBuildDir("foo5") + "/libfoo5.dylib.dwarf")); QVERIFY(directoryExists(relativeProductBuildDir("bar1") + "/bar1.bundle.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("bar1") + "/bar1.bundle.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("bar1") + "/bar1.bundle.dSYM/Contents/Resources/DWARF/bar1")); QCOMPARE(QDir(relativeProductBuildDir("bar1") + "/bar1.bundle.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(!QFile::exists(relativeProductBuildDir("bar2") + "/bar2.bundle.dSYM")); QVERIFY(!QFile::exists(relativeProductBuildDir("bar3") + "/bar3.bundle.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("bar3") + "/bar3.bundle/Contents/MacOS/bar3.dwarf")); QVERIFY(directoryExists(relativeProductBuildDir("bar4") + "/bar4.bundle.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("bar4") + "/bar4.bundle.dSYM/Contents/Info.plist")); QVERIFY(regularFileExists(relativeProductBuildDir("bar4") + "/bar4.bundle.dSYM/Contents/Resources/DWARF/bar4.bundle")); QCOMPARE(QDir(relativeProductBuildDir("bar4") + "/bar4.bundle.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(regularFileExists(relativeProductBuildDir("bar5") + "/bar5.bundle.dwarf")); } else if (toolchain.contains("gcc")) { const bool isWindows = qbs::Internal::contains(targetOS, "windows"); const QString exeSuffix = isWindows ? ".exe" : ""; const QString dllPrefix = isWindows ? "" : "lib"; const QString dllSuffix = isWindows ? ".dll" : ".so"; QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1" + exeSuffix + ".debug")); QVERIFY(!QFile::exists(relativeProductBuildDir("app2") + "/app2" + exeSuffix + ".debug")); QVERIFY(QFile::exists(relativeProductBuildDir("foo1") + '/' + dllPrefix + "foo1" + dllSuffix + ".debug")); QVERIFY(!QFile::exists(relativeProductBuildDir("foo2") + '/' + "foo2" + dllSuffix + ".debug")); QVERIFY(QFile::exists(relativeProductBuildDir("bar1") + '/' + dllPrefix + "bar1" + dllSuffix + ".debug")); QVERIFY(!QFile::exists(relativeProductBuildDir("bar2") + '/' + dllPrefix + "bar2" + dllSuffix + ".debug")); } else if (toolchain.contains("msvc")) { QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1.pdb")); QVERIFY(QFile::exists(relativeProductBuildDir("foo1") + "/foo1.pdb")); QVERIFY(QFile::exists(relativeProductBuildDir("bar1") + "/bar1.pdb")); // MSVC's linker even creates a pdb file if /Z7 is passed to the compiler. } else { QSKIP("Unsupported toolchain. Skipping."); } } void TestBlackbox::trackAddFile() { QList output; QDir::setCurrent(testDataDir + "/trackAddFile"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackAddFile/work"); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); QString unchangedObjectFile = relativeBuildDir() + objectFileName("/someapp/narf.cpp", profileName()); QDateTime unchangedObjectFileTime1 = QFileInfo(unchangedObjectFile).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("trackAddFile.qbs"); touch("main.cpp"); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); QCOMPARE(output.takeFirst().trimmed().constData(), "ZORT!"); // the object file of the untouched source should not have changed QDateTime unchangedObjectFileTime2 = QFileInfo(unchangedObjectFile).lastModified(); QCOMPARE(unchangedObjectFileTime1, unchangedObjectFileTime2); } void TestBlackbox::trackExternalProductChanges() { QDir::setCurrent(testDataDir + "/trackExternalProductChanges"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); QbsRunParameters params; params.environment.insert("QBS_TEST_PULL_IN_FILE_VIA_ENV", "1"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY2(!m_qbsStdout.contains("compiling jsFileChange.cpp"), m_qbsStdout.constData()); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("fileList.js", "return []", "return ['jsFileChange.cpp']"); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); rmDirR(relativeBuildDir()); REPLACE_IN_FILE("fileList.js", "['jsFileChange.cpp']", "[]"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); QFile cppFile("fileExists.cpp"); QVERIFY(cppFile.open(QIODevice::WriteOnly)); cppFile.write("void fileExists() { }\n"); cppFile.close(); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(m_qbsStdout.contains("compiling fileExists.cpp")); rmDirR(relativeBuildDir()); const SettingsPtr s = settings(); const Profile profile(profileName(), s.get()); const QStringList toolchainTypes = profile.value("qbs.toolchain").toStringList(); if (!toolchainTypes.contains("gcc")) QSKIP("Need GCC-like compiler to run this test"); params.environment = QProcessEnvironment::systemEnvironment(); params.environment.insert("INCLUDE_PATH_TEST", "1"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("hiddenheaderqbs.h"), m_qbsStderr.constData()); params.command = "resolve"; params.environment.insert("CPLUS_INCLUDE_PATH", QDir::toNativeSeparators(QDir::currentPath() + "/hidden")); params.expectFailure = false; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); } void TestBlackbox::trackGroupConditionChange() { QbsRunParameters params; params.expectFailure = true; QDir::setCurrent(testDataDir + "/group-condition-change"); QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("jibbetnich")); params.command = "resolve"; params.arguments = QStringList("project.kaputt:false"); params.expectFailure = false; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); } void TestBlackbox::trackRemoveFile() { QList output; QDir::setCurrent(testDataDir + "/trackAddFile"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); ccp("after", "work"); QDir::setCurrent(testDataDir + "/trackAddFile/work"); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); QCOMPARE(output.takeFirst().trimmed().constData(), "ZORT!"); QString unchangedObjectFile = relativeBuildDir() + objectFileName("/someapp/narf.cpp", profileName()); QDateTime unchangedObjectFileTime1 = QFileInfo(unchangedObjectFile).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); QFile::remove("trackAddFile.qbs"); QFile::remove("main.cpp"); QFile::copy("../before/trackAddFile.qbs", "trackAddFile.qbs"); QFile::copy("../before/main.cpp", "main.cpp"); QVERIFY(QFile::remove("zort.h")); QVERIFY(QFile::remove("zort.cpp")); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("resolve"))), 0); touch("main.cpp"); touch("trackAddFile.qbs"); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); // the object file of the untouched source should not have changed QDateTime unchangedObjectFileTime2 = QFileInfo(unchangedObjectFile).lastModified(); QCOMPARE(unchangedObjectFileTime1, unchangedObjectFileTime2); // the object file for the removed cpp file should have vanished too QVERIFY(!regularFileExists(relativeBuildDir() + objectFileName("/someapp/zort.cpp", profileName()))); } void TestBlackbox::trackAddFileTag() { QList output; QDir::setCurrent(testDataDir + "/trackFileTags"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackFileTags/work"); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "there's no foo here"); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("main.cpp"); touch("trackFileTags.qbs"); waitForFileUnlock(); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "there's 15 foo here"); } void TestBlackbox::trackRemoveFileTag() { QList output; QDir::setCurrent(testDataDir + "/trackFileTags"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("after", "work"); QDir::setCurrent(testDataDir + "/trackFileTags/work"); const QbsRunParameters runParams("run", QStringList{"-qp", "someapp"}); QCOMPARE(runQbs(runParams), 0); // check if the artifacts are here that will become stale in the 2nd step QVERIFY(regularFileExists(relativeProductBuildDir("someapp") + '/' + inputDirHash(".") + objectFileName("/main_foo.cpp", profileName()))); QVERIFY(regularFileExists(relativeProductBuildDir("someapp") + "/main_foo.cpp")); QVERIFY(regularFileExists(relativeProductBuildDir("someapp") + "/main.foo")); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "there's 15 foo here"); WAIT_FOR_NEW_TIMESTAMP(); ccp("../before", "."); touch("main.cpp"); touch("trackFileTags.qbs"); QCOMPARE(runQbs(runParams), 0); output = m_qbsStdout.split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "there's no foo here"); // check if stale artifacts have been removed QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") + '/' + inputDirHash(".") + objectFileName("/main_foo.cpp", profileName())), false); QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") + "/main_foo.cpp"), false); QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") + "/main.foo"), false); } void TestBlackbox::trackAddProduct() { QDir::setCurrent(testDataDir + "/trackProducts"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackProducts/work"); QbsRunParameters params(QStringList() << "-f" << "trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(m_qbsStdout.contains("linking product1")); QVERIFY(m_qbsStdout.contains("linking product2")); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling zoo.cpp")); QVERIFY(m_qbsStdout.contains("linking product3")); QVERIFY(!m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(!m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(!m_qbsStdout.contains("linking product1")); QVERIFY(!m_qbsStdout.contains("linking product2")); } void TestBlackbox::trackRemoveProduct() { QDir::setCurrent(testDataDir + "/trackProducts"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); ccp("after", "work"); QDir::setCurrent(testDataDir + "/trackProducts/work"); QbsRunParameters params(QStringList() << "-f" << "trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(m_qbsStdout.contains("compiling zoo.cpp")); QVERIFY(m_qbsStdout.contains("linking product1")); QVERIFY(m_qbsStdout.contains("linking product2")); QVERIFY(m_qbsStdout.contains("linking product3")); WAIT_FOR_NEW_TIMESTAMP(); QFile::remove("zoo.cpp"); QFile::remove("product3.qbs"); copyFileAndUpdateTimestamp("../before/trackProducts.qbs", "trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(!m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(!m_qbsStdout.contains("compiling zoo.cpp")); QVERIFY(!m_qbsStdout.contains("linking product1")); QVERIFY(!m_qbsStdout.contains("linking product2")); QVERIFY(!m_qbsStdout.contains("linking product3")); } void TestBlackbox::wildcardRenaming() { QDir::setCurrent(testDataDir + "/wildcard_renaming"); QCOMPARE(runQbs(QbsRunParameters("install")), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/pioniere.txt").exists()); WAIT_FOR_NEW_TIMESTAMP(); QFile::rename(QDir::currentPath() + "/pioniere.txt", QDir::currentPath() + "/fdj.txt"); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("install"), QStringList("--clean-install-root"))), 0); QVERIFY(!QFileInfo(defaultInstallRoot + "/pioniere.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/fdj.txt").exists()); } void TestBlackbox::recursiveRenaming() { QDir::setCurrent(testDataDir + "/recursive_renaming"); QCOMPARE(runQbs(QbsRunParameters("install")), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/wasser.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/subdir/blubb.txt").exists()); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(QFile::rename(QDir::currentPath() + "/dir/wasser.txt", QDir::currentPath() + "/dir/wein.txt")); QCOMPARE(runQbs(QbsRunParameters(QStringLiteral("install"), QStringList("--clean-install-root"))), 0); QVERIFY(!QFileInfo(defaultInstallRoot + "/dir/wasser.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/wein.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/subdir/blubb.txt").exists()); } void TestBlackbox::recursiveWildcards() { QDir::setCurrent(testDataDir + "/recursive_wildcards"); QCOMPARE(runQbs(QbsRunParameters("install")), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file1.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file2.txt").exists()); QFile outputFile(defaultInstallRoot + "/output.txt"); QVERIFY2(outputFile.open(QIODevice::ReadOnly), qPrintable(outputFile.errorString())); QCOMPARE(outputFile.readAll(), QByteArray("file1.txtfile2.txt")); outputFile.close(); WAIT_FOR_NEW_TIMESTAMP(); QFile newFile("dir/subdir/file3.txt"); QVERIFY2(newFile.open(QIODevice::WriteOnly), qPrintable(newFile.errorString())); newFile.close(); QCOMPARE(runQbs(QbsRunParameters("install")), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file3.txt").exists()); QVERIFY2(outputFile.open(QIODevice::ReadOnly), qPrintable(outputFile.errorString())); QCOMPARE(outputFile.readAll(), QByteArray("file1.txtfile2.txtfile3.txt")); outputFile.close(); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY2(newFile.remove(), qPrintable(newFile.errorString())); QVERIFY2(!newFile.exists(), qPrintable(newFile.fileName())); QCOMPARE(runQbs(QbsRunParameters("install", QStringList{ "--clean-install-root"})), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file1.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file2.txt").exists()); QVERIFY(!QFileInfo(defaultInstallRoot + "/dir/file3.txt").exists()); QVERIFY2(outputFile.open(QIODevice::ReadOnly), qPrintable(outputFile.errorString())); QCOMPARE(outputFile.readAll(), QByteArray("file1.txtfile2.txt")); } void TestBlackbox::referenceErrorInExport() { QDir::setCurrent(testDataDir + "/referenceErrorInExport"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains( "referenceErrorInExport.qbs:15:12 ReferenceError: Can't find variable: includePaths")); } void TestBlackbox::reproducibleBuild() { const SettingsPtr s = settings(); const Profile profile(profileName(), s.get()); const QStringList toolchains = profile.value("qbs.toolchain").toStringList(); if (!toolchains.contains("gcc") || toolchains.contains("clang")) QSKIP("reproducible builds only supported for gcc"); QFETCH(bool, reproducible); QDir::setCurrent(testDataDir + "/reproducible-build"); QbsRunParameters params; params.arguments << QString("modules.cpp.enableReproducibleBuilds:") + (reproducible ? "true" : "false"); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); QFile object(relativeProductBuildDir("the product") + '/' + inputDirHash(".") + '/' + objectFileName("file1.cpp", profileName())); QVERIFY2(object.open(QIODevice::ReadOnly), qPrintable(object.fileName())); const QByteArray oldContents = object.readAll(); object.close(); QCOMPARE(runQbs(QbsRunParameters("clean")), 0); QVERIFY(!object.exists()); QCOMPARE(runQbs(params), 0); if (reproducible) { QVERIFY(object.open(QIODevice::ReadOnly)); const QByteArray newContents = object.readAll(); QVERIFY(oldContents == newContents); object.close(); } QCOMPARE(runQbs(QbsRunParameters("clean")), 0); } void TestBlackbox::reproducibleBuild_data() { QTest::addColumn("reproducible"); QTest::newRow("non-reproducible build") << false; QTest::newRow("reproducible build") << true; } void TestBlackbox::responseFiles() { QDir::setCurrent(testDataDir + "/response-files"); QbsRunParameters params; params.command = "install"; params.arguments << "--install-root" << "installed"; QCOMPARE(runQbs(params), 0); QFile file("installed/response-file-content.txt"); QVERIFY(file.open(QIODevice::ReadOnly)); const QList expected = QList() << "foo" << qbs::Internal::shellQuote(QStringLiteral("with space")).toUtf8() << "bar" << ""; QList lines = file.readAll().split('\n'); for (auto &line : lines) line = line.trimmed(); QCOMPARE(lines, expected); } void TestBlackbox::retaggedOutputArtifact() { QDir::setCurrent(testDataDir + "/retagged-output-artifact"); QbsRunParameters resolveParams("resolve"); resolveParams.arguments = QStringList("products.p.useTag1:true"); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(), 0); const QString a2 = relativeProductBuildDir("p") + "/a2.txt"; const QString a3 = relativeProductBuildDir("p") + "/a3.txt"; QVERIFY2(QFile::exists(a2), qPrintable(a2)); QVERIFY2(!QFile::exists(a3), qPrintable(a3)); resolveParams.arguments = QStringList("products.p.useTag1:false"); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!QFile::exists(a2), qPrintable(a2)); QVERIFY2(QFile::exists(a3), qPrintable(a3)); resolveParams.arguments = QStringList("products.p.useTag1:true"); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(), 0); QVERIFY2(QFile::exists(a2), qPrintable(a2)); QVERIFY2(!QFile::exists(a3), qPrintable(a3)); } void TestBlackbox::ruleConditions() { QDir::setCurrent(testDataDir + "/ruleConditions"); QCOMPARE(runQbs(), 0); QVERIFY(QFileInfo(relativeExecutableFilePath("zorted")).exists()); QVERIFY(QFileInfo(relativeExecutableFilePath("unzorted")).exists()); QVERIFY(QFileInfo(relativeProductBuildDir("zorted") + "/zorted.foo.narf.zort").exists()); QVERIFY(!QFileInfo(relativeProductBuildDir("unzorted") + "/unzorted.foo.narf.zort").exists()); } void TestBlackbox::ruleConnectionWithExcludedInputs() { QDir::setCurrent(testDataDir + "/rule-connection-with-excluded-inputs"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("inputs.x: 2") && m_qbsStdout.contains("inputs.y: 0"), m_qbsStdout.constData()); } void TestBlackbox::ruleCycle() { QDir::setCurrent(testDataDir + "/ruleCycle"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("Cycle detected in rule dependencies")); } void TestBlackbox::ruleWithNoInputs() { QDir::setCurrent(testDataDir + "/rule-with-no-inputs"); QVERIFY2(runQbs() == 0, m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("running the rule"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("creating output"), m_qbsStdout.constData()); QVERIFY2(runQbs() == 0, m_qbsStderr.constData()); QVERIFY2(!m_qbsStdout.contains("running the rule"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating output"), m_qbsStdout.constData()); QbsRunParameters params("resolve", QStringList() << "products.theProduct.version:1"); QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); params.command = "build"; QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); QVERIFY2(!m_qbsStdout.contains("running the rule"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating output"), m_qbsStdout.constData()); params.command = "resolve"; params.arguments = QStringList() << "products.theProduct.version:2"; QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); params.command = "build"; QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); QVERIFY2(!m_qbsStdout.contains("running the rule"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("creating output"), m_qbsStdout.constData()); params.command = "resolve"; params.arguments = QStringList() << "products.theProduct.version:2" << "products.theProduct.dummy:true"; QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); params.command = "build"; QVERIFY2(runQbs(params) == 0, m_qbsStderr.constData()); QVERIFY2(m_qbsStdout.contains("running the rule"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("creating output"), m_qbsStdout.constData()); } void TestBlackbox::ruleWithNonRequiredInputs() { QDir::setCurrent(testDataDir + "/rule-with-non-required-inputs"); QbsRunParameters params("build", {"products.p.enableTagger:false"}); QCOMPARE(runQbs(params), 0); QFile outFile(relativeProductBuildDir("p") + "/output.txt"); QVERIFY2(outFile.open(QIODevice::ReadOnly), qPrintable(outFile.errorString())); QByteArray output = outFile.readAll(); QCOMPARE(output, QByteArray("()")); outFile.close(); params.command = "resolve"; params.arguments = QStringList({"products.p.enableTagger:true"}); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(outFile.open(QIODevice::ReadOnly), qPrintable(outFile.errorString())); output = outFile.readAll(); QCOMPARE(output, QByteArray("(a.inp,b.inp,c.inp,)")); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("Generating"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("a.inp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Generating"), m_qbsStdout.constData()); } void TestBlackbox::scannerItem() { QDir::setCurrent(testDataDir + "/scanner-item"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("handling file1.in"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("handling file2.in"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("subdir1/file.inc"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("handling file1.in"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("handling file2.in"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("subdir2/file.inc"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("handling file1.in"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("handling file2.in"), m_qbsStdout.constData()); } void TestBlackbox::setupBuildEnvironment() { QDir::setCurrent(testDataDir + "/setup-build-environment"); QCOMPARE(runQbs(), 0); QFile f(relativeProductBuildDir("first_product") + QLatin1String("/m.output")); QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString())); QCOMPARE(f.readAll().trimmed(), QByteArray("1")); f.close(); f.setFileName(relativeProductBuildDir("second_product") + QLatin1String("/m.output")); QVERIFY2(f.open(QIODevice::ReadOnly), qPrintable(f.errorString())); QCOMPARE(f.readAll().trimmed(), QByteArray()); } void TestBlackbox::setupRunEnvironment() { QDir::setCurrent(testDataDir + "/setup-run-environment"); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); QbsRunParameters failParams("run", QStringList({"--setup-run-env-config", "ignore-lib-dependencies"})); failParams.expectFailure = true; failParams.expectCrash = m_qbsStdout.contains("is windows"); QVERIFY(runQbs(QbsRunParameters(failParams)) != 0); QVERIFY2(failParams.expectCrash || m_qbsStderr.contains("lib"), m_qbsStderr.constData()); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QbsRunParameters dryRunParams("run", QStringList("--dry-run")); dryRunParams.buildDirectory = "dryrun"; QCOMPARE(runQbs(dryRunParams), 0); const QString appFilePath = QDir::currentPath() + "/dryrun/" + relativeExecutableFilePath("app"); QVERIFY2(m_qbsStdout.contains("Would start target") && m_qbsStdout.contains(QDir::toNativeSeparators(appFilePath).toLocal8Bit()), m_qbsStdout.constData()); } void TestBlackbox::smartRelinking() { QDir::setCurrent(testDataDir + "/smart-relinking"); rmDirR(relativeBuildDir()); QFETCH(bool, strictChecking); QbsRunParameters params(QStringList() << (QString("modules.cpp.exportedSymbolsCheckMode:%1") .arg(strictChecking ? "strict" : "ignore-undefined"))); QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains("project disabled")) QSKIP("Test does not apply on this target"); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Irrelevant change. WAIT_FOR_NEW_TIMESTAMP(); touch("lib.cpp"); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Add new private symbol. WAIT_FOR_NEW_TIMESTAMP(); params.command = "resolve"; params.arguments << "products.lib.defines:PRIV2"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Remove private symbol. WAIT_FOR_NEW_TIMESTAMP(); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Add new public symbol. WAIT_FOR_NEW_TIMESTAMP(); params.arguments << "products.lib.defines:PUB2"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Remove public symbol. WAIT_FOR_NEW_TIMESTAMP(); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Add new undefined symbol. WAIT_FOR_NEW_TIMESTAMP(); params.arguments << "products.lib.defines:PRINTF"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(strictChecking == m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); // Remove undefined symbol. WAIT_FOR_NEW_TIMESTAMP(); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking lib"), m_qbsStdout.constData()); QVERIFY2(strictChecking == m_qbsStdout.contains("linking app"), m_qbsStdout.constData()); } void TestBlackbox::smartRelinking_data() { QTest::addColumn("strictChecking"); QTest::newRow("strict checking") << true; QTest::newRow("ignore undefined") << false; } static QString soName(const QString &readElfPath, const QString &libFilePath) { QProcess readElf; readElf.start(readElfPath, QStringList() << "-a" << libFilePath); if (!readElf.waitForStarted() || !readElf.waitForFinished() || readElf.exitCode() != 0) { qDebug() << readElf.errorString() << readElf.readAllStandardError(); return {}; } const QByteArray output = readElf.readAllStandardOutput(); const QByteArray magicString = "Library soname: ["; const int magicStringIndex = output.indexOf(magicString); if (magicStringIndex == -1) return {}; const int endIndex = output.indexOf(']', magicStringIndex); if (endIndex == -1) return {}; const int nameIndex = magicStringIndex + magicString.size(); const QByteArray theName = output.mid(nameIndex, endIndex - nameIndex); return QString::fromLatin1(theName); } void TestBlackbox::soVersion() { const QString readElfPath = findExecutable(QStringList("readelf")); if (readElfPath.isEmpty() || readElfPath.endsWith("exe")) QSKIP("soversion test not applicable on this system"); QDir::setCurrent(testDataDir + "/soversion"); QFETCH(QString, soVersion); QFETCH(bool, useVersion); QFETCH(QString, expectedSoName); QbsRunParameters params; params.arguments << ("products.mylib.useVersion:" + QString((useVersion ? "true" : "false"))); if (!soVersion.isNull()) params.arguments << ("modules.cpp.soVersion:" + soVersion); const QString libFilePath = relativeProductBuildDir("mylib") + "/libmylib.so" + (useVersion ? ".1.2.3" : QString()); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); QVERIFY2(regularFileExists(libFilePath), qPrintable(libFilePath)); QCOMPARE(soName(readElfPath, libFilePath), expectedSoName); } void TestBlackbox::soVersion_data() { QTest::addColumn("soVersion"); QTest::addColumn("useVersion"); QTest::addColumn("expectedSoName"); QTest::newRow("default") << QString() << true << QString("libmylib.so.1"); QTest::newRow("explicit soVersion") << QString("1.2") << true << QString("libmylib.so.1.2"); QTest::newRow("empty soVersion") << QString("") << true << QString("libmylib.so.1.2.3"); QTest::newRow("no version, explicit soVersion") << QString("5") << false << QString("libmylib.so.5"); QTest::newRow("no version, default soVersion") << QString() << false << QString("libmylib.so"); QTest::newRow("no version, empty soVersion") << QString("") << false << QString("libmylib.so"); } void TestBlackbox::sourceArtifactChanges() { QDir::setCurrent(testDataDir + "/source-artifact-changes"); bool useCustomFileTags = false; bool overrideFileTags = true; bool filesAreTargets = false; bool useCxx11 = false; const QString appFilePath = QDir::currentPath() + '/' + relativeExecutableFilePath("app"); static const auto b2s = [](bool b) { return QString(b ? "true" : "false"); }; const auto resolveParams = [&useCustomFileTags, &overrideFileTags, &filesAreTargets, &useCxx11] { return QbsRunParameters("resolve", QStringList{ "modules.module_with_files.overrideTags:" + b2s(overrideFileTags), "modules.module_with_files.filesAreTargets:" + b2s(filesAreTargets), "modules.module_with_files.fileTags:" + QString(useCustomFileTags ? "custom" : "cpp"), "modules.cpp.cxxLanguageVersion:" + QString(useCxx11 ? "c++11" : "c++98") }); }; #define VERIFY_COMPILATION(expected) \ do { \ QVERIFY2(m_qbsStdout.contains("compiling main.cpp") == expected, m_qbsStdout.constData()); \ QVERIFY2(QFile::exists(appFilePath) == expected, qPrintable(appFilePath)); \ if (expected) \ QVERIFY2(m_qbsStdout.contains("cpp artifacts: 1"), m_qbsStdout.constData()); \ else \ QVERIFY2(m_qbsStdout.contains("cpp artifacts: 0"), m_qbsStdout.constData()); \ } while (false) // Initial build. QCOMPARE(runQbs(resolveParams()), 0); QVERIFY2(m_qbsStdout.contains("is gcc: "), m_qbsStdout.constData()); const bool isGcc = m_qbsStdout.contains("is gcc: true"); QCOMPARE(runQbs(), 0); VERIFY_COMPILATION(true); // Overwrite the file tags. Now the source file is no longer tagged "cpp" and nothing // should get built. WAIT_FOR_NEW_TIMESTAMP(); touch("modules/module_with_files/main.cpp"); useCustomFileTags = true; QCOMPARE(runQbs(resolveParams()), 0); QCOMPARE(runQbs(), 0); VERIFY_COMPILATION(false); // Now the custom file tag exists in addition to "cpp", and the app should get built again. overrideFileTags = false; QCOMPARE(runQbs(resolveParams()), 0); QCOMPARE(runQbs(), 0); VERIFY_COMPILATION(true); // Mark the cpp file as a module target. Now it will no longer be considered an input // by the compiler rule, and nothing should get built. WAIT_FOR_NEW_TIMESTAMP(); touch("modules/module_with_files/main.cpp"); filesAreTargets = true; QCOMPARE(runQbs(resolveParams()), 0); QCOMPARE(runQbs(), 0); VERIFY_COMPILATION(false); // Now just revert the last change. filesAreTargets = false; QCOMPARE(runQbs(resolveParams()), 0); QCOMPARE(runQbs(), 0); VERIFY_COMPILATION(true); // Change a relevant cpp property. A rebuild is expected. useCxx11 = true; QCOMPARE(runQbs(resolveParams()), 0); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line"})), 0); if (isGcc) { QVERIFY2(m_qbsStdout.contains("-std=c++11") || m_qbsStdout.contains("-std=c++0x"), m_qbsStdout.constData()); } #undef VERIFY_COMPILATION } void TestBlackbox::overrideProjectProperties() { QDir::setCurrent(testDataDir + "/overrideProjectProperties"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << QStringLiteral("-f") << QStringLiteral("overrideProjectProperties.qbs") << QStringLiteral("project.nameSuffix:ForYou") << QStringLiteral("project.someBool:false") << QStringLiteral("project.someInt:156") << QStringLiteral("project.someStringList:one") << QStringLiteral("products.MyAppForYou.mainFile:main.cpp"))), 0); QVERIFY(regularFileExists(relativeExecutableFilePath("MyAppForYou"))); QVERIFY(QFile::remove(relativeBuildGraphFilePath())); QbsRunParameters params; params.arguments << QStringLiteral("-f") << QStringLiteral("project_using_helper_lib.qbs"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); rmDirR(relativeBuildDir()); params.arguments = QStringList() << QStringLiteral("-f") << QStringLiteral("project_using_helper_lib.qbs") << QStringLiteral("project.linkSuccessfully:true"); params.expectFailure = false; QCOMPARE(runQbs(params), 0); } void TestBlackbox::pchChangeTracking() { QDir::setCurrent(testDataDir + "/pch-change-tracking"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("precompiling pch.h (cpp)")); WAIT_FOR_NEW_TIMESTAMP(); touch("header1.h"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("precompiling pch.h (cpp)")); QVERIFY(m_qbsStdout.contains("compiling header2.cpp")); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); WAIT_FOR_NEW_TIMESTAMP(); touch("header2.h"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("precompiling pch.h (cpp)"), m_qbsStdout.constData()); } void TestBlackbox::perGroupDefineInExportItem() { QDir::setCurrent(testDataDir + "/per-group-define-in-export-item"); QCOMPARE(runQbs(), 0); } void TestBlackbox::pkgConfigProbe() { const QString exe = findExecutable(QStringList() << "pkg-config"); if (exe.isEmpty()) QSKIP("This test requires the pkg-config tool"); QDir::setCurrent(testDataDir + "/pkg-config-probe"); QFETCH(QString, packageBaseName); QFETCH(QStringList, found); QFETCH(QStringList, libs); QFETCH(QStringList, cflags); QFETCH(QStringList, version); rmDirR(relativeBuildDir()); QbsRunParameters params(QStringList() << ("project.packageBaseName:" + packageBaseName)); QCOMPARE(runQbs(params), 0); const QString stdOut = m_qbsStdout; QVERIFY2(stdOut.contains("theProduct1 found: " + found.at(0)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct2 found: " + found.at(1)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct1 libs: " + libs.at(0)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct2 libs: " + libs.at(1)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct1 cflags: " + cflags.at(0)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct2 cflags: " + cflags.at(1)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct1 version: " + version.at(0)), m_qbsStdout.constData()); QVERIFY2(stdOut.contains("theProduct2 version: " + version.at(1)), m_qbsStdout.constData()); } void TestBlackbox::pkgConfigProbe_data() { QTest::addColumn("packageBaseName"); QTest::addColumn("found"); QTest::addColumn("libs"); QTest::addColumn("cflags"); QTest::addColumn("version"); QTest::newRow("existing package") << "dummy" << (QStringList() << "true" << "true") << (QStringList() << "[\"-Ldummydir1\",\"-ldummy1\"]" << "[\"-Ldummydir2\",\"-ldummy2\"]") << (QStringList() << "[]" << "[]") << (QStringList() << "0.0.1" << "0.0.2"); // Note: The array values should be "undefined", but we lose that information when // converting to QVariants in the ProjectResolver. QTest::newRow("non-existing package") << "blubb" << (QStringList() << "false" << "false") << (QStringList() << "[]" << "[]") << (QStringList() << "[]" << "[]") << (QStringList() << "undefined" << "undefined"); } void TestBlackbox::pkgConfigProbeSysroot() { const QString exe = findExecutable(QStringList() << "pkg-config"); if (exe.isEmpty()) QSKIP("This test requires the pkg-config tool"); QDir::setCurrent(testDataDir + "/pkg-config-probe-sysroot"); QCOMPARE(runQbs(QStringList("-v")), 0); QCOMPARE(m_qbsStderr.count("PkgConfigProbe: found packages"), 2); const QString outputTemplate = "theProduct%1 libs: [\"-L%2/usr/dummy\",\"-ldummy1\"]"; QVERIFY2(m_qbsStdout.contains(outputTemplate .arg("1", QDir::currentPath() + "/sysroot1").toLocal8Bit()), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains(outputTemplate .arg("2", QDir::currentPath() + "/sysroot2").toLocal8Bit()), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains(outputTemplate .arg("3", QDir::currentPath() + "/sysroot1").toLocal8Bit()), m_qbsStdout.constData()); } void TestBlackbox::pluginDependency() { QDir::setCurrent(testDataDir + "/plugin-dependency"); // Build the plugins and the helper2 lib. QCOMPARE(runQbs(QStringList{"--products", "plugin1,plugin2,plugin3,plugin4,helper2"}), 0); QVERIFY(m_qbsStdout.contains("plugin1")); QVERIFY(m_qbsStdout.contains("plugin2")); QVERIFY(m_qbsStdout.contains("plugin3")); QVERIFY(m_qbsStdout.contains("plugin4")); QVERIFY(m_qbsStdout.contains("helper2")); QVERIFY(!m_qbsStderr.contains("SOFT ASSERT")); // Build the app. Plugins 1 and 2 must not be linked. Plugin 3 must be linked. QCOMPARE(runQbs(QStringList{"--command-echo-mode", "command-line"}), 0); QByteArray output = m_qbsStdout + '\n' + m_qbsStderr; QVERIFY(!output.contains("plugin1")); QVERIFY(!output.contains("plugin2")); QVERIFY(!output.contains("helper2")); // Test change tracking for parameter in Parameters item. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("plugin-dependency.qbs", "false // marker 1", "true"); QCOMPARE(runQbs(QStringList{"-p", "plugin2"}), 0); QVERIFY2(!m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QCOMPARE(runQbs(QStringList{"--command-echo-mode", "command-line"}), 0); output = m_qbsStdout + '\n' + m_qbsStderr; QVERIFY2(!output.contains("plugin1"), output.constData()); QVERIFY2(!output.contains("helper2"), output.constData()); QVERIFY2(output.contains("plugin2"), output.constData()); // Test change tracking for parameter in Depends item. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("plugin-dependency.qbs", "false /* marker 2 */", "true"); QCOMPARE(runQbs(QStringList{"-p", "helper1", "--command-echo-mode", "command-line"}), 0); output = m_qbsStdout + '\n' + m_qbsStderr; QVERIFY2(output.contains("helper2"), output.constData()); // Check that the build dependency still works. QCOMPARE(runQbs(QStringLiteral("clean")), 0); QCOMPARE(runQbs(QStringList{"--products", "myapp", "--command-echo-mode", "command-line"}), 0); QVERIFY(m_qbsStdout.contains("plugin1")); QVERIFY(m_qbsStdout.contains("plugin2")); QVERIFY(m_qbsStdout.contains("plugin3")); QVERIFY(m_qbsStdout.contains("plugin4")); } void TestBlackbox::precompiledAndPrefixHeaders() { QDir::setCurrent(testDataDir + "/precompiled-and-prefix-headers"); QCOMPARE(runQbs(), 0); } void TestBlackbox::preventFloatingPointValues() { QDir::setCurrent(testDataDir + "/prevent-floating-point-values"); QCOMPARE(runQbs(QStringList("products.p.version:1.50")), 0); QVERIFY2(m_qbsStdout.contains("version: 1.50"), m_qbsStdout.constData()); } void TestBlackbox::probeChangeTracking() { QDir::setCurrent(testDataDir + "/probe-change-tracking"); // Product probe disabled, other probes enabled. QbsRunParameters params; params.command = "resolve"; params.arguments = QStringList("products.theProduct.runProbe:false"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("running tlpProbe")); QVERIFY(m_qbsStdout.contains("running subProbe")); QVERIFY(!m_qbsStdout.contains("running productProbe")); // Product probe newly enabled. params.arguments = QStringList("products.theProduct.runProbe:true"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); // Re-resolving with unchanged probe. WAIT_FOR_NEW_TIMESTAMP(); touch("probe-change-tracking.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(!m_qbsStdout.contains("running productProbe")); // Re-resolving with changed configure scripts. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("probe-change-tracking.qbs", "console.info", " console.info"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(m_qbsStdout.contains("running tlpProbe")); QVERIFY(m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); // Re-resolving with added property. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("probe-change-tracking.qbs", "condition: product.runProbe", "condition: product.runProbe\nproperty string something: 'x'"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); // Re-resolving with changed property. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("probe-change-tracking.qbs", "'x'", "'y'"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); // Re-resolving with removed property. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("probe-change-tracking.qbs", "property string something: 'y'", ""); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); // Re-resolving with unchanged probe again. WAIT_FOR_NEW_TIMESTAMP(); touch("probe-change-tracking.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(!m_qbsStdout.contains("running tlpProbe")); QVERIFY(!m_qbsStdout.contains("running subProbe")); QVERIFY(!m_qbsStdout.contains("running productProbe")); // Enforcing re-running via command-line option. params.arguments.prepend("--force-probe-execution"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Resolving")); QVERIFY(m_qbsStdout.contains("running tlpProbe")); QVERIFY(m_qbsStdout.contains("running subProbe")); QVERIFY(m_qbsStdout.contains("running productProbe: 12")); } void TestBlackbox::probeProperties() { QDir::setCurrent(testDataDir + "/probeProperties"); const QByteArray dir = QDir::cleanPath(testDataDir).toLatin1() + "/probeProperties"; QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("probe1.fileName=bin/tool"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe1.path=" + dir), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe1.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe2.fileName=tool"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe2.path=" + dir + "/bin"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe2.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData()); } void TestBlackbox::probesAndShadowProducts() { QDir::setCurrent(testDataDir + "/probes-and-shadow-products"); QCOMPARE(runQbs(QStringList("--log-time")), 0); QVERIFY2(m_qbsStdout.contains("2 probes encountered, 1 configure scripts executed"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("probes-and-shadow-products.qbs"); QCOMPARE(runQbs(QStringList("--log-time")), 0); QVERIFY2(m_qbsStdout.contains("2 probes encountered, 0 configure scripts executed"), m_qbsStdout.constData()); } void TestBlackbox::probeInExportedModule() { QDir::setCurrent(testDataDir + "/probe-in-exported-module"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << QStringLiteral("-f") << QStringLiteral("probe-in-exported-module.qbs"))), 0); QVERIFY2(m_qbsStdout.contains("found: true"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("prop: yes"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("listProp: my,myother"), m_qbsStdout.constData()); } void TestBlackbox::probesAndArrayProperties() { QDir::setCurrent(testDataDir + "/probes-and-array-properties"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("prop: [\"probe\"]"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("probes-and-array-properties.qbs", "//", ""); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("prop: [\"product\",\"probe\"]"), m_qbsStdout.constData()); } void TestBlackbox::productProperties() { QDir::setCurrent(testDataDir + "/productproperties"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << QStringLiteral("-f") << QStringLiteral("productproperties.qbs"))), 0); QVERIFY(regularFileExists(relativeExecutableFilePath("blubb_user"))); } void TestBlackbox::propertyAssignmentOnNonPresentModule() { QDir::setCurrent(testDataDir + "/property-assignment-on-non-present-module"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); } void TestBlackbox::propertyAssignmentInFailedModule() { QDir::setCurrent(testDataDir + "/property-assignment-in-failed-module"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.m.doFail:false"))), 0); QbsRunParameters failParams; failParams.expectFailure = true; QVERIFY(runQbs(failParams) != 0); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.m.doFail:true"))), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QEXPECT_FAIL(0, "circular dependency between module merging and validation", Continue); QCOMPARE(runQbs(failParams), 0); } void TestBlackbox::propertyChanges() { QDir::setCurrent(testDataDir + "/propertyChanges"); const QString projectFile("propertyChanges.qbs"); QbsRunParameters params(QStringList({"-f", "propertyChanges.qbs", "qbs.enableDebugCode:true"})); // Initial build. QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(m_qbsStdout.contains("Making output from input")); QVERIFY(m_qbsStdout.contains("default value")); QVERIFY(m_qbsStdout.contains("Making output from other output")); QFile generatedFile(relativeProductBuildDir("generated text file") + "/generated.txt"); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 1contents 1suffix 1")); generatedFile.close(); // Incremental build with no changes. QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp.cpp")); QVERIFY(!m_qbsStdout.contains("linking")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build with no changes, but updated project file timestamp. WAIT_FOR_NEW_TIMESTAMP(); touch(projectFile); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("linking")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, input property changed for first product WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "blubb1", "blubb01"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("linking library")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, input property changed via project for second product. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "blubb2", "blubb02"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, input property changed via command line for second product. params.command = "resolve"; params.arguments << "project.projectDefines:blubb002"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, input property changed via environment for third product. params.environment.insert("QBS_BLACKBOX_DEFINE", "newvalue"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); params.environment.remove("QBS_BLACKBOX_DEFINE"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); params.environment.insert("QBS_BLACKBOX_DEFINE", "newvalue"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); params.environment.remove("QBS_BLACKBOX_DEFINE"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, module property changed via command line. params.arguments << "qbs.enableDebugCode:false"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.release")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, non-essential dependency removed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "Depends { name: 'library' }", "// Depends { name: 'library' }"); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("linking library")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, prepare script of a transformer changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "contents 1", "contents 2"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 1contents 2suffix 1")); generatedFile.close(); // Incremental build, product property used in JavaScript command changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "prefix 1", "prefix 2"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 2contents 2suffix 1")); generatedFile.close(); // Incremental build, project property used in JavaScript command changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "suffix 1", "suffix 2"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 2contents 2suffix 2")); generatedFile.close(); // Incremental build, module property used in JavaScript command changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "default value", "new value"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(m_qbsStdout.contains("Making output from input")); QVERIFY(m_qbsStdout.contains("Making output from other output")); QVERIFY(m_qbsStdout.contains("new value")); // Incremental build, prepare script of a rule in a module changed. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("modules/TestModule/module.qbs", "// console.info('Change in source code')", "console.info('Change in source code')"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(m_qbsStdout.contains("Making output from input")); QVERIFY(m_qbsStdout.contains("Making output from other output")); } void TestBlackbox::qtBug51237() { const QString profileName = "profile-qtBug51237"; const QString propertyName = "mymodule.theProperty"; { const SettingsPtr s = settings(); Profile profile(profileName, s.get()); profile.setValue(propertyName, QStringList()); } QDir::setCurrent(testDataDir + "/QTBUG-51237"); QbsRunParameters params; params.profile = profileName; QCOMPARE(runQbs(params), 0); } void TestBlackbox::dynamicMultiplexRule() { const QString testDir = testDataDir + "/dynamicMultiplexRule"; QDir::setCurrent(testDir); QCOMPARE(runQbs(), 0); const QString outputFilePath = relativeProductBuildDir("dynamicMultiplexRule") + "/stuff-from-3-inputs"; QVERIFY(regularFileExists(outputFilePath)); WAIT_FOR_NEW_TIMESTAMP(); touch("two.txt"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(outputFilePath)); } void TestBlackbox::dynamicProject() { const QString testDir = testDataDir + "/dynamic-project"; QDir::setCurrent(testDir); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("compiling main.cpp"), 2); } void TestBlackbox::dynamicRuleOutputs() { const QString testDir = testDataDir + "/dynamicRuleOutputs"; QDir::setCurrent(testDir); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDir + "/work"); QCOMPARE(runQbs(), 0); const QString appFile = relativeExecutableFilePath("genlexer"); const QString headerFile1 = relativeProductBuildDir("genlexer") + "/GeneratedFiles/numberscanner.h"; const QString sourceFile1 = relativeProductBuildDir("genlexer") + "/GeneratedFiles/numberscanner.c"; const QString sourceFile2 = relativeProductBuildDir("genlexer") + "/GeneratedFiles/lex.yy.c"; // Check build #1: source and header file name are specified in numbers.l QVERIFY(regularFileExists(appFile)); QVERIFY(regularFileExists(headerFile1)); QVERIFY(regularFileExists(sourceFile1)); QVERIFY(!QFile::exists(sourceFile2)); QDateTime appFileTimeStamp1 = QFileInfo(appFile).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("../after/numbers.l", "numbers.l"); QCOMPARE(runQbs(), 0); // Check build #2: no file names are specified in numbers.l // flex will default to lex.yy.c without header file. QDateTime appFileTimeStamp2 = QFileInfo(appFile).lastModified(); QVERIFY(appFileTimeStamp1 < appFileTimeStamp2); QVERIFY(!QFile::exists(headerFile1)); QVERIFY(!QFile::exists(sourceFile1)); QVERIFY(regularFileExists(sourceFile2)); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("../before/numbers.l", "numbers.l"); QCOMPARE(runQbs(), 0); // Check build #3: source and header file name are specified in numbers.l QDateTime appFileTimeStamp3 = QFileInfo(appFile).lastModified(); QVERIFY(appFileTimeStamp2 < appFileTimeStamp3); QVERIFY(regularFileExists(appFile)); QVERIFY(regularFileExists(headerFile1)); QVERIFY(regularFileExists(sourceFile1)); QVERIFY(!QFile::exists(sourceFile2)); } void TestBlackbox::erroneousFiles_data() { QTest::addColumn("errorMessage"); QTest::newRow("nonexistentWorkingDir") << "The working directory '.does.not.exist' for process '.*ls.*' is invalid."; QTest::newRow("outputArtifacts-missing-filePath") << "Error in Rule\\.outputArtifacts\\[0\\]\n\r?" "Property filePath must be a non-empty string\\."; QTest::newRow("outputArtifacts-missing-fileTags") << "Error in Rule\\.outputArtifacts\\[0\\]\n\r?" "Property fileTags for artifact 'outputArtifacts-missing-fileTags\\.txt' " "must be a non-empty string list\\."; QTest::newRow("texttemplate-unknown-placeholder") << "Placeholder 'what' is not defined in textemplate.dict for 'boom.txt.in'"; QTest::newRow("tag-mismatch") << "tag-mismatch.qbs:8:18.*Artifact '.*dummy1' has undeclared file tags " "\\[\"y\",\"z\"\\]."; } void TestBlackbox::erroneousFiles() { QFETCH(QString, errorMessage); QDir::setCurrent(testDataDir + "/erroneous/" + QTest::currentDataTag()); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QString err = QString::fromLocal8Bit(m_qbsStderr); if (!err.contains(QRegExp(errorMessage))) { qDebug().noquote() << "Output: " << err; qDebug().noquote() << "Expected: " << errorMessage; QFAIL("Unexpected error message."); } } void TestBlackbox::errorInfo() { QDir::setCurrent(testDataDir + "/error-info"); QCOMPARE(runQbs(), 0); QbsRunParameters resolveParams; QbsRunParameters buildParams; buildParams.expectFailure = true; resolveParams.command = "resolve"; resolveParams.arguments = QStringList() << "project.fail1:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("error-info.qbs:24"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail2:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("error-info.qbs:36"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail3:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("error-info.qbs:51"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail4:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("error-info.qbs:66"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail5:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("helper.js:4"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail6:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("helper.js:8"), m_qbsStderr); resolveParams.arguments = QStringList() << "project.fail7:true"; QCOMPARE(runQbs(resolveParams), 0); buildParams.arguments = resolveParams.arguments; QVERIFY(runQbs(buildParams) != 0); QVERIFY2(m_qbsStderr.contains("JavaScriptCommand.sourceCode"), m_qbsStderr); QVERIFY2(m_qbsStderr.contains("error-info.qbs:57"), m_qbsStderr); } void TestBlackbox::escapedLinkerFlags() { const SettingsPtr s = settings(); const Profile buildProfile(profileName(), s.get()); const QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); if (!toolchain.contains("gcc") || targetOs() == HostOsInfo::HostOsMacos) QSKIP("escaped linker flags test only applies with gcc and GNU ld"); QDir::setCurrent(testDataDir + "/escaped-linker-flags"); QbsRunParameters params(QStringList("products.app.escapeLinkerFlags:false")); QCOMPARE(runQbs(params), 0); params.command = "resolve"; params.arguments = QStringList() << "products.app.escapeLinkerFlags:true"; QCOMPARE(runQbs(params), 0); params.command = "build"; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Encountered escaped linker flag"), m_qbsStderr.constData()); } void TestBlackbox::exportedDependencyInDisabledProduct() { QDir::setCurrent(testDataDir + "/exported-dependency-in-disabled-product"); QFETCH(QString, depCondition); QFETCH(bool, compileExpected); rmDirR(relativeBuildDir()); const QString propertyArg = "products.dep.conditionString:" + depCondition; QCOMPARE(runQbs(QStringList(propertyArg)), 0); QCOMPARE(m_qbsStdout.contains("compiling"), compileExpected); } void TestBlackbox::exportedDependencyInDisabledProduct_data() { QTest::addColumn("depCondition"); QTest::addColumn("compileExpected"); QTest::newRow("dependency enabled") << "true" << true; QTest::newRow("dependency directly disabled") << "false" << false; QTest::newRow("dependency disabled via non-present module") << "nosuchmodule.present" << false; QTest::newRow("dependency disabled via failed module") << "broken.present" << false; } void TestBlackbox::exportedPropertyInDisabledProduct() { QDir::setCurrent(testDataDir + "/exported-property-in-disabled-product"); QFETCH(QString, depCondition); QFETCH(bool, successExpected); const QString propertyArg = "products.dep.conditionString:" + depCondition; QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList(propertyArg))), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QbsRunParameters buildParams; buildParams.expectFailure = !successExpected; QCOMPARE(runQbs(buildParams) == 0, successExpected); } void TestBlackbox::exportedPropertyInDisabledProduct_data() { QTest::addColumn("depCondition"); QTest::addColumn("successExpected"); QTest::newRow("dependency enabled") << "true" << false; QTest::newRow("dependency directly disabled") << "false" << true; QTest::newRow("dependency disabled via non-present module") << "nosuchmodule.present" << true; QTest::newRow("dependency disabled via failed module") << "broken.present" << true; } void TestBlackbox::systemRunPaths() { const SettingsPtr s = settings(); const Profile buildProfile(profileName(), s.get()); switch (targetOs()) { case HostOsInfo::HostOsLinux: case HostOsInfo::HostOsMacos: case HostOsInfo::HostOsOtherUnix: break; default: QSKIP("only applies on Unix"); } const QString lddFilePath = findExecutable(QStringList() << "ldd"); if (lddFilePath.isEmpty()) QSKIP("ldd not found"); QDir::setCurrent(testDataDir + "/system-run-paths"); QFETCH(bool, setRunPaths); rmDirR(relativeBuildDir()); QbsRunParameters params; params.arguments << QString("project.setRunPaths:") + (setRunPaths ? "true" : "false"); QCOMPARE(runQbs(params), 0); QProcess ldd; ldd.start(lddFilePath, QStringList() << relativeExecutableFilePath("app")); QVERIFY2(ldd.waitForStarted(), qPrintable(ldd.errorString())); QVERIFY2(ldd.waitForFinished(), qPrintable(ldd.errorString())); QVERIFY2(ldd.exitCode() == 0, ldd.readAllStandardError().constData()); const QByteArray output = ldd.readAllStandardOutput(); const QList outputLines = output.split('\n'); QByteArray libLine; for (const auto &line : outputLines) { if (line.contains("theLib")) { libLine = line; break; } } QVERIFY2(!libLine.isEmpty(), output.constData()); QVERIFY2(setRunPaths == libLine.contains("not found"), libLine.constData()); } void TestBlackbox::systemRunPaths_data() { QTest::addColumn("setRunPaths"); QTest::newRow("do not set system run paths") << false; QTest::newRow("do set system run paths") << true; } void TestBlackbox::exportRule() { QDir::setCurrent(testDataDir + "/export-rule"); QbsRunParameters params(QStringList{"modules.blubber.enableTagger:false"}); params.expectFailure = true; QVERIFY(runQbs(params) != 0); params.command = "resolve"; params.arguments = QStringList{"modules.blubber.enableTagger:true"}; params.expectFailure = false; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Creating C++ source file"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("compiling myapp.cpp"), m_qbsStdout.constData()); } void TestBlackbox::exportToOutsideSearchPath() { QDir::setCurrent(testDataDir + "/export-to-outside-searchpath"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Dependency 'aModule' not found for product 'theProduct'."), m_qbsStderr.constData()); } void TestBlackbox::exportsPkgconfig() { QDir::setCurrent(testDataDir + "/exports-pkgconfig"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Creating TheFirstLib.pc"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("Creating TheSecondLib.pc"), m_qbsStdout.constData()); QFile sourcePcFile(HostOsInfo::isWindowsHost() ? "TheFirstLib_windows.pc" : "TheFirstLib.pc"); QString generatedPcFilePath = relativeProductBuildDir("TheFirstLib") + "/TheFirstLib.pc"; QFile generatedPcFile(generatedPcFilePath); QVERIFY2(sourcePcFile.open(QIODevice::ReadOnly), qPrintable(sourcePcFile.errorString())); QVERIFY2(generatedPcFile.open(QIODevice::ReadOnly), qPrintable(generatedPcFile.errorString())); QCOMPARE(generatedPcFile.readAll().replace("\r", ""), sourcePcFile.readAll().replace("\r", "")); sourcePcFile.close(); generatedPcFile.close(); TEXT_FILE_COMPARE(relativeProductBuildDir("TheSecondLib") + "/TheSecondLib.pc", "TheSecondLib.pc"); WAIT_FOR_NEW_TIMESTAMP(); touch("firstlib.cpp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("linking"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("Creating TheFirstLib.pc"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("Creating TheSecondLib.pc"), m_qbsStdout.constData()); } void TestBlackbox::exportsQbs() { QDir::setCurrent(testDataDir + "/exports-qbs"); // First we build exportable products and use them (as products) inside // the original project. QCOMPARE(runQbs(QStringList{"-f", "exports-qbs.qbs", "--command-echo-mode", "command-line"}), 0); QVERIFY2(m_qbsStdout.contains("somelocaldir"), m_qbsStdout.constData()); // Now we build an external product against the modules that were just installed. // We try debug and release mode; one module exists for each of them. QbsRunParameters paramsExternalBuild(QStringList{"-f", "consumer.qbs", "--command-echo-mode", "command-line", "modules.qbs.buildVariant:debug",}); paramsExternalBuild.buildDirectory = QDir::currentPath() + "/external-consumer-debug"; QCOMPARE(runQbs(paramsExternalBuild), 0); QVERIFY2(!m_qbsStdout.contains("somelocaldir"), m_qbsStdout.constData()); paramsExternalBuild.arguments = QStringList{"-f", "consumer.qbs", "modules.qbs.buildVariant:release"}; paramsExternalBuild.buildDirectory = QDir::currentPath() + "/external-consumer-release"; QCOMPARE(runQbs(paramsExternalBuild), 0); // Trying to build with an unsupported build variant must fail. paramsExternalBuild.arguments = QStringList{"-f", "consumer.qbs", "modules.qbs.buildVariant:unknown"}; paramsExternalBuild.buildDirectory = QDir::currentPath() + "/external-consumer-profile"; paramsExternalBuild.expectFailure = true; QVERIFY(runQbs(paramsExternalBuild) != 0); QVERIFY2(m_qbsStderr.contains("MyLib could not be loaded"), m_qbsStderr.constData()); // Removing the condition from the generated module leaves us with two conflicting // candidates. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{ "-f", "exports-qbs.qbs", "modules.Exporter.qbs.additionalContent:''"})), 0); QCOMPARE(runQbs(), 0); QVERIFY(runQbs(paramsExternalBuild) != 0); QVERIFY2(m_qbsStderr.contains("There is more than one equally prioritized candidate " "for module 'MyLib'."), m_qbsStderr.constData()); // Change tracking for accesses to product.exports (negative). QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{"-f", "exports-qbs.qbs"})), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Creating MyTool.qbs"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("exports-qbs.qbs"); QCOMPARE(runQbs(QStringList({"-p", "MyTool"})), 0); QVERIFY2(!m_qbsStdout.contains("Creating MyTool.qbs"), m_qbsStdout.constData()); // Rebuilding the target binary should not cause recreating the module file. WAIT_FOR_NEW_TIMESTAMP(); touch("mylib.cpp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.count("linking") >= 2, m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("Creating MyLib"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("Creating MyTool.qbs"), m_qbsStdout.constData()); // Changing a setting that influences the name of a target artifact should cause // recreating the module file. const QbsRunParameters resolveParams("resolve", QStringList{"-f", "exports-qbs.qbs", "modules.cpp.dynamicLibrarySuffix:.blubb"}); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.count("linking") >= 2, m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.count("Creating MyLib") == 2, m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("Creating MyTool.qbs"), m_qbsStdout.constData()); // Change tracking for accesses to product.exports (positive). WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("tool.qbs", "product.toolTags", "[]"); QCOMPARE(runQbs(QStringList({"-p", "MyTool"})), 0); QVERIFY2(m_qbsStdout.contains("Creating MyTool.qbs"), m_qbsStdout.constData()); } void TestBlackbox::externalLibs() { QDir::setCurrent(testDataDir + "/external-libs"); QCOMPARE(runQbs(), 0); } void TestBlackbox::fileDependencies() { QDir::setCurrent(testDataDir + "/fileDependencies"); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling narf.cpp")); QVERIFY(m_qbsStdout.contains("compiling zort.cpp")); const QString productFileName = relativeExecutableFilePath("myapp"); QVERIFY2(regularFileExists(productFileName), qPrintable(productFileName)); // Incremental build without changes. QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("compiling")); QVERIFY(!m_qbsStdout.contains("linking")); // Incremental build with changed file dependency. WAIT_FOR_NEW_TIMESTAMP(); touch("awesomelib/awesome.h"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling narf.cpp")); QVERIFY(!m_qbsStdout.contains("compiling zort.cpp")); // Incremental build with changed 2nd level file dependency. WAIT_FOR_NEW_TIMESTAMP(); touch("awesomelib/magnificent.h"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling narf.cpp")); QVERIFY(!m_qbsStdout.contains("compiling zort.cpp")); // Change the product in between to force the list of dependencies to get rescued. REPLACE_IN_FILE("fileDependencies.qbs", "//", ""); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY(!m_qbsStdout.contains("compiling narf.cpp")); QVERIFY(!m_qbsStdout.contains("compiling zort.cpp")); WAIT_FOR_NEW_TIMESTAMP(); touch("awesomelib/magnificent.h"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling narf.cpp [myapp]"), m_qbsStdout.constData()); QVERIFY(!m_qbsStdout.contains("compiling zort.cpp")); } void TestBlackbox::fileTagsFilterMerging() { QDir::setCurrent(testDataDir + "/filetagsfilter-merging"); QCOMPARE(runQbs(QStringList{"-f", "filetagsfilter-merging.qbs"}), 0); const QString installedApp = defaultInstallRoot + "/myapp/binDir/" + QFileInfo(relativeExecutableFilePath("myapp")).fileName(); QVERIFY2(QFile::exists(installedApp), qPrintable(installedApp)); const QString otherOutput = relativeProductBuildDir("myapp") + "/myapp.txt"; QVERIFY2(QFile::exists(otherOutput), qPrintable(otherOutput)); } void TestBlackbox::installedTransformerOutput() { QDir::setCurrent(testDataDir + "/installed-transformer-output"); QCOMPARE(runQbs(), 0); const QString installedFilePath = defaultInstallRoot + "/textfiles/HelloWorld.txt"; QVERIFY2(QFile::exists(installedFilePath), qPrintable(installedFilePath)); } void TestBlackbox::installLocations_data() { QTest::addColumn("binDir"); QTest::addColumn("dllDir"); QTest::addColumn("libDir"); QTest::newRow("explicit values") << QString("bindir") << QString("dlldir") << QString("libdir"); QTest::newRow("default values") << QString() << QString() << QString(); } void TestBlackbox::installLocations() { QDir::setCurrent(testDataDir + "/install-locations"); QFETCH(QString, binDir); QFETCH(QString, dllDir); QFETCH(QString, libDir); QbsRunParameters params("resolve"); if (!binDir.isEmpty()) params.arguments.push_back("products.theapp.installDir:" + binDir); if (!dllDir.isEmpty()) params.arguments.push_back("products.thelib.installDir:" + dllDir); if (!libDir.isEmpty()) params.arguments.push_back("products.thelib.importLibInstallDir:" + libDir); QCOMPARE(runQbs(params), 0); const bool isWindows = m_qbsStdout.contains("is windows"); const bool isMac = m_qbsStdout.contains("is mac"); const bool isUnix = m_qbsStdout.contains("is unix"); QVERIFY(isWindows || isMac || isUnix); QCOMPARE(runQbs(QbsRunParameters(QStringList("--clean-install-root"))), 0); const QString dllFileName = isWindows ? "thelib.dll" : isMac ? "thelib" : "libthelib.so"; const QString appFileName = isWindows ? "theapp.exe" : "theapp"; if (binDir.isEmpty()) binDir = isMac ? "/Applications" : "/bin"; if (dllDir.isEmpty()) dllDir = isMac ? "/Library/Frameworks" : isWindows ? "/bin" : "/lib"; if (libDir.isEmpty()) libDir = "/lib"; if (isMac) { binDir += "/theapp.app/Contents/MacOS"; dllDir += "/thelib.framework"; } const QString installRoot = QDir::currentPath() + "/default/install-root"; const QString installPrefix = isWindows ? QString() : "/usr/local"; const QString fullInstallPrefix = installRoot + '/' + installPrefix + '/'; const QString appFilePath = fullInstallPrefix + binDir + '/' + appFileName; QVERIFY2(QFile::exists(appFilePath), qPrintable(appFilePath)); const QString dllFilePath = fullInstallPrefix + dllDir + '/' + dllFileName; QVERIFY2(QFile::exists(dllFilePath), qPrintable(dllFilePath)); if (isWindows) { const QString libFilePath = fullInstallPrefix + libDir + "/thelib.lib"; QVERIFY2(QFile::exists(libFilePath), qPrintable(libFilePath)); } } void TestBlackbox::inputsFromDependencies() { QDir::setCurrent(testDataDir + "/inputs-from-dependencies"); QCOMPARE(runQbs(), 0); const QList output = m_qbsStdout.trimmed().split('\n'); QVERIFY2(output.contains((QDir::currentPath() + "/file1.txt").toUtf8()), m_qbsStdout.constData()); QVERIFY2(output.contains((QDir::currentPath() + "/file2.txt").toUtf8()), m_qbsStdout.constData()); QVERIFY2(output.contains((QDir::currentPath() + "/file3.txt").toUtf8()), m_qbsStdout.constData()); QVERIFY2(!output.contains((QDir::currentPath() + "/file4.txt").toUtf8()), m_qbsStdout.constData()); } void TestBlackbox::installPackage() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsWindows) QSKIP("Beware of the msys tar"); QString binary = findArchiver("tar"); if (binary.isEmpty()) QSKIP("tar not found"); MacosTarHealer tarHealer; QDir::setCurrent(testDataDir + "/installpackage"); QCOMPARE(runQbs(), 0); const QString tarFilePath = relativeProductBuildDir("tar-package") + "/tar-package.tar.gz"; QVERIFY2(regularFileExists(tarFilePath), qPrintable(tarFilePath)); QProcess tarList; tarList.start(binary, QStringList() << "tf" << tarFilePath); QVERIFY2(tarList.waitForStarted(), qPrintable(tarList.errorString())); QVERIFY2(tarList.waitForFinished(), qPrintable(tarList.errorString())); const QList outputLines = tarList.readAllStandardOutput().split('\n'); QList cleanOutputLines; for (const QByteArray &line : outputLines) { const QByteArray trimmedLine = line.trimmed(); if (!trimmedLine.isEmpty()) cleanOutputLines.push_back(trimmedLine); } QCOMPARE(cleanOutputLines.size(), 3); for (const QByteArray &line : qAsConst(cleanOutputLines)) { QVERIFY2(line.contains("public_tool") || line.contains("mylib") || line.contains("lib.h"), line.constData()); } } void TestBlackbox::installRootFromProjectFile() { QDir::setCurrent(testDataDir + "/install-root-from-project-file"); const QString installRoot = QDir::currentPath() + '/' + relativeBuildDir() + "/my-install-root/"; QCOMPARE(runQbs(QbsRunParameters(QStringList("products.p.installRoot:" + installRoot))), 0); const QString installedFile = installRoot + "/install-prefix/install-dir/file.txt"; QVERIFY2(QFile::exists(installedFile), qPrintable(installedFile)); } void TestBlackbox::installable() { QDir::setCurrent(testDataDir + "/installable"); QCOMPARE(runQbs(), 0); QFile installList(relativeProductBuildDir("install-list") + "/installed-files.txt"); QVERIFY2(installList.open(QIODevice::ReadOnly), qPrintable(installList.errorString())); QCOMPARE(installList.readAll().count('\n'), 2); } void TestBlackbox::installableAsAuxiliaryInput() { QDir::setCurrent(testDataDir + "/installable-as-auxiliary-input"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("f-impl"), m_qbsStdout.constData()); } void TestBlackbox::installTree() { QDir::setCurrent(testDataDir + "/install-tree"); QbsRunParameters params; params.command = "install"; QCOMPARE(runQbs(params), 0); const QString installRoot = relativeBuildDir() + "/install-root/"; QVERIFY(QFile::exists(installRoot + "content/foo.txt")); QVERIFY(QFile::exists(installRoot + "content/subdir1/bar.txt")); QVERIFY(QFile::exists(installRoot + "content/subdir2/baz.txt")); } void TestBlackbox::invalidCommandProperty_data() { QTest::addColumn("errorType"); QTest::newRow("assigning QObject") << QString("qobject"); QTest::newRow("assigning input artifact") << QString("input"); QTest::newRow("assigning other artifact") << QString("artifact"); } void TestBlackbox::invalidCommandProperty() { QDir::setCurrent(testDataDir + "/invalid-command-property"); QFETCH(QString, errorType); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.p.errorType:" + errorType))), 0); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("unsuitable"), m_qbsStderr.constData()); } void TestBlackbox::invalidLibraryNames() { QDir::setCurrent(testDataDir + "/invalid-library-names"); QFETCH(QString, index); QFETCH(bool, success); QFETCH(QStringList, diagnostics); QbsRunParameters params(QStringList("project.valueIndex:" + index)); params.expectFailure = !success; QCOMPARE(runQbs(params) == 0, success); for (const QString &diag : qAsConst(diagnostics)) QVERIFY2(m_qbsStderr.contains(diag.toLocal8Bit()), m_qbsStderr.constData()); } void TestBlackbox::invalidLibraryNames_data() { QTest::addColumn("index"); QTest::addColumn("success"); QTest::addColumn("diagnostics"); QTest::newRow("null") << "0" << false << QStringList("is null"); QTest::newRow("undefined") << "1" << false << QStringList("is undefined"); QTest::newRow("number") << "2" << false << QStringList("does not have string type"); QTest::newRow("array") << "3" << false << QStringList("does not have string type"); QTest::newRow("empty string") << "4" << true << (QStringList() << "WARNING: Removing empty string from value of property " "'cpp.dynamicLibraries' in product 'invalid-library-names'." << "WARNING: Removing empty string from value of property " "'cpp.staticLibraries' in product 'invalid-library-names'."); } void TestBlackbox::invalidExtensionInstantiation() { rmDirR(relativeBuildDir()); QDir::setCurrent(testDataDir + "/invalid-extension-instantiation"); QbsRunParameters params; params.expectFailure = true; params.arguments << (QString("products.theProduct.extension:") + QTest::currentDataTag()); QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("invalid-extension-instantiation.qbs:17") && m_qbsStderr.contains('\'' + QByteArray(QTest::currentDataTag()) + "' cannot be instantiated"), m_qbsStderr.constData()); } void TestBlackbox::invalidExtensionInstantiation_data() { QTest::addColumn("dummy"); QTest::newRow("Environment"); QTest::newRow("File"); QTest::newRow("FileInfo"); QTest::newRow("Utilities"); } void TestBlackbox::invalidInstallDir() { QDir::setCurrent(testDataDir + "/invalid-install-dir"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("outside of install root"), m_qbsStderr.constData()); } void TestBlackbox::cli() { int status; findCli(&status); QCOMPARE(status, 0); const SettingsPtr s = settings(); Profile p("qbs_autotests-cli", s.get()); const QStringList toolchain = p.value("qbs.toolchain").toStringList(); if (!p.exists() || !(toolchain.contains("dotnet") || toolchain.contains("mono"))) QSKIP("No suitable Common Language Infrastructure test profile"); QDir::setCurrent(testDataDir + "/cli"); QbsRunParameters params(QStringList() << "-f" << "dotnettest.qbs"); params.profile = p.name(); status = runQbs(params); if (p.value("cli.toolchainInstallPath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("toolchainInstallPath")) QSKIP("cli.toolchainInstallPath not set and automatic detection failed"); QCOMPARE(status, 0); rmDirR(relativeBuildDir()); QbsRunParameters params2(QStringList() << "-f" << "fshello.qbs"); params2.profile = p.name(); QCOMPARE(runQbs(params2), 0); rmDirR(relativeBuildDir()); } void TestBlackbox::combinedSources() { QDir::setCurrent(testDataDir + "/combined-sources"); QbsRunParameters params(QStringList("modules.cpp.combineCxxSources:false")); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(m_qbsStdout.contains("compiling combinable.cpp")); QVERIFY(m_qbsStdout.contains("compiling uncombinable.cpp")); QVERIFY(!m_qbsStdout.contains("compiling amalgamated_theapp.cpp")); params.arguments = QStringList("modules.cpp.combineCxxSources:true"); params.command = "resolve"; QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("combinable.cpp"); touch("main.cpp"); touch("uncombinable.cpp"); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling combinable.cpp")); QVERIFY(m_qbsStdout.contains("compiling uncombinable.cpp")); QVERIFY(m_qbsStdout.contains("compiling amalgamated_theapp.cpp")); } void TestBlackbox::commandFile() { QDir::setCurrent(testDataDir + "/command-file"); QbsRunParameters params(QStringList() << "-p" << "theLib"); QCOMPARE(runQbs(params), 0); params.arguments = QStringList() << "-p" << "theApp"; QCOMPARE(runQbs(params), 0); } void TestBlackbox::compilerDefinesByLanguage() { QDir::setCurrent(testDataDir + "/compilerDefinesByLanguage"); QbsRunParameters params(QStringList { "-f", "compilerDefinesByLanguage.qbs" }); QCOMPARE(runQbs(params), 0); } void TestBlackbox::jsExtensionsFile() { QDir::setCurrent(testDataDir + "/jsextensions-file"); QFile fileToMove("tomove.txt"); QVERIFY2(fileToMove.open(QIODevice::WriteOnly), qPrintable(fileToMove.errorString())); fileToMove.close(); fileToMove.setPermissions(fileToMove.permissions() & ~(QFile::ReadUser | QFile::ReadOwner | QFile::ReadGroup | QFile::ReadOther)); QbsRunParameters params(QStringList() << "-f" << "file.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(!QFileInfo("original.txt").exists()); QFile copy("copy.txt"); QVERIFY(copy.exists()); QVERIFY(copy.open(QIODevice::ReadOnly)); const QList lines = copy.readAll().trimmed().split('\n'); QCOMPARE(lines.size(), 2); QCOMPARE(lines.at(0).trimmed().constData(), "false"); QCOMPARE(lines.at(1).trimmed().constData(), "true"); } void TestBlackbox::jsExtensionsFileInfo() { QDir::setCurrent(testDataDir + "/jsextensions-fileinfo"); QbsRunParameters params(QStringList() << "-f" << "fileinfo.qbs"); QCOMPARE(runQbs(params), 0); QFile output("output.txt"); QVERIFY(output.exists()); QVERIFY(output.open(QIODevice::ReadOnly)); const QList lines = output.readAll().trimmed().split('\n'); QCOMPARE(lines.size(), 26); int i = 0; QCOMPARE(lines.at(i++).trimmed().constData(), "blubb"); QCOMPARE(lines.at(i++).trimmed().constData(), qUtf8Printable( QFileInfo(QDir::currentPath()).canonicalFilePath())); QCOMPARE(lines.at(i++).trimmed().constData(), "/usr/bin"); QCOMPARE(lines.at(i++).trimmed().constData(), "blubb.tar"); QCOMPARE(lines.at(i++).trimmed().constData(), "blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "/tmp/blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "c:/tmp/blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "true"); QCOMPARE(lines.at(i++).trimmed().constData(), HostOsInfo::isWindowsHost() ? "true" : "false"); QCOMPARE(lines.at(i++).trimmed().constData(), "false"); QCOMPARE(lines.at(i++).trimmed().constData(), "true"); QCOMPARE(lines.at(i++).trimmed().constData(), "false"); QCOMPARE(lines.at(i++).trimmed().constData(), "false"); QCOMPARE(lines.at(i++).trimmed().constData(), "/tmp/blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "/tmp/blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "/tmp"); QCOMPARE(lines.at(i++).trimmed().constData(), "/tmp"); QCOMPARE(lines.at(i++).trimmed().constData(), "/"); QCOMPARE(lines.at(i++).trimmed().constData(), HostOsInfo::isWindowsHost() ? "d:/" : "d:"); QCOMPARE(lines.at(i++).trimmed().constData(), "d:"); QCOMPARE(lines.at(i++).trimmed().constData(), "d:/"); QCOMPARE(lines.at(i++).trimmed().constData(), "blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "tmp/blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "../blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "\\tmp\\blubb.tar.gz"); QCOMPARE(lines.at(i++).trimmed().constData(), "c:\\tmp\\blubb.tar.gz"); } void TestBlackbox::jsExtensionsProcess() { QDir::setCurrent(testDataDir + "/jsextensions-process"); QbsRunParameters params(QStringList() << "-f" << "process.qbs"); QCOMPARE(runQbs(params), 0); QFile output("output.txt"); QVERIFY(output.exists()); QVERIFY(output.open(QIODevice::ReadOnly)); const QList lines = output.readAll().trimmed().split('\n'); QCOMPARE(lines.size(), 9); QCOMPARE(lines.at(0).trimmed().constData(), "0"); QVERIFY(lines.at(1).startsWith("qbs ")); QCOMPARE(lines.at(2).trimmed().constData(), "true"); QCOMPARE(lines.at(3).trimmed().constData(), "true"); QCOMPARE(lines.at(4).trimmed().constData(), "0"); QVERIFY(lines.at(5).startsWith("qbs ")); QCOMPARE(lines.at(6).trimmed().constData(), "false"); QCOMPARE(lines.at(7).trimmed().constData(), "should be"); QCOMPARE(lines.at(8).trimmed().constData(), "123"); } void TestBlackbox::jsExtensionsPropertyList() { if (!HostOsInfo::isMacosHost()) QSKIP("temporarily only applies on macOS"); QDir::setCurrent(testDataDir + "/jsextensions-propertylist"); QbsRunParameters params(QStringList() << "-nf" << "propertylist.qbs"); QCOMPARE(runQbs(params), 0); QFile file1("test.json"); QVERIFY(file1.exists()); QVERIFY(file1.open(QIODevice::ReadOnly)); QFile file2("test.xml"); QVERIFY(file2.exists()); QVERIFY(file2.open(QIODevice::ReadOnly)); QFile file3("test2.json"); QVERIFY(file3.exists()); QVERIFY(file3.open(QIODevice::ReadOnly)); QByteArray file1Contents = file1.readAll(); QCOMPARE(file3.readAll(), file1Contents); //QCOMPARE(file1Contents, file2.readAll()); // keys don't have guaranteed order QJsonParseError err1, err2; QCOMPARE(QJsonDocument::fromJson(file1Contents, &err1), QJsonDocument::fromJson(file2.readAll(), &err2)); QVERIFY(err1.error == QJsonParseError::NoError && err2.error == QJsonParseError::NoError); QFile file4("test.openstep.plist"); QVERIFY(file4.exists()); QFile file5("test3.json"); QVERIFY(file5.exists()); QVERIFY(file5.open(QIODevice::ReadOnly)); QVERIFY(file1Contents != file5.readAll()); } void TestBlackbox::jsExtensionsTemporaryDir() { QDir::setCurrent(testDataDir + "/jsextensions-temporarydir"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); } void TestBlackbox::jsExtensionsTextFile() { QDir::setCurrent(testDataDir + "/jsextensions-textfile"); QbsRunParameters params(QStringList() << "-f" << "textfile.qbs"); QCOMPARE(runQbs(params), 0); QFile file1("file1.txt"); QVERIFY(file1.exists()); QVERIFY(file1.open(QIODevice::ReadOnly)); QCOMPARE(file1.size(), qint64(0)); QFile file2("file2.txt"); QVERIFY(file2.exists()); QVERIFY(file2.open(QIODevice::ReadOnly)); const QList lines = file2.readAll().trimmed().split('\n'); QCOMPARE(lines.size(), 6); QCOMPARE(lines.at(0).trimmed().constData(), "false"); QCOMPARE(lines.at(1).trimmed().constData(), "First line."); QCOMPARE(lines.at(2).trimmed().constData(), "Second line."); QCOMPARE(lines.at(3).trimmed().constData(), "Third line."); QCOMPARE(lines.at(4).trimmed().constData(), qPrintable(QDir::currentPath() + "/file1.txt")); QCOMPARE(lines.at(5).trimmed().constData(), "true"); } void TestBlackbox::jsExtensionsBinaryFile() { QDir::setCurrent(testDataDir + "/jsextensions-binaryfile"); QbsRunParameters params(QStringList() << "-f" << "binaryfile.qbs"); QCOMPARE(runQbs(params), 0); QFile source("source.dat"); QVERIFY(source.exists()); QVERIFY(source.open(QIODevice::ReadOnly)); QCOMPARE(source.size(), qint64(0)); QFile destination("destination.dat"); QVERIFY(destination.exists()); QVERIFY(destination.open(QIODevice::ReadOnly)); const QByteArray data = destination.readAll(); QCOMPARE(data.size(), 8); QCOMPARE(data.at(0), char(0x00)); QCOMPARE(data.at(1), char(0x01)); QCOMPARE(data.at(2), char(0x02)); QCOMPARE(data.at(3), char(0x03)); QCOMPARE(data.at(4), char(0x04)); QCOMPARE(data.at(5), char(0x05)); QCOMPARE(data.at(6), char(0x06)); QCOMPARE(data.at(7), char(0xFF)); } void TestBlackbox::ld() { QDir::setCurrent(testDataDir + "/ld"); QCOMPARE(runQbs(), 0); } void TestBlackbox::symbolLinkMode() { if (!HostOsInfo::isAnyUnixHost()) QSKIP("only applies on Unix"); QDir::setCurrent(testDataDir + "/symbolLinkMode"); QbsRunParameters params; params.command = "run"; const QStringList commonArgs{"-p", "driver", "--setup-run-env-config", "ignore-lib-dependencies", "qbs.installPrefix:''"}; rmDirR(relativeBuildDir()); params.arguments = QStringList() << commonArgs << "project.shouldInstallLibrary:true"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("somefunction existed and it returned 42"), m_qbsStdout.constData()); rmDirR(relativeBuildDir()); params.arguments = QStringList() << commonArgs << "project.shouldInstallLibrary:false"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("somefunction did not exist"), m_qbsStdout.constData()); rmDirR(relativeBuildDir()); params.arguments = QStringList() << commonArgs << "project.lazy:false"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("Lib was loaded!\nmeow\n"), m_qbsStdout.constData()); if (HostOsInfo::isMacosHost()) { rmDirR(relativeBuildDir()); params.arguments = QStringList() << commonArgs << "project.lazy:true"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("meow\nLib was loaded!\n"), m_qbsStdout.constData()); } } void TestBlackbox::linkerMode() { if (!HostOsInfo::isAnyUnixHost()) QSKIP("only applies on Unix"); QDir::setCurrent(testDataDir + "/linkerMode"); QCOMPARE(runQbs(QbsRunParameters(QStringList("qbs.installPrefix:''"))), 0); auto testCondition = [&](const QString &lang, const std::function &condition) { if ((lang == "Objective-C" || lang == "Objective-C++") && HostOsInfo::hostOs() != HostOsInfo::HostOsMacos) return; const QString binary = defaultInstallRoot + "/LinkedProduct-" + lang; QProcess deptool; if (HostOsInfo::hostOs() == HostOsInfo::HostOsMacos) deptool.start("otool", QStringList() << "-L" << binary); else deptool.start("readelf", QStringList() << "-a" << binary); QVERIFY(deptool.waitForStarted()); QVERIFY(deptool.waitForFinished()); QByteArray deptoolOutput = deptool.readAllStandardOutput(); if (HostOsInfo::hostOs() != HostOsInfo::HostOsMacos) { QList lines = deptoolOutput.split('\n'); int sz = lines.size(); for (int i = 0; i < sz; ++i) { if (!lines.at(i).contains("NEEDED")) { lines.removeAt(i--); sz--; } } deptoolOutput = lines.join('\n'); } QCOMPARE(deptool.exitCode(), 0); QVERIFY2(condition(deptoolOutput), deptoolOutput.constData()); }; const QStringList nocpplangs = QStringList() << "Assembly" << "C" << "Objective-C"; for (const QString &lang : nocpplangs) testCondition(lang, [](const QByteArray &lddOutput) { return !lddOutput.contains("c++"); }); const QStringList cpplangs = QStringList() << "C++" << "Objective-C++"; for (const QString &lang : cpplangs) testCondition(lang, [](const QByteArray &lddOutput) { return lddOutput.contains("c++"); }); const QStringList objclangs = QStringList() << "Objective-C" << "Objective-C++"; for (const QString &lang : objclangs) testCondition(lang, [](const QByteArray &lddOutput) { return lddOutput.contains("objc"); }); } void TestBlackbox::linkerVariant_data() { QTest::addColumn("theType"); QTest::newRow("default") << QString(); QTest::newRow("bfd") << QString("bfd"); QTest::newRow("gold") << QString("gold"); } void TestBlackbox::linkerVariant() { QDir::setCurrent(testDataDir + "/linker-variant"); QFETCH(QString, theType); QStringList resolveArgs("--force-probe-execution"); if (!theType.isEmpty()) resolveArgs << ("products.p.linkerVariant:" + theType); QCOMPARE(runQbs(QbsRunParameters("resolve", resolveArgs)), 0); const bool isGcc = m_qbsStdout.contains("is GCC: true"); const bool isNotGcc = m_qbsStdout.contains("is GCC: false"); QVERIFY2(isGcc != isNotGcc, m_qbsStdout.constData()); QbsRunParameters buildParams("build", QStringList{"--command-echo-mode", "command-line"}); buildParams.expectFailure = true; runQbs(buildParams); if (isGcc && !theType.isEmpty()) QCOMPARE(m_qbsStdout.count("-fuse-ld=" + theType.toLocal8Bit()), 1); else QVERIFY2(!m_qbsStdout.contains("-fuse-ld"), m_qbsStdout.constData()); } void TestBlackbox::lexyacc() { if (!lexYaccExist()) QSKIP("lex or yacc not present"); QDir::setCurrent(testDataDir + "/lexyacc/one-grammar"); QCOMPARE(runQbs(), 0); const QString parserBinary = relativeExecutableFilePath("one-grammar"); QProcess p; p.start(parserBinary); QVERIFY2(p.waitForStarted(), qPrintable(p.errorString())); p.write("a && b || c && !d"); p.closeWriteChannel(); QVERIFY2(p.waitForFinished(), qPrintable(p.errorString())); QVERIFY2(p.exitCode() == 0, p.readAllStandardError().constData()); const QByteArray parserOutput = p.readAllStandardOutput(); QVERIFY2(parserOutput.contains("OR AND a b AND c NOT d"), parserOutput.constData()); QDir::setCurrent(testDataDir + "/lexyacc/two-grammars"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); params.expectFailure = false; params.command = "resolve"; params.arguments << (QStringList() << "modules.lex_yacc.uniqueSymbolPrefix:true"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStderr.contains("whatever"), m_qbsStderr.constData()); params.arguments << "modules.lex_yacc.enableCompilerWarnings:true"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); const QByteArray outputToCheck = m_qbsStdout + m_qbsStderr; QVERIFY2(outputToCheck.contains("whatever"), outputToCheck.constData()); } void TestBlackbox::lexyaccOutputs() { if (!lexYaccExist()) QSKIP("lex or yacc not present"); QFETCH(QString, lexOutputFilePath); QFETCH(QString, yaccOutputFilePath); QbsRunParameters params; if (!lexOutputFilePath.isEmpty()) params.arguments << "modules.lex_yacc.lexOutputFilePath:" + lexOutputFilePath; if (!yaccOutputFilePath.isEmpty()) params.arguments << "modules.lex_yacc.yaccOutputFilePath:" + yaccOutputFilePath; #define VERIFY_COMPILATION(file) \ if (!file.isEmpty()) { \ QByteArray expected = "compiling " + file.toUtf8(); \ if (!m_qbsStdout.contains(expected)) { \ qDebug() << "Expected output:" << expected; \ qDebug() << "Actual output:" << m_qbsStdout; \ QFAIL("Expected stdout content missing."); \ } \ } const auto version = bisonVersion(); if (version >= qbs::Version(2, 6)) { // prefix only supported starting from bison 2.6 QVERIFY(QDir::setCurrent(testDataDir + "/lexyacc/lex_prefix")); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); VERIFY_COMPILATION(yaccOutputFilePath); } QVERIFY(QDir::setCurrent(testDataDir + "/lexyacc/lex_outfile")); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); VERIFY_COMPILATION(yaccOutputFilePath); if (version >= qbs::Version(2, 4)) { // output syntax was changed in bison 2.4 QVERIFY(QDir::setCurrent(testDataDir + "/lexyacc/yacc_output")); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); VERIFY_COMPILATION(lexOutputFilePath); } #undef VERIFY_COMPILATION } void TestBlackbox::lexyaccOutputs_data() { QTest::addColumn("lexOutputFilePath"); QTest::addColumn("yaccOutputFilePath"); QTest::newRow("none") << QString() << QString(); QTest::newRow("lexOutputFilePath") << QString{"lex_luthor.cpp"} << QString(); QTest::newRow("yaccOutputFilePath") << QString() << QString{"shaven_yak.cpp"}; } void TestBlackbox::linkerScripts() { const SettingsPtr s = settings(); Profile buildProfile(profileName(), s.get()); QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); if (!toolchain.contains("gcc") || targetOs() != HostOsInfo::HostOsLinux) QSKIP("linker script test only applies to Linux "); QbsRunParameters runParams(QStringList() // << "--log-level" << "debug" << ("qbs.installRoot:" + QDir::currentPath())); const QString sourceDir = QDir::cleanPath(testDataDir + "/linkerscripts"); runParams.buildDirectory = sourceDir + "/build"; runParams.workingDir = sourceDir; QCOMPARE(runQbs(runParams), 0); const QString output = QString::fromLocal8Bit(m_qbsStderr); QRegExp pattern(".*---(.*)---.*"); QVERIFY2(pattern.exactMatch(output), qPrintable(output)); QCOMPARE(pattern.captureCount(), 1); const QString nmPath = pattern.capturedTexts().at(1); if (!QFile::exists(nmPath)) QSKIP("Cannot check for symbol presence: No nm found."); const auto verifySymbols = [nmPath](const QByteArrayList& symbols) -> bool { QProcess nm; nm.start(nmPath, QStringList(QDir::currentPath() + "/liblinkerscripts.so")); if (!nm.waitForStarted()) { qDebug() << "Wait for process started failed."; return false; } if (!nm.waitForFinished()) { qDebug() << "Wait for process finished failed."; return false; } if (nm.exitCode() != 0) { qDebug() << "nm returned exit code " << nm.exitCode(); return false; } const QByteArray nmOutput = nm.readAllStandardOutput(); for (const QByteArray& symbol : symbols) { if (!nmOutput.contains(symbol)) { qDebug() << "Expected symbol" << symbol << "not found in" << nmOutput.constData(); return false; } } return true; }; QVERIFY(verifySymbols({"TEST_SYMBOL1", "TEST_SYMBOL2", "TEST_SYMBOL_FROM_INCLUDE", "TEST_SYMBOL_FROM_DIRECTORY", "TEST_SYMBOL_FROM_RECURSIVE"})); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(sourceDir + "/linkerscript_to_include", "TEST_SYMBOL_FROM_INCLUDE = 1;", "TEST_SYMBOL_FROM_INCLUDE_MODIFIED = 1;\n"); QCOMPARE(runQbs(runParams), 0); QVERIFY2(m_qbsStdout.contains("linking liblinkerscripts.so"), "No linking after modifying included file"); QVERIFY(verifySymbols({"TEST_SYMBOL1", "TEST_SYMBOL2", "TEST_SYMBOL_FROM_INCLUDE_MODIFIED", "TEST_SYMBOL_FROM_DIRECTORY", "TEST_SYMBOL_FROM_RECURSIVE"})); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(sourceDir + "/scripts/linkerscript_in_directory", "TEST_SYMBOL_FROM_DIRECTORY = 1;\n", "TEST_SYMBOL_FROM_DIRECTORY_MODIFIED = 1;\n"); QCOMPARE(runQbs(runParams), 0); QVERIFY2(m_qbsStdout.contains("linking liblinkerscripts.so"), "No linking after modifying file in directory"); QVERIFY(verifySymbols({"TEST_SYMBOL1", "TEST_SYMBOL2", "TEST_SYMBOL_FROM_INCLUDE_MODIFIED", "TEST_SYMBOL_FROM_DIRECTORY_MODIFIED", "TEST_SYMBOL_FROM_RECURSIVE"})); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(sourceDir + "/linkerscript_recursive", "TEST_SYMBOL_FROM_RECURSIVE = 1;\n", "TEST_SYMBOL_FROM_RECURSIVE_MODIFIED = 1;\n"); QCOMPARE(runQbs(runParams), 0); QVERIFY2(m_qbsStdout.contains("linking liblinkerscripts.so"), "No linking after modifying recursive file"); QVERIFY(verifySymbols({"TEST_SYMBOL1", "TEST_SYMBOL2", "TEST_SYMBOL_FROM_INCLUDE_MODIFIED", "TEST_SYMBOL_FROM_DIRECTORY_MODIFIED", "TEST_SYMBOL_FROM_RECURSIVE_MODIFIED"})); } void TestBlackbox::listProducts() { QDir::setCurrent(testDataDir + "/list-products"); QCOMPARE(runQbs(QbsRunParameters("list-products")), 0); m_qbsStdout.replace("\r\n", "\n"); QVERIFY2(m_qbsStdout.contains( "a\n" "b {\"architecture\":\"mips\",\"buildVariant\":\"debug\"}\n" "b {\"architecture\":\"mips\",\"buildVariant\":\"release\"}\n" "b {\"architecture\":\"vax\",\"buildVariant\":\"debug\"}\n" "b {\"architecture\":\"vax\",\"buildVariant\":\"release\"}\n" "c\n"), m_qbsStdout.constData()); } void TestBlackbox::listPropertiesWithOuter() { QDir::setCurrent(testDataDir + "/list-properties-with-outer"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("listProp: [\"product\",\"higher\",\"group\"]"), m_qbsStdout.constData()); } void TestBlackbox::listPropertyOrder() { QDir::setCurrent(testDataDir + "/list-property-order"); const QbsRunParameters params(QStringList() << "-qq"); QCOMPARE(runQbs(params), 0); const QByteArray firstOutput = m_qbsStderr; for (int i = 0; i < 25; ++i) { rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); if (m_qbsStderr != firstOutput) break; } QCOMPARE(m_qbsStderr.constData(), firstOutput.constData()); } void TestBlackbox::require() { QDir::setCurrent(testDataDir + "/require"); QCOMPARE(runQbs(), 0); } void TestBlackbox::requireDeprecated() { QDir::setCurrent(testDataDir + "/require-deprecated"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStderr.contains("loadExtension() function is deprecated"), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("loadFile() function is deprecated"), m_qbsStderr.constData()); } void TestBlackbox::rescueTransformerData() { QDir::setCurrent(testDataDir + "/rescue-transformer-data"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp") && m_qbsStdout.contains("m.p: undefined"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp") && !m_qbsStdout.contains("m.p: "), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.m.p:true"))), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp") && m_qbsStdout.contains("m.p: true"), m_qbsStdout.constData()); } void TestBlackbox::multipleChanges() { QDir::setCurrent(testDataDir + "/multiple-changes"); QCOMPARE(runQbs(), 0); QFile newFile("test.blubb"); QVERIFY(newFile.open(QIODevice::WriteOnly)); newFile.close(); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList() << "project.prop:true")), 0); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("prop: true")); } void TestBlackbox::multipleConfigurations() { QDir::setCurrent(testDataDir + "/multiple-configurations"); QbsRunParameters params(QStringList{"config:x", "config:y", "config:z"}); params.profile.clear(); struct DefaultProfileSwitcher { DefaultProfileSwitcher() { const SettingsPtr s = settings(); oldDefaultProfile = s->defaultProfile(); s->setValue("defaultProfile", profileName()); s->sync(); } ~DefaultProfileSwitcher() { const SettingsPtr s = settings(); s->setValue("defaultProfile", oldDefaultProfile); s->sync(); } QVariant oldDefaultProfile; }; DefaultProfileSwitcher dps; QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStdout.count("compiling lib.cpp"), 3); QCOMPARE(m_qbsStdout.count("compiling file.cpp"), 3); QCOMPARE(m_qbsStdout.count("compiling main.cpp"), 3); } void TestBlackbox::multiplexedTool() { QDir::setCurrent(testDataDir + "/multiplexed-tool"); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("creating tool.out"), 4); } void TestBlackbox::nestedGroups() { QDir::setCurrent(testDataDir + "/nested-groups"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(relativeExecutableFilePath("nested-groups"))); } void TestBlackbox::nestedProperties() { QDir::setCurrent(testDataDir + "/nested-properties"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("value in higherlevel"), m_qbsStdout.constData()); } void TestBlackbox::newOutputArtifact() { QDir::setCurrent(testDataDir + "/new-output-artifact"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(relativeBuildDir() + "/install-root/output_98.out")); const QString the100thArtifact = relativeBuildDir() + "/install-root/output_99.out"; QVERIFY(!regularFileExists(the100thArtifact)); QbsRunParameters params("resolve", QStringList() << "products.theProduct.artifactCount:100"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(the100thArtifact)); } void TestBlackbox::noExportedSymbols_data() { QTest::addColumn("link"); QTest::addColumn("dryRun"); QTest::newRow("link") << true << false; QTest::newRow("link (dry run)") << true << true; QTest::newRow("do not link") << false << false; } void TestBlackbox::noExportedSymbols() { QDir::setCurrent(testDataDir + "/no-exported-symbols"); QFETCH(bool, link); QFETCH(bool, dryRun); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList{"--force-probe-execution", QString("products.the_app.link:") + (link ? "true" : "false")})), 0); const bool isMsvc = m_qbsStdout.contains("compiler is MSVC"); const bool isNotMsvc = m_qbsStdout.contains("compiler is not MSVC"); QVERIFY2(isMsvc || isNotMsvc, m_qbsStdout.constData()); if (isNotMsvc) QSKIP("Test applies with MSVC only"); QbsRunParameters buildParams; if (dryRun) buildParams.arguments << "--dry-run"; buildParams.expectFailure = link && !dryRun; QCOMPARE(runQbs(buildParams) == 0, !buildParams.expectFailure); QVERIFY2(m_qbsStderr.contains("This typically happens when a DLL does not export " "any symbols.") == buildParams.expectFailure, m_qbsStderr.constData()); } void TestBlackbox::noProfile() { QDir::setCurrent(testDataDir + "/no-profile"); QbsRunParameters params; params.profile = "none"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("profile: none"), m_qbsStdout.constData()); } void TestBlackbox::noSuchProfile() { QDir::setCurrent(testDataDir + "/no-such-profile"); QbsRunParameters params(QStringList("products.theProduct.p:1")); params.profile = "jibbetnich"; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Profile 'jibbetnich' does not exist"), m_qbsStderr.constData()); } void TestBlackbox::nonBrokenFilesInBrokenProduct() { QDir::setCurrent(testDataDir + "/non-broken-files-in-broken-product"); QbsRunParameters params(QStringList() << "-k"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStdout.contains("fine.cpp")); QVERIFY(runQbs(params) != 0); QVERIFY(!m_qbsStdout.contains("fine.cpp")); // The non-broken file must not be recompiled. } void TestBlackbox::nonDefaultProduct() { QDir::setCurrent(testDataDir + "/non-default-product"); const QString defaultAppExe = relativeExecutableFilePath("default app"); const QString nonDefaultAppExe = relativeExecutableFilePath("non-default app"); QCOMPARE(runQbs(), 0); QVERIFY2(QFile::exists(defaultAppExe), qPrintable(defaultAppExe)); QVERIFY2(!QFile::exists(nonDefaultAppExe), qPrintable(nonDefaultAppExe)); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "--all-products")), 0); QVERIFY2(QFile::exists(nonDefaultAppExe), qPrintable(nonDefaultAppExe)); } void TestBlackbox::notAlwaysUpdated() { QDir::setCurrent(testDataDir + "/not-always-updated"); QCOMPARE(runQbs(), 0); QCOMPARE(runQbs(), 0); } static void switchProfileContents(qbs::Profile &p, qbs::Settings *s, bool on) { const QString scalarKey = "leaf.scalarProp"; const QString listKey = "leaf.listProp"; if (on) { p.setValue(scalarKey, "profile"); p.setValue(listKey, QStringList() << "profile"); } else { p.remove(scalarKey); p.remove(listKey); } s->sync(); } static void switchFileContents(QFile &f, bool on) { f.seek(0); QByteArray contents = f.readAll(); f.resize(0); if (on) contents.replace("// leaf.", "leaf."); else contents.replace("leaf.", "// leaf."); f.write(contents); f.flush(); } void TestBlackbox::propertyPrecedence() { QDir::setCurrent(testDataDir + "/property-precedence"); const SettingsPtr s = settings(); qbs::Internal::TemporaryProfile profile("qbs_autotests_propPrecedence", s.get()); profile.p.setValue("qbs.architecture", "x86"); // Profiles must not be empty... s->sync(); const QStringList args = QStringList() << "-f" << "property-precedence.qbs"; QbsRunParameters params(args); params.profile = profile.p.name(); QbsRunParameters resolveParams = params; resolveParams.command = "resolve"; // Case 1: [cmdline=0,prod=0,export=0,nonleaf=0,profile=0] QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: leaf\n") && m_qbsStdout.contains("list prop: [\"leaf\"]\n"), m_qbsStdout.constData()); params.arguments.clear(); // Case 2: [cmdline=0,prod=0,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: profile\n") && m_qbsStdout.contains("list prop: [\"profile\"]\n"), m_qbsStdout.constData()); // Case 3: [cmdline=0,prod=0,export=0,nonleaf=1,profile=0] QFile nonleafFile("modules/nonleaf/nonleaf.qbs"); QVERIFY2(nonleafFile.open(QIODevice::ReadWrite), qPrintable(nonleafFile.errorString())); switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: nonleaf\n") && m_qbsStdout.contains("list prop: [\"nonleaf\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 4: [cmdline=0,prod=0,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: nonleaf\n") && m_qbsStdout.contains("list prop: [\"nonleaf\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 5: [cmdline=0,prod=0,export=1,nonleaf=0,profile=0] QFile depFile("dep.qbs"); QVERIFY2(depFile.open(QIODevice::ReadWrite), qPrintable(depFile.errorString())); switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 6: [cmdline=0,prod=0,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 7: [cmdline=0,prod=0,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"nonleaf\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 8: [cmdline=0,prod=0,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"nonleaf\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 9: [cmdline=0,prod=1,export=0,nonleaf=0,profile=0] QFile productFile("property-precedence.qbs"); QVERIFY2(productFile.open(QIODevice::ReadWrite), qPrintable(productFile.errorString())); switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, false); switchFileContents(productFile, true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 10: [cmdline=0,prod=1,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 11: [cmdline=0,prod=1,export=0,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"nonleaf\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 12: [cmdline=0,prod=1,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"nonleaf\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 13: [cmdline=0,prod=1,export=1,nonleaf=0,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 14: [cmdline=0,prod=1,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"profile\"]\n"), m_qbsStdout.constData()); // Case 15: [cmdline=0,prod=1,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"nonleaf\",\"leaf\"]\n"), m_qbsStdout.constData()); // Case 16: [cmdline=0,prod=1,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"nonleaf\",\"profile\"]\n"), m_qbsStdout.constData()); // Command line properties wipe everything, including lists. // Case 17: [cmdline=1,prod=0,export=0,nonleaf=0,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, false); switchFileContents(productFile, false); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 18: [cmdline=1,prod=0,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 19: [cmdline=1,prod=0,export=0,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 20: [cmdline=1,prod=0,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 21: [cmdline=1,prod=0,export=1,nonleaf=0,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 22: [cmdline=1,prod=0,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 23: [cmdline=1,prod=0,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 24: [cmdline=1,prod=0,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 25: [cmdline=1,prod=1,export=0,nonleaf=0,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, false); switchFileContents(productFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 26: [cmdline=1,prod=1,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 27: [cmdline=1,prod=1,export=0,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 28: [cmdline=1,prod=1,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 29: [cmdline=1,prod=1,export=1,nonleaf=0,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 30: [cmdline=1,prod=1,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 31: [cmdline=1,prod=1,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); // Case 32: [cmdline=1,prod=1,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), m_qbsStdout.constData()); } void TestBlackbox::productDependenciesByType() { QDir::setCurrent(testDataDir + "/product-dependencies-by-type"); QCOMPARE(runQbs(), 0); QFile appListFile(relativeProductBuildDir("app list") + "/app-list.txt"); QVERIFY2(appListFile.open(QIODevice::ReadOnly), qPrintable(appListFile.fileName())); const QList appList = appListFile.readAll().trimmed().split('\n'); QCOMPARE(appList.size(), 6); QStringList apps = QStringList() << QDir::currentPath() + '/' + relativeExecutableFilePath("app1") << QDir::currentPath() + '/' + relativeExecutableFilePath("app2") << QDir::currentPath() + '/' + relativeExecutableFilePath("app3") << QDir::currentPath() + '/' + relativeExecutableFilePath("app4") << QDir::currentPath() + '/' + relativeProductBuildDir("other-product") + "/output.txt" << QDir::currentPath() + '/' + relativeProductBuildDir("yet-another-product") + "/output.txt"; for (const QByteArray &line : appList) { const QString cleanLine = QString::fromLocal8Bit(line.trimmed()); QVERIFY2(apps.removeOne(cleanLine), qPrintable(cleanLine)); } QVERIFY(apps.empty()); } void TestBlackbox::properQuoting() { QDir::setCurrent(testDataDir + "/proper quoting"); QCOMPARE(runQbs(), 0); QbsRunParameters params(QStringLiteral("run"), QStringList() << "-q" << "-p" << "Hello World"); params.expectFailure = true; // Because the exit code is non-zero. QCOMPARE(runQbs(params), 156); const char * const expectedOutput = "whitespaceless\ncontains space\ncontains\ttab\n" "backslash\\\nHello World! The magic number is 156."; QCOMPARE(unifiedLineEndings(m_qbsStdout).constData(), expectedOutput); } void TestBlackbox::propertiesInExportItems() { QDir::setCurrent(testDataDir + "/properties-in-export-items"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(relativeExecutableFilePath("p1"))); QVERIFY(regularFileExists(relativeExecutableFilePath("p2"))); QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); } void TestBlackbox::protobuf_data() { QTest::addColumn("projectFile"); QTest::addColumn("properties"); QTest::addColumn("successExpected"); QTest::newRow("cpp") << QString("addressbook_cpp.qbs") << QStringList() << true; QTest::newRow("objc") << QString("addressbook_objc.qbs") << QStringList() << true; QTest::newRow("import") << QString("import.qbs") << QStringList() << true; QTest::newRow("missing import dir") << QString("needs-import-dir.qbs") << QStringList() << false; QTest::newRow("provided import dir") << QString("needs-import-dir.qbs") << QStringList("products.app.theImportDir:subdir") << true; } void TestBlackbox::protobuf() { QDir::setCurrent(testDataDir + "/protobuf"); QFETCH(QString, projectFile); QFETCH(QStringList, properties); QFETCH(bool, successExpected); rmDirR(relativeBuildDir()); QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile} << properties); QCOMPARE(runQbs(resolveParams), 0); const bool withProtobuf = m_qbsStdout.contains("has protobuf: true"); const bool withoutProtobuf = m_qbsStdout.contains("has protobuf: false"); QVERIFY2(withProtobuf || withoutProtobuf, m_qbsStdout.constData()); if (withoutProtobuf) QSKIP("protobuf module not present"); QbsRunParameters runParams("run"); runParams.expectFailure = !successExpected; QCOMPARE(runQbs(runParams) == 0, successExpected); } void TestBlackbox::pseudoMultiplexing() { // This is "pseudo-multiplexing" on all platforms that initialize qbs.architectures // to an array with one element. See QBS-1243. QDir::setCurrent(testDataDir + "/pseudo-multiplexing"); QCOMPARE(runQbs(), 0); } void TestBlackbox::qbsConfig() { QbsRunParameters params("config"); #ifdef QBS_ENABLE_UNIT_TESTS QTemporaryDir tempSystemSettingsDir; params.environment.insert("QBS_AUTOTEST_SYSTEM_SETTINGS_DIR", tempSystemSettingsDir.path()); QTemporaryDir tempUserSettingsDir; QVERIFY(tempSystemSettingsDir.isValid()); QVERIFY(tempUserSettingsDir.isValid()); const QStringList settingsDirArgs = QStringList{"--settings-dir", tempUserSettingsDir.path()}; // Set values. params.arguments = settingsDirArgs + QStringList{"--system", "key.subkey.scalar", "s"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"--system", "key.subkey.list", "['sl']"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"--user", "key.subkey.scalar", "u"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"key.subkey.list", "[\"u1\",\"u2\"]"}; QCOMPARE(runQbs(params), 0); // Check outputs. const auto valueExtractor = [this] { const QByteArray trimmed = m_qbsStdout.trimmed(); return trimmed.mid(trimmed.lastIndexOf(':') + 2); }; params.arguments = settingsDirArgs + QStringList{"--list", "key.subkey.scalar"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("\"u\"")); params.arguments = settingsDirArgs + QStringList{"--list", "--user", "key.subkey.scalar"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("\"u\"")); params.arguments = settingsDirArgs + QStringList{"--list", "--system", "key.subkey.scalar"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("\"s\"")); params.arguments = settingsDirArgs + QStringList{"--list", "key.subkey.list"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("[\"u1\", \"u2\", \"sl\"]")); params.arguments = settingsDirArgs + QStringList{"--list", "--user", "key.subkey.list"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("[\"u1\", \"u2\"]")); params.arguments = settingsDirArgs + QStringList{"--list", "--system", "key.subkey.list"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("[\"sl\"]")); // Remove some values and re-check. params.arguments = settingsDirArgs + QStringList{"--unset", "key.subkey.scalar"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"--system", "--unset", "key.subkey.list"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"--list", "key.subkey.scalar"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("\"s\"")); params.arguments = settingsDirArgs + QStringList{"--list", "key.subkey.list"}; QCOMPARE(runQbs(params), 0); QCOMPARE(valueExtractor(), QByteArray("[\"u1\", \"u2\"]")); // Check preferences.ignoreSystemSearchPaths params.arguments = settingsDirArgs + QStringList{"--system", "preferences.qbsSearchPaths", "['/usr/lib/qbs']"}; QCOMPARE(runQbs(params), 0); params.arguments = settingsDirArgs + QStringList{"preferences.qbsSearchPaths", "['/home/user/qbs']"}; QCOMPARE(runQbs(params), 0); qbs::Settings settings(tempUserSettingsDir.path(), tempSystemSettingsDir.path()); const qbs::Preferences prefs(&settings, "SomeProfile"); QVERIFY2(prefs.searchPaths().contains("/usr/lib/qbs") && prefs.searchPaths().contains("/home/user/qbs"), qPrintable(prefs.searchPaths().join(','))); settings.setValue("profiles.SomeProfile.preferences.ignoreSystemSearchPaths", true); QVERIFY2(!prefs.searchPaths().contains("/usr/lib/qbs") && prefs.searchPaths().contains("/home/user/qbs"), qPrintable(prefs.searchPaths().join(','))); #else qDebug() << "ability to redirect the system settings dir not compiled in, skipping" "most qbs-config tests"; #endif // QBS_ENABLE_UNIT_TESTS bool canWriteToSystemSettings; QString testSettingsFilePath; { QSettings testSettings( qbs::Settings::defaultSystemSettingsBaseDir() + "/dummyOrg" + "/dummyApp.conf", QSettings::IniFormat); testSettings.setValue("dummyKey", "dummyValue"); testSettings.sync(); canWriteToSystemSettings = testSettings.status() == QSettings::NoError; testSettingsFilePath = testSettings.fileName(); } if (canWriteToSystemSettings) QVERIFY(QFile::remove(testSettingsFilePath)); // Check that trying to write to actual system settings causes access failure. params.expectFailure = !canWriteToSystemSettings; params.environment.clear(); params.arguments = QStringList{"--system", "key.subkey.scalar", "s"}; QCOMPARE(runQbs(params) == 0, canWriteToSystemSettings); if (!canWriteToSystemSettings) { QVERIFY2(m_qbsStderr.contains("You do not have permission to write to that location."), m_qbsStderr.constData()); } } void TestBlackbox::radAfterIncompleteBuild_data() { QTest::addColumn("projectFileName"); QTest::newRow("Project with Rule") << "project_with_rule.qbs"; QTest::newRow("Project with Transformer") << "project_with_transformer.qbs"; } void TestBlackbox::radAfterIncompleteBuild() { QDir::setCurrent(testDataDir + "/rad-after-incomplete-build"); rmDirR(relativeBuildDir()); const QString projectFileName = "project_with_rule.qbs"; // Step 1: Have a directory where a file used to be. QbsRunParameters params(QStringList() << "-f" << projectFileName); QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "oldfile", "oldfile/newfile"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "oldfile/newfile", "newfile"); params.expectFailure = false; QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "newfile", "oldfile/newfile"); QCOMPARE(runQbs(params), 0); // Step 2: Have a file where a directory used to be. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "oldfile/newfile", "oldfile"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "oldfile", "newfile"); params.expectFailure = false; QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFileName, "newfile", "oldfile"); QCOMPARE(runQbs(params), 0); } void TestBlackbox::subProfileChangeTracking() { QDir::setCurrent(testDataDir + "/subprofile-change-tracking"); const SettingsPtr s = settings(); qbs::Internal::TemporaryProfile subProfile("qbs-autotests-subprofile", s.get()); subProfile.p.setValue("baseProfile", profileName()); subProfile.p.setValue("cpp.includePaths", QStringList("/tmp/include1")); s->sync(); QCOMPARE(runQbs(), 0); subProfile.p.setValue("cpp.includePaths", QStringList("/tmp/include2")); s->sync(); QbsRunParameters params; params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("main1.cpp")); QVERIFY(m_qbsStdout.contains("main2.cpp")); } void TestBlackbox::successiveChanges() { QDir::setCurrent(testDataDir + "/successive-changes"); QCOMPARE(runQbs(), 0); QbsRunParameters params("resolve", QStringList() << "products.theProduct.type:output,blubb"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); params.arguments << "project.version:2"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QFile output(relativeProductBuildDir("theProduct") + "/output.out"); QVERIFY2(output.open(QIODevice::ReadOnly), qPrintable(output.errorString())); const QByteArray version = output.readAll(); QCOMPARE(version.constData(), "2"); } void TestBlackbox::installedApp() { QDir::setCurrent(testDataDir + "/installed_artifact"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + HostOsInfo::appendExecutableSuffix(QStringLiteral("/usr/bin/installedApp")))); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("qbs.installRoot:" + testDataDir + "/installed-app"))), 0); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(testDataDir + HostOsInfo::appendExecutableSuffix("/installed-app/usr/bin/installedApp"))); QFile addedFile(defaultInstallRoot + QLatin1String("/blubb.txt")); QVERIFY(addedFile.open(QIODevice::WriteOnly)); addedFile.close(); QVERIFY(addedFile.exists()); QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "--clean-install-root")), 0); QVERIFY(regularFileExists(defaultInstallRoot + HostOsInfo::appendExecutableSuffix(QStringLiteral("/usr/bin/installedApp")))); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/src/main.cpp"))); QVERIFY(!addedFile.exists()); // Check whether changing install parameters on the product causes re-installation. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("installed_artifact.qbs", "qbs.installPrefix: \"/usr\"", "qbs.installPrefix: '/usr/local'"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + HostOsInfo::appendExecutableSuffix(QStringLiteral("/usr/local/bin/installedApp")))); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/local/src/main.cpp"))); // Check whether changing install parameters on the artifact causes re-installation. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("installed_artifact.qbs", "qbs.installDir: \"bin\"", "qbs.installDir: 'custom'"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + HostOsInfo::appendExecutableSuffix(QStringLiteral("/usr/local/custom/installedApp")))); // Check whether changing install parameters on a source file causes re-installation. WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("installed_artifact.qbs", "qbs.installDir: \"src\"", "qbs.installDir: 'source'"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/local/source/main.cpp"))); // Check whether changing install parameters on the command line causes re-installation. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("qbs.installRoot:" + relativeBuildDir() + "/blubb"))), 0); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(relativeBuildDir() + "/blubb/usr/local/source/main.cpp")); // Check --no-install rmDirR(relativeBuildDir()); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "--no-install")), 0); QCOMPARE(QDir(defaultInstallRoot).entryList(QDir::NoDotAndDotDot).size(), 0); // Check --no-build (with and without an existing build graph) QbsRunParameters params("install", QStringList() << "--no-build"); QCOMPARE(runQbs(params), 0); rmDirR(relativeBuildDir()); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Build graph not found"), m_qbsStderr.constData()); } void TestBlackbox::installDuplicates() { QDir::setCurrent(testDataDir + "/install-duplicates"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("Cannot install files")); } void TestBlackbox::installDuplicatesNoError() { QDir::setCurrent(testDataDir + "/install-duplicates-no-error"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); } void TestBlackbox::installedSourceFiles() { QDir::setCurrent(testDataDir + "/installed-source-files"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/readme.txt"))); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/main.cpp"))); } void TestBlackbox::toolLookup() { QbsRunParameters params(QStringLiteral("setup-toolchains"), QStringList("--help")); params.profile.clear(); QCOMPARE(runQbs(params), 0); } void TestBlackbox::topLevelSearchPath() { QDir::setCurrent(testDataDir + "/toplevel-searchpath"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("MyProduct"), m_qbsStderr.constData()); params.arguments << ("project.qbsSearchPaths:" + QDir::currentPath() + "/qbs-resources"); QCOMPARE(runQbs(params), 0); } void TestBlackbox::checkProjectFilePath() { QDir::setCurrent(testDataDir + "/project_filepath_check"); QbsRunParameters params(QStringList("-f") << "project1.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("main.cpp"), m_qbsStdout.constData()); QCOMPARE(runQbs(params), 0); params.arguments = QStringList("-f") << "project2.qbs"; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("project file")); params.arguments = QStringList("-f") << "project2.qbs"; params.command = "resolve"; params.expectFailure = false; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("main2.cpp"), m_qbsStdout.constData()); } void TestBlackbox::checkTimestamps() { QDir::setCurrent(testDataDir + "/check-timestamps"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling file.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY(QFile::remove(relativeBuildGraphFilePath())); WAIT_FOR_NEW_TIMESTAMP(); touch("file.h"); QCOMPARE(runQbs(QStringList("--check-timestamps")), 0); QVERIFY2(m_qbsStdout.contains("compiling file.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::chooseModuleInstanceByPriority() { QFETCH(QString, idol); QFETCH(QStringList, expectedSubStrings); QFETCH(bool, expectSuccess); QDir::setCurrent(testDataDir + "/choose-module-instance"); rmDirR(relativeBuildDir()); QbsRunParameters params(QStringList("modules.qbs.targetPlatform:" + idol)); params.expectFailure = !expectSuccess; if (expectSuccess) { QCOMPARE(runQbs(params), 0); } else { QVERIFY(runQbs(params) != 0); return; } const QString installRoot = relativeBuildDir() + "/install-root/"; QVERIFY(QFile::exists(installRoot + "/gerbil.txt")); QFile file(installRoot + "/gerbil.txt"); QVERIFY(file.open(QIODevice::ReadOnly)); const QString content = QString::fromUtf8(file.readAll()); for (const auto &str : expectedSubStrings) { if (content.contains(str)) continue; qDebug() << "content:" << content; qDebug() << "substring:" << str; QFAIL("missing substring"); } } void TestBlackbox::chooseModuleInstanceByPriority_data() { QTest::addColumn("idol"); QTest::addColumn("expectedSubStrings"); QTest::addColumn("expectSuccess"); QTest::newRow("ringo") << "Beatles" << QStringList() << false; QTest::newRow("ritchie1") << "Deep Purple" << QStringList{"slipped", "litchi", "ritchie"} << true; QTest::newRow("ritchie2") << "Rainbow" << QStringList{"slipped", "litchi", "ritchie"} << true; QTest::newRow("lord") << "Whitesnake" << QStringList{"chewed", "cord", "lord"} << true; } class TemporaryDefaultProfileRemover { public: TemporaryDefaultProfileRemover(qbs::Settings *settings) : m_settings(settings), m_defaultProfile(settings->defaultProfile()) { m_settings->remove(QStringLiteral("defaultProfile")); } ~TemporaryDefaultProfileRemover() { if (!m_defaultProfile.isEmpty()) m_settings->setValue(QStringLiteral("defaultProfile"), m_defaultProfile); } private: qbs::Settings *m_settings; const QString m_defaultProfile; }; void TestBlackbox::assembly() { QDir::setCurrent(testDataDir + "/assembly"); QVERIFY(runQbs() == 0); const QVariantMap properties = ([&]() { QFile propertiesFile(relativeProductBuildDir("assembly") + "/properties.json"); if (propertiesFile.open(QIODevice::ReadOnly)) return QJsonDocument::fromJson(propertiesFile.readAll()).toVariant().toMap(); return QVariantMap{}; })(); QVERIFY(!properties.empty()); const auto toolchain = properties.value("qbs.toolchain").toStringList(); QVERIFY(!toolchain.empty()); const bool haveGcc = toolchain.contains("gcc"); const bool haveMSVC = toolchain.contains("msvc"); QCOMPARE(m_qbsStdout.contains("assembling testa.s"), haveGcc); QCOMPARE(m_qbsStdout.contains("compiling testb.S"), haveGcc); QCOMPARE(m_qbsStdout.contains("compiling testc.sx"), haveGcc); QCOMPARE(m_qbsStdout.contains("creating libtesta.a"), haveGcc); QCOMPARE(m_qbsStdout.contains("creating libtestb.a"), haveGcc); QCOMPARE(m_qbsStdout.contains("creating libtestc.a"), haveGcc); QCOMPARE(m_qbsStdout.contains("creating testd.lib"), haveMSVC); } void TestBlackbox::autotestWithDependencies() { QDir::setCurrent(testDataDir + "/autotest-with-dependencies"); QCOMPARE(runQbs(QStringList({"-p", "autotest-runner"})), 0); QVERIFY2(m_qbsStdout.contains("i am the test app") && m_qbsStdout.contains("i am the helper"), m_qbsStdout.constData()); } void TestBlackbox::autotests_data() { QTest::addColumn("evilPropertySpec"); QTest::addColumn("expectedErrorMessage"); QTest::newRow("missing arguments") << QString("products.test1.autotest.arguments:[]") << QByteArray("This test needs exactly one argument"); QTest::newRow("missing working dir") << QString("products.test2.autotest.workingDir:''") << QByteArray("Test resource not found"); QTest::newRow("missing flaky specifier") << QString("products.test3.autotest.allowFailure:false") << QByteArray("I am an awful test"); QTest::newRow("everything's fine") << QString() << QByteArray(); } void TestBlackbox::autotests() { QDir::setCurrent(testDataDir + "/autotests"); QFETCH(QString, evilPropertySpec); QFETCH(QByteArray, expectedErrorMessage); QbsRunParameters resolveParams("resolve"); if (!evilPropertySpec.isEmpty()) resolveParams.arguments << evilPropertySpec; QCOMPARE(runQbs(resolveParams), 0); QbsRunParameters testParams(QStringList{"-p", "autotest-runner"}); if (!evilPropertySpec.isEmpty()) testParams.expectFailure = true; QCOMPARE(runQbs(testParams) == 0, !testParams.expectFailure); if (testParams.expectFailure) { QVERIFY2(m_qbsStderr.contains(expectedErrorMessage), m_qbsStderr.constData()); return; } QVERIFY2(m_qbsStdout.contains("Running test test1") && m_qbsStdout.contains("Running test test2") && m_qbsStdout.contains("Running test test3"), m_qbsStdout.constData()); QCOMPARE(m_qbsStdout.count("PASS"), 2); QCOMPARE(m_qbsStderr.count("FAIL"), 1); } void TestBlackbox::auxiliaryInputsFromDependencies() { QDir::setCurrent(testDataDir + "/aux-inputs-from-deps"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating dummy.out"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.dep.sleep:false"))), 0); WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("generating dummy.out"), m_qbsStdout.constData()); } void TestBlackbox::explicitlyDependsOn() { QFETCH(QString, useExplicitlyDependsOn); QFETCH(QString, useExplicitlyDependsOnFromDependencies); QFETCH(QString, useModule); QFETCH(bool, expectFailure); QDir::setCurrent(testDataDir + "/explicitly-depends-on"); QbsRunParameters params("", QStringList("products.prod1.useExplicitlyDependsOn:" + useExplicitlyDependsOn) << "products.prod1.useExplicitlyDependsOnFromDependencies:" + useExplicitlyDependsOnFromDependencies << "projects.proj1.useModule:" + useModule); params.expectFailure = expectFailure; rmDirR(relativeBuildDir()); if (params.expectFailure) { // Build should fail because a rule cycle is created within the product when // explicitlyDependsOn is used. QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Cycle detected in rule dependencies"), m_qbsStderr.constData()); } else { // When explicitlyDependsOnFromDependencies is used, build should succeed due to the // "final" tag being pulled in from dependencies. QCOMPARE(runQbs(params), 0); if (useModule == QLatin1String("false")) { QVERIFY2(m_qbsStdout.contains("creating 'product-fish.txt' tagged with 'final'"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("Using explicitlyDependsOnArtifact: product-fish.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step1 -> step2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step2 -> step3"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step3 -> final"), m_qbsStdout.constData()); } else { QVERIFY2(!m_qbsStdout.contains("creating 'product-fish.txt' tagged with 'final'"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("Using explicitlyDependsOnArtifact: module-fish.txt"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step1 -> step2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step2 -> step3"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("step3 -> final"), m_qbsStdout.constData()); } } } void TestBlackbox::explicitlyDependsOn_data() { QTest::addColumn("useExplicitlyDependsOn"); QTest::addColumn("useExplicitlyDependsOnFromDependencies"); QTest::addColumn("useModule"); QTest::addColumn("expectFailure"); QTest::newRow("useExplicitlyDependsOn -> causes cycle") << "true" << "false" << "false" << true; QTest::newRow("explicitlyDependsOnFromDependencies + product") << "false" << "true" << "false" << false; QTest::newRow("explicitlyDependsOnFromDependencies + module + filesAreTargets") << "false" << "true" << "true" << false; } static bool haveMakeNsis() { QStringList regKeys; regKeys << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS") << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS"); QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); for (const QString &key : qAsConst(regKeys)) { QSettings settings(key, QSettings::NativeFormat); QString str = settings.value(QStringLiteral(".")).toString(); if (!str.isEmpty()) paths.prepend(str); } bool haveMakeNsis = false; for (const QString &path : qAsConst(paths)) { if (regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QStringLiteral("/makensis")))) { haveMakeNsis = true; break; } } return haveMakeNsis; } void TestBlackbox::nsis() { if (!haveMakeNsis()) { QSKIP("makensis is not installed"); return; } bool targetIsWindows = targetOs() == HostOsInfo::HostOsWindows; QDir::setCurrent(testDataDir + "/nsis"); QVERIFY(runQbs() == 0); QCOMPARE((bool)m_qbsStdout.contains("compiling hello.nsi"), targetIsWindows); QCOMPARE((bool)m_qbsStdout.contains("SetCompressor ignored due to previous call with the /FINAL switch"), targetIsWindows); QVERIFY(!QFile::exists(defaultInstallRoot + "/you-should-not-see-a-file-with-this-name.exe")); } void TestBlackbox::nsisDependencies() { if (!haveMakeNsis()) { QSKIP("makensis is not installed"); return; } bool targetIsWindows = targetOs() == HostOsInfo::HostOsWindows; QDir::setCurrent(testDataDir + "/nsisDependencies"); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.contains("compiling hello.nsi"), targetIsWindows); } void TestBlackbox::outOfDateMarking() { QDir::setCurrent(testDataDir + "/out-of-date-marking"); for (int i = 0; i < 25; ++i) { QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("generating myheader.h"), qPrintable(QString::number(i))); QVERIFY2(m_qbsStdout.contains("compiling main.c"), qPrintable(QString::number(i))); } } void TestBlackbox::enableExceptions() { QFETCH(QString, file); QFETCH(bool, enable); QFETCH(bool, expectSuccess); QDir::setCurrent(testDataDir + QStringLiteral("/enableExceptions")); QbsRunParameters params; params.arguments = QStringList() << "-f" << file << (QStringLiteral("modules.cpp.enableExceptions:") + (enable ? "true" : "false")); params.expectFailure = !expectSuccess; rmDirR(relativeBuildDir()); if (!params.expectFailure) QCOMPARE(runQbs(params), 0); else QVERIFY(runQbs(params) != 0); } void TestBlackbox::enableExceptions_data() { QTest::addColumn("file"); QTest::addColumn("enable"); QTest::addColumn("expectSuccess"); QTest::newRow("no exceptions, enabled") << "none.qbs" << true << true; QTest::newRow("no exceptions, disabled") << "none.qbs" << false << true; QTest::newRow("C++ exceptions, enabled") << "exceptions.qbs" << true << true; QTest::newRow("C++ exceptions, disabled") << "exceptions.qbs" << false << false; if (HostOsInfo::isMacosHost()) { QTest::newRow("Objective-C exceptions, enabled") << "exceptions-objc.qbs" << true << true; QTest::newRow("Objective-C exceptions in Objective-C++ source, enabled") << "exceptions-objcpp.qbs" << true << true; QTest::newRow("C++ exceptions in Objective-C++ source, enabled") << "exceptions-objcpp-cpp.qbs" << true << true; QTest::newRow("Objective-C, disabled") << "exceptions-objc.qbs" << false << false; QTest::newRow("Objective-C exceptions in Objective-C++ source, disabled") << "exceptions-objcpp.qbs" << false << false; QTest::newRow("C++ exceptions in Objective-C++ source, disabled") << "exceptions-objcpp-cpp.qbs" << false << false; } } void TestBlackbox::enableRtti() { QDir::setCurrent(testDataDir + QStringLiteral("/enableRtti")); QbsRunParameters params; params.arguments = QStringList() << "modules.cpp.enableRtti:true"; rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); if (HostOsInfo::isMacosHost()) { params.arguments = QStringList() << "modules.cpp.enableRtti:true" << "project.treatAsObjcpp:true"; rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); } params.expectFailure = true; params.arguments = QStringList() << "modules.cpp.enableRtti:false"; rmDirR(relativeBuildDir()); QVERIFY(runQbs(params) != 0); if (HostOsInfo::isMacosHost()) { params.arguments = QStringList() << "modules.cpp.enableRtti:false" << "project.treatAsObjcpp:true"; rmDirR(relativeBuildDir()); QVERIFY(runQbs(params) != 0); } } void TestBlackbox::envMerging() { QDir::setCurrent(testDataDir + "/env-merging"); QbsRunParameters params; QString pathVal = params.environment.value("PATH"); pathVal.prepend(HostOsInfo::pathListSeparator()).prepend("/opt/blackbox/bin"); const QString keyName = HostOsInfo::isWindowsHost() ? "pATh" : "PATH"; params.environment.insert(keyName, pathVal); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains(QByteArray("PATH=/opt/tool/bin") + HostOsInfo::pathListSeparator().toLatin1()) && m_qbsStdout.contains(HostOsInfo::pathListSeparator().toLatin1() + QByteArray("/opt/blackbox/bin")), m_qbsStdout.constData()); } void TestBlackbox::envNormalization() { QDir::setCurrent(testDataDir + "/env-normalization"); QbsRunParameters params; params.environment.insert("myvar", "x"); QCOMPARE(runQbs(params), 0); if (HostOsInfo::isWindowsHost()) QVERIFY2(m_qbsStdout.contains("\"MYVAR\":\"x\""), m_qbsStdout.constData()); else QVERIFY2(m_qbsStdout.contains("\"myvar\":\"x\""), m_qbsStdout.constData()); } void TestBlackbox::generatedArtifactAsInputToDynamicRule() { QDir::setCurrent(testDataDir + "/generated-artifact-as-input-to-dynamic-rule"); QCOMPARE(runQbs(), 0); const QString oldFile = relativeProductBuildDir("p") + "/old.txt"; QVERIFY2(regularFileExists(oldFile), qPrintable(oldFile)); WAIT_FOR_NEW_TIMESTAMP(); QFile inputFile("input.txt"); QVERIFY2(inputFile.open(QIODevice::WriteOnly), qPrintable(inputFile.errorString())); inputFile.resize(0); inputFile.write("new.txt"); inputFile.close(); QCOMPARE(runQbs(), 0); QVERIFY2(!regularFileExists(oldFile), qPrintable(oldFile)); const QString newFile = relativeProductBuildDir("p") + "/new.txt"; QVERIFY2(regularFileExists(newFile), qPrintable(oldFile)); QVERIFY2(m_qbsStdout.contains("generating"), m_qbsStdout.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("generating"), m_qbsStdout.constData()); } void TestBlackbox::generator() { QFETCH(QString, inputFile); QFETCH(QStringList, toBeCompiled); QDir::setCurrent(testDataDir + "/generator"); if (!inputFile.isEmpty()) { WAIT_FOR_NEW_TIMESTAMP(); QFile input(inputFile); QFile output("input.txt"); QVERIFY2(!output.exists() || output.remove(), qPrintable(output.errorString())); QVERIFY2(input.copy(output.fileName()), qPrintable(input.errorString())); touch(output.fileName()); } QCOMPARE(runQbs(), 0); QCOMPARE(toBeCompiled.contains("main.cpp"), m_qbsStdout.contains("compiling main.cpp")); QCOMPARE(toBeCompiled.contains("file1.cpp"), m_qbsStdout.contains("compiling file1.cpp")); QCOMPARE(toBeCompiled.contains("file2.cpp"), m_qbsStdout.contains("compiling file2.cpp")); } void TestBlackbox::generator_data() { QTest::addColumn("inputFile"); QTest::addColumn("toBeCompiled"); QTest::newRow("both") << "input.both.txt" << QStringList{"main.cpp", "file1.cpp", "file2.cpp"}; QTest::newRow("file1") << "input.file1.txt" << QStringList{"file1.cpp"}; QTest::newRow("file2") << "input.file2.txt" << QStringList{"file2.cpp"}; QTest::newRow("none") << "input.none.txt" << QStringList(); QTest::newRow("both again") << "input.both.txt" << QStringList{"file1.cpp", "file2.cpp"}; QTest::newRow("no update") << QString() << QStringList(); } static bool haveWiX(const Profile &profile) { if (profile.value("wix.toolchainInstallPath").isValid() && profile.value("wix.toolchainInstallRoot").isValid()) { return true; } QStringList regKeys; regKeys << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows Installer XML\\") << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Installer XML\\"); QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); for (const QString &key : qAsConst(regKeys)) { const QStringList versions = QSettings(key, QSettings::NativeFormat).childGroups(); for (const QString &version : versions) { QSettings settings(key + version, QSettings::NativeFormat); QString str = settings.value(QStringLiteral("InstallRoot")).toString(); if (!str.isEmpty()) paths.prepend(str); } } for (const QString &path : qAsConst(paths)) { if (regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QStringLiteral("/candle"))) && regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QStringLiteral("/light")))) { return true; } } return false; } void TestBlackbox::wix() { const SettingsPtr s = settings(); Profile profile(profileName(), s.get()); if (!haveWiX(profile)) { QSKIP("WiX is not installed"); return; } QByteArray arch = profile.value("qbs.architecture").toString().toLatin1(); if (arch.isEmpty()) arch = QByteArrayLiteral("x86"); QDir::setCurrent(testDataDir + "/wix"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling QbsSetup.wxs"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("linking qbs.msi"), m_qbsStdout); QVERIFY(regularFileExists(relativeProductBuildDir("QbsSetup") + "/qbs.msi")); if (HostOsInfo::isWindowsHost()) { QVERIFY2(m_qbsStdout.contains("compiling QbsBootstrapper.wxs"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("linking qbs-setup-" + arch + ".exe"), m_qbsStdout); QVERIFY(regularFileExists(relativeProductBuildDir("QbsBootstrapper") + "/qbs-setup-" + arch + ".exe")); } } void TestBlackbox::wixDependencies() { const SettingsPtr s = settings(); Profile profile(profileName(), s.get()); if (!haveWiX(profile)) { QSKIP("WiX is not installed"); return; } QByteArray arch = profile.value("qbs.architecture").toString().toLatin1(); if (arch.isEmpty()) arch = QByteArrayLiteral("x86"); QDir::setCurrent(testDataDir + "/wixDependencies"); QbsRunParameters params; if (!HostOsInfo::isWindowsHost()) params.arguments << "qbs.targetOS:windows"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("compiling QbsSetup.wxs"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("linking qbs.msi"), m_qbsStdout); QVERIFY(regularFileExists(relativeBuildDir() + "/qbs.msi")); } void TestBlackbox::nodejs() { const SettingsPtr s = settings(); Profile p(profileName(), s.get()); int status; findNodejs(&status); QCOMPARE(status, 0); QDir::setCurrent(testDataDir + QLatin1String("/nodejs")); status = runQbs(); if (p.value("nodejs.toolchainInstallPath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("toolchainInstallPath")) { QSKIP("nodejs.toolchainInstallPath not set and automatic detection failed"); } if (p.value("nodejs.packageManagerPrefixPath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("nodejs.packageManagerPrefixPath")) { QSKIP("nodejs.packageManagerFilePath not set and automatic detection failed"); } QCOMPARE(status, 0); QbsRunParameters params; params.command = QLatin1String("run"); QCOMPARE(runQbs(params), 0); QVERIFY((bool)m_qbsStdout.contains("hello world")); QVERIFY(regularFileExists(relativeProductBuildDir("hello") + "/hello.js")); } void TestBlackbox::typescript() { const SettingsPtr s = settings(); Profile p(profileName(), s.get()); int status; findTypeScript(&status); QCOMPARE(status, 0); QDir::setCurrent(testDataDir + QLatin1String("/typescript")); QbsRunParameters params; params.expectFailure = true; status = runQbs(params); if (p.value("typescript.toolchainInstallPath").toString().isEmpty() && status != 0) { if (m_qbsStderr.contains("Path\" must be specified")) QSKIP("typescript probe failed"); if (m_qbsStderr.contains("typescript.toolchainInstallPath")) QSKIP("typescript.toolchainInstallPath not set and automatic detection failed"); if (m_qbsStderr.contains("nodejs.interpreterFilePath")) QSKIP("nodejs.interpreterFilePath not set and automatic detection failed"); } if (status != 0) qDebug() << m_qbsStderr; QCOMPARE(status, 0); params.expectFailure = false; params.command = QStringLiteral("run"); params.arguments = QStringList() << "-p" << "animals"; QCOMPARE(runQbs(params), 0); QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/animals.js")); QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/extra.js")); QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/main.js")); } void TestBlackbox::importInPropertiesCondition() { QDir::setCurrent(testDataDir + "/import-in-properties-condition"); QCOMPARE(runQbs(), 0); } void TestBlackbox::importSearchPath() { QDir::setCurrent(testDataDir + "/import-searchpath"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling somefile.cpp"), m_qbsStdout.constData()); } void TestBlackbox::importingProduct() { QDir::setCurrent(testDataDir + "/importing-product"); QCOMPARE(runQbs(), 0); } void TestBlackbox::importsConflict() { QDir::setCurrent(testDataDir + "/imports-conflict"); QCOMPARE(runQbs(), 0); } void TestBlackbox::includeLookup() { QDir::setCurrent(testDataDir + "/includeLookup"); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("definition.."), m_qbsStdout.constData()); } static bool haveInnoSetup(const Profile &profile) { if (profile.value("innosetup.toolchainInstallPath").isValid()) return true; QStringList regKeys; regKeys << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 5_is1") << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 5_is1"); QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); for (const QString &key : regKeys) { QSettings settings(key, QSettings::NativeFormat); QString str = settings.value(QStringLiteral("InstallLocation")).toString(); if (!str.isEmpty()) paths.prepend(str); } for (const QString &path : paths) { if (regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QStringLiteral("/ISCC")))) return true; } return false; } void TestBlackbox::innoSetup() { const SettingsPtr s = settings(); Profile profile(profileName(), s.get()); if (!haveInnoSetup(profile)) { QSKIP("Inno Setup is not installed"); return; } QDir::setCurrent(testDataDir + "/innosetup"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling test.iss")); QVERIFY(m_qbsStdout.contains("compiling Example1.iss")); QVERIFY(regularFileExists(relativeProductBuildDir("QbsSetup") + "/qbs.setup.test.exe")); QVERIFY(regularFileExists(relativeProductBuildDir("Example1") + "/Example1.exe")); } void TestBlackbox::innoSetupDependencies() { const SettingsPtr s = settings(); Profile profile(profileName(), s.get()); if (!haveInnoSetup(profile)) { QSKIP("Inno Setup is not installed"); return; } QDir::setCurrent(testDataDir + "/innosetupDependencies"); QbsRunParameters params; if (!HostOsInfo::isWindowsHost()) params.arguments << "qbs.targetOS:windows"; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling test.iss")); QVERIFY(regularFileExists(relativeBuildDir() + "/qbs.setup.test.exe")); } void TestBlackbox::inputTagsChangeTracking_data() { QTest::addColumn("generateInput"); QTest::newRow("source artifact") << QString("no"); QTest::newRow("generated artifact (static)") << QString("static"); QTest::newRow("generated artifact (dynamic)") << QString("dynamic"); } void TestBlackbox::inputTagsChangeTracking() { QDir::setCurrent(testDataDir + "/input-tags-change-tracking"); const QString xOut = QDir::currentPath() + '/' + relativeProductBuildDir("p") + "/x.out"; const QString yOut = QDir::currentPath() + '/' + relativeProductBuildDir("p") + "/y.out"; QFETCH(QString, generateInput); const QbsRunParameters resolveParams("resolve", QStringList("products.p.generateInput:" + generateInput)); QCOMPARE(runQbs(resolveParams), 0); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("generating input.txt") == (generateInput == "static")); QVERIFY2(!QFile::exists(xOut), qPrintable(xOut)); QVERIFY2(!QFile::exists(yOut), qPrintable(yOut)); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("input-tags-change-tracking.qbs", "Tags: [\"txt\", \"empty\"]", "Tags: \"txt\""); QCOMPARE(runQbs(), 0); QVERIFY2(QFile::exists(xOut), qPrintable(xOut)); QVERIFY2(!QFile::exists(yOut), qPrintable(yOut)); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("input-tags-change-tracking.qbs", "Tags: \"txt\"", "Tags: [\"txt\", \"y\"]"); QCOMPARE(runQbs(), 0); QVERIFY2(!QFile::exists(xOut), qPrintable(xOut)); QVERIFY2(QFile::exists(yOut), qPrintable(yOut)); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("input-tags-change-tracking.qbs", "Tags: [\"txt\", \"y\"]", "Tags: [\"txt\", \"empty\"]"); QCOMPARE(runQbs(), 0); QVERIFY2(!QFile::exists(xOut), qPrintable(xOut)); QVERIFY2(!QFile::exists(yOut), qPrintable(yOut)); } void TestBlackbox::outputArtifactAutoTagging() { QDir::setCurrent(testDataDir + QLatin1String("/output-artifact-auto-tagging")); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(relativeExecutableFilePath("output-artifact-auto-tagging"))); } void TestBlackbox::wildCardsAndRules() { QDir::setCurrent(testDataDir + "/wildcards-and-rules"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("Creating output artifact")); QFile output(relativeProductBuildDir("wildcards-and-rules") + "/test.mytype"); QVERIFY2(output.open(QIODevice::ReadOnly), qPrintable(output.errorString())); QCOMPARE(output.readAll().count('\n'), 1); output.close(); // Add input. WAIT_FOR_NEW_TIMESTAMP(); touch("input2.inp"); QbsRunParameters params; params.expectFailure = true; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Creating output artifact")); QVERIFY2(output.open(QIODevice::ReadOnly), qPrintable(output.errorString())); QCOMPARE(output.readAll().count('\n'), 2); output.close(); // Add "explicitlyDependsOn". WAIT_FOR_NEW_TIMESTAMP(); touch("dep.dep"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("Creating output artifact")); // Add nothing. QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("Creating output artifact")); } void TestBlackbox::loadableModule() { QDir::setCurrent(testDataDir + QLatin1String("/loadablemodule")); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("foo = 42"), m_qbsStdout.constData()); } void TestBlackbox::localDeployment() { QDir::setCurrent(testDataDir + "/localDeployment"); QFile main("main.cpp"); QVERIFY(main.open(QIODevice::ReadOnly)); QByteArray content = main.readAll(); content.replace('\r', ""); QbsRunParameters params; params.command = "run"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains(content), m_qbsStdout.constData()); } void TestBlackbox::makefileGenerator() { QDir::setCurrent(testDataDir + "/makefile-generator"); const QbsRunParameters params("generate", QStringList{"-g", "makefile"}); QCOMPARE(runQbs(params), 0); if (HostOsInfo::isWindowsHost()) return; QProcess make; make.setWorkingDirectory(QDir::currentPath() + '/' + relativeBuildDir()); const QString customInstallRoot = QDir::currentPath() + "/my-install-root"; make.start("make", QStringList{"INSTALL_ROOT=" + customInstallRoot, "install"}); QVERIFY(waitForProcessSuccess(make)); QVERIFY(QFile::exists(relativeExecutableFilePath("the app"))); QVERIFY(!QFile::exists(relativeBuildGraphFilePath())); QProcess app; app.start('"' + customInstallRoot + "/usr/local/bin/the app\""); QVERIFY(waitForProcessSuccess(app)); const QByteArray appStdout = app.readAllStandardOutput(); QVERIFY2(appStdout.contains("Hello, World!"), appStdout.constData()); make.start("make", QStringList("clean")); QVERIFY(waitForProcessSuccess(make)); QVERIFY(!QFile::exists(relativeExecutableFilePath("the app"))); } void TestBlackbox::maximumCLanguageVersion() { QDir::setCurrent(testDataDir + "/maximum-c-language-version"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:true"))), 0); if (m_qbsStdout.contains("is msvc")) QSKIP("MSVC has no support for setting the C language version."); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line", "-n"})), 0); QVERIFY2(m_qbsStdout.contains("c11") || m_qbsStdout.contains("c1x"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:false"))), 0); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line", "-n"})), 0); QVERIFY2(m_qbsStdout.contains("c99"), m_qbsStdout.constData()); } void TestBlackbox::maximumCxxLanguageVersion() { QDir::setCurrent(testDataDir + "/maximum-cxx-language-version"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:true"))), 0); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line", "-n"})), 0); QVERIFY2(m_qbsStdout.contains("c++17") || m_qbsStdout.contains("c++1z") || m_qbsStdout.contains("c++latest"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.enableNewestModule:false"))), 0); QCOMPARE(runQbs(QStringList({"--command-echo-mode", "command-line", "-n"})), 0); QVERIFY2(m_qbsStdout.contains("c++14") || m_qbsStdout.contains("c++1y"), m_qbsStdout.constData()); } void TestBlackbox::moduleProviders() { QDir::setCurrent(testDataDir + "/module-providers"); // Resolving in dry-run mode must not leave any data behind. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); QVERIFY(!QFile::exists(relativeBuildDir())); // Initial build. QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); QVERIFY(QFile::exists(relativeBuildDir())); QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); // Rebuild with overridden module provider config. The output for product 2 must change, // but no setup script must be re-run, because both config values have already been // handled in the first run. const QStringList resolveArgs("moduleProviders.mygenerator.chooseLettersFrom:beginning"); QCOMPARE(runQbs(QbsRunParameters("resolve", resolveArgs)), 0); QVERIFY2(!m_qbsStdout.contains("Running setup script"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); // Forcing Probe execution triggers a re-run of the setup script. But only once, // because the module provider config is the same now. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList(resolveArgs) << "--force-probe-execution")), 0); QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); // Now re-run without the module provider config override. Again, the setup script must // run once, for the config value that was not present in the last run. QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); } void TestBlackbox::fallbackModuleProvider_data() { QTest::addColumn("fallbacksEnabledGlobally"); QTest::addColumn("fallbacksEnabledInProduct"); QTest::addColumn("pkgConfigLibDirs"); QTest::addColumn("successExpected"); QTest::newRow("without custom lib dir, fallbacks disabled globally and in product") << false << false << QStringList() << false; QTest::newRow("without custom lib dir, fallbacks disabled globally, enabled in product") << false << true << QStringList() << false; QTest::newRow("without custom lib dir, fallbacks enabled globally, disabled in product") << true << false << QStringList() << false; QTest::newRow("without custom lib dir, fallbacks enabled globally and in product") << true << true << QStringList() << false; QTest::newRow("with custom lib dir, fallbacks disabled globally and in product") << false << false << QStringList(testDataDir + "/fallback-module-provider/libdir") << false; QTest::newRow("with custom lib dir, fallbacks disabled globally, enabled in product") << false << true << QStringList(testDataDir + "/fallback-module-provider/libdir") << false; QTest::newRow("with custom lib dir, fallbacks enabled globally, disabled in product") << true << false << QStringList(testDataDir + "/fallback-module-provider/libdir") << false; QTest::newRow("with custom lib dir, fallbacks enabled globally and in product") << true << true << QStringList(testDataDir + "/fallback-module-provider/libdir") << true; } void TestBlackbox::fallbackModuleProvider() { QFETCH(bool, fallbacksEnabledInProduct); QFETCH(bool, fallbacksEnabledGlobally); QFETCH(QStringList, pkgConfigLibDirs); QFETCH(bool, successExpected); QDir::setCurrent(testDataDir + "/fallback-module-provider"); static const auto b2s = [](bool b) { return QString(b ? "true" : "false"); }; QbsRunParameters resolveParams("resolve", QStringList{"modules.pkgconfig.libDirs:" + pkgConfigLibDirs.join(','), "products.p.fallbacksEnabled:" + b2s(fallbacksEnabledInProduct), "--force-probe-execution"}); if (!fallbacksEnabledGlobally) resolveParams.arguments << "--no-fallback-module-provider"; QCOMPARE(runQbs(resolveParams), 0); const bool pkgConfigPresent = m_qbsStdout.contains("pkg-config present: true"); const bool pkgConfigNotPresent = m_qbsStdout.contains("pkg-config present: false"); QVERIFY(pkgConfigPresent != pkgConfigNotPresent); if (pkgConfigNotPresent) successExpected = false; QbsRunParameters buildParams; buildParams.expectFailure = !successExpected; QCOMPARE(runQbs(buildParams) == 0, successExpected); } void TestBlackbox::minimumSystemVersion() { rmDirR(relativeBuildDir()); QDir::setCurrent(testDataDir + "/minimumSystemVersion"); QFETCH(QString, file); QFETCH(QString, output); QbsRunParameters params({ "-f", file + ".qbs" }); params.command = "run"; QCOMPARE(runQbs(params), 0); if (!m_qbsStdout.contains(output.toUtf8())) { qDebug() << "expected output:" << qPrintable(output); qDebug() << "actual output:" << m_qbsStdout.constData(); } QVERIFY(m_qbsStdout.contains(output.toUtf8())); } static qbs::Version fromMinimumDeploymentTargetValue(int v, bool isMacOS) { if (isMacOS && v < 100000) return qbs::Version(v / 100, v / 10 % 10, v % 10); return qbs::Version(v / 10000, v / 100 % 100, v % 100); } static int toMinimumDeploymentTargetValue(const qbs::Version &v, bool isMacOS) { if (isMacOS && v < qbs::Version(10, 10)) return (v.majorVersion() * 100) + (v.minorVersion() * 10) + v.patchLevel(); return (v.majorVersion() * 10000) + (v.minorVersion() * 100) + v.patchLevel(); } static qbs::Version defaultClangMinimumDeploymentTarget() { QProcess process; process.start("/usr/bin/xcrun", {"-sdk", "macosx", "clang++", "-target", "x86_64-apple-macosx-macho", "-dM", "-E", "-x", "objective-c++", "/dev/null"}); if (waitForProcessSuccess(process)) { const auto lines = process.readAllStandardOutput().split('\n'); for (const auto &line : lines) { static const QByteArray prefix = "#define __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ "; if (line.startsWith(prefix)) { bool ok = false; int v = line.mid(prefix.size()).trimmed().toInt(&ok); if (ok) return fromMinimumDeploymentTargetValue(v, true); break; } } } return qbs::Version(); } void TestBlackbox::minimumSystemVersion_data() { QTest::addColumn("file"); QTest::addColumn("output"); // Don't check for the full "version X.Y.Z\n" on macOS as some older versions of otool don't // show the patch version. Instead, simply check for "version X.Y" with no trailing \n. const QString unspecified = []() -> QString { if (HostOsInfo::isMacosHost()) { const auto v = defaultClangMinimumDeploymentTarget(); auto result = "__MAC_OS_X_VERSION_MIN_REQUIRED=" + QString::number(toMinimumDeploymentTargetValue(v, true)); if (v >= qbs::Version(10, 14)) result += "\nminos "; else result += "\nversion "; result += QString::number(v.majorVersion()) + "." + QString::number(v.minorVersion()); return result; } if (HostOsInfo::isWindowsHost()) return "WINVER is not defined\n"; return ""; }(); const QString specific = []() -> QString { if (HostOsInfo::isMacosHost()) return "__MAC_OS_X_VERSION_MIN_REQUIRED=1070\nversion 10.7\n"; if (HostOsInfo::isWindowsHost()) return "WINVER=1536\n6.00 operating system version\n6.00 subsystem version\n"; return ""; }(); QTest::newRow("unspecified") << "unspecified" << unspecified; QTest::newRow("unspecified-forced") << "unspecified-forced" << unspecified; if (HostOsInfo::isWindowsHost() || HostOsInfo::isMacosHost()) QTest::newRow("specific") << "specific" << specific; if (HostOsInfo::isWindowsHost()) QTest::newRow("fakewindows") << "fakewindows" << "WINVER=1283\n5.03 operating system " "version\n5.03 subsystem version\n"; if (HostOsInfo::isMacosHost()) QTest::newRow("macappstore") << "macappstore" << "__MAC_OS_X_VERSION_MIN_REQUIRED=1071\n" "version 10.7"; } void TestBlackbox::missingBuildGraph() { QTemporaryDir tmpDir; QVERIFY(tmpDir.isValid()); QDir::setCurrent(tmpDir.path()); QFETCH(QString, configName); const QStringList commands({"clean", "dump-nodes-tree", "status", "update-timestamps"}); const QString actualConfigName = configName.isEmpty() ? QString("default") : configName; QbsRunParameters params; params.expectFailure = true; params.arguments << QLatin1String("config:") + actualConfigName; for (const QString &command : qAsConst(commands)) { params.command = command; QVERIFY2(runQbs(params) != 0, qPrintable(command)); const QString expectedErrorMessage = QString("Build graph not found for " "configuration '%1'").arg(actualConfigName); if (!m_qbsStderr.contains(expectedErrorMessage.toLocal8Bit())) { qDebug() << command; qDebug() << expectedErrorMessage; qDebug() << m_qbsStderr; QFAIL("unexpected error message"); } } } void TestBlackbox::missingBuildGraph_data() { QTest::addColumn("configName"); QTest::newRow("implicit config name") << QString(); QTest::newRow("explicit config name") << QString("customConfig"); } void TestBlackbox::missingDependency() { QDir::setCurrent(testDataDir + "/missing-dependency"); QbsRunParameters params; params.expectFailure = true; params.arguments << "-p" << "theApp"; QVERIFY(runQbs(params) != 0); QVERIFY2(!m_qbsStderr.contains("ASSERT"), m_qbsStderr.constData()); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "-p" << "theDep")), 0); params.expectFailure = false; params.arguments << "-vv"; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStderr.contains("false positive")); } void TestBlackbox::missingProjectFile() { QDir::setCurrent(testDataDir + "/missing-project-file/empty-dir"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("No project file given and none found in current directory"), m_qbsStderr.constData()); QDir::setCurrent(testDataDir + "/missing-project-file"); params.arguments << "-f" << "empty-dir"; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("No project file found in directory"), m_qbsStderr.constData()); params.arguments = QStringList() << "-f" << "ambiguous-dir"; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("More than one project file found in directory"), m_qbsStderr.constData()); params.expectFailure = false; params.arguments = QStringList() << "-f" << "project-dir"; QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); touch("project-dir/file.cpp"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling file.cpp"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::missingOverridePrefix() { QDir::setCurrent(testDataDir + "/missing-override-prefix"); QbsRunParameters params; params.expectFailure = true; params.arguments << "blubb.whatever:false"; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Property override key 'blubb.whatever' not understood"), m_qbsStderr.constData()); } void TestBlackbox::moduleConditions() { QDir::setCurrent(testDataDir + "/module-conditions"); QCOMPARE(runQbs(), 0); QCOMPARE(m_qbsStdout.count("loaded m1"), 1); QCOMPARE(m_qbsStdout.count("loaded m2"), 2); QCOMPARE(m_qbsStdout.count("loaded m3"), 1); QCOMPARE(m_qbsStdout.count("loaded m4"), 1); } void TestBlackbox::movedFileDependency() { QDir::setCurrent(testDataDir + "/moved-file-dependency"); const QString subdir2 = QDir::currentPath() + "/subdir2"; QVERIFY(QDir::current().mkdir(subdir2)); const QString oldHeaderFilePath = QDir::currentPath() + "/subdir1/theheader.h"; const QString newHeaderFilePath = subdir2 + "/theheader.h"; QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QFile f(oldHeaderFilePath); QVERIFY2(f.rename(newHeaderFilePath), qPrintable(f.errorString())); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); f.setFileName(newHeaderFilePath); QVERIFY2(f.rename(oldHeaderFilePath), qPrintable(f.errorString())); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::badInterpreter() { if (!HostOsInfo::isAnyUnixHost()) QSKIP("only applies on Unix"); QDir::setCurrent(testDataDir + QLatin1String("/badInterpreter")); QCOMPARE(runQbs(), 0); QbsRunParameters params("run"); params.expectFailure = true; const QRegExp reNoSuchFileOrDir("bad interpreter:.* No such file or directory"); const QRegExp rePermissionDenied("bad interpreter:.* Permission denied"); params.arguments = QStringList() << "-p" << "script-interp-missing"; QCOMPARE(runQbs(params), 1); QString strerr = QString::fromLocal8Bit(m_qbsStderr); QVERIFY(strerr.contains(reNoSuchFileOrDir)); params.arguments = QStringList() << "-p" << "script-interp-noexec"; QCOMPARE(runQbs(params), 1); strerr = QString::fromLocal8Bit(m_qbsStderr); QVERIFY2(strerr.contains(reNoSuchFileOrDir) || strerr.contains(rePermissionDenied) || strerr.contains("script-noexec: bad interpreter: execve: Exec format error"), qPrintable(strerr)); params.arguments = QStringList() << "-p" << "script-noexec"; QCOMPARE(runQbs(params), 1); QCOMPARE(runQbs(QbsRunParameters("run", QStringList() << "-p" << "script-ok")), 0); } void TestBlackbox::bomSources() { QDir::setCurrent(testDataDir + "/bom-sources"); const bool success = runQbs() == 0; if (!success) QSKIP("Assuming compiler cannot deal with byte order mark"); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); touch("theheader.h"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::buildDataOfDisabledProduct() { QDir::setCurrent(testDataDir + QLatin1String("/build-data-of-disabled-product")); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("compiling test.cpp"), m_qbsStdout.constData()); // Touch a source file, disable the product, rebuild the project, verify nothing happens. WAIT_FOR_NEW_TIMESTAMP(); touch("test.cpp"); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.condition:false"))), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("linking"), m_qbsStdout.constData()); // Enable the product again, rebuild the project, verify that only the changed source file // is rebuilt. QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.app.condition:true"))), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("compiling test.cpp"), m_qbsStdout.constData()); } void TestBlackbox::qbsVersion() { const auto v = qbs::LanguageInfo::qbsVersion(); QDir::setCurrent(testDataDir + QLatin1String("/qbsVersion")); QbsRunParameters params; params.arguments = QStringList() << "project.qbsVersion:" + v.toString() << "project.qbsVersionMajor:" + QString::number(v.majorVersion()) << "project.qbsVersionMinor:" + QString::number(v.minorVersion()) << "project.qbsVersionPatch:" + QString::number(v.patchLevel()); QCOMPARE(runQbs(params), 0); params.arguments.push_back("project.qbsVersionPatch:" + QString::number(v.patchLevel() + 1)); params.expectFailure = true; QVERIFY(runQbs(params) != 0); } void TestBlackbox::transitiveOptionalDependencies() { QDir::setCurrent(testDataDir + "/transitive-optional-dependencies"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); } void TestBlackbox::groupsInModules() { QDir::setCurrent(testDataDir + "/groups-in-modules"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compile rock.coal => rock.diamond")); QVERIFY(m_qbsStdout.contains("compile chunk.coal => chunk.diamond")); QVERIFY(m_qbsStdout.contains("compiling helper2.c")); QVERIFY(!m_qbsStdout.contains("compiling helper3.c")); QVERIFY(m_qbsStdout.contains("compiling helper4.c")); QVERIFY(m_qbsStdout.contains("compiling helper5.c")); QVERIFY(!m_qbsStdout.contains("compiling helper6.c")); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compile rock.coal => rock.diamond")); QVERIFY(!m_qbsStdout.contains("compile chunk.coal => chunk.diamond")); WAIT_FOR_NEW_TIMESTAMP(); touch("modules/helper/diamondc.c"); waitForFileUnlock(); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling diamondc.c")); QVERIFY(m_qbsStdout.contains("compile rock.coal => rock.diamond")); QVERIFY(m_qbsStdout.contains("compile chunk.coal => chunk.diamond")); QVERIFY(regularFileExists(relativeProductBuildDir("groups-in-modules") + "/rock.diamond")); QFile output(relativeProductBuildDir("groups-in-modules") + "/rock.diamond"); QVERIFY(output.open(QIODevice::ReadOnly)); QCOMPARE(output.readAll().trimmed(), QByteArray("diamond")); } void TestBlackbox::ico() { QDir::setCurrent(testDataDir + "/ico"); QbsRunParameters params; params.expectFailure = true; params.arguments << "--command-echo-mode" << "command-line"; const int status = runQbs(params); if (status != 0) { if (m_qbsStderr.contains("Could not find icotool in any of the following locations:")) QSKIP("icotool is not installed"); if (!m_qbsStderr.isEmpty()) qDebug("%s", m_qbsStderr.constData()); if (!m_qbsStdout.isEmpty()) qDebug("%s", m_qbsStdout.constData()); } QCOMPARE(status, 0); QVERIFY(QFileInfo::exists(relativeProductBuildDir("icon") + "/icon.ico")); { QFile f(relativeProductBuildDir("icon") + "/icon.ico"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll().toStdString(); QCOMPARE(b.at(2), '\x1'); // icon QCOMPARE(b.at(4), '\x2'); // 2 images QVERIFY(b.find("\x89PNG") == std::string::npos); } QVERIFY(QFileInfo::exists(relativeProductBuildDir("icon-alpha") + "/icon-alpha.ico")); { QFile f(relativeProductBuildDir("icon-alpha") + "/icon-alpha.ico"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll().toStdString(); QCOMPARE(b.at(2), '\x1'); // icon QCOMPARE(b.at(4), '\x2'); // 2 images QVERIFY(b.find("\x89PNG") == std::string::npos); QVERIFY2(m_qbsStdout.contains("--alpha-threshold="), m_qbsStdout.constData()); } QVERIFY(QFileInfo::exists(relativeProductBuildDir("icon-big") + "/icon-big.ico")); { QFile f(relativeProductBuildDir("icon-big") + "/icon-big.ico"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll().toStdString(); QCOMPARE(b.at(2), '\x1'); // icon QCOMPARE(b.at(4), '\x5'); // 5 images QVERIFY(b.find("\x89PNG") != std::string::npos); } QVERIFY(QFileInfo::exists(relativeProductBuildDir("cursor") + "/cursor.cur")); { QFile f(relativeProductBuildDir("cursor") + "/cursor.cur"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll(); QVERIFY(b.size() > 0); QCOMPARE(b.at(2), '\x2'); // cursor QCOMPARE(b.at(4), '\x2'); // 2 images QCOMPARE(b.at(10), '\0'); QCOMPARE(b.at(12), '\0'); QCOMPARE(b.at(26), '\0'); QCOMPARE(b.at(28), '\0'); } QVERIFY(QFileInfo::exists(relativeProductBuildDir("cursor-hotspot") + "/cursor-hotspot.cur")); { QFile f(relativeProductBuildDir("cursor-hotspot") + "/cursor-hotspot.cur"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll(); QVERIFY(b.size() > 0); QCOMPARE(b.at(2), '\x2'); // cursor QCOMPARE(b.at(4), '\x2'); // 2 images const bool hasCursorHotspotBug = m_qbsStderr.contains( "does not support setting the hotspot for cursor files with multiple images"); if (hasCursorHotspotBug) { QCOMPARE(b.at(10), '\0'); QCOMPARE(b.at(12), '\0'); QCOMPARE(b.at(26), '\0'); QCOMPARE(b.at(28), '\0'); QWARN("this version of icoutil does not support setting the hotspot " "for cursor files with multiple images"); } else { QCOMPARE(b.at(10), '\x8'); QCOMPARE(b.at(12), '\x9'); QCOMPARE(b.at(26), '\x10'); QCOMPARE(b.at(28), '\x11'); } } QVERIFY(QFileInfo::exists(relativeProductBuildDir("cursor-hotspot-single") + "/cursor-hotspot-single.cur")); { QFile f(relativeProductBuildDir("cursor-hotspot-single") + "/cursor-hotspot-single.cur"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll(); QVERIFY(b.size() > 0); QCOMPARE(b.at(2), '\x2'); // cursor QCOMPARE(b.at(4), '\x1'); // 1 image // No version check needed because the hotspot can always be set if there's only one image QCOMPARE(b.at(10), '\x8'); QCOMPARE(b.at(12), '\x9'); } QVERIFY(QFileInfo::exists(relativeProductBuildDir("iconset") + "/dmg.ico")); { QFile f(relativeProductBuildDir("iconset") + "/dmg.ico"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll(); QVERIFY(b.size() > 0); QCOMPARE(b.at(2), '\x1'); // icon QCOMPARE(b.at(4), '\x5'); // 5 images } QVERIFY(QFileInfo::exists(relativeProductBuildDir("iconset") + "/dmg.cur")); { QFile f(relativeProductBuildDir("iconset") + "/dmg.cur"); QVERIFY(f.open(QIODevice::ReadOnly)); const auto b = f.readAll(); QVERIFY(b.size() > 0); QCOMPARE(b.at(2), '\x2'); // cursor QCOMPARE(b.at(4), '\x5'); // 5 images QCOMPARE(b.at(10), '\0'); QCOMPARE(b.at(12), '\0'); QCOMPARE(b.at(26), '\0'); QCOMPARE(b.at(28), '\0'); } } void TestBlackbox::importAssignment() { QDir::setCurrent(testDataDir + "/import-assignment"); QCOMPARE(runQbs(QStringList("project.qbsSearchPaths:" + QDir::currentPath())), 0); QVERIFY2(m_qbsStdout.contains("key 1 = value1") && m_qbsStdout.contains("key 2 = value2"), m_qbsStdout.constData()); } void TestBlackbox::importChangeTracking() { QDir::setCurrent(testDataDir + "/import-change-tracking"); QCOMPARE(runQbs(QStringList({"-f", "import-change-tracking.qbs"})), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running probe1"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in imported file that is not used in any rule or command. WAIT_FOR_NEW_TIMESTAMP(); touch("irrelevant.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in directly imported file only used by one prepare script. WAIT_FOR_NEW_TIMESTAMP(); touch("custom1prepare1.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in recursively imported file only used by one prepare script. WAIT_FOR_NEW_TIMESTAMP(); touch("custom1prepare2.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in imported file used only by one command. WAIT_FOR_NEW_TIMESTAMP(); touch("custom1command.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in file only used by one prepare script, using directory import. WAIT_FOR_NEW_TIMESTAMP(); touch("custom2prepare/custom2prepare2.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in file used only by one command, imported via search path. WAIT_FOR_NEW_TIMESTAMP(); touch("imports/custom2command/custom2command1.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe1 "), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in directly imported file only used by one Probe WAIT_FOR_NEW_TIMESTAMP(); touch("probe1.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running probe1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change in indirectly imported file only used by one Probe WAIT_FOR_NEW_TIMESTAMP(); touch("probe2.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running probe1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); // Change everything at once. WAIT_FOR_NEW_TIMESTAMP(); touch("irrelevant.js"); touch("custom1prepare1.js"); touch("custom1prepare2.js"); touch("custom1command.js"); touch("custom2prepare/custom2prepare1.js"); touch("imports/custom2command/custom2command2.js"); touch("probe2.js"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running probe1"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("running probe2"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData()); } void TestBlackbox::probesInNestedModules() { QDir::setCurrent(testDataDir + "/probes-in-nested-modules"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); QCOMPARE(m_qbsStdout.count("running probe a"), 1); QCOMPARE(m_qbsStdout.count("running probe b"), 1); QCOMPARE(m_qbsStdout.count("running probe c"), 1); QCOMPARE(m_qbsStdout.count("running second probe a"), 1); QVERIFY(m_qbsStdout.contains("product a, outer.somethingElse = goodbye")); QVERIFY(m_qbsStdout.contains("product b, inner.something = hahaha")); QVERIFY(m_qbsStdout.contains("product c, inner.something = hello")); QVERIFY(m_qbsStdout.contains("product a, inner.something = hahaha")); QVERIFY(m_qbsStdout.contains("product a, outer.something = hahaha")); } QTEST_MAIN(TestBlackbox) qbs-src-1.13.1/tests/auto/blackbox/tst_blackbox.h000066400000000000000000000233631347155106100217100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOX_H #define TST_BLACKBOX_H #include "tst_blackboxbase.h" class TestBlackbox : public TestBlackboxBase { Q_OBJECT public: TestBlackbox(); private slots: void addFileTagToGeneratedArtifact(); void alwaysRun(); void alwaysRun_data(); void artifactsMapChangeTracking(); void artifactsMapInvalidation(); void artifactsMapRaceCondition(); void artifactScanning(); void assembly(); void autotestWithDependencies(); void autotests_data(); void autotests(); void auxiliaryInputsFromDependencies(); void badInterpreter(); void bomSources(); void buildDataOfDisabledProduct(); void buildDirectories(); void buildEnvChange(); void buildGraphVersions(); void changedFiles_data(); void changedFiles(); void changedInputsFromDependencies(); void changedRuleInputs(); void changeInDisabledProduct(); void changeInImportedFile(); void changeTrackingAndMultiplexing(); void checkProjectFilePath(); void checkTimestamps(); void chooseModuleInstanceByPriority(); void chooseModuleInstanceByPriority_data(); void clean(); void cli(); void combinedSources(); void commandFile(); void compilerDefinesByLanguage(); void concurrentExecutor(); void conditionalExport(); void conditionalFileTagger(); void configure(); void conflictingArtifacts(); void cxxLanguageVersion(); void cxxLanguageVersion_data(); void cpuFeatures(); void dependenciesProperty(); void dependencyProfileMismatch(); void deprecatedProperty(); void disappearedProfile(); void discardUnusedData(); void discardUnusedData_data(); void driverLinkerFlags(); void driverLinkerFlags_data(); void dynamicLibraryInModule(); void dynamicMultiplexRule(); void dynamicProject(); void dynamicRuleOutputs(); void enableExceptions(); void enableExceptions_data(); void enableRtti(); void envMerging(); void envNormalization(); void erroneousFiles_data(); void erroneousFiles(); void errorInfo(); void escapedLinkerFlags(); void explicitlyDependsOn(); void explicitlyDependsOn_data(); void exportedDependencyInDisabledProduct(); void exportedDependencyInDisabledProduct_data(); void exportedPropertyInDisabledProduct(); void exportedPropertyInDisabledProduct_data(); void exportRule(); void exportToOutsideSearchPath(); void exportsPkgconfig(); void exportsQbs(); void externalLibs(); void fileDependencies(); void fileTagsFilterMerging(); void generatedArtifactAsInputToDynamicRule(); void generator(); void generator_data(); void groupsInModules(); void ico(); void importAssignment(); void importChangeTracking(); void importInPropertiesCondition(); void importSearchPath(); void importingProduct(); void importsConflict(); void includeLookup(); void innoSetup(); void innoSetupDependencies(); void inputTagsChangeTracking_data(); void inputTagsChangeTracking(); void inputsFromDependencies(); void installable(); void installableAsAuxiliaryInput(); void installedApp(); void installDuplicates(); void installDuplicatesNoError(); void installedSourceFiles(); void installedTransformerOutput(); void installLocations_data(); void installLocations(); void installPackage(); void installRootFromProjectFile(); void installTree(); void invalidCommandProperty_data(); void invalidCommandProperty(); void invalidExtensionInstantiation(); void invalidExtensionInstantiation_data(); void invalidInstallDir(); void invalidLibraryNames(); void invalidLibraryNames_data(); void jsExtensionsFile(); void jsExtensionsFileInfo(); void jsExtensionsProcess(); void jsExtensionsPropertyList(); void jsExtensionsTemporaryDir(); void jsExtensionsTextFile(); void jsExtensionsBinaryFile(); void ld(); void linkerMode(); void linkerVariant_data(); void linkerVariant(); void lexyacc(); void lexyaccOutputs(); void lexyaccOutputs_data(); void linkerScripts(); void listProducts(); void listPropertiesWithOuter(); void listPropertyOrder(); void loadableModule(); void localDeployment(); void makefileGenerator(); void maximumCLanguageVersion(); void maximumCxxLanguageVersion(); void moduleProviders(); void fallbackModuleProvider_data(); void fallbackModuleProvider(); void minimumSystemVersion(); void minimumSystemVersion_data(); void missingBuildGraph(); void missingBuildGraph_data(); void missingDependency(); void missingProjectFile(); void missingOverridePrefix(); void moduleConditions(); void movedFileDependency(); void multipleChanges(); void multipleConfigurations(); void multiplexedTool(); void nestedGroups(); void nestedProperties(); void newOutputArtifact(); void noExportedSymbols_data(); void noExportedSymbols(); void noProfile(); void noSuchProfile(); void nodejs(); void nonBrokenFilesInBrokenProduct(); void nonDefaultProduct(); void notAlwaysUpdated(); void nsis(); void nsisDependencies(); void outOfDateMarking(); void outputArtifactAutoTagging(); void overrideProjectProperties(); void pchChangeTracking(); void perGroupDefineInExportItem(); void pkgConfigProbe(); void pkgConfigProbe_data(); void pkgConfigProbeSysroot(); void pluginDependency(); void precompiledAndPrefixHeaders(); void preventFloatingPointValues(); void probeChangeTracking(); void probeProperties(); void probesAndShadowProducts(); void probeInExportedModule(); void probesAndArrayProperties(); void probesInNestedModules(); void productDependenciesByType(); void productProperties(); void propertyAssignmentOnNonPresentModule(); void propertyAssignmentInFailedModule(); void propertyChanges(); void propertyPrecedence(); void properQuoting(); void propertiesInExportItems(); void protobuf_data(); void protobuf(); void pseudoMultiplexing(); void qbsConfig(); void qbsVersion(); void qtBug51237(); void radAfterIncompleteBuild(); void radAfterIncompleteBuild_data(); void recursiveRenaming(); void recursiveWildcards(); void referenceErrorInExport(); void reproducibleBuild(); void reproducibleBuild_data(); void require(); void requireDeprecated(); void rescueTransformerData(); void responseFiles(); void retaggedOutputArtifact(); void ruleConditions(); void ruleConnectionWithExcludedInputs(); void ruleCycle(); void ruleWithNoInputs(); void ruleWithNonRequiredInputs(); void scannerItem(); void setupBuildEnvironment(); void setupRunEnvironment(); void smartRelinking(); void smartRelinking_data(); void soVersion(); void soVersion_data(); void sourceArtifactChanges(); void subProfileChangeTracking(); void successiveChanges(); void symbolLinkMode(); void symlinkRemoval(); void renameDependency(); void separateDebugInfo(); void sevenZip(); void sourceArtifactInInputsFromDependencies(); void staticLibWithoutSources(); void suspiciousCalls(); void suspiciousCalls_data(); void systemIncludePaths(); void systemRunPaths(); void systemRunPaths_data(); void tar(); void textTemplate(); void toolLookup(); void topLevelSearchPath(); void trackAddFile(); void trackAddFileTag(); void trackAddProduct(); void trackExternalProductChanges(); void trackGroupConditionChange(); void trackRemoveFile(); void trackRemoveFileTag(); void trackRemoveProduct(); void transitiveOptionalDependencies(); void typescript(); void usingsAsSoleInputsNonMultiplexed(); void variantSuffix(); void variantSuffix_data(); void vcsGit(); void vcsSubversion(); void versionCheck(); void versionCheck_data(); void versionScript(); void wholeArchive(); void wholeArchive_data(); void wildCardsAndRules(); void wildcardRenaming(); void wix(); void wixDependencies(); void zip(); void zip_data(); void zipInvalid(); private: QMap findCli(int *status); QMap findNodejs(int *status); QMap findTypeScript(int *status); QString findArchiver(const QString &fileName, int *status = nullptr); static bool lexYaccExist(); static qbs::Version bisonVersion(); }; #endif // TST_BLACKBOX_H qbs-src-1.13.1/tests/auto/blackbox/tst_blackboxandroid.cpp000066400000000000000000000531111347155106100235760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxandroid.h" #include "../shared.h" #include #include #include #include #include #include using qbs::Internal::none_of; using qbs::Profile; QMap TestBlackboxAndroid::findAndroid(int *status, const QString &profile) { QTemporaryDir temp; QDir::setCurrent(testDataDir + "/find"); QbsRunParameters params = QStringList({"-f", "find-android.qbs", "qbs.architecture:x86"}); params.profile = profile; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-android") + "/android.json"); if (!file.open(QIODevice::ReadOnly)) return {}; const auto tools = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); return { {"sdk", QDir::fromNativeSeparators(tools["sdk"].toString())}, {"sdk-build-tools-dx", QDir::fromNativeSeparators(tools["sdk-build-tools-dx"].toString())}, {"ndk", QDir::fromNativeSeparators(tools["ndk"].toString())}, {"ndk-samples", QDir::fromNativeSeparators(tools["ndk-samples"].toString())}, {"jar", QDir::fromNativeSeparators(tools["jar"].toString())}, }; } TestBlackboxAndroid::TestBlackboxAndroid() : TestBlackboxBase(SRCDIR "/testdata-android", "blackbox-android") { } static QString theProfileName(bool forQt) { return forQt ? "qbs_autotests-android-qt" : profileName(); } void TestBlackboxAndroid::android() { QFETCH(QString, projectDir); QFETCH(QStringList, productNames); QFETCH(QList, expectedFilesLists); QFETCH(QStringList, customProperties); const SettingsPtr s = settings(); Profile p(theProfileName(projectDir == "qml-app"), s.get()); if (!p.exists()) p = Profile("none", s.get()); int status; const auto androidPaths = findAndroid(&status, p.name()); QCOMPARE(status, 0); const auto sdkPath = androidPaths["sdk"]; if (sdkPath.isEmpty()) QSKIP("Android SDK is not installed"); const auto ndkPath = androidPaths["ndk"]; if (ndkPath.isEmpty() && projectDir != "no-native") QSKIP("Android NDK is not installed"); const auto ndkSamplesPath = androidPaths["ndk-samples"]; static const QStringList ndkSamplesDirs = QStringList() << "teapot" << "no-native"; if (!ndkPath.isEmpty() && !QFileInfo(ndkSamplesPath).isDir() && ndkSamplesDirs.contains(projectDir)) QSKIP("NDK samples directory not present"); QDir::setCurrent(testDataDir + "/" + projectDir); static const QStringList configNames { "debug", "release" }; for (const QString &configName : configNames) { auto currentExpectedFilesLists = expectedFilesLists; const QString configArgument = "config:" + configName; QbsRunParameters resolveParams("resolve"); resolveParams.arguments << configArgument << customProperties; resolveParams.profile = p.name(); QCOMPARE(runQbs(resolveParams), 0); QbsRunParameters buildParams(QStringList{"--command-echo-mode", "command-line", configArgument}); buildParams.profile = p.name(); QCOMPARE(runQbs(buildParams), 0); for (const QString &productName : qAsConst(productNames)) { const QByteArray tag(QTest::currentDataTag()); const bool isIncrementalBuild = tag.startsWith("qml app") && tag != "qml app"; QCOMPARE(m_qbsStdout.count("Generating BuildConfig.java"), isIncrementalBuild ? 0 : productNames.size()); QVERIFY(m_qbsStdout.contains(productName.toLocal8Bit() + ".apk")); const QString apkFilePath = relativeProductBuildDir(productName, configName) + '/' + productName + ".apk"; QVERIFY2(regularFileExists(apkFilePath), qPrintable(apkFilePath)); const QString jarFilePath = androidPaths["jar"]; QVERIFY(!jarFilePath.isEmpty()); QProcess jar; jar.start(jarFilePath, QStringList() << "-tf" << apkFilePath); QVERIFY2(jar.waitForStarted(), qPrintable(jar.errorString())); QVERIFY2(jar.waitForFinished(), qPrintable(jar.errorString())); QVERIFY2(jar.exitCode() == 0, qPrintable(jar.readAllStandardError().constData())); QByteArrayList actualFiles = jar.readAllStandardOutput().trimmed().split('\n'); for (QByteArray &f : actualFiles) f = f.trimmed(); QByteArrayList missingExpectedFiles; QByteArrayList expectedFiles = currentExpectedFilesLists.takeFirst(); for (const QByteArray &expectedFile : expectedFiles) { if (expectedFile.endsWith("/libgdbserver.so") && configName == "release") continue; auto it = std::find(actualFiles.begin(), actualFiles.end(), expectedFile); if (it != actualFiles.end()) { actualFiles.erase(it); continue; } missingExpectedFiles << expectedFile; } if (!missingExpectedFiles.empty()) QFAIL(QByteArray("missing expected files:\n") + missingExpectedFiles.join('\n')); if (!actualFiles.empty()) { QByteArray msg = "unexpected files encountered:\n" + actualFiles.join('\n'); auto isFileSharedObject = [](const QByteArray &f) { return f.endsWith(".so"); }; const auto isQmlToolingLib = [](const QByteArray &f) { return f.contains("qmltooling"); }; if (none_of(actualFiles, isFileSharedObject) || std::all_of(actualFiles.cbegin(), actualFiles.cend(), isQmlToolingLib)) { QWARN(msg); } else { QFAIL(msg); } } } if (projectDir == "multiple-libs-per-apk") { const auto dxPath = androidPaths["sdk-build-tools-dx"]; QVERIFY(!dxPath.isEmpty()); const auto lines = m_qbsStdout.split('\n'); const auto it = std::find_if(lines.cbegin(), lines.cend(), [&](const QByteArray &line) { return !line.isEmpty() && line.startsWith(dxPath.toUtf8()); }); QVERIFY2(it != lines.cend(), qPrintable(m_qbsStdout.constData())); const auto line = *it; QVERIFY2(line.contains("lib3.jar"), qPrintable(line.constData())); QVERIFY2(!line.contains("lib4.jar"), qPrintable(line.constData())); QVERIFY2(line.contains("lib5.jar"), qPrintable(line.constData())); QVERIFY2(line.contains("lib6.jar"), qPrintable(line.constData())); QVERIFY2(!line.contains("lib7.jar"), qPrintable(line.constData())); QVERIFY2(line.contains("lib8.jar"), qPrintable(line.constData())); } } } void TestBlackboxAndroid::android_data() { const SettingsPtr s = settings(); const Profile p(profileName(), s.get()); const Profile pQt(theProfileName(true), s.get()); QStringList archsStringList = p.value(QStringLiteral("qbs.architectures")).toStringList(); if (archsStringList.empty()) archsStringList << QStringLiteral("armv7a"); // must match default in common.qbs QByteArrayList archs; std::transform(archsStringList.begin(), archsStringList.end(), std::back_inserter(archs), [] (const QString &s) { return s.toUtf8().replace("armv7a", "armeabi-v7a") .replace("armv5te", "armeabi") .replace("arm64", "arm64-v8a"); }); const auto cxxLibPath = [&p, &pQt](const QByteArray &oldcxxLib, bool forQt) { const bool usesClang = (forQt ? pQt : p).value(QStringLiteral("qbs.toolchainType")) .toString() == "clang"; return QByteArray("lib/${ARCH}/") + (usesClang ? "libc++_shared.so" : oldcxxLib); }; const QByteArrayList archsForQt = { pQt.value("qbs.architecture").toString().toUtf8() }; QByteArrayList ndkArchsForQt = archsForQt; if (ndkArchsForQt.first() == "armv7a") ndkArchsForQt.first() = "armeabi-v7a"; else if (ndkArchsForQt.first() == "armv5te") ndkArchsForQt.first() = "armeabi"; else if (ndkArchsForQt.first() == "arm64") ndkArchsForQt.first() = "arm64-v8a"; auto expandArchs = [] (const QByteArrayList &archs, const QByteArrayList &lst) { const QByteArray &archPlaceHolder = "${ARCH}"; QByteArrayList result; for (const QByteArray &entry : lst) { if (entry.contains(archPlaceHolder)) { for (const QByteArray &arch : qAsConst(archs)) result << QByteArray(entry).replace(archPlaceHolder, arch); } else { result << entry; } } return result; }; const QByteArrayList commonFiles = expandArchs(archs, { "AndroidManifest.xml", "META-INF/ANDROIDD.RSA", "META-INF/ANDROIDD.SF", "META-INF/MANIFEST.MF", "classes.dex" }); QTest::addColumn("projectDir"); QTest::addColumn("productNames"); QTest::addColumn>("expectedFilesLists"); QTest::addColumn("customProperties"); QTest::newRow("teapot") << "teapot" << QStringList("TeapotNativeActivity") << (QList() << commonFiles + expandArchs(archs, { "resources.arsc", "assets/Shaders/ShaderPlain.fsh", "assets/Shaders/VS_ShaderPlain.vsh", "lib/${ARCH}/libgdbserver.so", cxxLibPath("libgnustl_shared.so", false), "lib/${ARCH}/libTeapotNativeActivity.so", "res/layout/widgets.xml"})) << QStringList(); QTest::newRow("minimal-native") << "minimal-native" << QStringList("minimalnative") << (QList() << commonFiles + expandArchs({archs.first()}, { "lib/${ARCH}/libminimalnative.so", cxxLibPath("libstlport_shared.so", false), "lib/${ARCH}/libdependency.so"})) << QStringList{"products.minimalnative.multiplexByQbsProperties:[]", "modules.qbs.architecture:" + archsStringList.first()}; QTest::newRow("qml app") << "qml-app" << QStringList("qmlapp") << (QList() << commonFiles + expandArchs(ndkArchsForQt, { "resources.arsc", "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes", "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir", "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes", "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir", "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", "lib/${ARCH}/libgdbserver.so", cxxLibPath("libgnustl_shared.so", true), "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so", "lib/${ARCH}/libplugins_imageformats_libqgif.so", "lib/${ARCH}/libplugins_imageformats_libqicns.so", "lib/${ARCH}/libplugins_imageformats_libqico.so", "lib/${ARCH}/libplugins_imageformats_libqjpeg.so", "lib/${ARCH}/libplugins_imageformats_libqtga.so", "lib/${ARCH}/libplugins_imageformats_libqtiff.so", "lib/${ARCH}/libplugins_imageformats_libqwbmp.so", "lib/${ARCH}/libplugins_imageformats_libqwebp.so", "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so", "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so", "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so", "lib/${ARCH}/libQt5Core.so", "lib/${ARCH}/libQt5Gui.so", "lib/${ARCH}/libQt5Network.so", "lib/${ARCH}/libQt5Qml.so", "lib/${ARCH}/libQt5QuickParticles.so", "lib/${ARCH}/libQt5Quick.so", "lib/${ARCH}/libqmlapp.so", "res/layout/splash.xml"})) << QStringList{"modules.Android.sdk.automaticSources:false", "modules.qbs.architecture:" + archsForQt.first()}; QTest::newRow("qml app using Ministro") << "qml-app" << QStringList("qmlapp") << (QList() << commonFiles + expandArchs(ndkArchsForQt, { "resources.arsc", "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", "lib/${ARCH}/libgdbserver.so", cxxLibPath("libgnustl_shared.so", true), "lib/${ARCH}/libqmlapp.so", "res/layout/splash.xml"})) << QStringList{"modules.Qt.android_support.useMinistro:true", "modules.Android.sdk.automaticSources:false"}; QTest::newRow("qml app with custom metadata") << "qml-app" << QStringList("qmlapp") << (QList() << commonFiles + expandArchs(ndkArchsForQt, { "resources.arsc", "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes", "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir", "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes", "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir", "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", "assets/dummyasset.txt", "lib/${ARCH}/libgdbserver.so", cxxLibPath("libgnustl_shared.so", true), "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so", "lib/${ARCH}/libplugins_imageformats_libqgif.so", "lib/${ARCH}/libplugins_imageformats_libqicns.so", "lib/${ARCH}/libplugins_imageformats_libqico.so", "lib/${ARCH}/libplugins_imageformats_libqjpeg.so", "lib/${ARCH}/libplugins_imageformats_libqtga.so", "lib/${ARCH}/libplugins_imageformats_libqtiff.so", "lib/${ARCH}/libplugins_imageformats_libqwbmp.so", "lib/${ARCH}/libplugins_imageformats_libqwebp.so", "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so", "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so", "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so", "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so", "lib/${ARCH}/libQt5Core.so", "lib/${ARCH}/libQt5Gui.so", "lib/${ARCH}/libQt5Network.so", "lib/${ARCH}/libQt5Qml.so", "lib/${ARCH}/libQt5QuickParticles.so", "lib/${ARCH}/libQt5Quick.so", "lib/${ARCH}/libqmlapp.so", "res/layout/splash.xml"})) << QStringList("modules.Android.sdk.automaticSources:true"); QTest::newRow("no native") << "no-native" << QStringList("com.example.android.basicmediadecoder") << (QList() << commonFiles + expandArchs(archs, { "resources.arsc", "res/drawable-hdpi-v4/ic_action_play_disabled.png", "res/drawable-hdpi-v4/ic_action_play.png", "res/drawable-hdpi-v4/ic_launcher.png", "res/drawable-hdpi-v4/tile.9.png", "res/drawable-mdpi-v4/ic_action_play_disabled.png", "res/drawable-mdpi-v4/ic_action_play.png", "res/drawable-mdpi-v4/ic_launcher.png", "res/drawable/selector_play.xml", "res/drawable-xhdpi-v4/ic_action_play_disabled.png", "res/drawable-xhdpi-v4/ic_action_play.png", "res/drawable-xhdpi-v4/ic_launcher.png", "res/drawable-xxhdpi-v4/ic_launcher.png", "res/layout/sample_main.xml", "res/menu/action_menu.xml", "res/menu-v11/action_menu.xml", "res/raw/vid_bigbuckbunny.mp4"})) << QStringList(); QTest::newRow("aidl") << "aidl" << QStringList("io.qbs.aidltest") << QList{commonFiles} << QStringList(); QTest::newRow("multiple libs") << "multiple-libs-per-apk" << QStringList("twolibs") << (QList() << commonFiles + expandArchs(archs, { "resources.arsc", "lib/${ARCH}/libgdbserver.so", "lib/${ARCH}/liblib1.so", "lib/${ARCH}/liblib2.so", cxxLibPath("libstlport_shared.so", false)})) << QStringList(); QByteArrayList expectedFiles1 = (commonFiles + expandArchs(QByteArrayList{"armeabi-v7a", "x86"}, { "resources.arsc", "lib/${ARCH}/libgdbserver.so", "lib/${ARCH}/libp1lib1.so", cxxLibPath("libstlport_shared.so", false)}) + expandArchs(QByteArrayList{archs}, { "resources.arsc", "lib/${ARCH}/libgdbserver.so", "lib/${ARCH}/libp1lib2.so", cxxLibPath("libstlport_shared.so", false)})).toSet().toList(); QByteArrayList expectedFiles2 = commonFiles + expandArchs(archs, { "lib/${ARCH}/libgdbserver.so", "lib/${ARCH}/libp2lib1.so", "lib/${ARCH}/libp2lib2.so", cxxLibPath("libstlport_shared.so", false)}); QTest::newRow("multiple apks") << "multiple-apks-per-project" << (QStringList() << "twolibs1" << "twolibs2") << QList{expectedFiles1, expectedFiles2} << QStringList(); } QTEST_MAIN(TestBlackboxAndroid) qbs-src-1.13.1/tests/auto/blackbox/tst_blackboxandroid.h000066400000000000000000000031011347155106100232350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOX_H #define TST_BLACKBOX_H #include "tst_blackboxbase.h" class TestBlackboxAndroid : public TestBlackboxBase { Q_OBJECT public: TestBlackboxAndroid(); private slots: void android(); void android_data(); private: QMap findAndroid(int *status, const QString &profile); }; #endif // TST_BLACKBOX_H qbs-src-1.13.1/tests/auto/blackbox/tst_blackboxapple.cpp000066400000000000000000001215051347155106100232620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxapple.h" #include "../shared.h" #include #include #include #include #include #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::Internal::HostOsInfo; using qbs::Profile; class QFileInfo2 : public QFileInfo { public: QFileInfo2(const QString &path) : QFileInfo(path) { } bool isRegularFile() const { return isFile() && !isSymLink(); } bool isRegularDir() const { return isDir() && !isSymLink(); } bool isFileSymLink() const { return isFile() && isSymLink(); } bool isDirSymLink() const { return isDir() && isSymLink(); } }; static QString getEmbeddedBinaryPlist(const QString &file) { QProcess p; p.start("otool", QStringList() << "-v" << "-X" << "-s" << "__TEXT" << "__info_plist" << file); p.waitForFinished(); return QString::fromUtf8(p.readAllStandardOutput()).trimmed(); } TestBlackboxApple::TestBlackboxApple() : TestBlackboxBase (SRCDIR "/testdata-apple", "blackbox-apple") { } void TestBlackboxApple::initTestCase() { if (!HostOsInfo::isMacosHost()) { QSKIP("only applies on macOS"); return; } TestBlackboxBase::initTestCase(); } void TestBlackboxApple::appleMultiConfig() { const auto xcodeVersion = findXcodeVersion(); const bool supportsX86 = xcodeVersion < qbs::Version(10); QDir::setCurrent(testDataDir + "/apple-multiconfig"); QCOMPARE(runQbs(QbsRunParameters(QStringList{ "qbs.installPrefix:''", QString("project.enableX86:") + (supportsX86 ? "true" : "false")})), 0); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/MacOS/singleapp").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/MacOS/singleapp_agg").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp_agg.app/Contents/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/singlelib").isFileSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Resources").isDirSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/singlelib").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/Resources").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/A/Resources/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singlelib.framework/Versions/Current").isDirSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/MacOS/multiapp").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multiapp.app/Contents/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/MacOS/fatmultiapp").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiapp.app/Contents/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" "fatmultiappmultivariant").isFileSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" "fatmultiappmultivariant_debug").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/MacOS/" "fatmultiappmultivariant_profile").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/Info.plist") .isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/fatmultiappmultivariant.app/Contents/PkgInfo") .isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/multilib").isFileSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Resources").isDirSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib_debug").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/multilib_profile").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/Resources").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/A/Resources/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/multilib.framework/Versions/Current").isDirSymLink()); for (const QString &variant : { "release", "debug", "profile" }) { for (const QString &arch : { "x86_64" }) { QProcess process; process.setProgram("/usr/bin/arch"); process.setArguments({ "-arch", arch, "-e", "DYLD_IMAGE_SUFFIX=_" + variant, defaultInstallRoot + "/multiapp.app/Contents/MacOS/multiapp" }); process.start(); process.waitForFinished(); QCOMPARE(process.exitCode(), 0); const auto processStdout = process.readAllStandardOutput(); QVERIFY2(processStdout.contains("Hello from " + variant.toUtf8() + " " + arch.toUtf8()), processStdout.constData()); } } } void TestBlackboxApple::aggregateDependencyLinking() { if (HostOsInfo::hostOsVersion() > qbs::Version(10, 13, 4)) QSKIP("32-bit arch build is no longer supported on macOS versions higher than 10.13.4."); QDir::setCurrent(testDataDir + "/aggregateDependencyLinking"); QCOMPARE(runQbs(QStringList{"-p", "multi_arch_lib"}), 0); QCOMPARE(runQbs(QStringList{"-p", "just_app", "--command-echo-mode", "command-line"}), 0); int linkedInLibrariesCount = QString::fromUtf8(m_qbsStdout).count(QStringLiteral("multi_arch_lib.a")); QCOMPARE(linkedInLibrariesCount, 1); } void TestBlackboxApple::assetCatalog() { QFETCH(bool, flatten); const auto xcodeVersion = findXcodeVersion(); QDir::setCurrent(testDataDir + QLatin1String("/ib/assetcatalog")); rmDirR(relativeBuildDir()); QbsRunParameters params; const auto v = HostOsInfo::hostOsVersion(); const QString flattens = "modules.ib.flatten:" + QString(flatten ? "true" : "false"); const QString macosTarget = "modules.cpp.minimumMacosVersion:'" + v.toString() + "'"; // Make sure a dry run does not write anything params.arguments = QStringList() << "-f" << "assetcatalogempty.qbs" << "--dry-run" << flattens << macosTarget; QCOMPARE(runQbs(params), 0); QVERIFY(!directoryExists(relativeBuildDir())); params.arguments = QStringList() << "-f" << "assetcatalogempty.qbs" << flattens << macosTarget; QCOMPARE(runQbs(params), 0); // empty asset catalogs must still produce output if (xcodeVersion >= qbs::Version(5)) QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); // should additionally produce raw assets since deployment target will be < 10.9 // older versions of ibtool generated either raw assets OR .car files; // newer versions always generate the .car file regardless of the deployment target if (v < qbs::Version(10, 9)) { QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/other.png")); QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/other@2x.png")); } rmDirR(relativeBuildDir()); params.arguments.push_back("modules.cpp.minimumMacosVersion:'10.10'"); // force CAR generation QCOMPARE(runQbs(params), 0); // empty asset catalogs must still produce output if (xcodeVersion >= qbs::Version(5)) { QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); // No matter what, we need a 10.9 host to build CAR files if (HostOsInfo::hostOsVersion() >= qbs::Version(10, 9)) { QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/Assets.car")); } else { QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/empty.icns")); QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/other.png")); QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/other@2x.png")); } } // this asset catalog happens to have an embedded icon set, // but this should NOT be built since it is not in the files list QVERIFY(!(bool)m_qbsStdout.contains(".iconset")); // now we'll add the iconset rmDirR(relativeBuildDir()); params.arguments.push_back("project.includeIconset:true"); QCOMPARE(runQbs(params), 0); QVERIFY(!(bool)m_qbsStdout.contains("compiling empty.xcassets")); QVERIFY((bool)m_qbsStdout.contains("compiling empty.iconset")); // make sure the nibs/storyboards are in there QString nib = relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/MainMenu.nib"; QStringList nibFiles; if (flatten) { QVERIFY(regularFileExists(nib)); } else { QVERIFY(directoryExists(nib)); nibFiles = QStringList() << "designable.nib" << "keyedobjects.nib"; } QString storyboardc = relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/Storyboard.storyboardc"; QStringList storyboardcFiles; if (HostOsInfo::hostOsVersion() >= qbs::Version(10, 10)) { QVERIFY(directoryExists(storyboardc)); storyboardcFiles = QStringList() << "1os-k8-h10-view-qKA-a5-eUe.nib" << "Info.plist" << "Iqk-Fi-Vhk-view-HRv-3O-Qxh.nib" << "Main.nib" << "NSViewController-Iqk-Fi-Vhk.nib" << "NSViewController-Yem-rc-72E.nib" << "Yem-rc-72E-view-ODp-aO-Dmf.nib"; if (!flatten) { storyboardcFiles << "designable.storyboard"; storyboardcFiles.sort(); } } QCOMPARE(QDir(nib).entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name), nibFiles); QCOMPARE(QDir(storyboardc).entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name), storyboardcFiles); QCOMPARE(runQbs(QbsRunParameters("clean")), 0); QCOMPARE(QDir(nib).entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name), QStringList()); QCOMPARE(QDir(storyboardc).entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name), QStringList()); } void TestBlackboxApple::assetCatalog_data() { QTest::addColumn("flatten"); QTest::newRow("flattened") << true; QTest::newRow("unflattened") << false; } void TestBlackboxApple::assetCatalogsEmpty() { if (findXcodeVersion() < qbs::Version(5)) QSKIP("requires Xcode 5 or above"); QDir::setCurrent(testDataDir + QLatin1String("/ib/empty-asset-catalogs")); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling assetcatalog1.xcassets"), m_qbsStdout); QVERIFY2(!m_qbsStdout.contains("compiling assetcatalog2.xcassets"), m_qbsStdout); } void TestBlackboxApple::assetCatalogsMultiple() { if (findXcodeVersion() < qbs::Version(5)) QSKIP("requires Xcode 5 or above"); QDir::setCurrent(testDataDir + QLatin1String("/ib/multiple-asset-catalogs")); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling assetcatalog1.xcassets"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("compiling assetcatalog2.xcassets"), m_qbsStdout); } void TestBlackboxApple::bundleStructure() { QFETCH(QString, productName); QFETCH(QString, productTypeIdentifier); QFETCH(bool, isShallow); QDir::setCurrent(testDataDir + "/bundle-structure"); QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); params.arguments << "project.buildableProducts:" + productName; if (isShallow) { // Coerce shallow bundles - don't set bundle.isShallow directly because we want to test the // automatic detection const auto xcode5 = findXcodeVersion() >= qbs::Version(5); params.arguments << "modules.qbs.targetPlatform:ios" << (xcode5 ? "qbs.architectures:arm64" : "qbs.architectures:armv7a"); } if (productName == "ABadApple" || productName == "ABadThirdParty") params.expectFailure = true; rmDirR(relativeBuildDir()); const int status = runQbs(params); if (status != 0) { QVERIFY2(m_qbsStderr.contains("Bundle product type " + productTypeIdentifier.toLatin1() + " is not supported."), m_qbsStderr.constData()); return; } QCOMPARE(status, 0); if (!isShallow) { if (productName == "A") { QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/MacOS").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/MacOS/A").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/Resources").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Contents/Resources/resource.txt").isRegularFile()); } if (productName == "B") { QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/B").isFileSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Headers").isDirSymLink()); //QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Modules").isDirSymLink()); QVERIFY(!QFileInfo2(defaultInstallRoot + "/B.framework/PkgInfo").exists()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/PrivateHeaders").isDirSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Resources").isDirSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/B").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Headers").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Headers/dummy.h").isRegularFile()); //QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Modules").isRegularDir()); //QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Modules/module.modulemap").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/PrivateHeaders").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/PrivateHeaders/dummy_p.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Resources").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/A/Resources/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Versions/Current").isDirSymLink()); } if (productName == "C") { QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/C").isFileSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Headers").isDirSymLink()); //QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Modules").isDirSymLink()); QVERIFY(!QFileInfo2(defaultInstallRoot + "/C.framework/PkgInfo").exists()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/PrivateHeaders").isDirSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Resources").isDirSymLink()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/C").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Headers").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Headers/dummy.h").isRegularFile()); //QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Modules").isRegularDir()); //QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Modules/module.modulemap").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/PrivateHeaders").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/PrivateHeaders/dummy_p.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Resources").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/A/Resources/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Versions/Current").isDirSymLink()); } if (productName == "D") { QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/MacOS").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/MacOS/D").isRegularFile()); QVERIFY(!QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/PkgInfo").exists()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/Resources").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Contents/Resources/resource.txt").isRegularFile()); } if (productName == "E") { QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents/MacOS").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents/MacOS/E").isRegularFile()); QVERIFY(!QFileInfo2(defaultInstallRoot + "/E.appex/Contents/PkgInfo").exists()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents/Resources").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Contents/Resources/resource.txt").isRegularFile()); } if (productName == "F") { QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/MacOS").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/MacOS/F").isRegularFile()); QVERIFY(!QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/PkgInfo").exists()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/Resources").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Contents/Resources/resource.txt").isRegularFile()); } if (productName == "G") { QVERIFY(QFileInfo2(defaultInstallRoot + "/G").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/G/ContentInfo.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/G/Contents/resource.txt").isRegularFile()); } } else { if (productName == "A") { QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/A").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/Info.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/PkgInfo").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/A.app/resource.txt").isRegularFile()); } if (productName == "B") { QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/B").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Headers").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Headers/dummy.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Info.plist").isRegularFile()); //QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Modules").isRegularDir()); //QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/Modules/module.modulemap").isRegularFile()); QVERIFY(!QFileInfo2(defaultInstallRoot + "/B.framework/PkgInfo").exists()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/PrivateHeaders").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/PrivateHeaders/dummy_p.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/B.framework/resource.txt").isRegularFile()); } if (productName == "C") { QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/C").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Headers").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Headers/dummy.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Info.plist").isRegularFile()); //QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Modules").isRegularDir()); //QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/Modules/module.modulemap").isRegularFile()); QVERIFY(!QFileInfo2(defaultInstallRoot + "/C.framework/PkgInfo").exists()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/PrivateHeaders").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/PrivateHeaders/dummy_p.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/C.framework/resource.txt").isRegularFile()); } if (productName == "D") { QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/D").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Headers").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Headers/dummy.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/Info.plist").isRegularFile()); QVERIFY(!QFileInfo2(defaultInstallRoot + "/D.bundle/PkgInfo").exists()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/PrivateHeaders").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/PrivateHeaders/dummy_p.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/D.bundle/resource.txt").isRegularFile()); } if (productName == "E") { QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/E").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Headers").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Headers/dummy.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/Info.plist").isRegularFile()); QVERIFY(!QFileInfo2(defaultInstallRoot + "/E.appex/PkgInfo").exists()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/PrivateHeaders").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/PrivateHeaders/dummy_p.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/E.appex/resource.txt").isRegularFile()); } if (productName == "F") { QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/F").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Headers").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Headers/dummy.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/Info.plist").isRegularFile()); QVERIFY(!QFileInfo2(defaultInstallRoot + "/F.xpc/PkgInfo").exists()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/PrivateHeaders").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/PrivateHeaders/dummy_p.h").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/F.xpc/resource.txt").isRegularFile()); } if (productName == "G") { QVERIFY(QFileInfo2(defaultInstallRoot + "/G").isRegularDir()); QVERIFY(QFileInfo2(defaultInstallRoot + "/G/ContentInfo.plist").isRegularFile()); QVERIFY(QFileInfo2(defaultInstallRoot + "/G/Contents/resource.txt").isRegularFile()); } } } void TestBlackboxApple::bundleStructure_data() { QTest::addColumn("productName"); QTest::addColumn("productTypeIdentifier"); QTest::addColumn("isShallow"); const auto addRows = [](bool isShallow) { const QString s = (isShallow ? " shallow" : ""); QTest::newRow(("A" + s).toLatin1()) << "A" << "com.apple.product-type.application" << isShallow; QTest::newRow(("ABadApple" + s).toLatin1()) << "ABadApple" << "com.apple.product-type.will.never.exist.ever.guaranteed" << isShallow; QTest::newRow(("ABadThirdParty" + s).toLatin1()) << "ABadThirdParty" << "org.special.third.party.non.existent.product.type" << isShallow; QTest::newRow(("B" + s).toLatin1()) << "B" << "com.apple.product-type.framework" << isShallow; QTest::newRow(("C" + s).toLatin1()) << "C" << "com.apple.product-type.framework.static" << isShallow; QTest::newRow(("D" + s).toLatin1()) << "D" << "com.apple.product-type.bundle" << isShallow; QTest::newRow(("E" + s).toLatin1()) << "E" << "com.apple.product-type.app-extension" << isShallow; QTest::newRow(("F" + s).toLatin1()) << "F" << "com.apple.product-type.xpc-service" << isShallow; QTest::newRow(("G" + s).toLatin1()) << "G" << "com.apple.product-type.in-app-purchase-content" << isShallow; }; addRows(true); addRows(false); } void TestBlackboxApple::deploymentTarget() { QFETCH(QString, sdk); QFETCH(QString, os); QFETCH(QString, arch); QFETCH(QString, cflags); QFETCH(QString, lflags); QDir::setCurrent(testDataDir + "/deploymentTarget"); QbsRunParameters params; params.arguments = QStringList() << "--command-echo-mode" << "command-line" << "modules.qbs.targetPlatform:" + os << "qbs.architectures:" + arch; rmDirR(relativeBuildDir()); int status = runQbs(params); const QStringList skippableMessages = QStringList() << "There is no matching SDK available for " + sdk + "." << "x86_64h will be mis-detected as x86_64 with Apple Clang < 6.0" << "clang: error: unknown argument: '-mtvos-version-min" << "clang: error: unknown argument: '-mtvos-simulator-version-min" << "clang: error: unknown argument: '-mwatchos-version-min" << "clang: error: unknown argument: '-mwatchos-simulator-version-min"; if (status != 0) { for (const auto &message : skippableMessages) { if (m_qbsStderr.contains(message.toUtf8())) QSKIP(message.toUtf8()); } } QCOMPARE(status, 0); QVERIFY2(m_qbsStderr.contains(cflags.toLatin1()), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains(lflags.toLatin1()), m_qbsStderr.constData()); } void TestBlackboxApple::deploymentTarget_data() { static const QString macos = QStringLiteral("macos"); static const QString ios = QStringLiteral("ios"); static const QString ios_sim = QStringLiteral("ios-simulator"); static const QString tvos = QStringLiteral("tvos"); static const QString tvos_sim = QStringLiteral("tvos-simulator"); static const QString watchos = QStringLiteral("watchos"); static const QString watchos_sim = QStringLiteral("watchos-simulator"); QTest::addColumn("sdk"); QTest::addColumn("os"); QTest::addColumn("arch"); QTest::addColumn("cflags"); QTest::addColumn("lflags"); const auto xcodeVersion = findXcodeVersion(); if (xcodeVersion < qbs::Version(10)) { QTest::newRow("macos x86") << "macosx" << macos << "x86" << "-triple i386-apple-macosx10.6" << "-macosx_version_min 10.6"; } QTest::newRow("macos x86_64") << "macosx" << macos << "x86_64" << "-triple x86_64-apple-macosx10.6" << "-macosx_version_min 10.6"; if (xcodeVersion >= qbs::Version(6)) QTest::newRow("macos x86_64h") << "macosx" << macos << "x86_64h" << "-triple x86_64h-apple-macosx10.12" << "-macosx_version_min 10.12"; QTest::newRow("ios armv7a") << "iphoneos" << ios << "armv7a" << "-triple thumbv7-apple-ios6.0" << "-iphoneos_version_min 6.0"; QTest::newRow("ios armv7s") << "iphoneos" <= qbs::Version(5)) QTest::newRow("ios arm64") << "iphoneos" <= qbs::Version(5)) QTest::newRow("ios-simulator x86_64") << "iphonesimulator" << ios_sim << "x86_64" << "-triple x86_64-apple-ios7.0" << "-ios_simulator_version_min 7.0"; if (xcodeVersion >= qbs::Version(7)) { if (xcodeVersion >= qbs::Version(7, 1)) { QTest::newRow("tvos arm64") << "appletvos" << tvos << "arm64" << "-triple arm64-apple-tvos9.0" << "-tvos_version_min 9.0"; QTest::newRow("tvos-simulator x86_64") << "appletvsimulator" << tvos_sim << "x86_64" << "-triple x86_64-apple-tvos9.0" << "-tvos_simulator_version_min 9.0"; } QTest::newRow("watchos armv7k") << "watchos" << watchos << "armv7k" << "-triple thumbv7k-apple-watchos2.0" << "-watchos_version_min 2.0"; QTest::newRow("watchos-simulator x86") << "watchsimulator" << watchos_sim << "x86" << "-triple i386-apple-watchos2.0" << "-watchos_simulator_version_min 2.0"; } } void TestBlackboxApple::dmg() { QDir::setCurrent(testDataDir + "/apple-dmg"); QCOMPARE(runQbs(), 0); } void TestBlackboxApple::embedInfoPlist() { QDir::setCurrent(testDataDir + QLatin1String("/embedInfoPlist")); QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); QCOMPARE(runQbs(params), 0); QVERIFY(!getEmbeddedBinaryPlist(defaultInstallRoot + "/app").isEmpty()); QVERIFY(!getEmbeddedBinaryPlist(defaultInstallRoot + "/liblib.dylib").isEmpty()); QVERIFY(!getEmbeddedBinaryPlist(defaultInstallRoot + "/mod.bundle").isEmpty()); params.arguments = QStringList(QLatin1String("modules.bundle.embedInfoPlist:false")); params.expectFailure = true; rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); QVERIFY(getEmbeddedBinaryPlist(defaultInstallRoot + "/app").isEmpty()); QVERIFY(getEmbeddedBinaryPlist(defaultInstallRoot + "/liblib.dylib").isEmpty()); QVERIFY(getEmbeddedBinaryPlist(defaultInstallRoot + "/mod.bundle").isEmpty()); } void TestBlackboxApple::frameworkStructure() { QDir::setCurrent(testDataDir + QLatin1String("/frameworkStructure")); QbsRunParameters params; QCOMPARE(runQbs(params), 0); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Widget")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Headers/Widget.h")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/PrivateHeaders/WidgetPrivate.h")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Resources/BaseResource")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Resources/en.lproj/EnglishResource")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/Current")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Widget")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Resources")); params.command = "resolve"; params.arguments = QStringList() << "project.includeHeaders:false"; QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(), 0); QVERIFY(!directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers")); QVERIFY(!directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders")); } void TestBlackboxApple::iconset() { QDir::setCurrent(testDataDir + QLatin1String("/ib/iconset")); QbsRunParameters params; params.arguments = QStringList() << "-f" << "iconset.qbs"; QCOMPARE(runQbs(params), 0); QVERIFY(regularFileExists(relativeProductBuildDir("iconset") + "/white.icns")); } void TestBlackboxApple::iconsetApp() { QDir::setCurrent(testDataDir + QLatin1String("/ib/iconsetapp")); QbsRunParameters params; params.arguments = QStringList() << "-f" << "iconsetapp.qbs"; QCOMPARE(runQbs(params), 0); QVERIFY(regularFileExists(relativeProductBuildDir("iconsetapp") + "/iconsetapp.app/Contents/Resources/white.icns")); } void TestBlackboxApple::infoPlist() { QDir::setCurrent(testDataDir + "/infoplist"); QbsRunParameters params; params.arguments = QStringList() << "-f" << "infoplist.qbs"; QCOMPARE(runQbs(params), 0); QFile infoplist(relativeProductBuildDir("infoplist") + "/infoplist.app/Contents/Info.plist"); QVERIFY(infoplist.open(QIODevice::ReadOnly)); const QByteArray fileContents = infoplist.readAll(); QVERIFY2(fileContents.contains("LSMinimumSystemVersion"), fileContents.constData()); QVERIFY2(fileContents.contains("10.7"), fileContents.constData()); QVERIFY2(fileContents.contains("NSPrincipalClass"), fileContents.constData()); } void TestBlackboxApple::objcArc() { QDir::setCurrent(testDataDir + QLatin1String("/objc-arc")); QCOMPARE(runQbs(), 0); } void TestBlackboxApple::xcode() { QProcess xcodeSelect; xcodeSelect.start("xcode-select", QStringList() << "--print-path"); QVERIFY2(xcodeSelect.waitForStarted(), qPrintable(xcodeSelect.errorString())); QVERIFY2(xcodeSelect.waitForFinished(), qPrintable(xcodeSelect.errorString())); QVERIFY2(xcodeSelect.exitCode() == 0, qPrintable(xcodeSelect.readAllStandardError().constData())); const QString developerPath(QString::fromLocal8Bit(xcodeSelect.readAllStandardOutput().trimmed())); std::multimap sdks; QProcess xcodebuildShowSdks; xcodebuildShowSdks.start("xcrun", QStringList() << "xcodebuild" << "-showsdks"); QVERIFY2(xcodebuildShowSdks.waitForStarted(), qPrintable(xcodebuildShowSdks.errorString())); QVERIFY2(xcodebuildShowSdks.waitForFinished(), qPrintable(xcodebuildShowSdks.errorString())); QVERIFY2(xcodebuildShowSdks.exitCode() == 0, qPrintable(xcodebuildShowSdks.readAllStandardError().constData())); for (const QString &line : QString::fromLocal8Bit(xcodebuildShowSdks.readAllStandardOutput().trimmed()).split('\n', QString::SkipEmptyParts)) { static const std::regex regexp("^.+\\s+\\-sdk\\s+([a-z]+)([0-9]+\\.[0-9]+)$"); const auto ln = line.toStdString(); std::smatch match; if (std::regex_match(ln, match, regexp)) sdks.insert({ match[1], match[2] }); } auto range = sdks.equal_range("macosx"); QStringList sdkValues; for (auto i = range.first; i != range.second; ++i) sdkValues.push_back(QString::fromStdString(i->second)); QDir::setCurrent(testDataDir + "/xcode"); QbsRunParameters params; params.arguments = (QStringList() << (QStringLiteral("modules.xcode.developerPath:") + developerPath) << (QStringLiteral("project.sdks:['") + sdkValues.join("','") + "']")); QCOMPARE(runQbs(params), 0); } QTEST_MAIN(TestBlackboxApple) QVariantMap TestBlackboxApple::findXcode(int *status) { QTemporaryDir temp; QbsRunParameters params = QStringList({"-f", testDataDir + "/find/find-xcode.qbs"}); params.profile = "none"; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-xcode") + "/xcode.json"); if (!file.open(QIODevice::ReadOnly)) return {}; return QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); } qbs::Version TestBlackboxApple::findXcodeVersion() { return qbs::Version::fromString(findXcode().value("version").toString()); } qbs-src-1.13.1/tests/auto/blackbox/tst_blackboxapple.h000066400000000000000000000041661347155106100227320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOXAPPLE_H #define TST_BLACKBOXAPPLE_H #include "tst_blackboxbase.h" namespace qbs { class Version; } // namespace qbs class TestBlackboxApple : public TestBlackboxBase { Q_OBJECT public: TestBlackboxApple(); public slots: void initTestCase() override; private slots: void appleMultiConfig(); void aggregateDependencyLinking(); void assetCatalog(); void assetCatalog_data(); void assetCatalogsEmpty(); void assetCatalogsMultiple(); void bundleStructure(); void bundleStructure_data(); void deploymentTarget(); void deploymentTarget_data(); void dmg(); void embedInfoPlist(); void frameworkStructure(); void iconset(); void iconsetApp(); void infoPlist(); void objcArc(); void xcode(); private: QVariantMap findXcode(int *status = nullptr); qbs::Version findXcodeVersion(); }; #endif // TST_BLACKBOXAPPLE_H qbs-src-1.13.1/tests/auto/blackbox/tst_blackboxbase.cpp000066400000000000000000000211361347155106100230720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxbase.h" #include "../shared.h" #include #include #include #include #include #include #include using qbs::Internal::HostOsInfo; using qbs::Internal::removeDirectoryWithContents; using qbs::InstallOptions; using qbs::Profile; static QString initQbsExecutableFilePath() { const QString qbsInstallDir = QString::fromLocal8Bit(qgetenv("QBS_INSTALL_DIR")); return HostOsInfo::appendExecutableSuffix(QDir::cleanPath(!qbsInstallDir.isEmpty() ? qbsInstallDir + QLatin1String("/bin/qbs") : QCoreApplication::applicationDirPath() + QLatin1String("/qbs"))); } static bool supportsBuildDirectoryOption(const QString &command) { return !(QStringList() << "help" << "config" << "config-ui" << "setup-android" << "setup-qt" << "setup-toolchains" << "create-project") .contains(command); } static bool supportsSettingsDirOption(const QString &command) { return !(QStringList() << "help" << "create-project").contains(command); } TestBlackboxBase::TestBlackboxBase(const QString &testDataSrcDir, const QString &testName) : testDataDir(testWorkDir(testName)), testSourceDir(QDir::cleanPath(testDataSrcDir)), qbsExecutableFilePath(initQbsExecutableFilePath()), defaultInstallRoot(relativeBuildDir() + QLatin1Char('/') + InstallOptions::defaultInstallRoot()) { QLocale::setDefault(QLocale::c()); } int TestBlackboxBase::runQbs(const QbsRunParameters ¶ms) { QStringList args; if (!params.command.isEmpty()) args << params.command; if (!params.settingsDir.isEmpty() && supportsSettingsDirOption(params.command)) args << "--settings-dir" << params.settingsDir; if (supportsBuildDirectoryOption(params.command)) { args.push_back(QStringLiteral("-d")); args.push_back(params.buildDirectory.isEmpty() ? QStringLiteral(".") : params.buildDirectory); } args << params.arguments; const bool commandImpliesResolve = params.command.isEmpty() || params.command == "resolve" || params.command == "build" || params.command == "install" || params.command == "run" || params.command == "generate"; if (!params.profile.isEmpty() && commandImpliesResolve) { args.push_back(QLatin1String("profile:") + params.profile); } QProcess process; if (!params.workingDir.isEmpty()) process.setWorkingDirectory(params.workingDir); process.setProcessEnvironment(params.environment); process.start(qbsExecutableFilePath, args); if (!process.waitForStarted() || !process.waitForFinished(testTimeoutInMsecs()) || process.exitStatus() != QProcess::NormalExit) { m_qbsStderr = process.readAllStandardError(); if (!params.expectCrash) { QTest::qFail("qbs did not run correctly", __FILE__, __LINE__); qDebug("%s", qPrintable(process.errorString())); } return -1; } m_qbsStderr = process.readAllStandardError(); m_qbsStdout = process.readAllStandardOutput(); sanitizeOutput(&m_qbsStderr); sanitizeOutput(&m_qbsStdout); const bool shouldLog = (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) && !params.expectFailure; if (!m_qbsStderr.isEmpty() && (shouldLog || qEnvironmentVariableIsSet("QBS_AUTOTEST_ALWAYS_LOG_STDERR"))) qDebug("%s", m_qbsStderr.constData()); if (!m_qbsStdout.isEmpty() && (shouldLog || qEnvironmentVariableIsSet("QBS_AUTOTEST_ALWAYS_LOG_STDOUT"))) qDebug("%s", m_qbsStdout.constData()); return process.exitCode(); } /*! Recursive copy from directory to another. Note that this updates the file stamps on Linux but not on Windows. */ void TestBlackboxBase::ccp(const QString &sourceDirPath, const QString &targetDirPath) { QDir currentDir; QDirIterator dit(sourceDirPath, QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden); while (dit.hasNext()) { dit.next(); const QString targetPath = targetDirPath + QLatin1Char('/') + dit.fileName(); currentDir.mkpath(targetPath); ccp(dit.filePath(), targetPath); } QDirIterator fit(sourceDirPath, QDir::Files | QDir::Hidden); while (fit.hasNext()) { fit.next(); const QString targetPath = targetDirPath + QLatin1Char('/') + fit.fileName(); QFile::remove(targetPath); // allowed to fail QFile src(fit.filePath()); QVERIFY2(src.copy(targetPath), qPrintable(src.errorString())); } } void TestBlackboxBase::rmDirR(const QString &dir) { QString errorMessage; removeDirectoryWithContents(dir, &errorMessage); } QByteArray TestBlackboxBase::unifiedLineEndings(const QByteArray &ba) { if (HostOsInfo::isWindowsHost()) { QByteArray result; result.reserve(ba.size()); for (const char &c : ba) { if (c != '\r') result.append(c); } return result; } else { return ba; } } void TestBlackboxBase::sanitizeOutput(QByteArray *ba) { if (HostOsInfo::isWindowsHost()) ba->replace('\r', ""); } void TestBlackboxBase::initTestCase() { QVERIFY(regularFileExists(qbsExecutableFilePath)); const SettingsPtr s = settings(); if (profileName() != "none" && !s->profiles().contains(profileName())) QFAIL(QByteArray("The build profile '" + profileName().toLocal8Bit() + "' could not be found. Please set it up on your machine.")); validateTestProfile(); // Initialize the test data directory. QVERIFY(testDataDir != testSourceDir); rmDirR(testDataDir); QDir().mkpath(testDataDir); ccp(testSourceDir, testDataDir); QDir().mkpath(testDataDir + "/find"); ccp(testSourceDir + "/../find", testDataDir + "/find"); QVERIFY(copyDllExportHeader(testSourceDir, testDataDir)); } QString TestBlackboxBase::findExecutable(const QStringList &fileNames) { const QStringList path = QString::fromLocal8Bit(qgetenv("PATH")) .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); for (const QString &fileName : fileNames) { QFileInfo fi(fileName); if (fi.isAbsolute()) return fi.exists() ? fileName : QString(); for (const QString &ppath : path) { const QString fullPath = HostOsInfo::appendExecutableSuffix(ppath + QLatin1Char('/') + fileName); if (QFileInfo(fullPath).exists()) return QDir::cleanPath(fullPath); } } return {}; } QMap TestBlackboxBase::findJdkTools(int *status) { QTemporaryDir temp; QDir::setCurrent(testDataDir + "/find"); QbsRunParameters params = QStringList() << "-f" << "find-jdk.qbs"; params.buildDirectory = temp.path(); const int res = runQbs(params); if (status) *status = res; QFile file(temp.path() + "/" + relativeProductBuildDir("find-jdk") + "/jdk.json"); if (!file.open(QIODevice::ReadOnly)) return {}; const auto tools = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); return { {"java", QDir::fromNativeSeparators(tools["java"].toString())}, {"javac", QDir::fromNativeSeparators(tools["javac"].toString())}, {"jar", QDir::fromNativeSeparators(tools["jar"].toString())} }; } qbs-src-1.13.1/tests/auto/blackbox/tst_blackboxbase.h000066400000000000000000000060471347155106100225430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOXBASE_H #define TST_BLACKBOXBASE_H #include "../shared.h" #include #include #include class QbsRunParameters { public: QbsRunParameters() { init(); } QbsRunParameters(const QString &cmd, const QStringList &args = QStringList()) : command(cmd), arguments(args) { init(); } QbsRunParameters(const QStringList &args) : arguments(args) { init(); } void init() { expectFailure = false; expectCrash = false; profile = profileName(); settingsDir = settings()->baseDirectory(); environment = QProcessEnvironment::systemEnvironment(); } QString command; QStringList arguments; QString buildDirectory; QProcessEnvironment environment; QString profile; QString settingsDir; QString workingDir; bool expectFailure; bool expectCrash; }; class TestBlackboxBase : public QObject { Q_OBJECT public: TestBlackboxBase(const QString &testDataSrcDir, const QString &testName); public slots: virtual void initTestCase(); protected: virtual void validateTestProfile() { } int runQbs(const QbsRunParameters ¶ms = QbsRunParameters()); void rmDirR(const QString &dir); static QByteArray unifiedLineEndings(const QByteArray &ba); static void sanitizeOutput(QByteArray *ba); static void ccp(const QString &sourceDirPath, const QString &targetDirPath); static QString findExecutable(const QStringList &fileNames); QMap findJdkTools(int *status); const QString testDataDir; const QString testSourceDir; const QString qbsExecutableFilePath; const QString defaultInstallRoot; QByteArray m_qbsStderr; QByteArray m_qbsStdout; }; #endif // TST_BLACKBOXBASE_H qbs-src-1.13.1/tests/auto/blackbox/tst_blackboxjava.cpp000066400000000000000000000237021347155106100231020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxjava.h" #include "../shared.h" #include #include #include #include #include using qbs::Internal::HostOsInfo; using qbs::Profile; TestBlackboxJava::TestBlackboxJava() : TestBlackboxBase (SRCDIR "/testdata-java", "blackbox-java") { } static QProcessEnvironment processEnvironmentWithCurrentDirectoryInLibraryPath() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(HostOsInfo::libraryPathEnvironmentVariable(), (QStringList() << env.value(HostOsInfo::libraryPathEnvironmentVariable()) << ".") .join(HostOsInfo::pathListSeparator())); return env; } void TestBlackboxJava::java() { #if defined(Q_OS_WIN32) && !defined(Q_OS_WIN64) QSKIP("QTBUG-3845"); #endif const SettingsPtr s = settings(); Profile p(profileName(), s.get()); int status; const auto jdkTools = findJdkTools(&status); QCOMPARE(status, 0); QDir::setCurrent(testDataDir + "/java"); status = runQbs(); if (p.value("java.jdkPath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("jdkPath")) { QSKIP("java.jdkPath not set and automatic detection failed"); } QCOMPARE(status, 0); const QStringList classFiles = QStringList() << "Jet" << "Ship" << "Vehicles"; QStringList classFiles1 = QStringList(classFiles) << "io/qt/qbs/HelloWorld" << "NoPackage"; for (QString &classFile : classFiles1) { classFile = relativeProductBuildDir("cc") + "/classes/" + classFile + ".class"; QVERIFY2(regularFileExists(classFile), qPrintable(classFile)); } for (const QString &classFile : classFiles) { const QString filePath = relativeProductBuildDir("jar_file") + "/classes/" + classFile + ".class"; QVERIFY2(regularFileExists(filePath), qPrintable(filePath)); } const QString jarFilePath = relativeProductBuildDir("jar_file") + '/' + "jar_file.jar"; QVERIFY2(regularFileExists(jarFilePath), qPrintable(jarFilePath)); // Now check whether we correctly predicted the class file output paths. QCOMPARE(runQbs(QbsRunParameters("clean")), 0); for (const QString &classFile : qAsConst(classFiles1)) { QVERIFY2(!regularFileExists(classFile), qPrintable(classFile)); } // This tests various things: java.manifestClassPath, JNI, etc. QDir::setCurrent(relativeBuildDir() + "/install-root"); QProcess process; process.setProcessEnvironment(processEnvironmentWithCurrentDirectoryInLibraryPath()); process.start(HostOsInfo::appendExecutableSuffix(jdkTools["java"]), QStringList() << "-jar" << "jar_file.jar"); if (process.waitForStarted()) { QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); QVERIFY2(process.exitCode() == 0, process.readAllStandardError().constData()); const QByteArray stdOut = process.readAllStandardOutput(); QVERIFY2(stdOut.contains("Driving!"), stdOut.constData()); QVERIFY2(stdOut.contains("Flying!"), stdOut.constData()); QVERIFY2(stdOut.contains("Flying (this is a space ship)!"), stdOut.constData()); QVERIFY2(stdOut.contains("Sailing!"), stdOut.constData()); QVERIFY2(stdOut.contains("Native code performing complex internal combustion process ("), stdOut.constData()); } process.start("unzip", QStringList() << "-p" << "jar_file.jar"); if (process.waitForStarted()) { QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); const QByteArray stdOut = process.readAllStandardOutput(); QVERIFY2(stdOut.contains("Class-Path: car_jar.jar random_stuff.jar"), stdOut.constData()); QVERIFY2(stdOut.contains("Main-Class: Vehicles"), stdOut.constData()); QVERIFY2(stdOut.contains("Some-Property: Some-Value"), stdOut.constData()); QVERIFY2(stdOut.contains("Additional-Property: Additional-Value"), stdOut.constData()); QVERIFY2(stdOut.contains("Extra-Property: Crazy-Value"), stdOut.constData()); } } static QString dpkgArch(const QString &prefix = QString()) { QProcess dpkg; dpkg.start("/usr/bin/dpkg", QStringList() << "--print-architecture"); dpkg.waitForFinished(); if (dpkg.exitStatus() == QProcess::NormalExit && dpkg.exitCode() == 0) return prefix + QString::fromLocal8Bit(dpkg.readAllStandardOutput().trimmed()); return {}; } void TestBlackboxJava::javaDependencyTracking() { QFETCH(QString, jdkPath); QFETCH(QString, javaVersion); QDir::setCurrent(testDataDir + "/java"); QbsRunParameters rp; rp.arguments.push_back("--check-outputs"); if (!jdkPath.isEmpty()) rp.arguments << ("modules.java.jdkPath:" + jdkPath); if (!javaVersion.isEmpty()) rp.arguments << ("modules.java.languageVersion:'" + javaVersion + "'"); rmDirR(relativeBuildDir()); const bool defaultJdkPossiblyTooOld = jdkPath.isEmpty() && !javaVersion.isEmpty(); rp.expectFailure = defaultJdkPossiblyTooOld; QVERIFY(runQbs(rp) == 0 || (defaultJdkPossiblyTooOld && m_qbsStderr.contains("invalid source release"))); } void TestBlackboxJava::javaDependencyTracking_data() { QTest::addColumn("jdkPath"); QTest::addColumn("javaVersion"); const SettingsPtr s = settings(); Profile p(profileName(), s.get()); auto getSpecificJdkVersion = [](const QString &jdkVersion) -> QString { if (HostOsInfo::isMacosHost()) { QProcess java_home; java_home.start("/usr/libexec/java_home", QStringList() << "--version" << jdkVersion); java_home.waitForFinished(); if (java_home.exitStatus() == QProcess::NormalExit && java_home.exitCode() == 0) return QString::fromLocal8Bit(java_home.readAllStandardOutput().trimmed()); } else if (HostOsInfo::isWindowsHost()) { QSettings settings("HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\" + jdkVersion, QSettings::NativeFormat); return settings.value("JavaHome").toString(); } else { QString minorVersion = jdkVersion; if (minorVersion.startsWith("1.")) minorVersion.remove(0, 2); const QStringList searchPaths = { "/usr/lib/jvm/java-" + minorVersion + "-openjdk" + dpkgArch("-"), // Debian "/usr/lib/jvm/java-" + minorVersion + "-openjdk", // Arch "/usr/lib/jvm/jre-1." + minorVersion + ".0-openjdk", // Fedora }; for (const QString &searchPath : searchPaths) { if (QFile::exists(searchPath + "/bin/javac")) return searchPath; } } return {}; }; static const auto knownJdkVersions = QStringList() << "1.6" << "1.7" << "1.8" << "1.9" << QString(); // default JDK; QStringList seenJdkVersions; for (const auto &jdkVersion : knownJdkVersions) { QString specificJdkPath = getSpecificJdkVersion(jdkVersion); if (jdkVersion.isEmpty() || !specificJdkPath.isEmpty()) { const auto jdkPath = jdkVersion.isEmpty() ? jdkVersion : specificJdkPath; if (!jdkVersion.isEmpty()) seenJdkVersions << jdkVersion; if (!seenJdkVersions.empty()) { const auto javaVersions = QStringList() << knownJdkVersions.mid(0, knownJdkVersions.indexOf(seenJdkVersions.last()) + 1) << QString(); // also test with no explicitly specified source version for (const auto ¤tJavaVersion : javaVersions) { const QString rowName = (!jdkPath.isEmpty() ? jdkPath : "default JDK") + QStringLiteral(", ") + (!currentJavaVersion.isEmpty() ? ("Java " + currentJavaVersion) : "default Java version"); QTest::newRow(rowName.toLatin1().constData()) << jdkPath << currentJavaVersion; } } } } if (seenJdkVersions.empty()) QSKIP("No JDKs installed"); } void TestBlackboxJava::javaDependencyTrackingInnerClass() { const SettingsPtr s = settings(); Profile p(profileName(), s.get()); QDir::setCurrent(testDataDir + "/java/inner-class"); QbsRunParameters params; int status = runQbs(params); if (p.value("java.jdkPath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("jdkPath")) { QSKIP("java.jdkPath not set and automatic detection failed"); } QCOMPARE(status, 0); } QTEST_MAIN(TestBlackboxJava) qbs-src-1.13.1/tests/auto/blackbox/tst_blackboxjava.h000066400000000000000000000031001347155106100225350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOX_H #define TST_BLACKBOX_H #include "tst_blackboxbase.h" class TestBlackboxJava : public TestBlackboxBase { Q_OBJECT public: TestBlackboxJava(); private slots: void java(); void javaDependencyTracking(); void javaDependencyTracking_data(); void javaDependencyTrackingInnerClass(); }; #endif // TST_BLACKBOX_H qbs-src-1.13.1/tests/auto/blackbox/tst_blackboxjoblimits.cpp000066400000000000000000000170401347155106100241530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxbase.h" #include "../shared.h" #include class TestBlackboxJobLimits : public TestBlackboxBase { Q_OBJECT public: TestBlackboxJobLimits(); private slots: void jobLimits_data(); void jobLimits(); }; TestBlackboxJobLimits::TestBlackboxJobLimits() : TestBlackboxBase (SRCDIR "/testdata-joblimits", "blackbox-joblimits") { } void TestBlackboxJobLimits::jobLimits_data() { QTest::addColumn("projectJobCount"); QTest::addColumn("productJobCount"); QTest::addColumn("moduleJobCount"); QTest::addColumn("prefsJobCount"); QTest::addColumn("cliJobCount"); QTest::addColumn("projectPrecedence"); QTest::addColumn("expectSuccess"); for (int projectJobCount = -1; projectJobCount <= 1; ++projectJobCount) { for (int productJobCount = -1; productJobCount <= 1; ++productJobCount) { for (int moduleJobCount = -1; moduleJobCount <= 1; ++moduleJobCount) { for (int prefsJobCount = -1; prefsJobCount <= 1; ++prefsJobCount) { for (int cliJobCount = -1; cliJobCount <= 1; ++cliJobCount) { QString description = QString("project:%1/" "product:%2/module:%3/prefs:%4/cli:%5/project precedence") .arg(projectJobCount).arg(productJobCount).arg(moduleJobCount) .arg(prefsJobCount).arg(cliJobCount).toLocal8Bit(); bool expectSuccess; switch (productJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (projectJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (moduleJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (cliJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: expectSuccess = prefsJobCount == 1; break; } break; } break; } break; } QTest::newRow(qPrintable(description)) << projectJobCount << productJobCount << moduleJobCount << prefsJobCount << cliJobCount << true << expectSuccess; description = QString("project:%1/" "product:%2/module:%3/prefs:%4/cli:%5/default precedence") .arg(projectJobCount).arg(productJobCount).arg(moduleJobCount) .arg(prefsJobCount).arg(cliJobCount).toLocal8Bit(); switch (cliJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (prefsJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (productJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: switch (projectJobCount) { case 1: expectSuccess = true; break; case 0: expectSuccess = false; break; case -1: expectSuccess = moduleJobCount == 1; break; } break; } break; } break; } QTest::newRow(qPrintable(description)) << projectJobCount << productJobCount << moduleJobCount << prefsJobCount << cliJobCount << false << expectSuccess; } } } } } } void TestBlackboxJobLimits::jobLimits() { QDir::setCurrent(testDataDir + "/job-limits"); QFETCH(int, projectJobCount); QFETCH(int, productJobCount); QFETCH(int, moduleJobCount); QFETCH(int, prefsJobCount); QFETCH(int, cliJobCount); QFETCH(bool, projectPrecedence); QFETCH(bool, expectSuccess); SettingsPtr theSettings = settings(); qbs::Internal::TemporaryProfile profile("jobLimitsProfile", theSettings.get()); profile.p.setValue("preferences.jobLimit.singleton", prefsJobCount); theSettings->sync(); QbsRunParameters resolveParams("resolve"); resolveParams.profile = profile.p.name(); resolveParams.arguments << ("project.projectJobCount:" + QString::number(projectJobCount)) << ("project.productJobCount:" + QString::number(productJobCount)) << ("project.moduleJobCount:" + QString::number(moduleJobCount)); QCOMPARE(runQbs(resolveParams), 0); QbsRunParameters buildParams; buildParams.expectFailure = !expectSuccess; if (cliJobCount != -1) buildParams.arguments << "--job-limits" << ("singleton:" + QString::number(cliJobCount)); if (projectPrecedence) buildParams.arguments << "--enforce-project-job-limits"; buildParams.profile = profile.p.name(); const int exitCode = runQbs(buildParams); if (expectSuccess) QCOMPARE(exitCode, 0); else if (exitCode == 0) QSKIP("no failure with no limit in place, result inconclusive"); else QVERIFY2(m_qbsStderr.contains("exclusive"), m_qbsStderr.constData()); if (exitCode == 0) QCOMPARE(m_qbsStdout.count("Running tool"), 7); } QTEST_MAIN(TestBlackboxJobLimits) #include qbs-src-1.13.1/tests/auto/blackbox/tst_blackboxqt.cpp000066400000000000000000000502341347155106100226050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_blackboxqt.h" #include "../shared.h" #include #include #include #include #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::Internal::HostOsInfo; using qbs::Profile; TestBlackboxQt::TestBlackboxQt() : TestBlackboxBase (SRCDIR "/testdata-qt", "blackbox-qt") { } void TestBlackboxQt::validateTestProfile() { const SettingsPtr s = settings(); if (profileName() != "none" && !s->profiles().contains(profileName())) QFAIL(QByteArray("The build profile '" + profileName().toLocal8Bit() + "' could not be found. Please set it up on your machine.")); const QStringList qmakeFilePaths = Profile(profileName(), s.get()) .value("moduleProviders.Qt.qmakeFilePaths").toStringList(); if (!qmakeFilePaths.empty()) return; if (!findExecutable(QStringList{"qmake"}).isEmpty()) return; QSKIP(QByteArray("The build profile '" + profileName().toLocal8Bit() + "' is not a valid Qt profile and Qt was not found " "in the global search paths.")); } void TestBlackboxQt::addQObjectMacroToGeneratedCppFile() { QDir::setCurrent(testDataDir + "/add-qobject-macro-to-generated-cpp-file"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("moc"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("object.cpp.in", "// ", ""); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("moc"), m_qbsStdout.constData()); } void TestBlackboxQt::autoQrc() { QDir::setCurrent(testDataDir + "/auto-qrc"); QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app"})), 0); QVERIFY2(m_qbsStdout.simplified().contains("resource data: resource1 resource2"), m_qbsStdout.constData()); } void TestBlackboxQt::cachedQml() { QDir::setCurrent(testDataDir + "/cached-qml"); QCOMPARE(runQbs(), 0); QString dataDir = relativeBuildDir() + "/install-root/data"; QVERIFY2(m_qbsStdout.contains("qmlcachegen must work: true") || m_qbsStdout.contains("qmlcachegen must work: false"), m_qbsStdout.constData()); if (m_qbsStdout.contains("qmlcachegen must work: false") && QFile::exists(dataDir + "/main.cpp")) { // If C++ source files were installed then Qt.qmlcache is not available. See project file. QSKIP("No QML cache files generated."); } QVERIFY(QFile::exists(dataDir + "/main.qmlc")); QVERIFY(QFile::exists(dataDir + "/MainForm.ui.qmlc")); QVERIFY(QFile::exists(dataDir + "/stuff.jsc")); } void TestBlackboxQt::combinedMoc() { QDir::setCurrent(testDataDir + "/combined-moc"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling moc_theobject.cpp")); QVERIFY(!m_qbsStdout.contains("creating amalgamated_moc_theapp.cpp")); QVERIFY(!m_qbsStdout.contains("compiling amalgamated_moc_theapp.cpp")); QbsRunParameters params(QStringList("modules.Qt.core.combineMocOutput:true")); params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling moc_theobject.cpp")); QVERIFY(m_qbsStdout.contains("creating amalgamated_moc_theapp.cpp")); QVERIFY(m_qbsStdout.contains("compiling amalgamated_moc_theapp.cpp")); } void TestBlackboxQt::createProject() { QDir::setCurrent(testDataDir + "/create-project"); QVERIFY(QFile::copy(SRCDIR "/../../../examples/helloworld-qt/main.cpp", QDir::currentPath() + "/main.cpp")); QbsRunParameters createParams("create-project"); createParams.profile.clear(); QCOMPARE(runQbs(createParams), 0); createParams.expectFailure = true; QVERIFY(runQbs(createParams) != 0); QVERIFY2(m_qbsStderr.contains("already contains qbs files"), m_qbsStderr.constData()); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("compiling"), m_qbsStdout.constData()); } void TestBlackboxQt::dbusAdaptors() { QDir::setCurrent(testDataDir + "/dbus-adaptors"); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::dbusInterfaces() { QDir::setCurrent(testDataDir + "/dbus-interfaces"); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::forcedMoc() { QDir::setCurrent(testDataDir + "/forced-moc"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStderr.contains("Hello from slot"), m_qbsStderr.constData()); } void TestBlackboxQt::includedMocCpp() { QDir::setCurrent(testDataDir + "/included-moc-cpp"); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("compiling moc_myobject.cpp"), m_qbsStdout.constData()); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE("myobject.cpp", "#include ("invalidPlugin"); QTest::newRow("request valid plugins") << false; QTest::newRow("request invalid plugin") << true; } void TestBlackboxQt::pluginSupport() { QDir::setCurrent(testDataDir + "/plugin-support"); QFETCH(bool, invalidPlugin); QbsRunParameters resolveParams("resolve"); if (invalidPlugin) { resolveParams.arguments << "modules.m1.useDummy:true"; resolveParams.expectFailure = true; } QCOMPARE(runQbs(resolveParams) == 0, !invalidPlugin); if (invalidPlugin) { QVERIFY2(m_qbsStderr.contains("Plugin 'dummy' of type 'imageformats' was requested, " "but is not available"), m_qbsStderr.constData()); return; } const bool isStaticQt = m_qbsStdout.contains("static Qt: true"); const bool isDynamicQt = m_qbsStdout.contains("static Qt: false"); QVERIFY(isStaticQt != isDynamicQt); if (isStaticQt) QVERIFY2(m_qbsStdout.contains("platform plugin count: 1"), m_qbsStdout.constData()); else QVERIFY2(m_qbsStdout.contains("platform plugin count: 0"), m_qbsStdout.constData()); const auto extractList = [this](const char sep) { const int listStartIndex = m_qbsStdout.indexOf(sep); const int listEndIndex = m_qbsStdout.indexOf(sep, listStartIndex + 1); const QByteArray listString = m_qbsStdout.mid(listStartIndex + 1, listEndIndex - listStartIndex - 1); return listString.isEmpty() ? QByteArrayList() : listString.split(','); }; const QByteArrayList enabledPlugins = extractList('%'); if (isStaticQt) QCOMPARE(enabledPlugins.size(), 2); else QVERIFY(enabledPlugins.empty()); const QByteArrayList allPlugins = extractList('#'); QVERIFY(allPlugins.size() >= enabledPlugins.size()); QCOMPARE(runQbs(), 0); for (const QByteArray &plugin : allPlugins) { QCOMPARE(m_qbsStdout.contains("qt_plugin_import_" + plugin + ".cpp"), enabledPlugins.contains(plugin)); } } void TestBlackboxQt::qmlDebugging() { QDir::setCurrent(testDataDir + "/qml-debugging"); QCOMPARE(runQbs(), 0); const SettingsPtr s = settings(); Profile profile(profileName(), s.get()); if (!profile.value("qbs.toolchain").toStringList().contains("gcc")) return; QProcess nm; nm.start("nm", QStringList(relativeExecutableFilePath("debuggable-app"))); if (nm.waitForStarted()) { // Let's ignore hosts without nm. QVERIFY2(nm.waitForFinished(), qPrintable(nm.errorString())); QVERIFY2(nm.exitCode() == 0, nm.readAllStandardError().constData()); const QByteArray output = nm.readAllStandardOutput(); QVERIFY2(output.toLower().contains("debugginghelper"), output.constData()); } } void TestBlackboxQt::qobjectInObjectiveCpp() { if (!HostOsInfo::isMacosHost()) QSKIP("only applies on macOS"); const QString testDir = testDataDir + "/qobject-in-mm"; QDir::setCurrent(testDir); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::qtKeywords() { QDir::setCurrent(testDataDir + "/qt-keywords"); QbsRunParameters params(QStringList("modules.Qt.core.enableKeywords:false")); params.expectFailure = true; QVERIFY(runQbs(params) != 0); params.arguments.clear(); QVERIFY(runQbs(params) != 0); params.command = "resolve"; QCOMPARE(runQbs(params), 0); params.command = "build"; QCOMPARE(runQbs(params), 0); } void TestBlackboxQt::quickCompiler() { QDir::setCurrent(testDataDir + "/quick-compiler"); QCOMPARE(runQbs(), 0); const bool hasCompiler = m_qbsStdout.contains("compiler available"); const bool doesNotHaveCompiler = m_qbsStdout.contains("compiler not available"); QVERIFY2(hasCompiler || doesNotHaveCompiler, m_qbsStdout.constData()); QCOMPARE(m_qbsStdout.contains("compiling qml_subdir_test_qml.cpp"), hasCompiler); if (doesNotHaveCompiler) QSKIP("qtquickcompiler not available"); QCOMPARE(runQbs(QbsRunParameters(QStringList{"config:off", "modules.Qt.quick.useCompiler:false"})), 0); QVERIFY2(m_qbsStdout.contains("compiling"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling qml_subdir_test_qml.cpp"), m_qbsStdout.constData()); } void TestBlackboxQt::qtScxml() { QDir::setCurrent(testDataDir + "/qtscxml"); QCOMPARE(runQbs(), 0); if (m_qbsStdout.contains("QtScxml not present")) QSKIP("QtScxml module not present"); QVERIFY2(m_qbsStdout.contains("state machine name: qbs_test_machine"), m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.Qt.scxml.additionalCompilerFlags:--blubb"))), 0); QbsRunParameters params; params.expectFailure = true; QVERIFY2(runQbs(params) != 0, m_qbsStdout.constData()); } void TestBlackboxQt::removeMocHeaderFromFileList() { QDir::setCurrent(testDataDir + "/remove-moc-header-from-file-list"); QCOMPARE(runQbs(), 0); QString projectFile("remove-moc-header-from-file-list.qbs"); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "\"file.h\"", "// \"file.h\""); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); WAIT_FOR_NEW_TIMESTAMP(); REPLACE_IN_FILE(projectFile, "// \"file.h\"", "\"file.h\""); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::staticQtPluginLinking() { QDir::setCurrent(testDataDir + "/static-qt-plugin-linking"); QCOMPARE(runQbs(QStringList("products.p.type:application")), 0); const bool isStaticQt = m_qbsStdout.contains("Qt is static"); QVERIFY2(m_qbsStdout.contains("Creating static import") == isStaticQt, m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.p.type:staticlibrary"))), 0); QCOMPARE(runQbs(), 0); QVERIFY2(!m_qbsStdout.contains("Creating static import"), m_qbsStdout.constData()); } void TestBlackboxQt::trackAddMocInclude() { QDir::setCurrent(testDataDir + "/trackAddMocInclude"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackAddMocInclude/work"); // The build must fail because the main.moc include is missing. QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("main.cpp"); QCOMPARE(runQbs(), 0); } void TestBlackboxQt::track_qobject_change() { QDir::setCurrent(testDataDir + "/trackQObjChange"); copyFileAndUpdateTimestamp("bla_qobject.h", "bla.h"); QCOMPARE(runQbs(), 0); const QString productFilePath = relativeExecutableFilePath("i"); QVERIFY2(regularFileExists(productFilePath), qPrintable(productFilePath)); QString moc_bla_objectFileName = relativeProductBuildDir("i") + '/' + inputDirHash("qt.headers") + objectFileName("/moc_bla.cpp", profileName()); QVERIFY2(regularFileExists(moc_bla_objectFileName), qPrintable(moc_bla_objectFileName)); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("bla_noqobject.h", "bla.h"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(productFilePath)); QVERIFY(!QFile(moc_bla_objectFileName).exists()); } void TestBlackboxQt::track_qrc() { QDir::setCurrent(testDataDir + "/qrc"); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("rcc"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling test.cpp"), m_qbsStdout.constData()); const QString fileName = relativeExecutableFilePath("i"); QVERIFY2(regularFileExists(fileName), qPrintable(fileName)); QDateTime dt = QFileInfo(fileName).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); { QFile f("stuff.txt"); f.remove(); QVERIFY(f.open(QFile::WriteOnly)); f.write("bla"); f.close(); } REPLACE_IN_FILE("i.qbs", "//\"test.cpp\"", "\"test.cpp\""); waitForFileUnlock(); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("rcc bla.qrc"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("compiling test.cpp"), m_qbsStdout.constData()); QVERIFY(regularFileExists(fileName)); QVERIFY(dt < QFileInfo(fileName).lastModified()); WAIT_FOR_NEW_TIMESTAMP(); touch("i.qbs"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("rcc"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("compiling test.cpp"), m_qbsStdout.constData()); // Turn on big resources. WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(QbsRunParameters("resolve", {"modules.Qt.core.enableBigResources:true"})), 0); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("rcc (pass 1) bla.qrc"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("rcc (pass 2) bla.qrc"), m_qbsStdout.constData()); // Check null build. WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Building"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("rcc"), m_qbsStdout.constData()); // Turn off big resources. WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(QbsRunParameters("resolve", {"modules.Qt.core.enableBigResources:false"})), 0); QCOMPARE(runQbs(QbsRunParameters("run")), 0); QVERIFY2(m_qbsStdout.contains("rcc bla.qrc"), m_qbsStdout.constData()); // Check null build. WAIT_FOR_NEW_TIMESTAMP(); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("Building"), m_qbsStdout.constData()); QVERIFY2(!m_qbsStdout.contains("rcc"), m_qbsStdout.constData()); } void TestBlackboxQt::unmocable() { QDir::setCurrent(testDataDir + "/unmocable"); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStderr.contains("No relevant classes found. No output generated.")); } QTEST_MAIN(TestBlackboxQt) qbs-src-1.13.1/tests/auto/blackbox/tst_blackboxqt.h000066400000000000000000000044331347155106100222520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BLACKBOXQT_H #define TST_BLACKBOXQT_H #include "tst_blackboxbase.h" class TestBlackboxQt : public TestBlackboxBase { Q_OBJECT public: TestBlackboxQt(); protected: void validateTestProfile() override; private slots: void addQObjectMacroToGeneratedCppFile(); void autoQrc(); void cachedQml(); void combinedMoc(); void createProject(); void dbusAdaptors(); void dbusInterfaces(); void forcedMoc(); void includedMocCpp(); void linkerVariant(); void lrelease(); void mixedBuildVariants(); void mocAndCppCombining(); void mocFlags(); void mocSameFileName(); void pkgconfig(); void pluginMetaData(); void pluginSupport_data(); void pluginSupport(); void qmlDebugging(); void qobjectInObjectiveCpp(); void qtKeywords(); void quickCompiler(); void qtScxml(); void removeMocHeaderFromFileList(); void staticQtPluginLinking(); void trackAddMocInclude(); void track_qobject_change(); void track_qrc(); void unmocable(); }; #endif // TST_BLACKBOXQT_H qbs-src-1.13.1/tests/auto/blackbox/tst_clangdb.cpp000066400000000000000000000176141347155106100220520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 Christian Gagneraud. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_clangdb.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include using qbs::InstallOptions; using qbs::Internal::HostOsInfo; int TestClangDb::runProcess(const QString &exec, const QStringList &args, QByteArray &stdErr, QByteArray &stdOut) { QProcess process; QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(processEnvironment); process.setProcessEnvironment(env); process.start(exec, args); const int waitTime = 10 * 60000; if (!process.waitForStarted() || !process.waitForFinished(waitTime)) { stdErr = process.readAllStandardError(); return -1; } stdErr = process.readAllStandardError(); stdOut = process.readAllStandardOutput(); sanitizeOutput(&stdErr); sanitizeOutput(&stdOut); if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) { if (!stdErr.isEmpty()) qDebug("%s", stdErr.constData()); if (!stdOut.isEmpty()) qDebug("%s", stdOut.constData()); } return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1; } qbs::Version TestClangDb::clangVersion() { QByteArray stdErr; QByteArray stdOut; if (runProcess("clang-check", QStringList("--version"), stdErr, stdOut) != 0) return qbs::Version(); stdOut.remove(0, stdOut.indexOf("LLVM version ") + 13); stdOut.truncate(stdOut.indexOf('\n')); return qbs::Version::fromString(QString::fromLocal8Bit(stdOut)); } TestClangDb::TestClangDb() : TestBlackboxBase(SRCDIR "/testdata-clangdb", "blackbox-clangdb"), projectDir(QDir::cleanPath(testDataDir + "/project1")), projectFileName("project.qbs"), buildDir(QDir::cleanPath(projectDir + "/" + relativeBuildDir())), sourceFilePath(QDir::cleanPath(projectDir + "/i like spaces.cpp")), dbFilePath(QDir::cleanPath(buildDir + "/compile_commands.json")) { } void TestClangDb::initTestCase() { TestBlackboxBase::initTestCase(); QDir::setCurrent(projectDir); } void TestClangDb::ensureBuildTreeCreated() { QCOMPARE(runQbs(), 0); QVERIFY(QFile::exists(buildDir)); if (m_qbsStdout.contains("is msvc") || m_qbsStdout.contains("is mingw")) { sanitizeOutput(&m_qbsStdout); for (const auto &line : m_qbsStdout.split('\n')) { static const QByteArray includeEnv = "INCLUDE="; static const QByteArray libEnv = "LIB="; static const QByteArray pathEnv = "PATH="; if (line.startsWith(includeEnv)) processEnvironment.insert("INCLUDE", line.mid(includeEnv.size())); if (line.startsWith(libEnv)) processEnvironment.insert("LIB", line.mid(libEnv.size())); if (line.startsWith(pathEnv)) processEnvironment.insert("PATH", line.mid(pathEnv.size())); } } } void TestClangDb::checkCanGenerateDb() { QbsRunParameters params; params.command = "generate"; params.arguments << "--generator" << "clangdb"; QCOMPARE(runQbs(params), 0); QVERIFY(QFile::exists(dbFilePath)); } void TestClangDb::checkDbIsValidJson() { QFile file(dbFilePath); QVERIFY(file.open(QFile::ReadOnly)); const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); QVERIFY(!doc.isNull()); QVERIFY(doc.isArray()); } void TestClangDb::checkDbIsConsistentWithProject() { QFile file(dbFilePath); QVERIFY(file.open(QFile::ReadOnly)); const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); // We expect only one command for now const QJsonArray array = doc.array(); QVERIFY(array.size() == 1); // Validate the "command object" const QJsonObject entry = array.at(0).toObject(); QVERIFY(entry.contains("directory")); QVERIFY(entry.value("directory").isString()); QVERIFY(entry.contains("arguments")); QVERIFY(entry.value("arguments").isArray()); QVERIFY(entry.value("arguments").toArray().size() >= 2); QVERIFY(entry.contains("file")); QVERIFY(entry.value("file").isString()); QVERIFY(entry.value("file").toString() == sourceFilePath); // Validate the compile command itself, this requires a previous build since the command // line contains 'deep' path that are created during Qbs build run QByteArray stdErr; QByteArray stdOut; QStringList arguments; const QJsonArray jsonArguments = entry.value("arguments").toArray(); QString executable = jsonArguments.at(0).toString(); for (int i=1; i/i like spaces.cpp:11:5: warning: Assigned value is garbage or undefined // int unused = garbage; // ^~~~~~~~~~ ~~~~~~~ // <...>/i like spaces.cpp:11:9: warning: Value stored to 'unused' during its initialization is never read // int unused = garbage; // ^~~~~~ ~~~~~~~ // 2 warnings generated. void TestClangDb::checkClangDetectsSourceCodeProblems() { QByteArray stdErr; QByteArray stdOut; QStringList arguments; const QString executable = findExecutable(QStringList("clang-check")); if (executable.isEmpty()) QSKIP("No working clang-check executable found"); // Older clang versions do not support the "arguments" array in the compilation database. // Should we really want to support them, we would have to fall back to "command" instead. if (clangVersion() < qbs::Version(3, 7)) QSKIP("This test requires clang-check to be based on at least LLVM 3.7.0."); // clang-check.exe does not understand MSVC command-line syntax const SettingsPtr s = settings(); qbs::Profile profile(profileName(), s.get()); if (profile.value("qbs.toolchain").toStringList().contains("msvc")) { arguments << "-extra-arg-before=--driver-mode=cl"; } else if (profile.value("qbs.toolchain").toStringList().contains("mingw")) { arguments << "-extra-arg-before=--driver-mode=g++"; } arguments << "-analyze" << "-p" << relativeBuildDir() << sourceFilePath; QVERIFY(runProcess(executable, arguments, stdErr, stdOut) == 0); const QString output = QString::fromLocal8Bit(stdErr); QVERIFY(output.contains(QRegExp(QStringLiteral("warning.*undefined"), Qt::CaseInsensitive))); QVERIFY(output.contains(QRegExp(QStringLiteral("warning.*never read"), Qt::CaseInsensitive))); } QTEST_MAIN(TestClangDb) qbs-src-1.13.1/tests/auto/blackbox/tst_clangdb.h000066400000000000000000000040221347155106100215040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TST_CLANGDB_H #define QBS_TST_CLANGDB_H #include "tst_blackbox.h" #include class TestClangDb : public TestBlackboxBase { Q_OBJECT public: TestClangDb(); private slots: void initTestCase(); void ensureBuildTreeCreated(); void checkCanGenerateDb(); void checkDbIsValidJson(); void checkDbIsConsistentWithProject(); void checkClangDetectsSourceCodeProblems(); private: int runProcess(const QString &exec, const QStringList &args, QByteArray &stdErr, QByteArray &stdOut); qbs::Version clangVersion(); const QString projectDir; const QString projectFileName; const QString buildDir; const QString sourceFilePath; const QString dbFilePath; QProcessEnvironment processEnvironment; }; #endif // Include guard. qbs-src-1.13.1/tests/auto/buildgraph/000077500000000000000000000000001347155106100174055ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/buildgraph/buildgraph.pro000066400000000000000000000005231347155106100222500ustar00rootroot00000000000000TARGET = tst_buildgraph SOURCES = tst_buildgraph.cpp HEADERS = tst_buildgraph.h include(../auto.pri) include(../../../src/app/shared/logging/logging.pri) include(../../../src/lib/bundledlibs.pri) qbs_use_bundled_qtscript { CONFIG += qbs_do_not_link_bundled_qtscript include(../../../src/lib/scriptengine/use_scriptengine.pri) } qbs-src-1.13.1/tests/auto/buildgraph/buildgraph.qbs000066400000000000000000000002611347155106100222340ustar00rootroot00000000000000import qbs QbsAutotest { testName: "buildgraph" condition: qbsbuildconfig.enableUnitTests files: [ "tst_buildgraph.cpp", "tst_buildgraph.h" ] } qbs-src-1.13.1/tests/auto/buildgraph/tst_buildgraph.cpp000066400000000000000000000120571347155106100231310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "tst_buildgraph.h" #include #include #include #include #include #include #include #include #include "../shared/logging/consolelogger.h" #include using namespace qbs; using namespace qbs::Internal; const TopLevelProjectPtr project = TopLevelProject::create(); TestBuildGraph::TestBuildGraph(ILogSink *logSink) : m_logSink(logSink) { project->buildData.reset(new ProjectBuildData); } void TestBuildGraph::initTestCase() { } void TestBuildGraph::cleanupTestCase() { } bool TestBuildGraph::cycleDetected(const ResolvedProductConstPtr &product) { try { CycleDetector(Logger(m_logSink)).visitProduct(product); return false; } catch (const ErrorInfo &) { return true; } } ResolvedProductConstPtr TestBuildGraph::productWithDirectCycle() { const ResolvedProductPtr product = ResolvedProduct::create(); product->project = project; product->buildData.reset(new ProductBuildData); const auto root = new Artifact; root->product = product; const auto child = new Artifact; child->product = product; product->buildData->addRootNode(root); product->buildData->addNode(root); product->buildData->addNode(child); qbs::Internal::connect(root, child); qbs::Internal::connect(child, root); return product; } ResolvedProductConstPtr TestBuildGraph::productWithLessDirectCycle() { const ResolvedProductPtr product = ResolvedProduct::create(); product->project = project; product->buildData.reset(new ProductBuildData); const auto root = new Artifact; const auto child = new Artifact; const auto grandchild = new Artifact; root->product = product; child->product = product; grandchild->product = product; product->buildData->addRootNode(root); product->buildData->addNode(root); product->buildData->addNode(child); product->buildData->addNode(grandchild); qbs::Internal::connect(root, child); qbs::Internal::connect(child, grandchild); qbs::Internal::connect(grandchild, root); return product; } // root appears as a child, but in a different tree ResolvedProductConstPtr TestBuildGraph::productWithNoCycle() { const ResolvedProductPtr product = ResolvedProduct::create(); product->project = project; product->buildData.reset(new ProductBuildData); const auto root = new Artifact; const auto root2 = new Artifact; root->product = product; root2->product = product; product->buildData->addRootNode(root); product->buildData->addRootNode(root2); product->buildData->addNode(root); product->buildData->addNode(root2); qbs::Internal::connect(root2, root); return product; } void TestBuildGraph::testCycle() { QVERIFY(cycleDetected(productWithDirectCycle())); QVERIFY(cycleDetected(productWithLessDirectCycle())); QVERIFY(!cycleDetected(productWithNoCycle())); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); TestBuildGraph tbg(ConsoleLogger::instance().logSink()); return QTest::qExec(&tbg, argc, argv); } qbs-src-1.13.1/tests/auto/buildgraph/tst_buildgraph.h000066400000000000000000000051451347155106100225760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_BUILDGRAPH_H #define TST_BUILDGRAPH_H #include #include #include #include #include class TestBuildGraph : public QObject { Q_OBJECT public: TestBuildGraph(qbs::ILogSink *logSink); private slots: void initTestCase(); void cleanupTestCase(); void testCycle(); private: qbs::Internal::ResolvedProductConstPtr productWithDirectCycle(); qbs::Internal::ResolvedProductConstPtr productWithLessDirectCycle(); qbs::Internal::ResolvedProductConstPtr productWithNoCycle(); bool cycleDetected(const qbs::Internal::ResolvedProductConstPtr &product); qbs::ILogSink * const m_logSink; }; #endif // TST_BUILDGRAPH_H qbs-src-1.13.1/tests/auto/cmdlineparser/000077500000000000000000000000001347155106100201145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/cmdlineparser/cmdlineparser.pro000066400000000000000000000003301347155106100234620ustar00rootroot00000000000000TARGET = tst_cmdlineparser SOURCES = tst_cmdlineparser.cpp ../../../src/app/qbs/qbstool.cpp include(../auto.pri) include(../../../src/app/qbs/parser/parser.pri) include(../../../src/app/shared/logging/logging.pri) qbs-src-1.13.1/tests/auto/cmdlineparser/cmdlineparser.qbs000066400000000000000000000015561347155106100234620ustar00rootroot00000000000000import qbs import qbs.Utilities QbsAutotest { Depends { name: "qbsversion" } testName: "cmdlineparser" files: ["tst_cmdlineparser.cpp", "../../../src/app/qbs/qbstool.cpp"] cpp.defines: base.concat([ "SRCDIR=" + Utilities.cStringQuote(path), "QBS_VERSION=" +Utilities.cStringQuote(qbsversion.version) ]) // TODO: Make parser a static library? Group { name: "parser" prefix: "../../../src/app/qbs/parser/" files: [ "commandlineoption.cpp", "commandlineoption.h", "commandlineoptionpool.cpp", "commandlineoptionpool.h", "commandlineparser.cpp", "commandlineparser.h", "commandpool.cpp", "commandpool.h", "commandtype.h", "parsercommand.cpp", "parsercommand.h", ] } } qbs-src-1.13.1/tests/auto/cmdlineparser/tst_cmdlineparser.cpp000066400000000000000000000247741347155106100243600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include using namespace qbs; class TestCmdLineParser : public QObject { Q_OBJECT public: TestCmdLineParser() { ConsoleLogger::instance().logSink()->setEnabled(false); } private slots: void initTestCase() { QVERIFY(m_projectFile.open()); m_fileArgs = QStringList() << "-f" << m_projectFile.fileName(); } void testValidCommandLine() { QStringList args; args.push_back("-vvk"); args.push_back("-v"); args << "--products" << "blubb"; args << "--changed-files" << "foo,bar" << m_fileArgs; args << "--check-timestamps"; args << "--check-outputs"; CommandLineParser parser; QVERIFY(parser.parseCommandLine(args)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerTrace); QCOMPARE(parser.command(), BuildCommandType); QCOMPARE(parser.products(), QStringList() << "blubb"); QCOMPARE(parser.buildOptions(QString()).changedFiles().size(), 2); QVERIFY(parser.buildOptions(QString()).keepGoing()); QVERIFY(parser.forceTimestampCheck()); QVERIFY(parser.forceOutputCheck()); QVERIFY(!parser.logTime()); QCOMPARE(parser.buildConfigurations().size(), 1); QVERIFY(parser.parseCommandLine(QStringList() << "-vvvqqq" << m_fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), defaultLogLevel()); QVERIFY(parser.parseCommandLine(QStringList() << "-t" << m_fileArgs)); QVERIFY(parser.logTime()); // Note: We cannot just check for !parser.logTime() here, because if the test is not // run in a terminal, "--show-progress" is ignored, in which case "--log-time" // takes effect. QVERIFY(parser.parseCommandLine(QStringList() << "-t" << "--show-progress" << m_fileArgs)); QVERIFY(parser.showProgress() != parser.logTime()); QVERIFY(parser.parseCommandLine(QStringList() << "-vvqqq" << m_fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerWarning); QVERIFY(parser.parseCommandLine(QStringList() << "-vvvqq" << m_fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerDebug); QVERIFY(parser.parseCommandLine(QStringList() << "--log-level" << "trace" << m_fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerTrace); // Second "global" profile overwrites first. QVERIFY(parser.parseCommandLine(QStringList() << "profile:a" << m_fileArgs << "profile:b")); QCOMPARE(parser.buildConfigurations().size(), 1); QCOMPARE(parser.buildConfigurations().front().value("qbs.profile").toString(), QLatin1String("b")); // Second build configuration-specific profile overwrites first. QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "config:debug" << "profile:a" << "profile:b")); QCOMPARE(parser.buildConfigurations().size(), 1); QCOMPARE(parser.buildConfigurations().front().value("qbs.profile").toString(), QLatin1String("b")); QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "config:a-debug" << "profile:a" << "config:b-debug" << "profile:b")); QCOMPARE(parser.buildConfigurations().size(), 2); QCOMPARE(parser.buildConfigurations().front().value("qbs.configurationName").toString(), QLatin1String("a-debug")); QCOMPARE(parser.buildConfigurations().front().value("qbs.profile").toString(), QLatin1String("a")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.configurationName").toString(), QLatin1String("b-debug")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.profile").toString(), QLatin1String("b")); // Redundant build request QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "config:debug" << "profile:a" << "config:debug" << "profile:a")); QCOMPARE(parser.buildConfigurations().size(), 1); QVERIFY(parser.parseCommandLine(QStringList() << "config:debug" << "profile:a" << "config:release" << "profile:b" << m_fileArgs)); QCOMPARE(parser.buildConfigurations().size(), 2); QCOMPARE(parser.buildConfigurations().front().value("qbs.configurationName").toString(), QLatin1String("debug")); QCOMPARE(parser.buildConfigurations().front().value("qbs.profile").toString(), QLatin1String("a")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.configurationName").toString(), QLatin1String("release")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.profile").toString(), QLatin1String("b")); // Non-global property takes precedence. QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "profile:a" << "config:debug" << "profile:b")); QCOMPARE(parser.buildConfigurations().size(), 1); QCOMPARE(parser.buildConfigurations().front().value("qbs.configurationName").toString(), QLatin1String("debug")); QCOMPARE(parser.buildConfigurations().front().value("qbs.profile").toString(), QLatin1String("b")); // Digits are always handled as option parameters. QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "-j" << "123")); QCOMPARE(parser.buildOptions(QString()).maxJobCount(), 123); QVERIFY(parser.parseCommandLine(QStringList(m_fileArgs) << "-j123")); QCOMPARE(parser.buildOptions(QString()).maxJobCount(), 123); // Argument list separation for the "run" command. QVERIFY(parser.parseCommandLine(QStringList("run") << m_fileArgs << "config:custom" << "-j123")); QCOMPARE(parser.command(), RunCommandType); QCOMPARE(parser.buildOptions(QString()).maxJobCount(), 123); QCOMPARE(parser.buildConfigurations().front().value("qbs.configurationName").toString(), QLatin1String("custom")); QVERIFY(parser.runArgs().empty()); QVERIFY(parser.parseCommandLine(QStringList("run") << m_fileArgs << "-j" << "123" << "--" << "config:custom")); QCOMPARE(parser.command(), RunCommandType); QCOMPARE(parser.buildOptions(QString()).maxJobCount(), 123); QCOMPARE(parser.buildConfigurations().front().value("qbs.configurationName").toString(), QLatin1String("default")); QCOMPARE(parser.runArgs(), QStringList({"config:custom"})); // show-version QVERIFY(parser.parseCommandLine(QStringList("show-version"))); QVERIFY(parser.showVersion()); QVERIFY(parser.parseCommandLine(QStringList("--version"))); QVERIFY(parser.showVersion()); QVERIFY(parser.parseCommandLine(QStringList("-V"))); QVERIFY(parser.showVersion()); QVERIFY(parser.parseCommandLine(QStringList{"run", "--setup-run-env-config", "x,y,z"})); QCOMPARE(parser.runEnvConfig(), QStringList({"x", "y", "z"})); } void testInvalidCommandLine() { QFETCH(QStringList, commandLine); CommandLineParser parser; QVERIFY(!parser.parseCommandLine(commandLine)); } void testInvalidCommandLine_data() { QTest::addColumn("commandLine"); QTest::newRow("Unknown short option") << (QStringList() << m_fileArgs << "-x"); QTest::newRow("Unknown long option") << (QStringList() << m_fileArgs << "--xyz"); QTest::newRow("Invalid position") << (QStringList() << m_fileArgs << "-vjv"); QTest::newRow("Missing jobs argument") << (QStringList() << m_fileArgs << "-j"); QTest::newRow("Missing products argument") << (QStringList() << m_fileArgs << "--products"); QTest::newRow("Wrong argument") << (QStringList() << "-j" << "0" << m_fileArgs); QTest::newRow("Invalid list argument") << (QStringList() << "--changed-files" << "," << m_fileArgs); QTest::newRow("Invalid log level") << (QStringList() << "--log-level" << "blubb" << m_fileArgs); QTest::newRow("Unknown numeric argument") << (QStringList() << m_fileArgs << "-123"); QTest::newRow("Unknown parameter") << (QStringList() << m_fileArgs << "debug"); QTest::newRow("Too many arguments") << (QStringList("help") << "build" << "clean"); QTest::newRow("Property assignment for clean") << (QStringList("clean") << "profile:x"); QTest::newRow("Property assignment for dump-nodes-tree") << (QStringList("dump-nodes-tree") << "profile:x"); QTest::newRow("Property assignment for status") << (QStringList("status") << "profile:x"); QTest::newRow("Property assignment for update-timestamps") << (QStringList("update-timestamps") << "profile:x"); QTest::newRow("Argument for show-version") << (QStringList("show-version") << "config:debug"); } private: QTemporaryFile m_projectFile; QStringList m_fileArgs; }; QTEST_MAIN(TestCmdLineParser) #include "tst_cmdlineparser.moc" qbs-src-1.13.1/tests/auto/dllexport.h000066400000000000000000000030471347155106100174560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef DLLEXPORT_H #define DLLEXPORT_H #if defined(_WIN32) || defined(WIN32) # define DLL_EXPORT __declspec(dllexport) # define DLL_IMPORT __declspec(dllimport) #else # define DLL_EXPORT __attribute__((visibility("default"))) # define DLL_IMPORT __attribute__((visibility("default"))) # endif #endif // include guard qbs-src-1.13.1/tests/auto/language/000077500000000000000000000000001347155106100170475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/language.pro000066400000000000000000000011051347155106100213510ustar00rootroot00000000000000TARGET = tst_language SOURCES = tst_language.cpp HEADERS = tst_language.h include(../auto.pri) include(../../../src/app/shared/logging/logging.pri) include(../../../src/lib/bundledlibs.pri) !qbs_use_bundled_qtscript: QT += script DATA_DIRS = testdata for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES qbs_use_bundled_qtscript { CONFIG += qbs_do_not_link_bundled_qtscript include(../../../src/lib/scriptengine/use_scriptengine.pri) } qbs-src-1.13.1/tests/auto/language/language.qbs000066400000000000000000000011621347155106100213410ustar00rootroot00000000000000import qbs import qbs.Utilities QbsAutotest { Depends { name: "qbsversion" } Depends { name: "Qt.script" condition: !qbsbuildconfig.useBundledQtScript required: false } testName: "language" condition: qbsbuildconfig.enableUnitTests files: [ "tst_language.cpp", "tst_language.h" ] cpp.defines: base.concat([ "QBS_VERSION=" + Utilities.cStringQuote(qbsversion.version), "SRCDIR=" + Utilities.cStringQuote(path) ]) Group { name: "testdata" prefix: "testdata/" files: ["**/*"] fileTags: [] } } qbs-src-1.13.1/tests/auto/language/testdata/000077500000000000000000000000001347155106100206605ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/Banana000066400000000000000000000000321347155106100217560ustar00rootroot00000000000000Peanut butter jelly time! qbs-src-1.13.1/tests/auto/language/testdata/MyProperties.qbs000066400000000000000000000000171347155106100240270ustar00rootroot00000000000000Properties { } qbs-src-1.13.1/tests/auto/language/testdata/ParentWithExport.qbs000066400000000000000000000001651347155106100246600ustar00rootroot00000000000000Product { Export { Depends { name: "dummy" } dummy.defines: [product.name.toUpperCase()] } } qbs-src-1.13.1/tests/auto/language/testdata/aboutdialog.cpp000066400000000000000000000000001347155106100236440ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/additional-product-types.qbs000066400000000000000000000004601347155106100263170ustar00rootroot00000000000000Product { name: "p" type: ["tag1"] Depends { name: "dummy" } Depends { name: "dummy2" } property bool hasTag1: type.contains("tag1") property bool hasTag2: type.contains("tag2") property bool hasTag3: type.contains("tag3") property bool hasTag4: type.contains("tag4") } qbs-src-1.13.1/tests/auto/language/testdata/base-validate/000077500000000000000000000000001347155106100233615ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/base-validate/base-validate.qbs000066400000000000000000000000461347155106100265710ustar00rootroot00000000000000Product { Depends { name: "m" } } qbs-src-1.13.1/tests/auto/language/testdata/base-validate/modules/000077500000000000000000000000001347155106100250315ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/base-validate/modules/m/000077500000000000000000000000001347155106100252655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/base-validate/modules/m/MParent.qbs000066400000000000000000000000631347155106100273410ustar00rootroot00000000000000Module { condition: false validate: true } qbs-src-1.13.1/tests/auto/language/testdata/base-validate/modules/m/m.qbs000066400000000000000000000003061347155106100262270ustar00rootroot00000000000000MParent { condition: true validate: { var parentResult = base; if (!parentResult) throw "Parent failed"; throw "Parent succeeded, child failed."; } } qbs-src-1.13.1/tests/auto/language/testdata/baseproperty.qbs000066400000000000000000000002221347155106100241020ustar00rootroot00000000000000import "baseproperty_base.qbs" as BaseProduct BaseProduct { name: "product1" narf: base.concat(["boo"]) zort: base.concat(["boo"]) } qbs-src-1.13.1/tests/auto/language/testdata/baseproperty_base.qbs000066400000000000000000000001011347155106100250700ustar00rootroot00000000000000Product { property var narf property var zort: ["bar"] } qbs-src-1.13.1/tests/auto/language/testdata/broken-dependency-cycle1.qbs000066400000000000000000000005011347155106100261350ustar00rootroot00000000000000Project { Product { name: "p1" Export { property bool c: true Depends { name: "p2"; condition: c } } } Product { name: "p2" Depends { name: "p1" } p1.c: false } Product { name: "p3" Depends { name: "p1" } } } qbs-src-1.13.1/tests/auto/language/testdata/broken-dependency-cycle2.qbs000066400000000000000000000005011347155106100261360ustar00rootroot00000000000000Project { Product { name: "p1" Export { property bool c: true Depends { name: "p2"; condition: c } } } Product { name: "p3" Depends { name: "p1" } } Product { name: "p2" Depends { name: "p1" } p1.c: false } } qbs-src-1.13.1/tests/auto/language/testdata/buildconfigstringlistsyntax.qbs000066400000000000000000000000601347155106100272420ustar00rootroot00000000000000Project { property stringList someStrings } qbs-src-1.13.1/tests/auto/language/testdata/builtinFunctionInSearchPathsProperty.qbs000066400000000000000000000002461347155106100307270ustar00rootroot00000000000000import qbs.Environment Project { qbsSearchPaths: { if (!Environment.getEnv("PATH")) throw "Environment.getEnv doesn't seem to work"; } } qbs-src-1.13.1/tests/auto/language/testdata/canonicalArchitecture.qbs000066400000000000000000000001241347155106100256560ustar00rootroot00000000000000import qbs.Utilities Product { name: Utilities.canonicalArchitecture("i386") } qbs-src-1.13.1/tests/auto/language/testdata/chained-probes/000077500000000000000000000000001347155106100235435ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/chained-probes/chained-probes.qbs000066400000000000000000000000461347155106100271350ustar00rootroot00000000000000Product { Depends { name: "m" } } qbs-src-1.13.1/tests/auto/language/testdata/chained-probes/modules/000077500000000000000000000000001347155106100252135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/chained-probes/modules/m/000077500000000000000000000000001347155106100254475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/chained-probes/modules/m/m.qbs000066400000000000000000000006501347155106100264130ustar00rootroot00000000000000Module { Probe { id: probe1 property string probe1Prop configure: { probe1Prop = "probe1Val"; found = true; } } Probe { id: probe2 property string inputProp: prop1 property string probe2Prop configure: { probe2Prop = inputProp + "probe2Val"; found = true; } } property string prop1: probe1.probe1Prop property string prop2: probe2.probe2Prop } qbs-src-1.13.1/tests/auto/language/testdata/conditionaldepends.qbs000066400000000000000000000042121347155106100252340ustar00rootroot00000000000000import "conditionaldepends_base.qbs" as CondBase Project { CondBase { name: 'conditionaldepends_derived' someProp: true } CondBase { name: 'conditionaldepends_derived_false' someProp: "knolf" === "narf" } Product { name: "product_props_true" property bool someTrueProp: true Depends { condition: someTrueProp; name: "dummy"} } Product { name: "product_props_false" property bool someFalseProp: false Depends { condition: someFalseProp; name: "dummy"} } property bool someTruePrjProp: true Product { name: "project_props_true" Depends { condition: project.someTruePrjProp; name: "dummy"} } property bool someFalsePrjProp: false Product { name: "project_props_false" Depends { condition: project.someFalsePrjProp; name: "dummy"} } Product { name: "module_props_true" Depends { name: "dummy2" } Depends { condition: dummy2.someTrueProp; name: "dummy" } } Product { name: "module_props_false" Depends { name: "dummy2" } Depends { condition: dummy2.someFalseProp; name: "dummy" } } Product { name: "multilevel_module_props_true" Depends { name: "dummy3" } dummy3.loadDummy: true } Product { name: "multilevel_module_props_false" Depends { name: "dummy3" } } Product { name: "multilevel_module_props_overridden" Depends { name: "dummy3" } } Product { name: "multilevel2_module_props_true" Depends { name: "dummy3_loader" } } Product { name: "contradictory_conditions1" Depends { condition: false; name: "dummy" } Depends { condition: true; name: "dummy" } // this one wins } Product { name: "contradictory_conditions2" Depends { condition: true; name: "dummy" } // this one wins Depends { condition: false; name: "dummy" } } Product { name: "unknown_dependency_condition_false" Depends { condition: false; name: "doesonlyexistifhellfreezesover" } } } qbs-src-1.13.1/tests/auto/language/testdata/conditionaldepends_base.qbs000066400000000000000000000002341347155106100262260ustar00rootroot00000000000000Application { name: 'conditionaldepends_base' property bool someProp: false Depends { condition: someProp name: 'dummy' } } qbs-src-1.13.1/tests/auto/language/testdata/defaultvalue/000077500000000000000000000000001347155106100233415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/defaultvalue/egon.qbs000066400000000000000000000003111347155106100247730ustar00rootroot00000000000000Project { Product { name: "dep" Export { Depends { name: "higher" } } } Product { name: "egon" Depends { name: "dep" } lower.prop1: "blubb" } } qbs-src-1.13.1/tests/auto/language/testdata/defaultvalue/modules/000077500000000000000000000000001347155106100250115ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/defaultvalue/modules/higher/000077500000000000000000000000001347155106100262575ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/defaultvalue/modules/higher/higher.qbs000066400000000000000000000002521347155106100302330ustar00rootroot00000000000000Module { Depends { name: "lower" } lower.prop2: lower.prop1 === "egon" ? "withEgon" : original lower.listProp: lower.prop1 === "egon" ? ["egon"] : original } qbs-src-1.13.1/tests/auto/language/testdata/defaultvalue/modules/lower/000077500000000000000000000000001347155106100261415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/defaultvalue/modules/lower/lower.qbs000066400000000000000000000003061347155106100277770ustar00rootroot00000000000000Module { property string prop1 property string prop2: prop1 === "blubb" ? "withBlubb" : "withoutBlubb" property stringList listProp: prop1 === "blubb" ? ["blubb", "other"] : ["other"] } qbs-src-1.13.1/tests/auto/language/testdata/defaultvalue/test.txt000066400000000000000000000000001347155106100250470ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/delayed-error/000077500000000000000000000000001347155106100234165ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/delayed-error/modules/000077500000000000000000000000001347155106100250665ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/delayed-error/modules/m/000077500000000000000000000000001347155106100253225ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/delayed-error/modules/m/m.qbs000066400000000000000000000000701347155106100262620ustar00rootroot00000000000000Module { validate: { throw "Validation error!"; } } qbs-src-1.13.1/tests/auto/language/testdata/delayed-error/nonexisting.qbs000066400000000000000000000002631347155106100264730ustar00rootroot00000000000000Project { property bool enableProduct: true Product { name: "theProduct" condition: project.enableProduct Depends { name: "nosuchmodule" } } } qbs-src-1.13.1/tests/auto/language/testdata/delayed-error/validation.qbs000066400000000000000000000002501347155106100262540ustar00rootroot00000000000000Project { property bool enableProduct: true Product { name: "theProduct" condition: project.enableProduct Depends { name: "m" } } } qbs-src-1.13.1/tests/auto/language/testdata/dependencyOnAllProfiles.qbs000066400000000000000000000004101347155106100261320ustar00rootroot00000000000000Project { property string profile1 property string profile2 Product { name: "dep" qbs.profiles: [project.profile1, project.profile2] } Product { name: "main" Depends { name: "dep" } } } qbs-src-1.13.1/tests/auto/language/testdata/derived-sub-project/000077500000000000000000000000001347155106100245355ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/derived-sub-project/DerivedSubProject.qbs000066400000000000000000000000171347155106100306250ustar00rootroot00000000000000SubProject { } qbs-src-1.13.1/tests/auto/language/testdata/derived-sub-project/project.qbs000066400000000000000000000002121347155106100267050ustar00rootroot00000000000000Project { DerivedSubProject { filePath: "subproject.qbs" Properties { name: "something" } } } qbs-src-1.13.1/tests/auto/language/testdata/derived-sub-project/subproject.qbs000066400000000000000000000000141347155106100274170ustar00rootroot00000000000000Product { } qbs-src-1.13.1/tests/auto/language/testdata/dirwithmultipleprojects/000077500000000000000000000000001347155106100256605ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/dirwithmultipleprojects/project.qbs000066400000000000000000000000001347155106100300230ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/dirwithmultipleprojects/project2.qbs000066400000000000000000000000001347155106100301050ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/dirwithnoprojects/000077500000000000000000000000001347155106100244415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/dirwithnoprojects/.gitignore000066400000000000000000000000161347155106100264260ustar00rootroot00000000000000* !.gitignore qbs-src-1.13.1/tests/auto/language/testdata/dirwithoneproject/000077500000000000000000000000001347155106100244235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/dirwithoneproject/project.qbs000066400000000000000000000000001347155106100265660ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/disabled-subproject.qbs000066400000000000000000000007611347155106100253200ustar00rootroot00000000000000Project { SubProject { condition: false filePath: "nosuchfile.qbs" } SubProject { Properties { condition: false } filePath: "nosuchfile.qbs" } SubProject { condition: true Properties { condition: false } filePath: "nosuchfile.qbs" } SubProject { condition: false Properties { condition: true } filePath: "nosuchfile.qbs" } } qbs-src-1.13.1/tests/auto/language/testdata/dotted-names/000077500000000000000000000000001347155106100232445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/dotted-names/dotted-names.qbs000066400000000000000000000010101347155106100263270ustar00rootroot00000000000000import qbs Project { name: "theProject" property bool includeDottedProduct property bool includeDottedModule Project { condition: project.includeDottedProduct Product { name: "a.b" Export { property string c: "default" } } } Product { name: "p" Depends { name: "a.b"; condition: project.includeDottedProduct } Depends { name: "x.y"; condition: project.includeDottedModule } a.b.c: "p" x.y.z: "p" } } qbs-src-1.13.1/tests/auto/language/testdata/dotted-names/modules/000077500000000000000000000000001347155106100247145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/dotted-names/modules/x/000077500000000000000000000000001347155106100251635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/dotted-names/modules/x/y/000077500000000000000000000000001347155106100254335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/dotted-names/modules/x/y/xy.qbs000066400000000000000000000000701347155106100265770ustar00rootroot00000000000000import qbs Module { property string z: "default" } qbs-src-1.13.1/tests/auto/language/testdata/drawline.asm000066400000000000000000000000001347155106100231550ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/dummy.txt000066400000000000000000000000001347155106100225420ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/empty-js-file.js000066400000000000000000000000001347155106100236710ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/empty-js-file.qbs000066400000000000000000000000601347155106100240500ustar00rootroot00000000000000import "empty-js-file.js" as Empty Product { } qbs-src-1.13.1/tests/auto/language/testdata/enum-project-props.qbs000066400000000000000000000004121347155106100251350ustar00rootroot00000000000000Project { property string anExistingFile: "dummy.txt" Product { files: { for (var k in project) { if (k === "anExistingFile") return [project[k]]; } return []; } } } qbs-src-1.13.1/tests/auto/language/testdata/environmentvariable.qbs000066400000000000000000000001211347155106100254330ustar00rootroot00000000000000import qbs.Environment Product { name: Environment.getEnv("PRODUCT_NAME") } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/000077500000000000000000000000001347155106100227015ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/ParentItem.qbs000066400000000000000000000001461347155106100254610ustar00rootroot00000000000000Product { property bool cpp readonly property string readOnlyString: "I cannot be changed!" } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/ParentWithExport.qbs000066400000000000000000000000751347155106100267010ustar00rootroot00000000000000Product { Export { property bool theProp } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/conflicting-module-instances.qbs000066400000000000000000000000721347155106100311560ustar00rootroot00000000000000Product { Depends { name: "conflicting-instances" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/conflicting-properties-in-export-items.qbs000066400000000000000000000001101347155106100331330ustar00rootroot00000000000000ParentWithExport { Export { property string theProp } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/conflicting_fileTagsFilter.qbs000066400000000000000000000002661347155106100306770ustar00rootroot00000000000000Application { Group { fileTagsFilter: "application" qbs.install: true } Group { fileTagsFilter: "application" qbs.install: false } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/dependency_cycle.qbs000066400000000000000000000005011347155106100267010ustar00rootroot00000000000000Project { CppApplication { name: "A" Depends { name: "B" } files: ["main.cpp"] } CppApplication { name: "B" Depends { name: "C" } files: ["main.cpp"] } CppApplication { name: "C" Depends { name: "A" } files: ["main.cpp"] } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/dependency_cycle2.qbs000066400000000000000000000006121347155106100267660ustar00rootroot00000000000000Project { CppApplication { name: "A" Depends { name: "B" } files: ["main.cpp"] } CppApplication { name: "B" Depends { name: "C" } files: ["main.cpp"] } CppApplication { name: "C" Depends { name: "A" } files: ["main.cpp"] } CppApplication { name: "D" files: ["main.cpp"] } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/dependency_cycle3.qbs000066400000000000000000000002621347155106100267700ustar00rootroot00000000000000Project { Product { type: ["a"] name: "A" Depends { name: "B" } } Product { name: "B" Depends { productTypes: ["a"] } } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/dependency_cycle4.qbs000066400000000000000000000000551347155106100267710ustar00rootroot00000000000000Product { Depends { name: "module-a" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/duplicate-multiplex-value.qbs000066400000000000000000000002261347155106100305150ustar00rootroot00000000000000import qbs Product { name: "p" multiplexByQbsProperties: "architectures" aggregate: false qbs.architectures: ["x86", "arm", "x86"] } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/duplicate-multiplex-value2.qbs000066400000000000000000000002631347155106100306000ustar00rootroot00000000000000import qbs Product { name: "p" multiplexByQbsProperties: ["architectures", "buildVariants", "architectures"] aggregate: false qbs.architectures: ["x86", "arm"] } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/duplicate_sources.qbs000066400000000000000000000001221347155106100271200ustar00rootroot00000000000000Product { files: ["main.cpp"] Group { files: ["main.cpp"] } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/duplicate_sources_wildcards.qbs000066400000000000000000000001461347155106100311620ustar00rootroot00000000000000Product { files: ["*.qbs"] Group { files: ["duplicate_sources_wildcards.qbs"] } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/importloop1.qbs000066400000000000000000000000451347155106100256740ustar00rootroot00000000000000import "importloop2.qbs" as X X {} qbs-src-1.13.1/tests/auto/language/testdata/erroneous/importloop2.qbs000066400000000000000000000000451347155106100256750ustar00rootroot00000000000000import "importloop1.qbs" as X X {} qbs-src-1.13.1/tests/auto/language/testdata/erroneous/invalid-parameter-rhs.qbs000066400000000000000000000001741347155106100276100ustar00rootroot00000000000000Product { Depends { name: "prefix2.suffix" } Depends { name: "readonly"; prefix2.suffix.nope: access.will.fail } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/invalid-parameter-type.qbs000066400000000000000000000003421347155106100277720ustar00rootroot00000000000000Product { Depends { name: "module_with_parameters" } Depends { name: "readonly" module_with_parameters.boolParameter: "This is not an error." module_with_parameters.stringParameter: 123 } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/invalid-property-option.qbs000066400000000000000000000001061347155106100302230ustar00rootroot00000000000000Product { Depends { name: "module-with-wrong-property-option" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/invalid-references.qbs000066400000000000000000000000601347155106100271510ustar00rootroot00000000000000Project { references: "nosuchproject.qbs" } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/invalid_child_item_type.qbs000066400000000000000000000000511347155106100302540ustar00rootroot00000000000000Project { Depends { name: "foo" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/invalid_file.qbs000066400000000000000000000000631347155106100260340ustar00rootroot00000000000000Application { files: ["main.cpp", "other.h"] } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/invalid_property_type.qbs000066400000000000000000000000531347155106100300410ustar00rootroot00000000000000Product { property nonsense esnesnon } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/invalid_stringlist_element.qbs000066400000000000000000000000571347155106100310330ustar00rootroot00000000000000Product { files: ["foo", ["zoo"], "bar"] } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/main.cpp000066400000000000000000000035601347155106100243350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ int main() { } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/mismatching-multiplex-dependency.qbs000066400000000000000000000004631347155106100320530ustar00rootroot00000000000000Project { Product { name: "a" multiplexByQbsProperties: ["architectures"] qbs.architectures: ["x86", "arm"] } Product { name: "b" Depends { name: "a" } multiplexByQbsProperties: ["architectures"] qbs.architectures: ["mips", "ppc"] } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/missing-colon.qbs000066400000000000000000000000601347155106100261650ustar00rootroot00000000000000CppApplication { cpp.dynamicLibraries { } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/misused-inherited-property.qbs000066400000000000000000000000551347155106100307140ustar00rootroot00000000000000ParentItem { cpp.compilerName: "blubb" } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/module-depends-on-product.qbs000066400000000000000000000002251347155106100304040ustar00rootroot00000000000000Project { Product { name: "p1" Depends { name: "module-with-product-dependency" } } Product { name: "p2" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/000077500000000000000000000000001347155106100243515ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/conflicting-instances/000077500000000000000000000000001347155106100306355ustar00rootroot00000000000000conflicting-instance1.qbs000066400000000000000000000000131347155106100354410ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/conflicting-instancesModule { } conflicting-instance2.qbs000066400000000000000000000000131347155106100354420ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/conflicting-instancesModule { } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module-a/000077500000000000000000000000001347155106100260545ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module-a/module-a.qbs000066400000000000000000000000541347155106100302650ustar00rootroot00000000000000Module { Depends { name: "module-b" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module-b/000077500000000000000000000000001347155106100260555ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module-b/module-b.qbs000066400000000000000000000000541347155106100302670ustar00rootroot00000000000000Module { Depends { name: "module-a" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module-with-invalid-original/000077500000000000000000000000001347155106100320355ustar00rootroot00000000000000module-with-invalid-original.qbs000066400000000000000000000000531347155106100401470ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module-with-invalid-originalModule { property string p: original } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module-with-product-dependency/000077500000000000000000000000001347155106100324015ustar00rootroot00000000000000module-with-product-dependency.qbs000066400000000000000000000000461347155106100410610ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module-with-product-dependencyModule { Depends { name: "p2" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module-with-wrong-property-option/000077500000000000000000000000001347155106100331315ustar00rootroot00000000000000m.qbs000066400000000000000000000002301347155106100340100ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module-with-wrong-property-optionModule { property string someProp PropertyOptions { name: "s0meProp" description: "Oops, spelt the property name wrong" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module_with_parameters/000077500000000000000000000000001347155106100311145ustar00rootroot00000000000000module_with_parameters.qbs000066400000000000000000000003211347155106100363030ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/module_with_parametersModule { Parameter { property bool boolParameter } Parameter { property int intParameter } Parameter { property stringList stringListParameter } Parameter { property string stringParameter } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/no_such_property/000077500000000000000000000000001347155106100277535ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/no_such_property/no-such-property.qbs000066400000000000000000000001521347155106100337160ustar00rootroot00000000000000Module { Depends { name: "module_with_parameters" } module_with_parameters.noSuchProperty: true } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/prefix1/000077500000000000000000000000001347155106100257275ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/prefix1/prefix1.qbs000066400000000000000000000000131347155106100300060ustar00rootroot00000000000000Module { } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/prefix1/suffix/000077500000000000000000000000001347155106100272335ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/prefix1/suffix/suffix.qbs000066400000000000000000000000531347155106100312440ustar00rootroot00000000000000Module { Depends { name: "prefix1" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/prefix2/000077500000000000000000000000001347155106100257305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/prefix2/prefix2.qbs000066400000000000000000000000621347155106100300140ustar00rootroot00000000000000Module { Depends { name: "prefix2.suffix" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/prefix2/suffix/000077500000000000000000000000001347155106100272345ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/prefix2/suffix/suffix.qbs000066400000000000000000000000131347155106100312410ustar00rootroot00000000000000Module { } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/readonly/000077500000000000000000000000001347155106100261665ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/erroneous/modules/readonly/readonly.qbs000066400000000000000000000001171347155106100305110ustar00rootroot00000000000000Module { readonly property string readOnlyString: "I cannot be changed!" } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/multiple_exports.qbs000066400000000000000000000000501347155106100270220ustar00rootroot00000000000000Product { Export {} Export {} } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/multiple_properties_in_subproject.qbs000066400000000000000000000001601347155106100324420ustar00rootroot00000000000000Project { SubProject { Properties { condition: false } Properties { name: "blubb" } } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/no-configure-in-probe.qbs000066400000000000000000000000571347155106100275160ustar00rootroot00000000000000Product { Probe { id: hurz } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/nonexistentouter.qbs000066400000000000000000000000641347155106100270450ustar00rootroot00000000000000Project { Product { name: outer } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/oldQbsVersion.qbs000066400000000000000000000001371347155106100262030ustar00rootroot00000000000000Project { minimumQbsVersion: "999.5.4" Product { qbs.enableSound: true } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/original-in-export-item.qbs000066400000000000000000000003051347155106100300710ustar00rootroot00000000000000import qbs Project { Product { name: "a" Export { property string p: original } } Product { name: "b" Depends { name: "a" } } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/original-in-export-item2.qbs000066400000000000000000000002711347155106100301550ustar00rootroot00000000000000import qbs Project { Product { name: "a" Export { x.y.z: original } } Product { name: "b" Depends { name: "a" } } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/original-in-export-item3.qbs000066400000000000000000000004041347155106100301540ustar00rootroot00000000000000import qbs Project { Product { name: "a" Export { Properties { condition: true x.y.z: original } } } Product { name: "b" Depends { name: "a" } } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/original-in-module-prototype.qbs000066400000000000000000000001151347155106100311430ustar00rootroot00000000000000import qbs Product { Depends { name: "module-with-invalid-original" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/original-in-product-property.qbs000066400000000000000000000000511347155106100311540ustar00rootroot00000000000000Product { property int n: original } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/overwrite-inherited-readonly-property.qbs000066400000000000000000000000771347155106100331100ustar00rootroot00000000000000ParentItem { readOnlyString: "changing the unchangeable" } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/overwrite-readonly-module-property.qbs000066400000000000000000000001461347155106100324170ustar00rootroot00000000000000Product { Depends { name: "readonly" } readonly.readOnlyString: "changing the unchangeable" } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/properties-item-with-invalid-condition.qbs000066400000000000000000000002341347155106100331200ustar00rootroot00000000000000Product { Depends { name: "cpp" } Properties { condition: cpp.nonexistingproperty.contains("somevalue") cpp.defines: ["ABC"] } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/references_cycle.qbs000066400000000000000000000000671347155106100267130ustar00rootroot00000000000000Project { references: ["references_cycle2.qbs"] } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/references_cycle2.qbs000066400000000000000000000000671347155106100267750ustar00rootroot00000000000000Project { references: ["references_cycle3.qbs"] } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/references_cycle3.qbs000066400000000000000000000000661347155106100267750ustar00rootroot00000000000000Project { references: ["references_cycle.qbs"] } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/reserved_name_in_import.qbs000066400000000000000000000000651347155106100303100ustar00rootroot00000000000000import "../idusagebase.qbs" as TextFile Product { } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/rule-without-output-tags.qbs000066400000000000000000000003461347155106100303550ustar00rootroot00000000000000Product { Rule { inputs: "input-tag" prepare: { var cmd = new JavaScriptCommand; cmd.silent = true; cmd.sourceCode = function() {}; return cmd; } } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/same-module-prefix1.qbs000066400000000000000000000000631347155106100271730ustar00rootroot00000000000000Product { Depends { name: "prefix1.suffix" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/same-module-prefix2.qbs000066400000000000000000000000541347155106100271740ustar00rootroot00000000000000Product { Depends { name: "prefix2" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/subproject_cycle.qbs000066400000000000000000000001161347155106100267450ustar00rootroot00000000000000Project { SubProject { filePath: "subproject_cycle2.qbs" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/subproject_cycle2.qbs000066400000000000000000000001161347155106100270270ustar00rootroot00000000000000Project { SubProject { filePath: "subproject_cycle3.qbs" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/subproject_cycle3.qbs000066400000000000000000000001151347155106100270270ustar00rootroot00000000000000Project { SubProject { filePath: "subproject_cycle.qbs" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/syntax-error-in-probe.qbs000066400000000000000000000001251347155106100275740ustar00rootroot00000000000000Product { Probe { id: hurz configure: { fngkgsdjfgklkf } } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/throw_in_property_binding.qbs000066400000000000000000000001021347155106100306700ustar00rootroot00000000000000Product { name: { throw "something is wrong"; } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undeclared-parameter1.qbs000066400000000000000000000001621347155106100275540ustar00rootroot00000000000000Product { Depends { name: "prefix2.suffix" } Depends { name: "readonly"; prefix2.suffix.nope: "nope" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undeclared-parameter2.qbs000066400000000000000000000001241347155106100275530ustar00rootroot00000000000000Product { name: "myproduct" Depends { name: "readonly"; foo.bar: "bla" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undeclared_item.qbs000066400000000000000000000000551347155106100265340ustar00rootroot00000000000000Product { cpp.defines: ["SUPERCRAZY"] } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undeclared_module_property_in_module.qbs000066400000000000000000000001031347155106100330540ustar00rootroot00000000000000Product { name: "p" Depends { name: "no_such_property" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undeclared_property.qbs000066400000000000000000000000421347155106100274560ustar00rootroot00000000000000Product { doesntexist: 123 } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undeclared_property_in_Properties_item.qbs000066400000000000000000000001221347155106100333750ustar00rootroot00000000000000Product { Properties { condition: true blubb.bla: "x" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undeclared_property_in_export_item.qbs000066400000000000000000000003001347155106100325600ustar00rootroot00000000000000Project { Product { name: "p1" Export { Depends { name: "cpp" } cpp.blubb: "x" } } Product { Depends { name: "p1" } } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undeclared_property_in_export_item2.qbs000066400000000000000000000002421347155106100326470ustar00rootroot00000000000000Project { Product { name: "p1" Export { something.other: "x" } } Product { Depends { name: "p1" } } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undeclared_property_in_export_item3.qbs000066400000000000000000000001721347155106100326520ustar00rootroot00000000000000Project { Product { name: "p1" Export { blubb: false } } Product { Depends { name: "p1" } } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undeclared_property_wrapper.qbs000066400000000000000000000001171347155106100312210ustar00rootroot00000000000000Project { SubProject { filePath: "undeclared_property.qbs" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undefined_stringlist_element.qbs000066400000000000000000000001071347155106100313420ustar00rootroot00000000000000Product { property string blubb files: ["foo", blubb, "bar"] } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/undefined_stringlist_element_in_probe.qbs000066400000000000000000000002231347155106100332160ustar00rootroot00000000000000Product { Probe { id: dummy property stringList l configure: { l = ["a", undefined, "b"] } } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/unknown_item_type.qbs000066400000000000000000000001431347155106100271640ustar00rootroot00000000000000Narf { zort: 1 // This invalid binding should not hide the "Unexpected item type" error. } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/unknown_module.qbs000066400000000000000000000000741347155106100264550ustar00rootroot00000000000000Product { Depends { name: "neitherModuleNorProduct" } } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/wrong-toplevel-item.qbs000066400000000000000000000000151347155106100273240ustar00rootroot00000000000000Artifact { } qbs-src-1.13.1/tests/auto/language/testdata/erroneous/wrongQbsVersionFormat.qbs000066400000000000000000000000621347155106100277270ustar00rootroot00000000000000Project { minimumQbsVersion: "hfyh1234wat?" } qbs-src-1.13.1/tests/auto/language/testdata/error-in-disabled-product.qbs000066400000000000000000000016171347155106100263540ustar00rootroot00000000000000Project { Product { name: "a" condition: false property stringList l: [undefined] } Product { name: "b" condition: false Group { name: { throw "boo!" } } } Product { name: "c" Group { condition: false name: { throw "boo!" } } } Project { condition: false Project { condition: true Product { name: "d" condition: { throw "ouch!" } } } } Product { condition: false Rule { inputs: [5] } } Project { condition: false minimumQbsVersion: false } Product { name: "e" condition: dummy.falseProperty Depends { name: "does.not.exist" } Depends { name: "dummy" } } } qbs-src-1.13.1/tests/auto/language/testdata/eval-error-in-non-present-module.qbs000066400000000000000000000002001347155106100275720ustar00rootroot00000000000000import qbs Product { name: "p" property bool moduleRequired Depends { name: "broken"; required: moduleRequired } } qbs-src-1.13.1/tests/auto/language/testdata/exports.qbs000066400000000000000000000074411347155106100231010ustar00rootroot00000000000000import "exports_product.qbs" as ProductWithInheritedExportItem Project { Application { name: "myapp" Depends { name: "mylib" } Depends { name: "dummy" } Depends { name: "qbs" } dummy.defines: ["BUILD_" + product.name.toUpperCase()] dummy.includePaths: ["./app"] } references: [ "subdir/exports-mylib.qbs", "subdir2/exports-mylib2.qbs" ] Application { name: "A" Depends { name: "qbs" } Depends { name: "B" } } StaticLibrary { name: "B" Export { Depends { name: "C" } Depends { name: "qbs" } } } StaticLibrary { name: "C" Export { Depends { name: "D" } Depends { name: "qbs" } } } StaticLibrary { name: "D" } Application { name: "myapp2" Depends { name: "productWithInheritedExportItem" } Depends { name: "qbs" } } ProductWithInheritedExportItem { name: "productWithInheritedExportItem" Export { dummy.cFlags: base.concat("PRODUCT_" + product.name.toUpperCase()) dummy.cxxFlags: ["-bar"] Properties { condition: true dummy.defines: base.concat(["DEF"]) } } } Application { name: "myapp3" Depends { name: "productWithInheritedExportItem"; versionAtLeast: "2.0" } } Project { name: "sub1" Product { name: "sub p1" Export { Depends { name: "dummy" } dummy.someString: project.name } } } Project { name: "sub2" Product { name: "sub p2" Depends { name: "sub p1" } } } ParentWithExport { name: "libA" Export { Depends { name: "libB" } } } ParentWithExport { name: "libB" } ParentWithExport { name: "libC" Export { Depends { name: "libA" } } } ParentWithExport { name: "libD" Export { Depends { name: "libA" } } } Product { name: "libE" Depends { name: "libD" } Depends { name: "libC" } Group { qbs.install: false } } Product { name: "dependency" Probe { id: configProbe property var config configure: { var obj = {}; obj.featureX = true; obj.featureY = false; obj.featureZ = true; config = obj; found = true; } } property var config: configProbe.config Export { property bool depend: false property var config: product.config Depends { condition: depend; name: "cpp" } Properties { condition: depend; cpp.includePaths: ["."] } } } Product { name: "depender" Depends { name: "dependency" } property bool featureX: dependency.config.featureX property bool featureY: dependency.config.featureY property bool featureZ: dependency.config.featureZ } Product { name: "broken_cycle1" Export { property bool depend: true Depends { name: "broken_cycle3"; condition: depend } } } Product { name: "broken_cycle2" Export { Depends { name: "broken_cycle1" } broken_cycle1.depend: false } } Product { name: "broken_cycle3" Depends { name: "broken_cycle2" } } } qbs-src-1.13.1/tests/auto/language/testdata/exports_product.qbs000066400000000000000000000003251347155106100246330ustar00rootroot00000000000000Product { Export { version: "2.0" Depends { name: "dummy" } dummy.cFlags: ["BASE_" + product.name.toUpperCase()] dummy.cxxFlags: ["-foo"] dummy.defines: ["ABC"] } } qbs-src-1.13.1/tests/auto/language/testdata/file-in-product-and-module.qbs000066400000000000000000000002621347155106100264130ustar00rootroot00000000000000Product { name: "p" Depends { name: "module_with_file" } property bool addFileToProduct Group { files: "zort" condition: addFileToProduct } } qbs-src-1.13.1/tests/auto/language/testdata/filecontextproperties.qbs000066400000000000000000000001431347155106100260260ustar00rootroot00000000000000Product { name: "product1" property string narf: filePath property string zort: path } qbs-src-1.13.1/tests/auto/language/testdata/filetags.qbs000066400000000000000000000030731347155106100231700ustar00rootroot00000000000000Project { FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } Product { name: "filetagger_project_scope" files: ["main.cpp"] } Product { name: "filetagger_product_scope" files: ["drawline.asm"] FileTagger { patterns: "*.asm" fileTags: ["asm"] } } Product { name: "filetagger_static_pattern" files: "Banana" FileTagger { patterns: "Banana" fileTags: ["yellow"] } } Product { name: "unknown_file_tag" files: "narf.zort" } Product { name: "set_file_tag_via_group" Group { files: ["main.cpp"] fileTags: ["c++"] } } Product { name: "override_file_tag_via_group" Group { files: "main.cpp" // gets file tag "cpp" through the FileTagger fileTags: ["c++"] } } Product { name: "add_file_tag_via_group" Group { overrideTags: false files: "main.cpp" fileTags: ["zzz"] } } Product { name: "prioritized_filetagger" files: ["main.cpp"] FileTagger { patterns: ["*.cpp"] fileTags: ["cpp1"] priority: 3 } FileTagger { patterns: ["*.cpp"] fileTags: ["cpp2"] priority: 3 } FileTagger { patterns: ["*.cpp"] fileTags: ["ignored"] priority: 2 } } } qbs-src-1.13.1/tests/auto/language/testdata/getNativeSetting.qbs000066400000000000000000000016151347155106100246560ustar00rootroot00000000000000import qbs.FileInfo import qbs.Utilities Project { Product { name: "p1" targetName: { if (qbs.hostOS.contains("macos")) { return Utilities.getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductName"); } else if (qbs.hostOS.contains("windows")) { var productName = Utilities.getNativeSetting("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion", "ProductName"); if (productName.contains("Windows")) { return "Windows"; } return undefined; } else { return Utilities.getNativeSetting(FileInfo.joinPaths(path, "nativesettings.ini"), "osname"); } } } Product { name: "p2" targetName: Utilities.getNativeSetting("/dev/null", undefined, "fallback"); } } qbs-src-1.13.1/tests/auto/language/testdata/groupconditions.qbs000066400000000000000000000021401347155106100246120ustar00rootroot00000000000000Project { property bool someTrueProperty: true Product { name: "no_condition_no_group" files: ["main.cpp"] } Product { name: "no_condition" Group { files: ["main.cpp"] } } Product { name: "true_condition" Group { condition: true files: ["main.cpp"] } } Product { name: "false_condition" Group { condition: false files: ["main.cpp"] } } Product { name: "true_condition_from_product" property bool anotherTrueProperty: true Group { condition: anotherTrueProperty files: ["main.cpp"] } } Product { name: "true_condition_from_project" Group { condition: project.someTrueProperty files: ["main.cpp"] } } Product { name: "condition_accessing_module_property" Group { condition: qbs.targetOS.contains("narf") files: ["main.cpp"] qbs.install: false } } } qbs-src-1.13.1/tests/auto/language/testdata/groupname.qbs000066400000000000000000000005411347155106100233640ustar00rootroot00000000000000Project { Product { name: "MyProduct" Group { name: product.name + ".MyGroup" files: "*" } } Product { name: "My2ndProduct" Group { name: product.name + ".MyGroup" files: ["narf"] } Group { files: ["zort"] } } } qbs-src-1.13.1/tests/auto/language/testdata/homeDirectory.qbs000066400000000000000000000006611347155106100242070ustar00rootroot00000000000000Project { Product { name: "home" // These should resolve property path home: "~" property path homeSlash: "~/" property path homeUp: "~/.." property path homeFile: "~/a" // These are sanity checks and should not property path bogus1: "a~b" property path bogus2: "a/~/bb" property path user: "~foo/bar" // we don't resolve other-user paths } } qbs-src-1.13.1/tests/auto/language/testdata/id-uniqueness.qbs000066400000000000000000000004061347155106100241600ustar00rootroot00000000000000import "idusagebase.qbs" as DerivedProduct Project { id: theProject DerivedProduct { id: baseProduct // OK - even though 'baseProduct' is used in the base item. } DerivedProduct { id: baseProduct // ERROR } } qbs-src-1.13.1/tests/auto/language/testdata/idusage.qbs000066400000000000000000000011331347155106100230060ustar00rootroot00000000000000import "idusagebase.qbs" as DerivedProduct Project { id: theProject property int initialNr: 0 DerivedProduct { id: product1 } Product { id: product2 property int nr: theProject.initialNr + product1.nr + 1 name: "product2_" + nr } Product { id: product3 property int nr: product2.nr + 1 name: "product3_" + nr } DerivedProduct { id: product4 nr: product3.nr + 1 name: "product4_" + nr } Product { name: "product5" Depends { name: "deepdummy.deep.moat" } } } qbs-src-1.13.1/tests/auto/language/testdata/idusage_group.qbs000066400000000000000000000001101347155106100242140ustar00rootroot00000000000000Group { id: baseGroup name: "base" prefix: baseGroup.name } qbs-src-1.13.1/tests/auto/language/testdata/idusage_group2.qbs000066400000000000000000000001401347155106100243010ustar00rootroot00000000000000import "idusage_group.qbs" as MyGroup MyGroup { name: "between the hammer and the anvil" } qbs-src-1.13.1/tests/auto/language/testdata/idusagebase.qbs000066400000000000000000000006331347155106100236450ustar00rootroot00000000000000import "idusagebasebase.qbs" as DeriveMeCrazy import "idusage_group.qbs" as MyGroup import "idusage_group2.qbs" as MyGroup2 DeriveMeCrazy { id: baseProduct property int nr: theProject.initialNr + 1 name: "product1_" + nr property string productName: baseProduct.name MyGroup { name: "group in base product" } MyGroup2 { name: "another group in base product" } } qbs-src-1.13.1/tests/auto/language/testdata/idusagebasebase.qbs000066400000000000000000000001761347155106100245020ustar00rootroot00000000000000Product { id: baseBaseProduct name: "ace of base" property string productNameInBaseOfBase: baseBaseProduct.name } qbs-src-1.13.1/tests/auto/language/testdata/import-collection/000077500000000000000000000000001347155106100243235ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/import-collection/collection/000077500000000000000000000000001347155106100264565ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/import-collection/collection/file1.js000066400000000000000000000000411347155106100300070ustar00rootroot00000000000000function f1() { return "C2f1"; } qbs-src-1.13.1/tests/auto/language/testdata/import-collection/collection/file2.js000066400000000000000000000000411347155106100300100ustar00rootroot00000000000000function f2() { return "C2f2"; } qbs-src-1.13.1/tests/auto/language/testdata/import-collection/imports/000077500000000000000000000000001347155106100260205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/import-collection/imports/Collection/000077500000000000000000000000001347155106100301135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/import-collection/imports/Collection/file1.js000066400000000000000000000000411347155106100314440ustar00rootroot00000000000000function f1() { return "C1f1"; } qbs-src-1.13.1/tests/auto/language/testdata/import-collection/imports/Collection/file2.js000066400000000000000000000000411347155106100314450ustar00rootroot00000000000000function f2() { return "C1f2"; } qbs-src-1.13.1/tests/auto/language/testdata/import-collection/product.qbs000066400000000000000000000003021347155106100265050ustar00rootroot00000000000000import Collection as Collection1 import "collection" as Collection2 Product { name: "da product" targetName: Collection1.f1() + Collection1.f2() + Collection2.f1() + Collection2.f2() } qbs-src-1.13.1/tests/auto/language/testdata/import-collection/project.qbs000066400000000000000000000000551347155106100265000ustar00rootroot00000000000000Project { references: ["product.qbs"] } qbs-src-1.13.1/tests/auto/language/testdata/inherited-properties-items/000077500000000000000000000000001347155106100261445ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/inherited-properties-items/imports/000077500000000000000000000000001347155106100276415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/inherited-properties-items/imports/DebugName.qbs000066400000000000000000000001411347155106100321730ustar00rootroot00000000000000import qbs Properties { condition: qbs.buildVariant === "debug" name: "product_debug" } qbs-src-1.13.1/tests/auto/language/testdata/inherited-properties-items/imports/ReleaseName.qbs000066400000000000000000000001451347155106100325310ustar00rootroot00000000000000import qbs Properties { condition: qbs.buildVariant === "release" name: "product_release" } inherited-properties-items-product.qbs000066400000000000000000000001301347155106100355300ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/inherited-properties-itemsimport qbs Product { name: "product_default" DebugName {} ReleaseName {} } inherited-properties-items.qbs000066400000000000000000000001651347155106100340620ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/inherited-properties-itemsimport qbs Project { qbsSearchPaths: sourceDirectory references: "inherited-properties-items-product.qbs" } qbs-src-1.13.1/tests/auto/language/testdata/invalid-overrides.qbs000066400000000000000000000003221347155106100250120ustar00rootroot00000000000000Project { name: "My.Project" property bool x Product { name: "MyProduct" property bool x } Product { name: "MyOtherProduct" Depends { name: "cpp" } } } qbs-src-1.13.1/tests/auto/language/testdata/invalidBindingInDisabledItem.qbs000066400000000000000000000005151347155106100270470ustar00rootroot00000000000000Project { Product { name: "product1" condition: false someNonsense: "Bitte stellen Sie die Tassen auf den Tisch." } Product { name: "product2" Group { condition: false moreNonsense: "Follen. Follen. Hünuntergefollen. Auf dön Töppüch." } } } qbs-src-1.13.1/tests/auto/language/testdata/jsextensions.js000066400000000000000000000042071347155106100237550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ (function() { // Function wrapper to keep the environment clean. /* * poor man's JS test suite */ var testctx = {}; function initTestContext(name) { testctx.nr = 1; testctx.name = name; } function verify(c) { if (!c) throw testctx.name + ": verification #" + testctx.nr + " failed."; testctx.nr++; } /* * Tests for extensions of JavaScript builtin types. */ var a = ["one", "two", "three"]; initTestContext("Array.prototype.contains"); for (var k in a) verify(k !== "contains"); verify(a.contains("one")); verify(a.contains("two")); verify(a.contains("three")); verify(!a.contains("four")); })() // END function wrapper qbs-src-1.13.1/tests/auto/language/testdata/jsimportsinmultiplescopes.js000066400000000000000000000003011347155106100265620ustar00rootroot00000000000000function getName(qbsModule) { if (qbsModule.debugInformation) return "MyProduct_debug"; else return "MyProduct"; } function getInstallDir() { return "somewhere"; } qbs-src-1.13.1/tests/auto/language/testdata/jsimportsinmultiplescopes.qbs000066400000000000000000000002531347155106100267410ustar00rootroot00000000000000import "jsimportsinmultiplescopes.js" as MyFunctions Product { name: MyFunctions.getName(qbs) qbs.installDir: MyFunctions.getInstallDir() files: "main.cpp" } qbs-src-1.13.1/tests/auto/language/testdata/main.cpp000066400000000000000000000000001347155106100222760ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-merging-variant-values/000077500000000000000000000000001347155106100265325ustar00rootroot00000000000000module-merging-variant-values.qbs000066400000000000000000000001731347155106100350350ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-merging-variant-valuesProduct { multiplexByQbsProperties: ["architectures"] qbs.architectures: ["a1", "a2"] Depends { name: "m2" } } qbs-src-1.13.1/tests/auto/language/testdata/module-merging-variant-values/modules/000077500000000000000000000000001347155106100302025ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-merging-variant-values/modules/m1/000077500000000000000000000000001347155106100305175ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-merging-variant-values/modules/m1/m1.qbs000066400000000000000000000002721347155106100315440ustar00rootroot00000000000000Module { condition: qbs.architecture === "a1" || qbs.architecture === "a2" property string arch qbs.architecture: undefined // We do something like this in GenericGCC.qbs } qbs-src-1.13.1/tests/auto/language/testdata/module-merging-variant-values/modules/m2/000077500000000000000000000000001347155106100305205ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-merging-variant-values/modules/m2/m2.qbs000066400000000000000000000007171347155106100315520ustar00rootroot00000000000000Module { Depends { name: "m1" } m1.arch: qbs.architecture property string arch: qbs.architecture validate: { if (qbs.architecture !== "a1" && qbs.architecture !== "a2") throw "Unexpected arch " + qbs.architecture; if (arch !== qbs.architecture) throw "Oops: " + arch + "/" + qbs.architecture; if (m1.arch !== qbs.architecture) throw "Oops: " + m1.arch + "/" + qbs.architecture; } } qbs-src-1.13.1/tests/auto/language/testdata/module-prioritization-by-search-path/000077500000000000000000000000001347155106100300365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-prioritization-by-search-path/bar/000077500000000000000000000000001347155106100306025ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-prioritization-by-search-path/bar/modules/000077500000000000000000000000001347155106100322525ustar00rootroot00000000000000conflicting-instances/000077500000000000000000000000001347155106100364575ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-prioritization-by-search-path/bar/modulesbar.qbs000066400000000000000000000000641347155106100377320ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-prioritization-by-search-path/bar/modules/conflicting-instancesModule { property string moduleVariant: "bar" } qbs-src-1.13.1/tests/auto/language/testdata/module-prioritization-by-search-path/foo/000077500000000000000000000000001347155106100306215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-prioritization-by-search-path/foo/modules/000077500000000000000000000000001347155106100322715ustar00rootroot00000000000000conflicting-instances/000077500000000000000000000000001347155106100364765ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-prioritization-by-search-path/foo/modulesfoo.qbs000066400000000000000000000000641347155106100377700ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/module-prioritization-by-search-path/foo/modules/conflicting-instancesModule { property string moduleVariant: "foo" } qbs-src-1.13.1/tests/auto/language/testdata/module-prioritization-by-search-path/product.qbs000066400000000000000000000000721347155106100322240ustar00rootroot00000000000000Product { Depends { name: "conflicting-instances" } } qbs-src-1.13.1/tests/auto/language/testdata/module-prioritization-by-search-path/project.qbs000066400000000000000000000000541347155106100322120ustar00rootroot00000000000000Project { references: ["product.qbs"] } qbs-src-1.13.1/tests/auto/language/testdata/module-property-overrides-per-product.qbs000066400000000000000000000005671347155106100310100ustar00rootroot00000000000000Project { Product { Depends { name: "dummy" } name: "a" property stringList rpaths: dummy.rpaths } Product { Depends { name: "dummy" } name: "b" property stringList rpaths: dummy.rpaths } Product { Depends { name: "dummy" } name: "c" property stringList rpaths: dummy.rpaths } } qbs-src-1.13.1/tests/auto/language/testdata/moduleproperties.qbs000066400000000000000000000037411347155106100247760ustar00rootroot00000000000000Project { name: "MyProject" property string projectName: name Product { name: "merge_lists" Depends { name: "dummyqt"; submodules: ["gui", "network"] } Depends { name: "dummy" } dummy.defines: ["THE_PRODUCT"] } Product { name: "merge_lists_and_values" Depends { name: "dummyqt"; submodules: ["network", "gui"] } Depends { name: "dummy" } dummy.defines: "THE_PRODUCT" } Product { name: "merge_lists_with_duplicates" Depends { name: "dummy" } dummy.cxxFlags: ["-foo", "BAR", "-foo", "BAZ"] } Product { name: "merge_lists_with_prototype_values" Depends { name: "dummyqt"; submodules: ["gui", "network"] } Depends { name: "dummy" } } Product { name: "list_property_that_references_product" type: ["blubb"] Depends { name: "dummy" } dummy.listProp: ["x"] } Product { name: "list_property_depending_on_overridden_property" Depends { name: "dummy" } dummy.listProp2: ["PRODUCT_STUFF"] dummy.controllingProp: true } Product { name: "overridden_list_property" Depends { name: "dummy" } Properties { condition: true overrideListProperties: true dummy.listProp: ["PRODUCT_STUFF"] } } Product { name: "shadowed-list-property" property string productName: name Depends { name: "dummy" } dummy.defines: [projectName, productName] } Product { name: "shadowed-scalar-property" property string productName: name Depends { name: "dummy" } dummy.someString: projectName + "_" + productName } Product { name: "merged-varlist" property string productName: name Depends { name: "dummy" } Depends { name: "dummyqt.core" } dummy.controllingProp: true dummy.varListProp: ({d: "product"}) } } qbs-src-1.13.1/tests/auto/language/testdata/modulepropertiesingroups.qbs000066400000000000000000000041561347155106100265660ustar00rootroot00000000000000Project { Product { name: "grouptest" Depends { name: "gmod.gmod1" } Depends { name: "gmod3" } Depends { name: "gmod4" } gmod.gmod1.gmod1_list2: base.concat([name, gmod.gmod1.gmod1_string]) gmod.gmod1.gmod1_list3: ["product"] gmod.gmod1.p1: 1 Group { name: "g1" files: ["Banana"] gmod.gmod1.gmod1_string: name gmod.gmod1.gmod1_list2: outer.concat([name]) gmod.gmod1.p2: 2 gmod2.prop: 1 gmod2.commonName: "g1" gmod3.gmod3_string: "g1_gmod3" gmod4.gmod4_string: "g1_gmod4" Group { name: "g1.1" gmod.gmod1.gmod1_string: name gmod.gmod1.gmod1_list2: outer.concat([name]) gmod.gmod1.p2: 4 gmod2.prop: 2 gmod2.commonName: name gmod3.gmod3_string: "g1.1_gmod3" gmod4.gmod4_string: "g1.1_gmod4" } Group { name: "g1.2" gmod.gmod1.gmod1_string: name gmod.gmod1.gmod1_list2: outer.concat([name]) gmod.gmod1.p2: 8 gmod2.commonName: name gmod3.gmod3_string: "g1.2_gmod3" } } Group { name: "g2" files: ["zort"] gmod.gmod1.gmod1_string: name gmod.gmod1.p1: 2 gmod.gmod1.p2: 4 gmod2.prop: 2 gmod3.gmod3_string: name + "_gmod3" gmod4.gmod4_string: name + "_gmod4" Group { name: "g2.1" Group { name: "g2.1.1" gmod.gmod1.gmod1_list2: [name] gmod.gmod1.p2: 15 } } } } Product { name: "grouptest2" Depends { name: "gmod.gmod1" } Group { name: "g1" gmod.gmod1.gmod1_list2: ["G1"] Group { name: "g1.1" gmod.gmod1.gmod1_string: "G1.1" } } } } qbs-src-1.13.1/tests/auto/language/testdata/modules.qbs000066400000000000000000000025661347155106100230500ustar00rootroot00000000000000Project { Product { name: "no_modules" property var foo } Product { name: "qt_core" dummyqt.core.version: "1.2.3" property var foo: dummyqt.core.coreVersion Depends { name: "dummyqt.core" } } Product { name: "qt_gui" property var foo: dummyqt.gui.guiProperty Depends { name: "dummyqt.gui" } } Product { name: "qt_gui_network" property var foo: dummyqt.gui.guiProperty + ',' + dummyqt.network.networkProperty Depends { name: "dummyqt" submodules: ["gui", "network"] } } Product { name: "deep_module_name" property var foo: deepdummy.deep.moat.depth Depends { name: "deepdummy.deep.moat" } } Product { name: "deep_module_name_submodule_syntax1" property var foo: deepdummy.deep.moat.depth Depends { name: "deepdummy.deep" submodules: ["moat"] } } Product { name: "deep_module_name_submodule_syntax2" property var foo: deepdummy.deep.moat.depth Depends { name: "deepdummy" submodules: ["deep.moat"] } } Product { name: "dummy_twice" Depends { name: "dummy" } Depends { name: "dummy" } } } qbs-src-1.13.1/tests/auto/language/testdata/modules/000077500000000000000000000000001347155106100223305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/broken/000077500000000000000000000000001347155106100236105ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/broken/broken.qbs000066400000000000000000000006011347155106100255740ustar00rootroot00000000000000import qbs Module { Probe { id: theProbe property stringList broken property stringList fine configure: { broken = [["x"]]; fine = ["x"] found = true; } } property stringList broken: theProbe.broken property stringList fine: theProbe.fine.filter(function(incl) { return incl != "y"; }); } qbs-src-1.13.1/tests/auto/language/testdata/modules/deepdummy/000077500000000000000000000000001347155106100243215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/deepdummy/deep/000077500000000000000000000000001347155106100252365ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/deepdummy/deep/moat/000077500000000000000000000000001347155106100261765ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/deepdummy/deep/moat/dummydeepmoat.qbs000066400000000000000000000002021347155106100315510ustar00rootroot00000000000000Module { property string depth: "abysmal" Depends { name: "dummy"; id: dummyId } property string zort: dummyId.zort } qbs-src-1.13.1/tests/auto/language/testdata/modules/dummy/000077500000000000000000000000001347155106100234635ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/dummy/dummy.qbs000066400000000000000000000015571347155106100253350ustar00rootroot00000000000000import "dummy_base.qbs" as DummyBase DummyBase { condition: true additionalProductTypes: ["tag2"] property bool falseProperty: false property stringList defines property stringList cFlags property stringList cxxFlags property stringList rpaths: ["$ORIGIN"] property string someString property string productName: product.name property string upperCaseProductName: productName.toUpperCase() property string zort: "zort in dummy" property pathList includePaths property path somePath property stringList listProp: product.type.contains("blubb") ? ["123"] : ["456"] property bool controllingProp: false property stringList listProp2: controllingProp ? ["DEFAULT_STUFF", "EXTRA_STUFF"] : ["DEFAULT_STUFF"] property varList varListProp: [{a: controllingProp, b: someString}] } qbs-src-1.13.1/tests/auto/language/testdata/modules/dummy/dummy_base.qbs000066400000000000000000000001031347155106100263110ustar00rootroot00000000000000Module { condition: false property pathList includePaths } qbs-src-1.13.1/tests/auto/language/testdata/modules/dummy2/000077500000000000000000000000001347155106100235455ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/dummy2/dummy2.qbs000066400000000000000000000002241347155106100254670ustar00rootroot00000000000000Module { additionalProductTypes: ["tag3"] property var defines property var someTrueProp: true property var someFalseProp: false } qbs-src-1.13.1/tests/auto/language/testdata/modules/dummy3/000077500000000000000000000000001347155106100235465ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/dummy3/dummy3.qbs000066400000000000000000000001421347155106100254700ustar00rootroot00000000000000Module { property bool loadDummy: false Depends { name: "dummy"; condition: loadDummy } } qbs-src-1.13.1/tests/auto/language/testdata/modules/dummy3_loader/000077500000000000000000000000001347155106100250745ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/dummy3_loader/dummy3_loader.qbs000066400000000000000000000001051347155106100303430ustar00rootroot00000000000000Module { Depends { name: "dummy3" } dummy3.loadDummy: true } qbs-src-1.13.1/tests/auto/language/testdata/modules/dummyqt/000077500000000000000000000000001347155106100240305ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/dummyqt/core/000077500000000000000000000000001347155106100247605ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs000066400000000000000000000011741347155106100274760ustar00rootroot00000000000000Module { id: qtcore property int versionMajor: 5 property int versionMinor: 0 property int versionPatch: 0 property string version: versionMajor.toString() + "." + versionMinor.toString() + "." + versionPatch.toString() property string coreProperty: "coreProperty" property string coreVersion: qtcore.version property string zort: "zort in dummyqt.core" Depends { name: "dummy" } dummy.defines: ["QT_CORE"] dummy.rpaths: ["/opt/qt/lib"] dummy.cFlags: [zort] dummy.varListProp: [{c: "qtcore"}] Properties { condition: true dummy.productName: product.name } } qbs-src-1.13.1/tests/auto/language/testdata/modules/dummyqt/gui/000077500000000000000000000000001347155106100246145ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/dummyqt/gui/dummygui.qbs000066400000000000000000000004161347155106100271640ustar00rootroot00000000000000Module { Depends { name: "dummyqt.core" } property string guiProperty: "guiProperty" property string someString: "ene mene muh" Depends { name: "dummy" } dummy.defines: ["QT_GUI"] dummy.someString: someString dummy.zort: dummyqt.core.zort } qbs-src-1.13.1/tests/auto/language/testdata/modules/dummyqt/network/000077500000000000000000000000001347155106100255215ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/dummyqt/network/dummynetwork.qbs000066400000000000000000000002711347155106100307750ustar00rootroot00000000000000Module { Depends { name: "dummyqt"; submodules: ["core"] } property string networkProperty: "networkProperty" Depends { name: "dummy" } dummy.defines: ["QT_NETWORK"] } qbs-src-1.13.1/tests/auto/language/testdata/modules/gmod/000077500000000000000000000000001347155106100232565ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/gmod/gmod1/000077500000000000000000000000001347155106100242655ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/gmod/gmod1/gmod1.qbs000066400000000000000000000010631347155106100260030ustar00rootroot00000000000000Module { Depends { name: "gmod2" } Depends { name: "gmod4" } property stringList gmod1_list1: ["gmod1_list1_proto", gmod1_string] property stringList gmod1_list2: ["gmod1_list2_proto"] property stringList gmod1_list3: [gmod1_string] property string gmod1_string: "gmod1_string_proto" property string commonName: "commonName_in_gmod1" property int depProp: gmod2.prop property int p0: p1 + p2 property int p1: 0 property int p2: 0 gmod2.gmod2_string: gmod1_string gmod2.gmod2_list: [gmod1_string, commonName] } qbs-src-1.13.1/tests/auto/language/testdata/modules/gmod2/000077500000000000000000000000001347155106100233405ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/gmod2/gmod2.qbs000066400000000000000000000003121347155106100250530ustar00rootroot00000000000000Module { property int prop: 0 property string gmod2_string: "gmod2_string_proto" property string commonName: "commonName_in_gmod2" property stringList gmod2_list: ["gmod2_list_proto"] } qbs-src-1.13.1/tests/auto/language/testdata/modules/gmod3/000077500000000000000000000000001347155106100233415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/gmod3/qmod3.qbs000066400000000000000000000002051347155106100250700ustar00rootroot00000000000000Module { Depends { name: "gmod2" } property string gmod3_string: "gmod3_string_proto" gmod2.gmod2_list: [gmod3_string] } qbs-src-1.13.1/tests/auto/language/testdata/modules/gmod4/000077500000000000000000000000001347155106100233425ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/gmod4/gmod4.qbs000066400000000000000000000002761347155106100250700ustar00rootroot00000000000000Module { Depends { name: "gmod2" } Depends { name: "gmod3" } property string gmod4_string: "gmod4_string_proto" gmod2.gmod2_list: [gmod4_string + "_" + gmod3.gmod3_string] } qbs-src-1.13.1/tests/auto/language/testdata/modules/module-with-properties-item/000077500000000000000000000000001347155106100277145ustar00rootroot00000000000000module-with-properties-item.qbs000066400000000000000000000003301347155106100357240ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/module-with-properties-itemModule { property bool boolProperty: true property string stringProperty: "set in Module item" Properties { condition: boolProperty stringProperty: "overridden in Properties item" } } qbs-src-1.13.1/tests/auto/language/testdata/modules/module_with_file/000077500000000000000000000000001347155106100256475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/module_with_file/module-with-file.qbs000066400000000000000000000005671347155106100315410ustar00rootroot00000000000000Module { property bool file1IsTarget property bool file2IsTarget Group { prefix: product.sourceDirectory + '/' files: "zort" filesAreTargets: product.module_with_file.file1IsTarget } Group { prefix: product.sourceDirectory + '/' files: "zort" filesAreTargets: product.module_with_file.file2IsTarget } } qbs-src-1.13.1/tests/auto/language/testdata/modules/multiple_backends/000077500000000000000000000000001347155106100260155ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/multiple_backends/backend1.qbs000066400000000000000000000001351347155106100301730ustar00rootroot00000000000000Module { condition: qbs.targetOS.contains("os1") property string prop: "backend 1" } qbs-src-1.13.1/tests/auto/language/testdata/modules/multiple_backends/backend2.qbs000066400000000000000000000001761347155106100302010ustar00rootroot00000000000000Module { condition: qbs.targetOS.contains("os2") property string prop: "backend 2" property string backend2Prop } qbs-src-1.13.1/tests/auto/language/testdata/modules/multiple_backends/backend3.qbs000066400000000000000000000002101347155106100301670ustar00rootroot00000000000000Module { condition: qbs.targetOS.contains("os2") && qbs.toolchain.contains("tc") priority: 1 property string backend3Prop } qbs-src-1.13.1/tests/auto/language/testdata/modules/scopemod/000077500000000000000000000000001347155106100241415ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/modules/scopemod/scopemod.qbs000066400000000000000000000003031347155106100264550ustar00rootroot00000000000000Module { property int a: 1 property int b: 1 property int c: a + 1 property int d: b + 1 property int e: 1 property int f: 1 property int g: 1 property int h: 1 } qbs-src-1.13.1/tests/auto/language/testdata/modulescope.qbs000066400000000000000000000004001347155106100237000ustar00rootroot00000000000000import "modulescope_base.qbs" as MyProduct Project { MyProduct { name: "product1" property int e: 12 property int f: 13 scopemod.a: 2 scopemod.f: 2 scopemod.g: e * f scopemod.h: base + 2 } } qbs-src-1.13.1/tests/auto/language/testdata/modulescope_base.qbs000066400000000000000000000001031347155106100246720ustar00rootroot00000000000000Product { Depends { name: "scopemod" } scopemod.h: e * f } qbs-src-1.13.1/tests/auto/language/testdata/multiplexed-exports.qbs000066400000000000000000000010011347155106100254150ustar00rootroot00000000000000Project { Product { name: "dep" multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] property string includeDir: qbs.buildVariant === "debug" ? "/d" : "/r" Export { Depends { name: "cpp" } cpp.includePaths: product.includeDir } } Product { name: "p" Depends { name: "dep" } multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] } } qbs-src-1.13.1/tests/auto/language/testdata/multiplexing-by-profile/000077500000000000000000000000001347155106100254475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/multiplexing-by-profile/p1.qbs000066400000000000000000000004241347155106100264760ustar00rootroot00000000000000Project { Profile { name: "theProfile" qbs.architecture: "dummy" } Product { name: "p1" qbs.profiles: ["theProfile"] } Product { name: "p2" qbs.profiles: ["theProfile"] Depends { name: "p1" } } } qbs-src-1.13.1/tests/auto/language/testdata/multiplexing-by-profile/p2.qbs000066400000000000000000000005511347155106100265000ustar00rootroot00000000000000Project { Profile { name: "profile1" qbs.architecture: "dummy" } Profile { name: "profile2" qbs.architecture: "blubb" } Product { name: "p1" qbs.profiles: ["profile1"] } Product { name: "p2" qbs.profiles: ["profile1", "profile2"] Depends { name: "p1" } } } qbs-src-1.13.1/tests/auto/language/testdata/multiplexing-by-profile/p3.qbs000066400000000000000000000010211347155106100264720ustar00rootroot00000000000000Project { Profile { name: "profile1" qbs.architecture: "dummy" } Profile { name: "profile2" qbs.architecture: "blubb" } Profile { name: "profile3" qbs.architecture: "hurz" } Profile { name: "profile4" qbs.architecture: "zonk" } Product { name: "p1" qbs.profiles: ["profile1", "profile2"] Depends { name: "p2" } } Product { name: "p2" qbs.profiles: ["profile3", "profile4"] } } qbs-src-1.13.1/tests/auto/language/testdata/multiplexing-by-profile/p4.qbs000066400000000000000000000006011347155106100264760ustar00rootroot00000000000000Project { Profile { name: "profile1" qbs.architecture: "dummy" } Profile { name: "profile2" qbs.architecture: "blubb" } Product { name: "p1" qbs.profiles: ["profile1"] Depends { name: "p2"; profiles: ["profile1"] } } Product { name: "p2" qbs.profiles: ["profile1", "profile2"] } } qbs-src-1.13.1/tests/auto/language/testdata/narf000066400000000000000000000000001347155106100215170ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/narf.zort000066400000000000000000000000001347155106100225140ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/nativesettings.ini000066400000000000000000000000161347155106100244250ustar00rootroot00000000000000osname = Unix qbs-src-1.13.1/tests/auto/language/testdata/non-applicable-module-property-in-profile.qbs000066400000000000000000000006721347155106100314670ustar00rootroot00000000000000Project { property string targetOS property string toolchain Product { name: "p" multiplexByQbsProperties: ["profiles"] qbs.profiles: ["theProfile"] Depends { name: "multiple_backends" } Profile { name: "theProfile" qbs.targetOS: [project.targetOS] qbs.toolchain: [project.toolchain] multiple_backends.backend3Prop: "value" } } } qbs-src-1.13.1/tests/auto/language/testdata/non-required-products.qbs000066400000000000000000000013411347155106100256370ustar00rootroot00000000000000Project { Product { name: "depender" Depends { name: "dummy" } Depends { name: "dependee"; required: false } Properties { condition: dependee.present dummy.defines: ["WITH_DEPENDEE"] } } Project { name: "subproject" Product { name: "dependee" } } Product { name: "p1" condition: p2.present Depends { name: "p2"; required: false } } Product { name: "p2" condition: p3.present Depends { name: "p3"; required: false } } Product { name: "p3" condition: nosuchmodule.present Depends { name: "nosuchmodule"; required: false } } } qbs-src-1.13.1/tests/auto/language/testdata/outerInGroup.qbs000066400000000000000000000004151347155106100240310ustar00rootroot00000000000000Project { Product { name: "OuterInGroup" qbs.installDir: "/somewhere" files: ["main.cpp"] Group { name: "Special Group" files: ["aboutdialog.cpp"] qbs.installDir: outer + "/else" } } } qbs-src-1.13.1/tests/auto/language/testdata/overridden-properties-and-prototypes.qbs000066400000000000000000000001041347155106100307030ustar00rootroot00000000000000Product { name: "p" Depends { name: "multiple_backends" } } qbs-src-1.13.1/tests/auto/language/testdata/overridden-variant-property.qbs000066400000000000000000000000641347155106100270540ustar00rootroot00000000000000Product { name: "p" property var myObject } qbs-src-1.13.1/tests/auto/language/testdata/parameter-types.qbs000066400000000000000000000007341347155106100245150ustar00rootroot00000000000000Project { Product { name: "foo" qbsSearchPaths: "./erroneous" Depends { name: "module_with_parameters" } Depends { name: "bar" module_with_parameters.boolParameter: true module_with_parameters.intParameter: 156 module_with_parameters.stringParameter: "hello" module_with_parameters.stringListParameter: ["la", "le", "lu"] } } Product { name: "bar" } } qbs-src-1.13.1/tests/auto/language/testdata/pathproperties.qbs000066400000000000000000000004231347155106100244370ustar00rootroot00000000000000import "subdir/pathproperties_base.qbs" as ProductBase ProductBase { name: "product1" property path projectFileDir: "." property pathList filesInProjectFileDir: ["./aboutdialog.h", "aboutdialog.cpp"] Depends { name: "dummy" } dummy.includePaths: ["."] } qbs-src-1.13.1/tests/auto/language/testdata/productconditions.qbs000066400000000000000000000014301347155106100251370ustar00rootroot00000000000000import qbs.Probes Project { Product { name: "product_no_condition" } Product { name: "product_true_condition" condition: 1 === 1 } Product { name: "product_false_condition" condition: 1 === 2 } Product { name: "product_condition_dependent_of_module" condition: qbs.architecture !== (qbs.architecture + "foo") } Product { name: "product_probe_condition_true" condition: trueProbe.found Probe { id: trueProbe configure: { found = true; } } } Product { name: "product_probe_condition_false" condition: falseProbe.found Probe { id: falseProbe configure: { found = false; } } } } qbs-src-1.13.1/tests/auto/language/testdata/productdirectories.qbs000066400000000000000000000000361347155106100253030ustar00rootroot00000000000000Product { name: "MyApp" } qbs-src-1.13.1/tests/auto/language/testdata/profilevaluesandoverriddenvalues.qbs000066400000000000000000000014261347155106100302370ustar00rootroot00000000000000Project { Application { name: "product1" property bool dummyProp: { if (!(dummy.cFlags instanceof Array)) throw new Error("dummy.cFlags: Array type expected."); if (!(dummy.cxxFlags instanceof Array)) throw new Error("dummy.cxxFlags: Array type expected."); if (!(dummy.defines instanceof Array)) throw new Error("dummy.defines: Array type expected."); return true; } consoleApplication: true Depends { name: "dummy" } // dummy.cxxFlags is set via profile and is not overridden dummy.defines: ["IN_FILE"] // set in profile, overridden in file dummy.cFlags: ["IN_FILE"] // set in profile, overridden on command line } } qbs-src-1.13.1/tests/auto/language/testdata/properties-block-in-group.qbs000066400000000000000000000005171347155106100264140ustar00rootroot00000000000000Product { name: "in-group" property bool featureEnabled: true Depends { name: "dummy" } dummy.defines: ["BASEDEF"] Group { name: "the group" files: ["dummy.txt" ] Properties { condition: featureEnabled dummy.defines: outer.concat("FEATURE_ENABLED") } } } qbs-src-1.13.1/tests/auto/language/testdata/properties-item-in-module.qbs000066400000000000000000000002041347155106100264020ustar00rootroot00000000000000Project { Product { name: "a"; Depends { name: "dummyqt.core" } } Product { name: "b"; Depends { name: "dummyqt.core" } } } qbs-src-1.13.1/tests/auto/language/testdata/propertiesblocks.qbs000066400000000000000000000142631347155106100247670ustar00rootroot00000000000000import "propertiesblocks_base.qbs" as ProductBase Project { Product { name: "property_overwrite" Depends { name: "dummy" } dummy.defines: ["SOMETHING"] Properties { condition: true dummy.defines: ["OVERWRITTEN"] } } Product { name: "property_set_indirect" Depends { name: "dummyqt.core" } Properties { condition: true dummyqt.core.zort: "VAL" } } Product { name: "property_overwrite_no_outer" Depends { name: "dummy" } Properties { condition: true dummy.defines: ["OVERWRITTEN"] } } Product { name: "property_append_to_outer" Depends { name: "dummy" } dummy.defines: ["ONE"] Properties { condition: true dummy.defines: outer.concat(["TWO"]) } } Product { name: "property_append_to_indirect_outer" Depends { name: "dummy" } property stringList myDefines: ["ONE"] dummy.defines: myDefines Properties { condition: true dummy.defines: outer.concat(["TWO"]) } } ProductBase { name: "property_append_to_indirect_derived_outer1" Properties { condition: true dummy.cFlags: outer.concat("PROPS") } } ProductBase { name: "property_append_to_indirect_derived_outer2" Properties { condition: true dummy.cFlags: outer.concat("PROPS") } dummy.cFlags: ["PRODUCT"] } ProductBase { name: "property_append_to_indirect_derived_outer3" Properties { condition: true dummy.cFlags: outer.concat("PROPS") } dummy.cFlags: base.concat("PRODUCT") } Product { name: "property_append_to_indirect_merged_outer" Depends { name: "dummy" } property string justOne: "ONE" dummy.rpaths: [justOne] Properties { condition: true dummy.rpaths: outer.concat(["TWO"]) } } Product { name: "multiple_exclusive_properties" Depends { name: "dummy" } dummy.defines: ["SOMETHING"] Properties { condition: true dummy.defines: ["OVERWRITTEN"] } Properties { condition: false dummy.defines: ["IMPOSSIBLE"] } } Product { name: "multiple_exclusive_properties_no_outer" Depends { name: "dummy" } Properties { condition: true dummy.defines: ["OVERWRITTEN"] } Properties { condition: false dummy.defines: ["IMPOSSIBLE"] } } Product { name: "multiple_exclusive_properties_append_to_outer" Depends { name: "dummy" } dummy.defines: ["ONE"] Properties { condition: true dummy.defines: outer.concat(["TWO"]) } Properties { condition: false dummy.defines: ["IMPOSSIBLE"] } } Product { name: "ambiguous_properties" Depends { name: "dummy" } dummy.defines: ["ONE"] Properties { condition: true dummy.defines: outer.concat(["TWO"]) } Properties { condition: false dummy.defines: outer.concat(["IMPOSSIBLE"]) } Properties { // will be ignored condition: true dummy.defines: outer.concat(["THREE"]) } } Product { name: "condition_refers_to_product_property" property bool narf: true property string someString: "SOMETHING" Depends { name: "dummy" } Properties { condition: narf dummy.defines: ["OVERWRITTEN"] someString: "OVERWRITTEN" } } property bool zort: true Product { name: "condition_refers_to_project_property" property string someString: "SOMETHING" Depends { name: "dummy" } Properties { condition: project.zort dummy.defines: ["OVERWRITTEN"] someString: "OVERWRITTEN" } } ProductBase { name: "inheritance_overwrite_in_subitem" dummy.defines: ["OVERWRITTEN_IN_SUBITEM"] } ProductBase { name: "inheritance_retain_base1" dummy.defines: base.concat("SUB") } ProductBase { name: "inheritance_retain_base2" Properties { condition: true dummy.defines: base.concat("SUB") } dummy.defines: ["GNAMPF"] } ProductBase { name: "inheritance_retain_base3" Properties { condition: true dummy.defines: base.concat("SUB") } // no dummy.defines binding } ProductBase { name: "inheritance_retain_base4" Properties { condition: false dummy.defines: ["NEVERMORE"] } // no "else case" for dummy.defines. The value is derived from ProductBase. } ProductBase { name: "inheritance_condition_in_subitem1" defineBase: false dummy.defines: base.concat("SUB") } ProductBase { name: "inheritance_condition_in_subitem2" defineBase: false // no dummy.defines binding } Product { id: knolf name: "gnampf" } Product { name: "condition_references_id" Depends { name: "dummy" } Properties { condition: knolf.name === "gnampf" dummy.defines: ["OVERWRITTEN"] } } Product { name: "using_derived_Properties_item" Depends { name: "dummy" } MyProperties { condition: true dummy.defines: ["string from MyProperties"] } } Product { name: "conditional-depends" Depends { name: "dummy" condition: false } Properties { condition: false dummy.defines: ["a string"] } } Product { name: "use-module-with-properties-item" Depends { name: "module-with-properties-item" } } } qbs-src-1.13.1/tests/auto/language/testdata/propertiesblocks_base.qbs000066400000000000000000000004111347155106100257470ustar00rootroot00000000000000Product { property bool defineBase: true Depends { name: "dummy" } Properties { condition: defineBase dummy.defines: ["BASE"] } dummy.defines: ["SOMETHING"] property stringList myCFlags: ["BASE"] dummy.cFlags: myCFlags } qbs-src-1.13.1/tests/auto/language/testdata/property-assignment-in-exported-group.qbs000066400000000000000000000004731347155106100310130ustar00rootroot00000000000000Project { Product { name: "dep" Export { Depends { name: "dummy" } Group { name: "exported_group" dummy.someString: "test" files: ["narf"] } } } Product { Depends { name: "dep" } } } qbs-src-1.13.1/tests/auto/language/testdata/qbs-properties-in-project-condition.qbs000066400000000000000000000001601347155106100303770ustar00rootroot00000000000000Project { condition: qbs.targetOS.contains("whatever") Product { name: "never reached" } } qbs-src-1.13.1/tests/auto/language/testdata/qbs-property-convenience-override.qbs000066400000000000000000000000761347155106100301500ustar00rootroot00000000000000Product { name: "p" qbs.installPrefix: "/usr/local" } qbs-src-1.13.1/tests/auto/language/testdata/qbs1275.qbs000066400000000000000000000011111347155106100224650ustar00rootroot00000000000000Project { Product { name: "v-bug" Export { Depends { name: "cpp"} cpp.defines: "" } } Product { name: "e-bug" Export { Depends { name: "v-bug" } } } Product { name: "u-bug" Export { Depends { name: "c-bug" } } } Product { name: "c-bug" Export { Depends { name: "e-bug" } } } Product { name: "H-bug" Depends { name: "e-bug" } Depends { name: "u-bug" } Group { qbs.install: true } } } qbs-src-1.13.1/tests/auto/language/testdata/recursive-dependencies/000077500000000000000000000000001347155106100253135ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/recursive-dependencies/recursive-dependencies.qbs000066400000000000000000000004301347155106100324520ustar00rootroot00000000000000Project { Product { name: "p1" Depends { name: "p3" } } Product { name: "p2" Depends { name: "p3" } } Product { name: "p3" Export { Depends { name: "p4" } } } Product { name: "p4" } } qbs-src-1.13.1/tests/auto/language/testdata/relaxed-error-mode/000077500000000000000000000000001347155106100243555ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/relaxed-error-mode/file1.txt000066400000000000000000000000001347155106100261040ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/relaxed-error-mode/file2.txt000066400000000000000000000000001347155106100261050ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/relaxed-error-mode/relaxed-error-mode.qbs000066400000000000000000000012101347155106100305530ustar00rootroot00000000000000Project { Product { name: "recursive depender" Depends { name: "depender required" } files: "file1.txt" } Product { name: "broken" Depends { name: "nosuchmodule" } } Product { name: "depender required" Depends { name: "broken" } files: "file1.txt" } Product { name: "depender nonrequired" Depends { name: "broken"; required: false } files: "file1.txt" } Product { name: "missing file" files: ["file1.txt", "file3.txt", "file2.txt"] } Product { name: "fine" files: "file2.txt" } } qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/000077500000000000000000000000001347155106100302155ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/complicated.qbs000066400000000000000000000003011347155106100332020ustar00rootroot00000000000000Product { Depends { name: "failing-validation"; required: false } Depends { name: "failing-validation-indirect" } Depends { name: "failing-validation-indirect"; required: false } } dependency-via-export.qbs000066400000000000000000000003671347155106100350650ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependenciesProject { Product { name: "dep" Export { Depends { name: "failing-validation" } } } Product { Depends { name: "failing-validation"; required: false } Depends { name: "dep" } } } dependency-via-module.qbs000066400000000000000000000001741347155106100350250ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependenciesProduct { Depends { name: "failing-validation"; required: false } Depends { name: "failing-validation-indirect" } } direct-dependencies.qbs000066400000000000000000000001631347155106100345430ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependenciesProduct { Depends { name: "failing-validation"; required: false } Depends { name: "failing-validation" } } qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/000077500000000000000000000000001347155106100316655ustar00rootroot00000000000000failing-validation-indirect/000077500000000000000000000000001347155106100371465ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modulesfailing-validation-indirect.qbs000066400000000000000000000000661347155106100452170ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/failing-validation-indirectModule { Depends { name: "failing-validation" } } failing-validation/000077500000000000000000000000001347155106100353475ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modulesfailing-validation.qbs000066400000000000000000000000701347155106100416140ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependencies/modules/failing-validationModule { validate: { throw "validation error!"; } } required-chain-export-indirect.qbs000066400000000000000000000005751347155106100366720ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependenciesProject { Product { name: "dep2" Export { Depends { name: "dep1" } } } Product { name: "dep1" Export { Depends { name: "failing-validation-indirect" } } } Product { Depends { name: "failing-validation"; required: false } Depends { name: "dep2"; required: false } } } required-chain-export.qbs000066400000000000000000000004101347155106100350570ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependenciesProject { Product { name: "dep" Export { Depends { name: "failing-validation" } } } Product { Depends { name: "failing-validation"; required: false } Depends { name: "dep"; required: false } } } required-chain-module.qbs000066400000000000000000000002151347155106100350260ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/required-and-nonrequired-dependenciesProduct { Depends { name: "failing-validation"; required: false } Depends { name: "failing-validation-indirect"; required: false } } qbs-src-1.13.1/tests/auto/language/testdata/rfc1034identifier.qbs000066400000000000000000000004641347155106100245200ustar00rootroot00000000000000import qbs.Utilities CppApplication { name: Utilities.rfc1034Identifier("this!has@special#characters$uh-oh,Undersc0r3s_Are.Bad") Properties { condition: qbs.targetOS.contains("darwin") bundle.infoPlist: { return {"CFBundleIdentifier": "$(PRODUCT_NAME:rfc1034identifier)"}; } } } qbs-src-1.13.1/tests/auto/language/testdata/subdir/000077500000000000000000000000001347155106100221505ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/subdir/exports-mylib.qbs000066400000000000000000000007141347155106100254770ustar00rootroot00000000000000StaticLibrary { name: "mylib" Depends { name: "dummy" } dummy.defines: ["BUILD_" + product.name.toUpperCase()] property string definePrefix: "USE_" property path aPath: "." dummy.somePath: aPath Export { Depends { name: "dummy" } Depends { name: "mylib2" } dummy.defines: [product.definePrefix + product.name.toUpperCase()] dummy.includePaths: ["./lib"] dummy.somePath: product.aPath } } qbs-src-1.13.1/tests/auto/language/testdata/subdir/pathproperties_base.qbs000066400000000000000000000001661347155106100267250ustar00rootroot00000000000000Product { property path base_fileInProductDir: "foo" property path base_fileInBaseProductDir: path + "/bar" } qbs-src-1.13.1/tests/auto/language/testdata/subdir2/000077500000000000000000000000001347155106100222325ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/testdata/subdir2/exports-mylib2.qbs000066400000000000000000000005151347155106100256420ustar00rootroot00000000000000StaticLibrary { name: "mylib2" Depends { name: "dummy" } dummy.defines: ["BUILD_" + product.name.toUpperCase()] property string definePrefix: "USE_" Export { Depends { name: "dummy" } dummy.defines: [product.definePrefix + product.name.toUpperCase()] dummy.includePaths: ["./lib"] } } qbs-src-1.13.1/tests/auto/language/testdata/suppressed-and-non-suppressed-errors.qbs000066400000000000000000000003431347155106100306210ustar00rootroot00000000000000Project { CppApplication { name: "mysterious creature" files: ["easter bunny"] } Product { name: "tasty food" condition: false Depends { name: "TheBeautifulSausage" } } } qbs-src-1.13.1/tests/auto/language/testdata/throwing-probe.qbs000066400000000000000000000003021347155106100243300ustar00rootroot00000000000000Product { name: "theProduct" property bool enableProbe Probe { id: whatever condition: enableProbe configure: { throw "Error!"; } } } qbs-src-1.13.1/tests/auto/language/testdata/versionCompare.qbs000066400000000000000000000011351347155106100243630ustar00rootroot00000000000000import qbs.Utilities Product { name: { var e = "unexpected comparison result"; if (Utilities.versionCompare("1.5", "1.5") !== 0) throw e; if (Utilities.versionCompare("1.5", "1.5.0") !== 0) throw e; if (Utilities.versionCompare("1.5", "1.6") >= 0) throw e; if (Utilities.versionCompare("1.6", "1.5") <= 0) throw e; if (Utilities.versionCompare("2.5", "1.6") <= 0) throw e; if (Utilities.versionCompare("1.6", "2.5") >= 0) throw e; return "versionCompare"; } } qbs-src-1.13.1/tests/auto/language/testdata/zort000066400000000000000000000000001347155106100215670ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/language/tst_language.cpp000066400000000000000000004204611347155106100222370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #undef QT_NO_CAST_FROM_ASCII // I am qmake, and I approve this hack. #include "tst_language.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../shared/logging/consolelogger.h" #include #include #include #include #include Q_DECLARE_METATYPE(QList) using namespace qbs; using namespace qbs::Internal; static QString testDataDir() { return FileInfo::resolvePath(QStringLiteral(SRCDIR), QStringLiteral("../../../tests/auto/language/testdata")); } static QString testProject(const char *fileName) { return testDataDir() + QLatin1Char('/') + QLatin1String(fileName); } TestLanguage::TestLanguage(ILogSink *logSink, Settings *settings) : m_logSink(logSink) , m_settings(settings) , m_wildcardsTestDirPath(QDir::tempPath() + QLatin1String("/_wildcards_test_dir_")) { qsrand(QTime::currentTime().msec()); qRegisterMetaType >("QList"); defaultParameters.setBuildRoot(m_tempDir.path() + "/buildroot"); defaultParameters.setPropertyCheckingMode(ErrorHandlingMode::Strict); defaultParameters.setSettingsDirectory(m_settings->baseDirectory()); } TestLanguage::~TestLanguage() { } QHash TestLanguage::productsFromProject(ResolvedProjectPtr project) { QHash result; const auto products = project->allProducts(); for (const ResolvedProductPtr &product : products) result.insert(product->name, product); return result; } template typename C::value_type findByName(const C &container, const QString &name) { auto endIt = std::end(container); auto it = std::find_if(std::begin(container), endIt, [&name] (const typename C::value_type &thing) { return thing->name == name; }); if (it != endIt) return *it; return typename C::value_type(); } ResolvedModuleConstPtr TestLanguage::findModuleByName(ResolvedProductPtr product, const QString &name) { return findByName(product->modules, name); } QVariant TestLanguage::productPropertyValue(ResolvedProductPtr product, QString propertyName) { QStringList propertyNameComponents = propertyName.split(QLatin1Char('.')); if (propertyNameComponents.size() > 1) return product->moduleProperties->property(propertyNameComponents); return getConfigProperty(product->productProperties, propertyNameComponents); } void TestLanguage::handleInitCleanupDataTags(const char *projectFileName, bool *handled) { const QByteArray dataTag = QTest::currentDataTag(); if (dataTag == "init") { *handled = true; bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject(projectFileName)); project = loader->loadProject(defaultParameters); QVERIFY(!!project); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } else if (dataTag == "cleanup") { *handled = true; project.reset(); } else { *handled = false; } } void TestLanguage::init() { m_logSink->setLogLevel(LoggerInfo); QVERIFY(m_tempDir.isValid()); } #define HANDLE_INIT_CLEANUP_DATATAGS(fn) {\ bool handled;\ handleInitCleanupDataTags(fn, &handled);\ if (handled)\ return;\ QVERIFY(!!project);\ } void TestLanguage::initTestCase() { m_logger = Logger(m_logSink); m_engine = ScriptEngine::create(m_logger, EvalContext::PropertyEvaluation, this); loader = new Loader(m_engine, m_logger); loader->setSearchPaths(QStringList() << QStringLiteral(SRCDIR "/../../../share/qbs")); defaultParameters.setTopLevelProfile(profileName()); defaultParameters.setConfigurationName("default"); defaultParameters.expandBuildConfiguration(); defaultParameters.setEnvironment(QProcessEnvironment::systemEnvironment()); QVERIFY(QFileInfo(m_wildcardsTestDirPath).isAbsolute()); } void TestLanguage::cleanupTestCase() { delete loader; } void TestLanguage::additionalProductTypes() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("additional-product-types.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(!!project); const QHash products = productsFromProject(project); const ResolvedProductConstPtr product = products.value("p"); QVERIFY(!!product); const QVariantMap cfg = product->productProperties; QVERIFY(cfg.value("hasTag1").toBool()); QVERIFY(cfg.value("hasTag2").toBool()); QVERIFY(cfg.value("hasTag3").toBool()); QVERIFY(!cfg.value("hasTag4").toBool()); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::baseProperty() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("baseproperty.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(!!product); QVariantMap cfg = product->productProperties; QCOMPARE(cfg.value("narf").toStringList(), QStringList() << "boo"); QCOMPARE(cfg.value("zort").toStringList(), QStringList() << "bar" << "boo"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::baseValidation() { qbs::SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("base-validate/base-validate.qbs")); try { project = loader->loadProject(params); QVERIFY2(false, "exception expected"); } catch (const qbs::ErrorInfo &e) { QVERIFY2(e.toString().contains("Parent succeeded, child failed."), qPrintable(e.toString())); } } void TestLanguage::brokenDependencyCycle() { qbs::SetupProjectParameters params = defaultParameters; QFETCH(QString, projectFileName); params.setProjectFilePath(testProject(qPrintable(projectFileName))); try { project = loader->loadProject(params); } catch (const qbs::ErrorInfo &e) { QVERIFY2(false, qPrintable(e.toString())); } } void TestLanguage::brokenDependencyCycle_data() { QTest::addColumn("projectFileName"); QTest::newRow("one order of products") << "broken-dependency-cycle1.qbs"; QTest::newRow("another order of products") << "broken-dependency-cycle2.qbs"; } void TestLanguage::buildConfigStringListSyntax() { bool exceptionCaught = false; try { SetupProjectParameters parameters = defaultParameters; QVariantMap overriddenValues; overriddenValues.insert("project.someStrings", "foo,bar,baz"); parameters.setOverriddenValues(overriddenValues); parameters.setProjectFilePath(testProject("buildconfigstringlistsyntax.qbs")); project = loader->loadProject(parameters); QVERIFY(!!project); QCOMPARE(project->projectProperties().value("someStrings").toStringList(), QStringList() << "foo" << "bar" << "baz"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::builtinFunctionInSearchPathsProperty() { bool exceptionCaught = false; try { SetupProjectParameters parameters = defaultParameters; parameters.setProjectFilePath(testProject("builtinFunctionInSearchPathsProperty.qbs")); QVERIFY(!!loader->loadProject(parameters)); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::chainedProbes() { bool exceptionCaught = false; try { SetupProjectParameters parameters = defaultParameters; parameters.setProjectFilePath(testProject("chained-probes/chained-probes.qbs")); const TopLevelProjectConstPtr project = loader->loadProject(parameters); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); const QString prop2Val = project->products.front()->moduleProperties ->moduleProperty("m", "prop2").toString(); QCOMPARE(prop2Val, QLatin1String("probe1Valprobe2Val")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::versionCompare() { bool exceptionCaught = false; try { SetupProjectParameters parameters = defaultParameters; parameters.setProjectFilePath(testProject("versionCompare.qbs")); QVERIFY(!!loader->loadProject(parameters)); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::canonicalArchitecture() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("canonicalArchitecture.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value(QStringLiteral("x86")); QVERIFY(!!product); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::rfc1034Identifier() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("rfc1034identifier.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value(QStringLiteral("this-has-special-characters-" "uh-oh-Undersc0r3s-Are.Bad")); QVERIFY(!!product); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::conditionalDepends() { bool exceptionCaught = false; ResolvedProductPtr product; ResolvedModuleConstPtr dependency; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("conditionaldepends.qbs")); params.setOverriddenValues({std::make_pair(QString("products." "multilevel_module_props_overridden.dummy3.loadDummy"), true)}); project = loader->loadProject(params); QVERIFY(!!project); QHash products = productsFromProject(project); product = products.value("conditionaldepends_derived"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("conditionaldepends_derived_false"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("product_props_true"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("product_props_false"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("project_props_true"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("project_props_false"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("module_props_true"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy2"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("module_props_false"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy2"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("multilevel_module_props_true"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy3"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("multilevel_module_props_false"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy3"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("multilevel_module_props_overridden"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy3"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("multilevel2_module_props_true"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy3_loader"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy3"); QVERIFY(!!dependency); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("contradictory_conditions1"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("contradictory_conditions2"); QVERIFY(!!product); dependency = findModuleByName(product, "dummy"); QVERIFY(!!dependency); product = products.value("unknown_dependency_condition_false"); QVERIFY(!!product); dependency = findModuleByName(product, "doesonlyexistifhellfreezesover"); QVERIFY(!dependency); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::delayedError() { QFETCH(bool, productEnabled); try { QFETCH(QString, projectFileName); SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject(projectFileName.toLatin1())); QVariantMap overriddenValues; overriddenValues.insert("project.enableProduct", productEnabled); params.setOverriddenValues(overriddenValues); project = loader->loadProject(params); QCOMPARE(productEnabled, false); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); const ResolvedProductConstPtr theProduct = productsFromProject(project).value("theProduct"); QVERIFY(!!theProduct); QCOMPARE(theProduct->enabled, false); } catch (const ErrorInfo &e) { if (!productEnabled) qDebug() << e.toString(); QCOMPARE(productEnabled, true); } } void TestLanguage::delayedError_data() { QTest::addColumn("projectFileName"); QTest::addColumn("productEnabled"); QTest::newRow("product enabled, module validation error") << "delayed-error/validation.qbs" << true; QTest::newRow("product disabled, module validation error") << "delayed-error/validation.qbs" << false; QTest::newRow("product enabled, module not found") << "delayed-error/nonexisting.qbs" << true; QTest::newRow("product disabled, module not found") << "delayed-error/nonexisting.qbs" << false; } void TestLanguage::dependencyOnAllProfiles() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("dependencyOnAllProfiles.qbs")); TemporaryProfile p1("p1", m_settings); p1.p.setValue("qbs.architecture", "arch1"); TemporaryProfile p2("p2", m_settings); p2.p.setValue("qbs.architecture", "arch2"); QVariantMap overriddenValues; overriddenValues.insert("project.profile1", "p1"); overriddenValues.insert("project.profile2", "p2"); params.setOverriddenValues(overriddenValues); project = loader->loadProject(params); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(3)); const ResolvedProductConstPtr mainProduct = productsFromProject(project).value("main"); QVERIFY(!!mainProduct); QCOMPARE(mainProduct->dependencies.size(), size_t { 2 }); for (const ResolvedProductConstPtr &p : mainProduct->dependencies) { QCOMPARE(p->name, QLatin1String("dep")); QVERIFY(p->profile() == "p1" || p->profile() == "p2"); } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::derivedSubProject() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("derived-sub-project/project.qbs")); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::disabledSubProject() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("disabled-subproject.qbs")); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 0); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::dottedNames_data() { QTest::addColumn("useProduct"); QTest::addColumn("useModule"); QTest::addColumn("expectSuccess"); QTest::addColumn("expectedErrorMessage"); QTest::newRow("missing product dependency") << false << true << false << QString("Item 'a.b' is not declared. Did you forget to add a Depends item"); QTest::newRow("missing module dependency") << true << false << false << QString("Item 'x.y' is not declared. Did you forget to add a Depends item"); QTest::newRow("missing both dependencies") << false << false << false << QString(); QTest::newRow("ok") << true << true << true << QString(); } void TestLanguage::dottedNames() { QFETCH(bool, expectSuccess); try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("dotted-names/dotted-names.qbs")); QFETCH(bool, useProduct); QFETCH(bool, useModule); const QVariantMap overridden{ std::make_pair("projects.theProject.includeDottedProduct", useProduct), std::make_pair("projects.theProject.includeDottedModule", useModule) }; params.setOverriddenValues(overridden); TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(expectSuccess); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), useProduct ? 2 : 1); const ResolvedProductPtr product = products.value("p"); QVERIFY(!!product); QCOMPARE(product->moduleProperties->moduleProperty("a.b", "c").toString(), QString("p")); QCOMPARE(product->moduleProperties->moduleProperty("x.y", "z").toString(), QString("p")); } catch (const ErrorInfo &e) { QVERIFY(!expectSuccess); QFETCH(QString, expectedErrorMessage); if (!expectedErrorMessage.isEmpty()) QVERIFY2(e.toString().contains(expectedErrorMessage), qPrintable(e.toString())); } } void TestLanguage::emptyJsFile() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("empty-js-file.qbs")); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::enumerateProjectProperties() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("enum-project-props.qbs")); auto project = loader->loadProject(params); QVERIFY(!!project); auto products = productsFromProject(project); QCOMPARE(products.size(), 1); auto product = products.values().front(); auto files = product->groups.front()->allFiles(); QCOMPARE(product->groups.size(), size_t(1)); QCOMPARE(files.size(), size_t(1)); auto fileName = FileInfo::fileName(files.front()->absoluteFilePath); QCOMPARE(fileName, QString("dummy.txt")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::evalErrorInNonPresentModule_data() { QTest::addColumn("moduleRequired"); QTest::addColumn("errorMessage"); QTest::newRow("module required") << true << "broken.qbs:4:5 Element at index 0 of list property 'broken' " "does not have string type"; QTest::newRow("module not required") << false << QString(); } void TestLanguage::evalErrorInNonPresentModule() { QFETCH(bool, moduleRequired); QFETCH(QString, errorMessage); try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("eval-error-in-non-present-module.qbs")); QVariantMap overridden{std::make_pair("products.p.moduleRequired", moduleRequired)}; params.setOverriddenValues(overridden); TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(errorMessage.isEmpty()); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); const ResolvedProductPtr product = products.value("p"); QVERIFY(!!product); } catch (const ErrorInfo &e) { QVERIFY(!errorMessage.isEmpty()); QVERIFY2(e.toString().contains(errorMessage), qPrintable(e.toString())); } } void TestLanguage::defaultValue() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("defaultvalue/egon.qbs")); QFETCH(QString, prop1Value); QVariantMap overridden; if (!prop1Value.isEmpty()) overridden.insert("modules.lower.prop1", prop1Value); params.setOverriddenValues(overridden); TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 2); const ResolvedProductPtr product = products.value("egon"); QVERIFY(!!product); QStringList propertyName = QStringList() << "lower" << "prop2"; QVariant propertyValue = product->moduleProperties->property(propertyName); QFETCH(QVariant, expectedProp2Value); QCOMPARE(propertyValue, expectedProp2Value); propertyName = QStringList() << "lower" << "listProp"; propertyValue = product->moduleProperties->property(propertyName); QFETCH(QVariant, expectedListPropValue); QCOMPARE(propertyValue.toStringList(), expectedListPropValue.toStringList()); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::defaultValue_data() { QTest::addColumn("prop1Value"); QTest::addColumn("expectedProp2Value"); QTest::addColumn("expectedListPropValue"); QTest::newRow("controlling property with random value") << "random" << QVariant("withoutBlubb") << QVariant(QStringList({"other"})); QTest::newRow("controlling property with blubb value") << "blubb" << QVariant("withBlubb") << QVariant(QStringList({"blubb", "other"})); QTest::newRow("controlling property with egon value") << "egon" << QVariant("withEgon") << QVariant(QStringList({"egon", "other"})); QTest::newRow("controlling property not overwritten") << "" << QVariant("withBlubb") << QVariant(QStringList({"blubb", "other"})); } void TestLanguage::environmentVariable() { bool exceptionCaught = false; try { // Create new environment: const QString varName = QStringLiteral("PRODUCT_NAME"); const QString productName = QLatin1String("MyApp") + QString::number(qrand()); QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(varName, productName); QProcessEnvironment origEnv = defaultParameters.environment(); // store orig environment defaultParameters.setEnvironment(env); defaultParameters.setProjectFilePath(testProject("environmentvariable.qbs")); project = loader->loadProject(defaultParameters); defaultParameters.setEnvironment(origEnv); // reset environment QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value(productName); QVERIFY(!!product); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::errorInDisabledProduct() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("error-in-disabled-product.qbs")); auto project = loader->loadProject(params); QVERIFY(!!project); auto products = productsFromProject(project); QCOMPARE(products.size(), 5); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::erroneousFiles_data() { QTest::addColumn("errorMessage"); QTest::newRow("unknown_module") << "Dependency 'neitherModuleNorProduct' not found"; QTest::newRow("multiple_exports") << "Multiple Export items in one product are prohibited."; QTest::newRow("multiple_properties_in_subproject") << "Multiple instances of item 'Properties' found where at most one " "is allowed."; QTest::newRow("importloop1") << "Loop detected when importing"; QTest::newRow("nonexistentouter") << "Can't find variable: outer"; QTest::newRow("invalid_file") << "does not exist"; QTest::newRow("invalid-parameter-rhs") << "ReferenceError: Can't find variable: access"; QTest::newRow("invalid-parameter-type") << "Value assigned to property 'stringParameter' does not have type 'string'."; QTest::newRow("invalid_property_type") << "Unknown type 'nonsense' in property declaration."; QTest::newRow("reserved_name_in_import") << "Cannot reuse the name of built-in extension 'TextFile'."; QTest::newRow("throw_in_property_binding") << "something is wrong"; QTest::newRow("no-configure-in-probe") << "no-configure-in-probe.qbs:2:5.*Probe.configure must be set"; QTest::newRow("dependency_cycle") << "Cyclic dependencies detected."; QTest::newRow("dependency_cycle2") << "Cyclic dependencies detected."; QTest::newRow("dependency_cycle3") << "Cyclic dependencies detected."; QTest::newRow("dependency_cycle4") << "Cyclic dependencies detected."; QTest::newRow("references_cycle") << "Cycle detected while referencing file 'references_cycle.qbs'."; QTest::newRow("subproject_cycle") << "Cycle detected while loading subproject file 'subproject_cycle.qbs'."; QTest::newRow("invalid_stringlist_element") << "Element at index 1 of list property 'files' does not have string type."; QTest::newRow("undefined_stringlist_element") << "Element at index 1 of list property 'files' is undefined. String expected."; QTest::newRow("undefined_stringlist_element_in_probe") << "Element at index 1 of list property 'l' is undefined. String expected."; QTest::newRow("undeclared_item") << "Item 'cpp' is not declared."; QTest::newRow("undeclared-parameter1") << "Parameter 'prefix2.suffix.nope' is not declared."; QTest::newRow("undeclared-parameter2") << "Cannot set parameter 'foo.bar', " "because 'myproduct' does not have a dependency on 'foo'."; QTest::newRow("undeclared_property_wrapper") << "Property 'doesntexist' is not declared."; QTest::newRow("undeclared_property_in_export_item") << "Property 'blubb' is not declared."; QTest::newRow("undeclared_property_in_export_item2") << "Item 'something' is not declared."; QTest::newRow("undeclared_property_in_export_item3") << "Property 'blubb' is not declared."; QTest::newRow("undeclared_module_property_in_module") << "Property 'noSuchProperty' is not declared."; QTest::newRow("unknown_item_type") << "Unexpected item type 'Narf'"; QTest::newRow("invalid_child_item_type") << "Items of type 'Project' cannot contain items of type 'Depends'."; QTest::newRow("conflicting_fileTagsFilter") << "Conflicting fileTagsFilter in Group items"; QTest::newRow("duplicate_sources") << "Duplicate source file '.*main.cpp'" ".*duplicate_sources.qbs:2:12.*duplicate_sources.qbs:4:16."; QTest::newRow("duplicate_sources_wildcards") << "Duplicate source file '.*duplicate_sources_wildcards.qbs'" ".*duplicate_sources_wildcards.qbs:2:12" ".*duplicate_sources_wildcards.qbs:4:16."; QTest::newRow("oldQbsVersion") << "The project requires at least qbs version \\d+\\.\\d+.\\d+, " "but this is qbs version " QBS_VERSION "."; QTest::newRow("wrongQbsVersionFormat") << "The value '.*' of Project.minimumQbsVersion is not a valid version string."; QTest::newRow("properties-item-with-invalid-condition") << "properties-item-with-invalid-condition.qbs:4:19.*TypeError: Result of expression " "'cpp.nonexistingproperty'"; QTest::newRow("misused-inherited-property") << "Binding to non-item property"; QTest::newRow("undeclared_property_in_Properties_item") << "Item 'blubb' is not declared"; QTest::newRow("same-module-prefix1") << "The name of module 'prefix1' is equal to the first " "component of the name of module 'prefix1.suffix'"; QTest::newRow("same-module-prefix2") << "The name of module 'prefix2' is equal to the first " "component of the name of module 'prefix2.suffix'"; QTest::newRow("conflicting-properties-in-export-items") << "Export item in inherited item redeclares property 'theProp' with different type."; QTest::newRow("invalid-property-option") << "PropertyOptions item refers to non-existing property 's0meProp'"; QTest::newRow("missing-colon") << "Invalid item 'cpp.dynamicLibraries'. Did you mean to set a module property?"; QTest::newRow("syntax-error-in-probe") << "syntax-error-in-probe.qbs:4:20.*ReferenceError"; QTest::newRow("wrong-toplevel-item") << "wrong-toplevel-item.qbs:1:1.*The top-level item must be of type 'Project' or " "'Product', but it is of type 'Artifact'."; QTest::newRow("conflicting-module-instances") << "There is more than one equally prioritized candidate for module " "'conflicting-instances'."; QTest::newRow("module-depends-on-product") << "module-with-product-dependency.qbs:2:5.*Modules cannot depend on products."; QTest::newRow("overwrite-inherited-readonly-property") << "overwrite-inherited-readonly-property.qbs" ":2:21.*Cannot set read-only property 'readOnlyString'."; QTest::newRow("overwrite-readonly-module-property") << "overwrite-readonly-module-property.qbs" ":3:30.*Cannot set read-only property 'readOnlyString'."; QTest::newRow("original-in-product-property") << "original-in-product-property.qbs" ":2:21.*The special value 'original' can only be used with module properties."; QTest::newRow("rule-without-output-tags") << "rule-without-output-tags.qbs:2:5.*A rule needs to have Artifact items or " "a non-empty outputFileTags property."; QTest::newRow("original-in-module-prototype") << "module-with-invalid-original.qbs:2:24.*The special value 'original' cannot be used " "on the right-hand side of a property declaration."; QTest::newRow("original-in-export-item") << "original-in-export-item.qbs:7:32.*The special value 'original' cannot be used " "on the right-hand side of a property declaration."; QTest::newRow("original-in-export-item2") << "original-in-export-item2.qbs:6:9.*Item 'x.y' is not declared. Did you forget " "to add a Depends item"; QTest::newRow("original-in-export-item3") << "original-in-export-item3.qbs:6:9.*Item 'x.y' is not declared. Did you forget " "to add a Depends item"; QTest::newRow("mismatching-multiplex-dependency") << "mismatching-multiplex-dependency.qbs:7:5.*Dependency from product " "'b \\{\"architecture\":\"mips\"\\}' to product 'a \\{\"architecture\":\"mips\"\\}'" " not fulfilled."; QTest::newRow("duplicate-multiplex-value") << "duplicate-multiplex-value.qbs:3:1.*Duplicate entry 'x86' in qbs.architectures."; QTest::newRow("duplicate-multiplex-value2") << "duplicate-multiplex-value2.qbs:3:1.*Duplicate entry 'architecture' in " "Product.multiplexByQbsProperties."; QTest::newRow("invalid-references") << "invalid-references.qbs:2:17.*Cannot open '.*nosuchproject.qbs'"; } void TestLanguage::erroneousFiles() { QFETCH(QString, errorMessage); QString fileName = QString::fromLocal8Bit(QTest::currentDataTag()) + QLatin1String(".qbs"); try { defaultParameters.setProjectFilePath(testProject("/erroneous/") + fileName); loader->loadProject(defaultParameters); } catch (const ErrorInfo &e) { if (!e.toString().contains(QRegExp(errorMessage))) { qDebug() << "Message: " << e.toString(); qDebug() << "Expected: " << errorMessage; QFAIL("Unexpected error message."); } return; } QEXPECT_FAIL("undeclared_property_in_Properties_item", "Too expensive to check", Continue); QEXPECT_FAIL("original-in-export-item3", "Too expensive to check", Continue); QVERIFY(!"No error thrown on invalid input."); } void TestLanguage::exports() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("exports.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 22); ResolvedProductPtr product; product = products.value("myapp"); QVERIFY(!!product); QStringList propertyName = QStringList() << "dummy" << "defines"; QVariant propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "BUILD_MYAPP" << "USE_MYLIB" << "USE_MYLIB2"); propertyName = QStringList() << "dummy" << "includePaths"; QVariantList propertyValues = product->moduleProperties->property(propertyName).toList(); QCOMPARE(propertyValues.size(), 3); QVERIFY(propertyValues.at(0).toString().endsWith("/app")); QVERIFY(propertyValues.at(1).toString().endsWith("/subdir/lib")); QVERIFY(propertyValues.at(2).toString().endsWith("/subdir2/lib")); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "productName").toString(), QString("myapp")); QVERIFY(product->moduleProperties->moduleProperty("dummy", "somePath").toString() .endsWith("/subdir")); product = products.value("mylib"); QVERIFY(!!product); propertyName = QStringList() << "dummy" << "defines"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "BUILD_MYLIB"); QVERIFY(product->moduleProperties->moduleProperty("dummy", "somePath").toString() .endsWith("/subdir")); product = products.value("mylib2"); QVERIFY(!!product); propertyName = QStringList() << "dummy" << "defines"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "BUILD_MYLIB2"); product = products.value("A"); QVERIFY(!!product); QVERIFY(contains(product->dependencies, products.value("B"))); QVERIFY(contains(product->dependencies, products.value("C"))); QVERIFY(contains(product->dependencies, products.value("D"))); product = products.value("B"); QVERIFY(!!product); QVERIFY(product->dependencies.empty()); product = products.value("C"); QVERIFY(!!product); QVERIFY(product->dependencies.empty()); product = products.value("D"); QVERIFY(!!product); QVERIFY(product->dependencies.empty()); product = products.value("myapp2"); QVERIFY(!!product); propertyName = QStringList() << "dummy" << "cFlags"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "BASE_PRODUCTWITHINHERITEDEXPORTITEM" << "PRODUCT_PRODUCTWITHINHERITEDEXPORTITEM"); propertyName = QStringList() << "dummy" << "cxxFlags"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "-bar"); propertyName = QStringList() << "dummy" << "defines"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList({"ABC", "DEF"})); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "productName").toString(), QString("myapp2")); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "upperCaseProductName").toString(), QString("MYAPP2")); // Check whether we're returning incorrect cached values. product = products.value("myapp3"); QVERIFY(!!product); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "productName").toString(), QString("myapp3")); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "upperCaseProductName").toString(), QString("MYAPP3")); // Verify we refer to the right "project" variable. product = products.value("sub p2"); QVERIFY(!!product); QCOMPARE(product->moduleProperties->moduleProperty("dummy", "someString").toString(), QString("sub1")); product = products.value("libE"); QVERIFY(!!product); propertyName = QStringList() << "dummy" << "defines"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "LIBA" << "LIBB" << "LIBC" << "LIBD"); propertyName = QStringList() << "dummy" << "productName"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toString(), QString("libE")); product = products.value("depender"); QVERIFY(!!product); QCOMPARE(product->modules.size(), size_t(2)); for (const ResolvedModuleConstPtr &m : product->modules) { QVERIFY2(m->name == QString("qbs") || m->name == QString("dependency"), qPrintable(m->name)); } QCOMPARE(product->productProperties.value("featureX").toBool(), true); QCOMPARE(product->productProperties.value("featureY").toBool(), false); QCOMPARE(product->productProperties.value("featureZ").toBool(), true); product = products.value("broken_cycle3"); QVERIFY(!!product); QCOMPARE(product->modules.size(), size_t(3)); for (const ResolvedModuleConstPtr &m : product->modules) { QVERIFY2(m->name == QString("qbs") || m->name == QString("broken_cycle1") || m->name == QString("broken_cycle2"), qPrintable(m->name)); } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::fileContextProperties() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("filecontextproperties.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(!!product); QVariantMap cfg = product->productProperties; QCOMPARE(cfg.value("narf").toString(), defaultParameters.projectFilePath()); QString dirPath = QFileInfo(defaultParameters.projectFilePath()).absolutePath(); QCOMPARE(cfg.value("zort").toString(), dirPath); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::fileInProductAndModule_data() { QTest::addColumn("file1IsTarget"); QTest::addColumn("file2IsTarget"); QTest::addColumn("addFileToProduct"); QTest::addColumn("successExpected"); QTest::newRow("file occurs twice in module as non-target") << false << false << false << false; QTest::newRow("file occurs twice in module as non-target, and in product as well") << false << false << true << false; QTest::newRow("file occurs in module as non-target and target") << false << true << false << true; QTest::newRow("file occurs in module as non-target and target, and in product as well") << false << true << true << false; QTest::newRow("file occurs in module as target and non-target") << true << false << false << true; QTest::newRow("file occurs in module as target and non-target, and in product as well") << true << false << true << false; QTest::newRow("file occurs twice in module as target") << true << true << false << false; QTest::newRow("file occurs twice in module as target, and in product as well") << true << true << true << false; } void TestLanguage::fileInProductAndModule() { bool exceptionCaught = false; QFETCH(bool, file1IsTarget); QFETCH(bool, file2IsTarget); QFETCH(bool, addFileToProduct); QFETCH(bool, successExpected); try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("file-in-product-and-module.qbs")); params.setOverriddenValues(QVariantMap{ std::make_pair("modules.module_with_file.file1IsTarget", file1IsTarget), std::make_pair("modules.module_with_file.file2IsTarget", file2IsTarget), std::make_pair("products.p.addFileToProduct", addFileToProduct), }); project = loader->loadProject(params); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); } catch (const ErrorInfo &e) { exceptionCaught = true; QVERIFY2(e.toString().contains("Duplicate"), qPrintable(e.toString())); } QCOMPARE(exceptionCaught, !successExpected); } void TestLanguage::getNativeSetting() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("getNativeSetting.qbs")); project = loader->loadProject(defaultParameters); QString expectedTargetName; if (HostOsInfo::isMacosHost()) expectedTargetName = QStringLiteral("Mac OS X"); else if (HostOsInfo::isWindowsHost()) expectedTargetName = QStringLiteral("Windows"); else expectedTargetName = QStringLiteral("Unix"); QVERIFY(!!project); QHash products; for (const ResolvedProductPtr &product : project->allProducts()) products.insert(product->targetName, product); ResolvedProductPtr product = products.value(expectedTargetName); QVERIFY(!!product); ResolvedProductPtr product2 = products.value(QStringLiteral("fallback")); QVERIFY(!!product2); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::groupConditions_data() { QTest::addColumn("groupCount"); QTest::addColumn>("groupEnabled"); QTest::newRow("init") << size_t(0) << std::vector(); QTest::newRow("no_condition_no_group") << size_t(1) << std::vector{ true }; QTest::newRow("no_condition") << size_t(2) << std::vector{ true, true }; QTest::newRow("true_condition") << size_t(2) << std::vector{ true, true }; QTest::newRow("false_condition") << size_t(2) << std::vector{ true, false }; QTest::newRow("true_condition_from_product") << size_t(2) << std::vector{ true, true }; QTest::newRow("true_condition_from_project") << size_t(2) << std::vector{ true, true }; QTest::newRow("condition_accessing_module_property") << size_t(2) << std::vector{ true, false }; QTest::newRow("cleanup") << size_t(0) << std::vector(); } void TestLanguage::groupConditions() { HANDLE_INIT_CLEANUP_DATATAGS("groupconditions.qbs"); QFETCH(size_t, groupCount); QFETCH(std::vector, groupEnabled); QCOMPARE(groupCount, groupEnabled.size()); const QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); ResolvedProductPtr product = products.value(productName); QVERIFY(!!product); QCOMPARE(product->name, productName); QCOMPARE(product->groups.size(), groupCount); for (size_t i = 0; i < groupCount; ++i) { if (product->groups.at(i)->enabled != groupEnabled.at(i)) { QFAIL(qPrintable( QString("groups.at(%1)->enabled != %2").arg(i).arg(groupEnabled.at(i)))); } } } void TestLanguage::groupName() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("groupname.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 2); ResolvedProductPtr product = products.value("MyProduct"); QVERIFY(!!product); QCOMPARE(product->groups.size(), size_t(2)); GroupConstPtr group = product->groups.at(0); QVERIFY(!!group); QCOMPARE(group->name, QString("MyProduct")); group = product->groups.at(1); QVERIFY(!!group); QCOMPARE(group->name, QString("MyProduct.MyGroup")); product = products.value("My2ndProduct"); QVERIFY(!!product); QCOMPARE(product->groups.size(), size_t(3)); group = product->groups.at(0); QVERIFY(!!group); QCOMPARE(group->name, QString("My2ndProduct")); group = product->groups.at(1); QVERIFY(!!group); QCOMPARE(group->name, QString("My2ndProduct.MyGroup")); group = product->groups.at(2); QVERIFY(!!group); QCOMPARE(group->name, QString("Group 2")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::homeDirectory() { try { defaultParameters.setProjectFilePath(testProject("homeDirectory.qbs")); ResolvedProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.value("home"); QVERIFY(!!product); QDir dir = QDir::home(); QCOMPARE(product->productProperties.value("home").toString(), dir.path()); QCOMPARE(product->productProperties.value("homeSlash").toString(), dir.path()); dir.cdUp(); QCOMPARE(product->productProperties.value("homeUp").toString(), dir.path()); dir = QDir::home(); QCOMPARE(product->productProperties.value("homeFile").toString(), dir.filePath("a")); QCOMPARE(product->productProperties.value("bogus1").toString(), FileInfo::resolvePath(product->sourceDirectory, QStringLiteral("a~b"))); QCOMPARE(product->productProperties.value("bogus2").toString(), FileInfo::resolvePath(product->sourceDirectory, QStringLiteral("a/~/bb"))); QCOMPARE(product->productProperties.value("user").toString(), FileInfo::resolvePath(product->sourceDirectory, QStringLiteral("~foo/bar"))); } catch (const ErrorInfo &e) { qDebug() << e.toString(); } } void TestLanguage::identifierSearch_data() { QTest::addColumn("expectedHasNarf"); QTest::addColumn("expectedHasZort"); QTest::addColumn("sourceCode"); QTest::newRow("no narf, no zort") << false << false << QString( "Product {\n" " name: {\n" " var foo = 'bar';\n" " console.info(foo);\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("narf, no zort") << true << false << QString( "Product {\n" " name: {\n" " var foo = 'zort';\n" " console.info(narf + foo);\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("no narf, zort") << false << true << QString( "Product {\n" " name: {\n" " var foo = 'narf';\n" " console.info(zort + foo);\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("narf, zort") << true << true << QString( "Product {\n" " name: {\n" " var foo = narf;\n" " foo = foo + zort;\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("2 narfs, 1 zort") << true << true << QString( "Product {\n" " name: {\n" " var foo = narf;\n" " foo = narf + foo + zort;\n" " return foo;\n" " }\n" "}\n"); } void TestLanguage::identifierSearch() { QFETCH(bool, expectedHasNarf); QFETCH(bool, expectedHasZort); QFETCH(QString, sourceCode); bool hasNarf = !expectedHasNarf; bool hasZort = !expectedHasZort; IdentifierSearch isearch; isearch.add("narf", &hasNarf); isearch.add("zort", &hasZort); QbsQmlJS::Engine engine; QbsQmlJS::Lexer lexer(&engine); lexer.setCode(sourceCode, 1); QbsQmlJS::Parser parser(&engine); QVERIFY(parser.parse()); QVERIFY(parser.ast()); isearch.start(parser.ast()); QCOMPARE(hasNarf, expectedHasNarf); QCOMPARE(hasZort, expectedHasZort); } void TestLanguage::idUsage() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("idusage.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 5); QVERIFY(products.contains("product1_1")); QVERIFY(products.contains("product2_2")); QVERIFY(products.contains("product3_3")); ResolvedProductPtr product4 = products.value("product4_4"); QVERIFY(!!product4); auto product4Property = [&product4] (const char *name) { return product4->productProperties.value(QString::fromUtf8(name)).toString(); }; QCOMPARE(product4Property("productName"), product4->name); QCOMPARE(product4Property("productNameInBaseOfBase"), product4->name); GroupPtr group = findByName(product4->groups, "group in base product"); QVERIFY(!!group); QCOMPARE(qPrintable(group->prefix), "group in base product"); group = findByName(product4->groups, "another group in base product"); QVERIFY(!!group); QCOMPARE(qPrintable(group->prefix), "another group in base product"); ResolvedProductPtr product5 = products.value("product5"); QVERIFY(!!product5); QCOMPARE(product5->moduleProperties->moduleProperty("deepdummy.deep.moat", "zort") .toString(), QString("zort in dummy")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::idUniqueness() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("id-uniqueness.qbs")); loader->loadProject(defaultParameters); } catch (const ErrorInfo &e) { exceptionCaught = true; const QList items = e.items(); QCOMPARE(items.size(), 3); QCOMPARE(items.at(0).toString(), QString::fromUtf8("The id 'baseProduct' is not unique.")); QVERIFY(items.at(1).toString().contains("id-uniqueness.qbs:5:5 First occurrence is here.")); QVERIFY(items.at(2).toString().contains("id-uniqueness.qbs:8:5 Next occurrence is here.")); } QVERIFY(exceptionCaught); } void TestLanguage::importCollection() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("import-collection/project.qbs")); const TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); const ResolvedProductConstPtr product = products.value("da product"); QCOMPARE(product->productProperties.value("targetName").toString(), QLatin1String("C1f1C1f2C2f1C2f2")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::inheritedPropertiesItems_data() { QTest::addColumn("buildVariant"); QTest::addColumn("productName"); QTest::newRow("debug build") << "debug" << "product_debug"; QTest::newRow("release build") << "release" << "product_release"; } void TestLanguage::inheritedPropertiesItems() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; QFETCH(QString, buildVariant); QFETCH(QString, productName); params.setProjectFilePath (testProject("inherited-properties-items/inherited-properties-items.qbs")); params.setOverriddenValues(QVariantMap{std::make_pair("qbs.buildVariant", buildVariant)}); TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); QVERIFY(!!products.value(productName)); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::invalidBindingInDisabledItem() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("invalidBindingInDisabledItem.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 2); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::invalidOverrides() { QFETCH(QString, key); QFETCH(QString, expectedErrorMessage); const bool successExpected = expectedErrorMessage.isEmpty(); bool exceptionCaught = false; try { qbs::SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("invalid-overrides.qbs")); params.setOverriddenValues(QVariantMap{std::make_pair(key, true)}); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); } catch (const ErrorInfo &e) { exceptionCaught = true; if (successExpected) qDebug() << e.toString(); else QVERIFY2(e.toString().contains(expectedErrorMessage), qPrintable(e.toString())); } QEXPECT_FAIL("no such module in product", "not easily checkable", Continue); QCOMPARE(!exceptionCaught, successExpected); } void TestLanguage::invalidOverrides_data() { QTest::addColumn("key"); QTest::addColumn("expectedErrorMessage"); QTest::newRow("no such project") << "projects.myproject.x" << QString("Unknown project 'myproject' in property override."); QTest::newRow("no such project property") << "projects.My.Project.y" << QString("Unknown property: projects.My.Project.y"); QTest::newRow("valid project property override") << "projects.My.Project.x" << QString(); QTest::newRow("no such product") << "products.myproduct.x" << QString("Unknown product 'myproduct' in property override."); QTest::newRow("no such product (with module)") << "products.myproduct.cpp.useRPaths" << QString("Unknown product 'myproduct' in property override."); QTest::newRow("no such product property") << "products.MyProduct.y" << QString("Unknown property: products.MyProduct.y"); QTest::newRow("valid product property override") << "products.MyProduct.x" << QString(); // This cannot be an error, because the semantics are "if some product in the project has // such a module, then set that property", and the code that does the property overrides // does not have a global view. QTest::newRow("no such module") << "modules.blubb.x" << QString(); QTest::newRow("no such module in product") << "products.MyProduct.cpp.useRPaths" << QString("Invalid module 'cpp' in property override."); QTest::newRow("no such module property") << "modules.cpp.blubb" << QString("Unknown property: modules.cpp.blubb"); QTest::newRow("no such module property (per product)") << "products.MyOtherProduct.cpp.blubb" << QString("Unknown property: products.MyOtherProduct.cpp.blubb"); QTest::newRow("valid per-product module property override") << "products.MyOtherProduct.cpp.useRPaths" << QString(); } class JSSourceValueCreator { FileContextPtr m_fileContext; QList m_strings; public: JSSourceValueCreator(const FileContextPtr &fileContext) : m_fileContext(fileContext) { } ~JSSourceValueCreator() { qDeleteAll(m_strings); } JSSourceValuePtr create(const QString &sourceCode) { JSSourceValuePtr value = JSSourceValue::create(); value->setFile(m_fileContext); const auto str = new QString(sourceCode); m_strings.push_back(str); value->setSourceCode(QStringRef(str)); return value; } }; void TestLanguage::itemPrototype() { FileContextPtr fileContext = FileContext::create(); fileContext->setFilePath("/dev/null"); JSSourceValueCreator sourceValueCreator(fileContext); ItemPool pool; Item *proto = Item::create(&pool, ItemType::Product); proto->setProperty("x", sourceValueCreator.create("1")); proto->setProperty("y", sourceValueCreator.create("1")); Item *item = Item::create(&pool, ItemType::Product); item->setPrototype(proto); item->setProperty("y", sourceValueCreator.create("x + 1")); item->setProperty("z", sourceValueCreator.create("2")); Evaluator evaluator(m_engine); QCOMPARE(evaluator.property(proto, "x").toVariant().toInt(), 1); QCOMPARE(evaluator.property(proto, "y").toVariant().toInt(), 1); QVERIFY(!evaluator.property(proto, "z").isValid()); QCOMPARE(evaluator.property(item, "x").toVariant().toInt(), 1); QCOMPARE(evaluator.property(item, "y").toVariant().toInt(), 2); QCOMPARE(evaluator.property(item, "z").toVariant().toInt(), 2); } void TestLanguage::itemScope() { FileContextPtr fileContext = FileContext::create(); fileContext->setFilePath("/dev/null"); JSSourceValueCreator sourceValueCreator(fileContext); ItemPool pool; Item *scope1 = Item::create(&pool, ItemType::Scope); scope1->setProperty("x", sourceValueCreator.create("1")); Item *scope2 = Item::create(&pool, ItemType::Scope); scope2->setScope(scope1); scope2->setProperty("y", sourceValueCreator.create("x + 1")); Item *item = Item::create(&pool, ItemType::Scope); item->setScope(scope2); item->setProperty("z", sourceValueCreator.create("x + y")); Evaluator evaluator(m_engine); QCOMPARE(evaluator.property(scope1, "x").toVariant().toInt(), 1); QCOMPARE(evaluator.property(scope2, "y").toVariant().toInt(), 2); QVERIFY(!evaluator.property(scope2, "x").isValid()); QCOMPARE(evaluator.property(item, "z").toVariant().toInt(), 3); } void TestLanguage::jsExtensions() { QFile file(testProject("jsextensions.js")); QVERIFY(file.open(QFile::ReadOnly)); QTextStream ts(&file); QString code = ts.readAll(); QVERIFY(!code.isEmpty()); QScriptValue evaluated = m_engine->evaluate(code, file.fileName(), 1); if (m_engine->hasErrorOrException(evaluated)) { qDebug() << m_engine->uncaughtExceptionBacktrace(); QFAIL(qPrintable(m_engine->lastErrorString(evaluated))); } } void TestLanguage::jsImportUsedInMultipleScopes_data() { QTest::addColumn("buildVariant"); QTest::addColumn("expectedProductName"); QTest::newRow("debug") << QString("debug") << QString("MyProduct_debug"); QTest::newRow("release") << QString("release") << QString("MyProduct"); } void TestLanguage::jsImportUsedInMultipleScopes() { QFETCH(QString, buildVariant); QFETCH(QString, expectedProductName); bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("jsimportsinmultiplescopes.qbs")); params.setOverriddenValues({std::make_pair(QStringLiteral("qbs.buildVariant"), buildVariant)}); params.expandBuildConfiguration(); TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.values().front(); QVERIFY(!!product); QCOMPARE(product->name, expectedProductName); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::moduleMergingVariantValues() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath (testProject("module-merging-variant-values/module-merging-variant-values.qbs")); params.expandBuildConfiguration(); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); QCOMPARE(int(project->products.size()), 2); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::modulePrioritizationBySearchPath_data() { QTest::addColumn("searchPaths"); QTest::addColumn("expectedVariant"); QTest::newRow("foo has priority") << QStringList{"./foo", "./bar"} << "foo"; QTest::newRow("bar has priority") << QStringList{"./bar", "./foo"} << "bar"; } void TestLanguage::modulePrioritizationBySearchPath() { QFETCH(QStringList, searchPaths); QFETCH(QString, expectedVariant); bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("module-prioritization-by-search-path/project.qbs")); params.setOverriddenValues({std::make_pair(QStringLiteral("project.qbsSearchPaths"), searchPaths)}); params.expandBuildConfiguration(); TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.values().front(); QVERIFY(!!product); const QString actualVariant = product->moduleProperties->moduleProperty ("conflicting-instances", "moduleVariant").toString(); QCOMPARE(actualVariant, expectedVariant); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::moduleProperties_data() { QTest::addColumn("propertyName"); QTest::addColumn("expectedValue"); QTest::newRow("init") << QString() << QVariant(); QTest::newRow("merge_lists") << "defines" << QVariant(QStringList() << "THE_PRODUCT" << "QT_CORE" << "QT_GUI" << "QT_NETWORK"); QTest::newRow("merge_lists_and_values") << "defines" << QVariant(QStringList() << "THE_PRODUCT" << "QT_CORE" << "QT_GUI" << "QT_NETWORK"); QTest::newRow("merge_lists_with_duplicates") << "cxxFlags" << QVariant(QStringList() << "-foo" << "BAR" << "-foo" << "BAZ"); QTest::newRow("merge_lists_with_prototype_values") << "rpaths" << QVariant(QStringList() << "/opt/qt/lib" << "$ORIGIN"); QTest::newRow("list_property_that_references_product") << "listProp" << QVariant(QStringList() << "x" << "123"); QTest::newRow("list_property_depending_on_overridden_property") << "listProp2" << QVariant(QStringList() << "PRODUCT_STUFF" << "DEFAULT_STUFF" << "EXTRA_STUFF"); QTest::newRow("overridden_list_property") << "listProp" << QVariant(QStringList() << "PRODUCT_STUFF"); QTest::newRow("shadowed-list-property") << "defines" << QVariant(QStringList() << "MyProject" << "shadowed-list-property"); QTest::newRow("shadowed-scalar-property") << "someString" << QVariant(QString("MyProject_shadowed-scalar-property")); QTest::newRow("merged-varlist") << "varListProp" << QVariant(QVariantList() << QVariantMap({std::make_pair("d", "product")}) << QVariantMap({std::make_pair("c", "qtcore")}) << QVariantMap({std::make_pair("a", true), std::make_pair("b", QVariant())})); QTest::newRow("cleanup") << QString() << QVariant(); } void TestLanguage::moduleProperties() { HANDLE_INIT_CLEANUP_DATATAGS("moduleproperties.qbs"); QFETCH(QString, propertyName); QFETCH(QVariant, expectedValue); QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); ResolvedProductPtr product = products.value(productName); QVERIFY(!!product); const QVariant value = product->moduleProperties->moduleProperty("dummy", propertyName); QCOMPARE(value, expectedValue); } void TestLanguage::modulePropertiesInGroups() { defaultParameters.setProjectFilePath(testProject("modulepropertiesingroups.qbs")); bool exceptionCaught = false; try { TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); const QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("grouptest"); QVERIFY(!!product); GroupConstPtr g1; GroupConstPtr g11; GroupConstPtr g12; GroupConstPtr g2; GroupConstPtr g21; GroupConstPtr g211; for (const GroupConstPtr &g : product->groups) { if (g->name == "g1") g1= g; else if (g->name == "g2") g2 = g; else if (g->name == "g1.1") g11 = g; else if (g->name == "g1.2") g12 = g; else if (g->name == "g2.1") g21 = g; else if (g->name == "g2.1.1") g211 = g; } QVERIFY(!!g1); QVERIFY(!!g2); QVERIFY(!!g11); QVERIFY(!!g12); QVERIFY(!!g21); QVERIFY(!!g211); const QVariantMap productProps = product->moduleProperties->value(); const auto &productGmod1List1 = moduleProperty(productProps, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(productGmod1List1, QStringList() << "gmod1_list1_proto" << "gmod1_string_proto"); const auto &productGmod1List2 = moduleProperty(productProps, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(productGmod1List2, QStringList() << "grouptest" << "gmod1_string_proto" << "gmod1_list2_proto"); const auto &productGmod1List3 = moduleProperty(productProps, "gmod.gmod1", "gmod1_list3") .toStringList(); QCOMPARE(productGmod1List3, QStringList() << "product" << "gmod1_string_proto"); const int productP0 = moduleProperty(productProps, "gmod.gmod1", "p0").toInt(); QCOMPARE(productP0, 1); const int productDepProp = moduleProperty(productProps, "gmod.gmod1", "depProp").toInt(); QCOMPARE(productDepProp, 0); const auto &productGmod2String = moduleProperty(productProps, "gmod2", "gmod2_string") .toString(); QCOMPARE(productGmod2String, QString("gmod1_string_proto")); const auto &productGmod2List = moduleProperty(productProps, "gmod2", "gmod2_list") .toStringList(); QCOMPARE(productGmod2List, QStringList() << "gmod1_string_proto" << "commonName_in_gmod1" << "gmod4_string_proto_gmod3_string_proto" << "gmod3_string_proto" << "gmod2_list_proto"); const QVariantMap g1Props = g1->properties->value(); const auto &g1Gmod1List1 = moduleProperty(g1Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g1Gmod1List1, QStringList() << "gmod1_list1_proto" << "g1"); const auto &g1Gmod1List2 = moduleProperty(g1Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(g1Gmod1List2, QStringList() << "grouptest" << "gmod1_string_proto" << "gmod1_list2_proto" << "g1"); const auto &g1Gmod1List3 = moduleProperty(g1Props, "gmod.gmod1", "gmod1_list3") .toStringList(); QCOMPARE(g1Gmod1List3, QStringList() << "product" << "g1"); const int g1P0 = moduleProperty(g1Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g1P0, 3); const int g1DepProp = moduleProperty(g1Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g1DepProp, 1); const auto &g1Gmod2String = moduleProperty(g1Props, "gmod2", "gmod2_string").toString(); QCOMPARE(g1Gmod2String, QString("g1")); const auto &g1Gmod2List = moduleProperty(g1Props, "gmod2", "gmod2_list") .toStringList(); QCOMPARE(g1Gmod2List, QStringList() << "g1" << "commonName_in_gmod1" << "g1_gmod4_g1_gmod3" << "g1_gmod3" << "gmod2_list_proto"); const QVariantMap g11Props = g11->properties->value(); const auto &g11Gmod1List1 = moduleProperty(g11Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g11Gmod1List1, QStringList() << "gmod1_list1_proto" << "g1.1"); const auto &g11Gmod1List2 = moduleProperty(g11Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(g11Gmod1List2, QStringList() << "grouptest" << "gmod1_string_proto" << "gmod1_list2_proto" << "g1" << "g1.1"); const auto &g11Gmod1List3 = moduleProperty(g11Props, "gmod.gmod1", "gmod1_list3") .toStringList(); QCOMPARE(g11Gmod1List3, QStringList() << "product" << "g1.1"); const int g11P0 = moduleProperty(g11Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g11P0, 5); const int g11DepProp = moduleProperty(g11Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g11DepProp, 2); const auto &g11Gmod2String = moduleProperty(g11Props, "gmod2", "gmod2_string").toString(); QCOMPARE(g11Gmod2String, QString("g1.1")); const auto &g11Gmod2List = moduleProperty(g11Props, "gmod2", "gmod2_list") .toStringList(); QCOMPARE(g11Gmod2List, QStringList() << "g1.1" << "commonName_in_gmod1" << "g1.1_gmod4_g1.1_gmod3" << "g1.1_gmod3" << "gmod2_list_proto"); const QVariantMap g12Props = g12->properties->value(); const auto &g12Gmod1List1 = moduleProperty(g12Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g12Gmod1List1, QStringList() << "gmod1_list1_proto" << "g1.2"); const auto &g12Gmod1List2 = moduleProperty(g12Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(g12Gmod1List2, QStringList() << "grouptest" << "gmod1_string_proto" << "gmod1_list2_proto" << "g1" << "g1.2"); const auto &g12Gmod1List3 = moduleProperty(g12Props, "gmod.gmod1", "gmod1_list3") .toStringList(); QCOMPARE(g12Gmod1List3, QStringList() << "product" << "g1.2"); const int g12P0 = moduleProperty(g12Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g12P0, 9); const int g12DepProp = moduleProperty(g12Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g12DepProp, 1); const auto &g12Gmod2String = moduleProperty(g12Props, "gmod2", "gmod2_string").toString(); QCOMPARE(g12Gmod2String, QString("g1.2")); const auto &g12Gmod2List = moduleProperty(g12Props, "gmod2", "gmod2_list") .toStringList(); QCOMPARE(g12Gmod2List, QStringList() << "g1.2" << "commonName_in_gmod1" << "g1_gmod4_g1.2_gmod3" << "g1.2_gmod3" << "gmod2_list_proto"); const QVariantMap g2Props = g2->properties->value(); const auto &g2Gmod1List1 = moduleProperty(g2Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g2Gmod1List1, QStringList() << "gmod1_list1_proto" << "g2"); const auto &g2Gmod1List2 = moduleProperty(g2Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(g2Gmod1List2, QStringList() << "grouptest" << "g2" << "gmod1_list2_proto"); const int g2P0 = moduleProperty(g2Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g2P0, 6); const int g2DepProp = moduleProperty(g2Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g2DepProp, 2); const auto &g2Gmod2String = moduleProperty(g2Props, "gmod2", "gmod2_string").toString(); QCOMPARE(g2Gmod2String, QString("g2")); const auto &g2Gmod2List = moduleProperty(g2Props, "gmod2", "gmod2_list") .toStringList(); QCOMPARE(g2Gmod2List, QStringList() << "g2" << "commonName_in_gmod1" << "g2_gmod4_g2_gmod3" << "g2_gmod3" << "gmod2_list_proto"); const QVariantMap g21Props = g21->properties->value(); const auto &g21Gmod1List1 = moduleProperty(g21Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g21Gmod1List1, QStringList() << "gmod1_list1_proto" << "g2"); const auto &g21Gmod1List2 = moduleProperty(g21Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QEXPECT_FAIL(0, "no re-eval when no module props set", Continue); QCOMPARE(g21Gmod1List2, QStringList() << "grouptest" << "g2.1" << "gmod1_list2_proto"); const int g21P0 = moduleProperty(g21Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g21P0, 6); const int g21DepProp = moduleProperty(g21Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g21DepProp, 2); const auto &g21Gmod2String = moduleProperty(g21Props, "gmod2", "gmod2_string").toString(); QCOMPARE(g21Gmod2String, QString("g2")); const auto &g21Gmod2List = moduleProperty(g21Props, "gmod2", "gmod2_list") .toStringList(); QEXPECT_FAIL(0, "no re-eval when no module props set", Continue); QCOMPARE(g21Gmod2List, QStringList() << "g2" << "commonName_in_gmod1" << "g2.1_gmod4_g2.1_gmod3" << "g2.1_gmod3" << "gmod2_list_proto"); const QVariantMap g211Props = g211->properties->value(); const auto &g211Gmod1List1 = moduleProperty(g211Props, "gmod.gmod1", "gmod1_list1") .toStringList(); QCOMPARE(g211Gmod1List1, QStringList() << "gmod1_list1_proto" << "g2"); const auto &g211Gmod1List2 = moduleProperty(g211Props, "gmod.gmod1", "gmod1_list2") .toStringList(); QCOMPARE(g211Gmod1List2, QStringList() << "g2.1.1"); const int g211P0 = moduleProperty(g211Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g211P0, 17); const int g211DepProp = moduleProperty(g211Props, "gmod.gmod1", "depProp").toInt(); QCOMPARE(g211DepProp, 2); const auto &g211Gmod2String = moduleProperty(g211Props, "gmod2", "gmod2_string").toString(); QEXPECT_FAIL(0, "re-eval not triggered", Continue); QCOMPARE(g211Gmod2String, QString("g2.1.1")); const auto &g211Gmod2List = moduleProperty(g211Props, "gmod2", "gmod2_list") .toStringList(); QEXPECT_FAIL(0, "re-eval not triggered", Continue); QCOMPARE(g211Gmod2List, QStringList() << "g2.1.1" << "commonName_in_gmod1" << "g2.1.1_gmod4_g2.1.1_gmod3" << "g2.1.1_gmod3" << "gmod2_list_proto"); product = products.value("grouptest2"); QVERIFY(!!product); g1.reset(); g11.reset(); for (const GroupConstPtr &g : product->groups) { if (g->name == "g1") g1= g; else if (g->name == "g1.1") g11 = g; } QVERIFY(!!g1); QVERIFY(!!g11); QCOMPARE(moduleProperty(g1->properties->value(), "gmod.gmod1", "gmod1_list2") .toStringList(), QStringList({"G1"})); QCOMPARE(moduleProperty(g11->properties->value(), "gmod.gmod1", "gmod1_list2") .toStringList(), moduleProperty(g1->properties->value(), "gmod.gmod1", "gmod1_list2") .toStringList()); QCOMPARE(moduleProperty(g11->properties->value(), "gmod.gmod1", "gmod1_string").toString(), QString("G1.1")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::modulePropertyOverridesPerProduct() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setOverriddenValues({ std::make_pair("modules.dummy.rpaths", QStringList({"/usr/lib"})), std::make_pair("modules.dummy.someString", "m"), std::make_pair("products.b.dummy.someString", "b"), std::make_pair("products.c.dummy.someString", "c"), std::make_pair("products.c.dummy.rpaths", QStringList({"/home", "/tmp"})) }); params.setProjectFilePath( testProject("module-property-overrides-per-product.qbs")); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 3); const ResolvedProductConstPtr a = products.value("a"); QVERIFY(!!a); const ResolvedProductConstPtr b = products.value("b"); QVERIFY(!!b); const ResolvedProductConstPtr c = products.value("c"); QVERIFY(!!c); const auto stringPropertyValue = [](const ResolvedProductConstPtr &p) -> QString { return p->moduleProperties->moduleProperty("dummy", "someString").toString(); }; const auto listPropertyValue = [](const ResolvedProductConstPtr &p) -> QStringList { return p->moduleProperties->moduleProperty("dummy", "rpaths").toStringList(); }; const auto productPropertyValue = [](const ResolvedProductConstPtr &p) -> QStringList { return p->productProperties.value("rpaths").toStringList(); }; QCOMPARE(stringPropertyValue(a), QString("m")); QCOMPARE(stringPropertyValue(b), QString("b")); QCOMPARE(stringPropertyValue(c), QString("c")); QCOMPARE(listPropertyValue(a), QStringList({"/usr/lib"})); QCOMPARE(listPropertyValue(b), QStringList({"/usr/lib"})); QCOMPARE(listPropertyValue(c), QStringList({"/home", "/tmp"})); QCOMPARE(listPropertyValue(a), productPropertyValue(a)); QCOMPARE(listPropertyValue(b), productPropertyValue(b)); QCOMPARE(listPropertyValue(c), productPropertyValue(c)); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::moduleScope() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("modulescope.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.value("product1"); QVERIFY(!!product); auto intModuleValue = [product] (const QString &name) -> int { return product->moduleProperties->moduleProperty("scopemod", name).toInt(); }; QCOMPARE(intModuleValue("a"), 2); // overridden in module instance QCOMPARE(intModuleValue("b"), 1); // genuine QCOMPARE(intModuleValue("c"), 3); // genuine, dependent on overridden value QCOMPARE(intModuleValue("d"), 2); // genuine, dependent on genuine value QCOMPARE(intModuleValue("e"), 1); // genuine QCOMPARE(intModuleValue("f"), 2); // overridden QCOMPARE(intModuleValue("g"), 156); // overridden, dependent on product properties QCOMPARE(intModuleValue("h"), 158); // overridden, base dependent on product properties } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::modules_data() { QTest::addColumn("expectedModulesInProduct"); QTest::addColumn("expectedProductProperty"); QTest::newRow("init") << QStringList(); QTest::newRow("no_modules") << (QStringList() << "qbs") << QString(); QTest::newRow("qt_core") << (QStringList() << "qbs" << "dummy" << "dummyqt.core") << QString("1.2.3"); QTest::newRow("qt_gui") << (QStringList() << "qbs" << "dummy" << "dummyqt.core" << "dummyqt.gui") << QString("guiProperty"); QTest::newRow("qt_gui_network") << (QStringList() << "qbs" << "dummy" << "dummyqt.core" << "dummyqt.gui" << "dummyqt.network") << QString("guiProperty,networkProperty"); QTest::newRow("deep_module_name") << (QStringList() << "qbs" << "deepdummy.deep.moat" << "dummy") << QString("abysmal"); QTest::newRow("deep_module_name_submodule_syntax1") << (QStringList() << "qbs" << "deepdummy.deep.moat" << "dummy") << QString("abysmal"); QTest::newRow("deep_module_name_submodule_syntax2") << (QStringList() << "qbs" << "deepdummy.deep.moat" << "dummy") << QString("abysmal"); QTest::newRow("dummy_twice") << (QStringList() << "qbs" << "dummy") << QString(); QTest::newRow("cleanup") << QStringList(); } void TestLanguage::modules() { HANDLE_INIT_CLEANUP_DATATAGS("modules.qbs"); QFETCH(QStringList, expectedModulesInProduct); QFETCH(QString, expectedProductProperty); QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); const ResolvedProductPtr product = products.value(productName); QVERIFY(!!product); QCOMPARE(product->name, productName); QStringList modulesInProduct; for (ResolvedModuleConstPtr m : product->modules) modulesInProduct += m->name; modulesInProduct.sort(); expectedModulesInProduct.sort(); QCOMPARE(modulesInProduct, expectedModulesInProduct); QCOMPARE(product->productProperties.value("foo").toString(), expectedProductProperty); } void TestLanguage::multiplexedExports() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("multiplexed-exports.qbs")); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); const auto products = project->allProducts(); QCOMPARE(products.size(), size_t(4)); std::set pVariants; for (const auto &product : products) { if (product->name != "p") continue; static const auto buildVariant = [](const ResolvedProductConstPtr &p) { return p->moduleProperties->qbsPropertyValue("buildVariant").toString(); }; static const auto cppIncludePaths = [](const ResolvedProductConstPtr &p) { return p->moduleProperties->moduleProperty("cpp", "includePaths").toStringList(); }; if (buildVariant(product) == "debug") { pVariants.insert(product); QCOMPARE(cppIncludePaths(product), QStringList("/d")); } else if (buildVariant(product) == "release") { pVariants.insert(product); QCOMPARE(cppIncludePaths(product), QStringList("/r")); } } QCOMPARE(int(pVariants.size()), 2); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::multiplexingByProfile() { QFETCH(QString, projectFileName); QFETCH(bool, successExpected); SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testDataDir() + "/multiplexing-by-profile/" + projectFileName); try { params.setDryRun(true); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(successExpected); QVERIFY(!!project); } catch (const ErrorInfo &e) { QVERIFY2(!successExpected, qPrintable(e.toString())); } } void TestLanguage::multiplexingByProfile_data() { QTest::addColumn("projectFileName"); QTest::addColumn("successExpected"); QTest::newRow("same profile") << "p1.qbs" << true; QTest::newRow("dependency on non-multiplexed") << "p2.qbs" << true; QTest::newRow("dependency by non-multiplexed") << "p3.qbs" << false; QTest::newRow("dependency by non-multiplexed with Depends.profile") << "p4.qbs" << true; } void TestLanguage::nonApplicableModulePropertyInProfile() { QFETCH(QString, targetOS); QFETCH(QString, toolchain); QFETCH(bool, successExpected); try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("non-applicable-module-property-in-profile.qbs")); params.setOverriddenValues(QVariantMap{std::make_pair("project.targetOS", targetOS), std::make_pair("project.toolchain", toolchain)}); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); QVERIFY(successExpected); } catch (const ErrorInfo &e) { QVERIFY2(!successExpected, qPrintable(e.toString())); QVERIFY2(e.toString().contains("Loading module 'multiple_backends' for product 'p' failed " "due to invalid values in profile 'theProfile'"), qPrintable(e.toString())); QVERIFY2(e.toString().contains("backend3Prop"), qPrintable(e.toString())); } } void TestLanguage::nonApplicableModulePropertyInProfile_data() { QTest::addColumn("targetOS"); QTest::addColumn("toolchain"); QTest::addColumn("successExpected"); QTest::newRow("no matching property (1)") << "os1" << QString() << false; QTest::newRow("no matching property (2)") << "os2" << QString() << false; // The point here is that there's a second, lower-prioritized candidate with a matching // condition that doesn't have the property. This candidate must not throw an error. QTest::newRow("matching property") << "os2" << "tc" << true; } void TestLanguage::nonRequiredProducts() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("non-required-products.qbs")); QFETCH(bool, subProjectEnabled); QFETCH(bool, dependeeEnabled); QVariantMap overriddenValues; if (!subProjectEnabled) overriddenValues.insert("projects.subproject.condition", false); else if (!dependeeEnabled) overriddenValues.insert("products.dependee.condition", false); params.setOverriddenValues(overriddenValues); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); const auto products = productsFromProject(project); QCOMPARE(products.size(), 4 + !!subProjectEnabled); const ResolvedProductConstPtr dependee = products.value("dependee"); QCOMPARE(subProjectEnabled, !!dependee); if (dependee) QCOMPARE(dependeeEnabled, dependee->enabled); const ResolvedProductConstPtr depender = products.value("depender"); QVERIFY(!!depender); const QStringList defines = depender->moduleProperties->moduleProperty("dummy", "defines") .toStringList(); QCOMPARE(subProjectEnabled && dependeeEnabled, defines.contains("WITH_DEPENDEE")); for (const auto &name : std::vector({ "p3", "p2", "p1"})) { const ResolvedProductConstPtr &product = products.value(name); QVERIFY2(product, name); QVERIFY2(!product->enabled, name); } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::nonRequiredProducts_data() { QTest::addColumn("subProjectEnabled"); QTest::addColumn("dependeeEnabled"); QTest::newRow("dependee enabled") << true << true; QTest::newRow("dependee disabled") << true << false; QTest::newRow("sub project disabled") << false << true; } void TestLanguage::outerInGroup() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("outerInGroup.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.value("OuterInGroup"); QVERIFY(!!product); QCOMPARE(product->groups.size(), size_t(2)); GroupPtr group = product->groups.at(0); QVERIFY(!!group); QCOMPARE(group->name, product->name); QCOMPARE(group->files.size(), size_t(1)); SourceArtifactConstPtr artifact = group->files.front(); QVariant installDir = artifact->properties->qbsPropertyValue("installDir"); QCOMPARE(installDir.toString(), QString("/somewhere")); group = product->groups.at(1); QVERIFY(!!group); QCOMPARE(group->name, QString("Special Group")); QCOMPARE(group->files.size(), size_t(1)); artifact = group->files.front(); installDir = artifact->properties->qbsPropertyValue("installDir"); QCOMPARE(installDir.toString(), QString("/somewhere/else")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::overriddenPropertiesAndPrototypes() { bool exceptionCaught = false; try { QFETCH(QString, osName); QFETCH(QString, backendName); SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("overridden-properties-and-prototypes.qbs")); params.setOverriddenValues({std::make_pair("modules.qbs.targetPlatform", osName)}); TopLevelProjectConstPtr project = loader->loadProject(params); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->moduleProperties->moduleProperty( "multiple_backends", "prop").toString(), backendName); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::overriddenPropertiesAndPrototypes_data() { QTest::addColumn("osName"); QTest::addColumn("backendName"); QTest::newRow("first backend") << "os1" << "backend 1"; QTest::newRow("second backend") << "os2" << "backend 2"; } void TestLanguage::overriddenVariantProperty() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; const QVariantMap objectValue{std::make_pair("x", 1), std::make_pair("y", 2)}; params.setOverriddenValues({std::make_pair("products.p.myObject", objectValue)}); params.setProjectFilePath(testProject("overridden-variant-property.qbs")); TopLevelProjectConstPtr project = loader->loadProject(params); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->productProperties.value("myObject").toMap(), objectValue); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::parameterTypes() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("parameter-types.qbs")); loader->loadProject(defaultParameters); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::pathProperties() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("pathproperties.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(!!product); QString projectFileDir = QFileInfo(defaultParameters.projectFilePath()).absolutePath(); const QVariantMap productProps = product->productProperties; QCOMPARE(productProps.value("projectFileDir").toString(), projectFileDir); QStringList filesInProjectFileDir = QStringList() << FileInfo::resolvePath(projectFileDir, "aboutdialog.h") << FileInfo::resolvePath(projectFileDir, "aboutdialog.cpp"); QCOMPARE(productProps.value("filesInProjectFileDir").toStringList(), filesInProjectFileDir); QStringList includePaths = product->moduleProperties->property( QStringList() << "dummy" << "includePaths").toStringList(); QCOMPARE(includePaths, QStringList() << projectFileDir); QCOMPARE(productProps.value("base_fileInProductDir").toString(), FileInfo::resolvePath(projectFileDir, QStringLiteral("foo"))); QCOMPARE(productProps.value("base_fileInBaseProductDir").toString(), FileInfo::resolvePath(projectFileDir, QStringLiteral("subdir/bar"))); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::profileValuesAndOverriddenValues() { bool exceptionCaught = false; try { TemporaryProfile tp(QStringLiteral("tst_lang_profile"), m_settings); Profile profile = tp.p; profile.setValue("dummy.defines", "IN_PROFILE"); profile.setValue("dummy.cFlags", "IN_PROFILE"); profile.setValue("dummy.cxxFlags", "IN_PROFILE"); profile.setValue("qbs.architecture", "x86"); SetupProjectParameters parameters = defaultParameters; parameters.setTopLevelProfile(profile.name()); QVariantMap overriddenValues; overriddenValues.insert("modules.dummy.cFlags", "OVERRIDDEN"); parameters.setOverriddenValues(overriddenValues); parameters.setProjectFilePath(testProject("profilevaluesandoverriddenvalues.qbs")); parameters.expandBuildConfiguration(); project = loader->loadProject(parameters); QVERIFY(!!project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(!!product); QVariantList values; values = product->moduleProperties->moduleProperty("dummy", "cxxFlags").toList(); QCOMPARE(values.length(), 1); QCOMPARE(values.front().toString(), QString("IN_PROFILE")); values = product->moduleProperties->moduleProperty("dummy", "defines").toList(); QCOMPARE(values, QVariantList() << QStringLiteral("IN_FILE") << QStringLiteral("IN_PROFILE")); values = product->moduleProperties->moduleProperty("dummy", "cFlags").toList(); QCOMPARE(values.length(), 1); QCOMPARE(values.front().toString(), QString("OVERRIDDEN")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::projectFileLookup() { QFETCH(QString, projectFileInput); QFETCH(QString, projectFileOutput); QFETCH(bool, failureExpected); try { SetupProjectParameters params; params.setProjectFilePath(projectFileInput); Loader::setupProjectFilePath(params); QVERIFY(!failureExpected); QCOMPARE(params.projectFilePath(), projectFileOutput); } catch (const ErrorInfo &) { QVERIFY(failureExpected); } } void TestLanguage::projectFileLookup_data() { QTest::addColumn("projectFileInput"); QTest::addColumn("projectFileOutput"); QTest::addColumn("failureExpected"); const QString baseDir = QLatin1String(SRCDIR) + "/testdata"; const QString multiProjectsDir = baseDir + "/dirwithmultipleprojects"; const QString noProjectsDir = baseDir + "/dirwithnoprojects"; const QString oneProjectDir = baseDir + "/dirwithoneproject"; QVERIFY(QDir(noProjectsDir).exists() && QDir(oneProjectDir).exists() && QDir(multiProjectsDir).exists()); const QString fullFilePath = multiProjectsDir + "/project.qbs"; QTest::newRow("full file path") << fullFilePath << fullFilePath << false; QTest::newRow("base dir ") << oneProjectDir << (oneProjectDir + "/project.qbs") << false; QTest::newRow("empty dir") << noProjectsDir << QString() << true; QTest::newRow("ambiguous dir") << multiProjectsDir << QString() << true; } void TestLanguage::productConditions() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("productconditions.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 6); ResolvedProductPtr product; product = products.value("product_no_condition"); QVERIFY(!!product); QVERIFY(product->enabled); product = products.value("product_true_condition"); QVERIFY(!!product); QVERIFY(product->enabled); product = products.value("product_condition_dependent_of_module"); QVERIFY(!!product); QVERIFY(product->enabled); product = products.value("product_false_condition"); QVERIFY(!!product); QVERIFY(!product->enabled); product = products.value("product_probe_condition_false"); QVERIFY(!!product); QVERIFY(!product->enabled); product = products.value("product_probe_condition_true"); QVERIFY(!!product); QVERIFY(product->enabled); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::productDirectories() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("productdirectories.qbs")); ResolvedProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); QHash products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product; product = products.value("MyApp"); QVERIFY(!!product); const QVariantMap config = product->productProperties; QCOMPARE(config.value(QStringLiteral("buildDirectory")).toString(), product->buildDirectory()); QCOMPARE(config.value(QStringLiteral("sourceDirectory")).toString(), testDataDir()); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::propertiesBlocks_data() { QTest::addColumn("propertyName"); QTest::addColumn("expectedValue"); QTest::addColumn("expectedStringValue"); QTest::newRow("init") << QString() << QVariant() << QString(); QTest::newRow("property_overwrite") << QString("dummy.defines") << QVariant(QStringList("OVERWRITTEN")) << QString(); QTest::newRow("property_set_indirect") << QString("dummy.cFlags") << QVariant(QStringList("VAL")) << QString(); QTest::newRow("property_overwrite_no_outer") << QString("dummy.defines") << QVariant(QStringList("OVERWRITTEN")) << QString(); QTest::newRow("property_append_to_outer") << QString("dummy.defines") << QVariant(QStringList() << QString("ONE") << QString("TWO")) << QString(); QTest::newRow("property_append_to_indirect_outer") << QString("dummy.defines") << QVariant(QStringList() << QString("ONE") << QString("TWO")) << QString(); QTest::newRow("property_append_to_indirect_derived_outer1") << QString("dummy.cFlags") << QVariant(QStringList() << QString("BASE") << QString("PROPS")) << QString(); QTest::newRow("property_append_to_indirect_derived_outer2") << QString("dummy.cFlags") << QVariant(QStringList() << QString("PRODUCT") << QString("PROPS")) << QString(); QTest::newRow("property_append_to_indirect_derived_outer3") << QString("dummy.cFlags") << QVariant(QStringList() << QString("BASE") << QString("PRODUCT") << QString("PROPS")) << QString(); QTest::newRow("property_append_to_indirect_merged_outer") << QString("dummy.rpaths") << QVariant(QStringList() << QString("ONE") << QString("TWO") << QString("$ORIGIN")) << QString(); QTest::newRow("multiple_exclusive_properties") << QString("dummy.defines") << QVariant(QStringList("OVERWRITTEN")) << QString(); QTest::newRow("multiple_exclusive_properties_no_outer") << QString("dummy.defines") << QVariant(QStringList("OVERWRITTEN")) << QString(); QTest::newRow("multiple_exclusive_properties_append_to_outer") << QString("dummy.defines") << QVariant(QStringList() << QString("ONE") << QString("TWO")) << QString(); QTest::newRow("condition_refers_to_product_property") << QString("dummy.defines") << QVariant(QStringList("OVERWRITTEN")) << QString("OVERWRITTEN"); QTest::newRow("condition_refers_to_project_property") << QString("dummy.defines") << QVariant(QStringList("OVERWRITTEN")) << QString("OVERWRITTEN"); QTest::newRow("ambiguous_properties") << QString("dummy.defines") << QVariant(QStringList() << QString("ONE") << QString("TWO")) << QString(); QTest::newRow("inheritance_overwrite_in_subitem") << QString("dummy.defines") << QVariant(QStringList() << QString("OVERWRITTEN_IN_SUBITEM")) << QString(); QTest::newRow("inheritance_retain_base1") << QString("dummy.defines") << QVariant(QStringList() << QString("BASE") << QString("SUB")) << QString(); QTest::newRow("inheritance_retain_base2") << QString("dummy.defines") << QVariant(QStringList() << QString("BASE") << QString("SUB")) << QString(); QTest::newRow("inheritance_retain_base3") << QString("dummy.defines") << QVariant(QStringList() << QString("BASE") << QString("SUB")) << QString(); QTest::newRow("inheritance_retain_base4") << QString("dummy.defines") << QVariant(QStringList() << QString("BASE")) << QString(); QTest::newRow("inheritance_condition_in_subitem1") << QString("dummy.defines") << QVariant(QStringList() << QString("SOMETHING") << QString("SUB")) << QString(); QTest::newRow("inheritance_condition_in_subitem2") << QString("dummy.defines") << QVariant(QStringList() << QString("SOMETHING")) << QString(); QTest::newRow("condition_references_id") << QString("dummy.defines") << QVariant(QStringList() << QString("OVERWRITTEN")) << QString(); QTest::newRow("using_derived_Properties_item") << "dummy.defines" << QVariant(QStringList() << "string from MyProperties") << QString(); QTest::newRow("conditional-depends") << QString("dummy.defines") << QVariant() << QString(); QTest::newRow("use-module-with-properties-item") << QString("module-with-properties-item.stringProperty") << QVariant(QString("overridden in Properties item")) << QString(); QTest::newRow("cleanup") << QString() << QVariant() << QString(); } void TestLanguage::propertiesBlocks() { HANDLE_INIT_CLEANUP_DATATAGS("propertiesblocks.qbs"); QFETCH(QString, propertyName); QFETCH(QVariant, expectedValue); QFETCH(QString, expectedStringValue); QVERIFY(!!project); QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); ResolvedProductPtr product = products.value(productName); QVERIFY(!!product); QCOMPARE(product->name, productName); QVariant v = productPropertyValue(product, propertyName); QCOMPARE(v, expectedValue); if (!expectedStringValue.isEmpty()) { v = productPropertyValue(product, "someString"); QCOMPARE(v.toString(), expectedStringValue); } } void TestLanguage::propertiesBlockInGroup() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("properties-block-in-group.qbs")); const TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); QCOMPARE(project->allProducts().size(), size_t(1)); const ResolvedProductConstPtr product = project->allProducts().front(); const auto groupIt = std::find_if(product->groups.cbegin(), product->groups.cend(), [](const GroupConstPtr &g) { return g->name == "the group"; }); QVERIFY(groupIt != product->groups.cend()); const QVariantMap propertyMap = (*groupIt)->properties->value(); const QVariantList value = moduleProperty(propertyMap, "dummy", "defines").toList(); QStringList stringListValue; std::transform(value.constBegin(), value.constEnd(), std::back_inserter(stringListValue), [](const QVariant &v) { return v.toString(); }); QCOMPARE(stringListValue, QStringList() << "BASEDEF" << "FEATURE_ENABLED"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::propertiesItemInModule() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath( testProject("properties-item-in-module.qbs")); const TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 2); for (const ResolvedProductConstPtr &p : products) { QCOMPARE(p->moduleProperties->moduleProperty("dummy", "productName").toString(), p->name); } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::propertyAssignmentInExportedGroup() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath( testProject("property-assignment-in-exported-group.qbs")); const TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 2); for (const ResolvedProductConstPtr &p : products) { QCOMPARE(p->moduleProperties->moduleProperty("dummy", "someString").toString(), QString()); for (const GroupConstPtr &g : p->groups) { const QString propValue = g->properties->moduleProperty("dummy", "someString").toString(); if (g->name == "exported_group") QCOMPARE(propValue, QString("test")); else QCOMPARE(propValue, QString()); } } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::qbs1275() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("qbs1275.qbs")); const TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.count(), 5); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::qbsPropertiesInProjectCondition() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath( testProject("qbs-properties-in-project-condition.qbs")); const TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 0); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::qbsPropertyConvenienceOverride() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("qbs-property-convenience-override.qbs")); params.setOverriddenValues({std::make_pair("qbs.installPrefix", "/opt")}); TopLevelProjectConstPtr project = loader->loadProject(params); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->moduleProperties->qbsPropertyValue("installPrefix") .toString(), QString("/opt")); } catch (const ErrorInfo &e) { qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::relaxedErrorMode() { m_logSink->setLogLevel(LoggerMinLevel); QFETCH(bool, strictMode); try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("relaxed-error-mode/relaxed-error-mode.qbs")); params.setProductErrorMode(strictMode ? ErrorHandlingMode::Strict : ErrorHandlingMode::Relaxed); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!strictMode); const auto productMap = productsFromProject(project); const ResolvedProductConstPtr brokenProduct = productMap.value("broken"); QVERIFY(!brokenProduct->enabled); QVERIFY(brokenProduct->location.isValid()); QCOMPARE(brokenProduct->allFiles().size(), size_t(0)); const ResolvedProductConstPtr dependerRequired = productMap.value("depender required"); QVERIFY(!dependerRequired->enabled); QVERIFY(dependerRequired->location.isValid()); QCOMPARE(dependerRequired->allFiles().size(), size_t(1)); const ResolvedProductConstPtr dependerNonRequired = productMap.value("depender nonrequired"); QVERIFY(dependerNonRequired->enabled); QCOMPARE(dependerNonRequired->allFiles().size(), size_t(1)); const ResolvedProductConstPtr recursiveDepender = productMap.value("recursive depender"); QVERIFY(!recursiveDepender->enabled); QVERIFY(recursiveDepender->location.isValid()); QCOMPARE(recursiveDepender->allFiles().size(), size_t(1)); const ResolvedProductConstPtr missingFile = productMap.value("missing file"); QVERIFY(missingFile->enabled); QCOMPARE(missingFile->groups.size(), size_t(1)); QVERIFY(missingFile->groups.front()->enabled); QCOMPARE(missingFile->groups.front()->allFiles().size(), size_t(2)); const ResolvedProductConstPtr fine = productMap.value("fine"); QVERIFY(fine->enabled); QCOMPARE(fine->allFiles().size(), size_t(1)); } catch (const ErrorInfo &e) { QVERIFY2(strictMode, qPrintable(e.toString())); } } void TestLanguage::relaxedErrorMode_data() { QTest::addColumn("strictMode"); QTest::newRow("strict mode") << true; QTest::newRow("relaxed mode") << false; } void TestLanguage::requiredAndNonRequiredDependencies() { QFETCH(QString, projectFile); QFETCH(bool, exceptionExpected); try { SetupProjectParameters params = defaultParameters; const QString projectFilePath = "required-and-nonrequired-dependencies/" + projectFile; params.setProjectFilePath(testProject(projectFilePath.toLocal8Bit())); const TopLevelProjectConstPtr project = loader->loadProject(params); QVERIFY(!!project); QVERIFY(!exceptionExpected); } catch (const ErrorInfo &e) { QVERIFY(exceptionExpected); QVERIFY2(e.toString().contains("validation error!"), qPrintable(e.toString())); } } void TestLanguage::requiredAndNonRequiredDependencies_data() { QTest::addColumn("projectFile"); QTest::addColumn("exceptionExpected"); QTest::newRow("same file") << "direct-dependencies.qbs" << true; QTest::newRow("dependency via module") << "dependency-via-module.qbs" << true; QTest::newRow("dependency via export") << "dependency-via-export.qbs" << true; QTest::newRow("more indirection") << "complicated.qbs" << true; QTest::newRow("required chain (module)") << "required-chain-module.qbs" << false; QTest::newRow("required chain (export)") << "required-chain-export.qbs" << false; QTest::newRow("required chain (export indirect)") << "required-chain-export-indirect.qbs" << false; } void TestLanguage::suppressedAndNonSuppressedErrors() { try { SetupProjectParameters params = defaultParameters; const QString projectFilePath = "suppressed-and-non-suppressed-errors.qbs"; params.setProjectFilePath(testProject(projectFilePath.toLocal8Bit())); const TopLevelProjectConstPtr project = loader->loadProject(params); QFAIL("failure expected"); } catch (const ErrorInfo &e) { QVERIFY2(e.toString().contains("easter bunny"), qPrintable(e.toString())); QVERIFY2(!e.toString().contains("TheBeautifulSausage"), qPrintable(e.toString())); } } void TestLanguage::throwingProbe() { QFETCH(bool, enableProbe); try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("throwing-probe.qbs")); QVariantMap properties; properties.insert(QStringLiteral("products.theProduct.enableProbe"), enableProbe); params.setOverriddenValues(properties); const TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(!!project); QVERIFY(!enableProbe); } catch (const ErrorInfo &e) { QVERIFY2(enableProbe, qPrintable(e.toString())); } } void TestLanguage::throwingProbe_data() { QTest::addColumn("enableProbe"); QTest::newRow("enabled probe") << true; QTest::newRow("disabled probe") << false; } void TestLanguage::qualifiedId() { QString str = "foo.bar.baz"; QualifiedId id = QualifiedId::fromString(str); QCOMPARE(id.size(), 3); QCOMPARE(id.toString(), str); id = QualifiedId("blubb.di.blubb"); // c'tor does not split QCOMPARE(id.size(), 1); QList ids; ids << QualifiedId::fromString("a") << QualifiedId::fromString("a.a") << QualifiedId::fromString("b") << QualifiedId::fromString("c.a") << QualifiedId::fromString("c.b.a") << QualifiedId::fromString("c.c"); QList sorted = ids; std::sort(sorted.begin(), sorted.end()); QCOMPARE(ids, sorted); } void TestLanguage::recursiveProductDependencies() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath( testProject("recursive-dependencies/recursive-dependencies.qbs")); const TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(!!project); const QHash products = productsFromProject(project); QCOMPARE(products.size(), 4); const ResolvedProductConstPtr p1 = products.value("p1"); QVERIFY(!!p1); const ResolvedProductConstPtr p2 = products.value("p2"); QVERIFY(!!p2); const ResolvedProductPtr p3 = products.value("p3"); QVERIFY(!!p3); const ResolvedProductPtr p4 = products.value("p4"); QVERIFY(!!p4); QVERIFY(p1->dependencies == std::vector({p3, p4})); QVERIFY(p2->dependencies == std::vector({p3, p4})); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::fileTags_data() { QTest::addColumn("numberOfGroups"); QTest::addColumn("expectedFileTags"); QTest::newRow("init") << size_t(0) << QStringList(); QTest::newRow("filetagger_project_scope") << size_t(1) << (QStringList() << "cpp"); QTest::newRow("filetagger_product_scope") << size_t(1) << (QStringList() << "asm"); QTest::newRow("filetagger_static_pattern") << size_t(1) << (QStringList() << "yellow"); QTest::newRow("unknown_file_tag") << size_t(1) << (QStringList() << "unknown-file-tag"); QTest::newRow("set_file_tag_via_group") << size_t(2) << (QStringList() << "c++"); QTest::newRow("override_file_tag_via_group") << size_t(2) << (QStringList() << "c++"); QTest::newRow("add_file_tag_via_group") << size_t(2) << (QStringList() << "cpp" << "zzz"); QTest::newRow("prioritized_filetagger") << size_t(1) << (QStringList() << "cpp1" << "cpp2"); QTest::newRow("cleanup") << size_t(0) << QStringList(); } void TestLanguage::fileTags() { HANDLE_INIT_CLEANUP_DATATAGS("filetags.qbs"); QFETCH(size_t, numberOfGroups); QFETCH(QStringList, expectedFileTags); QHash products = productsFromProject(project); ResolvedProductPtr product; const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); QVERIFY(!!(product = products.value(productName))); QCOMPARE(product->groups.size(), numberOfGroups); GroupPtr group = *(product->groups.end() - 1); QVERIFY(!!group); QCOMPARE(group->files.size(), size_t(1)); SourceArtifactConstPtr sourceFile = group->files.front(); QStringList fileTags = sourceFile->fileTags.toStringList(); fileTags.sort(); QCOMPARE(fileTags, expectedFileTags); } void TestLanguage::wildcards_data() { QTest::addColumn("useGroup"); QTest::addColumn("filesToCreate"); QTest::addColumn("projectFileSubDir"); QTest::addColumn("prefix"); QTest::addColumn("patterns"); QTest::addColumn("excludePatterns"); QTest::addColumn("expected"); const bool useGroup = true; for (int i = 0; i <= 1; ++i) { const bool useGroup = i; const QByteArray dataTagSuffix = useGroup ? " group" : " nogroup"; QTest::newRow(QByteArray("simple 1") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*.h") << QStringList() << (QStringList() << "foo.h" << "bar.h"); QTest::newRow(QByteArray("simple 2") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "foo.*") << QStringList() << (QStringList() << "foo.h" << "foo.cpp"); QTest::newRow(QByteArray("simple 3") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*.h" << "*.cpp") << QStringList() << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp"); QTest::newRow(QByteArray("exclude 1") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*.h" << "*.cpp") << (QStringList() << "bar*") << (QStringList() << "foo.h" << "foo.cpp"); QTest::newRow(QByteArray("exclude 2") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*") << (QStringList() << "*.qbs") << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp"); QTest::newRow(QByteArray("non-recursive") + dataTagSuffix) << useGroup << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp") << QString() << QString() << (QStringList() << "a/*") << QStringList() << (QStringList() << "a/foo.h" << "a/foo.cpp"); QTest::newRow(QByteArray("absolute paths") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << m_wildcardsTestDirPath + "/?oo.*") << QStringList() << (QStringList() << "foo.h" << "foo.cpp"); QTest::newRow(QByteArray("relative paths with dotdot") + dataTagSuffix) << useGroup << (QStringList() << "bar.h" << "bar.cpp") << QString("TheLaughingLlama") << QString() << (QStringList() << "../bar.*") << QStringList() << (QStringList() << "bar.h" << "bar.cpp"); } QTest::newRow(QByteArray("recursive 1")) << useGroup << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp") << QString() << QString() << (QStringList() << "a/**") << QStringList() << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp"); QTest::newRow(QByteArray("recursive 2")) << useGroup << (QStringList() << "d/1.h" << "b/d/1.h" << "b/c/d/1.h" << "d/e/1.h" << "b/d/e/1.h" << "b/c/d/e/1.h" << "a/d/1.h" << "a/b/d/1.h" << "a/b/c/d/1.h" << "a/d/e/1.h" << "a/b/d/e/1.h" << "a/b/c/d/e/1.h" << "a/d/1.cpp" << "a/b/d/1.cpp" << "a/b/c/d/1.h" << "a/d/e/1.cpp" << "a/b/d/e/1.cpp" << "a/b/c/d/e/1.cpp") << QString() << QString() << (QStringList() << "a/**/d/*.h") << QStringList() << (QStringList() << "a/d/1.h" << "a/b/d/1.h" << "a/b/c/d/1.h"); QTest::newRow(QByteArray("recursive 3")) << useGroup << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp") << QString() << QString() << (QStringList() << "a/**/**/**") << QStringList() << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp"); QTest::newRow(QByteArray("prefix")) << useGroup << (QStringList() << "subdir/foo.h" << "subdir/foo.cpp" << "subdir/bar.h" << "subdir/bar.cpp") << QString() << QString("subdir/") << (QStringList() << "*.h") << QStringList() << (QStringList() << "subdir/foo.h" << "subdir/bar.h"); QTest::newRow(QByteArray("non-existing absolute path")) << useGroup << QStringList() << QString() << QString("/dir") << (QStringList() << "*.whatever") << QStringList() << QStringList(); } void TestLanguage::wildcards() { QFETCH(bool, useGroup); QFETCH(QStringList, filesToCreate); QFETCH(QString, projectFileSubDir); QFETCH(QString, prefix); QFETCH(QStringList, patterns); QFETCH(QStringList, excludePatterns); QFETCH(QStringList, expected); // create test directory QDir::setCurrent(QDir::tempPath()); { QString errorMessage; if (QFile::exists(m_wildcardsTestDirPath)) { if (!removeDirectoryWithContents(m_wildcardsTestDirPath, &errorMessage)) { qDebug() << errorMessage; QVERIFY2(false, "removeDirectoryWithContents failed"); } } QVERIFY(QDir().mkdir(m_wildcardsTestDirPath)); } // create project file const QString groupName = "Keks"; QString dataTag = QString::fromLocal8Bit(QTest::currentDataTag()); dataTag.replace(' ', '_'); if (!projectFileSubDir.isEmpty()) { if (!projectFileSubDir.startsWith('/')) projectFileSubDir.prepend('/'); if (projectFileSubDir.endsWith('/')) projectFileSubDir.chop(1); QVERIFY(QDir().mkpath(m_wildcardsTestDirPath + projectFileSubDir)); } const QString projectFilePath = m_wildcardsTestDirPath + projectFileSubDir + "/test_" + dataTag + ".qbs"; { QFile projectFile(projectFilePath); QVERIFY(projectFile.open(QIODevice::WriteOnly)); QTextStream s(&projectFile); s << "import qbs.base 1.0" << endl << endl << "Application {" << endl << " name: \"MyProduct\"" << endl; if (useGroup) { s << " Group {" << endl << " name: " << toJSLiteral(groupName) << endl; } if (!prefix.isEmpty()) s << " prefix: " << toJSLiteral(prefix) << endl; if (!patterns.empty()) s << " files: " << toJSLiteral(patterns) << endl; if (!excludePatterns.empty()) s << " excludeFiles: " << toJSLiteral(excludePatterns) << endl; if (useGroup) s << " }" << endl; s << "}" << endl << endl; } // create files for (QString filePath : qAsConst(filesToCreate)) { filePath.prepend(m_wildcardsTestDirPath + '/'); QFileInfo fi(filePath); if (!QDir(fi.path()).exists()) QVERIFY(QDir().mkpath(fi.path())); QFile file(filePath); QVERIFY(file.open(QIODevice::WriteOnly)); } // read the project bool exceptionCaught = false; ResolvedProductPtr product; try { defaultParameters.setProjectFilePath(projectFilePath); project = loader->loadProject(defaultParameters); QVERIFY(!!project); const QHash products = productsFromProject(project); product = products.value("MyProduct"); QVERIFY(!!product); GroupPtr group; if (useGroup) { QCOMPARE(product->groups.size(), size_t(HostOsInfo::isMacosHost() ? 3 : 2)); for (const GroupPtr &rg : product->groups) { if (rg->name == groupName) { group = rg; break; } } } else { QCOMPARE(product->groups.size(), size_t(HostOsInfo::isMacosHost() ? 2 : 1)); group = product->groups.front(); } QVERIFY(!!group); QCOMPARE(group->files.size(), size_t(0)); QVERIFY(!!group->wildcards); QStringList actualFilePaths; for (const SourceArtifactConstPtr &artifact : group->wildcards->files) { QString str = artifact->absoluteFilePath; int idx = str.indexOf(m_wildcardsTestDirPath); if (idx != -1) str.remove(0, idx + m_wildcardsTestDirPath.size() + 1); actualFilePaths << str; } actualFilePaths.sort(); expected.sort(); QCOMPARE(actualFilePaths, expected); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); const SettingsPtr s = settings(); TestLanguage tl(ConsoleLogger::instance().logSink(), s.get()); return QTest::qExec(&tl, argc, argv); } qbs-src-1.13.1/tests/auto/language/tst_language.h000066400000000000000000000147321347155106100217040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TST_LANGUAGE_H #define TST_LANGUAGE_H #include #include #include #include #include #include class TestLanguage : public QObject { Q_OBJECT public: TestLanguage(qbs::ILogSink *logSink, qbs::Settings *settings); ~TestLanguage(); private: qbs::ILogSink *m_logSink; qbs::Settings * const m_settings; qbs::Internal::Logger m_logger; qbs::Internal::ScriptEngine *m_engine; qbs::Internal::Loader *loader; qbs::Internal::TopLevelProjectPtr project; qbs::SetupProjectParameters defaultParameters; const QString m_wildcardsTestDirPath; QHash productsFromProject( qbs::Internal::ResolvedProjectPtr project); qbs::Internal::ResolvedModuleConstPtr findModuleByName( qbs::Internal::ResolvedProductPtr product, const QString &name); QVariant productPropertyValue(qbs::Internal::ResolvedProductPtr product, QString propertyName); void handleInitCleanupDataTags(const char *projectFileName, bool *handled); private slots: void init(); void initTestCase(); void cleanupTestCase(); void additionalProductTypes(); void baseProperty(); void baseValidation(); void brokenDependencyCycle(); void brokenDependencyCycle_data(); void buildConfigStringListSyntax(); void builtinFunctionInSearchPathsProperty(); void chainedProbes(); void canonicalArchitecture(); void conditionalDepends(); void delayedError(); void delayedError_data(); void dependencyOnAllProfiles(); void derivedSubProject(); void disabledSubProject(); void dottedNames_data(); void dottedNames(); void emptyJsFile(); void enumerateProjectProperties(); void evalErrorInNonPresentModule_data(); void evalErrorInNonPresentModule(); void environmentVariable(); void errorInDisabledProduct(); void erroneousFiles_data(); void erroneousFiles(); void exports(); void fileContextProperties(); void fileInProductAndModule_data(); void fileInProductAndModule(); void fileTags_data(); void fileTags(); void groupConditions_data(); void groupConditions(); void groupName(); void getNativeSetting(); void homeDirectory(); void identifierSearch_data(); void identifierSearch(); void idUsage(); void idUniqueness(); void importCollection(); void inheritedPropertiesItems_data(); void inheritedPropertiesItems(); void invalidBindingInDisabledItem(); void invalidOverrides(); void invalidOverrides_data(); void itemPrototype(); void itemScope(); void jsExtensions(); void jsImportUsedInMultipleScopes_data(); void jsImportUsedInMultipleScopes(); void moduleMergingVariantValues(); void modulePrioritizationBySearchPath_data(); void modulePrioritizationBySearchPath(); void moduleProperties_data(); void moduleProperties(); void modulePropertiesInGroups(); void modulePropertyOverridesPerProduct(); void moduleScope(); void modules_data(); void modules(); void multiplexedExports(); void multiplexingByProfile(); void multiplexingByProfile_data(); void nonApplicableModulePropertyInProfile(); void nonApplicableModulePropertyInProfile_data(); void nonRequiredProducts(); void nonRequiredProducts_data(); void outerInGroup(); void overriddenPropertiesAndPrototypes(); void overriddenPropertiesAndPrototypes_data(); void overriddenVariantProperty(); void parameterTypes(); void pathProperties(); void productConditions(); void productDirectories(); void profileValuesAndOverriddenValues(); void projectFileLookup(); void projectFileLookup_data(); void propertiesBlocks_data(); void propertiesBlocks(); void propertiesBlockInGroup(); void propertiesItemInModule(); void propertyAssignmentInExportedGroup(); void qbs1275(); void qbsPropertiesInProjectCondition(); void qbsPropertyConvenienceOverride(); void relaxedErrorMode(); void relaxedErrorMode_data(); void requiredAndNonRequiredDependencies(); void requiredAndNonRequiredDependencies_data(); void suppressedAndNonSuppressedErrors(); void throwingProbe(); void throwingProbe_data(); void defaultValue(); void defaultValue_data(); void qualifiedId(); void recursiveProductDependencies(); void rfc1034Identifier(); void versionCompare(); void wildcards_data(); void wildcards(); private: QTemporaryDir m_tempDir; }; #endif // TST_LANGUAGE_H qbs-src-1.13.1/tests/auto/shared.h000066400000000000000000000312651347155106100167120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_TEST_SHARED_H #define QBS_TEST_SHARED_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define REPLACE_IN_FILE(filePath, oldContent, newContent) \ do { \ QFile f((filePath)); \ QVERIFY2(f.open(QIODevice::ReadWrite), qPrintable(f.errorString())); \ QByteArray content = f.readAll(); \ const QByteArray savedContent = content; \ content.replace((oldContent), (newContent)); \ QVERIFY(content != savedContent); \ f.resize(0); \ f.write(content); \ } while (false) inline int testTimeoutInMsecs() { bool ok; int timeoutInSecs = qEnvironmentVariableIntValue("QBS_AUTOTEST_TIMEOUT", &ok); if (!ok) timeoutInSecs = 600; return timeoutInSecs * 1000; } // On Windows, it appears that a lock is sometimes held on files for a short while even after // they are closed. The likelihood for that seems to increase with the slowness of the machine. inline void waitForFileUnlock() { bool ok; int timeoutInSecs = qEnvironmentVariableIntValue("QBS_AUTOTEST_IO_GRACE_PERIOD", &ok); if (!ok) timeoutInSecs = qbs::Internal::HostOsInfo::isWindowsHost() ? 1 : 0; if (timeoutInSecs > 0) QTest::qWait(timeoutInSecs * 1000); } using SettingsPtr = std::unique_ptr; inline SettingsPtr settings() { const QString settingsDir = QLatin1String(qgetenv("QBS_AUTOTEST_SETTINGS_DIR")); return SettingsPtr(new qbs::Settings(settingsDir)); } inline QString profileName() { const QString suiteProfile = QLatin1String( qgetenv("QBS_AUTOTEST_PROFILE_" QBS_TEST_SUITE_NAME)); if (!suiteProfile.isEmpty()) return suiteProfile; const QString profile = QLatin1String(qgetenv("QBS_AUTOTEST_PROFILE")); return !profile.isEmpty() ? profile : QLatin1String("none"); } inline QString relativeBuildDir(const QString &configurationName = QString()) { return !configurationName.isEmpty() ? configurationName : QLatin1String("default"); } inline QString relativeBuildGraphFilePath() { return relativeBuildDir() + QLatin1Char('/') + relativeBuildDir() + QLatin1String(".bg"); } inline bool regularFileExists(const QString &filePath) { const QFileInfo fi(filePath); return fi.exists() && fi.isFile(); } inline bool directoryExists(const QString &dirPath) { const QFileInfo fi(dirPath); return fi.exists() && fi.isDir(); } struct ReadFileContentResult { QByteArray content; QString errorString; }; inline ReadFileContentResult readFileContent(const QString &filePath) { ReadFileContentResult result; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { result.errorString = file.errorString(); return result; } result.content = file.readAll(); return result; } inline QByteArray diffText(const QByteArray &actual, const QByteArray &expected) { QByteArray result; QList actualLines = actual.split('\n'); QList expectedLines = expected.split('\n'); int n = 1; while (!actualLines.isEmpty() && !expectedLines.isEmpty()) { QByteArray actualLine = actualLines.takeFirst(); QByteArray expectedLine = expectedLines.takeFirst(); if (actualLine != expectedLine) { result += QStringLiteral("%1: actual: %2\n%1:expected: %3\n") .arg(n, 2) .arg(QString::fromUtf8(actualLine)) .arg(QString::fromUtf8(expectedLine)) .toUtf8(); } n++; } auto addLines = [&result, &n] (const QList &lines) { for (const QByteArray &line : qAsConst(lines)) { result += QStringLiteral("%1: %2\n").arg(n).arg(QString::fromUtf8(line)); n++; } }; if (!actualLines.isEmpty()) { result += "Extra unexpected lines:\n"; addLines(actualLines); } if (!expectedLines.isEmpty()) { result += "Missing expected lines:\n"; addLines(expectedLines); } return result; } #define READ_TEXT_FILE(filePath, contentVariable) \ QByteArray contentVariable; \ { \ auto c = readFileContent(filePath); \ QVERIFY2(c.errorString.isEmpty(), \ qUtf8Printable(QStringLiteral("Cannot open file %1. %2") \ .arg(filePath, c.errorString))); \ contentVariable = std::move(c.content); \ } #define TEXT_FILE_COMPARE(actualFilePath, expectedFilePath) \ { \ READ_TEXT_FILE(actualFilePath, ba1); \ READ_TEXT_FILE(expectedFilePath, ba2); \ if (ba1 != ba2) { \ QByteArray msg = "File contents differ:\n" + diffText(ba1, ba2); \ QFAIL(msg.constData()); \ } \ } template inline QString prefixedIfNonEmpty(const T &prefix, const QString &str) { if (str.isEmpty()) return QString(); return prefix + str; } inline QString uniqueProductName(const QString &productName, const QString &multiplexConfigurationId) { return productName + prefixedIfNonEmpty(QLatin1Char('.'), multiplexConfigurationId); } inline QString relativeProductBuildDir(const QString &productName, const QString &configurationName = QString(), const QString &multiplexConfigurationId = QString()) { const QString fullName = uniqueProductName(productName, multiplexConfigurationId); QString dirName = qbs::Internal::HostOsInfo::rfc1034Identifier(fullName); const QByteArray hash = QCryptographicHash::hash(fullName.toUtf8(), QCryptographicHash::Sha1); dirName.append('.').append(hash.toHex().left(8)); return relativeBuildDir(configurationName) + '/' + dirName; } inline QString relativeExecutableFilePath(const QString &productName) { return relativeProductBuildDir(productName) + '/' + qbs::Internal::HostOsInfo::appendExecutableSuffix(productName); } inline void waitForNewTimestamp(const QString &testDir) { // Waits for the time that corresponds to the host file system's time stamp granularity. if (qbs::Internal::HostOsInfo::isWindowsHost()) { QTest::qWait(1); // NTFS has 100 ns precision. Let's ignore exFAT. } else { const QString nameTemplate = testDir + "/XXXXXX"; QTemporaryFile f1(nameTemplate); if (!f1.open()) qFatal("Failed to open temp file"); const QDateTime initialTime = QFileInfo(f1).lastModified(); int totalMsPassed = 0; while (totalMsPassed <= 2000) { static const int increment = 50; QTest::qWait(increment); totalMsPassed += increment; QTemporaryFile f2(nameTemplate); if (!f2.open()) qFatal("Failed to open temp file"); if (QFileInfo(f2).lastModified() > initialTime) return; } qWarning("Got no new timestamp after two seconds, going ahead anyway. Subsequent " "test failure might not be genuine."); } } inline void touch(const QString &fn) { QFile f(fn); int s = f.size(); if (!f.open(QFile::ReadWrite)) qFatal("cannot open file %s", qPrintable(fn)); f.resize(s+1); f.resize(s); } inline void copyFileAndUpdateTimestamp(const QString &source, const QString &target) { QFile::remove(target); if (!QFile::copy(source, target)) qFatal("Failed to copy '%s' to '%s'", qPrintable(source), qPrintable(target)); touch(target); } inline QString objectFileName(const QString &baseName, const QString &profileName) { const SettingsPtr s = settings(); qbs::Profile profile(profileName, s.get()); const auto tc = profile.value("qbs.toolchainType").toString(); const auto tcList = profile.value("qbs.toolchain").toStringList(); const bool isMsvc = tc == "msvc" || tcList.contains("msvc") || (tc.isEmpty() && tcList.isEmpty() && qbs::Internal::HostOsInfo::isWindowsHost()); const QString suffix = isMsvc ? "obj" : "o"; return baseName + '.' + suffix; } inline QString inputDirHash(const QString &dir) { return QCryptographicHash::hash(dir.toLatin1(), QCryptographicHash::Sha1).toHex().left(16); } inline QString testWorkDir(const QString &testName) { QString dir = QDir::fromNativeSeparators(QString::fromLocal8Bit(qgetenv("QBS_TEST_WORK_ROOT"))); if (dir.isEmpty()) { dir = QCoreApplication::applicationDirPath() + QStringLiteral("/../tests/auto/"); } else { if (!dir.endsWith(QLatin1Char('/'))) dir += QLatin1Char('/'); } return dir + testName + "/testWorkDir"; } inline bool copyDllExportHeader(const QString &srcDataDir, const QString &targetDataDir) { QFile sourceFile(srcDataDir + "/../../dllexport.h"); const QString targetPath = targetDataDir + "/dllexport.h"; QFile::remove(targetPath); return sourceFile.copy(targetPath); } inline qbs::Internal::HostOsInfo::HostOs targetOs() { const SettingsPtr s = settings(); const qbs::Profile buildProfile(profileName(), s.get()); const QString targetPlatform = buildProfile.value("qbs.targetPlatform").toString(); if (!targetPlatform.isEmpty()) { const std::vector targetOS = qbs::Internal::HostOsInfo::canonicalOSIdentifiers( targetPlatform.toStdString()); if (qbs::Internal::contains(targetOS, "windows")) return qbs::Internal::HostOsInfo::HostOsWindows; if (qbs::Internal::contains(targetOS, "linux")) return qbs::Internal::HostOsInfo::HostOsLinux; if (qbs::Internal::contains(targetOS, "macos")) return qbs::Internal::HostOsInfo::HostOsMacos; if (qbs::Internal::contains(targetOS, "unix")) return qbs::Internal::HostOsInfo::HostOsOtherUnix; return qbs::Internal::HostOsInfo::HostOsOther; } return qbs::Internal::HostOsInfo::hostOs(); } #endif // Include guard. qbs-src-1.13.1/tests/auto/tools/000077500000000000000000000000001347155106100164245ustar00rootroot00000000000000qbs-src-1.13.1/tests/auto/tools/tools.pro000066400000000000000000000001711347155106100203050ustar00rootroot00000000000000TARGET = tst_tools SOURCES = tst_tools.cpp ../../../src/app/qbs/qbstool.cpp HEADERS = tst_tools.h include(../auto.pri) qbs-src-1.13.1/tests/auto/tools/tools.qbs000066400000000000000000000004701347155106100202740ustar00rootroot00000000000000import qbs import qbs.Utilities QbsAutotest { Depends { name: "qbsversion" } testName: "tools" condition: qbsbuildconfig.enableUnitTests files: [ "tst_tools.cpp", "tst_tools.h" ] cpp.defines: base.concat(["QBS_VERSION=" + Utilities.cStringQuote(qbsversion.version)]) } qbs-src-1.13.1/tests/auto/tools/tst_tools.cpp000066400000000000000000001114351347155106100211670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #undef QT_NO_CAST_FROM_ASCII // I am qmake, and I approve this hack. #include "tst_tools.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using namespace qbs::Internal; TestTools::TestTools(Settings *settings) : m_settings(settings), testDataDir(testWorkDir("tools")) { } TestTools::~TestTools() { qDeleteAll(m_tmpDirs); } void TestTools::initTestCase() { QDir().mkpath(testDataDir); } void TestTools::fileSaver() { QVERIFY(QDir::setCurrent(testDataDir)); static const char *fn = "foo.txt"; const auto run = [](const std::function &func) { if (QFile::exists(fn)) QVERIFY(QFile::remove(fn)); func(); if (QFile::exists(fn)) QVERIFY(QFile::remove(fn)); }; // failing to open the file means nothing works run([] { Internal::FileSaver fs(fn); QVERIFY(!fs.device()); QVERIFY(!fs.write("hello")); QVERIFY(!fs.commit()); QVERIFY(!QFile::exists(fn)); }); // verify that correct usage creates a file with the right contents run([] { Internal::FileSaver fs(fn); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello")); QVERIFY(fs.commit()); QVERIFY(QFile::exists(fn)); QFile f(fn); QVERIFY(f.open(QIODevice::ReadOnly)); QCOMPARE(f.readAll(), QByteArrayLiteral("hello")); }); // failing to commit writes nothing run([] { Internal::FileSaver fs(fn); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello")); QVERIFY(!QFile::exists(fn)); }); // verify that correct usage creates a file with the right contents and does not overwrite run([] { { Internal::FileSaver fs(fn); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello")); QVERIFY(fs.commit()); QVERIFY(QFile::exists(fn)); QFile f(fn); QVERIFY(f.open(QIODevice::ReadOnly)); QCOMPARE(f.readAll(), QByteArrayLiteral("hello")); } const auto lm = QFileInfo(fn).lastModified(); QVERIFY(lm.isValid()); waitForNewTimestamp("."); { Internal::FileSaver fs(fn); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello")); QVERIFY(fs.commit()); QVERIFY(QFile::exists(fn)); } const auto lm2 = QFileInfo(fn).lastModified(); QVERIFY(lm2.isValid()); QCOMPARE(lm, lm2); // timestamps should be the same since content did not change waitForNewTimestamp("."); { Internal::FileSaver fs(fn); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello2")); QVERIFY(fs.commit()); QVERIFY(QFile::exists(fn)); QFile f(fn); QVERIFY(f.open(QIODevice::ReadOnly)); QCOMPARE(f.readAll(), QByteArrayLiteral("hello2")); } const auto lm3 = QFileInfo(fn).lastModified(); QVERIFY(lm3.isValid()); QVERIFY(lm != lm3); // timestamps should differ since the content changed waitForNewTimestamp("."); { // Test overwriteIfUnchanged Internal::FileSaver fs(fn, true); QVERIFY(fs.open()); QVERIFY(fs.device()); QVERIFY(fs.write("hello2")); QVERIFY(fs.commit()); QVERIFY(QFile::exists(fn)); QFile f(fn); QVERIFY(f.open(QIODevice::ReadOnly)); QCOMPARE(f.readAll(), QByteArrayLiteral("hello2")); } const auto lm4 = QFileInfo(fn).lastModified(); QVERIFY(lm4.isValid()); QVERIFY(lm3 != lm4); // timestamps should differ since we always overwrite }); } void TestTools::testFileInfo() { QCOMPARE(FileInfo::fileName("C:/waffl/copter.exe"), QString("copter.exe")); QCOMPARE(FileInfo::baseName("C:/waffl/copter.exe.lib"), QString("copter")); QCOMPARE(FileInfo::completeBaseName("C:/waffl/copter.exe.lib"), QString("copter.exe")); QCOMPARE(FileInfo::suffix("C:/waffl/copter.exe.lib"), QString("lib")); QCOMPARE(FileInfo::completeSuffix("C:/waffl/copter.exe.lib"), QString("exe.lib")); QCOMPARE(FileInfo::path("abc"), QString(".")); QCOMPARE(FileInfo::path("/abc/lol"), QString("/abc")); QCOMPARE(FileInfo::path("/fileInRoot"), QString(QLatin1Char('/'))); if (HostOsInfo::isWindowsHost()) QCOMPARE(FileInfo::path("C:/fileInDriveRoot"), QString("C:/")); QVERIFY(!FileInfo::isAbsolute("bla/lol")); QVERIFY(FileInfo::isAbsolute("/bla/lol")); if (HostOsInfo::isWindowsHost()) { QVERIFY(FileInfo::isAbsolute("C:\\bla\\lol")); QVERIFY(FileInfo::isAbsolute("C:\\")); QVERIFY(FileInfo::isAbsolute("C:/")); QVERIFY(!FileInfo::isAbsolute("C:")); } QCOMPARE(FileInfo::resolvePath("/abc/lol", "waffl"), QString("/abc/lol/waffl")); QCOMPARE(FileInfo::resolvePath("/abc/def/ghi/jkl/", "../foo/bar"), QString("/abc/def/ghi/foo/bar")); QCOMPARE(FileInfo::resolvePath("/abc/def/ghi/jkl/", "../../foo/bar"), QString("/abc/def/foo/bar")); QCOMPARE(FileInfo::resolvePath("/abc", "../../../foo/bar"), QString("/foo/bar")); if (HostOsInfo::isWindowsHost()) { QCOMPARE(FileInfo::resolvePath("C:/share", ".."), QString("C:/")); QCOMPARE(FileInfo::resolvePath("C:/share", "D:/"), QString("D:/")); QCOMPARE(FileInfo::resolvePath("C:/share", "D:"), QString()); // should soft-assert } QCOMPARE(FileInfo("/does/not/exist").lastModified(), FileTime()); } void TestTools::fileCaseCheck() { QTemporaryFile tempFile(QDir::tempPath() + QLatin1String("/CamelCase")); QVERIFY2(tempFile.open(), qPrintable(tempFile.errorString())); QFileInfo tempFileInfo(tempFile.fileName()); const QString lowerFilePath = tempFileInfo.absolutePath() + QLatin1Char('/') + tempFileInfo.fileName().toLower(); const QString upperFilePath = tempFileInfo.absolutePath() + QLatin1Char('/') + tempFileInfo.fileName().toUpper(); QVERIFY(FileInfo::isFileCaseCorrect(tempFileInfo.absoluteFilePath())); if (QFile::exists(lowerFilePath)) QVERIFY(!FileInfo::isFileCaseCorrect(lowerFilePath)); if (QFile::exists(upperFilePath)) QVERIFY(!FileInfo::isFileCaseCorrect(upperFilePath)); } void TestTools::testProfiles() { TemporaryProfile tpp("parent", m_settings); Profile parentProfile = tpp.p; TemporaryProfile tpc("child", m_settings); Profile childProfile = tpc.p; parentProfile.removeBaseProfile(); parentProfile.remove("testKey"); QCOMPARE(parentProfile.value("testKey", "none").toString(), QLatin1String("none")); parentProfile.setValue("testKey", "testValue"); QCOMPARE(parentProfile.value("testKey").toString(), QLatin1String("testValue")); childProfile.remove("testKey"); childProfile.removeBaseProfile(); QCOMPARE(childProfile.value("testKey", "none").toString(), QLatin1String("none")); childProfile.setBaseProfile("parent"); QCOMPARE(childProfile.value("testKey").toString(), QLatin1String("testValue")); // Change base profile and check if the inherited value also changes. TemporaryProfile tpf("foo", m_settings); Profile fooProfile = tpf.p; fooProfile.setValue("testKey", "gnampf"); childProfile.setBaseProfile("foo"); QCOMPARE(childProfile.value("testKey", "none").toString(), QLatin1String("gnampf")); ErrorInfo errorInfo; childProfile.setBaseProfile("SmurfAlongWithMe"); childProfile.value("blubb", QString(), &errorInfo); QVERIFY(errorInfo.hasError()); errorInfo.clear(); childProfile.setBaseProfile("parent"); parentProfile.setBaseProfile("child"); QVERIFY(!childProfile.value("blubb", QString(), &errorInfo).isValid()); QVERIFY(errorInfo.hasError()); QVERIFY(!childProfile.allKeys(Profile::KeySelectionNonRecursive).empty()); errorInfo.clear(); QVERIFY(childProfile.allKeys(Profile::KeySelectionRecursive, &errorInfo).empty()); QVERIFY(errorInfo.hasError()); } void TestTools::testSettingsMigration() { QFETCH(QString, baseDir); QFETCH(bool, hasOldSettings); Settings settings(baseDir); if (hasOldSettings) { QVERIFY(QFileInfo(settings.baseDirectory() + "/qbs/" QBS_VERSION "/profiles/right.txt") .exists()); QCOMPARE(settings.value("key", Settings::UserScope).toString(), settings.baseDirectory() + "/qbs/" QBS_VERSION "/profilesright"); } else { QVERIFY(!QFileInfo(settings.baseDirectory() + "/qbs/" QBS_VERSION "/profiles").exists()); QVERIFY(settings.allKeys(Settings::UserScope).empty()); } } void TestTools::testSettingsMigration_data() { QTest::addColumn("baseDir"); QTest::addColumn("hasOldSettings"); QTest::newRow("settings dir with lots of versions") << setupSettingsDir1() << true; QTest::newRow("settings dir with only a fallback") << setupSettingsDir2() << true; QTest::newRow("no previous settings") << setupSettingsDir3() << false; } QString TestTools::setupSettingsDir1() { const auto baseDir = new QTemporaryDir; m_tmpDirs.push_back(baseDir); const Version thisVersion = Version::fromString(QBS_VERSION); Version predecessor; if (thisVersion.patchLevel() > 0) { predecessor.setMajorVersion(thisVersion.majorVersion()); predecessor.setMinorVersion(thisVersion.minorVersion()); predecessor.setPatchLevel(thisVersion.patchLevel() - 1); } else if (thisVersion.minorVersion() > 0) { predecessor.setMajorVersion(thisVersion.majorVersion()); predecessor.setMinorVersion(thisVersion.minorVersion() - 1); predecessor.setPatchLevel(99); } else { predecessor.setMajorVersion(thisVersion.majorVersion() - 1); predecessor.setMajorVersion(99); predecessor.setPatchLevel(99); } const auto versions = QList() << Version(0, 1, 0) << Version(1, 0, 5) << predecessor << Version(thisVersion.majorVersion() + 1, thisVersion.minorVersion(), thisVersion.patchLevel()) << Version(thisVersion.majorVersion(), thisVersion.minorVersion() + 1, thisVersion.patchLevel()) << Version(thisVersion.majorVersion(), thisVersion.minorVersion(), thisVersion.patchLevel() + 1) << Version(99, 99, 99); for (const Version &v : versions) { const QString settingsDir = baseDir->path() + "/qbs/" + v.toString(); QSettings s(settingsDir + "/qbs.conf", HostOsInfo::isWindowsHost() ? QSettings::IniFormat : QSettings::NativeFormat); const QString profilesDir = settingsDir + "/profiles"; QDir::root().mkpath(profilesDir); const QString magicString = v == predecessor ? "right" : "wrong"; QFile f(profilesDir + '/' + magicString + ".txt"); f.open(QIODevice::WriteOnly); s.setValue("org/qt-project/qbs/key", profilesDir + magicString); } return baseDir->path(); } QString TestTools::setupSettingsDir2() { const auto baseDir = new QTemporaryDir; m_tmpDirs.push_back(baseDir); const QString settingsDir = baseDir->path(); QSettings s(settingsDir + QLatin1String("/qbs.conf"), HostOsInfo::isWindowsHost() ? QSettings::IniFormat : QSettings::NativeFormat); const QString profilesDir = settingsDir + QLatin1String("/qbs/profiles"); QDir::root().mkpath(profilesDir); QFile f(profilesDir + "/right.txt"); f.open(QIODevice::WriteOnly); s.setValue("org/qt-project/qbs/key", profilesDir + "right"); return baseDir->path(); } QString TestTools::setupSettingsDir3() { const auto baseDir = new QTemporaryDir; m_tmpDirs.push_back(baseDir); return baseDir->path(); } void TestTools::testBuildConfigMerging() { TemporaryProfile tp(QLatin1String("tst_tools_profile"), m_settings); Profile profile = tp.p; profile.setValue(QStringLiteral("topLevelKey"), QStringLiteral("topLevelValue")); profile.setValue(QStringLiteral("qbs.toolchain"), QStringLiteral("gcc")); profile.setValue(QStringLiteral("qbs.architecture"), QStringLiteral("Jean-Claude Pillemann")); profile.setValue(QStringLiteral("cpp.treatWarningsAsErrors"), true); QVariantMap overrideMap; overrideMap.insert(QStringLiteral("qbs.toolchain"), QStringLiteral("clang")); overrideMap.insert(QStringLiteral("qbs.installRoot"), QStringLiteral("/blubb")); SetupProjectParameters params; params.setSettingsDirectory(m_settings->baseDirectory()); params.setTopLevelProfile(profile.name()); params.setConfigurationName(QStringLiteral("debug")); params.setOverriddenValues(overrideMap); const ErrorInfo error = params.expandBuildConfiguration(); QVERIFY2(!error.hasError(), qPrintable(error.toString())); const QVariantMap finalMap = params.finalBuildConfigurationTree(); QCOMPARE(finalMap.size(), 3); QCOMPARE(finalMap.value(QStringLiteral("topLevelKey")).toString(), QStringLiteral("topLevelValue")); const QVariantMap finalQbsMap = finalMap.value(QStringLiteral("qbs")).toMap(); QCOMPARE(finalQbsMap.size(), 4); QCOMPARE(finalQbsMap.value(QStringLiteral("toolchain")).toString(), QStringLiteral("clang")); QCOMPARE(finalQbsMap.value(QStringLiteral("configurationName")).toString(), QStringLiteral("debug")); QCOMPARE(finalQbsMap.value(QStringLiteral("architecture")).toString(), QStringLiteral("Jean-Claude Pillemann")); QCOMPARE(finalQbsMap.value(QStringLiteral("installRoot")).toString(), QLatin1String("/blubb")); const QVariantMap finalCppMap = finalMap.value(QStringLiteral("cpp")).toMap(); QCOMPARE(finalCppMap.size(), 1); QCOMPARE(finalCppMap.value(QStringLiteral("treatWarningsAsErrors")).toBool(), true); } void TestTools::testProcessNameByPid() { QCOMPARE(qAppName(), processNameByPid(QCoreApplication::applicationPid())); } int toNumber(const QString &str) { int res = 0; for (const QChar &c : str) res = (res * 10) + c.digitValue(); return res; } void TestTools::set_operator_eq() { { Set set1, set2; QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set1.insert(1); QVERIFY(set1 != set2); QVERIFY(!(set1 == set2)); set2.insert(1); QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set2.insert(1); QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set1.insert(2); QVERIFY(set1 != set2); QVERIFY(!(set1 == set2)); } { Set set1, set2; QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set1.insert("one"); QVERIFY(set1 != set2); QVERIFY(!(set1 == set2)); set2.insert("one"); QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set2.insert("one"); QVERIFY(set1 == set2); QVERIFY(!(set1 != set2)); set1.insert("two"); QVERIFY(set1 != set2); QVERIFY(!(set1 == set2)); } { Set a; Set b; a += "otto"; b += "willy"; QVERIFY(a != b); QVERIFY(!(a == b)); } { Set s1, s2; s1.reserve(100); s2.reserve(4); QVERIFY(s1 == s2); s1 << 100 << 200 << 300 << 400; s2 << 400 << 300 << 200 << 100; QVERIFY(s1 == s2); } } void TestTools::set_swap() { Set s1, s2; s1.insert(1); s2.insert(2); s1.swap(s2); QCOMPARE(*s1.begin(),2); QCOMPARE(*s2.begin(),1); } void TestTools::set_size() { Set set; QVERIFY(set.size() == 0); QVERIFY(set.empty()); QVERIFY(set.size() == set.size()); set.insert(1); QVERIFY(set.size() == 1); QVERIFY(!set.empty()); QVERIFY(set.size() == set.size()); set.insert(1); QVERIFY(set.size() == 1); QVERIFY(!set.empty()); QVERIFY(set.size() == set.size()); set.insert(2); QVERIFY(set.size() == 2); QVERIFY(!set.empty()); QVERIFY(set.size() == set.size()); set.remove(1); QVERIFY(set.size() == 1); QVERIFY(!set.empty()); QVERIFY(set.size() == set.size()); set.remove(1); QVERIFY(set.size() == 1); QVERIFY(!set.empty()); QVERIFY(set.size() == set.size()); set.remove(2); QVERIFY(set.size() == 0); QVERIFY(set.empty()); QVERIFY(set.size() == set.size()); } void TestTools::set_capacity() { Set set; size_t n = set.capacity(); QVERIFY(n == 0); for (int i = 0; i < 1000; ++i) { set.insert(i); QVERIFY(set.capacity() >= set.size()); } } void TestTools::set_reserve() { Set set; set.reserve(1000); QVERIFY(set.capacity() >= 1000); for (int i = 0; i < 500; ++i) set.insert(i); QVERIFY(set.capacity() >= 1000); for (int j = 0; j < 500; ++j) set.remove(j); QVERIFY(set.capacity() >= 1000); } void TestTools::set_clear() { Set set1, set2; QVERIFY(set1.size() == 0); set1.clear(); QVERIFY(set1.size() == 0); set1.insert("foo"); QVERIFY(set1.size() != 0); set2 = set1; set1.clear(); QVERIFY(set1.size() == 0); QVERIFY(set2.size() != 0); set2.clear(); QVERIFY(set1.size() == 0); QVERIFY(set2.size() == 0); } void TestTools::set_remove() { Set set1; const size_t max = 500; for (size_t i = 0; i < max; ++i) set1.insert(QString::number(i)); QCOMPARE(set1.size(), max); for (size_t j = 0; j < max; ++j) { set1.remove(QString::number((j * 17) % max)); QCOMPARE(set1.size(), max - j - 1); } } void TestTools::set_contains() { Set set1; for (int i = 0; i < 500; ++i) { QVERIFY(!set1.contains(QString::number(i))); set1.insert(QString::number(i)); QVERIFY(set1.contains(QString::number(i))); } QCOMPARE(set1.size(), size_t { 500 }); for (int j = 0; j < 500; ++j) { int i = (j * 17) % 500; QVERIFY(set1.contains(QString::number(i))); set1.remove(QString::number(i)); QVERIFY(!set1.contains(QString::number(i))); } } void TestTools::set_containsSet() { Set set1; Set set2; // empty set contains the empty set QVERIFY(set1.contains(set2)); for (int i = 0; i < 500; ++i) { set1.insert(QString::number(i)); set2.insert(QString::number(i)); } QVERIFY(set1.contains(set2)); set2.remove(QString::number(19)); set2.remove(QString::number(82)); set2.remove(QString::number(7)); QVERIFY(set1.contains(set2)); set1.remove(QString::number(23)); QVERIFY(!set1.contains(set2)); // filled set contains the empty set as well Set set3; QVERIFY(set1.contains(set3)); // the empty set doesn't contain a filled set QVERIFY(!set3.contains(set1)); // verify const signature const Set set4; QVERIFY(set3.contains(set4)); } void TestTools::set_begin() { Set set1; Set set2 = set1; { Set::const_iterator i = set1.constBegin(); Set::const_iterator j = set1.cbegin(); Set::const_iterator k = set2.constBegin(); Set::const_iterator ell = set2.cbegin(); QVERIFY(i == j); QVERIFY(k == ell); } set1.insert(44); { Set::const_iterator i = set1.constBegin(); Set::const_iterator j = set1.cbegin(); Set::const_iterator k = set2.constBegin(); Set::const_iterator ell = set2.cbegin(); QVERIFY(i == j); QVERIFY(k == ell); } set2 = set1; { Set::const_iterator i = set1.constBegin(); Set::const_iterator j = set1.cbegin(); Set::const_iterator k = set2.constBegin(); Set::const_iterator ell = set2.cbegin(); QVERIFY(i == j); QVERIFY(k == ell); } } void TestTools::set_end() { Set set1; Set set2 = set1; { Set::const_iterator i = set1.constEnd(); Set::const_iterator j = set1.cend(); Set::const_iterator k = set2.constEnd(); Set::const_iterator ell = set2.cend(); QVERIFY(i == j); QVERIFY(k == ell); QVERIFY(set1.constBegin() == set1.constEnd()); QVERIFY(set2.constBegin() == set2.constEnd()); } set1.insert(44); { Set::const_iterator i = set1.constEnd(); Set::const_iterator j = set1.cend(); Set::const_iterator k = set2.constEnd(); Set::const_iterator ell = set2.cend(); QVERIFY(i == j); QVERIFY(k == ell); QVERIFY(set1.constBegin() != set1.constEnd()); QVERIFY(set2.constBegin() == set2.constEnd()); } set2 = set1; { Set::const_iterator i = set1.constEnd(); Set::const_iterator j = set1.cend(); Set::const_iterator k = set2.constEnd(); Set::const_iterator ell = set2.cend(); QVERIFY(i == j); QVERIFY(k == ell); QVERIFY(set1.constBegin() != set1.constEnd()); QVERIFY(set2.constBegin() != set2.constEnd()); } set1.clear(); set2.clear(); QVERIFY(set1.constBegin() == set1.constEnd()); QVERIFY(set2.constBegin() == set2.constEnd()); } struct IdentityTracker { int value, id; }; inline bool operator==(IdentityTracker lhs, IdentityTracker rhs) { return lhs.value == rhs.value; } inline bool operator<(IdentityTracker lhs, IdentityTracker rhs) { return lhs.value < rhs.value; } void TestTools::set_insert() { { Set set1; QVERIFY(set1.size() == 0); set1.insert(1); QVERIFY(set1.size() == 1); set1.insert(2); QVERIFY(set1.size() == 2); set1.insert(2); QVERIFY(set1.size() == 2); QVERIFY(set1.contains(2)); set1.remove(2); QVERIFY(set1.size() == 1); QVERIFY(!set1.contains(2)); set1.insert(2); QVERIFY(set1.size() == 2); QVERIFY(set1.contains(2)); } { Set set1; QVERIFY(set1.size() == 0); set1 << 1; QVERIFY(set1.size() == 1); set1 << 2; QVERIFY(set1.size() == 2); set1 << 2; QVERIFY(set1.size() == 2); QVERIFY(set1.contains(2)); set1.remove(2); QVERIFY(set1.size() == 1); QVERIFY(!set1.contains(2)); set1 << 2; QVERIFY(set1.size() == 2); QVERIFY(set1.contains(2)); } { Set set; QCOMPARE(set.size(), size_t { 0 }); const int dummy = -1; IdentityTracker id00 = {0, 0}, id01 = {0, 1}, searchKey = {0, dummy}; QCOMPARE(set.insert(id00).first->id, id00.id); QCOMPARE(set.size(), size_t { 1 }); QCOMPARE(set.insert(id01).first->id, id00.id); // first inserted is kept QCOMPARE(set.size(), size_t { 1 }); QCOMPARE(set.find(searchKey)->id, id00.id); } } void TestTools::set_reverseIterators() { Set s; s << 1 << 17 << 61 << 127 << 911; std::vector v(s.begin(), s.end()); std::reverse(v.begin(), v.end()); const Set &cs = s; QVERIFY(std::equal(v.begin(), v.end(), s.rbegin())); QVERIFY(std::equal(v.begin(), v.end(), s.crbegin())); QVERIFY(std::equal(v.begin(), v.end(), cs.rbegin())); QVERIFY(std::equal(s.rbegin(), s.rend(), v.begin())); QVERIFY(std::equal(s.crbegin(), s.crend(), v.begin())); QVERIFY(std::equal(cs.rbegin(), cs.rend(), v.begin())); } void TestTools::set_stlIterator() { Set set1; for (int i = 0; i < 25000; ++i) set1.insert(QString::number(i)); { int sum = 0; Set::const_iterator i = set1.cbegin(); while (i != set1.end()) { sum += toNumber(*i); ++i; } QVERIFY(sum == 24999 * 25000 / 2); } { int sum = 0; Set::const_iterator i = set1.cend(); while (i != set1.begin()) { --i; sum += toNumber(*i); } QVERIFY(sum == 24999 * 25000 / 2); } } void TestTools::set_stlMutableIterator() { Set set1; for (int i = 0; i < 25000; ++i) set1.insert(QString::number(i)); { int sum = 0; Set::iterator i = set1.begin(); while (i != set1.end()) { sum += toNumber(*i); ++i; } QVERIFY(sum == 24999 * 25000 / 2); } { int sum = 0; Set::iterator i = set1.end(); while (i != set1.begin()) { --i; sum += toNumber(*i); } QVERIFY(sum == 24999 * 25000 / 2); } { Set set2 = set1; Set set3 = set2; Set::iterator i = set2.begin(); Set::iterator j = set3.begin(); while (i != set2.end()) { i = set2.erase(i); } QVERIFY(set2.empty()); QVERIFY(!set3.empty()); j = set3.end(); while (j != set3.begin()) { j--; if (j + 1 != set3.end()) set3.erase(j + 1); } if (set3.begin() != set3.end()) set3.erase(set3.begin()); QVERIFY(set2.empty()); QVERIFY(set3.empty()); i = set2.insert("foo").first; QCOMPARE(*i, QLatin1String("foo")); } } void TestTools::set_setOperations() { Set set1, set2; set1 << "alpha" << "beta" << "gamma" << "delta" << "zeta" << "omega"; set2 << "beta" << "gamma" << "delta" << "epsilon" << "iota" << "omega"; Set set3 = set1; set3.unite(set2); QVERIFY(set3.size() == 8); QVERIFY(set3.contains("alpha")); QVERIFY(set3.contains("beta")); QVERIFY(set3.contains("gamma")); QVERIFY(set3.contains("delta")); QVERIFY(set3.contains("epsilon")); QVERIFY(set3.contains("zeta")); QVERIFY(set3.contains("iota")); QVERIFY(set3.contains("omega")); Set set4 = set2; set4.unite(set1); QVERIFY(set4.size() == 8); QVERIFY(set4.contains("alpha")); QVERIFY(set4.contains("beta")); QVERIFY(set4.contains("gamma")); QVERIFY(set4.contains("delta")); QVERIFY(set4.contains("epsilon")); QVERIFY(set4.contains("zeta")); QVERIFY(set4.contains("iota")); QVERIFY(set4.contains("omega")); QVERIFY(set3 == set4); Set set5 = set1; set5.intersect(set2); QVERIFY(set5.size() == 4); QVERIFY(set5.contains("beta")); QVERIFY(set5.contains("gamma")); QVERIFY(set5.contains("delta")); QVERIFY(set5.contains("omega")); Set set6 = set2; set6.intersect(set1); QVERIFY(set6.size() == 4); QVERIFY(set6.contains("beta")); QVERIFY(set6.contains("gamma")); QVERIFY(set6.contains("delta")); QVERIFY(set6.contains("omega")); QVERIFY(set5 == set6); Set set7 = set1; set7.subtract(set2); QVERIFY(set7.size() == 2); QVERIFY(set7.contains("alpha")); QVERIFY(set7.contains("zeta")); Set set8 = set2; set8.subtract(set1); QVERIFY(set8.size() == 2); QVERIFY(set8.contains("epsilon")); QVERIFY(set8.contains("iota")); Set set9 = set1 | set2; QVERIFY(set9 == set3); Set set10 = set1 & set2; QVERIFY(set10 == set5); Set set11 = set1 + set2; QVERIFY(set11 == set3); Set set12 = set1 - set2; QVERIFY(set12 == set7); Set set13 = set2 - set1; QVERIFY(set13 == set8); Set set14 = set1; set14 |= set2; QVERIFY(set14 == set3); Set set15 = set1; set15 &= set2; QVERIFY(set15 == set5); Set set16 = set1; set16 += set2; QVERIFY(set16 == set3); Set set17 = set1; set17 -= set2; QVERIFY(set17 == set7); Set set18 = set2; set18 -= set1; QVERIFY(set18 == set8); } void TestTools::set_makeSureTheComfortFunctionsCompile() { Set set1, set2, set3; set1 << 5; set1 |= set2; set1 |= 5; set1 &= set2; set1 &= 5; set1 += set2; set1 += 5; set1 -= set2; set1 -= 5; set1 = set2 | set3; set1 = set2 & set3; set1 = set2 + set3; set1 = set2 - set3; } void TestTools::set_initializerList() { Set set = {1, 1, 2, 3, 4, 5}; QCOMPARE(set.size(), size_t { 5 }); QVERIFY(set.contains(1)); QVERIFY(set.contains(2)); QVERIFY(set.contains(3)); QVERIFY(set.contains(4)); QVERIFY(set.contains(5)); // check _which_ of the equal elements gets inserted (in the QHash/QMap case, it's the last): const Set set2 = {{1, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; QCOMPARE(set2.size(), size_t { 5 }); const int dummy = -1; const IdentityTracker searchKey = {1, dummy}; QCOMPARE(set2.find(searchKey)->id, 0); Set emptySet{}; QVERIFY(emptySet.empty()); Set set3{{}, {}, {}}; QVERIFY(!set3.empty()); } void TestTools::set_intersects() { Set s1; Set s2; QVERIFY(!s1.intersects(s1)); QVERIFY(!s1.intersects(s2)); s1 << 100; QVERIFY(s1.intersects(s1)); QVERIFY(!s1.intersects(s2)); s2 << 200; QVERIFY(!s1.intersects(s2)); s1 << 200; QVERIFY(s1.intersects(s2)); Set s3; s3 << 500; QVERIFY(!s1.intersects(s3)); s3 << 200; QVERIFY(s1.intersects(s3)); } void TestTools::stringutils_join() { QFETCH(std::vector, input); QFETCH(std::string, separator); QFETCH(std::string, expectedResult); QCOMPARE(join(input, separator), expectedResult); } void TestTools::stringutils_join_data() { QTest::addColumn>("input"); QTest::addColumn("separator"); QTest::addColumn("expectedResult"); QTest::newRow("data1") << std::vector() << std::string() << std::string(); QTest::newRow("data2") << std::vector() << std::string("separator") << std::string(); QTest::newRow("data3") << std::vector({"one"}) << std::string("separator") << std::string("one"); QTest::newRow("data4") << std::vector({"one"}) << std::string("separator") << std::string("one"); QTest::newRow("data5") << std::vector({"a", "b"}) << std::string(" ") << std::string("a b"); QTest::newRow("data6") << std::vector({"a", "b", "c"}) << std::string(" ") << std::string("a b c"); } void TestTools::stringutils_join_empty() { std::vector list; std::string string = join(list, std::string()); QVERIFY(string.empty()); } void TestTools::stringutils_join_char() { QFETCH(std::vector, input); QFETCH(char, separator); QFETCH(std::string, expectedResult); QCOMPARE(join(input, separator), expectedResult); } void TestTools::stringutils_join_char_data() { QTest::addColumn>("input"); QTest::addColumn("separator"); QTest::addColumn("expectedResult"); QTest::newRow("data1") << std::vector() << ' ' << std::string(); QTest::newRow("data5") << std::vector({"a", "b"}) << ' ' << std::string("a b"); QTest::newRow("data6") << std::vector({"a", "b", "c"}) << ' ' << std::string("a b c"); } void TestTools::stringutils_startsWith() { std::string a; a = "AB"; QVERIFY( startsWith(a, "A") ); QVERIFY( startsWith(a, "AB") ); QVERIFY( !startsWith(a, "C") ); QVERIFY( !startsWith(a, "ABCDEF") ); QVERIFY( startsWith(a, "") ); QVERIFY( startsWith(a, 'A') ); QVERIFY( !startsWith(a, 'C') ); QVERIFY( !startsWith(a, char()) ); QVERIFY( startsWith(a, "A") ); QVERIFY( startsWith(a, "AB") ); QVERIFY( !startsWith(a, "C") ); QVERIFY( !startsWith(a, "ABCDEF") ); QVERIFY( startsWith(a, "") ); a = ""; QVERIFY( startsWith(a, "") ); QVERIFY( !startsWith(a, "ABC") ); QVERIFY( startsWith(a, "") ); QVERIFY( !startsWith(a, "ABC") ); QVERIFY( !startsWith(a, 'x') ); QVERIFY( !startsWith(a, char()) ); a = std::string(); QVERIFY( startsWith(a, "") ); // different from QString::startsWith QVERIFY( !startsWith(a, "ABC") ); QVERIFY( !startsWith(a, 'x') ); QVERIFY( !startsWith(a, char()) ); a = u8"\xc3\xa9"; QVERIFY( startsWith(a, u8"\xc3\xa9") ); QVERIFY( !startsWith(a, u8"\xc3\xa1") ); } void TestTools::stringutils_endsWith() { std::string a; a = "AB"; QVERIFY( endsWith(a, "B") ); QVERIFY( endsWith(a, "AB") ); QVERIFY( !endsWith(a, "C") ); QVERIFY( !endsWith(a, "ABCDEF") ); QVERIFY( endsWith(a, "") ); QVERIFY( endsWith(a, 'B') ); QVERIFY( !endsWith(a, 'C') ); QVERIFY( !endsWith(a, char()) ); QVERIFY( endsWith(a, "B") ); QVERIFY( endsWith(a, "AB") ); QVERIFY( !endsWith(a, "C") ); QVERIFY( !endsWith(a, "ABCDEF") ); QVERIFY( endsWith(a, "") ); a = ""; QVERIFY( endsWith(a, "") ); QVERIFY( !endsWith(a, "ABC") ); QVERIFY( !endsWith(a, 'x') ); QVERIFY( !endsWith(a, char()) ); QVERIFY( endsWith(a, "") ); QVERIFY( !endsWith(a, "ABC") ); a = std::string(); QVERIFY( endsWith(a, "") ); // different from QString::endsWith QVERIFY( !endsWith(a, "ABC") ); QVERIFY( !endsWith(a, 'x') ); QVERIFY( !endsWith(a, char()) ); a = u8"\xc3\xa9"; QVERIFY( endsWith(a, u8"\xc3\xa9") ); QVERIFY( !endsWith(a, u8"\xc3\xa1") ); } void TestTools::stringutils_trimmed() { std::string a; a = "Text"; QCOMPARE(a, std::string("Text")); QCOMPARE(trimmed(a), std::string("Text")); QCOMPARE(a, std::string("Text")); a = " "; QCOMPARE(trimmed(a), std::string("")); QCOMPARE(a, std::string(" ")); a = " a "; QCOMPARE(trimmed(a), std::string("a")); a = "Text"; QCOMPARE(trimmed(std::move(a)), std::string("Text")); a = " "; QCOMPARE(trimmed(std::move(a)), std::string("")); a = " a "; QCOMPARE(trimmed(std::move(a)), std::string("a")); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); const SettingsPtr s = settings(); TestTools tt(s.get()); return QTest::qExec(&tt, argc, argv); } qbs-src-1.13.1/tests/auto/tools/tst_tools.h000066400000000000000000000066131347155106100206350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include QT_BEGIN_NAMESPACE class QTemporaryDir; QT_END_NAMESPACE namespace qbs { class Settings; } class TestTools : public QObject { Q_OBJECT public: TestTools(qbs::Settings *settings); ~TestTools(); public slots: virtual void initTestCase(); private slots: void fileSaver(); void fileCaseCheck(); void testBuildConfigMerging(); void testFileInfo(); void testProcessNameByPid(); void testProfiles(); void testSettingsMigration(); void testSettingsMigration_data(); void set_operator_eq(); void set_swap(); void set_size(); void set_capacity(); void set_reserve(); void set_clear(); void set_remove(); void set_contains(); void set_containsSet(); void set_begin(); void set_end(); void set_insert(); void set_reverseIterators(); void set_stlIterator(); void set_stlMutableIterator(); void set_setOperations(); void set_makeSureTheComfortFunctionsCompile(); void set_initializerList(); void set_intersects(); void stringutils_join(); void stringutils_join_data(); void stringutils_join_empty(); void stringutils_join_char(); void stringutils_join_char_data(); void stringutils_startsWith(); void stringutils_endsWith(); void stringutils_trimmed(); private: QString setupSettingsDir1(); QString setupSettingsDir2(); QString setupSettingsDir3(); qbs::Settings * const m_settings; QList m_tmpDirs; const QString testDataDir; }; qbs-src-1.13.1/tests/benchmarker/000077500000000000000000000000001347155106100165755ustar00rootroot00000000000000qbs-src-1.13.1/tests/benchmarker/activities.h000066400000000000000000000030761347155106100211200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_ACTIVITY_H #define QBS_BENCHMARKER_ACTIVITY_H #include namespace qbsBenchmarker { enum Activity { ActivityResolving = 1, ActivityRuleExecution = 2, ActivityNullBuild = 4 }; Q_DECLARE_FLAGS(Activities, Activity) Q_DECLARE_OPERATORS_FOR_FLAGS(Activities) } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.13.1/tests/benchmarker/benchmarker-main.cpp000066400000000000000000000117171347155106100225130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "benchmarker.h" #include "commandlineparser.h" #include "exception.h" #include #include #include using namespace qbsBenchmarker; static bool hasRegression = false; static int relativeChange(qint64 oldVal, qint64 newVal) { return newVal == 0 ? 0 : newVal * 100 / oldVal - 100; } static QByteArray relativeChangeString(int change) { QByteArray changeString = QByteArray::number(change); changeString += " %"; if (change > 0) changeString.prepend('+'); return changeString; } static void printResults(Activity activity, const BenchmarkResults &results, int regressionThreshold) { std::cout << "========== Performance data for "; switch (activity) { case ActivityResolving: std::cout << "Resolving"; break; case ActivityRuleExecution: std::cout << "Rule Execution"; break; case ActivityNullBuild: std::cout << "Null Build"; break; } std::cout << " ==========" << std::endl; const BenchmarkResult result = results.value(activity); const char * const indent = " "; std::cout << indent << "Old instruction count: " << result.oldInstructionCount << std::endl; std::cout << indent << "New instruction count: " << result.newInstructionCount << std::endl; int change = relativeChange(result.oldInstructionCount, result.newInstructionCount); if (change > regressionThreshold) hasRegression = true; std::cout << indent << "Relative change: " << relativeChangeString(change).constData() << std::endl; std::cout << indent << "Old peak memory usage: " << result.oldPeakMemoryUsage << " Bytes" << std::endl; std::cout << indent << "New peak memory usage: " << result.newPeakMemoryUsage << " Bytes" << std::endl; change = relativeChange(result.oldPeakMemoryUsage, result.newPeakMemoryUsage); if (change > regressionThreshold) hasRegression = true; std::cout << indent << "Relative change: " << relativeChangeString(change).constData() << std::endl; } static void printResults(Activities activities, const BenchmarkResults &results, int regressionThreshold) { if (activities & ActivityResolving) printResults(ActivityResolving, results, regressionThreshold); if (activities & ActivityRuleExecution) printResults(ActivityRuleExecution, results, regressionThreshold); if (activities & ActivityNullBuild) printResults(ActivityNullBuild, results, regressionThreshold); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); CommandLineParser clParser; try { clParser.parse(); } catch (const Exception &e) { std::cerr << qPrintable(e.description()) << std::endl; return EXIT_FAILURE; } Benchmarker benchmarker(clParser.activies(), clParser.oldCommit(), clParser.newCommit(), clParser.testProjectFilePath(), clParser.qbsRepoDirPath()); try { benchmarker.benchmark(); printResults(clParser.activies(), benchmarker.results(), clParser.regressionThreshold()); if (hasRegression) { benchmarker.keepRawData(); std::cout << "Performance regression detected. Raw benchmarking data available " "under " << qPrintable(benchmarker.rawDataBaseDir()) << '.' << std::endl; } } catch (const Exception &e) { benchmarker.keepRawData(); std::cerr << qPrintable(e.description()) << std::endl; std::cerr << "Build data available under " << qPrintable(benchmarker.rawDataBaseDir()) << '.' << std::endl; return EXIT_FAILURE; } } qbs-src-1.13.1/tests/benchmarker/benchmarker.cpp000066400000000000000000000121571347155106100215700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "benchmarker.h" #include "exception.h" #include "runsupport.h" #include "valgrindrunner.h" #include #include namespace qbsBenchmarker { Benchmarker::Benchmarker(Activities activities, const QString &oldCommit, const QString &newCommit, const QString &testProject, const QString &qbsRepo) : m_activities(activities) , m_oldCommit(oldCommit) , m_newCommit(newCommit) , m_testProject(testProject) , m_qbsRepo(qbsRepo) { } Benchmarker::~Benchmarker() { if (!m_commitToRestore.isEmpty()) { try { runProcess(QStringList() << "git" << "checkout" << m_commitToRestore, m_qbsRepo); } catch (const Exception &e) { qDebug("Failed to restore original commit %s: %s", qPrintable(m_commitToRestore), qPrintable(e.description())); } } } void Benchmarker::benchmark() { rememberCurrentRepoState(); runProcess(QStringList() << "git" << "checkout" << m_oldCommit, m_qbsRepo); const QString oldQbsBuildDir = m_baseOutputDir.path() + "/qbs-build." + m_oldCommit; std::cout << "Building from old repo state..." << std::endl; buildQbs(oldQbsBuildDir); runProcess(QStringList() << "git" << "checkout" << m_newCommit, m_qbsRepo); const QString newQbsBuildDir = m_baseOutputDir.path() + "/qbs-build." + m_newCommit; std::cout << "Building from new repo state..." << std::endl; buildQbs(newQbsBuildDir); std::cout << "Now running valgrind. This can take a while." << std::endl; ValgrindRunner oldDataRetriever(m_activities, m_testProject, oldQbsBuildDir, m_baseOutputDir.path() + "/benchmark-data." + m_oldCommit); ValgrindRunner newDataRetriever(m_activities, m_testProject, newQbsBuildDir, m_baseOutputDir.path() + "/benchmark-data." + m_newCommit); QFuture oldFuture = QtConcurrent::run(&oldDataRetriever, &ValgrindRunner::run); QFuture newFuture = QtConcurrent::run(&newDataRetriever, &ValgrindRunner::run); oldFuture.waitForFinished(); const auto oldValgrindResults = oldDataRetriever.results(); for (const ValgrindResult &valgrindResult : oldValgrindResults) { BenchmarkResult &benchmarkResult = m_results[valgrindResult.activity]; benchmarkResult.oldInstructionCount = valgrindResult.instructionCount; benchmarkResult.oldPeakMemoryUsage = valgrindResult.peakMemoryUsage; } newFuture.waitForFinished(); const auto newValgrindResults = newDataRetriever.results(); for (const ValgrindResult &valgrindResult : newValgrindResults) { BenchmarkResult &benchmarkResult = m_results[valgrindResult.activity]; benchmarkResult.newInstructionCount = valgrindResult.instructionCount; benchmarkResult.newPeakMemoryUsage = valgrindResult.peakMemoryUsage; } std::cout << "Done!" << std::endl; } void Benchmarker::rememberCurrentRepoState() { QByteArray commit; int exitCode = 0; try { runProcess(QStringList() << "git" << "symbolic-ref" << "--short" << "HEAD", m_qbsRepo, &commit, &exitCode); } catch (const Exception &) { if (exitCode == 0) { // runProcess did not throw because of the exit code. throw; } // Fallback, in case git cannot retrieve a nice symbolic name. runProcess(QStringList() << "git" << "describe" << "HEAD", m_qbsRepo, &commit); } m_commitToRestore = QString::fromLatin1(commit); } void Benchmarker::buildQbs(const QString &buildDir) const { if (!QDir::root().mkpath(buildDir)) throw Exception(QStringLiteral("Failed to create directory '%1'.").arg(buildDir)); runProcess(QStringList() << "qmake" << "CONFIG+=force_debug_info" << (m_qbsRepo + "/qbs.pro"), buildDir); runProcess(QStringList() << "make" << "-s", buildDir); } } // namespace qbsBenchmarker qbs-src-1.13.1/tests/benchmarker/benchmarker.h000066400000000000000000000050241347155106100212300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_BENCHMARKER_H #define QBS_BENCHMARKER_BENCHMARKER_H #include "activities.h" #include #include #include QT_BEGIN_NAMESPACE class QStringList; QT_END_NAMESPACE namespace qbsBenchmarker { class BenchmarkResult { public: qint64 oldInstructionCount; qint64 newInstructionCount; qint64 oldPeakMemoryUsage; qint64 newPeakMemoryUsage; }; using BenchmarkResults = QHash; class Benchmarker { public: Benchmarker(Activities activities, const QString &oldCommit, const QString &newCommit, const QString &testProject, const QString &qbsRepo); ~Benchmarker(); void benchmark(); void keepRawData() { m_baseOutputDir.setAutoRemove(false ); } BenchmarkResults results() const { return m_results; } QString rawDataBaseDir() const { return m_baseOutputDir.path(); } private: void rememberCurrentRepoState(); void buildQbs(const QString &buildDir) const; const Activities m_activities; const QString m_oldCommit; const QString m_newCommit; const QString m_testProject; const QString m_qbsRepo; QString m_commitToRestore; QTemporaryDir m_baseOutputDir; BenchmarkResults m_results; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.13.1/tests/benchmarker/benchmarker.pro000066400000000000000000000006021347155106100215760ustar00rootroot00000000000000TARGET = qbs_benchmarker DESTDIR = ../../bin CONFIG += console CONFIG -= app_bundle CONFIG += c++14 QT += concurrent SOURCES = \ benchmarker-main.cpp \ benchmarker.cpp \ commandlineparser.cpp \ runsupport.cpp \ valgrindrunner.cpp HEADERS = \ activities.h \ benchmarker.h \ commandlineparser.h \ exception.h \ runsupport.h \ valgrindrunner.h qbs-src-1.13.1/tests/benchmarker/benchmarker.qbs000066400000000000000000000013611347155106100215660ustar00rootroot00000000000000import qbs QtApplication { name: "qbs_benchmarker" type: "application" consoleApplication: true cpp.cxxLanguageVersion: "c++14" condition: Qt.concurrent.present Depends { name: "qbsbuildconfig" } Depends { name: "Qt.concurrent" required: false } files: [ "activities.h", "benchmarker-main.cpp", "benchmarker.cpp", "benchmarker.h", "commandlineparser.cpp", "commandlineparser.h", "exception.h", "runsupport.cpp", "runsupport.h", "valgrindrunner.cpp", "valgrindrunner.h", ] Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: qbsbuildconfig.appInstallDir } } qbs-src-1.13.1/tests/benchmarker/commandlineparser.cpp000066400000000000000000000137421347155106100230130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include "exception.h" #include #include #include #include namespace qbsBenchmarker { static QString resolveActivity() { return "resolving"; } static QString ruleExecutionActivity() { return "rule-execution"; } static QString nullBuildActivity() { return "null-build"; } static QString allActivities() { return "all"; } CommandLineParser::CommandLineParser() { } void CommandLineParser::parse() { QCommandLineParser parser; parser.setApplicationDescription("This tool aims to detect qbs performance regressions " "using valgrind."); parser.addHelpOption(); QCommandLineOption oldCommitOption(QStringList{"old-commit", "o"}, "The old qbs commit.", "old commit"); parser.addOption(oldCommitOption); QCommandLineOption newCommitOption(QStringList{"new-commit", "n"}, "The new qbs commit.", "new commit"); parser.addOption(newCommitOption); QCommandLineOption testProjectOption(QStringList{"test-project", "p"}, "The example project to use for the benchmark.", "project file path"); parser.addOption(testProjectOption); QCommandLineOption qbsRepoOption(QStringList{"qbs-repo", "r"}, "The qbs repository.", "repo path"); parser.addOption(qbsRepoOption); QCommandLineOption activitiesOption(QStringList{"activities", "a"}, QStringLiteral("The activities to benchmark. Possible values (CSV): %1,%2,%3,%4") .arg(resolveActivity(), ruleExecutionActivity(), nullBuildActivity(), allActivities()), "activities", allActivities()); parser.addOption(activitiesOption); QCommandLineOption thresholdOption(QStringList{"regression-threshold", "t"}, "A relative increase higher than this is considered a performance regression. " "All temporary data from running the benchmarks will be kept if that happens.", "value in per cent"); parser.addOption(thresholdOption); parser.process(*QCoreApplication::instance()); const QList mandatoryOptions = QList() << oldCommitOption << newCommitOption << testProjectOption << qbsRepoOption; for (const QCommandLineOption &o : mandatoryOptions) { if (!parser.isSet(o)) throwException(o.names().constFirst(), parser.helpText()); if (parser.value(o).isEmpty()) throwException(o.names().constFirst(), QString(), parser.helpText()); } m_oldCommit = parser.value(oldCommitOption); m_newCommit = parser.value(newCommitOption); m_testProjectFilePath = parser.value(testProjectOption); m_qbsRepoDirPath = parser.value(qbsRepoOption); const QStringList activitiesList = parser.value(activitiesOption).split(','); m_activities = 0; for (const QString &activityString : activitiesList) { if (activityString == allActivities()) { m_activities = ActivityResolving | ActivityRuleExecution | ActivityNullBuild; break; } else if (activityString == resolveActivity()) { m_activities = ActivityResolving; } else if (activityString == ruleExecutionActivity()) { m_activities |= ActivityRuleExecution; } else if (activityString == nullBuildActivity()) { m_activities |= ActivityNullBuild; } else { throwException(activitiesOption.names().constFirst(), activityString, parser.helpText()); } } m_regressionThreshold = 5; if (parser.isSet(thresholdOption)) { bool ok = true; const QString rawThresholdValue = parser.value(thresholdOption); m_regressionThreshold = rawThresholdValue.toInt(&ok); if (!ok) throwException(thresholdOption.names().constFirst(), rawThresholdValue, parser.helpText()); } } void CommandLineParser::throwException(const QString &optionName, const QString &illegalValue, const QString &helpText) { const QString errorText(QStringLiteral("Error parsing command line: Illegal value '%1' " "for option '--%2'.\n%3").arg(illegalValue, optionName, helpText)); throw Exception(errorText); } void CommandLineParser::throwException(const QString &missingOption, const QString &helpText) { const QString errorText(QStringLiteral("Error parsing command line: Missing mandatory " "option '--%1'.\n%3").arg(missingOption, helpText)); throw Exception(errorText); } } // namespace qbsBenchmarker qbs-src-1.13.1/tests/benchmarker/commandlineparser.h000066400000000000000000000044721347155106100224600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_COMMANDLINEPARSER_H #define QBS_BENCHMARKER_COMMANDLINEPARSER_H #include "activities.h" #include namespace qbsBenchmarker { class CommandLineParser { public: CommandLineParser(); void parse(); Activities activies() const { return m_activities; } QString oldCommit() const { return m_oldCommit; } QString newCommit() const { return m_newCommit; } QString testProjectFilePath() const { return m_testProjectFilePath; } QString qbsRepoDirPath() const { return m_qbsRepoDirPath; } int regressionThreshold() const { return m_regressionThreshold; } private: [[noreturn]] void throwException(const QString &optionName, const QString &illegalValue, const QString &helpText); [[noreturn]] void throwException(const QString &missingOption, const QString &helpText); Activities m_activities; QString m_oldCommit; QString m_newCommit; QString m_testProjectFilePath; QString m_qbsRepoDirPath; int m_regressionThreshold; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.13.1/tests/benchmarker/exception.h000066400000000000000000000034351347155106100207510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_EXCEPTION_H #define QBS_BENCHMARKER_EXCEPTION_H #include #include namespace qbsBenchmarker { class Exception : public QException { public: explicit Exception(const QString &description) : m_description(description) {} ~Exception() throw() { } QString description() const { return m_description; } private: void raise() const { throw *this; } Exception *clone() const { return new Exception(*this); } QString m_description; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.13.1/tests/benchmarker/runsupport.cpp000066400000000000000000000052101347155106100215400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "runsupport.h" #include "exception.h" #include #include #include #include namespace qbsBenchmarker { void runProcess(const QStringList &commandLine, const QString &workingDir, QByteArray *output, int *exitCode) { QStringList args = commandLine; const QString command = args.takeFirst(); QProcess p; if (!workingDir.isEmpty()) p.setWorkingDirectory(workingDir); p.start(command, args); if (!p.waitForStarted()) throw Exception(QStringLiteral("Process '%1' failed to start.").arg(command)); p.waitForFinished(-1); if (p.exitStatus() != QProcess::NormalExit) { throw Exception(QStringLiteral("Error running '%1': %2") .arg(command, p.errorString())); } if (exitCode) *exitCode = p.exitCode(); if (p.exitCode() != 0) { QString errorString = QStringLiteral("Command '%1' finished with exit code %2.") .arg(command).arg(p.exitCode()); const QByteArray stdErr = p.readAllStandardError(); if (!stdErr.isEmpty()) { errorString += QStringLiteral("\nStandard error output was: '%1'") .arg(QString::fromLocal8Bit(stdErr)); } throw Exception(errorString); } if (output) *output = p.readAllStandardOutput().trimmed(); } } // namespace qbsBenchmarker qbs-src-1.13.1/tests/benchmarker/runsupport.h000066400000000000000000000032351347155106100212120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_RUNSUPPORT_H #define QBS_BENCHMARKER_RUNSUPPORT_H #include #include QT_BEGIN_NAMESPACE class QByteArray; class QStringList; QT_END_NAMESPACE namespace qbsBenchmarker { void runProcess(const QStringList &commandLine, const QString& workingDir = QString(), QByteArray *output = nullptr, int *exitCode = nullptr); } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.13.1/tests/benchmarker/valgrindrunner.cpp000066400000000000000000000241321347155106100223430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "valgrindrunner.h" #include "exception.h" #include "runsupport.h" #include #include #include #include #include #include #include #include namespace qbsBenchmarker { ValgrindRunner::ValgrindRunner(Activities activities, const QString &testProject, const QString &qbsBuildDir, const QString &baseOutputDir) : m_activities(activities) , m_testProject(testProject) , m_qbsBinary(qbsBuildDir + "/bin/qbs") , m_baseOutputDir(baseOutputDir) { if (!QDir::root().mkpath(m_baseOutputDir)) throw Exception(QStringLiteral("Failed to create directory '%1'.").arg(baseOutputDir)); } void ValgrindRunner::run() { QList> futures; if (m_activities & ActivityResolving) futures.push_back(QtConcurrent::run(this, &ValgrindRunner::traceResolving)); if (m_activities & ActivityRuleExecution) futures.push_back(QtConcurrent::run(this, &ValgrindRunner::traceRuleExecution)); if (m_activities & ActivityNullBuild) futures.push_back(QtConcurrent::run(this, &ValgrindRunner::traceNullBuild)); while (!futures.empty()) futures.takeFirst().waitForFinished(); } void ValgrindRunner::traceResolving() { const QString buildDirCallgrind = m_baseOutputDir + "/build-dir.resolving.callgrind"; const QString buildDirMassif = m_baseOutputDir + "/build-dir.resolving.massif"; traceActivity(ActivityResolving, buildDirCallgrind, buildDirMassif); } void ValgrindRunner::traceRuleExecution() { const QString buildDirCallgrind = m_baseOutputDir + "/build-dir.rule-execution.callgrind"; const QString buildDirMassif = m_baseOutputDir + "/build-dir.rule-execution.massif"; runProcess(qbsCommandLine("resolve", buildDirCallgrind, false)); runProcess(qbsCommandLine("resolve", buildDirMassif, false)); traceActivity(ActivityRuleExecution, buildDirCallgrind, buildDirMassif); } void ValgrindRunner::traceNullBuild() { const QString buildDirCallgrind = m_baseOutputDir + "/build-dir.null-build.callgrind"; const QString buildDirMassif = m_baseOutputDir + "/build-dir.null-build.massif"; runProcess(qbsCommandLine("build", buildDirCallgrind, false)); runProcess(qbsCommandLine("build", buildDirMassif, false)); traceActivity(ActivityNullBuild, buildDirCallgrind, buildDirMassif); } void ValgrindRunner::traceActivity(Activity activity, const QString &buildDirCallgrind, const QString &buildDirMassif) { QString activityString; QString qbsCommand; bool dryRun; switch (activity) { case ActivityResolving: activityString = "resolving"; qbsCommand = "resolve"; dryRun = false; break; case ActivityRuleExecution: activityString = "rule-execution"; qbsCommand = "build"; dryRun = true; break; case ActivityNullBuild: activityString = "null-build"; qbsCommand = "build"; dryRun = false; break; } const QString outFileCallgrind = m_baseOutputDir + "/outfile." + activityString + ".callgrind"; const QString outFileMassif = m_baseOutputDir + "/outfile." + activityString + ".massif"; QFuture callGrindFuture = QtConcurrent::run(this, &ValgrindRunner::runCallgrind, qbsCommand, buildDirCallgrind, dryRun, outFileCallgrind); QFuture massifFuture = QtConcurrent::run(this, &ValgrindRunner::runMassif, qbsCommand, buildDirMassif, dryRun, outFileMassif); callGrindFuture.waitForFinished(); massifFuture.waitForFinished(); addToResults(ValgrindResult(activity, callGrindFuture.result(), massifFuture.result())); } QStringList ValgrindRunner::qbsCommandLine(const QString &command, const QString &buildDir, bool dryRun) const { QStringList commandLine = QStringList() << m_qbsBinary << command << "-qq" << "-d" << buildDir << "-f" << m_testProject; if (dryRun) commandLine << "--dry-run"; return commandLine; } QStringList ValgrindRunner::wrapForValgrind(const QStringList &commandLine, const QString &tool, const QString &outFile) const { return QStringList() << "valgrind" << "--smc-check=all" << "--trace-children=yes" << ("--tool=" + tool) << ("--" + tool + "-out-file=" + outFile) << commandLine; } QStringList ValgrindRunner::valgrindCommandLine(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &tool, const QString &outFile) const { return wrapForValgrind(qbsCommandLine(qbsCommand, buildDir, dryRun), tool, outFile); } void ValgrindRunner::addToResults(const ValgrindResult &result) { std::lock_guard locker(m_resultsMutex); m_results.push_back(result); } qint64 ValgrindRunner::runCallgrind(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile) { runProcess(valgrindCommandLine(qbsCommand, buildDir, dryRun, "callgrind", outFile)); QFile f(outFile); if (!f.open(QIODevice::ReadOnly)) { throw Exception(QStringLiteral("Failed to open file '%1': %2") .arg(outFile, f.errorString())); } while (!f.atEnd()) { const QByteArray line = f.readLine().trimmed(); static const QByteArray magicString = "summary: "; if (!line.startsWith(magicString)) continue; const QByteArray icString = line.mid(magicString.size()); bool ok; const qint64 iCount = icString.toLongLong(&ok); if (!ok) { throw Exception(QStringLiteral("Unexpected line in callgrind output file " "'%1': '%2'.") .arg(outFile, QString::fromLocal8Bit(line))); } return iCount; } throw Exception(QStringLiteral("Failed to find summary line in callgrind " "output file '%1'.").arg(outFile)); } qint64 ValgrindRunner::runMassif(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile) { runProcess(valgrindCommandLine(qbsCommand, buildDir, dryRun, "massif", outFile)); QByteArray ms_printOutput; runProcess(QStringList() << "ms_print" << outFile, QString(), &ms_printOutput); QBuffer buffer(&ms_printOutput); buffer.open(QIODevice::ReadOnly); QByteArray peakSnapshot; const QString exceptionStringPattern = QStringLiteral("Failed to extract peak memory " "usage from file '%1': %2").arg(outFile); while (!buffer.atEnd()) { const QByteArray line = buffer.readLine(); static const QByteArray magicString = " (peak)"; const int magicStringOffset = line.indexOf(magicString); if (magicStringOffset == -1) continue; int delimiterOffset = line.lastIndexOf(',', magicStringOffset); if (delimiterOffset == -1) delimiterOffset = line.lastIndexOf('[', magicStringOffset); if (delimiterOffset == -1) { const QString details = QStringLiteral("Failed to extract peak snapshot from " "line '%1'.").arg(QString::fromLocal8Bit(line)); throw Exception(exceptionStringPattern.arg(details)); } peakSnapshot = line.mid(delimiterOffset + 1, magicStringOffset - delimiterOffset).trimmed(); break; } if (peakSnapshot.isEmpty()) throw Exception(exceptionStringPattern.arg("No peak marker found")); while (!buffer.atEnd()) { const QByteArray line = buffer.readLine().simplified(); if (!line.startsWith(peakSnapshot + ' ')) continue; const QList entries = line.split(' '); if (entries.size() != 6) { const QString details = QStringLiteral("Expected 6 entries in line '%1', but " "there are %2.").arg(QString::fromLocal8Bit(line)).arg(entries.size()); throw Exception(exceptionStringPattern.arg(details)); } QByteArray peakMemoryString = entries.at(2); peakMemoryString.replace(',', QByteArray()); bool ok; qint64 peakMemoryUsage = peakMemoryString.toLongLong(&ok); if (!ok) { const QString details = QStringLiteral("Failed to parse peak memory value '%1' " "as a number.").arg(QString::fromLocal8Bit(peakMemoryString)); throw Exception(exceptionStringPattern.arg(details)); } return peakMemoryUsage; } const QString details = QStringLiteral("Failed to find snapshot '%1'.") .arg(QString::fromLocal8Bit(peakSnapshot)); throw Exception(exceptionStringPattern.arg(details)); } } // namespace qbsBenchmarker qbs-src-1.13.1/tests/benchmarker/valgrindrunner.h000066400000000000000000000062451347155106100220150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_BENCHMARKRUNNER_H #define QBS_BENCHMARKER_BENCHMARKRUNNER_H #include "activities.h" #include #include #include QT_BEGIN_NAMESPACE class QStringList; QT_END_NAMESPACE namespace qbsBenchmarker { class ValgrindResult { public: ValgrindResult(Activity a, qint64 ic, qint64 mem) : activity(a), instructionCount(ic), peakMemoryUsage(mem) {} Activity activity; qint64 instructionCount; qint64 peakMemoryUsage; }; class ValgrindRunner { public: ValgrindRunner(Activities activities, const QString &testProject, const QString &qbsBuildDir, const QString &baseOutputDir); void run(); QList results() const { return m_results; } private: void traceResolving(); void traceRuleExecution(); void traceNullBuild(); void traceActivity(Activity activity, const QString &buildDirCallgrind, const QString &buildDirMassif); QStringList qbsCommandLine(const QString &command, const QString &buildDir, bool dryRun) const; QStringList wrapForValgrind(const QStringList &commandLine, const QString &tool, const QString &outFile) const; QStringList valgrindCommandLine(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &tool, const QString &outFile) const; void addToResults(const ValgrindResult &results); qint64 runCallgrind(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile); qint64 runMassif(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile); const Activities m_activities; const QString m_testProject; const QString m_qbsBinary; const QString m_baseOutputDir; QList m_results; std::mutex m_resultsMutex; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.13.1/tests/fuzzy-test/000077500000000000000000000000001347155106100164605ustar00rootroot00000000000000qbs-src-1.13.1/tests/fuzzy-test/commandlineparser.cpp000066400000000000000000000114131347155106100226670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include #include static QString profileOption() { return "--profile"; } static QString startCommitOption() { return "--start-commit"; } static QString maxDurationoption() { return "--max-duration"; } static QString jobCountOption() { return "--jobs"; } static QString logOption() { return "--log"; } CommandLineParser::CommandLineParser() { } void CommandLineParser::parse(const QStringList &commandLine) { m_profile.clear(); m_startCommit.clear(); m_maxDuration = 0; m_jobCount = 0; m_log = false; m_commandLine = commandLine; Q_ASSERT(!m_commandLine.empty()); m_command = m_commandLine.takeFirst(); while (!m_commandLine.empty()) { const QString arg = m_commandLine.takeFirst(); if (arg == profileOption()) assignOptionArgument(arg, m_profile); else if (arg == startCommitOption()) assignOptionArgument(arg, m_startCommit); else if (arg == jobCountOption()) assignOptionArgument(arg, m_jobCount); else if (arg == maxDurationoption()) parseDuration(); else if (arg == logOption()) m_log = true; else throw ParseException(QStringLiteral("Unknown parameter '%1'").arg(arg)); } if (m_profile.isEmpty()) throw ParseException("No profile given."); if (m_startCommit.isEmpty()) throw ParseException("No start commit given."); } QString CommandLineParser::usageString() const { return QStringLiteral("%1 %2 %3 [%4 ] " "[%5 ] [%6]") .arg(QFileInfo(m_command).fileName(), profileOption(), startCommitOption(), maxDurationoption(), jobCountOption(), logOption()); } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.empty()) throw ParseException(QStringLiteral("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) { throw ParseException(QStringLiteral("Argument for option '%1' must not be empty.") .arg(option)); } } void CommandLineParser::assignOptionArgument(const QString &option, int &argument) { QString numberString; assignOptionArgument(option, numberString); bool ok; argument = numberString.toInt(&ok); if (!ok || argument <= 0) { throw ParseException(QStringLiteral("Invalid argument '%1' for option '%2'.") .arg(numberString, option)); } } void CommandLineParser::parseDuration() { QString durationString; QString choppedDurationString; assignOptionArgument(maxDurationoption(), durationString); choppedDurationString = durationString; const char suffix = durationString.at(durationString.size() - 1).toLatin1(); const bool hasSuffix = !std::isdigit(suffix); if (hasSuffix) choppedDurationString.chop(1); bool ok; m_maxDuration = choppedDurationString.toInt(&ok); if (!ok || m_maxDuration <= 0) { throw ParseException(QStringLiteral("Invalid duration argument '%1'.") .arg(durationString)); } if (hasSuffix) { switch (suffix) { case 'm': break; case 'd': m_maxDuration *= 24; // Fall-through. case 'h': m_maxDuration *= 60; break; default: throw ParseException(QStringLiteral("Invalid duration suffix '%1'.") .arg(suffix)); } } } qbs-src-1.13.1/tests/fuzzy-test/commandlineparser.h000066400000000000000000000045701347155106100223420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_FUZZYTEST_COMMANDLINEPARSER_H #define QBS_FUZZYTEST_COMMANDLINEPARSER_H #include #include class ParseException : public std::exception { public: ParseException(const QString &error) : errorMessage(error) { } ~ParseException() throw() {} QString errorMessage; private: const char *what() const throw() { return qPrintable(errorMessage); } }; class CommandLineParser { public: CommandLineParser(); void parse(const QStringList &commandLine); QString profile() const { return m_profile; } QString startCommit() const { return m_startCommit; } int maxDurationInMinutes() const { return m_maxDuration; } int jobCount() const { return m_jobCount; } bool log() const { return m_log; } QString usageString() const; private: void assignOptionArgument(const QString &option, QString &argument); void assignOptionArgument(const QString &option, int &argument); void parseDuration(); QStringList m_commandLine; QString m_command; QString m_profile; QString m_startCommit; int m_maxDuration; int m_jobCount; bool m_log; }; #endif // Include guard. qbs-src-1.13.1/tests/fuzzy-test/fuzzy-test.pro000066400000000000000000000003221347155106100213430ustar00rootroot00000000000000TARGET = qbs_fuzzy-test DESTDIR = ../../bin CONFIG += console CONFIG -= app_bundle SOURCES = main.cpp \ commandlineparser.cpp \ fuzzytester.cpp HEADERS += \ commandlineparser.h \ fuzzytester.h qbs-src-1.13.1/tests/fuzzy-test/fuzzy-test.qbs000066400000000000000000000007321347155106100213350ustar00rootroot00000000000000import qbs QtApplication { name: "qbs_fuzzy-test" type: "application" consoleApplication: true Depends { name: "qbsbuildconfig" } cpp.cxxLanguageVersion: "c++14" files: [ "commandlineparser.cpp", "commandlineparser.h", "fuzzytester.cpp", "fuzzytester.h", "main.cpp", ] Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: qbsbuildconfig.appInstallDir } } qbs-src-1.13.1/tests/fuzzy-test/fuzzytester.cpp000066400000000000000000000274451347155106100216160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "fuzzytester.h" #include #include #include #include #include #include #include #include static QString resolveIncrementalActivity() { return "resolve-incremental"; } static QString buildIncrementalActivity() { return "build-incremental"; } static QString buildFromScratchActivity() { return "build-from-scratch"; } FuzzyTester::FuzzyTester() { loadSettings(); } FuzzyTester::~FuzzyTester() { storeSettings(); } void FuzzyTester::runTest(const QString &profile, const QString &startCommit, int maxDurationInMinutes, int jobCount, bool log) { m_profile = profile; m_jobCount = jobCount; m_log = log; runGit(QStringList() << "rev-parse" << "HEAD", &m_headCommit); qDebug("HEAD is %s", qPrintable(m_headCommit)); qDebug("Trying to find a buildable commit to start with..."); const QString workingStartCommit = findWorkingStartCommit(startCommit); qDebug("Found buildable start commit %s.", qPrintable(workingStartCommit)); QStringList allCommits = findAllCommits(workingStartCommit); qDebug("The test set comprises all %d commits between the start commit and HEAD.", allCommits.size()); // Shuffle the initial sequence. Otherwise all invocations of the tool with the same start // commit would try the same sequence of commits. std::srand(std::time(nullptr)); std::random_shuffle(allCommits.begin(), allCommits.end()); quint64 run = 0; QStringList buildSequence(workingStartCommit); QElapsedTimer timer; const qint64 maxDurationInMillis = maxDurationInMinutes * 60 * 1000; if (maxDurationInMillis != 0) timer.start(); bool timerHasExpired = false; while (std::next_permutation(allCommits.begin(), allCommits.end()) && !timerHasExpired) { qDebug("Testing permutation %llu...", ++run); const auto &allCommitsImmutable = allCommits; for (const QString ¤tCommit : allCommitsImmutable) { if (timer.isValid() && timer.hasExpired(maxDurationInMillis)) { timerHasExpired = true; break; } m_currentCommit = currentCommit; buildSequence << currentCommit; checkoutCommit(currentCommit); qDebug("Testing incremental build #%d (%s)", buildSequence.size() - 1, qPrintable(currentCommit)); // Doing "resolve" and "build" separately introduces additional possibilities // for errors, as information from change tracking has to be serialized correctly. QString qbsError; m_currentActivity = resolveIncrementalActivity(); bool success = runQbs(defaultBuildDir(), QStringLiteral("resolve"), &qbsError); if (success) { m_currentActivity = buildIncrementalActivity(); success = runQbs(defaultBuildDir(), QStringLiteral("build"), &qbsError); } m_currentActivity = buildFromScratchActivity(); if (success) { if (!doCleanBuild(&qbsError)) { QString message = "An incremental build succeeded " "with a commit for which a clean build failed."; if (!m_log) { message += QStringLiteral("\nThe qbs error message " "for the clean build was: '%1'").arg(qbsError); } throwIncrementalBuildError(message, buildSequence); } } else { qDebug("Incremental build failed. Checking whether clean build works..."); if (doCleanBuild()) { QString message = "An incremental build failed " "with a commit for which a clean build succeeded."; if (!m_log) { message += QStringLiteral("\nThe qbs error message for " "the incremental build was: '%1'").arg(qbsError); } throwIncrementalBuildError(message, buildSequence); } else { qDebug("Clean build also fails. Continuing."); } } } } if (timerHasExpired) qDebug("Maximum duration reached."); else qDebug("All possible permutations were tried."); } void FuzzyTester::checkoutCommit(const QString &commit) { runGit(QStringList() << "checkout" << commit); runGit(QStringList() << "submodule" << "update" << "--init"); } QStringList FuzzyTester::findAllCommits(const QString &startCommit) { QString allCommitsString; runGit(QStringList() << "log" << (startCommit + "~1.." + m_headCommit) << "--format=format:%h", &allCommitsString); return allCommitsString.simplified().split(QLatin1Char(' '), QString::SkipEmptyParts); } QString FuzzyTester::findWorkingStartCommit(const QString &startCommit) { const QStringList allCommits = findAllCommits(startCommit); QString qbsError; m_currentActivity = buildFromScratchActivity(); for (auto it = allCommits.crbegin(), end = allCommits.crend(); it != end; ++it) { m_currentCommit = *it; if (m_unbuildableCommits.contains(m_currentCommit)) { qDebug("Skipping known bad commit %s.", qPrintable(m_currentCommit)); continue; } checkoutCommit(m_currentCommit); removeDir(defaultBuildDir()); if (runQbs(defaultBuildDir(), QStringLiteral("build"), &qbsError)) { m_buildableCommits << m_currentCommit; return m_currentCommit; } qDebug("Commit %s is not buildable.", qPrintable(m_currentCommit)); m_unbuildableCommits << m_currentCommit; } throw TestError(QStringLiteral("Cannot run test: Failed to find a single commit that " "builds successfully with qbs. The last qbs error was: '%1'").arg(qbsError)); } void FuzzyTester::runGit(const QStringList &arguments, QString *output) { QProcess git; git.start("git", arguments); if (!git.waitForStarted()) throw TestError("Failed to start git. It is expected to be in the PATH."); if (!git.waitForFinished(300000) || git.exitStatus() != QProcess::NormalExit) // 5 minutes ought to be enough for everyone throw TestError(QStringLiteral("git failed: %1").arg(git.errorString())); if (git.exitCode() != 0) { throw TestError(QStringLiteral("git failed: %1") .arg(QString::fromLocal8Bit(git.readAllStandardError()))); } if (output) *output = QString::fromLocal8Bit(git.readAllStandardOutput()).trimmed(); } bool FuzzyTester::runQbs(const QString &buildDir, const QString &command, QString *errorOutput) { if (errorOutput) errorOutput->clear(); QProcess qbs; QStringList commandLine = QStringList(command) << "-d" << buildDir; if (m_log) { commandLine << "-vv"; const size_t maxLoggedCommits = 2; Q_ASSERT(m_commitsWithLogFiles.size() <= maxLoggedCommits + 1); if (m_commitsWithLogFiles.size() == maxLoggedCommits + 1) { static const QStringList allActivities = QStringList() << resolveIncrementalActivity() << buildIncrementalActivity() << buildFromScratchActivity(); const QString oldCommit = m_commitsWithLogFiles.front(); m_commitsWithLogFiles.pop(); for (const QString &a : allActivities) QFile::remove(logFilePath(oldCommit, a)); } qbs.setStandardErrorFile(logFilePath(m_currentCommit, m_currentActivity)); if (m_commitsWithLogFiles.empty() || m_commitsWithLogFiles.back() != m_currentCommit) m_commitsWithLogFiles.push(m_currentCommit); } else { commandLine << "-qq"; } if (m_jobCount != 0) commandLine << "--jobs" << QString::number(m_jobCount); commandLine << ("profile:" + m_profile); qbs.start("qbs", commandLine); if (!qbs.waitForStarted()) { throw TestError(QStringLiteral("Failed to start qbs. It is expected to be " "in the PATH. QProcess error string: '%1'").arg(qbs.errorString())); } if (!qbs.waitForFinished(-1) || qbs.exitCode() != 0) { if (errorOutput) *errorOutput = QString::fromLocal8Bit(qbs.readAllStandardError()); return false; } return true; } void FuzzyTester::removeDir(const QString &dirPath) { QDir dir(dirPath); if (!dir.removeRecursively()) { throw TestError(QStringLiteral("Failed to remove temporary dir '%1'.") .arg(dir.absolutePath())); } } bool FuzzyTester::doCleanBuild(QString *errorMessage) { if (m_unbuildableCommits.contains(m_currentCommit)) { qDebug("Commit is known not to be buildable, not running qbs."); return false; } if (m_buildableCommits.contains(m_currentCommit)) { qDebug("Commit is known to be buildable, not running qbs."); return true; } const QString cleanBuildDir = "fuzzytest-verification-build"; removeDir(cleanBuildDir); if (runQbs(cleanBuildDir, QStringLiteral("build"), errorMessage)) { m_buildableCommits << m_currentCommit; return true; } m_unbuildableCommits << m_currentCommit; return false; } void FuzzyTester::throwIncrementalBuildError(const QString &message, const QStringList &commitSequence) { const QString commitSequenceString = commitSequence.join(QLatin1Char(',')); throw TestError(QStringLiteral("Found qbs bug with incremental build!\n" "%1\n" "The sequence of commits was: %2.").arg(message, commitSequenceString)); } QString FuzzyTester::logFilePath(const QString &commit, const QString &activity) { return "log." + commit + '.' + activity; } QString FuzzyTester::defaultBuildDir() { return "fuzzytest-build"; } static QString organization() { return "QtProject"; } static QString app() { return "qbs-fuzzy-tester"; } static QString unbuildableCommitsKey() { return "unbuildable-commits"; } static QString buildableCommitsKey() { return "buildable-commits"; } void FuzzyTester::loadSettings() { QSettings s(organization(), app()); m_unbuildableCommits = s.value(unbuildableCommitsKey()).toStringList(); m_buildableCommits = s.value(buildableCommitsKey()).toStringList(); } void FuzzyTester::storeSettings() const { QSettings s(organization(), app()); s.setValue(unbuildableCommitsKey(), m_unbuildableCommits); s.setValue(buildableCommitsKey(), m_buildableCommits); } qbs-src-1.13.1/tests/fuzzy-test/fuzzytester.h000066400000000000000000000054021347155106100212500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QBS_FUZZYTESTER_H #define QBS_FUZZYTESTER_H #include #include #include class TestError { public: TestError(const QString &errorMessage) : errorMessage(errorMessage) {} ~TestError() throw() {} QString errorMessage; private: const char *what() const throw() { return qPrintable(errorMessage); } }; class FuzzyTester { public: FuzzyTester(); ~FuzzyTester(); void runTest(const QString &profile, const QString &startCommit, int maxDurationInMinutes, int jobCount, bool log); private: void checkoutCommit(const QString &commit); QStringList findAllCommits(const QString &startCommit); QString findWorkingStartCommit(const QString &startCommit); void runGit(const QStringList &arguments, QString *output = 0); bool runQbs(const QString &buildDir, const QString &command, QString *errorOutput = 0); void removeDir(const QString &dir); bool doCleanBuild(QString *errorMessage = 0); void throwIncrementalBuildError(const QString &message, const QStringList &commitSequence); void loadSettings(); void storeSettings() const; static QString logFilePath(const QString &commit, const QString &activity); static QString defaultBuildDir(); QString m_profile; int m_jobCount; bool m_log; QString m_headCommit; QString m_currentCommit; QString m_currentActivity; std::queue m_commitsWithLogFiles; QStringList m_unbuildableCommits; QStringList m_buildableCommits; }; #endif // Include guard. qbs-src-1.13.1/tests/fuzzy-test/main.cpp000066400000000000000000000062441347155106100201160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qbs. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "commandlineparser.h" #include "fuzzytester.h" #include #include #include static bool parseCommandLine(const QStringList &commandLine, QString &profile, QString &startCommi, int &maxDuration, int &jobCount, bool &log); static bool runTest(const QString &profile, const QString &startCommit, int maxDuration, int jobCount, bool log); int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QString profile; QString startCommit; int maxDuration; int jobCount; bool log; if (!parseCommandLine(app.arguments(), profile, startCommit, maxDuration, jobCount, log)) return EXIT_FAILURE; if (!runTest(profile, startCommit, maxDuration, jobCount, log)) return EXIT_FAILURE; std::cout << "Test finished successfully." << std::endl; return EXIT_SUCCESS; } bool parseCommandLine(const QStringList &commandLine, QString &profile, QString &startCommit, int &maxDuration, int &jobCount, bool &log) { CommandLineParser cmdParser; try { cmdParser.parse(commandLine); } catch (const ParseException &e) { std::cerr << "Invalid command line: " << qPrintable(e.errorMessage) << std::endl; std::cerr << "Usage:" << std::endl << qPrintable(cmdParser.usageString()) << std::endl; return false; } profile = cmdParser.profile(); startCommit = cmdParser.startCommit(); maxDuration = cmdParser.maxDurationInMinutes(); jobCount = cmdParser.jobCount(); log = cmdParser.log(); return true; } bool runTest(const QString &profile, const QString &startCommit, int maxDuration, int jobCount, bool log) { try { FuzzyTester().runTest(profile, startCommit, maxDuration, jobCount, log); } catch (const TestError &e) { std::cerr << qPrintable(e.errorMessage) << std::endl; return false; } return true; } qbs-src-1.13.1/tests/tests.pro000066400000000000000000000001371347155106100162010ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS = auto fuzzy-test qtHaveModule(concurrent): SUBDIRS += benchmarker qbs-src-1.13.1/tests/tests.qbs000066400000000000000000000026721347155106100161740ustar00rootroot00000000000000import qbs import qbs.FileInfo Project { references: [ "auto/auto.qbs", "benchmarker/benchmarker.qbs", "fuzzy-test/fuzzy-test.qbs", ] AutotestRunner { Depends { name: "Qt.core" } Depends { name: "qbs resources" } Depends { name: "qbs_cpp_scanner" } Depends { name: "qbs_qt_scanner" } arguments: project.autotestArguments wrapper: project.autotestWrapper environment: { var env = base; env.push("QBS_INSTALL_DIR=" + FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix)); if (qbs.hostOS.contains("windows") && qbs.targetOS.contains("windows")) { var path = ""; for (var i = 0; i < env.length; ++i) { if (env[i].startsWith("PATH=")) { path = env[i].substring(5); break; } } path = Qt.core.binPath + ";" + path; var arrayElem = "PATH=" + path; if (i < env.length) env[i] = arrayElem; else env.push(arrayElem); } if (qbs.hostOS.contains("darwin") && qbs.targetOS.contains("darwin")) { env.push("DYLD_FRAMEWORK_PATH=" + Qt.core.libPath); env.push("DYLD_LIBRARY_PATH=" + Qt.core.libPath); } return env; } } }